autumnnote 1.4.2 → 1.6.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 +102 -21
- package/dist/autumnnote.css +324 -2
- package/dist/autumnnote.es.js +700 -228
- package/dist/autumnnote.es.js.map +1 -1
- package/dist/autumnnote.umd.js +691 -235
- package/dist/autumnnote.umd.js.map +1 -1
- package/package.json +8 -1
- package/src/js/Context.js +8 -3
- package/src/js/core/detectLang.js +98 -0
- package/src/js/core/dom.js +62 -6
- package/src/js/core/markdown.js +14 -13
- package/src/js/core/range.js +2 -2
- package/src/js/editing/History.js +6 -6
- package/src/js/editing/Style.js +19 -19
- package/src/js/editing/Table.js +4 -6
- package/src/js/editing/Typing.js +6 -6
- package/src/js/i18n/en.js +2 -0
- package/src/js/i18n/vi.js +2 -0
- package/src/js/index.js +4 -3
- package/src/js/module/BubbleToolbar.js +30 -13
- package/src/js/module/Buttons.js +16 -14
- package/src/js/module/Clipboard.js +5 -5
- package/src/js/module/CodeTooltip.js +42 -16
- package/src/js/module/Codeview.js +2 -2
- package/src/js/module/ContextMenu.js +12 -12
- package/src/js/module/Editor.js +64 -12
- package/src/js/module/EmojiDialog.js +19 -13
- package/src/js/module/FindReplace.js +85 -59
- package/src/js/module/Fullscreen.js +1 -1
- package/src/js/module/IconDialog.js +26 -20
- package/src/js/module/ImageCropOverlay.js +6 -6
- package/src/js/module/ImageDialog.js +18 -12
- package/src/js/module/ImageResizer.js +1 -1
- package/src/js/module/ImageTooltip.js +8 -4
- package/src/js/module/LinkDialog.js +18 -12
- package/src/js/module/LinkTooltip.js +5 -2
- package/src/js/module/Mention.js +3 -3
- package/src/js/module/Statusbar.js +2 -2
- package/src/js/module/TableTooltip.js +180 -18
- package/src/js/module/Toolbar.js +16 -15
- package/src/js/module/VideoDialog.js +8 -2
- package/src/js/module/VideoResizer.js +3 -3
- package/src/js/module/VideoTooltip.js +11 -6
- package/src/js/renderer.js +4 -2
- package/src/js/settings.js +53 -36
- package/src/styles/autumnnote.scss +332 -4
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* • Direct video URLs → <video> element (.mp4 / .webm / .ogg)
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { createElement, on, trapFocus } from '../core/dom.js';
|
|
10
|
+
import { createElement, on, trapFocus, makeDraggable } from '../core/dom.js';
|
|
11
11
|
import { withSavedRange } from '../core/range.js';
|
|
12
12
|
|
|
13
13
|
export class VideoDialog {
|
|
@@ -68,8 +68,13 @@ export class VideoDialog {
|
|
|
68
68
|
});
|
|
69
69
|
const box = createElement('div', { class: 'an-dialog-box' });
|
|
70
70
|
|
|
71
|
+
const header = createElement('div', { class: 'an-dialog-header' });
|
|
72
|
+
const iconEl = createElement('span', { class: 'an-dialog-icon' });
|
|
73
|
+
iconEl.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="23 7 16 12 23 17 23 7"/><rect x="1" y="5" width="15" height="14" rx="2"/></svg>`;
|
|
71
74
|
const title = createElement('h3', { class: 'an-dialog-title' });
|
|
72
75
|
title.textContent = L.title;
|
|
76
|
+
header.appendChild(iconEl);
|
|
77
|
+
header.appendChild(title);
|
|
73
78
|
|
|
74
79
|
// URL input
|
|
75
80
|
const urlLabel = createElement('label', { class: 'an-label' });
|
|
@@ -108,8 +113,9 @@ export class VideoDialog {
|
|
|
108
113
|
btnRow.appendChild(insertBtn);
|
|
109
114
|
btnRow.appendChild(cancelBtn);
|
|
110
115
|
|
|
111
|
-
box.append(
|
|
116
|
+
box.append(header, urlLabel, urlInput, hintEl, widthLabel, widthInput, btnRow);
|
|
112
117
|
overlay.appendChild(box);
|
|
118
|
+
makeDraggable(header, box);
|
|
113
119
|
|
|
114
120
|
// Live URL hint
|
|
115
121
|
const d0 = on(urlInput, 'input', () => {
|
|
@@ -111,10 +111,10 @@ export class VideoResizer {
|
|
|
111
111
|
_findWrapper(el) {
|
|
112
112
|
if (!el || !(el instanceof Element)) return null;
|
|
113
113
|
// Direct hit on wrapper
|
|
114
|
-
if (el.classList && el.classList.contains('an-video-wrapper')) return el;
|
|
114
|
+
if (el.classList && el.classList.contains('an-video-wrapper')) return /** @type {HTMLElement} */ (el);
|
|
115
115
|
// Child element (iframe, video, or nested)
|
|
116
116
|
const w = el.closest('.an-video-wrapper');
|
|
117
|
-
if (w) return w;
|
|
117
|
+
if (w) return /** @type {HTMLElement} */ (w);
|
|
118
118
|
return null;
|
|
119
119
|
}
|
|
120
120
|
|
|
@@ -200,7 +200,7 @@ export class VideoResizer {
|
|
|
200
200
|
const wrapper = this._activeWrapper;
|
|
201
201
|
if (!wrapper) return;
|
|
202
202
|
|
|
203
|
-
const embed = wrapper.querySelector('iframe, video');
|
|
203
|
+
const embed = /** @type {HTMLElement|null} */ (wrapper.querySelector('iframe, video'));
|
|
204
204
|
const startX = e.clientX;
|
|
205
205
|
const startY = e.clientY;
|
|
206
206
|
const startW = wrapper.offsetWidth || 560;
|
|
@@ -39,26 +39,31 @@ export class VideoTooltip {
|
|
|
39
39
|
on(editable, 'mouseover', (e) => {
|
|
40
40
|
if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;
|
|
41
41
|
// The shield div sits on top of iframes — we detect hover via it or the wrapper
|
|
42
|
-
const
|
|
42
|
+
const target = /** @type {Element} */ (e.target);
|
|
43
|
+
const wrapper = target && target.closest ? target.closest('.an-video-wrapper') : null;
|
|
43
44
|
if (wrapper && editable.contains(wrapper)) {
|
|
44
45
|
this._scheduleShow(wrapper);
|
|
45
46
|
}
|
|
46
47
|
}, { passive: true }),
|
|
47
48
|
on(editable, 'mouseout', (e) => {
|
|
48
|
-
const to = e.relatedTarget;
|
|
49
|
-
if (!to || (!editable.contains(to) && !this._el.contains(to))) {
|
|
49
|
+
const to = /** @type {MouseEvent} */ (e).relatedTarget;
|
|
50
|
+
if (!to || (!editable.contains(/** @type {Node} */ (to)) && !this._el.contains(/** @type {Node} */ (to)))) {
|
|
50
51
|
this._scheduleHide();
|
|
51
52
|
}
|
|
52
53
|
}, { passive: true }),
|
|
53
54
|
on(document, 'click', (e) => {
|
|
55
|
+
const target = /** @type {Node} */ (e.target);
|
|
54
56
|
if (
|
|
55
57
|
this._activeWrapper &&
|
|
56
|
-
!this._activeWrapper.contains(
|
|
57
|
-
!this._el.contains(
|
|
58
|
+
!this._activeWrapper.contains(target) &&
|
|
59
|
+
!this._el.contains(target)
|
|
58
60
|
) {
|
|
59
61
|
this._hide();
|
|
60
62
|
}
|
|
61
63
|
}),
|
|
64
|
+
// Hide when the page scrolls or resizes — the tooltip position becomes stale
|
|
65
|
+
on(window, 'scroll', () => this._hide(), { passive: true }),
|
|
66
|
+
on(window, 'resize', () => this._hide(), { passive: true }),
|
|
62
67
|
);
|
|
63
68
|
|
|
64
69
|
return this;
|
|
@@ -174,7 +179,7 @@ export class VideoTooltip {
|
|
|
174
179
|
this._hideTimer = setTimeout(() => this._hide(), HIDE_DELAY);
|
|
175
180
|
}
|
|
176
181
|
|
|
177
|
-
_show(
|
|
182
|
+
_show(_wrapper) {
|
|
178
183
|
this._el.style.display = 'flex';
|
|
179
184
|
// Defer: offsetWidth on a newly-visible element forces synchronous layout
|
|
180
185
|
requestAnimationFrame(() => {
|
package/src/js/renderer.js
CHANGED
|
@@ -40,7 +40,7 @@ export function renderLayout(targetEl, options) {
|
|
|
40
40
|
}
|
|
41
41
|
if (!initialContent) {
|
|
42
42
|
initialContent = targetEl.tagName === 'TEXTAREA'
|
|
43
|
-
? (targetEl.value || '').trim()
|
|
43
|
+
? ((/** @type {HTMLTextAreaElement} */ (targetEl)).value || '').trim()
|
|
44
44
|
: (targetEl.innerHTML || '').trim();
|
|
45
45
|
}
|
|
46
46
|
editable.innerHTML = sanitiseHTML(initialContent, { allowIframes: true });
|
|
@@ -70,9 +70,11 @@ export function renderLayout(targetEl, options) {
|
|
|
70
70
|
|
|
71
71
|
container.appendChild(editable);
|
|
72
72
|
|
|
73
|
-
// Apply dark theme
|
|
73
|
+
// Apply dark theme — also add to body so floating elements (dialogs, tooltips,
|
|
74
|
+
// popovers) appended to document.body inherit the dark CSS rules.
|
|
74
75
|
if (options.theme === 'dark') {
|
|
75
76
|
container.classList.add('an-theme-dark');
|
|
77
|
+
document.body.classList.add('an-theme-dark');
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
// Read-only mode
|
package/src/js/settings.js
CHANGED
|
@@ -7,48 +7,65 @@ import { defaultToolbar } from './module/Buttons.js';
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @typedef {object} AsnOptions
|
|
10
|
-
* @property {string} [placeholder]
|
|
11
|
-
* @property {number} [height]
|
|
12
|
-
* @property {number} [minHeight]
|
|
13
|
-
* @property {number} [maxHeight]
|
|
14
|
-
* @property {boolean} [focus]
|
|
15
|
-
* @property {boolean} [resizable]
|
|
16
|
-
* @property {Array} [toolbar]
|
|
17
|
-
* @property {boolean} [
|
|
18
|
-
* @property {
|
|
10
|
+
* @property {string} [placeholder] - Placeholder text when editor is empty
|
|
11
|
+
* @property {number} [height] - Editor height in px (min)
|
|
12
|
+
* @property {number} [minHeight] - Minimum height in px
|
|
13
|
+
* @property {number} [maxHeight] - Maximum height in px (0 = unlimited)
|
|
14
|
+
* @property {boolean} [focus] - Auto-focus on init
|
|
15
|
+
* @property {boolean} [resizable] - Show resize handle
|
|
16
|
+
* @property {Array} [toolbar] - Toolbar button group config
|
|
17
|
+
* @property {boolean} [useBootstrap] - Use Bootstrap button classes on toolbar buttons
|
|
18
|
+
* @property {string} [toolbarButtonClass] - CSS classes for Bootstrap toolbar buttons
|
|
19
|
+
* @property {boolean} [useFontAwesome] - Use Font Awesome icons (default: true)
|
|
20
|
+
* @property {string} [fontAwesomeClass] - Font Awesome prefix class, e.g. 'fas' or 'fa-solid'
|
|
21
|
+
* @property {boolean} [pasteAsPlainText] - Force plain-text paste
|
|
22
|
+
* @property {boolean} [pasteCleanHTML] - Sanitise HTML on paste
|
|
19
23
|
* @property {boolean} [pasteStripAttributes] - Strip class/style/data-* from pasted HTML (default: false)
|
|
20
|
-
* @property {boolean} [allowImageUpload]
|
|
21
|
-
* @property {number} [maxImageSize]
|
|
22
|
-
* @property {number} [tabSize]
|
|
23
|
-
* @property {
|
|
24
|
-
* @property {
|
|
25
|
-
* @property {
|
|
26
|
-
* @property {
|
|
27
|
-
* @property {
|
|
28
|
-
* @property {
|
|
29
|
-
* @property {
|
|
30
|
-
* @property {
|
|
31
|
-
* @property {
|
|
32
|
-
* @property {
|
|
33
|
-
* @property {boolean} [
|
|
34
|
-
* @property {
|
|
35
|
-
* @property {string} [
|
|
36
|
-
* @property {
|
|
37
|
-
* @property {
|
|
38
|
-
* @property {
|
|
39
|
-
* @property {
|
|
40
|
-
* @property {
|
|
41
|
-
* @property {
|
|
42
|
-
* @property {
|
|
43
|
-
* @property {
|
|
44
|
-
* @property {string
|
|
24
|
+
* @property {boolean} [allowImageUpload] - Allow file upload in image dialog
|
|
25
|
+
* @property {number} [maxImageSize] - Max upload size in MB
|
|
26
|
+
* @property {number} [tabSize] - Spaces per tab in non-list context
|
|
27
|
+
* @property {number} [historyLimit] - Maximum undo/redo history steps
|
|
28
|
+
* @property {string} [defaultFontFamily] - Default font family applied to the editable area on init
|
|
29
|
+
* @property {string} [defaultFontSize] - Default font size applied to the editable area on init (e.g. '14px')
|
|
30
|
+
* @property {string[]} [fontFamilies] - Font families shown in the font-family toolbar dropdown
|
|
31
|
+
* @property {Function} [onChange] - Callback on content change
|
|
32
|
+
* @property {Function} [onFocus] - Callback on focus
|
|
33
|
+
* @property {Function} [onBlur] - Callback on blur
|
|
34
|
+
* @property {Function} [onInit] - Callback after the editor has initialised
|
|
35
|
+
* @property {Function} [onImageUpload] - Custom upload handler: (files) => void
|
|
36
|
+
* @property {Function} [onImageError] - Callback when an image upload error occurs
|
|
37
|
+
* @property {boolean} [stickyToolbar] - Stick the toolbar to the viewport top when scrolling
|
|
38
|
+
* @property {number} [stickyToolbarOffset] - Top offset in px for sticky toolbar (e.g. fixed nav height)
|
|
39
|
+
* @property {string} [theme] - 'light' (default) | 'dark'
|
|
40
|
+
* @property {boolean} [codeHighlight] - Auto-load Prism.js for syntax highlighting of code blocks
|
|
41
|
+
* @property {string} [codeHighlightCDN] - CDN base URL for Prism assets (defaults to cdnjs)
|
|
42
|
+
* @property {boolean} [markdownPaste] - Convert pasted Markdown text to HTML (default: true)
|
|
43
|
+
* @property {boolean} [readOnly] - Start editor in read-only / non-editable mode
|
|
44
|
+
* @property {boolean} [spellcheck] - Enable browser spellcheck in the editable area (default: true)
|
|
45
|
+
* @property {string} [direction] - Text direction: 'ltr' (default) | 'rtl'
|
|
46
|
+
* @property {string} [toolbarOverflow] - Toolbar overflow strategy: 'wrap' (default) | 'scroll'
|
|
47
|
+
* @property {boolean} [autoSave] - Auto-save content to localStorage on change
|
|
48
|
+
* @property {string} [autoSaveKey] - localStorage key used for auto-save (default: 'autumnnote-autosave')
|
|
49
|
+
* @property {number} [maxChars] - Maximum character count (0 = unlimited). Shows warning in statusbar.
|
|
50
|
+
* @property {number} [maxWords] - Maximum word count (0 = unlimited). Shows warning in statusbar.
|
|
51
|
+
* @property {boolean} [tableHeaderRow] - Insert a header row (<thead><th>) when creating tables
|
|
52
|
+
* @property {Function} [onPaste] - Callback fired on every paste: ({ text, html }) => void
|
|
53
|
+
* @property {Function} [onSelectionChange] - Callback fired on cursor/selection change: (context) => void
|
|
54
|
+
* @property {string[]} [colorSwatches] - Custom brand colour swatches prepended to the colour-picker palette
|
|
45
55
|
* @property {Function} [onDestroy] - Callback fired when the editor is destroyed: (context) => void
|
|
46
56
|
* @property {Function} [onCharLimitReached] - Callback fired when the character limit is hit: (context) => void
|
|
47
57
|
* @property {Function} [onWordLimitReached] - Callback fired when the word limit is hit: (context) => void
|
|
48
|
-
* @property {string} [focusColor]
|
|
58
|
+
* @property {string} [focusColor] - Custom focus ring colour, e.g. '#f97316'. Overrides the default blue.
|
|
59
|
+
* @property {boolean} [autoSaveRestore] - Show a restore banner when a previously auto-saved draft exists
|
|
60
|
+
* @property {number} [autoSaveRestoreTimeout] - Maximum age in days for a draft to be offered for restore (0 = no expiry)
|
|
61
|
+
* @property {Function} [onAutoSaveRestore] - Callback fired after the user chooses to restore a draft
|
|
62
|
+
* @property {boolean} [markdownShortcuts] - Convert markdown syntax typed inline to HTML
|
|
63
|
+
* @property {boolean} [bubbleToolbar] - Show a mini floating toolbar above text selections
|
|
64
|
+
* @property {string[]} [bubbleToolbarItems] - Button names for the bubble toolbar
|
|
65
|
+
* @property {object|null} [mention] - @mention configuration (onSearch, minChars, ...)
|
|
66
|
+
* @property {string} [lang] - Display language or partial locale object override
|
|
49
67
|
*/
|
|
50
68
|
|
|
51
|
-
/** @type {AsnOptions} */
|
|
52
69
|
export const defaultOptions = {
|
|
53
70
|
placeholder: '',
|
|
54
71
|
height: 200,
|
|
@@ -652,6 +652,31 @@
|
|
|
652
652
|
letter-spacing: 0.02em;
|
|
653
653
|
}
|
|
654
654
|
|
|
655
|
+
// Color-strip variant for the cell shade button (mirrors .an-bubble-btn--color)
|
|
656
|
+
.an-link-tooltip-btn--shade {
|
|
657
|
+
flex-direction: column;
|
|
658
|
+
gap: 1px;
|
|
659
|
+
padding: 4px 0 3px;
|
|
660
|
+
height: auto;
|
|
661
|
+
|
|
662
|
+
.an-bubble-btn-svg {
|
|
663
|
+
display: flex;
|
|
664
|
+
align-items: center;
|
|
665
|
+
justify-content: center;
|
|
666
|
+
line-height: 0;
|
|
667
|
+
svg { display: block; }
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
.an-link-tooltip-color-strip {
|
|
671
|
+
display: block;
|
|
672
|
+
width: 13px;
|
|
673
|
+
height: 3px;
|
|
674
|
+
border-radius: 1px;
|
|
675
|
+
pointer-events: none;
|
|
676
|
+
background: transparent;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
655
680
|
// Active state for toggle buttons in tooltips (e.g. Select Cells)
|
|
656
681
|
.an-link-tooltip-btn--active {
|
|
657
682
|
background: rgba(#3b82f6, 0.12) !important;
|
|
@@ -726,6 +751,58 @@
|
|
|
726
751
|
}
|
|
727
752
|
}
|
|
728
753
|
|
|
754
|
+
// =============================================================================
|
|
755
|
+
// Cell shade popover
|
|
756
|
+
|
|
757
|
+
.an-cell-shade-popover {
|
|
758
|
+
position: fixed;
|
|
759
|
+
z-index: 1200;
|
|
760
|
+
background: $an-bg;
|
|
761
|
+
border: 1px solid $an-border;
|
|
762
|
+
border-radius: 8px;
|
|
763
|
+
padding: 10px 10px 6px;
|
|
764
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
765
|
+
min-width: 166px;
|
|
766
|
+
|
|
767
|
+
.an-size-popover-title {
|
|
768
|
+
font-size: 11px;
|
|
769
|
+
font-weight: 600;
|
|
770
|
+
color: $an-muted;
|
|
771
|
+
text-transform: uppercase;
|
|
772
|
+
letter-spacing: 0.5px;
|
|
773
|
+
margin-bottom: 8px;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
.an-shade-no-color {
|
|
777
|
+
display: inline-flex;
|
|
778
|
+
align-items: center;
|
|
779
|
+
gap: 4px;
|
|
780
|
+
padding: 3px 8px;
|
|
781
|
+
font-size: 12px;
|
|
782
|
+
color: $an-muted;
|
|
783
|
+
background: transparent;
|
|
784
|
+
border: 1px solid $an-border;
|
|
785
|
+
border-radius: $an-radius-sm;
|
|
786
|
+
cursor: pointer;
|
|
787
|
+
font-family: inherit;
|
|
788
|
+
|
|
789
|
+
&:hover {
|
|
790
|
+
background: $an-bg-btn-hover;
|
|
791
|
+
color: $an-text;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
.an-shade-color-input {
|
|
796
|
+
width: 24px;
|
|
797
|
+
height: 24px;
|
|
798
|
+
padding: 0;
|
|
799
|
+
border: 1px solid $an-border;
|
|
800
|
+
border-radius: $an-radius-sm;
|
|
801
|
+
cursor: pointer;
|
|
802
|
+
background: transparent;
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
|
|
729
806
|
// =============================================================================
|
|
730
807
|
// Codeview textarea
|
|
731
808
|
// =============================================================================
|
|
@@ -819,8 +896,29 @@
|
|
|
819
896
|
gap: 10px;
|
|
820
897
|
}
|
|
821
898
|
|
|
899
|
+
.an-dialog-header {
|
|
900
|
+
display: flex;
|
|
901
|
+
align-items: center;
|
|
902
|
+
gap: 12px;
|
|
903
|
+
margin-bottom: 4px;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
.an-dialog-icon {
|
|
907
|
+
display: flex;
|
|
908
|
+
align-items: center;
|
|
909
|
+
justify-content: center;
|
|
910
|
+
width: 38px;
|
|
911
|
+
height: 38px;
|
|
912
|
+
flex-shrink: 0;
|
|
913
|
+
border-radius: 10px;
|
|
914
|
+
background: rgba($an-primary, 0.1);
|
|
915
|
+
color: $an-primary;
|
|
916
|
+
|
|
917
|
+
svg { display: block; stroke: currentColor; }
|
|
918
|
+
}
|
|
919
|
+
|
|
822
920
|
.an-dialog-title {
|
|
823
|
-
margin: 0
|
|
921
|
+
margin: 0;
|
|
824
922
|
font-size: 16px;
|
|
825
923
|
font-weight: 600;
|
|
826
924
|
color: $an-text;
|
|
@@ -871,6 +969,114 @@
|
|
|
871
969
|
}
|
|
872
970
|
}
|
|
873
971
|
|
|
972
|
+
// =============================================================================
|
|
973
|
+
// Find & Replace — floating panel
|
|
974
|
+
// =============================================================================
|
|
975
|
+
|
|
976
|
+
.an-fr-dialog {
|
|
977
|
+
// Override centered-modal defaults: floating panel, no backdrop
|
|
978
|
+
background: transparent;
|
|
979
|
+
pointer-events: none;
|
|
980
|
+
align-items: flex-start;
|
|
981
|
+
justify-content: flex-end;
|
|
982
|
+
padding: 56px 16px 0 0;
|
|
983
|
+
|
|
984
|
+
.an-fr-box {
|
|
985
|
+
pointer-events: auto;
|
|
986
|
+
width: 360px;
|
|
987
|
+
padding: 14px 16px 16px;
|
|
988
|
+
gap: 8px;
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
.an-fr-header {
|
|
993
|
+
display: flex;
|
|
994
|
+
align-items: center;
|
|
995
|
+
justify-content: space-between;
|
|
996
|
+
margin-bottom: 2px;
|
|
997
|
+
|
|
998
|
+
.an-dialog-title { margin: 0; font-size: 14px; }
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
// Compact search bar: input + toggle buttons + counter in one row
|
|
1002
|
+
.an-fr-search-bar {
|
|
1003
|
+
display: flex;
|
|
1004
|
+
align-items: center;
|
|
1005
|
+
gap: 4px;
|
|
1006
|
+
|
|
1007
|
+
.an-fr-input {
|
|
1008
|
+
flex: 1;
|
|
1009
|
+
min-width: 0;
|
|
1010
|
+
padding: 6px 8px;
|
|
1011
|
+
font-size: 13px;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
// Replace row
|
|
1016
|
+
.an-fr-replace-row {
|
|
1017
|
+
display: flex;
|
|
1018
|
+
align-items: center;
|
|
1019
|
+
gap: 6px;
|
|
1020
|
+
|
|
1021
|
+
.an-fr-input {
|
|
1022
|
+
flex: 1;
|
|
1023
|
+
min-width: 0;
|
|
1024
|
+
padding: 6px 8px;
|
|
1025
|
+
font-size: 13px;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
.an-fr-replace-btn {
|
|
1029
|
+
flex-shrink: 0;
|
|
1030
|
+
padding: 5px 10px;
|
|
1031
|
+
font-size: 12px;
|
|
1032
|
+
white-space: nowrap;
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
// Icon buttons (Aa, ↑, ↓)
|
|
1037
|
+
.an-fr-icon-btn {
|
|
1038
|
+
display: flex;
|
|
1039
|
+
align-items: center;
|
|
1040
|
+
justify-content: center;
|
|
1041
|
+
flex-shrink: 0;
|
|
1042
|
+
width: 28px;
|
|
1043
|
+
height: 28px;
|
|
1044
|
+
padding: 0;
|
|
1045
|
+
font-size: 12px;
|
|
1046
|
+
font-weight: 600;
|
|
1047
|
+
font-family: inherit;
|
|
1048
|
+
border: 1px solid transparent;
|
|
1049
|
+
border-radius: $an-radius-sm;
|
|
1050
|
+
background: transparent;
|
|
1051
|
+
color: $an-muted;
|
|
1052
|
+
cursor: pointer;
|
|
1053
|
+
|
|
1054
|
+
svg { display: block; stroke: currentColor; }
|
|
1055
|
+
|
|
1056
|
+
&:hover {
|
|
1057
|
+
background: $an-bg-btn-hover;
|
|
1058
|
+
color: $an-text;
|
|
1059
|
+
border-color: $an-border;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
&.an-fr-icon-btn--active {
|
|
1063
|
+
background: rgba($an-primary, 0.1);
|
|
1064
|
+
color: $an-primary;
|
|
1065
|
+
border-color: rgba($an-primary, 0.3);
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
.an-fr-counter {
|
|
1070
|
+
font-size: 11px;
|
|
1071
|
+
color: $an-muted;
|
|
1072
|
+
white-space: nowrap;
|
|
1073
|
+
min-width: 36px;
|
|
1074
|
+
text-align: right;
|
|
1075
|
+
flex-shrink: 0;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
// =============================================================================
|
|
1079
|
+
|
|
874
1080
|
.an-input {
|
|
875
1081
|
width: 100%;
|
|
876
1082
|
padding: 7px 10px;
|
|
@@ -1242,6 +1448,28 @@ $an-video-accent: #8b5cf6; // violet-500
|
|
|
1242
1448
|
}
|
|
1243
1449
|
}
|
|
1244
1450
|
|
|
1451
|
+
// Icon + title grouped together (used in emoji/icon/find dialogs)
|
|
1452
|
+
.an-dialog-title-group {
|
|
1453
|
+
display: flex;
|
|
1454
|
+
align-items: center;
|
|
1455
|
+
gap: 10px;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
// Small icon variant for dialogs with title-row layout
|
|
1459
|
+
.an-dialog-icon--sm {
|
|
1460
|
+
width: 32px;
|
|
1461
|
+
height: 32px;
|
|
1462
|
+
border-radius: 8px;
|
|
1463
|
+
background: rgba($an-primary, 0.1);
|
|
1464
|
+
color: $an-primary;
|
|
1465
|
+
display: flex;
|
|
1466
|
+
align-items: center;
|
|
1467
|
+
justify-content: center;
|
|
1468
|
+
flex-shrink: 0;
|
|
1469
|
+
|
|
1470
|
+
svg { display: block; stroke: currentColor; }
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1245
1473
|
.an-icon-close {
|
|
1246
1474
|
display: flex;
|
|
1247
1475
|
align-items: center;
|
|
@@ -1759,6 +1987,20 @@ $an-video-accent: #8b5cf6; // violet-500
|
|
|
1759
1987
|
|
|
1760
1988
|
.an-dialog-title { color: #cdd6f4; }
|
|
1761
1989
|
|
|
1990
|
+
.an-dialog-icon,
|
|
1991
|
+
.an-dialog-icon--sm {
|
|
1992
|
+
background: rgba(#818cf8, 0.15);
|
|
1993
|
+
color: #818cf8;
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
.an-fr-icon-btn {
|
|
1997
|
+
color: #a6adc8;
|
|
1998
|
+
&:hover { background: #313244; color: #cdd6f4; border-color: #45475a; }
|
|
1999
|
+
&.an-fr-icon-btn--active { background: rgba(#818cf8, 0.15); color: #818cf8; border-color: rgba(#818cf8, 0.3); }
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
.an-fr-counter { color: #6c7086; }
|
|
2003
|
+
|
|
1762
2004
|
.an-label { color: #cdd6f4; }
|
|
1763
2005
|
|
|
1764
2006
|
.an-input {
|
|
@@ -1794,12 +2036,23 @@ $an-video-accent: #8b5cf6; // violet-500
|
|
|
1794
2036
|
|
|
1795
2037
|
.an-color-popup,
|
|
1796
2038
|
.an-table-picker-popup,
|
|
1797
|
-
.an-size-popover
|
|
2039
|
+
.an-size-popover,
|
|
2040
|
+
.an-cell-shade-popover {
|
|
1798
2041
|
background: #24273a;
|
|
1799
2042
|
border-color: #3f3f5f;
|
|
1800
2043
|
color: #cdd6f4;
|
|
1801
2044
|
}
|
|
1802
2045
|
|
|
2046
|
+
.an-cell-shade-popover .an-shade-no-color {
|
|
2047
|
+
border-color: #3f3f5f;
|
|
2048
|
+
color: #a6adc8;
|
|
2049
|
+
|
|
2050
|
+
&:hover {
|
|
2051
|
+
background: #313244;
|
|
2052
|
+
color: #cdd6f4;
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
|
|
1803
2056
|
.an-link-tooltip-btn--active {
|
|
1804
2057
|
background: rgba(#6366f1, 0.2) !important;
|
|
1805
2058
|
color: #818cf8 !important;
|
|
@@ -1821,6 +2074,17 @@ $an-video-accent: #8b5cf6; // violet-500
|
|
|
1821
2074
|
}
|
|
1822
2075
|
}
|
|
1823
2076
|
|
|
2077
|
+
// Color popup children
|
|
2078
|
+
.an-color-custom {
|
|
2079
|
+
border-top-color: #3f3f5f;
|
|
2080
|
+
color: #cdd6f4;
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
.an-color-arrow:hover { border-left-color: #45475a; }
|
|
2084
|
+
|
|
2085
|
+
.an-table-label { color: #6c7086; }
|
|
2086
|
+
.an-context-table-grid-panel { border-top-color: #3f3f5f; }
|
|
2087
|
+
|
|
1824
2088
|
.an-context-item { color: #cdd6f4; }
|
|
1825
2089
|
.an-context-sep { background: #3f3f5f; }
|
|
1826
2090
|
|
|
@@ -1857,9 +2121,18 @@ $an-video-accent: #8b5cf6; // violet-500
|
|
|
1857
2121
|
}
|
|
1858
2122
|
|
|
1859
2123
|
.an-icon-cell {
|
|
1860
|
-
color: #
|
|
2124
|
+
color: #a6adc8;
|
|
2125
|
+
|
|
2126
|
+
i { color: #cdd6f4; }
|
|
2127
|
+
|
|
2128
|
+
&:hover { background: #2a2a3e; border-color: #45475a; }
|
|
1861
2129
|
|
|
1862
|
-
|
|
2130
|
+
&.active {
|
|
2131
|
+
background: rgba(#818cf8, 0.15);
|
|
2132
|
+
border-color: #818cf8;
|
|
2133
|
+
color: #818cf8;
|
|
2134
|
+
i { color: #818cf8; }
|
|
2135
|
+
}
|
|
1863
2136
|
}
|
|
1864
2137
|
|
|
1865
2138
|
.an-icon-close {
|
|
@@ -1870,6 +2143,61 @@ $an-video-accent: #8b5cf6; // violet-500
|
|
|
1870
2143
|
color: #cdd6f4;
|
|
1871
2144
|
}
|
|
1872
2145
|
}
|
|
2146
|
+
|
|
2147
|
+
// Emoji dialog
|
|
2148
|
+
.an-emoji-box { background: #1e1e2e; border-color: #45475a; }
|
|
2149
|
+
|
|
2150
|
+
.an-emoji-cell {
|
|
2151
|
+
color: inherit;
|
|
2152
|
+
&:hover { background: #313244; }
|
|
2153
|
+
}
|
|
2154
|
+
|
|
2155
|
+
.an-emoji-grid {
|
|
2156
|
+
scrollbar-color: #45475a transparent;
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
// Icon dialog
|
|
2160
|
+
.an-icon-box { background: #1e1e2e; border-color: #45475a; }
|
|
2161
|
+
|
|
2162
|
+
.an-icon-grid { background: #181825; border-color: #45475a; }
|
|
2163
|
+
|
|
2164
|
+
.an-icon-options {
|
|
2165
|
+
background: #181825;
|
|
2166
|
+
border-color: #45475a;
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
.an-icon-preview {
|
|
2170
|
+
background: #181825;
|
|
2171
|
+
border-color: #45475a;
|
|
2172
|
+
color: #cdd6f4;
|
|
2173
|
+
|
|
2174
|
+
.an-icon-preview-empty { color: #6c7086; }
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
.an-icon-option-select {
|
|
2178
|
+
background: #313244;
|
|
2179
|
+
border-color: #45475a;
|
|
2180
|
+
color: #cdd6f4;
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
.an-icon-empty { color: #6c7086; }
|
|
2184
|
+
|
|
2185
|
+
// Bubble toolbar color picker
|
|
2186
|
+
.an-bubble-color-picker {
|
|
2187
|
+
background: #24273a;
|
|
2188
|
+
border-color: #3f3f5f;
|
|
2189
|
+
|
|
2190
|
+
.an-context-color-custom {
|
|
2191
|
+
border-color: #3f3f5f;
|
|
2192
|
+
color: #a6adc8;
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2196
|
+
// Table tooltip (extends link-tooltip dark rules)
|
|
2197
|
+
.an-table-tooltip { background: #24273a; border-color: #3f3f5f; }
|
|
2198
|
+
|
|
2199
|
+
// Find & Replace floating panel box
|
|
2200
|
+
.an-fr-box { background: #1e1e2e; border-color: #45475a; }
|
|
1873
2201
|
}
|
|
1874
2202
|
|
|
1875
2203
|
|