@kinetixui/angular 0.24.0 → 0.25.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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { ElementRef } from '@angular/core';
2
+ import { ElementRef, TemplateRef, Signal } from '@angular/core';
3
3
  import { ControlValueAccessor } from '@angular/forms';
4
4
 
5
5
  /**
@@ -28,6 +28,21 @@ type KxToggleVariant = 'default' | 'outline';
28
28
  type KxToggleSize = 'sm' | 'md' | 'lg';
29
29
  /** Tone of the text under a field. `error` is the only one that also sets `aria-invalid` on the control. */
30
30
  type KxFieldMessageVariant = 'error' | 'success' | 'warning' | 'info';
31
+ /**
32
+ * Intent for the two notice surfaces, Banner and Inform. The same five names the React implementation
33
+ * uses, so a design decision made once reads the same on both platforms. `action` is not an intent in the
34
+ * severity sense — it is the inverted, high-contrast promo treatment.
35
+ */
36
+ type KxInformVariant = 'information' | 'warning' | 'success' | 'error' | 'action';
37
+ /** Floating action button fills. Capitalised to match the design source's Variant property, as Button does. */
38
+ type KxFabVariant = 'Primary' | 'Secondary';
39
+ type KxFabSize = 'default' | 'sm';
40
+ /** `row` sets term and value side by side; `stacked` puts the value under a full-width term. */
41
+ type KxDescriptionListLayout = 'row' | 'stacked';
42
+ /** Named aspect ratios Image accepts, alongside any explicit number. */
43
+ type KxImageRatio = '1:1' | '3:2' | '4:3' | '3:4' | '3:1' | '16:9';
44
+ /** A marker tone on a Timeline item. */
45
+ type KxTimelineStatus = 'default' | 'active' | 'success' | 'error';
31
46
 
32
47
  /**
33
48
  * KinetixUI button.
@@ -72,9 +87,24 @@ declare class KxBadge {
72
87
  static ɵfac: i0.ɵɵFactoryDeclaration<KxBadge, never>;
73
88
  static ɵcmp: i0.ɵɵComponentDeclaration<KxBadge, "kx-badge", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
74
89
  }
90
+ /**
91
+ * <kx-card>…</kx-card> a static surface
92
+ * <a kxCard href="/reports/q3">…</a> a card that is a link
93
+ * <button kxCard type="button" [attr.aria-pressed]="on">…</button> a card that is a toggle
94
+ *
95
+ * A raised surface (TOKENS.md, "Surface model"). `kx-card` is static: no hover, no pressed state, no pointer
96
+ * cursor, because a surface that reacts to the pointer reads as clickable.
97
+ *
98
+ * Interaction is opt-in through the element, as in React (`<Card asChild>`): put `kxCard` on a real `<a href>`
99
+ * or `<button>` and the card takes the interactive states — hover, pressed, focus and selected
100
+ * (`aria-pressed="true"` on a button, `aria-current` on a link). The states are keyed on the element being
101
+ * interactive, so they cannot drift from what it does, and the element's own semantics (link, button, pressed,
102
+ * current) are what assistive technology reads. One action per card: it must not contain other controls, and a
103
+ * button card holds phrasing content only (no headings).
104
+ */
75
105
  declare class KxCard {
76
106
  static ɵfac: i0.ɵɵFactoryDeclaration<KxCard, never>;
77
- static ɵcmp: i0.ɵɵComponentDeclaration<KxCard, "kx-card", never, {}, {}, never, ["*"], true, never>;
107
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxCard, "kx-card, a[kxCard], button[kxCard]", never, {}, {}, never, ["*"], true, never>;
78
108
  }
