diff --git a/src/components/CiceroneOverlay/hooks/useCiceroneOverlayViewModel/__tests__/useCiceroneOverlayViewModel.test.ts b/src/components/CiceroneOverlay/hooks/useCiceroneOverlayViewModel/__tests__/useCiceroneOverlayViewModel.test.ts index 2e4bb0b..53b35be 100644 --- a/src/components/CiceroneOverlay/hooks/useCiceroneOverlayViewModel/__tests__/useCiceroneOverlayViewModel.test.ts +++ b/src/components/CiceroneOverlay/hooks/useCiceroneOverlayViewModel/__tests__/useCiceroneOverlayViewModel.test.ts @@ -111,6 +111,19 @@ describe('useCiceroneOverlayViewModel', () => { }); }); + describe('cardProps', () => { + it('Carries the positioning data renderCard needs to place itself', async () => { + const { result } = await renderHook(() => + useCiceroneOverlayViewModel(mountProps()), + ); + + expect(result.current.cardProps.layout).toEqual(result.current.layout); + expect(result.current.cardProps.width).toBe(result.current.cardWidth); + expect(result.current.cardProps.containerHeight).toBe(result.current.screen.height); + expect(result.current.cardProps.isExiting).toBe(false); + }); + }); + describe('cardWidth', () => { it('Uses the prototype width unless the consumer overrides it', async () => { const { result } = await renderHook(() => diff --git a/src/components/CiceroneOverlay/hooks/useCiceroneOverlayViewModel/index.ts b/src/components/CiceroneOverlay/hooks/useCiceroneOverlayViewModel/index.ts index 44e8a08..3737016 100644 --- a/src/components/CiceroneOverlay/hooks/useCiceroneOverlayViewModel/index.ts +++ b/src/components/CiceroneOverlay/hooks/useCiceroneOverlayViewModel/index.ts @@ -84,12 +84,16 @@ export const useCiceroneOverlayViewModel = (props: ICiceroneOverlayProps) => { placement, palette, labels, + layout, + width: cardWidth, + containerHeight: screen.height, + isExiting: props.isExiting, next: props.next, previous: props.previous, skip: props.skip, stop: props.stop, }), - [step, props, placement, palette, labels], + [step, props, placement, palette, labels, layout, cardWidth, screen.height], ); const overlayPress = options.overlayPress ?? 'next'; diff --git a/src/components/CiceroneOverlay/index.tsx b/src/components/CiceroneOverlay/index.tsx index 4b2a1c4..86bb1ef 100644 --- a/src/components/CiceroneOverlay/index.tsx +++ b/src/components/CiceroneOverlay/index.tsx @@ -10,8 +10,6 @@ export const CiceroneOverlay: React.FC = (props) => { const { theme, isHighlight, - cardWidth, - layout, cardProps, geometry, screen, @@ -44,14 +42,7 @@ export const CiceroneOverlay: React.FC = (props) => { {options.renderCard ? ( options.renderCard(cardProps) ) : ( - + )} ); diff --git a/src/components/TourCard/types/ITourCardProps.ts b/src/components/TourCard/types/ITourCardProps.ts index b6ea323..edfc1d3 100644 --- a/src/components/TourCard/types/ITourCardProps.ts +++ b/src/components/TourCard/types/ITourCardProps.ts @@ -1,11 +1,6 @@ import type { StyleProp, ViewStyle } from 'react-native'; -import type { ICardLayout, ICiceroneCardProps } from '@/types'; +import type { ICiceroneCardProps } from '@/types'; export interface ITourCardProps extends ICiceroneCardProps { - layout: ICardLayout; - width: number; - /** The overlay's box, which the layout was measured against. */ - containerHeight: number; - isExiting: boolean; style?: StyleProp; } diff --git a/src/types/ICiceroneCardProps.ts b/src/types/ICiceroneCardProps.ts index cac6dfa..d0400c8 100644 --- a/src/types/ICiceroneCardProps.ts +++ b/src/types/ICiceroneCardProps.ts @@ -1,3 +1,4 @@ +import type { ICardLayout } from './ICardLayout'; import type { ICiceroneCardPalette } from './ICiceroneCardPalette'; import type { ICiceroneLabels } from './ICiceroneLabels'; import type { ICiceronePlacement } from './ICiceronePlacement'; @@ -12,6 +13,11 @@ export interface ICiceroneCardProps { placement: ICiceronePlacement; palette: ICiceroneCardPalette; labels: ICiceroneLabels; + layout: ICardLayout; + width: number; + /** The overlay's box, which the layout was measured against. */ + containerHeight: number; + isExiting: boolean; next: () => void; previous: () => void; skip: () => void; diff --git a/website/docs/api.md b/website/docs/api.md index cf5970e..12ff00d 100644 --- a/website/docs/api.md +++ b/website/docs/api.md @@ -93,4 +93,13 @@ What `renderCard` receives. | `placement` | `'top' \| 'bottom'` | | `palette` | `ICiceroneCardPalette` | | `labels` | `ICiceroneLabels` | +| `layout` | `ICardLayout` | +| `width` | `number` | +| `containerHeight` | `number` | +| `isExiting` | `boolean` | | `next` / `previous` / `skip` / `stop` | `() => void` | + +`layout`, `width` and `containerHeight` are what the built-in card uses to position itself +next to the target — `left`/`arrowLeft` from `layout`, anchored against `containerHeight` +depending on `placement`. `isExiting` drives the exit animation. A custom `renderCard` needs +all four to place itself the same way; see [Replacing the card](./theming.md#replacing-the-card). diff --git a/website/docs/theming.md b/website/docs/theming.md index 96c311b..ec849cc 100644 --- a/website/docs/theming.md +++ b/website/docs/theming.md @@ -102,18 +102,42 @@ you draw your own. The spotlight, ring and placement stay as they are. ```tsx ( - - )} + renderCard={({ + step, + index, + total, + isLast, + next, + skip, + placement, + layout, + width, + containerHeight, + }) => { + const anchorY = + placement === 'bottom' ? (layout.top ?? 0) : containerHeight - (layout.bottom ?? 0); + + return ( + + ); + }} /> ``` -Positioning is on you. The `placement` and `layout` you get tell you which side the tour -picked and where it would have put its own card. +Positioning is on you. `placement` tells you which side the tour picked; `layout`, `width` +and `containerHeight` are the same numbers `TourCard` itself uses to land there — see +[`ICiceroneCardProps`](./api.md#iciceronecardprops) for what each one means. diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/api.md b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/api.md index 3331946..87c5119 100644 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/api.md +++ b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/api.md @@ -93,4 +93,13 @@ O que o `renderCard` recebe. | `placement` | `'top' \| 'bottom'` | | `palette` | `ICiceroneCardPalette` | | `labels` | `ICiceroneLabels` | +| `layout` | `ICardLayout` | +| `width` | `number` | +| `containerHeight` | `number` | +| `isExiting` | `boolean` | | `next` / `previous` / `skip` / `stop` | `() => void` | + +`layout`, `width` e `containerHeight` são o que o card embutido usa para se posicionar ao +lado do alvo — `left`/`arrowLeft` vêm de `layout`, ancorado em `containerHeight` conforme o +`placement`. `isExiting` controla a animação de saída. Um `renderCard` customizado precisa +dos quatro para se posicionar do mesmo jeito; veja [Trocando o card](./theming.md#trocando-o-card). diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/theming.md b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/theming.md index 1d9b09d..80f4676 100644 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/theming.md +++ b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/theming.md @@ -103,18 +103,42 @@ desenhar o seu. O holofote, o anel e o posicionamento continuam como estão. ```tsx ( - - )} + renderCard={({ + step, + index, + total, + isLast, + next, + skip, + placement, + layout, + width, + containerHeight, + }) => { + const anchorY = + placement === 'bottom' ? (layout.top ?? 0) : containerHeight - (layout.bottom ?? 0); + + return ( + + ); + }} /> ``` -O posicionamento fica com você. O `placement` e o `layout` que chegam dizem qual lado o tour -escolheu e onde ele teria posto o próprio card. +O posicionamento fica com você. `placement` diz qual lado o tour escolheu; `layout`, `width` +e `containerHeight` são os mesmos números que o próprio `TourCard` usa para se posicionar — +veja [`ICiceroneCardProps`](./api.md#iciceronecardprops) para o que cada um significa.