@mk-kit/ui 0.45.0 → 0.47.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/README.md CHANGED
@@ -2,12 +2,13 @@
2
2
 
3
3
  **Themable, accessible Angular component library for admin dashboards, back-offices and internal tools.**
4
4
 
5
- 175+ standalone components, directives and services — data tables, charts,
5
+ 185+ components (225+ selectors with directives and pipes) and 16 services — data tables, charts,
6
6
  date & time pickers, editors, kanban, overlays, an app shell — written for
7
7
  Angular 22 with signals and `OnPush` from day one. Every visual value is a
8
8
  `--mk-*` CSS custom property; light and dark ship out of the box; WCAG 2.1 AA
9
- is the target, not the marketing. MIT licensed. Zero runtime dependencies
10
- beyond Angular.
9
+ is the target, not the marketing. MIT licensed. No third-party runtime
10
+ dependencies — only Angular and the sibling `@mk-kit/validators` (the
11
+ identifier checks, 14 kB, tree-shakeable).
11
12
 
12
13
  - **Docs & live demos:** <https://mk-kit.dev>
13
14
  - **API reference:** <https://mk-kit.dev/api> — also as [api.json](https://mk-kit.dev/api.json), [llms.txt](https://mk-kit.dev/llms.txt) and [llms-full.txt](https://mk-kit.dev/llms-full.txt) for tools and AI assistants
@@ -28,7 +29,14 @@ ng add @mk-kit/ui
28
29
  **Coming from PrimeNG?** `ng g @mk-kit/ui:migrate-primeng --dry-run` shows
29
30
  what the codemod would rewrite (imports, class names, 1:1 selectors, a few
30
31
  input names) and what needs a manual touch; without `--dry-run` it applies
31
- the changes and writes `primeng-migration.md`. Details: <https://mk-kit.dev/migration>. By hand instead:
32
+ the changes and writes `primeng-migration.md`. Details: <https://mk-kit.dev/migration>.
33
+
34
+ **Scaffolding an admin screen?** `ng g @mk-kit/ui:crud product --fields
35
+ "name!:string,price:currency,status:select=draft|published"` generates a
36
+ working slice — typed model, data service (in-memory, or `--api /api/products`
37
+ for HttpClient), `mk-table` list page with search/sort/pagination/delete,
38
+ `mk-dynamic-form` create/edit page, lazy routes wired into the app, and a
39
+ harness-driven spec. Details: <https://mk-kit.dev/crud>. By hand instead:
32
40
 
33
41
  ```bash
34
42
  npm install @mk-kit/ui
@@ -103,10 +111,13 @@ import { MkDatePicker } from '@mk-kit/ui/datetime';
103
111
  ```
104
112
 
105
113
  Available: `core`, `forms`, `datetime`, `table`, `data`, `navigation`,
106
- `feedback`, `directives`, `dnd`, `media`, `icon`, `button`, `checkbox`, `chip`,
107
- `context-menu`, `layout`, `chat`, `query-builder`, `dynamic-form`, `rich-text`, `block-editor`,
108
- plus `testing` (component harnesses for specs — never re-exported from the
109
- umbrella). `sideEffects: false` throughout.
114
+ `feedback`, `directives`, `dnd`, `media`, `icon`, `icon/extended` (the opt-in
115
+ 305-icon set), `button`, `checkbox`, `chip`, `context-menu`, `layout`, `chat`,
116
+ `query-builder`, `dynamic-form`, `rich-text`, `block-editor`, plus `testing`
117
+ (component harnesses for specs), `locales/pl` (the Polish string pack) and
118
+ `embed` (ship components as shadow-DOM custom elements,
119
+ <https://mk-kit.dev/embed>) — the last three are never re-exported from the
120
+ umbrella. `sideEffects: false` throughout.
110
121
 
111
122
  ## Theming
112
123
 
@@ -632,6 +632,47 @@ class MkOverlayRef {
632
632
  }
633
633
  }
