@aquera/nile-elements 1.6.0 → 1.6.2

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 (235) hide show
  1. package/README.md +9 -0
  2. package/dist/index.cjs.js +1 -1
  3. package/dist/index.esm.js +1 -1
  4. package/dist/index.js +1103 -629
  5. package/dist/internal/enum.cjs.js +1 -1
  6. package/dist/internal/enum.cjs.js.map +1 -1
  7. package/dist/internal/enum.esm.js +1 -1
  8. package/dist/nile-badge/index.cjs.js +1 -1
  9. package/dist/nile-badge/index.esm.js +1 -1
  10. package/dist/nile-badge/nile-badge.cjs.js +1 -1
  11. package/dist/nile-badge/nile-badge.cjs.js.map +1 -1
  12. package/dist/nile-badge/nile-badge.esm.js +1 -1
  13. package/dist/nile-button/index.cjs.js +1 -1
  14. package/dist/nile-button/index.esm.js +1 -1
  15. package/dist/nile-button/nile-button.cjs.js +1 -1
  16. package/dist/nile-button/nile-button.cjs.js.map +1 -1
  17. package/dist/nile-button/nile-button.esm.js +1 -1
  18. package/dist/nile-carousel/index.cjs.js +1 -1
  19. package/dist/nile-carousel/index.esm.js +1 -1
  20. package/dist/nile-carousel/nile-carousel.cjs.js +1 -1
  21. package/dist/nile-carousel/nile-carousel.cjs.js.map +1 -1
  22. package/dist/nile-carousel/nile-carousel.esm.js +1 -1
  23. package/dist/nile-dialog/index.cjs.js +1 -1
  24. package/dist/nile-dialog/index.esm.js +1 -1
  25. package/dist/nile-dialog/nile-dialog.cjs.js +1 -1
  26. package/dist/nile-dialog/nile-dialog.cjs.js.map +1 -1
  27. package/dist/nile-dialog/nile-dialog.esm.js +1 -1
  28. package/dist/nile-drawer/index.cjs.js +1 -1
  29. package/dist/nile-drawer/index.esm.js +1 -1
  30. package/dist/nile-drawer/nile-drawer.cjs.js +1 -1
  31. package/dist/nile-drawer/nile-drawer.cjs.js.map +1 -1
  32. package/dist/nile-drawer/nile-drawer.esm.js +1 -1
  33. package/dist/nile-floating-panel/index.cjs.js +1 -1
  34. package/dist/nile-floating-panel/index.esm.js +1 -1
  35. package/dist/nile-floating-panel/nile-floating-panel.cjs.js +1 -1
  36. package/dist/nile-floating-panel/nile-floating-panel.cjs.js.map +1 -1
  37. package/dist/nile-floating-panel/nile-floating-panel.css.cjs.js +1 -1
  38. package/dist/nile-floating-panel/nile-floating-panel.css.cjs.js.map +1 -1
  39. package/dist/nile-floating-panel/nile-floating-panel.css.esm.js +137 -21
  40. package/dist/nile-floating-panel/nile-floating-panel.esm.js +1 -1
  41. package/dist/nile-icon/icons/svg/folder_delete.cjs.js +2 -0
  42. package/dist/nile-icon/icons/svg/folder_delete.cjs.js.map +1 -0
  43. package/dist/nile-icon/icons/svg/folder_delete.esm.js +1 -0
  44. package/dist/nile-icon/icons/svg/index.cjs.js +1 -1
  45. package/dist/nile-icon/icons/svg/index.esm.js +1 -1
  46. package/dist/nile-icon/icons/svg/layers-three-02.cjs.js +1 -1
  47. package/dist/nile-icon/icons/svg/layers-three-02.cjs.js.map +1 -1
  48. package/dist/nile-icon/icons/svg/layers-three-02.esm.js +1 -1
  49. package/dist/nile-icon/index.cjs.js +1 -1
  50. package/dist/nile-icon/index.cjs.js.map +1 -1
  51. package/dist/nile-icon/index.esm.js +1 -1
  52. package/dist/nile-icon-button/index.cjs.js +1 -1
  53. package/dist/nile-icon-button/index.esm.js +1 -1
  54. package/dist/nile-icon-button/nile-icon-button.cjs.js +1 -1
  55. package/dist/nile-icon-button/nile-icon-button.cjs.js.map +1 -1
  56. package/dist/nile-icon-button/nile-icon-button.esm.js +1 -1
  57. package/dist/nile-input/index.cjs.js +1 -1
  58. package/dist/nile-input/index.esm.js +1 -1
  59. package/dist/nile-input/nile-input.cjs.js +1 -1
  60. package/dist/nile-input/nile-input.cjs.js.map +1 -1
  61. package/dist/nile-input/nile-input.esm.js +1 -1
  62. package/dist/nile-lite-tooltip/index.cjs.js +1 -1
  63. package/dist/nile-lite-tooltip/index.esm.js +1 -1
  64. package/dist/nile-lite-tooltip/nile-lite-tooltip.cjs.js +1 -1
  65. package/dist/nile-lite-tooltip/nile-lite-tooltip.cjs.js.map +1 -1
  66. package/dist/nile-lite-tooltip/nile-lite-tooltip.esm.js +1 -1
  67. package/dist/nile-menu-item/index.cjs.js +1 -1
  68. package/dist/nile-menu-item/index.esm.js +1 -1
  69. package/dist/nile-menu-item/nile-menu-item.cjs.js +1 -1
  70. package/dist/nile-menu-item/nile-menu-item.cjs.js.map +1 -1
  71. package/dist/nile-menu-item/nile-menu-item.esm.js +1 -1
  72. package/dist/nile-option/index.cjs.js +1 -1
  73. package/dist/nile-option/index.esm.js +1 -1
  74. package/dist/nile-option/nile-option.cjs.js +1 -1
  75. package/dist/nile-option/nile-option.cjs.js.map +1 -1
  76. package/dist/nile-option/nile-option.esm.js +1 -1
  77. package/dist/nile-otp-input/index.cjs.js +2 -0
  78. package/dist/nile-otp-input/index.cjs.js.map +1 -0
  79. package/dist/nile-otp-input/index.esm.js +1 -0
  80. package/dist/nile-otp-input/nile-otp-input.cjs.js +2 -0
  81. package/dist/nile-otp-input/nile-otp-input.cjs.js.map +1 -0
  82. package/dist/nile-otp-input/nile-otp-input.css.cjs.js +2 -0
  83. package/dist/nile-otp-input/nile-otp-input.css.cjs.js.map +1 -0
  84. package/dist/nile-otp-input/nile-otp-input.css.esm.js +257 -0
  85. package/dist/nile-otp-input/nile-otp-input.enum.cjs.js +2 -0
  86. package/dist/nile-otp-input/nile-otp-input.enum.cjs.js.map +1 -0
  87. package/dist/nile-otp-input/nile-otp-input.enum.esm.js +1 -0
  88. package/dist/nile-otp-input/nile-otp-input.esm.js +103 -0
  89. package/dist/nile-select/index.cjs.js +1 -1
  90. package/dist/nile-select/index.esm.js +1 -1
  91. package/dist/nile-select/nile-select.cjs.js +1 -1
  92. package/dist/nile-select/nile-select.cjs.js.map +1 -1
  93. package/dist/nile-select/nile-select.esm.js +1 -1
  94. package/dist/nile-side-bar-action-menu-item/index.cjs.js +1 -1
  95. package/dist/nile-side-bar-action-menu-item/index.esm.js +1 -1
  96. package/dist/nile-side-bar-action-menu-item/nile-side-bar-action-menu-item.cjs.js +1 -1
  97. package/dist/nile-side-bar-action-menu-item/nile-side-bar-action-menu-item.cjs.js.map +1 -1
  98. package/dist/nile-side-bar-action-menu-item/nile-side-bar-action-menu-item.esm.js +1 -1
  99. package/dist/nile-tab/index.cjs.js +1 -1
  100. package/dist/nile-tab/index.esm.js +1 -1
  101. package/dist/nile-tab/nile-tab.cjs.js +1 -1
  102. package/dist/nile-tab/nile-tab.cjs.js.map +1 -1
  103. package/dist/nile-tab/nile-tab.esm.js +1 -1
  104. package/dist/nile-tab-group/index.cjs.js +1 -1
  105. package/dist/nile-tab-group/index.esm.js +1 -1
  106. package/dist/nile-tab-group/nile-tab-group.cjs.js +1 -1
  107. package/dist/nile-tab-group/nile-tab-group.cjs.js.map +1 -1
  108. package/dist/nile-tab-group/nile-tab-group.esm.js +1 -1
  109. package/dist/nile-tag/index.cjs.js +1 -1
  110. package/dist/nile-tag/index.esm.js +1 -1
  111. package/dist/nile-tag/nile-tag.cjs.js +1 -1
  112. package/dist/nile-tag/nile-tag.cjs.js.map +1 -1
  113. package/dist/nile-tag/nile-tag.esm.js +1 -1
  114. package/dist/nile-toast/index.cjs.js +1 -1
  115. package/dist/nile-toast/index.esm.js +1 -1
  116. package/dist/nile-toast/nile-toast.cjs.js +1 -1
  117. package/dist/nile-toast/nile-toast.cjs.js.map +1 -1
  118. package/dist/nile-toast/nile-toast.esm.js +1 -1
  119. package/dist/nile-tree/index.cjs.js +1 -1
  120. package/dist/nile-tree/index.esm.js +1 -1
  121. package/dist/nile-tree/nile-tree.cjs.js +1 -1
  122. package/dist/nile-tree/nile-tree.cjs.js.map +1 -1
  123. package/dist/nile-tree/nile-tree.esm.js +1 -1
  124. package/dist/nile-tree-item/index.cjs.js +1 -1
  125. package/dist/nile-tree-item/index.esm.js +1 -1
  126. package/dist/nile-tree-item/nile-tree-item.cjs.js +1 -1
  127. package/dist/nile-tree-item/nile-tree-item.cjs.js.map +1 -1
  128. package/dist/nile-tree-item/nile-tree-item.esm.js +1 -1
  129. package/dist/nile-virtual-select/index.cjs.js +1 -1
  130. package/dist/nile-virtual-select/index.esm.js +1 -1
  131. package/dist/nile-virtual-select/nile-virtual-select.cjs.js +2 -2
  132. package/dist/nile-virtual-select/nile-virtual-select.esm.js +1 -1
  133. package/dist/src/index.d.ts +2 -1
  134. package/dist/src/index.js +2 -1
  135. package/dist/src/index.js.map +1 -1
  136. package/dist/src/internal/enum.d.ts +21 -0
  137. package/dist/src/internal/enum.js +23 -1
  138. package/dist/src/internal/enum.js.map +1 -1
  139. package/dist/src/nile-floating-panel/index.js.map +1 -1
  140. package/dist/src/nile-floating-panel/nile-floating-panel.css.d.ts +1 -1
  141. package/dist/src/nile-floating-panel/nile-floating-panel.css.js +147 -20
  142. package/dist/src/nile-floating-panel/nile-floating-panel.css.js.map +1 -1
  143. package/dist/src/nile-floating-panel/nile-floating-panel.d.ts +92 -24
  144. package/dist/src/nile-floating-panel/nile-floating-panel.js +489 -159
  145. package/dist/src/nile-floating-panel/nile-floating-panel.js.map +1 -1
  146. package/dist/src/nile-icon/icons/svg/folder_delete.d.ts +5 -0
  147. package/dist/src/nile-icon/icons/svg/folder_delete.js +5 -0
  148. package/dist/src/nile-icon/icons/svg/folder_delete.js.map +1 -0
  149. package/dist/src/nile-icon/icons/svg/index.d.ts +1 -0
  150. package/dist/src/nile-icon/icons/svg/index.js +1 -0
  151. package/dist/src/nile-icon/icons/svg/index.js.map +1 -1
  152. package/dist/src/nile-icon/icons/svg/layers-three-02.d.ts +1 -1
  153. package/dist/src/nile-icon/icons/svg/layers-three-02.js +1 -1
  154. package/dist/src/nile-icon/icons/svg/layers-three-02.js.map +1 -1
  155. package/dist/src/nile-otp-input/index.d.ts +1 -0
  156. package/dist/src/nile-otp-input/index.js +2 -0
  157. package/dist/src/nile-otp-input/index.js.map +1 -0
  158. package/dist/src/nile-otp-input/nile-otp-input.css.d.ts +12 -0
  159. package/dist/src/nile-otp-input/nile-otp-input.css.js +269 -0
  160. package/dist/src/nile-otp-input/nile-otp-input.css.js.map +1 -0
  161. package/dist/src/nile-otp-input/nile-otp-input.d.ts +156 -0
  162. package/dist/src/nile-otp-input/nile-otp-input.enum.d.ts +26 -0
  163. package/dist/src/nile-otp-input/nile-otp-input.enum.js +32 -0
  164. package/dist/src/nile-otp-input/nile-otp-input.enum.js.map +1 -0
  165. package/dist/src/nile-otp-input/nile-otp-input.js +762 -0
  166. package/dist/src/nile-otp-input/nile-otp-input.js.map +1 -0
  167. package/dist/src/nile-otp-input/nile-otp-input.test.d.ts +1 -0
  168. package/dist/src/nile-otp-input/nile-otp-input.test.js +493 -0
  169. package/dist/src/nile-otp-input/nile-otp-input.test.js.map +1 -0
  170. package/dist/src/version.js +2 -2
  171. package/dist/src/version.js.map +1 -1
  172. package/dist/tippy.esm-57628c2b.esm.js +1 -0
  173. package/dist/tippy.esm-78baa8f2.cjs.js +2 -0
  174. package/dist/tippy.esm-78baa8f2.cjs.js.map +1 -0
  175. package/dist/tsconfig.tsbuildinfo +1 -1
  176. package/package.json +5 -3
  177. package/plop-templates/lit/index.ts.hbs +1 -1
  178. package/plop-templates/lit/lit.css.ts.hbs +1 -1
  179. package/plop-templates/lit/lit.ts.hbs +1 -1
  180. package/src/index.ts +3 -2
  181. package/src/internal/enum.ts +23 -1
  182. package/src/nile-floating-panel/index.ts +0 -1
  183. package/src/nile-floating-panel/nile-floating-panel.css.ts +149 -21
  184. package/src/nile-floating-panel/nile-floating-panel.ts +498 -190
  185. package/src/nile-icon/icons/svg/folder_delete.ts +5 -0
  186. package/src/nile-icon/icons/svg/index.ts +1 -0
  187. package/src/nile-icon/icons/svg/layers-three-02.ts +1 -1
  188. package/src/nile-otp-input/index.ts +1 -0
  189. package/src/nile-otp-input/nile-otp-input.css.ts +271 -0
  190. package/src/nile-otp-input/nile-otp-input.enum.ts +30 -0
  191. package/src/nile-otp-input/nile-otp-input.test.ts +732 -0
  192. package/src/nile-otp-input/nile-otp-input.ts +835 -0
  193. package/vscode-html-custom-data.json +383 -23
  194. package/dist/nile-floating-panel/anchor-manager.cjs.js +0 -2
  195. package/dist/nile-floating-panel/anchor-manager.cjs.js.map +0 -1
  196. package/dist/nile-floating-panel/anchor-manager.esm.js +0 -1
  197. package/dist/nile-floating-panel/content-manager.cjs.js +0 -2
  198. package/dist/nile-floating-panel/content-manager.cjs.js.map +0 -1
  199. package/dist/nile-floating-panel/content-manager.esm.js +0 -1
  200. package/dist/nile-floating-panel/event-manager.cjs.js +0 -2
  201. package/dist/nile-floating-panel/event-manager.cjs.js.map +0 -1
  202. package/dist/nile-floating-panel/event-manager.esm.js +0 -1
  203. package/dist/nile-floating-panel/position-manager.cjs.js +0 -2
  204. package/dist/nile-floating-panel/position-manager.cjs.js.map +0 -1
  205. package/dist/nile-floating-panel/position-manager.esm.js +0 -1
  206. package/dist/nile-floating-panel/style-manager.cjs.js +0 -2
  207. package/dist/nile-floating-panel/style-manager.cjs.js.map +0 -1
  208. package/dist/nile-floating-panel/style-manager.esm.js +0 -1
  209. package/dist/nile-floating-panel/types.cjs.js +0 -2
  210. package/dist/nile-floating-panel/types.cjs.js.map +0 -1
  211. package/dist/nile-floating-panel/types.esm.js +0 -1
  212. package/dist/src/nile-floating-panel/anchor-manager.d.ts +0 -6
  213. package/dist/src/nile-floating-panel/anchor-manager.js +0 -27
  214. package/dist/src/nile-floating-panel/anchor-manager.js.map +0 -1
  215. package/dist/src/nile-floating-panel/content-manager.d.ts +0 -5
  216. package/dist/src/nile-floating-panel/content-manager.js +0 -44
  217. package/dist/src/nile-floating-panel/content-manager.js.map +0 -1
  218. package/dist/src/nile-floating-panel/event-manager.d.ts +0 -14
  219. package/dist/src/nile-floating-panel/event-manager.js +0 -52
  220. package/dist/src/nile-floating-panel/event-manager.js.map +0 -1
  221. package/dist/src/nile-floating-panel/position-manager.d.ts +0 -17
  222. package/dist/src/nile-floating-panel/position-manager.js +0 -72
  223. package/dist/src/nile-floating-panel/position-manager.js.map +0 -1
  224. package/dist/src/nile-floating-panel/style-manager.d.ts +0 -9
  225. package/dist/src/nile-floating-panel/style-manager.js +0 -44
  226. package/dist/src/nile-floating-panel/style-manager.js.map +0 -1
  227. package/dist/src/nile-floating-panel/types.d.ts +0 -11
  228. package/dist/src/nile-floating-panel/types.js +0 -2
  229. package/dist/src/nile-floating-panel/types.js.map +0 -1
  230. package/src/nile-floating-panel/anchor-manager.ts +0 -33
  231. package/src/nile-floating-panel/content-manager.ts +0 -54
  232. package/src/nile-floating-panel/event-manager.ts +0 -74
  233. package/src/nile-floating-panel/position-manager.ts +0 -102
  234. package/src/nile-floating-panel/style-manager.ts +0 -54
  235. package/src/nile-floating-panel/types.ts +0 -15
