@situaction/traquiste-mobile 1.0.0-next.2 → 1.0.0-next.4
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/package.json +4 -1
- package/.eslintrc.js +0 -5
- package/.releaserc +0 -12
- package/CLAUDE.md +0 -25
- package/app.json +0 -5
- package/bitbucket-pipelines.yml +0 -81
- package/build/components/Button/Button.stories.d.ts +0 -19
- package/build/components/Button/Button.stories.d.ts.map +0 -1
- package/build/components/Button/Button.stories.js +0 -95
- package/build/components/Button/Button.stories.js.map +0 -1
- package/build/components/ButtonAction/ButtonAction.stories.d.ts +0 -13
- package/build/components/ButtonAction/ButtonAction.stories.d.ts.map +0 -1
- package/build/components/ButtonAction/ButtonAction.stories.js +0 -51
- package/build/components/ButtonAction/ButtonAction.stories.js.map +0 -1
- package/build/components/ButtonMap/ButtonMap.stories.d.ts +0 -12
- package/build/components/ButtonMap/ButtonMap.stories.d.ts.map +0 -1
- package/build/components/ButtonMap/ButtonMap.stories.js +0 -36
- package/build/components/ButtonMap/ButtonMap.stories.js.map +0 -1
- package/build/components/ButtonMenu/ButtonMenu.stories.d.ts +0 -15
- package/build/components/ButtonMenu/ButtonMenu.stories.d.ts.map +0 -1
- package/build/components/ButtonMenu/ButtonMenu.stories.js +0 -52
- package/build/components/ButtonMenu/ButtonMenu.stories.js.map +0 -1
- package/build/components/FilterChip/FilterChip.stories.d.ts +0 -15
- package/build/components/FilterChip/FilterChip.stories.d.ts.map +0 -1
- package/build/components/FilterChip/FilterChip.stories.js +0 -55
- package/build/components/FilterChip/FilterChip.stories.js.map +0 -1
- package/docs/README.md +0 -73
- package/docs/eslint.config.js +0 -22
- package/docs/index.html +0 -16
- package/docs/package-lock.json +0 -5578
- package/docs/package.json +0 -37
- package/docs/public/favicon.svg +0 -1
- package/docs/public/icons.svg +0 -24
- package/docs/src/App.css +0 -184
- package/docs/src/App.tsx +0 -38
- package/docs/src/assets/hero.png +0 -0
- package/docs/src/assets/react.svg +0 -1
- package/docs/src/assets/vite.svg +0 -1
- package/docs/src/components/Layout.tsx +0 -108
- package/docs/src/components/LiveEditor.tsx +0 -294
- package/docs/src/components/PropsTable.tsx +0 -101
- package/docs/src/components/Sidebar.tsx +0 -103
- package/docs/src/components/TableOfContents.tsx +0 -75
- package/docs/src/context/ColorModeContext.tsx +0 -34
- package/docs/src/index.css +0 -76
- package/docs/src/lib/createComponentPage.tsx +0 -270
- package/docs/src/main.tsx +0 -13
- package/docs/src/pages/Examples.tsx +0 -273
- package/docs/src/pages/Home.tsx +0 -70
- package/docs/src/pages/components/button-action.ts +0 -88
- package/docs/src/pages/components/button-map.ts +0 -67
- package/docs/src/pages/components/button-menu.ts +0 -90
- package/docs/src/pages/components/button.ts +0 -158
- package/docs/src/pages/components/filter-chip.ts +0 -109
- package/docs/tsconfig.app.json +0 -32
- package/docs/tsconfig.json +0 -7
- package/docs/tsconfig.node.json +0 -24
- package/docs/vite.config.ts +0 -18
- package/ios/.xcode.env +0 -11
- package/ios/Podfile +0 -63
- package/ios/Podfile.properties.json +0 -4
- package/ios/situactiontraquistemobile/AppDelegate.swift +0 -69
- package/ios/situactiontraquistemobile/Images.xcassets/AppIcon.appiconset/Contents.json +0 -13
- package/ios/situactiontraquistemobile/Images.xcassets/Contents.json +0 -6
- package/ios/situactiontraquistemobile/Images.xcassets/SplashScreenLegacy.imageset/Contents.json +0 -21
- package/ios/situactiontraquistemobile/Images.xcassets/SplashScreenLegacy.imageset/SplashScreenLegacy.png +0 -0
- package/ios/situactiontraquistemobile/Info.plist +0 -53
- package/ios/situactiontraquistemobile/SplashScreen.storyboard +0 -47
- package/ios/situactiontraquistemobile/Supporting/Expo.plist +0 -6
- package/ios/situactiontraquistemobile/situactiontraquistemobile-Bridging-Header.h +0 -3
- package/ios/situactiontraquistemobile.xcodeproj/project.pbxproj +0 -432
- package/ios/situactiontraquistemobile.xcodeproj/xcshareddata/xcschemes/situactiontraquistemobile.xcscheme +0 -88
- package/jest.config.js +0 -197
- package/src/components/.gitkeep +0 -0
- package/src/components/Button/Button.stories.tsx +0 -123
- package/src/components/Button/Button.tsx +0 -128
- package/src/components/Button/index.ts +0 -2
- package/src/components/ButtonAction/ButtonAction.stories.tsx +0 -67
- package/src/components/ButtonAction/ButtonAction.tsx +0 -67
- package/src/components/ButtonAction/index.ts +0 -2
- package/src/components/ButtonMap/ButtonMap.stories.tsx +0 -49
- package/src/components/ButtonMap/ButtonMap.tsx +0 -40
- package/src/components/ButtonMap/index.ts +0 -2
- package/src/components/ButtonMenu/ButtonMenu.stories.tsx +0 -68
- package/src/components/ButtonMenu/ButtonMenu.tsx +0 -97
- package/src/components/ButtonMenu/index.ts +0 -2
- package/src/components/FilterChip/FilterChip.stories.tsx +0 -71
- package/src/components/FilterChip/FilterChip.tsx +0 -124
- package/src/components/FilterChip/index.ts +0 -2
- package/src/constants/colors.ts +0 -2
- package/src/context/ThemeContext.tsx +0 -84
- package/src/index.ts +0 -23
- package/src/theme/index.ts +0 -20
- package/src/theme/tokens/dark.ts +0 -160
- package/src/theme/tokens/light.ts +0 -166
- package/src/theme/type.ts +0 -122
- package/src/types/.gitkeep +0 -0
- package/src/utils/.gitkeep +0 -0
- package/tsconfig.json +0 -9
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/** Storybook stories for the ButtonMap component */
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import type { Meta, StoryObj } from '@storybook/react-native';
|
|
4
|
-
import { View } from 'react-native';
|
|
5
|
-
import { Plus, Minus, Crosshair, MapPin, MagnifyingGlass } from 'phosphor-react-native';
|
|
6
|
-
import { ButtonMap, type ButtonMapProps } from './ButtonMap';
|
|
7
|
-
|
|
8
|
-
type StoryArgs = ButtonMapProps & { colorScheme: 'light' | 'dark' };
|
|
9
|
-
|
|
10
|
-
const meta: Meta<StoryArgs> = {
|
|
11
|
-
title: 'Components/ButtonMap',
|
|
12
|
-
component: ButtonMap,
|
|
13
|
-
render: ({ colorScheme: _colorScheme, ...args }) => (
|
|
14
|
-
<ButtonMap {...args} icon={<Crosshair />} />
|
|
15
|
-
),
|
|
16
|
-
argTypes: {
|
|
17
|
-
colorScheme: {
|
|
18
|
-
control: { type: 'radio' },
|
|
19
|
-
options: ['light', 'dark'],
|
|
20
|
-
},
|
|
21
|
-
disabled: { control: { type: 'boolean' } },
|
|
22
|
-
},
|
|
23
|
-
args: {
|
|
24
|
-
colorScheme: 'light',
|
|
25
|
-
disabled: false,
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export default meta;
|
|
30
|
-
|
|
31
|
-
type Story = StoryObj<StoryArgs>;
|
|
32
|
-
|
|
33
|
-
export const Default: Story = {};
|
|
34
|
-
|
|
35
|
-
export const Disabled: Story = {
|
|
36
|
-
args: { disabled: true },
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export const MapControls: Story = {
|
|
40
|
-
render: () => (
|
|
41
|
-
<View style={{ gap: 8, padding: 16, alignItems: 'flex-start' }}>
|
|
42
|
-
<ButtonMap icon={<Plus />} />
|
|
43
|
-
<ButtonMap icon={<Minus />} />
|
|
44
|
-
<ButtonMap icon={<Crosshair />} />
|
|
45
|
-
<ButtonMap icon={<MapPin />} />
|
|
46
|
-
<ButtonMap icon={<MagnifyingGlass />} disabled />
|
|
47
|
-
</View>
|
|
48
|
-
),
|
|
49
|
-
};
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ButtonMap component — icon-only-rounded Button wrapper for map UI.
|
|
3
|
-
* Applies a specific cartography shadow (Below/Minimal).
|
|
4
|
-
*/
|
|
5
|
-
import React from 'react';
|
|
6
|
-
import type { StyleProp, ViewStyle } from 'react-native';
|
|
7
|
-
import { Button } from '../Button';
|
|
8
|
-
|
|
9
|
-
export interface ButtonMapProps {
|
|
10
|
-
/** Icon component (Phosphor Duotone) */
|
|
11
|
-
icon: React.ReactElement;
|
|
12
|
-
/** Disabled state */
|
|
13
|
-
disabled?: boolean;
|
|
14
|
-
/** Press handler */
|
|
15
|
-
onPress?: () => void;
|
|
16
|
-
/** Additional container styles */
|
|
17
|
-
style?: StyleProp<ViewStyle>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const shadowStyle: ViewStyle = {
|
|
21
|
-
shadowColor: '#0f0f0f0d',
|
|
22
|
-
shadowOffset: { width: 0, height: 4 },
|
|
23
|
-
shadowRadius: 5,
|
|
24
|
-
shadowOpacity: 1,
|
|
25
|
-
elevation: 3,
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export function ButtonMap({ icon, disabled, onPress, style }: ButtonMapProps) {
|
|
29
|
-
return (
|
|
30
|
-
<Button
|
|
31
|
-
variant="tertiary"
|
|
32
|
-
content="icon-only-rounded"
|
|
33
|
-
size="S"
|
|
34
|
-
iconLeft={icon}
|
|
35
|
-
disabled={disabled}
|
|
36
|
-
onPress={onPress}
|
|
37
|
-
style={[shadowStyle, style]}
|
|
38
|
-
/>
|
|
39
|
-
);
|
|
40
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/** Storybook stories for the ButtonMenu component */
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import type { Meta, StoryObj } from '@storybook/react-native';
|
|
4
|
-
import { View } from 'react-native';
|
|
5
|
-
import { House, MagnifyingGlass, Bell, Gear } from 'phosphor-react-native';
|
|
6
|
-
import { ButtonMenu, type ButtonMenuProps } from './ButtonMenu';
|
|
7
|
-
|
|
8
|
-
type StoryArgs = ButtonMenuProps & { colorScheme: 'light' | 'dark' };
|
|
9
|
-
|
|
10
|
-
const meta: Meta<StoryArgs> = {
|
|
11
|
-
title: 'Components/ButtonMenu',
|
|
12
|
-
component: ButtonMenu,
|
|
13
|
-
render: ({ colorScheme: _colorScheme, ...args }) => (
|
|
14
|
-
<ButtonMenu {...args} icon={<House />} />
|
|
15
|
-
),
|
|
16
|
-
argTypes: {
|
|
17
|
-
colorScheme: {
|
|
18
|
-
control: { type: 'radio' },
|
|
19
|
-
options: ['light', 'dark'],
|
|
20
|
-
},
|
|
21
|
-
state: {
|
|
22
|
-
control: { type: 'radio' },
|
|
23
|
-
options: ['default', 'active', 'disabled'],
|
|
24
|
-
},
|
|
25
|
-
notif: { control: { type: 'boolean' } },
|
|
26
|
-
},
|
|
27
|
-
args: {
|
|
28
|
-
colorScheme: 'light',
|
|
29
|
-
state: 'default',
|
|
30
|
-
notif: false,
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export default meta;
|
|
35
|
-
|
|
36
|
-
type Story = StoryObj<StoryArgs>;
|
|
37
|
-
|
|
38
|
-
export const Default: Story = {
|
|
39
|
-
args: { state: 'default' },
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export const Active: Story = {
|
|
43
|
-
args: { state: 'active' },
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export const Disabled: Story = {
|
|
47
|
-
args: { state: 'disabled' },
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export const WithNotif: Story = {
|
|
51
|
-
args: { state: 'default', notif: true },
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export const ActiveWithNotif: Story = {
|
|
55
|
-
args: { state: 'active', notif: true },
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
export const AllStates: Story = {
|
|
59
|
-
render: () => (
|
|
60
|
-
<View style={{ flexDirection: 'row', gap: 12, padding: 16 }}>
|
|
61
|
-
<ButtonMenu state="default" icon={<House />} />
|
|
62
|
-
<ButtonMenu state="active" icon={<MagnifyingGlass />} />
|
|
63
|
-
<ButtonMenu state="disabled" icon={<Gear />} />
|
|
64
|
-
<ButtonMenu state="default" icon={<Bell />} notif />
|
|
65
|
-
<ButtonMenu state="active" icon={<Bell />} notif />
|
|
66
|
-
</View>
|
|
67
|
-
),
|
|
68
|
-
};
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ButtonMenu component — icon-only toggle button for navigation/menu bars.
|
|
3
|
-
* Supports default, active and disabled states with an optional notification dot.
|
|
4
|
-
*/
|
|
5
|
-
import React, {ReactElement, useState } from 'react';
|
|
6
|
-
import { Pressable, View } from 'react-native';
|
|
7
|
-
import type { StyleProp, ViewStyle } from 'react-native';
|
|
8
|
-
import { useTheme } from '../../context/ThemeContext';
|
|
9
|
-
|
|
10
|
-
export type ButtonMenuState = 'default' | 'active' | 'disabled';
|
|
11
|
-
|
|
12
|
-
export interface ButtonMenuProps {
|
|
13
|
-
/** Icon component (Phosphor Duotone icon) */
|
|
14
|
-
icon: ReactElement;
|
|
15
|
-
/** Toggle state */
|
|
16
|
-
state?: ButtonMenuState;
|
|
17
|
-
/** Show notification dot */
|
|
18
|
-
notif?: boolean;
|
|
19
|
-
/** Press handler */
|
|
20
|
-
onPress?: () => void;
|
|
21
|
-
/** Additional container styles */
|
|
22
|
-
style?: StyleProp<ViewStyle>;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const BACKGROUND: Record<ButtonMenuState, string> = {
|
|
26
|
-
default: 'transparent',
|
|
27
|
-
active: '#d1c3a033',
|
|
28
|
-
disabled: '#0f0f0f0d',
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const BORDER_COLOR: Record<ButtonMenuState, string | undefined> = {
|
|
32
|
-
default: undefined,
|
|
33
|
-
active: '#afafad80',
|
|
34
|
-
disabled: undefined,
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const PRESSED_BACKGROUND = '#d1c3a066';
|
|
38
|
-
const ICON_SIZE = 28;
|
|
39
|
-
const NOTIF_DOT = 8;
|
|
40
|
-
|
|
41
|
-
export function ButtonMenu({
|
|
42
|
-
icon,
|
|
43
|
-
state = 'default',
|
|
44
|
-
notif = false,
|
|
45
|
-
onPress,
|
|
46
|
-
style,
|
|
47
|
-
}: ButtonMenuProps) {
|
|
48
|
-
const [pressed, setPressed] = useState(false);
|
|
49
|
-
const { colors } = useTheme();
|
|
50
|
-
|
|
51
|
-
const isDisabled = state === 'disabled';
|
|
52
|
-
const background = pressed && !isDisabled ? PRESSED_BACKGROUND : BACKGROUND[state];
|
|
53
|
-
const borderColor = BORDER_COLOR[state];
|
|
54
|
-
|
|
55
|
-
const containerStyle: ViewStyle = {
|
|
56
|
-
width: 48,
|
|
57
|
-
height: 48,
|
|
58
|
-
padding: 10,
|
|
59
|
-
borderRadius: 8,
|
|
60
|
-
backgroundColor: background,
|
|
61
|
-
borderWidth: borderColor != null ? 1 : undefined,
|
|
62
|
-
borderColor: borderColor ?? undefined,
|
|
63
|
-
alignItems: 'center',
|
|
64
|
-
justifyContent: 'center',
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const clonedIcon = React.cloneElement(icon, {
|
|
68
|
-
size: ICON_SIZE,
|
|
69
|
-
color: isDisabled ? colors.text.disabled : undefined,
|
|
70
|
-
...(icon.props as Record<string, unknown>),
|
|
71
|
-
} as object);
|
|
72
|
-
|
|
73
|
-
return (
|
|
74
|
-
<Pressable
|
|
75
|
-
pointerEvents={isDisabled ? 'none' : 'auto'}
|
|
76
|
-
onPressIn={() => setPressed(true)}
|
|
77
|
-
onPressOut={() => setPressed(false)}
|
|
78
|
-
onPress={isDisabled ? undefined : onPress}
|
|
79
|
-
style={[containerStyle, style]}
|
|
80
|
-
>
|
|
81
|
-
{clonedIcon}
|
|
82
|
-
{notif && (
|
|
83
|
-
<View
|
|
84
|
-
style={{
|
|
85
|
-
position: 'absolute',
|
|
86
|
-
top: 6,
|
|
87
|
-
left: 34,
|
|
88
|
-
width: NOTIF_DOT,
|
|
89
|
-
height: NOTIF_DOT,
|
|
90
|
-
borderRadius: 9999,
|
|
91
|
-
backgroundColor: '#ff4747',
|
|
92
|
-
}}
|
|
93
|
-
/>
|
|
94
|
-
)}
|
|
95
|
-
</Pressable>
|
|
96
|
-
);
|
|
97
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/** Storybook stories for the FilterChip component */
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import type { Meta, StoryObj } from '@storybook/react-native';
|
|
4
|
-
import { View } from 'react-native';
|
|
5
|
-
import { Funnel, CaretDown, X, MagnifyingGlass } from 'phosphor-react-native';
|
|
6
|
-
import { FilterChip, type FilterChipProps } from './FilterChip';
|
|
7
|
-
|
|
8
|
-
type StoryArgs = FilterChipProps & { colorScheme: 'light' | 'dark' };
|
|
9
|
-
|
|
10
|
-
const meta: Meta<StoryArgs> = {
|
|
11
|
-
title: 'Components/FilterChip',
|
|
12
|
-
component: FilterChip,
|
|
13
|
-
render: ({ colorScheme: _colorScheme, ...args }) => (
|
|
14
|
-
<FilterChip {...args} />
|
|
15
|
-
),
|
|
16
|
-
argTypes: {
|
|
17
|
-
colorScheme: {
|
|
18
|
-
control: { type: 'radio' },
|
|
19
|
-
options: ['light', 'dark'],
|
|
20
|
-
},
|
|
21
|
-
type: {
|
|
22
|
-
control: { type: 'radio' },
|
|
23
|
-
options: ['icon', 'icon-text'],
|
|
24
|
-
},
|
|
25
|
-
selected: { control: { type: 'boolean' } },
|
|
26
|
-
disabled: { control: { type: 'boolean' } },
|
|
27
|
-
},
|
|
28
|
-
args: {
|
|
29
|
-
colorScheme: 'light',
|
|
30
|
-
type: 'icon-text',
|
|
31
|
-
selected: false,
|
|
32
|
-
disabled: false,
|
|
33
|
-
label: 'Filtrer',
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export default meta;
|
|
38
|
-
|
|
39
|
-
type Story = StoryObj<StoryArgs>;
|
|
40
|
-
|
|
41
|
-
export const Default: Story = {
|
|
42
|
-
args: { label: 'Filtrer', iconLeft: <Funnel />, iconRight: <CaretDown /> },
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export const Selected: Story = {
|
|
46
|
-
args: { label: 'Filtrer', iconLeft: <Funnel />, iconRight: <X />, selected: true },
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export const Disabled: Story = {
|
|
50
|
-
args: { label: 'Filtrer', iconLeft: <Funnel />, disabled: true },
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export const IconOnly: Story = {
|
|
54
|
-
args: { type: 'icon', iconLeft: <MagnifyingGlass /> },
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export const IconOnlySelected: Story = {
|
|
58
|
-
args: { type: 'icon', iconLeft: <Funnel />, selected: true },
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
export const AllStates: Story = {
|
|
62
|
-
render: () => (
|
|
63
|
-
<View style={{ flexDirection: 'row', gap: 8, padding: 16, flexWrap: 'wrap' }}>
|
|
64
|
-
<FilterChip label="Default" iconLeft={<Funnel />} iconRight={<CaretDown />} />
|
|
65
|
-
<FilterChip label="Selected" iconLeft={<Funnel />} iconRight={<X />} selected />
|
|
66
|
-
<FilterChip label="Disabled" iconLeft={<Funnel />} disabled />
|
|
67
|
-
<FilterChip type="icon" iconLeft={<Funnel />} />
|
|
68
|
-
<FilterChip type="icon" iconLeft={<Funnel />} selected />
|
|
69
|
-
</View>
|
|
70
|
-
),
|
|
71
|
-
};
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FilterChip component — pill-shaped selection chip for filters.
|
|
3
|
-
* Supports icon-only and icon+text layouts with controlled selection state.
|
|
4
|
-
*/
|
|
5
|
-
import React, { useState } from 'react';
|
|
6
|
-
import { Pressable, Text, View } from 'react-native';
|
|
7
|
-
import type { StyleProp, ViewStyle } from 'react-native';
|
|
8
|
-
import { useTheme } from '../../context/ThemeContext';
|
|
9
|
-
|
|
10
|
-
export type FilterChipState = 'default' | 'pressed' | 'selected' | 'disabled';
|
|
11
|
-
export type FilterChipType = 'icon' | 'icon-text';
|
|
12
|
-
|
|
13
|
-
export interface FilterChipProps {
|
|
14
|
-
/** Content layout */
|
|
15
|
-
type?: FilterChipType;
|
|
16
|
-
/** Controlled selection state */
|
|
17
|
-
selected?: boolean;
|
|
18
|
-
/** Disabled state */
|
|
19
|
-
disabled?: boolean;
|
|
20
|
-
/** Label text — required when type is icon-text */
|
|
21
|
-
label?: string;
|
|
22
|
-
/** Left icon (Phosphor Duotone) */
|
|
23
|
-
iconLeft?: React.ReactElement;
|
|
24
|
-
/** Right icon — typically a caret or close icon */
|
|
25
|
-
iconRight?: React.ReactElement;
|
|
26
|
-
/** Press handler */
|
|
27
|
-
onPress?: () => void;
|
|
28
|
-
/** Additional container styles */
|
|
29
|
-
style?: StyleProp<ViewStyle>;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// --- State color tokens (hardcoded per spec) ---
|
|
33
|
-
|
|
34
|
-
interface StateTokens {
|
|
35
|
-
background: string;
|
|
36
|
-
text: string;
|
|
37
|
-
icon: string;
|
|
38
|
-
borderColor: string;
|
|
39
|
-
borderWidth: number;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const STATE_TOKENS: Record<FilterChipState, StateTokens> = {
|
|
43
|
-
default: { background: 'transparent', text: '#28242e', icon: '#28242e', borderColor: '#afafad80', borderWidth: 1 },
|
|
44
|
-
pressed: { background: '#d1c3a066', text: '#28242e', icon: '#28242e', borderColor: '#afafad80', borderWidth: 1 },
|
|
45
|
-
selected: { background: 'transparent', text: '#28242e', icon: '#28242e', borderColor: '#28242e', borderWidth: 2 },
|
|
46
|
-
disabled: { background: '#0f0f0f0d', text: '#0f0f0f99', icon: '#0f0f0f99', borderColor: '#0f0f0f1a', borderWidth: 1 },
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
const ICON_LEFT_SIZE = 20;
|
|
50
|
-
const ICON_RIGHT_SIZE = 16;
|
|
51
|
-
|
|
52
|
-
// --- Component ---
|
|
53
|
-
|
|
54
|
-
export function FilterChip({
|
|
55
|
-
type = 'icon-text',
|
|
56
|
-
selected = false,
|
|
57
|
-
disabled = false,
|
|
58
|
-
label,
|
|
59
|
-
iconLeft,
|
|
60
|
-
iconRight,
|
|
61
|
-
onPress,
|
|
62
|
-
style,
|
|
63
|
-
}: FilterChipProps) {
|
|
64
|
-
const [internalPressed, setInternalPressed] = useState(false);
|
|
65
|
-
useTheme(); // consumed for future theme-aware tokens
|
|
66
|
-
|
|
67
|
-
const resolvedState: FilterChipState = disabled
|
|
68
|
-
? 'disabled'
|
|
69
|
-
: internalPressed
|
|
70
|
-
? 'pressed'
|
|
71
|
-
: selected
|
|
72
|
-
? 'selected'
|
|
73
|
-
: 'default';
|
|
74
|
-
|
|
75
|
-
const tokens = STATE_TOKENS[resolvedState];
|
|
76
|
-
const isIconOnly = type === 'icon';
|
|
77
|
-
|
|
78
|
-
const chipStyle: ViewStyle = {
|
|
79
|
-
height: 32,
|
|
80
|
-
borderRadius: 100,
|
|
81
|
-
paddingVertical: 6,
|
|
82
|
-
paddingHorizontal: isIconOnly ? 6 : 12,
|
|
83
|
-
flexDirection: 'row',
|
|
84
|
-
alignItems: 'center',
|
|
85
|
-
gap: isIconOnly ? 0 : 4,
|
|
86
|
-
backgroundColor: tokens.background,
|
|
87
|
-
borderWidth: tokens.borderWidth,
|
|
88
|
-
borderColor: tokens.borderColor,
|
|
89
|
-
alignSelf: 'flex-start',
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
const textStyle = {
|
|
93
|
-
color: tokens.text,
|
|
94
|
-
fontSize: 14,
|
|
95
|
-
lineHeight: 20,
|
|
96
|
-
fontFamily: 'Urbanist',
|
|
97
|
-
fontWeight: '500' as const,
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
const cloneIcon = (icon: React.ReactElement | undefined, size: number) => {
|
|
101
|
-
if (!icon) return null;
|
|
102
|
-
return React.cloneElement(icon, {
|
|
103
|
-
size,
|
|
104
|
-
color: tokens.icon,
|
|
105
|
-
...(icon.props as Record<string, unknown>),
|
|
106
|
-
} as object);
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
return (
|
|
110
|
-
<Pressable
|
|
111
|
-
pointerEvents={disabled ? 'none' : 'auto'}
|
|
112
|
-
onPressIn={() => setInternalPressed(true)}
|
|
113
|
-
onPressOut={() => setInternalPressed(false)}
|
|
114
|
-
onPress={disabled ? undefined : onPress}
|
|
115
|
-
style={[{ paddingVertical: 6 }, style]}
|
|
116
|
-
>
|
|
117
|
-
<View style={chipStyle}>
|
|
118
|
-
{cloneIcon(iconLeft, ICON_LEFT_SIZE)}
|
|
119
|
-
{!isIconOnly && label != null && <Text style={textStyle}>{label}</Text>}
|
|
120
|
-
{cloneIcon(iconRight, ICON_RIGHT_SIZE)}
|
|
121
|
-
</View>
|
|
122
|
-
</Pressable>
|
|
123
|
-
);
|
|
124
|
-
}
|
package/src/constants/colors.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Theme system for Traq[UI]ste Mobile.
|
|
3
|
-
* Provides ThemeProvider and useTheme hook.
|
|
4
|
-
* Consumer apps inject their own light/dark tokens via ThemeProvider props.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import React, {
|
|
8
|
-
createContext,
|
|
9
|
-
useContext,
|
|
10
|
-
useMemo,
|
|
11
|
-
type ReactNode,
|
|
12
|
-
} from 'react';
|
|
13
|
-
import { useColorScheme } from 'react-native';
|
|
14
|
-
|
|
15
|
-
import { lightTokens } from '../theme/tokens/light';
|
|
16
|
-
import { darkTokens } from '../theme/tokens/dark';
|
|
17
|
-
import type { ColorSchemeTokens } from '../theme/type';
|
|
18
|
-
|
|
19
|
-
// ---------------------------------------------------------------------------
|
|
20
|
-
// Context
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
|
|
23
|
-
interface ThemeContextValue {
|
|
24
|
-
/** Resolved tokens for the active color scheme */
|
|
25
|
-
colors: ColorSchemeTokens;
|
|
26
|
-
/** Active color scheme */
|
|
27
|
-
colorScheme: 'light' | 'dark';
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const DEFAULT_VALUE: ThemeContextValue = {
|
|
31
|
-
colors: lightTokens,
|
|
32
|
-
colorScheme: 'light',
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const ThemeContext = createContext<ThemeContextValue>(DEFAULT_VALUE);
|
|
36
|
-
|
|
37
|
-
// ---------------------------------------------------------------------------
|
|
38
|
-
// Provider
|
|
39
|
-
// ---------------------------------------------------------------------------
|
|
40
|
-
|
|
41
|
-
interface ThemeProviderProps {
|
|
42
|
-
/** Light tokens — defaults to GDM light */
|
|
43
|
-
light?: ColorSchemeTokens;
|
|
44
|
-
/** Dark tokens — defaults to GDM dark */
|
|
45
|
-
dark?: ColorSchemeTokens;
|
|
46
|
-
/** Force a color scheme — defaults to system preference */
|
|
47
|
-
colorScheme?: 'light' | 'dark';
|
|
48
|
-
children: ReactNode;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function ThemeProvider({
|
|
52
|
-
light = lightTokens,
|
|
53
|
-
dark = darkTokens,
|
|
54
|
-
colorScheme: forcedScheme,
|
|
55
|
-
children,
|
|
56
|
-
}: ThemeProviderProps) {
|
|
57
|
-
const systemScheme = useColorScheme();
|
|
58
|
-
const colorScheme: 'light' | 'dark' =
|
|
59
|
-
forcedScheme ?? (systemScheme === 'dark' ? 'dark' : 'light');
|
|
60
|
-
|
|
61
|
-
const value = useMemo<ThemeContextValue>(
|
|
62
|
-
() => ({
|
|
63
|
-
colors: colorScheme === 'dark' ? dark : light,
|
|
64
|
-
colorScheme,
|
|
65
|
-
}),
|
|
66
|
-
[light, dark, colorScheme],
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
return (
|
|
70
|
-
<ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// ---------------------------------------------------------------------------
|
|
75
|
-
// Hook
|
|
76
|
-
// ---------------------------------------------------------------------------
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Returns resolved color tokens for the active theme and color scheme.
|
|
80
|
-
* Falls back to light tokens when used outside a ThemeProvider.
|
|
81
|
-
*/
|
|
82
|
-
export function useTheme(): ThemeContextValue {
|
|
83
|
-
return useContext(ThemeContext);
|
|
84
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// Public API — re-export all components, types, and utilities from this file
|
|
2
|
-
|
|
3
|
-
// Theme
|
|
4
|
-
export { ThemeProvider, useTheme } from './context/ThemeContext'
|
|
5
|
-
export { lightTokens } from './theme/tokens/light'
|
|
6
|
-
export { darkTokens } from './theme/tokens/dark'
|
|
7
|
-
export type {
|
|
8
|
-
ColorMode,
|
|
9
|
-
ColorSchemeTokens,
|
|
10
|
-
ColorTheme,
|
|
11
|
-
BackgroundTokens,
|
|
12
|
-
TextTokens,
|
|
13
|
-
BorderTokens,
|
|
14
|
-
ShadowTokens,
|
|
15
|
-
StatusTokens,
|
|
16
|
-
ButtonTokens,
|
|
17
|
-
InteractiveVariantTokens,
|
|
18
|
-
InteractiveStateTokens,
|
|
19
|
-
} from './theme/type'
|
|
20
|
-
|
|
21
|
-
// Components
|
|
22
|
-
export { Button } from './components/Button'
|
|
23
|
-
export type { ButtonProps, ButtonVariant, ButtonSize, ButtonContent } from './components/Button'
|
package/src/theme/index.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
// Provider + hook
|
|
2
|
-
export { ThemeProvider, useTheme } from '../context/ThemeContext';
|
|
3
|
-
|
|
4
|
-
// Base tokens (useful for consumer apps building their own theme)
|
|
5
|
-
export { lightTokens } from './tokens/light';
|
|
6
|
-
export { darkTokens } from './tokens/dark';
|
|
7
|
-
|
|
8
|
-
// Types
|
|
9
|
-
export type {
|
|
10
|
-
ColorTheme,
|
|
11
|
-
ColorSchemeTokens,
|
|
12
|
-
BackgroundTokens,
|
|
13
|
-
TextTokens,
|
|
14
|
-
BorderTokens,
|
|
15
|
-
ShadowTokens,
|
|
16
|
-
StatusTokens,
|
|
17
|
-
ButtonTokens,
|
|
18
|
-
InteractiveVariantTokens,
|
|
19
|
-
InteractiveStateTokens,
|
|
20
|
-
} from './type';
|