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

Create carousel hooks #132

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft

Conversation

leroykorterink
Copy link
Collaborator

No description provided.

@leroykorterink leroykorterink added enhancement New feature or request help wanted Extra attention is needed labels Apr 26, 2023
@leroykorterink leroykorterink requested review from ThaNarie and a team April 26, 2023 15:39
@leroykorterink leroykorterink self-assigned this Apr 26, 2023
Copy link
Member

@ThaNarie ThaNarie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mostly reviewed the code, and not the architecture, since without any documentation and examples it's really tough to understand how everything fits together.

packages/react-animation/src/carousel/hooks/useCarousel.ts Outdated Show resolved Hide resolved
packages/react-animation/src/carousel/hooks/useCarousel.ts Outdated Show resolved Hide resolved
Comment on lines +10 to +11
getElementOffset<T extends HTMLElement>(element: T): number;
getElementSize<T extends HTMLElement>(element: T, sizeType?: SizeType): number;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be missing something, but what's the benefit of the T generic here? It's only used in one place (the element parameter), so the type could be specified just there as well?

const size = getCarouselSize(triggerRef.current, type);
const position = gsap.getProperty(proxyRef.current, type) as number;

return (position % size) / size;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this correctly handle negative values for position, since getCarouselIndex tried to use Math.abs, might be needed her as well, or at least the correct version of that.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this didn't worked for me, also the calculations were wrong because it didn't take the container width into account. This worked for me:
return Math.abs( (position % (size - triggerRef.current.offsetWidth + 0.01)) / (size - triggerRef.current.offsetWidth + 0.01), );

Comment on lines 3 to 9
/**
* Returns a number between 0 and 1 representing the progress of the target slide.
*
* -1 represents the slide being completely off the left side of the carousel.
* 1 represents the slide being completely off the right side of the carousel.
* 0 represents the slide being at the left side of the carousel.
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should have a few definitions and examples to clarify this better.

For example:

  • what does "the carousel" mean in this context? Is it the visible bounding box where the carousel sits on the screen (e.g. in a container, that is often full-bleed, or could have paddings)
  • or is it the focussed around a single "focus" slot that would be marked as a "center" one
  • or something else

And then how that would impact the progress, I presume the following, in a carousel where 3 items would fit on screen:

  • if a slide moves from the left side off the screen to it's left position, that would move for example 300px from -1 to 0.
  • then if the slide would continue moving to the right, it would travel the same distance each time, but instead go from 0 to 0.33 (position 2), then 0.33 to 0.66 (position 3), and finally to progress 1 (off screen).

If the above is true, this would also mean that if you resize your screen, and suddenly 4 items would fit in the carousel, the progress of a slide at position one would be updated from 0.33 to 0.25, even though it wouldn't move.

I'm not saying this is bad, it's just that this isn't clearly documented yet, and might be important to understand to make use of it.

@leroykorterink leroykorterink changed the title Copy carousel hooks to current package Create carousel hooks May 1, 2023
@VictorGa VictorGa self-assigned this Aug 4, 2023
0,
children.findIndex(
// prettier-ignore
(child) => getElementOffset(child) + (getElementSize(child) * alignment) > ((position % size) + size) % size,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This didn't seem to work for me.
Index started at 0 and then went to 7 ( max ) and then it counted down.

This seemed to fix it ( maybe there is a better way to fix it tho ):
return Math.max( 0, children.findIndex( // prettier-ignore (child) => getElementOffset(child) + (getElementSize(child) * alignment) > Math.abs((((position % size) + size) % size) - size), ), );

console.warn("Can't set bounds, sliderRef is undefined");
return;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In foundation I added an extra check for the example AutoHeight to work without an insane amount of re-renders. Please see full code changes in foundation.

if (type === CarouselType.X && containerWidth.current === sliderRef.current.offsetWidth) { return; }

draggable.current.applyBounds(variablesRef.current?.bounds ?? null);
}, [draggable, variablesRef]);

const onResize = useRafCallback(() => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In foundation I added an extra check for the example AutoHeight to work without an insane amount of re-renders. Please see full code changes in foundation.

if (type === CarouselType.X && containerWidth.current === triggerRef.current?.offsetWidth) { return; }

export type CarouselControls = {
next(): Promise<void>;
previous(): Promise<void>;
index(index: number): Promise<void>;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added the option to set initial index to Foundation. See comments below for the code I've added.
Still behaves a bit buggy:

setInitial(index: number): Promise<void>;


return useMemo<CarouselControls>(() => {
function getPositionUpdater<T extends keyof CarouselControls>(
control?: T,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

immediate = false,

await gsap.to(proxyRef.current, {
..._tweenVariables,
[type]: position,
onUpdate() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onUpdate() { if (!immediate) { update?.(); } }
onComplete() { update?.(); }

next: getPositionUpdater('next'),
previous: getPositionUpdater('previous'),
index: getPositionUpdater(),
};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setInitial: getPositionUpdater('index', true)

@@ -12,7 +12,8 @@ export default {
};

const Amount = 6;
const Elements = Array.from({ length: Amount });
/* eslint-disable unicorn/new-for-builtins */
const Elements: Array<number> = [...Array(8).keys()];
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking :), this variable should start with a lower case character.

return;
}
[draggableRef.current = null] = draggable.create(target.current, {
...variables,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to create a new draggable instance when any of the dependencies change? It's not reactive at all now which, this isn't in line with how the other hooks work that we create.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants