@nova-design-system/nova-react 3.9.1 → 3.10.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/cjs/{constants-4faa1fae-BzFAKCkR.js → constants-23aaef7b-Cj2b-su0.js} +12 -0
  2. package/dist/cjs/{index-BtjpbnUr.js → index-B-1F0q3j.js} +1458 -448
  3. package/dist/cjs/index.js +4 -1
  4. package/dist/cjs/{nv-accordion-item.entry-Dr_2iHhQ.js → nv-accordion-item.entry-BF6TIAqX.js} +2 -2
  5. package/dist/cjs/{nv-accordion.entry-CYVpcwuY.js → nv-accordion.entry-CaTzxCZe.js} +1 -1
  6. package/dist/cjs/{nv-alert.entry-C_H-R9wb.js → nv-alert.entry-EOVv8IiE.js} +8 -8
  7. package/dist/cjs/{nv-avatar.entry-BeSOqGvb.js → nv-avatar.entry-DyiNDtz4.js} +7 -7
  8. package/dist/cjs/nv-badge_2.entry-DTc3EkVi.js +212 -0
  9. package/dist/cjs/{nv-breadcrumb.entry-yQozUTFi.js → nv-breadcrumb.entry-DKmd0vLH.js} +2 -2
  10. package/dist/cjs/{nv-breadcrumbs.entry-Qar1fOI7.js → nv-breadcrumbs.entry-CQB0c_7Y.js} +1 -1
  11. package/dist/cjs/{nv-button.entry-M_c4r8PX.js → nv-button.entry-rPyTGZZw.js} +8 -8
  12. package/dist/cjs/nv-buttongroup.entry-BT9JC-IJ.js +195 -0
  13. package/dist/cjs/{nv-calendar.entry-DFE372aB.js → nv-calendar.entry-C4stLDAG.js} +120 -43
  14. package/dist/cjs/{nv-col.entry-Bi8pH33J.js → nv-col.entry-DY7HEDMv.js} +2 -2
  15. package/dist/cjs/{nv-datagrid.entry-B-blFDg-.js → nv-datagrid.entry-yzQVVpxg.js} +9 -9
  16. package/dist/cjs/{nv-datagridcolumn.entry-CAzB7NtB.js → nv-datagridcolumn.entry-AOVwen5Y.js} +2 -2
  17. package/dist/cjs/{nv-dialog.entry-Bdw3O22w.js → nv-dialog.entry-DztbR2hl.js} +3 -3
  18. package/dist/cjs/{nv-dialogfooter_2.entry-BTUrxVzn.js → nv-dialogfooter_2.entry-iPMNyDQF.js} +5 -5
  19. package/dist/cjs/{nv-fieldcheckbox.entry-DNzC8s-J.js → nv-fieldcheckbox.entry-WEzw8Y0l.js} +6 -6
  20. package/dist/cjs/{nv-fielddate.entry-BI8REINj.js → nv-fielddate.entry-B4B2QgCn.js} +7 -7
  21. package/dist/cjs/{nv-fielddaterange.entry-B7mtEV97.js → nv-fielddaterange.entry-BQ-J4HKx.js} +7 -7
  22. package/dist/cjs/{nv-fielddropdown.entry-Cz7yuHTj.js → nv-fielddropdown.entry-B2YBjdkI.js} +4 -4
  23. package/dist/cjs/{nv-fielddropdownitem.entry-CH_C4Dr-.js → nv-fielddropdownitem.entry-B0wCnSfT.js} +2 -2
  24. package/dist/cjs/{nv-fieldmultiselect.entry-BqEdEUR0.js → nv-fieldmultiselect.entry-DuPOvire.js} +433 -43
  25. package/dist/cjs/{nv-fieldnumber.entry-BhRb8v1L.js → nv-fieldnumber.entry-BJANMe4j.js} +4 -4
  26. package/dist/cjs/{nv-fieldpassword.entry-BL4T90zr.js → nv-fieldpassword.entry-DkkJHwkG.js} +4 -4
  27. package/dist/cjs/{nv-fieldradio.entry-D-x10Pri.js → nv-fieldradio.entry-8uDJz8PS.js} +5 -5
  28. package/dist/cjs/{nv-fieldselect.entry-B-kynHlw.js → nv-fieldselect.entry-DN6euwMc.js} +6 -6
  29. package/dist/cjs/{nv-fieldslider.entry-D6X0LJKJ.js → nv-fieldslider.entry-BI72B0_Z.js} +4 -4
  30. package/dist/cjs/{nv-fieldtext.entry-xR41AQcM.js → nv-fieldtext.entry-DzHqp5Lp.js} +4 -4
  31. package/dist/cjs/{nv-fieldtextarea.entry-4mqhSSHM.js → nv-fieldtextarea.entry-CFgoC_mT.js} +4 -4
  32. package/dist/cjs/{nv-fieldtime.entry-S3r7RYwN.js → nv-fieldtime.entry-nVAeh7Ot.js} +66 -66
  33. package/dist/cjs/{nv-icon.entry-C2t6pj-B.js → nv-icon.entry-C0-IQQji.js} +9 -9
  34. package/dist/cjs/{nv-iconbutton_2.entry-Cv1d6ktl.js → nv-iconbutton_2.entry-BnnDZjg4.js} +4 -4
  35. package/dist/cjs/{nv-menu.entry-J_Ytq1Kn.js → nv-menu.entry-BB2mjwHV.js} +2 -2
  36. package/dist/cjs/{nv-menuitem.entry-DpOO9tMo.js → nv-menuitem.entry-CgkJiqc_.js} +2 -2
  37. package/dist/cjs/{nv-popover.entry-BZJHJXSA.js → nv-popover.entry-_Iv8yq0t.js} +2 -2
  38. package/dist/cjs/{nv-row.entry-D4qBjtBv.js → nv-row.entry-BZ2prXQS.js} +2 -2
  39. package/dist/cjs/{nv-stack.entry-DOc6ZvMZ.js → nv-stack.entry-C69ZIFWU.js} +2 -2
  40. package/dist/cjs/{nv-table.entry-7-TxQSlH.js → nv-table.entry-CXqK-89M.js} +3 -3
  41. package/dist/cjs/{nv-tablecolumn.entry-Bd4xWDYD.js → nv-tablecolumn.entry-RMYxY100.js} +1 -1
  42. package/dist/cjs/{nv-toggle.entry-DJmXXavz.js → nv-toggle.entry-Bx7cG_fC.js} +4 -4
  43. package/dist/cjs/nv-togglebutton.entry-CeYlChll.js +55 -0
  44. package/dist/cjs/nv-togglebuttongroup.entry-ehe00MUL.js +169 -0
  45. package/dist/cjs/{nv-tooltip.entry-D9nl_ejz.js → nv-tooltip.entry-CCDVLdqi.js} +2 -2
  46. package/dist/generated/components.js +24 -0
  47. package/dist/generated/components.server.js +41 -4
  48. package/dist/types/generated/components.d.ts +16 -0
  49. package/dist/types/generated/components.server.d.ts +16 -0
  50. package/package.json +1 -1
  51. package/dist/cjs/nv-badge_2.entry-BGWUswPo.js +0 -206
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-BtjpbnUr.js');
3
+ var index = require('./index-B-1F0q3j.js');
4
4
  var v4A79185f4 = require('./v4-a79185f4-2n0dOd_Y.js');
5
5
  require('react');
6
6
 
