@milaboratories/uikit 2.15.27 → 2.15.29

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.
@@ -1,6 +1,6 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @milaboratories/uikit@2.15.27 build /home/runner/_work/platforma/platforma/lib/ui/uikit
3
+ > @milaboratories/uikit@2.15.29 build /home/runner/_work/platforma/platforma/lib/ui/uikit
4
4
  > ts-builder build --target browser-lib --build-config ./build.browser-lib.config.js
5
5
 
6
6
  Building browser-lib project...
@@ -18,7 +18,7 @@ Using custom config: ./build.browser-lib.config.js
18
18
  rendering chunks...
19
19
 
20
20
  [unplugin:dts] Start generate declaration files...
21
- [unplugin:dts] Declaration files built in 6078ms.
21
+ [unplugin:dts] Declaration files built in 7444ms.
22
22
 
23
23
  computing gzip size...
24
24
  dist/components/PlClipboard/PlClipboard.vue?vue&type=style&index=0&lang.css 0.04 kB │ gzip: 0.06 kB
@@ -197,7 +197,7 @@ dist/components/PlBtnGroup/PlBtnGroup.js
197
197
  dist/components/PlBtnSplit/PlBtnSplit.js 0.20 kB │ gzip: 0.16 kB │ map: 5.82 kB
198
198
  dist/components/PlCheckbox/PlCheckbox.js 0.20 kB │ gzip: 0.16 kB │ map: 1.37 kB
199
199
  dist/components/PlDropdown/OptionList.js 0.20 kB │ gzip: 0.17 kB │ map: 2.40 kB
200
- dist/components/PlDropdown/PlDropdown.js 0.20 kB │ gzip: 0.16 kB │ map: 12.33 kB
200
+ dist/components/PlDropdown/PlDropdown.js 0.20 kB │ gzip: 0.16 kB │ map: 12.76 kB
201
201
  dist/components/PlTextArea/PlTextArea.js 0.20 kB │ gzip: 0.16 kB │ map: 4.74 kB
202
202
  dist/layout/PlContainer/PlContainer.js 0.20 kB │ gzip: 0.16 kB │ map: 0.94 kB
203
203
  dist/components/PlSlideModal/props.js 0.20 kB │ gzip: 0.18 kB │ map: 0.75 kB
@@ -224,7 +224,7 @@ dist/components/PlNumberField/PlNumberField.js
224
224
  dist/components/PlProgressBar/PlProgressBar.js 0.22 kB │ gzip: 0.16 kB │ map: 0.93 kB
225
225
  dist/components/DataTable/RowsCommandMenu.js 0.22 kB │ gzip: 0.17 kB │ map: 1.05 kB
226
226
  dist/utils/DropdownOverlay/DropdownOverlay.js 0.22 kB │ gzip: 0.16 kB │ map: 2.40 kB
227
- dist/components/PlAutocomplete/PlAutocomplete.js 0.22 kB │ gzip: 0.16 kB │ map: 13.31 kB
227
+ dist/components/PlAutocomplete/PlAutocomplete.js 0.22 kB │ gzip: 0.16 kB │ map: 13.58 kB
228
228
  dist/components/PlBtnSecondary/PlBtnSecondary.js 0.22 kB │ gzip: 0.16 kB │ map: 1.13 kB
229
229
  dist/components/PlDropdownLine/PlDropdownLine.js 0.22 kB │ gzip: 0.16 kB │ map: 9.47 kB
230
230
  dist/components/PlDropdownLine/ResizableInput.js 0.22 kB │ gzip: 0.17 kB │ map: 1.33 kB
@@ -239,7 +239,7 @@ dist/components/PlErrorBoundary/PlErrorBoundary.js
239
239
  dist/components/PlSlideModal/PlPureSlideModal.js 0.22 kB │ gzip: 0.17 kB │ map: 1.91 kB
240
240
  dist/utils/PlCloseModalBtn.vue_vue_type_style_index_0_lang.module.js 0.22 kB │ gzip: 0.18 kB │ map: 0.42 kB
241
241
  dist/components/DataTable/ColumnsCommandMenu.js 0.23 kB │ gzip: 0.17 kB │ map: 1.06 kB
242
- dist/components/PlDropdownLegacy/PlDropdownLegacy.js 0.23 kB │ gzip: 0.17 kB │ map: 11.18 kB
242
+ dist/components/PlDropdownLegacy/PlDropdownLegacy.js 0.23 kB │ gzip: 0.17 kB │ map: 11.53 kB
243
243
  dist/components/PlEditableTitle/pl-editable-title.module.js 0.23 kB │ gzip: 0.18 kB │ map: 0.45 kB
244
244
  dist/components/PlLoaderCircular/PlLoaderCircular.js 0.23 kB │ gzip: 0.16 kB │ map: 1.02 kB
245
245
  dist/layout/PlBlockPage/PlBlockPageTitleTeleportTarget.js 0.23 kB │ gzip: 0.16 kB │ map: 0.31 kB