@@ -1,229 +1,559 @@
1
+ /**
2
+ * Copyright Aquera Inc 2025
3
+ *
4
+ * This source code is licensed under the BSD-3-Clause license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
1
7
  var NileFloatingPanel_1;
2
8
  import { __decorate } from "tslib";
3
- import { html, } from 'lit';
4
9
  import { customElement, property } from 'lit/decorators.js';
5
10
  import { styles } from './nile-floating-panel.css';
6
11
  import NileElement from '../internal/nile-element';
7
- import { PositionManager } from './position-manager';
8
- import { StyleManager } from './style-manager';
9
- import { ContentManager } from './content-manager';
10
- import { AnchorManager } from './anchor-manager';
11
- import { EventManager } from './event-manager';
12
- import { VisibilityManager } from '../utilities/visibility-manager';
12
+ import tippy, { roundArrow, followCursor as followCursorPlugin, } from 'tippy.js';
13
+ import { parseFollowCursor, parseDuration, } from '../nile-lite-tooltip/utils';
14
+ import { VisibilityManager } from '../utilities/visibility-manager.js';
13
15
  /**
14
- * Nile floating panel component.
16
+ * Nile floating-panel component.
17
+ *
18
+ * A popover that supports rich content (title, body, actions).
19
+ *
20
+ * **Wrapper mode** (default): first child element is the trigger.
21
+ * **For mode**: set `for="elementId"` to attach to an external element.
15
22
  *
16
23
  * @tag nile-floating-panel
17
- * @event nile-show - Emitted when the panel opens.
18
- * @event nile-hide - Emitted when the panel closes.
24
+ *
25
+ * @fires nile-init - Component initialized.
26
+ * @fires nile-destroy - Component destroyed.
27
+ * @fires nile-show - Panel opened.
28
+ * @fires nile-hide - Panel closed.
29
+ * @fires nile-after-show - Panel fully visible after animation.
30
+ * @fires nile-after-hide - Panel fully hidden after animation.
31
+ * @fires nile-toggle - Open/close transition (detail.open).
32
+ * @fires nile-visibility-change - Hidden by scroll/tab change.
19
33
  */
