@milaboratories/uikit 2.6.1 → 2.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +48 -48
- package/.turbo/turbo-type-check.log +1 -1
- package/CHANGELOG.md +8 -0
- package/dist/components/DataTable/TableComponent.vue.js +4 -2
- package/dist/components/DataTable/TableComponent.vue.js.map +1 -1
- package/dist/components/PlAccordion/ExpandTransition.vue3.js +1 -1
- package/dist/components/PlAccordion/PlAccordionSection.vue2.js +1 -1
- package/dist/components/PlAutocomplete/PlAutocomplete.vue.d.ts +4 -0
- package/dist/components/PlAutocomplete/PlAutocomplete.vue.js +74 -68
- package/dist/components/PlAutocomplete/PlAutocomplete.vue.js.map +1 -1
- package/dist/components/PlAutocompleteMulti/PlAutocompleteMulti.vue.d.ts +4 -0
- package/dist/components/PlAutocompleteMulti/PlAutocompleteMulti.vue.js +52 -46
- package/dist/components/PlAutocompleteMulti/PlAutocompleteMulti.vue.js.map +1 -1
- package/dist/components/PlDropdown/PlDropdown.vue.d.ts +8 -0
- package/dist/components/PlDropdown/PlDropdown.vue.js +67 -60
- package/dist/components/PlDropdown/PlDropdown.vue.js.map +1 -1
- package/dist/components/PlDropdownLegacy/PlDropdownLegacy.vue.js +21 -19
- package/dist/components/PlDropdownLegacy/PlDropdownLegacy.vue.js.map +1 -1
- package/dist/components/PlDropdownMulti/PlDropdownMulti.vue.d.ts +4 -0
- package/dist/components/PlDropdownMulti/PlDropdownMulti.vue.js +47 -41
- package/dist/components/PlDropdownMulti/PlDropdownMulti.vue.js.map +1 -1
- package/dist/components/PlElementList/PlElementList.vue.d.ts +20 -0
- package/dist/components/PlElementList/PlElementList.vue2.js +180 -135
- package/dist/components/PlElementList/PlElementList.vue2.js.map +1 -1
- package/dist/components/PlElementList/PlElementListItem.vue.d.ts +20 -0
- package/dist/components/PlElementList/PlElementListItem.vue2.js +99 -74
- package/dist/components/PlElementList/PlElementListItem.vue2.js.map +1 -1
- package/dist/components/PlFileInput/PlFileInput.vue.js +24 -22
- package/dist/components/PlFileInput/PlFileInput.vue.js.map +1 -1
- package/dist/components/PlLogView/PlLogView.vue.js +24 -22
- package/dist/components/PlLogView/PlLogView.vue.js.map +1 -1
- package/dist/components/PlNumberField/PlNumberField.vue.d.ts +5 -0
- package/dist/components/PlNumberField/PlNumberField.vue.js +60 -54
- package/dist/components/PlNumberField/PlNumberField.vue.js.map +1 -1
- package/dist/components/PlSlideModal/PlPureSlideModal.vue.js +4 -2
- package/dist/components/PlSlideModal/PlPureSlideModal.vue.js.map +1 -1
- package/dist/components/PlTextArea/PlTextArea.vue.js +15 -13
- package/dist/components/PlTextArea/PlTextArea.vue.js.map +1 -1
- package/dist/components/PlTextField/PlTextField.vue.d.ts +4 -0
- package/dist/components/PlTextField/PlTextField.vue.js +45 -39
- package/dist/components/PlTextField/PlTextField.vue.js.map +1 -1
- package/dist/composition/filters/metadata.d.ts +205 -0
- package/dist/composition/filters/metadata.js +129 -19
- package/dist/composition/filters/metadata.js.map +1 -1
- package/dist/utils/DoubleContour.vue.d.ts +7 -1
- package/dist/utils/DoubleContour.vue.js +20 -13
- package/dist/utils/DoubleContour.vue.js.map +1 -1
- package/dist/utils/DoubleContour.vue2.js +19 -3
- package/dist/utils/DoubleContour.vue2.js.map +1 -1
- package/dist/utils/DoubleContour.vue3.js +7 -0
- package/dist/utils/DoubleContour.vue3.js.map +1 -0
- package/package.json +4 -4
- package/src/components/PlAutocomplete/PlAutocomplete.vue +6 -1
- package/src/components/PlAutocompleteMulti/PlAutocompleteMulti.vue +6 -1
- package/src/components/PlDropdown/PlDropdown.vue +12 -2
- package/src/components/PlDropdownMulti/PlDropdownMulti.vue +6 -1
- package/src/components/PlElementList/PlElementList.vue +40 -6
- package/src/components/PlElementList/PlElementListItem.vue +64 -47
- package/src/components/PlNumberField/PlNumberField.vue +4 -1
- package/src/components/PlTextField/PlTextField.vue +5 -1
- package/src/composition/filters/metadata.ts +105 -0
- package/src/utils/DoubleContour.vue +68 -2
- package/dist/components/PlAccordion/ExpandTransition.vue.js +0 -27
- package/dist/components/PlAccordion/ExpandTransition.vue.js.map +0 -1
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
(function(){"use strict";try{if(typeof document<"u"){var o=document.createElement("style");o.appendChild(document.createTextNode(`.pl-autocomplete-multi{--contour-color: var(--txt-01);--contour-border-width: 1px;--options-bg: #fff;--option-hover-bg: var(--btn-sec-hover-grey);--label-offset-left-x: 8px;--label-offset-right-x: 8px;--label-color: var(--txt-01);position:relative;outline:none;min-height:var(--control-height);border-radius:6px;font-family:var(--font-family-base);font-size:var(--font-size-base);font-weight:var(--font-weigh-base)}[data-theme=dark] .pl-autocomplete-multi{--options-bg: #1B1B1F}.pl-autocomplete-multi__envelope{font-family:var(--control-font-family);min-width:160px}.pl-autocomplete-multi label{display:flex;align-items:center;gap:4px;position:absolute;top:0;transform:translateY(-60%);left:var(--label-offset-left-x);padding:0 4px;max-width:calc(100% - 16px);overflow:hidden;white-space:pre;text-overflow:ellipsis;cursor:inherit;color:var(--label-color);font-size:12px;font-weight:500;border-bottom-right-radius:4px;border-bottom-left-radius:4px;background:var(--bg-elevated-01)}.pl-autocomplete-multi label>span{overflow:hidden;white-space:pre;text-overflow:ellipsis}.pl-autocomplete-multi__container{position:absolute;top:0;left:0;right:0;border-radius:6px;min-height:var(--control-height);padding:1px;color:var(--txt-01)}.pl-autocomplete-multi__contour{border-radius:var(--border-radius-control);border:var(--contour-border-width) solid var(--contour-color);box-shadow:var(--contour-box-shadow);z-index:0;pointer-events:none}.pl-autocomplete-multi__options{position:absolute;z-index:var(--z-dropdown-options);border:1px solid var(--border-color-div-grey);background-color:var(--pl-dropdown-options-bg);border-radius:6px;max-height:244px;box-shadow:0 4px 12px -2px #0f244d14,0 6px 24px -2px #0f244d14;--thumb-color: var(--ic-02);overflow-y:auto}.pl-autocomplete-multi__options::-webkit-scrollbar{width:var(--scrollbar-width, 6px);height:5px;background-color:transparent;display:block}.pl-autocomplete-multi__options::-webkit-scrollbar-thumb{background:var(--thumb-color);border-radius:5px}.pl-autocomplete-multi__options::-webkit-scrollbar-thumb:hover{--thumb-color: var(--border-color-focus)}.pl-autocomplete-multi__options .nothing-found{padding:0 10px;height:var(--control-height);line-height:20px;background-color:#fff;opacity:.5;font-style:italic}.pl-autocomplete-multi__field{position:relative;border-radius:6px;overflow:hidden;background:transparent;padding-left:11px;min-height:var(--control-height);line-height:20px;cursor:pointer;display:flex;flex-direction:row;align-items:center}.pl-autocomplete-multi__field .chips-container{position:absolute;top:0;left:0;bottom:0;right:30px;overflow:hidden;padding:0 60px 0 11px;line-height:20px;color:var(--contour-color);display:flex;gap:8px;align-items:center}.pl-autocomplete-multi__field input{min-height:calc(var(--control-height) - 2px);line-height:20px;font-family:inherit;font-size:inherit;background-color:transparent;border:none;padding:0;width:calc(100% - 20px);color:var(--txt-01);caret-color:var(--border-color-focus)}.pl-autocomplete-multi__field input:focus{outline:none}.pl-autocomplete-multi__field input:placeholder-shown{text-overflow:ellipsis}.pl-autocomplete-multi__field input::placeholder{color:var(--color-placeholder)}.pl-autocomplete-multi__field:hover .clear{display:block}.pl-autocomplete-multi__controls{display:flex;flex-direction:row;align-items:center;gap:6px;margin-left:auto}.pl-autocomplete-multi__controls .mask-16,.pl-autocomplete-multi__controls .mask-24{--icon-color: var(--control-mask-fill);cursor:pointer}.pl-autocomplete-multi__controls .mask-loading{--icon-color: var(--ic-accent);animation:spin 2.5s linear infinite}.pl-autocomplete-multi__arrow-wrapper{display:flex;align-items:center;min-height:var(--control-height);padding-right:11px}.pl-autocomplete-multi .arrow-icon{cursor:pointer}.pl-autocomplete-multi .arrow-icon.arrow-icon-default{transition:transform .2s;background-color:var(--control-mask-fill);mask-image:url("data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M2.46967%206.53033L3.53033%205.46967L8%209.93934L12.4697%205.46967L13.5303%206.53033L8%2012.0607L2.46967%206.53033Z'%20fill='%23110529'/%3e%3c/svg%3e");-webkit-mask-image:url("data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M2.46967%206.53033L3.53033%205.46967L8%209.93934L12.4697%205.46967L13.5303%206.53033L8%2012.0607L2.46967%206.53033Z'%20fill='%23110529'/%3e%3c/svg%3e");mask-repeat:no-repeat;-webkit-mask-repeat:no-repeat;mask-position:center;-webkit-mask-position:center;mask-size:16px;-webkit-mask-size:16px;width:16px;height:16px}.pl-autocomplete-multi__helper{font-size:12px;color:var(--txt-03);padding:2px 0 0;white-space:pre-wrap;text-overflow:ellipsis;font-weight:500;line-height:16px;margin-top:6px}.pl-autocomplete-multi__error{font-size:12px;color:var(--txt-error);padding:2px 0 0;white-space:pre-wrap;text-overflow:ellipsis;font-weight:500;line-height:16px;margin-top:6px}.pl-autocomplete-multi.open .arrow-icon.arrow-icon-default{background-color:var(--control-mask-fill);transform:rotate(-180deg)}.pl-autocomplete-multi .clear{display:none;position:absolute;top:50%;transform:translateY(-50%);right:36px;z-index:1;background:url("data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20clip-path='url(%23clip0_586_7851)'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M8%2016C12.4183%2016%2016%2012.4183%2016%208C16%203.58172%2012.4183%200%208%200C3.58172%200%200%203.58172%200%208C0%2012.4183%203.58172%2016%208%2016ZM4.46967%205.53033L6.93934%208L4.46967%2010.4697L5.53033%2011.5303L8%209.06066L10.4697%2011.5303L11.5303%2010.4697L9.06066%208L11.5303%205.53033L10.4697%204.46967L8%206.93934L5.53033%204.46967L4.46967%205.53033Z'%20fill='%23CFD1DB'/%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='clip0_586_7851'%3e%3crect%20width='16'%20height='16'%20fill='white'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e") no-repeat center;width:16px;height:16px;cursor:pointer}.pl-autocomplete-multi.open,.pl-autocomplete-multi:focus-within{z-index:1}.pl-autocomplete-multi.open .pl-autocomplete-multi__container .label,.pl-autocomplete-multi:focus-within .pl-autocomplete-multi__container .label{color:var(--txt-focus)}.pl-autocomplete-multi.open .pl-autocomplete-multi__container{z-index:1000}.pl-autocomplete-multi.open .pl-autocomplete-multi__field{border-radius:6px 6px 0 0}.pl-autocomplete-multi.open .arrow{background-color:var(--control-mask-fill);mask-image:url("data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M8%204.93933L13.5303%2010.4697L12.4697%2011.5303L8%207.06065L3.53033%2011.5303L2.46967%2010.4697L8%204.93933Z'%20fill='%23110529'/%3e%3c/svg%3e");-webkit-mask-image:url("data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M8%204.93933L13.5303%2010.4697L12.4697%2011.5303L8%207.06065L3.53033%2011.5303L2.46967%2010.4697L8%204.93933Z'%20fill='%23110529'/%3e%3c/svg%3e");mask-repeat:no-repeat;-webkit-mask-repeat:no-repeat;mask-position:center;-webkit-mask-position:center;mask-size:16px;-webkit-mask-size:16px;width:16px;height:16px}.pl-autocomplete-multi:hover{--contour-color: var(--control-hover-color)}.pl-autocomplete-multi:focus-within:not(.error){--label-color: var(--txt-focus);--contour-color: var(--border-color-focus);--contour-border-width: 2px;--contour-box-shadow: 0 0 0 4px var(--border-color-focus-shadow)}.pl-autocomplete-multi:focus-within.error{--contour-border-width: 2px;--contour-box-shadow: 0 0 0 4px var(--color-error-shadow)}.pl-autocomplete-multi.error{--contour-color: var(--txt-error);--label-color: var(--txt-error)}.pl-autocomplete-multi.disabled{--contour-color: var(--color-dis-01);--control-mask-fill: var(--color-dis-01);--label-color: var(--color-dis-01);cursor:not-allowed;pointer-events:none}.pl-autocomplete-multi.disabled .mask-loading{animation:spin 2.5s linear infinite;--icon-color: var(--ic-accent)}.pl-autocomplete-multi__open-chips-container{padding:12px}.pl-autocomplete-multi__open-chips-container .pl-chip{margin-right:4px;margin-bottom:4px}
|
|
2
|
-
|
|
1
|
+
(function(){"use strict";try{if(typeof document<"u"){var o=document.createElement("style");o.appendChild(document.createTextNode(`.pl-autocomplete-multi{--contour-color: var(--txt-01);--contour-border-width: 1px;--options-bg: #fff;--option-hover-bg: var(--btn-sec-hover-grey);--label-offset-left-x: 8px;--label-offset-right-x: 8px;--label-color: var(--txt-01);position:relative;outline:none;min-height:var(--control-height);border-radius:6px;font-family:var(--font-family-base);font-size:var(--font-size-base);font-weight:var(--font-weigh-base)}[data-theme=dark] .pl-autocomplete-multi{--options-bg: #1B1B1F}.pl-autocomplete-multi__envelope{font-family:var(--control-font-family);min-width:160px}.pl-autocomplete-multi label{display:flex;align-items:center;gap:4px;position:absolute;top:0;transform:translateY(-60%);left:var(--label-offset-left-x);padding:0 4px;max-width:calc(100% - 16px);overflow:hidden;white-space:pre;text-overflow:ellipsis;cursor:inherit;color:var(--label-color);font-size:12px;font-weight:500;border-bottom-right-radius:4px;border-bottom-left-radius:4px;background:var(--bg-elevated-01)}.pl-autocomplete-multi label>span{overflow:hidden;white-space:pre;text-overflow:ellipsis}.pl-autocomplete-multi__container{position:absolute;top:0;left:0;right:0;border-radius:6px;min-height:var(--control-height);padding:1px;color:var(--txt-01)}.pl-autocomplete-multi__contour{border-radius:var(--border-radius-control);border:var(--contour-border-width) solid var(--contour-color);box-shadow:var(--contour-box-shadow);z-index:0;pointer-events:none}.pl-autocomplete-multi__options{position:absolute;z-index:var(--z-dropdown-options);border:1px solid var(--border-color-div-grey);background-color:var(--pl-dropdown-options-bg);border-radius:6px;max-height:244px;box-shadow:0 4px 12px -2px #0f244d14,0 6px 24px -2px #0f244d14;--thumb-color: var(--ic-02);overflow-y:auto}.pl-autocomplete-multi__options::-webkit-scrollbar{width:var(--scrollbar-width, 6px);height:5px;background-color:transparent;display:block}.pl-autocomplete-multi__options::-webkit-scrollbar-thumb{background:var(--thumb-color);border-radius:5px}.pl-autocomplete-multi__options::-webkit-scrollbar-thumb:hover{--thumb-color: var(--border-color-focus)}.pl-autocomplete-multi__options .nothing-found{padding:0 10px;height:var(--control-height);line-height:20px;background-color:#fff;opacity:.5;font-style:italic}.pl-autocomplete-multi__field{position:relative;border-radius:6px;overflow:hidden;background:transparent;padding-left:11px;min-height:var(--control-height);line-height:20px;cursor:pointer;display:flex;flex-direction:row;align-items:center}.pl-autocomplete-multi__field .chips-container{position:absolute;top:0;left:0;bottom:0;right:30px;overflow:hidden;padding:0 60px 0 11px;line-height:20px;color:var(--contour-color);display:flex;gap:8px;align-items:center}.pl-autocomplete-multi__field input{min-height:calc(var(--control-height) - 2px);line-height:20px;font-family:inherit;font-size:inherit;background-color:transparent;border:none;padding:0;width:calc(100% - 20px);color:var(--txt-01);caret-color:var(--border-color-focus)}.pl-autocomplete-multi__field input:focus{outline:none}.pl-autocomplete-multi__field input:placeholder-shown{text-overflow:ellipsis}.pl-autocomplete-multi__field input::placeholder{color:var(--color-placeholder)}.pl-autocomplete-multi__field:hover .clear{display:block}.pl-autocomplete-multi__controls{display:flex;flex-direction:row;align-items:center;gap:6px;margin-left:auto}.pl-autocomplete-multi__controls .mask-16,.pl-autocomplete-multi__controls .mask-24{--icon-color: var(--control-mask-fill);cursor:pointer}.pl-autocomplete-multi__controls .mask-loading{--icon-color: var(--ic-accent);animation:spin 2.5s linear infinite}.pl-autocomplete-multi__arrow-wrapper{display:flex;align-items:center;min-height:var(--control-height);padding-right:11px}.pl-autocomplete-multi .arrow-icon{cursor:pointer}.pl-autocomplete-multi .arrow-icon.arrow-icon-default{transition:transform .2s;background-color:var(--control-mask-fill);mask-image:url("data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M2.46967%206.53033L3.53033%205.46967L8%209.93934L12.4697%205.46967L13.5303%206.53033L8%2012.0607L2.46967%206.53033Z'%20fill='%23110529'/%3e%3c/svg%3e");-webkit-mask-image:url("data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M2.46967%206.53033L3.53033%205.46967L8%209.93934L12.4697%205.46967L13.5303%206.53033L8%2012.0607L2.46967%206.53033Z'%20fill='%23110529'/%3e%3c/svg%3e");mask-repeat:no-repeat;-webkit-mask-repeat:no-repeat;mask-position:center;-webkit-mask-position:center;mask-size:16px;-webkit-mask-size:16px;width:16px;height:16px}.pl-autocomplete-multi__helper{font-size:12px;color:var(--txt-03);padding:2px 0 0;white-space:pre-wrap;text-overflow:ellipsis;font-weight:500;line-height:16px;margin-top:6px}.pl-autocomplete-multi__error{font-size:12px;color:var(--txt-error);padding:2px 0 0;white-space:pre-wrap;text-overflow:ellipsis;font-weight:500;line-height:16px;margin-top:6px}.pl-autocomplete-multi.open .arrow-icon.arrow-icon-default{background-color:var(--control-mask-fill);transform:rotate(-180deg)}.pl-autocomplete-multi .clear{display:none;position:absolute;top:50%;transform:translateY(-50%);right:36px;z-index:1;background:url("data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20clip-path='url(%23clip0_586_7851)'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M8%2016C12.4183%2016%2016%2012.4183%2016%208C16%203.58172%2012.4183%200%208%200C3.58172%200%200%203.58172%200%208C0%2012.4183%203.58172%2016%208%2016ZM4.46967%205.53033L6.93934%208L4.46967%2010.4697L5.53033%2011.5303L8%209.06066L10.4697%2011.5303L11.5303%2010.4697L9.06066%208L11.5303%205.53033L10.4697%204.46967L8%206.93934L5.53033%204.46967L4.46967%205.53033Z'%20fill='%23CFD1DB'/%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='clip0_586_7851'%3e%3crect%20width='16'%20height='16'%20fill='white'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e") no-repeat center;width:16px;height:16px;cursor:pointer}.pl-autocomplete-multi.open,.pl-autocomplete-multi:focus-within{z-index:1}.pl-autocomplete-multi.open .pl-autocomplete-multi__container .label,.pl-autocomplete-multi:focus-within .pl-autocomplete-multi__container .label{color:var(--txt-focus)}.pl-autocomplete-multi.open .pl-autocomplete-multi__container{z-index:1000}.pl-autocomplete-multi.open .pl-autocomplete-multi__field{border-radius:6px 6px 0 0}.pl-autocomplete-multi.open .arrow{background-color:var(--control-mask-fill);mask-image:url("data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M8%204.93933L13.5303%2010.4697L12.4697%2011.5303L8%207.06065L3.53033%2011.5303L2.46967%2010.4697L8%204.93933Z'%20fill='%23110529'/%3e%3c/svg%3e");-webkit-mask-image:url("data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M8%204.93933L13.5303%2010.4697L12.4697%2011.5303L8%207.06065L3.53033%2011.5303L2.46967%2010.4697L8%204.93933Z'%20fill='%23110529'/%3e%3c/svg%3e");mask-repeat:no-repeat;-webkit-mask-repeat:no-repeat;mask-position:center;-webkit-mask-position:center;mask-size:16px;-webkit-mask-size:16px;width:16px;height:16px}.pl-autocomplete-multi:hover{--contour-color: var(--control-hover-color)}.pl-autocomplete-multi:focus-within:not(.error){--label-color: var(--txt-focus);--contour-color: var(--border-color-focus);--contour-border-width: 2px;--contour-box-shadow: 0 0 0 4px var(--border-color-focus-shadow)}.pl-autocomplete-multi:focus-within.error{--contour-border-width: 2px;--contour-box-shadow: 0 0 0 4px var(--color-error-shadow)}.pl-autocomplete-multi.error{--contour-color: var(--txt-error);--label-color: var(--txt-error)}.pl-autocomplete-multi.disabled{--contour-color: var(--color-dis-01);--control-mask-fill: var(--color-dis-01);--label-color: var(--color-dis-01);cursor:not-allowed;pointer-events:none}.pl-autocomplete-multi.disabled .mask-loading{animation:spin 2.5s linear infinite;--icon-color: var(--ic-accent)}.pl-autocomplete-multi__open-chips-container{padding:12px}.pl-autocomplete-multi__open-chips-container .pl-chip{margin-right:4px;margin-bottom:4px}
|
|
2
|
+
.double-contour.top>div{border-bottom-right-radius:0;border-bottom-left-radius:0}.double-contour.bottom>div{border-top-right-radius:0;border-top-left-radius:0}.double-contour.left>div{border-top-right-radius:0;border-bottom-right-radius:0}.double-contour.right>div{border-top-left-radius:0;border-bottom-left-radius:0}.double-contour.top-left>div{border-top-right-radius:0;border-bottom-left-radius:0;border-bottom-right-radius:0}.double-contour.top-right>div{border-bottom-right-radius:0;border-top-left-radius:0;border-top-right-radius:0}.double-contour.bottom-left>div{border-top-right-radius:0;border-bottom-right-radius:0;border-top-left-radius:0}.double-contour.bottom-right>div{border-top-right-radius:0;border-bottom-left-radius:0;border-top-left-radius:0}.double-contour.middle>div{border-radius:0}`)),document.head.appendChild(o)}}catch(t){console.error("vite-plugin-css-injected-by-js",t)}})();
|
|
3
|
+
import { defineComponent as ne, useSlots as re, ref as P, useTemplateRef as se, reactive as ae, watch as z, computed as u, toRef as ie, unref as i, createElementBlock as c, openBlock as s, createElementVNode as d, createCommentVNode as p, normalizeClass as ue, createBlock as f, createVNode as ce, withDirectives as de, vModelText as pe, Fragment as E, renderList as F, withModifiers as T, withCtx as O, createTextVNode as L, toDisplayString as m, renderSlot as U } from "vue";
|
|
3
4
|
|
|
4
5
|
import fe from "canonicalize";
|
|
5
6
|
import { useWatchFetch as K } from "../../composition/useWatchFetch.js";
|
|
6
|
-
import { getErrorMessage as
|
|
7
|
-
import { deepEqual as
|
|
7
|
+
import { getErrorMessage as B } from "../../helpers/error.js";
|
|
8
|
+
import { deepEqual as I, deepIncludes as W } from "../../helpers/objects.js";
|
|
8
9
|
import me from "../../utils/DoubleContour.vue.js";
|
|
10
|
+
|
|
9
11
|
import ve from "../../utils/DropdownOverlay/DropdownOverlay.vue.js";
|
|
10
12
|
import { useLabelNotch as he } from "../../utils/useLabelNotch.js";
|
|
11
13
|
import _e from "../DropdownListItem.vue.js";
|
|
12
14
|
import H from "../PlChip/PlChip.vue.js";
|
|
13
15
|
import ye from "../PlIcon24/PlIcon24.vue.js";
|
|
14
|
-
import
|
|
16
|
+
import ge from "../PlTooltip/PlTooltip.vue.js";
|
|
15
17
|
import ke from "../../assets/images/required.svg.js";
|
|
16
|
-
import
|
|
17
|
-
const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we = { class: "pl-autocomplete-multi__field" }, Re = ["disabled", "placeholder"],
|
|
18
|
+
import be from "../PlSvg/PlSvg.vue.js";
|
|
19
|
+
const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we = { class: "pl-autocomplete-multi__field" }, Re = ["disabled", "placeholder"], Se = {
|
|
18
20
|
key: 0,
|
|
19
21
|
class: "chips-container"
|
|
20
|
-
},
|
|
22
|
+
}, Ce = { class: "pl-autocomplete-multi__controls" }, $e = { key: 0 }, Ae = { class: "pl-autocomplete-multi__open-chips-container" }, Ee = {
|
|
21
23
|
key: 0,
|
|
22
24
|
class: "nothing-found"
|
|
23
25
|
}, Fe = {
|
|
@@ -26,10 +28,10 @@ const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we
|
|
|
26
28
|
}, Te = {
|
|
27
29
|
key: 1,
|
|
28
30
|
class: "pl-autocomplete-multi__helper"
|
|
29
|
-
},
|
|
31
|
+
}, Be = {
|
|
30
32
|
name: "PlAutocompleteMulti"
|
|
31
|
-
},
|
|
32
|
-
...
|
|
33
|
+
}, Qe = /* @__PURE__ */ ne({
|
|
34
|
+
...Be,
|
|
33
35
|
props: {
|
|
34
36
|
modelValue: { default: () => [] },
|
|
35
37
|
optionsSearch: {},
|
|
@@ -43,24 +45,25 @@ const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we
|
|
|
43
45
|
disabled: { type: Boolean, default: !1 },
|
|
44
46
|
debounce: { default: 300 },
|
|
45
47
|
resetSearchOnSelect: { type: Boolean },
|
|
46
|
-
emptyOptionsText: { default: "Nothing found" }
|
|
48
|
+
emptyOptionsText: { default: "Nothing found" },
|
|
49
|
+
groupPosition: { default: void 0 }
|
|
47
50
|
},
|
|
48
51
|
emits: ["update:modelValue"],
|
|
49
52
|
setup(j, { emit: G }) {
|
|
50
|
-
const J = G,
|
|
53
|
+
const J = G, M = (e) => J("update:modelValue", e), Q = re(), n = j, g = P(), k = P(), V = se("overlay"), l = ae({
|
|
51
54
|
search: "",
|
|
52
55
|
activeOption: -1,
|
|
53
56
|
open: !1,
|
|
54
57
|
optionsHeight: 0
|
|
55
58
|
});
|
|
56
|
-
|
|
59
|
+
z(() => l.open, (e) => {
|
|
57
60
|
e || (l.search = "");
|
|
58
61
|
}, { flush: "sync" });
|
|
59
|
-
const
|
|
62
|
+
const b = u(() => Array.isArray(n.modelValue) ? n.modelValue : []), X = u(() => l.open && n.modelValue.length > 0 ? n.placeholder : n.modelValue.length > 0 ? "" : n.placeholder), x = ie(n, "debounce"), v = K(() => [l.search, l.open, n.sourceId], async ([e, t]) => n.optionsSearch(e), {
|
|
60
63
|
filterWatchResult: ([e, t]) => t,
|
|
61
|
-
debounce:
|
|
64
|
+
debounce: x
|
|
62
65
|
}), h = K(() => [n.modelValue, n.sourceId], async ([e]) => n.modelSearch(e), {
|
|
63
|
-
debounce:
|
|
66
|
+
debounce: x
|
|
64
67
|
}), Y = u(() => {
|
|
65
68
|
const e = h.value ?? [], t = v.value ?? [], o = /* @__PURE__ */ new Set(), r = [], a = (A) => {
|
|
66
69
|
for (const _ of A) {
|
|
@@ -69,27 +72,27 @@ const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we
|
|
|
69
72
|
}
|
|
70
73
|
};
|
|
71
74
|
return a(e), a(t), r;
|
|
72
|
-
}), w = u(() =>
|
|
75
|
+
}), w = u(() => b.value.map((e) => Y.value.find((t) => I(t.value, e))).filter(
|
|
73
76
|
(e) => e !== void 0
|
|
74
77
|
)), R = u(() => {
|
|
75
|
-
const e = i(
|
|
78
|
+
const e = i(b);
|
|
76
79
|
return [...v.value ?? []].map((o) => ({
|
|
77
80
|
...o,
|
|
78
81
|
selected: W(e, o.value)
|
|
79
82
|
}));
|
|
80
|
-
}),
|
|
83
|
+
}), S = u(() => v.loading || h.loading), C = u(() => h.value === void 0 ? !0 : n.disabled), Z = u(() => C.value ? void 0 : "0"), ee = () => {
|
|
81
84
|
l.activeOption = 0;
|
|
82
|
-
},
|
|
85
|
+
}, D = (e) => {
|
|
83
86
|
var o;
|
|
84
|
-
const t = i(
|
|
85
|
-
|
|
86
|
-
}, N = (e) =>
|
|
87
|
+
const t = i(b);
|
|
88
|
+
M(W(t, e) ? t.filter((r) => !I(r, e)) : [...t, e]), n.resetSearchOnSelect && (l.search = ""), (o = k.value) == null || o.focus();
|
|
89
|
+
}, N = (e) => M(i(b).filter((t) => !I(t, e))), oe = () => {
|
|
87
90
|
var e;
|
|
88
91
|
return (e = k.value) == null ? void 0 : e.focus();
|
|
89
92
|
}, te = () => l.open = !l.open, q = (e) => {
|
|
90
93
|
var o, r, a;
|
|
91
94
|
const t = e.relatedTarget;
|
|
92
|
-
!((o =
|
|
95
|
+
!((o = g.value) != null && o.contains(t)) && !((a = (r = V.value) == null ? void 0 : r.listRef) != null && a.contains(t)) && (l.open = !1);
|
|
93
96
|
}, le = (e) => {
|
|
94
97
|
var _;
|
|
95
98
|
const { open: t, activeOption: o } = l;
|
|
@@ -101,26 +104,26 @@ const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we
|
|
|
101
104
|
const r = i(R), { length: a } = r;
|
|
102
105
|
if (!a)
|
|
103
106
|
return;
|
|
104
|
-
["ArrowDown", "ArrowUp", "Enter"].includes(e.code) && e.preventDefault(), e.code === "Enter" &&
|
|
107
|
+
["ArrowDown", "ArrowUp", "Enter"].includes(e.code) && e.preventDefault(), e.code === "Enter" && D(r[o].value);
|
|
105
108
|
const A = e.code === "ArrowDown" ? 1 : e.code === "ArrowUp" ? -1 : 0;
|
|
106
109
|
l.activeOption = Math.abs(o + A + a) % a, requestAnimationFrame(() => {
|
|
107
110
|
var y;
|
|
108
111
|
return (y = V.value) == null ? void 0 : y.scrollIntoActive();
|
|
109
112
|
});
|
|
110
113
|
};
|
|
111
|
-
he(
|
|
114
|
+
he(g), z(
|
|
112
115
|
() => n.modelValue,
|
|
113
116
|
() => ee(),
|
|
114
117
|
{ immediate: !0 }
|
|
115
118
|
);
|
|
116
119
|
const $ = u(() => {
|
|
117
|
-
if (!
|
|
120
|
+
if (!S.value) {
|
|
118
121
|
if (v.error)
|
|
119
|
-
return
|
|
122
|
+
return B(v.error);
|
|
120
123
|
if (h.error)
|
|
121
|
-
return
|
|
124
|
+
return B(h.error);
|
|
122
125
|
if (n.error)
|
|
123
|
-
return
|
|
126
|
+
return B(n.error);
|
|
124
127
|
if (n.modelValue.length && w.value.length !== n.modelValue.length)
|
|
125
128
|
return "The selected values are not one of the options";
|
|
126
129
|
}
|
|
@@ -131,9 +134,9 @@ const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we
|
|
|
131
134
|
}, [
|
|
132
135
|
d("div", {
|
|
133
136
|
ref_key: "rootRef",
|
|
134
|
-
ref:
|
|
137
|
+
ref: g,
|
|
135
138
|
tabindex: Z.value,
|
|
136
|
-
class: ue(["pl-autocomplete-multi", { open: l.open, error: !!$.value, disabled:
|
|
139
|
+
class: ue(["pl-autocomplete-multi", { open: l.open, error: !!$.value, disabled: C.value }]),
|
|
137
140
|
onKeydown: le,
|
|
138
141
|
onFocusout: q
|
|
139
142
|
}, [
|
|
@@ -145,7 +148,7 @@ const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we
|
|
|
145
148
|
"onUpdate:modelValue": t[0] || (t[0] = (o) => l.search = o),
|
|
146
149
|
type: "text",
|
|
147
150
|
tabindex: "-1",
|
|
148
|
-
disabled:
|
|
151
|
+
disabled: C.value,
|
|
149
152
|
placeholder: X.value,
|
|
150
153
|
spellcheck: "false",
|
|
151
154
|
autocomplete: "chrome-off",
|
|
@@ -153,7 +156,7 @@ const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we
|
|
|
153
156
|
}, null, 40, Re), [
|
|
154
157
|
[pe, l.search]
|
|
155
158
|
]),
|
|
156
|
-
l.open ? p("", !0) : (s(), c("div",
|
|
159
|
+
l.open ? p("", !0) : (s(), c("div", Se, [
|
|
157
160
|
(s(!0), c(E, null, F(w.value, (o, r) => (s(), f(i(H), {
|
|
158
161
|
key: r,
|
|
159
162
|
closeable: "",
|
|
@@ -162,13 +165,13 @@ const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we
|
|
|
162
165
|
onClose: (a) => N(o.value)
|
|
163
166
|
}, {
|
|
164
167
|
default: O(() => [
|
|
165
|
-
|
|
168
|
+
L(m(o.label || o.value), 1)
|
|
166
169
|
]),
|
|
167
170
|
_: 2
|
|
168
171
|
}, 1032, ["onClose"]))), 128))
|
|
169
172
|
])),
|
|
170
|
-
d("div",
|
|
171
|
-
|
|
173
|
+
d("div", Ce, [
|
|
174
|
+
S.value ? (s(), f(i(ye), {
|
|
172
175
|
key: 0,
|
|
173
176
|
name: "loading"
|
|
174
177
|
})) : p("", !0),
|
|
@@ -182,12 +185,12 @@ const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we
|
|
|
182
185
|
])
|
|
183
186
|
]),
|
|
184
187
|
e.label ? (s(), c("label", $e, [
|
|
185
|
-
e.required ? (s(), f(i(
|
|
188
|
+
e.required ? (s(), f(i(be), {
|
|
186
189
|
key: 0,
|
|
187
190
|
uri: i(ke)
|
|
188
191
|
}, null, 8, ["uri"])) : p("", !0),
|
|
189
192
|
d("span", null, m(e.label), 1),
|
|
190
|
-
i(Q).tooltip ? (s(), f(i(
|
|
193
|
+
i(Q).tooltip ? (s(), f(i(ge), {
|
|
191
194
|
key: 1,
|
|
192
195
|
class: "info",
|
|
193
196
|
position: "top"
|
|
@@ -202,7 +205,7 @@ const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we
|
|
|
202
205
|
key: 1,
|
|
203
206
|
ref_key: "overlay",
|
|
204
207
|
ref: V,
|
|
205
|
-
root:
|
|
208
|
+
root: g.value,
|
|
206
209
|
class: "pl-autocomplete-multi__options",
|
|
207
210
|
gap: 5,
|
|
208
211
|
tabindex: "-1",
|
|
@@ -217,7 +220,7 @@ const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we
|
|
|
217
220
|
onClose: (a) => N(o.value)
|
|
218
221
|
}, {
|
|
219
222
|
default: O(() => [
|
|
220
|
-
|
|
223
|
+
L(m(o.label || o.value), 1)
|
|
221
224
|
]),
|
|
222
225
|
_: 2
|
|
223
226
|
}, 1032, ["onClose"]))), 128))
|
|
@@ -230,13 +233,16 @@ const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we
|
|
|
230
233
|
"is-hovered": l.activeOption == r,
|
|
231
234
|
size: "medium",
|
|
232
235
|
"use-checkbox": "",
|
|
233
|
-
onClick: T((a) =>
|
|
236
|
+
onClick: T((a) => D(o.value), ["stop"])
|
|
234
237
|
}, null, 8, ["option", "is-selected", "is-hovered", "onClick"]))), 128)),
|
|
235
|
-
!R.value.length && !
|
|
238
|
+
!R.value.length && !S.value ? (s(), c("div", Ee, m(e.emptyOptionsText), 1)) : p("", !0)
|
|
236
239
|
]),
|
|
237
240
|
_: 1
|
|
238
241
|
}, 8, ["root"])) : p("", !0),
|
|
239
|
-
ce(me, {
|
|
242
|
+
ce(me, {
|
|
243
|
+
class: "pl-autocomplete-multi__contour",
|
|
244
|
+
"group-position": e.groupPosition
|
|
245
|
+
}, null, 8, ["group-position"])
|
|
240
246
|
])
|
|
241
247
|
], 42, Oe),
|
|
242
248
|
$.value ? (s(), c("div", Fe, m($.value), 1)) : e.helper ? (s(), c("div", Te, m(e.helper), 1)) : p("", !0)
|
|
@@ -244,6 +250,6 @@ const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we
|
|
|
244
250
|
}
|
|
245
251
|
});
|
|
246
252
|
export {
|
|
247
|
-
|
|
253
|
+
Qe as default
|
|
248
254
|
};
|
|
249
255
|
//# sourceMappingURL=PlAutocompleteMulti.vue.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAutocompleteMulti.vue.js","sources":["../../../src/components/PlAutocompleteMulti/PlAutocompleteMulti.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * A multi-select autocomplete component that allows users to search and select multiple values from a list of options.\n * Supports async data fetching, keyboard navigation, and displays selected items as removable chips.\n *\n * @example\n * Basic usage:\n * <PlAutocompleteMulti\n * v-model=\"selectedUsers\"\n * :options-search=\"searchUsers\"\n * :model-search=\"getUsersByIds\"\n * label=\"Select Users\"\n * placeholder=\"Search for users...\"\n * required\n * :debounce=\"300\"\n * helper=\"Choose one or more users from the list\"\n * />\n *\n * With async functions:\n * const selectedUsers = ref([])\n *\n * const searchUsers = async (searchTerm) => {\n * const response = await fetch('/api/users/search?q=' + searchTerm)\n * const users = await response.json()\n * return users.map(user => ({ value: user.id, label: user.name }))\n * }\n *\n * const getUsersByIds = async (userIds) => {\n * if (!userIds.length) return []\n * const response = await fetch('/api/users?ids=' + userIds.join(','))\n * const users = await response.json()\n * return users.map(user => ({ value: user.id, label: user.name }))\n * }\n */\nexport default {\n name: 'PlAutocompleteMulti',\n};\n</script>\n\n<script lang=\"ts\" setup generic=\"M = unknown\">\nimport './pl-autocomplete-multi.scss';\n\nimport type { ListOptionBase } from '@platforma-sdk/model';\nimport canonicalize from 'canonicalize';\nimport { computed, reactive, ref, toRef, unref, useSlots, useTemplateRef, watch } from 'vue';\nimport { useWatchFetch } from '../../composition/useWatchFetch.ts';\nimport { getErrorMessage } from '../../helpers/error.ts';\nimport { deepEqual, deepIncludes } from '../../helpers/objects';\nimport DoubleContour from '../../utils/DoubleContour.vue';\nimport DropdownOverlay from '../../utils/DropdownOverlay/DropdownOverlay.vue';\nimport { useLabelNotch } from '../../utils/useLabelNotch';\nimport DropdownListItem from '../DropdownListItem.vue';\nimport { PlChip } from '../PlChip';\nimport { PlMaskIcon24 } from '../PlMaskIcon24';\nimport { PlTooltip } from '../PlTooltip';\n\nimport SvgRequired from '../../assets/images/required.svg?raw';\nimport { PlSvg } from '../PlSvg';\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', v: M[]): void;\n}>();\n\nconst emitModel = (v: M[]) => emit('update:modelValue', v);\n\nconst slots = useSlots();\n\nconst props = withDefaults(\n defineProps<{\n /**\n * The current selected values.\n */\n modelValue: M[];\n /**\n * Lambda for requesting of available options for the dropdown by search string.\n */\n optionsSearch: (s: string) => Promise<Readonly<ListOptionBase<M>[]>>;\n /**\n * Lambda for requesting options that correspond to the current model values.\n */\n modelSearch: (values: M[]) => Promise<Readonly<ListOptionBase<M>[]>>;\n /**\n * Unique identifier for the source of the options, changing it will invalidate the options cache.\n */\n sourceId?: string;\n /**\n * The label text for the dropdown field (optional)\n */\n label?: string;\n /**\n * A helper text displayed below the dropdown when there are no errors (optional).\n */\n helper?: string;\n /**\n * Error message displayed below the dropdown (optional)\n */\n error?: unknown;\n /**\n * Placeholder text shown when no value is selected.\n */\n placeholder?: string;\n /**\n * If `true`, the dropdown component is marked as required.\n */\n required?: boolean;\n /**\n * If `true`, the dropdown component is disabled and cannot be interacted with.\n */\n disabled?: boolean;\n /**\n * Debounce time in ms for the options search.\n */\n debounce?: number;\n /**\n * If `true`, the search input is reset and focus is set on it when the new option is selected.\n */\n resetSearchOnSelect?: boolean;\n /**\n * The text to display when no options are found.\n */\n emptyOptionsText?: string;\n }>(),\n {\n modelValue: () => [],\n label: undefined,\n helper: undefined,\n error: undefined,\n placeholder: '...',\n required: false,\n disabled: false,\n debounce: 300,\n emptyOptionsText: 'Nothing found',\n sourceId: undefined,\n },\n);\n\nconst rootRef = ref<HTMLElement | undefined>();\nconst inputRef = ref<HTMLInputElement | undefined>();\n\nconst overlay = useTemplateRef('overlay');\n\nconst data = reactive({\n search: '',\n activeOption: -1,\n open: false,\n optionsHeight: 0,\n});\n\nwatch(() => data.open, (v) => {\n if (!v) {\n data.search = '';\n }\n}, { flush: 'sync' });\n\nconst selectedValuesRef = computed(() => (Array.isArray(props.modelValue) ? props.modelValue : []));\n\nconst placeholderRef = computed(() => {\n if (data.open && props.modelValue.length > 0) {\n return props.placeholder;\n }\n\n return props.modelValue.length > 0 ? '' : props.placeholder;\n});\n\nconst debounce = toRef(props, 'debounce');\n\nconst searchOptionsRef = useWatchFetch(() => [data.search, data.open, props.sourceId] as const, async ([search, _open]) => {\n return props.optionsSearch(search);\n}, {\n filterWatchResult: ([_search, open]) => open,\n debounce,\n});\n\nconst modelOptionsRef = useWatchFetch(() => [props.modelValue, props.sourceId] as const, async ([v]) => {\n return props.modelSearch(v);\n}, {\n debounce,\n});\n\nconst allOptionsRef = computed(() => {\n const modelOptions = modelOptionsRef.value ?? [];\n const searchOptions = searchOptionsRef.value ?? [];\n\n const seenValues = new Set<string | undefined>();\n const result = [] as ListOptionBase<M>[];\n\n const addOptions = (options: Readonly<ListOptionBase<M>[]>) => {\n for (const option of options) {\n const canonicalValue = canonicalize(option.value);\n if (!seenValues.has(canonicalValue)) {\n seenValues.add(canonicalValue);\n result.push(option);\n }\n }\n };\n\n addOptions(modelOptions);\n addOptions(searchOptions);\n\n return result;\n});\n\nconst selectedOptionsRef = computed(() => {\n return selectedValuesRef.value.map((v) =>\n allOptionsRef.value.find((opt) => deepEqual(opt.value, v))).filter((v) => v !== undefined,\n );\n});\n\nconst filteredOptionsRef = computed(() => {\n const selectedValues = unref(selectedValuesRef);\n\n const options = searchOptionsRef.value ?? [];\n\n return [...options].map((opt) => ({\n ...opt,\n selected: deepIncludes(selectedValues, opt.value),\n }));\n});\n\nconst isOptionsLoading = computed(() => searchOptionsRef.loading || modelOptionsRef.loading);\n\nconst isDisabled = computed(() => {\n if (modelOptionsRef.value === undefined) {\n return true;\n }\n\n return props.disabled;\n});\n\nconst tabindex = computed(() => (isDisabled.value ? undefined : '0'));\n\nconst updateActiveOption = () => {\n data.activeOption = 0;\n};\n\nconst selectOption = (v: M) => {\n const values = unref(selectedValuesRef);\n emitModel(deepIncludes(values, v) ? values.filter((it) => !deepEqual(it, v)) : [...values, v]);\n if (props.resetSearchOnSelect) {\n data.search = '';\n }\n inputRef.value?.focus();\n};\n\nconst unselectOption = (d: M) => emitModel(unref(selectedValuesRef).filter((v) => !deepEqual(v, d)));\n\nconst setFocusOnInput = () => inputRef.value?.focus();\n\nconst toggleOpen = () => data.open = !data.open;\n\nconst onFocusOut = (event: FocusEvent) => {\n const relatedTarget = event.relatedTarget as Node | null;\n\n if (!rootRef.value?.contains(relatedTarget) && !overlay.value?.listRef?.contains(relatedTarget)) {\n data.open = false;\n }\n};\n\nconst handleKeydown = (e: { code: string; preventDefault(): void }) => {\n const { open, activeOption } = data;\n\n if (!open) {\n if (e.code === 'Enter') {\n data.open = true;\n }\n return;\n }\n\n if (e.code === 'Escape') {\n data.open = false;\n inputRef.value?.focus();\n }\n\n const filteredOptions = unref(filteredOptionsRef);\n\n const { length } = filteredOptions;\n\n if (!length) {\n return;\n }\n\n if (['ArrowDown', 'ArrowUp', 'Enter'].includes(e.code)) {\n e.preventDefault();\n }\n\n if (e.code === 'Enter') {\n selectOption(filteredOptions[activeOption].value);\n }\n\n const d = e.code === 'ArrowDown' ? 1 : e.code === 'ArrowUp' ? -1 : 0;\n\n data.activeOption = Math.abs(activeOption + d + length) % length;\n\n requestAnimationFrame(() => overlay.value?.scrollIntoActive());\n};\n\nuseLabelNotch(rootRef);\n\nwatch(\n () => props.modelValue,\n () => updateActiveOption(),\n { immediate: true },\n);\n\nconst computedError = computed(() => {\n if (isOptionsLoading.value) {\n return undefined;\n }\n\n if (searchOptionsRef.error) {\n return getErrorMessage(searchOptionsRef.error);\n }\n\n if (modelOptionsRef.error) {\n return getErrorMessage(modelOptionsRef.error);\n }\n\n if (props.error) {\n return getErrorMessage(props.error);\n }\n\n if (props.modelValue.length && selectedOptionsRef.value.length !== props.modelValue.length) {\n return 'The selected values are not one of the options';\n }\n\n return undefined;\n});\n</script>\n\n<template>\n <div class=\"pl-autocomplete-multi__envelope\" @click=\"setFocusOnInput\">\n <div\n ref=\"rootRef\"\n :tabindex=\"tabindex\"\n class=\"pl-autocomplete-multi\"\n :class=\"{ open: data.open, error: Boolean(computedError), disabled: isDisabled }\"\n @keydown=\"handleKeydown\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-autocomplete-multi__container\">\n <div class=\"pl-autocomplete-multi__field\">\n <input\n ref=\"inputRef\"\n v-model=\"data.search\"\n type=\"text\"\n tabindex=\"-1\"\n :disabled=\"isDisabled\"\n :placeholder=\"placeholderRef\"\n spellcheck=\"false\"\n autocomplete=\"chrome-off\"\n @focus=\"data.open = true\"\n />\n <div v-if=\"!data.open\" class=\"chips-container\">\n <PlChip v-for=\"(opt, i) in selectedOptionsRef\" :key=\"i\" closeable small @click.stop=\"data.open = true\" @close=\"unselectOption(opt.value)\">\n {{ opt.label || opt.value }}\n </PlChip>\n </div>\n\n <div class=\"pl-autocomplete-multi__controls\">\n <PlMaskIcon24 v-if=\"isOptionsLoading\" name=\"loading\" />\n <slot name=\"append\" />\n <div class=\"pl-autocomplete-multi__arrow-wrapper\" @click.stop=\"toggleOpen\">\n <div class=\"arrow-icon arrow-icon-default\" />\n </div>\n </div>\n </div>\n <label v-if=\"label\">\n <PlSvg v-if=\"required\" :uri=\"SvgRequired\" />\n <span>{{ label }}</span>\n <PlTooltip v-if=\"slots.tooltip\" class=\"info\" position=\"top\">\n <template #tooltip>\n <slot name=\"tooltip\" />\n </template>\n </PlTooltip>\n </label>\n <DropdownOverlay\n v-if=\"data.open\"\n ref=\"overlay\"\n :root=\"rootRef\"\n class=\"pl-autocomplete-multi__options\"\n :gap=\"5\"\n tabindex=\"-1\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-autocomplete-multi__open-chips-container\">\n <PlChip\n v-for=\"(opt, i) in selectedOptionsRef\"\n :key=\"i\"\n closeable\n small\n @close=\"unselectOption(opt.value)\"\n >\n {{ opt.label || opt.value }}\n </PlChip>\n </div>\n <DropdownListItem\n v-for=\"(item, index) in filteredOptionsRef\"\n :key=\"index\"\n :option=\"item\"\n :text-item=\"'text'\"\n :is-selected=\"item.selected\"\n :is-hovered=\"data.activeOption == index\"\n size=\"medium\"\n use-checkbox\n @click.stop=\"selectOption(item.value)\"\n />\n <div v-if=\"!filteredOptionsRef.length && !isOptionsLoading\" class=\"nothing-found\">{{ emptyOptionsText }}</div>\n </DropdownOverlay>\n <DoubleContour class=\"pl-autocomplete-multi__contour\" />\n </div>\n </div>\n <div v-if=\"computedError\" class=\"pl-autocomplete-multi__error\">{{ computedError }}</div>\n <div v-else-if=\"helper\" class=\"pl-autocomplete-multi__helper\">{{ helper }}</div>\n </div>\n</template>\n"],"names":["__default__","emit","__emit","emitModel","v","slots","useSlots","props","__props","rootRef","ref","inputRef","overlay","useTemplateRef","data","reactive","watch","selectedValuesRef","computed","placeholderRef","debounce","toRef","searchOptionsRef","useWatchFetch","search","_open","_search","open","modelOptionsRef","allOptionsRef","modelOptions","searchOptions","seenValues","result","addOptions","options","option","canonicalValue","canonicalize","selectedOptionsRef","opt","deepEqual","filteredOptionsRef","selectedValues","unref","deepIncludes","isOptionsLoading","isDisabled","tabindex","updateActiveOption","selectOption","values","it","_a","unselectOption","d","setFocusOnInput","toggleOpen","onFocusOut","event","relatedTarget","_c","_b","handleKeydown","activeOption","filteredOptions","length","useLabelNotch","computedError","getErrorMessage"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PlAutocompleteMulti.vue.js","sources":["../../../src/components/PlAutocompleteMulti/PlAutocompleteMulti.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * A multi-select autocomplete component that allows users to search and select multiple values from a list of options.\n * Supports async data fetching, keyboard navigation, and displays selected items as removable chips.\n *\n * @example\n * Basic usage:\n * <PlAutocompleteMulti\n * v-model=\"selectedUsers\"\n * :options-search=\"searchUsers\"\n * :model-search=\"getUsersByIds\"\n * label=\"Select Users\"\n * placeholder=\"Search for users...\"\n * required\n * :debounce=\"300\"\n * helper=\"Choose one or more users from the list\"\n * />\n *\n * With async functions:\n * const selectedUsers = ref([])\n *\n * const searchUsers = async (searchTerm) => {\n * const response = await fetch('/api/users/search?q=' + searchTerm)\n * const users = await response.json()\n * return users.map(user => ({ value: user.id, label: user.name }))\n * }\n *\n * const getUsersByIds = async (userIds) => {\n * if (!userIds.length) return []\n * const response = await fetch('/api/users?ids=' + userIds.join(','))\n * const users = await response.json()\n * return users.map(user => ({ value: user.id, label: user.name }))\n * }\n */\nexport default {\n name: 'PlAutocompleteMulti',\n};\n</script>\n\n<script lang=\"ts\" setup generic=\"M = unknown\">\nimport './pl-autocomplete-multi.scss';\n\nimport type { ListOptionBase } from '@platforma-sdk/model';\nimport canonicalize from 'canonicalize';\nimport { computed, reactive, ref, toRef, unref, useSlots, useTemplateRef, watch } from 'vue';\nimport { useWatchFetch } from '../../composition/useWatchFetch.ts';\nimport { getErrorMessage } from '../../helpers/error.ts';\nimport { deepEqual, deepIncludes } from '../../helpers/objects';\nimport DoubleContour from '../../utils/DoubleContour.vue';\nimport DropdownOverlay from '../../utils/DropdownOverlay/DropdownOverlay.vue';\nimport { useLabelNotch } from '../../utils/useLabelNotch';\nimport DropdownListItem from '../DropdownListItem.vue';\nimport { PlChip } from '../PlChip';\nimport { PlMaskIcon24 } from '../PlMaskIcon24';\nimport { PlTooltip } from '../PlTooltip';\n\nimport SvgRequired from '../../assets/images/required.svg?raw';\nimport { PlSvg } from '../PlSvg';\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', v: M[]): void;\n}>();\n\nconst emitModel = (v: M[]) => emit('update:modelValue', v);\n\nconst slots = useSlots();\n\nconst props = withDefaults(\n defineProps<{\n /**\n * The current selected values.\n */\n modelValue: M[];\n /**\n * Lambda for requesting of available options for the dropdown by search string.\n */\n optionsSearch: (s: string) => Promise<Readonly<ListOptionBase<M>[]>>;\n /**\n * Lambda for requesting options that correspond to the current model values.\n */\n modelSearch: (values: M[]) => Promise<Readonly<ListOptionBase<M>[]>>;\n /**\n * Unique identifier for the source of the options, changing it will invalidate the options cache.\n */\n sourceId?: string;\n /**\n * The label text for the dropdown field (optional)\n */\n label?: string;\n /**\n * A helper text displayed below the dropdown when there are no errors (optional).\n */\n helper?: string;\n /**\n * Error message displayed below the dropdown (optional)\n */\n error?: unknown;\n /**\n * Placeholder text shown when no value is selected.\n */\n placeholder?: string;\n /**\n * If `true`, the dropdown component is marked as required.\n */\n required?: boolean;\n /**\n * If `true`, the dropdown component is disabled and cannot be interacted with.\n */\n disabled?: boolean;\n /**\n * Debounce time in ms for the options search.\n */\n debounce?: number;\n /**\n * If `true`, the search input is reset and focus is set on it when the new option is selected.\n */\n resetSearchOnSelect?: boolean;\n /**\n * The text to display when no options are found.\n */\n emptyOptionsText?: string;\n /**\n * Makes some of corners not rounded\n * */\n groupPosition?: 'top' | 'bottom' | 'left' | 'right' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'middle';\n }>(),\n {\n modelValue: () => [],\n label: undefined,\n helper: undefined,\n error: undefined,\n placeholder: '...',\n required: false,\n disabled: false,\n debounce: 300,\n emptyOptionsText: 'Nothing found',\n sourceId: undefined,\n groupPosition: undefined,\n },\n);\n\nconst rootRef = ref<HTMLElement | undefined>();\nconst inputRef = ref<HTMLInputElement | undefined>();\n\nconst overlay = useTemplateRef('overlay');\n\nconst data = reactive({\n search: '',\n activeOption: -1,\n open: false,\n optionsHeight: 0,\n});\n\nwatch(() => data.open, (v) => {\n if (!v) {\n data.search = '';\n }\n}, { flush: 'sync' });\n\nconst selectedValuesRef = computed(() => (Array.isArray(props.modelValue) ? props.modelValue : []));\n\nconst placeholderRef = computed(() => {\n if (data.open && props.modelValue.length > 0) {\n return props.placeholder;\n }\n\n return props.modelValue.length > 0 ? '' : props.placeholder;\n});\n\nconst debounce = toRef(props, 'debounce');\n\nconst searchOptionsRef = useWatchFetch(() => [data.search, data.open, props.sourceId] as const, async ([search, _open]) => {\n return props.optionsSearch(search);\n}, {\n filterWatchResult: ([_search, open]) => open,\n debounce,\n});\n\nconst modelOptionsRef = useWatchFetch(() => [props.modelValue, props.sourceId] as const, async ([v]) => {\n return props.modelSearch(v);\n}, {\n debounce,\n});\n\nconst allOptionsRef = computed(() => {\n const modelOptions = modelOptionsRef.value ?? [];\n const searchOptions = searchOptionsRef.value ?? [];\n\n const seenValues = new Set<string | undefined>();\n const result = [] as ListOptionBase<M>[];\n\n const addOptions = (options: Readonly<ListOptionBase<M>[]>) => {\n for (const option of options) {\n const canonicalValue = canonicalize(option.value);\n if (!seenValues.has(canonicalValue)) {\n seenValues.add(canonicalValue);\n result.push(option);\n }\n }\n };\n\n addOptions(modelOptions);\n addOptions(searchOptions);\n\n return result;\n});\n\nconst selectedOptionsRef = computed(() => {\n return selectedValuesRef.value.map((v) =>\n allOptionsRef.value.find((opt) => deepEqual(opt.value, v))).filter((v) => v !== undefined,\n );\n});\n\nconst filteredOptionsRef = computed(() => {\n const selectedValues = unref(selectedValuesRef);\n\n const options = searchOptionsRef.value ?? [];\n\n return [...options].map((opt) => ({\n ...opt,\n selected: deepIncludes(selectedValues, opt.value),\n }));\n});\n\nconst isOptionsLoading = computed(() => searchOptionsRef.loading || modelOptionsRef.loading);\n\nconst isDisabled = computed(() => {\n if (modelOptionsRef.value === undefined) {\n return true;\n }\n\n return props.disabled;\n});\n\nconst tabindex = computed(() => (isDisabled.value ? undefined : '0'));\n\nconst updateActiveOption = () => {\n data.activeOption = 0;\n};\n\nconst selectOption = (v: M) => {\n const values = unref(selectedValuesRef);\n emitModel(deepIncludes(values, v) ? values.filter((it) => !deepEqual(it, v)) : [...values, v]);\n if (props.resetSearchOnSelect) {\n data.search = '';\n }\n inputRef.value?.focus();\n};\n\nconst unselectOption = (d: M) => emitModel(unref(selectedValuesRef).filter((v) => !deepEqual(v, d)));\n\nconst setFocusOnInput = () => inputRef.value?.focus();\n\nconst toggleOpen = () => data.open = !data.open;\n\nconst onFocusOut = (event: FocusEvent) => {\n const relatedTarget = event.relatedTarget as Node | null;\n\n if (!rootRef.value?.contains(relatedTarget) && !overlay.value?.listRef?.contains(relatedTarget)) {\n data.open = false;\n }\n};\n\nconst handleKeydown = (e: { code: string; preventDefault(): void }) => {\n const { open, activeOption } = data;\n\n if (!open) {\n if (e.code === 'Enter') {\n data.open = true;\n }\n return;\n }\n\n if (e.code === 'Escape') {\n data.open = false;\n inputRef.value?.focus();\n }\n\n const filteredOptions = unref(filteredOptionsRef);\n\n const { length } = filteredOptions;\n\n if (!length) {\n return;\n }\n\n if (['ArrowDown', 'ArrowUp', 'Enter'].includes(e.code)) {\n e.preventDefault();\n }\n\n if (e.code === 'Enter') {\n selectOption(filteredOptions[activeOption].value);\n }\n\n const d = e.code === 'ArrowDown' ? 1 : e.code === 'ArrowUp' ? -1 : 0;\n\n data.activeOption = Math.abs(activeOption + d + length) % length;\n\n requestAnimationFrame(() => overlay.value?.scrollIntoActive());\n};\n\nuseLabelNotch(rootRef);\n\nwatch(\n () => props.modelValue,\n () => updateActiveOption(),\n { immediate: true },\n);\n\nconst computedError = computed(() => {\n if (isOptionsLoading.value) {\n return undefined;\n }\n\n if (searchOptionsRef.error) {\n return getErrorMessage(searchOptionsRef.error);\n }\n\n if (modelOptionsRef.error) {\n return getErrorMessage(modelOptionsRef.error);\n }\n\n if (props.error) {\n return getErrorMessage(props.error);\n }\n\n if (props.modelValue.length && selectedOptionsRef.value.length !== props.modelValue.length) {\n return 'The selected values are not one of the options';\n }\n\n return undefined;\n});\n</script>\n\n<template>\n <div class=\"pl-autocomplete-multi__envelope\" @click=\"setFocusOnInput\">\n <div\n ref=\"rootRef\"\n :tabindex=\"tabindex\"\n class=\"pl-autocomplete-multi\"\n :class=\"{ open: data.open, error: Boolean(computedError), disabled: isDisabled }\"\n @keydown=\"handleKeydown\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-autocomplete-multi__container\">\n <div class=\"pl-autocomplete-multi__field\">\n <input\n ref=\"inputRef\"\n v-model=\"data.search\"\n type=\"text\"\n tabindex=\"-1\"\n :disabled=\"isDisabled\"\n :placeholder=\"placeholderRef\"\n spellcheck=\"false\"\n autocomplete=\"chrome-off\"\n @focus=\"data.open = true\"\n />\n <div v-if=\"!data.open\" class=\"chips-container\">\n <PlChip v-for=\"(opt, i) in selectedOptionsRef\" :key=\"i\" closeable small @click.stop=\"data.open = true\" @close=\"unselectOption(opt.value)\">\n {{ opt.label || opt.value }}\n </PlChip>\n </div>\n\n <div class=\"pl-autocomplete-multi__controls\">\n <PlMaskIcon24 v-if=\"isOptionsLoading\" name=\"loading\" />\n <slot name=\"append\" />\n <div class=\"pl-autocomplete-multi__arrow-wrapper\" @click.stop=\"toggleOpen\">\n <div class=\"arrow-icon arrow-icon-default\" />\n </div>\n </div>\n </div>\n <label v-if=\"label\">\n <PlSvg v-if=\"required\" :uri=\"SvgRequired\" />\n <span>{{ label }}</span>\n <PlTooltip v-if=\"slots.tooltip\" class=\"info\" position=\"top\">\n <template #tooltip>\n <slot name=\"tooltip\" />\n </template>\n </PlTooltip>\n </label>\n <DropdownOverlay\n v-if=\"data.open\"\n ref=\"overlay\"\n :root=\"rootRef\"\n class=\"pl-autocomplete-multi__options\"\n :gap=\"5\"\n tabindex=\"-1\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-autocomplete-multi__open-chips-container\">\n <PlChip\n v-for=\"(opt, i) in selectedOptionsRef\"\n :key=\"i\"\n closeable\n small\n @close=\"unselectOption(opt.value)\"\n >\n {{ opt.label || opt.value }}\n </PlChip>\n </div>\n <DropdownListItem\n v-for=\"(item, index) in filteredOptionsRef\"\n :key=\"index\"\n :option=\"item\"\n :text-item=\"'text'\"\n :is-selected=\"item.selected\"\n :is-hovered=\"data.activeOption == index\"\n size=\"medium\"\n use-checkbox\n @click.stop=\"selectOption(item.value)\"\n />\n <div v-if=\"!filteredOptionsRef.length && !isOptionsLoading\" class=\"nothing-found\">{{ emptyOptionsText }}</div>\n </DropdownOverlay>\n <DoubleContour class=\"pl-autocomplete-multi__contour\" :group-position=\"groupPosition\" />\n </div>\n </div>\n <div v-if=\"computedError\" class=\"pl-autocomplete-multi__error\">{{ computedError }}</div>\n <div v-else-if=\"helper\" class=\"pl-autocomplete-multi__helper\">{{ helper }}</div>\n </div>\n</template>\n"],"names":["__default__","emit","__emit","emitModel","v","slots","useSlots","props","__props","rootRef","ref","inputRef","overlay","useTemplateRef","data","reactive","watch","selectedValuesRef","computed","placeholderRef","debounce","toRef","searchOptionsRef","useWatchFetch","search","_open","_search","open","modelOptionsRef","allOptionsRef","modelOptions","searchOptions","seenValues","result","addOptions","options","option","canonicalValue","canonicalize","selectedOptionsRef","opt","deepEqual","filteredOptionsRef","selectedValues","unref","deepIncludes","isOptionsLoading","isDisabled","tabindex","updateActiveOption","selectOption","values","it","_a","unselectOption","d","setFocusOnInput","toggleOpen","onFocusOut","event","relatedTarget","_c","_b","handleKeydown","activeOption","filteredOptions","length","useLabelNotch","computedError","getErrorMessage"],"mappings":"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"}
|
|
@@ -30,6 +30,10 @@ declare const _default: <M = unknown>(__VLS_props: NonNullable<Awaited<typeof __
|
|
|
30
30
|
* Error message displayed below the dropdown (optional)
|
|
31
31
|
*/
|
|
32
32
|
error?: unknown;
|
|
33
|
+
/**
|
|
34
|
+
* Shows red border even without an error message
|
|
35
|
+
*/
|
|
36
|
+
errorStatus?: boolean;
|
|
33
37
|
/**
|
|
34
38
|
* Placeholder text shown when no value is selected.
|
|
35
39
|
*/
|
|
@@ -58,6 +62,10 @@ declare const _default: <M = unknown>(__VLS_props: NonNullable<Awaited<typeof __
|
|
|
58
62
|
* Option list item size
|
|
59
63
|
*/
|
|
60
64
|
optionSize?: "small" | "medium";
|
|
65
|
+
/**
|
|
66
|
+
* Makes some of corners not rounded
|
|
67
|
+
* */
|
|
68
|
+
groupPosition?: "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "middle";
|
|
61
69
|
} & Partial<{}>> & import('vue').PublicProps;
|
|
62
70
|
expose(exposed: import('vue').ShallowUnwrapRef<{}>): void;
|
|
63
71
|
attrs: any;
|