@meenainwal/rich-text-editor 1.0.8 → 1.0.9

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.
Files changed (45) hide show
  1. package/ReadME.md +28 -44
  2. package/dist/core/Editor.d.ts +133 -0
  3. package/dist/core/HistoryManager.d.ts +30 -0
  4. package/dist/core/ImageManager.d.ts +19 -0
  5. package/dist/core/SelectionManager.d.ts +31 -0
  6. package/dist/index.d.ts +11 -0
  7. package/dist/rich-text-editor.css +1 -1
  8. package/dist/style.d.ts +4 -0
  9. package/dist/test-editor.cjs +2 -2
  10. package/dist/test-editor.mjs +535 -232
  11. package/dist/ui/Toolbar.d.ts +19 -0
  12. package/dist/ui/toolbar/EmojiList.d.ts +6 -0
  13. package/dist/ui/toolbar/EmojiPicker.d.ts +19 -0
  14. package/dist/ui/toolbar/ToolbarItem.d.ts +16 -0
  15. package/dist/ui/toolbar/items/AlignCenter.d.ts +2 -0
  16. package/dist/ui/toolbar/items/AlignJustify.d.ts +2 -0
  17. package/dist/ui/toolbar/items/AlignLeft.d.ts +2 -0
  18. package/dist/ui/toolbar/items/AlignRight.d.ts +2 -0
  19. package/dist/ui/toolbar/items/Bold.d.ts +2 -0
  20. package/dist/ui/toolbar/items/BulletList.d.ts +2 -0
  21. package/dist/ui/toolbar/items/ClearFormatting.d.ts +2 -0
  22. package/dist/ui/toolbar/items/Emoji.d.ts +2 -0
  23. package/dist/ui/toolbar/items/FontFamily.d.ts +2 -0
  24. package/dist/ui/toolbar/items/FontSize.d.ts +2 -0
  25. package/dist/ui/toolbar/items/Heading.d.ts +2 -0
  26. package/dist/ui/toolbar/items/HighlightColor.d.ts +2 -0
  27. package/dist/ui/toolbar/items/HorizontalRule.d.ts +2 -0
  28. package/dist/ui/toolbar/items/Image.d.ts +2 -0
  29. package/dist/ui/toolbar/items/Indent.d.ts +2 -0
  30. package/dist/ui/toolbar/items/Italic.d.ts +2 -0
  31. package/dist/ui/toolbar/items/LineHeight.d.ts +2 -0
  32. package/dist/ui/toolbar/items/Link.d.ts +2 -0
  33. package/dist/ui/toolbar/items/OrderedList.d.ts +2 -0
  34. package/dist/ui/toolbar/items/Outdent.d.ts +2 -0
  35. package/dist/ui/toolbar/items/Redo.d.ts +2 -0
  36. package/dist/ui/toolbar/items/Strikethrough.d.ts +2 -0
  37. package/dist/ui/toolbar/items/Table.d.ts +2 -0
  38. package/dist/ui/toolbar/items/TableActions.d.ts +5 -0
  39. package/dist/ui/toolbar/items/TextColor.d.ts +2 -0
  40. package/dist/ui/toolbar/items/Underline.d.ts +2 -0
  41. package/dist/ui/toolbar/items/Undo.d.ts +2 -0
  42. package/dist/ui/toolbar/registry.d.ts +2 -0
  43. package/package.json +15 -10
  44. package/images/Screenshot from 2026-03-07 12-13-13.png +0 -0
  45. package/images/editor-preview.png +0 -0
package/ReadME.md CHANGED
@@ -15,12 +15,14 @@ A premium, ultra-lightweight, framework-agnostic rich text editor built entirely
15
15
  - **Framework Agnostic**: Drop it into React, Vue, Angular, Svelte, or plain HTML projects seamlessly.
16
16
  - **Auto-Formatting Magic**: Intelligently parses pasted HTML strings automatically into perfectly formatted rich text.
17
17
  - **Beautiful UI**: Modern aesthetics curated with a polished Slate & Indigo color palette, smooth transitions, and dynamic SVG icons.
18
+ - **Table Support**: Natively insert and style interactive HTML tables with ease.
19
+ - **Micro-Animations**: Subtle, premium transitions for tooltips, pickers, and status updates.
18
20
  - **Local Image Uploads**: Natively integrates with the OS file picker for rapid inline base64 image insertions.
