From ee1b6260d7757a2cc596d68f7eebe21d2cd672f6 Mon Sep 17 00:00:00 2001 From: tugcekucukoglu Date: Fri, 4 Oct 2024 12:02:05 +0300 Subject: [PATCH] Refactor #6522 - For ContextMenu --- .../src/contextmenu/BaseContextMenu.vue | 4 ++ .../primevue/src/contextmenu/ContextMenu.d.ts | 15 ++++-- .../primevue/src/contextmenu/ContextMenu.vue | 27 ++++++++++- .../src/contextmenu/style/ContextMenuStyle.js | 48 ++++++++++++++++++- .../src/presets/aura/contextmenu/index.js | 3 ++ .../src/presets/lara/contextmenu/index.js | 3 ++ .../src/presets/material/contextmenu/index.js | 3 ++ .../src/presets/nora/contextmenu/index.js | 3 ++ 8 files changed, 99 insertions(+), 7 deletions(-) diff --git a/packages/primevue/src/contextmenu/BaseContextMenu.vue b/packages/primevue/src/contextmenu/BaseContextMenu.vue index 36e557387..582185124 100644 --- a/packages/primevue/src/contextmenu/BaseContextMenu.vue +++ b/packages/primevue/src/contextmenu/BaseContextMenu.vue @@ -26,6 +26,10 @@ export default { type: Boolean, default: false }, + breakpoint: { + type: String, + default: '960px' + }, tabindex: { type: Number, default: 0 diff --git a/packages/primevue/src/contextmenu/ContextMenu.d.ts b/packages/primevue/src/contextmenu/ContextMenu.d.ts index 8b50b43a6..6f48f255b 100755 --- a/packages/primevue/src/contextmenu/ContextMenu.d.ts +++ b/packages/primevue/src/contextmenu/ContextMenu.d.ts @@ -227,6 +227,16 @@ export interface ContextMenuProps { * An array of menuitems. */ model?: MenuItem[] | undefined; + /** + * The breakpoint to define the maximum width boundary. + * @defaultValue 960px + */ + breakpoint?: string | undefined; + /** + * Attaches the menu to document instead of a particular item. + * @defaultValue false + */ + global?: boolean | undefined; /** * A valid query selector or an HTMLElement to specify where the overlay gets attached. * @defaultValue body @@ -242,11 +252,6 @@ export interface ContextMenuProps { * @defaultValue 0 */ baseZIndex?: number | undefined; - /** - * Attaches the menu to document instead of a particular item. - * @defaultValue false - */ - global?: boolean | undefined; /** * Index of the element in tabbing order. */ diff --git a/packages/primevue/src/contextmenu/ContextMenu.vue b/packages/primevue/src/contextmenu/ContextMenu.vue index 384507f61..f704dd789 100755 --- a/packages/primevue/src/contextmenu/ContextMenu.vue +++ b/packages/primevue/src/contextmenu/ContextMenu.vue @@ -52,6 +52,7 @@ export default { outsideClickListener: null, resizeListener: null, documentContextMenuListener: null, + matchMediaListener: null, pageX: null, pageY: null, container: null, @@ -63,7 +64,9 @@ export default { focusedItemInfo: { index: -1, level: 0, parentKey: '' }, activeItemPath: [], visible: false, - submenuVisible: false + submenuVisible: false, + query: null, + queryMatches: false }; }, watch: { @@ -82,6 +85,7 @@ export default { }, mounted() { this.id = this.id || UniqueComponentId(); + this.bindMatchMediaListener(); if (this.global) { this.bindDocumentContextMenuListener(); @@ -91,6 +95,7 @@ export default { this.unbindResizeListener(); this.unbindOutsideClickListener(); this.unbindDocumentContextMenuListener(); + this.unbindMatchMediaListener(); if (this.container && this.autoZIndex) { ZIndex.clear(this.container); @@ -465,6 +470,26 @@ export default { this.documentContextMenuListener = null; } }, + bindMatchMediaListener() { + if (!this.matchMediaListener) { + const query = matchMedia(`(max-width: ${this.breakpoint})`); + + this.query = query; + this.queryMatches = query.matches; + + this.matchMediaListener = () => { + this.queryMatches = query.matches; + }; + + this.query.addEventListener('change', this.matchMediaListener); + } + }, + unbindMatchMediaListener() { + if (this.matchMediaListener) { + this.query.removeEventListener('change', this.matchMediaListener); + this.matchMediaListener = null; + } + }, isItemMatched(processedItem) { return this.isValidItem(processedItem) && this.getProccessedItemLabel(processedItem)?.toLocaleLowerCase().startsWith(this.searchValue.toLocaleLowerCase()); }, diff --git a/packages/primevue/src/contextmenu/style/ContextMenuStyle.js b/packages/primevue/src/contextmenu/style/ContextMenuStyle.js index c4c0989e0..723592dfc 100644 --- a/packages/primevue/src/contextmenu/style/ContextMenuStyle.js +++ b/packages/primevue/src/contextmenu/style/ContextMenuStyle.js @@ -124,10 +124,56 @@ const theme = ({ dt }) => ` .p-contextmenu-enter-active { transition: opacity 250ms; } + +.p-contextmenu-mobile { + position: relative; +} + +.p-contextmenu-mobile .p-contextmenu-button { + display: flex; +} + +.p-contextmenu-mobile .p-contextmenu-root-list .p-contextmenu-item { + position: static; +} + +.p-contextmenu-mobile .p-contextmenu-root-list .p-contextmenu-separator { + border-top: 1px solid ${dt('contextmenu.separator.border.color')}; +} + +.p-contextmenu-mobile .p-contextmenu-root-list > .p-contextmenu-item > .p-contextmenu-item-content .p-contextmenu-submenu-icon { + margin-left: auto; + transition: transform 0.2s; +} + +.p-contextmenu-mobile .p-contextmenu-root-list > .p-contextmenu-item-active > .p-contextmenu-item-content .p-contextmenu-submenu-icon { + transform: rotate(-90deg); +} + +.p-contextmenu-mobile .p-contextmenu-submenu .p-contextmenu-submenu-icon { + transition: transform 0.2s; + transform: rotate(90deg); +} + +.p-contextmenu-mobile .p-contextmenu-item-active > .p-contextmenu-item-content .p-contextmenu-submenu-icon { + transform: rotate(-90deg); +} + +.p-contextmenu-mobile .p-contextmenu-submenu { + position: static; + box-shadow: none; + border: 0 none; + padding-left: ${dt('contextmenu.submenu.mobile.indent')}; +} `; const classes = { - root: 'p-contextmenu p-component', + root: ({ instance }) => [ + 'p-contextmenu p-component', + { + 'p-contextmenu-mobile': instance.queryMatches + } + ], rootList: 'p-contextmenu-root-list', item: ({ instance, processedItem }) => [ 'p-contextmenu-item', diff --git a/packages/themes/src/presets/aura/contextmenu/index.js b/packages/themes/src/presets/aura/contextmenu/index.js index 0d328e6d3..c7b92fa56 100644 --- a/packages/themes/src/presets/aura/contextmenu/index.js +++ b/packages/themes/src/presets/aura/contextmenu/index.js @@ -26,6 +26,9 @@ export default { activeColor: '{navigation.item.icon.active.color}' } }, + submenu: { + mobileIndent: '1rem' + }, submenuIcon: { size: '{navigation.submenu.icon.size}', color: '{navigation.submenu.icon.color}', diff --git a/packages/themes/src/presets/lara/contextmenu/index.js b/packages/themes/src/presets/lara/contextmenu/index.js index f157f99a0..c117c6241 100644 --- a/packages/themes/src/presets/lara/contextmenu/index.js +++ b/packages/themes/src/presets/lara/contextmenu/index.js @@ -26,6 +26,9 @@ export default { activeColor: '{navigation.item.icon.active.color}' } }, + submenu: { + mobileIndent: '1.25rem' + }, submenuLabel: { padding: '{navigation.submenu.label.padding}', fontWeight: '{navigation.submenu.label.font.weight}', diff --git a/packages/themes/src/presets/material/contextmenu/index.js b/packages/themes/src/presets/material/contextmenu/index.js index 0d328e6d3..c7b92fa56 100644 --- a/packages/themes/src/presets/material/contextmenu/index.js +++ b/packages/themes/src/presets/material/contextmenu/index.js @@ -26,6 +26,9 @@ export default { activeColor: '{navigation.item.icon.active.color}' } }, + submenu: { + mobileIndent: '1rem' + }, submenuIcon: { size: '{navigation.submenu.icon.size}', color: '{navigation.submenu.icon.color}', diff --git a/packages/themes/src/presets/nora/contextmenu/index.js b/packages/themes/src/presets/nora/contextmenu/index.js index 0d328e6d3..c7b92fa56 100644 --- a/packages/themes/src/presets/nora/contextmenu/index.js +++ b/packages/themes/src/presets/nora/contextmenu/index.js @@ -26,6 +26,9 @@ export default { activeColor: '{navigation.item.icon.active.color}' } }, + submenu: { + mobileIndent: '1rem' + }, submenuIcon: { size: '{navigation.submenu.icon.size}', color: '{navigation.submenu.icon.color}',