@scalewing/react-native 0.3.0 → 0.4.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,23 @@
1
1
  # @scalewing/react-native
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Keep public package versions matched for the GitHub `v0.4.0` release tag.
8
+ Native TabBar, Table, and SegmentedControl ship in this version.
9
+ - feef1f8: Add native SegmentedControl with radiogroup semantics, a glass pill track, and a surface-filled selected item. Labels stay in the consumer.
10
+ - feef1f8: Add native TabBar with selected tab semantics, icon slots, and an optional trailing control for round search-style actions.
11
+ - feef1f8: Add native Table with compact density, numeric cells, and the same row/cell language as the web table.
12
+
13
+ ### Patch Changes
14
+
15
+ - 01b138f: Point package metadata to the GitHub source repository and document explicit GitHub Actions releases. Package names and runtime APIs are unchanged.
16
+ - feef1f8: Allow optional `onPress` on native TableRow so compact score rows can open a detail screen without a product-only MatchRow.
17
+ - Updated dependencies [01b138f]
18
+ - Updated dependencies
19
+ - @scalewing/tokens@0.4.0
20
+
3
21
  ## 0.3.0
4
22
 
5
23
  ### Minor Changes
package/README.md CHANGED
@@ -3,7 +3,7 @@
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, Stack, Text, ThemeProvider } from '@scalewing/react-native';
6
+ import { Button, Card, SegmentedControl, Stack, TabBar, Text, ThemeProvider } from '@scalewing/react-native';
7
7
 
8
8
  <ThemeProvider colorScheme="system" palette="cerulean">
9
9
  <Card padding={4}>
@@ -1,5 +1,5 @@
1
1
  import { type FlexAlignType, type FlexStyle } from 'react-native';
2
2
  export type Align = 'start' | 'center' | 'end' | 'stretch';
3
- export type Justify = 'start' | 'center' | 'end' | 'between';
3
+ export type Justify = 'start' | 'center' | 'end' | 'between' | 'around';
4
4
  export declare const alignItems: Record<Align, FlexAlignType>;
5
5
  export declare const justifyContent: Record<Justify, FlexStyle['justifyContent']>;
package/dist/alignment.js CHANGED
@@ -5,6 +5,7 @@ export const alignItems = {
5
5
  stretch: 'stretch',
6
6
  };
