jfs-components 0.1.51 → 0.1.54

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.
Files changed (90) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/lib/commonjs/components/ActionFooter/ActionFooter.js +319 -135
  3. package/lib/commonjs/components/Badge/Badge.js +20 -1
  4. package/lib/commonjs/components/Button/Button.js +139 -47
  5. package/lib/commonjs/components/ButtonGroup/ButtonGroup.js +1 -1
  6. package/lib/commonjs/components/Card/Card.js +151 -112
  7. package/lib/commonjs/components/Card/assets/gold-logo-mark.png +0 -0
  8. package/lib/commonjs/components/CategoryCard/CategoryCard.js +97 -63
  9. package/lib/commonjs/components/CategoryCard/assets/sample.png +0 -0
  10. package/lib/commonjs/components/CheckboxItem/CheckboxItem.js +59 -10
  11. package/lib/commonjs/components/ExpandableCheckbox/ExpandableCheckbox.js +132 -49
  12. package/lib/commonjs/components/HelloJioInput/HelloJioInput.js +56 -14
  13. package/lib/commonjs/components/IconCapsule/IconCapsule.js +1 -1
  14. package/lib/commonjs/components/MetricData/MetricData.js +26 -13
  15. package/lib/commonjs/components/MoneyValue/MoneyValue.js +1 -1
  16. package/lib/commonjs/components/Nudge/Nudge.js +1 -1
  17. package/lib/commonjs/components/PdpCcCard/PdpCcCard.js +47 -91
  18. package/lib/commonjs/components/PlanComparisonCard/PlanComparisonCard.js +52 -45
  19. package/lib/commonjs/components/PortfolioHero/PortfolioHero.js +1 -1
  20. package/lib/commonjs/components/Slider/Slider.js +3 -3
  21. package/lib/commonjs/components/TextInput/TextInput.js +26 -8
  22. package/lib/commonjs/components/Tooltip/Tooltip.js +3 -5
  23. package/lib/commonjs/components/index.js +7 -1
  24. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
  25. package/lib/commonjs/design-tokens/figma-modes.generated.js +13 -13
  26. package/lib/commonjs/icons/registry.js +1 -1
  27. package/lib/module/components/ActionFooter/ActionFooter.js +322 -138
  28. package/lib/module/components/Badge/Badge.js +20 -1
  29. package/lib/module/components/Button/Button.js +140 -48
  30. package/lib/module/components/ButtonGroup/ButtonGroup.js +1 -1
  31. package/lib/module/components/Card/Card.js +152 -114
  32. package/lib/module/components/Card/assets/gold-logo-mark.png +0 -0
  33. package/lib/module/components/CategoryCard/CategoryCard.js +97 -63
  34. package/lib/module/components/CategoryCard/assets/sample.png +0 -0
  35. package/lib/module/components/CheckboxItem/CheckboxItem.js +59 -10
  36. package/lib/module/components/ExpandableCheckbox/ExpandableCheckbox.js +135 -52
  37. package/lib/module/components/HelloJioInput/HelloJioInput.js +56 -14
  38. package/lib/module/components/IconCapsule/IconCapsule.js +1 -1
  39. package/lib/module/components/MetricData/MetricData.js +26 -14
  40. package/lib/module/components/MoneyValue/MoneyValue.js +1 -1
  41. package/lib/module/components/Nudge/Nudge.js +1 -1
  42. package/lib/module/components/PdpCcCard/PdpCcCard.js +48 -92
  43. package/lib/module/components/PlanComparisonCard/PlanComparisonCard.js +52 -45
  44. package/lib/module/components/PortfolioHero/PortfolioHero.js +1 -1
  45. package/lib/module/components/Slider/Slider.js +3 -3
  46. package/lib/module/components/TextInput/TextInput.js +27 -9
  47. package/lib/module/components/Tooltip/Tooltip.js +3 -5
  48. package/lib/module/components/index.js +1 -1
  49. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
  50. package/lib/module/design-tokens/figma-modes.generated.js +13 -13
  51. package/lib/module/icons/registry.js +1 -1
  52. package/lib/typescript/src/components/ActionFooter/ActionFooter.d.ts +50 -21
  53. package/lib/typescript/src/components/Button/Button.d.ts +24 -1
  54. package/lib/typescript/src/components/ButtonGroup/ButtonGroup.d.ts +2 -2
  55. package/lib/typescript/src/components/Card/Card.d.ts +54 -25
  56. package/lib/typescript/src/components/CategoryCard/CategoryCard.d.ts +29 -12
  57. package/lib/typescript/src/components/CheckboxItem/CheckboxItem.d.ts +27 -9
  58. package/lib/typescript/src/components/ExpandableCheckbox/ExpandableCheckbox.d.ts +37 -12
  59. package/lib/typescript/src/components/IconCapsule/IconCapsule.d.ts +1 -1
  60. package/lib/typescript/src/components/MetricData/MetricData.d.ts +7 -5
  61. package/lib/typescript/src/components/PdpCcCard/PdpCcCard.d.ts +16 -6
  62. package/lib/typescript/src/components/PlanComparisonCard/PlanComparisonCard.d.ts +9 -2
  63. package/lib/typescript/src/components/index.d.ts +2 -2
  64. package/lib/typescript/src/icons/registry.d.ts +1 -1
  65. package/package.json +1 -1
  66. package/src/components/ActionFooter/ActionFooter.tsx +375 -141
  67. package/src/components/Badge/Badge.tsx +21 -1
  68. package/src/components/Button/Button.tsx +192 -44
  69. package/src/components/ButtonGroup/ButtonGroup.tsx +2 -2
  70. package/src/components/Card/Card.tsx +370 -212
  71. package/src/components/Card/assets/gold-logo-mark.png +0 -0
  72. package/src/components/CategoryCard/CategoryCard.tsx +130 -84
  73. package/src/components/CategoryCard/assets/sample.png +0 -0
  74. package/src/components/CheckboxItem/CheckboxItem.tsx +72 -12
  75. package/src/components/ExpandableCheckbox/ExpandableCheckbox.tsx +186 -67
  76. package/src/components/HelloJioInput/HelloJioInput.tsx +58 -17
  77. package/src/components/IconCapsule/IconCapsule.tsx +1 -1
  78. package/src/components/MetricData/MetricData.tsx +39 -22
  79. package/src/components/MoneyValue/MoneyValue.tsx +1 -1
  80. package/src/components/Nudge/Nudge.tsx +1 -1
  81. package/src/components/PdpCcCard/PdpCcCard.tsx +41 -92
  82. package/src/components/PlanComparisonCard/PlanComparisonCard.tsx +73 -58
  83. package/src/components/PortfolioHero/PortfolioHero.tsx +1 -1
  84. package/src/components/Slider/Slider.tsx +3 -3
  85. package/src/components/TextInput/TextInput.tsx +26 -9
  86. package/src/components/Tooltip/Tooltip.tsx +3 -5
  87. package/src/components/index.ts +9 -2
  88. package/src/design-tokens/Coin Variables-variables-full.json +1 -1
  89. package/src/design-tokens/figma-modes.generated.ts +13 -13
  90. package/src/icons/registry.ts +1 -1
