From 9ca784dc280be40f5bd60dfd4fe66af1d16b00f8 Mon Sep 17 00:00:00 2001 From: tugcekucukoglu Date: Fri, 4 Oct 2024 17:01:56 +0300 Subject: [PATCH 1/4] Refactor #6522 - For CascadeSelect --- .../src/cascadeselect/BaseCascadeSelect.vue | 4 ++ .../src/cascadeselect/CascadeSelect.vue | 33 ++++++++++- .../src/cascadeselect/CascadeSelectSub.vue | 19 +------ .../cascadeselect/style/CascadeSelectStyle.js | 55 +++++++++++++++++-- .../src/presets/aura/cascadeselect/index.js | 3 +- .../src/presets/lara/cascadeselect/index.js | 3 +- .../presets/material/cascadeselect/index.js | 3 +- .../src/presets/nora/cascadeselect/index.js | 3 +- 8 files changed, 94 insertions(+), 29 deletions(-) diff --git a/packages/primevue/src/cascadeselect/BaseCascadeSelect.vue b/packages/primevue/src/cascadeselect/BaseCascadeSelect.vue index 1cf8e5cb6..3031c819d 100644 --- a/packages/primevue/src/cascadeselect/BaseCascadeSelect.vue +++ b/packages/primevue/src/cascadeselect/BaseCascadeSelect.vue @@ -14,6 +14,10 @@ export default { optionGroupLabel: null, optionGroupChildren: null, placeholder: String, + breakpoint: { + type: String, + default: '960px' + }, variant: { type: String, default: null diff --git a/packages/primevue/src/cascadeselect/CascadeSelect.vue b/packages/primevue/src/cascadeselect/CascadeSelect.vue index 1a4b0e280..ca2065ce1 100644 --- a/packages/primevue/src/cascadeselect/CascadeSelect.vue +++ b/packages/primevue/src/cascadeselect/CascadeSelect.vue @@ -109,6 +109,7 @@ export default { $pcFluid: { default: null } }, outsideClickListener: null, + matchMediaListener: null, scrollHandler: null, resizeListener: null, overlay: null, @@ -122,7 +123,10 @@ export default { focusedOptionInfo: { index: -1, level: 0, parentKey: '' }, activeOptionPath: [], overlayVisible: false, - dirty: false + dirty: false, + mobileActive: false, + query: null, + queryMatches: false }; }, watch: { @@ -136,10 +140,12 @@ export default { mounted() { this.id = this.id || UniqueComponentId(); this.autoUpdateModel(); + this.bindMatchMediaListener(); }, beforeUnmount() { this.unbindOutsideClickListener(); this.unbindResizeListener(); + this.unbindMatchMediaListener(); if (this.scrollHandler) { this.scrollHandler.destroy(); @@ -150,6 +156,10 @@ export default { ZIndex.clear(this.overlay); this.overlay = null; } + + if (this.mobileActive) { + this.mobileActive = false; + } }, methods: { getOptionLabel(option) { @@ -571,6 +581,27 @@ export default { this.resizeListener = 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.mobileActive = false; + }; + + this.query.addEventListener('change', this.matchMediaListener); + } + }, + unbindMatchMediaListener() { + if (this.matchMediaListener) { + this.query.removeEventListener('change', this.matchMediaListener); + this.matchMediaListener = null; + } + }, isOptionMatched(processedOption) { return this.isValidOption(processedOption) && this.getProccessedOptionLabel(processedOption)?.toLocaleLowerCase(this.searchLocale).startsWith(this.searchValue.toLocaleLowerCase(this.searchLocale)); }, diff --git a/packages/primevue/src/cascadeselect/CascadeSelectSub.vue b/packages/primevue/src/cascadeselect/CascadeSelectSub.vue index cabe4727d..91bad4584 100644 --- a/packages/primevue/src/cascadeselect/CascadeSelectSub.vue +++ b/packages/primevue/src/cascadeselect/CascadeSelectSub.vue @@ -48,7 +48,6 @@ @option-focus-change="onOptionFocusChange" :pt="pt" :unstyled="unstyled" - :isParentMount="mounted" /> @@ -86,23 +85,7 @@ export default { templates: null, isParentMount: Boolean }, - data() { - return { - mounted: false - }; - }, - watch: { - isParentMount: { - handler(newValue) { - newValue && nestedPosition(this.container, this.level); - } - } - }, - mounted() { - // entering order correction when an option is selected - (this.isParentMount || this.level === 0) && nestedPosition(this.container, this.level); - this.mounted = true; - }, + methods: { getOptionId(processedOption) { return `${this.selectId}_${processedOption.key}`; diff --git a/packages/primevue/src/cascadeselect/style/CascadeSelectStyle.js b/packages/primevue/src/cascadeselect/style/CascadeSelectStyle.js index d83ed181d..d734c42e5 100644 --- a/packages/primevue/src/cascadeselect/style/CascadeSelectStyle.js +++ b/packages/primevue/src/cascadeselect/style/CascadeSelectStyle.js @@ -144,11 +144,15 @@ const theme = ({ dt }) => ` .p-cascadeselect-option-active { overflow: visible; - background: ${dt('cascadeselect.option.focus.background')}; - color: ${dt('cascadeselect.option.focus.color')}; } -.p-cascadeselect-option:not(.p-cascadeselect-option-selected):not(.p-disabled).p-focus { +.p-cascadeselect-option-active > .p-cascadeselect-option-content { + background: ${dt('cascadeselect.option.focus.background')}; + color: ${dt('cascadeselect.option.focus.color')}; + border-radius: ${dt('cascadeselect.option.border.radius')}; +} + +.p-cascadeselect-option:not(.p-cascadeselect-option-selected):not(.p-disabled).p-focus > .p-cascadeselect-option-content { background: ${dt('cascadeselect.option.focus.background')}; color: ${dt('cascadeselect.option.focus.color')}; } @@ -157,7 +161,7 @@ const theme = ({ dt }) => ` color: ${dt('cascadeselect.option.icon.focus.color')}; } -.p-cascadeselect-option-selected { +.p-cascadeselect-option-selected .p-cascadeselect-option-content { background: ${dt('cascadeselect.option.selected.background')}; color: ${dt('cascadeselect.option.selected.color')}; } @@ -188,6 +192,39 @@ const theme = ({ dt }) => ` height: ${dt('cascadeselect.option.icon.size')}; color: ${dt('cascadeselect.option.icon.color')}; } + +.p-cascadeselect-mobile-active .p-cascadeselect-option-content { + border-radius: ${dt('cascadeselect.option.border.radius')}; +} + +.p-cascadeselect-mobile-active-active .p-cascadeselect-list { + display: flex; + flex-direction: column; + top: 100%; + left: 0; + z-index: 1; +} + +.p-cascadeselect-mobile-active .p-cascadeselect-list > .p-cascadeselect-option > .p-cascadeselect-option-content .p-cascadeselect-group-icon { + margin-left: auto; + transition: transform 0.2s; +} + +.p-cascadeselect-mobile-active .p-cascadeselect-list .p-cascadeselect-group-icon { + transition: transform 0.2s; + transform: rotate(90deg); +} + +.p-cascadeselect-mobile-active .p-cascadeselect-option-active > .p-cascadeselect-option-content .p-cascadeselect-group-icon { + transform: rotate(-90deg); +} + +.p-cascadeselect-mobile-active .p-cascadeselect-option-list { + position: static; + box-shadow: none; + border: 0 none; + padding-left: ${dt('cascadeselect.list.mobile.indent')}; +} `; const inlineStyles = { @@ -198,6 +235,7 @@ const classes = { root: ({ instance, props }) => [ 'p-cascadeselect p-component p-inputwrapper', { + 'p-cascadeselect-mobile': instance.queryMatches, 'p-disabled': props.disabled, 'p-invalid': props.invalid, 'p-variant-filled': props.variant ? props.variant === 'filled' : instance.$primevue.config.inputStyle === 'filled' || instance.$primevue.config.inputVariant === 'filled', @@ -218,8 +256,13 @@ const classes = { dropdown: 'p-cascadeselect-dropdown', loadingIcon: 'p-cascadeselect-loading-icon', dropdownIcon: 'p-cascadeselect-dropdown-icon', - overlay: 'p-cascadeselect-overlay p-component', - listContainer: 'p-cascadeselect-list-container', + overlay: ({ instance }) => [ + 'p-cascadeselect-overlay p-component', + { + 'p-cascadeselect-mobile-active': instance.queryMatches + } + ], + listContainer: 'p-cascadeselect-list', list: 'p-cascadeselect-list', option: ({ instance, processedOption }) => [ 'p-cascadeselect-option', diff --git a/packages/themes/src/presets/aura/cascadeselect/index.js b/packages/themes/src/presets/aura/cascadeselect/index.js index f19c746d2..a96da0652 100644 --- a/packages/themes/src/presets/aura/cascadeselect/index.js +++ b/packages/themes/src/presets/aura/cascadeselect/index.js @@ -38,7 +38,8 @@ export default { }, list: { padding: '{list.padding}', - gap: '{list.gap}' + gap: '{list.gap}', + mobileIndent: '1rem' }, option: { focusBackground: '{list.option.focus.background}', diff --git a/packages/themes/src/presets/lara/cascadeselect/index.js b/packages/themes/src/presets/lara/cascadeselect/index.js index f19c746d2..7d2a9d0ff 100644 --- a/packages/themes/src/presets/lara/cascadeselect/index.js +++ b/packages/themes/src/presets/lara/cascadeselect/index.js @@ -38,7 +38,8 @@ export default { }, list: { padding: '{list.padding}', - gap: '{list.gap}' + gap: '{list.gap}', + mobileIndent: '1.25rem' }, option: { focusBackground: '{list.option.focus.background}', diff --git a/packages/themes/src/presets/material/cascadeselect/index.js b/packages/themes/src/presets/material/cascadeselect/index.js index e17764179..6b6fbcc09 100644 --- a/packages/themes/src/presets/material/cascadeselect/index.js +++ b/packages/themes/src/presets/material/cascadeselect/index.js @@ -38,7 +38,8 @@ export default { }, list: { padding: '{list.padding}', - gap: '{list.gap}' + gap: '{list.gap}', + mobileIndent: '1rem' }, option: { focusBackground: '{list.option.focus.background}', diff --git a/packages/themes/src/presets/nora/cascadeselect/index.js b/packages/themes/src/presets/nora/cascadeselect/index.js index f19c746d2..a96da0652 100644 --- a/packages/themes/src/presets/nora/cascadeselect/index.js +++ b/packages/themes/src/presets/nora/cascadeselect/index.js @@ -38,7 +38,8 @@ export default { }, list: { padding: '{list.padding}', - gap: '{list.gap}' + gap: '{list.gap}', + mobileIndent: '1rem' }, option: { focusBackground: '{list.option.focus.background}', From 2b1611d69bb8de62394460c11707a7e49753c61b Mon Sep 17 00:00:00 2001 From: GitHub Actions Bot <> Date: Fri, 4 Oct 2024 14:03:02 +0000 Subject: [PATCH 2/4] Update API doc --- apps/showcase/doc/common/apidoc/index.json | 9 ++++++ .../themes/types/cascadeselect/index.d.ts | 6 ++++ pnpm-lock.yaml | 31 +++++++++++-------- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/apps/showcase/doc/common/apidoc/index.json b/apps/showcase/doc/common/apidoc/index.json index 3ab3a9595..8921ad6de 100644 --- a/apps/showcase/doc/common/apidoc/index.json +++ b/apps/showcase/doc/common/apidoc/index.json @@ -75122,6 +75122,15 @@ "default": "", "description": "Gap of list" }, + { + "name": "list.mobileIndent", + "token": "cascadeselect.list.mobile.indent", + "optional": true, + "readonly": false, + "type": "string", + "default": "", + "description": "Mobile indent of list" + }, { "name": "option.focusBackground", "token": "cascadeselect.option.focus.background", diff --git a/packages/themes/types/cascadeselect/index.d.ts b/packages/themes/types/cascadeselect/index.d.ts index 6cf349853..227773089 100644 --- a/packages/themes/types/cascadeselect/index.d.ts +++ b/packages/themes/types/cascadeselect/index.d.ts @@ -221,6 +221,12 @@ export interface CascadeSelectDesignTokens extends ColorSchemeDesignToken Date: Fri, 4 Oct 2024 17:13:47 +0300 Subject: [PATCH 3/4] Update CascadeSelect.d.ts --- packages/primevue/src/cascadeselect/CascadeSelect.d.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/primevue/src/cascadeselect/CascadeSelect.d.ts b/packages/primevue/src/cascadeselect/CascadeSelect.d.ts index dcfb7873d..28e8f913f 100644 --- a/packages/primevue/src/cascadeselect/CascadeSelect.d.ts +++ b/packages/primevue/src/cascadeselect/CascadeSelect.d.ts @@ -291,6 +291,11 @@ export interface CascadeSelectProps { * Default text to display when no option is selected. */ placeholder?: string | undefined; + /** + * The breakpoint to define the maximum width boundary. + * @defaultValue 960px + */ + breakpoint?: string | undefined; /** * When present, it specifies that the component should have invalid state style. * @defaultValue false From ebdff4a2eed96d39441ddcada096816c8f3d0f49 Mon Sep 17 00:00:00 2001 From: GitHub Actions Bot <> Date: Fri, 4 Oct 2024 14:14:55 +0000 Subject: [PATCH 4/4] Update API doc --- apps/showcase/doc/common/apidoc/index.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/showcase/doc/common/apidoc/index.json b/apps/showcase/doc/common/apidoc/index.json index 8921ad6de..dfc1da545 100644 --- a/apps/showcase/doc/common/apidoc/index.json +++ b/apps/showcase/doc/common/apidoc/index.json @@ -8136,6 +8136,14 @@ "default": "", "description": "Default text to display when no option is selected." }, + { + "name": "breakpoint", + "optional": true, + "readonly": false, + "type": "string", + "default": "960px", + "description": "The breakpoint to define the maximum width boundary." + }, { "name": "invalid", "optional": true,