From f8010659c4878d4fcef79937be6cec11955f2b7a Mon Sep 17 00:00:00 2001 From: Legacy <52163001+3m1n3nc3@users.noreply.github.com> Date: Sat, 30 Sep 2023 06:58:09 +0100 Subject: [PATCH 1/5] Add support for Vite --- ui/src/components/QIconPicker.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/ui/src/components/QIconPicker.js b/ui/src/components/QIconPicker.js index 4508bc3..4d01148 100644 --- a/ui/src/components/QIconPicker.js +++ b/ui/src/components/QIconPicker.js @@ -142,7 +142,7 @@ function useIconPickerPagination(data, props, emit, computedFilteredIcons) { */ function useIconPickerIcons(data, props, computedFirstItemIndex, computedLastItemIndex) { - function loadIconSet(iconSet) { + async function loadIconSet (iconSet) { data.iconsList = [] if (iconSet) { // detect if UMD version is installed @@ -157,12 +157,18 @@ function useIconPickerIcons(data, props, computedFirstItemIndex, computedLastIte } } else { - try { - data.iconsList = require(`@quasar/quasar-ui-qiconpicker/src/components/icon-set/${ iconSet }.js`).default.icons - } - catch (e) { - console.error(`QIconPicker: cannot find icon set found called ${ iconSet }`) - } + // If vite + if (typeof import.meta !== 'undefined' && import.meta.env !== undefined) { + const set = await import( + `/node_modules/@quasar/quasar-ui-qiconpicker/src/components/icon-set/material-icons.js` + ) + data.iconsList = set.default.icons + // Else if webpack + } else { + data.iconsList = require( + `@quasar/quasar-ui-qiconpicker/src/components/icon-set/${iconSet}.js`, + ).default.icons; + } } } console.info(`Loaded ${ data.iconsList.length } icons.`) From 0af7a582d9c18806c3f00d03104d22ea10953033 Mon Sep 17 00:00:00 2001 From: Legacy <52163001+3m1n3nc3@users.noreply.github.com> Date: Sat, 30 Sep 2023 07:39:53 +0100 Subject: [PATCH 2/5] Update QIconPicker.js --- ui/src/components/QIconPicker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/components/QIconPicker.js b/ui/src/components/QIconPicker.js index 4d01148..9eefba9 100644 --- a/ui/src/components/QIconPicker.js +++ b/ui/src/components/QIconPicker.js @@ -160,7 +160,7 @@ function useIconPickerIcons(data, props, computedFirstItemIndex, computedLastIte // If vite if (typeof import.meta !== 'undefined' && import.meta.env !== undefined) { const set = await import( - `/node_modules/@quasar/quasar-ui-qiconpicker/src/components/icon-set/material-icons.js` + `/node_modules/@quasar/quasar-ui-qiconpicker/src/components/icon-set/${iconSet}.js` ) data.iconsList = set.default.icons // Else if webpack From f6bed4371ad6b8670e9b16c4b10727d9cffedaa8 Mon Sep 17 00:00:00 2001 From: Legacy <52163001+3m1n3nc3@users.noreply.github.com> Date: Sat, 30 Sep 2023 08:23:06 +0100 Subject: [PATCH 3/5] Make icon-set import path relative to cwd. --- ui/src/components/QIconPicker.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/src/components/QIconPicker.js b/ui/src/components/QIconPicker.js index 9eefba9..5773f80 100644 --- a/ui/src/components/QIconPicker.js +++ b/ui/src/components/QIconPicker.js @@ -159,9 +159,7 @@ function useIconPickerIcons(data, props, computedFirstItemIndex, computedLastIte else { // If vite if (typeof import.meta !== 'undefined' && import.meta.env !== undefined) { - const set = await import( - `/node_modules/@quasar/quasar-ui-qiconpicker/src/components/icon-set/${iconSet}.js` - ) + const set = await import(`./icon-set/${iconSet}.js`) data.iconsList = set.default.icons // Else if webpack } else { From d9516ad8a7ea17d5ac5f3ce3960e5840ba59a7a7 Mon Sep 17 00:00:00 2001 From: Legacy <52163001+3m1n3nc3@users.noreply.github.com> Date: Sat, 30 Sep 2023 08:57:06 +0100 Subject: [PATCH 4/5] Update QIconPicker.js --- ui/src/components/QIconPicker.js | 735 ++++++++++++++++++------------- 1 file changed, 428 insertions(+), 307 deletions(-) diff --git a/ui/src/components/QIconPicker.js b/ui/src/components/QIconPicker.js index 5773f80..469121f 100644 --- a/ui/src/components/QIconPicker.js +++ b/ui/src/components/QIconPicker.js @@ -1,5 +1,21 @@ -import { h, defineComponent, onMounted, reactive, computed, ref, nextTick, watch, Transition } from 'vue' -import { QBtn, QPagination, QResizeObserver, QScrollArea, QTooltip } from "quasar"; +import { + QBtn, + QPagination, + QResizeObserver, + QScrollArea, + QTooltip, +} from "quasar"; +import { + Transition, + computed, + defineComponent, + h, + nextTick, + onMounted, + reactive, + ref, + watch, +} from "vue"; /** * QIconPicker Properties @@ -8,23 +24,24 @@ const useIconPickerProps = { modelValue: String, iconSet: { type: String, - validator: v => [ - 'material-icons', - 'material-icons-outlined', - 'material-icons-round', - 'material-icons-sharp', - 'ionicons-v4', - 'mdi-v4', - 'mdi-v5', - 'mdi-v6', - 'fontawesome-v5', - 'eva-icons', - 'themify', - 'line-awesome', - 'bootstrap-icons', - '' - ].includes(v), - default: '' + validator: (v) => + [ + "material-icons", + "material-icons-outlined", + "material-icons-round", + "material-icons-sharp", + "ionicons-v4", + "mdi-v4", + "mdi-v5", + "mdi-v6", + "fontawesome-v5", + "eva-icons", + "themify", + "line-awesome", + "bootstrap-icons", + "", + ].includes(v), + default: "", }, icons: Array, filter: String, @@ -34,97 +51,106 @@ const useIconPickerProps = { noFooter: Boolean, size: { type: String, - default: 'inherit' + default: "inherit", }, color: String, textColor: String, selectedColor: { type: String, - default: 'primary' + default: "primary", }, selectedTextColor: { type: String, - default: 'grey-1' + default: "grey-1", }, paginationProps: { type: Object, default: () => ({ maxPages: 5, - input: true - }) + input: true, + }), }, modelPagination: Object, animated: Boolean, transitionPrev: { type: String, - default: 'slide-right' + default: "slide-right", }, transitionNext: { type: String, - default: 'slide-left' - } -} + default: "slide-left", + }, +}; const direction = { - NEXT: 'next', - PREV: 'prev' -} + NEXT: "next", + PREV: "prev", +}; /** * Pagination */ -function useIconPickerPagination(data, props, emit, computedFilteredIcons) { - - function fixPagination(p) { +function useIconPickerPagination (data, props, emit, computedFilteredIcons) { + function fixPagination (p) { if (p.page < 1) { - p.page = 1 + p.page = 1; } if (p.itemsPerPage === void 0 || p.itemsPerPage < 1) { - p.itemsPerPage = 0 // all + p.itemsPerPage = 0; // all } - return p + return p; } // returns true if the pagination is the same, // otherwise returns false if it has changed - function samePagination(oldPag, newPag) { + function samePagination (oldPag, newPag) { for (const prop in newPag) { - if (newPag[ prop ] !== oldPag[ prop ]) { - return false + if (newPag[prop] !== oldPag[prop]) { + return false; } } - return true + return true; } const computedPagination = computed(() => { return fixPagination({ ...data.innerPagination, - ...props.modelPagination - }) - }) + ...props.modelPagination, + }); + }); const computedPagesNumber = computed(() => { - return computedPagination.value.itemsPerPage === 0 ? 1 - : Math.max(1, Math.ceil(computedFilteredIcons.value.length / computedPagination.value.itemsPerPage)) - }) - - function setPagination(val) { + return computedPagination.value.itemsPerPage === 0 + ? 1 + : Math.max( + 1, + Math.ceil( + computedFilteredIcons.value.length / + computedPagination.value.itemsPerPage, + ), + ); + }); + + function setPagination (val) { const newPagination = fixPagination({ ...computedPagination.value, - ...val - }) + ...val, + }); if (!samePagination(data.innerPagination, newPagination)) { if (props.modelPagination) { - emit('update:model-pagination', newPagination) + emit("update:model-pagination", newPagination); } - data.innerPagination = newPagination + data.innerPagination = newPagination; } } - function updatePagination() { + function updatePagination () { if (props.modelPagination !== void 0) { - setPagination({ total: computedFilteredIcons.value.length, totalPages: computedPagesNumber.value }) + setPagination({ + total: computedFilteredIcons.value.length, + totalPages: computedPagesNumber.value, + }); } } @@ -133,142 +159,181 @@ function useIconPickerPagination(data, props, emit, computedFilteredIcons) { computedPagination, setPagination, updatePagination, - computedPagesNumber - } + computedPagesNumber, + }; } /** * Icons */ -function useIconPickerIcons(data, props, computedFirstItemIndex, computedLastItemIndex) { - - async function loadIconSet (iconSet) { - data.iconsList = [] +function useIconPickerIcons ( + data, + props, + computedFirstItemIndex, + computedLastItemIndex, +) { + function loadIconSet (iconSet) { + data.iconsList = []; if (iconSet) { // detect if UMD version is installed if (window.QIconPicker) { - const name = iconSet.replace(/-([a-z])/g, g => g[ 1 ].toUpperCase()) - if (window.QIconPicker.iconSet && window.QIconPicker.iconSet[ name ]) { - data.iconsList = window.QIconPicker.iconSet[ name ].icons - } - else { - console.error(`QIconPicker: no icon set loaded called ${ iconSet }`) - console.error('Be sure to load the UMD version of the icon set in a script tag before using QIconPicker UMD version') + const name = iconSet.replace(/-([a-z])/g, (g) => g[1].toUpperCase()); + if (window.QIconPicker.iconSet && window.QIconPicker.iconSet[name]) { + data.iconsList = window.QIconPicker.iconSet[name].icons; + } else { + console.error(`QIconPicker: no icon set loaded called ${iconSet}`); + console.error( + "Be sure to load the UMD version of the icon set in a script tag before using QIconPicker UMD version", + ); } - } - else { + console.info(`Loaded ${data.iconsList.length} icons.`); + } else { + try { // If vite if (typeof import.meta !== 'undefined' && import.meta.env !== undefined) { - const set = await import(`./icon-set/${iconSet}.js`) - data.iconsList = set.default.icons + viteImporter(iconSet) // Else if webpack } else { data.iconsList = require( `@quasar/quasar-ui-qiconpicker/src/components/icon-set/${iconSet}.js`, ).default.icons; + console.info(`Loaded ${data.iconsList.length} icons.`); } + } catch (e) { + console.error( + `QIconPicker: cannot find icon set found called ${iconSet}`, + ); + } } } - console.info(`Loaded ${ data.iconsList.length } icons.`) + } + + const viteImporter = async (iconSet) => { + const set = await import(`./icon-set/${iconSet}.js`) + data.iconsList = set.default.icons + console.info(`Loaded ${data.iconsList.length} icons.`); } const computedDisplayedIcons = computed(() => { - let icons = [] + let icons = []; if (data.iconsList) { - icons = computedFilteredIcons.value + icons = computedFilteredIcons.value; // should the icons be paged? if (props.modelPagination && props.modelPagination.itemsPerPage !== 0) { - icons = icons.slice(computedFirstItemIndex.value, computedLastItemIndex.value) + icons = icons.slice( + computedFirstItemIndex.value, + computedLastItemIndex.value, + ); } } - return icons - }) + return icons; + }); const computedFilteredIcons = computed(() => { - let icons = data.iconsList + let icons = data.iconsList; if (icons) { - if (props.tags !== void 0 && props.tags !== '' && props.tags !== null && props.tags.length > 0) { - icons = icons.filter(icon => { - return icon.tags.filter(tag => props.tags.includes(tag)).length > 0 - }) + if ( + props.tags !== void 0 && + props.tags !== "" && + props.tags !== null && + props.tags.length > 0 + ) { + icons = icons.filter((icon) => { + return icon.tags.filter((tag) => props.tags.includes(tag)).length > 0; + }); } - if (props.filter !== void 0 && props.filter !== '' && props.filter !== null) { - icons = icons.filter(icon => icon.name.includes(props.filter)) + if ( + props.filter !== void 0 && + props.filter !== "" && + props.filter !== null + ) { + icons = icons.filter((icon) => icon.name.includes(props.filter)); } } - return icons - }) + return icons; + }); - function categories() { - const t = [] - data.iconsList.forEach(icon => { - const tags = icon.tags + function categories () { + const t = []; + data.iconsList.forEach((icon) => { + const tags = icon.tags; if (tags && tags.length > 0) { - tags.forEach(tag => { + tags.forEach((tag) => { if (t.includes(tag) !== true) { - t.push(tag) + t.push(tag); } - }) + }); } - }) - t.sort() - data.categories = t - return true + }); + t.sort(); + data.categories = t; + return true; } return { loadIconSet, computedDisplayedIcons, computedFilteredIcons, - categories - } + categories, + }; } /** * Exposes api functions */ -function exposeIconPickerApi(data, expose, computedPagination, setPagination, computedFirstItemIndex, computedLastItemIndex, computedFilteredIcons, computedPagesNumber) { +function exposeIconPickerApi ( + data, + expose, + computedPagination, + setPagination, + computedFirstItemIndex, + computedLastItemIndex, + computedFilteredIcons, + computedPagesNumber, +) { // goes to previous page const prevPage = () => { - const { page } = computedPagination.value + const { page } = computedPagination.value; if (page > 1) { - setPagination({ page: page - 1 }) - data.direction = direction.PREV + setPagination({ page: page - 1 }); + data.direction = direction.PREV; } - } + }; // goes to next page const nextPage = () => { - const { page, itemsPerPage } = computedPagination.value - if (computedLastItemIndex.value > 0 && page * itemsPerPage < computedFilteredIcons.value.length) { - setPagination({ page: page + 1 }) - data.direction = direction.NEXT + const { page, itemsPerPage } = computedPagination.value; + if ( + computedLastItemIndex.value > 0 && + page * itemsPerPage < computedFilteredIcons.value.length + ) { + setPagination({ page: page + 1 }); + data.direction = direction.NEXT; } - } + }; // goes to last page const lastPage = () => { - setPagination({ page: computedPagesNumber.value }) - } + setPagination({ page: computedPagesNumber.value }); + }; // goes to first page const firstPage = () => { - setPagination({ page: 0 }) - } + setPagination({ page: 0 }); + }; // checks if we are on the last page const isLastPage = computed(() => { return computedLastItemIndex.value === 0 ? true - : computedPagination.value.page >= computedPagesNumber.value - }) - + : computedPagination.value.page >= computedPagesNumber.value; + }); // checks if we are on the first page const isFirstPage = computed(() => { - return computedPagination.value.page === 1 - }) + return computedPagination.value.page === 1; + }); expose({ prevPage, @@ -276,273 +341,329 @@ function exposeIconPickerApi(data, expose, computedPagination, setPagination, co lastPage, firstPage, isLastPage, - isFirstPage - }) + isFirstPage, + }); } - export default defineComponent({ - name: 'QIconPicker', + name: "QIconPicker", props: { - ...useIconPickerProps + ...useIconPickerProps, }, - emits: [ - 'update:model-value', - 'update:tags', - 'update:model-pagination' - ], + emits: ["update:model-value", "update:tags", "update:model-pagination"], - setup(props, { slots, emit, expose }) { - const scrollAreaRef = ref(null) + setup (props, { slots, emit, expose }) { + const scrollAreaRef = ref(null); const data = reactive({ iconsList: [], innerPagination: { page: 1, itemsPerPage: 0, - totalPages: 0 + totalPages: 0, }, categories: [], - width: '100', - height: '100', - direction: '' - }) + width: "100", + height: "100", + direction: "", + }); // index of first item on a page const computedFirstItemIndex = computed(() => { - const { page, itemsPerPage } = computedPagination.value - return (page - 1) * itemsPerPage - }) + const { page, itemsPerPage } = computedPagination.value; + return (page - 1) * itemsPerPage; + }); // index of last item on a page const computedLastItemIndex = computed(() => { - const { page, itemsPerPage } = computedPagination.value - return page * itemsPerPage - }) + const { page, itemsPerPage } = computedPagination.value; + return page * itemsPerPage; + }); const { loadIconSet, computedDisplayedIcons, computedFilteredIcons, - categories - } = useIconPickerIcons(data, props, computedFirstItemIndex, computedLastItemIndex) + categories, + } = useIconPickerIcons( + data, + props, + computedFirstItemIndex, + computedLastItemIndex, + ); const { samePagination, computedPagination, setPagination, updatePagination, - computedPagesNumber - } = useIconPickerPagination(data, props, emit, computedFilteredIcons) + computedPagesNumber, + } = useIconPickerPagination(data, props, emit, computedFilteredIcons); - exposeIconPickerApi(data, expose, computedPagination, setPagination, computedFirstItemIndex, computedLastItemIndex, computedFilteredIcons, computedPagesNumber) + exposeIconPickerApi( + data, + expose, + computedPagination, + setPagination, + computedFirstItemIndex, + computedLastItemIndex, + computedFilteredIcons, + computedPagesNumber, + ); onMounted(() => { if (props.iconSet) { - loadIconSet(props.iconSet) - } - else if (props.icons !== void 0 && props.icons.length > 0) { - data.iconsList = props.icons + loadIconSet(props.iconSet); + } else if (props.icons !== void 0 && props.icons.length > 0) { + data.iconsList = props.icons; } - updatePagination() - }) - + updatePagination(); + }); + + watch( + () => props.iconSet, + (val) => { + if (val) { + loadIconSet(val); + updatePagination(); + nextTick(() => { + // whenever the icon set changes, it resets pagination page to page 1 + setPagination({ page: 1 }); + }).catch((e) => console.error(e)); + // scroll to top of QScrollArea, if applicable + if (scrollAreaRef.value) { + scrollAreaRef.value.setScrollPosition(0); + } + } + }, + ); - watch(() => props.iconSet, (val) => { - if (val) { - loadIconSet(val) - updatePagination() + watch( + () => props.icons, + () => { + if (props.icons !== void 0 && props.icons.length > 0) { + data.iconsList = props.icons; + } + updatePagination(); nextTick(() => { // whenever the icon set changes, it resets pagination page to page 1 - setPagination({ page: 1 }) - }).catch(e => console.error(e)) + setPagination({ page: 1 }); + }).catch((e) => console.error(e)); // scroll to top of QScrollArea, if applicable - if(scrollAreaRef.value) { - scrollAreaRef.value.setScrollPosition(0) + if (scrollAreaRef.value) { + scrollAreaRef.value.setScrollPosition(0); } - } - }) - - watch(() => props.icons, (val) => { - if (props.icons !== void 0 && props.icons.length > 0) { - data.iconsList = props.icons - } - updatePagination() - nextTick(() => { - // whenever the icon set changes, it resets pagination page to page 1 - setPagination({ page: 1 }) - }).catch(e => console.error(e)) - // scroll to top of QScrollArea, if applicable - if(scrollAreaRef.value) { - scrollAreaRef.value.setScrollPosition(0) - } - }) - - watch(() => props.filter, () => { - // whenever the filter changes, it resets pagination page to page 1 - setPagination({ page: 1, totalPages: computedPagesNumber.value }) - updatePagination() - }) - - watch(() => props.tags, (val) => { - // whenever the tags change, it resets pagination page to page 1 - setPagination({ page: 1, totalPages: computedPagesNumber.value }) - updatePagination() - }) + }, + ); + + watch( + () => props.filter, + () => { + // whenever the filter changes, it resets pagination page to page 1 + setPagination({ page: 1, totalPages: computedPagesNumber.value }); + updatePagination(); + }, + ); + + watch( + () => props.tags, + () => { + // whenever the tags change, it resets pagination page to page 1 + setPagination({ page: 1, totalPages: computedPagesNumber.value }); + updatePagination(); + }, + ); if (props.modelPagination) { - watch(() => props.modelPagination, (newVal, oldVal) => { - if (!samePagination(oldVal, newVal)) { - updatePagination() - } - }) + watch( + () => props.modelPagination, + (newVal, oldVal) => { + if (!samePagination(oldVal, newVal)) { + updatePagination(); + } + }, + ); } if (props.modelPagination) { - watch(() => props.modelPagination.itemsPerPage, () => { - updatePagination() - }) - - watch(() =>props.modelPagination.page, () => { - updatePagination() - }) + watch( + () => props.modelPagination.itemsPerPage, + () => { + updatePagination(); + }, + ); + + watch( + () => props.modelPagination.page, + () => { + updatePagination(); + }, + ); } return () => { - - function renderPagination() { - if (props.modelPagination && props.modelPagination.itemsPerPage === 0) return '' - const slot = (slots.pagination && slots.pagination()) - const { page, totalPages } = computedPagination.value - - return slot || h(QPagination, { - class: 'q-icon-picker__pagination', - ...props.paginationProps, - modelValue: page, - max: totalPages, - 'onUpdate:modelValue': value => { - if (props.animated) { - if (value > page) { - data.direction = direction.NEXT - } - else { - data.direction = direction.PREV + function renderPagination () { + if (props.modelPagination && props.modelPagination.itemsPerPage === 0) + return ""; + const slot = slots.pagination && slots.pagination(); + const { page, totalPages } = computedPagination.value; + + return ( + slot || + h(QPagination, { + class: "q-icon-picker__pagination", + ...props.paginationProps, + modelValue: page, + max: totalPages, + "onUpdate:modelValue": (value) => { + if (props.animated) { + if (value > page) { + data.direction = direction.NEXT; + } else { + data.direction = direction.PREV; + } } - } - setPagination({ page: value }) - } - }) + setPagination({ page: value }); + }, + }) + ); } - function renderFooter() { + function renderFooter () { if (props.noFooter !== true && props.modelPagination !== void 0) { - const slot = (slots.footer && slots.footer()) - - return h('div', { - class: 'q-icon-picker__footer flex flex-center' - }, [ - slot ? slot(computedPagination.value) : renderPagination() - ]) + const slot = slots.footer && slots.footer(); + + return h( + "div", + { + class: "q-icon-picker__footer flex flex-center", + }, + [slot ? slot(computedPagination.value) : renderPagination()], + ); } } - function renderTooltip(name) { + function renderTooltip (name) { if (props.tooltips === true) { - return () => h(QTooltip, {}, () => name) + return () => h(QTooltip, {}, () => name); } } - function renderIcon(icon) { - const name = (icon.prefix !== void 0 ? icon.prefix + ' ' + icon.name : icon.name) + function renderIcon (icon) { + const name = + icon.prefix !== void 0 ? icon.prefix + " " + icon.name : icon.name; if (slots.icon && slots.icon()) { - return slots.icon(name) + return slots.icon(name); } - const isSelected = name === props.modelValue - const textColor = isSelected ? props.selectedTextColor : undefined - const color = isSelected ? props.selectedColor : undefined - const size = props.size ? props.size : undefined - - return h(QBtn, { - id: name, - unelevated: true, - dense: props.dense, - noWrap: true, - size: size, - textColor: textColor, - color: color, - icon: name, - onClick: () => emit('update:model-value', name), - }, renderTooltip(name)) + const isSelected = name === props.modelValue; + const textColor = isSelected ? props.selectedTextColor : undefined; + const color = isSelected ? props.selectedColor : undefined; + const size = props.size ? props.size : undefined; + + return h( + QBtn, + { + id: name, + unelevated: true, + dense: props.dense, + noWrap: true, + size: size, + textColor: textColor, + color: color, + icon: name, + onClick: () => emit("update:model-value", name), + }, + renderTooltip(name), + ); } - function renderIcons() { - return computedDisplayedIcons.value.map(icon => renderIcon(icon)) + function renderIcons () { + return computedDisplayedIcons.value.map((icon) => renderIcon(icon)); } - function renderContainer() { - const container = () => h('div', { - key: computedPagination.value.page, - class: 'q-icon-picker__container col' - }, [...renderIcons()]) + function renderContainer () { + const container = () => + h( + "div", + { + key: computedPagination.value.page, + class: "q-icon-picker__container col", + }, + [...renderIcons()], + ); if (props.animated === true) { - const transition = 'q-transition--' + (data.direction === 'prev' ? props.transitionPrev : props.transitionNext) - return () => h(Transition, { - name: transition, - appear: true - }, container) + const transition = + "q-transition--" + + (data.direction === "prev" + ? props.transitionPrev + : props.transitionNext); + return () => + h( + Transition, + { + name: transition, + appear: true, + }, + container, + ); } - return container + return container; } - - function renderScrollArea() { - return h(QScrollArea, { - ref: scrollAreaRef, - style: { - width: data.width + 'px', - height: data.height + 'px' - } - }, renderContainer()) + function renderScrollArea () { + return h( + QScrollArea, + { + ref: scrollAreaRef, + style: { + width: data.width + "px", + height: data.height + "px", + }, + }, + renderContainer(), + ); } - function renderBody() { - return h('div', { - class: 'q-icon-picker__body col column' - }, [ - renderScrollArea(), - h(QResizeObserver, { - onResize: (size) => { - data.width = size.width - data.height = size.height - } - }) - ]) + function renderBody () { + return h( + "div", + { + class: "q-icon-picker__body col column", + }, + [ + renderScrollArea(), + h(QResizeObserver, { + onResize: (size) => { + data.width = size.width; + data.height = size.height; + }, + }), + ], + ); } - const classes = [ - 'q-icon-picker', - 'column' - ] - if (props.color) classes.push('bg-' + props.color) - if (props.textColor) classes.push('text-' + props.textColor) + const classes = ["q-icon-picker", "column"]; + if (props.color) classes.push("bg-" + props.color); + if (props.textColor) classes.push("text-" + props.textColor); - const picker = h('div', { - class: classes.join(' ') - }, [ - renderBody(), - renderFooter() - ]) + const picker = h( + "div", + { + class: classes.join(" "), + }, + [renderBody(), renderFooter()], + ); nextTick(() => { - categories() - emit('update:tags', data.categories) - }).catch(e => console.error(e)) + categories(); + emit("update:tags", data.categories); + }).catch((e) => console.error(e)); - return picker - } - } -}) + return picker; + }; + }, +}); From cc6e026187ce671c55a7046bda0d470229da76ef Mon Sep 17 00:00:00 2001 From: Legacy <52163001+3m1n3nc3@users.noreply.github.com> Date: Sat, 30 Sep 2023 09:36:07 +0100 Subject: [PATCH 5/5] Update QIconPicker.js: Handle synchronous vite imports. --- ui/src/components/QIconPicker.js | 553 ++++++++++++++++--------------- 1 file changed, 277 insertions(+), 276 deletions(-) diff --git a/ui/src/components/QIconPicker.js b/ui/src/components/QIconPicker.js index 469121f..a368317 100644 --- a/ui/src/components/QIconPicker.js +++ b/ui/src/components/QIconPicker.js @@ -12,7 +12,6 @@ import { h, nextTick, onMounted, - reactive, ref, watch, } from "vue"; @@ -87,264 +86,6 @@ const direction = { PREV: "prev", }; -/** - * Pagination - */ -function useIconPickerPagination (data, props, emit, computedFilteredIcons) { - function fixPagination (p) { - if (p.page < 1) { - p.page = 1; - } - if (p.itemsPerPage === void 0 || p.itemsPerPage < 1) { - p.itemsPerPage = 0; // all - } - return p; - } - - // returns true if the pagination is the same, - // otherwise returns false if it has changed - function samePagination (oldPag, newPag) { - for (const prop in newPag) { - if (newPag[prop] !== oldPag[prop]) { - return false; - } - } - return true; - } - - const computedPagination = computed(() => { - return fixPagination({ - ...data.innerPagination, - ...props.modelPagination, - }); - }); - - const computedPagesNumber = computed(() => { - return computedPagination.value.itemsPerPage === 0 - ? 1 - : Math.max( - 1, - Math.ceil( - computedFilteredIcons.value.length / - computedPagination.value.itemsPerPage, - ), - ); - }); - - function setPagination (val) { - const newPagination = fixPagination({ - ...computedPagination.value, - ...val, - }); - - if (!samePagination(data.innerPagination, newPagination)) { - if (props.modelPagination) { - emit("update:model-pagination", newPagination); - } - data.innerPagination = newPagination; - } - } - - function updatePagination () { - if (props.modelPagination !== void 0) { - setPagination({ - total: computedFilteredIcons.value.length, - totalPages: computedPagesNumber.value, - }); - } - } - - return { - samePagination, - computedPagination, - setPagination, - updatePagination, - computedPagesNumber, - }; -} - -/** - * Icons - */ -function useIconPickerIcons ( - data, - props, - computedFirstItemIndex, - computedLastItemIndex, -) { - function loadIconSet (iconSet) { - data.iconsList = []; - if (iconSet) { - // detect if UMD version is installed - if (window.QIconPicker) { - const name = iconSet.replace(/-([a-z])/g, (g) => g[1].toUpperCase()); - if (window.QIconPicker.iconSet && window.QIconPicker.iconSet[name]) { - data.iconsList = window.QIconPicker.iconSet[name].icons; - } else { - console.error(`QIconPicker: no icon set loaded called ${iconSet}`); - console.error( - "Be sure to load the UMD version of the icon set in a script tag before using QIconPicker UMD version", - ); - } - console.info(`Loaded ${data.iconsList.length} icons.`); - } else { - try { - // If vite - if (typeof import.meta !== 'undefined' && import.meta.env !== undefined) { - viteImporter(iconSet) - // Else if webpack - } else { - data.iconsList = require( - `@quasar/quasar-ui-qiconpicker/src/components/icon-set/${iconSet}.js`, - ).default.icons; - console.info(`Loaded ${data.iconsList.length} icons.`); - } - } catch (e) { - console.error( - `QIconPicker: cannot find icon set found called ${iconSet}`, - ); - } - } - } - } - - const viteImporter = async (iconSet) => { - const set = await import(`./icon-set/${iconSet}.js`) - data.iconsList = set.default.icons - console.info(`Loaded ${data.iconsList.length} icons.`); - } - - const computedDisplayedIcons = computed(() => { - let icons = []; - if (data.iconsList) { - icons = computedFilteredIcons.value; - - // should the icons be paged? - if (props.modelPagination && props.modelPagination.itemsPerPage !== 0) { - icons = icons.slice( - computedFirstItemIndex.value, - computedLastItemIndex.value, - ); - } - } - return icons; - }); - - const computedFilteredIcons = computed(() => { - let icons = data.iconsList; - if (icons) { - if ( - props.tags !== void 0 && - props.tags !== "" && - props.tags !== null && - props.tags.length > 0 - ) { - icons = icons.filter((icon) => { - return icon.tags.filter((tag) => props.tags.includes(tag)).length > 0; - }); - } - if ( - props.filter !== void 0 && - props.filter !== "" && - props.filter !== null - ) { - icons = icons.filter((icon) => icon.name.includes(props.filter)); - } - } - return icons; - }); - - function categories () { - const t = []; - data.iconsList.forEach((icon) => { - const tags = icon.tags; - if (tags && tags.length > 0) { - tags.forEach((tag) => { - if (t.includes(tag) !== true) { - t.push(tag); - } - }); - } - }); - t.sort(); - data.categories = t; - return true; - } - - return { - loadIconSet, - computedDisplayedIcons, - computedFilteredIcons, - categories, - }; -} - -/** - * Exposes api functions - */ -function exposeIconPickerApi ( - data, - expose, - computedPagination, - setPagination, - computedFirstItemIndex, - computedLastItemIndex, - computedFilteredIcons, - computedPagesNumber, -) { - // goes to previous page - const prevPage = () => { - const { page } = computedPagination.value; - if (page > 1) { - setPagination({ page: page - 1 }); - data.direction = direction.PREV; - } - }; - - // goes to next page - const nextPage = () => { - const { page, itemsPerPage } = computedPagination.value; - if ( - computedLastItemIndex.value > 0 && - page * itemsPerPage < computedFilteredIcons.value.length - ) { - setPagination({ page: page + 1 }); - data.direction = direction.NEXT; - } - }; - - // goes to last page - const lastPage = () => { - setPagination({ page: computedPagesNumber.value }); - }; - - // goes to first page - const firstPage = () => { - setPagination({ page: 0 }); - }; - - // checks if we are on the last page - const isLastPage = computed(() => { - return computedLastItemIndex.value === 0 - ? true - : computedPagination.value.page >= computedPagesNumber.value; - }); - - // checks if we are on the first page - const isFirstPage = computed(() => { - return computedPagination.value.page === 1; - }); - - expose({ - prevPage, - nextPage, - lastPage, - firstPage, - isLastPage, - isFirstPage, - }); -} - export default defineComponent({ name: "QIconPicker", @@ -356,7 +97,8 @@ export default defineComponent({ setup (props, { slots, emit, expose }) { const scrollAreaRef = ref(null); - const data = reactive({ + const data = ref({ + viteLoaded: false, iconsList: [], innerPagination: { page: 1, @@ -381,30 +123,283 @@ export default defineComponent({ return page * itemsPerPage; }); + /** + * Icons + */ + const useIconPickerIcons = ( + computedFirstItemIndex, + computedLastItemIndex, + ) => { + function loadIconSet (iconSet) { + data.value.iconsList = []; + if (iconSet) { + // detect if UMD version is installed + if (window.QIconPicker) { + const name = iconSet.replace(/-([a-z])/g, (g) => g[1].toUpperCase()); + if (window.QIconPicker.iconSet && window.QIconPicker.iconSet[name]) { + data.value.iconsList = window.QIconPicker.iconSet[name].icons; + } else { + console.error(`QIconPicker: no icon set loaded called ${iconSet}`); + console.error( + "Be sure to load the UMD version of the icon set in a script tag before using QIconPicker UMD version", + ); + } + console.info(`Loaded ${data.value.iconsList.length} icons.`); + } else { + try { + // If vite + if (typeof import.meta !== 'undefined' && import.meta.env !== undefined) { + viteImporter(iconSet) + // Else if webpack + } else { + data.value.iconsList = require( + `@quasar/quasar-ui-qiconpicker/src/components/icon-set/${iconSet}.js`, + ).default.icons; + console.info(`Loaded ${data.value.iconsList.length} icons.`); + } + } catch (e) { + console.error( + `QIconPicker: cannot find icon set found called ${iconSet}`, + ); + } + } + } + } + + const viteImporter = async (iconSet) => { + console.info('Vite support detected'); + const set = await import(`./icon-set/${iconSet}.js`) + data.value.iconsList = set.default.icons + data.value.viteLoaded = true + console.info(`Loaded ${data.value.iconsList.length} icons.`); + } + + const computedDisplayedIcons = computed(() => { + let icons = []; + if (data.value.iconsList) { + icons = computedFilteredIcons.value; + + // should the icons be paged? + if (props.modelPagination && props.modelPagination.itemsPerPage !== 0) { + icons = icons.slice( + computedFirstItemIndex.value, + computedLastItemIndex.value, + ); + } + } + return icons; + }); + + const computedFilteredIcons = computed(() => { + let icons = data.value.iconsList; + if (icons) { + if ( + props.tags !== void 0 && + props.tags !== "" && + props.tags !== null && + props.tags.length > 0 + ) { + icons = icons.filter((icon) => { + return icon.tags.filter((tag) => props.tags.includes(tag)).length > 0; + }); + } + if ( + props.filter !== void 0 && + props.filter !== "" && + props.filter !== null + ) { + icons = icons.filter((icon) => icon.name.includes(props.filter)); + } + } + return icons; + }); + + function categories () { + const t = []; + data.value.iconsList.forEach((icon) => { + const tags = icon.tags; + if (tags && tags.length > 0) { + tags.forEach((tag) => { + if (t.includes(tag) !== true) { + t.push(tag); + } + }); + } + }); + t.sort(); + data.value.categories = t; + return true; + } + + return { + loadIconSet, + computedDisplayedIcons, + computedFilteredIcons, + categories, + }; + } + const { loadIconSet, computedDisplayedIcons, computedFilteredIcons, categories, } = useIconPickerIcons( - data, - props, computedFirstItemIndex, computedLastItemIndex, ); + /** + * Pagination + */ + function useIconPickerPagination () { + function fixPagination (p) { + if (p.page < 1) { + p.page = 1; + } + if (p.itemsPerPage === void 0 || p.itemsPerPage < 1) { + p.itemsPerPage = 0; // all + } + return p; + } + + // returns true if the pagination is the same, + // otherwise returns false if it has changed + function samePagination (oldPag, newPag) { + for (const prop in newPag) { + if (newPag[prop] !== oldPag[prop]) { + return false; + } + } + return true; + } + + const computedPagination = computed(() => { + return fixPagination({ + ...data.value.innerPagination, + ...props.modelPagination, + }); + }); + + const computedPagesNumber = computed(() => { + return computedPagination.value.itemsPerPage === 0 + ? 1 + : Math.max( + 1, + Math.ceil( + computedFilteredIcons.value.length / + computedPagination.value.itemsPerPage, + ), + ); + }); + + function setPagination (val) { + const newPagination = fixPagination({ + ...computedPagination.value, + ...val, + }); + + if (!samePagination(data.value.innerPagination, newPagination)) { + if (props.modelPagination) { + emit("update:model-pagination", newPagination); + } + data.value.innerPagination = newPagination; + } + } + + function updatePagination () { + if (props.modelPagination !== void 0) { + setPagination({ + total: computedFilteredIcons.value.length, + totalPages: computedPagesNumber.value, + }); + } + } + + return { + samePagination, + computedPagination, + setPagination, + updatePagination, + computedPagesNumber, + }; + } + + // ========== + const { samePagination, computedPagination, setPagination, updatePagination, computedPagesNumber, - } = useIconPickerPagination(data, props, emit, computedFilteredIcons); + } = useIconPickerPagination(); + + + /** + * Exposes api functions + */ + const exposeIconPickerApi = ( + setPagination, + computedFirstItemIndex, + computedLastItemIndex, + computedFilteredIcons, + computedPagesNumber, + ) => { + // goes to previous page + const prevPage = () => { + const { page } = computedPagination.value; + if (page > 1) { + setPagination({ page: page - 1 }); + data.value.direction = direction.PREV; + } + }; + + // goes to next page + const nextPage = () => { + const { page, itemsPerPage } = computedPagination.value; + if ( + computedLastItemIndex.value > 0 && + page * itemsPerPage < computedFilteredIcons.value.length + ) { + setPagination({ page: page + 1 }); + data.value.direction = direction.NEXT; + } + }; + + // goes to last page + const lastPage = () => { + setPagination({ page: computedPagesNumber.value }); + }; + + // goes to first page + const firstPage = () => { + setPagination({ page: 0 }); + }; + + // checks if we are on the last page + const isLastPage = computed(() => { + return computedLastItemIndex.value === 0 + ? true + : computedPagination.value.page >= computedPagesNumber.value; + }); + + // checks if we are on the first page + const isFirstPage = computed(() => { + return computedPagination.value.page === 1; + }); + + expose({ + prevPage, + nextPage, + lastPage, + firstPage, + isLastPage, + isFirstPage, + }); + } exposeIconPickerApi( - data, - expose, - computedPagination, setPagination, computedFirstItemIndex, computedLastItemIndex, @@ -416,11 +411,17 @@ export default defineComponent({ if (props.iconSet) { loadIconSet(props.iconSet); } else if (props.icons !== void 0 && props.icons.length > 0) { - data.iconsList = props.icons; + data.value.iconsList = props.icons; } updatePagination(); }); + watch(() => data.value.viteLoaded, (viteLoaded) => { + if (viteLoaded === true) { + updatePagination(); + } + }) + watch( () => props.iconSet, (val) => { @@ -443,7 +444,7 @@ export default defineComponent({ () => props.icons, () => { if (props.icons !== void 0 && props.icons.length > 0) { - data.iconsList = props.icons; + data.value.iconsList = props.icons; } updatePagination(); nextTick(() => { @@ -519,9 +520,9 @@ export default defineComponent({ "onUpdate:modelValue": (value) => { if (props.animated) { if (value > page) { - data.direction = direction.NEXT; + data.value.direction = direction.NEXT; } else { - data.direction = direction.PREV; + data.value.direction = direction.PREV; } } setPagination({ page: value }); @@ -597,7 +598,7 @@ export default defineComponent({ if (props.animated === true) { const transition = "q-transition--" + - (data.direction === "prev" + (data.value.direction === "prev" ? props.transitionPrev : props.transitionNext); return () => @@ -620,8 +621,8 @@ export default defineComponent({ { ref: scrollAreaRef, style: { - width: data.width + "px", - height: data.height + "px", + width: data.value.width + "px", + height: data.value.height + "px", }, }, renderContainer(), @@ -638,8 +639,8 @@ export default defineComponent({ renderScrollArea(), h(QResizeObserver, { onResize: (size) => { - data.width = size.width; - data.height = size.height; + data.value.width = size.width; + data.value.height = size.height; }, }), ], @@ -660,7 +661,7 @@ export default defineComponent({ nextTick(() => { categories(); - emit("update:tags", data.categories); + emit("update:tags", data.value.categories); }).catch((e) => console.error(e)); return picker;