@@ -4,11 +4,23 @@ import type { Modes } from '../../design-tokens';
4
4
  export type ActionFooterProps = {
5
5
  /**
6
6
  * Content to render inside the action footer slot.
7
- * Typically includes `IconButton` and `Button` components.
8
- * `IconButton` children keep their intrinsic square size; everything else
9
- * is auto-stretched to share the remaining horizontal space equally.
7
+ *
8
+ * **Legacy (fully supported):** pass loose `IconButton` / `Button` children —
9
+ * IconButtons keep their intrinsic square size; everything else is
10
+ * auto-stretched to share the remaining horizontal space equally.
11
+ *
12
+ * **Figma shape (preferred for new code):** pass a single `ButtonGroup`
13
+ * (or `Stack` / `Slot`) that owns its own internal layout. ActionFooter will
14
+ * not re-stretch that composite — it only cascades `modes` and stretches it
15
+ * to full width.
10
16
  */
11
17
  children?: React.ReactNode;
18
+ /**
19
+ * Optional centered title rendered above the action slot (Figma "title wrap").
20
+ * Omitted / empty string → title wrap is not mounted (identical to the
21
+ * pre-title layout tree for loose children).
22
+ */
23
+ title?: string;
12
24
  /**
13
25
  * Mode configuration passed to the token resolver.
14
26
  * Automatically merged into every slot child via {@link cloneChildrenWithModes}
@@ -16,43 +28,60 @@ export type ActionFooterProps = {
16
28
  */
17
29
  modes?: Modes;
18
30
  /**
19
- * Optional style overrides for the outer container.
31
+ * Optional style overrides for the footer chrome (not the sticky shell).
20
32
  */
21
33
  style?: StyleProp<ViewStyle>;
22
34
  /**
23
35
  * Accessibility label for the footer region (announced for the toolbar).
24
36
  */
25
37
  accessibilityLabel?: string;
38
+ /**
39
+ * When `true` (default on native), the footer rides above the software
40
+ * keyboard by exactly the uncovered keyboard height. Web ignores this —
41
+ * there is no software keyboard inset to track.
42
+ */
43
+ avoidKeyboard?: boolean;
26
44
  };
