Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: migrate ItemsListInjection mixin #1460

Merged
merged 23 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7d99409
lock
annacv Apr 2, 2024
fad45e2
Merge branch 'main' of https://github.com/empathyco/x into feature/EM…
annacv Apr 8, 2024
15da996
feat: WIP migrate resultsList component
annacv Apr 9, 2024
2617e13
Merge branch 'main' of https://github.com/empathyco/x into feature/EM…
annacv Apr 9, 2024
c8ac1f4
feat: WIP migrate resultsList component
annacv Apr 9, 2024
ea4a02c
chore: migrate promoteds-list component
lauramargar Apr 18, 2024
18fe26a
chore: migrate next-queries-list component
lauramargar Apr 18, 2024
5b0a5c5
chore: migrate banners-list component
lauramargar Apr 18, 2024
7fcd99e
chore: update migration of results-list component
lauramargar Apr 18, 2024
5af69d7
Merge branch 'main' into feature/EMP-3792-Migrate-result-list
lauramargar Apr 24, 2024
e38a6dd
feat: migrate component tests
lauramargar May 2, 2024
57b677f
chore: remove ItemsListInjection mixin
lauramargar May 2, 2024
98ec59a
Merge branch 'main' into feature/EMP-3792-Migrate-result-list
lauramargar May 3, 2024
b46a37d
chore: add components to the playground
lauramargar May 7, 2024
fc3a4c9
Merge branch 'main' into feature/EMP-3792-Migrate-result-list
lauramargar May 7, 2024
eb0a8ec
chore: fix pr comments
lauramargar May 7, 2024
d1bb8f0
chore: return `slots` itself instead of renaming it
lauramargar May 7, 2024
a4425ea
chore: remove lock
lauramargar May 7, 2024
092566a
chore: add @remarks on `onInfiniteScrollEnd` function
lauramargar May 7, 2024
7e84a53
chore: move test-elements-list to x-modules folder and rm disable-max…
lauramargar May 8, 2024
89d3a28
chore: move modules config to x-module files
lauramargar May 8, 2024
83686a7
Merge branch 'main' into feature/EMP-3792-Migrate-result-list
lauramargar May 9, 2024
653b6b3
chore: remove eslint unbound-method
lauramargar May 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion packages/_vue3-migration-test/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { createStore } from 'vuex';
import { xPlugin } from '../../x-components/src/plugins/x-plugin';
import App from './App.vue';
import router from './router';
import { searchXModule } from './x-modules/search/x-module';
import { nextQueriesXModule } from './x-modules/next-queries/x-module';

// Warnings that cannot be solved in Vue 2 (a.k.a. breaking changes) are suppressed
const VUE_COMPAT_MODE = Number(import.meta.env.VITE_VUE_COMPAT_MODE);
Expand All @@ -30,5 +32,12 @@ const store = createStore({});
createApp(App as Component)
.use(router)
.use(store)
.use(xPlugin, { adapter, store })
.use(xPlugin, {
adapter,
store,
__PRIVATE__xModules: {
search: searchXModule,
nextQueries: nextQueriesXModule
}
})
.mount('#app');
6 changes: 6 additions & 0 deletions packages/_vue3-migration-test/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
TestSortDropdown,
TestSortList,
TestSortPickerList,
TestElementsList,
TestBaseColumnPickerDropdown
} from './';

Expand Down Expand Up @@ -56,6 +57,11 @@ const routes = [
path: '/sort-picker-list',
name: 'SortPickerList',
component: TestSortPickerList
},
{
path: '/elements-list',
name: 'ElementsList',
component: TestElementsList
}
];

Expand Down
1 change: 1 addition & 0 deletions packages/_vue3-migration-test/src/x-modules/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './search';
export { default as TestElementsList } from './test-elements-list.vue';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './x-module';
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { getNextQueriesStub } from '../../../../x-components/src/__stubs__/next-queries-stubs.factory';
import { PrivateXModuleOptions } from '../../../../x-components/src/plugins';
import { NextQueriesXModule } from '../../../../x-components/src/x-modules/next-queries';

