admins-components 9.0.72 → 9.0.75
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/dist/admins-components.js +32 -32
- package/dist/admins-components103.js +96 -96
- package/dist/admins-components103.js.map +1 -1
- package/dist/admins-components105.js.map +1 -1
- package/dist/admins-components26.js +2 -2
- package/dist/admins-components26.js.map +1 -1
- package/dist/admins-components28.js.map +1 -1
- package/dist/admins-components83.js +15 -22
- package/dist/admins-components83.js.map +1 -1
- package/dist/admins-components85.js.map +1 -1
- package/dist/admins-components87.js +42 -22
- package/dist/admins-components87.js.map +1 -1
- package/dist/admins-components91.js +29 -21
- package/dist/admins-components91.js.map +1 -1
- package/dist/admins-components93.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/utils/dataFilters.d.ts +9 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admins-components26.js","names":[],"sources":["../src/components/DropdownSelect.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface DropdownSelectConfig {\n placeholder?: string\n filterable?: boolean\n filterPlaceholder?: string\n clearable?: boolean\n textEllipsis?: boolean\n multiple?: boolean\n lazy?: boolean\n size?: ControlSize\n loading?: boolean\n highlight?: boolean\n disabled?: boolean\n}\n\nexport const dropdownSelectConfigDefaults: DropdownSelectConfig = {\n placeholder: 'Válassz...',\n filterable: true,\n filterPlaceholder: 'Kezdj el gépelni...',\n clearable: true,\n textEllipsis: true,\n multiple: false,\n lazy: false,\n loading: false,\n size: 'normal' as ControlSize,\n highlight: true,\n disabled: false,\n}\n\nexport interface DropdownOption {\n icon?: string\n value?: string\n label: string\n callback?: () => void\n}\n\nexport interface DropdownSelectProps {\n modelValue?: DropdownOption | DropdownOption[] | string | string[] | null\n options: DropdownOption[]\n config?: DropdownSelectConfig\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick, onMounted, onBeforeUnmount } from 'vue'\nimport Button from '@/components/Button.vue'\nimport type { ControlSize } from '@/types/types'\nimport Loader from '@/components/Loader.vue'\n\nconst props = withDefaults(defineProps<DropdownSelectProps>(), {\n modelValue: null,\n config: () => ({ ...dropdownSelectConfigDefaults }),\n})\n\nconst cfg = computed(() => ({ ...dropdownSelectConfigDefaults, ...props.config }))\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: DropdownOption | DropdownOption[] | null]\n 'filter-input': [filterText: string]\n}>()\n\nconst isOpen = ref(false)\nconst filterText = ref('')\nconst wrapperRef = ref<HTMLElement | null>(null)\nconst filterInputRef = ref<HTMLInputElement | null>(null)\nconst buffer = ref<DropdownOption[]>([])\nconst selection = ref<DropdownOption[]>(normalizeToOptions(props.modelValue, props.options))\n\n\nfunction normalizeToOptions(\n val: DropdownOption | DropdownOption[] | string | string[] | null | undefined,\n options: DropdownOption[],\n): DropdownOption[] {\n if (val == null) return []\n const arr = Array.isArray(val) ? val : [val]\n return arr\n .map((entry): DropdownOption | null => {\n if (entry == null) return null\n if (typeof entry === 'object' && 'label' in entry) {\n return entry as DropdownOption\n }\n if (typeof entry === 'string') {\n const found = options.find((o) => o.value === entry)\n return found ?? { value: entry, label: entry }\n }\n return null\n })\n .filter((o): o is DropdownOption => o !== null)\n}\n\nwatch(\n () => [props.modelValue, props.options],\n ([v]) => {\n selection.value = normalizeToOptions(v as typeof props.modelValue, props.options)\n },\n)\n\nwatch(isOpen, (open) => {\n if (open) {\n filterText.value = ''\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n if (cfg.value.lazy) buffer.value = [...selection.value]\n }\n})\n\nfunction onFilterInput(text: string) {\n filterText.value = text\n emit('filter-input', text)\n //debouncedEmit(text)\n}\n\n/* const debouncedEmit = debounce((raw: string) => {\n emit('filter-input', raw)\n}) */\n\n// Display\nconst selectedLabel = computed(() => {\n if (selection.value.length === 0) return null\n if (!cfg.value.multiple) {\n const sel = selection.value[0]\n // Prefer the label from the live options list, fall back to the stored label\n return props.options.find((o) => o.value === sel.value)?.label ?? sel.label ?? null\n }\n if (selection.value.length > 2) return `${selection.value.length} kiválasztva`\n return selection.value\n .map((sel) => props.options.find((o) => o.value === sel.value)?.label ?? sel.label ?? sel.value)\n .join(', ')\n})\n\nconst filteredOptions = computed(() => {\n const q = filterText.value.toLowerCase()\n return q ? props.options.filter((o) => o.label.toLowerCase().includes(q)) : props.options\n})\n\nfunction escapeHtml(str: string) {\n return str.replace(\n /[&<>\"']/g,\n (m) => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' })[m]!,\n )\n}\n\nfunction highlight(label: string) {\n const q = filterText.value.trim()\n if (!q || !cfg.value.highlight) return escapeHtml(label)\n\n const safeLabel = escapeHtml(label)\n const safeQ = escapeHtml(q)\n\n const re = new RegExp(safeQ.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'ig')\n return safeLabel.replace(re, (m) => `<mark class=\"ds-option__highlight\">${m}</mark>`)\n}\n\nconst selectableOptions = computed(() => {\n return filteredOptions.value.filter((o) => o.value)\n})\n\nconst allOptionsSelected = computed(() => {\n if (selectableOptions.value.length === 0) return false\n const currentList = cfg.value.lazy && isOpen.value ? buffer.value : selection.value\n return selectableOptions.value.every((o) => o.value && currentList.some((s) => s.value === o.value))\n})\n\nfunction isSelected(value: string): boolean {\n const list = cfg.value.lazy && isOpen.value ? buffer : selection\n return list.value.some((s) => s.value === value)\n}\n\nfunction toggleAllOptions() {\n const currentList = cfg.value.lazy && isOpen.value ? buffer : selection\n const selectableOpts = selectableOptions.value.filter((o) => o.value)\n\n if (allOptionsSelected.value) {\n const selectableValues = new Set(selectableOpts.map((o) => o.value as string))\n currentList.value = currentList.value.filter((s) => !selectableValues.has(s.value))\n } else {\n const existingValues = new Set(currentList.value.map((s) => s.value))\n const toAdd = selectableOpts.filter((o) => !existingValues.has(o.value as string))\n currentList.value = [...currentList.value, ...toAdd]\n }\n\n if (!cfg.value.lazy) {\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n}\n\n// Actions\nfunction toggleList(list: DropdownOption[], opt: DropdownOption): DropdownOption[] {\n const idx = list.findIndex((s) => s.value === opt.value)\n return idx >= 0 ? list.filter((_, i) => i !== idx) : [...list, opt]\n}\n\nfunction selectOption(opt: DropdownOption) {\n if (opt.callback) {\n opt.callback()\n isOpen.value = false\n return\n }\n\n const value = opt.value\n if (!value) return\n\n if (cfg.value.multiple) {\n if (cfg.value.lazy) {\n buffer.value = toggleList(buffer.value, opt)\n } else {\n selection.value = toggleList(selection.value, opt)\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n } else {\n selection.value = [opt]\n emit('update:modelValue', opt)\n isOpen.value = false\n }\n}\n\nfunction confirm() {\n if (cfg.value.lazy) {\n selection.value = [...buffer.value]\n emit('update:modelValue', buffer.value.length > 0 ? [...buffer.value] : null)\n }\n isOpen.value = false\n}\n\nfunction clear() {\n if (cfg.value.lazy) {\n buffer.value = []\n } else {\n selection.value = []\n emit('update:modelValue', null)\n }\n}\n\nfunction onOptionKeydown(e: KeyboardEvent, opt: DropdownOption) {\n if (e.key === ' ') {\n e.preventDefault()\n selectOption(opt)\n } else if (e.key === 'Enter') {\n e.preventDefault()\n confirm()\n }\n}\n\nfunction onClickOutside(e: MouseEvent) {\n if (wrapperRef.value && !wrapperRef.value.contains(e.target as Node)) isOpen.value = false\n}\n\nonMounted(() => document.addEventListener('mousedown', onClickOutside))\nonBeforeUnmount(() => {\n document.removeEventListener('mousedown', onClickOutside)\n})\n\nfunction toggleOpen() {\n if (cfg.value.disabled) return\n isOpen.value = !isOpen.value\n if (isOpen.value) {\n if (cfg.value.filterable) {\n filterText.value = ''\n emit('filter-input', '')\n }\n }\n}\n\nfunction clearInput() {\n if (cfg.value.disabled) return\n selection.value = []\n emit('update:modelValue', null)\n isOpen.value = false\n}\n\nfunction focusAndOpen() {\n if (cfg.value.disabled) return\n isOpen.value = true\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n}\n\nfunction handleFilterClear() {\n filterText.value = ''\n emit('filter-input', '')\n}\n\ndefineExpose({ focusAndOpen })\n</script>\n\n<template>\n <div class=\"ac-component\">\n <div ref=\"wrapperRef\" class=\"c-wrapper ds-wrapper\">\n <div\n class=\"c-input-row pointer\"\n :class=\"{\n 'c-input-row--sm': cfg.size === 'small',\n 'c-input-row--lg': cfg.size === 'large',\n 'c-input-row--disabled': cfg.disabled,\n }\"\n :aria-disabled=\"cfg.disabled || undefined\"\n @click=\"toggleOpen()\"\n >\n <span v-if=\"selectedLabel\" class=\"c-truncate ds-value\">{{ selectedLabel }}</span>\n <span v-else class=\"c-placeholder\">{{ cfg.placeholder }}</span>\n <button\n v-if=\"cfg.clearable && selection.length > 0\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-clear-btn\"\n @click.stop=\"clearInput()\"\n aria-label=\"Törlés\"\n >\n <i class=\"fa-solid fa-fw fa-xmark\"></i>\n </button>\n <span\n class=\"c-icon-btn c-icon-btn--chevron mr-2\"\n :class=\"{ 'c-icon-btn--chevron-open': isOpen }\"\n >\n <i class=\"fa-solid fa-fw fa-chevron-down\"></i>\n </span>\n </div>\n\n <div\n v-if=\"isOpen\"\n class=\"c-dropdown ds-dropdown ac-component\"\n :class=\"{ 'ds-dropdown--multiple': cfg.multiple }\"\n >\n <div v-if=\"cfg.filterable\" class=\"ds-filter\">\n <span\n v-if=\"cfg.multiple\"\n class=\"c-checkbox ds-select-all-checkbox\"\n :class=\"{ 'c-checkbox--checked': allOptionsSelected }\"\n @click.stop=\"toggleAllOptions()\"\n :title=\"allOptionsSelected ? 'Összes kijelölés törlése' : 'Összes kijelölése'\"\n ></span>\n <input\n ref=\"filterInputRef\"\n type=\"text\"\n id=\"ds-filter-input\"\n class=\"c-focus ds-filter-input\"\n :value=\"filterText\"\n @input=\"onFilterInput(($event.target as HTMLInputElement).value)\"\n autocomplete=\"off\"\n :placeholder=\"cfg.filterPlaceholder\"\n @click.stop\n />\n <button\n v-if=\"filterText\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-filter-clear\"\n @click.stop=\"handleFilterClear()\"\n aria-label=\"Szűrők törlése\"\n >\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <ul class=\"ds-options c-scroll\">\n <li v-if=\"cfg.loading\" class=\"ds-option ds-option--loading\">\n <Loader size=\"2rem\" color=\"var(--neutral-300)\" class=\"m-auto p-3\" />\n </li>\n <template v-else>\n <li\n v-for=\"(opt, idx) in filteredOptions\"\n :key=\"opt.value ?? `cb-${idx}`\"\n class=\"d-option ds-option\"\n :class=\"{ 'ds-option--selected': opt.value && isSelected(opt.value) }\"\n tabindex=\"0\"\n @click=\"selectOption(opt)\"\n @keydown=\"onOptionKeydown($event, opt)\"\n >\n <span\n v-if=\"cfg.multiple && opt.value\"\n class=\"c-checkbox\"\n :class=\"{ 'c-checkbox--checked': isSelected(opt.value) }\"\n ></span>\n <i v-if=\"opt.icon\" class=\"fa-fw\" :class=\"opt.icon\"></i>\n <span\n class=\"d-option__label\"\n :class=\"{ 'c-truncate': cfg.textEllipsis }\"\n v-html=\"highlight(opt.label)\"\n ></span>\n </li>\n <li v-if=\"filteredOptions.length === 0\" class=\"ds-option ds-option--empty\">\n Nincs találat\n </li>\n </template>\n </ul>\n\n <div v-if=\"cfg.multiple || (cfg.clearable && selection.length > 0)\" class=\"c-footer\">\n <Button v-if=\"cfg.clearable\" label=\"Törlés\" outline @click=\"clear\" />\n <Button v-if=\"cfg.multiple\" label=\"OK\" type=\"success\" @click=\"confirm\" />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/dropdown-select.scss\"></style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"admins-components26.js","names":[],"sources":["../src/components/DropdownSelect.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface DropdownSelectConfig {\n placeholder?: string\n filterable?: boolean\n filterPlaceholder?: string\n clearable?: boolean\n textEllipsis?: boolean\n multiple?: boolean\n lazy?: boolean\n size?: ControlSize\n loading?: boolean\n highlight?: boolean\n disabled?: boolean\n}\n\nexport const dropdownSelectConfigDefaults: DropdownSelectConfig = {\n placeholder: 'Válassz...',\n filterable: true,\n filterPlaceholder: 'Kezdj el gépelni...',\n clearable: true,\n textEllipsis: true,\n multiple: false,\n lazy: false,\n loading: false,\n size: 'normal' as ControlSize,\n highlight: true,\n disabled: false,\n}\n\nexport interface DropdownOption {\n icon?: string\n value?: string\n label: string\n callback?: () => void\n}\n\nexport interface DropdownSelectProps {\n modelValue?: DropdownOption | DropdownOption[] | string | string[] | null\n options: DropdownOption[]\n config?: DropdownSelectConfig\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick, onMounted, onBeforeUnmount } from 'vue'\nimport Button from '@/components/Button.vue'\nimport type { ControlSize } from '@/types/types'\nimport Loader from '@/components/Loader.vue'\n\nconst props = withDefaults(defineProps<DropdownSelectProps>(), {\n modelValue: null,\n config: () => ({ ...dropdownSelectConfigDefaults }),\n})\n\nconst cfg = computed(() => ({ ...dropdownSelectConfigDefaults, ...props.config }))\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: DropdownOption | DropdownOption[] | null]\n 'filter-input': [filterText: string]\n}>()\n\nconst isOpen = ref(false)\nconst filterText = ref('')\nconst wrapperRef = ref<HTMLElement | null>(null)\nconst filterInputRef = ref<HTMLInputElement | null>(null)\nconst buffer = ref<DropdownOption[]>([])\nconst selection = ref<DropdownOption[]>(normalizeToOptions(props.modelValue, props.options))\n\n\nfunction normalizeToOptions(\n val: DropdownOption | DropdownOption[] | string | string[] | null | undefined,\n options: DropdownOption[],\n): DropdownOption[] {\n if (val == null) return []\n const arr = Array.isArray(val) ? val : [val]\n return arr\n .map((entry): DropdownOption | null => {\n if (entry == null) return null\n if (typeof entry === 'object' && 'label' in entry) {\n return entry as DropdownOption\n }\n if (typeof entry === 'string') {\n const found = options.find((o) => o.value === entry)\n return found ?? { value: entry, label: entry }\n }\n return null\n })\n .filter((o): o is DropdownOption => o !== null)\n}\n\nwatch(\n () => [props.modelValue, props.options],\n ([v]) => {\n selection.value = normalizeToOptions(v as typeof props.modelValue, props.options)\n },\n)\n\nwatch(isOpen, (open) => {\n if (open) {\n filterText.value = ''\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n if (cfg.value.lazy) buffer.value = [...selection.value]\n }\n})\n\nfunction onFilterInput(text: string) {\n filterText.value = text\n emit('filter-input', text)\n //debouncedEmit(text)\n}\n\n/* const debouncedEmit = debounce((raw: string) => {\n emit('filter-input', raw)\n}) */\n\n// Display\nconst selectedLabel = computed(() => {\n if (selection.value.length === 0) return null\n if (!cfg.value.multiple) {\n const sel = selection.value[0]\n // Prefer the label from the live options list, fall back to the stored label\n return props.options.find((o) => o.value === sel?.value)?.label ?? sel?.label ?? null\n }\n if (selection.value.length > 2) return `${selection.value.length} kiválasztva`\n return selection.value\n .map((sel) => props.options.find((o) => o.value === sel.value)?.label ?? sel.label ?? sel.value)\n .join(', ')\n})\n\nconst filteredOptions = computed(() => {\n const q = filterText.value.toLowerCase()\n return q ? props.options.filter((o) => o.label.toLowerCase().includes(q)) : props.options\n})\n\nfunction escapeHtml(str: string) {\n return str.replace(\n /[&<>\"']/g,\n (m) => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' })[m]!,\n )\n}\n\nfunction highlight(label: string) {\n const q = filterText.value.trim()\n if (!q || !cfg.value.highlight) return escapeHtml(label)\n\n const safeLabel = escapeHtml(label)\n const safeQ = escapeHtml(q)\n\n const re = new RegExp(safeQ.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'ig')\n return safeLabel.replace(re, (m) => `<mark class=\"ds-option__highlight\">${m}</mark>`)\n}\n\nconst selectableOptions = computed(() => {\n return filteredOptions.value.filter((o) => o.value)\n})\n\nconst allOptionsSelected = computed(() => {\n if (selectableOptions.value.length === 0) return false\n const currentList = cfg.value.lazy && isOpen.value ? buffer.value : selection.value\n return selectableOptions.value.every((o) => o.value && currentList.some((s) => s.value === o.value))\n})\n\nfunction isSelected(value: string): boolean {\n const list = cfg.value.lazy && isOpen.value ? buffer : selection\n return list.value.some((s) => s.value === value)\n}\n\nfunction toggleAllOptions() {\n const currentList = cfg.value.lazy && isOpen.value ? buffer : selection\n const selectableOpts = selectableOptions.value.filter((o) => o.value)\n\n if (allOptionsSelected.value) {\n const selectableValues = new Set(selectableOpts.map((o) => o.value as string))\n currentList.value = currentList.value.filter((s) => !selectableValues.has(s.value ?? ''))\n } else {\n const existingValues = new Set(currentList.value.map((s) => s.value))\n const toAdd = selectableOpts.filter((o) => !existingValues.has(o.value as string))\n currentList.value = [...currentList.value, ...toAdd]\n }\n\n if (!cfg.value.lazy) {\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n}\n\n// Actions\nfunction toggleList(list: DropdownOption[], opt: DropdownOption): DropdownOption[] {\n const idx = list.findIndex((s) => s.value === opt.value)\n return idx >= 0 ? list.filter((_, i) => i !== idx) : [...list, opt]\n}\n\nfunction selectOption(opt: DropdownOption) {\n if (opt.callback) {\n opt.callback()\n isOpen.value = false\n return\n }\n\n const value = opt.value\n if (!value) return\n\n if (cfg.value.multiple) {\n if (cfg.value.lazy) {\n buffer.value = toggleList(buffer.value, opt)\n } else {\n selection.value = toggleList(selection.value, opt)\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n } else {\n selection.value = [opt]\n emit('update:modelValue', opt)\n isOpen.value = false\n }\n}\n\nfunction confirm() {\n if (cfg.value.lazy) {\n selection.value = [...buffer.value]\n emit('update:modelValue', buffer.value.length > 0 ? [...buffer.value] : null)\n }\n isOpen.value = false\n}\n\nfunction clear() {\n if (cfg.value.lazy) {\n buffer.value = []\n } else {\n selection.value = []\n emit('update:modelValue', null)\n }\n}\n\nfunction onOptionKeydown(e: KeyboardEvent, opt: DropdownOption) {\n if (e.key === ' ') {\n e.preventDefault()\n selectOption(opt)\n } else if (e.key === 'Enter') {\n e.preventDefault()\n confirm()\n }\n}\n\nfunction onClickOutside(e: MouseEvent) {\n if (wrapperRef.value && !wrapperRef.value.contains(e.target as Node)) isOpen.value = false\n}\n\nonMounted(() => document.addEventListener('mousedown', onClickOutside))\nonBeforeUnmount(() => {\n document.removeEventListener('mousedown', onClickOutside)\n})\n\nfunction toggleOpen() {\n if (cfg.value.disabled) return\n isOpen.value = !isOpen.value\n if (isOpen.value) {\n if (cfg.value.filterable) {\n filterText.value = ''\n emit('filter-input', '')\n }\n }\n}\n\nfunction clearInput() {\n if (cfg.value.disabled) return\n selection.value = []\n emit('update:modelValue', null)\n isOpen.value = false\n}\n\nfunction focusAndOpen() {\n if (cfg.value.disabled) return\n isOpen.value = true\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n}\n\nfunction handleFilterClear() {\n filterText.value = ''\n emit('filter-input', '')\n}\n\ndefineExpose({ focusAndOpen })\n</script>\n\n<template>\n <div class=\"ac-component\">\n <div ref=\"wrapperRef\" class=\"c-wrapper ds-wrapper\">\n <div\n class=\"c-input-row pointer\"\n :class=\"{\n 'c-input-row--sm': cfg.size === 'small',\n 'c-input-row--lg': cfg.size === 'large',\n 'c-input-row--disabled': cfg.disabled,\n }\"\n :aria-disabled=\"cfg.disabled || undefined\"\n @click=\"toggleOpen()\"\n >\n <span v-if=\"selectedLabel\" class=\"c-truncate ds-value\">{{ selectedLabel }}</span>\n <span v-else class=\"c-placeholder\">{{ cfg.placeholder }}</span>\n <button\n v-if=\"cfg.clearable && selection.length > 0\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-clear-btn\"\n @click.stop=\"clearInput()\"\n aria-label=\"Törlés\"\n >\n <i class=\"fa-solid fa-fw fa-xmark\"></i>\n </button>\n <span\n class=\"c-icon-btn c-icon-btn--chevron mr-2\"\n :class=\"{ 'c-icon-btn--chevron-open': isOpen }\"\n >\n <i class=\"fa-solid fa-fw fa-chevron-down\"></i>\n </span>\n </div>\n\n <div\n v-if=\"isOpen\"\n class=\"c-dropdown ds-dropdown ac-component\"\n :class=\"{ 'ds-dropdown--multiple': cfg.multiple }\"\n >\n <div v-if=\"cfg.filterable\" class=\"ds-filter\">\n <span\n v-if=\"cfg.multiple\"\n class=\"c-checkbox ds-select-all-checkbox\"\n :class=\"{ 'c-checkbox--checked': allOptionsSelected }\"\n @click.stop=\"toggleAllOptions()\"\n :title=\"allOptionsSelected ? 'Összes kijelölés törlése' : 'Összes kijelölése'\"\n ></span>\n <input\n ref=\"filterInputRef\"\n type=\"text\"\n id=\"ds-filter-input\"\n class=\"c-focus ds-filter-input\"\n :value=\"filterText\"\n @input=\"onFilterInput(($event.target as HTMLInputElement).value)\"\n autocomplete=\"off\"\n :placeholder=\"cfg.filterPlaceholder\"\n @click.stop\n />\n <button\n v-if=\"filterText\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-filter-clear\"\n @click.stop=\"handleFilterClear()\"\n aria-label=\"Szűrők törlése\"\n >\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <ul class=\"ds-options c-scroll\">\n <li v-if=\"cfg.loading\" class=\"ds-option ds-option--loading\">\n <Loader size=\"2rem\" color=\"var(--neutral-300)\" class=\"m-auto p-3\" />\n </li>\n <template v-else>\n <li\n v-for=\"(opt, idx) in filteredOptions\"\n :key=\"opt.value ?? `cb-${idx}`\"\n class=\"d-option ds-option\"\n :class=\"{ 'ds-option--selected': opt.value && isSelected(opt.value) }\"\n tabindex=\"0\"\n @click=\"selectOption(opt)\"\n @keydown=\"onOptionKeydown($event, opt)\"\n >\n <span\n v-if=\"cfg.multiple && opt.value\"\n class=\"c-checkbox\"\n :class=\"{ 'c-checkbox--checked': isSelected(opt.value) }\"\n ></span>\n <i v-if=\"opt.icon\" class=\"fa-fw\" :class=\"opt.icon\"></i>\n <span\n class=\"d-option__label\"\n :class=\"{ 'c-truncate': cfg.textEllipsis }\"\n v-html=\"highlight(opt.label)\"\n ></span>\n </li>\n <li v-if=\"filteredOptions.length === 0\" class=\"ds-option ds-option--empty\">\n Nincs találat\n </li>\n </template>\n </ul>\n\n <div v-if=\"cfg.multiple || (cfg.clearable && selection.length > 0)\" class=\"c-footer\">\n <Button v-if=\"cfg.clearable\" label=\"Törlés\" outline @click=\"clear\" />\n <Button v-if=\"cfg.multiple\" label=\"OK\" type=\"success\" @click=\"confirm\" />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/dropdown-select.scss\"></style>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admins-components28.js","names":[],"sources":["../src/components/DropdownSelect.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface DropdownSelectConfig {\n placeholder?: string\n filterable?: boolean\n filterPlaceholder?: string\n clearable?: boolean\n textEllipsis?: boolean\n multiple?: boolean\n lazy?: boolean\n size?: ControlSize\n loading?: boolean\n highlight?: boolean\n disabled?: boolean\n}\n\nexport const dropdownSelectConfigDefaults: DropdownSelectConfig = {\n placeholder: 'Válassz...',\n filterable: true,\n filterPlaceholder: 'Kezdj el gépelni...',\n clearable: true,\n textEllipsis: true,\n multiple: false,\n lazy: false,\n loading: false,\n size: 'normal' as ControlSize,\n highlight: true,\n disabled: false,\n}\n\nexport interface DropdownOption {\n icon?: string\n value?: string\n label: string\n callback?: () => void\n}\n\nexport interface DropdownSelectProps {\n modelValue?: DropdownOption | DropdownOption[] | string | string[] | null\n options: DropdownOption[]\n config?: DropdownSelectConfig\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick, onMounted, onBeforeUnmount } from 'vue'\nimport Button from '@/components/Button.vue'\nimport type { ControlSize } from '@/types/types'\nimport Loader from '@/components/Loader.vue'\n\nconst props = withDefaults(defineProps<DropdownSelectProps>(), {\n modelValue: null,\n config: () => ({ ...dropdownSelectConfigDefaults }),\n})\n\nconst cfg = computed(() => ({ ...dropdownSelectConfigDefaults, ...props.config }))\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: DropdownOption | DropdownOption[] | null]\n 'filter-input': [filterText: string]\n}>()\n\nconst isOpen = ref(false)\nconst filterText = ref('')\nconst wrapperRef = ref<HTMLElement | null>(null)\nconst filterInputRef = ref<HTMLInputElement | null>(null)\nconst buffer = ref<DropdownOption[]>([])\nconst selection = ref<DropdownOption[]>(normalizeToOptions(props.modelValue, props.options))\n\n\nfunction normalizeToOptions(\n val: DropdownOption | DropdownOption[] | string | string[] | null | undefined,\n options: DropdownOption[],\n): DropdownOption[] {\n if (val == null) return []\n const arr = Array.isArray(val) ? val : [val]\n return arr\n .map((entry): DropdownOption | null => {\n if (entry == null) return null\n if (typeof entry === 'object' && 'label' in entry) {\n return entry as DropdownOption\n }\n if (typeof entry === 'string') {\n const found = options.find((o) => o.value === entry)\n return found ?? { value: entry, label: entry }\n }\n return null\n })\n .filter((o): o is DropdownOption => o !== null)\n}\n\nwatch(\n () => [props.modelValue, props.options],\n ([v]) => {\n selection.value = normalizeToOptions(v as typeof props.modelValue, props.options)\n },\n)\n\nwatch(isOpen, (open) => {\n if (open) {\n filterText.value = ''\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n if (cfg.value.lazy) buffer.value = [...selection.value]\n }\n})\n\nfunction onFilterInput(text: string) {\n filterText.value = text\n emit('filter-input', text)\n //debouncedEmit(text)\n}\n\n/* const debouncedEmit = debounce((raw: string) => {\n emit('filter-input', raw)\n}) */\n\n// Display\nconst selectedLabel = computed(() => {\n if (selection.value.length === 0) return null\n if (!cfg.value.multiple) {\n const sel = selection.value[0]\n // Prefer the label from the live options list, fall back to the stored label\n return props.options.find((o) => o.value === sel.value)?.label ?? sel.label ?? null\n }\n if (selection.value.length > 2) return `${selection.value.length} kiválasztva`\n return selection.value\n .map((sel) => props.options.find((o) => o.value === sel.value)?.label ?? sel.label ?? sel.value)\n .join(', ')\n})\n\nconst filteredOptions = computed(() => {\n const q = filterText.value.toLowerCase()\n return q ? props.options.filter((o) => o.label.toLowerCase().includes(q)) : props.options\n})\n\nfunction escapeHtml(str: string) {\n return str.replace(\n /[&<>\"']/g,\n (m) => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' })[m]!,\n )\n}\n\nfunction highlight(label: string) {\n const q = filterText.value.trim()\n if (!q || !cfg.value.highlight) return escapeHtml(label)\n\n const safeLabel = escapeHtml(label)\n const safeQ = escapeHtml(q)\n\n const re = new RegExp(safeQ.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'ig')\n return safeLabel.replace(re, (m) => `<mark class=\"ds-option__highlight\">${m}</mark>`)\n}\n\nconst selectableOptions = computed(() => {\n return filteredOptions.value.filter((o) => o.value)\n})\n\nconst allOptionsSelected = computed(() => {\n if (selectableOptions.value.length === 0) return false\n const currentList = cfg.value.lazy && isOpen.value ? buffer.value : selection.value\n return selectableOptions.value.every((o) => o.value && currentList.some((s) => s.value === o.value))\n})\n\nfunction isSelected(value: string): boolean {\n const list = cfg.value.lazy && isOpen.value ? buffer : selection\n return list.value.some((s) => s.value === value)\n}\n\nfunction toggleAllOptions() {\n const currentList = cfg.value.lazy && isOpen.value ? buffer : selection\n const selectableOpts = selectableOptions.value.filter((o) => o.value)\n\n if (allOptionsSelected.value) {\n const selectableValues = new Set(selectableOpts.map((o) => o.value as string))\n currentList.value = currentList.value.filter((s) => !selectableValues.has(s.value))\n } else {\n const existingValues = new Set(currentList.value.map((s) => s.value))\n const toAdd = selectableOpts.filter((o) => !existingValues.has(o.value as string))\n currentList.value = [...currentList.value, ...toAdd]\n }\n\n if (!cfg.value.lazy) {\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n}\n\n// Actions\nfunction toggleList(list: DropdownOption[], opt: DropdownOption): DropdownOption[] {\n const idx = list.findIndex((s) => s.value === opt.value)\n return idx >= 0 ? list.filter((_, i) => i !== idx) : [...list, opt]\n}\n\nfunction selectOption(opt: DropdownOption) {\n if (opt.callback) {\n opt.callback()\n isOpen.value = false\n return\n }\n\n const value = opt.value\n if (!value) return\n\n if (cfg.value.multiple) {\n if (cfg.value.lazy) {\n buffer.value = toggleList(buffer.value, opt)\n } else {\n selection.value = toggleList(selection.value, opt)\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n } else {\n selection.value = [opt]\n emit('update:modelValue', opt)\n isOpen.value = false\n }\n}\n\nfunction confirm() {\n if (cfg.value.lazy) {\n selection.value = [...buffer.value]\n emit('update:modelValue', buffer.value.length > 0 ? [...buffer.value] : null)\n }\n isOpen.value = false\n}\n\nfunction clear() {\n if (cfg.value.lazy) {\n buffer.value = []\n } else {\n selection.value = []\n emit('update:modelValue', null)\n }\n}\n\nfunction onOptionKeydown(e: KeyboardEvent, opt: DropdownOption) {\n if (e.key === ' ') {\n e.preventDefault()\n selectOption(opt)\n } else if (e.key === 'Enter') {\n e.preventDefault()\n confirm()\n }\n}\n\nfunction onClickOutside(e: MouseEvent) {\n if (wrapperRef.value && !wrapperRef.value.contains(e.target as Node)) isOpen.value = false\n}\n\nonMounted(() => document.addEventListener('mousedown', onClickOutside))\nonBeforeUnmount(() => {\n document.removeEventListener('mousedown', onClickOutside)\n})\n\nfunction toggleOpen() {\n if (cfg.value.disabled) return\n isOpen.value = !isOpen.value\n if (isOpen.value) {\n if (cfg.value.filterable) {\n filterText.value = ''\n emit('filter-input', '')\n }\n }\n}\n\nfunction clearInput() {\n if (cfg.value.disabled) return\n selection.value = []\n emit('update:modelValue', null)\n isOpen.value = false\n}\n\nfunction focusAndOpen() {\n if (cfg.value.disabled) return\n isOpen.value = true\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n}\n\nfunction handleFilterClear() {\n filterText.value = ''\n emit('filter-input', '')\n}\n\ndefineExpose({ focusAndOpen })\n</script>\n\n<template>\n <div class=\"ac-component\">\n <div ref=\"wrapperRef\" class=\"c-wrapper ds-wrapper\">\n <div\n class=\"c-input-row pointer\"\n :class=\"{\n 'c-input-row--sm': cfg.size === 'small',\n 'c-input-row--lg': cfg.size === 'large',\n 'c-input-row--disabled': cfg.disabled,\n }\"\n :aria-disabled=\"cfg.disabled || undefined\"\n @click=\"toggleOpen()\"\n >\n <span v-if=\"selectedLabel\" class=\"c-truncate ds-value\">{{ selectedLabel }}</span>\n <span v-else class=\"c-placeholder\">{{ cfg.placeholder }}</span>\n <button\n v-if=\"cfg.clearable && selection.length > 0\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-clear-btn\"\n @click.stop=\"clearInput()\"\n aria-label=\"Törlés\"\n >\n <i class=\"fa-solid fa-fw fa-xmark\"></i>\n </button>\n <span\n class=\"c-icon-btn c-icon-btn--chevron mr-2\"\n :class=\"{ 'c-icon-btn--chevron-open': isOpen }\"\n >\n <i class=\"fa-solid fa-fw fa-chevron-down\"></i>\n </span>\n </div>\n\n <div\n v-if=\"isOpen\"\n class=\"c-dropdown ds-dropdown ac-component\"\n :class=\"{ 'ds-dropdown--multiple': cfg.multiple }\"\n >\n <div v-if=\"cfg.filterable\" class=\"ds-filter\">\n <span\n v-if=\"cfg.multiple\"\n class=\"c-checkbox ds-select-all-checkbox\"\n :class=\"{ 'c-checkbox--checked': allOptionsSelected }\"\n @click.stop=\"toggleAllOptions()\"\n :title=\"allOptionsSelected ? 'Összes kijelölés törlése' : 'Összes kijelölése'\"\n ></span>\n <input\n ref=\"filterInputRef\"\n type=\"text\"\n id=\"ds-filter-input\"\n class=\"c-focus ds-filter-input\"\n :value=\"filterText\"\n @input=\"onFilterInput(($event.target as HTMLInputElement).value)\"\n autocomplete=\"off\"\n :placeholder=\"cfg.filterPlaceholder\"\n @click.stop\n />\n <button\n v-if=\"filterText\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-filter-clear\"\n @click.stop=\"handleFilterClear()\"\n aria-label=\"Szűrők törlése\"\n >\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <ul class=\"ds-options c-scroll\">\n <li v-if=\"cfg.loading\" class=\"ds-option ds-option--loading\">\n <Loader size=\"2rem\" color=\"var(--neutral-300)\" class=\"m-auto p-3\" />\n </li>\n <template v-else>\n <li\n v-for=\"(opt, idx) in filteredOptions\"\n :key=\"opt.value ?? `cb-${idx}`\"\n class=\"d-option ds-option\"\n :class=\"{ 'ds-option--selected': opt.value && isSelected(opt.value) }\"\n tabindex=\"0\"\n @click=\"selectOption(opt)\"\n @keydown=\"onOptionKeydown($event, opt)\"\n >\n <span\n v-if=\"cfg.multiple && opt.value\"\n class=\"c-checkbox\"\n :class=\"{ 'c-checkbox--checked': isSelected(opt.value) }\"\n ></span>\n <i v-if=\"opt.icon\" class=\"fa-fw\" :class=\"opt.icon\"></i>\n <span\n class=\"d-option__label\"\n :class=\"{ 'c-truncate': cfg.textEllipsis }\"\n v-html=\"highlight(opt.label)\"\n ></span>\n </li>\n <li v-if=\"filteredOptions.length === 0\" class=\"ds-option ds-option--empty\">\n Nincs találat\n </li>\n </template>\n </ul>\n\n <div v-if=\"cfg.multiple || (cfg.clearable && selection.length > 0)\" class=\"c-footer\">\n <Button v-if=\"cfg.clearable\" label=\"Törlés\" outline @click=\"clear\" />\n <Button v-if=\"cfg.multiple\" label=\"OK\" type=\"success\" @click=\"confirm\" />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/dropdown-select.scss\"></style>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"admins-components28.js","names":[],"sources":["../src/components/DropdownSelect.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface DropdownSelectConfig {\n placeholder?: string\n filterable?: boolean\n filterPlaceholder?: string\n clearable?: boolean\n textEllipsis?: boolean\n multiple?: boolean\n lazy?: boolean\n size?: ControlSize\n loading?: boolean\n highlight?: boolean\n disabled?: boolean\n}\n\nexport const dropdownSelectConfigDefaults: DropdownSelectConfig = {\n placeholder: 'Válassz...',\n filterable: true,\n filterPlaceholder: 'Kezdj el gépelni...',\n clearable: true,\n textEllipsis: true,\n multiple: false,\n lazy: false,\n loading: false,\n size: 'normal' as ControlSize,\n highlight: true,\n disabled: false,\n}\n\nexport interface DropdownOption {\n icon?: string\n value?: string\n label: string\n callback?: () => void\n}\n\nexport interface DropdownSelectProps {\n modelValue?: DropdownOption | DropdownOption[] | string | string[] | null\n options: DropdownOption[]\n config?: DropdownSelectConfig\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick, onMounted, onBeforeUnmount } from 'vue'\nimport Button from '@/components/Button.vue'\nimport type { ControlSize } from '@/types/types'\nimport Loader from '@/components/Loader.vue'\n\nconst props = withDefaults(defineProps<DropdownSelectProps>(), {\n modelValue: null,\n config: () => ({ ...dropdownSelectConfigDefaults }),\n})\n\nconst cfg = computed(() => ({ ...dropdownSelectConfigDefaults, ...props.config }))\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: DropdownOption | DropdownOption[] | null]\n 'filter-input': [filterText: string]\n}>()\n\nconst isOpen = ref(false)\nconst filterText = ref('')\nconst wrapperRef = ref<HTMLElement | null>(null)\nconst filterInputRef = ref<HTMLInputElement | null>(null)\nconst buffer = ref<DropdownOption[]>([])\nconst selection = ref<DropdownOption[]>(normalizeToOptions(props.modelValue, props.options))\n\n\nfunction normalizeToOptions(\n val: DropdownOption | DropdownOption[] | string | string[] | null | undefined,\n options: DropdownOption[],\n): DropdownOption[] {\n if (val == null) return []\n const arr = Array.isArray(val) ? val : [val]\n return arr\n .map((entry): DropdownOption | null => {\n if (entry == null) return null\n if (typeof entry === 'object' && 'label' in entry) {\n return entry as DropdownOption\n }\n if (typeof entry === 'string') {\n const found = options.find((o) => o.value === entry)\n return found ?? { value: entry, label: entry }\n }\n return null\n })\n .filter((o): o is DropdownOption => o !== null)\n}\n\nwatch(\n () => [props.modelValue, props.options],\n ([v]) => {\n selection.value = normalizeToOptions(v as typeof props.modelValue, props.options)\n },\n)\n\nwatch(isOpen, (open) => {\n if (open) {\n filterText.value = ''\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n if (cfg.value.lazy) buffer.value = [...selection.value]\n }\n})\n\nfunction onFilterInput(text: string) {\n filterText.value = text\n emit('filter-input', text)\n //debouncedEmit(text)\n}\n\n/* const debouncedEmit = debounce((raw: string) => {\n emit('filter-input', raw)\n}) */\n\n// Display\nconst selectedLabel = computed(() => {\n if (selection.value.length === 0) return null\n if (!cfg.value.multiple) {\n const sel = selection.value[0]\n // Prefer the label from the live options list, fall back to the stored label\n return props.options.find((o) => o.value === sel?.value)?.label ?? sel?.label ?? null\n }\n if (selection.value.length > 2) return `${selection.value.length} kiválasztva`\n return selection.value\n .map((sel) => props.options.find((o) => o.value === sel.value)?.label ?? sel.label ?? sel.value)\n .join(', ')\n})\n\nconst filteredOptions = computed(() => {\n const q = filterText.value.toLowerCase()\n return q ? props.options.filter((o) => o.label.toLowerCase().includes(q)) : props.options\n})\n\nfunction escapeHtml(str: string) {\n return str.replace(\n /[&<>\"']/g,\n (m) => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' })[m]!,\n )\n}\n\nfunction highlight(label: string) {\n const q = filterText.value.trim()\n if (!q || !cfg.value.highlight) return escapeHtml(label)\n\n const safeLabel = escapeHtml(label)\n const safeQ = escapeHtml(q)\n\n const re = new RegExp(safeQ.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'ig')\n return safeLabel.replace(re, (m) => `<mark class=\"ds-option__highlight\">${m}</mark>`)\n}\n\nconst selectableOptions = computed(() => {\n return filteredOptions.value.filter((o) => o.value)\n})\n\nconst allOptionsSelected = computed(() => {\n if (selectableOptions.value.length === 0) return false\n const currentList = cfg.value.lazy && isOpen.value ? buffer.value : selection.value\n return selectableOptions.value.every((o) => o.value && currentList.some((s) => s.value === o.value))\n})\n\nfunction isSelected(value: string): boolean {\n const list = cfg.value.lazy && isOpen.value ? buffer : selection\n return list.value.some((s) => s.value === value)\n}\n\nfunction toggleAllOptions() {\n const currentList = cfg.value.lazy && isOpen.value ? buffer : selection\n const selectableOpts = selectableOptions.value.filter((o) => o.value)\n\n if (allOptionsSelected.value) {\n const selectableValues = new Set(selectableOpts.map((o) => o.value as string))\n currentList.value = currentList.value.filter((s) => !selectableValues.has(s.value ?? ''))\n } else {\n const existingValues = new Set(currentList.value.map((s) => s.value))\n const toAdd = selectableOpts.filter((o) => !existingValues.has(o.value as string))\n currentList.value = [...currentList.value, ...toAdd]\n }\n\n if (!cfg.value.lazy) {\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n}\n\n// Actions\nfunction toggleList(list: DropdownOption[], opt: DropdownOption): DropdownOption[] {\n const idx = list.findIndex((s) => s.value === opt.value)\n return idx >= 0 ? list.filter((_, i) => i !== idx) : [...list, opt]\n}\n\nfunction selectOption(opt: DropdownOption) {\n if (opt.callback) {\n opt.callback()\n isOpen.value = false\n return\n }\n\n const value = opt.value\n if (!value) return\n\n if (cfg.value.multiple) {\n if (cfg.value.lazy) {\n buffer.value = toggleList(buffer.value, opt)\n } else {\n selection.value = toggleList(selection.value, opt)\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n } else {\n selection.value = [opt]\n emit('update:modelValue', opt)\n isOpen.value = false\n }\n}\n\nfunction confirm() {\n if (cfg.value.lazy) {\n selection.value = [...buffer.value]\n emit('update:modelValue', buffer.value.length > 0 ? [...buffer.value] : null)\n }\n isOpen.value = false\n}\n\nfunction clear() {\n if (cfg.value.lazy) {\n buffer.value = []\n } else {\n selection.value = []\n emit('update:modelValue', null)\n }\n}\n\nfunction onOptionKeydown(e: KeyboardEvent, opt: DropdownOption) {\n if (e.key === ' ') {\n e.preventDefault()\n selectOption(opt)\n } else if (e.key === 'Enter') {\n e.preventDefault()\n confirm()\n }\n}\n\nfunction onClickOutside(e: MouseEvent) {\n if (wrapperRef.value && !wrapperRef.value.contains(e.target as Node)) isOpen.value = false\n}\n\nonMounted(() => document.addEventListener('mousedown', onClickOutside))\nonBeforeUnmount(() => {\n document.removeEventListener('mousedown', onClickOutside)\n})\n\nfunction toggleOpen() {\n if (cfg.value.disabled) return\n isOpen.value = !isOpen.value\n if (isOpen.value) {\n if (cfg.value.filterable) {\n filterText.value = ''\n emit('filter-input', '')\n }\n }\n}\n\nfunction clearInput() {\n if (cfg.value.disabled) return\n selection.value = []\n emit('update:modelValue', null)\n isOpen.value = false\n}\n\nfunction focusAndOpen() {\n if (cfg.value.disabled) return\n isOpen.value = true\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n}\n\nfunction handleFilterClear() {\n filterText.value = ''\n emit('filter-input', '')\n}\n\ndefineExpose({ focusAndOpen })\n</script>\n\n<template>\n <div class=\"ac-component\">\n <div ref=\"wrapperRef\" class=\"c-wrapper ds-wrapper\">\n <div\n class=\"c-input-row pointer\"\n :class=\"{\n 'c-input-row--sm': cfg.size === 'small',\n 'c-input-row--lg': cfg.size === 'large',\n 'c-input-row--disabled': cfg.disabled,\n }\"\n :aria-disabled=\"cfg.disabled || undefined\"\n @click=\"toggleOpen()\"\n >\n <span v-if=\"selectedLabel\" class=\"c-truncate ds-value\">{{ selectedLabel }}</span>\n <span v-else class=\"c-placeholder\">{{ cfg.placeholder }}</span>\n <button\n v-if=\"cfg.clearable && selection.length > 0\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-clear-btn\"\n @click.stop=\"clearInput()\"\n aria-label=\"Törlés\"\n >\n <i class=\"fa-solid fa-fw fa-xmark\"></i>\n </button>\n <span\n class=\"c-icon-btn c-icon-btn--chevron mr-2\"\n :class=\"{ 'c-icon-btn--chevron-open': isOpen }\"\n >\n <i class=\"fa-solid fa-fw fa-chevron-down\"></i>\n </span>\n </div>\n\n <div\n v-if=\"isOpen\"\n class=\"c-dropdown ds-dropdown ac-component\"\n :class=\"{ 'ds-dropdown--multiple': cfg.multiple }\"\n >\n <div v-if=\"cfg.filterable\" class=\"ds-filter\">\n <span\n v-if=\"cfg.multiple\"\n class=\"c-checkbox ds-select-all-checkbox\"\n :class=\"{ 'c-checkbox--checked': allOptionsSelected }\"\n @click.stop=\"toggleAllOptions()\"\n :title=\"allOptionsSelected ? 'Összes kijelölés törlése' : 'Összes kijelölése'\"\n ></span>\n <input\n ref=\"filterInputRef\"\n type=\"text\"\n id=\"ds-filter-input\"\n class=\"c-focus ds-filter-input\"\n :value=\"filterText\"\n @input=\"onFilterInput(($event.target as HTMLInputElement).value)\"\n autocomplete=\"off\"\n :placeholder=\"cfg.filterPlaceholder\"\n @click.stop\n />\n <button\n v-if=\"filterText\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-filter-clear\"\n @click.stop=\"handleFilterClear()\"\n aria-label=\"Szűrők törlése\"\n >\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <ul class=\"ds-options c-scroll\">\n <li v-if=\"cfg.loading\" class=\"ds-option ds-option--loading\">\n <Loader size=\"2rem\" color=\"var(--neutral-300)\" class=\"m-auto p-3\" />\n </li>\n <template v-else>\n <li\n v-for=\"(opt, idx) in filteredOptions\"\n :key=\"opt.value ?? `cb-${idx}`\"\n class=\"d-option ds-option\"\n :class=\"{ 'ds-option--selected': opt.value && isSelected(opt.value) }\"\n tabindex=\"0\"\n @click=\"selectOption(opt)\"\n @keydown=\"onOptionKeydown($event, opt)\"\n >\n <span\n v-if=\"cfg.multiple && opt.value\"\n class=\"c-checkbox\"\n :class=\"{ 'c-checkbox--checked': isSelected(opt.value) }\"\n ></span>\n <i v-if=\"opt.icon\" class=\"fa-fw\" :class=\"opt.icon\"></i>\n <span\n class=\"d-option__label\"\n :class=\"{ 'c-truncate': cfg.textEllipsis }\"\n v-html=\"highlight(opt.label)\"\n ></span>\n </li>\n <li v-if=\"filteredOptions.length === 0\" class=\"ds-option ds-option--empty\">\n Nincs találat\n </li>\n </template>\n </ul>\n\n <div v-if=\"cfg.multiple || (cfg.clearable && selection.length > 0)\" class=\"c-footer\">\n <Button v-if=\"cfg.clearable\" label=\"Törlés\" outline @click=\"clear\" />\n <Button v-if=\"cfg.multiple\" label=\"OK\" type=\"success\" @click=\"confirm\" />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/dropdown-select.scss\"></style>\n"],"mappings":""}
|
|
@@ -38,19 +38,9 @@ var j = /* @__PURE__ */ d({
|
|
|
38
38
|
extraStyle: (e) => ({ minWidth: `${Math.max(e.width, 240)}px` }),
|
|
39
39
|
closeOnScroll: !0
|
|
40
40
|
}), R = a({
|
|
41
|
-
get: () =>
|
|
42
|
-
let e = M.modelValue?.key;
|
|
43
|
-
return e ? M.options.find((t) => t.value === e) ?? {
|
|
44
|
-
value: e,
|
|
45
|
-
label: e
|
|
46
|
-
} : null;
|
|
47
|
-
},
|
|
41
|
+
get: () => M.modelValue?.key ?? null,
|
|
48
42
|
set: (e) => {
|
|
49
|
-
|
|
50
|
-
V(null, M.modelValue?.direction ?? "asc");
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
Array.isArray(e) || V(e.value ?? null, M.modelValue?.direction ?? "asc");
|
|
43
|
+
Array.isArray(e) || V(typeof e == "string" ? e : null, M.modelValue?.direction ?? "asc");
|
|
54
44
|
}
|
|
55
45
|
}), z = a({
|
|
56
46
|
get: () => M.modelValue?.direction ?? "asc",
|
|
@@ -74,6 +64,9 @@ var j = /* @__PURE__ */ d({
|
|
|
74
64
|
function H() {
|
|
75
65
|
V(null, "asc"), I.value = !1;
|
|
76
66
|
}
|
|
67
|
+
function U(e) {
|
|
68
|
+
Array.isArray(e) || (R.value = e?.value ?? null);
|
|
69
|
+
}
|
|
77
70
|
return v(I, (e) => {
|
|
78
71
|
if (!e || !M.handleUrl || M.modelValue) return;
|
|
79
72
|
let t = A();
|
|
@@ -102,8 +95,8 @@ var j = /* @__PURE__ */ d({
|
|
|
102
95
|
"aria-label": "Rendezés törlése",
|
|
103
96
|
title: "Rendezés törlése",
|
|
104
97
|
onClick: y(H, ["stop"])
|
|
105
|
-
}, [...r[
|
|
106
|
-
l("span", { class: f(["c-icon-btn c-icon-btn--chevron", { "c-icon-btn--chevron-open": _(I) }]) }, [...r[
|
|
98
|
+
}, [...r[4] ||= [l("i", { class: "fa-solid fa-fw fa-xmark" }, null, -1)]])) : s("", !0),
|
|
99
|
+
l("span", { class: f(["c-icon-btn c-icon-btn--chevron", { "c-icon-btn--chevron-open": _(I) }]) }, [...r[5] ||= [l("i", { class: "fa-solid fa-fw fa-chevron-down" }, null, -1)]], 2)
|
|
107
100
|
], 10, x), (m(), o(i, { to: "body" }, [l("div", C, [_(I) ? (m(), c("div", {
|
|
108
101
|
key: 0,
|
|
109
102
|
ref_key: "dropdownRef",
|
|
@@ -111,7 +104,7 @@ var j = /* @__PURE__ */ d({
|
|
|
111
104
|
class: "ds-sort-panel",
|
|
112
105
|
style: p(_(L))
|
|
113
106
|
}, [
|
|
114
|
-
l("div", w, [r[
|
|
107
|
+
l("div", w, [r[6] ||= l("label", { class: "ds-sort-panel__label" }, "Oszlop", -1), u(n, {
|
|
115
108
|
"model-value": R.value,
|
|
116
109
|
options: d.options,
|
|
117
110
|
config: {
|
|
@@ -119,26 +112,26 @@ var j = /* @__PURE__ */ d({
|
|
|
119
112
|
placeholder: "Válassz oszlopot...",
|
|
120
113
|
filterable: !1
|
|
121
114
|
},
|
|
122
|
-
"onUpdate:modelValue":
|
|
115
|
+
"onUpdate:modelValue": U
|
|
123
116
|
}, null, 8, ["model-value", "options"])]),
|
|
124
|
-
l("div", T, [r[
|
|
117
|
+
l("div", T, [r[9] ||= l("span", { class: "ds-sort-panel__label" }, "Irány", -1), l("div", E, [l("button", {
|
|
125
118
|
type: "button",
|
|
126
119
|
class: f(["ds-sort-direction__btn", { "is-active": z.value === "asc" }]),
|
|
127
120
|
"aria-pressed": z.value === "asc",
|
|
128
121
|
"aria-label": "Növekvő",
|
|
129
|
-
onClick: r[
|
|
130
|
-
}, [...r[
|
|
122
|
+
onClick: r[1] ||= (e) => z.value = "asc"
|
|
123
|
+
}, [...r[7] ||= [l("i", { class: "fa-solid fa-fw fa-arrow-up-wide-short" }, null, -1), l("span", null, "Növekvő", -1)]], 10, D), l("button", {
|
|
131
124
|
type: "button",
|
|
132
125
|
class: f(["ds-sort-direction__btn dir-desc", { "is-active": z.value === "desc" }]),
|
|
133
126
|
"aria-pressed": z.value === "desc",
|
|
134
127
|
"aria-label": "Csökkenő",
|
|
135
|
-
onClick: r[
|
|
136
|
-
}, [...r[
|
|
128
|
+
onClick: r[2] ||= (e) => z.value = "desc"
|
|
129
|
+
}, [...r[8] ||= [l("i", { class: "fa-solid fa-fw fa-arrow-down-wide-short" }, null, -1), l("span", null, "Csökkenő", -1)]], 10, O)])]),
|
|
137
130
|
l("div", k, [u(e, {
|
|
138
131
|
label: "Rendben",
|
|
139
132
|
outline: "",
|
|
140
133
|
size: "small",
|
|
141
|
-
onClick: r[
|
|
134
|
+
onClick: r[3] ||= (e) => I.value = !1
|
|
142
135
|
})])
|
|
143
136
|
], 4)) : s("", !0)])]))], 512)]));
|
|
144
137
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admins-components83.js","names":[],"sources":["../src/components/data-table/DataSort.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type SortDirection = 'asc' | 'desc'\n\nexport interface DataSortOption {\n value: string\n label: string\n icon?: string\n}\n\nexport interface DataSortProps {\n modelValue: { key: string; direction: SortDirection } | null\n options: DataSortOption[]\n placeholder?: string\n handleUrl?: boolean\n disabled?: boolean\n}\n\nexport function getDefaultSort(): { key: string; direction: SortDirection } | null {\n if (typeof window === 'undefined') return null\n const params = new URLSearchParams(window.location.search)\n const key = params.get('sortBy')\n const dir = params.get('sortDir')\n if (key && (dir === 'asc' || dir === 'desc')) {\n return { key, direction: dir }\n }\n return null\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport DropdownSelect, { type DropdownOption } from '@/components/DropdownSelect.vue'\nimport { useDropdownAnchor } from '@/composables/useDropdownAnchor'\nimport { writeUrlOrRemove } from '@/utils/url'\nimport Button from '../Button.vue'\n\nconst props = withDefaults(defineProps<DataSortProps>(), {\n placeholder: 'Rendezés...',\n handleUrl: false,\n disabled: false\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [sort: { key: string; direction: SortDirection } | null]\n 'sort-change': [sort: { key: string; direction: SortDirection } | null]\n}>()\n\nconst wrapperRef = ref<HTMLElement | null>(null)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst { isOpen, dropdownStyle } = useDropdownAnchor(wrapperRef, dropdownRef, {\n extraStyle: (rect) => ({ minWidth: `${Math.max(rect.width, 240)}px` }),\n closeOnScroll: true,\n})\n\nconst sortBy = computed<DropdownOption | DropdownOption[] | null>({\n get: () => {\n const key = props.modelValue?.key\n if (!key) return null\n const opt = props.options.find((o) => o.value === key)\n return opt ?? { value: key, label: key }\n },\n set: (v) => {\n if (v == null) {\n emitChange(null, props.modelValue?.direction ?? 'asc')\n return\n }\n if (Array.isArray(v)) return\n emitChange(v.value ?? null, props.modelValue?.direction ?? 'asc')\n },\n})\n\nconst direction = computed<SortDirection>({\n get: () => props.modelValue?.direction ?? 'asc',\n set: (d) => emitChange(props.modelValue?.key ?? null, d),\n})\n\nconst activeLabel = computed(() => {\n if (!props.modelValue) return props.placeholder\n const opt = props.options.find((o) => o.value === props.modelValue!.key)\n const label = opt?.label ?? props.modelValue.key\n return `${label} (${props.modelValue.direction === 'asc' ? 'növekvő' : 'csökkenő'})`\n})\n\nfunction emitChange(key: string | null, dir: SortDirection) {\n if (key == null) {\n if (props.handleUrl) {\n writeUrlOrRemove('sortBy', null, { handleUrl: true })\n writeUrlOrRemove('sortDir', null, { handleUrl: true })\n }\n emit('update:modelValue', null)\n emit('sort-change', null)\n return\n }\n if (props.handleUrl) {\n writeUrlOrRemove('sortBy', key, { handleUrl: true })\n writeUrlOrRemove('sortDir', dir, { handleUrl: true, default: 'asc' })\n }\n const next = { key, direction: dir }\n emit('update:modelValue', next)\n emit('sort-change', next)\n}\n\nfunction clear() {\n emitChange(null, 'asc')\n isOpen.value = false\n}\n\n// Read initial state from URL on mount when handleUrl is true and modelValue is empty.\nwatch(\n isOpen,\n (open) => {\n if (!open || !props.handleUrl || props.modelValue) return\n const sort = getDefaultSort()\n if (sort) emitChange(sort.key, sort.direction)\n },\n { immediate: true },\n)\n</script>\n\n<template>\n <div class=\"ac-component\">\n <div ref=\"wrapperRef\" class=\"ds-sort-wrapper\">\n <button\n type=\"button\"\n class=\"c-btn ds-sort-trigger lh-1\"\n :class=\"[modelValue && 'is-active', disabled && 'is-disabled', isOpen && 'is-open']\"\n :disabled=\"disabled\"\n :aria-label=\"`Rendezés: ${activeLabel}`\"\n @click=\"isOpen = !isOpen\"\n >\n <i\n class=\"fa-solid fa-fw\"\n :class=\"\n !modelValue || modelValue.direction === 'asc'\n ? 'fa-arrow-up-wide-short'\n : 'fa-arrow-down-wide-short'\n \"\n ></i>\n <span class=\"ds-sort-label c-truncate\">{{ activeLabel }}</span>\n <button\n v-if=\"modelValue\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-sort-clear\"\n aria-label=\"Rendezés törlése\"\n title=\"Rendezés törlése\"\n @click.stop=\"clear\"\n >\n <i class=\"fa-solid fa-fw fa-xmark\"></i>\n </button>\n <span\n class=\"c-icon-btn c-icon-btn--chevron\"\n :class=\"{ 'c-icon-btn--chevron-open': isOpen }\"\n >\n <i class=\"fa-solid fa-fw fa-chevron-down\"></i>\n </span>\n </button>\n\n <Teleport to=\"body\">\n <div class=\"ac-component\">\n <div v-if=\"isOpen\" ref=\"dropdownRef\" class=\"ds-sort-panel\" :style=\"dropdownStyle\">\n\n <div class=\"ds-sort-panel__row\">\n <label class=\"ds-sort-panel__label\">Oszlop</label>\n <DropdownSelect\n :model-value=\"sortBy\"\n :options=\"options\"\n :config=\"{\n clearable: false,\n placeholder: 'Válassz oszlopot...',\n filterable: false,\n }\"\n @update:model-value=\"(v) => (sortBy = v)\"\n />\n </div>\n\n <div class=\"ds-sort-panel__row\">\n <span class=\"ds-sort-panel__label\">Irány</span>\n <div class=\"ds-sort-direction\" role=\"group\" aria-label=\"Rendezés iránya\">\n <button\n type=\"button\"\n class=\"ds-sort-direction__btn\"\n :class=\"{ 'is-active': direction === 'asc' }\"\n :aria-pressed=\"direction === 'asc'\"\n aria-label=\"Növekvő\"\n @click=\"direction = 'asc'\"\n >\n <i class=\"fa-solid fa-fw fa-arrow-up-wide-short\"></i>\n <span>Növekvő</span>\n </button>\n <button\n type=\"button\"\n class=\"ds-sort-direction__btn dir-desc\"\n :class=\"{ 'is-active': direction === 'desc' }\"\n :aria-pressed=\"direction === 'desc'\"\n aria-label=\"Csökkenő\"\n @click=\"direction = 'desc'\"\n >\n <i class=\"fa-solid fa-fw fa-arrow-down-wide-short\"></i>\n <span>Csökkenő</span>\n </button>\n </div>\n </div>\n\n <div class=\"ds-sort-panel__footer\">\n <Button label=\"Rendben\" outline size=\"small\" @click=\"isOpen = false\" />\n </div>\n </div>\n </div>\n </Teleport>\n </div>\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/data-table/data-sort.scss\"></style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"admins-components83.js","names":[],"sources":["../src/components/data-table/DataSort.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type SortDirection = 'asc' | 'desc'\n\nexport interface DataSortOption {\n value: string\n label: string\n icon?: string\n}\n\nexport interface DataSortProps {\n modelValue: { key: string; direction: SortDirection } | null\n options: DataSortOption[]\n placeholder?: string\n handleUrl?: boolean\n disabled?: boolean\n}\n\nexport function getDefaultSort(): { key: string; direction: SortDirection } | null {\n if (typeof window === 'undefined') return null\n const params = new URLSearchParams(window.location.search)\n const key = params.get('sortBy')\n const dir = params.get('sortDir')\n if (key && (dir === 'asc' || dir === 'desc')) {\n return { key, direction: dir }\n }\n return null\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport DropdownSelect, { type DropdownOption } from '@/components/DropdownSelect.vue'\nimport { useDropdownAnchor } from '@/composables/useDropdownAnchor'\nimport { writeUrlOrRemove } from '@/utils/url'\nimport Button from '../Button.vue'\n\nconst props = withDefaults(defineProps<DataSortProps>(), {\n placeholder: 'Rendezés...',\n handleUrl: false,\n disabled: false\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [sort: { key: string; direction: SortDirection } | null]\n 'sort-change': [sort: { key: string; direction: SortDirection } | null]\n}>()\n\nconst wrapperRef = ref<HTMLElement | null>(null)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst { isOpen, dropdownStyle } = useDropdownAnchor(wrapperRef, dropdownRef, {\n extraStyle: (rect) => ({ minWidth: `${Math.max(rect.width, 240)}px` }),\n closeOnScroll: true,\n})\n\nconst sortBy = computed<string | string[] | null>({\n get: () => props.modelValue?.key ?? null,\n set: (v) => {\n if (Array.isArray(v)) return\n const next = typeof v === 'string' ? v : null\n emitChange(next, props.modelValue?.direction ?? 'asc')\n },\n})\n\nconst direction = computed<SortDirection>({\n get: () => props.modelValue?.direction ?? 'asc',\n set: (d) => emitChange(props.modelValue?.key ?? null, d),\n})\n\nconst activeLabel = computed(() => {\n if (!props.modelValue) return props.placeholder\n const opt = props.options.find((o) => o.value === props.modelValue!.key)\n const label = opt?.label ?? props.modelValue.key\n return `${label} (${props.modelValue.direction === 'asc' ? 'növekvő' : 'csökkenő'})`\n})\n\nfunction emitChange(key: string | null, dir: SortDirection) {\n if (key == null) {\n if (props.handleUrl) {\n writeUrlOrRemove('sortBy', null, { handleUrl: true })\n writeUrlOrRemove('sortDir', null, { handleUrl: true })\n }\n emit('update:modelValue', null)\n emit('sort-change', null)\n return\n }\n if (props.handleUrl) {\n writeUrlOrRemove('sortBy', key, { handleUrl: true })\n writeUrlOrRemove('sortDir', dir, { handleUrl: true, default: 'asc' })\n }\n const next = { key, direction: dir }\n emit('update:modelValue', next)\n emit('sort-change', next)\n}\n\nfunction clear() {\n emitChange(null, 'asc')\n isOpen.value = false\n}\n\nfunction onSortColumnChange(v: DropdownOption | DropdownOption[] | null) {\n if (Array.isArray(v)) return\n sortBy.value = v?.value ?? null\n}\n\n// Read initial state from URL on mount when handleUrl is true and modelValue is empty.\nwatch(\n isOpen,\n (open) => {\n if (!open || !props.handleUrl || props.modelValue) return\n const sort = getDefaultSort()\n if (sort) emitChange(sort.key, sort.direction)\n },\n { immediate: true },\n)\n</script>\n\n<template>\n <div class=\"ac-component\">\n <div ref=\"wrapperRef\" class=\"ds-sort-wrapper\">\n <button\n type=\"button\"\n class=\"c-btn ds-sort-trigger lh-1\"\n :class=\"[modelValue && 'is-active', disabled && 'is-disabled', isOpen && 'is-open']\"\n :disabled=\"disabled\"\n :aria-label=\"`Rendezés: ${activeLabel}`\"\n @click=\"isOpen = !isOpen\"\n >\n <i\n class=\"fa-solid fa-fw\"\n :class=\"\n !modelValue || modelValue.direction === 'asc'\n ? 'fa-arrow-up-wide-short'\n : 'fa-arrow-down-wide-short'\n \"\n ></i>\n <span class=\"ds-sort-label c-truncate\">{{ activeLabel }}</span>\n <button\n v-if=\"modelValue\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-sort-clear\"\n aria-label=\"Rendezés törlése\"\n title=\"Rendezés törlése\"\n @click.stop=\"clear\"\n >\n <i class=\"fa-solid fa-fw fa-xmark\"></i>\n </button>\n <span\n class=\"c-icon-btn c-icon-btn--chevron\"\n :class=\"{ 'c-icon-btn--chevron-open': isOpen }\"\n >\n <i class=\"fa-solid fa-fw fa-chevron-down\"></i>\n </span>\n </button>\n\n <Teleport to=\"body\">\n <div class=\"ac-component\">\n <div v-if=\"isOpen\" ref=\"dropdownRef\" class=\"ds-sort-panel\" :style=\"dropdownStyle\">\n\n <div class=\"ds-sort-panel__row\">\n <label class=\"ds-sort-panel__label\">Oszlop</label>\n <DropdownSelect\n :model-value=\"sortBy\"\n :options=\"options\"\n :config=\"{\n clearable: false,\n placeholder: 'Válassz oszlopot...',\n filterable: false,\n }\"\n @update:model-value=\"onSortColumnChange\"\n />\n </div>\n\n <div class=\"ds-sort-panel__row\">\n <span class=\"ds-sort-panel__label\">Irány</span>\n <div class=\"ds-sort-direction\" role=\"group\" aria-label=\"Rendezés iránya\">\n <button\n type=\"button\"\n class=\"ds-sort-direction__btn\"\n :class=\"{ 'is-active': direction === 'asc' }\"\n :aria-pressed=\"direction === 'asc'\"\n aria-label=\"Növekvő\"\n @click=\"direction = 'asc'\"\n >\n <i class=\"fa-solid fa-fw fa-arrow-up-wide-short\"></i>\n <span>Növekvő</span>\n </button>\n <button\n type=\"button\"\n class=\"ds-sort-direction__btn dir-desc\"\n :class=\"{ 'is-active': direction === 'desc' }\"\n :aria-pressed=\"direction === 'desc'\"\n aria-label=\"Csökkenő\"\n @click=\"direction = 'desc'\"\n >\n <i class=\"fa-solid fa-fw fa-arrow-down-wide-short\"></i>\n <span>Csökkenő</span>\n </button>\n </div>\n </div>\n\n <div class=\"ds-sort-panel__footer\">\n <Button label=\"Rendben\" outline size=\"small\" @click=\"isOpen = false\" />\n </div>\n </div>\n </div>\n </Teleport>\n </div>\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/data-table/data-sort.scss\"></style>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admins-components85.js","names":[],"sources":["../src/components/data-table/DataSort.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type SortDirection = 'asc' | 'desc'\n\nexport interface DataSortOption {\n value: string\n label: string\n icon?: string\n}\n\nexport interface DataSortProps {\n modelValue: { key: string; direction: SortDirection } | null\n options: DataSortOption[]\n placeholder?: string\n handleUrl?: boolean\n disabled?: boolean\n}\n\nexport function getDefaultSort(): { key: string; direction: SortDirection } | null {\n if (typeof window === 'undefined') return null\n const params = new URLSearchParams(window.location.search)\n const key = params.get('sortBy')\n const dir = params.get('sortDir')\n if (key && (dir === 'asc' || dir === 'desc')) {\n return { key, direction: dir }\n }\n return null\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport DropdownSelect, { type DropdownOption } from '@/components/DropdownSelect.vue'\nimport { useDropdownAnchor } from '@/composables/useDropdownAnchor'\nimport { writeUrlOrRemove } from '@/utils/url'\nimport Button from '../Button.vue'\n\nconst props = withDefaults(defineProps<DataSortProps>(), {\n placeholder: 'Rendezés...',\n handleUrl: false,\n disabled: false\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [sort: { key: string; direction: SortDirection } | null]\n 'sort-change': [sort: { key: string; direction: SortDirection } | null]\n}>()\n\nconst wrapperRef = ref<HTMLElement | null>(null)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst { isOpen, dropdownStyle } = useDropdownAnchor(wrapperRef, dropdownRef, {\n extraStyle: (rect) => ({ minWidth: `${Math.max(rect.width, 240)}px` }),\n closeOnScroll: true,\n})\n\nconst sortBy = computed<
|
|
1
|
+
{"version":3,"file":"admins-components85.js","names":[],"sources":["../src/components/data-table/DataSort.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type SortDirection = 'asc' | 'desc'\n\nexport interface DataSortOption {\n value: string\n label: string\n icon?: string\n}\n\nexport interface DataSortProps {\n modelValue: { key: string; direction: SortDirection } | null\n options: DataSortOption[]\n placeholder?: string\n handleUrl?: boolean\n disabled?: boolean\n}\n\nexport function getDefaultSort(): { key: string; direction: SortDirection } | null {\n if (typeof window === 'undefined') return null\n const params = new URLSearchParams(window.location.search)\n const key = params.get('sortBy')\n const dir = params.get('sortDir')\n if (key && (dir === 'asc' || dir === 'desc')) {\n return { key, direction: dir }\n }\n return null\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport DropdownSelect, { type DropdownOption } from '@/components/DropdownSelect.vue'\nimport { useDropdownAnchor } from '@/composables/useDropdownAnchor'\nimport { writeUrlOrRemove } from '@/utils/url'\nimport Button from '../Button.vue'\n\nconst props = withDefaults(defineProps<DataSortProps>(), {\n placeholder: 'Rendezés...',\n handleUrl: false,\n disabled: false\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [sort: { key: string; direction: SortDirection } | null]\n 'sort-change': [sort: { key: string; direction: SortDirection } | null]\n}>()\n\nconst wrapperRef = ref<HTMLElement | null>(null)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst { isOpen, dropdownStyle } = useDropdownAnchor(wrapperRef, dropdownRef, {\n extraStyle: (rect) => ({ minWidth: `${Math.max(rect.width, 240)}px` }),\n closeOnScroll: true,\n})\n\nconst sortBy = computed<string | string[] | null>({\n get: () => props.modelValue?.key ?? null,\n set: (v) => {\n if (Array.isArray(v)) return\n const next = typeof v === 'string' ? v : null\n emitChange(next, props.modelValue?.direction ?? 'asc')\n },\n})\n\nconst direction = computed<SortDirection>({\n get: () => props.modelValue?.direction ?? 'asc',\n set: (d) => emitChange(props.modelValue?.key ?? null, d),\n})\n\nconst activeLabel = computed(() => {\n if (!props.modelValue) return props.placeholder\n const opt = props.options.find((o) => o.value === props.modelValue!.key)\n const label = opt?.label ?? props.modelValue.key\n return `${label} (${props.modelValue.direction === 'asc' ? 'növekvő' : 'csökkenő'})`\n})\n\nfunction emitChange(key: string | null, dir: SortDirection) {\n if (key == null) {\n if (props.handleUrl) {\n writeUrlOrRemove('sortBy', null, { handleUrl: true })\n writeUrlOrRemove('sortDir', null, { handleUrl: true })\n }\n emit('update:modelValue', null)\n emit('sort-change', null)\n return\n }\n if (props.handleUrl) {\n writeUrlOrRemove('sortBy', key, { handleUrl: true })\n writeUrlOrRemove('sortDir', dir, { handleUrl: true, default: 'asc' })\n }\n const next = { key, direction: dir }\n emit('update:modelValue', next)\n emit('sort-change', next)\n}\n\nfunction clear() {\n emitChange(null, 'asc')\n isOpen.value = false\n}\n\nfunction onSortColumnChange(v: DropdownOption | DropdownOption[] | null) {\n if (Array.isArray(v)) return\n sortBy.value = v?.value ?? null\n}\n\n// Read initial state from URL on mount when handleUrl is true and modelValue is empty.\nwatch(\n isOpen,\n (open) => {\n if (!open || !props.handleUrl || props.modelValue) return\n const sort = getDefaultSort()\n if (sort) emitChange(sort.key, sort.direction)\n },\n { immediate: true },\n)\n</script>\n\n<template>\n <div class=\"ac-component\">\n <div ref=\"wrapperRef\" class=\"ds-sort-wrapper\">\n <button\n type=\"button\"\n class=\"c-btn ds-sort-trigger lh-1\"\n :class=\"[modelValue && 'is-active', disabled && 'is-disabled', isOpen && 'is-open']\"\n :disabled=\"disabled\"\n :aria-label=\"`Rendezés: ${activeLabel}`\"\n @click=\"isOpen = !isOpen\"\n >\n <i\n class=\"fa-solid fa-fw\"\n :class=\"\n !modelValue || modelValue.direction === 'asc'\n ? 'fa-arrow-up-wide-short'\n : 'fa-arrow-down-wide-short'\n \"\n ></i>\n <span class=\"ds-sort-label c-truncate\">{{ activeLabel }}</span>\n <button\n v-if=\"modelValue\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-sort-clear\"\n aria-label=\"Rendezés törlése\"\n title=\"Rendezés törlése\"\n @click.stop=\"clear\"\n >\n <i class=\"fa-solid fa-fw fa-xmark\"></i>\n </button>\n <span\n class=\"c-icon-btn c-icon-btn--chevron\"\n :class=\"{ 'c-icon-btn--chevron-open': isOpen }\"\n >\n <i class=\"fa-solid fa-fw fa-chevron-down\"></i>\n </span>\n </button>\n\n <Teleport to=\"body\">\n <div class=\"ac-component\">\n <div v-if=\"isOpen\" ref=\"dropdownRef\" class=\"ds-sort-panel\" :style=\"dropdownStyle\">\n\n <div class=\"ds-sort-panel__row\">\n <label class=\"ds-sort-panel__label\">Oszlop</label>\n <DropdownSelect\n :model-value=\"sortBy\"\n :options=\"options\"\n :config=\"{\n clearable: false,\n placeholder: 'Válassz oszlopot...',\n filterable: false,\n }\"\n @update:model-value=\"onSortColumnChange\"\n />\n </div>\n\n <div class=\"ds-sort-panel__row\">\n <span class=\"ds-sort-panel__label\">Irány</span>\n <div class=\"ds-sort-direction\" role=\"group\" aria-label=\"Rendezés iránya\">\n <button\n type=\"button\"\n class=\"ds-sort-direction__btn\"\n :class=\"{ 'is-active': direction === 'asc' }\"\n :aria-pressed=\"direction === 'asc'\"\n aria-label=\"Növekvő\"\n @click=\"direction = 'asc'\"\n >\n <i class=\"fa-solid fa-fw fa-arrow-up-wide-short\"></i>\n <span>Növekvő</span>\n </button>\n <button\n type=\"button\"\n class=\"ds-sort-direction__btn dir-desc\"\n :class=\"{ 'is-active': direction === 'desc' }\"\n :aria-pressed=\"direction === 'desc'\"\n aria-label=\"Csökkenő\"\n @click=\"direction = 'desc'\"\n >\n <i class=\"fa-solid fa-fw fa-arrow-down-wide-short\"></i>\n <span>Csökkenő</span>\n </button>\n </div>\n </div>\n\n <div class=\"ds-sort-panel__footer\">\n <Button label=\"Rendben\" outline size=\"small\" @click=\"isOpen = false\" />\n </div>\n </div>\n </div>\n </Teleport>\n </div>\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/data-table/data-sort.scss\"></style>\n"],"mappings":""}
|
|
@@ -2,32 +2,52 @@ import { getFullStorageKey as e } from "./admins-components78.js";
|
|
|
2
2
|
import { getUrlParam as t, removeUrlParam as n, setUrlParam as r } from "./admins-components79.js";
|
|
3
3
|
//#region src/utils/dataFilters.ts
|
|
4
4
|
function i(e, t, n = !0) {
|
|
5
|
-
let r =
|
|
5
|
+
let r = s(e), i = Object.keys(r).length > 0, a = (i ? null : l(t))?.values ?? {}, o = {};
|
|
6
6
|
for (let t of e) {
|
|
7
7
|
if (t.type === "separator") continue;
|
|
8
8
|
let e;
|
|
9
9
|
if (t.key in r) e = r[t.key];
|
|
10
10
|
else if (i) continue;
|
|
11
|
-
else if (t.key in
|
|
11
|
+
else if (t.key in a) e = a[t.key];
|
|
12
12
|
else if (t.value !== void 0) e = t.value;
|
|
13
13
|
else continue;
|
|
14
14
|
if (e != null) if (n && t.transformer) {
|
|
15
15
|
let n = t.transformer(e);
|
|
16
|
-
n && Object.assign(
|
|
17
|
-
} else
|
|
16
|
+
n && Object.assign(o, n);
|
|
17
|
+
} else o[t.key] = e;
|
|
18
18
|
}
|
|
19
|
-
return
|
|
19
|
+
return o;
|
|
20
20
|
}
|
|
21
|
-
function a(e) {
|
|
21
|
+
function a(e, t, n = !0) {
|
|
22
|
+
let r = i(e, t, n), a = {};
|
|
23
|
+
for (let t of e) {
|
|
24
|
+
if (t.type !== "dropdown") {
|
|
25
|
+
t.key in r && (a[t.key] = r[t.key]);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
let e = o(r[t.key]);
|
|
29
|
+
e != null && (a[t.key] = e);
|
|
30
|
+
}
|
|
31
|
+
return a;
|
|
32
|
+
}
|
|
33
|
+
function o(e) {
|
|
34
|
+
if (e == null) return null;
|
|
35
|
+
if (Array.isArray(e)) {
|
|
36
|
+
let t = e.map((e) => e == null ? null : typeof e == "object" && "value" in e ? e.value ?? null : typeof e == "string" ? e : null).filter((e) => e !== null);
|
|
37
|
+
return t.length > 0 ? t : null;
|
|
38
|
+
}
|
|
39
|
+
return typeof e == "object" && "value" in e ? e.value ?? null : typeof e == "string" ? e : null;
|
|
40
|
+
}
|
|
41
|
+
function s(e) {
|
|
22
42
|
let n = {};
|
|
23
43
|
for (let r of e) {
|
|
24
44
|
if (r.type === "separator") continue;
|
|
25
45
|
let e = t(r.key);
|
|
26
|
-
e && (n[r.key] =
|
|
46
|
+
e && (n[r.key] = d(r.type, e, r.value));
|
|
27
47
|
}
|
|
28
48
|
return n;
|
|
29
49
|
}
|
|
30
|
-
function
|
|
50
|
+
function c(t) {
|
|
31
51
|
try {
|
|
32
52
|
let n = e("filters", t), r = JSON.parse(localStorage.getItem(n) ?? "[]");
|
|
33
53
|
return Array.isArray(r) ? r.filter((e) => e && typeof e == "object" && typeof e.id == "string" && e.values && typeof e.savedAt == "string") : [];
|
|
@@ -35,34 +55,34 @@ function o(t) {
|
|
|
35
55
|
return [];
|
|
36
56
|
}
|
|
37
57
|
}
|
|
38
|
-
function
|
|
39
|
-
return
|
|
58
|
+
function l(e) {
|
|
59
|
+
return c(e).find((e) => e.isDefault) ?? null;
|
|
40
60
|
}
|
|
41
|
-
function
|
|
61
|
+
function u(e) {
|
|
42
62
|
return Object.fromEntries(Object.entries(e).filter(([e, t]) => t !== null && t !== "" && t !== void 0));
|
|
43
63
|
}
|
|
44
|
-
function
|
|
64
|
+
function d(e, t, n) {
|
|
45
65
|
if (e === "number") {
|
|
46
66
|
let e = Number(t);
|
|
47
67
|
return isNaN(e) ? n ?? null : e;
|
|
48
68
|
}
|
|
49
|
-
return e === "date" || e === "datetime" ? { utc: t } : e === "daterange" || e === "datetimerange" ?
|
|
69
|
+
return e === "date" || e === "datetime" ? { utc: t } : e === "daterange" || e === "datetimerange" ? m(t, n) : e === "dropdown" ? f(t) : e === "checkbox" ? t === "true" : t;
|
|
50
70
|
}
|
|
51
|
-
function
|
|
71
|
+
function f(e) {
|
|
52
72
|
if (e.startsWith("[") || e.startsWith("{")) try {
|
|
53
73
|
let t = JSON.parse(e);
|
|
54
74
|
if (Array.isArray(t)) {
|
|
55
|
-
let e = t.map(
|
|
75
|
+
let e = t.map(p).filter((e) => e !== null);
|
|
56
76
|
return e.length > 0 ? e : null;
|
|
57
77
|
}
|
|
58
|
-
if (t && typeof t == "object") return
|
|
78
|
+
if (t && typeof t == "object") return p(t);
|
|
59
79
|
} catch {}
|
|
60
80
|
return e ? {
|
|
61
81
|
value: e,
|
|
62
82
|
label: e
|
|
63
83
|
} : null;
|
|
64
84
|
}
|
|
65
|
-
function
|
|
85
|
+
function p(e) {
|
|
66
86
|
if (e == null) return null;
|
|
67
87
|
if (typeof e == "object" && "label" in e) {
|
|
68
88
|
let t = e;
|
|
@@ -76,7 +96,7 @@ function d(e) {
|
|
|
76
96
|
label: e
|
|
77
97
|
} : null;
|
|
78
98
|
}
|
|
79
|
-
function
|
|
99
|
+
function m(e, t) {
|
|
80
100
|
try {
|
|
81
101
|
let t = JSON.parse(e);
|
|
82
102
|
return t && typeof t == "object" && "local" in t && t.local && (t.local = new Date(t.local)), t;
|
|
@@ -84,14 +104,14 @@ function f(e, t) {
|
|
|
84
104
|
return t ?? null;
|
|
85
105
|
}
|
|
86
106
|
}
|
|
87
|
-
function
|
|
107
|
+
function h(e, t) {
|
|
88
108
|
for (let i of e) {
|
|
89
109
|
if (i.type === "separator") continue;
|
|
90
110
|
let e = t[i.key];
|
|
91
|
-
e == null || e === "" ? n(i.key) : i.type === "date" || i.type === "datetime" ? r(i.key, e.utc) : i.type === "dropdown" ? r(i.key, JSON.stringify(
|
|
111
|
+
e == null || e === "" ? n(i.key) : i.type === "date" || i.type === "datetime" ? r(i.key, e.utc) : i.type === "dropdown" ? r(i.key, JSON.stringify(g(e))) : typeof e == "object" ? r(i.key, JSON.stringify(e)) : r(i.key, String(e));
|
|
92
112
|
}
|
|
93
113
|
}
|
|
94
|
-
function
|
|
114
|
+
function g(e, t) {
|
|
95
115
|
if (e == null) return null;
|
|
96
116
|
let n = (e) => {
|
|
97
117
|
if (e == null) return null;
|
|
@@ -109,4 +129,4 @@ function m(e, t) {
|
|
|
109
129
|
return n(e);
|
|
110
130
|
}
|
|
111
131
|
//#endregion
|
|
112
|
-
export {
|
|
132
|
+
export { u as filterEmptyValues, a as getDefaultFilterValues, i as getDefaultFilters, l as getDefaultSavedFilter, s as getFilterUrlParams, c as getSavedFilters, h as writeFilterParams };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admins-components87.js","names":[],"sources":["../src/utils/dataFilters.ts"],"sourcesContent":["import type { FilterItem } from '@/components/data-table/DataFilters.vue'\nimport type { SavedFilter } from '@/components/data-table/FiltersHistory.vue'\nimport type { DropdownOption } from '@/components/DropdownSelect.vue'\nimport { getFullStorageKey } from '@/utils/storageKey'\nimport { getUrlParam, setUrlParam, removeUrlParam } from '@/utils/url'\n\n export function getDefaultFilters(\n items: FilterItem[],\n storageKey?: string,\n useTransformers = true,\n): Record<string, unknown> {\n const urlFilters = getFilterUrlParams(items)\n const hasUrlParams = Object.keys(urlFilters).length > 0\n const defaultFilter = hasUrlParams ? null : getDefaultSavedFilter(storageKey)\n const defaultSavedValues = defaultFilter?.values ?? {}\n\n const result: Record<string, unknown> = {}\n\n for (const item of items) {\n if (item.type === 'separator') continue\n\n let value: unknown\n\n if (item.key in urlFilters) {\n value = urlFilters[item.key]\n } else if (hasUrlParams) {\n continue\n } else if (item.key in defaultSavedValues) {\n value = defaultSavedValues[item.key]\n } else if (item.value !== undefined) {\n value = item.value\n } else {\n continue\n }\n\n if (value == null) continue\n\n if (useTransformers && item.transformer) {\n const transformed = item.transformer(value)\n if (transformed) {\n Object.assign(result, transformed)\n }\n } else {\n result[item.key] = value\n }\n }\n\n return result\n}\n\nexport function getFilterUrlParams(items: FilterItem[]): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n\n for (const item of items) {\n if (item.type === 'separator') continue\n\n const raw = getUrlParam(item.key)\n if (raw) {\n result[item.key] = parseFilterValue(item.type, raw, item.value)\n }\n }\n return result\n}\n\nexport function getSavedFilters(storageKey?: string): SavedFilter[] {\n try {\n const fullStorageKey = getFullStorageKey('filters', storageKey)\n const parsed = JSON.parse(localStorage.getItem(fullStorageKey) ?? '[]')\n return Array.isArray(parsed)\n ? parsed.filter(\n (e) =>\n e &&\n typeof e === 'object' &&\n typeof e.id === 'string' &&\n e.values &&\n typeof e.savedAt === 'string',\n )\n : []\n } catch {\n return []\n }\n}\n\nexport function getDefaultSavedFilter(storageKey?: string): SavedFilter | null {\n const savedFilters = getSavedFilters(storageKey)\n return savedFilters.find((f) => f.isDefault) ?? null\n}\n\nexport function filterEmptyValues(filters: Record<string, any>): Record<string, any> {\n return Object.fromEntries(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n Object.entries(filters).filter(([_, val]) => val !== null && val !== '' && val !== undefined),\n )\n}\n\nfunction parseFilterValue(type: FilterItem['type'], raw: string, fallback: unknown): unknown {\n if (type === 'number') {\n const n = Number(raw)\n return isNaN(n) ? (fallback ?? null) : n\n }\n if (type === 'date' || type === 'datetime') {\n return { utc: raw }\n }\n if (type === 'daterange' || type === 'datetimerange') {\n return parseRangeValue(raw, fallback)\n }\n if (type === 'dropdown') {\n return parseDropdownStoredValue(raw)\n }\n if (type === 'checkbox') {\n return raw === 'true'\n }\n\n return raw\n}\n\nfunction parseDropdownStoredValue(raw: string): DropdownOption | DropdownOption[] | null {\n // Try to parse as JSON first (new format or legacy array)\n if (raw.startsWith('[') || raw.startsWith('{')) {\n try {\n const parsed = JSON.parse(raw)\n if (Array.isArray(parsed)) {\n const opts = parsed.map(toDropdownOption).filter((o): o is DropdownOption => o !== null)\n return opts.length > 0 ? opts : null\n }\n if (parsed && typeof parsed === 'object') {\n const opt = toDropdownOption(parsed)\n return opt\n }\n } catch {\n // fall through to legacy handling\n }\n }\n // Legacy: plain string value\n if (raw) return { value: raw, label: raw }\n return null\n}\n\nfunction toDropdownOption(entry: unknown): DropdownOption | null {\n if (entry == null) return null\n if (typeof entry === 'object' && 'label' in (entry as object)) {\n const obj = entry as DropdownOption\n if (obj.value != null && typeof obj.label === 'string') {\n return { value: obj.value, label: obj.label }\n }\n }\n if (typeof entry === 'string') {\n return { value: entry, label: entry }\n }\n return null\n}\n\nfunction parseRangeValue(raw: string, fallback: unknown): unknown {\n try {\n const parsed = JSON.parse(raw)\n if (parsed && typeof parsed === 'object' && 'local' in parsed && parsed.local) {\n parsed.local = new Date(parsed.local)\n }\n return parsed\n } catch {\n return fallback ?? null\n }\n}\n\nexport function writeFilterParams(items: FilterItem[], vals: Record<string, unknown>) {\n for (const item of items) {\n if (item.type === 'separator') continue\n const v = vals[item.key]\n if (v === null || v === undefined || v === '') {\n removeUrlParam(item.key)\n } else if (item.type === 'date' || item.type === 'datetime') {\n setUrlParam(item.key, (v as { utc: string }).utc)\n } else if (item.type === 'dropdown') {\n // Store the full option object(s) so the label is preserved even when\n // the options list hasn't been loaded yet (e.g. lazy onInnerSearch).\n setUrlParam(item.key, JSON.stringify(normalizeDropdownValue(v)))\n } else if (typeof v === 'object') {\n setUrlParam(item.key, JSON.stringify(v))\n } else {\n setUrlParam(item.key, String(v))\n }\n }\n}\n\nfunction normalizeDropdownValue(\n v: unknown,\n options?: DropdownOption[],\n): DropdownOption | DropdownOption[] | null {\n if (v == null) return null\n const toOption = (entry: unknown): DropdownOption | null => {\n if (entry == null) return null\n if (typeof entry === 'object' && 'label' in (entry as object)) {\n return entry as DropdownOption\n }\n const value = String(entry)\n const label = options?.find((o) => o.value === value)?.label ?? value\n return { value, label }\n }\n if (Array.isArray(v)) {\n const opts = v.map(toOption).filter((o): o is DropdownOption => o !== null)\n return opts.length > 0 ? opts : null\n }\n const opt = toOption(v)\n return opt\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"admins-components87.js","names":[],"sources":["../src/utils/dataFilters.ts"],"sourcesContent":["import type { FilterItem } from '@/components/data-table/DataFilters.vue'\nimport type { SavedFilter } from '@/components/data-table/FiltersHistory.vue'\nimport type { DropdownOption } from '@/components/DropdownSelect.vue'\nimport { getFullStorageKey } from '@/utils/storageKey'\nimport { getUrlParam, setUrlParam, removeUrlParam } from '@/utils/url'\n\n export function getDefaultFilters(\n items: FilterItem[],\n storageKey?: string,\n useTransformers = true,\n): Record<string, unknown> {\n const urlFilters = getFilterUrlParams(items)\n const hasUrlParams = Object.keys(urlFilters).length > 0\n const defaultFilter = hasUrlParams ? null : getDefaultSavedFilter(storageKey)\n const defaultSavedValues = defaultFilter?.values ?? {}\n\n const result: Record<string, unknown> = {}\n\n for (const item of items) {\n if (item.type === 'separator') continue\n\n let value: unknown\n\n if (item.key in urlFilters) {\n value = urlFilters[item.key]\n } else if (hasUrlParams) {\n continue\n } else if (item.key in defaultSavedValues) {\n value = defaultSavedValues[item.key]\n } else if (item.value !== undefined) {\n value = item.value\n } else {\n continue\n }\n\n if (value == null) continue\n\n if (useTransformers && item.transformer) {\n const transformed = item.transformer(value)\n if (transformed) {\n Object.assign(result, transformed)\n }\n } else {\n result[item.key] = value\n }\n }\n\n return result\n}\n\n/**\n * Like `getDefaultFilters`, but for `dropdown` items returns plain\n * `string | string[]` values instead of the full `DropdownOption` object(s).\n *\n * Useful for consumers that just want to send the filter payload to an API\n * (e.g. `getDefaultFetchData` callers that prefer not to deal with option\n * objects on the wire).\n */\nexport function getDefaultFilterValues(\n items: FilterItem[],\n storageKey?: string,\n useTransformers = true,\n): Record<string, unknown> {\n const filters = getDefaultFilters(items, storageKey, useTransformers)\n const result: Record<string, unknown> = {}\n\n for (const item of items) {\n if (item.type !== 'dropdown') {\n if (item.key in filters) result[item.key] = filters[item.key]\n continue\n }\n\n const extracted = extractDropdownValues(filters[item.key])\n if (extracted != null) {\n result[item.key] = extracted\n }\n }\n\n return result\n}\n\n/**\n * Extracts plain value(s) from a dropdown filter value.\n * Accepts `DropdownOption | DropdownOption[] | string | string[] | null`\n * and returns `string | string[] | null`.\n */\nfunction extractDropdownValues(val: unknown): string | string[] | null {\n if (val == null) return null\n if (Array.isArray(val)) {\n const values = val\n .map((entry) => {\n if (entry == null) return null\n if (typeof entry === 'object' && 'value' in entry) {\n return (entry as { value?: string }).value ?? null\n }\n if (typeof entry === 'string') return entry\n return null\n })\n .filter((v): v is string => v !== null)\n return values.length > 0 ? values : null\n }\n if (typeof val === 'object' && 'value' in val) {\n return (val as { value?: string }).value ?? null\n }\n if (typeof val === 'string') return val\n return null\n}\n\nexport function getFilterUrlParams(items: FilterItem[]): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n\n for (const item of items) {\n if (item.type === 'separator') continue\n\n const raw = getUrlParam(item.key)\n if (raw) {\n result[item.key] = parseFilterValue(item.type, raw, item.value)\n }\n }\n return result\n}\n\nexport function getSavedFilters(storageKey?: string): SavedFilter[] {\n try {\n const fullStorageKey = getFullStorageKey('filters', storageKey)\n const parsed = JSON.parse(localStorage.getItem(fullStorageKey) ?? '[]')\n return Array.isArray(parsed)\n ? parsed.filter(\n (e) =>\n e &&\n typeof e === 'object' &&\n typeof e.id === 'string' &&\n e.values &&\n typeof e.savedAt === 'string',\n )\n : []\n } catch {\n return []\n }\n}\n\nexport function getDefaultSavedFilter(storageKey?: string): SavedFilter | null {\n const savedFilters = getSavedFilters(storageKey)\n return savedFilters.find((f) => f.isDefault) ?? null\n}\n\nexport function filterEmptyValues(filters: Record<string, any>): Record<string, any> {\n return Object.fromEntries(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n Object.entries(filters).filter(([_, val]) => val !== null && val !== '' && val !== undefined),\n )\n}\n\nfunction parseFilterValue(type: FilterItem['type'], raw: string, fallback: unknown): unknown {\n if (type === 'number') {\n const n = Number(raw)\n return isNaN(n) ? (fallback ?? null) : n\n }\n if (type === 'date' || type === 'datetime') {\n return { utc: raw }\n }\n if (type === 'daterange' || type === 'datetimerange') {\n return parseRangeValue(raw, fallback)\n }\n if (type === 'dropdown') {\n return parseDropdownStoredValue(raw)\n }\n if (type === 'checkbox') {\n return raw === 'true'\n }\n\n return raw\n}\n\nfunction parseDropdownStoredValue(raw: string): DropdownOption | DropdownOption[] | null {\n // Try to parse as JSON first (new format or legacy array)\n if (raw.startsWith('[') || raw.startsWith('{')) {\n try {\n const parsed = JSON.parse(raw)\n if (Array.isArray(parsed)) {\n const opts = parsed.map(toDropdownOption).filter((o): o is DropdownOption => o !== null)\n return opts.length > 0 ? opts : null\n }\n if (parsed && typeof parsed === 'object') {\n const opt = toDropdownOption(parsed)\n return opt\n }\n } catch {\n // fall through to legacy handling\n }\n }\n // Legacy: plain string value\n if (raw) return { value: raw, label: raw }\n return null\n}\n\nfunction toDropdownOption(entry: unknown): DropdownOption | null {\n if (entry == null) return null\n if (typeof entry === 'object' && 'label' in (entry as object)) {\n const obj = entry as DropdownOption\n if (obj.value != null && typeof obj.label === 'string') {\n return { value: obj.value, label: obj.label }\n }\n }\n if (typeof entry === 'string') {\n return { value: entry, label: entry }\n }\n return null\n}\n\nfunction parseRangeValue(raw: string, fallback: unknown): unknown {\n try {\n const parsed = JSON.parse(raw)\n if (parsed && typeof parsed === 'object' && 'local' in parsed && parsed.local) {\n parsed.local = new Date(parsed.local)\n }\n return parsed\n } catch {\n return fallback ?? null\n }\n}\n\nexport function writeFilterParams(items: FilterItem[], vals: Record<string, unknown>) {\n for (const item of items) {\n if (item.type === 'separator') continue\n const v = vals[item.key]\n if (v === null || v === undefined || v === '') {\n removeUrlParam(item.key)\n } else if (item.type === 'date' || item.type === 'datetime') {\n setUrlParam(item.key, (v as { utc: string }).utc)\n } else if (item.type === 'dropdown') {\n // Store the full option object(s) so the label is preserved even when\n // the options list hasn't been loaded yet (e.g. lazy onInnerSearch).\n setUrlParam(item.key, JSON.stringify(normalizeDropdownValue(v)))\n } else if (typeof v === 'object') {\n setUrlParam(item.key, JSON.stringify(v))\n } else {\n setUrlParam(item.key, String(v))\n }\n }\n}\n\nfunction normalizeDropdownValue(\n v: unknown,\n options?: DropdownOption[],\n): DropdownOption | DropdownOption[] | null {\n if (v == null) return null\n const toOption = (entry: unknown): DropdownOption | null => {\n if (entry == null) return null\n if (typeof entry === 'object' && 'label' in (entry as object)) {\n return entry as DropdownOption\n }\n const value = String(entry)\n const label = options?.find((o) => o.value === value)?.label ?? value\n return { value, label }\n }\n if (Array.isArray(v)) {\n const opts = v.map(toOption).filter((o): o is DropdownOption => o !== null)\n return opts.length > 0 ? opts : null\n }\n const opt = toOption(v)\n return opt\n}\n"],"mappings":"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"}
|