@scalewing/react-native 0.4.0 → 0.5.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 CHANGED
@@ -1,5 +1,19 @@
1
1
  # @scalewing/react-native
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Keep public package versions matched for the GitHub `v0.5.0` release tag.
8
+ Native Field ships in this version.
9
+ - 7cf64df: Add an accessible token-styled native `Field` with label, hint,
10
+ error, focus, disabled, and standard React Native text-input behavior.
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies
15
+ - @scalewing/tokens@0.5.0
16
+
3
17
  ## 0.4.0
4
18
 
5
19
  ### Minor Changes
package/README.md CHANGED
@@ -3,18 +3,24 @@
3
3
  React Native / Expo primitives that consume the same Scalewing tokens as the DOM package.
4
4
 
5
5
  ```ts
6
- import { Button, Card, SegmentedControl, Stack, TabBar, Text, ThemeProvider } from '@scalewing/react-native';
6
+ import { Button, Card, Field, SegmentedControl, Stack, TabBar, Text, ThemeProvider } from '@scalewing/react-native';
7
7
 
8
8
  <ThemeProvider colorScheme="system" palette="cerulean">
9
9
  <Card padding={4}>
10
10
  <Stack gap={3}>
11
11
  <Text variant="title">Kickoff</Text>
12
+ <Field label="Team name" onChangeText={() => undefined} value="Harbor United" />
12
13
  <Button onPress={() => undefined}>Save</Button>
13
14
  </Stack>
14
15
  </Card>
15
16
  </ThemeProvider>
16
17
  ```
17
18
 
18
- There is no CSS class API. `padding={4}` is spacing step 4, the same step as `sw-padding-4` on web. Field is web-only (`@scalewing/react`). `colorScheme` is `"light"`, `"dark"`, or `"system"`. Named palettes include both schemes; `colors` may be `{ light, dark }`.
19
+ There is no CSS class API. `padding={4}` is spacing step 4, the same step as
20
+ `sw-padding-4` on web. Native `Field` renders a controlled `TextInput` with a
21
+ visible label and optional hint or error; it accepts standard text-input props
22
+ except styling and controlled semantics owned by the component. `colorScheme`
23
+ is `"light"`, `"dark"`, or `"system"`. Named palettes include both schemes;
24
+ `colors` may be `{ light, dark }`.
19
25
 
20
26
  React and React Native are peer dependencies so the host Expo app owns the runtime. Rationale: duplicating React Native inside this package would fight Metro and Expo upgrades.
@@ -0,0 +1,10 @@
1
+ import { type TextInputProps } from 'react-native';
2
+ export type FieldProps = Omit<TextInputProps, 'accessibilityLabel' | 'accessibilityState' | 'editable' | 'onChangeText' | 'style' | 'value'> & {
3
+ disabled?: boolean;
4
+ error?: string;
5
+ hint?: string;
6
+ label: string;
7
+ onChangeText: (value: string) => void;
8
+ value: string;
9
+ };
10
+ export declare function Field({ disabled, error, hint, label, onBlur, onChangeText, onFocus, value, ...inputProps }: FieldProps): import("react").JSX.Element;
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { TextInput } from 'react-native';
4
+ import { mapFieldAccessibility } from '../map-field-accessibility.js';
5
+ import { mapFieldInputStyle } from '../map-field-style.js';
6
+ import { useTheme } from '../theme/ThemeProvider.js';
7
+ import { Stack } from './Stack.js';
8
+ import { Text } from './Text.js';
9
+ export function Field({ disabled = false, error, hint, label, onBlur, onChangeText, onFocus, value, ...inputProps }) {
10
+ const theme = useTheme();
11
+ const [focused, setFocused] = useState(false);
12
+ const supportingText = error ?? hint;
13
+ return (_jsxs(Stack, { gap: 1, children: [_jsx(Text, { variant: "label", children: label }), _jsx(TextInput, { ...inputProps, ...mapFieldAccessibility({
14
+ accessibilityHint: inputProps.accessibilityHint,
15
+ disabled,
16
+ error,
17
+ hint,
18
+ label,
19
+ }), editable: !disabled, onBlur: (event) => {
20
+ setFocused(false);
21
+ onBlur?.(event);
22
+ }, onChangeText: onChangeText, onFocus: (event) => {
23
+ setFocused(true);
24
+ onFocus?.(event);
25
+ }, placeholderTextColor: theme.colors.muted, style: mapFieldInputStyle(theme, {
26
+ disabled,
27
+ focused,
28
+ invalid: Boolean(error),
29
+ }), value: value }), supportingText ? (_jsx(Text, { accessibilityLiveRegion: error ? 'polite' : 'none', color: error ? 'danger' : 'muted', variant: "caption", children: supportingText })) : null] }));
30
+ }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { Box, type BoxProps } from './components/Box.js';
2
2
  export { Button, type ButtonProps, type ButtonSize, type ButtonVariant, } from './components/Button.js';