@@ -529,11 +529,11 @@ dist/assets/icons/icon-assets-min/16_settings.js
529
529
  dist/assets/icons/icon-assets-min/24_table-upload.js 0.64 kB │ gzip: 0.38 kB │ map: 0.73 kB
530
530
  dist/assets/icons/icon-assets-min/16_data-dimentions.js 0.64 kB │ gzip: 0.42 kB │ map: 0.74 kB
531
531
  [PLUGIN_TIMINGS] Warning: Your build spent significant time in plugins. Here is a breakdown:
532
- - vite:asset (39%)
533
- - vite:css-post (12%)
532
+ - vite:asset (41%)
533
+ - sourcemaps (11%)
534
+ - vite:vue (10%)
534
535
  - unplugin-dts (9%)
535
- - vite:vue (9%)
536
- - sourcemaps (9%)
536
+ - vite:css-post (9%)
537
537
  See https://rolldown.rs/options/checks#plugintimings for more details.
538
538
  
539
539
  dist/assets/icons/icon-assets-min/16_clipboard.js 0.64 kB │ gzip: 0.38 kB │ map: 0.72 kB
@@ -779,16 +779,16 @@ dist/components/PlNumberField/PlNumberField.vue_vue_type_script_setup_true_lang.
779
779
  dist/components/PlDropdownLine/PlDropdownLine.vue_vue_type_script_setup_true_lang.js 7.15 kB │ gzip: 2.53 kB │ map: 20.82 kB
780
780
  dist/components/PlFileDialog/Remote.vue_vue_type_script_setup_true_lang.js 7.32 kB │ gzip: 2.76 kB │ map: 15.24 kB
781
781
  dist/components/SliderRangeTriple.vue_vue_type_script_setup_true_lang.js 7.35 kB │ gzip: 2.43 kB │ map: 15.58 kB
782
- dist/components/PlDropdownLegacy/PlDropdownLegacy.vue_vue_type_script_setup_true_lang.js 7.78 kB │ gzip: 2.80 kB │ map: 15.70 kB
783
- dist/components/PlDropdown/PlDropdown.vue_vue_type_script_setup_true_lang.js 7.95 kB │ gzip: 2.80 kB │ map: 23.31 kB
782
+ dist/components/PlDropdownLegacy/PlDropdownLegacy.vue_vue_type_script_setup_true_lang.js 7.94 kB │ gzip: 2.84 kB │ map: 16.19 kB
784
783
  dist/components/PlDropdownMulti/PlDropdownMulti.vue_vue_type_script_setup_true_lang.js 7.96 kB │ gzip: 2.87 kB │ map: 23.66 kB
784
+ dist/components/PlDropdown/PlDropdown.vue_vue_type_script_setup_true_lang.js 8.12 kB │ gzip: 2.84 kB │ map: 23.81 kB
785
785
  dist/components/PlAutocompleteMulti/PlAutocompleteMulti.vue_vue_type_script_setup_true_lang.js 8.35 kB │ gzip: 3.04 kB │ map: 24.74 kB
786
- dist/components/PlAutocomplete/PlAutocomplete.vue_vue_type_script_setup_true_lang.js 8.79 kB │ gzip: 3.11 kB │ map: 26.05 kB
786
+ dist/components/PlAutocomplete/PlAutocomplete.vue_vue_type_script_setup_true_lang.js 8.89 kB │ gzip: 3.14 kB │ map: 26.37 kB
787
787
  dist/components/PlElementList/PlElementList.vue_vue_type_script_setup_true_lang.js 9.01 kB │ gzip: 2.39 kB │ map: 20.07 kB
788
788
  dist/demo-site-data/all-css-variables.js 9.68 kB │ gzip: 1.75 kB │ map: 17.53 kB
789
789
  dist/composition/filters/metadata.js 11.37 kB │ gzip: 1.20 kB │ map: 22.01 kB
790
790
  dist/index.js 12.53 kB │ gzip: 2.96 kB │ map: 21.32 kB
791
791
  dist/components/PlSvg/PlSvg.vue_vue_type_script_setup_true_lang.js 39.41 kB │ gzip: 3.40 kB │ map: 8.66 kB
792
792
 
793
- ✓ built in 8.56s
793
+ ✓ built in 9.99s
794
794
  Build completed successfully
@@ -1,6 +1,6 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @milaboratories/uikit@2.15.27 formatter:check /home/runner/_work/platforma/platforma/lib/ui/uikit
3
+ > @milaboratories/uikit@2.15.29 formatter:check /home/runner/_work/platforma/platforma/lib/ui/uikit
4
4
  > ts-builder formatter --check
5
5
 
6
6
  Checking formatting...
@@ -8,5 +8,5 @@ Checking formatting...
8
8
  Checking formatting...
9
9
 
10
10
  All matched files use the correct format.
