@koobiq/components 19.8.5 → 19.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/accordion/accordion-content.directive.d.ts +23 -3
  2. package/accordion/accordion-trigger.component.d.ts +1 -0
  3. package/accordion/accordion.component.scss +4 -1
  4. package/alert/alert-tokens.scss +4 -4
  5. package/autocomplete/autocomplete-trigger.directive.d.ts +10 -5
  6. package/breadcrumbs/breadcrumbs.d.ts +2 -0
  7. package/breadcrumbs/breadcrumbs.scss +4 -0
  8. package/button/button-group.scss +42 -2
  9. package/button-toggle/button-toggle-tokens.scss +16 -0
  10. package/button-toggle/button-toggle.component.d.ts +3 -1
  11. package/button-toggle/button-toggle.scss +105 -1
  12. package/checkbox/checkbox.scss +5 -4
  13. package/clamped-text/clamped-text.d.ts +1 -0
  14. package/core/form-field/field-sizing-content.d.ts +0 -1
  15. package/core/form-field/form-field-ref.d.ts +1 -0
  16. package/core/form-field/index.d.ts +1 -0
  17. package/core/form-field/text-field-selection.d.ts +18 -0
  18. package/core/form-field/text-ruler.d.ts +16 -0
  19. package/core/navbar/rectangle-item.d.ts +8 -0
  20. package/core/option/_action-container-mixins.scss +28 -0
  21. package/core/option/_option-theme.scss +8 -0
  22. package/core/option/action.d.ts +9 -0
  23. package/core/option/action.scss +7 -0
  24. package/core/option/option.d.ts +10 -6
  25. package/core/pop-up/pop-up-trigger.d.ts +6 -0
  26. package/core/select/constants.d.ts +8 -1
  27. package/core/services/measure-scrollbar.service.d.ts +1 -0
  28. package/core/styles/common/_animation.scss +35 -24
  29. package/core/styles/common/_select.scss +17 -2
  30. package/core/styles/theming/_scrollbar-theme.scss +4 -0
  31. package/core/styles/typography/_typography.scss +8 -0
  32. package/core/utils/dom.d.ts +12 -0
  33. package/datepicker/datepicker-input.directive.d.ts +20 -5
  34. package/datepicker/datepicker.component.d.ts +4 -1
  35. package/dl/dl.component.d.ts +1 -0
  36. package/dl/dl.scss +10 -0
  37. package/dropdown/dropdown-item.component.d.ts +10 -2
  38. package/dropdown/dropdown-item.scss +16 -0
  39. package/dropdown/dropdown-trigger.directive.d.ts +6 -1
  40. package/dropdown/dropdown.component.d.ts +6 -1
  41. package/dropdown/dropdown.module.d.ts +1 -1
  42. package/dropdown/dropdown.scss +18 -3
  43. package/ellipsis-center/ellipsis-center.directive.d.ts +35 -2
  44. package/fesm2022/koobiq-components-accordion.mjs +104 -16
  45. package/fesm2022/koobiq-components-accordion.mjs.map +1 -1
  46. package/fesm2022/koobiq-components-alert.mjs +2 -2
  47. package/fesm2022/koobiq-components-app-switcher.mjs +6 -6
  48. package/fesm2022/koobiq-components-app-switcher.mjs.map +1 -1
  49. package/fesm2022/koobiq-components-autocomplete.mjs +21 -9
  50. package/fesm2022/koobiq-components-autocomplete.mjs.map +1 -1
  51. package/fesm2022/koobiq-components-breadcrumbs.mjs +10 -5
  52. package/fesm2022/koobiq-components-breadcrumbs.mjs.map +1 -1
  53. package/fesm2022/koobiq-components-button-toggle.mjs +8 -5
  54. package/fesm2022/koobiq-components-button-toggle.mjs.map +1 -1
  55. package/fesm2022/koobiq-components-button.mjs +4 -4
  56. package/fesm2022/koobiq-components-button.mjs.map +1 -1
  57. package/fesm2022/koobiq-components-checkbox.mjs +2 -2
  58. package/fesm2022/koobiq-components-checkbox.mjs.map +1 -1
  59. package/fesm2022/koobiq-components-clamped-text.mjs +4 -0
  60. package/fesm2022/koobiq-components-clamped-text.mjs.map +1 -1
  61. package/fesm2022/koobiq-components-code-block.mjs +14 -5
  62. package/fesm2022/koobiq-components-code-block.mjs.map +1 -1
  63. package/fesm2022/koobiq-components-content-panel.mjs +5 -4
  64. package/fesm2022/koobiq-components-content-panel.mjs.map +1 -1
  65. package/fesm2022/koobiq-components-core.mjs +234 -64
  66. package/fesm2022/koobiq-components-core.mjs.map +1 -1
  67. package/fesm2022/koobiq-components-datepicker.mjs +73 -49
  68. package/fesm2022/koobiq-components-datepicker.mjs.map +1 -1
  69. package/fesm2022/koobiq-components-dl.mjs +5 -4
  70. package/fesm2022/koobiq-components-dl.mjs.map +1 -1
  71. package/fesm2022/koobiq-components-dropdown.mjs +65 -22
  72. package/fesm2022/koobiq-components-dropdown.mjs.map +1 -1
  73. package/fesm2022/koobiq-components-ellipsis-center.mjs +77 -22
  74. package/fesm2022/koobiq-components-ellipsis-center.mjs.map +1 -1
  75. package/fesm2022/koobiq-components-file-upload.mjs +12 -12
  76. package/fesm2022/koobiq-components-file-upload.mjs.map +1 -1
  77. package/fesm2022/koobiq-components-filter-bar.mjs +152 -46
  78. package/fesm2022/koobiq-components-filter-bar.mjs.map +1 -1
  79. package/fesm2022/koobiq-components-form-field.mjs +2 -2
  80. package/fesm2022/koobiq-components-form-field.mjs.map +1 -1
  81. package/fesm2022/koobiq-components-icon.mjs +1 -1
  82. package/fesm2022/koobiq-components-icon.mjs.map +1 -1
  83. package/fesm2022/koobiq-components-inline-edit.mjs +26 -5
  84. package/fesm2022/koobiq-components-inline-edit.mjs.map +1 -1
  85. package/fesm2022/koobiq-components-list.mjs +12 -22
  86. package/fesm2022/koobiq-components-list.mjs.map +1 -1
  87. package/fesm2022/koobiq-components-markdown.mjs +4 -1
  88. package/fesm2022/koobiq-components-markdown.mjs.map +1 -1
  89. package/fesm2022/koobiq-components-modal.mjs +53 -12
  90. package/fesm2022/koobiq-components-modal.mjs.map +1 -1
  91. package/fesm2022/koobiq-components-navbar.mjs +29 -13
  92. package/fesm2022/koobiq-components-navbar.mjs.map +1 -1
  93. package/fesm2022/koobiq-components-notification-center.mjs +45 -7
  94. package/fesm2022/koobiq-components-notification-center.mjs.map +1 -1
  95. package/fesm2022/koobiq-components-overflow-items.mjs +4 -0
  96. package/fesm2022/koobiq-components-overflow-items.mjs.map +1 -1
  97. package/fesm2022/koobiq-components-popover.mjs +35 -18
  98. package/fesm2022/koobiq-components-popover.mjs.map +1 -1
  99. package/fesm2022/koobiq-components-radio.mjs +3 -7
  100. package/fesm2022/koobiq-components-radio.mjs.map +1 -1
  101. package/fesm2022/koobiq-components-resizer.mjs +23 -4
  102. package/fesm2022/koobiq-components-resizer.mjs.map +1 -1
  103. package/fesm2022/koobiq-components-select.mjs +126 -29
  104. package/fesm2022/koobiq-components-select.mjs.map +1 -1
  105. package/fesm2022/koobiq-components-sidebar.mjs +10 -0
  106. package/fesm2022/koobiq-components-sidebar.mjs.map +1 -1
  107. package/fesm2022/koobiq-components-sidepanel.mjs +34 -10
  108. package/fesm2022/koobiq-components-sidepanel.mjs.map +1 -1
  109. package/fesm2022/koobiq-components-splitter.mjs +4 -0
  110. package/fesm2022/koobiq-components-splitter.mjs.map +1 -1
  111. package/fesm2022/koobiq-components-tabs.mjs +27 -7
  112. package/fesm2022/koobiq-components-tabs.mjs.map +1 -1
  113. package/fesm2022/koobiq-components-tags.mjs +3 -1
  114. package/fesm2022/koobiq-components-tags.mjs.map +1 -1
  115. package/fesm2022/koobiq-components-textarea.mjs +7 -14
  116. package/fesm2022/koobiq-components-textarea.mjs.map +1 -1
  117. package/fesm2022/koobiq-components-timepicker.mjs +44 -19
  118. package/fesm2022/koobiq-components-timepicker.mjs.map +1 -1
  119. package/fesm2022/koobiq-components-timezone.mjs +10 -4
  120. package/fesm2022/koobiq-components-timezone.mjs.map +1 -1
  121. package/fesm2022/koobiq-components-title.mjs +41 -3
  122. package/fesm2022/koobiq-components-title.mjs.map +1 -1
  123. package/fesm2022/koobiq-components-toast.mjs +31 -3
  124. package/fesm2022/koobiq-components-toast.mjs.map +1 -1
  125. package/fesm2022/koobiq-components-toggle.mjs +2 -2
  126. package/fesm2022/koobiq-components-toggle.mjs.map +1 -1
  127. package/fesm2022/koobiq-components-tooltip.mjs +4 -1
  128. package/fesm2022/koobiq-components-tooltip.mjs.map +1 -1
  129. package/fesm2022/koobiq-components-tree-select.mjs +36 -12
  130. package/fesm2022/koobiq-components-tree-select.mjs.map +1 -1
  131. package/fesm2022/koobiq-components-tree.mjs +41 -37
  132. package/fesm2022/koobiq-components-tree.mjs.map +1 -1
  133. package/fesm2022/koobiq-components-username.mjs +2 -2
  134. package/fesm2022/koobiq-components-username.mjs.map +1 -1
  135. package/file-upload/dropzone.d.ts +0 -1
  136. package/file-upload/file-upload.scss +11 -0
  137. package/file-upload/multiple-file-upload.component.scss +29 -3
  138. package/file-upload/primitives/file-picker.d.ts +1 -1
  139. package/file-upload/single-file-upload.component.scss +10 -2
  140. package/filter-bar/filter-bar.d.ts +1 -1
  141. package/filter-bar/pipes/base-pipe.d.ts +31 -0
  142. package/filter-bar/pipes/pipe-date.d.ts +1 -1
  143. package/filter-bar/pipes/pipe-datetime.d.ts +1 -1
  144. package/form-field/fieldset.scss +10 -0
  145. package/inline-edit/inline-edit.d.ts +5 -0
  146. package/inline-edit/inline-edit.scss +7 -7
  147. package/link/_link-theme.scss +50 -15
  148. package/list/_list-theme.scss +12 -0
  149. package/list/list-selection.component.d.ts +1 -0
  150. package/list/list.scss +2 -9
  151. package/modal/modal-tokens.scss +1 -1
  152. package/modal/modal.component.d.ts +9 -1
  153. package/modal/modal.directive.d.ts +11 -0
  154. package/modal/modal.type.d.ts +7 -0
  155. package/navbar/_navbar-item_horizontal.scss +5 -0
  156. package/navbar/_navbar-item_vertical.scss +7 -5
  157. package/navbar/navbar-item.component.d.ts +15 -0
  158. package/navbar/navbar.component.d.ts +1 -0
  159. package/navbar/vertical-navbar.scss +6 -0
  160. package/notification-center/notification-center.d.ts +13 -1
  161. package/notification-center/notification-center.scss +12 -0
  162. package/notification-center/notification-item.scss +6 -0
  163. package/overflow-items/overflow-items.d.ts +1 -0
  164. package/package.json +4 -4
  165. package/prebuilt-themes/dark-theme.css +1 -1
  166. package/prebuilt-themes/light-theme.css +1 -1
  167. package/prebuilt-themes/theme.css +1 -1
  168. package/radio/radio.component.d.ts +1 -5
  169. package/radio/radio.scss +18 -4
  170. package/resizer/resizer.d.ts +12 -0
  171. package/schematics/ng-add/index.js +2 -2
  172. package/select/select-option.directive.d.ts +1 -0
  173. package/select/select.component.d.ts +29 -4
  174. package/sidebar/sidebar.component.d.ts +3 -0
  175. package/sidepanel/sidepanel-directives.d.ts +2 -0
  176. package/sidepanel/sidepanel.service.d.ts +8 -0
  177. package/splitter/splitter.component.d.ts +1 -0
  178. package/tabs/tab-body.component.d.ts +2 -0
  179. package/tabs/tab-header.component.d.ts +1 -0
  180. package/tabs/tab-header.scss +1 -0
  181. package/tabs/tab-nav-bar.d.ts +1 -0
  182. package/tabs/tabs-tokens.scss +1 -1
  183. package/textarea/textarea.component.d.ts +0 -1
  184. package/timepicker/timepicker.directive.d.ts +3 -0
  185. package/timezone/timezone-option.directive.d.ts +1 -0
  186. package/title/title.directive.d.ts +21 -0
  187. package/toast/toast-container.component.d.ts +25 -0
  188. package/tree/_tree-theme.scss +5 -11
  189. package/tree/toggle.scss +4 -0
  190. package/tree/tree-option.component.d.ts +3 -0
  191. package/tree/tree-option.scss +2 -12
  192. package/tree/tree-selection.component.d.ts +1 -0
  193. package/tree-select/tree-select.component.d.ts +9 -2
