@milaboratories/uikit 2.6.1 → 2.6.3
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 +143 -143
- package/.turbo/turbo-type-check.log +1 -1
- package/CHANGELOG.md +14 -0
- package/dist/base/BtnBase.vue.js +18 -18
- package/dist/base/BtnBase.vue.js.map +1 -1
- package/dist/components/ContextProvider.vue.js.map +1 -1
- package/dist/components/DataTable/BaseCellComponent.vue.js +20 -20
- package/dist/components/DataTable/BaseCellComponent.vue.js.map +1 -1
- package/dist/components/DataTable/ColumnCaret.vue.js +6 -6
- package/dist/components/DataTable/ColumnCaret.vue.js.map +1 -1
- package/dist/components/DataTable/ColumnsCommandMenu.vue.js.map +1 -1
- package/dist/components/DataTable/RowsCommandMenu.vue.js.map +1 -1
- package/dist/components/DataTable/TScroll.vue.js +12 -12
- package/dist/components/DataTable/TScroll.vue.js.map +1 -1
- package/dist/components/DataTable/TableComponent.vue.js +5 -3
- package/dist/components/DataTable/TableComponent.vue.js.map +1 -1
- package/dist/components/DataTable/TdCell.vue.js +36 -36
- package/dist/components/DataTable/TdCell.vue.js.map +1 -1
- package/dist/components/DataTable/ThCell.vue.js +27 -27
- package/dist/components/DataTable/ThCell.vue.js.map +1 -1
- package/dist/components/DataTable/TrBody.vue.js +12 -12
- package/dist/components/DataTable/TrBody.vue.js.map +1 -1
- package/dist/components/DataTable/TrHead.vue.js.map +1 -1
- package/dist/components/DataTable/assets/TableIcon.vue.js +2 -2
- package/dist/components/DataTable/assets/TableIcon.vue.js.map +1 -1
- package/dist/components/DropdownListItem.vue.js +18 -18
- package/dist/components/DropdownListItem.vue.js.map +1 -1
- package/dist/components/HScroll.vue.js.map +1 -1
- package/dist/components/InputRange.vue.js.map +1 -1
- package/dist/components/LongText.vue.js +1 -1
- package/dist/components/LongText.vue.js.map +1 -1
- package/dist/components/LongText.vue3.js +1 -1
- package/dist/components/PlAccordion/ExpandTransition.vue.js.map +1 -1
- package/dist/components/PlAccordion/ExpandTransition.vue2.js.map +1 -1
- package/dist/components/PlAccordion/ExpandTransition.vue3.js +1 -1
- package/dist/components/PlAccordion/PlAccordion.vue.js.map +1 -1
- package/dist/components/PlAccordion/PlAccordionSection.vue2.js +21 -21
- package/dist/components/PlAccordion/PlAccordionSection.vue2.js.map +1 -1
- package/dist/components/PlAlert/PlAlert.vue.js +23 -23
- package/dist/components/PlAlert/PlAlert.vue.js.map +1 -1
- package/dist/components/PlAutocomplete/PlAutocomplete.vue.d.ts +4 -0
- package/dist/components/PlAutocomplete/PlAutocomplete.vue.js +112 -106
- 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 +100 -94
- package/dist/components/PlAutocompleteMulti/PlAutocompleteMulti.vue.js.map +1 -1
- package/dist/components/PlBtnAccent/PlBtnAccent.vue.js.map +1 -1
- package/dist/components/PlBtnDanger/PlBtnDanger.vue.js.map +1 -1
- package/dist/components/PlBtnGhost/PlBtnGhost.vue.js +21 -21
- package/dist/components/PlBtnGhost/PlBtnGhost.vue.js.map +1 -1
- package/dist/components/PlBtnGroup/PlBtnGroup.vue.js +34 -34
- package/dist/components/PlBtnGroup/PlBtnGroup.vue.js.map +1 -1
- package/dist/components/PlBtnLink/PlBtnLink.vue.js +12 -12
- package/dist/components/PlBtnLink/PlBtnLink.vue.js.map +1 -1
- package/dist/components/PlBtnPrimary/PlBtnPrimary.vue.js.map +1 -1
- package/dist/components/PlBtnSecondary/PlBtnSecondary.vue.js.map +1 -1
- package/dist/components/PlBtnSplit/PlBtnSplit.vue.js +31 -31
- package/dist/components/PlBtnSplit/PlBtnSplit.vue.js.map +1 -1
- package/dist/components/PlChartHistogram/PlChartHistogram.vue2.js +18 -18
- package/dist/components/PlChartHistogram/PlChartHistogram.vue2.js.map +1 -1
- package/dist/components/PlChartStackedBar/Legends.vue2.js.map +1 -1
- package/dist/components/PlChartStackedBar/PlChartStackedBar.vue2.js +15 -15
- package/dist/components/PlChartStackedBar/PlChartStackedBar.vue2.js.map +1 -1
- package/dist/components/PlChartStackedBar/PlChartStackedBarCompact.vue2.js.map +1 -1
- package/dist/components/PlChartStackedBar/StackedRow.vue2.js.map +1 -1
- package/dist/components/PlChartStackedBar/StackedRowCompact.vue2.js.map +1 -1
- package/dist/components/PlCheckbox/PlCheckbox.vue.js +13 -13
- package/dist/components/PlCheckbox/PlCheckbox.vue.js.map +1 -1
- package/dist/components/PlCheckbox/PlCheckboxBase.vue.js +6 -6
- package/dist/components/PlCheckbox/PlCheckboxBase.vue.js.map +1 -1
- package/dist/components/PlCheckboxGroup/PlCheckboxGroup.vue.js +28 -28
- package/dist/components/PlCheckboxGroup/PlCheckboxGroup.vue.js.map +1 -1
- package/dist/components/PlChip/PlChip.vue.js +20 -20
- package/dist/components/PlChip/PlChip.vue.js.map +1 -1
- package/dist/components/PlClipboard/PlClipboard.vue2.js.map +1 -1
- package/dist/components/PlConfirmDialog.vue.js +14 -14
- package/dist/components/PlConfirmDialog.vue.js.map +1 -1
- package/dist/components/PlDialogModal/PlDialogModal.vue.js +30 -30
- package/dist/components/PlDialogModal/PlDialogModal.vue.js.map +1 -1
- package/dist/components/PlDropdown/OptionList.vue.js +40 -40
- package/dist/components/PlDropdown/OptionList.vue.js.map +1 -1
- package/dist/components/PlDropdown/PlDropdown.vue.d.ts +8 -0
- package/dist/components/PlDropdown/PlDropdown.vue.js +102 -95
- package/dist/components/PlDropdown/PlDropdown.vue.js.map +1 -1
- package/dist/components/PlDropdownLegacy/PlDropdownLegacy.vue.js +95 -93
- package/dist/components/PlDropdownLegacy/PlDropdownLegacy.vue.js.map +1 -1
- package/dist/components/PlDropdownLine/PlDropdownLine.vue.d.ts +1 -1
- package/dist/components/PlDropdownLine/PlDropdownLine.vue.js +4 -4
- package/dist/components/PlDropdownLine/PlDropdownLine.vue.js.map +1 -1
- package/dist/components/PlDropdownLine/ResizableInput.vue.js +12 -12
- package/dist/components/PlDropdownLine/ResizableInput.vue.js.map +1 -1
- package/dist/components/PlDropdownMulti/PlDropdownMulti.vue.d.ts +4 -0
- package/dist/components/PlDropdownMulti/PlDropdownMulti.vue.js +88 -82
- package/dist/components/PlDropdownMulti/PlDropdownMulti.vue.js.map +1 -1
- package/dist/components/PlDropdownMultiRef/PlDropdownMultiRef.vue.d.ts +1 -1
- package/dist/components/PlDropdownMultiRef/PlDropdownMultiRef.vue.js.map +1 -1
- package/dist/components/PlDropdownRef/PlDropdownRef.vue.js +11 -11
- package/dist/components/PlDropdownRef/PlDropdownRef.vue.js.map +1 -1
- package/dist/components/PlEditableTitle/PlEditableTitle.vue.d.ts +1 -1
- package/dist/components/PlEditableTitle/PlEditableTitle.vue.js +36 -36
- package/dist/components/PlEditableTitle/PlEditableTitle.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 +101 -76
- package/dist/components/PlElementList/PlElementListItem.vue2.js.map +1 -1
- package/dist/components/PlErrorAlert/PlErrorAlert.vue2.js.map +1 -1
- package/dist/components/PlErrorBoundary/PlErrorBoundary.vue.js.map +1 -1
- package/dist/components/PlFileDialog/Local.vue.js +24 -24
- package/dist/components/PlFileDialog/Local.vue.js.map +1 -1
- package/dist/components/PlFileDialog/PlFileDialog.vue.js +38 -38
- package/dist/components/PlFileDialog/PlFileDialog.vue.js.map +1 -1
- package/dist/components/PlFileDialog/Remote.vue.js +2 -2
- package/dist/components/PlFileDialog/Remote.vue.js.map +1 -1
- package/dist/components/PlFileDialog/Shortcuts.vue2.js +4 -4
- package/dist/components/PlFileDialog/Shortcuts.vue2.js.map +1 -1
- package/dist/components/PlFileInput/PlFileInput.vue.d.ts +1 -1
- package/dist/components/PlFileInput/PlFileInput.vue.js +78 -76
- package/dist/components/PlFileInput/PlFileInput.vue.js.map +1 -1
- package/dist/components/PlIcon16/PlIcon16.vue2.js.map +1 -1
- package/dist/components/PlIcon24/PlIcon24.vue2.js.map +1 -1
- package/dist/components/PlLoaderCircular/PlLoaderCircular.vue.js +11 -11
- package/dist/components/PlLoaderCircular/PlLoaderCircular.vue.js.map +1 -1
- package/dist/components/PlLogView/PlLogView.vue.js +62 -60
- package/dist/components/PlLogView/PlLogView.vue.js.map +1 -1
- package/dist/components/PlNotificationAlert/PlNotificationAlert.vue.js +22 -22
- package/dist/components/PlNotificationAlert/PlNotificationAlert.vue.js.map +1 -1
- package/dist/components/PlNumberField/PlNumberField.vue.d.ts +6 -1
- package/dist/components/PlNumberField/PlNumberField.vue.js +66 -60
- package/dist/components/PlNumberField/PlNumberField.vue.js.map +1 -1
- package/dist/components/PlProgressBar/PlProgressBar.vue.js +12 -12
- package/dist/components/PlProgressBar/PlProgressBar.vue.js.map +1 -1
- package/dist/components/PlProgressCell/PlProgressCell.vue.js +20 -20
- package/dist/components/PlProgressCell/PlProgressCell.vue.js.map +1 -1
- package/dist/components/PlRadio/PlRadio.vue2.js.map +1 -1
- package/dist/components/PlRadio/PlRadioGroup.vue2.js +8 -8
- package/dist/components/PlRadio/PlRadioGroup.vue2.js.map +1 -1
- package/dist/components/PlSearchField/PlSearchField.vue2.js +19 -19
- package/dist/components/PlSearchField/PlSearchField.vue2.js.map +1 -1
- package/dist/components/PlSectionSeparator/PlSectionSeparator.vue2.js +8 -8
- package/dist/components/PlSectionSeparator/PlSectionSeparator.vue2.js.map +1 -1
- package/dist/components/PlSidebar/PlSidebarGroup.vue2.js.map +1 -1
- package/dist/components/PlSidebar/PlSidebarItem.vue2.js.map +1 -1
- package/dist/components/PlSlideModal/PlPureSlideModal.vue.js +5 -3
- package/dist/components/PlSlideModal/PlPureSlideModal.vue.js.map +1 -1
- package/dist/components/PlSlideModal/PlSlideModal.vue2.js.map +1 -1
- package/dist/components/PlSplash/PlSplash.vue.js +16 -16
- package/dist/components/PlSplash/PlSplash.vue.js.map +1 -1
- package/dist/components/PlStatusTag/PlStatusTag.vue.js +7 -7
- package/dist/components/PlStatusTag/PlStatusTag.vue.js.map +1 -1
- package/dist/components/PlSvg/PlSvg.vue2.js.map +1 -1
- package/dist/components/PlTabs/PlTabs.vue.js +18 -18
- package/dist/components/PlTabs/PlTabs.vue.js.map +1 -1
- package/dist/components/PlTabs/Tab.vue.js +9 -9
- package/dist/components/PlTabs/Tab.vue.js.map +1 -1
- package/dist/components/PlTextArea/PlTextArea.vue.js +55 -53
- 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 +66 -60
- package/dist/components/PlTextField/PlTextField.vue.js.map +1 -1
- package/dist/components/PlToggleSwitch/PlToggleSwitch.vue.js +14 -14
- package/dist/components/PlToggleSwitch/PlToggleSwitch.vue.js.map +1 -1
- package/dist/components/PlTooltip/Beak.vue.js +2 -2
- package/dist/components/PlTooltip/Beak.vue.js.map +1 -1
- package/dist/components/PlTooltip/PlTooltip.vue.js +50 -50
- package/dist/components/PlTooltip/PlTooltip.vue.js.map +1 -1
- package/dist/components/Scrollable.vue.js.map +1 -1
- package/dist/components/Slider.vue.js +35 -35
- package/dist/components/Slider.vue.js.map +1 -1
- package/dist/components/SliderRange.vue.js +47 -47
- package/dist/components/SliderRange.vue.js.map +1 -1
- package/dist/components/SliderRangeTriple.vue.js +47 -47
- package/dist/components/SliderRangeTriple.vue.js.map +1 -1
- package/dist/components/TabItem.vue.js.map +1 -1
- package/dist/components/ThemeSwitcher.vue.js +2 -2
- package/dist/components/ThemeSwitcher.vue.js.map +1 -1
- package/dist/components/TransitionSlidePanel.vue.js.map +1 -1
- package/dist/components/VScroll.vue.js.map +1 -1
- package/dist/components/contextMenu/Menu.vue2.js +12 -12
- package/dist/components/contextMenu/Menu.vue2.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/index.js +1 -1
- package/dist/layout/PlBlockPage/PlBlockPage.vue.js +27 -27
- package/dist/layout/PlBlockPage/PlBlockPage.vue.js.map +1 -1
- package/dist/layout/PlContainer/PlContainer.vue.js +10 -10
- package/dist/layout/PlContainer/PlContainer.vue.js.map +1 -1
- package/dist/layout/PlGrid/PlGrid.vue.js.map +1 -1
- package/dist/layout/PlRow/PlRow.vue.js +8 -8
- package/dist/layout/PlRow/PlRow.vue.js.map +1 -1
- package/dist/layout/PlSpacer/PlSpacer.vue.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.vue3.js +7 -0
- package/dist/utils/DoubleContour.vue3.js.map +1 -0
- package/dist/utils/DropdownOverlay/DropdownOverlay.vue.js.map +1 -1
- package/dist/utils/PlCloseModalBtn.vue.js +2 -2
- package/dist/utils/PlCloseModalBtn.vue.js.map +1 -1
- package/dist/utils/TextLabel.vue.js.map +1 -1
- package/package.json +5 -5
- 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/utils/DoubleContour.vue2.js +0 -7
- package/dist/utils/DoubleContour.vue2.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAutocomplete.vue.js","sources":["../../../src/components/PlAutocomplete/PlAutocomplete.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * A component for selecting one value from a big list of options using string search request\n */\nexport default {\n name: 'PlAutocomplete',\n};\n</script>\n\n<script lang=\"ts\" setup generic=\"M = unknown\">\nimport './pl-autocomplete.scss';\nimport { computed, reactive, ref, unref, useTemplateRef, watch, watchPostEffect } from 'vue';\nimport { tap } from '../../helpers/functions';\nimport { PlTooltip } from '../PlTooltip';\nimport DoubleContour from '../../utils/DoubleContour.vue';\nimport { useLabelNotch } from '../../utils/useLabelNotch';\nimport type { ListOption, ListOptionNormalized } from '../../types';\nimport { deepEqual } from '../../helpers/objects';\nimport DropdownListItem from '../DropdownListItem.vue';\nimport LongText from '../LongText.vue';\nimport { normalizeListOptions } from '../../helpers/utils';\nimport { PlIcon16 } from '../PlIcon16';\nimport { PlMaskIcon24 } from '../PlMaskIcon24';\nimport { DropdownOverlay } from '../../utils/DropdownOverlay';\nimport { refDebounced } from '@vueuse/core';\nimport { useWatchFetch } from '../../composition/useWatchFetch.ts';\nimport { getErrorMessage } from '../../helpers/error.ts';\nimport type { ListOptionBase } from '@platforma-sdk/model';\nimport { PlSvg } from '../PlSvg';\nimport SvgRequired from '../../assets/images/required.svg?raw';\n\n/**\n * The current selected value.\n */\nconst model = defineModel<M>({ required: true });\n\nconst props = withDefaults(\n defineProps<{\n /**\n * Lambda for requesting of available options for the dropdown by search string.\n */\n optionsSearch: (s: string) => Promise<ListOption<M>[]>;\n /**\n * Lambda for requesting of corresponding option for current model value. If empty, optionsSearch is used for this.\n */\n modelSearch?: (v: M) => Promise<ListOption<M>>;\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 * A helper text displayed below the dropdown when there are no options yet or options is undefined (optional).\n */\n loadingOptionsHelper?: 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 * Enables a button to clear the selected value (default: false)\n */\n clearable?: boolean;\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 * Custom icon (16px) class for the dropdown arrow (optional)\n */\n arrowIcon?: string;\n /**\n * Custom icon (24px) class for the dropdown arrow (optional)\n */\n arrowIconLarge?: string;\n /**\n * Option list item size\n */\n optionSize?: 'small' | 'medium';\n /**\n * Formatter for the selected value if its label is absent\n */\n formatValue?: (value: M) => string;\n }>(),\n {\n modelSearch: undefined,\n label: '',\n helper: undefined,\n loadingOptionsHelper: undefined,\n error: undefined,\n placeholder: '...',\n clearable: false,\n required: false,\n disabled: false,\n arrowIcon: undefined,\n arrowIconLarge: undefined,\n optionSize: 'small',\n formatValue: (v: M) => String(v),\n },\n);\n\nconst slots = defineSlots<{\n [key: string]: unknown;\n}>();\n\nconst rootRef = ref<HTMLElement | undefined>();\nconst input = ref<HTMLInputElement | undefined>();\n\nconst overlayRef = useTemplateRef('overlay');\n\nconst search = ref<string | null>(null);\nconst data = reactive({\n activeIndex: -1,\n open: false,\n});\n\nconst findActiveIndex = () =>\n tap(\n renderedOptionsRef.value.findIndex((o) => deepEqual(o.value, model.value)),\n (v) => (v < 0 ? 0 : v),\n );\n\nconst updateActive = () => (data.activeIndex = findActiveIndex());\n\nconst loadedOptionsRef = ref<ListOption<M>[]>([]);\nconst modelOptionRef = ref<ListOptionNormalized<M> | undefined>(); // list of 1 option that is selected or empty, to keep selected label\n\nconst renderedOptionsRef = computed(() => {\n return normalizeListOptions(loadedOptionsRef.value).map((opt, index) => ({\n ...opt,\n index,\n isSelected: index === selectedIndex.value,\n isActive: index === data.activeIndex,\n })) as (ListOptionBase<M> & { index: number; isSelected: boolean; isActive: boolean })[];\n});\nconst isLoadingOptions = ref<boolean>(true);\nconst isLoadingError = ref<boolean>(false);\n\nconst isDisabled = computed(() => {\n return props.disabled;\n});\n\nconst selectedIndex = computed(() => {\n return loadedOptionsRef.value.findIndex((o) => deepEqual(o.value, model.value));\n});\n\nconst computedError = computed(() => {\n if (isLoadingOptions.value) {\n return undefined;\n }\n\n if (props.error) {\n return getErrorMessage(props.error);\n }\n\n if (isLoadingError.value) {\n return 'Data loading error';\n }\n\n return undefined;\n});\n\nconst textValue = computed(() => {\n const modelOption = unref(modelOptionRef);\n const options = unref(renderedOptionsRef);\n\n const item: ListOptionNormalized | undefined = modelOption ?? options.find((o) => deepEqual(o.value, model.value)) ?? options.find((o) => deepEqual(o.value, model.value));\n\n return item?.label || (model.value ? props.formatValue(model.value) : '');\n});\n\nconst computedPlaceholder = computed(() => {\n if (!data.open && model.value) {\n return '';\n }\n\n return model.value ? String(textValue.value) : props.placeholder;\n});\n\nconst hasValue = computed(() => {\n return model.value !== undefined && model.value !== null;\n});\n\nconst tabindex = computed(() => (isDisabled.value ? undefined : '0'));\n\nconst selectOption = (v: ListOptionBase<M> & { index: number } | undefined) => {\n model.value = v?.value as M;\n modelOptionRef.value = v;\n search.value = null;\n data.open = false;\n rootRef?.value?.focus();\n};\n\nconst clear = () => {\n model.value = undefined as M;\n modelOptionRef.value = undefined;\n};\n\nconst setFocusOnInput = () => input.value?.focus();\n\nconst toggleOpen = () => {\n data.open = !data.open;\n};\n\nwatch(() => data.open, (v) => {\n search.value = v ? '' : null;\n});\n\nconst onInputFocus = () => {\n data.open = true;\n};\n\nconst onFocusOut = (event: FocusEvent) => {\n const relatedTarget = event.relatedTarget as Node | null;\n\n if (!rootRef.value?.contains(relatedTarget) && !overlayRef.value?.listRef?.contains(relatedTarget)) {\n search.value = null;\n data.open = false;\n }\n};\n\nconst handleKeydown = (e: { code: string; preventDefault(): void }) => {\n if (!['ArrowDown', 'ArrowUp', 'Enter', 'Escape'].includes(e.code)) {\n return;\n } else {\n e.preventDefault();\n }\n\n const { open, activeIndex } = data;\n\n if (!open) {\n if (e.code === 'Enter') {\n data.open = true;\n search.value = '';\n }\n return;\n }\n\n if (e.code === 'Escape') {\n data.open = false;\n search.value = null;\n rootRef.value?.focus();\n }\n\n const options = unref(renderedOptionsRef);\n\n const { length } = options;\n\n if (!length) {\n return;\n }\n\n if (e.code === 'Enter') {\n selectOption(options.find((it) => it.index === activeIndex));\n }\n\n const localIndex = options.findIndex((it) => it.index === activeIndex) ?? -1;\n\n const delta = e.code === 'ArrowDown' ? 1 : e.code === 'ArrowUp' ? -1 : 0;\n\n const newIndex = Math.abs(localIndex + delta + length) % length;\n\n data.activeIndex = renderedOptionsRef.value[newIndex].index ?? -1;\n};\n\nuseLabelNotch(rootRef);\n\nwatch(() => model.value, updateActive, { immediate: true });\n\nwatch(\n () => data.open,\n (open) => (open ? input.value?.focus() : ''),\n);\n\nwatchPostEffect(() => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n search.value; // to watch\n\n if (data.activeIndex >= 0 && data.open) {\n overlayRef.value?.scrollIntoActive();\n }\n});\n\nconst searchDebounced = refDebounced(search, 300, { maxWait: 1000 });\n\nconst optionsRequest = useWatchFetch(() => searchDebounced.value, async (v) => {\n if (v !== null) { // search is null when dropdown is closed;\n return props.optionsSearch(v);\n }\n return undefined;\n});\n\nconst modelOptionRequest = useWatchFetch(() => model.value, async (v) => {\n if (v && !deepEqual(modelOptionRef.value?.value, v)) { // load label for selected value if it was updated from outside the component\n if (props.modelSearch) {\n return props.modelSearch(v);\n }\n return (await props.optionsSearch(String(v)))?.[0];\n }\n return modelOptionRef.value;\n});\n\nwatch(() => optionsRequest.value, (result) => {\n if (result) {\n loadedOptionsRef.value = result;\n if (search.value !== null) {\n isLoadingError.value = false;\n }\n }\n});\n\nwatch(() => modelOptionRequest.value, (result) => {\n if (result) {\n modelOptionRef.value = normalizeListOptions([result])[0];\n }\n});\n\nwatch(() => optionsRequest.error, (err) => {\n if (err) {\n isLoadingError.value = Boolean(err);\n }\n});\n\nwatch(() => optionsRequest.loading || modelOptionRequest.loading, (loading) => {\n isLoadingOptions.value = loading;\n});\n</script>\n\n<template>\n <div class=\"pl-autocomplete__envelope\" @click.stop=\"setFocusOnInput\">\n <div\n ref=\"rootRef\"\n :tabindex=\"tabindex\"\n class=\"pl-autocomplete\"\n :class=\"{ open: data.open, error: Boolean(computedError), disabled: isDisabled }\"\n @keydown=\"handleKeydown\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-autocomplete__container\">\n <div class=\"pl-autocomplete__field\">\n <input\n ref=\"input\"\n v-model=\"search\"\n type=\"text\"\n tabindex=\"-1\"\n :disabled=\"isDisabled\"\n :placeholder=\"computedPlaceholder\"\n spellcheck=\"false\"\n autocomplete=\"chrome-off\"\n @focus=\"onInputFocus\"\n />\n\n <div v-if=\"!data.open\" class=\"input-value\">\n <LongText> {{ textValue }} </LongText>\n </div>\n\n <div class=\"pl-autocomplete__controls\">\n <PlMaskIcon24 v-if=\"isLoadingOptions\" name=\"loading\" />\n <PlIcon16 v-if=\"clearable && hasValue\" class=\"clear\" name=\"delete-clear\" @click.stop=\"clear\" />\n <slot name=\"append\" />\n <div class=\"pl-autocomplete__arrow-wrapper\" @click.stop=\"toggleOpen\">\n <div v-if=\"arrowIconLarge\" class=\"arrow-icon\" :class=\"[`icon-24 ${arrowIconLarge}`]\" />\n <div v-else-if=\"arrowIcon\" class=\"arrow-icon\" :class=\"[`icon-16 ${arrowIcon}`]\" />\n <div v-else 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 v-if=\"data.open\" ref=\"overlay\" :root=\"rootRef\" class=\"pl-autocomplete__options\" tabindex=\"-1\" :gap=\"3\">\n <DropdownListItem\n v-for=\"(item, index) in renderedOptionsRef\"\n :key=\"index\"\n :option=\"item\"\n :is-selected=\"item.isSelected\"\n :is-hovered=\"item.isActive\"\n :size=\"optionSize\"\n @click.stop=\"selectOption(item)\"\n />\n <div v-if=\"!renderedOptionsRef.length\" class=\"nothing-found\">Nothing found</div>\n </DropdownOverlay>\n <DoubleContour class=\"pl-autocomplete__contour\" />\n </div>\n </div>\n <div v-if=\"computedError\" class=\"pl-autocomplete__error\">{{ computedError }}</div>\n <div v-else-if=\"isLoadingOptions && loadingOptionsHelper\" class=\"pl-autocomplete__helper\">{{ loadingOptionsHelper }}</div>\n <div v-else-if=\"helper\" class=\"pl-autocomplete__helper\">{{ helper }}</div>\n </div>\n</template>\n"],"names":["__default__","model","_useModel","props","__props","slots","_useSlots","rootRef","ref","input","overlayRef","useTemplateRef","search","data","reactive","findActiveIndex","tap","renderedOptionsRef","o","deepEqual","v","updateActive","loadedOptionsRef","modelOptionRef","computed","normalizeListOptions","opt","index","selectedIndex","isLoadingOptions","isLoadingError","isDisabled","computedError","getErrorMessage","textValue","modelOption","unref","options","item","computedPlaceholder","hasValue","tabindex","selectOption","_a","clear","setFocusOnInput","toggleOpen","watch","onInputFocus","onFocusOut","event","relatedTarget","_c","_b","handleKeydown","open","activeIndex","length","it","localIndex","delta","newIndex","useLabelNotch","watchPostEffect","searchDebounced","refDebounced","optionsRequest","useWatchFetch","modelOptionRequest","result","err","loading"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PlAutocomplete.vue.js","sources":["../../../src/components/PlAutocomplete/PlAutocomplete.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * A component for selecting one value from a big list of options using string search request\n */\nexport default {\n name: 'PlAutocomplete',\n};\n</script>\n\n<script lang=\"ts\" setup generic=\"M = unknown\">\nimport './pl-autocomplete.scss';\nimport { computed, reactive, ref, unref, useTemplateRef, watch, watchPostEffect } from 'vue';\nimport { tap } from '../../helpers/functions';\nimport { PlTooltip } from '../PlTooltip';\nimport DoubleContour from '../../utils/DoubleContour.vue';\nimport { useLabelNotch } from '../../utils/useLabelNotch';\nimport type { ListOption, ListOptionNormalized } from '../../types';\nimport { deepEqual } from '../../helpers/objects';\nimport DropdownListItem from '../DropdownListItem.vue';\nimport LongText from '../LongText.vue';\nimport { normalizeListOptions } from '../../helpers/utils';\nimport { PlIcon16 } from '../PlIcon16';\nimport { PlMaskIcon24 } from '../PlMaskIcon24';\nimport { DropdownOverlay } from '../../utils/DropdownOverlay';\nimport { refDebounced } from '@vueuse/core';\nimport { useWatchFetch } from '../../composition/useWatchFetch.ts';\nimport { getErrorMessage } from '../../helpers/error.ts';\nimport type { ListOptionBase } from '@platforma-sdk/model';\nimport { PlSvg } from '../PlSvg';\nimport SvgRequired from '../../assets/images/required.svg?raw';\n\n/**\n * The current selected value.\n */\nconst model = defineModel<M>({ required: true });\n\nconst props = withDefaults(\n defineProps<{\n /**\n * Lambda for requesting of available options for the dropdown by search string.\n */\n optionsSearch: (s: string) => Promise<ListOption<M>[]>;\n /**\n * Lambda for requesting of corresponding option for current model value. If empty, optionsSearch is used for this.\n */\n modelSearch?: (v: M) => Promise<ListOption<M>>;\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 * A helper text displayed below the dropdown when there are no options yet or options is undefined (optional).\n */\n loadingOptionsHelper?: 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 * Enables a button to clear the selected value (default: false)\n */\n clearable?: boolean;\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 * Custom icon (16px) class for the dropdown arrow (optional)\n */\n arrowIcon?: string;\n /**\n * Custom icon (24px) class for the dropdown arrow (optional)\n */\n arrowIconLarge?: string;\n /**\n * Option list item size\n */\n optionSize?: 'small' | 'medium';\n /**\n * Formatter for the selected value if its label is absent\n */\n formatValue?: (value: M) => 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 modelSearch: undefined,\n label: '',\n helper: undefined,\n loadingOptionsHelper: undefined,\n error: undefined,\n placeholder: '...',\n clearable: false,\n required: false,\n disabled: false,\n arrowIcon: undefined,\n arrowIconLarge: undefined,\n optionSize: 'small',\n formatValue: (v: M) => String(v),\n groupPosition: undefined,\n },\n);\n\nconst slots = defineSlots<{\n [key: string]: unknown;\n}>();\n\nconst rootRef = ref<HTMLElement | undefined>();\nconst input = ref<HTMLInputElement | undefined>();\n\nconst overlayRef = useTemplateRef('overlay');\n\nconst search = ref<string | null>(null);\nconst data = reactive({\n activeIndex: -1,\n open: false,\n});\n\nconst findActiveIndex = () =>\n tap(\n renderedOptionsRef.value.findIndex((o) => deepEqual(o.value, model.value)),\n (v) => (v < 0 ? 0 : v),\n );\n\nconst updateActive = () => (data.activeIndex = findActiveIndex());\n\nconst loadedOptionsRef = ref<ListOption<M>[]>([]);\nconst modelOptionRef = ref<ListOptionNormalized<M> | undefined>(); // list of 1 option that is selected or empty, to keep selected label\n\nconst renderedOptionsRef = computed(() => {\n return normalizeListOptions(loadedOptionsRef.value).map((opt, index) => ({\n ...opt,\n index,\n isSelected: index === selectedIndex.value,\n isActive: index === data.activeIndex,\n })) as (ListOptionBase<M> & { index: number; isSelected: boolean; isActive: boolean })[];\n});\nconst isLoadingOptions = ref<boolean>(true);\nconst isLoadingError = ref<boolean>(false);\n\nconst isDisabled = computed(() => {\n return props.disabled;\n});\n\nconst selectedIndex = computed(() => {\n return loadedOptionsRef.value.findIndex((o) => deepEqual(o.value, model.value));\n});\n\nconst computedError = computed(() => {\n if (isLoadingOptions.value) {\n return undefined;\n }\n\n if (props.error) {\n return getErrorMessage(props.error);\n }\n\n if (isLoadingError.value) {\n return 'Data loading error';\n }\n\n return undefined;\n});\n\nconst textValue = computed(() => {\n const modelOption = unref(modelOptionRef);\n const options = unref(renderedOptionsRef);\n\n const item: ListOptionNormalized | undefined = modelOption ?? options.find((o) => deepEqual(o.value, model.value)) ?? options.find((o) => deepEqual(o.value, model.value));\n\n return item?.label || (model.value ? props.formatValue(model.value) : '');\n});\n\nconst computedPlaceholder = computed(() => {\n if (!data.open && model.value) {\n return '';\n }\n\n return model.value ? String(textValue.value) : props.placeholder;\n});\n\nconst hasValue = computed(() => {\n return model.value !== undefined && model.value !== null;\n});\n\nconst tabindex = computed(() => (isDisabled.value ? undefined : '0'));\n\nconst selectOption = (v: ListOptionBase<M> & { index: number } | undefined) => {\n model.value = v?.value as M;\n modelOptionRef.value = v;\n search.value = null;\n data.open = false;\n rootRef?.value?.focus();\n};\n\nconst clear = () => {\n model.value = undefined as M;\n modelOptionRef.value = undefined;\n};\n\nconst setFocusOnInput = () => input.value?.focus();\n\nconst toggleOpen = () => {\n data.open = !data.open;\n};\n\nwatch(() => data.open, (v) => {\n search.value = v ? '' : null;\n});\n\nconst onInputFocus = () => {\n data.open = true;\n};\n\nconst onFocusOut = (event: FocusEvent) => {\n const relatedTarget = event.relatedTarget as Node | null;\n\n if (!rootRef.value?.contains(relatedTarget) && !overlayRef.value?.listRef?.contains(relatedTarget)) {\n search.value = null;\n data.open = false;\n }\n};\n\nconst handleKeydown = (e: { code: string; preventDefault(): void }) => {\n if (!['ArrowDown', 'ArrowUp', 'Enter', 'Escape'].includes(e.code)) {\n return;\n } else {\n e.preventDefault();\n }\n\n const { open, activeIndex } = data;\n\n if (!open) {\n if (e.code === 'Enter') {\n data.open = true;\n search.value = '';\n }\n return;\n }\n\n if (e.code === 'Escape') {\n data.open = false;\n search.value = null;\n rootRef.value?.focus();\n }\n\n const options = unref(renderedOptionsRef);\n\n const { length } = options;\n\n if (!length) {\n return;\n }\n\n if (e.code === 'Enter') {\n selectOption(options.find((it) => it.index === activeIndex));\n }\n\n const localIndex = options.findIndex((it) => it.index === activeIndex) ?? -1;\n\n const delta = e.code === 'ArrowDown' ? 1 : e.code === 'ArrowUp' ? -1 : 0;\n\n const newIndex = Math.abs(localIndex + delta + length) % length;\n\n data.activeIndex = renderedOptionsRef.value[newIndex].index ?? -1;\n};\n\nuseLabelNotch(rootRef);\n\nwatch(() => model.value, updateActive, { immediate: true });\n\nwatch(\n () => data.open,\n (open) => (open ? input.value?.focus() : ''),\n);\n\nwatchPostEffect(() => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n search.value; // to watch\n\n if (data.activeIndex >= 0 && data.open) {\n overlayRef.value?.scrollIntoActive();\n }\n});\n\nconst searchDebounced = refDebounced(search, 300, { maxWait: 1000 });\n\nconst optionsRequest = useWatchFetch(() => searchDebounced.value, async (v) => {\n if (v !== null) { // search is null when dropdown is closed;\n return props.optionsSearch(v);\n }\n return undefined;\n});\n\nconst modelOptionRequest = useWatchFetch(() => model.value, async (v) => {\n if (v && !deepEqual(modelOptionRef.value?.value, v)) { // load label for selected value if it was updated from outside the component\n if (props.modelSearch) {\n return props.modelSearch(v);\n }\n return (await props.optionsSearch(String(v)))?.[0];\n }\n return modelOptionRef.value;\n});\n\nwatch(() => optionsRequest.value, (result) => {\n if (result) {\n loadedOptionsRef.value = result;\n if (search.value !== null) {\n isLoadingError.value = false;\n }\n }\n});\n\nwatch(() => modelOptionRequest.value, (result) => {\n if (result) {\n modelOptionRef.value = normalizeListOptions([result])[0];\n }\n});\n\nwatch(() => optionsRequest.error, (err) => {\n if (err) {\n isLoadingError.value = Boolean(err);\n }\n});\n\nwatch(() => optionsRequest.loading || modelOptionRequest.loading, (loading) => {\n isLoadingOptions.value = loading;\n});\n</script>\n\n<template>\n <div class=\"pl-autocomplete__envelope\" @click.stop=\"setFocusOnInput\">\n <div\n ref=\"rootRef\"\n :tabindex=\"tabindex\"\n class=\"pl-autocomplete\"\n :class=\"{ open: data.open, error: Boolean(computedError), disabled: isDisabled }\"\n @keydown=\"handleKeydown\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-autocomplete__container\">\n <div class=\"pl-autocomplete__field\">\n <input\n ref=\"input\"\n v-model=\"search\"\n type=\"text\"\n tabindex=\"-1\"\n :disabled=\"isDisabled\"\n :placeholder=\"computedPlaceholder\"\n spellcheck=\"false\"\n autocomplete=\"chrome-off\"\n @focus=\"onInputFocus\"\n />\n\n <div v-if=\"!data.open\" class=\"input-value\">\n <LongText> {{ textValue }} </LongText>\n </div>\n\n <div class=\"pl-autocomplete__controls\">\n <PlMaskIcon24 v-if=\"isLoadingOptions\" name=\"loading\" />\n <PlIcon16 v-if=\"clearable && hasValue\" class=\"clear\" name=\"delete-clear\" @click.stop=\"clear\" />\n <slot name=\"append\" />\n <div class=\"pl-autocomplete__arrow-wrapper\" @click.stop=\"toggleOpen\">\n <div v-if=\"arrowIconLarge\" class=\"arrow-icon\" :class=\"[`icon-24 ${arrowIconLarge}`]\" />\n <div v-else-if=\"arrowIcon\" class=\"arrow-icon\" :class=\"[`icon-16 ${arrowIcon}`]\" />\n <div v-else 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 v-if=\"data.open\" ref=\"overlay\" :root=\"rootRef\" class=\"pl-autocomplete__options\" tabindex=\"-1\" :gap=\"3\">\n <DropdownListItem\n v-for=\"(item, index) in renderedOptionsRef\"\n :key=\"index\"\n :option=\"item\"\n :is-selected=\"item.isSelected\"\n :is-hovered=\"item.isActive\"\n :size=\"optionSize\"\n @click.stop=\"selectOption(item)\"\n />\n <div v-if=\"!renderedOptionsRef.length\" class=\"nothing-found\">Nothing found</div>\n </DropdownOverlay>\n <DoubleContour class=\"pl-autocomplete__contour\" :group-position=\"groupPosition\" />\n </div>\n </div>\n <div v-if=\"computedError\" class=\"pl-autocomplete__error\">{{ computedError }}</div>\n <div v-else-if=\"isLoadingOptions && loadingOptionsHelper\" class=\"pl-autocomplete__helper\">{{ loadingOptionsHelper }}</div>\n <div v-else-if=\"helper\" class=\"pl-autocomplete__helper\">{{ helper }}</div>\n </div>\n</template>\n"],"names":["__default__","model","_useModel","props","__props","slots","_useSlots","rootRef","ref","input","overlayRef","useTemplateRef","search","data","reactive","findActiveIndex","tap","renderedOptionsRef","o","deepEqual","v","updateActive","loadedOptionsRef","modelOptionRef","computed","normalizeListOptions","opt","index","selectedIndex","isLoadingOptions","isLoadingError","isDisabled","computedError","getErrorMessage","textValue","modelOption","unref","options","item","computedPlaceholder","hasValue","tabindex","selectOption","_a","clear","setFocusOnInput","toggleOpen","watch","onInputFocus","onFocusOut","event","relatedTarget","_c","_b","handleKeydown","open","activeIndex","length","it","localIndex","delta","newIndex","useLabelNotch","watchPostEffect","searchDebounced","refDebounced","optionsRequest","useWatchFetch","modelOptionRequest","result","err","loading","_createElementBlock","_createElementVNode","_normalizeClass","_hoisted_2","_hoisted_3","$event","_openBlock","_hoisted_5","_createVNode","LongText","_hoisted_6","_createBlock","_unref","PlMaskIcon24","PlIcon16","_renderSlot","_ctx","_hoisted_7","_hoisted_8","PlSvg","SvgRequired","PlTooltip","DropdownOverlay","_Fragment","_renderList","DropdownListItem","_withModifiers","_hoisted_9","DoubleContour","_hoisted_10","_toDisplayString","_hoisted_11","_hoisted_12"],"mappings":"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"}
|
|
@@ -88,6 +88,10 @@ declare const _default: <M = unknown>(__VLS_props: NonNullable<Awaited<typeof __
|
|
|
88
88
|
* The text to display when no options are found.
|
|
89
89
|
*/
|
|
90
90
|
emptyOptionsText?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Makes some of corners not rounded
|
|
93
|
+
* */
|
|
94
|
+
groupPosition?: "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "middle";
|
|
91
95
|
} & Partial<{}>> & import('vue').PublicProps;
|
|
92
96
|
expose(exposed: import('vue').ShallowUnwrapRef<{}>): void;
|
|
93
97
|
attrs: any;
|
|
@@ -1,35 +1,37 @@
|
|
|
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 z, useTemplateRef as se, reactive as ae, watch as L, computed as u, toRef as ie, unref as i, createElementBlock as c, openBlock as s, createElementVNode as d, createCommentVNode as f, normalizeClass as ue, createBlock as m, createVNode as ce, withDirectives as de, vModelText as pe, Fragment as E, renderList as F, withModifiers as T, withCtx as V, createTextVNode as U, toDisplayString as v, renderSlot as K } from "vue";
|
|
3
4
|
|
|
4
5
|
import fe from "canonicalize";
|
|
5
|
-
import { useWatchFetch as
|
|
6
|
-
import { getErrorMessage as
|
|
7
|
-
import { deepEqual as
|
|
6
|
+
import { useWatchFetch as W } from "../../composition/useWatchFetch.js";
|
|
7
|
+
import { getErrorMessage as B } from "../../helpers/error.js";
|
|
8
|
+
import { deepEqual as I, deepIncludes as H } 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
|
-
import
|
|
14
|
+
import j 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
|
+
}, xe = { class: "pl-autocomplete-multi__controls" }, Ce = { key: 0 }, $e = { class: "pl-autocomplete-multi__open-chips-container" }, Ae = {
|
|
21
23
|
key: 0,
|
|
22
24
|
class: "nothing-found"
|
|
23
|
-
},
|
|
25
|
+
}, Ee = {
|
|
24
26
|
key: 0,
|
|
25
27
|
class: "pl-autocomplete-multi__error"
|
|
26
|
-
},
|
|
28
|
+
}, Fe = {
|
|
27
29
|
key: 1,
|
|
28
30
|
class: "pl-autocomplete-multi__helper"
|
|
29
|
-
},
|
|
31
|
+
}, Te = {
|
|
30
32
|
name: "PlAutocompleteMulti"
|
|
31
|
-
},
|
|
32
|
-
...
|
|
33
|
+
}, Qe = /* @__PURE__ */ ne({
|
|
34
|
+
...Te,
|
|
33
35
|
props: {
|
|
34
36
|
modelValue: { default: () => [] },
|
|
35
37
|
optionsSearch: {},
|
|
@@ -43,11 +45,12 @@ 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
|
-
setup(
|
|
50
|
-
const J = G,
|
|
52
|
+
setup(p, { emit: G }) {
|
|
53
|
+
const J = G, M = (e) => J("update:modelValue", e), Q = re(), n = p, k = z(), b = z(), w = se("overlay"), l = ae({
|
|
51
54
|
search: "",
|
|
52
55
|
activeOption: -1,
|
|
53
56
|
open: !1,
|
|
@@ -56,72 +59,72 @@ const Oe = ["tabindex"], Ve = { class: "pl-autocomplete-multi__container" }, we
|
|
|
56
59
|
L(() => l.open, (e) => {
|
|
57
60
|
e || (l.search = "");
|
|
58
61
|
}, { flush: "sync" });
|
|
59
|
-
const
|
|
62
|
+
const O = u(() => Array.isArray(n.modelValue) ? n.modelValue : []), X = u(() => l.open && n.modelValue.length > 0 ? n.placeholder : n.modelValue.length > 0 ? "" : n.placeholder), D = ie(n, "debounce"), h = W(() => [l.search, l.open, n.sourceId], async ([e, t]) => n.optionsSearch(e), {
|
|
60
63
|
filterWatchResult: ([e, t]) => t,
|
|
61
|
-
debounce:
|
|
62
|
-
}),
|
|
63
|
-
debounce:
|
|
64
|
+
debounce: D
|
|
65
|
+
}), _ = W(() => [n.modelValue, n.sourceId], async ([e]) => n.modelSearch(e), {
|
|
66
|
+
debounce: D
|
|
64
67
|
}), Y = u(() => {
|
|
65
|
-
const e =
|
|
66
|
-
for (const
|
|
67
|
-
const
|
|
68
|
-
o.has(
|
|
68
|
+
const e = _.value ?? [], t = h.value ?? [], o = /* @__PURE__ */ new Set(), r = [], a = (A) => {
|
|
69
|
+
for (const y of A) {
|
|
70
|
+
const g = fe(y.value);
|
|
71
|
+
o.has(g) || (o.add(g), r.push(y));
|
|
69
72
|
}
|
|
70
73
|
};
|
|
71
74
|
return a(e), a(t), r;
|
|
72
|
-
}),
|
|
75
|
+
}), R = u(() => O.value.map((e) => Y.value.find((t) => I(t.value, e))).filter(
|
|
73
76
|
(e) => e !== void 0
|
|
74
|
-
)),
|
|
75
|
-
const e = i(
|
|
76
|
-
return [...
|
|
77
|
+
)), S = u(() => {
|
|
78
|
+
const e = i(O);
|
|
79
|
+
return [...h.value ?? []].map((o) => ({
|
|
77
80
|
...o,
|
|
78
|
-
selected:
|
|
81
|
+
selected: H(e, o.value)
|
|
79
82
|
}));
|
|
80
|
-
}),
|
|
83
|
+
}), x = u(() => h.loading || _.loading), C = u(() => _.value === void 0 ? !0 : n.disabled), Z = u(() => C.value ? void 0 : "0"), ee = () => {
|
|
81
84
|
l.activeOption = 0;
|
|
82
|
-
},
|
|
85
|
+
}, N = (e) => {
|
|
83
86
|
var o;
|
|
84
|
-
const t = i(
|
|
85
|
-
|
|
86
|
-
},
|
|
87
|
+
const t = i(O);
|
|
88
|
+
M(H(t, e) ? t.filter((r) => !I(r, e)) : [...t, e]), n.resetSearchOnSelect && (l.search = ""), (o = b.value) == null || o.focus();
|
|
89
|
+
}, q = (e) => M(i(O).filter((t) => !I(t, e))), oe = () => {
|
|
87
90
|
var e;
|
|
88
|
-
return (e =
|
|
89
|
-
}, te = () => l.open = !l.open,
|
|
91
|
+
return (e = b.value) == null ? void 0 : e.focus();
|
|
92
|
+
}, te = () => l.open = !l.open, P = (e) => {
|
|
90
93
|
var o, r, a;
|
|
91
94
|
const t = e.relatedTarget;
|
|
92
|
-
!((o =
|
|
95
|
+
!((o = k.value) != null && o.contains(t)) && !((a = (r = w.value) == null ? void 0 : r.listRef) != null && a.contains(t)) && (l.open = !1);
|
|
93
96
|
}, le = (e) => {
|
|
94
|
-
var
|
|
97
|
+
var y;
|
|
95
98
|
const { open: t, activeOption: o } = l;
|
|
96
99
|
if (!t) {
|
|
97
100
|
e.code === "Enter" && (l.open = !0);
|
|
98
101
|
return;
|
|
99
102
|
}
|
|
100
|
-
e.code === "Escape" && (l.open = !1, (
|
|
101
|
-
const r = i(
|
|
103
|
+
e.code === "Escape" && (l.open = !1, (y = b.value) == null || y.focus());
|
|
104
|
+
const r = i(S), { 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" && N(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
|
-
var
|
|
108
|
-
return (
|
|
110
|
+
var g;
|
|
111
|
+
return (g = w.value) == null ? void 0 : g.scrollIntoActive();
|
|
109
112
|
});
|
|
110
113
|
};
|
|
111
|
-
he(
|
|
114
|
+
he(k), L(
|
|
112
115
|
() => n.modelValue,
|
|
113
116
|
() => ee(),
|
|
114
117
|
{ immediate: !0 }
|
|
115
118
|
);
|
|
116
119
|
const $ = u(() => {
|
|
117
|
-
if (!
|
|
118
|
-
if (v.error)
|
|
119
|
-
return x(v.error);
|
|
120
|
+
if (!x.value) {
|
|
120
121
|
if (h.error)
|
|
121
|
-
return
|
|
122
|
+
return B(h.error);
|
|
123
|
+
if (_.error)
|
|
124
|
+
return B(_.error);
|
|
122
125
|
if (n.error)
|
|
123
|
-
return
|
|
124
|
-
if (n.modelValue.length &&
|
|
126
|
+
return B(n.error);
|
|
127
|
+
if (n.modelValue.length && R.value.length !== n.modelValue.length)
|
|
125
128
|
return "The selected values are not one of the options";
|
|
126
129
|
}
|
|
127
130
|
});
|
|
@@ -131,21 +134,21 @@ 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: k,
|
|
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
|
-
onFocusout:
|
|
141
|
+
onFocusout: P
|
|
139
142
|
}, [
|
|
140
143
|
d("div", Ve, [
|
|
141
144
|
d("div", we, [
|
|
142
145
|
de(d("input", {
|
|
143
146
|
ref_key: "inputRef",
|
|
144
|
-
ref:
|
|
147
|
+
ref: b,
|
|
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,76 +156,76 @@ 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 ?
|
|
157
|
-
(s(!0), c(E, null, F(
|
|
159
|
+
l.open ? f("", !0) : (s(), c("div", Se, [
|
|
160
|
+
(s(!0), c(E, null, F(R.value, (o, r) => (s(), m(i(j), {
|
|
158
161
|
key: r,
|
|
159
162
|
closeable: "",
|
|
160
163
|
small: "",
|
|
161
164
|
onClick: t[2] || (t[2] = T((a) => l.open = !0, ["stop"])),
|
|
162
|
-
onClose: (a) =>
|
|
165
|
+
onClose: (a) => q(o.value)
|
|
163
166
|
}, {
|
|
164
|
-
default:
|
|
165
|
-
|
|
167
|
+
default: V(() => [
|
|
168
|
+
U(v(o.label || o.value), 1)
|
|
166
169
|
]),
|
|
167
170
|
_: 2
|
|
168
171
|
}, 1032, ["onClose"]))), 128))
|
|
169
172
|
])),
|
|
170
|
-
d("div",
|
|
171
|
-
|
|
173
|
+
d("div", xe, [
|
|
174
|
+
x.value ? (s(), m(i(ye), {
|
|
172
175
|
key: 0,
|
|
173
176
|
name: "loading"
|
|
174
|
-
})) :
|
|
175
|
-
|
|
177
|
+
})) : f("", !0),
|
|
178
|
+
K(e.$slots, "append"),
|
|
176
179
|
d("div", {
|
|
177
180
|
class: "pl-autocomplete-multi__arrow-wrapper",
|
|
178
181
|
onClick: T(te, ["stop"])
|
|
179
|
-
}, t[3] || (t[3] = [
|
|
182
|
+
}, [...t[3] || (t[3] = [
|
|
180
183
|
d("div", { class: "arrow-icon arrow-icon-default" }, null, -1)
|
|
181
|
-
]))
|
|
184
|
+
])])
|
|
182
185
|
])
|
|
183
186
|
]),
|
|
184
|
-
|
|
185
|
-
|
|
187
|
+
p.label ? (s(), c("label", Ce, [
|
|
188
|
+
p.required ? (s(), m(i(be), {
|
|
186
189
|
key: 0,
|
|
187
190
|
uri: i(ke)
|
|
188
|
-
}, null, 8, ["uri"])) :
|
|
189
|
-
d("span", null,
|
|
190
|
-
i(Q).tooltip ? (s(),
|
|
191
|
+
}, null, 8, ["uri"])) : f("", !0),
|
|
192
|
+
d("span", null, v(p.label), 1),
|
|
193
|
+
i(Q).tooltip ? (s(), m(i(ge), {
|
|
191
194
|
key: 1,
|
|
192
195
|
class: "info",
|
|
193
196
|
position: "top"
|
|
194
197
|
}, {
|
|
195
|
-
tooltip:
|
|
196
|
-
|
|
198
|
+
tooltip: V(() => [
|
|
199
|
+
K(e.$slots, "tooltip")
|
|
197
200
|
]),
|
|
198
201
|
_: 3
|
|
199
|
-
})) :
|
|
200
|
-
])) :
|
|
201
|
-
l.open ? (s(),
|
|
202
|
+
})) : f("", !0)
|
|
203
|
+
])) : f("", !0),
|
|
204
|
+
l.open ? (s(), m(ve, {
|
|
202
205
|
key: 1,
|
|
203
206
|
ref_key: "overlay",
|
|
204
|
-
ref:
|
|
205
|
-
root:
|
|
207
|
+
ref: w,
|
|
208
|
+
root: k.value,
|
|
206
209
|
class: "pl-autocomplete-multi__options",
|
|
207
210
|
gap: 5,
|
|
208
211
|
tabindex: "-1",
|
|
209
|
-
onFocusout:
|
|
212
|
+
onFocusout: P
|
|
210
213
|
}, {
|
|
211
|
-
default:
|
|
212
|
-
d("div",
|
|
213
|
-
(s(!0), c(E, null, F(
|
|
214
|
+
default: V(() => [
|
|
215
|
+
d("div", $e, [
|
|
216
|
+
(s(!0), c(E, null, F(R.value, (o, r) => (s(), m(i(j), {
|
|
214
217
|
key: r,
|
|
215
218
|
closeable: "",
|
|
216
219
|
small: "",
|
|
217
|
-
onClose: (a) =>
|
|
220
|
+
onClose: (a) => q(o.value)
|
|
218
221
|
}, {
|
|
219
|
-
default:
|
|
220
|
-
|
|
222
|
+
default: V(() => [
|
|
223
|
+
U(v(o.label || o.value), 1)
|
|
221
224
|
]),
|
|
222
225
|
_: 2
|
|
223
226
|
}, 1032, ["onClose"]))), 128))
|
|
224
227
|
]),
|
|
225
|
-
(s(!0), c(E, null, F(
|
|
228
|
+
(s(!0), c(E, null, F(S.value, (o, r) => (s(), m(_e, {
|
|
226
229
|
key: r,
|
|
227
230
|
option: o,
|
|
228
231
|
"text-item": "text",
|
|
@@ -230,20 +233,23 @@ 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) => N(o.value), ["stop"])
|
|
234
237
|
}, null, 8, ["option", "is-selected", "is-hovered", "onClick"]))), 128)),
|
|
235
|
-
!
|
|
238
|
+
!S.value.length && !x.value ? (s(), c("div", Ae, v(p.emptyOptionsText), 1)) : f("", !0)
|
|
236
239
|
]),
|
|
237
240
|
_: 1
|
|
238
|
-
}, 8, ["root"])) :
|
|
239
|
-
ce(me, {
|
|
241
|
+
}, 8, ["root"])) : f("", !0),
|
|
242
|
+
ce(me, {
|
|
243
|
+
class: "pl-autocomplete-multi__contour",
|
|
244
|
+
"group-position": p.groupPosition
|
|
245
|
+
}, null, 8, ["group-position"])
|
|
240
246
|
])
|
|
241
247
|
], 42, Oe),
|
|
242
|
-
$.value ? (s(), c("div",
|
|
248
|
+
$.value ? (s(), c("div", Ee, v($.value), 1)) : p.helper ? (s(), c("div", Fe, v(p.helper), 1)) : f("", !0)
|
|
243
249
|
]));
|
|
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","_createElementBlock","_createElementVNode","_normalizeClass","_hoisted_2","_hoisted_3","_cache","$event","_vModelText","_openBlock","_hoisted_5","_Fragment","_renderList","i","_createBlock","_unref","PlChip","_withModifiers","_createTextVNode","_toDisplayString","_hoisted_6","PlMaskIcon24","_renderSlot","_ctx","_hoisted_7","PlSvg","SvgRequired","PlTooltip","DropdownOverlay","_hoisted_8","item","index","DropdownListItem","_hoisted_9","_createVNode","DoubleContour","_hoisted_10","_hoisted_11"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlBtnAccent.vue.js","sources":["../../../src/components/PlBtnAccent/PlBtnAccent.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Accent button\n */\nexport default {\n name: 'PlBtnAccent',\n};\n</script>\n\n<script lang=\"ts\" setup>\nimport './pl-btn-accent.scss';\nimport type { MaskIconName16, Size } from '../../types';\nimport BtnBase from '../../base/BtnBase.vue';\n\nconst props = defineProps<{\n /**\n * If `true,` the button is disabled, cannot be interacted with, and shows a special 'loading' icon.\n */\n loading?: boolean;\n /**\n * Size of the button, the default value is 'medium'\n */\n size?: Size;\n /**\n * If `true` the shape is round.\n */\n round?: boolean;\n /**\n * Icon to display\n */\n icon?: MaskIconName16;\n /**\n * If `true`, an icon is displayed before the text.\n */\n reverse?: boolean;\n /**\n * Justify text at the center\n */\n justifyCenter?: boolean;\n}>();\n</script>\n\n<template>\n <BtnBase class=\"pl-btn-accent\" v-bind=\"props\">\n <slot />\n </BtnBase>\n</template>\n"],"names":["__default__","props","__props"],"mappings":";;;AAIA,MAAAA,IAAe;AAAA,EACb,MAAM;AACR;;;;;;;;;;;AAQA,UAAMC,IAAQC
|
|
1
|
+
{"version":3,"file":"PlBtnAccent.vue.js","sources":["../../../src/components/PlBtnAccent/PlBtnAccent.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Accent button\n */\nexport default {\n name: 'PlBtnAccent',\n};\n</script>\n\n<script lang=\"ts\" setup>\nimport './pl-btn-accent.scss';\nimport type { MaskIconName16, Size } from '../../types';\nimport BtnBase from '../../base/BtnBase.vue';\n\nconst props = defineProps<{\n /**\n * If `true,` the button is disabled, cannot be interacted with, and shows a special 'loading' icon.\n */\n loading?: boolean;\n /**\n * Size of the button, the default value is 'medium'\n */\n size?: Size;\n /**\n * If `true` the shape is round.\n */\n round?: boolean;\n /**\n * Icon to display\n */\n icon?: MaskIconName16;\n /**\n * If `true`, an icon is displayed before the text.\n */\n reverse?: boolean;\n /**\n * Justify text at the center\n */\n justifyCenter?: boolean;\n}>();\n</script>\n\n<template>\n <BtnBase class=\"pl-btn-accent\" v-bind=\"props\">\n <slot />\n </BtnBase>\n</template>\n"],"names":["__default__","props","__props","_openBlock","_createBlock","BtnBase","_mergeProps","_renderSlot","_ctx"],"mappings":";;;AAIA,MAAAA,IAAe;AAAA,EACb,MAAM;AACR;;;;;;;;;;;AAQA,UAAMC,IAAQC;sBA6BZC,EAAA,GAAAC,EAEUC,GAFVC,EAEU,EAFD,OAAM,mBAAwBL,CAAK,GAAA;AAAA,iBAC1C,MAAQ;AAAA,QAARM,EAAQC,EAAA,QAAA,SAAA;AAAA,MAAA;;;;;"}
|