11
- Finished in 2464ms on 383 files using 16 threads.
11
+ Finished in 2321ms on 383 files using 16 threads.
12
12
  Format check completed successfully
@@ -1,10 +1,10 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @milaboratories/uikit@2.15.27 linter:check /home/runner/_work/platforma/platforma/lib/ui/uikit
3
+ > @milaboratories/uikit@2.15.29 linter:check /home/runner/_work/platforma/platforma/lib/ui/uikit
4
4
  > ts-builder linter --check
5
5
 
6
6
  Linting project...
7
7
  ↳ oxlint --config /home/runner/_work/platforma/platforma/lib/ui/uikit/.oxlintrc.json --deny-warnings
8
8
  Found 0 warnings and 0 errors.
9
- Finished in 34ms on 310 files with 108 rules using 16 threads.
9
+ Finished in 27ms on 310 files with 108 rules using 16 threads.
10
10
  Linting completed successfully
@@ -1,6 +1,6 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @milaboratories/uikit@2.15.27 types:check /home/runner/_work/platforma/platforma/lib/ui/uikit
3
+ > @milaboratories/uikit@2.15.29 types:check /home/runner/_work/platforma/platforma/lib/ui/uikit
4
4
  > ts-builder type-check --target browser-lib
5
5
 
6
6
  ↳ vue-tsc-ts6.cjs --noEmit --project ./tsconfig.json --customConditions default
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @milaboratories/uikit
2
2
 
3
+ ## 2.15.29
4
+
5
+ ### Patch Changes
6
+
7
+ - b659a5d: PlDropdown, PlDropdownLegacy, PlAutocomplete: show the full selected value as a native tooltip on hover when it is truncated with an ellipsis
8
+
9
+ ## 2.15.28
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies [1b1c13c]
14
+ - @platforma-sdk/model@1.83.9
15
+
3
16
  ## 2.15.27
4
17
 
