@alveole/storybook 1.0.1 → 1.1.1

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.
package/README.md CHANGED
@@ -69,6 +69,16 @@ export const BoxPadded = () => (
69
69
 
70
70
  Le `default` porte les metadonnees de la story. Les autres exports sont les variantes affichees par `StoryDetailScreen`.
71
71
 
72
+ ### Champ `shortDescription`
73
+
74
+ Optionnel. A renseigner quand `description` contient du Markdown ou depasse 160 caracteres.
75
+
76
+ - Max 160 caracteres
77
+ - Texte brut uniquement (pas de Markdown)
78
+ - Utilise pour `<meta name="description">` sur la page de detail du composant
79
+
80
+ Si absent, la meta description est calculee automatiquement en retirant le Markdown de `description`.
81
+
72
82
  Concretement, `@alveole/storybook` n'introduit pas un nouveau format de story. Il reutilise celui que tu ecris deja dans `packages/components/src/**/*.stories.tsx`.
73
83
 
74
84
  ## Structure attendue par le package
@@ -4,7 +4,7 @@ import { useTheme } from '@alveole/theme';
4
4
  import React from 'react';
5
5
  import { Platform, TextInput } from 'react-native';
6
6
  export const SearchField = ({ label, placeholder, value, onChangeText, size = 'md' }) => {
7
- const { text, color, radius, spacing } = useTheme();
7
+ const { text, color, radius, spacingValue } = useTheme();
8
8
  const inputRef = React.useRef(null);
9
9
  React.useEffect(() => {
10
10
  if (Platform.OS !== 'web')
@@ -22,8 +22,8 @@ export const SearchField = ({ label, placeholder, value, onChangeText, size = 'm
22
22
  borderWidth: 1,
23
23
  borderColor: color.light.border['default-grey'],
24
24
  borderRadius: radius('md'),
25
- paddingVertical: size === 'sm' ? spacing('1,5V') : spacing('1W'),
26
- paddingHorizontal: spacing('2W'),
25
+ paddingVertical: size === 'sm' ? spacingValue('1,5V') : spacingValue('1W'),
26
+ paddingHorizontal: spacingValue('2W'),
27
27
  backgroundColor: color.light.background['default-grey'],
28
28
  color: color.light.text['default-grey'],
29
29
  ...(size === 'sm' ? text['Corps de texte'].SM.Regular : text['Corps de texte'].MD.Regular),
@@ -1,7 +1,7 @@
1
1
  import { StorybookModule } from '../types';
2
2
  export type StoryCardProps = {
3
3
  story: StorybookModule;
4
- onPress?: (story: StorybookModule) => void;
4
+ href: string;
5
5
  };
6
- export declare const StoryCard: ({ story, onPress }: StoryCardProps) => import("react").JSX.Element;
6
+ export declare const StoryCard: ({ story, href }: StoryCardProps) => import("react").JSX.Element;
7
7
  //# sourceMappingURL=StoryCard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"StoryCard.d.ts","sourceRoot":"","sources":["../../src/components/StoryCard.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAC5C,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,oBAAoB,cAAc,gCA8B3D,CAAC"}
1
+ {"version":3,"file":"StoryCard.d.ts","sourceRoot":"","sources":["../../src/components/StoryCard.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,eAAe,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,iBAAiB,cAAc,gCA6BxD,CAAC"}
@@ -1,11 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Badge, Box, Card, Typography } from '@alveole/components';
2
+ import { A, Badge, Box, Card, Typography } from '@alveole/components';
3
3
  import { useTheme } from '@alveole/theme';
4
- import { Pressable } from 'react-native';
5
- import { getStoryFlags } from '../utils';
6
- export const StoryCard = ({ story, onPress }) => {
4
+ import { getStoryFlags, stripMarkdown } from '../utils';
5
+ export const StoryCard = ({ story, href }) => {
7
6
  const { text, isVariant } = useTheme();
8
7
  const meta = story.default;
9
8
  const flags = getStoryFlags(meta);
10
- return (_jsx(Pressable, { onPress: onPress ? () => onPress(story) : undefined, style: { height: isVariant('mobile') ? undefined : '100%' }, children: _jsx(Card, { height: isVariant('mobile') ? undefined : '100%', children: _jsxs(Box, { display: "flex", gap: 12, p: '100', style: { height: isVariant('mobile') ? undefined : '100%' }, children: [_jsxs(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 8, children: [meta.tags.map(tag => (_jsx(Badge, { variant: "info", size: "sm", style: { marginRight: 0 }, children: tag }, tag))), flags.map(flag => (_jsx(Badge, { variant: "default", size: "sm", style: { marginRight: 0 }, children: flag.label }, flag.key)))] }), _jsx(Typography, { style: text.Titres['H5 - XS'], children: meta.title }), _jsx(Typography, { style: text['Corps de texte'].SM.Regular, children: meta.description })] }) }) }));
9
+ const description = meta.shortDescription ?? stripMarkdown(meta.description);
10
+ return (_jsx(A, { href: href, style: { height: isVariant('mobile') ? undefined : '100%' }, children: _jsx(Card, { height: isVariant('mobile') ? undefined : '100%', children: _jsxs(Box, { display: "flex", gap: 12, p: '100', style: { height: isVariant('mobile') ? undefined : '100%' }, children: [_jsxs(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 8, children: [meta.tags.map(tag => (_jsx(Badge, { variant: "info", size: "sm", style: { marginRight: 0 }, children: tag }, tag))), flags.map(flag => (_jsx(Badge, { variant: "default", size: "sm", style: { marginRight: 0 }, children: flag.label }, flag.key)))] }), _jsx(Typography, { style: text.Titres['H5 - XS'], children: meta.title }), _jsx(Typography, { style: text['Corps de texte'].SM.Regular, children: description })] }) }) }));
11
11
  };
@@ -39,7 +39,7 @@ export const UIKitPage = ({ stories, constants, palette = CustomPalette, typogra
39
39
  return (_jsx(HomeScreen, { title: title, description: description, blankPage: blankPage, onOpenComponents: () => push({ name: 'components' }), onOpenTheme: () => push({ name: 'theme-home' }), onOpenConstants: () => push({ name: 'constants' }), onOpenBlank: () => push({ name: 'blank' }), onOpenPhilosophy: () => push({ name: 'philosophy' }) }));
40
40
  }
41
41
  if (route.name === 'components') {
42
- return (_jsx(StoriesScreen, { beforeContent: beforeContent, stories: stories, title: "UI Kit - Composants", description: "Catalogue des composants", createLabel: blankPage ? (blankPage.title ?? 'Page vierge') : undefined, onCreatePress: blankPage ? () => push({ name: 'blank' }) : undefined, onSelectStory: story => push({ name: 'component-detail', story }) }));
42
+ return (_jsx(StoriesScreen, { beforeContent: beforeContent, stories: stories, title: "UI Kit - Composants", description: "Catalogue des composants", createLabel: blankPage ? (blankPage.title ?? 'Page vierge') : undefined, onCreatePress: blankPage ? () => push({ name: 'blank' }) : undefined, getStoryHref: story => `/components/${encodeURIComponent(story.default.title)}` }));
43
43
  }
44
44
  if (route.name === 'component-detail') {
45
45
  return (_jsx(StoryDetailScreen, { beforeContent: beforeContent, story: route.story, notFoundMessage: "Composant introuvable" }));
@@ -9,7 +9,7 @@ export type StoriesScreenProps = {
9
9
  footerContent?: React.ReactNode;
10
10
  createLabel?: string;
11
11
  onCreatePress?: () => void;
12
- onSelectStory?: (story: StorybookModule) => void;
12
+ getStoryHref: (story: StorybookModule) => string;
13
13
  };
14
- export declare const StoriesScreen: ({ stories, title, description, emptyMessage, beforeContent, footerContent, createLabel, onCreatePress, onSelectStory, }: StoriesScreenProps) => React.JSX.Element;
14
+ export declare const StoriesScreen: ({ stories, title, description, emptyMessage, beforeContent, footerContent, createLabel, onCreatePress, getStoryHref, }: StoriesScreenProps) => React.JSX.Element;
15
15
  //# sourceMappingURL=StoriesScreen.d.ts.map
@@ -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,sBAkJpB,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,YAAY,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,MAAM,CAAC;CAClD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,wHAU3B,kBAAkB,sBAkJpB,CAAC"}
@@ -14,7 +14,7 @@ const AVAILABLE_FLAGS = [
14
14
  { key: 'webOnly', label: 'Web only' },
15
15
  { key: 'mobileOnly', label: 'Mobile only' },
16
16
  ];
17
- export const StoriesScreen = ({ stories, title = 'UI Kit - Components', description = 'Shared component catalog', emptyMessage = 'No story found.', beforeContent, footerContent, createLabel, onCreatePress, onSelectStory, }) => {
17
+ export const StoriesScreen = ({ stories, title = 'UI Kit - Components', description = 'Shared component catalog', emptyMessage = 'No story found.', beforeContent, footerContent, createLabel, onCreatePress, getStoryHref, }) => {
18
18
  const { text } = useTheme();
19
19
  const { width } = useWindowDimensions();
20
20
  const columns = width >= 1200 ? 3 : width >= 768 ? 2 : 1;
@@ -41,5 +41,5 @@ export const StoriesScreen = ({ stories, title = 'UI Kit - Components', descript
41
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
42
  setSelectedFlag(prev => (prev === flag.key ? null : flag.key));
43
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] }));
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, href: getStoryHref(story) }) }, story.default.title))) })] }) }, tag))))] }), footerContent] }));
45
45
  };
