@nova-design-system/nova-webcomponents 3.0.0-beta.28 → 3.0.0-beta.30

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 (228) hide show
  1. package/dist/blazor-docs.json +1345 -174
  2. package/dist/cjs/index-c50face0.js +14 -14
  3. package/dist/cjs/loader.cjs.js +1 -1
  4. package/dist/cjs/native.cjs.js +1 -1
  5. package/dist/cjs/{nv-badge.cjs.entry.js → nv-badge_2.cjs.entry.js} +44 -4
  6. package/dist/cjs/nv-badge_2.cjs.entry.js.map +1 -0
  7. package/dist/cjs/nv-fieldmultiselect.cjs.entry.js +1038 -0
  8. package/dist/cjs/nv-fieldmultiselect.cjs.entry.js.map +1 -0
  9. package/dist/cjs/nv-fieldnumber.cjs.entry.js +3 -3
  10. package/dist/cjs/nv-fieldpassword.cjs.entry.js +3 -3
  11. package/dist/cjs/nv-fieldradio.cjs.entry.js +3 -3
  12. package/dist/cjs/nv-fieldselect.cjs.entry.js +5 -5
  13. package/dist/cjs/nv-fieldtext.cjs.entry.js +3 -3
  14. package/dist/cjs/nv-fieldtextarea.cjs.entry.js +3 -3
  15. package/dist/cjs/nv-fieldtoggle.cjs.entry.js +2 -2
  16. package/dist/cjs/nv-icon.cjs.entry.js +1 -1
  17. package/dist/cjs/{nv-iconbutton.cjs.entry.js → nv-iconbutton_2.cjs.entry.js} +22 -2
  18. package/dist/cjs/nv-iconbutton_2.cjs.entry.js.map +1 -0
  19. package/dist/cjs/nv-menu.cjs.entry.js +1 -1
  20. package/dist/cjs/nv-popover.cjs.entry.js +1 -1
  21. package/dist/cjs/nv-row.cjs.entry.js +1 -1
  22. package/dist/cjs/nv-stack.cjs.entry.js +1 -1
  23. package/dist/cjs/nv-table.cjs.entry.js +2 -2
  24. package/dist/cjs/nv-tablebody.cjs.entry.js +1 -1
  25. package/dist/cjs/nv-tablecolumn.cjs.entry.js +1 -1
  26. package/dist/cjs/nv-tabledatacell.cjs.entry.js +1 -1
  27. package/dist/cjs/nv-tablehead.cjs.entry.js +1 -1
  28. package/dist/cjs/nv-tablerow.cjs.entry.js +1 -1
  29. package/dist/cjs/nv-tooltip.cjs.entry.js +1 -1
  30. package/dist/collection/collection-manifest.json +2 -0
  31. package/dist/collection/components/nv-badge/nv-badge.css +70 -0
  32. package/dist/collection/components/nv-badge/nv-badge.docs.js +1 -1
  33. package/dist/collection/components/nv-badge/nv-badge.docs.js.map +1 -1
  34. package/dist/collection/components/nv-badge/nv-badge.js +3 -3
  35. package/dist/collection/components/nv-badge/nv-badge.js.map +1 -1
  36. package/dist/collection/components/nv-fielddropdownitemcheck/nv-fielddropdownitemcheck.css +12 -0
  37. package/dist/collection/components/nv-fielddropdownitemcheck/nv-fielddropdownitemcheck.docs.js +6 -0
  38. package/dist/collection/components/nv-fielddropdownitemcheck/nv-fielddropdownitemcheck.docs.js.map +1 -0
  39. package/dist/collection/components/nv-fielddropdownitemcheck/nv-fielddropdownitemcheck.js +171 -0
  40. package/dist/collection/components/nv-fielddropdownitemcheck/nv-fielddropdownitemcheck.js.map +1 -0
  41. package/dist/collection/components/nv-fieldmultiselect/nv-fieldmultiselect.css +201 -0
  42. package/dist/collection/components/nv-fieldmultiselect/nv-fieldmultiselect.docs.js +257 -0
  43. package/dist/collection/components/nv-fieldmultiselect/nv-fieldmultiselect.docs.js.map +1 -0
  44. package/dist/collection/components/nv-fieldmultiselect/nv-fieldmultiselect.js +1578 -0
  45. package/dist/collection/components/nv-fieldmultiselect/nv-fieldmultiselect.js.map +1 -0
  46. package/dist/collection/components/nv-fieldnumber/nv-fieldnumber.js +3 -3
  47. package/dist/collection/components/nv-fieldpassword/nv-fieldpassword.js +3 -3
  48. package/dist/collection/components/nv-fieldradio/nv-fieldradio.js +3 -3
  49. package/dist/collection/components/nv-fieldselect/nv-fieldselect.js +5 -5
  50. package/dist/collection/components/nv-fieldtext/nv-fieldtext.js +3 -3
  51. package/dist/collection/components/nv-fieldtextarea/nv-fieldtextarea.js +3 -3
  52. package/dist/collection/components/nv-fieldtoggle/nv-fieldtoggle.js +2 -2
  53. package/dist/collection/components/nv-icon/nv-icon.js +1 -1
  54. package/dist/collection/components/nv-iconbutton/nv-iconbutton.js +1 -1
  55. package/dist/collection/components/nv-loader/nv-loader.js +1 -1
  56. package/dist/collection/components/nv-menu/nv-menu.js +1 -1
  57. package/dist/collection/components/nv-popover/nv-popover.js +1 -1
  58. package/dist/collection/components/nv-row/nv-row.js +1 -1
  59. package/dist/collection/components/nv-stack/nv-stack.js +1 -1
  60. package/dist/collection/components/nv-table/nv-table.js +2 -2
  61. package/dist/collection/components/nv-tablebody/nv-tablebody.js +1 -1
  62. package/dist/collection/components/nv-tablecolumn/nv-tablecolumn.js +1 -1
  63. package/dist/collection/components/nv-tabledatacell/nv-tabledatacell.js +1 -1
  64. package/dist/collection/components/nv-tablehead/nv-tablehead.js +1 -1
  65. package/dist/collection/components/nv-tablerow/nv-tablerow.js +1 -1
  66. package/dist/collection/components/nv-tooltip/nv-tooltip.js +1 -1
  67. package/dist/collection/dev/dev-components.js +1 -1
  68. package/dist/collection/dev/dev-components.js.map +1 -1
  69. package/dist/components/nv-alert.js +1 -1
  70. package/dist/components/nv-avatar.js +1 -1
  71. package/dist/components/nv-badge.js +1 -147
  72. package/dist/components/nv-badge.js.map +1 -1
  73. package/dist/components/nv-button.js +1 -1
  74. package/dist/components/nv-fieldcheckbox.js +1 -121
  75. package/dist/components/nv-fieldcheckbox.js.map +1 -1
  76. package/dist/components/nv-fielddropdown.js +5 -5
  77. package/dist/components/nv-fielddropdownitem.js +1 -1
  78. package/dist/components/nv-fielddropdownitemcheck.d.ts +11 -0
  79. package/dist/components/nv-fielddropdownitemcheck.js +8 -0
  80. package/dist/components/nv-fielddropdownitemcheck.js.map +1 -0
  81. package/dist/components/nv-fieldmultiselect.d.ts +11 -0
  82. package/dist/components/nv-fieldmultiselect.js +1129 -0
  83. package/dist/components/nv-fieldmultiselect.js.map +1 -0
  84. package/dist/components/nv-fieldnumber.js +4 -4
  85. package/dist/components/nv-fieldpassword.js +6 -6
  86. package/dist/components/nv-fieldradio.js +3 -3
  87. package/dist/components/nv-fieldselect.js +6 -6
  88. package/dist/components/nv-fieldtext.js +4 -4
  89. package/dist/components/nv-fieldtextarea.js +3 -3
  90. package/dist/components/nv-fieldtoggle.js +2 -2
  91. package/dist/components/nv-icon.js +1 -1
  92. package/dist/components/nv-iconbutton.js +1 -1
  93. package/dist/components/nv-loader.js +1 -1
  94. package/dist/components/nv-menu.js +2 -2
  95. package/dist/components/nv-menuitem.js +1 -1
  96. package/dist/components/nv-popover.js +1 -1
  97. package/dist/components/nv-row.js +1 -1
  98. package/dist/components/nv-stack.js +1 -1
  99. package/dist/components/nv-table.js +2 -2
  100. package/dist/components/nv-tablebody.js +1 -1
  101. package/dist/components/nv-tablecolumn.js +1 -1
  102. package/dist/components/nv-tabledatacell.js +1 -1
  103. package/dist/components/nv-tablehead.js +1 -1
  104. package/dist/components/nv-tablerow.js +1 -1
  105. package/dist/components/nv-tooltip.js +2 -2
  106. package/dist/components/p-5ce661bd.js +125 -0
  107. package/dist/components/p-5ce661bd.js.map +1 -0
  108. package/dist/components/{p-45c63143.js → p-8bec002e.js} +4 -4
  109. package/dist/components/{p-45c63143.js.map → p-8bec002e.js.map} +1 -1
  110. package/dist/components/{p-8c8cf8ea.js → p-a1aa8970.js} +2 -2
  111. package/dist/components/{p-8c8cf8ea.js.map → p-a1aa8970.js.map} +1 -1
  112. package/dist/{esm/nv-badge.entry.js → components/p-a4802979.js} +51 -15
  113. package/dist/components/p-a4802979.js.map +1 -0
  114. package/dist/components/{p-45405075.js → p-b12abc99.js} +2 -2
  115. package/dist/components/{p-45405075.js.map → p-b12abc99.js.map} +1 -1
  116. package/dist/components/{p-89fb6636.js → p-d5dd3def.js} +2 -2
  117. package/dist/components/{p-89fb6636.js.map → p-d5dd3def.js.map} +1 -1
  118. package/dist/components/{p-689a7b38.js → p-d70df149.js} +2 -2
  119. package/dist/components/{p-689a7b38.js.map → p-d70df149.js.map} +1 -1
  120. package/dist/components/p-e4641c41.js +72 -0
  121. package/dist/components/p-e4641c41.js.map +1 -0
  122. package/dist/docs.json +1326 -171
  123. package/dist/esm/index-e7b35c14.js +14 -14
  124. package/dist/esm/loader.js +1 -1
  125. package/dist/esm/native.js +1 -1
  126. package/dist/esm/nv-badge_2.entry.js +154 -0
  127. package/dist/esm/nv-badge_2.entry.js.map +1 -0
  128. package/dist/esm/nv-fieldmultiselect.entry.js +1034 -0
  129. package/dist/esm/nv-fieldmultiselect.entry.js.map +1 -0
  130. package/dist/esm/nv-fieldnumber.entry.js +3 -3
  131. package/dist/esm/nv-fieldpassword.entry.js +3 -3
  132. package/dist/esm/nv-fieldradio.entry.js +3 -3
  133. package/dist/esm/nv-fieldselect.entry.js +5 -5
  134. package/dist/esm/nv-fieldtext.entry.js +3 -3
  135. package/dist/esm/nv-fieldtextarea.entry.js +3 -3
  136. package/dist/esm/nv-fieldtoggle.entry.js +2 -2
  137. package/dist/esm/nv-icon.entry.js +1 -1
  138. package/dist/esm/{nv-iconbutton.entry.js → nv-iconbutton_2.entry.js} +22 -3
  139. package/dist/esm/nv-iconbutton_2.entry.js.map +1 -0
  140. package/dist/esm/nv-menu.entry.js +1 -1
  141. package/dist/esm/nv-popover.entry.js +1 -1
  142. package/dist/esm/nv-row.entry.js +1 -1
  143. package/dist/esm/nv-stack.entry.js +1 -1
  144. package/dist/esm/nv-table.entry.js +2 -2
  145. package/dist/esm/nv-tablebody.entry.js +1 -1
  146. package/dist/esm/nv-tablecolumn.entry.js +1 -1
  147. package/dist/esm/nv-tabledatacell.entry.js +1 -1
  148. package/dist/esm/nv-tablehead.entry.js +1 -1
  149. package/dist/esm/nv-tablerow.entry.js +1 -1
  150. package/dist/esm/nv-tooltip.entry.js +1 -1
  151. package/dist/native/native.css +1 -1
  152. package/dist/native/native.esm.js +1 -1
  153. package/dist/native/native.esm.js.map +1 -1
  154. package/dist/native/{p-dbae3920.entry.js → p-0fbb962b.entry.js} +2 -2
  155. package/dist/native/{p-81256924.entry.js → p-12eaebd6.entry.js} +2 -2
  156. package/dist/native/p-1c689ec7.entry.js +2 -0
  157. package/dist/native/{p-bdab3562.entry.js → p-305951e4.entry.js} +2 -2
  158. package/dist/native/p-306d1f04.entry.js +2 -0
  159. package/dist/native/p-306d1f04.entry.js.map +1 -0
  160. package/dist/native/{p-de6e0e1f.entry.js → p-3f912745.entry.js} +2 -2
  161. package/dist/native/p-589eb477.entry.js +2 -0
  162. package/dist/native/{p-e2df46e2.entry.js → p-5b4bdbe2.entry.js} +2 -2
  163. package/dist/native/{p-75b5fdce.entry.js → p-65ad60eb.entry.js} +2 -2
  164. package/dist/native/{p-ea4092a7.entry.js → p-7b2d8b8c.entry.js} +2 -2
  165. package/dist/native/{p-c1c661a0.entry.js → p-7b3a4cbf.entry.js} +2 -2
  166. package/dist/native/{p-38817aa3.entry.js → p-91d30cd7.entry.js} +2 -2
  167. package/dist/native/{p-c4f7e36d.entry.js → p-92e3e334.entry.js} +2 -2
  168. package/dist/native/{p-1edb76e1.entry.js → p-a03df637.entry.js} +2 -2
  169. package/dist/native/p-a5582014.entry.js +2 -0
  170. package/dist/native/p-a5582014.entry.js.map +1 -0
  171. package/dist/native/p-a7a3c45f.entry.js +2 -0
  172. package/dist/native/p-a7be7540.entry.js +2 -0
  173. package/dist/native/p-a7be7540.entry.js.map +1 -0
  174. package/dist/native/p-a8c0fefa.entry.js +2 -0
  175. package/dist/native/{p-99850272.entry.js.map → p-a8c0fefa.entry.js.map} +1 -1
  176. package/dist/native/{p-808cf007.entry.js → p-c8f36510.entry.js} +2 -2
  177. package/dist/native/p-d3d682a7.entry.js +2 -0
  178. package/dist/native/p-d4c0a1e0.entry.js +2 -0
  179. package/dist/native/{p-844f4878.entry.js → p-dbade286.entry.js} +2 -2
  180. package/dist/types/components/nv-badge/nv-badge.d.ts +1 -1
  181. package/dist/types/components/nv-fielddropdownitemcheck/nv-fielddropdownitemcheck.d.ts +52 -0
  182. package/dist/types/components/nv-fielddropdownitemcheck/nv-fielddropdownitemcheck.docs.d.ts +4 -0
  183. package/dist/types/components/nv-fieldmultiselect/nv-fieldmultiselect.d.ts +405 -0
  184. package/dist/types/components/nv-fieldmultiselect/nv-fieldmultiselect.docs.d.ts +4 -0
  185. package/dist/types/components.d.ts +331 -2
  186. package/dist/vscode-data.json +325 -1
  187. package/hydrate/index.js +1171 -40
  188. package/hydrate/index.mjs +1171 -40
  189. package/package.json +7 -2
  190. package/readme.md +5 -1
  191. package/dist/cjs/nv-badge.cjs.entry.js.map +0 -1
  192. package/dist/cjs/nv-iconbutton.cjs.entry.js.map +0 -1
  193. package/dist/cjs/nv-loader.cjs.entry.js +0 -29
  194. package/dist/cjs/nv-loader.cjs.entry.js.map +0 -1
  195. package/dist/esm/nv-badge.entry.js.map +0 -1
  196. package/dist/esm/nv-iconbutton.entry.js.map +0 -1
  197. package/dist/esm/nv-loader.entry.js +0 -25
  198. package/dist/esm/nv-loader.entry.js.map +0 -1
  199. package/dist/native/p-01be802d.entry.js +0 -2
  200. package/dist/native/p-0cfe2048.entry.js +0 -2
  201. package/dist/native/p-0cfe2048.entry.js.map +0 -1
  202. package/dist/native/p-28cf537b.entry.js +0 -2
  203. package/dist/native/p-4b926563.entry.js +0 -2
  204. package/dist/native/p-861f91d3.entry.js +0 -2
  205. package/dist/native/p-9221f72a.entry.js +0 -2
  206. package/dist/native/p-99850272.entry.js +0 -2
  207. package/dist/native/p-dba9c57c.entry.js +0 -2
  208. package/dist/native/p-dba9c57c.entry.js.map +0 -1
  209. package/dist/native/p-ed893068.entry.js +0 -2
  210. package/dist/native/p-ed893068.entry.js.map +0 -1
  211. /package/dist/native/{p-dbae3920.entry.js.map → p-0fbb962b.entry.js.map} +0 -0
  212. /package/dist/native/{p-81256924.entry.js.map → p-12eaebd6.entry.js.map} +0 -0
  213. /package/dist/native/{p-4b926563.entry.js.map → p-1c689ec7.entry.js.map} +0 -0
  214. /package/dist/native/{p-bdab3562.entry.js.map → p-305951e4.entry.js.map} +0 -0
  215. /package/dist/native/{p-de6e0e1f.entry.js.map → p-3f912745.entry.js.map} +0 -0
  216. /package/dist/native/{p-9221f72a.entry.js.map → p-589eb477.entry.js.map} +0 -0
  217. /package/dist/native/{p-e2df46e2.entry.js.map → p-5b4bdbe2.entry.js.map} +0 -0
  218. /package/dist/native/{p-75b5fdce.entry.js.map → p-65ad60eb.entry.js.map} +0 -0
  219. /package/dist/native/{p-ea4092a7.entry.js.map → p-7b2d8b8c.entry.js.map} +0 -0
  220. /package/dist/native/{p-c1c661a0.entry.js.map → p-7b3a4cbf.entry.js.map} +0 -0
  221. /package/dist/native/{p-38817aa3.entry.js.map → p-91d30cd7.entry.js.map} +0 -0
  222. /package/dist/native/{p-c4f7e36d.entry.js.map → p-92e3e334.entry.js.map} +0 -0
  223. /package/dist/native/{p-1edb76e1.entry.js.map → p-a03df637.entry.js.map} +0 -0
  224. /package/dist/native/{p-01be802d.entry.js.map → p-a7a3c45f.entry.js.map} +0 -0
  225. /package/dist/native/{p-808cf007.entry.js.map → p-c8f36510.entry.js.map} +0 -0
  226. /package/dist/native/{p-28cf537b.entry.js.map → p-d3d682a7.entry.js.map} +0 -0
  227. /package/dist/native/{p-861f91d3.entry.js.map → p-d4c0a1e0.entry.js.map} +0 -0
  228. /package/dist/native/{p-844f4878.entry.js.map → p-dbade286.entry.js.map} +0 -0
