@alveole/storybook 0.43.2 → 1.0.0

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,8 +1,10 @@
1
+ import React from 'react';
1
2
  export type SearchFieldProps = {
2
- label: string;
3
+ label?: string;
3
4
  placeholder?: string;
4
5
  value: string;
5
6
  onChangeText: (value: string) => void;
7
+ size?: 'sm' | 'md';
6
8
  };
7
- export declare const SearchField: ({ label, placeholder, value, onChangeText }: SearchFieldProps) => import("react").JSX.Element;
9
+ export declare const SearchField: ({ label, placeholder, value, onChangeText, size }: SearchFieldProps) => React.JSX.Element;
8
10
  //# sourceMappingURL=SearchField.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SearchField.d.ts","sourceRoot":"","sources":["../../src/components/SearchField.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,6CAA6C,gBAAgB,gCA0BxF,CAAC"}
1
+ {"version":3,"file":"SearchField.d.ts","sourceRoot":"","sources":["../../src/components/SearchField.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,mDAA0D,gBAAgB,sBA0CrG,CAAC"}
@@ -1,17 +1,31 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Typography } from '@alveole/components';
3
3
  import { useTheme } from '@alveole/theme';
4
- import { TextInput } from 'react-native';
5
- export const SearchField = ({ label, placeholder, value, onChangeText }) => {
4
+ import React from 'react';
5
+ import { Platform, TextInput } from 'react-native';
6
+ export const SearchField = ({ label, placeholder, value, onChangeText, size = 'md' }) => {
6
7
  const { text, color, radius, spacing } = useTheme();
7
- return (_jsxs(Box, { display: "flex", gap: 8, children: [_jsx(Typography, { style: text['Corps de texte'].XS.CapsBold, children: label }), _jsx(TextInput, { placeholder: placeholder, value: value, onChangeText: onChangeText, placeholderTextColor: color.light.text['mention-grey'], autoCapitalize: "none", autoCorrect: false, style: {
8
+ const inputRef = React.useRef(null);
9
+ React.useEffect(() => {
10
+ if (Platform.OS !== 'web')
11
+ return;
12
+ const handleKeyDown = (e) => {
13
+ if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
14
+ e.preventDefault();
15
+ inputRef.current?.focus();
16
+ }
17
+ };
18
+ document.addEventListener('keydown', handleKeyDown);
19
+ return () => document.removeEventListener('keydown', handleKeyDown);
20
+ }, []);
21
+ return (_jsxs(Box, { display: "flex", gap: 8, children: [label ? _jsx(Typography, { style: text['Corps de texte'].XS.CapsBold, children: label }) : null, _jsx(TextInput, { ref: inputRef, placeholder: placeholder, value: value, onChangeText: onChangeText, placeholderTextColor: color.light.text['mention-grey'], autoCapitalize: "none", autoCorrect: false, style: {
8
22
  borderWidth: 1,
9
23
  borderColor: color.light.border['default-grey'],
10
24
  borderRadius: radius('md'),
11
- paddingVertical: spacing('1W'),
25
+ paddingVertical: size === 'sm' ? spacing('1,5V') : spacing('1W'),
12
26
  paddingHorizontal: spacing('2W'),
13
27
  backgroundColor: color.light.background['default-grey'],
14
28
  color: color.light.text['default-grey'],
15
- ...text['Corps de texte'].MD.Regular,
29
+ ...(size === 'sm' ? text['Corps de texte'].SM.Regular : text['Corps de texte'].MD.Regular),
16
30
  } })] }));
17
31
  };
package/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@ export * from './screens/StoriesScreen';
9
9
  export * from './screens/StoryDetailScreen';
10
10
  export * from './screens/ThemeConstantDetailScreen';
11
11
  export * from './screens/ThemeConstantsScreen';
12
+ export * from './screens/ThemeCSSVariablesScreen';
12
13
  export * from './screens/ThemePaletteScreen';
13
14
  export * from './screens/ThemeTypographyScreen';
14
15
  export * from './types';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qCAAqC,CAAC;AACpD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qCAAqC,CAAC;AACpD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ export * from './screens/StoriesScreen';
9
9
  export * from './screens/StoryDetailScreen';
10
10
  export * from './screens/ThemeConstantDetailScreen';
11
11
  export * from './screens/ThemeConstantsScreen';
12
+ export * from './screens/ThemeCSSVariablesScreen';
12
13
  export * from './screens/ThemePaletteScreen';
13
14
  export * from './screens/ThemeTypographyScreen';
14
15
  export * from './types';
@@ -1 +1 @@
1
- {"version":3,"file":"PhilosophyPage.d.ts","sourceRoot":"","sources":["../../src/pages/PhilosophyPage.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAkB1B,MAAM,MAAM,mBAAmB,GAAG;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACjC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,kCAAkC,mBAAmB,sBAoFnF,CAAC"}
1
+ {"version":3,"file":"PhilosophyPage.d.ts","sourceRoot":"","sources":["../../src/pages/PhilosophyPage.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAmB1B,MAAM,MAAM,mBAAmB,GAAG;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACjC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,kCAAkC,mBAAmB,sBAyFnF,CAAC"}
@@ -1,11 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Page, Section, Typography } from '@alveole/components';
2
+ import { Box, Page, PageHeader, Section, Typography } from '@alveole/components';
3
3
  import { useTheme } from '@alveole/theme';
4
+ import { screenContent } from '../styles';
4
5
  const PhilosophySection = ({ title, children }) => {
5
6
  const { text } = useTheme();
6
7
  return (_jsxs(Box, { display: "flex", gap: 8, mb: '400', children: [_jsx(Typography, { style: text.Titres['H4 - SM'], children: title }), children] }));
7
8
  };
8
9
  export const PhilosophyPage = ({ beforeContent, footerContent }) => {
9
10
  const { text } = useTheme();
10
- return (_jsx(Page, { scrollable: true, title: "Philosophie", description: "Les principes qui guident Alveole", beforeContent: beforeContent, footerContent: footerContent, children: _jsx(Section, { withPaddingY: true, children: _jsxs(Box, { display: "flex", gap: 0, style: { maxWidth: 720 }, children: [_jsx(PhilosophySection, { title: "Objectif", children: _jsxs(Typography, { style: text['Corps de texte'].MD.Regular, children: ["Alveole est un framework de composants conçu pour accélérer la construction d'outils B2B. L'ambition est", ' de proposer une expérience clé en main : installer les packages, utiliser les composants, livrer. Pas de', ' configuration interminable, pas de décisions de design à prendre à chaque écran.'] }) }), _jsx(PhilosophySection, { title: "Convention plut\u00F4t que configuration", children: _jsxs(Typography, { style: text['Corps de texte'].MD.Regular, children: ["Alveole s'inspire du principe ", _jsx(Typography, { style: text['Corps de texte'].MD.Regular, children: "Convention over Configuration" }), ' : le thème par défaut est pensé pour fonctionner sans ajustement. La customisation reste possible — palette,', ' typographie, espacements — mais elle est optionnelle et ciblée. Le but est de ne pas passer du temps à', ' configurer ce qui fonctionne déjà bien.'] }) }), _jsx(PhilosophySection, { title: "Des composants pens\u00E9s pour l'UX", children: _jsxs(Typography, { style: text['Corps de texte'].MD.Regular, children: ["Chaque composant embarque les meilleures pratiques UI et UX de sa catégorie. L'objectif n'est pas de", " fournir une brique neutre que chaque projet devra affiner, mais un composant fini qui propose d'emblée la", " meilleure expérience pour l'utilisateur final. Il ne faut pas réinventer la roue à chaque projet."] }) }), _jsx(PhilosophySection, { title: "Des choix assum\u00E9s", children: _jsxs(Typography, { style: text['Corps de texte'].MD.Regular, children: ['Certaines décisions ne sont pas exposées en configuration. Par exemple, les icônes Lucide utilisent', ' systématiquement un ', _jsx(Typography, { style: text['Corps de texte'].MD.Regular, children: "strokeWidth \u00E0 1.5" }), " — cette valeur n'est pas modifiable par le consommateur du composant. Ce type de choix garantit la cohérence", " visuelle de l'ensemble : un design system qui offre trop de flexibilité cesse d'être un design system."] }) }), _jsx(PhilosophySection, { title: "Inspirations", children: _jsxs(Typography, { style: text['Corps de texte'].MD.Regular, children: ["Alveole s'inspire de deux systèmes de design de référence dans l'écosystème B2B et open source :", " l'Atlassian Design System, reconnu pour sa rigueur dans les outils professionnels, et Primer, le design", ' system de GitHub, apprécié pour sa clarté et sa cohérence à grande échelle.'] }) }), _jsx(PhilosophySection, { title: "Construit dans la dur\u00E9e par Captive", children: _jsxs(Typography, { style: text['Corps de texte'].MD.Regular, children: ['Alveole est maintenu par Captive et évolue au fil des projets réels. Chaque composant est extrait,', ' généralisé et affiné à partir de besoins concrets. Le framework grandit progressivement, avec une', " attention constante à la qualité plutôt qu'à l'exhaustivité."] }) })] }) }) }));
11
+ return (_jsx(Page, { scrollable: true, title: "Philosophie", description: "Les principes qui guident Alveole", beforeContent: beforeContent, footerContent: footerContent, children: _jsxs(Box, { ...screenContent, children: [_jsx(Section, { withPaddingY: false, children: _jsx(PageHeader, { title: "Philosophie" }) }), _jsx(Section, { withPaddingY: false, children: _jsxs(Box, { display: "flex", gap: 0, style: { maxWidth: 720 }, children: [_jsx(PhilosophySection, { title: "Objectif", children: _jsxs(Typography, { style: text['Corps de texte'].MD.Regular, children: ["Alveole est un framework de composants conçu pour accélérer la construction d'outils B2B. L'ambition est", ' de proposer une expérience clé en main : installer les packages, utiliser les composants, livrer. Pas de', ' configuration interminable, pas de décisions de design à prendre à chaque écran.'] }) }), _jsx(PhilosophySection, { title: "Convention plut\u00F4t que configuration", children: _jsxs(Typography, { style: text['Corps de texte'].MD.Regular, children: ["Alveole s'inspire du principe ", _jsx(Typography, { style: text['Corps de texte'].MD.Regular, children: "Convention over Configuration" }), ' : le thème par défaut est pensé pour fonctionner sans ajustement. La customisation reste possible — palette,', ' typographie, espacements — mais elle est optionnelle et ciblée. Le but est de ne pas passer du temps à', ' configurer ce qui fonctionne déjà bien.'] }) }), _jsx(PhilosophySection, { title: "Des composants pens\u00E9s pour l'UX", children: _jsxs(Typography, { style: text['Corps de texte'].MD.Regular, children: ["Chaque composant embarque les meilleures pratiques UI et UX de sa catégorie. L'objectif n'est pas de", " fournir une brique neutre que chaque projet devra affiner, mais un composant fini qui propose d'emblée la", " meilleure expérience pour l'utilisateur final. Il ne faut pas réinventer la roue à chaque projet."] }) }), _jsx(PhilosophySection, { title: "Des choix assum\u00E9s", children: _jsxs(Typography, { style: text['Corps de texte'].MD.Regular, children: ['Certaines décisions ne sont pas exposées en configuration. Par exemple, les icônes Lucide utilisent', ' systématiquement un ', _jsx(Typography, { style: text['Corps de texte'].MD.Regular, children: "strokeWidth \u00E0 1.5" }), " — cette valeur n'est pas modifiable par le consommateur du composant. Ce type de choix garantit la cohérence", " visuelle de l'ensemble : un design system qui offre trop de flexibilité cesse d'être un design system."] }) }), _jsx(PhilosophySection, { title: "Inspirations", children: _jsxs(Typography, { style: text['Corps de texte'].MD.Regular, children: ["Alveole s'inspire de deux systèmes de design de référence dans l'écosystème B2B et open source :", " l'Atlassian Design System, reconnu pour sa rigueur dans les outils professionnels, et Primer, le design", ' system de GitHub, apprécié pour sa clarté et sa cohérence à grande échelle.'] }) }), _jsx(PhilosophySection, { title: "Construit dans la dur\u00E9e par Captive", children: _jsxs(Typography, { style: text['Corps de texte'].MD.Regular, children: ['Alveole est maintenu par Captive et évolue au fil des projets réels. Chaque composant est extrait,', ' généralisé et affiné à partir de besoins concrets. Le framework grandit progressivement, avec une', " attention constante à la qualité plutôt qu'à l'exhaustivité."] }) })] }) })] }) }));
11
12
  };
@@ -1 +1 @@
1
- {"version":3,"file":"StoriesScreen.d.ts","sourceRoot":"","sources":["../../src/screens/StoriesScreen.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,EAAiB,eAAe,EAAE,MAAM,UAAU,CAAC;AAW1D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAClD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,yHAU3B,kBAAkB,sBAiKpB,CAAC"}
1
+ {"version":3,"file":"StoriesScreen.d.ts","sourceRoot":"","sources":["../../src/screens/StoriesScreen.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,EAAiB,eAAe,EAAE,MAAM,UAAU,CAAC;AAW1D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAClD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,yHAU3B,kBAAkB,sBAkJpB,CAAC"}
@@ -1,11 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Box, Button, Page, Section, Typography } from '@alveole/components';
2
+ import { ActionMenu, Box, Button, Page, PageHeader, Section, Typography } from '@alveole/components';
3
3
  import { useTheme } from '@alveole/theme';
4
4
  import React from 'react';
5
- import { useWindowDimensions } from 'react-native';
6
- import { FilterBadge } from '../components/FilterBadge';
5
+ import { Platform, ScrollView, useWindowDimensions } from 'react-native';
7
6
  import { SearchField } from '../components/SearchField';
8
7
  import { StoryCard } from '../components/StoryCard';
8
+ import { screenContent } from '../styles';
9
9
  import { filterStories, getAllStoryTags, groupStoriesByTag } from '../utils';
10
10
  const AVAILABLE_FLAGS = [
11
11
  { key: 'figma', label: 'Figma' },
@@ -15,7 +15,7 @@ const AVAILABLE_FLAGS = [
15
15
  { key: 'mobileOnly', label: 'Mobile only' },
16
16
  ];
17
17
  export const StoriesScreen = ({ stories, title = 'UI Kit - Components', description = 'Shared component catalog', emptyMessage = 'No story found.', beforeContent, footerContent, createLabel, onCreatePress, onSelectStory, }) => {
18
- const { text, color, radius } = useTheme();
18
+ const { text } = useTheme();
19
19
  const { width } = useWindowDimensions();
20
20
  const columns = width >= 1200 ? 3 : width >= 768 ? 2 : 1;
21
21
  const columnStyle = columns === 1
@@ -26,6 +26,7 @@ export const StoriesScreen = ({ stories, title = 'UI Kit - Components', descript
26
26
  const [query, setQuery] = React.useState('');
27
27
  const [selectedTag, setSelectedTag] = React.useState(null);
28
28
  const [selectedFlag, setSelectedFlag] = React.useState(null);
29
+ const [openFilter, setOpenFilter] = React.useState(null);
29
30
  const allTags = React.useMemo(() => getAllStoryTags(stories), [stories]);
30
31
  const filteredStories = React.useMemo(() => filterStories({
31
32
  stories,
@@ -34,22 +35,11 @@ export const StoriesScreen = ({ stories, title = 'UI Kit - Components', descript
34
35
  selectedFlag,
35
36
  }), [stories, query, selectedTag, selectedFlag]);
36
37
  const groupedStories = React.useMemo(() => groupStoriesByTag(filteredStories, allTags), [filteredStories, allTags]);
37
- const hasActiveFilters = query.trim().length > 0 || selectedTag !== null || selectedFlag !== null;
38
- const activeFiltersCount = [query.trim().length > 0, selectedTag !== null, selectedFlag !== null].filter(Boolean).length;
39
- return (_jsxs(Page, { scrollable: true, title: title, description: description, beforeContent: _jsxs(_Fragment, { children: [beforeContent, createLabel && onCreatePress ? (_jsx(Section, { withPaddingY: true, children: _jsx(Box, { style: { alignItems: 'flex-end' }, children: _jsx(Button, { title: createLabel, variant: "primary", onPress: onCreatePress }) }) })) : null] }), children: [_jsx(Section, { withPaddingY: true, children: _jsxs(Box, { borderColor: color.light.border['default-grey'], borderRadius: radius('lg'), borderWidth: 1, display: "flex", gap: 16, p: '150', style: {
40
- backgroundColor: color.light.background['alt-grey'],
41
- }, children: [_jsxs(Box, { display: "flex", gap: 12, style: {
42
- alignItems: width >= 1024 ? 'center' : 'stretch',
43
- flexDirection: width >= 1024 ? 'row' : 'column',
44
- justifyContent: 'space-between',
45
- }, children: [_jsxs(Box, { display: "flex", gap: 4, children: [_jsx(Typography, { style: text.Titres['H5 - XS'], children: "Filtres" }), _jsxs(Typography, { style: text['Corps de texte'].SM.Regular, children: [filteredStories.length, " composant", filteredStories.length > 1 ? 's' : '', hasActiveFilters
46
- ? `, ${activeFiltersCount} filtre${activeFiltersCount > 1 ? 's' : ''} actif${activeFiltersCount > 1 ? 's' : ''}`
47
- : ''] })] }), hasActiveFilters ? (_jsx(Button, { title: "R\u00E9initialiser", variant: "tertiary", size: "sm", onPress: () => {
48
- setQuery('');
49
- setSelectedTag(null);
50
- setSelectedFlag(null);
51
- } })) : null] }), _jsx(SearchField, { label: "Recherche", placeholder: "Button, Tabs, Card...", value: query, onChangeText: setQuery }), _jsxs(Box, { display: "flex", gap: 16, style: {
52
- alignItems: 'flex-start',
53
- flexDirection: width >= 1024 ? 'row' : 'column',
54
- }, children: [_jsxs(Box, { display: "flex", gap: 8, style: { flex: 1, width: '100%' }, children: [_jsx(Typography, { style: text['Corps de texte'].XS.CapsBold, children: "Tags" }), _jsxs(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 8, children: [_jsx(FilterBadge, { active: selectedTag === null, label: "Tous", onPress: () => setSelectedTag(null) }), allTags.map(tag => (_jsx(FilterBadge, { active: selectedTag === tag, label: tag, onPress: () => setSelectedTag(current => (current === tag ? null : tag)) }, tag)))] })] }), _jsxs(Box, { display: "flex", gap: 8, style: { flex: 1, width: '100%' }, children: [_jsx(Typography, { style: text['Corps de texte'].XS.CapsBold, children: "Indicateurs" }), _jsxs(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 8, children: [_jsx(FilterBadge, { active: selectedFlag === null, label: "Tous", onPress: () => setSelectedFlag(null) }), AVAILABLE_FLAGS.map(flag => (_jsx(FilterBadge, { active: selectedFlag === flag.key, label: flag.label, onPress: () => setSelectedFlag(current => (current === flag.key ? null : flag.key)) }, flag.key)))] })] })] })] }) }), groupedStories.length === 0 ? (_jsx(Section, { withPaddingY: true, children: _jsx(Typography, { style: text['Corps de texte'].MD.Regular, children: emptyMessage }) })) : (groupedStories.map(([tag, taggedStories]) => (_jsx(Section, { withPaddingY: true, children: _jsxs(Box, { display: "flex", gap: 16, children: [_jsx(Typography, { style: text.Titres['H4 - SM'], children: tag }), _jsx(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 16, children: taggedStories.map(story => (_jsx(Box, { style: { alignSelf: 'stretch', width: columnStyle.width }, children: _jsx(StoryCard, { story: story, onPress: onSelectStory }) }, story.default.title))) })] }) }, tag)))), footerContent] }));
38
+ return (_jsxs(Page, { scrollable: true, title: title, description: description, beforeContent: _jsxs(_Fragment, { children: [beforeContent, createLabel && onCreatePress ? (_jsx(Section, { withPaddingY: true, children: _jsx(Box, { style: { alignItems: 'flex-end' }, children: _jsx(Button, { title: createLabel, variant: "primary", onPress: onCreatePress }) }) })) : null] }), children: [_jsxs(Box, { ...screenContent, children: [_jsx(Section, { withPaddingY: false, children: _jsx(PageHeader, { title: title }) }), _jsx(Section, { withPaddingY: false, children: _jsxs(ScrollView, { horizontal: true, nestedScrollEnabled: true, directionalLockEnabled: Platform.OS === 'ios', showsHorizontalScrollIndicator: false, contentContainerStyle: { flexDirection: 'row', gap: 8, alignItems: 'center' }, children: [_jsx(Box, { style: { minWidth: 200 }, children: _jsx(SearchField, { placeholder: "Button, Tabs, Card...", value: query, onChangeText: setQuery, size: "sm" }) }), _jsx(ActionMenu, { placement: "bottom-start", scrollable: false, open: openFilter === 'tags', setOpen: open => setOpenFilter(open ? 'tags' : null), renderTrigger: () => (_jsx(Button, { variant: "secondary", title: selectedTag ?? 'Tags', endIcon: "ChevronDown", size: "sm", selected: selectedTag !== null, active: openFilter === 'tags' })), children: allTags.map(tag => (_jsx(ActionMenu.Item, { title: tag, selected: selectedTag === tag, onPress: () => {
39
+ setSelectedTag(prev => (prev === tag ? null : tag));
40
+ setOpenFilter(null);
41
+ } }, tag))) }), _jsx(ActionMenu, { placement: "bottom-start", scrollable: false, open: openFilter === 'indicateurs', setOpen: open => setOpenFilter(open ? 'indicateurs' : null), renderTrigger: () => (_jsx(Button, { variant: "secondary", title: AVAILABLE_FLAGS.find(f => f.key === selectedFlag)?.label ?? 'Indicateurs', endIcon: "ChevronDown", size: "sm", selected: selectedFlag !== null, active: openFilter === 'indicateurs' })), children: AVAILABLE_FLAGS.map(flag => (_jsx(ActionMenu.Item, { title: flag.label, selected: selectedFlag === flag.key, onPress: () => {
42
+ setSelectedFlag(prev => (prev === flag.key ? null : flag.key));
43
+ setOpenFilter(null);
44
+ } }, flag.key))) })] }) }), groupedStories.length === 0 ? (_jsx(Section, { withPaddingY: false, children: _jsx(Typography, { style: text['Corps de texte'].MD.Regular, children: emptyMessage }) })) : (groupedStories.map(([tag, taggedStories]) => (_jsx(Section, { withPaddingY: false, children: _jsxs(Box, { display: "flex", gap: 16, children: [_jsx(Typography, { style: text.Titres['H4 - SM'], children: tag }), _jsx(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 16, children: taggedStories.map(story => (_jsx(Box, { style: { alignSelf: 'stretch', width: columnStyle.width }, children: _jsx(StoryCard, { story: story, onPress: onSelectStory }) }, story.default.title))) })] }) }, tag))))] }), footerContent] }));
55
45
  };
@@ -1 +1 @@
1
- {"version":3,"file":"StoryDetailScreen.d.ts","sourceRoot":"","sources":["../../src/screens/StoryDetailScreen.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACjC,CAAC;AAiIF,eAAO,MAAM,iBAAiB,GAAI,2DAK/B,sBAAsB,sBAmKxB,CAAC"}
1
+ {"version":3,"file":"StoryDetailScreen.d.ts","sourceRoot":"","sources":["../../src/screens/StoryDetailScreen.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACjC,CAAC;AAiIF,eAAO,MAAM,iBAAiB,GAAI,2DAK/B,sBAAsB,sBAwKxB,CAAC"}
@@ -1,9 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { AnchorHeading, Box, Button, Divider, Page, Section, Typography } from '@alveole/components';
2
+ import { AnchorHeading, Box, Button, Divider, Page, PageHeader, Section, Typography } from '@alveole/components';
3
3
  import { useTheme } from '@alveole/theme';
4
4
  import React from 'react';
5
5
  import { Linking, ScrollView } from 'react-native';
6
6
  import { JsonBlock } from '../components/JsonBlock';
7
+ import { screenContent } from '../styles';
7
8
  import { getStoryExamples, getStoryFlags } from '../utils';
8
9
  const DetailPill = ({ label, tone = 'info' }) => {
9
10
  const { color, radius, text, spacing } = useTheme();
@@ -57,32 +58,32 @@ export const StoryDetailScreen = ({ story, notFoundMessage = 'Story not found.',
57
58
  minHeight: isTemplate ? 420 : undefined,
58
59
  }, children: _jsx(Example, {}) }), _jsx(Divider, { mt: "1W", mb: "1,5V" }), source ? _jsx(JsonBlock, { language: "tsx", value: source }) : null] }, key));
59
60
  }) }));
60
- return (_jsx(Page, { scrollable: true, title: meta.title, description: meta.description, beforeContent: beforeContent, footerContent: footerContent, children: _jsx(Section, { withPaddingY: true, children: _jsxs(Box, { display: "flex", gap: 20, children: [_jsxs(Box, { borderColor: color.light.border['default-grey'], borderRadius: radius('lg'), borderWidth: 1, display: "flex", gap: 16, p: '150', style: { backgroundColor: color.light.background['alt-grey'] }, children: [_jsxs(Box, { display: "flex", gap: 12, style: {
61
- alignItems: 'flex-start',
62
- flexDirection: 'row',
63
- justifyContent: 'space-between',
64
- }, children: [_jsxs(Box, { display: "flex", gap: 6, style: { flex: 1 }, children: [_jsx(Typography, { style: text.Titres['H3 - MD'], children: meta.title }), _jsx(Typography, { style: text['Corps de texte'].MD.Regular, children: meta.description })] }), meta.figmaURL ? (_jsx(Button, { title: "Ouvrir Figma", variant: "primary", onPress: () => Linking.openURL(meta.figmaURL) })) : null] }), _jsxs(Box, { display: "flex", gap: 10, children: [_jsx(Typography, { style: text['Corps de texte'].XS.CapsBold, children: "Tags" }), _jsx(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 8, children: meta.tags.map(tag => (_jsx(DetailPill, { label: tag, tone: "tag" }, tag))) })] }), flags.length > 0 ? (_jsxs(Box, { display: "flex", gap: 10, children: [_jsx(Typography, { style: text['Corps de texte'].XS.CapsBold, children: "Informations" }), _jsx(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 8, children: flags.map(flag => (_jsx(DetailPill, { label: flag.label }, flag.key))) })] })) : null, _jsxs(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 12, children: [_jsx(MetaCard, { label: "Exemples", value: String(examples.length) }), _jsx(MetaCard, { label: "Styles", value: "Disponibles" }), meta.props != null ? _jsx(MetaCard, { label: "Props", value: "Document\u00E9es" }) : null] })] }), _jsx(DetailTabs, { defaultValue: "examples", tabs: [
65
- {
66
- value: 'examples',
67
- label: 'Examples',
68
- content: examplesContent,
69
- scrollable: true,
70
- },
71
- {
72
- value: 'styles',
73
- label: 'Styles',
74
- content: _jsx(JsonBlock, { value: meta.styleFn() }),
75
- scrollable: true,
76
- },
77
- ...(meta.props != null
78
- ? [
61
+ return (_jsx(Page, { scrollable: true, title: meta.title, description: meta.description, beforeContent: beforeContent, footerContent: footerContent, children: _jsxs(Box, { ...screenContent, children: [_jsx(Section, { withPaddingY: false, children: _jsx(PageHeader, { title: meta.title }) }), _jsx(Section, { withPaddingY: false, children: _jsxs(Box, { display: "flex", gap: 20, children: [_jsxs(Box, { borderColor: color.light.border['default-grey'], borderRadius: radius('lg'), borderWidth: 1, display: "flex", gap: 16, p: '150', style: { backgroundColor: color.light.background['alt-grey'] }, children: [_jsxs(Box, { display: "flex", gap: 12, style: {
62
+ alignItems: 'flex-start',
63
+ flexDirection: 'row',
64
+ justifyContent: 'space-between',
65
+ }, children: [_jsxs(Box, { display: "flex", gap: 6, style: { flex: 1 }, children: [_jsx(Typography, { style: text.Titres['H3 - MD'], children: meta.title }), _jsx(Typography, { style: text['Corps de texte'].MD.Regular, children: meta.description })] }), meta.figmaURL ? (_jsx(Button, { title: "Ouvrir Figma", variant: "primary", onPress: () => Linking.openURL(meta.figmaURL) })) : null] }), _jsxs(Box, { display: "flex", gap: 10, children: [_jsx(Typography, { style: text['Corps de texte'].XS.CapsBold, children: "Tags" }), _jsx(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 8, children: meta.tags.map(tag => (_jsx(DetailPill, { label: tag, tone: "tag" }, tag))) })] }), flags.length > 0 ? (_jsxs(Box, { display: "flex", gap: 10, children: [_jsx(Typography, { style: text['Corps de texte'].XS.CapsBold, children: "Informations" }), _jsx(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 8, children: flags.map(flag => (_jsx(DetailPill, { label: flag.label }, flag.key))) })] })) : null, _jsxs(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 12, children: [_jsx(MetaCard, { label: "Exemples", value: String(examples.length) }), _jsx(MetaCard, { label: "Styles", value: "Disponibles" }), meta.props != null ? _jsx(MetaCard, { label: "Props", value: "Document\u00E9es" }) : null] })] }), _jsx(DetailTabs, { defaultValue: "examples", tabs: [
79
66
  {
80
- value: 'props',
81
- label: 'Props',
82
- content: _jsx(JsonBlock, { value: meta.props }),
67
+ value: 'examples',
68
+ label: 'Examples',
69
+ content: examplesContent,
83
70
  scrollable: true,
84
71
  },
85
- ]
86
- : []),
87
- ] })] }) }) }));
72
+ {
73
+ value: 'styles',
74
+ label: 'Styles',
75
+ content: _jsx(JsonBlock, { value: meta.styleFn() }),
76
+ scrollable: true,
77
+ },
78
+ ...(meta.props != null
79
+ ? [
80
+ {
81
+ value: 'props',
82
+ label: 'Props',
83
+ content: _jsx(JsonBlock, { value: meta.props }),
84
+ scrollable: true,
85
+ },
86
+ ]
87
+ : []),
88
+ ] })] }) })] }) }));
88
89
  };
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ export type ThemeCSSVariablesScreenProps = {
3
+ beforeContent?: React.ReactNode;
4
+ footerContent?: React.ReactNode;
5
+ };
6
+ export declare const ThemeCSSVariablesScreen: ({ beforeContent, footerContent }: ThemeCSSVariablesScreenProps) => React.JSX.Element;
7
+ //# sourceMappingURL=ThemeCSSVariablesScreen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeCSSVariablesScreen.d.ts","sourceRoot":"","sources":["../../src/screens/ThemeCSSVariablesScreen.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,MAAM,OAAO,CAAC;AA0P1B,MAAM,MAAM,4BAA4B,GAAG;IACzC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACjC,CAAC;AAIF,eAAO,MAAM,uBAAuB,GAAI,kCAAkC,4BAA4B,sBA+DrG,CAAC"}
@@ -0,0 +1,183 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Accordion, Box, Page, PageHeader, Section, Typography, useToast } from '@alveole/components';
3
+ import { Colors, CustomPalette, Spacings, useTheme } from '@alveole/theme';
4
+ import { Elevations } from '@alveole/theme/src/constants/Elevation';
5
+ import { FontWeightMap } from '@alveole/theme/src/constants/Font';
6
+ import { RadiusList } from '@alveole/theme/src/constants/Radius';
7
+ import { CustomTypography } from '@alveole/theme/src/constants/Typography';
8
+ import { sanitizeCSSKey } from '@alveole/theme/src/helpers/sanitizeCSSKey';
9
+ import React from 'react';
10
+ import { Platform, Pressable } from 'react-native';
11
+ import { screenContent } from '../styles';
12
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
13
+ function collectTypographyVarNames(node, path, out) {
14
+ if (typeof node.fontSize === 'number') {
15
+ const prefix = `--typography-${path.map(sanitizeCSSKey).join('-')}`;
16
+ out.push({ name: `${prefix}-font-size`, rawValue: `${node.fontSize}px`, preview: 'none' });
17
+ out.push({ name: `${prefix}-line-height`, rawValue: `${node.lineHeight}px`, preview: 'none' });
18
+ if (typeof node.fontFamily === 'string') {
19
+ out.push({ name: `${prefix}-font-family`, rawValue: node.fontFamily, preview: 'none' });
20
+ }
21
+ if (typeof node.fontWeight === 'string') {
22
+ out.push({ name: `${prefix}-font-weight`, rawValue: node.fontWeight, preview: 'none' });
23
+ }
24
+ return;
25
+ }
26
+ Object.entries(node).forEach(([key, value]) => {
27
+ if (typeof value === 'object' && value !== null) {
28
+ collectTypographyVarNames(value, [...path, key], out);
29
+ }
30
+ });
31
+ }
32
+ function buildGroups() {
33
+ const groups = [];
34
+ // Couleurs palette
35
+ const paletteVars = [];
36
+ Object.entries(Colors).forEach(([name, shades]) => {
37
+ Object.entries(shades).forEach(([variant, value]) => {
38
+ paletteVars.push({
39
+ name: `--color-${name}-${variant}`,
40
+ rawValue: value,
41
+ preview: 'color',
42
+ });
43
+ });
44
+ });
45
+ groups.push({ title: 'Couleurs palette', vars: paletteVars });
46
+ // Tokens sémantiques light
47
+ const semanticCategories = ['background', 'text', 'border', 'artwork', 'system'];
48
+ semanticCategories.forEach(category => {
49
+ const tokens = CustomPalette.light[category];
50
+ if (!tokens)
51
+ return;
52
+ const vars = Object.entries(tokens)
53
+ .filter(([, value]) => typeof value === 'string')
54
+ .map(([token, value]) => ({
55
+ name: `--${category}-${token}`,
56
+ rawValue: value,
57
+ preview: 'color',
58
+ }));
59
+ if (vars.length)
60
+ groups.push({ title: `Tokens — ${category}`, vars });
61
+ });
62
+ // Spacing
63
+ groups.push({
64
+ title: 'Spacing',
65
+ vars: Object.entries(Spacings).map(([key, value]) => ({
66
+ name: `--spacing-${sanitizeCSSKey(key)}`,
67
+ rawValue: `${value}px`,
68
+ preview: 'spacing',
69
+ })),
70
+ });
71
+ // Radius
72
+ groups.push({
73
+ title: 'Radius',
74
+ vars: Object.entries(RadiusList).map(([key, value]) => ({
75
+ name: `--radius-${key}`,
76
+ rawValue: `${value}px`,
77
+ preview: 'radius',
78
+ })),
79
+ });
80
+ // Elevations
81
+ groups.push({
82
+ title: 'Elevations',
83
+ vars: Object.entries(Elevations).map(([key, value]) => ({
84
+ name: `--elevation-${key}`,
85
+ rawValue: value.web,
86
+ preview: 'elevation',
87
+ })),
88
+ });
89
+ // Fonts
90
+ groups.push({
91
+ title: 'Fonts',
92
+ vars: Object.entries(FontWeightMap).flatMap(([key, { familyWithFallback, weight }]) => [
93
+ { name: `--font-${key}-family`, rawValue: familyWithFallback, preview: 'none' },
94
+ { name: `--font-${key}-weight`, rawValue: weight, preview: 'none' },
95
+ ]),
96
+ });
97
+ // Typographies
98
+ const typoVars = [];
99
+ collectTypographyVarNames(CustomTypography, [], typoVars);
100
+ groups.push({ title: 'Typographies', vars: typoVars });
101
+ return groups;
102
+ }
103
+ // ─── Preview components ────────────────────────────────────────────────────────
104
+ const ColorPreview = ({ value }) => (_jsx(Box, { style: {
105
+ width: 28,
106
+ height: 28,
107
+ borderRadius: 6,
108
+ backgroundColor: value,
109
+ borderWidth: 1,
110
+ borderColor: 'rgba(0,0,0,0.1)',
111
+ flexShrink: 0,
112
+ } }));
113
+ const SpacingPreview = ({ value }) => {
114
+ const px = parseInt(value, 10);
115
+ const width = Math.min(px, 96);
116
+ return (_jsx(Box, { style: {
117
+ width,
118
+ height: 12,
119
+ borderRadius: 2,
120
+ backgroundColor: '#3B82F6',
121
+ flexShrink: 0,
122
+ alignSelf: 'center',
123
+ } }));
124
+ };
125
+ const RadiusPreview = ({ value }) => {
126
+ const px = Math.min(parseInt(value, 10), 14);
127
+ return (_jsx(Box, { style: {
128
+ width: 28,
129
+ height: 28,
130
+ borderRadius: px,
131
+ borderWidth: 2,
132
+ borderColor: '#3B82F6',
133
+ flexShrink: 0,
134
+ } }));
135
+ };
136
+ const ElevationPreview = ({ value }) => Platform.OS === 'web' ? (_jsx(Box, { style: {
137
+ width: 28,
138
+ height: 28,
139
+ borderRadius: 4,
140
+ backgroundColor: 'white',
141
+ boxShadow: value,
142
+ flexShrink: 0,
143
+ } })) : null;
144
+ // ─── Row ──────────────────────────────────────────────────────────────────────
145
+ const VarRow = ({ entry }) => {
146
+ const { color } = useTheme();
147
+ const toast = useToast();
148
+ const copy = () => {
149
+ if (typeof navigator !== 'undefined' && navigator.clipboard) {
150
+ navigator.clipboard.writeText(entry.name).then(() => {
151
+ toast.present('Copié !', entry.name, { variant: 'success', duration: 1500 });
152
+ });
153
+ }
154
+ };
155
+ return (_jsx(Pressable, { onPress: copy, children: ({ pressed }) => (_jsxs(Box, { style: {
156
+ flexDirection: 'row',
157
+ alignItems: 'center',
158
+ gap: 12,
159
+ paddingVertical: 6,
160
+ paddingHorizontal: 12,
161
+ borderRadius: 6,
162
+ backgroundColor: pressed ? color.light.background['transparent-hover'] : 'transparent',
163
+ }, children: [entry.preview === 'color' && _jsx(ColorPreview, { value: entry.rawValue }), entry.preview === 'spacing' && _jsx(SpacingPreview, { value: entry.rawValue }), entry.preview === 'radius' && _jsx(RadiusPreview, { value: entry.rawValue }), entry.preview === 'elevation' && _jsx(ElevationPreview, { value: entry.rawValue }), entry.preview === 'none' && _jsx(Box, { style: { width: 28 } }), _jsxs(Box, { style: { flex: 1, gap: 1 }, children: [_jsx(Typography, { style: {
164
+ fontSize: 12,
165
+ fontFamily: 'monospace',
166
+ color: color.light.text['title-grey'],
167
+ lineHeight: 16,
168
+ }, numberOfLines: 1, children: entry.name }), _jsx(Typography, { style: {
169
+ fontSize: 11,
170
+ fontFamily: 'monospace',
171
+ color: color.light.text['mention-grey'],
172
+ lineHeight: 14,
173
+ }, numberOfLines: 1, children: entry.rawValue })] }), _jsx(Typography, { style: { fontSize: 11, color: color.light.text['mention-grey'] }, children: '⎘' })] })) }));
174
+ };
175
+ const COLLAPSED_BY_DEFAULT = ['Typographies', 'Fonts', 'Couleurs palette'];
176
+ export const ThemeCSSVariablesScreen = ({ beforeContent, footerContent }) => {
177
+ const { color } = useTheme();
178
+ const groups = React.useMemo(() => buildGroups(), []);
179
+ const total = groups.reduce((sum, g) => sum + g.vars.length, 0);
180
+ const initialOpen = React.useMemo(() => groups.filter(g => !COLLAPSED_BY_DEFAULT.some(prefix => g.title.startsWith(prefix))).map(g => g.title), [groups]);
181
+ const [openGroups, setOpenGroups] = React.useState(initialOpen);
182
+ return (_jsx(Page, { scrollable: true, title: "Variables CSS", description: "Toutes les variables CSS inject\u00E9es par le ThemeProvider", beforeContent: beforeContent, footerContent: footerContent, children: _jsxs(Box, { ...screenContent, children: [_jsx(Section, { withPaddingY: false, children: _jsx(PageHeader, { title: "Variables CSS", breadcrumbsProps: { getHref: (segment, _index, path) => (segment === 'theme' ? null : path) } }) }), _jsxs(Section, { withPaddingY: false, children: [_jsxs(Typography, { style: { fontSize: 14, color: color.light.text['mention-grey'], marginBottom: 8 }, children: [`${total} variables injectées dans `, _jsx(Typography, { style: { fontSize: 14, fontFamily: 'monospace', color: color.light.text['default-grey'] }, children: ':root' }), ' par le ThemeProvider sur web. Cliquez sur une ligne pour copier le nom de la variable.'] }), _jsx(Typography, { style: { fontSize: 13, color: color.light.text['mention-grey'], marginBottom: 24, fontFamily: 'monospace' }, children: 'color: var(--background-action-high-primary);' }), _jsx(Accordion, { type: "multiple", value: openGroups, onValueChange: setOpenGroups, children: groups.map(g => (_jsx(Accordion.Item, { value: g.title, label: g.title, variant: "alt", labelChildren: _jsx(Typography, { style: { fontSize: 11, color: color.light.text['mention-grey'] }, children: `${g.vars.length} var${g.vars.length > 1 ? 's' : ''}` }), noPadding: true, children: g.vars.map(v => (_jsx(VarRow, { entry: v }, v.name))) }, g.title))) })] })] }) }));
183
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeConstantDetailScreen.d.ts","sourceRoot":"","sources":["../../src/screens/ThemeConstantDetailScreen.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,MAAM,8BAA8B,GAAG;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACjC,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,gDAKvC,8BAA8B,sBAsBhC,CAAC"}
1
+ {"version":3,"file":"ThemeConstantDetailScreen.d.ts","sourceRoot":"","sources":["../../src/screens/ThemeConstantDetailScreen.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,MAAM,8BAA8B,GAAG;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACjC,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,gDAKvC,8BAA8B,sBA2BhC,CAAC"}
@@ -1,9 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Page, Section, Typography } from '@alveole/components';
2
+ import { Box, Page, PageHeader, Section, Typography } from '@alveole/components';
3
3
  import { useTheme } from '@alveole/theme';
4
4
  import { JsonBlock } from '../components/JsonBlock';
5
+ import { screenContent } from '../styles';
5
6
  export const ThemeConstantDetailScreen = ({ name, value, beforeContent, footerContent, }) => {
6
7
  const { text } = useTheme();
7
8
  const entries = typeof value === 'object' && value != null ? Object.entries(value) : [];
8
- return (_jsx(Page, { scrollable: true, title: name, description: name, beforeContent: beforeContent, footerContent: footerContent, children: _jsx(Section, { withPaddingY: true, children: _jsx(Box, { display: "flex", gap: 16, children: entries.length === 0 ? (_jsx(JsonBlock, { value: value })) : (entries.map(([entryName, entryValue]) => (_jsxs(Box, { display: "flex", gap: 8, children: [_jsx(Typography, { style: text.Titres['H6 - XXS'], children: entryName }), _jsx(JsonBlock, { value: entryValue })] }, entryName)))) }) }) }));
9
+ return (_jsx(Page, { scrollable: true, title: name, description: name, beforeContent: beforeContent, footerContent: footerContent, children: _jsxs(Box, { ...screenContent, children: [_jsx(Section, { withPaddingY: false, children: _jsx(PageHeader, { title: name }) }), _jsx(Section, { withPaddingY: false, children: _jsx(Box, { display: "flex", gap: 16, children: entries.length === 0 ? (_jsx(JsonBlock, { value: value })) : (entries.map(([entryName, entryValue]) => (_jsxs(Box, { display: "flex", gap: 8, children: [_jsx(Typography, { style: text.Titres['H6 - XXS'], children: entryName }), _jsx(JsonBlock, { value: entryValue })] }, entryName)))) }) })] }) }));
9
10
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeConstantsScreen.d.ts","sourceRoot":"","sources":["../../src/screens/ThemeConstantsScreen.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,MAAM,yBAAyB,GAAG;IACtC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;CACtE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,oFAOlC,yBAAyB,sBAsC3B,CAAC"}
1
+ {"version":3,"file":"ThemeConstantsScreen.d.ts","sourceRoot":"","sources":["../../src/screens/ThemeConstantsScreen.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,MAAM,yBAAyB,GAAG;IACtC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;CACtE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,oFAOlC,yBAAyB,sBA2C3B,CAAC"}
@@ -1,8 +1,9 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Box, Card, Page, Section, Typography } from '@alveole/components';
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Card, Page, PageHeader, Section, Typography } from '@alveole/components';
3
3
  import { useTheme } from '@alveole/theme';
4
4
  import React from 'react';
5
5
  import { Pressable, useWindowDimensions } from 'react-native';
6
+ import { screenContent } from '../styles';
6
7
  export const ThemeConstantsScreen = ({ constants, title = 'UI Kit - Constants', description = 'Theme constants', beforeContent, footerContent, onSelectConstant, }) => {
7
8
  const { text } = useTheme();
8
9
  const { width } = useWindowDimensions();
@@ -10,5 +11,5 @@ export const ThemeConstantsScreen = ({ constants, title = 'UI Kit - Constants',
10
11
  const entries = React.useMemo(() => Object.entries(constants)
11
12
  .filter(([, value]) => typeof value === 'object' && value != null)
12
13
  .sort((left, right) => left[0].localeCompare(right[0])), [constants]);
13
- return (_jsx(Page, { scrollable: true, title: title, description: description, beforeContent: beforeContent, footerContent: footerContent, children: _jsx(Section, { withPaddingY: true, children: _jsx(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 16, children: entries.map(([name, value]) => (_jsx(Box, { width: columns === 1 ? '100%' : columns === 2 ? '48%' : '31%', children: _jsx(Pressable, { onPress: onSelectConstant ? () => onSelectConstant({ name, value }) : undefined, children: _jsx(Card, { children: _jsx(Box, { p: '100', children: _jsx(Typography, { style: text.Titres['H5 - XS'], children: name }) }) }) }) }, name))) }) }) }));
14
+ return (_jsx(Page, { scrollable: true, title: title, description: description, beforeContent: beforeContent, footerContent: footerContent, children: _jsxs(Box, { ...screenContent, children: [_jsx(Section, { withPaddingY: false, children: _jsx(PageHeader, { title: title }) }), _jsx(Section, { withPaddingY: false, children: _jsx(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 16, children: entries.map(([name, value]) => (_jsx(Box, { width: columns === 1 ? '100%' : columns === 2 ? '48%' : '31%', children: _jsx(Pressable, { onPress: onSelectConstant ? () => onSelectConstant({ name, value }) : undefined, children: _jsx(Card, { children: _jsx(Box, { p: '100', children: _jsx(Typography, { style: text.Titres['H5 - XS'], children: name }) }) }) }) }, name))) }) })] }) }));
14
15
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ThemePaletteScreen.d.ts","sourceRoot":"","sources":["../../src/screens/ThemePaletteScreen.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AA+K1B,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACjC,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,gEAMhC,uBAAuB,sBAsBzB,CAAC"}
1
+ {"version":3,"file":"ThemePaletteScreen.d.ts","sourceRoot":"","sources":["../../src/screens/ThemePaletteScreen.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AA8H1B,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACjC,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,gEAMhC,uBAAuB,sBAoDzB,CAAC"}
@@ -1,8 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Page, Section, Typography, useToast } from '@alveole/components';
2
+ import { Accordion, Box, Page, PageHeader, Section, Typography, useToast } from '@alveole/components';
3
3
  import { useTheme } from '@alveole/theme';
4
4
  import React from 'react';
5
5
  import { Pressable } from 'react-native';
6
+ import { screenContent } from '../styles';
6
7
  function flattenColors(obj, prefix = '') {
7
8
  const entries = [];
8
9
  for (const [key, val] of Object.entries(obj)) {
@@ -89,29 +90,10 @@ const ColorSwatch = ({ entry }) => {
89
90
  marginTop: 2,
90
91
  }, numberOfLines: 1, children: entry.value })] })] })) }));