3
3
  export { Card, type CardProps, type CardVariant } from './components/Card.js';
4
+ export { Field, type FieldProps } from './components/Field.js';
4
5
  export { Inline, type InlineProps } from './components/Inline.js';
5
6
  export { Stack, type StackProps } from './components/Stack.js';
6
7
  export { type Align, type Justify } from './alignment.js';
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export { Box } from './components/Box.js';
2
2
  export { Button, } from './components/Button.js';
3
3
  export { Card } from './components/Card.js';
4
+ export { Field } from './components/Field.js';
4
5
  export { Inline } from './components/Inline.js';
5
6
  export { Stack } from './components/Stack.js';
6
7
  export { SegmentedControl, } from './components/SegmentedControl.js';
@@ -0,0 +1,10 @@
1
+ import { type TextInputProps } from 'react-native';
2
+ type FieldAccessibilityProps = Pick<TextInputProps, 'accessibilityHint' | 'accessibilityLabel' | 'accessibilityState'>;
3
+ export declare function mapFieldAccessibility(options: {
4
+ accessibilityHint?: string;
5
+ disabled: boolean;
6
+ error?: string;
7
+ hint?: string;
8
+ label: string;
9
+ }): FieldAccessibilityProps;
10
+ export {};
@@ -0,0 +1,7 @@
1
+ export function mapFieldAccessibility(options) {
2
+ return {
3
+ accessibilityHint: options.error ?? options.hint ?? options.accessibilityHint,
4
+ accessibilityLabel: options.label,
5
+ accessibilityState: { disabled: options.disabled },
6
+ };
7
+ }
@@ -0,0 +1,7 @@
1
+ import { type Theme } from '@scalewing/tokens';
2
+ import { type TextStyle } from 'react-native';
3
+ export declare function mapFieldInputStyle(theme: Theme, options: {
4
+ disabled: boolean;
5
+ focused: boolean;
6
+ invalid: boolean;
7
+ }): TextStyle;
@@ -0,0 +1,22 @@
1
+ export function mapFieldInputStyle(theme, options) {
2
+ const type = theme.typography.body;
3
+ return {
4
+ backgroundColor: theme.colors.surface,
5
+ borderColor: options.invalid
6
+ ? theme.colors.danger
7
+ : options.focused
8
+ ? theme.colors.accent
9
+ : theme.colors.border,
10
+ borderRadius: theme.radius.lg,
11
+ borderWidth: 1,
12
+ color: theme.colors.text,
13
+ fontSize: type.fontSize,
14
+ fontWeight: String(type.fontWeight),
15
+ letterSpacing: type.letterSpacing,
16
+ lineHeight: type.lineHeight,
17
+ minHeight: theme.control.md.minHeight,
18
+ opacity: options.disabled ? theme.disabledOpacity : 1,
19
+ paddingHorizontal: theme.control.md.paddingInline,
20
+ paddingVertical: theme.space[2],
21
+ };
22
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scalewing/react-native",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Scalewing React Native layout primitives.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -28,7 +28,7 @@
28
28
  "README.md"
29
29
  ],
30
30
  "dependencies": {
31
- "@scalewing/tokens": "0.4.0"
31
+ "@scalewing/tokens": "0.5.0"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "react": "^19.0.0",