@rathkit/rte-ui 0.0.0-stage → 0.1.0-alpha.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/dist/ui.js ADDED
@@ -0,0 +1,482 @@
1
+ import { checkFields, createAnnouncer, createDialog, createMenu, createToolbar, createTooltip } from "@rathkit/rte-headless";
2
+ import { createFindBar } from "./findbar.js";
3
+ import { setIcon } from "./icon.js";
4
+ import { createShortcuts } from "./shortcuts.js";
5
+ import { createSourceView } from "./source.js";
6
+ import { text } from "./messages.js";
7
+ let counter = 0;
8
+ const sameEntries = (a, b) => {
9
+ const x = Object.entries(a ?? {});
10
+ const y = Object.entries(b ?? {});
11
+ return x.length === y.length && x.every(([k, v], i) => y[i]?.[0] === k && Object.is(y[i]?.[1], v));
12
+ };
13
+ export function createUi(editor, options) {
14
+ const { root } = options;
15
+ const slot = options.slot ?? "toolbar.main";
16
+ let style = {};
17
+ const appliedTokens = new Set();
18
+ const appliedClasses = new Map();
19
+ const parts = new Map();
20
+ const part = (el, name) => {
21
+ el.setAttribute("data-rk-part", name);
22
+ let set = parts.get(name);
23
+ if (!set)
24
+ parts.set(name, (set = new Set()));
25
+ set.add(el);
26
+ for (const cls of style.classes?.[name]?.split(/\s+/).filter(Boolean) ?? [])
27
+ el.classList.add(cls);
28
+ return el;
29
+ };
30
+ const message = (key, fallback = "", values = {}) => text(style.messages, key, fallback, values);
31
+ root.classList.add("rk-root");
32
+ part(root, "root");
33
+ const toolbarEl = part(document.createElement("div"), "toolbar");
34
+ const contentEl = part(document.createElement("div"), "content");
35
+ const statusEl = part(document.createElement("div"), "status");
36
+ root.append(toolbarEl, contentEl);
37
+ contentEl.appendChild(editor.element);
38
+ let statusTimer;
39
+ const showStatus = () => {
40
+ statusTimer = undefined;
41
+ const counts = editor.counts?.();
42
+ if (!counts)
43
+ return;
44
+ const words = counts.document.words;
45
+ statusEl.textContent = counts.selection.words > 0
46
+ ? message("status.selection", "", { selected: String(counts.selection.words), total: String(words) })
47
+ : `${message(words === 1 ? "status.word" : "status.words", "", { count: String(words) })} · ${message("status.characters", "", { count: String(counts.document.characters) })}`;
48
+ };
49
+ const findBar = editor.commands.list().some((c) => c.name === "find.set")
50
+ ? createFindBar({ editor, part: (el, name) => part(el, name), message: (key, fallback, values) => message(key, fallback, values), icon: (name) => iconFor(name), announce: (m) => announcer.announce(m) })
51
+ : undefined;
52
+ if (findBar)
53
+ root.insertBefore(findBar.element, contentEl);
54
+ const stopStatus = editor.counts && options.status !== false ? editor.subscribe(() => { statusTimer ??= setTimeout(showStatus, 150); }) : undefined;
55
+ if (stopStatus)
56
+ root.appendChild(statusEl);
57
+ const announcer = createAnnouncer(root);
58
+ const tipEl = part(document.createElement("div"), "tooltip");
59
+ root.appendChild(tipEl);
60
+ const tooltip = createTooltip({
61
+ container: root, popup: tipEl,
62
+ onShow: (target, popup) => {
63
+ const box = root.getBoundingClientRect();
64
+ const at = target.getBoundingClientRect();
65
+ popup.style.top = `${Math.round(at.bottom - box.top + 6)}px`;
66
+ popup.style.left = `${Math.round(Math.max(0, Math.min(at.left - box.left, box.width - popup.offsetWidth)))}px`;
67
+ },
68
+ });
69
+ const removeSourceItem = editor.getHtml ? editor.ui.add(slot, { kind: "panel", id: "source", name: "source", label: "HTML source", icon: "source", group: "tools", order: 1 }) : undefined;
70
+ const removeShortcutsItem = editor.ui.add(slot, { kind: "panel", id: "shortcuts", name: "shortcuts", label: "Keyboard shortcuts", icon: "keyboard", group: "tools", order: 2 });
71
+ const toolbar = createToolbar(editor, { slot, label: message("toolbar.label") });
72
+ const shortcuts = createShortcuts({ editor, root, part: (el, name) => part(el, name), message: (key) => message(key) });
73
+ const sourceView = editor.getHtml ? createSourceView({ editor, content: contentEl, toolbar: toolbarEl, part: (el, name) => part(el, name), message: (key) => message(key), announce: (m) => announcer.announce(m) }) : undefined;
74
+ const iconSpans = new Map();
75
+ const dialogs = new Map();
76
+ function applyStyle(given) {
77
+ const previous = style;
78
+ const base = options.defaults;
79
+ const next = base
80
+ ? { ...given, icons: { ...base.icons, ...given.icons }, messages: { ...base.messages, ...given.messages } }
81
+ : given;
82
+ style = next;
83
+ const set = (name, value) => (value === undefined ? root.removeAttribute(name) : root.setAttribute(name, value));
84
+ set("data-rk-theme", next.theme);
85
+ set("data-rk-scheme", next.scheme);
86
+ set("data-rk-density", next.density);
87
+ for (const name of [...appliedTokens])
88
+ if (!(next.tokens && name in next.tokens)) {
89
+ root.style.removeProperty(name);
90
+ appliedTokens.delete(name);
91
+ }
92
+ for (const [name, value] of Object.entries(next.tokens ?? {})) {
93
+ root.style.setProperty(name, value);
94
+ appliedTokens.add(name);
95
+ }
96
+ for (const [name, classes] of appliedClasses)
97
+ for (const el of parts.get(name) ?? [])
98
+ el.classList.remove(...classes);
99
+ appliedClasses.clear();
100
+ for (const [name, value] of Object.entries(next.classes ?? {})) {
101
+ const classes = value.split(/\s+/).filter(Boolean);
102
+ appliedClasses.set(name, classes);
103
+ for (const el of parts.get(name) ?? [])
104
+ el.classList.add(...classes);
105
+ }
106
+ if (!sameEntries(previous.icons, next.icons) || !sameEntries(previous.messages, next.messages) || previous.parts !== next.parts) {
107
+ draw();
108
+ findBar?.refresh();
109
+ shortcuts.refresh();
110
+ }
111
+ syncDialogs();
112
+ }
113
+ function iconFor(name) {
114
+ return name === undefined ? undefined : style.icons?.[name];
115
+ }
116
+ let unbind;
117
+ function labelOf(item) {
118
+ return message(`item.${item.id}`, toolbar.state(item.id)?.label ?? item.id);
119
+ }
120
+ function control(item) {
121
+ if (item.kind === "separator")
122
+ return part(document.createElement("span"), "separator");
123
+ if (item.kind === "panel" && item.name !== "source" && item.name !== "shortcuts")
124
+ return undefined;
125
+ const state = toolbar.state(item.id);
126
+ if (!state)
127
+ return undefined;
128
+ if (item.kind === "select") {
129
+ const select = part(document.createElement("select"), "select");
130
+ select.setAttribute("data-rk-item", item.id);
131
+ for (const o of item.options) {
132
+ const option = document.createElement("option");
133
+ option.value = String(o.value);
134
+ option.textContent = o.label;
135
+ select.appendChild(option);
136
+ }
137
+ return select;
138
+ }
139
+ if (item.kind === "menu")
140
+ return menuControl(item, state);
141
+ const customize = style.parts?.button;
142
+ if (customize) {
143
+ const el = customize({ item, state, run: (value) => toolbar.activate(item.id, value) });
144
+ el.setAttribute("data-rk-part", "button");
145
+ el.setAttribute("data-rk-item", item.id);
146
+ (parts.get("button") ?? parts.set("button", new Set()).get("button"))?.add(el);
147
+ return el;
148
+ }
149
+ const button = part(document.createElement("button"), "button");
150
+ button.type = "button";
151
+ button.setAttribute("data-rk-item", item.id);
152
+ const icon = part(document.createElement("span"), "icon");
153
+ icon.setAttribute("aria-hidden", "true");
154
+ if (setIcon(icon, iconFor(state.icon))) {
155
+ iconSpans.set(icon, state.icon ?? "");
156
+ button.appendChild(icon);
157
+ }
158
+ else {
159
+ const label = part(document.createElement("span"), "label");
160
+ label.textContent = labelOf(item);
161
+ button.appendChild(label);
162
+ }
163
+ return button;
164
+ }
165
+ const menus = [];
166
+ const menuItems = new Map();
167
+ function menuControl(item, state) {
168
+ const host = part(document.createElement("span"), "menu-host");
169
+ const trigger = part(document.createElement("button"), "button");
170
+ trigger.type = "button";
171
+ trigger.setAttribute("data-rk-item", item.id);
172
+ const icon = part(document.createElement("span"), "icon");
173
+ icon.setAttribute("aria-hidden", "true");
174
+ if (setIcon(icon, iconFor(state.icon))) {
175
+ iconSpans.set(icon, state.icon ?? "");
176
+ trigger.appendChild(icon);
177
+ }
178
+ else {
179
+ const label = part(document.createElement("span"), "label");
180
+ label.textContent = labelOf(item);
181
+ trigger.appendChild(label);
182
+ }
183
+ const caret = part(document.createElement("span"), "icon");
184
+ caret.setAttribute("aria-hidden", "true");
185
+ if (setIcon(caret, iconFor("chevron-down")))
186
+ trigger.appendChild(caret);
187
+ const popup = part(document.createElement("div"), "menu");
188
+ for (const child of item.items) {
189
+ if (child.kind === "separator") {
190
+ const rule = part(document.createElement("div"), "menu-separator");
191
+ rule.setAttribute("role", "separator");
192
+ popup.appendChild(rule);
193
+ continue;
194
+ }
195
+ if (child.kind !== "button" && child.kind !== "toggle" && child.kind !== "dialog")
196
+ continue;
197
+ menuItems.set(child.id, child);
198
+ const entry = part(document.createElement("button"), "menu-item");
199
+ entry.type = "button";
200
+ entry.setAttribute("data-rk-menuitem", "");
201
+ entry.setAttribute("data-rk-menu-item", child.id);
202
+ const words = part(document.createElement("span"), "label");
203
+ const keys = part(document.createElement("span"), "menu-keys");
204
+ if (child.kind !== "dialog" && child.swatch) {
205
+ const swatch = part(document.createElement("span"), "swatch");
206
+ swatch.setAttribute("aria-hidden", "true");
207
+ swatch.style.backgroundColor = child.swatch;
208
+ entry.append(swatch);
209
+ }
210
+ entry.append(words, keys);
211
+ popup.appendChild(entry);
212
+ }
213
+ host.append(trigger, popup);
214
+ const menu = createMenu({
215
+ trigger, menu: popup,
216
+ onOpen: () => {
217
+ popup.style.translate = "";
218
+ const box = popup.getBoundingClientRect();
219
+ const width = document.documentElement.clientWidth;
220
+ const dx = box.right > width - 4 ? width - 4 - box.right : box.left < 4 ? 4 - box.left : 0;
221
+ if (dx !== 0)
222
+ popup.style.translate = `${Math.round(dx)}px`;
223
+ },
224
+ onSelect: (entry) => {
225
+ const id = entry.getAttribute("data-rk-menu-item") ?? "";
226
+ const child = menuItems.get(id);
227
+ if (child?.kind === "dialog") {
228
+ openDialog(child, trigger);
229
+ return;
230
+ }
231
+ if (toolbar.activate(id) && child?.kind === "toggle") {
232
+ const now = toolbar.state(id);
233
+ announcer.announce(message(now?.pressed ? "toggle.on" : "toggle.off", "", { label: labelOf(child) }));
234
+ }
235
+ editor.focus();
236
+ },
237
+ });
238
+ for (const entry of popup.querySelectorAll("[data-rk-menu-item]")) {
239
+ if (menuItems.get(entry.getAttribute("data-rk-menu-item") ?? "")?.kind === "toggle")
240
+ entry.setAttribute("role", "menuitemcheckbox");
241
+ }
242
+ menus.push(menu);
243
+ return host;
244
+ }
245
+ function menuEntries() {
246
+ for (const entry of toolbarEl.querySelectorAll("[data-rk-menu-item]")) {
247
+ const id = entry.getAttribute("data-rk-menu-item") ?? "";
248
+ const child = menuItems.get(id);
249
+ const state = toolbar.state(id);
250
+ if (!child || !state)
251
+ continue;
252
+ const label = labelOf(child);
253
+ const words = entry.querySelector('[data-rk-part="label"]');
254
+ if (words)
255
+ words.textContent = label;
256
+ const keys = entry.querySelector('[data-rk-part="menu-keys"]');
257
+ if (keys)
258
+ keys.textContent = state.shortcutLabel ?? "";
259
+ if (state.shortcut)
260
+ entry.setAttribute("aria-keyshortcuts", state.shortcut);
261
+ else
262
+ entry.removeAttribute("aria-keyshortcuts");
263
+ entry.setAttribute("aria-disabled", String(state.disabled));
264
+ if (child.kind === "toggle")
265
+ entry.setAttribute("aria-checked", String(state.pressed === true));
266
+ }
267
+ }
268
+ function draw() {
269
+ unbind?.();
270
+ for (const menu of menus.splice(0))
271
+ menu.destroy();
272
+ menuItems.clear();
273
+ iconSpans.clear();
274
+ for (const name of ["button", "select", "separator", "icon", "label", "menu-host", "menu", "menu-item", "menu-separator", "menu-keys", "swatch"]) {
275
+ const kept = new Set();
276
+ for (const el of parts.get(name) ?? [])
277
+ if (!toolbarEl.contains(el))
278
+ kept.add(el);
279
+ parts.set(name, kept);
280
+ }
281
+ const controls = [];
282
+ let group;
283
+ for (const item of toolbar.items) {
284
+ const next = item.group ?? "";
285
+ if (group !== undefined && next !== group && item.kind !== "separator")
286
+ controls.push(part(document.createElement("span"), "separator"));
287
+ group = next;
288
+ const el = control(item);
289
+ if (el)
290
+ controls.push(el);
291
+ }
292
+ toolbarEl.replaceChildren(...controls);
293
+ unbind = toolbar.bind(toolbarEl, { onOpen: (item, opener) => { if (item.kind === "dialog")
294
+ openDialog(item, opener);
295
+ else if (item.kind === "panel" && item.name === "source")
296
+ sourceView?.toggle(opener);
297
+ else if (item.kind === "panel" && item.name === "shortcuts")
298
+ shortcuts.open(opener); } });
299
+ toolbarEl.removeEventListener("click", onToolbarClick);
300
+ toolbarEl.addEventListener("click", onToolbarClick);
301
+ names();
302
+ menuEntries();
303
+ }
304
+ function names() {
305
+ for (const el of toolbarEl.querySelectorAll("[data-rk-item]")) {
306
+ const id = el.getAttribute("data-rk-item") ?? "";
307
+ const item = toolbar.items.find((i) => i.id === id);
308
+ const state = toolbar.state(id);
309
+ if (!item || !state)
310
+ continue;
311
+ const label = labelOf(item);
312
+ el.setAttribute("aria-label", label);
313
+ el.setAttribute("data-rk-tip", state.shortcutLabel ? `${label} (${state.shortcutLabel})` : label);
314
+ if (el.tagName === "BUTTON") {
315
+ const word = el.querySelector('[data-rk-part="label"]');
316
+ if (word)
317
+ word.textContent = label;
318
+ }
319
+ }
320
+ }
321
+ toolbar.subscribe(names);
322
+ toolbar.subscribe(menuEntries);
323
+ const stopRedraw = toolbar.subscribe(() => {
324
+ const ids = toolbar.items.map((i) => i.id).join("\u0000");
325
+ if (ids !== drawn) {
326
+ drawn = ids;
327
+ draw();
328
+ }
329
+ });
330
+ let drawn = "";
331
+ const onToolbarClick = (e) => {
332
+ const el = e.target?.closest("[data-rk-item]");
333
+ if (!el)
334
+ return;
335
+ const item = toolbar.items.find((i) => i.id === el.getAttribute("data-rk-item"));
336
+ const state = item ? toolbar.state(item.id) : undefined;
337
+ if (item?.kind === "toggle" && state && !state.disabled) {
338
+ const group = item.group === "align" || item.group === "lists";
339
+ announcer.announce(group ? labelOf(item) : message(state.pressed ? "toggle.on" : "toggle.off", "", { label: labelOf(item) }));
340
+ }
341
+ };
342
+ function syncDialogs() {
343
+ for (const [id, d] of dialogs) {
344
+ const item = toolbar.items.find((i) => i.id === id) ?? menuItems.get(id);
345
+ if (!item || item.kind !== "dialog")
346
+ continue;
347
+ d.title.textContent = labelOf(item);
348
+ d.ok.textContent = message("dialog.ok");
349
+ d.cancel.textContent = message("dialog.cancel");
350
+ }
351
+ }
352
+ function openDialog(item, opener) {
353
+ let entry = dialogs.get(item.id);
354
+ if (!entry) {
355
+ const element = part(document.createElement("dialog"), "dialog");
356
+ const titleId = `rk-dialog-title-${++counter}`;
357
+ element.setAttribute("aria-labelledby", titleId);
358
+ const form = document.createElement("form");
359
+ form.noValidate = true;
360
+ const title = part(document.createElement("h2"), "dialog-title");
361
+ title.id = titleId;
362
+ form.appendChild(title);
363
+ for (const field of item.fields) {
364
+ const inputId = `rk-field-${++counter}`;
365
+ const label = part(document.createElement("label"), "field-label");
366
+ label.htmlFor = inputId;
367
+ label.textContent = field.label;
368
+ const input = (field.type === "choice" ? part(document.createElement("select"), "field") : part(document.createElement("input"), "field"));
369
+ input.id = inputId;
370
+ input.name = field.name;
371
+ if (field.type === "choice") {
372
+ for (const choice of field.choices ?? []) {
373
+ const option = document.createElement("option");
374
+ option.value = choice.value;
375
+ option.textContent = choice.label;
376
+ input.appendChild(option);
377
+ }
378
+ }
379
+ else {
380
+ input.type = field.type === "checkbox" ? "checkbox" : "text";
381
+ if (field.type === "url")
382
+ input.inputMode = "url";
383
+ input.autocomplete = "off";
384
+ }
385
+ if (field.required)
386
+ input.required = true;
387
+ const error = part(document.createElement("span"), "field-error");
388
+ error.setAttribute("data-rk-error", field.name);
389
+ if (field.type === "checkbox") {
390
+ const row = part(document.createElement("div"), "field-check");
391
+ row.append(input, label);
392
+ form.append(row, error);
393
+ }
394
+ else
395
+ form.append(label, input, error);
396
+ }
397
+ const actions = part(document.createElement("div"), "actions");
398
+ const ok = part(document.createElement("button"), "action");
399
+ ok.type = "submit";
400
+ ok.setAttribute("data-primary", "");
401
+ const cancel = part(document.createElement("button"), "action");
402
+ cancel.type = "button";
403
+ actions.append(cancel, ok);
404
+ form.appendChild(actions);
405
+ element.appendChild(form);
406
+ root.appendChild(element);
407
+ const from = { opener };
408
+ const dialog = createDialog({ dialog: element, editor, get opener() { return from.opener; } });
409
+ cancel.addEventListener("click", () => dialog.close("cancel"));
410
+ form.addEventListener("submit", (e) => {
411
+ e.preventDefault();
412
+ const check = checkFields(form, item.fields, { required: message("field.required", "", { label: "{label}" }), url: message("field.url") }, (m) => announcer.announce(m));
413
+ if (!check.ok)
414
+ return;
415
+ dialog.close("submit");
416
+ editor.commands.run(item.command, check.values);
417
+ });
418
+ entry = { dialog, element, form, title, ok, cancel, from };
419
+ dialogs.set(item.id, entry);
420
+ syncDialogs();
421
+ }
422
+ const current = editor.commands.state(item.command).value;
423
+ for (const f of item.fields) {
424
+ const input = entry.form.querySelector(`[name="${f.name}"]`);
425
+ if (!input)
426
+ continue;
427
+ const given = current !== null && typeof current === "object" ? current[f.name] : item.fields.length === 1 ? current : undefined;
428
+ if (f.type === "checkbox")
429
+ input.checked = given === true;
430
+ else
431
+ input.value = typeof given === "string" ? given : "";
432
+ }
433
+ for (const f of item.fields) {
434
+ const bad = entry.form.querySelector(`[name="${f.name}"]`);
435
+ bad?.removeAttribute("aria-invalid");
436
+ const err = entry.form.querySelector(`[data-rk-error="${f.name}"]`);
437
+ if (err)
438
+ err.textContent = "";
439
+ }
440
+ entry.from.opener = opener;
441
+ entry.dialog.open();
442
+ }
443
+ drawn = toolbar.items.map((i) => i.id).join("\u0000");
444
+ applyStyle(options.style ?? {});
445
+ if (stopStatus)
446
+ showStatus();
447
+ return {
448
+ root, toolbar,
449
+ setStyle: applyStyle,
450
+ announce: (m) => announcer.announce(m),
451
+ destroy() {
452
+ unbind?.();
453
+ for (const menu of menus.splice(0))
454
+ menu.destroy();
455
+ tooltip.destroy();
456
+ tipEl.remove();
457
+ stopStatus?.();
458
+ findBar?.destroy();
459
+ sourceView?.destroy();
460
+ removeSourceItem?.();
461
+ shortcuts.destroy();
462
+ removeShortcutsItem();
463
+ if (statusTimer)
464
+ clearTimeout(statusTimer);
465
+ statusEl.remove();
466
+ stopRedraw();
467
+ toolbarEl.removeEventListener("click", onToolbarClick);
468
+ for (const d of dialogs.values()) {
469
+ d.dialog.destroy();
470
+ d.element.remove();
471
+ }
472
+ announcer.destroy();
473
+ toolbar.destroy();
474
+ toolbarEl.remove();
475
+ root.classList.remove("rk-root");
476
+ for (const name of ["data-rk-theme", "data-rk-scheme", "data-rk-density", "data-rk-part"])
477
+ root.removeAttribute(name);
478
+ for (const t of appliedTokens)
479
+ root.style.removeProperty(t);
480
+ },
481
+ };
482
+ }
package/package.json CHANGED
@@ -1,6 +1,99 @@
1
1
  {
2
2
  "name": "@rathkit/rte-ui",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0-alpha.0",
4
+ "description": "The styled editor interface: a toolbar and dialogs on the headless layer, themeable with tokens, presets, icons and messages.",
5
+ "keywords": [
6
+ "rich-text",
7
+ "editor",
8
+ "wysiwyg",
9
+ "contenteditable",
10
+ "zero-dependencies",
11
+ "typescript",
12
+ "toolbar",
13
+ "theming"
14
+ ],
15
+ "license": "Apache-2.0",
16
+ "homepage": "https://rathkit.com",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/rathkit/rte.git",
20
+ "directory": "packages/rte-ui"
21
+ },
22
+ "bugs": {
23
+ "url": "https://github.com/rathkit/rte/issues"
24
+ },
25
+ "type": "module",
26
+ "sideEffects": [
27
+ "*.css"
28
+ ],
29
+ "engines": {
30
+ "node": ">=22.14.0"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public",
34
+ "provenance": true,
35
+ "tag": "next"
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "NOTICE",
40
+ "css",
41
+ "!dist/**/*.map"
42
+ ],
43
+ "exports": {
44
+ ".": {
45
+ "types": "./dist/index.d.ts",
46
+ "default": "./dist/index.js"
47
+ },
48
+ "./standard": {
49
+ "types": "./dist/standard.d.ts",
50
+ "default": "./dist/standard.js"
51
+ },
52
+ "./base.css": "./css/base.css"
53
+ },
54
+ "peerDependencies": {
55
+ "@rathkit/rte-core": ">=0.1.0-alpha.0 <0.2.0",
56
+ "@rathkit/rte-headless": ">=0.1.0-alpha.0 <0.2.0",
57
+ "@rathkit/rte-themes": ">=0.1.0-alpha.0 <0.2.0",
58
+ "@rathkit/rte-icons": ">=0.1.0-alpha.0 <0.2.0"
59
+ },
60
+ "peerDependenciesMeta": {
61
+ "@rathkit/rte-core": {
62
+ "optional": true
63
+ },
64
+ "@rathkit/rte-headless": {
65
+ "optional": true
66
+ },
67
+ "@rathkit/rte-themes": {
68
+ "optional": true
69
+ },
70
+ "@rathkit/rte-icons": {
71
+ "optional": true
72
+ }
73
+ },
74
+ "devDependencies": {
75
+ "@rathkit/rte-core": "workspace:*",
76
+ "@rathkit/rte-headless": "workspace:*",
77
+ "@rathkit/rte-themes": "workspace:*",
78
+ "@rathkit/rte-icons": "workspace:*"
79
+ },
80
+ "scripts": {
81
+ "build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json && tsc -p tsconfig.build.js.json",
82
+ "typecheck": "tsc -p tsconfig.json",
83
+ "test": "node -e \"process.exit(0)\""
84
+ },
85
+ "rathkit": {
86
+ "budgets": [
87
+ {
88
+ "name": "ui",
89
+ "entry": "dist/index.js",
90
+ "gzipKB": 25
91
+ },
92
+ {
93
+ "name": "ui with default icons",
94
+ "entry": "dist/standard.js",
95
+ "gzipKB": 30
96
+ }
97
+ ]
98
+ }
99
+ }