@hzblj/kara-components 0.12.0 → 0.13.0
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 +19 -0
- package/README.md +2 -1
- package/lib/module/atoms/icon/icon.android.js +1 -1
- package/lib/module/atoms/icon/icon.android.js.map +1 -1
- package/lib/module/atoms/icon/icon.ios.js +1 -1
- package/lib/module/atoms/icon/icon.ios.js.map +1 -1
- package/lib/module/atoms/pressable/pressable.js +1 -1
- package/lib/module/atoms/pressable/pressable.js.map +1 -1
- package/lib/module/atoms/rn-icon/index.js +1 -1
- package/lib/module/atoms/rn-icon/index.js.map +1 -1
- package/lib/module/atoms/rn-icon/rn-icon.js +26 -0
- package/lib/module/atoms/rn-icon/rn-icon.js.map +1 -0
- package/lib/module/atoms/segmented-control/segmented-control.android.js +1 -1
- package/lib/module/atoms/segmented-control/segmented-control.android.js.map +1 -1
- package/lib/module/atoms/slider/slider.android.js +1 -1
- package/lib/module/atoms/slider/slider.android.js.map +1 -1
- package/lib/module/atoms/switch/switch.android.js +1 -1
- package/lib/module/atoms/switch/switch.android.js.map +1 -1
- package/lib/module/glyph/rn-glyph.android.js +8 -3
- package/lib/module/glyph/rn-glyph.android.js.map +1 -1
- package/lib/module/index.js +0 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/molecules/navigation-bar/navigation-bar.android.js +1 -1
- package/lib/module/molecules/navigation-bar/navigation-bar.android.js.map +1 -1
- package/lib/module/molecules/navigation-bar/navigation-bar.ios.js +1 -1
- package/lib/module/molecules/navigation-bar/navigation-bar.ios.js.map +1 -1
- package/lib/module/organisms/context-menu/context-menu.android.js +1 -1
- package/lib/module/organisms/context-menu/context-menu.android.js.map +1 -1
- package/lib/module/organisms/context-menu/context-menu.ios.js +1 -1
- package/lib/module/organisms/context-menu/context-menu.ios.js.map +1 -1
- package/lib/module/organisms/fab-menu/fab-menu.ios.js +1 -1
- package/lib/module/organisms/fab-menu/fab-menu.ios.js.map +1 -1
- package/lib/module/organisms/swipe-actions/swipe-actions.ios.js +1 -1
- package/lib/module/organisms/swipe-actions/swipe-actions.ios.js.map +1 -1
- package/lib/typescript/atoms/icon/icon.types.d.ts +6 -15
- package/lib/typescript/atoms/pressable/pressable.types.d.ts +1 -1
- package/lib/typescript/atoms/rn-icon/rn-icon.d.ts +6 -1
- package/lib/typescript/index.d.ts +0 -1
- package/package.json +6 -4
- package/src/atoms/icon/icon.android.tsx +1 -1
- package/src/atoms/icon/icon.ios.tsx +1 -1
- package/src/atoms/icon/icon.types.ts +6 -15
- package/src/atoms/pressable/pressable.tsx +1 -1
- package/src/atoms/pressable/pressable.types.ts +1 -2
- package/src/atoms/rn-icon/rn-icon.tsx +28 -0
- package/src/atoms/segmented-control/segmented-control.android.tsx +1 -1
- package/src/atoms/slider/slider.android.tsx +1 -1
- package/src/atoms/switch/switch.android.tsx +1 -1
- package/src/glyph/rn-glyph.android.tsx +14 -3
- package/src/index.ts +0 -1
- package/src/molecules/navigation-bar/navigation-bar.android.tsx +1 -1
- package/src/molecules/navigation-bar/navigation-bar.ios.tsx +1 -1
- package/src/organisms/context-menu/context-menu.android.tsx +1 -1
- package/src/organisms/context-menu/context-menu.ios.tsx +1 -1
- package/src/organisms/fab-menu/fab-menu.ios.tsx +1 -1
- package/src/organisms/swipe-actions/swipe-actions.ios.tsx +1 -1
- package/lib/module/atoms/rn-icon/rn-icon.android.js +0 -29
- package/lib/module/atoms/rn-icon/rn-icon.android.js.map +0 -1
- package/lib/module/atoms/rn-icon/rn-icon.ios.js +0 -29
- package/lib/module/atoms/rn-icon/rn-icon.ios.js.map +0 -1
- package/lib/module/haptics/haptics.js +0 -56
- package/lib/module/haptics/haptics.js.map +0 -1
- package/lib/module/haptics/index.js +0 -5
- package/lib/module/haptics/index.js.map +0 -1
- package/lib/module/haptics/use-haptic-feedback.js +0 -33
- package/lib/module/haptics/use-haptic-feedback.js.map +0 -1
- package/lib/typescript/atoms/rn-icon/rn-icon.ios.d.ts +0 -3
- package/lib/typescript/haptics/haptics.d.ts +0 -61
- package/lib/typescript/haptics/index.d.ts +0 -2
- package/lib/typescript/haptics/use-haptic-feedback.d.ts +0 -15
- package/src/atoms/rn-icon/rn-icon.android.tsx +0 -28
- package/src/atoms/rn-icon/rn-icon.ios.tsx +0 -28
- package/src/haptics/haptics.ts +0 -68
- package/src/haptics/index.ts +0 -2
- package/src/haptics/use-haptic-feedback.ts +0 -36
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Image} from '@expo/ui/swift-ui'
|
|
2
2
|
import {accessibilityHidden, frame, accessibilityLabel as labelModifier, resizable} from '@expo/ui/swift-ui/modifiers'
|
|
3
|
-
import {iconResourceName} from '@hzblj/
|
|
3
|
+
import {iconResourceName} from '@hzblj/expo-native-icons'
|
|
4
4
|
import {spacing, useAppTheme} from '@hzblj/kara-theme'
|
|
5
5
|
import {useMemo} from 'react'
|
|
6
6
|
|
|
@@ -1,22 +1,13 @@
|
|
|
1
|
+
import type {NativeIconName} from '@hzblj/expo-native-icons'
|
|
1
2
|
import type {ColorToken, SpaceSize} from '@hzblj/kara-theme'
|
|
2
3
|
import type {ReactNode} from 'react'
|
|
3
4
|
|
|
4
|
-
declare global {
|
|
5
|
-
/**
|
|
6
|
-
* The app's icon names, one key per SVG in its icon folder. Written by the config plugin
|
|
7
|
-
* (`plugins: [['@hzblj/kara-ui', {icons: {source: './assets/icons'}}]]`) into `kara-icons.d.ts`, or by
|
|
8
|
-
* `npx kara-icons`. Empty until then. Global, so the declaration reaches it without resolving any kara package.
|
|
9
|
-
*/
|
|
10
|
-
interface KaraIcons {}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
type DeclaredIconName = keyof KaraIcons & string
|
|
14
|
-
|
|
15
5
|
/**
|
|
16
|
-
* One of the app's icons
|
|
17
|
-
*
|
|
6
|
+
* One of the app's icons: a key of the global `NativeIcons`, which the config plugin writes into `native-icons.d.ts`
|
|
7
|
+
* (`plugins: [['@hzblj/kara-ui', {icons: {source: './assets/icons'}}]]`) or `npx kara-icons` does. Once it exists only
|
|
8
|
+
* those names type-check, so an icon removed from the folder fails at every call site; before that, any string.
|
|
18
9
|
*/
|
|
19
|
-
export type IconName =
|
|
10
|
+
export type IconName = NativeIconName
|
|
20
11
|
|
|
21
12
|
/**
|
|
22
13
|
* One of the app's icons, in a host: SwiftUI `Image` from the asset catalog on iOS, Material's `Icon` with the vector
|
|
@@ -27,7 +18,7 @@ export type IconProps = {
|
|
|
27
18
|
accessibilityLabel?: string
|
|
28
19
|
/** The icon's tint. `content.primary` by default. */
|
|
29
20
|
color?: ColorToken
|
|
30
|
-
/** Which of the app's icons
|
|
21
|
+
/** Which of the app's icons: a key of `NativeIcons`, one per SVG in the icon folder. */
|
|
31
22
|
name: IconName
|
|
32
23
|
/** Its width and height, a spacing token. `s24` by default. */
|
|
33
24
|
size?: SpaceSize
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {haptics} from '@hzblj/expo-rich-haptics'
|
|
1
2
|
import {
|
|
2
3
|
type AnimatableKey,
|
|
3
4
|
accessibilityProps,
|
|
@@ -13,7 +14,6 @@ import {useCallback, useMemo} from 'react'
|
|
|
13
14
|
import {Platform, Pressable as RNPressable, type ViewStyle} from 'react-native'
|
|
14
15
|
import Animated, {useAnimatedStyle, useSharedValue, withSpring, withTiming} from 'react-native-reanimated'
|
|
15
16
|
|
|
16
|
-
import {haptics} from '../../haptics'
|
|
17
17
|
import {splitForRipple} from '../../ripple-clip'
|
|
18
18
|
import type {PressableComponent, PressableProps} from './pressable.types'
|
|
19
19
|
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
+
import type {Haptic} from '@hzblj/expo-rich-haptics'
|
|
1
2
|
import type {AccessibilityProps, MotionProps, ResponsiveViewSx} from '@hzblj/kara-sx'
|
|
2
3
|
import type {OpacitySize} from '@hzblj/kara-theme'
|
|
3
4
|
import type {ReactNode} from 'react'
|
|
4
5
|
|
|
5
|
-
import type {Haptic} from '../../haptics'
|
|
6
|
-
|
|
7
6
|
/** How the content answers a press: it eases down, it dims, or it stays still. */
|
|
8
7
|
export type PressEffect = 'none' | 'opacity' | 'scale'
|
|
9
8
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {NativeIcon} from '@hzblj/expo-native-icons'
|
|
2
|
+
import {spacing, useAppTheme} from '@hzblj/kara-theme'
|
|
3
|
+
|
|
4
|
+
import type {RnIconComponent, RnIconProps} from './rn-icon.types'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* `@hzblj/expo-native-icons`' `NativeIcon`: a `UIImageView` over the app's asset-catalog icon on iOS, one view drawing
|
|
8
|
+
* its vector drawable on Android. What a list row wants, rather than a SwiftUI or Compose host per row.
|
|
9
|
+
*/
|
|
10
|
+
export const RnIcon: RnIconComponent = ({
|
|
11
|
+
accessibilityLabel,
|
|
12
|
+
color = 'content.primary',
|
|
13
|
+
name,
|
|
14
|
+
size = 's24',
|
|
15
|
+
testID,
|
|
16
|
+
}: RnIconProps) => {
|
|
17
|
+
const theme = useAppTheme()
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<NativeIcon
|
|
21
|
+
accessibilityLabel={accessibilityLabel}
|
|
22
|
+
color={theme.color(color)}
|
|
23
|
+
name={name}
|
|
24
|
+
size={spacing[size]}
|
|
25
|
+
testID={testID}
|
|
26
|
+
/>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {Host, SegmentedButton, SingleChoiceSegmentedButtonRow, Text} from '@expo/ui/jetpack-compose'
|
|
2
2
|
import {fillMaxWidth, testID as testIdModifier, weight} from '@expo/ui/jetpack-compose/modifiers'
|
|
3
|
+
import {haptics} from '@hzblj/expo-rich-haptics'
|
|
3
4
|
import {useAppTheme} from '@hzblj/kara-theme'
|
|
4
5
|
import {useCallback, useMemo} from 'react'
|
|
5
6
|
|
|
6
|
-
import {haptics} from '../../haptics'
|
|
7
7
|
import type {SegmentedControlComponent, SegmentedControlProps} from './segmented-control.types'
|
|
8
8
|
|
|
9
9
|
const MATCH_HEIGHT_ONLY = {horizontal: false, vertical: true}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {Slider as ComposeSlider} from '@expo/ui/jetpack-compose'
|
|
2
|
+
import {haptics} from '@hzblj/expo-rich-haptics'
|
|
2
3
|
import {useAppTheme} from '@hzblj/kara-theme'
|
|
3
4
|
import {useCallback, useEffect, useRef} from 'react'
|
|
4
5
|
|
|
5
|
-
import {haptics} from '../../haptics'
|
|
6
6
|
import {useHostGuard} from '../../host-context'
|
|
7
7
|
import type {SliderComponent, SliderProps} from './slider.types'
|
|
8
8
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {Switch as ComposeSwitch, Row, Text} from '@expo/ui/jetpack-compose'
|
|
2
2
|
import {clickable, fillMaxWidth} from '@expo/ui/jetpack-compose/modifiers'
|
|
3
|
+
import {haptics} from '@hzblj/expo-rich-haptics'
|
|
3
4
|
import {useAppTheme} from '@hzblj/kara-theme'
|
|
4
5
|
import {useCallback, useMemo} from 'react'
|
|
5
6
|
|
|
6
|
-
import {haptics} from '../../haptics'
|
|
7
7
|
import {useHostGuard} from '../../host-context'
|
|
8
8
|
import type {SwitchComponent, SwitchProps} from './switch.types'
|
|
9
9
|
|
|
@@ -1,14 +1,25 @@
|
|
|
1
|
+
import {NativeIconView} from '@hzblj/expo-native-icons'
|
|
1
2
|
import {GLYPHS} from '@hzblj/kara-native'
|
|
2
|
-
import {IconView} from '@hzblj/kara-native/jetpack-compose'
|
|
3
3
|
import {spacing, useAppTheme} from '@hzblj/kara-theme'
|
|
4
4
|
import {useMemo} from 'react'
|
|
5
5
|
|
|
6
6
|
import type {GlyphComponent, GlyphProps} from './glyph.types'
|
|
7
7
|
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* The Material Symbol drawable, drawn by `@hzblj/expo-native-icons`' `NativeIconView` (any drawable by name, not only
|
|
10
|
+
* the app's icons): the React Native tier.
|
|
11
|
+
*/
|
|
9
12
|
export const RnGlyph: GlyphComponent = ({color = 'content.primary', name, size = 's24'}: GlyphProps) => {
|
|
10
13
|
const theme = useAppTheme()
|
|
11
14
|
const style = useMemo(() => ({height: spacing[size], width: spacing[size]}), [size])
|
|
12
15
|
|
|
13
|
-
return
|
|
16
|
+
return (
|
|
17
|
+
<NativeIconView
|
|
18
|
+
accessibilityElementsHidden
|
|
19
|
+
iconColor={theme.color(color)}
|
|
20
|
+
importantForAccessibility="no-hide-descendants"
|
|
21
|
+
resourceName={GLYPHS[name].android}
|
|
22
|
+
style={style}
|
|
23
|
+
/>
|
|
24
|
+
)
|
|
14
25
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {iconResourceName} from '@hzblj/
|
|
1
|
+
import {iconResourceName} from '@hzblj/expo-native-icons'
|
|
2
2
|
import {TopAppBar, type TopAppBarItem} from '@hzblj/kara-native/jetpack-compose'
|
|
3
3
|
import {useAppTheme} from '@hzblj/kara-theme'
|
|
4
4
|
import {useMemo} from 'react'
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {Text as ComposeText, DropdownMenu, DropdownMenuItem, Host} from '@expo/ui/jetpack-compose'
|
|
2
|
+
import {haptics} from '@hzblj/expo-rich-haptics'
|
|
2
3
|
import {useSx} from '@hzblj/kara-sx'
|
|
3
4
|
import {useAppTheme} from '@hzblj/kara-theme'
|
|
4
5
|
import {useCallback, useMemo, useRef, useState} from 'react'
|
|
5
6
|
import {type GestureResponderEvent, Pressable, StyleSheet, View} from 'react-native'
|
|
6
7
|
import {Icon} from '../../atoms/icon'
|
|
7
|
-
import {haptics} from '../../haptics'
|
|
8
8
|
import {HostBoundary} from '../../host-context'
|
|
9
9
|
import {splitForRipple} from '../../ripple-clip'
|
|
10
10
|
import type {MenuAction} from '../menu'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Button, Image, Label, SwipeActions as SwiftUISwipeActions} from '@expo/ui/swift-ui'
|
|
2
2
|
import {tint} from '@expo/ui/swift-ui/modifiers'
|
|
3
|
-
import {iconResourceName} from '@hzblj/
|
|
3
|
+
import {iconResourceName} from '@hzblj/expo-native-icons'
|
|
4
4
|
import {useAppTheme} from '@hzblj/kara-theme'
|
|
5
5
|
|
|
6
6
|
import {useHostGuard} from '../../host-context'
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { iconResourceName } from '@hzblj/kara-native';
|
|
4
|
-
import { IconView } from '@hzblj/kara-native/jetpack-compose';
|
|
5
|
-
import { spacing, useAppTheme } from '@hzblj/kara-theme';
|
|
6
|
-
import { useMemo } from 'react';
|
|
7
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
-
/** An `ImageView` over the app's vector drawable — what a list row wants, rather than a Compose host per row. */
|
|
9
|
-
export const RnIcon = ({
|
|
10
|
-
accessibilityLabel,
|
|
11
|
-
color = 'content.primary',
|
|
12
|
-
name,
|
|
13
|
-
size = 's24',
|
|
14
|
-
testID
|
|
15
|
-
}) => {
|
|
16
|
-
const theme = useAppTheme();
|
|
17
|
-
const style = useMemo(() => ({
|
|
18
|
-
height: spacing[size],
|
|
19
|
-
width: spacing[size]
|
|
20
|
-
}), [size]);
|
|
21
|
-
return /*#__PURE__*/_jsx(IconView, {
|
|
22
|
-
accessibilityLabel: accessibilityLabel,
|
|
23
|
-
iconColor: theme.color(color),
|
|
24
|
-
resourceName: iconResourceName(name),
|
|
25
|
-
style: style,
|
|
26
|
-
testID: testID
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
//# sourceMappingURL=rn-icon.android.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["iconResourceName","IconView","spacing","useAppTheme","useMemo","jsx","_jsx","RnIcon","accessibilityLabel","color","name","size","testID","theme","style","height","width","iconColor","resourceName"],"sourceRoot":"../../../../src","sources":["atoms/rn-icon/rn-icon.android.tsx"],"mappings":";;AAAA,SAAQA,gBAAgB,QAAO,oBAAoB;AACnD,SAAQC,QAAQ,QAAO,oCAAoC;AAC3D,SAAQC,OAAO,EAAEC,WAAW,QAAO,mBAAmB;AACtD,SAAQC,OAAO,QAAO,OAAO;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAI7B;AACA,OAAO,MAAMC,MAAuB,GAAGA,CAAC;EACtCC,kBAAkB;EAClBC,KAAK,GAAG,iBAAiB;EACzBC,IAAI;EACJC,IAAI,GAAG,KAAK;EACZC;AACW,CAAC,KAAK;EACjB,MAAMC,KAAK,GAAGV,WAAW,CAAC,CAAC;EAC3B,MAAMW,KAAK,GAAGV,OAAO,CAAC,OAAO;IAACW,MAAM,EAAEb,OAAO,CAACS,IAAI,CAAC;IAAEK,KAAK,EAAEd,OAAO,CAACS,IAAI;EAAC,CAAC,CAAC,EAAE,CAACA,IAAI,CAAC,CAAC;EAEpF,oBACEL,IAAA,CAACL,QAAQ;IACPO,kBAAkB,EAAEA,kBAAmB;IACvCS,SAAS,EAAEJ,KAAK,CAACJ,KAAK,CAACA,KAAK,CAAE;IAC9BS,YAAY,EAAElB,gBAAgB,CAACU,IAAI,CAAE;IACrCI,KAAK,EAAEA,KAAM;IACbF,MAAM,EAAEA;EAAO,CAChB,CAAC;AAEN,CAAC","ignoreList":[]}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { iconResourceName } from '@hzblj/kara-native';
|
|
4
|
-
import { IconView } from '@hzblj/kara-native/swift-ui';
|
|
5
|
-
import { spacing, useAppTheme } from '@hzblj/kara-theme';
|
|
6
|
-
import { useMemo } from 'react';
|
|
7
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
-
/** A `UIImageView` over the app's asset-catalog icon — what a list row wants, rather than a SwiftUI host per row. */
|
|
9
|
-
export const RnIcon = ({
|
|
10
|
-
accessibilityLabel,
|
|
11
|
-
color = 'content.primary',
|
|
12
|
-
name,
|
|
13
|
-
size = 's24',
|
|
14
|
-
testID
|
|
15
|
-
}) => {
|
|
16
|
-
const theme = useAppTheme();
|
|
17
|
-
const style = useMemo(() => ({
|
|
18
|
-
height: spacing[size],
|
|
19
|
-
width: spacing[size]
|
|
20
|
-
}), [size]);
|
|
21
|
-
return /*#__PURE__*/_jsx(IconView, {
|
|
22
|
-
accessibilityLabel: accessibilityLabel,
|
|
23
|
-
assetName: iconResourceName(name),
|
|
24
|
-
iconColor: theme.color(color),
|
|
25
|
-
style: style,
|
|
26
|
-
testID: testID
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
//# sourceMappingURL=rn-icon.ios.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["iconResourceName","IconView","spacing","useAppTheme","useMemo","jsx","_jsx","RnIcon","accessibilityLabel","color","name","size","testID","theme","style","height","width","assetName","iconColor"],"sourceRoot":"../../../../src","sources":["atoms/rn-icon/rn-icon.ios.tsx"],"mappings":";;AAAA,SAAQA,gBAAgB,QAAO,oBAAoB;AACnD,SAAQC,QAAQ,QAAO,6BAA6B;AACpD,SAAQC,OAAO,EAAEC,WAAW,QAAO,mBAAmB;AACtD,SAAQC,OAAO,QAAO,OAAO;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAI7B;AACA,OAAO,MAAMC,MAAuB,GAAGA,CAAC;EACtCC,kBAAkB;EAClBC,KAAK,GAAG,iBAAiB;EACzBC,IAAI;EACJC,IAAI,GAAG,KAAK;EACZC;AACW,CAAC,KAAK;EACjB,MAAMC,KAAK,GAAGV,WAAW,CAAC,CAAC;EAC3B,MAAMW,KAAK,GAAGV,OAAO,CAAC,OAAO;IAACW,MAAM,EAAEb,OAAO,CAACS,IAAI,CAAC;IAAEK,KAAK,EAAEd,OAAO,CAACS,IAAI;EAAC,CAAC,CAAC,EAAE,CAACA,IAAI,CAAC,CAAC;EAEpF,oBACEL,IAAA,CAACL,QAAQ;IACPO,kBAAkB,EAAEA,kBAAmB;IACvCS,SAAS,EAAEjB,gBAAgB,CAACU,IAAI,CAAE;IAClCQ,SAAS,EAAEL,KAAK,CAACJ,KAAK,CAACA,KAAK,CAAE;IAC9BK,KAAK,EAAEA,KAAM;IACbF,MAAM,EAAEA;EAAO,CAChB,CAAC;AAEN,CAAC","ignoreList":[]}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { HAPTICS, playHaptic, prepareHaptic } from '@hzblj/kara-native';
|
|
4
|
-
let enabled = true;
|
|
5
|
-
const play = (haptic, options) => {
|
|
6
|
-
if (enabled) {
|
|
7
|
-
playHaptic(haptic, options?.intensity);
|
|
8
|
-
}
|
|
9
|
-
};
|
|
10
|
-
const prepare = haptic => {
|
|
11
|
-
if (enabled) {
|
|
12
|
-
prepareHaptic(haptic);
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
const shorthands = Object.fromEntries(HAPTICS.map(haptic => [haptic, options => play(haptic, options)]));
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* The platform's own haptic feedback, named for what happened: UIKit's feedback generators on iOS, the system's
|
|
19
|
-
* `HapticFeedbackConstants` on Android — never a raw vibration. Both follow the user's system haptics setting, and
|
|
20
|
-
* every call is synchronous, with nothing to await.
|
|
21
|
-
*
|
|
22
|
-
* ```ts
|
|
23
|
-
* haptics.success() // a name you know: one function per haptic
|
|
24
|
-
* haptics.play(haptic) // a name that arrives as data
|
|
25
|
-
* haptics.light({intensity: 0.6}) // impacts scale on iOS
|
|
26
|
-
* haptics.prepare('selection') // iOS: warm the Taptic Engine as a gesture begins
|
|
27
|
-
* haptics.setEnabled(userPreference) // silences every kara haptic, the components' own too
|
|
28
|
-
* ```
|
|
29
|
-
*
|
|
30
|
-
* - `selection` — a choice changed: a segment, a chip, a picker row.
|
|
31
|
-
* - `tick` — one step of a continuous gesture: a slider detent, a scrubbed value.
|
|
32
|
-
* - `toggleOn` / `toggleOff` — a switch flipped.
|
|
33
|
-
* - `success` / `warning` / `error` — how a task ended. Android has no warning of its own; it plays a rejection.
|
|
34
|
-
* - `longPress` / `dragStart` — a long press was recognised; an item lifted to be dragged.
|
|
35
|
-
* - `thresholdActivate` / `thresholdDeactivate` — a gesture crossed its commit point, or went back over it.
|
|
36
|
-
* - `keyPress` — a key of the app's own keypad.
|
|
37
|
-
* - `soft`, `light`, `medium`, `rigid`, `heavy` — a collision none of the names above describes.
|
|
38
|
-
*
|
|
39
|
-
* On Android the names that came with Android 14's constants fall back to the nearest older feedback, so every name
|
|
40
|
-
* plays on every version. Haptics are silent in a build without kara's native module.
|
|
41
|
-
*/
|
|
42
|
-
export const haptics = {
|
|
43
|
-
...shorthands,
|
|
44
|
-
/** Whether kara plays haptics — `true` until `setEnabled(false)`. */
|
|
45
|
-
isEnabled: () => enabled,
|
|
46
|
-
play,
|
|
47
|
-
prepare,
|
|
48
|
-
/**
|
|
49
|
-
* Switches every kara haptic on or off, the ones its components play included — for an app's own "Haptics" setting.
|
|
50
|
-
* Not persisted: call it at start-up with the stored preference. The system setting applies either way.
|
|
51
|
-
*/
|
|
52
|
-
setEnabled: value => {
|
|
53
|
-
enabled = value;
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
//# sourceMappingURL=haptics.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["HAPTICS","playHaptic","prepareHaptic","enabled","play","haptic","options","intensity","prepare","shorthands","Object","fromEntries","map","haptics","isEnabled","setEnabled","value"],"sourceRoot":"../../../src","sources":["haptics/haptics.ts"],"mappings":";;AAAA,SAAQA,OAAO,EAAeC,UAAU,EAAEC,aAAa,QAAO,oBAAoB;AAWlF,IAAIC,OAAO,GAAG,IAAI;AAElB,MAAMC,IAAI,GAAGA,CAACC,MAAc,EAAEC,OAAuB,KAAW;EAC9D,IAAIH,OAAO,EAAE;IACXF,UAAU,CAACI,MAAM,EAAEC,OAAO,EAAEC,SAAS,CAAC;EACxC;AACF,CAAC;AAED,MAAMC,OAAO,GAAIH,MAAc,IAAW;EACxC,IAAIF,OAAO,EAAE;IACXD,aAAa,CAACG,MAAM,CAAC;EACvB;AACF,CAAC;AAED,MAAMI,UAAU,GAAGC,MAAM,CAACC,WAAW,CACnCX,OAAO,CAACY,GAAG,CAACP,MAAM,IAAI,CAACA,MAAM,EAAGC,OAAuB,IAAKF,IAAI,CAACC,MAAM,EAAEC,OAAO,CAAC,CAAC,CACpF,CAAqB;;AAErB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMO,OAAO,GAAG;EACrB,GAAGJ,UAAU;EACb;EACAK,SAAS,EAAEA,CAAA,KAAeX,OAAO;EACjCC,IAAI;EACJI,OAAO;EACP;AACF;AACA;AACA;EACEO,UAAU,EAAGC,KAAc,IAAW;IACpCb,OAAO,GAAGa,KAAK;EACjB;AACF,CAAC","ignoreList":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["haptics","useHapticFeedback"],"sourceRoot":"../../../src","sources":["haptics/index.ts"],"mappings":";;AAAA,SAAyCA,OAAO,QAAO,cAAW;AAClE,SAA6BC,iBAAiB,QAAO,0BAAuB","ignoreList":[]}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { useEffect, useRef } from 'react';
|
|
4
|
-
import { haptics } from "./haptics.js";
|
|
5
|
-
|
|
6
|
-
/** Picks the haptic for one change of a trigger — or none, to stay silent for that change. */
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Plays a haptic whenever `trigger` changes — never on mount — like SwiftUI's `sensoryFeedback(_:trigger:)`. Give it
|
|
10
|
-
* a haptic, or a function of the previous and next value that picks one per change. Changes are compared with
|
|
11
|
-
* `Object.is`, so a trigger is a primitive or a stable reference.
|
|
12
|
-
*
|
|
13
|
-
* ```ts
|
|
14
|
-
* useHapticFeedback(tab, 'selection')
|
|
15
|
-
* useHapticFeedback(quantity, (before, after) => (after > before ? 'tick' : 'soft'))
|
|
16
|
-
* useHapticFeedback(payment.status, (_, status) => status === 'paid' ? 'success' : status === 'failed' && 'error')
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
export const useHapticFeedback = (trigger, feedback) => {
|
|
20
|
-
const previous = useRef(trigger);
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
const before = previous.current;
|
|
23
|
-
if (Object.is(before, trigger)) {
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
previous.current = trigger;
|
|
27
|
-
const haptic = typeof feedback === 'function' ? feedback(before, trigger) : feedback;
|
|
28
|
-
if (haptic) {
|
|
29
|
-
haptics.play(haptic);
|
|
30
|
-
}
|
|
31
|
-
}, [feedback, trigger]);
|
|
32
|
-
};
|
|
33
|
-
//# sourceMappingURL=use-haptic-feedback.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["useEffect","useRef","haptics","useHapticFeedback","trigger","feedback","previous","before","current","Object","is","haptic","play"],"sourceRoot":"../../../src","sources":["haptics/use-haptic-feedback.ts"],"mappings":";;AAAA,SAAQA,SAAS,EAAEC,MAAM,QAAO,OAAO;AAEvC,SAAqBC,OAAO,QAAO,cAAW;;AAE9C;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,iBAAiB,GAAGA,CAAIC,OAAU,EAAEC,QAAoC,KAAW;EAC9F,MAAMC,QAAQ,GAAGL,MAAM,CAACG,OAAO,CAAC;EAEhCJ,SAAS,CAAC,MAAM;IACd,MAAMO,MAAM,GAAGD,QAAQ,CAACE,OAAO;IAE/B,IAAIC,MAAM,CAACC,EAAE,CAACH,MAAM,EAAEH,OAAO,CAAC,EAAE;MAC9B;IACF;IAEAE,QAAQ,CAACE,OAAO,GAAGJ,OAAO;IAC1B,MAAMO,MAAM,GAAG,OAAON,QAAQ,KAAK,UAAU,GAAGA,QAAQ,CAACE,MAAM,EAAEH,OAAO,CAAC,GAAGC,QAAQ;IAEpF,IAAIM,MAAM,EAAE;MACVT,OAAO,CAACU,IAAI,CAACD,MAAM,CAAC;IACtB;EACF,CAAC,EAAE,CAACN,QAAQ,EAAED,OAAO,CAAC,CAAC;AACzB,CAAC","ignoreList":[]}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { type Haptic } from '@hzblj/kara-native';
|
|
2
|
-
export type { Haptic };
|
|
3
|
-
export type HapticOptions = {
|
|
4
|
-
/** iOS: scales an impact — `soft`, `light`, `medium`, `rigid`, `heavy` — from 0 to 1. Everything else ignores it. */
|
|
5
|
-
intensity?: number;
|
|
6
|
-
};
|
|
7
|
-
declare const play: (haptic: Haptic, options?: HapticOptions) => void;
|
|
8
|
-
declare const prepare: (haptic: Haptic) => void;
|
|
9
|
-
/**
|
|
10
|
-
* The platform's own haptic feedback, named for what happened: UIKit's feedback generators on iOS, the system's
|
|
11
|
-
* `HapticFeedbackConstants` on Android — never a raw vibration. Both follow the user's system haptics setting, and
|
|
12
|
-
* every call is synchronous, with nothing to await.
|
|
13
|
-
*
|
|
14
|
-
* ```ts
|
|
15
|
-
* haptics.success() // a name you know: one function per haptic
|
|
16
|
-
* haptics.play(haptic) // a name that arrives as data
|
|
17
|
-
* haptics.light({intensity: 0.6}) // impacts scale on iOS
|
|
18
|
-
* haptics.prepare('selection') // iOS: warm the Taptic Engine as a gesture begins
|
|
19
|
-
* haptics.setEnabled(userPreference) // silences every kara haptic, the components' own too
|
|
20
|
-
* ```
|
|
21
|
-
*
|
|
22
|
-
* - `selection` — a choice changed: a segment, a chip, a picker row.
|
|
23
|
-
* - `tick` — one step of a continuous gesture: a slider detent, a scrubbed value.
|
|
24
|
-
* - `toggleOn` / `toggleOff` — a switch flipped.
|
|
25
|
-
* - `success` / `warning` / `error` — how a task ended. Android has no warning of its own; it plays a rejection.
|
|
26
|
-
* - `longPress` / `dragStart` — a long press was recognised; an item lifted to be dragged.
|
|
27
|
-
* - `thresholdActivate` / `thresholdDeactivate` — a gesture crossed its commit point, or went back over it.
|
|
28
|
-
* - `keyPress` — a key of the app's own keypad.
|
|
29
|
-
* - `soft`, `light`, `medium`, `rigid`, `heavy` — a collision none of the names above describes.
|
|
30
|
-
*
|
|
31
|
-
* On Android the names that came with Android 14's constants fall back to the nearest older feedback, so every name
|
|
32
|
-
* plays on every version. Haptics are silent in a build without kara's native module.
|
|
33
|
-
*/
|
|
34
|
-
export declare const haptics: {
|
|
35
|
-
/** Whether kara plays haptics — `true` until `setEnabled(false)`. */
|
|
36
|
-
isEnabled: () => boolean;
|
|
37
|
-
play: typeof play;
|
|
38
|
-
prepare: typeof prepare;
|
|
39
|
-
/**
|
|
40
|
-
* Switches every kara haptic on or off, the ones its components play included — for an app's own "Haptics" setting.
|
|
41
|
-
* Not persisted: call it at start-up with the stored preference. The system setting applies either way.
|
|
42
|
-
*/
|
|
43
|
-
setEnabled: (value: boolean) => void;
|
|
44
|
-
dragStart: (options?: HapticOptions) => void;
|
|
45
|
-
error: (options?: HapticOptions) => void;
|
|
46
|
-
heavy: (options?: HapticOptions) => void;
|
|
47
|
-
keyPress: (options?: HapticOptions) => void;
|
|
48
|
-
light: (options?: HapticOptions) => void;
|
|
49
|
-
longPress: (options?: HapticOptions) => void;
|
|
50
|
-
medium: (options?: HapticOptions) => void;
|
|
51
|
-
rigid: (options?: HapticOptions) => void;
|
|
52
|
-
selection: (options?: HapticOptions) => void;
|
|
53
|
-
soft: (options?: HapticOptions) => void;
|
|
54
|
-
success: (options?: HapticOptions) => void;
|
|
55
|
-
thresholdActivate: (options?: HapticOptions) => void;
|
|
56
|
-
thresholdDeactivate: (options?: HapticOptions) => void;
|
|
57
|
-
tick: (options?: HapticOptions) => void;
|
|
58
|
-
toggleOff: (options?: HapticOptions) => void;
|
|
59
|
-
toggleOn: (options?: HapticOptions) => void;
|
|
60
|
-
warning: (options?: HapticOptions) => void;
|
|
61
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { type Haptic } from './haptics';
|
|
2
|
-
/** Picks the haptic for one change of a trigger — or none, to stay silent for that change. */
|
|
3
|
-
export type HapticResolver<T> = (previous: T, next: T) => Haptic | false | null | undefined;
|
|
4
|
-
/**
|
|
5
|
-
* Plays a haptic whenever `trigger` changes — never on mount — like SwiftUI's `sensoryFeedback(_:trigger:)`. Give it
|
|
6
|
-
* a haptic, or a function of the previous and next value that picks one per change. Changes are compared with
|
|
7
|
-
* `Object.is`, so a trigger is a primitive or a stable reference.
|
|
8
|
-
*
|
|
9
|
-
* ```ts
|
|
10
|
-
* useHapticFeedback(tab, 'selection')
|
|
11
|
-
* useHapticFeedback(quantity, (before, after) => (after > before ? 'tick' : 'soft'))
|
|
12
|
-
* useHapticFeedback(payment.status, (_, status) => status === 'paid' ? 'success' : status === 'failed' && 'error')
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
15
|
-
export declare const useHapticFeedback: <T>(trigger: T, feedback: Haptic | HapticResolver<T>) => void;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import {iconResourceName} from '@hzblj/kara-native'
|
|
2
|
-
import {IconView} from '@hzblj/kara-native/jetpack-compose'
|
|
3
|
-
import {spacing, useAppTheme} from '@hzblj/kara-theme'
|
|
4
|
-
import {useMemo} from 'react'
|
|
5
|
-
|
|
6
|
-
import type {RnIconComponent, RnIconProps} from './rn-icon.types'
|
|
7
|
-
|
|
8
|
-
/** An `ImageView` over the app's vector drawable — what a list row wants, rather than a Compose host per row. */
|
|
9
|
-
export const RnIcon: RnIconComponent = ({
|
|
10
|
-
accessibilityLabel,
|
|
11
|
-
color = 'content.primary',
|
|
12
|
-
name,
|
|
13
|
-
size = 's24',
|
|
14
|
-
testID,
|
|
15
|
-
}: RnIconProps) => {
|
|
16
|
-
const theme = useAppTheme()
|
|
17
|
-
const style = useMemo(() => ({height: spacing[size], width: spacing[size]}), [size])
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<IconView
|
|
21
|
-
accessibilityLabel={accessibilityLabel}
|
|
22
|
-
iconColor={theme.color(color)}
|
|
23
|
-
resourceName={iconResourceName(name)}
|
|
24
|
-
style={style}
|
|
25
|
-
testID={testID}
|
|
26
|
-
/>
|
|
27
|
-
)
|
|
28
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import {iconResourceName} from '@hzblj/kara-native'
|
|
2
|
-
import {IconView} from '@hzblj/kara-native/swift-ui'
|
|
3
|
-
import {spacing, useAppTheme} from '@hzblj/kara-theme'
|
|
4
|
-
import {useMemo} from 'react'
|
|
5
|
-
|
|
6
|
-
import type {RnIconComponent, RnIconProps} from './rn-icon.types'
|
|
7
|
-
|
|
8
|
-
/** A `UIImageView` over the app's asset-catalog icon — what a list row wants, rather than a SwiftUI host per row. */
|
|
9
|
-
export const RnIcon: RnIconComponent = ({
|
|
10
|
-
accessibilityLabel,
|
|
11
|
-
color = 'content.primary',
|
|
12
|
-
name,
|
|
13
|
-
size = 's24',
|
|
14
|
-
testID,
|
|
15
|
-
}: RnIconProps) => {
|
|
16
|
-
const theme = useAppTheme()
|
|
17
|
-
const style = useMemo(() => ({height: spacing[size], width: spacing[size]}), [size])
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<IconView
|
|
21
|
-
accessibilityLabel={accessibilityLabel}
|
|
22
|
-
assetName={iconResourceName(name)}
|
|
23
|
-
iconColor={theme.color(color)}
|
|
24
|
-
style={style}
|
|
25
|
-
testID={testID}
|
|
26
|
-
/>
|
|
27
|
-
)
|
|
28
|
-
}
|
package/src/haptics/haptics.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import {HAPTICS, type Haptic, playHaptic, prepareHaptic} from '@hzblj/kara-native'
|
|
2
|
-
|
|
3
|
-
export type {Haptic}
|
|
4
|
-
|
|
5
|
-
export type HapticOptions = {
|
|
6
|
-
/** iOS: scales an impact — `soft`, `light`, `medium`, `rigid`, `heavy` — from 0 to 1. Everything else ignores it. */
|
|
7
|
-
intensity?: number
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
type HapticShorthands = {readonly [K in Haptic]: (options?: HapticOptions) => void}
|
|
11
|
-
|
|
12
|
-
let enabled = true
|
|
13
|
-
|
|
14
|
-
const play = (haptic: Haptic, options?: HapticOptions): void => {
|
|
15
|
-
if (enabled) {
|
|
16
|
-
playHaptic(haptic, options?.intensity)
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const prepare = (haptic: Haptic): void => {
|
|
21
|
-
if (enabled) {
|
|
22
|
-
prepareHaptic(haptic)
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const shorthands = Object.fromEntries(
|
|
27
|
-
HAPTICS.map(haptic => [haptic, (options?: HapticOptions) => play(haptic, options)])
|
|
28
|
-
) as HapticShorthands
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* The platform's own haptic feedback, named for what happened: UIKit's feedback generators on iOS, the system's
|
|
32
|
-
* `HapticFeedbackConstants` on Android — never a raw vibration. Both follow the user's system haptics setting, and
|
|
33
|
-
* every call is synchronous, with nothing to await.
|
|
34
|
-
*
|
|
35
|
-
* ```ts
|
|
36
|
-
* haptics.success() // a name you know: one function per haptic
|
|
37
|
-
* haptics.play(haptic) // a name that arrives as data
|
|
38
|
-
* haptics.light({intensity: 0.6}) // impacts scale on iOS
|
|
39
|
-
* haptics.prepare('selection') // iOS: warm the Taptic Engine as a gesture begins
|
|
40
|
-
* haptics.setEnabled(userPreference) // silences every kara haptic, the components' own too
|
|
41
|
-
* ```
|
|
42
|
-
*
|
|
43
|
-
* - `selection` — a choice changed: a segment, a chip, a picker row.
|
|
44
|
-
* - `tick` — one step of a continuous gesture: a slider detent, a scrubbed value.
|
|
45
|
-
* - `toggleOn` / `toggleOff` — a switch flipped.
|
|
46
|
-
* - `success` / `warning` / `error` — how a task ended. Android has no warning of its own; it plays a rejection.
|
|
47
|
-
* - `longPress` / `dragStart` — a long press was recognised; an item lifted to be dragged.
|
|
48
|
-
* - `thresholdActivate` / `thresholdDeactivate` — a gesture crossed its commit point, or went back over it.
|
|
49
|
-
* - `keyPress` — a key of the app's own keypad.
|
|
50
|
-
* - `soft`, `light`, `medium`, `rigid`, `heavy` — a collision none of the names above describes.
|
|
51
|
-
*
|
|
52
|
-
* On Android the names that came with Android 14's constants fall back to the nearest older feedback, so every name
|
|
53
|
-
* plays on every version. Haptics are silent in a build without kara's native module.
|
|
54
|
-
*/
|
|
55
|
-
export const haptics = {
|
|
56
|
-
...shorthands,
|
|
57
|
-
/** Whether kara plays haptics — `true` until `setEnabled(false)`. */
|
|
58
|
-
isEnabled: (): boolean => enabled,
|
|
59
|
-
play,
|
|
60
|
-
prepare,
|
|
61
|
-
/**
|
|
62
|
-
* Switches every kara haptic on or off, the ones its components play included — for an app's own "Haptics" setting.
|
|
63
|
-
* Not persisted: call it at start-up with the stored preference. The system setting applies either way.
|
|
64
|
-
*/
|
|
65
|
-
setEnabled: (value: boolean): void => {
|
|
66
|
-
enabled = value
|
|
67
|
-
},
|
|
68
|
-
}
|
package/src/haptics/index.ts
DELETED