autumnnote 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -88,7 +88,7 @@ Right-click inside the editor opens a context menu with: **Undo**, **Redo**, **C
88
88
  - **Auto-fallback** — unknown codes or missing keys fall back to English
89
89
 
90
90
  ### UI
91
- - **Toolbar** — fully configurable button groups; overflow strategy: `wrap` (default) or `scroll`; FontAwesome icons with built-in SVG fallback
91
+ - **Toolbar** — fully configurable button groups; overflow strategy: `wrap` (default) or `scroll`; on viewports ≤ 640 px the toolbar automatically switches to a single horizontally-scrollable row regardless of the `toolbarOverflow` setting; FontAwesome icons with built-in SVG fallback
92
92
  - **Sticky toolbar** — `stickyToolbar: true` pins the toolbar to the viewport top; configurable offset for fixed nav bars
93
93
  - **Dark / light theme** — `theme: 'dark'` or `theme: 'light'` (default); full SCSS variable coverage
94
94
  - **Image resizer** — drag handle on selected image to resize proportionally
@@ -100,7 +100,7 @@ Right-click inside the editor opens a context menu with: **Undo**, **Redo**, **C
100
100
  - **Read-only mode** — `readOnly: true` renders a non-editable preview with toolbar hidden; toggle at runtime via `editor.setDisabled()`
101
101
  - **Auto-save** — `autoSave: true` persists content to `localStorage` on every change; key configurable via `autoSaveKey`
102
102
  - **Auto-save restore** — when `autoSave` and `autoSaveRestore` are both `true`, a dismissible banner prompts the user to restore or discard a previously saved draft on load; configurable age window via `autoSaveRestoreTimeout`