5
18
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"PlAutocomplete.js","names":[],"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\n lang=\"ts\"\n setup\n generic=\"M extends null | undefined | string | number = null | undefined | string\"\n>\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\";\nimport { isNil } from \"@milaboratories/helpers\";\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: (string: string, type: \"value\" | \"label\") => 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?:\n | \"top\"\n | \"bottom\"\n | \"left\"\n | \"right\"\n | \"top-left\"\n | \"top-right\"\n | \"bottom-left\"\n | \"bottom-right\"\n | \"middle\";\n }>(),\n {\n 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 =\n modelOption ??\n options.find((o) => deepEqual(o.value, model.value)) ??\n 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(\n () => data.open,\n (v) => {\n search.value = v ? \"\" : null;\n },\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 (\n !rootRef.value?.contains(relatedTarget) &&\n !overlayRef.value?.listRef?.contains(relatedTarget)\n ) {\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(\n () => searchDebounced.value,\n async (v) => (isNil(v) ? undefined : props.optionsSearch(v, \"label\")),\n);\n\nconst modelOptionRequest = useWatchFetch(\n () => model.value,\n async (v) => {\n if (isNil(v) || deepEqual(modelOptionRef.value?.value, v)) {\n return modelOptionRef.value;\n }\n\n const options = await props.optionsSearch(String(v), \"value\");\n return options.find((o) => String(o.value) === String(v));\n },\n);\n\nwatch(\n () => optionsRequest.value,\n (result) => {\n if (result) {\n loadedOptionsRef.value = result;\n if (search.value !== null) {\n isLoadingError.value = false;\n }\n }\n },\n);\n\nwatch(\n () => modelOptionRequest.value,\n (result) => {\n if (result) {\n modelOptionRef.value = normalizeListOptions([result])[0];\n }\n },\n);\n\nwatch(\n () => optionsRequest.error,\n (err) => {\n if (err) {\n isLoadingError.value = Boolean(err);\n }\n },\n);\n\nwatch(\n () => optionsRequest.loading || modelOptionRequest.loading,\n (loading) => {\n isLoadingOptions.value = loading;\n },\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\n v-if=\"clearable && hasValue\"\n class=\"clear\"\n name=\"delete-clear\"\n @click.stop=\"clear\"\n />\n <slot name=\"append\" />\n <div class=\"pl-autocomplete__arrow-wrapper\" @click.stop=\"toggleOpen\">\n <div\n v-if=\"arrowIconLarge\"\n class=\"arrow-icon\"\n :class=\"[`icon-24 ${arrowIconLarge}`]\"\n />\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\n v-if=\"data.open\"\n ref=\"overlay\"\n :root=\"rootRef\"\n class=\"pl-autocomplete__options\"\n tabindex=\"-1\"\n :gap=\"3\"\n >\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\">\n {{ loadingOptionsHelper }}\n </div>\n <div v-else-if=\"helper\" class=\"pl-autocomplete__helper\">{{ helper }}</div>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"PlAutocomplete.js","names":[],"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\n lang=\"ts\"\n setup\n generic=\"M extends null | undefined | string | number = null | undefined | string\"\n>\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\";\nimport { isNil } from \"@milaboratories/helpers\";\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: (string: string, type: \"value\" | \"label\") => 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?:\n | \"top\"\n | \"bottom\"\n | \"left\"\n | \"right\"\n | \"top-left\"\n | \"top-right\"\n | \"bottom-left\"\n | \"bottom-right\"\n | \"middle\";\n }>(),\n {\n 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 =\n modelOption ??\n options.find((o) => deepEqual(o.value, model.value)) ??\n options.find((o) => deepEqual(o.value, model.value));\n\n return item?.label || (model.value ? props.formatValue(model.value) : \"\");\n});\n\n// Native tooltip with the full selected value; the value layer itself has\n// `pointer-events: none`, so the title goes on the field wrapper.\nconst fieldTitle = computed(() => (!data.open && textValue.value ? textValue.value : undefined));\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(\n () => data.open,\n (v) => {\n search.value = v ? \"\" : null;\n },\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 (\n !rootRef.value?.contains(relatedTarget) &&\n !overlayRef.value?.listRef?.contains(relatedTarget)\n ) {\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(\n () => searchDebounced.value,\n async (v) => (isNil(v) ? undefined : props.optionsSearch(v, \"label\")),\n);\n\nconst modelOptionRequest = useWatchFetch(\n () => model.value,\n async (v) => {\n if (isNil(v) || deepEqual(modelOptionRef.value?.value, v)) {\n return modelOptionRef.value;\n }\n\n const options = await props.optionsSearch(String(v), \"value\");\n return options.find((o) => String(o.value) === String(v));\n },\n);\n\nwatch(\n () => optionsRequest.value,\n (result) => {\n if (result) {\n loadedOptionsRef.value = result;\n if (search.value !== null) {\n isLoadingError.value = false;\n }\n }\n },\n);\n\nwatch(\n () => modelOptionRequest.value,\n (result) => {\n if (result) {\n modelOptionRef.value = normalizeListOptions([result])[0];\n }\n },\n);\n\nwatch(\n () => optionsRequest.error,\n (err) => {\n if (err) {\n isLoadingError.value = Boolean(err);\n }\n },\n);\n\nwatch(\n () => optionsRequest.loading || modelOptionRequest.loading,\n (loading) => {\n isLoadingOptions.value = loading;\n },\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\" :title=\"fieldTitle\">\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\n v-if=\"clearable && hasValue\"\n class=\"clear\"\n name=\"delete-clear\"\n @click.stop=\"clear\"\n />\n <slot name=\"append\" />\n <div class=\"pl-autocomplete__arrow-wrapper\" @click.stop=\"toggleOpen\">\n <div\n v-if=\"arrowIconLarge\"\n class=\"arrow-icon\"\n :class=\"[`icon-24 ${arrowIconLarge}`]\"\n />\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\n v-if=\"data.open\"\n ref=\"overlay\"\n :root=\"rootRef\"\n class=\"pl-autocomplete__options\"\n tabindex=\"-1\"\n :gap=\"3\"\n >\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\">\n {{ loadingOptionsHelper }}\n </div>\n <div v-else-if=\"helper\" class=\"pl-autocomplete__helper\">{{ helper }}</div>\n </div>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"PlAutocomplete.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlAutocomplete/PlAutocomplete.vue"],"names":[],"mappings":"AAgdA,OAAO,wBAAwB,CAAC;AAMhC,OAAO,KAAK,EAAE,UAAU,EAAwB,MAAM,aAAa,CAAC;AAiBpE;;GAEG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAKzC,QAAA,MAAM,YAAY,GAAK,CAAC,SAAS,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAC9F,aAAa,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAC9D,YAAY,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,EAC3G,gBAAgB,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAClE;WA4qBO,OAAO,KAAK,EAAE,WAAW,GAAG,mBAAmB,CAAC;QArqBpD;;WAEG;uBACY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QACpF;;WAEG;gBACK,MAAM;QACd;;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;QAC/B;;WAEG;sBACW,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM;QAClC;;aAEK;wBAED,KAAK,GACL,QAAQ,GACR,MAAM,GACN,OAAO,GACP,UAAU,GACV,WAAW,GACX,aAAa,GACb,cAAc,GACd,QAAQ;;QAgRhB;;WAEG;oBACS,CAAC;;;KAkV8E,CAAC,GAAG,CAAC,OAAO,UAAU,SAAS;QAAE,oBAAoB,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,CAAC,GAAG,EAAE,CAAC;YAC5J,CAAC,OAAO,EAAE,EAAE,KAAK,IAAI;WACtB,GAAG;;;;;EAIP,KACQ,OAAO,KAAK,EAAE,KAAK,GAAG;IAAE,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAA;CAAI,CAAC;AACzF,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,CAAC,GAAG,EAAE,CAAC"}
1
+ {"version":3,"file":"PlAutocomplete.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlAutocomplete/PlAutocomplete.vue"],"names":[],"mappings":"AAodA,OAAO,wBAAwB,CAAC;AAMhC,OAAO,KAAK,EAAE,UAAU,EAAwB,MAAM,aAAa,CAAC;AAiBpE;;GAEG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAKzC,QAAA,MAAM,YAAY,GAAK,CAAC,SAAS,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAC9F,aAAa,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAC9D,YAAY,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,EAC3G,gBAAgB,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAClE;WAkrBO,OAAO,KAAK,EAAE,WAAW,GAAG,mBAAmB,CAAC;QA3qBpD;;WAEG;uBACY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QACpF;;WAEG;gBACK,MAAM;QACd;;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;QAC/B;;WAEG;sBACW,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM;QAClC;;aAEK;wBAED,KAAK,GACL,QAAQ,GACR,MAAM,GACN,OAAO,GACP,UAAU,GACV,WAAW,GACX,aAAa,GACb,cAAc,GACd,QAAQ;;QAoRhB;;WAEG;oBACS,CAAC;;;KAoV8E,CAAC,GAAG,CAAC,OAAO,UAAU,SAAS;QAAE,oBAAoB,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,CAAC,GAAG,EAAE,CAAC;YAC5J,CAAC,OAAO,EAAE,EAAE,KAAK,IAAI;WACtB,GAAG;;;;;EAIP,KACQ,OAAO,KAAK,EAAE,KAAK,GAAG;IAAE,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAA;CAAI,CAAC;AACzF,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,CAAC,GAAG,EAAE,CAAC"}
@@ -19,29 +19,29 @@ import re from "../../utils/DropdownOverlay/DropdownOverlay.js";
19
19
  import "../../utils/DropdownOverlay/index.js";
