@milaboratories/uikit 2.2.95 → 2.2.97
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 +32 -27
- package/.turbo/turbo-type-check.log +1 -1
- package/CHANGELOG.md +17 -0
- package/dist/components/DataTable/TableComponent.vue.js +1 -1
- package/dist/components/PlAccordion/PlAccordionSection.vue2.js +21 -21
- package/dist/components/PlAccordion/PlAccordionSection.vue2.js.map +1 -1
- package/dist/components/PlAutocomplete/PlAutocomplete.vue.js.map +1 -1
- package/dist/components/PlClipboard/PlClipboard.vue.d.ts +1 -1
- package/dist/components/PlDropdown/OptionList.vue.d.ts +77 -0
- package/dist/components/PlDropdown/OptionList.vue.d.ts.map +1 -0
- package/dist/components/PlDropdown/OptionList.vue.js +88 -0
- package/dist/components/PlDropdown/OptionList.vue.js.map +1 -0
- package/dist/components/PlDropdown/OptionList.vue2.js +5 -0
- package/dist/components/PlDropdown/OptionList.vue2.js.map +1 -0
- package/dist/components/PlDropdown/PlDropdown.vue.d.ts.map +1 -1
- package/dist/components/PlDropdown/PlDropdown.vue.js +110 -122
- package/dist/components/PlDropdown/PlDropdown.vue.js.map +1 -1
- package/dist/components/PlDropdown/types.d.ts +7 -0
- package/dist/components/PlDropdown/types.d.ts.map +1 -0
- package/dist/components/PlDropdown/useGroupBy.d.ts +7 -0
- package/dist/components/PlDropdown/useGroupBy.d.ts.map +1 -0
- package/dist/components/PlDropdown/useGroupBy.js +36 -0
- package/dist/components/PlDropdown/useGroupBy.js.map +1 -0
- package/dist/components/PlDropdownRef/PlDropdownRef.vue.d.ts +1 -1
- package/dist/components/PlDropdownRef/PlDropdownRef.vue.d.ts.map +1 -1
- package/dist/components/PlDropdownRef/PlDropdownRef.vue.js +11 -10
- package/dist/components/PlDropdownRef/PlDropdownRef.vue.js.map +1 -1
- package/dist/components/PlElementList/PlElementList.vue.d.ts +19 -27
- package/dist/components/PlElementList/PlElementList.vue.d.ts.map +1 -1
- package/dist/components/PlElementList/PlElementList.vue2.js +155 -174
- package/dist/components/PlElementList/PlElementList.vue2.js.map +1 -1
- package/dist/components/PlElementList/PlElementListItem.vue.d.ts.map +1 -1
- package/dist/components/PlElementList/PlElementListItem.vue2.js +1 -1
- package/dist/components/PlElementList/PlElementListItem.vue2.js.map +1 -1
- package/dist/components/PlElementList/PlElementListItem.vue3.js +24 -24
- package/dist/components/PlElementList/utils.d.ts +0 -1
- package/dist/components/PlElementList/utils.d.ts.map +1 -1
- package/dist/components/PlElementList/utils.js +5 -11
- package/dist/components/PlElementList/utils.js.map +1 -1
- package/dist/components/PlErrorBoundary/PlErrorBoundary.vue.js +8 -8
- package/dist/components/PlFileInput/PlFileInput.vue.js +8 -8
- package/dist/components/PlIcon16/PlIcon16.vue.d.ts +1 -1
- package/dist/components/PlIcon24/PlIcon24.vue.d.ts +1 -1
- package/dist/components/PlSlideModal/PlSlideModal.vue.js +1 -1
- package/dist/components/PlSvg/PlSvg.vue.d.ts +1 -1
- package/dist/components/PlSvg/PlSvg.vue.d.ts.map +1 -1
- package/dist/components/PlSvg/PlSvg.vue2.js +24 -22
- package/dist/components/PlSvg/PlSvg.vue2.js.map +1 -1
- package/dist/composition/useWatchFetch.js +10 -10
- package/dist/helpers/utils.d.ts +1 -0
- package/dist/helpers/utils.d.ts.map +1 -1
- package/dist/helpers/utils.js +2 -1
- package/dist/helpers/utils.js.map +1 -1
- package/dist/lib/util/helpers/dist/index.js +108 -104
- package/dist/lib/util/helpers/dist/index.js.map +1 -1
- package/dist/sdk/model/dist/index.js +1 -1
- package/dist/sdk/model/dist/index.js.map +1 -1
- package/dist/types.d.ts +4 -14
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/TextLabel.vue.d.ts +18 -0
- package/dist/utils/TextLabel.vue.d.ts.map +1 -0
- package/dist/utils/TextLabel.vue.js +26 -0
- package/dist/utils/TextLabel.vue.js.map +1 -0
- package/dist/utils/TextLabel.vue2.js +13 -0
- package/dist/utils/TextLabel.vue2.js.map +1 -0
- package/package.json +4 -4
- package/src/components/PlAccordion/PlAccordionSection.vue +3 -3
- package/src/components/PlAutocomplete/PlAutocomplete.vue +1 -1
- package/src/components/PlDropdown/OptionList.vue +71 -0
- package/src/components/PlDropdown/PlDropdown.vue +29 -25
- package/src/components/PlDropdown/pl-dropdown.scss +4 -0
- package/src/components/PlDropdown/types.ts +3 -0
- package/src/components/PlDropdown/useGroupBy.ts +63 -0
- package/src/components/PlDropdownRef/PlDropdownRef.vue +1 -0
- package/src/components/PlElementList/PlElementList.vue +116 -135
- package/src/components/PlElementList/PlElementListItem.vue +9 -1
- package/src/components/PlElementList/README.md +325 -72
- package/src/components/PlElementList/utils.ts +0 -9
- package/src/components/PlSvg/PlSvg.vue +2 -2
- package/src/helpers/utils.ts +1 -0
- package/src/types.ts +5 -15
- package/src/utils/TextLabel.vue +43 -0
|
@@ -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, useSlots, 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 SvgRequired from '../../generated/components/svg/images/SvgRequired.vue';\nimport { getErrorMessage } from '../../helpers/error.ts';\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 }));\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: ListOptionNormalized<M> | 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 [];\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 <SvgRequired v-if=\"required\" />\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 SvgRequired from '../../generated/components/svg/images/SvgRequired.vue';\nimport { getErrorMessage } from '../../helpers/error.ts';\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 }));\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: ListOptionNormalized<M> | 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 [];\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 <SvgRequired v-if=\"required\" />\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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"}
|
|
@@ -7,6 +7,6 @@ declare const _default: import('vue').DefineComponent<{
|
|
|
7
7
|
size?: Size;
|
|
8
8
|
}> & Readonly<{
|
|
9
9
|
onCopy?: ((...args: any[]) => any) | undefined;
|
|
10
|
-
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {},
|
|
10
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, SVGSVGElement>;
|
|
11
11
|
export default _default;
|
|
12
12
|
//# sourceMappingURL=PlClipboard.vue.d.ts.map
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { LOption } from './types';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
rootRef: HTMLElement;
|
|
4
|
+
groups: Map<string, LOption[]>;
|
|
5
|
+
rest: LOption[];
|
|
6
|
+
optionSize: 'small' | 'medium';
|
|
7
|
+
selectOption: (v: unknown) => void;
|
|
8
|
+
};
|
|
9
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {
|
|
10
|
+
scrollIntoActive: () => void;
|
|
11
|
+
listRef: import('vue').ComputedRef<HTMLElement | undefined>;
|
|
12
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
|
|
13
|
+
overlay: ({
|
|
14
|
+
$: import('vue').ComponentInternalInstance;
|
|
15
|
+
$data: {};
|
|
16
|
+
$props: {
|
|
17
|
+
readonly root: HTMLElement | undefined;
|
|
18
|
+
readonly gap?: number | undefined;
|
|
19
|
+
} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps;
|
|
20
|
+
$attrs: {
|
|
21
|
+
[x: string]: unknown;
|
|
22
|
+
};
|
|
23
|
+
$refs: {
|
|
24
|
+
[x: string]: unknown;
|
|
25
|
+
} & {
|
|
26
|
+
listRef: HTMLDivElement;
|
|
27
|
+
};
|
|
28
|
+
$slots: Readonly<{
|
|
29
|
+
[name: string]: import('vue').Slot<any> | undefined;
|
|
30
|
+
}>;
|
|
31
|
+
$root: import('vue').ComponentPublicInstance | null;
|
|
32
|
+
$parent: import('vue').ComponentPublicInstance | null;
|
|
33
|
+
$host: Element | null;
|
|
34
|
+
$emit: (event: string, ...args: any[]) => void;
|
|
35
|
+
$el: any;
|
|
36
|
+
$options: import('vue').ComponentOptionsBase<Readonly<{
|
|
37
|
+
root: HTMLElement | undefined;
|
|
38
|
+
gap?: number;
|
|
39
|
+
}> & Readonly<{}>, {
|
|
40
|
+
scrollIntoActive: () => void;
|
|
41
|
+
listRef: import('vue').Ref<HTMLElement | undefined, HTMLElement | undefined>;
|
|
42
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, {}, {}, string, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, import('vue').ComponentProvideOptions> & {
|
|
43
|
+
beforeCreate?: (() => void) | (() => void)[];
|
|
44
|
+
created?: (() => void) | (() => void)[];
|
|
45
|
+
beforeMount?: (() => void) | (() => void)[];
|
|
46
|
+
mounted?: (() => void) | (() => void)[];
|
|
47
|
+
beforeUpdate?: (() => void) | (() => void)[];
|
|
48
|
+
updated?: (() => void) | (() => void)[];
|
|
49
|
+
activated?: (() => void) | (() => void)[];
|
|
50
|
+
deactivated?: (() => void) | (() => void)[];
|
|
51
|
+
beforeDestroy?: (() => void) | (() => void)[];
|
|
52
|
+
beforeUnmount?: (() => void) | (() => void)[];
|
|
53
|
+
destroyed?: (() => void) | (() => void)[];
|
|
54
|
+
unmounted?: (() => void) | (() => void)[];
|
|
55
|
+
renderTracked?: ((e: import('vue').DebuggerEvent) => void) | ((e: import('vue').DebuggerEvent) => void)[];
|
|
56
|
+
renderTriggered?: ((e: import('vue').DebuggerEvent) => void) | ((e: import('vue').DebuggerEvent) => void)[];
|
|
57
|
+
errorCaptured?: ((err: unknown, instance: import('vue').ComponentPublicInstance | null, info: string) => boolean | void) | ((err: unknown, instance: import('vue').ComponentPublicInstance | null, info: string) => boolean | void)[];
|
|
58
|
+
};
|
|
59
|
+
$forceUpdate: () => void;
|
|
60
|
+
$nextTick: typeof import('vue').nextTick;
|
|
61
|
+
$watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends (...args: any) => infer R ? (...args: [R, R, import('@vue/reactivity').OnCleanup]) => any : (...args: [any, any, import('@vue/reactivity').OnCleanup]) => any, options?: import('vue').WatchOptions): import('vue').WatchStopHandle;
|
|
62
|
+
} & Readonly<{}> & Omit<Readonly<{
|
|
63
|
+
root: HTMLElement | undefined;
|
|
64
|
+
gap?: number;
|
|
65
|
+
}> & Readonly<{}>, "scrollIntoActive" | "listRef"> & import('vue').ShallowUnwrapRef<{
|
|
66
|
+
scrollIntoActive: () => void;
|
|
67
|
+
listRef: import('vue').Ref<HTMLElement | undefined, HTMLElement | undefined>;
|
|
68
|
+
}> & {} & import('vue').ComponentCustomProperties & {} & {
|
|
69
|
+
$slots: {
|
|
70
|
+
default?(_: {
|
|
71
|
+
ref: string;
|
|
72
|
+
}): any;
|
|
73
|
+
};
|
|
74
|
+
}) | null;
|
|
75
|
+
}, any>;
|
|
76
|
+
export default _default;
|
|
77
|
+
//# sourceMappingURL=OptionList.vue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OptionList.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlDropdown/OptionList.vue"],"names":[],"mappings":"AA6EA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,KAAK,WAAW,GAAG;IACjB,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAC/B,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,UAAU,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC/B,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oCA6MwygB,GAAG,8CAA8C,GAAG,yBAAyB,GAAG,6DAAmC,GAAG;;;;;;;;;;;;;;;AAjBh6gB,wBASG"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { defineComponent as I, useTemplateRef as L, computed as c, createBlock as u, openBlock as o, unref as O, withCtx as f, createElementBlock as s, createCommentVNode as m, Fragment as a, renderList as p, normalizeClass as h, createVNode as g, createElementVNode as k, createTextVNode as V, toDisplayString as $, withModifiers as y } from "vue";
|
|
2
|
+
import z from "../DropdownListItem.vue.js";
|
|
3
|
+
import w from "../../utils/DropdownOverlay/DropdownOverlay.vue.js";
|
|
4
|
+
import _ from "../../utils/TextLabel.vue.js";
|
|
5
|
+
const B = {
|
|
6
|
+
key: 1,
|
|
7
|
+
class: "nothing-found"
|
|
8
|
+
}, M = /* @__PURE__ */ I({
|
|
9
|
+
__name: "OptionList",
|
|
10
|
+
props: {
|
|
11
|
+
rootRef: {},
|
|
12
|
+
groups: {},
|
|
13
|
+
rest: {},
|
|
14
|
+
optionSize: {},
|
|
15
|
+
selectOption: { type: Function }
|
|
16
|
+
},
|
|
17
|
+
setup(C, { expose: S }) {
|
|
18
|
+
const r = C, l = L("overlay"), A = c(() => {
|
|
19
|
+
var e;
|
|
20
|
+
return (e = l.value) == null ? void 0 : e.listRef;
|
|
21
|
+
}), d = c(() => r.groups.size > 0), N = c(() => {
|
|
22
|
+
let e = 0;
|
|
23
|
+
for (const v of r.groups.values())
|
|
24
|
+
e += v.length;
|
|
25
|
+
return e + r.rest.length;
|
|
26
|
+
});
|
|
27
|
+
return S({
|
|
28
|
+
scrollIntoActive: () => {
|
|
29
|
+
var e;
|
|
30
|
+
(e = l.value) == null || e.scrollIntoActive();
|
|
31
|
+
},
|
|
32
|
+
listRef: A
|
|
33
|
+
}), (e, v) => (o(), u(O(w), {
|
|
34
|
+
ref_key: "overlay",
|
|
35
|
+
ref: l,
|
|
36
|
+
root: e.rootRef,
|
|
37
|
+
class: "pl-dropdown__options",
|
|
38
|
+
tabindex: "-1",
|
|
39
|
+
gap: 3
|
|
40
|
+
}, {
|
|
41
|
+
default: f(() => [
|
|
42
|
+
(o(!0), s(a, null, p(e.groups.entries(), ([t, i]) => (o(), s("div", {
|
|
43
|
+
key: t,
|
|
44
|
+
class: h({ "group-container": d.value })
|
|
45
|
+
}, [
|
|
46
|
+
g(_, null, {
|
|
47
|
+
default: f(() => [
|
|
48
|
+
V($(t), 1)
|
|
49
|
+
]),
|
|
50
|
+
_: 2
|
|
51
|
+
}, 1024),
|
|
52
|
+
k("div", null, [
|
|
53
|
+
(o(!0), s(a, null, p(i, (n, R) => (o(), u(z, {
|
|
54
|
+
key: R,
|
|
55
|
+
option: n,
|
|
56
|
+
"is-selected": n.isSelected,
|
|
57
|
+
"is-hovered": n.isActive,
|
|
58
|
+
size: e.optionSize,
|
|
59
|
+
onClick: y((b) => e.selectOption(n.value), ["stop"])
|
|
60
|
+
}, null, 8, ["option", "is-selected", "is-hovered", "size", "onClick"]))), 128))
|
|
61
|
+
])
|
|
62
|
+
], 2))), 128)),
|
|
63
|
+
e.rest.length ? (o(), s("div", {
|
|
64
|
+
key: 0,
|
|
65
|
+
class: h({ "group-container": d.value })
|
|
66
|
+
}, [
|
|
67
|
+
g(_),
|
|
68
|
+
k("div", null, [
|
|
69
|
+
(o(!0), s(a, null, p(e.rest, (t, i) => (o(), u(z, {
|
|
70
|
+
key: i,
|
|
71
|
+
option: t,
|
|
72
|
+
"is-selected": t.isSelected,
|
|
73
|
+
"is-hovered": t.isActive,
|
|
74
|
+
size: e.optionSize,
|
|
75
|
+
onClick: y((n) => e.selectOption(t.value), ["stop"])
|
|
76
|
+
}, null, 8, ["option", "is-selected", "is-hovered", "size", "onClick"]))), 128))
|
|
77
|
+
])
|
|
78
|
+
], 2)) : m("", !0),
|
|
79
|
+
N.value ? m("", !0) : (o(), s("div", B, "Nothing found"))
|
|
80
|
+
]),
|
|
81
|
+
_: 1
|
|
82
|
+
}, 8, ["root"]));
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
export {
|
|
86
|
+
M as default
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=OptionList.vue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OptionList.vue.js","sources":["../../../src/components/PlDropdown/OptionList.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport DropdownListItem from '../DropdownListItem.vue';\nimport { DropdownOverlay } from '../../utils/DropdownOverlay';\nimport TextLabel from '../../utils/TextLabel.vue';\nimport { computed, useTemplateRef } from 'vue';\nimport type { LOption } from './types';\n\nconst props = defineProps<{\n rootRef: HTMLElement;\n groups: Map<string, LOption[]>;\n rest: LOption[];\n optionSize: 'small' | 'medium';\n selectOption: (v: unknown) => void;\n}>();\n\nconst overlay = useTemplateRef('overlay');\n\nconst listRef = computed(() => overlay.value?.listRef);\n\nconst hasGroups = computed(() => props.groups.size > 0);\n\nconst optionsLength = computed(() => {\n let totalGroupItems = 0;\n for (const items of props.groups.values()) {\n totalGroupItems += items.length;\n }\n return totalGroupItems + props.rest.length;\n});\n\nconst scrollIntoActive = () => {\n overlay.value?.scrollIntoActive();\n};\n\ndefineExpose({\n scrollIntoActive,\n listRef,\n});\n</script>\n\n<template>\n <DropdownOverlay ref=\"overlay\" :root=\"rootRef\" class=\"pl-dropdown__options\" tabindex=\"-1\" :gap=\"3\">\n <div v-for=\"[group, items] in groups.entries()\" :key=\"group\" :class=\"{ 'group-container': hasGroups }\">\n <TextLabel>{{ group }}</TextLabel>\n <div>\n <DropdownListItem\n v-for=\"(item, index) in items\"\n :key=\"index\"\n :option=\"item\"\n :is-selected=\"item.isSelected\"\n :is-hovered=\"item.isActive\"\n :size=\"optionSize\"\n @click.stop=\"selectOption(item.value)\"\n />\n </div>\n </div>\n <div v-if=\"rest.length\" :class=\"{ 'group-container': hasGroups }\">\n <TextLabel />\n <div>\n <DropdownListItem\n v-for=\"(item, index) in rest\"\n :key=\"index\" :option=\"item\"\n :is-selected=\"item.isSelected\"\n :is-hovered=\"item.isActive\"\n :size=\"optionSize\"\n @click.stop=\"selectOption(item.value)\"\n />\n </div>\n </div>\n <div v-if=\"!optionsLength\" class=\"nothing-found\">Nothing found</div>\n </DropdownOverlay>\n</template>\n"],"names":["props","__props","overlay","useTemplateRef","listRef","computed","_a","hasGroups","optionsLength","totalGroupItems","items","__expose"],"mappings":";;;;;;;;;;;;;;;;;AAOA,UAAMA,IAAQC,GAQRC,IAAUC,EAAe,SAAS,GAElCC,IAAUC,EAAS,MAAM;;AAAA,cAAAC,IAAAJ,EAAQ,UAAR,gBAAAI,EAAe;AAAA,KAAO,GAE/CC,IAAYF,EAAS,MAAML,EAAM,OAAO,OAAO,CAAC,GAEhDQ,IAAgBH,EAAS,MAAM;AACnC,UAAII,IAAkB;AACtB,iBAAWC,KAASV,EAAM,OAAO,OAAA;AAC/B,QAAAS,KAAmBC,EAAM;AAEpB,aAAAD,IAAkBT,EAAM,KAAK;AAAA,IAAA,CACrC;AAMY,WAAAW,EAAA;AAAA,MACX,kBALuB,MAAM;;AAC7B,SAAAL,IAAAJ,EAAQ,UAAR,QAAAI,EAAe;AAAA,MACjB;AAAA,MAIE,SAAAF;AAAA,IAAA,CACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OptionList.vue2.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlDropdown.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlDropdown/PlDropdown.vue"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"PlDropdown.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlDropdown/PlDropdown.vue"],"names":[],"mappings":"AAAA,OA8XO,oBAAoB,CAAC;AAM5B,OAAO,KAAK,EAAE,UAAU,EAAwB,MAAM,aAAa,CAAC;AAapE;;GAEG;yBACc,CAAC,yBACJ,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,cAClD,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,iBAC5F,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;WA2jB1D,mBAAmB,CAAC;;;QAhjBxB;;WAEG;oBACS,CAAC;QACb;;WAEG;gBACK,MAAM;QACd;;WAEG;kBACO,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QACnC;;WAEG;iBACM,MAAM;QACf;;WAEG;+BACoB,MAAM;QAC7B;;WAEG;gBACK,OAAO;QACf;;WAEG;sBACW,MAAM;QACpB;;WAEG;oBACS,OAAO;QACnB;;WAEG;mBACQ,OAAO;QAClB;;WAEG;mBACQ,OAAO;QAClB;;WAEG;oBACS,MAAM;QAClB;;WAEG;yBACc,MAAM;QACvB;;WAEG;qBACU,OAAO,GAAG,QAAQ;mBA6f2D,CAAC,4BAA2B;oBACzG,OAAO,KAAK,EAAE,gBAAgB,CAAC,EAAE,CAAC,GAAG,IAAI;WAClD,GAAG;;;;;;cAvjBL,mBAAmB,SAAS,CAAC,GAAG,SAAS,KAAG,IAAI;;;;YA4jBV,OAAO,CAAC,OAAO,WAAW,CAAC;;AArkBvE,wBAqkB4E;AAG5E,KAAK,mBAAmB,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG,EAAE,CAAC"}
|