@lion/ui 0.0.9 → 0.0.11

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 (158) hide show
  1. package/components/accordion/src/LionAccordion.js +2 -2
  2. package/components/core/src/SlotMixin.js +2 -1
  3. package/components/dialog/src/LionDialog.js +0 -28
  4. package/components/dialog/test/lion-dialog.test.js +11 -10
  5. package/components/form-integrations/test/form-group-methods.test.js +6 -4
  6. package/components/form-integrations/test/form-integrations.test.js +10 -5
  7. package/components/form-integrations/test/helpers/umbrella-form.js +10 -0
  8. package/components/form-integrations/test/model-value-consistency.test.js +29 -20
  9. package/components/input-datepicker/src/LionInputDatepicker.js +66 -104
  10. package/components/input-datepicker/src/localizeNamespaceLoader.js +188 -0
  11. package/components/input-datepicker/test/lion-input-datepicker.test.js +15 -20
  12. package/components/input-datepicker/test-helpers/DatepickerInputObject.js +3 -3
  13. package/components/input-tel/src/parsers.js +1 -1
  14. package/components/listbox/test-suites/ListboxMixin.suite.js +3 -3
  15. package/components/localize/src/singleton.js +1 -1
  16. package/components/localize/test/number/formatNumber.test.js +2 -6
  17. package/components/overlays/src/OverlayController.js +292 -291
  18. package/components/overlays/src/OverlayMixin.js +17 -18
  19. package/components/overlays/src/OverlaysManager.js +28 -53
  20. package/components/overlays/src/configurations/visibility-trigger-partials/withClickInteraction.js +32 -0
  21. package/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.js +76 -0
  22. package/components/overlays/src/configurations/withBottomSheetConfig.js +3 -0
  23. package/components/overlays/src/configurations/withDropdownConfig.js +3 -0
  24. package/components/overlays/src/configurations/withModalDialogConfig.js +3 -0
  25. package/components/overlays/src/configurations/withTooltipConfig.js +29 -0
  26. package/components/overlays/src/overlayDocumentStyle.js +24 -0
  27. package/components/overlays/src/overlayShadowDomStyle.js +138 -0
  28. package/components/overlays/src/singleton.js +3 -1
  29. package/components/overlays/test/ArrowMixin.test.js +0 -1
  30. package/components/overlays/test/OverlayController.test.js +372 -274
  31. package/components/overlays/test/OverlaysManager.test.js +23 -32
  32. package/components/overlays/test/global-positioning.test.js +4 -15
  33. package/components/overlays/test/local-positioning.test.js +65 -38
  34. package/components/overlays/test-suites/OverlayMixin.suite.js +18 -26
  35. package/components/overlays/types/OverlayConfig.ts +38 -11
  36. package/components/overlays/types/OverlayMixinTypes.ts +2 -2
  37. package/components/select-rich/src/LionSelectInvoker.js +2 -3
  38. package/components/select-rich/src/LionSelectRich.js +22 -20
  39. package/components/select-rich/test/lion-select-rich.test.js +5 -7
  40. package/components/tooltip/src/LionTooltip.js +3 -90
  41. package/components/tooltip/test/lion-tooltip.test.js +52 -20
  42. package/custom-elements.json +535 -503
  43. package/dist-types/components/core/src/SlotMixin.d.ts.map +1 -1
  44. package/dist-types/components/dialog/src/LionDialog.d.ts +0 -2
  45. package/dist-types/components/dialog/src/LionDialog.d.ts.map +1 -1
  46. package/dist-types/components/form-integrations/test/helpers/umbrella-form.d.ts +4 -0
  47. package/dist-types/components/form-integrations/test/helpers/umbrella-form.d.ts.map +1 -1
  48. package/dist-types/components/form-integrations/test/model-value-consistency.test.d.ts.map +1 -1
  49. package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts +3 -3
  50. package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts.map +1 -1
  51. package/dist-types/components/input-datepicker/src/localizeNamespaceLoader.d.ts +4 -0
  52. package/dist-types/components/input-datepicker/src/localizeNamespaceLoader.d.ts.map +1 -0
  53. package/dist-types/components/overlays/src/OverlayController.d.ts +56 -101
  54. package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
  55. package/dist-types/components/overlays/src/OverlayMixin.d.ts.map +1 -1
  56. package/dist-types/components/overlays/src/OverlaysManager.d.ts +0 -7
  57. package/dist-types/components/overlays/src/OverlaysManager.d.ts.map +1 -1
  58. package/dist-types/components/overlays/src/configurations/visibility-trigger-partials/withClickInteraction.d.ts +12 -0
  59. package/dist-types/components/overlays/src/configurations/visibility-trigger-partials/withClickInteraction.d.ts.map +1 -0
  60. package/dist-types/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.d.ts +18 -0
  61. package/dist-types/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.d.ts.map +1 -0
  62. package/dist-types/components/overlays/src/configurations/withBottomSheetConfig.d.ts.map +1 -1
  63. package/dist-types/components/overlays/src/configurations/withDropdownConfig.d.ts.map +1 -1
  64. package/dist-types/components/overlays/src/configurations/withModalDialogConfig.d.ts.map +1 -1
  65. package/dist-types/components/overlays/src/configurations/withTooltipConfig.d.ts +8 -0
  66. package/dist-types/components/overlays/src/configurations/withTooltipConfig.d.ts.map +1 -0
  67. package/dist-types/components/overlays/src/overlayDocumentStyle.d.ts +2 -0
  68. package/dist-types/components/overlays/src/overlayDocumentStyle.d.ts.map +1 -0
  69. package/dist-types/components/overlays/src/overlayShadowDomStyle.d.ts +2 -0
  70. package/dist-types/components/overlays/src/overlayShadowDomStyle.d.ts.map +1 -0
  71. package/dist-types/components/overlays/src/singleton.d.ts +2 -1
  72. package/dist-types/components/overlays/src/singleton.d.ts.map +1 -1
  73. package/dist-types/components/overlays/test-suites/OverlayMixin.suite.d.ts.map +1 -1
  74. package/dist-types/components/overlays/types/OverlayConfig.d.ts +19 -10
  75. package/dist-types/components/overlays/types/OverlayConfig.d.ts.map +1 -1
  76. package/dist-types/components/overlays/types/OverlayMixinTypes.d.ts +2 -2
  77. package/dist-types/components/overlays/types/OverlayMixinTypes.d.ts.map +1 -1
  78. package/dist-types/components/select-rich/src/LionSelectInvoker.d.ts +3 -27
  79. package/dist-types/components/select-rich/src/LionSelectInvoker.d.ts.map +1 -1
  80. package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
  81. package/dist-types/components/select-rich/test/lion-select-rich.test.d.ts.map +1 -1
  82. package/dist-types/components/tooltip/src/LionTooltip.d.ts +4 -20
  83. package/dist-types/components/tooltip/src/LionTooltip.d.ts.map +1 -1
  84. package/dist-types/components/tooltip/test/lion-tooltip.test.d.ts.map +1 -1
  85. package/dist-types/exports/input-datepicker.d.ts +0 -1
  86. package/dist-types/exports/overlays.d.ts +1 -1
  87. package/dist-types/exports/types/overlays.d.ts +1 -0
  88. package/dist-types/exports/types/overlays.d.ts.map +1 -1
  89. package/dist-types/tsconfig.tsbuildinfo +1 -1
  90. package/docs/components/checkbox-group/overview.md +2 -2
  91. package/docs/components/collapsible/overview.md +1 -1
  92. package/docs/components/combobox/overview.md +1 -1
  93. package/docs/components/combobox/use-cases.md +1 -1
  94. package/docs/components/dialog/overview.md +5 -9
  95. package/docs/components/dialog/use-cases.md +43 -87
  96. package/docs/components/fieldset/overview.md +5 -5
  97. package/docs/components/form/overview.md +3 -3
  98. package/docs/components/icon/use-cases.md +1 -1
  99. package/docs/components/input/overview.md +1 -1
  100. package/docs/components/input-amount/overview.md +3 -3
  101. package/docs/components/input-date/overview.md +3 -3
  102. package/docs/components/input-datepicker/overview.md +5 -5
  103. package/docs/components/input-email/overview.md +2 -2
  104. package/docs/components/input-iban/overview.md +2 -2
  105. package/docs/components/input-range/overview.md +2 -2
  106. package/docs/components/input-stepper/overview.md +1 -1
  107. package/docs/components/input-tel/overview.md +1 -1
  108. package/docs/components/input-tel/use-cases.md +6 -6
  109. package/docs/components/input-tel-dropdown/overview.md +1 -1
  110. package/docs/components/radio-group/overview.md +3 -3
  111. package/docs/components/select-rich/use-cases.md +1 -1
  112. package/docs/components/tabs/examples.md +1 -1
  113. package/docs/fundamentals/index.md +4 -4
  114. package/docs/fundamentals/node-tools/providence-analytics/LocalConfiguration.md +1 -1
  115. package/docs/fundamentals/node-tools/providence-analytics/QueryResult.md +1 -1
  116. package/docs/fundamentals/node-tools/providence-analytics/analyzer.md +1 -1
  117. package/docs/fundamentals/node-tools/providence-analytics/dashboard.md +1 -1
  118. package/docs/fundamentals/node-tools/providence-analytics/overview.md +3 -3
  119. package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
  120. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
  121. package/docs/fundamentals/systems/core/overview.md +1 -1
  122. package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
  123. package/docs/fundamentals/systems/form/model-value.md +1 -1
  124. package/docs/fundamentals/systems/form/overview.md +28 -28
  125. package/docs/fundamentals/systems/form/use-cases.md +4 -0
  126. package/docs/fundamentals/systems/form/validate.md +1 -1
  127. package/docs/fundamentals/systems/localize/overview.md +4 -4
  128. package/docs/fundamentals/systems/overlays/assets/{applyDemoOverlayStyles.js → applyDemoOverlayStyles.mjs} +2 -1
  129. package/docs/fundamentals/systems/overlays/assets/demo-el-using-overlaymixin.mjs +119 -0
  130. package/docs/fundamentals/systems/overlays/assets/{demo-overlay-backdrop.js → demo-overlay-backdrop.mjs} +3 -4
  131. package/docs/fundamentals/systems/overlays/assets/demo-overlay-positioning.mjs +537 -0
  132. package/docs/fundamentals/systems/overlays/assets/umbrella-form.js +9 -2
  133. package/docs/fundamentals/systems/overlays/configuration.md +56 -54
  134. package/docs/fundamentals/systems/overlays/overview.md +5 -5
  135. package/docs/fundamentals/systems/overlays/use-cases.md +83 -77
  136. package/docs/fundamentals/tools/helpers/overview.md +1 -1
  137. package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
  138. package/docs/guides/how-to/create-a-custom-field.md +6 -6
  139. package/docs/guides/how-to/extend-a-native-input.md +3 -3
  140. package/docs/guides/index.md +8 -8
  141. package/docs/guides/principles/index.md +5 -5
  142. package/docs/guides/principles/styling.md +1 -1
  143. package/exports/input-datepicker.js +0 -1
  144. package/exports/overlays.js +1 -1
  145. package/exports/types/overlays.ts +1 -0
  146. package/package.json +2 -1
  147. package/components/input-datepicker/src/LionCalendarOverlayFrame.js +0 -125
  148. package/components/overlays/src/globalOverlaysStyle.js +0 -139
  149. package/dist-types/components/input-datepicker/src/LionCalendarOverlayFrame.d.ts +0 -10
  150. package/dist-types/components/input-datepicker/src/LionCalendarOverlayFrame.d.ts.map +0 -1
  151. package/dist-types/components/overlays/src/globalOverlaysStyle.d.ts +0 -2
  152. package/dist-types/components/overlays/src/globalOverlaysStyle.d.ts.map +0 -1
  153. package/dist-types/exports/define/lion-calendar-overlay-frame.d.ts +0 -2
  154. package/dist-types/exports/define/lion-calendar-overlay-frame.d.ts.map +0 -1
  155. package/docs/fundamentals/systems/overlays/assets/demo-overlay-system.js +0 -42
  156. package/docs/fundamentals/systems/overlays/form-integration.md +0 -65
  157. package/docs/fundamentals/systems/overlays/scope.md +0 -176
  158. package/exports/define/lion-calendar-overlay-frame.js +0 -3
