@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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -0
  3. package/block-editor/README.md +254 -0
  4. package/fesm2022/mk-kit-ui-block-editor.mjs +2158 -0
  5. package/fesm2022/mk-kit-ui-block-editor.mjs.map +1 -0
  6. package/fesm2022/mk-kit-ui-button.mjs +81 -0
  7. package/fesm2022/mk-kit-ui-button.mjs.map +1 -0
  8. package/fesm2022/mk-kit-ui-checkbox.mjs +136 -0
  9. package/fesm2022/mk-kit-ui-checkbox.mjs.map +1 -0
  10. package/fesm2022/mk-kit-ui-chip.mjs +122 -0
  11. package/fesm2022/mk-kit-ui-chip.mjs.map +1 -0
  12. package/fesm2022/mk-kit-ui-context-menu.mjs +144 -0
  13. package/fesm2022/mk-kit-ui-context-menu.mjs.map +1 -0
  14. package/fesm2022/mk-kit-ui-core.mjs +1576 -0
  15. package/fesm2022/mk-kit-ui-core.mjs.map +1 -0
  16. package/fesm2022/mk-kit-ui-data.mjs +6055 -0
  17. package/fesm2022/mk-kit-ui-data.mjs.map +1 -0
  18. package/fesm2022/mk-kit-ui-datetime.mjs +3409 -0
  19. package/fesm2022/mk-kit-ui-datetime.mjs.map +1 -0
  20. package/fesm2022/mk-kit-ui-directives.mjs +1779 -0
  21. package/fesm2022/mk-kit-ui-directives.mjs.map +1 -0
  22. package/fesm2022/mk-kit-ui-dnd.mjs +1073 -0
  23. package/fesm2022/mk-kit-ui-dnd.mjs.map +1 -0
  24. package/fesm2022/mk-kit-ui-feedback.mjs +2426 -0
  25. package/fesm2022/mk-kit-ui-feedback.mjs.map +1 -0
  26. package/fesm2022/mk-kit-ui-forms.mjs +9208 -0
  27. package/fesm2022/mk-kit-ui-forms.mjs.map +1 -0
  28. package/fesm2022/mk-kit-ui-icon.mjs +470 -0
  29. package/fesm2022/mk-kit-ui-icon.mjs.map +1 -0
  30. package/fesm2022/mk-kit-ui-media.mjs +896 -0
  31. package/fesm2022/mk-kit-ui-media.mjs.map +1 -0
  32. package/fesm2022/mk-kit-ui-navigation.mjs +2542 -0
  33. package/fesm2022/mk-kit-ui-navigation.mjs.map +1 -0
  34. package/fesm2022/mk-kit-ui-rich-text.mjs +565 -0
  35. package/fesm2022/mk-kit-ui-rich-text.mjs.map +1 -0
  36. package/fesm2022/mk-kit-ui-table.mjs +1378 -0
  37. package/fesm2022/mk-kit-ui-table.mjs.map +1 -0
  38. package/fesm2022/mk-kit-ui.mjs +32 -0
  39. package/fesm2022/mk-kit-ui.mjs.map +1 -0
  40. package/package.json +130 -0
  41. package/schematics/collection.json +10 -0
  42. package/schematics/ng-add/index.js +113 -0
  43. package/schematics/ng-add/schema.json +22 -0
  44. package/schematics/package.json +3 -0
  45. package/styles/mk-kit.css +750 -0
  46. package/types/mk-kit-ui-block-editor.d.ts +292 -0
  47. package/types/mk-kit-ui-button.d.ts +40 -0
  48. package/types/mk-kit-ui-checkbox.d.ts +62 -0
  49. package/types/mk-kit-ui-chip.d.ts +59 -0
  50. package/types/mk-kit-ui-context-menu.d.ts +57 -0
  51. package/types/mk-kit-ui-core.d.ts +1105 -0
  52. package/types/mk-kit-ui-data.d.ts +2580 -0
  53. package/types/mk-kit-ui-datetime.d.ts +1171 -0
  54. package/types/mk-kit-ui-directives.d.ts +807 -0
  55. package/types/mk-kit-ui-dnd.d.ts +423 -0
  56. package/types/mk-kit-ui-feedback.d.ts +1270 -0
  57. package/types/mk-kit-ui-forms.d.ts +3586 -0
  58. package/types/mk-kit-ui-icon.d.ts +108 -0
  59. package/types/mk-kit-ui-media.d.ts +549 -0
  60. package/types/mk-kit-ui-navigation.d.ts +1169 -0
  61. package/types/mk-kit-ui-rich-text.d.ts +187 -0
  62. package/types/mk-kit-ui-table.d.ts +739 -0
  63. package/types/mk-kit-ui.d.ts +17 -0
