@koobiq/components 20.1.0 → 20.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/accordion/_accordion-theme.scss +6 -2
  2. package/accordion/accordion-tokens.scss +3 -0
  3. package/accordion/{accordion-trigger.component.scss → accordion-trigger.scss} +10 -0
  4. package/accordion/accordion.scss +71 -0
  5. package/accordion/index.d.ts +264 -121
  6. package/actions-panel/index.d.ts +25 -13
  7. package/alert/_alert-theme.scss +14 -0
  8. package/alert/alert.component.scss +24 -13
  9. package/alert/index.d.ts +63 -29
  10. package/app-switcher/app-switcher-dropdown-app.scss +7 -5
  11. package/app-switcher/app-switcher-dropdown-site.scss +6 -4
  12. package/app-switcher/index.d.ts +41 -4
  13. package/app-switcher/kbq-app-switcher-list-item.scss +6 -8
  14. package/autocomplete/autocomplete.scss +2 -1
  15. package/autocomplete/index.d.ts +58 -37
  16. package/badge/index.d.ts +2 -3
  17. package/breadcrumbs/index.d.ts +1 -1
  18. package/button/index.d.ts +2 -2
  19. package/button-toggle/button-toggle-tokens.scss +2 -0
  20. package/button-toggle/button-toggle.scss +9 -0
  21. package/button-toggle/index.d.ts +5 -0
  22. package/checkbox/index.d.ts +33 -29
  23. package/clamped-text/index.d.ts +3 -2
  24. package/code-block/index.d.ts +24 -19
  25. package/content-panel/index.d.ts +1 -1
  26. package/core/index.d.ts +1217 -186
  27. package/core/option/_action-container-mixins.scss +28 -0
  28. package/core/option/_option-theme.scss +24 -0
  29. package/core/option/action.scss +7 -0
  30. package/core/styles/_core.scss +2 -0
  31. package/core/styles/_koobiq-theme.scss +2 -0
  32. package/core/styles/_tokens.scss +1 -0
  33. package/core/styles/common/_animation.scss +31 -24
  34. package/core/styles/common/_connected-overlay.scss +39 -0
  35. package/core/styles/common/_select.scss +19 -2
  36. package/core/styles/common/_tokens.scss +0 -9
  37. package/core/styles/theming/_index.scss +0 -1
  38. package/core/styles/theming/_theming.scss +34 -5
  39. package/datepicker/index.d.ts +46 -15
  40. package/dl/dl.scss +26 -0
  41. package/dl/index.d.ts +8 -1
  42. package/dropdown/_dropdown-theme.scss +28 -2
  43. package/dropdown/dropdown-item.scss +29 -0
  44. package/dropdown/dropdown-tokens.scss +2 -1
  45. package/dropdown/dropdown.scss +16 -1
  46. package/dropdown/index.d.ts +331 -17
  47. package/dynamic-translation/index.d.ts +1 -1
  48. package/fesm2022/koobiq-components-accordion.mjs +480 -317
  49. package/fesm2022/koobiq-components-accordion.mjs.map +1 -1
  50. package/fesm2022/koobiq-components-actions-panel.mjs +57 -46
  51. package/fesm2022/koobiq-components-actions-panel.mjs.map +1 -1
  52. package/fesm2022/koobiq-components-alert.mjs +98 -58
  53. package/fesm2022/koobiq-components-alert.mjs.map +1 -1
  54. package/fesm2022/koobiq-components-app-switcher.mjs +233 -38
  55. package/fesm2022/koobiq-components-app-switcher.mjs.map +1 -1
  56. package/fesm2022/koobiq-components-autocomplete.mjs +89 -52
  57. package/fesm2022/koobiq-components-autocomplete.mjs.map +1 -1
  58. package/fesm2022/koobiq-components-badge.mjs +18 -17
  59. package/fesm2022/koobiq-components-badge.mjs.map +1 -1
  60. package/fesm2022/koobiq-components-breadcrumbs.mjs +25 -25
  61. package/fesm2022/koobiq-components-breadcrumbs.mjs.map +1 -1
  62. package/fesm2022/koobiq-components-button-toggle.mjs +17 -12
  63. package/fesm2022/koobiq-components-button-toggle.mjs.map +1 -1
  64. package/fesm2022/koobiq-components-button.mjs +25 -25
  65. package/fesm2022/koobiq-components-checkbox.mjs +69 -92
  66. package/fesm2022/koobiq-components-checkbox.mjs.map +1 -1
  67. package/fesm2022/koobiq-components-clamped-text.mjs +18 -13
  68. package/fesm2022/koobiq-components-clamped-text.mjs.map +1 -1
  69. package/fesm2022/koobiq-components-code-block.mjs +56 -69
  70. package/fesm2022/koobiq-components-code-block.mjs.map +1 -1
  71. package/fesm2022/koobiq-components-content-panel.mjs +29 -29
  72. package/fesm2022/koobiq-components-core.mjs +2485 -735
  73. package/fesm2022/koobiq-components-core.mjs.map +1 -1
  74. package/fesm2022/koobiq-components-datepicker.mjs +168 -126
  75. package/fesm2022/koobiq-components-datepicker.mjs.map +1 -1
  76. package/fesm2022/koobiq-components-divider.mjs +7 -7
  77. package/fesm2022/koobiq-components-dl.mjs +23 -15
  78. package/fesm2022/koobiq-components-dl.mjs.map +1 -1
  79. package/fesm2022/koobiq-components-dropdown.mjs +814 -136
  80. package/fesm2022/koobiq-components-dropdown.mjs.map +1 -1
  81. package/fesm2022/koobiq-components-dynamic-translation.mjs +13 -13
  82. package/fesm2022/koobiq-components-ellipsis-center.mjs +7 -7
  83. package/fesm2022/koobiq-components-empty-state.mjs +19 -19
  84. package/fesm2022/koobiq-components-file-upload.mjs +74 -42
  85. package/fesm2022/koobiq-components-file-upload.mjs.map +1 -1
  86. package/fesm2022/koobiq-components-filter-bar.mjs +783 -199
  87. package/fesm2022/koobiq-components-filter-bar.mjs.map +1 -1
  88. package/fesm2022/koobiq-components-flag.mjs +7 -7
  89. package/fesm2022/koobiq-components-form-field.mjs +350 -162
  90. package/fesm2022/koobiq-components-form-field.mjs.map +1 -1
  91. package/fesm2022/koobiq-components-icon.mjs +52 -25
  92. package/fesm2022/koobiq-components-icon.mjs.map +1 -1
  93. package/fesm2022/koobiq-components-inline-edit.mjs +175 -28
  94. package/fesm2022/koobiq-components-inline-edit.mjs.map +1 -1
  95. package/fesm2022/koobiq-components-input.mjs +41 -24
  96. package/fesm2022/koobiq-components-input.mjs.map +1 -1
  97. package/fesm2022/koobiq-components-link.mjs +8 -8
  98. package/fesm2022/koobiq-components-list.mjs +657 -143
  99. package/fesm2022/koobiq-components-list.mjs.map +1 -1
  100. package/fesm2022/koobiq-components-loader-overlay.mjs +16 -16
  101. package/fesm2022/koobiq-components-markdown.mjs +14 -11
  102. package/fesm2022/koobiq-components-markdown.mjs.map +1 -1
  103. package/fesm2022/koobiq-components-modal.mjs +59 -35
  104. package/fesm2022/koobiq-components-modal.mjs.map +1 -1
  105. package/fesm2022/koobiq-components-navbar.mjs +177 -67
  106. package/fesm2022/koobiq-components-navbar.mjs.map +1 -1
  107. package/fesm2022/koobiq-components-notification-center.mjs +40 -24
  108. package/fesm2022/koobiq-components-notification-center.mjs.map +1 -1
  109. package/fesm2022/koobiq-components-overflow-items.mjs +16 -17
  110. package/fesm2022/koobiq-components-overflow-items.mjs.map +1 -1
  111. package/fesm2022/koobiq-components-popover.mjs +31 -21
  112. package/fesm2022/koobiq-components-popover.mjs.map +1 -1
  113. package/fesm2022/koobiq-components-progress-bar.mjs +13 -13
  114. package/fesm2022/koobiq-components-progress-spinner.mjs +13 -13
  115. package/fesm2022/koobiq-components-radio.mjs +10 -10
  116. package/fesm2022/koobiq-components-resizer.mjs +33 -14
  117. package/fesm2022/koobiq-components-resizer.mjs.map +1 -1
  118. package/fesm2022/koobiq-components-scrollbar.mjs +10 -10
  119. package/fesm2022/koobiq-components-search-expandable.mjs +49 -14
  120. package/fesm2022/koobiq-components-search-expandable.mjs.map +1 -1
  121. package/fesm2022/koobiq-components-select.mjs +450 -146
  122. package/fesm2022/koobiq-components-select.mjs.map +1 -1
  123. package/fesm2022/koobiq-components-sidebar.mjs +14 -14
  124. package/fesm2022/koobiq-components-sidepanel.mjs +26 -26
  125. package/fesm2022/koobiq-components-skeleton.mjs +10 -10
  126. package/fesm2022/koobiq-components-split-button.mjs +10 -17
  127. package/fesm2022/koobiq-components-split-button.mjs.map +1 -1
  128. package/fesm2022/koobiq-components-splitter.mjs +17 -17
  129. package/fesm2022/koobiq-components-table.mjs +15 -13
  130. package/fesm2022/koobiq-components-table.mjs.map +1 -1
  131. package/fesm2022/koobiq-components-tabs.mjs +80 -68
  132. package/fesm2022/koobiq-components-tabs.mjs.map +1 -1
  133. package/fesm2022/koobiq-components-tags.mjs +283 -122
  134. package/fesm2022/koobiq-components-tags.mjs.map +1 -1
  135. package/fesm2022/koobiq-components-textarea.mjs +13 -8
  136. package/fesm2022/koobiq-components-textarea.mjs.map +1 -1
  137. package/fesm2022/koobiq-components-time-range.mjs +29 -24
  138. package/fesm2022/koobiq-components-time-range.mjs.map +1 -1
  139. package/fesm2022/koobiq-components-timepicker.mjs +61 -30
  140. package/fesm2022/koobiq-components-timepicker.mjs.map +1 -1
  141. package/fesm2022/koobiq-components-timezone.mjs +77 -42
  142. package/fesm2022/koobiq-components-timezone.mjs.map +1 -1
  143. package/fesm2022/koobiq-components-title.mjs +7 -7
  144. package/fesm2022/koobiq-components-toast.mjs +51 -26
  145. package/fesm2022/koobiq-components-toast.mjs.map +1 -1
  146. package/fesm2022/koobiq-components-toggle.mjs +72 -64
  147. package/fesm2022/koobiq-components-toggle.mjs.map +1 -1
  148. package/fesm2022/koobiq-components-tooltip.mjs +219 -28
  149. package/fesm2022/koobiq-components-tooltip.mjs.map +1 -1
  150. package/fesm2022/koobiq-components-top-bar.mjs +13 -13
  151. package/fesm2022/koobiq-components-tree-select.mjs +222 -80
  152. package/fesm2022/koobiq-components-tree-select.mjs.map +1 -1
  153. package/fesm2022/koobiq-components-tree.mjs +302 -81
  154. package/fesm2022/koobiq-components-tree.mjs.map +1 -1
  155. package/fesm2022/koobiq-components-username.mjs +27 -27
  156. package/file-upload/index.d.ts +25 -6
  157. package/file-upload/multiple-file-upload.component.scss +14 -0
  158. package/filter-bar/_filter-bar-theme.scss +0 -10
  159. package/filter-bar/filter-bar-tokens.scss +3 -0
  160. package/filter-bar/filters.scss +3 -2
  161. package/filter-bar/index.d.ts +281 -9
  162. package/filter-bar/pipes/base-pipe.scss +0 -11
  163. package/filter-bar/pipes/pipe-input.scss +10 -0
  164. package/filter-bar/pipes/pipe-multi-tree-select.scss +0 -6
  165. package/filter-bar/pipes/pipe-multiselect.scss +0 -6
  166. package/filter-bar/pipes/pipe-tree-select.scss +0 -6
  167. package/form-field/_form-field-theme.scss +76 -20
  168. package/form-field/fieldset.scss +10 -0
  169. package/form-field/form-field-tokens.scss +15 -1
  170. package/form-field/form-field.scss +15 -19
  171. package/form-field/index.d.ts +147 -65
  172. package/icon/icon-button.scss +3 -1
  173. package/icon/index.d.ts +45 -7
  174. package/inline-edit/index.d.ts +57 -4
  175. package/inline-edit/inline-edit.scss +10 -0
  176. package/input/index.d.ts +17 -2
  177. package/list/_list-theme.scss +42 -10
  178. package/list/index.d.ts +326 -79
  179. package/list/list-tokens.scss +43 -8
  180. package/list/list.scss +186 -12
  181. package/markdown/index.d.ts +1 -1
  182. package/modal/index.d.ts +21 -4
  183. package/modal/modal-tokens.scss +1 -1
  184. package/navbar/_navbar-item_vertical.scss +7 -5
  185. package/navbar/index.d.ts +54 -5
  186. package/navbar/navbar-brand.scss +23 -7
  187. package/navbar/vertical-navbar.scss +6 -0
  188. package/notification-center/index.d.ts +2 -1
  189. package/notification-center/notification-item.scss +6 -0
  190. package/package.json +3 -6
  191. package/popover/index.d.ts +2 -2
  192. package/prebuilt-themes/dark-theme.css +1 -1
  193. package/prebuilt-themes/light-theme.css +1 -1
  194. package/prebuilt-themes/theme.css +1 -1
  195. package/resizer/index.d.ts +12 -0
  196. package/schematics/collection.json +10 -0
  197. package/schematics/migrations/alert-signals/README.md +64 -0
  198. package/schematics/migrations/alert-signals/data.js +70 -0
  199. package/schematics/migrations/alert-signals/index.js +350 -0
  200. package/schematics/migrations/alert-signals/schema.json +20 -0
  201. package/schematics/migrations/autocomplete-panel-width-auto/README.md +68 -0
  202. package/schematics/migrations/autocomplete-panel-width-auto/index.js +70 -0
  203. package/schematics/migrations/autocomplete-panel-width-auto/schema.json +15 -0
  204. package/schematics/migrations/deprecated-icons/README.md +29 -4
  205. package/schematics/migrations/deprecated-icons/data.js +7 -0
  206. package/schematics/migrations/deprecated-icons/index.js +62 -35
  207. package/schematics/migrations/filter-bar-signals/README.md +1 -1
  208. package/schematics/migrations/new-icons-pack/README.md +37 -2
  209. package/schematics/migrations/new-icons-pack/data.js +8 -0
  210. package/schematics/migrations/new-icons-pack/index.js +144 -53
  211. package/schematics/migrations.json +11 -1
  212. package/schematics/ng-add/index.js +3 -3
  213. package/schematics/utils/angular-parsing.js +41 -14
  214. package/schematics/utils/ast.js +31 -0
  215. package/schematics/utils/icon-migration.js +530 -0
  216. package/schematics/utils/typescript.js +44 -0
  217. package/scrollbar/index.d.ts +1 -1
  218. package/search-expandable/index.d.ts +3 -0
  219. package/select/index.d.ts +212 -40
  220. package/select/select-tokens.scss +0 -1
  221. package/select/select.scss +0 -2
  222. package/splitter/index.d.ts +1 -1
  223. package/table/_table-theme.scss +4 -0
  224. package/table/index.d.ts +2 -1
  225. package/table/table.scss +8 -0
  226. package/tabs/_tabs-common.scss +60 -31
  227. package/tabs/_tabs-theme.scss +12 -0
  228. package/tabs/index.d.ts +2 -2
  229. package/tabs/tab-header.scss +14 -0
  230. package/tabs/tab-nav-bar.scss +4 -0
  231. package/tabs/tabs-tokens.scss +1 -0
  232. package/tags/index.d.ts +128 -29
  233. package/textarea/index.d.ts +5 -0
  234. package/time-range/index.d.ts +1 -1
  235. package/timepicker/index.d.ts +4 -0
  236. package/timezone/index.d.ts +10 -8
  237. package/toast/index.d.ts +26 -3
  238. package/toggle/index.d.ts +34 -14
  239. package/tooltip/index.d.ts +119 -7
  240. package/tree/_tree-theme.scss +25 -5
  241. package/tree/index.d.ts +71 -3
  242. package/tree/tree-option.scss +2 -8
  243. package/tree-select/_tree-select-theme.scss +22 -0
  244. package/tree-select/index.d.ts +127 -36
  245. package/accordion/accordion.component.scss +0 -50
  246. package/core/styles/_tokens.kbq.import.scss +0 -4
  247. package/core/styles/theming/_components-theming.scss +0 -1927
  248. package/filter-bar/pipes/pipe-select.scss +0 -5
  249. package/overflow-items/overflow-items.scss +0 -20