export const nextQueriesXModule = {
storeModule: {
state: {
query: 'dress',
nextQueries: getNextQueriesStub(),
status: 'success'
}
}
} as PrivateXModuleOptions<NextQueriesXModule>;
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './components';
export * from './x-module';
17 changes: 17 additions & 0 deletions packages/_vue3-migration-test/src/x-modules/search/x-module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { getResultsStub } from '../../../../x-components/src/__stubs__/results-stubs.factory';
import { getBannersStub } from '../../../../x-components/src/__stubs__/banners-stubs.factory';
import { getPromotedsStub } from '../../../../x-components/src/__stubs__/promoteds-stubs.factory';
import { PrivateXModuleOptions } from '../../../../x-components/src/plugins';
import { SearchXModule } from '../../../../x-components/src/x-modules/search';

export const searchXModule = {
storeModule: {
state: {
query: 'dress',
results: getResultsStub(10),
promoteds: getPromotedsStub(),
banners: getBannersStub(),
status: 'success'
}
}
} as PrivateXModuleOptions<SearchXModule>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<template>
<LocationProvider location="results">
<ResultsList>
<PromotedsList>
<BannersList>
<NextQueriesList>
<BaseGrid>
<template #result="{ item: result }">
{{ result.id }}
</template>

<template #banner="{ item: banner }">
{{ banner.id }}
</template>

<template #promoted="{ item: promoted }">
{{ promoted.title }}
</template>
<template #next-queries-group="{ item: { nextQueries } }">
<li v-for="nextQuery in nextQueries" :key="nextQuery.query" class="next-query">
{{ nextQuery.query }}
</li>
</template>
</BaseGrid>
</NextQueriesList>
</BannersList>
</PromotedsList>
</ResultsList>
</LocationProvider>
</template>

<script setup lang="ts">
import PromotedsList from '../../../x-components/src/x-modules/search/components/promoteds-list.vue';
import ResultsList from '../../../x-components/src/x-modules/search/components/results-list.vue';
import BannersList from '../../../x-components/src/x-modules/search/components/banners-list.vue';
import BaseGrid from '../../../x-components/src/components/base-grid.vue';
import LocationProvider from '../../../x-components/src/components/location-provider.vue';
import NextQueriesList from '../../../x-components/src/x-modules/next-queries/components/next-queries-list.vue';
</script>
42 changes: 31 additions & 11 deletions packages/x-components/src/components/base-grid.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
the item using that slot composition to render.
@binding {item} item - Item to render
-->
<slot v-if="$scopedSlots[slotName]" :name="slotName" :item="item" />
<slot v-if="slots[slotName]" :name="slotName" :item="item" />
<!--
@slot (required) Default item rendering. This slot will be used by default for rendering
the item without an specific slot implementation.
Expand All @@ -41,10 +41,10 @@
ref,
watch
} from 'vue';
import { useResizeObserver } from '@vueuse/core';
import { MaybeComputedElementRef, useResizeObserver } from '@vueuse/core';
import { toKebabCase } from '../utils/string';
import { ListItem, VueCSSClasses } from '../utils/types';
import { AnimationProp } from '../types/index';
import { AnimationProp } from '../types/animation-prop';
import { useXBus } from '../composables/use-x-bus';
import { LIST_ITEMS_KEY } from './decorators/injection.consts';