@@ -1 +1 @@
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
+ {"version":3,"file":"StoryDetailScreen.d.ts","sourceRoot":"","sources":["../../src/screens/StoryDetailScreen.tsx"],"names":[],"mappings":"AAaA,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;AAsGF,eAAO,MAAM,iBAAiB,GAAI,2DAK/B,sBAAsB,sBA6KxB,CAAC"}
@@ -1,32 +1,18 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { AnchorHeading, Box, Button, Divider, Page, PageHeader, Section, Typography } from '@alveole/components';
2
+ import { AnchorHeading, Box, Button, Divider, MarkdownDescription, Page, PageHeader, Section, Tag, 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
7
  import { screenContent } from '../styles';
8
- import { getStoryExamples, getStoryFlags } from '../utils';
9
- const DetailPill = ({ label, tone = 'info' }) => {
10
- const { color, radius, text, spacing } = useTheme();
11
- return (_jsx(Box, { borderColor: tone === 'tag' ? color.light.border['action-low-primary'] : color.light.border['default-grey'], borderRadius: radius('full'), borderWidth: 1, style: {
12
- backgroundColor: tone === 'tag' ? color.light.background['contrast-info'] : color.light.background['default-grey'],
13
- paddingLeft: spacing('1W'),
14
- paddingRight: spacing('1W'),
15
- paddingTop: spacing('0,5V'),
16
- paddingBottom: spacing('0,5V'),
17
- }, children: _jsx(Typography, { style: [
18
- text['Corps de texte'].XS.CapsBold,
19
- {
20
- color: tone === 'tag' ? color.light.text['default-info'] : color.light.text['default-grey'],
21
- },
22
- ], children: label }) }));
23
- };
8
+ import { getStoryExamples, getStoryFlags, stripMarkdown } from '../utils';
24
9
  const MetaCard = ({ label, value }) => {
25
10
  const { color, radius, text } = useTheme();
26
11
  return (_jsxs(Box, { borderColor: color.light.border['default-grey'], borderRadius: radius('md'), borderWidth: 1, display: "flex", gap: 4, p: '100', style: { backgroundColor: color.light.background['alt-grey'], minWidth: 160 }, children: [_jsx(Typography, { style: text['Corps de texte'].XS.CapsBold, children: label }), _jsx(Typography, { style: text['Corps de texte'].SM.SemiBold, children: value })] }));
27
12
  };
13
+ const getSources = (story) => story.Sources;
28
14
  const getStoryExampleSource = (story, exampleName) => {
29
- const sources = story.Sources;
15
+ const sources = getSources(story);
30
16
  const source = sources?.storySources?.[exampleName] ?? sources?.[exampleName];
31
17
  if (typeof source === 'string')
32
18
  return source;
@@ -36,6 +22,10 @@ const getStoryExampleSource = (story, exampleName) => {
36
22
  }
37
23
  return null;
38
24
  };
25
+ const getStoryExampleDescription = (story, exampleName) => {
26
+ const description = getSources(story)?.storyDescriptions?.[exampleName];
27
+ return typeof description === 'string' ? description : null;
28
+ };
39
29
  const DetailTabs = ({ tabs, defaultValue }) => {
40
30
  const initialValue = defaultValue || tabs[0]?.value || '';
41
31
  const [activeValue, setActiveValue] = React.useState(initialValue);
@@ -53,16 +43,17 @@ export const StoryDetailScreen = ({ story, notFoundMessage = 'Story not found.',
53
43
  const isTemplate = meta.tags.includes('Template');
54
44
  const examplesContent = (_jsx(Box, { display: "flex", gap: 24, mt: '1,5V', children: examples.map(([key, Example]) => {
55
45
  const source = getStoryExampleSource(story, key);
56
- return (_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: [!isTemplate ? (_jsx(Box, { display: "flex", gap: 6, children: _jsx(AnchorHeading, { style: text.Titres['H5 - XS'], children: key }) })) : null, _jsx(Box, { borderColor: color.light.border['default-grey'], borderWidth: 1, borderRadius: radius('md'), p: '100', style: {
46
+ const description = getStoryExampleDescription(story, key);
47
+ return (_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: [!isTemplate ? (_jsxs(Box, { display: "flex", gap: 6, children: [_jsx(AnchorHeading, { style: text.Titres['H5 - XS'], children: key }), description ? _jsx(MarkdownDescription, { children: description }) : null] })) : null, _jsx(Box, { borderColor: color.light.border['default-grey'], borderWidth: 1, borderRadius: radius('md'), p: '100', style: {
57
48
  backgroundColor: color.light.background['default-grey'],
58
49
  minHeight: isTemplate ? 420 : undefined,
59
50
  }, children: _jsx(Example, {}) }), _jsx(Divider, { mt: "1W", mb: "1,5V" }), source ? _jsx(JsonBlock, { language: "tsx", value: source }) : null] }, key));
60
51
  }) }));
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: {
52
+ return (_jsx(Page, { scrollable: true, title: meta.title, description: meta.shortDescription ?? stripMarkdown(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
53
  alignItems: 'flex-start',
63
54
  flexDirection: 'row',
64
55
  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: [
56
+ }, children: [_jsx(Box, { display: "flex", gap: 6, style: { flex: 1 }, children: _jsx(MarkdownDescription, { 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(Tag, { color: "action", size: "md", children: 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(Tag, { color: "default", size: "md", children: 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: [
66
57
  {
67
58
  value: 'examples',
68
59
  label: 'Examples',
package/dist/utils.d.ts CHANGED
@@ -14,4 +14,5 @@ export declare const getStoryExamples: (story: StorybookModule) => [string, Excl
14
14
  export declare const toStoryModules: (stories: Record<string, unknown>) => StorybookModule[];
15
15
  export declare const findStoryByTitle: (stories: StorybookModule[], title: string | undefined | null) => StorybookModule | null;
16
16
  export declare const findConstantByName: (constants: Record<string, unknown>, name: string | undefined | null) => [string, unknown] | null;
17
+ export declare const stripMarkdown: (markdown: string) => string;
17
18
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAUxE,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,WAIP,CAAC;AAErC,eAAO,MAAM,aAAa,GAAI,MAAM,aAAa,KAAG,aAAa,EAC+B,CAAC;AAEjG,eAAO,MAAM,eAAe,GAAI,SAAS,eAAe,EAAE,KAAG,MAAM,EAOlE,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,QAAQ;IACpC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,aAAa,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;CAC3C,sBAoBA,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,SAAS,eAAe,EAAE,sBAC8B,CAAC;AAE5F,eAAO,MAAM,iBAAiB,GAAI,SAAS,eAAe,EAAE,EAAE,MAAM,MAAM,EAAE,6CAGd,CAAC;AAE/D,eAAO,MAAM,gBAAgB,GAAI,OAAO,eAAe,KAC+C,CAClG,MAAM,EACN,OAAO,CAAC,eAAe,CAAC,MAAM,eAAe,CAAC,EAAE,aAAa,CAAC,CAC/D,EAAE,CAAC;AAEN,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAA+B,eAAe,EAAE,CAAC;AAEhH,eAAO,MAAM,gBAAgB,GAAI,SAAS,eAAe,EAAE,EAAE,OAAO,MAAM,GAAG,SAAS,GAAG,IAAI,2BAC/B,CAAC;AAE/D,eAAO,MAAM,kBAAkB,GAAI,WAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,GAAG,IAAI,6BACrC,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAUxE,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,WAIP,CAAC;AAErC,eAAO,MAAM,aAAa,GAAI,MAAM,aAAa,KAAG,aAAa,EAC+B,CAAC;AAEjG,eAAO,MAAM,eAAe,GAAI,SAAS,eAAe,EAAE,KAAG,MAAM,EAOlE,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,QAAQ;IACpC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,aAAa,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;CAC3C,sBAoBA,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,SAAS,eAAe,EAAE,sBAC8B,CAAC;AAE5F,eAAO,MAAM,iBAAiB,GAAI,SAAS,eAAe,EAAE,EAAE,MAAM,MAAM,EAAE,6CAGd,CAAC;AAE/D,eAAO,MAAM,gBAAgB,GAAI,OAAO,eAAe,KAC+C,CAClG,MAAM,EACN,OAAO,CAAC,eAAe,CAAC,MAAM,eAAe,CAAC,EAAE,aAAa,CAAC,CAC/D,EAAE,CAAC;AAEN,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAA+B,eAAe,EAAE,CAAC;AAEhH,eAAO,MAAM,gBAAgB,GAAI,SAAS,eAAe,EAAE,EAAE,OAAO,MAAM,GAAG,SAAS,GAAG,IAAI,2BAC/B,CAAC;AAE/D,eAAO,MAAM,kBAAkB,GAAI,WAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,GAAG,IAAI,6BACrC,CAAC;AAElE,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,KAAG,MAWtC,CAAC"}
package/dist/utils.js CHANGED
@@ -46,3 +46,14 @@ export const getStoryExamples = (story) => Object.entries(story).filter(([key, v
46
46
  export const toStoryModules = (stories) => Object.values(stories);
47
47
  export const findStoryByTitle = (stories, title) => stories.find(story => story.default.title === title) ?? null;
48
48
  export const findConstantByName = (constants, name) => Object.entries(constants).find(([key]) => key === name) ?? null;
49
+ export const stripMarkdown = (markdown) => markdown
50
+ .replace(/#{1,6}\s*/g, '')
51
+ .replace(/\*\*([^*]+)\*\*/g, '$1')
52
+ .replace(/__([^_]+)__/g, '$1')
53
+ .replace(/\*([^*]+)\*/g, '$1')
54
+ .replace(/_([^_]+)_/g, '$1')
55
+ .replace(/`([^`]+)`/g, '$1')
56
+ .replace(/^\s*[-*+]\s+/gm, '')
57
+ .replace(/^\s*\d+\.\s+/gm, '')
58
+ .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
59
+ .trim();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alveole/storybook",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
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,7 @@
23
23
  },
24
24
  "devDependencies": {
25
25
  "@alveole/eslint-config": "file:../eslint-config",
26
- "eslint": "9.39.4",
26
+ "eslint": "9.39.5",
27
27
  "react": "19.2.3",
28
28
  "react-native": "0.85.3"
29
29
  },