@aquera/nile-elements 0.1.67-beta-2.3 → 0.1.67-beta-2.4

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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Webcomponent nile-elements following open-wc recommendations",
4
4
  "license": "MIT",
5
5
  "author": "nile-elements",
6
- "version": "0.1.67-beta-2.3",
6
+ "version": "0.1.67-beta-2.4",
7
7
  "main": "dist/src/index.js",
8
8
  "type": "module",
9
9
  "module": "dist/src/index.js",
@@ -1,143 +1,134 @@
1
- // rte-styles.ts
1
+ // FILE: src/components/rte-styles.ts
2
2
  import { css } from 'lit';
3
3
 
4
4
  export const styles = css`
5
-
6
-
7
- .editor {all: revert;}
8
-
9
- nile-rich-text-editor { position: relative; display: block; font-family: inherit; }
10
-
11
-
12
- nile-rte-toolbar-item nile-button::part(base) {
13
-
14
- width:32px; height:32px; padding:0px 6px;
15
- border: none;
16
- }
17
-
18
- nile-rte-preview {
19
- white-space: normal;
20
- word-break: break-word;
21
- }
22
-
23
-
24
- .editor.single-line {
25
- width: 478px;
26
- min-height: 50px;
27
- overflow-x: auto;
28
- white-space: nowrap;
29
- border-radius: 8px;
30
- }
31
-
32
-
33
-
34
-
35
-
36
-
37
- .toolbar, nile-rte-toolbar {
38
- width:486px;
39
- display:flex; align-items:center; gap:6px; padding:8px;
40
- border:1px solid #e5e7eb; border-bottom:none; border-radius:8px 8px 0 0; background:#fff;
41
- }
42
-
43
- nile-rte-toolbar-item > button, .toolbar button, nile-rte-toolbar button {
44
- border:1px solid #e5e7eb; background:#fff; border-radius:6px;
45
- cursor:pointer;
46
- }
47
-
48
-
49
- /* Ensure clicks hit the button (not nested icon internals) */
50
- nile-rte-toolbar-item > button nile-icon { pointer-events:none; }
51
-
52
- nile-rte-toolbar-item > button.active { border-color:#2563eb; background:#eff6ff; }
53
- nile-rte-select select { height:32px; border:1px solid #e5e7eb; border-radius:6px; background:#fff; }
54
- nile-rte-color input[type="color"] { height:32px; width:36px; border:1px solid #e5e7eb; padding:0; border-radius:6px; background:#fff; }
55
- nile-rte-divider { width:1px; height:20px; background:#e5e7eb; display:inline-block; margin:0 4px; }
56
-
57
- .editor p { margin:1em 0; }
58
- .editor h1, .preview h1 { all: revert; font-size:2em, display: block;
59
- font-size: 2em;
60
- margin-top: 0.67em;
61
- margin-bottom: 0.67em;
62
- margin-left: 0;
63
- margin-right: 0;
64
- font-weight: bold; }
65
- .editor h2, .preview h2 { all: revert; display: block;
66
- font-size: 1.5em;
67
- margin-top: 0.83em;
68
- margin-bottom: 0.83em;
69
- margin-left: 0;
70
- margin-right: 0;
71
- font-weight: bold;}
72
- .editor h3 { font-size:1.17em }
73
- .editor h4 { font-size:1em }
74
- .editor h5 { font-size:0.83em }
75
- .editor h6 { font-size:0.67em }
76
-
77
- .editor { min-height:160px; max-width:478px; padding:12px; border:1px solid #e5e7eb; border-radius:0 0 8px 8px; background:#fff; outline:none;
78
- tab-size: 4;
79
- -moz-tab-size: 4;
80
- word-break: break-word;
81
- }
82
- nile-rte-preview { display:block; margin-top:10px; padding:10px; border:1px dashed #cbd5e1; border-radius:8px; background:#fafafa; max-width:478px; }
83
-
84
- nile-rte-preview.single-line {
85
- width: 478px;
86
- min-height: 50px;
87
- overflow-x: auto;
88
- white-space: nowrap;
89
- }
90
-
91
- .rte-color-trigger {
92
- display: inline-flex;
5
+ .editor { all: revert; }
6
+
7
+ nile-rich-text-editor {
8
+ position: relative;
9
+ display: block;
10
+ font-family: inherit;
11
+ }
12
+
13
+ /* --- Card 1: Toolbar + Editor --- */
14
+ .rte-container {
15
+ width: 100%;
16
+ border: 1px solid #e5e7eb;
17
+ border-radius: 8px;
18
+ background: #fff;
19
+ box-sizing: border-box;
20
+ }
21
+
22
+ /* Toolbar inside container */
23
+ .rte-container nile-rte-toolbar {
24
+ display: flex;
93
25
  align-items: center;
94
- justify-content: center;
95
- /* border: 1px solid var(--nile-color-border, #d9d9d9); */
96
- border-radius: 6px;
26
+ gap: 6px;
27
+ padding: 8px;
28
+ border-bottom: 1px solid #e5e7eb;
97
29
  background: #fff;
98
- cursor: pointer;
99
- border:none;
100
-
30
+ border-radius: 8px 8px 0 0;
101
31
 
102
- }
103
- nile-button.rte-color-trigger::part(base){
104
- width:32px; height:32px; padding:0px 6px;
105
- }
106
- .rte-color-trigger .glyph-stack {
107
- display: grid; /* stack vertically */
108
- grid-auto-rows: max-content;
109
- align-items: center;
110
- justify-items: center;
111
- line-height: 1;
32
+ width: 100%;
33
+ box-sizing: border-box;
112
34
  }
113
35
 
114
- .rte-color-trigger .glyph {
115
- font-size: 14px;
116
- line-height: 1;
117
- margin-bottom: 2px;
118
- }
119
36
 
120
- .rte-color-trigger .underline {
121
- width: 18px;
122
- height: 3px;
123
- border-radius: 2px;
124
- background: currentColor;
125
- }
126
-
127
- .rte-color-trigger .swatch-box {
128
- width: 18px;
129
- height: 16px;
130
- border-radius: 4px;
131
- border: 1px solid rgba(0,0,0,0.35);
132
- background: currentColor; /* overridden via JS */
133
- }
134
- nile-rte-toolbar-item nile-button[data-active]::part(base) {
135
- background-color: var(--nile-colors-primary-400);
37
+ .rte-container .editor {
38
+ min-height: 160px;
39
+ width: 100%;
40
+ padding: 12px;
41
+ background: #fff;
42
+ border-radius: 0 0 8px 8px;
43
+ outline: none;
44
+ tab-size: 4;
45
+ -moz-tab-size: 4;
46
+ word-break: break-word;
47
+ box-sizing: border-box;
48
+ border-radius: 8px;
49
+ }
50
+
51
+ /* --- Card 2: Preview --- */
52
+ /* Preview card */
53
+ nile-rte-preview {
54
+ display: block;
55
+ width: 100%;
56
+ margin-top: 16px;
57
+ padding: 12px;
58
+ border: 1px dashed #e5e7eb;
59
+ border-radius: 8px;
60
+ background: #fafafa;
61
+ box-sizing: border-box;
62
+ word-wrap: break-word;
136
63
  }
137
64
 
138
- nile-rte-toolbar-item nile-button[data-active]::part(base):hover {
139
- background-color: var(--nile-colors-primary-500);
140
- }
65
+
66
+ /* Toolbar button styling */
67
+ nile-rte-toolbar-item nile-button::part(base) {
68
+ width: 32px;
69
+ height: 32px;
70
+ padding: 0px 6px;
71
+ border: none;
72
+ }
73
+
74
+ nile-rte-toolbar-item > button,
75
+ nile-rte-toolbar button {
76
+ border: 1px solid #e5e7eb;
77
+ background: #fff;
78
+ border-radius: 6px;
79
+ cursor: pointer;
80
+ }
81
+
82
+ nile-rte-toolbar-item > button nile-icon { pointer-events: none; }
83
+
84
+ nile-rte-toolbar-item > button.active {
85
+ border-color: #2563eb;
86
+ background: #eff6ff;
87
+ }
88
+
89
+ /* Heading normalization */
90
+ .editor p { margin: 1em 0; }
91
+ .editor h1, .preview h1 {
92
+ font-size: 2em;
93
+ margin: 0.67em 0;
94
+ font-weight: bold;
95
+ }
96
+ .editor h2, .preview h2 {
97
+ font-size: 1.5em;
98
+ margin: 0.83em 0;
99
+ font-weight: bold;
100
+ }
101
+ .editor h3 { font-size: 1.17em; }
102
+ .editor h4 { font-size: 1em; }
103
+ .editor h5 { font-size: 0.83em; }
104
+ .editor h6 { font-size: 0.67em; }
105
+
106
+ /* Single-line variant */
107
+ .editor.single-line {
108
+ min-height: 50px;
109
+ max-height: 50px;
110
+ overflow-x: auto;
111
+ white-space: nowrap;
112
+ padding: 0px 12px 0px 12px;
113
+ scrollbar-width: none;
114
+ -ms-overflow-style: none;
115
+ }
116
+ nile-rte-preview.single-line {
117
+ min-height: 50px;
118
+ max-height: 50px;
119
+ padding: 0px 12px 0px 12px;
120
+ overflow-x: auto;
121
+ white-space: nowrap;
122
+ scrollbar-width: none;
123
+ -ms-overflow-style: none;
124
+ }
125
+ nile-rte-divider {
126
+ margin: 0 4px;
127
+ display: inline-block;
128
+ height: 24px;
129
+ width: 1px;
130
+ background: #E6E9EB;
131
+ }
141
132
  `;
