diff --git a/packages/_vue3-migration-test/src/components/animations/index.ts b/packages/_vue3-migration-test/src/components/animations/index.ts
index f1ee0800dd..a102e70e6b 100644
--- a/packages/_vue3-migration-test/src/components/animations/index.ts
+++ b/packages/_vue3-migration-test/src/components/animations/index.ts
@@ -4,3 +4,4 @@ export { default as TestCollapseWidth } from './test-collapse-width.vue';
export { default as TestCrossFade } from './test-cross-fade.vue';
export { default as TestFade } from './test-fade.vue';
export { default as TestFadeAndSlide } from './test-fade-and-slide.vue';
+export { default as TestStaggeredFadeAndSlide } from './test-staggered-fade-and-slide.vue';
diff --git a/packages/_vue3-migration-test/src/components/animations/test-staggered-fade-and-slide.vue b/packages/_vue3-migration-test/src/components/animations/test-staggered-fade-and-slide.vue
new file mode 100644
index 0000000000..6d3a6a9d54
--- /dev/null
+++ b/packages/_vue3-migration-test/src/components/animations/test-staggered-fade-and-slide.vue
@@ -0,0 +1,72 @@
+
+ Dinamic content:
+
+
+
+
+
+ {{ item.id }} - {{ item.name }}
+
+
+
+
+
+ Animation as prop
+
+
+ {{ suggestion.query }}
+
+
+
+
+ Static content:
+
+ Element to animate
+ Element to animate
+ Element to animate
+
+
+
+
diff --git a/packages/_vue3-migration-test/src/components/test-search.vue b/packages/_vue3-migration-test/src/components/test-search.vue
index 52a714c1c7..d16fa58f27 100644
--- a/packages/_vue3-migration-test/src/components/test-search.vue
+++ b/packages/_vue3-migration-test/src/components/test-search.vue
@@ -19,6 +19,7 @@
style="--x-size-min-width-grid-item: 150px"
class="x-gap-12"
:columns="4"
+ :animation="Vue3StaggeredFadeAndSlide"
>
@@ -38,6 +39,7 @@
import ClearSearchInput from '../../../x-components/src/x-modules/search-box/components/clear-search-input.vue';
import SearchButton from '../../../x-components/src/x-modules/search-box/components/search-button.vue';
import { use$x } from '../../../x-components/src/composables/use-$x';
+ import Vue3StaggeredFadeAndSlide from '../../../x-components/src/components/animations/vue3-staggered-fade-and-slide.vue';
// TODO `$x` name cannot be used while XPlugin defines its own `this.$x` in the mixin
const _$x = use$x();
diff --git a/packages/_vue3-migration-test/src/router.ts b/packages/_vue3-migration-test/src/router.ts
index b085e6abb8..519946ce05 100644
--- a/packages/_vue3-migration-test/src/router.ts
+++ b/packages/_vue3-migration-test/src/router.ts
@@ -12,6 +12,7 @@ import {
TestFacets,
TestFade,
TestFadeAndSlide,
+ TestStaggeredFadeAndSlide,
TestScroll,
TestSortDropdown,
TestSortList,
@@ -87,6 +88,11 @@ const routes = [
name: 'FadeAndSlide',
component: TestFadeAndSlide
},
+ {
+ path: '/staggered-fade-and-slide',
+ name: 'StaggeredFadeAndSlide',
+ component: TestStaggeredFadeAndSlide
+ },
{
path: '/base-dropdown',
name: 'BaseDropdown',
diff --git a/packages/x-components/src/components/animations/index.ts b/packages/x-components/src/components/animations/index.ts
index 26240a7f04..4bddd1d953 100644
--- a/packages/x-components/src/components/animations/index.ts
+++ b/packages/x-components/src/components/animations/index.ts
@@ -5,6 +5,7 @@ export { default as CrossFade } from './cross-fade.vue';
export { default as Fade } from './fade.vue';
export { default as FadeAndSlide } from './fade-and-slide.vue';
export { default as StaggeredFadeAndSlide } from './staggered-fade-and-slide.vue';
+export { default as Vue3StaggeredFadeAndSlide } from './vue3-staggered-fade-and-slide.vue';
export { default as StaggeringTransitionGroup } from './staggering-transition-group.vue';
export { createDirectionalAnimationFactory } from './create-directional-animation-factory';
export { animateClipPath } from './animate-clip-path/animate-clip-path.factory';
diff --git a/packages/x-components/src/components/animations/vue3-staggered-fade-and-slide.vue b/packages/x-components/src/components/animations/vue3-staggered-fade-and-slide.vue
new file mode 100644
index 0000000000..2ac72150da
--- /dev/null
+++ b/packages/x-components/src/components/animations/vue3-staggered-fade-and-slide.vue
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
+
+
+
+
+
+The Staggered fade and slide components works as the normal fade and slide components, but it also
+adds a configurable delay to each transition.
+
+## Example
+
+### Used with animatable components
+
+```vue
+
+```
+
+### Used as a regular component:
+
+This components exposes all the props and events of the Staggering transition group, like the `tag`
+or the `stagger` props:
+
+```vue
+
+ Element to animate
+ Element to animate
+ Element to animate
+
+```
+
diff --git a/packages/x-components/src/components/base-grid.vue b/packages/x-components/src/components/base-grid.vue
index 1d4a096948..b3451f1ce8 100644
--- a/packages/x-components/src/components/base-grid.vue
+++ b/packages/x-components/src/components/base-grid.vue
@@ -1,7 +1,6 @@
(null);
+
+ /**
+ * ResizeObserver instance to keep track of the number of columns rendered inside the grid.
+ */
+ let resizeObserver: { stop: () => void };
+
/**
* It injects {@link ListItem} provided by an ancestor.
*
@@ -119,9 +131,6 @@
undefined
);
- const gridEl = ref(null);
-
- let renderedColumnsNumber = ref(0);
/**
* Emits the {@link XEventsTypes.RenderedColumnsNumberChanged}
* event whenever the number of columns rendered inside the grid changes.
@@ -131,9 +140,7 @@
watch(
renderedColumnsNumber,
() => xBus.emit('RenderedColumnsNumberChanged', renderedColumnsNumber.value),
- {
- immediate: false
- }
+ { immediate: false }
);
/**
@@ -201,45 +208,45 @@
);
/**
- * 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.
+ * Updates the number of columns rendered inside the grid.
*
* @internal
*/
- const isElementRef = (value: any): value is ElementRef => {
- return value && value.$el instanceof HTMLElement;
+ const updateRenderedColumnsNumber = (): void => {
+ if (rootEl.value) {
+ const { gridTemplateColumns } = getComputedStyle(rootEl.value);
+ renderedColumnsNumber.value = gridTemplateColumns.split(' ').length;
+ }
};
/**
- * Updates the number of columns rendered inside the grid.
+ * Initialises the rendered columns number and sets a ResizeObserver to keep it updated.
*
* @internal
*/
- const updateRenderedColumnsNumber = (): void => {
- const { gridTemplateColumns } = getComputedStyle(
- isElementRef(gridEl.value) ? gridEl.value.$el : (gridEl.value as Element)
+ onMounted(() => {
+ /**
+ * Using querySelector to get the root element of the grid instead of using the ref directly
+ * because with the introductions of Fragments, Vue returns every DOM element inside the component.
+ */
+ rootEl.value = document.querySelector('.x-base-grid');
+ resizeObserver = useResizeObserver(
+ rootEl as MaybeComputedElementRef,
+ updateRenderedColumnsNumber
);
- renderedColumnsNumber.value = gridTemplateColumns.split(' ').length;
- };
+ });
/**
- * Initialises the rendered columns number and sets a ResizeObserver to keep it updated.
+ * Stops the ResizeObserver when the component is unmounted.
*
* @internal
*/
- const resizeObserver = useResizeObserver(
- gridEl as MaybeComputedElementRef,
- updateRenderedColumnsNumber
- );
onBeforeUnmount(() => resizeObserver.stop());
return {
gridItems,
cssClasses,
style,
- gridEl,
slots
};
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7efe38f2e8..9441e48fde 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1,4 +1,4 @@
-lockfileVersion: '6.0'
+lockfileVersion: '6.1'
settings:
autoInstallPeers: true
@@ -21729,6 +21729,7 @@ packages:
resolution: { directory: packages/eslint-plugin-x, type: directory }
id: file:packages/eslint-plugin-x
name: '@empathyco/eslint-plugin-x'
+ version: 2.0.2
engines: { node: '>=18' }
peerDependencies:
eslint: ~8.32.0