@kirbydesign/designsystem 0.0.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 (552) hide show
  1. package/README.md +7 -0
  2. package/karma.conf.js +34 -0
  3. package/ng-package.json +32 -0
  4. package/ngcc.config.js +3 -0
  5. package/package.json +27 -0
  6. package/src/index.ts +1 -0
  7. package/src/lib/animation/kirby-animation.ts +12 -0
  8. package/src/lib/components/accordion/accordion-item.component.html +25 -0
  9. package/src/lib/components/accordion/accordion-item.component.scss +64 -0
  10. package/src/lib/components/accordion/accordion-item.component.spec.ts +52 -0
  11. package/src/lib/components/accordion/accordion-item.component.ts +27 -0
  12. package/src/lib/components/accordion/accordion.directive.ts +7 -0
  13. package/src/lib/components/accordion/index.ts +2 -0
  14. package/src/lib/components/angular-component-lib/utils.ts +43 -0
  15. package/src/lib/components/app/app.component.html +3 -0
  16. package/src/lib/components/app/app.component.scss +10 -0
  17. package/src/lib/components/app/app.component.spec.ts +52 -0
  18. package/src/lib/components/app/app.component.ts +50 -0
  19. package/src/lib/components/app/app.module.ts +12 -0
  20. package/src/lib/components/app/index.ts +2 -0
  21. package/src/lib/components/avatar/avatar.component.html +6 -0
  22. package/src/lib/components/avatar/avatar.component.scss +153 -0
  23. package/src/lib/components/avatar/avatar.component.spec.ts +207 -0
  24. package/src/lib/components/avatar/avatar.component.ts +32 -0
  25. package/src/lib/components/badge/badge.component.spec.ts +78 -0
  26. package/src/lib/components/button/button.component.html +1 -0
  27. package/src/lib/components/button/button.component.integration.spec.ts +576 -0
  28. package/src/lib/components/button/button.component.scss +286 -0
  29. package/src/lib/components/button/button.component.spec.ts +404 -0
  30. package/src/lib/components/button/button.component.ts +96 -0
  31. package/src/lib/components/calendar/calendar.component.html +49 -0
  32. package/src/lib/components/calendar/calendar.component.initialization.spec.ts +93 -0
  33. package/src/lib/components/calendar/calendar.component.scss +132 -0
  34. package/src/lib/components/calendar/calendar.component.spec.ts +470 -0
  35. package/src/lib/components/calendar/calendar.component.ts +513 -0
  36. package/src/lib/components/calendar/helpers/calendar-cell.model.ts +7 -0
  37. package/src/lib/components/calendar/helpers/calendar-options.model.ts +10 -0
  38. package/src/lib/components/calendar/helpers/calendar.helper.ts +108 -0
  39. package/src/lib/components/calendar/index.ts +2 -0
  40. package/src/lib/components/calendar/options/calendar-year-navigator-config.ts +4 -0
  41. package/src/lib/components/card/card-footer/card-footer.component.html +3 -0
  42. package/src/lib/components/card/card-footer/card-footer.component.scss +19 -0
  43. package/src/lib/components/card/card-footer/card-footer.component.ts +13 -0
  44. package/src/lib/components/card/card-header/card-header.component.html +5 -0
  45. package/src/lib/components/card/card-header/card-header.component.scss +63 -0
  46. package/src/lib/components/card/card-header/card-header.component.ts +20 -0
  47. package/src/lib/components/card/card.component.html +5 -0
  48. package/src/lib/components/card/card.component.scss +56 -0
  49. package/src/lib/components/card/card.component.spec.ts +81 -0
  50. package/src/lib/components/card/card.component.ts +95 -0
  51. package/src/lib/components/card/index.ts +3 -0
  52. package/src/lib/components/chart/chart-js/chart-js.service.integration.spec.ts +320 -0
  53. package/src/lib/components/chart/chart-js/chart-js.service.spec.ts +1004 -0
  54. package/src/lib/components/chart/chart-js/chart-js.service.ts +445 -0
  55. package/src/lib/components/chart/chart-js/chartjs-plugin-marker/chartjs-plugin-marker.ts +254 -0
  56. package/src/lib/components/chart/chart-js/configured-chart-js.ts +39 -0
  57. package/src/lib/components/chart/chart-js/test-utils.ts +171 -0
  58. package/src/lib/components/chart/chart.component.html +7 -0
  59. package/src/lib/components/chart/chart.component.scss +6 -0
  60. package/src/lib/components/chart/chart.component.spec.ts +188 -0
  61. package/src/lib/components/chart/chart.component.ts +148 -0
  62. package/src/lib/components/chart/chart.module.ts +11 -0
  63. package/src/lib/components/chart/chart.types.ts +34 -0
  64. package/src/lib/components/chart/configs/annotations.config.ts +36 -0
  65. package/src/lib/components/chart/configs/chart-config.service.spec.ts +21 -0
  66. package/src/lib/components/chart/configs/chart-config.service.ts +34 -0
  67. package/src/lib/components/chart/configs/global-defaults.config.ts +50 -0
  68. package/src/lib/components/chart/configs/interaction-functions-extensions.config.ts +19 -0
  69. package/src/lib/components/chart/configs/shared.utils.ts +28 -0
  70. package/src/lib/components/chart/configs/type.config.ts +214 -0
  71. package/src/lib/components/chart/index.ts +5 -0
  72. package/src/lib/components/chart-deprecated/chart-deprecated-helper.ts +25 -0
  73. package/src/lib/components/chart-deprecated/chart-deprecated-type.ts +10 -0
  74. package/src/lib/components/chart-deprecated/chart-deprecated.component.scss +3 -0
  75. package/src/lib/components/chart-deprecated/chart-deprecated.component.spec.ts +271 -0
  76. package/src/lib/components/chart-deprecated/chart-deprecated.component.ts +233 -0
  77. package/src/lib/components/chart-deprecated/index.ts +2 -0
  78. package/src/lib/components/chart-deprecated/options/activitygauge.ts +87 -0
  79. package/src/lib/components/chart-deprecated/options/areaspline.ts +95 -0
  80. package/src/lib/components/chart-deprecated/options/bar.ts +93 -0
  81. package/src/lib/components/chart-deprecated/options/column.ts +101 -0
  82. package/src/lib/components/chart-deprecated/options/donut.ts +118 -0
  83. package/src/lib/components/chart-deprecated/options/timeseries.ts +96 -0
  84. package/src/lib/components/checkbox/checkbox.component.html +10 -0
  85. package/src/lib/components/checkbox/checkbox.component.integration.spec.ts +59 -0
  86. package/src/lib/components/checkbox/checkbox.component.scss +130 -0
  87. package/src/lib/components/checkbox/checkbox.component.spec.ts +205 -0
  88. package/src/lib/components/checkbox/checkbox.component.ts +56 -0
  89. package/src/lib/components/chip/chip.component.html +1 -0
  90. package/src/lib/components/chip/chip.component.integration.spec.ts +111 -0
  91. package/src/lib/components/chip/chip.component.scss +49 -0
  92. package/src/lib/components/chip/chip.component.spec.ts +84 -0
  93. package/src/lib/components/chip/chip.component.ts +16 -0
  94. package/src/lib/components/divider/divider.component.html +1 -0
  95. package/src/lib/components/divider/divider.component.scss +22 -0
  96. package/src/lib/components/divider/divider.component.spec.ts +24 -0
  97. package/src/lib/components/divider/divider.component.ts +12 -0
  98. package/src/lib/components/dropdown/dropdown-popover.component.integration.spec.ts +177 -0
  99. package/src/lib/components/dropdown/dropdown-popover.component.spec.ts +1154 -0
  100. package/src/lib/components/dropdown/dropdown.component.html +42 -0
  101. package/src/lib/components/dropdown/dropdown.component.scss +142 -0
  102. package/src/lib/components/dropdown/dropdown.component.spec.ts +1215 -0
  103. package/src/lib/components/dropdown/dropdown.component.ts +538 -0
  104. package/src/lib/components/dropdown/dropdown.types.ts +10 -0
  105. package/src/lib/components/dropdown/keyboard-handler.service.ts +38 -0
  106. package/src/lib/components/empty-state/empty-state.component.html +10 -0
  107. package/src/lib/components/empty-state/empty-state.component.integration.spec.ts +110 -0
  108. package/src/lib/components/empty-state/empty-state.component.scss +50 -0
  109. package/src/lib/components/empty-state/empty-state.component.spec.ts +40 -0
  110. package/src/lib/components/empty-state/empty-state.component.ts +50 -0
  111. package/src/lib/components/fab-sheet/fab-sheet.component.html +13 -0
  112. package/src/lib/components/fab-sheet/fab-sheet.component.scss +67 -0
  113. package/src/lib/components/fab-sheet/fab-sheet.component.spec.ts +29 -0
  114. package/src/lib/components/fab-sheet/fab-sheet.component.ts +100 -0
  115. package/src/lib/components/flag/flag.component.scss +40 -0
  116. package/src/lib/components/flag/flag.component.spec.ts +152 -0
  117. package/src/lib/components/flag/flag.component.ts +18 -0
  118. package/src/lib/components/form-field/_form-field-inputs.shared.scss +62 -0
  119. package/src/lib/components/form-field/directives/date/date-input.directive.spec.ts +127 -0
  120. package/src/lib/components/form-field/directives/date/date-input.directive.ts +94 -0
  121. package/src/lib/components/form-field/directives/decimal-mask/decimal-mask.directive.spec.ts +231 -0
  122. package/src/lib/components/form-field/directives/decimal-mask/decimal-mask.directive.ts +113 -0
  123. package/src/lib/components/form-field/form-field-message/form-field-message.component.html +1 -0
  124. package/src/lib/components/form-field/form-field-message/form-field-message.component.scss +11 -0
  125. package/src/lib/components/form-field/form-field-message/form-field-message.component.ts +12 -0
  126. package/src/lib/components/form-field/form-field.component.html +39 -0
  127. package/src/lib/components/form-field/form-field.component.scss +43 -0
  128. package/src/lib/components/form-field/form-field.component.spec.ts +521 -0
  129. package/src/lib/components/form-field/form-field.component.ts +141 -0
  130. package/src/lib/components/form-field/index.ts +7 -0
  131. package/src/lib/components/form-field/input/input.component.integration.spec.ts +83 -0
  132. package/src/lib/components/form-field/input/input.component.scss +54 -0
  133. package/src/lib/components/form-field/input/input.component.spec.ts +159 -0
  134. package/src/lib/components/form-field/input/input.component.ts +91 -0
  135. package/src/lib/components/form-field/input-counter/input-counter.component.html +1 -0
  136. package/src/lib/components/form-field/input-counter/input-counter.component.spec.ts +184 -0
  137. package/src/lib/components/form-field/input-counter/input-counter.component.ts +41 -0
  138. package/src/lib/components/form-field/textarea/textarea.component.html +2 -0
  139. package/src/lib/components/form-field/textarea/textarea.component.scss +11 -0
  140. package/src/lib/components/form-field/textarea/textarea.component.spec.ts +100 -0
  141. package/src/lib/components/form-field/textarea/textarea.component.ts +64 -0
  142. package/src/lib/components/grid/breakpoint-helper.service.ts +27 -0
  143. package/src/lib/components/grid/grid-card-configuration.ts +7 -0
  144. package/src/lib/components/grid/grid.component.html +6 -0
  145. package/src/lib/components/grid/grid.component.scss +26 -0
  146. package/src/lib/components/grid/grid.component.ts +106 -0
  147. package/src/lib/components/icon/icon-registry.service.spec.ts +107 -0
  148. package/src/lib/components/icon/icon-registry.service.ts +39 -0
  149. package/src/lib/components/icon/icon-settings.ts +8 -0
  150. package/src/lib/components/icon/icon.component.html +1 -0
  151. package/src/lib/components/icon/icon.component.scss +47 -0
  152. package/src/lib/components/icon/icon.component.spec.ts +254 -0
  153. package/src/lib/components/icon/icon.component.ts +89 -0
  154. package/src/lib/components/icon/icon.module.ts +11 -0
  155. package/src/lib/components/icon/index.ts +5 -0
  156. package/src/lib/components/icon/kirby-icon-settings.ts +65 -0
  157. package/src/lib/components/icon/readme.md +16 -0
  158. package/src/lib/components/icon/selection.json +1776 -0
  159. package/src/lib/components/index.ts +67 -0
  160. package/src/lib/components/item/_item.utils.scss +36 -0
  161. package/src/lib/components/item/index.ts +3 -0
  162. package/src/lib/components/item/item.component.html +16 -0
  163. package/src/lib/components/item/item.component.integration.spec.ts +64 -0
  164. package/src/lib/components/item/item.component.scss +156 -0
  165. package/src/lib/components/item/item.component.spec.ts +85 -0
  166. package/src/lib/components/item/item.component.ts +37 -0
  167. package/src/lib/components/item/item.module.ts +14 -0
  168. package/src/lib/components/item/label/label.component.html +3 -0
  169. package/src/lib/components/item/label/label.component.scss +36 -0
  170. package/src/lib/components/item/label/label.component.spec.ts +23 -0
  171. package/src/lib/components/item/label/label.component.ts +16 -0
  172. package/src/lib/components/item-group/item-group.component.html +1 -0
  173. package/src/lib/components/item-group/item-group.component.scss +3 -0
  174. package/src/lib/components/item-group/item-group.component.spec.ts +42 -0
  175. package/src/lib/components/item-group/item-group.component.ts +10 -0
  176. package/src/lib/components/item-sliding/index.ts +2 -0
  177. package/src/lib/components/item-sliding/item-sliding.component.html +20 -0
  178. package/src/lib/components/item-sliding/item-sliding.component.scss +9 -0
  179. package/src/lib/components/item-sliding/item-sliding.component.spec.ts +174 -0
  180. package/src/lib/components/item-sliding/item-sliding.component.ts +23 -0
  181. package/src/lib/components/item-sliding/item-sliding.shared.scss +18 -0
  182. package/src/lib/components/item-sliding/item-sliding.types.ts +13 -0
  183. package/src/lib/components/list/directives/infinite-scroll.directive.spec.ts +131 -0
  184. package/src/lib/components/list/directives/infinite-scroll.directive.ts +137 -0
  185. package/src/lib/components/list/directives/list-item-color.directive.ts +27 -0
  186. package/src/lib/components/list/directives/scroll.model.ts +5 -0
  187. package/src/lib/components/list/helpers/list-helper.spec.ts +109 -0
  188. package/src/lib/components/list/helpers/list-helper.ts +19 -0
  189. package/src/lib/components/list/index.ts +21 -0
  190. package/src/lib/components/list/list-experimental/list-experimental.component.html +4 -0
  191. package/src/lib/components/list/list-experimental/list-experimental.component.scss +6 -0
  192. package/src/lib/components/list/list-experimental/list-experimental.component.spec.ts +112 -0
  193. package/src/lib/components/list/list-experimental/list-experimental.component.ts +21 -0
  194. package/src/lib/components/list/list-header/list-header.component.html +1 -0
  195. package/src/lib/components/list/list-header/list-header.component.scss +10 -0
  196. package/src/lib/components/list/list-header/list-header.component.spec.ts +24 -0
  197. package/src/lib/components/list/list-header/list-header.component.ts +11 -0
  198. package/src/lib/components/list/list-item/list-item.component.html +39 -0
  199. package/src/lib/components/list/list-item/list-item.component.scss +13 -0
  200. package/src/lib/components/list/list-item/list-item.component.ts +144 -0
  201. package/src/lib/components/list/list-section-header/list-section-header.component.html +3 -0
  202. package/src/lib/components/list/list-section-header/list-section-header.component.spec.ts +24 -0
  203. package/src/lib/components/list/list-section-header/list-section-header.component.ts +13 -0
  204. package/src/lib/components/list/list-swipe-action.ts +2 -0
  205. package/src/lib/components/list/list-swipe-action.type.ts +23 -0
  206. package/src/lib/components/list/list.component.html +65 -0
  207. package/src/lib/components/list/list.component.integration.spec.ts +177 -0
  208. package/src/lib/components/list/list.component.scss +243 -0
  209. package/src/lib/components/list/list.component.spec.ts +219 -0
  210. package/src/lib/components/list/list.component.ts +213 -0
  211. package/src/lib/components/list/list.directive.ts +21 -0
  212. package/src/lib/components/list/list.event.ts +8 -0
  213. package/src/lib/components/list/list.module.ts +47 -0
  214. package/src/lib/components/list/pipes/group-by.pipe.spec.ts +71 -0
  215. package/src/lib/components/list/pipes/group-by.pipe.ts +34 -0
  216. package/src/lib/components/loading-overlay/index.ts +2 -0
  217. package/src/lib/components/loading-overlay/loading-overlay.component.html +8 -0
  218. package/src/lib/components/loading-overlay/loading-overlay.component.scss +37 -0
  219. package/src/lib/components/loading-overlay/loading-overlay.component.ts +12 -0
  220. package/src/lib/components/loading-overlay/loading-overlay.service.ts +44 -0
  221. package/src/lib/components/modal/action-sheet/action-sheet.component.html +24 -0
  222. package/src/lib/components/modal/action-sheet/action-sheet.component.scss +47 -0
  223. package/src/lib/components/modal/action-sheet/action-sheet.component.spec.ts +153 -0
  224. package/src/lib/components/modal/action-sheet/action-sheet.component.ts +27 -0
  225. package/src/lib/components/modal/action-sheet/config/action-sheet-config.ts +8 -0
  226. package/src/lib/components/modal/action-sheet/config/action-sheet-item.ts +4 -0
  227. package/src/lib/components/modal/alert/alert.component.html +29 -0
  228. package/src/lib/components/modal/alert/alert.component.scss +21 -0
  229. package/src/lib/components/modal/alert/alert.component.spec.ts +104 -0
  230. package/src/lib/components/modal/alert/alert.component.ts +67 -0
  231. package/src/lib/components/modal/alert/config/alert-config.ts +19 -0
  232. package/src/lib/components/modal/footer/modal-footer.component.html +3 -0
  233. package/src/lib/components/modal/footer/modal-footer.component.scss +57 -0
  234. package/src/lib/components/modal/footer/modal-footer.component.spec.ts +209 -0
  235. package/src/lib/components/modal/footer/modal-footer.component.ts +17 -0
  236. package/src/lib/components/modal/index.ts +9 -0
  237. package/src/lib/components/modal/modal-wrapper/compact/modal-compact-wrapper.component.html +3 -0
  238. package/src/lib/components/modal/modal-wrapper/compact/modal-compact-wrapper.component.scss +8 -0
  239. package/src/lib/components/modal/modal-wrapper/compact/modal-compact-wrapper.component.ts +79 -0
  240. package/src/lib/components/modal/modal-wrapper/config/drawer-supplementary-action.ts +4 -0
  241. package/src/lib/components/modal/modal-wrapper/config/modal-config.helper.ts +3 -0
  242. package/src/lib/components/modal/modal-wrapper/config/modal-config.ts +22 -0
  243. package/src/lib/components/modal/modal-wrapper/modal-wrapper.component.html +43 -0
  244. package/src/lib/components/modal/modal-wrapper/modal-wrapper.component.scss +159 -0
  245. package/src/lib/components/modal/modal-wrapper/modal-wrapper.component.spec.ts +942 -0
  246. package/src/lib/components/modal/modal-wrapper/modal-wrapper.component.ts +587 -0
  247. package/src/lib/components/modal/modal-wrapper/modal-wrapper.testbuilder.ts +155 -0
  248. package/src/lib/components/modal/services/action-sheet.helper.spec.ts +86 -0
  249. package/src/lib/components/modal/services/action-sheet.helper.ts +47 -0
  250. package/src/lib/components/modal/services/alert.helper.spec.ts +89 -0
  251. package/src/lib/components/modal/services/alert.helper.ts +57 -0
  252. package/src/lib/components/modal/services/modal-animation-builder.service.ts +276 -0
  253. package/src/lib/components/modal/services/modal-navigation.service.spec.ts +543 -0
  254. package/src/lib/components/modal/services/modal-navigation.service.ts +331 -0
  255. package/src/lib/components/modal/services/modal.controller.spec.ts +212 -0
  256. package/src/lib/components/modal/services/modal.controller.ts +194 -0
  257. package/src/lib/components/modal/services/modal.helper.spec.ts +828 -0
  258. package/src/lib/components/modal/services/modal.helper.ts +128 -0
  259. package/src/lib/components/modal/services/modal.interfaces.ts +28 -0
  260. package/src/lib/components/page/index.ts +13 -0
  261. package/src/lib/components/page/page-footer/page-footer.component.html +3 -0
  262. package/src/lib/components/page/page-footer/page-footer.component.scss +23 -0
  263. package/src/lib/components/page/page-footer/page-footer.component.spec.ts +52 -0
  264. package/src/lib/components/page/page-footer/page-footer.component.ts +46 -0
  265. package/src/lib/components/page/page.component.html +101 -0
  266. package/src/lib/components/page/page.component.scss +141 -0
  267. package/src/lib/components/page/page.component.spec.ts +224 -0
  268. package/src/lib/components/page/page.component.ts +415 -0
  269. package/src/lib/components/page/page.module.ts +52 -0
  270. package/src/lib/components/popover/popover.component.scss +26 -0
  271. package/src/lib/components/popover/popover.component.spec.ts +0 -0
  272. package/src/lib/components/popover/popover.component.ts +221 -0
  273. package/src/lib/components/progress-circle/progress-circle-ring.component.scss +22 -0
  274. package/src/lib/components/progress-circle/progress-circle-ring.component.spec.ts +143 -0
  275. package/src/lib/components/progress-circle/progress-circle-ring.component.svg +23 -0
  276. package/src/lib/components/progress-circle/progress-circle-ring.component.ts +42 -0
  277. package/src/lib/components/progress-circle/progress-circle.component.html +11 -0
  278. package/src/lib/components/progress-circle/progress-circle.component.scss +28 -0
  279. package/src/lib/components/progress-circle/progress-circle.component.spec.ts +339 -0
  280. package/src/lib/components/progress-circle/progress-circle.component.ts +96 -0
  281. package/src/lib/components/radio/index.ts +2 -0
  282. package/src/lib/components/radio/radio-group/radio-group.component.html +24 -0
  283. package/src/lib/components/radio/radio-group/radio-group.component.spec.ts +1328 -0
  284. package/src/lib/components/radio/radio-group/radio-group.component.ts +272 -0
  285. package/src/lib/components/radio/radio.component.html +9 -0
  286. package/src/lib/components/radio/radio.component.integration.spec.ts +93 -0
  287. package/src/lib/components/radio/radio.component.scss +133 -0
  288. package/src/lib/components/radio/radio.component.spec.ts +244 -0
  289. package/src/lib/components/radio/radio.component.ts +50 -0
  290. package/src/lib/components/range/range.component.html +16 -0
  291. package/src/lib/components/range/range.component.scss +81 -0
  292. package/src/lib/components/range/range.component.ts +105 -0
  293. package/src/lib/components/reorder-list/index.ts +3 -0
  294. package/src/lib/components/reorder-list/reorder-event.ts +17 -0
  295. package/src/lib/components/reorder-list/reorder-list.component.html +30 -0
  296. package/src/lib/components/reorder-list/reorder-list.component.scss +90 -0
  297. package/src/lib/components/reorder-list/reorder-list.component.spec.ts +123 -0
  298. package/src/lib/components/reorder-list/reorder-list.component.ts +86 -0
  299. package/src/lib/components/router-outlet/index.ts +5 -0
  300. package/src/lib/components/router-outlet/router-outlet.component.html +6 -0
  301. package/src/lib/components/router-outlet/router-outlet.component.scss +13 -0
  302. package/src/lib/components/router-outlet/router-outlet.component.spec.ts +28 -0
  303. package/src/lib/components/router-outlet/router-outlet.component.ts +11 -0
  304. package/src/lib/components/router-outlet/router-outlet.module.ts +12 -0
  305. package/src/lib/components/section-header/_section-header.utils.scss +34 -0
  306. package/src/lib/components/section-header/section-header.component.html +3 -0
  307. package/src/lib/components/section-header/section-header.component.scss +15 -0
  308. package/src/lib/components/section-header/section-header.component.spec.ts +59 -0
  309. package/src/lib/components/section-header/section-header.component.ts +9 -0
  310. package/src/lib/components/section-header/section-header.integration.spec.ts +67 -0
  311. package/src/lib/components/segmented-control/segment-item.ts +18 -0
  312. package/src/lib/components/segmented-control/segmented-control.component.html +39 -0
  313. package/src/lib/components/segmented-control/segmented-control.component.scss +84 -0
  314. package/src/lib/components/segmented-control/segmented-control.component.spec.ts +247 -0
  315. package/src/lib/components/segmented-control/segmented-control.component.ts +96 -0
  316. package/src/lib/components/shared/component-configuration.ts +6 -0
  317. package/src/lib/components/shared/component-loader.directive.ts +42 -0
  318. package/src/lib/components/shared/dynamic-component.ts +3 -0
  319. package/src/lib/components/shared/index.ts +9 -0
  320. package/src/lib/components/shared/resize-observer/resize-observer.factory.ts +20 -0
  321. package/src/lib/components/shared/resize-observer/resize-observer.service.ts +65 -0
  322. package/src/lib/components/shared/resize-observer/types/resize-observer-callback.ts +7 -0
  323. package/src/lib/components/shared/resize-observer/types/resize-observer-entry.ts +14 -0
  324. package/src/lib/components/shared/resize-observer/types/resize-observer.ts +17 -0
  325. package/src/lib/components/slide-button/slide-button.component.html +14 -0
  326. package/src/lib/components/slide-button/slide-button.component.scss +81 -0
  327. package/src/lib/components/slide-button/slide-button.component.shared.scss +12 -0
  328. package/src/lib/components/slide-button/slide-button.component.spec.ts +75 -0
  329. package/src/lib/components/slide-button/slide-button.component.ts +81 -0
  330. package/src/lib/components/slides/slides.component.spec.ts +76 -0
  331. package/src/lib/components/slides/slides.component.ts +57 -0
  332. package/src/lib/components/spinner/index.ts +2 -0
  333. package/src/lib/components/spinner/spinner.component.html +4 -0
  334. package/src/lib/components/spinner/spinner.component.scss +37 -0
  335. package/src/lib/components/spinner/spinner.component.ts +13 -0
  336. package/src/lib/components/spinner/spinner.module.ts +12 -0
  337. package/src/lib/components/stock-chart-deprecated/index.ts +2 -0
  338. package/src/lib/components/stock-chart-deprecated/options/stock-chart-deprecated-options.ts +220 -0
  339. package/src/lib/components/stock-chart-deprecated/stock-chart-deprecated.component.scss +3 -0
  340. package/src/lib/components/stock-chart-deprecated/stock-chart-deprecated.component.spec.ts +32 -0
  341. package/src/lib/components/stock-chart-deprecated/stock-chart-deprecated.component.ts +92 -0
  342. package/src/lib/components/tabs/index.ts +5 -0
  343. package/src/lib/components/tabs/tab-button/tab-button.component.html +13 -0
  344. package/src/lib/components/tabs/tab-button/tab-button.component.scss +48 -0
  345. package/src/lib/components/tabs/tab-button/tab-button.component.spec.ts +24 -0
  346. package/src/lib/components/tabs/tab-button/tab-button.component.ts +47 -0
  347. package/src/lib/components/tabs/tab-button/tab-button.events.ts +1 -0
  348. package/src/lib/components/tabs/tabs.component.html +5 -0
  349. package/src/lib/components/tabs/tabs.component.scss +52 -0
  350. package/src/lib/components/tabs/tabs.component.spec.ts +125 -0
  351. package/src/lib/components/tabs/tabs.component.ts +21 -0
  352. package/src/lib/components/tabs/tabs.module.ts +16 -0
  353. package/src/lib/components/tabs/tabs.service.ts +17 -0
  354. package/src/lib/components/toast/config/toast-config.ts +8 -0
  355. package/src/lib/components/toast/index.ts +2 -0
  356. package/src/lib/components/toast/services/toast.controller.ts +18 -0
  357. package/src/lib/components/toast/services/toast.helper.spec.ts +89 -0
  358. package/src/lib/components/toast/services/toast.helper.ts +39 -0
  359. package/src/lib/components/toggle/toggle.component.html +5 -0
  360. package/src/lib/components/toggle/toggle.component.scss +5 -0
  361. package/src/lib/components/toggle/toggle.component.spec.ts +62 -0
  362. package/src/lib/components/toggle/toggle.component.ts +17 -0
  363. package/src/lib/components/toggle-button/index.ts +2 -0
  364. package/src/lib/components/toggle-button/toggle-button.component.html +6 -0
  365. package/src/lib/components/toggle-button/toggle-button.component.spec.ts +23 -0
  366. package/src/lib/components/toggle-button/toggle-button.component.ts +24 -0
  367. package/src/lib/components/toggle-button/toggle-button.module.ts +13 -0
  368. package/src/lib/components/web-component-proxies.component.ts +25 -0
  369. package/src/lib/custom-elements-initializer.ts +19 -0
  370. package/src/lib/directives/element-as-button/element-as-button.directive.spec.ts +31 -0
  371. package/src/lib/directives/element-as-button/element-as-button.directive.ts +26 -0
  372. package/src/lib/directives/fit-heading/fit-heading.directive.ts +131 -0
  373. package/src/lib/directives/fit-heading/fit-heading.module.ts +9 -0
  374. package/src/lib/directives/index.ts +9 -0
  375. package/src/lib/directives/key-handler/key-handler.directive.ts +20 -0
  376. package/src/lib/directives/modal-router-link/modal-router-link.directive.ts +24 -0
  377. package/src/lib/directives/theme-color/theme-color.directive.ts +117 -0
  378. package/src/lib/helpers/color-helper.styles.ts +193 -0
  379. package/src/lib/helpers/color-helper.ts +1 -0
  380. package/src/lib/helpers/deep-copy.ts +13 -0
  381. package/src/lib/helpers/design-token-helper.styles.ts +78 -0
  382. package/src/lib/helpers/design-token-helper.ts +6 -0
  383. package/src/lib/helpers/element-has-ancestor.ts +28 -0
  384. package/src/lib/helpers/index.ts +8 -0
  385. package/src/lib/helpers/line-clamp-helper.ts +28 -0
  386. package/src/lib/helpers/merge-deep.spec.ts +11 -0
  387. package/src/lib/helpers/merge-deep.ts +41 -0
  388. package/src/lib/helpers/platform.service.ts +22 -0
  389. package/src/lib/helpers/string-helper.ts +6 -0
  390. package/src/lib/helpers/theme-color.type.ts +1 -0
  391. package/src/lib/helpers/unique-id-generator.helper.spec.ts +58 -0
  392. package/src/lib/helpers/unique-id-generator.helper.ts +19 -0
  393. package/src/lib/icons/svg/QR.svg +7 -0
  394. package/src/lib/icons/svg/accounts-outline.svg +9 -0
  395. package/src/lib/icons/svg/accounts.svg +9 -0
  396. package/src/lib/icons/svg/add.svg +7 -0
  397. package/src/lib/icons/svg/arrow-back.svg +7 -0
  398. package/src/lib/icons/svg/arrow-down.svg +7 -0
  399. package/src/lib/icons/svg/arrow-more.svg +7 -0
  400. package/src/lib/icons/svg/arrow-up.svg +7 -0
  401. package/src/lib/icons/svg/attach.svg +7 -0
  402. package/src/lib/icons/svg/backspace.svg +9 -0
  403. package/src/lib/icons/svg/calendar.svg +7 -0
  404. package/src/lib/icons/svg/camera.svg +9 -0
  405. package/src/lib/icons/svg/checkbox-outline.svg +7 -0
  406. package/src/lib/icons/svg/checkbox.svg +7 -0
  407. package/src/lib/icons/svg/checkmark-selected.svg +3 -0
  408. package/src/lib/icons/svg/clock.svg +7 -0
  409. package/src/lib/icons/svg/close.svg +7 -0
  410. package/src/lib/icons/svg/cog.svg +7 -0
  411. package/src/lib/icons/svg/copy.svg +9 -0
  412. package/src/lib/icons/svg/edit.svg +7 -0
  413. package/src/lib/icons/svg/filter.svg +7 -0
  414. package/src/lib/icons/svg/flag.svg +9 -0
  415. package/src/lib/icons/svg/flash-off.svg +7 -0
  416. package/src/lib/icons/svg/flash.svg +7 -0
  417. package/src/lib/icons/svg/foreign-payment.svg +7 -0
  418. package/src/lib/icons/svg/help.svg +7 -0
  419. package/src/lib/icons/svg/home.svg +5 -0
  420. package/src/lib/icons/svg/inbox-outline.svg +9 -0
  421. package/src/lib/icons/svg/inbox.svg +9 -0
  422. package/src/lib/icons/svg/information.svg +9 -0
  423. package/src/lib/icons/svg/investment.svg +5 -0
  424. package/src/lib/icons/svg/kirby.svg +3 -0
  425. package/src/lib/icons/svg/link.svg +7 -0
  426. package/src/lib/icons/svg/log-out.svg +7 -0
  427. package/src/lib/icons/svg/menu-outline.svg +9 -0
  428. package/src/lib/icons/svg/menu.svg +9 -0
  429. package/src/lib/icons/svg/misc.svg +5 -0
  430. package/src/lib/icons/svg/moneybag.svg +7 -0
  431. package/src/lib/icons/svg/more.svg +5 -0
  432. package/src/lib/icons/svg/move.svg +7 -0
  433. package/src/lib/icons/svg/payment-card.svg +6 -0
  434. package/src/lib/icons/svg/pension.svg +7 -0
  435. package/src/lib/icons/svg/person-outline.svg +9 -0
  436. package/src/lib/icons/svg/person.svg +9 -0
  437. package/src/lib/icons/svg/remove.svg +6 -0
  438. package/src/lib/icons/svg/reorder.svg +9 -0
  439. package/src/lib/icons/svg/search.svg +7 -0
  440. package/src/lib/icons/svg/share.svg +7 -0
  441. package/src/lib/icons/svg/sort.svg +7 -0
  442. package/src/lib/icons/svg/support.svg +9 -0
  443. package/src/lib/icons/svg/swap.svg +7 -0
  444. package/src/lib/icons/svg/trash.svg +7 -0
  445. package/src/lib/icons/svg/unsubscribe.svg +7 -0
  446. package/src/lib/icons/svg/verify.svg +7 -0
  447. package/src/lib/icons/svg/warning.svg +7 -0
  448. package/src/lib/icons/svg/write-message.svg +7 -0
  449. package/src/lib/index.ts +8 -0
  450. package/src/lib/kirby.module.spec.ts +20 -0
  451. package/src/lib/kirby.module.ts +219 -0
  452. package/src/lib/polyfills/intersection-observer-polyfill-loader.js +14 -0
  453. package/src/lib/polyfills/intersection-observer-polyfill-loader.min.js +1 -0
  454. package/src/lib/polyfills/intersection-observer-polyfill.js +2 -0
  455. package/src/lib/polyfills/intersection-observer-polyfill.min.js +1 -0
  456. package/src/lib/polyfills/resize-observer-polyfill-loader.js +14 -0
  457. package/src/lib/polyfills/resize-observer-polyfill-loader.min.js +1 -0
  458. package/src/lib/polyfills/resize-observer-polyfill.js +2 -0
  459. package/src/lib/polyfills/resize-observer-polyfill.min.js +1 -0
  460. package/src/lib/scss/link.spec.ts +47 -0
  461. package/src/lib/scss/scss-helper.ts +8 -0
  462. package/src/lib/scss/typography.spec.ts +241 -0
  463. package/src/lib/testing/element-css-custom-matchers.d.ts +7 -0
  464. package/src/lib/testing/element-css-custom-matchers.ts +139 -0
  465. package/src/lib/testing/styles.scss +13 -0
  466. package/src/lib/testing/test-helper.ts +158 -0
  467. package/src/lib/types/index.ts +1 -0
  468. package/src/lib/types/window-ref.ts +10 -0
  469. package/src/test.ts +34 -0
  470. package/src/typings.test.d.ts +1 -0
  471. package/testing-base/ng-package.json +3 -0
  472. package/testing-base/src/lib/components/index.ts +66 -0
  473. package/testing-base/src/lib/components/mock.accordion-item.component.ts +21 -0
  474. package/testing-base/src/lib/components/mock.action-sheet.component.ts +27 -0
  475. package/testing-base/src/lib/components/mock.app.component.ts +18 -0
  476. package/testing-base/src/lib/components/mock.avatar.component.ts +38 -0
  477. package/testing-base/src/lib/components/mock.badge.component.ts +20 -0
  478. package/testing-base/src/lib/components/mock.button.component.ts +26 -0
  479. package/testing-base/src/lib/components/mock.calendar.component.ts +36 -0
  480. package/testing-base/src/lib/components/mock.card-footer.component.ts +18 -0
  481. package/testing-base/src/lib/components/mock.card-header.component.ts +23 -0
  482. package/testing-base/src/lib/components/mock.card.component.ts +25 -0
  483. package/testing-base/src/lib/components/mock.chart-deprecated.component.ts +28 -0
  484. package/testing-base/src/lib/components/mock.chart.component.ts +36 -0
  485. package/testing-base/src/lib/components/mock.checkbox.component.ts +26 -0
  486. package/testing-base/src/lib/components/mock.chip.component.ts +21 -0
  487. package/testing-base/src/lib/components/mock.divider.component.ts +20 -0
  488. package/testing-base/src/lib/components/mock.dropdown.component.ts +32 -0
  489. package/testing-base/src/lib/components/mock.empty-state.component.ts +23 -0
  490. package/testing-base/src/lib/components/mock.fab-sheet.component.ts +21 -0
  491. package/testing-base/src/lib/components/mock.flag.component.ts +21 -0
  492. package/testing-base/src/lib/components/mock.form-field-message.component.ts +21 -0
  493. package/testing-base/src/lib/components/mock.form-field.component.ts +23 -0
  494. package/testing-base/src/lib/components/mock.grid.component.ts +21 -0
  495. package/testing-base/src/lib/components/mock.icon.component.ts +22 -0
  496. package/testing-base/src/lib/components/mock.input-counter.component.ts +24 -0
  497. package/testing-base/src/lib/components/mock.input.component.ts +29 -0
  498. package/testing-base/src/lib/components/mock.item-group.component.ts +18 -0
  499. package/testing-base/src/lib/components/mock.item-sliding.component.ts +21 -0
  500. package/testing-base/src/lib/components/mock.item.component.ts +24 -0
  501. package/testing-base/src/lib/components/mock.label.component.ts +20 -0
  502. package/testing-base/src/lib/components/mock.list-experimental.component.ts +18 -0
  503. package/testing-base/src/lib/components/mock.list-header.component.ts +18 -0
  504. package/testing-base/src/lib/components/mock.list-item.component.ts +33 -0
  505. package/testing-base/src/lib/components/mock.list-section-header.component.ts +20 -0
  506. package/testing-base/src/lib/components/mock.list.component.ts +39 -0
  507. package/testing-base/src/lib/components/mock.loading-overlay.component.ts +21 -0
  508. package/testing-base/src/lib/components/mock.modal-footer.component.ts +21 -0
  509. package/testing-base/src/lib/components/mock.page-footer.component.ts +20 -0
  510. package/testing-base/src/lib/components/mock.page.component.ts +152 -0
  511. package/testing-base/src/lib/components/mock.popover.component.ts +22 -0
  512. package/testing-base/src/lib/components/mock.progress-circle.component.ts +22 -0
  513. package/testing-base/src/lib/components/mock.radio-group.component.ts +27 -0
  514. package/testing-base/src/lib/components/mock.radio.component.ts +23 -0
  515. package/testing-base/src/lib/components/mock.range.component.ts +35 -0
  516. package/testing-base/src/lib/components/mock.reorder-list.component.ts +25 -0
  517. package/testing-base/src/lib/components/mock.router-outlet.component.ts +20 -0
  518. package/testing-base/src/lib/components/mock.section-header.component.ts +18 -0
  519. package/testing-base/src/lib/components/mock.segmented-control.component.ts +29 -0
  520. package/testing-base/src/lib/components/mock.slide-button.component.ts +23 -0
  521. package/testing-base/src/lib/components/mock.slides.component.ts +29 -0
  522. package/testing-base/src/lib/components/mock.spinner.component.ts +18 -0
  523. package/testing-base/src/lib/components/mock.tab-button.component.ts +21 -0
  524. package/testing-base/src/lib/components/mock.tabs.component.ts +18 -0
  525. package/testing-base/src/lib/components/mock.textarea.component.ts +26 -0
  526. package/testing-base/src/lib/components/mock.toggle-button.component.ts +21 -0
  527. package/testing-base/src/lib/components/mock.toggle.component.ts +22 -0
  528. package/testing-base/src/lib/components/mock.web-component-proxies.component.ts +32 -0
  529. package/testing-base/src/lib/directives/index.ts +3 -0
  530. package/testing-base/src/lib/directives/mock.accordion.directive.ts +15 -0
  531. package/testing-base/src/lib/directives/mock.fit-heading.directive.ts +19 -0
  532. package/testing-base/src/lib/directives/mock.theme-color.directive.ts +19 -0
  533. package/testing-base/src/lib/index.ts +4 -0
  534. package/testing-base/src/lib/kirby-testing-base.module.ts +10 -0
  535. package/testing-base/src/lib/mock-components.ts +133 -0
  536. package/testing-base/src/lib/mock-directives.ts +9 -0
  537. package/testing-base/src/public_api.ts +1 -0
  538. package/testing-base/src/tsconfig.json +9 -0
  539. package/testing-jasmine/ng-package.json +3 -0
  540. package/testing-jasmine/src/lib/kirby-testing.module.ts +14 -0
  541. package/testing-jasmine/src/lib/mock-providers.ts +68 -0
  542. package/testing-jasmine/src/public_api.ts +1 -0
  543. package/testing-jasmine/src/tsconfig.json +10 -0
  544. package/testing-jest/ng-package.json +3 -0
  545. package/testing-jest/src/lib/kirby-testing.module.ts +14 -0
  546. package/testing-jest/src/lib/mock-providers.ts +76 -0
  547. package/testing-jest/src/public_api.ts +1 -0
  548. package/testing-jest/src/tsconfig.json +10 -0
  549. package/tsconfig.json +17 -0
  550. package/tsconfig.lib.json +23 -0
  551. package/tsconfig.spec.json +9 -0
  552. package/tslint.json +10 -0
