@situaction/traquiste-mobile 1.0.0-next.2

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 (168) hide show
  1. package/.eslintrc.js +5 -0
  2. package/.releaserc +12 -0
  3. package/CLAUDE.md +25 -0
  4. package/README.md +124 -0
  5. package/app.json +5 -0
  6. package/bitbucket-pipelines.yml +81 -0
  7. package/build/components/Button/Button.d.ts +31 -0
  8. package/build/components/Button/Button.d.ts.map +1 -0
  9. package/build/components/Button/Button.js +67 -0
  10. package/build/components/Button/Button.js.map +1 -0
  11. package/build/components/Button/Button.stories.d.ts +19 -0
  12. package/build/components/Button/Button.stories.d.ts.map +1 -0
  13. package/build/components/Button/Button.stories.js +95 -0
  14. package/build/components/Button/Button.stories.js.map +1 -0
  15. package/build/components/Button/index.d.ts +3 -0
  16. package/build/components/Button/index.d.ts.map +1 -0
  17. package/build/components/Button/index.js +2 -0
  18. package/build/components/Button/index.js.map +1 -0
  19. package/build/components/ButtonAction/ButtonAction.d.ts +21 -0
  20. package/build/components/ButtonAction/ButtonAction.d.ts.map +1 -0
  21. package/build/components/ButtonAction/ButtonAction.js +35 -0
  22. package/build/components/ButtonAction/ButtonAction.js.map +1 -0
  23. package/build/components/ButtonAction/ButtonAction.stories.d.ts +13 -0
  24. package/build/components/ButtonAction/ButtonAction.stories.d.ts.map +1 -0
  25. package/build/components/ButtonAction/ButtonAction.stories.js +51 -0
  26. package/build/components/ButtonAction/ButtonAction.stories.js.map +1 -0
  27. package/build/components/ButtonAction/index.d.ts +3 -0
  28. package/build/components/ButtonAction/index.d.ts.map +1 -0
  29. package/build/components/ButtonAction/index.js +2 -0
  30. package/build/components/ButtonAction/index.js.map +1 -0
  31. package/build/components/ButtonMap/ButtonMap.d.ts +18 -0
  32. package/build/components/ButtonMap/ButtonMap.d.ts.map +1 -0
  33. package/build/components/ButtonMap/ButtonMap.js +17 -0
  34. package/build/components/ButtonMap/ButtonMap.js.map +1 -0
  35. package/build/components/ButtonMap/ButtonMap.stories.d.ts +12 -0
  36. package/build/components/ButtonMap/ButtonMap.stories.d.ts.map +1 -0
  37. package/build/components/ButtonMap/ButtonMap.stories.js +36 -0
  38. package/build/components/ButtonMap/ButtonMap.stories.js.map +1 -0
  39. package/build/components/ButtonMap/index.d.ts +3 -0
  40. package/build/components/ButtonMap/index.d.ts.map +1 -0
  41. package/build/components/ButtonMap/index.js +2 -0
  42. package/build/components/ButtonMap/index.js.map +1 -0
  43. package/build/components/ButtonMenu/ButtonMenu.d.ts +21 -0
  44. package/build/components/ButtonMenu/ButtonMenu.d.ts.map +1 -0
  45. package/build/components/ButtonMenu/ButtonMenu.js +56 -0
  46. package/build/components/ButtonMenu/ButtonMenu.js.map +1 -0
  47. package/build/components/ButtonMenu/ButtonMenu.stories.d.ts +15 -0
  48. package/build/components/ButtonMenu/ButtonMenu.stories.d.ts.map +1 -0
  49. package/build/components/ButtonMenu/ButtonMenu.stories.js +52 -0
  50. package/build/components/ButtonMenu/ButtonMenu.stories.js.map +1 -0
  51. package/build/components/ButtonMenu/index.d.ts +3 -0
  52. package/build/components/ButtonMenu/index.d.ts.map +1 -0
  53. package/build/components/ButtonMenu/index.js +2 -0
  54. package/build/components/ButtonMenu/index.js.map +1 -0
  55. package/build/components/FilterChip/FilterChip.d.ts +28 -0
  56. package/build/components/FilterChip/FilterChip.d.ts.map +1 -0
  57. package/build/components/FilterChip/FilterChip.js +66 -0
  58. package/build/components/FilterChip/FilterChip.js.map +1 -0
  59. package/build/components/FilterChip/FilterChip.stories.d.ts +15 -0
  60. package/build/components/FilterChip/FilterChip.stories.d.ts.map +1 -0
  61. package/build/components/FilterChip/FilterChip.stories.js +55 -0
  62. package/build/components/FilterChip/FilterChip.stories.js.map +1 -0
  63. package/build/components/FilterChip/index.d.ts +3 -0
  64. package/build/components/FilterChip/index.d.ts.map +1 -0
  65. package/build/components/FilterChip/index.js +2 -0
  66. package/build/components/FilterChip/index.js.map +1 -0
  67. package/build/constants/colors.d.ts +2 -0
  68. package/build/constants/colors.d.ts.map +1 -0
  69. package/build/constants/colors.js +3 -0
  70. package/build/constants/colors.js.map +1 -0
  71. package/build/context/ThemeContext.d.ts +30 -0
  72. package/build/context/ThemeContext.d.ts.map +1 -0
  73. package/build/context/ThemeContext.js +34 -0
  74. package/build/context/ThemeContext.js.map +1 -0
  75. package/build/index.d.ts +7 -0
  76. package/build/index.d.ts.map +1 -0
  77. package/build/index.js +8 -0
  78. package/build/index.js.map +1 -0
  79. package/build/theme/index.d.ts +5 -0
  80. package/build/theme/index.d.ts.map +1 -0
  81. package/build/theme/index.js +6 -0
  82. package/build/theme/index.js.map +1 -0
  83. package/build/theme/tokens/dark.d.ts +8 -0
  84. package/build/theme/tokens/dark.d.ts.map +1 -0
  85. package/build/theme/tokens/dark.js +146 -0
  86. package/build/theme/tokens/dark.js.map +1 -0
  87. package/build/theme/tokens/light.d.ts +8 -0
  88. package/build/theme/tokens/light.d.ts.map +1 -0
  89. package/build/theme/tokens/light.js +152 -0
  90. package/build/theme/tokens/light.js.map +1 -0
  91. package/build/theme/type.d.ts +75 -0
  92. package/build/theme/type.d.ts.map +1 -0
  93. package/build/theme/type.js +7 -0
  94. package/build/theme/type.js.map +1 -0
  95. package/docs/README.md +73 -0
  96. package/docs/eslint.config.js +22 -0
  97. package/docs/index.html +16 -0
  98. package/docs/package-lock.json +5578 -0
  99. package/docs/package.json +37 -0
  100. package/docs/public/favicon.svg +1 -0
  101. package/docs/public/icons.svg +24 -0
  102. package/docs/src/App.css +184 -0
  103. package/docs/src/App.tsx +38 -0
  104. package/docs/src/assets/hero.png +0 -0
  105. package/docs/src/assets/react.svg +1 -0
  106. package/docs/src/assets/vite.svg +1 -0
  107. package/docs/src/components/Layout.tsx +108 -0
  108. package/docs/src/components/LiveEditor.tsx +294 -0
  109. package/docs/src/components/PropsTable.tsx +101 -0
  110. package/docs/src/components/Sidebar.tsx +103 -0
  111. package/docs/src/components/TableOfContents.tsx +75 -0
  112. package/docs/src/context/ColorModeContext.tsx +34 -0
  113. package/docs/src/index.css +76 -0
  114. package/docs/src/lib/createComponentPage.tsx +270 -0
  115. package/docs/src/main.tsx +13 -0
  116. package/docs/src/pages/Examples.tsx +273 -0
  117. package/docs/src/pages/Home.tsx +70 -0
  118. package/docs/src/pages/components/button-action.ts +88 -0
  119. package/docs/src/pages/components/button-map.ts +67 -0
  120. package/docs/src/pages/components/button-menu.ts +90 -0
  121. package/docs/src/pages/components/button.ts +158 -0
  122. package/docs/src/pages/components/filter-chip.ts +109 -0
  123. package/docs/tsconfig.app.json +32 -0
  124. package/docs/tsconfig.json +7 -0
  125. package/docs/tsconfig.node.json +24 -0
  126. package/docs/vite.config.ts +18 -0
  127. package/ios/.xcode.env +11 -0
  128. package/ios/Podfile +63 -0
  129. package/ios/Podfile.properties.json +4 -0
  130. package/ios/situactiontraquistemobile/AppDelegate.swift +69 -0
  131. package/ios/situactiontraquistemobile/Images.xcassets/AppIcon.appiconset/Contents.json +13 -0
  132. package/ios/situactiontraquistemobile/Images.xcassets/Contents.json +6 -0
  133. package/ios/situactiontraquistemobile/Images.xcassets/SplashScreenLegacy.imageset/Contents.json +21 -0
  134. package/ios/situactiontraquistemobile/Images.xcassets/SplashScreenLegacy.imageset/SplashScreenLegacy.png +0 -0
  135. package/ios/situactiontraquistemobile/Info.plist +53 -0
  136. package/ios/situactiontraquistemobile/SplashScreen.storyboard +47 -0
  137. package/ios/situactiontraquistemobile/Supporting/Expo.plist +6 -0
  138. package/ios/situactiontraquistemobile/situactiontraquistemobile-Bridging-Header.h +3 -0
  139. package/ios/situactiontraquistemobile.xcodeproj/project.pbxproj +432 -0
  140. package/ios/situactiontraquistemobile.xcodeproj/xcshareddata/xcschemes/situactiontraquistemobile.xcscheme +88 -0
  141. package/jest.config.js +197 -0
  142. package/package.json +90 -0
  143. package/src/components/.gitkeep +0 -0
  144. package/src/components/Button/Button.stories.tsx +123 -0
  145. package/src/components/Button/Button.tsx +128 -0
  146. package/src/components/Button/index.ts +2 -0
  147. package/src/components/ButtonAction/ButtonAction.stories.tsx +67 -0
  148. package/src/components/ButtonAction/ButtonAction.tsx +67 -0
  149. package/src/components/ButtonAction/index.ts +2 -0
  150. package/src/components/ButtonMap/ButtonMap.stories.tsx +49 -0
  151. package/src/components/ButtonMap/ButtonMap.tsx +40 -0
  152. package/src/components/ButtonMap/index.ts +2 -0
  153. package/src/components/ButtonMenu/ButtonMenu.stories.tsx +68 -0
  154. package/src/components/ButtonMenu/ButtonMenu.tsx +97 -0
  155. package/src/components/ButtonMenu/index.ts +2 -0
  156. package/src/components/FilterChip/FilterChip.stories.tsx +71 -0
  157. package/src/components/FilterChip/FilterChip.tsx +124 -0
  158. package/src/components/FilterChip/index.ts +2 -0
  159. package/src/constants/colors.ts +2 -0
  160. package/src/context/ThemeContext.tsx +84 -0
  161. package/src/index.ts +23 -0
  162. package/src/theme/index.ts +20 -0
  163. package/src/theme/tokens/dark.ts +160 -0
  164. package/src/theme/tokens/light.ts +166 -0
  165. package/src/theme/type.ts +122 -0
  166. package/src/types/.gitkeep +0 -0
  167. package/src/utils/.gitkeep +0 -0
  168. package/tsconfig.json +9 -0
