jfs-components 0.0.79 → 0.0.84

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 (110) hide show
  1. package/lib/commonjs/components/AppBar/AppBar.js +56 -6
  2. package/lib/commonjs/components/Attached/Attached.js +46 -7
  3. package/lib/commonjs/components/Checkbox/Checkbox.js +18 -2
  4. package/lib/commonjs/components/Drawer/Drawer.js +6 -1
  5. package/lib/commonjs/components/DropdownInput/DropdownInput.js +30 -6
  6. package/lib/commonjs/components/ExpandableCheckbox/ExpandableCheckbox.js +17 -11
  7. package/lib/commonjs/components/FormField/FormField.js +1 -14
  8. package/lib/commonjs/components/FullscreenModal/FullscreenModal.js +5 -1
  9. package/lib/commonjs/components/ListItem/ListItem.js +6 -11
  10. package/lib/commonjs/components/MessageField/MessageField.js +1 -13
  11. package/lib/commonjs/components/PaymentFeedback/PaymentFeedback.js +12 -9
  12. package/lib/commonjs/components/PlanComparisonCard/PlanComparisonCard.js +69 -160
  13. package/lib/commonjs/components/Spinner/Spinner.js +217 -0
  14. package/lib/commonjs/components/TextInput/TextInput.js +33 -18
  15. package/lib/commonjs/components/index.js +7 -0
  16. package/lib/commonjs/icons/components/IconArrowdown.js +19 -0
  17. package/lib/commonjs/icons/components/IconArrowup.js +19 -0
  18. package/lib/commonjs/icons/components/IconChevrondowncircle.js +19 -0
  19. package/lib/commonjs/icons/components/IconChevronleftcircle.js +19 -0
  20. package/lib/commonjs/icons/components/IconChevronrightcircle.js +19 -0
  21. package/lib/commonjs/icons/components/IconChevronupcircle.js +19 -0
  22. package/lib/commonjs/icons/components/IconOsnavback.js +19 -0
  23. package/lib/commonjs/icons/components/IconOsnavcenter.js +19 -0
  24. package/lib/commonjs/icons/components/IconOsnavhome.js +19 -0
  25. package/lib/commonjs/icons/components/IconOsnavtask.js +19 -0
  26. package/lib/commonjs/icons/components/IconSignin.js +19 -0
  27. package/lib/commonjs/icons/components/IconSignout.js +19 -0
  28. package/lib/commonjs/icons/components/index.js +132 -0
  29. package/lib/commonjs/icons/registry.js +2 -2
  30. package/lib/module/components/AppBar/AppBar.js +56 -6
  31. package/lib/module/components/Attached/Attached.js +46 -7
  32. package/lib/module/components/Checkbox/Checkbox.js +18 -2
  33. package/lib/module/components/Drawer/Drawer.js +6 -1
  34. package/lib/module/components/DropdownInput/DropdownInput.js +30 -6
  35. package/lib/module/components/ExpandableCheckbox/ExpandableCheckbox.js +17 -11
  36. package/lib/module/components/FormField/FormField.js +3 -16
  37. package/lib/module/components/FullscreenModal/FullscreenModal.js +5 -1
  38. package/lib/module/components/ListItem/ListItem.js +6 -11
  39. package/lib/module/components/MessageField/MessageField.js +3 -15
  40. package/lib/module/components/PaymentFeedback/PaymentFeedback.js +13 -9
  41. package/lib/module/components/PlanComparisonCard/PlanComparisonCard.js +72 -160
  42. package/lib/module/components/Spinner/Spinner.js +212 -0
  43. package/lib/module/components/TextInput/TextInput.js +34 -19
  44. package/lib/module/components/index.js +1 -0
  45. package/lib/module/icons/components/IconArrowdown.js +12 -0
  46. package/lib/module/icons/components/IconArrowup.js +12 -0
  47. package/lib/module/icons/components/IconChevrondowncircle.js +12 -0
  48. package/lib/module/icons/components/IconChevronleftcircle.js +12 -0
  49. package/lib/module/icons/components/IconChevronrightcircle.js +12 -0
  50. package/lib/module/icons/components/IconChevronupcircle.js +12 -0
  51. package/lib/module/icons/components/IconOsnavback.js +12 -0
  52. package/lib/module/icons/components/IconOsnavcenter.js +12 -0
  53. package/lib/module/icons/components/IconOsnavhome.js +12 -0
  54. package/lib/module/icons/components/IconOsnavtask.js +12 -0
  55. package/lib/module/icons/components/IconSignin.js +12 -0
  56. package/lib/module/icons/components/IconSignout.js +12 -0
  57. package/lib/module/icons/components/index.js +12 -0
  58. package/lib/module/icons/registry.js +2 -2
  59. package/lib/typescript/src/components/AppBar/AppBar.d.ts +12 -1
  60. package/lib/typescript/src/components/Attached/Attached.d.ts +19 -16
  61. package/lib/typescript/src/components/DropdownInput/DropdownInput.d.ts +3 -2
  62. package/lib/typescript/src/components/ListItem/ListItem.d.ts +3 -3
  63. package/lib/typescript/src/components/PaymentFeedback/PaymentFeedback.d.ts +5 -1
  64. package/lib/typescript/src/components/PlanComparisonCard/PlanComparisonCard.d.ts +10 -8
  65. package/lib/typescript/src/components/Spinner/Spinner.d.ts +45 -0
  66. package/lib/typescript/src/components/index.d.ts +1 -0
  67. package/lib/typescript/src/icons/components/IconArrowdown.d.ts +3 -0
  68. package/lib/typescript/src/icons/components/IconArrowup.d.ts +3 -0
  69. package/lib/typescript/src/icons/components/IconChevrondowncircle.d.ts +3 -0
  70. package/lib/typescript/src/icons/components/IconChevronleftcircle.d.ts +3 -0
  71. package/lib/typescript/src/icons/components/IconChevronrightcircle.d.ts +3 -0
  72. package/lib/typescript/src/icons/components/IconChevronupcircle.d.ts +3 -0
  73. package/lib/typescript/src/icons/components/IconOsnavback.d.ts +3 -0
  74. package/lib/typescript/src/icons/components/IconOsnavcenter.d.ts +3 -0
  75. package/lib/typescript/src/icons/components/IconOsnavhome.d.ts +3 -0
  76. package/lib/typescript/src/icons/components/IconOsnavtask.d.ts +3 -0
  77. package/lib/typescript/src/icons/components/IconSignin.d.ts +3 -0
  78. package/lib/typescript/src/icons/components/IconSignout.d.ts +3 -0
  79. package/lib/typescript/src/icons/components/index.d.ts +12 -0
  80. package/lib/typescript/src/icons/registry.d.ts +1 -1
  81. package/package.json +3 -2
  82. package/src/components/AppBar/AppBar.tsx +79 -12
  83. package/src/components/Attached/Attached.tsx +63 -7
  84. package/src/components/Checkbox/Checkbox.tsx +14 -2
  85. package/src/components/Drawer/Drawer.tsx +4 -0
  86. package/src/components/DropdownInput/DropdownInput.tsx +54 -20
  87. package/src/components/ExpandableCheckbox/ExpandableCheckbox.tsx +13 -9
  88. package/src/components/FormField/FormField.tsx +3 -19
  89. package/src/components/FullscreenModal/FullscreenModal.tsx +3 -0
  90. package/src/components/ListItem/ListItem.tsx +14 -16
  91. package/src/components/MessageField/MessageField.tsx +3 -18
  92. package/src/components/PaymentFeedback/PaymentFeedback.tsx +15 -8
  93. package/src/components/PlanComparisonCard/PlanComparisonCard.tsx +82 -192
  94. package/src/components/Spinner/Spinner.tsx +273 -0
  95. package/src/components/TextInput/TextInput.tsx +37 -19
  96. package/src/components/index.ts +1 -0
  97. package/src/icons/components/IconArrowdown.tsx +11 -0
  98. package/src/icons/components/IconArrowup.tsx +11 -0
  99. package/src/icons/components/IconChevrondowncircle.tsx +11 -0
  100. package/src/icons/components/IconChevronleftcircle.tsx +11 -0
  101. package/src/icons/components/IconChevronrightcircle.tsx +11 -0
  102. package/src/icons/components/IconChevronupcircle.tsx +11 -0
  103. package/src/icons/components/IconOsnavback.tsx +11 -0
  104. package/src/icons/components/IconOsnavcenter.tsx +11 -0
  105. package/src/icons/components/IconOsnavhome.tsx +11 -0
  106. package/src/icons/components/IconOsnavtask.tsx +11 -0
  107. package/src/icons/components/IconSignin.tsx +11 -0
  108. package/src/icons/components/IconSignout.tsx +11 -0
  109. package/src/icons/components/index.ts +12 -0
  110. package/src/icons/registry.ts +49 -1