7
- const nvFieldmultiselectCss = "nv-fieldslider .slider-container .track-container:has(.thumb:hover) .track-range{background:var(--components-slider-track-filled-hover)}nv-fieldslider .slider-container .track-container:has(.thumb:hover) .thumb{border-color:var(--components-slider-track-filled-hover)}nv-fieldslider .slider-container .track-container:has(.thumb:focus) .track-range{background:var(--components-slider-track-filled-focus)}nv-fieldslider .slider-container .track-container:has(.thumb:focus) .thumb{border-color:var(--components-slider-track-filled-focus)}nv-fieldslider[error] .slider-container .track-container .track .track-range{background:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container .track .thumb{border-color:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container .track .thumb:hover{border-color:var(--components-slider-track-filled-error);outline:calc(var(--focus-outline-stroke) * 1) solid var(--components-slider-track-filled-error);outline-offset:calc(var(--focus-outline-offset) * 1);background-color:var(--components-slider-handler-background-error)}nv-fieldslider[error] .slider-container .track-container .track .thumb:focus{border-color:var(--components-slider-track-filled-error);outline:calc(var(--focus-outline-stroke) * 1) solid var(--components-slider-track-filled-error);outline-offset:calc(var(--focus-outline-offset) * 1);background-color:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container:has(.thumb:hover) .track-range{background:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container:has(.thumb:hover) .thumb{border-color:var(--components-slider-track-filled-error)}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;max-width:480px}nv-fieldmultiselect[fluid]:not([fluid=false]){max-width:unset}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-in-field)}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 nv-popover [data-scope=popover]{width:100%;padding:var(--list-dropdown-padding);border-radius:var(--list-dropdown-radius);background-color:var(--components-list-dropdown-background);border:1px solid var(--components-list-dropdown-border)}nv-fieldmultiselect nv-popover [slot=content]{gap:var(--list-dropdown-gap-y);display:flex;flex-direction:column}nv-fieldmultiselect nv-popover hr{color:var(--components-list-dropdown-separator)}nv-fieldmultiselect nv-popover div[slot=content]{max-height:calc(90vh - var(--list-dropdown-padding) * 2);overflow-y:auto;position:relative}nv-fieldmultiselect nv-popover div[slot=content]::-webkit-scrollbar{width:6px;height:6px}nv-fieldmultiselect nv-popover div[slot=content]::-webkit-scrollbar-track{background-color:var(--color-level-10-background);border-radius:9999px}nv-fieldmultiselect nv-popover div[slot=content]::-webkit-scrollbar-thumb{background-color:var(--color-gray-200);border-radius:9999px}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;justify-content:center;align-items:center;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, 1);background:var(--nv-field-background);transition:all 150ms ease-out;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,nv-fieldmultiselect .input-container-multiselect:focus-within:hover,nv-fieldmultiselect .input-container-multiselect:focus,nv-fieldmultiselect .input-container-multiselect:focus: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 .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>nv-badge{margin-left:var(--form-field-padding-x)}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);padding:var(--form-field-padding-y) var(--form-field-padding-x);font-size:var(--form-field-font-size);font-style:normal;font-weight:500;line-height:var(--form-field-line-height);width:100%;width:100%;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 input[type=password]::-ms-clear,nv-fieldmultiselect .input-container-multiselect input[type=password]::-ms-reveal,nv-fieldmultiselect .input-container-multiselect p.non-filterable-text[type=password]::-ms-clear,nv-fieldmultiselect .input-container-multiselect p.non-filterable-text[type=password]::-ms-reveal{display:none;width:0;height:0}nv-fieldmultiselect .input-container-multiselect>nv-iconbutton{border:0px;border-radius:0px}nv-fieldmultiselect .input-container-multiselect>nv-iconbutton:focus-visible{border-radius:var(--button-md-border-radius);outline-offset:-3px}nv-fieldmultiselect .input-container-multiselect nv-icon.validation{color:var(--nv-field-border-default)}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{display:flex;align-items:center;align-self:stretch;gap:var(--spacing-1);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{display:flex;align-items:center;align-self:stretch;gap:var(--spacing-1);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)}.no-results-message{text-align:center;padding:10px;color:var(--components-form-text-description-error)}.multiselect-divider{display:block;width:100%;height:1px;background-color:var(--components-list-dropdown-separator);margin:var(--list-dropdown-item-padding-y) 0;border:0}";
7
+ const nvFieldmultiselectCss = "nv-fieldslider .slider-container .track-container:has(.thumb:hover) .track-range{background:var(--components-slider-track-filled-hover)}nv-fieldslider .slider-container .track-container:has(.thumb:hover) .thumb{border-color:var(--components-slider-track-filled-hover)}nv-fieldslider .slider-container .track-container:has(.thumb:focus) .track-range{background:var(--components-slider-track-filled-focus)}nv-fieldslider .slider-container .track-container:has(.thumb:focus) .thumb{border-color:var(--components-slider-track-filled-focus)}nv-fieldslider[error] .slider-container .track-container .track .track-range{background:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container .track .thumb{border-color:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container .track .thumb:hover{border-color:var(--components-slider-track-filled-error);outline:calc(var(--focus-outline-stroke) * 1) solid var(--components-slider-track-filled-error);outline-offset:calc(var(--focus-outline-offset) * 1);background-color:var(--components-slider-handler-background-error)}nv-fieldslider[error] .slider-container .track-container .track .thumb:focus{border-color:var(--components-slider-track-filled-error);outline:calc(var(--focus-outline-stroke) * 1) solid var(--components-slider-track-filled-error);outline-offset:calc(var(--focus-outline-offset) * 1);background-color:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container:has(.thumb:hover) .track-range{background:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container:has(.thumb:hover) .thumb{border-color:var(--components-slider-track-filled-error)}nv-fieldslider .slider-container .track-container:has(.thumb:hover) .track-range{background:var(--components-slider-track-filled-hover)}nv-fieldslider .slider-container .track-container:has(.thumb:hover) .thumb{border-color:var(--components-slider-track-filled-hover)}nv-fieldslider .slider-container .track-container:has(.thumb:focus) .track-range{background:var(--components-slider-track-filled-focus)}nv-fieldslider .slider-container .track-container:has(.thumb:focus) .thumb{border-color:var(--components-slider-track-filled-focus)}nv-fieldslider[error] .slider-container .track-container .track .track-range{background:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container .track .thumb{border-color:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container .track .thumb:hover{border-color:var(--components-slider-track-filled-error);outline:calc(var(--focus-outline-stroke) * 1) solid var(--components-slider-track-filled-error);outline-offset:calc(var(--focus-outline-offset) * 1);background-color:var(--components-slider-handler-background-error)}nv-fieldslider[error] .slider-container .track-container .track .thumb:focus{border-color:var(--components-slider-track-filled-error);outline:calc(var(--focus-outline-stroke) * 1) solid var(--components-slider-track-filled-error);outline-offset:calc(var(--focus-outline-offset) * 1);background-color:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container:has(.thumb:hover) .track-range{background:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container:has(.thumb:hover) .thumb{border-color:var(--components-slider-track-filled-error)}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;max-width:480px}nv-fieldmultiselect[fluid]:not([fluid=false]){max-width:unset}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-in-field)}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 nv-popover [data-scope=popover]{width:100%;padding:var(--list-dropdown-padding);border-radius:var(--list-dropdown-radius);background-color:var(--components-list-dropdown-background);border:1px solid var(--components-list-dropdown-border)}nv-fieldmultiselect nv-popover [slot=content]{gap:var(--list-dropdown-gap-y);display:flex;flex-direction:column}nv-fieldmultiselect nv-popover hr{color:var(--components-list-dropdown-separator)}nv-fieldmultiselect nv-popover div[slot=content]{max-height:calc(90vh - var(--list-dropdown-padding) * 2);overflow-y:auto;position:relative}nv-fieldmultiselect nv-popover div[slot=content]::-webkit-scrollbar{width:6px;height:6px}nv-fieldmultiselect nv-popover div[slot=content]::-webkit-scrollbar-track{background-color:var(--color-level-10-background);border-radius:9999px}nv-fieldmultiselect nv-popover div[slot=content]::-webkit-scrollbar-thumb{background-color:var(--color-gray-200);border-radius:9999px}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;justify-content:center;align-items:center;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, 1);background:var(--nv-field-background);transition:all 150ms ease-out;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,nv-fieldmultiselect .input-container-multiselect:focus-within:hover,nv-fieldmultiselect .input-container-multiselect:focus,nv-fieldmultiselect .input-container-multiselect:focus: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 .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>nv-badge{margin-left:var(--form-field-padding-x)}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);padding:var(--form-field-padding-y) var(--form-field-padding-x);font-size:var(--form-field-font-size);font-style:normal;font-weight:500;line-height:var(--form-field-line-height);width:100%;width:100%;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 input[type=password]::-ms-clear,nv-fieldmultiselect .input-container-multiselect input[type=password]::-ms-reveal,nv-fieldmultiselect .input-container-multiselect p.non-filterable-text[type=password]::-ms-clear,nv-fieldmultiselect .input-container-multiselect p.non-filterable-text[type=password]::-ms-reveal{display:none;width:0;height:0}nv-fieldmultiselect .input-container-multiselect>nv-iconbutton{border:0px;border-radius:0px}nv-fieldmultiselect .input-container-multiselect>nv-iconbutton:focus-visible{border-radius:var(--button-md-border-radius);outline-offset:-3px}nv-fieldmultiselect .input-container-multiselect nv-icon.validation{color:var(--nv-field-border-default)}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{display:flex;align-items:center;align-self:stretch;gap:var(--spacing-1);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{display:flex;align-items:center;align-self:stretch;gap:var(--spacing-1);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)}.no-results-message{cursor:not-allowed;background-color:unset;color:var(--components-menu-contextual-item-content-disabled);padding:var(--list-dropdown-item-padding-y) var(--list-dropdown-item-padding-x)}.multiselect-divider{display:block;width:100%;height:1px;background-color:var(--components-list-dropdown-separator);margin:var(--list-dropdown-item-padding-y) 0;border:0}.select-all-container{position:sticky;top:0;background-color:var(--components-list-dropdown-background);border-bottom:1px solid var(--components-list-dropdown-separator);padding:var(--list-dropdown-item-padding-y) var(--list-dropdown-item-padding-x);z-index:10;margin-bottom:0}.select-all-container .select-all-header{display:flex;align-items:center;gap:var(--form-field-gap)}.select-all-container .select-all-header nv-fieldcheckbox{flex:1;margin:0}.select-all-container .select-all-header nv-iconbutton,.select-all-container .select-all-header nv-button{flex-shrink:0;margin-left:auto}.select-all-container .select-all-header nv-button{justify-content:center}";
8
8
  const NvFieldmultiselectStyle0 = nvFieldmultiselectCss;