91
92
  };
92
- const ColorSectionView = ({ section }) => {
93
- const [collapsed, setCollapsed] = React.useState(section.deprecated === true);
94
- const { color, radius } = useTheme();
95
- return (_jsxs(Box, { style: { marginBottom: 24 }, children: [_jsx(Pressable, { onPress: () => setCollapsed(c => !c), children: _jsxs(Box, { style: {
96
- flexDirection: 'row',
97
- alignItems: 'center',
98
- paddingVertical: 10,
99
- paddingHorizontal: 16,
100
- backgroundColor: color.light.background['alt-grey'],
101
- borderRadius: radius('md'),
102
- borderWidth: 1,
103
- borderColor: color.light.border['default-grey'],
104
- marginBottom: collapsed ? 0 : 12,
105
- }, children: [_jsx(Typography, { style: {
106
- fontSize: 13,
107
- fontWeight: '700',
108
- color: section.deprecated ? color.light.text['mention-grey'] : color.light.text['title-grey'],
109
- flex: 1,
110
- fontFamily: 'monospace',
111
- }, children: section.title }), _jsxs(Typography, { style: { fontSize: 11, color: color.light.text['mention-grey'], marginRight: 8 }, children: [section.entries.length, " token", section.entries.length > 1 ? 's' : ''] }), _jsx(Typography, { style: { fontSize: 12, color: color.light.text['mention-grey'] }, children: collapsed ? '▸' : '▾' })] }) }), !collapsed && (_jsx(Box, { style: { flexDirection: 'row', flexWrap: 'wrap', gap: 8, paddingHorizontal: 4 }, children: section.entries.map(entry => (_jsx(ColorSwatch, { entry: entry }, entry.path))) }))] }));
112
- };
113
93
  export const ThemePaletteScreen = ({ palette, title = 'UI Kit - Couleurs du thème', description = 'Palette et couleurs du thème', beforeContent, footerContent, }) => {
114
94
  const { color } = useTheme();
115
95
  const sections = React.useMemo(() => buildSections(palette), [palette]);
116
- return (_jsx(Page, { scrollable: true, title: title, description: description, beforeContent: beforeContent, footerContent: footerContent, children: _jsxs(Section, { withPaddingY: true, children: [_jsx(Typography, { style: { fontSize: 14, color: color.light.text['mention-grey'], marginBottom: 24 }, children: 'Cliquez sur un swatch pour copier sa valeur dans le presse-papiers.' }), sections.map(section => (_jsx(ColorSectionView, { section: section }, section.title)))] }) }));
96
+ const initialOpen = React.useMemo(() => sections.filter(s => !s.deprecated).map(s => s.title), [sections]);
97
+ const [openSections, setOpenSections] = React.useState(initialOpen);
98
+ return (_jsx(Page, { scrollable: true, title: title, description: description, beforeContent: beforeContent, footerContent: footerContent, children: _jsxs(Box, { ...screenContent, children: [_jsx(Section, { withPaddingY: false, children: _jsx(PageHeader, { title: title, breadcrumbsProps: { getHref: (segment, _index, path) => (segment === 'theme' ? null : path) } }) }), _jsxs(Section, { withPaddingY: false, children: [_jsx(Typography, { style: { fontSize: 14, color: color.light.text['mention-grey'], marginBottom: 24 }, children: 'Cliquez sur un swatch pour copier sa valeur dans le presse-papiers.' }), _jsx(Accordion, { type: "multiple", value: openSections, onValueChange: setOpenSections, children: sections.map(section => (_jsx(Accordion.Item, { value: section.title, label: section.title, variant: "alt", labelChildren: _jsx(Typography, { style: { fontSize: 11, color: color.light.text['mention-grey'] }, children: `${section.entries.length} token${section.entries.length > 1 ? 's' : ''}` }), noPadding: true, children: _jsx(Box, { style: { flexDirection: 'row', flexWrap: 'wrap', gap: 8, padding: 8 }, children: section.entries.map(entry => (_jsx(ColorSwatch, { entry: entry }, entry.path))) }) }, section.title))) })] })] }) }));
117
99
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeTypographyScreen.d.ts","sourceRoot":"","sources":["../../src/screens/ThemeTypographyScreen.tsx"],"names":[],"mappings":"AAKA,MAAM,MAAM,0BAA0B,GAAG;IACvC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACjC,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,mEAMnC,0BAA0B,gCAsC5B,CAAC"}
1
+ {"version":3,"file":"ThemeTypographyScreen.d.ts","sourceRoot":"","sources":["../../src/screens/ThemeTypographyScreen.tsx"],"names":[],"mappings":"AAKA,MAAM,MAAM,0BAA0B,GAAG;IACvC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACjC,CAAC;AAwGF,eAAO,MAAM,qBAAqB,GAAI,mEAMnC,0BAA0B,gCA8C5B,CAAC"}
@@ -1,11 +1,55 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Card, Page, Section, Typography } from '@alveole/components';
2
+ import { Box, Card, Page, PageHeader, Section, Typography } from '@alveole/components';
3
3
  import { useTheme } from '@alveole/theme';
