smartrte-react 1.0.0-beta.2 → 1.0.0-beta.3
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/CHANGELOG.md +4 -0
- package/dist/components/ToolbarPrimitives.d.ts +12 -0
- package/dist/components/ToolbarPrimitives.js +40 -2
- package/dist/theme.d.ts +1 -1
- package/dist/theme.js +14 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.3
|
|
4
|
+
|
|
5
|
+
- Fix toolbar dropdown menus (e.g. "More text styles", "More paragraph tools") getting visually clipped to unusable fragments when the editor is embedded inside a host container with `overflow: hidden` (e.g. a rounded card or a clipped split-pane panel) — the menu now positions itself relative to the viewport instead of the nearest ancestor, so it can never be clipped regardless of host layout.
|
|
6
|
+
|
|
3
7
|
## 1.0.0-beta.2
|
|
4
8
|
|
|
5
9
|
- Fix the toolbar promoting extra buttons based on the browser window's width instead of the editor's own rendered width — broke embedding the editor in a split pane or any container narrower than the window, causing overlapping/mashed toolbar labels and misdirected clicks that looked like an unresponsive toolbar.
|
|
@@ -101,6 +101,18 @@ export declare function ToolbarMenuItem({ icon, label, ariaLabel, pressed, disab
|
|
|
101
101
|
* keyboard support (Enter/Space to open, native focus handling) without a
|
|
102
102
|
* new open/close state to manage; outside-click dismiss is handled by
|
|
103
103
|
* useDismissDetailsOnOutsideClick above.
|
|
104
|
+
*
|
|
105
|
+
* The panel itself renders `position: fixed` with JS-measured coordinates
|
|
106
|
+
* (docs/bugs/toolbar-dropdown-clipped-by-host-overflow-hidden.md), the same
|
|
107
|
+
* pattern ColorPickerPopover/TableBorderPopover already use - a real host
|
|
108
|
+
* can (and, reported live, does) wrap the editor in an `overflow: hidden`
|
|
109
|
+
* container for its own layout reasons; a `position: absolute` panel
|
|
110
|
+
* anchored inside that container gets visually clipped the moment it needs
|
|
111
|
+
* to extend past the container's own bounds, which is exactly when a
|
|
112
|
+
* narrow host is most likely to need the dropdown in the first place.
|
|
113
|
+
* `position: fixed`'s containing block is the viewport (barring an
|
|
114
|
+
* ancestor with its own transform/filter, not the case here), so it always
|
|
115
|
+
* escapes ANY ancestor's overflow clipping regardless of DOM depth.
|
|
104
116
|
*/
|
|
105
117
|
export declare function ToolbarDropdown({ icon, label, priority, children }: {
|
|
106
118
|
icon?: ToolbarIconKey;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useRef } from "react";
|
|
2
|
+
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
3
3
|
import { AlignCenter, AlignJustify, AlignLeft, AlignRight, ALargeSmall, Baseline, Bold, CheckSquare, ChevronDown, Code, Columns3, Download, Eye, FileJson, History, Image as ImageIcon, IndentDecrease, IndentIncrease, Italic, Link2, ListChecks, ListOrdered, ListRestart, List as ListIcon, MessageSquare, MessageSquarePlus, MoreHorizontal, MoveDown, MoveLeft, MoveRight, MoveUp, Music, Omega, PanelTop, PenLine, Pilcrow, Quote, Redo2, Rows3, Square, Sigma, Strikethrough, Subscript, Superscript, Table2, Trash2, Type, Underline, Undo2, Unlink2, Upload, Video, Pencil, ZoomIn, ZoomOut, } from "lucide-react";
|
|
4
4
|
/**
|
|
5
5
|
* The toolbar's icon set (Phase: Direction B toolbar redesign, 2026-08-29).
|
|
@@ -119,11 +119,49 @@ const useDismissDetailsOnOutsideClick = (ref) => {
|
|
|
119
119
|
* keyboard support (Enter/Space to open, native focus handling) without a
|
|
120
120
|
* new open/close state to manage; outside-click dismiss is handled by
|
|
121
121
|
* useDismissDetailsOnOutsideClick above.
|
|
122
|
+
*
|
|
123
|
+
* The panel itself renders `position: fixed` with JS-measured coordinates
|
|
124
|
+
* (docs/bugs/toolbar-dropdown-clipped-by-host-overflow-hidden.md), the same
|
|
125
|
+
* pattern ColorPickerPopover/TableBorderPopover already use - a real host
|
|
126
|
+
* can (and, reported live, does) wrap the editor in an `overflow: hidden`
|
|
127
|
+
* container for its own layout reasons; a `position: absolute` panel
|
|
128
|
+
* anchored inside that container gets visually clipped the moment it needs
|
|
129
|
+
* to extend past the container's own bounds, which is exactly when a
|
|
130
|
+
* narrow host is most likely to need the dropdown in the first place.
|
|
131
|
+
* `position: fixed`'s containing block is the viewport (barring an
|
|
132
|
+
* ancestor with its own transform/filter, not the case here), so it always
|
|
133
|
+
* escapes ANY ancestor's overflow clipping regardless of DOM depth.
|
|
122
134
|
*/
|
|
123
135
|
export function ToolbarDropdown({ icon, label, priority, children }) {
|
|
124
136
|
const detailsRef = useRef(null);
|
|
125
137
|
useDismissDetailsOnOutsideClick(detailsRef);
|
|
126
|
-
|
|
138
|
+
const [placement, setPlacement] = useState(null);
|
|
139
|
+
useLayoutEffect(() => {
|
|
140
|
+
const details = detailsRef.current;
|
|
141
|
+
if (!details)
|
|
142
|
+
return;
|
|
143
|
+
const recompute = () => {
|
|
144
|
+
if (!details.open) {
|
|
145
|
+
setPlacement(null);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const margin = 8;
|
|
149
|
+
const triggerRect = details.getBoundingClientRect();
|
|
150
|
+
const menu = details.querySelector(":scope > .srte-menu");
|
|
151
|
+
const menuWidth = menu?.offsetWidth ?? 210;
|
|
152
|
+
const menuHeight = menu?.offsetHeight ?? 0;
|
|
153
|
+
const viewportWidth = window.innerWidth;
|
|
154
|
+
const viewportHeight = window.innerHeight;
|
|
155
|
+
const left = Math.min(Math.max(margin, triggerRect.left), Math.max(margin, viewportWidth - menuWidth - margin));
|
|
156
|
+
const overflowsBottom = triggerRect.bottom + 6 + menuHeight > viewportHeight - margin;
|
|
157
|
+
const top = overflowsBottom ? Math.max(margin, triggerRect.top - menuHeight - 6) : triggerRect.bottom + 6;
|
|
158
|
+
setPlacement({ left, top });
|
|
159
|
+
};
|
|
160
|
+
recompute();
|
|
161
|
+
details.addEventListener("toggle", recompute);
|
|
162
|
+
return () => details.removeEventListener("toggle", recompute);
|
|
163
|
+
}, []);
|
|
164
|
+
return _jsxs("details", { ref: detailsRef, className: "srte-toolbar-menu", ...(priority ? { "data-srte-priority": priority } : {}), children: [_jsxs("summary", { className: "srte-tool-button srte-menu-trigger", onMouseDown: (event) => event.preventDefault(), children: [icon ? toolbarIcons[icon] : null, _jsx("span", { children: label }), _jsx(ChevronDown, { width: 13, height: 13, strokeWidth: 2, "aria-hidden": "true" })] }), _jsx("div", { className: "srte-menu", role: "menu", "data-srte-menu-fixed": "true", style: { left: placement?.left ?? 0, top: placement?.top ?? 0, visibility: placement ? "visible" : "hidden" }, children: children })] });
|
|
127
165
|
}
|
|
128
166
|
/** A visually-separated cluster of controls, optionally collapsing as a whole unit on narrow viewports (theme.ts's `.srte-toolbar-group[data-srte-priority="3"]`). */
|
|
129
167
|
export function ToolbarGroup({ priority, children }) {
|
package/dist/theme.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export type SrteTheme = 'light' | 'dark';
|
|
2
|
-
export declare const SRTE_DEFAULT_CSS = "\n.srte-editor {\n --srte-background: var(--card, #ffffff);\n --srte-canvas: var(--background, #ffffff);\n --srte-foreground: var(--foreground, #0f172a);\n --srte-muted: var(--muted, #f1f5f9);\n --srte-muted-foreground: var(--muted-foreground, #64748b);\n --srte-ring: var(--ring, #0284c7);\n --srte-radius: var(--radius, 0.625rem);\n --srte-bg: var(--srte-canvas);\n --srte-text: var(--srte-foreground);\n --srte-text-muted: var(--srte-muted-foreground);\n --srte-border: var(--border, #e2e8f0);\n --srte-border-light: var(--srte-border);\n --srte-toolbar-bg: var(--srte-background);\n --srte-input-bg: var(--srte-background);\n --srte-input-text: var(--srte-foreground);\n --srte-input-border: var(--srte-border);\n --srte-modal-backdrop: rgba(0, 0, 0, 0.35);\n --srte-modal-backdrop-filter: blur(2px);\n --srte-modal-bg: #ffffff;\n --srte-modal-text: #000000;\n --srte-menu-bg: var(--srte-background);\n --srte-menu-text: var(--srte-foreground);\n --srte-menu-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);\n --srte-accent: #0284c7;\n --srte-accent-bg: rgba(2, 132, 199, 0.12);\n --srte-danger: #dc2626;\n --srte-primary: #2563eb;\n /* --srte-primary on --srte-accent-bg measures 4.43:1, under WCAG AA's\n 4.5:1 for normal text - used only for the pressed toolbar-button state\n (see .srte-tool-button[aria-pressed=\"true\"]), not a replacement for\n --srte-primary generally. */\n --srte-primary-pressed: #1d4ed8;\n --srte-surface-subtle: #f3f4f6;\n --srte-on-primary: #ffffff;\n --srte-cancel-bg: #f3f4f6;\n --srte-code-bg: #f6f8fa;\n --srte-code-text: #24292f;\n}\n.srte-editor.srte-dark {\n --srte-background: var(--card, #1e293b);\n --srte-canvas: var(--background, #0f172a);\n --srte-foreground: var(--foreground, #f8fafc);\n --srte-muted: var(--muted, #334155);\n --srte-muted-foreground: var(--muted-foreground, #94a3b8);\n --srte-ring: var(--ring, #38bdf8);\n --srte-bg: var(--srte-canvas);\n --srte-text: var(--srte-foreground);\n --srte-text-muted: var(--srte-muted-foreground);\n --srte-border: var(--border, #334155);\n --srte-border-light: var(--srte-border);\n --srte-toolbar-bg: var(--srte-background);\n --srte-input-bg: var(--srte-background);\n --srte-input-text: var(--srte-foreground);\n --srte-input-border: var(--srte-border);\n --srte-modal-backdrop: rgba(0, 0, 0, 0.22);\n --srte-modal-backdrop-filter: blur(10px) saturate(0.9);\n --srte-modal-bg: #1e293b;\n --srte-modal-text: #e0e0e0;\n --srte-menu-bg: var(--srte-background);\n --srte-menu-text: var(--srte-foreground);\n --srte-menu-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);\n --srte-accent: #38bdf8;\n --srte-accent-bg: rgba(56, 189, 248, 0.16);\n --srte-danger: #ef4444;\n --srte-primary: #3b82f6;\n --srte-primary-pressed: var(--srte-primary);\n --srte-surface-subtle: #333333;\n --srte-on-primary: #ffffff;\n --srte-cancel-bg: #333333;\n --srte-code-bg: #111827;\n --srte-code-text: #e5e7eb;\n}\n.srte-editor {\n border-radius: var(--srte-radius);\n font-family: \"IBM Plex Sans\", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n container: srte-editor / inline-size;\n}\n.srte-canonical-authority > .srte-editor[contenteditable] {\n width: 100%;\n padding: 16px 20px;\n box-sizing: border-box;\n border: 1px solid var(--srte-border);\n border-radius: 0 0 var(--srte-radius) var(--srte-radius);\n outline: none;\n background: var(--srte-canvas);\n color: var(--srte-foreground);\n caret-color: var(--srte-foreground);\n line-height: 1.6;\n}\n.srte-toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px;\n width: 100%;\n min-height: 48px;\n padding: 8px;\n box-sizing: border-box;\n border-bottom: 1px solid var(--srte-border);\n background: var(--srte-background);\n color: var(--srte-foreground);\n position: sticky;\n top: 0;\n z-index: 10;\n}\n.srte-toolbar-group {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n min-width: 0;\n}\n.srte-toolbar-group + .srte-toolbar-group::before {\n content: \"\";\n width: 1px;\n height: 20px;\n margin: 0 5px 0 3px;\n background: var(--srte-border);\n}\n.srte-tool-button,\n.srte-toolbar select {\n height: 32px;\n min-width: 32px;\n box-sizing: border-box;\n border: 1px solid transparent;\n border-radius: 8px;\n background: transparent;\n color: var(--srte-foreground);\n font: 500 13px/1 \"IBM Plex Sans\", ui-sans-serif, system-ui, sans-serif;\n}\n.srte-tool-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n padding: 0 7px;\n cursor: pointer;\n}\n.srte-toolbar select {\n max-width: 132px;\n padding: 0 26px 0 9px;\n border-color: var(--srte-border);\n background: var(--srte-input-bg);\n cursor: pointer;\n}\n.srte-tool-button:hover,\n.srte-toolbar select:hover,\n.srte-toolbar-menu[open] > .srte-menu-trigger {\n background: var(--srte-muted);\n border-color: var(--srte-border);\n}\n.srte-tool-button.srte-active,\n.srte-tool-button[aria-pressed=\"true\"] {\n /* var(--srte-primary) (#2563eb) on var(--srte-accent-bg) measured 4.43:1,\n just under WCAG AA's 4.5:1 for normal text (axe-core, Phase 11 Tier 3) -\n a dedicated, darker pressed-state color keeps the same hue family\n while clearing the threshold, without changing --srte-primary's other,\n already-compliant usages (e.g. against solid backgrounds). */\n color: var(--srte-primary-pressed);\n background: var(--srte-accent-bg);\n border-color: color-mix(in srgb, var(--srte-primary) 35%, transparent);\n}\n.srte-tool-button:focus-visible,\n.srte-toolbar select:focus-visible,\n.srte-menu-item:focus-visible {\n outline: 2px solid var(--srte-ring);\n outline-offset: 1px;\n}\n.srte-tool-button:disabled,\n.srte-menu-item:disabled,\n.srte-toolbar select:disabled {\n cursor: not-allowed;\n opacity: .4;\n}\n.srte-toolbar-menu {\n position: relative;\n}\n.srte-toolbar-menu > summary {\n list-style: none;\n}\n.srte-toolbar-menu > summary::-webkit-details-marker {\n display: none;\n}\n.srte-menu {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n z-index: 80;\n min-width: 210px;\n padding: 4px;\n overflow: hidden;\n border: 1px solid var(--srte-border);\n border-radius: 12px;\n background: var(--srte-menu-bg);\n color: var(--srte-menu-text);\n box-shadow: var(--srte-menu-shadow);\n}\n.srte-menu-item {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n height: 36px;\n padding: 0 8px;\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n font: 500 13px/1 \"IBM Plex Sans\", ui-sans-serif, system-ui, sans-serif;\n text-align: left;\n white-space: nowrap;\n}\n.srte-menu-item:hover {\n background: var(--srte-muted);\n}\n.srte-menu-check {\n margin-left: auto;\n color: var(--srte-primary);\n font-weight: 700;\n}\n.srte-menu-separator {\n height: 1px;\n margin: 4px;\n background: var(--srte-border);\n}\n.srte-mobile-more { display: none; }\n.srte-toolbar .srte-command-proxy { display: none; }\n.srte-split-control {\n display: inline-flex;\n}\n.srte-split-control > .srte-tool-button:first-child {\n border-radius: 8px 0 0 8px;\n}\n.srte-split-control > select {\n width: 27px;\n padding: 0;\n border-radius: 0 8px 8px 0;\n border-left: 0;\n appearance: none;\n -webkit-appearance: none;\n color: transparent;\n background-color: var(--srte-muted);\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m7 10 5 5 5-5'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: center;\n cursor: pointer;\n}\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li {\n display: grid;\n grid-template-columns: 1.1em minmax(0, 1fr);\n column-gap: .45em;\n align-items: start;\n padding-left: 0;\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal-paren\"][data-srte-list-depth=\"0\"] > li::marker {\n content: counter(list-item, decimal) \") \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal-paren\"][data-srte-list-depth=\"1\"] > li::marker {\n content: counter(list-item, lower-alpha) \") \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal-paren\"][data-srte-list-depth=\"2\"] > li::marker,\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal-paren\"][data-srte-list-depth=\"3\"] > li::marker {\n content: counter(list-item, lower-roman) \") \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal\"][data-srte-list-depth=\"0\"] > li::marker {\n content: counter(list-item, decimal) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal\"][data-srte-list-depth=\"1\"] > li::marker {\n content: counter(list-item, lower-alpha) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal\"][data-srte-list-depth=\"2\"] > li::marker,\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal\"][data-srte-list-depth=\"3\"] > li::marker {\n content: counter(list-item, lower-roman) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-alpha\"][data-srte-list-depth=\"0\"] > li::marker {\n content: counter(list-item, upper-alpha) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-alpha\"][data-srte-list-depth=\"1\"] > li::marker {\n content: counter(list-item, lower-alpha) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-alpha\"][data-srte-list-depth=\"2\"] > li::marker,\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-alpha\"][data-srte-list-depth=\"3\"] > li::marker {\n content: counter(list-item, lower-roman) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-roman\"][data-srte-list-depth=\"0\"] > li::marker {\n content: counter(list-item, upper-roman) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-roman\"][data-srte-list-depth=\"1\"] > li::marker {\n content: counter(list-item, upper-alpha) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-roman\"][data-srte-list-depth=\"2\"] > li::marker,\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-roman\"][data-srte-list-depth=\"3\"] > li::marker {\n content: counter(list-item, decimal) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-leading-zero\"][data-srte-list-depth=\"0\"] > li::marker {\n content: counter(list-item, decimal-leading-zero) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-leading-zero\"][data-srte-list-depth=\"1\"] > li::marker {\n content: counter(list-item, lower-alpha) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-leading-zero\"][data-srte-list-depth=\"2\"] > li::marker,\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-leading-zero\"][data-srte-list-depth=\"3\"] > li::marker {\n content: counter(list-item, lower-roman) \". \";\n}\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-disc\"][data-srte-list-depth=\"0\"] > li::marker {\n content: \"\u25CF \";\n}\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-disc\"][data-srte-list-depth=\"1\"] > li::marker {\n content: \"\u25CB \";\n}\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-disc\"][data-srte-list-depth=\"2\"] > li::marker,\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-disc\"][data-srte-list-depth=\"3\"] > li::marker {\n content: \"\u25A0 \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-outline\"] > li::marker {\n content: counters(list-item, \".\") \". \";\n}\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-diamond\"][data-srte-list-depth=\"0\"] > li::marker { content: \"\u2756 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-diamond\"][data-srte-list-depth=\"1\"] > li::marker { content: \"\u27A2 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-diamond\"][data-srte-list-depth=\"2\"] > li::marker { content: \"\u25A0 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-square\"][data-srte-list-depth=\"0\"] > li::marker { content: \"\u25A1 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-square\"][data-srte-list-depth=\"1\"] > li::marker { content: \"\u25A3 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-square\"][data-srte-list-depth=\"2\"] > li::marker { content: \"\u25AA \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-arrow\"][data-srte-list-depth=\"0\"] > li::marker { content: \"\u279C \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-arrow\"][data-srte-list-depth=\"1\"] > li::marker { content: \"\u25C6 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-arrow\"][data-srte-list-depth=\"2\"] > li::marker { content: \"\u25CF \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-star\"][data-srte-list-depth=\"0\"] > li::marker { content: \"\u2605 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-star\"][data-srte-list-depth=\"1\"] > li::marker { content: \"\u25CB \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-star\"][data-srte-list-depth=\"2\"] > li::marker { content: \"\u25A0 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-arrow-circle\"][data-srte-list-depth=\"0\"] > li::marker { content: \"\u27A2 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-arrow-circle\"][data-srte-list-depth=\"1\"] > li::marker { content: \"\u25CB \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-arrow-circle\"][data-srte-list-depth=\"2\"] > li::marker { content: \"\u25A0 \"; }\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li > [data-srte-check] {\n display: inline-flex;\n grid-column: 1;\n grid-row: 1;\n align-items: center;\n justify-content: center;\n width: 1.1em;\n height: 1.6em;\n min-width: 0;\n box-sizing: border-box;\n padding: 0;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: pointer;\n appearance: none;\n outline: none;\n margin: 0;\n line-height: 1.6;\n vertical-align: top;\n position: relative;\n}\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li > [data-srte-check]:focus-visible {\n outline: 2px solid var(--srte-ring);\n outline-offset: 2px;\n}\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li > [data-srte-check]::before {\n content: \"\";\n width: .9em;\n height: .9em;\n box-sizing: border-box;\n border: 1.5px solid var(--srte-muted-foreground);\n border-radius: 3px;\n background: var(--srte-canvas);\n}\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li > [data-srte-check][data-checked=\"true\"]::before {\n border-color: var(--srte-primary);\n background: var(--srte-primary);\n box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--srte-on-primary) 25%, transparent);\n}\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li > [data-srte-check][data-checked=\"true\"]::after {\n content: \"\";\n position: absolute;\n width: .42em;\n height: .22em;\n border-left: 1.5px solid var(--srte-on-primary);\n border-bottom: 1.5px solid var(--srte-on-primary);\n transform: translateY(-.08em) rotate(-45deg);\n}\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li > :is(p,h1,h2,h3,h4,h5,h6,blockquote,pre) {\n grid-column: 2;\n min-width: 0;\n margin-top: 0;\n}\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li > :is(ul,ol) {\n grid-column: 2;\n}\n.srte-editor:focus-within {\n border-color: var(--srte-ring) !important;\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--srte-ring) 18%, transparent);\n}\n/*\n * @container (element width), not @media (viewport width): a host can embed\n * the editor at any fraction of the browser window - a split pane next to a\n * preview panel is the case that surfaced this (docs/bugs/\n * toolbar-wide-promotion-fires-on-viewport-width-not-container-width.md). A\n * plain @media breakpoint here would fire based on the *window*, wrongly\n * switching tiers for an editor instance that's actually much narrower (or\n * wider) than the window - .srte-editor already establishes its own\n * container: srte-editor / inline-size (see the .srte-editor rule above),\n * so @container always reflects this specific instance's real rendered width regardless of host\n * layout, with no @media fallback needed (container queries have full\n * support across this project's three target engines).\n */\n@container srte-editor (max-width: 639px) {\n .srte-toolbar { gap: 3px; padding: 6px; }\n .srte-tool-button, .srte-toolbar select { height: 40px; min-width: 40px; }\n .srte-toolbar-group[data-srte-priority=\"3\"],\n .srte-toolbar-menu[data-srte-priority=\"2\"] { display: none; }\n .srte-mobile-more { display: block; }\n .srte-mobile-more .srte-menu {\n left: auto;\n right: 0;\n width: min(280px, calc(100vw - 16px));\n min-width: 0;\n max-height: min(70dvh, 480px);\n overflow-x: hidden;\n overflow-y: auto;\n overscroll-behavior: contain;\n -webkit-overflow-scrolling: touch;\n }\n .srte-menu-item { height: 40px; }\n}\n/*\n * Wide-viewport promotion (docs/bugs/toolbar-priority-collapse-fixed-threshold-no-wide-promotion.md):\n * below this, the single 639px breakpoint above was this system's ONLY\n * threshold - every dropdown-grouped tool stayed hidden inside its dropdown\n * at every width from 640px up to and past a 2200px+ desktop, since nothing\n * ever measured or scaled with the extra room. A handful of tools frequent\n * enough to matter once there's genuinely spare room (Superscript,\n * Subscript, Text colour, Background colour, Font size, Font family, Remove\n * link, Insert formula, Special characters) get a standalone always-visible\n * ToolbarButton copy (data-srte-wide-promote, rendered directly in the\n * toolbar row) that appears past this breakpoint, while their existing\n * dropdown/mobile-menu ToolbarMenuItem copy (the exact same\n * data-srte-wide-promote attribute, on the .srte-menu-item element instead)\n * hides so the tool isn't offered twice. Below this breakpoint - including\n * all of mobile AND the 640-1439px tablet/typical-laptop band, which keeps\n * today's grouped-dropdown layout unchanged - the standalone copy stays\n * hidden and the dropdown copy is what's reachable.\n *\n * 1440px, not 1280px: Playwright's own default test viewport is exactly\n * 1280x720, and the vast majority of this suite's toolbar interactions run\n * at that default without ever calling page.setViewportSize - a 1280px\n * threshold would have flipped nearly every existing toolbar test's\n * dropdown-item locators (role=menuitem) over to CSS display:none out from\n * under them. 1440px clears that default with room to spare while still\n * comfortably covering \"wide desktop\" (the ~2264px width the original\n * report was filed against).\n *\n * @container only, no @media fallback - same reasoning as the mobile tier\n * above (docs/bugs/toolbar-wide-promotion-fires-on-viewport-width-not-container-width.md):\n * a plain @media(min-width:1440px) fired whenever the *browser window* was\n * wide, even when this editor instance was embedded in a much narrower\n * split pane - promoting 9 extra buttons into a group with no room for\n * them, which squeezed/overlapped the group's existing buttons instead of\n * wrapping cleanly.\n */\n.srte-tool-button[data-srte-wide-promote=\"true\"] { display: none; }\n@container srte-editor (min-width: 1440px) {\n .srte-tool-button[data-srte-wide-promote=\"true\"] { display: inline-flex; }\n .srte-menu-item[data-srte-wide-promote=\"true\"] { display: none; }\n}\n.srte-editor [contenteditable] blockquote {\n border-left: 4px solid var(--srte-accent);\n margin: 0.75em 0;\n padding: 0.5em 1em;\n background: var(--srte-surface-subtle);\n color: var(--srte-text);\n}\n.srte-editor [contenteditable] p,\n.srte-editor [contenteditable] h1,\n.srte-editor [contenteditable] h2,\n.srte-editor [contenteditable] h3 {\n color: inherit;\n}\n.srte-editor [contenteditable] p {\n display: block;\n margin: 0 0 0.75em;\n font-size: 1em;\n font-weight: 400;\n line-height: 1.6;\n}\n.srte-editor [contenteditable] p[data-srte-caret-boundary=\"true\"] {\n min-height: 1.6em;\n}\n.srte-editor [contenteditable] h1,\n.srte-editor [contenteditable] h2,\n.srte-editor [contenteditable] h3 {\n display: block;\n margin: 0.75em 0 0.4em;\n font-weight: 700;\n line-height: 1.25;\n}\n.srte-editor [contenteditable] h1 {\n font-size: 2em;\n}\n.srte-editor [contenteditable] h2 {\n font-size: 1.5em;\n}\n.srte-editor [contenteditable] h3 {\n font-size: 1.25em;\n}\n.srte-editor [contenteditable] > :first-child {\n margin-top: 0;\n}\n.srte-editor [contenteditable] ul {\n list-style-type: disc;\n list-style-position: outside;\n margin: 0.75em 0;\n padding-left: 1.75em;\n}\n.srte-editor [contenteditable] ol {\n list-style-type: decimal;\n list-style-position: outside;\n margin: 0.75em 0;\n padding-left: 1.75em;\n}\n.srte-editor [contenteditable] li {\n display: list-item;\n margin: 0.25em 0;\n padding-left: 0.25em;\n}\n.srte-editor [contenteditable] li::marker {\n color: currentColor;\n}\n.srte-editor [contenteditable] table {\n width: 100%;\n margin: 0.75em 0;\n border-collapse: collapse;\n}\n.srte-editor [contenteditable] th,\n.srte-editor [contenteditable] td {\n padding: 8px;\n border: 1px solid var(--srte-border);\n vertical-align: top;\n}\n.srte-editor [contenteditable] [data-smart-cell-selected=\"true\"] {\n background: color-mix(in srgb, var(--srte-primary) 12%, var(--srte-canvas));\n box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--srte-primary) 65%, transparent);\n}\n.srte-editor [contenteditable][data-smart-cell-selection-active] ::selection {\n background: transparent;\n color: inherit;\n}\n.srte-editor [contenteditable] th {\n background: var(--srte-surface-subtle);\n font-weight: 600;\n text-align: left;\n}\n.srte-editor [contenteditable] td > h1,\n.srte-editor [contenteditable] td > h2,\n.srte-editor [contenteditable] td > h3,\n.srte-editor [contenteditable] th > h1,\n.srte-editor [contenteditable] th > h2,\n.srte-editor [contenteditable] th > h3 {\n margin: 0 0 0.4em;\n overflow-wrap: anywhere;\n}\n.srte-editor [contenteditable] pre {\n display: block;\n margin: 0.75em 0;\n padding: 12px 14px;\n overflow-x: auto;\n border: 1px solid var(--srte-border);\n border-radius: 6px;\n background: var(--srte-code-bg);\n color: var(--srte-code-text);\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", monospace;\n font-size: 0.9em;\n line-height: 1.55;\n white-space: pre-wrap;\n}\n.srte-editor [contenteditable] pre code {\n padding: 0;\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n}\n.srte-editor [contenteditable] code:not(pre code) {\n padding: 0.1em 0.35em;\n border-radius: 3px;\n background: var(--srte-code-bg);\n color: var(--srte-code-text);\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", monospace;\n font-size: 0.9em;\n}\n.srte-editor [contenteditable] a,\n.srte-editor [contenteditable] a:visited {\n color: var(--srte-primary) !important;\n text-decoration: underline !important;\n text-decoration-thickness: 1px !important;\n text-underline-offset: 2px !important;\n cursor: pointer;\n}\n.srte-editor [contenteditable] a:hover {\n color: var(--srte-accent) !important;\n}\n.srte-editor [contenteditable] a:focus-visible {\n outline: 2px solid var(--srte-accent);\n outline-offset: 2px;\n}\n.srte-editor [contenteditable] sub,\n.srte-editor [contenteditable] sup {\n line-height: 0;\n}\n";
|
|
2
|
+
export declare const SRTE_DEFAULT_CSS = "\n.srte-editor {\n --srte-background: var(--card, #ffffff);\n --srte-canvas: var(--background, #ffffff);\n --srte-foreground: var(--foreground, #0f172a);\n --srte-muted: var(--muted, #f1f5f9);\n --srte-muted-foreground: var(--muted-foreground, #64748b);\n --srte-ring: var(--ring, #0284c7);\n --srte-radius: var(--radius, 0.625rem);\n --srte-bg: var(--srte-canvas);\n --srte-text: var(--srte-foreground);\n --srte-text-muted: var(--srte-muted-foreground);\n --srte-border: var(--border, #e2e8f0);\n --srte-border-light: var(--srte-border);\n --srte-toolbar-bg: var(--srte-background);\n --srte-input-bg: var(--srte-background);\n --srte-input-text: var(--srte-foreground);\n --srte-input-border: var(--srte-border);\n --srte-modal-backdrop: rgba(0, 0, 0, 0.35);\n --srte-modal-backdrop-filter: blur(2px);\n --srte-modal-bg: #ffffff;\n --srte-modal-text: #000000;\n --srte-menu-bg: var(--srte-background);\n --srte-menu-text: var(--srte-foreground);\n --srte-menu-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);\n --srte-accent: #0284c7;\n --srte-accent-bg: rgba(2, 132, 199, 0.12);\n --srte-danger: #dc2626;\n --srte-primary: #2563eb;\n /* --srte-primary on --srte-accent-bg measures 4.43:1, under WCAG AA's\n 4.5:1 for normal text - used only for the pressed toolbar-button state\n (see .srte-tool-button[aria-pressed=\"true\"]), not a replacement for\n --srte-primary generally. */\n --srte-primary-pressed: #1d4ed8;\n --srte-surface-subtle: #f3f4f6;\n --srte-on-primary: #ffffff;\n --srte-cancel-bg: #f3f4f6;\n --srte-code-bg: #f6f8fa;\n --srte-code-text: #24292f;\n}\n.srte-editor.srte-dark {\n --srte-background: var(--card, #1e293b);\n --srte-canvas: var(--background, #0f172a);\n --srte-foreground: var(--foreground, #f8fafc);\n --srte-muted: var(--muted, #334155);\n --srte-muted-foreground: var(--muted-foreground, #94a3b8);\n --srte-ring: var(--ring, #38bdf8);\n --srte-bg: var(--srte-canvas);\n --srte-text: var(--srte-foreground);\n --srte-text-muted: var(--srte-muted-foreground);\n --srte-border: var(--border, #334155);\n --srte-border-light: var(--srte-border);\n --srte-toolbar-bg: var(--srte-background);\n --srte-input-bg: var(--srte-background);\n --srte-input-text: var(--srte-foreground);\n --srte-input-border: var(--srte-border);\n --srte-modal-backdrop: rgba(0, 0, 0, 0.22);\n --srte-modal-backdrop-filter: blur(10px) saturate(0.9);\n --srte-modal-bg: #1e293b;\n --srte-modal-text: #e0e0e0;\n --srte-menu-bg: var(--srte-background);\n --srte-menu-text: var(--srte-foreground);\n --srte-menu-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);\n --srte-accent: #38bdf8;\n --srte-accent-bg: rgba(56, 189, 248, 0.16);\n --srte-danger: #ef4444;\n --srte-primary: #3b82f6;\n --srte-primary-pressed: var(--srte-primary);\n --srte-surface-subtle: #333333;\n --srte-on-primary: #ffffff;\n --srte-cancel-bg: #333333;\n --srte-code-bg: #111827;\n --srte-code-text: #e5e7eb;\n}\n.srte-editor {\n border-radius: var(--srte-radius);\n font-family: \"IBM Plex Sans\", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n container: srte-editor / inline-size;\n}\n.srte-canonical-authority > .srte-editor[contenteditable] {\n width: 100%;\n padding: 16px 20px;\n box-sizing: border-box;\n border: 1px solid var(--srte-border);\n border-radius: 0 0 var(--srte-radius) var(--srte-radius);\n outline: none;\n background: var(--srte-canvas);\n color: var(--srte-foreground);\n caret-color: var(--srte-foreground);\n line-height: 1.6;\n}\n.srte-toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px;\n width: 100%;\n min-height: 48px;\n padding: 8px;\n box-sizing: border-box;\n border-bottom: 1px solid var(--srte-border);\n background: var(--srte-background);\n color: var(--srte-foreground);\n position: sticky;\n top: 0;\n z-index: 10;\n}\n.srte-toolbar-group {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n min-width: 0;\n}\n.srte-toolbar-group + .srte-toolbar-group::before {\n content: \"\";\n width: 1px;\n height: 20px;\n margin: 0 5px 0 3px;\n background: var(--srte-border);\n}\n.srte-tool-button,\n.srte-toolbar select {\n height: 32px;\n min-width: 32px;\n box-sizing: border-box;\n border: 1px solid transparent;\n border-radius: 8px;\n background: transparent;\n color: var(--srte-foreground);\n font: 500 13px/1 \"IBM Plex Sans\", ui-sans-serif, system-ui, sans-serif;\n}\n.srte-tool-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n padding: 0 7px;\n cursor: pointer;\n}\n.srte-toolbar select {\n max-width: 132px;\n padding: 0 26px 0 9px;\n border-color: var(--srte-border);\n background: var(--srte-input-bg);\n cursor: pointer;\n}\n.srte-tool-button:hover,\n.srte-toolbar select:hover,\n.srte-toolbar-menu[open] > .srte-menu-trigger {\n background: var(--srte-muted);\n border-color: var(--srte-border);\n}\n.srte-tool-button.srte-active,\n.srte-tool-button[aria-pressed=\"true\"] {\n /* var(--srte-primary) (#2563eb) on var(--srte-accent-bg) measured 4.43:1,\n just under WCAG AA's 4.5:1 for normal text (axe-core, Phase 11 Tier 3) -\n a dedicated, darker pressed-state color keeps the same hue family\n while clearing the threshold, without changing --srte-primary's other,\n already-compliant usages (e.g. against solid backgrounds). */\n color: var(--srte-primary-pressed);\n background: var(--srte-accent-bg);\n border-color: color-mix(in srgb, var(--srte-primary) 35%, transparent);\n}\n.srte-tool-button:focus-visible,\n.srte-toolbar select:focus-visible,\n.srte-menu-item:focus-visible {\n outline: 2px solid var(--srte-ring);\n outline-offset: 1px;\n}\n.srte-tool-button:disabled,\n.srte-menu-item:disabled,\n.srte-toolbar select:disabled {\n cursor: not-allowed;\n opacity: .4;\n}\n.srte-toolbar-menu {\n position: relative;\n}\n.srte-toolbar-menu > summary {\n list-style: none;\n}\n.srte-toolbar-menu > summary::-webkit-details-marker {\n display: none;\n}\n.srte-menu {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n z-index: 80;\n min-width: 210px;\n padding: 4px;\n overflow: hidden;\n border: 1px solid var(--srte-border);\n border-radius: 12px;\n background: var(--srte-menu-bg);\n color: var(--srte-menu-text);\n box-shadow: var(--srte-menu-shadow);\n}\n/*\n * ToolbarDropdown's own menu panel (docs/bugs/\n * toolbar-dropdown-clipped-by-host-overflow-hidden.md): position:fixed with\n * JS-measured left/top (ToolbarPrimitives.tsx) instead of the default\n * position:absolute above, so it always escapes an ancestor host container's\n * own overflow:hidden regardless of DOM depth - MobileMoreMenu's overflow\n * menu (no data-srte-menu-fixed attribute) is unaffected and keeps its\n * existing position:absolute/right-anchored behavior.\n */\n.srte-menu[data-srte-menu-fixed=\"true\"] {\n position: fixed;\n top: 0;\n left: 0;\n}\n.srte-menu-item {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n height: 36px;\n padding: 0 8px;\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n font: 500 13px/1 \"IBM Plex Sans\", ui-sans-serif, system-ui, sans-serif;\n text-align: left;\n white-space: nowrap;\n}\n.srte-menu-item:hover {\n background: var(--srte-muted);\n}\n.srte-menu-check {\n margin-left: auto;\n color: var(--srte-primary);\n font-weight: 700;\n}\n.srte-menu-separator {\n height: 1px;\n margin: 4px;\n background: var(--srte-border);\n}\n.srte-mobile-more { display: none; }\n.srte-toolbar .srte-command-proxy { display: none; }\n.srte-split-control {\n display: inline-flex;\n}\n.srte-split-control > .srte-tool-button:first-child {\n border-radius: 8px 0 0 8px;\n}\n.srte-split-control > select {\n width: 27px;\n padding: 0;\n border-radius: 0 8px 8px 0;\n border-left: 0;\n appearance: none;\n -webkit-appearance: none;\n color: transparent;\n background-color: var(--srte-muted);\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m7 10 5 5 5-5'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: center;\n cursor: pointer;\n}\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li {\n display: grid;\n grid-template-columns: 1.1em minmax(0, 1fr);\n column-gap: .45em;\n align-items: start;\n padding-left: 0;\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal-paren\"][data-srte-list-depth=\"0\"] > li::marker {\n content: counter(list-item, decimal) \") \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal-paren\"][data-srte-list-depth=\"1\"] > li::marker {\n content: counter(list-item, lower-alpha) \") \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal-paren\"][data-srte-list-depth=\"2\"] > li::marker,\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal-paren\"][data-srte-list-depth=\"3\"] > li::marker {\n content: counter(list-item, lower-roman) \") \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal\"][data-srte-list-depth=\"0\"] > li::marker {\n content: counter(list-item, decimal) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal\"][data-srte-list-depth=\"1\"] > li::marker {\n content: counter(list-item, lower-alpha) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal\"][data-srte-list-depth=\"2\"] > li::marker,\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-decimal\"][data-srte-list-depth=\"3\"] > li::marker {\n content: counter(list-item, lower-roman) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-alpha\"][data-srte-list-depth=\"0\"] > li::marker {\n content: counter(list-item, upper-alpha) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-alpha\"][data-srte-list-depth=\"1\"] > li::marker {\n content: counter(list-item, lower-alpha) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-alpha\"][data-srte-list-depth=\"2\"] > li::marker,\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-alpha\"][data-srte-list-depth=\"3\"] > li::marker {\n content: counter(list-item, lower-roman) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-roman\"][data-srte-list-depth=\"0\"] > li::marker {\n content: counter(list-item, upper-roman) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-roman\"][data-srte-list-depth=\"1\"] > li::marker {\n content: counter(list-item, upper-alpha) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-roman\"][data-srte-list-depth=\"2\"] > li::marker,\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-upper-roman\"][data-srte-list-depth=\"3\"] > li::marker {\n content: counter(list-item, decimal) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-leading-zero\"][data-srte-list-depth=\"0\"] > li::marker {\n content: counter(list-item, decimal-leading-zero) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-leading-zero\"][data-srte-list-depth=\"1\"] > li::marker {\n content: counter(list-item, lower-alpha) \". \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-leading-zero\"][data-srte-list-depth=\"2\"] > li::marker,\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-leading-zero\"][data-srte-list-depth=\"3\"] > li::marker {\n content: counter(list-item, lower-roman) \". \";\n}\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-disc\"][data-srte-list-depth=\"0\"] > li::marker {\n content: \"\u25CF \";\n}\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-disc\"][data-srte-list-depth=\"1\"] > li::marker {\n content: \"\u25CB \";\n}\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-disc\"][data-srte-list-depth=\"2\"] > li::marker,\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-disc\"][data-srte-list-depth=\"3\"] > li::marker {\n content: \"\u25A0 \";\n}\n.srte-editor [contenteditable] ol[data-srte-list-preset=\"ordered-outline\"] > li::marker {\n content: counters(list-item, \".\") \". \";\n}\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-diamond\"][data-srte-list-depth=\"0\"] > li::marker { content: \"\u2756 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-diamond\"][data-srte-list-depth=\"1\"] > li::marker { content: \"\u27A2 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-diamond\"][data-srte-list-depth=\"2\"] > li::marker { content: \"\u25A0 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-square\"][data-srte-list-depth=\"0\"] > li::marker { content: \"\u25A1 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-square\"][data-srte-list-depth=\"1\"] > li::marker { content: \"\u25A3 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-square\"][data-srte-list-depth=\"2\"] > li::marker { content: \"\u25AA \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-arrow\"][data-srte-list-depth=\"0\"] > li::marker { content: \"\u279C \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-arrow\"][data-srte-list-depth=\"1\"] > li::marker { content: \"\u25C6 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-arrow\"][data-srte-list-depth=\"2\"] > li::marker { content: \"\u25CF \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-star\"][data-srte-list-depth=\"0\"] > li::marker { content: \"\u2605 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-star\"][data-srte-list-depth=\"1\"] > li::marker { content: \"\u25CB \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-star\"][data-srte-list-depth=\"2\"] > li::marker { content: \"\u25A0 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-arrow-circle\"][data-srte-list-depth=\"0\"] > li::marker { content: \"\u27A2 \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-arrow-circle\"][data-srte-list-depth=\"1\"] > li::marker { content: \"\u25CB \"; }\n.srte-editor [contenteditable] ul[data-srte-list-preset=\"bullet-arrow-circle\"][data-srte-list-depth=\"2\"] > li::marker { content: \"\u25A0 \"; }\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li > [data-srte-check] {\n display: inline-flex;\n grid-column: 1;\n grid-row: 1;\n align-items: center;\n justify-content: center;\n width: 1.1em;\n height: 1.6em;\n min-width: 0;\n box-sizing: border-box;\n padding: 0;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: pointer;\n appearance: none;\n outline: none;\n margin: 0;\n line-height: 1.6;\n vertical-align: top;\n position: relative;\n}\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li > [data-srte-check]:focus-visible {\n outline: 2px solid var(--srte-ring);\n outline-offset: 2px;\n}\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li > [data-srte-check]::before {\n content: \"\";\n width: .9em;\n height: .9em;\n box-sizing: border-box;\n border: 1.5px solid var(--srte-muted-foreground);\n border-radius: 3px;\n background: var(--srte-canvas);\n}\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li > [data-srte-check][data-checked=\"true\"]::before {\n border-color: var(--srte-primary);\n background: var(--srte-primary);\n box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--srte-on-primary) 25%, transparent);\n}\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li > [data-srte-check][data-checked=\"true\"]::after {\n content: \"\";\n position: absolute;\n width: .42em;\n height: .22em;\n border-left: 1.5px solid var(--srte-on-primary);\n border-bottom: 1.5px solid var(--srte-on-primary);\n transform: translateY(-.08em) rotate(-45deg);\n}\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li > :is(p,h1,h2,h3,h4,h5,h6,blockquote,pre) {\n grid-column: 2;\n min-width: 0;\n margin-top: 0;\n}\n.srte-editor [contenteditable] ul[data-srte-checklist=\"true\"] > li > :is(ul,ol) {\n grid-column: 2;\n}\n.srte-editor:focus-within {\n border-color: var(--srte-ring) !important;\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--srte-ring) 18%, transparent);\n}\n/*\n * @container (element width), not @media (viewport width): a host can embed\n * the editor at any fraction of the browser window - a split pane next to a\n * preview panel is the case that surfaced this (docs/bugs/\n * toolbar-wide-promotion-fires-on-viewport-width-not-container-width.md). A\n * plain @media breakpoint here would fire based on the *window*, wrongly\n * switching tiers for an editor instance that's actually much narrower (or\n * wider) than the window - .srte-editor already establishes its own\n * container: srte-editor / inline-size (see the .srte-editor rule above),\n * so @container always reflects this specific instance's real rendered width regardless of host\n * layout, with no @media fallback needed (container queries have full\n * support across this project's three target engines).\n */\n@container srte-editor (max-width: 639px) {\n .srte-toolbar { gap: 3px; padding: 6px; }\n .srte-tool-button, .srte-toolbar select { height: 40px; min-width: 40px; }\n .srte-toolbar-group[data-srte-priority=\"3\"],\n .srte-toolbar-menu[data-srte-priority=\"2\"] { display: none; }\n .srte-mobile-more { display: block; }\n .srte-mobile-more .srte-menu {\n left: auto;\n right: 0;\n width: min(280px, calc(100vw - 16px));\n min-width: 0;\n max-height: min(70dvh, 480px);\n overflow-x: hidden;\n overflow-y: auto;\n overscroll-behavior: contain;\n -webkit-overflow-scrolling: touch;\n }\n .srte-menu-item { height: 40px; }\n}\n/*\n * Wide-viewport promotion (docs/bugs/toolbar-priority-collapse-fixed-threshold-no-wide-promotion.md):\n * below this, the single 639px breakpoint above was this system's ONLY\n * threshold - every dropdown-grouped tool stayed hidden inside its dropdown\n * at every width from 640px up to and past a 2200px+ desktop, since nothing\n * ever measured or scaled with the extra room. A handful of tools frequent\n * enough to matter once there's genuinely spare room (Superscript,\n * Subscript, Text colour, Background colour, Font size, Font family, Remove\n * link, Insert formula, Special characters) get a standalone always-visible\n * ToolbarButton copy (data-srte-wide-promote, rendered directly in the\n * toolbar row) that appears past this breakpoint, while their existing\n * dropdown/mobile-menu ToolbarMenuItem copy (the exact same\n * data-srte-wide-promote attribute, on the .srte-menu-item element instead)\n * hides so the tool isn't offered twice. Below this breakpoint - including\n * all of mobile AND the 640-1439px tablet/typical-laptop band, which keeps\n * today's grouped-dropdown layout unchanged - the standalone copy stays\n * hidden and the dropdown copy is what's reachable.\n *\n * 1440px, not 1280px: Playwright's own default test viewport is exactly\n * 1280x720, and the vast majority of this suite's toolbar interactions run\n * at that default without ever calling page.setViewportSize - a 1280px\n * threshold would have flipped nearly every existing toolbar test's\n * dropdown-item locators (role=menuitem) over to CSS display:none out from\n * under them. 1440px clears that default with room to spare while still\n * comfortably covering \"wide desktop\" (the ~2264px width the original\n * report was filed against).\n *\n * @container only, no @media fallback - same reasoning as the mobile tier\n * above (docs/bugs/toolbar-wide-promotion-fires-on-viewport-width-not-container-width.md):\n * a plain @media(min-width:1440px) fired whenever the *browser window* was\n * wide, even when this editor instance was embedded in a much narrower\n * split pane - promoting 9 extra buttons into a group with no room for\n * them, which squeezed/overlapped the group's existing buttons instead of\n * wrapping cleanly.\n */\n.srte-tool-button[data-srte-wide-promote=\"true\"] { display: none; }\n@container srte-editor (min-width: 1440px) {\n .srte-tool-button[data-srte-wide-promote=\"true\"] { display: inline-flex; }\n .srte-menu-item[data-srte-wide-promote=\"true\"] { display: none; }\n}\n.srte-editor [contenteditable] blockquote {\n border-left: 4px solid var(--srte-accent);\n margin: 0.75em 0;\n padding: 0.5em 1em;\n background: var(--srte-surface-subtle);\n color: var(--srte-text);\n}\n.srte-editor [contenteditable] p,\n.srte-editor [contenteditable] h1,\n.srte-editor [contenteditable] h2,\n.srte-editor [contenteditable] h3 {\n color: inherit;\n}\n.srte-editor [contenteditable] p {\n display: block;\n margin: 0 0 0.75em;\n font-size: 1em;\n font-weight: 400;\n line-height: 1.6;\n}\n.srte-editor [contenteditable] p[data-srte-caret-boundary=\"true\"] {\n min-height: 1.6em;\n}\n.srte-editor [contenteditable] h1,\n.srte-editor [contenteditable] h2,\n.srte-editor [contenteditable] h3 {\n display: block;\n margin: 0.75em 0 0.4em;\n font-weight: 700;\n line-height: 1.25;\n}\n.srte-editor [contenteditable] h1 {\n font-size: 2em;\n}\n.srte-editor [contenteditable] h2 {\n font-size: 1.5em;\n}\n.srte-editor [contenteditable] h3 {\n font-size: 1.25em;\n}\n.srte-editor [contenteditable] > :first-child {\n margin-top: 0;\n}\n.srte-editor [contenteditable] ul {\n list-style-type: disc;\n list-style-position: outside;\n margin: 0.75em 0;\n padding-left: 1.75em;\n}\n.srte-editor [contenteditable] ol {\n list-style-type: decimal;\n list-style-position: outside;\n margin: 0.75em 0;\n padding-left: 1.75em;\n}\n.srte-editor [contenteditable] li {\n display: list-item;\n margin: 0.25em 0;\n padding-left: 0.25em;\n}\n.srte-editor [contenteditable] li::marker {\n color: currentColor;\n}\n.srte-editor [contenteditable] table {\n width: 100%;\n margin: 0.75em 0;\n border-collapse: collapse;\n}\n.srte-editor [contenteditable] th,\n.srte-editor [contenteditable] td {\n padding: 8px;\n border: 1px solid var(--srte-border);\n vertical-align: top;\n}\n.srte-editor [contenteditable] [data-smart-cell-selected=\"true\"] {\n background: color-mix(in srgb, var(--srte-primary) 12%, var(--srte-canvas));\n box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--srte-primary) 65%, transparent);\n}\n.srte-editor [contenteditable][data-smart-cell-selection-active] ::selection {\n background: transparent;\n color: inherit;\n}\n.srte-editor [contenteditable] th {\n background: var(--srte-surface-subtle);\n font-weight: 600;\n text-align: left;\n}\n.srte-editor [contenteditable] td > h1,\n.srte-editor [contenteditable] td > h2,\n.srte-editor [contenteditable] td > h3,\n.srte-editor [contenteditable] th > h1,\n.srte-editor [contenteditable] th > h2,\n.srte-editor [contenteditable] th > h3 {\n margin: 0 0 0.4em;\n overflow-wrap: anywhere;\n}\n.srte-editor [contenteditable] pre {\n display: block;\n margin: 0.75em 0;\n padding: 12px 14px;\n overflow-x: auto;\n border: 1px solid var(--srte-border);\n border-radius: 6px;\n background: var(--srte-code-bg);\n color: var(--srte-code-text);\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", monospace;\n font-size: 0.9em;\n line-height: 1.55;\n white-space: pre-wrap;\n}\n.srte-editor [contenteditable] pre code {\n padding: 0;\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n}\n.srte-editor [contenteditable] code:not(pre code) {\n padding: 0.1em 0.35em;\n border-radius: 3px;\n background: var(--srte-code-bg);\n color: var(--srte-code-text);\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", monospace;\n font-size: 0.9em;\n}\n.srte-editor [contenteditable] a,\n.srte-editor [contenteditable] a:visited {\n color: var(--srte-primary) !important;\n text-decoration: underline !important;\n text-decoration-thickness: 1px !important;\n text-underline-offset: 2px !important;\n cursor: pointer;\n}\n.srte-editor [contenteditable] a:hover {\n color: var(--srte-accent) !important;\n}\n.srte-editor [contenteditable] a:focus-visible {\n outline: 2px solid var(--srte-accent);\n outline-offset: 2px;\n}\n.srte-editor [contenteditable] sub,\n.srte-editor [contenteditable] sup {\n line-height: 0;\n}\n";
|
|
3
3
|
export declare function ensureStyleSheet(): void;
|
package/dist/theme.js
CHANGED
|
@@ -196,6 +196,20 @@ export const SRTE_DEFAULT_CSS = `
|
|
|
196
196
|
color: var(--srte-menu-text);
|
|
197
197
|
box-shadow: var(--srte-menu-shadow);
|
|
198
198
|
}
|
|
199
|
+
/*
|
|
200
|
+
* ToolbarDropdown's own menu panel (docs/bugs/
|
|
201
|
+
* toolbar-dropdown-clipped-by-host-overflow-hidden.md): position:fixed with
|
|
202
|
+
* JS-measured left/top (ToolbarPrimitives.tsx) instead of the default
|
|
203
|
+
* position:absolute above, so it always escapes an ancestor host container's
|
|
204
|
+
* own overflow:hidden regardless of DOM depth - MobileMoreMenu's overflow
|
|
205
|
+
* menu (no data-srte-menu-fixed attribute) is unaffected and keeps its
|
|
206
|
+
* existing position:absolute/right-anchored behavior.
|
|
207
|
+
*/
|
|
208
|
+
.srte-menu[data-srte-menu-fixed="true"] {
|
|
209
|
+
position: fixed;
|
|
210
|
+
top: 0;
|
|
211
|
+
left: 0;
|
|
212
|
+
}
|
|
199
213
|
.srte-menu-item {
|
|
200
214
|
display: flex;
|
|
201
215
|
align-items: center;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "smartrte-react",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.3",
|
|
4
4
|
"description": "A powerful, feature-rich Rich Text Editor for React with support for tables, mathematical formulas (LaTeX/KaTeX), and media management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|