jfs-components 0.0.86 → 0.0.95
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/CHANGELOG.md +8 -0
- package/lib/commonjs/assets.d.js +1 -0
- package/lib/commonjs/components/FullscreenModal/FullscreenModal.js +97 -50
- package/lib/commonjs/components/Icon/Icon.js +112 -0
- package/lib/commonjs/components/index.js +7 -0
- package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
- package/lib/commonjs/icons/registry.js +1 -1
- package/lib/module/assets.d.js +1 -0
- package/lib/module/components/FullscreenModal/FullscreenModal.js +99 -52
- package/lib/module/components/Icon/Icon.js +106 -0
- package/lib/module/components/index.js +1 -0
- package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
- package/lib/module/icons/registry.js +1 -1
- package/lib/typescript/src/components/FullscreenModal/FullscreenModal.d.ts +35 -21
- package/lib/typescript/src/components/Icon/Icon.d.ts +75 -0
- package/lib/typescript/src/components/index.d.ts +1 -0
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/package.json +1 -1
- package/src/assets.d.ts +24 -0
- package/src/components/FullscreenModal/FullscreenModal.tsx +124 -61
- package/src/components/Icon/Icon.tsx +167 -0
- package/src/components/index.ts +1 -0
- package/src/design-tokens/Coin Variables-variables-full.json +1 -1
- package/src/icons/registry.ts +1 -1
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import React, { useMemo } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
type AccessibilityProps,
|
|
5
|
+
type StyleProp,
|
|
6
|
+
type ViewStyle,
|
|
7
|
+
} from 'react-native'
|
|
8
|
+
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
9
|
+
import { useTokens } from '../../design-tokens/JFSThemeProvider'
|
|
10
|
+
import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
|
|
11
|
+
import BaseIcon from '../../icons/Icon'
|
|
12
|
+
import type { UnifiedSource } from '../../utils/MediaSource'
|
|
13
|
+
|
|
14
|
+
type IconProps = AccessibilityProps & {
|
|
15
|
+
/**
|
|
16
|
+
* Built-in icon name from the registry, in the `ic_something` format
|
|
17
|
+
* (e.g. `'ic_card'`, `'ic_scan_qr_code'`). When omitted and no `source` or
|
|
18
|
+
* `children` slot is supplied, defaults to `'ic_card'` to match the Figma
|
|
19
|
+
* design's default glyph.
|
|
20
|
+
*/
|
|
21
|
+
iconName?: string
|
|
22
|
+
/**
|
|
23
|
+
* Unified fallback source rendered when `iconName` is missing or not in the
|
|
24
|
+
* registry. Accepts a remote URI, an inline SVG XML string, a `require()`
|
|
25
|
+
* asset, an SVG React component, or an already-rendered element. The media
|
|
26
|
+
* is tinted with the mode-resolved icon color so it follows design tokens
|
|
27
|
+
* just like a built-in icon. See {@link UnifiedSource}.
|
|
28
|
+
*/
|
|
29
|
+
source?: UnifiedSource
|
|
30
|
+
/**
|
|
31
|
+
* Icon slot. Render any node here (another `Icon`, a custom SVG component,
|
|
32
|
+
* etc.) and it takes precedence over `iconName`/`source`. `modes` cascade
|
|
33
|
+
* into the slotted children automatically.
|
|
34
|
+
*/
|
|
35
|
+
children?: React.ReactNode
|
|
36
|
+
/**
|
|
37
|
+
* Override the mode-resolved icon color. When omitted the value comes from
|
|
38
|
+
* the `icon/color` design token.
|
|
39
|
+
*/
|
|
40
|
+
color?: string
|
|
41
|
+
/**
|
|
42
|
+
* Override the mode-resolved icon size (in px). When omitted the value comes
|
|
43
|
+
* from the `icon/size` design token.
|
|
44
|
+
*/
|
|
45
|
+
size?: number
|
|
46
|
+
modes?: Record<string, any>
|
|
47
|
+
style?: StyleProp<ViewStyle>
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface IconTokens {
|
|
51
|
+
containerStyle: ViewStyle
|
|
52
|
+
iconColor: string
|
|
53
|
+
iconSize: number
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function resolveIconTokens(modes: Record<string, any>): IconTokens {
|
|
57
|
+
const iconColor = (getVariableByName('icon/color', modes) || '#ad8444') as string
|
|
58
|
+
const iconSize = (getVariableByName('icon/size', modes) || 18) as number
|
|
59
|
+
const paddingLeft = (getVariableByName('icon/padding/left', modes) || 0) as number
|
|
60
|
+
const paddingTop = (getVariableByName('icon/padding/top', modes) || 0) as number
|
|
61
|
+
const paddingRight = (getVariableByName('icon/padding/right', modes) || 0) as number
|
|
62
|
+
const paddingBottom = (getVariableByName('icon/padding/bottom', modes) || 0) as number
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
containerStyle: {
|
|
66
|
+
flexDirection: 'column',
|
|
67
|
+
alignItems: 'center',
|
|
68
|
+
justifyContent: 'center',
|
|
69
|
+
overflow: 'hidden',
|
|
70
|
+
paddingLeft,
|
|
71
|
+
paddingTop,
|
|
72
|
+
paddingRight,
|
|
73
|
+
paddingBottom,
|
|
74
|
+
},
|
|
75
|
+
iconColor,
|
|
76
|
+
iconSize,
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Icon component — a design-token-driven wrapper around a single glyph.
|
|
82
|
+
*
|
|
83
|
+
* It mirrors the Figma "Icon" component: a padded, centered container whose
|
|
84
|
+
* color and size are resolved from the `icon/*` design tokens via `modes`.
|
|
85
|
+
* The glyph itself can be supplied three ways, in order of precedence:
|
|
86
|
+
*
|
|
87
|
+
* 1. `children` — a real slot for any node (custom SVG component, nested
|
|
88
|
+
* `Icon`, etc.). `modes` cascade into the slot automatically.
|
|
89
|
+
* 2. `iconName` — a registry icon in the `ic_something` format.
|
|
90
|
+
* 3. `source` — a {@link UnifiedSource} fallback (remote URI, inline SVG XML,
|
|
91
|
+
* `require()` asset, SVG component, or React element), tinted with the
|
|
92
|
+
* mode-resolved icon color.
|
|
93
|
+
*
|
|
94
|
+
* `color` and `size` props let consumers override the token values per
|
|
95
|
+
* instance without touching `modes`.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```tsx
|
|
99
|
+
* // Built-in registry icon (default path).
|
|
100
|
+
* <Icon iconName="ic_card" modes={{ 'Color Mode': 'Light' }} />
|
|
101
|
+
*
|
|
102
|
+
* // Per-instance overrides.
|
|
103
|
+
* <Icon iconName="ic_ccv" color="#5c00b5" size={24} />
|
|
104
|
+
*
|
|
105
|
+
* // Fallback to an external source when the name isn't in the registry.
|
|
106
|
+
* <Icon source="https://cdn.example.com/glyph.svg" />
|
|
107
|
+
*
|
|
108
|
+
* // Slot: render any node as the icon.
|
|
109
|
+
* <Icon><BrandLogo /></Icon>
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
function Icon({
|
|
113
|
+
iconName,
|
|
114
|
+
source,
|
|
115
|
+
children,
|
|
116
|
+
color,
|
|
117
|
+
size,
|
|
118
|
+
modes: propModes = EMPTY_MODES,
|
|
119
|
+
style: styleProp,
|
|
120
|
+
...rest
|
|
121
|
+
}: IconProps) {
|
|
122
|
+
const { modes: globalModes } = useTokens()
|
|
123
|
+
|
|
124
|
+
const modes = useMemo(
|
|
125
|
+
() => (globalModes === EMPTY_MODES && propModes === EMPTY_MODES
|
|
126
|
+
? EMPTY_MODES
|
|
127
|
+
: { ...globalModes, ...propModes }),
|
|
128
|
+
[globalModes, propModes]
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
const tokens = useMemo(() => resolveIconTokens(modes), [modes])
|
|
132
|
+
|
|
133
|
+
const composedStyle = useMemo<StyleProp<ViewStyle>>(
|
|
134
|
+
() => (styleProp ? [tokens.containerStyle, styleProp] : tokens.containerStyle),
|
|
135
|
+
[tokens.containerStyle, styleProp]
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
const hasSlot = React.Children.count(children) > 0
|
|
139
|
+
|
|
140
|
+
// Only fall back to the default glyph when nothing at all is provided so an
|
|
141
|
+
// explicit `source` (without an `iconName`) isn't shadowed by `ic_card`.
|
|
142
|
+
const resolvedName =
|
|
143
|
+
iconName ?? (source === undefined ? 'ic_card' : undefined)
|
|
144
|
+
|
|
145
|
+
const iconColor = color ?? tokens.iconColor
|
|
146
|
+
const iconSize = size ?? tokens.iconSize
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<View style={composedStyle} {...rest}>
|
|
150
|
+
{hasSlot ? (
|
|
151
|
+
cloneChildrenWithModes(children, modes)
|
|
152
|
+
) : (
|
|
153
|
+
<BaseIcon
|
|
154
|
+
name={resolvedName}
|
|
155
|
+
{...(source !== undefined ? { source } : {})}
|
|
156
|
+
size={iconSize}
|
|
157
|
+
color={iconColor}
|
|
158
|
+
accessibilityElementsHidden={true}
|
|
159
|
+
importantForAccessibility="no"
|
|
160
|
+
/>
|
|
161
|
+
)}
|
|
162
|
+
</View>
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export default React.memo(Icon)
|
|
167
|
+
export type { IconProps }
|
package/src/components/index.ts
CHANGED
|
@@ -43,6 +43,7 @@ export { default as MonthlyStatusGrid, CalendarGlyph, type MonthlyStatusGridProp
|
|
|
43
43
|
export { default as Gauge, type GaugeProps } from './Gauge/Gauge';
|
|
44
44
|
export { default as HoldingsCard, type HoldingsCardProps } from './HoldingsCard/HoldingsCard';
|
|
45
45
|
export { default as HStack, type HStackProps } from './HStack/HStack';
|
|
46
|
+
export { default as Icon, type IconProps } from './Icon/Icon';
|
|
46
47
|
export { default as IconButton } from './IconButton/IconButton';
|
|
47
48
|
export { default as IconCapsule } from './IconCapsule/IconCapsule';
|
|
48
49
|
export { default as Image, type ImageProps } from './Image/Image';
|