jfs-components 0.0.64 → 0.0.65
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/components/Carousel/Carousel.js +12 -9
- package/lib/commonjs/components/Drawer/Drawer.js +9 -3
- package/lib/commonjs/components/IconButton/IconButton.js +42 -6
- package/lib/commonjs/components/IconCapsule/IconCapsule.js +5 -0
- package/lib/commonjs/components/Popup/Popup.js +2 -2
- package/lib/commonjs/components/UpiHandle/UpiHandle.js +19 -7
- package/lib/commonjs/icons/Icon.js +72 -75
- package/lib/commonjs/icons/registry.js +1 -1
- package/lib/commonjs/utils/MediaSource.js +181 -0
- package/lib/commonjs/utils/index.js +9 -1
- package/lib/module/components/Carousel/Carousel.js +12 -9
- package/lib/module/components/Drawer/Drawer.js +9 -3
- package/lib/module/components/IconButton/IconButton.js +42 -6
- package/lib/module/components/IconCapsule/IconCapsule.js +5 -0
- package/lib/module/components/Popup/Popup.js +2 -2
- package/lib/module/components/UpiHandle/UpiHandle.js +20 -8
- package/lib/module/icons/Icon.js +72 -75
- package/lib/module/icons/registry.js +1 -1
- package/lib/module/utils/MediaSource.js +176 -0
- package/lib/module/utils/index.js +2 -1
- package/lib/typescript/src/components/Drawer/Drawer.d.ts +6 -1
- package/lib/typescript/src/components/IconButton/IconButton.d.ts +25 -14
- package/lib/typescript/src/components/IconCapsule/IconCapsule.d.ts +12 -1
- package/lib/typescript/src/components/UpiHandle/UpiHandle.d.ts +17 -3
- package/lib/typescript/src/icons/Icon.d.ts +35 -16
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/lib/typescript/src/utils/MediaSource.d.ts +63 -0
- package/lib/typescript/src/utils/index.d.ts +2 -0
- package/package.json +1 -1
- package/src/components/Carousel/Carousel.tsx +16 -17
- package/src/components/Drawer/Drawer.tsx +13 -2
- package/src/components/IconButton/IconButton.tsx +70 -11
- package/src/components/IconCapsule/IconCapsule.tsx +13 -0
- package/src/components/Popup/Popup.tsx +2 -2
- package/src/components/UpiHandle/UpiHandle.tsx +37 -11
- package/src/icons/Icon.tsx +91 -76
- package/src/icons/registry.ts +1 -1
- package/src/utils/MediaSource.tsx +220 -0
- package/src/utils/index.ts +2 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import {
|
|
3
|
+
Image,
|
|
4
|
+
type ImageStyle,
|
|
5
|
+
type ImageURISource,
|
|
6
|
+
type StyleProp,
|
|
7
|
+
} from 'react-native'
|
|
8
|
+
import { SvgUri, SvgXml } from 'react-native-svg'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A unified, "do-the-right-thing" image source accepted by `MediaSource` and
|
|
12
|
+
* by the `source` prop on `Icon`, `IconCapsule` and `UpiHandle`.
|
|
13
|
+
*
|
|
14
|
+
* Accepts any of:
|
|
15
|
+
* - `string` — a URI (raster or `.svg`) **or** an inline SVG XML document
|
|
16
|
+
* (`'<svg …>…</svg>'`).
|
|
17
|
+
* - `number` — a Metro asset id from `require('./foo.png')`.
|
|
18
|
+
* - `{ uri, … }` — the standard RN `ImageURISource` object (works for both
|
|
19
|
+
* raster and `.svg` URIs).
|
|
20
|
+
* - `React.ComponentType` — an SVG React component (e.g. produced by
|
|
21
|
+
* `react-native-svg-transformer`, by `@svgr/*`,
|
|
22
|
+
* or hand-written). It is rendered with
|
|
23
|
+
* `{ width, height, color, fill }` so it can be
|
|
24
|
+
* tinted just like a built-in icon.
|
|
25
|
+
* - `React.ReactElement` — an already-rendered node, passed through verbatim.
|
|
26
|
+
*
|
|
27
|
+
* The helper sniffs the input shape (no extension hint required from the
|
|
28
|
+
* caller) and picks the correct renderer for the platform.
|
|
29
|
+
*/
|
|
30
|
+
export type UnifiedSource =
|
|
31
|
+
| string
|
|
32
|
+
| number
|
|
33
|
+
| ImageURISource
|
|
34
|
+
| React.ComponentType<{
|
|
35
|
+
width?: number
|
|
36
|
+
height?: number
|
|
37
|
+
color?: string
|
|
38
|
+
fill?: string
|
|
39
|
+
}>
|
|
40
|
+
| React.ReactElement
|
|
41
|
+
|
|
42
|
+
export type MediaSourceProps = {
|
|
43
|
+
/** Smart source. See {@link UnifiedSource}. */
|
|
44
|
+
source: UnifiedSource
|
|
45
|
+
/** Convenience shorthand that sets both width and height. */
|
|
46
|
+
size?: number
|
|
47
|
+
width?: number
|
|
48
|
+
height?: number
|
|
49
|
+
/**
|
|
50
|
+
* Optional tint applied to the rendered media.
|
|
51
|
+
* - Raster `<Image>` → mapped to `style.tintColor` (works on iOS, Android,
|
|
52
|
+
* and react-native-web).
|
|
53
|
+
* - SVG (XML / URI / component) → mapped to the `color` / `fill` props.
|
|
54
|
+
* For an SVG to actually re-color, its source must use `currentColor`
|
|
55
|
+
* (or have no hardcoded fill). SVGs with baked-in `fill="#xxx"` cannot
|
|
56
|
+
* be re-tinted without parsing — this is a `react-native-svg`
|
|
57
|
+
* limitation, not something we can paper over here.
|
|
58
|
+
*/
|
|
59
|
+
tintColor?: string
|
|
60
|
+
/** Extra style merged into the underlying `<Image>` (raster path only). */
|
|
61
|
+
style?: StyleProp<ImageStyle>
|
|
62
|
+
resizeMode?: 'cover' | 'contain' | 'stretch' | 'center' | 'repeat'
|
|
63
|
+
accessibilityElementsHidden?: boolean
|
|
64
|
+
importantForAccessibility?: 'auto' | 'yes' | 'no' | 'no-hide-descendants'
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const SVG_XML_RE = /<svg[\s>]/i
|
|
68
|
+
const SVG_URI_RE = /\.svg(\?|#|$)/i
|
|
69
|
+
|
|
70
|
+
function isSvgXml(s: string): boolean {
|
|
71
|
+
return /^\s*</.test(s) && SVG_XML_RE.test(s)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isSvgUri(s: string): boolean {
|
|
75
|
+
return SVG_URI_RE.test(s)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function isUriObject(
|
|
79
|
+
v: unknown
|
|
80
|
+
): v is ImageURISource & { uri: string } {
|
|
81
|
+
return (
|
|
82
|
+
typeof v === 'object' &&
|
|
83
|
+
v !== null &&
|
|
84
|
+
'uri' in v &&
|
|
85
|
+
typeof (v as { uri: unknown }).uri === 'string'
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Smart renderer that picks the right primitive for the source shape. See
|
|
91
|
+
* {@link UnifiedSource}.
|
|
92
|
+
*
|
|
93
|
+
* Designed to be used internally by `Icon`, `IconCapsule`, and `UpiHandle`,
|
|
94
|
+
* but also exported for ad-hoc consumer use.
|
|
95
|
+
*/
|
|
96
|
+
function MediaSource(props: MediaSourceProps) {
|
|
97
|
+
const {
|
|
98
|
+
source,
|
|
99
|
+
size,
|
|
100
|
+
width,
|
|
101
|
+
height,
|
|
102
|
+
tintColor,
|
|
103
|
+
style,
|
|
104
|
+
resizeMode = 'cover',
|
|
105
|
+
accessibilityElementsHidden,
|
|
106
|
+
importantForAccessibility,
|
|
107
|
+
} = props
|
|
108
|
+
|
|
109
|
+
const w = width ?? size
|
|
110
|
+
const h = height ?? size
|
|
111
|
+
|
|
112
|
+
// Pre-rendered element — pass through.
|
|
113
|
+
if (React.isValidElement(source)) {
|
|
114
|
+
return source
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// SVG / icon component.
|
|
118
|
+
if (typeof source === 'function') {
|
|
119
|
+
const Comp = source as React.ComponentType<{
|
|
120
|
+
width?: number
|
|
121
|
+
height?: number
|
|
122
|
+
color?: string
|
|
123
|
+
fill?: string
|
|
124
|
+
}>
|
|
125
|
+
return (
|
|
126
|
+
<Comp
|
|
127
|
+
{...(w !== undefined ? { width: w } : {})}
|
|
128
|
+
{...(h !== undefined ? { height: h } : {})}
|
|
129
|
+
{...(tintColor !== undefined ? { color: tintColor, fill: tintColor } : {})}
|
|
130
|
+
/>
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const sizeStyle: ImageStyle | null =
|
|
135
|
+
w !== undefined || h !== undefined ? { width: w, height: h } : null
|
|
136
|
+
const tintStyle: ImageStyle | null = tintColor ? { tintColor } : null
|
|
137
|
+
const composedStyle: StyleProp<ImageStyle> = [sizeStyle, tintStyle, style]
|
|
138
|
+
|
|
139
|
+
if (typeof source === 'string') {
|
|
140
|
+
if (isSvgXml(source)) {
|
|
141
|
+
return (
|
|
142
|
+
<SvgXml
|
|
143
|
+
xml={source}
|
|
144
|
+
{...(w !== undefined ? { width: w } : {})}
|
|
145
|
+
{...(h !== undefined ? { height: h } : {})}
|
|
146
|
+
{...(tintColor !== undefined ? { color: tintColor } : {})}
|
|
147
|
+
/>
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
if (isSvgUri(source)) {
|
|
151
|
+
return (
|
|
152
|
+
<SvgUri
|
|
153
|
+
uri={source}
|
|
154
|
+
{...(w !== undefined ? { width: w } : {})}
|
|
155
|
+
{...(h !== undefined ? { height: h } : {})}
|
|
156
|
+
{...(tintColor !== undefined ? { color: tintColor } : {})}
|
|
157
|
+
/>
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
return (
|
|
161
|
+
<Image
|
|
162
|
+
source={{ uri: source }}
|
|
163
|
+
style={composedStyle}
|
|
164
|
+
resizeMode={resizeMode}
|
|
165
|
+
{...(accessibilityElementsHidden !== undefined
|
|
166
|
+
? { accessibilityElementsHidden }
|
|
167
|
+
: {})}
|
|
168
|
+
{...(importantForAccessibility !== undefined
|
|
169
|
+
? { importantForAccessibility }
|
|
170
|
+
: {})}
|
|
171
|
+
/>
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (isUriObject(source)) {
|
|
176
|
+
if (isSvgUri(source.uri)) {
|
|
177
|
+
return (
|
|
178
|
+
<SvgUri
|
|
179
|
+
uri={source.uri}
|
|
180
|
+
{...(w !== undefined ? { width: w } : {})}
|
|
181
|
+
{...(h !== undefined ? { height: h } : {})}
|
|
182
|
+
{...(tintColor !== undefined ? { color: tintColor } : {})}
|
|
183
|
+
/>
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
return (
|
|
187
|
+
<Image
|
|
188
|
+
source={source}
|
|
189
|
+
style={composedStyle}
|
|
190
|
+
resizeMode={resizeMode}
|
|
191
|
+
{...(accessibilityElementsHidden !== undefined
|
|
192
|
+
? { accessibilityElementsHidden }
|
|
193
|
+
: {})}
|
|
194
|
+
{...(importantForAccessibility !== undefined
|
|
195
|
+
? { importantForAccessibility }
|
|
196
|
+
: {})}
|
|
197
|
+
/>
|
|
198
|
+
)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (typeof source === 'number') {
|
|
202
|
+
return (
|
|
203
|
+
<Image
|
|
204
|
+
source={source}
|
|
205
|
+
style={composedStyle}
|
|
206
|
+
resizeMode={resizeMode}
|
|
207
|
+
{...(accessibilityElementsHidden !== undefined
|
|
208
|
+
? { accessibilityElementsHidden }
|
|
209
|
+
: {})}
|
|
210
|
+
{...(importantForAccessibility !== undefined
|
|
211
|
+
? { importantForAccessibility }
|
|
212
|
+
: {})}
|
|
213
|
+
/>
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return null
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export default React.memo(MediaSource)
|
package/src/utils/index.ts
CHANGED