20
20
  import { useWatchFetch as l } from "../../composition/useWatchFetch.js";
21
21
  import ie from "../../assets/images/required.js";
22
- import { Fragment as ae, computed as u, createBlock as d, createCommentVNode as f, createElementBlock as p, createElementVNode as m, createTextVNode as oe, createVNode as h, defineComponent as g, mergeModels as _, normalizeClass as v, openBlock as y, reactive as se, ref as b, renderList as ce, renderSlot as x, toDisplayString as S, unref as C, useModel as w, useSlots as le, useTemplateRef as ue, vModelText as de, watch as T, watchPostEffect as fe, withCtx as E, withDirectives as pe, withModifiers as D } from "vue";
23
- import { isNil as O } from "@milaboratories/helpers";
24
- import { refDebounced as me } from "@vueuse/core";
22
+ import { Fragment as ae, computed as u, createBlock as d, createCommentVNode as f, createElementBlock as p, createElementVNode as m, createTextVNode as oe, createVNode as h, defineComponent as g, mergeModels as _, normalizeClass as v, openBlock as y, reactive as se, ref as b, renderList as ce, renderSlot as x, toDisplayString as S, unref as C, useModel as le, useSlots as ue, useTemplateRef as de, vModelText as fe, watch as w, watchPostEffect as pe, withCtx as T, withDirectives as me, withModifiers as E } from "vue";
23
+ import { isNil as D } from "@milaboratories/helpers";
24
+ import { refDebounced as he } from "@vueuse/core";
25
25
  //#region src/components/PlAutocomplete/PlAutocomplete.vue?vue&type=script&setup=true&lang.ts
