@duro-app/ui 0.34.7 → 0.34.9
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/dist/components/Badge/Badge.d.ts.map +1 -1
- package/dist/components/Badge/styles.css.d.ts +3 -0
- package/dist/components/Badge/styles.css.d.ts.map +1 -1
- package/dist/components/Button/Button.d.ts.map +1 -1
- package/dist/components/Button/styles.css.d.ts +3 -0
- package/dist/components/Button/styles.css.d.ts.map +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/styles.css.d.ts +28 -3
- package/dist/components/Checkbox/styles.css.d.ts.map +1 -1
- package/dist/components/InputGroup/InputGroup.d.ts.map +1 -1
- package/dist/components/InputGroup/styles.css.d.ts +3 -0
- package/dist/components/InputGroup/styles.css.d.ts.map +1 -1
- package/dist/components/Switch/Switch.d.ts.map +1 -1
- package/dist/components/Switch/styles.css.d.ts +3 -0
- package/dist/components/Switch/styles.css.d.ts.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.js +1292 -1273
- package/dist/index.js.map +1 -1
- package/dist/platform.d.ts +12 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.native.d.ts +2 -0
- package/dist/platform.native.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/components/Badge/Badge.tsx +6 -1
- package/src/components/Badge/styles.css.ts +5 -0
- package/src/components/Button/Button.tsx +2 -0
- package/src/components/Button/styles.css.ts +5 -0
- package/src/components/Checkbox/Checkbox.tsx +50 -0
- package/src/components/Checkbox/styles.css.ts +38 -4
- package/src/components/InputGroup/InputGroup.tsx +2 -0
- package/src/components/InputGroup/styles.css.ts +5 -0
- package/src/components/Switch/Switch.tsx +27 -17
- package/src/components/Switch/styles.css.ts +5 -0
- package/src/platform.native.ts +3 -0
- package/src/platform.ts +11 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform flag resolved by the bundler's platform extensions: web bundlers
|
|
3
|
+
* (Vite/Rollup) read THIS file (`isNative = false`); Metro reads
|
|
4
|
+
* `platform.native.ts` (`isNative = true`) on React Native / Expo.
|
|
5
|
+
*
|
|
6
|
+
* It lets shared components layer a native-only style override without
|
|
7
|
+
* importing `react-native` on web (the DS web build has no react-native).
|
|
8
|
+
* Typed `boolean` (not the `false` literal) so `isNative && styles.x` stays a
|
|
9
|
+
* `false | Style` union in style arrays rather than narrowing to `false`.
|
|
10
|
+
*/
|
|
11
|
+
export declare const isNative: boolean;
|
|
12
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ,EAAE,OAAe,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.native.d.ts","sourceRoot":"","sources":["../src/platform.native.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,QAAQ,EAAE,OAAc,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@duro-app/ui",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
}
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@duro-app/tokens": "^0.34.
|
|
57
|
+
"@duro-app/tokens": "^0.34.9"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@babel/preset-typescript": "^7.28.0",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type {ReactNode} from 'react'
|
|
2
2
|
import {html} from 'react-strict-dom'
|
|
3
|
+
import {isNative} from '../../platform'
|
|
3
4
|
import {styles} from './styles.css'
|
|
4
5
|
|
|
5
6
|
export type BadgeVariant = 'default' | 'success' | 'warning' | 'error' | 'info'
|
|
@@ -17,5 +18,9 @@ const sizeMap = {
|
|
|
17
18
|
} as const
|
|
18
19
|
|
|
19
20
|
export function Badge({variant = 'default', size = 'md', children}: BadgeProps) {
|
|
20
|
-
return
|
|
21
|
+
return (
|
|
22
|
+
<html.span style={[styles.base, isNative && styles.nativeFlex, sizeMap[size], styles[variant]]}>
|
|
23
|
+
{children}
|
|
24
|
+
</html.span>
|
|
25
|
+
)
|
|
21
26
|
}
|
|
@@ -48,4 +48,9 @@ export const styles = css.create({
|
|
|
48
48
|
backgroundColor: colors.infoBg,
|
|
49
49
|
color: colors.infoText,
|
|
50
50
|
},
|
|
51
|
+
// RSD-native only honors display:'flex' (not 'inline-flex'). Layered on
|
|
52
|
+
// native via `isNative` so the flex container applies; web keeps inline-flex.
|
|
53
|
+
nativeFlex: {
|
|
54
|
+
display: 'flex',
|
|
55
|
+
},
|
|
51
56
|
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type {ReactNode} from 'react'
|
|
2
2
|
import {html} from 'react-strict-dom'
|
|
3
|
+
import {isNative} from '../../platform'
|
|
3
4
|
import {styles} from './styles.css'
|
|
4
5
|
|
|
5
6
|
export type ButtonVariant = 'primary' | 'secondary' | 'inverseSecondary' | 'link' | 'danger'
|
|
@@ -36,6 +37,7 @@ export function Button({
|
|
|
36
37
|
onClick={onClick}
|
|
37
38
|
style={[
|
|
38
39
|
styles.base,
|
|
40
|
+
isNative && styles.nativeFlex,
|
|
39
41
|
sizeMap[size],
|
|
40
42
|
styles[variant],
|
|
41
43
|
fullWidth && styles.fullWidth,
|
|
@@ -116,4 +116,9 @@ export const styles = css.create({
|
|
|
116
116
|
opacity: 0.5,
|
|
117
117
|
cursor: 'not-allowed',
|
|
118
118
|
},
|
|
119
|
+
// RSD-native only honors display:'flex' (not 'inline-flex'). Layered on
|
|
120
|
+
// native via `isNative` so the flex container applies; web keeps inline-flex.
|
|
121
|
+
nativeFlex: {
|
|
122
|
+
display: 'flex',
|
|
123
|
+
},
|
|
119
124
|
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {type ReactNode, useState, useCallback} from 'react'
|
|
2
2
|
import {html} from 'react-strict-dom'
|
|
3
|
+
import {isNative} from '../../platform'
|
|
3
4
|
import {styles} from './styles.css'
|
|
4
5
|
|
|
5
6
|
interface CheckboxProps {
|
|
@@ -28,6 +29,7 @@ export function Checkbox({
|
|
|
28
29
|
const [internalChecked, setInternalChecked] = useState(defaultChecked)
|
|
29
30
|
const isChecked = isControlled ? controlledChecked : internalChecked
|
|
30
31
|
|
|
32
|
+
// Web: the real <input type=checkbox> drives toggling, a11y and form submit.
|
|
31
33
|
const handleChange = useCallback(
|
|
32
34
|
(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
33
35
|
if (!isControlled) {
|
|
@@ -38,6 +40,54 @@ export function Checkbox({
|
|
|
38
40
|
[isControlled, onChange],
|
|
39
41
|
)
|
|
40
42
|
|
|
43
|
+
// Native: RSD only makes <button> pressable and has no <input type=checkbox>,
|
|
44
|
+
// so the whole row is a button and we synthesize the change payload that
|
|
45
|
+
// consumers read (e.target.checked).
|
|
46
|
+
const handlePress = useCallback(() => {
|
|
47
|
+
if (disabled) return
|
|
48
|
+
const next = !isChecked
|
|
49
|
+
if (!isControlled) {
|
|
50
|
+
setInternalChecked(next)
|
|
51
|
+
}
|
|
52
|
+
onChange?.({
|
|
53
|
+
target: {checked: next, name, value},
|
|
54
|
+
} as unknown as React.ChangeEvent<HTMLInputElement>)
|
|
55
|
+
}, [disabled, isChecked, isControlled, onChange, name, value])
|
|
56
|
+
|
|
57
|
+
if (isNative) {
|
|
58
|
+
return (
|
|
59
|
+
<html.button
|
|
60
|
+
type="button"
|
|
61
|
+
onClick={handlePress}
|
|
62
|
+
disabled={disabled}
|
|
63
|
+
role="checkbox"
|
|
64
|
+
aria-checked={isChecked}
|
|
65
|
+
aria-label={!children ? ariaLabel : undefined}
|
|
66
|
+
style={[
|
|
67
|
+
styles.root,
|
|
68
|
+
styles.nativeFlex,
|
|
69
|
+
styles.nativeButton,
|
|
70
|
+
disabled && styles.rootDisabled,
|
|
71
|
+
]}
|
|
72
|
+
>
|
|
73
|
+
<html.div
|
|
74
|
+
style={[
|
|
75
|
+
styles.box,
|
|
76
|
+
styles.nativeFlex,
|
|
77
|
+
isChecked ? styles.boxChecked : styles.boxUnchecked,
|
|
78
|
+
]}
|
|
79
|
+
>
|
|
80
|
+
{/* CSS-border checkmark (rotated right+bottom borders) — no SVG, no
|
|
81
|
+
react-native-svg dep, so nothing is added to the web bundle. */}
|
|
82
|
+
<html.div
|
|
83
|
+
style={[styles.checkmark, isChecked ? styles.checkmarkVisible : styles.checkmarkHidden]}
|
|
84
|
+
/>
|
|
85
|
+
</html.div>
|
|
86
|
+
{children && <html.span style={styles.labelText}>{children}</html.span>}
|
|
87
|
+
</html.button>
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
41
91
|
return (
|
|
42
92
|
<html.label style={[styles.root, disabled && styles.rootDisabled]}>
|
|
43
93
|
<html.input
|
|
@@ -42,10 +42,39 @@ export const styles = css.create({
|
|
|
42
42
|
backgroundColor: colors.accent,
|
|
43
43
|
borderColor: colors.accent,
|
|
44
44
|
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
// Native-only checkmark: a small box showing just its right + bottom border,
|
|
46
|
+
// rotated 45° into a tick. Pure CSS (RSD translates the transform string to
|
|
47
|
+
// an RN transform), so no SVG / react-native-svg weight reaches web.
|
|
48
|
+
checkmark: {
|
|
49
|
+
width: 5,
|
|
50
|
+
height: 9,
|
|
51
|
+
borderRightWidth: 2,
|
|
52
|
+
borderRightStyle: 'solid',
|
|
53
|
+
borderRightColor: colors.accentContrast,
|
|
54
|
+
borderBottomWidth: 2,
|
|
55
|
+
borderBottomStyle: 'solid',
|
|
56
|
+
borderBottomColor: colors.accentContrast,
|
|
57
|
+
transform: 'rotate(45deg)',
|
|
58
|
+
marginTop: -2,
|
|
59
|
+
},
|
|
60
|
+
checkmarkVisible: {
|
|
61
|
+
opacity: 1,
|
|
62
|
+
},
|
|
63
|
+
checkmarkHidden: {
|
|
64
|
+
opacity: 0,
|
|
65
|
+
},
|
|
66
|
+
// Native label text — RN <Text> doesn't inherit color/size from the button
|
|
67
|
+
// ancestor the way web inherits from <label>, so set it explicitly.
|
|
68
|
+
labelText: {
|
|
69
|
+
fontSize: typography.fontSizeSm,
|
|
70
|
+
color: colors.text,
|
|
71
|
+
},
|
|
72
|
+
// Strip the default button chrome RSD gives <button> on native (border/bg/
|
|
73
|
+
// padding mimic the browser default) so the row matches the web checkbox.
|
|
74
|
+
nativeButton: {
|
|
75
|
+
borderWidth: 0,
|
|
76
|
+
backgroundColor: 'transparent',
|
|
77
|
+
padding: 0,
|
|
49
78
|
},
|
|
50
79
|
input: {
|
|
51
80
|
position: 'absolute',
|
|
@@ -54,4 +83,9 @@ export const styles = css.create({
|
|
|
54
83
|
opacity: 0,
|
|
55
84
|
overflow: 'hidden',
|
|
56
85
|
},
|
|
86
|
+
// RSD-native only honors display:'flex' (not 'inline-flex'). Layered on
|
|
87
|
+
// native via `isNative` (on both .root and .box); web keeps inline-flex.
|
|
88
|
+
nativeFlex: {
|
|
89
|
+
display: 'flex',
|
|
90
|
+
},
|
|
57
91
|
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {ReactNode} from 'react'
|
|
2
2
|
import {useMemo} from 'react'
|
|
3
3
|
import {css, html} from 'react-strict-dom'
|
|
4
|
+
import {isNative} from '../../platform'
|
|
4
5
|
import {InputGroupContext} from './InputGroupContext'
|
|
5
6
|
import {styles} from './styles.css'
|
|
6
7
|
|
|
@@ -37,6 +38,7 @@ function Addon({position = 'end', onClick, disabled, minWidth, children}: AddonP
|
|
|
37
38
|
const positionStyle = position === 'start' ? styles.addonStart : styles.addonEnd
|
|
38
39
|
const style = [
|
|
39
40
|
styles.addon,
|
|
41
|
+
isNative && styles.nativeFlex,
|
|
40
42
|
positionStyle,
|
|
41
43
|
onClick && !disabled && styles.addonClickable,
|
|
42
44
|
disabled && styles.addonDisabled,
|
|
@@ -58,4 +58,9 @@ export const styles = css.create({
|
|
|
58
58
|
opacity: 0.4,
|
|
59
59
|
cursor: 'not-allowed',
|
|
60
60
|
},
|
|
61
|
+
// RSD-native only honors display:'flex' (not 'inline-flex'). Layered on
|
|
62
|
+
// native via `isNative` so the flex container applies; web keeps inline-flex.
|
|
63
|
+
nativeFlex: {
|
|
64
|
+
display: 'flex',
|
|
65
|
+
},
|
|
61
66
|
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {type ReactNode, useCallback, useRef} from 'react'
|
|
2
2
|
import {html} from 'react-strict-dom'
|
|
3
|
+
import {isNative} from '../../platform'
|
|
3
4
|
import {useControllableValue} from '../../hooks/useControllableValue'
|
|
4
5
|
import {styles} from './styles.css'
|
|
5
6
|
|
|
@@ -46,26 +47,35 @@ export function Switch({
|
|
|
46
47
|
}, [disabled, checked, setChecked])
|
|
47
48
|
|
|
48
49
|
return (
|
|
49
|
-
<html.label
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
50
|
+
<html.label
|
|
51
|
+
style={[styles.root, isNative && styles.nativeFlex, disabled && styles.rootDisabled]}
|
|
52
|
+
>
|
|
53
|
+
{!isNative && (
|
|
54
|
+
// Web: hidden real checkbox carries a11y + form submission. RSD has no
|
|
55
|
+
// <input type=checkbox> on native, so it's omitted there and the
|
|
56
|
+
// button below carries the switch role instead.
|
|
57
|
+
<html.input
|
|
58
|
+
ref={inputRef}
|
|
59
|
+
type="checkbox"
|
|
60
|
+
role="switch"
|
|
61
|
+
name={name}
|
|
62
|
+
value={value}
|
|
63
|
+
checked={controlledChecked !== undefined ? controlledChecked : undefined}
|
|
64
|
+
defaultChecked={controlledChecked === undefined ? defaultChecked : undefined}
|
|
65
|
+
disabled={disabled}
|
|
66
|
+
aria-checked={checked}
|
|
67
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
68
|
+
onCheckedChange?.(e.target.checked)
|
|
69
|
+
}}
|
|
70
|
+
style={styles.input}
|
|
71
|
+
/>
|
|
72
|
+
)}
|
|
65
73
|
<html.button
|
|
66
74
|
type="button"
|
|
67
75
|
tabIndex={-1}
|
|
68
|
-
aria-hidden
|
|
76
|
+
aria-hidden={isNative ? undefined : true}
|
|
77
|
+
role={isNative ? 'switch' : undefined}
|
|
78
|
+
aria-checked={isNative ? checked : undefined}
|
|
69
79
|
disabled={disabled}
|
|
70
80
|
onClick={handleClick}
|
|
71
81
|
style={[styles.track, checked ? styles.trackChecked : styles.trackUnchecked]}
|
|
@@ -68,4 +68,9 @@ export const styles = css.create({
|
|
|
68
68
|
opacity: 0,
|
|
69
69
|
overflow: 'hidden',
|
|
70
70
|
},
|
|
71
|
+
// RSD-native only honors display:'flex' (not 'inline-flex'). Layered on
|
|
72
|
+
// native via `isNative` so the flex container applies; web keeps inline-flex.
|
|
73
|
+
nativeFlex: {
|
|
74
|
+
display: 'flex',
|
|
75
|
+
},
|
|
71
76
|
})
|
package/src/platform.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform flag resolved by the bundler's platform extensions: web bundlers
|
|
3
|
+
* (Vite/Rollup) read THIS file (`isNative = false`); Metro reads
|
|
4
|
+
* `platform.native.ts` (`isNative = true`) on React Native / Expo.
|
|
5
|
+
*
|
|
6
|
+
* It lets shared components layer a native-only style override without
|
|
7
|
+
* importing `react-native` on web (the DS web build has no react-native).
|
|
8
|
+
* Typed `boolean` (not the `false` literal) so `isNative && styles.x` stays a
|
|
9
|
+
* `false | Style` union in style arrays rather than narrowing to `false`.
|
|
10
|
+
*/
|
|
11
|
+
export const isNative: boolean = false
|