634
634
 
635
+ /**
636
+ * Where mk-kit mounts everything that leaves the component tree: overlay
637
+ * containers (dialogs), anchored panels (selects, menus, tooltips), toast /
638
+ * snackbar containers and the tour surfaces. Defaults to `document.body`.
639
+ *
640
+ * Override it to confine those surfaces to another element — `@mk-kit/ui/embed`
641
+ * points it at a themed shadow-DOM host so overlays opened by embedded custom
642
+ * elements stay isolated from the host page's stylesheet:
643
+ *
644
+ * ```ts
645
+ * { provide: MK_OVERLAY_ROOT, useValue: () => myOverlayHost }
646
+ * ```
647
+ */
648
+ const MK_OVERLAY_ROOT = new InjectionToken('MK_OVERLAY_ROOT', {
649
+ providedIn: 'root',
650
+ factory: () => {
651
+ const doc = inject(DOCUMENT);
652
+ return () => doc.body;
653
+ },
654
+ });
655
+ /**
656
+ * The direct child of `document.body` an overlay-root descendant lives under,
657
+ * crossing shadow boundaries on the way up — `null` when the node is not under
658
+ * `body` at all. The overlay service uses it to keep the overlay's own host
659
+ * out of the elements it makes `inert` behind a modal.
660
+ */
661
+ function mkBodyLevelAncestor(node, body) {
662
+ let current = node;
663
+ for (;;) {
664
+ const root = current.getRootNode();
665
+ if (root instanceof ShadowRoot) {
666
+ current = root.host;
667
+ continue;
668
+ }
669
+ let el = current;
670
+ while (el.parentNode && el.parentNode !== body)
671
+ el = el.parentNode;
672
+ return el.parentNode === body ? el : null;
673
+ }
674
+ }
675
+
635
676
  /**
636
677
  * Body-level elements a modal must NOT inert:
637
678
  * - `[popover]` — anchored panels / tooltips teleport to `document.body` and
@@ -652,6 +693,7 @@ class MkOverlayService {
652
693
  appRef = inject(ApplicationRef);
653
694
  envInjector = inject(EnvironmentInjector);
654
695
  document = inject(DOCUMENT);
696
+ overlayRoot = inject(MK_OVERLAY_ROOT);
655
697
  isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
656
698
  // All coordination state lives on the INSTANCE, not the module: the service
657
699
  // is a root singleton, so one app still shares one stack — but each test
@@ -830,7 +872,7 @@ class MkOverlayService {
830
872
  });
831
873
  overlayRef.componentRef = componentRef;
832
874
  this.appRef.attachView(componentRef.hostView);
833
- this.document.body.appendChild(container);
875
+ this.overlayRoot().appendChild(container);
834
876
  // Lock body scroll while any overlay is open (see lockBodyScroll for the
835
877
  // iOS-proof fixed-body technique and the reference counting).
836
878
  if (this.openOverlays++ === 0) {
@@ -846,8 +888,12 @@ class MkOverlayService {
846
888
  const isModal = hasBackdrop && role !== 'menu';
847
889
  const inerted = [];
848
890
  if (isModal) {
891
+ // With a custom MK_OVERLAY_ROOT the container is nested (possibly behind
892
+ // a shadow boundary), so resolve which body child carries it — that one
893
+ // must stay interactive.
894
+ const containerHost = mkBodyLevelAncestor(container, this.document.body);
849
895
  for (const sibling of Array.from(this.document.body.children)) {
850
- if (sibling === container ||
896
+ if (sibling === containerHost ||
851
897
  sibling.hasAttribute('inert') ||
852
898
  sibling.matches(INERT_EXEMPT_SELECTOR)) {
853
899
  continue;
@@ -1002,6 +1048,7 @@ function mkComputeAnchoredPosition(anchor, panel, viewport, opts) {
1002
1048
  class MkAnchoredPanel {
1003
1049
  host = inject(ElementRef);
1004
1050
  document = inject(DOCUMENT);
1051
+ overlayRoot = inject(MK_OVERLAY_ROOT);
1005
1052
  isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
1006
1053
  /** The trigger element to position against. */
