@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.
Files changed (99) hide show
  1. package/package.json +4 -1
  2. package/.eslintrc.js +0 -5
  3. package/.releaserc +0 -12
  4. package/CLAUDE.md +0 -25
  5. package/app.json +0 -5
  6. package/bitbucket-pipelines.yml +0 -81
  7. package/build/components/Button/Button.stories.d.ts +0 -19
  8. package/build/components/Button/Button.stories.d.ts.map +0 -1
  9. package/build/components/Button/Button.stories.js +0 -95
  10. package/build/components/Button/Button.stories.js.map +0 -1
  11. package/build/components/ButtonAction/ButtonAction.stories.d.ts +0 -13
  12. package/build/components/ButtonAction/ButtonAction.stories.d.ts.map +0 -1
  13. package/build/components/ButtonAction/ButtonAction.stories.js +0 -51
  14. package/build/components/ButtonAction/ButtonAction.stories.js.map +0 -1
  15. package/build/components/ButtonMap/ButtonMap.stories.d.ts +0 -12
  16. package/build/components/ButtonMap/ButtonMap.stories.d.ts.map +0 -1
  17. package/build/components/ButtonMap/ButtonMap.stories.js +0 -36
  18. package/build/components/ButtonMap/ButtonMap.stories.js.map +0 -1
  19. package/build/components/ButtonMenu/ButtonMenu.stories.d.ts +0 -15
  20. package/build/components/ButtonMenu/ButtonMenu.stories.d.ts.map +0 -1
  21. package/build/components/ButtonMenu/ButtonMenu.stories.js +0 -52
  22. package/build/components/ButtonMenu/ButtonMenu.stories.js.map +0 -1
  23. package/build/components/FilterChip/FilterChip.stories.d.ts +0 -15
  24. package/build/components/FilterChip/FilterChip.stories.d.ts.map +0 -1
  25. package/build/components/FilterChip/FilterChip.stories.js +0 -55
  26. package/build/components/FilterChip/FilterChip.stories.js.map +0 -1
  27. package/docs/README.md +0 -73
  28. package/docs/eslint.config.js +0 -22
  29. package/docs/index.html +0 -16
  30. package/docs/package-lock.json +0 -5578
  31. package/docs/package.json +0 -37
  32. package/docs/public/favicon.svg +0 -1
  33. package/docs/public/icons.svg +0 -24
  34. package/docs/src/App.css +0 -184
  35. package/docs/src/App.tsx +0 -38
  36. package/docs/src/assets/hero.png +0 -0
  37. package/docs/src/assets/react.svg +0 -1
  38. package/docs/src/assets/vite.svg +0 -1
  39. package/docs/src/components/Layout.tsx +0 -108
  40. package/docs/src/components/LiveEditor.tsx +0 -294
  41. package/docs/src/components/PropsTable.tsx +0 -101
  42. package/docs/src/components/Sidebar.tsx +0 -103
  43. package/docs/src/components/TableOfContents.tsx +0 -75
  44. package/docs/src/context/ColorModeContext.tsx +0 -34
  45. package/docs/src/index.css +0 -76
  46. package/docs/src/lib/createComponentPage.tsx +0 -270
  47. package/docs/src/main.tsx +0 -13
  48. package/docs/src/pages/Examples.tsx +0 -273
  49. package/docs/src/pages/Home.tsx +0 -70
  50. package/docs/src/pages/components/button-action.ts +0 -88
  51. package/docs/src/pages/components/button-map.ts +0 -67
  52. package/docs/src/pages/components/button-menu.ts +0 -90
  53. package/docs/src/pages/components/button.ts +0 -158
  54. package/docs/src/pages/components/filter-chip.ts +0 -109
  55. package/docs/tsconfig.app.json +0 -32
  56. package/docs/tsconfig.json +0 -7
  57. package/docs/tsconfig.node.json +0 -24
  58. package/docs/vite.config.ts +0 -18
  59. package/ios/.xcode.env +0 -11
  60. package/ios/Podfile +0 -63
  61. package/ios/Podfile.properties.json +0 -4
  62. package/ios/situactiontraquistemobile/AppDelegate.swift +0 -69
  63. package/ios/situactiontraquistemobile/Images.xcassets/AppIcon.appiconset/Contents.json +0 -13
  64. package/ios/situactiontraquistemobile/Images.xcassets/Contents.json +0 -6
  65. package/ios/situactiontraquistemobile/Images.xcassets/SplashScreenLegacy.imageset/Contents.json +0 -21
  66. package/ios/situactiontraquistemobile/Images.xcassets/SplashScreenLegacy.imageset/SplashScreenLegacy.png +0 -0
  67. package/ios/situactiontraquistemobile/Info.plist +0 -53
  68. package/ios/situactiontraquistemobile/SplashScreen.storyboard +0 -47
  69. package/ios/situactiontraquistemobile/Supporting/Expo.plist +0 -6
  70. package/ios/situactiontraquistemobile/situactiontraquistemobile-Bridging-Header.h +0 -3
  71. package/ios/situactiontraquistemobile.xcodeproj/project.pbxproj +0 -432
  72. package/ios/situactiontraquistemobile.xcodeproj/xcshareddata/xcschemes/situactiontraquistemobile.xcscheme +0 -88
  73. package/jest.config.js +0 -197
  74. package/src/components/.gitkeep +0 -0
  75. package/src/components/Button/Button.stories.tsx +0 -123
  76. package/src/components/Button/Button.tsx +0 -128
  77. package/src/components/Button/index.ts +0 -2
  78. package/src/components/ButtonAction/ButtonAction.stories.tsx +0 -67
  79. package/src/components/ButtonAction/ButtonAction.tsx +0 -67
  80. package/src/components/ButtonAction/index.ts +0 -2
  81. package/src/components/ButtonMap/ButtonMap.stories.tsx +0 -49
  82. package/src/components/ButtonMap/ButtonMap.tsx +0 -40
  83. package/src/components/ButtonMap/index.ts +0 -2
  84. package/src/components/ButtonMenu/ButtonMenu.stories.tsx +0 -68
  85. package/src/components/ButtonMenu/ButtonMenu.tsx +0 -97
  86. package/src/components/ButtonMenu/index.ts +0 -2
  87. package/src/components/FilterChip/FilterChip.stories.tsx +0 -71
  88. package/src/components/FilterChip/FilterChip.tsx +0 -124
  89. package/src/components/FilterChip/index.ts +0 -2
  90. package/src/constants/colors.ts +0 -2
  91. package/src/context/ThemeContext.tsx +0 -84
  92. package/src/index.ts +0 -23
  93. package/src/theme/index.ts +0 -20
  94. package/src/theme/tokens/dark.ts +0 -160
  95. package/src/theme/tokens/light.ts +0 -166
  96. package/src/theme/type.ts +0 -122
  97. package/src/types/.gitkeep +0 -0
  98. package/src/utils/.gitkeep +0 -0
  99. 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,2 +0,0 @@
1
- export { ButtonMap } from './ButtonMap';
2
- export type { ButtonMapProps } from './ButtonMap';
@@ -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,2 +0,0 @@
1
- export { ButtonMenu } from './ButtonMenu';
2
- export type { ButtonMenuProps, ButtonMenuState } from './ButtonMenu';
@@ -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
- }
@@ -1,2 +0,0 @@
1
- export { FilterChip } from './FilterChip';
2
- export type { FilterChipProps, FilterChipState, FilterChipType } from './FilterChip';
@@ -1,2 +0,0 @@
1
- // Color design tokens — add tokens here as the design system grows
2
- export const colors = {} as const;
@@ -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'
@@ -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';