@lion/ui 0.1.3 → 0.1.5

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 (107) hide show
  1. package/README.md +222 -0
  2. package/components/combobox/src/LionCombobox.js +107 -68
  3. package/components/combobox/src/utils/makeMatchingTextBold.js +68 -0
  4. package/components/combobox/test/lion-combobox.test.js +210 -4
  5. package/components/combobox/translations/bg.js +3 -0
  6. package/components/combobox/translations/cs.js +3 -0
  7. package/components/combobox/translations/de.js +3 -0
  8. package/components/combobox/translations/en.js +3 -0
  9. package/components/combobox/translations/es.js +3 -0
  10. package/components/combobox/translations/fr.js +3 -0
  11. package/components/combobox/translations/hu.js +3 -0
  12. package/components/combobox/translations/it.js +3 -0
  13. package/components/combobox/translations/nl.js +3 -0
  14. package/components/combobox/translations/pl.js +3 -0
  15. package/components/combobox/translations/ro.js +3 -0
  16. package/components/combobox/translations/ru.js +3 -0
  17. package/components/combobox/translations/sk.js +3 -0
  18. package/components/combobox/translations/uk.js +3 -0
  19. package/components/combobox/translations/zh.js +3 -0
  20. package/custom-elements.json +668 -0
  21. package/dist-types/components/combobox/src/LionCombobox.d.ts +14 -1
  22. package/dist-types/components/combobox/src/LionCombobox.d.ts.map +1 -1
  23. package/dist-types/components/combobox/src/utils/makeMatchingTextBold.d.ts +10 -0
  24. package/dist-types/components/combobox/src/utils/makeMatchingTextBold.d.ts.map +1 -0
  25. package/dist-types/components/combobox/test/lion-combobox.test.d.ts +1 -0
  26. package/dist-types/components/combobox/test/lion-combobox.test.d.ts.map +1 -1
  27. package/dist-types/components/combobox/translations/bg.d.ts +5 -0
  28. package/dist-types/components/combobox/translations/bg.d.ts.map +1 -0
  29. package/dist-types/components/combobox/translations/cs.d.ts +5 -0
  30. package/dist-types/components/combobox/translations/cs.d.ts.map +1 -0
  31. package/dist-types/components/combobox/translations/de.d.ts +5 -0
  32. package/dist-types/components/combobox/translations/de.d.ts.map +1 -0
  33. package/dist-types/components/combobox/translations/en.d.ts +5 -0
  34. package/dist-types/components/combobox/translations/en.d.ts.map +1 -0
  35. package/dist-types/components/combobox/translations/es.d.ts +5 -0
  36. package/dist-types/components/combobox/translations/es.d.ts.map +1 -0
  37. package/dist-types/components/combobox/translations/fr.d.ts +5 -0
  38. package/dist-types/components/combobox/translations/fr.d.ts.map +1 -0
  39. package/dist-types/components/combobox/translations/hu.d.ts +5 -0
  40. package/dist-types/components/combobox/translations/hu.d.ts.map +1 -0
  41. package/dist-types/components/combobox/translations/it.d.ts +5 -0
  42. package/dist-types/components/combobox/translations/it.d.ts.map +1 -0
  43. package/dist-types/components/combobox/translations/nl.d.ts +5 -0
  44. package/dist-types/components/combobox/translations/nl.d.ts.map +1 -0
  45. package/dist-types/components/combobox/translations/pl.d.ts +5 -0
  46. package/dist-types/components/combobox/translations/pl.d.ts.map +1 -0
  47. package/dist-types/components/combobox/translations/ro.d.ts +5 -0
  48. package/dist-types/components/combobox/translations/ro.d.ts.map +1 -0
  49. package/dist-types/components/combobox/translations/ru.d.ts +5 -0
  50. package/dist-types/components/combobox/translations/ru.d.ts.map +1 -0
  51. package/dist-types/components/combobox/translations/sk.d.ts +5 -0
  52. package/dist-types/components/combobox/translations/sk.d.ts.map +1 -0
  53. package/dist-types/components/combobox/translations/uk.d.ts +5 -0
  54. package/dist-types/components/combobox/translations/uk.d.ts.map +1 -0
  55. package/dist-types/components/combobox/translations/zh.d.ts +5 -0
  56. package/dist-types/components/combobox/translations/zh.d.ts.map +1 -0
  57. package/dist-types/exports/combobox.d.ts +1 -0
  58. package/dist-types/tsconfig.tsbuildinfo +1 -1
  59. package/docs/components/checkbox-group/overview.md +2 -2
  60. package/docs/components/collapsible/overview.md +1 -1
  61. package/docs/components/combobox/overview.md +1 -1
  62. package/docs/components/combobox/use-cases.md +40 -16
  63. package/docs/components/dialog/overview.md +1 -1
  64. package/docs/components/fieldset/overview.md +5 -5
  65. package/docs/components/form/overview.md +3 -3
  66. package/docs/components/icon/use-cases.md +1 -1
  67. package/docs/components/input/overview.md +1 -1
  68. package/docs/components/input-amount/overview.md +3 -3
  69. package/docs/components/input-date/overview.md +3 -3
  70. package/docs/components/input-datepicker/overview.md +5 -5
  71. package/docs/components/input-email/overview.md +2 -2
  72. package/docs/components/input-iban/overview.md +2 -2
  73. package/docs/components/input-range/overview.md +2 -2
  74. package/docs/components/input-stepper/overview.md +1 -1
  75. package/docs/components/input-tel/overview.md +1 -1
  76. package/docs/components/input-tel/use-cases.md +6 -6
  77. package/docs/components/input-tel-dropdown/overview.md +1 -1
  78. package/docs/components/listbox/src/listboxData.js +66 -0
  79. package/docs/components/radio-group/overview.md +3 -3
  80. package/docs/components/select-rich/use-cases.md +1 -1
  81. package/docs/components/tabs/examples.md +1 -1
  82. package/docs/fundamentals/index.md +4 -4
  83. package/docs/fundamentals/node-tools/providence-analytics/LocalConfiguration.md +1 -1
  84. package/docs/fundamentals/node-tools/providence-analytics/QueryResult.md +1 -1
  85. package/docs/fundamentals/node-tools/providence-analytics/analyzer.md +1 -1
  86. package/docs/fundamentals/node-tools/providence-analytics/dashboard.md +1 -1
  87. package/docs/fundamentals/node-tools/providence-analytics/overview.md +3 -3
  88. package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
  89. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
  90. package/docs/fundamentals/systems/core/overview.md +1 -1
  91. package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
  92. package/docs/fundamentals/systems/form/model-value.md +1 -1
  93. package/docs/fundamentals/systems/form/overview.md +28 -28
  94. package/docs/fundamentals/systems/form/validate.md +1 -1
  95. package/docs/fundamentals/systems/localize/overview.md +4 -4
  96. package/docs/fundamentals/systems/overlays/configuration.md +2 -2
  97. package/docs/fundamentals/systems/overlays/overview.md +5 -5
  98. package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
  99. package/docs/fundamentals/tools/helpers/overview.md +1 -1
  100. package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
  101. package/docs/guides/how-to/create-a-custom-field.md +5 -5
  102. package/docs/guides/how-to/extend-a-native-input.md +2 -2
  103. package/docs/guides/index.md +8 -8
  104. package/docs/guides/principles/index.md +5 -5
  105. package/docs/guides/principles/styling.md +1 -1
  106. package/exports/combobox.js +4 -0
  107. package/package.json +9 -1
