overtype 2.1.1 → 2.3.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/src/styles.js CHANGED
@@ -37,7 +37,7 @@ export function generateStyles(options = {}) {
37
37
  ` : '';
38
38
 
39
39
  // Generate theme variables if provided
40
- const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';
40
+ const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors, theme.previewColors) : '';
41
41
 
42
42
  return `
43
43
  /* OverType Editor Styles */
@@ -211,17 +211,36 @@ export function generateStyles(options = {}) {
211
211
  /* Prevent mobile zoom on focus */
212
212
  touch-action: manipulation !important;
213
213
 
214
- /* Disable autofill and spellcheck */
214
+ /* Disable autofill */
215
215
  autocomplete: off !important;
216
216
  autocorrect: off !important;
217
217
  autocapitalize: off !important;
218
- spellcheck: false !important;
219
218
  }
220
219
 
221
220
  .overtype-wrapper .overtype-input::selection {
222
221
  background-color: var(--selection, rgba(244, 211, 94, 0.4));
223
222
  }
224
223
 
224
+ /* Placeholder shim - visible when textarea is empty */
225
+ .overtype-wrapper .overtype-placeholder {
226
+ position: absolute !important;
227
+ top: 0 !important;
228
+ left: 0 !important;
229
+ width: 100% !important;
230
+ z-index: 0 !important;
231
+ pointer-events: none !important;
232
+ user-select: none !important;
233
+ font-family: ${fontFamily} !important;
234
+ font-size: var(--instance-font-size, ${fontSize}) !important;
235
+ line-height: var(--instance-line-height, ${lineHeight}) !important;
236
+ padding: var(--instance-padding, ${padding}) !important;
237
+ box-sizing: border-box !important;
238
+ color: var(--placeholder, #999) !important;
239
+ overflow: hidden !important;
240
+ white-space: nowrap !important;
241
+ text-overflow: ellipsis !important;
242
+ }
243
+
225
244
  /* Preview layer styles */
226
245
  .overtype-wrapper .overtype-preview {
227
246
  /* Layer positioning */
@@ -489,6 +508,10 @@ export function generateStyles(options = {}) {
489
508
 
490
509
 
491
510
  /* Toolbar Styles */
511
+ .overtype-toolbar.overtype-toolbar-hidden {
512
+ display: none !important;
513
+ }
514
+
492
515
  .overtype-toolbar {
493
516
  display: flex !important;
494
517
  align-items: center !important;
@@ -687,27 +710,29 @@ export function generateStyles(options = {}) {
687
710
  }
688
711
 
689
712
  /* Headers - restore proper sizing in preview mode */
690
- .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h1,
691
- .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h2,
713
+ .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h1,
714
+ .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h2,
692
715
  .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h3 {
693
716
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
694
717
  font-weight: 600 !important;
695
718
  margin: 0 !important;
696
719
  display: block !important;
697
- color: inherit !important; /* Use parent text color */
698
- line-height: 1 !important; /* Tight line height for headings */
720
+ line-height: 1 !important;
699
721
  }
700
-
701
- .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h1 {
702
- font-size: 2em !important;
722
+
723
+ .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h1 {
724
+ font-size: 2em !important;
725
+ color: var(--preview-h1, #222) !important;
703
726
  }
704
-
705
- .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h2 {
706
- font-size: 1.5em !important;
727
+
728
+ .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h2 {
729
+ font-size: 1.5em !important;
730
+ color: var(--preview-h2, #333) !important;
707
731
  }
708
-
709
- .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h3 {
710
- font-size: 1.17em !important;
732
+
733
+ .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h3 {
734
+ font-size: 1.17em !important;
735
+ color: var(--preview-h3, #444) !important;
711
736
  }
712
737
 
713
738
  /* Lists - restore list styling in preview mode */
@@ -757,25 +782,20 @@ export function generateStyles(options = {}) {
757
782
  .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview a {
758
783
  pointer-events: auto !important;
759
784
  cursor: pointer !important;
760
- color: var(--link, #0066cc) !important;
785
+ color: var(--preview-link, #0066cc) !important;
761
786
  text-decoration: underline !important;
762
787
  }
763
788
 
764
789
  /* Code blocks - proper pre/code styling in preview mode */
765
790
  .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview pre.code-block {
766
- background: #2d2d2d !important;
767
- color: #f8f8f2 !important;
791
+ background: var(--preview-code-bg, rgba(135, 131, 120, 0.15)) !important;
792
+ color: var(--preview-code, #333) !important;
768
793
  padding: 1.2em !important;
769
794
  border-radius: 3px !important;
770
795
  overflow-x: auto !important;
771
796
  margin: 0 !important;
772
797
  display: block !important;
773
798
  }
774
-
775
- /* Cave theme code block background in preview mode */
776
- .overtype-container[data-theme="cave"][data-mode="preview"] .overtype-wrapper .overtype-preview pre.code-block {
777
- background: #11171F !important;
778
- }
779
799
 
780
800
  .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview pre.code-block code {
781
801
  background: transparent !important;
@@ -798,7 +818,8 @@ export function generateStyles(options = {}) {
798
818
  /* Blockquotes - enhanced styling in preview mode */
799
819
  .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview .blockquote {
800
820
  display: block !important;
801
- border-left: 4px solid var(--blockquote, #ddd) !important;
821
+ border-left: 4px solid var(--preview-blockquote, #666) !important;
822
+ color: var(--preview-blockquote, #666) !important;
802
823
  padding-left: 1em !important;
803
824
  margin: 1em 0 !important;
804
825
  font-style: italic !important;
@@ -809,14 +830,16 @@ export function generateStyles(options = {}) {
809
830
  font-family: Georgia, 'Times New Roman', serif !important;
810
831
  font-size: 16px !important;
811
832
  line-height: 1.8 !important;
812
- color: var(--text, #333) !important; /* Consistent text color */
833
+ color: var(--preview-text, #333) !important;
834
+ background: var(--preview-bg, transparent) !important;
813
835
  }
814
836
 
815
837
  /* Inline code in preview mode - keep monospace */
816
838
  .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview code {
817
839
  font-family: ${fontFamily} !important;
818
840
  font-size: 0.9em !important;
819
- background: rgba(135, 131, 120, 0.15) !important;
841
+ background: var(--preview-code-bg, rgba(135, 131, 120, 0.15)) !important;
842
+ color: var(--preview-code, #333) !important;
820
843
  padding: 0.2em 0.4em !important;
821
844
  border-radius: 3px !important;
822
845
  }
@@ -824,32 +847,33 @@ export function generateStyles(options = {}) {
824
847
  /* Strong and em elements in preview mode */
825
848
  .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview strong {
826
849
  font-weight: 700 !important;
827
- color: inherit !important; /* Use parent text color */
850
+ color: var(--preview-strong, inherit) !important;
828
851
  }
829
852
 
830
853
  .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview em {
831
854
  font-style: italic !important;
832
- color: inherit !important; /* Use parent text color */
855
+ color: var(--preview-em, inherit) !important;
833
856
  }
834
857
 
835
858
  /* HR in preview mode */
836
859
  .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview .hr-marker {
837
860
  display: block !important;
838
- border-top: 2px solid var(--hr, #ddd) !important;
861
+ border-top: 2px solid var(--preview-hr, #ddd) !important;
839
862
  text-indent: -9999px !important;
840
863
  height: 2px !important;
841
864
  }
842
865
 
843
- /* Link Tooltip - Base styles (all browsers) */
866
+ /* Link Tooltip */
844
867
  .overtype-link-tooltip {
845
- /* Visual styles that work for both positioning methods */
846
868
  background: #333 !important;
847
869
  color: white !important;
848
870
  padding: 6px 10px !important;
849
871
  border-radius: 16px !important;
850
872
  font-size: 12px !important;
851
873
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
852
- display: none !important;
874
+ display: flex !important;
875
+ visibility: hidden !important;
876
+ pointer-events: none !important;
853
877
  z-index: 10000 !important;
854
878
  cursor: pointer !important;
855
879
  box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;
@@ -857,25 +881,14 @@ export function generateStyles(options = {}) {
857
881
  white-space: nowrap !important;
858
882
  overflow: hidden !important;
859
883
  text-overflow: ellipsis !important;
860
-
861
- /* Base positioning for Floating UI fallback */
862
- position: absolute;
884
+ position: fixed;
885
+ top: 0;
886
+ left: 0;
863
887
  }
864
888
 
865
889
  .overtype-link-tooltip.visible {
866
- display: flex !important;
867
- }
868
-
869
- /* CSS Anchor Positioning (modern browsers only) */
870
- @supports (position-anchor: --x) and (position-area: center) {
871
- .overtype-link-tooltip {
872
- /* Only anchor positioning specific properties */
873
- position-anchor: var(--target-anchor, --link-0);
874
- position-area: block-end center;
875
- margin-top: 8px !important;
876
- position-try: most-width block-end inline-end, flip-inline, block-start center;
877
- position-visibility: anchors-visible;
878
- }
890
+ visibility: visible !important;
891
+ pointer-events: auto !important;
879
892
  }
880
893
 
881
894
  ${mobileStyles}
package/src/themes.js CHANGED
@@ -39,6 +39,21 @@ export const solar = {
39
39
  toolbarIcon: '#0d3b66', // Yale Blue - icon color
40
40
  toolbarHover: '#f5f5f5', // Light gray - hover background
41
41
  toolbarActive: '#faf0ca', // Lemon Chiffon - active button background
42
+ placeholder: '#999999', // Gray - placeholder text
43
+ },
44
+ previewColors: {
45
+ text: '#1a1a1a',
46
+ h1: '#1a1a1a',
47
+ h2: '#2a2a2a',
48
+ h3: '#3a3a3a',
49
+ strong: 'inherit',
50
+ em: 'inherit',
51
+ link: '#0066cc',
52
+ code: '#1a1a1a',
53
+ codeBg: 'rgba(135, 131, 120, 0.15)',
54
+ blockquote: '#555',
55
+ hr: '#ddd',
56
+ bg: 'transparent',
42
57
  }
43
58
  };
44
59
 
@@ -78,6 +93,21 @@ export const cave = {
78
93
  toolbarIcon: '#c5dde8', // Light blue-gray - icon color
79
94
  toolbarHover: '#243546', // Slightly lighter charcoal - hover background
80
95
  toolbarActive: '#2a3f52', // Even lighter - active button background
96
+ placeholder: '#6a7a88', // Muted blue-gray - placeholder text
97
+ },
98
+ previewColors: {
99
+ text: '#c5dde8',
100
+ h1: '#e0e0e0',
101
+ h2: '#d0d0d0',
102
+ h3: '#c0c0c0',
103
+ strong: 'inherit',
104
+ em: 'inherit',
105
+ link: '#6cb6e0',
106
+ code: '#c5dde8',
107
+ codeBg: 'rgba(255, 255, 255, 0.08)',
108
+ blockquote: '#9aa8b4',
109
+ hr: 'rgba(255, 255, 255, 0.15)',
110
+ bg: 'transparent',
81
111
  }
82
112
  };
83
113
 
@@ -87,6 +117,7 @@ export const cave = {
87
117
  export const themes = {
88
118
  solar,
89
119
  cave,
120
+ auto: solar,
90
121
  // Aliases for backward compatibility
91
122
  light: solar,
92
123
  dark: cave
@@ -106,18 +137,34 @@ export function getTheme(theme) {
106
137
  return theme;
107
138
  }
108
139
 
140
+ /**
141
+ * Resolve auto theme to actual theme based on system color scheme
142
+ * @param {string} themeName - Theme name to resolve
143
+ * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise unchanged)
144
+ */
145
+ export function resolveAutoTheme(themeName) {
146
+ if (themeName !== 'auto') return themeName;
147
+ const mq = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)');
148
+ return mq?.matches ? 'cave' : 'solar';
149
+ }
150
+
109
151
  /**
110
152
  * Apply theme colors to CSS variables
111
153
  * @param {Object} colors - Theme colors object
112
154
  * @returns {string} CSS custom properties string
113
155
  */
114
- export function themeToCSSVars(colors) {
156
+ export function themeToCSSVars(colors, previewColors) {
115
157
  const vars = [];
116
158
  for (const [key, value] of Object.entries(colors)) {
117
- // Convert camelCase to kebab-case
118
159
  const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();
119
160
  vars.push(`--${varName}: ${value};`);
120
161
  }
162
+ if (previewColors) {
163
+ for (const [key, value] of Object.entries(previewColors)) {
164
+ const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();
165
+ vars.push(`--preview-${varName}: ${value};`);
166
+ }
167
+ }
121
168
  return vars.join('\n');
122
169
  }
123
170
 
@@ -127,12 +174,16 @@ export function themeToCSSVars(colors) {
127
174
  * @param {Object} customColors - Custom color overrides
128
175
  * @returns {Object} Merged theme object
129
176
  */
130
- export function mergeTheme(baseTheme, customColors = {}) {
177
+ export function mergeTheme(baseTheme, customColors = {}, customPreviewColors = {}) {
131
178
  return {
132
179
  ...baseTheme,
133
180
  colors: {
134
181
  ...baseTheme.colors,
135
182
  ...customColors
183
+ },
184
+ previewColors: {
185
+ ...baseTheme.previewColors,
186
+ ...customPreviewColors
136
187
  }
137
188
  };
138
189
  }
@@ -142,6 +142,29 @@ export const toolbarButtons = {
142
142
  }
143
143
  },
144
144
 
145
+ upload: {
146
+ name: 'upload',
147
+ actionId: 'uploadFile',
148
+ icon: icons.uploadIcon,
149
+ title: 'Upload File',
150
+ action: ({ editor }) => {
151
+ if (!editor.options.fileUpload?.enabled) return;
152
+ const input = document.createElement('input');
153
+ input.type = 'file';
154
+ input.multiple = true;
155
+ if (editor.options.fileUpload.mimeTypes?.length > 0) {
156
+ input.accept = editor.options.fileUpload.mimeTypes.join(',');
157
+ }
158
+ input.onchange = () => {
159
+ if (!input.files?.length) return;
160
+ const dt = new DataTransfer();
161
+ for (const f of input.files) dt.items.add(f);
162
+ editor._handleDataTransfer(dt);
163
+ };
164
+ input.click();
165
+ }
166
+ },
167
+
145
168
  viewMode: {
146
169
  name: 'viewMode',
147
170
  icon: icons.eyeIcon,
package/src/toolbar.js CHANGED
@@ -287,6 +287,18 @@ export class Toolbar {
287
287
  }
288
288
  }
289
289
 
290
+ show() {
291
+ if (this.container) {
292
+ this.container.classList.remove('overtype-toolbar-hidden');
293
+ }
294
+ }
295
+
296
+ hide() {
297
+ if (this.container) {
298
+ this.container.classList.add('overtype-toolbar-hidden');
299
+ }
300
+ }
301
+
290
302
  /**
291
303
  * Destroy toolbar and cleanup
292
304
  */