@@ -1,8 +1,9 @@
1
- import { AfterContentInit, AfterViewInit } from '@angular/core';
1
+ import { AfterContentInit, AfterViewInit, DoCheck } from '@angular/core';
2
2
  import { KbqAccordionItem } from './accordion-item';
3
3
  import * as i0 from "@angular/core";
4
- export declare class KbqAccordionContentDirective implements AfterContentInit, AfterViewInit {
4
+ export declare class KbqAccordionContentDirective implements AfterContentInit, DoCheck, AfterViewInit {
5
5
  private readonly renderer;
6
+ private readonly injector;
6
7
  private readonly platform;
7
8
  /** @docs-private */
8
9
  protected readonly nativeElement: HTMLElement;
@@ -15,13 +16,32 @@ export declare class KbqAccordionContentDirective implements AfterContentInit, A
15
16
  /** @docs-private */
16
17
  protected readonly hidden: import("@angular/core").WritableSignal<boolean>;
17
18
  private savedTransition;
18
- private readonly afterRenderRef?;
19
+ /** Whether the first browser render has happened; until then a toggle only sets the initial state. */
20
+ private rendered;
19
21
  constructor();
22
+ ngDoCheck(): void;
20
23
  ngAfterViewInit(): void;
21
24
  ngAfterContentInit(): void;
22
25
  toggle(): void;
26
+ /** @docs-private */
27
+ protected onTransitionEnd(event: TransitionEvent): void;
23
28
  disableAnimation(): void;
24
29
  enableAnimation(): void;
30
+ /**
31
+ * Pins the height the transition runs between: the natural height of the content when expanding,
32
+ * the current one when collapsing. The pin is released once the transition ends, so expanded
33
+ * content keeps `height: auto` and follows its own size — its container can be laid out later
34
+ * (a content panel, an overlay) or resized, and nested items can toggle.
35
+ *
36
+ * `scrollHeight` reports the natural height even while the `overflow: hidden` host is collapsed.
37
+ */
38
+ private pinHeight;
39
+ /** Checks the pin once `data-state` has flipped. */
40
+ private settleHeight;
41
+ /** Whether a height transition runs on the host; `undefined` without the Web Animations API. */
42
+ private isHeightTransitionRunning;
43
+ private setHeight;
44
+ private releaseHeight;
25
45
  static ɵfac: i0.ɵɵFactoryDeclaration<KbqAccordionContentDirective, never>;
26
46
  static ɵdir: i0.ɵɵDirectiveDeclaration<KbqAccordionContentDirective, "[kbqAccordionContent]", ["kbqAccordionContent"], {}, {}, never, never, true, never>;
27
47
  }
@@ -4,6 +4,7 @@ import { KbqAccordion } from './accordion.component';
4
4
  import * as i0 from "@angular/core";
5
5
  import * as i1 from "./accordion-trigger.directive";
6
6
  export declare class KbqAccordionTrigger implements AfterViewInit {
7
+ private readonly platform;
7
8
  /** @docs-private */
8
9
  protected readonly nativeElement: HTMLElement;
9
10
  /** @docs-private */
@@ -24,13 +24,16 @@
24
24
  overflow: hidden;
25
25
 
26
26
  & > p {
27
+ // Nested contents must not inherit this host's pinned height.
28
+ --radix-accordion-content-height: initial;
29
+
27
30
  margin: unset;
28
31
  padding: var(--kbq-accordion-size-item-content-padding);
29
32
  }
30
33
 
31
34
  &[data-state='open'] {
32
35
  transition: 300ms ease-out;
33
- height: var(--radix-accordion-content-height);
36
+ height: var(--radix-accordion-content-height, auto);
34
37
  }
35
38
 
36
39
  &[data-state='closed'] {
@@ -40,16 +40,16 @@
40
40
  --kbq-alert-size-compact-no-title-icon-margin-top: var(--kbq-size-m);
41
41
  --kbq-alert-size-compact-no-title-icon-padding-top: var(--kbq-size-3xs);
42
42
  /* THEME TOKENS */
43
- --kbq-alert-default-error-container-background: var(--kbq-background-contrast-fade);
43
+ --kbq-alert-default-error-container-background: var(--kbq-background-contrast-less);
44
44
  --kbq-alert-default-error-container-title: var(--kbq-foreground-contrast);
45
45
  --kbq-alert-default-error-container-text: var(--kbq-foreground-contrast);
46
- --kbq-alert-default-warning-container-background: var(--kbq-background-contrast-fade);
46
+ --kbq-alert-default-warning-container-background: var(--kbq-background-contrast-less);
47
47
  --kbq-alert-default-warning-container-title: var(--kbq-foreground-contrast);
48
48
  --kbq-alert-default-warning-container-text: var(--kbq-foreground-contrast);
49
- --kbq-alert-default-success-container-background: var(--kbq-background-contrast-fade);
49
+ --kbq-alert-default-success-container-background: var(--kbq-background-contrast-less);
50
50
  --kbq-alert-default-success-container-title: var(--kbq-foreground-contrast);
51
51
  --kbq-alert-default-success-container-text: var(--kbq-foreground-contrast);
52
- --kbq-alert-default-info-container-background: var(--kbq-background-contrast-fade);
52
+ --kbq-alert-default-info-container-background: var(--kbq-background-contrast-less);
53
53
  --kbq-alert-default-info-container-title: var(--kbq-foreground-contrast);
54
54
  --kbq-alert-default-info-container-text: var(--kbq-foreground-contrast);
55
55
  --kbq-alert-colored-error-container-background: var(--kbq-background-error-less);
@@ -10,13 +10,18 @@ import { KbqAutocompleteOrigin } from './autocomplete-origin.directive';
10
10
  import { KbqAutocomplete } from './autocomplete.component';
11
11
  import * as i0 from "@angular/core";
12
12
  /**
13
- * The following style constants are necessary to save here in order
14
- * to properly calculate the scrollTop of the panel. Because we are not
15
- * actually focusing the active item, scroll must be handled manually.
13
+ * The total height of the autocomplete panel.
14
+ *
15
+ * @deprecated Unused — the panel is capped by `--kbq-autocomplete-size-panel-max-height` and reveals its
16
+ * active option through `KbqOption.focus`, so nothing computes a scroll offset from this. Will be removed
17
+ * in the next major release.
16
18
  */
17
- /** The total height of the autocomplete panel. */
18
19
  export declare const AUTOCOMPLETE_PANEL_HEIGHT = 256;
19
- /** Injection token that determines the scroll handling while the autocomplete panel is open. */
20
+ /**
21
+ * Injection token that determines the scroll handling while the autocomplete panel is open. The root default
22
+ * keeps the trigger usable outside `KbqAutocompleteModule`'s injector; providing the token anywhere still wins
23
+ * over it.
24
+ */
20
25
  export declare const KBQ_AUTOCOMPLETE_SCROLL_STRATEGY: InjectionToken<() => ScrollStrategy>;
21
26
  export declare function KBQ_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY(overlay: Overlay): () => ScrollStrategy;
22
27
  export declare const KBQ_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY_PROVIDER: {
@@ -19,9 +19,11 @@ export declare class KbqBreadcrumbsSeparator {
19
19
  * Directive to style and configure buttons used as breadcrumb items.
20
20
  * - Inherits focus management behavior from `RdxRovingFocusItemDirective`.
21
21
  * - Optionally injects `KbqButton` to customize its style for breadcrumb usage.
22
+ * - Sets `type="button"` on a `<button>` host, so a breadcrumb never submits a surrounding form.
22
23
  */
23
24
  export declare class KbqBreadcrumbButton implements OnInit {
24
25
  private readonly button;
26
+ protected readonly element: HTMLElement;
25
27
  ngOnInit(): void;
26
28
  static ɵfac: i0.ɵɵFactoryDeclaration<KbqBreadcrumbButton, never>;
27
29
  static ɵdir: i0.ɵɵDirectiveDeclaration<KbqBreadcrumbButton, "[kbq-button][kbqBreadcrumb]", never, {}, {}, never, never, true, [{ directive: typeof i1.RdxRovingFocusItemDirective; inputs: { "focusable": "focusable"; }; outputs: {}; }]>;
@@ -73,6 +73,10 @@
73
73
  --kbq-button-size-border-radius: var(--kbq-breadcrumb-item-border-radius);
74
74
  }
75
75
 
76
+ &.kbq-dropdown-trigger {
77
+ --kbq-dropdown-trigger-horizontal-padding: var(--kbq-breadcrumb-item-horizontal-padding);
78
+ }
79
+
76
80
  &:focus-visible {
77
81
  outline-offset: unset;
78
82
  }
@@ -3,15 +3,55 @@
3
3
  .kbq-button-group {
4
4
  &.kbq-button-group_horizontal {
5
5
  @include groups-mixins.group(':is(.kbq-button, .kbq-button-icon)');
6
+
7
+ & > :is(.kbq-button, .kbq-button-icon):not(:last-child, .cdk-keyboard-focused) {
8
+ border-right-color: transparent;
9
+ }
6
10
  }
7
11
 
8
12
  &.kbq-button-group_vertical {
9
13
  @include groups-mixins.vertical-group(':is(.kbq-button, .kbq-button-icon)');
14
+
15
+ & > :is(.kbq-button, .kbq-button-icon):not(:last-child, .cdk-keyboard-focused) {
16
+ border-bottom-color: transparent;
17
+ }
10
18
  }
11
19
 
12
20
  &:not(:has(> :not(.kbq-contrast-fade.kbq-button_filled))),
13
21
  &:not(:has(> :not(.kbq-contrast.kbq-button_filled))) {
14
- // @TODO tech debt (#DS-4847)
15
- gap: var(--kbq-size-3xs);
22
+ :is(.kbq-button, .kbq-button-icon) {
23
+ background-clip: padding-box !important;
24
+ }
25
+ }
26
+
27
+ &.kbq-contrast-fade.kbq-button-group-root_filled {
28
+ // internal css variable, so don't prefixed with kbq
29
+ --button-group-divider-color: var(--kbq-line-contrast-fade);
30
+
31
+ &.kbq-button-group_horizontal {
32
+ :is(.kbq-button, .kbq-button-icon):not(:first-child)::before {
33
+ content: '';
34
+ position: absolute;
35
+ // offset by -1px because absolute positioning is relative to the padding edge,
36
+ // but the visual junction sits 1px to the left in the transparent border area
37
+ left: calc(-1 * var(--kbq-size-border-width));
38
+ top: 0;
39
+ bottom: 0;
40
+ width: var(--kbq-size-border-width);
41
+ background: var(--button-group-divider-color);
42
+ }
43
+ }
44
+
45
+ &.kbq-button-group_vertical {
46
+ :is(.kbq-button, .kbq-button-icon):not(:first-child)::before {
47
+ content: '';
48
+ position: absolute;
49
+ top: calc(-1 * var(--kbq-size-border-width));
50
+ left: 0;
51
+ right: 0;
52
+ height: var(--kbq-size-border-width);
53
+ background: var(--button-group-divider-color);
54
+ }
55
+ }
16
56
  }
17
57
  }
@@ -3,12 +3,28 @@
3
3
  --kbq-button-toggle-size-container-padding-horizontal: var(--kbq-size-xxs);
4
4
  --kbq-button-toggle-size-container-padding-vertical: var(--kbq-size-xxs);
5
5
  --kbq-button-toggle-size-container-content-gap-horizontal: var(--kbq-size-xxs);
6
+ // 22px, not the design's 24px: the item's 1px border is outside this height. See the
7
+ // `box-sizing: content-box` in button-toggle.scss, which is what keeps that arithmetic true.
6
8
  --kbq-button-toggle-size-item-height: 22px;
7
9
  --kbq-button-toggle-size-item-border-radius: var(--kbq-size-xxs);
8
10
  --kbq-button-toggle-size-item-padding-horizontal: var(--kbq-size-s);
9
11
  --kbq-button-toggle-size-item-padding-vertical: var(--kbq-size-3xs);
10
12
  --kbq-button-toggle-size-item-content-gap-horizontal: var(--kbq-size-xxs);
11
13
  --kbq-button-toggle-size-item-focus-outline-width: var(--kbq-size-3xs);
14
+ // How far an item's hit area reaches past the pill it paints. Measured from the inner button's
15
+ // border box, one item border inside the item's own — hence the border-width term in each. `-gap` is
16
+ // the half of the inter-item gap an item claims; the other two cover the group's padding. The
17
+ // pseudo-element they offset is in button-toggle.scss, next to the note on the two other places
18
+ // this repo extends a hit area the same way.
19
+ --kbq-button-toggle-size-item-hit-area-gap: calc(
20
+ var(--kbq-size-border-width) + var(--kbq-button-toggle-size-container-content-gap-horizontal) / 2
21
+ );
22
+ --kbq-button-toggle-size-item-hit-area-horizontal: calc(
23
+ var(--kbq-size-border-width) + var(--kbq-button-toggle-size-container-padding-horizontal)
24
+ );
25
+ --kbq-button-toggle-size-item-hit-area-vertical: calc(
26
+ var(--kbq-size-border-width) + var(--kbq-button-toggle-size-container-padding-vertical)
27
+ );
12
28
  /* THEME TOKENS */
13
29
  --kbq-button-toggle-container-background: var(--kbq-background-contrast-fade);
14
30
  --kbq-button-toggle-item-default-background: var(--kbq-background-transparent);
@@ -30,6 +30,8 @@ export declare class KbqButtonToggleGroup implements ControlValueAccessor, OnIni
30
30
  /** Whether the toggle group is vertical. */
31
31
  get vertical(): boolean;
32
32
  set vertical(value: boolean);
33
+ /** Whether the toggle group stretches to fill its container width, with toggles sharing equal space. */
34
+ readonly stretched: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
33
35
  /** Value of the toggle group. */
34
36
  get value(): any;
35
37
  set value(newValue: any);
@@ -100,7 +102,7 @@ export declare class KbqButtonToggleGroup implements ControlValueAccessor, OnIni
100
102
  /** Selects a value if there's a toggle that corresponds to it. */
101
103
  private selectValue;
102
104
  static ɵfac: i0.ɵɵFactoryDeclaration<KbqButtonToggleGroup, never>;
103
- static ɵdir: i0.ɵɵDirectiveDeclaration<KbqButtonToggleGroup, "kbq-button-toggle-group", ["kbqButtonToggleGroup"], { "vertical": { "alias": "vertical"; "required": false; }; "value": { "alias": "value"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; }, { "valueChange": "valueChange"; "change": "change"; }, ["buttonToggles"], never, true, never>;
105
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KbqButtonToggleGroup, "kbq-button-toggle-group", ["kbqButtonToggleGroup"], { "vertical": { "alias": "vertical"; "required": false; }; "stretched": { "alias": "stretched"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; }, { "valueChange": "valueChange"; "change": "change"; }, ["buttonToggles"], never, true, never>;
104
106
  }
105
107
  /** Single button inside of a toggle group. */
106
108
  export declare class KbqButtonToggle implements OnInit, AfterContentInit, AfterViewInit, OnDestroy {
@@ -17,10 +17,33 @@
17
17
 
18
18
  .kbq-button-toggle {
19
19
  display: flex;
20
- overflow: hidden;
21
20
  justify-content: flex-start;
22
21
  align-items: center;
23
22
 
23
+ // Must not clip: the button's hit area below reaches outside this box. Not `overflow: clip` with
24
+ // an `overflow-clip-margin` — Chromium rejects math functions there, so the margin cannot follow
25
+ // the tokens the offsets come from and computes to `0px`, clipping the hit area away.
26
+
27
+ // What the item stops containing, and why nothing here takes it back: a toggle projects its
28
+ // content into the button's own `.kbq-button-text`, which keeps the `overflow: hidden` of
29
+ // `kbq-truncate-line()`, so content still cannot spill sideways past the button's content box.
30
+ // Content *taller* than the fixed item height no longer is — and cannot be re-clipped from
31
+ // inside the button, since the only boxes there with a definite height are the button itself,
32
+ // whose `::before` this exists for, and the label box, which would clip its own descenders.
33
+ overflow: visible;
34
+
35
+ // What that clip used to give for free: a flex item's automatic minimum size is zero only while
36
+ // its `overflow` is non-`visible`, and that is what lets the label truncate.
37
+ min-width: 0;
38
+
39
+ // Content-box on purpose, and load-bearing. `--kbq-button-toggle-size-item-height` is 22px,
40
+ // not the 24px of the design's `--kbq-size-xxl`: DS-3136 subtracted the border it added here
41
+ // from the token rather than from the rendered box, so the item only reaches its designed
42
+ // 24px while the border sits outside the declared height. A global `border-box` reset in a
43
+ // consuming application would pull the border back inside and leave the item 2px short —
44
+ // and the inner button, which is sized from the same token, would then spill past it.
45
+ box-sizing: content-box;
46
+
24
47
  height: var(--kbq-button-toggle-size-item-height);
25
48
  min-height: var(--kbq-button-toggle-size-item-height);
26
49
 
@@ -48,12 +71,28 @@
48
71
  button-toggle-size-item-focus-outline-width]
49
72
  );
50
73
 
74
+ // Hit area over the gutters the group's `gap` and `padding` leave around the pill this button
75
+ // paints, so the highlight does not drop out between segments. On the button, not the item
76
+ // host, so pointer events resolve to it and the gutter is clickable too. `::before` because
77
+ // `::after` is the `.kbq-progress` shimmer. Offsets are per orientation, below.
78
+
79
+ // The third place this repo extends a hit area with a transparent pseudo-element, after
80
+ // `.kbq-navbar-item`'s `:before` (DS-2558) and `select.item-active-area()`. Neither is
81
+ // reusable here: the mixin claims a fixed strip on one side of a plain vertical list, with
82
+ // no gap to tile between two neighbours, no group padding at the ends, and no orientation
83
+ // to swap the axes for.
84
+ &:before {
85
+ content: '';
86
+ position: absolute;
87
+ }
88
+
51
89
  & .kbq-button-wrapper {
52
90
  width: 100%;
53
91
  }
54
92
 
55
93
  .kbq-button-toggle-wrapper {
56
94
  display: inline-flex;
95
+ justify-content: center;
57
96
 
58
97
  text-overflow: ellipsis;
59
98
  overflow: hidden;
@@ -71,6 +110,16 @@
71
110
  }
72
111
  }
73
112
 
113
+ // Hit-area offsets, one orientation each — the vertical block below is this one with the axes
114
+ // swapped. The gap is split at its midline so two neighbours tile it rather than overlap, which would
115
+ // hand the whole gutter to whichever paints last; the outermost sides have no neighbour to share with
116
+ // and take the group's padding instead, leaving no point inside the group unclaimed.
117
+
118
+ // `:first-of-type`/`:last-of-type`, not `:first-child`/`:last-child`: the group is a bare directive
119
+ // with no template, so a consumer's own element — a divider, a leading icon — is rendered as a real
120
+ // child among the toggles and would take the positional match away from the toggle that actually sits
121
+ // at the edge, putting the dead zone back. The class only ever lands on a `kbq-button-toggle` element,
122
+ // so matching by type reads the toggles alone.
74
123
  &:not(.kbq-button-toggle_vertical) {
75
124
  .kbq-button-toggle {
76
125
  > .kbq-button,
@@ -78,6 +127,61 @@
78
127
  max-width: 100%;
79
128
 
80
129
  height: var(--kbq-button-toggle-size-item-height);
130
+
131
+ &:before {
132
+ inset-block: calc(-1 * var(--kbq-button-toggle-size-item-hit-area-vertical));
133
+ inset-inline: calc(-1 * var(--kbq-button-toggle-size-item-hit-area-gap));
134
+ }
135
+ }
136
+
137
+ &:first-of-type > :is(.kbq-button, .kbq-button-icon):before {
138
+ inset-inline-start: calc(-1 * var(--kbq-button-toggle-size-item-hit-area-horizontal));
139
+ }
140
+
141
+ &:last-of-type > :is(.kbq-button, .kbq-button-icon):before {
142
+ inset-inline-end: calc(-1 * var(--kbq-button-toggle-size-item-hit-area-horizontal));
143
+ }
144
+ }
145
+ }
146
+
147
+ &.kbq-button-toggle_vertical {
148
+ .kbq-button-toggle {
149
+ > .kbq-button,
150
+ > .kbq-button-icon {
151
+ &:before {
152
+ inset-inline: calc(-1 * var(--kbq-button-toggle-size-item-hit-area-horizontal));
153
+ inset-block: calc(-1 * var(--kbq-button-toggle-size-item-hit-area-gap));
154
+ }
155
+ }
156
+
157
+ &:first-of-type > :is(.kbq-button, .kbq-button-icon):before {
158
+ inset-block-start: calc(-1 * var(--kbq-button-toggle-size-item-hit-area-vertical));
159
+ }
160
+
161
+ &:last-of-type > :is(.kbq-button, .kbq-button-icon):before {
162
+ inset-block-end: calc(-1 * var(--kbq-button-toggle-size-item-hit-area-vertical));
163
+ }
164
+ }
165
+ }
166
+
167
+ &.kbq-button-toggle-group_stretched {
168
+ width: 100%;
169
+
170
+ .kbq-button-toggle {
171
+ flex: 1;
172
+
173
+ > .kbq-button,
174
+ > .kbq-button-icon {
175
+ width: 100%;
176
+ flex: 1;
177
+
178
+ .kbq-button-wrapper {
179
+ justify-content: center;
180
+ }
181
+
182
+ .kbq-button-toggle-wrapper {
183
+ display: block;
184
+ }
81
185
  }
82
186
  }
83
187
  }
@@ -32,9 +32,7 @@
32
32
 
33
33
  max-width: calc(100% - var(--padding));
34
34
 
35
- // `cursor: inherit` ensures that the wrapper element gets the same cursor as the kbq-checkbox
36
- // (e.g. pointer by default, regular when disabled), instead of the browser default.
37
- cursor: inherit;
35
+ cursor: pointer;
38
36
 
39
37
  padding-top: var(--kbq-checkbox-size-normal-padding-top);
40
38
 
@@ -56,7 +54,6 @@
56
54
  .kbq-checkbox {
57
55
  display: inline-block;
58
56
 
59
- cursor: pointer;
60
57
  -webkit-tap-highlight-color: transparent;
61
58
 
62
59
  max-width: 100%;
@@ -89,6 +86,10 @@
89
86
  &.kbq-disabled {
90
87
  cursor: default;
91
88
 
89
+ .kbq-checkbox__layout {
90
+ cursor: default;
91
+ }
92
+
92
93
  .kbq-checkbox__frame {
93
94
  box-shadow: none;
94
95
  }
@@ -34,6 +34,7 @@ export declare class KbqClampedText implements KbqClamped, OnInit, AfterViewInit
34
34
  private readonly destroyRef;
35
35
  private readonly elementRef;
36
36
  private readonly resizeObserver;
37
+ private readonly platform;
37
38
  /**
38
39
  * Clamped text locale configuration.
39
40
  * @docs-private
@@ -14,7 +14,6 @@ export declare class KbqFieldSizingContent {
14
14
  constructor();
15
15
  private emulate;
16
16
  private setupWidth;
17
- private createRuler;
18
17
  private calculateWidth;
19
18
  static ɵfac: i0.ɵɵFactoryDeclaration<KbqFieldSizingContent, never>;
20
19
  static ɵdir: i0.ɵɵDirectiveDeclaration<KbqFieldSizingContent, "[kbqFieldSizingContent]", ["kbqFieldSizingContent"], {}, {}, never, never, true, never>;
@@ -3,6 +3,7 @@ import { InjectionToken, ModelSignal } from '@angular/core';
3
3
  * @deprecated Will be removed in next major release, use `KbqFormField` instead.
4
4
  */
5
5
  export interface KbqFormFieldRef {
6
+ /** @see KbqFormField.control */
6
7
  control: any;
7
8
  canCleanerClearByEsc: boolean;
8
9
  /** Use when KbqFormField is in an overlay container. */
@@ -1,2 +1,3 @@
1
1
  export * from './field-sizing-content';
2
2
  export * from './form-field-ref';
3
+ export * from './text-field-selection';
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Scrolls a text field horizontally so that its current selection is visible.
3
+ *
4
+ * Browsers scroll a field to the caret only for edits the user makes: a selection set from script leaves
5
+ * the field at whatever offset the last keystroke produced. A masked field re-renders its value and moves
6
+ * the caret between value parts on every keystroke, so without this the field keeps the offset of the part
7
+ * that was edited before and clips the one being edited now.
8
+ *
9
+ * Leaves the field alone when it is not focused, when it renders something other than its value, and in
10
+ * right-to-left text, where the browser's own caret following is already correct.
11
+ */
12
+ export declare const kbqRevealSelection: (element: HTMLInputElement) => void;
13
+ /**
14
+ * Selects the `[start, end]` range of a text field and keeps it visible.
15
+ *
16
+ * @see {@link kbqRevealSelection}
17
+ */
18
+ export declare const kbqSetSelectionRange: (element: HTMLInputElement, start: number, end: number) => void;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Builds a hidden element that renders text with the typography of the element `computedStyle` was taken
3
+ * from. Append it to the document, measure through {@link kbqMeasureRulerText}, and remove it.
4
+ *
5
+ * @docs-private
6
+ */
7
+ export declare const kbqCreateTextRuler: (document: Document, computedStyle: CSSStyleDeclaration) => HTMLSpanElement;
8
+ /**
9
+ * Width of `text` in pixels, in the same coordinate space as `clientWidth` and `scrollLeft`.
10
+ *
11
+ * `scrollWidth`, not `getBoundingClientRect()`: the latter reports the transformed box, which disagrees
12
+ * with the untransformed layout metrics it would be compared against under a scaled ancestor.
13
+ *
14
+ * @docs-private
15
+ */
16
+ export declare const kbqMeasureRulerText: (ruler: HTMLSpanElement, text: string) => number;
@@ -8,6 +8,14 @@ export declare class KbqRectangleItem {
8
8
  get collapsed(): boolean;
9
9
  set collapsed(value: boolean);
10
10
  private _collapsed;
11
+ /**
12
+ * Outer width of the item: its border box plus horizontal margins.
13
+ *
14
+ * `getComputedStyle().width` resolves to the used content-box width whatever `box-sizing` says,
15
+ * so it silently drops padding and borders on the `border-box` elements this measures, and the
16
+ * result would change again under a consuming application's global reset.
17
+ * `getBoundingClientRect()` is always the border box, which makes it host-independent.
18
+ */
11
19
  getOuterElementWidth(): number;
12
20
  static ɵfac: i0.ɵɵFactoryDeclaration<KbqRectangleItem, never>;
13
21
  static ɵdir: i0.ɵɵDirectiveDeclaration<KbqRectangleItem, never, never, {}, {}, never, never, true, never>;
@@ -0,0 +1,28 @@
1
+ /// Decides when the trailing `<kbq-option-action>` of an option becomes visible.
2
+ ///
3
+ /// `.kbq-action-container` is `display: none` by default (see `action-container.scss`),
4
+ /// so this mixin is the single source of truth for the reveal rules shared by
5
+ /// `kbq-list-option` and `kbq-tree-option`. Include it inside the option's own rule.
6
+ ///
7
+ /// @param {String} $keyboard-focused-host - selector of the focus-monitored selection host
8
+ /// that CDK's `FocusMonitor` marks with `cdk-keyboard-focused`.
9
+ @mixin kbq-option-action-visibility($keyboard-focused-host) {
10
+ &:not(.kbq-disabled) {
11
+ &:hover,
12
+ &.kbq-hovered,
13
+ &.kbq-action-button-focused {
14
+ & .kbq-action-container {
15
+ display: flex;
16
+ }
17
+ }
18
+ }
19
+
20
+ // Roving focus reveals the action only when focus arrived from the keyboard.
21
+ // `.kbq-focused` alone is not enough: options are `tabindex="-1"`, so a mouse click
22
+ // focuses them too and the action would stay visible after the pointer moves away.
23
+ #{$keyboard-focused-host} &:not(.kbq-disabled).kbq-focused {
24
+ & .kbq-action-container {
25
+ display: flex;
26
+ }
27
+ }
28
+ }
@@ -36,6 +36,10 @@
36
36
  @include kbq-option(states-disabled);
37
37
  }
38
38
 
39
+ &.kbq-selected.kbq-disabled {
40
+ background: var(--kbq-list-states-selected-container-background);
41
+ }
42
+
39
43
  &:is(.kbq-selected, .kbq-active):has(+ :is(.kbq-selected, .kbq-active)) {
40
44
  border-bottom-left-radius: 0;
41
45
  border-bottom-right-radius: 0;
@@ -55,6 +59,10 @@
55
59
  @include kbq-option(multiple-states-selected-hover);
56
60
  }
57
61
  }
62
+
63
+ &.kbq-selected.kbq-disabled {
64
+ background: var(--kbq-list-multiple-states-selected-container-background);
65
+ }
58
66
  }
59
67
  }
60
68
 
@@ -36,3 +36,12 @@ export declare class KbqOptionActionComponent implements AfterViewInit, OnDestro
36
36
  static ɵcmp: i0.ɵɵComponentDeclaration<KbqOptionActionComponent, "kbq-option-action", ["kbqOptionAction"], { "disabled": { "alias": "disabled"; "required": false; }; }, {}, never, ["[kbq-icon]"], true, never>;
37
37
  static ngAcceptInputType_disabled: unknown;
38
38
  }
39
+ /**
40
+ * Moves focus from an option to its trailing action button on Tab.
41
+ *
42
+ * Shared by `KbqListOption` and `KbqTreeOption` so the two cannot drift apart. Tab is swallowed only
43
+ * when focus actually landed: the action lives in a `display: none` container until the option is
44
+ * hovered or keyboard-focused, and focusing a hidden element is a no-op, so suppressing Tab there
45
+ * would trap focus on the option.
46
+ */
47
+ export declare function kbqFocusOptionActionOnTab($event: KeyboardEvent, actionButton: KbqOptionActionComponent | undefined): void;
@@ -11,6 +11,13 @@
11
11
 
12
12
  outline: none;
13
13
 
14
+ // The transparent border reserves the focus ring, and the size token below is the icon box
15
+ // without it: 20px + 2 * 2px comes out at the 24px the action actually occupies. Declared so a
16
+ // global `border-box` reset in a consuming application cannot pull the ring inside and leave the
17
+ // icon box at 16px. Note that `.kbq-option` next to it uses the same transparent-border trick
18
+ // the other way round — it is `border-box`, and its 32px is the whole row.
19
+ box-sizing: content-box;
20
+
14
21
  border: var(--kbq-size-3xs) solid transparent;
15
22
  border-radius: var(--kbq-size-xs);
16
23
 
@@ -104,13 +104,11 @@ export declare class KbqOption extends KbqOptionBase implements AfterViewChecked
104
104
  private _active;
105
105
  private mostRecentViewValue;
106
106
  /**
107
- * Flag that indicates whether the component is currently focused by a mouse interaction.
108
- *
109
- * When set to `true`, the component has focus resulting from a mouse click or
110
- * other pointer event. It is automatically cleared when the component loses
111
- * focus or if focus is obtained through keyboard navigation or programmatic means.
107
+ * Whether the pointer is currently over this option. Cleared on `mouseleave` rather than when the
108
+ * option is focused: hovering the option that is already active does not move the key manager's
109
+ * index, so no focus follows and a flag cleared only there would stay armed indefinitely.
112
110
  */
113
- private isFocusedByMouse;
111
+ private hoveredByPointer;
114
112
  constructor(elementRef: ElementRef<HTMLElement>, changeDetectorRef: ChangeDetectorRef, parent: KbqOptionParentComponent, group: KbqOptgroup);
115
113
  ngAfterViewChecked(): void;
116
114
  ngOnDestroy(): void;
@@ -118,6 +116,7 @@ export declare class KbqOption extends KbqOptionBase implements AfterViewChecked
118
116
  getHeight(): number;
119
117
  select(emitEvent?: boolean): void;
120
118
  deselect(emitEvent?: boolean): void;
119
+ /** Moves keyboard focus to this option and reveals it — see {@link kbqFocusAndReveal}. */
121
120
  focus(): void;
122
121
  /**
123
122
  * This method sets display styles on the option to make it appear
@@ -146,6 +145,8 @@ export declare class KbqOption extends KbqOptionBase implements AfterViewChecked
146
145
  getHostElement(): HTMLElement;
147
146
  /** @docs-private */
148
147
  protected onMouseenter(): void;
148
+ /** @docs-private */
149
+ protected onMouseleave(): void;
149
150
  static ɵfac: i0.ɵɵFactoryDeclaration<KbqOption, [null, null, { optional: true; }, { optional: true; }]>;
150
151
  static ɵcmp: i0.ɵɵComponentDeclaration<KbqOption, "kbq-option", ["kbqOption"], { "value": { "alias": "value"; "required": false; }; "selectable": { "alias": "selectable"; "required": false; }; "userSelect": { "alias": "userSelect"; "required": false; }; "showCheckbox": { "alias": "showCheckbox"; "required": false; }; "viewValue": { "alias": "viewValue"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; }, { "onSelectionChange": "onSelectionChange"; }, never, ["kbq-pseudo-checkbox", "*"], true, never>;
151
152
  static ngAcceptInputType_selectable: unknown;
@@ -166,5 +167,8 @@ export declare function countGroupLabelsBeforeOption(optionIndex: number, option
166
167
  * @param currentScrollPosition Current scroll position of the panel.
167
168
  * @param panelHeight Height of the panel.
168
169
  * @docs-private
170
+ * @deprecated Unused — an option reveals itself on focus through `KbqOption.focus`, which lets the
171
+ * browser resolve the scroll container instead of computing an offset from a uniform row height. Will be
172
+ * removed in the next major release.
169
173
  */
170
174
  export declare function getOptionScrollPosition(optionIndex: number, optionHeight: number, currentScrollPosition: number, panelHeight: number): number;