@@ -210,10 +210,10 @@ export class LionAccordion extends LitElement {
210
210
  */
211
211
  __rearrangeInvokersAndContent() {
212
212
  const invokers = /** @type {HTMLElement[]} */ (
213
- Array.from(this.querySelectorAll('[slot="invoker"]'))
213
+ Array.from(this.children).filter(child => child.slot === 'invoker')
214
214
  );
215
215
  const contents = /** @type {HTMLElement[]} */ (
216
- Array.from(this.querySelectorAll('[slot="content"]'))
216
+ Array.from(this.children).filter(child => child.slot === 'content')
217
217
  );
218
218
  const accordion = this.shadowRoot?.querySelector('slot[name=_accordion]');
219
219
  if (accordion) {
@@ -196,7 +196,8 @@ const SlotMixinImplementation = superclass =>
196
196
  this.__slotsThatNeedRerender.add(slotName);
197
197
  } else {
198
198
  throw new Error(
199
- 'Please provide a function inside "get slots()" returning TemplateResult | Node | {template:TemplateResult, afterRender?:function} | undefined',
199
+ `Slot "${slotName}" configured inside "get slots()" (in prototype) of ${this.constructor.name} may return these types: TemplateResult | Node | {template:TemplateResult, afterRender?:function} | undefined.
200
+ You provided: ${slotFunctionResult}`,
200
201
  );
201
202
  }
202
203
  }
@@ -2,14 +2,6 @@ import { html, LitElement } from 'lit';
2
2
  import { OverlayMixin, withModalDialogConfig } from '@lion/ui/overlays.js';
3
3
 
4
4
  export class LionDialog extends OverlayMixin(LitElement) {
5
- constructor() {
6
- super();
7
- /** @private */
8
- this.__toggle = () => {
9
- this.opened = !this.opened;
10
- };
11
- }
12
-
13
5
  /**
14
6
  * @protected
15
7
  */
@@ -20,26 +12,6 @@ export class LionDialog extends OverlayMixin(LitElement) {
20
12
  };
21
13
  }
22
14
 
23
- /**
24
- * @protected
25
- */
26
- _setupOpenCloseListeners() {
27
- super._setupOpenCloseListeners();
28
- if (this._overlayInvokerNode) {
29
- this._overlayInvokerNode.addEventListener('click', this.__toggle);
30
- }
31
- }
32
-
33
- /**
34
- * @protected
35
- */
36
- _teardownOpenCloseListeners() {
37
- super._teardownOpenCloseListeners();
38
- if (this._overlayInvokerNode) {
39
- this._overlayInvokerNode.removeEventListener('click', this.__toggle);
40
- }
41
- }
42
-
43
15
  render() {
44
16
  return html`
45
17
  <slot name="invoker"></slot>
@@ -12,7 +12,7 @@ describe('lion-dialog', () => {
12
12
  // For some reason, globalRootNode is not cleared properly on disconnectedCallback from previous overlay test fixtures...
13
13
  // Not sure why this "bug" happens...
14
14
  beforeEach(() => {
15
- const globalRootNode = document.querySelector('.global-overlays');
15
+ const globalRootNode = document.querySelector('.overlays');
16
16
  if (globalRootNode) {
17
17
  globalRootNode.innerHTML = '';
18
18
  }
@@ -39,7 +39,8 @@ describe('lion-dialog', () => {
39
39
  `);
40
40
  const invoker = /** @type {HTMLElement} */ (el.querySelector('[slot="invoker"]'));
41
41
  invoker.click();
42
-
42
+ // @ts-expect-error [allow-protected-in-tests]
43
+ await el._overlayCtrl._showComplete;
43
44
  expect(el.opened).to.be.true;
44
45
  });
