@milaboratories/uikit 2.10.39 → 2.10.41
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 +154 -93
- package/.turbo/turbo-formatter$colon$check.log +2 -2
- package/.turbo/turbo-linter$colon$check.log +2 -2
- package/.turbo/turbo-types$colon$check.log +1 -1
- package/CHANGELOG.md +12 -0
- package/dist/assets/ui.css +1 -1
- package/dist/base/BtnBase.vue2.js +1 -0
- package/dist/base/BtnBase.vue2.js.map +1 -1
- package/dist/colors/index.js +3 -0
- package/dist/components/DataTable/TableComponent.vue2.js +1 -0
- package/dist/components/DataTable/TableComponent.vue2.js.map +1 -1
- package/dist/components/DataTable/assets/data-table-style.css +1 -1
- package/dist/components/PlAccordion/PlAccordionSection.vue.css +1 -1
- package/dist/components/PlAccordion/PlAccordionSection.vue2.js +2 -0
- package/dist/components/PlAccordion/PlAccordionSection.vue2.js.map +1 -1
- package/dist/components/PlAccordion/index.js +2 -0
- package/dist/components/PlAlert/PlAlert.js.map +1 -1
- package/dist/components/PlAlert/PlAlert.vue.d.ts.map +1 -1
- package/dist/components/PlAlert/PlAlert.vue2.js +19 -20
- package/dist/components/PlAlert/PlAlert.vue2.js.map +1 -1
- package/dist/components/PlAlert/index.js +1 -0
- package/dist/components/PlAlert/pl-alert.css +1 -1
- package/dist/components/PlAutocomplete/PlAutocomplete.vue2.js +5 -0
- package/dist/components/PlAutocomplete/PlAutocomplete.vue2.js.map +1 -1
- package/dist/components/PlAutocomplete/index.js +1 -0
- package/dist/components/PlAutocomplete/pl-autocomplete.css +1 -1
- package/dist/components/PlAutocompleteMulti/PlAutocompleteMulti.vue2.js +4 -0
- package/dist/components/PlAutocompleteMulti/PlAutocompleteMulti.vue2.js.map +1 -1
- package/dist/components/PlAutocompleteMulti/index.js +1 -0
- package/dist/components/PlAutocompleteMulti/pl-autocomplete-multi.css +1 -1
- package/dist/components/PlBtnAccent/index.js +1 -0
- package/dist/components/PlBtnAccent/pl-btn-accent.css +1 -1
- package/dist/components/PlBtnDanger/index.js +1 -0
- package/dist/components/PlBtnDanger/pl-btn-danger.css +1 -1
- package/dist/components/PlBtnGhost/PlBtnGhost.vue2.js +1 -0
- package/dist/components/PlBtnGhost/PlBtnGhost.vue2.js.map +1 -1
- package/dist/components/PlBtnGhost/index.js +1 -0
- package/dist/components/PlBtnGhost/pl-btn-ghost.css +1 -1
- package/dist/components/PlBtnGroup/PlBtnGroup.vue2.js +1 -0
- package/dist/components/PlBtnGroup/PlBtnGroup.vue2.js.map +1 -1
- package/dist/components/PlBtnGroup/index.js +1 -0
- package/dist/components/PlBtnGroup/pl-btn-group.css +1 -1
- package/dist/components/PlBtnLink/index.js +1 -0
- package/dist/components/PlBtnPrimary/index.js +1 -0
- package/dist/components/PlBtnPrimary/pl-btn-primary.css +1 -1
- package/dist/components/PlBtnSecondary/index.js +1 -0
- package/dist/components/PlBtnSecondary/pl-btn-secondary.css +1 -1
- package/dist/components/PlBtnSplit/PlBtnSplit.vue2.js +1 -0
- package/dist/components/PlBtnSplit/PlBtnSplit.vue2.js.map +1 -1
- package/dist/components/PlBtnSplit/index.js +1 -0
- package/dist/components/PlChartHistogram/PlChartHistogram.vue.css +1 -1
- package/dist/components/PlChartHistogram/index.js +1 -0
- package/dist/components/PlChartStackedBar/index.js +2 -0
- package/dist/components/PlCheckbox/index.js +1 -0
- package/dist/components/PlCheckbox/pl-checkbox.css +1 -1
- package/dist/components/PlCheckboxGroup/PlCheckboxGroup.vue2.js +1 -0
- package/dist/components/PlCheckboxGroup/PlCheckboxGroup.vue2.js.map +1 -1
- package/dist/components/PlCheckboxGroup/index.js +1 -0
- package/dist/components/PlChip/PlChip.vue2.js +1 -0
- package/dist/components/PlChip/PlChip.vue2.js.map +1 -1
- package/dist/components/PlChip/index.js +1 -0
- package/dist/components/PlChip/pl-chip.css +1 -1
- package/dist/components/PlClipboard/PlClipboard.vue2.js +1 -0
- package/dist/components/PlClipboard/PlClipboard.vue2.js.map +1 -1
- package/dist/components/PlClipboard/index.js +1 -0
- package/dist/components/PlConfirmDialog.vue2.js +3 -0
- package/dist/components/PlConfirmDialog.vue2.js.map +1 -1
- package/dist/components/PlDialogModal/PlDialogModal.vue2.js +1 -1
- package/dist/components/PlDialogModal/index.js +1 -0
- package/dist/components/PlDropdown/OptionList.vue2.js +1 -0
- package/dist/components/PlDropdown/OptionList.vue2.js.map +1 -1
- package/dist/components/PlDropdown/PlDropdown.vue2.js +4 -0
- package/dist/components/PlDropdown/PlDropdown.vue2.js.map +1 -1
- package/dist/components/PlDropdown/index.js +1 -0
- package/dist/components/PlDropdown/pl-dropdown.css +1 -1
- package/dist/components/PlDropdownLegacy/PlDropdownLegacy.vue2.js +4 -0
- package/dist/components/PlDropdownLegacy/PlDropdownLegacy.vue2.js.map +1 -1
- package/dist/components/PlDropdownLegacy/index.js +1 -0
- package/dist/components/PlDropdownLine/index.js +1 -0
- package/dist/components/PlDropdownLine/pl-dropdown-line.css +1 -1
- package/dist/components/PlDropdownLine/resizable-input.css +1 -1
- package/dist/components/PlDropdownMulti/PlDropdownMulti.vue2.js +4 -0
- package/dist/components/PlDropdownMulti/PlDropdownMulti.vue2.js.map +1 -1
- package/dist/components/PlDropdownMulti/index.js +1 -0
- package/dist/components/PlDropdownMulti/pl-dropdown-multi.css +1 -1
- package/dist/components/PlDropdownMultiRef/index.js +1 -0
- package/dist/components/PlDropdownRef/PlDropdownRef.vue2.js +1 -0
- package/dist/components/PlDropdownRef/PlDropdownRef.vue2.js.map +1 -1
- package/dist/components/PlDropdownRef/index.js +1 -0
- package/dist/components/PlEditableTitle/index.js +1 -0
- package/dist/components/PlEditableTitle/pl-editable-title.css +1 -1
- package/dist/components/PlElementList/PlElementListItem.vue.css +1 -1
- package/dist/components/PlElementList/PlElementListItem.vue2.js +2 -0
- package/dist/components/PlElementList/PlElementListItem.vue2.js.map +1 -1
- package/dist/components/PlElementList/index.js +1 -0
- package/dist/components/PlErrorAlert/PlErrorAlert.vue.css +1 -1
- package/dist/components/PlErrorAlert/PlErrorAlert.vue2.js +2 -0
- package/dist/components/PlErrorAlert/PlErrorAlert.vue2.js.map +1 -1
- package/dist/components/PlErrorAlert/index.js +1 -0
- package/dist/components/PlErrorBoundary/PlErrorBoundary.vue2.js +1 -0
- package/dist/components/PlErrorBoundary/PlErrorBoundary.vue2.js.map +1 -1
- package/dist/components/PlErrorBoundary/index.js +1 -0
- package/dist/components/PlFileDialog/Local.vue2.js +1 -0
- package/dist/components/PlFileDialog/Local.vue2.js.map +1 -1
- package/dist/components/PlFileDialog/PlFileDialog.vue2.js +4 -0
- package/dist/components/PlFileDialog/PlFileDialog.vue2.js.map +1 -1
- package/dist/components/PlFileDialog/Remote.vue2.js +4 -0
- package/dist/components/PlFileDialog/Remote.vue2.js.map +1 -1
- package/dist/components/PlFileDialog/Shortcuts.vue2.js +1 -0
- package/dist/components/PlFileDialog/Shortcuts.vue2.js.map +1 -1
- package/dist/components/PlFileDialog/index.js +1 -0
- package/dist/components/PlFileDialog/pl-file-dialog.css +1 -1
- package/dist/components/PlFileInput/PlFileInput.vue2.js +4 -0
- package/dist/components/PlFileInput/PlFileInput.vue2.js.map +1 -1
- package/dist/components/PlFileInput/index.js +1 -0
- package/dist/components/PlIcon16/PlIcon16.vue2.js +1 -0
- package/dist/components/PlIcon16/PlIcon16.vue2.js.map +1 -1
- package/dist/components/PlIcon16/index.js +1 -0
- package/dist/components/PlIcon24/PlIcon24.vue2.js +1 -0
- package/dist/components/PlIcon24/PlIcon24.vue2.js.map +1 -1
- package/dist/components/PlIcon24/index.js +1 -0
- package/dist/components/PlLoaderCircular/index.js +1 -0
- package/dist/components/PlLoaderLogo.vue.css +1 -1
- package/dist/components/PlLogView/PlLogView.vue2.js +3 -0
- package/dist/components/PlLogView/PlLogView.vue2.js.map +1 -1
- package/dist/components/PlLogView/index.js +1 -0
- package/dist/components/PlMaskIcon16/index.js +1 -0
- package/dist/components/PlMaskIcon24/index.js +1 -0
- package/dist/components/PlNotificationAlert/PlNotificationAlert.vue2.js +1 -0
- package/dist/components/PlNotificationAlert/PlNotificationAlert.vue2.js.map +1 -1
- package/dist/components/PlNotificationAlert/index.js +1 -0
- package/dist/components/PlNumberField/PlNumberField.vue2.js +1 -0
- package/dist/components/PlNumberField/PlNumberField.vue2.js.map +1 -1
- package/dist/components/PlNumberField/index.js +1 -0
- package/dist/components/PlProgressBar/index.js +1 -0
- package/dist/components/PlProgressCell/PlProgressCell.vue2.js +1 -0
- package/dist/components/PlProgressCell/PlProgressCell.vue2.js.map +1 -1
- package/dist/components/PlProgressCell/index.js +1 -0
- package/dist/components/PlRadio/PlRadio.vue.css +1 -1
- package/dist/components/PlRadio/index.js +2 -0
- package/dist/components/PlSearchField/PlSearchField.vue2.js +2 -0
- package/dist/components/PlSearchField/PlSearchField.vue2.js.map +1 -1
- package/dist/components/PlSearchField/index.js +1 -0
- package/dist/components/PlSectionSeparator/PlSectionSeparator.vue.css +1 -1
- package/dist/components/PlSectionSeparator/index.js +1 -0
- package/dist/components/PlSidebar/PlSidebarGroup.vue.css +1 -1
- package/dist/components/PlSidebar/PlSidebarItem.vue.css +1 -1
- package/dist/components/PlSidebar/index.js +2 -0
- package/dist/components/PlSlideModal/PlPureSlideModal.js.map +1 -1
- package/dist/components/PlSlideModal/PlPureSlideModal.vue.d.ts.map +1 -1
- package/dist/components/PlSlideModal/PlPureSlideModal.vue2.js +13 -12
- package/dist/components/PlSlideModal/PlPureSlideModal.vue2.js.map +1 -1
- package/dist/components/PlSlideModal/index.js +2 -0
- package/dist/components/PlSlideModal/pl-slide-modal.css +1 -1
- package/dist/components/PlSplash/PlSplash.vue2.js +1 -0
- package/dist/components/PlSplash/PlSplash.vue2.js.map +1 -1
- package/dist/components/PlSplash/index.js +1 -0
- package/dist/components/PlSplash/pl-splash.css +1 -1
- package/dist/components/PlStatusTag/index.js +1 -0
- package/dist/components/PlSvg/index.js +1 -0
- package/dist/components/PlTabs/Tab.vue2.js +1 -0
- package/dist/components/PlTabs/Tab.vue2.js.map +1 -1
- package/dist/components/PlTabs/index.js +1 -0
- package/dist/components/PlTextArea/PlTextArea.vue2.js +2 -0
- package/dist/components/PlTextArea/PlTextArea.vue2.js.map +1 -1
- package/dist/components/PlTextArea/index.js +1 -0
- package/dist/components/PlTextField/PlTextField.vue2.js +4 -0
- package/dist/components/PlTextField/PlTextField.vue2.js.map +1 -1
- package/dist/components/PlTextField/index.js +1 -0
- package/dist/components/PlToggleSwitch/index.js +1 -0
- package/dist/components/PlTooltip/index.js +1 -0
- package/dist/components/Slider.vue2.js +1 -0
- package/dist/components/Slider.vue2.js.map +1 -1
- package/dist/components/SliderRange.vue2.js +1 -0
- package/dist/components/SliderRange.vue2.js.map +1 -1
- package/dist/components/SliderRangeTriple.vue2.js +1 -0
- package/dist/components/SliderRangeTriple.vue2.js.map +1 -1
- package/dist/components/contextMenu/Menu.style.css +1 -1
- package/dist/index.js +79 -20
- package/dist/index.js.map +1 -1
- package/dist/layout/PlBlockPage/PlBlockPage.vue.css +1 -1
- package/dist/layout/PlBlockPage/PlBlockPage.vue2.js +1 -0
- package/dist/layout/PlBlockPage/PlBlockPage.vue2.js.map +1 -1
- package/dist/layout/PlBlockPage/index.js +2 -0
- package/dist/layout/PlContainer/index.js +1 -0
- package/dist/layout/PlGrid/index.js +1 -0
- package/dist/layout/PlPlaceholder/PlPlaceholder.vue.css +1 -1
- package/dist/layout/PlRow/index.js +1 -0
- package/dist/layout/PlSpacer/index.js +1 -0
- package/dist/utils/DoubleContour.style.css +1 -1
- package/dist/utils/DropdownOverlay/index.js +1 -0
- package/dist/utils/PlCloseModalBtn.vue.css +1 -1
- package/package.json +3 -6
- package/src/components/PlAlert/PlAlert.vue +3 -3
- package/src/components/PlAlert/pl-alert.scss +0 -7
- package/src/components/PlSlideModal/PlPureSlideModal.vue +5 -2
- package/src/components/PlSlideModal/pl-slide-modal.scss +0 -8
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import e from "../components/PlIcon16/PlIcon16.js";
|
|
2
|
+
import "../components/PlMaskIcon16/index.js";
|
|
2
3
|
import { useRipple as t } from "../composition/useRipple.js";
|
|
3
4
|
import { computed as n, createBlock as r, createCommentVNode as i, createElementBlock as a, defineComponent as o, mergeProps as s, openBlock as c, ref as l, renderSlot as u, unref as d } from "vue";
|
|
4
5
|
var f = { key: 0 }, p = /* @__PURE__ */ o({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BtnBase.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../src/base/BtnBase.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n inheritAttrs: false,\n};\n</script>\n\n<script lang=\"ts\" setup>\nimport type { MaskIconName16, Size } from \"../types\";\nimport { computed, ref } from \"vue\";\nimport { PlMaskIcon16 } from \"../components/PlMaskIcon16\";\nimport { useRipple } from \"../composition/useRipple\";\n\nconst props = defineProps<{\n loading?: boolean;\n small?: boolean;\n large?: boolean;\n size?: Size;\n round?: boolean;\n icon?: MaskIconName16;\n reverse?: boolean;\n justifyCenter?: boolean;\n}>();\n\nconst btn = ref();\n\nconst small = computed(() => props.small || props.size === \"small\");\nconst large = computed(() => props.large || props.size === \"large\");\n\nuseRipple(btn);\n</script>\n\n<template>\n <button\n ref=\"btn\"\n tabindex=\"0\"\n :class=\"{ loading, small, large, round, reverse, justifyCenter, [$attrs.class + '']: true }\"\n v-bind=\"{ ...$attrs, disabled: Boolean($attrs.disabled) || loading }\"\n >\n <span v-if=\"!round\">\n <slot />\n </span>\n <slot name=\"icon\">\n <PlMaskIcon16 v-if=\"loading\" name=\"loading\" :size=\"size\" />\n <PlMaskIcon16 v-else-if=\"icon\" :name=\"icon\" :size=\"size\" />\n </slot>\n </button>\n</template>\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"BtnBase.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../src/base/BtnBase.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n inheritAttrs: false,\n};\n</script>\n\n<script lang=\"ts\" setup>\nimport type { MaskIconName16, Size } from \"../types\";\nimport { computed, ref } from \"vue\";\nimport { PlMaskIcon16 } from \"../components/PlMaskIcon16\";\nimport { useRipple } from \"../composition/useRipple\";\n\nconst props = defineProps<{\n loading?: boolean;\n small?: boolean;\n large?: boolean;\n size?: Size;\n round?: boolean;\n icon?: MaskIconName16;\n reverse?: boolean;\n justifyCenter?: boolean;\n}>();\n\nconst btn = ref();\n\nconst small = computed(() => props.small || props.size === \"small\");\nconst large = computed(() => props.large || props.size === \"large\");\n\nuseRipple(btn);\n</script>\n\n<template>\n <button\n ref=\"btn\"\n tabindex=\"0\"\n :class=\"{ loading, small, large, round, reverse, justifyCenter, [$attrs.class + '']: true }\"\n v-bind=\"{ ...$attrs, disabled: Boolean($attrs.disabled) || loading }\"\n >\n <span v-if=\"!round\">\n <slot />\n </span>\n <slot name=\"icon\">\n <PlMaskIcon16 v-if=\"loading\" name=\"loading\" :size=\"size\" />\n <PlMaskIcon16 v-else-if=\"icon\" :name=\"icon\" :size=\"size\" />\n </slot>\n </button>\n</template>\n"],"mappings":";;;;;CAEE,cAAc;;;;;;;;;;;;;EAUhB,IAAM,IAAQ,GAWR,IAAM,GAAK,EAEX,IAAQ,QAAe,EAAM,SAAS,EAAM,SAAS,QAAQ,EAC7D,IAAQ,QAAe,EAAM,SAAS,EAAM,SAAS,QAAQ;SAEnE,EAAU,EAAI,kBAIZ,EAaS,UAbT,EAaS;YAZH;GAAJ,KAAI;GACJ,UAAS;GACR,OAAK;IAAA,SAAI,EAAA;IAAO,OAAE,EAAA;IAAK,OAAE,EAAA;IAAK,OAAE,EAAA;IAAK,SAAE,EAAA;IAAO,eAAE,EAAA;KAAgBA,EAAAA,OAAO,QAAK,KAAA;IAAA;;MAChEA,EAAAA;GAAM,UAAY,EAAQA,EAAAA,OAAO,YAAa,EAAA;GAAO,CAAA,EAAA,CAErD,EAAA,QACH,EAAA,IAAA,GAAA,IADG,GAAA,EAAb,EAEO,QAAA,GAAA,CADL,EAAQ,EAAA,QAAA,UAAA,CAAA,CAAA,GAEV,EAGO,EAAA,QAAA,QAAA,EAAA,QAAA,CAFe,EAAA,WAAA,GAAA,EAApB,EAA2D,EAAA,EAAA,EAAA;;GAA9B,MAAK;GAAW,MAAM,EAAA;2BAC1B,EAAA,QAAA,GAAA,EAAzB,EAA2D,EAAA,EAAA,EAAA;;GAA3B,MAAM,EAAA;GAAO,MAAM,EAAA"}
|
|
@@ -11,6 +11,7 @@ import c from "./RowsCommandMenu.js";
|
|
|
11
11
|
import l from "./ColumnsCommandMenu.js";
|
|
12
12
|
import u from "./TScroll.js";
|
|
13
13
|
import { createState as d } from "./state.js";
|
|
14
|
+
import "../../index.js";
|
|
14
15
|
import { Fragment as f, computed as p, createBlock as m, createCommentVNode as h, createElementBlock as g, createElementVNode as _, createVNode as v, defineComponent as y, nextTick as b, normalizeStyle as x, onMounted as S, openBlock as C, ref as w, renderList as T, unref as E, watch as D, watchPostEffect as O, withCtx as k } from "vue";
|
|
15
16
|
import { tapIf as A } from "@milaboratories/helpers";
|
|
16
17
|
var j = { class: "command-menu__container" }, M = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableComponent.vue_vue_type_script_setup_true_lang.js","names":["$emit"],"sources":["../../../src/components/DataTable/TableComponent.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport \"./assets/data-table-style.scss\";\nimport { ref, unref, onMounted, nextTick, watchPostEffect, watch, computed } from \"vue\";\nimport TdCell from \"./TdCell.vue\";\nimport type { TableSettings, TableData } from \"./types\";\nimport TableIcon from \"./assets/TableIcon.vue\";\nimport TrHead from \"./TrHead.vue\";\nimport ThCell from \"./ThCell.vue\";\nimport TrBody from \"./TrBody.vue\";\nimport ColumnCaret from \"./ColumnCaret.vue\";\nimport { useEventListener } from \"../../index\";\nimport { tapIf } from \"@milaboratories/helpers\";\nimport { useResize } from \"./composition/useResize\";\nimport RowsCommandMenu from \"./RowsCommandMenu.vue\";\nimport ColumnsCommandMenu from \"./ColumnsCommandMenu.vue\";\nimport TScroll from \"./TScroll.vue\";\nimport { createState } from \"./state\";\n\nconst emit = defineEmits<{\n (e: \"update:data\", value: TableData): void;\n (e: \"change:sort\", value: unknown): void;\n}>();\n\nconst props = defineProps<{\n settings: Readonly<TableSettings>;\n}>();\n\nconst state = createState(props);\n\nconst hasNoData = computed(() => state.data.rows.length === 0);\n\nconst tableBodyStyle = computed(() => ({\n height: hasNoData.value ? \"212px\" /* css value */ : state.data.bodyHeight + \"px\",\n}));\n\nwatch(state.data, (v) => emit(\"update:data\", v), { deep: true });\n\nwatch(props, () => updateDimensions);\n\nconst tableRef = ref<HTMLElement>();\nconst headRef = ref<HTMLElement>();\nconst bodyRef = ref<HTMLElement>();\n\nconst updateDimensions = () => {\n tapIf(bodyRef.value, (el) => {\n state.updateDimensions(el.getBoundingClientRect());\n });\n};\n\nconst tableColumns = state.tableColumns;\n\nconst tableRows = state.tableRows;\n\nconst { mouseDown } = useResize(state, tableRef);\n\nonMounted(() => {\n nextTick(updateDimensions);\n});\n\nwatchPostEffect(() => {\n unref(props.settings);\n nextTick(updateDimensions);\n});\n\nuseEventListener(window, \"resize\", () => nextTick(updateDimensions));\n\nconst onWheel = (ev: WheelEvent) => {\n ev.preventDefault();\n state.updateOffsets(ev);\n};\n</script>\n\n<template>\n <div ref=\"tableRef\" class=\"data-table\" @mousedown=\"mouseDown\">\n <div class=\"command-menu__container\">\n <RowsCommandMenu />\n <ColumnsCommandMenu />\n </div>\n <div ref=\"headRef\" class=\"table-head\">\n <TrHead>\n <ThCell\n v-for=\"(col, i) in tableColumns\"\n :key=\"i\"\n :col=\"col\"\n :style=\"col.style\"\n @change:sort=\"$emit('change:sort', $event)\"\n />\n </TrHead>\n </div>\n <div ref=\"bodyRef\" class=\"table-body\" :style=\"tableBodyStyle\" @wheel=\"onWheel\">\n <div v-if=\"hasNoData\" class=\"table-body__no-data\">\n <div>\n <TableIcon />\n <div>No Data To Show</div>\n </div>\n </div>\n <TrBody v-for=\"(row, i) in tableRows\" :key=\"i\" :row=\"row\">\n <TdCell\n v-for=\"cell in row.cells\"\n :key=\"cell.column.id + ':' + i\"\n :cell=\"cell\"\n :style=\"cell.style\"\n />\n </TrBody>\n </div>\n <div class=\"carets\">\n <ColumnCaret\n v-for=\"(col, i) in tableColumns\"\n :key=\"i\"\n :column=\"col\"\n :style=\"col.style\"\n @change:sort=\"$emit('change:sort', $event)\"\n />\n </div>\n <TScroll\n :offset=\"state.data.scrollTop\"\n :window-size=\"state.data.bodyHeight\"\n :data-size=\"state.data.dataHeight\"\n @change:offset=\"state.updateScrollTop\"\n />\n </div>\n</template>\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"TableComponent.vue_vue_type_script_setup_true_lang.js","names":["$emit"],"sources":["../../../src/components/DataTable/TableComponent.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport \"./assets/data-table-style.scss\";\nimport { ref, unref, onMounted, nextTick, watchPostEffect, watch, computed } from \"vue\";\nimport TdCell from \"./TdCell.vue\";\nimport type { TableSettings, TableData } from \"./types\";\nimport TableIcon from \"./assets/TableIcon.vue\";\nimport TrHead from \"./TrHead.vue\";\nimport ThCell from \"./ThCell.vue\";\nimport TrBody from \"./TrBody.vue\";\nimport ColumnCaret from \"./ColumnCaret.vue\";\nimport { useEventListener } from \"../../index\";\nimport { tapIf } from \"@milaboratories/helpers\";\nimport { useResize } from \"./composition/useResize\";\nimport RowsCommandMenu from \"./RowsCommandMenu.vue\";\nimport ColumnsCommandMenu from \"./ColumnsCommandMenu.vue\";\nimport TScroll from \"./TScroll.vue\";\nimport { createState } from \"./state\";\n\nconst emit = defineEmits<{\n (e: \"update:data\", value: TableData): void;\n (e: \"change:sort\", value: unknown): void;\n}>();\n\nconst props = defineProps<{\n settings: Readonly<TableSettings>;\n}>();\n\nconst state = createState(props);\n\nconst hasNoData = computed(() => state.data.rows.length === 0);\n\nconst tableBodyStyle = computed(() => ({\n height: hasNoData.value ? \"212px\" /* css value */ : state.data.bodyHeight + \"px\",\n}));\n\nwatch(state.data, (v) => emit(\"update:data\", v), { deep: true });\n\nwatch(props, () => updateDimensions);\n\nconst tableRef = ref<HTMLElement>();\nconst headRef = ref<HTMLElement>();\nconst bodyRef = ref<HTMLElement>();\n\nconst updateDimensions = () => {\n tapIf(bodyRef.value, (el) => {\n state.updateDimensions(el.getBoundingClientRect());\n });\n};\n\nconst tableColumns = state.tableColumns;\n\nconst tableRows = state.tableRows;\n\nconst { mouseDown } = useResize(state, tableRef);\n\nonMounted(() => {\n nextTick(updateDimensions);\n});\n\nwatchPostEffect(() => {\n unref(props.settings);\n nextTick(updateDimensions);\n});\n\nuseEventListener(window, \"resize\", () => nextTick(updateDimensions));\n\nconst onWheel = (ev: WheelEvent) => {\n ev.preventDefault();\n state.updateOffsets(ev);\n};\n</script>\n\n<template>\n <div ref=\"tableRef\" class=\"data-table\" @mousedown=\"mouseDown\">\n <div class=\"command-menu__container\">\n <RowsCommandMenu />\n <ColumnsCommandMenu />\n </div>\n <div ref=\"headRef\" class=\"table-head\">\n <TrHead>\n <ThCell\n v-for=\"(col, i) in tableColumns\"\n :key=\"i\"\n :col=\"col\"\n :style=\"col.style\"\n @change:sort=\"$emit('change:sort', $event)\"\n />\n </TrHead>\n </div>\n <div ref=\"bodyRef\" class=\"table-body\" :style=\"tableBodyStyle\" @wheel=\"onWheel\">\n <div v-if=\"hasNoData\" class=\"table-body__no-data\">\n <div>\n <TableIcon />\n <div>No Data To Show</div>\n </div>\n </div>\n <TrBody v-for=\"(row, i) in tableRows\" :key=\"i\" :row=\"row\">\n <TdCell\n v-for=\"cell in row.cells\"\n :key=\"cell.column.id + ':' + i\"\n :cell=\"cell\"\n :style=\"cell.style\"\n />\n </TrBody>\n </div>\n <div class=\"carets\">\n <ColumnCaret\n v-for=\"(col, i) in tableColumns\"\n :key=\"i\"\n :column=\"col\"\n :style=\"col.style\"\n @change:sort=\"$emit('change:sort', $event)\"\n />\n </div>\n <TScroll\n :offset=\"state.data.scrollTop\"\n :window-size=\"state.data.bodyHeight\"\n :data-size=\"state.data.dataHeight\"\n @change:offset=\"state.updateScrollTop\"\n />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;EAkBA,IAAM,IAAO,GAKP,IAAQ,GAIR,IAAQ,EAAY,EAAM,EAE1B,IAAY,QAAe,EAAM,KAAK,KAAK,WAAW,EAAE,EAExD,IAAiB,SAAgB,EACrC,QAAQ,EAAU,QAAQ,UAA0B,EAAM,KAAK,aAAa,MAC7E,EAAE;AAIH,EAFA,EAAM,EAAM,OAAO,MAAM,EAAK,eAAe,EAAE,EAAE,EAAE,MAAM,IAAM,CAAC,EAEhE,EAAM,SAAa,EAAiB;EAEpC,IAAM,IAAW,GAAkB,EAC7B,IAAU,GAAkB,EAC5B,IAAU,GAAkB,EAE5B,UAAyB;AAC7B,KAAM,EAAQ,QAAQ,MAAO;AAC3B,MAAM,iBAAiB,EAAG,uBAAuB,CAAC;KAClD;KAGE,IAAe,EAAM,cAErB,IAAY,EAAM,WAElB,EAAE,iBAAc,EAAU,GAAO,EAAS;AAWhD,EATA,QAAgB;AACd,KAAS,EAAiB;IAC1B,EAEF,QAAsB;AAEpB,GADA,EAAM,EAAM,SAAS,EACrB,EAAS,EAAiB;IAC1B,EAEF,EAAiB,QAAQ,gBAAgB,EAAS,EAAiB,CAAC;EAEpE,IAAM,KAAW,MAAmB;AAElC,GADA,EAAG,gBAAgB,EACnB,EAAM,cAAc,EAAG;;yBAKvB,EA+CM,OAAA;YA/CG;GAAJ,KAAI;GAAW,OAAM;GAAc,aAAS,AAAA,EAAA,QAAA,GAAA,MAAE,EAAA,EAAA,IAAA,EAAA,EAAA,CAAA,GAAA,EAAS;;GAC1D,EAGM,OAHN,GAGM,CAFJ,EAAmB,EAAA,EACnB,EAAsB,EAAA,CAAA,CAAA;GAExB,EAUM,OAAA;aAVG;IAAJ,KAAI;IAAU,OAAM;OACvB,EAQS,GAAA,MAAA;qBAN2B,EAAA,EAAA,GAAA,EADlC,EAME,GAAA,MAAA,EALmB,EAAA,EAAY,GAAvB,GAAK,YADf,EAME,GAAA;KAJC,KAAK;KACA;KACL,OAAK,EAAE,EAAI,MAAK;KAChB,iBAAW,AAAA,EAAA,QAAA,MAAEA,EAAAA,MAAK,eAAgB,EAAM;;;;GAI/C,EAeM,OAAA;aAfG;IAAJ,KAAI;IAAU,OAAM;IAAc,OAAK,EAAE,EAAA,MAAc;IAAU;OACzD,EAAA,SAAA,GAAA,EAAX,EAKM,OALN,GAKM,CAJJ,EAGM,OAAA,MAAA,CAFJ,EAAa,EAAA,EAAA,AAAA,EAAA,OACb,EAA0B,OAAA,MAArB,mBAAe,GAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EAAA,IAAA,GAAA,GAAA,EAAA,GAAA,EAGxB,EAOS,GAAA,MAAA,EAPkB,EAAA,EAAS,GAApB,GAAK,YAArB,EAOS,GAAA;IAP8B,KAAK;IAAS;;qBAExB,EAAA,EAAA,GAAA,EAD3B,EAKE,GAAA,MAAA,EAJe,EAAI,QAAZ,YADT,EAKE,GAAA;KAHC,KAAK,EAAK,OAAO,KAAE,MAAS;KACtB;KACN,OAAK,EAAE,EAAK,MAAK;;;;GAIxB,EAQM,OARN,GAQM,EAAA,EAAA,GAAA,EAPJ,EAME,GAAA,MAAA,EALmB,EAAA,EAAY,GAAvB,GAAK,YADf,EAME,GAAA;IAJC,KAAK;IACL,QAAQ;IACR,OAAK,EAAE,EAAI,MAAK;IAChB,iBAAW,AAAA,EAAA,QAAA,MAAEA,EAAAA,MAAK,eAAgB,EAAM;;GAG7C,EAKE,GAAA;IAJC,QAAQ,EAAA,EAAK,CAAC,KAAK;IACnB,eAAa,EAAA,EAAK,CAAC,KAAK;IACxB,aAAW,EAAA,EAAK,CAAC,KAAK;IACtB,mBAAe,EAAA,EAAK,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.data-table{--cell-font-family:var(--font-family-base);--cell-font-weight:500;--selected-bg:#63e0241f;border:1px solid var(--bg-elevated-02);border-radius:6px;flex-direction:column;width:100%;max-height:100%;font-weight:500;position:relative}.data-table.monospace{--cell-font-family:var(--font-family-monospace);--cell-font-weight:400}.data-table .t-scroll{--handle-bg:#ccc;z-index:1;width:0;position:absolute;bottom:0;right:0}.data-table .t-scroll>div{width:0;position:absolute;top:6px;bottom:6px}.data-table .t-scroll__handle{background-color:var(--handle-bg);cursor:pointer;width:12px;position:absolute;transform:translate(-50%)}.data-table .t-scroll__handle:before{background-color:var(--handle-bg);content:"";border-radius:6px 6px 0 0;width:100%;height:6px;position:absolute;top:-6px}.data-table .t-scroll__handle:after{background-color:var(--handle-bg);content:"";border-radius:0 0 6px 6px;width:100%;height:6px;position:absolute;bottom:-6px}.data-table .carets{pointer-events:none;position:absolute;inset:0;overflow:hidden}.data-table .column-caret{pointer-events:none;height:100%;position:absolute;top:0}.data-table .column-caret.selected{outline:1px solid var(--border-color-focus);background:var(--selected-bg)}.data-table .column-caret.frozen{z-index:1;box-shadow:10px 0 5px -2px #888}.data-table .command-menu{color:#fff;background:#110529;border-radius:6px;flex-shrink:0;align-items:center;gap:12px;height:40px;padding:0 12px;display:inline-flex;box-shadow:0 4px 12px -2px #0f244d14,0 6px 24px -2px #0f244d14}.data-table .command-menu hr{opacity:.24;background-color:#9babcc;width:1px;height:100%;margin:12px 0}.data-table .command-menu span.command{color:#fff;cursor:pointer;font-weight:600}.data-table .command-menu__container{z-index:1000;gap:12px;width:100%;display:flex;position:absolute;top:-45px;left:0}.data-table .table-head{background-color:var(--bg-elevated-02);border-bottom:1px solid var(--txt-01);max-width:100%;padding-bottom:1px;position:relative;overflow:hidden}.data-table .table-head .tr-head{background-color:#0000;flex-direction:row;gap:1px;max-width:100%;min-height:40px;display:flex;position:relative;overflow:hidden}.data-table .table-head .th-cell{
|
|
1
|
+
.data-table{--cell-font-family:var(--font-family-base);--cell-font-weight:500;--selected-bg:#63e0241f;border:1px solid var(--bg-elevated-02);border-radius:6px;flex-direction:column;width:100%;max-height:100%;font-weight:500;position:relative}.data-table.monospace{--cell-font-family:var(--font-family-monospace);--cell-font-weight:400}.data-table .t-scroll{--handle-bg:#ccc;z-index:1;width:0;position:absolute;bottom:0;right:0}.data-table .t-scroll>div{width:0;position:absolute;top:6px;bottom:6px}.data-table .t-scroll__handle{background-color:var(--handle-bg);cursor:pointer;width:12px;position:absolute;transform:translate(-50%)}.data-table .t-scroll__handle:before{background-color:var(--handle-bg);content:"";border-radius:6px 6px 0 0;width:100%;height:6px;position:absolute;top:-6px}.data-table .t-scroll__handle:after{background-color:var(--handle-bg);content:"";border-radius:0 0 6px 6px;width:100%;height:6px;position:absolute;bottom:-6px}.data-table .carets{pointer-events:none;position:absolute;inset:0;overflow:hidden}.data-table .column-caret{pointer-events:none;height:100%;position:absolute;top:0}.data-table .column-caret.selected{outline:1px solid var(--border-color-focus);background:var(--selected-bg)}.data-table .column-caret.frozen{z-index:1;box-shadow:10px 0 5px -2px #888}.data-table .command-menu{color:#fff;background:#110529;border-radius:6px;flex-shrink:0;align-items:center;gap:12px;height:40px;padding:0 12px;display:inline-flex;box-shadow:0 4px 12px -2px #0f244d14,0 6px 24px -2px #0f244d14}.data-table .command-menu hr{opacity:.24;background-color:#9babcc;width:1px;height:100%;margin:12px 0}.data-table .command-menu span.command{color:#fff;cursor:pointer;font-weight:600}.data-table .command-menu__container{z-index:1000;gap:12px;width:100%;display:flex;position:absolute;top:-45px;left:0}.data-table .table-head{background-color:var(--bg-elevated-02);border-bottom:1px solid var(--txt-01);max-width:100%;padding-bottom:1px;position:relative;overflow:hidden}.data-table .table-head .tr-head{background-color:#0000;flex-direction:row;gap:1px;max-width:100%;min-height:40px;display:flex;position:relative;overflow:hidden}.data-table .table-head .th-cell{user-select:none;white-space:nowrap;background-color:#f7f8fa;align-items:center;height:100%;padding:8px 12px;font-size:14px;font-weight:600;display:flex;position:absolute;overflow:hidden}.data-table .table-head .th-cell .integer,.data-table .table-head .th-cell .float{background:url("data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M4.22886%2012.993H5.65686L6.41286%2010.158H8.33786L7.58886%2012.993H9.01686L9.77286%2010.158H12.4189L12.7829%208.76501H10.1439L10.6409%206.92401H13.2869L13.6509%205.54501H11.0119L11.7189%202.92001H10.2839L9.57686%205.54501H7.65186L8.35886%202.92001H6.92386L6.21686%205.54501H3.58486L3.20686%206.92401H5.84586L5.36286%208.76501H2.71686L2.34586%2010.158H4.98486L4.22886%2012.993ZM6.79086%208.76501L7.28086%206.92401H9.20586L8.70886%208.76501H6.79086Z'%20fill='%2307AD3E'/%3e%3c/svg%3e") 50% no-repeat;width:16px;height:16px;margin-right:4px}.data-table .table-head .th-cell .string{background:url("data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M0.0372314%2013H1.55623L2.29123%2010.725H6.42823L7.17723%2013H8.69623L5.42023%202.92001H3.31323L0.0372314%2013ZM2.73923%209.35301L4.34923%204.38301L5.98023%209.35301H2.73923Z'%20fill='%2307AD3E'/%3e%3cpath%20d='M11.3871%2013.21C12.6121%2013.21%2013.4871%2012.79%2014.1101%2011.901V13H15.4051V8.34501C15.4051%207.71501%2015.3771%207.16901%2015.1391%206.67201C14.6701%205.67801%2013.6201%205.23001%2012.2691%205.23001C10.5191%205.23001%209.46908%206.05601%209.10508%207.35101L10.4701%207.77101C10.7291%206.93101%2011.4571%206.58101%2012.2551%206.58101C13.4381%206.58101%2013.9141%207.07101%2013.9631%208.11401C12.7381%208.28201%2011.4921%208.44301%2010.6171%208.70201C9.44808%209.07301%208.83208%209.80101%208.83208%2010.942C8.83208%2012.174%209.71408%2013.21%2011.3871%2013.21ZM10.2811%2010.928C10.2811%2010.333%2010.7221%2010.011%2011.3241%209.80801C11.9611%209.61901%2012.8081%209.50001%2013.9491%209.33201C13.9421%209.68201%2013.9141%2010.165%2013.7951%2010.515C13.6271%2011.25%2012.8921%2012.013%2011.6461%2012.013C10.7081%2012.013%2010.2811%2011.516%2010.2811%2010.928Z'%20fill='%2307AD3E'/%3e%3c/svg%3e") 50% no-repeat;width:16px;height:16px;margin-right:4px}.data-table .table-head .th-cell .unknown{opacity:.5;background:url("data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M0.0372314%2013H1.55623L2.29123%2010.725H6.42823L7.17723%2013H8.69623L5.42023%202.92001H3.31323L0.0372314%2013ZM2.73923%209.35301L4.34923%204.38301L5.98023%209.35301H2.73923Z'%20fill='%2307AD3E'/%3e%3cpath%20d='M11.3871%2013.21C12.6121%2013.21%2013.4871%2012.79%2014.1101%2011.901V13H15.4051V8.34501C15.4051%207.71501%2015.3771%207.16901%2015.1391%206.67201C14.6701%205.67801%2013.6201%205.23001%2012.2691%205.23001C10.5191%205.23001%209.46908%206.05601%209.10508%207.35101L10.4701%207.77101C10.7291%206.93101%2011.4571%206.58101%2012.2551%206.58101C13.4381%206.58101%2013.9141%207.07101%2013.9631%208.11401C12.7381%208.28201%2011.4921%208.44301%2010.6171%208.70201C9.44808%209.07301%208.83208%209.80101%208.83208%2010.942C8.83208%2012.174%209.71408%2013.21%2011.3871%2013.21ZM10.2811%2010.928C10.2811%2010.333%2010.7221%2010.011%2011.3241%209.80801C11.9611%209.61901%2012.8081%209.50001%2013.9491%209.33201C13.9421%209.68201%2013.9141%2010.165%2013.7951%2010.515C13.6271%2011.25%2012.8921%2012.013%2011.6461%2012.013C10.7081%2012.013%2010.2811%2011.516%2010.2811%2010.928Z'%20fill='%2307AD3E'/%3e%3c/svg%3e") 50% no-repeat;width:16px;height:16px;margin-right:4px}.data-table .table-head .th-cell .sort{opacity:.1;cursor:pointer;background:url("data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M8%2014.0607L13.5303%208.53034L12.4697%207.46968L8.75%2011.1893V2.00001H7.25V11.1893L3.53033%207.46968L2.46967%208.53034L8%2014.0607Z'%20fill='%23110529'/%3e%3c/svg%3e") 50% no-repeat;width:16px;height:16px;margin-left:auto}.data-table .table-head .th-cell .sort:hover{opacity:.5}.data-table .table-head .th-cell .sort.DESC{opacity:1;display:block}.data-table .table-head .th-cell .sort.ASC{opacity:1;display:block;transform:rotate(180deg)}.data-table .table-body{background-color:var(--bg-elevated-02);max-width:100%;max-height:100%;position:relative;overflow:hidden}.data-table .table-body .tr-body{background-color:#0000;flex-direction:row;gap:1px;width:100%;max-width:100%;display:flex;position:absolute;left:0;overflow:hidden}.data-table .table-body .tr-body.selected{outline:1px solid var(--border-color-focus);background-color:#fff}.data-table .table-body .tr-body.selected .td-cell:after{content:"";background:var(--selected-bg);pointer-events:none;position:absolute;inset:0}.data-table .table-body__no-data{height:212px;color:var(--txt-mask);letter-spacing:-.56px;background-color:#f7f8fa;justify-content:center;align-items:center;font-size:28px;font-style:normal;font-weight:500;line-height:32px;display:flex}.data-table .table-body__no-data>div{flex-direction:column;align-items:center;gap:4px;display:flex}.data-table .td-cell{background-color:#fff;align-items:center;height:100%;padding:1px;display:flex;position:absolute;overflow:hidden}.data-table .td-cell.justify-center{justify-content:center}.data-table .td-cell .control-cell{padding:8px 12px}.data-table .td-cell .base-cell{font-family:var(--cell-font-family);font-weight:var(--cell-font-weight);user-select:text;align-items:center;width:100%;height:100%;padding:8px 12px;display:flex;overflow:hidden}.data-table .td-cell .base-cell input{font-size:inherit;font-family:inherit;font-weight:inherit;border:none;outline:none;width:100%;padding:0}.data-table .td-cell .base-cell__edit{outline:1px solid var(--border-color-focus)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
._content_e3dof_2{gap:var(--gap-v);will-change:height, opacity;flex-direction:column;display:flex}._content_e3dof_2>:first-child{margin-top:24px}._content_e3dof_2>:last-child{margin-bottom:4px}._separator_e3dof_19{cursor:pointer
|
|
1
|
+
._content_e3dof_2{gap:var(--gap-v);will-change:height, opacity;flex-direction:column;display:flex}._content_e3dof_2>:first-child{margin-top:24px}._content_e3dof_2>:last-child{margin-bottom:4px}._separator_e3dof_19{cursor:pointer;&:hover{--pl-separator-txt-color:var(--txt-01);--mask-icon-bg-color:var(--ic-01)}}._chevron_e3dof_27{transition-duration:50ms}._down_e3dof_31{transform:rotate(90deg)}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import e from "../PlIcon16/PlIcon16.js";
|
|
2
|
+
import "../PlMaskIcon16/index.js";
|
|
2
3
|
import t from "../PlSectionSeparator/PlSectionSeparator.js";
|
|
4
|
+
import "../PlSectionSeparator/index.js";
|
|
3
5
|
import n from "./ExpandTransition.js";
|
|
4
6
|
import { computed as r, createCommentVNode as i, createElementBlock as a, createTextVNode as o, createVNode as s, defineComponent as c, inject as l, mergeModels as u, normalizeClass as d, openBlock as f, renderSlot as p, toDisplayString as m, toRef as h, unref as g, useModel as _, withCtx as v } from "vue";
|
|
5
7
|
import { uniqueId as y } from "@milaboratories/helpers";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAccordionSection.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../src/components/PlAccordion/PlAccordionSection.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { uniqueId } from \"@milaboratories/helpers\";\nimport { PlMaskIcon16 } from \"../PlMaskIcon16\";\nimport { PlSectionSeparator } from \"../PlSectionSeparator\";\nimport ExpandTransition from \"./ExpandTransition.vue\";\nimport type { Ref } from \"vue\";\nimport { computed, inject, toRef } from \"vue\";\n\nconst $m = inject<Ref<string>>(\"pl-accordion-model\", () => toRef(\"\"), true);\n\nconst $p = inject<\n Ref<{\n multiple?: boolean;\n }>\n>(\"pl-accordion-props\", () => toRef({ multiple: false }), true);\n\nconst model = defineModel<boolean>();\n\nconst id = uniqueId();\n\nconst isMulti = computed(() => !$p || $p.value.multiple);\n\nconst open = computed({\n get() {\n if (isMulti.value) {\n return model.value;\n }\n\n return $m ? $m.value === id : model.value;\n },\n set(on) {\n if (isMulti.value) {\n model.value = on;\n } else if ($m) {\n $m.value = $m.value === id ? \"\" : id;\n }\n },\n});\n\ndefineProps<{\n /**\n * The label text (optional)\n */\n label?: string;\n /**\n * If `true`, remove top padding\n */\n compact?: boolean;\n}>();\n</script>\n\n<template>\n <div class=\"pl-accordion-section\">\n <PlSectionSeparator :class=\"$style.separator\" :compact=\"compact\" @click=\"open = !open\">\n <PlMaskIcon16 name=\"chevron-right\" :class=\"[{ [$style.down]: open }, $style.chevron]\" />\n {{ label }}\n </PlSectionSeparator>\n <ExpandTransition>\n <div v-if=\"open\" :class=\"$style.content\">\n <slot />\n </div>\n </ExpandTransition>\n </div>\n</template>\n\n<style module>\n.content {\n display: flex;\n flex-direction: column;\n gap: var(--gap-v);\n will-change: height, opacity;\n /* transform: translateZ(0);\n backface-visibility: hidden; */\n}\n\n.content > *:first-child {\n margin-top: 24px;\n}\n\n.content > *:last-child {\n margin-bottom: 4px;\n}\n\n.separator {\n cursor: pointer;\n &:hover {\n --pl-separator-txt-color: var(--txt-01);\n --mask-icon-bg-color: var(--ic-01);\n }\n}\n\n.chevron {\n transition-duration: 50ms;\n}\n\n.down {\n transform: rotate(90deg);\n}\n</style>\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"PlAccordionSection.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../src/components/PlAccordion/PlAccordionSection.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { uniqueId } from \"@milaboratories/helpers\";\nimport { PlMaskIcon16 } from \"../PlMaskIcon16\";\nimport { PlSectionSeparator } from \"../PlSectionSeparator\";\nimport ExpandTransition from \"./ExpandTransition.vue\";\nimport type { Ref } from \"vue\";\nimport { computed, inject, toRef } from \"vue\";\n\nconst $m = inject<Ref<string>>(\"pl-accordion-model\", () => toRef(\"\"), true);\n\nconst $p = inject<\n Ref<{\n multiple?: boolean;\n }>\n>(\"pl-accordion-props\", () => toRef({ multiple: false }), true);\n\nconst model = defineModel<boolean>();\n\nconst id = uniqueId();\n\nconst isMulti = computed(() => !$p || $p.value.multiple);\n\nconst open = computed({\n get() {\n if (isMulti.value) {\n return model.value;\n }\n\n return $m ? $m.value === id : model.value;\n },\n set(on) {\n if (isMulti.value) {\n model.value = on;\n } else if ($m) {\n $m.value = $m.value === id ? \"\" : id;\n }\n },\n});\n\ndefineProps<{\n /**\n * The label text (optional)\n */\n label?: string;\n /**\n * If `true`, remove top padding\n */\n compact?: boolean;\n}>();\n</script>\n\n<template>\n <div class=\"pl-accordion-section\">\n <PlSectionSeparator :class=\"$style.separator\" :compact=\"compact\" @click=\"open = !open\">\n <PlMaskIcon16 name=\"chevron-right\" :class=\"[{ [$style.down]: open }, $style.chevron]\" />\n {{ label }}\n </PlSectionSeparator>\n <ExpandTransition>\n <div v-if=\"open\" :class=\"$style.content\">\n <slot />\n </div>\n </ExpandTransition>\n </div>\n</template>\n\n<style module>\n.content {\n display: flex;\n flex-direction: column;\n gap: var(--gap-v);\n will-change: height, opacity;\n /* transform: translateZ(0);\n backface-visibility: hidden; */\n}\n\n.content > *:first-child {\n margin-top: 24px;\n}\n\n.content > *:last-child {\n margin-bottom: 4px;\n}\n\n.separator {\n cursor: pointer;\n &:hover {\n --pl-separator-txt-color: var(--txt-01);\n --mask-icon-bg-color: var(--ic-01);\n }\n}\n\n.chevron {\n transition-duration: 50ms;\n}\n\n.down {\n transform: rotate(90deg);\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;EAQA,IAAM,IAAK,EAAoB,4BAA4B,EAAM,GAAG,EAAE,GAAK,EAErE,IAAK,EAIT,4BAA4B,EAAM,EAAE,UAAU,IAAO,CAAC,EAAE,GAAK,EAEzD,IAAQ,EAAoB,GAAA,aAAE,EAE9B,IAAK,GAAU,EAEf,IAAU,QAAe,CAAC,KAAM,EAAG,MAAM,SAAS,EAElD,IAAO,EAAS;GACpB,MAAM;AAKJ,WAJI,EAAQ,QACH,EAAM,QAGR,IAAK,EAAG,UAAU,IAAK,EAAM;;GAEtC,IAAI,GAAI;AACN,IAAI,EAAQ,QACV,EAAM,QAAQ,IACL,MACT,EAAG,QAAQ,EAAG,UAAU,IAAK,KAAK;;GAGvC,CAAC;yBAeA,EAUM,OAVN,GAUM,CATJ,EAGqB,EAAA,EAAA,EAAA;GAHA,OAAK,EAAEA,EAAAA,OAAO,UAAS;GAAG,SAAS,EAAA;GAAU,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,QAAI,CAAI,EAAA;;oBACS,CAAxF,EAAwF,EAAA,EAAA,EAAA;IAA1E,MAAK;IAAiB,OAAK,EAAA,CAAA,GAAMA,EAAAA,OAAO,OAAO,EAAA,OAAI,EAAIA,EAAAA,OAAO,QAAO,CAAA;6BAAK,MACxF,EAAG,EAAA,MAAK,EAAA,EAAA,CAAA,CAAA;;+BAEV,EAImB,GAAA,MAAA;oBADX,CAFK,EAAA,SAAA,GAAA,EAAX,EAEM,OAAA;;IAFY,OAAK,EAAEA,EAAAA,OAAO,QAAO;OACrC,EAAQ,EAAA,QAAA,UAAA,CAAA,EAAA,EAAA,IAAA,EAAA,IAAA,GAAA,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAlert.js","names":[],"sources":["../../../src/components/PlAlert/PlAlert.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"PlAlert\",\n};\n</script>\n\n<script lang=\"ts\" setup>\nimport \"./pl-alert.scss\";\n\ndefineEmits<{\n /**\n * Emitted when the model value is updated, typically when the close button is clicked.\n *\n * @param value - The new value of the model, generally `false` when the alert is closed.\n */\n (e: \"update:modelValue\", value: boolean): void;\n}>();\n\nwithDefaults(\n defineProps<{\n /**\n * Controls the visibility of the alert component. If `true`, the alert is visible.\n *\n * @default true\n */\n modelValue?: boolean;\n /**\n * The type of alert, which determines the alert's style and icon.\n * Can be one of `'success' | 'info' | 'warn' | 'error'`.\n */\n type?: \"success\" | \"info\" | \"warn\" | \"error\";\n /**\n * An optional label that appears at the top of the alert.\n */\n label?: string;\n /**\n * If `true`, an icon corresponding to the alert type is displayed.\n */\n icon?: boolean;\n /**\n * If `true`, a close button is displayed in the alert, allowing the user to close it.\n */\n closeable?: boolean;\n /**\n * If `true`, the alert text is displayed in a monospace font.\n */\n monospace?: boolean;\n /**\n * If `true`, the alert content will preserve whitespace and line breaks.\n */\n whiteSpacePre?: boolean;\n\n /**\n * Max height (css value like '120px or 30%')\n */\n maxHeight?: string;\n }>(),\n {\n modelValue: true,\n type: undefined,\n label: undefined,\n icon: undefined,\n closeable: undefined,\n monospace: undefined,\n whiteSpacePre: undefined,\n maxHeight: undefined,\n },\n);\n\nconst iconMap = {\n success: \"success\",\n warn: \"warning\",\n info: \"edit\",\n error: \"error\",\n};\n</script>\n\n<template>\n <div\n v-if=\"modelValue\"\n class=\"pl-alert\"\n :style=\"{ maxHeight }\"\n :class=\"[{ monospace, whiteSpacePre }, type ? `pl-alert__${type}` : '']\"\n >\n <div v-if=\"icon && type\" class=\"pl-alert__icon\">\n <div :class=\"`icon-24 icon-${iconMap[type]}`\" />\n </div>\n <div class=\"pl-alert__main\">\n <label v-if=\"label\">{{ label }}</label>\n <div class=\"pl-alert__main__text\"><slot /></div>\n </div>\n <
|
|
1
|
+
{"version":3,"file":"PlAlert.js","names":[],"sources":["../../../src/components/PlAlert/PlAlert.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"PlAlert\",\n};\n</script>\n\n<script lang=\"ts\" setup>\nimport \"./pl-alert.scss\";\n\nimport PlCloseModalBtn from \"../../utils/PlCloseModalBtn.vue\";\n\ndefineEmits<{\n /**\n * Emitted when the model value is updated, typically when the close button is clicked.\n *\n * @param value - The new value of the model, generally `false` when the alert is closed.\n */\n (e: \"update:modelValue\", value: boolean): void;\n}>();\n\nwithDefaults(\n defineProps<{\n /**\n * Controls the visibility of the alert component. If `true`, the alert is visible.\n *\n * @default true\n */\n modelValue?: boolean;\n /**\n * The type of alert, which determines the alert's style and icon.\n * Can be one of `'success' | 'info' | 'warn' | 'error'`.\n */\n type?: \"success\" | \"info\" | \"warn\" | \"error\";\n /**\n * An optional label that appears at the top of the alert.\n */\n label?: string;\n /**\n * If `true`, an icon corresponding to the alert type is displayed.\n */\n icon?: boolean;\n /**\n * If `true`, a close button is displayed in the alert, allowing the user to close it.\n */\n closeable?: boolean;\n /**\n * If `true`, the alert text is displayed in a monospace font.\n */\n monospace?: boolean;\n /**\n * If `true`, the alert content will preserve whitespace and line breaks.\n */\n whiteSpacePre?: boolean;\n\n /**\n * Max height (css value like '120px or 30%')\n */\n maxHeight?: string;\n }>(),\n {\n modelValue: true,\n type: undefined,\n label: undefined,\n icon: undefined,\n closeable: undefined,\n monospace: undefined,\n whiteSpacePre: undefined,\n maxHeight: undefined,\n },\n);\n\nconst iconMap = {\n success: \"success\",\n warn: \"warning\",\n info: \"edit\",\n error: \"error\",\n};\n</script>\n\n<template>\n <div\n v-if=\"modelValue\"\n class=\"pl-alert\"\n :style=\"{ maxHeight }\"\n :class=\"[{ monospace, whiteSpacePre }, type ? `pl-alert__${type}` : '']\"\n >\n <div v-if=\"icon && type\" class=\"pl-alert__icon\">\n <div :class=\"`icon-24 icon-${iconMap[type]}`\" />\n </div>\n <div class=\"pl-alert__main\">\n <label v-if=\"label\">{{ label }}</label>\n <div class=\"pl-alert__main__text\"><slot /></div>\n </div>\n <PlCloseModalBtn\n v-if=\"closeable\"\n class=\"pl-alert__close-btn\"\n @click=\"$emit('update:modelValue', false)\"\n />\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAlert.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlAlert/PlAlert.vue"],"names":[],"mappings":"AAsGA,OAAO,iBAAiB,CAAC;;
|
|
1
|
+
{"version":3,"file":"PlAlert.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlAlert/PlAlert.vue"],"names":[],"mappings":"AAsGA,OAAO,iBAAiB,CAAC;;IAiBrB;;;;OAIG;iBACU,OAAO;IACpB;;;OAGG;WACI,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO;IAC5C;;OAEG;YACK,MAAM;IACd;;OAEG;WACI,OAAO;IACd;;OAEG;gBACS,OAAO;IACnB;;OAEG;gBACS,OAAO;IACnB;;OAEG;oBACa,OAAO;IAEvB;;OAEG;gBACS,MAAM;;;;IAnClB;;;;OAIG;iBACU,OAAO;IACpB;;;OAGG;WACI,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO;IAC5C;;OAEG;YACK,MAAM;IACd;;OAEG;WACI,OAAO;IACd;;OAEG;gBACS,OAAO;IACnB;;OAEG;gBACS,OAAO;IACnB;;OAEG;oBACa,OAAO;IAEvB;;OAEG;gBACS,MAAM;;;;WArBV,MAAM;gBATD,OAAO;UAKb,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO;UAQrC,OAAO;eAiBF,MAAM;eAbN,OAAO;eAIP,OAAO;mBAIH,OAAO;;qBAoGE,GAAG;;AA9IhC,wBAwLK;AAcL,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import './pl-alert.css';/* empty css */
|
|
2
|
-
import
|
|
3
|
-
|
|
2
|
+
import e from "../../utils/PlCloseModalBtn.js";
|
|
3
|
+
import { createBlock as t, createCommentVNode as n, createElementBlock as r, createElementVNode as i, defineComponent as a, normalizeClass as o, normalizeStyle as s, openBlock as c, renderSlot as l, toDisplayString as u } from "vue";
|
|
4
|
+
var d = {
|
|
4
5
|
key: 0,
|
|
5
6
|
class: "pl-alert__icon"
|
|
6
|
-
},
|
|
7
|
+
}, f = { class: "pl-alert__main" }, p = { key: 0 }, m = { class: "pl-alert__main__text" }, h = /* @__PURE__ */ a({
|
|
7
8
|
name: "PlAlert",
|
|
8
9
|
props: {
|
|
9
10
|
modelValue: {
|
|
@@ -31,33 +32,31 @@ var l = {
|
|
|
31
32
|
maxHeight: { default: void 0 }
|
|
32
33
|
},
|
|
33
34
|
emits: ["update:modelValue"],
|
|
34
|
-
setup(
|
|
35
|
-
let
|
|
35
|
+
setup(a) {
|
|
36
|
+
let h = {
|
|
36
37
|
success: "success",
|
|
37
38
|
warn: "warning",
|
|
38
39
|
info: "edit",
|
|
39
40
|
error: "error"
|
|
40
41
|
};
|
|
41
|
-
return (
|
|
42
|
+
return (g, _) => a.modelValue ? (c(), r("div", {
|
|
42
43
|
key: 0,
|
|
43
|
-
class:
|
|
44
|
-
monospace:
|
|
45
|
-
whiteSpacePre:
|
|
46
|
-
},
|
|
47
|
-
style:
|
|
44
|
+
class: o(["pl-alert", [{
|
|
45
|
+
monospace: a.monospace,
|
|
46
|
+
whiteSpacePre: a.whiteSpacePre
|
|
47
|
+
}, a.type ? `pl-alert__${a.type}` : ""]]),
|
|
48
|
+
style: s({ maxHeight: a.maxHeight })
|
|
48
49
|
}, [
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
a.icon && a.type ? (c(), r("div", d, [i("div", { class: o(`icon-24 icon-${h[a.type]}`) }, null, 2)])) : n("", !0),
|
|
51
|
+
i("div", f, [a.label ? (c(), r("label", p, u(a.label), 1)) : n("", !0), i("div", m, [l(g.$slots, "default")])]),
|
|
52
|
+
a.closeable ? (c(), t(e, {
|
|
52
53
|
key: 1,
|
|
53
54
|
class: "pl-alert__close-btn",
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
})) : e("", !0)
|
|
58
|
-
], 6)) : e("", !0);
|
|
55
|
+
onClick: _[0] ||= (e) => g.$emit("update:modelValue", !1)
|
|
56
|
+
})) : n("", !0)
|
|
57
|
+
], 6)) : n("", !0);
|
|
59
58
|
}
|
|
60
59
|
});
|
|
61
|
-
export {
|
|
60
|
+
export { h as default };
|
|
62
61
|
|
|
63
62
|
//# sourceMappingURL=PlAlert.vue2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAlert.vue_vue_type_script_setup_true_lang.js","names":["$emit"],"sources":["../../../src/components/PlAlert/PlAlert.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"PlAlert\",\n};\n</script>\n\n<script lang=\"ts\" setup>\nimport \"./pl-alert.scss\";\n\ndefineEmits<{\n /**\n * Emitted when the model value is updated, typically when the close button is clicked.\n *\n * @param value - The new value of the model, generally `false` when the alert is closed.\n */\n (e: \"update:modelValue\", value: boolean): void;\n}>();\n\nwithDefaults(\n defineProps<{\n /**\n * Controls the visibility of the alert component. If `true`, the alert is visible.\n *\n * @default true\n */\n modelValue?: boolean;\n /**\n * The type of alert, which determines the alert's style and icon.\n * Can be one of `'success' | 'info' | 'warn' | 'error'`.\n */\n type?: \"success\" | \"info\" | \"warn\" | \"error\";\n /**\n * An optional label that appears at the top of the alert.\n */\n label?: string;\n /**\n * If `true`, an icon corresponding to the alert type is displayed.\n */\n icon?: boolean;\n /**\n * If `true`, a close button is displayed in the alert, allowing the user to close it.\n */\n closeable?: boolean;\n /**\n * If `true`, the alert text is displayed in a monospace font.\n */\n monospace?: boolean;\n /**\n * If `true`, the alert content will preserve whitespace and line breaks.\n */\n whiteSpacePre?: boolean;\n\n /**\n * Max height (css value like '120px or 30%')\n */\n maxHeight?: string;\n }>(),\n {\n modelValue: true,\n type: undefined,\n label: undefined,\n icon: undefined,\n closeable: undefined,\n monospace: undefined,\n whiteSpacePre: undefined,\n maxHeight: undefined,\n },\n);\n\nconst iconMap = {\n success: \"success\",\n warn: \"warning\",\n info: \"edit\",\n error: \"error\",\n};\n</script>\n\n<template>\n <div\n v-if=\"modelValue\"\n class=\"pl-alert\"\n :style=\"{ maxHeight }\"\n :class=\"[{ monospace, whiteSpacePre }, type ? `pl-alert__${type}` : '']\"\n >\n <div v-if=\"icon && type\" class=\"pl-alert__icon\">\n <div :class=\"`icon-24 icon-${iconMap[type]}`\" />\n </div>\n <div class=\"pl-alert__main\">\n <label v-if=\"label\">{{ label }}</label>\n <div class=\"pl-alert__main__text\"><slot /></div>\n </div>\n <
|
|
1
|
+
{"version":3,"file":"PlAlert.vue_vue_type_script_setup_true_lang.js","names":["$emit"],"sources":["../../../src/components/PlAlert/PlAlert.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"PlAlert\",\n};\n</script>\n\n<script lang=\"ts\" setup>\nimport \"./pl-alert.scss\";\n\nimport PlCloseModalBtn from \"../../utils/PlCloseModalBtn.vue\";\n\ndefineEmits<{\n /**\n * Emitted when the model value is updated, typically when the close button is clicked.\n *\n * @param value - The new value of the model, generally `false` when the alert is closed.\n */\n (e: \"update:modelValue\", value: boolean): void;\n}>();\n\nwithDefaults(\n defineProps<{\n /**\n * Controls the visibility of the alert component. If `true`, the alert is visible.\n *\n * @default true\n */\n modelValue?: boolean;\n /**\n * The type of alert, which determines the alert's style and icon.\n * Can be one of `'success' | 'info' | 'warn' | 'error'`.\n */\n type?: \"success\" | \"info\" | \"warn\" | \"error\";\n /**\n * An optional label that appears at the top of the alert.\n */\n label?: string;\n /**\n * If `true`, an icon corresponding to the alert type is displayed.\n */\n icon?: boolean;\n /**\n * If `true`, a close button is displayed in the alert, allowing the user to close it.\n */\n closeable?: boolean;\n /**\n * If `true`, the alert text is displayed in a monospace font.\n */\n monospace?: boolean;\n /**\n * If `true`, the alert content will preserve whitespace and line breaks.\n */\n whiteSpacePre?: boolean;\n\n /**\n * Max height (css value like '120px or 30%')\n */\n maxHeight?: string;\n }>(),\n {\n modelValue: true,\n type: undefined,\n label: undefined,\n icon: undefined,\n closeable: undefined,\n monospace: undefined,\n whiteSpacePre: undefined,\n maxHeight: undefined,\n },\n);\n\nconst iconMap = {\n success: \"success\",\n warn: \"warning\",\n info: \"edit\",\n error: \"error\",\n};\n</script>\n\n<template>\n <div\n v-if=\"modelValue\"\n class=\"pl-alert\"\n :style=\"{ maxHeight }\"\n :class=\"[{ monospace, whiteSpacePre }, type ? `pl-alert__${type}` : '']\"\n >\n <div v-if=\"icon && type\" class=\"pl-alert__icon\">\n <div :class=\"`icon-24 icon-${iconMap[type]}`\" />\n </div>\n <div class=\"pl-alert__main\">\n <label v-if=\"label\">{{ label }}</label>\n <div class=\"pl-alert__main__text\"><slot /></div>\n </div>\n <PlCloseModalBtn\n v-if=\"closeable\"\n class=\"pl-alert__close-btn\"\n @click=\"$emit('update:modelValue', false)\"\n />\n </div>\n</template>\n"],"mappings":";;;;;;;CAEE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqER,IAAM,IAAU;GACd,SAAS;GACT,MAAM;GACN,MAAM;GACN,OAAO;GACR;mBAKS,EAAA,cAAA,GAAA,EADR,EAkBM,OAAA;;GAhBJ,OAAK,EAAA,CAAC,YAAU,CAAA;IAAA,WAEL,EAAA;IAAS,eAAE,EAAA;IAAa,EAAI,EAAA,OAAI,aAAgB,EAAA,SAAI,GAAA,CAAA,CAAA;GAD9D,OAAK,EAAA,EAAA,WAAI,EAAA,WAAS,CAAA;;GAGR,EAAA,QAAQ,EAAA,QAAA,GAAA,EAAnB,EAEM,OAFN,GAEM,CADJ,EAAgD,OAAA,EAA1C,OAAK,EAAA,gBAAkB,EAAQ,EAAA,QAAI,EAAA,EAAA,MAAA,EAAA,CAAA,CAAA,IAAA,EAAA,IAAA,GAAA;GAE3C,EAGM,OAHN,GAGM,CAFS,EAAA,SAAA,GAAA,EAAb,EAAuC,SAAA,GAAA,EAAhB,EAAA,MAAK,EAAA,EAAA,IAAA,EAAA,IAAA,GAAA,EAC5B,EAAgD,OAAhD,GAAgD,CAAd,EAAQ,EAAA,QAAA,UAAA,CAAA,CAAA,CAAA,CAAA;GAGpC,EAAA,aAAA,GAAA,EADR,EAIE,GAAA;;IAFA,OAAM;IACL,SAAK,AAAA,EAAA,QAAA,MAAEA,EAAAA,MAAK,qBAAA,GAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "./PlAlert.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.pl-alert{--text-font-family:var(--font-family-base);--text-white-space:normal;--indent:24px;border:1px solid var(--border-color-default);color:var(--txt-01);border-radius:6px;flex-wrap:nowrap;gap:12px;padding:12px;display:flex;position:relative}.pl-alert.monospace{--text-font-family:var(--font-family-monospace)}.pl-alert.whiteSpacePre{--text-white-space:pre}.pl-alert__error{background:var(--notification-error)}.pl-alert__warn{background:var(--notification-warning)}.pl-alert__success{background:var(--notification-success)}.pl-alert__info{background:var(--notification-neutral)}.pl-alert__icon{width:24px}.pl-alert__main{flex-direction:column;flex:1;gap:6px;width:100%;min-height:24px;display:flex;overflow:hidden}.pl-alert__main label{letter-spacing:-.2px;font-size:20px;font-weight:500;line-height:24px}.pl-alert__main__text{font-size:14px;font-weight:500;line-height:20px;font-family:var(--text-font-family);white-space:var(--text-white-space);--thumb-color:var(--ic-02);flex:1;max-width:100%;overflow-y:auto}.pl-alert__main__text::-webkit-scrollbar{width:var(--scrollbar-width,6px);background-color:#0000;height:5px;display:block}.pl-alert__main__text::-webkit-scrollbar-thumb{background:var(--thumb-color);border-radius:5px}.pl-alert__main__text::-webkit-scrollbar-thumb:hover{--thumb-color:var(--border-color-focus)}.pl-alert__close-btn{
|
|
1
|
+
.pl-alert{--text-font-family:var(--font-family-base);--text-white-space:normal;--indent:24px;border:1px solid var(--border-color-default);color:var(--txt-01);border-radius:6px;flex-wrap:nowrap;gap:12px;padding:12px;display:flex;position:relative}.pl-alert.monospace{--text-font-family:var(--font-family-monospace)}.pl-alert.whiteSpacePre{--text-white-space:pre}.pl-alert__error{background:var(--notification-error)}.pl-alert__warn{background:var(--notification-warning)}.pl-alert__success{background:var(--notification-success)}.pl-alert__info{background:var(--notification-neutral)}.pl-alert__icon{width:24px}.pl-alert__main{flex-direction:column;flex:1;gap:6px;width:100%;min-height:24px;display:flex;overflow:hidden}.pl-alert__main label{letter-spacing:-.2px;font-size:20px;font-weight:500;line-height:24px}.pl-alert__main__text{font-size:14px;font-weight:500;line-height:20px;font-family:var(--text-font-family);white-space:var(--text-white-space);--thumb-color:var(--ic-02);flex:1;max-width:100%;overflow-y:auto}.pl-alert__main__text::-webkit-scrollbar{width:var(--scrollbar-width,6px);background-color:#0000;height:5px;display:block}.pl-alert__main__text::-webkit-scrollbar-thumb{background:var(--thumb-color);border-radius:5px}.pl-alert__main__text::-webkit-scrollbar-thumb:hover{--thumb-color:var(--border-color-focus)}.pl-alert__close-btn{position:absolute;top:10px;right:12px}
|
|
@@ -2,16 +2,21 @@ import e from "../DropdownListItem.js";
|
|
|
2
2
|
import { tap as t } from "../../helpers/functions.js";
|
|
3
3
|
import { normalizeListOptions as n } from "../../helpers/utils.js";
|
|
4
4
|
import r from "../PlTooltip/PlTooltip.js";
|
|
5
|
+
import "../PlTooltip/index.js";
|
|
5
6
|
import { getErrorMessage as i } from "../../helpers/error.js";
|
|
6
7
|
import a from "../LongText.js";
|
|
7
8
|
import o from "../PlSvg/PlSvg.js";
|
|
9
|
+
import "../PlSvg/index.js";
|
|
8
10
|
import s from "../PlIcon24/PlIcon24.js";
|
|
9
11
|
import ee from "../PlIcon16/PlIcon16.js";
|
|
10
12
|
import './pl-autocomplete.css';/* empty css */
|
|
11
13
|
import te from "../../utils/DoubleContour.js";
|
|
12
14
|
import { useLabelNotch as ne } from "../../utils/useLabelNotch.js";
|
|
13
15
|
import { deepEqual as c } from "../../helpers/objects.js";
|
|
16
|
+
import "../PlIcon16/index.js";
|
|
17
|
+
import "../PlMaskIcon24/index.js";
|
|
14
18
|
import re from "../../utils/DropdownOverlay/DropdownOverlay.js";
|
|
19
|
+
import "../../utils/DropdownOverlay/index.js";
|
|
15
20
|
import { useWatchFetch as l } from "../../composition/useWatchFetch.js";
|
|
16
21
|
import ie from "../../assets/images/required.js";
|
|
17
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";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAutocomplete.vue_vue_type_script_setup_true_lang.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\";\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) => {\n if (v !== null) {\n // search is null when dropdown is closed;\n return props.optionsSearch(v, \"label\");\n }\n return undefined;\n },\n);\n\nconst modelOptionRequest = useWatchFetch(\n () => model.value,\n async (v) => {\n if (v != null && !deepEqual(modelOptionRef.value?.value, v)) {\n // load label for selected value if it was updated from outside the component\n return (await props.optionsSearch(String(v), \"value\"))?.[0];\n }\n return modelOptionRef.value;\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":"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"}
|
|
1
|
+
{"version":3,"file":"PlAutocomplete.vue_vue_type_script_setup_true_lang.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\";\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) => {\n if (v !== null) {\n // search is null when dropdown is closed;\n return props.optionsSearch(v, \"label\");\n }\n return undefined;\n },\n);\n\nconst modelOptionRequest = useWatchFetch(\n () => model.value,\n async (v) => {\n if (v != null && !deepEqual(modelOptionRef.value?.value, v)) {\n // load label for selected value if it was updated from outside the component\n return (await props.optionsSearch(String(v), \"value\"))?.[0];\n }\n return modelOptionRef.value;\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":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "./PlAutocomplete.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.pl-autocomplete__options{--option-hover-bg:var(--btn-sec-hover-grey);z-index:var(--z-dropdown-options);border:1px solid var(--border-color-div-grey);background-color:var(--pl-dropdown-options-bg);--thumb-color:var(--ic-02);border-radius:6px;max-height:244px;position:absolute;overflow-y:auto;box-shadow:0 4px 12px -2px #0f244d14,0 6px 24px -2px #0f244d14}.pl-autocomplete__options::-webkit-scrollbar{width:var(--scrollbar-width,6px);background-color:#0000;height:5px;display:block}.pl-autocomplete__options::-webkit-scrollbar-thumb{background:var(--thumb-color);border-radius:5px}.pl-autocomplete__options::-webkit-scrollbar-thumb:hover{--thumb-color:var(--border-color-focus)}.pl-autocomplete__options .nothing-found{height:var(--control-height);line-height:var(--control-height);opacity:.5;background-color:#fff;padding:0 10px;font-style:italic}.pl-autocomplete__options .option{height:var(--control-height);line-height:var(--control-height);cursor:pointer
|
|
1
|
+
.pl-autocomplete__options{--option-hover-bg:var(--btn-sec-hover-grey);z-index:var(--z-dropdown-options);border:1px solid var(--border-color-div-grey);background-color:var(--pl-dropdown-options-bg);--thumb-color:var(--ic-02);border-radius:6px;max-height:244px;position:absolute;overflow-y:auto;box-shadow:0 4px 12px -2px #0f244d14,0 6px 24px -2px #0f244d14}.pl-autocomplete__options::-webkit-scrollbar{width:var(--scrollbar-width,6px);background-color:#0000;height:5px;display:block}.pl-autocomplete__options::-webkit-scrollbar-thumb{background:var(--thumb-color);border-radius:5px}.pl-autocomplete__options::-webkit-scrollbar-thumb:hover{--thumb-color:var(--border-color-focus)}.pl-autocomplete__options .nothing-found{height:var(--control-height);line-height:var(--control-height);opacity:.5;background-color:#fff;padding:0 10px;font-style:italic}.pl-autocomplete__options .option{height:var(--control-height);line-height:var(--control-height);cursor:pointer;user-select:none;padding:0 30px 0 10px;position:relative}.pl-autocomplete__options .option .checkmark{display:none;position:absolute;top:50%;right:10px;transform:translateY(-50%)}.pl-autocomplete__options .option>span{white-space:nowrap;text-overflow:ellipsis;max-width:100%;display:block;overflow:hidden}.pl-autocomplete__options .option.selected{background-color:var(--color-active-select)}.pl-autocomplete__options .option.selected .checkmark{display:block}.pl-autocomplete__options .option.active:not(.selected),.pl-autocomplete__options .option:hover{background-color:var(--option-hover-bg)}.pl-autocomplete{--contour-color:var(--txt-01);--contour-border-width:1px;--label-offset-left-x:8px;--label-offset-right-x:8px;--label-color:var(--txt-01);min-height:var(--control-height);font-family:var(--font-family-base);font-size:var(--font-size-base);font-weight:var(--font-weigh-base);border-radius:6px;outline:none;position:relative}.pl-autocomplete__envelope{font-family:var(--control-font-family);min-width:160px}.pl-autocomplete label{top:-8px;left:var(--label-offset-left-x);white-space:pre;text-overflow:ellipsis;max-width:calc(100% - 16px);cursor:inherit;color:var(--label-color);background:var(--bg-elevated-01);border-bottom-right-radius:4px;border-bottom-left-radius:4px;align-items:center;gap:4px;padding:0 4px;font-size:12px;font-weight:500;display:flex;position:absolute;overflow:hidden}.pl-autocomplete label>span{white-space:pre;text-overflow:ellipsis;overflow:hidden}.pl-autocomplete__container{min-height:var(--control-height);color:var(--txt-01);border-radius:6px;position:absolute;top:0;left:0;right:0}.pl-autocomplete__contour{border-radius:var(--border-radius-control);border:var(--contour-border-width) solid var(--contour-color);box-shadow:var(--contour-box-shadow);z-index:0;pointer-events:none}.pl-autocomplete__field{min-height:var(--control-height);line-height:var(--control-height);cursor:pointer;background:0 0;border-radius:6px;flex-direction:row;align-items:center;padding-left:11px;display:flex;position:relative;overflow:hidden}.pl-autocomplete__field .input-value{pointer-events:none;color:var(--txt-01);white-space:pre;text-overflow:ellipsis;cursor:inherit;flex-direction:row;align-items:center;padding:0 60px 0 11px;line-height:20px;display:flex;position:absolute;inset:0;overflow:hidden}.pl-autocomplete__field input{min-height:calc(var(--control-height) - 2px);font-family:inherit;line-height:20px;font-size:inherit;width:calc(100% - 40px);color:var(--txt-01);caret-color:var(--border-color-focus);background-color:#0000;border:none;padding:0}.pl-autocomplete__field input:focus{outline:none}.pl-autocomplete__field input:placeholder-shown{text-overflow:ellipsis}.pl-autocomplete__field input::placeholder{color:var(--color-placeholder)}.pl-autocomplete__helper{color:var(--txt-03);white-space:pre-wrap;text-overflow:ellipsis;margin-top:6px;padding:2px 0 0;font-size:12px;font-weight:500;line-height:16px}.pl-autocomplete__error{color:var(--txt-error);white-space:pre-wrap;text-overflow:ellipsis;margin-top:6px;padding:2px 0 0;font-size:12px;font-weight:500;line-height:16px}.pl-autocomplete__controls{min-height:var(--control-height);flex-direction:row;align-items:center;gap:6px;margin-left:auto;display:flex}.pl-autocomplete__controls .mask-16,.pl-autocomplete__controls .mask-24{--icon-color:var(--control-mask-fill);cursor:pointer}.pl-autocomplete__controls .clear{--icon-color:var(--ic-02)}.pl-autocomplete__controls .mask-loading{--icon-color:#07ad3e;animation:2.5s linear infinite spin}.pl-autocomplete__arrow-wrapper{min-height:var(--control-height);align-items:center;padding-right:11px;display:flex}.pl-autocomplete .arrow-icon{cursor:pointer}.pl-autocomplete .arrow-icon.arrow-icon-default{background-color:var(--control-mask-fill);width:16px;height:16px;transition:transform .2s;mask-image:url("data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M2.46967%206.53033L3.53033%205.46967L8%209.93934L12.4697%205.46967L13.5303%206.53033L8%2012.0607L2.46967%206.53033Z'%20fill='%23110529'/%3e%3c/svg%3e");mask-position:50%;mask-size:16px;mask-repeat:no-repeat}.pl-autocomplete.open,.pl-autocomplete:focus-within{z-index:1;--label-color:var(--txt-focus)}.pl-autocomplete.open .pl-autocomplete__container{z-index:1000}.pl-autocomplete.open .pl-autocomplete__field{border-radius:6px 6px 0 0}.pl-autocomplete.open .arrow-icon.arrow-icon-default{background-color:var(--control-mask-fill);transform:rotate(-180deg)}.pl-autocomplete:hover{--contour-color:var(--control-hover-color)}.pl-autocomplete:focus-within:not(.error){--label-color:var(--txt-focus);--contour-color:var(--border-color-focus);--contour-border-width:2px;--contour-box-shadow:0 0 0 4px var(--border-color-focus-shadow)}.pl-autocomplete:focus-within.error{--contour-border-width:2px;--contour-box-shadow:0 0 0 4px var(--color-error-shadow)}.pl-autocomplete.error{--contour-color:var(--txt-error);--label-color:var(--txt-error)}.pl-autocomplete.disabled{--contour-color:var(--color-dis-01);--control-mask-fill:var(--color-dis-01);--label-color:var(--color-dis-01);cursor:not-allowed;pointer-events:none;user-select:none}.pl-autocomplete.disabled .input-value{color:var(--dis-01)}
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import e from "../DropdownListItem.js";
|
|
2
2
|
import t from "../PlTooltip/PlTooltip.js";
|
|
3
|
+
import "../PlTooltip/index.js";
|
|
3
4
|
import { getErrorMessage as n } from "../../helpers/error.js";
|
|
4
5
|
import r from "../PlSvg/PlSvg.js";
|
|
6
|
+
import "../PlSvg/index.js";
|
|
5
7
|
import i from "../PlIcon24/PlIcon24.js";
|
|
6
8
|
import a from "../../utils/DoubleContour.js";
|
|
7
9
|
import { useLabelNotch as o } from "../../utils/useLabelNotch.js";
|
|
8
10
|
import { deepEqual as s, deepIncludes as c } from "../../helpers/objects.js";
|
|
11
|
+
import "../PlMaskIcon24/index.js";
|
|
9
12
|
import ee from "../../utils/DropdownOverlay/DropdownOverlay.js";
|
|
10
13
|
import { useWatchFetch as l } from "../../composition/useWatchFetch.js";
|
|
11
14
|
import te from "../../assets/images/required.js";
|
|
12
15
|
import './pl-autocomplete-multi.css';/* empty css */
|
|
13
16
|
import u from "../PlChip/PlChip.js";
|
|
17
|
+
import "../PlChip/index.js";
|
|
14
18
|
import { Fragment as d, computed as f, createBlock as p, createCommentVNode as m, createElementBlock as h, createElementVNode as g, createTextVNode as _, createVNode as ne, defineComponent as v, normalizeClass as re, openBlock as y, reactive as b, ref as x, renderList as S, renderSlot as C, toDisplayString as w, toRef as T, unref as E, useSlots as ie, useTemplateRef as ae, vModelText as D, watch as O, withCtx as k, withDirectives as oe, withModifiers as A } from "vue";
|
|
15
19
|
import se from "canonicalize";
|
|
16
20
|
var ce = ["tabindex"], le = { class: "pl-autocomplete-multi__container" }, ue = { class: "pl-autocomplete-multi__field" }, de = ["disabled", "placeholder"], fe = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAutocompleteMulti.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/PlAutocompleteMulti/PlAutocompleteMulti.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * A multi-select autocomplete component that allows users to search and select multiple values from a list of options.\n * Supports async data fetching, keyboard navigation, and displays selected items as removable chips.\n *\n * @example\n * Basic usage:\n * <PlAutocompleteMulti\n * v-model=\"selectedUsers\"\n * :options-search=\"searchUsers\"\n * :model-search=\"getUsersByIds\"\n * label=\"Select Users\"\n * placeholder=\"Search for users...\"\n * required\n * :debounce=\"300\"\n * helper=\"Choose one or more users from the list\"\n * />\n *\n * With async functions:\n * const selectedUsers = ref([])\n *\n * const searchUsers = async (searchTerm) => {\n * const response = await fetch('/api/users/search?q=' + searchTerm)\n * const users = await response.json()\n * return users.map(user => ({ value: user.id, label: user.name }))\n * }\n *\n * const getUsersByIds = async (userIds) => {\n * if (!userIds.length) return []\n * const response = await fetch('/api/users?ids=' + userIds.join(','))\n * const users = await response.json()\n * return users.map(user => ({ value: user.id, label: user.name }))\n * }\n */\nexport default {\n name: \"PlAutocompleteMulti\",\n};\n\nexport interface OptionsSearch<T> {\n (s: string, type: \"label\"): Promise<Readonly<ListOptionBase<T>[]>>;\n (s: T[], type: \"value\"): Promise<Readonly<ListOptionBase<T>[]>>;\n}\n</script>\n\n<script lang=\"ts\" setup generic=\"M extends string | number = string\">\nimport \"./pl-autocomplete-multi.scss\";\n\nimport type { ListOptionBase } from \"@platforma-sdk/model\";\nimport canonicalize from \"canonicalize\";\nimport { computed, reactive, ref, toRef, unref, useSlots, useTemplateRef, watch } from \"vue\";\nimport { useWatchFetch } from \"../../composition/useWatchFetch.ts\";\nimport { getErrorMessage } from \"../../helpers/error.ts\";\nimport { deepEqual, deepIncludes } from \"../../helpers/objects\";\nimport DoubleContour from \"../../utils/DoubleContour.vue\";\nimport DropdownOverlay from \"../../utils/DropdownOverlay/DropdownOverlay.vue\";\nimport { useLabelNotch } from \"../../utils/useLabelNotch\";\nimport DropdownListItem from \"../DropdownListItem.vue\";\nimport { PlChip } from \"../PlChip\";\nimport { PlMaskIcon24 } from \"../PlMaskIcon24\";\nimport { PlTooltip } from \"../PlTooltip\";\n\nimport SvgRequired from \"../../assets/images/required.svg?raw\";\nimport { PlSvg } from \"../PlSvg\";\n\nconst emit = defineEmits<{\n (e: \"update:modelValue\", v: M[]): void;\n}>();\n\nconst emitModel = (v: M[]) => emit(\"update:modelValue\", v);\n\nconst slots = useSlots();\n\nconst props = withDefaults(\n defineProps<{\n /**\n * The current selected values.\n */\n modelValue: M[];\n /**\n * Lambda for requesting of available options for the dropdown by search string.\n */\n optionsSearch: OptionsSearch<M>;\n /**\n * Unique identifier for the source of the options, changing it will invalidate the options cache.\n */\n sourceId?: string;\n /**\n * The label text for the dropdown field (optional)\n */\n label?: string;\n /**\n * A helper text displayed below the dropdown when there are no errors (optional).\n */\n helper?: string;\n /**\n * Error message displayed below the dropdown (optional)\n */\n error?: unknown;\n /**\n * Placeholder text shown when no value is selected.\n */\n placeholder?: string;\n /**\n * If `true`, the dropdown component is marked as required.\n */\n required?: boolean;\n /**\n * If `true`, the dropdown component is disabled and cannot be interacted with.\n */\n disabled?: boolean;\n /**\n * Debounce time in ms for the options search.\n */\n debounce?: number;\n /**\n * If `true`, the search input is reset and focus is set on it when the new option is selected.\n */\n resetSearchOnSelect?: boolean;\n /**\n * The text to display when no options are found.\n */\n emptyOptionsText?: string;\n /**\n * Makes some of corners not rounded\n * */\n groupPosition?:\n | \"top\"\n | \"bottom\"\n | \"left\"\n | \"right\"\n | \"top-left\"\n | \"top-right\"\n | \"bottom-left\"\n | \"bottom-right\"\n | \"middle\";\n }>(),\n {\n modelValue: () => [],\n label: undefined,\n helper: undefined,\n error: undefined,\n placeholder: \"...\",\n required: false,\n disabled: false,\n debounce: 300,\n emptyOptionsText: \"Nothing found\",\n sourceId: undefined,\n groupPosition: undefined,\n },\n);\n\nconst rootRef = ref<HTMLElement | undefined>();\nconst inputRef = ref<HTMLInputElement | undefined>();\n\nconst overlay = useTemplateRef(\"overlay\");\n\nconst data = reactive({\n search: \"\",\n activeOption: -1,\n open: false,\n optionsHeight: 0,\n});\n\nwatch(\n () => data.open,\n (v) => {\n if (!v) {\n data.search = \"\";\n }\n },\n { flush: \"sync\" },\n);\n\nconst selectedValuesRef = computed(() => (Array.isArray(props.modelValue) ? props.modelValue : []));\n\nconst placeholderRef = computed(() => {\n if (data.open && props.modelValue.length > 0) {\n return props.placeholder;\n }\n\n return props.modelValue.length > 0 ? \"\" : props.placeholder;\n});\n\nconst debounce = toRef(props, \"debounce\");\n\nconst searchOptionsRef = useWatchFetch(\n () => [data.search, data.open, props.sourceId] as const,\n async ([search, _open]) => {\n return props.optionsSearch(search, \"label\");\n },\n {\n filterWatchResult: ([_search, open]) => open,\n debounce,\n },\n);\n\nconst modelOptionsRef = useWatchFetch(\n () => [props.modelValue, props.sourceId] as const,\n async ([v]) => {\n return props.optionsSearch(v, \"value\");\n },\n {\n debounce,\n },\n);\n\nconst allOptionsRef = computed(() => {\n const modelOptions = modelOptionsRef.value ?? [];\n const searchOptions = searchOptionsRef.value ?? [];\n\n const seenValues = new Set<string | undefined>();\n const result = [] as ListOptionBase<M>[];\n\n const addOptions = (options: Readonly<ListOptionBase<M>[]>) => {\n for (const option of options) {\n const canonicalValue = canonicalize(option.value);\n if (!seenValues.has(canonicalValue)) {\n seenValues.add(canonicalValue);\n result.push(option);\n }\n }\n };\n\n addOptions(modelOptions);\n addOptions(searchOptions);\n\n return result;\n});\n\nconst selectedOptionsRef = computed(() => {\n return selectedValuesRef.value\n .map((v) => allOptionsRef.value.find((opt) => deepEqual(opt.value, v)))\n .filter((v) => v !== undefined);\n});\n\nconst filteredOptionsRef = computed(() => {\n const selectedValues = unref(selectedValuesRef);\n\n const options = searchOptionsRef.value ?? [];\n\n return [...options].map((opt) => ({\n ...opt,\n selected: deepIncludes(selectedValues, opt.value),\n }));\n});\n\nconst isOptionsLoading = computed(() => searchOptionsRef.loading || modelOptionsRef.loading);\n\nconst isDisabled = computed(() => {\n if (modelOptionsRef.value === undefined) {\n return true;\n }\n\n return props.disabled;\n});\n\nconst tabindex = computed(() => (isDisabled.value ? undefined : \"0\"));\n\nconst updateActiveOption = () => {\n data.activeOption = 0;\n};\n\nconst selectOption = (v: M) => {\n const values = unref(selectedValuesRef);\n emitModel(deepIncludes(values, v) ? values.filter((it) => !deepEqual(it, v)) : [...values, v]);\n if (props.resetSearchOnSelect) {\n data.search = \"\";\n }\n inputRef.value?.focus();\n};\n\nconst unselectOption = (d: M) =>\n emitModel(unref(selectedValuesRef).filter((v) => !deepEqual(v, d)));\n\nconst setFocusOnInput = () => inputRef.value?.focus();\n\nconst toggleOpen = () => (data.open = !data.open);\n\nconst onFocusOut = (event: FocusEvent) => {\n const relatedTarget = event.relatedTarget as Node | null;\n\n if (!rootRef.value?.contains(relatedTarget) && !overlay.value?.listRef?.contains(relatedTarget)) {\n data.open = false;\n }\n};\n\nconst handleKeydown = (e: { code: string; preventDefault(): void }) => {\n const { open, activeOption } = data;\n\n if (!open) {\n if (e.code === \"Enter\") {\n data.open = true;\n }\n return;\n }\n\n if (e.code === \"Escape\") {\n data.open = false;\n inputRef.value?.focus();\n }\n\n const filteredOptions = unref(filteredOptionsRef);\n\n const { length } = filteredOptions;\n\n if (!length) {\n return;\n }\n\n if ([\"ArrowDown\", \"ArrowUp\", \"Enter\"].includes(e.code)) {\n e.preventDefault();\n }\n\n if (e.code === \"Enter\") {\n selectOption(filteredOptions[activeOption].value);\n }\n\n const d = e.code === \"ArrowDown\" ? 1 : e.code === \"ArrowUp\" ? -1 : 0;\n\n data.activeOption = Math.abs(activeOption + d + length) % length;\n\n requestAnimationFrame(() => overlay.value?.scrollIntoActive());\n};\n\nuseLabelNotch(rootRef);\n\nwatch(\n () => props.modelValue,\n () => updateActiveOption(),\n { immediate: true },\n);\n\nconst computedError = computed(() => {\n if (isOptionsLoading.value) {\n return undefined;\n }\n\n if (searchOptionsRef.error) {\n return getErrorMessage(searchOptionsRef.error);\n }\n\n if (modelOptionsRef.error) {\n return getErrorMessage(modelOptionsRef.error);\n }\n\n if (props.error) {\n return getErrorMessage(props.error);\n }\n\n if (props.modelValue.length && selectedOptionsRef.value.length !== props.modelValue.length) {\n return \"The selected values are not one of the options\";\n }\n\n return undefined;\n});\n</script>\n\n<template>\n <div class=\"pl-autocomplete-multi__envelope\" @click=\"setFocusOnInput\">\n <div\n ref=\"rootRef\"\n :tabindex=\"tabindex\"\n class=\"pl-autocomplete-multi\"\n :class=\"{ open: data.open, error: Boolean(computedError), disabled: isDisabled }\"\n @keydown=\"handleKeydown\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-autocomplete-multi__container\">\n <div class=\"pl-autocomplete-multi__field\">\n <input\n ref=\"inputRef\"\n v-model=\"data.search\"\n type=\"text\"\n tabindex=\"-1\"\n :disabled=\"isDisabled\"\n :placeholder=\"placeholderRef\"\n spellcheck=\"false\"\n autocomplete=\"chrome-off\"\n @focus=\"data.open = true\"\n />\n <div v-if=\"!data.open\" class=\"chips-container\">\n <PlChip\n v-for=\"(opt, i) in selectedOptionsRef\"\n :key=\"i\"\n closeable\n small\n @click.stop=\"data.open = true\"\n @close=\"unselectOption(opt.value)\"\n >\n {{ opt.label || opt.value }}\n </PlChip>\n </div>\n\n <div class=\"pl-autocomplete-multi__controls\">\n <PlMaskIcon24 v-if=\"isOptionsLoading\" name=\"loading\" />\n <slot name=\"append\" />\n <div class=\"pl-autocomplete-multi__arrow-wrapper\" @click.stop=\"toggleOpen\">\n <div class=\"arrow-icon arrow-icon-default\" />\n </div>\n </div>\n </div>\n <label v-if=\"label\">\n <PlSvg v-if=\"required\" :uri=\"SvgRequired\" />\n <span>{{ label }}</span>\n <PlTooltip v-if=\"slots.tooltip\" class=\"info\" position=\"top\">\n <template #tooltip>\n <slot name=\"tooltip\" />\n </template>\n </PlTooltip>\n </label>\n <DropdownOverlay\n v-if=\"data.open\"\n ref=\"overlay\"\n :root=\"rootRef\"\n class=\"pl-autocomplete-multi__options\"\n :gap=\"5\"\n tabindex=\"-1\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-autocomplete-multi__open-chips-container\">\n <PlChip\n v-for=\"(opt, i) in selectedOptionsRef\"\n :key=\"i\"\n closeable\n small\n @close=\"unselectOption(opt.value)\"\n >\n {{ opt.label || opt.value }}\n </PlChip>\n </div>\n <DropdownListItem\n v-for=\"(item, index) in filteredOptionsRef\"\n :key=\"index\"\n :option=\"item\"\n :text-item=\"'text'\"\n :is-selected=\"item.selected\"\n :is-hovered=\"data.activeOption == index\"\n size=\"medium\"\n use-checkbox\n @click.stop=\"selectOption(item.value)\"\n />\n <div v-if=\"!filteredOptionsRef.length && !isOptionsLoading\" class=\"nothing-found\">\n {{ emptyOptionsText }}\n </div>\n </DropdownOverlay>\n <DoubleContour class=\"pl-autocomplete-multi__contour\" :group-position=\"groupPosition\" />\n </div>\n </div>\n <div v-if=\"computedError\" class=\"pl-autocomplete-multi__error\">{{ computedError }}</div>\n <div v-else-if=\"helper\" class=\"pl-autocomplete-multi__helper\">{{ helper }}</div>\n </div>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PlAutocompleteMulti.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/PlAutocompleteMulti/PlAutocompleteMulti.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * A multi-select autocomplete component that allows users to search and select multiple values from a list of options.\n * Supports async data fetching, keyboard navigation, and displays selected items as removable chips.\n *\n * @example\n * Basic usage:\n * <PlAutocompleteMulti\n * v-model=\"selectedUsers\"\n * :options-search=\"searchUsers\"\n * :model-search=\"getUsersByIds\"\n * label=\"Select Users\"\n * placeholder=\"Search for users...\"\n * required\n * :debounce=\"300\"\n * helper=\"Choose one or more users from the list\"\n * />\n *\n * With async functions:\n * const selectedUsers = ref([])\n *\n * const searchUsers = async (searchTerm) => {\n * const response = await fetch('/api/users/search?q=' + searchTerm)\n * const users = await response.json()\n * return users.map(user => ({ value: user.id, label: user.name }))\n * }\n *\n * const getUsersByIds = async (userIds) => {\n * if (!userIds.length) return []\n * const response = await fetch('/api/users?ids=' + userIds.join(','))\n * const users = await response.json()\n * return users.map(user => ({ value: user.id, label: user.name }))\n * }\n */\nexport default {\n name: \"PlAutocompleteMulti\",\n};\n\nexport interface OptionsSearch<T> {\n (s: string, type: \"label\"): Promise<Readonly<ListOptionBase<T>[]>>;\n (s: T[], type: \"value\"): Promise<Readonly<ListOptionBase<T>[]>>;\n}\n</script>\n\n<script lang=\"ts\" setup generic=\"M extends string | number = string\">\nimport \"./pl-autocomplete-multi.scss\";\n\nimport type { ListOptionBase } from \"@platforma-sdk/model\";\nimport canonicalize from \"canonicalize\";\nimport { computed, reactive, ref, toRef, unref, useSlots, useTemplateRef, watch } from \"vue\";\nimport { useWatchFetch } from \"../../composition/useWatchFetch.ts\";\nimport { getErrorMessage } from \"../../helpers/error.ts\";\nimport { deepEqual, deepIncludes } from \"../../helpers/objects\";\nimport DoubleContour from \"../../utils/DoubleContour.vue\";\nimport DropdownOverlay from \"../../utils/DropdownOverlay/DropdownOverlay.vue\";\nimport { useLabelNotch } from \"../../utils/useLabelNotch\";\nimport DropdownListItem from \"../DropdownListItem.vue\";\nimport { PlChip } from \"../PlChip\";\nimport { PlMaskIcon24 } from \"../PlMaskIcon24\";\nimport { PlTooltip } from \"../PlTooltip\";\n\nimport SvgRequired from \"../../assets/images/required.svg?raw\";\nimport { PlSvg } from \"../PlSvg\";\n\nconst emit = defineEmits<{\n (e: \"update:modelValue\", v: M[]): void;\n}>();\n\nconst emitModel = (v: M[]) => emit(\"update:modelValue\", v);\n\nconst slots = useSlots();\n\nconst props = withDefaults(\n defineProps<{\n /**\n * The current selected values.\n */\n modelValue: M[];\n /**\n * Lambda for requesting of available options for the dropdown by search string.\n */\n optionsSearch: OptionsSearch<M>;\n /**\n * Unique identifier for the source of the options, changing it will invalidate the options cache.\n */\n sourceId?: string;\n /**\n * The label text for the dropdown field (optional)\n */\n label?: string;\n /**\n * A helper text displayed below the dropdown when there are no errors (optional).\n */\n helper?: string;\n /**\n * Error message displayed below the dropdown (optional)\n */\n error?: unknown;\n /**\n * Placeholder text shown when no value is selected.\n */\n placeholder?: string;\n /**\n * If `true`, the dropdown component is marked as required.\n */\n required?: boolean;\n /**\n * If `true`, the dropdown component is disabled and cannot be interacted with.\n */\n disabled?: boolean;\n /**\n * Debounce time in ms for the options search.\n */\n debounce?: number;\n /**\n * If `true`, the search input is reset and focus is set on it when the new option is selected.\n */\n resetSearchOnSelect?: boolean;\n /**\n * The text to display when no options are found.\n */\n emptyOptionsText?: string;\n /**\n * Makes some of corners not rounded\n * */\n groupPosition?:\n | \"top\"\n | \"bottom\"\n | \"left\"\n | \"right\"\n | \"top-left\"\n | \"top-right\"\n | \"bottom-left\"\n | \"bottom-right\"\n | \"middle\";\n }>(),\n {\n modelValue: () => [],\n label: undefined,\n helper: undefined,\n error: undefined,\n placeholder: \"...\",\n required: false,\n disabled: false,\n debounce: 300,\n emptyOptionsText: \"Nothing found\",\n sourceId: undefined,\n groupPosition: undefined,\n },\n);\n\nconst rootRef = ref<HTMLElement | undefined>();\nconst inputRef = ref<HTMLInputElement | undefined>();\n\nconst overlay = useTemplateRef(\"overlay\");\n\nconst data = reactive({\n search: \"\",\n activeOption: -1,\n open: false,\n optionsHeight: 0,\n});\n\nwatch(\n () => data.open,\n (v) => {\n if (!v) {\n data.search = \"\";\n }\n },\n { flush: \"sync\" },\n);\n\nconst selectedValuesRef = computed(() => (Array.isArray(props.modelValue) ? props.modelValue : []));\n\nconst placeholderRef = computed(() => {\n if (data.open && props.modelValue.length > 0) {\n return props.placeholder;\n }\n\n return props.modelValue.length > 0 ? \"\" : props.placeholder;\n});\n\nconst debounce = toRef(props, \"debounce\");\n\nconst searchOptionsRef = useWatchFetch(\n () => [data.search, data.open, props.sourceId] as const,\n async ([search, _open]) => {\n return props.optionsSearch(search, \"label\");\n },\n {\n filterWatchResult: ([_search, open]) => open,\n debounce,\n },\n);\n\nconst modelOptionsRef = useWatchFetch(\n () => [props.modelValue, props.sourceId] as const,\n async ([v]) => {\n return props.optionsSearch(v, \"value\");\n },\n {\n debounce,\n },\n);\n\nconst allOptionsRef = computed(() => {\n const modelOptions = modelOptionsRef.value ?? [];\n const searchOptions = searchOptionsRef.value ?? [];\n\n const seenValues = new Set<string | undefined>();\n const result = [] as ListOptionBase<M>[];\n\n const addOptions = (options: Readonly<ListOptionBase<M>[]>) => {\n for (const option of options) {\n const canonicalValue = canonicalize(option.value);\n if (!seenValues.has(canonicalValue)) {\n seenValues.add(canonicalValue);\n result.push(option);\n }\n }\n };\n\n addOptions(modelOptions);\n addOptions(searchOptions);\n\n return result;\n});\n\nconst selectedOptionsRef = computed(() => {\n return selectedValuesRef.value\n .map((v) => allOptionsRef.value.find((opt) => deepEqual(opt.value, v)))\n .filter((v) => v !== undefined);\n});\n\nconst filteredOptionsRef = computed(() => {\n const selectedValues = unref(selectedValuesRef);\n\n const options = searchOptionsRef.value ?? [];\n\n return [...options].map((opt) => ({\n ...opt,\n selected: deepIncludes(selectedValues, opt.value),\n }));\n});\n\nconst isOptionsLoading = computed(() => searchOptionsRef.loading || modelOptionsRef.loading);\n\nconst isDisabled = computed(() => {\n if (modelOptionsRef.value === undefined) {\n return true;\n }\n\n return props.disabled;\n});\n\nconst tabindex = computed(() => (isDisabled.value ? undefined : \"0\"));\n\nconst updateActiveOption = () => {\n data.activeOption = 0;\n};\n\nconst selectOption = (v: M) => {\n const values = unref(selectedValuesRef);\n emitModel(deepIncludes(values, v) ? values.filter((it) => !deepEqual(it, v)) : [...values, v]);\n if (props.resetSearchOnSelect) {\n data.search = \"\";\n }\n inputRef.value?.focus();\n};\n\nconst unselectOption = (d: M) =>\n emitModel(unref(selectedValuesRef).filter((v) => !deepEqual(v, d)));\n\nconst setFocusOnInput = () => inputRef.value?.focus();\n\nconst toggleOpen = () => (data.open = !data.open);\n\nconst onFocusOut = (event: FocusEvent) => {\n const relatedTarget = event.relatedTarget as Node | null;\n\n if (!rootRef.value?.contains(relatedTarget) && !overlay.value?.listRef?.contains(relatedTarget)) {\n data.open = false;\n }\n};\n\nconst handleKeydown = (e: { code: string; preventDefault(): void }) => {\n const { open, activeOption } = data;\n\n if (!open) {\n if (e.code === \"Enter\") {\n data.open = true;\n }\n return;\n }\n\n if (e.code === \"Escape\") {\n data.open = false;\n inputRef.value?.focus();\n }\n\n const filteredOptions = unref(filteredOptionsRef);\n\n const { length } = filteredOptions;\n\n if (!length) {\n return;\n }\n\n if ([\"ArrowDown\", \"ArrowUp\", \"Enter\"].includes(e.code)) {\n e.preventDefault();\n }\n\n if (e.code === \"Enter\") {\n selectOption(filteredOptions[activeOption].value);\n }\n\n const d = e.code === \"ArrowDown\" ? 1 : e.code === \"ArrowUp\" ? -1 : 0;\n\n data.activeOption = Math.abs(activeOption + d + length) % length;\n\n requestAnimationFrame(() => overlay.value?.scrollIntoActive());\n};\n\nuseLabelNotch(rootRef);\n\nwatch(\n () => props.modelValue,\n () => updateActiveOption(),\n { immediate: true },\n);\n\nconst computedError = computed(() => {\n if (isOptionsLoading.value) {\n return undefined;\n }\n\n if (searchOptionsRef.error) {\n return getErrorMessage(searchOptionsRef.error);\n }\n\n if (modelOptionsRef.error) {\n return getErrorMessage(modelOptionsRef.error);\n }\n\n if (props.error) {\n return getErrorMessage(props.error);\n }\n\n if (props.modelValue.length && selectedOptionsRef.value.length !== props.modelValue.length) {\n return \"The selected values are not one of the options\";\n }\n\n return undefined;\n});\n</script>\n\n<template>\n <div class=\"pl-autocomplete-multi__envelope\" @click=\"setFocusOnInput\">\n <div\n ref=\"rootRef\"\n :tabindex=\"tabindex\"\n class=\"pl-autocomplete-multi\"\n :class=\"{ open: data.open, error: Boolean(computedError), disabled: isDisabled }\"\n @keydown=\"handleKeydown\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-autocomplete-multi__container\">\n <div class=\"pl-autocomplete-multi__field\">\n <input\n ref=\"inputRef\"\n v-model=\"data.search\"\n type=\"text\"\n tabindex=\"-1\"\n :disabled=\"isDisabled\"\n :placeholder=\"placeholderRef\"\n spellcheck=\"false\"\n autocomplete=\"chrome-off\"\n @focus=\"data.open = true\"\n />\n <div v-if=\"!data.open\" class=\"chips-container\">\n <PlChip\n v-for=\"(opt, i) in selectedOptionsRef\"\n :key=\"i\"\n closeable\n small\n @click.stop=\"data.open = true\"\n @close=\"unselectOption(opt.value)\"\n >\n {{ opt.label || opt.value }}\n </PlChip>\n </div>\n\n <div class=\"pl-autocomplete-multi__controls\">\n <PlMaskIcon24 v-if=\"isOptionsLoading\" name=\"loading\" />\n <slot name=\"append\" />\n <div class=\"pl-autocomplete-multi__arrow-wrapper\" @click.stop=\"toggleOpen\">\n <div class=\"arrow-icon arrow-icon-default\" />\n </div>\n </div>\n </div>\n <label v-if=\"label\">\n <PlSvg v-if=\"required\" :uri=\"SvgRequired\" />\n <span>{{ label }}</span>\n <PlTooltip v-if=\"slots.tooltip\" class=\"info\" position=\"top\">\n <template #tooltip>\n <slot name=\"tooltip\" />\n </template>\n </PlTooltip>\n </label>\n <DropdownOverlay\n v-if=\"data.open\"\n ref=\"overlay\"\n :root=\"rootRef\"\n class=\"pl-autocomplete-multi__options\"\n :gap=\"5\"\n tabindex=\"-1\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-autocomplete-multi__open-chips-container\">\n <PlChip\n v-for=\"(opt, i) in selectedOptionsRef\"\n :key=\"i\"\n closeable\n small\n @close=\"unselectOption(opt.value)\"\n >\n {{ opt.label || opt.value }}\n </PlChip>\n </div>\n <DropdownListItem\n v-for=\"(item, index) in filteredOptionsRef\"\n :key=\"index\"\n :option=\"item\"\n :text-item=\"'text'\"\n :is-selected=\"item.selected\"\n :is-hovered=\"data.activeOption == index\"\n size=\"medium\"\n use-checkbox\n @click.stop=\"selectOption(item.value)\"\n />\n <div v-if=\"!filteredOptionsRef.length && !isOptionsLoading\" class=\"nothing-found\">\n {{ emptyOptionsText }}\n </div>\n </DropdownOverlay>\n <DoubleContour class=\"pl-autocomplete-multi__contour\" :group-position=\"groupPosition\" />\n </div>\n </div>\n <div v-if=\"computedError\" class=\"pl-autocomplete-multi__error\">{{ computedError }}</div>\n <div v-else-if=\"helper\" class=\"pl-autocomplete-multi__helper\">{{ helper }}</div>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "./PlAutocompleteMulti.js";
|