@impulse-ui-native/pagination 15.0.4 → 16.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
# @impulse-ui-native/pagination
|
|
2
|
-
|
|
3
|
-
Token-aware page navigation for React Native mobile applications.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```sh
|
|
8
|
-
pnpm add @impulse-ui-native/pagination
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
Render the component inside `ThemeProvider` from `@impulse-ui-native/theme`.
|
|
12
|
-
The package expects compatible `react`, `react-native`, and `react-native-svg`
|
|
13
|
-
peer dependencies in the host application.
|
|
14
|
-
|
|
15
|
-
## Usage
|
|
16
|
-
|
|
17
|
-
```tsx
|
|
18
|
-
import { Pagination } from "@impulse-ui-native/pagination";
|
|
19
|
-
|
|
20
|
-
export function ResultsPagination() {
|
|
21
|
-
return <Pagination defaultPage={1} pageCount={12} />;
|
|
22
|
-
}
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
Use `page` and `onPageChange` for controlled state, or `defaultPage` for
|
|
26
|
-
uncontrolled state. Page values are normalized to the available range.
|
|
27
|
-
|
|
28
|
-
Set `compact` for the mobile-friendly previous/status/next layout:
|
|
29
|
-
|
|
30
|
-
```tsx
|
|
31
|
-
<Pagination compact defaultPage={3} pageCount={12} />
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
The control supports `small`, `medium`, and `large` sizes. Its visible page
|
|
35
|
-
window adapts to the measured width: it shows up to seven page items, condenses
|
|
36
|
-
to five items around the current page, and falls back to the compact status
|
|
37
|
-
layout when space is tighter. Set `compact` to force that layout. Override
|
|
38
|
-
`getCompactLabel` to localize the visible compact status text.
|
|
39
|
-
|
|
40
|
-
Pagination items use the shared primitives `Pressable`; pressed feedback comes
|
|
41
|
-
from that primitive and is not modeled as Pagination state or theme tokens.
|
|
42
|
-
|
|
43
|
-
## Repository palette consistency
|
|
44
|
-
|
|
45
|
-
Pagination accepts `tone="neutral" | "primary" | "secondary"` (default primary).
|
|
46
|
-
The current page uses the shared filled Button palette. Disabled controls use the
|
|
47
|
-
shared unavailable filled palette; unselected pages and compact counts remain
|
|
48
|
-
neutral. Custom theme states move to pagination.colors[tone].
|
|
49
|
-
|
|
50
|
-
## Agent and design reference
|
|
51
|
-
|
|
52
|
-
Start with the [capability guide](../../docs/design-system/capabilities/pagination.md) for supported exports, props, defaults, composition rules, setup, and recipes. Use the [component chooser](../../docs/design-system/component-chooser.md) to select a package. These references describe the repository source; verify your installed package version before copying examples.
|
|
1
|
+
# @impulse-ui-native/pagination
|
|
2
|
+
|
|
3
|
+
Token-aware page navigation for React Native mobile applications.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
pnpm add @impulse-ui-native/pagination
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Render the component inside `ThemeProvider` from `@impulse-ui-native/theme`.
|
|
12
|
+
The package expects compatible `react`, `react-native`, and `react-native-svg`
|
|
13
|
+
peer dependencies in the host application.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { Pagination } from "@impulse-ui-native/pagination";
|
|
19
|
+
|
|
20
|
+
export function ResultsPagination() {
|
|
21
|
+
return <Pagination defaultPage={1} pageCount={12} />;
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Use `page` and `onPageChange` for controlled state, or `defaultPage` for
|
|
26
|
+
uncontrolled state. Page values are normalized to the available range.
|
|
27
|
+
|
|
28
|
+
Set `compact` for the mobile-friendly previous/status/next layout:
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
<Pagination compact defaultPage={3} pageCount={12} />
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The control supports `small`, `medium`, and `large` sizes. Its visible page
|
|
35
|
+
window adapts to the measured width: it shows up to seven page items, condenses
|
|
36
|
+
to five items around the current page, and falls back to the compact status
|
|
37
|
+
layout when space is tighter. Set `compact` to force that layout. Override
|
|
38
|
+
`getCompactLabel` to localize the visible compact status text.
|
|
39
|
+
|
|
40
|
+
Pagination items use the shared primitives `Pressable`; pressed feedback comes
|
|
41
|
+
from that primitive and is not modeled as Pagination state or theme tokens.
|
|
42
|
+
|
|
43
|
+
## Repository palette consistency
|
|
44
|
+
|
|
45
|
+
Pagination accepts `tone="neutral" | "primary" | "secondary"` (default primary).
|
|
46
|
+
The current page uses the shared filled Button palette. Disabled controls use the
|
|
47
|
+
shared unavailable filled palette; unselected pages and compact counts remain
|
|
48
|
+
neutral. Custom theme states move to pagination.colors[tone].
|
|
49
|
+
|
|
50
|
+
## Agent and design reference
|
|
51
|
+
|
|
52
|
+
Start with the [capability guide](../../docs/design-system/capabilities/pagination.md) for supported exports, props, defaults, composition rules, setup, and recipes. Use the [component chooser](../../docs/design-system/component-chooser.md) to select a package. These references describe the repository source; verify your installed package version before copying examples.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/pagination-button.tsx"],"sourcesContent":["import type { GestureResponderEvent } from \"react-native\";\nimport { memo } from \"react\";\nimport { StyleSheet } from \"react-native\";\n\nimport type { IconProps } from \"@impulse-ui-native/icon/types\";\nimport type {\n AppTheme,\n ComponentSize,\n ComponentTone,\n} from \"@impulse-ui-native/theme\";\nimport { useEventCallback } from \"@impulse-ui-native/core\";\nimport { Icon } from \"@impulse-ui-native/icon\";\nimport { Pressable, Typography } from \"@impulse-ui-native/primitives\";\nimport {\n getPaginationStateTokens,\n useComponentsTokens,\n useThemedStyles,\n} from \"@impulse-ui-native/theme\";\n\nimport type { PaginationButtonThemeProps } from \"../types\";\n\ninterface PaginationButtonProps {\n current?: boolean;\n disabled?: boolean;\n Icon?: IconProps[\"icon\"];\n label?: number;\n onSelect: (page: number) => void;\n size: ComponentSize;\n tone: ComponentTone;\n targetPage: number;\n}\n\nexport const PaginationButton = memo(function PaginationButton({\n current = false,\n disabled = false,\n Icon: IconComponent,\n label,\n onSelect,\n size,\n tone,\n targetPage,\n}: PaginationButtonProps) {\n const tokens = useComponentsTokens().pagination;\n\n const styles = useThemedStyles(\n themedStyles,\n { current, disabled, size, tone },\n [current, disabled, size, tone],\n );\n\n const handlePress = useEventCallback((_event: GestureResponderEvent) => {\n onSelect(targetPage);\n });\n\n return (\n <Pressable\n disabled={disabled}\n hitSlop={tokens.sizes[size].hitSlop}\n onPress={handlePress}\n style={styles.root}\n >\n {IconComponent ? (\n <Icon\n color={styles.content.color}\n icon={IconComponent}\n size={tokens.sizes[size].iconSize}\n variant=\"bold\"\n />\n ) : (\n <Typography.Label numeric style={styles.content}>\n {label}\n </Typography.Label>\n )}\n </Pressable>\n );\n});\n\nfunction themedStyles(theme: AppTheme, props: PaginationButtonThemeProps) {\n const tokens = theme.components.pagination;\n const sizeTokens = tokens.sizes[props.size];\n const stateTokens = getPaginationStateTokens(tokens.colors[props.tone], {\n current: props.current,\n disabled: props.disabled,\n });\n\n return StyleSheet.create({\n root: {\n alignItems: \"center\",\n justifyContent: \"center\",\n\n width: sizeTokens.controlSize,\n height: sizeTokens.controlSize,\n\n backgroundColor: stateTokens.backgroundColor,\n borderColor: stateTokens.borderColor,\n borderRadius: tokens.borderRadius,\n borderWidth: tokens.borderWidth,\n },\n content: {\n color: stateTokens.color,\n fontSize: sizeTokens.fontSize,\n textAlign: \"center\",\n },\n });\n}\n"],"mappings":"AA8DQ;AA7DR,SAAS,YAAY;AACrB,SAAS,kBAAkB;AAQ3B,SAAS,wBAAwB;AACjC,SAAS,YAAY;AACrB,SAAS,WAAW,kBAAkB;AACtC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAeA,MAAM,mBAAmB,KAAK,SAASA,kBAAiB;AAAA,EAC7D,UAAU;AAAA,EACV,WAAW;AAAA,EACX,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,SAAS,oBAAoB,EAAE;AAErC,QAAM,SAAS;AAAA,IACb;AAAA,IACA,EAAE,SAAS,UAAU,MAAM,KAAK;AAAA,IAChC,CAAC,SAAS,UAAU,MAAM,IAAI;AAAA,EAChC;AAEA,QAAM,cAAc,iBAAiB,CAAC,WAAkC;AACtE,aAAS,UAAU;AAAA,EACrB,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,SAAS,OAAO,MAAM,IAAI,EAAE;AAAA,MAC5B,SAAS;AAAA,MACT,OAAO,OAAO;AAAA,MAEb,0BACC;AAAA,QAAC;AAAA;AAAA,UACC,OAAO,OAAO,QAAQ;AAAA,UACtB,MAAM;AAAA,UACN,MAAM,OAAO,MAAM,IAAI,EAAE;AAAA,UACzB,SAAQ;AAAA;AAAA,MACV,IAEA,oBAAC,WAAW,OAAX,EAAiB,SAAO,MAAC,OAAO,OAAO,SACrC,iBACH;AAAA;AAAA,EAEJ;AAEJ,CAAC;AAED,SAAS,aAAa,OAAiB,OAAmC;AACxE,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,aAAa,OAAO,MAAM,MAAM,IAAI;AAC1C,QAAM,cAAc,yBAAyB,OAAO,OAAO,MAAM,IAAI,GAAG;AAAA,IACtE,SAAS,MAAM;AAAA,IACf,UAAU,MAAM;AAAA,EAClB,CAAC;AAED,SAAO,WAAW,OAAO;AAAA,IACvB,MAAM;AAAA,MACJ,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAEhB,OAAO,WAAW;AAAA,MAClB,QAAQ,WAAW;AAAA,MAEnB,iBAAiB,YAAY;AAAA,MAC7B,aAAa,YAAY;AAAA,MACzB,cAAc,OAAO;AAAA,MACrB,aAAa,OAAO;AAAA,IACtB;AAAA,IACA,SAAS;AAAA,MACP,OAAO,YAAY;AAAA,MACnB,UAAU,WAAW;AAAA,MACrB,WAAW;AAAA,IACb;AAAA,EACF,CAAC;AACH;","names":["PaginationButton"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/pagination-button.tsx"],"sourcesContent":["import type { GestureResponderEvent } from \"react-native\";\r\nimport { memo } from \"react\";\r\nimport { StyleSheet } from \"react-native\";\r\n\r\nimport type { IconProps } from \"@impulse-ui-native/icon/types\";\r\nimport type {\r\n AppTheme,\r\n ComponentSize,\r\n ComponentTone,\r\n} from \"@impulse-ui-native/theme\";\r\nimport { useEventCallback } from \"@impulse-ui-native/core\";\r\nimport { Icon } from \"@impulse-ui-native/icon\";\r\nimport { Pressable, Typography } from \"@impulse-ui-native/primitives\";\r\nimport {\r\n getPaginationStateTokens,\r\n useComponentsTokens,\r\n useThemedStyles,\r\n} from \"@impulse-ui-native/theme\";\r\n\r\nimport type { PaginationButtonThemeProps } from \"../types\";\r\n\r\ninterface PaginationButtonProps {\r\n current?: boolean;\r\n disabled?: boolean;\r\n Icon?: IconProps[\"icon\"];\r\n label?: number;\r\n onSelect: (page: number) => void;\r\n size: ComponentSize;\r\n tone: ComponentTone;\r\n targetPage: number;\r\n}\r\n\r\nexport const PaginationButton = memo(function PaginationButton({\r\n current = false,\r\n disabled = false,\r\n Icon: IconComponent,\r\n label,\r\n onSelect,\r\n size,\r\n tone,\r\n targetPage,\r\n}: PaginationButtonProps) {\r\n const tokens = useComponentsTokens().pagination;\r\n\r\n const styles = useThemedStyles(\r\n themedStyles,\r\n { current, disabled, size, tone },\r\n [current, disabled, size, tone],\r\n );\r\n\r\n const handlePress = useEventCallback((_event: GestureResponderEvent) => {\r\n onSelect(targetPage);\r\n });\r\n\r\n return (\r\n <Pressable\r\n disabled={disabled}\r\n hitSlop={tokens.sizes[size].hitSlop}\r\n onPress={handlePress}\r\n style={styles.root}\r\n >\r\n {IconComponent ? (\r\n <Icon\r\n color={styles.content.color}\r\n icon={IconComponent}\r\n size={tokens.sizes[size].iconSize}\r\n variant=\"bold\"\r\n />\r\n ) : (\r\n <Typography.Label numeric style={styles.content}>\r\n {label}\r\n </Typography.Label>\r\n )}\r\n </Pressable>\r\n );\r\n});\r\n\r\nfunction themedStyles(theme: AppTheme, props: PaginationButtonThemeProps) {\r\n const tokens = theme.components.pagination;\r\n const sizeTokens = tokens.sizes[props.size];\r\n const stateTokens = getPaginationStateTokens(tokens.colors[props.tone], {\r\n current: props.current,\r\n disabled: props.disabled,\r\n });\r\n\r\n return StyleSheet.create({\r\n root: {\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n\r\n width: sizeTokens.controlSize,\r\n height: sizeTokens.controlSize,\r\n\r\n backgroundColor: stateTokens.backgroundColor,\r\n borderColor: stateTokens.borderColor,\r\n borderRadius: tokens.borderRadius,\r\n borderWidth: tokens.borderWidth,\r\n },\r\n content: {\r\n color: stateTokens.color,\r\n fontSize: sizeTokens.fontSize,\r\n textAlign: \"center\",\r\n },\r\n });\r\n}\r\n"],"mappings":"AA8DQ;AA7DR,SAAS,YAAY;AACrB,SAAS,kBAAkB;AAQ3B,SAAS,wBAAwB;AACjC,SAAS,YAAY;AACrB,SAAS,WAAW,kBAAkB;AACtC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAeA,MAAM,mBAAmB,KAAK,SAASA,kBAAiB;AAAA,EAC7D,UAAU;AAAA,EACV,WAAW;AAAA,EACX,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,SAAS,oBAAoB,EAAE;AAErC,QAAM,SAAS;AAAA,IACb;AAAA,IACA,EAAE,SAAS,UAAU,MAAM,KAAK;AAAA,IAChC,CAAC,SAAS,UAAU,MAAM,IAAI;AAAA,EAChC;AAEA,QAAM,cAAc,iBAAiB,CAAC,WAAkC;AACtE,aAAS,UAAU;AAAA,EACrB,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,SAAS,OAAO,MAAM,IAAI,EAAE;AAAA,MAC5B,SAAS;AAAA,MACT,OAAO,OAAO;AAAA,MAEb,0BACC;AAAA,QAAC;AAAA;AAAA,UACC,OAAO,OAAO,QAAQ;AAAA,UACtB,MAAM;AAAA,UACN,MAAM,OAAO,MAAM,IAAI,EAAE;AAAA,UACzB,SAAQ;AAAA;AAAA,MACV,IAEA,oBAAC,WAAW,OAAX,EAAiB,SAAO,MAAC,OAAO,OAAO,SACrC,iBACH;AAAA;AAAA,EAEJ;AAEJ,CAAC;AAED,SAAS,aAAa,OAAiB,OAAmC;AACxE,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,aAAa,OAAO,MAAM,MAAM,IAAI;AAC1C,QAAM,cAAc,yBAAyB,OAAO,OAAO,MAAM,IAAI,GAAG;AAAA,IACtE,SAAS,MAAM;AAAA,IACf,UAAU,MAAM;AAAA,EAClB,CAAC;AAED,SAAO,WAAW,OAAO;AAAA,IACvB,MAAM;AAAA,MACJ,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAEhB,OAAO,WAAW;AAAA,MAClB,QAAQ,WAAW;AAAA,MAEnB,iBAAiB,YAAY;AAAA,MAC7B,aAAa,YAAY;AAAA,MACzB,cAAc,OAAO;AAAA,MACrB,aAAa,OAAO;AAAA,IACtB;AAAA,IACA,SAAS;AAAA,MACP,OAAO,YAAY;AAAA,MACnB,UAAU,WAAW;AAAA,MACrB,WAAW;AAAA,IACb;AAAA,EACF,CAAC;AACH;","names":["PaginationButton"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/pagination.tsx"],"sourcesContent":["import type { LayoutChangeEvent } from \"react-native\";\nimport { memo, useMemo, useState } from \"react\";\nimport { StyleSheet } from \"react-native\";\n\nimport type { AppTheme } from \"@impulse-ui-native/theme\";\nimport {\n useControllableState,\n useEventCallback,\n} from \"@impulse-ui-native/core\";\nimport { CaretLeftIcon } from \"@impulse-ui-native/icon/icons/caret-left\";\nimport { CaretRightIcon } from \"@impulse-ui-native/icon/icons/caret-right\";\nimport { Typography, View } from \"@impulse-ui-native/primitives\";\nimport {\n getPaginationStateTokens,\n useComponentsTokens,\n useThemedStyles,\n} from \"@impulse-ui-native/theme\";\n\nimport type { PaginationProps, PaginationThemeProps } from \"../types\";\nimport {\n clampPage,\n getDefaultCompactLabel,\n getPaginationItems,\n getPaginationWindowLayout,\n normalizePageCount,\n} from \"../utils\";\nimport { PaginationButton } from \"./pagination-button\";\n\nexport const Pagination = memo(function Pagination({\n compact = false,\n defaultPage = 1,\n disabled = false,\n getCompactLabel = getDefaultCompactLabel,\n onLayout,\n onPageChange,\n page: pageProp,\n pageCount,\n size = \"medium\",\n tone = \"primary\",\n style,\n ...props\n}: PaginationProps) {\n const tokens = useComponentsTokens().pagination;\n\n const [availableWidth, setAvailableWidth] = useState<number>();\n\n const normalizedPageCount = normalizePageCount(pageCount);\n\n const [page, setPage] = useControllableState<number>({\n prop: pageProp,\n defaultProp: clampPage(defaultPage, normalizedPageCount),\n onChange: onPageChange,\n });\n\n const resolvedPage = clampPage(page, normalizedPageCount);\n\n const styles = useThemedStyles(themedStyles, { disabled, size, tone }, [\n disabled,\n size,\n tone,\n ]);\n\n const windowLayout = useMemo(\n () =>\n getPaginationWindowLayout(\n availableWidth,\n normalizedPageCount,\n tokens.sizes[size].controlSize,\n tokens.sizes[size].compactMinWidth,\n tokens.gap,\n ),\n [availableWidth, normalizedPageCount, size, tokens.gap, tokens.sizes],\n );\n const items = useMemo(\n () =>\n getPaginationItems(\n resolvedPage,\n normalizedPageCount,\n windowLayout === \"condensed\" ? 5 : 7,\n ),\n [normalizedPageCount, resolvedPage, windowLayout],\n );\n const rootStyle = useMemo(() => [styles.root, style], [style, styles.root]);\n\n const selectPage = useEventCallback((nextPage: number) => {\n if (!disabled) {\n setPage(clampPage(nextPage, normalizedPageCount));\n }\n });\n\n const handleLayout = useEventCallback((event: LayoutChangeEvent) => {\n setAvailableWidth(event.nativeEvent.layout.width);\n onLayout?.(event);\n });\n\n const previousDisabled = disabled || resolvedPage === 1;\n const nextDisabled = disabled || resolvedPage === normalizedPageCount;\n const showCompact = compact || windowLayout === \"compact\";\n\n return (\n <View {...props} onLayout={handleLayout} style={rootStyle}>\n <PaginationButton\n disabled={previousDisabled}\n Icon={CaretLeftIcon}\n onSelect={selectPage}\n size={size}\n tone={tone}\n targetPage={resolvedPage - 1}\n />\n\n {showCompact ? (\n <View style={styles.compactStatus}>\n <Typography.Label numeric style={styles.compactLabel}>\n {getCompactLabel(resolvedPage, normalizedPageCount)}\n </Typography.Label>\n </View>\n ) : (\n items.map((item) =>\n typeof item === \"number\" ? (\n <PaginationButton\n key={item}\n current={item === resolvedPage}\n disabled={disabled}\n label={item}\n onSelect={selectPage}\n size={size}\n tone={tone}\n targetPage={item}\n />\n ) : (\n <View key={item} style={styles.ellipsis}>\n <Typography.Label style={styles.ellipsisLabel}>\n {\"\\u2026\"}\n </Typography.Label>\n </View>\n ),\n )\n )}\n\n <PaginationButton\n disabled={nextDisabled}\n Icon={CaretRightIcon}\n onSelect={selectPage}\n size={size}\n tone={tone}\n targetPage={resolvedPage + 1}\n />\n </View>\n );\n});\n\nfunction themedStyles(theme: AppTheme, props: PaginationThemeProps) {\n const tokens = theme.components.pagination;\n const sizeTokens = tokens.sizes[props.size];\n const statusTokens = getPaginationStateTokens(tokens.colors[props.tone], {\n current: false,\n disabled: props.disabled,\n });\n\n return StyleSheet.create({\n root: {\n alignItems: \"center\",\n flexDirection: \"row\",\n flexWrap: \"nowrap\",\n gap: tokens.gap,\n },\n compactStatus: {\n alignItems: \"center\",\n justifyContent: \"center\",\n\n minWidth: sizeTokens.compactMinWidth,\n height: sizeTokens.controlSize,\n paddingHorizontal: sizeTokens.paddingHorizontal,\n\n backgroundColor: statusTokens.backgroundColor,\n borderColor: statusTokens.borderColor,\n borderRadius: tokens.borderRadius,\n borderWidth: tokens.borderWidth,\n },\n compactLabel: {\n color: statusTokens.color,\n fontSize: sizeTokens.fontSize,\n textAlign: \"center\",\n },\n ellipsis: {\n alignItems: \"center\",\n justifyContent: \"center\",\n width: sizeTokens.controlSize,\n height: sizeTokens.controlSize,\n },\n ellipsisLabel: {\n color: statusTokens.ellipsisColor,\n fontSize: sizeTokens.fontSize,\n textAlign: \"center\",\n },\n });\n}\n"],"mappings":"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","names":["Pagination"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/pagination.tsx"],"sourcesContent":["import type { LayoutChangeEvent } from \"react-native\";\r\nimport { memo, useMemo, useState } from \"react\";\r\nimport { StyleSheet } from \"react-native\";\r\n\r\nimport type { AppTheme } from \"@impulse-ui-native/theme\";\r\nimport {\r\n useControllableState,\r\n useEventCallback,\r\n} from \"@impulse-ui-native/core\";\r\nimport { CaretLeftIcon } from \"@impulse-ui-native/icon/icons/caret-left\";\r\nimport { CaretRightIcon } from \"@impulse-ui-native/icon/icons/caret-right\";\r\nimport { Typography, View } from \"@impulse-ui-native/primitives\";\r\nimport {\r\n getPaginationStateTokens,\r\n useComponentsTokens,\r\n useThemedStyles,\r\n} from \"@impulse-ui-native/theme\";\r\n\r\nimport type { PaginationProps, PaginationThemeProps } from \"../types\";\r\nimport {\r\n clampPage,\r\n getDefaultCompactLabel,\r\n getPaginationItems,\r\n getPaginationWindowLayout,\r\n normalizePageCount,\r\n} from \"../utils\";\r\nimport { PaginationButton } from \"./pagination-button\";\r\n\r\nexport const Pagination = memo(function Pagination({\r\n compact = false,\r\n defaultPage = 1,\r\n disabled = false,\r\n getCompactLabel = getDefaultCompactLabel,\r\n onLayout,\r\n onPageChange,\r\n page: pageProp,\r\n pageCount,\r\n size = \"medium\",\r\n tone = \"primary\",\r\n style,\r\n ...props\r\n}: PaginationProps) {\r\n const tokens = useComponentsTokens().pagination;\r\n\r\n const [availableWidth, setAvailableWidth] = useState<number>();\r\n\r\n const normalizedPageCount = normalizePageCount(pageCount);\r\n\r\n const [page, setPage] = useControllableState<number>({\r\n prop: pageProp,\r\n defaultProp: clampPage(defaultPage, normalizedPageCount),\r\n onChange: onPageChange,\r\n });\r\n\r\n const resolvedPage = clampPage(page, normalizedPageCount);\r\n\r\n const styles = useThemedStyles(themedStyles, { disabled, size, tone }, [\r\n disabled,\r\n size,\r\n tone,\r\n ]);\r\n\r\n const windowLayout = useMemo(\r\n () =>\r\n getPaginationWindowLayout(\r\n availableWidth,\r\n normalizedPageCount,\r\n tokens.sizes[size].controlSize,\r\n tokens.sizes[size].compactMinWidth,\r\n tokens.gap,\r\n ),\r\n [availableWidth, normalizedPageCount, size, tokens.gap, tokens.sizes],\r\n );\r\n const items = useMemo(\r\n () =>\r\n getPaginationItems(\r\n resolvedPage,\r\n normalizedPageCount,\r\n windowLayout === \"condensed\" ? 5 : 7,\r\n ),\r\n [normalizedPageCount, resolvedPage, windowLayout],\r\n );\r\n const rootStyle = useMemo(() => [styles.root, style], [style, styles.root]);\r\n\r\n const selectPage = useEventCallback((nextPage: number) => {\r\n if (!disabled) {\r\n setPage(clampPage(nextPage, normalizedPageCount));\r\n }\r\n });\r\n\r\n const handleLayout = useEventCallback((event: LayoutChangeEvent) => {\r\n setAvailableWidth(event.nativeEvent.layout.width);\r\n onLayout?.(event);\r\n });\r\n\r\n const previousDisabled = disabled || resolvedPage === 1;\r\n const nextDisabled = disabled || resolvedPage === normalizedPageCount;\r\n const showCompact = compact || windowLayout === \"compact\";\r\n\r\n return (\r\n <View {...props} onLayout={handleLayout} style={rootStyle}>\r\n <PaginationButton\r\n disabled={previousDisabled}\r\n Icon={CaretLeftIcon}\r\n onSelect={selectPage}\r\n size={size}\r\n tone={tone}\r\n targetPage={resolvedPage - 1}\r\n />\r\n\r\n {showCompact ? (\r\n <View style={styles.compactStatus}>\r\n <Typography.Label numeric style={styles.compactLabel}>\r\n {getCompactLabel(resolvedPage, normalizedPageCount)}\r\n </Typography.Label>\r\n </View>\r\n ) : (\r\n items.map((item) =>\r\n typeof item === \"number\" ? (\r\n <PaginationButton\r\n key={item}\r\n current={item === resolvedPage}\r\n disabled={disabled}\r\n label={item}\r\n onSelect={selectPage}\r\n size={size}\r\n tone={tone}\r\n targetPage={item}\r\n />\r\n ) : (\r\n <View key={item} style={styles.ellipsis}>\r\n <Typography.Label style={styles.ellipsisLabel}>\r\n {\"\\u2026\"}\r\n </Typography.Label>\r\n </View>\r\n ),\r\n )\r\n )}\r\n\r\n <PaginationButton\r\n disabled={nextDisabled}\r\n Icon={CaretRightIcon}\r\n onSelect={selectPage}\r\n size={size}\r\n tone={tone}\r\n targetPage={resolvedPage + 1}\r\n />\r\n </View>\r\n );\r\n});\r\n\r\nfunction themedStyles(theme: AppTheme, props: PaginationThemeProps) {\r\n const tokens = theme.components.pagination;\r\n const sizeTokens = tokens.sizes[props.size];\r\n const statusTokens = getPaginationStateTokens(tokens.colors[props.tone], {\r\n current: false,\r\n disabled: props.disabled,\r\n });\r\n\r\n return StyleSheet.create({\r\n root: {\r\n alignItems: \"center\",\r\n flexDirection: \"row\",\r\n flexWrap: \"nowrap\",\r\n gap: tokens.gap,\r\n },\r\n compactStatus: {\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n\r\n minWidth: sizeTokens.compactMinWidth,\r\n height: sizeTokens.controlSize,\r\n paddingHorizontal: sizeTokens.paddingHorizontal,\r\n\r\n backgroundColor: statusTokens.backgroundColor,\r\n borderColor: statusTokens.borderColor,\r\n borderRadius: tokens.borderRadius,\r\n borderWidth: tokens.borderWidth,\r\n },\r\n compactLabel: {\r\n color: statusTokens.color,\r\n fontSize: sizeTokens.fontSize,\r\n textAlign: \"center\",\r\n },\r\n ellipsis: {\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n width: sizeTokens.controlSize,\r\n height: sizeTokens.controlSize,\r\n },\r\n ellipsisLabel: {\r\n color: statusTokens.ellipsisColor,\r\n fontSize: sizeTokens.fontSize,\r\n textAlign: \"center\",\r\n },\r\n });\r\n}\r\n"],"mappings":"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","names":["Pagination"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@impulse-ui-native/pagination",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "16.0.0",
|
|
4
4
|
"description": "Token-aware pagination controls for ImpulseUI Native applications.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
],
|
|
29
29
|
"sideEffects": false,
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@impulse-ui-native/core": "
|
|
32
|
-
"@impulse-ui-native/icon": "
|
|
33
|
-
"@impulse-ui-native/primitives": "
|
|
34
|
-
"@impulse-ui-native/theme": "
|
|
31
|
+
"@impulse-ui-native/core": "16.0.0",
|
|
32
|
+
"@impulse-ui-native/icon": "16.0.0",
|
|
33
|
+
"@impulse-ui-native/primitives": "16.0.0",
|
|
34
|
+
"@impulse-ui-native/theme": "16.0.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@impulse-ui-native/eslint-config": "1.0.0",
|