@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
@@ -0,0 +1,51 @@
1
+ /** Storybook stories for the ButtonAction component */
2
+ import React from 'react';
3
+ import { View } from 'react-native';
4
+ import { X, DotsThree, ArrowLeft, MagnifyingGlass, Bell } from 'phosphor-react-native';
5
+ import { ButtonAction } from './ButtonAction';
6
+ const meta = {
7
+ title: 'Components/ButtonAction',
8
+ component: ButtonAction,
9
+ render: ({ colorScheme: _colorScheme, ...args }) => (<ButtonAction {...args} icon={<X />}/>),
10
+ argTypes: {
11
+ colorScheme: {
12
+ control: { type: 'radio' },
13
+ options: ['light', 'dark'],
14
+ },
15
+ size: {
16
+ control: { type: 'radio' },
17
+ options: ['XS', 'S', 'M', 'L', 'XL', 'XXL'],
18
+ },
19
+ disabled: { control: { type: 'boolean' } },
20
+ },
21
+ args: {
22
+ colorScheme: 'light',
23
+ size: 'M',
24
+ disabled: false,
25
+ },
26
+ };
27
+ export default meta;
28
+ export const Default = {};
29
+ export const Disabled = {
30
+ args: { disabled: true },
31
+ };
32
+ export const AllSizes = {
33
+ render: () => (<View style={{ flexDirection: 'row', gap: 16, padding: 16, alignItems: 'center' }}>
34
+ <ButtonAction size="XS" icon={<X />}/>
35
+ <ButtonAction size="S" icon={<X />}/>
36
+ <ButtonAction size="M" icon={<X />}/>
37
+ <ButtonAction size="L" icon={<X />}/>
38
+ <ButtonAction size="XL" icon={<X />}/>
39
+ <ButtonAction size="XXL" icon={<X />}/>
40
+ </View>),
41
+ };
42
+ export const AllIcons = {
43
+ render: () => (<View style={{ flexDirection: 'row', gap: 16, padding: 16, alignItems: 'center' }}>
44
+ <ButtonAction size="L" icon={<ArrowLeft />}/>
45
+ <ButtonAction size="L" icon={<MagnifyingGlass />}/>
46
+ <ButtonAction size="L" icon={<Bell />}/>
47
+ <ButtonAction size="L" icon={<DotsThree />}/>
48
+ <ButtonAction size="L" icon={<X />}/>
49
+ </View>),
50
+ };
51
+ //# sourceMappingURL=ButtonAction.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonAction.stories.js","sourceRoot":"","sources":["../../../src/components/ButtonAction/ButtonAction.stories.tsx"],"names":[],"mappings":"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","sourcesContent":["/** Storybook stories for the ButtonAction component */\nimport React from 'react';\nimport type { Meta, StoryObj } from '@storybook/react-native';\nimport { View } from 'react-native';\nimport { X, DotsThree, ArrowLeft, MagnifyingGlass, Bell } from 'phosphor-react-native';\nimport { ButtonAction, type ButtonActionProps } from './ButtonAction';\n\ntype StoryArgs = ButtonActionProps & { colorScheme: 'light' | 'dark' };\n\nconst meta: Meta<StoryArgs> = {\n title: 'Components/ButtonAction',\n component: ButtonAction,\n render: ({ colorScheme: _colorScheme, ...args }) => (\n <ButtonAction {...args} icon={<X />} />\n ),\n argTypes: {\n colorScheme: {\n control: { type: 'radio' },\n options: ['light', 'dark'],\n },\n size: {\n control: { type: 'radio' },\n options: ['XS', 'S', 'M', 'L', 'XL', 'XXL'],\n },\n disabled: { control: { type: 'boolean' } },\n },\n args: {\n colorScheme: 'light',\n size: 'M',\n disabled: false,\n },\n};\n\nexport default meta;\n\ntype Story = StoryObj<StoryArgs>;\n\nexport const Default: Story = {};\n\nexport const Disabled: Story = {\n args: { disabled: true },\n};\n\nexport const AllSizes: Story = {\n render: () => (\n <View style={{ flexDirection: 'row', gap: 16, padding: 16, alignItems: 'center' }}>\n <ButtonAction size=\"XS\" icon={<X />} />\n <ButtonAction size=\"S\" icon={<X />} />\n <ButtonAction size=\"M\" icon={<X />} />\n <ButtonAction size=\"L\" icon={<X />} />\n <ButtonAction size=\"XL\" icon={<X />} />\n <ButtonAction size=\"XXL\" icon={<X />} />\n </View>\n ),\n};\n\nexport const AllIcons: Story = {\n render: () => (\n <View style={{ flexDirection: 'row', gap: 16, padding: 16, alignItems: 'center' }}>\n <ButtonAction size=\"L\" icon={<ArrowLeft />} />\n <ButtonAction size=\"L\" icon={<MagnifyingGlass />} />\n <ButtonAction size=\"L\" icon={<Bell />} />\n <ButtonAction size=\"L\" icon={<DotsThree />} />\n <ButtonAction size=\"L\" icon={<X />} />\n </View>\n ),\n};"]}
@@ -0,0 +1,3 @@
1
+ export { ButtonAction } from './ButtonAction';
2
+ export type { ButtonActionProps, ButtonActionSize } from './ButtonAction';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonAction/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { ButtonAction } from './ButtonAction';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ButtonAction/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC","sourcesContent":["export { ButtonAction } from './ButtonAction';\nexport type { ButtonActionProps, ButtonActionSize } from './ButtonAction';"]}
@@ -0,0 +1,18 @@
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
+ export interface ButtonMapProps {
8
+ /** Icon component (Phosphor Duotone) */
9
+ icon: React.ReactElement;
10
+ /** Disabled state */
11
+ disabled?: boolean;
12
+ /** Press handler */
13
+ onPress?: () => void;
14
+ /** Additional container styles */
15
+ style?: StyleProp<ViewStyle>;
16
+ }
17
+ export declare function ButtonMap({ icon, disabled, onPress, style }: ButtonMapProps): React.JSX.Element;
18
+ //# sourceMappingURL=ButtonMap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonMap.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonMap/ButtonMap.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzD,MAAM,WAAW,cAAc;IAC7B,wCAAwC;IACxC,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC;IACzB,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;AAUD,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,cAAc,qBAY3E"}
@@ -0,0 +1,17 @@
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 { Button } from '../Button';
7
+ const shadowStyle = {
8
+ shadowColor: '#0f0f0f0d',
9
+ shadowOffset: { width: 0, height: 4 },
10
+ shadowRadius: 5,
11
+ shadowOpacity: 1,
12
+ elevation: 3,
13
+ };
14
+ export function ButtonMap({ icon, disabled, onPress, style }) {
15
+ return (<Button variant="tertiary" content="icon-only-rounded" size="S" iconLeft={icon} disabled={disabled} onPress={onPress} style={[shadowStyle, style]}/>);
16
+ }
17
+ //# sourceMappingURL=ButtonMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonMap.js","sourceRoot":"","sources":["../../../src/components/ButtonMap/ButtonMap.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAanC,MAAM,WAAW,GAAc;IAC7B,WAAW,EAAE,WAAW;IACxB,YAAY,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;IACrC,YAAY,EAAE,CAAC;IACf,aAAa,EAAE,CAAC;IAChB,SAAS,EAAE,CAAC;CACb,CAAC;AAEF,MAAM,UAAU,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAkB;IAC1E,OAAO,CACL,CAAC,MAAM,CACL,OAAO,CAAC,UAAU,CAClB,OAAO,CAAC,mBAAmB,CAC3B,IAAI,CAAC,GAAG,CACR,QAAQ,CAAC,CAAC,IAAI,CAAC,CACf,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,KAAK,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,EAC5B,CACH,CAAC;AACJ,CAAC","sourcesContent":["/**\n * ButtonMap component — icon-only-rounded Button wrapper for map UI.\n * Applies a specific cartography shadow (Below/Minimal).\n */\nimport React from 'react';\nimport type { StyleProp, ViewStyle } from 'react-native';\nimport { Button } from '../Button';\n\nexport interface ButtonMapProps {\n /** Icon component (Phosphor Duotone) */\n icon: React.ReactElement;\n /** Disabled state */\n disabled?: boolean;\n /** Press handler */\n onPress?: () => void;\n /** Additional container styles */\n style?: StyleProp<ViewStyle>;\n}\n\nconst shadowStyle: ViewStyle = {\n shadowColor: '#0f0f0f0d',\n shadowOffset: { width: 0, height: 4 },\n shadowRadius: 5,\n shadowOpacity: 1,\n elevation: 3,\n};\n\nexport function ButtonMap({ icon, disabled, onPress, style }: ButtonMapProps) {\n return (\n <Button\n variant=\"tertiary\"\n content=\"icon-only-rounded\"\n size=\"S\"\n iconLeft={icon}\n disabled={disabled}\n onPress={onPress}\n style={[shadowStyle, style]}\n />\n );\n}"]}
@@ -0,0 +1,12 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-native';
2
+ import { type ButtonMapProps } from './ButtonMap';
3
+ type StoryArgs = ButtonMapProps & {
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 MapControls: Story;
12
+ //# sourceMappingURL=ButtonMap.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonMap.stories.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonMap/ButtonMap.stories.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAG9D,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7D,KAAK,SAAS,GAAG,cAAc,GAAG;IAAE,WAAW,EAAE,OAAO,GAAG,MAAM,CAAA;CAAE,CAAC;AAEpE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS,CAiBzB,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,WAAW,EAAE,KAUzB,CAAC"}
@@ -0,0 +1,36 @@
1
+ /** Storybook stories for the ButtonMap component */
2
+ import React from 'react';
3
+ import { View } from 'react-native';
4
+ import { Plus, Minus, Crosshair, MapPin, MagnifyingGlass } from 'phosphor-react-native';
5
+ import { ButtonMap } from './ButtonMap';
6
+ const meta = {
7
+ title: 'Components/ButtonMap',
8
+ component: ButtonMap,
9
+ render: ({ colorScheme: _colorScheme, ...args }) => (<ButtonMap {...args} icon={<Crosshair />}/>),
10
+ argTypes: {
11
+ colorScheme: {
12
+ control: { type: 'radio' },
13
+ options: ['light', 'dark'],
14
+ },
15
+ disabled: { control: { type: 'boolean' } },
16
+ },
17
+ args: {
18
+ colorScheme: 'light',
19
+ disabled: false,
20
+ },
21
+ };
22
+ export default meta;
23
+ export const Default = {};
24
+ export const Disabled = {
25
+ args: { disabled: true },
26
+ };
27
+ export const MapControls = {
28
+ render: () => (<View style={{ gap: 8, padding: 16, alignItems: 'flex-start' }}>
29
+ <ButtonMap icon={<Plus />}/>
30
+ <ButtonMap icon={<Minus />}/>
31
+ <ButtonMap icon={<Crosshair />}/>
32
+ <ButtonMap icon={<MapPin />}/>
33
+ <ButtonMap icon={<MagnifyingGlass />} disabled/>
34
+ </View>),
35
+ };
36
+ //# sourceMappingURL=ButtonMap.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonMap.stories.js","sourceRoot":"","sources":["../../../src/components/ButtonMap/ButtonMap.stories.tsx"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,SAAS,EAAuB,MAAM,aAAa,CAAC;AAI7D,MAAM,IAAI,GAAoB;IAC5B,KAAK,EAAE,sBAAsB;IAC7B,SAAS,EAAE,SAAS;IACpB,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,CAClD,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,AAAD,EAAG,CAAC,EAAG,CAC7C;IACD,QAAQ,EAAE;QACR,WAAW,EAAE;YACX,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;YAC1B,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;SAC3B;QACD,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE;KAC3C;IACD,IAAI,EAAE;QACJ,WAAW,EAAE,OAAO;QACpB,QAAQ,EAAE,KAAK;KAChB;CACF,CAAC;AAEF,eAAe,IAAI,CAAC;AAIpB,MAAM,CAAC,MAAM,OAAO,GAAU,EAAE,CAAC;AAEjC,MAAM,CAAC,MAAM,QAAQ,GAAU;IAC7B,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;CACzB,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAU;IAChC,MAAM,EAAE,GAAG,EAAE,CAAC,CACZ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,CAC7D;MAAA,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,AAAD,EAAG,CAAC,EAC1B;MAAA,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,AAAD,EAAG,CAAC,EAC3B;MAAA,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,AAAD,EAAG,CAAC,EAC/B;MAAA,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,AAAD,EAAG,CAAC,EAC5B;MAAA,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,AAAD,EAAG,CAAC,CAAC,QAAQ,EAChD;IAAA,EAAE,IAAI,CAAC,CACR;CACF,CAAC","sourcesContent":["/** Storybook stories for the ButtonMap component */\nimport React from 'react';\nimport type { Meta, StoryObj } from '@storybook/react-native';\nimport { View } from 'react-native';\nimport { Plus, Minus, Crosshair, MapPin, MagnifyingGlass } from 'phosphor-react-native';\nimport { ButtonMap, type ButtonMapProps } from './ButtonMap';\n\ntype StoryArgs = ButtonMapProps & { colorScheme: 'light' | 'dark' };\n\nconst meta: Meta<StoryArgs> = {\n title: 'Components/ButtonMap',\n component: ButtonMap,\n render: ({ colorScheme: _colorScheme, ...args }) => (\n <ButtonMap {...args} icon={<Crosshair />} />\n ),\n argTypes: {\n colorScheme: {\n control: { type: 'radio' },\n options: ['light', 'dark'],\n },\n disabled: { control: { type: 'boolean' } },\n },\n args: {\n colorScheme: 'light',\n disabled: false,\n },\n};\n\nexport default meta;\n\ntype Story = StoryObj<StoryArgs>;\n\nexport const Default: Story = {};\n\nexport const Disabled: Story = {\n args: { disabled: true },\n};\n\nexport const MapControls: Story = {\n render: () => (\n <View style={{ gap: 8, padding: 16, alignItems: 'flex-start' }}>\n <ButtonMap icon={<Plus />} />\n <ButtonMap icon={<Minus />} />\n <ButtonMap icon={<Crosshair />} />\n <ButtonMap icon={<MapPin />} />\n <ButtonMap icon={<MagnifyingGlass />} disabled />\n </View>\n ),\n};"]}
@@ -0,0 +1,3 @@
1
+ export { ButtonMap } from './ButtonMap';
2
+ export type { ButtonMapProps } from './ButtonMap';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonMap/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { ButtonMap } from './ButtonMap';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ButtonMap/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC","sourcesContent":["export { ButtonMap } from './ButtonMap';\nexport type { ButtonMapProps } from './ButtonMap';"]}
@@ -0,0 +1,21 @@
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 } from 'react';
6
+ import type { StyleProp, ViewStyle } from 'react-native';
7
+ export type ButtonMenuState = 'default' | 'active' | 'disabled';
8
+ export interface ButtonMenuProps {
9
+ /** Icon component (Phosphor Duotone icon) */
10
+ icon: ReactElement;
11
+ /** Toggle state */
12
+ state?: ButtonMenuState;
13
+ /** Show notification dot */
14
+ notif?: boolean;
15
+ /** Press handler */
16
+ onPress?: () => void;
17
+ /** Additional container styles */
18
+ style?: StyleProp<ViewStyle>;
19
+ }
20
+ export declare function ButtonMenu({ icon, state, notif, onPress, style, }: ButtonMenuProps): React.JSX.Element;
21
+ //# sourceMappingURL=ButtonMenu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonMenu.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonMenu/ButtonMenu.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,EAAC,YAAY,EAAY,MAAM,OAAO,CAAC;AAErD,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEhE,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,IAAI,EAAE,YAAY,CAAC;IACnB,mBAAmB;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,kCAAkC;IAClC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B;AAkBD,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,KAAiB,EACjB,KAAa,EACb,OAAO,EACP,KAAK,GACN,EAAE,eAAe,qBAkDjB"}
@@ -0,0 +1,56 @@
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, { useState } from 'react';
6
+ import { Pressable, View } from 'react-native';
7
+ import { useTheme } from '../../context/ThemeContext';
8
+ const BACKGROUND = {
9
+ default: 'transparent',
10
+ active: '#d1c3a033',
11
+ disabled: '#0f0f0f0d',
12
+ };
13
+ const BORDER_COLOR = {
14
+ default: undefined,
15
+ active: '#afafad80',
16
+ disabled: undefined,
17
+ };
18
+ const PRESSED_BACKGROUND = '#d1c3a066';
19
+ const ICON_SIZE = 28;
20
+ const NOTIF_DOT = 8;
21
+ export function ButtonMenu({ icon, state = 'default', notif = false, onPress, style, }) {
22
+ const [pressed, setPressed] = useState(false);
23
+ const { colors } = useTheme();
24
+ const isDisabled = state === 'disabled';
25
+ const background = pressed && !isDisabled ? PRESSED_BACKGROUND : BACKGROUND[state];
26
+ const borderColor = BORDER_COLOR[state];
27
+ const containerStyle = {
28
+ width: 48,
29
+ height: 48,
30
+ padding: 10,
31
+ borderRadius: 8,
32
+ backgroundColor: background,
33
+ borderWidth: borderColor != null ? 1 : undefined,
34
+ borderColor: borderColor ?? undefined,
35
+ alignItems: 'center',
36
+ justifyContent: 'center',
37
+ };
38
+ const clonedIcon = React.cloneElement(icon, {
39
+ size: ICON_SIZE,
40
+ color: isDisabled ? colors.text.disabled : undefined,
41
+ ...icon.props,
42
+ });
43
+ return (<Pressable pointerEvents={isDisabled ? 'none' : 'auto'} onPressIn={() => setPressed(true)} onPressOut={() => setPressed(false)} onPress={isDisabled ? undefined : onPress} style={[containerStyle, style]}>
44
+ {clonedIcon}
45
+ {notif && (<View style={{
46
+ position: 'absolute',
47
+ top: 6,
48
+ left: 34,
49
+ width: NOTIF_DOT,
50
+ height: NOTIF_DOT,
51
+ borderRadius: 9999,
52
+ backgroundColor: '#ff4747',
53
+ }}/>)}
54
+ </Pressable>);
55
+ }
56
+ //# sourceMappingURL=ButtonMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonMenu.js","sourceRoot":"","sources":["../../../src/components/ButtonMenu/ButtonMenu.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,EAAe,QAAQ,EAAE,MAAM,OAAO,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAiBtD,MAAM,UAAU,GAAoC;IAClD,OAAO,EAAG,aAAa;IACvB,MAAM,EAAI,WAAW;IACrB,QAAQ,EAAE,WAAW;CACtB,CAAC;AAEF,MAAM,YAAY,GAAgD;IAChE,OAAO,EAAG,SAAS;IACnB,MAAM,EAAI,WAAW;IACrB,QAAQ,EAAE,SAAS;CACpB,CAAC;AAEF,MAAM,kBAAkB,GAAG,WAAW,CAAC;AACvC,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,SAAS,GAAG,CAAC,CAAC;AAEpB,MAAM,UAAU,UAAU,CAAC,EACzB,IAAI,EACJ,KAAK,GAAG,SAAS,EACjB,KAAK,GAAG,KAAK,EACb,OAAO,EACP,KAAK,GACW;IAChB,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IAE9B,MAAM,UAAU,GAAG,KAAK,KAAK,UAAU,CAAC;IACxC,MAAM,UAAU,GAAG,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACnF,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IAExC,MAAM,cAAc,GAAc;QAChC,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,EAAE;QACV,OAAO,EAAE,EAAE;QACX,YAAY,EAAE,CAAC;QACf,eAAe,EAAE,UAAU;QAC3B,WAAW,EAAE,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;QAChD,WAAW,EAAE,WAAW,IAAI,SAAS;QACrC,UAAU,EAAE,QAAQ;QACpB,cAAc,EAAE,QAAQ;KACzB,CAAC;IAEF,MAAM,UAAU,GAAG,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE;QAC1C,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;QACpD,GAAI,IAAI,CAAC,KAAiC;KACjC,CAAC,CAAC;IAEb,OAAO,CACL,CAAC,SAAS,CACR,aAAa,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAC5C,SAAS,CAAC,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAClC,UAAU,CAAC,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CACpC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAC1C,KAAK,CAAC,CAAC,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,CAE/B;MAAA,CAAC,UAAU,CACX;MAAA,CAAC,KAAK,IAAI,CACR,CAAC,IAAI,CACH,KAAK,CAAC,CAAC;gBACL,QAAQ,EAAE,UAAU;gBACpB,GAAG,EAAE,CAAC;gBACN,IAAI,EAAE,EAAE;gBACR,KAAK,EAAE,SAAS;gBAChB,MAAM,EAAE,SAAS;gBACjB,YAAY,EAAE,IAAI;gBAClB,eAAe,EAAE,SAAS;aAC3B,CAAC,EACF,CACH,CACH;IAAA,EAAE,SAAS,CAAC,CACb,CAAC;AACJ,CAAC","sourcesContent":["/**\n * ButtonMenu component — icon-only toggle button for navigation/menu bars.\n * Supports default, active and disabled states with an optional notification dot.\n */\nimport React, {ReactElement, useState } from 'react';\nimport { Pressable, View } from 'react-native';\nimport type { StyleProp, ViewStyle } from 'react-native';\nimport { useTheme } from '../../context/ThemeContext';\n\nexport type ButtonMenuState = 'default' | 'active' | 'disabled';\n\nexport interface ButtonMenuProps {\n /** Icon component (Phosphor Duotone icon) */\n icon: ReactElement;\n /** Toggle state */\n state?: ButtonMenuState;\n /** Show notification dot */\n notif?: boolean;\n /** Press handler */\n onPress?: () => void;\n /** Additional container styles */\n style?: StyleProp<ViewStyle>;\n}\n\nconst BACKGROUND: Record<ButtonMenuState, string> = {\n default: 'transparent',\n active: '#d1c3a033',\n disabled: '#0f0f0f0d',\n};\n\nconst BORDER_COLOR: Record<ButtonMenuState, string | undefined> = {\n default: undefined,\n active: '#afafad80',\n disabled: undefined,\n};\n\nconst PRESSED_BACKGROUND = '#d1c3a066';\nconst ICON_SIZE = 28;\nconst NOTIF_DOT = 8;\n\nexport function ButtonMenu({\n icon,\n state = 'default',\n notif = false,\n onPress,\n style,\n}: ButtonMenuProps) {\n const [pressed, setPressed] = useState(false);\n const { colors } = useTheme();\n\n const isDisabled = state === 'disabled';\n const background = pressed && !isDisabled ? PRESSED_BACKGROUND : BACKGROUND[state];\n const borderColor = BORDER_COLOR[state];\n\n const containerStyle: ViewStyle = {\n width: 48,\n height: 48,\n padding: 10,\n borderRadius: 8,\n backgroundColor: background,\n borderWidth: borderColor != null ? 1 : undefined,\n borderColor: borderColor ?? undefined,\n alignItems: 'center',\n justifyContent: 'center',\n };\n\n const clonedIcon = React.cloneElement(icon, {\n size: ICON_SIZE,\n color: isDisabled ? colors.text.disabled : undefined,\n ...(icon.props as Record<string, unknown>),\n } as object);\n\n return (\n <Pressable\n pointerEvents={isDisabled ? 'none' : 'auto'}\n onPressIn={() => setPressed(true)}\n onPressOut={() => setPressed(false)}\n onPress={isDisabled ? undefined : onPress}\n style={[containerStyle, style]}\n >\n {clonedIcon}\n {notif && (\n <View\n style={{\n position: 'absolute',\n top: 6,\n left: 34,\n width: NOTIF_DOT,\n height: NOTIF_DOT,\n borderRadius: 9999,\n backgroundColor: '#ff4747',\n }}\n />\n )}\n </Pressable>\n );\n}"]}
@@ -0,0 +1,15 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-native';
2
+ import { type ButtonMenuProps } from './ButtonMenu';
3
+ type StoryArgs = ButtonMenuProps & {
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 Active: Story;
11
+ export declare const Disabled: Story;
12
+ export declare const WithNotif: Story;
13
+ export declare const ActiveWithNotif: Story;
14
+ export declare const AllStates: Story;
15
+ //# sourceMappingURL=ButtonMenu.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonMenu.stories.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonMenu/ButtonMenu.stories.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAG9D,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAEhE,KAAK,SAAS,GAAG,eAAe,GAAG;IAAE,WAAW,EAAE,OAAO,GAAG,MAAM,CAAA;CAAE,CAAC;AAErE,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,KAErB,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,KAEpB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAEvB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAE7B,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAUvB,CAAC"}
@@ -0,0 +1,52 @@
1
+ /** Storybook stories for the ButtonMenu component */
2
+ import React from 'react';
3
+ import { View } from 'react-native';
4
+ import { House, MagnifyingGlass, Bell, Gear } from 'phosphor-react-native';
5
+ import { ButtonMenu } from './ButtonMenu';
6
+ const meta = {
7
+ title: 'Components/ButtonMenu',
8
+ component: ButtonMenu,
9
+ render: ({ colorScheme: _colorScheme, ...args }) => (<ButtonMenu {...args} icon={<House />}/>),
10
+ argTypes: {
11
+ colorScheme: {
12
+ control: { type: 'radio' },
13
+ options: ['light', 'dark'],
14
+ },
15
+ state: {
16
+ control: { type: 'radio' },
17
+ options: ['default', 'active', 'disabled'],
18
+ },
19
+ notif: { control: { type: 'boolean' } },
20
+ },
21
+ args: {
22
+ colorScheme: 'light',
23
+ state: 'default',
24
+ notif: false,
25
+ },
26
+ };
27
+ export default meta;
28
+ export const Default = {
29
+ args: { state: 'default' },
30
+ };
31
+ export const Active = {
32
+ args: { state: 'active' },
33
+ };
34
+ export const Disabled = {
35
+ args: { state: 'disabled' },
36
+ };
37
+ export const WithNotif = {
38
+ args: { state: 'default', notif: true },
39
+ };
40
+ export const ActiveWithNotif = {
41
+ args: { state: 'active', notif: true },
42
+ };
43
+ export const AllStates = {
44
+ render: () => (<View style={{ flexDirection: 'row', gap: 12, padding: 16 }}>
45
+ <ButtonMenu state="default" icon={<House />}/>
46
+ <ButtonMenu state="active" icon={<MagnifyingGlass />}/>
47
+ <ButtonMenu state="disabled" icon={<Gear />}/>
48
+ <ButtonMenu state="default" icon={<Bell />} notif/>
49
+ <ButtonMenu state="active" icon={<Bell />} notif/>
50
+ </View>),
51
+ };
52
+ //# sourceMappingURL=ButtonMenu.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonMenu.stories.js","sourceRoot":"","sources":["../../../src/components/ButtonMenu/ButtonMenu.stories.tsx"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAwB,MAAM,cAAc,CAAC;AAIhE,MAAM,IAAI,GAAoB;IAC5B,KAAK,EAAE,uBAAuB;IAC9B,SAAS,EAAE,UAAU;IACrB,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,CAClD,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,AAAD,EAAG,CAAC,EAAG,CAC1C;IACD,QAAQ,EAAE;QACR,WAAW,EAAE;YACX,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;YAC1B,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;SAC3B;QACD,KAAK,EAAE;YACL,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;YAC1B,OAAO,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,UAAU,CAAC;SAC3C;QACD,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE;KACxC;IACD,IAAI,EAAE;QACJ,WAAW,EAAE,OAAO;QACpB,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,KAAK;KACb;CACF,CAAC;AAEF,eAAe,IAAI,CAAC;AAIpB,MAAM,CAAC,MAAM,OAAO,GAAU;IAC5B,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE;CAC3B,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAAU;IAC3B,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE;CAC1B,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAU;IAC7B,IAAI,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE;CAC5B,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAU;IAC9B,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE;CACxC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAU;IACpC,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE;CACvC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAU;IAC9B,MAAM,EAAE,GAAG,EAAE,CAAC,CACZ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAC1D;MAAA,CAAC,UAAU,CAAC,KAAK,CAAC,SAAS,CAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,AAAD,EAAG,CAAC,EAC7C;MAAA,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAG,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,AAAD,EAAG,CAAC,EACvD;MAAA,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,AAAD,EAAG,CAAC,EAC5C;MAAA,CAAC,UAAU,CAAC,KAAK,CAAC,SAAS,CAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,AAAD,EAAG,CAAC,CAAC,KAAK,EAClD;MAAA,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,AAAD,EAAG,CAAC,CAAC,KAAK,EACpD;IAAA,EAAE,IAAI,CAAC,CACR;CACF,CAAC","sourcesContent":["/** Storybook stories for the ButtonMenu component */\nimport React from 'react';\nimport type { Meta, StoryObj } from '@storybook/react-native';\nimport { View } from 'react-native';\nimport { House, MagnifyingGlass, Bell, Gear } from 'phosphor-react-native';\nimport { ButtonMenu, type ButtonMenuProps } from './ButtonMenu';\n\ntype StoryArgs = ButtonMenuProps & { colorScheme: 'light' | 'dark' };\n\nconst meta: Meta<StoryArgs> = {\n title: 'Components/ButtonMenu',\n component: ButtonMenu,\n render: ({ colorScheme: _colorScheme, ...args }) => (\n <ButtonMenu {...args} icon={<House />} />\n ),\n argTypes: {\n colorScheme: {\n control: { type: 'radio' },\n options: ['light', 'dark'],\n },\n state: {\n control: { type: 'radio' },\n options: ['default', 'active', 'disabled'],\n },\n notif: { control: { type: 'boolean' } },\n },\n args: {\n colorScheme: 'light',\n state: 'default',\n notif: false,\n },\n};\n\nexport default meta;\n\ntype Story = StoryObj<StoryArgs>;\n\nexport const Default: Story = {\n args: { state: 'default' },\n};\n\nexport const Active: Story = {\n args: { state: 'active' },\n};\n\nexport const Disabled: Story = {\n args: { state: 'disabled' },\n};\n\nexport const WithNotif: Story = {\n args: { state: 'default', notif: true },\n};\n\nexport const ActiveWithNotif: Story = {\n args: { state: 'active', notif: true },\n};\n\nexport const AllStates: Story = {\n render: () => (\n <View style={{ flexDirection: 'row', gap: 12, padding: 16 }}>\n <ButtonMenu state=\"default\" icon={<House />} />\n <ButtonMenu state=\"active\" icon={<MagnifyingGlass />} />\n <ButtonMenu state=\"disabled\" icon={<Gear />} />\n <ButtonMenu state=\"default\" icon={<Bell />} notif />\n <ButtonMenu state=\"active\" icon={<Bell />} notif />\n </View>\n ),\n};"]}
@@ -0,0 +1,3 @@
1
+ export { ButtonMenu } from './ButtonMenu';
2
+ export type { ButtonMenuProps, ButtonMenuState } from './ButtonMenu';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ButtonMenu/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { ButtonMenu } from './ButtonMenu';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ButtonMenu/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC","sourcesContent":["export { ButtonMenu } from './ButtonMenu';\nexport type { ButtonMenuProps, ButtonMenuState } from './ButtonMenu';"]}
@@ -0,0 +1,28 @@
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 from 'react';
6
+ import type { StyleProp, ViewStyle } from 'react-native';
7
+ export type FilterChipState = 'default' | 'pressed' | 'selected' | 'disabled';
8
+ export type FilterChipType = 'icon' | 'icon-text';
9
+ export interface FilterChipProps {
10
+ /** Content layout */
11
+ type?: FilterChipType;
12
+ /** Controlled selection state */
13
+ selected?: boolean;
14
+ /** Disabled state */
15
+ disabled?: boolean;
16
+ /** Label text — required when type is icon-text */
17
+ label?: string;
18
+ /** Left icon (Phosphor Duotone) */
19
+ iconLeft?: React.ReactElement;
20
+ /** Right icon — typically a caret or close icon */
21
+ iconRight?: React.ReactElement;
22
+ /** Press handler */
23
+ onPress?: () => void;
24
+ /** Additional container styles */
25
+ style?: StyleProp<ViewStyle>;
26
+ }
27
+ export declare function FilterChip({ type, selected, disabled, label, iconLeft, iconRight, onPress, style, }: FilterChipProps): React.JSX.Element;
28
+ //# sourceMappingURL=FilterChip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterChip.d.ts","sourceRoot":"","sources":["../../../src/components/FilterChip/FilterChip.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,eAAe,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAC9E,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,WAAW,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B,qBAAqB;IACrB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,QAAQ,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC;IAC9B,mDAAmD;IACnD,SAAS,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC;IAC/B,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,kCAAkC;IAClC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B;AAwBD,wBAAgB,UAAU,CAAC,EACzB,IAAkB,EAClB,QAAgB,EAChB,QAAgB,EAChB,KAAK,EACL,QAAQ,EACR,SAAS,EACT,OAAO,EACP,KAAK,GACN,EAAE,eAAe,qBA6DjB"}
@@ -0,0 +1,66 @@
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 { useTheme } from '../../context/ThemeContext';
8
+ const STATE_TOKENS = {
9
+ default: { background: 'transparent', text: '#28242e', icon: '#28242e', borderColor: '#afafad80', borderWidth: 1 },
10
+ pressed: { background: '#d1c3a066', text: '#28242e', icon: '#28242e', borderColor: '#afafad80', borderWidth: 1 },
11
+ selected: { background: 'transparent', text: '#28242e', icon: '#28242e', borderColor: '#28242e', borderWidth: 2 },
12
+ disabled: { background: '#0f0f0f0d', text: '#0f0f0f99', icon: '#0f0f0f99', borderColor: '#0f0f0f1a', borderWidth: 1 },
13
+ };
14
+ const ICON_LEFT_SIZE = 20;
15
+ const ICON_RIGHT_SIZE = 16;
16
+ // --- Component ---
17
+ export function FilterChip({ type = 'icon-text', selected = false, disabled = false, label, iconLeft, iconRight, onPress, style, }) {
18
+ const [internalPressed, setInternalPressed] = useState(false);
19
+ useTheme(); // consumed for future theme-aware tokens
20
+ const resolvedState = disabled
21
+ ? 'disabled'
22
+ : internalPressed
23
+ ? 'pressed'
24
+ : selected
25
+ ? 'selected'
26
+ : 'default';
27
+ const tokens = STATE_TOKENS[resolvedState];
28
+ const isIconOnly = type === 'icon';
29
+ const chipStyle = {
30
+ height: 32,
31
+ borderRadius: 100,
32
+ paddingVertical: 6,
33
+ paddingHorizontal: isIconOnly ? 6 : 12,
34
+ flexDirection: 'row',
35
+ alignItems: 'center',
36
+ gap: isIconOnly ? 0 : 4,
37
+ backgroundColor: tokens.background,
38
+ borderWidth: tokens.borderWidth,
39
+ borderColor: tokens.borderColor,
40
+ alignSelf: 'flex-start',
41
+ };
42
+ const textStyle = {
43
+ color: tokens.text,
44
+ fontSize: 14,
45
+ lineHeight: 20,
46
+ fontFamily: 'Urbanist',
47
+ fontWeight: '500',
48
+ };
49
+ const cloneIcon = (icon, size) => {
50
+ if (!icon)
51
+ return null;
52
+ return React.cloneElement(icon, {
53
+ size,
54
+ color: tokens.icon,
55
+ ...icon.props,
56
+ });
57
+ };
58
+ return (<Pressable pointerEvents={disabled ? 'none' : 'auto'} onPressIn={() => setInternalPressed(true)} onPressOut={() => setInternalPressed(false)} onPress={disabled ? undefined : onPress} style={[{ paddingVertical: 6 }, style]}>
59
+ <View style={chipStyle}>
60
+ {cloneIcon(iconLeft, ICON_LEFT_SIZE)}
61
+ {!isIconOnly && label != null && <Text style={textStyle}>{label}</Text>}
62
+ {cloneIcon(iconRight, ICON_RIGHT_SIZE)}
63
+ </View>
64
+ </Pressable>);
65
+ }
66
+ //# sourceMappingURL=FilterChip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterChip.js","sourceRoot":"","sources":["../../../src/components/FilterChip/FilterChip.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * FilterChip component — pill-shaped selection chip for filters.\n * Supports icon-only and icon+text layouts with controlled selection state.\n */\nimport React, { useState } from 'react';\nimport { Pressable, Text, View } from 'react-native';\nimport type { StyleProp, ViewStyle } from 'react-native';\nimport { useTheme } from '../../context/ThemeContext';\n\nexport type FilterChipState = 'default' | 'pressed' | 'selected' | 'disabled';\nexport type FilterChipType = 'icon' | 'icon-text';\n\nexport interface FilterChipProps {\n /** Content layout */\n type?: FilterChipType;\n /** Controlled selection state */\n selected?: boolean;\n /** Disabled state */\n disabled?: boolean;\n /** Label text — required when type is icon-text */\n label?: string;\n /** Left icon (Phosphor Duotone) */\n iconLeft?: React.ReactElement;\n /** Right icon — typically a caret or close icon */\n iconRight?: React.ReactElement;\n /** Press handler */\n onPress?: () => void;\n /** Additional container styles */\n style?: StyleProp<ViewStyle>;\n}\n\n// --- State color tokens (hardcoded per spec) ---\n\ninterface StateTokens {\n background: string;\n text: string;\n icon: string;\n borderColor: string;\n borderWidth: number;\n}\n\nconst STATE_TOKENS: Record<FilterChipState, StateTokens> = {\n default: { background: 'transparent', text: '#28242e', icon: '#28242e', borderColor: '#afafad80', borderWidth: 1 },\n pressed: { background: '#d1c3a066', text: '#28242e', icon: '#28242e', borderColor: '#afafad80', borderWidth: 1 },\n selected: { background: 'transparent', text: '#28242e', icon: '#28242e', borderColor: '#28242e', borderWidth: 2 },\n disabled: { background: '#0f0f0f0d', text: '#0f0f0f99', icon: '#0f0f0f99', borderColor: '#0f0f0f1a', borderWidth: 1 },\n};\n\nconst ICON_LEFT_SIZE = 20;\nconst ICON_RIGHT_SIZE = 16;\n\n// --- Component ---\n\nexport function FilterChip({\n type = 'icon-text',\n selected = false,\n disabled = false,\n label,\n iconLeft,\n iconRight,\n onPress,\n style,\n}: FilterChipProps) {\n const [internalPressed, setInternalPressed] = useState(false);\n useTheme(); // consumed for future theme-aware tokens\n\n const resolvedState: FilterChipState = disabled\n ? 'disabled'\n : internalPressed\n ? 'pressed'\n : selected\n ? 'selected'\n : 'default';\n\n const tokens = STATE_TOKENS[resolvedState];\n const isIconOnly = type === 'icon';\n\n const chipStyle: ViewStyle = {\n height: 32,\n borderRadius: 100,\n paddingVertical: 6,\n paddingHorizontal: isIconOnly ? 6 : 12,\n flexDirection: 'row',\n alignItems: 'center',\n gap: isIconOnly ? 0 : 4,\n backgroundColor: tokens.background,\n borderWidth: tokens.borderWidth,\n borderColor: tokens.borderColor,\n alignSelf: 'flex-start',\n };\n\n const textStyle = {\n color: tokens.text,\n fontSize: 14,\n lineHeight: 20,\n fontFamily: 'Urbanist',\n fontWeight: '500' as const,\n };\n\n const cloneIcon = (icon: React.ReactElement | undefined, size: number) => {\n if (!icon) return null;\n return React.cloneElement(icon, {\n size,\n color: tokens.icon,\n ...(icon.props as Record<string, unknown>),\n } as object);\n };\n\n return (\n <Pressable\n pointerEvents={disabled ? 'none' : 'auto'}\n onPressIn={() => setInternalPressed(true)}\n onPressOut={() => setInternalPressed(false)}\n onPress={disabled ? undefined : onPress}\n style={[{ paddingVertical: 6 }, style]}\n >\n <View style={chipStyle}>\n {cloneIcon(iconLeft, ICON_LEFT_SIZE)}\n {!isIconOnly && label != null && <Text style={textStyle}>{label}</Text>}\n {cloneIcon(iconRight, ICON_RIGHT_SIZE)}\n </View>\n </Pressable>\n );\n}"]}
@@ -0,0 +1,15 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-native';
2
+ import { type FilterChipProps } from './FilterChip';
3
+ type StoryArgs = FilterChipProps & {
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 Selected: Story;
11
+ export declare const Disabled: Story;
12
+ export declare const IconOnly: Story;
13
+ export declare const IconOnlySelected: Story;
14
+ export declare const AllStates: Story;
15
+ //# sourceMappingURL=FilterChip.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterChip.stories.d.ts","sourceRoot":"","sources":["../../../src/components/FilterChip/FilterChip.stories.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAG9D,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAEhE,KAAK,SAAS,GAAG,eAAe,GAAG;IAAE,WAAW,EAAE,OAAO,GAAG,MAAM,CAAA;CAAE,CAAC;AAErE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS,CAyBzB,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,QAAQ,EAAE,KAEtB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAE9B,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAUvB,CAAC"}
@@ -0,0 +1,55 @@
1
+ /** Storybook stories for the FilterChip component */
2
+ import React from 'react';
3
+ import { View } from 'react-native';
4
+ import { Funnel, CaretDown, X, MagnifyingGlass } from 'phosphor-react-native';
5
+ import { FilterChip } from './FilterChip';
6
+ const meta = {
7
+ title: 'Components/FilterChip',
8
+ component: FilterChip,
9
+ render: ({ colorScheme: _colorScheme, ...args }) => (<FilterChip {...args}/>),
10
+ argTypes: {
11
+ colorScheme: {
12
+ control: { type: 'radio' },
13
+ options: ['light', 'dark'],
14
+ },
15
+ type: {
16
+ control: { type: 'radio' },
17
+ options: ['icon', 'icon-text'],
18
+ },
19
+ selected: { control: { type: 'boolean' } },
20
+ disabled: { control: { type: 'boolean' } },
21
+ },
22
+ args: {
23
+ colorScheme: 'light',
24
+ type: 'icon-text',
25
+ selected: false,
26
+ disabled: false,
27
+ label: 'Filtrer',
28
+ },
29
+ };
30
+ export default meta;
31
+ export const Default = {
32
+ args: { label: 'Filtrer', iconLeft: <Funnel />, iconRight: <CaretDown /> },
33
+ };
34
+ export const Selected = {
35
+ args: { label: 'Filtrer', iconLeft: <Funnel />, iconRight: <X />, selected: true },
36
+ };
37
+ export const Disabled = {
38
+ args: { label: 'Filtrer', iconLeft: <Funnel />, disabled: true },
39
+ };
40
+ export const IconOnly = {
41
+ args: { type: 'icon', iconLeft: <MagnifyingGlass /> },
42
+ };
43
+ export const IconOnlySelected = {
44
+ args: { type: 'icon', iconLeft: <Funnel />, selected: true },
45
+ };
46
+ export const AllStates = {
47
+ render: () => (<View style={{ flexDirection: 'row', gap: 8, padding: 16, flexWrap: 'wrap' }}>
48
+ <FilterChip label="Default" iconLeft={<Funnel />} iconRight={<CaretDown />}/>
49
+ <FilterChip label="Selected" iconLeft={<Funnel />} iconRight={<X />} selected/>
50
+ <FilterChip label="Disabled" iconLeft={<Funnel />} disabled/>
51
+ <FilterChip type="icon" iconLeft={<Funnel />}/>
52
+ <FilterChip type="icon" iconLeft={<Funnel />} selected/>
53
+ </View>),
54
+ };
55
+ //# sourceMappingURL=FilterChip.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterChip.stories.js","sourceRoot":"","sources":["../../../src/components/FilterChip/FilterChip.stories.tsx"],"names":[],"mappings":"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","sourcesContent":["/** Storybook stories for the FilterChip component */\nimport React from 'react';\nimport type { Meta, StoryObj } from '@storybook/react-native';\nimport { View } from 'react-native';\nimport { Funnel, CaretDown, X, MagnifyingGlass } from 'phosphor-react-native';\nimport { FilterChip, type FilterChipProps } from './FilterChip';\n\ntype StoryArgs = FilterChipProps & { colorScheme: 'light' | 'dark' };\n\nconst meta: Meta<StoryArgs> = {\n title: 'Components/FilterChip',\n component: FilterChip,\n render: ({ colorScheme: _colorScheme, ...args }) => (\n <FilterChip {...args} />\n ),\n argTypes: {\n colorScheme: {\n control: { type: 'radio' },\n options: ['light', 'dark'],\n },\n type: {\n control: { type: 'radio' },\n options: ['icon', 'icon-text'],\n },\n selected: { control: { type: 'boolean' } },\n disabled: { control: { type: 'boolean' } },\n },\n args: {\n colorScheme: 'light',\n type: 'icon-text',\n selected: false,\n disabled: false,\n label: 'Filtrer',\n },\n};\n\nexport default meta;\n\ntype Story = StoryObj<StoryArgs>;\n\nexport const Default: Story = {\n args: { label: 'Filtrer', iconLeft: <Funnel />, iconRight: <CaretDown /> },\n};\n\nexport const Selected: Story = {\n args: { label: 'Filtrer', iconLeft: <Funnel />, iconRight: <X />, selected: true },\n};\n\nexport const Disabled: Story = {\n args: { label: 'Filtrer', iconLeft: <Funnel />, disabled: true },\n};\n\nexport const IconOnly: Story = {\n args: { type: 'icon', iconLeft: <MagnifyingGlass /> },\n};\n\nexport const IconOnlySelected: Story = {\n args: { type: 'icon', iconLeft: <Funnel />, selected: true },\n};\n\nexport const AllStates: Story = {\n render: () => (\n <View style={{ flexDirection: 'row', gap: 8, padding: 16, flexWrap: 'wrap' }}>\n <FilterChip label=\"Default\" iconLeft={<Funnel />} iconRight={<CaretDown />} />\n <FilterChip label=\"Selected\" iconLeft={<Funnel />} iconRight={<X />} selected />\n <FilterChip label=\"Disabled\" iconLeft={<Funnel />} disabled />\n <FilterChip type=\"icon\" iconLeft={<Funnel />} />\n <FilterChip type=\"icon\" iconLeft={<Funnel />} selected />\n </View>\n ),\n};"]}