Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
alvarodE committed May 9, 2024
2 parents 2a0f9a9 + a89fb51 commit 22b0250
Show file tree
Hide file tree
Showing 22 changed files with 825 additions and 594 deletions.
6 changes: 5 additions & 1 deletion packages/_vue3-migration-test/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { xPlugin } from '../../x-components/src/plugins/x-plugin';
import { facetsXModule } from '../../x-components/src/x-modules/facets/x-module';
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';
import { scrollXModule, testFacetsXModule } from './';

// Warnings that cannot be solved in Vue 2 (a.k.a. breaking changes) are suppressed
Expand Down Expand Up @@ -38,7 +40,9 @@ createApp(App as Component)
initialXModules: [facetsXModule],
__PRIVATE__xModules: {
facets: testFacetsXModule,
scroll: scrollXModule
nextQueries: nextQueriesXModule,
scroll: scrollXModule,
search: searchXModule
}
})
.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 @@ -5,6 +5,7 @@ import {
TestBaseColumnPickerList,
TestBaseDropdown,
TestBaseEventButton,
TestElementsList,
TestFacets,
TestFade,
TestScroll,
Expand Down Expand Up @@ -68,6 +69,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,3 +1,4 @@
export * from './facets';
export * from './search';
export { default as TestElementsList } from './test-elements-list.vue';
export * from './scroll';
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>;
39 changes: 39 additions & 0 deletions packages/_vue3-migration-test/src/x-modules/test-elements-list.vue
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>
43 changes: 31 additions & 12 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,32 +197,47 @@
})
);
/**
* 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;
};
/**
* Initialises the rendered columns number and sets a ResizeObserver to keep it updated.
*
* @internal
*/
// eslint-disable-next-line @typescript-eslint/unbound-method
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';
45 changes: 0 additions & 45 deletions packages/x-components/src/components/items-list-injection.mixin.ts

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>
2 changes: 1 addition & 1 deletion packages/x-components/src/components/location-provider.vue
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

0 comments on commit 22b0250

Please sign in to comment.