9
9
 
10
10
  const NvFieldmultiselect = class {
@@ -12,8 +12,7 @@ const NvFieldmultiselect = class {
12
12
  index.registerInstance(this, hostRef);
13
13
  this.valueChanged = index.createEvent(this, "valueChanged");
14
14
  this.filterTextChanged = index.createEvent(this, "filterTextChanged");
15
- /****************************************************************************/
16
- //#region PROPERTIES
15
+ this.isBulkOperation = false;
17
16
  /**
18
17
  * Sets the ID for the input element and the for attribute of the associated
19
18
  * label. If no ID is provided, a random one will be automatically generated
@@ -28,11 +27,6 @@ const NvFieldmultiselect = class {
28
27
  * always type in fresh data.
29
28
  */
30
29
  this.autocomplete = 'off';
31
- /**
32
- * Specifies the selected values of the multiselect field.
33
- * This is the canonical value for the component and is used for form submission.
34
- */
35
- this.value = [];
36
30
  /**
37
31
  * Marks the input field as required.
38
32
  */
@@ -60,13 +54,22 @@ const NvFieldmultiselect = class {
60
54
  */
61
55
  this.open = false;
62
56
  /**
63
- * The text to display when no items match the filter.
57
+ * Allows the field to stretch and fill the entire width of its container.
64
58
  */
65
- this.emptyResult = 'No results found';
59
+ this.fluid = false;
60
+ /**
61
+ * Specifies the selected values of the multiselect field.
62
+ * This is the canonical value for the component and is used for form submission.
63
+ */
64
+ this.value = [];
66
65
  /**
67
66
  * Enables or disables the filtering feature for the multiselect items.
68
67
  */
69
68
  this.filterable = false;
69
+ /**
70
+ * The text to display when no items match the filter.
71
+ */
72
+ this.emptyResult = 'No results found';
70
73
  /**
71
74
  * Delay in milliseconds before the search is triggered when typing in the filter input.
72
75
  * @default 300
@@ -78,10 +81,6 @@ const NvFieldmultiselect = class {
78
81
  * element.
79
82
  */
80
83
  this.autofocus = false;
81
- /**
82
- * Allows the field to stretch and fill the entire width of its container.
83
- */
84
- this.fluid = false;
85
84
  /**
86
85
  * Text for the badge showing the number of selected items.
87
86
  */
@@ -90,6 +89,18 @@ const NvFieldmultiselect = class {
90
89
  * The text entered by the user for filtering multiselect items.
91
90
  */
92
91
  this.filterText = '';
92
+ /**
93
+ * Enables or disables the "Select All / Deselect All" toggle functionality.
94
+ */
95
+ this.enableSelectAll = false;
96
+ /**
97
+ * Text for the "Select All" button.
98
+ */
99
+ this.selectAllLabel = 'Select/deselect all';
100
+ /**
101
+ * Text for the "Deselect All" button.
102
+ */
103
+ this.deselectAllLabel = 'Select/deselect all';
93
104
  //#endregion PROPERTIES
94
105
  /****************************************************************************/
95
106
  //#region STATE
@@ -98,10 +109,25 @@ const NvFieldmultiselect = class {
98
109
  */
99
110
  this.sortedOptions = [];
100
111
  this.isHandlingEscape = false;
112
+ /**
113
+ * Indicates whether the current filter has visible results.
114
+ * Used to control the visibility of the "Select All" button.
115
+ */
116
+ this.hasFilterResults = true;
117
+ /**
118
+ * Controls the visibility of the select all section.
119
+ */
120
+ this.isSelectAllSectionVisible = true;
121
+ // Add the flag to the class
122
+ this.preventBlurClose = false;
123
+ this.handleMouseDownPreventBlur = () => {
124
+ this.preventBlurClose = true;
125
+ };
101
126
  /**
102
127
  * Handle badge close for options mode.
103
128
  */
104
129
  this.handleBadgeCloseOptions = () => {
130
+ console.info('handleBadgeCloseOptions:', this.value);
105
131
  this.value = [];
106
132
  this.valueChanged.emit(this.value);
107
133
  // Uncheck all elements
@@ -119,6 +145,7 @@ const NvFieldmultiselect = class {
119
145
  * Handle badge close for slots mode.
120
146
  */
121
147
  this.handleBadgeCloseSlots = () => {
148
+ console.info('handleBadgeCloseSlots:', this.value);
122
149
  this.value = [];
123
150
  this.valueChanged.emit(this.value);
124
151
  // Uncheck all elements
@@ -127,8 +154,11 @@ const NvFieldmultiselect = class {
127
154
  item.checked = false;
128
155
  item.style.display = '';
129
156
  });
130
- // Reorder slot content
131
- this.reorderSlotContent();
157
+ // Force DOM update before reordering
158
+ requestAnimationFrame(() => {
159
+ // Reorder slot content
160
+ this.reorderSlotContent();
161
+ });
132
162
  };
133
163
  /**
134
164
  * Handle popover close
@@ -150,12 +180,17 @@ const NvFieldmultiselect = class {
150
180
  this.filterText = '';
151
181
  this.filterTextChanged.emit('');
152
182
  this.resetFilter();
183
+ this.hasFilterResults = true;
153
184
  };
154
185
  /**
155
186
  * Handle input blur for options mode.
156
187
  */
157
188
  this.handleInputBlurOptions = () => {
158
189
  setTimeout(() => {
190
+ if (this.preventBlurClose) {
191
+ this.preventBlurClose = false;
192
+ return; // Don't close the popover
193
+ }
159
194
  if (!this.el.contains(document.activeElement)) {
160
195
  // Close the popover without affecting the divider
161
196
  this.open = false;
@@ -274,6 +309,11 @@ const NvFieldmultiselect = class {
274
309
  */
275
310
  this.handleInputBlurSlots = () => {
276
311
  setTimeout(() => {
312
+ // Honor preventBlurClose to avoid closing when interacting inside the popover
313
+ if (this.preventBlurClose) {
314
+ this.preventBlurClose = false;
315
+ return; // Don't close the popover
316
+ }
277
317
  if (!this.el.contains(document.activeElement)) {
278
318
  // Close the popover without affecting the divider
279
319
  this.open = false;
@@ -302,6 +342,120 @@ const NvFieldmultiselect = class {
302
342
  }
303
343
  this.open = !this.open;
304
344
  };
345
+ /**
346
+ * Toggles the selection state of all non-disabled options in options mode.
347
+ * Respects filtering by only selecting/deselecting visible items.
348
+ * @param {boolean} selectAll - Whether to select all items (true) or deselect all (false)
349
+ */
350
+ this.toggleSelectAllOptions = (selectAll) => {
351
+ if (!this.options)
352
+ return;
353
+ this.isBulkOperation = true; // Set flag to suppress individual emissions
354
+ try {
355
+ // Get visible and enabled option values from DOM
356
+ const visibleOptionValues = this.getVisibleEnabledOptionItems();
357
+ console.info('[SelectAll][Options] toggleSelectAllOptions called. selectAll:', selectAll, 'visibleOptionValues:', visibleOptionValues, 'Current value:', this.value);
358
+ if (selectAll) {
359
+ // Select all visible options - merge with existing selections
360
+ this.value = [...new Set([...this.value, ...visibleOptionValues])];
361
+ }
362
+ else {
363
+ // Deselect only the visible options, keep others that might be filtered out
364
+ this.value = this.value.filter(val => !visibleOptionValues.includes(val));
365
+ }
366
+ console.info('[SelectAll][Options] New value after toggle:', this.value);
367
+ // Emit the change event
368
+ this.valueChanged.emit(this.value);
369
+ // Synchronize child components
370
+ this.syncChildComponents();
371
+ // Reorder content to move selected items to top
372
+ this.reorderOptionsContent();
373
+ }
374
+ finally {
375
+ // Defer reset to next frame to ensure any async child emissions are ignored
376
+ requestAnimationFrame(() => {
377
+ this.isBulkOperation = false; // Reset flag
378
+ });
379
+ }
380
+ };
381
+ /**
382
+ * Toggles the selection state of all non-disabled slot items.
383
+ * @param {boolean} selectAll - Whether to select all items (true) or deselect all (false)
384
+ */
385
+ this.toggleSelectAllSlots = (selectAll) => {
386
+ if (this.options)
387
+ return; // Only for slots mode
388
+ this.isBulkOperation = true; // Set flag to suppress individual emissions
389
+ try {
390
+ // Get visible and enabled items
391
+ const items = this.getVisibleEnabledSlotItems();
392
+ console.info('[SelectAll][Slots] toggleSelectAllSlots called. selectAll:', selectAll, 'visible slot items:', items.map(item => item.getAttribute('value') || item.getAttribute('label')), 'Current value:', this.value);
393
+ if (selectAll) {
394
+ // Select all visible items
395
+ const allActiveValues = items
396
+ .map(item => item.getAttribute('value') || item.getAttribute('label') || '')
397
+ .filter(value => value !== '');
398
+ this.value = [...new Set([...this.value, ...allActiveValues])];
399
+ }
400
+ else {
401
+ // Deselect only the visible items, keep others that might be filtered out
402
+ const visibleValues = items
403
+ .map(item => item.getAttribute('value') || item.getAttribute('label') || '')
404
+ .filter(value => value !== '');
405
+ this.value = this.value.filter(val => !visibleValues.includes(val));
406
+ }
407
+ console.info('[SelectAll][Slots] New value after toggle:', this.value);
408
+ // Emit the change event
409
+ this.valueChanged.emit(this.value);
410
+ // Force synchronization with a small delay to ensure DOM is updated
411
+ requestAnimationFrame(() => {
412
+ this.syncChildComponents();
413
+ this.reorderSlotContent();
414
+ });
415
+ }
416
+ finally {
417
+ // Defer reset to next frame to ensure any async child emissions are ignored
418
+ requestAnimationFrame(() => {
419
+ this.isBulkOperation = false; // Reset flag
420
+ });
421
+ }
422
+ };
423
+ /**
424
+ * Handle click on the select all checkbox in options mode.
425
+ * @param {Event} event - The click event.
426
+ */
427
+ this.handleSelectAllCheckboxOptionsClick = (event) => {
428
+ event.stopPropagation();
429
+ event.preventDefault();
430
+ console.info('[handleSelectAllCheckboxOptionsClick] event:', event);
431
+ const currentState = this.getSelectAllCheckboxStateOptions();
432
+ console.info('[SelectAll][Options] Checkbox clicked. Current state:', currentState, 'Current value:', this.value);
433
+ // Logic to handle the indeterminate state
434
+ // - unchecked → select all
435
+ // - indeterminate → select all (clicking on indeterminate will change to checked)
436
+ // - checked → deselect all
437
+ const shouldSelectAll = currentState === 'unchecked' || currentState === 'indeterminate';
438
+ console.info('[SelectAll][Options] shouldSelectAll:', shouldSelectAll);
439
+ this.toggleSelectAllOptions(shouldSelectAll);
440
+ };
441
+ /**
442
+ * Handle click on the select all checkbox in slots mode.
443
+ * @param {Event} event - The click event.
444
+ */
445
+ this.handleSelectAllCheckboxSlotsClick = (event) => {
446
+ event.stopPropagation();
447
+ event.preventDefault();
448
+ console.info('[handleSelectAllCheckboxSlotsClick] event:', event);
449
+ const currentState = this.getSelectAllCheckboxStateSlots();
450
+ console.info('[SelectAll][Slots] Checkbox clicked. Current state:', currentState, 'Current value:', this.value);
451
+ // Logic to handle the indeterminate state
452
+ // - unchecked → select all
453
+ // - indeterminate → select all (clicking on indeterminate will change to checked)
454
+ // - checked → deselect all
455
+ const shouldSelectAll = currentState === 'unchecked' || currentState === 'indeterminate';
456
+ console.info('[SelectAll][Slots] shouldSelectAll:', shouldSelectAll);
457
+ this.toggleSelectAllSlots(shouldSelectAll);
458
+ };
305
459
  //#endregion METHODS
306
460
  /****************************************************************************/
307
461
  //#region RENDER
@@ -310,35 +464,76 @@ const NvFieldmultiselect = class {
310
464
  * @returns {any} The JSX for options mode
311
465
  */
312
466
  this.renderOptionsMode = () => {
313
- return (index.h(index.Host, { "aria-label": this.label, "aria-expanded": this.open.toString() }, (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" }), this.value.length > 0 && (index.h("nv-badge", { slot: "leading-input", "prevent-auto-close": true, color: "10", dismissible: this.value.length > 0, label: `${this.value.length} ${this.badgeLabel}`, "aria-label": `Clear all ${this.value.length} ${this.badgeLabel} items`, onCloseClicked: this.handleBadgeCloseOptions })), this.filterable || this.disabled || this.readonly ? (index.h("input", { type: "text", id: this.inputId, ref: e => (this.inputElement = e), autofocus: this.autofocus, autocomplete: this.autocomplete, placeholder: this.placeholder, name: this.name, value: this.filterText, required: this.required, disabled: this.disabled, readOnly: this.readonly, onInput: this.handleInputOptions, onFocus: this.handleInputFocusOptions, onBlur: this.handleInputBlurOptions, onKeyDown: this.handleKeyDown, "data-scope": "focusable" })) : (index.h("p", { id: this.inputId, class: "non-filterable-text", onClick: this.handleInputContainerClickOptions, tabIndex: 0, onKeyDown: this.handleKeyDown, onFocus: this.handleInputFocusOptions, role: "combobox", "aria-expanded": this.open, "data-scope": "focusable" }, index.h("span", null, this.placeholder))), this.error && (index.h("nv-icon", { name: "alert-circle", class: "validation", size: "md" })), this.filterable && this.filterText.length > 0 && (index.h("nv-iconbutton", { "data-scope": "clear-filter", name: "x", size: "md", emphasis: "lower", tabindex: "-1", onClick: this.clearFilterText, "aria-label": "Clear filter text" })), index.h("nv-iconbutton", { "data-scope": "toggle-dropdown", 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: this.maxHeight ? { maxHeight: this.maxHeight } : {} }, index.h("ul", { role: "content" }, this.options.map(option => (index.h("nv-fielddropdownitemcheck", { label: option.label, description: option.description, value: option.value, checked: this.value.includes(option.value), disabled: option.disabled }))), index.h("hr", { class: "multiselect-divider", style: { display: 'none' } })))), this.renderDescriptions()));
467
+ return (index.h(index.Host, { "aria-label": this.label }, (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" }), this.value.length > 0 && (index.h("nv-badge", { slot: "leading-input", "prevent-auto-close": true, color: "10", dismissible: this.value.length > 0, label: `${this.value.length} ${this.badgeLabel}`, "aria-label": `Clear all ${this.value.length} ${this.badgeLabel} items`, onCloseClicked: this.handleBadgeCloseOptions })), this.filterable || this.disabled || this.readonly ? (index.h("input", { type: "text", id: this.inputId, ref: e => (this.inputElement = e), autofocus: this.autofocus, autocomplete: this.autocomplete, placeholder: this.placeholder, name: this.name, value: this.filterText, required: this.required, disabled: this.disabled, readOnly: this.readonly, onInput: this.handleInputOptions, onFocus: this.handleInputFocusOptions, onBlur: this.handleInputBlurOptions, onKeyDown: this.handleKeyDown, "data-scope": "focusable", "aria-label": this.label, "aria-controls": `${this.inputId}-listbox` })) : (index.h(index.Fragment, null, index.h("input", { id: this.inputId, type: "text", style: {
468
+ position: 'absolute',
469
+ opacity: '0',
470
+ width: '0',
471
+ height: '0',
472
+ pointerEvents: 'none',
473
+ }, tabIndex: -1, "aria-hidden": "true", autoComplete: this.autocomplete, name: this.name, onFocus: this.handleInputFocusOptions }), index.h("p", { id: this.inputId, class: "non-filterable-text", onClick: this.handleInputContainerClickOptions, tabIndex: 0, onKeyDown: this.handleKeyDown, onFocus: this.handleInputFocusOptions, "aria-label": this.label, "aria-controls": `${this.inputId}-listbox`, "data-scope": "focusable", role: "button" }, index.h("span", null, this.placeholder)))), this.error && (index.h("nv-icon", { name: "alert-circle", class: "validation", size: "md" })), this.filterable && this.filterText.length > 0 && (index.h("nv-iconbutton", { "data-scope": "clear-filter", name: "x", size: "md", emphasis: "lower", "aria-label": "Clear filter text", tabindex: "-1", title: "Clear filter text", onMouseDown: this.handleMouseDownPreventBlur, onClick: this.clearFilterText })), index.h("nv-iconbutton", { "data-scope": "toggle-dropdown", name: this.open ? 'chevron-top' : 'chevron-down', size: "md", emphasis: "lower", "aria-label": this.open ? 'Hide dropdown' : 'Show dropdown', title: this.open ? 'Hide dropdown' : 'Show dropdown', onMouseDown: this.handleMouseDownPreventBlur, onClick: this.togglePopoverOptions })), index.h("slot", { name: "after-input" })), index.h("div", { id: `${this.inputId}-listbox`, slot: "content", style: this.maxHeight ? { maxHeight: this.maxHeight } : {}, onMouseDown: this.handleMouseDownPreventBlur }, this.shouldShowToggleAllOptionsButton() && (index.h("div", { class: "select-all-container" }, index.h("div", { class: "select-all-header" }, this.isSelectAllSectionVisible && (index.h("nv-fieldcheckbox", { checked: this.getSelectAllCheckboxStateOptions() === 'checked', indeterminate: this.getSelectAllCheckboxStateOptions() ===
474
+ 'indeterminate', label: this.getSelectAllCheckboxStateOptions() === 'unchecked'
475
+ ? this.selectAllLabel
476
+ : this.deselectAllLabel, onMouseDown: this.handleMouseDownPreventBlur, onClick: this.handleSelectAllCheckboxOptionsClick }))))), index.h("ul", { role: "listbox", "aria-multiselectable": "true" }, this.options.map(option => (index.h("nv-fielddropdownitemcheck", { role: "option", label: option.label, description: option.description, value: option.value, checked: this.value.includes(option.value), disabled: option.disabled })))))), this.renderDescriptions()));
314
477
  };
315
478
  /**
316
479
  * Renders the component in slots mode
317
480
  * @returns {any} The JSX for slots mode
318
481
  */
319
482
  this.renderSlotsMode = () => {
320
- return (index.h(index.Host, { "aria-label": this.label, "aria-expanded": this.open.toString() }, (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" }), this.value.length > 0 && (index.h("nv-badge", { slot: "leading-input", "prevent-auto-close": true, color: "10", dismissible: this.value.length > 0, label: `${this.value.length} ${this.badgeLabel}`, "aria-label": `Clear all ${this.value.length} ${this.badgeLabel} items`, onCloseClicked: this.handleBadgeCloseSlots })), this.filterable || 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.filterText, required: this.required, disabled: this.disabled, readOnly: this.readonly, onInput: this.handleInputSlots, onFocus: this.handleInputFocusSlots, onBlur: this.handleInputBlurSlots, onKeyDown: this.handleKeyDown, "data-scope": "focusable" })) : (index.h("p", { id: this.inputId, class: "non-filterable-text", onClick: this.handleInputContainerClickSlots, tabIndex: 0, onKeyDown: this.handleKeyDown, onFocus: this.handleInputFocusSlots, role: "combobox", "aria-expanded": this.open, "data-scope": "focusable" }, index.h("span", null, this.placeholder))), this.error && (index.h("nv-icon", { name: "alert-circle", class: "validation", size: "md" })), this.filterable && this.filterText.length > 0 && (index.h("nv-iconbutton", { name: "x", size: "md", emphasis: "lower", tabindex: "-1", onClick: this.clearFilterText, "aria-label": "Clear filter text" })), index.h("nv-iconbutton", { "data-scope": "toggle-dropdown", 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: this.maxHeight ? { maxHeight: this.maxHeight } : {} }, index.h("slot", { name: "content" }))), this.renderDescriptions()));
483
+ return (index.h(index.Host, { "aria-label": this.label }, (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" }), this.value.length > 0 && (index.h("nv-badge", { slot: "leading-input", "prevent-auto-close": true, color: "10", dismissible: this.value.length > 0, label: `${this.value.length} ${this.badgeLabel}`, "aria-label": `Clear all ${this.value.length} ${this.badgeLabel} items`, onCloseClicked: this.handleBadgeCloseSlots })), this.filterable || 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.filterText, required: this.required, disabled: this.disabled, readOnly: this.readonly, onInput: this.handleInputSlots, onFocus: this.handleInputFocusSlots, onBlur: this.handleInputBlurSlots, onKeyDown: this.handleKeyDown, "data-scope": "focusable", "aria-label": this.label, "aria-controls": `${this.inputId}-listbox` })) : (index.h(index.Fragment, null, index.h("input", { id: this.inputId, type: "text", style: {
484
+ position: 'absolute',
485
+ opacity: '0',
486
+ width: '0',
487
+ height: '0',
488
+ pointerEvents: 'none',
489
+ }, tabIndex: -1, "aria-hidden": "true", autoComplete: this.autocomplete, name: this.name, onFocus: this.handleInputFocusSlots }), index.h("p", { id: this.inputId, class: "non-filterable-text", "aria-label": this.label, onClick: this.handleInputContainerClickSlots, tabIndex: 0, onKeyDown: this.handleKeyDown, onFocus: this.handleInputFocusSlots, "aria-controls": `${this.inputId}-listbox`, "data-scope": "focusable", role: "button" }, index.h("span", null, this.placeholder)))), this.error && (index.h("nv-icon", { name: "alert-circle", class: "validation", size: "md" })), this.filterable && this.filterText.length > 0 && (index.h("nv-iconbutton", { name: "x", size: "md", emphasis: "lower", tabindex: "-1", onMouseDown: this.handleMouseDownPreventBlur, onClick: this.clearFilterText, "aria-label": "Clear filter text" })), index.h("nv-iconbutton", { "data-scope": "toggle-dropdown", name: this.open ? 'chevron-top' : 'chevron-down', size: "md", emphasis: "lower", "aria-label": this.open ? 'Hide dropdown' : 'Show dropdown', title: this.open ? 'Hide dropdown' : 'Show dropdown', onMouseDown: this.handleMouseDownPreventBlur, onClick: this.togglePopoverSlots })), index.h("slot", { name: "after-input" })), index.h("div", { id: `${this.inputId}-listbox`, slot: "content", style: this.maxHeight ? { maxHeight: this.maxHeight } : {}, onMouseDown: this.handleMouseDownPreventBlur }, this.shouldShowToggleAllSlotButton() && (index.h("div", { class: "select-all-container" }, index.h("div", { class: "select-all-header" }, this.isSelectAllSectionVisible && (index.h("nv-fieldcheckbox", { checked: this.getSelectAllCheckboxStateSlots() === 'checked', indeterminate: this.getSelectAllCheckboxStateSlots() ===
490
+ 'indeterminate', label: this.getSelectAllCheckboxStateSlots() === 'unchecked'
491
+ ? this.selectAllLabel
492
+ : this.deselectAllLabel, onMouseDown: this.handleMouseDownPreventBlur, onClick: this.handleSelectAllCheckboxSlotsClick }))))), index.h("slot", { name: "content" }))), this.renderDescriptions()));
321
493
  };
322
494
  }
323
495
  //#endregion EVENTS
324
496
  /****************************************************************************/
325
497
  //#region WATCHERS
326
498
  handleOptionsChange(newValue) {
499
+ console.info('[Watch:options] newValue:', newValue);
500
+ console.info('[Watch:options] current value before update:', this.value);
327
501
  if (!newValue)
328
502
  return;
329
- this.value = newValue
330
- .filter(option => option.checked)
331
- .map(option => option.value);
503
+ // If the parent has set a value prop, use it. Otherwise, derive from checked options.
504
+ // (Assume: if value is undefined, it's not set by parent; if it's an array, it's set.)
505
+ if (this.value === undefined || this.value.length === 0) {
506
+ this.value = newValue
507
+ .filter(option => option.checked)
508
+ .map(option => option.value);
509
+ console.info('[Watch:options] updated value from checked options:', this.value);
510
+ }
511
+ else {
512
+ // If value is set, ensure checked states in options match value
513
+ newValue.forEach(option => {
514
+ option.checked = this.value.includes(option.value);
515
+ });
516
+ console.info('[Watch:options] options checked state synced to value:', newValue);
517
+ }
332
518
  this.reorderOptionsContent();
333
519
  }
334
- /**
335
- * Emitted when the value changes.
336
- */
337
520
  watchValueHandler() {
521
+ console.info('[Watch:value] Value changed:', this.value, 'isBulkOperation:', this.isBulkOperation);
522
+ // Skip processing during bulk operations
523
+ if (this.isBulkOperation) {
524
+ console.info('[Watch:value] Skipping syncChildComponents and options update due to bulk operation');
525
+ return;
526
+ }
338
527
  // Synchronize child components when value changes programmatically
339
528
  if (this.el && this.el.isConnected) {
340
529
  this.syncChildComponents();
341
530
  }
531
+ // Also, update options checked state if options exist
532
+ if (this.options) {
533
+ this.options.forEach(option => {
534
+ option.checked = this.value.includes(option.value);
535
+ });
536
+ }
342
537
  }
343
538
  //#endregion WATCHERS
344
539
  /****************************************************************************/
@@ -373,32 +568,38 @@ const NvFieldmultiselect = class {
373
568
  * @param {CustomEvent} event - The event object containing the selected value and its checked state.
374
569
  */
375
570
  handleItemChecked(event) {
376
- if (this.disabled || this.readonly) {
571
+ if (this.disabled || this.readonly || this.isBulkOperation) {
572
+ // Skip processing itemChecked events during bulk operations
573
+ console.info('[Event:itemChecked] Skipped due to bulk operation or disabled/readonly', event.detail);
377
574
  return;
378
575
  }
379
576
  const { value, checked } = event.detail;
577
+ console.info('[Event:itemChecked] value:', value, 'checked:', checked, 'current value:', this.value);
380
578
  if (value !== undefined && value !== null) {
381
579
  const newValue = [...this.value];
382
580
  const valueIndex = newValue.indexOf(value);
581
+ let hasChanged = false;
383
582
  if (checked && valueIndex === -1) {
384
583
  newValue.push(value);
584
+ hasChanged = true;
385
585
  }
386
586
  else if (!checked && valueIndex > -1) {
387
587
  newValue.splice(valueIndex, 1);
588
+ hasChanged = true;
589
+ }
590
+ console.info('[Event:itemChecked] newValue after update:', newValue);
591
+ if (hasChanged) {
592
+ this.value = newValue;
593
+ this.valueChanged.emit(this.value);
594
+ this.syncChildComponents();
388
595
  }
389
- // Always update the state and emit the event when an item is checked/unchecked
390
- this.value = newValue;
391
- this.valueChanged.emit(this.value);
392
- // Update the checked state of all items to ensure consistency
393
- this.syncChildComponents();
394
596
  // Preserve the filter text in the input
395
597
  if (this.filterable && this.inputElement) {
396
- // Keep the current filter text in the input
397
598
  this.inputElement.value = this.filterText;
398
599
  }
399
600
  }
400
601
  else {
401
- console.warn('Received itemChecked event with undefined or null value'); // Warning log
602
+ console.warn('[Event:itemChecked] Received itemChecked event with undefined or null value'); // Warning log
402
603
  }
403
604
  }
404
605
  // Add a listener for the slot content
@@ -420,19 +621,27 @@ const NvFieldmultiselect = class {
420
621
  * Subscribe to click outside event.
421
622
  */
422
623
  connectedCallback() {
423
- document.addEventListener('click', this.handleClickOutside.bind(this));
624
+ console.info('[Lifecycle] connectedCallback - value:', this.value);
625
+ // Bind once and reuse the same reference for add/remove to avoid leaks
626
+ if (!this._boundHandleClickOutside) {
627
+ this._boundHandleClickOutside = this.handleClickOutside.bind(this);
628
+ }
629
+ document.addEventListener('click', this._boundHandleClickOutside);
424
630
  }
425
631
  /**
426
632
  * Set the mode state and handle options change.
427
633
  */
428
634
  componentWillLoad() {
429
635
  var _a;
636
+ console.info('[Lifecycle] componentWillLoad - value:', this.value, 'options:', this.options);
430
637
  // Don't call handleOptionsChange if we are in slots mode
431
638
  if (this.options) {
432
639
  this.handleOptionsChange(this.options);
433
640
  }
434
641
  // Specific initialization for slots mode
435
642
  if (!this.options) {
643
+ // Initialize value from checked slotted children
644
+ this.initializeValueFromSlots();
436
645
  // Use a microtask to ensure DOM is ready
437
646
  Promise.resolve().then(() => {
438
647
  // Synchronize child components
@@ -451,22 +660,33 @@ const NvFieldmultiselect = class {
451
660
  if (!this.filterText) {
452
661
  this.resetFilter();
453
662
  }
663
+ // Initialize filter results state
664
+ this.hasFilterResults = true;
454
665
  }
455
666
  /**
456
667
  * Force reorder if options mode in componentDidLoad because of the initial render not trigger @watch
457
668
  */
458
669
  componentDidLoad() {
670
+ console.info('[Lifecycle] componentDidLoad - value:', this.value, 'options:', this.options);
459
671
  if (this.options) {
460
672
  this.handleOptionsChange(this.options);
461
673
  }
462
674
  // Final synchronization of child components after everything is loaded
463
675
  this.syncChildComponents();
676
+ // For slots mode, ensure value is initialized from checked children if not already
677
+ if (!this.options) {
678
+ this.initializeValueFromSlots();
679
+ this.syncChildComponents();
680
+ }
464
681
  }
465
682
  /**
466
683
  * Unsubscribe from click outside event.
467
684
  */
468
685
  disconnectedCallback() {
469
- document.removeEventListener('click', this.handleClickOutside.bind(this));
686
+ console.info('[Lifecycle] disconnectedCallback - value:', this.value);
687
+ if (this._boundHandleClickOutside) {
688
+ document.removeEventListener('click', this._boundHandleClickOutside);
689
+ }
470
690
  }
471
691
  //#endregion LIFECYCLE
472
692
  /****************************************************************************/
@@ -500,14 +720,67 @@ const NvFieldmultiselect = class {
500
720
  this.manageDivider(ul, selectedItems, unselectedItems);
501
721
  }
502
722
  }
723
+ // Reset filter results state
724
+ this.hasFilterResults = true;
503
725
  }
504
726
  /**
505
727
  * Returns the list of selected values.
506
728
  * @returns {string[]} The selected values.
507
729
  */
508
730
  async getSelectedValues() {
731
+ console.info('getSelectedValues:', this.value);
509
732
  return this.value;
510
733
  }
734
+ /**
735
+ * Select all visible and enabled items.
736
+ * Works for both options and slots mode.
737
+ * @returns {Promise<void>}
738
+ */
739
+ async selectAll() {
740
+ if (this.disabled || this.readonly)
741
+ return;
742
+ if (this.options) {
743
+ this.toggleSelectAllOptions(true);
744
+ }
745
+ else {
746
+ this.toggleSelectAllSlots(true);
747
+ }
748
+ }
749
+ /**
750
+ * Deselect all visible and enabled items.
751
+ * Works for both options and slots mode.
752
+ * @returns {Promise<void>}
753
+ */
754
+ async deselectAll() {
755
+ if (this.disabled || this.readonly)
756
+ return;
757
+ if (this.options) {
758
+ this.toggleSelectAllOptions(false);
759
+ }
760
+ else {
761
+ this.toggleSelectAllSlots(false);
762
+ }
763
+ }
764
+ /**
765
+ * Toggle selection state of all visible and enabled items.
766
+ * If all items are selected, deselects all. Otherwise, selects all.
767
+ * Works for both options and slots mode.
768
+ * @returns {Promise<void>}
769
+ */
770
+ async toggleSelectAll() {
771
+ if (this.disabled || this.readonly)
772
+ return;
773
+ const currentState = this.options
774
+ ? this.getSelectAllCheckboxStateOptions()
775
+ : this.getSelectAllCheckboxStateSlots();
776
+ const shouldSelectAll = currentState === 'unchecked' || currentState === 'indeterminate';
777
+ if (this.options) {
778
+ this.toggleSelectAllOptions(shouldSelectAll);
779
+ }
780
+ else {
781
+ this.toggleSelectAllSlots(shouldSelectAll);
782
+ }
783
+ }
511
784
  /**
512
785
  * Reorder the content of the slot.
513
786
  */
@@ -551,7 +824,7 @@ const NvFieldmultiselect = class {
551
824
  * Reorder the content for options mode with async handling
552
825
  */
553
826
  reorderOptionsContent() {
554
- const ul = this.el.querySelector('ul[role="content"]');
827
+ const ul = this.el.querySelector('ul');
555
828
  if (!ul)
556
829
  return;
557
830
  const items = Array.from(ul.querySelectorAll('nv-fielddropdownitemcheck')).filter(item => item.style.display !== 'none');
@@ -659,6 +932,7 @@ const NvFieldmultiselect = class {
659
932
  this.removeEmptyMessageOption(ul);
660
933
  items.forEach(item => (item.style.display = ''));
661
934
  this.reorderOptionsContent(); // Reorder after reset
935
+ this.hasFilterResults = true; // Reset filter means we have results
662
936
  return;
663
937
  }
664
938
  // Filter the items
@@ -671,6 +945,8 @@ const NvFieldmultiselect = class {
671
945
  if (matchesFilter)
672
946
  hasVisibleItems = true;
673
947
  });
948
+ // Update the filter results state
949
+ this.hasFilterResults = hasVisibleItems;
674
950
  // Manage the divider with the visible items
675
951
  const visibleItems = items.filter(item => item.style.display !== 'none');
676
952
  const visibleSelected = visibleItems.filter(item => this.value.includes(item.getAttribute('value') || ''));
@@ -701,6 +977,7 @@ const NvFieldmultiselect = class {
701
977
  // If filter text is empty, reset all items visibility
702
978
  if (!this.filterText.trim()) {
703
979
  this.resetFilter();
980
+ this.hasFilterResults = true; // Reset filter means we have results
704
981
  return;
705
982
  }
706
983
  const normalizedFilter = this.normalizeText(this.filterText);
@@ -720,6 +997,8 @@ const NvFieldmultiselect = class {
720
997
  if (matchesFilter)
721
998
  hasVisibleItems = true;
722
999
  });
1000
+ // Update the filter results state
1001
+ this.hasFilterResults = hasVisibleItems;
723
1002
  // Get visible items after filtering
724
1003
  const visibleItems = items.filter(item => item.style.display !== 'none');
725
1004
  const visibleSelectedItems = visibleItems.filter(item => this.value.includes(item.getAttribute('value') || ''));
@@ -930,18 +1209,129 @@ const NvFieldmultiselect = class {
930
1209
  return;
931
1210
  }
932
1211
  const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
1212
+ console.info('[syncChildComponents] value:', this.value);
933
1213
  items.forEach(item => {
934
1214
  // Get the effective value: use explicit value if present, otherwise use label
935
1215
  const itemValue = item.getAttribute('value') || item.getAttribute('label') || '';
936
- if (this.value.includes(itemValue)) {
937
- item.setAttribute('checked', '');
938
- item.checked = true;
939
- }
940
- else {
941
- item.removeAttribute('checked');
942
- item.checked = false;
1216
+ const shouldBeChecked = this.value.includes(itemValue);
1217
+ console.info('[syncChildComponents] itemValue:', itemValue, 'shouldBeChecked:', shouldBeChecked, 'item.checked(before):', item.checked);
1218
+ // Only update if the checked state differs to avoid triggering unnecessary events
1219
+ if (item.checked !== shouldBeChecked) {
1220
+ // Set attribute and property, but avoid triggering itemChecked during bulk
1221
+ if (this.isBulkOperation) {
1222
+ // Directly update the DOM attribute to avoid triggering the setter
1223
+ if (shouldBeChecked) {
1224
+ item.setAttribute('checked', '');
1225
+ }
1226
+ else {
1227
+ item.removeAttribute('checked');
1228
+ }
1229
+ // Update internal state without emitting events (assumes nv-fielddropdownitemcheck respects this)
1230
+ item.checked = shouldBeChecked;
1231
+ }
1232
+ else {
1233
+ item.checked = shouldBeChecked;
1234
+ }
943
1235
  }
1236
+ console.info('[syncChildComponents] itemValue:', itemValue, 'item.checked(after):', item.checked);
1237
+ });
1238
+ }
1239
+ /**
1240
+ * Gets visible and enabled slot items using consistent logic.
1241
+ * @returns {Element[]} Array of visible and enabled items
1242
+ */
1243
+ getVisibleEnabledSlotItems() {
1244
+ const allItems = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
1245
+ return allItems.filter(item => {
1246
+ const isHidden = item.style.display === 'none';
1247
+ const isDisabled = item.hasAttribute('disabled');
1248
+ return !isHidden && !isDisabled;
1249
+ });
1250
+ }
1251
+ /**
1252
+ * Gets visible and enabled option items by checking DOM elements.
1253
+ * @returns {string[]} Array of visible and enabled option values
1254
+ */
1255
+ getVisibleEnabledOptionItems() {
1256
+ const allItems = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
1257
+ const visibleItems = allItems.filter(item => {
1258
+ const isHidden = item.style.display === 'none';
1259
+ const isDisabled = item.hasAttribute('disabled');
1260
+ return !isHidden && !isDisabled;
1261
+ });
1262
+ return visibleItems
1263
+ .map(item => item.getAttribute('value') || '')
1264
+ .filter(value => value !== '');
1265
+ }
1266
+ /**
1267
+ * Determines if the toggle all button should be shown in options mode.
1268
+ * @returns {boolean} True if there are visible items and no "No results found" message
1269
+ */
1270
+ shouldShowToggleAllOptionsButton() {
1271
+ if (!this.options)
1272
+ return false; // Only for options mode
1273
+ return this.enableSelectAll && this.hasFilterResults;
1274
+ }
1275
+ /**
1276
+ * Gets the checkbox state for the select all checkbox in options mode.
1277
+ * @returns {'checked' | 'unchecked' | 'indeterminate'} The checkbox state
1278
+ */
1279
+ getSelectAllCheckboxStateOptions() {
1280
+ if (!this.options)
1281
+ return 'unchecked';
1282
+ // Get visible and enabled option values from DOM
1283
+ const visibleOptionValues = this.getVisibleEnabledOptionItems();
1284
+ if (visibleOptionValues.length === 0)
1285
+ return 'unchecked';
1286
+ const selectedVisibleOptions = visibleOptionValues.filter(value => this.value.includes(value));
1287
+ if (selectedVisibleOptions.length === 0)
1288
+ return 'unchecked';
1289
+ if (selectedVisibleOptions.length === visibleOptionValues.length)
1290
+ return 'checked';
1291
+ return 'indeterminate';
1292
+ }
1293
+ /**
1294
+ * Gets the checkbox state for the select all checkbox in slots mode.
1295
+ * @returns {'checked' | 'unchecked' | 'indeterminate'} The checkbox state
1296
+ */
1297
+ getSelectAllCheckboxStateSlots() {
1298
+ if (this.options)
1299
+ return 'unchecked';
1300
+ // Get all visible and enabled items
1301
+ const items = this.getVisibleEnabledSlotItems();
1302
+ if (items.length === 0)
1303
+ return 'unchecked';
1304
+ const selectedItems = items.filter(item => {
1305
+ const itemValue = item.getAttribute('value') || item.getAttribute('label') || '';
1306
+ return itemValue !== '' && this.value.includes(itemValue);
944
1307
  });
1308
+ if (selectedItems.length === 0)
1309
+ return 'unchecked';
1310
+ if (selectedItems.length === items.length)
1311
+ return 'checked';
1312
+ return 'indeterminate';
1313
+ }
1314
+ /**
1315
+ * Determines if the toggle all button should be shown in slots mode.
1316
+ * @returns {boolean} True if there are visible items and no "No results found" message
1317
+ */
1318
+ shouldShowToggleAllSlotButton() {
1319
+ if (this.options)
1320
+ return false; // Only for slots mode
1321
+ return this.enableSelectAll && this.hasFilterResults;
1322
+ }
1323
+ /**
1324
+ * Initializes the value array from checked slotted nv-fielddropdownitemcheck elements (slots mode only).
1325
+ */
1326
+ initializeValueFromSlots() {
1327
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
1328
+ // Values from checked slot children
1329
+ const checkedValues = items
1330
+ .filter(item => item.hasAttribute('checked'))
1331
+ .map(item => item.getAttribute('value') || item.getAttribute('label') || '');
1332
+ // Combine with current this.value (set by code), ensuring uniqueness
1333
+ this.value = Array.from(new Set([...(this.value || []), ...checkedValues]));
1334
+ console.info('[initializeValueFromSlots] checkedValues:', checkedValues, 'combined value:', this.value);
945
1335
  }
946
1336
  /**
947
1337
  * Renders description and error description sections