@ship-ui/core 0.22.15 → 0.22.17
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/assets/mcp/components.json +213 -47
- package/bin/src/subset.ts +6 -6
- package/bin/src/utilities.ts +14 -14
- package/fesm2022/ship-ui-core-ship-a11y-keybindings.mjs +12 -86
- package/fesm2022/ship-ui-core-ship-a11y-keybindings.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-accordion.mjs +4 -3
- package/fesm2022/ship-ui-core-ship-accordion.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-alert.mjs +1 -4
- package/fesm2022/ship-ui-core-ship-alert.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-blueprint.mjs +17 -11
- package/fesm2022/ship-ui-core-ship-blueprint.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-checkbox.mjs +3 -2
- package/fesm2022/ship-ui-core-ship-checkbox.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-color-picker.mjs +66 -62
- package/fesm2022/ship-ui-core-ship-color-picker.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-datepicker.mjs +24 -16
- package/fesm2022/ship-ui-core-ship-datepicker.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-dialog.mjs +4 -0
- package/fesm2022/ship-ui-core-ship-dialog.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-editor.mjs +0 -42
- package/fesm2022/ship-ui-core-ship-editor.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-form-field.mjs +0 -1
- package/fesm2022/ship-ui-core-ship-form-field.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-kbd.mjs +0 -6
- package/fesm2022/ship-ui-core-ship-kbd.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-list-item-swipe.mjs +241 -0
- package/fesm2022/ship-ui-core-ship-list-item-swipe.mjs.map +1 -0
- package/fesm2022/ship-ui-core-ship-menu.mjs +7 -10
- package/fesm2022/ship-ui-core-ship-menu.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-popover.mjs +5 -20
- package/fesm2022/ship-ui-core-ship-popover.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-radio.mjs +3 -2
- package/fesm2022/ship-ui-core-ship-radio.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-range-slider.mjs +7 -9
- package/fesm2022/ship-ui-core-ship-range-slider.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-select.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-sidenav.mjs +2 -2
- package/fesm2022/ship-ui-core-ship-sidenav.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-sortable.mjs +262 -68
- package/fesm2022/ship-ui-core-ship-sortable.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-spotlight.mjs +0 -11
- package/fesm2022/ship-ui-core-ship-spotlight.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-stepper.mjs +1 -1
- package/fesm2022/ship-ui-core-ship-stepper.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-table.mjs +426 -23
- package/fesm2022/ship-ui-core-ship-table.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-toggle.mjs +3 -2
- package/fesm2022/ship-ui-core-ship-toggle.mjs.map +1 -1
- package/fesm2022/ship-ui-core-ship-tree.mjs +1 -9
- package/fesm2022/ship-ui-core-ship-tree.mjs.map +1 -1
- package/fesm2022/ship-ui-core.mjs +37 -53
- package/fesm2022/ship-ui-core.mjs.map +1 -1
- package/package.json +5 -1
- package/types/ship-ui-core-ship-a11y-keybindings.d.ts +0 -55
- package/types/ship-ui-core-ship-accordion.d.ts +7 -7
- package/types/ship-ui-core-ship-blueprint.d.ts +2 -1
- package/types/ship-ui-core-ship-checkbox.d.ts +2 -3
- package/types/ship-ui-core-ship-color-picker.d.ts +1 -25
- package/types/ship-ui-core-ship-datepicker.d.ts +2 -3
- package/types/ship-ui-core-ship-editor.d.ts +10 -10
- package/types/ship-ui-core-ship-list-item-swipe.d.ts +25 -0
- package/types/ship-ui-core-ship-menu.d.ts +1 -2
- package/types/ship-ui-core-ship-radio.d.ts +2 -3
- package/types/ship-ui-core-ship-range-slider.d.ts +6 -6
- package/types/ship-ui-core-ship-sortable.d.ts +31 -9
- package/types/ship-ui-core-ship-table.d.ts +12 -1
- package/types/ship-ui-core-ship-toggle.d.ts +2 -3
- package/types/ship-ui-core-ship-tree.d.ts +20 -25
- package/types/ship-ui-core.d.ts +17 -24
|
@@ -7,7 +7,6 @@ import { ShipIcon } from '@ship-ui/core/ship-icon';
|
|
|
7
7
|
import { ShipMenu } from '@ship-ui/core/ship-menu';
|
|
8
8
|
import { ShipA11yKeybindingsService } from '@ship-ui/core/ship-a11y-keybindings';
|
|
9
9
|
|
|
10
|
-
// Value Accessor Provider
|
|
11
10
|
const SHIP_EDITOR_VALUE_ACCESSOR = {
|
|
12
11
|
provide: NG_VALUE_ACCESSOR,
|
|
13
12
|
useExisting: forwardRef(() => ShipEditor),
|
|
@@ -29,11 +28,8 @@ class ShipEditor {
|
|
|
29
28
|
#maxHistorySize;
|
|
30
29
|
#isInternalDOMUpdate;
|
|
31
30
|
#typingTimeout;
|
|
32
|
-
// Image layout overlay signals
|
|
33
31
|
#selectedImage;
|
|
34
|
-
// Selection backup for inserting links/images when modal is open
|
|
35
32
|
#savedRange;
|
|
36
|
-
// Track outer changes
|
|
37
33
|
#isWriting;
|
|
38
34
|
#lastFormat;
|
|
39
35
|
constructor() {
|
|
@@ -42,7 +38,6 @@ class ShipEditor {
|
|
|
42
38
|
this.#isBrowser = isPlatformBrowser(this.#platformId);
|
|
43
39
|
this.#elementRef = inject(ElementRef);
|
|
44
40
|
this.#keybindings = inject(ShipA11yKeybindingsService);
|
|
45
|
-
// Elements
|
|
46
41
|
this.editorRef = viewChild('editorRef', /* @ts-ignore */
|
|
47
42
|
...(ngDevMode ? [{ debugName: "editorRef" }] : /* istanbul ignore next */ []));
|
|
48
43
|
this.codeEditorRef = viewChild('codeEditorRef', /* @ts-ignore */
|
|
@@ -53,7 +48,6 @@ class ShipEditor {
|
|
|
53
48
|
...(ngDevMode ? [{ debugName: "imageInput" }] : /* istanbul ignore next */ []));
|
|
54
49
|
this.linkInput = viewChild('linkInput', /* @ts-ignore */
|
|
55
50
|
...(ngDevMode ? [{ debugName: "linkInput" }] : /* istanbul ignore next */ []));
|
|
56
|
-
// Configuration inputs & model signals
|
|
57
51
|
this.value = model('', /* @ts-ignore */
|
|
58
52
|
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
59
53
|
this.format = input('html', /* @ts-ignore */
|
|
@@ -70,7 +64,6 @@ class ShipEditor {
|
|
|
70
64
|
...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
71
65
|
this.customCommands = input([], /* @ts-ignore */
|
|
72
66
|
...(ngDevMode ? [{ debugName: "customCommands" }] : /* istanbul ignore next */ []));
|
|
73
|
-
// Slash commands state signals
|
|
74
67
|
this.showSlashMenu = signal(false, /* @ts-ignore */
|
|
75
68
|
...(ngDevMode ? [{ debugName: "showSlashMenu" }] : /* istanbul ignore next */ []));
|
|
76
69
|
this.slashSearchQuery = signal('', /* @ts-ignore */
|
|
@@ -183,7 +176,6 @@ class ShipEditor {
|
|
|
183
176
|
cmd.id.toLowerCase().includes(query));
|
|
184
177
|
}, /* @ts-ignore */
|
|
185
178
|
...(ngDevMode ? [{ debugName: "filteredCommands" }] : /* istanbul ignore next */ []));
|
|
186
|
-
// Toolbar group configuration inputs
|
|
187
179
|
this.showFormats = input(true, /* @ts-ignore */
|
|
188
180
|
...(ngDevMode ? [{ debugName: "showFormats" }] : /* istanbul ignore next */ []));
|
|
189
181
|
this.showBlocks = input(true, /* @ts-ignore */
|
|
@@ -196,13 +188,11 @@ class ShipEditor {
|
|
|
196
188
|
...(ngDevMode ? [{ debugName: "showInsertions" }] : /* istanbul ignore next */ []));
|
|
197
189
|
this.showHistory = input(true, /* @ts-ignore */
|
|
198
190
|
...(ngDevMode ? [{ debugName: "showHistory" }] : /* istanbul ignore next */ []));
|
|
199
|
-
// File upload output hook & configuration
|
|
200
191
|
this.customUpload = input(false, /* @ts-ignore */
|
|
201
192
|
...(ngDevMode ? [{ debugName: "customUpload" }] : /* istanbul ignore next */ []));
|
|
202
193
|
this.imageUploadEnabled = input(true, /* @ts-ignore */
|
|
203
194
|
...(ngDevMode ? [{ debugName: "imageUploadEnabled" }] : /* istanbul ignore next */ []));
|
|
204
195
|
this.imageUpload = output();
|
|
205
|
-
// Image layout overlay signals
|
|
206
196
|
this.#selectedImage = signal(null, /* @ts-ignore */
|
|
207
197
|
...(ngDevMode ? [{ debugName: "#selectedImage" }] : /* istanbul ignore next */ []));
|
|
208
198
|
this.imgToolbarTop = signal(0, /* @ts-ignore */
|
|
@@ -213,7 +203,6 @@ class ShipEditor {
|
|
|
213
203
|
...(ngDevMode ? [{ debugName: "imgMode" }] : /* istanbul ignore next */ []));
|
|
214
204
|
this.imgSize = signal('auto', /* @ts-ignore */
|
|
215
205
|
...(ngDevMode ? [{ debugName: "imgSize" }] : /* istanbul ignore next */ []));
|
|
216
|
-
// Local state signals
|
|
217
206
|
this.viewMode = signal('design', /* @ts-ignore */
|
|
218
207
|
...(ngDevMode ? [{ debugName: "viewMode" }] : /* istanbul ignore next */ []));
|
|
219
208
|
this.isFocused = signal(false, /* @ts-ignore */
|
|
@@ -226,7 +215,6 @@ class ShipEditor {
|
|
|
226
215
|
...(ngDevMode ? [{ debugName: "rawCodeValue" }] : /* istanbul ignore next */ []));
|
|
227
216
|
this.showBlockMenu = signal(false, /* @ts-ignore */
|
|
228
217
|
...(ngDevMode ? [{ debugName: "showBlockMenu" }] : /* istanbul ignore next */ []));
|
|
229
|
-
// Toolbar active states
|
|
230
218
|
this.isBold = signal(false, /* @ts-ignore */
|
|
231
219
|
...(ngDevMode ? [{ debugName: "isBold" }] : /* istanbul ignore next */ []));
|
|
232
220
|
this.isItalic = signal(false, /* @ts-ignore */
|
|
@@ -243,28 +231,22 @@ class ShipEditor {
|
|
|
243
231
|
...(ngDevMode ? [{ debugName: "canUndo" }] : /* istanbul ignore next */ []));
|
|
244
232
|
this.canRedo = signal(false, /* @ts-ignore */
|
|
245
233
|
...(ngDevMode ? [{ debugName: "canRedo" }] : /* istanbul ignore next */ []));
|
|
246
|
-
// Selection backup for inserting links/images when modal is open
|
|
247
234
|
this.#savedRange = null;
|
|
248
|
-
// Text metrics signals
|
|
249
235
|
this.charCount = signal(0, /* @ts-ignore */
|
|
250
236
|
...(ngDevMode ? [{ debugName: "charCount" }] : /* istanbul ignore next */ []));
|
|
251
237
|
this.wordCount = signal(0, /* @ts-ignore */
|
|
252
238
|
...(ngDevMode ? [{ debugName: "wordCount" }] : /* istanbul ignore next */ []));
|
|
253
|
-
// Form accessors callbacks
|
|
254
239
|
this.onChange = () => { };
|
|
255
240
|
this.onTouched = () => { };
|
|
256
|
-
// Host CSS classes resolver
|
|
257
241
|
this.hostClasses = shipComponentClasses('editor', {
|
|
258
242
|
color: this.color,
|
|
259
243
|
variant: this.variant,
|
|
260
244
|
readonly: this.readonly,
|
|
261
245
|
});
|
|
262
|
-
// Track outer changes
|
|
263
246
|
this.#isWriting = false;
|
|
264
247
|
this.#lastFormat = null;
|
|
265
248
|
// --- IMAGE FILE HANDLING & LAYOUT OVERLAYS ---
|
|
266
249
|
this.selectedImage = this.#selectedImage.asReadonly();
|
|
267
|
-
// Auto-focus link dialog input when opened
|
|
268
250
|
effect(() => {
|
|
269
251
|
if (this.showLinkModal()) {
|
|
270
252
|
const linkInput = this.linkInput();
|
|
@@ -273,7 +255,6 @@ class ShipEditor {
|
|
|
273
255
|
}
|
|
274
256
|
}
|
|
275
257
|
});
|
|
276
|
-
// Auto-focus image dialog elements when opened based on configuration
|
|
277
258
|
effect(() => {
|
|
278
259
|
if (this.showImageModal()) {
|
|
279
260
|
const uploadBtn = this.uploadBtn();
|
|
@@ -290,12 +271,9 @@ class ShipEditor {
|
|
|
290
271
|
}
|
|
291
272
|
}
|
|
292
273
|
});
|
|
293
|
-
// Keep DOM inside editor in sync with value model changes reactively (when written from parent)
|
|
294
274
|
effect(() => {
|
|
295
275
|
const val = this.value();
|
|
296
276
|
const editor = this.editorRef()?.nativeElement;
|
|
297
|
-
// If the DOM element itself has changed (re-created during HMR), we must reset
|
|
298
|
-
// lastValueWrittenFromDOM to force content initialization onto the new element.
|
|
299
277
|
if (editor && editor !== this.#lastEditorElement) {
|
|
300
278
|
this.#lastEditorElement = editor;
|
|
301
279
|
this.#lastValueWrittenFromDOM = undefined;
|
|
@@ -304,14 +282,12 @@ class ShipEditor {
|
|
|
304
282
|
return;
|
|
305
283
|
this.#syncModelToDOM(val);
|
|
306
284
|
});
|
|
307
|
-
// React to format changes by converting the model value to the new format reactively
|
|
308
285
|
effect(() => {
|
|
309
286
|
const fmt = this.format();
|
|
310
287
|
const prev = this.#lastFormat;
|
|
311
288
|
this.#lastFormat = fmt;
|
|
312
289
|
if (prev !== null && prev !== fmt) {
|
|
313
290
|
const val = this.value();
|
|
314
|
-
// 1. Convert current value in prev format to HTML
|
|
315
291
|
let html = '';
|
|
316
292
|
if (prev === 'html' && typeof val === 'string') {
|
|
317
293
|
html = val;
|
|
@@ -322,7 +298,6 @@ class ShipEditor {
|
|
|
322
298
|
else if (prev === 'json' && Array.isArray(val)) {
|
|
323
299
|
html = this.#jsonToHTML(val);
|
|
324
300
|
}
|
|
325
|
-
// 2. Convert HTML to the new format
|
|
326
301
|
let newValue = '';
|
|
327
302
|
if (fmt === 'html') {
|
|
328
303
|
newValue = html;
|
|
@@ -333,7 +308,6 @@ class ShipEditor {
|
|
|
333
308
|
else if (fmt === 'json') {
|
|
334
309
|
newValue = this.#htmlToJSON(html);
|
|
335
310
|
}
|
|
336
|
-
// 3. Update the model and DOM
|
|
337
311
|
this.#isWriting = true;
|
|
338
312
|
this.value.set(newValue);
|
|
339
313
|
this.#lastValueWrittenFromDOM = newValue;
|
|
@@ -359,7 +333,6 @@ class ShipEditor {
|
|
|
359
333
|
this.#isWriting = false;
|
|
360
334
|
}
|
|
361
335
|
});
|
|
362
|
-
// Recalculate metrics whenever raw content updates
|
|
363
336
|
effect(() => {
|
|
364
337
|
const val = this.value();
|
|
365
338
|
const fmt = this.format();
|
|
@@ -384,7 +357,6 @@ class ShipEditor {
|
|
|
384
357
|
this.charCount.set(text.length);
|
|
385
358
|
this.wordCount.set(text === '' ? 0 : text.split(/\s+/).filter((w) => w.length > 0).length);
|
|
386
359
|
});
|
|
387
|
-
// Reinitialize toolbar tabindexes when visibility inputs change
|
|
388
360
|
effect(() => {
|
|
389
361
|
this.showFormats();
|
|
390
362
|
this.showBlocks();
|
|
@@ -398,7 +370,6 @@ class ShipEditor {
|
|
|
398
370
|
});
|
|
399
371
|
}
|
|
400
372
|
ngOnInit() {
|
|
401
|
-
// Empty hook
|
|
402
373
|
}
|
|
403
374
|
ngAfterViewInit() {
|
|
404
375
|
this.#syncModelToDOM(this.value());
|
|
@@ -409,7 +380,6 @@ class ShipEditor {
|
|
|
409
380
|
clearTimeout(this.#typingTimeout);
|
|
410
381
|
}
|
|
411
382
|
}
|
|
412
|
-
// --- CONTROL VALUE ACCESSOR ---
|
|
413
383
|
writeValue(obj) {
|
|
414
384
|
this.#isWriting = true;
|
|
415
385
|
this.value.set(obj);
|
|
@@ -423,9 +393,7 @@ class ShipEditor {
|
|
|
423
393
|
this.onTouched = fn;
|
|
424
394
|
}
|
|
425
395
|
setDisabledState(isDisabled) {
|
|
426
|
-
// In Angular forms, this matches readonly
|
|
427
396
|
}
|
|
428
|
-
// --- MODEL TO DOM SYNCING ---
|
|
429
397
|
#syncModelToDOM(val) {
|
|
430
398
|
let html = '';
|
|
431
399
|
if (val === null || val === undefined || val === '') {
|
|
@@ -446,7 +414,6 @@ class ShipEditor {
|
|
|
446
414
|
html = '<p><br></p>';
|
|
447
415
|
}
|
|
448
416
|
const isNewValue = val !== this.#lastValueWrittenFromDOM;
|
|
449
|
-
// Set code editor value
|
|
450
417
|
if (this.format() === 'markdown' && typeof val === 'string') {
|
|
451
418
|
this.rawCodeValue.set(val);
|
|
452
419
|
}
|
|
@@ -456,11 +423,9 @@ class ShipEditor {
|
|
|
456
423
|
else {
|
|
457
424
|
this.rawCodeValue.set(html);
|
|
458
425
|
}
|
|
459
|
-
// Update WYSIWYG editor surface if in design mode
|
|
460
426
|
const editor = this.editorRef()?.nativeElement;
|
|
461
427
|
if (editor) {
|
|
462
428
|
this.#lastValueWrittenFromDOM = val;
|
|
463
|
-
// Avoid resetting selection if html content is equivalent
|
|
464
429
|
const normalizedHTML = html === '<p><br></p>' ? '' : html;
|
|
465
430
|
const currentNormalized = editor.innerHTML === '<p><br></p>' ? '' : editor.innerHTML;
|
|
466
431
|
if (normalizedHTML !== currentNormalized) {
|
|
@@ -477,13 +442,11 @@ class ShipEditor {
|
|
|
477
442
|
}
|
|
478
443
|
this.#updateHistoryStates();
|
|
479
444
|
}
|
|
480
|
-
// --- DOM TO MODEL SYNCING ---
|
|
481
445
|
#updateValueFromDOM() {
|
|
482
446
|
const editor = this.editorRef()?.nativeElement;
|
|
483
447
|
if (!editor)
|
|
484
448
|
return;
|
|
485
449
|
let html = editor.innerHTML;
|
|
486
|
-
// Normalize empty editor contents to empty string or basic paragraph
|
|
487
450
|
if (html === '' || html === '<br>' || html === '<p><br></p>') {
|
|
488
451
|
html = '';
|
|
489
452
|
}
|
|
@@ -510,11 +473,9 @@ class ShipEditor {
|
|
|
510
473
|
}
|
|
511
474
|
this.#isWriting = false;
|
|
512
475
|
}
|
|
513
|
-
// --- COMPONENT HANDLERS ---
|
|
514
476
|
onDOMInput() {
|
|
515
477
|
this.#ensureImagesFocusable();
|
|
516
478
|
this.#updateValueFromDOM();
|
|
517
|
-
// Debounce history save on typing (500ms) or save immediately on word/sentence boundaries
|
|
518
479
|
const selection = window.getSelection();
|
|
519
480
|
let saveImmediately = false;
|
|
520
481
|
if (selection && selection.rangeCount > 0) {
|
|
@@ -568,13 +529,11 @@ class ShipEditor {
|
|
|
568
529
|
this.onChange(parsed);
|
|
569
530
|
}
|
|
570
531
|
catch (e) {
|
|
571
|
-
// invalid JSON, do not update model, let user fix it
|
|
572
532
|
}
|
|
573
533
|
}
|
|
574
534
|
this.#isWriting = false;
|
|
575
535
|
this.onTouched();
|
|
576
536
|
}
|
|
577
|
-
// --- SELECTION STATE & COMMANDS ---
|
|
578
537
|
formatText(command, value = '') {
|
|
579
538
|
if (this.readonly())
|
|
580
539
|
return;
|
|
@@ -764,7 +723,6 @@ class ShipEditor {
|
|
|
764
723
|
selection.addRange(newRange);
|
|
765
724
|
}
|
|
766
725
|
catch (e) {
|
|
767
|
-
// Fallback
|
|
768
726
|
}
|
|
769
727
|
}
|
|
770
728
|
this.#updateValueFromDOM();
|