1007
1054
  anchor = input(undefined, { ...(ngDevMode ? { debugName: "anchor" } : /* istanbul ignore next */ {}), alias: 'mkAnchoredPanelFor' });
@@ -1080,7 +1127,7 @@ class MkAnchoredPanel {
1080
1127
  // setProperty (not .style.zIndex) so the CSS var() value is accepted. Only
1081
1128
  // matters in the no-Popover fallback; the top layer ignores z-index.
1082
1129
  el.style.setProperty('z-index', 'var(--mk-z-menu)');
1083
- this.document.body.appendChild(el);
1130
+ this.overlayRoot().appendChild(el);
1084
1131
  // Promote into the top layer when the Popover API is available.
1085
1132
  const withPopover = el;
1086
1133
  if (typeof withPopover.showPopover === 'function') {
@@ -2273,5 +2320,5 @@ function mkQueryToText(group, fields = [], i18n = MK_DEFAULT_I18N) {
2273
2320
  * Generated bundle index. Do not edit.
2274
2321
  */
2275
2322
 
2276
- export { MK_BREAKPOINTS, MK_DEFAULT_BREAKPOINTS, MK_DEFAULT_DATE_NAMES, MK_DEFAULT_I18N, MK_DEFAULT_VALIDATION, MK_I18N, MK_OVERLAY_DATA, MK_QUERY_OPERATORS, MK_QUERY_UNARY, MkAnchoredPanel, MkBreakpointService, MkFieldContext, MkFocusTrap, MkLiveAnnouncer, MkOverlayRef, MkOverlayService, MkThemeService, mkComputeAnchoredPosition, mkCreateQueryGroup, mkCreateQueryRule, mkFirstErrorMessage, mkGetFocusable, mkHighlight, mkHighlightJson, mkInjectFieldTouched, mkIsQueryGroup, mkIsResponsive, mkMergeI18n, mkQueryCompact, mkQueryIsEmpty, mkQueryOperatorLabel, mkQueryOperatorsFor, mkQueryRuleCount, mkQueryRuleIsComplete, mkQueryRuleMatches, mkQueryToPredicate, mkQueryToText, mkSignalErrorMessage, mkSignalErrorsToValidationErrors, mkUniqueId, mkValidatorChange, provideMkI18n };
2323
+ export { MK_BREAKPOINTS, MK_DEFAULT_BREAKPOINTS, MK_DEFAULT_DATE_NAMES, MK_DEFAULT_I18N, MK_DEFAULT_VALIDATION, MK_I18N, MK_OVERLAY_DATA, MK_OVERLAY_ROOT, MK_QUERY_OPERATORS, MK_QUERY_UNARY, MkAnchoredPanel, MkBreakpointService, MkFieldContext, MkFocusTrap, MkLiveAnnouncer, MkOverlayRef, MkOverlayService, MkThemeService, mkBodyLevelAncestor, mkComputeAnchoredPosition, mkCreateQueryGroup, mkCreateQueryRule, mkFirstErrorMessage, mkGetFocusable, mkHighlight, mkHighlightJson, mkInjectFieldTouched, mkIsQueryGroup, mkIsResponsive, mkMergeI18n, mkQueryCompact, mkQueryIsEmpty, mkQueryOperatorLabel, mkQueryOperatorsFor, mkQueryRuleCount, mkQueryRuleIsComplete, mkQueryRuleMatches, mkQueryToPredicate, mkQueryToText, mkSignalErrorMessage, mkSignalErrorsToValidationErrors, mkUniqueId, mkValidatorChange, provideMkI18n };
2277
2324
  //# sourceMappingURL=mk-kit-ui-core.mjs.map