@@ -19,8 +19,19 @@ export type AppBarProps = {
19
19
  /**
20
20
  * Slot for the middle content.
21
21
  * Often used for "Page Title" in SubPage.
22
+ *
23
+ * On `SubPage` this is rendered as an absolutely-centered box (matching the
24
+ * Figma "slot wrap"): it stays centered in the bar regardless of how wide
25
+ * the leading/actions slots are, and its content fills/shrinks responsively
26
+ * within {@link middleSlotWidth}.
22
27
  */
23
28
  middleSlot?: React.ReactNode;
29
+ /**
30
+ * Width of the centered `SubPage` middle slot, in px.
31
+ * Defaults to the Figma value (192). Has no effect on `MainPage`.
32
+ * @default 192
33
+ */
34
+ middleSlotWidth?: number;
24
35
  /**
25
36
  * Slot for the actions on the right.
26
37
  */
@@ -40,6 +51,6 @@ export type AppBarProps = {
40
51
  accessibilityLabel?: string;
41
52
  accessibilityHint?: string;
42
53
  } & Omit<React.ComponentProps<typeof View>, 'style' | 'accessibilityRole' | 'accessibilityLabel' | 'accessibilityHint'>;
43
- export default function AppBar({ type, leadingSlot, middleSlot, actionsSlot, modes: propModes, onLeadingPress, style, accessibilityLabel, accessibilityHint, ...rest }: AppBarProps): import("react/jsx-runtime").JSX.Element;
54
+ export default function AppBar({ type, leadingSlot, middleSlot, middleSlotWidth, actionsSlot, modes: propModes, onLeadingPress, style, accessibilityLabel, accessibilityHint, ...rest }: AppBarProps): import("react/jsx-runtime").JSX.Element;
44
55
  export {};
45
56
  //# sourceMappingURL=AppBar.d.ts.map
@@ -18,6 +18,24 @@ export type AttachedProps = Omit<ViewProps, 'children'> & {
18
18
  * `modes` are cascaded into it as well.
19
19
  */
20
20
  badge?: React.ReactNode;
21
+ /**
22
+ * Enforces a fixed square size (in px) on the `badge` slot, regardless of
23
+ * what node is passed. The badge is wrapped in a box of
24
+ * `badgeSize × badgeSize` with `overflow: 'hidden'`, and the badge content is
25
+ * stretched to fill it. Use this to guarantee the design-token size even when
26
+ * a consumer drops in an arbitrary node (e.g. an `Image`) whose intrinsic
27
+ * size/aspect-ratio would otherwise win.
28
+ *
29
+ * When omitted, the badge keeps its own intrinsic size (legacy behavior).
30
+ */
31
+ badgeSize?: number;
32
+ /**
33
+ * Corner radius used to clip the `badge` box. Only applies when `badgeSize`
34
+ * is set. Anything that overflows the rounded box (e.g. a non-square image)
35
+ * is clipped.
36
+ * @default badgeSize / 2 (a full circle)
37
+ */
38
+ badgeRadius?: number;
21
39
  /**
22
40
  * Anchor point for the `badge` relative to the main content.
23
41
  * @default 'bottom-right'
@@ -40,22 +58,7 @@ export type AttachedProps = Omit<ViewProps, 'children'> & {
40
58
  modes?: Record<string, any>;
41
59
  style?: StyleProp<ViewStyle>;
42
60
  };
43
- /**
44
- * Attached — overlays a small `badge` on top of arbitrary main content,
45
- * centered on one of nine anchor points (corners, edge midpoints, or center).
46
- *
47
- * The badge straddles the chosen anchor regardless of either element's size:
48
- * both the main content and the badge are measured via `onLayout`, then the
49
- * badge is absolutely positioned so its center lands exactly on the anchor.
50
- *
51
- * @example
52
- * ```tsx
53
- * <Attached position="bottom-right" badge={<InstitutionBadge modes={modes} />} modes={modes}>
54
- * <IconCapsule iconName="ic_card" modes={modes} />
55
- * </Attached>
56
- * ```
57
- */
58
- declare function Attached({ children, badge, position, circular, modes: propModes, style, ...rest }: AttachedProps): import("react/jsx-runtime").JSX.Element;
61
+ declare function Attached({ children, badge, badgeSize, badgeRadius, position, circular, modes: propModes, style, ...rest }: AttachedProps): import("react/jsx-runtime").JSX.Element;
59
62
  declare const _default: React.MemoExoticComponent<typeof Attached>;
60
63
  export default _default;
61
64
  //# sourceMappingURL=Attached.d.ts.map
@@ -73,8 +73,9 @@ export type DropdownInputProps = {
73
73
  */
74
74
  menuMaxHeight?: number;
75
75
  /**
76
- * Pixel offset between the trigger and the popup. Defaults to 4 so the
77
- * popup visually peeks below the input.
76
+ * Pixel gap between the trigger and the popup. When omitted, it defaults
77
+ * to the `formField/gap` design token so the menu sits the same distance
78
+ * below the input as the rest of the field's internal spacing.
78
79
  */
79
80
  menuOffset?: number;
80
81
  /**
@@ -6,8 +6,8 @@ type ListItemProps = {
6
6
  title?: string;
7
7
  supportText?: string;
8
8
  showSupportText?: boolean;
9
- /** Leading slot (Figma "leading"). Defaults to an `IconCapsule` when omitted. */
10
- leading?: React.ReactNode;
9
+ /** Leading slot (Figma "leading"). Omitted or `null` renders nothing. */
10
+ leading?: React.ReactNode | null;
11
11
  supportSlot?: React.ReactNode;
12
12
  /** Trailing slot (Figma "trailing"), e.g. `MoneyValue` or `Button`. Horizontal layout only. */
13
13
  trailing?: React.ReactNode;
@@ -53,7 +53,7 @@ type ListItemProps = {
53
53
  * @param {string} [props.title='Title'] - Primary title used in the horizontal layout.
54
54
  * @param {string} [props.supportText='Support Text'] - Support text used in both layouts when `supportSlot` is not provided.
55
55
  * @param {boolean} [props.showSupportText=true] - Toggles rendering of the support text in Horizontal layout.
56
- * @param {React.ReactNode} [props.leading] - Optional leading slot. Defaults to `IconCapsule`.
56
+ * @param {React.ReactNode|null} [props.leading] - Optional leading slot. Omitted or `null` renders nothing.
57
57
  * @param {React.ReactNode} [props.supportSlot] - Optional custom slot used instead of the default support text block.
58
58
  * @param {React.ReactNode} [props.trailing] - Optional trailing slot (Figma Slot "trailing"). Horizontal layout only.
59
59
  * @param {boolean} [props.navArrow=true] - Whether to show NavArrow on the far right (Horizontal layout only).
@@ -15,7 +15,11 @@ export type PaymentFeedbackProps = {
15
15
  iconName?: string;
16
16
  /** Optional custom media slot that replaces the default IconCapsule */
17
17
  renderMedia?: ReactNode;
18
- /** Mode configuration for design tokens */
18
+ /**
19
+ * Mode configuration for design tokens. Also drives the default
20
+ * IconCapsule's color — pass `AppearanceSystem: 'positive' | 'warning' |
21
+ * 'negative'` to render a green/orange/red capsule (defaults to `positive`).
22
+ */
19
23
  modes?: Record<string, any>;
20
24
  style?: ViewStyle;
21
25
  };
@@ -47,18 +47,20 @@ export type PlanComparisonCardProps = {
47
47
  columns?: PlanComparisonColumn[];
48
48
  /** Feature rows compared across the plan columns. */
49
49
  rows?: PlanComparisonRow[];
50
- /**
51
- * Minimum flex-grow on the label column when the table is given extra
52
- * horizontal space. Plan columns always size to their content and never
53
- * shrink below it.
54
- * @default 0
55
- */
56
- labelColumnFlex?: number;
57
50
  /** Design token modes for theming (e.g. `{ "Color Mode": "Light" }`). */
58
51
  modes?: Record<string, any>;
59
52
  /** Override the outer container style. */
60
53
  style?: StyleProp<ViewStyle>;
61
54
  };
62
- declare function PlanComparisonCard({ columns, rows, labelColumnFlex, modes, style, }: PlanComparisonCardProps): import("react/jsx-runtime").JSX.Element;
55
+ /**
56
+ * PlanComparisonCard renders a compact comparison table that pits the user's
57
+ * current plan against one or more alternative plans across a set of feature
58
+ * rows. Implementation of Figma node `4498:2968` (`PlanComparisonCard`).
59
+ *
60
+ * Columns use a 1.8fr / 1fr flex ratio (label vs plan), matching the Figma grid.
61
+ *
62
+ * @component
63
+ */
64
+ declare function PlanComparisonCard({ columns, rows, modes, style, }: PlanComparisonCardProps): import("react/jsx-runtime").JSX.Element;
63
65
  export default PlanComparisonCard;
64
66
  //# sourceMappingURL=PlanComparisonCard.d.ts.map
@@ -0,0 +1,45 @@
1
+ import { type StyleProp, type ViewProps, type ViewStyle } from 'react-native';
2
+ /**
3
+ * Per-segment colours, resolved from the Figma `spiner/*` tokens. Consumers can
4
+ * override any subset via the `colors` prop.
5
+ */
6
+ export type SpinnerColors = {
7
+ /** Leading segment (front of the falling chain). */
8
+ primary?: string;
9
+ /** Middle segment. */
10
+ secondary?: string;
11
+ /** Trailing segment (tail of the chain). */
12
+ tertiary?: string;
13
+ };
14
+ type SpinnerBaseProps = Omit<ViewProps, 'children' | 'style'>;
15
+ export type SpinnerProps = SpinnerBaseProps & {
16
+ /**
17
+ * Diameter in px. The spinner is always rendered at a 1:1 ratio, so a single
18
+ * size controls both width and height. Defaults to the Figma size (72).
19
+ */
20
+ size?: number;
21
+ /**
22
+ * Duration of one full clockwise revolution of the leading segment, in ms.
23
+ * Lower = faster. Defaults to 2400.
24
+ */
25
+ durationMs?: number;
26
+ /**
27
+ * "Weightiness" of the fall, in `[0, 0.9]`. 0 = perfectly constant speed;
28
+ * higher values make segments whip faster over the top and ease through the
29
+ * bottom. Kept below 1 so the motion never reverses. Defaults to 0.45.
30
+ */
31
+ gravity?: number;
32
+ /** Override any subset of the token-driven segment colours. */
33
+ colors?: SpinnerColors;
34
+ /** When false, renders a static resting spinner (also honoured for reduced motion). Defaults to true. */
35
+ animating?: boolean;
36
+ /** Design token modes forwarded to token lookups. */
37
+ modes?: Record<string, any>;
38
+ /** Container style override. */
39
+ style?: StyleProp<ViewStyle>;
40
+ /** Accessibility label announced to assistive tech. Defaults to "Loading". */
41
+ accessibilityLabel?: string;
42
+ };
43
+ declare function Spinner({ size, durationMs, gravity, colors, animating, modes: propModes, style, accessibilityLabel, ...rest }: SpinnerProps): import("react/jsx-runtime").JSX.Element;
44
+ export default Spinner;
45
+ //# sourceMappingURL=Spinner.d.ts.map
@@ -65,6 +65,7 @@ export { default as Title, type TitleProps } from './Title/Title';
65
65
  export { default as Screen, type ScreenProps } from './Screen/Screen';
66
66
  export { default as Section } from './Section/Section';
67
67
  export { default as Slot, type SlotProps, type SlotLayoutDirection } from './Slot/Slot';
68
+ export { default as Spinner, type SpinnerProps, type SpinnerColors } from './Spinner/Spinner';
68
69
  export { default as Stepper, type StepperProps } from './Stepper/Stepper';
69
70
  export { Step, type StepProps, type StepStatus } from './Stepper/Step';
70
71
  export { StepLabel, type StepLabelProps } from './Stepper/StepLabel';
@@ -0,0 +1,3 @@
1
+ import { SvgProps } from 'react-native-svg';
2
+ export declare const IconArrowdown: (props: SvgProps) => import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=IconArrowdown.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { SvgProps } from 'react-native-svg';
2
+ export declare const IconArrowup: (props: SvgProps) => import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=IconArrowup.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { SvgProps } from 'react-native-svg';
2
+ export declare const IconChevrondowncircle: (props: SvgProps) => import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=IconChevrondowncircle.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { SvgProps } from 'react-native-svg';
2
+ export declare const IconChevronleftcircle: (props: SvgProps) => import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=IconChevronleftcircle.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { SvgProps } from 'react-native-svg';
2
+ export declare const IconChevronrightcircle: (props: SvgProps) => import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=IconChevronrightcircle.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { SvgProps } from 'react-native-svg';
2
+ export declare const IconChevronupcircle: (props: SvgProps) => import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=IconChevronupcircle.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { SvgProps } from 'react-native-svg';
2
+ export declare const IconOsnavback: (props: SvgProps) => import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=IconOsnavback.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { SvgProps } from 'react-native-svg';
2
+ export declare const IconOsnavcenter: (props: SvgProps) => import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=IconOsnavcenter.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { SvgProps } from 'react-native-svg';
2
+ export declare const IconOsnavhome: (props: SvgProps) => import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=IconOsnavhome.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { SvgProps } from 'react-native-svg';
2
+ export declare const IconOsnavtask: (props: SvgProps) => import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=IconOsnavtask.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { SvgProps } from 'react-native-svg';
2
+ export declare const IconSignin: (props: SvgProps) => import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=IconSignin.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { SvgProps } from 'react-native-svg';
2
+ export declare const IconSignout: (props: SvgProps) => import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=IconSignout.d.ts.map
@@ -63,10 +63,12 @@ export * from './IconArmed';
63
63
  export * from './IconArmedoff';
64
64
  export * from './IconArmedpartially';
65
65
  export * from './IconArrowback';
66
+ export * from './IconArrowdown';
66
67
  export * from './IconArrowline';
67
68
  export * from './IconArrowlinediagonal';
68
69
  export * from './IconArrowlinedot';
69
70
  export * from './IconArrownext';
71
+ export * from './IconArrowup';
70
72
  export * from './IconArtificialinsemination';
71
73
  export * from './IconAssistivegrid';
72
74
  export * from './IconAstrology';
@@ -236,9 +238,13 @@ export * from './IconChemistry';
236
238
  export * from './IconCherry';
237
239
  export * from './IconChestpain';
238
240
  export * from './IconChevrondown';
241
+ export * from './IconChevrondowncircle';
239
242
  export * from './IconChevronleft';
243
+ export * from './IconChevronleftcircle';
240
244
  export * from './IconChevronright';
245
+ export * from './IconChevronrightcircle';
241
246
  export * from './IconChevronup';
247
+ export * from './IconChevronupcircle';
242
248
  export * from './IconChildrengame';
243
249
  export * from './IconCholesterol';
244
250
  export * from './IconCleaning';
@@ -757,6 +763,10 @@ export * from './IconOperatingtable';
757
763
  export * from './IconOperator';
758
764
  export * from './IconOrder';
759
765
  export * from './IconOrders';
766
+ export * from './IconOsnavback';
767
+ export * from './IconOsnavcenter';
768
+ export * from './IconOsnavhome';
769
+ export * from './IconOsnavtask';
760
770
  export * from './IconOtp';
761
771
  export * from './IconOutofstock';
762
772
  export * from './IconOutgoing';
@@ -953,6 +963,8 @@ export * from './IconShutter10s';
953
963
  export * from './IconShutter3s';
954
964
  export * from './IconShutter5s';
955
965
  export * from './IconSign';
966
+ export * from './IconSignin';
967
+ export * from './IconSignout';
956
968
  export * from './IconSim';
957
969
  export * from './IconSim1';
958
970
  export * from './IconSim2';
@@ -4,7 +4,7 @@
4
4
  * Auto-generated from SVG files in src/icons/
5
5
  * DO NOT EDIT MANUALLY - Run "npm run icons:generate" to regenerate
6
6
  *
7
- * Generated: 2026-05-29T17:01:15.629Z
7
+ * Generated: 2026-06-01T15:33:15.385Z
8
8
  */
9
9
  export declare const iconRegistry: Record<string, {
10
10
  path: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jfs-components",
3
- "version": "0.0.79",
3
+ "version": "0.0.84",
4
4
  "description": "React Native Jio Finance Components Library",
5
5
  "author": "sunshuaiqi@gmail.com",
6
6
  "license": "MIT",
@@ -40,7 +40,8 @@
40
40
  "icons:generate": "node scripts/generate-icon-registry.js",
41
41
  "prepare": "bob build",
42
42
  "build": "bob build",
43
- "prepack": "yarn icons:generate && bob build"
43
+ "prepack": "yarn icons:generate && bob build",
44
+ "push:xpaydemo": "bash scripts/push-to-xpaydemo.sh"
44
45
  },
45
46
  "react-native-builder-bob": {
46
47
  "source": "src",
@@ -8,6 +8,14 @@ import { cloneChildrenWithModes, EMPTY_MODES } from '../../utils/react-utils'
8
8
 
9
9
  type AppBarType = 'MainPage' | 'SubPage'
10
10
 
11
+ // SubPage "slot wrap" geometry, taken directly from the Figma design
12
+ // (node 449:7876). The middle slot is an absolutely-centered box of a fixed
13
+ // size; its inner content (node 3991:4125) is a `flex: 1 0 0; min-width: 1px`
14
+ // item so it fills / shrinks responsively within that box.
15
+ const SUBPAGE_MIDDLE_DEFAULT_WIDTH = 192
16
+ const SUBPAGE_MIDDLE_HEIGHT = 32
17
+ const SUBPAGE_MIDDLE_PADDING_HORIZONTAL = 21
18
+
11
19
  export type AppBarProps = {
12
20
  /**
13
21
  * Type of the App Bar.
@@ -26,8 +34,19 @@ export type AppBarProps = {
26
34
  /**
27
35
  * Slot for the middle content.
28
36
  * Often used for "Page Title" in SubPage.
37
+ *
38
+ * On `SubPage` this is rendered as an absolutely-centered box (matching the
39
+ * Figma "slot wrap"): it stays centered in the bar regardless of how wide
40
+ * the leading/actions slots are, and its content fills/shrinks responsively
41
+ * within {@link middleSlotWidth}.
29
42
  */
30
43
  middleSlot?: React.ReactNode;
44
+ /**
45
+ * Width of the centered `SubPage` middle slot, in px.
46
+ * Defaults to the Figma value (192). Has no effect on `MainPage`.
47
+ * @default 192
48
+ */
49
+ middleSlotWidth?: number;
31
50
  /**
32
51
  * Slot for the actions on the right.
33
52
  */
@@ -52,6 +71,7 @@ export default function AppBar({
52
71
  type = 'MainPage',
53
72
  leadingSlot,
54
73
  middleSlot,
74
+ middleSlotWidth = SUBPAGE_MIDDLE_DEFAULT_WIDTH,
55
75
  actionsSlot,
56
76
  modes: propModes = EMPTY_MODES,
57
77
  onLeadingPress,
@@ -160,13 +180,39 @@ export default function AppBar({
160
180
  ? <View style={actionsStyle}>{cloneChildrenWithModes(React.Children.toArray(actionsSlot), modes)}</View>
161
181
  : null
162
182
 
163
- // When there is no middleSlot we want leading & actions pinned to the
164
- // outer edges, so we apply `space-between` at the wrapper. With a middle
165
- // slot present, the middle (flex: 1) absorbs the remaining space, so
166
- // `space-between` is a no-op.
183
+ // SubPage centers its middle slot via absolute positioning (see Figma
184
+ // "slot wrap"), so it never participates in the row flow. Only MainPage
185
+ // keeps the legacy in-flow middle slot.
186
+ const hasInFlowMiddle = isMain && !!processedMiddle
187
+
188
+ // With an in-flow middle (MainPage) the middle (flex: 1) absorbs the
189
+ // remaining space, so leading & actions sit at the edges naturally. In all
190
+ // other cases we pin leading & actions to the outer edges with
191
+ // `space-between`; the SubPage middle floats above, centered.
167
192
  const wrapperStyle: ViewStyle = {
168
193
  ...containerStyle,
169
- justifyContent: processedMiddle ? 'flex-start' : 'space-between',
194
+ justifyContent: hasInFlowMiddle ? 'flex-start' : 'space-between',
195
+ }
196
+
197
+ // Absolutely-centered middle box for SubPage, mirroring the Figma geometry.
198
+ // `left/top: 50%` + a negative translate keeps it centered regardless of the
199
+ // bar width, while the fixed width clips overly-wide content (overflow:
200
+ // hidden) instead of letting it bleed under the leading/actions slots.
201
+ const subPageMiddleStyle: ViewStyle = {
202
+ position: 'absolute',
203
+ top: '50%',
204
+ left: '50%',
205
+ width: middleSlotWidth,
206
+ height: SUBPAGE_MIDDLE_HEIGHT,
207
+ transform: [
208
+ { translateX: -middleSlotWidth / 2 },
209
+ { translateY: -SUBPAGE_MIDDLE_HEIGHT / 2 },
210
+ ],
211
+ flexDirection: 'row',
212
+ alignItems: 'center',
213
+ justifyContent: 'center',
214
+ paddingHorizontal: SUBPAGE_MIDDLE_PADDING_HORIZONTAL,
215
+ overflow: 'hidden',
170
216
  }
171
217
 
172
218
  return (
@@ -183,14 +229,12 @@ export default function AppBar({
183
229
  </View>
184
230
 
185
231
  {/*
186
- * Middle Section — rendered as an in-flow flex item (`flex: 1`) so it
187
- * occupies the space between leading and actions but never overflows
188
- * past them. This fixes wide children (e.g. <LinearProgress /> with
189
- * width: '100%') stretching edge-to-edge under the leading/actions.
190
- * `minWidth: 0` is required so the flex item can shrink below its
191
- * content's intrinsic width on platforms that respect it (web).
232
+ * MainPage in-flow middle occupies the space between leading and
233
+ * actions (`flex: 1`) without overflowing. `minWidth: 0` lets the flex
234
+ * item shrink below its content's intrinsic width on platforms that
235
+ * respect it (web).
192
236
  */}
193
- {processedMiddle && (
237
+ {hasInFlowMiddle && (
194
238
  <View
195
239
  style={{
196
240
  flex: 1,
@@ -209,6 +253,29 @@ export default function AppBar({
209
253
  <View style={actionsStyle}>
210
254
  {processedActions}
211
255
  </View>
256
+
257
+ {/*
258
+ * SubPage middle — absolutely centered "slot wrap". The inner wrapper is
259
+ * a responsive `flex: 1` item (matching Figma's `flex-[1_0_0] min-w-px`)
260
+ * so its content fills / shrinks within the fixed-width box.
261
+ */}
262
+ {isSub && processedMiddle && (
263
+ <View style={subPageMiddleStyle} pointerEvents="box-none">
264
+ <View
265
+ style={{
266
+ flex: 1,
267
+ minWidth: 1,
268
+ height: '100%',
269
+ flexDirection: 'row',
270
+ alignItems: 'center',
271
+ justifyContent: 'center',
272
+ }}
273
+ pointerEvents="box-none"
274
+ >
275
+ {processedMiddle}
276
+ </View>
277
+ </View>
278
+ )}
212
279
  </View>
213
280
  )
214
281
  }
@@ -37,6 +37,24 @@ export type AttachedProps = Omit<ViewProps, 'children'> & {
37
37
  * `modes` are cascaded into it as well.
38
38
  */
39
39
  badge?: React.ReactNode
40
+ /**
41
+ * Enforces a fixed square size (in px) on the `badge` slot, regardless of
42
+ * what node is passed. The badge is wrapped in a box of
43
+ * `badgeSize × badgeSize` with `overflow: 'hidden'`, and the badge content is
44
+ * stretched to fill it. Use this to guarantee the design-token size even when
45
+ * a consumer drops in an arbitrary node (e.g. an `Image`) whose intrinsic
46
+ * size/aspect-ratio would otherwise win.
47
+ *
48
+ * When omitted, the badge keeps its own intrinsic size (legacy behavior).
49
+ */
50
+ badgeSize?: number
51
+ /**
52
+ * Corner radius used to clip the `badge` box. Only applies when `badgeSize`
53
+ * is set. Anything that overflows the rounded box (e.g. a non-square image)
54
+ * is clipped.
55
+ * @default badgeSize / 2 (a full circle)
56
+ */
57
+ badgeRadius?: number
40
58
  /**
41
59
  * Anchor point for the `badge` relative to the main content.
42
60
  * @default 'bottom-right'
@@ -89,9 +107,28 @@ function resolveAnchorFractions(position: AttachedPosition): { fx: number; fy: n
89
107
  * </Attached>
90
108
  * ```
91
109
  */
110
+ /**
111
+ * Stretches the immediate badge child/children to fill the enforced badge box.
112
+ * Merges `{ width: '100%', height: '100%' }` into each top-level element's
113
+ * `style` so an arbitrary node (e.g. an `Image` with its own width/aspectRatio)
114
+ * fills the fixed `badgeSize` box instead of laying out at its intrinsic size.
115
+ * The wrapping box's `overflow: 'hidden'` clips anything that still overflows.
116
+ */
117
+ function forceBadgeFill(children: React.ReactNode): React.ReactNode {
118
+ return React.Children.map(children, (child) => {
119
+ if (!React.isValidElement(child)) return child
120
+ const childStyle = (child.props as any)?.style
121
+ return React.cloneElement(child as React.ReactElement<any>, {
122
+ style: [FILL_STYLE, childStyle],
123
+ })
124
+ })
125
+ }
126
+
92
127
  function Attached({
93
128
  children,
94
129
  badge,
130
+ badgeSize,
131
+ badgeRadius,
95
132
  position = 'bottom-right',
96
133
  circular = true,
97
134
  modes: propModes = EMPTY_MODES,
@@ -108,7 +145,7 @@ function Attached({
108
145
  )
109
146
 
110
147
  const [mainSize, setMainSize] = useState<Size>(ZERO_SIZE)
111
- const [badgeSize, setBadgeSize] = useState<Size>(ZERO_SIZE)
148
+ const [measuredBadgeSize, setMeasuredBadgeSize] = useState<Size>(ZERO_SIZE)
112
149
 
113
150
  const onMainLayout = useCallback((e: LayoutChangeEvent) => {
114
151
  const { width, height } = e.nativeEvent.layout
@@ -117,7 +154,7 @@ function Attached({
117
154
 
118
155
  const onBadgeLayout = useCallback((e: LayoutChangeEvent) => {
119
156
  const { width, height } = e.nativeEvent.layout
120
- setBadgeSize((prev) => (prev.width === width && prev.height === height ? prev : { width, height }))
157
+ setMeasuredBadgeSize((prev) => (prev.width === width && prev.height === height ? prev : { width, height }))
121
158
  }, [])
122
159
 
123
160
  const mainChildren = useMemo(
@@ -129,9 +166,21 @@ function Attached({
129
166
  [badge, modes]
130
167
  )
131
168
 
169
+ // When a fixed size is requested, the badge is wrapped in a clipped box and
170
+ // its content is force-stretched to fill it (see `forceBadgeFill`).
171
+ const badgeBoxStyle = useMemo<ViewStyle | null>(() => {
172
+ if (badgeSize == null) return null
173
+ return {
174
+ width: badgeSize,
175
+ height: badgeSize,
176
+ borderRadius: badgeRadius ?? badgeSize / 2,
177
+ overflow: 'hidden',
178
+ }
179
+ }, [badgeSize, badgeRadius])
180
+
132
181
  const badgePlacement = useMemo<ViewStyle>(() => {
133
182
  const { fx, fy } = resolveAnchorFractions(position)
134
- const measured = mainSize.width > 0 && badgeSize.width > 0
183
+ const measured = mainSize.width > 0 && measuredBadgeSize.width > 0
135
184
 
136
185
  let anchorX: number
137
186
  let anchorY: number
@@ -153,19 +202,23 @@ function Attached({
153
202
 
154
203
  return {
155
204
  position: 'absolute',
156
- left: anchorX - badgeSize.width / 2,
157
- top: anchorY - badgeSize.height / 2,
205
+ left: anchorX - measuredBadgeSize.width / 2,
206
+ top: anchorY - measuredBadgeSize.height / 2,
158
207
  // Hide until both elements are measured to avoid a one-frame flash at (0,0).
159
208
  opacity: measured ? 1 : 0,
160
209
  }
161
- }, [position, circular, mainSize, badgeSize])
210
+ }, [position, circular, mainSize, measuredBadgeSize])
162
211
 
163
212
  return (
164
213
  <View style={[styles.container, style]} {...rest}>
165
214
  <View onLayout={onMainLayout}>{mainChildren}</View>
166
215
  {badgeChildren != null && (
167
216
  <View style={badgePlacement} onLayout={onBadgeLayout} pointerEvents="box-none">
168
- {badgeChildren}
217
+ {badgeBoxStyle != null ? (
218
+ <View style={badgeBoxStyle}>{forceBadgeFill(badgeChildren)}</View>
219
+ ) : (
220
+ badgeChildren
221
+ )}
169
222
  </View>
170
223
  )}
171
224
  </View>
@@ -178,4 +231,7 @@ const styles = {
178
231
  container: { position: 'relative', alignSelf: 'flex-start' } as ViewStyle,
179
232
  }
180
233
 
234
+ /** Fill style merged into badge content when `badgeSize` enforces a fixed box. */
235
+ const FILL_STYLE = { width: '100%', height: '100%' } as ViewStyle
236
+
181
237
  export default React.memo(Attached)
@@ -55,12 +55,21 @@ function useFocusVisible() {
55
55
  const MIN_TOUCH_TARGET = 44
56
56
 
57
57
  const touchTargetStyle: ViewStyle = {
58
- minWidth: MIN_TOUCH_TARGET,
59
- minHeight: MIN_TOUCH_TARGET,
60
58
  alignItems: 'center',
61
59
  justifyContent: 'center',
62
60
  }
63
61
 
62
+ /**
63
+ * Expands the tappable region to the 44pt minimum without changing layout.
64
+ * `hitSlop` extends the press-responder bounds beyond the visual box on both
65
+ * native and web (react-native-web ≥ 0.19), so the Pressable keeps its natural
66
+ * checkbox-sized footprint and sibling alignment stays intact.
67
+ */
68
+ function invisibleTouchHitSlop(checkboxSize: number) {
69
+ const slop = Math.max(0, Math.ceil((MIN_TOUCH_TARGET - checkboxSize) / 2))
70
+ return { top: slop, bottom: slop, left: slop, right: slop }
71
+ }
72
+
64
73
  export interface CheckboxProps {
65
74
  /** Whether the checkbox is checked (controlled) */
66
75
  checked?: boolean
@@ -216,9 +225,12 @@ function Checkbox({
216
225
  ? (disabledActiveMark as string)
217
226
  : (selectedMarkColor as string)
218
227
 
228
+ const hitSlop = invisibleTouchHitSlop(size as number)
229
+
219
230
  return (
220
231
  <Pressable
221
232
  style={[touchTargetStyle, style]}
233
+ hitSlop={hitSlop}
222
234
  onPress={handlePress}
223
235
  disabled={disabled}
224
236
  onHoverIn={() => setIsHovered(true)}