7
7
  export const justifyContent = {
8
+ around: 'space-around',
8
9
  between: 'space-between',
9
10
  center: 'center',
10
11
  end: 'flex-end',
@@ -0,0 +1,11 @@
1
+ export type SegmentedItem = {
2
+ id: string;
3
+ label: string;
4
+ };
5
+ export type SegmentedControlProps = {
6
+ accessibilityLabel: string;
7
+ items: readonly SegmentedItem[];
8
+ onChange: (id: string) => void;
9
+ value: string;
10
+ };
11
+ export declare function SegmentedControl({ accessibilityLabel, items, onChange, value, }: SegmentedControlProps): import("react").JSX.Element;
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Pressable } from 'react-native';
3
+ import { mapSegmentedControlStyle, mapSegmentedItemStyle, segmentedItemColor, } from '../map-segmented-style.js';
4
+ import { useTheme } from '../theme/ThemeProvider.js';
5
+ import { Box } from './Box.js';
6
+ import { Text } from './Text.js';
7
+ export function SegmentedControl({ accessibilityLabel, items, onChange, value, }) {
8
+ const theme = useTheme();
9
+ return (_jsx(Box, { accessibilityLabel: accessibilityLabel, accessibilityRole: "radiogroup", style: mapSegmentedControlStyle(theme), children: items.map((item) => {
10
+ const selected = item.id === value;
11
+ return (_jsx(Pressable, { accessibilityRole: "radio", accessibilityState: { selected }, onPress: () => {
12
+ if (!selected) {
13
+ onChange(item.id);
14
+ }
15
+ }, style: mapSegmentedItemStyle(theme, selected), children: _jsx(Text, { color: segmentedItemColor(selected), variant: "label", children: item.label }) }, item.id));
16
+ }) }));
17
+ }
@@ -0,0 +1,20 @@
1
+ import { type ReactNode } from 'react';
2
+ export type TabBarItem = {
3
+ icon: ReactNode;
4
+ key: string;
5
+ label: string;
6
+ onPress: () => void;
7
+ selected: boolean;
8
+ };
9
+ export type TabBarProps = {
10
+ bottomInset?: number;
11
+ items: readonly TabBarItem[];
12
+ trailing?: ReactNode;
13
+ };
14
+ export type TabBarTrailingProps = {
15
+ accessibilityLabel: string;
16
+ children: ReactNode;
17
+ onPress: () => void;
18
+ };
19
+ export declare function TabBarTrailing({ accessibilityLabel, children, onPress, }: TabBarTrailingProps): import("react").JSX.Element;
20
+ export declare function TabBar({ bottomInset, items, trailing }: TabBarProps): import("react").JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Pressable } from 'react-native';
3
+ import { mapTabBarStyle, mapTabBarTrailingStyle, tabBarItemColor, } from '../map-tab-bar-style.js';
4
+ import { useTheme } from '../theme/ThemeProvider.js';
5
+ import { Box } from './Box.js';
6
+ import { Inline } from './Inline.js';
7
+ import { Stack } from './Stack.js';
8
+ import { Text } from './Text.js';
9
+ export function TabBarTrailing({ accessibilityLabel, children, onPress, }) {
10
+ const theme = useTheme();
11
+ return (_jsx(Pressable, { accessibilityLabel: accessibilityLabel, accessibilityRole: "button", onPress: onPress, style: mapTabBarTrailingStyle(theme), children: children }));
12
+ }
13
+ export function TabBar({ bottomInset = 0, items, trailing }) {
14
+ const theme = useTheme();
15
+ return (_jsx(Box, { accessibilityRole: "tablist", style: mapTabBarStyle(theme, { bottomInset }), children: _jsxs(Inline, { align: "center", gap: 3, children: [_jsx(Inline, { align: "center", justify: "around", style: { flex: 1 }, children: items.map((item) => (_jsx(Pressable, { accessibilityLabel: item.label, accessibilityRole: "tab", accessibilityState: { selected: item.selected }, onPress: item.onPress, children: _jsxs(Stack, { align: "center", gap: 1, children: [item.icon, _jsx(Text, { color: tabBarItemColor(item.selected), variant: "caption", children: item.label })] }) }, item.key))) }), trailing] }) }));
16
+ }
@@ -0,0 +1,31 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type TableDensity } from '../map-table-style.js';
3
+ export type TableProps = {
4
+ children: ReactNode;
5
+ density?: TableDensity;
6
+ };
7
+ export declare function Table({ children, density }: TableProps): import("react").JSX.Element;
8
+ export type TableHeaderProps = {
9
+ children: ReactNode;
10
+ };
11
+ export declare function TableHeader({ children }: TableHeaderProps): import("react").JSX.Element;
12
+ export type TableBodyProps = {
13
+ children: ReactNode;
14
+ };
15
+ export declare function TableBody({ children }: TableBodyProps): import("react").JSX.Element;
16
+ export type TableRowProps = {
17
+ accessibilityLabel?: string;
18
+ children: ReactNode;
19
+ onPress?: () => void;
20
+ };
21
+ export declare function TableRow({ accessibilityLabel, children, onPress, }: TableRowProps): import("react").JSX.Element;
22
+ export type TableCellProps = {
23
+ align?: 'start' | 'center' | 'end';
24
+ children: ReactNode;
25
+ flex?: number;
26
+ header?: boolean;
27
+ numeric?: boolean;
28
+ truncate?: boolean;
29
+ };
30
+ export declare function TableCell({ align, children, flex, header, numeric, truncate, }: TableCellProps): import("react").JSX.Element;
31
+ export type { TableDensity };
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext } from 'react';
3
+ import { Pressable } from 'react-native';
4
+ import { Box } from './Box.js';
5
+ import { Text } from './Text.js';
6
+ import { useTheme } from '../theme/ThemeProvider.js';
7
+ import { mapTableCellStyle, mapTableRowStyle, } from '../map-table-style.js';
8
+ const TableContext = createContext({
9
+ density: 'compact',
10
+ });
11
+ export function Table({ children, density = 'compact' }) {
12
+ return (_jsx(TableContext.Provider, { value: { density }, children: _jsx(Box, { children: children }) }));
13
+ }
14
+ export function TableHeader({ children }) {
15
+ return _jsx(Box, { children: children });
16
+ }
17
+ export function TableBody({ children }) {
18
+ return _jsx(Box, { children: children });
19
+ }
20
+ export function TableRow({ accessibilityLabel, children, onPress, }) {
21
+ const theme = useTheme();
22
+ const { density } = useContext(TableContext);
23
+ if (onPress) {
24
+ return (_jsx(Pressable, { accessibilityLabel: accessibilityLabel, accessibilityRole: "button", onPress: onPress, style: ({ pressed }) => mapTableRowStyle(theme, { density, pressed }), children: children }));
25
+ }
26
+ return _jsx(Box, { style: mapTableRowStyle(theme, { density }), children: children });
27
+ }
28
+ export function TableCell({ align = 'start', children, flex = 1, header = false, numeric = false, truncate = false, }) {
29
+ return (_jsx(Box, { style: mapTableCellStyle({ align, flex, numeric }), children: typeof children === 'string' || typeof children === 'number' ? (_jsx(Text, { color: header ? 'muted' : 'text', truncate: truncate, variant: numeric ? 'data' : 'caption', children: children })) : (children) }));
30
+ }
package/dist/index.d.ts CHANGED
@@ -4,5 +4,8 @@ export { Card, type CardProps, type CardVariant } from './components/Card.js';
4
4
  export { Inline, type InlineProps } from './components/Inline.js';