19
21
  - **Flexible Styling**: Full control over font families, complex line heights, text colors, and highlighting.
22
+ - **Customizable Toolbar**: Full control over which tools are visible to the user.
20
23
 
21
24
  ### 👎 Cons (Current Limitations)
22
25
  - Base64 image storage can increase the raw output string size for very large images (Backend S3 uploading adapter coming soon).
23
- - Lacks advanced table grid manipulations in the current version.
24
26
  - Markdown shortcut typing (e.g., typing `#` for H1) is not natively supported yet.
25
27
 
26
28
  ---
@@ -36,82 +38,64 @@ npm install @meenainwal/rich-text-editor
36
38
  ### Basic Usage (Vanilla JS)
37
39
 
38
40
  ```javascript
39
- import { CoreEditor } from '@meenainwal/rich-text-editor';
40
- import '@meenainwal/rich-text-editor/dist/rich-text-editor.css'; // Import the CSS!
41
+ import { TestEditor } from '@meenainwal/rich-text-editor';
42
+ import '@meenainwal/rich-text-editor/style'; // Simple style import
41
43
 
42
44
  const container = document.getElementById('editor');
43
- const editor = new CoreEditor(container, {
45
+ const editor = new TestEditor(container, {
44
46
  placeholder: 'Type something beautiful...',
45
- autofocus: true
47
+ autofocus: true,
48
+ showStatus: true,
49
+ toolbarItems: ['bold', 'italic', 'heading', 'table', 'link'] // Customize tools
46
50
  });
47
-
48
- // To extract the customized HTML:
49
- const htmlOutput = editor.getHTML();
50
- ```
51
-
52
- ### Via CDN (Direct Download, No NPM Required)
53
-
54
- You can instantly drop the editor into any standard HTML page without installing tools or bundlers. Simply use standard CDN links (like `unpkg.com` or `jsdelivr.net`):
55
-
56
- ```html
57
- <!-- Load the beautifully styled CSS -->
58
- <link rel="stylesheet" href="https://unpkg.com/@meenainwal/rich-text-editor/dist/rich-text-editor.css">
59
-
60
- <!-- Load the Logic Script as an ES Module -->
61
- <script type="module">
62
- import { CoreEditor } from 'https://unpkg.com/@meenainwal/rich-text-editor/dist/test-editor.mjs';
63
-
64
- const container = document.getElementById('editor');
65
- const editor = new CoreEditor(container);
66
- </script>
67
51
  ```
68
52
 
69
- ### In React
53
+ ### In React / Next.js (SSR Safe)
70
54
 
71
55
  ```tsx
56
+ "use client";
72
57
  import { useEffect, useRef } from 'react';
73
- import { CoreEditor } from '@meenainwal/rich-text-editor';
74
- import '@meenainwal/rich-text-editor/dist/rich-text-editor.css';
58
+ import { TestEditor } from '@meenainwal/rich-text-editor';
59
+ import '@meenainwal/rich-text-editor/style';
75
60
 
76
- export const EditorComponent = () => {
61
+ export default function Editor() {
77
62
  const containerRef = useRef<HTMLDivElement>(null);
78
63
 
79
64
  useEffect(() => {
80
65
  if (containerRef.current) {
81
- new CoreEditor(containerRef.current);
66
+ new TestEditor(containerRef.current, {
67
+ onSave: (html) => console.log("Saved:", html)
68
+ });
82
69
  }
83
70
  }, []);
84
71
 
85
72
  return <div ref={containerRef} />;
86
- };
73
+ }
87
74
  ```
88
75
 
89
76
  ---
90
77
 
91
- ## 🗺️ Future Roadmap & Upcoming Updates
92
-
93
- As the project manager, we are aggressively expanding this editor. Next releases will feature:
94
-
95
- 1. **Phase 2.1 - Markdown Power:** Seamless markdown shortcuts (typing `**bold**`, `## Header`) that auto-convert to rich text instantly.
96
- 2. **Phase 2.2 - Table Support:** An interactive grid UI to insert, resize, and style complex HTML tables.
97
- 3. **Phase 2.3 - Framework Wrappers:** Official, first-party wrapper components for `<ReactEditor />` and `<VueEditor />` for even faster plug-and-play.
98
- 4. **Phase 2.4 - Advanced Image Handlers:** Providing hooks to intercept image uploads and pipe them to external buckets (AWS S3, Cloudinary) to return URLs instead of raw base64.
99
-
100
- ---
101
-
102
78
  ## ⚙️ Configuration Options
