@milaboratories/uikit 2.16.3 → 2.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/.turbo/turbo-build.log +30 -22
  2. package/.turbo/turbo-formatter$colon$check.log +1 -1
  3. package/.turbo/turbo-linter$colon$check.log +1 -1
  4. package/CHANGELOG.md +26 -0
  5. package/dist/components/PlAlert/PlAlert.js.map +1 -1
  6. package/dist/components/PlAlert/PlAlert.vue.d.ts +4 -1
  7. package/dist/components/PlAlert/PlAlert.vue.d.ts.map +1 -1
  8. package/dist/components/PlAlert/PlAlert.vue2.js +19 -18
  9. package/dist/components/PlAlert/PlAlert.vue2.js.map +1 -1
  10. package/dist/components/PlDropdown/PlDropdown.js +5 -4
  11. package/dist/components/PlDropdown/PlDropdown.js.map +1 -1
  12. package/dist/components/PlDropdown/PlDropdown.style.css +1 -0
  13. package/dist/components/PlDropdown/PlDropdown.style.js +5 -0
  14. package/dist/components/PlDropdown/PlDropdown.style.js.map +1 -0
  15. package/dist/components/PlDropdown/PlDropdown.vue.d.ts +10 -2
  16. package/dist/components/PlDropdown/PlDropdown.vue.d.ts.map +1 -1
  17. package/dist/components/PlDropdown/PlDropdown.vue2.js +136 -110
  18. package/dist/components/PlDropdown/PlDropdown.vue2.js.map +1 -1
  19. package/dist/components/PlDropdownMulti/PlDropdownMulti.js.map +1 -1
  20. package/dist/components/PlDropdownMulti/PlDropdownMulti.vue.d.ts +10 -2
  21. package/dist/components/PlDropdownMulti/PlDropdownMulti.vue.d.ts.map +1 -1
  22. package/dist/components/PlDropdownMulti/PlDropdownMulti.vue2.js +123 -84
  23. package/dist/components/PlDropdownMulti/PlDropdownMulti.vue2.js.map +1 -1
  24. package/dist/components/PlDropdownMultiRef/PlDropdownMultiRef.js.map +1 -1
  25. package/dist/components/PlDropdownMultiRef/PlDropdownMultiRef.vue.d.ts +12 -5
  26. package/dist/components/PlDropdownMultiRef/PlDropdownMultiRef.vue.d.ts.map +1 -1
  27. package/dist/components/PlDropdownMultiRef/PlDropdownMultiRef.vue2.js +8 -1
  28. package/dist/components/PlDropdownMultiRef/PlDropdownMultiRef.vue2.js.map +1 -1
  29. package/dist/components/PlDropdownRef/PlDropdownRef.js.map +1 -1
  30. package/dist/components/PlDropdownRef/PlDropdownRef.vue.d.ts +8 -2
  31. package/dist/components/PlDropdownRef/PlDropdownRef.vue.d.ts.map +1 -1
  32. package/dist/components/PlDropdownRef/PlDropdownRef.vue2.js +8 -1
  33. package/dist/components/PlDropdownRef/PlDropdownRef.vue2.js.map +1 -1
  34. package/dist/components/PlTooltip/PlTooltip.js.map +1 -1
  35. package/dist/components/PlTooltip/PlTooltip.style.css +1 -1
  36. package/dist/components/PlTooltip/PlTooltip.style.js +1 -1
  37. package/dist/components/PlTooltip/PlTooltip.style.js.map +1 -1
  38. package/dist/components/PlTooltip/PlTooltip.vue.d.ts.map +1 -1
  39. package/dist/components/PlTooltip/PlTooltip.vue2.js +1 -1
  40. package/dist/components/PlTooltip/PlTooltip.vue2.js.map +1 -1
  41. package/dist/components/PlValueLabel/PlValueLabel.js +7 -0
  42. package/dist/components/PlValueLabel/PlValueLabel.js.map +1 -0
  43. package/dist/components/PlValueLabel/PlValueLabel.style.css +1 -0
  44. package/dist/components/PlValueLabel/PlValueLabel.style.js +5 -0
  45. package/dist/components/PlValueLabel/PlValueLabel.style.js.map +1 -0
  46. package/dist/components/PlValueLabel/PlValueLabel.vue.d.ts +45 -0
  47. package/dist/components/PlValueLabel/PlValueLabel.vue.d.ts.map +1 -0
  48. package/dist/components/PlValueLabel/PlValueLabel.vue2.js +37 -0
  49. package/dist/components/PlValueLabel/PlValueLabel.vue2.js.map +1 -0
  50. package/dist/components/PlValueLabel/__tests__/PlValueLabel.spec.d.ts +2 -0
  51. package/dist/components/PlValueLabel/__tests__/PlValueLabel.spec.d.ts.map +1 -0
  52. package/dist/components/PlValueLabel/index.d.ts +2 -0
  53. package/dist/components/PlValueLabel/index.d.ts.map +1 -0
  54. package/dist/components/PlValueLabel/index.js +1 -0
  55. package/dist/helpers/columnValue.d.ts +25 -0
  56. package/dist/helpers/columnValue.d.ts.map +1 -0
  57. package/dist/helpers/columnValue.js +17 -0
  58. package/dist/helpers/columnValue.js.map +1 -0
  59. package/dist/index.d.ts +2 -0
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +32 -30
  62. package/dist/index.js.map +1 -1
  63. package/package.json +2 -2
  64. package/src/components/PlAlert/PlAlert.vue +13 -2
  65. package/src/components/PlDropdown/PlDropdown.vue +49 -8
  66. package/src/components/PlDropdown/__tests__/PlDropdown.spec.ts +95 -0
  67. package/src/components/PlDropdownMulti/PlDropdownMulti.vue +50 -9
  68. package/src/components/PlDropdownMulti/__tests__/PlDropdownMulti.spec.ts +47 -0
  69. package/src/components/PlDropdownMultiRef/PlDropdownMultiRef.vue +10 -3
  70. package/src/components/PlDropdownMultiRef/__tests__/PlDropdownMultiRef.spec.ts +2 -2
  71. package/src/components/PlDropdownRef/PlDropdownRef.vue +10 -3
  72. package/src/components/PlDropdownRef/__tests__/PlDropdownRef.spec.ts +2 -2
  73. package/src/components/PlTooltip/PlTooltip.vue +1 -0
  74. package/src/components/PlValueLabel/PlValueLabel.vue +80 -0
  75. package/src/components/PlValueLabel/__tests__/PlValueLabel.spec.ts +64 -0
  76. package/src/components/PlValueLabel/index.ts +1 -0
  77. package/src/helpers/columnValue.ts +43 -0
  78. package/src/index.ts +2 -0