@@ -0,0 +1,538 @@
1
+ import {
2
+ AfterContentChecked,
3
+ AfterViewInit,
4
+ ChangeDetectorRef,
5
+ Component,
6
+ ContentChild,
7
+ ContentChildren,
8
+ ElementRef,
9
+ EventEmitter,
10
+ forwardRef,
11
+ HostBinding,
12
+ HostListener,
13
+ Input,
14
+ OnDestroy,
15
+ Output,
16
+ QueryList,
17
+ Renderer2,
18
+ RendererStyleFlags2,
19
+ TemplateRef,
20
+ ViewChild,
21
+ ViewChildren,
22
+ } from '@angular/core';
23
+ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
24
+
25
+ import { ButtonComponent } from '../button/button.component';
26
+ import { CardComponent } from '../card/card.component';
27
+ import { ItemComponent } from '../item/item.component';
28
+ import { ListItemTemplateDirective } from '../list/list.directive';
29
+ import { HorizontalDirection, PopoverComponent } from '../popover/popover.component';
30
+
31
+ import { OpenState, VerticalDirection } from './dropdown.types';
32
+ import { KeyboardHandlerService } from './keyboard-handler.service';
33
+
34
+ @Component({
35
+ selector: 'kirby-dropdown',
36
+ templateUrl: './dropdown.component.html',
37
+ styleUrls: ['./dropdown.component.scss'],
38
+ providers: [
39
+ {
40
+ provide: NG_VALUE_ACCESSOR,
41
+ useExisting: forwardRef(() => DropdownComponent),
42
+ multi: true,
43
+ },
44
+ ],
45
+ })
46
+ export class DropdownComponent
47
+ implements AfterContentChecked, AfterViewInit, OnDestroy, ControlValueAccessor
48
+ {
49
+ static readonly OPEN_DELAY_IN_MS = 100;
50
+ private state = OpenState.closed;
51
+ private hasConfiguredSlottedItems = false;
52
+ private horizontalDirection: HorizontalDirection | `${HorizontalDirection}` =
53
+ HorizontalDirection.right;
54
+ private verticalDirection: VerticalDirection | `${VerticalDirection}` = VerticalDirection.down;
55
+
56
+ private _items: string[] | any[] = [];
57
+ get items(): string[] | any[] {
58
+ return this._items;
59
+ }
60
+
61
+ @Input() set items(value: string[] | any[]) {
62
+ this._items = value;
63
+ this._value = this.items[this.selectedIndex] || null;
64
+ }
65
+
66
+ private _selectedIndex: number = -1;
67
+ get selectedIndex(): number {
68
+ return this._selectedIndex;
69
+ }
70
+
71
+ @Input() set selectedIndex(value: number) {
72
+ if (this._selectedIndex != value) {
73
+ this._selectedIndex = value;
74
+ this._value = this.items[this.selectedIndex] || null;
75
+ }
76
+ }
77
+
78
+ @Input()
79
+ itemTextProperty = 'text';
80
+
81
+ @Input()
82
+ placeholder = 'Please select:';
83
+
84
+ @Input() set popout(direction: HorizontalDirection | `${HorizontalDirection}`) {
85
+ this.horizontalDirection = direction || HorizontalDirection.right;
86
+ }
87
+
88
+ get popout() {
89
+ return this.horizontalDirection;
90
+ }
91
+
92
+ @Input()
93
+ attentionLevel: '1' | '2' | '3' | '4' = '3';
94
+ readonly attentionLevelOpen = '2';
95
+
96
+ @Input()
97
+ expand?: 'block';
98
+
99
+ @Input()
100
+ disabled = false;
101
+
102
+ @HostBinding('attr.disabled')
103
+ get _isDisabled() {
104
+ return this.disabled ? 'disabled' : null;
105
+ }
106
+
107
+ @HostBinding('class.error')
108
+ @Input()
109
+ hasError: boolean;
110
+
111
+ @Input()
112
+ size: 'sm' | 'md' = 'md';
113
+
114
+ @Input()
115
+ tabindex = 0;
116
+
117
+ @HostBinding('class.with-popover')
118
+ @Input()
119
+ usePopover = false;
120
+
121
+ @HostBinding('attr.tabindex')
122
+ get _tabindex() {
123
+ return this.disabled ? -1 : this.tabindex;
124
+ }
125
+
126
+ // Prevent Ionic blur on scroll
127
+ @HostBinding('attr.no-blur')
128
+ get _noBlurOnScroll() {
129
+ return true;
130
+ }
131
+
132
+ /**
133
+ * Emitted when an item is selected (tap on mobile, click/keypress on web)
134
+ */
135
+ @Output() change: EventEmitter<string | any> = new EventEmitter<string | any>();
136
+
137
+ private _value: string | any = null;
138
+ get value(): string | any {
139
+ return this._value;
140
+ }
141
+
142
+ get selectedText(): string {
143
+ return this.getTextFromItem(this.value);
144
+ }
145
+
146
+ @HostBinding('class.expand')
147
+ get _isBlockLevel() {
148
+ return this.expand === 'block';
149
+ }
150
+
151
+ @HostBinding('attr.role')
152
+ _role = 'listbox';
153
+
154
+ @HostBinding('class.is-opening')
155
+ get _isOpening(): boolean {
156
+ return this.state === OpenState.opening;
157
+ }
158
+
159
+ @HostBinding('class.is-open')
160
+ get isOpen(): boolean {
161
+ return this.state === OpenState.open;
162
+ }
163
+
164
+ @HostBinding('class.popout-left')
165
+ get _popoutLeft() {
166
+ return this.horizontalDirection === HorizontalDirection.left;
167
+ }
168
+
169
+ @HostBinding('class.popout-up')
170
+ get _popoutUp() {
171
+ return this.verticalDirection === VerticalDirection.up;
172
+ }
173
+
174
+ @ContentChild(ListItemTemplateDirective, { static: true, read: TemplateRef })
175
+ itemTemplate: TemplateRef<any>;
176
+ @ContentChildren(ListItemTemplateDirective, { read: ElementRef })
177
+ slottedItems: QueryList<ElementRef<HTMLElement>>;
178
+ @ViewChild(CardComponent, { read: ElementRef })
179
+ cardElement: ElementRef<HTMLElement>;
180
+ @ViewChild(PopoverComponent)
181
+ popover?: PopoverComponent;
182
+ @ViewChild(ButtonComponent, { static: true, read: ElementRef })
183
+ buttonElement: ElementRef<HTMLElement>;
184
+ @ViewChildren(ItemComponent, { read: ElementRef })
185
+ kirbyItemsDefault: QueryList<ElementRef<HTMLElement>>;
186
+ @ContentChildren(ItemComponent, { read: ElementRef })
187
+ kirbyItemsSlotted: QueryList<ElementRef<HTMLElement>>;
188
+
189
+ private itemClickUnlisten: (() => void)[] = [];
190
+ private intersectionObserverRef: IntersectionObserver;
191
+ private showDropdownTimeoutId: ReturnType<typeof setTimeout>;
192
+
193
+ constructor(
194
+ private renderer: Renderer2,
195
+ private elementRef: ElementRef<HTMLElement>,
196
+ private changeDetectorRef: ChangeDetectorRef,
197
+ private keyboardHandlerService: KeyboardHandlerService
198
+ ) {}
199
+
200
+ onToggle(event: MouseEvent) {
201
+ event.stopPropagation();
202
+ if (!this.isOpen) {
203
+ this.elementRef.nativeElement.focus();
204
+ }
205
+ this.toggle();
206
+ }
207
+
208
+ toggle() {
209
+ if (this.disabled) {
210
+ return;
211
+ }
212
+ this.isOpen ? this.close() : this.open();
213
+ }
214
+
215
+ onButtonMouseEvent(event: Event) {
216
+ // Prevent button focus;
217
+ event.preventDefault();
218
+ }
219
+
220
+ ngAfterContentChecked() {
221
+ if (!this.hasConfiguredSlottedItems && this.kirbyItemsSlotted.length) {
222
+ this.kirbyItemsSlotted.forEach((kirbyItem, index) => {
223
+ this.renderer.setAttribute(kirbyItem.nativeElement, 'role', 'option');
224
+ const unlisten = this.renderer.listen(kirbyItem.nativeElement, 'click', () => {
225
+ this.onItemSelect(index);
226
+ });
227
+ this.itemClickUnlisten.push(unlisten);
228
+ });
229
+ this.hasConfiguredSlottedItems = true;
230
+ }
231
+ }
232
+
233
+ /* Utility that makes it easier to set styles on card element
234
+ when using popover*/
235
+ private setPopoverCardStyle(style: string, value: string) {
236
+ if (!this.usePopover) return;
237
+
238
+ this.renderer.setStyle(
239
+ this.cardElement.nativeElement,
240
+ style,
241
+ value,
242
+ RendererStyleFlags2.DashCase
243
+ );
244
+ }
245
+
246
+ ngAfterViewInit() {
247
+ if (this.usePopover && this.expand === 'block') {
248
+ const { width } = this.elementRef.nativeElement.getBoundingClientRect();
249
+ this.setPopoverCardStyle('--kirby-card-width', `${width}px`);
250
+ this.setPopoverCardStyle('max-width', 'initial');
251
+ this.setPopoverCardStyle('min-width', 'initial');
252
+ }
253
+ this.initializeAlignment();
254
+ }
255
+
256
+ private initializeAlignment() {
257
+ if (this.usePopover) return;
258
+ if (!this.intersectionObserverRef) {
259
+ const options = {
260
+ rootMargin: '0px',
261
+ };
262
+ const callback: IntersectionObserverCallback = (entries) => {
263
+ // Only apply alignment when opening:
264
+ if (this.state !== OpenState.opening) {
265
+ return;
266
+ }
267
+
268
+ // Cancel any pending timer to show dropdown:
269
+ clearTimeout(this.showDropdownTimeoutId);
270
+ const entry = entries[0];
271
+ const isVisible = entry.boundingClientRect.width > 0;
272
+ if (isVisible && entry.intersectionRatio < 1) {
273
+ this.setHorizontalDirection(entry);
274
+ this.setVerticalDirection(entry);
275
+ }
276
+ this.showDropdown();
277
+ this.changeDetectorRef.detectChanges();
278
+ };
279
+ this.intersectionObserverRef = new IntersectionObserver(callback, options);
280
+ this.intersectionObserverRef.observe(this.cardElement.nativeElement);
281
+ }
282
+ }
283
+
284
+ private setHorizontalDirection(entry: IntersectionObserverEntry) {
285
+ // If popout direction is set to right, and the entry is cut off to the right by ${entry.boundingClientRect.right - entry.intersectionRect.right}px
286
+ // it is set to popout left instead, and vice versa for popout direction left
287
+ if (this.horizontalDirection === HorizontalDirection.right) {
288
+ if (entry.boundingClientRect.right > entry.rootBounds.right) {
289
+ this.horizontalDirection = HorizontalDirection.left;
290
+ }
291
+ } else {
292
+ if (entry.boundingClientRect.left < entry.rootBounds.left) {
293
+ this.horizontalDirection = HorizontalDirection.right;
294
+ }
295
+ }
296
+ }
297
+
298
+ private setVerticalDirection(entry: IntersectionObserverEntry) {
299
+ if (entry.boundingClientRect.top < 0) {
300
+ // entry is cut off at the top by ${entry.boundingClientRect.top}px
301
+ // open downwards:
302
+ this.verticalDirection = VerticalDirection.down;
303
+ }
304
+ if (entry.boundingClientRect.bottom > entry.rootBounds.bottom) {
305
+ // entry is cut off at the bottom by ${entry.boundingClientRect.bottom - entry.intersectionRect.bottom}px
306
+ const containerOffsetTop = this.elementRef.nativeElement.getBoundingClientRect().top;
307
+ const SPACING = 5; //TODO: Get from SCSS
308
+ // Check if the card can fit on top of button:
309
+ if (containerOffsetTop > entry.target.clientHeight + SPACING) {
310
+ // open upwards:
311
+ this.verticalDirection = VerticalDirection.up;
312
+ }
313
+ }
314
+ }
315
+
316
+ open() {
317
+ if (this.disabled) {
318
+ return;
319
+ }
320
+ if (!this.isOpen) {
321
+ this.state = OpenState.opening;
322
+ // ensures that the dropdown is opened in case the IntersectionObserverCallback isn't invoked
323
+ this.showDropdownTimeoutId = setTimeout(
324
+ () => this.showDropdown(),
325
+ DropdownComponent.OPEN_DELAY_IN_MS
326
+ );
327
+ }
328
+ }
329
+
330
+ private showDropdown() {
331
+ if (this.state === OpenState.opening) {
332
+ this.state = OpenState.open;
333
+ this.popover?.show();
334
+ this.scrollItemIntoView(this.selectedIndex);
335
+ this.changeDetectorRef.markForCheck();
336
+ }
337
+ }
338
+
339
+ close() {
340
+ if (this.disabled) {
341
+ return;
342
+ }
343
+ if (this.isOpen) {
344
+ this.state = OpenState.closed;
345
+ // Reset vertical direction to default
346
+ this.verticalDirection = VerticalDirection.down;
347
+ this.popover?.hide();
348
+ }
349
+ }
350
+
351
+ onItemSelect(index: number) {
352
+ this.selectItem(index);
353
+ this.close();
354
+ }
355
+
356
+ private _onChange: (value: any) => void = () => {};
357
+ private _onTouched = () => {};
358
+
359
+ /**
360
+ * Sets the select's value. Part of the ControlValueAccessor interface
361
+ * required to integrate with Angular's core forms API.
362
+ *
363
+ * @param value New value to be written to the model.
364
+ */
365
+ writeValue(value: any): void {
366
+ this._selectItemByValue(value);
367
+ }
368
+
369
+ /**
370
+ * Saves a callback function to be invoked when the select's value
371
+ * changes from user input. Part of the ControlValueAccessor interface
372
+ * required to integrate with Angular's core forms API.
373
+ *
374
+ * @param fn Callback to be triggered when the value changes.
375
+ */
376
+ registerOnChange(fn: any): void {
377
+ this._onChange = fn;
378
+ }
379
+
380
+ /**
381
+ * Saves a callback function to be invoked when the select is blurred
382
+ * by the user. Part of the ControlValueAccessor interface required
383
+ * to integrate with Angular's core forms API.
384
+ *
385
+ * @param fn Callback to be triggered when the component has been touched.
386
+ */
387
+ registerOnTouched(fn: any): void {
388
+ this._onTouched = fn;
389
+ }
390
+
391
+ /**
392
+ * Disables the select. Part of the ControlValueAccessor interface required
393
+ * to integrate with Angular's core forms API.
394
+ *
395
+ * @param isDisabled Sets whether the component is disabled.
396
+ */
397
+ setDisabledState?(isDisabled: boolean): void {
398
+ this.disabled = isDisabled;
399
+ }
400
+
401
+ private selectItem(index: number) {
402
+ if (index != this.selectedIndex) {
403
+ this.selectedIndex = index;
404
+ this.change.emit(this.value);
405
+ this._onChange(this.value);
406
+ this.scrollItemIntoView(index);
407
+ }
408
+ }
409
+
410
+ private _selectItemByValue(value: string | any) {
411
+ this.selectedIndex = this.items.indexOf(value);
412
+ }
413
+
414
+ getTextFromItem(item: string | any) {
415
+ if (!item) {
416
+ return null;
417
+ }
418
+ return typeof item === 'string' ? item : item[this.itemTextProperty];
419
+ }
420
+
421
+ scrollItemIntoView(index: number) {
422
+ const kirbyItems =
423
+ this.kirbyItemsSlotted && this.kirbyItemsSlotted.length
424
+ ? this.kirbyItemsSlotted
425
+ : this.kirbyItemsDefault;
426
+ if (kirbyItems && kirbyItems.length) {
427
+ const selectedKirbyItem = kirbyItems.toArray()[index];
428
+ if (selectedKirbyItem && selectedKirbyItem.nativeElement) {
429
+ const itemElement = selectedKirbyItem.nativeElement;
430
+ const scrollContainer = this.cardElement.nativeElement;
431
+ const itemTop = itemElement.offsetTop;
432
+ const itemBottom = itemElement.offsetTop + itemElement.offsetHeight;
433
+ const containerVisibleTop = scrollContainer.scrollTop;
434
+ const containerVisibleBottom = scrollContainer.clientHeight + scrollContainer.scrollTop;
435
+ if (itemTop < containerVisibleTop) {
436
+ scrollContainer.scrollTop = itemTop;
437
+ } else if (itemBottom > containerVisibleBottom) {
438
+ scrollContainer.scrollTop = itemBottom - scrollContainer.clientHeight;
439
+ }
440
+ }
441
+ }
442
+ }
443
+
444
+ @HostListener('keydown.tab', ['$event'])
445
+ _onTab(event: KeyboardEvent) {
446
+ if (this.isOpen) {
447
+ event.preventDefault();
448
+ this.close();
449
+ }
450
+ }
451
+
452
+ @HostListener('mousedown', ['$event'])
453
+ _onMouseDown(event: MouseEvent) {
454
+ if (this.disabled) {
455
+ event.preventDefault();
456
+ event.stopImmediatePropagation();
457
+ }
458
+ }
459
+
460
+ @HostListener('focus')
461
+ _onFocus() {
462
+ if (this.disabled) {
463
+ this.elementRef.nativeElement.blur();
464
+ }
465
+ }
466
+
467
+ _onPopoverWillHide() {
468
+ this.state = OpenState.closed;
469
+ this.elementRef.nativeElement.focus();
470
+ }
471
+
472
+ @HostListener('keydown.enter')
473
+ @HostListener('keydown.escape')
474
+ @HostListener('blur', ['$event'])
475
+ _onBlur(event?: FocusEvent) {
476
+ if (this.disabled) return;
477
+ if (this.isOpen) {
478
+ if (!this.cardElement.nativeElement.contains(event?.relatedTarget as HTMLElement)) {
479
+ this.close();
480
+ }
481
+ }
482
+ this._onTouched();
483
+ }
484
+
485
+ @HostListener('keydown.space', ['$event'])
486
+ _onSpace(event: KeyboardEvent) {
487
+ event.preventDefault();
488
+ event.stopPropagation();
489
+ if (!this.isOpen) {
490
+ this.open();
491
+ }
492
+ }
493
+
494
+ @HostListener('keydown.enter', ['$event'])
495
+ _onEnter(event: KeyboardEvent) {
496
+ event.preventDefault();
497
+ event.stopPropagation();
498
+ this.toggle();
499
+ }
500
+
501
+ @HostListener('keydown.arrowup', ['$event'])
502
+ @HostListener('keydown.arrowdown', ['$event'])
503
+ @HostListener('keydown.arrowleft', ['$event'])
504
+ @HostListener('keydown.arrowright', ['$event'])
505
+ _onArrowKeys(event: KeyboardEvent) {
506
+ if (this.disabled) return;
507
+ // Mirror default HTML5 select behaviour - prevent left/right arrows when open:
508
+ if (this.isOpen && (event.key === 'ArrowLeft' || event.key === 'ArrowRight')) {
509
+ return;
510
+ }
511
+ const newIndex = this.keyboardHandlerService.handle(event, this.items, this.selectedIndex);
512
+ if (newIndex > -1) {
513
+ this.selectItem(newIndex);
514
+ }
515
+ return false;
516
+ }
517
+
518
+ @HostListener('keydown.home', ['$event'])
519
+ @HostListener('keydown.end', ['$event'])
520
+ _onHomeEndKeys(event: KeyboardEvent) {
521
+ if (this.disabled) return;
522
+ const newIndex = this.keyboardHandlerService.handle(event, this.items, this.selectedIndex);
523
+ if (newIndex > -1) {
524
+ this.selectItem(newIndex);
525
+ }
526
+ return false;
527
+ }
528
+
529
+ ngOnDestroy(): void {
530
+ let unlisten: () => void;
531
+ while ((unlisten = this.itemClickUnlisten.pop()) !== undefined) {
532
+ unlisten();
533
+ }
534
+ if (this.intersectionObserverRef) {
535
+ this.intersectionObserverRef.disconnect();
536
+ }
537
+ }
538
+ }
@@ -0,0 +1,10 @@
1
+ export enum OpenState {
2
+ closed,
3
+ opening,
4
+ open,
5
+ }
6
+
7
+ export enum VerticalDirection {
8
+ up,
9
+ down,
10
+ }
@@ -0,0 +1,38 @@
1
+ import { Injectable } from '@angular/core';
2
+
3
+ @Injectable({
4
+ providedIn: 'root',
5
+ })
6
+ export class KeyboardHandlerService {
7
+ handle(event: KeyboardEvent, items: any[] | string[], selectedIndex: number) {
8
+ let newIndex = -1;
9
+ switch (event.key) {
10
+ case 'ArrowUp':
11
+ case 'ArrowLeft':
12
+ // Select previous item:
13
+ newIndex = selectedIndex - 1;
14
+ break;
15
+ case 'ArrowDown':
16
+ case 'ArrowRight':
17
+ if (selectedIndex === undefined) {
18
+ // None selected, select first item:
19
+ newIndex = 0;
20
+ } else if (selectedIndex < items.length - 1) {
21
+ // Select next item:
22
+ newIndex = selectedIndex + 1;
23
+ }
24
+ break;
25
+ case 'Home':
26
+ // Select first item:
27
+ newIndex = 0;
28
+ break;
29
+ case 'End':
30
+ // Select last item:
31
+ newIndex = items.length - 1;
32
+ break;
33
+ default:
34
+ break;
35
+ }
36
+ return newIndex;
37
+ }
38
+ }
@@ -0,0 +1,10 @@
1
+ <article>
2
+ <div *ngIf="iconName || customIconName" class="icon-outline">
3
+ <kirby-icon [name]="iconName" [customName]="customIconName" size="lg"></kirby-icon>
4
+ </div>
5
+ <h3 *ngIf="title" class="title">{{ title }}</h3>
6
+ <p *ngIf="subtitle" class="subtitle">{{ subtitle }}</p>
7
+ <div class="content">
8
+ <ng-content></ng-content>
9
+ </div>
10
+ </article>
@@ -0,0 +1,110 @@
1
+ import { createHostFactory, SpectatorHost } from '@ngneat/spectator';
2
+ import { MockComponent } from 'ng-mocks';
3
+
4
+ import { ButtonComponent } from '../button/button.component';
5
+ import { IconComponent } from '../icon/icon.component';
6
+
7
+ import { EmptyStateComponent } from './empty-state.component';
8
+
9
+ describe('EmptyStateComponent with slotted buttons', () => {
10
+ let spectator: SpectatorHost<EmptyStateComponent>;
11
+ let buttons: ButtonComponent[];
12
+
13
+ const createHost = createHostFactory({
14
+ component: EmptyStateComponent,
15
+ declarations: [MockComponent(IconComponent), ButtonComponent],
16
+ });
17
+
18
+ beforeEach(() => {
19
+ spectator = createHost(`
20
+ <kirby-empty-state
21
+ iconName="help"
22
+ title="No items"
23
+ subtitle="You don't have any items. Call support to add some items to your account."
24
+ >
25
+ <button kirby-button>Call support</button>
26
+ <button kirby-button>Mail support</button>
27
+ <button kirby-button>Get directions</button>
28
+ <button kirby-button>Cancel</button>
29
+ </kirby-empty-state>
30
+ `);
31
+
32
+ buttons = spectator.queryAll(ButtonComponent);
33
+ });
34
+
35
+ it('should not change the attention level of the first button', () => {
36
+ expect(buttons[0].isAttentionLevel1).toBeTrue();
37
+ });
38
+
39
+ it('should set the attention level of all buttons to 3 except the first one', () => {
40
+ const allButtonsButTheFirst = buttons.splice(1, buttons.length);
41
+ expect(allButtonsButTheFirst.every((button) => button.isAttentionLevel3)).toBeTrue();
42
+ });
43
+ });
44
+
45
+ describe('EmptyStateComponent with slotted buttons configured with attention levels', () => {
46
+ let spectator: SpectatorHost<EmptyStateComponent>;
47
+ let buttons: ButtonComponent[];
48
+
49
+ const createHost = createHostFactory({
50
+ component: EmptyStateComponent,
51
+ declarations: [MockComponent(IconComponent), ButtonComponent],
52
+ });
53
+
54
+ beforeEach(() => {
55
+ spectator = createHost(`
56
+ <kirby-empty-state
57
+ iconName="help"
58
+ title="No items"
59
+ subtitle="You don't have any items. Call support to add some items to your account."
60
+ >
61
+ <button kirby-button attentionLevel="4">Call support</button>
62
+ <button kirby-button attentionLevel="3">Mail support</button>
63
+ <button kirby-button attentionLevel="2">Get directions</button>
64
+ <button kirby-button attentionLevel="1">Cancel</button>
65
+ </kirby-empty-state>
66
+ `);
67
+
68
+ buttons = spectator.queryAll(ButtonComponent);
69
+ });
70
+
71
+ it('should set the attention level of all buttons to 3', () => {
72
+ expect(buttons.every((button) => button.isAttentionLevel3)).toBeTrue();
73
+ });
74
+ });
75
+
76
+ describe('EmptyStateComponent with slotted buttons configured with attention levels where the first has attention level 1', () => {
77
+ let spectator: SpectatorHost<EmptyStateComponent>;
78
+ let buttons: ButtonComponent[];
79
+
80
+ const createHost = createHostFactory({
81
+ component: EmptyStateComponent,
82
+ declarations: [MockComponent(IconComponent), ButtonComponent],
83
+ });
84
+
85
+ beforeEach(() => {
86
+ spectator = createHost(`
87
+ <kirby-empty-state
88
+ iconName="help"
89
+ title="No items"
90
+ subtitle="You don't have any items. Call support to add some items to your account."
91
+ >
92
+ <button kirby-button attentionLevel="1">Call support</button>
93
+ <button kirby-button attentionLevel="2">Mail support</button>
94
+ <button kirby-button attentionLevel="3">Get directions</button>
95
+ <button kirby-button attentionLevel="4">Cancel</button>
96
+ </kirby-empty-state>
97
+ `);
98
+
99
+ buttons = spectator.queryAll(ButtonComponent);
100
+ });
101
+
102
+ it('should not change the attention level of the first button', () => {
103
+ expect(buttons[0].isAttentionLevel1).toBeTrue();
104
+ });
105
+
106
+ it('should set the attention level of all buttons to 3 except the first one', () => {
107
+ const allButtonsButTheFirst = buttons.splice(1, buttons.length);
108
+ expect(allButtonsButTheFirst.every((button) => button.isAttentionLevel3)).toBeTrue();
109
+ });
110
+ });