27
45
  /**
28
- * ActionFooter — a sticky bottom container for primary screen actions.
46
+ * ActionFooter — sticky bottom container for primary screen actions.
29
47
  *
30
- * Layout contract:
31
- * - The outer container stretches horizontally (`alignSelf: 'stretch'`) so
32
- * it fills the parent regardless of whether the parent is a flex column,
33
- * a ScrollView contentContainer, or a plain View.
34
- * - The inner slot is a single row sized by its tallest child. It does NOT
35
- * use `flex: 1` that previously caused the row to collapse to zero on
36
- * the first Yoga pass on native, taking the button labels with it.
37
- * - `IconButton` children keep their intrinsic square size.
38
- * - Every other child is auto-stretched with the Yoga-safe stretch style
39
- * above so two `<Button>` siblings render at equal width on iOS, Android,
40
- * and Web.
48
+ * Layout contract (native):
49
+ * - Self-pins to the bottom of its flex-column screen via `marginTop: 'auto'`
50
+ * plus an absolutely positioned chrome inside a height-locked shell.
51
+ * - The shell keeps scroll/flex siblings from painting under the footer —
52
+ * callers do not need to hand-maintain `paddingBottom`.
53
+ * - Keyboard avoidance is owned here: the footer moves up by exactly the
54
+ * keyboard height that layout has not already absorbed. Host
55
+ * `KeyboardAvoidingView` is unnecessary and should not wrap this.
41
56
  *
42
- * The `modes` prop is automatically pushed down to every slot child via
43
- * {@link cloneChildrenWithModes}; explicit child-level modes win over the
44
- * parent's modes.
57
+ * Layout contract (web):
58
+ * - In-flow stretch container (Storybook / docs friendly). No keyboard inset.
59
+ *
60
+ * Content contract:
61
+ * - Optional centered `title` (Figma title wrap; Drawer title tokens).
62
+ * - Loose `IconButton`/`Button` children keep the original equal-stretch row.
63
+ * - A sole `ButtonGroup` / `Stack` / `Slot` child is treated as the Figma
64
+ * composite and is not re-stretched internally.
45
65
  *
46
66
  * @example
47
67
  * ```tsx
48
- * <ActionFooter modes={modes}>
68
+ * // Legacy — still the recommended simple path
69
+ * <ActionFooter>
49
70
  * <IconButton iconName="ic_split" />
50
71
  * <Button label="Request" modes={{ AppearanceBrand: 'Secondary' }} />
51
72
  * <Button label="Pay" modes={{ AppearanceBrand: 'Primary' }} />
52
73
  * </ActionFooter>
74
+ *
75
+ * // Figma shape + title
76
+ * <ActionFooter title="Confirm payment">
77
+ * <ButtonGroup>
78
+ * <Button label="Request" modes={{ AppearanceBrand: 'Secondary' }} />
79
+ * <Button label="Pay" modes={{ AppearanceBrand: 'Primary' }} />
80
+ * </ButtonGroup>
81
+ * </ActionFooter>
53
82
  * ```
54
83
  */
55
- declare function ActionFooter({ children, modes, style, accessibilityLabel, }: ActionFooterProps): import("react/jsx-runtime").JSX.Element;
84
+ declare function ActionFooter({ avoidKeyboard, ...props }: ActionFooterProps): import("react/jsx-runtime").JSX.Element;
56
85
  declare const _default: React.MemoExoticComponent<typeof ActionFooter>;
57
86
  export default _default;
58
87
  //# sourceMappingURL=ActionFooter.d.ts.map
@@ -2,6 +2,13 @@ import React from 'react';
2
2
  import { type AccessibilityState, type StyleProp, type ViewStyle, type TextStyle } from 'react-native';
3
3
  import { type SafePressableProps, type WebAccessibilityProps } from '../../utils/web-platform-utils';
4
4
  import type { Modes } from '../../design-tokens';