Expand Down Expand Up @@ -103,7 +103,11 @@
type: Array as PropType<ListItem[]>
}
},
setup(props) {
setup(props, { slots }) {
type ElementRef = {
$el: HTMLElement;
};

const xBus = useXBus();
/**
* It injects {@link ListItem} provided by an ancestor.
Expand All @@ -112,7 +116,7 @@
*/
const injectedListItems = inject<Ref<ListItem[]>>(LIST_ITEMS_KEY as string);

const gridEl = ref<HTMLElement | null>(null);
const gridEl = ref<ElementRef | HTMLElement | null>(null);

let renderedColumnsNumber = ref(0);
/**
Expand Down Expand Up @@ -193,16 +197,28 @@
})
);

/**
* Checks if a given value is an `ElementRef` object.
*
* @param value - The value to check.
* @returns `true` if the value is an `ElementRef` object, `false` otherwise.
*
* @internal
*/
const isElementRef = (value: any): value is ElementRef => {
return value && value.$el instanceof HTMLElement;
};

/**
* Updates the number of columns rendered inside the grid.
*
* @internal
*/
const updateRenderedColumnsNumber = (): void => {
if (gridEl.value !== null && gridEl.value instanceof HTMLElement) {
const { gridTemplateColumns } = getComputedStyle(gridEl.value);
renderedColumnsNumber.value = gridTemplateColumns.split(' ').length;
}
const { gridTemplateColumns } = getComputedStyle(
isElementRef(gridEl.value) ? gridEl.value.$el : (gridEl.value as Element)
);
renderedColumnsNumber.value = gridTemplateColumns.split(' ').length;
};

/**
Expand All @@ -211,14 +227,18 @@
* @internal
*/
// eslint-disable-next-line @typescript-eslint/unbound-method
lauramargar marked this conversation as resolved.
Show resolved Hide resolved
const resizeObserver = useResizeObserver(gridEl, updateRenderedColumnsNumber);
const resizeObserver = useResizeObserver(
gridEl as MaybeComputedElementRef,
updateRenderedColumnsNumber
);
onBeforeUnmount(() => resizeObserver.stop());

return {
gridItems,
cssClasses,
style,
gridEl
gridEl,
slots
};
}
});
Expand Down
1 change: 0 additions & 1 deletion packages/x-components/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,5 @@ export * from './decorators/debounce.decorators';
export * from './decorators/injection.consts';
export * from './decorators/injection.decorators';
export * from './decorators/store.decorators';
export * from './items-list-injection.mixin';
export * from './x-component.mixin';
export * from './x-component.utils';

This file was deleted.

99 changes: 59 additions & 40 deletions packages/x-components/src/components/items-list.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,56 +23,75 @@
</template>

<script lang="ts">
import Vue from 'vue';
import { Component, Mixins, Prop } from 'vue-property-decorator';
import { computed, defineComponent, PropType } from 'vue';
import { ListItem } from '../utils/types';
import { toKebabCase } from '../utils/string';
import { dynamicPropsMixin } from './dynamic-props.mixin';
import { animationProp } from '../utils/options-api';

/**
* It renders a list of {@link ListItem} providing a slot for each `slotName` which depends on
* the `modelName`of the item.
*
* @public
*/
@Component
export default class ItemsList extends Mixins(dynamicPropsMixin(['itemClass'])) {
/**
* Animation component that will be used to animate the list.
*
* @public
*/
@Prop({ default: 'ul' })
protected animation!: Vue | string;
export default defineComponent({
name: 'ItemsList',
props: {
/**
* Animation component that will be used to animate the list.
*
* @public
*/
animation: {
type: animationProp,
default: 'ul'
},

/**
* List of items.
*
* @public
*/
@Prop({ required: true })
protected items!: ListItem[];
/**
* List of items.
*
* @public
*/
items: {
type: Array as PropType<ListItem[]>,
required: true
},

/**
* The list of the items with additional properties.
*
* @returns A list of items with `dataTest`, `class` and the `slotName` for each item.
*
* @internal
*/
protected get computedItems(): {
dataTest: string;
class: Array<string | undefined>;
}[] {
return this.items.map(item => {
const modelName = toKebabCase(item.modelName);
return {
...item,
dataTest: `${modelName}s-list-item`,
class: [`x-${modelName}s-list-item`, this.itemClass],
slotName: modelName
};
});
/**
* Item's classes.
*
* @public
*/
itemClass: {
type: String
}
},
setup(props) {
/**
* The list of the items with additional properties.
*
* @returns A list of items with `dataTest`, `class` and the `slotName` for each item.
*
* @internal
*/
const computedItems = computed(
(): {
dataTest: string;
class: Array<string | undefined>;
}[] => {
return props.items.map(item => {
const modelName = toKebabCase(item.modelName);
return {
...item,
dataTest: `${modelName}s-list-item`,
class: [`x-${modelName}s-list-item`, props.itemClass],
slotName: modelName
};
});
}
);

return { computedItems };
}
}
});
</script>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { defineComponent, PropType, provide, toRef } from 'vue';
import { FeatureLocation } from '../types';
import { useNoElementRender } from '../composables/index';
import { useNoElementRender } from '../composables/use-no-element-render';

/**
* Location Provider component.
Expand Down
Loading
Loading