4
- import { useWindowDimensions } from 'react-native';
5
- import { JsonBlock } from '../components/JsonBlock';
4
+ import { View } from 'react-native';
5
+ import { screenContent } from '../styles';
6
+ const isLeafStyle = (value) => typeof value === 'object' && value !== null && typeof value.fontSize === 'number';
7
+ const flattenStyles = (value, prefix = '') => {
8
+ if (isLeafStyle(value)) {
9
+ return prefix ? [{ label: prefix, style: value }] : [];
10
+ }
11
+ if (typeof value === 'object' && value !== null) {
12
+ return Object.entries(value).flatMap(([k, v]) => {
13
+ if (typeof v !== 'object' || v === null)
14
+ return [];
15
+ const label = prefix ? `${prefix} ${k}` : k;
16
+ return flattenStyles(v, label);
17
+ });
18
+ }
19
+ return [];
20
+ };
21
+ const getFontInfo = (style) => {
22
+ const fontFamily = style.fontFamily ?? '';
23
+ const fontWeight = style.fontWeight ?? '';
24
+ if (fontFamily.includes(',')) {
25
+ const family = fontFamily.split(',')[0]?.trim() ?? '';
26
+ const weightLabels = {
27
+ '300': 'Light',
28
+ '400': 'Regular',
29
+ '500': 'Medium',
30
+ '600': 'SemiBold',
31
+ '700': 'Bold',
32
+ };
33
+ return { family, weight: weightLabels[fontWeight] ?? fontWeight };
34
+ }
35
+ const [family = '', weight = ''] = fontFamily.split('-');
36
+ return { family, weight };
37
+ };
38
+ const DIVIDER_COLOR = '#E5E7EB';
39
+ const MUTED_COLOR = '#6B7280';
40
+ const PREVIEW_WIDTH = 96;
41
+ const TableHeader = ({ labelStyle }) => (_jsxs(Box, { display: "flex", gap: 0, children: [_jsxs(Box, { display: "flex", flexDirection: "row", style: { paddingVertical: 8 }, children: [_jsx(Box, { style: { width: PREVIEW_WIDTH }, children: _jsx(Typography, { style: labelStyle, children: "Aper\u00E7u" }) }), _jsx(Box, { style: { flex: 2 }, children: _jsx(Typography, { style: labelStyle, children: "Nom" }) }), _jsx(Box, { style: { flex: 1 }, children: _jsx(Typography, { style: labelStyle, children: "Police" }) }), _jsx(Box, { style: { flex: 1 }, children: _jsx(Typography, { style: labelStyle, children: "Graisse" }) }), _jsx(Box, { style: { flex: 1 }, children: _jsx(Typography, { style: labelStyle, children: "Taille" }) }), _jsx(Box, { style: { flex: 1 }, children: _jsx(Typography, { style: labelStyle, children: "Hauteur" }) })] }), _jsx(View, { style: { height: 1, backgroundColor: DIVIDER_COLOR } })] }));
42
+ const TableRow = ({ entry, valueStyle }) => {
43
+ const { family, weight } = getFontInfo(entry.style);
44
+ return (_jsxs(Box, { display: "flex", gap: 0, children: [_jsxs(Box, { display: "flex", flexDirection: "row", style: { paddingVertical: 12, alignItems: 'center' }, children: [_jsx(Box, { style: { width: PREVIEW_WIDTH }, children: _jsx(Typography, { style: entry.style, children: "Aa" }) }), _jsx(Box, { style: { flex: 2 }, children: _jsx(Typography, { style: valueStyle, children: entry.label }) }), _jsx(Box, { style: { flex: 1 }, children: _jsx(Typography, { style: [valueStyle, { color: MUTED_COLOR }], children: family }) }), _jsx(Box, { style: { flex: 1 }, children: _jsx(Typography, { style: [valueStyle, { color: MUTED_COLOR }], children: weight }) }), _jsx(Box, { style: { flex: 1 }, children: _jsxs(Typography, { style: [valueStyle, { color: MUTED_COLOR }], children: [entry.style.fontSize, "px"] }) }), _jsx(Box, { style: { flex: 1 }, children: _jsxs(Typography, { style: [valueStyle, { color: MUTED_COLOR }], children: [entry.style.lineHeight, "px"] }) })] }), _jsx(View, { style: { height: 1, backgroundColor: DIVIDER_COLOR } })] }));
45
+ };
6
46
  export const ThemeTypographyScreen = ({ typography, title = 'UI Kit - Theme typography', description = 'Theme text styles', beforeContent, footerContent, }) => {
7
47
  const { text } = useTheme();
8
- const { width } = useWindowDimensions();
9
- const columns = width >= 1200 ? 3 : width >= 768 ? 2 : 1;
10
- return (_jsx(Page, { scrollable: true, title: title, description: description, beforeContent: beforeContent, footerContent: footerContent, children: _jsx(Section, { withPaddingY: true, children: _jsx(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 16, children: Object.entries(typography).map(([key, value]) => (_jsx(Box, { width: columns === 1 ? '100%' : columns === 2 ? '48%' : '31%', children: _jsx(Card, { children: _jsxs(Box, { display: "flex", gap: 16, p: '100', children: [_jsx(Typography, { style: text.Titres['H5 - XS'], children: key }), typeof value === 'object' && value != null ? (Object.entries(value).map(([subKey, subValue]) => (_jsxs(Box, { display: "flex", gap: 8, children: [_jsx(Typography, { style: text['Corps de texte'].XS.SemiBold, children: subKey }), _jsx(JsonBlock, { value: subValue })] }, subKey)))) : (_jsx(JsonBlock, { value: value }))] }) }) }, key))) }) }) }));
48
+ const labelStyle = text['Corps de texte'].XS.SemiBold;
49
+ const valueStyle = text['Corps de texte'].SM.Regular;
50
+ const categories = Object.entries(typography).map(([key, value]) => ({
51
+ key,
52
+ entries: flattenStyles(value),
53
+ }));
54
+ return (_jsx(Page, { scrollable: true, title: title, description: description, beforeContent: beforeContent, footerContent: footerContent, children: _jsxs(Box, { ...screenContent, children: [_jsx(Section, { withPaddingY: false, children: _jsx(PageHeader, { title: title, breadcrumbsProps: { getHref: (segment, _index, path) => (segment === 'theme' ? null : path) } }) }), _jsx(Section, { withPaddingY: false, children: _jsx(Box, { display: "flex", gap: 16, children: categories.map(({ key, entries }) => (_jsx(Card, { children: _jsxs(Box, { display: "flex", gap: 16, p: "150", children: [_jsx(Typography, { style: text.Titres['H4 - SM'], children: key }), _jsxs(Box, { display: "flex", gap: 0, children: [_jsx(TableHeader, { labelStyle: labelStyle }), entries.map(entry => (_jsx(TableRow, { entry: entry, valueStyle: valueStyle }, entry.label)))] })] }) }, key))) }) })] }) }));
11
55
  };