@@ -22,7 +22,18 @@
22
22
  .kbq-input,
23
23
  .kbq-tag-input,
24
24
  .kbq-textarea {
25
- color: var(--kbq-form-field-#{$state-name}-text);
25
+ // Private, and only for the autofill rule near the bottom of this file. The browser forces
26
+ // `color` on an autofilled control with a UA `!important` rule, so that rule has to repaint
27
+ // through `-webkit-text-fill-color` — and to do that it has to know what *this* state
28
+ // wanted. Declared in the same rule as the `color` that reads it, so one cascade decides
29
+ // both and they cannot drift apart.
30
+ // Published as a variable rather than emitting an autofill rule per state: this mixin runs
31
+ // five times, once of them nested under eight `kbq-form-field-type-*` classes, so the
32
+ // per-state form compiled to 84 selectors for two declarations — and gave a text colour a
33
+ // specificity of (0,7,0), which no consumer could override without `!important`.
34
+ --kbq-form-field-resolved-text: var(--kbq-form-field-#{$state-name}-text);
35
+
36
+ color: var(--kbq-form-field-resolved-text);
26
37
 
27
38
  &::placeholder {
28
39
  color: var(--kbq-form-field-#{$state-name}-placeholder);
@@ -42,21 +53,47 @@
42
53
  .kbq-form-field {
43
54
  @include _kbq-form-field-state(default);
44
55
 
56
+ // `color-scheme` is what stops the browser painting its own autofill highlight from the
57
+ // light palette in a dark application. It is declared once for the whole theme in
58
+ // `kbq-core-theme()`, not here: scoping it to the form field inverted nested themes, since
59
+ // both the base and the dark rule land on the same specificity and the dark one then won on
60
+ // source order under any `.kbq-dark` ancestor, however near a `.kbq-light` was.
61
+
62
+ // The browser paints its own background on an autofilled control with a UA `!important`
63
+ // declaration that no author rule can out-rank. It is suppressed rather than painted over:
64
+ // a running transition sits *above* important-UA in the cascade, so animating
65
+ // `background-color` over an absurd duration parks its used value at the control's own
66
+ // transparent background — every control here is already transparent, `.kbq-input` and
67
+ // `.kbq-tag-input` through `kbq-reset-input`, `.kbq-textarea` in its own stylesheet — and
68
+ // the container's tint shows through untouched.
69
+ // https://css-tricks.com/almanac/selectors/a/autofill/
70
+
71
+ // Painting over it instead would be wrong: the tint token is translucent, so a second coat
72
+ // on the control would make its rectangle visibly darker than the container's padding
73
+ // around it, and would still not hide the UA colour underneath.
45
74
  & .kbq-input,
46
- & .kbq-tag-input {
47
- //https://css-tricks.com/almanac/selectors/a/autofill/
48
- &:-webkit-autofill,
49
- &:-webkit-autofill:hover,
50
- &:-webkit-autofill:focus {
51
- // set as transparent to not override container background-color;
52
- --kbq-form-field-states-autofill-background: var(--kbq-background-transparent);
53
- -webkit-box-shadow: inset 0 0 0 40rem var(--kbq-form-field-states-autofill-background);
54
- -webkit-text-fill-color: var(--kbq-form-field-states-autofill-text);
55
- caret-color: var(--kbq-form-field-states-autofill-text);
56
-
57
- /* hide browser default autofill background, no matter what background color set */
58
- transition: background-color 5000s ease-in-out;
59
- background-color: var(--kbq-background-transparent) !important;
75
+ & .kbq-tag-input,
76
+ & .kbq-textarea {
77
+ // `:is()` takes a forgiving selector list, so every browser keeps whichever of the two
78
+ // spellings it knows. A plain comma list would not: one unknown pseudo-class
79
+ // invalidates the whole list.
80
+ &:is(:autofill, :-webkit-autofill) {
81
+ // Longhands rather than the shorthand, which would also reset `transition-delay`
82
+ // and `transition-timing-function`. Nothing transitions on these controls today,
83
+ // but the next thing that does should not break here.
84
+ // The duration has to outlast the page, not merely be large: a transition that
85
+ // *finishes* lands on its end value, which is the browser's own background, and
86
+ // there is no recovering it without a reload. At 5000s that happened after 83
87
+ // minutes a dashboard left open over lunch.
88
+ transition-property: background-color;
89
+ transition-duration: 600000s;
90
+
91
+ // Repaints what the state cascade resolved above, so an autofilled control that is
92
+ // also invalid or disabled still gets that state's text colour. The fallback covers
93
+ // a control outside any state block, which cannot happen today because `default`
94
+ // always runs.
95
+ -webkit-text-fill-color: var(--kbq-form-field-resolved-text, var(--kbq-form-field-default-text));
96
+ caret-color: var(--kbq-form-field-resolved-text, var(--kbq-form-field-default-text));
60
97
  }
61
98
  }
62
99
 
@@ -68,6 +105,7 @@
68
105
  }
69
106
 
70
107
  &.kbq-form-field-type-input,
108
+ &.kbq-form-field-type-input-number,
71
109
  &.kbq-form-field-type-textarea,
72
110
  &.kbq-form-field-type-timepicker,
73
111
  &.kbq-form-field-type-datepicker,
@@ -107,11 +145,29 @@
107
145
  color: var(--kbq-form-field-label-color);
108
146
  }
109
147
 
110
- // todo quick fix for bug DS-4060. Technical debt DS-4096
111
- & .kbq-form-field__container:has(:is(.kbq-input, .kbq-tag-input):-webkit-autofill),
112
- & .kbq-form-field__container:has(:is(.kbq-input, .kbq-tag-input):-webkit-autofill:hover),
113
- & .kbq-form-field__container:has(:is(.kbq-input, .kbq-tag-input):-webkit-autofill:focus) {
114
- background-color: var(--kbq-form-field-states-autofill-background) !important;
148
+ // Autofill says "the browser filled this in" and nothing more, so it contributes a tint and
149
+ // leaves every other channel — border, focus ring, text colour — to the state the field is
150
+ // actually in.
151
+
152
+ // The tint goes into `background-image` rather than `background-color`, and that is what
153
+ // makes the sentence above true. The state keeps ownership of `background-color`, the tint
154
+ // composites over whatever it resolved, and no priority conflict is possible: an invalid
155
+ // field stays error-red *and* tinted, a field in an overlay keeps its card background.
156
+ // Painting `background-color` instead is what DS-4060 did, and it needed `!important` to
157
+ // land — which is exactly why it then out-ranked error, disabled and the overlay.
158
+
159
+ // One arm, not three. The rule this replaces spelled out `:-webkit-autofill`,
160
+ // `:-webkit-autofill:hover` and `:-webkit-autofill:focus`, mirroring the UA's own selector
161
+ // list — but the extra two match the same elements as the bare pseudo-class, and nothing in
162
+ // the UA styles this container. The control rule above dropped them for the same reason.
163
+ &
164
+ .kbq-form-field__container:has(
165
+ :is(.kbq-input, .kbq-tag-input, .kbq-textarea):is(:autofill, :-webkit-autofill)
166
+ ) {
167
+ background-image: linear-gradient(
168
+ var(--kbq-form-field-states-autofill-background),
169
+ var(--kbq-form-field-states-autofill-background)
170
+ );
115
171
  }
116
172
 
117
173
  &.kbq-disabled {
@@ -20,6 +20,16 @@
20
20
  }
21
21
 
22
22
  .kbq-form-field {
23
+ // Force a single-token height, matching how the button computes its own height, so both
24
+ // round to the same pixel value. Without this, form-field's height is the sum of independently
25
+ // rounded border/padding/line-height values, which can drift 1px from the button's height after
26
+ // a resize-triggered subpixel layout recalculation, breaking the merged border line.
27
+ height: var(--kbq-form-field-size-height);
28
+
29
+ .kbq-form-field__content {
30
+ height: 100%;
31
+ }
32
+
23
33
  // set selector specifity to 0 , so focused state will override z-index
24
34
  :where(&.kbq-form-field_invalid, &.kbq-form-field_has-validate-directive.ng-invalid) {
25
35
  z-index: 2;
@@ -36,9 +36,23 @@
36
36
  --kbq-form-field-states-error-placeholder: var(--kbq-foreground-error-tertiary);
37
37
  --kbq-form-field-states-error-text: var(--kbq-foreground-error);
38
38
  --kbq-form-field-states-error-focused-focus-outline: var(--kbq-states-line-focus-error);
39
- --kbq-form-field-states-autofill-border-color: var(--kbq-states-line-focus-theme);
39
+ /* Autofill only tints the background: it is a hint that the browser filled the field, not a
40
+ state of its own, so the border, the focus ring and the text colour stay with the state that
41
+ owns them. Background is the only one of these four the component reads; the other three are
42
+ declared and no longer read, and overriding them has no effect (#DS-4096). They are kept
43
+ rather than deleted because `@koobiq/design-tokens` publishes all four names globally
44
+ anyway — removing them here would not take the names out of the CSS a consumer loads — and
45
+ upstream already marks the set `deprecated`, so it retires them on its own schedule.
46
+ This file is nominally generated by tools/tokens/build-each-component.js, but has been
47
+ hand-maintained for a long time and no npm script runs the generator. Re-running it would
48
+ revert the background below to `theme-fade` (see DS-2873) and drop the size tokens above. */
40
49
  --kbq-form-field-states-autofill-background: var(--kbq-background-theme-less);
50
+ /* No longer read: it aliased the focus colour, so a merely filled field read as focused. */
51
+ --kbq-form-field-states-autofill-border-color: var(--kbq-states-line-focus-theme);
52
+ /* No longer read, and never observable: an autofilled field has a value, so no placeholder. */
41
53
  --kbq-form-field-states-autofill-placeholder: var(--kbq-foreground-contrast-tertiary);
54
+ /* No longer read: it forced one colour on every state, which is what lost the error and
55
+ disabled text colours. The state owns the text now. */
42
56
  --kbq-form-field-states-autofill-text: var(--kbq-foreground-contrast);
43
57
  --kbq-form-field-states-disabled-border-color: var(--kbq-states-line-disabled);
44
58
  --kbq-form-field-states-disabled-background: var(--kbq-states-background-disabled);
@@ -91,6 +91,14 @@
91
91
  max-width: 100%;
92
92
  }
93
93
 
94
+ // The rule above drops the indent because the tags carry one of their own. A custom trigger
95
+ // replaces the tag list entirely, so nothing is left to provide it and the projected content
96
+ // would sit tighter to the border than a single select's value — put the indent back.
97
+ // Same specificity as the rule above, so it has to stay after it.
98
+ &:has(.kbq-select_multiple, .kbq-select_multiline):has(kbq-select-trigger, [kbq-select-trigger]) {
99
+ padding-left: var(--kbq-form-field-size-infix-left-padding);
100
+ }
101
+
94
102
  & .kbq-input,
95
103
  & .kbq-tag-input {
96
104
  padding-right: var(--kbq-form-field-size-infix-right-padding);
@@ -109,27 +117,15 @@
109
117
  &.cdk-focused,
110
118
  &.kbq-focused {
111
119
  z-index: 3;
112
-
113
- .kbq-input {
114
- &:-webkit-autofill,
115
- &:-webkit-autofill:hover,
116
- &:-webkit-autofill:focus {
117
- min-height: calc(
118
- var(--kbq-form-field-size-height) - var(--kbq-form-field-size-border-width) *
119
- 2 - var(--kbq-form-field-size-focus-outline-width) * 2
120
- );
121
-
122
- --kbq-input-size-padding-vertical: calc(
123
- var(--kbq-size-xs) - var(--kbq-form-field-size-border-width) - var(
124
- --kbq-form-field-size-focus-outline-width
125
- )
126
- );
127
-
128
- margin: var(--kbq-form-field-size-border-width) 0;
129
- }
130
- }
131
120
  }
132
121
 
122
+ // No autofill geometry here on purpose. DS-4950 shrank the autofilled control by twice the
123
+ // focus-outline width and handed the pixels back as margin, because the control's own autofill
124
+ // background was painting over the 1px ring the container draws as an inset shadow. It has
125
+ // nothing left to paint over: the control is transparent — the browser's background is
126
+ // suppressed, not replaced — and the tint lives on the container, under a shadow that is drawn
127
+ // above it. Reinstating any of it would only move the text on focus.
128
+
133
129
  &.kbq-form-field_without-borders .kbq-form-field__container,
134
130
  &.kbq-form-field_no-borders .kbq-form-field__container {
135
131
  border-color: transparent !important;
@@ -1,20 +1,108 @@
1
- import { KbqIconButton } from '@koobiq/components/icon';
2
1
  import * as i0 from '@angular/core';
3
- import { Signal, AfterContentInit, QueryList, AfterViewInit, OnDestroy, ChangeDetectorRef, TemplateRef, OutputEmitterRef, InjectionToken, Provider, AfterContentChecked, ElementRef } from '@angular/core';
4
- import { KbqColorDirective, KbqComponentColors } from '@koobiq/components/core';
5
- import { FocusMonitor, FocusOrigin } from '@angular/cdk/a11y';
2
+ import { Signal, InjectionToken, AfterContentInit, Provider, QueryList, AfterViewInit, OnDestroy, ChangeDetectorRef, TemplateRef, OutputEmitterRef, AfterContentChecked, ElementRef } from '@angular/core';
3
+ import { KbqIconButton } from '@koobiq/components/icon';
6
4
  import { NgControl } from '@angular/forms';
7
5
  import { Observable, Subject } from 'rxjs';
6
+ import { KbqColorDirective, KbqComponentColors } from '@koobiq/components/core';
7
+ import { FocusMonitor, FocusOrigin } from '@angular/cdk/a11y';
8
8
  import { KbqTooltipTrigger } from '@koobiq/components/tooltip';
9
9
 
10
+ /** An interface which allows a control to work inside of a `KbqFormField`. */
11
+ declare abstract class KbqFormFieldControl<T> {
12
+ /** The value of the control. */
13
+ value: T | null;
14
+ /**
15
+ * Stream that emits whenever the state of the control changes such that the parent `KbqFormField`
16
+ * needs to run change detection.
17
+ */
18
+ readonly stateChanges: Observable<void>;
19
+ /** The element ID for this control. */
20
+ readonly id: string;
21
+ /** The placeholder for this control. */
22
+ readonly placeholder: string;
23
+ /** Gets the NgControl for this control. */
24
+ readonly ngControl: NgControl | null;
25
+ /** Whether the control is focused. */
26
+ readonly focused: boolean;
27
+ /** Whether the control is empty. */
28
+ readonly empty: boolean;
29
+ /** Whether the control is required. */
30
+ readonly required: boolean;
31
+ /** Whether the control is disabled. */
32
+ readonly disabled: boolean;
33
+ /** Whether the control is in an error state. */
34
+ readonly errorState: boolean;
35
+ /**
36
+ * Whether the control's value was filled in by the browser.
37
+ *
38
+ * Implement it only where autofill is reachable: on a control that is itself a text input or a
39
+ * textarea, or — like `KbqTagList` — on a wrapper that forwards the state of the input it hosts.
40
+ * Leave it out on controls the browser never fills.
41
+ *
42
+ * A signal rather than a plain property because the form field reads it from a host binding and
43
+ * runs `OnPush`: a signal read there marks the form field dirty on its own.
44
+ */
45
+ readonly autofilled?: Signal<boolean>;
46
+ /**
47
+ * An optional name for the control type that can be used to distinguish `kbq-form-field` elements
48
+ * based on their control type. The form field will add a class,
49
+ * `kbq-form-field-type-{{controlType}}` to its root element.
50
+ */
51
+ readonly controlType?: string;
52
+ /** Handles a click on the control's container. */
53
+ abstract onContainerClick(event: MouseEvent): void;
54
+ /** Focuses the control. */
55
+ abstract focus(options?: FocusOptions): void;
56
+ /** Opens control's overlay. */
57
+ abstract open?(): void;
58
+ }
59
+
60
+ /** @docs-private */
61
+ interface KbqCleanerContext {
62
+ readonly control: KbqFormFieldControl<unknown>;
63
+ readonly keydownTarget: HTMLElement;
64
+ readonly clearByEscape: boolean;
65
+ /** Overrides the default `cleanerControl.ngControl?.reset()` behavior when the cleaner is activated. */
66
+ clear?(): void;
67
+ }
68
+ /** @docs-private */
69
+ declare const KBQ_CLEANER_CONTEXT: InjectionToken<KbqCleanerContext | null>;
70
+ /**
71
+ * Utility provider for `KBQ_CLEANER_CONTEXT`, built from a factory that resolves the current host's `KbqCleanerContext`.
72
+ * @docs-private
73
+ */
74
+ declare const kbqCleanerFactoryProvider: (factory: () => KbqCleanerContext) => Provider;
75
+ /** @docs-private */
76
+ declare function getKbqFormFieldYouCanNotUseCleanerInNumberInputError(): Error;
10
77
  /**
11
78
  * Element to be placed in end of the form field.
12
79
  * Resets form control by click.
13
80
  */
14
- declare class KbqCleaner extends KbqIconButton {
81
+ declare class KbqCleaner extends KbqIconButton implements AfterContentInit {
82
+ private readonly context;
83
+ /**
84
+ * Whether the cleaner can be displayed for the current control state.
85
+ * @docs-private
86
+ */
87
+ get canShow(): boolean;
88
+ private readonly a11yLocaleConfiguration;
89
+ /** Accessible name of the cleaner. Defaults to the localized "Clear". */
90
+ readonly ariaLabel: i0.InputSignal<string | undefined>;
91
+ /** @docs-private */
92
+ protected readonly accessibleName: i0.Signal<string>;
15
93
  constructor();
94
+ ngAfterContentInit(): void;
95
+ /**
96
+ * Clears the owning control in response to pointer or keyboard activation.
97
+ * @docs-private
98
+ */
99
+ clear(event: Event): void;
100
+ /**
101
+ * Clears the focused control when Escape handling is enabled.
102
+ */
103
+ private onKeyDown;
16
104
  static ɵfac: i0.ɵɵFactoryDeclaration<KbqCleaner, never>;
17
- static ɵcmp: i0.ɵɵComponentDeclaration<KbqCleaner, "kbq-cleaner", ["kbqCleaner"], {}, {}, never, ["*"], true, never>;
105
+ static ɵcmp: i0.ɵɵComponentDeclaration<KbqCleaner, "kbq-cleaner", ["kbqCleaner"], { "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
18
106
  }
19
107
 
20
108
  /** Hint text to be shown below the form field control. */
@@ -64,45 +152,6 @@ declare class KbqFieldset {
64
152
  static ɵcmp: i0.ɵɵComponentDeclaration<KbqFieldset, "kbq-fieldset", never, {}, {}, ["legend"], ["[kbqLegend]", "*", "kbq-error", "kbq-hint, kbq-password-hint, kbq-reactive-password-hint"], true, never>;
65
153
  }
66
154
 
67
- /** An interface which allows a control to work inside of a `KbqFormField`. */
68
- declare abstract class KbqFormFieldControl<T> {
69
- /** The value of the control. */
70
- value: T | null;
71
- /**
72
- * Stream that emits whenever the state of the control changes such that the parent `KbqFormField`
73
- * needs to run change detection.
74
- */
75
- readonly stateChanges: Observable<void>;
76
- /** The element ID for this control. */
77
- readonly id: string;
78
- /** The placeholder for this control. */
79
- readonly placeholder: string;
80
- /** Gets the NgControl for this control. */
81
- readonly ngControl: NgControl | null;
82
- /** Whether the control is focused. */
83
- readonly focused: boolean;
84
- /** Whether the control is empty. */
85
- readonly empty: boolean;
86
- /** Whether the control is required. */
87
- readonly required: boolean;
88
- /** Whether the control is disabled. */
89
- readonly disabled: boolean;
90
- /** Whether the control is in an error state. */
91
- readonly errorState: boolean;
92
- /**
93
- * An optional name for the control type that can be used to distinguish `kbq-form-field` elements
94
- * based on their control type. The form field will add a class,
95
- * `kbq-form-field-type-{{controlType}}` to its root element.
96
- */
97
- readonly controlType?: string;
98
- /** Handles a click on the control's container. */
99
- abstract onContainerClick(event: MouseEvent): void;
100
- /** Focuses the control. */
101
- abstract focus(options?: FocusOptions): void;
102
- /** Opens control's overlay. */
103
- abstract open?(): void;
104
- }
105
-
106
155
  declare enum PasswordRules {
107
156
  Length = 0,
108
157
  UpperLatin = 1,
@@ -157,14 +206,20 @@ declare class KbqPasswordToggle extends KbqTooltipTrigger implements AfterViewIn
157
206
  protected readonly nativeElement: HTMLElement;
158
207
  protected readonly focusMonitor: FocusMonitor;
159
208
  protected readonly changeDetectorRef: ChangeDetectorRef;
209
+ private readonly a11yLocaleConfiguration;
160
210
  private readonly formField;
161
211
  readonly tabindex: i0.InputSignalWithTransform<number, unknown>;
162
212
  /**
163
213
  * @docs-private
164
214
  */
165
215
  readonly icon: i0.Signal<KbqIconButton>;
216
+ /**
217
+ * Tooltip shown while the password is visible. Reading it resolves to the tooltip matching the current
218
+ * visibility, so that the base trigger renders the right one.
219
+ */
166
220
  get content(): string | TemplateRef<any>;
167
221
  set content(content: string | TemplateRef<any>);
222
+ /** Tooltip shown while the password is hidden. */
168
223
  readonly kbqTooltipHidden: i0.InputSignal<string | TemplateRef<any>>;
169
224
  protected hasError: boolean;
170
225
  /** Form field password control. */
@@ -181,23 +236,24 @@ declare class KbqPasswordToggle extends KbqTooltipTrigger implements AfterViewIn
181
236
  * @docs-private
182
237
  */
183
238
  get visibility(): 'hidden' | 'visible';
184
- constructor();
185
239
  /**
240
+ * Accessible name of the icon-only toggle, describing the action it performs.
241
+ *
186
242
  * @docs-private
187
243
  */
244
+ protected get accessibleName(): string;
245
+ constructor();
188
246
  ngAfterContentInit(): void;
189
- /**
190
- * @docs-private
191
- */
192
247
  ngAfterViewInit(): void;
248
+ ngOnDestroy(): void;
193
249
  /**
194
250
  * @docs-private
195
251
  */
196
- ngOnDestroy(): void;
252
+ toggle(event: Event): void;
197
253
  /**
198
- * @docs-private
254
+ * Toggles password visibility for the Alt+F8 shortcut.
199
255
  */
200
- toggle(event: KeyboardEvent): void;
256
+ private onFormFieldKeyDown;
201
257
  private updateState;
202
258
  static ɵfac: i0.ɵɵFactoryDeclaration<KbqPasswordToggle, never>;
203
259
  static ɵcmp: i0.ɵɵComponentDeclaration<KbqPasswordToggle, "kbq-password-toggle", ["kbqPasswordToggle"], { "tabindex": { "alias": "tabindex"; "required": false; "isSignal": true; }; "content": { "alias": "kbqTooltipNotHidden"; "required": false; }; "kbqTooltipHidden": { "alias": "kbqTooltipHidden"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
@@ -209,10 +265,16 @@ declare class KbqPrefix {
209
265
  static ɵdir: i0.ɵɵDirectiveDeclaration<KbqPrefix, "[kbqPrefix]", ["kbqPrefix"], {}, {}, never, never, true, never>;
210
266
  }
211
267
 
212
- type KbqNumberInput = KbqFormFieldControl<unknown> & {
268
+ /**
269
+ * Narrow structural contract for the control hosted by `kbqNumberInput`, duck-typed here to avoid
270
+ * a circular dependency between `@koobiq/components/form-field` and `@koobiq/components/input`.
271
+ */
272
+ type KbqStepperControl = KbqFormFieldControl<unknown> & {
273
+ readonly controlType: 'input-number';
274
+ readonly step: number;
213
275
  stepUp: (step: number) => void;
276
+ /** Decreases the value by `step`. */
214
277
  stepDown: (step: number) => void;
215
- step: number;
216
278
  };
217
279
  /**
218
280
  * Timeout duration when clicking the up/down arrow
@@ -228,6 +290,7 @@ declare const KBQ_STEPPER_INTERVAL_DELAY = 75;
228
290
  declare class KbqStepper {
229
291
  private readonly formField;
230
292
  private readonly document;
293
+ private readonly destroyRef;
231
294
  /** Emitted when the stepper is incremented. */
232
295
  readonly stepUp: OutputEmitterRef<void>;
233
296
  /** Emitted when the stepper is decremented. */
@@ -246,19 +309,21 @@ declare class KbqStepper {
246
309
  */
247
310
  private readonly longPress;
248
311
  /**
249
- * Form field number control.
312
+ * Form field number control. Resolved once per control change instead of on every template read.
250
313
  *
251
314
  * @docs-private
252
315
  */
253
- protected get control(): KbqNumberInput;
316
+ protected readonly control: i0.Signal<KbqStepperControl>;
317
+ constructor();
254
318
  /**
319
+ * @deprecated No longer required — `KbqStepper` resolves its control automatically via DI.
255
320
  * @docs-private
256
321
  */
257
- connectTo(numberInput: KbqNumberInput): void;
322
+ connectTo(_: any): void;
258
323
  /** @docs-private */
259
- onStepUp($event: MouseEvent): void;
324
+ onStepUp(event: MouseEvent): void;
260
325
  /** @docs-private */
261
- onStepDown($event: MouseEvent): void;
326
+ onStepDown(event: MouseEvent): void;
262
327
  private handleStep;
263
328
  static ɵfac: i0.ɵɵFactoryDeclaration<KbqStepper, never>;
264
329
  static ɵcmp: i0.ɵɵComponentDeclaration<KbqStepper, "kbq-stepper", ["kbqStepper"], {}, { "stepUp": "stepUp"; "stepDown": "stepDown"; }, never, never, true, never>;
@@ -272,8 +337,11 @@ declare class KbqSuffix {
272
337
 
273
338
  /** @docs-private */
274
339
  declare function getKbqFormFieldMissingControlError(): Error;
275
- /** @docs-private */
276
- declare function getKbqFormFieldYouCanNotUseCleanerInNumberInputError(): Error;
340
+ /**
341
+ * Injection token used to access the owning `KbqFormField`.
342
+ * @docs-private
343
+ */
344
+ declare const KBQ_FORM_FIELD: InjectionToken<KbqFormField>;
277
345
  /**
278
346
  * Default options for the kbq-form-field that can be configured using the `KBQ_FORM_FIELD_DEFAULT_OPTIONS`
279
347
  * injection token.
@@ -292,6 +360,7 @@ type KbqFormFieldDefaultOptions = Partial<{
292
360
  }>;
293
361
  /**
294
362
  * Injection token that can be used to configure the default options for all kbq-form-field's.
363
+ * @docs-private
295
364
  */
296
365
  declare const KBQ_FORM_FIELD_DEFAULT_OPTIONS: InjectionToken<Partial<{
297
366
  /** Disables form field borders and shadows. */
@@ -313,6 +382,7 @@ declare class KbqFormField extends KbqColorDirective implements AfterContentInit
313
382
  private readonly changeDetectorRef;
314
383
  private readonly focusMonitor;
315
384
  private readonly defaultOptions;
385
+ private readonly customOverlayOrigin;
316
386
  /**
317
387
  * @docs-private
318
388
  */
@@ -376,6 +446,7 @@ declare class KbqFormField extends KbqColorDirective implements AfterContentInit
376
446
  hovered: boolean;
377
447
  /**
378
448
  * @docs-private
449
+ * @deprecated Unused. This property is no longer used by the form field and will be removed in a future version.
379
450
  */
380
451
  canCleanerClearByEsc: boolean;
381
452
  /** Whether the form field is invalid. */
@@ -457,6 +528,17 @@ declare class KbqFormField extends KbqColorDirective implements AfterContentInit
457
528
  get canShowCleaner(): boolean;
458
529
  /** Whether the form field is disabled. */
459
530
  get disabled(): boolean;
531
+ /**
532
+ * Whether the form field control's value was filled in by the browser. Controls that cannot be
533
+ * autofilled do not implement `autofilled`, and report `false` here.
534
+ *
535
+ * Reflected as `kbq-form-field_autofilled` for application code to key on. The autofill styling
536
+ * does not use it: CSS matches `:autofill` directly, in the same style pass the browser fills
537
+ * the field, where this arrives a frame or two later. Keeping the paint on one source also means
538
+ * a class left behind by a detached or re-attached control cannot tint a field the browser no
539
+ * longer considers autofilled.
540
+ */
541
+ get autofilled(): boolean;
460
542
  ngAfterContentInit(): void;
461
543
  ngAfterContentChecked(): void;
462
544
  ngAfterViewInit(): void;
@@ -475,10 +557,10 @@ declare class KbqFormField extends KbqColorDirective implements AfterContentInit
475
557
  onContainerClick(event: MouseEvent): void;
476
558
  /**
477
559
  * Handles keydown events.
478
- *
560
+ * @deprecated Unused. This method is no longer called by the form field and will be removed in a future version.
479
561
  * @docs-private
480
562
  */
481
- onKeyDown(event: KeyboardEvent): void;
563
+ onKeyDown(_event: KeyboardEvent): void;
482
564
  /**
483
565
  * @docs-private
484
566
  */
@@ -565,5 +647,5 @@ declare class KbqFormFieldModule {
565
647
  static ɵinj: i0.ɵɵInjectorDeclaration<KbqFormFieldModule>;
566
648
  }
567
649
 
568
- export { KBQ_FORM_FIELD_DEFAULT_OPTIONS, KBQ_STEPPER_INITIAL_TIMEOUT, KBQ_STEPPER_INTERVAL_DELAY, KbqCleaner, KbqError, KbqFieldset, KbqFieldsetItem, KbqFormField, KbqFormFieldControl, KbqFormFieldModule, KbqHint, KbqLabel, KbqLegend, KbqPasswordHint, KbqPasswordToggle, KbqPrefix, KbqReactivePasswordHint, KbqStepper, KbqSuffix, KbqTrim, PasswordRules, getKbqFormFieldMissingControlError, getKbqFormFieldYouCanNotUseCleanerInNumberInputError, hasPasswordStrengthError, kbqFormFieldDefaultOptionsProvider, regExpPasswordValidator };
569
- export type { KbqFormFieldDefaultOptions };
650
+ export { KBQ_CLEANER_CONTEXT, KBQ_FORM_FIELD, KBQ_FORM_FIELD_DEFAULT_OPTIONS, KBQ_STEPPER_INITIAL_TIMEOUT, KBQ_STEPPER_INTERVAL_DELAY, KbqCleaner, KbqError, KbqFieldset, KbqFieldsetItem, KbqFormField, KbqFormFieldControl, KbqFormFieldModule, KbqHint, KbqLabel, KbqLegend, KbqPasswordHint, KbqPasswordToggle, KbqPrefix, KbqReactivePasswordHint, KbqStepper, KbqSuffix, KbqTrim, PasswordRules, getKbqFormFieldMissingControlError, getKbqFormFieldYouCanNotUseCleanerInNumberInputError, hasPasswordStrengthError, kbqCleanerFactoryProvider, kbqFormFieldDefaultOptionsProvider, regExpPasswordValidator };
651
+ export type { KbqCleanerContext, KbqFormFieldDefaultOptions };
@@ -9,7 +9,9 @@
9
9
 
10
10
  padding: var(--kbq-icon-button-size-normal-vertical-padding) var(--kbq-icon-button-size-normal-horizontal-padding);
11
11
 
12
- &.kbq-icon-button_small {
12
+ // @deprcated Will be removed in the next major release (#DS-5338)
13
+ &.kbq-icon-button_small,
14
+ &.kbq-icon-button_compact {
13
15
  padding: var(--kbq-icon-button-size-small-vertical-padding) var(--kbq-icon-button-size-small-horizontal-padding);
14
16
  }
15
17