autumnnote 1.1.1 → 1.2.1

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.
@@ -1173,6 +1173,7 @@
1173
1173
  "underline",
1174
1174
  "link",
1175
1175
  "foreColor",
1176
+ "hiliteColor",
1176
1177
  "removeFormat"
1177
1178
  ],
1178
1179
  mention: null
@@ -5556,7 +5557,18 @@
5556
5557
  };
5557
5558
  const openPopup = () => {
5558
5559
  isOpen = true;
5560
+ const rect = btn.getBoundingClientRect();
5561
+ popup.style.visibility = "hidden";
5559
5562
  popup.style.display = "block";
5563
+ const pw = popup.offsetWidth;
5564
+ const ph = popup.offsetHeight;
5565
+ let left = rect.left;
5566
+ let top = rect.bottom + 4;
5567
+ if (left + pw > window.innerWidth - 8) left = Math.max(8, window.innerWidth - pw - 8);
5568
+ if (top + ph > window.innerHeight - 8) top = rect.top - ph - 4;
5569
+ popup.style.left = `${left}px`;
5570
+ popup.style.top = `${top}px`;
5571
+ popup.style.visibility = "";
5560
5572
  btn.setAttribute("aria-expanded", "true");
5561
5573
  };
5562
5574
  const closePopup = () => {
@@ -5588,9 +5600,11 @@
5588
5600
  const d5 = on(document, "click", () => {
5589
5601
  if (isOpen) closePopup();
5590
5602
  });
5591
- this._disposers.push(d1, d2, d3, d4, d5);
5603
+ this._disposers.push(d1, d2, d3, d4, d5, () => {
5604
+ if (popup.parentNode) popup.parentNode.removeChild(popup);
5605
+ });
5592
5606
  wrap.appendChild(btn);
5593
- wrap.appendChild(popup);
5607
+ document.body.appendChild(popup);
5594
5608
  return wrap;
5595
5609
  }
5596
5610
  /**
@@ -12687,7 +12701,7 @@
12687
12701
  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>`,
12688
12702
  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>`
12689
12703
  };
12690
- var COLOR_PRESETS = [
12704
+ var COLOR_PRESETS$1 = [
12691
12705
  "#000000",
12692
12706
  "#434343",
12693
12707
  "#666666",
@@ -12975,7 +12989,7 @@
12975
12989
  }
12976
12990
  if (it.colorPalette) {
12977
12991
  const palette = createElement("div", { class: "an-context-color-palette" });
12978
- COLOR_PRESETS.forEach((color) => {
12992
+ COLOR_PRESETS$1.forEach((color) => {
12979
12993
  const sw = createElement("div", {
12980
12994
  class: "an-context-color-swatch",
12981
12995
  title: color,
@@ -14634,9 +14648,35 @@
14634
14648
  * controlled by `bubbleToolbarItems` (array of button name strings).
14635
14649
  *
14636
14650
  * Built-in names: 'bold', 'italic', 'underline', 'strikethrough',
14637
- * 'link', 'foreColor', 'removeFormat', 'inlineCode'.
14651
+ * 'link', 'foreColor', 'hiliteColor', 'removeFormat', 'inlineCode'.
14638
14652
  * Any name not found in the built-in map is silently ignored.
14639
14653
  */
14654
+ var COLOR_PRESETS = [
14655
+ "#000000",
14656
+ "#434343",
14657
+ "#666666",
14658
+ "#999999",
14659
+ "#b7b7b7",
14660
+ "#cccccc",
14661
+ "#efefef",
14662
+ "#ffffff",
14663
+ "#ff0000",
14664
+ "#ff9900",
14665
+ "#ffff00",
14666
+ "#00ff00",
14667
+ "#00ffff",
14668
+ "#4a86e8",
14669
+ "#9900ff",
14670
+ "#ff00ff",
14671
+ "#f4cccc",
14672
+ "#fce5cd",
14673
+ "#fff2cc",
14674
+ "#d9ead3",
14675
+ "#d0e0e3",
14676
+ "#c9daf8",
14677
+ "#d9d2e9",
14678
+ "#ead1dc"
14679
+ ];
14640
14680
  var _S = "stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"";
