@hzblj/kara-components 0.14.0 → 0.14.2
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 +22 -0
- package/lib/module/atoms/activity-indicator/activity-indicator.android.js +14 -7
- package/lib/module/atoms/activity-indicator/activity-indicator.android.js.map +1 -1
- package/lib/module/atoms/activity-indicator/activity-indicator.ios.js +12 -2
- package/lib/module/atoms/activity-indicator/activity-indicator.ios.js.map +1 -1
- package/lib/module/atoms/date-picker/date-picker.android.js +13 -1
- package/lib/module/atoms/date-picker/date-picker.android.js.map +1 -1
- package/lib/module/atoms/date-picker/date-picker.ios.js +19 -12
- package/lib/module/atoms/date-picker/date-picker.ios.js.map +1 -1
- package/lib/module/atoms/picker/picker.android.js +48 -41
- package/lib/module/atoms/picker/picker.android.js.map +1 -1
- package/lib/module/atoms/picker/picker.ios.js +25 -2
- package/lib/module/atoms/picker/picker.ios.js.map +1 -1
- package/lib/module/atoms/segmented-control/segmented-control.android.js +25 -18
- package/lib/module/atoms/segmented-control/segmented-control.android.js.map +1 -1
- package/lib/module/atoms/segmented-control/segmented-control.ios.js +15 -2
- package/lib/module/atoms/segmented-control/segmented-control.ios.js.map +1 -1
- package/lib/module/host-context.js +8 -0
- package/lib/module/host-context.js.map +1 -1
- package/lib/typescript/atoms/activity-indicator/activity-indicator.ios.d.ts +4 -1
- package/lib/typescript/atoms/activity-indicator/activity-indicator.types.d.ts +2 -1
- package/lib/typescript/atoms/date-picker/date-picker.ios.d.ts +2 -1
- package/lib/typescript/atoms/date-picker/date-picker.types.d.ts +1 -1
- package/lib/typescript/atoms/picker/picker.ios.d.ts +5 -0
- package/lib/typescript/atoms/picker/picker.types.d.ts +6 -2
- package/lib/typescript/atoms/segmented-control/segmented-control.ios.d.ts +2 -1
- package/lib/typescript/atoms/segmented-control/segmented-control.types.d.ts +2 -1
- package/lib/typescript/host-context.d.ts +7 -0
- package/package.json +4 -4
- package/src/atoms/activity-indicator/activity-indicator.android.tsx +18 -5
- package/src/atoms/activity-indicator/activity-indicator.ios.tsx +10 -2
- package/src/atoms/activity-indicator/activity-indicator.types.ts +2 -1
- package/src/atoms/date-picker/date-picker.android.tsx +15 -1
- package/src/atoms/date-picker/date-picker.ios.tsx +20 -9
- package/src/atoms/date-picker/date-picker.types.ts +1 -1
- package/src/atoms/picker/picker.android.tsx +53 -44
- package/src/atoms/picker/picker.ios.tsx +28 -7
- package/src/atoms/picker/picker.types.ts +6 -2
- package/src/atoms/segmented-control/segmented-control.android.tsx +29 -18
- package/src/atoms/segmented-control/segmented-control.ios.tsx +10 -2
- package/src/atoms/segmented-control/segmented-control.types.ts +2 -1
- package/src/host-context.tsx +8 -0
|
@@ -4,6 +4,7 @@ import {haptics} from '@hzblj/expo-rich-haptics'
|
|
|
4
4
|
import {useAppTheme} from '@hzblj/kara-theme'
|
|
5
5
|
import {useCallback, useMemo} from 'react'
|
|
6
6
|
|
|
7
|
+
import {useInsideHost} from '../../host-context'
|
|
7
8
|
import type {SegmentedControlComponent, SegmentedControlProps} from './segmented-control.types'
|
|
8
9
|
|
|
9
10
|
const MATCH_HEIGHT_ONLY = {horizontal: false, vertical: true}
|
|
@@ -13,8 +14,9 @@ const SEGMENT = [weight(1)]
|
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Material's single-choice segmented buttons, the selected one filled with the accent like a checked `Switch`. Its own
|
|
16
|
-
* host, themed like an `Island`, so it drops into React Native layout the way the iOS control does.
|
|
17
|
-
* nothing on a new segment, so this
|
|
17
|
+
* host, themed like an `Island`, so it drops into React Native layout the way the iOS control does. Inside a `Screen`
|
|
18
|
+
* or `Island` it renders into that host instead (see `useInsideHost`). Material plays nothing on a new segment, so this
|
|
19
|
+
* plays `selection`.
|
|
18
20
|
*/
|
|
19
21
|
export const SegmentedControl: SegmentedControlComponent = ({
|
|
20
22
|
disabled = false,
|
|
@@ -24,6 +26,7 @@ export const SegmentedControl: SegmentedControlComponent = ({
|
|
|
24
26
|
values,
|
|
25
27
|
}: SegmentedControlProps) => {
|
|
26
28
|
const theme = useAppTheme()
|
|
29
|
+
const insideHost = useInsideHost()
|
|
27
30
|
|
|
28
31
|
// Every segment keeps the same outline, the selected one too: an accent border would run its fill out over the line
|
|
29
32
|
// the others draw inside, and make it look taller than its neighbours.
|
|
@@ -58,24 +61,32 @@ export const SegmentedControl: SegmentedControlComponent = ({
|
|
|
58
61
|
[onChange, selectedIndex, values]
|
|
59
62
|
)
|
|
60
63
|
|
|
64
|
+
const row = (
|
|
65
|
+
<SingleChoiceSegmentedButtonRow modifiers={rowModifiers}>
|
|
66
|
+
{values.map((label, index) => (
|
|
67
|
+
<SegmentedButton
|
|
68
|
+
colors={colors}
|
|
69
|
+
enabled={!disabled}
|
|
70
|
+
key={index}
|
|
71
|
+
modifiers={SEGMENT}
|
|
72
|
+
onClick={() => select(index)}
|
|
73
|
+
selected={index === selectedIndex}
|
|
74
|
+
>
|
|
75
|
+
<SegmentedButton.Label>
|
|
76
|
+
<Text style={theme.typography.subheadlineMedium}>{label}</Text>
|
|
77
|
+
</SegmentedButton.Label>
|
|
78
|
+
</SegmentedButton>
|
|
79
|
+
))}
|
|
80
|
+
</SingleChoiceSegmentedButtonRow>
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if (insideHost) {
|
|
84
|
+
return row
|
|
85
|
+
}
|
|
86
|
+
|
|
61
87
|
return (
|
|
62
88
|
<Host colorScheme={theme.dark ? 'dark' : 'light'} matchContents={MATCH_HEIGHT_ONLY} seedColor={theme.materialSeed}>
|
|
63
|
-
|
|
64
|
-
{values.map((label, index) => (
|
|
65
|
-
<SegmentedButton
|
|
66
|
-
colors={colors}
|
|
67
|
-
enabled={!disabled}
|
|
68
|
-
key={index}
|
|
69
|
-
modifiers={SEGMENT}
|
|
70
|
-
onClick={() => select(index)}
|
|
71
|
-
selected={index === selectedIndex}
|
|
72
|
-
>
|
|
73
|
-
<SegmentedButton.Label>
|
|
74
|
-
<Text style={theme.typography.subheadlineMedium}>{label}</Text>
|
|
75
|
-
</SegmentedButton.Label>
|
|
76
|
-
</SegmentedButton>
|
|
77
|
-
))}
|
|
78
|
-
</SingleChoiceSegmentedButtonRow>
|
|
89
|
+
{row}
|
|
79
90
|
</Host>
|
|
80
91
|
)
|
|
81
92
|
}
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
+
import {RNHostView} from '@expo/ui/swift-ui'
|
|
1
2
|
import {SegmentedControl as NativeSegmentedControl} from '@hzblj/kara-native/swift-ui'
|
|
2
3
|
import {useAppTheme} from '@hzblj/kara-theme'
|
|
3
4
|
import {useCallback, useMemo} from 'react'
|
|
4
5
|
|
|
6
|
+
import {useInsideHost} from '../../host-context'
|
|
5
7
|
import type {SegmentedControlComponent, SegmentedControlProps} from './segmented-control.types'
|
|
6
8
|
|
|
9
|
+
const MATCH_HEIGHT_ONLY = {horizontal: false, vertical: true}
|
|
10
|
+
|
|
7
11
|
/**
|
|
8
12
|
* kara's own `UISegmentedControl`, with the pill in the accent and white text on it — the system control tints only the
|
|
9
13
|
* pill, and SwiftUI's segmented picker not even that. A plain `UIView` in React Native layout: it needs no host, takes
|
|
10
|
-
* the width it is given and UIKit's height.
|
|
14
|
+
* the width it is given and UIKit's height. Inside a `Screen` or `Island` it is carried into that host by `RNHostView`
|
|
15
|
+
* (see `useInsideHost`), the host's width and its own height. UIKit plays the control's own feedback.
|
|
11
16
|
*/
|
|
12
17
|
export const SegmentedControl: SegmentedControlComponent = ({
|
|
13
18
|
disabled = false,
|
|
@@ -17,6 +22,7 @@ export const SegmentedControl: SegmentedControlComponent = ({
|
|
|
17
22
|
values,
|
|
18
23
|
}: SegmentedControlProps) => {
|
|
19
24
|
const theme = useAppTheme()
|
|
25
|
+
const insideHost = useInsideHost()
|
|
20
26
|
const face = theme.typography.footnoteMedium
|
|
21
27
|
|
|
22
28
|
// The native control speaks in values; a segment's is its index, so two labels may read the same.
|
|
@@ -30,7 +36,7 @@ export const SegmentedControl: SegmentedControlComponent = ({
|
|
|
30
36
|
[onChange, values]
|
|
31
37
|
)
|
|
32
38
|
|
|
33
|
-
|
|
39
|
+
const control = (
|
|
34
40
|
<NativeSegmentedControl
|
|
35
41
|
activePillColor={theme.color('fill.accent.primary')}
|
|
36
42
|
activeTextColor={theme.color('content.on.accent')}
|
|
@@ -44,4 +50,6 @@ export const SegmentedControl: SegmentedControlComponent = ({
|
|
|
44
50
|
testID={testID}
|
|
45
51
|
/>
|
|
46
52
|
)
|
|
53
|
+
|
|
54
|
+
return insideHost ? <RNHostView matchContents={MATCH_HEIGHT_ONLY}>{control}</RNHostView> : control
|
|
47
55
|
}
|
|
@@ -3,7 +3,8 @@ import type {ReactNode} from 'react'
|
|
|
3
3
|
/**
|
|
4
4
|
* A row of mutually exclusive segments, the selected one in the accent: kara's own `UISegmentedControl` on iOS,
|
|
5
5
|
* Material's single-choice segmented buttons on Android. It needs no `Screen` or `Island`: iOS is a plain view, Android
|
|
6
|
-
* brings its own host.
|
|
6
|
+
* brings its own host. Inside one it joins that host, so it can share a stack with other native views. It takes the
|
|
7
|
+
* width it is given; the height is the platform's.
|
|
7
8
|
*/
|
|
8
9
|
export type SegmentedControlProps = {
|
|
9
10
|
/** Stops the user changing the segment, and dims the control. */
|
package/src/host-context.tsx
CHANGED
|
@@ -6,6 +6,14 @@ export const HostBoundary = ({children}: {children: ReactNode}) => (
|
|
|
6
6
|
<HostContext.Provider value>{children}</HostContext.Provider>
|
|
7
7
|
)
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Whether this renders inside a `Screen` or `Island` already. An atom that brings its own host renders straight into
|
|
11
|
+
* that one instead: on Android a host nested in another is a real view beside the outer host's own `ComposeView`, and
|
|
12
|
+
* the outer host (a horizontal `LinearLayout`) measures its `ComposeView` in the width the nested one leaves over,
|
|
13
|
+
* which for a full-width nested host is none.
|
|
14
|
+
*/
|
|
15
|
+
export const useInsideHost = () => useContext(HostContext)
|
|
16
|
+
|
|
9
17
|
export const useHostGuard = (atom: string) => {
|
|
10
18
|
const insideHost = useContext(HostContext)
|
|
11
19
|
|