103
79
 
104
80
  | Option | Type | Default | Description |
105
81
  | :--- | :--- | :--- | :--- |
106
82
  | `placeholder` | `string` | `undefined` | The placeholder text when the editor is empty. |
107
- | `autofocus` | `boolean` | `false` | Whether to focus the editor automatically on initialization. |
83
+ | `autofocus` | `boolean` | `false` | Focus the editor automatically on initialization. |
84
+ | `dark` | `boolean` | `false` | Enable sophisticated Dark Mode theme. |
85
+ | `showStatus` | `boolean` | `true` | Show/hide the "Saved at..." status in the toolbar. |
86
+ | `toolbarItems` | `string[]` | `all` | Array of tool IDs to display (e.g., `['bold', 'table']`). |
87
+ | `onSave` | `function` | `undefined` | Callback triggered when content is saved. |
88
+ | `autoSaveInterval` | `number` | `1000` | Delay in ms before auto-save triggers after typing. |
108
89
 
109
90
  ## 🛠 API Methods
110
91
 
111
92
  - `getHTML()`: Returns the content as a sanitized HTML string.
112
93
  - `setHTML(html)`: Programmatically sets the editor content.
113
94
  - `focus()`: Forces focus onto the editor.
114
- - `execute(command, value)`: Execute standard editor commands internally.
95
+ - `setDarkMode(boolean)`: Dynamically toggle dark mode.
96
+ - `insertTable(rows, cols)`: Programmatically insert a table.
97
+
98
+ ---
115
99
 
116
100
  ## 📄 License
117
101
 