79
109
  declare class KxCardHeader {
80
110
  static ɵfac: i0.ɵɵFactoryDeclaration<KxCardHeader, never>;
@@ -300,7 +330,7 @@ declare class KxToggleGroupItem {
300
330
  readonly id: i0.InputSignal<string>;
301
331
  constructor(group: KxToggleGroup);
302
332
  static ɵfac: i0.ɵɵFactoryDeclaration<KxToggleGroupItem, never>;
303
- static ɵcmp: i0.ɵɵComponentDeclaration<KxToggleGroupItem, "kx-toggle-group-item", never, { "value": { "alias": "value"; "required": true; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; }, {}, never, ["*", "*"], true, never>;
333
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxToggleGroupItem, "kx-toggle-group-item", never, { "value": { "alias": "value"; "required": true; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
304
334
  }
305
335
  /**
306
336
  * <kx-segmented-control [(value)]="range" aria-label="Range">
@@ -651,6 +681,11 @@ declare class KxRadio {
651
681
  * the RTL direction flip and touch dragging are all the browser's, and all of them are things hand-rolled
652
682
  * sliders routinely lose. The filled track is drawn with a CSS custom property set from the value, so the
653
683
  * visual follows the real control rather than the other way round.
684
+ *
685
+ * The track and its fill are elements behind the input rather than a gradient on the input's own track: a
686
+ * gradient has no logical direction (`to right` stays right in RTL), so the fill grew from the wrong end in
687
+ * an RTL page while the browser moved the thumb correctly. An element placed with `inset-inline-start`
688
+ * follows the slider's own direction, nested or not (scripts/angular-browser.mjs, rtl).
654
689
  */
655
690
  declare class KxSlider extends KxValueBase<number> {
656
691
  readonly value: i0.ModelSignal<number>;
@@ -677,21 +712,29 @@ declare class KxSlider extends KxValueBase<number> {
677
712
  *
678
713
  * The buttons are `aria-hidden` and `tabindex="-1"`: they duplicate keyboard behaviour the input already has,
679
714
  * so exposing them adds two stops to the tab order that do nothing new.
715
+ *
716
+ * `readonly` keeps the value readable, focusable and submitted but unchangeable: the input is `readonly` (so the
717
+ * browser's own arrow-key stepping stops too) and both steppers are disabled.
680
718
  */
681
719
  declare class KxNumberInput extends KxValueBase<number | null> {
682
720
  readonly value: i0.ModelSignal<number>;
683
721
  readonly min: i0.InputSignal<number>;
684
722
  readonly max: i0.InputSignal<number>;
685
723
  readonly step: i0.InputSignal<number>;
724
+ readonly readonly: i0.InputSignalWithTransform<boolean, unknown>;
686
725
  readonly ariaLabel: i0.InputSignal<string>;
687
726
  readonly ariaLabelledby: i0.InputSignal<string>;
727
+ /** Forwarded to the inner input, which is what assistive technology reads and what the field's error state keys on. */
728
+ readonly ariaInvalid: i0.InputSignal<"true" | "false">;
729
+ /** Forwarded to the inner input, so an error or hint is announced with the field. */
730
+ readonly ariaDescribedby: i0.InputSignal<string>;
688
731
  readonly changed: i0.OutputEmitterRef<number>;
689
732
  protected nudge(direction: 1 | -1): void;
690
733
  protected commit(next: number): void;
691
734
  private clamp;
692
735
  writeValue(value: number | null): void;
693
736
  static ɵfac: i0.ɵɵFactoryDeclaration<KxNumberInput, never>;
694
- static ɵcmp: i0.ɵɵComponentDeclaration<KxNumberInput, "kx-number-input", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "ariaLabelledby": { "alias": "aria-labelledby"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "changed": "changed"; }, never, never, true, never>;
737
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxNumberInput, "kx-number-input", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "ariaLabelledby": { "alias": "aria-labelledby"; "required": false; "isSignal": true; }; "ariaInvalid": { "alias": "aria-invalid"; "required": false; "isSignal": true; }; "ariaDescribedby": { "alias": "aria-describedby"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "changed": "changed"; }, never, never, true, never>;
695
738
  }
696
739
  /**
697
740
  * <kx-password-input [(ngModel)]="password" aria-label="Password" />
@@ -705,11 +748,15 @@ declare class KxPasswordInput extends KxValueBase<string> {
705
748
  readonly autocomplete: i0.InputSignal<"current-password" | "new-password">;
706
749
  readonly ariaLabel: i0.InputSignal<string>;
707
750
  readonly ariaLabelledby: i0.InputSignal<string>;
751
+ /** Forwarded to the inner input, which is what assistive technology reads and what the field's error state keys on. */
752
+ readonly ariaInvalid: i0.InputSignal<"true" | "false">;
753
+ /** Forwarded to the inner input, so an error or hint is announced with the field. */
754
+ readonly ariaDescribedby: i0.InputSignal<string>;
708
755
  protected readonly revealed: i0.WritableSignal<boolean>;
709
756
  protected commit(next: string): void;
710
757
  writeValue(value: string): void;
711
758
  static ɵfac: i0.ɵɵFactoryDeclaration<KxPasswordInput, never>;
712
- static ɵcmp: i0.ɵɵComponentDeclaration<KxPasswordInput, "kx-password-input", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "ariaLabelledby": { "alias": "aria-labelledby"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
759
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxPasswordInput, "kx-password-input", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "ariaLabelledby": { "alias": "aria-labelledby"; "required": false; "isSignal": true; }; "ariaInvalid": { "alias": "aria-invalid"; "required": false; "isSignal": true; }; "ariaDescribedby": { "alias": "aria-describedby"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
713
760
  }
714
761
  /**
715
762
  * <kx-field>
@@ -745,6 +792,162 @@ declare class KxFieldMessage {
745
792
  static ɵcmp: i0.ɵɵComponentDeclaration<KxFieldMessage, "kx-field-message", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
746
793
  }
747
794
 
795
+ /**
796
+ * <kx-input-group>
797
+ * <kx-input-group-text>https://</kx-input-group-text>
798
+ * <input kxInputGroupInput aria-label="Website" placeholder="kinetixui.com" />
799
+ * <button kxInputGroupButton>Copy</button>
800
+ * </kx-input-group>
801
+ *
802
+ * One bordered field that hosts an input plus fixed add-ons (an icon, text, a button) on either side — React's
803
+ * InputGroup. The input is a real `<input>` carrying `kxInputGroupInput`, so `ngModel`, `formControlName`,
804
+ * `type`, `autocomplete`, `readonly` and the browser's validation all work on it untouched, and it is the only
805
+ * thing in the group a label has to name.
806
+ *
807
+ * The shell follows the text-entry state contract (TOKENS.md, "Composite fields"): it is ONE field, and it reads
808
+ * its edge, hover, focus, invalid, read-only and disabled states from the input inside it — `aria-invalid`,
809
+ * `readonly` and `disabled` go on the input, where assistive technology reads them, and the shell follows. A
810
+ * focused add-on button draws its own inset ring and leaves the shell at rest, so the ring says which part has
811
+ * focus.
812
+ */
813
+ declare class KxInputGroup {
814
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxInputGroup, never>;
815
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxInputGroup, "kx-input-group", never, {}, {}, never, ["*"], true, never>;
816
+ }
817
+ /** The group's input. Put it on a real `<input>`; every native and Angular forms attribute still applies. */
818
+ declare class KxInputGroupInput {
819
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxInputGroupInput, never>;
820
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxInputGroupInput, "input[kxInputGroupInput]", never, {}, {}, never, never, true, never>;
821
+ }
822
+ /**
823
+ * An icon or a cluster of add-ons at one end of the group. `align` is logical: `start` is the reading start,
824
+ * so the add-on follows the page into right-to-left without a separate RTL rule.
825
+ */
826
+ declare class KxInputGroupAddon {
827
+ readonly align: i0.InputSignal<"start" | "end">;
828
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxInputGroupAddon, never>;
829
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxInputGroupAddon, "kx-input-group-addon", never, { "align": { "alias": "align"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
830
+ }
831
+ /** Fixed text beside the input — a protocol, a unit, a domain. Not announced as part of the input's value. */
832
+ declare class KxInputGroupText {
833
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxInputGroupText, never>;
834
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxInputGroupText, "kx-input-group-text", never, {}, {}, never, ["*"], true, never>;
835
+ }
836
+ /**
837
+ * A real `<button>` inside the group, divided from the input by a quiet internal line. `type` defaults to
838
+ * `button`, so a button in a group inside a `<form>` never submits it by accident.
839
+ */
840
+ declare class KxInputGroupButton {
841
+ readonly type: i0.InputSignal<"button" | "submit" | "reset">;
842
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxInputGroupButton, never>;
843
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxInputGroupButton, "button[kxInputGroupButton]", never, { "type": { "alias": "type"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
844
+ }
845
+
846
+ /**
847
+ * <kx-input-otp [(ngModel)]="code" [length]="6" [groups]="[3, 3]" aria-label="Verification code" />
848
+ *
849
+ * A one-time code field drawn as a row of cells — React's InputOTP. Underneath it is ONE real `<input>`,
850
+ * laid transparently over the cells, which is what makes it work everywhere a code field has to:
851
+ *
852
+ * - `autocomplete="one-time-code"`, so iOS and Android offer the code from the SMS, and a password manager
853
+ * can fill it;
854
+ * - a paste of the whole code lands in one go (characters the field does not accept are dropped);
855
+ * - assistive technology meets a single labelled text field with a maximum length, not six unlabelled boxes —
856
+ * the cells are `aria-hidden` decoration of the input's value;
857
+ * - `inputmode="numeric"` raises the number pad for a digits-only code.
858
+ *
859
+ * Editing happens at the end of the code: typing appends and Backspace removes the last character, and the
860
+ * caret is held at the end so the highlighted cell is always the one the next character goes into (the
861
+ * `data-active` cell, which carries the field's focus ring). `completed` fires once the code is full.
862
+ *
863
+ * The cells read the field's state from the input, as every composite field does (TOKENS.md, "Composite fields"):
864
+ * `aria-invalid` on the component is forwarded to the input and turns every cell's edge destructive, and a
865
+ * disabled field dims as one. The caret is a static bar rather than a blinking one, so there is no motion to
866
+ * reduce.
867
+ */
868
+ declare class KxInputOtp extends KxValueBase<string> {
869
+ readonly value: i0.ModelSignal<string>;
870
+ /** How many characters the code has. */
871
+ readonly length: i0.InputSignal<number>;
872
+ /** Cells per visual group, separated by a dash — `[3, 3]` draws 123–456. Defaults to one group. */
873
+ readonly groups: i0.InputSignal<readonly number[]>;
874
+ /** Which characters the field accepts. Anything else, typed or pasted, is dropped. */
875
+ readonly allow: i0.InputSignal<"digits" | "alphanumeric">;
876
+ readonly ariaLabel: i0.InputSignal<string>;
877
+ readonly ariaLabelledby: i0.InputSignal<string>;
878
+ /** Forwarded to the input, which is what assistive technology reads and what the cells' error state keys on. */
879
+ readonly ariaInvalid: i0.InputSignal<"true" | "false">;
880
+ /** Forwarded to the input, so an error or hint is announced with the field. */
881
+ readonly ariaDescribedby: i0.InputSignal<string>;
882
+ /** The full code, once every cell is filled. */
883
+ readonly completed: i0.OutputEmitterRef<string>;
884
+ protected readonly focused: i0.WritableSignal<boolean>;
885
+ private readonly field;
886
+ /** Cell indices, split into the requested groups. A `groups` that does not add up to `length` is ignored. */
887
+ protected readonly layout: i0.Signal<number[][]>;
888
+ /** The cell the next character goes into — the last one once the code is full — while the field has focus. */
889
+ protected readonly active: i0.Signal<number>;
890
+ /** What the field accepts: only allowed characters, at most `length` of them. */
891
+ private clean;
892
+ protected commit(el: HTMLInputElement): void;
893
+ /** Keep the caret at the end, so the highlighted cell and the insertion point never disagree. */
894
+ protected toEnd(): void;
895
+ /** A value written by the form is held to the same rules as typing, so the field never holds more than its cells show. */
896
+ writeValue(value: string): void;
897
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxInputOtp, never>;
898
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxInputOtp, "kx-input-otp", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "length": { "alias": "length"; "required": false; "isSignal": true; }; "groups": { "alias": "groups"; "required": false; "isSignal": true; }; "allow": { "alias": "allow"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "ariaLabelledby": { "alias": "aria-labelledby"; "required": false; "isSignal": true; }; "ariaInvalid": { "alias": "aria-invalid"; "required": false; "isSignal": true; }; "ariaDescribedby": { "alias": "aria-describedby"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "completed": "completed"; }, never, never, true, never>;
899
+ }
900
+
901
+ /**
902
+ * <kx-rating [(ngModel)]="stars" aria-label="Rate this article" />
903
+ * <kx-rating [value]="4" readonly />
904
+ *
905
+ * A star rating. The interaction contract, defined before the implementation and asserted in a real browser
906
+ * (scripts/angular-browser.mjs):
907
+ *
908
+ * semantics a `radiogroup` named by `aria-label` / `aria-labelledby` ("Rating" if neither is given), whose
909
+ * stars are real `<input type="radio">`s named "1 star" … "5 stars". One of N, chosen — which is
910
+ * what a rating is, and what a screen reader already knows how to announce ("3 stars, radio,
911
+ * checked, 3 of 5").
912
+ * keyboard one tab stop: the chosen star, or the first when nothing is chosen yet. The arrow keys move
913
+ * and choose (the browser's own radio behaviour, mirrored in RTL); Home and End choose the
914
+ * lowest and highest. Space chooses the focused star.
915
+ * pointer clicking a star chooses it; hovering previews the fill up to that star without changing the
916
+ * value.
917
+ * read-only `readonly` renders a static display — `role="img"` named "Rated 3 out of 5", the stars hidden
918
+ * from assistive technology, no tab stop — for a rating that is shown, not given.
919
+ * disabled every radio is disabled; the group dims and does not answer the pointer.
920
+ * direction the stars run from the inline start, so the first star is on the right in an RTL page.
921
+ * motion none: a star's fill changes colour instantly.
922
+ *
923
+ * This differs from React's Rating, which renders `aria-pressed` buttons inside a `radiogroup` with no arrow-key
924
+ * movement; the radios here are the closer fit to the role the group claims.
925
+ */
926
+ declare class KxRating extends KxValueBase<number> {
927
+ /** The chosen number of stars; 0 is "not rated yet". */
928
+ readonly value: i0.ModelSignal<number>;
929
+ readonly max: i0.InputSignal<number>;
930
+ readonly size: i0.InputSignal<"sm" | "md" | "lg">;
931
+ readonly readonly: i0.InputSignalWithTransform<boolean, unknown>;
932
+ readonly ariaLabel: i0.InputSignal<string>;
933
+ readonly ariaLabelledby: i0.InputSignal<string>;
934
+ readonly changed: i0.OutputEmitterRef<number>;
935
+ protected readonly name: string;
936
+ protected readonly hovered: i0.WritableSignal<number>;
937
+ protected readonly stars: i0.Signal<number[]>;
938
+ /** What the stars show: the hovered preview while the pointer is over one, otherwise the value. */
939
+ protected readonly shown: i0.Signal<number>;
940
+ /** A five-pointed star on a 24-unit grid. */
941
+ protected readonly star = "M12 2.5l2.94 5.96 6.56.95-4.75 4.63 1.12 6.54L12 17.5l-5.87 3.08 1.12-6.54L2.5 9.41l6.56-.95z";
942
+ protected preview(n: number): void;
943
+ protected commit(n: number): void;
944
+ /** Home and End — the one piece of radio-group keyboard behaviour the browser does not provide. */
945
+ protected onKey(event: KeyboardEvent): void;
946
+ writeValue(value: number): void;
947
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxRating, never>;
948
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxRating, "kx-rating", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "ariaLabelledby": { "alias": "aria-labelledby"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "changed": "changed"; }, never, never, true, never>;
949
+ }
950
+
748
951
  declare class KxTab {
749
952
  readonly tabs: KxTabs;
750
953
  readonly el: ElementRef<HTMLButtonElement>;
@@ -770,6 +973,11 @@ declare class KxTabPanel {
770
973
  readonly value: i0.InputSignal<string>;
771
974
  active(): boolean;
772
975
  labelledBy(): string | null;
976
+ /**
977
+ * The id its tab's `aria-controls` names. The tab always pointed here, but the panel never carried the id, so
978
+ * every tab referenced an element that did not exist (axe `aria-valid-attr-value`, check:angular-browser).
979
+ */
980
+ panelId(): string | null;
773
981
  static ɵfac: i0.ɵɵFactoryDeclaration<KxTabPanel, never>;
774
982
  static ɵcmp: i0.ɵɵComponentDeclaration<KxTabPanel, "kx-tab-panel", never, { "value": { "alias": "value"; "required": true; "isSignal": true; }; }, {}, never, ["*"], true, never>;
775
983
  }
@@ -797,5 +1005,1336 @@ declare class KxTabs {
797
1005
  static ɵcmp: i0.ɵɵComponentDeclaration<KxTabs, "kx-tabs", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, ["tabs"], ["*"], true, never>;
798
1006
  }
799
1007
 
800
- export { KxAlert, KxAlertDescription, KxAlertTitle, KxAspectRatio, KxAvatar, KxAvatarFallback, KxAvatarGroup, KxAvatarImage, KxBadge, KxButton, KxCard, KxCardContent, KxCardDescription, KxCardFooter, KxCardHeader, KxCardTitle, KxCheckbox, KxEmpty, KxEmptyContent, KxEmptyDescription, KxEmptyHeader, KxEmptyMedia, KxEmptyTitle, KxField, KxFieldDescription, KxFieldLabel, KxFieldMessage, KxInput, KxKbd, KxKbdGroup, KxLabel, KxMetric, KxNativeSelect, KxNumberInput, KxPasswordInput, KxProgress, KxQuote, KxRadio, KxRadioGroup, KxSegment, KxSegmentedControl, KxSeparator, KxSkeleton, KxSlider, KxSpinner, KxSwitch, KxTab, KxTabList, KxTabPanel, KxTabs, KxTag, KxTextarea, KxToggle, KxToggleGroup, KxToggleGroupItem };
801
- export type { KxAlertVariant, KxBadgeVariant, KxButtonSize, KxButtonVariant, KxCorners, KxEmptyMediaVariant, KxFieldMessageVariant, KxOrientation, KxSpinnerSize, KxSpinnerVariant, KxTagVariant, KxToggleSize, KxToggleVariant, KxTrend };
1008
+ /**
1009
+ * The content and layout wave: banner, button group, circular progress, code block, description list, FAB,
1010
+ * image, inform, list, marquee, page header and timeline.
1011
+ *
1012
+ * Two conventions this file follows, both inherited rather than invented:
1013
+ *
1014
+ * Icons arrive by projection, never by import, with one exception that matters: the dismiss button
1015
+ * carries a built-in glyph as `<ng-content>` fallback content. A projected slot that the caller leaves
1016
+ * empty is fine for a decorative leading icon and is not fine for a control — an empty button is a few
1017
+ * pixels of nothing, so the only people who could find it are the ones reading its `aria-label`. Project
1018
+ * `[kxDismissIcon]` to replace the default; leave it out and the control is still visible.
1019
+ * The React implementations reach for `lucide-react`, which is a
1020
+ * reasonable choice for a package that already depends on React's ecosystem. Adding an icon library to
1021
+ * `@kinetixui/angular` would make every consumer carry it to render a banner, so each surface here exposes a
1022
+ * slot and the application supplies whatever it already uses. Nothing is hard-coded and nothing is missing:
1023
+ * the surfaces that need a decorative glyph lay out correctly with or without one.
1024
+ *
1025
+ * Callbacks arrive as `output()`, never as object inputs. React passes `action={{ label, onClick }}`, which is
1026
+ * idiomatic there. In Angular the label is content and the click is an event, so a caller writes
1027
+ * `<button kxBannerAction (click)="…">Retry</button>`. This is the "equivalent capability, idiomatic
1028
+ * implementation" rule in RTL.md and types.ts applied to event handling.
1029
+ */
1030
+ /**
1031
+ * <kx-banner variant="warning" sticky (dismiss)="hidden = true">
1032
+ * <svg kxIcon …></svg>
1033
+ * Scheduled maintenance at 02:00 UTC.
1034
+ * <button kxBannerAction (click)="more()">Details</button>
1035
+ * </kx-banner>
1036
+ *
1037
+ * A page-level, full-bleed notice: no radius and no width of its own, so it spans whatever contains it. That
1038
+ * is the whole distinction from Inform, which is a contained rounded card, and from a toast, which is
1039
+ * transient.
1040
+ *
1041
+ * `role="status"` rather than `alert`. A banner is persistent and usually present on arrival, and an assertive
1042
+ * live region interrupts a screen-reader user mid-sentence to read something that is not urgent. A caller with
1043
+ * a genuinely urgent banner can set `role="alert"` on the host, which wins over this default.
1044
+ */
1045
+ declare class KxBanner {
1046
+ readonly variant: i0.InputSignal<KxInformVariant>;
1047
+ readonly sticky: i0.InputSignalWithTransform<boolean, unknown>;
1048
+ /** Renders the dismiss control. The banner does not hide itself — the caller owns that state. */
1049
+ readonly dismissible: i0.InputSignalWithTransform<boolean, unknown>;
1050
+ /**
1051
+ * The dismiss button's accessible name. An input rather than a hard-coded "Dismiss" because this package
1052
+ * ships no translations, and a button whose only label is in the wrong language is worse than one the
1053
+ * application names itself.
1054
+ */
1055
+ readonly dismissLabel: i0.InputSignal<string>;
1056
+ readonly dismiss: i0.OutputEmitterRef<void>;
1057
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxBanner, never>;
1058
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxBanner, "kx-banner", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "sticky": { "alias": "sticky"; "required": false; "isSignal": true; }; "dismissible": { "alias": "dismissible"; "required": false; "isSignal": true; }; "dismissLabel": { "alias": "dismissLabel"; "required": false; "isSignal": true; }; }, { "dismiss": "dismiss"; }, never, ["[kxIcon]", "*", "[kxBannerAction]", "[kxDismissIcon]"], true, never>;
1059
+ }
1060
+ /**
1061
+ * <div kxButtonGroup>
1062
+ * <button kxButton variant="Outline">Day</button>
1063
+ * <button kxButton variant="Outline">Week</button>
1064
+ * </div>
1065
+ *
1066
+ * Joins adjacent controls into one cluster: inner corners squared, shared borders overlapped so they do not
1067
+ * double, and the focused child raised so its ring is not clipped by its neighbour.
1068
+ *
1069
+ * A directive on the caller's element, not a wrapper component, because the group contributes layout and
1070
+ * nothing else — the same reason `kxButton` is a directive on `<button>`. `role="group"` is set, but no
1071
+ * roving tabindex: these are buttons, each is individually tabbable, and a toolbar's arrow-key navigation is
1072
+ * `kx-segmented-control`'s job. Pretending otherwise would break Tab for every existing caller.
1073
+ */
1074
+ declare class KxButtonGroup {
1075
+ readonly orientation: i0.InputSignal<KxOrientation>;
1076
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxButtonGroup, never>;
1077
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxButtonGroup, "[kxButtonGroup]", never, { "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1078
+ }
1079
+ /** A thin divider between segments, for fills with no shared border for the overlap trick to lean on. */
1080
+ declare class KxButtonGroupSeparator {
1081
+ readonly orientation: i0.InputSignal<KxOrientation>;
1082
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxButtonGroupSeparator, never>;
1083
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxButtonGroupSeparator, "kx-button-group-separator", never, { "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1084
+ }
1085
+ /** A static, non-interactive segment — a unit, a prefix, a count. Not a button, so not focusable. */
1086
+ declare class KxButtonGroupText {
1087
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxButtonGroupText, never>;
1088
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxButtonGroupText, "kx-button-group-text", never, {}, {}, never, ["*"], true, never>;
1089
+ }
1090
+ /**
1091
+ * <kx-circular-progress [value]="72" showValue />
1092
+ * <kx-circular-progress /> <!-- indeterminate -->
1093
+ *
1094
+ * The ring is two SVG circles, the indicator revealed by `stroke-dashoffset`. `aria-valuenow` is omitted when
1095
+ * no value is given, which is how ARIA spells an indeterminate progressbar — a determinate bar reporting 0
1096
+ * says "nothing has happened", which is a different and usually wrong claim.
1097
+ */
1098
+ declare class KxCircularProgress {
1099
+ /** 0–100. Left undefined for an indeterminate ring. */
1100
+ readonly value: i0.InputSignal<number>;
1101
+ /** Diameter in px. A number, not a token, because a ring's size is a layout decision at the call site. */
1102
+ readonly size: i0.InputSignal<number>;
1103
+ readonly strokeWidth: i0.InputSignal<number>;
1104
+ readonly showValue: i0.InputSignalWithTransform<boolean, unknown>;
1105
+ protected readonly clamped: i0.Signal<number>;
1106
+ protected readonly centre: i0.Signal<number>;
1107
+ protected readonly radius: i0.Signal<number>;
1108
+ protected readonly circumference: i0.Signal<number>;
1109
+ protected readonly offset: i0.Signal<number>;
1110
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxCircularProgress, never>;
1111
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxCircularProgress, "kx-circular-progress", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "strokeWidth": { "alias": "strokeWidth"; "required": false; "isSignal": true; }; "showValue": { "alias": "showValue"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1112
+ }
1113
+ interface KxCodeBlockFile {
1114
+ name: string;
1115
+ code: string;
1116
+ language?: string;
1117
+ }
1118
+ /**
1119
+ * <kx-code-block [code]="snippet" filename="main.ts" />
1120
+ * <kx-code-block [files]="[{ name: 'app.ts', code: a }, { name: 'app.html', code: b }]" />
1121
+ *
1122
+ * Shows code and copies it. Deliberately does not highlight: syntax highlighting needs a grammar per language
1123
+ * and is a build-time concern, and a component that shipped one would force the choice on every consumer.
1124
+ * `<pre><code>` keeps the whitespace and lets the application bring Shiki or Prism if it wants colour.
1125
+ *
1126
+ * The file switcher is a real tablist with arrow-key navigation, because that is what a row of tabs is. The
1127
+ * copy button reports its result through `aria-live` rather than only swapping an icon, so the outcome is
1128
+ * available to someone who cannot see the tick.
1129
+ */
1130
+ declare class KxCodeBlock {
1131
+ readonly code: i0.InputSignal<string>;
1132
+ readonly language: i0.InputSignal<string>;
1133
+ readonly filename: i0.InputSignal<string>;
1134
+ readonly files: i0.InputSignal<readonly KxCodeBlockFile[]>;
1135
+ readonly hideCopy: i0.InputSignalWithTransform<boolean, unknown>;
1136
+ readonly copyLabel: i0.InputSignal<string>;
1137
+ readonly copiedLabel: i0.InputSignal<string>;
1138
+ protected readonly active: i0.WritableSignal<number>;
1139
+ protected readonly copied: i0.WritableSignal<boolean>;
1140
+ protected readonly tabs: i0.Signal<readonly KxCodeBlockFile[]>;
1141
+ protected readonly current: i0.Signal<KxCodeBlockFile>;
1142
+ protected readonly hasHeader: i0.Signal<boolean>;
1143
+ protected select(i: number): void;
1144
+ /** Home/End and the arrows, mirrored for direction: in an RTL page ArrowRight moves toward the start. */
1145
+ protected onTabKeydown(event: KeyboardEvent, i: number): void;
1146
+ private readonly host;
1147
+ protected copy(): Promise<void>;
1148
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxCodeBlock, never>;
1149
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxCodeBlock, "kx-code-block", never, { "code": { "alias": "code"; "required": false; "isSignal": true; }; "language": { "alias": "language"; "required": false; "isSignal": true; }; "filename": { "alias": "filename"; "required": false; "isSignal": true; }; "files": { "alias": "files"; "required": false; "isSignal": true; }; "hideCopy": { "alias": "hideCopy"; "required": false; "isSignal": true; }; "copyLabel": { "alias": "copyLabel"; "required": false; "isSignal": true; }; "copiedLabel": { "alias": "copiedLabel"; "required": false; "isSignal": true; }; }, {}, never, ["[kxCopyIcon]", "[kxCopyIcon]"], true, never>;
1150
+ }
1151
+ /**
1152
+ * <dl kxDescriptionList>
1153
+ * <kx-description-list-item term="Status">Active</kx-description-list-item>
1154
+ * </dl>
1155
+ *
1156
+ * A directive on a real `<dl>`, and each item is a component with an ATTRIBUTE selector on a `<div>`, so the
1157
+ * rendered tree is `<dl><div><dt>…</dt><dd>…</dd></div></dl>`. That distinction is the whole point: a `dl`'s
1158
+ * content model allows `dt`/`dd` directly or wrapped in a `div`, and nothing else. An earlier spelling used a
1159
+ * `<kx-description-list-item>` element as the wrapper, which is neither — the grouping was invalid and the
1160
+ * term/description association was left to chance. The term is an input rather than a slot because a `<dt>`
1161
+ * takes text, and two projection slots in one item would let a caller put the value in the term position.
1162
+ */
1163
+ declare class KxDescriptionList {
1164
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxDescriptionList, never>;
1165
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxDescriptionList, "dl[kxDescriptionList]", never, {}, {}, never, never, true, never>;
1166
+ }
1167
+ declare class KxDescriptionListItem {
1168
+ readonly term: i0.InputSignal<string>;
1169
+ readonly layout: i0.InputSignal<KxDescriptionListLayout>;
1170
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxDescriptionListItem, never>;
1171
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxDescriptionListItem, "div[kxDescriptionListItem]", never, { "term": { "alias": "term"; "required": true; "isSignal": true; }; "layout": { "alias": "layout"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1172
+ }
1173
+ /**
1174
+ * <button kxFab aria-label="New message"><svg …></svg></button>
1175
+ * <button kxFab extended>New message</button>
1176
+ *
1177
+ * A directive on a real `<button>`: the element already has the activation behaviour, the disabled semantics
1178
+ * and the keyboard contract, and a component wrapping one would have to re-expose all three.
1179
+ *
1180
+ * An icon-only FAB has no text, so it needs `aria-label` from the caller. This does not supply a default —
1181
+ * "Action" is not a useful accessible name, and a wrong one is harder to notice than a missing one. The
1182
+ * `extended` form has a visible label and needs nothing.
1183
+ */
1184
+ declare class KxFab {
1185
+ readonly variant: i0.InputSignal<KxFabVariant>;
1186
+ readonly size: i0.InputSignal<KxFabSize>;
1187
+ readonly extended: i0.InputSignalWithTransform<boolean, unknown>;
1188
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxFab, never>;
1189
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxFab, "button[kxFab]", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "extended": { "alias": "extended"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1190
+ }
1191
+ /**
1192
+ * <kx-image src="cover.jpg" alt="Harbour at dusk" ratio="16:9" />
1193
+ * <kx-image src="broken.png" alt="" ><svg kxImageFallback …></svg></kx-image>
1194
+ *
1195
+ * Holds the aspect ratio before the image arrives so the page does not reflow, fades it in once decoded, and
1196
+ * swaps to a fallback slot on error.
1197
+ *
1198
+ * `alt` is required, not optional with an empty default. An empty alt is the correct answer for a decorative
1199
+ * image and a silent failure for every other one, so the caller states which it is — `alt=""` is still one
1200
+ * character to type, and now it is a decision rather than an omission.
1201
+ */
1202
+ declare class KxImage {
1203
+ readonly src: i0.InputSignal<string>;
1204
+ readonly alt: i0.InputSignal<string>;
1205
+ readonly ratio: i0.InputSignal<number | KxImageRatio>;
1206
+ readonly rounded: i0.InputSignalWithTransform<boolean, unknown>;
1207
+ /** Native lazy loading. Defaults to `lazy`; pass `eager` for an image above the fold. */
1208
+ readonly loading: i0.InputSignal<"lazy" | "eager">;
1209
+ /**
1210
+ * Reset to `loading` whenever `src` changes. A plain signal kept the old verdict: once a source had
1211
+ * failed, the fallback branch stayed rendered and a later, valid URL was never even requested — and a
1212
+ * previously loaded image kept its loaded styling while its replacement was still arriving.
1213
+ */
1214
+ protected readonly status: i0.WritableSignal<"error" | "loading" | "loaded">;
1215
+ protected readonly ratioValue: i0.Signal<number>;
1216
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxImage, never>;
1217
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxImage, "kx-image", never, { "src": { "alias": "src"; "required": true; "isSignal": true; }; "alt": { "alias": "alt"; "required": true; "isSignal": true; }; "ratio": { "alias": "ratio"; "required": false; "isSignal": true; }; "rounded": { "alias": "rounded"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; }, {}, never, ["[kxImageFallback]"], true, never>;
1218
+ }
1219
+ /**
1220
+ * <kx-inform variant="success">Your changes were saved.</kx-inform>
1221
+ *
1222
+ * The contained counterpart to Banner: rounded, in flow, sized by its container. Same intents and the same
1223
+ * `role="status"` reasoning — persistent, not urgent, so polite rather than assertive.
1224
+ */
1225
+ declare class KxInform {
1226
+ readonly variant: i0.InputSignal<KxInformVariant>;
1227
+ readonly dismissible: i0.InputSignalWithTransform<boolean, unknown>;
1228
+ readonly dismissLabel: i0.InputSignal<string>;
1229
+ readonly dismiss: i0.OutputEmitterRef<void>;
1230
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxInform, never>;
1231
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxInform, "kx-inform", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "dismissible": { "alias": "dismissible"; "required": false; "isSignal": true; }; "dismissLabel": { "alias": "dismissLabel"; "required": false; "isSignal": true; }; }, { "dismiss": "dismiss"; }, never, ["[kxIcon]", "*", "[kxInformAction]", "[kxDismissIcon]"], true, never>;
1232
+ }
1233
+ /**
1234
+ * <ul kxList>
1235
+ * <li kxListItem title="Billing" description="Invoices and receipts" />
1236
+ * </ul>
1237
+ *
1238
+ * A directive on a real `<ul>`, and items on real `<li>`s, so the list semantics are the platform's rather
1239
+ * than three ARIA roles standing in for them. A pressable row puts a `<button>` inside the `<li>` instead of
1240
+ * giving the `<li>` itself `role="button"`: a list's children must be list items, and an element cannot be
1241
+ * both. That also means the keyboard contract is the button's — Enter and Space, for free and correct.
1242
+ */
1243
+ declare class KxList {
1244
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxList, never>;
1245
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxList, "ul[kxList], ol[kxList]", never, {}, {}, never, never, true, never>;
1246
+ }
1247
+ declare class KxListItem {
1248
+ readonly title: i0.InputSignal<string>;
1249
+ readonly description: i0.InputSignal<string>;
1250
+ readonly disabled: i0.InputSignalWithTransform<boolean, unknown>;
1251
+ /** Set to render the row as a button. Without it the row is static text and not focusable. */
1252
+ readonly pressable: i0.InputSignalWithTransform<boolean, unknown>;
1253
+ readonly select: i0.OutputEmitterRef<void>;
1254
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxListItem, never>;
1255
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxListItem, "li[kxListItem]", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "description": { "alias": "description"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "pressable": { "alias": "pressable"; "required": false; "isSignal": true; }; }, { "select": "select"; }, never, ["[kxListLeading]", "[kxListTrailing]"], true, never>;
1256
+ }
1257
+ /**
1258
+ * <kx-marquee [durationSeconds]="24" pauseOnHover>
1259
+ * <ng-template kxMarqueeContent>
1260
+ * <span>Shipping to 48 countries</span>
1261
+ * </ng-template>
1262
+ * </kx-marquee>
1263
+ *
1264
+ * Scrolls its content on a loop. A seamless loop needs the content rendered twice, and the content is the
1265
+ * caller's — so it arrives as a `<ng-template>` and this component renders it twice itself. Asking the caller
1266
+ * to paste their own markup twice would make the duplicate their problem and let the two copies drift.
1267
+ *
1268
+ * The second copy is `aria-hidden`, so assistive technology reads the row once instead of stuttering.
1269
+ *
1270
+ * Under `prefers-reduced-motion: reduce` the animation is removed in CSS and the row becomes an ordinary
1271
+ * horizontally scrollable strip — the content stays reachable, which is the part that matters. Continuous
1272
+ * motion is what WCAG 2.2.2 is about, and the reader's own setting is the control, so this exposes no
1273
+ * "pause" affordance that would only work for people who can see it move.
1274
+ */
1275
+ declare class KxMarqueeContent {
1276
+ readonly template: TemplateRef<unknown>;
1277
+ constructor(template: TemplateRef<unknown>);
1278
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxMarqueeContent, never>;
1279
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxMarqueeContent, "[kxMarqueeContent]", never, {}, {}, never, never, true, never>;
1280
+ }
1281
+ declare class KxMarquee {
1282
+ /** Seconds for one full loop. Slower is calmer; this is a readability decision, not a style one. */
1283
+ readonly durationSeconds: i0.InputSignal<number>;
1284
+ readonly pauseOnHover: i0.InputSignalWithTransform<boolean, unknown>;
1285
+ protected readonly content: i0.Signal<KxMarqueeContent>;
1286
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxMarquee, never>;
1287
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxMarquee, "kx-marquee", never, { "durationSeconds": { "alias": "durationSeconds"; "required": false; "isSignal": true; }; "pauseOnHover": { "alias": "pauseOnHover"; "required": false; "isSignal": true; }; }, {}, ["content"], never, true, never>;
1288
+ }
1289
+ /**
1290
+ * <kx-page-header title="Billing" description="Plan, invoices and payment method" [level]="1">
1291
+ * <nav kxPageHeaderBreadcrumb>…</nav>
1292
+ * <button kxButton kxPageHeaderActions>Upgrade</button>
1293
+ * </kx-page-header>
1294
+ *
1295
+ * `level` exists for the same reason `kx-card-title` has one: a page header is usually the `<h1>`, but a
1296
+ * component that hard-codes a heading level produces a broken document outline the moment it is used twice or
1297
+ * nested. The level is carried by `role="heading"` + `aria-level`, because `<ng-content>` projects once and a
1298
+ * template with one heading tag per branch silently renders every branch after the first empty — the same
1299
+ * trade-off `primitives.ts` documents, resolved the same way.
1300
+ */
1301
+ declare class KxPageHeader {
1302
+ readonly title: i0.InputSignal<string>;
1303
+ readonly description: i0.InputSignal<string>;
1304
+ readonly level: i0.InputSignal<number>;
1305
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxPageHeader, never>;
1306
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxPageHeader, "kx-page-header", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "description": { "alias": "description"; "required": false; "isSignal": true; }; "level": { "alias": "level"; "required": false; "isSignal": true; }; }, {}, never, ["[kxPageHeaderBreadcrumb]", "[kxPageHeaderActions]", "*"], true, never>;
1307
+ }
1308
+ /**
1309
+ * <ol kxTimeline>
1310
+ * <li kxTimelineItem title="Shipped" description="14 March" status="success" />
1311
+ * </ol>
1312
+ *
1313
+ * An ordered list, because a timeline is ordered and the platform already says so — losing that to a stack of
1314
+ * `<div>`s would mean a screen reader no longer announces "3 of 5".
1315
+ *
1316
+ * `status` is carried by a class on a decorative marker plus text, never by colour alone: the item's state is
1317
+ * in `title`/`description`, which is what WCAG 1.4.1 asks for. The connecting line is drawn with logical
1318
+ * insets so it stays on the start edge in an RTL page.
1319
+ */
1320
+ declare class KxTimeline {
1321
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxTimeline, never>;
1322
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxTimeline, "ol[kxTimeline]", never, {}, {}, never, never, true, never>;
1323
+ }
1324
+ declare class KxTimelineItem {
1325
+ readonly title: i0.InputSignal<string>;
1326
+ readonly description: i0.InputSignal<string>;
1327
+ readonly status: i0.InputSignal<KxTimelineStatus>;
1328
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxTimelineItem, never>;
1329
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxTimelineItem, "li[kxTimelineItem]", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "description": { "alias": "description"; "required": false; "isSignal": true; }; "status": { "alias": "status"; "required": false; "isSignal": true; }; }, {}, never, ["[kxTimelineIcon]", "*"], true, never>;
1330
+ }
1331
+
1332
+ /**
1333
+ * <kx-accordion type="single" collapsible [(value)]="open">
1334
+ * <kx-accordion-item value="shipping">
1335
+ * <kx-accordion-trigger>Shipping</kx-accordion-trigger>
1336
+ * <kx-accordion-content>Orders leave the warehouse within two working days.</kx-accordion-content>
1337
+ * </kx-accordion-item>
1338
+ * </kx-accordion>
1339
+ *
1340
+ * `value` is the list of open items' values, in both modes — in `single` it holds at most one. One shape for
1341
+ * both modes keeps the two-way binding typed without a union the template would have to narrow.
1342
+ */
1343
+ declare class KxAccordion {
1344
+ readonly type: i0.InputSignal<"single" | "multiple">;
1345
+ /** In `single` mode, whether the open item may be closed again, leaving none open. */
1346
+ readonly collapsible: i0.InputSignalWithTransform<boolean, unknown>;
1347
+ readonly disabled: i0.InputSignalWithTransform<boolean, unknown>;
1348
+ /** The heading level each trigger sits in. */
1349
+ readonly headingLevel: i0.InputSignalWithTransform<number, unknown>;
1350
+ /** Two-way: the values of the open items. */
1351
+ readonly value: i0.ModelSignal<readonly string[]>;
1352
+ private readonly triggers;
1353
+ isOpen(item: string): boolean;
1354
+ /** Whether activating this open item would do nothing — a single accordion that is not collapsible. */
1355
+ locked(item: string): boolean;
1356
+ toggle(item: string): void;
1357
+ /** APG accordion keys, on the triggers: focus moves, nothing opens. */
1358
+ onKeydown(event: KeyboardEvent, from: KxAccordionTrigger): void;
1359
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxAccordion, never>;
1360
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxAccordion, "kx-accordion", never, { "type": { "alias": "type"; "required": false; "isSignal": true; }; "collapsible": { "alias": "collapsible"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "headingLevel": { "alias": "headingLevel"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, ["triggers"], ["*"], true, never>;
1361
+ }
1362
+ declare class KxAccordionItem {
1363
+ readonly accordion: KxAccordion;
1364
+ readonly value: i0.InputSignal<string>;
1365
+ readonly disabled: i0.InputSignalWithTransform<boolean, unknown>;
1366
+ private readonly id;
1367
+ readonly triggerId: string;
1368
+ readonly contentId: string;
1369
+ readonly open: i0.Signal<boolean>;
1370
+ readonly isDisabled: i0.Signal<boolean>;
1371
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxAccordionItem, never>;
1372
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxAccordionItem, "kx-accordion-item", never, { "value": { "alias": "value"; "required": true; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1373
+ }
1374
+ /**
1375
+ * The heading and its button. The chevron is built in (as the dismiss glyph is in banner and inform): a
1376
+ * disclosure control whose only state cue is the caller remembering to add an icon is one nobody can see.
1377
+ * It points down and turns to point up when open. It does not mirror in RTL — down is down in both directions.
1378
+ */
1379
+ declare class KxAccordionTrigger {
1380
+ readonly item: KxAccordionItem;
1381
+ private readonly button;
1382
+ focus(): void;
1383
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxAccordionTrigger, never>;
1384
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxAccordionTrigger, "kx-accordion-trigger", never, {}, {}, never, ["*"], true, never>;
1385
+ }
1386
+ declare class KxAccordionContent {
1387
+ readonly item: KxAccordionItem;
1388
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxAccordionContent, never>;
1389
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxAccordionContent, "kx-accordion-content", never, {}, {}, never, ["*"], true, never>;
1390
+ }
1391
+ /**
1392
+ * <kx-collapsible [(open)]="showAdvanced">
1393
+ * <button kxButton kxCollapsibleTrigger variant="Ghost">Advanced settings</button>
1394
+ * <kx-collapsible-content>…</kx-collapsible-content>
1395
+ * </kx-collapsible>
1396
+ *
1397
+ * One trigger, one region. The trigger is a directive on the caller's own `<button>`, so it can be any button
1398
+ * the design calls for (a ghost `kxButton`, a link-styled one) and keeps every native behaviour.
1399
+ */
1400
+ declare class KxCollapsible {
1401
+ /** Two-way: whether the content is shown. */
1402
+ readonly open: i0.ModelSignal<boolean>;
1403
+ readonly disabled: i0.InputSignalWithTransform<boolean, unknown>;
1404
+ readonly contentId: string;
1405
+ toggle(): void;
1406
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxCollapsible, never>;
1407
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxCollapsible, "kx-collapsible", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "open": "openChange"; }, never, ["*"], true, never>;
1408
+ }
1409
+ declare class KxCollapsibleTrigger {
1410
+ readonly collapsible: KxCollapsible;
1411
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxCollapsibleTrigger, never>;
1412
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxCollapsibleTrigger, "button[kxCollapsibleTrigger]", never, {}, {}, never, never, true, never>;
1413
+ }
1414
+ declare class KxCollapsibleContent {
1415
+ readonly collapsible: KxCollapsible;
1416
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxCollapsibleContent, never>;
1417
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxCollapsibleContent, "kx-collapsible-content", never, {}, {}, never, ["*"], true, never>;
1418
+ }
1419
+
1420
+ /**
1421
+ * Navigation: breadcrumb, pagination, table of contents, tab bar, stepper, navigation bar, app bar, footer.
1422
+ *
1423
+ * ── The shared contract (written before the code) ──────────────────────────
1424
+ *
1425
+ * Links stay links. A destination is an `<a href>` the caller writes, so middle-click, "copy link", the
1426
+ * router's own directives and the browser's link semantics all keep working. Where a destination can also be
1427
+ * an in-page action (a client-side pager, a tab bar that swaps views), the same directive also accepts a
1428
+ * `<button>`. Nothing here turns navigation into a generic button to make it easier to test.
1429
+ *
1430
+ * "You are here" is `aria-current`, set by one boolean input (`current` / `active`):
1431
+ * page breadcrumb's last crumb, pagination's page, an app-bar or tab-bar destination
1432
+ * location a table-of-contents entry (a position within the page, not a page)
1433
+ * step the stepper's current step
1434
+ * It is never conveyed by colour alone: the current item also carries a shape cue — an indicator bar, a
1435
+ * raised outlined surface or a weight change — measured by `check:navigation-visual`.
1436
+ *
1437
+ * Keyboard: every destination is one Tab stop and Enter follows it, which is what a list of links is. None of
1438
+ * these is a composite widget, so none takes arrow keys — a roving tabindex on a breadcrumb or a footer would
1439
+ * hide links from Tab and teach the reader a pattern nothing announces. (The arrow-key pattern is Tabs'.)
1440
+ *
1441
+ * Direction. Layout is logical throughout (inline-start/end, padding-inline), so every row runs from the
1442
+ * inline start of the direction its own element resolves to. Glyphs that point along the reading direction —
1443
+ * the breadcrumb separator, Previous / Next, Back — are the Unicode angle quotation marks ‹ ›, which the bidi
1444
+ * algorithm mirrors in a right-to-left run. That makes the glyph follow the EFFECTIVE direction of the element
1445
+ * it is in, including an LTR region inside an RTL page, with no rule keyed on a `[dir]` ancestor (wrong when
1446
+ * nested) and no `:dir()` (which some CSS pipelines lower to a guess — TOKENS.md, "Switch direction"). The
1447
+ * pixels are checked: `check:angular-browser`'s RTL pass reads which way each glyph actually points.
1448
+ */
1449
+ /**
1450
+ * <nav kxBreadcrumb>
1451
+ * <ol kxBreadcrumbList>
1452
+ * <li kxBreadcrumbItem><a kxBreadcrumbLink href="/">Home</a></li>
1453
+ * <li kxBreadcrumbSeparator></li>
1454
+ * <li kxBreadcrumbItem><span kxBreadcrumbPage>Settings</span></li>
1455
+ * </ol>
1456
+ * </nav>
1457
+ *
1458
+ * The landmark is named "Breadcrumb" unless the caller names it (`label`). The current page is plain text with
1459
+ * `aria-current="page"`, not a link to itself.
1460
+ */
1461
+ declare class KxBreadcrumb {
1462
+ readonly label: i0.InputSignal<string>;
1463
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxBreadcrumb, never>;
1464
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxBreadcrumb, "nav[kxBreadcrumb]", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1465
+ }
1466
+ declare class KxBreadcrumbList {
1467
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxBreadcrumbList, never>;
1468
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxBreadcrumbList, "ol[kxBreadcrumbList]", never, {}, {}, never, never, true, never>;
1469
+ }
1470
+ declare class KxBreadcrumbItem {
1471
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxBreadcrumbItem, never>;
1472
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxBreadcrumbItem, "li[kxBreadcrumbItem]", never, {}, {}, never, never, true, never>;
1473
+ }
1474
+ declare class KxBreadcrumbLink {
1475
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxBreadcrumbLink, never>;
1476
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxBreadcrumbLink, "a[kxBreadcrumbLink]", never, {}, {}, never, never, true, never>;
1477
+ }
1478
+ declare class KxBreadcrumbPage {
1479
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxBreadcrumbPage, never>;
1480
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxBreadcrumbPage, "span[kxBreadcrumbPage]", never, {}, {}, never, never, true, never>;
1481
+ }
1482
+ /** Hidden from assistive technology: the list already says these are steps of a path. */
1483
+ declare class KxBreadcrumbSeparator {
1484
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxBreadcrumbSeparator, never>;
1485
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxBreadcrumbSeparator, "li[kxBreadcrumbSeparator]", never, {}, {}, never, ["*"], true, never>;
1486
+ }
1487
+ /**
1488
+ * A disabled `<button>` is `disabled`. A link has no disabled state, so a disabled link reports
1489
+ * `aria-disabled="true"`, leaves the tab order, and swallows its click — it stays in the list, so the reader
1490
+ * still learns there is no previous page, rather than finding a gap.
1491
+ */
1492
+ declare abstract class KxDestination {
1493
+ private readonly el;
1494
+ readonly disabled: i0.InputSignalWithTransform<boolean, unknown>;
1495
+ readonly isButton: boolean;
1496
+ onClick(event: Event): void;
1497
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxDestination, never>;
1498
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxDestination, never, never, { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1499
+ }
1500
+ /**
1501
+ * <nav kxPagination>
1502
+ * <ul kxPaginationContent>
1503
+ * <li kxPaginationItem><a kxPaginationPrevious href="?page=1">Previous</a></li>
1504
+ * <li kxPaginationItem><a kxPaginationLink href="?page=1">1</a></li>
1505
+ * <li kxPaginationItem><a kxPaginationLink href="?page=2" current>2</a></li>
1506
+ * <li kxPaginationItem><kx-pagination-ellipsis /></li>
1507
+ * <li kxPaginationItem><a kxPaginationNext href="?page=3">Next</a></li>
1508
+ * </ul>
1509
+ * </nav>
1510
+ *
1511
+ * The caller owns which page is current — the same division React's Pagination makes — because only the
1512
+ * application knows its routes. `<button>` works in place of every `<a>` for a pager that changes state
1513
+ * rather than the URL.
1514
+ */
1515
+ declare class KxPagination {
1516
+ readonly label: i0.InputSignal<string>;
1517
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxPagination, never>;
1518
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxPagination, "nav[kxPagination]", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1519
+ }
1520
+ declare class KxPaginationContent {
1521
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxPaginationContent, never>;
1522
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxPaginationContent, "ul[kxPaginationContent]", never, {}, {}, never, never, true, never>;
1523
+ }
1524
+ declare class KxPaginationItem {
1525
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxPaginationItem, never>;
1526
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxPaginationItem, "li[kxPaginationItem]", never, {}, {}, never, never, true, never>;
1527
+ }
1528
+ declare class KxPaginationLink extends KxDestination {
1529
+ readonly current: i0.InputSignalWithTransform<boolean, unknown>;
1530
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxPaginationLink, never>;
1531
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxPaginationLink, "a[kxPaginationLink], button[kxPaginationLink]", never, { "current": { "alias": "current"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1532
+ }
1533
+ /**
1534
+ * Previous and Next: the visible word is the accessible name (default "Previous" / "Next", replaceable by
1535
+ * projecting text, because this package ships no translations). The glyph is decorative and mirrors with the
1536
+ * reading direction.
1537
+ */
1538
+ declare class KxPaginationPrevious extends KxDestination {
1539
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxPaginationPrevious, never>;
1540
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxPaginationPrevious, "a[kxPaginationPrevious], button[kxPaginationPrevious]", never, {}, {}, never, ["*"], true, never>;
1541
+ }
1542
+ declare class KxPaginationNext extends KxDestination {
1543
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxPaginationNext, never>;
1544
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxPaginationNext, "a[kxPaginationNext], button[kxPaginationNext]", never, {}, {}, never, ["*"], true, never>;
1545
+ }
1546
+ /** A gap in the page range. Decorative: the numbers either side already say pages were skipped. */
1547
+ declare class KxPaginationEllipsis {
1548
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxPaginationEllipsis, never>;
1549
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxPaginationEllipsis, "kx-pagination-ellipsis", never, {}, {}, never, never, true, never>;
1550
+ }
1551
+ interface KxTocItem {
1552
+ /** The id of the heading this entry links to (`href="#id"`). */
1553
+ id: string;
1554
+ label: string;
1555
+ /** Nesting depth, from 1. Each level indents from the inline start. */
1556
+ level?: number;
1557
+ }
1558
+ /**
1559
+ * <nav kxTableOfContents [items]="sections" [(active)]="section"></nav>
1560
+ *
1561
+ * In-page anchors, so they work with no JavaScript and with the browser's own scrolling. The entry for the
1562
+ * section being read carries `aria-current="location"`; `active` is two-way so a click marks its entry at once,
1563
+ * and an application with a scroll-spy writes the same signal from its observer.
1564
+ */
1565
+ declare class KxTableOfContents {
1566
+ readonly items: i0.InputSignal<readonly KxTocItem[]>;
1567
+ readonly active: i0.ModelSignal<string>;
1568
+ readonly label: i0.InputSignal<string>;
1569
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxTableOfContents, never>;
1570
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxTableOfContents, "nav[kxTableOfContents]", never, { "items": { "alias": "items"; "required": true; "isSignal": true; }; "active": { "alias": "active"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, { "active": "activeChange"; }, never, never, true, never>;
1571
+ }
1572
+ /**
1573
+ * <nav kxTabBar aria-label="Primary">
1574
+ * <a kxTabBarItem href="/home" active><svg kxTabBarIcon …></svg>Home</a>
1575
+ * <a kxTabBarItem href="/inbox" badge="3"><svg kxTabBarIcon …></svg>Inbox</a>
1576
+ * </nav>
1577
+ *
1578
+ * A phone's bottom navigation: a row of destinations, each an icon over its label. The label is always
1579
+ * visible and is the accessible name; the icon is projected and decorative. The current destination is
1580
+ * `aria-current="page"`, drawn with a full-strength label, an `--action` icon AND a pill behind it, so it does
1581
+ * not depend on hue (React's TabBar colours the label only).
1582
+ *
1583
+ * Not a `tablist`: these are destinations, not panels of one view, so they are links in a navigation landmark
1584
+ * and each is its own Tab stop.
1585
+ */
1586
+ declare class KxTabBar {
1587
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxTabBar, never>;
1588
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxTabBar, "nav[kxTabBar]", never, {}, {}, never, never, true, never>;
1589
+ }
1590
+ declare class KxTabBarItem extends KxDestination {
1591
+ readonly active: i0.InputSignalWithTransform<boolean, unknown>;
1592
+ /**
1593
+ * A short count shown on the icon. The painted badge is hidden from assistive technology and the same text
1594
+ * follows the label, so the name reads "Inbox (3)" — label first — rather than "3Inbox", which is what a
1595
+ * badge drawn before the label contributes. The space sits inside the hidden text, so the name is the same
1596
+ * whether or not the caller's label carries whitespace of its own.
1597
+ */
1598
+ readonly badge: i0.InputSignal<string | number>;
1599
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxTabBarItem, never>;
1600
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxTabBarItem, "a[kxTabBarItem], button[kxTabBarItem]", never, { "active": { "alias": "active"; "required": false; "isSignal": true; }; "badge": { "alias": "badge"; "required": false; "isSignal": true; }; }, {}, never, ["[kxTabBarIcon]", "*"], true, never>;
1601
+ }
1602
+ interface KxStep {
1603
+ label: string;
1604
+ description?: string;
1605
+ }
1606
+ /**
1607
+ * <ol kxStepper [steps]="steps" [current]="1"></ol>
1608
+ *
1609
+ * Progress through a fixed sequence: an ordered list, so position and count are announced by the list itself.
1610
+ * Each step is complete, current or upcoming, derived from `current` (zero-based) against its index. Current is
1611
+ * `aria-current="step"`. Complete steps also carry visually hidden text (`completedLabel`) — the check mark
1612
+ * that replaces their number is decorative, and without the text a screen reader would hear the label and
1613
+ * nothing else. Display only: a step is not a control (React's Stepper is not either).
1614
+ */
1615
+ declare class KxStepper {
1616
+ readonly steps: i0.InputSignal<readonly KxStep[]>;
1617
+ /** Zero-based index of the step in progress. */
1618
+ readonly current: i0.InputSignalWithTransform<number, unknown>;
1619
+ readonly orientation: i0.InputSignal<KxOrientation>;
1620
+ readonly completedLabel: i0.InputSignal<string>;
1621
+ status(index: number): 'complete' | 'current' | 'upcoming';
1622
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxStepper, never>;
1623
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxStepper, "ol[kxStepper]", never, { "steps": { "alias": "steps"; "required": true; "isSignal": true; }; "current": { "alias": "current"; "required": false; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "completedLabel": { "alias": "completedLabel"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1624
+ }
1625
+ /**
1626
+ * <header kxNavigationBar title="Inbox" infoText="3 unread" backButton (back)="location.back()">
1627
+ * <button kxButton kxNavigationBarActions variant="Ghost">Edit</button>
1628
+ * </header>
1629
+ *
1630
+ * A phone's top bar for one screen: an optional Back control, the screen's title (with optional info text) and
1631
+ * trailing actions. The title wraps rather than truncating: at 200% text a cut-off title is a title nobody can
1632
+ * read. `level` makes the title a heading when the bar is what names the screen.
1633
+ *
1634
+ * Back is a named button (`backLabel`, default "Back") whose glyph points toward the inline start.
1635
+ */
1636
+ declare class KxNavigationBar {
1637
+ readonly title: i0.InputSignal<string>;
1638
+ readonly infoText: i0.InputSignal<string>;
1639
+ readonly backButton: i0.InputSignalWithTransform<boolean, unknown>;
1640
+ readonly backLabel: i0.InputSignal<string>;
1641
+ /** A heading level for the title, or none (the default) when the page names itself elsewhere. */
1642
+ readonly level: i0.InputSignal<number>;
1643
+ readonly back: i0.OutputEmitterRef<void>;
1644
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxNavigationBar, never>;
1645
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxNavigationBar, "header[kxNavigationBar], div[kxNavigationBar]", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "infoText": { "alias": "infoText"; "required": false; "isSignal": true; }; "backButton": { "alias": "backButton"; "required": false; "isSignal": true; }; "backLabel": { "alias": "backLabel"; "required": false; "isSignal": true; }; "level": { "alias": "level"; "required": false; "isSignal": true; }; }, { "back": "back"; }, never, ["[kxNavigationBarLeading]", "[kxNavigationBarActions]"], true, never>;
1646
+ }
1647
+ /**
1648
+ * <header kxAppBar>
1649
+ * <a kxAppBarBrand href="/">Acme</a>
1650
+ * <nav kxAppBarNav aria-label="Primary">
1651
+ * <a kxAppBarLink href="/" active>Overview</a>
1652
+ * <a kxAppBarLink href="/reports">Reports</a>
1653
+ * </nav>
1654
+ * <div kxAppBarActions><button kxButton size="sm">New</button></div>
1655
+ * </header>
1656
+ *
1657
+ * A web application's top bar. From 48rem up the navigation is a row between the brand and the actions. Below
1658
+ * it, the same `<nav>` — one element, not a copy — becomes a disclosure under the bar, opened by a Menu button
1659
+ * (`aria-expanded`, `aria-controls`). In DOM order the button comes straight before the panel it opens, so Tab
1660
+ * goes from the button into the links. The panel animates like accordion content (disclosure.ts), Escape
1661
+ * closes it and returns focus to the button, and following a link closes it.
1662
+ */
1663
+ declare class KxAppBar {
1664
+ /** Two-way: whether the narrow-screen menu is open. Ignored from 48rem up, where the links are always shown. */
1665
+ readonly open: i0.ModelSignal<boolean>;
1666
+ readonly sticky: i0.InputSignalWithTransform<boolean, unknown>;
1667
+ /** The menu button's name. Its open/closed state is `aria-expanded`, so the name does not change with it. */
1668
+ readonly menuLabel: i0.InputSignal<string>;
1669
+ readonly navId: string;
1670
+ private readonly toggle;
1671
+ close(returnFocus?: boolean): void;
1672
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxAppBar, never>;
1673
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxAppBar, "header[kxAppBar]", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "sticky": { "alias": "sticky"; "required": false; "isSignal": true; }; "menuLabel": { "alias": "menuLabel"; "required": false; "isSignal": true; }; }, { "open": "openChange"; }, never, ["[kxAppBarBrand]", "[kxAppBarNav]", "[kxAppBarActions]", "*"], true, never>;
1674
+ }
1675
+ declare class KxAppBarBrand {
1676
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxAppBarBrand, never>;
1677
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxAppBarBrand, "[kxAppBarBrand]", never, {}, {}, never, never, true, never>;
1678
+ }
1679
+ declare class KxAppBarNav {
1680
+ readonly bar: KxAppBar;
1681
+ /** Following a link closes the narrow menu; the page it leads to should not open under a menu. */
1682
+ onClick(event: Event): void;
1683
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxAppBarNav, never>;
1684
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxAppBarNav, "nav[kxAppBarNav]", never, {}, {}, never, ["*"], true, never>;
1685
+ }
1686
+ declare class KxAppBarLink {
1687
+ readonly active: i0.InputSignalWithTransform<boolean, unknown>;
1688
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxAppBarLink, never>;
1689
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxAppBarLink, "a[kxAppBarLink]", never, { "active": { "alias": "active"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1690
+ }
1691
+ declare class KxAppBarActions {
1692
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxAppBarActions, never>;
1693
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxAppBarActions, "[kxAppBarActions]", never, {}, {}, never, never, true, never>;
1694
+ }
1695
+ /**
1696
+ * <footer kxFooter>
1697
+ * <div kxFooterColumns>
1698
+ * <kx-footer-column title="Product">
1699
+ * <a kxFooterLink href="/pricing">Pricing</a>
1700
+ * </kx-footer-column>
1701
+ * </div>
1702
+ * <div kxFooterBottom>© 2026 Acme</div>
1703
+ * </footer>
1704
+ *
1705
+ * The caller's own `<footer>`, so the `contentinfo` landmark is the browser's. Each column is a `group` named by
1706
+ * its title, so a screen reader announces "Product, group" on entry instead of a run of unrelated links.
1707
+ */
1708
+ declare class KxFooter {
1709
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxFooter, never>;
1710
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxFooter, "footer[kxFooter]", never, {}, {}, never, never, true, never>;
1711
+ }
1712
+ declare class KxFooterColumns {
1713
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxFooterColumns, never>;
1714
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxFooterColumns, "[kxFooterColumns]", never, {}, {}, never, never, true, never>;
1715
+ }
1716
+ declare class KxFooterColumn {
1717
+ readonly title: i0.InputSignal<string>;
1718
+ readonly titleId: string;
1719
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxFooterColumn, never>;
1720
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxFooterColumn, "kx-footer-column", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1721
+ }
1722
+ declare class KxFooterLink {
1723
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxFooterLink, never>;
1724
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxFooterLink, "a[kxFooterLink]", never, {}, {}, never, never, true, never>;
1725
+ }
1726
+ declare class KxFooterBottom {
1727
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxFooterBottom, never>;
1728
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxFooterBottom, "[kxFooterBottom]", never, {}, {}, never, never, true, never>;
1729
+ }
1730
+
1731
+ /**
1732
+ * The overlay layer: one small set of primitives every floating or modal surface in this package stands on.
1733
+ * Nothing in this file is exported from `public-api.ts` — it is infrastructure the dialog family
1734
+ * (dialog.ts) and the floating family (floating.ts) share, and that Wave C2's menus and listboxes will
1735
+ * consume. Its contract is documented in TOKENS.md ("Overlays") and ANGULAR-GRADUATION.md.
1736
+ *
1737
+ * ── Rendering: the browser's top layer, not a portal ───────────────────────
1738
+ *
1739
+ * An overlay has to escape every clipping and stacking context its trigger lives in: an `overflow: hidden`
1740
+ * card, a transformed app shell, a sticky header with its own z-index. The usual answer is a portal that
1741
+ * moves the surface's DOM to the end of `<body>`. That costs Angular a great deal: the content leaves the
1742
+ * element injector it was declared under, inherits styles (and `dir`) from `<body>` instead of from where it
1743
+ * was written, and needs a host outlet and teardown of its own.
1744
+ *
1745
+ * The platform now has the answer built in. A modal surface is a real `<dialog>` opened with `showModal()`,
1746
+ * and a floating surface carries `popover="manual"` and is shown with `showPopover()`. Both put the element
1747
+ * in the TOP LAYER: rendered above everything, positioned against the viewport, outside every ancestor's
1748
+ * overflow clip, transform and z-index — while staying exactly where the template declared it in the DOM.
1749
+ * So DI, change detection, CSS inheritance and the direction a nested `dir` region resolves to all keep
1750
+ * working with no code, and there is no z-index anywhere in this layer. Order in the top layer is the order
1751
+ * surfaces were shown, which is the stacking order this file's stack keeps.
1752
+ *
1753
+ * `showModal()` also makes everything outside the dialog inert: the background leaves the tab order and the
1754
+ * accessibility tree, which is the containment a modal needs, from the browser rather than from an
1755
+ * `aria-hidden` sweep over siblings.
1756
+ *
1757
+ * SSR: nothing here touches the DOM when a component is created. A server renders closed elements (`<dialog>`
1758
+ * without `open`, a `[popover]` that is not shown); every call below runs from a browser-only render hook or an
1759
+ * event handler.
1760
+ *
1761
+ * ── The stack ──────────────────────────────────────────────────────────────
1762
+ *
1763
+ * `KxOverlayStack` keeps open layers in the order they opened. It owns the three document listeners every
1764
+ * overlay needs — keydown, pointerdown and focusin — installed when the first layer opens and removed when
1765
+ * the last one closes, so a page with no open overlay has none of them.
1766
+ *
1767
+ * Escape goes to the TOPMOST layer only, and the keydown's default is prevented so a native
1768
+ * `<dialog>` underneath never also receives a close request for the same key press.
1769
+ * An Escape another component already handled (`defaultPrevented`) is left alone.
1770
+ * outside press walks down from the top: each layer the press is outside of is asked to close; it stops
1771
+ * at the first layer the press is inside, and after the first modal layer (nothing beneath a
1772
+ * modal can have been pressed). "Inside" is the layer's own DOM subtree plus its companions
1773
+ * (its trigger and anchor). A popover declared inside a dialog is inside that dialog's
1774
+ * subtree, so pressing the popover can never read as a press outside its dialog.
1775
+ * focus outside the same walk for focus, for the layers whose policy asks for it (non-modal surfaces).
1776
+ * nesting closing a layer first closes every open layer nested inside its subtree.
1777
+ * scroll lock the page's scrolling is held while at least one MODAL layer is open — derived from the
1778
+ * stack on every change, not counted up and down, so it cannot drift: an inner modal closing
1779
+ * leaves it locked while an outer one remains.
1780
+ *
1781
+ * Each layer applies its own policy when asked: an alert dialog declines to close on an outside press.
1782
+ */
1783
+ /** Why the stack is asking a layer to close. `parent` is not a request: the layer it is nested in is closing. */
1784
+ type KxDismissReason = 'escape' | 'outside' | 'focus-outside' | 'parent';
1785
+ interface KxLayer {
1786
+ readonly modal: boolean;
1787
+ /** Whether this layer closes when focus moves outside it (non-modal surfaces). */
1788
+ readonly closesOnFocusOutside: boolean;
1789
+ /** The surface element. Inside it is inside the layer. */
1790
+ surface(): HTMLElement | null;
1791
+ /** Elements outside the surface that belong to it — its trigger, its anchor. */
1792
+ companions(): readonly (Element | null | undefined)[];
1793
+ /** The stack asks the layer to close. The layer decides, by its own policy, whether it does. */
1794
+ request(reason: KxDismissReason): void;
1795
+ }
1796
+ /**
1797
+ * Where a floating surface goes, relative to the element it belongs to. The contract is deliberately small:
1798
+ *
1799
+ * side top | bottom | start | end — start and end are LOGICAL: they resolve to left or right by the
1800
+ * direction the anchor itself computes to, so a popover set to open "toward the end" opens to the
1801
+ * right in an LTR page and to the left in an RTL one (and in a nested region, by that region)
1802
+ * align start | center | end along the other axis, logical in the same way
1803
+ * offset the gap between anchor and surface, in px
1804
+ *
1805
+ * Collision handling, in order: FLIP to the opposite side when the chosen one lacks the room and the
1806
+ * opposite has more; SHIFT along the cross axis so the surface stays `padding` inside the viewport; and CAP
1807
+ * the surface's size to the room it has (`maxWidth`, `maxHeight`, published as CSS custom properties) so large
1808
+ * text or a phone-sized viewport makes it scroll inside itself rather than run off the screen.
1809
+ *
1810
+ * Pure: rects in, coordinates out. The DOM side (`autoPlace`) measures, calls this, writes the result.
1811
+ */
1812
+ type KxSide = 'top' | 'bottom' | 'start' | 'end';
1813
+ type KxAlign = 'start' | 'center' | 'end';
1814
+
1815
+ /** The state every member of the family shares. */
1816
+ declare abstract class KxDialogRoot {
1817
+ /** Two-way: whether the surface is open. */
1818
+ readonly open: i0.ModelSignal<boolean>;
1819
+ /**
1820
+ * Where focus goes on close when the element that opened it is gone — say, a row the dialog just deleted.
1821
+ * Used only when the element focused before opening is no longer a valid focus target.
1822
+ */
1823
+ readonly returnFocus: i0.InputSignal<HTMLElement>;
1824
+ private readonly base;
1825
+ /** Each part's own `id` input, static or bound, registered by the part as it is created. */
1826
+ readonly contentIdFrom: i0.WritableSignal<Signal<string>>;
1827
+ readonly titleIdFrom: i0.WritableSignal<Signal<string>>;
1828
+ readonly descriptionIdFrom: i0.WritableSignal<Signal<string>>;
1829
+ /** Generated, unless the part has an `id` of its own (`id="…"` or `[id]="…"`) — then that one, as it changes. */
1830
+ readonly contentId: Signal<string>;
1831
+ readonly titleId: Signal<string>;
1832
+ readonly descriptionId: Signal<string>;
1833
+ /** The trigger, when there is one: a fallback focus target on close. */
1834
+ trigger: HTMLElement | null;
1835
+ show(): void;
1836
+ close(): void;
1837
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxDialogRoot, never>;
1838
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxDialogRoot, never, never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "returnFocus": { "alias": "returnFocus"; "required": false; "isSignal": true; }; }, { "open": "openChange"; }, never, never, true, never>;
1839
+ }
1840
+ /**
1841
+ * <kx-dialog [(open)]="editing">
1842
+ * <button kxButton kxDialogTrigger>Edit profile</button>
1843
+ * <dialog kxDialogContent>
1844
+ * <kx-dialog-header>
1845
+ * <h2 kxDialogTitle>Edit profile</h2>
1846
+ * <p kxDialogDescription>Changes are saved when you press Save.</p>
1847
+ * </kx-dialog-header>
1848
+ * …
1849
+ * <kx-dialog-footer>
1850
+ * <button kxButton variant="Outline" kxDialogClose>Cancel</button>
1851
+ * <button kxButton (click)="save()">Save</button>
1852
+ * </kx-dialog-footer>
1853
+ * </dialog>
1854
+ * </kx-dialog>
1855
+ */
1856
+ declare class KxDialog extends KxDialogRoot {
1857
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxDialog, never>;
1858
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxDialog, "kx-dialog", never, {}, {}, never, ["*"], true, never>;
1859
+ }
1860
+ /** An alert dialog: a decision that must be answered. See `kxAlertDialogContent`. */
1861
+ declare class KxAlertDialog extends KxDialogRoot {
1862
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxAlertDialog, never>;
1863
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxAlertDialog, "kx-alert-dialog", never, {}, {}, never, ["*"], true, never>;
1864
+ }
1865
+ /** A sheet: a modal panel from one edge of the viewport. See `kxSheetContent`. */
1866
+ declare class KxSheet extends KxDialogRoot {
1867
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxSheet, never>;
1868
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxSheet, "kx-sheet", never, {}, {}, never, ["*"], true, never>;
1869
+ }
1870
+ /** A drawer: a modal panel from the bottom edge, with a grab handle. See `kxDrawerContent`. */
1871
+ declare class KxDrawer extends KxDialogRoot {
1872
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxDrawer, never>;
1873
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxDrawer, "kx-drawer", never, {}, {}, never, ["*"], true, never>;
1874
+ }
1875
+ /** Opens the surface. On the caller's own button, so it can be any button the design calls for. */
1876
+ declare class KxDialogTrigger {
1877
+ readonly root: KxDialogRoot;
1878
+ constructor();
1879
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxDialogTrigger, never>;
1880
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxDialogTrigger, "button[kxDialogTrigger]", never, {}, {}, never, never, true, never>;
1881
+ }
1882
+ /** Closes the surface — Cancel, Done, a footer's dismiss. */
1883
+ declare class KxDialogClose {
1884
+ readonly root: KxDialogRoot;
1885
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxDialogClose, never>;
1886
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxDialogClose, "button[kxDialogClose]", never, {}, {}, never, never, true, never>;
1887
+ }
1888
+ /**
1889
+ * The surface's name. Put it on a real heading at the level the page needs (`<h2 kxDialogTitle>` in most
1890
+ * applications: the dialog sits above the page's own `<h1>`).
1891
+ */
1892
+ declare class KxDialogTitle {
1893
+ readonly root: KxDialogRoot;
1894
+ /** Your own id for the title, static or bound; the surface's `aria-labelledby` follows it. */
1895
+ readonly id: i0.InputSignal<string>;
1896
+ constructor();
1897
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxDialogTitle, never>;
1898
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxDialogTitle, "[kxDialogTitle]", never, { "id": { "alias": "id"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1899
+ }
1900
+ declare class KxDialogDescription {
1901
+ readonly root: KxDialogRoot;
1902
+ /** Your own id for the description, static or bound; the surface's `aria-describedby` follows it. */
1903
+ readonly id: i0.InputSignal<string>;
1904
+ constructor();
1905
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxDialogDescription, never>;
1906
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxDialogDescription, "[kxDialogDescription]", never, { "id": { "alias": "id"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1907
+ }
1908
+ declare class KxDialogHeader {
1909
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxDialogHeader, never>;
1910
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxDialogHeader, "kx-dialog-header", never, {}, {}, never, ["*"], true, never>;
1911
+ }
1912
+ /**
1913
+ * The actions row. In DOM order (Cancel before the confirming action, as the reader meets them), laid out
1914
+ * toward the inline end; in a narrow surface it stacks in that same order, so what is seen and what Tab
1915
+ * reaches never disagree.
1916
+ */
1917
+ declare class KxDialogFooter {
1918
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxDialogFooter, never>;
1919
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxDialogFooter, "kx-dialog-footer", never, {}, {}, never, ["*"], true, never>;
1920
+ }
1921
+ /** What every modal surface in the family does; the members differ only in role, layout and two policies. */
1922
+ declare abstract class KxModalSurface implements KxLayer {
1923
+ readonly root: KxDialogRoot;
1924
+ protected readonly el: HTMLDialogElement;
1925
+ private readonly stack;
1926
+ private readonly doc;
1927
+ /** The accessible name when there is no `kxDialogTitle` inside. */
1928
+ readonly label: i0.InputSignal<string>;
1929
+ /** Your own id for the surface, static or bound; the trigger's `aria-controls` follows it. */
1930
+ readonly id: i0.InputSignal<string>;
1931
+ readonly modal = true;
1932
+ readonly closesOnFocusOutside = false;
1933
+ /** Whether a press on the backdrop closes it. An alert dialog's answer is no. */
1934
+ protected readonly closesOnOutside: boolean;
1935
+ private readonly titles;
1936
+ private readonly descriptions;
1937
+ protected readonly hasTitle: Signal<boolean>;
1938
+ protected readonly hasDescription: Signal<boolean>;
1939
+ private shown;
1940
+ private returnTo;
1941
+ private parent;
1942
+ constructor();
1943
+ surface(): HTMLElement;
1944
+ companions(): readonly (Element | null)[];
1945
+ request(reason: KxDismissReason): void;
1946
+ /** The member's own first focus, when nothing in the content is marked `autofocus`. */
1947
+ protected initialFocus(): HTMLElement | null;
1948
+ private sync;
1949
+ private own;
1950
+ private focusInitial;
1951
+ private restoreFocus;
1952
+ /**
1953
+ * A close request the stack did not see first (a platform back gesture): route it through the same policy
1954
+ * as Escape. Escape itself never arrives here — the stack consumes the key.
1955
+ */
1956
+ protected onCancel(event: Event): void;
1957
+ /** The browser closed the dialog by itself (a cancel it would not let us prevent): follow it. */
1958
+ protected onNativeClose(): void;
1959
+ protected onKeydown(event: KeyboardEvent): void;
1960
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxModalSurface, never>;
1961
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxModalSurface, never, never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; }, {}, ["titles", "descriptions"], never, true, never>;
1962
+ }
1963
+ /**
1964
+ * <dialog kxDialogContent [closeButton]="true" closeLabel="Close">…</dialog>
1965
+ *
1966
+ * A dialog: centred, `--radius-surface`, modal elevation. The built-in close button (an X, named by
1967
+ * `closeLabel`) comes LAST in the DOM and sits at the inline-end of the top edge, so Tab meets the content
1968
+ * first and the close control last — and the first focus lands in the content, not on the X.
1969
+ */
1970
+ declare class KxDialogContent extends KxModalSurface {
1971
+ /** Whether to show the built-in close button. */
1972
+ readonly closeButton: i0.InputSignalWithTransform<boolean, unknown>;
1973
+ readonly closeLabel: i0.InputSignal<string>;
1974
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxDialogContent, never>;
1975
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxDialogContent, "dialog[kxDialogContent]", never, { "closeButton": { "alias": "closeButton"; "required": false; "isSignal": true; }; "closeLabel": { "alias": "closeLabel"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1976
+ }
1977
+ /**
1978
+ * Cancel and the confirming action of an alert dialog. Put them on your own buttons — usually
1979
+ * `<button kxButton variant="Outline" kxAlertDialogCancel>` and
1980
+ * `<button kxButton variant="Destructive" kxAlertDialogAction>` — in that order. Both close the dialog after
1981
+ * your own click handler has run.
1982
+ */
1983
+ declare class KxAlertDialogCancel {
1984
+ readonly root: KxDialogRoot;
1985
+ readonly el: HTMLButtonElement;
1986
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxAlertDialogCancel, never>;
1987
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxAlertDialogCancel, "button[kxAlertDialogCancel]", never, {}, {}, never, never, true, never>;
1988
+ }
1989
+ declare class KxAlertDialogAction {
1990
+ readonly root: KxDialogRoot;
1991
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxAlertDialogAction, never>;
1992
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxAlertDialogAction, "button[kxAlertDialogAction]", never, {}, {}, never, never, true, never>;
1993
+ }
1994
+ /**
1995
+ * <kx-alert-dialog [(open)]="confirming">
1996
+ * <button kxButton variant="Destructive" kxDialogTrigger>Delete project</button>
1997
+ * <dialog kxAlertDialogContent>
1998
+ * <kx-dialog-header>
1999
+ * <h2 kxDialogTitle>Delete "Atlas"?</h2>
2000
+ * <p kxDialogDescription>Its 214 files are removed for everyone. This cannot be undone.</p>
2001
+ * </kx-dialog-header>
2002
+ * <kx-dialog-footer>
2003
+ * <button kxButton variant="Outline" kxAlertDialogCancel>Cancel</button>
2004
+ * <button kxButton variant="Destructive" kxAlertDialogAction (click)="delete()">Delete project</button>
2005
+ * </kx-dialog-footer>
2006
+ * </dialog>
2007
+ * </kx-alert-dialog>
2008
+ *
2009
+ * A behaviour, not a style: `role="alertdialog"`, so assistive technology announces it as an interruption that
2010
+ * needs an answer. Its defaults make an accidental confirmation harder, not easier:
2011
+ *
2012
+ * - first focus is Cancel, never the destructive action — Enter on arrival declines
2013
+ * - a press on the backdrop does nothing: a decision is not answered by clicking away
2014
+ * - Escape is Cancel (the WAI-ARIA alert dialog pattern allows it, and it is the safe answer)
2015
+ * - no X: the two buttons are the only ways to answer, and they say what they do
2016
+ */
2017
+ declare class KxAlertDialogContent extends KxModalSurface {
2018
+ protected readonly closesOnOutside = false;
2019
+ private readonly cancel;
2020
+ protected initialFocus(): HTMLElement | null;
2021
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxAlertDialogContent, never>;
2022
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxAlertDialogContent, "dialog[kxAlertDialogContent]", never, {}, {}, ["cancel"], ["*"], true, never>;
2023
+ }
2024
+ type KxSheetSide = 'top' | 'bottom' | 'start' | 'end';
2025
+ /**
2026
+ * <kx-sheet [(open)]="filtersOpen">
2027
+ * <button kxButton variant="Outline" kxDialogTrigger>Filters</button>
2028
+ * <dialog kxSheetContent side="end">…</dialog>
2029
+ * </kx-sheet>
2030
+ *
2031
+ * A modal panel against one edge of the viewport, full length along it. `start` and `end` are LOGICAL: an
2032
+ * `end` sheet is on the right in a left-to-right page and on the left in a right-to-left one, resolved by the
2033
+ * direction the sheet's own element computes to — so a sheet inside an RTL region of an LTR page opens from
2034
+ * that region's end. (React's Sheet names physical edges, `left` / `right`; this is a deliberate difference.)
2035
+ *
2036
+ * The panel is as wide as `--kx-sheet-size` (24rem) but never wider than the viewport less 3rem, so the page
2037
+ * behind stays visible — a reader can see where they are and that a press there closes the panel. It scrolls
2038
+ * inside itself, and keeps clear of a device's safe areas.
2039
+ */
2040
+ declare class KxSheetContent extends KxModalSurface {
2041
+ readonly side: i0.InputSignal<KxSheetSide>;
2042
+ readonly closeButton: i0.InputSignalWithTransform<boolean, unknown>;
2043
+ readonly closeLabel: i0.InputSignal<string>;
2044
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxSheetContent, never>;
2045
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxSheetContent, "dialog[kxSheetContent]", never, { "side": { "alias": "side"; "required": false; "isSignal": true; }; "closeButton": { "alias": "closeButton"; "required": false; "isSignal": true; }; "closeLabel": { "alias": "closeLabel"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
2046
+ }
2047
+ /**
2048
+ * <kx-drawer [(open)]="sharing">
2049
+ * <button kxButton kxDialogTrigger>Share</button>
2050
+ * <dialog kxDrawerContent>
2051
+ * <kx-dialog-header><h2 kxDialogTitle>Share</h2></kx-dialog-header>
2052
+ * …
2053
+ * <kx-dialog-footer><button kxButton variant="Outline" kxDialogClose>Done</button></kx-dialog-footer>
2054
+ * </dialog>
2055
+ * </kx-drawer>
2056
+ *
2057
+ * KinetixUI's drawer is a bottom sheet with a grab handle and rounded top corners (React's is vaul's; the
2058
+ * SwiftUI and Compose ports make it their bottom sheet). First focus goes to the PANEL, not to a field inside
2059
+ * it, for the reason React's drawer gives: on a phone, focusing a text field on open raises the keyboard over
2060
+ * the drawer the reader has not yet seen. From the panel, the screen reader announces the drawer's title and
2061
+ * Tab walks its content in order. The handle is decorative: there is no drag-to-dismiss in this package (it
2062
+ * is not claimed); Escape, the backdrop and your own close control dismiss it.
2063
+ */
2064
+ declare class KxDrawerContent extends KxModalSurface {
2065
+ protected initialFocus(): HTMLElement;
2066
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxDrawerContent, never>;
2067
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxDrawerContent, "dialog[kxDrawerContent]", never, {}, {}, never, ["*"], true, never>;
2068
+ }
2069
+ /**
2070
+ * Info — one action ("Got it"). Confirmation, Warning — Cancel + a primary action. Destructive — Cancel + a
2071
+ * destructive action. The same four names React's Modal takes.
2072
+ */
2073
+ type KxModalType = 'Info' | 'Confirmation' | 'Warning' | 'Destructive';
2074
+ /**
2075
+ * <kx-modal type="Destructive" title="Delete this view?" description="Saved filters in it are lost."
2076
+ * [(open)]="confirming" (action)="deleteView()">
2077
+ * <button kxButton variant="Outline" kxDialogTrigger>Delete view</button>
2078
+ * </kx-modal>
2079
+ *
2080
+ * Not a second primitive: React's Modal is a dialog with a fixed structure — a header with the title and a
2081
+ * close button, a divider, the description and any projected content, a divider, and an end-aligned footer
2082
+ * whose buttons follow `type`. This is the same composition on the same `kxDialogContent` surface, so it has
2083
+ * every behaviour of the dialog above and adds none of its own beyond its defaults:
2084
+ *
2085
+ * - first focus is Cancel when there is one (never the action), the action when it is alone (Info)
2086
+ * - `action` fires when the action is chosen; `cancel` when Cancel is. Escape, the backdrop and the close
2087
+ * button close it without either — `openChange` reports every close
2088
+ *
2089
+ * A decision that must be answered — nothing else on the screen may proceed until it is — is an alert dialog,
2090
+ * not a Destructive modal: the modal can still be dismissed by a backdrop press (as React's can).
2091
+ *
2092
+ * The trigger is projected (`kxDialogTrigger`); anything else projected goes in the body under the description.
2093
+ */
2094
+ declare class KxModal extends KxDialogRoot {
2095
+ readonly type: i0.InputSignal<KxModalType>;
2096
+ readonly title: i0.InputSignal<string>;
2097
+ readonly description: i0.InputSignal<string>;
2098
+ /** Overrides the type's default action label. */
2099
+ readonly actionLabel: i0.InputSignal<string>;
2100
+ readonly cancelLabel: i0.InputSignal<string>;
2101
+ readonly closeLabel: i0.InputSignal<string>;
2102
+ readonly action: i0.OutputEmitterRef<void>;
2103
+ readonly cancel: i0.OutputEmitterRef<void>;
2104
+ protected readonly defaultAction: Signal<string>;
2105
+ protected choose(what: 'action' | 'cancel'): void;
2106
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxModal, never>;
2107
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxModal, "kx-modal", never, { "type": { "alias": "type"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": true; "isSignal": true; }; "description": { "alias": "description"; "required": false; "isSignal": true; }; "actionLabel": { "alias": "actionLabel"; "required": false; "isSignal": true; }; "cancelLabel": { "alias": "cancelLabel"; "required": false; "isSignal": true; }; "closeLabel": { "alias": "closeLabel"; "required": false; "isSignal": true; }; }, { "action": "action"; "cancel": "cancel"; }, never, ["[kxDialogTrigger]", "*"], true, never>;
2108
+ }
2109
+
2110
+ /**
2111
+ * The floating family: popover, tooltip, hover card — three surfaces that sit beside the element they belong
2112
+ * to, never modal, and are three different things:
2113
+ *
2114
+ * opened by is focus
2115
+ * popover pressing its trigger a non-modal dialog moves in; Tab out closes it
2116
+ * tooltip hover (after a delay), or the trigger's DESCRIPTION stays on the trigger
2117
+ * keyboard focus (`role="tooltip"`)
2118
+ * hover card hover with intent, or a preview of where the stays on the trigger; Tab
2119
+ * keyboard focus trigger leads walks into its links
2120
+ *
2121
+ * A tooltip is not a tiny popover: it carries no controls, never takes focus, and what it says is already the
2122
+ * trigger's accessible description whether or not it is showing — so a touch user, who never hovers, still has
2123
+ * it read out. A hover card is not a tooltip: it is not a description (a card of profile details read as a
2124
+ * button's description would be noise) and it may hold links. Neither may be the only way to an action or a
2125
+ * piece of information the reader needs: a tooltip does not open on touch, and a hover card's trigger is a
2126
+ * link whose destination carries the same content.
2127
+ *
2128
+ * ── Shared ─────────────────────────────────────────────────────────────────
2129
+ *
2130
+ * Each surface is `popover="manual"` and shown into the top layer (overlay.ts), placed by `autoPlace`: `side`
2131
+ * top | bottom | start | end (logical), `align` start | center | end, `offset` px; flipped, shifted and capped
2132
+ * to the room it has, and re-placed on scroll, resize and size changes. It is declared where it is used, so
2133
+ * inside a dialog it is inside that dialog — a press on it is never a press outside its dialog, and Escape
2134
+ * closes it first.
2135
+ *
2136
+ * Every surface answers Escape. Hover surfaces honour WCAG 1.4.13: dismissible (Escape, without moving the
2137
+ * pointer), hoverable (the pointer can travel from the trigger onto the surface: leaving the trigger starts a
2138
+ * short close delay that entering the surface cancels) and persistent (they stay while hovered or focused).
2139
+ *
2140
+ * Motion: a fade and a 4px settle away from the side it opens on, over `--duration-fast` in and
2141
+ * `--duration-instant` out (a tooltip `--duration-instant` both ways); `none` under reduced motion.
2142
+ */
2143
+ /** Why a floating surface closed — decides whether focus goes back to the trigger. */
2144
+ type CloseReason = KxDismissReason | 'close' | 'blur' | 'pointer' | 'press' | 'programmatic';
2145
+ declare abstract class KxFloatingRoot {
2146
+ /** Two-way: whether the surface is showing. */
2147
+ readonly open: i0.ModelSignal<boolean>;
2148
+ private readonly generatedId;
2149
+ /** The content's own `id` input, static or bound, once the content exists. */
2150
+ readonly contentIdFrom: i0.WritableSignal<Signal<string>>;
2151
+ /** Generated, unless the content has an `id` of its own (`id="…"` or `[id]="…"`) — then that one, as it changes. */
2152
+ readonly contentId: Signal<string>;
2153
+ trigger: HTMLElement | null;
2154
+ anchor: HTMLElement | null;
2155
+ /** The last reason it closed for; `programmatic` when `open` was set from outside. */
2156
+ reason: CloseReason;
2157
+ show(): void;
2158
+ hide(reason?: CloseReason): void;
2159
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxFloatingRoot, never>;
2160
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxFloatingRoot, never, never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; }, { "open": "openChange"; }, never, never, true, never>;
2161
+ }
2162
+ /** Where a floating surface goes, and the open/close lifecycle every member shares. */
2163
+ declare abstract class KxFloatingSurface implements KxLayer {
2164
+ abstract readonly root: KxFloatingRoot;
2165
+ abstract readonly side: () => KxSide;
2166
+ /** Your own id for the surface, static or bound; the trigger's references follow it. Generated when absent. */
2167
+ readonly id: i0.InputSignal<string>;
2168
+ /** Alignment along the trigger, logical. */
2169
+ readonly align: i0.InputSignal<KxAlign>;
2170
+ /** The gap between the trigger and the surface, in px. */
2171
+ readonly offset: i0.InputSignalWithTransform<number, unknown>;
2172
+ protected readonly el: HTMLElement;
2173
+ protected readonly doc: Document;
2174
+ private readonly stack;
2175
+ readonly modal = false;
2176
+ abstract readonly closesOnFocusOutside: boolean;
2177
+ private shown;
2178
+ private release;
2179
+ constructor();
2180
+ surface(): HTMLElement;
2181
+ companions(): readonly (Element | null)[];
2182
+ request(reason: KxDismissReason): void;
2183
+ protected afterShow(): void;
2184
+ protected afterHide(_reason: CloseReason, _focusWasInside: boolean): void;
2185
+ private sync;
2186
+ private teardown;
2187
+ private isShowing;
2188
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxFloatingSurface, never>;
2189
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxFloatingSurface, never, never, { "id": { "alias": "id"; "required": false; "isSignal": true; }; "align": { "alias": "align"; "required": false; "isSignal": true; }; "offset": { "alias": "offset"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2190
+ }
2191
+ /**
2192
+ * <kx-popover [(open)]="filtersOpen">
2193
+ * <button kxButton variant="Outline" kxPopoverTrigger>Filters</button>
2194
+ * <kx-popover-content side="bottom" align="start" label="Filters">…</kx-popover-content>
2195
+ * </kx-popover>
2196
+ *
2197
+ * A non-modal dialog beside its trigger. Pressing the trigger toggles it (`aria-expanded`, `aria-controls`,
2198
+ * `aria-haspopup="dialog"`). On open, focus moves to the first `autofocus` element or Tab stop inside it, else
2199
+ * to the surface. Because the surface follows its trigger in the DOM, Tab order runs trigger → popover →
2200
+ * the rest of the page with no focus guards; when focus leaves both, the popover closes. Escape, a press
2201
+ * outside, `kxPopoverClose` and `[(open)]` close it. Escape and the close control return focus to the trigger;
2202
+ * a press elsewhere leaves focus where the reader put it.
2203
+ *
2204
+ * It is never modal and nothing behind it is made inert — content that must hold focus is a dialog.
2205
+ */
2206
+ declare class KxPopover extends KxFloatingRoot {
2207
+ toggle(): void;
2208
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxPopover, never>;
2209
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxPopover, "kx-popover", never, {}, {}, never, ["*"], true, never>;
2210
+ }
2211
+ declare class KxPopoverTrigger {
2212
+ readonly root: KxPopover;
2213
+ constructor();
2214
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxPopoverTrigger, never>;
2215
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxPopoverTrigger, "button[kxPopoverTrigger]", never, {}, {}, never, never, true, never>;
2216
+ }
2217
+ /** Positions the popover against this element instead of the trigger. */
2218
+ declare class KxPopoverAnchor {
2219
+ constructor();
2220
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxPopoverAnchor, never>;
2221
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxPopoverAnchor, "[kxPopoverAnchor]", never, {}, {}, never, never, true, never>;
2222
+ }
2223
+ /** Closes the popover and returns focus to its trigger. */
2224
+ declare class KxPopoverClose {
2225
+ readonly root: KxPopover;
2226
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxPopoverClose, never>;
2227
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxPopoverClose, "button[kxPopoverClose]", never, {}, {}, never, never, true, never>;
2228
+ }
2229
+ declare class KxPopoverContent extends KxFloatingSurface {
2230
+ readonly root: KxPopover;
2231
+ readonly side: i0.InputSignal<KxSide>;
2232
+ readonly label: i0.InputSignal<string>;
2233
+ /** The id of an element inside that names the popover (a heading); preferred over `label`. */
2234
+ readonly labelledby: i0.InputSignal<string>;
2235
+ readonly closesOnFocusOutside = true;
2236
+ protected afterShow(): void;
2237
+ protected afterHide(reason: CloseReason, focusWasInside: boolean): void;
2238
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxPopoverContent, never>;
2239
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxPopoverContent, "kx-popover-content", never, { "side": { "alias": "side"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelledby": { "alias": "labelledby"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
2240
+ }
2241
+ declare abstract class KxHoverRoot extends KxFloatingRoot {
2242
+ /** ms the pointer rests on the trigger before the surface opens. Keyboard focus opens it at once. */
2243
+ abstract readonly openDelay: () => number;
2244
+ /** ms after the pointer leaves before the surface closes — the time it has to travel onto the surface. */
2245
+ abstract readonly closeDelay: () => number;
2246
+ /** Whether losing focus from the trigger closes it (tooltip), or focus may move into it (hover card). */
2247
+ protected abstract readonly closesOnBlur: boolean;
2248
+ private openTimer;
2249
+ private closeTimer;
2250
+ constructor();
2251
+ private clear;
2252
+ /** The pointer reached the trigger. Touch has no hover: a tap is the trigger's own action. */
2253
+ enter(event: PointerEvent): void;
2254
+ /** The pointer left the trigger or the surface: close unless it arrives on the other in time. */
2255
+ leave(event: PointerEvent): void;
2256
+ private keyboardFocusWithin;
2257
+ /** The pointer is on the surface: stay. */
2258
+ hold(): void;
2259
+ /** Keyboard focus opens at once; focus from a press (not `:focus-visible`) does not. */
2260
+ focused(el: EventTarget | null): void;
2261
+ blurred(): void;
2262
+ /** Pressing the trigger acts on it; the surface gets out of the way. */
2263
+ pressed(): void;
2264
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxHoverRoot, never>;
2265
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxHoverRoot, never, never, {}, {}, never, never, true, never>;
2266
+ }
2267
+ /**
2268
+ * <kx-tooltip>
2269
+ * <button kxButton variant="Ghost" size="icon" aria-label="Copy link" kxTooltipTrigger>…</button>
2270
+ * <kx-tooltip-content>Copies a link anyone in the workspace can open</kx-tooltip-content>
2271
+ * </kx-tooltip>
2272
+ *
2273
+ * The content is the trigger's `aria-describedby` from the start — it stays in the DOM, hidden, while closed —
2274
+ * so the description is read on focus whether or not the tooltip is showing, and a touch user gets it too.
2275
+ * An icon-only trigger still needs its own name (`aria-label`): a description is not a name.
2276
+ *
2277
+ * Opens after `openDelay` (700ms, React's) of hover, or at once on keyboard focus. Closes on Escape, on
2278
+ * blur, on pressing the trigger, and `closeDelay` (100ms) after the pointer leaves both trigger and tooltip.
2279
+ * There is no group "skip delay" between neighbouring tooltips (React's provider has one).
2280
+ */
2281
+ declare class KxTooltip extends KxHoverRoot {
2282
+ readonly openDelay: i0.InputSignalWithTransform<number, unknown>;
2283
+ readonly closeDelay: i0.InputSignalWithTransform<number, unknown>;
2284
+ protected readonly closesOnBlur = true;
2285
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxTooltip, never>;
2286
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxTooltip, "kx-tooltip", never, { "openDelay": { "alias": "openDelay"; "required": false; "isSignal": true; }; "closeDelay": { "alias": "closeDelay"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
2287
+ }
2288
+ declare class KxTooltipTrigger {
2289
+ readonly root: KxTooltip;
2290
+ private readonly own;
2291
+ /** The caller's own description, if the element had one, and then the tooltip. */
2292
+ protected describedby(): string;
2293
+ constructor();
2294
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxTooltipTrigger, never>;
2295
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxTooltipTrigger, "[kxTooltipTrigger]", never, {}, {}, never, never, true, never>;
2296
+ }
2297
+ declare class KxTooltipContent extends KxFloatingSurface {
2298
+ readonly root: KxTooltip;
2299
+ readonly side: i0.InputSignal<KxSide>;
2300
+ readonly closesOnFocusOutside = false;
2301
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxTooltipContent, never>;
2302
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxTooltipContent, "kx-tooltip-content", never, { "side": { "alias": "side"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
2303
+ }
2304
+ /**
2305
+ * <kx-hover-card>
2306
+ * <a kxHoverCardTrigger href="/people/ada">Ada Lovelace</a>
2307
+ * <kx-hover-card-content>…</kx-hover-card-content>
2308
+ * </kx-hover-card>
2309
+ *
2310
+ * A preview of what the trigger — a link — leads to. Opens after `openDelay` (700ms) of hover, or at once on
2311
+ * keyboard focus, and waits `closeDelay` (300ms) after the pointer leaves, long enough to move onto the card
2312
+ * and use a link in it. Focus stays on the trigger; Tab goes from the trigger into the card's links (it
2313
+ * follows the trigger in the DOM), and the card closes when focus leaves both. Escape closes it.
2314
+ *
2315
+ * It is not a description and has no role: the destination page carries the same content, which is how a
2316
+ * touch user — who never sees the card — gets it.
2317
+ */
2318
+ declare class KxHoverCard extends KxHoverRoot {
2319
+ readonly openDelay: i0.InputSignalWithTransform<number, unknown>;
2320
+ readonly closeDelay: i0.InputSignalWithTransform<number, unknown>;
2321
+ protected readonly closesOnBlur = false;
2322
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxHoverCard, never>;
2323
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxHoverCard, "kx-hover-card", never, { "openDelay": { "alias": "openDelay"; "required": false; "isSignal": true; }; "closeDelay": { "alias": "closeDelay"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
2324
+ }
2325
+ declare class KxHoverCardTrigger {
2326
+ readonly root: KxHoverCard;
2327
+ constructor();
2328
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxHoverCardTrigger, never>;
2329
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KxHoverCardTrigger, "[kxHoverCardTrigger]", never, {}, {}, never, never, true, never>;
2330
+ }
2331
+ declare class KxHoverCardContent extends KxFloatingSurface {
2332
+ readonly root: KxHoverCard;
2333
+ readonly side: i0.InputSignal<KxSide>;
2334
+ readonly closesOnFocusOutside = true;
2335
+ static ɵfac: i0.ɵɵFactoryDeclaration<KxHoverCardContent, never>;
2336
+ static ɵcmp: i0.ɵɵComponentDeclaration<KxHoverCardContent, "kx-hover-card-content", never, { "side": { "alias": "side"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
2337
+ }
2338
+
2339
+ export { KxAccordion, KxAccordionContent, KxAccordionItem, KxAccordionTrigger, KxAlert, KxAlertDescription, KxAlertDialog, KxAlertDialogAction, KxAlertDialogCancel, KxAlertDialogContent, KxAlertTitle, KxAppBar, KxAppBarActions, KxAppBarBrand, KxAppBarLink, KxAppBarNav, KxAspectRatio, KxAvatar, KxAvatarFallback, KxAvatarGroup, KxAvatarImage, KxBadge, KxBanner, KxBreadcrumb, KxBreadcrumbItem, KxBreadcrumbLink, KxBreadcrumbList, KxBreadcrumbPage, KxBreadcrumbSeparator, KxButton, KxButtonGroup, KxButtonGroupSeparator, KxButtonGroupText, KxCard, KxCardContent, KxCardDescription, KxCardFooter, KxCardHeader, KxCardTitle, KxCheckbox, KxCircularProgress, KxCodeBlock, KxCollapsible, KxCollapsibleContent, KxCollapsibleTrigger, KxDescriptionList, KxDescriptionListItem, KxDialog, KxDialogClose, KxDialogContent, KxDialogDescription, KxDialogFooter, KxDialogHeader, KxDialogTitle, KxDialogTrigger, KxDrawer, KxDrawerContent, KxEmpty, KxEmptyContent, KxEmptyDescription, KxEmptyHeader, KxEmptyMedia, KxEmptyTitle, KxFab, KxField, KxFieldDescription, KxFieldLabel, KxFieldMessage, KxFooter, KxFooterBottom, KxFooterColumn, KxFooterColumns, KxFooterLink, KxHoverCard, KxHoverCardContent, KxHoverCardTrigger, KxImage, KxInform, KxInput, KxInputGroup, KxInputGroupAddon, KxInputGroupButton, KxInputGroupInput, KxInputGroupText, KxInputOtp, KxKbd, KxKbdGroup, KxLabel, KxList, KxListItem, KxMarquee, KxMarqueeContent, KxMetric, KxModal, KxNativeSelect, KxNavigationBar, KxNumberInput, KxPageHeader, KxPagination, KxPaginationContent, KxPaginationEllipsis, KxPaginationItem, KxPaginationLink, KxPaginationNext, KxPaginationPrevious, KxPasswordInput, KxPopover, KxPopoverAnchor, KxPopoverClose, KxPopoverContent, KxPopoverTrigger, KxProgress, KxQuote, KxRadio, KxRadioGroup, KxRating, KxSegment, KxSegmentedControl, KxSeparator, KxSheet, KxSheetContent, KxSkeleton, KxSlider, KxSpinner, KxStepper, KxSwitch, KxTab, KxTabBar, KxTabBarItem, KxTabList, KxTabPanel, KxTableOfContents, KxTabs, KxTag, KxTextarea, KxTimeline, KxTimelineItem, KxToggle, KxToggleGroup, KxToggleGroupItem, KxTooltip, KxTooltipContent, KxTooltipTrigger };
2340
+ export type { KxAlertVariant, KxAlign, KxBadgeVariant, KxButtonSize, KxButtonVariant, KxCodeBlockFile, KxCorners, KxDescriptionListLayout, KxEmptyMediaVariant, KxFabSize, KxFabVariant, KxFieldMessageVariant, KxImageRatio, KxInformVariant, KxModalType, KxOrientation, KxSheetSide, KxSide, KxSpinnerSize, KxSpinnerVariant, KxStep, KxTagVariant, KxTimelineStatus, KxTocItem, KxToggleSize, KxToggleVariant, KxTrend };