@aquera/nile-elements 0.1.67-beta-1.4 → 0.1.67-beta-1.6
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/demo/index.html +13 -6
- package/dist/index.js +143 -247
- package/dist/nile-rich-text-editor/nile-rich-text-editor.cjs.js +1 -1
- package/dist/nile-rich-text-editor/nile-rich-text-editor.cjs.js.map +1 -1
- package/dist/nile-rich-text-editor/nile-rich-text-editor.css.cjs.js +1 -1
- package/dist/nile-rich-text-editor/nile-rich-text-editor.css.cjs.js.map +1 -1
- package/dist/nile-rich-text-editor/nile-rich-text-editor.css.esm.js +68 -172
- package/dist/nile-rich-text-editor/nile-rich-text-editor.esm.js +1 -1
- package/dist/nile-rich-text-editor/nile-rte-select.cjs.js +1 -1
- package/dist/nile-rich-text-editor/nile-rte-select.cjs.js.map +1 -1
- package/dist/nile-rich-text-editor/nile-rte-select.esm.js +39 -39
- package/dist/nile-rich-text-editor/utils.cjs.js.map +1 -1
- package/dist/src/nile-rich-text-editor/nile-rich-text-editor.css.js +68 -172
- package/dist/src/nile-rich-text-editor/nile-rich-text-editor.css.js.map +1 -1
- package/dist/src/nile-rich-text-editor/nile-rich-text-editor.d.ts +0 -3
- package/dist/src/nile-rich-text-editor/nile-rich-text-editor.js +35 -125
- package/dist/src/nile-rich-text-editor/nile-rich-text-editor.js.map +1 -1
- package/dist/src/nile-rich-text-editor/nile-rte-select.js +62 -57
- package/dist/src/nile-rich-text-editor/nile-rte-select.js.map +1 -1
- package/dist/src/nile-rich-text-editor/rte-utils/content.d.ts +2 -0
- package/dist/src/nile-rich-text-editor/rte-utils/content.js +25 -0
- package/dist/src/nile-rich-text-editor/rte-utils/content.js.map +1 -0
- package/dist/src/nile-rich-text-editor/rte-utils/css.d.ts +1 -0
- package/dist/src/nile-rich-text-editor/rte-utils/css.js +9 -0
- package/dist/src/nile-rich-text-editor/rte-utils/css.js.map +1 -0
- package/dist/src/nile-rich-text-editor/rte-utils/dom.d.ts +2 -0
- package/dist/src/nile-rich-text-editor/rte-utils/dom.js +48 -0
- package/dist/src/nile-rich-text-editor/rte-utils/dom.js.map +1 -0
- package/dist/src/nile-rich-text-editor/rte-utils/formatting.d.ts +2 -0
- package/dist/src/nile-rich-text-editor/rte-utils/formatting.js +69 -0
- package/dist/src/nile-rich-text-editor/rte-utils/formatting.js.map +1 -0
- package/dist/src/nile-rich-text-editor/rte-utils/keys.d.ts +2 -0
- package/dist/src/nile-rich-text-editor/rte-utils/keys.js +38 -0
- package/dist/src/nile-rich-text-editor/rte-utils/keys.js.map +1 -0
- package/dist/src/nile-rich-text-editor/rte-utils/lists.d.ts +2 -0
- package/dist/src/nile-rich-text-editor/rte-utils/lists.js +28 -0
- package/dist/src/nile-rich-text-editor/rte-utils/lists.js.map +1 -0
- package/dist/src/nile-rich-text-editor/rte-utils/selection.d.ts +17 -0
- package/dist/src/nile-rich-text-editor/rte-utils/selection.js +39 -0
- package/dist/src/nile-rich-text-editor/rte-utils/selection.js.map +1 -0
- package/dist/src/nile-rich-text-editor/rte-utils/toolbar.d.ts +28 -0
- package/dist/src/nile-rich-text-editor/rte-utils/toolbar.js +161 -0
- package/dist/src/nile-rich-text-editor/rte-utils/toolbar.js.map +1 -0
- package/dist/src/nile-rich-text-editor/rte-utils/toolbarState.d.ts +13 -0
- package/dist/src/nile-rich-text-editor/rte-utils/toolbarState.js +119 -0
- package/dist/src/nile-rich-text-editor/rte-utils/toolbarState.js.map +1 -0
- package/dist/src/nile-rich-text-editor/rte-utils/vars.d.ts +1 -0
- package/dist/src/nile-rich-text-editor/rte-utils/vars.js +14 -0
- package/dist/src/nile-rich-text-editor/rte-utils/vars.js.map +1 -0
- package/dist/src/nile-rich-text-editor/utils.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/nile-rich-text-editor/nile-rich-text-editor.css.ts +68 -172
- package/src/nile-rich-text-editor/nile-rich-text-editor.ts +74 -160
- package/src/nile-rich-text-editor/nile-rte-select.ts +178 -173
- package/src/nile-rich-text-editor/utils.ts +342 -341
- package/vscode-html-custom-data.json +1 -1
@@ -1,195 +1,180 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
1
|
+
// nile-rte-select.ts
|
2
|
+
import { LitElement, html } from 'lit';
|
3
|
+
import { customElement, property, state } from 'lit/decorators.js';
|
4
|
+
|
5
|
+
type HeadingTag = 'p' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
6
|
+
type GenericOption = { value: string; label?: string; icon?: string };
|
7
|
+
type HeadingOption = { value: HeadingTag; label?: string; icon?: string };
|
8
|
+
type NormalizedOption = { value: string; label: string; icon?: string };
|
9
|
+
|
10
|
+
const HEADING_ALLOWLIST: ReadonlySet<HeadingTag> = new Set([
|
11
|
+
'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'
|
12
|
+
]);
|
13
|
+
|
14
|
+
function isHeadingTag(v: string): v is HeadingTag {
|
15
|
+
return HEADING_ALLOWLIST.has(v as HeadingTag);
|
16
|
+
}
|
17
|
+
|
18
|
+
@customElement('nile-rte-select')
|
19
|
+
export class NileRteSelect extends LitElement {
|
20
|
+
protected createRenderRoot() { return this; }
|
21
|
+
|
22
|
+
/** 'heading' | 'font' | 'align' */
|
23
|
+
@property({ type: String }) type = '';
|
24
|
+
|
25
|
+
/** JSON: [{ value, label?, icon? }, ...] (attribute-based; runtime-validated) */
|
26
|
+
@property({ type: String }) options = '[]';
|
27
|
+
|
28
|
+
/** Programmatic options (preferred for TS safety). */
|
29
|
+
@property({ attribute: false })
|
30
|
+
optionsObj?: Array<GenericOption | HeadingOption>;
|
31
|
+
|
32
|
+
/** Fallback label for trigger (e.g., "Align") */
|
33
|
+
@property({ type: String }) label = '';
|
34
|
+
|
35
|
+
@state() private selectedValue = '';
|
36
|
+
|
37
|
+
private mapAlignIcon(v: string) {
|
38
|
+
const map: Record<string,string> = {
|
39
|
+
left: 'format_align_left',
|
40
|
+
center: 'format_align_middle',
|
41
|
+
right: 'format_align_right',
|
42
|
+
justify: 'format_align_justify'
|
43
|
+
};
|
44
|
+
return map[v] || 'format_align_left';
|
16
45
|
}
|
17
46
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
47
|
+
private get parsedOptions(): NormalizedOption[] {
|
48
|
+
// Prefer programmatic options if present (gives TS compile-time checks)
|
49
|
+
const source: unknown = this.optionsObj ?? this.options;
|
50
|
+
|
51
|
+
const rawArray: any[] = (() => {
|
52
|
+
if (Array.isArray(source)) return source;
|
53
|
+
try { return JSON.parse(String(source)); } catch { return []; }
|
54
|
+
})();
|
55
|
+
|
56
|
+
// Normalize to consistent shape
|
57
|
+
let items: NormalizedOption[] = rawArray.map((o: any) => {
|
58
|
+
const value: string = o?.value ?? o;
|
59
|
+
const label: string = o?.label ?? o?.value ?? o;
|
60
|
+
const icon: string | undefined =
|
61
|
+
o?.icon ?? (this.type === 'align' ? this.mapAlignIcon(String(value)) : undefined);
|
62
|
+
return { value, label, icon };
|
63
|
+
});
|
64
|
+
|
65
|
+
// If type is heading, enforce allowlist (runtime validation)
|
66
|
+
if (this.type === 'heading') {
|
67
|
+
const before = items.length;
|
68
|
+
items = items.filter(i => isHeadingTag(i.value));
|
69
|
+
if (items.length !== before) {
|
70
|
+
}
|
71
|
+
// If current selection is invalid for heading, reset
|
72
|
+
if (this.selectedValue && !isHeadingTag(this.selectedValue)) {
|
73
|
+
this.selectedValue = '';
|
74
|
+
}
|
75
|
+
}
|
31
76
|
|
32
|
-
|
33
|
-
|
77
|
+
return items;
|
78
|
+
}
|
34
79
|
|
35
|
-
|
80
|
+
private ensureDefault() {
|
81
|
+
if (!this.selectedValue) {
|
82
|
+
const first = this.parsedOptions[0];
|
83
|
+
if (first) this.selectedValue = first.value;
|
84
|
+
}
|
85
|
+
}
|
36
86
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
right: 'format_align_right',
|
42
|
-
justify: 'format_align_justify'
|
43
|
-
};
|
44
|
-
return map[v] || 'align-left';
|
87
|
+
private onSelect(value: string) {
|
88
|
+
if (this.type === 'heading' && !isHeadingTag(value)) {
|
89
|
+
console.warn(`[nile-rte-select] Ignoring invalid heading value: ${value}`);
|
90
|
+
return;
|
45
91
|
}
|
92
|
+
this.selectedValue = value;
|
93
|
+
this.dispatchEvent(new CustomEvent('change', {
|
94
|
+
detail: value, bubbles: true, composed: true
|
95
|
+
}));
|
96
|
+
}
|
46
97
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
const rawArray: any[] = (() => {
|
52
|
-
if (Array.isArray(source)) return source;
|
53
|
-
try { return JSON.parse(String(source)); } catch { return []; }
|
54
|
-
})();
|
55
|
-
|
56
|
-
// Normalize to consistent shape
|
57
|
-
let items: NormalizedOption[] = rawArray.map((o: any) => {
|
58
|
-
const value: string = o?.value ?? o;
|
59
|
-
const label: string = o?.label ?? o?.value ?? o;
|
60
|
-
const icon: string | undefined =
|
61
|
-
o?.icon ?? (this.type === 'align' ? this.mapAlignIcon(String(value)) : undefined);
|
62
|
-
return { value, label, icon };
|
63
|
-
});
|
64
|
-
|
65
|
-
// If type is heading, enforce allowlist (runtime validation)
|
66
|
-
if (this.type === 'heading') {
|
67
|
-
const before = items.length;
|
68
|
-
items = items.filter(i => isHeadingTag(i.value));
|
69
|
-
if (items.length !== before) {
|
70
|
-
}
|
71
|
-
// If current selection is invalid for heading, reset
|
72
|
-
if (this.selectedValue && !isHeadingTag(this.selectedValue)) {
|
73
|
-
this.selectedValue = '';
|
74
|
-
}
|
75
|
-
}
|
98
|
+
connectedCallback(): void {
|
99
|
+
super.connectedCallback();
|
100
|
+
this.injectLocalStyles();
|
101
|
+
}
|
76
102
|
|
77
|
-
|
78
|
-
|
103
|
+
private injectLocalStyles() {
|
104
|
+
if (this.querySelector('style[data-rte-select-style]')) return;
|
79
105
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
106
|
+
const style = document.createElement('style');
|
107
|
+
style.setAttribute('data-rte-select-style', 'true');
|
108
|
+
style.textContent = `
|
109
|
+
nile-menu.rte-align-menu::part(menu__items-wrapper) {
|
110
|
+
display: flex;
|
84
111
|
}
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
if (this.type === 'heading' && !isHeadingTag(value)) {
|
89
|
-
console.warn(`[nile-rte-select] Ignoring invalid heading value: ${value}`);
|
90
|
-
return;
|
112
|
+
nile-menu.rte-align-menu,
|
113
|
+
nile-menu.rte-default-menu {
|
114
|
+
margin-top: 0px;
|
91
115
|
}
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
116
|
+
nile-button.rte-align-trigger::part(base),
|
117
|
+
nile-button.rte-default-trigger::part(base) {
|
118
|
+
min-width: 32px;
|
119
|
+
height: 32px;
|
120
|
+
padding: 0px 6px;
|
121
|
+
box-shadow: none;
|
122
|
+
}
|
123
|
+
nile-button.rte-align-trigger::part(base) {
|
124
|
+
|
97
125
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
126
|
+
border: none;
|
127
|
+
}
|
128
|
+
`;
|
129
|
+
this.insertBefore(style, this.firstChild);
|
130
|
+
}
|
102
131
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
style.setAttribute('data-rte-select-style', 'true');
|
108
|
-
style.textContent = `
|
109
|
-
nile-menu.rte-align-menu::part(menu__items-wrapper) {
|
110
|
-
display: flex;
|
111
|
-
}
|
112
|
-
nile-menu.rte-align-menu,
|
113
|
-
nile-menu.rte-default-menu {
|
114
|
-
margin-top: 0px;
|
115
|
-
}
|
116
|
-
nile-button.rte-align-trigger::part(base),
|
117
|
-
nile-button.rte-default-trigger::part(base) {
|
118
|
-
min-width: 32px;
|
119
|
-
height: 32px;
|
120
|
-
padding: 0px 6px;
|
121
|
-
box-shadow: none;
|
122
|
-
}
|
123
|
-
`;
|
124
|
-
this.insertBefore(style, this.firstChild);
|
125
|
-
}
|
132
|
+
render() {
|
133
|
+
const opts = this.parsedOptions;
|
134
|
+
this.ensureDefault();
|
135
|
+
const current = opts.find(o => o.value === this.selectedValue);
|
126
136
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
// ► Align: icon-only items + icon trigger
|
133
|
-
if (this.type === 'align') {
|
134
|
-
const trigger = current?.icon
|
135
|
-
? html`<nile-icon name="${current.icon}"></nile-icon>`
|
136
|
-
: (this.label || 'Align');
|
137
|
-
|
138
|
-
return html`
|
139
|
-
<nile-dropdown class="rte-align-dd">
|
140
|
-
<nile-button slot="trigger" variant="tertiary" class="rte-align-trigger">
|
141
|
-
${trigger}
|
142
|
-
</nile-button>
|
143
|
-
<nile-menu class="rte-align-menu">
|
144
|
-
${opts.map(o => html`
|
145
|
-
<nile-menu-item
|
146
|
-
class="rte-align-item"
|
147
|
-
?active=${o.value === this.selectedValue}
|
148
|
-
@click=${() => this.onSelect(o.value)}>
|
149
|
-
<nile-icon name="${o.icon}"></nile-icon>
|
150
|
-
</nile-menu-item>
|
151
|
-
`)}
|
152
|
-
</nile-menu>
|
153
|
-
</nile-dropdown>
|
154
|
-
`;
|
155
|
-
}
|
137
|
+
// ► Align: icon-only items + icon trigger
|
138
|
+
if (this.type === 'align') {
|
139
|
+
const trigger = current?.icon
|
140
|
+
? html`<nile-icon name="${current.icon}"></nile-icon>`
|
141
|
+
: (this.label || 'Align');
|
156
142
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
${o.label}
|
176
|
-
</nile-menu-item>
|
177
|
-
`)}
|
178
|
-
</nile-menu>
|
179
|
-
</nile-dropdown>
|
180
|
-
`;
|
181
|
-
}
|
143
|
+
return html`
|
144
|
+
<nile-dropdown class="rte-align-dd">
|
145
|
+
<nile-button slot="trigger" variant="tertiary" class="rte-align-trigger">
|
146
|
+
${trigger}
|
147
|
+
</nile-button>
|
148
|
+
<nile-menu class="rte-align-menu">
|
149
|
+
${opts.map(o => html`
|
150
|
+
<nile-menu-item
|
151
|
+
class="rte-align-item"
|
152
|
+
?active=${o.value === this.selectedValue}
|
153
|
+
@click=${() => this.onSelect(o.value)}>
|
154
|
+
<nile-icon name="${o.icon}"></nile-icon>
|
155
|
+
</nile-menu-item>
|
156
|
+
`)}
|
157
|
+
</nile-menu>
|
158
|
+
</nile-dropdown>
|
159
|
+
`;
|
160
|
+
}
|
182
161
|
|
183
|
-
|
184
|
-
|
162
|
+
// ► Font: show labels, preview fonts in items and trigger
|
163
|
+
if (this.type === 'font') {
|
164
|
+
const triggerText = current?.label || this.label || 'Font';
|
185
165
|
return html`
|
186
166
|
<nile-dropdown class="rte-default-dd">
|
187
|
-
<nile-button
|
167
|
+
<nile-button
|
168
|
+
slot="trigger"
|
169
|
+
variant="tertiary"
|
170
|
+
class="rte-default-trigger"
|
171
|
+
style="font-family: ${current?.value || 'inherit'}">
|
188
172
|
${triggerText} <nile-icon name="arrowdown"></nile-icon>
|
189
173
|
</nile-button>
|
190
174
|
<nile-menu class="rte-default-menu">
|
191
175
|
${opts.map(o => html`
|
192
176
|
<nile-menu-item
|
177
|
+
style="font-family: ${o.value}"
|
193
178
|
?active=${o.value === this.selectedValue}
|
194
179
|
@click=${() => this.onSelect(o.value)}>
|
195
180
|
${o.label}
|
@@ -199,10 +184,30 @@
|
|
199
184
|
</nile-dropdown>
|
200
185
|
`;
|
201
186
|
}
|
187
|
+
|
188
|
+
// ► Default (e.g., heading): text items; heading values are validated already
|
189
|
+
const triggerText = current?.label || this.label || 'Select';
|
190
|
+
return html`
|
191
|
+
<nile-dropdown class="rte-default-dd">
|
192
|
+
<nile-button slot="trigger" variant="tertiary" class="rte-default-trigger">
|
193
|
+
${triggerText} <nile-icon name="arrowdown"></nile-icon>
|
194
|
+
</nile-button>
|
195
|
+
<nile-menu class="rte-default-menu">
|
196
|
+
${opts.map(o => html`
|
197
|
+
<nile-menu-item
|
198
|
+
?active=${o.value === this.selectedValue}
|
199
|
+
@click=${() => this.onSelect(o.value)}>
|
200
|
+
${o.label}
|
201
|
+
</nile-menu-item>
|
202
|
+
`)}
|
203
|
+
</nile-menu>
|
204
|
+
</nile-dropdown>
|
205
|
+
`;
|
202
206
|
}
|
207
|
+
}
|
203
208
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
}
|
209
|
+
declare global {
|
210
|
+
interface HTMLElementTagNameMap {
|
211
|
+
'nile-rte-select': NileRteSelect;
|
208
212
|
}
|
213
|
+
}
|