45
46
 
@@ -57,18 +58,18 @@ describe('lion-dialog', () => {
57
58
  </lion-dialog>
58
59
  `);
59
60
 
60
- // @ts-expect-error you're not allowed to call protected _overlayInvokerNode in public context, but for testing it's okay
61
+ // @ts-expect-error [allow-protected-in-tests]
61
62
  el._overlayInvokerNode.click();
63
+ // @ts-expect-error [allow-protected-in-tests]
64
+ await el._overlayCtrl._showComplete;
62
65
  expect(el.opened).to.be.true;
63
66
 
64
- const overlaysContainer = /** @type {HTMLElement} */ (
65
- document.querySelector('.global-overlays')
66
- );
67
- const wrapperNode = Array.from(overlaysContainer.children)[1];
68
- const nestedDialog = /** @type {LionDialog} */ (wrapperNode.querySelector('lion-dialog'));
67
+ const nestedDialogEl = /** @type {LionDialog} */ (el.querySelector('lion-dialog'));
69
68
  // @ts-expect-error you're not allowed to call protected _overlayInvokerNode in public context, but for testing it's okay
70
- nestedDialog?._overlayInvokerNode.click();
71
- expect(nestedDialog.opened).to.be.true;
69
+ nestedDialogEl?._overlayInvokerNode.click();
70
+ // @ts-expect-error [allow-protected-in-tests]
71
+ await nestedDialogEl._overlayCtrl._showComplete;
72
+ expect(nestedDialogEl.opened).to.be.true;
72
73
  });
73
74
  });
74
75
  });
@@ -96,15 +96,13 @@ describe(`Submitting/Resetting/Clearing Form`, async () => {
96
96
  it('pressing submit button of a form should make submitted true for all fields', async () => {
97
97
  const el = /** @type {UmbrellaForm} */ (await fixture(html`<umbrella-form></umbrella-form>`));
98
98
  await el.updateComplete;
99
+ await el.waitForAllChildrenUpdates();
100
+
99
101
  const formEl = el._lionFormNode;
100
102
 
101
103
  const allElements = getAllFieldsAndFormGroups(formEl);
102
104
 
103
105
  allElements.forEach((/** @type {LionField} */ field) => {
104
- if (field.tagName === 'LION-SWITCH') {
105
- // TODO: remove this when this is fixed: https://github.com/ing-bank/lion/issues/1204
106
- return;
107
- }
108
106
  // TODO: prefer submitted 'false' over 'undefined'
109
107
  expect(Boolean(field.submitted)).to.be.false;
110
108
  });
@@ -122,6 +120,8 @@ describe(`Submitting/Resetting/Clearing Form`, async () => {
122
120
  html`<umbrella-form .serializedValue="${fullyPrefilledSerializedValue}"></umbrella-form>`,
123
121
  )
124
122
  );
123
+ await el.waitForAllChildrenUpdates();
124
+
125
125
  await el.updateComplete;
126
126
  const formEl = el._lionFormNode;
127
127
 
@@ -168,6 +168,8 @@ describe(`Submitting/Resetting/Clearing Form`, async () => {
168
168
  html`<umbrella-form .serializedValue="${fullyPrefilledSerializedValue}"></umbrella-form>`,
169
169
  )
170
170
  );
171
+ await el.waitForAllChildrenUpdates();
172
+
171
173
  await el.updateComplete;
172
174
  const formEl = el._lionFormNode;
173
175
 
@@ -25,6 +25,7 @@ describe('Form Integrations', () => {
25
25
  it('".serializedValue" returns all non disabled fields based on form structure', async () => {
26
26
  const el = /** @type {UmbrellaForm} */ (await fixture(html`<umbrella-form></umbrella-form>`));
27
27
  await el.updateComplete;
28
+ await el.waitForAllChildrenUpdates();
28
29
  const formEl = el._lionFormNode;
29
30
 
30
31
  expect(formEl.serializedValue).to.eql({
@@ -46,7 +47,7 @@ describe('Form Integrations', () => {
46
47
  notifications: { value: '', checked: false },
47
48
  rsvp: '',
48
49
  tel: '',
49
- 'tel-dropdown': '',
50
+ 'tel-dropdown': '+44',
50
51
  comments: '',
51
52
  });
52
53
  });
@@ -110,6 +111,7 @@ describe('Form Integrations', () => {
110
111
  ></umbrella-form>`,
111
112
  )
112
113
  );
