admins-components 9.0.76 → 9.0.78

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.
Files changed (57) hide show
  1. package/dist/admins-components100.js.map +1 -1
  2. package/dist/admins-components102.js.map +1 -1
  3. package/dist/admins-components103.js.map +1 -1
  4. package/dist/admins-components105.js.map +1 -1
  5. package/dist/admins-components109.js.map +1 -1
  6. package/dist/admins-components11.js.map +1 -1
  7. package/dist/admins-components112.js.map +1 -1
  8. package/dist/admins-components12.js +44 -29
  9. package/dist/admins-components12.js.map +1 -1
  10. package/dist/admins-components13.js.map +1 -1
  11. package/dist/admins-components14.js.map +1 -1
  12. package/dist/admins-components169.js.map +1 -1
  13. package/dist/admins-components173.js +2 -2
  14. package/dist/admins-components173.js.map +1 -1
  15. package/dist/admins-components174.js.map +1 -1
  16. package/dist/admins-components179.js.map +1 -1
  17. package/dist/admins-components21.js.map +1 -1
  18. package/dist/admins-components22.js.map +1 -1
  19. package/dist/admins-components26.js +88 -82
  20. package/dist/admins-components26.js.map +1 -1
  21. package/dist/admins-components28.js.map +1 -1
  22. package/dist/admins-components31.js.map +1 -1
  23. package/dist/admins-components35.js +25 -23
  24. package/dist/admins-components35.js.map +1 -1
  25. package/dist/admins-components37.js.map +1 -1
  26. package/dist/admins-components46.js.map +1 -1
  27. package/dist/admins-components48.js.map +1 -1
  28. package/dist/admins-components54.js.map +1 -1
  29. package/dist/admins-components56.js.map +1 -1
  30. package/dist/admins-components65.js.map +1 -1
  31. package/dist/admins-components68.js.map +1 -1
  32. package/dist/admins-components70.js.map +1 -1
  33. package/dist/admins-components75.js.map +1 -1
  34. package/dist/admins-components77.js.map +1 -1
  35. package/dist/admins-components79.js.map +1 -1
  36. package/dist/admins-components8.js.map +1 -1
  37. package/dist/admins-components80.js.map +1 -1
  38. package/dist/admins-components82.js.map +1 -1
  39. package/dist/admins-components83.js.map +1 -1
  40. package/dist/admins-components85.js.map +1 -1
  41. package/dist/admins-components86.js.map +1 -1
  42. package/dist/admins-components87.js.map +1 -1
  43. package/dist/admins-components91.js.map +1 -1
  44. package/dist/admins-components93.js.map +1 -1
  45. package/dist/main.css +1 -1
  46. package/dist/main.css.map +1 -1
  47. package/dist/src/components/HeaderComponent.vue.d.ts +3 -0
  48. package/dist/src/composables/useDropdownAnchor.d.ts +2 -0
  49. package/dist/src/composables/useSwipeToClose.d.ts +0 -31
  50. package/dist/src/utils/dataFilters.d.ts +0 -8
  51. package/dist/src/utils/dataListConverters.d.ts +0 -10
  52. package/dist/src/utils/url.d.ts +0 -11
  53. package/dist/styles/components/dropdown-select.scss_vue_type_style_index_0_src_true_lang.css +1 -1
  54. package/dist/styles/components/header.scss_vue_type_style_index_0_src_true_lang.css +1 -1
  55. package/dist/vueformelements/ArticlePickerElement.vue_vue_type_style_index_0_scoped_54217a66_lang.css +1 -0
  56. package/package.json +1 -1
  57. package/dist/vueformelements/ArticlePickerElement.vue_vue_type_style_index_0_scoped_43c54caa_lang.css +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"admins-components100.js","names":[],"sources":["../src/components/data-table/DataSearch.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface DataSearchProps {\n showExactMatch?: boolean\n showSearch?: boolean\n placeholder?: string\n handleUrl?: boolean\n searchKey?: string\n exactMatchKey?: string\n}\n\nexport interface DefaultSearch {\n search?: string\n exactMatch?: boolean | undefined\n}\n\nexport function getDefaultSearch(\n searchKey = 'search',\n exactMatchKey = 'exactMatch',\n): DefaultSearch {\n const params = new URLSearchParams(\n typeof window === 'undefined' ? '' : window.location.search,\n )\n const search = params.get(searchKey) ?? ''\n const exactRaw = params.get(exactMatchKey)\n const exactMatch = exactRaw === 'true' || exactRaw === '1'\n ? true\n : exactRaw === 'false' || exactRaw === '0'\n ? false\n : undefined\n return filterEmptyValues({ search, exactMatch })\n}\n</script>\n\n<script setup lang=\"ts\">\nimport Checkbox from '@/components/Checkbox.vue'\nimport TextInput from '@/components/TextInput.vue'\nimport { writeUrlOrRemove } from '@/utils/url'\nimport { debounce } from '@/utils/debounce'\nimport { onMounted, ref } from 'vue'\nimport { filterEmptyValues } from '@/utils/dataFilters'\n\nconst props = withDefaults(\n defineProps<DataSearchProps>(),\n {\n showExactMatch: true,\n showSearch: true,\n placeholder: 'Keresés...',\n handleUrl: false,\n searchKey: 'search',\n exactMatchKey: 'exactMatch',\n },\n)\n\ntype SearchFilterPayload = { [k: string]: string | boolean }\n\n// Seed refs from URL synchronously at setup so the input shows the URL value\n// on first render. URL is the only persistent source for search.\nconst initial = getDefaultSearch(props.searchKey, props.exactMatchKey)\nconst exactMatch = ref<boolean | undefined>(initial.exactMatch)\nconst search = ref<string>(initial.search ?? '')\n\nconst emit = defineEmits<{\n 'search-change': [filters: SearchFilterPayload]\n}>()\n\nfunction emitChange() {\n const filters: SearchFilterPayload = {}\n if (props.showSearch) filters[props.searchKey] = search.value\n if (props.showExactMatch) filters[props.exactMatchKey] = exactMatch.value ?? false\n emit('search-change', filters)\n}\n\nfunction syncToUrl() {\n writeUrlOrRemove(props.searchKey, search.value, { handleUrl: props.handleUrl })\n writeUrlOrRemove(props.exactMatchKey, exactMatch.value ?? false, {\n handleUrl: props.handleUrl,\n default: false,\n })\n}\n\nconst debouncedSyncToUrl = debounce(syncToUrl, 300)\n\nfunction onCheckboxChange(value: boolean | undefined) {\n exactMatch.value = value\n emitChange()\n debouncedSyncToUrl()\n}\n\nfunction onSearchChange(value: string | number | null) {\n search.value = value == null ? '' : String(value).trim()\n emitChange()\n debouncedSyncToUrl()\n}\n\nonMounted(() => {\n if (!props.handleUrl) return\n // If we had URL values at setup, push them up to the parent now.\n if (search.value || (exactMatch.value ?? false)) emitChange()\n})\n</script>\n<template>\n <div class=\"data-search-wrapper\">\n <Checkbox\n v-if=\"showExactMatch\"\n :model-value=\"exactMatch\"\n class=\"gap-1\"\n @update:model-value=\"onCheckboxChange\"\n >\n <template #label>\n <span class=\"data-search-label\">Pontos<br />egyezés </span>\n </template>\n </Checkbox>\n <TextInput\n v-if=\"showSearch\"\n type=\"text\"\n clearable\n :model-value=\"search\"\n inputClass=\"data-search-input\"\n label-on-border=\"Keresés\"\n :placeholder=\"placeholder\"\n :autocomplete=\"false\"\n @update:model-value=\"onSearchChange\"\n />\n </div>\n</template>\n<style lang=\"scss\" src=\"@/styles/components/data-table/data-search.scss\"></style>\n"],"mappings":";;;;;;;;AAeA,SAAgB,EACd,IAAY,UACZ,IAAgB,cACD;CACf,IAAM,IAAS,IAAI,gBACjB,OAAO,SAAW,MAAc,KAAK,OAAO,SAAS,MACvD,GACM,IAAS,EAAO,IAAI,CAAS,KAAK,IAClC,IAAW,EAAO,IAAI,CAAa;CAMzC,OAAO,EAAkB;EAAE;EAAQ,YALhB,MAAa,UAAU,MAAa,MACnD,KACA,MAAa,WAAW,MAAa,MACrC,KACA,KAAA;CAC0C,CAAC;AACjD;;;;;;;;;;;;;;;;;;;;;;EAWA,IAAM,IAAQ,GAgBR,IAAU,EAAiB,EAAM,WAAW,EAAM,aAAa,GAC/D,IAAa,EAAyB,EAAQ,UAAU,GACxD,IAAS,EAAY,EAAQ,UAAU,EAAE,GAEzC,IAAO;EAIb,SAAS,IAAa;GACpB,IAAM,IAA+B,CAAC;GAGtC,AAFI,EAAM,eAAY,EAAQ,EAAM,aAAa,EAAO,QACpD,EAAM,mBAAgB,EAAQ,EAAM,iBAAiB,EAAW,SAAS,KAC7E,EAAK,iBAAiB,CAAO;EAC/B;EAEA,SAAS,IAAY;GAEnB,AADA,EAAiB,EAAM,WAAW,EAAO,OAAO,EAAE,WAAW,EAAM,UAAU,CAAC,GAC9E,EAAiB,EAAM,eAAe,EAAW,SAAS,IAAO;IAC/D,WAAW,EAAM;IACjB,SAAS;GACX,CAAC;EACH;EAEA,IAAM,IAAqB,EAAS,GAAW,GAAG;EAElD,SAAS,EAAiB,GAA4B;GAGpD,AAFA,EAAW,QAAQ,GACnB,EAAW,GACX,EAAmB;EACrB;EAEA,SAAS,EAAe,GAA+B;GAGrD,AAFA,EAAO,QAAQ,KAAS,OAAO,KAAK,OAAO,CAAK,CAAC,CAAC,KAAK,GACvD,EAAW,GACX,EAAmB;EACrB;SAEA,QAAgB;GACT,EAAM,cAEP,EAAO,UAAU,EAAW,SAAS,QAAQ,EAAW;EAC9D,CAAC,cAGC,EAAA,GAAA,EAsBM,OAtBN,GAsBM,CApBI,EAAA,kBADR,EAAA,GAAA,EASW,GAAA;;GAPR,eAAa,EAAA;GACd,OAAM;GACL,uBAAoB;;GAEV,OAAK,QAC6C,CAAA,GAAA,AAAA,EAAA,OAAA,CAA3D,EAA2D,QAAA,EAArD,OAAM,oBAAmB,GAAA;IAAC,EAAA,QAAM;IAAA,EAAM,IAAA;IAAA,EAAA,UAAQ;;;EAIhD,GAAA,GAAA,CAAA,aAAA,CAAA,KAAA,EAAA,IAAA,EAAA,GAAA,EAAA,cADR,EAAA,GAAA,EAUE,GAAA;;GARA,MAAK;GACL,WAAA;GACC,eAAa,EAAA;GACd,YAAW;GACX,mBAAgB;GACf,aAAa,EAAA;GACb,cAAc;GACd,uBAAoB"}