5
5
  export { Stack, type StackProps } from './components/Stack.js';
6
6
  export { type Align, type Justify } from './alignment.js';
7
+ export { SegmentedControl, type SegmentedControlProps, type SegmentedItem, } from './components/SegmentedControl.js';
8
+ export { TabBar, TabBarTrailing, type TabBarItem, type TabBarProps, type TabBarTrailingProps, } from './components/TabBar.js';
9
+ export { Table, TableBody, TableCell, TableHeader, TableRow, type TableBodyProps, type TableCellProps, type TableDensity, type TableHeaderProps, type TableProps, type TableRowProps, } from './components/Table.js';
7
10
  export { Text, type TextProps } from './components/Text.js';
8
11
  export { ThemeProvider, useTheme, type ThemeProviderProps, } from './theme/ThemeProvider.js';
package/dist/index.js CHANGED
@@ -3,5 +3,8 @@ export { Button, } from './components/Button.js';
3
3
  export { Card } from './components/Card.js';
4
4
  export { Inline } from './components/Inline.js';
5
5
  export { Stack } from './components/Stack.js';
6
+ export { SegmentedControl, } from './components/SegmentedControl.js';
7
+ export { TabBar, TabBarTrailing, } from './components/TabBar.js';
8
+ export { Table, TableBody, TableCell, TableHeader, TableRow, } from './components/Table.js';
6
9
  export { Text } from './components/Text.js';
7
10
  export { ThemeProvider, useTheme, } from './theme/ThemeProvider.js';