20
34
  let NileFloatingPanel = NileFloatingPanel_1 = class NileFloatingPanel extends NileElement {
21
35
  constructor() {
22
36
  super(...arguments);
23
- this.anchor = null;
24
- this.position = 'bottom';
37
+ // ─── Tippy.js props ───
38
+ this.placement = 'bottom';
39
+ this.trigger = 'click';
40
+ this.distance = 12;
41
+ this.skidding = 0;
42
+ this.arrow = 'round';
43
+ this.animation = 'fade';
44
+ this.duration = 200;
45
+ this.delay = 0;
46
+ this.interactive = true;
47
+ this.interactiveBorder = 2;
48
+ this.maxWidth = 'none';
49
+ this.zIndex = 9999;
50
+ this.followCursor = false;
51
+ this.hideOnClick = true;
52
+ this.inertia = false;
53
+ this.allowHTML = false;
54
+ this.flip = true;
55
+ // ─── Popover-like props ───
56
+ this.for = null;
25
57
  this.open = false;
26
- this.closeOnOutsideClick = true;
27
- this.enableVisibilityEffect = true;
58
+ this.preventOverlayClose = false;
59
+ this.title = '';
60
+ this.disabled = false;
61
+ /** When set, only one panel in the same group can be open at a time. */
62
+ this.group = null;
63
+ /** Close the panel when Escape is pressed. */
64
+ this.closeOnEscape = true;
65
+ /** Custom CSS class(es) added to the Tippy popper element, allowing per-instance styling from the host. */
66
+ this.panelClass = '';
67
+ // ─── Visibility manager props ───
68
+ this.enableVisibilityEffect = false;
28
69
  this.enableTabClose = false;
70
+ // ─── Internal state ───
71
+ this.tippyInstance = null;
29
72
  this.panelContainer = null;
30
- this.positionManager = null;
31
- this.styleManager = new StyleManager();
32
- this.eventManager = new EventManager(this);
33
- this.handleSlotChange = () => {
34
- if (this.open && this.panelContainer) {
35
- this.updatePanelContent();
36
- }
37
- };
73
+ this.anchorEl = null;
74
+ this._suppressOpenWatch = false;
75
+ this._panelId = `nile-fp-${Math.random().toString(36).slice(2, 9)}`;
76
+ this._boundEscHandler = this._handleEscapeKey.bind(this);
77
+ this._pendingShowListener = null;
78
+ this._pendingHideListener = null;
79
+ }
80
+ static get prefersReducedMotion() {
81
+ if (!NileFloatingPanel_1._reducedMotionQuery) {
82
+ NileFloatingPanel_1._reducedMotionQuery =
83
+ window.matchMedia('(prefers-reduced-motion: reduce)');
84
+ }
85
+ return NileFloatingPanel_1._reducedMotionQuery.matches;
38
86
  }
39
87
  static get styles() {
40
88
  return [styles];
41
89
  }
42
- connectedCallback() {
43
- super.connectedCallback();
90
+ createRenderRoot() {
91
+ return this;
92
+ }
93
+ // ─── Lifecycle ───
94
+ firstUpdated() {
95
+ this._buildDOM();
96
+ this._attachTippy();
97
+ this._joinGroup();
98
+ this.visibilityManager = new VisibilityManager({
99
+ host: this,
100
+ target: this.anchorEl || null,
101
+ enableVisibilityEffect: this.enableVisibilityEffect,
102
+ enableTabClose: this.enableTabClose,
103
+ isOpen: () => this.open,
104
+ onAnchorOutOfView: () => {
105
+ this._setOpen(false);
106
+ this.tippyInstance?.hide();
107
+ this.emit('nile-visibility-change', {
108
+ visible: false,
109
+ reason: 'anchor-out-of-view',
110
+ });
111
+ },
112
+ onDocumentHidden: () => {
113
+ this._setOpen(false);
114
+ this.tippyInstance?.hide();
115
+ this.emit('nile-visibility-change', {
116
+ visible: false,
117
+ reason: 'document-hidden',
118
+ });
119
+ },
120
+ emit: (event, detail) => this.emit(`nile-${event}`, detail),
121
+ });
122
+ this.emit('nile-init');
44
123
  }
45
124
  disconnectedCallback() {
46
125
  super.disconnectedCallback();
47
- this.cleanupPanel();
126
+ this._cleanupPendingShowListener();
127
+ this._cleanupPendingHideListener();
48
128
  this.visibilityManager?.cleanup();
129
+ this._leaveGroup();
130
+ this._removeEscListener();
131
+ this._destroyTippy();
132
+ this.emit('nile-destroy');
49
133
  }
50
- updated(changedProperties) {
51
- super.updated(changedProperties);
52
- if (changedProperties.has('open')) {
134
+ updated(changed) {
135
+ super.updated(changed);
136
+ if (!this.panelContainer)
137
+ return;
138
+ if (changed.has('open') && !this._suppressOpenWatch) {
53
139
  if (this.open) {
54
- this.emit('nile-show');
55
- this.setupPanel();
56
140
  this.visibilityManager?.setup();
141
+ queueMicrotask(() => this.tippyInstance?.show());
57
142
  }
58
143
  else {
59
- this.emit('nile-hide');
60
144
  this.visibilityManager?.cleanup();
61
- this.cleanupPanel();
145
+ this.tippyInstance?.hide();
62
146
  }
63
147
  }
64
- if (changedProperties.has('closeOnOutsideClick') &&
65
- this.open &&
66
- this.panelContainer) {
67
- this.eventManager.updateOutsideClickHandler(this.panelContainer, this.closeOnOutsideClick, this.open);
68
- }
69
- if (changedProperties.has('anchor') && this.open) {
70
- this.cleanupPanel();
71
- this.setupPanel();
148
+ if (changed.has('group')) {
149
+ this._leaveGroup(changed.get('group'));
150
+ this._joinGroup();
72
151
  }
73
- if ((changedProperties.has('enableVisibilityEffect') ||
74
- changedProperties.has('enableTabClose')) &&
75
- this.open) {
76
- this.setupVisibilityManager();
152
+ const rebuildProps = [
153
+ 'placement', 'trigger', 'distance', 'skidding', 'arrow',
154
+ 'animation', 'duration', 'delay', 'interactive', 'interactiveBorder',
155
+ 'maxWidth', 'zIndex', 'followCursor', 'hideOnClick', 'inertia',
156
+ 'allowHTML', 'flip', 'preventOverlayClose', 'disabled', 'width', 'height',
157
+ 'panelClass'
158
+ ];
159
+ if (rebuildProps.some(p => changed.has(p))) {
160
+ this._attachTippy();
77
161
  }
78
- if (changedProperties.has('position') &&
79
- this.open &&
80
- this.positionManager) {
81
- this.positionManager.updatePosition(this.position);
162
+ }
163
+ // ─── Public API ───
164
+ /** Programmatically shows the panel. Returns a promise that resolves after the show animation. */
165
+ show() {
166
+ this.open = true;
167
+ return new Promise(resolve => {
168
+ this._cleanupPendingShowListener();
169
+ const handler = () => {
170
+ this._pendingShowListener = null;
171
+ resolve();
172
+ };
173
+ this._pendingShowListener = handler;
174
+ this.addEventListener('nile-after-show', handler, { once: true });
175
+ });
176
+ }
177
+ /** Programmatically hides the panel. Returns a promise that resolves after the hide animation. */
178
+ hide() {
179
+ this.open = false;
180
+ return new Promise(resolve => {
181
+ this._cleanupPendingHideListener();
182
+ const handler = () => {
183
+ this._pendingHideListener = null;
184
+ resolve();
185
+ };
186
+ this._pendingHideListener = handler;
187
+ this.addEventListener('nile-after-hide', handler, { once: true });
188
+ });
189
+ }
190
+ _cleanupPendingShowListener() {
191
+ if (this._pendingShowListener) {
192
+ this.removeEventListener('nile-after-show', this._pendingShowListener);
193
+ this._pendingShowListener = null;
82
194
  }
83
- if (changedProperties.has('open') && this.open && this.panelContainer) {
84
- this.updatePanelContent();
195
+ }
196
+ _cleanupPendingHideListener() {
197
+ if (this._pendingHideListener) {
198
+ this.removeEventListener('nile-after-hide', this._pendingHideListener);
199
+ this._pendingHideListener = null;
85
200
  }
86
201
  }
87
- setupPanel() {
88
- if (this.panelContainer) {
202
+ toggle() {
203
+ this.open = !this.open;
204
+ }
205
+ refresh() {
206
+ this._attachTippy();
207
+ }
208
+ /** Returns the current resolved placement from Tippy/Popper. */
209
+ getCurrentPlacement() {
210
+ const popper = this.tippyInstance?.popper;
211
+ const box = popper?.querySelector('.tippy-box');
212
+ return box?.dataset.placement ?? this.placement;
213
+ }
214
+ /** Returns true if the resolved placement matches the requested placement. */
215
+ isPositioningOptimal() {
216
+ return this.getCurrentPlacement() === this.placement;
217
+ }
218
+ // ─── Group management ───
219
+ _joinGroup() {
220
+ if (!this.group)
89
221
  return;
222
+ let set = NileFloatingPanel_1._groups.get(this.group);
223
+ if (!set) {
224
+ set = new Set();
225
+ NileFloatingPanel_1._groups.set(this.group, set);
90
226
  }
91
- const componentStyles = this.constructor
92
- .styles;
93
- if (componentStyles) {
94
- this.styleManager.injectStyles(componentStyles);
95
- }
96
- this.panelContainer = document.createElement('div');
97
- this.panelContainer.setAttribute('part', 'panel');
98
- this.panelContainer.className = 'nile-floating-panel__container';
99
- this.updatePanelContent();
100
- const anchorElement = AnchorManager.resolveAnchor(this.anchor);
101
- AnchorManager.appendToAnchor(anchorElement, this.panelContainer);
102
- requestAnimationFrame(() => {
103
- this.setupPositionManager();
104
- this.setupEventHandlers();
105
- this.setupVisibilityManager();
106
- });
227
+ set.add(this);
107
228
  }
108
- setupEventHandlers() {
109
- if (!this.panelContainer) {
229
+ _leaveGroup(oldGroup) {
230
+ const key = oldGroup ?? this.group;
231
+ if (!key)
110
232
  return;
233
+ const set = NileFloatingPanel_1._groups.get(key);
234
+ if (set) {
235
+ set.delete(this);
236
+ if (set.size === 0)
237
+ NileFloatingPanel_1._groups.delete(key);
111
238
  }
112
- this.eventManager.setupOutsideClickHandler(this.panelContainer, this.closeOnOutsideClick, this.open, () => {
113
- this.open = false;
239
+ }
240
+ _hideGroupSiblings() {
241
+ if (!this.group)
242
+ return;
243
+ const set = NileFloatingPanel_1._groups.get(this.group);
244
+ if (!set)
245
+ return;
246
+ set.forEach(panel => {
247
+ if (panel !== this && panel.open) {
248
+ panel._setOpen(false);
249
+ panel.tippyInstance?.hide();
250
+ }
114
251
  });
115
252
  }
116
- setupPositionManager() {
117
- if (!this.panelContainer) {
253
+ // ─── Escape key ───
254
+ _addEscListener() {
255
+ if (this.closeOnEscape) {
256
+ document.addEventListener('keydown', this._boundEscHandler);
257
+ }
258
+ }
259
+ _removeEscListener() {
260
+ document.removeEventListener('keydown', this._boundEscHandler);
261
+ }
262
+ _handleEscapeKey(e) {
263
+ if (e.key === 'Escape' && this.open) {
264
+ this._setOpen(false);
265
+ this.tippyInstance?.hide();
266
+ }
267
+ }
268
+ // ─── ARIA ───
269
+ _applyAria() {
270
+ if (!this.anchorEl || !this.panelContainer)
118
271
  return;
272
+ this.panelContainer.setAttribute('role', 'dialog');
273
+ this.panelContainer.id = this._panelId;
274
+ this.anchorEl.setAttribute('aria-haspopup', 'dialog');
275
+ this._syncAriaExpanded();
276
+ }
277
+ _syncAriaExpanded() {
278
+ this.anchorEl?.setAttribute('aria-expanded', String(this.open));
279
+ if (this.open) {
280
+ this.anchorEl?.setAttribute('aria-describedby', this._panelId);
119
281
  }
120
- const referenceElement = this.findTriggerElement() || this;
121
- this.positionManager = new PositionManager(referenceElement, this.panelContainer, this.position);
122
- this.positionManager.reposition();
123
- this.positionManager.setupAutoUpdate();
124
- }
125
- findTriggerElement() {
126
- // Try to find the next sibling element as the trigger
127
- let nextSibling = this.nextElementSibling;
128
- while (nextSibling) {
129
- if (nextSibling instanceof HTMLElement) {
130
- return nextSibling;
282
+ else {
283
+ this.anchorEl?.removeAttribute('aria-describedby');
284
+ }
285
+ }
286
+ // ─── DOM construction ───
287
+ _buildDOM() {
288
+ const children = Array.from(this.childNodes);
289
+ this.anchorEl = null;
290
+ const titleNodes = [];
291
+ const actionNodes = [];
292
+ const bodyNodes = [];
293
+ let firstElementSeen = false;
294
+ for (const child of children) {
295
+ if (child instanceof HTMLElement) {
296
+ const slot = child.getAttribute('slot');
297
+ if (slot === 'title') {
298
+ child.removeAttribute('slot');
299
+ titleNodes.push(child);
300
+ continue;
301
+ }
302
+ if (slot === 'action') {
303
+ child.removeAttribute('slot');
304
+ actionNodes.push(child);
305
+ continue;
306
+ }
307
+ if (!firstElementSeen && !this.for) {
308
+ this.anchorEl = child;
309
+ firstElementSeen = true;
310
+ continue;
311
+ }
131
312
  }
132
- nextSibling = nextSibling.nextElementSibling;
313
+ bodyNodes.push(child);
133
314
  }
134
- // Try to find the previous sibling element
135
- let previousSibling = this.previousElementSibling;
136
- while (previousSibling) {
137
- if (previousSibling instanceof HTMLElement) {
138
- return previousSibling;
315
+ if (this.for) {
316
+ const anchor = document.getElementById(this.for);
317
+ if (anchor) {
318
+ this.anchorEl = anchor;
139
319
  }
140
- previousSibling = previousSibling.previousElementSibling;
141
320
  }
142
- return null;
143
- }
144
- setupVisibilityManager() {
145
- if (!this.enableVisibilityEffect) {
146
- return;
321
+ while (this.firstChild) {
322
+ this.removeChild(this.firstChild);
147
323
  }
148
- const triggerElement = this.findTriggerElement();
149
- // Cleanup existing visibility manager if it exists
150
- if (this.visibilityManager) {
151
- this.visibilityManager.cleanup();
324
+ if (this.anchorEl && !this.for) {
325
+ this.appendChild(this.anchorEl);
152
326
  }
153
- this.visibilityManager = new VisibilityManager({
154
- host: this,
155
- target: triggerElement || null,
156
- enableVisibilityEffect: this.enableVisibilityEffect,
157
- enableTabClose: this.enableTabClose,
158
- isOpen: () => this.open,
159
- onAnchorOutOfView: () => {
160
- this.open = false;
161
- this.emit('nile-visibility-change', {
162
- visible: false,
163
- reason: 'anchor-out-of-view',
164
- });
165
- },
166
- onDocumentHidden: () => {
167
- this.open = false;
168
- this.emit('nile-visibility-change', {
169
- visible: false,
170
- reason: 'document-hidden',
171
- });
172
- },
173
- emit: (event, detail) => this.emit(`nile-${event}`, detail),
174
- });
175
- if (this.open) {
176
- this.visibilityManager.setup();
327
+ this.panelContainer = document.createElement('div');
328
+ this.panelContainer.className = 'nile-floating-panel__content';
329
+ this.panelContainer.style.display = 'none';
330
+ const body = document.createElement('div');
331
+ body.className = 'nile-floating-panel__body';
332
+ if (titleNodes.length > 0 || this.title) {
333
+ const titleDiv = document.createElement('div');
334
+ titleDiv.className = 'nile-floating-panel__title';
335
+ if (this.title) {
336
+ titleDiv.textContent = this.title;
337
+ }
338
+ else {
339
+ titleNodes.forEach(n => titleDiv.appendChild(n));
340
+ }
341
+ body.appendChild(titleDiv);
342
+ }
343
+ if (bodyNodes.length > 0) {
344
+ const mainDiv = document.createElement('div');
345
+ mainDiv.className = 'nile-floating-panel__main';
346
+ bodyNodes.forEach(n => mainDiv.appendChild(n));
347
+ body.appendChild(mainDiv);
348
+ }
349
+ if (actionNodes.length > 0) {
350
+ const actionDiv = document.createElement('div');
351
+ actionDiv.className = 'nile-floating-panel__action';
352
+ actionNodes.forEach(n => actionDiv.appendChild(n));
353
+ body.appendChild(actionDiv);
177
354
  }
355
+ this.panelContainer.appendChild(body);
356
+ this.appendChild(this.panelContainer);
357
+ this._applyAria();
178
358
  }
179
- updatePanelContent() {
180
- if (!this.panelContainer) {
181
- return;
359
+ // ─── Tippy management ───
360
+ _resolveArrow() {
361
+ switch (this.arrow) {
362
+ case 'round': return roundArrow;
363
+ case 'none': return false;
364
+ default: return true;
182
365
  }
183
- const slot = this.shadowRoot?.querySelector('slot') || null;
184
- ContentManager.updatePanelContent(this.panelContainer, slot, '');
185
366
  }
186
- reposition() {
187
- if (this.positionManager) {
188
- this.positionManager.reposition();
367
+ _setOpen(value) {
368
+ this._suppressOpenWatch = true;
369
+ this.open = value;
370
+ this._syncAriaExpanded();
371
+ this._suppressOpenWatch = false;
372
+ }
373
+ _getEffectiveDuration() {
374
+ if (NileFloatingPanel_1.prefersReducedMotion)
375
+ return 0;
376
+ return parseDuration(this.duration);
377
+ }
378
+ _getEffectiveAnimation() {
379
+ if (NileFloatingPanel_1.prefersReducedMotion)
380
+ return false;
381
+ return this.animation;
382
+ }
383
+ _attachTippy() {
384
+ this._destroyTippy();
385
+ if (this.disabled || !this.anchorEl || !this.panelContainer)
386
+ return;
387
+ const resolvedFollowCursor = parseFollowCursor(this.followCursor);
388
+ const effectiveHideOnClick = this.preventOverlayClose ? false : this.hideOnClick;
389
+ const options = {
390
+ content: this.panelContainer,
391
+ placement: this.placement,
392
+ trigger: this.trigger,
393
+ offset: [this.skidding, this.distance],
394
+ theme: 'floating-panel',
395
+ animation: this._getEffectiveAnimation(),
396
+ interactive: this.interactive,
397
+ arrow: this._resolveArrow(),
398
+ duration: this._getEffectiveDuration(),
399
+ allowHTML: this.allowHTML,
400
+ delay: this.delay,
401
+ maxWidth: this.maxWidth,
402
+ zIndex: this.zIndex,
403
+ hideOnClick: effectiveHideOnClick,
404
+ inertia: NileFloatingPanel_1.prefersReducedMotion ? false : this.inertia,
405
+ interactiveBorder: this.interactiveBorder,
406
+ appendTo: document.body,
407
+ followCursor: resolvedFollowCursor,
408
+ plugins: resolvedFollowCursor ? [followCursorPlugin] : [],
409
+ popperOptions: {
410
+ modifiers: [{ name: 'flip', enabled: this.flip }],
411
+ },
412
+ onMount: (instance) => {
413
+ if (this.panelContainer)
414
+ this.panelContainer.style.display = '';
415
+ if (this.panelClass) {
416
+ this.panelClass.split(/\s+/).filter(Boolean).forEach(cls => {
417
+ instance.popper.classList.add(cls);
418
+ });
419
+ }
420
+ },
421
+ onShow: (instance) => {
422
+ if (this.panelContainer)
423
+ this.panelContainer.style.display = '';
424
+ const tc = instance.popper.querySelector('.tippy-content');
425
+ if (tc) {
426
+ if (this.width)
427
+ tc.style.width = this.width;
428
+ if (this.height) {
429
+ tc.style.height = this.height;
430
+ tc.style.overflow = 'auto';
431
+ }
432
+ }
433
+ this._hideGroupSiblings();
434
+ this._setOpen(true);
435
+ this._addEscListener();
436
+ this.dispatchEvent(new CustomEvent('nile-show', { detail: { instance, target: instance.reference } }));
437
+ this.dispatchEvent(new CustomEvent('nile-toggle', { detail: { open: true, instance, target: instance.reference } }));
438
+ return undefined;
439
+ },
440
+ onShown: (instance) => {
441
+ this.dispatchEvent(new CustomEvent('nile-after-show', { detail: { instance, target: instance.reference } }));
442
+ },
443
+ onHide: (instance) => {
444
+ this._setOpen(false);
445
+ this._removeEscListener();
446
+ this.dispatchEvent(new CustomEvent('nile-hide', { detail: { instance, target: instance.reference } }));
447
+ this.dispatchEvent(new CustomEvent('nile-toggle', { detail: { open: false, instance, target: instance.reference } }));
448
+ return undefined;
449
+ },
450
+ onHidden: (instance) => {
451
+ if (this.panelContainer)
452
+ this.panelContainer.style.display = 'none';
453
+ this.dispatchEvent(new CustomEvent('nile-after-hide', { detail: { instance, target: instance.reference } }));
454
+ },
455
+ };
456
+ this.tippyInstance = tippy(this.anchorEl, options);
457
+ if (this.open) {
458
+ queueMicrotask(() => this.tippyInstance?.show());
189
459
  }
190
460
  }
191
- cleanupPanel() {
192
- this.eventManager.destroy();
193
- if (this.positionManager) {
194
- this.positionManager.destroy();
195
- this.positionManager = null;
461
+ _destroyTippy() {
462
+ if (this.tippyInstance) {
463
+ this.tippyInstance.destroy();
464
+ this.tippyInstance = null;
196
465
  }
197
466
  if (this.panelContainer) {
198
- AnchorManager.removeFromAnchor(this.panelContainer);
467
+ this.panelContainer.style.display = 'none';
468
+ if (this.panelContainer.parentElement !== this) {
469
+ this.appendChild(this.panelContainer);
470
+ }
199
471
  }
200
- this.panelContainer = null;
201
- this.styleManager.cleanupStyles();
202
- }
203
- render() {
204
- return html ` <slot @slotchange=${this.handleSlotChange}></slot> `;
205
472
  }
206
473
  };
474
+ NileFloatingPanel._groups = new Map();
475
+ NileFloatingPanel._reducedMotionQuery = null;
476
+ __decorate([
477
+ property({ type: String })
478
+ ], NileFloatingPanel.prototype, "placement", void 0);
479
+ __decorate([
480
+ property({ type: String })
481
+ ], NileFloatingPanel.prototype, "trigger", void 0);
482
+ __decorate([
483
+ property({ type: Number })
484
+ ], NileFloatingPanel.prototype, "distance", void 0);
485
+ __decorate([
486
+ property({ type: Number })
487
+ ], NileFloatingPanel.prototype, "skidding", void 0);
488
+ __decorate([
489
+ property({ type: String, reflect: true })
490
+ ], NileFloatingPanel.prototype, "arrow", void 0);
491
+ __decorate([
492
+ property({ type: String, reflect: true })
493
+ ], NileFloatingPanel.prototype, "animation", void 0);
494
+ __decorate([
495
+ property({ type: String, reflect: true })
496
+ ], NileFloatingPanel.prototype, "duration", void 0);
497
+ __decorate([
498
+ property({ type: String, reflect: true })
499
+ ], NileFloatingPanel.prototype, "delay", void 0);
500
+ __decorate([
501
+ property({ type: Boolean, reflect: true })
502
+ ], NileFloatingPanel.prototype, "interactive", void 0);
503
+ __decorate([
504
+ property({ type: Number, reflect: true })
505
+ ], NileFloatingPanel.prototype, "interactiveBorder", void 0);
506
+ __decorate([
507
+ property({ type: String, reflect: true })
508
+ ], NileFloatingPanel.prototype, "maxWidth", void 0);
509
+ __decorate([
510
+ property({ type: Number, reflect: true })
511
+ ], NileFloatingPanel.prototype, "zIndex", void 0);
512
+ __decorate([
513
+ property({ type: String, reflect: true })
514
+ ], NileFloatingPanel.prototype, "followCursor", void 0);
515
+ __decorate([
516
+ property({ type: Boolean, reflect: true })
517
+ ], NileFloatingPanel.prototype, "hideOnClick", void 0);
207
518
  __decorate([
208
- property()
209
- ], NileFloatingPanel.prototype, "anchor", void 0);
519
+ property({ type: Boolean, reflect: true })
520
+ ], NileFloatingPanel.prototype, "inertia", void 0);
210
521
  __decorate([
211
- property()
212
- ], NileFloatingPanel.prototype, "position", void 0);
522
+ property({ type: Boolean, reflect: true })
523
+ ], NileFloatingPanel.prototype, "allowHTML", void 0);
524
+ __decorate([
525
+ property({ type: Boolean, reflect: true })
526
+ ], NileFloatingPanel.prototype, "flip", void 0);
213
527
  __decorate([
214
- property({ type: Boolean, reflect: true, attribute: true })
528
+ property({ type: String, attribute: 'for' })
529
+ ], NileFloatingPanel.prototype, "for", void 0);
530
+ __decorate([
531
+ property({ type: Boolean, reflect: true })
215
532
  ], NileFloatingPanel.prototype, "open", void 0);
216
533
  __decorate([
217
- property({
218
- type: Boolean,
219
- reflect: true,
220
- attribute: 'close-on-outside-click',
221
- converter: {
222
- fromAttribute: (value) => (!value || value === 'false' ? false : true),
223
- toAttribute: (value) => (value ? 'true' : 'false'),
224
- },
225
- })
226
- ], NileFloatingPanel.prototype, "closeOnOutsideClick", void 0);
534
+ property({ type: Boolean, reflect: true })
535
+ ], NileFloatingPanel.prototype, "preventOverlayClose", void 0);
536
+ __decorate([
537
+ property({ type: String, reflect: true })
538
+ ], NileFloatingPanel.prototype, "title", void 0);
539
+ __decorate([
540
+ property({ type: Boolean, reflect: true })
541
+ ], NileFloatingPanel.prototype, "disabled", void 0);
542
+ __decorate([
543
+ property({ type: String, reflect: true })
544
+ ], NileFloatingPanel.prototype, "width", void 0);
545
+ __decorate([
546
+ property({ type: String, reflect: true })
547
+ ], NileFloatingPanel.prototype, "height", void 0);
548
+ __decorate([
549
+ property({ type: String, reflect: true })
550
+ ], NileFloatingPanel.prototype, "group", void 0);
551
+ __decorate([
552
+ property({ type: Boolean, reflect: true })
553
+ ], NileFloatingPanel.prototype, "closeOnEscape", void 0);
554
+ __decorate([
555
+ property({ type: String, reflect: true, attribute: true })
556
+ ], NileFloatingPanel.prototype, "panelClass", void 0);
227
557
  __decorate([
228
558
  property({ type: Boolean, reflect: true })
229
559
  ], NileFloatingPanel.prototype, "enableVisibilityEffect", void 0);