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.
- package/lib/commonjs/components/AppBar/AppBar.js +56 -6
- package/lib/commonjs/components/Attached/Attached.js +46 -7
- package/lib/commonjs/components/Checkbox/Checkbox.js +18 -2
- package/lib/commonjs/components/Drawer/Drawer.js +6 -1
- package/lib/commonjs/components/DropdownInput/DropdownInput.js +30 -6
- package/lib/commonjs/components/ExpandableCheckbox/ExpandableCheckbox.js +17 -11
- package/lib/commonjs/components/FormField/FormField.js +1 -14
- package/lib/commonjs/components/FullscreenModal/FullscreenModal.js +5 -1
- package/lib/commonjs/components/ListItem/ListItem.js +6 -11
- package/lib/commonjs/components/MessageField/MessageField.js +1 -13
- package/lib/commonjs/components/PaymentFeedback/PaymentFeedback.js +12 -9
- package/lib/commonjs/components/PlanComparisonCard/PlanComparisonCard.js +69 -160
- package/lib/commonjs/components/Spinner/Spinner.js +217 -0
- package/lib/commonjs/components/TextInput/TextInput.js +33 -18
- package/lib/commonjs/components/index.js +7 -0
- package/lib/commonjs/icons/components/IconArrowdown.js +19 -0
- package/lib/commonjs/icons/components/IconArrowup.js +19 -0
- package/lib/commonjs/icons/components/IconChevrondowncircle.js +19 -0
- package/lib/commonjs/icons/components/IconChevronleftcircle.js +19 -0
- package/lib/commonjs/icons/components/IconChevronrightcircle.js +19 -0
- package/lib/commonjs/icons/components/IconChevronupcircle.js +19 -0
- package/lib/commonjs/icons/components/IconOsnavback.js +19 -0
- package/lib/commonjs/icons/components/IconOsnavcenter.js +19 -0
- package/lib/commonjs/icons/components/IconOsnavhome.js +19 -0
- package/lib/commonjs/icons/components/IconOsnavtask.js +19 -0
- package/lib/commonjs/icons/components/IconSignin.js +19 -0
- package/lib/commonjs/icons/components/IconSignout.js +19 -0
- package/lib/commonjs/icons/components/index.js +132 -0
- package/lib/commonjs/icons/registry.js +2 -2
- package/lib/module/components/AppBar/AppBar.js +56 -6
- package/lib/module/components/Attached/Attached.js +46 -7
- package/lib/module/components/Checkbox/Checkbox.js +18 -2
- package/lib/module/components/Drawer/Drawer.js +6 -1
- package/lib/module/components/DropdownInput/DropdownInput.js +30 -6
- package/lib/module/components/ExpandableCheckbox/ExpandableCheckbox.js +17 -11
- package/lib/module/components/FormField/FormField.js +3 -16
- package/lib/module/components/FullscreenModal/FullscreenModal.js +5 -1
- package/lib/module/components/ListItem/ListItem.js +6 -11
- package/lib/module/components/MessageField/MessageField.js +3 -15
- package/lib/module/components/PaymentFeedback/PaymentFeedback.js +13 -9
- package/lib/module/components/PlanComparisonCard/PlanComparisonCard.js +72 -160
- package/lib/module/components/Spinner/Spinner.js +212 -0
- package/lib/module/components/TextInput/TextInput.js +34 -19
- package/lib/module/components/index.js +1 -0
- package/lib/module/icons/components/IconArrowdown.js +12 -0
- package/lib/module/icons/components/IconArrowup.js +12 -0
- package/lib/module/icons/components/IconChevrondowncircle.js +12 -0
- package/lib/module/icons/components/IconChevronleftcircle.js +12 -0
- package/lib/module/icons/components/IconChevronrightcircle.js +12 -0
- package/lib/module/icons/components/IconChevronupcircle.js +12 -0
- package/lib/module/icons/components/IconOsnavback.js +12 -0
- package/lib/module/icons/components/IconOsnavcenter.js +12 -0
- package/lib/module/icons/components/IconOsnavhome.js +12 -0
- package/lib/module/icons/components/IconOsnavtask.js +12 -0
- package/lib/module/icons/components/IconSignin.js +12 -0
- package/lib/module/icons/components/IconSignout.js +12 -0
- package/lib/module/icons/components/index.js +12 -0
- package/lib/module/icons/registry.js +2 -2
- package/lib/typescript/src/components/AppBar/AppBar.d.ts +12 -1
- package/lib/typescript/src/components/Attached/Attached.d.ts +19 -16
- package/lib/typescript/src/components/DropdownInput/DropdownInput.d.ts +3 -2
- package/lib/typescript/src/components/ListItem/ListItem.d.ts +3 -3
- package/lib/typescript/src/components/PaymentFeedback/PaymentFeedback.d.ts +5 -1
- package/lib/typescript/src/components/PlanComparisonCard/PlanComparisonCard.d.ts +10 -8
- package/lib/typescript/src/components/Spinner/Spinner.d.ts +45 -0
- package/lib/typescript/src/components/index.d.ts +1 -0
- package/lib/typescript/src/icons/components/IconArrowdown.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconArrowup.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconChevrondowncircle.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconChevronleftcircle.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconChevronrightcircle.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconChevronupcircle.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconOsnavback.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconOsnavcenter.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconOsnavhome.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconOsnavtask.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconSignin.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconSignout.d.ts +3 -0
- package/lib/typescript/src/icons/components/index.d.ts +12 -0
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/package.json +3 -2
- package/src/components/AppBar/AppBar.tsx +79 -12
- package/src/components/Attached/Attached.tsx +63 -7
- package/src/components/Checkbox/Checkbox.tsx +14 -2
- package/src/components/Drawer/Drawer.tsx +4 -0
- package/src/components/DropdownInput/DropdownInput.tsx +54 -20
- package/src/components/ExpandableCheckbox/ExpandableCheckbox.tsx +13 -9
- package/src/components/FormField/FormField.tsx +3 -19
- package/src/components/FullscreenModal/FullscreenModal.tsx +3 -0
- package/src/components/ListItem/ListItem.tsx +14 -16
- package/src/components/MessageField/MessageField.tsx +3 -18
- package/src/components/PaymentFeedback/PaymentFeedback.tsx +15 -8
- package/src/components/PlanComparisonCard/PlanComparisonCard.tsx +82 -192
- package/src/components/Spinner/Spinner.tsx +273 -0
- package/src/components/TextInput/TextInput.tsx +37 -19
- package/src/components/index.ts +1 -0
- package/src/icons/components/IconArrowdown.tsx +11 -0
- package/src/icons/components/IconArrowup.tsx +11 -0
- package/src/icons/components/IconChevrondowncircle.tsx +11 -0
- package/src/icons/components/IconChevronleftcircle.tsx +11 -0
- package/src/icons/components/IconChevronrightcircle.tsx +11 -0
- package/src/icons/components/IconChevronupcircle.tsx +11 -0
- package/src/icons/components/IconOsnavback.tsx +11 -0
- package/src/icons/components/IconOsnavcenter.tsx +11 -0
- package/src/icons/components/IconOsnavhome.tsx +11 -0
- package/src/icons/components/IconOsnavtask.tsx +11 -0
- package/src/icons/components/IconSignin.tsx +11 -0
- package/src/icons/components/IconSignout.tsx +11 -0
- package/src/icons/components/index.ts +12 -0
- 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
|
|
77
|
-
*
|
|
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").
|
|
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.
|
|
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
|
-
/**
|
|
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
|
-
|
|
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';
|
|
@@ -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-
|
|
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.
|
|
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
|
-
//
|
|
164
|
-
//
|
|
165
|
-
//
|
|
166
|
-
|
|
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:
|
|
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
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
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
|
-
{
|
|
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 [
|
|
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
|
-
|
|
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 &&
|
|
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 -
|
|
157
|
-
top: anchorY -
|
|
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,
|
|
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
|
-
{
|
|
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)}
|