26
- var he = ["tabindex"], ge = { class: "pl-autocomplete__container" }, _e = { class: "pl-autocomplete__field" }, k = ["disabled", "placeholder"], A = {
26
+ var ge = ["tabindex"], _e = { class: "pl-autocomplete__container" }, ve = ["title"], O = ["disabled", "placeholder"], k = {
27
27
  key: 0,
28
28
  class: "input-value"
29
- }, j = { class: "pl-autocomplete__controls" }, M = {
29
+ }, A = { class: "pl-autocomplete__controls" }, j = {
30
30
  key: 2,
31
31
  class: "arrow-icon arrow-icon-default"
32
- }, N = { key: 0 }, P = {
32
+ }, M = { key: 0 }, N = {
33
33
  key: 0,
34
34
  class: "nothing-found"
35
- }, F = {
35
+ }, P = {
36
36
  key: 0,
37
37
  class: "pl-autocomplete__error"
38
- }, I = {
38
+ }, F = {
39
39
  key: 1,
40
40
  class: "pl-autocomplete__helper"
41
- }, ve = {
41
+ }, ye = {
42
42
  key: 2,
43
43
  class: "pl-autocomplete__helper"
44
- }, L = /* @__PURE__ */ g({
44
+ }, I = /* @__PURE__ */ g({
45
45
  name: "PlAutocomplete",
46
46
  props: /* @__PURE__ */ _({
47
47
  optionsSearch: {},
@@ -76,38 +76,38 @@ var he = ["tabindex"], ge = { class: "pl-autocomplete__container" }, _e = { clas
76
76
  }),
77
77
  emits: ["update:modelValue"],
78
78
  setup(g) {
79
- let _ = w(g, "modelValue"), L = g, ye = le(), R = b(), z = b(), B = ue("overlay"), V = b(null), H = se({
79
+ let _ = le(g, "modelValue"), I = g, be = ue(), L = b(), R = b(), z = de("overlay"), B = b(null), V = se({
80
80
  activeIndex: -1,
81
81
  open: !1
82
- }), be = () => t(G.value.findIndex((e) => c(e.value, _.value)), (e) => e < 0 ? 0 : e), xe = () => H.activeIndex = be(), U = b([]), W = b(), G = u(() => n(U.value).map((e, t) => ({
82
+ }), xe = () => t(W.value.findIndex((e) => c(e.value, _.value)), (e) => e < 0 ? 0 : e), Se = () => V.activeIndex = xe(), H = b([]), U = b(), W = u(() => n(H.value).map((e, t) => ({
83
83
  ...e,
84
84
  index: t,
85
- isSelected: t === Se.value,
86
- isActive: t === H.activeIndex
87
- }))), K = b(!0), q = b(!1), J = u(() => L.disabled), Se = u(() => U.value.findIndex((e) => c(e.value, _.value))), Y = u(() => {
88
- if (!K.value) {
89
- if (L.error) return i(L.error);
90
- if (q.value) return "Data loading error";
85
+ isSelected: t === Ce.value,
86
+ isActive: t === V.activeIndex
87
+ }))), G = b(!0), K = b(!1), q = u(() => I.disabled), Ce = u(() => H.value.findIndex((e) => c(e.value, _.value))), J = u(() => {
88
+ if (!G.value) {
89
+ if (I.error) return i(I.error);
90
+ if (K.value) return "Data loading error";
91
91
  }
92
- }), X = u(() => {
93
- let e = C(W), t = C(G);
94
- return (e ?? t.find((e) => c(e.value, _.value)) ?? t.find((e) => c(e.value, _.value)))?.label || (_.value ? L.formatValue(_.value) : "");
95
- }), Ce = u(() => !H.open && _.value ? "" : _.value ? String(X.value) : L.placeholder), we = u(() => _.value !== void 0 && _.value !== null), Te = u(() => J.value ? void 0 : "0"), Z = (e) => {
96
- _.value = e?.value, W.value = e, V.value = null, H.open = !1, R?.value?.focus();
97
- }, Ee = () => {
98
- _.value = void 0, W.value = void 0;
99
- }, De = () => z.value?.focus(), Oe = () => {
100
- H.open = !H.open;
92
+ }), Y = u(() => {
93
+ let e = C(U), t = C(W);
94
+ return (e ?? t.find((e) => c(e.value, _.value)) ?? t.find((e) => c(e.value, _.value)))?.label || (_.value ? I.formatValue(_.value) : "");
95
+ }), we = u(() => !V.open && Y.value ? Y.value : void 0), Te = u(() => !V.open && _.value ? "" : _.value ? String(Y.value) : I.placeholder), Ee = u(() => _.value !== void 0 && _.value !== null), De = u(() => q.value ? void 0 : "0"), X = (e) => {
96
+ _.value = e?.value, U.value = e, B.value = null, V.open = !1, L?.value?.focus();
97
+ }, Oe = () => {
98
+ _.value = void 0, U.value = void 0;
99
+ }, ke = () => R.value?.focus(), Z = () => {
100
+ V.open = !V.open;
101
101
  };
102
- T(() => H.open, (e) => {
103
- V.value = e ? "" : null;
102
+ w(() => V.open, (e) => {
103
+ B.value = e ? "" : null;
104
104
  });
105
- let ke = () => {
106
- H.open = !0;
107
- }, Ae = (e) => {
108
- let t = e.relatedTarget;
109
- !R.value?.contains(t) && !B.value?.listRef?.contains(t) && (V.value = null, H.open = !1);
105
+ let Ae = () => {
106
+ V.open = !0;
110
107
  }, je = (e) => {
108
+ let t = e.relatedTarget;
109
+ !L.value?.contains(t) && !z.value?.listRef?.contains(t) && (B.value = null, V.open = !1);
110
+ }, Me = (e) => {
111
111
  if ([
112
112
  "ArrowDown",
113
113
  "ArrowUp",
@@ -115,133 +115,136 @@ var he = ["tabindex"], ge = { class: "pl-autocomplete__container" }, _e = { clas
115
115
  "Escape"
116
116
  ].includes(e.code)) e.preventDefault();
117
117
  else return;
118
- let { open: t, activeIndex: n } = H;
118
+ let { open: t, activeIndex: n } = V;
119
119
  if (!t) {
120
- e.code === "Enter" && (H.open = !0, V.value = "");
120
+ e.code === "Enter" && (V.open = !0, B.value = "");
121
121
  return;
122
122
  }
123
- e.code === "Escape" && (H.open = !1, V.value = null, R.value?.focus());
124
- let r = C(G), { length: i } = r;
123
+ e.code === "Escape" && (V.open = !1, B.value = null, L.value?.focus());
124
+ let r = C(W), { length: i } = r;
125
125
  if (!i) return;
126
- e.code === "Enter" && Z(r.find((e) => e.index === n));
126
+ e.code === "Enter" && X(r.find((e) => e.index === n));
127
127
  let a = r.findIndex((e) => e.index === n) ?? -1, o = e.code === "ArrowDown" ? 1 : e.code === "ArrowUp" ? -1 : 0, s = Math.abs(a + o + i) % i;
128
- H.activeIndex = G.value[s].index ?? -1;
128
+ V.activeIndex = W.value[s].index ?? -1;
129
129
  };
130
- ne(R), T(() => _.value, xe, { immediate: !0 }), T(() => H.open, (e) => e ? z.value?.focus() : ""), fe(() => {
131
- V.value, H.activeIndex >= 0 && H.open && B.value?.scrollIntoActive();
130
+ ne(L), w(() => _.value, Se, { immediate: !0 }), w(() => V.open, (e) => e ? R.value?.focus() : ""), pe(() => {
131
+ B.value, V.activeIndex >= 0 && V.open && z.value?.scrollIntoActive();
132
132
  });
133
- let Me = me(V, 300, { maxWait: 1e3 }), Q = l(() => Me.value, async (e) => O(e) ? void 0 : L.optionsSearch(e, "label")), $ = l(() => _.value, async (e) => O(e) || c(W.value?.value, e) ? W.value : (await L.optionsSearch(String(e), "value")).find((t) => String(t.value) === String(e)));
134
- return T(() => Q.value, (e) => {
135
- e && (U.value = e, V.value !== null && (q.value = !1));
136
- }), T(() => $.value, (e) => {
137
- e && (W.value = n([e])[0]);
138
- }), T(() => Q.error, (e) => {
139
- e && (q.value = !!e);
140
- }), T(() => Q.loading || $.loading, (e) => {
141
- K.value = e;
133
+ let Ne = he(B, 300, { maxWait: 1e3 }), Q = l(() => Ne.value, async (e) => D(e) ? void 0 : I.optionsSearch(e, "label")), $ = l(() => _.value, async (e) => D(e) || c(U.value?.value, e) ? U.value : (await I.optionsSearch(String(e), "value")).find((t) => String(t.value) === String(e)));
134
+ return w(() => Q.value, (e) => {
135
+ e && (H.value = e, B.value !== null && (K.value = !1));
136
+ }), w(() => $.value, (e) => {
137
+ e && (U.value = n([e])[0]);
138
+ }), w(() => Q.error, (e) => {
139
+ e && (K.value = !!e);
140
+ }), w(() => Q.loading || $.loading, (e) => {
141
+ G.value = e;
142
142
  }), (t, n) => (y(), p("div", {
143
143
  class: "pl-autocomplete__envelope",
144
- onClick: D(De, ["stop"])
144
+ onClick: E(ke, ["stop"])
145
145
  }, [m("div", {
146
146
  ref_key: "rootRef",
147
- ref: R,
148
- tabindex: Te.value,
147
+ ref: L,
148
+ tabindex: De.value,
149
149
  class: v(["pl-autocomplete", {
150
- open: H.open,
151
- error: !!Y.value,
152
- disabled: J.value
150
+ open: V.open,
151
+ error: !!J.value,
152
+ disabled: q.value
153
153
  }]),
154
- onKeydown: je,
155
- onFocusout: Ae
156
- }, [m("div", ge, [
157
- m("div", _e, [
158
- pe(m("input", {
154
+ onKeydown: Me,
155
+ onFocusout: je
156
+ }, [m("div", _e, [
157
+ m("div", {
158
+ class: "pl-autocomplete__field",
159
+ title: we.value
160
+ }, [
161
+ me(m("input", {
159
162
  ref_key: "input",
160
- ref: z,
161
- "onUpdate:modelValue": n[0] ||= (e) => V.value = e,
163
+ ref: R,
164
+ "onUpdate:modelValue": n[0] ||= (e) => B.value = e,
162
165
  type: "text",
163
166
  tabindex: "-1",
164
- disabled: J.value,
165
- placeholder: Ce.value,
167
+ disabled: q.value,
168
+ placeholder: Te.value,
166
169
  spellcheck: "false",
167
170
  autocomplete: "chrome-off",
168
- onFocus: ke
169
- }, null, 40, k), [[de, V.value]]),
170
- H.open ? f("", !0) : (y(), p("div", A, [h(a, null, {
171
- default: E(() => [oe(S(X.value), 1)]),
171
+ onFocus: Ae
172
+ }, null, 40, O), [[fe, B.value]]),
173
+ V.open ? f("", !0) : (y(), p("div", k, [h(a, null, {
174
+ default: T(() => [oe(S(Y.value), 1)]),
172
175
  _: 1
173
176
  })])),
174
- m("div", j, [
175
- K.value ? (y(), d(C(s), {
177
+ m("div", A, [
178
+ G.value ? (y(), d(C(s), {
176
179
  key: 0,
177
180
  name: "loading"
178
181
  })) : f("", !0),
179
- g.clearable && we.value ? (y(), d(C(ee), {
182
+ g.clearable && Ee.value ? (y(), d(C(ee), {
180
183
  key: 1,
181
184
  class: "clear",
182
185
  name: "delete-clear",
183
- onClick: D(Ee, ["stop"])
186
+ onClick: E(Oe, ["stop"])
184
187
  })) : f("", !0),
185
188
  x(t.$slots, "append"),
186
189
  m("div", {
187
190
  class: "pl-autocomplete__arrow-wrapper",
188
- onClick: D(Oe, ["stop"])
191
+ onClick: E(Z, ["stop"])
189
192
  }, [g.arrowIconLarge ? (y(), p("div", {
190
193
  key: 0,
191
194
  class: v(["arrow-icon", [`icon-24 ${g.arrowIconLarge}`]])
192
195
  }, null, 2)) : g.arrowIcon ? (y(), p("div", {
193
196
  key: 1,
194
197
  class: v(["arrow-icon", [`icon-16 ${g.arrowIcon}`]])
195
- }, null, 2)) : (y(), p("div", M))])
198
+ }, null, 2)) : (y(), p("div", j))])
196
199
  ])
197
- ]),
198
- g.label ? (y(), p("label", N, [
200
+ ], 8, ve),
201
+ g.label ? (y(), p("label", M, [
199
202
  g.required ? (y(), d(C(o), {
200
203
  key: 0,
201
204
  uri: C(ie)
202
205
  }, null, 8, ["uri"])) : f("", !0),
203
206
  m("span", null, S(g.label), 1),
204
- ye.tooltip ? (y(), d(C(r), {
207
+ be.tooltip ? (y(), d(C(r), {
205
208
  key: 1,
206
209
  class: "info",
207
210
  position: "top"
208
211
  }, {
209
- tooltip: E(() => [x(t.$slots, "tooltip")]),
212
+ tooltip: T(() => [x(t.$slots, "tooltip")]),
210
213
  _: 3
211
214
  })) : f("", !0)
212
215
  ])) : f("", !0),
213
- H.open ? (y(), d(C(re), {
216
+ V.open ? (y(), d(C(re), {
214
217
  key: 1,
215
218
  ref: "overlay",
216
- root: R.value,
219
+ root: L.value,
217
220
  class: "pl-autocomplete__options",
218
221
  tabindex: "-1",
219
222
  gap: 3
220
223
  }, {
221
- default: E(() => [(y(!0), p(ae, null, ce(G.value, (t, n) => (y(), d(e, {
224
+ default: T(() => [(y(!0), p(ae, null, ce(W.value, (t, n) => (y(), d(e, {
222
225
  key: n,
223
226
  option: t,
224
227
  "is-selected": t.isSelected,
225
228
  "is-hovered": t.isActive,
226
229
  size: g.optionSize,
227
- onClick: D((e) => Z(t), ["stop"])
230
+ onClick: E((e) => X(t), ["stop"])
228
231
  }, null, 8, [
229
232
  "option",
230
233
  "is-selected",
231
234
  "is-hovered",
232
235
  "size",
233
236
  "onClick"
234
- ]))), 128)), G.value.length ? f("", !0) : (y(), p("div", P, "Nothing found"))]),
237
+ ]))), 128)), W.value.length ? f("", !0) : (y(), p("div", N, "Nothing found"))]),
235
238
  _: 1
236
239
  }, 8, ["root"])) : f("", !0),
237
240
  h(te, {
238
241
  class: "pl-autocomplete__contour",
239
242
  "group-position": g.groupPosition
240
243
  }, null, 8, ["group-position"])
241
- ])], 42, he), Y.value ? (y(), p("div", F, S(Y.value), 1)) : K.value && g.loadingOptionsHelper ? (y(), p("div", I, S(g.loadingOptionsHelper), 1)) : g.helper ? (y(), p("div", ve, S(g.helper), 1)) : f("", !0)]));
244
+ ])], 42, ge), J.value ? (y(), p("div", P, S(J.value), 1)) : G.value && g.loadingOptionsHelper ? (y(), p("div", F, S(g.loadingOptionsHelper), 1)) : g.helper ? (y(), p("div", ye, S(g.helper), 1)) : f("", !0)]));
242
245
  }
243
246
  });
244
247
  //#endregion
245
- export { L as default };
248
+ export { I as default };
246
249
 
247
250
  //# sourceMappingURL=PlAutocomplete.vue2.js.map