package/.eslintrc.js ADDED
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ root: true,
3
+ extends: ['universe/native', 'universe/web'],
4
+ ignorePatterns: ['build'],
5
+ };
package/.releaserc ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "branches": [
3
+ "master",
4
+ { "name": "develop", "prerelease": "next" }
5
+ ],
6
+ "plugins": [
7
+ "@semantic-release/commit-analyzer",
8
+ "@semantic-release/release-notes-generator",
9
+ "@semantic-release/npm",
10
+ "@semantic-release/git"
11
+ ]
12
+ }
package/CLAUDE.md ADDED
@@ -0,0 +1,25 @@
1
+ # Instructions Claude Code — traquiste-mobile
2
+
3
+ ## Stack
4
+ Expo + TypeScript strict + StyleSheet natif. Zéro lib externe de styling.
5
+
6
+ ## Conventions
7
+ - Commentaires en anglais, style concis
8
+ - /** Description composant */ en haut de chaque fichier
9
+ - Props documentées inline /** description */
10
+
11
+ ## Commits
12
+ Convention semantic-release : feat / fix / chore / docs / test
13
+
14
+ ## Tests
15
+ Jest + @testing-library/react-native.
16
+ Fichiers de test colocalisés : `ComponentName.test.tsx` dans le même dossier que le composant.
17
+ Lancer : `npm test -- --watchAll=false`
18
+
19
+ ## Storybook
20
+ Local uniquement. Stories générées depuis le code du composant.
21
+ Format : même argTypes que traquiste-web (radio pour unions, boolean pour booléens).
22
+
23
+ ## Doc Next.js
24
+ Une page par composant dans docs/pages/components/.
25
+ Playground interactif + éditeur code live bidirectionnel + props table.
package/README.md ADDED
@@ -0,0 +1,124 @@
1
+
2
+ # @situaction/traquiste-mobile
3
+
4
+ React Native UI component library for Traquiste — built with Expo + TypeScript strict + native StyleSheet.
5
+
6
+ ## Requirements
7
+
8
+ - Node.js >= 18
9
+ - Xcode (iOS)
10
+ - CocoaPods
11
+
12
+ ## Installation
13
+
14
+ ```sh
15
+ npm install @situaction/traquiste-mobile
16
+ ```
17
+
18
+ Peer dependencies required in your project:
19
+
20
+ ```sh
21
+ npm install expo react react-native
22
+ ```
23
+
24
+ ---
25
+
26
+ ## Development
27
+
28
+ ### 1. Clone and install
29
+
30
+ ```sh
31
+ git clone git@bitbucket.org:situaction/traquiste-mobile.git
32
+ cd traquiste-mobile
33
+ npm install
34
+ cd example && npm install --legacy-peer-deps && cd ..
35
+ ```
36
+
37
+ ### 2. Build the library
38
+
39
+ ```sh
40
+ npm run build
41
+ ```
42
+
43
+ ### 3. First time — build the native binary
44
+
45
+ The `example/ios/` directory is not committed and must be generated locally.
46
+
47
+ ```sh
48
+ cd example
49
+
50
+ # iOS simulator
51
+ npx expo run:ios
52
+
53
+ # iOS device (connect via USB)
54
+ npx expo run:ios --device
55
+ ```
56
+
57
+ > Rebuild required each time a native dependency is added.
58
+
59
+ ### 4. Run tests
60
+
61
+ ```sh
62
+ npm test
63
+ ```
64
+
65
+ Tests run with Jest + `@testing-library/react-native`. Use `--watchAll=false` for a single run (e.g. in CI):
66
+
67
+ ```sh
68
+ npm test -- --watchAll=false
69
+ ```
70
+
71
+ Test files live in `src/` alongside their components: `ComponentName.test.tsx`.
72
+
73
+ ### 5. Run Storybook
74
+
75
+ ```sh
76
+ npm run storybook
77
+ ```
78
+
79
+ Storybook runs directly on the simulator/device — not in a browser. Open the `TraquisteMobileExample` app on your device to see the Storybook UI.
80
+
81
+ Any change in `src/` is reflected instantly via hot reload.
82
+
83
+ > If port 8081 is already in use, Metro will prompt to use another port. Update the bundle location in the app dev menu (shake device → **Change Bundle Location**).
84
+
85
+ ---
86
+
87
+ ## Scripts
88
+
89
+ | Command | Description |
90
+ | -------- | ----------- |
91
+ | `npm run build` | Compile TypeScript to `build/` |
92
+ | `npm run lint` | Type-check without emitting |
93
+ | `npm test` | Run Jest tests |
94
+ | `npm run storybook` | Start Storybook on simulator/device |
95
+
96
+ ## Versioning
97
+
98
+ Releases are automated via [semantic-release](https://semantic-release.gitbook.io/) on push to `master` and `develop`.
99
+
100
+ Commit convention:
101
+
102
+ | Prefix | Effect |
103
+ | ------ | ------- |
104
+ | `feat:` | Minor release (1.x.0) |
105
+ | `fix:` | Patch release (1.0.x) |
106
+ | `feat!:` / `BREAKING CHANGE` | Major release (x.0.0) |
107
+ | `chore:` / `docs:` / `test:` | No release |
108
+
109
+ Branches:
110
+
111
+ - `master` → published as `latest` on npm
112
+ - `develop` → published as `next` on npm (prerelease)
113
+
114
+ ## Stack
115
+
116
+ - Expo SDK 55 / React Native 0.83.6 / React 19.2
117
+ - TypeScript strict
118
+ - Storybook React Native v10
119
+ - semantic-release + Bitbucket Pipelines
120
+ - Zero external styling libraries
121
+
122
+ ## License
123
+
124
+ MIT
package/app.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "ios": {
3
+ "bundleIdentifier": "com.chloe-gueret.-situactiontraquiste-mobile"
4
+ }
5
+ }
@@ -0,0 +1,81 @@
1
+ image: node:22
2
+
3
+ definitions:
4
+ caches:
5
+ npm: ~/.npm
6
+
7
+ steps:
8
+ - step: &build
9
+ name: Build
10
+ caches: [npm]
11
+ script:
12
+ - npm ci --ignore-scripts
13
+ - npm run build
14
+ artifacts:
15
+ - build/**
16
+
17
+ - step: &test
18
+ name: Test
19
+ caches: [npm]
20
+ script:
21
+ - npm ci --ignore-scripts
22
+ - npm test -- --ci --passWithNoTests
23
+
24
+ - step: &build-docs
25
+ name: Build Docs
26
+ caches: [npm]
27
+ script:
28
+ - npm ci --ignore-scripts
29
+ - cd docs && npm ci --ignore-scripts && npm run build
30
+ artifacts:
31
+ - docs/dist/**
32
+
33
+ - step: &deploy-docs
34
+ name: Deploy Docs
35
+ clone:
36
+ enabled: false
37
+ script:
38
+ - pipe: atlassian/aws-s3-deploy:1.6.0
39
+ variables:
40
+ AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
41
+ AWS_SECRET_ACCESS_KEY: $AWS_SECRET_KEY
42
+ AWS_DEFAULT_REGION: "eu-west-3"
43
+ S3_BUCKET: $DOCS_S3_BUCKET
44
+ LOCAL_PATH: 'docs/dist'
45
+ DELETE_FLAG: 'true'
46
+ - pipe: atlassian/aws-cloudfront-invalidate:0.6.0
47
+ variables:
48
+ AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
49
+ AWS_SECRET_ACCESS_KEY: $AWS_SECRET_KEY
50
+ AWS_DEFAULT_REGION: "eu-west-3"
51
+ DISTRIBUTION_ID: $CLOUDFRONT_DISTRIBUTION_ID
52
+
53
+ - step: &publish
54
+ name: Publish
55
+ trigger: manual
56
+ script:
57
+ - npm ci --ignore-scripts
58
+ - npx semantic-release
59
+
60
+ pipelines:
61
+ pull-requests:
62
+ '**':
63
+ - step: *build
64
+ - step: *test
65
+
66
+ branches:
67
+ master:
68
+ - step: *build
69
+ - step: *test
70
+ - step:
71
+ <<: *build-docs
72
+ deployment: Production
73
+ - step:
74
+ <<: *deploy-docs
75
+ deployment: Production_AWS
76
+ - step: *publish
77
+
78
+ develop:
79
+ - step: *build
80
+ - step: *test
81
+ - step: *publish
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Button component for Traq[UI]ste Mobile.
3
+ * Supports four variants, four sizes and three content layouts.
4
+ */
5
+ import React from 'react';
6
+ import type { StyleProp, ViewStyle } from 'react-native';
7
+ export type ButtonVariant = 'primary' | 'tertiary' | 'ghost' | 'destructive';
8
+ export type ButtonSize = 'S' | 'M' | 'L' | 'XL';
9
+ export type ButtonContent = 'icon-only' | 'icon-only-rounded' | 'icon-both';
10
+ export interface ButtonProps {
11
+ /** Button visual variant */
12
+ variant?: ButtonVariant;
13
+ /** Button size */
14
+ size?: ButtonSize;
15
+ /** Content layout */
16
+ content?: ButtonContent;
17
+ /** Label text — required when content is 'icon-both' */
18
+ label?: string;
19
+ /** Left icon component (Phosphor icon) */
20
+ iconLeft?: React.ReactElement;
21
+ /** Right icon component (Phosphor icon) */
22
+ iconRight?: React.ReactElement;
23
+ /** Disabled state */
24
+ disabled?: boolean;
25
+ /** Press handler */
26
+ onPress?: () => void;
27
+ /** Additional container styles */
28
+ style?: StyleProp<ViewStyle>;
29
+ }
30
+ export declare function Button({ variant, size, content, label, iconLeft, iconRight, disabled, onPress, style, }: ButtonProps): React.JSX.Element;
31
+ //# sourceMappingURL=Button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/components/Button/Button.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,GAAG,aAAa,CAAC;AAC7E,MAAM,MAAM,UAAU,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC;AAChD,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,mBAAmB,GAAG,WAAW,CAAC;AAE5E,MAAM,WAAW,WAAW;IAC1B,4BAA4B;IAC5B,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,kBAAkB;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,qBAAqB;IACrB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC;IAC9B,2CAA2C;IAC3C,SAAS,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC;IAC/B,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,kCAAkC;IAClC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B;AAaD,wBAAgB,MAAM,CAAC,EACrB,OAAmB,EACnB,IAAU,EACV,OAAqB,EACrB,KAAK,EACL,QAAQ,EACR,SAAS,EACT,QAAgB,EAChB,OAAO,EACP,KAAK,GACN,EAAE,WAAW,qBAwEb"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Button component for Traq[UI]ste Mobile.
3
+ * Supports four variants, four sizes and three content layouts.
4
+ */
5
+ import React, { useState } from 'react';
6
+ import { Pressable, Text } from 'react-native';
7
+ import { useTheme } from '../../context/ThemeContext';
8
+ // --- Size tokens (static, theme-independent) ---
9
+ const SIZE_TOKENS = {
10
+ S: { height: 36, paddingVertical: 10, paddingHorizontal: 10, gap: 8, borderRadius: 8, iconSize: 16, fontSize: 12, lineHeight: 16 },
11
+ M: { height: 40, paddingVertical: 10, paddingHorizontal: 16, gap: 4, borderRadius: 8, iconSize: 18, fontSize: 14, lineHeight: 20 },
12
+ L: { height: 48, paddingVertical: 12, paddingHorizontal: 12, gap: 10, borderRadius: 8, iconSize: 20, fontSize: 16, lineHeight: 24 },
13
+ XL: { height: 60, paddingVertical: 16, paddingHorizontal: 32, gap: 12, borderRadius: 8, iconSize: 24, fontSize: 18, lineHeight: 26 },
14
+ };
15
+ // --- Component ---
16
+ export function Button({ variant = 'primary', size = 'M', content = 'icon-both', label, iconLeft, iconRight, disabled = false, onPress, style, }) {
17
+ const [pressed, setPressed] = useState(false);
18
+ const { colors } = useTheme();
19
+ const sizeTokens = SIZE_TOKENS[size];
20
+ const state = disabled ? 'disabled' : pressed ? 'pressed' : 'default';
21
+ const colorTokens = colors.button[variant][state];
22
+ const isIconOnly = content === 'icon-only' || content === 'icon-only-rounded';
23
+ const borderRadius = content === 'icon-only-rounded' ? 9999 : sizeTokens.borderRadius;
24
+ const hasBorder = colorTokens.border !== 'transparent';
25
+ const containerStyle = {
26
+ height: sizeTokens.height,
27
+ paddingVertical: isIconOnly ? undefined : sizeTokens.paddingVertical,
28
+ paddingHorizontal: isIconOnly ? undefined : sizeTokens.paddingHorizontal,
29
+ width: isIconOnly ? sizeTokens.height : undefined,
30
+ borderRadius,
31
+ gap: sizeTokens.gap,
32
+ backgroundColor: colorTokens.background,
33
+ borderWidth: hasBorder ? 1 : undefined,
34
+ borderColor: hasBorder ? colorTokens.border : undefined,
35
+ alignItems: 'center',
36
+ justifyContent: 'center',
37
+ flexDirection: 'row',
38
+ };
39
+ const textStyle = {
40
+ color: colorTokens.text,
41
+ fontSize: sizeTokens.fontSize,
42
+ lineHeight: sizeTokens.lineHeight,
43
+ fontFamily: 'Urbanist',
44
+ fontWeight: '500',
45
+ };
46
+ // Clone icon elements to inject size and color from active theme state
47
+ const cloneIcon = (icon) => {
48
+ if (!icon)
49
+ return null;
50
+ return React.cloneElement(icon, {
51
+ size: sizeTokens.iconSize,
52
+ color: colorTokens.icon,
53
+ ...icon.props,
54
+ });
55
+ };
56
+ if (isIconOnly) {
57
+ return (<Pressable pointerEvents={disabled ? 'none' : 'auto'} onPressIn={() => setPressed(true)} onPressOut={() => setPressed(false)} onPress={disabled ? undefined : onPress} style={[containerStyle, style]}>
58
+ {cloneIcon(iconLeft)}
59
+ </Pressable>);
60
+ }
61
+ return (<Pressable pointerEvents={disabled ? 'none' : 'auto'} onPressIn={() => setPressed(true)} onPressOut={() => setPressed(false)} onPress={disabled ? undefined : onPress} style={[containerStyle, style]}>
62
+ {cloneIcon(iconLeft)}
63
+ {label != null && <Text style={textStyle}>{label}</Text>}
64
+ {cloneIcon(iconRight)}
65
+ </Pressable>);
66
+ }
67
+ //# sourceMappingURL=Button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../src/components/Button/Button.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * Button component for Traq[UI]ste Mobile.\n * Supports four variants, four sizes and three content layouts.\n */\nimport React, { useState } from 'react';\nimport { Pressable, Text } from 'react-native';\nimport type { StyleProp, ViewStyle } from 'react-native';\nimport { useTheme } from '../../context/ThemeContext';\n\nexport type ButtonVariant = 'primary' | 'tertiary' | 'ghost' | 'destructive';\nexport type ButtonSize = 'S' | 'M' | 'L' | 'XL';\nexport type ButtonContent = 'icon-only' | 'icon-only-rounded' | 'icon-both';\n\nexport interface ButtonProps {\n /** Button visual variant */\n variant?: ButtonVariant;\n /** Button size */\n size?: ButtonSize;\n /** Content layout */\n content?: ButtonContent;\n /** Label text — required when content is 'icon-both' */\n label?: string;\n /** Left icon component (Phosphor icon) */\n iconLeft?: React.ReactElement;\n /** Right icon component (Phosphor icon) */\n iconRight?: React.ReactElement;\n /** Disabled state */\n disabled?: boolean;\n /** Press handler */\n onPress?: () => void;\n /** Additional container styles */\n style?: StyleProp<ViewStyle>;\n}\n\n// --- Size tokens (static, theme-independent) ---\n\nconst SIZE_TOKENS = {\n S: { height: 36, paddingVertical: 10, paddingHorizontal: 10, gap: 8, borderRadius: 8, iconSize: 16, fontSize: 12, lineHeight: 16 },\n M: { height: 40, paddingVertical: 10, paddingHorizontal: 16, gap: 4, borderRadius: 8, iconSize: 18, fontSize: 14, lineHeight: 20 },\n L: { height: 48, paddingVertical: 12, paddingHorizontal: 12, gap: 10, borderRadius: 8, iconSize: 20, fontSize: 16, lineHeight: 24 },\n XL: { height: 60, paddingVertical: 16, paddingHorizontal: 32, gap: 12, borderRadius: 8, iconSize: 24, fontSize: 18, lineHeight: 26 },\n} as const;\n\n// --- Component ---\n\nexport function Button({\n variant = 'primary',\n size = 'M',\n content = 'icon-both',\n label,\n iconLeft,\n iconRight,\n disabled = false,\n onPress,\n style,\n}: ButtonProps) {\n const [pressed, setPressed] = useState(false);\n const { colors } = useTheme();\n\n const sizeTokens = SIZE_TOKENS[size];\n const state = disabled ? 'disabled' : pressed ? 'pressed' : 'default';\n const colorTokens = colors.button[variant][state];\n\n const isIconOnly = content === 'icon-only' || content === 'icon-only-rounded';\n const borderRadius = content === 'icon-only-rounded' ? 9999 : sizeTokens.borderRadius;\n const hasBorder = colorTokens.border !== 'transparent';\n\n const containerStyle: ViewStyle = {\n height: sizeTokens.height,\n paddingVertical: isIconOnly ? undefined : sizeTokens.paddingVertical,\n paddingHorizontal: isIconOnly ? undefined : sizeTokens.paddingHorizontal,\n width: isIconOnly ? sizeTokens.height : undefined,\n borderRadius,\n gap: sizeTokens.gap,\n backgroundColor: colorTokens.background,\n borderWidth: hasBorder ? 1 : undefined,\n borderColor: hasBorder ? colorTokens.border : undefined,\n alignItems: 'center',\n justifyContent: 'center',\n flexDirection: 'row',\n };\n\n const textStyle = {\n color: colorTokens.text,\n fontSize: sizeTokens.fontSize,\n lineHeight: sizeTokens.lineHeight,\n fontFamily: 'Urbanist',\n fontWeight: '500' as const,\n };\n\n // Clone icon elements to inject size and color from active theme state\n const cloneIcon = (icon: React.ReactElement | undefined) => {\n if (!icon) return null;\n return React.cloneElement(icon, {\n size: sizeTokens.iconSize,\n color: colorTokens.icon,\n ...(icon.props as Record<string, unknown>),\n } as object);\n };\n\n if (isIconOnly) {\n return (\n <Pressable\n pointerEvents={disabled ? 'none' : 'auto'}\n onPressIn={() => setPressed(true)}\n onPressOut={() => setPressed(false)}\n onPress={disabled ? undefined : onPress}\n style={[containerStyle, style]}\n >\n {cloneIcon(iconLeft)}\n </Pressable>\n );\n }\n\n return (\n <Pressable\n pointerEvents={disabled ? 'none' : 'auto'}\n onPressIn={() => setPressed(true)}\n onPressOut={() => setPressed(false)}\n onPress={disabled ? undefined : onPress}\n style={[containerStyle, style]}\n >\n {cloneIcon(iconLeft)}\n {label != null && <Text style={textStyle}>{label}</Text>}\n {cloneIcon(iconRight)}\n </Pressable>\n );\n}"]}
@@ -0,0 +1,19 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-native';
2
+ import { type ButtonProps } from './Button';
3
+ type StoryArgs = ButtonProps & {
4
+ colorScheme: 'light' | 'dark';
5
+ };
6
+ declare const meta: Meta<StoryArgs>;
7
+ export default meta;
8
+ type Story = StoryObj<StoryArgs>;
9
+ export declare const Primary: Story;
10
+ export declare const Tertiary: Story;
11
+ export declare const Ghost: Story;
12
+ export declare const Destructive: Story;
13
+ export declare const WithIconLeft: Story;
14
+ export declare const WithIconRight: Story;
15
+ export declare const WithIconBoth: Story;
16
+ export declare const IconOnly: Story;
17
+ export declare const AllSizes: Story;
18
+ export declare const Disabled: Story;
19
+ //# sourceMappingURL=Button.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.stories.d.ts","sourceRoot":"","sources":["../../../src/components/Button/Button.stories.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAG9D,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAEpD,KAAK,SAAS,GAAG,WAAW,GAAG;IAAE,WAAW,EAAE,OAAO,GAAG,MAAM,CAAA;CAAE,CAAC;AAEjE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS,CA+BzB,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;AAEjC,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAEnB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAS1B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAO3B,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAO1B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAStB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAStB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAStB,CAAC"}
@@ -0,0 +1,95 @@
1
+ /** Storybook stories for the Button component */
2
+ import React from 'react';
3
+ import { View } from 'react-native';
4
+ import { ArrowRight, Check, Trash, Plus, X, MagnifyingGlass } from 'phosphor-react-native';
5
+ import { Button } from './Button';
6
+ const meta = {
7
+ title: 'Components/Button',
8
+ component: Button,
9
+ render: ({ colorScheme: _colorScheme, ...args }) => <Button {...args}/>,
10
+ argTypes: {
11
+ colorScheme: {
12
+ control: { type: 'radio' },
13
+ options: ['light', 'dark'],
14
+ },
15
+ variant: {
16
+ control: { type: 'radio' },
17
+ options: ['primary', 'tertiary', 'ghost', 'destructive'],
18
+ },
19
+ size: {
20
+ control: { type: 'radio' },
21
+ options: ['S', 'M', 'L', 'XL'],
22
+ },
23
+ content: {
24
+ control: { type: 'radio' },
25
+ options: ['icon-only', 'icon-only-rounded', 'icon-both'],
26
+ },
27
+ disabled: { control: { type: 'boolean' } },
28
+ },
29
+ args: {
30
+ colorScheme: 'light',
31
+ label: 'Button',
32
+ variant: 'primary',
33
+ size: 'M',
34
+ content: 'icon-both',
35
+ disabled: false,
36
+ },
37
+ };
38
+ export default meta;
39
+ export const Primary = {
40
+ args: { variant: 'primary', label: 'Primary' },
41
+ };
42
+ export const Tertiary = {
43
+ args: { variant: 'tertiary', label: 'Tertiary' },
44
+ };
45
+ export const Ghost = {
46
+ args: { variant: 'ghost', label: 'Ghost' },
47
+ };
48
+ export const Destructive = {
49
+ args: { variant: 'destructive', label: 'Destructive' },
50
+ };
51
+ export const WithIconLeft = {
52
+ render: () => (<View style={{ gap: 12, padding: 16, alignItems: 'flex-start' }}>
53
+ <Button variant="primary" label="Rechercher" iconLeft={<MagnifyingGlass />}/>
54
+ <Button variant="tertiary" label="Ajouter" iconLeft={<Plus />}/>
55
+ <Button variant="ghost" label="Confirmer" iconLeft={<Check />}/>
56
+ <Button variant="destructive" label="Supprimer" iconLeft={<Trash />}/>
57
+ </View>),
58
+ };
59
+ export const WithIconRight = {
60
+ render: () => (<View style={{ gap: 12, padding: 16, alignItems: 'flex-start' }}>
61
+ <Button variant="primary" label="Suivant" iconRight={<ArrowRight />}/>
62
+ <Button variant="tertiary" label="Fermer" iconRight={<X />}/>
63
+ </View>),
64
+ };
65
+ export const WithIconBoth = {
66
+ render: () => (<View style={{ gap: 12, padding: 16, alignItems: 'flex-start' }}>
67
+ <Button variant="primary" label="Rechercher" iconLeft={<MagnifyingGlass />} iconRight={<ArrowRight />}/>
68
+ <Button variant="tertiary" label="Supprimer" iconLeft={<Trash />} iconRight={<X />}/>
69
+ </View>),
70
+ };
71
+ export const IconOnly = {
72
+ render: () => (<View style={{ flexDirection: 'row', gap: 12, padding: 16 }}>
73
+ <Button variant="primary" content="icon-only" iconLeft={<Plus />}/>
74
+ <Button variant="tertiary" content="icon-only" iconLeft={<MagnifyingGlass />}/>
75
+ <Button variant="ghost" content="icon-only" iconLeft={<X />}/>
76
+ <Button variant="destructive" content="icon-only-rounded" iconLeft={<Trash />}/>
77
+ </View>),
78
+ };
79
+ export const AllSizes = {
80
+ render: () => (<View style={{ gap: 12, padding: 16, alignItems: 'flex-start' }}>
81
+ <Button variant="primary" size="S" label="Small" iconLeft={<Check />}/>
82
+ <Button variant="primary" size="M" label="Medium" iconLeft={<Check />}/>
83
+ <Button variant="primary" size="L" label="Large" iconLeft={<Check />}/>
84
+ <Button variant="primary" size="XL" label="XLarge" iconLeft={<Check />}/>
85
+ </View>),
86
+ };
87
+ export const Disabled = {
88
+ render: () => (<View style={{ gap: 12, padding: 16, alignItems: 'flex-start' }}>
89
+ <Button variant="primary" disabled label="Primary" iconLeft={<Check />}/>
90
+ <Button variant="tertiary" disabled label="Tertiary" iconLeft={<Check />}/>
91
+ <Button variant="ghost" disabled label="Ghost" iconLeft={<Check />}/>
92
+ <Button variant="destructive" disabled label="Destructive" iconLeft={<Trash />}/>
93
+ </View>),
94
+ };
95
+ //# sourceMappingURL=Button.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.stories.js","sourceRoot":"","sources":["../../../src/components/Button/Button.stories.tsx"],"names":[],"mappings":"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","sourcesContent":["/** Storybook stories for the Button component */\nimport React from 'react';\nimport type { Meta, StoryObj } from '@storybook/react-native';\nimport { View } from 'react-native';\nimport { ArrowRight, Check, Trash, Plus, X, MagnifyingGlass } from 'phosphor-react-native';\nimport { Button, type ButtonProps } from './Button';\n\ntype StoryArgs = ButtonProps & { colorScheme: 'light' | 'dark' };\n\nconst meta: Meta<StoryArgs> = {\n title: 'Components/Button',\n component: Button,\n render: ({ colorScheme: _colorScheme, ...args }) => <Button {...args} />,\n argTypes: {\n colorScheme: {\n control: { type: 'radio' },\n options: ['light', 'dark'],\n },\n variant: {\n control: { type: 'radio' },\n options: ['primary', 'tertiary', 'ghost', 'destructive'],\n },\n size: {\n control: { type: 'radio' },\n options: ['S', 'M', 'L', 'XL'],\n },\n content: {\n control: { type: 'radio' },\n options: ['icon-only', 'icon-only-rounded', 'icon-both'],\n },\n disabled: { control: { type: 'boolean' } },\n },\n args: {\n colorScheme: 'light',\n label: 'Button',\n variant: 'primary',\n size: 'M',\n content: 'icon-both',\n disabled: false,\n },\n};\n\nexport default meta;\n\ntype Story = StoryObj<StoryArgs>;\n\nexport const Primary: Story = {\n args: { variant: 'primary', label: 'Primary' },\n};\n\nexport const Tertiary: Story = {\n args: { variant: 'tertiary', label: 'Tertiary' },\n};\n\nexport const Ghost: Story = {\n args: { variant: 'ghost', label: 'Ghost' },\n};\n\nexport const Destructive: Story = {\n args: { variant: 'destructive', label: 'Destructive' },\n};\n\nexport const WithIconLeft: Story = {\n render: () => (\n <View style={{ gap: 12, padding: 16, alignItems: 'flex-start' }}>\n <Button variant=\"primary\" label=\"Rechercher\" iconLeft={<MagnifyingGlass />} />\n <Button variant=\"tertiary\" label=\"Ajouter\" iconLeft={<Plus />} />\n <Button variant=\"ghost\" label=\"Confirmer\" iconLeft={<Check />} />\n <Button variant=\"destructive\" label=\"Supprimer\" iconLeft={<Trash />} />\n </View>\n ),\n};\n\nexport const WithIconRight: Story = {\n render: () => (\n <View style={{ gap: 12, padding: 16, alignItems: 'flex-start' }}>\n <Button variant=\"primary\" label=\"Suivant\" iconRight={<ArrowRight />} />\n <Button variant=\"tertiary\" label=\"Fermer\" iconRight={<X />} />\n </View>\n ),\n};\n\nexport const WithIconBoth: Story = {\n render: () => (\n <View style={{ gap: 12, padding: 16, alignItems: 'flex-start' }}>\n <Button variant=\"primary\" label=\"Rechercher\" iconLeft={<MagnifyingGlass />} iconRight={<ArrowRight />} />\n <Button variant=\"tertiary\" label=\"Supprimer\" iconLeft={<Trash />} iconRight={<X />} />\n </View>\n ),\n};\n\nexport const IconOnly: Story = {\n render: () => (\n <View style={{ flexDirection: 'row', gap: 12, padding: 16 }}>\n <Button variant=\"primary\" content=\"icon-only\" iconLeft={<Plus />} />\n <Button variant=\"tertiary\" content=\"icon-only\" iconLeft={<MagnifyingGlass />} />\n <Button variant=\"ghost\" content=\"icon-only\" iconLeft={<X />} />\n <Button variant=\"destructive\" content=\"icon-only-rounded\" iconLeft={<Trash />} />\n </View>\n ),\n};\n\nexport const AllSizes: Story = {\n render: () => (\n <View style={{ gap: 12, padding: 16, alignItems: 'flex-start' }}>\n <Button variant=\"primary\" size=\"S\" label=\"Small\" iconLeft={<Check />} />\n <Button variant=\"primary\" size=\"M\" label=\"Medium\" iconLeft={<Check />} />\n <Button variant=\"primary\" size=\"L\" label=\"Large\" iconLeft={<Check />} />\n <Button variant=\"primary\" size=\"XL\" label=\"XLarge\" iconLeft={<Check />} />\n </View>\n ),\n};\n\nexport const Disabled: Story = {\n render: () => (\n <View style={{ gap: 12, padding: 16, alignItems: 'flex-start' }}>\n <Button variant=\"primary\" disabled label=\"Primary\" iconLeft={<Check />} />\n <Button variant=\"tertiary\" disabled label=\"Tertiary\" iconLeft={<Check />} />\n <Button variant=\"ghost\" disabled label=\"Ghost\" iconLeft={<Check />} />\n <Button variant=\"destructive\" disabled label=\"Destructive\" iconLeft={<Trash />} />\n </View>\n ),\n};"]}
@@ -0,0 +1,3 @@
1
+ export { Button } from './Button';
2
+ export type { ButtonProps, ButtonVariant, ButtonSize, ButtonContent } from './Button';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Button/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { Button } from './Button';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Button/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC","sourcesContent":["export { Button } from './Button';\nexport type { ButtonProps, ButtonVariant, ButtonSize, ButtonContent } from './Button';"]}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * ButtonAction component — bare icon-only pressable with no background or border.
3
+ * Extends Button size range with XS and XXL sizes.
4
+ */
5
+ import React from 'react';
6
+ import type { StyleProp, ViewStyle } from 'react-native';
7
+ export type ButtonActionSize = 'XS' | 'S' | 'M' | 'L' | 'XL' | 'XXL';
8
+ export interface ButtonActionProps {
9
+ /** Icon component (Phosphor Duotone) */
10
+ icon: React.ReactElement;
11
+ /** Icon size */
12
+ size?: ButtonActionSize;
13
+ /** Disabled state */
14
+ disabled?: boolean;
15
+ /** Press handler */
16
+ onPress?: () => void;
17
+ /** Additional container styles */
18
+ style?: StyleProp<ViewStyle>;
19
+ }
20
+ export declare function ButtonAction({ icon, size, disabled, onPress, style, }: ButtonActionProps): React.JSX.Element;
21
+ //# sourceMappingURL=ButtonAction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonAction.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonAction/ButtonAction.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzD,MAAM,MAAM,gBAAgB,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,KAAK,CAAC;AAErE,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC;IACzB,gBAAgB;IAChB,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,kCAAkC;IAClC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B;AAWD,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,IAAU,EACV,QAAgB,EAChB,OAAO,EACP,KAAK,GACN,EAAE,iBAAiB,qBA2BnB"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * ButtonAction component — bare icon-only pressable with no background or border.
3
+ * Extends Button size range with XS and XXL sizes.
4
+ */
5
+ import React from 'react';
6
+ import { Pressable } from 'react-native';
7
+ import { useTheme } from '../../context/ThemeContext';
8
+ const ICON_SIZE = {
9
+ XS: 12,
10
+ S: 16,
11
+ M: 20,
12
+ L: 24,
13
+ XL: 28,
14
+ XXL: 32,
15
+ };
16
+ export function ButtonAction({ icon, size = 'M', disabled = false, onPress, style, }) {
17
+ const { colors } = useTheme();
18
+ const iconPx = ICON_SIZE[size];
19
+ const containerStyle = {
20
+ width: iconPx,
21
+ height: iconPx,
22
+ opacity: disabled ? 0.5 : 1,
23
+ alignItems: 'center',
24
+ justifyContent: 'center',
25
+ };
26
+ const clonedIcon = React.cloneElement(icon, {
27
+ size: iconPx,
28
+ color: colors.text.primary,
29
+ ...icon.props,
30
+ });
31
+ return (<Pressable pointerEvents={disabled ? 'none' : 'auto'} onPress={disabled ? undefined : onPress} style={[containerStyle, style]}>
32
+ {clonedIcon}
33
+ </Pressable>);
34
+ }
35
+ //# sourceMappingURL=ButtonAction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonAction.js","sourceRoot":"","sources":["../../../src/components/ButtonAction/ButtonAction.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAiBtD,MAAM,SAAS,GAAqC;IAClD,EAAE,EAAG,EAAE;IACP,CAAC,EAAI,EAAE;IACP,CAAC,EAAI,EAAE;IACP,CAAC,EAAI,EAAE;IACP,EAAE,EAAG,EAAE;IACP,GAAG,EAAE,EAAE;CACR,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,EAC3B,IAAI,EACJ,IAAI,GAAG,GAAG,EACV,QAAQ,GAAG,KAAK,EAChB,OAAO,EACP,KAAK,GACa;IAClB,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE/B,MAAM,cAAc,GAAc;QAChC,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3B,UAAU,EAAE,QAAQ;QACpB,cAAc,EAAE,QAAQ;KACzB,CAAC;IAEF,MAAM,UAAU,GAAG,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE;QAC1C,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO;QAC1B,GAAI,IAAI,CAAC,KAAiC;KACjC,CAAC,CAAC;IAEb,OAAO,CACL,CAAC,SAAS,CACR,aAAa,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAC1C,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CACxC,KAAK,CAAC,CAAC,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,CAE/B;MAAA,CAAC,UAAU,CACb;IAAA,EAAE,SAAS,CAAC,CACb,CAAC;AACJ,CAAC","sourcesContent":["/**\n * ButtonAction component — bare icon-only pressable with no background or border.\n * Extends Button size range with XS and XXL sizes.\n */\nimport React from 'react';\nimport { Pressable } from 'react-native';\nimport type { StyleProp, ViewStyle } from 'react-native';\nimport { useTheme } from '../../context/ThemeContext';\n\nexport type ButtonActionSize = 'XS' | 'S' | 'M' | 'L' | 'XL' | 'XXL';\n\nexport interface ButtonActionProps {\n /** Icon component (Phosphor Duotone) */\n icon: React.ReactElement;\n /** Icon size */\n size?: ButtonActionSize;\n /** Disabled state */\n disabled?: boolean;\n /** Press handler */\n onPress?: () => void;\n /** Additional container styles */\n style?: StyleProp<ViewStyle>;\n}\n\nconst ICON_SIZE: Record<ButtonActionSize, number> = {\n XS: 12,\n S: 16,\n M: 20,\n L: 24,\n XL: 28,\n XXL: 32,\n};\n\nexport function ButtonAction({\n icon,\n size = 'M',\n disabled = false,\n onPress,\n style,\n}: ButtonActionProps) {\n const { colors } = useTheme();\n const iconPx = ICON_SIZE[size];\n\n const containerStyle: ViewStyle = {\n width: iconPx,\n height: iconPx,\n opacity: disabled ? 0.5 : 1,\n alignItems: 'center',\n justifyContent: 'center',\n };\n\n const clonedIcon = React.cloneElement(icon, {\n size: iconPx,\n color: colors.text.primary,\n ...(icon.props as Record<string, unknown>),\n } as object);\n\n return (\n <Pressable\n pointerEvents={disabled ? 'none' : 'auto'}\n onPress={disabled ? undefined : onPress}\n style={[containerStyle, style]}\n >\n {clonedIcon}\n </Pressable>\n );\n}"]}
@@ -0,0 +1,13 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-native';
2
+ import { type ButtonActionProps } from './ButtonAction';
3
+ type StoryArgs = ButtonActionProps & {
4
+ colorScheme: 'light' | 'dark';
5
+ };
6
+ declare const meta: Meta<StoryArgs>;
7
+ export default meta;
8
+ type Story = StoryObj<StoryArgs>;
9
+ export declare const Default: Story;
10
+ export declare const Disabled: Story;
11
+ export declare const AllSizes: Story;
12
+ export declare const AllIcons: Story;
13
+ //# sourceMappingURL=ButtonAction.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonAction.stories.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonAction/ButtonAction.stories.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAG9D,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEtE,KAAK,SAAS,GAAG,iBAAiB,GAAG;IAAE,WAAW,EAAE,OAAO,GAAG,MAAM,CAAA;CAAE,CAAC;AAEvE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS,CAsBzB,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;AAEjC,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAWtB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC"}