114
+ await el.waitForAllChildrenUpdates();
113
115
 
114
116
  await el._lionFormNode.initComplete;
115
117
  expect(el._lionFormNode.dirty).to.be.false;
@@ -162,9 +164,10 @@ describe('Form Integrations', () => {
162
164
  ];
163
165
 
164
166
  it('successfully registers all form components', async () => {
165
- const el = /** @type {UmbrellaForm} */ await fixture(html`<umbrella-form></umbrella-form>`);
166
- // @ts-ignore
167
- const formEl = /** @type {LionForm} */ (el._lionFormNode);
167
+ const el = /** @type {UmbrellaForm} */ (await fixture(html`<umbrella-form></umbrella-form>`));
168
+ await el.waitForAllChildrenUpdates();
169
+
170
+ const formEl = el._lionFormNode;
168
171
  await formEl.registrationComplete;
169
172
  const registeredEls = getAllTagNames(formEl);
170
173
 
@@ -172,8 +175,10 @@ describe('Form Integrations', () => {
172
175
  });
173
176
 
174
177
  it('successfully unregisters all form components', async () => {
175
- const el = /** @type {UmbrellaForm} */ await fixture(html`<umbrella-form></umbrella-form>`);
178
+ const el = /** @type {UmbrellaForm} */ (await fixture(html`<umbrella-form></umbrella-form>`));
176
179
  const offlineContainer = document.createElement('div');
180
+ await el.waitForAllChildrenUpdates();
181
+
177
182
  // @ts-ignore
178
183
  const formEl = /** @type {LionForm} */ (el._lionFormNode);
179
184
  await formEl.registrationComplete;
@@ -11,10 +11,13 @@ import '@lion/ui/define/lion-input-email.js';
11
11
  import '@lion/ui/define/lion-input-tel.js';
12
12
  import '@lion/ui/define/lion-input-tel-dropdown.js';
13
13
  import '@lion/ui/define/lion-checkbox-group.js';
14
+ import '@lion/ui/define/lion-checkbox.js';
14
15
  import '@lion/ui/define/lion-radio-group.js';
16
+ import '@lion/ui/define/lion-radio.js';
15
17
  import '@lion/ui/define/lion-select.js';
16
18
  import '@lion/ui/define/lion-select-rich.js';
17
19
  import '@lion/ui/define/lion-listbox.js';
20
+ import '@lion/ui/define/lion-option.js';
18
21
  import '@lion/ui/define/lion-combobox.js';
19
22
  import '@lion/ui/define/lion-input-range.js';
20
23
  import '@lion/ui/define/lion-textarea.js';
@@ -36,6 +39,13 @@ export class UmbrellaForm extends LitElement {
36
39
  this.__serializedValue = v;
37
40
  }
38
41
 
42
+ /**
43
+ * Prevents errors outside test from being thrown
44
+ */
45
+ async waitForAllChildrenUpdates() {
46
+ return Promise.all(this._lionFormNode.formElements.map(child => child.updateComplete));
47
+ }
48
+
39
49
  render() {
40
50
  return html`
41
51
  <lion-form .serializedValue="${this.__serializedValue}">
@@ -11,23 +11,19 @@ import '@lion/ui/define/lion-input-email.js';
11
11
  import '@lion/ui/define/lion-input-iban.js';
12
12
  import '@lion/ui/define/lion-input-range.js';
13
13
  import '@lion/ui/define/lion-input-stepper.js';
14
-
14
+ import '@lion/ui/define/lion-input-tel.js';
15
+ import '@lion/ui/define/lion-input-tel-dropdown.js';
15
16
  import '@lion/ui/define/lion-textarea.js';
16
-
17
17
  import '@lion/ui/define/lion-checkbox.js';
18
18
  import '@lion/ui/define/lion-checkbox-group.js';
19
-
20
19
  import '@lion/ui/define/lion-radio.js';
21
20
  import '@lion/ui/define/lion-radio-group.js';
22
21
  import '@lion/ui/define/lion-switch.js';
23
-
24
22
  import '@lion/ui/define/lion-select.js';
25
23
  import '@lion/ui/define/lion-option.js';
26
-
27
24
  import '@lion/ui/define/lion-combobox.js';
28
25
  import '@lion/ui/define/lion-listbox.js';
29
26
  import '@lion/ui/define/lion-select-rich.js';
30
-
31
27
  import '@lion/ui/define/lion-fieldset.js';
32
28
  import '@lion/ui/define/lion-form.js';
33
29
  import '@lion/ui/define/lion-field.js';
@@ -344,7 +340,6 @@ describe('lion-fieldset', () => {
344
340
 
345
341
  describe('detail.isTriggeredByUser', () => {
346
342
  const allFormControls = [
347
- 'switch', // TODO: move back below when scoped-elements (polyfill) fixed side effects
348
343
  // 1) Fields
349
344
  'field',
350
345
  // 1a) Input Fields
@@ -356,12 +351,14 @@ describe('detail.isTriggeredByUser', () => {
356
351
  'input-iban',
357
352
  'input-range',
358
353
  'input-stepper',
354
+ 'input-tel',
355
+ 'input-tel-dropdown',
359
356
  'textarea',
360
357
  // 1b) Choice Fields
361
358
  'option',
362
359
  'checkbox',
363
360
  'radio',
364
- // 'switch',
361
+ 'switch',
365
362
  // 1c) Choice Group Fields
366
363
  'select',
367
364
  'listbox',
@@ -423,9 +420,10 @@ describe('detail.isTriggeredByUser', () => {
423
420
  /**
424
421
  * @param {FormControl & {value: string;}} el
425
422
  * @param {string} newViewValue
426
- * @param {{ triggerType?: string, labelInsteadOfInput?: boolean }} [optionals]
423
+ * @param {{ triggerType?: string, labelInsteadOfInput?: boolean, parent?: HTMLElement }} options
427
424
  */
428
- function mimicUserInput(el, newViewValue, optionals) {
425
+ function mimicUserInput(el, newViewValue, options = {}) {
426
+ // @ts-ignore
429
427
  const { _inputNode, _labelNode } = getFormControlMembers(el);
430
428
  const type = detectType(el);
431
429
  let userInputEv;
@@ -434,15 +432,15 @@ describe('detail.isTriggeredByUser', () => {
434
432
  el.value = newViewValue; // eslint-disable-line no-param-reassign
435
433
  _inputNode.dispatchEvent(new Event(userInputEv, { bubbles: true }));
436
434
  } else if (type === 'ChoiceField') {
437
- if (optionals?.labelInsteadOfInput) {
435
+ if (options?.labelInsteadOfInput) {
438
436
  _labelNode.click();
439
437
  } else {
440
438
  _inputNode.click();
441
439
  }
442
440
  } else if (type === 'OptionChoiceField') {
443
- if (!optionals?.triggerType) {
441
+ if (!options?.triggerType) {
444
442
  el.dispatchEvent(new Event('click', { bubbles: true }));
445
- } else if (optionals?.triggerType === 'keypress') {
443
+ } else if (options?.triggerType === 'keypress') {
446
444
  el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }));
447
445
  el.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowDown', bubbles: true }));
448
446
  el.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
@@ -503,9 +501,12 @@ describe('detail.isTriggeredByUser', () => {
503
501
 
504
502
  /**
505
503
  * @param {FormControl & {value: string;}} formControl
506
- * @param {boolean | undefined} [testKeyboardBehavior]
504
+ * @param {{parent?: FormControl; testKeyboardBehavior?: boolean}} moreOpts
507
505
  */
508
- async function expectCorrectEventMetaChoiceField(formControl, testKeyboardBehavior) {
506
+ async function expectCorrectEventMetaChoiceField(
507
+ formControl,
508
+ { parent, testKeyboardBehavior } = {},
509
+ ) {
509
510
  const type = detectType(formControl);
510
511
 
511
512
  await resetChoiceFieldToForceRepropagation(formControl);
@@ -526,14 +527,19 @@ describe('detail.isTriggeredByUser', () => {
526
527
  formControl.modelValue = { value: 'programmaticValue', checked: false };
527
528
  expect(spy.secondCall.args[0].detail.isTriggeredByUser).to.be.false;
528
529
 
529
- if (type === 'OptionChoiceField' && testKeyboardBehavior) {
530
+ if (
531
+ type === 'OptionChoiceField' &&
532
+ testKeyboardBehavior &&
533
+ parent?.constructor.name !== 'LionCombobox' // modelValue only changeable via click or textbox
534
+ ) {
530
535
  await resetChoiceFieldToForceRepropagation(formControl);
531
- mimicUserInput(formControl, 'userValue', { triggerType: 'keypress' });
532
- // TODO: get rid of try/catch (?)...
536
+ mimicUserInput(formControl, 'userValue', { triggerType: 'keypress', parent });
533
537
  try {
534
538
  expect(spy.firstCall.args[0].detail.isTriggeredByUser).to.be.true;
535
539
  } catch (e) {
536
- console.log(formControl);
540
+ throw new Error(
541
+ `model-value-changed of ${formControl.constructor.name} with parent ${parent?.constructor.name} not caught`,
542
+ );
537
543
  }
538
544
  }
539
545
  }
@@ -556,7 +562,10 @@ describe('detail.isTriggeredByUser', () => {
556
562
  );
557
563
  el.appendChild(childrenEls);
558
564
  await el.registrationComplete;
559
- await expectCorrectEventMetaChoiceField(el.formElements[0], true);
565
+ await expectCorrectEventMetaChoiceField(el.formElements[0], {
566
+ testKeyboardBehavior: true,
567
+ parent: el,
568
+ });
560
569
  } else if (type === 'FormOrFieldset') {
561
570
  const childrenEls = await fixture(
562
571
  html`<div><lion-input name="one"></lion-input><lion-input name="two"></lion-input></div>`,
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable import/no-extraneous-dependencies */
2
2
  import { LionCalendar } from '@lion/ui/calendar.js';
3
3
  import { ScopedElementsMixin } from '@open-wc/scoped-elements';
4
- import { html, render } from 'lit';
4
+ import { html, css } from 'lit';
5
5
  import { ifDefined } from 'lit/directives/if-defined.js';
6
6
  import { LionInputDate } from '@lion/ui/input-date.js';
7
7
  import {
@@ -10,7 +10,8 @@ import {
10
10
  withModalDialogConfig,
11
11
  ArrowMixin,
12
12
  } from '@lion/ui/overlays.js';
13
- import { LionCalendarOverlayFrame } from './LionCalendarOverlayFrame.js';
13
+ import { LocalizeMixin } from '@lion/ui/localize.js';
14
+ import { localizeNamespaceLoader } from './localizeNamespaceLoader.js';
14
15
 
15
16
  /**
16
17
  * @typedef {import('../../form-core/src/validate/Validator.js').Validator} Validator
@@ -21,16 +22,49 @@ import { LionCalendarOverlayFrame } from './LionCalendarOverlayFrame.js';
21
22
  * @customElement lion-input-datepicker
22
23
  */
23
24
  export class LionInputDatepicker extends ScopedElementsMixin(
24
- ArrowMixin(OverlayMixin(LionInputDate)),
25
+ ArrowMixin(OverlayMixin(LocalizeMixin(LionInputDate))),
25
26
  ) {
26
27
  static get scopedElements() {
27
28
  return {
28
29
  ...super.scopedElements,
29
30
  'lion-calendar': LionCalendar,
30
- 'lion-calendar-overlay-frame': LionCalendarOverlayFrame,
31
31
  };
32
32
  }
33
33
 
34
+ static get styles() {
35
+ return [
36
+ ...super.styles,
37
+ css`
38
+ .calendar__overlay-frame {
39
+ display: inline-block;
40
+ background: white;
41
+ position: relative;
42
+ }
43
+
44
+ .calendar-overlay__header {
45
+ display: flex;
46
+ }
47
+
48
+ .calendar-overlay__heading {
49
+ padding: 16px 16px 8px;
50
+ flex: 1;
51
+ }
52
+
53
+ .calendar-overlay__heading > .calendar-overlay__close-button {
54
+ flex: none;
55
+ }
56
+
57
+ .calendar-overlay__close-button {
58
+ min-width: 40px;
59
+ min-height: 32px;
60
+ border-width: 0;
61
+ padding: 0;
62
+ font-size: 24px;
63
+ }
64
+ `,
65
+ ];
66
+ }
67
+
34
68
  /** @type {any} */
35
69
  static get properties() {
36
70
  return {
@@ -68,101 +102,12 @@ export class LionInputDatepicker extends ScopedElementsMixin(
68
102
  get slots() {
69
103
  return {
70
104
  ...super.slots,
71
- [this._calendarInvokerSlot]: () => {
72
- const renderParent = document.createElement('div');
73
- render(
74
- this._invokerTemplate(),
75
- renderParent,
76
- /** @type {RenderOptions} */ ({
77
- scopeName: this.localName,
78
- eventContext: this,
79
- }),
80
- );
81
- return /** @type {HTMLElement} */ (renderParent.firstElementChild);
82
- },
105
+ [this._calendarInvokerSlot]: () => this._invokerTemplate(),
83
106
  };
84
107
  }
85
108
 
86
109
  static get localizeNamespaces() {
87
- return [
88
- {
89
- 'lion-input-datepicker': /** @param {string} locale */ locale => {
90
- switch (locale) {
91
- case 'bg-BG':
92
- return import('@lion/ui/input-datepicker-translations/bg-BG.js');
93
- case 'bg':
94
- return import('@lion/ui/input-datepicker-translations/bg.js');
95
- case 'cs-CZ':
96
- return import('@lion/ui/input-datepicker-translations/cs-CZ.js');
97
- case 'cs':
98
- return import('@lion/ui/input-datepicker-translations/cs.js');
99
- case 'de-DE':
100
- return import('@lion/ui/input-datepicker-translations/de-DE.js');
101
- case 'de':
102
- return import('@lion/ui/input-datepicker-translations/de.js');
103
- case 'en-AU':
104
- return import('@lion/ui/input-datepicker-translations/en-AU.js');
105
- case 'en-GB':
106
- return import('@lion/ui/input-datepicker-translations/en-GB.js');
107
- case 'en-US':
108
- return import('@lion/ui/input-datepicker-translations/en-US.js');
109
- case 'en-PH':
110
- case 'en':
111
- return import('@lion/ui/input-datepicker-translations/en.js');
112
- case 'es-ES':
113
- return import('@lion/ui/input-datepicker-translations/es-ES.js');
114
- case 'es':
115
- return import('@lion/ui/input-datepicker-translations/es.js');
116
- case 'fr-FR':
117
- return import('@lion/ui/input-datepicker-translations/fr-FR.js');
118
- case 'fr-BE':
119
- return import('@lion/ui/input-datepicker-translations/fr-BE.js');
120
- case 'fr':
121
- return import('@lion/ui/input-datepicker-translations/fr.js');
122
- case 'hu-HU':
123
- return import('@lion/ui/input-datepicker-translations/hu-HU.js');
124
- case 'hu':
125
- return import('@lion/ui/input-datepicker-translations/hu.js');
126
- case 'it-IT':
127
- return import('@lion/ui/input-datepicker-translations/it-IT.js');
128
- case 'it':
129
- return import('@lion/ui/input-datepicker-translations/it.js');
130
- case 'nl-BE':
131
- return import('@lion/ui/input-datepicker-translations/nl-BE.js');
132
- case 'nl-NL':
133
- return import('@lion/ui/input-datepicker-translations/nl-NL.js');
134
- case 'nl':
135
- return import('@lion/ui/input-datepicker-translations/nl.js');
136
- case 'pl-PL':
137
- return import('@lion/ui/input-datepicker-translations/pl-PL.js');
138
- case 'pl':
139
- return import('@lion/ui/input-datepicker-translations/pl.js');
140
- case 'ro-RO':
141
- return import('@lion/ui/input-datepicker-translations/ro-RO.js');
142
- case 'ro':
143
- return import('@lion/ui/input-datepicker-translations/ro.js');
144
- case 'ru-RU':
145
- return import('@lion/ui/input-datepicker-translations/ru-RU.js');
146
- case 'ru':
147
- return import('@lion/ui/input-datepicker-translations/ru.js');
148
- case 'sk-SK':
149
- return import('@lion/ui/input-datepicker-translations/sk-SK.js');
150
- case 'sk':
151
- return import('@lion/ui/input-datepicker-translations/sk.js');
152
- case 'uk-UA':
153
- return import('@lion/ui/input-datepicker-translations/uk-UA.js');
154
- case 'uk':
155
- return import('@lion/ui/input-datepicker-translations/uk.js');
156
- case 'zh-CN':
157
- case 'zh':
158
- return import('@lion/ui/input-datepicker-translations/zh.js');
159
- default:
160
- return import('@lion/ui/input-datepicker-translations/en.js');
161
- }
162
- },
163
- },
164
- ...super.localizeNamespaces,
165
- ];
110
+ return [{ 'lion-input-datepicker': localizeNamespaceLoader }, ...super.localizeNamespaces];
166
111
  }
167
112
 
168
113
  /**
@@ -262,11 +207,29 @@ export class LionInputDatepicker extends ScopedElementsMixin(
262
207
  // This would make first paint quicker
263
208
  return html`
264
209
  <div id="overlay-content-node-wrapper">
265
- <lion-calendar-overlay-frame class="calendar__overlay-frame">
266
- <span slot="heading">${this.calendarHeading}</span>
267
- ${this._calendarTemplate()}
268
- </lion-calendar-overlay-frame>
269
- ${this._arrowNodeTemplate()}
210
+ ${this._overlayFrameTemplate()} ${this._arrowNodeTemplate()}
211
+ </div>
212
+ `;
213
+ }
214
+
215
+ _overlayFrameTemplate() {
216
+ return html`
217
+ <div class="calendar__overlay-frame">
218
+ <div class="calendar-overlay">
219
+ <div class="calendar-overlay__header">
220
+ <h1 class="calendar-overlay__heading">${this.calendarHeading}</h1>
221
+ <button
222
+ @click="${() => this._overlayCtrl.hide()}"
223
+ id="close-button"
224
+ title="${this.msgLit('lion-input-datepicker:close')}"
225
+ aria-label="${this.msgLit('lion-input-datepicker:close')}"
226
+ class="calendar-overlay__close-button"
227
+ >
228
+ <slot name="close-icon">&times;</slot>
229
+ </button>
230
+ </div>
231
+ <div>${this._calendarTemplate()}</div>
232
+ </div>
270
233
  </div>
271
234
  `;
272
235
  }
@@ -342,6 +305,7 @@ export class LionInputDatepicker extends ScopedElementsMixin(
342
305
  return {
343
306
  ...withModalDialogConfig(),
344
307
  hidesOnOutsideClick: true,
308
+ visibilityTriggerFunction: undefined,
345
309
  ...super._defineOverlayConfig(),
346
310
  popperConfig: {
347
311
  ...super._defineOverlayConfig().popperConfig,
@@ -416,10 +380,7 @@ export class LionInputDatepicker extends ScopedElementsMixin(
416
380
  // On every validator change, synchronize disabled dates: this means
417
381
  // we need to extract minDate, maxDate, minMaxDate and disabledDates validators
418
382
  validators.forEach(v => {
419
- const vctor =
420
- /** @type {typeof import('../../form-core/src/validate/Validator.js').Validator} */ (
421
- v.constructor
422
- );
383
+ const vctor = /** @type {typeof import('@lion/ui/form-core.js').Validator} */ (v.constructor);
423
384
  if (vctor.validatorName === 'MinDate') {
424
385
  this.__calendarMinDate = v.param;
425
386
  } else if (vctor.validatorName === 'MaxDate') {
@@ -466,6 +427,7 @@ export class LionInputDatepicker extends ScopedElementsMixin(
466
427
  this._cachedOverlayContentNode = /** @type {HTMLElement} */ (
467
428
  /** @type {ShadowRoot} */ (this.shadowRoot).querySelector('.calendar__overlay-frame')
468
429
  );
430
+
469
431
  return this._cachedOverlayContentNode;
470
432
  }
471
433
  }