103
- - **Bubble toolbar** — `bubbleToolbar: true` shows a compact floating toolbar above selected text with quick-access buttons (bold, italic, underline, strikethrough, link, text colour, remove format, inline code); button set configurable via `bubbleToolbarItems`
103
+ - **Bubble toolbar** — `bubbleToolbar: true` shows a compact floating toolbar above selected text; default buttons: bold, italic, underline, strikethrough, link, **text colour**, **highlight colour**, remove format, inline code; each colour button displays a live colour-strip indicator and opens an inline colour palette (matching the context menu); button set configurable via `bubbleToolbarItems`
104
104
  - **Markdown shortcuts** — `markdownShortcuts: true` (default) converts Markdown syntax typed in the editor into HTML in real time: `# ` → H1–H3, `> ` → blockquote, `- ` / `* ` → unordered list, `1. ` → ordered list, `[ ] ` → checklist, `---` → HR, ` ``` ` → code block; inline: `**bold**`, `*italic*`, `~~strikethrough~~`, `` `code` ``
105
105
  - **Custom focus ring** — `focusColor` accepts any CSS colour string to override the default blue focus ring
106
106
  - **Spellcheck** — browser spellcheck enabled by default (`spellcheck: true`)
@@ -68,6 +68,7 @@
68
68
  background: #f9fafb;
69
69
  border-bottom: 1px solid #d1d5db;
70
70
  user-select: none;
71
+ border-radius: 6px 6px 0 0;
71
72
  }
72
73
 
73
74
  .an-btn-group {
@@ -140,9 +141,7 @@
140
141
 
141
142
  .an-table-picker-popup {
142
143
  display: none;
143
- position: absolute;
144
- top: calc(100% + 4px);
145
- left: 0;
144
+ position: fixed;
146
145
  background: #ffffff;
147
146
  border: 1px solid #d1d5db;
148
147
  border-radius: 6px;
@@ -654,6 +653,11 @@
654
653
  font-size: 11px;
655
654
  color: #6b7280;
656
655
  user-select: none;
656
+ border-radius: 0 0 6px 6px;
657
+ }
658
+
659
+ .an-container > .an-editable:last-child {
660
+ border-radius: 0 0 6px 6px;
657
661
  }
658
662
 
659
663
  .an-status-info {
@@ -1725,6 +1729,30 @@
1725
1729
  border-radius: 2px;
1726
1730
  }
1727
1731
 
1732
+ @media (max-width: 640px) {
1733
+ .an-toolbar {
1734
+ flex-wrap: nowrap;
1735
+ overflow-x: auto;
1736
+ scrollbar-width: none;
1737
+ -ms-overflow-style: none;
1738
+ }
1739
+ .an-toolbar::-webkit-scrollbar {
1740
+ display: none;
1741
+ }
1742
+ .an-select {
1743
+ min-width: 72px;
1744
+ max-width: 90px;
1745
+ font-size: 11px;
1746
+ }
1747
+ .an-select-style {
1748
+ min-width: 62px;
1749
+ max-width: 76px;
1750
+ }
1751
+ .an-select-narrow {
1752
+ min-width: 50px;
1753
+ max-width: 66px;
1754
+ }
1755
+ }
1728
1756
  .an-dir-rtl .an-toolbar {
1729
1757
  direction: rtl;
1730
1758
  }
@@ -1910,6 +1938,27 @@
1910
1938
  background: #dbeafe;
1911
1939
  color: #3b82f6;
1912
1940
  }
1941
+ .an-bubble-btn.an-bubble-btn--color {
1942
+ flex-direction: column;
1943
+ gap: 1px;
1944
+ padding: 4px 0 3px;
1945
+ }
1946
+ .an-bubble-btn.an-bubble-btn--color .an-bubble-btn-svg {
1947
+ display: flex;
1948
+ align-items: center;
1949
+ justify-content: center;
1950
+ line-height: 0;
1951
+ }
1952
+ .an-bubble-btn.an-bubble-btn--color .an-bubble-btn-svg svg {
1953
+ display: block;
1954
+ }
1955
+ .an-bubble-btn.an-bubble-btn--color .an-bubble-color-strip {
1956
+ display: block;
1957
+ width: 14px;
1958
+ height: 3px;
1959
+ border-radius: 1px;
1960
+ pointer-events: none;
1961
+ }
1913
1962
  .an-theme-dark .an-bubble-btn {
1914
1963
  color: #cdd6f4;
1915
1964
  }
@@ -1921,6 +1970,21 @@
1921
1970
  color: #93c5fd;
1922
1971
  }
1923
1972
 
1973
+ .an-bubble-color-picker {
1974
+ position: fixed;
1975
+ z-index: 10041;
1976
+ background: #ffffff;
1977
+ border: 1px solid #d1d5db;
1978
+ border-radius: 8px;
1979
+ box-shadow: 0 8px 28px rgba(0, 0, 0, 0.14);
1980
+ padding: 4px 0;
1981
+ min-width: 160px;
1982
+ }
1983
+ .an-theme-dark .an-bubble-color-picker {
1984
+ background: #24273a;
1985
+ border-color: #3f3f5f;
1986
+ }
1987
+
1924
1988
  .an-mention-dropdown {
1925
1989
  display: none;
1926
1990
  position: fixed;
@@ -1455,6 +1455,7 @@ var defaultOptions = {
1455
1455
  "underline",
1456
1456
  "link",
1457
1457
  "foreColor",
1458
+ "hiliteColor",
1458
1459
  "removeFormat"
1459
1460
  ],
1460
1461
  mention: null
@@ -5838,12 +5839,23 @@ var Toolbar = class {
5838
5839
  };
5839
5840
  const openPopup = () => {
5840
5841
  isOpen = true;
5842
+ const rect = btn.getBoundingClientRect();
5841
5843
  popup.style.display = "block";
5844
+ const pw = popup.offsetWidth;
5845
+ const ph = popup.offsetHeight;
5846
+ let left = rect.left;
5847
+ let top = rect.bottom + 4;
5848
+ if (left + pw > window.innerWidth - 8) left = Math.max(8, window.innerWidth - pw - 8);
5849
+ if (top + ph > window.innerHeight - 8) top = rect.top - ph - 4;
5850
+ popup.style.left = `${left}px`;
5851
+ popup.style.top = `${top}px`;
5842
5852
  btn.setAttribute("aria-expanded", "true");
5843
5853
  };
5844
5854
  const closePopup = () => {
5845
5855
  isOpen = false;
5846
5856
  popup.style.display = "none";
5857
+ popup.style.top = "";
5858
+ popup.style.left = "";
5847
5859
  btn.setAttribute("aria-expanded", "false");
5848
5860
  setHighlight(0, 0);
5849
5861
  };
@@ -12969,7 +12981,7 @@ var ICONS = {
12969
12981
  noColor: `<svg xmlns="http://www.w3.org/2000/svg" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="4" y1="4" x2="20" y2="20"/><line x1="20" y1="4" x2="4" y2="20"/></svg>`,
12970
12982
  back: `<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>`
12971
12983
  };
12972
- var COLOR_PRESETS = [
12984
+ var COLOR_PRESETS$1 = [
12973
12985
  "#000000",
12974
12986
  "#434343",
12975
12987
  "#666666",
@@ -13257,7 +13269,7 @@ var ContextMenu = class {
13257
13269
  }
13258
13270
  if (it.colorPalette) {
13259
13271
  const palette = createElement("div", { class: "an-context-color-palette" });
13260
- COLOR_PRESETS.forEach((color) => {
13272
+ COLOR_PRESETS$1.forEach((color) => {
13261
13273
  const sw = createElement("div", {
13262
13274
  class: "an-context-color-swatch",
13263
13275
  title: color,
@@ -14916,9 +14928,35 @@ var MarkdownShortcuts = class {
14916
14928
  * controlled by `bubbleToolbarItems` (array of button name strings).
14917
14929
  *
14918
14930
  * Built-in names: 'bold', 'italic', 'underline', 'strikethrough',
14919
- * 'link', 'foreColor', 'removeFormat', 'inlineCode'.
14931
+ * 'link', 'foreColor', 'hiliteColor', 'removeFormat', 'inlineCode'.
14920
14932
  * Any name not found in the built-in map is silently ignored.
14921
14933
  */
14934
+ var COLOR_PRESETS = [
14935
+ "#000000",
14936
+ "#434343",
14937
+ "#666666",
14938
+ "#999999",
14939
+ "#b7b7b7",
14940
+ "#cccccc",
14941
+ "#efefef",
14942
+ "#ffffff",
14943
+ "#ff0000",
14944
+ "#ff9900",
14945
+ "#ffff00",
14946
+ "#00ff00",
14947
+ "#00ffff",
14948
+ "#4a86e8",
14949
+ "#9900ff",
14950
+ "#ff00ff",
14951
+ "#f4cccc",
14952
+ "#fce5cd",
14953
+ "#fff2cc",
14954
+ "#d9ead3",
14955
+ "#d0e0e3",
14956
+ "#c9daf8",
14957
+ "#d9d2e9",
14958
+ "#ead1dc"
14959
+ ];
14922
14960
  var _S = "stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"";
14923
14961
  var _svg = (p) => `<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" ${_S} style="display:block">${p}</svg>`;
