@mk-kit/ui 0.34.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/LICENSE +21 -0
- package/README.md +115 -0
- package/block-editor/README.md +254 -0
- package/fesm2022/mk-kit-ui-block-editor.mjs +2158 -0
- package/fesm2022/mk-kit-ui-block-editor.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-button.mjs +81 -0
- package/fesm2022/mk-kit-ui-button.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-checkbox.mjs +136 -0
- package/fesm2022/mk-kit-ui-checkbox.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-chip.mjs +122 -0
- package/fesm2022/mk-kit-ui-chip.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-context-menu.mjs +144 -0
- package/fesm2022/mk-kit-ui-context-menu.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-core.mjs +1576 -0
- package/fesm2022/mk-kit-ui-core.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-data.mjs +6055 -0
- package/fesm2022/mk-kit-ui-data.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-datetime.mjs +3409 -0
- package/fesm2022/mk-kit-ui-datetime.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-directives.mjs +1779 -0
- package/fesm2022/mk-kit-ui-directives.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-dnd.mjs +1073 -0
- package/fesm2022/mk-kit-ui-dnd.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-feedback.mjs +2426 -0
- package/fesm2022/mk-kit-ui-feedback.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-forms.mjs +9208 -0
- package/fesm2022/mk-kit-ui-forms.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-icon.mjs +470 -0
- package/fesm2022/mk-kit-ui-icon.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-media.mjs +896 -0
- package/fesm2022/mk-kit-ui-media.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-navigation.mjs +2542 -0
- package/fesm2022/mk-kit-ui-navigation.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-rich-text.mjs +565 -0
- package/fesm2022/mk-kit-ui-rich-text.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-table.mjs +1378 -0
- package/fesm2022/mk-kit-ui-table.mjs.map +1 -0
- package/fesm2022/mk-kit-ui.mjs +32 -0
- package/fesm2022/mk-kit-ui.mjs.map +1 -0
- package/package.json +130 -0
- package/schematics/collection.json +10 -0
- package/schematics/ng-add/index.js +113 -0
- package/schematics/ng-add/schema.json +22 -0
- package/schematics/package.json +3 -0
- package/styles/mk-kit.css +750 -0
- package/types/mk-kit-ui-block-editor.d.ts +292 -0
- package/types/mk-kit-ui-button.d.ts +40 -0
- package/types/mk-kit-ui-checkbox.d.ts +62 -0
- package/types/mk-kit-ui-chip.d.ts +59 -0
- package/types/mk-kit-ui-context-menu.d.ts +57 -0
- package/types/mk-kit-ui-core.d.ts +1105 -0
- package/types/mk-kit-ui-data.d.ts +2580 -0
- package/types/mk-kit-ui-datetime.d.ts +1171 -0
- package/types/mk-kit-ui-directives.d.ts +807 -0
- package/types/mk-kit-ui-dnd.d.ts +423 -0
- package/types/mk-kit-ui-feedback.d.ts +1270 -0
- package/types/mk-kit-ui-forms.d.ts +3586 -0
- package/types/mk-kit-ui-icon.d.ts +108 -0
- package/types/mk-kit-ui-media.d.ts +549 -0
- package/types/mk-kit-ui-navigation.d.ts +1169 -0
- package/types/mk-kit-ui-rich-text.d.ts +187 -0
- package/types/mk-kit-ui-table.d.ts +739 -0
- package/types/mk-kit-ui.d.ts +17 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { OnDestroy } from '@angular/core';
|
|
3
|
+
import { ControlValueAccessor } from '@angular/forms';
|
|
4
|
+
import * as _mk_kit_ui_core from '@mk-kit/ui/core';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Rich text — a small WYSIWYG form control over a sanitised HTML string, for
|
|
8
|
+
* single "description"-style fields where the full block editor is overkill.
|
|
9
|
+
* Renders a textarea-like surface with the floating inline formatting toolbar
|
|
10
|
+
* (Bold, Italic, Underline, Strikethrough, Inline code, Link, Clear) on text
|
|
11
|
+
* selection; Enter inserts a line break.
|
|
12
|
+
*
|
|
13
|
+
* Implements `ControlValueAccessor` with a two-way `value` model, so it works
|
|
14
|
+
* with `[(ngModel)]`, reactive forms and `[(value)]`. Every value — written or
|
|
15
|
+
* emitted — passes through {@link sanitizeInlineHtml}, and a visually empty
|
|
16
|
+
* surface (whitespace / lone `<br>`s) normalises to `''` so `required`
|
|
17
|
+
* validation behaves.
|
|
18
|
+
*
|
|
19
|
+
* ```html
|
|
20
|
+
* <mk-rich-text [(ngModel)]="description" placeholder="Describe it…" />
|
|
21
|
+
* <mk-rich-text [(value)]="html" minHeight="8rem" />
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
declare class MkRichText implements ControlValueAccessor {
|
|
25
|
+
private readonly field;
|
|
26
|
+
private readonly i18n;
|
|
27
|
+
/** Two-way HTML string value (sanitised; `''` when visually empty). */
|
|
28
|
+
readonly value: _angular_core.ModelSignal<string>;
|
|
29
|
+
/** Placeholder shown when empty. */
|
|
30
|
+
readonly placeholder: _angular_core.InputSignal<string>;
|
|
31
|
+
/** Disable the control. */
|
|
32
|
+
readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
33
|
+
/** Force the invalid visual + `aria-invalid` when used standalone. */
|
|
34
|
+
readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
35
|
+
/** Minimum height of the editable area (any CSS length). */
|
|
36
|
+
readonly minHeight: _angular_core.InputSignal<string>;
|
|
37
|
+
/** Accessible label when not labelled by an `mk-form-field`. */
|
|
38
|
+
readonly ariaLabel: _angular_core.InputSignal<string>;
|
|
39
|
+
private readonly cvaDisabled;
|
|
40
|
+
private onChange;
|
|
41
|
+
private onTouched;
|
|
42
|
+
protected readonly isDisabled: _angular_core.Signal<boolean>;
|
|
43
|
+
protected readonly isInvalid: _angular_core.Signal<boolean>;
|
|
44
|
+
protected readonly labelledBy: string | null;
|
|
45
|
+
protected readonly describedBy: _angular_core.Signal<string | null>;
|
|
46
|
+
protected readonly effectiveAriaLabel: _angular_core.Signal<string>;
|
|
47
|
+
/** Sanitised view of the model, rendered into the engine. */
|
|
48
|
+
protected readonly safeHtml: _angular_core.Signal<string>;
|
|
49
|
+
/** User edit: sanitise, normalise the empty state, propagate. */
|
|
50
|
+
protected onContentChange(html: string): void;
|
|
51
|
+
protected onFocusChange(focused: boolean): void;
|
|
52
|
+
writeValue(value: unknown): void;
|
|
53
|
+
registerOnChange(fn: (value: string) => void): void;
|
|
54
|
+
registerOnTouched(fn: () => void): void;
|
|
55
|
+
setDisabledState(isDisabled: boolean): void;
|
|
56
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkRichText, never>;
|
|
57
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkRichText, "mk-rich-text", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "minHeight": { "alias": "minHeight"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Payload for a split (Enter) event: text before/after the caret. */
|
|
61
|
+
interface MkRichTextSplit {
|
|
62
|
+
before: string;
|
|
63
|
+
after: string;
|
|
64
|
+
}
|
|
65
|
+
/** A formatting command exposed by the floating toolbar. */
|
|
66
|
+
interface MkInlineTool {
|
|
67
|
+
id: string;
|
|
68
|
+
label: string;
|
|
69
|
+
icon: string;
|
|
70
|
+
shortcut?: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Rich-text engine — an accessible contenteditable surface with a floating
|
|
74
|
+
* inline formatting toolbar (Bold, Italic, Underline, Strikethrough, Inline
|
|
75
|
+
* code, Link, Clear). Built on the native Selection API +
|
|
76
|
+
* `document.execCommand` (deprecated but universally supported and
|
|
77
|
+
* dependency-free — the only practical way to do inline formatting without a
|
|
78
|
+
* heavyweight editor engine).
|
|
79
|
+
*
|
|
80
|
+
* This is the low-level building block: it emits HTML via `contentChange`, and
|
|
81
|
+
* structural intents (`splitAt`, `removeEmpty`, `arrowOut`) so a block-editor
|
|
82
|
+
* host can create, merge or navigate blocks. For a standalone form control use
|
|
83
|
+
* {@link MkRichText} (`<mk-rich-text>`), which wraps this engine in a CVA over
|
|
84
|
+
* a sanitised HTML string.
|
|
85
|
+
*/
|
|
86
|
+
declare class MkRichTextEngine implements OnDestroy {
|
|
87
|
+
private readonly document;
|
|
88
|
+
private readonly host;
|
|
89
|
+
private readonly editableRef;
|
|
90
|
+
protected readonly i18n: _mk_kit_ui_core.MkI18nStrings;
|
|
91
|
+
/** Pending toolbar-hide delay from `onBlur`; cleared on destroy. */
|
|
92
|
+
private blurTimer;
|
|
93
|
+
/** Current HTML content. */
|
|
94
|
+
readonly html: _angular_core.InputSignal<string>;
|
|
95
|
+
/** Placeholder shown when empty. */
|
|
96
|
+
readonly placeholder: _angular_core.InputSignal<string>;
|
|
97
|
+
/** Disable editing. */
|
|
98
|
+
readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
99
|
+
/** Allow soft line breaks (Shift+Enter). Plain Enter always splits. */
|
|
100
|
+
readonly multiline: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
101
|
+
/**
|
|
102
|
+
* Emit `splitAt` on Enter (block-editor hosts). When `false` — standalone
|
|
103
|
+
* field usage — Enter inserts a line break inside this surface instead.
|
|
104
|
+
*/
|
|
105
|
+
readonly splitOnEnter: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
106
|
+
/** Minimum height of the editable surface (any CSS length). */
|
|
107
|
+
readonly minHeight: _angular_core.InputSignal<string | null>;
|
|
108
|
+
/** Accessible label for the editable region. */
|
|
109
|
+
readonly ariaLabel: _angular_core.InputSignal<string>;
|
|
110
|
+
/** Id of an external label element, for `aria-labelledby`. */
|
|
111
|
+
readonly labelledBy: _angular_core.InputSignal<string | null>;
|
|
112
|
+
/** Space-separated id list for `aria-describedby`. */
|
|
113
|
+
readonly describedBy: _angular_core.InputSignal<string | null>;
|
|
114
|
+
/** Reflect an invalid state via `aria-invalid`. */
|
|
115
|
+
readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
116
|
+
/** Fired on every edit with the sanitised-by-construction HTML. */
|
|
117
|
+
readonly contentChange: _angular_core.OutputEmitterRef<string>;
|
|
118
|
+
/** Enter pressed: `before` stays in this block, `after` starts a new one. */
|
|
119
|
+
readonly splitAt: _angular_core.OutputEmitterRef<MkRichTextSplit>;
|
|
120
|
+
/** Backspace at the very start of an empty block. */
|
|
121
|
+
readonly removeEmpty: _angular_core.OutputEmitterRef<void>;
|
|
122
|
+
/** Caret tried to leave the top/bottom edge with an arrow key. */
|
|
123
|
+
readonly arrowOut: _angular_core.OutputEmitterRef<"up" | "down">;
|
|
124
|
+
/** Focus/blur bubbled so the wrapper can show selection chrome. */
|
|
125
|
+
readonly focusChange: _angular_core.OutputEmitterRef<boolean>;
|
|
126
|
+
protected readonly isEmpty: _angular_core.WritableSignal<boolean>;
|
|
127
|
+
protected readonly toolbar: _angular_core.WritableSignal<{
|
|
128
|
+
visible: boolean;
|
|
129
|
+
top: number;
|
|
130
|
+
left: number;
|
|
131
|
+
}>;
|
|
132
|
+
protected readonly activeFormats: _angular_core.WritableSignal<Set<string>>;
|
|
133
|
+
protected readonly tools: MkInlineTool[];
|
|
134
|
+
protected readonly showPlaceholder: _angular_core.Signal<boolean>;
|
|
135
|
+
constructor();
|
|
136
|
+
/** Places the caret and focuses (called by the host for navigation). */
|
|
137
|
+
focus(position?: 'start' | 'end'): void;
|
|
138
|
+
protected onInput(): void;
|
|
139
|
+
protected onFocus(): void;
|
|
140
|
+
ngOnDestroy(): void;
|
|
141
|
+
protected onBlur(): void;
|
|
142
|
+
protected onSelectionChange(): void;
|
|
143
|
+
protected onKeydown(event: KeyboardEvent): void;
|
|
144
|
+
/** Escape inside the toolbar returns focus to the text; arrows move tools. */
|
|
145
|
+
protected onToolbarKeydown(event: KeyboardEvent): void;
|
|
146
|
+
/** Runs a toolbar command, keeping the model + toolbar state in sync. */
|
|
147
|
+
protected runTool(id: string): void;
|
|
148
|
+
protected isActive(id: string): boolean;
|
|
149
|
+
private emitSplit;
|
|
150
|
+
/** Inserts a `<br>` at the caret (Enter in `splitOnEnter=false` mode). */
|
|
151
|
+
private insertLineBreak;
|
|
152
|
+
/** Extracts markup after the caret so the host can start a new block with it. */
|
|
153
|
+
private splitHtmlAtCaret;
|
|
154
|
+
private wrapInlineCode;
|
|
155
|
+
private applyLink;
|
|
156
|
+
private updateToolbar;
|
|
157
|
+
private computeEmpty;
|
|
158
|
+
private setCaret;
|
|
159
|
+
private isSelectionCollapsed;
|
|
160
|
+
private isCaretAtStart;
|
|
161
|
+
private isCaretAtEnd;
|
|
162
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkRichTextEngine, never>;
|
|
163
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkRichTextEngine, "mk-rich-text-engine", never, { "html": { "alias": "html"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "multiline": { "alias": "multiline"; "required": false; "isSignal": true; }; "splitOnEnter": { "alias": "splitOnEnter"; "required": false; "isSignal": true; }; "minHeight": { "alias": "minHeight"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "labelledBy": { "alias": "labelledBy"; "required": false; "isSignal": true; }; "describedBy": { "alias": "describedBy"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; }, { "contentChange": "contentChange"; "splitAt": "splitAt"; "removeEmpty": "removeEmpty"; "arrowOut": "arrowOut"; "focusChange": "focusChange"; }, never, never, true, never>;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Allow-list sanitiser for inline rich-text HTML — the security backbone of
|
|
168
|
+
* both `<mk-rich-text>` and the block editor's text blocks.
|
|
169
|
+
*
|
|
170
|
+
* SECURITY MODEL: rich-text surfaces store HTML authored through the editor's
|
|
171
|
+
* restricted formatting commands. Before that markup is emitted, persisted or
|
|
172
|
+
* re-rendered it is passed through {@link sanitizeInlineHtml}, an allow-list
|
|
173
|
+
* cleaner that strips scripts, event handlers and dangerous URLs. Angular's
|
|
174
|
+
* `DomSanitizer` re-sanitises at display time where applicable. This module is
|
|
175
|
+
* dependency-free so it can run on a server (SSG/SSR) — never feed its output
|
|
176
|
+
* back into `innerHTML` without sanitising again.
|
|
177
|
+
*/
|
|
178
|
+
/**
|
|
179
|
+
* Allow-list cleaner for inline rich text. Keeps a small set of formatting
|
|
180
|
+
* tags, strips everything else's tags (preserving their text), removes event
|
|
181
|
+
* handler attributes and unsafe `href`s. Not a substitute for `DomSanitizer`,
|
|
182
|
+
* but makes the serialised string safe by construction.
|
|
183
|
+
*/
|
|
184
|
+
declare function sanitizeInlineHtml(html: string): string;
|
|
185
|
+
|
|
186
|
+
export { MkRichText, MkRichTextEngine, sanitizeInlineHtml };
|
|
187
|
+
export type { MkRichTextSplit };
|