@@ -0,0 +1,5 @@
1
+ import { type SemanticColorKey, type Theme } from '@scalewing/tokens';
2
+ import { type ViewStyle } from 'react-native';
3
+ export declare function mapSegmentedControlStyle(theme: Theme): ViewStyle;
4
+ export declare function mapSegmentedItemStyle(theme: Theme, selected: boolean): ViewStyle;
5
+ export declare function segmentedItemColor(selected: boolean): SemanticColorKey;
@@ -0,0 +1,26 @@
1
+ import { trackInset, } from '@scalewing/tokens';
2
+ export function mapSegmentedControlStyle(theme) {
3
+ return {
4
+ backgroundColor: theme.glass.fill,
5
+ borderColor: theme.glass.border,
6
+ borderRadius: theme.radius.pill,
7
+ borderWidth: 1,
8
+ flexDirection: 'row',
9
+ gap: trackInset,
10
+ padding: trackInset,
11
+ };
12
+ }
13
+ export function mapSegmentedItemStyle(theme, selected) {
14
+ return {
15
+ alignItems: 'center',
16
+ backgroundColor: selected ? theme.colors.surface : 'transparent',
17
+ borderRadius: theme.radius.pill,
18
+ flex: 1,
19
+ justifyContent: 'center',
20
+ minHeight: theme.control.xs.minHeight,
21
+ paddingHorizontal: theme.control.xs.paddingInline,
22
+ };
23
+ }
24
+ export function segmentedItemColor(selected) {
25
+ return selected ? 'text' : 'muted';
26
+ }
@@ -0,0 +1,7 @@
1
+ import { type SemanticColorKey, type Theme } from '@scalewing/tokens';
2
+ import { type ViewStyle } from 'react-native';
3
+ export declare function mapTabBarStyle(theme: Theme, options?: {
4
+ bottomInset: number;
5
+ }): ViewStyle;
6
+ export declare function tabBarItemColor(selected: boolean): SemanticColorKey;
7
+ export declare function mapTabBarTrailingStyle(theme: Theme): ViewStyle;
@@ -0,0 +1,26 @@
1
+ export function mapTabBarStyle(theme, options = { bottomInset: 0 }) {
2
+ return {
3
+ backgroundColor: theme.colors.surface,
4
+ borderTopColor: theme.colors.border,
5
+ borderTopWidth: 1,
6
+ paddingBottom: theme.space[2] + options.bottomInset,
7
+ paddingHorizontal: theme.space[3],
8
+ paddingTop: theme.space[2],
9
+ };
10
+ }
11
+ export function tabBarItemColor(selected) {
12
+ return selected ? 'accent' : 'muted';
13
+ }
14
+ export function mapTabBarTrailingStyle(theme) {
15
+ const size = theme.control.md.minHeight;
16
+ return {
17
+ alignItems: 'center',
18
+ backgroundColor: theme.colors.surface,
19
+ borderColor: theme.colors.border,
20
+ borderRadius: theme.radius.pill,
21
+ borderWidth: 1,
22
+ height: size,
23
+ justifyContent: 'center',
24
+ width: size,
25
+ };
26
+ }
@@ -0,0 +1,12 @@
1
+ import { type Theme } from '@scalewing/tokens';
2
+ import { type ViewStyle } from 'react-native';
3
+ export type TableDensity = 'comfortable' | 'compact';
4
+ export declare function mapTableRowStyle(theme: Theme, options: {
5
+ density: TableDensity;
6
+ pressed?: boolean;
7
+ }): ViewStyle;
8
+ export declare function mapTableCellStyle(options: {
9
+ align: 'start' | 'center' | 'end';
10
+ flex: number;
11
+ numeric: boolean;
12
+ }): ViewStyle;
@@ -0,0 +1,24 @@
1
+ export function mapTableRowStyle(theme, options) {
2
+ const compact = options.density === 'compact';
3
+ return {
4
+ alignItems: 'center',
5
+ borderBottomColor: theme.colors.border,
6
+ borderBottomWidth: 1,
7
+ flexDirection: 'row',
8
+ opacity: options.pressed ? theme.disabledOpacity : 1,
9
+ paddingHorizontal: compact ? theme.space[2] : theme.space[3],
10
+ paddingVertical: compact ? theme.space[1] : theme.space[2],
11
+ };
12
+ }
13
+ export function mapTableCellStyle(options) {
14
+ const alignment = options.align === 'center'
15
+ ? 'center'
16
+ : options.numeric || options.align === 'end'
17
+ ? 'flex-end'
18
+ : 'flex-start';
19
+ return {
20
+ alignItems: alignment,
21
+ flex: options.flex,
22
+ minWidth: 0,
23
+ };
24
+ }
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@scalewing/react-native",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Scalewing React Native layout primitives.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+https://gitlab.com/dna-consulting/scalewing.git",
9
+ "url": "git+https://github.com/nestor-garcia-dev/scalewing.git",
10
10
  "directory": "packages/react-native"
11
11
  },
12
- "homepage": "https://gitlab.com/dna-consulting/scalewing#readme",
12
+ "homepage": "https://github.com/nestor-garcia-dev/scalewing#readme",
13
13
  "bugs": {
14
- "url": "https://gitlab.com/dna-consulting/scalewing/-/issues"
14
+ "url": "https://github.com/nestor-garcia-dev/scalewing/issues"
15
15
  },
16
16
  "sideEffects": false,
17
17
  "exports": {
@@ -28,7 +28,7 @@
28
28
  "README.md"
29
29
  ],
30
30
  "dependencies": {
31
- "@scalewing/tokens": "0.3.0"
31
+ "@scalewing/tokens": "0.4.0"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "react": "^19.0.0",