5
+ /**
6
+ * Figma `Type` property on Button.
7
+ * - `'default'` — solid token-colored pill (hugs content)
8
+ * - `'glass'` — frosted translucent pill backed by {@link GlassFill}
9
+ * - `'fixed'` — solid pill constrained by `button/maxWidth`
10
+ */
11
+ export type ButtonType = 'default' | 'glass' | 'fixed';
5
12
  export type ButtonProps = SafePressableProps & {
6
13
  label?: string;
7
14
  children?: React.ReactNode;
@@ -29,6 +36,22 @@ export type ButtonProps = SafePressableProps & {
29
36
  * Takes precedence over `trailing` if both are provided.
30
37
  */
31
38
  icon?: string;
39
+ /**
40
+ * Visual/layout type matching the Figma `Type` property. Defaults to
41
+ * `'default'`. `'glass'` also activates when `modes['Button type'] === 'glass'`.
42
+ */
43
+ type?: ButtonType;
44
+ /**
45
+ * Glass-only override for the translucent overlay color painted over the live
46
+ * blur. Defaults to the resolved `button/background` token under
47
+ * `Button type=glass`. Ignored for non-glass types.
48
+ */
49
+ glassOverlayColor?: string;
50
+ /**
51
+ * Glass-only override for blur intensity on the 0–100 scale. Defaults to the
52
+ * `blur/minimal` token. Ignored for non-glass types.
53
+ */
54
+ glassIntensity?: number;
32
55
  modes?: Modes;
33
56
  onPress?: () => void;
34
57
  disabled?: boolean;
@@ -90,7 +113,7 @@ export type ButtonProps = SafePressableProps & {
90
113
  * advantage of this should pass stable `modes` (the default `EMPTY_MODES`
91
114
  * is already stable) and stable callback props.
92
115
  */
93
- declare function ButtonImpl({ label, children, renderContent, leading, trailing, icon, modes, onPress, disabled, style, labelStyle, accessibilityLabel, accessibilityHint, accessibilityState, webAccessibilityProps, loading, disableTruncation, ...rest }: ButtonProps): import("react/jsx-runtime").JSX.Element;
116
+ declare function ButtonImpl({ label, children, renderContent, leading, trailing, icon, type, glassOverlayColor, glassIntensity, modes, onPress, disabled, style, labelStyle, accessibilityLabel, accessibilityHint, accessibilityState, webAccessibilityProps, loading, disableTruncation, ...rest }: ButtonProps): import("react/jsx-runtime").JSX.Element;
94
117
  declare const Button: React.MemoExoticComponent<typeof ButtonImpl>;
95
118
  export default Button;
96
119
  //# sourceMappingURL=Button.d.ts.map
@@ -8,7 +8,7 @@ export type ButtonGroupProps = {
8
8
  */
9
9
  children?: React.ReactNode;
10
10
  /**
11
- * Mode configuration for design tokens (e.g., {"Button / Size": "M", "Appearance": "high"})
11
+ * Mode configuration for design tokens (e.g., {"Button / Size": "M", "Emphasis": "High"})
12
12
  * These modes are passed down to all child components.
13
13
  */
14
14
  modes?: Modes;
@@ -28,7 +28,7 @@ export type ButtonGroupProps = {
28
28
  * @component
29
29
  * @example
30
30
  * ```jsx
31
- * <ButtonGroup modes={{"Appearance": "light"}}>
31
+ * <ButtonGroup modes={{"Color Mode": "Light"}}>
32
32
  * <IconButton iconName="ic_qr_code" />
33
33
  * <Button label="Pay" />
34
34
  * </ButtonGroup>
@@ -1,68 +1,97 @@
1
1
  import React from 'react';
2
2
  import { type ViewStyle, type TextStyle, type StyleProp } from 'react-native';
3
3
  import type { Modes } from '../../design-tokens';
4
+ /** Canonical variant values. Maps 1:1 to Figma `Property 1`. */
5
+ export type CardVariant = 'default' | 'slim';
6
+ /**
7
+ * Accepts both the canonical lowercase API and Figma's PascalCase property
8
+ * values so Code Connect / design tooling can pass either.
9
+ */
10
+ export type CardVariantInput = CardVariant | 'Default' | 'Slim';
11
+ /**
12
+ * Figma `Ratio` default for the media slot (node 766:6258) — 154×116.
13
+ * Kept as a named constant so stories / docs stay aligned with the design.
14
+ */
15
+ export declare const CARD_MEDIA_ASPECT_RATIO: number;
4
16
  export interface CardProps {
5
17
  /**
6
- * Content rendered in the header slot at the top of the card (e.g. a brand logo).
7
- * Sits above the media slot, with its own padding.
18
+ * Visual layout variant matching Figma `Property 1`.
19
+ * - `'default'` header + optional media + content (Figma Default)
20
+ * - `'slim'` — header + content only; `media` is ignored (Figma Slim)
21
+ *
22
+ * Defaults to `'default'`. Existing call sites that omit `media` continue
23
+ * to render a media-less default card (backward compatible). Prefer
24
+ * `variant="slim"` when you want the Slim contract explicitly.
8
25
  */
9
- header?: React.ReactNode;
26
+ variant?: CardVariantInput;
10
27
  /**
11
- * The content to be rendered in the media slot (e.g. an Image).
12
- * This content is wrapped in a container that respects the `aspectRatio`.
28
+ * Content rendered in the header slot at the top of the card (e.g. a brand
29
+ * logo). Sits above the media slot, padded with `card/content/padding/*`.
13
30
  */
14
- media?: React.ReactNode;
31
+ header?: React.ReactNode;
15
32
  /**
16
- * Content to render inside the card (e.g. Card.Title, Card.SupportText).
33
+ * Media slot content (e.g. `<Image />`). Wrapped in a container that
34
+ * respects `mediaAspectRatio`. Ignored when `variant="slim"`.
17
35
  */
36
+ media?: React.ReactNode;
37
+ /** Content slot (e.g. `Card.Title`, `Card.SupportText`). */
18
38
  children?: React.ReactNode;
19
- /**
20
- * Modes object for token resolution (e.g. { "Mode": "Dark" }).
21
- */
39
+ /** Modes object for token resolution. Cascades into all slots. */
22
40
  modes?: Modes;
23
41
  /**
24
42
  * Aspect ratio for the media slot container.
25
- * Default is based on Figma design 154/116 (~1.328).
43
+ * Defaults to the Figma Ratio 154/116 (~1.328).
26
44
  */
27
45
  mediaAspectRatio?: number;
28
- /**
29
- * Style overrides for the card container.
30
- */
46
+ /** Style overrides for the card container. */
31
47
  style?: StyleProp<ViewStyle>;
32
48
  /**
33
49
  * Press handler for the whole card. When set, the card becomes pressable
34
- * (rendered through a `Pressable` with `accessibilityRole="button"`).
50
+ * (`Pressable` + `accessibilityRole="button"`).
35
51
  */
36
52
  onPress?: () => void;
37
53
  /** Disable interaction when `onPress` is set. */
38
54
  disabled?: boolean;
39
- /** Accessibility label forwarded to the pressable wrapper. */
55
+ /** Accessibility label forwarded to the root. */
40
56
  accessibilityLabel?: string;
41
57
  }
42
58
  /**
43
- * Card component implementation from Figma node 765:6186.
59
+ * `Card` Figma node 5739:794 (`Property 1=Default` / `Property 1=Slim`).
44
60
  *
45
- * Supports a `media` slot (with aspect ratio) and a content area.
46
- * Supports an optional `header` slot (e.g. a brand logo), a `media` slot
47
- * (with aspect ratio) and a content area.
48
- * Usage:
61
+ * Slots: optional `header`, optional `media` (Default only), and `children`
62
+ * for the content stack. Typography subcomponents (`Card.Title`,
63
+ * `Card.SupportText`) read tokens via context.
64
+ *
65
+ * @example
49
66
  * ```tsx
50
- * <Card header={<GoldLogo />} media={<Image source={...} />} modes={modes}>
67
+ * <Card
68
+ * variant="default"
69
+ * header={<GoldLogo />}
70
+ * media={<Image imageSource={uri} ratio={154 / 116} />}
71
+ * modes={{ AppearanceBrand: 'Neutral' }}
72
+ * >
51
73
  * <Card.SupportText>Support text</Card.SupportText>
52
74
  * <Card.Title>Title</Card.Title>
53
75
  * <Card.SupportText>Support text</Card.SupportText>
54
76
  * </Card>
55
77
  * ```
78
+ *
79
+ * @component
56
80
  */
57
- export declare function Card({ header, media, children, modes, mediaAspectRatio, style, onPress, disabled, accessibilityLabel, }: CardProps): import("react/jsx-runtime").JSX.Element;
81
+ export declare function Card({ variant: variantProp, header, media, children, modes: propModes, mediaAspectRatio, style, onPress, disabled, accessibilityLabel, }: CardProps): import("react/jsx-runtime").JSX.Element;
58
82
  export declare namespace Card {
59
- var Title: ({ children, style, modes: propModes }: CardTextProps) => import("react/jsx-runtime").JSX.Element;
60
- var SupportText: ({ children, style, modes: propModes }: CardTextProps) => import("react/jsx-runtime").JSX.Element;
83
+ var Title: ({ children, style, modes: propModes, numberOfLines, }: CardTextProps) => import("react/jsx-runtime").JSX.Element;
84
+ var SupportText: ({ children, style, modes: propModes, numberOfLines, }: CardTextProps) => import("react/jsx-runtime").JSX.Element;
61
85
  }
62
86
  export interface CardTextProps {
63
87
  children?: React.ReactNode;
64
88
  style?: StyleProp<TextStyle>;
65
89
  modes?: Modes;
90
+ /**
91
+ * Line clamp before ellipsis. `Card.Title` defaults to `3` (Figma).
92
+ * Pass a different number to override, or `0` for no clamp.
93
+ */
94
+ numberOfLines?: number;
66
95
  }
67
96
  export default Card;
68
97
  //# sourceMappingURL=Card.d.ts.map
@@ -6,21 +6,32 @@ export type CategoryCardProps = SafePressableProps & {
6
6
  /** Bottom label (e.g. `"Popular"`). */
7
7
  label?: string;
8
8
  /**
9
- * Image shown in the card centre. Ignored when `imageSlot` is provided.
10
- * Accepts a remote URL string, `{ uri }` object, or `require()`-ed asset.
9
+ * Image shown in the card centre. Ignored when `imageSlot` / `children` is
10
+ * provided. Accepts a remote URL string, `{ uri }` object, or `require()`-ed
11
+ * asset.
11
12
  */
12
13
  imageSource?: ImageSourcePropType | string;
13
14
  /**
14
- * Slot replacing the default `Image`. Receives `modes` recursively so inner
15
- * components inherit theming.
15
+ * Slot replacing the default `Image` (Figma Image instance / Code Connect).
16
+ * Receives `modes` recursively so inner components inherit theming.
17
+ * Prefer this or `children` when swapping the media.
16
18
  */
17
19
  imageSlot?: React.ReactNode;
20
+ /**
21
+ * Alias for {@link imageSlot} — the Figma image slot. When both are set,
22
+ * `imageSlot` wins so existing `imageSlot` callers stay authoritative.
23
+ */
24
+ children?: React.ReactNode;
18
25
  /**
19
26
  * Optional badge label rendered as an overlapping pill at the top edge.
20
27
  * Omit or pass `undefined` to hide the badge.
21
28
  */
22
29
  badge?: string;
23
- /** Whether the card is in the selected / active state. */
30
+ /**
31
+ * Whether the card is in the selected / active state (gold stroke).
32
+ * When omitted, falls back to `modes['Card Tab State'] === 'Active'`
33
+ * (and the legacy `modes['Category Card State'] === 'Active'` alias).
34
+ */
24
35
  active?: boolean;
25
36
  /**
26
37
  * Fixed width of the card in dp. Defaults to `60` per the Figma spec.
@@ -28,15 +39,16 @@ export type CategoryCardProps = SafePressableProps & {
28
39
  width?: number;
29
40
  /**
30
41
  * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
31
- * shown and any `numberOfLines` clamp is ignored, so the label wraps to as many
32
- * lines as it needs even when horizontal space is tight. Same behaviour as
33
- * {@link Text}'s `disableTruncation`.
42
+ * shown and any `numberOfLines` clamp is ignored. Defaults to `true` (same
43
+ * overflow behaviour as {@link Text}'s `disableTruncation`). Pass `false` to
44
+ * restore single-line ellipsis clamping.
34
45
  */
35
46
  disableTruncation?: boolean;
36
47
  /**
37
48
  * When `true`, forces the label onto a single line with no wrapping (implies
38
49
  * `disableTruncation`). On web the line overflows horizontally instead of
39
- * wrapping or truncating. Same behaviour as {@link Text}'s `singleLine`.
50
+ * wrapping or truncating. Defaults to `true` — same API as {@link Text}'s
51
+ * `singleLine`. Pass `false` to allow wrapping.
40
52
  */
41
53
  singleLine?: boolean;
42
54
  /** Press handler — the card is always a `Pressable`. */
@@ -60,13 +72,18 @@ export type CategoryCardProps = SafePressableProps & {
60
72
  * optionally show an overlapping badge at the top edge. Cards are typically
61
73
  * laid out in a horizontal `ScrollView` or `HStack`.
62
74
  *
63
- * All visual values resolve through the `cardTab/*` design tokens with
64
- * sensible Figma defaults so the card renders correctly out of the box.
75
+ * Selection is communicated with a gold stroke (`Card Tab State = Active`);
76
+ * the surface stays white in both Idle and Active. All visual values resolve
77
+ * through the `cardTab/*` design tokens with sensible Figma defaults so the
78
+ * card renders correctly out of the box.
79
+ *
80
+ * The image area is a real slot (`imageSlot` or `children`) matching the Figma
81
+ * Image instance — omit both to keep the default `Image`.
65
82
  *
66
83
  * @component
67
84
  * @param {CategoryCardProps} props
68
85
  */
69
- declare function CategoryCard({ label, imageSource, imageSlot, badge, active, width, disableTruncation, singleLine, onPress, disabled, modes: propModes, style, labelStyle, accessibilityLabel, accessibilityHint, accessibilityState, webAccessibilityProps, testID, ...rest }: CategoryCardProps): import("react/jsx-runtime").JSX.Element;
86
+ declare function CategoryCard({ label, imageSource, imageSlot, children, badge, active: activeProp, width, disableTruncation, singleLine, onPress, disabled, modes: propModes, style, labelStyle, accessibilityLabel, accessibilityHint, accessibilityState, webAccessibilityProps, testID, ...rest }: CategoryCardProps): import("react/jsx-runtime").JSX.Element;
70
87
  declare const _default: React.MemoExoticComponent<typeof CategoryCard>;
71
88
  export default _default;
72
89
  //# sourceMappingURL=CategoryCard.d.ts.map
@@ -13,9 +13,13 @@ export type CheckboxItemProps = {
13
13
  /**
14
14
  * Content rendered in the row's label slot (between the leading and trailing
15
15
  * edges). This is the primary way to supply the label and mirrors the Figma
16
- * "slot" — pass a plain string for the default token-styled label, or any
17
- * custom node (e.g. a `<Text>`, a row of `<Text>` + `<Badge>`, etc.) for full
18
- * control. Custom nodes receive the same `modes` as the parent.
16
+ * "Text" slot — pass a plain string for the default token-styled label, or any
17
+ * custom node(s) for full control.
18
+ *
19
+ * Multiple children are laid out in a horizontal row with `slot/gap` (Figma
20
+ * default `Slot gap = XS` → 2px), matching the `Text` + `Link` composition in
21
+ * the design. A single custom node (e.g. a vertical stack) is left as-is.
22
+ * Custom nodes receive the same `modes` as the parent.
19
23
  *
20
24
  * When both `children` and the legacy {@link label} prop are provided,
21
25
  * `children` wins.
@@ -33,7 +37,8 @@ export type CheckboxItemProps = {
33
37
  /**
34
38
  * Position of the checkbox control relative to the label.
35
39
  * - `'leading'` (default): checkbox is rendered on the left, then label, then optional `endSlot` on the right.
36
- * - `'trailing'`: optional `endSlot` is rendered on the left, then label, then checkbox on the right.
40
+ * - `'trailing'`: optional `endSlot` is rendered on the left, then label, then checkbox on the right
41
+ * (row uses `space-between` so the checkbox sits on the trailing edge).
37
42
  *
38
43
  * Matches the Figma "Control" variant on the Checkbox Item component.
39
44
  */
@@ -41,7 +46,8 @@ export type CheckboxItemProps = {
41
46
  /**
42
47
  * Optional content rendered in the row's end slot (e.g. a `Button`). When provided,
43
48
  * it receives the same `modes` as the parent. Wrapped in a fixed-width container
44
- * matching the Figma `endSlot` design.
49
+ * matching the Figma `endSlot` design. Presses on the end slot do not toggle
50
+ * the checkbox.
45
51
  *
46
52
  * Placement depends on `control`:
47
53
  * - With `control="leading"` the slot appears on the right edge (after the label).
@@ -60,15 +66,21 @@ export type CheckboxItemProps = {
60
66
  accessibilityLabel?: string;
61
67
  };
62
68
  /**
63
- * CheckboxItem composes a `Checkbox`, a label and an optional `endSlot` into a
69
+ * CheckboxItem composes a `Checkbox`, a label slot and an optional `endSlot` into a
64
70
  * single horizontal pressable row. Pressing anywhere on the row (outside of the
65
- * `endSlot`) toggles the checkbox, mirroring the typical native form pattern.
71
+ * `endSlot` and nested interactive children such as `Link`) toggles the checkbox,
72
+ * mirroring the typical native form pattern.
66
73
  *
67
74
  * Use the `control` prop to swap the checkbox between the leading (left, default)
68
75
  * and trailing (right) edge of the row. The `endSlot` flips to the opposite edge.
69
76
  *
77
+ * The Figma default composition places `Text` + `Link` in the label slot
78
+ * ("I agree" + "Terms & Conditions"). Pass those as `children` — the slot lays
79
+ * multiple children out in a horizontal row with `slot/gap`.
80
+ *
70
81
  * Mirrors the Figma "Checkbox Item" component and uses the `checkboxItem/*`
71
- * design tokens for typography and spacing.
82
+ * design tokens for row spacing; string labels still resolve `checkboxItem/label/*`
83
+ * for backward-compatible typography.
72
84
  *
73
85
  * @component
74
86
  * @param {CheckboxItemProps} props
@@ -77,13 +89,19 @@ export type CheckboxItemProps = {
77
89
  * ```tsx
78
90
  * const [checked, setChecked] = useState(false)
79
91
  *
80
- * // Recommended: pass the label via the children slot.
92
+ * // Figma default composition Text + Link in the label slot.
81
93
  * <CheckboxItem
82
94
  * checked={checked}
83
95
  * onValueChange={setChecked}
84
96
  * control="leading"
85
97
  * modes={{ 'Color Mode': 'Light' }}
86
98
  * >
99
+ * <Text text="I agree" autolayout="Hug" />
100
+ * <Link text="Terms & Conditions" autolayout="Hug" onPress={openTerms} />
101
+ * </CheckboxItem>
102
+ *
103
+ * // Plain string (still supported).
104
+ * <CheckboxItem checked={checked} onValueChange={setChecked}>
87
105
  * Fixed deposit • 0245
88
106
  * </CheckboxItem>
89
107
  *
@@ -1,8 +1,27 @@
1
- import { type StyleProp, type ViewStyle, type TextStyle } from 'react-native';
1
+ import React from 'react';
2
+ import { type StyleProp, type ViewStyle, type TextStyle, type GestureResponderEvent } from 'react-native';
2
3
  import type { Modes } from '../../design-tokens';
3
4
  export type ExpandableCheckboxProps = {
4
- /** Long text label rendered next to the checkbox. */
5
+ /**
6
+ * Primary label rendered next to the checkbox (Figma `Text` instance).
7
+ * Ignored when {@link children} is provided.
8
+ */
5
9
  label?: string;
10
+ /**
11
+ * Optional underlined link rendered after {@link label} (Figma `Link`
12
+ * instance, e.g. "Terms & Conditions"). Ignored when {@link children} is
13
+ * provided.
14
+ */
15
+ linkLabel?: string;
16
+ /** Press handler for {@link linkLabel}. Navigation is left to the consumer. */
17
+ onLinkPress?: (event: GestureResponderEvent) => void;
18
+ /**
19
+ * Full label-slot override matching the Figma Checkbox Item `slot`. When
20
+ * provided, {@link label} / {@link linkLabel} are ignored and `modes` are
21
+ * cascaded into the slot children. Prefer this for fully custom label
22
+ * compositions.
23
+ */
24
+ children?: React.ReactNode;
6
25
  /** Whether the checkbox is checked (controlled). */
7
26
  checked?: boolean;
8
27
  /** Initial checked state (uncontrolled). */
@@ -33,20 +52,24 @@ export type ExpandableCheckboxProps = {
33
52
  modes?: Modes;
34
53
  /** Override outer container styles. */
35
54
  style?: StyleProp<ViewStyle>;
36
- /** Override the label text styles. */
55
+ /**
56
+ * Override styles applied to the composed {@link label} `Text`. No-op when
57
+ * {@link children} is provided.
58
+ */
37
59
  labelStyle?: StyleProp<TextStyle>;
38
60
  /** Accessibility label for the checkbox. Falls back to `label`. */
39
61
  accessibilityLabel?: string;
40
62
  };
41
63
  /**
42
- * ExpandableCheckbox composes a `Checkbox`, a long-form label and a
43
- * "Read more" / "Read less" toggle. Mirrors the Figma "Expandable Checkbox"
44
- * component with two states:
64
+ * ExpandableCheckbox composes a `CheckboxItem` (checkbox + label slot), optional
65
+ * `Text`/`Link` label content, and a "Read more" / "Read less" toggle. Mirrors
66
+ * the Figma "Expandable Checkbox" component with two states:
45
67
  *
46
- * - **Idle (collapsed)** — checkbox + truncated label + toggle button arranged
47
- * in a horizontal row (cross-axis centered).
48
- * - **Open (expanded)** — checkbox + full multi-line label, with the toggle
49
- * button right-aligned beneath the row.
68
+ * - **Idle (collapsed)** — horizontal row: CheckboxItem (fill) + toggle button
69
+ * (hug), cross-axis centered.
70
+ * - **Open (expanded)** — vertical stack aligned to the end: CheckboxItem with
71
+ * the label slot wrapped in a `ScrollArea` (capped by `checkbox/maxHeight`),
72
+ * then the toggle button right-aligned beneath.
50
73
  *
51
74
  * The checkbox and the toggle button have independent press handlers — pressing
52
75
  * the toggle does not affect the checked state, and toggling the checkbox does
@@ -58,13 +81,15 @@ export type ExpandableCheckboxProps = {
58
81
  * @example
59
82
  * ```tsx
60
83
  * <ExpandableCheckbox
61
- * label="By checking this box, I (a) acknowledge and (b) agree to the full terms…"
84
+ * label="I agree"
85
+ * linkLabel="Terms & Conditions"
86
+ * onLinkPress={openTerms}
62
87
  * defaultChecked
63
88
  * onValueChange={setAccepted}
64
89
  * modes={{ 'Color Mode': 'Light' }}
65
90
  * />
66
91
  * ```
67
92
  */
68
- declare function ExpandableCheckbox({ label, checked: controlledChecked, defaultChecked, onValueChange, expanded: controlledExpanded, defaultExpanded, onExpandedChange, disabled, readMoreLabel, readLessLabel, collapsedLines, disableTruncation, modes, style, labelStyle, accessibilityLabel, }: ExpandableCheckboxProps): import("react/jsx-runtime").JSX.Element;
93
+ declare function ExpandableCheckbox({ label, linkLabel, onLinkPress, children, checked: controlledChecked, defaultChecked, onValueChange, expanded: controlledExpanded, defaultExpanded, onExpandedChange, disabled, readMoreLabel, readLessLabel, collapsedLines, disableTruncation, modes, style, labelStyle, accessibilityLabel, }: ExpandableCheckboxProps): import("react/jsx-runtime").JSX.Element;
69
94
  export default ExpandableCheckbox;
70
95
  //# sourceMappingURL=ExpandableCheckbox.d.ts.map
@@ -26,7 +26,7 @@ type IconCapsuleProps = {
26
26
  * @param {Object} props - Component props
27
27
  * @param {string} [props.iconName="ic_card"] - The name of the icon to display from the icon registry
28
28
  * @param {UnifiedSource} [props.source] - Fallback source (remote URI, inline SVG XML, `require()` asset, SVG React component, or React element). Used when `iconName` is missing or unknown. Tinted with the mode-resolved icon color so it follows design tokens just like a built-in icon.
29
- * @param {Object} [props.modes={}] - Mode configuration for design tokens (e.g., {"Appearance": "Primary"})
29
+ * @param {Object} [props.modes={}] - Mode configuration for design tokens (e.g., {"AppearanceBrand": "Primary"})
30
30
  * @param {string} [props.accessibilityLabel] - Accessibility label for screen readers
31
31
  * @param {string} [props.accessibilityRole] - Accessibility role (defaults to "image" for decorative icons)
32
32
  *
@@ -13,8 +13,9 @@ export type MetricDataProps = {
13
13
  caption?: string;
14
14
  /**
15
15
  * Optional glyph shown to the left of the value. Pass a registry icon name
16
- * (e.g. `'ic_card'`) or a custom node. Rendered at 18px, tinted to the value
17
- * colour. Hidden when omitted.
16
+ * (e.g. `'ic_card'`) or a custom node. Size/colour resolve from `icon/size`
17
+ * and `icon/color` (Figma seeds `AppearanceBrand: Secondary` → purple).
18
+ * Opt-in — omitted keeps existing no-icon instances unchanged.
18
19
  */
19
20
  icon?: string | React.ReactNode;
20
21
  /** Design-token modes for theming. */
@@ -37,9 +38,10 @@ export type MetricDataProps = {
37
38
  * MetricData — a compact, centered metric block.
38
39
  *
39
40
  * Stacks a small `title`, a prominent `value` (with an optional leading
40
- * `icon`), and a muted `caption`. Typography, colours, gaps and padding all
41
- * resolve from the `metricdata/*` design tokens. `title`, `caption` and `icon`
42
- * are optional; only `value` is shown by default.
41
+ * `icon` in a `value wrap` row), and a muted `caption`. Typography, colours,
42
+ * gaps and padding resolve from the `metricdata/*` design tokens; the leading
43
+ * glyph uses `icon/*`. `title`, `caption` and `icon` are optional — omit
44
+ * `icon` to keep the legacy text-only layout.
43
45
  *
44
46
  * @example
45
47
  * ```tsx
@@ -3,15 +3,24 @@ import { type ViewStyle, type StyleProp, type ImageSourcePropType } from 'react-
3
3
  import type { Modes } from '../../design-tokens';
4
4
  /**
5
5
  * A single metric column inside the card's stats row: a small title, a bold
6
- * value and an optional muted caption.
6
+ * value (optionally preceded by an icon) and an optional muted caption.
7
7
  */
8
8
  export interface PdpCcCardMetric {
9
9
  /** Small label rendered above the value (e.g. `"Weight"`). */
10
10
  title?: string;
11
- /** The prominent value (e.g. `"24K"`). */
12
- value?: string;
11
+ /**
12
+ * The prominent value (e.g. `"24K"`). Accepts a string or any node
13
+ * (e.g. a `MoneyValue`) for richer composition.
14
+ */
15
+ value?: string | React.ReactNode;
13
16
  /** Optional muted caption rendered below the value. */
14
17
  caption?: string;
18
+ /**
19
+ * Optional glyph shown to the left of the value. Pass a registry icon name
20
+ * (e.g. `'ic_card'`) or a custom node. Opt-in — omit to keep the legacy
21
+ * text-only metric column.
22
+ */
23
+ icon?: string | React.ReactNode;
15
24
  }
16
25
  export interface PdpCcCardProps {
17
26
  /**
@@ -59,7 +68,7 @@ export interface PdpCcCardProps {
59
68
  /**
60
69
  * The metric columns rendered in the stats row. Vertical dividers are
61
70
  * inserted automatically between adjacent metrics. Defaults to two sample
62
- * metrics.
71
+ * metrics (with leading icons) matching the Figma default.
63
72
  */
64
73
  metrics?: PdpCcCardMetric[];
65
74
  /** CTA button label. Defaults to `"button"`. */
@@ -96,8 +105,9 @@ export interface PdpCcCardProps {
96
105
  * `imageSource` for the default image or `media` for a full slot override.
97
106
  * - **Title** — a centered headline + subtitle rendered through the shared
98
107
  * {@link Title} component (`title/*`, `pageSubtitle/*` tokens).
99
- * - **Metrics** — a row of {@link PdpCcCardMetric} columns (title / value /
100
- * caption) separated by vertical `Divider`s (`metricdata/*` tokens).
108
+ * - **Metrics** — a row of {@link PdpCcCardMetric} columns composed via
109
+ * {@link MetricData} (title / optional icon + value / caption) separated by
110
+ * vertical `Divider`s (`metricdata/*`, `icon/*` tokens).
101
111
  * - **CTA** — a small tonal {@link Button} (`Button / Size: S`,
102
112
  * `AppearanceBrand: Secondary`, `Emphasis: Medium`) with a leading icon.
103
113
  *