@nova-design-system/nova-react 3.22.0 → 3.24.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.
- package/dist/cjs/_commonjsHelpers-B85MJLTf-CFO10eej.js +7 -0
- package/dist/cjs/{collapse.animation-6e0b08df-AHWzNGm_.js → collapse.animation-DZDm0vSK-C2TOIhIK.js} +3 -3
- package/dist/cjs/events.utils-B6GgGra--01N__3wY.js +23 -0
- package/dist/cjs/{fade.animation-9b939939-DV--bM4S.js → fade.animation-DcRL9lcm-DAZeHoKN.js} +75 -75
- package/dist/cjs/generated/components.server.js +292 -50
- package/dist/cjs/{grow.animation-24ad5cf8-LUp_ITEx.js → grow.animation-D7ep_aVl-BuXEDSK-.js} +5 -26
- package/dist/cjs/i18n.utils-IlwlcG9l-ku0bScip.js +2494 -0
- package/dist/cjs/{index-WPRkQD3O.js → index-kU2nW5aN.js} +12692 -7009
- package/dist/cjs/{nv-dialog.entry-CDSK9pUH.js → index.esm-D3eWMME9-CG1TVKfu.js} +1 -296
- package/dist/cjs/index.js +15 -1
- package/dist/cjs/inputmask-CSo292ul-DlvupPk6.js +3758 -0
- package/dist/cjs/{nv-accordion-item.entry-BuTvA6w9.js → nv-accordion-item.entry-Bu1tAcCq.js} +11 -10
- package/dist/cjs/{nv-accordion.entry-Dtsfw6He.js → nv-accordion.entry-jWjLdX8w.js} +9 -11
- package/dist/cjs/{nv-alert.entry-TIdfdU7Y.js → nv-alert.entry-E9ZJay_K.js} +22 -23
- package/dist/cjs/{nv-avatar.entry-CaxrhPuw.js → nv-avatar.entry-CUX7u0kR.js} +11 -11
- package/dist/cjs/{nv-badge_2.entry-CfYvTZxX.js → nv-badge_2.entry-bxpV5gxE.js} +24 -24
- package/dist/cjs/{nv-breadcrumb.entry-BCZ4MmfD.js → nv-breadcrumb.entry-Cbbb9Qeh.js} +5 -5
- package/dist/cjs/{nv-breadcrumbs.entry-DwzCE7F6.js → nv-breadcrumbs.entry-BTqnp9zO.js} +3 -3
- package/dist/cjs/{nv-button.entry-Cr_86bcZ.js → nv-button.entry-upWH19y6.js} +12 -14
- package/dist/cjs/{nv-buttongroup.entry-CWjRoHY1.js → nv-buttongroup.entry-CuZCRsnV.js} +3 -3
- package/dist/cjs/{nv-calendar.entry-CXfwNt6G.js → nv-calendar.entry-CT3mASW6.js} +113 -97
- package/dist/cjs/{nv-col.entry-CJLDS3LY.js → nv-col.entry--pCxkaTh.js} +5 -5
- package/dist/cjs/{nv-datagrid.entry-Cns8XSud.js → nv-datagrid.entry-CGCEhO8C.js} +80 -85
- package/dist/cjs/{nv-datagridcolumn.entry-CFFAipHF.js → nv-datagridcolumn.entry-Fsqc7CT_.js} +2 -1
- package/dist/cjs/nv-dialog.entry-B6OYcZxQ.js +300 -0
- package/dist/cjs/{nv-dialogfooter_2.entry-To_dGUn4.js → nv-dialogfooter_2.entry-C4fP_n2-.js} +10 -11
- package/dist/cjs/nv-drawer.entry-C5O4KvHU.js +445 -0
- package/dist/cjs/nv-drawerfooter_2.entry-C-reYJXG.js +146 -0
- package/dist/cjs/nv-fieldcheckbox.entry-bk7UNQny.js +177 -0
- package/dist/cjs/{nv-fielddate.entry-C3pXtMHL.js → nv-fielddate.entry-dqZDBVmm.js} +89 -46
- package/dist/cjs/{nv-fielddaterange.entry-CjVVPEK_.js → nv-fielddaterange.entry-wNRasXky.js} +151 -103
- package/dist/cjs/nv-fielddropdown.entry-BA15piWa.js +678 -0
- package/dist/cjs/{nv-fielddropdownitem.entry-Dah-PaE8.js → nv-fielddropdownitem.entry-DEWaf9dC.js} +7 -7
- package/dist/cjs/{nv-fieldmultiselect.entry-BMLjhqoJ.js → nv-fieldmultiselect.entry-BWY5xOAd.js} +343 -236
- package/dist/cjs/nv-fieldnumber.entry-DoYORd0d.js +187 -0
- package/dist/cjs/nv-fieldpassword.entry-CPaLj9aD.js +165 -0
- package/dist/cjs/{nv-fieldradio.entry-X_2VT1Dj.js → nv-fieldradio.entry-CvUmEaCa.js} +11 -11
- package/dist/cjs/{nv-fieldselect.entry-pSp-2rNn.js → nv-fieldselect.entry-uUIZ6hmN.js} +52 -13
- package/dist/cjs/{nv-fieldslider.entry-pZf7zzLU.js → nv-fieldslider.entry-DnvmxxYY.js} +16 -31
- package/dist/cjs/nv-fieldtext.entry-BYAJp3n_.js +163 -0
- package/dist/cjs/{nv-fieldtextarea.entry-t3Ixxi23.js → nv-fieldtextarea.entry-DU2bWYeg.js} +52 -14
- package/dist/cjs/{nv-fieldtime.entry-DY7D5_6K.js → nv-fieldtime.entry-DlMNDTht.js} +128 -84
- package/dist/cjs/{nv-icon.entry-6oYPSf4c.js → nv-icon.entry-CnUkRzaA.js} +12 -12
- package/dist/cjs/{nv-iconbutton_2.entry-ChULGovr.js → nv-iconbutton_2.entry-hqp4AcRq.js} +10 -12
- package/dist/cjs/{nv-menu.entry-sd0tatWq.js → nv-menu.entry-Dc_FvIx7.js} +18 -32
- package/dist/cjs/{nv-menuitem.entry-CCOqR7UF.js → nv-menuitem.entry-DzMhx6c_.js} +6 -5
- package/dist/cjs/nv-notification-bullet.entry-BwhHCMQF.js +76 -0
- package/dist/cjs/{nv-notification.entry-Cc3zE3yY.js → nv-notification.entry-C3m5p5BL.js} +42 -128
- package/dist/cjs/{nv-notificationcontainer.entry-DV4D6oOH.js → nv-notificationcontainer.entry-DTRNn7VE.js} +4 -4
- package/dist/cjs/{nv-popover.entry-DQSwI2jT.js → nv-popover.entry-B0c-2rO4.js} +51 -47
- package/dist/cjs/{nv-row.entry-UUuMSAY5.js → nv-row.entry-CdcjVGZv.js} +4 -4
- package/dist/cjs/nv-sidebar.entry-CiN813gQ.js +177 -0
- package/dist/cjs/nv-sidebarcontent.entry-D9hpAhK8.js +22 -0
- package/dist/cjs/nv-sidebardivider.entry-B4EMyca5.js +22 -0
- package/dist/cjs/nv-sidebarfooter.entry-CHi4qOFe.js +22 -0
- package/dist/cjs/nv-sidebargroup.entry-RVqrsyIU.js +23 -0
- package/dist/cjs/nv-sidebarheader.entry-_7ch0O3G.js +22 -0
- package/dist/cjs/nv-sidebarlogo.entry-Ch9F-JnT.js +32 -0
- package/dist/cjs/nv-sidebarnavitem.entry-DVrafSMr.js +296 -0
- package/dist/cjs/nv-sidebarnavsubitem.entry-C0XDAzma.js +35 -0
- package/dist/cjs/{nv-split.entry-CYP2bTTM.js → nv-split.entry-0HTslRAX.js} +47 -45
- package/dist/cjs/{nv-stack.entry-D35-75Vw.js → nv-stack.entry-CqO7uTQf.js} +5 -5
- package/dist/cjs/{nv-table.entry-DevWJBnL.js → nv-table.entry-DH85n8Mc.js} +9 -11
- package/dist/cjs/{nv-tableheader.entry-Hs7nUSOC.js → nv-tableheader.entry-CKfocdxD.js} +7 -7
- package/dist/cjs/{nv-toggle.entry-Eje9d--6.js → nv-toggle.entry-BHUl76Im.js} +9 -9
- package/dist/cjs/nv-togglebutton.entry-D_9COjY-.js +67 -0
- package/dist/cjs/{nv-togglebuttongroup.entry-CWN_Ucry.js → nv-togglebuttongroup.entry-C0NLbsq7.js} +10 -8
- package/dist/cjs/{nv-tooltip.entry-BGkKDEFg.js → nv-tooltip.entry-BfViGE_U.js} +5 -5
- package/dist/cjs/slide.animation-CmH5d1of-BZuw607U.js +90 -0
- package/dist/cjs/{style-value-types.es-f5d10b79-D0QCM8OB.js → style-value-types.es-xlgmw4x8-B1vLqX9m.js} +6 -3
- package/dist/cjs/{v4-a79185f4-2n0dOd_Y.js → v4-BdYh22OP-C1vaJ4yP.js} +1 -1
- package/dist/components/NvDatatable/NvDatatable.js +40 -24
- package/dist/generated/components.js +107 -0
- package/dist/generated/components.server.js +260 -50
- package/dist/providers/NotificationProvider.js +3 -4
- package/dist/types/components/NvDatatable/NvDatatable.d.ts +1 -1
- package/dist/types/components/NvDatatable/types.d.ts +8 -3
- package/dist/types/generated/components.d.ts +46 -0
- package/dist/types/generated/components.server.d.ts +46 -0
- package/package.json +2 -2
- package/dist/cjs/_commonjsHelpers-1789f0cf-BJu3ubxk.js +0 -10
- package/dist/cjs/inputmask-edcad3c1-B9Omti4z.js +0 -3749
- package/dist/cjs/nv-fieldcheckbox.entry-fdonR07Z.js +0 -138
- package/dist/cjs/nv-fielddropdown.entry-C9mXuNNj.js +0 -392
- package/dist/cjs/nv-fieldnumber.entry-DBdJviXu.js +0 -148
- package/dist/cjs/nv-fieldpassword.entry-Cim_usSM.js +0 -122
- package/dist/cjs/nv-fieldtext.entry-DlI_ExaV.js +0 -124
- package/dist/cjs/nv-togglebutton.entry-LGI7pIeK.js +0 -56
- /package/dist/cjs/{clsx-297c1ffe-BtxeOLZW.js → clsx-ChV9xqsO-BtxeOLZW.js} +0 -0
- /package/dist/cjs/{constants-69bafca2-DpB_ghPF.js → constants-BReL3Lsa-DpB_ghPF.js} +0 -0
- /package/dist/cjs/{timeline.animation-79215cd4-KteJaZPb.js → timeline.animation-CgHCo_Ho-KteJaZPb.js} +0 -0
package/dist/cjs/{nv-fieldmultiselect.entry-BMLjhqoJ.js → nv-fieldmultiselect.entry-BWY5xOAd.js}
RENAMED
|
@@ -1,28 +1,37 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
4
|
-
var
|
|
3
|
+
var index = require('./index-kU2nW5aN.js');
|
|
4
|
+
var i18n_utilsIlwlcG9l = require('./i18n.utils-IlwlcG9l-ku0bScip.js');
|
|
5
|
+
var v4BdYh22OP = require('./v4-BdYh22OP-C1vaJ4yP.js');
|
|
6
|
+
require('@stencil/react-output-target/runtime');
|
|
5
7
|
require('react');
|
|
6
8
|
require('react-dom');
|
|
7
9
|
|
|
8
|
-
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:var(--font-weight-high-emphasis)}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:var(--font-family-default), var(--font-family-fallback), sans-serif;font-size:var(--form-label-font-size);font-style:normal;font-weight:var(--font-weight-medium-emphasis);line-height:var(--form-label-line-height)}nv-fieldmultiselect nv-popover{width:100%;display:block}nv-fieldmultiselect nv-popover [data-scope=popover]{min-width:100%;width:max-content;max-width:400px;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:var(--font-weight-medium-emphasis);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:var(--font-family-default), var(--font-family-fallback), sans-serif;font-size:var(--form-field-font-size);font-style:normal;font-weight:var(--font-weight-low-emphasis);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-iconbutton:last-of-type{border-top-right-radius:var(--form-field-radius);border-bottom-right-radius:var(--form-field-radius)}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:var(--font-weight-medium-emphasis);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:var(--font-family-default), var(--font-family-fallback), 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:var(--font-family-default), var(--font-family-fallback), 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}";
|
|
9
|
-
const NvFieldmultiselectStyle0 = nvFieldmultiselectCss;
|
|
10
|
+
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,nv-fieldmultiselect[aria-required=true] label::after{content:\"*\";color:var(--components-form-text-required);font-weight:var(--font-weight-high-emphasis)}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:var(--font-family-default), var(--font-family-fallback), sans-serif;font-size:var(--form-label-font-size);font-style:normal;font-weight:var(--font-weight-medium-emphasis);line-height:var(--form-label-line-height)}nv-fieldmultiselect nv-popover{width:100%;display:block}nv-fieldmultiselect nv-popover [data-scope=popover]{min-width:100%;width:max-content;max-width:400px;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]::-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 nv-popover div[slot=content]{max-height:calc(90vh - var(--list-dropdown-padding) * 2);overflow-y:auto;position:relative}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}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){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{position:relative;width:100%;min-height:40px}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:calc(var(--form-field-padding-y) - 1px) var(--form-field-padding-x);font-size:var(--form-field-font-size);font-style:normal;font-weight:var(--font-weight-medium-emphasis);line-height:var(--form-field-line-height);width:100%}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:var(--font-family-default), var(--font-family-fallback), sans-serif;font-size:var(--form-field-font-size);font-style:normal;font-weight:var(--font-weight-low-emphasis);line-height:var(--form-field-line-height)}nv-fieldmultiselect .input-container-multiselect input,nv-fieldmultiselect .input-container-multiselect p.non-filterable-text{}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 input,nv-fieldmultiselect .input-container-multiselect p.non-filterable-text{width:100%;flex-grow:1;margin:0;min-height:100%;box-sizing:border-box}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-iconbutton:last-of-type{border-top-right-radius:var(--form-field-radius);border-bottom-right-radius:var(--form-field-radius)}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:var(--font-weight-medium-emphasis);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:var(--font-family-default), var(--font-family-fallback), 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:var(--font-family-default), var(--font-family-fallback), 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}";
|
|
10
11
|
|
|
11
12
|
const NvFieldmultiselect = class {
|
|
12
13
|
constructor(hostRef) {
|
|
13
14
|
index.registerInstance(this, hostRef);
|
|
14
|
-
this.valueChanged = index.createEvent(this, "valueChanged");
|
|
15
|
-
this.filterTextChanged = index.createEvent(this, "filterTextChanged");
|
|
15
|
+
this.valueChanged = index.createEvent(this, "valueChanged", 3);
|
|
16
|
+
this.filterTextChanged = index.createEvent(this, "filterTextChanged", 3);
|
|
16
17
|
this.isBulkOperation = false;
|
|
17
18
|
// Add the flag to the class
|
|
18
19
|
this.preventBlurClose = false;
|
|
20
|
+
/** Pre-computed search index for efficient filtering */
|
|
21
|
+
this.indexedItems = [];
|
|
22
|
+
/** Raw items for worker initialization */
|
|
23
|
+
this.rawItems = [];
|
|
24
|
+
/** Web Worker client for async search operations */
|
|
25
|
+
this.workerClient = null;
|
|
26
|
+
/** Effective filter mode (may differ from prop if fuzzy falls back to smart) */
|
|
27
|
+
this.effectiveFilterMode = 'strict';
|
|
19
28
|
/**
|
|
20
29
|
* Sets the ID for the input element and the for attribute of the associated
|
|
21
30
|
* label. If no ID is provided, a random one will be automatically generated
|
|
22
31
|
* to ensure unique identification, facilitating proper label association and
|
|
23
32
|
* accessibility.
|
|
24
33
|
*/
|
|
25
|
-
this.inputId =
|
|
34
|
+
this.inputId = v4BdYh22OP.v4();
|
|
26
35
|
/**
|
|
27
36
|
* The autocomplete prop helps users fill out the input field faster by
|
|
28
37
|
* suggesting entries they've used before, like their email or address.
|
|
@@ -32,8 +41,18 @@ const NvFieldmultiselect = class {
|
|
|
32
41
|
this.autocomplete = 'off';
|
|
33
42
|
/**
|
|
34
43
|
* Marks the input field as required.
|
|
44
|
+
* @note This uses the native HTML `required` attribute, which triggers browser validation.
|
|
35
45
|
*/
|
|
36
46
|
this.required = false;
|
|
47
|
+
/**
|
|
48
|
+
* Marks the input field as required for accessibility purposes without triggering
|
|
49
|
+
* native HTML validation. Use this when implementing custom validation logic.
|
|
50
|
+
* @note When set, this uses `aria-required` instead of the native `required` attribute.
|
|
51
|
+
* This allows developers to implement custom validation while maintaining accessibility.
|
|
52
|
+
* @note If this prop is not explicitly set, the component will check for the HTML attribute
|
|
53
|
+
* 'aria-required' directly to determine if it should be applied.
|
|
54
|
+
*/
|
|
55
|
+
this.ariaRequiredAttr = false;
|
|
37
56
|
/**
|
|
38
57
|
* Display the input field's content without allowing users to change it.
|
|
39
58
|
*/
|
|
@@ -104,6 +123,39 @@ const NvFieldmultiselect = class {
|
|
|
104
123
|
* Text for the "Deselect All" button.
|
|
105
124
|
*/
|
|
106
125
|
this.deselectAllLabel = 'Select/deselect all';
|
|
126
|
+
/**
|
|
127
|
+
* Filter mode for multiselect search:
|
|
128
|
+
* - 'strict': Simple substring matching (normalized includes)
|
|
129
|
+
* - 'smart': Token-based matching (all query tokens must exist, order ignored)
|
|
130
|
+
* - 'fuzzy': Typo-tolerant matching using Fuse.js (runs in Web Worker)
|
|
131
|
+
* @default 'strict'
|
|
132
|
+
*/
|
|
133
|
+
this.filterMode = 'strict';
|
|
134
|
+
/**
|
|
135
|
+
* Maximum number of results to display. Protects UI performance on large datasets.
|
|
136
|
+
* Values are clamped between 10 and 500 (hard cap).
|
|
137
|
+
* @default 25
|
|
138
|
+
*/
|
|
139
|
+
this.maxResults = 25;
|
|
140
|
+
/**
|
|
141
|
+
* Minimum number of characters required before filtering starts.
|
|
142
|
+
* Useful for preventing overwhelming results on very large datasets.
|
|
143
|
+
* @default 0
|
|
144
|
+
*/
|
|
145
|
+
this.startFilterAt = 0;
|
|
146
|
+
/**
|
|
147
|
+
* Number of items above which filtering is offloaded to a Web Worker.
|
|
148
|
+
* This keeps the main thread responsive for large datasets.
|
|
149
|
+
* @default 2000
|
|
150
|
+
*/
|
|
151
|
+
this.workerThreshold = 2000;
|
|
152
|
+
/**
|
|
153
|
+
* Threshold for fuzzy matching (0-1). Lower values are stricter.
|
|
154
|
+
* Only applies when filterMode is 'fuzzy'.
|
|
155
|
+
* @default 0.3
|
|
156
|
+
* @see {@link https://fusejs.io/api/options.html#threshold} Fuse.js threshold documentation
|
|
157
|
+
*/
|
|
158
|
+
this.fuzzyThreshold = 0.3;
|
|
107
159
|
//#endregion PROPERTIES
|
|
108
160
|
/****************************************************************************/
|
|
109
161
|
//#region STATE
|
|
@@ -121,6 +173,19 @@ const NvFieldmultiselect = class {
|
|
|
121
173
|
* Controls the visibility of the select all section.
|
|
122
174
|
*/
|
|
123
175
|
this.isSelectAllSectionVisible = true;
|
|
176
|
+
/**
|
|
177
|
+
* Whether search results were truncated due to maxResults limit.
|
|
178
|
+
*/
|
|
179
|
+
this.resultsTruncated = false;
|
|
180
|
+
/**
|
|
181
|
+
* Total number of matches before truncation.
|
|
182
|
+
*/
|
|
183
|
+
this.totalResults = 0;
|
|
184
|
+
/**
|
|
185
|
+
* Whether a worker search is in progress.
|
|
186
|
+
*/
|
|
187
|
+
this.isSearching = false;
|
|
188
|
+
// (filterItems handles both options and slots mode)
|
|
124
189
|
/**
|
|
125
190
|
* Handle badge close for options mode.
|
|
126
191
|
*/
|
|
@@ -255,7 +320,7 @@ const NvFieldmultiselect = class {
|
|
|
255
320
|
}
|
|
256
321
|
// Set a new timer for filtering
|
|
257
322
|
this.debounceTimer = window.setTimeout(() => {
|
|
258
|
-
this.
|
|
323
|
+
void this.filterItems();
|
|
259
324
|
}, this.debounceDelay);
|
|
260
325
|
};
|
|
261
326
|
/**
|
|
@@ -276,7 +341,7 @@ const NvFieldmultiselect = class {
|
|
|
276
341
|
}
|
|
277
342
|
// Set a new timer for filtering
|
|
278
343
|
this.debounceTimer = window.setTimeout(() => {
|
|
279
|
-
this.
|
|
344
|
+
void this.filterItems();
|
|
280
345
|
}, this.debounceDelay);
|
|
281
346
|
};
|
|
282
347
|
/**
|
|
@@ -447,8 +512,12 @@ const NvFieldmultiselect = class {
|
|
|
447
512
|
* @returns {any} The JSX for options mode
|
|
448
513
|
*/
|
|
449
514
|
this.renderOptionsMode = () => {
|
|
450
|
-
|
|
451
|
-
|
|
515
|
+
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, onOpenChanged: this.handleOpenChanged }, 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) > 0 && (index.h("nv-badge", { slot: "leading-input", "prevent-auto-close": true, color: "10", dismissible: (this.value?.length || 0) > 0, label: `${this.value?.length || 0} ${this.badgeLabel}`, "aria-label": `Clear all ${this.value?.length || 0} ${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.getRequiredAttributes().useNativeRequired
|
|
516
|
+
? this.required
|
|
517
|
+
: undefined, ...(this.getRequiredAttributes().ariaRequiredValue !==
|
|
518
|
+
undefined && {
|
|
519
|
+
'aria-required': String(this.getRequiredAttributes().ariaRequiredValue),
|
|
520
|
+
}), 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: {
|
|
452
521
|
position: 'absolute',
|
|
453
522
|
opacity: '0',
|
|
454
523
|
width: '0',
|
|
@@ -464,8 +533,12 @@ const NvFieldmultiselect = class {
|
|
|
464
533
|
* @returns {any} The JSX for slots mode
|
|
465
534
|
*/
|
|
466
535
|
this.renderSlotsMode = () => {
|
|
467
|
-
|
|
468
|
-
|
|
536
|
+
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) > 0 && (index.h("nv-badge", { slot: "leading-input", "prevent-auto-close": true, color: "10", dismissible: (this.value?.length || 0) > 0, label: `${this.value?.length || 0} ${this.badgeLabel}`, "aria-label": `Clear all ${this.value?.length || 0} ${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.getRequiredAttributes().useNativeRequired
|
|
537
|
+
? this.required
|
|
538
|
+
: undefined, ...(this.getRequiredAttributes().ariaRequiredValue !==
|
|
539
|
+
undefined && {
|
|
540
|
+
'aria-required': String(this.getRequiredAttributes().ariaRequiredValue),
|
|
541
|
+
}), 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: {
|
|
469
542
|
position: 'absolute',
|
|
470
543
|
opacity: '0',
|
|
471
544
|
width: '0',
|
|
@@ -531,46 +604,13 @@ const NvFieldmultiselect = class {
|
|
|
531
604
|
//#endregion WATCHERS
|
|
532
605
|
/****************************************************************************/
|
|
533
606
|
//#region LISTENERS
|
|
534
|
-
|
|
535
|
-
* Emitted when the input loses focus.
|
|
536
|
-
* @param {CustomEvent<boolean>} event - The event object containing the focus state.
|
|
537
|
-
*/
|
|
538
|
-
handleOpenChanged(event) {
|
|
539
|
-
// Stop propagation to prevent the event from affecting parent components like dialogs
|
|
540
|
-
event.stopPropagation();
|
|
541
|
-
// Only update if the event comes from our popover
|
|
542
|
-
if (event.target === this.popoverElement) {
|
|
543
|
-
// Only update if open state differs to avoid redundant actions
|
|
544
|
-
if (this.open !== event.detail) {
|
|
545
|
-
this.open = event.detail;
|
|
546
|
-
if (this.open) {
|
|
547
|
-
// Filter items only if there is filter text
|
|
548
|
-
if (this.filterText) {
|
|
549
|
-
this.filterItems();
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
else {
|
|
553
|
-
// Clear filter text on close if filterable
|
|
554
|
-
if (this.filterable) {
|
|
555
|
-
this.clearFilterText();
|
|
556
|
-
}
|
|
557
|
-
this.handlePopoverClose();
|
|
558
|
-
}
|
|
559
|
-
// Reorder content as needed
|
|
560
|
-
if (this.options) {
|
|
561
|
-
this.reorderOptionsContent();
|
|
562
|
-
}
|
|
563
|
-
else {
|
|
564
|
-
this.reorderSlotContent();
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
}
|
|
607
|
+
/* eslint-disable nova/native-event-listener */
|
|
569
608
|
/**
|
|
570
609
|
* Listen for the `itemChecked` event emitted by child items.
|
|
571
610
|
* @param {CustomEvent} event - The event object containing the selected value and its checked state.
|
|
572
611
|
*/
|
|
573
612
|
handleItemChecked(event) {
|
|
613
|
+
event.stopPropagation();
|
|
574
614
|
if (this.disabled || this.readonly || this.isBulkOperation) {
|
|
575
615
|
// Skip processing itemChecked events during bulk operations
|
|
576
616
|
return;
|
|
@@ -602,6 +642,7 @@ const NvFieldmultiselect = class {
|
|
|
602
642
|
console.warn('[Event:itemChecked] Received itemChecked event with undefined or null value'); // Warning log
|
|
603
643
|
}
|
|
604
644
|
}
|
|
645
|
+
/* eslint-enable nova/native-event-listener */
|
|
605
646
|
// Add a listener for the slot content
|
|
606
647
|
handleSlotChange(event) {
|
|
607
648
|
// Check: we only want to reorder if it's the "content" slot
|
|
@@ -715,7 +756,6 @@ const NvFieldmultiselect = class {
|
|
|
715
756
|
* Set the mode state and handle options change.
|
|
716
757
|
*/
|
|
717
758
|
componentWillLoad() {
|
|
718
|
-
var _a;
|
|
719
759
|
// Don't call handleOptionsChange if we are in slots mode
|
|
720
760
|
if (this.options) {
|
|
721
761
|
this.handleOptionsChange(this.options);
|
|
@@ -736,7 +776,7 @@ const NvFieldmultiselect = class {
|
|
|
736
776
|
}
|
|
737
777
|
// Initialize the sorted options array with the parsed options for initial rendering
|
|
738
778
|
if (this.options) {
|
|
739
|
-
this.sortedOptions = [...(
|
|
779
|
+
this.sortedOptions = [...(this.options ?? [])];
|
|
740
780
|
}
|
|
741
781
|
// Reset filter if needed
|
|
742
782
|
if (!this.filterText) {
|
|
@@ -759,14 +799,17 @@ const NvFieldmultiselect = class {
|
|
|
759
799
|
this.initializeValueFromSlots();
|
|
760
800
|
this.syncChildComponents();
|
|
761
801
|
}
|
|
802
|
+
// Build the search index on load
|
|
803
|
+
this.rebuildSearchIndex();
|
|
762
804
|
}
|
|
763
805
|
/**
|
|
764
|
-
* Unsubscribe from click outside event.
|
|
806
|
+
* Unsubscribe from click outside event and clean up worker.
|
|
765
807
|
*/
|
|
766
808
|
disconnectedCallback() {
|
|
767
809
|
if (this._boundHandleClickOutside) {
|
|
768
810
|
document.removeEventListener('click', this._boundHandleClickOutside);
|
|
769
811
|
}
|
|
812
|
+
this.terminateSearchWorker();
|
|
770
813
|
}
|
|
771
814
|
//#endregion LIFECYCLE
|
|
772
815
|
/****************************************************************************/
|
|
@@ -917,211 +960,219 @@ const NvFieldmultiselect = class {
|
|
|
917
960
|
}
|
|
918
961
|
/**
|
|
919
962
|
* Filter multiselect items based on the text entered by the user.
|
|
963
|
+
* Uses the search engine for optimized filtering with configurable modes.
|
|
920
964
|
*/
|
|
921
|
-
filterItems() {
|
|
965
|
+
async filterItems() {
|
|
922
966
|
const ul = this.el.querySelector('ul');
|
|
923
967
|
if (!ul)
|
|
924
968
|
return;
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
item.style.display = '';
|
|
936
|
-
});
|
|
937
|
-
}
|
|
938
|
-
else {
|
|
939
|
-
// Reset slot items display
|
|
940
|
-
const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
|
|
941
|
-
items.forEach(item => {
|
|
942
|
-
item.style.display = '';
|
|
943
|
-
});
|
|
944
|
-
}
|
|
945
|
-
// Reorder with divider
|
|
946
|
-
const items = Array.from(ul.querySelectorAll('nv-fielddropdownitemcheck'));
|
|
947
|
-
const selectedItems = items.filter(item => (this.value || []).includes(item.getAttribute('value') || ''));
|
|
948
|
-
const unselectedItems = items.filter(item => !(this.value || []).includes(item.getAttribute('value') || ''));
|
|
949
|
-
this.manageDivider(ul, selectedItems, unselectedItems);
|
|
950
|
-
return;
|
|
951
|
-
}
|
|
952
|
-
const normalizedFilter = this.normalizeText(this.filterText);
|
|
953
|
-
let hasVisibleItems = false;
|
|
954
|
-
if (this.options && this.options.length > 0) {
|
|
955
|
-
// Filter options mode
|
|
969
|
+
this.effectiveFilterMode = i18n_utilsIlwlcG9l.getEffectiveFilterMode(this.filterMode);
|
|
970
|
+
// Remove existing empty message and truncation message if any
|
|
971
|
+
ul.querySelector('[data-empty]')?.remove();
|
|
972
|
+
ul.querySelector('[data-truncated]')?.remove();
|
|
973
|
+
// Reset truncation state
|
|
974
|
+
this.resultsTruncated = false;
|
|
975
|
+
this.totalResults = 0;
|
|
976
|
+
if (!this.filterText.trim() ||
|
|
977
|
+
this.filterText.length < this.startFilterAt) {
|
|
978
|
+
// Reset display and apply maxResults limit
|
|
956
979
|
const items = Array.from(ul.querySelectorAll('nv-fielddropdownitemcheck'));
|
|
980
|
+
const effectiveMaxResults = i18n_utilsIlwlcG9l.clampMaxResults(this.maxResults);
|
|
981
|
+
let visibleCount = 0;
|
|
957
982
|
items.forEach(item => {
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
hasVisibleItems = true;
|
|
983
|
+
if (visibleCount < effectiveMaxResults) {
|
|
984
|
+
item.style.display = '';
|
|
985
|
+
visibleCount++;
|
|
986
|
+
}
|
|
987
|
+
else {
|
|
988
|
+
item.style.display = 'none';
|
|
965
989
|
}
|
|
966
990
|
});
|
|
967
|
-
//
|
|
991
|
+
// Track truncation
|
|
992
|
+
this.totalResults = items.length;
|
|
993
|
+
this.resultsTruncated = items.length > effectiveMaxResults;
|
|
994
|
+
this.hasFilterResults = visibleCount > 0;
|
|
995
|
+
// Reorder with divider
|
|
968
996
|
const visibleItems = items.filter(item => item.style.display !== 'none');
|
|
969
|
-
const
|
|
970
|
-
const
|
|
971
|
-
this.manageDivider(ul,
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
|
|
976
|
-
items.forEach(item => {
|
|
977
|
-
const label = item.getAttribute('label') || '';
|
|
978
|
-
const value = item.getAttribute('value') || '';
|
|
979
|
-
const textContent = item.textContent || '';
|
|
980
|
-
const matchesFilter = this.normalizeText(label).includes(normalizedFilter) ||
|
|
981
|
-
this.normalizeText(value).includes(normalizedFilter) ||
|
|
982
|
-
this.normalizeText(textContent).includes(normalizedFilter);
|
|
983
|
-
item.style.display = matchesFilter ? '' : 'none';
|
|
984
|
-
if (matchesFilter)
|
|
985
|
-
hasVisibleItems = true;
|
|
986
|
-
});
|
|
987
|
-
}
|
|
988
|
-
// Add empty message if no items match the filter
|
|
989
|
-
if (!hasVisibleItems) {
|
|
990
|
-
const emptyMessage = document.createElement('li');
|
|
991
|
-
emptyMessage.setAttribute('data-empty', 'true');
|
|
992
|
-
emptyMessage.textContent = this.emptyResult;
|
|
993
|
-
emptyMessage.classList.add('no-results-message');
|
|
994
|
-
ul.appendChild(emptyMessage);
|
|
995
|
-
}
|
|
996
|
-
this.reorderSlotContent();
|
|
997
|
-
}
|
|
998
|
-
/**
|
|
999
|
-
* Filter multiselect items in options mode.
|
|
1000
|
-
*/
|
|
1001
|
-
filterItemsOption() {
|
|
1002
|
-
const ul = this.el.querySelector('ul');
|
|
1003
|
-
if (!ul)
|
|
997
|
+
const selectedItems = visibleItems.filter(item => (this.value || []).includes(item.getAttribute('value') || ''));
|
|
998
|
+
const unselectedItems = visibleItems.filter(item => !(this.value || []).includes(item.getAttribute('value') || ''));
|
|
999
|
+
this.manageDivider(ul, selectedItems, unselectedItems);
|
|
1000
|
+
if (this.resultsTruncated) {
|
|
1001
|
+
this.addTruncatedMessage(ul, effectiveMaxResults, items.length);
|
|
1002
|
+
}
|
|
1004
1003
|
return;
|
|
1005
|
-
|
|
1004
|
+
}
|
|
1005
|
+
// Use advanced search engine
|
|
1006
|
+
const result = await this.performAdvancedSearch();
|
|
1007
|
+
this.resultsTruncated = result.truncated;
|
|
1008
|
+
this.totalResults = result.total;
|
|
1009
|
+
// Create a Set of matching IDs for fast lookup
|
|
1010
|
+
const matchingIds = new Set(result.ids);
|
|
1006
1011
|
let hasVisibleItems = false;
|
|
1007
1012
|
const items = Array.from(ul.querySelectorAll('nv-fielddropdownitemcheck'));
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
this.removeEmptyMessageOption(ul);
|
|
1011
|
-
items.forEach(item => {
|
|
1012
|
-
item.style.display = '';
|
|
1013
|
-
item.removeAttribute('aria-hidden'); // Ensure accessibility
|
|
1014
|
-
});
|
|
1015
|
-
this.reorderOptionsContent();
|
|
1016
|
-
this.hasFilterResults = true;
|
|
1017
|
-
return;
|
|
1018
|
-
}
|
|
1019
|
-
// Filter the items
|
|
1013
|
+
const effectiveMaxResults = i18n_utilsIlwlcG9l.clampMaxResults(this.maxResults);
|
|
1014
|
+
let visibleCount = 0;
|
|
1020
1015
|
items.forEach(item => {
|
|
1021
|
-
const
|
|
1022
|
-
if
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
item.style.display =
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
hasVisibleItems = true;
|
|
1016
|
+
const itemValue = item.getAttribute('value') || '';
|
|
1017
|
+
// Check if this item matches
|
|
1018
|
+
const isMatch = matchingIds.has(itemValue);
|
|
1019
|
+
if (isMatch && visibleCount < effectiveMaxResults) {
|
|
1020
|
+
item.style.display = '';
|
|
1021
|
+
hasVisibleItems = true;
|
|
1022
|
+
visibleCount++;
|
|
1029
1023
|
}
|
|
1030
1024
|
else {
|
|
1031
|
-
item.style.display = 'none';
|
|
1032
|
-
item.setAttribute('aria-hidden', 'true');
|
|
1025
|
+
item.style.display = 'none';
|
|
1033
1026
|
}
|
|
1034
1027
|
});
|
|
1035
|
-
// Update the filter results state
|
|
1036
|
-
this.hasFilterResults = hasVisibleItems;
|
|
1037
1028
|
// Manage the divider with the visible items
|
|
1038
1029
|
const visibleItems = items.filter(item => item.style.display !== 'none');
|
|
1039
1030
|
const visibleSelected = visibleItems.filter(item => (this.value || []).includes(item.getAttribute('value') || ''));
|
|
1040
1031
|
const visibleUnselected = visibleItems.filter(item => !(this.value || []).includes(item.getAttribute('value') || ''));
|
|
1041
1032
|
this.manageDivider(ul, visibleSelected, visibleUnselected);
|
|
1042
|
-
// Add
|
|
1033
|
+
// Add empty message if no items match the filter
|
|
1034
|
+
this.hasFilterResults = hasVisibleItems;
|
|
1043
1035
|
if (!hasVisibleItems) {
|
|
1044
|
-
|
|
1036
|
+
const emptyMessage = document.createElement('li');
|
|
1037
|
+
emptyMessage.setAttribute('data-empty', 'true');
|
|
1038
|
+
emptyMessage.textContent = this.emptyResult;
|
|
1039
|
+
emptyMessage.classList.add('no-results-message');
|
|
1040
|
+
ul.appendChild(emptyMessage);
|
|
1041
|
+
}
|
|
1042
|
+
else if (result.truncated) {
|
|
1043
|
+
this.addTruncatedMessage(ul, result.ids.length, result.total);
|
|
1044
|
+
}
|
|
1045
|
+
if (this.options) {
|
|
1046
|
+
this.reorderOptionsContent();
|
|
1045
1047
|
}
|
|
1046
1048
|
else {
|
|
1047
|
-
this.
|
|
1049
|
+
this.reorderSlotContent();
|
|
1048
1050
|
}
|
|
1049
1051
|
}
|
|
1050
1052
|
/**
|
|
1051
|
-
*
|
|
1053
|
+
* Rebuilds the search index from current items (options prop or slot items).
|
|
1052
1054
|
*/
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1055
|
+
async rebuildSearchIndex() {
|
|
1056
|
+
// Build raw items array for indexing
|
|
1057
|
+
this.rawItems = [];
|
|
1058
|
+
if (this.options?.length) {
|
|
1059
|
+
this.options.forEach((opt, index) => {
|
|
1060
|
+
if (!opt.isDivider) {
|
|
1061
|
+
this.rawItems.push({
|
|
1062
|
+
id: opt.value || `opt-${index}`,
|
|
1063
|
+
label: opt.label || opt.value || '',
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
});
|
|
1063
1067
|
}
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
this.
|
|
1067
|
-
|
|
1068
|
+
else {
|
|
1069
|
+
// Use slot items
|
|
1070
|
+
const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
|
|
1071
|
+
items.forEach((item, index) => {
|
|
1072
|
+
this.rawItems.push({
|
|
1073
|
+
id: item.getAttribute('value') || `item-${index}`,
|
|
1074
|
+
label: item.getAttribute('label') || item.textContent?.trim() || '',
|
|
1075
|
+
});
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
// Build local index for main-thread search
|
|
1079
|
+
this.indexedItems = i18n_utilsIlwlcG9l.buildIndex(this.rawItems);
|
|
1080
|
+
// Determine effective filter mode
|
|
1081
|
+
this.effectiveFilterMode = i18n_utilsIlwlcG9l.getEffectiveFilterMode(this.filterMode);
|
|
1082
|
+
// Initialize worker if needed
|
|
1083
|
+
const itemCount = this.rawItems.length;
|
|
1084
|
+
const threshold = i18n_utilsIlwlcG9l.clampWorkerThreshold(this.workerThreshold);
|
|
1085
|
+
if (i18n_utilsIlwlcG9l.shouldUseWorker(itemCount, this.effectiveFilterMode, threshold)) {
|
|
1086
|
+
await this.initSearchWorker();
|
|
1087
|
+
}
|
|
1088
|
+
else {
|
|
1089
|
+
this.terminateSearchWorker();
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
/**
|
|
1093
|
+
* Initializes the Web Worker for search operations.
|
|
1094
|
+
* Falls back to main thread if worker is not available.
|
|
1095
|
+
* Note: Fuzzy search now works on main thread with Fuse.js, so no mode change needed.
|
|
1096
|
+
*/
|
|
1097
|
+
async initSearchWorker() {
|
|
1098
|
+
if (!i18n_utilsIlwlcG9l.isWorkerSupported()) {
|
|
1099
|
+
// Workers not supported - will use main thread (fuzzy still works with Fuse.js)
|
|
1068
1100
|
return;
|
|
1069
1101
|
}
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitemcheck'));
|
|
1074
|
-
// Instead of removing/reordering, just hide/show items
|
|
1075
|
-
items.forEach(item => {
|
|
1076
|
-
var _a;
|
|
1077
|
-
const label = item.getAttribute('label') || '';
|
|
1078
|
-
const value = item.getAttribute('value') || '';
|
|
1079
|
-
const textContent = ((_a = item.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || '';
|
|
1080
|
-
const matchesFilter = this.normalizeText(label).includes(normalizedFilter) ||
|
|
1081
|
-
this.normalizeText(value).includes(normalizedFilter) ||
|
|
1082
|
-
this.normalizeText(textContent).includes(normalizedFilter);
|
|
1083
|
-
item.style.display = matchesFilter ? '' : 'none';
|
|
1084
|
-
if (matchesFilter)
|
|
1085
|
-
hasVisibleItems = true;
|
|
1086
|
-
});
|
|
1087
|
-
// Update the filter results state
|
|
1088
|
-
this.hasFilterResults = hasVisibleItems;
|
|
1089
|
-
// Get visible items after filtering
|
|
1090
|
-
const visibleItems = items.filter(item => item.style.display !== 'none');
|
|
1091
|
-
const visibleSelectedItems = visibleItems.filter(item => (this.value || []).includes(item.getAttribute('value') || ''));
|
|
1092
|
-
this.manageDivider(ul, visibleSelectedItems, visibleItems.filter(item => !(this.value || []).includes(item.getAttribute('value') || '')));
|
|
1093
|
-
// Add empty message if no items match the filter
|
|
1094
|
-
if (!hasVisibleItems) {
|
|
1095
|
-
const emptyMessage = document.createElement('li');
|
|
1096
|
-
emptyMessage.setAttribute('data-empty', 'true');
|
|
1097
|
-
emptyMessage.textContent = this.emptyResult;
|
|
1098
|
-
emptyMessage.classList.add('no-results-message');
|
|
1099
|
-
ul.appendChild(emptyMessage);
|
|
1102
|
+
if (!this.workerClient) {
|
|
1103
|
+
this.workerClient = new i18n_utilsIlwlcG9l.SearchWorkerClient();
|
|
1104
|
+
// No fallback mode change needed - fuzzy works on main thread now
|
|
1100
1105
|
}
|
|
1106
|
+
// Init will silently handle fallback if worker can't be created
|
|
1107
|
+
await this.workerClient.init(this.rawItems);
|
|
1101
1108
|
}
|
|
1102
1109
|
/**
|
|
1103
|
-
*
|
|
1104
|
-
* @param {string} text - The text to normalize
|
|
1105
|
-
* @returns {string} The normalized text
|
|
1106
|
-
*
|
|
1107
|
-
* @example
|
|
1108
|
-
* normalizeText("Café Latte") => "cafe latte"
|
|
1109
|
-
*
|
|
1110
|
-
* @description
|
|
1111
|
-
* This function performs text normalization in three steps:
|
|
1112
|
-
* 1. Decomposes characters into their base form and combining characters (NFD)
|
|
1113
|
-
* 2. Removes all diacritical marks (accents, umlauts, etc.)
|
|
1114
|
-
* 3. Converts to lowercase and trims whitespace
|
|
1115
|
-
*
|
|
1116
|
-
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize} - MDN documentation on String.normalize()
|
|
1117
|
-
* @see {@link https://en.wikipedia.org/wiki/Unicode_equivalence#Normal_forms} - More info about Unicode normalization forms
|
|
1110
|
+
* Terminates the Web Worker and cleans up resources.
|
|
1118
1111
|
*/
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
.
|
|
1122
|
-
.
|
|
1123
|
-
|
|
1124
|
-
|
|
1112
|
+
terminateSearchWorker() {
|
|
1113
|
+
if (this.workerClient) {
|
|
1114
|
+
this.workerClient.terminate();
|
|
1115
|
+
this.workerClient = null;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Performs a search over the indexed items, using a Web Worker when available
|
|
1120
|
+
* and falling back to the main thread otherwise.
|
|
1121
|
+
* @returns {Promise<SearchResult>} Resolves with the search results.
|
|
1122
|
+
*/
|
|
1123
|
+
async performAdvancedSearch() {
|
|
1124
|
+
// Ensure index is built
|
|
1125
|
+
if (!this.indexedItems.length) {
|
|
1126
|
+
await this.rebuildSearchIndex();
|
|
1127
|
+
}
|
|
1128
|
+
const itemCount = this.rawItems.length;
|
|
1129
|
+
const threshold = i18n_utilsIlwlcG9l.clampWorkerThreshold(this.workerThreshold);
|
|
1130
|
+
const useWorker = i18n_utilsIlwlcG9l.shouldUseWorker(itemCount, this.effectiveFilterMode, threshold);
|
|
1131
|
+
if (useWorker && this.workerClient?.isReady) {
|
|
1132
|
+
this.isSearching = true;
|
|
1133
|
+
try {
|
|
1134
|
+
return await this.workerClient.search(this.filterText, this.effectiveFilterMode, this.maxResults, this.fuzzyThreshold);
|
|
1135
|
+
}
|
|
1136
|
+
catch (error) {
|
|
1137
|
+
console.error('Worker search failed:', error);
|
|
1138
|
+
// Fall back to main thread (fuzzy now works with Fuse.js)
|
|
1139
|
+
return i18n_utilsIlwlcG9l.search(this.indexedItems, {
|
|
1140
|
+
query: this.filterText,
|
|
1141
|
+
filterMode: this.effectiveFilterMode,
|
|
1142
|
+
maxResults: this.maxResults,
|
|
1143
|
+
startFilterAt: this.startFilterAt,
|
|
1144
|
+
fuzzyThreshold: this.fuzzyThreshold,
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
finally {
|
|
1148
|
+
this.isSearching = false;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
// Use main thread search (fuzzy now works with Fuse.js)
|
|
1152
|
+
return i18n_utilsIlwlcG9l.search(this.indexedItems, {
|
|
1153
|
+
query: this.filterText,
|
|
1154
|
+
filterMode: this.effectiveFilterMode,
|
|
1155
|
+
maxResults: this.maxResults,
|
|
1156
|
+
startFilterAt: this.startFilterAt,
|
|
1157
|
+
fuzzyThreshold: this.fuzzyThreshold,
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
1160
|
+
/**
|
|
1161
|
+
* Adds a non-selectable list item showing truncation information.
|
|
1162
|
+
* @param {HTMLElement} ul - The list element to which the truncation message will be appended.
|
|
1163
|
+
* @param {number} shown - The number of items currently shown.
|
|
1164
|
+
* @param {number} total - The total number of available items.
|
|
1165
|
+
*/
|
|
1166
|
+
addTruncatedMessage(ul, shown, total) {
|
|
1167
|
+
// Remove existing truncation message
|
|
1168
|
+
ul.querySelector('[data-truncated]')?.remove();
|
|
1169
|
+
// Get the text template: use provided text or auto-detect from locale
|
|
1170
|
+
const textTemplate = this.truncatedResultsText || i18n_utilsIlwlcG9l.getTruncatedResultsText(this.locale);
|
|
1171
|
+
const truncatedItem = document.createElement('li');
|
|
1172
|
+
truncatedItem.setAttribute('data-truncated', 'true');
|
|
1173
|
+
truncatedItem.className = 'truncated-message no-results-message';
|
|
1174
|
+
truncatedItem.textContent = i18n_utilsIlwlcG9l.formatTruncatedResults(textTemplate, shown, total);
|
|
1175
|
+
ul.appendChild(truncatedItem);
|
|
1125
1176
|
}
|
|
1126
1177
|
handleClickOutside(event) {
|
|
1127
1178
|
if (this.el.contains(event.target) ||
|
|
@@ -1173,21 +1224,6 @@ const NvFieldmultiselect = class {
|
|
|
1173
1224
|
console.warn('No visible first item found to focus');
|
|
1174
1225
|
}
|
|
1175
1226
|
}
|
|
1176
|
-
addEmptyMessageOption(ul) {
|
|
1177
|
-
const existingMessage = ul.querySelector('[data-empty]');
|
|
1178
|
-
if (existingMessage)
|
|
1179
|
-
return;
|
|
1180
|
-
const emptyMessage = document.createElement('li');
|
|
1181
|
-
emptyMessage.setAttribute('data-empty', 'true');
|
|
1182
|
-
emptyMessage.textContent = this.emptyResult;
|
|
1183
|
-
emptyMessage.classList.add('no-results-message');
|
|
1184
|
-
ul.appendChild(emptyMessage);
|
|
1185
|
-
}
|
|
1186
|
-
removeEmptyMessageOption(ul) {
|
|
1187
|
-
const existingMessage = ul.querySelector('[data-empty]');
|
|
1188
|
-
if (existingMessage)
|
|
1189
|
-
existingMessage.remove();
|
|
1190
|
-
}
|
|
1191
1227
|
manageDivider(ul, selectedItems, unselectedItems) {
|
|
1192
1228
|
let divider = ul.querySelector('hr.multiselect-divider');
|
|
1193
1229
|
if (!divider) {
|
|
@@ -1338,6 +1374,77 @@ const NvFieldmultiselect = class {
|
|
|
1338
1374
|
// Combine with current this.value (set by code), ensuring uniqueness
|
|
1339
1375
|
this.value = Array.from(new Set([...(this.value || []), ...checkedValues]));
|
|
1340
1376
|
}
|
|
1377
|
+
/**
|
|
1378
|
+
* Calculates aria-required and native required values based on props and attributes
|
|
1379
|
+
* @returns {object} Object with ariaRequiredValue and useNativeRequired
|
|
1380
|
+
*/
|
|
1381
|
+
getRequiredAttributes() {
|
|
1382
|
+
// Check aria-required from multiple sources:
|
|
1383
|
+
// 1. JavaScript prop (most reliable)
|
|
1384
|
+
// 2. HTML attribute 'aria-required' (direct HTML)
|
|
1385
|
+
// 3. HTML attribute 'aria-required-attr' (from JSX kebab-case conversion)
|
|
1386
|
+
// Check aria-required from multiple sources:
|
|
1387
|
+
// 1. HTML attribute 'aria-required' (direct HTML) - check if explicitly set
|
|
1388
|
+
// 2. JavaScript prop (when prop is explicitly set via JavaScript)
|
|
1389
|
+
// We use hasAttribute to determine if the attribute was explicitly set by the user,
|
|
1390
|
+
// since the prop now defaults to false (to maintain Blazor compatibility)
|
|
1391
|
+
const hasAriaRequiredAttr = this.el.hasAttribute('aria-required') ||
|
|
1392
|
+
this.el.hasAttribute('aria-required-attr');
|
|
1393
|
+
const ariaRequiredFromAttr = hasAriaRequiredAttr
|
|
1394
|
+
? this.el.getAttribute('aria-required') ||
|
|
1395
|
+
this.el.getAttribute('aria-required-attr')
|
|
1396
|
+
: null;
|
|
1397
|
+
// Use aria-required if the attribute was explicitly set
|
|
1398
|
+
// With reflect: true, setting the prop will also set the attribute
|
|
1399
|
+
const useAriaRequired = hasAriaRequiredAttr;
|
|
1400
|
+
// Determine the value: use attribute if it exists (prop reflects to attribute via reflect: true)
|
|
1401
|
+
// If attribute doesn't exist, the prop was never set and we don't use aria-required
|
|
1402
|
+
const ariaRequiredAttrValue = hasAriaRequiredAttr
|
|
1403
|
+
? ariaRequiredFromAttr
|
|
1404
|
+
: null;
|
|
1405
|
+
// Determine which attributes to use
|
|
1406
|
+
// If aria-required HTML attribute is present, use it (convert string to boolean)
|
|
1407
|
+
// If required is set and aria-required is not "false", use native required
|
|
1408
|
+
// If aria-required is "false", don't use native required even if required is set
|
|
1409
|
+
const ariaRequiredValue = useAriaRequired
|
|
1410
|
+
? ariaRequiredAttrValue === 'true' || ariaRequiredAttrValue === ''
|
|
1411
|
+
: undefined;
|
|
1412
|
+
const useNativeRequired = this.required && (!useAriaRequired || ariaRequiredValue === true);
|
|
1413
|
+
return {
|
|
1414
|
+
ariaRequiredValue,
|
|
1415
|
+
useNativeRequired,
|
|
1416
|
+
};
|
|
1417
|
+
}
|
|
1418
|
+
/**
|
|
1419
|
+
* Emitted when the input loses focus.
|
|
1420
|
+
* @param {CustomEvent<boolean>} event - The event object containing the focus state.
|
|
1421
|
+
*/
|
|
1422
|
+
handleOpenChanged(event) {
|
|
1423
|
+
// Only update if open state differs to avoid redundant actions
|
|
1424
|
+
if (this.open !== event.detail) {
|
|
1425
|
+
this.open = event.detail;
|
|
1426
|
+
if (this.open) {
|
|
1427
|
+
// Filter items only if there is filter text
|
|
1428
|
+
if (this.filterText) {
|
|
1429
|
+
this.filterItems();
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
else {
|
|
1433
|
+
// Clear filter text on close if filterable
|
|
1434
|
+
if (this.filterable) {
|
|
1435
|
+
this.clearFilterText();
|
|
1436
|
+
}
|
|
1437
|
+
this.handlePopoverClose();
|
|
1438
|
+
}
|
|
1439
|
+
// Reorder content as needed
|
|
1440
|
+
if (this.options) {
|
|
1441
|
+
this.reorderOptionsContent();
|
|
1442
|
+
}
|
|
1443
|
+
else {
|
|
1444
|
+
this.reorderSlotContent();
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1341
1448
|
/**
|
|
1342
1449
|
* Renders description and error description sections
|
|
1343
1450
|
* @returns {any} The JSX for descriptions
|
|
@@ -1364,6 +1471,6 @@ const NvFieldmultiselect = class {
|
|
|
1364
1471
|
"open": ["handleOpenChange"]
|
|
1365
1472
|
}; }
|
|
1366
1473
|
};
|
|
1367
|
-
NvFieldmultiselect.style =
|
|
1474
|
+
NvFieldmultiselect.style = nvFieldmultiselectCss;
|
|
1368
1475
|
|
|
1369
1476
|
exports.nv_fieldmultiselect = NvFieldmultiselect;
|