@lion/ui 0.16.0-alpha.0 → 0.16.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 (54) hide show
  1. package/components/overlays/src/OverlayController.js +1 -1
  2. package/components/overlays/test/OverlayController.test.js +36 -0
  3. package/components/overlays/test-suites/OverlayMixin.suite.js +58 -0
  4. package/dist-types/components/overlays/test-suites/OverlayMixin.suite.d.ts.map +1 -1
  5. package/dist-types/tsconfig.tsbuildinfo +1 -1
  6. package/docs/components/checkbox-group/overview.md +2 -2
  7. package/docs/components/collapsible/overview.md +1 -1
  8. package/docs/components/combobox/overview.md +1 -1
  9. package/docs/components/combobox/use-cases.md +1 -1
  10. package/docs/components/dialog/overview.md +1 -1
  11. package/docs/components/fieldset/overview.md +5 -5
  12. package/docs/components/form/overview.md +3 -3
  13. package/docs/components/form/use-cases.md +2 -2
  14. package/docs/components/icon/use-cases.md +1 -1
  15. package/docs/components/input/overview.md +1 -1
  16. package/docs/components/input-amount/overview.md +3 -3
  17. package/docs/components/input-date/overview.md +3 -3
  18. package/docs/components/input-datepicker/overview.md +5 -5
  19. package/docs/components/input-email/overview.md +2 -2
  20. package/docs/components/input-file/overview.md +1 -1
  21. package/docs/components/input-iban/overview.md +2 -2
  22. package/docs/components/input-range/overview.md +2 -2
  23. package/docs/components/input-stepper/overview.md +1 -1
  24. package/docs/components/input-tel/overview.md +1 -1
  25. package/docs/components/input-tel/use-cases.md +6 -6
  26. package/docs/components/input-tel-dropdown/overview.md +1 -1
  27. package/docs/components/listbox/use-cases.md +1 -1
  28. package/docs/components/radio-group/overview.md +3 -3
  29. package/docs/components/select/use-cases.md +1 -1
  30. package/docs/components/select-rich/use-cases.md +2 -2
  31. package/docs/components/tabs/examples.md +1 -1
  32. package/docs/fundamentals/index.md +4 -4
  33. package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
  34. package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
  35. package/docs/fundamentals/rationales/accessibility.md +1 -1
  36. package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
  37. package/docs/fundamentals/systems/core/overview.md +1 -1
  38. package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
  39. package/docs/fundamentals/systems/form/model-value.md +1 -1
  40. package/docs/fundamentals/systems/form/overview.md +28 -28
  41. package/docs/fundamentals/systems/form/validate.md +2 -2
  42. package/docs/fundamentals/systems/localize/overview.md +4 -4
  43. package/docs/fundamentals/systems/overlays/configuration.md +2 -2
  44. package/docs/fundamentals/systems/overlays/overview.md +5 -5
  45. package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
  46. package/docs/fundamentals/tools/helpers/overview.md +1 -1
  47. package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
  48. package/docs/guides/how-to/create-a-custom-field.md +5 -5
  49. package/docs/guides/how-to/create-a-form.md +4 -4
  50. package/docs/guides/how-to/extend-a-native-input.md +2 -2
  51. package/docs/guides/index.md +8 -8
  52. package/docs/guides/principles/index.md +5 -5
  53. package/docs/guides/principles/styling.md +1 -1
  54. package/package.json +1 -1
@@ -911,7 +911,7 @@ export class OverlayController extends EventTarget {
911
911
  this.contentNode.getRootNode()
912
912
  ).activeElement;
913
913
 
914
- if (this.manager) {
914
+ if (this.manager && this.#isRegisteredOnManager()) {
915
915
  this.manager.hide(this);
916
916
  }
917
917
 
@@ -310,6 +310,42 @@ describe('OverlayController', () => {
310
310
 
311
311
  expect(isRegisteredOnManager(ctrl)).to.be.false;
312
312
  });
313
+
314
+ it('handles removal from DOM gracefully when overlay is open', async () => {
315
+ const contentNode = /** @type {HTMLElement} */ (fixtureSync(html`<div>my content</div>`));
316
+ const ctrl = new OverlayController({
317
+ placementMode: 'global',
318
+ contentNode,
319
+ });
320
+ await ctrl.show();
321
+ expect(ctrl.isShown).to.be.true;
322
+ expect(isRegisteredOnManager(ctrl)).to.be.true;
323
+
324
+ // Remove contentNode from DOM (simulates element being removed while open)
325
+ contentNode.parentElement?.removeChild(contentNode);
326
+
327
+ // Manually trigger teardown (normally happens via disconnectedCallback in OverlayMixin)
328
+ ctrl.teardown();
329
+
330
+ // Teardown should complete without errors
331
+ expect(isRegisteredOnManager(ctrl)).to.be.false;
332
+ });
333
+
334
+ it('does not throw when hide() is called after teardown() on a shown controller', async () => {
335
+ const ctrl = new OverlayController({
336
+ ...withGlobalTestConfig(),
337
+ });
338
+ await ctrl.show();
339
+ expect(ctrl.isShown).to.be.true;
340
+
341
+ // teardown removes the controller from the manager
342
+ ctrl.teardown();
343
+ expect(isRegisteredOnManager(ctrl)).to.be.false;
344
+
345
+ // hide() should handle gracefully that the controller is no longer on the manager
346
+ await ctrl.hide();
347
+ expect(ctrl.isShown).to.be.false;
348
+ });
313
349
  });