@@ -1 +1 @@
1
- {"version":3,"file":"PlDropdownMulti.js","names":["_sfc_main","PlDropdownMulti_vue_vue_type_script_setup_true_lang_default","PlDropdownMulti_default"],"sources":["../../../src/components/PlDropdownMulti/PlDropdownMulti.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * A component for selecting multiple values from a list of options\n */\nexport default {\n name: \"PlDropdownMulti\",\n};\n</script>\n\n<script lang=\"ts\" setup generic=\"M = unknown\">\nimport {\n computed,\n reactive,\n ref,\n unref,\n useSlots,\n useTemplateRef,\n watch,\n watchPostEffect,\n} from \"vue\";\nimport SvgRequired from \"../../assets/images/required.svg?raw\";\nimport { getErrorMessage } from \"../../helpers/error.ts\";\nimport { deepEqual, deepIncludes } from \"../../helpers/objects\";\nimport { normalizeListOptions } from \"../../helpers/utils\";\nimport type { ListOption } from \"../../types\";\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 { PlIcon24 } from \"../PlIcon24\";\nimport { PlSvg } from \"../PlSvg\";\nimport { PlTooltip } from \"../PlTooltip\";\nimport \"./pl-dropdown-multi.scss\";\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 * The label text for the dropdown field (optional)\n */\n label?: string;\n /**\n * List of available options for the dropdown\n */\n options?: Readonly<ListOption<M>[]>;\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 * Text shown in a chip when a `modelValue` entry is missing from `options` —\n * e.g. its upstream source was deleted. Rendered italic in error color.\n */\n missingValueLabel?: 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 * Makes some of corners not rounded\n * */\n groupPosition?:\n | \"top\"\n | \"bottom\"\n | \"left\"\n | \"right\"\n | \"top-left\"\n | \"top-right\"\n | \"bottom-left\"\n | \"bottom-right\"\n | \"middle\";\n }>(),\n {\n modelValue: () => [],\n label: undefined,\n helper: undefined,\n error: undefined,\n placeholder: \"...\",\n missingValueLabel: \"Value not available\",\n required: false,\n disabled: false,\n options: undefined,\n groupPosition: undefined,\n },\n);\n\nconst rootRef = ref<HTMLElement | undefined>();\nconst input = 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\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 normalizedOptionsRef = computed(() => normalizeListOptions(props.options ?? []));\n\nconst selectedOptionsRef = computed(() => {\n // While options load (`options === undefined`), hide chips for unresolved values\n // to avoid a \"missing\" flash that resolves once options arrive.\n const optionsLoaded = props.options !== undefined;\n return selectedValuesRef.value\n .map((v) => {\n const opt = normalizedOptionsRef.value.find((o) => deepEqual(o.value, v));\n if (opt) {\n // Found: render the option's own (normalized) label verbatim — matches\n // PlDropdown. `opt.label` is always a string (possibly \"\"), never an object,\n // so there is no raw-value leak to guard against.\n return { ...opt, isMissing: false };\n }\n if (!optionsLoaded) {\n return undefined;\n }\n // Honor empty `missingValueLabel` verbatim — caller's explicit \"render nothing\".\n return {\n value: v,\n label: props.missingValueLabel,\n isMissing: true,\n };\n })\n .filter((v): v is NonNullable<typeof v> => v !== undefined);\n});\n\nconst filteredOptionsRef = computed(() => {\n const selectedValues = unref(selectedValuesRef);\n\n const options = unref(normalizedOptionsRef);\n\n return (\n data.search\n ? options.filter((opt) => {\n const search = data.search.toLowerCase();\n\n if (opt.label.toLowerCase().includes(search)) {\n return true;\n }\n\n if (typeof opt.value === \"string\") {\n return opt.value.toLowerCase().includes(search);\n }\n\n return opt.value === data.search;\n })\n : [...options]\n ).map((opt) => ({\n ...opt,\n selected: deepIncludes(selectedValues, opt.value),\n }));\n});\n\nconst isLoadingOptions = computed(() => {\n return props.options === undefined;\n});\n\nconst showLoadingSpinner = computed(() => {\n return !props.disabled && isLoadingOptions.value;\n});\n\nconst isDisabled = computed(() => {\n if (isLoadingOptions.value) {\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 data.search = \"\";\n rootRef?.value?.focus();\n};\n\nconst unselectOption = (d: M) =>\n emitModel(unref(selectedValuesRef).filter((v) => !deepEqual(v, d)));\n\nconst setFocusOnInput = () => input.value?.focus();\n\nconst toggleModel = () => {\n data.open = !data.open;\n if (!data.open) {\n data.search = \"\";\n }\n};\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.search = \"\";\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 rootRef.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\nwatchPostEffect(() => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n data.search;\n\n if (data.open) {\n overlay.value?.scrollIntoActive();\n }\n});\n</script>\n\n<template>\n <div class=\"pl-dropdown-multi__envelope\" @click=\"setFocusOnInput\" data-testid=\"pl-dropdown-multi\">\n <div\n ref=\"rootRef\"\n :tabindex=\"tabindex\"\n class=\"pl-dropdown-multi\"\n data-testid=\"pl-dropdown-multi-control\"\n :class=\"{ open: data.open, error, disabled: isDisabled }\"\n @keydown=\"handleKeydown\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-dropdown-multi__container\">\n <div class=\"pl-dropdown-multi__field\">\n <input\n ref=\"input\"\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 data-testid=\"pl-dropdown-multi-input\"\n @focus=\"data.open = true\"\n />\n <div v-if=\"!data.open\" class=\"chips-container\" data-testid=\"pl-dropdown-multi-chips\">\n <PlChip\n v-for=\"(opt, i) in selectedOptionsRef\"\n :key=\"i\"\n :class=\"{ 'pl-dropdown-multi__chip--missing': opt.isMissing }\"\n closeable\n data-testid=\"pl-dropdown-multi-chip\"\n small\n @click.stop=\"data.open = true\"\n @close=\"unselectOption(opt.value)\"\n >\n {{ opt.label }}\n </PlChip>\n </div>\n\n <div class=\"pl-dropdown-multi__controls\">\n <PlIcon24\n v-if=\"showLoadingSpinner\"\n name=\"loading\"\n data-testid=\"pl-dropdown-multi-loading\"\n />\n <slot name=\"append\" />\n <div\n class=\"pl-dropdown-multi__arrow-wrapper\"\n data-testid=\"pl-dropdown-multi-arrow\"\n @click.stop=\"toggleModel\"\n >\n <div class=\"arrow-icon arrow-icon-default\" />\n </div>\n </div>\n </div>\n <label v-if=\"label\" data-testid=\"pl-dropdown-multi-label\">\n <PlSvg v-if=\"required\" :uri=\"SvgRequired\" data-testid=\"pl-dropdown-multi-required\" />\n <span>{{ label }}</span>\n <PlTooltip\n v-if=\"slots.tooltip\"\n class=\"info\"\n position=\"top\"\n data-testid=\"pl-dropdown-multi-tooltip\"\n >\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-dropdown-multi__options\"\n data-testid=\"pl-dropdown-multi-options\"\n :gap=\"5\"\n tabindex=\"-1\"\n @focusout=\"onFocusOut\"\n >\n <div\n class=\"pl-dropdown-multi__open-chips-container\"\n data-testid=\"pl-dropdown-multi-chips\"\n >\n <PlChip\n v-for=\"(opt, i) in selectedOptionsRef\"\n :key=\"i\"\n :class=\"{ 'pl-dropdown-multi__chip--missing': opt.isMissing }\"\n closeable\n data-testid=\"pl-dropdown-multi-chip\"\n small\n @close=\"unselectOption(opt.value)\"\n >\n {{ opt.label }}\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 data-testid=\"pl-dropdown-multi-option\"\n @click.stop=\"selectOption(item.value)\"\n />\n <div\n v-if=\"!filteredOptionsRef.length\"\n class=\"nothing-found\"\n data-testid=\"pl-dropdown-multi-options-empty\"\n >\n Nothing found\n </div>\n </DropdownOverlay>\n <DoubleContour class=\"pl-dropdown-multi__contour\" :group-position=\"groupPosition\" />\n </div>\n </div>\n <div v-if=\"error\" class=\"pl-dropdown-multi__error\" data-testid=\"pl-dropdown-multi-error\">\n {{ getErrorMessage(error) }}\n </div>\n <div\n v-else-if=\"helper\"\n class=\"pl-dropdown-multi__helper\"\n data-testid=\"pl-dropdown-multi-helper\"\n >\n {{ helper }}\n </div>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"PlDropdownMulti.js","names":["_sfc_main","PlDropdownMulti_vue_vue_type_script_setup_true_lang_default","PlDropdownMulti_default"],"sources":["../../../src/components/PlDropdownMulti/PlDropdownMulti.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * A component for selecting multiple values from a list of options\n */\nexport default {\n name: \"PlDropdownMulti\",\n};\n</script>\n\n<script lang=\"ts\" setup generic=\"M = unknown\">\nimport {\n computed,\n reactive,\n ref,\n unref,\n useSlots,\n useTemplateRef,\n watch,\n watchPostEffect,\n} from \"vue\";\nimport SvgRequired from \"../../assets/images/required.svg?raw\";\nimport { missingValueText, missingValueTooltip, pickedValueText } from \"../../helpers/columnValue\";\nimport type { MissingValueLabel, MissingValueTooltip } from \"../../helpers/columnValue\";\nimport { getErrorMessage } from \"../../helpers/error.ts\";\nimport { deepEqual, deepIncludes } from \"../../helpers/objects\";\nimport { normalizeListOptions } from \"../../helpers/utils\";\nimport type { ListOption } from \"../../types\";\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 { PlIcon24 } from \"../PlIcon24\";\nimport { PlSvg } from \"../PlSvg\";\nimport { PlTooltip } from \"../PlTooltip\";\nimport \"./pl-dropdown-multi.scss\";\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 * The label text for the dropdown field (optional)\n */\n label?: string;\n /**\n * List of available options for the dropdown\n */\n options?: Readonly<ListOption<M>[]>;\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 * Text shown in a chip when a `modelValue` entry is missing from `options` —\n * e.g. its upstream source was deleted. Rendered italic in error color. One text for every\n * such value, or a function giving it per value. By default, the value a column value id\n * picks, marked as not available, or \"Value not available\".\n */\n missingValueLabel?: MissingValueLabel;\n /**\n * Explains a selected value missing from the options in a tooltip over it: one text for every\n * such value, or a function giving the content per value.\n */\n missingValueTooltip?: MissingValueTooltip;\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 * Makes some of corners not rounded\n * */\n groupPosition?:\n | \"top\"\n | \"bottom\"\n | \"left\"\n | \"right\"\n | \"top-left\"\n | \"top-right\"\n | \"bottom-left\"\n | \"bottom-right\"\n | \"middle\";\n }>(),\n {\n modelValue: () => [],\n label: undefined,\n helper: undefined,\n error: undefined,\n placeholder: \"...\",\n missingValueLabel: undefined,\n missingValueTooltip: undefined,\n required: false,\n disabled: false,\n options: undefined,\n groupPosition: undefined,\n },\n);\n\nconst rootRef = ref<HTMLElement | undefined>();\nconst input = 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\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 normalizedOptionsRef = computed(() => normalizeListOptions(props.options ?? []));\n\nconst selectedOptionsRef = computed(() => {\n // While options load (`options === undefined`), hide chips for unresolved values\n // to avoid a \"missing\" flash that resolves once options arrive. A picked column value\n // is shown by its own label meanwhile.\n const optionsLoaded = props.options !== undefined;\n return selectedValuesRef.value\n .map((v) => {\n const opt = normalizedOptionsRef.value.find((o) => deepEqual(o.value, v));\n if (opt) {\n // Found: render the option's own (normalized) label verbatim — matches\n // PlDropdown. `opt.label` is always a string (possibly \"\"), never an object,\n // so there is no raw-value leak to guard against.\n return { ...opt, isMissing: false, hint: undefined };\n }\n if (!optionsLoaded) {\n const label = pickedValueText(v);\n return label === undefined\n ? undefined\n : { value: v, label, isMissing: false, hint: undefined };\n }\n // Honor empty `missingValueLabel` verbatim — caller's explicit \"render nothing\".\n return {\n value: v,\n label: missingValueText(v, props.missingValueLabel),\n isMissing: true,\n hint: missingValueTooltip(v, props.missingValueTooltip),\n };\n })\n .filter((v): v is NonNullable<typeof v> => v !== undefined);\n});\n\nconst filteredOptionsRef = computed(() => {\n const selectedValues = unref(selectedValuesRef);\n\n const options = unref(normalizedOptionsRef);\n\n return (\n data.search\n ? options.filter((opt) => {\n const search = data.search.toLowerCase();\n\n if (opt.label.toLowerCase().includes(search)) {\n return true;\n }\n\n if (typeof opt.value === \"string\") {\n return opt.value.toLowerCase().includes(search);\n }\n\n return opt.value === data.search;\n })\n : [...options]\n ).map((opt) => ({\n ...opt,\n selected: deepIncludes(selectedValues, opt.value),\n }));\n});\n\nconst isLoadingOptions = computed(() => {\n return props.options === undefined;\n});\n\nconst showLoadingSpinner = computed(() => {\n return !props.disabled && isLoadingOptions.value;\n});\n\nconst isDisabled = computed(() => {\n if (isLoadingOptions.value) {\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 data.search = \"\";\n rootRef?.value?.focus();\n};\n\nconst unselectOption = (d: M) =>\n emitModel(unref(selectedValuesRef).filter((v) => !deepEqual(v, d)));\n\nconst setFocusOnInput = () => input.value?.focus();\n\nconst toggleModel = () => {\n data.open = !data.open;\n if (!data.open) {\n data.search = \"\";\n }\n};\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.search = \"\";\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 rootRef.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\nwatchPostEffect(() => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n data.search;\n\n if (data.open) {\n overlay.value?.scrollIntoActive();\n }\n});\n</script>\n\n<template>\n <div class=\"pl-dropdown-multi__envelope\" @click=\"setFocusOnInput\" data-testid=\"pl-dropdown-multi\">\n <div\n ref=\"rootRef\"\n :tabindex=\"tabindex\"\n class=\"pl-dropdown-multi\"\n data-testid=\"pl-dropdown-multi-control\"\n :class=\"{ open: data.open, error, disabled: isDisabled }\"\n @keydown=\"handleKeydown\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-dropdown-multi__container\">\n <div class=\"pl-dropdown-multi__field\">\n <input\n ref=\"input\"\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 data-testid=\"pl-dropdown-multi-input\"\n @focus=\"data.open = true\"\n />\n <div v-if=\"!data.open\" class=\"chips-container\" data-testid=\"pl-dropdown-multi-chips\">\n <PlChip\n v-for=\"(opt, i) in selectedOptionsRef\"\n :key=\"i\"\n :class=\"{ 'pl-dropdown-multi__chip--missing': opt.isMissing }\"\n closeable\n data-testid=\"pl-dropdown-multi-chip\"\n small\n @click.stop=\"data.open = true\"\n @close=\"unselectOption(opt.value)\"\n >\n <!-- The hover stops here: the tooltip of the chip itself would close this one. -->\n <PlTooltip\n v-if=\"opt.hint !== undefined\"\n element=\"span\"\n position=\"top\"\n data-testid=\"pl-dropdown-multi-chip-hint\"\n @mouseover.stop\n >\n <span>{{ opt.label }}</span>\n <template #tooltip>\n <component :is=\"opt.hint\" />\n </template>\n </PlTooltip>\n <template v-else>{{ opt.label }}</template>\n </PlChip>\n </div>\n\n <div class=\"pl-dropdown-multi__controls\">\n <PlIcon24\n v-if=\"showLoadingSpinner\"\n name=\"loading\"\n data-testid=\"pl-dropdown-multi-loading\"\n />\n <slot name=\"append\" />\n <div\n class=\"pl-dropdown-multi__arrow-wrapper\"\n data-testid=\"pl-dropdown-multi-arrow\"\n @click.stop=\"toggleModel\"\n >\n <div class=\"arrow-icon arrow-icon-default\" />\n </div>\n </div>\n </div>\n <label v-if=\"label\" data-testid=\"pl-dropdown-multi-label\">\n <PlSvg v-if=\"required\" :uri=\"SvgRequired\" data-testid=\"pl-dropdown-multi-required\" />\n <span>{{ label }}</span>\n <PlTooltip\n v-if=\"slots.tooltip\"\n class=\"info\"\n position=\"top\"\n data-testid=\"pl-dropdown-multi-tooltip\"\n >\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-dropdown-multi__options\"\n data-testid=\"pl-dropdown-multi-options\"\n :gap=\"5\"\n tabindex=\"-1\"\n @focusout=\"onFocusOut\"\n >\n <div\n class=\"pl-dropdown-multi__open-chips-container\"\n data-testid=\"pl-dropdown-multi-chips\"\n >\n <PlChip\n v-for=\"(opt, i) in selectedOptionsRef\"\n :key=\"i\"\n :class=\"{ 'pl-dropdown-multi__chip--missing': opt.isMissing }\"\n closeable\n data-testid=\"pl-dropdown-multi-chip\"\n small\n @close=\"unselectOption(opt.value)\"\n >\n <!-- The hover stops here: the tooltip of the chip itself would close this one. -->\n <PlTooltip\n v-if=\"opt.hint !== undefined\"\n element=\"span\"\n position=\"top\"\n data-testid=\"pl-dropdown-multi-chip-hint\"\n @mouseover.stop\n >\n <span>{{ opt.label }}</span>\n <template #tooltip>\n <component :is=\"opt.hint\" />\n </template>\n </PlTooltip>\n <template v-else>{{ opt.label }}</template>\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 data-testid=\"pl-dropdown-multi-option\"\n @click.stop=\"selectOption(item.value)\"\n />\n <div\n v-if=\"!filteredOptionsRef.length\"\n class=\"nothing-found\"\n data-testid=\"pl-dropdown-multi-options-empty\"\n >\n Nothing found\n </div>\n </DropdownOverlay>\n <DoubleContour class=\"pl-dropdown-multi__contour\" :group-position=\"groupPosition\" />\n </div>\n </div>\n <div v-if=\"error\" class=\"pl-dropdown-multi__error\" data-testid=\"pl-dropdown-multi-error\">\n {{ getErrorMessage(error) }}\n </div>\n <div\n v-else-if=\"helper\"\n class=\"pl-dropdown-multi__helper\"\n data-testid=\"pl-dropdown-multi-helper\"\n >\n {{ helper }}\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -1,3 +1,4 @@
1
+ import { MissingValueLabel, MissingValueTooltip } from '../../helpers/columnValue';
1
2
  import { ListOption } from '../../types';
2
3
  /**
3
4
  * A component for selecting multiple values from a list of options
@@ -32,9 +33,16 @@ declare const __VLS_export: <M = unknown>(__VLS_props: NonNullable<Awaited<typeo
32
33
  placeholder?: string;
33
34
  /**
34
35
  * Text shown in a chip when a `modelValue` entry is missing from `options` —
35
- * e.g. its upstream source was deleted. Rendered italic in error color.
36
+ * e.g. its upstream source was deleted. Rendered italic in error color. One text for every
37
+ * such value, or a function giving it per value. By default, the value a column value id
38
+ * picks, marked as not available, or "Value not available".
36
39
  */
37
- missingValueLabel?: string;
40
+ missingValueLabel?: MissingValueLabel;
41
+ /**
42
+ * Explains a selected value missing from the options in a tooltip over it: one text for every
43
+ * such value, or a function giving the content per value.
44
+ */
45
+ missingValueTooltip?: MissingValueTooltip;
38
46
  /**
39
47
  * If `true`, the dropdown component is marked as required.
40
48
  */
@@ -1 +1 @@
1
- {"version":3,"file":"PlDropdownMulti.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlDropdownMulti/PlDropdownMulti.vue"],"names":[],"mappings":"AAybA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAS9C,OAAO,0BAA0B,CAAC;AAGlC;;GAEG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAKzC,QAAA,MAAM,YAAY,GAAK,CAAC,GAAG,OAAO,EACjC,aAAa,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAC9D,YAAY,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,EAC3G,gBAAgB,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAClE;WAspBO,OAAO,KAAK,EAAE,WAAW,GAAG,mBAAmB,CAAC;QA3oBpD;;WAEG;oBACS,CAAC,EAAE;QACf;;WAEG;gBACK,MAAM;QACd;;WAEG;kBACO,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QACnC;;WAEG;iBACM,MAAM;QACf;;WAEG;gBACK,OAAO;QACf;;WAEG;sBACW,MAAM;QACpB;;;WAGG;4BACiB,MAAM;QAC1B;;WAEG;mBACQ,OAAO;QAClB;;WAEG;mBACQ,OAAO;QAClB;;aAEK;wBAED,KAAK,GACL,QAAQ,GACR,MAAM,GACN,OAAO,GACP,UAAU,GACV,WAAW,GACX,aAAa,GACb,cAAc,GACd,QAAQ;;;KA0lB2E,CAAC,GAAG,CAAC,OAAO,UAAU,SAAS;QAAE,oBAAoB,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,CAAC,GAAG,EAAE,CAAC;YAC5J,CAAC,OAAO,EAAE,EAAE,KAAK,IAAI;WACtB,GAAG;;iBAbE,CAAC,KAAK,IAAiB,KAAK,GAAG;;kBAC9B,CAAC,KAAK,IAAiB,KAAK,GAAG;;cA1oBvC,mBAAmB,KAAK,CAAC,EAAE,KAAG,IAAI;EA0pBpC,KACQ,OAAO,KAAK,EAAE,KAAK,GAAG;IAAE,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAA;CAAI,CAAC;AACzF,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,CAAC,GAAG,EAAE,CAAC"}
1
+ {"version":3,"file":"PlDropdownMulti.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlDropdownMulti/PlDropdownMulti.vue"],"names":[],"mappings":"AAgeA,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAIxF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAS9C,OAAO,0BAA0B,CAAC;AAGlC;;GAEG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAKzC,QAAA,MAAM,YAAY,GAAK,CAAC,GAAG,OAAO,EACjC,aAAa,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAC9D,YAAY,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,EAC3G,gBAAgB,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAClE;WA4vBO,OAAO,KAAK,EAAE,WAAW,GAAG,mBAAmB,CAAC;QAjvBpD;;WAEG;oBACS,CAAC,EAAE;QACf;;WAEG;gBACK,MAAM;QACd;;WAEG;kBACO,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QACnC;;WAEG;iBACM,MAAM;QACf;;WAEG;gBACK,OAAO;QACf;;WAEG;sBACW,MAAM;QACpB;;;;;WAKG;4BACiB,iBAAiB;QACrC;;;WAGG;8BACmB,mBAAmB;QACzC;;WAEG;mBACQ,OAAO;QAClB;;WAEG;mBACQ,OAAO;QAClB;;aAEK;wBAED,KAAK,GACL,QAAQ,GACR,MAAM,GACN,OAAO,GACP,UAAU,GACV,WAAW,GACX,aAAa,GACb,cAAc,GACd,QAAQ;;;KAyrB2E,CAAC,GAAG,CAAC,OAAO,UAAU,SAAS;QAAE,oBAAoB,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,CAAC,GAAG,EAAE,CAAC;YAC5J,CAAC,OAAO,EAAE,EAAE,KAAK,IAAI;WACtB,GAAG;;iBAbE,CAAC,KAAK,IAAiB,KAAK,GAAG;;kBAC9B,CAAC,KAAK,IAAiB,KAAK,GAAG;;cAhvBvC,mBAAmB,KAAK,CAAC,EAAE,KAAG,IAAI;EAgwBpC,KACQ,OAAO,KAAK,EAAE,KAAK,GAAG;IAAE,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAA;CAAI,CAAC;AACzF,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,CAAC,GAAG,EAAE,CAAC"}
@@ -7,39 +7,40 @@ import r from "../DropdownListItem.js";
7
7
  import { getErrorMessage as i } from "../../helpers/error.js";
8
8
  import a from "../PlIcon24/PlIcon24.js";
9
9
  import "../PlIcon24/index.js";
10
- import o from "../../utils/DoubleContour.js";
11
- import { useLabelNotch as s } from "../../utils/useLabelNotch.js";
12
- import { deepEqual as c, deepIncludes as l } from "../../helpers/objects.js";
13
- import u from "../../utils/DropdownOverlay/DropdownOverlay.js";
14
- import ee from "../../assets/images/required.js";
15
- import d from "../PlChip/PlChip.js";
10
+ import ee from "../../utils/DoubleContour.js";
11
+ import { useLabelNotch as o } from "../../utils/useLabelNotch.js";
12
+ import { deepEqual as s, deepIncludes as c } from "../../helpers/objects.js";
13
+ import te from "../../utils/DropdownOverlay/DropdownOverlay.js";
14
+ import ne from "../../assets/images/required.js";
15
+ import l from "../PlChip/PlChip.js";
16
16
  import "../PlChip/index.js";
17
+ import { missingValueText as re, missingValueTooltip as u, pickedValueText as ie } from "../../helpers/columnValue.js";
17
18
  import './pl-dropdown-multi.css';/* empty css */
18
- import { Fragment as f, computed as p, createBlock as m, createCommentVNode as h, createElementBlock as g, createElementVNode as _, createTextVNode as v, createVNode as te, defineComponent as y, normalizeClass as b, openBlock as x, reactive as S, ref as C, renderList as w, renderSlot as T, toDisplayString as E, unref as D, useSlots as ne, useTemplateRef as re, vModelText as ie, watch as ae, watchPostEffect as oe, withCtx as O, withDirectives as se, withModifiers as k } from "vue";
19
+ import { Fragment as d, computed as f, createBlock as p, createCommentVNode as m, createElementBlock as h, createElementVNode as g, createTextVNode as _, createVNode as ae, defineComponent as v, normalizeClass as y, openBlock as b, reactive as oe, ref as x, renderList as S, renderSlot as C, resolveDynamicComponent as w, toDisplayString as T, unref as E, useSlots as se, useTemplateRef as ce, vModelText as le, watch as ue, watchPostEffect as de, withCtx as D, withDirectives as fe, withModifiers as O } from "vue";
19
20
  // src/components/PlDropdownMulti/PlDropdownMulti.vue?vue&type=script&setup=true&lang.ts
20
- var ce = ["tabindex"], le = { class: "pl-dropdown-multi__container" }, ue = { class: "pl-dropdown-multi__field" }, de = ["disabled", "placeholder"], fe = {
21
+ var pe = ["tabindex"], me = { class: "pl-dropdown-multi__container" }, he = { class: "pl-dropdown-multi__field" }, ge = ["disabled", "placeholder"], k = {
21
22
  key: 0,
22
23
  class: "chips-container",
23
24
  "data-testid": "pl-dropdown-multi-chips"
24
- }, pe = { class: "pl-dropdown-multi__controls" }, A = {
25
+ }, A = { class: "pl-dropdown-multi__controls" }, j = {
25
26
  key: 0,
26
27
  "data-testid": "pl-dropdown-multi-label"
27
- }, j = {
28
+ }, M = {
28
29
  class: "pl-dropdown-multi__open-chips-container",
29
30
  "data-testid": "pl-dropdown-multi-chips"
30
- }, M = {
31
+ }, N = {
31
32
  key: 0,
32
33
  class: "nothing-found",
33
34
  "data-testid": "pl-dropdown-multi-options-empty"
34
- }, N = {
35
+ }, P = {
35
36
  key: 0,
36
37
  class: "pl-dropdown-multi__error",
37
38
  "data-testid": "pl-dropdown-multi-error"
38
- }, P = {
39
+ }, F = {
39
40
  key: 1,
40
41
  class: "pl-dropdown-multi__helper",
41
42
  "data-testid": "pl-dropdown-multi-helper"
42
- }, F = /*@__PURE__*/ y({
43
+ }, I = /*@__PURE__*/ v({
43
44
  name: "PlDropdownMulti",
44
45
  props: {
45
46
  modelValue: { default: () => [] },
@@ -48,7 +49,14 @@ var ce = ["tabindex"], le = { class: "pl-dropdown-multi__container" }, ue = { cl
48
49
  helper: { default: void 0 },
49
50
  error: { default: void 0 },
50
51
  placeholder: { default: "..." },
51
- missingValueLabel: { default: "Value not available" },
52
+ missingValueLabel: {
53
+ type: [String, Function],
54
+ default: void 0
55
+ },
56
+ missingValueTooltip: {
57
+ type: [String, Function],
58
+ default: void 0
59
+ },
52
60
  required: {
53
61
  type: Boolean,
54
62
  default: !1
@@ -60,139 +68,160 @@ var ce = ["tabindex"], le = { class: "pl-dropdown-multi__container" }, ue = { cl
60
68
  groupPosition: { default: void 0 }
61
69
  },
62
70
  emits: ["update:modelValue"],
63
- setup(y, { emit: F }) {
64
- let I = F, L = (e) => I("update:modelValue", e), R = ne(), z = y, B = C(), V = C(), H = re("overlay"), U = S({
71
+ setup(v, { emit: I }) {
72
+ let L = I, R = (e) => L("update:modelValue", e), _e = se(), z = v, B = x(), V = x(), H = ce("overlay"), U = oe({
65
73
  search: "",
66
74
  activeOption: -1,
67
75
  open: !1,
68
76
  optionsHeight: 0
69
- }), W = p(() => Array.isArray(z.modelValue) ? z.modelValue : []), me = p(() => U.open && z.modelValue.length > 0 ? z.placeholder : z.modelValue.length > 0 ? "" : z.placeholder), G = p(() => t(z.options ?? [])), K = p(() => {
77
+ }), W = f(() => Array.isArray(z.modelValue) ? z.modelValue : []), ve = f(() => U.open && z.modelValue.length > 0 ? z.placeholder : z.modelValue.length > 0 ? "" : z.placeholder), G = f(() => t(z.options ?? [])), K = f(() => {
70
78
  let e = z.options !== void 0;
71
79
  return W.value.map((t) => {
72
- let n = G.value.find((e) => c(e.value, t));
80
+ let n = G.value.find((e) => s(e.value, t));
73
81
  if (n) return {
74
82
  ...n,
75
- isMissing: !1
83
+ isMissing: !1,
84
+ hint: void 0
76
85
  };
77
- if (e) return {
86
+ if (!e) {
87
+ let e = ie(t);
88
+ return e === void 0 ? void 0 : {
89
+ value: t,
90
+ label: e,
91
+ isMissing: !1,
92
+ hint: void 0
93
+ };
94
+ }
95
+ return {
78
96
  value: t,
79
- label: z.missingValueLabel,
80
- isMissing: !0
97
+ label: re(t, z.missingValueLabel),
98
+ isMissing: !0,
99
+ hint: u(t, z.missingValueTooltip)
81
100
  };
82
101
  }).filter((e) => e !== void 0);
83
- }), q = p(() => {
84
- let e = D(W), t = D(G);
102
+ }), q = f(() => {
103
+ let e = E(W), t = E(G);
85
104
  return (U.search ? t.filter((e) => {
86
105
  let t = U.search.toLowerCase();
87
106
  return e.label.toLowerCase().includes(t) ? !0 : typeof e.value == "string" ? e.value.toLowerCase().includes(t) : e.value === U.search;
88
107
  }) : [...t]).map((t) => ({
89
108
  ...t,
90
- selected: l(e, t.value)
109
+ selected: c(e, t.value)
91
110
  }));
92
- }), J = p(() => z.options === void 0), he = p(() => !z.disabled && J.value), Y = p(() => J.value ? !0 : z.disabled), ge = p(() => Y.value ? void 0 : "0"), _e = () => {
111
+ }), J = f(() => z.options === void 0), ye = f(() => !z.disabled && J.value), Y = f(() => J.value ? !0 : z.disabled), X = f(() => Y.value ? void 0 : "0"), be = () => {
93
112
  U.activeOption = 0;
94
- }, X = (e) => {
95
- let t = D(W);
96
- L(l(t, e) ? t.filter((t) => !c(t, e)) : [...t, e]), U.search = "", B?.value?.focus();
97
- }, Z = (e) => L(D(W).filter((t) => !c(t, e))), Q = () => V.value?.focus(), ve = () => {
113
+ }, Z = (e) => {
114
+ let t = E(W);
115
+ R(c(t, e) ? t.filter((t) => !s(t, e)) : [...t, e]), U.search = "", B?.value?.focus();
116
+ }, Q = (e) => R(E(W).filter((t) => !s(t, e))), xe = () => V.value?.focus(), Se = () => {
98
117
  U.open = !U.open, U.open || (U.search = "");
99
118
  }, $ = (e) => {
100
119
  let t = e.relatedTarget;
101
120
  !B.value?.contains(t) && !H.value?.listRef?.contains(t) && (U.search = "", U.open = !1);
102
- }, ye = (e) => {
121
+ }, Ce = (e) => {
103
122
  let { open: t, activeOption: n } = U;
104
123
  if (!t) {
105
124
  e.code === "Enter" && (U.open = !0);
106
125
  return;
107
126
  }
108
127
  e.code === "Escape" && (U.open = !1, B.value?.focus());
109
- let r = D(q), { length: i } = r;
128
+ let r = E(q), { length: i } = r;
110
129
  if (!i) return;
111
130
  [
112
131
  "ArrowDown",
113
132
  "ArrowUp",
114
133
  "Enter"
115
- ].includes(e.code) && e.preventDefault(), e.code === "Enter" && X(r[n].value);
134
+ ].includes(e.code) && e.preventDefault(), e.code === "Enter" && Z(r[n].value);
116
135
  let a = e.code === "ArrowDown" ? 1 : e.code === "ArrowUp" ? -1 : 0;
117
136
  U.activeOption = Math.abs(n + a + i) % i, requestAnimationFrame(() => H.value?.scrollIntoActive());
118
137
  };
119
- return s(B), ae(() => z.modelValue, () => _e(), { immediate: !0 }), oe(() => {
138
+ return o(B), ue(() => z.modelValue, () => be(), { immediate: !0 }), de(() => {
120
139
  U.search, U.open && H.value?.scrollIntoActive();
121
- }), (t, s) => (x(), g("div", {
140
+ }), (t, o) => (b(), h("div", {
122
141
  class: "pl-dropdown-multi__envelope",
123
- onClick: Q,
142
+ onClick: xe,
124
143
  "data-testid": "pl-dropdown-multi"
125
- }, [_("div", {
144
+ }, [g("div", {
126
145
  ref_key: "rootRef",
127
146
  ref: B,
128
- tabindex: ge.value,
129
- class: b(["pl-dropdown-multi", {
147
+ tabindex: X.value,
148
+ class: y(["pl-dropdown-multi", {
130
149
  open: U.open,
131
- error: y.error,
150
+ error: v.error,
132
151
  disabled: Y.value
133
152
  }]),
134
153
  "data-testid": "pl-dropdown-multi-control",
135
- onKeydown: ye,
154
+ onKeydown: Ce,
136
155
  onFocusout: $
137
- }, [_("div", le, [
138
- _("div", ue, [
139
- se(_("input", {
156
+ }, [g("div", me, [
157
+ g("div", he, [
158
+ fe(g("input", {
140
159
  ref_key: "input",
141
160
  ref: V,
142
- "onUpdate:modelValue": s[0] ||= (e) => U.search = e,
161
+ "onUpdate:modelValue": o[0] ||= (e) => U.search = e,
143
162
  type: "text",
144
163
  tabindex: "-1",
145
164
  disabled: Y.value,
146
- placeholder: me.value,
165
+ placeholder: ve.value,
147
166
  spellcheck: "false",
148
167
  autocomplete: "chrome-off",
149
168
  "data-testid": "pl-dropdown-multi-input",
150
- onFocus: s[1] ||= (e) => U.open = !0
151
- }, null, 40, de), [[ie, U.search]]),
152
- U.open ? h("", !0) : (x(), g("div", fe, [(x(!0), g(f, null, w(K.value, (e, t) => (x(), m(D(d), {
169
+ onFocus: o[1] ||= (e) => U.open = !0
170
+ }, null, 40, ge), [[le, U.search]]),
171
+ U.open ? m("", !0) : (b(), h("div", k, [(b(!0), h(d, null, S(K.value, (e, t) => (b(), p(E(l), {
153
172
  key: t,
154
- class: b({ "pl-dropdown-multi__chip--missing": e.isMissing }),
173
+ class: y({ "pl-dropdown-multi__chip--missing": e.isMissing }),
155
174
  closeable: "",
156
175
  "data-testid": "pl-dropdown-multi-chip",
157
176
  small: "",
158
- onClick: s[2] ||= k((e) => U.open = !0, ["stop"]),
159
- onClose: (t) => Z(e.value)
177
+ onClick: o[3] ||= O((e) => U.open = !0, ["stop"]),
178
+ onClose: (t) => Q(e.value)
160
179
  }, {
161
- default: O(() => [v(E(e.label), 1)]),
180
+ default: D(() => [e.hint === void 0 ? (b(), h(d, { key: 1 }, [_(T(e.label), 1)], 64)) : (b(), p(E(n), {
181
+ key: 0,
182
+ element: "span",
183
+ position: "top",
184
+ "data-testid": "pl-dropdown-multi-chip-hint",
185
+ onMouseover: o[2] ||= O(() => {}, ["stop"])
186
+ }, {
187
+ tooltip: D(() => [(b(), p(w(e.hint)))]),
188
+ default: D(() => [g("span", null, T(e.label), 1)]),
189
+ _: 2
190
+ }, 1024))]),
162
191
  _: 2
163
192
  }, 1032, ["class", "onClose"]))), 128))])),
164
- _("div", pe, [
165
- he.value ? (x(), m(D(a), {
193
+ g("div", A, [
194
+ ye.value ? (b(), p(E(a), {
166
195
  key: 0,
167
196
  name: "loading",
168
197
  "data-testid": "pl-dropdown-multi-loading"
169
- })) : h("", !0),
170
- T(t.$slots, "append"),
171
- _("div", {
198
+ })) : m("", !0),
199
+ C(t.$slots, "append"),
200
+ g("div", {
172
201
  class: "pl-dropdown-multi__arrow-wrapper",
173
202
  "data-testid": "pl-dropdown-multi-arrow",
174
- onClick: k(ve, ["stop"])
175
- }, [...s[3] ||= [_("div", { class: "arrow-icon arrow-icon-default" }, null, -1)]])
203
+ onClick: O(Se, ["stop"])
204
+ }, [...o[5] ||= [g("div", { class: "arrow-icon arrow-icon-default" }, null, -1)]])
176
205
  ])
177
206
  ]),
178
- y.label ? (x(), g("label", A, [
179
- y.required ? (x(), m(D(e), {
207
+ v.label ? (b(), h("label", j, [
208
+ v.required ? (b(), p(E(e), {
180
209
  key: 0,
181
- uri: D(ee),
210
+ uri: E(ne),
182
211
  "data-testid": "pl-dropdown-multi-required"
183
- }, null, 8, ["uri"])) : h("", !0),
184
- _("span", null, E(y.label), 1),
185
- D(R).tooltip ? (x(), m(D(n), {
212
+ }, null, 8, ["uri"])) : m("", !0),
213
+ g("span", null, T(v.label), 1),
214
+ E(_e).tooltip ? (b(), p(E(n), {
186
215
  key: 1,
187
216
  class: "info",
188
217
  position: "top",
189
218
  "data-testid": "pl-dropdown-multi-tooltip"
190
219
  }, {
191
- tooltip: O(() => [T(t.$slots, "tooltip")]),
220
+ tooltip: D(() => [C(t.$slots, "tooltip")]),
192
221
  _: 3
193
- })) : h("", !0)
194
- ])) : h("", !0),
195
- U.open ? (x(), m(u, {
222
+ })) : m("", !0)
223
+ ])) : m("", !0),
224
+ U.open ? (b(), p(te, {
196
225
  key: 1,
197
226
  ref_key: "overlay",
198
227
  ref: H,
@@ -203,19 +232,29 @@ var ce = ["tabindex"], le = { class: "pl-dropdown-multi__container" }, ue = { cl
203
232
  tabindex: "-1",
204
233
  onFocusout: $
205
234
  }, {
206
- default: O(() => [
207
- _("div", j, [(x(!0), g(f, null, w(K.value, (e, t) => (x(), m(D(d), {
235
+ default: D(() => [
236
+ g("div", M, [(b(!0), h(d, null, S(K.value, (e, t) => (b(), p(E(l), {
208
237
  key: t,
209
- class: b({ "pl-dropdown-multi__chip--missing": e.isMissing }),
238
+ class: y({ "pl-dropdown-multi__chip--missing": e.isMissing }),
210
239
  closeable: "",
211
240
  "data-testid": "pl-dropdown-multi-chip",
212
241
  small: "",
213
- onClose: (t) => Z(e.value)
242
+ onClose: (t) => Q(e.value)
214
243
  }, {
215
- default: O(() => [v(E(e.label), 1)]),
244
+ default: D(() => [e.hint === void 0 ? (b(), h(d, { key: 1 }, [_(T(e.label), 1)], 64)) : (b(), p(E(n), {
245
+ key: 0,
246
+ element: "span",
247
+ position: "top",
248
+ "data-testid": "pl-dropdown-multi-chip-hint",
249
+ onMouseover: o[4] ||= O(() => {}, ["stop"])
250
+ }, {
251
+ tooltip: D(() => [(b(), p(w(e.hint)))]),
252
+ default: D(() => [g("span", null, T(e.label), 1)]),
253
+ _: 2
254
+ }, 1024))]),
216
255
  _: 2
217
256
  }, 1032, ["class", "onClose"]))), 128))]),
218
- (x(!0), g(f, null, w(q.value, (e, t) => (x(), m(r, {
257
+ (b(!0), h(d, null, S(q.value, (e, t) => (b(), p(r, {
219
258
  key: t,
220
259
  option: e,
221
260
  "text-item": "text",
@@ -224,24 +263,24 @@ var ce = ["tabindex"], le = { class: "pl-dropdown-multi__container" }, ue = { cl
224
263
  size: "medium",
225
264
  "use-checkbox": "",
226
265
  "data-testid": "pl-dropdown-multi-option",
227
- onClick: k((t) => X(e.value), ["stop"])
266
+ onClick: O((t) => Z(e.value), ["stop"])
228
267
  }, null, 8, [
229
268
  "option",
230
269
  "is-selected",
231
270
  "is-hovered",
232
271
  "onClick"
233
272
  ]))), 128)),
234
- q.value.length ? h("", !0) : (x(), g("div", M, " Nothing found "))
273
+ q.value.length ? m("", !0) : (b(), h("div", N, " Nothing found "))
235
274
  ]),
236
275
  _: 1
237
- }, 8, ["root"])) : h("", !0),
238
- te(o, {
276
+ }, 8, ["root"])) : m("", !0),
277
+ ae(ee, {
239
278
  class: "pl-dropdown-multi__contour",
240
- "group-position": y.groupPosition
279
+ "group-position": v.groupPosition
241
280
  }, null, 8, ["group-position"])
242
- ])], 42, ce), y.error ? (x(), g("div", N, E(D(i)(y.error)), 1)) : y.helper ? (x(), g("div", P, E(y.helper), 1)) : h("", !0)]));
281
+ ])], 42, pe), v.error ? (b(), h("div", P, T(E(i)(v.error)), 1)) : v.helper ? (b(), h("div", F, T(v.helper), 1)) : m("", !0)]));
243
282
  }
244
283
  });
245
- export { F as default };
284
+ export { I as default };
246
285
 
247
286
  //# sourceMappingURL=PlDropdownMulti.vue2.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PlDropdownMulti.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_createElementVNode","_normalizeClass","_withDirectives","_vModelText","_Fragment","_renderList","_createBlock","_unref","PlChip","_withModifiers","_withCtx","_createTextVNode","_toDisplayString","_createCommentVNode","PlIcon24","_renderSlot","PlSvg","SvgRequired","PlTooltip","DropdownOverlay","DropdownListItem","_createVNode","DoubleContour","PlSvg_default","PlTooltip_default","DropdownListItem_default","PlIcon24_default","DoubleContour_default","DropdownOverlay_default","required_default","PlChip_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","PlDropdownMulti_vue_vue_type_script_setup_true_lang_default","__emit","emit","emitModel","v","slots","useSlots","props","__props","rootRef","ref","input","overlay","useTemplateRef","data","reactive","selectedValuesRef","computed","placeholderRef","normalizedOptionsRef","normalizeListOptions","selectedOptionsRef","optionsLoaded","opt","deepEqual","o","filteredOptionsRef","selectedValues","unref","options","search","deepIncludes","isLoadingOptions","showLoadingSpinner","isDisabled","tabindex","updateActiveOption","selectOption","values","it","unselectOption","d","setFocusOnInput","toggleModel","onFocusOut","relatedTarget","event","handleKeydown","open","filteredOptions","length","activeOption","useLabelNotch","watch","watchPostEffect","openBlock","createElementBlock","createElementVNode","normalizeClass","withDirectives","_cache","$event","vModelText","createCommentVNode","Fragment","renderList","createBlock","i","withModifiers","withCtx","createTextVNode","toDisplayString","renderSlot","_ctx","index","item","createVNode","getErrorMessage"],"sources":["../../../src/components/PlDropdownMulti/PlDropdownMulti.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * A component for selecting multiple values from a list of options\n */\nexport default {\n name: \"PlDropdownMulti\",\n};\n</script>\n\n<script lang=\"ts\" setup generic=\"M = unknown\">\nimport {\n computed,\n reactive,\n ref,\n unref,\n useSlots,\n useTemplateRef,\n watch,\n watchPostEffect,\n} from \"vue\";\nimport SvgRequired from \"../../assets/images/required.svg?raw\";\nimport { getErrorMessage } from \"../../helpers/error.ts\";\nimport { deepEqual, deepIncludes } from \"../../helpers/objects\";\nimport { normalizeListOptions } from \"../../helpers/utils\";\nimport type { ListOption } from \"../../types\";\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 { PlIcon24 } from \"../PlIcon24\";\nimport { PlSvg } from \"../PlSvg\";\nimport { PlTooltip } from \"../PlTooltip\";\nimport \"./pl-dropdown-multi.scss\";\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 * The label text for the dropdown field (optional)\n */\n label?: string;\n /**\n * List of available options for the dropdown\n */\n options?: Readonly<ListOption<M>[]>;\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 * Text shown in a chip when a `modelValue` entry is missing from `options` —\n * e.g. its upstream source was deleted. Rendered italic in error color.\n */\n missingValueLabel?: 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 * Makes some of corners not rounded\n * */\n groupPosition?:\n | \"top\"\n | \"bottom\"\n | \"left\"\n | \"right\"\n | \"top-left\"\n | \"top-right\"\n | \"bottom-left\"\n | \"bottom-right\"\n | \"middle\";\n }>(),\n {\n modelValue: () => [],\n label: undefined,\n helper: undefined,\n error: undefined,\n placeholder: \"...\",\n missingValueLabel: \"Value not available\",\n required: false,\n disabled: false,\n options: undefined,\n groupPosition: undefined,\n },\n);\n\nconst rootRef = ref<HTMLElement | undefined>();\nconst input = 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\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 normalizedOptionsRef = computed(() => normalizeListOptions(props.options ?? []));\n\nconst selectedOptionsRef = computed(() => {\n // While options load (`options === undefined`), hide chips for unresolved values\n // to avoid a \"missing\" flash that resolves once options arrive.\n const optionsLoaded = props.options !== undefined;\n return selectedValuesRef.value\n .map((v) => {\n const opt = normalizedOptionsRef.value.find((o) => deepEqual(o.value, v));\n if (opt) {\n // Found: render the option's own (normalized) label verbatim — matches\n // PlDropdown. `opt.label` is always a string (possibly \"\"), never an object,\n // so there is no raw-value leak to guard against.\n return { ...opt, isMissing: false };\n }\n if (!optionsLoaded) {\n return undefined;\n }\n // Honor empty `missingValueLabel` verbatim — caller's explicit \"render nothing\".\n return {\n value: v,\n label: props.missingValueLabel,\n isMissing: true,\n };\n })\n .filter((v): v is NonNullable<typeof v> => v !== undefined);\n});\n\nconst filteredOptionsRef = computed(() => {\n const selectedValues = unref(selectedValuesRef);\n\n const options = unref(normalizedOptionsRef);\n\n return (\n data.search\n ? options.filter((opt) => {\n const search = data.search.toLowerCase();\n\n if (opt.label.toLowerCase().includes(search)) {\n return true;\n }\n\n if (typeof opt.value === \"string\") {\n return opt.value.toLowerCase().includes(search);\n }\n\n return opt.value === data.search;\n })\n : [...options]\n ).map((opt) => ({\n ...opt,\n selected: deepIncludes(selectedValues, opt.value),\n }));\n});\n\nconst isLoadingOptions = computed(() => {\n return props.options === undefined;\n});\n\nconst showLoadingSpinner = computed(() => {\n return !props.disabled && isLoadingOptions.value;\n});\n\nconst isDisabled = computed(() => {\n if (isLoadingOptions.value) {\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 data.search = \"\";\n rootRef?.value?.focus();\n};\n\nconst unselectOption = (d: M) =>\n emitModel(unref(selectedValuesRef).filter((v) => !deepEqual(v, d)));\n\nconst setFocusOnInput = () => input.value?.focus();\n\nconst toggleModel = () => {\n data.open = !data.open;\n if (!data.open) {\n data.search = \"\";\n }\n};\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.search = \"\";\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 rootRef.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\nwatchPostEffect(() => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n data.search;\n\n if (data.open) {\n overlay.value?.scrollIntoActive();\n }\n});\n</script>\n\n<template>\n <div class=\"pl-dropdown-multi__envelope\" @click=\"setFocusOnInput\" data-testid=\"pl-dropdown-multi\">\n <div\n ref=\"rootRef\"\n :tabindex=\"tabindex\"\n class=\"pl-dropdown-multi\"\n data-testid=\"pl-dropdown-multi-control\"\n :class=\"{ open: data.open, error, disabled: isDisabled }\"\n @keydown=\"handleKeydown\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-dropdown-multi__container\">\n <div class=\"pl-dropdown-multi__field\">\n <input\n ref=\"input\"\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 data-testid=\"pl-dropdown-multi-input\"\n @focus=\"data.open = true\"\n />\n <div v-if=\"!data.open\" class=\"chips-container\" data-testid=\"pl-dropdown-multi-chips\">\n <PlChip\n v-for=\"(opt, i) in selectedOptionsRef\"\n :key=\"i\"\n :class=\"{ 'pl-dropdown-multi__chip--missing': opt.isMissing }\"\n closeable\n data-testid=\"pl-dropdown-multi-chip\"\n small\n @click.stop=\"data.open = true\"\n @close=\"unselectOption(opt.value)\"\n >\n {{ opt.label }}\n </PlChip>\n </div>\n\n <div class=\"pl-dropdown-multi__controls\">\n <PlIcon24\n v-if=\"showLoadingSpinner\"\n name=\"loading\"\n data-testid=\"pl-dropdown-multi-loading\"\n />\n <slot name=\"append\" />\n <div\n class=\"pl-dropdown-multi__arrow-wrapper\"\n data-testid=\"pl-dropdown-multi-arrow\"\n @click.stop=\"toggleModel\"\n >\n <div class=\"arrow-icon arrow-icon-default\" />\n </div>\n </div>\n </div>\n <label v-if=\"label\" data-testid=\"pl-dropdown-multi-label\">\n <PlSvg v-if=\"required\" :uri=\"SvgRequired\" data-testid=\"pl-dropdown-multi-required\" />\n <span>{{ label }}</span>\n <PlTooltip\n v-if=\"slots.tooltip\"\n class=\"info\"\n position=\"top\"\n data-testid=\"pl-dropdown-multi-tooltip\"\n >\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-dropdown-multi__options\"\n data-testid=\"pl-dropdown-multi-options\"\n :gap=\"5\"\n tabindex=\"-1\"\n @focusout=\"onFocusOut\"\n >\n <div\n class=\"pl-dropdown-multi__open-chips-container\"\n data-testid=\"pl-dropdown-multi-chips\"\n >\n <PlChip\n v-for=\"(opt, i) in selectedOptionsRef\"\n :key=\"i\"\n :class=\"{ 'pl-dropdown-multi__chip--missing': opt.isMissing }\"\n closeable\n data-testid=\"pl-dropdown-multi-chip\"\n small\n @close=\"unselectOption(opt.value)\"\n >\n {{ opt.label }}\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 data-testid=\"pl-dropdown-multi-option\"\n @click.stop=\"selectOption(item.value)\"\n />\n <div\n v-if=\"!filteredOptionsRef.length\"\n class=\"nothing-found\"\n data-testid=\"pl-dropdown-multi-options-empty\"\n >\n Nothing found\n </div>\n </DropdownOverlay>\n <DoubleContour class=\"pl-dropdown-multi__contour\" :group-position=\"groupPosition\" />\n </div>\n </div>\n <div v-if=\"error\" class=\"pl-dropdown-multi__error\" data-testid=\"pl-dropdown-multi-error\">\n {{ getErrorMessage(error) }}\n </div>\n <div\n v-else-if=\"helper\"\n class=\"pl-dropdown-multi__helper\"\n data-testid=\"pl-dropdown-multi-helper\"\n >\n {{ helper }}\n </div>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"PlDropdownMulti.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_createElementVNode","_normalizeClass","_withDirectives","_vModelText","_Fragment","_renderList","_createBlock","_unref","PlChip","_withModifiers","_withCtx","PlTooltip","_resolveDynamicComponent","_toDisplayString","_createTextVNode","_createCommentVNode","PlIcon24","_renderSlot","PlSvg","SvgRequired","DropdownOverlay","DropdownListItem","_createVNode","DoubleContour","PlSvg_default","PlTooltip_default","DropdownListItem_default","PlIcon24_default","DoubleContour_default","DropdownOverlay_default","required_default","PlChip_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","PlDropdownMulti_vue_vue_type_script_setup_true_lang_default","__emit","emit","emitModel","v","slots","useSlots","props","__props","rootRef","ref","input","overlay","useTemplateRef","data","reactive","selectedValuesRef","computed","placeholderRef","normalizedOptionsRef","normalizeListOptions","selectedOptionsRef","optionsLoaded","opt","deepEqual","o","label","pickedValueText","missingValueText","missingValueTooltip","filteredOptionsRef","selectedValues","unref","options","search","deepIncludes","isLoadingOptions","showLoadingSpinner","isDisabled","tabindex","updateActiveOption","selectOption","values","it","unselectOption","d","setFocusOnInput","toggleModel","onFocusOut","relatedTarget","event","handleKeydown","open","filteredOptions","length","activeOption","useLabelNotch","watch","watchPostEffect","openBlock","createElementBlock","createElementVNode","normalizeClass","withDirectives","_cache","$event","vModelText","createCommentVNode","Fragment","renderList","createBlock","i","withModifiers","withCtx","createTextVNode","toDisplayString","resolveDynamicComponent","renderSlot","_ctx","index","item","createVNode","getErrorMessage"],"sources":["../../../src/components/PlDropdownMulti/PlDropdownMulti.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * A component for selecting multiple values from a list of options\n */\nexport default {\n name: \"PlDropdownMulti\",\n};\n</script>\n\n<script lang=\"ts\" setup generic=\"M = unknown\">\nimport {\n computed,\n reactive,\n ref,\n unref,\n useSlots,\n useTemplateRef,\n watch,\n watchPostEffect,\n} from \"vue\";\nimport SvgRequired from \"../../assets/images/required.svg?raw\";\nimport { missingValueText, missingValueTooltip, pickedValueText } from \"../../helpers/columnValue\";\nimport type { MissingValueLabel, MissingValueTooltip } from \"../../helpers/columnValue\";\nimport { getErrorMessage } from \"../../helpers/error.ts\";\nimport { deepEqual, deepIncludes } from \"../../helpers/objects\";\nimport { normalizeListOptions } from \"../../helpers/utils\";\nimport type { ListOption } from \"../../types\";\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 { PlIcon24 } from \"../PlIcon24\";\nimport { PlSvg } from \"../PlSvg\";\nimport { PlTooltip } from \"../PlTooltip\";\nimport \"./pl-dropdown-multi.scss\";\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 * The label text for the dropdown field (optional)\n */\n label?: string;\n /**\n * List of available options for the dropdown\n */\n options?: Readonly<ListOption<M>[]>;\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 * Text shown in a chip when a `modelValue` entry is missing from `options` —\n * e.g. its upstream source was deleted. Rendered italic in error color. One text for every\n * such value, or a function giving it per value. By default, the value a column value id\n * picks, marked as not available, or \"Value not available\".\n */\n missingValueLabel?: MissingValueLabel;\n /**\n * Explains a selected value missing from the options in a tooltip over it: one text for every\n * such value, or a function giving the content per value.\n */\n missingValueTooltip?: MissingValueTooltip;\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 * Makes some of corners not rounded\n * */\n groupPosition?:\n | \"top\"\n | \"bottom\"\n | \"left\"\n | \"right\"\n | \"top-left\"\n | \"top-right\"\n | \"bottom-left\"\n | \"bottom-right\"\n | \"middle\";\n }>(),\n {\n modelValue: () => [],\n label: undefined,\n helper: undefined,\n error: undefined,\n placeholder: \"...\",\n missingValueLabel: undefined,\n missingValueTooltip: undefined,\n required: false,\n disabled: false,\n options: undefined,\n groupPosition: undefined,\n },\n);\n\nconst rootRef = ref<HTMLElement | undefined>();\nconst input = 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\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 normalizedOptionsRef = computed(() => normalizeListOptions(props.options ?? []));\n\nconst selectedOptionsRef = computed(() => {\n // While options load (`options === undefined`), hide chips for unresolved values\n // to avoid a \"missing\" flash that resolves once options arrive. A picked column value\n // is shown by its own label meanwhile.\n const optionsLoaded = props.options !== undefined;\n return selectedValuesRef.value\n .map((v) => {\n const opt = normalizedOptionsRef.value.find((o) => deepEqual(o.value, v));\n if (opt) {\n // Found: render the option's own (normalized) label verbatim — matches\n // PlDropdown. `opt.label` is always a string (possibly \"\"), never an object,\n // so there is no raw-value leak to guard against.\n return { ...opt, isMissing: false, hint: undefined };\n }\n if (!optionsLoaded) {\n const label = pickedValueText(v);\n return label === undefined\n ? undefined\n : { value: v, label, isMissing: false, hint: undefined };\n }\n // Honor empty `missingValueLabel` verbatim — caller's explicit \"render nothing\".\n return {\n value: v,\n label: missingValueText(v, props.missingValueLabel),\n isMissing: true,\n hint: missingValueTooltip(v, props.missingValueTooltip),\n };\n })\n .filter((v): v is NonNullable<typeof v> => v !== undefined);\n});\n\nconst filteredOptionsRef = computed(() => {\n const selectedValues = unref(selectedValuesRef);\n\n const options = unref(normalizedOptionsRef);\n\n return (\n data.search\n ? options.filter((opt) => {\n const search = data.search.toLowerCase();\n\n if (opt.label.toLowerCase().includes(search)) {\n return true;\n }\n\n if (typeof opt.value === \"string\") {\n return opt.value.toLowerCase().includes(search);\n }\n\n return opt.value === data.search;\n })\n : [...options]\n ).map((opt) => ({\n ...opt,\n selected: deepIncludes(selectedValues, opt.value),\n }));\n});\n\nconst isLoadingOptions = computed(() => {\n return props.options === undefined;\n});\n\nconst showLoadingSpinner = computed(() => {\n return !props.disabled && isLoadingOptions.value;\n});\n\nconst isDisabled = computed(() => {\n if (isLoadingOptions.value) {\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 data.search = \"\";\n rootRef?.value?.focus();\n};\n\nconst unselectOption = (d: M) =>\n emitModel(unref(selectedValuesRef).filter((v) => !deepEqual(v, d)));\n\nconst setFocusOnInput = () => input.value?.focus();\n\nconst toggleModel = () => {\n data.open = !data.open;\n if (!data.open) {\n data.search = \"\";\n }\n};\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.search = \"\";\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 rootRef.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\nwatchPostEffect(() => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n data.search;\n\n if (data.open) {\n overlay.value?.scrollIntoActive();\n }\n});\n</script>\n\n<template>\n <div class=\"pl-dropdown-multi__envelope\" @click=\"setFocusOnInput\" data-testid=\"pl-dropdown-multi\">\n <div\n ref=\"rootRef\"\n :tabindex=\"tabindex\"\n class=\"pl-dropdown-multi\"\n data-testid=\"pl-dropdown-multi-control\"\n :class=\"{ open: data.open, error, disabled: isDisabled }\"\n @keydown=\"handleKeydown\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-dropdown-multi__container\">\n <div class=\"pl-dropdown-multi__field\">\n <input\n ref=\"input\"\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 data-testid=\"pl-dropdown-multi-input\"\n @focus=\"data.open = true\"\n />\n <div v-if=\"!data.open\" class=\"chips-container\" data-testid=\"pl-dropdown-multi-chips\">\n <PlChip\n v-for=\"(opt, i) in selectedOptionsRef\"\n :key=\"i\"\n :class=\"{ 'pl-dropdown-multi__chip--missing': opt.isMissing }\"\n closeable\n data-testid=\"pl-dropdown-multi-chip\"\n small\n @click.stop=\"data.open = true\"\n @close=\"unselectOption(opt.value)\"\n >\n <!-- The hover stops here: the tooltip of the chip itself would close this one. -->\n <PlTooltip\n v-if=\"opt.hint !== undefined\"\n element=\"span\"\n position=\"top\"\n data-testid=\"pl-dropdown-multi-chip-hint\"\n @mouseover.stop\n >\n <span>{{ opt.label }}</span>\n <template #tooltip>\n <component :is=\"opt.hint\" />\n </template>\n </PlTooltip>\n <template v-else>{{ opt.label }}</template>\n </PlChip>\n </div>\n\n <div class=\"pl-dropdown-multi__controls\">\n <PlIcon24\n v-if=\"showLoadingSpinner\"\n name=\"loading\"\n data-testid=\"pl-dropdown-multi-loading\"\n />\n <slot name=\"append\" />\n <div\n class=\"pl-dropdown-multi__arrow-wrapper\"\n data-testid=\"pl-dropdown-multi-arrow\"\n @click.stop=\"toggleModel\"\n >\n <div class=\"arrow-icon arrow-icon-default\" />\n </div>\n </div>\n </div>\n <label v-if=\"label\" data-testid=\"pl-dropdown-multi-label\">\n <PlSvg v-if=\"required\" :uri=\"SvgRequired\" data-testid=\"pl-dropdown-multi-required\" />\n <span>{{ label }}</span>\n <PlTooltip\n v-if=\"slots.tooltip\"\n class=\"info\"\n position=\"top\"\n data-testid=\"pl-dropdown-multi-tooltip\"\n >\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-dropdown-multi__options\"\n data-testid=\"pl-dropdown-multi-options\"\n :gap=\"5\"\n tabindex=\"-1\"\n @focusout=\"onFocusOut\"\n >\n <div\n class=\"pl-dropdown-multi__open-chips-container\"\n data-testid=\"pl-dropdown-multi-chips\"\n >\n <PlChip\n v-for=\"(opt, i) in selectedOptionsRef\"\n :key=\"i\"\n :class=\"{ 'pl-dropdown-multi__chip--missing': opt.isMissing }\"\n closeable\n data-testid=\"pl-dropdown-multi-chip\"\n small\n @close=\"unselectOption(opt.value)\"\n >\n <!-- The hover stops here: the tooltip of the chip itself would close this one. -->\n <PlTooltip\n v-if=\"opt.hint !== undefined\"\n element=\"span\"\n position=\"top\"\n data-testid=\"pl-dropdown-multi-chip-hint\"\n @mouseover.stop\n >\n <span>{{ opt.label }}</span>\n <template #tooltip>\n <component :is=\"opt.hint\" />\n </template>\n </PlTooltip>\n <template v-else>{{ opt.label }}</template>\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 data-testid=\"pl-dropdown-multi-option\"\n @click.stop=\"selectOption(item.value)\"\n />\n <div\n v-if=\"!filteredOptionsRef.length\"\n class=\"nothing-found\"\n data-testid=\"pl-dropdown-multi-options-empty\"\n >\n Nothing found\n </div>\n </DropdownOverlay>\n <DoubleContour class=\"pl-dropdown-multi__contour\" :group-position=\"groupPosition\" />\n </div>\n </div>\n <div v-if=\"error\" class=\"pl-dropdown-multi__error\" data-testid=\"pl-dropdown-multi-error\">\n {{ getErrorMessage(error) }}\n </div>\n <div\n v-else-if=\"helper\"\n class=\"pl-dropdown-multi__helper\"\n data-testid=\"pl-dropdown-multi-helper\"\n >\n {{ helper }}\n </div>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PlDropdownMultiRef.js","names":["_sfc_main","PlDropdownMultiRef_vue_vue_type_script_setup_true_lang_default","PlDropdownMultiRef_default"],"sources":["../../../src/components/PlDropdownMultiRef/PlDropdownMultiRef.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ModelRef, RefOption } from \"../../types\";\nimport PlDropdownMulti from \"../PlDropdownMulti/PlDropdownMulti.vue\";\nimport { computed, useSlots } from \"vue\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst slots: any = useSlots();\n\ndefineEmits<{\n /**\n * Emitted when the model value is updated.\n */\n (e: \"update:modelValue\", value: ModelRef[] | undefined): void;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n /**\n * The current selected values.\n */\n modelValue: ModelRef[] | undefined;\n /**\n * The label text for the dropdown field (optional)\n */\n label?: string;\n /**\n * List of available options for the dropdown\n */\n options?: Readonly<RefOption[]>;\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 * Text shown in a chip when a `modelValue` entry's upstream block no longer\n * exists. Defaults to \"Upstream value removed\".\n */\n missingValueLabel?: 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 {\n modelValue: () => [],\n label: undefined,\n helper: undefined,\n error: undefined,\n placeholder: \"...\",\n missingValueLabel: \"Upstream value removed\",\n required: false,\n disabled: false,\n options: undefined,\n },\n);\n\nconst options = computed(() =>\n props.options?.map((opt) => ({\n label: opt.label,\n value: opt.ref,\n })),\n);\n</script>\n\n<template>\n <PlDropdownMulti\n data-testid=\"pl-dropdown-multi-ref\"\n v-bind=\"props\"\n :options=\"options\"\n @update:model-value=\"$emit('update:modelValue', $event)\"\n >\n <template v-if=\"slots.tooltip\" #tooltip>\n <slot name=\"tooltip\" />\n </template>\n </PlDropdownMulti>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"PlDropdownMultiRef.js","names":["_sfc_main","PlDropdownMultiRef_vue_vue_type_script_setup_true_lang_default","PlDropdownMultiRef_default"],"sources":["../../../src/components/PlDropdownMultiRef/PlDropdownMultiRef.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { MissingValueLabel, MissingValueTooltip } from \"../../helpers/columnValue\";\nimport type { ModelRef, RefOption } from \"../../types\";\nimport PlDropdownMulti from \"../PlDropdownMulti/PlDropdownMulti.vue\";\nimport { computed, useSlots } from \"vue\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst slots: any = useSlots();\n\ndefineEmits<{\n /**\n * Emitted when the model value is updated.\n */\n (e: \"update:modelValue\", value: ModelRef[] | undefined): void;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n /**\n * The current selected values.\n */\n modelValue: ModelRef[] | undefined;\n /**\n * The label text for the dropdown field (optional)\n */\n label?: string;\n /**\n * List of available options for the dropdown\n */\n options?: Readonly<RefOption[]>;\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 * Text shown in a chip when a `modelValue` entry's upstream block no longer\n * exists: one text, or a function giving it per value. Defaults to \"Value not available\".\n */\n missingValueLabel?: MissingValueLabel;\n /**\n * Explains a selected value missing from the options in a tooltip over it: one text for every\n * such value, or a function giving the content per value.\n */\n missingValueTooltip?: MissingValueTooltip;\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 {\n modelValue: () => [],\n label: undefined,\n helper: undefined,\n error: undefined,\n placeholder: \"...\",\n missingValueLabel: undefined,\n missingValueTooltip: undefined,\n required: false,\n disabled: false,\n options: undefined,\n },\n);\n\nconst options = computed(() =>\n props.options?.map((opt) => ({\n label: opt.label,\n value: opt.ref,\n })),\n);\n</script>\n\n<template>\n <PlDropdownMulti\n data-testid=\"pl-dropdown-multi-ref\"\n v-bind=\"props\"\n :options=\"options\"\n @update:model-value=\"$emit('update:modelValue', $event)\"\n >\n <template v-if=\"slots.tooltip\" #tooltip>\n <slot name=\"tooltip\" />\n </template>\n </PlDropdownMulti>\n</template>\n"],"mappings":""}