14641
14681
  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>`;
14642
14682
  var _ICONS = {
@@ -14646,6 +14686,7 @@
14646
14686
  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\"/>"),
14647
14687
  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\"/>"),
14648
14688
  foreColor: _svg("<path d=\"M4 20L12 4L20 20\"/><line x1=\"7.5\" y1=\"14\" x2=\"16.5\" y2=\"14\"/>"),
14689
+ 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\"/>"),
14649
14690
  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\"/>"),
14650
14691
  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\"/>")
14651
14692
  };
@@ -14655,11 +14696,13 @@
14655
14696
  underline: (ctx) => ctx.invoke("editor.underline"),
14656
14697
  strikethrough: (ctx) => ctx.invoke("editor.strikethrough"),
14657
14698
  link: (ctx) => ctx.invoke("linkDialog.show"),
14658
- foreColor: (ctx) => {
14659
- const color = window.prompt("Text color (hex or name):", "#000000");
14660
- if (color) ctx.invoke("editor.foreColor", color);
14699
+ removeFormat: (ctx) => {
14700
+ const editable = ctx.layoutInfo && ctx.layoutInfo.editable;
14701
+ if (!editable) return;
14702
+ editable.focus();
14703
+ document.execCommand("removeFormat");
14704
+ ctx.invoke("editor.afterCommand");
14661
14705
  },
14662
- removeFormat: (ctx) => ctx.invoke("editor.removeFormat"),
14663
14706
  inlineCode: (ctx) => ctx.invoke("editor.inlineCode")
14664
14707
  };
14665
14708
  var _ACTIVE = {
@@ -14668,6 +14711,10 @@
14668
14711
  underline: () => document.queryCommandState("underline"),
14669
14712
  strikethrough: () => document.queryCommandState("strikeThrough")
14670
14713
  };
14714
+ var _COLOR_TYPES = {
14715
+ foreColor: true,
14716
+ hiliteColor: true
14717
+ };
14671
14718
  var BubbleToolbar = class {
14672
14719
  /** @param {import('../Context.js').Context} context */
14673
14720
  constructor(context) {
@@ -14675,6 +14722,10 @@
14675
14722
  this.options = context.options;
14676
14723
  /** @type {HTMLElement|null} */
14677
14724
  this._el = null;
14725
+ /** @type {HTMLElement|null} */
14726
+ this._picker = null;
14727
+ this._pickerType = null;
14728
+ this._savedRange = null;
14678
14729
  this._visible = false;
14679
14730
  this._rafId = null;
14680
14731
  this._contextMenuOpen = false;
@@ -14687,6 +14738,7 @@
14687
14738
  initialize() {
14688
14739
  if (!this.options.bubbleToolbar) return this;
14689
14740
  this._build();
14741
+ this._buildColorPicker();
14690
14742
  const d1 = on(document, "selectionchange", this._onSelectionChange);
14691
14743
  const d2 = on(document, "mousedown", this._onMousedown);
14692
14744
  const d3 = on(document, "keydown", this._onKeydown);
@@ -14704,6 +14756,8 @@
14704
14756
  destroy() {
14705
14757
  if (this._el && this._el.parentNode) this._el.parentNode.removeChild(this._el);
14706
14758
  this._el = null;
14759
+ if (this._picker && this._picker.parentNode) this._picker.parentNode.removeChild(this._picker);
14760
+ this._picker = null;
14707
14761
  this._disposers.forEach((d) => d());
14708
14762
  this._disposers = [];
14709
14763
  cancelAnimationFrame(this._rafId);
@@ -14719,25 +14773,41 @@
14719
14773
  "underline",
14720
14774
  "link",
14721
14775
  "foreColor",
14776
+ "hiliteColor",
14722
14777
  "removeFormat"
14723
14778
  ];
14724
14779
  for (const name of items) {
14725
- if (!_ICONS[name] || !_ACTIONS[name]) continue;
14780
+ if (!_ICONS[name]) continue;
14726
14781
  const btn = document.createElement("button");
14727
14782
  btn.type = "button";
14728
- btn.className = "an-bubble-btn";
14729
14783
  btn.dataset.name = name;
14730
14784
  btn.setAttribute("aria-label", name);
14731
- btn.innerHTML = _ICONS[name];
14785
+ if (_COLOR_TYPES[name]) {
14786
+ btn.className = "an-bubble-btn an-bubble-btn--color";
14787
+ const iconWrap = document.createElement("span");
14788
+ iconWrap.className = "an-bubble-btn-svg";
14789
+ iconWrap.innerHTML = _ICONS[name];
14790
+ const strip = document.createElement("span");
14791
+ strip.className = "an-bubble-color-strip";
14792
+ strip.style.background = name === "foreColor" ? "#000000" : "transparent";
14793
+ btn.appendChild(iconWrap);
14794
+ btn.appendChild(strip);
14795
+ } else {
14796
+ btn.className = "an-bubble-btn";
14797
+ btn.innerHTML = _ICONS[name];
14798
+ }
14732
14799
  btn.addEventListener("mousedown", (e) => {
14733
14800
  e.preventDefault();
14734
14801
  });
14735
14802
  btn.addEventListener("click", (e) => {
14736
14803
  e.preventDefault();
14737
14804
  e.stopPropagation();
14805
+ if (_COLOR_TYPES[name]) {
14806
+ this._openColorPicker(name, btn);
14807
+ return;
14808
+ }
14738
14809
  this.context.invoke("editor.focus");
14739
- _ACTIONS[name](this.context);
14740
- this.context.invoke("editor.afterCommand");
14810
+ if (_ACTIONS[name]) _ACTIONS[name](this.context);
14741
14811
  this._syncActive();
14742
14812
  });
14743
14813
  el.appendChild(btn);
@@ -14745,6 +14815,100 @@
14745
14815
  document.body.appendChild(el);
14746
14816
  this._el = el;
14747
14817
  }
14818
+ _buildColorPicker() {
14819
+ const picker = document.createElement("div");
14820
+ picker.className = "an-bubble-color-picker";
14821
+ picker.style.display = "none";
14822
+ picker.addEventListener("mousedown", (e) => e.preventDefault());
14823
+ const palette = document.createElement("div");
14824
+ palette.className = "an-context-color-palette";
14825
+ COLOR_PRESETS.forEach((color) => {
14826
+ const sw = document.createElement("div");
14827
+ sw.className = "an-context-color-swatch";
14828
+ sw.title = color;
14829
+ sw.style.background = color;
14830
+ sw.setAttribute("role", "button");
14831
+ sw.setAttribute("aria-label", color);
14832
+ sw.addEventListener("click", (e) => {
14833
+ e.stopPropagation();
14834
+ this._applyColor(this._pickerType, color);
14835
+ });
14836
+ palette.appendChild(sw);
14837
+ });
14838
+ const noColorBtn = document.createElement("div");
14839
+ noColorBtn.className = "an-context-color-swatch an-context-color-none";
14840
+ noColorBtn.title = "No highlight";
14841
+ noColorBtn.setAttribute("role", "button");
14842
+ noColorBtn.setAttribute("aria-label", "No highlight");
14843
+ 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>`;
14844
+ noColorBtn.addEventListener("click", (e) => {
14845
+ e.stopPropagation();
14846
+ this._applyColor("hiliteColor", "transparent");
14847
+ });
14848
+ const customRow = document.createElement("div");
14849
+ customRow.className = "an-context-color-custom";
14850
+ const colorInput = document.createElement("input");
14851
+ colorInput.type = "color";
14852
+ colorInput.value = "#000000";
14853
+ colorInput.title = "Custom color";
14854
+ colorInput.addEventListener("mousedown", (e) => e.stopPropagation());
14855
+ colorInput.addEventListener("change", () => {
14856
+ this._applyColor(this._pickerType, colorInput.value);
14857
+ });
14858
+ const customLabel = document.createElement("span");
14859
+ customLabel.textContent = "Custom…";
14860
+ customRow.appendChild(colorInput);
14861
+ customRow.appendChild(customLabel);
14862
+ picker.appendChild(palette);
14863
+ picker.appendChild(customRow);
14864
+ document.body.appendChild(picker);
14865
+ this._picker = picker;
14866
+ this._picker._paletteEl = palette;
14867
+ this._picker._noColorBtn = noColorBtn;
14868
+ this._picker._colorInput = colorInput;
14869
+ }
14870
+ _openColorPicker(type, anchorBtn) {
14871
+ const sel = window.getSelection();
14872
+ if (sel && sel.rangeCount > 0) this._savedRange = sel.getRangeAt(0).cloneRange();
14873
+ this._pickerType = type;
14874
+ const palette = this._picker._paletteEl;
14875
+ const noColorBtn = this._picker._noColorBtn;
14876
+ if (type === "hiliteColor") {
14877
+ if (!palette.contains(noColorBtn)) palette.appendChild(noColorBtn);
14878
+ } else if (palette.contains(noColorBtn)) palette.removeChild(noColorBtn);
14879
+ this._picker._colorInput.value = type === "foreColor" ? "#000000" : "#ffff00";
14880
+ this._picker.style.display = "block";
14881
+ const pw = this._picker.offsetWidth;
14882
+ const ph = this._picker.offsetHeight;
14883
+ const toolbarRect = this._el.getBoundingClientRect();
14884
+ let top = toolbarRect.top - ph - 6;
14885
+ if (top < 8) top = toolbarRect.bottom + 6;
14886
+ let left = anchorBtn.getBoundingClientRect().left;
14887
+ left = Math.max(8, Math.min(left, window.innerWidth - pw - 8));
14888
+ this._picker.style.left = `${left}px`;
14889
+ this._picker.style.top = `${top}px`;
14890
+ }
14891
+ _closeColorPicker() {
14892
+ if (this._picker) this._picker.style.display = "none";
14893
+ this._pickerType = null;
14894
+ }
14895
+ /** Restore the saved selection, apply execCommand, update the color strip, then close the picker. */
14896
+ _applyColor(type, color) {
14897
+ const editable = this.context.layoutInfo && this.context.layoutInfo.editable;
14898
+ if (!editable || !this._savedRange) return;
14899
+ editable.focus();
14900
+ const sel = window.getSelection();
14901
+ sel.removeAllRanges();
14902
+ sel.addRange(this._savedRange.cloneRange());
14903
+ document.execCommand(type, false, color);
14904
+ this.context.invoke("editor.afterCommand");
14905
+ const name = type === "hiliteColor" ? "hiliteColor" : "foreColor";
14906
+ const btn = this._el && this._el.querySelector(`[data-name="${name}"]`);
14907
+ const strip = btn && btn.querySelector(".an-bubble-color-strip");
14908
+ if (strip) strip.style.background = color === "transparent" ? "transparent" : color;
14909
+ this._closeColorPicker();
14910
+ this._syncActive();
14911
+ }
14748
14912
  _show(rect) {
14749
14913
  if (!this._el) return;
14750
14914
  const el = this._el;
@@ -14761,12 +14925,14 @@
14761
14925
  el.style.left = `${left}px`;
14762
14926
  el.style.visibility = "";
14763
14927
  this._syncActive();
14928
+ this._syncColorStrips();
14764
14929
  this._visible = true;
14765
14930
  }