package/README.md ADDED
@@ -0,0 +1,222 @@
1
+ <p align="center">
2
+ <img
3
+ width="20%"
4
+ src="./docs/_assets/logo.svg"
5
+ alt="Lion"
6
+ />
7
+ <h1 style="text-align: center;">Lion</h1>
8
+ </p>
9
+
10
+ <p align="center">
11
+ <a href="https://github.com/modernweb-dev/rocket/actions"
12
+ ><img
13
+ src="https://img.shields.io/github/workflow/status/modernweb-dev/rocket/Release/main?label=workflow&style=flat-square"
14
+ alt="GitHub Actions workflow status"
15
+ /></a>
16
+ <a href="https://github.com/modernweb-dev/rocket/actions"
17
+ ><img
18
+ src="https://img.shields.io/github/workflow/status/modernweb-dev/rocket/Release/main?label=workflow&style=flat-square"
19
+ alt="GitHub Actions workflow status"
20
+ /></a>
21
+ <a href="https://www.tickgit.com/browse?repo=github.com/ing-bank/lion"
22
+ ><img
23
+ src="https://badgen.net/https/api.tickgit.com/badgen/github.comgithub.com/ing-bank/lion"
24
+ alt="Todos"
25
+ /></a>
26
+ </p>
27
+
28
+ <p align="center">
29
+ <a href="https://lion-web.netlify.app">Website</a>
30
+ ·
31
+ <a href="https://lion-web.netlify.app/guides/">Guides</a>
32
+ ·
33
+ <a href="https://lion-web.netlify.app/components/">Components</a>
34
+ ·
35
+ <a href="https://lion-web.netlify.app/docs/">Documentation</a>
36
+ ·
37
+ <a href="https://lion-web.netlify.app/blog/">Blog</a>
38
+ </p>
39
+
40
+ **Lion is a set of highly performant, accessible and flexible Web Components.!**
41
+
42
+ They provide an unopinionated, white-label layer that can be extended to your own layer of components.
43
+
44
+ - **High Performance:** Focused on great performance in all relevant browsers with a minimal number of dependencies.
45
+ - **Accessibility:** Aimed at compliance with the WCAG 2.1 AA standard to create components that are accessible for everybody.
46
+ - **Flexibility:** Provides solutions through Web Components and JavaScript classes which can be used, adopted and extended to fit all needs.
47
+ - **Modern Code:** Lion is distributes as pure es modules.
48
+ - **Exposes functions/classes and Web Components:** Ships a functionality in it's most appropriate form.
49
+
50
+ > Note: Our demos may look a little bland but that is on purpose. They only come with functional stylings.
51
+ > This makes sense as the main use case is to extend those components and if you do you do not want to override existing stylings.
52
+
53
+ <p align="center">
54
+ <a href="https://lion-web.netlify.app/guides/"><strong>Explore the Lion Guides&nbsp;&nbsp;▶</strong></a>
55
+ </p>
56
+
57
+ ## How to install
58
+
59
+ ```bash
60
+ npm i @lion/<package-name>
61
+ ```
62
+
63
+ ## How to use
64
+
65
+ ### Extend a Web Component
66
+
67
+ **This is the main use case for lion**. To import component classes, and extend them for your own design system's components.
68
+
69
+ ```js
70
+ import { css } from 'lit';
71
+ import { LionInput } from '@lion/input';
72
+
73
+ class MyInput extends LionInput {
74
+ static get styles() {
75
+ return [
76
+ super.styles,
77
+ css`
78
+ /* your styles here */
79
+ `,
80
+ ];
81
+ }
82
+ }
83
+ customElements.define('my-input', MyInput);
84
+ ```
85
+
86
+ ### Use a JavaScript system
87
+
88
+ There's a couple of "systems" in lion which have a JavaScript API. Examples are `localize`, `overlays`, `ajax`, etc.
89
+
90
+ ```html
91
+ <script type="module">
92
+ import { ajax } from '@lion/ajax';
93
+
94
+ ajax
95
+ .fetch('data.json')
96
+ .then(response => response.json())
97
+ .then(data => {
98
+ // do something with the data
99
+ });
100
+ </script>
101
+ ```
102
+
103
+ ### Use a Web Component
104
+
105
+ You can also use the lion elements directly, although this is likely not a common use case.
106
+
107
+ ```html
108
+ <script type="module">
109
+ import '@lion/input/define';
110
+ </script>
111
+
112
+ <lion-input name="firstName"></lion-input>
113
+ ```
114
+
115
+ ## Issues
116
+
117
+ If you encounter an issue with any of the packages we are offering please open a [new bug issue](https://github.com/ing-bank/lion/issues/new?assignees=&labels=&template=bug_report.md&title=). Be sure to include a description of the expected and the current behavior - additional adding a [reproduction](https://webcomponents.dev/edit/kpZmz1CJN580OaXsk56f?pm=1) always helps.
118
+
119
+ ## Feature requests
120
+
121
+ When you have an idea on how we could improve, please check our [discussions](https://github.com/ing-bank/lion/discussions) to see if there are similar ideas or feature requests. If there are none, please [start](https://github.com/ing-bank/lion/discussions/new) your feature request as a new discussion topic. Add the title `[Feature Request] My awesome feature` and a description of what you expect from the improvement and what the use case is.
122
+
123
+ ## Content
124
+
125
+ Lion web components is logically organized in groups of systems.
126
+
127
+ The accessibility column indicates whether the functionality is accessible in its core. Aspects like styling and content determine actual accessibility in usage.
128
+
129
+ | Package | Version | Description | Accessibility |
130
+ | ------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | -------------------------- |
131
+ | **-- [Form System](https://lion-web.netlify.app/fundamentals/systems/form/overview/) --** | | A system that lets you make complex forms with ease, including: validation, translations. | ✔️ |
132
+ | [combobox](https://lion-web.netlify.app/components/combobox/overview/) | [![combobox](https://img.shields.io/npm/v/@lion/combobox.svg)](https://www.npmjs.com/package/@lion/form) | Text box controlling popup listbox | ✔️ |
133
+ | [form](https://lion-web.netlify.app/components/form/overview) | [![form](https://img.shields.io/npm/v/@lion/form.svg)](https://www.npmjs.com/package/@lion/form) | Wrapper for multiple form elements | ✔️ |
134
+ | [form-core](https://lion-web.netlify.app/fundamentals/systems/form/overview/) | [![form-core](https://img.shields.io/npm/v/@lion/form-core.svg)](https://www.npmjs.com/package/@lion/form-core) | Core functionality for all form controls | ✔️ |
135
+ | [form-integrations](https://lion-web.netlify.app/fundamentals/systems/form/overview/) | [![form-integrations](https://img.shields.io/npm/v/@lion/form-integrations.svg)](https://www.npmjs.com/package/@lion/form-integrations) | Shows form elements in an integrated way | ✔️ |
136
+ | [fieldset](https://lion-web.netlify.app/components/fieldset/overview/) | [![fieldset](https://img.shields.io/npm/v/@lion/fieldset.svg)](https://www.npmjs.com/package/@lion/fieldset) | Group for form inputs | ✔️ |
137
+ | [checkbox-group](https://lion-web.netlify.app/components/checkbox-group/overview/) | [![checkbox-group](https://img.shields.io/npm/v/@lion/checkbox-group.svg)](https://www.npmjs.com/package/@lion/checkbox-group) | Group of checkboxes | ✔️ |
138
+ | [input](https://lion-web.netlify.app/components/input/overview/) | [![input](https://img.shields.io/npm/v/@lion/input.svg)](https://www.npmjs.com/package/@lion/input) | Input element for strings | ✔️ |
139
+ | [input-amount](https://lion-web.netlify.app/components/input-amount/overview/) | [![input-amount](https://img.shields.io/npm/v/@lion/input-amount.svg)](https://www.npmjs.com/package/@lion/input-amount) | Input element for amounts | ✔️ |
140
+ | [input-date](https://lion-web.netlify.app/components/input-date/overview/) | [![input-date](https://img.shields.io/npm/v/@lion/input-date.svg)](https://www.npmjs.com/package/@lion/input-date) | Input element for dates | ✔️ |
141
+ | [input-datepicker](https://lion-web.netlify.app/components/input-datepicker/overview/) | [![input-datepicker](https://img.shields.io/npm/v/@lion/input-datepicker.svg)](https://www.npmjs.com/package/@lion/input-datepicker) | Input element for dates with a datepicker | ✔️ |
142
+ | [input-email](https://lion-web.netlify.app/components/input-email/overview/) | [![input-email](https://img.shields.io/npm/v/@lion/input-email.svg)](https://www.npmjs.com/package/@lion/input-email) | Input element for e-mails | ✔️ |
143
+ | [input-iban](https://lion-web.netlify.app/components/input-iban/overview/) | [![input-iban](https://img.shields.io/npm/v/@lion/input-iban.svg)](https://www.npmjs.com/package/@lion/input-iban) | Input element for IBANs | ✔️ |
144
+ | [input-range](https://lion-web.netlify.app/components/input-range/overview/) | [![input-range](https://img.shields.io/npm/v/@lion/input-range.svg)](https://www.npmjs.com/package/@lion/input-range) | Input element for a range of values | ✔️ |
145
+ | [input-stepper](https://lion-web.netlify.app/components/input-stepper/overview/) | [![input-stepper](https://img.shields.io/npm/v/@lion/input-stepper.svg)](https://www.npmjs.com/package/@lion/input-stepper) | Input stepper element for the predefined range | ✔️ |
146
+ | [listbox](https://lion-web.netlify.app/components/listbox/overview/) | [![listbox](https://img.shields.io/npm/v/@lion/listbox.svg)](https://www.npmjs.com/package/@lion/form) | Interactive list with selectable options | ✔️ |
147
+ | [radio-group](https://lion-web.netlify.app/components/radio-group/overview/) | [![radio-group](https://img.shields.io/npm/v/@lion/radio-group.svg)](https://www.npmjs.com/package/@lion/radio-group) | Group of radios | ✔️ |
148
+ | [select](https://lion-web.netlify.app/components/select/overview/) | [![select](https://img.shields.io/npm/v/@lion/select.svg)](https://www.npmjs.com/package/@lion/select) | Simple native dropdown element | ✔️ |
149
+ | [select-rich](https://lion-web.netlify.app/components/select-rich/overview/) | [![select-rich](https://img.shields.io/npm/v/@lion/select-rich.svg)](https://www.npmjs.com/package/@lion/select-rich) | 'rich' version of the native dropdown element | [#243][i243] |
150
+ | [textarea](https://lion-web.netlify.app/components/textarea/overview/) | [![textarea](https://img.shields.io/npm/v/@lion/textarea.svg)](https://www.npmjs.com/package/@lion/textarea) | Multiline text input | ✔️ |
151
+ | **-- [Button System](https://lion-web.netlify.app/components/buttons-intro--page) --** | | These web components bring common UX patterns while still full integrated with (native) forms. | |
152
+ | [button](https://lion-web.netlify.app/components/button/overview/) | [![button](https://img.shields.io/npm/v/@lion/button.svg)](https://www.npmjs.com/package/@lion/button) | Button | ✔️ |
153
+ | [switch](https://lion-web.netlify.app/components/switch/overview/) | [![switch](https://img.shields.io/npm/v/@lion/switch.svg)](https://www.npmjs.com/package/@lion/switch) | Switch | ✔️ |
154
+ | **-- [Overlay System](https://lion-web.netlify.app/components/overlays-intro--page) --** | | If something needs to overlay content this is your place. | |
155
+ | [overlays](https://lion-web.netlify.app/fundamentals/systems/overlays/overview/) | [![overlays](https://img.shields.io/npm/v/@lion/overlays.svg)](https://www.npmjs.com/package/@lion/overlays) | Overlay System | ✔️ |
156
+ | [dialog](https://lion-web.netlify.app/components/dialog/overview/) | [![dialog](https://img.shields.io/npm/v/@lion/dialog.svg)](https://www.npmjs.com/package/@lion/dialog) | Dialog element | ✔️ |
157
+ | [tooltip](https://lion-web.netlify.app/components/tooltip/overview/) | [![tooltip](https://img.shields.io/npm/v/@lion/tooltip.svg)](https://www.npmjs.com/package/@lion/tooltip) | Tooltip element | [#175][i175] |
158
+ | **-- [Navigation System](https://lion-web.netlify.app/components/navigation-intro--page) --** | | Components which are used to guide users | |
159
+ | [accordion](https://lion-web.netlify.app/components/accordion/overview/) | [![accordion](https://img.shields.io/npm/v/@lion/accordion.svg)](https://www.npmjs.com/package/@lion/accordion) | Accordion | ✔️ |
160
+ | [pagination](https://lion-web.netlify.app/components/pagination/overview/) | [![pagination](https://img.shields.io/npm/v/@lion/pagination.svg)](https://www.npmjs.com/package/@lion/pagination) | Pagination | ✔️ |
161
+ | [steps](https://lion-web.netlify.app/components/steps/overview) | [![steps](https://img.shields.io/npm/v/@lion/steps.svg)](https://www.npmjs.com/package/@lion/steps) | Multi Step System | n/a |
162
+ | [tabs](https://lion-web.netlify.app/components/tabs/overview) | [![tBS](https://img.shields.io/npm/v/@lion/tabs.svg)](https://www.npmjs.com/package/@lion/tabs) | Move between a small number of equally important views | n/a |
163
+ | **-- [localize System](https://lion-web.netlify.app/fundamentals/systems/localize/overview/) --** | | Localize text, numbers, dates and a way to store/fetch these data. | |
164
+ | [localize](https://lion-web.netlify.app/fundamentals/systems/localize/overview/) | [![localize](https://img.shields.io/npm/v/@lion/localize.svg)](https://www.npmjs.com/package/@lion/localize) | Localize and translate your application/components | n/a |
165
+ | **-- [Icon System](https://lion-web.netlify.app/fundamentals/systems/icon/overview/) --** | | Loading and displaying icons | |
166
+ | [icon](https://lion-web.netlify.app/fundamentals/systems/icon/overview/) | [![icon](https://img.shields.io/npm/v/@lion/icon.svg)](https://www.npmjs.com/package/@lion/icon) | Display our svg icons | [#173][i173], [#172][i172] |
167
+ | **-- Others --** | | Features not fitting any other category | |
168
+ | [core](https://lion-web.netlify.app/fundamentals/systems/core/overview/) | [![core](https://img.shields.io/npm/v/@lion/core.svg)](https://www.npmjs.com/package/@lion/core) | Core System (exports LitElement, lit-html) | n/a |
169
+ | [ajax](https://lion-web.netlify.app/fundamentals/tools/ajax/overview/) | [![ajax](https://img.shields.io/npm/v/@lion/ajax.svg)](https://www.npmjs.com/package/@lion/ajax) | Fetching data via ajax request | n/a |
170
+ | [calendar](https://lion-web.netlify.app/components/calendar/overview/) | [![calendar](https://img.shields.io/npm/v/@lion/calendar.svg)](https://www.npmjs.com/package/@lion/calendar) | Standalone calendar | [#195][i195], [#194][i194] |
171
+ | [collapsible](https://lion-web.netlify.app/components/collapsible/overview/) | [![collapsible](https://img.shields.io/npm/v/@lion/collapsible.svg)](https://www.npmjs.com/package/@lion/collapsible) | Combination of a button and a chunk of extra content | ✔️ |
172
+ | **-- [Helpers](https://lion-web.netlify.app/fundamentals/tools/helpers/overview/) --** | [![helpers](https://img.shields.io/npm/v/@lion/helpers.svg)](https://www.npmjs.com/package/@lion/helpers) | Helpers to make your and your life easier | |
173
+ | [sb-action-logger](https://lion-web.netlify.app/fundamentals/tools/helpers/action-logger/) | | Storybook action logger |
174
+
175
+ ## Technologies
176
+
177
+ Lion Web Components aims to be future-proof and use well-supported proven technology. The stack we have chosen should reflect this.
178
+
179
+ - [lit](https://lit.dev/)
180
+ - [npm](http://npmjs.com)
181
+ - [Open Web Components](https://open-wc.org)
182
+ - [Modern Web](https://modern-web.dev)
183
+ - [Mocha](https://mochajs.org)
184
+ - [Chai](https://www.chaijs.com)
185
+ - [ESLint](https://eslint.org)
186
+ - [prettier](https://prettier.io)
187
+ - [ES modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)
188
+ - Lots and lots of tests
189
+
190
+ ## Rationale
191
+
192
+ We know from experience that making high quality, accessible UI components is hard and time consuming:
193
+ it takes many iterations, a lot of development time and a lot of testing to get a generic component that works in every
194
+ context, supports many edge cases and is accessible in all relevant screen readers.
195
+
196
+ Lion aims to do the heavy lifting for you.
197
+ This means you only have to apply your own Design System: by delivering styles, configuring components and adding a minimal set of custom logic on top.
198
+
199
+ ## Coding guidelines
200
+
201
+ Check out our [coding guidelines](https://lion-web.netlify.app/guides/principles/definitions-and-terms/) for more detailed information.
202
+
203
+ ## How to contribute
204
+
205
+ **Please note:** This project uses Npm [Workspaces](https://docs.npmjs.com/cli/v8/using-npm/workspaces). If you want to run all demos locally you need to get at least npm 7+ and install all dependencies by executing `npm install`.
206
+
207
+ Lion Web Components are only as good as its contributions.
208
+ Read our [contribution guide](https://github.com/ing-bank/lion/blob/master/CONTRIBUTING.md) and feel free to enhance/improve Lion. We keep feature requests closed while we're not working on them.
209
+
210
+ ## Contact
211
+
212
+ Feel free to create a github issue for any feedback or questions you might have.
213
+ You can also find us on the Lit & Friends slack in the [#lion](https://lit-and-friends.slack.com/archives/CJGFWJN9J) channel.
214
+
215
+ You can join the Lit & Friends slack by visiting [https://lit.dev/slack-invite/](https://lit.dev/slack-invite/).
216
+
217
+ [i172]: https://github.com/ing-bank/lion/issues/172
218
+ [i173]: https://github.com/ing-bank/lion/issues/173
219
+ [i175]: https://github.com/ing-bank/lion/issues/175
220
+ [i194]: https://github.com/ing-bank/lion/issues/194
221
+ [i195]: https://github.com/ing-bank/lion/issues/195
222
+ [i243]: https://github.com/ing-bank/lion/issues/243
@@ -1,62 +1,12 @@
1
- import { html, css } from 'lit';
2
1
  import { browserDetection } from '@lion/ui/core.js';
3
- import { OverlayMixin, withDropdownConfig } from '@lion/ui/overlays.js';
4
2
  import { LionListbox } from '@lion/ui/listbox.js';
3
+ import { LocalizeMixin } from '@lion/ui/localize-no-side-effects.js';
4
+ import { OverlayMixin, withDropdownConfig } from '@lion/ui/overlays.js';
5
+ import { css, html } from 'lit';
6
+ import { makeMatchingTextBold, unmakeMatchingTextBold } from './utils/makeMatchingTextBold.js';
5
7
 
6
- const matchReverseFns = new WeakMap();
7
8
  const matchA11ySpanReverseFns = new WeakMap();
8
9
 
9
- /**
10
- * @param {Node} root
11
- * @param {string} matchingString
12
- * @param {Node} option
13
- */
14
- function makeMatchingTextBold(root, matchingString, option) {
15
- Array.from(root.childNodes).forEach(childNode => {
16
- if (childNode.nodeName === '#text') {
17
- // check for match based on nodeValue
18
-
19
- const re = new RegExp(`^(.*)(${matchingString})(.*)$`, 'i');
20
- // @ts-ignore
21
- const match = childNode.nodeValue.match(re);
22
-
23
- if (match) {
24
- // 1. textContent before match
25
-
26
- const textBefore = document.createTextNode(match[1]);
27
- root.appendChild(textBefore);
28
-
29
- // 2. matched part
30
- const boldElement = document.createElement('b');
31
- // eslint-disable-next-line prefer-destructuring
32
- boldElement.textContent = match[2];
33
- root.appendChild(boldElement);
34
-
35
- // 3. textContent after match
36
-
37
- const textAfter = document.createTextNode(match[3]);
38
- root.appendChild(textAfter);
39
- root.removeChild(childNode);
40
-
41
- matchReverseFns.set(option, () => {
42
- root.appendChild(childNode);
43
- if (root.contains(textBefore) && textBefore.parentNode !== null) {
44
- textBefore.parentNode.removeChild(textBefore);
45
- }
46
- if (root.contains(boldElement) && boldElement.parentNode !== null) {
47
- boldElement.parentNode.removeChild(boldElement);
48
- }
49
- if (root.contains(textAfter) && textAfter.parentNode !== null) {
50
- textAfter.parentNode.removeChild(textAfter);
51
- }
52
- });
53
- }
54
- } else {
55
- makeMatchingTextBold(childNode, matchingString, option);
56
- }
57
- });
58
- }
59
-
60
10
  // TODO: make ListboxOverlayMixin that is shared between SelectRich and Combobox
61
11
  // TODO: extract option matching based on 'typed character cache' and share that logic
62
12
  // on Listbox or ListNavigationWithActiveDescendantMixin
@@ -75,7 +25,7 @@ function makeMatchingTextBold(root, matchingString, option) {
75
25
  * LionCombobox: implements the wai-aria combobox design pattern and integrates it as a Lion
76
26
  * FormControl
77
27
  */
78
- export class LionCombobox extends OverlayMixin(LionListbox) {
28
+ export class LionCombobox extends LocalizeMixin(OverlayMixin(LionListbox)) {
79
29
  /** @type {any} */
80
30
  static get properties() {
81
31
  return {
@@ -126,6 +76,71 @@ export class LionCombobox extends OverlayMixin(LionListbox) {
126
76
  ];
127
77
  }
128
78
 
79
+ static get localizeNamespaces() {
80
+ return [
81
+ {
82
+ 'lion-combobox': /** @param {string} locale */ locale => {
83
+ switch (locale) {
84
+ case 'bg-BG':
85
+ case 'bg':
86
+ return import('@lion/ui/combobox-translations/bg.js');
87
+ case 'cs-CZ':
88
+ case 'cs':
89
+ return import('@lion/ui/combobox-translations/cs.js');
90
+ case 'de-AT':
91
+ case 'de-DE':
92
+ case 'de':
93
+ return import('@lion/ui/combobox-translations/de.js');
94
+ case 'en-AU':
95
+ case 'en-GB':
96
+ case 'en-PH':
97
+ case 'en-US':
98
+ case 'en':
99
+ return import('@lion/ui/combobox-translations/en.js');
100
+ case 'es-ES':
101
+ case 'es':
102
+ return import('@lion/ui/combobox-translations/es.js');
103
+ case 'fr-FR':
104
+ case 'fr-BE':
105
+ case 'fr':
106
+ return import('@lion/ui/combobox-translations/fr.js');
107
+ case 'hu-HU':
108
+ case 'hu':
109
+ return import('@lion/ui/combobox-translations/hu.js');
110
+ case 'it-IT':
111
+ case 'it':
112
+ return import('@lion/ui/combobox-translations/it.js');
113
+ case 'nl-BE':
114
+ case 'nl-NL':
115
+ case 'nl':
116
+ return import('@lion/ui/combobox-translations/nl.js');
117
+ case 'pl-PL':
118
+ case 'pl':
119
+ return import('@lion/ui/combobox-translations/pl.js');
120
+ case 'ro-RO':
121
+ case 'ro':
122
+ return import('@lion/ui/combobox-translations/ro.js');
123
+ case 'ru-RU':
124
+ case 'ru':
125
+ return import('@lion/ui/combobox-translations/ru.js');
126
+ case 'sk-SK':
127
+ case 'sk':
128
+ return import('@lion/ui/combobox-translations/sk.js');
129
+ case 'uk-UA':
130
+ case 'uk':
131
+ return import('@lion/ui/combobox-translations/uk.js');
132
+ case 'zh-CN':
133
+ case 'zh':
134
+ return import('@lion/ui/combobox-translations/zh.js');
135
+ default:
136
+ return import('@lion/ui/combobox-translations/en.js');
137
+ }
138
+ },
139
+ },
140
+ ...super.localizeNamespaces,
141
+ ];
142
+ }
143
+
129
144
  /**
130
145
  * @enhance FormControlMixin - add slot[name=selection-display]
131
146
  * @protected
@@ -145,9 +160,12 @@ export class LionCombobox extends OverlayMixin(LionListbox) {
145
160
  */
146
161
  // eslint-disable-next-line class-methods-use-this
147
162
  _overlayListboxTemplate() {
148
- // TODO: Localize the aria-label
149
163
  return html`
150
- <div id="overlay-content-node-wrapper" role="dialog" aria-label="Combobox options popup">
164
+ <div
165
+ id="overlay-content-node-wrapper"
166
+ role="dialog"
167
+ aria-label="${this.msgLit(`lion-combobox:optionsPopup`)}"
168
+ >
151
169
  <slot name="listbox"></slot>
152
170
  </div>
153
171
  <slot id="options-outlet"></slot>
@@ -304,7 +322,6 @@ export class LionCombobox extends OverlayMixin(LionListbox) {
304
322
  * @type {'begin'|'all'}
305
323
  */
306
324
  this.matchMode = 'all';
307
-
308
325
  /**
309
326
  * When true, the listbox is open and textbox goes from a value to empty, all options are shown.
310
327
  * By default, the listbox closes on empty, similar to wai-aria example and <datalist>
@@ -642,14 +659,27 @@ export class LionCombobox extends OverlayMixin(LionListbox) {
642
659
  * @param {string} matchingString
643
660
  * @protected
644
661
  */
645
- // eslint-disable-next-line class-methods-use-this
646
662
  _onFilterMatch(option, matchingString) {
647
- makeMatchingTextBold(option, matchingString, option);
663
+ this._highlightMatchedOption(option, matchingString);
664
+
665
+ // Alternatively, an extension can add an animation here
666
+ option.style.display = '';
667
+ }
668
+
669
+ /**
670
+ * @overridable
671
+ * @param {Element} option
672
+ * @param {string} matchingString
673
+ * @protected
674
+ */
675
+ // eslint-disable-next-line class-methods-use-this
676
+ _highlightMatchedOption(option, matchingString) {
677
+ makeMatchingTextBold(option, matchingString);
648
678
 
649
679
  // For Safari, we need to add a label to the element
650
680
  if (option.textContent) {
651
681
  const a11ySpan = document.createElement('span');
652
- a11ySpan.setAttribute('aria-label', option.textContent);
682
+ a11ySpan.setAttribute('aria-label', option.textContent.replace(/\s+/g, ' '));
653
683
  Array.from(option.childNodes).forEach(childNode => {
654
684
  a11ySpan.appendChild(childNode);
655
685
  });
@@ -664,8 +694,6 @@ export class LionCombobox extends OverlayMixin(LionListbox) {
664
694
  }
665
695
  });
666
696
  }
667
- // Alternatively, an extension can add an animation here
668
- option.style.display = '';
669
697
  }
670
698
 
671
699
  /**
@@ -677,14 +705,24 @@ export class LionCombobox extends OverlayMixin(LionListbox) {
677
705
  */
678
706
  // eslint-disable-next-line no-unused-vars, class-methods-use-this
679
707
  _onFilterUnmatch(option, curValue, prevValue) {
680
- if (matchReverseFns.has(option)) {
681
- matchReverseFns.get(option)();
682
- }
708
+ this._unhighlightMatchedOption(option);
709
+
710
+ // Alternatively, an extension can add an animation here
711
+ option.style.display = 'none';
712
+ }
713
+
714
+ /**
715
+ * @overridable
716
+ * @param {Element} option
717
+ * @protected
718
+ */
719
+ // eslint-disable-next-line class-methods-use-this
720
+ _unhighlightMatchedOption(option) {
721
+ unmakeMatchingTextBold(option);
722
+
683
723
  if (matchA11ySpanReverseFns.has(option)) {
684
724
  matchA11ySpanReverseFns.get(option)();
685
725
  }
686
- // Alternatively, an extension can add an animation here
687
- option.style.display = 'none';
688
726
  }
689
727
  /* eslint-enable no-param-reassign */
690
728
 
@@ -887,6 +925,7 @@ export class LionCombobox extends OverlayMixin(LionListbox) {
887
925
  ...withDropdownConfig(),
888
926
  elementToFocusAfterHide: undefined,
889
927
  invokerNode: this._comboboxNode,
928
+ visibilityTriggerFunction: undefined,
890
929
  });
891
930
  }
892
931
 
@@ -0,0 +1,68 @@
1
+ const matchReverseFns = new WeakMap();
2
+
3
+ /**
4
+ * @param {Node} root
5
+ * @param {string} matchingString
6
+ */
7
+ export function makeMatchingTextBold(root, matchingString) {
8
+ Array.from(root.childNodes).forEach(childNode => {
9
+ if (childNode.nodeName === '#text') {
10
+ // check for match based on nodeValue
11
+
12
+ const re = new RegExp(`^(.*?)(${matchingString})(.*)$`, 'i');
13
+ // @ts-ignore
14
+ const match = childNode.nodeValue.match(re);
15
+
16
+ if (match) {
17
+ // 1. textContent before match
18
+ const textBefore = document.createTextNode(match[1]);
19
+ root.appendChild(textBefore);
20
+
21
+ // 2. matched part
22
+ const boldElement = document.createElement('b');
23
+ // eslint-disable-next-line prefer-destructuring
24
+ boldElement.textContent = match[2];
25
+ root.appendChild(boldElement);
26
+
27
+ // 3. textContent after match
28
+ const textAfter = document.createTextNode(match[3]);
29
+ root.appendChild(textAfter);
30
+
31
+ root.removeChild(childNode);
32
+
33
+ matchReverseFns.set(root, () => {
34
+ root.appendChild(childNode);
35
+ if (root.contains(textBefore) && textBefore.parentNode !== null) {
36
+ textBefore.parentNode.removeChild(textBefore);
37
+ }
38
+ if (root.contains(boldElement) && boldElement.parentNode !== null) {
39
+ boldElement.parentNode.removeChild(boldElement);
40
+ }
41
+ if (root.contains(textAfter) && textAfter.parentNode !== null) {
42
+ textAfter.parentNode.removeChild(textAfter);
43
+ }
44
+ });
45
+ }
46
+ } else {
47
+ makeMatchingTextBold(childNode, matchingString);
48
+ }
49
+ });
50
+ }
51
+
52
+ /**
53
+ * @param {Node} root
54
+ */
55
+ export function unmakeMatchingTextBold(root) {
56
+ if (matchReverseFns.has(root)) {
57
+ matchReverseFns.get(root)();
58
+ }
59
+ Array.from(root.childNodes).forEach(childNode => {
60
+ if (childNode.nodeName === '#text') {
61
+ if (matchReverseFns.has(childNode)) {
62
+ matchReverseFns.get(childNode)();
63
+ }
64
+ } else {
65
+ unmakeMatchingTextBold(childNode);
66
+ }
67
+ });
68
+ }