14924
14962
  var _ICONS = {
@@ -14928,6 +14966,7 @@ var _ICONS = {
14928
14966
  strikethrough: _svg("<path d=\"M17.3 12H6.7\"/><path d=\"M10 6.5C10 5.1 11.1 4 12.5 4c1.4 0 2.5 1.1 2.5 2.5 0 .8-.4 1.5-1 2\"/><path d=\"M14 17.5C14 19 12.9 20 11.5 20 10.1 20 9 18.9 9 17.5c0-.8.4-1.5 1-2\"/>"),
14929
14967
  link: _svg("<path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/>"),
14930
14968
  foreColor: _svg("<path d=\"M4 20L12 4L20 20\"/><line x1=\"7.5\" y1=\"14\" x2=\"16.5\" y2=\"14\"/>"),
14969
+ hiliteColor: _svg("<path d=\"M3 21v-4l9-9 4 4-9 9z\"/><path d=\"M12 8l4 4\"/><line x1=\"3\" y1=\"21\" x2=\"21\" y2=\"21\"/>"),
14931
14970
  removeFormat: _svg("<path d=\"m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21\"/><path d=\"M22 21H7\"/><path d=\"m5 11 9 9\"/>"),
14932
14971
  inlineCode: _svg("<path d=\"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1\"/><path d=\"M16 3h1a2 2 0 0 1 2 2v5c0 1.1.9 2 2 2a2 2 0 0 1-2 2v5a2 2 0 0 1-2 2h-1\"/>")
14933
14972
  };
@@ -14937,11 +14976,13 @@ var _ACTIONS = {
14937
14976
  underline: (ctx) => ctx.invoke("editor.underline"),
14938
14977
  strikethrough: (ctx) => ctx.invoke("editor.strikethrough"),
14939
14978
  link: (ctx) => ctx.invoke("linkDialog.show"),
14940
- foreColor: (ctx) => {
14941
- const color = window.prompt("Text color (hex or name):", "#000000");
14942
- if (color) ctx.invoke("editor.foreColor", color);
14979
+ removeFormat: (ctx) => {
14980
+ const editable = ctx.layoutInfo && ctx.layoutInfo.editable;
14981
+ if (!editable) return;
14982
+ editable.focus();
14983
+ document.execCommand("removeFormat");
14984
+ ctx.invoke("editor.afterCommand");
14943
14985
  },
14944
- removeFormat: (ctx) => ctx.invoke("editor.removeFormat"),
14945
14986
  inlineCode: (ctx) => ctx.invoke("editor.inlineCode")
14946
14987
  };
14947
14988
  var _ACTIVE = {
@@ -14950,6 +14991,10 @@ var _ACTIVE = {
14950
14991
  underline: () => document.queryCommandState("underline"),
14951
14992
  strikethrough: () => document.queryCommandState("strikeThrough")
14952
14993
  };
14994
+ var _COLOR_TYPES = {
14995
+ foreColor: true,
14996
+ hiliteColor: true
14997
+ };
14953
14998
  var BubbleToolbar = class {
14954
14999
  /** @param {import('../Context.js').Context} context */
14955
15000
  constructor(context) {
@@ -14957,6 +15002,10 @@ var BubbleToolbar = class {
14957
15002
  this.options = context.options;
14958
15003
  /** @type {HTMLElement|null} */
14959
15004
  this._el = null;
15005
+ /** @type {HTMLElement|null} */
15006
+ this._picker = null;
15007
+ this._pickerType = null;
15008
+ this._savedRange = null;
14960
15009
  this._visible = false;
14961
15010
  this._rafId = null;
14962
15011
  this._contextMenuOpen = false;
@@ -14969,6 +15018,7 @@ var BubbleToolbar = class {
14969
15018
  initialize() {
14970
15019
  if (!this.options.bubbleToolbar) return this;
14971
15020
  this._build();
15021
+ this._buildColorPicker();
14972
15022
  const d1 = on(document, "selectionchange", this._onSelectionChange);
14973
15023
  const d2 = on(document, "mousedown", this._onMousedown);
14974
15024
  const d3 = on(document, "keydown", this._onKeydown);
@@ -14986,6 +15036,8 @@ var BubbleToolbar = class {
14986
15036
  destroy() {
14987
15037
  if (this._el && this._el.parentNode) this._el.parentNode.removeChild(this._el);
14988
15038
  this._el = null;
15039
+ if (this._picker && this._picker.parentNode) this._picker.parentNode.removeChild(this._picker);
15040
+ this._picker = null;
14989
15041
  this._disposers.forEach((d) => d());
14990
15042
  this._disposers = [];
14991
15043
  cancelAnimationFrame(this._rafId);
@@ -15001,25 +15053,41 @@ var BubbleToolbar = class {
15001
15053
  "underline",
15002
15054
  "link",
15003
15055
  "foreColor",
15056
+ "hiliteColor",
15004
15057
  "removeFormat"
15005
15058
  ];
15006
15059
  for (const name of items) {
15007
- if (!_ICONS[name] || !_ACTIONS[name]) continue;
15060
+ if (!_ICONS[name]) continue;
15008
15061
  const btn = document.createElement("button");
15009
15062
  btn.type = "button";
15010
- btn.className = "an-bubble-btn";
15011
15063
  btn.dataset.name = name;
15012
15064
  btn.setAttribute("aria-label", name);
15013
- btn.innerHTML = _ICONS[name];
15065
+ if (_COLOR_TYPES[name]) {
15066
+ btn.className = "an-bubble-btn an-bubble-btn--color";
15067
+ const iconWrap = document.createElement("span");
15068
+ iconWrap.className = "an-bubble-btn-svg";
15069
+ iconWrap.innerHTML = _ICONS[name];
15070
+ const strip = document.createElement("span");
15071
+ strip.className = "an-bubble-color-strip";
15072
+ strip.style.background = name === "foreColor" ? "#000000" : "transparent";
15073
+ btn.appendChild(iconWrap);
15074
+ btn.appendChild(strip);
15075
+ } else {
15076
+ btn.className = "an-bubble-btn";
15077
+ btn.innerHTML = _ICONS[name];
15078
+ }
15014
15079
  btn.addEventListener("mousedown", (e) => {
15015
15080
  e.preventDefault();
15016
15081
  });
15017
15082
  btn.addEventListener("click", (e) => {
15018
15083
  e.preventDefault();
15019
15084
  e.stopPropagation();
15085
+ if (_COLOR_TYPES[name]) {
15086
+ this._openColorPicker(name, btn);
15087
+ return;
15088
+ }
15020
15089
  this.context.invoke("editor.focus");
15021
- _ACTIONS[name](this.context);
15022
- this.context.invoke("editor.afterCommand");
15090
+ if (_ACTIONS[name]) _ACTIONS[name](this.context);
15023
15091
  this._syncActive();
15024
15092
  });
15025
15093
  el.appendChild(btn);
@@ -15027,6 +15095,100 @@ var BubbleToolbar = class {
15027
15095
  document.body.appendChild(el);
15028
15096
  this._el = el;
15029
15097
  }
15098
+ _buildColorPicker() {
15099
+ const picker = document.createElement("div");
15100
+ picker.className = "an-bubble-color-picker";
15101
+ picker.style.display = "none";
15102
+ picker.addEventListener("mousedown", (e) => e.preventDefault());
15103
+ const palette = document.createElement("div");
15104
+ palette.className = "an-context-color-palette";
15105
+ COLOR_PRESETS.forEach((color) => {
15106
+ const sw = document.createElement("div");
15107
+ sw.className = "an-context-color-swatch";
15108
+ sw.title = color;
15109
+ sw.style.background = color;
15110
+ sw.setAttribute("role", "button");
15111
+ sw.setAttribute("aria-label", color);
15112
+ sw.addEventListener("click", (e) => {
15113
+ e.stopPropagation();
15114
+ this._applyColor(this._pickerType, color);
15115
+ });
15116
+ palette.appendChild(sw);
15117
+ });
15118
+ const noColorBtn = document.createElement("div");
15119
+ noColorBtn.className = "an-context-color-swatch an-context-color-none";
15120
+ noColorBtn.title = "No highlight";
15121
+ noColorBtn.setAttribute("role", "button");
15122
+ noColorBtn.setAttribute("aria-label", "No highlight");
15123
+ noColorBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="4" y1="4" x2="20" y2="20"/><line x1="20" y1="4" x2="4" y2="20"/></svg>`;
15124
+ noColorBtn.addEventListener("click", (e) => {
15125
+ e.stopPropagation();
15126
+ this._applyColor("hiliteColor", "transparent");
15127
+ });
15128
+ const customRow = document.createElement("div");
15129
+ customRow.className = "an-context-color-custom";
15130
+ const colorInput = document.createElement("input");
15131
+ colorInput.type = "color";
15132
+ colorInput.value = "#000000";
15133
+ colorInput.title = "Custom color";
15134
+ colorInput.addEventListener("mousedown", (e) => e.stopPropagation());
15135
+ colorInput.addEventListener("change", () => {
15136
+ this._applyColor(this._pickerType, colorInput.value);
15137
+ });
15138
+ const customLabel = document.createElement("span");
15139
+ customLabel.textContent = "Custom…";
15140
+ customRow.appendChild(colorInput);
15141
+ customRow.appendChild(customLabel);
15142
+ picker.appendChild(palette);
15143
+ picker.appendChild(customRow);
15144
+ document.body.appendChild(picker);
15145
+ this._picker = picker;
15146
+ this._picker._paletteEl = palette;
15147
+ this._picker._noColorBtn = noColorBtn;
15148
+ this._picker._colorInput = colorInput;
15149
+ }
15150
+ _openColorPicker(type, anchorBtn) {
15151
+ const sel = window.getSelection();
15152
+ if (sel && sel.rangeCount > 0) this._savedRange = sel.getRangeAt(0).cloneRange();
15153
+ this._pickerType = type;
15154
+ const palette = this._picker._paletteEl;
15155
+ const noColorBtn = this._picker._noColorBtn;
15156
+ if (type === "hiliteColor") {
15157
+ if (!palette.contains(noColorBtn)) palette.appendChild(noColorBtn);
15158
+ } else if (palette.contains(noColorBtn)) palette.removeChild(noColorBtn);
15159
+ this._picker._colorInput.value = type === "foreColor" ? "#000000" : "#ffff00";
15160
+ this._picker.style.display = "block";
15161
+ const pw = this._picker.offsetWidth;
15162
+ const ph = this._picker.offsetHeight;
15163
+ const toolbarRect = this._el.getBoundingClientRect();
15164
+ let top = toolbarRect.top - ph - 6;
15165
+ if (top < 8) top = toolbarRect.bottom + 6;
15166
+ let left = anchorBtn.getBoundingClientRect().left;
15167
+ left = Math.max(8, Math.min(left, window.innerWidth - pw - 8));
15168
+ this._picker.style.left = `${left}px`;
15169
+ this._picker.style.top = `${top}px`;
15170
+ }
15171
+ _closeColorPicker() {
15172
+ if (this._picker) this._picker.style.display = "none";
15173
+ this._pickerType = null;
15174
+ }
15175
+ /** Restore the saved selection, apply execCommand, update the color strip, then close the picker. */
15176
+ _applyColor(type, color) {
15177
+ const editable = this.context.layoutInfo && this.context.layoutInfo.editable;
15178
+ if (!editable || !this._savedRange) return;
15179
+ editable.focus();
15180
+ const sel = window.getSelection();
15181
+ sel.removeAllRanges();
15182
+ sel.addRange(this._savedRange.cloneRange());
15183
+ document.execCommand(type, false, color);
15184
+ this.context.invoke("editor.afterCommand");
15185
+ const name = type === "hiliteColor" ? "hiliteColor" : "foreColor";
15186
+ const btn = this._el && this._el.querySelector(`[data-name="${name}"]`);
15187
+ const strip = btn && btn.querySelector(".an-bubble-color-strip");
15188
+ if (strip) strip.style.background = color === "transparent" ? "transparent" : color;
15189
+ this._closeColorPicker();
15190
+ this._syncActive();
15191
+ }
15030
15192
  _show(rect) {
15031
15193
  if (!this._el) return;
15032
15194
  const el = this._el;
@@ -15043,12 +15205,14 @@ var BubbleToolbar = class {
15043
15205
  el.style.left = `${left}px`;
15044
15206
  el.style.visibility = "";
15045
15207
  this._syncActive();
15208
+ this._syncColorStrips();
15046
15209
  this._visible = true;
15047
15210
  }
15048
15211
  _hide() {
15049
15212
  if (!this._el) return;
15050
15213
  this._el.style.display = "none";
15051
15214
  this._visible = false;
15215
+ this._closeColorPicker();
15052
15216
  }
15053
15217
  _syncActive() {
15054
15218
  if (!this._el) return;
@@ -15057,10 +15221,30 @@ var BubbleToolbar = class {
15057
15221
  btn.classList.toggle("an-active", !!(activeFn && activeFn()));
15058
15222
  });
15059
15223
  }
15224
+ /** Read the current selection's color and update the color-strip indicators. */
15225
+ _syncColorStrips() {
15226
+ if (!this._el) return;
15227
+ const sel = window.getSelection();
15228
+ if (!sel || !sel.rangeCount) return;
15229
+ let node = sel.getRangeAt(0).startContainer;
15230
+ if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;
15231
+ if (!node) return;
15232
+ const cs = window.getComputedStyle(node);
15233
+ const foreBtn = this._el.querySelector("[data-name=\"foreColor\"]");
15234
+ const foreStrip = foreBtn && foreBtn.querySelector(".an-bubble-color-strip");
15235
+ if (foreStrip) foreStrip.style.background = cs.color || "#000000";
15236
+ const hiliteBtn = this._el.querySelector("[data-name=\"hiliteColor\"]");
15237
+ const hiliteStrip = hiliteBtn && hiliteBtn.querySelector(".an-bubble-color-strip");
15238
+ if (hiliteStrip) {
15239
+ const bg = cs.backgroundColor;
15240
+ hiliteStrip.style.background = !bg || bg === "rgba(0, 0, 0, 0)" || bg === "transparent" ? "transparent" : bg;
15241
+ }
15242
+ }
15060
15243
  _onSelectionChange() {
15061
15244
  cancelAnimationFrame(this._rafId);
15062
15245
  this._rafId = requestAnimationFrame(() => {
15063
15246
  if (this._contextMenuOpen) return;
15247
+ if (this._picker && this._picker.style.display !== "none") return;
15064
15248
  const sel = window.getSelection();
15065
15249
  if (!sel || sel.isCollapsed || !sel.rangeCount) {
15066
15250
  this._hide();
@@ -15085,11 +15269,15 @@ var BubbleToolbar = class {
15085
15269
  _onMousedown(e) {
15086
15270
  if (!this._visible) return;
15087
15271
  if (this._el && this._el.contains(e.target)) return;
15272
+ if (this._picker && this._picker.contains(e.target)) return;
15088
15273
  if (this.context.layoutInfo.editable.contains(e.target)) return;
15089
15274
  this._hide();
15090
15275
  }
15091
15276
  _onKeydown(e) {
15092
- if (e.key === "Escape" && this._visible) this._hide();
15277
+ if (e.key === "Escape") {
15278
+ if (this._picker && this._picker.style.display !== "none") this._closeColorPicker();
15279
+ else if (this._visible) this._hide();
15280
+ }
15093
15281
  }
15094
15282
  _onContextMenu() {
15095
15283
  this._hide();