@alveole/components 2.0.0-alpha.13 → 2.0.0-alpha.15

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.
@@ -1,2 +1,2 @@
1
- export declare const ALVEOLE_COMPONENTS_VERSION: "2.0.0-alpha.13";
1
+ export declare const ALVEOLE_COMPONENTS_VERSION: "2.0.0-alpha.15";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1 +1 @@
1
- export const ALVEOLE_COMPONENTS_VERSION = "2.0.0-alpha.13";
1
+ export const ALVEOLE_COMPONENTS_VERSION = "2.0.0-alpha.15";
@@ -3,7 +3,7 @@ import { format } from 'date-fns/format';
3
3
  import { enUS } from 'date-fns/locale/en-US';
4
4
  import { fr } from 'date-fns/locale/fr';
5
5
  import React from 'react';
6
- import { ScrollView } from 'react-native';
6
+ import { ScrollView } from 'react-native-gesture-handler';
7
7
  import { Box } from '../../core/Box';
8
8
  import { Grid } from '../../core/Grid';
9
9
  import { Typography } from '../../core/Typography';
@@ -1 +1 @@
1
- {"version":3,"file":"useChoixDeFichier.d.ts","sourceRoot":"","sources":["../../../src/ui/FormControl/useChoixDeFichier.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAGL,eAAe,EAKhB,MAAM,mBAAmB,CAAC;AAmC3B,KAAK,OAAO,GAAG,IAAI,CAAC,cAAc,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,aAAa,CAAC,GAAG;IAChG,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,OAAO,wBAuDjD,CAAC"}
1
+ {"version":3,"file":"useChoixDeFichier.d.ts","sourceRoot":"","sources":["../../../src/ui/FormControl/useChoixDeFichier.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAGL,eAAe,EAKhB,MAAM,mBAAmB,CAAC;AAmD3B,KAAK,OAAO,GAAG,IAAI,CAAC,cAAc,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,aAAa,CAAC,GAAG;IAChG,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,OAAO,wBA6DjD,CAAC"}
@@ -2,10 +2,17 @@ import { useTheme } from '@alveole/theme';
2
2
  import * as DocumentPicker from 'expo-document-picker';
3
3
  import * as ImagePicker from 'expo-image-picker';
4
4
  import React from 'react';
5
- import { Platform } from 'react-native';
5
+ import { ActionSheetIOS, Platform } from 'react-native';
6
6
  import { Alert } from '../../core/Alert';
7
7
  import { ajoute, imagesSeulement, libelleDeLaSource, sourcesProposees, } from './fichiersDuChamp';
8
8
  import { valideLeType } from './valideLeType';
9
+ const showActionSheetIOS = ({ sources, lancer, titre, labels, type, grandEcran }) => {
10
+ const options = [...sources.map(s => libelleDeLaSource(s, labels, { type, grandEcran })), labels.cancel];
11
+ ActionSheetIOS.showActionSheetWithOptions({ title: titre, options, cancelButtonIndex: options.length - 1 }, index => {
12
+ if (index < sources.length)
13
+ lancer(sources[index]);
14
+ });
15
+ };
9
16
  const enFichier = (asset) => ({
10
17
  uri: asset.uri,
11
18
  name: asset.fileName ?? 'image.jpg',
@@ -56,16 +63,21 @@ export const useChoixDeFichier = (options) => {
56
63
  const ouvrirLaFeuille = React.useCallback(() => {
57
64
  const lancer = (source) => (source === 'document' ? choisirUnDocument() : choisirUneImage(source));
58
65
  const images = imagesSeulement(type);
66
+ const sources = sourcesProposees(type, grandEcran);
67
+ const titre = images ? labels.chooseImageTitle : labels.chooseDocumentTitle;
68
+ if (Platform.OS === 'ios')
69
+ return showActionSheetIOS({ sources, lancer, titre, labels, type, grandEcran });
59
70
  Alert.alert({
60
- title: images ? labels.chooseImageTitle : labels.chooseDocumentTitle,
71
+ title: titre,
61
72
  message: images ? labels.chooseImageMessage : undefined,
62
73
  buttons: [
63
- ...sourcesProposees(type, grandEcran).map(source => ({
74
+ ...sources.map(source => ({
64
75
  text: libelleDeLaSource(source, labels, { type, grandEcran }),
65
76
  onPress: () => lancer(source),
66
77
  })),
67
78
  { text: labels.cancel, style: 'cancel' },
68
79
  ],
80
+ options: { cancelable: true },
69
81
  });
70
82
  }, [type, labels, grandEcran, choisirUnDocument, choisirUneImage]);
71
83
  return React.useCallback(async () => {
@@ -12,6 +12,12 @@ export type TabsProps = Omit<BoxProps, 'children' | 'onChange'> & {
12
12
  renderAction?: () => React.ReactNode;
13
13
  }[];
14
14
  defaultValue?: string;
15
+ /**
16
+ * L'onglet actif, impose par le parent : `Tabs` devient controle. Un clic sur un onglet appelle
17
+ * toujours `onChange`, au parent de mettre `value` a jour. Absent, `Tabs` garde l'onglet actif
18
+ * pour lui, a partir de `defaultValue`.
19
+ */
20
+ value?: string;
15
21
  onChange?: (index: number) => void;
16
22
  /**
17
23
  * Active l'Anchor Sync (voir ADR 0022) : au clic, l'onglet actif est ecrit dans l'etat
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/ui/Tabs/Tabs.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAO,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAOrC,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,UAAU,GAAG,UAAU,CAAC,GAAG;IAChE,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;QACzB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;KACtC,EAAE,CAAC;IACJ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,IAAI,GAAI,OAAO,SAAS,sBAkEpC,CAAC"}
1
+ {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/ui/Tabs/Tabs.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAO,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAOrC,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,UAAU,GAAG,UAAU,CAAC,GAAG;IAChE,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;QACzB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;KACtC,EAAE,CAAC;IACJ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,IAAI,GAAI,OAAO,SAAS,sBAkEpC,CAAC"}
@@ -9,10 +9,10 @@ import { TabsTab } from './TabsTab';
9
9
  import { useAnchorSync } from './useAnchorSync';
10
10
  import { useTabsState } from './useTabsState';
11
11
  export const Tabs = (props) => {
12
- const { tabs, defaultValue = '', onChange, urlAnchorPrefix, style, ...boxProps } = props;
12
+ const { tabs, defaultValue = '', value, onChange, urlAnchorPrefix, style, ...boxProps } = props;
13
13
  const styles = useStyles();
14
14
  const initialValue = defaultValue || tabs[0]?.value || '';
15
- const { currentTab, etatDeLOnglet, setCurrentTab, restoreCurrentTab, setHoverTab, handleOnInteraction } = useTabsState(initialValue, onChange);
15
+ const { currentTab, etatDeLOnglet, setCurrentTab, restoreCurrentTab, setHoverTab, handleOnInteraction } = useTabsState(initialValue, onChange, value);
16
16
  const { persist } = useAnchorSync(urlAnchorPrefix, anchor => {
17
17
  const tab = tabs.find(t => toSlug(t.label) === anchor);
18
18
  if (tab)
@@ -121,5 +121,6 @@ declare const _default: {
121
121
  };
122
122
  export default _default;
123
123
  export declare const Example: () => React.JSX.Element;
124
+ export declare const Controle: () => React.JSX.Element;
124
125
  export * as Sources from './Tabs.stories.sources';
125
126
  //# sourceMappingURL=Tabs.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.stories.d.ts","sourceRoot":"","sources":["../../../src/ui/Tabs/Tabs.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAO1B,wBAQkB;AAElB,eAAO,MAAM,OAAO,yBAuBnB,CAAC;AAEF,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"Tabs.stories.d.ts","sourceRoot":"","sources":["../../../src/ui/Tabs/Tabs.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQ1B,wBAQkB;AAElB,eAAO,MAAM,OAAO,yBAuBnB,CAAC;AAIF,eAAO,MAAM,QAAQ,yBAiBpB,CAAC;AAEF,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAC"}
@@ -1,7 +1,8 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from 'react';
3
3
  import { Box } from '../../core/Box';
4
4
  import { Typography } from '../../core/Typography';
5
+ import { Button } from '../Button';
5
6
  import { Tabs } from './Tabs';
6
7
  import { useStyles } from './Tabs.styles';
7
8
  export default {
@@ -27,4 +28,15 @@ export const Example = () => {
27
28
  },
28
29
  ] }) }));
29
30
  };
31
+ // `value` rend les Tabs controles : le parent choisit l'onglet actif, par exemple depuis un
32
+ // bouton ou une carte cliquee, et le suit depuis `onChange` quand l'utilisateur clique un onglet.
33
+ export const Controle = () => {
34
+ const onglets = [
35
+ { label: 'Onglet 1', value: 'onglet-1', content: _jsx(Typography, { children: "Contenu de onglet 1" }) },
36
+ { label: 'Onglet 2', value: 'onglet-2', content: _jsx(Typography, { children: "Contenu de onglet 2" }) },
37
+ { label: 'Onglet 3', value: 'onglet-3', content: _jsx(Typography, { children: "Contenu de onglet 3" }) },
38
+ ];
39
+ const [ongletActif, setOngletActif] = React.useState('onglet-1');
40
+ return (_jsxs(Box, { width: '100%', gap: 16, children: [_jsxs(Box, { flexDirection: "row", gap: 8, children: [_jsx(Button, { title: "Aller \u00E0 l\u2019onglet 1", variant: "secondary", onPress: () => setOngletActif('onglet-1') }), _jsx(Button, { title: "Aller \u00E0 l\u2019onglet 3", variant: "secondary", onPress: () => setOngletActif('onglet-3') })] }), _jsx(Tabs, { value: ongletActif, onChange: index => setOngletActif(onglets[index].value), tabs: onglets })] }));
41
+ };
30
42
  export * as Sources from './Tabs.stories.sources';
@@ -1,6 +1,8 @@
1
1
  export declare const Example: () => string;
2
+ export declare const Controle: () => string;
2
3
  export declare const storySources: {
3
4
  readonly Example: () => string;
5
+ readonly Controle: () => string;
4
6
  };
5
7
  export type StorySourceName = keyof typeof storySources;
6
8
  //# sourceMappingURL=Tabs.stories.sources.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.stories.sources.d.ts","sourceRoot":"","sources":["../../../src/ui/Tabs/Tabs.stories.sources.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,cAAk1B,CAAC;AAEv2B,eAAO,MAAM,YAAY;;CAEf,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,YAAY,CAAC"}
1
+ {"version":3,"file":"Tabs.stories.sources.d.ts","sourceRoot":"","sources":["../../../src/ui/Tabs/Tabs.stories.sources.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,cAAk1B,CAAC;AAEv2B,eAAO,MAAM,QAAQ,cAA44B,CAAC;AAEl6B,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,YAAY,CAAC"}
@@ -1,6 +1,8 @@
1
1
  // This file is generated. Do not edit manually.
2
2
  // Source: src/ui/Tabs/Tabs.stories.tsx
3
3
  export const Example = () => "export const Example = () => {\n const [_activeTab, setActiveTab] = React.useState(0);\n\n return (\n <Box width={'100%'}>\n <Tabs\n defaultValue={'onglet-1'}\n onChange={setActiveTab}\n urlAnchorPrefix=\"tabs-story\"\n tabs={[\n { label: 'Onglet 1', value: 'onglet-1', content: <Typography>Contenu de onglet 1</Typography> },\n { label: 'Onglet 2', counter: 12, value: 'onglet-2', content: <Typography>Contenu de onglet 2</Typography> },\n { label: 'Onglet 3', value: 'onglet-3', content: <Typography>Contenu de onglet 3</Typography> },\n {\n label: 'Onglet 4',\n leading: 'Settings',\n value: 'onglet-4',\n content: <Typography>Contenu de onglet 4</Typography>,\n },\n ]}\n />\n </Box>\n );\n};";
4
+ export const Controle = () => "export const Controle = () => {\n const onglets = [\n { label: 'Onglet 1', value: 'onglet-1', content: <Typography>Contenu de onglet 1</Typography> },\n { label: 'Onglet 2', value: 'onglet-2', content: <Typography>Contenu de onglet 2</Typography> },\n { label: 'Onglet 3', value: 'onglet-3', content: <Typography>Contenu de onglet 3</Typography> },\n ];\n const [ongletActif, setOngletActif] = React.useState('onglet-1');\n\n return (\n <Box width={'100%'} gap={16}>\n <Box flexDirection=\"row\" gap={8}>\n <Button title=\"Aller à l’onglet 1\" variant=\"secondary\" onPress={() => setOngletActif('onglet-1')} />\n <Button title=\"Aller à l’onglet 3\" variant=\"secondary\" onPress={() => setOngletActif('onglet-3')} />\n </Box>\n <Tabs value={ongletActif} onChange={index => setOngletActif(onglets[index].value)} tabs={onglets} />\n </Box>\n );\n};";
4
5
  export const storySources = {
5
6
  Example,
7
+ Controle,
6
8
  };
@@ -1,6 +1,6 @@
1
1
  import { TabLayout } from 'tamagui';
2
2
  import { EtatDeLOnglet } from './Tabs.apparence';
3
- export declare const useTabsState: (initialValue: string, onChange?: (index: number) => void) => {
3
+ export declare const useTabsState: (initialValue: string, onChange?: (index: number) => void, value?: string) => {
4
4
  currentTab: string;
5
5
  etatDeLOnglet: (tabValue: string) => EtatDeLOnglet;
6
6
  setCurrentTab: (currentTab: string, index: number) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"useTabsState.d.ts","sourceRoot":"","sources":["../../../src/ui/Tabs/useTabsState.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAgB,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAgBjD,eAAO,MAAM,YAAY,GAAI,cAAc,MAAM,EAAE,WAAW,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;;8BA+BlD,MAAM,KAAG,aAAa;gCAtBpB,MAAM,SAAS,MAAM;oCAOjB,MAAM;4BAKd,MAAM,GAAG,IAAI;;CAuB7C,CAAC"}
1
+ {"version":3,"file":"useTabsState.d.ts","sourceRoot":"","sources":["../../../src/ui/Tabs/useTabsState.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAgB,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAkBjD,eAAO,MAAM,YAAY,GAAI,cAAc,MAAM,EAAE,WAAW,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EAAE,QAAQ,MAAM;;8BAiClE,MAAM,KAAG,aAAa;gCAxBpB,MAAM,SAAS,MAAM;oCAOjB,MAAM;4BAKd,MAAM,GAAG,IAAI;;CAyB7C,CAAC"}
@@ -5,7 +5,9 @@ import React from 'react';
5
5
  //
6
6
  // Le focus n'en fait pas partie : il est rendu par la regle CSS `:focus-visible` du theme, la
7
7
  // seule qui distingue le clavier de la souris. Suivi en React, il s'affichait aussi au clic.
8
- export const useTabsState = (initialValue, onChange) => {
8
+ // `value`, quand le parent la donne, fait foi sur l'onglet retenu en interne : `Tabs` est alors
9
+ // controle, et c'est au parent de la mettre a jour depuis `onChange`.
10
+ export const useTabsState = (initialValue, onChange, value) => {
9
11
  const [tabState, setTabState] = React.useState({
10
12
  activeAt: null,
11
13
  currentTab: initialValue,
@@ -32,12 +34,13 @@ export const useTabsState = (initialValue, onChange) => {
32
34
  setTabState(state => ({ ...state, intentAt: layout }));
33
35
  }
34
36
  };
37
+ const currentTab = value ?? tabState.currentTab;
35
38
  const etatDeLOnglet = (tabValue) => ({
36
- actif: tabState.currentTab === tabValue,
39
+ actif: currentTab === tabValue,
37
40
  survole: tabState.hoverTab === tabValue,
38
41
  });
39
42
  return {
40
- currentTab: tabState.currentTab,
43
+ currentTab,
41
44
  etatDeLOnglet,
42
45
  setCurrentTab,
43
46
  restoreCurrentTab,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alveole/components",
3
- "version": "2.0.0-alpha.13",
3
+ "version": "2.0.0-alpha.15",
4
4
  "description": "Shared UI components.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",