@@ -0,0 +1,292 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { InjectionToken } from '@angular/core';
3
+ import * as _mk_kit_ui_core from '@mk-kit/ui/core';
4
+ import { ControlValueAccessor } from '@angular/forms';
5
+ import { SafeResourceUrl } from '@angular/platform-browser';
6
+ export { sanitizeInlineHtml } from '@mk-kit/ui/rich-text';
7
+
8
+ /**
9
+ * Block document model for the mk-kit block editor.
10
+ *
11
+ * The model is deliberately small and 100% JSON-serialisable so a document can
12
+ * be persisted to a database, sent over the wire, and re-hydrated without any
13
+ * class instances or functions. All editor state lives in these plain objects.
14
+ */
15
+ /**
16
+ * A single content block.
17
+ *
18
+ * `type` keys into the {@link MkBlockDefinition} registry that knows how to
19
+ * edit, serialise and render it. `data` is a free-form, JSON-safe bag of the
20
+ * block's own state (e.g. `{ html }` for a paragraph, `{ src, alt }` for an
21
+ * image). `children` enables nested layout blocks (a Columns block stores its
22
+ * columns' contents here).
23
+ */
24
+ interface MkBlock {
25
+ /** Stable unique id (used for keying, focus and drag/move). */
26
+ id: string;
27
+ /** Registry type key, e.g. `paragraph`, `heading`, `columns`. */
28
+ type: string;
29
+ /** JSON-serialisable per-block state. */
30
+ data: Record<string, any>;
31
+ /** Nested blocks for layout/container blocks (e.g. columns). */
32
+ children?: MkBlock[];
33
+ }
34
+ /** A full editor document: a version stamp plus an ordered list of blocks. */
35
+ interface MkBlockDocument {
36
+ /** Schema version, bumped when the persisted shape changes. */
37
+ version: number;
38
+ /** Top-level blocks, in document order. */
39
+ blocks: MkBlock[];
40
+ }
41
+ /** Current document schema version. */
42
+ declare const MK_BLOCK_DOCUMENT_VERSION = 1;
43
+ /** An empty, valid document. */
44
+ declare function mkEmptyDocument(): MkBlockDocument;
45
+ /**
46
+ * Generates a reasonably unique, JSON-safe block id. Combines a monotonic
47
+ * counter with a short random suffix so ids are unique even across documents
48
+ * merged at runtime.
49
+ */
50
+ declare function mkBlockId(prefix?: string): string;
51
+ /** Deep-clones a block (and its subtree), assigning fresh ids. */
52
+ declare function mkCloneBlock(block: MkBlock): MkBlock;
53
+
54
+ /**
55
+ * Describes one registerable block type — the extensibility layer of the
56
+ * editor. Mirrors Gutenberg's `registerBlockType`: consumers supply an array of
57
+ * these (via the `blocks` input or the {@link MK_BLOCK_DEFINITIONS} token) to
58
+ * add, remove or reconfigure the palette. The built-in set is
59
+ * {@link MK_DEFAULT_BLOCKS}.
60
+ */
61
+ interface MkBlockDefinition {
62
+ /** Unique type key that {@link MkBlock.type} references. */
63
+ type: string;
64
+ /** Human label shown in the inserter and block toolbar. */
65
+ label: string;
66
+ /** Optional icon (emoji or short text glyph) shown in the inserter. */
67
+ icon?: string;
68
+ /** Inserter grouping heading, e.g. `Text`, `Media`, `Layout`. */
69
+ group?: string;
70
+ /** Short description shown in the inserter. */
71
+ description?: string;
72
+ /** Factory returning a fresh, ready-to-edit block of this type. */
73
+ create(): MkBlock;
74
+ /** May this block be placed inside a Columns column? Default `true`. */
75
+ allowedInColumns?: boolean;
76
+ /** Keywords to match against when filtering the inserter. */
77
+ keywords?: string[];
78
+ /** Block types this one can transform into (by type key). */
79
+ transforms?: string[];
80
+ }
81
+ /**
82
+ * The default palette of built-in block definitions. Grouped for the inserter.
83
+ * Consumers can spread this and append custom definitions, or replace it.
84
+ *
85
+ * The English `label`/`group`/`description` text here is only a base: the
86
+ * editor resolves the built-in types' display text from the `blockEditor`
87
+ * i18n strings (see `provideMkI18n`) before merging custom definitions.
88
+ */
89
+ declare const MK_DEFAULT_BLOCKS: MkBlockDefinition[];
90
+ /**
91
+ * Multi-provider injection token for adding block definitions app-wide. Each
92
+ * provided array is merged over {@link MK_DEFAULT_BLOCKS} (by `type`). The
93
+ * editor's `blocks` input takes final precedence.
94
+ *
95
+ * ```ts
96
+ * providers: [
97
+ * { provide: MK_BLOCK_DEFINITIONS, multi: true, useValue: [myCalloutBlock] },
98
+ * ]
99
+ * ```
100
+ */
101
+ declare const MK_BLOCK_DEFINITIONS: InjectionToken<MkBlockDefinition[][]>;
102
+ /**
103
+ * Async handler that persists an uploaded {@link File} and resolves to its URL.
104
+ * Provide app-wide via this token, or per-editor via the `uploadHandler` input.
105
+ * When absent, the Image block falls back to an inline `data:` URL.
106
+ */
107
+ type MkBlockUploadHandler = (file: File) => Promise<string>;
108
+ /** App-wide upload handler token (overridable by the editor's input). */
109
+ declare const MK_BLOCK_UPLOAD_HANDLER: InjectionToken<MkBlockUploadHandler>;
110
+ /**
111
+ * An allow-listed embed provider. `test` matches a pasted URL; `toEmbedUrl`
112
+ * returns the safe iframe `src` (which is the ONLY value ever passed to
113
+ * `DomSanitizer.bypassSecurityTrustResourceUrl`). Non-matching URLs fall back
114
+ * to a plain link card — raw HTML is never injected.
115
+ */
116
+ interface MkEmbedProvider {
117
+ /** Display name, e.g. `YouTube`. */
118
+ name: string;
119
+ /** Matches URLs this provider handles. */
120
+ test: RegExp;
121
+ /** Transforms a matched page URL into an embeddable iframe `src`. */
122
+ toEmbedUrl(url: string): string | null;
123
+ /** Aspect ratio `width / height` for the responsive frame. Default 16/9. */
124
+ aspectRatio?: number;
125
+ /** Allow list for the iframe `sandbox` attribute. */
126
+ sandbox?: string;
127
+ }
128
+ /** Default embed providers: YouTube + Vimeo. */
129
+ declare const MK_DEFAULT_EMBED_PROVIDERS: MkEmbedProvider[];
130
+ /** App-wide embed providers token (merged with the editor's input). */
131
+ declare const MK_BLOCK_EMBED_PROVIDERS: InjectionToken<MkEmbedProvider[][]>;
132
+ /**
133
+ * Merges default definitions with app-token definitions and per-editor input,
134
+ * de-duplicating by `type` (later sources win).
135
+ */
136
+ declare function mkMergeBlockDefinitions(defaults: MkBlockDefinition[], ...sources: (MkBlockDefinition[] | null | undefined)[]): MkBlockDefinition[];
137
+
138
+ /** How the form/CVA value is exchanged: a document object or an HTML string. */
139
+ type MkBlockValueFormat = 'document' | 'html';
140
+ /**
141
+ * Block editor — a configurable, Gutenberg-style block content editor. Renders
142
+ * an ordered document of blocks (paragraph, heading, image, columns, embed,
143
+ * list, quote, button, divider, code) with a filterable inserter, per-block
144
+ * chrome (move/duplicate/transform/delete) and inline rich-text formatting.
145
+ *
146
+ * The palette is fully customisable: pass definitions via the `blocks` input or
147
+ * the {@link MK_BLOCK_DEFINITIONS} token (mirrors `registerBlockType`). Both are
148
+ * merged over {@link MK_DEFAULT_BLOCKS}.
149
+ *
150
+ * Implements `ControlValueAccessor` AND a two-way `value` model, so it works
151
+ * with `[(ngModel)]`, reactive forms and `[(value)]`.
152
+ *
153
+ * ```html
154
+ * <mk-block-editor [(value)]="doc" [uploadHandler]="upload" />
155
+ * ```
156
+ */
157
+ declare class MkBlockEditor implements ControlValueAccessor {
158
+ protected readonly i18n: _mk_kit_ui_core.MkI18nStrings;
159
+ private readonly ctx;
160
+ private readonly hostRef;
161
+ private readonly tokenDefinitions;
162
+ private readonly tokenUpload;
163
+ private readonly tokenEmbeds;
164
+ /** Two-way document value (always an `MkBlockDocument`, regardless of format). */
165
+ readonly value: _angular_core.ModelSignal<MkBlockDocument>;
166
+ /**
167
+ * Form/CVA exchange format. `document` (default) reads/writes an
168
+ * `MkBlockDocument`; `html` reads/writes an **HTML string** — so the editor
169
+ * can back a string-typed richtext field (`[(ngModel)]="htmlString"`). The
170
+ * two-way `value` model stays an `MkBlockDocument` either way.
171
+ */
172
+ readonly valueFormat: _angular_core.InputSignal<MkBlockValueFormat>;
173
+ /** Custom / extended block definitions (merged over the defaults + token). */
174
+ readonly blocks: _angular_core.InputSignal<MkBlockDefinition[] | null>;
175
+ /** Placeholder for empty text blocks. */
176
+ readonly placeholder: _angular_core.InputSignal<string>;
177
+ /** Accessible label for the editor region. */
178
+ readonly ariaLabel: _angular_core.InputSignal<string>;
179
+ /** Read-only: renders content without editing chrome. */
180
+ readonly readonly: _angular_core.InputSignalWithTransform<boolean, unknown>;
181
+ /** Disabled (form-level). */
182
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
183
+ /** Force the invalid visual + `aria-invalid` when used standalone. */
184
+ readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
185
+ /** Async upload handler (overrides the {@link MK_BLOCK_UPLOAD_HANDLER} token). */
186
+ readonly uploadHandler: _angular_core.InputSignal<MkBlockUploadHandler | null>;
187
+ /** Extra embed providers (merged with defaults + token). */
188
+ readonly embedProviders: _angular_core.InputSignal<MkEmbedProvider[] | null>;
189
+ /** Fires on any document change (in addition to the `value` model). */
190
+ readonly change: _angular_core.OutputEmitterRef<MkBlockDocument>;
191
+ /** Fires the serialised HTML on any change — convenient in `html` mode. */
192
+ readonly htmlChange: _angular_core.OutputEmitterRef<string>;
193
+ protected readonly cvaDisabled: _angular_core.WritableSignal<boolean>;
194
+ /** Invalid visual, forced by the `invalid` input. */
195
+ protected readonly isInvalid: _angular_core.Signal<boolean>;
196
+ private onChange;
197
+ private onTouched;
198
+ /** Effective, merged block definitions (defaults localised via MK_I18N). */
199
+ private readonly definitions;
200
+ protected readonly topBlocks: _angular_core.Signal<MkBlock[]>;
201
+ constructor();
202
+ protected onBlocksChange(blocks: MkBlock[]): void;
203
+ /**
204
+ * Marks the control touched once focus leaves it entirely, so a form that
205
+ * gates its errors on `touched` behaves the same here as on a native input.
206
+ */
207
+ protected onFocusOut(event: FocusEvent): void;
208
+ writeValue(value: MkBlockDocument | string | null): void;
209
+ registerOnChange(fn: (value: MkBlockDocument | string) => void): void;
210
+ registerOnTouched(fn: () => void): void;
211
+ setDisabledState(isDisabled: boolean): void;
212
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkBlockEditor, never>;
213
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkBlockEditor, "mk-block-editor", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "valueFormat": { "alias": "valueFormat"; "required": false; "isSignal": true; }; "blocks": { "alias": "blocks"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "uploadHandler": { "alias": "uploadHandler"; "required": false; "isSignal": true; }; "embedProviders": { "alias": "embedProviders"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "change": "change"; "htmlChange": "htmlChange"; }, never, never, true, never>;
214
+ }
215
+
216
+ /**
217
+ * Block renderer — read-only, themed display of a {@link MkBlockDocument} for
218
+ * published content pages and blog posts. Reuses the same layout CSS as the
219
+ * editor so authored columns look identical when published.
220
+ *
221
+ * SECURITY MODEL: rich-text HTML is passed through {@link sanitizeInlineHtml}
222
+ * and then bound with `[innerHTML]`, so Angular's `DomSanitizer` sanitises it
223
+ * again at render time (never bypassed for author HTML). The ONLY bypass is for
224
+ * a stored embed's `embedUrl`, which came from an allow-listed provider.
225
+ */
226
+ declare class MkBlockRenderer {
227
+ protected readonly i18n: _mk_kit_ui_core.MkI18nStrings;
228
+ private readonly sanitizer;
229
+ private readonly safeSrcCache;
230
+ /** The document to render. */
231
+ readonly value: _angular_core.InputSignal<MkBlockDocument | null>;
232
+ /** Internal: a block subtree (used when recursing into columns). */
233
+ readonly blocks: _angular_core.InputSignal<MkBlock[] | null>;
234
+ protected readonly items: _angular_core.Signal<MkBlock[]>;
235
+ /** Sanitised rich-text HTML for `[innerHTML]` binding. */
236
+ protected safeHtml(html: unknown): string;
237
+ protected listItems(block: MkBlock): string[];
238
+ protected headingLevel(block: MkBlock): number;
239
+ protected isImageSafe(block: MkBlock): boolean;
240
+ protected buttonHref(block: MkBlock): string;
241
+ protected paddingTop(block: MkBlock): string;
242
+ /** Trusts only a provider-transformed https embed URL — see class doc. */
243
+ protected embedSrc(block: MkBlock): SafeResourceUrl | null;
244
+ protected fallbackUrl(block: MkBlock): string | null;
245
+ protected gridColumns(block: MkBlock): string;
246
+ protected gridGap(block: MkBlock): string;
247
+ protected justifyValue(block: MkBlock): string;
248
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkBlockRenderer, never>;
249
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkBlockRenderer, "mk-block-renderer", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "blocks": { "alias": "blocks"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
250
+ }
251
+
252
+ /** Escapes text for safe placement in element content. */
253
+ declare function mkEscapeHtml(value: string): string;
254
+ /** Escapes a value for safe placement in a double-quoted attribute. */
255
+ declare function mkEscapeAttr(value: string): string;
256
+ /** True for URL schemes safe to place in `href`/`src`. */
257
+ declare function mkIsSafeUrl(url: string): boolean;
258
+ /**
259
+ * Serialises a document to clean, semantic, self-contained HTML — the "rich
260
+ * HTML content" you persist and publish for a blog post or content page.
261
+ * Layout blocks become responsive grid wrappers with inline styles.
262
+ */
263
+ declare function mkBlocksToHtml(doc: MkBlockDocument | null | undefined): string;
264
+ /**
265
+ * Serialises a document to plain text — handy for previews, excerpts, search
266
+ * indexes and meta descriptions.
267
+ */
268
+ declare function mkBlocksToText(doc: MkBlockDocument | null | undefined): string;
269
+
270
+ /**
271
+ * HTML → {@link MkBlockDocument} parser — the inverse of {@link mkBlocksToHtml}.
272
+ *
273
+ * Lets the block editor back a **string-typed richtext field** (e.g. a CMS
274
+ * `richtext` column that stores an HTML string): seed the editor from stored
275
+ * HTML, and serialise back to HTML on change. Best-effort and forgiving — any
276
+ * HTML parses, with unrecognised block-level wrappers recursed into and loose
277
+ * inline runs grouped into paragraphs. Round-trips the blocks `mkBlocksToHtml`
278
+ * emits (paragraph, heading, list, quote, code, image, divider, button, embed,
279
+ * columns).
280
+ *
281
+ * Uses the DOM (`DOMParser`) — available in browsers and jsdom. In a pure Node
282
+ * context without a DOM it falls back to a single sanitised paragraph.
283
+ */
284
+
285
+ /**
286
+ * Parse an HTML string into a {@link MkBlockDocument}. Empty / whitespace input
287
+ * yields an empty document.
288
+ */
289
+ declare function mkHtmlToBlocks(html: string): MkBlockDocument;
290
+
291
+ export { MK_BLOCK_DEFINITIONS, MK_BLOCK_DOCUMENT_VERSION, MK_BLOCK_EMBED_PROVIDERS, MK_BLOCK_UPLOAD_HANDLER, MK_DEFAULT_BLOCKS, MK_DEFAULT_EMBED_PROVIDERS, MkBlockEditor, MkBlockRenderer, mkBlockId, mkBlocksToHtml, mkBlocksToText, mkCloneBlock, mkEmptyDocument, mkEscapeAttr, mkEscapeHtml, mkHtmlToBlocks, mkIsSafeUrl, mkMergeBlockDefinitions };
292
+ export type { MkBlock, MkBlockDefinition, MkBlockDocument, MkBlockUploadHandler, MkBlockValueFormat, MkEmbedProvider };
@@ -0,0 +1,40 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { MkVariant, MkTone, MkSize } from '@mk-kit/ui/core';
3
+
4
+ /**
5
+ * Button — enhances a native `<button>` or `<a>` so semantics and keyboard
6
+ * behaviour come for free. Fully themed via `--mk-*` tokens.
7
+ *
8
+ * ```html
9
+ * <button mkButton tone="primary">Save</button>
10
+ * <button mkButton variant="outline" tone="danger" [loading]="saving()">Delete</button>
11
+ * <a mkButton variant="ghost" href="/docs">Docs</a>
12
+ * ```
13
+ */
14
+ declare class MkButton {
15
+ private readonly host;
16
+ private readonly isAnchor;
17
+ /** Visual treatment. */
18
+ readonly variant: _angular_core.InputSignal<MkVariant>;
19
+ /** Semantic color tone. */
20
+ readonly tone: _angular_core.InputSignal<MkTone>;
21
+ /** Control size. */
22
+ readonly size: _angular_core.InputSignal<MkSize>;
23
+ /** Shows a spinner and blocks interaction without collapsing layout. */
24
+ readonly loading: _angular_core.InputSignalWithTransform<boolean, unknown>;
25
+ /** Stretch to fill the container width. */
26
+ readonly fullWidth: _angular_core.InputSignalWithTransform<boolean, unknown>;
27
+ /** Square, icon-only button (ensure an `aria-label` is provided). */
28
+ readonly iconOnly: _angular_core.InputSignalWithTransform<boolean, unknown>;
29
+ /** Disable the button (native `disabled` for `<button>`, aria for `<a>`). */
30
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
31
+ protected readonly isDisabled: _angular_core.Signal<boolean>;
32
+ protected readonly nativeDisabled: _angular_core.Signal<"" | null>;
33
+ protected readonly ariaDisabled: _angular_core.Signal<"true" | null>;
34
+ protected readonly linkDisabledTabindex: _angular_core.Signal<"-1" | null>;
35
+ protected onClick(event: Event): void;
36
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkButton, never>;
37
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkButton, "button[mkButton], a[mkButton]", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "fullWidth": { "alias": "fullWidth"; "required": false; "isSignal": true; }; "iconOnly": { "alias": "iconOnly"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
38
+ }
39
+
40
+ export { MkButton };
@@ -0,0 +1,62 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { ControlValueAccessor, Validator, AbstractControl, ValidationErrors } from '@angular/forms';
3
+ import { MkSize, MkTone } from '@mk-kit/ui/core';
4
+
5
+ /**
6
+ * Checkbox — a themed checkbox built on a visually-hidden native
7
+ * `input[type=checkbox]` (so keyboard + form semantics are native) with a
8
+ * custom box. Supports an `indeterminate` state and projects its label.
9
+ *
10
+ * Implements `ControlValueAccessor` with a two-way `checked` model, so it works
11
+ * with `[(ngModel)]`, reactive forms and `[(checked)]`.
12
+ *
13
+ * ```html
14
+ * <mk-checkbox [(ngModel)]="accepted">Accept terms</mk-checkbox>
15
+ * <mk-checkbox [(checked)]="all" [indeterminate]="some()" tone="success">
16
+ * Select all
17
+ * </mk-checkbox>
18
+ * ```
19
+ */
20
+ declare class MkCheckbox implements ControlValueAccessor, Validator {
21
+ private readonly field;
22
+ /** Two-way checked state. */
23
+ readonly checked: _angular_core.ModelSignal<boolean>;
24
+ /** Two-way indeterminate ("mixed") state; cleared when the user toggles. */
25
+ readonly indeterminate: _angular_core.ModelSignal<boolean>;
26
+ /** Disable the control. */
27
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
28
+ /** Force the invalid visual + `aria-invalid` when used standalone. */
29
+ readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
30
+ /** Mark required (adds `aria-required`). */
31
+ readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
32
+ /** Control size. */
33
+ readonly size: _angular_core.InputSignal<MkSize>;
34
+ /** Semantic color tone for the checked box. */
35
+ readonly tone: _angular_core.InputSignal<MkTone>;
36
+ /** Accessible label when no text content is projected. */
37
+ readonly ariaLabel: _angular_core.InputSignal<string>;
38
+ private readonly cvaDisabled;
39
+ private onChange;
40
+ protected onTouched: () => void;
41
+ readonly inputId: string;
42
+ protected readonly isDisabled: _angular_core.Signal<boolean>;
43
+ protected readonly isRequired: _angular_core.Signal<boolean>;
44
+ protected readonly isInvalid: _angular_core.Signal<boolean>;
45
+ protected readonly describedBy: _angular_core.Signal<string | null>;
46
+ protected onNativeChange(event: Event): void;
47
+ writeValue(value: unknown): void;
48
+ registerOnChange(fn: (value: boolean) => void): void;
49
+ registerOnTouched(fn: () => void): void;
50
+ setDisabledState(isDisabled: boolean): void;
51
+ private readonly validatorChange;
52
+ /**
53
+ * Reports `required` for an unchecked box when `[required]` is set, so
54
+ * `required` on the element behaves like `Validators.requiredTrue`.
55
+ */
56
+ validate(control: AbstractControl): ValidationErrors | null;
57
+ registerOnValidatorChange(fn: () => void): void;
58
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkCheckbox, never>;
59
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkCheckbox, "mk-checkbox", never, { "checked": { "alias": "checked"; "required": false; "isSignal": true; }; "indeterminate": { "alias": "indeterminate"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; }, { "checked": "checkedChange"; "indeterminate": "indeterminateChange"; }, never, ["*"], true, never>;
60
+ }
61
+
62
+ export { MkCheckbox };
@@ -0,0 +1,59 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import * as _mk_kit_ui_core from '@mk-kit/ui/core';
3
+ import { MkTone, MkSize } from '@mk-kit/ui/core';
4
+
5
+ /** Visual treatment for a {@link MkChip}. */
6
+ type MkChipVariant = 'solid' | 'soft' | 'outline';
7
+ /**
8
+ * Chip — an interactive, optionally removable/selectable token. Use it for
9
+ * filters, active selections or editable input tokens. For a purely decorative
10
+ * label use {@link MkTag} instead.
11
+ *
12
+ * ```html
13
+ * <mk-chip removable (removed)="drop(item)">{{ item.name }}</mk-chip>
14
+ * <mk-chip selectable [(selected)]="active" tone="primary">Filter</mk-chip>
15
+ * ```
16
+ */
17
+ declare class MkChip {
18
+ protected readonly i18n: _mk_kit_ui_core.MkI18nStrings;
19
+ /** Semantic color tone. */
20
+ readonly tone: _angular_core.InputSignal<MkTone>;
21
+ /** Visual treatment. */
22
+ readonly variant: _angular_core.InputSignal<MkChipVariant>;
23
+ /** Size scale. */
24
+ readonly size: _angular_core.InputSignal<MkSize>;
25
+ /** Make the chip toggle a selected state on click / Enter / Space. */
26
+ readonly selectable: _angular_core.InputSignalWithTransform<boolean, unknown>;
27
+ /** Show a trailing remove button and enable Delete/Backspace removal. */
28
+ readonly removable: _angular_core.InputSignalWithTransform<boolean, unknown>;
29
+ /** Disable all interaction. */
30
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
31
+ /** Accessible label for the remove button. */
32
+ readonly removeLabel: _angular_core.InputSignal<string>;
33
+ /** Id of the projected content, so the remove button's name can include it. */
34
+ protected readonly contentId: string;
35
+ /** Id of the sr-only "Remove" text inside the remove button. */
36
+ protected readonly removeTextId: string;
37
+ /**
38
+ * A consumer-supplied `removeLabel`, or `null` when it is still the i18n
39
+ * default. With the default the button is named via `aria-labelledby`
40
+ * ("Remove <chip text>") so N chips don't get N identical names;
41
+ * `aria-labelledby` would beat `aria-label` in the accname algorithm, so the
42
+ * two bindings are branched rather than stacked.
43
+ */
44
+ protected readonly customRemoveLabel: _angular_core.Signal<string | null>;
45
+ /** Two-way selected state (only meaningful when `selectable`). */
46
+ readonly selected: _angular_core.ModelSignal<boolean>;
47
+ /** Emitted when the chip is removed via the button or Delete/Backspace. */
48
+ readonly removed: _angular_core.OutputEmitterRef<void>;
49
+ protected hostTabindex(): number | null;
50
+ protected onClick(): void;
51
+ protected onKeydown(event: Event): void;
52
+ protected onRemoveClick(event: Event): void;
53
+ private remove;
54
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkChip, never>;
55
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkChip, "mk-chip", never, { "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "selectable": { "alias": "selectable"; "required": false; "isSignal": true; }; "removable": { "alias": "removable"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "removeLabel": { "alias": "removeLabel"; "required": false; "isSignal": true; }; "selected": { "alias": "selected"; "required": false; "isSignal": true; }; }, { "selected": "selectedChange"; "removed": "removed"; }, never, ["*"], true, never>;
56
+ }
57
+
58
+ export { MkChip };
59
+ export type { MkChipVariant };
@@ -0,0 +1,57 @@
1
+ import * as i0 from '@angular/core';
2
+ import { OnDestroy } from '@angular/core';
3
+ import { MkMenu } from '@mk-kit/ui/navigation';
4
+
5
+ /**
6
+ * Turns its host element into a right-click trigger for an `<mk-menu>`, reusing
7
+ * the same {@link MkMenu} instance as `mkMenuTriggerFor`. On `contextmenu` it
8
+ * prevents the native menu and opens the menu at the pointer coordinates via
9
+ * {@link MkMenu.openAt}, restoring focus to the host on close.
10
+ *
11
+ * On touch devices a long-press (~500ms hold with a touch pointer) opens the
12
+ * menu at the touch point — iOS Safari never fires `contextmenu`, so this is
13
+ * the only way to reach a context menu on iPhones. Moving the finger beyond a
14
+ * small slop, or lifting it early, cancels the press. On platforms that do
15
+ * synthesize a `contextmenu` after a long-press (Android), that follow-up
16
+ * event is suppressed so the menu doesn't open twice. While the directive is
17
+ * attached it disables the iOS press callout and text selection on the host
18
+ * (inline host styles — the directive has no stylesheet).
19
+ *
20
+ * For keyboard users (WCAG) the dedicated <kbd>ContextMenu</kbd> key and
21
+ * <kbd>Shift</kbd>+<kbd>F10</kbd> open the menu anchored to the host element;
22
+ * <kbd>Escape</kbd> closes it. The host advertises `aria-haspopup="menu"`.
23
+ * The menu closes on selection, Escape or an outside click (handled by
24
+ * {@link MkMenu}).
25
+ *
26
+ * ```html
27
+ * <tr [mkContextMenuTriggerFor]="rowMenu" tabindex="0">…</tr>
28
+ * <mk-menu #rowMenu>
29
+ * <mk-menu-item (action)="edit()">Edit</mk-menu-item>
30
+ * <mk-menu-item danger (action)="del()">Delete</mk-menu-item>
31
+ * </mk-menu>
32
+ * ```
33
+ */
34
+ declare class MkContextMenuTrigger implements OnDestroy {
35
+ private readonly host;
36
+ /** The menu instance to open on right-click / context-menu key. */
37
+ readonly menu: i0.InputSignal<MkMenu>;
38
+ private longPressTimer?;
39
+ private pressX;
40
+ private pressY;
41
+ /**
42
+ * Set when a long-press just opened the menu; consumed by the `contextmenu`
43
+ * handler so the synthetic event Android fires after a long-press doesn't
44
+ * open the menu a second time.
45
+ */
46
+ private longPressFired;
47
+ protected onContextMenu(event: Event): void;
48
+ protected onPointerDown(event: Event): void;
49
+ protected onPointerMove(event: Event): void;
50
+ protected cancelLongPress(): void;
51
+ protected onKeydown(event: Event): void;
52
+ ngOnDestroy(): void;
53
+ static ɵfac: i0.ɵɵFactoryDeclaration<MkContextMenuTrigger, never>;
54
+ static ɵdir: i0.ɵɵDirectiveDeclaration<MkContextMenuTrigger, "[mkContextMenuTriggerFor]", ["mkContextMenuTrigger"], { "menu": { "alias": "mkContextMenuTriggerFor"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
55
+ }
56
+
57
+ export { MkContextMenuTrigger };