14766
14931
  _hide() {
14767
14932
  if (!this._el) return;
14768
14933
  this._el.style.display = "none";
14769
14934
  this._visible = false;
14935
+ this._closeColorPicker();
14770
14936
  }
14771
14937
  _syncActive() {
14772
14938
  if (!this._el) return;
@@ -14775,10 +14941,30 @@
14775
14941
  btn.classList.toggle("an-active", !!(activeFn && activeFn()));
14776
14942
  });
14777
14943
  }
14944
+ /** Read the current selection's color and update the color-strip indicators. */
14945
+ _syncColorStrips() {
14946
+ if (!this._el) return;
14947
+ const sel = window.getSelection();
14948
+ if (!sel || !sel.rangeCount) return;
14949
+ let node = sel.getRangeAt(0).startContainer;
14950
+ if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;
14951
+ if (!node) return;
14952
+ const cs = window.getComputedStyle(node);
14953
+ const foreBtn = this._el.querySelector("[data-name=\"foreColor\"]");
14954
+ const foreStrip = foreBtn && foreBtn.querySelector(".an-bubble-color-strip");
14955
+ if (foreStrip) foreStrip.style.background = cs.color || "#000000";
14956
+ const hiliteBtn = this._el.querySelector("[data-name=\"hiliteColor\"]");
14957
+ const hiliteStrip = hiliteBtn && hiliteBtn.querySelector(".an-bubble-color-strip");
14958
+ if (hiliteStrip) {
14959
+ const bg = cs.backgroundColor;
14960
+ hiliteStrip.style.background = !bg || bg === "rgba(0, 0, 0, 0)" || bg === "transparent" ? "transparent" : bg;
14961
+ }
14962
+ }
14778
14963
  _onSelectionChange() {
14779
14964
  cancelAnimationFrame(this._rafId);
14780
14965
  this._rafId = requestAnimationFrame(() => {
14781
14966
  if (this._contextMenuOpen) return;
14967
+ if (this._picker && this._picker.style.display !== "none") return;
14782
14968
  const sel = window.getSelection();
14783
14969
  if (!sel || sel.isCollapsed || !sel.rangeCount) {
14784
14970
  this._hide();
@@ -14803,11 +14989,15 @@
14803
14989
  _onMousedown(e) {
14804
14990
  if (!this._visible) return;
14805
14991
  if (this._el && this._el.contains(e.target)) return;
14992
+ if (this._picker && this._picker.contains(e.target)) return;
14806
14993
  if (this.context.layoutInfo.editable.contains(e.target)) return;
14807
14994
  this._hide();
14808
14995
  }
14809
14996
  _onKeydown(e) {
14810
- if (e.key === "Escape" && this._visible) this._hide();
14997
+ if (e.key === "Escape") {
14998
+ if (this._picker && this._picker.style.display !== "none") this._closeColorPicker();
14999
+ else if (this._visible) this._hide();
15000
+ }
14811
15001
  }
14812
15002
  _onContextMenu() {
14813
15003
  this._hide();