@@ -0,0 +1,133 @@
1
+ import { SelectionManager } from './SelectionManager';
2
+ import { ImageManager } from './ImageManager';
3
+ export interface ThemeConfig {
4
+ primaryColor?: string;
5
+ primaryHover?: string;
6
+ bgApp?: string;
7
+ bgEditor?: string;
8
+ toolbarBg?: string;
9
+ borderColor?: string;
10
+ borderFocus?: string;
11
+ textMain?: string;
12
+ textMuted?: string;
13
+ placeholder?: string;
14
+ btnHover?: string;
15
+ btnActive?: string;
16
+ radiusLg?: string;
17
+ radiusMd?: string;
18
+ radiusSm?: string;
19
+ shadowSm?: string;
20
+ shadowMd?: string;
21
+ shadowLg?: string;
22
+ }
23
+ export interface EditorOptions {
24
+ placeholder?: string;
25
+ autofocus?: boolean;
26
+ theme?: ThemeConfig;
27
+ dark?: boolean;
28
+ onSave?: (html: string) => void;
29
+ onSaving?: () => void;
30
+ onChange?: (html: string) => void;
31
+ autoSaveInterval?: number;
32
+ showStatus?: boolean;
33
+ toolbarItems?: string[];
34
+ }
35
+ export declare class CoreEditor {
36
+ protected container: HTMLElement;
37
+ protected editableElement: HTMLElement;
38
+ selection: SelectionManager;
39
+ protected imageManager: ImageManager;
40
+ private history;
41
+ protected options: EditorOptions;
42
+ private saveTimeout;
43
+ private historyTimeout;
44
+ private pendingStyles;
45
+ constructor(container: HTMLElement, options?: EditorOptions);
46
+ /**
47
+ * Applies custom theme variables to the editor container.
48
+ */
49
+ private applyTheme;
50
+ /**
51
+ * Toggles dark mode on the editor.
52
+ */
53
+ setDarkMode(enabled: boolean): void;
54
+ protected setupImageObserver(): void;
55
+ /**
56
+ * Wraps a raw <img> element in the interactive container
57
+ */
58
+ private wrapImage;
59
+ protected setupInputHandlers(): void;
60
+ private handleInput;
61
+ private scheduleHistoryRecord;
62
+ private scheduleAutoSave;
63
+ save(): void;
64
+ undo(): void;
65
+ redo(): void;
66
+ private triggerChange;
67
+ protected createEditableElement(): HTMLElement;
68
+ /**
69
+ * Focuses the editor.
70
+ */
71
+ focus(): void;
72
+ /**
73
+ * Executes a command on the current selection.
74
+ */
75
+ execute(command: string, value?: string | null): void;
76
+ /**
77
+ * Inserts a table at the current selection.
78
+ */
79
+ insertTable(rows?: number, cols?: number): void;
80
+ /**
81
+ * Adds a row to the currently selected table.
82
+ */
83
+ addRow(): void;
84
+ /**
85
+ * Deletes the currently selected row.
86
+ */
87
+ deleteRow(): void;
88
+ /**
89
+ * Adds a column to the currently selected table.
90
+ */
91
+ addColumn(): void;
92
+ /**
93
+ * Deletes the currently selected column.
94
+ */
95
+ deleteColumn(): void;
96
+ private getSelectedTd;
97
+ private getSelectedTable;
98
+ /**
99
+ * Recursively removes a style property from all elements in a fragment.
100
+ */
101
+ private clearStyleRecursive;
102
+ /**
103
+ * Applies an inline style to the selection.
104
+ * This is used for properties like font-size (px) and font-family
105
+ * where execCommand is outdated or limited.
106
+ */
107
+ setStyle(property: string, value: string, range?: Range): Range | null;
108
+ /**
109
+ * Creates a link at the current selection.
110
+ * Ensures the link opens in a new tab with proper security attributes.
111
+ */
112
+ createLink(url: string): void;
113
+ /**
114
+ * Inserts an image at the current selection.
115
+ */
116
+ insertImage(url: string): void;
117
+ /**
118
+ * Returns the clean HTML content of the editor.
119
+ */
120
+ getHTML(): string;
121
+ /**
122
+ * Sets the HTML content of the editor.
123
+ */
124
+ setHTML(html: string): void;
125
+ /**
126
+ * Internal access to the editable element.
127
+ */
128
+ get el(): HTMLElement;
129
+ /**
130
+ * Returns the editor options.
131
+ */
132
+ getOptions(): EditorOptions;
133
+ }
@@ -0,0 +1,30 @@
1
+ export interface HistoryState {
2
+ html: string;
3
+ }
4
+ export declare class HistoryManager {
5
+ private stack;
6
+ private index;
7
+ private maxDepth;
8
+ constructor(initialState?: string);
9
+ /**
10
+ * Records a new state in the history stack.
11
+ * Clears any "redo" states if we record a new action.
12
+ */
13
+ record(html: string): void;
14
+ /**
15
+ * Returns the previous state if available.
16
+ */
17
+ undo(): string | null;
18
+ /**
19
+ * Returns the next state if available.
20
+ */
21
+ redo(): string | null;
22
+ /**
23
+ * Checks if undo is possible.
24
+ */
25
+ canUndo(): boolean;
26
+ /**
27
+ * Checks if redo is possible.
28
+ */
29
+ canRedo(): boolean;
30
+ }
@@ -0,0 +1,19 @@
1
+ import { CoreEditor } from './Editor';
2
+ export declare class ImageManager {
3
+ private editor;
4
+ private activeContainer;
5
+ private isResizing;
6
+ private startX;
7
+ private startY;
8
+ private startWidth;
9
+ private startHeight;
10
+ private currentHandle;
11
+ private aspectRatio;
12
+ constructor(editor: CoreEditor);
13
+ private setupListeners;
14
+ private selectImage;
15
+ private deselectImage;
16
+ private startResize;
17
+ private handleResize;
18
+ private stopResize;
19
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * SelectionManager handles wrapping the native browser Selection and Range APIs.
3
+ * This ensures consistent behavior across different environments and simplifies
4
+ * interaction with the editor's cursor and selected text.
5
+ */
6
+ export declare class SelectionManager {
7
+ /**
8
+ * Returns the current selection object.
9
+ */
10
+ getSelection(): Selection | null;
11
+ /**
12
+ * Returns the first range of the current selection.
13
+ */
14
+ getRange(): Range | null;
15
+ /**
16
+ * Saves the current selection range.
17
+ */
18
+ saveSelection(): Range | null;
19
+ /**
20
+ * Restores a previously saved range.
21
+ */
22
+ restoreSelection(range: Range | null): void;
23
+ /**
24
+ * Checks if the selection is within a specific element.
25
+ */
26
+ isSelectionInElement(element: HTMLElement): boolean;
27
+ /**
28
+ * Clears the current selection.
29
+ */
30
+ clearSelection(): void;
31
+ }
@@ -0,0 +1,11 @@
1
+ import { CoreEditor, EditorOptions } from './core/Editor';
2
+ import { Toolbar } from './ui/Toolbar';
3
+ export declare class TestEditor extends CoreEditor {
4
+ private toolbar;
5
+ constructor(container: HTMLElement, options?: EditorOptions);
6
+ getToolbar(): Toolbar;
7
+ }
8
+ export { CoreEditor, type EditorOptions } from './core/Editor';
9
+ export { SelectionManager } from './core/SelectionManager';
10
+ export { Toolbar } from './ui/Toolbar';
11
+ export { HistoryManager } from './core/HistoryManager';
@@ -1 +1 @@
1
- :root{--te-primary-color: #6366f1;--te-primary-hover: #4f46e5;--te-bg-app: #f8fafc;--te-bg-editor: #ffffff;--te-toolbar-bg: #ffffff;--te-border-color: #e2e8f0;--te-border-focus: #cbd5e1;--te-text-main: #1e293b;--te-text-muted: #64748b;--te-placeholder: #94a3b8;--te-btn-hover: #f1f5f9;--te-btn-active: #e2e8f0;--te-radius-lg: 12px;--te-radius-md: 8px;--te-radius-sm: 6px;--te-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .05);--te-shadow-md: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--te-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--te-transition: all .2s cubic-bezier(.4, 0, .2, 1)}.te-container{display:flex;flex-direction:column;height:500px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-lg);background:var(--te-bg-editor);box-shadow:var(--te-shadow-sm);overflow:hidden;font-family:Inter,-apple-system,system-ui,sans-serif;color:var(--te-text-main);transition:var(--te-transition);max-width:100%}.te-container:focus-within{border-color:var(--te-primary-color);box-shadow:0 0 0 4px #6366f11a,var(--te-shadow-md)}.te-toolbar{display:flex;flex-wrap:wrap;gap:6px;padding:10px 12px;border-bottom:1px solid var(--te-border-color);background:var(--te-toolbar-bg);align-items:center;-webkit-user-select:none;user-select:none;position:sticky;top:0;z-index:10}.te-divider{width:1px;height:20px;background-color:var(--te-border-color);margin:0 6px}.te-button,.te-select,.te-input{display:flex;align-items:center;justify-content:center;height:32px;border:1px solid transparent;background:transparent;border-radius:var(--te-radius-sm);cursor:pointer;color:var(--te-text-muted);font-size:13px;font-weight:500;transition:var(--te-transition);box-sizing:border-box}.te-button{width:32px;padding:0}.te-button svg{width:16px;height:16px;stroke:currentColor;stroke-width:2.2;fill:none}.te-select{padding:0 24px 0 8px;min-width:120px;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2364748b'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2.5' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 6px center;background-size:12px;border:1px solid var(--te-border-color);background-color:#fff}.te-input{width:56px;padding:0 4px;text-align:center;cursor:text;border:1px solid var(--te-border-color);background-color:#fff}.te-color-picker{width:32px;height:32px;padding:4px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-sm);background:#fff;cursor:pointer;box-sizing:border-box}.te-color-picker:hover{border-color:var(--te-border-focus)}.te-color-picker-wrapper{position:relative;display:inline-flex;width:32px;height:32px;border-radius:var(--te-radius-sm);transition:var(--te-transition)}.te-color-picker-wrapper:hover{background:var(--te-btn-hover)}.te-color-picker-input{position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;cursor:pointer;z-index:2}.te-color-icon{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center;z-index:1}.te-color-indicator{position:absolute;bottom:4px;left:6px;right:6px;height:3px;border-radius:2px;box-shadow:0 1px 1px #0000001a}.te-emoji-picker{position:absolute;width:280px;height:320px;background:#fff;border:1px solid var(--te-border-color);border-radius:var(--te-radius-md);box-shadow:var(--te-shadow-lg);display:flex;flex-direction:column;z-index:1000;animation:te-fade-in .2s ease-out}@keyframes te-fade-in{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.te-emoji-header{padding:12px;border-bottom:1px solid var(--te-border-color)}.te-emoji-search{width:100%;padding:8px 12px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-sm);font-size:13px;outline:none;transition:var(--te-transition)}.te-emoji-search:focus{border-color:var(--te-primary-color);box-shadow:0 0 0 2px #6366f11a}.te-emoji-body{flex:1;overflow-y:auto;padding:8px}.te-emoji-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}.te-emoji-category-title{grid-column:span 7;padding:8px 4px 4px;font-size:11px;font-weight:600;color:var(--te-text-muted);text-transform:uppercase;letter-spacing:.05em}.te-emoji-item{width:32px;height:32px;display:flex;align-items:center;justify-content:center;font-size:20px;border:none;background:transparent;cursor:pointer;border-radius:var(--te-radius-sm);transition:var(--te-transition)}.te-emoji-item:hover{background:var(--te-btn-hover);transform:scale(1.1)}.te-emoji-empty{grid-column:span 7;text-align:center;padding:20px;color:var(--te-text-muted);font-size:13px}.te-button:hover{background:var(--te-btn-hover);color:var(--te-text-main)}.te-select:hover,.te-input:hover{border-color:var(--te-border-focus)}.te-button.active{background:var(--te-btn-active);color:var(--te-primary-color);border-color:#6366f133}.te-select:focus,.te-input:focus{border-color:var(--te-primary-color);box-shadow:0 0 0 2px #6366f11a;outline:none;background:#fff;color:var(--te-text-main)}.te-content{flex:1;overflow-y:auto;min-height:240px;padding:24px;line-height:1.25;outline:none;font-size:16px}.te-content p{margin:0 0 1.25em}.te-content h1,.te-content h2,.te-content h3,.te-content h4,.te-content h5,.te-content h6{color:var(--te-text-main);font-weight:700;margin:1.5em 0 .5em;line-height:1.25}.te-content h1:first-child,.te-content p:first-child{margin-top:0}.te-content h1{font-size:2.25em}.te-content h2{font-size:1.875em}.te-content h3{font-size:1.5em}.te-content h4{font-size:1.25em}.te-content[data-placeholder]:empty:before{content:attr(data-placeholder);color:var(--te-placeholder);pointer-events:none}.te-image-container{position:relative;display:inline-block;margin:1.5rem 0;max-width:100%;border-radius:var(--te-radius-lg);overflow:visible;transition:box-shadow var(--te-transition-fast);line-height:0}.te-image-container:hover{box-shadow:0 0 0 2px var(--te-primary-color)}.te-image-container.active{box-shadow:0 0 0 2px var(--te-primary-color),var(--te-shadow-lg)}.te-image{display:block;max-width:100%;height:auto;-webkit-user-select:none;user-select:none}.te-image-caption{font-size:.875rem;color:var(--te-text-muted);text-align:center;padding:.75rem;background:var(--te-bg-app);line-height:normal;border-bottom-left-radius:var(--te-radius-lg);border-bottom-right-radius:var(--te-radius-lg)}.te-image-caption:empty:before{content:attr(data-placeholder);color:var(--te-placeholder)}.te-image-resizer{position:absolute;width:10px;height:10px;background:var(--te-primary-color);border:1px solid white;z-index:10;display:none}.te-image-container:hover .te-image-resizer,.te-image-container.active .te-image-resizer{display:block}.te-resizer-top-left{top:-5px;left:-5px;cursor:nwse-resize}.te-resizer-top-right{top:-5px;right:-5px;cursor:nesw-resize}.te-resizer-bottom-left{bottom:-5px;left:-5px;cursor:nesw-resize}.te-resizer-bottom-right{bottom:-5px;right:-5px;cursor:nwse-resize}.te-content.dragover{background:#f0f7ff;outline:2px dashed var(--te-primary-color);outline-offset:-4px}
1
+ .te-container,.te-emoji-picker{--te-primary-color: #6366f1;--te-primary-hover: #4f46e5;--te-bg-app: #f8fafc;--te-bg-editor: #ffffff;--te-toolbar-bg: #ffffff;--te-border-color: #e2e8f0;--te-border-focus: #cbd5e1;--te-text-main: #1e293b;--te-text-muted: #64748b;--te-placeholder: #94a3b8;--te-btn-hover: #f1f5f9;--te-btn-active: #e2e8f0;--te-radius-lg: 12px;--te-radius-md: 8px;--te-radius-sm: 6px;--te-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .05);--te-shadow-md: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--te-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--te-transition: all .2s cubic-bezier(.4, 0, .2, 1)}.te-container.te-dark,.te-emoji-picker.te-dark{--te-primary-color: #818cf8 !important;--te-primary-hover: #6366f1 !important;--te-bg-app: #0f172a !important;--te-bg-editor: #1e293b !important;--te-toolbar-bg: #1e293b !important;--te-border-color: #334155 !important;--te-border-focus: #475569 !important;--te-text-main: #f8fafc !important;--te-text-muted: #94a3b8 !important;--te-placeholder: #64748b !important;--te-btn-hover: #334155 !important;--te-btn-active: #475569 !important;--te-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .3) !important;--te-shadow-md: 0 4px 6px -1px rgb(0 0 0 / .5), 0 2px 4px -2px rgb(0 0 0 / .5) !important;--te-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .5), 0 4px 6px -4px rgb(0 0 0 / .5) !important}.te-container,.te-container *,.te-emoji-picker,.te-emoji-picker *{box-sizing:border-box}.te-container{display:flex;flex-direction:column;height:500px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-lg);background:var(--te-bg-editor);box-shadow:var(--te-shadow-sm);overflow:hidden;font-family:Inter,-apple-system,system-ui,sans-serif;color:var(--te-text-main)!important;transition:var(--te-transition);max-width:100%}.te-container:focus-within{border-color:var(--te-primary-color);box-shadow:0 0 0 4px #6366f11a,var(--te-shadow-md)}.te-toolbar{display:flex;flex-wrap:wrap;gap:6px;padding:10px 12px;border-bottom:1px solid var(--te-border-color);background:var(--te-toolbar-bg);align-items:center;-webkit-user-select:none;user-select:none;position:sticky;top:0;z-index:10}.te-divider{width:1px;height:20px;background-color:var(--te-border-color);margin:0 6px}.te-button,.te-select,.te-input{display:flex;align-items:center;justify-content:center;height:32px;border:1px solid transparent;background:transparent;border-radius:var(--te-radius-sm);cursor:pointer;color:var(--te-text-muted);font-size:13px;font-weight:500;transition:var(--te-transition);box-sizing:border-box}.te-button{width:32px;padding:0}.te-button svg{width:16px;height:16px;stroke:currentColor;stroke-width:2.2;fill:none}.te-select{padding:0 24px 0 8px;min-width:120px;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2364748b'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2.5' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 6px center;background-size:12px;border:1px solid var(--te-border-color);background-color:var(--te-bg-editor)!important;color:var(--te-text-main)!important}.te-input{width:56px;padding:0 4px;text-align:center;cursor:text;border:1px solid var(--te-border-color);background-color:var(--te-bg-editor)!important;color:var(--te-text-main)!important}.te-color-picker{width:32px;height:32px;padding:4px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-sm);background:var(--te-bg-editor);cursor:pointer;box-sizing:border-box}.te-color-picker:hover{border-color:var(--te-border-focus)}.te-color-picker-wrapper{position:relative;display:inline-flex;width:32px;height:32px;border-radius:var(--te-radius-sm);transition:var(--te-transition)}.te-color-picker-wrapper:hover{background:var(--te-btn-hover)}.te-color-picker-input{position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;cursor:pointer;z-index:2}.te-color-icon{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center;z-index:1}.te-color-indicator{position:absolute;bottom:4px;left:6px;right:6px;height:3px;border-radius:2px;box-shadow:0 1px 1px var(--te-shadow-sm)}.te-emoji-picker{position:absolute;width:280px;height:320px;background:var(--te-bg-editor);border:1px solid var(--te-border-color);border-radius:var(--te-radius-md);box-shadow:var(--te-shadow-lg);display:flex;flex-direction:column;z-index:1000;animation:te-fade-in .2s ease-out}@keyframes te-fade-in{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.te-emoji-header{padding:12px;border-bottom:1px solid var(--te-border-color)}.te-emoji-search{width:100%;padding:8px 12px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-sm);background-color:var(--te-bg-editor)!important;color:var(--te-text-main)!important;font-size:13px;outline:none;transition:var(--te-transition)}.te-emoji-search:focus{border-color:var(--te-primary-color);box-shadow:0 0 0 2px #6366f11a}.te-emoji-body{flex:1;overflow-y:auto;overflow-x:hidden;padding:8px}.te-emoji-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}.te-emoji-category-title{grid-column:span 7;padding:8px 4px 4px;font-size:11px;font-weight:600;color:var(--te-text-muted);text-transform:uppercase;letter-spacing:.05em}.te-emoji-item{width:32px;height:32px;display:flex;align-items:center;justify-content:center;font-size:20px;border:none;background:transparent;cursor:pointer;border-radius:var(--te-radius-sm);transition:var(--te-transition)}.te-emoji-item:hover{background:var(--te-btn-hover);transform:scale(1.1)}.te-emoji-empty{grid-column:span 7;text-align:center;padding:20px;color:var(--te-text-muted);font-size:13px}.te-button:hover{background:var(--te-btn-hover);color:var(--te-text-main)!important}.te-select:hover,.te-input:hover{border-color:var(--te-border-focus)}.te-button.active{background:var(--te-btn-active);color:var(--te-primary-color);border-color:#6366f133}.te-select:focus,.te-input:focus{border-color:var(--te-primary-color);box-shadow:0 0 0 2px #6366f11a;outline:none;background:var(--te-bg-editor);color:var(--te-text-main)!important}.te-content{flex:1;overflow-y:auto;min-height:240px;padding:24px;line-height:1.25;outline:none;font-size:16px}.te-content p{margin:0 0 1.25em}.te-content h1,.te-content h2,.te-content h3,.te-content h4,.te-content h5,.te-content h6{color:var(--te-text-main)!important;font-weight:700;margin:1.5em 0 .5em;line-height:1.25}.te-content h1:first-child,.te-content p:first-child{margin-top:0}.te-content h1{font-size:2.25em}.te-content h2{font-size:1.875em}.te-content h3{font-size:1.5em}.te-content h4{font-size:1.25em}.te-content[data-placeholder]:empty:before{content:attr(data-placeholder);color:var(--te-placeholder);pointer-events:none}.te-image-container{position:relative;display:inline-block;margin:1.5rem 0;max-width:100%;border-radius:var(--te-radius-lg);overflow:visible;transition:box-shadow var(--te-transition-fast);line-height:0}.te-image-container:hover{box-shadow:0 0 0 2px var(--te-primary-color)}.te-image-container.active{box-shadow:0 0 0 2px var(--te-primary-color),var(--te-shadow-lg)}.te-image{display:block;max-width:100%;height:auto;-webkit-user-select:none;user-select:none}.te-image-caption{font-size:.875rem;color:var(--te-text-muted);text-align:center;padding:.75rem;background:var(--te-bg-app);line-height:normal;border-bottom-left-radius:var(--te-radius-lg);border-bottom-right-radius:var(--te-radius-lg)}.te-image-caption:empty:before{content:attr(data-placeholder);color:var(--te-placeholder)}.te-image-resizer{position:absolute;width:10px;height:10px;background:var(--te-primary-color);border:1px solid var(--te-bg-editor);z-index:10;display:none}.te-image-container:hover .te-image-resizer,.te-image-container.active .te-image-resizer{display:block}.te-resizer-top-left{top:-5px;left:-5px;cursor:nwse-resize}.te-resizer-top-right{top:-5px;right:-5px;cursor:nesw-resize}.te-resizer-bottom-left{bottom:-5px;left:-5px;cursor:nesw-resize}.te-resizer-bottom-right{bottom:-5px;right:-5px;cursor:nwse-resize}.te-content.dragover{background:var(--te-btn-hover);outline:2px dashed var(--te-primary-color);outline-offset:-4px}.te-table{width:100%;border-collapse:collapse;margin:1.5rem 0;border:1px solid var(--te-border-color);border-radius:var(--te-radius-md);table-layout:fixed}.te-table td,.te-table th{border:1px solid var(--te-border-color);padding:12px;min-height:44px;vertical-align:top;position:relative;transition:background-color .2s ease;color:var(--te-text-main)}.te-table tr{border-bottom:1px solid var(--te-border-color)}.te-table tr:last-child{border-bottom:none}.te-table td:hover{background-color:var(--te-btn-hover)}.te-table td:focus-within{background-color:var(--te-btn-active);outline:none}.te-dark .te-table,.te-dark .te-table td,.te-dark .te-table th{border-color:#334155}.te-dark .te-table td:hover{background-color:#1e293b}
@@ -0,0 +1,4 @@
1
+ declare module '@meenainwal/rich-text-editor/style' {
2
+ const content: any;
3
+ export default content;
4
+ }