314
350
 
315
351
  describe('Node Configuration', () => {
@@ -597,6 +597,64 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) {
597
597
  expect(isCtrlRegisteredAtOverlaysManager).to.equal(true);
598
598
  });
599
599
 
600
+ it('teardown completes successfully when open overlay is removed from DOM', async () => {
601
+ const el = /** @type {OverlayEl} */ (
602
+ await fixture(html`
603
+ <${tag}>
604
+ <div slot="content">content of the overlay</div>
605
+ <button slot="invoker">invoker button</button>
606
+ </${tag}>
607
+ `)
608
+ );
609
+
610
+ // 1. Open the overlay
611
+ el.opened = true;
612
+ await el.updateComplete;
613
+ await el._overlayCtrl._showComplete;
614
+ expect(el._overlayCtrl.isShown).to.be.true;
615
+
616
+ // 2. Remove element from DOM without closing
617
+ /** @type {HTMLElement} */ (el.parentNode).removeChild(el);
618
+
619
+ // 3. Wait for _isPermanentlyDisconnected to resolve and teardown to complete
620
+ await aTimeout(0);
621
+
622
+ // 4. Teardown should complete without errors
623
+ // The controller should no longer be registered
624
+ expect(el._overlayCtrl.manager.list.find(ctrl => ctrl === el._overlayCtrl)).to.be.undefined;
625
+ });
626
+
627
+ it('does not throw when element is removed from DOM while overlay is open', async () => {
628
+ const el = /** @type {OverlayEl} */ (
629
+ await fixture(html`
630
+ <${tag}>
631
+ <div slot="content">content of the overlay</div>
632
+ <button slot="invoker">invoker button</button>
633
+ </${tag}>
634
+ `)
635
+ );
636
+
637
+ // 1. Open the overlay
638
+ el.opened = true;
639
+ await el.updateComplete;
640
+ await el._overlayCtrl._showComplete;
641
+ expect(el._overlayCtrl.isShown).to.be.true;
642
+
643
+ // 2. Store reference to the controller before removal
644
+ const ctrl = el._overlayCtrl;
645
+
646
+ // 3. Remove element from DOM without closing the overlay
647
+ /** @type {HTMLElement} */ (el.parentNode).removeChild(el);
648
+
649
+ // 4. Wait for _isPermanentlyDisconnected to resolve and teardown to complete
650
+ await aTimeout(0);
651
+
652
+ // 5. Teardown removed the controller from the manager.
653
+ // hide() should handle this gracefully without throwing.
654
+ await ctrl.hide();
655
+ expect(ctrl.isShown).to.be.false;
656
+ });
657
+
600
658
  it('correctly removes event listeners when disconnected from dom', async () => {
601
659
  const el = /** @type {OverlayEl} */ (
602
660
  await fixture(html`
@@ -1 +1 @@
1
- {"version":3,"file":"OverlayMixin.suite.d.ts","sourceRoot":"","sources":["../../../../components/overlays/test-suites/OverlayMixin.suite.js"],"names":[],"mappings":"AAwDA;;GAEG;AACH,iEAFW;IAAC,SAAS,EAAC,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAC,MAAM,CAAA;CAAC,QAwqBzD;kCA9sBY,OAAO,+BAA+B,EAAE,mBAAmB;wBAC3D,UAAU,GAAG,WAAW,GAAG;IAAC,YAAY,EAAC,iBAAiB,CAAA;CAAC;2BAC3D,OAAO,+BAA+B,EAAE,YAAY;0BACpD,OAAO,+BAA+B,EAAE,WAAW;4BACnD,OAAO,2BAA2B,EAAE,aAAa"}
1
+ {"version":3,"file":"OverlayMixin.suite.d.ts","sourceRoot":"","sources":["../../../../components/overlays/test-suites/OverlayMixin.suite.js"],"names":[],"mappings":"AAwDA;;GAEG;AACH,iEAFW;IAAC,SAAS,EAAC,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAC,MAAM,CAAA;CAAC,QAkuBzD;kCAxwBY,OAAO,+BAA+B,EAAE,mBAAmB;wBAC3D,UAAU,GAAG,WAAW,GAAG;IAAC,YAAY,EAAC,iBAAiB,CAAA;CAAC;2BAC3D,OAAO,+BAA+B,EAAE,YAAY;0BACpD,OAAO,+BAA+B,EAAE,WAAW;4BACnD,OAAO,2BAA2B,EAAE,aAAa"}