@@ -0,0 +1,7 @@
1
+ export declare const screenContent: {
2
+ readonly display: "flex";
3
+ readonly gap: 24;
4
+ readonly pt: "150";
5
+ readonly pb: "150";
6
+ };
7
+ //# sourceMappingURL=styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa;;;;;CAKhB,CAAC"}
package/dist/styles.js ADDED
@@ -0,0 +1,6 @@
1
+ export const screenContent = {
2
+ display: 'flex',
3
+ gap: 24,
4
+ pt: '150',
5
+ pb: '150',
6
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alveole/storybook",
3
- "version": "0.43.2",
3
+ "version": "1.0.0",
4
4
  "description": "Catalog screens and helpers for Alveole stories and theme tokens.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -23,7 +23,9 @@
23
23
  },
24
24
  "devDependencies": {
25
25
  "@alveole/eslint-config": "file:../eslint-config",
26
- "eslint": "^9.39.2"
26
+ "eslint": "9.39.4",
27
+ "react": "19.2.3",
28
+ "react-native": "0.85.3"
27
29
  },
28
30
  "peerDependencies": {
29
31
  "@alveole/components": "*",
@@ -1,7 +0,0 @@
1
- export type FilterBadgeProps = {
2
- active: boolean;
3
- label: string;
4
- onPress: () => void;
5
- };
6
- export declare const FilterBadge: ({ active, label, onPress }: FilterBadgeProps) => import("react").JSX.Element;
7
- //# sourceMappingURL=FilterBadge.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"FilterBadge.d.ts","sourceRoot":"","sources":["../../src/components/FilterBadge.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,4BAA4B,gBAAgB,gCA+BvE,CAAC"}
@@ -1,19 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Box, Typography } from '@alveole/components';
3
- import { useTheme } from '@alveole/theme';
4
- import { Pressable } from 'react-native';
5
- export const FilterBadge = ({ active, label, onPress }) => {
6
- const { color, radius, text, spacing } = useTheme();
7
- return (_jsx(Pressable, { onPress: onPress, children: _jsx(Box, { borderColor: active ? color.light.border['action-low-primary'] : color.light.border['default-grey'], borderRadius: radius('full'), borderWidth: 1, p: '000', style: {
8
- backgroundColor: active ? color.light.background['contrast-info'] : color.light.background['default-grey'],
9
- paddingLeft: spacing('1W'),
10
- paddingRight: spacing('1W'),
11
- paddingTop: spacing('0,5V'),
12
- paddingBottom: spacing('0,5V'),
13
- }, children: _jsx(Typography, { style: [
14
- text['Corps de texte'].XS.CapsBold,
15
- {
16
- color: active ? color.light.text['default-info'] : color.light.text['default-grey'],
17
- },
18
- ], children: label }) }) }));
19
- };