1
+ {"version":3,"file":"admins-components100.js","names":[],"sources":["../src/components/data-table/DataSearch.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface DataSearchProps {\n showExactMatch?: boolean\n showSearch?: boolean\n placeholder?: string\n handleUrl?: boolean\n searchKey?: string\n exactMatchKey?: string\n}\n\nexport interface DefaultSearch {\n search?: string\n exactMatch?: boolean | undefined\n}\n\nexport function getDefaultSearch(\n searchKey = 'search',\n exactMatchKey = 'exactMatch',\n): DefaultSearch {\n const params = new URLSearchParams(\n typeof window === 'undefined' ? '' : window.location.search,\n )\n const search = params.get(searchKey) ?? ''\n const exactRaw = params.get(exactMatchKey)\n const exactMatch = exactRaw === 'true' || exactRaw === '1'\n ? true\n : exactRaw === 'false' || exactRaw === '0'\n ? false\n : undefined\n return filterEmptyValues({ search, exactMatch })\n}\n</script>\n\n<script setup lang=\"ts\">\nimport Checkbox from '@/components/Checkbox.vue'\nimport TextInput from '@/components/TextInput.vue'\nimport { writeUrlOrRemove } from '@/utils/url'\nimport { debounce } from '@/utils/debounce'\nimport { onMounted, ref } from 'vue'\nimport { filterEmptyValues } from '@/utils/dataFilters'\n\nconst props = withDefaults(\n defineProps<DataSearchProps>(),\n {\n showExactMatch: true,\n showSearch: true,\n placeholder: 'Keresés...',\n handleUrl: false,\n searchKey: 'search',\n exactMatchKey: 'exactMatch',\n },\n)\n\ntype SearchFilterPayload = { [k: string]: string | boolean }\n\nconst initial = getDefaultSearch(props.searchKey, props.exactMatchKey)\nconst exactMatch = ref<boolean | undefined>(initial.exactMatch)\nconst search = ref<string>(initial.search ?? '')\n\nconst emit = defineEmits<{\n 'search-change': [filters: SearchFilterPayload]\n}>()\n\nfunction emitChange() {\n const filters: SearchFilterPayload = {}\n if (props.showSearch) filters[props.searchKey] = search.value\n if (props.showExactMatch) filters[props.exactMatchKey] = exactMatch.value ?? false\n emit('search-change', filters)\n}\n\nfunction syncToUrl() {\n writeUrlOrRemove(props.searchKey, search.value, { handleUrl: props.handleUrl })\n writeUrlOrRemove(props.exactMatchKey, exactMatch.value ?? false, {\n handleUrl: props.handleUrl,\n default: false,\n })\n}\n\nconst debouncedSyncToUrl = debounce(syncToUrl, 300)\n\nfunction onCheckboxChange(value: boolean | undefined) {\n exactMatch.value = value\n emitChange()\n debouncedSyncToUrl()\n}\n\nfunction onSearchChange(value: string | number | null) {\n search.value = value == null ? '' : String(value).trim()\n emitChange()\n debouncedSyncToUrl()\n}\n\nonMounted(() => {\n if (!props.handleUrl) return\n\n if (search.value || (exactMatch.value ?? false)) emitChange()\n})\n</script>\n<template>\n <div class=\"data-search-wrapper\">\n <Checkbox\n v-if=\"showExactMatch\"\n :model-value=\"exactMatch\"\n class=\"gap-1\"\n @update:model-value=\"onCheckboxChange\"\n >\n <template #label>\n <span class=\"data-search-label\">Pontos<br />egyezés </span>\n </template>\n </Checkbox>\n <TextInput\n v-if=\"showSearch\"\n type=\"text\"\n clearable\n :model-value=\"search\"\n inputClass=\"data-search-input\"\n label-on-border=\"Keresés\"\n :placeholder=\"placeholder\"\n :autocomplete=\"false\"\n @update:model-value=\"onSearchChange\"\n />\n </div>\n</template>\n<style lang=\"scss\" src=\"@/styles/components/data-table/data-search.scss\"></style>\n"],"mappings":";;;;;;;;AAeA,SAAgB,EACd,IAAY,UACZ,IAAgB,cACD;CACf,IAAM,IAAS,IAAI,gBACjB,OAAO,SAAW,MAAc,KAAK,OAAO,SAAS,MACvD,GACM,IAAS,EAAO,IAAI,CAAS,KAAK,IAClC,IAAW,EAAO,IAAI,CAAa;CAMzC,OAAO,EAAkB;EAAE;EAAQ,YALhB,MAAa,UAAU,MAAa,MACnD,KACA,MAAa,WAAW,MAAa,MACrC,KACA,KAAA;CAC0C,CAAC;AACjD;;;;;;;;;;;;;;;;;;;;;;EAWA,IAAM,IAAQ,GAcR,IAAU,EAAiB,EAAM,WAAW,EAAM,aAAa,GAC/D,IAAa,EAAyB,EAAQ,UAAU,GACxD,IAAS,EAAY,EAAQ,UAAU,EAAE,GAEzC,IAAO;EAIb,SAAS,IAAa;GACpB,IAAM,IAA+B,CAAC;GAGtC,AAFI,EAAM,eAAY,EAAQ,EAAM,aAAa,EAAO,QACpD,EAAM,mBAAgB,EAAQ,EAAM,iBAAiB,EAAW,SAAS,KAC7E,EAAK,iBAAiB,CAAO;EAC/B;EAEA,SAAS,IAAY;GAEnB,AADA,EAAiB,EAAM,WAAW,EAAO,OAAO,EAAE,WAAW,EAAM,UAAU,CAAC,GAC9E,EAAiB,EAAM,eAAe,EAAW,SAAS,IAAO;IAC/D,WAAW,EAAM;IACjB,SAAS;GACX,CAAC;EACH;EAEA,IAAM,IAAqB,EAAS,GAAW,GAAG;EAElD,SAAS,EAAiB,GAA4B;GAGpD,AAFA,EAAW,QAAQ,GACnB,EAAW,GACX,EAAmB;EACrB;EAEA,SAAS,EAAe,GAA+B;GAGrD,AAFA,EAAO,QAAQ,KAAS,OAAO,KAAK,OAAO,CAAK,CAAC,CAAC,KAAK,GACvD,EAAW,GACX,EAAmB;EACrB;SAEA,QAAgB;GACT,EAAM,cAEP,EAAO,UAAU,EAAW,SAAS,QAAQ,EAAW;EAC9D,CAAC,cAGC,EAAA,GAAA,EAsBM,OAtBN,GAsBM,CApBI,EAAA,kBADR,EAAA,GAAA,EASW,GAAA;;GAPR,eAAa,EAAA;GACd,OAAM;GACL,uBAAoB;;GAEV,OAAK,QAC6C,CAAA,GAAA,AAAA,EAAA,OAAA,CAA3D,EAA2D,QAAA,EAArD,OAAM,oBAAmB,GAAA;IAAC,EAAA,QAAM;IAAA,EAAM,IAAA;IAAA,EAAA,UAAQ;;;EAIhD,GAAA,GAAA,CAAA,aAAA,CAAA,KAAA,EAAA,IAAA,EAAA,GAAA,EAAA,cADR,EAAA,GAAA,EAUE,GAAA;;GARA,MAAK;GACL,WAAA;GACC,eAAa,EAAA;GACd,YAAW;GACX,mBAAgB;GACf,aAAa,EAAA;GACb,cAAc;GACd,uBAAoB"}
@@ -1 +1 @@
1
- {"version":3,"file":"admins-components102.js","names":[],"sources":["../src/components/data-table/DataSearch.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface DataSearchProps {\n showExactMatch?: boolean\n showSearch?: boolean\n placeholder?: string\n handleUrl?: boolean\n searchKey?: string\n exactMatchKey?: string\n}\n\nexport interface DefaultSearch {\n search?: string\n exactMatch?: boolean | undefined\n}\n\nexport function getDefaultSearch(\n searchKey = 'search',\n exactMatchKey = 'exactMatch',\n): DefaultSearch {\n const params = new URLSearchParams(\n typeof window === 'undefined' ? '' : window.location.search,\n )\n const search = params.get(searchKey) ?? ''\n const exactRaw = params.get(exactMatchKey)\n const exactMatch = exactRaw === 'true' || exactRaw === '1'\n ? true\n : exactRaw === 'false' || exactRaw === '0'\n ? false\n : undefined\n return filterEmptyValues({ search, exactMatch })\n}\n</script>\n\n<script setup lang=\"ts\">\nimport Checkbox from '@/components/Checkbox.vue'\nimport TextInput from '@/components/TextInput.vue'\nimport { writeUrlOrRemove } from '@/utils/url'\nimport { debounce } from '@/utils/debounce'\nimport { onMounted, ref } from 'vue'\nimport { filterEmptyValues } from '@/utils/dataFilters'\n\nconst props = withDefaults(\n defineProps<DataSearchProps>(),\n {\n showExactMatch: true,\n showSearch: true,\n placeholder: 'Keresés...',\n handleUrl: false,\n searchKey: 'search',\n exactMatchKey: 'exactMatch',\n },\n)\n\ntype SearchFilterPayload = { [k: string]: string | boolean }\n\n// Seed refs from URL synchronously at setup so the input shows the URL value\n// on first render. URL is the only persistent source for search.\nconst initial = getDefaultSearch(props.searchKey, props.exactMatchKey)\nconst exactMatch = ref<boolean | undefined>(initial.exactMatch)\nconst search = ref<string>(initial.search ?? '')\n\nconst emit = defineEmits<{\n 'search-change': [filters: SearchFilterPayload]\n}>()\n\nfunction emitChange() {\n const filters: SearchFilterPayload = {}\n if (props.showSearch) filters[props.searchKey] = search.value\n if (props.showExactMatch) filters[props.exactMatchKey] = exactMatch.value ?? false\n emit('search-change', filters)\n}\n\nfunction syncToUrl() {\n writeUrlOrRemove(props.searchKey, search.value, { handleUrl: props.handleUrl })\n writeUrlOrRemove(props.exactMatchKey, exactMatch.value ?? false, {\n handleUrl: props.handleUrl,\n default: false,\n })\n}\n\nconst debouncedSyncToUrl = debounce(syncToUrl, 300)\n\nfunction onCheckboxChange(value: boolean | undefined) {\n exactMatch.value = value\n emitChange()\n debouncedSyncToUrl()\n}\n\nfunction onSearchChange(value: string | number | null) {\n search.value = value == null ? '' : String(value).trim()\n emitChange()\n debouncedSyncToUrl()\n}\n\nonMounted(() => {\n if (!props.handleUrl) return\n // If we had URL values at setup, push them up to the parent now.\n if (search.value || (exactMatch.value ?? false)) emitChange()\n})\n</script>\n<template>\n <div class=\"data-search-wrapper\">\n <Checkbox\n v-if=\"showExactMatch\"\n :model-value=\"exactMatch\"\n class=\"gap-1\"\n @update:model-value=\"onCheckboxChange\"\n >\n <template #label>\n <span class=\"data-search-label\">Pontos<br />egyezés </span>\n </template>\n </Checkbox>\n <TextInput\n v-if=\"showSearch\"\n type=\"text\"\n clearable\n :model-value=\"search\"\n inputClass=\"data-search-input\"\n label-on-border=\"Keresés\"\n :placeholder=\"placeholder\"\n :autocomplete=\"false\"\n @update:model-value=\"onSearchChange\"\n />\n </div>\n</template>\n<style lang=\"scss\" src=\"@/styles/components/data-table/data-search.scss\"></style>\n"],"mappings":""}
1
+ {"version":3,"file":"admins-components102.js","names":[],"sources":["../src/components/data-table/DataSearch.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface DataSearchProps {\n showExactMatch?: boolean\n showSearch?: boolean\n placeholder?: string\n handleUrl?: boolean\n searchKey?: string\n exactMatchKey?: string\n}\n\nexport interface DefaultSearch {\n search?: string\n exactMatch?: boolean | undefined\n}\n\nexport function getDefaultSearch(\n searchKey = 'search',\n exactMatchKey = 'exactMatch',\n): DefaultSearch {\n const params = new URLSearchParams(\n typeof window === 'undefined' ? '' : window.location.search,\n )\n const search = params.get(searchKey) ?? ''\n const exactRaw = params.get(exactMatchKey)\n const exactMatch = exactRaw === 'true' || exactRaw === '1'\n ? true\n : exactRaw === 'false' || exactRaw === '0'\n ? false\n : undefined\n return filterEmptyValues({ search, exactMatch })\n}\n</script>\n\n<script setup lang=\"ts\">\nimport Checkbox from '@/components/Checkbox.vue'\nimport TextInput from '@/components/TextInput.vue'\nimport { writeUrlOrRemove } from '@/utils/url'\nimport { debounce } from '@/utils/debounce'\nimport { onMounted, ref } from 'vue'\nimport { filterEmptyValues } from '@/utils/dataFilters'\n\nconst props = withDefaults(\n defineProps<DataSearchProps>(),\n {\n showExactMatch: true,\n showSearch: true,\n placeholder: 'Keresés...',\n handleUrl: false,\n searchKey: 'search',\n exactMatchKey: 'exactMatch',\n },\n)\n\ntype SearchFilterPayload = { [k: string]: string | boolean }\n\nconst initial = getDefaultSearch(props.searchKey, props.exactMatchKey)\nconst exactMatch = ref<boolean | undefined>(initial.exactMatch)\nconst search = ref<string>(initial.search ?? '')\n\nconst emit = defineEmits<{\n 'search-change': [filters: SearchFilterPayload]\n}>()\n\nfunction emitChange() {\n const filters: SearchFilterPayload = {}\n if (props.showSearch) filters[props.searchKey] = search.value\n if (props.showExactMatch) filters[props.exactMatchKey] = exactMatch.value ?? false\n emit('search-change', filters)\n}\n\nfunction syncToUrl() {\n writeUrlOrRemove(props.searchKey, search.value, { handleUrl: props.handleUrl })\n writeUrlOrRemove(props.exactMatchKey, exactMatch.value ?? false, {\n handleUrl: props.handleUrl,\n default: false,\n })\n}\n\nconst debouncedSyncToUrl = debounce(syncToUrl, 300)\n\nfunction onCheckboxChange(value: boolean | undefined) {\n exactMatch.value = value\n emitChange()\n debouncedSyncToUrl()\n}\n\nfunction onSearchChange(value: string | number | null) {\n search.value = value == null ? '' : String(value).trim()\n emitChange()\n debouncedSyncToUrl()\n}\n\nonMounted(() => {\n if (!props.handleUrl) return\n\n if (search.value || (exactMatch.value ?? false)) emitChange()\n})\n</script>\n<template>\n <div class=\"data-search-wrapper\">\n <Checkbox\n v-if=\"showExactMatch\"\n :model-value=\"exactMatch\"\n class=\"gap-1\"\n @update:model-value=\"onCheckboxChange\"\n >\n <template #label>\n <span class=\"data-search-label\">Pontos<br />egyezés </span>\n </template>\n </Checkbox>\n <TextInput\n v-if=\"showSearch\"\n type=\"text\"\n clearable\n :model-value=\"search\"\n inputClass=\"data-search-input\"\n label-on-border=\"Keresés\"\n :placeholder=\"placeholder\"\n :autocomplete=\"false\"\n @update:model-value=\"onSearchChange\"\n />\n </div>\n</template>\n<style lang=\"scss\" src=\"@/styles/components/data-table/data-search.scss\"></style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"admins-components103.js","names":[],"sources":["../src/components/data-table/DataList.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type { PaginatorSettings } from '@/types/data-list'\nexport type { DataSearchProps } from './DataSearch.vue'\nexport type { DataFiltersProps } from './DataFilters.vue'\n\nexport interface DataListProps {\n config: DataListConfig\n items: Record<string, unknown>[]\n settings?: Partial<DataListSettings>\n id: string\n layoutBreakpoint?: number\n orderable?: boolean\n pagination?: PaginatorSettings\n loading?: boolean\n handleUrl?: boolean\n useSearch?: boolean\n useFilters?: boolean\n searchConfig?: DataSearchProps\n filterConfig?: DataFiltersProps\n fillHeight?: boolean\n}\n\nexport const dataListDefaults = {\n layoutBreakpoint: 768,\n orderable: true,\n loading: false,\n useSearch: true,\n useFilters: true,\n handleUrl: false,\n fillHeight: false,\n}\n\nexport function getDefaultFetchData(filters: FilterItem[], storageKey: string) {\n const defaultPaginator = getDefaultPaginator(storageKey)\n const defaultSort = getDefaultSort()\n const defaultSearch = getDefaultSearch()\n const defaultFilters = getDefaultFilterValues(filters, storageKey, true)\n\n return {\n ...defaultPaginator,\n ...defaultSort,\n ...defaultSearch,\n ...defaultFilters,\n }\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onBeforeUnmount, useSlots } from 'vue'\nimport DataTable from '@/components/data-table/DataTable.vue'\nimport DataCards from '@/components/data-table/DataCards.vue'\nimport DataListOptions from '@/components/data-table/DataListOptions.vue'\nimport DataPaginator, { getDefaultPaginator } from '@/components/data-table/DataPaginator.vue'\nimport Button from '@/components/Button.vue'\nimport DataSort, { getDefaultSort, type DataSortOption } from '@/components/data-table/DataSort.vue'\nimport type {\n DataListConfig,\n DataListSettings,\n PageSettings,\n PaginatorSettings,\n} from '@/types/data-list'\nimport type { FilterValue } from '@/types/data-list'\nimport DataFilters, {\n type FilterResponse,\n type DataFiltersProps,\n type FilterItem,\n} from '@/components/data-table/DataFilters.vue'\nimport FilterTags from '@/components/data-table/FilterTags.vue'\nimport DataListGuide from '@/components/data-table/DataListGuide.vue'\nimport DataSearch, { getDefaultSearch, type DataSearchProps } from './DataSearch.vue'\nimport { getDefaultFilters, getDefaultFilterValues } from '@/utils/dataFilters.ts'\n\nconst dataFiltersRef = ref<InstanceType<typeof DataFilters> | null>(null)\nconst slots = useSlots()\nconst hasActionsSlot = computed(() => !!slots.actions)\n\nconst props = withDefaults(defineProps<DataListProps>(), {\n ...dataListDefaults,\n searchConfig: undefined,\n filterConfig: undefined,\n})\n\nfunction resolvedHandleUrl(side: 'searchConfig' | 'filterConfig'): boolean | undefined {\n const sideConfig = props[side]\n if (sideConfig && Object.hasOwn(sideConfig as object, 'handleUrl')) {\n return (sideConfig as { handleUrl?: boolean }).handleUrl\n }\n return props.handleUrl\n}\n\nconst mergedSearchConfig = computed<DataSearchProps>(() => ({\n ...props.searchConfig,\n handleUrl: resolvedHandleUrl('searchConfig'),\n}))\n\nconst mergedFilterConfig = computed<DataFiltersProps>(() => ({\n ...(props.filterConfig as DataFiltersProps),\n handleUrl: resolvedHandleUrl('filterConfig'),\n}))\n\nconst emit = defineEmits<{\n 'filter-change': [filters: Record<string, FilterValue>]\n 'selection-change': [selected: unknown[]]\n 'settings-change': [settings: DataListSettings]\n 'pagination-change': [pagination: PageSettings]\n 'sort-change': [sort: { key: string; direction: 'asc' | 'desc' } | null]\n 'search-change': [filters: Record<string, string | boolean>]\n}>()\n\nconst showOptions = ref(false)\nconst showGuide = ref(false)\nconst resolvedSettings = ref<DataListSettings | null>(null)\nconst isMobile = ref(false)\nconst root = ref<HTMLElement | null>(null)\nconst showFilters = ref(false)\n\nconst activeFilters = ref<Record<string, unknown>>(\n props.filterConfig?.items ? getDefaultFilters(props.filterConfig.items, props.id, false) : {},\n)\nlet resizeObserver: ResizeObserver | null = null\n\nonMounted(() => {\n resizeObserver = new ResizeObserver((entries) => {\n isMobile.value = (entries[0]?.contentRect.width ?? 0) < props.layoutBreakpoint\n })\n if (root.value) resizeObserver.observe(root.value)\n})\n\nonBeforeUnmount(() => resizeObserver?.disconnect())\n\nconst effectiveLayout = computed<'table' | 'cards'>(() => {\n const layout = resolvedSettings.value?.layout\n if (layout === 'table' || layout === 'cards') return layout\n return isMobile.value ? 'cards' : 'table'\n})\n\nconst internalConfig = computed<DataListConfig>(() => {\n if (!resolvedSettings.value) return props.config\n const order = resolvedSettings.value.columnOrder\n const mapped = props.config.columns.map((c) => ({\n ...c,\n visible: resolvedSettings.value!.columns[c.property] ?? c.visible !== false,\n }))\n if (order?.length) {\n mapped.sort((a, b) => {\n const ai = order.indexOf(a.property)\n const bi = order.indexOf(b.property)\n return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi)\n })\n }\n return { ...props.config, columns: mapped }\n})\n\nfunction onSettingsChange(s: DataListSettings) {\n resolvedSettings.value = s\n emit('settings-change', s)\n}\n\ndefineExpose({\n openOptions: () => (showOptions.value = true),\n closeOptions: () => (showOptions.value = false),\n openFilters: () => (showFilters.value = true),\n closeFilters: () => (showFilters.value = false),\n})\n\nasync function openFilter(key: string) {\n showFilters.value = true\n setTimeout(() => {\n dataFiltersRef.value?.focusFilter(key)\n }, 300)\n}\n\nfunction onFilterChange(response: FilterResponse) {\n activeFilters.value = response.values\n emit('filter-change', response.transformed)\n}\n\nconst activeFiltersCount = computed(\n () => Object.values(activeFilters.value).filter((v) => v != null && v !== '').length,\n)\n\nconst showPaginator = computed(\n () => !!props.pagination && (props.items.length > 0 || !props.loading),\n)\n\nconst searchChange = (value: Record<string, string | boolean>) => {\n emit('search-change', value)\n}\n\nconst sortableColumns = computed<DataSortOption[]>(() =>\n props.config.columns.filter((c) => c.sort).map((c) => ({ value: c.property, label: c.label })),\n)\n\nconst currentSort = ref<{ key: string; direction: 'asc' | 'desc' } | null>(\n props.handleUrl ? getDefaultSort() : null,\n)\n\nconst onSortChange = (sort: { key: string; direction: 'asc' | 'desc' } | null) => {\n currentSort.value = sort\n // DataSort already writes the URL when handleUrl: true; we only emit.\n emit('sort-change', sort)\n}\n</script>\n\n<template>\n <div\n ref=\"root\"\n class=\"ac-component c-data-list\"\n :class=\"{ 'c-data-list--fill-height': fillHeight }\"\n >\n <div class=\"c-data-list__toolbar\">\n <DataSearch v-if=\"useSearch\" v-bind=\"mergedSearchConfig\" @search-change=\"searchChange\" />\n <Button\n v-if=\"useFilters && filterConfig?.items && filterConfig.items.length > 0\"\n label=\"Szűrők\"\n icon=\"fa-solid fa-filter\"\n @click=\"showFilters = true\"\n style=\"flex-shrink: 0\"\n :type=\"activeFiltersCount > 0 ? 'primary' : 'normal'\"\n :indicator=\"activeFiltersCount > 0 ? activeFiltersCount : undefined\"\n />\n <div\n class=\"flex-center gap-1 flex-center-wrap-on-mobile\"\n v-if=\"useFilters && filterConfig?.items && filterConfig.items.length > 0\"\n >\n <FilterTags\n :filters=\"activeFilters\"\n :items=\"filterConfig.items\"\n compact\n @remove=\"(key: string) => dataFiltersRef?.clearFilter(key)\"\n @openFilter=\"openFilter\"\n />\n </div>\n <div class=\"c-data-list__toolbar__right\">\n <DataSort\n v-if=\"sortableColumns.length > 0\"\n v-model=\"currentSort\"\n :options=\"sortableColumns\"\n :handle-url=\"handleUrl\"\n @sort-change=\"onSortChange\"\n />\n\n <Button\n icon=\"fa-solid fa-gear\"\n class=\"lh-normal settings-btn\"\n ariaLabel=\"Beállítások\"\n @click=\"showOptions = true\"\n />\n <Button\n icon=\"fa-solid fa-question\"\n class=\"lh-normal\"\n @click=\"showGuide = true\"\n ariaLabel=\"Súgó\"\n />\n </div>\n </div>\n <DataFilters\n ref=\"dataFiltersRef\"\n v-if=\"useFilters && filterConfig?.items && filterConfig.items.length > 0\"\n v-bind=\"mergedFilterConfig\"\n :storage-key=\"id\"\n :open=\"showFilters\"\n @close=\"showFilters = false\"\n @change=\"onFilterChange\"\n />\n <DataListGuide :open=\"showGuide\" @close=\"showGuide = false\" />\n <DataTable\n v-if=\"effectiveLayout === 'table'\"\n :config=\"internalConfig\"\n :loading=\"loading\"\n :items=\"items\"\n :settings=\"resolvedSettings ?? undefined\"\n :initial-sort=\"currentSort\"\n @filter-change=\"emit('filter-change', $event)\"\n @selection-change=\"emit('selection-change', $event)\"\n @sort-change=\"onSortChange\"\n >\n <template\n v-for=\"col in internalConfig.columns\"\n :key=\"col.property\"\n #[`cell:${col.property}`]=\"slotProps\"\n >\n <slot :name=\"`cell:${col.property}`\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"hasActionsSlot\" #actions=\"slotProps\">\n <slot name=\"actions\" v-bind=\"slotProps\" />\n </template>\n </DataTable>\n\n <DataCards\n v-else\n :config=\"internalConfig\"\n :loading=\"loading\"\n :items=\"items\"\n :settings=\"resolvedSettings ?? undefined\"\n @selection-change=\"emit('selection-change', $event)\"\n >\n <template\n v-for=\"col in internalConfig.columns\"\n :key=\"col.property\"\n #[`cell:${col.property}`]=\"slotProps\"\n >\n <slot :name=\"`cell:${col.property}`\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"hasActionsSlot\" #actions=\"slotProps\">\n <slot name=\"actions\" v-bind=\"slotProps\" />\n </template>\n </DataCards>\n\n <DataPaginator\n v-if=\"pagination && showPaginator\"\n :settings=\"pagination\"\n :storage-key=\"id\"\n :handle-url=\"handleUrl\"\n @update:pagination=\"emit('pagination-change', $event)\"\n />\n\n <DataListOptions\n :open=\"showOptions\"\n :columns=\"config.columns\"\n :settings=\"settings ?? {}\"\n :storage-key=\"id\"\n :orderable=\"orderable\"\n @close=\"showOptions = false\"\n @change=\"onSettingsChange\"\n />\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/data-table/data-list.scss\"></style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"admins-components103.js","names":[],"sources":["../src/components/data-table/DataList.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type { PaginatorSettings } from '@/types/data-list'\nexport type { DataSearchProps } from './DataSearch.vue'\nexport type { DataFiltersProps } from './DataFilters.vue'\n\nexport interface DataListProps {\n config: DataListConfig\n items: Record<string, unknown>[]\n settings?: Partial<DataListSettings>\n id: string\n layoutBreakpoint?: number\n orderable?: boolean\n pagination?: PaginatorSettings\n loading?: boolean\n handleUrl?: boolean\n useSearch?: boolean\n useFilters?: boolean\n searchConfig?: DataSearchProps\n filterConfig?: DataFiltersProps\n fillHeight?: boolean\n}\n\nexport const dataListDefaults = {\n layoutBreakpoint: 768,\n orderable: true,\n loading: false,\n useSearch: true,\n useFilters: true,\n handleUrl: false,\n fillHeight: false,\n}\n\nexport function getDefaultFetchData(filters: FilterItem[], storageKey: string) {\n const defaultPaginator = getDefaultPaginator(storageKey)\n const defaultSort = getDefaultSort()\n const defaultSearch = getDefaultSearch()\n const defaultFilters = getDefaultFilterValues(filters, storageKey, true)\n\n return {\n ...defaultPaginator,\n ...defaultSort,\n ...defaultSearch,\n ...defaultFilters,\n }\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onBeforeUnmount, useSlots } from 'vue'\nimport DataTable from '@/components/data-table/DataTable.vue'\nimport DataCards from '@/components/data-table/DataCards.vue'\nimport DataListOptions from '@/components/data-table/DataListOptions.vue'\nimport DataPaginator, { getDefaultPaginator } from '@/components/data-table/DataPaginator.vue'\nimport Button from '@/components/Button.vue'\nimport DataSort, { getDefaultSort, type DataSortOption } from '@/components/data-table/DataSort.vue'\nimport type {\n DataListConfig,\n DataListSettings,\n PageSettings,\n PaginatorSettings,\n} from '@/types/data-list'\nimport type { FilterValue } from '@/types/data-list'\nimport DataFilters, {\n type FilterResponse,\n type DataFiltersProps,\n type FilterItem,\n} from '@/components/data-table/DataFilters.vue'\nimport FilterTags from '@/components/data-table/FilterTags.vue'\nimport DataListGuide from '@/components/data-table/DataListGuide.vue'\nimport DataSearch, { getDefaultSearch, type DataSearchProps } from './DataSearch.vue'\nimport { getDefaultFilters, getDefaultFilterValues } from '@/utils/dataFilters.ts'\n\nconst dataFiltersRef = ref<InstanceType<typeof DataFilters> | null>(null)\nconst slots = useSlots()\nconst hasActionsSlot = computed(() => !!slots.actions)\n\nconst props = withDefaults(defineProps<DataListProps>(), {\n ...dataListDefaults,\n searchConfig: undefined,\n filterConfig: undefined,\n})\n\nfunction resolvedHandleUrl(side: 'searchConfig' | 'filterConfig'): boolean | undefined {\n const sideConfig = props[side]\n if (sideConfig && Object.hasOwn(sideConfig as object, 'handleUrl')) {\n return (sideConfig as { handleUrl?: boolean }).handleUrl\n }\n return props.handleUrl\n}\n\nconst mergedSearchConfig = computed<DataSearchProps>(() => ({\n ...props.searchConfig,\n handleUrl: resolvedHandleUrl('searchConfig'),\n}))\n\nconst mergedFilterConfig = computed<DataFiltersProps>(() => ({\n ...(props.filterConfig as DataFiltersProps),\n handleUrl: resolvedHandleUrl('filterConfig'),\n}))\n\nconst emit = defineEmits<{\n 'filter-change': [filters: Record<string, FilterValue>]\n 'selection-change': [selected: unknown[]]\n 'settings-change': [settings: DataListSettings]\n 'pagination-change': [pagination: PageSettings]\n 'sort-change': [sort: { key: string; direction: 'asc' | 'desc' } | null]\n 'search-change': [filters: Record<string, string | boolean>]\n}>()\n\nconst showOptions = ref(false)\nconst showGuide = ref(false)\nconst resolvedSettings = ref<DataListSettings | null>(null)\nconst isMobile = ref(false)\nconst root = ref<HTMLElement | null>(null)\nconst showFilters = ref(false)\n\nconst activeFilters = ref<Record<string, unknown>>(\n props.filterConfig?.items ? getDefaultFilters(props.filterConfig.items, props.id, false) : {},\n)\nlet resizeObserver: ResizeObserver | null = null\n\nonMounted(() => {\n resizeObserver = new ResizeObserver((entries) => {\n isMobile.value = (entries[0]?.contentRect.width ?? 0) < props.layoutBreakpoint\n })\n if (root.value) resizeObserver.observe(root.value)\n})\n\nonBeforeUnmount(() => resizeObserver?.disconnect())\n\nconst effectiveLayout = computed<'table' | 'cards'>(() => {\n const layout = resolvedSettings.value?.layout\n if (layout === 'table' || layout === 'cards') return layout\n return isMobile.value ? 'cards' : 'table'\n})\n\nconst internalConfig = computed<DataListConfig>(() => {\n if (!resolvedSettings.value) return props.config\n const order = resolvedSettings.value.columnOrder\n const mapped = props.config.columns.map((c) => ({\n ...c,\n visible: resolvedSettings.value!.columns[c.property] ?? c.visible !== false,\n }))\n if (order?.length) {\n mapped.sort((a, b) => {\n const ai = order.indexOf(a.property)\n const bi = order.indexOf(b.property)\n return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi)\n })\n }\n return { ...props.config, columns: mapped }\n})\n\nfunction onSettingsChange(s: DataListSettings) {\n resolvedSettings.value = s\n emit('settings-change', s)\n}\n\ndefineExpose({\n openOptions: () => (showOptions.value = true),\n closeOptions: () => (showOptions.value = false),\n openFilters: () => (showFilters.value = true),\n closeFilters: () => (showFilters.value = false),\n})\n\nasync function openFilter(key: string) {\n showFilters.value = true\n setTimeout(() => {\n dataFiltersRef.value?.focusFilter(key)\n }, 300)\n}\n\nfunction onFilterChange(response: FilterResponse) {\n activeFilters.value = response.values\n emit('filter-change', response.transformed)\n}\n\nconst activeFiltersCount = computed(\n () => Object.values(activeFilters.value).filter((v) => v != null && v !== '').length,\n)\n\nconst showPaginator = computed(\n () => !!props.pagination && (props.items.length > 0 || !props.loading),\n)\n\nconst searchChange = (value: Record<string, string | boolean>) => {\n emit('search-change', value)\n}\n\nconst sortableColumns = computed<DataSortOption[]>(() =>\n props.config.columns.filter((c) => c.sort).map((c) => ({ value: c.property, label: c.label })),\n)\n\nconst currentSort = ref<{ key: string; direction: 'asc' | 'desc' } | null>(\n props.handleUrl ? getDefaultSort() : null,\n)\n\nconst onSortChange = (sort: { key: string; direction: 'asc' | 'desc' } | null) => {\n currentSort.value = sort\n emit('sort-change', sort)\n}\n</script>\n\n<template>\n <div\n ref=\"root\"\n class=\"ac-component c-data-list\"\n :class=\"{ 'c-data-list--fill-height': fillHeight }\"\n >\n <div class=\"c-data-list__toolbar\">\n <DataSearch v-if=\"useSearch\" v-bind=\"mergedSearchConfig\" @search-change=\"searchChange\" />\n <Button\n v-if=\"useFilters && filterConfig?.items && filterConfig.items.length > 0\"\n label=\"Szűrők\"\n icon=\"fa-solid fa-filter\"\n @click=\"showFilters = true\"\n style=\"flex-shrink: 0\"\n :type=\"activeFiltersCount > 0 ? 'primary' : 'normal'\"\n :indicator=\"activeFiltersCount > 0 ? activeFiltersCount : undefined\"\n />\n <div\n class=\"flex-center gap-1 flex-center-wrap-on-mobile\"\n v-if=\"useFilters && filterConfig?.items && filterConfig.items.length > 0\"\n >\n <FilterTags\n :filters=\"activeFilters\"\n :items=\"filterConfig.items\"\n compact\n @remove=\"(key: string) => dataFiltersRef?.clearFilter(key)\"\n @openFilter=\"openFilter\"\n />\n </div>\n <div class=\"c-data-list__toolbar__right\">\n <DataSort\n v-if=\"sortableColumns.length > 0\"\n v-model=\"currentSort\"\n :options=\"sortableColumns\"\n :handle-url=\"handleUrl\"\n @sort-change=\"onSortChange\"\n />\n\n <Button\n icon=\"fa-solid fa-gear\"\n class=\"lh-normal settings-btn\"\n ariaLabel=\"Beállítások\"\n @click=\"showOptions = true\"\n />\n <Button\n icon=\"fa-solid fa-question\"\n class=\"lh-normal\"\n @click=\"showGuide = true\"\n ariaLabel=\"Súgó\"\n />\n </div>\n </div>\n <DataFilters\n ref=\"dataFiltersRef\"\n v-if=\"useFilters && filterConfig?.items && filterConfig.items.length > 0\"\n v-bind=\"mergedFilterConfig\"\n :storage-key=\"id\"\n :open=\"showFilters\"\n @close=\"showFilters = false\"\n @change=\"onFilterChange\"\n />\n <DataListGuide :open=\"showGuide\" @close=\"showGuide = false\" />\n <DataTable\n v-if=\"effectiveLayout === 'table'\"\n :config=\"internalConfig\"\n :loading=\"loading\"\n :items=\"items\"\n :settings=\"resolvedSettings ?? undefined\"\n :initial-sort=\"currentSort\"\n @filter-change=\"emit('filter-change', $event)\"\n @selection-change=\"emit('selection-change', $event)\"\n @sort-change=\"onSortChange\"\n >\n <template\n v-for=\"col in internalConfig.columns\"\n :key=\"col.property\"\n #[`cell:${col.property}`]=\"slotProps\"\n >\n <slot :name=\"`cell:${col.property}`\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"hasActionsSlot\" #actions=\"slotProps\">\n <slot name=\"actions\" v-bind=\"slotProps\" />\n </template>\n </DataTable>\n\n <DataCards\n v-else\n :config=\"internalConfig\"\n :loading=\"loading\"\n :items=\"items\"\n :settings=\"resolvedSettings ?? undefined\"\n @selection-change=\"emit('selection-change', $event)\"\n >\n <template\n v-for=\"col in internalConfig.columns\"\n :key=\"col.property\"\n #[`cell:${col.property}`]=\"slotProps\"\n >\n <slot :name=\"`cell:${col.property}`\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"hasActionsSlot\" #actions=\"slotProps\">\n <slot name=\"actions\" v-bind=\"slotProps\" />\n </template>\n </DataCards>\n\n <DataPaginator\n v-if=\"pagination && showPaginator\"\n :settings=\"pagination\"\n :storage-key=\"id\"\n :handle-url=\"handleUrl\"\n @update:pagination=\"emit('pagination-change', $event)\"\n />\n\n <DataListOptions\n :open=\"showOptions\"\n :columns=\"config.columns\"\n :settings=\"settings ?? {}\"\n :storage-key=\"id\"\n :orderable=\"orderable\"\n @close=\"showOptions = false\"\n @change=\"onSettingsChange\"\n />\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/data-table/data-list.scss\"></style>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"admins-components105.js","names":[],"sources":["../src/components/data-table/DataList.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type { PaginatorSettings } from '@/types/data-list'\nexport type { DataSearchProps } from './DataSearch.vue'\nexport type { DataFiltersProps } from './DataFilters.vue'\n\nexport interface DataListProps {\n config: DataListConfig\n items: Record<string, unknown>[]\n settings?: Partial<DataListSettings>\n id: string\n layoutBreakpoint?: number\n orderable?: boolean\n pagination?: PaginatorSettings\n loading?: boolean\n handleUrl?: boolean\n useSearch?: boolean\n useFilters?: boolean\n searchConfig?: DataSearchProps\n filterConfig?: DataFiltersProps\n fillHeight?: boolean\n}\n\nexport const dataListDefaults = {\n layoutBreakpoint: 768,\n orderable: true,\n loading: false,\n useSearch: true,\n useFilters: true,\n handleUrl: false,\n fillHeight: false,\n}\n\nexport function getDefaultFetchData(filters: FilterItem[], storageKey: string) {\n const defaultPaginator = getDefaultPaginator(storageKey)\n const defaultSort = getDefaultSort()\n const defaultSearch = getDefaultSearch()\n const defaultFilters = getDefaultFilterValues(filters, storageKey, true)\n\n return {\n ...defaultPaginator,\n ...defaultSort,\n ...defaultSearch,\n ...defaultFilters,\n }\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onBeforeUnmount, useSlots } from 'vue'\nimport DataTable from '@/components/data-table/DataTable.vue'\nimport DataCards from '@/components/data-table/DataCards.vue'\nimport DataListOptions from '@/components/data-table/DataListOptions.vue'\nimport DataPaginator, { getDefaultPaginator } from '@/components/data-table/DataPaginator.vue'\nimport Button from '@/components/Button.vue'\nimport DataSort, { getDefaultSort, type DataSortOption } from '@/components/data-table/DataSort.vue'\nimport type {\n DataListConfig,\n DataListSettings,\n PageSettings,\n PaginatorSettings,\n} from '@/types/data-list'\nimport type { FilterValue } from '@/types/data-list'\nimport DataFilters, {\n type FilterResponse,\n type DataFiltersProps,\n type FilterItem,\n} from '@/components/data-table/DataFilters.vue'\nimport FilterTags from '@/components/data-table/FilterTags.vue'\nimport DataListGuide from '@/components/data-table/DataListGuide.vue'\nimport DataSearch, { getDefaultSearch, type DataSearchProps } from './DataSearch.vue'\nimport { getDefaultFilters, getDefaultFilterValues } from '@/utils/dataFilters.ts'\n\nconst dataFiltersRef = ref<InstanceType<typeof DataFilters> | null>(null)\nconst slots = useSlots()\nconst hasActionsSlot = computed(() => !!slots.actions)\n\nconst props = withDefaults(defineProps<DataListProps>(), {\n ...dataListDefaults,\n searchConfig: undefined,\n filterConfig: undefined,\n})\n\nfunction resolvedHandleUrl(side: 'searchConfig' | 'filterConfig'): boolean | undefined {\n const sideConfig = props[side]\n if (sideConfig && Object.hasOwn(sideConfig as object, 'handleUrl')) {\n return (sideConfig as { handleUrl?: boolean }).handleUrl\n }\n return props.handleUrl\n}\n\nconst mergedSearchConfig = computed<DataSearchProps>(() => ({\n ...props.searchConfig,\n handleUrl: resolvedHandleUrl('searchConfig'),\n}))\n\nconst mergedFilterConfig = computed<DataFiltersProps>(() => ({\n ...(props.filterConfig as DataFiltersProps),\n handleUrl: resolvedHandleUrl('filterConfig'),\n}))\n\nconst emit = defineEmits<{\n 'filter-change': [filters: Record<string, FilterValue>]\n 'selection-change': [selected: unknown[]]\n 'settings-change': [settings: DataListSettings]\n 'pagination-change': [pagination: PageSettings]\n 'sort-change': [sort: { key: string; direction: 'asc' | 'desc' } | null]\n 'search-change': [filters: Record<string, string | boolean>]\n}>()\n\nconst showOptions = ref(false)\nconst showGuide = ref(false)\nconst resolvedSettings = ref<DataListSettings | null>(null)\nconst isMobile = ref(false)\nconst root = ref<HTMLElement | null>(null)\nconst showFilters = ref(false)\n\nconst activeFilters = ref<Record<string, unknown>>(\n props.filterConfig?.items ? getDefaultFilters(props.filterConfig.items, props.id, false) : {},\n)\nlet resizeObserver: ResizeObserver | null = null\n\nonMounted(() => {\n resizeObserver = new ResizeObserver((entries) => {\n isMobile.value = (entries[0]?.contentRect.width ?? 0) < props.layoutBreakpoint\n })\n if (root.value) resizeObserver.observe(root.value)\n})\n\nonBeforeUnmount(() => resizeObserver?.disconnect())\n\nconst effectiveLayout = computed<'table' | 'cards'>(() => {\n const layout = resolvedSettings.value?.layout\n if (layout === 'table' || layout === 'cards') return layout\n return isMobile.value ? 'cards' : 'table'\n})\n\nconst internalConfig = computed<DataListConfig>(() => {\n if (!resolvedSettings.value) return props.config\n const order = resolvedSettings.value.columnOrder\n const mapped = props.config.columns.map((c) => ({\n ...c,\n visible: resolvedSettings.value!.columns[c.property] ?? c.visible !== false,\n }))\n if (order?.length) {\n mapped.sort((a, b) => {\n const ai = order.indexOf(a.property)\n const bi = order.indexOf(b.property)\n return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi)\n })\n }\n return { ...props.config, columns: mapped }\n})\n\nfunction onSettingsChange(s: DataListSettings) {\n resolvedSettings.value = s\n emit('settings-change', s)\n}\n\ndefineExpose({\n openOptions: () => (showOptions.value = true),\n closeOptions: () => (showOptions.value = false),\n openFilters: () => (showFilters.value = true),\n closeFilters: () => (showFilters.value = false),\n})\n\nasync function openFilter(key: string) {\n showFilters.value = true\n setTimeout(() => {\n dataFiltersRef.value?.focusFilter(key)\n }, 300)\n}\n\nfunction onFilterChange(response: FilterResponse) {\n activeFilters.value = response.values\n emit('filter-change', response.transformed)\n}\n\nconst activeFiltersCount = computed(\n () => Object.values(activeFilters.value).filter((v) => v != null && v !== '').length,\n)\n\nconst showPaginator = computed(\n () => !!props.pagination && (props.items.length > 0 || !props.loading),\n)\n\nconst searchChange = (value: Record<string, string | boolean>) => {\n emit('search-change', value)\n}\n\nconst sortableColumns = computed<DataSortOption[]>(() =>\n props.config.columns.filter((c) => c.sort).map((c) => ({ value: c.property, label: c.label })),\n)\n\nconst currentSort = ref<{ key: string; direction: 'asc' | 'desc' } | null>(\n props.handleUrl ? getDefaultSort() : null,\n)\n\nconst onSortChange = (sort: { key: string; direction: 'asc' | 'desc' } | null) => {\n currentSort.value = sort\n // DataSort already writes the URL when handleUrl: true; we only emit.\n emit('sort-change', sort)\n}\n</script>\n\n<template>\n <div\n ref=\"root\"\n class=\"ac-component c-data-list\"\n :class=\"{ 'c-data-list--fill-height': fillHeight }\"\n >\n <div class=\"c-data-list__toolbar\">\n <DataSearch v-if=\"useSearch\" v-bind=\"mergedSearchConfig\" @search-change=\"searchChange\" />\n <Button\n v-if=\"useFilters && filterConfig?.items && filterConfig.items.length > 0\"\n label=\"Szűrők\"\n icon=\"fa-solid fa-filter\"\n @click=\"showFilters = true\"\n style=\"flex-shrink: 0\"\n :type=\"activeFiltersCount > 0 ? 'primary' : 'normal'\"\n :indicator=\"activeFiltersCount > 0 ? activeFiltersCount : undefined\"\n />\n <div\n class=\"flex-center gap-1 flex-center-wrap-on-mobile\"\n v-if=\"useFilters && filterConfig?.items && filterConfig.items.length > 0\"\n >\n <FilterTags\n :filters=\"activeFilters\"\n :items=\"filterConfig.items\"\n compact\n @remove=\"(key: string) => dataFiltersRef?.clearFilter(key)\"\n @openFilter=\"openFilter\"\n />\n </div>\n <div class=\"c-data-list__toolbar__right\">\n <DataSort\n v-if=\"sortableColumns.length > 0\"\n v-model=\"currentSort\"\n :options=\"sortableColumns\"\n :handle-url=\"handleUrl\"\n @sort-change=\"onSortChange\"\n />\n\n <Button\n icon=\"fa-solid fa-gear\"\n class=\"lh-normal settings-btn\"\n ariaLabel=\"Beállítások\"\n @click=\"showOptions = true\"\n />\n <Button\n icon=\"fa-solid fa-question\"\n class=\"lh-normal\"\n @click=\"showGuide = true\"\n ariaLabel=\"Súgó\"\n />\n </div>\n </div>\n <DataFilters\n ref=\"dataFiltersRef\"\n v-if=\"useFilters && filterConfig?.items && filterConfig.items.length > 0\"\n v-bind=\"mergedFilterConfig\"\n :storage-key=\"id\"\n :open=\"showFilters\"\n @close=\"showFilters = false\"\n @change=\"onFilterChange\"\n />\n <DataListGuide :open=\"showGuide\" @close=\"showGuide = false\" />\n <DataTable\n v-if=\"effectiveLayout === 'table'\"\n :config=\"internalConfig\"\n :loading=\"loading\"\n :items=\"items\"\n :settings=\"resolvedSettings ?? undefined\"\n :initial-sort=\"currentSort\"\n @filter-change=\"emit('filter-change', $event)\"\n @selection-change=\"emit('selection-change', $event)\"\n @sort-change=\"onSortChange\"\n >\n <template\n v-for=\"col in internalConfig.columns\"\n :key=\"col.property\"\n #[`cell:${col.property}`]=\"slotProps\"\n >\n <slot :name=\"`cell:${col.property}`\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"hasActionsSlot\" #actions=\"slotProps\">\n <slot name=\"actions\" v-bind=\"slotProps\" />\n </template>\n </DataTable>\n\n <DataCards\n v-else\n :config=\"internalConfig\"\n :loading=\"loading\"\n :items=\"items\"\n :settings=\"resolvedSettings ?? undefined\"\n @selection-change=\"emit('selection-change', $event)\"\n >\n <template\n v-for=\"col in internalConfig.columns\"\n :key=\"col.property\"\n #[`cell:${col.property}`]=\"slotProps\"\n >\n <slot :name=\"`cell:${col.property}`\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"hasActionsSlot\" #actions=\"slotProps\">\n <slot name=\"actions\" v-bind=\"slotProps\" />\n </template>\n </DataCards>\n\n <DataPaginator\n v-if=\"pagination && showPaginator\"\n :settings=\"pagination\"\n :storage-key=\"id\"\n :handle-url=\"handleUrl\"\n @update:pagination=\"emit('pagination-change', $event)\"\n />\n\n <DataListOptions\n :open=\"showOptions\"\n :columns=\"config.columns\"\n :settings=\"settings ?? {}\"\n :storage-key=\"id\"\n :orderable=\"orderable\"\n @close=\"showOptions = false\"\n @change=\"onSettingsChange\"\n />\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/data-table/data-list.scss\"></style>\n"],"mappings":""}
1
+ {"version":3,"file":"admins-components105.js","names":[],"sources":["../src/components/data-table/DataList.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type { PaginatorSettings } from '@/types/data-list'\nexport type { DataSearchProps } from './DataSearch.vue'\nexport type { DataFiltersProps } from './DataFilters.vue'\n\nexport interface DataListProps {\n config: DataListConfig\n items: Record<string, unknown>[]\n settings?: Partial<DataListSettings>\n id: string\n layoutBreakpoint?: number\n orderable?: boolean\n pagination?: PaginatorSettings\n loading?: boolean\n handleUrl?: boolean\n useSearch?: boolean\n useFilters?: boolean\n searchConfig?: DataSearchProps\n filterConfig?: DataFiltersProps\n fillHeight?: boolean\n}\n\nexport const dataListDefaults = {\n layoutBreakpoint: 768,\n orderable: true,\n loading: false,\n useSearch: true,\n useFilters: true,\n handleUrl: false,\n fillHeight: false,\n}\n\nexport function getDefaultFetchData(filters: FilterItem[], storageKey: string) {\n const defaultPaginator = getDefaultPaginator(storageKey)\n const defaultSort = getDefaultSort()\n const defaultSearch = getDefaultSearch()\n const defaultFilters = getDefaultFilterValues(filters, storageKey, true)\n\n return {\n ...defaultPaginator,\n ...defaultSort,\n ...defaultSearch,\n ...defaultFilters,\n }\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onBeforeUnmount, useSlots } from 'vue'\nimport DataTable from '@/components/data-table/DataTable.vue'\nimport DataCards from '@/components/data-table/DataCards.vue'\nimport DataListOptions from '@/components/data-table/DataListOptions.vue'\nimport DataPaginator, { getDefaultPaginator } from '@/components/data-table/DataPaginator.vue'\nimport Button from '@/components/Button.vue'\nimport DataSort, { getDefaultSort, type DataSortOption } from '@/components/data-table/DataSort.vue'\nimport type {\n DataListConfig,\n DataListSettings,\n PageSettings,\n PaginatorSettings,\n} from '@/types/data-list'\nimport type { FilterValue } from '@/types/data-list'\nimport DataFilters, {\n type FilterResponse,\n type DataFiltersProps,\n type FilterItem,\n} from '@/components/data-table/DataFilters.vue'\nimport FilterTags from '@/components/data-table/FilterTags.vue'\nimport DataListGuide from '@/components/data-table/DataListGuide.vue'\nimport DataSearch, { getDefaultSearch, type DataSearchProps } from './DataSearch.vue'\nimport { getDefaultFilters, getDefaultFilterValues } from '@/utils/dataFilters.ts'\n\nconst dataFiltersRef = ref<InstanceType<typeof DataFilters> | null>(null)\nconst slots = useSlots()\nconst hasActionsSlot = computed(() => !!slots.actions)\n\nconst props = withDefaults(defineProps<DataListProps>(), {\n ...dataListDefaults,\n searchConfig: undefined,\n filterConfig: undefined,\n})\n\nfunction resolvedHandleUrl(side: 'searchConfig' | 'filterConfig'): boolean | undefined {\n const sideConfig = props[side]\n if (sideConfig && Object.hasOwn(sideConfig as object, 'handleUrl')) {\n return (sideConfig as { handleUrl?: boolean }).handleUrl\n }\n return props.handleUrl\n}\n\nconst mergedSearchConfig = computed<DataSearchProps>(() => ({\n ...props.searchConfig,\n handleUrl: resolvedHandleUrl('searchConfig'),\n}))\n\nconst mergedFilterConfig = computed<DataFiltersProps>(() => ({\n ...(props.filterConfig as DataFiltersProps),\n handleUrl: resolvedHandleUrl('filterConfig'),\n}))\n\nconst emit = defineEmits<{\n 'filter-change': [filters: Record<string, FilterValue>]\n 'selection-change': [selected: unknown[]]\n 'settings-change': [settings: DataListSettings]\n 'pagination-change': [pagination: PageSettings]\n 'sort-change': [sort: { key: string; direction: 'asc' | 'desc' } | null]\n 'search-change': [filters: Record<string, string | boolean>]\n}>()\n\nconst showOptions = ref(false)\nconst showGuide = ref(false)\nconst resolvedSettings = ref<DataListSettings | null>(null)\nconst isMobile = ref(false)\nconst root = ref<HTMLElement | null>(null)\nconst showFilters = ref(false)\n\nconst activeFilters = ref<Record<string, unknown>>(\n props.filterConfig?.items ? getDefaultFilters(props.filterConfig.items, props.id, false) : {},\n)\nlet resizeObserver: ResizeObserver | null = null\n\nonMounted(() => {\n resizeObserver = new ResizeObserver((entries) => {\n isMobile.value = (entries[0]?.contentRect.width ?? 0) < props.layoutBreakpoint\n })\n if (root.value) resizeObserver.observe(root.value)\n})\n\nonBeforeUnmount(() => resizeObserver?.disconnect())\n\nconst effectiveLayout = computed<'table' | 'cards'>(() => {\n const layout = resolvedSettings.value?.layout\n if (layout === 'table' || layout === 'cards') return layout\n return isMobile.value ? 'cards' : 'table'\n})\n\nconst internalConfig = computed<DataListConfig>(() => {\n if (!resolvedSettings.value) return props.config\n const order = resolvedSettings.value.columnOrder\n const mapped = props.config.columns.map((c) => ({\n ...c,\n visible: resolvedSettings.value!.columns[c.property] ?? c.visible !== false,\n }))\n if (order?.length) {\n mapped.sort((a, b) => {\n const ai = order.indexOf(a.property)\n const bi = order.indexOf(b.property)\n return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi)\n })\n }\n return { ...props.config, columns: mapped }\n})\n\nfunction onSettingsChange(s: DataListSettings) {\n resolvedSettings.value = s\n emit('settings-change', s)\n}\n\ndefineExpose({\n openOptions: () => (showOptions.value = true),\n closeOptions: () => (showOptions.value = false),\n openFilters: () => (showFilters.value = true),\n closeFilters: () => (showFilters.value = false),\n})\n\nasync function openFilter(key: string) {\n showFilters.value = true\n setTimeout(() => {\n dataFiltersRef.value?.focusFilter(key)\n }, 300)\n}\n\nfunction onFilterChange(response: FilterResponse) {\n activeFilters.value = response.values\n emit('filter-change', response.transformed)\n}\n\nconst activeFiltersCount = computed(\n () => Object.values(activeFilters.value).filter((v) => v != null && v !== '').length,\n)\n\nconst showPaginator = computed(\n () => !!props.pagination && (props.items.length > 0 || !props.loading),\n)\n\nconst searchChange = (value: Record<string, string | boolean>) => {\n emit('search-change', value)\n}\n\nconst sortableColumns = computed<DataSortOption[]>(() =>\n props.config.columns.filter((c) => c.sort).map((c) => ({ value: c.property, label: c.label })),\n)\n\nconst currentSort = ref<{ key: string; direction: 'asc' | 'desc' } | null>(\n props.handleUrl ? getDefaultSort() : null,\n)\n\nconst onSortChange = (sort: { key: string; direction: 'asc' | 'desc' } | null) => {\n currentSort.value = sort\n emit('sort-change', sort)\n}\n</script>\n\n<template>\n <div\n ref=\"root\"\n class=\"ac-component c-data-list\"\n :class=\"{ 'c-data-list--fill-height': fillHeight }\"\n >\n <div class=\"c-data-list__toolbar\">\n <DataSearch v-if=\"useSearch\" v-bind=\"mergedSearchConfig\" @search-change=\"searchChange\" />\n <Button\n v-if=\"useFilters && filterConfig?.items && filterConfig.items.length > 0\"\n label=\"Szűrők\"\n icon=\"fa-solid fa-filter\"\n @click=\"showFilters = true\"\n style=\"flex-shrink: 0\"\n :type=\"activeFiltersCount > 0 ? 'primary' : 'normal'\"\n :indicator=\"activeFiltersCount > 0 ? activeFiltersCount : undefined\"\n />\n <div\n class=\"flex-center gap-1 flex-center-wrap-on-mobile\"\n v-if=\"useFilters && filterConfig?.items && filterConfig.items.length > 0\"\n >\n <FilterTags\n :filters=\"activeFilters\"\n :items=\"filterConfig.items\"\n compact\n @remove=\"(key: string) => dataFiltersRef?.clearFilter(key)\"\n @openFilter=\"openFilter\"\n />\n </div>\n <div class=\"c-data-list__toolbar__right\">\n <DataSort\n v-if=\"sortableColumns.length > 0\"\n v-model=\"currentSort\"\n :options=\"sortableColumns\"\n :handle-url=\"handleUrl\"\n @sort-change=\"onSortChange\"\n />\n\n <Button\n icon=\"fa-solid fa-gear\"\n class=\"lh-normal settings-btn\"\n ariaLabel=\"Beállítások\"\n @click=\"showOptions = true\"\n />\n <Button\n icon=\"fa-solid fa-question\"\n class=\"lh-normal\"\n @click=\"showGuide = true\"\n ariaLabel=\"Súgó\"\n />\n </div>\n </div>\n <DataFilters\n ref=\"dataFiltersRef\"\n v-if=\"useFilters && filterConfig?.items && filterConfig.items.length > 0\"\n v-bind=\"mergedFilterConfig\"\n :storage-key=\"id\"\n :open=\"showFilters\"\n @close=\"showFilters = false\"\n @change=\"onFilterChange\"\n />\n <DataListGuide :open=\"showGuide\" @close=\"showGuide = false\" />\n <DataTable\n v-if=\"effectiveLayout === 'table'\"\n :config=\"internalConfig\"\n :loading=\"loading\"\n :items=\"items\"\n :settings=\"resolvedSettings ?? undefined\"\n :initial-sort=\"currentSort\"\n @filter-change=\"emit('filter-change', $event)\"\n @selection-change=\"emit('selection-change', $event)\"\n @sort-change=\"onSortChange\"\n >\n <template\n v-for=\"col in internalConfig.columns\"\n :key=\"col.property\"\n #[`cell:${col.property}`]=\"slotProps\"\n >\n <slot :name=\"`cell:${col.property}`\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"hasActionsSlot\" #actions=\"slotProps\">\n <slot name=\"actions\" v-bind=\"slotProps\" />\n </template>\n </DataTable>\n\n <DataCards\n v-else\n :config=\"internalConfig\"\n :loading=\"loading\"\n :items=\"items\"\n :settings=\"resolvedSettings ?? undefined\"\n @selection-change=\"emit('selection-change', $event)\"\n >\n <template\n v-for=\"col in internalConfig.columns\"\n :key=\"col.property\"\n #[`cell:${col.property}`]=\"slotProps\"\n >\n <slot :name=\"`cell:${col.property}`\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"hasActionsSlot\" #actions=\"slotProps\">\n <slot name=\"actions\" v-bind=\"slotProps\" />\n </template>\n </DataCards>\n\n <DataPaginator\n v-if=\"pagination && showPaginator\"\n :settings=\"pagination\"\n :storage-key=\"id\"\n :handle-url=\"handleUrl\"\n @update:pagination=\"emit('pagination-change', $event)\"\n />\n\n <DataListOptions\n :open=\"showOptions\"\n :columns=\"config.columns\"\n :settings=\"settings ?? {}\"\n :storage-key=\"id\"\n :orderable=\"orderable\"\n @close=\"showOptions = false\"\n @change=\"onSettingsChange\"\n />\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/data-table/data-list.scss\"></style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"admins-components109.js","names":[],"sources":["../src/services/createNativeFetch.ts"],"sourcesContent":["/* VueUse helyett */\nimport { ref, type Ref } from 'vue'\nimport { joinUrl } from '@/utils/url'\n\nexport type NativeUseFetchReturn<T = unknown> = {\n data: Ref<T | null>\n error: Ref<any>\n response: Ref<Response | null>\n statusCode: Ref<number | null>\n isFetching: Ref<boolean>\n canAbort: Ref<boolean>\n\n get: () => NativeUseFetchReturn<T>\n post: (payload?: unknown) => NativeUseFetchReturn<T>\n put: (payload?: unknown) => NativeUseFetchReturn<T>\n patch: (payload?: unknown) => NativeUseFetchReturn<T>\n delete: (payload?: unknown) => NativeUseFetchReturn<T>\n\n json: <R = T>() => NativeUseFetchReturn<R>\n text: () => NativeUseFetchReturn<string>\n\n execute: () => Promise<NativeUseFetchReturn<T>>\n abort: () => void\n}\n\nexport type CreateFetchOptions = {\n baseUrl: string\n fetchOptions?: RequestInit\n options?: {\n immediate?: boolean\n beforeFetch?: (ctx: { url: string; options: RequestInit }) => any\n afterFetch?: (ctx: { data: unknown; response: Response }) => any\n onFetchError?: (ctx: { error: any; response: Response | null; data: unknown }) => any\n }\n}\n\nexport function createNativeFetch(config: CreateFetchOptions) {\n return function useNativeFetch<T = unknown>(url: string): NativeUseFetchReturn<T> {\n const data = ref<T | null>(null) as Ref<T | null>\n const error = ref<any>(null)\n const response = ref<Response | null>(null)\n const statusCode = ref<number | null>(null)\n const isFetching = ref(false)\n const canAbort = ref(false)\n\n let method = 'GET'\n let payload: unknown = undefined\n let parser: 'json' | 'text' = 'json'\n let controller: AbortController | null = null\n\n const instance: NativeUseFetchReturn<T> = {\n data,\n error,\n response,\n statusCode,\n isFetching,\n canAbort,\n\n get() {\n method = 'GET'\n return instance\n },\n\n post(p?: unknown) {\n method = 'POST'\n payload = p\n return instance\n },\n\n put(p?: unknown) {\n method = 'PUT'\n payload = p\n return instance\n },\n\n patch(p?: unknown) {\n method = 'PATCH'\n payload = p\n return instance\n },\n\n delete(p?: unknown) {\n method = 'DELETE'\n payload = p\n return instance\n },\n\n json<R = T>() {\n parser = 'json'\n return instance as unknown as NativeUseFetchReturn<R>\n },\n\n text() {\n parser = 'text'\n return instance as unknown as NativeUseFetchReturn<string>\n },\n\n abort() {\n controller?.abort()\n },\n\n async execute() {\n controller = new AbortController()\n\n isFetching.value = true\n canAbort.value = true\n error.value = null\n response.value = null\n statusCode.value = null\n\n const requestOptions: RequestInit = {\n ...config.fetchOptions,\n method,\n signal: controller.signal,\n }\n\n if (payload !== undefined && payload !== null && method !== 'GET') {\n requestOptions.body = isRefLike(payload)\n ? JSON.stringify(payload.value)\n : JSON.stringify(payload)\n }\n\n const ctx = {\n url: joinUrl(config.baseUrl, url),\n options: requestOptions,\n }\n\n try {\n config.options?.beforeFetch?.(ctx)\n\n const res = await fetch(ctx.url, ctx.options)\n\n response.value = res\n statusCode.value = res.status\n\n let parsedData: unknown = null\n\n if (parser === 'text') {\n parsedData = await res.text()\n } else {\n const text = await res.text()\n parsedData = text ? JSON.parse(text) : null\n }\n\n data.value = parsedData as T\n\n if (!res.ok) {\n throw new Error(res.statusText || `HTTP ${res.status}`)\n }\n\n config.options?.afterFetch?.({\n data: parsedData,\n response: res,\n })\n } catch (e: any) {\n error.value = e\n\n config.options?.onFetchError?.({\n error: e,\n response: response.value,\n data: data.value,\n })\n } finally {\n isFetching.value = false\n canAbort.value = false\n controller = null\n }\n\n return instance\n },\n } satisfies NativeUseFetchReturn<T>\n\n if (config.options?.immediate !== false) {\n instance.execute()\n }\n\n return instance\n }\n}\n\nfunction isRefLike(value: unknown): value is Ref<unknown> {\n return !!value && typeof value === 'object' && 'value' in value\n}\n"],"mappings":";;;AAoCA,SAAgB,EAAkB,GAA4B;CAC5D,OAAO,SAAqC,GAAsC;EAChF,IAAM,IAAO,EAAc,IAAI,GACzB,IAAQ,EAAS,IAAI,GACrB,IAAW,EAAqB,IAAI,GACpC,IAAa,EAAmB,IAAI,GACpC,IAAa,EAAI,EAAK,GACtB,IAAW,EAAI,EAAK,GAEtB,IAAS,OACT,GACA,IAA0B,QAC1B,IAAqC,MAEnC,IAAoC;GACxC;GACA;GACA;GACA;GACA;GACA;GAEA,MAAM;IAEJ,OADA,IAAS,OACF;GACT;GAEA,KAAK,GAAa;IAGhB,OAFA,IAAS,QACT,IAAU,GACH;GACT;GAEA,IAAI,GAAa;IAGf,OAFA,IAAS,OACT,IAAU,GACH;GACT;GAEA,MAAM,GAAa;IAGjB,OAFA,IAAS,SACT,IAAU,GACH;GACT;GAEA,OAAO,GAAa;IAGlB,OAFA,IAAS,UACT,IAAU,GACH;GACT;GAEA,OAAc;IAEZ,OADA,IAAS,QACF;GACT;GAEA,OAAO;IAEL,OADA,IAAS,QACF;GACT;GAEA,QAAQ;IACN,GAAY,MAAM;GACpB;GAEA,MAAM,UAAU;IAOd,AANA,IAAa,IAAI,gBAAgB,GAEjC,EAAW,QAAQ,IACnB,EAAS,QAAQ,IACjB,EAAM,QAAQ,MACd,EAAS,QAAQ,MACjB,EAAW,QAAQ;IAEnB,IAAM,IAA8B;KAClC,GAAG,EAAO;KACV;KACA,QAAQ,EAAW;IACrB;IAEA,AAAI,KAAqC,QAAQ,MAAW,UAC1D,EAAe,OAAO,EAAU,CAAO,IACnC,KAAK,UAAU,EAAQ,KAAK,IAC5B,KAAK,UAAU,CAAO;IAG5B,IAAM,IAAM;KACV,KAAK,EAAQ,EAAO,SAAS,CAAG;KAChC,SAAS;IACX;IAEA,IAAI;KACF,EAAO,SAAS,cAAc,CAAG;KAEjC,IAAM,IAAM,MAAM,MAAM,EAAI,KAAK,EAAI,OAAO;KAG5C,AADA,EAAS,QAAQ,GACjB,EAAW,QAAQ,EAAI;KAEvB,IAAI,IAAsB;KAE1B,IAAI,MAAW,QACb,IAAa,MAAM,EAAI,KAAK;UACvB;MACL,IAAM,IAAO,MAAM,EAAI,KAAK;MAC5B,IAAa,IAAO,KAAK,MAAM,CAAI,IAAI;KACzC;KAIA,IAFA,EAAK,QAAQ,GAET,CAAC,EAAI,IACP,MAAU,MAAM,EAAI,cAAc,QAAQ,EAAI,QAAQ;KAGxD,EAAO,SAAS,aAAa;MAC3B,MAAM;MACN,UAAU;KACZ,CAAC;IACH,SAAS,GAAQ;KAGf,AAFA,EAAM,QAAQ,GAEd,EAAO,SAAS,eAAe;MAC7B,OAAO;MACP,UAAU,EAAS;MACnB,MAAM,EAAK;KACb,CAAC;IACH,UAAU;KAGR,AAFA,EAAW,QAAQ,IACnB,EAAS,QAAQ,IACjB,IAAa;IACf;IAEA,OAAO;GACT;EACF;EAMA,OAJI,EAAO,SAAS,cAAc,MAChC,EAAS,QAAQ,GAGZ;CACT;AACF;AAEA,SAAS,EAAU,GAAuC;CACxD,OAAO,CAAC,CAAC,KAAS,OAAO,KAAU,YAAY,WAAW;AAC5D"}
1
+ {"version":3,"file":"admins-components109.js","names":[],"sources":["../src/services/createNativeFetch.ts"],"sourcesContent":["import { ref, type Ref } from 'vue'\nimport { joinUrl } from '@/utils/url'\n\nexport type NativeUseFetchReturn<T = unknown> = {\n data: Ref<T | null>\n error: Ref<any>\n response: Ref<Response | null>\n statusCode: Ref<number | null>\n isFetching: Ref<boolean>\n canAbort: Ref<boolean>\n\n get: () => NativeUseFetchReturn<T>\n post: (payload?: unknown) => NativeUseFetchReturn<T>\n put: (payload?: unknown) => NativeUseFetchReturn<T>\n patch: (payload?: unknown) => NativeUseFetchReturn<T>\n delete: (payload?: unknown) => NativeUseFetchReturn<T>\n\n json: <R = T>() => NativeUseFetchReturn<R>\n text: () => NativeUseFetchReturn<string>\n\n execute: () => Promise<NativeUseFetchReturn<T>>\n abort: () => void\n}\n\nexport type CreateFetchOptions = {\n baseUrl: string\n fetchOptions?: RequestInit\n options?: {\n immediate?: boolean\n beforeFetch?: (ctx: { url: string; options: RequestInit }) => any\n afterFetch?: (ctx: { data: unknown; response: Response }) => any\n onFetchError?: (ctx: { error: any; response: Response | null; data: unknown }) => any\n }\n}\n\nexport function createNativeFetch(config: CreateFetchOptions) {\n return function useNativeFetch<T = unknown>(url: string): NativeUseFetchReturn<T> {\n const data = ref<T | null>(null) as Ref<T | null>\n const error = ref<any>(null)\n const response = ref<Response | null>(null)\n const statusCode = ref<number | null>(null)\n const isFetching = ref(false)\n const canAbort = ref(false)\n\n let method = 'GET'\n let payload: unknown = undefined\n let parser: 'json' | 'text' = 'json'\n let controller: AbortController | null = null\n\n const instance: NativeUseFetchReturn<T> = {\n data,\n error,\n response,\n statusCode,\n isFetching,\n canAbort,\n\n get() {\n method = 'GET'\n return instance\n },\n\n post(p?: unknown) {\n method = 'POST'\n payload = p\n return instance\n },\n\n put(p?: unknown) {\n method = 'PUT'\n payload = p\n return instance\n },\n\n patch(p?: unknown) {\n method = 'PATCH'\n payload = p\n return instance\n },\n\n delete(p?: unknown) {\n method = 'DELETE'\n payload = p\n return instance\n },\n\n json<R = T>() {\n parser = 'json'\n return instance as unknown as NativeUseFetchReturn<R>\n },\n\n text() {\n parser = 'text'\n return instance as unknown as NativeUseFetchReturn<string>\n },\n\n abort() {\n controller?.abort()\n },\n\n async execute() {\n controller = new AbortController()\n\n isFetching.value = true\n canAbort.value = true\n error.value = null\n response.value = null\n statusCode.value = null\n\n const requestOptions: RequestInit = {\n ...config.fetchOptions,\n method,\n signal: controller.signal,\n }\n\n if (payload !== undefined && payload !== null && method !== 'GET') {\n requestOptions.body = isRefLike(payload)\n ? JSON.stringify(payload.value)\n : JSON.stringify(payload)\n }\n\n const ctx = {\n url: joinUrl(config.baseUrl, url),\n options: requestOptions,\n }\n\n try {\n config.options?.beforeFetch?.(ctx)\n\n const res = await fetch(ctx.url, ctx.options)\n\n response.value = res\n statusCode.value = res.status\n\n let parsedData: unknown = null\n\n if (parser === 'text') {\n parsedData = await res.text()\n } else {\n const text = await res.text()\n parsedData = text ? JSON.parse(text) : null\n }\n\n data.value = parsedData as T\n\n if (!res.ok) {\n throw new Error(res.statusText || `HTTP ${res.status}`)\n }\n\n config.options?.afterFetch?.({\n data: parsedData,\n response: res,\n })\n } catch (e: any) {\n error.value = e\n\n config.options?.onFetchError?.({\n error: e,\n response: response.value,\n data: data.value,\n })\n } finally {\n isFetching.value = false\n canAbort.value = false\n controller = null\n }\n\n return instance\n },\n } satisfies NativeUseFetchReturn<T>\n\n if (config.options?.immediate !== false) {\n instance.execute()\n }\n\n return instance\n }\n}\n\nfunction isRefLike(value: unknown): value is Ref<unknown> {\n return !!value && typeof value === 'object' && 'value' in value\n}\n"],"mappings":";;;AAmCA,SAAgB,EAAkB,GAA4B;CAC5D,OAAO,SAAqC,GAAsC;EAChF,IAAM,IAAO,EAAc,IAAI,GACzB,IAAQ,EAAS,IAAI,GACrB,IAAW,EAAqB,IAAI,GACpC,IAAa,EAAmB,IAAI,GACpC,IAAa,EAAI,EAAK,GACtB,IAAW,EAAI,EAAK,GAEtB,IAAS,OACT,GACA,IAA0B,QAC1B,IAAqC,MAEnC,IAAoC;GACxC;GACA;GACA;GACA;GACA;GACA;GAEA,MAAM;IAEJ,OADA,IAAS,OACF;GACT;GAEA,KAAK,GAAa;IAGhB,OAFA,IAAS,QACT,IAAU,GACH;GACT;GAEA,IAAI,GAAa;IAGf,OAFA,IAAS,OACT,IAAU,GACH;GACT;GAEA,MAAM,GAAa;IAGjB,OAFA,IAAS,SACT,IAAU,GACH;GACT;GAEA,OAAO,GAAa;IAGlB,OAFA,IAAS,UACT,IAAU,GACH;GACT;GAEA,OAAc;IAEZ,OADA,IAAS,QACF;GACT;GAEA,OAAO;IAEL,OADA,IAAS,QACF;GACT;GAEA,QAAQ;IACN,GAAY,MAAM;GACpB;GAEA,MAAM,UAAU;IAOd,AANA,IAAa,IAAI,gBAAgB,GAEjC,EAAW,QAAQ,IACnB,EAAS,QAAQ,IACjB,EAAM,QAAQ,MACd,EAAS,QAAQ,MACjB,EAAW,QAAQ;IAEnB,IAAM,IAA8B;KAClC,GAAG,EAAO;KACV;KACA,QAAQ,EAAW;IACrB;IAEA,AAAI,KAAqC,QAAQ,MAAW,UAC1D,EAAe,OAAO,EAAU,CAAO,IACnC,KAAK,UAAU,EAAQ,KAAK,IAC5B,KAAK,UAAU,CAAO;IAG5B,IAAM,IAAM;KACV,KAAK,EAAQ,EAAO,SAAS,CAAG;KAChC,SAAS;IACX;IAEA,IAAI;KACF,EAAO,SAAS,cAAc,CAAG;KAEjC,IAAM,IAAM,MAAM,MAAM,EAAI,KAAK,EAAI,OAAO;KAG5C,AADA,EAAS,QAAQ,GACjB,EAAW,QAAQ,EAAI;KAEvB,IAAI,IAAsB;KAE1B,IAAI,MAAW,QACb,IAAa,MAAM,EAAI,KAAK;UACvB;MACL,IAAM,IAAO,MAAM,EAAI,KAAK;MAC5B,IAAa,IAAO,KAAK,MAAM,CAAI,IAAI;KACzC;KAIA,IAFA,EAAK,QAAQ,GAET,CAAC,EAAI,IACP,MAAU,MAAM,EAAI,cAAc,QAAQ,EAAI,QAAQ;KAGxD,EAAO,SAAS,aAAa;MAC3B,MAAM;MACN,UAAU;KACZ,CAAC;IACH,SAAS,GAAQ;KAGf,AAFA,EAAM,QAAQ,GAEd,EAAO,SAAS,eAAe;MAC7B,OAAO;MACP,UAAU,EAAS;MACnB,MAAM,EAAK;KACb,CAAC;IACH,UAAU;KAGR,AAFA,EAAW,QAAQ,IACnB,EAAS,QAAQ,IACjB,IAAa;IACf;IAEA,OAAO;GACT;EACF;EAMA,OAJI,EAAO,SAAS,cAAc,MAChC,EAAS,QAAQ,GAGZ;CACT;AACF;AAEA,SAAS,EAAU,GAAuC;CACxD,OAAO,CAAC,CAAC,KAAS,OAAO,KAAU,YAAY,WAAW;AAC5D"}
@@ -1 +1 @@
1
- {"version":3,"file":"admins-components11.js","names":[],"sources":["../src/components/Calendar.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { calendarConfigDefaults, type CalendarConfig } from '@/types/datepickers'\n\nexport { calendarConfigDefaults }\nexport type { CalendarConfig }\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, useTemplateRef, nextTick } from 'vue'\nimport { formatDate, parseDate } from '@/utils/date'\nimport Button from '@/components/Button.vue'\n\nconst props = withDefaults(defineProps<{ modelValue: string | null; config?: CalendarConfig }>(), {\n config: () => ({ ...calendarConfigDefaults }),\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | null]\n confirm: [value: string | null]\n}>()\n\nconst cfg = computed(() => ({ ...calendarConfigDefaults, ...props.config }))\n\nconst DAYS_PER_PAGE = 5 * 7\n\nconst outputFormat = computed(\n () => cfg.value.format ?? (cfg.value.showTime ? 'YYYY-MM-DD HH:mm' : 'YYYY-MM-DD'),\n)\n\nfunction parseModelValue(val: string | null): Date | null {\n return val ? parseDate(val, outputFormat.value) : null\n}\n\nconst initial = parseModelValue(props.modelValue)\nconst currentMonth = ref(initial?.getMonth() ?? new Date().getMonth())\nconst currentYear = ref(initial?.getFullYear() ?? new Date().getFullYear())\nconst selectedDate = ref<Date | null>(initial)\nconst hours = ref(initial?.getHours() ?? 0)\nconst minutes = ref(initial?.getMinutes() ?? 0)\nconst activePicker = ref<'year' | 'month' | null>(null)\n\nwatch(\n () => props.modelValue,\n (val) => {\n const parsed = parseModelValue(val ?? null)\n if (parsed) {\n selectedDate.value = parsed\n currentMonth.value = parsed.getMonth()\n currentYear.value = parsed.getFullYear()\n hours.value = parsed.getHours()\n minutes.value = parsed.getMinutes()\n } else {\n selectedDate.value = null\n }\n },\n)\n\n// Locale\nconst weekDays = computed(() =>\n Array.from({ length: 7 }, (_, i) =>\n new Date(2024, 0, i + 1).toLocaleDateString(cfg.value.locale, { weekday: 'narrow' }),\n ),\n)\nconst monthName = computed(() =>\n new Date(currentYear.value, currentMonth.value).toLocaleDateString(cfg.value.locale, {\n month: 'long',\n }),\n)\nconst monthNames = computed(() =>\n Array.from({ length: 12 }, (_, i) =>\n new Date(2024, i).toLocaleDateString(cfg.value.locale, { month: 'long' }),\n ),\n)\n\n// Days grid\nconst calendarDays = computed(() => {\n const first = new Date(currentYear.value, currentMonth.value, 1)\n const last = new Date(currentYear.value, currentMonth.value + 1, 0)\n const offset = (first.getDay() + 6) % 7\n const days: { date: Date; currentMonth: boolean; disabled: boolean }[] = []\n\n for (let i = offset - 1; i >= 0; i--)\n days.push({\n date: new Date(currentYear.value, currentMonth.value, -i),\n currentMonth: false,\n disabled: isDisabled(new Date(currentYear.value, currentMonth.value, -i)),\n })\n for (let i = 1; i <= last.getDate(); i++)\n days.push({\n date: new Date(currentYear.value, currentMonth.value, i),\n currentMonth: true,\n disabled: isDisabled(new Date(currentYear.value, currentMonth.value, i)),\n })\n for (let i = 1; days.length < DAYS_PER_PAGE; i++)\n days.push({\n date: new Date(currentYear.value, currentMonth.value + 1, i),\n currentMonth: false,\n disabled: isDisabled(new Date(currentYear.value, currentMonth.value + 1, i)),\n })\n\n return days\n})\n\n// ISO 8601 week number\nfunction getIsoWeekNumber(d: Date) {\n const target = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()))\n const dayNum = (target.getUTCDay() + 6) % 7\n target.setUTCDate(target.getUTCDate() - dayNum + 3)\n const firstThursday = new Date(Date.UTC(target.getUTCFullYear(), 0, 4))\n const diff = (target.getTime() - firstThursday.getTime()) / 86400000\n return 1 + Math.round((diff - 3 + ((firstThursday.getUTCDay() + 6) % 7)) / 7)\n}\n\nconst weekNumbers = computed(() => {\n const weeks: number[] = []\n for (let row = 0; row < 6; row++) {\n const firstDayOfRow = calendarDays.value[row * 7]?.date\n weeks.push(firstDayOfRow ? getIsoWeekNumber(firstDayOfRow) : 0)\n }\n return weeks\n})\n\n// Helpers\nfunction stripTime(d: Date) {\n return new Date(d.getFullYear(), d.getMonth(), d.getDate())\n}\nfunction isDisabled(d: Date) {\n return (\n (cfg.value.minDate && d < stripTime(cfg.value.minDate)) ||\n (cfg.value.maxDate && d > stripTime(cfg.value.maxDate)) ||\n false\n )\n}\nfunction isWeekend(d: Date) {\n return d.getDay() === 0 || d.getDay() === 6\n}\nfunction isSameDay(a: Date, b: Date | null) {\n return (\n !!b &&\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate()\n )\n}\nfunction isToday(d: Date) {\n return isSameDay(d, new Date())\n}\n\n// Navigation\nfunction navigate(delta: number) {\n const d = new Date(currentYear.value, currentMonth.value + delta, 1)\n currentYear.value = d.getFullYear()\n currentMonth.value = d.getMonth()\n}\n\nfunction backToDayPicker() {\n activePicker.value = null\n}\n\nfunction onPrev() {\n if (activePicker.value) backToDayPicker()\n else navigate(-1)\n}\n\nfunction onNext() {\n if (activePicker.value) backToDayPicker()\n else navigate(1)\n}\n\n// Pickers\nconst yearList = computed(() =>\n Array.from({ length: new Date().getFullYear() + 3 - 2000 + 1 }, (_, i) => 2000 + i),\n)\nconst yearPickerRef = useTemplateRef<HTMLElement>('yearPickerRef')\n\nfunction togglePicker(picker: 'year' | 'month') {\n activePicker.value = activePicker.value === picker ? null : picker\n if (activePicker.value === 'year') {\n nextTick(() => {\n const container = yearPickerRef.value\n const el = container?.querySelector('.dp-picker-item--selected') as HTMLElement | null\n if (el && container) {\n container.scrollTop = el.offsetTop - container.offsetHeight / 2 + el.offsetHeight / 2\n } else if (container) {\n container.scrollTop = container.scrollHeight\n }\n })\n }\n}\n\nfunction selectYear(year: number) {\n currentYear.value = year\n activePicker.value = null\n}\nfunction selectMonth(month: number) {\n currentMonth.value = month\n activePicker.value = null\n}\n\n// Selection & emit\nfunction selectDay(day: { date: Date; disabled: boolean }) {\n if (day.disabled) return\n selectedDate.value = new Date(day.date)\n emitValue()\n if (cfg.value.showTime) {\n nextTick(() => hoursInput.value?.focus())\n }\n}\n\nfunction emitValue() {\n if (!selectedDate.value) {\n emit('update:modelValue', null)\n return\n }\n const result = new Date(selectedDate.value)\n if (cfg.value.showTime) result.setHours(hours.value, minutes.value, 0, 0)\n else result.setHours(0, 0, 0, 0)\n emit('update:modelValue', formatDate(result, outputFormat.value))\n}\n\nfunction onClear() {\n selectedDate.value = null\n hours.value = 0\n minutes.value = 0\n emit('update:modelValue', null)\n}\n\n// Time input\nfunction createTimeField(max: number, valueRef: { value: number }) {\n return computed({\n get: () => String(valueRef.value).padStart(2, '0'),\n set: (val: string) => {\n valueRef.value = Math.min(max, Math.max(0, parseInt(val) || 0))\n },\n })\n}\n\nconst formattedHours = createTimeField(23, hours)\nconst formattedMinutes = createTimeField(59, minutes)\nconst hoursInput = useTemplateRef<HTMLInputElement>('hoursInput')\nconst minutesInput = useTemplateRef<HTMLInputElement>('minutesInput')\n\nfunction onTimeInput(field: 'hours' | 'minutes', event: Event) {\n const el = event.target as HTMLInputElement\n if (field === 'hours') {\n formattedHours.value = el.value\n if (el.value.length >= 2) {\n minutesInput.value?.focus()\n minutesInput.value?.select()\n }\n } else {\n formattedMinutes.value = el.value\n if (el.value.length >= 2) el.blur()\n }\n emitValue()\n}\n</script>\n\n<template>\n <div class=\"ac-component\">\n <div class=\"dp-calendar\">\n <div class=\"dp-header\">\n <button\n class=\"dp-nav-btn\"\n type=\"button\"\n :aria-label=\"activePicker ? 'Back to days' : 'Previous'\"\n @click=\"onPrev\"\n >\n <i class=\"fa-solid fa-chevron-left\"></i>\n </button>\n <div class=\"dp-header-labels\">\n <span class=\"dp-header-labels--item\" @click=\"togglePicker('year')\">{{\n currentYear\n }}</span>\n <span class=\"dp-header-labels--item\" @click=\"togglePicker('month')\">{{ monthName }}</span>\n </div>\n <button\n class=\"dp-nav-btn\"\n type=\"button\"\n :aria-label=\"activePicker ? 'Back to days' : 'Next'\"\n :class=\"{ 'dp-nav-btn--spacer': activePicker !== null }\"\n :aria-hidden=\"activePicker ? 'true' : 'false'\"\n @click=\"onNext\"\n >\n <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n </div>\n\n <div\n class=\"dp-body\"\n :class=\"{ 'dp-body--has-footer': cfg.showTime || cfg.showOkButton || cfg.showClearButton }\"\n >\n <!-- Year picker -->\n <div\n v-if=\"activePicker === 'year'\"\n ref=\"yearPickerRef\"\n class=\"dp-picker-grid dp-picker-grid--4col dp-picker-grid--scrollable c-scroll\"\n >\n <button\n v-for=\"y in yearList\"\n :key=\"y\"\n type=\"button\"\n class=\"dp-picker-item\"\n :class=\"{\n 'dp-picker-item--selected': y === currentYear,\n 'dp-picker-item--today': y === new Date().getFullYear(),\n }\"\n @click=\"selectYear(y)\"\n >\n {{ y }}\n </button>\n </div>\n\n <!-- Month picker -->\n <div\n v-else-if=\"activePicker === 'month'\"\n class=\"dp-picker-grid dp-month-picker dp-picker-grid--3col\"\n >\n <button\n v-for=\"(name, idx) in monthNames\"\n :key=\"idx\"\n type=\"button\"\n class=\"dp-picker-item\"\n :class=\"{\n 'dp-picker-item--selected': idx === currentMonth,\n 'dp-picker-item--today':\n idx === new Date().getMonth() && currentYear === new Date().getFullYear(),\n }\"\n @click=\"selectMonth(idx)\"\n >\n {{ name }}\n </button>\n </div>\n\n <!-- Day picker -->\n <template v-else>\n <div class=\"dp-weekdays\" :class=\"{ 'dp-weekdays--has-week': cfg.showWeekNumber }\">\n <span v-if=\"cfg.showWeekNumber\" class=\"dp-weekday dp-weekday--week\"></span>\n <span v-for=\"d in weekDays\" :key=\"d\" class=\"dp-weekday\">{{ d }}</span>\n </div>\n <div\n class=\"dp-picker-grid\"\n :class=\"cfg.showWeekNumber ? 'dp-picker-grid--8col' : 'dp-picker-grid--7col'\"\n >\n <template v-for=\"(day, i) in calendarDays\" :key=\"i\">\n <span\n v-if=\"cfg.showWeekNumber && Number(i) % 7 === 0\"\n class=\"dp-week-number\"\n :class=\"{\n 'dp-week-number--other':\n !day.currentMonth && !calendarDays[Number(i) + 7]?.currentMonth,\n }\"\n v-tooltip=\"`${weekNumbers[Math.floor(Number(i) / 7)]}. hét`\"\n >\n {{ weekNumbers[Math.floor(Number(i) / 7)] }}.\n </span>\n <button\n type=\"button\"\n class=\"dp-picker-item dp-picker-item--circle\"\n :class=\"{\n 'dp-picker-item--other': !day.currentMonth,\n 'dp-picker-item--selected': isSameDay(day.date, selectedDate),\n 'dp-picker-item--today': isToday(day.date),\n 'dp-picker-item--disabled': day.disabled,\n 'dp-picker-item--weekend': cfg.highlightWeekends && isWeekend(day.date),\n }\"\n :disabled=\"day.disabled\"\n @click=\"selectDay(day)\"\n >\n {{ day.date.getDate() }}\n </button>\n </template>\n </div>\n\n <div v-if=\"cfg.showTime || cfg.showOkButton || cfg.showClearButton\" class=\"c-footer\">\n <template v-if=\"cfg.showTime\">\n <label class=\"dp-time-label\" for=\"dp-hours\">Idő</label>\n <div class=\"dp-time-inputs\">\n <input\n id=\"dp-hours\"\n ref=\"hoursInput\"\n type=\"number\"\n class=\"c-focus dp-time-input\"\n :value=\"formattedHours\"\n :disabled=\"!selectedDate\"\n min=\"0\"\n max=\"23\"\n @input=\"onTimeInput('hours', $event)\"\n @focus=\"($event.target as HTMLInputElement).select()\"\n />\n <span class=\"dp-time-sep\">:</span>\n <input\n id=\"dp-minutes\"\n ref=\"minutesInput\"\n type=\"number\"\n class=\"c-focus dp-time-input\"\n :value=\"formattedMinutes\"\n :disabled=\"!selectedDate\"\n min=\"0\"\n max=\"59\"\n @input=\"onTimeInput('minutes', $event)\"\n @focus=\"($event.target as HTMLInputElement).select()\"\n />\n </div>\n </template>\n <Button\n v-if=\"cfg.showClearButton\"\n label=\"Törlés\"\n @click=\"onClear\"\n outline\n :disabled=\"!selectedDate\"\n />\n <Button\n v-if=\"cfg.showOkButton\"\n label=\"OK\"\n type=\"success\"\n @click=\"emit('confirm', modelValue)\"\n :disabled=\"!selectedDate\"\n />\n </div>\n </template>\n </div>\n </div>\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/calendar.scss\"></style>\n<style lang=\"scss\" src=\"@/styles/components/datepickers.scss\"></style>\n"],"mappings":""}
1
+ {"version":3,"file":"admins-components11.js","names":[],"sources":["../src/components/Calendar.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { calendarConfigDefaults, type CalendarConfig } from '@/types/datepickers'\n\nexport { calendarConfigDefaults }\nexport type { CalendarConfig }\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, useTemplateRef, nextTick } from 'vue'\nimport { formatDate, parseDate } from '@/utils/date'\nimport Button from '@/components/Button.vue'\n\nconst props = withDefaults(defineProps<{ modelValue: string | null; config?: CalendarConfig }>(), {\n config: () => ({ ...calendarConfigDefaults }),\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string | null]\n confirm: [value: string | null]\n}>()\n\nconst cfg = computed(() => ({ ...calendarConfigDefaults, ...props.config }))\n\nconst DAYS_PER_PAGE = 5 * 7\n\nconst outputFormat = computed(\n () => cfg.value.format ?? (cfg.value.showTime ? 'YYYY-MM-DD HH:mm' : 'YYYY-MM-DD'),\n)\n\nfunction parseModelValue(val: string | null): Date | null {\n return val ? parseDate(val, outputFormat.value) : null\n}\n\nconst initial = parseModelValue(props.modelValue)\nconst currentMonth = ref(initial?.getMonth() ?? new Date().getMonth())\nconst currentYear = ref(initial?.getFullYear() ?? new Date().getFullYear())\nconst selectedDate = ref<Date | null>(initial)\nconst hours = ref(initial?.getHours() ?? 0)\nconst minutes = ref(initial?.getMinutes() ?? 0)\nconst activePicker = ref<'year' | 'month' | null>(null)\n\nwatch(\n () => props.modelValue,\n (val) => {\n const parsed = parseModelValue(val ?? null)\n if (parsed) {\n selectedDate.value = parsed\n currentMonth.value = parsed.getMonth()\n currentYear.value = parsed.getFullYear()\n hours.value = parsed.getHours()\n minutes.value = parsed.getMinutes()\n } else {\n selectedDate.value = null\n }\n },\n)\n\nconst weekDays = computed(() =>\n Array.from({ length: 7 }, (_, i) =>\n new Date(2024, 0, i + 1).toLocaleDateString(cfg.value.locale, { weekday: 'narrow' }),\n ),\n)\nconst monthName = computed(() =>\n new Date(currentYear.value, currentMonth.value).toLocaleDateString(cfg.value.locale, {\n month: 'long',\n }),\n)\nconst monthNames = computed(() =>\n Array.from({ length: 12 }, (_, i) =>\n new Date(2024, i).toLocaleDateString(cfg.value.locale, { month: 'long' }),\n ),\n)\n\nconst calendarDays = computed(() => {\n const first = new Date(currentYear.value, currentMonth.value, 1)\n const last = new Date(currentYear.value, currentMonth.value + 1, 0)\n const offset = (first.getDay() + 6) % 7\n const days: { date: Date; currentMonth: boolean; disabled: boolean }[] = []\n\n for (let i = offset - 1; i >= 0; i--)\n days.push({\n date: new Date(currentYear.value, currentMonth.value, -i),\n currentMonth: false,\n disabled: isDisabled(new Date(currentYear.value, currentMonth.value, -i)),\n })\n for (let i = 1; i <= last.getDate(); i++)\n days.push({\n date: new Date(currentYear.value, currentMonth.value, i),\n currentMonth: true,\n disabled: isDisabled(new Date(currentYear.value, currentMonth.value, i)),\n })\n for (let i = 1; days.length < DAYS_PER_PAGE; i++)\n days.push({\n date: new Date(currentYear.value, currentMonth.value + 1, i),\n currentMonth: false,\n disabled: isDisabled(new Date(currentYear.value, currentMonth.value + 1, i)),\n })\n\n return days\n})\n\nfunction getIsoWeekNumber(d: Date) {\n const target = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()))\n const dayNum = (target.getUTCDay() + 6) % 7\n target.setUTCDate(target.getUTCDate() - dayNum + 3)\n const firstThursday = new Date(Date.UTC(target.getUTCFullYear(), 0, 4))\n const diff = (target.getTime() - firstThursday.getTime()) / 86400000\n return 1 + Math.round((diff - 3 + ((firstThursday.getUTCDay() + 6) % 7)) / 7)\n}\n\nconst weekNumbers = computed(() => {\n const weeks: number[] = []\n for (let row = 0; row < 6; row++) {\n const firstDayOfRow = calendarDays.value[row * 7]?.date\n weeks.push(firstDayOfRow ? getIsoWeekNumber(firstDayOfRow) : 0)\n }\n return weeks\n})\n\nfunction stripTime(d: Date) {\n return new Date(d.getFullYear(), d.getMonth(), d.getDate())\n}\nfunction isDisabled(d: Date) {\n return (\n (cfg.value.minDate && d < stripTime(cfg.value.minDate)) ||\n (cfg.value.maxDate && d > stripTime(cfg.value.maxDate)) ||\n false\n )\n}\nfunction isWeekend(d: Date) {\n return d.getDay() === 0 || d.getDay() === 6\n}\nfunction isSameDay(a: Date, b: Date | null) {\n return (\n !!b &&\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate()\n )\n}\nfunction isToday(d: Date) {\n return isSameDay(d, new Date())\n}\n\nfunction navigate(delta: number) {\n const d = new Date(currentYear.value, currentMonth.value + delta, 1)\n currentYear.value = d.getFullYear()\n currentMonth.value = d.getMonth()\n}\n\nfunction backToDayPicker() {\n activePicker.value = null\n}\n\nfunction onPrev() {\n if (activePicker.value) backToDayPicker()\n else navigate(-1)\n}\n\nfunction onNext() {\n if (activePicker.value) backToDayPicker()\n else navigate(1)\n}\n\nconst yearList = computed(() =>\n Array.from({ length: new Date().getFullYear() + 3 - 2000 + 1 }, (_, i) => 2000 + i),\n)\nconst yearPickerRef = useTemplateRef<HTMLElement>('yearPickerRef')\n\nfunction togglePicker(picker: 'year' | 'month') {\n activePicker.value = activePicker.value === picker ? null : picker\n if (activePicker.value === 'year') {\n nextTick(() => {\n const container = yearPickerRef.value\n const el = container?.querySelector('.dp-picker-item--selected') as HTMLElement | null\n if (el && container) {\n container.scrollTop = el.offsetTop - container.offsetHeight / 2 + el.offsetHeight / 2\n } else if (container) {\n container.scrollTop = container.scrollHeight\n }\n })\n }\n}\n\nfunction selectYear(year: number) {\n currentYear.value = year\n activePicker.value = null\n}\nfunction selectMonth(month: number) {\n currentMonth.value = month\n activePicker.value = null\n}\n\nfunction selectDay(day: { date: Date; disabled: boolean }) {\n if (day.disabled) return\n selectedDate.value = new Date(day.date)\n emitValue()\n if (cfg.value.showTime) {\n nextTick(() => hoursInput.value?.focus())\n }\n}\n\nfunction emitValue() {\n if (!selectedDate.value) {\n emit('update:modelValue', null)\n return\n }\n const result = new Date(selectedDate.value)\n if (cfg.value.showTime) result.setHours(hours.value, minutes.value, 0, 0)\n else result.setHours(0, 0, 0, 0)\n emit('update:modelValue', formatDate(result, outputFormat.value))\n}\n\nfunction onClear() {\n selectedDate.value = null\n hours.value = 0\n minutes.value = 0\n emit('update:modelValue', null)\n}\n\nfunction createTimeField(max: number, valueRef: { value: number }) {\n return computed({\n get: () => String(valueRef.value).padStart(2, '0'),\n set: (val: string) => {\n valueRef.value = Math.min(max, Math.max(0, parseInt(val) || 0))\n },\n })\n}\n\nconst formattedHours = createTimeField(23, hours)\nconst formattedMinutes = createTimeField(59, minutes)\nconst hoursInput = useTemplateRef<HTMLInputElement>('hoursInput')\nconst minutesInput = useTemplateRef<HTMLInputElement>('minutesInput')\n\nfunction onTimeInput(field: 'hours' | 'minutes', event: Event) {\n const el = event.target as HTMLInputElement\n if (field === 'hours') {\n formattedHours.value = el.value\n if (el.value.length >= 2) {\n minutesInput.value?.focus()\n minutesInput.value?.select()\n }\n } else {\n formattedMinutes.value = el.value\n if (el.value.length >= 2) el.blur()\n }\n emitValue()\n}\n</script>\n\n<template>\n <div class=\"ac-component\">\n <div class=\"dp-calendar\">\n <div class=\"dp-header\">\n <button\n class=\"dp-nav-btn\"\n type=\"button\"\n :aria-label=\"activePicker ? 'Back to days' : 'Previous'\"\n @click=\"onPrev\"\n >\n <i class=\"fa-solid fa-chevron-left\"></i>\n </button>\n <div class=\"dp-header-labels\">\n <span class=\"dp-header-labels--item\" @click=\"togglePicker('year')\">{{\n currentYear\n }}</span>\n <span class=\"dp-header-labels--item\" @click=\"togglePicker('month')\">{{ monthName }}</span>\n </div>\n <button\n class=\"dp-nav-btn\"\n type=\"button\"\n :aria-label=\"activePicker ? 'Back to days' : 'Next'\"\n :class=\"{ 'dp-nav-btn--spacer': activePicker !== null }\"\n :aria-hidden=\"activePicker ? 'true' : 'false'\"\n @click=\"onNext\"\n >\n <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n </div>\n\n <div\n class=\"dp-body\"\n :class=\"{ 'dp-body--has-footer': cfg.showTime || cfg.showOkButton || cfg.showClearButton }\"\n >\n <!-- Year picker -->\n <div\n v-if=\"activePicker === 'year'\"\n ref=\"yearPickerRef\"\n class=\"dp-picker-grid dp-picker-grid--4col dp-picker-grid--scrollable c-scroll\"\n >\n <button\n v-for=\"y in yearList\"\n :key=\"y\"\n type=\"button\"\n class=\"dp-picker-item\"\n :class=\"{\n 'dp-picker-item--selected': y === currentYear,\n 'dp-picker-item--today': y === new Date().getFullYear(),\n }\"\n @click=\"selectYear(y)\"\n >\n {{ y }}\n </button>\n </div>\n\n <!-- Month picker -->\n <div\n v-else-if=\"activePicker === 'month'\"\n class=\"dp-picker-grid dp-month-picker dp-picker-grid--3col\"\n >\n <button\n v-for=\"(name, idx) in monthNames\"\n :key=\"idx\"\n type=\"button\"\n class=\"dp-picker-item\"\n :class=\"{\n 'dp-picker-item--selected': idx === currentMonth,\n 'dp-picker-item--today':\n idx === new Date().getMonth() && currentYear === new Date().getFullYear(),\n }\"\n @click=\"selectMonth(idx)\"\n >\n {{ name }}\n </button>\n </div>\n\n <!-- Day picker -->\n <template v-else>\n <div class=\"dp-weekdays\" :class=\"{ 'dp-weekdays--has-week': cfg.showWeekNumber }\">\n <span v-if=\"cfg.showWeekNumber\" class=\"dp-weekday dp-weekday--week\"></span>\n <span v-for=\"d in weekDays\" :key=\"d\" class=\"dp-weekday\">{{ d }}</span>\n </div>\n <div\n class=\"dp-picker-grid\"\n :class=\"cfg.showWeekNumber ? 'dp-picker-grid--8col' : 'dp-picker-grid--7col'\"\n >\n <template v-for=\"(day, i) in calendarDays\" :key=\"i\">\n <span\n v-if=\"cfg.showWeekNumber && Number(i) % 7 === 0\"\n class=\"dp-week-number\"\n :class=\"{\n 'dp-week-number--other':\n !day.currentMonth && !calendarDays[Number(i) + 7]?.currentMonth,\n }\"\n v-tooltip=\"`${weekNumbers[Math.floor(Number(i) / 7)]}. hét`\"\n >\n {{ weekNumbers[Math.floor(Number(i) / 7)] }}.\n </span>\n <button\n type=\"button\"\n class=\"dp-picker-item dp-picker-item--circle\"\n :class=\"{\n 'dp-picker-item--other': !day.currentMonth,\n 'dp-picker-item--selected': isSameDay(day.date, selectedDate),\n 'dp-picker-item--today': isToday(day.date),\n 'dp-picker-item--disabled': day.disabled,\n 'dp-picker-item--weekend': cfg.highlightWeekends && isWeekend(day.date),\n }\"\n :disabled=\"day.disabled\"\n @click=\"selectDay(day)\"\n >\n {{ day.date.getDate() }}\n </button>\n </template>\n </div>\n\n <div v-if=\"cfg.showTime || cfg.showOkButton || cfg.showClearButton\" class=\"c-footer\">\n <template v-if=\"cfg.showTime\">\n <label class=\"dp-time-label\" for=\"dp-hours\">Idő</label>\n <div class=\"dp-time-inputs\">\n <input\n id=\"dp-hours\"\n ref=\"hoursInput\"\n type=\"number\"\n class=\"c-focus dp-time-input\"\n :value=\"formattedHours\"\n :disabled=\"!selectedDate\"\n min=\"0\"\n max=\"23\"\n @input=\"onTimeInput('hours', $event)\"\n @focus=\"($event.target as HTMLInputElement).select()\"\n />\n <span class=\"dp-time-sep\">:</span>\n <input\n id=\"dp-minutes\"\n ref=\"minutesInput\"\n type=\"number\"\n class=\"c-focus dp-time-input\"\n :value=\"formattedMinutes\"\n :disabled=\"!selectedDate\"\n min=\"0\"\n max=\"59\"\n @input=\"onTimeInput('minutes', $event)\"\n @focus=\"($event.target as HTMLInputElement).select()\"\n />\n </div>\n </template>\n <Button\n v-if=\"cfg.showClearButton\"\n label=\"Törlés\"\n @click=\"onClear\"\n outline\n :disabled=\"!selectedDate\"\n />\n <Button\n v-if=\"cfg.showOkButton\"\n label=\"OK\"\n type=\"success\"\n @click=\"emit('confirm', modelValue)\"\n :disabled=\"!selectedDate\"\n />\n </div>\n </template>\n </div>\n </div>\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/calendar.scss\"></style>\n<style lang=\"scss\" src=\"@/styles/components/datepickers.scss\"></style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"admins-components112.js","names":[],"sources":["../src/services/currentUserInfo.ts"],"sourcesContent":["import { ref, computed, type Ref, type ComputedRef } from 'vue'\nimport { useArticleEditorService } from '@/services/articleEditorService'\nimport type { UserInfoModel, Site } from '@/services/models'\nimport { isIpInUrl } from '@/utils/ipUtils'\n\nexport type UserState = 'loading' | 'authenticated' | 'error'\n\nexport interface CurrentUserStore {\n user: Ref<UserInfoModel | null>\n state: Ref<UserState>\n error: Ref<string | null>\n isLoading: ComputedRef<boolean>\n isAuthenticated: ComputedRef<boolean>\n displayName: ComputedRef<string>\n email: ComputedRef<string>\n roles: ComputedRef<readonly string[]>\n initialize(backendUrl: string, enableLogging?: boolean): Promise<void>\n clear(): void\n hasPermission(\n siteId: string,\n entityName: string | 'all',\n accessLevel: 'reader' | 'admin',\n ): boolean\n getMixableSitesForResource(entityName: string | 'all', currentSiteId: string | undefined): Site[]\n getMixableSiteIdsForResource(\n entityName: string | 'all',\n currentSiteId: string | undefined,\n ): string[]\n}\n\nlet storeInstance: CurrentUserStore | null = null\nlet sites = [] as Site[]\nlet loggingEnabled = false\n\nexport function useCurrentUser(): CurrentUserStore {\n if (storeInstance) {\n if (loggingEnabled) console.debug('[currentUserInfo] Returning existing store instance')\n return storeInstance\n }\n\n if (loggingEnabled) console.debug('[currentUserInfo] Creating new store instance')\n const user = ref<UserInfoModel | null>(null)\n const state = ref<UserState>('loading')\n const error = ref<string | null>(null)\n const _backendUrl = ref<string | null>(null)\n const isLoading = computed(() => state.value === 'loading')\n const isAuthenticated = computed(() => state.value === 'authenticated' && user.value !== null)\n const displayName = computed(() => user.value?.displayName ?? '')\n const email = computed(() => user.value?.email ?? '')\n const roles = computed(() => user.value?.roles ?? [])\n\n async function initialize(backendUrl: string, enableLogging?: boolean): Promise<void> {\n loggingEnabled = enableLogging ?? false\n\n if (loggingEnabled) console.debug('[currentUserInfo] initialize() called', { backendUrl })\n\n if (loggingEnabled) console.debug('[currentUserInfo] Starting initialization')\n _backendUrl.value = backendUrl\n state.value = 'loading'\n error.value = null\n\n try {\n const service = useArticleEditorService(backendUrl)\n\n await new Promise<void>((resolve, reject) => {\n if (service.baseUrl.indexOf('localhost') != -1 || isIpInUrl(service.baseUrl)) {\n if (loggingEnabled)\n console.debug('[currentUserInfo] Localhost/IP detected, using dev credentials')\n user.value = {\n displayName: 'developer',\n email: 'developer@hvg.hu',\n roles: ['devadmin'],\n id: '00000000-0000-0000-0000-000000000000',\n }\n state.value = 'authenticated'\n return resolve()\n }\n\n service.whoAmI.successCallback = (userInfo: UserInfoModel) => {\n if (loggingEnabled) {\n console.debug('[currentUserInfo] whoAmI success', {\n displayName: userInfo.displayName,\n email: userInfo.email,\n rolesCount: userInfo.roles?.length ?? 0,\n })\n }\n user.value = userInfo\n state.value = 'authenticated'\n resolve()\n }\n\n service.whoAmI.errorCallback = (err) => {\n if (loggingEnabled) console.error('[currentUserInfo] whoAmI failed:', err)\n error.value = err.message ?? 'Ismeretlen hiba történt'\n state.value = 'error'\n reject(new Error(error.value))\n }\n\n if (loggingEnabled) console.debug('[currentUserInfo] Executing whoAmI request')\n service.whoAmI.execute()\n })\n\n await new Promise<void>((resolve, reject) => {\n service.sites.successCallback = (fetchedSites) => {\n if (loggingEnabled)\n console.debug('[currentUserInfo] sites fetch success', {\n sitesCount: fetchedSites.length,\n })\n sites = fetchedSites\n resolve()\n }\n\n service.sites.errorCallback = (err) => {\n if (loggingEnabled) console.error('[currentUserInfo] sites fetch failed:', err)\n reject(new Error(err.message ?? 'Ismeretlen hiba történt'))\n }\n\n if (loggingEnabled) console.debug('[currentUserInfo] Executing sites request')\n service.sites.execute()\n })\n\n if (loggingEnabled) console.debug('[currentUserInfo] Initialization completed successfully')\n } catch (err) {\n if (loggingEnabled) console.error('[currentUserInfo] initialize failed:', err)\n state.value = 'error'\n if (!error.value) {\n error.value = 'Felhasználói adatok vagy site-ok lekérése sikertelen'\n }\n throw err\n }\n }\n\n function clear(): void {\n if (loggingEnabled) console.debug('[currentUserInfo] clear() called, resetting all state')\n user.value = null\n state.value = 'loading'\n error.value = null\n _backendUrl.value = null\n sites = []\n }\n\n function hasPermission(\n siteId: string,\n entityName: string | 'all',\n accessLevel: 'reader' | 'admin',\n ): boolean {\n if (loggingEnabled)\n console.debug('[currentUserInfo] hasPermission() check', { siteId, entityName, accessLevel })\n\n if (!user.value?.roles || user.value.roles.length === 0) {\n if (loggingEnabled) console.debug('[currentUserInfo] hasPermission() denied: no roles')\n return false\n }\n\n if (user.value.roles.includes('devadmin')) {\n if (loggingEnabled) console.debug('[currentUserInfo] hasPermission() granted: devadmin role')\n return true\n }\n\n const requiredLevels = accessLevel === 'admin' ? ['admin'] : ['reader', 'admin']\n\n for (const level of requiredLevels) {\n const specificRole = `cms-${siteId}-${entityName}-${level}`\n if (user.value.roles.includes(specificRole)) {\n if (loggingEnabled)\n console.debug('[currentUserInfo] hasPermission() granted: specific role', specificRole)\n return true\n }\n\n const allentityRole = `cms-${siteId}-all-${level}`\n if (user.value.roles.includes(allentityRole)) {\n if (loggingEnabled)\n console.debug('[currentUserInfo] hasPermission() granted: all-entity role', allentityRole)\n return true\n }\n }\n\n if (loggingEnabled) console.debug('[currentUserInfo] hasPermission() denied: no matching roles')\n return false\n }\n\n function getMixableSitesForResource(\n entityName: string | 'all',\n currentSiteId: string | undefined,\n ): Site[] {\n if (loggingEnabled)\n console.debug('[currentUserInfo] getMixableSitesForResource() called', {\n entityName,\n currentSiteId,\n })\n\n if (!_backendUrl.value) {\n if (loggingEnabled)\n console.error('[currentUserInfo] getMixableSitesForResource called before initialize')\n throw new Error('Store nincs inicializálva. Hívd meg előbb az initialize() metódust!')\n }\n\n const currentSite = sites.find((site) => site.id === currentSiteId)\n if (loggingEnabled)\n console.debug('[currentUserInfo] Current site lookup', {\n found: !!currentSite,\n totalSites: sites.length,\n })\n\n const mixableSites = [] as Site[]\n sites.forEach((site) => {\n if (currentSite === undefined) {\n // Case 1: No current site specified - only check permissions\n if (!hasPermission(site.id, entityName, 'reader')) {\n return\n }\n mixableSites.push(site)\n } else {\n // Case 2: Current site specified - check entity allowance AND permissions\n if (\n currentSite.entities.find(\n (e) => e.type === entityName && e.allowedSiteIds.includes(site.id),\n ) === undefined\n ) {\n return\n }\n\n if (!hasPermission(site.id, entityName, 'reader')) {\n return\n }\n\n mixableSites.push(site)\n }\n })\n\n if (loggingEnabled) {\n console.debug('[currentUserInfo] getMixableSitesForResource() result', {\n mixableCount: mixableSites.length,\n mixableSiteIds: mixableSites.map((s) => s.id),\n })\n }\n return mixableSites\n }\n\n function getMixableSiteIdsForResource(\n entityName: string | 'all',\n currentSiteId: string | undefined,\n ): string[] {\n if (loggingEnabled)\n console.debug('[currentUserInfo] getMixableSiteIdsForResource() called', {\n entityName,\n currentSiteId,\n })\n const mixableSites = getMixableSitesForResource(entityName, currentSiteId)\n return mixableSites.map((site) => site.id)\n }\n\n storeInstance = {\n user,\n state,\n error,\n isLoading,\n isAuthenticated,\n displayName,\n email,\n roles,\n initialize,\n clear,\n hasPermission,\n getMixableSitesForResource,\n getMixableSiteIdsForResource,\n }\n\n return storeInstance\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"admins-components112.js","names":[],"sources":["../src/services/currentUserInfo.ts"],"sourcesContent":["import { ref, computed, type Ref, type ComputedRef } from 'vue'\nimport { useArticleEditorService } from '@/services/articleEditorService'\nimport type { UserInfoModel, Site } from '@/services/models'\nimport { isIpInUrl } from '@/utils/ipUtils'\n\nexport type UserState = 'loading' | 'authenticated' | 'error'\n\nexport interface CurrentUserStore {\n user: Ref<UserInfoModel | null>\n state: Ref<UserState>\n error: Ref<string | null>\n isLoading: ComputedRef<boolean>\n isAuthenticated: ComputedRef<boolean>\n displayName: ComputedRef<string>\n email: ComputedRef<string>\n roles: ComputedRef<readonly string[]>\n initialize(backendUrl: string, enableLogging?: boolean): Promise<void>\n clear(): void\n hasPermission(\n siteId: string,\n entityName: string | 'all',\n accessLevel: 'reader' | 'admin',\n ): boolean\n getMixableSitesForResource(entityName: string | 'all', currentSiteId: string | undefined): Site[]\n getMixableSiteIdsForResource(\n entityName: string | 'all',\n currentSiteId: string | undefined,\n ): string[]\n}\n\nlet storeInstance: CurrentUserStore | null = null\nlet sites = [] as Site[]\nlet loggingEnabled = false\n\nexport function useCurrentUser(): CurrentUserStore {\n if (storeInstance) {\n if (loggingEnabled) console.debug('[currentUserInfo] Returning existing store instance')\n return storeInstance\n }\n\n if (loggingEnabled) console.debug('[currentUserInfo] Creating new store instance')\n const user = ref<UserInfoModel | null>(null)\n const state = ref<UserState>('loading')\n const error = ref<string | null>(null)\n const _backendUrl = ref<string | null>(null)\n const isLoading = computed(() => state.value === 'loading')\n const isAuthenticated = computed(() => state.value === 'authenticated' && user.value !== null)\n const displayName = computed(() => user.value?.displayName ?? '')\n const email = computed(() => user.value?.email ?? '')\n const roles = computed(() => user.value?.roles ?? [])\n\n async function initialize(backendUrl: string, enableLogging?: boolean): Promise<void> {\n loggingEnabled = enableLogging ?? false\n\n if (loggingEnabled) console.debug('[currentUserInfo] initialize() called', { backendUrl })\n\n if (loggingEnabled) console.debug('[currentUserInfo] Starting initialization')\n _backendUrl.value = backendUrl\n state.value = 'loading'\n error.value = null\n\n try {\n const service = useArticleEditorService(backendUrl)\n\n await new Promise<void>((resolve, reject) => {\n if (service.baseUrl.indexOf('localhost') != -1 || isIpInUrl(service.baseUrl)) {\n if (loggingEnabled)\n console.debug('[currentUserInfo] Localhost/IP detected, using dev credentials')\n user.value = {\n displayName: 'developer',\n email: 'developer@hvg.hu',\n roles: ['devadmin'],\n id: '00000000-0000-0000-0000-000000000000',\n }\n state.value = 'authenticated'\n return resolve()\n }\n\n service.whoAmI.successCallback = (userInfo: UserInfoModel) => {\n if (loggingEnabled) {\n console.debug('[currentUserInfo] whoAmI success', {\n displayName: userInfo.displayName,\n email: userInfo.email,\n rolesCount: userInfo.roles?.length ?? 0,\n })\n }\n user.value = userInfo\n state.value = 'authenticated'\n resolve()\n }\n\n service.whoAmI.errorCallback = (err) => {\n if (loggingEnabled) console.error('[currentUserInfo] whoAmI failed:', err)\n error.value = err.message ?? 'Ismeretlen hiba történt'\n state.value = 'error'\n reject(new Error(error.value))\n }\n\n if (loggingEnabled) console.debug('[currentUserInfo] Executing whoAmI request')\n service.whoAmI.execute()\n })\n\n await new Promise<void>((resolve, reject) => {\n service.sites.successCallback = (fetchedSites) => {\n if (loggingEnabled)\n console.debug('[currentUserInfo] sites fetch success', {\n sitesCount: fetchedSites.length,\n })\n sites = fetchedSites\n resolve()\n }\n\n service.sites.errorCallback = (err) => {\n if (loggingEnabled) console.error('[currentUserInfo] sites fetch failed:', err)\n reject(new Error(err.message ?? 'Ismeretlen hiba történt'))\n }\n\n if (loggingEnabled) console.debug('[currentUserInfo] Executing sites request')\n service.sites.execute()\n })\n\n if (loggingEnabled) console.debug('[currentUserInfo] Initialization completed successfully')\n } catch (err) {\n if (loggingEnabled) console.error('[currentUserInfo] initialize failed:', err)\n state.value = 'error'\n if (!error.value) {\n error.value = 'Felhasználói adatok vagy site-ok lekérése sikertelen'\n }\n throw err\n }\n }\n\n function clear(): void {\n if (loggingEnabled) console.debug('[currentUserInfo] clear() called, resetting all state')\n user.value = null\n state.value = 'loading'\n error.value = null\n _backendUrl.value = null\n sites = []\n }\n\n function hasPermission(\n siteId: string,\n entityName: string | 'all',\n accessLevel: 'reader' | 'admin',\n ): boolean {\n if (loggingEnabled)\n console.debug('[currentUserInfo] hasPermission() check', { siteId, entityName, accessLevel })\n\n if (!user.value?.roles || user.value.roles.length === 0) {\n if (loggingEnabled) console.debug('[currentUserInfo] hasPermission() denied: no roles')\n return false\n }\n\n if (user.value.roles.includes('devadmin')) {\n if (loggingEnabled) console.debug('[currentUserInfo] hasPermission() granted: devadmin role')\n return true\n }\n\n const requiredLevels = accessLevel === 'admin' ? ['admin'] : ['reader', 'admin']\n\n for (const level of requiredLevels) {\n const specificRole = `cms-${siteId}-${entityName}-${level}`\n if (user.value.roles.includes(specificRole)) {\n if (loggingEnabled)\n console.debug('[currentUserInfo] hasPermission() granted: specific role', specificRole)\n return true\n }\n\n const allentityRole = `cms-${siteId}-all-${level}`\n if (user.value.roles.includes(allentityRole)) {\n if (loggingEnabled)\n console.debug('[currentUserInfo] hasPermission() granted: all-entity role', allentityRole)\n return true\n }\n }\n\n if (loggingEnabled) console.debug('[currentUserInfo] hasPermission() denied: no matching roles')\n return false\n }\n\n function getMixableSitesForResource(\n entityName: string | 'all',\n currentSiteId: string | undefined,\n ): Site[] {\n if (loggingEnabled)\n console.debug('[currentUserInfo] getMixableSitesForResource() called', {\n entityName,\n currentSiteId,\n })\n\n if (!_backendUrl.value) {\n if (loggingEnabled)\n console.error('[currentUserInfo] getMixableSitesForResource called before initialize')\n throw new Error('Store nincs inicializálva. Hívd meg előbb az initialize() metódust!')\n }\n\n const currentSite = sites.find((site) => site.id === currentSiteId)\n if (loggingEnabled)\n console.debug('[currentUserInfo] Current site lookup', {\n found: !!currentSite,\n totalSites: sites.length,\n })\n\n const mixableSites = [] as Site[]\n sites.forEach((site) => {\n if (currentSite === undefined) {\n if (!hasPermission(site.id, entityName, 'reader')) {\n return\n }\n mixableSites.push(site)\n } else {\n if (\n currentSite.entities.find(\n (e) => e.type === entityName && e.allowedSiteIds.includes(site.id),\n ) === undefined\n ) {\n return\n }\n\n if (!hasPermission(site.id, entityName, 'reader')) {\n return\n }\n\n mixableSites.push(site)\n }\n })\n\n if (loggingEnabled) {\n console.debug('[currentUserInfo] getMixableSitesForResource() result', {\n mixableCount: mixableSites.length,\n mixableSiteIds: mixableSites.map((s) => s.id),\n })\n }\n return mixableSites\n }\n\n function getMixableSiteIdsForResource(\n entityName: string | 'all',\n currentSiteId: string | undefined,\n ): string[] {\n if (loggingEnabled)\n console.debug('[currentUserInfo] getMixableSiteIdsForResource() called', {\n entityName,\n currentSiteId,\n })\n const mixableSites = getMixableSitesForResource(entityName, currentSiteId)\n return mixableSites.map((site) => site.id)\n }\n\n storeInstance = {\n user,\n state,\n error,\n isLoading,\n isAuthenticated,\n displayName,\n email,\n roles,\n initialize,\n clear,\n hasPermission,\n getMixableSitesForResource,\n getMixableSiteIdsForResource,\n }\n\n return storeInstance\n}\n"],"mappings":"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"}
@@ -9,27 +9,41 @@ function o(e, t) {
9
9
  let n = e ? Number.parseFloat(e) : NaN, r = Number.parseFloat(t);
10
10
  return Number.isNaN(n) || n < r ? t : e;
11
11
  }
12
- function s(s, c, l = {}) {
13
- let { extraStyle: u, isOutsideClick: d = a, closeOnScroll: f = !1, minWidth: p = "120px" } = l, m = r(!1), h = r({});
14
- function g() {
15
- if (!s.value) return;
16
- let t = s.value.getBoundingClientRect(), n = u ? u(t) : void 0, r = o(n?.minWidth, p);
17
- h.value = {
12
+ function s(e) {
13
+ let t = e.trim(), n = Number.parseFloat(t);
14
+ if (Number.isNaN(n)) return NaN;
15
+ if (/rem$/i.test(t)) return n * parseFloat(getComputedStyle(document.documentElement).fontSize || "16");
16
+ if (/em$/i.test(t)) {
17
+ let e = document.body || document.documentElement;
18
+ return n * parseFloat(getComputedStyle(e).fontSize || "16");
19
+ }
20
+ return n;
21
+ }
22
+ function c(c, l, u = {}) {
23
+ let { extraStyle: d, isOutsideClick: f = a, closeOnScroll: p = !1, minWidth: m = "120px", maxHeight: h } = u, g = r(!1), _ = r({}), v = r("down");
24
+ function y() {
25
+ if (!c.value) return;
26
+ let t = c.value.getBoundingClientRect(), n = d ? d(t) : void 0, r = o(n?.minWidth, m), i = window.innerHeight, a = i - t.bottom - 2, u = t.top - 2, f = h ? s(h) : NaN, p = !Number.isNaN(f) && a < f && u > a;
27
+ v.value = p ? "up" : "down";
28
+ let g = p ? "auto" : `${t.bottom + 2}px`, y = p ? `${i - t.top + 2}px` : "auto";
29
+ _.value = {
18
30
  position: "fixed",
19
- top: `${t.bottom + 2}px`,
31
+ top: g,
32
+ bottom: y,
20
33
  left: `${t.left}px`,
21
34
  zIndex: "10001",
22
35
  ...n ?? {},
23
36
  ...r ? { minWidth: r } : {}
24
37
  }, e(() => {
25
- if (!c.value || !s.value) return;
26
- let e = c.value.getBoundingClientRect(), t = s.value.getBoundingClientRect(), n = window.innerHeight, r = window.innerWidth, i = e.bottom > n, a = e.right > r, l = i ? `${t.top - e.height - 2}px` : `${t.bottom + 2}px`, d = a ? `${Math.max(t.right - e.width, 0)}px` : `${t.left}px`;
27
- if (i || a) {
28
- let e = u ? u(t) : void 0, n = o(e?.minWidth, p);
29
- h.value = {
38
+ if (!l.value || !c.value) return;
39
+ let e = l.value.getBoundingClientRect(), t = c.value.getBoundingClientRect(), n = window.innerWidth, r = window.innerHeight, i = e.right > n, a = i ? `${Math.max(t.right - e.width, 0)}px` : `${t.left}px`, s = g, u = y;
40
+ if (v.value === "up" && (e.top < 4 ? (s = "4px", u = "auto") : (u = `${r - t.top + 2}px`, s = "auto")), i || s !== g || u !== y) {
41
+ let e = d ? d(t) : void 0, n = o(e?.minWidth, m);
42
+ _.value = {
30
43
  position: "fixed",
31
- top: l,
32
- left: d,
44
+ top: s,
45
+ bottom: u,
46
+ left: a,
33
47
  zIndex: "10001",
34
48
  ...e ?? {},
35
49
  ...n ? { minWidth: n } : {}
@@ -37,29 +51,30 @@ function s(s, c, l = {}) {
37
51
  }
38
52
  });
39
53
  }
40
- function _(e) {
41
- d(e, s.value, c.value) && (m.value = !1);
54
+ function b(e) {
55
+ f(e, c.value, l.value) && (g.value = !1);
42
56
  }
43
- function v() {
44
- if (m.value) {
45
- if (f) {
46
- m.value = !1;
57
+ function x() {
58
+ if (g.value) {
59
+ if (p) {
60
+ g.value = !1;
47
61
  return;
48
62
  }
49
- g();
63
+ y();
50
64
  }
51
65
  }
52
- return i(m, (e) => {
53
- e && g();
66
+ return i(g, (e) => {
67
+ e && y();
54
68
  }), n(() => {
55
- document.addEventListener("mousedown", _), window.addEventListener("scroll", v, !0), window.addEventListener("resize", v);
69
+ document.addEventListener("mousedown", b), window.addEventListener("scroll", x, !0), window.addEventListener("resize", x);
56
70
  }), t(() => {
57
- document.removeEventListener("mousedown", _), window.removeEventListener("scroll", v, !0), window.removeEventListener("resize", v);
71
+ document.removeEventListener("mousedown", b), window.removeEventListener("scroll", x, !0), window.removeEventListener("resize", x);
58
72
  }), {
59
- isOpen: m,
60
- dropdownStyle: h,
61
- positionDropdown: g
73
+ isOpen: g,
74
+ dropdownStyle: _,
75
+ positionDropdown: y,
76
+ placement: v
62
77
  };
63
78
  }
64
79
  //#endregion
65
- export { s as useDropdownAnchor };
80
+ export { c as useDropdownAnchor };
@@ -1 +1 @@
1
- {"version":3,"file":"admins-components12.js","names":[],"sources":["../src/composables/useDropdownAnchor.ts"],"sourcesContent":["import { ref, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'\nimport type { Ref } from 'vue'\n\nexport interface UseDropdownAnchorOptions {\n extraStyle?: (rect: DOMRect) => Record<string, string>\n isOutsideClick?: (\n e: MouseEvent,\n wrapperEl: HTMLElement | null,\n dropdownEl: HTMLElement | null,\n ) => boolean\n closeOnScroll?: boolean\n minWidth?: string | null\n}\n\nexport interface UseDropdownAnchorReturn {\n isOpen: Ref<boolean>\n dropdownStyle: Ref<Record<string, string>>\n positionDropdown: () => void\n}\n\nfunction defaultIsOutsideClick(\n e: MouseEvent,\n wrapperEl: HTMLElement | null,\n dropdownEl: HTMLElement | null,\n): boolean {\n const target = e.target as Node\n const inWrapper = wrapperEl?.contains(target) ?? false\n const inDropdown = dropdownEl?.contains(target) ?? false\n return !inWrapper && !inDropdown\n}\n\nfunction pickMinWidth(extraMinWidth: string | undefined, floor: string | null): string | null {\n if (!floor) return extraMinWidth ?? null\n const extraPx = extraMinWidth ? Number.parseFloat(extraMinWidth) : Number.NaN\n const floorPx = Number.parseFloat(floor)\n if (Number.isNaN(extraPx) || extraPx < floorPx) return floor\n return extraMinWidth!\n}\n\nexport function useDropdownAnchor(\n wrapperRef: Ref<HTMLElement | null>,\n dropdownRef: Ref<HTMLElement | null>,\n options: UseDropdownAnchorOptions = {},\n): UseDropdownAnchorReturn {\n const {\n extraStyle,\n isOutsideClick = defaultIsOutsideClick,\n closeOnScroll = false,\n minWidth = '120px',\n } = options\n\n const isOpen = ref(false)\n const dropdownStyle = ref<Record<string, string>>({})\n\n function positionDropdown() {\n if (!wrapperRef.value) return\n const rect = wrapperRef.value.getBoundingClientRect()\n const extraStyleValues = extraStyle ? extraStyle(rect) : undefined\n const effectiveMinWidth = pickMinWidth(extraStyleValues?.minWidth, minWidth)\n\n dropdownStyle.value = {\n position: 'fixed',\n top: `${rect.bottom + 2}px`,\n left: `${rect.left}px`,\n zIndex: '10001',\n ...(extraStyleValues ?? {}),\n ...(effectiveMinWidth ? { minWidth: effectiveMinWidth } : {}),\n }\n nextTick(() => {\n if (!dropdownRef.value || !wrapperRef.value) return\n const dropdownRect = dropdownRef.value.getBoundingClientRect()\n const anchorRect = wrapperRef.value.getBoundingClientRect()\n const viewportHeight = window.innerHeight\n const viewportWidth = window.innerWidth\n\n const flipY = dropdownRect.bottom > viewportHeight\n const flipX = dropdownRect.right > viewportWidth\n\n const top = flipY\n ? `${anchorRect.top - dropdownRect.height - 2}px`\n : `${anchorRect.bottom + 2}px`\n const left = flipX\n ? `${Math.max(anchorRect.right - dropdownRect.width, 0)}px`\n : `${anchorRect.left}px`\n\n if (flipY || flipX) {\n const flippedExtras = extraStyle ? extraStyle(anchorRect) : undefined\n const flippedMinWidth = pickMinWidth(flippedExtras?.minWidth, minWidth)\n dropdownStyle.value = {\n position: 'fixed',\n top,\n left,\n zIndex: '10001',\n ...(flippedExtras ?? {}),\n ...(flippedMinWidth ? { minWidth: flippedMinWidth } : {}),\n }\n }\n })\n }\n\n function onClickOutside(e: MouseEvent) {\n if (isOutsideClick(e, wrapperRef.value, dropdownRef.value)) {\n isOpen.value = false\n }\n }\n\n function onScrollOrResize() {\n if (!isOpen.value) return\n if (closeOnScroll) {\n isOpen.value = false\n return\n }\n positionDropdown()\n }\n\n watch(isOpen, (open) => {\n if (open) positionDropdown()\n })\n\n onMounted(() => {\n document.addEventListener('mousedown', onClickOutside)\n\n window.addEventListener('scroll', onScrollOrResize, true)\n window.addEventListener('resize', onScrollOrResize)\n })\n\n onBeforeUnmount(() => {\n document.removeEventListener('mousedown', onClickOutside)\n\n window.removeEventListener('scroll', onScrollOrResize, true)\n window.removeEventListener('resize', onScrollOrResize)\n })\n\n return { isOpen, dropdownStyle, positionDropdown }\n}\n"],"mappings":";;AAoBA,SAAS,EACP,GACA,GACA,GACS;CACT,IAAM,IAAS,EAAE,QACX,IAAY,GAAW,SAAS,CAAM,KAAK,IAC3C,IAAa,GAAY,SAAS,CAAM,KAAK;CACnD,OAAO,CAAC,KAAa,CAAC;AACxB;AAEA,SAAS,EAAa,GAAmC,GAAqC;CAC5F,IAAI,CAAC,GAAO,OAAO,KAAiB;CACpC,IAAM,IAAU,IAAgB,OAAO,WAAW,CAAa,IAAI,KAC7D,IAAU,OAAO,WAAW,CAAK;CAEvC,OADI,OAAO,MAAM,CAAO,KAAK,IAAU,IAAgB,IAChD;AACT;AAEA,SAAgB,EACd,GACA,GACA,IAAoC,CAAC,GACZ;CACzB,IAAM,EACJ,eACA,oBAAiB,GACjB,mBAAgB,IAChB,cAAW,YACT,GAEE,IAAS,EAAI,EAAK,GAClB,IAAgB,EAA4B,CAAC,CAAC;CAEpD,SAAS,IAAmB;EAC1B,IAAI,CAAC,EAAW,OAAO;EACvB,IAAM,IAAO,EAAW,MAAM,sBAAsB,GAC9C,IAAmB,IAAa,EAAW,CAAI,IAAI,KAAA,GACnD,IAAoB,EAAa,GAAkB,UAAU,CAAQ;EAU3E,AARA,EAAc,QAAQ;GACpB,UAAU;GACV,KAAK,GAAG,EAAK,SAAS,EAAE;GACxB,MAAM,GAAG,EAAK,KAAK;GACnB,QAAQ;GACR,GAAI,KAAoB,CAAC;GACzB,GAAI,IAAoB,EAAE,UAAU,EAAkB,IAAI,CAAC;EAC7D,GACA,QAAe;GACb,IAAI,CAAC,EAAY,SAAS,CAAC,EAAW,OAAO;GAC7C,IAAM,IAAe,EAAY,MAAM,sBAAsB,GACvD,IAAa,EAAW,MAAM,sBAAsB,GACpD,IAAiB,OAAO,aACxB,IAAgB,OAAO,YAEvB,IAAQ,EAAa,SAAS,GAC9B,IAAQ,EAAa,QAAQ,GAE7B,IAAM,IACR,GAAG,EAAW,MAAM,EAAa,SAAS,EAAE,MAC5C,GAAG,EAAW,SAAS,EAAE,KACvB,IAAO,IACT,GAAG,KAAK,IAAI,EAAW,QAAQ,EAAa,OAAO,CAAC,EAAE,MACtD,GAAG,EAAW,KAAK;GAEvB,IAAI,KAAS,GAAO;IAClB,IAAM,IAAgB,IAAa,EAAW,CAAU,IAAI,KAAA,GACtD,IAAkB,EAAa,GAAe,UAAU,CAAQ;IACtE,EAAc,QAAQ;KACpB,UAAU;KACV;KACA;KACA,QAAQ;KACR,GAAI,KAAiB,CAAC;KACtB,GAAI,IAAkB,EAAE,UAAU,EAAgB,IAAI,CAAC;IACzD;GACF;EACF,CAAC;CACH;CAEA,SAAS,EAAe,GAAe;EACrC,AAAI,EAAe,GAAG,EAAW,OAAO,EAAY,KAAK,MACvD,EAAO,QAAQ;CAEnB;CAEA,SAAS,IAAmB;EACrB,MAAO,OACZ;OAAI,GAAe;IACjB,EAAO,QAAQ;IACf;GACF;GACA,EAAiB;EADjB;CAEF;CAoBA,OAlBA,EAAM,IAAS,MAAS;EACtB,AAAI,KAAM,EAAiB;CAC7B,CAAC,GAED,QAAgB;EAId,AAHA,SAAS,iBAAiB,aAAa,CAAc,GAErD,OAAO,iBAAiB,UAAU,GAAkB,EAAI,GACxD,OAAO,iBAAiB,UAAU,CAAgB;CACpD,CAAC,GAED,QAAsB;EAIpB,AAHA,SAAS,oBAAoB,aAAa,CAAc,GAExD,OAAO,oBAAoB,UAAU,GAAkB,EAAI,GAC3D,OAAO,oBAAoB,UAAU,CAAgB;CACvD,CAAC,GAEM;EAAE;EAAQ;EAAe;CAAiB;AACnD"}
1
+ {"version":3,"file":"admins-components12.js","names":[],"sources":["../src/composables/useDropdownAnchor.ts"],"sourcesContent":["import { ref, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'\nimport type { Ref } from 'vue'\n\nexport interface UseDropdownAnchorOptions {\n extraStyle?: (rect: DOMRect) => Record<string, string>\n isOutsideClick?: (\n e: MouseEvent,\n wrapperEl: HTMLElement | null,\n dropdownEl: HTMLElement | null,\n ) => boolean\n closeOnScroll?: boolean\n minWidth?: string | null\n maxHeight?: string\n}\n\nexport interface UseDropdownAnchorReturn {\n isOpen: Ref<boolean>\n dropdownStyle: Ref<Record<string, string>>\n positionDropdown: () => void\n placement: Ref<'down' | 'up'>\n}\n\nfunction defaultIsOutsideClick(\n e: MouseEvent,\n wrapperEl: HTMLElement | null,\n dropdownEl: HTMLElement | null,\n): boolean {\n const target = e.target as Node\n const inWrapper = wrapperEl?.contains(target) ?? false\n const inDropdown = dropdownEl?.contains(target) ?? false\n return !inWrapper && !inDropdown\n}\n\nfunction pickMinWidth(extraMinWidth: string | undefined, floor: string | null): string | null {\n if (!floor) return extraMinWidth ?? null\n const extraPx = extraMinWidth ? Number.parseFloat(extraMinWidth) : Number.NaN\n const floorPx = Number.parseFloat(floor)\n if (Number.isNaN(extraPx) || extraPx < floorPx) return floor\n return extraMinWidth!\n}\n\nfunction cssLengthToPx(value: string): number {\n const trimmed = value.trim()\n const num = Number.parseFloat(trimmed)\n if (Number.isNaN(num)) return Number.NaN\n if (/rem$/i.test(trimmed)) return num * parseFloat(getComputedStyle(document.documentElement).fontSize || '16')\n if (/em$/i.test(trimmed)) {\n const el = document.body || document.documentElement\n return num * parseFloat(getComputedStyle(el).fontSize || '16')\n }\n\n return num\n}\n\nexport function useDropdownAnchor(\n wrapperRef: Ref<HTMLElement | null>,\n dropdownRef: Ref<HTMLElement | null>,\n options: UseDropdownAnchorOptions = {},\n): UseDropdownAnchorReturn {\n const {\n extraStyle,\n isOutsideClick = defaultIsOutsideClick,\n closeOnScroll = false,\n minWidth = '120px',\n maxHeight,\n } = options\n\n const isOpen = ref(false)\n const dropdownStyle = ref<Record<string, string>>({})\n const placement = ref<'down' | 'up'>('down')\n\n function positionDropdown() {\n if (!wrapperRef.value) return\n const rect = wrapperRef.value.getBoundingClientRect()\n const extraStyleValues = extraStyle ? extraStyle(rect) : undefined\n const effectiveMinWidth = pickMinWidth(extraStyleValues?.minWidth, minWidth)\n\n const viewportHeight = window.innerHeight\n const spaceBelow = viewportHeight - rect.bottom - 2\n const spaceAbove = rect.top - 2\n const maxHeightPx = maxHeight ? cssLengthToPx(maxHeight) : Number.NaN\n const openUp =\n !Number.isNaN(maxHeightPx) && spaceBelow < maxHeightPx && spaceAbove > spaceBelow\n\n placement.value = openUp ? 'up' : 'down'\n\n const initialTop = openUp ? 'auto' : `${rect.bottom + 2}px`\n const initialBottom = openUp\n ? `${viewportHeight - rect.top + 2}px`\n : 'auto'\n\n dropdownStyle.value = {\n position: 'fixed',\n top: initialTop,\n bottom: initialBottom,\n left: `${rect.left}px`,\n zIndex: '10001',\n ...(extraStyleValues ?? {}),\n ...(effectiveMinWidth ? { minWidth: effectiveMinWidth } : {}),\n }\n nextTick(() => {\n if (!dropdownRef.value || !wrapperRef.value) return\n const dropdownRect = dropdownRef.value.getBoundingClientRect()\n const anchorRect = wrapperRef.value.getBoundingClientRect()\n const viewportWidth = window.innerWidth\n const vpHeight = window.innerHeight\n\n const flipX = dropdownRect.right > viewportWidth\n\n const left = flipX\n ? `${Math.max(anchorRect.right - dropdownRect.width, 0)}px`\n : `${anchorRect.left}px`\n\n let top = initialTop\n let bottom = initialBottom\n\n if (placement.value === 'up') {\n const minTop = 4\n if (dropdownRect.top < minTop) {\n top = `${minTop}px`\n bottom = 'auto'\n }\n else {\n bottom = `${vpHeight - anchorRect.top + 2}px`\n top = 'auto'\n }\n }\n\n if (flipX || top !== initialTop || bottom !== initialBottom) {\n const snappedExtras = extraStyle ? extraStyle(anchorRect) : undefined\n const snappedMinWidth = pickMinWidth(snappedExtras?.minWidth, minWidth)\n dropdownStyle.value = {\n position: 'fixed',\n top,\n bottom,\n left,\n zIndex: '10001',\n ...(snappedExtras ?? {}),\n ...(snappedMinWidth ? { minWidth: snappedMinWidth } : {}),\n }\n }\n })\n }\n\n function onClickOutside(e: MouseEvent) {\n if (isOutsideClick(e, wrapperRef.value, dropdownRef.value)) {\n isOpen.value = false\n }\n }\n\n function onScrollOrResize() {\n if (!isOpen.value) return\n if (closeOnScroll) {\n isOpen.value = false\n return\n }\n positionDropdown()\n }\n\n watch(isOpen, (open) => {\n if (open) positionDropdown()\n })\n\n onMounted(() => {\n document.addEventListener('mousedown', onClickOutside)\n\n window.addEventListener('scroll', onScrollOrResize, true)\n window.addEventListener('resize', onScrollOrResize)\n })\n\n onBeforeUnmount(() => {\n document.removeEventListener('mousedown', onClickOutside)\n\n window.removeEventListener('scroll', onScrollOrResize, true)\n window.removeEventListener('resize', onScrollOrResize)\n })\n\n return { isOpen, dropdownStyle, positionDropdown, placement }\n}\n"],"mappings":";;AAsBA,SAAS,EACP,GACA,GACA,GACS;CACT,IAAM,IAAS,EAAE,QACX,IAAY,GAAW,SAAS,CAAM,KAAK,IAC3C,IAAa,GAAY,SAAS,CAAM,KAAK;CACnD,OAAO,CAAC,KAAa,CAAC;AACxB;AAEA,SAAS,EAAa,GAAmC,GAAqC;CAC5F,IAAI,CAAC,GAAO,OAAO,KAAiB;CACpC,IAAM,IAAU,IAAgB,OAAO,WAAW,CAAa,IAAI,KAC7D,IAAU,OAAO,WAAW,CAAK;CAEvC,OADI,OAAO,MAAM,CAAO,KAAK,IAAU,IAAgB,IAChD;AACT;AAEA,SAAS,EAAc,GAAuB;CAC5C,IAAM,IAAU,EAAM,KAAK,GACrB,IAAM,OAAO,WAAW,CAAO;CACrC,IAAI,OAAO,MAAM,CAAG,GAAG,OAAO;CAC9B,IAAI,QAAQ,KAAK,CAAO,GAAG,OAAO,IAAM,WAAW,iBAAiB,SAAS,eAAe,CAAC,CAAC,YAAY,IAAI;CAC9G,IAAI,OAAO,KAAK,CAAO,GAAG;EACxB,IAAM,IAAK,SAAS,QAAQ,SAAS;EACrC,OAAO,IAAM,WAAW,iBAAiB,CAAE,CAAC,CAAC,YAAY,IAAI;CAC/D;CAEA,OAAO;AACT;AAEA,SAAgB,EACd,GACA,GACA,IAAoC,CAAC,GACZ;CACzB,IAAM,EACJ,eACA,oBAAiB,GACjB,mBAAgB,IAChB,cAAW,SACX,iBACE,GAEE,IAAS,EAAI,EAAK,GAClB,IAAgB,EAA4B,CAAC,CAAC,GAC9C,IAAY,EAAmB,MAAM;CAE3C,SAAS,IAAmB;EAC1B,IAAI,CAAC,EAAW,OAAO;EACvB,IAAM,IAAO,EAAW,MAAM,sBAAsB,GAC9C,IAAmB,IAAa,EAAW,CAAI,IAAI,KAAA,GACnD,IAAoB,EAAa,GAAkB,UAAU,CAAQ,GAErE,IAAiB,OAAO,aACxB,IAAa,IAAiB,EAAK,SAAS,GAC5C,IAAa,EAAK,MAAM,GACxB,IAAc,IAAY,EAAc,CAAS,IAAI,KACrD,IACJ,CAAC,OAAO,MAAM,CAAW,KAAK,IAAa,KAAe,IAAa;EAEzE,EAAU,QAAQ,IAAS,OAAO;EAElC,IAAM,IAAa,IAAS,SAAS,GAAG,EAAK,SAAS,EAAE,KAClD,IAAgB,IAClB,GAAG,IAAiB,EAAK,MAAM,EAAE,MACjC;EAWJ,AATA,EAAc,QAAQ;GACpB,UAAU;GACV,KAAK;GACL,QAAQ;GACR,MAAM,GAAG,EAAK,KAAK;GACnB,QAAQ;GACR,GAAI,KAAoB,CAAC;GACzB,GAAI,IAAoB,EAAE,UAAU,EAAkB,IAAI,CAAC;EAC7D,GACA,QAAe;GACb,IAAI,CAAC,EAAY,SAAS,CAAC,EAAW,OAAO;GAC7C,IAAM,IAAe,EAAY,MAAM,sBAAsB,GACvD,IAAa,EAAW,MAAM,sBAAsB,GACpD,IAAgB,OAAO,YACvB,IAAW,OAAO,aAElB,IAAQ,EAAa,QAAQ,GAE7B,IAAO,IACT,GAAG,KAAK,IAAI,EAAW,QAAQ,EAAa,OAAO,CAAC,EAAE,MACtD,GAAG,EAAW,KAAK,KAEnB,IAAM,GACN,IAAS;GAcb,IAZI,EAAU,UAAU,SAElB,EAAa,MAAM,KACrB,IAAM,OACN,IAAS,WAGT,IAAS,GAAG,IAAW,EAAW,MAAM,EAAE,KAC1C,IAAM,UAIN,KAAS,MAAQ,KAAc,MAAW,GAAe;IAC3D,IAAM,IAAgB,IAAa,EAAW,CAAU,IAAI,KAAA,GACtD,IAAkB,EAAa,GAAe,UAAU,CAAQ;IACtE,EAAc,QAAQ;KACpB,UAAU;KACV;KACA;KACA;KACA,QAAQ;KACR,GAAI,KAAiB,CAAC;KACtB,GAAI,IAAkB,EAAE,UAAU,EAAgB,IAAI,CAAC;IACzD;GACF;EACF,CAAC;CACH;CAEA,SAAS,EAAe,GAAe;EACrC,AAAI,EAAe,GAAG,EAAW,OAAO,EAAY,KAAK,MACvD,EAAO,QAAQ;CAEnB;CAEA,SAAS,IAAmB;EACrB,MAAO,OACZ;OAAI,GAAe;IACjB,EAAO,QAAQ;IACf;GACF;GACA,EAAiB;EADjB;CAEF;CAoBA,OAlBA,EAAM,IAAS,MAAS;EACtB,AAAI,KAAM,EAAiB;CAC7B,CAAC,GAED,QAAgB;EAId,AAHA,SAAS,iBAAiB,aAAa,CAAc,GAErD,OAAO,iBAAiB,UAAU,GAAkB,EAAI,GACxD,OAAO,iBAAiB,UAAU,CAAgB;CACpD,CAAC,GAED,QAAsB;EAIpB,AAHA,SAAS,oBAAoB,aAAa,CAAc,GAExD,OAAO,oBAAoB,UAAU,GAAkB,EAAI,GAC3D,OAAO,oBAAoB,UAAU,CAAgB;CACvD,CAAC,GAEM;EAAE;EAAQ;EAAe;EAAkB;CAAU;AAC9D"}
@@ -1 +1 @@
1
- {"version":3,"file":"admins-components13.js","names":[],"sources":["../src/components/DatePicker.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { PickedDate } from '@/types/types'\nimport { datePickerConfigDefaults, type DatePickerConfig } from '@/types/datepickers'\n\nexport { datePickerConfigDefaults, type DatePickerConfig, type PickedDate }\n\nexport interface DatePickerProps {\n modelValue?: PickedDate | null\n config: DatePickerConfig\n id?: string\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick, useId } from 'vue'\nimport Calendar from '@/components/Calendar.vue'\nimport { formatDate, parseDate, localToUTCString, castToDate } from '@/utils/date'\nimport { useDropdownAnchor } from '@/composables/useDropdownAnchor'\n\nconst props = withDefaults(defineProps<DatePickerProps>(), {\n modelValue: null,\n config: () => ({\n ...datePickerConfigDefaults,\n }),\n id: () => `dp-input-${useId()}`,\n})\n\nconst innerConfig = computed(() => ({\n ...datePickerConfigDefaults,\n ...props.config,\n}))\n\nconst emit = defineEmits<{ 'update:modelValue': [value: PickedDate | null] }>()\n\nconst wrapperRef = ref<HTMLElement | null>(null)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst { isOpen, dropdownStyle } = useDropdownAnchor(wrapperRef, dropdownRef)\nconst inputRef = ref<HTMLInputElement | null>(null)\nconst DIGITS = 'YMDHms'\nconst format = computed(\n () =>\n innerConfig.value.format ?? (innerConfig.value.showTime ? 'YYYY-MM-DD HH:mm' : 'YYYY-MM-DD'),\n)\n\nconst inputValue = ref(\n castToDate(props.modelValue?.local ?? props.modelValue?.utc)\n ? formatDate(castToDate(props.modelValue?.local ?? props.modelValue?.utc)!, format.value)\n : '',\n)\nwatch(\n () => props.modelValue,\n (v) => {\n const d = castToDate(v?.local ?? v?.utc)\n inputValue.value = d ? formatDate(d, format.value) : ''\n },\n)\n\nfunction mask(digits: string): string {\n let r = '',\n di = 0\n for (let i = 0; i < format.value.length && di < digits.length; i++)\n r += DIGITS.includes(format.value[i]!) ? digits[di++] : format.value[i]\n return r\n}\n\nfunction fill(partial: string): string {\n let r = partial\n for (let i = r.length; i < format.value.length; i++)\n r += DIGITS.includes(format.value[i]!) ? '0' : format.value[i]\n return r\n}\n\nfunction valid(val: string): boolean {\n if (val.length !== format.value.length) return false\n for (let i = 0; i < format.value.length; i++) {\n if (DIGITS.includes(format.value[i]!)) {\n if (!/\\d/.test(val[i]!)) return false\n } else if (val[i] !== format.value[i]) return false\n }\n return true\n}\n\nfunction emitParsed(val: string | null) {\n if (!val) {\n inputValue.value = ''\n emit('update:modelValue', null)\n return\n }\n inputValue.value = val\n const local = parseDate(val, format.value)\n emit(\n 'update:modelValue',\n local ? { local, utc: localToUTCString(local, innerConfig.value.showTime) } : null,\n )\n}\n\n// Input handling\nfunction onInput(e: Event) {\n const el = e.target as HTMLInputElement\n const cursor = el.selectionStart ?? 0\n const raw = el.value.replace(/\\D/g, '')\n isOpen.value = false\n\n if (!raw) {\n emitParsed(null)\n el.value = ''\n return\n }\n\n let masked = mask(raw)\n if (masked.length < format.value.length && !DIGITS.includes(format.value[masked.length]!))\n masked += format.value[masked.length]\n\n // Auto-fill time zeros when date portion is complete\n if (\n innerConfig.value.showTime &&\n masked.length >= 10 &&\n masked.length < format.value.length &&\n masked.replace(/\\D/g, '').length <= 8\n ) {\n const filled = fill(masked)\n el.value = filled\n inputValue.value = filled\n const pos = Math.min(cursor, masked.length)\n nextTick(() => el.setSelectionRange(pos, pos))\n if (valid(filled)) emitParsed(filled)\n return\n }\n\n el.value = masked\n inputValue.value = masked\n let pos = Math.min(cursor, masked.length)\n while (pos < masked.length && !DIGITS.includes(format.value[pos]!)) pos++\n nextTick(() => el.setSelectionRange(pos, pos))\n if (valid(masked)) emitParsed(masked)\n}\n\nfunction onBlur() {\n if (inputValue.value && !valid(inputValue.value))\n inputValue.value = props.modelValue?.local\n ? formatDate(props.modelValue.local, format.value)\n : ''\n}\n\nfunction onKeydown(e: KeyboardEvent) {\n if (e.ctrlKey || e.metaKey) return\n if (\n !['Backspace', 'Delete', 'Tab', 'ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(e.key) &&\n !/^\\d$/.test(e.key)\n )\n e.preventDefault()\n}\n\nfunction onCalendarUpdate(val: string | null) {\n emitParsed(val)\n if (!innerConfig.value.showTime) isOpen.value = false\n}\n\nfunction focusAndOpen() {\n isOpen.value = true\n nextTick(() => inputRef.value?.focus())\n}\n\ndefineExpose({ focusAndOpen })\n</script>\n\n<template>\n <div class=\"ac-component\">\n <div ref=\"wrapperRef\" class=\"drp-wrapper\">\n <div\n class=\"c-input-row\"\n :class=\"{\n 'c-input-row--sm': innerConfig.size === 'small',\n 'c-input-row--lg': innerConfig.size === 'large',\n }\"\n >\n <input\n ref=\"inputRef\"\n type=\"text\"\n :id=\"id\"\n class=\"c-input dp-input pr-0\"\n inputmode=\"numeric\"\n :value=\"inputValue\"\n :placeholder=\"innerConfig.placeholder\"\n :maxlength=\"format.length\"\n @input=\"onInput\"\n @blur=\"onBlur\"\n @keydown=\"onKeydown\"\n />\n <button\n type=\"button\"\n class=\"c-icon-btn dp-clear c-icon-btn--clear\"\n :class=\"{ 'c-icon-btn--hidden': !inputValue }\"\n @click=\"emitParsed(null)\"\n aria-label=\"Törlés\"\n >\n <i class=\"fa-solid fa-fw fa-xmark\"></i>\n </button>\n <button\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--calendar\"\n @click=\"isOpen = !isOpen\"\n aria-label=\"Naptár megnyitása\"\n >\n <i class=\"fa-regular fa-fw fa-calendar\"></i>\n </button>\n </div>\n <Teleport to=\"body\">\n <div v-if=\"isOpen\" ref=\"dropdownRef\" class=\"c-dropdown ac-component\" :style=\"dropdownStyle\">\n <Calendar\n :model-value=\"inputValue || null\"\n :config=\"innerConfig\"\n @update:model-value=\"onCalendarUpdate\"\n @confirm=\"isOpen = false\"\n />\n </div>\n </Teleport>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"admins-components13.js","names":[],"sources":["../src/components/DatePicker.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { PickedDate } from '@/types/types'\nimport { datePickerConfigDefaults, type DatePickerConfig } from '@/types/datepickers'\n\nexport { datePickerConfigDefaults, type DatePickerConfig, type PickedDate }\n\nexport interface DatePickerProps {\n modelValue?: PickedDate | null\n config: DatePickerConfig\n id?: string\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick, useId } from 'vue'\nimport Calendar from '@/components/Calendar.vue'\nimport { formatDate, parseDate, localToUTCString, castToDate } from '@/utils/date'\nimport { useDropdownAnchor } from '@/composables/useDropdownAnchor'\n\nconst props = withDefaults(defineProps<DatePickerProps>(), {\n modelValue: null,\n config: () => ({\n ...datePickerConfigDefaults,\n }),\n id: () => `dp-input-${useId()}`,\n})\n\nconst innerConfig = computed(() => ({\n ...datePickerConfigDefaults,\n ...props.config,\n}))\n\nconst emit = defineEmits<{ 'update:modelValue': [value: PickedDate | null] }>()\n\nconst wrapperRef = ref<HTMLElement | null>(null)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst { isOpen, dropdownStyle } = useDropdownAnchor(wrapperRef, dropdownRef)\nconst inputRef = ref<HTMLInputElement | null>(null)\nconst DIGITS = 'YMDHms'\nconst format = computed(\n () =>\n innerConfig.value.format ?? (innerConfig.value.showTime ? 'YYYY-MM-DD HH:mm' : 'YYYY-MM-DD'),\n)\n\nconst inputValue = ref(\n castToDate(props.modelValue?.local ?? props.modelValue?.utc)\n ? formatDate(castToDate(props.modelValue?.local ?? props.modelValue?.utc)!, format.value)\n : '',\n)\nwatch(\n () => props.modelValue,\n (v) => {\n const d = castToDate(v?.local ?? v?.utc)\n inputValue.value = d ? formatDate(d, format.value) : ''\n },\n)\n\nfunction mask(digits: string): string {\n let r = '',\n di = 0\n for (let i = 0; i < format.value.length && di < digits.length; i++)\n r += DIGITS.includes(format.value[i]!) ? digits[di++] : format.value[i]\n return r\n}\n\nfunction fill(partial: string): string {\n let r = partial\n for (let i = r.length; i < format.value.length; i++)\n r += DIGITS.includes(format.value[i]!) ? '0' : format.value[i]\n return r\n}\n\nfunction valid(val: string): boolean {\n if (val.length !== format.value.length) return false\n for (let i = 0; i < format.value.length; i++) {\n if (DIGITS.includes(format.value[i]!)) {\n if (!/\\d/.test(val[i]!)) return false\n } else if (val[i] !== format.value[i]) return false\n }\n return true\n}\n\nfunction emitParsed(val: string | null) {\n if (!val) {\n inputValue.value = ''\n emit('update:modelValue', null)\n return\n }\n inputValue.value = val\n const local = parseDate(val, format.value)\n emit(\n 'update:modelValue',\n local ? { local, utc: localToUTCString(local, innerConfig.value.showTime) } : null,\n )\n}\n\nfunction onInput(e: Event) {\n const el = e.target as HTMLInputElement\n const cursor = el.selectionStart ?? 0\n const raw = el.value.replace(/\\D/g, '')\n isOpen.value = false\n\n if (!raw) {\n emitParsed(null)\n el.value = ''\n return\n }\n\n let masked = mask(raw)\n if (masked.length < format.value.length && !DIGITS.includes(format.value[masked.length]!))\n masked += format.value[masked.length]\n\n if (\n innerConfig.value.showTime &&\n masked.length >= 10 &&\n masked.length < format.value.length &&\n masked.replace(/\\D/g, '').length <= 8\n ) {\n const filled = fill(masked)\n el.value = filled\n inputValue.value = filled\n const pos = Math.min(cursor, masked.length)\n nextTick(() => el.setSelectionRange(pos, pos))\n if (valid(filled)) emitParsed(filled)\n return\n }\n\n el.value = masked\n inputValue.value = masked\n let pos = Math.min(cursor, masked.length)\n while (pos < masked.length && !DIGITS.includes(format.value[pos]!)) pos++\n nextTick(() => el.setSelectionRange(pos, pos))\n if (valid(masked)) emitParsed(masked)\n}\n\nfunction onBlur() {\n if (inputValue.value && !valid(inputValue.value))\n inputValue.value = props.modelValue?.local\n ? formatDate(props.modelValue.local, format.value)\n : ''\n}\n\nfunction onKeydown(e: KeyboardEvent) {\n if (e.ctrlKey || e.metaKey) return\n if (\n !['Backspace', 'Delete', 'Tab', 'ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(e.key) &&\n !/^\\d$/.test(e.key)\n )\n e.preventDefault()\n}\n\nfunction onCalendarUpdate(val: string | null) {\n emitParsed(val)\n if (!innerConfig.value.showTime) isOpen.value = false\n}\n\nfunction focusAndOpen() {\n isOpen.value = true\n nextTick(() => inputRef.value?.focus())\n}\n\ndefineExpose({ focusAndOpen })\n</script>\n\n<template>\n <div class=\"ac-component\">\n <div ref=\"wrapperRef\" class=\"drp-wrapper\">\n <div\n class=\"c-input-row\"\n :class=\"{\n 'c-input-row--sm': innerConfig.size === 'small',\n 'c-input-row--lg': innerConfig.size === 'large',\n }\"\n >\n <input\n ref=\"inputRef\"\n type=\"text\"\n :id=\"id\"\n class=\"c-input dp-input pr-0\"\n inputmode=\"numeric\"\n :value=\"inputValue\"\n :placeholder=\"innerConfig.placeholder\"\n :maxlength=\"format.length\"\n @input=\"onInput\"\n @blur=\"onBlur\"\n @keydown=\"onKeydown\"\n />\n <button\n type=\"button\"\n class=\"c-icon-btn dp-clear c-icon-btn--clear\"\n :class=\"{ 'c-icon-btn--hidden': !inputValue }\"\n @click=\"emitParsed(null)\"\n aria-label=\"Törlés\"\n >\n <i class=\"fa-solid fa-fw fa-xmark\"></i>\n </button>\n <button\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--calendar\"\n @click=\"isOpen = !isOpen\"\n aria-label=\"Naptár megnyitása\"\n >\n <i class=\"fa-regular fa-fw fa-calendar\"></i>\n </button>\n </div>\n <Teleport to=\"body\">\n <div v-if=\"isOpen\" ref=\"dropdownRef\" class=\"c-dropdown ac-component\" :style=\"dropdownStyle\">\n <Calendar\n :model-value=\"inputValue || null\"\n :config=\"innerConfig\"\n @update:model-value=\"onCalendarUpdate\"\n @confirm=\"isOpen = false\"\n />\n </div>\n </Teleport>\n </div>\n </div>\n</template>\n"],"mappings":"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"}