@@ -0,0 +1,1038 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ const index = require('./index-c50face0.js');
6
+ const v4 = require('./v4-7014b8b0.js');
7
+
8
+ const nvFieldmultiselectCss = "nv-fieldmultiselect{--nv-field-border-default:var(--components-form-field-border-default);--nv-field-border-hover:var(--components-form-field-border-hover);--nv-field-border-focus:var(--components-form-field-border-focus);--nv-field-border-disabled:var(--components-form-field-border-default);--nv-field-border-readonly:var(--components-form-field-border-default);--nv-field-focus-box-shadow:var(--color-focus-brand);--nv-field-background:var(--components-form-field-background-default);display:flex;flex-direction:column;align-items:flex-start;gap:var(--form-gap-y);box-sizing:border-box}nv-fieldmultiselect[readonly]:not([readonly=false]){--nv-field-border-default:var(--components-form-field-border-readonly);--nv-field-border-hover:var(--nv-field-border-default);--nv-field-border-focus:var(--components-form-field-border-focus);--nv-field-border-disabled:var(--nv-field-border-default);--nv-field-border-readonly:var(--nv-field-border-default);--nv-field-background:var(--components-form-field-background-readonly)}nv-fieldmultiselect[error]:not([error=false]){--nv-field-border-default:var(--components-form-field-border-error);--nv-field-border-hover:var(--nv-field-border-default);--nv-field-border-focus:var(--nv-field-border-default);--nv-field-border-disabled:var(--nv-field-border-default);--nv-field-border-readonly:var(--nv-field-border-default);--nv-field-focus-box-shadow:var(--color-focus-destructive)}nv-fieldmultiselect[required]:not([required=false])>label::after{content:\"*\";color:var(--components-form-text-required);font-weight:700}nv-fieldmultiselect label{display:flex;align-items:center;gap:var(--form-label-gap);align-self:stretch;color:var(--components-form-text-label-default);font-family:\"TT Norms Pro\", sans-serif;font-size:var(--form-label-font-size);font-style:normal;font-weight:500;line-height:var(--form-label-line-height)}nv-fieldmultiselect nv-popover{width:100%;display:block}nv-fieldmultiselect .input-wrapper-multiselect{display:flex;flex-wrap:wrap;gap:var(--form-gap-x);align-items:stretch;align-self:stretch;width:100%}nv-fieldmultiselect .input-container-multiselect{display:flex;flex-grow:1;padding:calc(var(--form-field-padding-y) - 1px) var(--form-field-padding-x);justify-content:center;align-items:center;gap:var(--form-field-gap);align-self:stretch;border-radius:var(--form-field-radius);border-width:1px;border-style:solid;border-color:var(--nv-field-border-default);opacity:var(--components-form-opacity-default);background:var(--nv-field-background);transition:all 150ms ease-out;display:flex;align-items:center;position:relative;width:100%;min-height:40px}nv-fieldmultiselect .input-container-multiselect:hover{border-color:var(--nv-field-border-hover)}nv-fieldmultiselect .input-container-multiselect:focus-within{border-color:var(--nv-field-border-focus);box-shadow:0px 0px 0px var(--focus-field-stroke) var(--nv-field-focus-box-shadow)}nv-fieldmultiselect .input-container-multiselect:has(input:read-only){opacity:0.5;background-color:var(--components-form-field-background-readonly);border-color:var(--nv-field-border-readonly)}nv-fieldmultiselect .input-container-multiselect:has(input:disabled){opacity:0.5;background-color:var(--components-form-field-background-disabled);border-color:var(--nv-field-border-disabled)}nv-fieldmultiselect .input-container-multiselect input,nv-fieldmultiselect .input-container-multiselect p.non-filterable-text{display:flex;align-items:center;flex:1 0 0;overflow:hidden;background-color:transparent;color:var(--components-form-field-content-text);text-overflow:ellipsis;font-size:var(--form-field-font-size);font-style:normal;font-weight:500;line-height:var(--form-field-line-height);width:100%;padding-right:2rem;flex-grow:1;margin:0;min-height:100%;box-sizing:border-box}nv-fieldmultiselect .input-container-multiselect input:focus,nv-fieldmultiselect .input-container-multiselect p.non-filterable-text:focus{outline:none}nv-fieldmultiselect .input-container-multiselect input::placeholder,nv-fieldmultiselect .input-container-multiselect p.non-filterable-text::placeholder{overflow:hidden;color:var(--components-form-field-content-placeholder);text-overflow:ellipsis;font-family:\"TT Norms Pro\", sans-serif;font-size:var(--form-field-font-size);font-style:normal;font-weight:400;line-height:var(--form-field-line-height)}nv-fieldmultiselect .input-container-multiselect .toggle-dropdown-icon{position:absolute;right:0;top:50%;transform:translateY(-50%);z-index:2}nv-fieldmultiselect .input-container-multiselect nv-icon.validation{color:var(--nv-field-border-default);position:absolute;right:50px}nv-fieldmultiselect .input-container-multiselect.focus-within,nv-fieldmultiselect .input-container-multiselect:hover{border-color:var(--nv-field-border-focus);box-shadow:0px 0px 0px var(--focus-field-stroke) var(--nv-field-focus-box-shadow)}nv-fieldmultiselect .non-filterable-text{display:block;border-radius:var(--form-field-radius);background-color:var(--nv-field-background);color:var(--components-form-field-content-text);font-size:var(--form-field-font-size);font-weight:500;line-height:var(--form-field-line-height);box-sizing:border-box;cursor:pointer;height:100%;min-height:40px}nv-fieldmultiselect .non-filterable-text span{display:inline-block;width:100%;overflow:hidden;text-overflow:ellipsis}nv-fieldmultiselect .description{align-self:stretch;color:var(--components-form-text-description-default);font-family:\"TT Norms Pro\", sans-serif;font-size:var(--form-description-font-size);font-style:normal;line-height:var(--form-description-line-height)}nv-fieldmultiselect .error-description{align-self:stretch;color:var(--components-form-text-description-default);font-family:\"TT Norms Pro\", sans-serif;font-size:var(--form-description-font-size);font-style:normal;line-height:var(--form-description-line-height);color:var(--components-form-text-description-error)}nv-fieldmultiselect hr{border:none;border-top:1px solid var(--dropdown-divider-color, #ccc);margin:0.5rem 0}.input-container-multiselect.focus-within,.input-container-multiselect:hover{border-color:var(--nv-field-border-focus);box-shadow:0px 0px 0px var(--focus-field-stroke) var(--nv-field-focus-box-shadow)}.no-results-message{text-align:center;padding:10px;color:var(--nv-field-error-text, #999)}";
9
+ const NvFieldmultiselectStyle0 = nvFieldmultiselectCss;
10
+
11
+ const NvFieldmultiselect = class {
12
+ constructor(hostRef) {
13
+ index.registerInstance(this, hostRef);
14
+ this.dropdownItemSelected = index.createEvent(this, "dropdownItemSelected", 7);
15
+ this.valueChanged = index.createEvent(this, "valueChanged", 7);
16
+ this.multiselectChange = index.createEvent(this, "multiselectChange", 7);
17
+ /**
18
+ * Flag to prevent concurrent reordering operations.
19
+ * Private property preferred over @State as it:
20
+ * - Manages internal component logic without affecting UI
21
+ * - Avoids unnecessary re-renders
22
+ * - Provides better performance for rapid state changes
23
+ * - Only needs class-level scope
24
+ */
25
+ this.isReordering = false;
26
+ /**
27
+ * Handle badge close for options mode.
28
+ */
29
+ this.handleBadgeCloseOptions = () => {
30
+ this.selectedValues = [];
31
+ this.multiselectChange.emit(this.selectedValues);
32
+ // Uncheck all elements
33
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
34
+ items.forEach(item => {
35
+ item.checked = false;
36
+ item.style.display = '';
37
+ });
38
+ // Reorder options without the divider since there are no selected elements
39
+ this.parsedOptions = this.parsedOptions.filter(option => !option.isDivider);
40
+ // Reorder options without the divider since there are no selected elements
41
+ this.reorderOptionsContent();
42
+ };
43
+ /**
44
+ * Handle badge close for slots mode.
45
+ */
46
+ this.handleBadgeCloseSlots = () => {
47
+ this.selectedValues = [];
48
+ this.multiselectChange.emit(this.selectedValues);
49
+ // Uncheck all elements
50
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
51
+ items.forEach(item => {
52
+ item.checked = false;
53
+ item.style.display = '';
54
+ });
55
+ // Reorder slot content
56
+ this.reorderSlotContent();
57
+ };
58
+ /**
59
+ * Handle popover close
60
+ */
61
+ this.handlePopoverClose = () => {
62
+ this.open = false;
63
+ this.filterText = '';
64
+ if (this.modeState === 'options') {
65
+ this.reorderOptionsContent();
66
+ }
67
+ else {
68
+ this.reorderSlotContent();
69
+ }
70
+ // Reset filter if needed
71
+ if (this.filterable) {
72
+ this.resetFilter();
73
+ }
74
+ };
75
+ /**
76
+ * Handle keyboard events for options mode.
77
+ * @param {KeyboardEvent} event - The keyboard event.
78
+ */
79
+ this.handleKeyDownOptions = (event) => {
80
+ if (!this.open) {
81
+ if (event.key === 'ArrowDown') {
82
+ this.open = true;
83
+ this.popoverElement.show();
84
+ if (!this.filterable) {
85
+ this.focusFirstItem();
86
+ }
87
+ event.preventDefault();
88
+ return;
89
+ }
90
+ return;
91
+ }
92
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
93
+ if (items.length === 0) {
94
+ console.warn('No dropdown items found to navigate');
95
+ return;
96
+ }
97
+ let currentIndex = items.findIndex(item => item.classList.contains('highlighted'));
98
+ if (event.key === 'ArrowDown') {
99
+ event.preventDefault();
100
+ currentIndex = (currentIndex + 1) % items.length;
101
+ this.updateHighlightedItem(items, currentIndex);
102
+ }
103
+ else if (event.key === 'ArrowUp') {
104
+ event.preventDefault();
105
+ currentIndex = (currentIndex - 1 + items.length) % items.length;
106
+ this.updateHighlightedItem(items, currentIndex);
107
+ }
108
+ else if (event.key === 'Enter' && currentIndex >= 0) {
109
+ event.preventDefault();
110
+ items[currentIndex].click();
111
+ }
112
+ else if (event.key === 'Escape') {
113
+ event.preventDefault();
114
+ this.handlePopoverClose();
115
+ if (this.inputElement) {
116
+ this.inputElement.blur();
117
+ }
118
+ }
119
+ };
120
+ /**
121
+ * Handle input blur for options mode.
122
+ */
123
+ this.handleInputBlurOptions = () => {
124
+ setTimeout(() => {
125
+ if (!this.el.contains(document.activeElement)) {
126
+ this.handlePopoverClose();
127
+ }
128
+ }, 150);
129
+ };
130
+ /**
131
+ * Handle click on the input container for options mode.
132
+ * @param {MouseEvent} event - The click event.
133
+ */
134
+ this.handleInputContainerClickOptions = (event) => {
135
+ if (this.disabled || this.readonly) {
136
+ return;
137
+ }
138
+ const target = event.target;
139
+ if (target.tagName === 'P' || target.tagName === 'SPAN') {
140
+ this.open = true;
141
+ this.popoverElement.show();
142
+ const inputContainer = this.el.querySelector('.input-container');
143
+ if (inputContainer) {
144
+ inputContainer.classList.add('focus-within');
145
+ const removeFocusWithin = () => {
146
+ inputContainer.classList.remove('focus-within');
147
+ };
148
+ this.popoverElement.addEventListener('hide', removeFocusWithin);
149
+ }
150
+ }
151
+ };
152
+ /**
153
+ * Handle click on the input container for slots mode.
154
+ * @param {MouseEvent} event - The click event.
155
+ */
156
+ this.handleInputContainerClickSlots = (event) => {
157
+ if (this.disabled || this.readonly) {
158
+ return;
159
+ }
160
+ const target = event.target;
161
+ if (target.tagName === 'P' || target.tagName === 'SPAN') {
162
+ this.open = true;
163
+ this.popoverElement.show();
164
+ const inputContainer = this.el.querySelector('.input-container');
165
+ if (inputContainer) {
166
+ inputContainer.classList.add('focus-within');
167
+ const removeFocusWithin = () => {
168
+ inputContainer.classList.remove('focus-within');
169
+ };
170
+ this.popoverElement.addEventListener('hide', removeFocusWithin);
171
+ }
172
+ }
173
+ };
174
+ /**
175
+ * Handle input change for options mode.
176
+ * @param {Event} event - The input event.
177
+ */
178
+ this.handleInputOptions = (event) => {
179
+ if (!this.filterable)
180
+ return;
181
+ if (this.disabled || this.readonly) {
182
+ return;
183
+ }
184
+ const input = event.target;
185
+ this.value = input.value;
186
+ this.valueChanged.emit(this.value);
187
+ // Clear any existing timer
188
+ if (this.debounceTimer) {
189
+ window.clearTimeout(this.debounceTimer);
190
+ }
191
+ // Set a new timer for filtering
192
+ this.debounceTimer = window.setTimeout(() => {
193
+ this.filterText = input.value.toLowerCase();
194
+ this.filterOptionsItems();
195
+ }, this.debounceDelay);
196
+ };
197
+ /**
198
+ * Handle input change for slots mode
199
+ * @param {Event} event - The input event.
200
+ */
201
+ this.handleInputSlots = (event) => {
202
+ if (!this.filterable)
203
+ return;
204
+ if (this.disabled || this.readonly)
205
+ return;
206
+ const input = event.target;
207
+ this.value = input.value;
208
+ this.valueChanged.emit(this.value);
209
+ // Clear any existing timer
210
+ if (this.debounceTimer) {
211
+ window.clearTimeout(this.debounceTimer);
212
+ }
213
+ // Set a new timer for filtering
214
+ this.debounceTimer = window.setTimeout(() => {
215
+ this.filterText = input.value.toLowerCase();
216
+ this.filterSlotsItems();
217
+ }, this.debounceDelay);
218
+ };
219
+ /**
220
+ * Handle input focus for options mode.
221
+ */
222
+ this.handleInputFocusOptions = () => {
223
+ if (this.disabled || this.readonly) {
224
+ return;
225
+ }
226
+ this.open = true;
227
+ };
228
+ /**
229
+ * Handle input focus for slots mode.
230
+ */
231
+ this.handleInputFocusSlots = () => {
232
+ if (this.disabled || this.readonly) {
233
+ return;
234
+ }
235
+ this.open = true;
236
+ };
237
+ /**
238
+ * Handle input blur for slots mode.
239
+ */
240
+ this.handleInputBlurSlots = () => {
241
+ setTimeout(() => {
242
+ if (!this.el.contains(document.activeElement)) {
243
+ this.handlePopoverClose();
244
+ }
245
+ }, 150);
246
+ };
247
+ /**
248
+ * Toggle the multiselect popover for options mode.
249
+ */
250
+ this.togglePopoverOptions = () => {
251
+ if (this.disabled || this.readonly) {
252
+ return;
253
+ }
254
+ if (this.open) {
255
+ this.handlePopoverClose();
256
+ }
257
+ else {
258
+ this.open = true;
259
+ this.popoverElement.show();
260
+ if (!this.filterable) {
261
+ this.focusFirstItem();
262
+ }
263
+ }
264
+ };
265
+ /**
266
+ * Toggle the multiselect popover for slots mode.
267
+ */
268
+ this.togglePopoverSlots = () => {
269
+ if (this.disabled || this.readonly) {
270
+ return;
271
+ }
272
+ this.open = !this.open;
273
+ if (this.open) {
274
+ this.popoverElement.show();
275
+ if (!this.filterable) {
276
+ this.focusFirstItem();
277
+ }
278
+ }
279
+ else {
280
+ this.popoverElement.hide();
281
+ }
282
+ };
283
+ /**
284
+ * Handle keyboard events for slots mode.
285
+ * @param {KeyboardEvent} event - The keyboard event.
286
+ */
287
+ this.handleKeyDownSlots = (event) => {
288
+ if (!this.open) {
289
+ if (event.key === 'ArrowDown') {
290
+ this.open = true;
291
+ this.popoverElement.show();
292
+ if (!this.filterable) {
293
+ this.focusFirstItem();
294
+ }
295
+ event.preventDefault();
296
+ return;
297
+ }
298
+ return;
299
+ }
300
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
301
+ if (items.length === 0) {
302
+ console.warn('No dropdown items found to navigate');
303
+ return;
304
+ }
305
+ let currentIndex = items.findIndex(item => item.classList.contains('highlighted'));
306
+ if (event.key === 'ArrowDown') {
307
+ event.preventDefault();
308
+ currentIndex = (currentIndex + 1) % items.length;
309
+ this.updateHighlightedItem(items, currentIndex);
310
+ }
311
+ else if (event.key === 'ArrowUp') {
312
+ event.preventDefault();
313
+ currentIndex = (currentIndex - 1 + items.length) % items.length;
314
+ this.updateHighlightedItem(items, currentIndex);
315
+ }
316
+ else if (event.key === 'Enter' && currentIndex >= 0) {
317
+ event.preventDefault();
318
+ items[currentIndex].click();
319
+ }
320
+ else if (event.key === 'Escape') {
321
+ event.preventDefault();
322
+ this.handlePopoverClose();
323
+ if (this.inputElement) {
324
+ this.inputElement.blur();
325
+ }
326
+ }
327
+ };
328
+ this.inputId = v4.v4();
329
+ this.name = undefined;
330
+ this.label = undefined;
331
+ this.description = undefined;
332
+ this.placeholder = undefined;
333
+ this.maxHeight = '200px';
334
+ this.badgeLabel = '';
335
+ this.emptyresult = 'No results found';
336
+ this.required = false;
337
+ this.error = false;
338
+ this.errorDescription = undefined;
339
+ this.readonly = false;
340
+ this.disabled = false;
341
+ this.autocomplete = 'off';
342
+ this.filterable = false;
343
+ this.value = undefined;
344
+ this.open = false;
345
+ this.mode = undefined;
346
+ this.options = undefined;
347
+ this.parsedOptions = [];
348
+ this.selectedValues = [];
349
+ this.sortedOptions = [];
350
+ this.filterText = '';
351
+ this.isFilterable = this.filterable;
352
+ this.debounceDelay = 300;
353
+ this.modeState = 'options';
354
+ }
355
+ //#endregion PROPERTIES
356
+ /****************************************************************************/
357
+ //#region EVENTS
358
+ /**
359
+ * Subscribe to click outside event.
360
+ */
361
+ connectedCallback() {
362
+ this.modeState = this.mode;
363
+ this.handleOptionsChange(this.options);
364
+ document.addEventListener('click', this.handleClickOutside.bind(this));
365
+ // If we don't have parsed options, initialize with slot elements
366
+ if (!this.parsedOptions || this.parsedOptions.length === 0) {
367
+ // Wait for the slot to be available
368
+ requestAnimationFrame(() => {
369
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
370
+ // Initialize selectedValues with checked elements
371
+ this.selectedValues = items
372
+ .filter(item => item.hasAttribute('checked'))
373
+ .map(item => item.getAttribute('value') || '');
374
+ });
375
+ }
376
+ // Initialize the sorted options array with the parsed options for initial rendering
377
+ this.sortedOptions = [...this.parsedOptions];
378
+ // Handle pre-selection during component initialization
379
+ this.setInitialSelection();
380
+ // Apply filtering if the multiselect is filterable and there is a value
381
+ if (this.filterable && this.value) {
382
+ this.filterText = this.value.toLowerCase();
383
+ this.filterItems();
384
+ }
385
+ else {
386
+ // Reset visibility state of all dropdown items
387
+ this.resetFilter();
388
+ }
389
+ const slot = this.el.querySelector('slot[name="content"]');
390
+ if (slot) {
391
+ const observer = new MutationObserver(() => {
392
+ this.reorderSlotContent();
393
+ });
394
+ observer.observe(slot, {
395
+ childList: true,
396
+ subtree: true,
397
+ });
398
+ this.reorderSlotContent();
399
+ }
400
+ }
401
+ /**
402
+ * Unsubscribe from click outside event.
403
+ */
404
+ disconnectedCallback() {
405
+ document.removeEventListener('click', this.handleClickOutside.bind(this));
406
+ }
407
+ /**
408
+ * Emitted when the input loses focus.
409
+ * @param {CustomEvent<boolean>} event - The event object containing the focus state.
410
+ */
411
+ handleOpenChanged(event) {
412
+ // Update the open state of popover
413
+ this.open = event.detail;
414
+ if (this.open) {
415
+ if (this.filterText) {
416
+ this.filterItems();
417
+ }
418
+ }
419
+ else {
420
+ this.reorderSlotContent();
421
+ }
422
+ }
423
+ /**
424
+ * Listen for the `itemChecked` event emitted by child items.
425
+ * @param {CustomEvent<{ value: string; checked: boolean }>} event - The event object containing the selected value and its checked state.
426
+ */
427
+ handleItemChecked(event) {
428
+ if (this.disabled || this.readonly)
429
+ return;
430
+ const { value, checked } = event.detail;
431
+ if (value !== undefined && value !== null) {
432
+ const newSelectedValues = [...this.selectedValues];
433
+ if (checked && !newSelectedValues.includes(value)) {
434
+ newSelectedValues.push(value);
435
+ }
436
+ else if (!checked) {
437
+ const index = newSelectedValues.indexOf(value);
438
+ if (index > -1) {
439
+ newSelectedValues.splice(index, 1);
440
+ }
441
+ }
442
+ this.selectedValues = newSelectedValues;
443
+ this.multiselectChange.emit(this.selectedValues);
444
+ }
445
+ }
446
+ /**
447
+ * Emitted when the options change.
448
+ * @param {string | Array<{label: string, value: string, isDivider?: boolean, disabled?: boolean, description?: string, checked?: boolean}>} newValue - The new value of the options.
449
+ */
450
+ handleOptionsChange(newValue) {
451
+ if (typeof newValue === 'string') {
452
+ try {
453
+ const parsedOpts = JSON.parse(newValue);
454
+ // Process options: initialize selections, reorder items, and add dividers where needed
455
+ this.selectedValues = parsedOpts
456
+ .filter(option => option.checked)
457
+ .map(option => option.value);
458
+ const checkedItems = parsedOpts.filter(option => this.selectedValues.includes(option.value));
459
+ const uncheckedItems = parsedOpts.filter(option => !this.selectedValues.includes(option.value));
460
+ this.parsedOptions = [
461
+ ...checkedItems,
462
+ ...(checkedItems.length > 0 && uncheckedItems.length > 0
463
+ ? [{ isDivider: true, label: '', value: '' }]
464
+ : []),
465
+ ...uncheckedItems,
466
+ ];
467
+ }
468
+ catch (error) {
469
+ console.error('Error parsing options:', error);
470
+ this.parsedOptions = [];
471
+ }
472
+ }
473
+ else if (Array.isArray(newValue)) {
474
+ this.selectedValues = newValue
475
+ .filter(option => option.checked)
476
+ .map(option => option.value);
477
+ this.parsedOptions = [...newValue];
478
+ }
479
+ else {
480
+ this.parsedOptions = [];
481
+ }
482
+ this.reorderSlotContent();
483
+ }
484
+ /**
485
+ * Emitted when the value changes.
486
+ */
487
+ watchValueHandler() {
488
+ // Handle value change and update the corresponding multiselect item if it exists
489
+ this.setInitialSelection();
490
+ }
491
+ /**
492
+ * Emitted when the filterable property changes.
493
+ * @param {boolean} newValue - The new value of the filterable property.
494
+ */
495
+ watchFilterableHandler(newValue) {
496
+ this.isFilterable = newValue;
497
+ this.filterable = newValue;
498
+ }
499
+ // Add a watcher for the slot content
500
+ handleSlotChange(event) {
501
+ const slot = event.target;
502
+ if (slot.name === 'content') {
503
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
504
+ // Update selectedValues when slot content changes
505
+ this.selectedValues = items
506
+ .filter(item => item.hasAttribute('checked'))
507
+ .map(item => item.getAttribute('value') || '');
508
+ }
509
+ }
510
+ //#endregion EVENTS
511
+ /****************************************************************************/
512
+ //#region METHODS
513
+ /**
514
+ * Retrieves the current filter text entered by the user.
515
+ * @returns {string} The filter text.
516
+ */
517
+ async getFilterText() {
518
+ return this.filterText;
519
+ }
520
+ /**
521
+ * Set the initial selection based on the current value and update the inputElement value.
522
+ */
523
+ setInitialSelection() {
524
+ var _a;
525
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitem'));
526
+ const selectedItem = items.find(item => {
527
+ var _a;
528
+ return item.getAttribute('label') === this.value ||
529
+ item.getAttribute('value') === this.value ||
530
+ ((_a = item.textContent) === null || _a === void 0 ? void 0 : _a.trim()) === this.value;
531
+ });
532
+ // Remove 'selected' from all items first to reset the state
533
+ items.forEach(item => {
534
+ item.removeAttribute('selected');
535
+ item.classList.remove('selected');
536
+ });
537
+ if (selectedItem) {
538
+ // Add the `selected` attribute and `selected` class for visual styling
539
+ selectedItem.setAttribute('selected', 'true');
540
+ selectedItem.classList.add('selected');
541
+ // Update the value and inputElement value to reflect the pre-selected item
542
+ this.value =
543
+ selectedItem.getAttribute('label') ||
544
+ selectedItem.getAttribute('value') ||
545
+ ((_a = selectedItem.textContent) === null || _a === void 0 ? void 0 : _a.trim()) ||
546
+ '';
547
+ if (this.inputElement) {
548
+ this.inputElement.value = this.value;
549
+ }
550
+ }
551
+ }
552
+ /**
553
+ * Reset the filter and make all items visible.
554
+ */
555
+ async resetFilter() {
556
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
557
+ // Reset visibility state of all dropdown items
558
+ items.forEach(item => {
559
+ item.style.display = '';
560
+ });
561
+ // Clean up filter-related UI elements
562
+ const ul = this.el.querySelector('ul');
563
+ if (ul) {
564
+ const emptyMessage = ul.querySelector('[data-empty]');
565
+ const divider = ul.querySelector('hr.dropdown-divider');
566
+ if (emptyMessage)
567
+ emptyMessage.remove();
568
+ if (divider)
569
+ divider.remove();
570
+ }
571
+ }
572
+ /**
573
+ * Returns the list of selected values.
574
+ * @returns {string[]} The selected values.
575
+ */
576
+ async getSelectedValues() {
577
+ return this.selectedValues;
578
+ }
579
+ /**
580
+ * Reorder the content of the slot.
581
+ */
582
+ reorderSlotContent() {
583
+ if (this.modeState === 'options')
584
+ return;
585
+ const ul = this.el.querySelector('ul');
586
+ if (!ul)
587
+ return;
588
+ // First remove all existing dividers
589
+ ul.querySelectorAll('hr.dropdown-divider').forEach(divider => divider.remove());
590
+ // Get all visible items (not hidden)
591
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck')).filter(item => item.style.display !== 'none');
592
+ // Check if we have an empty message
593
+ const hasEmptyMessage = ul.querySelector('[data-empty]');
594
+ if (hasEmptyMessage) {
595
+ // If we have an empty message, don't reorder
596
+ return;
597
+ }
598
+ // Separate selected and unselected items
599
+ const selectedItems = items.filter(item => this.selectedValues.includes(item.getAttribute('value') || ''));
600
+ const unselectedItems = items.filter(item => !this.selectedValues.includes(item.getAttribute('value') || ''));
601
+ // Empty the list
602
+ while (ul.firstChild) {
603
+ ul.removeChild(ul.firstChild);
604
+ }
605
+ // Reorder items
606
+ selectedItems.forEach(item => ul.appendChild(item));
607
+ // Add divider only if we have both selected AND unselected items
608
+ // AND if visible items are different
609
+ if (selectedItems.length > 0 &&
610
+ unselectedItems.length > 0 &&
611
+ items.length > 1) {
612
+ const divider = document.createElement('hr');
613
+ divider.className = 'dropdown-divider';
614
+ ul.appendChild(divider);
615
+ }
616
+ // Add unselected items
617
+ unselectedItems.forEach(item => ul.appendChild(item));
618
+ }
619
+ /**
620
+ * Reorder the content for options mode with async handling
621
+ */
622
+ async reorderOptionsContent() {
623
+ if (this.isReordering ||
624
+ !this.parsedOptions ||
625
+ this.parsedOptions.length === 0 ||
626
+ this.modeState !== 'options') {
627
+ return;
628
+ }
629
+ try {
630
+ this.isReordering = true;
631
+ // Update parsedOptions first
632
+ const optionsWithoutDivider = this.parsedOptions.filter(opt => !opt.isDivider);
633
+ const selectedOptions = optionsWithoutDivider.filter(opt => this.selectedValues.includes(opt.value));
634
+ const unselectedOptions = optionsWithoutDivider.filter(opt => !this.selectedValues.includes(opt.value));
635
+ // Update parsedOptions with new divider
636
+ this.parsedOptions = [
637
+ ...selectedOptions,
638
+ ...(selectedOptions.length > 0 && unselectedOptions.length > 0
639
+ ? [{ isDivider: true, label: '', value: '' }]
640
+ : []),
641
+ ...unselectedOptions,
642
+ ];
643
+ // Then update DOM
644
+ await new Promise(resolve => requestAnimationFrame(resolve));
645
+ const ul = this.el.querySelector('ul');
646
+ if (!ul)
647
+ return;
648
+ // Get all items
649
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
650
+ // Remove all existing dividers
651
+ ul.querySelectorAll('hr.dropdown-divider').forEach(divider => divider.remove());
652
+ // Separate selected and unselected items
653
+ const selectedItems = items.filter(item => this.selectedValues.includes(item.getAttribute('value') || ''));
654
+ const unselectedItems = items.filter(item => !this.selectedValues.includes(item.getAttribute('value') || ''));
655
+ // Empty the list
656
+ while (ul.firstChild) {
657
+ ul.removeChild(ul.firstChild);
658
+ }
659
+ // Reorder items
660
+ selectedItems.forEach(item => ul.appendChild(item));
661
+ // Add divider only if there are both selected AND unselected items
662
+ if (selectedItems.length > 0 && unselectedItems.length > 0) {
663
+ const divider = document.createElement('hr');
664
+ divider.className = 'dropdown-divider';
665
+ ul.appendChild(divider);
666
+ }
667
+ // Add unselected items
668
+ unselectedItems.forEach(item => ul.appendChild(item));
669
+ }
670
+ finally {
671
+ this.isReordering = false;
672
+ }
673
+ }
674
+ /**
675
+ * Filter multiselect items based on the text entered by the user.
676
+ */
677
+ filterItems() {
678
+ const ul = this.el.querySelector('ul');
679
+ if (!ul)
680
+ return;
681
+ // Remove existing empty message if any
682
+ const existingEmptyMessage = ul.querySelector('[data-empty]');
683
+ if (existingEmptyMessage) {
684
+ existingEmptyMessage.remove();
685
+ }
686
+ if (!this.filterText.trim()) {
687
+ if (this.parsedOptions && this.parsedOptions.length > 0) {
688
+ // Reset options display
689
+ const items = Array.from(ul.querySelectorAll('nv-fielddropdownitemcheck'));
690
+ items.forEach(item => {
691
+ item.style.display = '';
692
+ });
693
+ }
694
+ else {
695
+ // Reset slot items display
696
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
697
+ items.forEach(item => {
698
+ item.style.display = '';
699
+ });
700
+ }
701
+ this.reorderSlotContent();
702
+ return;
703
+ }
704
+ const normalizedFilter = this.normalizeText(this.filterText);
705
+ let hasVisibleItems = false;
706
+ if (this.parsedOptions && this.parsedOptions.length > 0) {
707
+ // Filter options mode
708
+ const items = Array.from(ul.querySelectorAll('nv-fielddropdownitemcheck'));
709
+ items.forEach(item => {
710
+ const option = this.parsedOptions.find(opt => opt.value === item.getAttribute('value'));
711
+ if (option && !option.isDivider) {
712
+ const matchesFilter = this.normalizeText(option.label).includes(normalizedFilter) ||
713
+ this.normalizeText(option.value).includes(normalizedFilter);
714
+ item.style.display = matchesFilter ? '' : 'none';
715
+ if (matchesFilter)
716
+ hasVisibleItems = true;
717
+ }
718
+ });
719
+ // Hide dividers if needed
720
+ const dividers = ul.querySelectorAll('hr.dropdown-divider');
721
+ dividers.forEach(divider => {
722
+ divider.style.display = hasVisibleItems ? '' : 'none';
723
+ });
724
+ }
725
+ else {
726
+ // Filter slot items mode
727
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
728
+ items.forEach(item => {
729
+ const label = item.getAttribute('label') || '';
730
+ const value = item.getAttribute('value') || '';
731
+ const textContent = item.textContent || '';
732
+ const matchesFilter = this.normalizeText(label).includes(normalizedFilter) ||
733
+ this.normalizeText(value).includes(normalizedFilter) ||
734
+ this.normalizeText(textContent).includes(normalizedFilter);
735
+ item.style.display = matchesFilter ? '' : 'none';
736
+ if (matchesFilter)
737
+ hasVisibleItems = true;
738
+ });
739
+ }
740
+ // Add empty message if no items match the filter
741
+ if (!hasVisibleItems) {
742
+ const emptyMessage = document.createElement('li');
743
+ emptyMessage.setAttribute('data-empty', 'true');
744
+ emptyMessage.textContent = this.emptyresult;
745
+ emptyMessage.classList.add('no-results-message');
746
+ ul.appendChild(emptyMessage);
747
+ }
748
+ this.reorderSlotContent();
749
+ }
750
+ /**
751
+ * Filter multiselect items in options mode.
752
+ */
753
+ filterOptionsItems() {
754
+ const ul = this.el.querySelector('ul');
755
+ if (!ul)
756
+ return;
757
+ // Remove existing empty message if any
758
+ const existingEmptyMessage = ul.querySelector('[data-empty]');
759
+ if (existingEmptyMessage) {
760
+ existingEmptyMessage.remove();
761
+ }
762
+ if (!this.filterText.trim()) {
763
+ // Reset options display
764
+ const items = Array.from(ul.querySelectorAll('nv-fielddropdownitemcheck'));
765
+ items.forEach(item => {
766
+ item.style.display = '';
767
+ });
768
+ this.reorderOptionsContent();
769
+ return;
770
+ }
771
+ const normalizedFilter = this.normalizeText(this.filterText);
772
+ let hasVisibleItems = false;
773
+ // Filter options mode
774
+ const items = Array.from(ul.querySelectorAll('nv-fielddropdownitemcheck'));
775
+ items.forEach(item => {
776
+ const option = this.parsedOptions.find(opt => opt.value === item.getAttribute('value'));
777
+ if (option && !option.isDivider) {
778
+ const matchesFilter = this.normalizeText(option.label).includes(normalizedFilter) ||
779
+ this.normalizeText(option.value).includes(normalizedFilter);
780
+ item.style.display = matchesFilter ? '' : 'none';
781
+ if (matchesFilter)
782
+ hasVisibleItems = true;
783
+ }
784
+ });
785
+ // Get visible items after filtering
786
+ const visibleItems = items.filter(item => item.style.display !== 'none');
787
+ const visibleSelectedItems = visibleItems.filter(item => this.selectedValues.includes(item.getAttribute('value') || ''));
788
+ // Hide divider if all visible items are either all selected or all unselected
789
+ const divider = ul.querySelector('hr.dropdown-divider');
790
+ if (divider) {
791
+ const shouldShowDivider = visibleSelectedItems.length > 0 &&
792
+ visibleSelectedItems.length < visibleItems.length;
793
+ divider.style.display = shouldShowDivider ? '' : 'none';
794
+ }
795
+ // Add empty message if no items match the filter
796
+ if (!hasVisibleItems) {
797
+ const emptyMessage = document.createElement('li');
798
+ emptyMessage.setAttribute('data-empty', 'true');
799
+ emptyMessage.textContent = this.emptyresult;
800
+ emptyMessage.classList.add('no-results-message');
801
+ ul.appendChild(emptyMessage);
802
+ }
803
+ }
804
+ /**
805
+ * Filter multiselect items in slots mode
806
+ */
807
+ filterSlotsItems() {
808
+ if (this.modeState === 'options')
809
+ return;
810
+ const ul = this.el.querySelector('ul');
811
+ if (!ul)
812
+ return;
813
+ // Remove existing empty message if any
814
+ const existingEmptyMessage = ul.querySelector('[data-empty]');
815
+ if (existingEmptyMessage) {
816
+ existingEmptyMessage.remove();
817
+ }
818
+ // If filter text is empty, reset all items visibility
819
+ if (!this.filterText.trim()) {
820
+ this.resetFilter();
821
+ return;
822
+ }
823
+ const normalizedFilter = this.normalizeText(this.filterText);
824
+ let hasVisibleItems = false;
825
+ // Get all items and preserve them in the DOM
826
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
827
+ // Instead of removing/reordering, just hide/show items
828
+ items.forEach(item => {
829
+ var _a;
830
+ const label = item.getAttribute('label') || '';
831
+ const value = item.getAttribute('value') || '';
832
+ const textContent = ((_a = item.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || '';
833
+ const matchesFilter = this.normalizeText(label).includes(normalizedFilter) ||
834
+ this.normalizeText(value).includes(normalizedFilter) ||
835
+ this.normalizeText(textContent).includes(normalizedFilter);
836
+ item.style.display = matchesFilter ? '' : 'none';
837
+ if (matchesFilter)
838
+ hasVisibleItems = true;
839
+ });
840
+ // Get visible items after filtering
841
+ const visibleItems = items.filter(item => item.style.display !== 'none');
842
+ const visibleSelectedItems = visibleItems.filter(item => this.selectedValues.includes(item.getAttribute('value') || ''));
843
+ // Hide divider if all visible items are either all selected or all unselected
844
+ const divider = ul.querySelector('hr.dropdown-divider');
845
+ if (divider) {
846
+ const shouldShowDivider = visibleSelectedItems.length > 0 &&
847
+ visibleSelectedItems.length < visibleItems.length;
848
+ divider.style.display = shouldShowDivider ? '' : 'none';
849
+ }
850
+ // Add empty message if no items match the filter
851
+ if (!hasVisibleItems) {
852
+ const emptyMessage = document.createElement('li');
853
+ emptyMessage.setAttribute('data-empty', 'true');
854
+ emptyMessage.textContent = this.emptyresult;
855
+ emptyMessage.classList.add('no-results-message');
856
+ ul.appendChild(emptyMessage);
857
+ }
858
+ }
859
+ /**
860
+ * Normalizes text by removing accents and converting to lowercase
861
+ * @param {string} text - The text to normalize
862
+ * @returns {string} The normalized text
863
+ *
864
+ * @example
865
+ * normalizeText("Café Latte") => "cafe latte"
866
+ *
867
+ * @description
868
+ * This function performs text normalization in three steps:
869
+ * 1. Decomposes characters into their base form and combining characters (NFD)
870
+ * 2. Removes all diacritical marks (accents, umlauts, etc.)
871
+ * 3. Converts to lowercase and trims whitespace
872
+ *
873
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize} - MDN documentation on String.normalize()
874
+ * @see {@link https://en.wikipedia.org/wiki/Unicode_equivalence#Normal_forms} - More info about Unicode normalization forms
875
+ */
876
+ normalizeText(text) {
877
+ return text
878
+ .normalize('NFD') // Decompose characters into base + combining characters (e.g., é => e + ´)
879
+ .replace(/[\u0300-\u036f]/g, '') // Remove all diacritical marks (Unicode range for combining characters)
880
+ .toLowerCase() // Convert to lowercase
881
+ .trim(); // Remove leading and trailing whitespace
882
+ }
883
+ /**
884
+ * Handle click outside the component.
885
+ * @param {MouseEvent} event - The click event.
886
+ */
887
+ handleClickOutside(event) {
888
+ if (this.el.contains(event.target) ||
889
+ (this.inputElement && this.inputElement.contains(event.target))) {
890
+ return;
891
+ }
892
+ // Force le même comportement que la fermeture par iconbutton
893
+ if (this.modeState === 'options') {
894
+ this.handlePopoverClose();
895
+ }
896
+ else {
897
+ this.popoverElement.hide();
898
+ }
899
+ }
900
+ /**
901
+ * Handle keyboard events & arrow key navigation.
902
+ * If the multiselect is not open, opens it and focuses on the first item if the list is not filterable.
903
+ * If the multiselect is open, handles arrow key navigation and closes it if the focus is outside the component.
904
+ * @param {KeyboardEvent} event - The keyboard event.
905
+ */
906
+ handleKeyDown(event) {
907
+ if (!this.open) {
908
+ if (event.key === 'ArrowDown') {
909
+ this.open = true;
910
+ this.popoverElement.show();
911
+ // Focus on the first item if the list is not filterable
912
+ if (!this.filterable) {
913
+ this.focusFirstItem();
914
+ }
915
+ event.preventDefault();
916
+ return;
917
+ }
918
+ return;
919
+ }
920
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
921
+ if (items.length === 0) {
922
+ console.warn('No dropdown items found to navigate');
923
+ return;
924
+ }
925
+ let currentIndex = items.findIndex(item => item.classList.contains('highlighted'));
926
+ if (event.key === 'ArrowDown') {
927
+ event.preventDefault();
928
+ currentIndex = (currentIndex + 1) % items.length;
929
+ this.updateHighlightedItem(items, currentIndex);
930
+ }
931
+ else if (event.key === 'ArrowUp') {
932
+ event.preventDefault();
933
+ currentIndex = (currentIndex - 1 + items.length) % items.length;
934
+ this.updateHighlightedItem(items, currentIndex);
935
+ }
936
+ else if (event.key === 'Enter' && currentIndex >= 0) {
937
+ event.preventDefault();
938
+ items[currentIndex].click();
939
+ }
940
+ else if (event.key === 'Escape') {
941
+ event.preventDefault();
942
+ this.open = false;
943
+ this.popoverElement.hide();
944
+ if (this.inputElement) {
945
+ this.inputElement.blur();
946
+ }
947
+ }
948
+ }
949
+ /**
950
+ * Updates the highlighted item in the dropdown list.
951
+ *
952
+ * @param {(HTMLNvFielddropdownitemElement | HTMLNvFielddropdownitemcheckElement)[]} items - The items to update.
953
+ * @param {number} index - The index of the item to highlight.
954
+ */
955
+ updateHighlightedItem(items, index) {
956
+ items.forEach((item, i) => {
957
+ if (i === index) {
958
+ item.classList.add('highlighted');
959
+ item.setAttribute('tabindex', '0');
960
+ item.focus();
961
+ }
962
+ else {
963
+ item.classList.remove('highlighted');
964
+ item.setAttribute('tabindex', '-1');
965
+ }
966
+ });
967
+ }
968
+ /**
969
+ * Focus on the first item in the dropdown list.
970
+ */
971
+ focusFirstItem() {
972
+ const firstItem = this.el.querySelector('nv-fielddropdownitemcheck');
973
+ if (firstItem) {
974
+ firstItem.setAttribute('tabindex', '0');
975
+ firstItem.classList.add('highlighted');
976
+ firstItem.focus();
977
+ }
978
+ else {
979
+ console.warn('No first item found to focus');
980
+ }
981
+ }
982
+ /**
983
+ * Watch for changes in the mode prop and update modeState accordingly
984
+ * @param {string} newValue - The new mode value
985
+ */
986
+ handleModeChange(newValue) {
987
+ this.modeState = newValue;
988
+ }
989
+ //#endregion METHODS
990
+ /****************************************************************************/
991
+ //#region RENDER
992
+ /**
993
+ * Renders the component in options mode
994
+ * @returns {any} The JSX for options mode
995
+ */
996
+ renderOptionsMode() {
997
+ return (index.h(index.Host, null, (this.label || this.el.querySelector('[slot="label"]')) && (index.h("label", { htmlFor: this.inputId }, index.h("slot", { name: "label" }, this.label))), index.h("nv-popover", { ref: el => (this.popoverElement = el), triggerMode: "controlled", placement: "bottom-start", open: this.open }, index.h("div", { class: "input-wrapper-multiselect", slot: "trigger" }, index.h("slot", { name: "before-input" }), index.h("div", { class: "input-container-multiselect" }, index.h("slot", { name: "leading-input" }), index.h("nv-badge", { slot: "leading-input", "prevent-auto-close": "true", color: "10", dismissible: this.selectedValues.length > 0, hidden: this.selectedValues.length <= 0, label: `${this.selectedValues.length} ${this.badgeLabel}`, "aria-label": `Clear all ${this.selectedValues.length} ${this.badgeLabel} items`, onCloseClicked: this.handleBadgeCloseOptions }), this.isFilterable || this.disabled || this.readonly ? (index.h("input", { id: this.inputId, ref: e => (this.inputElement = e), autocomplete: this.autocomplete, placeholder: this.placeholder, name: this.name, value: this.value, required: this.required, disabled: this.disabled, readOnly: this.readonly, onInput: this.handleInputOptions, onFocus: this.handleInputFocusOptions, onBlur: this.handleInputBlurOptions, onKeyDown: this.handleKeyDownOptions })) : (index.h("p", { id: this.inputId, class: "non-filterable-text", onClick: this.handleInputContainerClickOptions, tabIndex: 0, onKeyDown: this.handleKeyDownOptions, onFocus: this.handleInputFocusOptions, role: "combobox", "aria-expanded": this.open }, index.h("span", null, this.value || this.placeholder))), index.h("nv-iconbutton", { class: "toggle-dropdown-icon", name: this.open ? 'chevron-top' : 'chevron-down', size: "md", emphasis: "lower", "aria-label": this.open ? 'Hide dropdown' : 'Show dropdown', "aria-pressed": this.open.toString(), onClick: this.togglePopoverOptions })), index.h("slot", { name: "after-input" })), index.h("div", { slot: "content", role: "listbox", "aria-multiselectable": "true", style: { 'max-height': this.maxHeight, 'overflow-y': 'auto' } }, index.h("ul", { role: "presentation" }, this.parsedOptions.map(option => option.isDivider ? (index.h("hr", { class: "dropdown-divider" })) : (index.h("nv-fielddropdownitemcheck", { label: option.label, description: option.description, value: option.value, checked: this.selectedValues.includes(option.value), disabled: option.disabled })))))), this.renderDescriptions()));
998
+ }
999
+ /**
1000
+ * Renders the component in slots mode
1001
+ * @returns {any} The JSX for slots mode
1002
+ */
1003
+ renderSlotsMode() {
1004
+ return (index.h(index.Host, null, (this.label || this.el.querySelector('[slot="label"]')) && (index.h("label", { htmlFor: this.inputId }, index.h("slot", { name: "label" }, this.label))), index.h("nv-popover", { ref: el => (this.popoverElement = el), triggerMode: "controlled", placement: "bottom-start", open: this.open }, index.h("div", { class: "input-wrapper-multiselect", slot: "trigger" }, index.h("slot", { name: "before-input" }), index.h("div", { class: "input-container-multiselect", onClick: this.handleInputContainerClickSlots }, index.h("slot", { name: "leading-input" }, index.h("p", null, "No leading input")), index.h("nv-badge", { slot: "leading-input", "prevent-auto-close": "true", color: "10", dismissible: this.selectedValues.length > 0, hidden: this.selectedValues.length <= 0, label: `${this.selectedValues.length} ${this.badgeLabel}`, "aria-label": `Clear all ${this.selectedValues.length} ${this.badgeLabel} items`, onCloseClicked: this.handleBadgeCloseSlots }), this.isFilterable || this.disabled || this.readonly ? (index.h("input", { id: this.inputId, ref: e => (this.inputElement = e), autocomplete: this.autocomplete, placeholder: this.placeholder, name: this.name, value: this.value, required: this.required, disabled: this.disabled, readOnly: this.readonly, onInput: this.handleInputSlots, onFocus: this.handleInputFocusSlots, onBlur: this.handleInputBlurSlots, onKeyDown: this.handleKeyDownSlots })) : (index.h("p", { id: this.inputId, class: "non-filterable-text", onClick: this.handleInputContainerClickSlots, tabIndex: 0, onKeyDown: this.handleKeyDownSlots, onFocus: this.handleInputFocusSlots, role: "combobox", "aria-expanded": this.open }, index.h("span", null, this.value || this.placeholder))), index.h("nv-iconbutton", { class: "toggle-dropdown-icon", name: this.open ? 'chevron-top' : 'chevron-down', size: "md", emphasis: "lower", "aria-label": this.open ? 'Hide dropdown' : 'Show dropdown', "aria-pressed": this.open.toString(), onClick: this.togglePopoverSlots })), index.h("slot", { name: "after-input" })), index.h("div", { slot: "content", role: "listbox", "aria-multiselectable": "true", style: { 'max-height': this.maxHeight, 'overflow-y': 'auto' } }, index.h("slot", { name: "content" }))), this.renderDescriptions()));
1005
+ }
1006
+ /**
1007
+ * Renders description and error description sections
1008
+ * @returns {any} The JSX for descriptions
1009
+ */
1010
+ renderDescriptions() {
1011
+ return [
1012
+ (this.description || this.el.querySelector('[slot="description"]')) && (index.h("div", { class: "description" }, index.h("slot", { name: "description" }, this.description))),
1013
+ (this.errorDescription ||
1014
+ this.el.querySelector('[slot="error-description"]')) && (index.h("div", { hidden: !this.error, class: "error-description" }, index.h("slot", { name: "error-description" }, this.errorDescription))),
1015
+ ];
1016
+ }
1017
+ /**
1018
+ * Main render method that decides which mode to render
1019
+ * @returns {any} The JSX for the component
1020
+ */
1021
+ render() {
1022
+ return this.modeState === 'options'
1023
+ ? this.renderOptionsMode()
1024
+ : this.renderSlotsMode();
1025
+ }
1026
+ get el() { return index.getElement(this); }
1027
+ static get watchers() { return {
1028
+ "options": ["handleOptionsChange"],
1029
+ "value": ["watchValueHandler"],
1030
+ "filterable": ["watchFilterableHandler"],
1031
+ "mode": ["handleModeChange"]
1032
+ }; }
1033
+ };
1034
+ NvFieldmultiselect.style = NvFieldmultiselectStyle0;
1035
+
1036
+ exports.nv_fieldmultiselect = NvFieldmultiselect;
1037
+
1038
+ //# sourceMappingURL=nv-fieldmultiselect.cjs.entry.js.map