@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": "15.0.4",
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": "15.0.4",
32
- "@impulse-ui-native/icon": "15.0.4",
33
- "@impulse-ui-native/primitives": "15.0.4",
34
- "@impulse-ui-native/theme": "15.0.4"
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",