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