142
133
 
143
- export default [styles];
134
+ export default [styles];
@@ -43,7 +43,7 @@ const DEFAULT_ICONS: Record<string, string> = {
43
43
  @customElement('nile-rich-text-editor')
44
44
  export class NileRichTextEditor extends LitElement {
45
45
  protected createRenderRoot() { return this; }
46
- protected shouldUpdate() { return false; }
46
+ // protected shouldUpdate() { return false; }
47
47
 
48
48
 
49
49
  @property({ type: String }) value = '';
@@ -89,6 +89,8 @@ export class NileRichTextEditor extends LitElement {
89
89
  private bgColorInput: HTMLInputElement | null = null;
90
90
  private colorSwatchEl: HTMLElement | null = null;
91
91
  private bgSwatchEl: HTMLElement | null = null;
92
+ private containerEl: HTMLElement | null = null;
93
+
92
94
 
93
95
 
94
96
 
@@ -106,55 +108,61 @@ private bgSwatchEl: HTMLElement | null = null;
106
108
 
107
109
  connectedCallback(): void {
108
110
  super.connectedCallback();
111
+ this.injectCss(styles.cssText);
112
+ this.ensureStructure();
109
113
 
110
-
111
- this.injectCss(styles.cssText);
112
-
113
-
114
-
115
- this.toolbarEl = this.querySelector('nile-rte-toolbar');
116
- this.previewEl = this.querySelector('nile-rte-preview');
117
- if (this.singleLineEditor) {
118
- this.editorEl?.classList.add('single-line');
119
- this.previewEl?.classList.add('single-line');
120
- }
121
-
122
- this.ensureEditor();
123
-
124
-
125
114
  if (this.value && !this.editorEl.innerHTML.trim()) {
126
115
  this.editorEl.innerHTML = this.value;
127
116
  }
128
117
  this.content = this.editorEl.innerHTML;
129
118
 
130
-
131
119
  if (this.toolbarEl) this.wireAuthoredToolbar(this.toolbarEl);
132
-
133
-
134
120
  this.mentionsEl = this.querySelector('nile-rte-mentions');
135
121
  if (this.mentionsEl) {
136
-
137
122
  (this.mentionsEl as any).attach?.(this.editorEl, this as HTMLElement);
138
-
139
123
  (this.mentionsEl as any).setExternalConfig?.(this.mentions);
140
124
  }
141
125
 
142
-
143
126
  this.wireEditor();
144
-
145
-
146
127
  this.updateToolbarState();
147
128
  this.syncPreview();
129
+ }
148
130
 
149
-
150
- document.addEventListener('selectionchange', this.onSelectionChange, true);
151
- if (this.mentionsEl) {
152
- this.mentionsEl.addEventListener('mention-selected', (e: any) => {
153
- this.updateContentWithMention(e.detail);
154
- });
131
+ private ensureStructure() {
132
+ this.toolbarEl = this.querySelector('nile-rte-toolbar');
133
+ this.previewEl = this.querySelector('nile-rte-preview');
134
+
135
+ // container for toolbar + editor
136
+ this.containerEl = this.querySelector('.rte-container') as HTMLElement;
137
+ if (!this.containerEl) {
138
+ this.containerEl = document.createElement('div');
139
+ this.containerEl.className = 'rte-container';
140
+ this.appendChild(this.containerEl);
141
+ }
142
+
143
+ // ensure editor
144
+ this.ensureEditor();
145
+
146
+ // put toolbar + editor inside container
147
+ if (this.toolbarEl && this.toolbarEl.parentElement !== this.containerEl) {
148
+ this.containerEl.appendChild(this.toolbarEl);
149
+ }
150
+ if (this.editorEl.parentElement !== this.containerEl) {
151
+ this.containerEl.appendChild(this.editorEl);
152
+ }
153
+
154
+ // 👉 move preview OUTSIDE container, right after it
155
+ if (this.previewEl) {
156
+ if (this.previewEl.parentElement !== this) {
157
+ this.appendChild(this.previewEl);
158
+ }
159
+ // ensure preview is placed AFTER container
160
+ if (this.previewEl.previousElementSibling !== this.containerEl) {
161
+ this.insertBefore(this.previewEl, this.containerEl.nextSibling);
162
+ }
155
163
  }
156
-
157
164
  }
165
+
158
166
 
159
167
  private updateContentWithMention(mentionDetail: any) {
160
168
  this.updateContent();
@@ -188,28 +196,17 @@ private bgSwatchEl: HTMLElement | null = null;
188
196
  }
189
197
  }
190
198
 
191
-
192
199
  private ensureEditor() {
193
200
  this.editorEl = this.querySelector('.editor') as HTMLElement;
194
201
  if (!this.editorEl) {
195
202
  const editor = document.createElement('article');
196
203
  editor.className = 'editor';
197
- editor.setAttribute('contenteditable','true');
198
- if (this.singleLineEditor) editor.classList.add('single-line');
199
-
200
- if (this.toolbarEl?.nextSibling) {
201
- this.insertBefore(editor, this.toolbarEl.nextSibling);
202
- } else if (this.previewEl) {
203
- this.insertBefore(editor, this.previewEl);
204
- } else {
205
- this.appendChild(editor);
206
- }
204
+ editor.setAttribute('contenteditable', 'true');
207
205
  this.editorEl = editor;
208
206
  }
209
207
  if (!this.editorEl.innerHTML.trim()) {
210
208
  this.editorEl.innerHTML = '<p><br></p>';
211
209
  }
212
- this.ensureAtLeastOneParagraph();
213
210
  }
214
211
 
215
212
 
@@ -2953,7 +2953,7 @@
2953
2953
  },
2954
2954
  {
2955
2955
  "name": "nile-rich-text-editor",
2956
- "description": "Events:\n\n * `content-changed` {`CustomEvent<{ content: string; mention: any; }>`} - \n\nAttributes:\n\n * `value` {`string`} - \n\n * `singlelineeditor` {`boolean`} - \n\n * `mentions` - \n\nProperties:\n\n * `value` {`string`} - \n\n * `singleLineEditor` {`boolean`} - \n\n * `mentions` - \n\n * `content` {`string`} - \n\n * `editorEl` {`HTMLElement`} - \n\n * `previewEl` {`HTMLElement | null`} - \n\n * `toolbarEl` {`HTMLElement | null`} - \n\n * `lastRange` {`Range | null`} - \n\n * `buttonMap` {`Map<string, HTMLElement[]>`} - \n\n * `headingSelect` {`HTMLSelectElement | null`} - \n\n * `fontSelect` {`HTMLSelectElement | null`} - \n\n * `colorInput` {`HTMLInputElement | null`} - \n\n * `bgColorInput` {`HTMLInputElement | null`} - \n\n * `colorSwatchEl` {`HTMLElement | null`} - \n\n * `bgSwatchEl` {`HTMLElement | null`} - \n\n * `mentionsEl` {`HTMLElement | null`} - \n\n * `onEditorKeydown` - \n\n * `onSelectionChange` - ",
2956
+ "description": "Events:\n\n * `content-changed` {`CustomEvent<{ content: string; mention: any; }>`} - \n\nAttributes:\n\n * `value` {`string`} - \n\n * `singlelineeditor` {`boolean`} - \n\n * `mentions` - \n\nProperties:\n\n * `value` {`string`} - \n\n * `singleLineEditor` {`boolean`} - \n\n * `mentions` - \n\n * `content` {`string`} - \n\n * `editorEl` {`HTMLElement`} - \n\n * `previewEl` {`HTMLElement | null`} - \n\n * `toolbarEl` {`HTMLElement | null`} - \n\n * `lastRange` {`Range | null`} - \n\n * `buttonMap` {`Map<string, HTMLElement[]>`} - \n\n * `headingSelect` {`HTMLSelectElement | null`} - \n\n * `fontSelect` {`HTMLSelectElement | null`} - \n\n * `colorInput` {`HTMLInputElement | null`} - \n\n * `bgColorInput` {`HTMLInputElement | null`} - \n\n * `colorSwatchEl` {`HTMLElement | null`} - \n\n * `bgSwatchEl` {`HTMLElement | null`} - \n\n * `containerEl` {`HTMLElement | null`} - \n\n * `mentionsEl` {`HTMLElement | null`} - \n\n * `onEditorKeydown` - \n\n * `onSelectionChange` - ",
2957
2957
  "attributes": [
2958
2958
  {
2959
2959
  "name": "value",