@alveole/storybook 0.41.0 → 0.42.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.
@@ -0,0 +1,2 @@
1
+ export declare const DocFooter: () => import("react").JSX.Element;
2
+ //# sourceMappingURL=DocFooter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DocFooter.d.ts","sourceRoot":"","sources":["../../src/components/DocFooter.tsx"],"names":[],"mappings":"AAGA,eAAO,MAAM,SAAS,mCAoBrB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { ALVEOLE_COMPONENTS_VERSION, Box, Typography } from '@alveole/components';
3
+ import { useTheme } from '@alveole/theme';
4
+ export const DocFooter = () => {
5
+ const { color, text } = useTheme();
6
+ return (_jsx(Box, { style: {
7
+ borderTopWidth: 1,
8
+ borderTopColor: color.light.border['default-grey'],
9
+ paddingTop: 12,
10
+ paddingBottom: 12,
11
+ paddingLeft: 24,
12
+ paddingRight: 24,
13
+ display: 'flex',
14
+ alignItems: 'center',
15
+ }, children: _jsxs(Typography, { style: { ...text['Corps de texte'].XS.Regular, color: color.light.text['mention-grey'] }, children: ["Alveole UI Kit \u2014 v", ALVEOLE_COMPONENTS_VERSION] }) }));
16
+ };
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  export type UIKitTopBarItem = {
2
3
  key: string;
3
4
  label: string;
@@ -7,5 +8,5 @@ export type UIKitTopBarProps = {
7
8
  activeKey: string;
8
9
  items: UIKitTopBarItem[];
9
10
  };
10
- export declare const UIKitTopBar: ({ activeKey, items }: UIKitTopBarProps) => import("react").JSX.Element;
11
+ export declare const UIKitTopBar: ({ activeKey, items }: UIKitTopBarProps) => React.JSX.Element;
11
12
  //# sourceMappingURL=UIKitTopBar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UIKitTopBar.d.ts","sourceRoot":"","sources":["../../src/components/UIKitTopBar.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,sBAAsB,gBAAgB,gCA+EjE,CAAC"}
1
+ {"version":3,"file":"UIKitTopBar.d.ts","sourceRoot":"","sources":["../../src/components/UIKitTopBar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B,CAAC;AAqBF,eAAO,MAAM,WAAW,GAAI,sBAAsB,gBAAgB,sBAoEjE,CAAC"}
@@ -1,35 +1,45 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { ALVEOLE_COMPONENTS_VERSION, Box, Typography } from '@alveole/components';
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Button, Header, LucideIcon, Typography } from '@alveole/components';
3
3
  import { useTheme } from '@alveole/theme';
4
- import { Pressable, useWindowDimensions } from 'react-native';
5
- export const UIKitTopBar = ({ activeKey, items }) => {
4
+ import React from 'react';
5
+ import { Pressable } from 'react-native';
6
+ const AlveoleLogo = () => {
6
7
  const { color, radius, text } = useTheme();
7
- const { width } = useWindowDimensions();
8
8
  return (_jsx(Box, { style: {
9
- backgroundColor: color.light.background['default-grey'],
10
- borderBottomColor: color.light.border['default-grey'],
11
- borderBottomWidth: 1,
12
- }, children: _jsxs(Box, { display: "flex", gap: 12, p: '150', style: {
13
- alignItems: width >= 960 ? 'center' : 'flex-start',
14
- flexDirection: width >= 960 ? 'row' : 'column',
15
- justifyContent: 'space-between',
16
- }, children: [_jsxs(Box, { display: "flex", gap: 2, children: [_jsx(Typography, { style: text['Corps de texte'].SM.Bold, children: "Alveole \u2022 UI Kit" }), _jsxs(Typography, { style: {
17
- ...text['Corps de texte'].XS.Regular,
18
- color: color.light.text['mention-grey'],
19
- }, children: ["Version ", ALVEOLE_COMPONENTS_VERSION] })] }), _jsx(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 8, children: items.map(item => {
20
- const isActive = item.key === activeKey;
21
- return (_jsx(Pressable, { accessibilityRole: "link", onPress: item.onPress, children: ({ pressed }) => (_jsx(Box, { borderColor: isActive ? color.light.border['action-low-primary'] : color.light.border['default-grey'], borderRadius: radius('full'), borderWidth: 1, pl: '100', pr: '100', pt: '075', pb: '075', style: {
22
- backgroundColor: isActive
23
- ? color.light.background['action-low-primary']
24
- : pressed
25
- ? color.light.background['alt-grey']
26
- : color.light.background['default-grey'],
27
- transitionDuration: '150ms',
28
- transitionProperty: 'background-color, border-color, color',
29
- transitionTimingFunction: 'ease',
30
- }, children: _jsx(Typography, { style: {
31
- ...text['Corps de texte'].SM.Medium,
32
- color: isActive ? color.light.text['action-high-primary'] : color.light.text['default-grey'],
33
- }, children: item.label }) })) }, item.key));
34
- }) })] }) }));
9
+ width: 32,
10
+ height: 32,
11
+ borderRadius: radius('md'),
12
+ backgroundColor: color.light.background['action-high-primary'],
13
+ display: 'flex',
14
+ alignItems: 'center',
15
+ justifyContent: 'center',
16
+ }, children: _jsx(Typography, { style: { ...text['Corps de texte'].XS.Bold, color: '#fff' }, children: "A" }) }));
17
+ };
18
+ export const UIKitTopBar = ({ activeKey, items }) => {
19
+ const { color, isVariant, spacing } = useTheme();
20
+ const [menuOpen, setMenuOpen] = React.useState(false);
21
+ if (isVariant('mobile')) {
22
+ return (_jsxs(_Fragment, { children: [_jsx(Header, { logo: _jsx(AlveoleLogo, {}), right: _jsx(Pressable, { onPress: () => setMenuOpen(v => !v), style: { padding: 8 }, children: _jsx(LucideIcon, { name: menuOpen ? 'X' : 'Menu', size: "md", color: color.light.text['title-grey'] }) }) }), menuOpen && (_jsx(Box, { style: {
23
+ position: 'sticky',
24
+ top: 64,
25
+ left: 0,
26
+ right: 0,
27
+ zIndex: 99,
28
+ backgroundColor: color.light.background['default-grey'],
29
+ borderBottomWidth: 1,
30
+ borderBottomColor: color.light.border['default-grey'],
31
+ paddingTop: spacing('2W'),
32
+ paddingBottom: spacing('2W'),
33
+ paddingLeft: spacing('2W'),
34
+ paddingRight: spacing('2W'),
35
+ display: 'flex',
36
+ flexDirection: 'column',
37
+ gap: spacing('050'),
38
+ }, children: items.map(item => (_jsx(Button, { variant: activeKey === item.key ? 'primary' : 'tertiary', title: item.label, size: "sm", onPress: () => {
39
+ item.onPress();
40
+ setMenuOpen(false);
41
+ } }, item.key))) }))] }));
42
+ }
43
+ const right = (_jsx(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 8, children: items.map(item => (_jsx(Button, { variant: activeKey === item.key ? 'primary' : 'tertiary', title: item.label, size: "sm", onPress: item.onPress }, item.key))) }));
44
+ return _jsx(Header, { logo: _jsx(AlveoleLogo, {}), title: "Alveole UI Kit", right: right });
35
45
  };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
+ export * from './components/DocFooter';
1
2
  export * from './components/JsonBlock';
2
3
  export * from './components/UIKitTopBar';
4
+ export * from './pages/PhilosophyPage';
3
5
  export * from './pages/UIKitHomePage';
4
6
  export * from './pages/UIKitPage';
5
7
  export * from './pages/UIKitThemePage';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,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,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
+ export * from './components/DocFooter';
1
2
  export * from './components/JsonBlock';
2
3
  export * from './components/UIKitTopBar';
4
+ export * from './pages/PhilosophyPage';
3
5
  export * from './pages/UIKitHomePage';
4
6
  export * from './pages/UIKitPage';
5
7
  export * from './pages/UIKitThemePage';
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ export type PhilosophyPageProps = {
3
+ beforeContent?: React.ReactNode;
4
+ footerContent?: React.ReactNode;
5
+ };
6
+ export declare const PhilosophyPage: ({ beforeContent, footerContent }: PhilosophyPageProps) => React.JSX.Element;
7
+ //# sourceMappingURL=PhilosophyPage.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Page, Section, Typography } from '@alveole/components';
3
+ import { useTheme } from '@alveole/theme';
4
+ const PhilosophySection = ({ title, children }) => {
5
+ const { text } = useTheme();
6
+ return (_jsxs(Box, { display: "flex", gap: 8, mb: '400', children: [_jsx(Typography, { style: text.Titres['H4 - SM'], children: title }), children] }));
7
+ };
8
+ export const PhilosophyPage = ({ beforeContent, footerContent }) => {
9
+ 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
+ };
@@ -6,9 +6,10 @@ export type StoriesScreenProps = {
6
6
  description?: string;
7
7
  emptyMessage?: string;
8
8
  beforeContent?: React.ReactNode;
9
+ footerContent?: React.ReactNode;
9
10
  createLabel?: string;
10
11
  onCreatePress?: () => void;
11
12
  onSelectStory?: (story: StorybookModule) => void;
12
13
  };
13
- export declare const StoriesScreen: ({ stories, title, description, emptyMessage, beforeContent, createLabel, onCreatePress, onSelectStory, }: StoriesScreenProps) => React.JSX.Element;
14
+ export declare const StoriesScreen: ({ stories, title, description, emptyMessage, beforeContent, footerContent, createLabel, onCreatePress, onSelectStory, }: StoriesScreenProps) => React.JSX.Element;
14
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,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,0GAS3B,kBAAkB,sBAgKpB,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,sBAiKpB,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, createLabel, onCreatePress, onSelectStory, }) => {
17
+ export const StoriesScreen = ({ stories, title = 'UI Kit - Components', description = 'Shared component catalog', emptyMessage = 'No story found.', beforeContent, footerContent, createLabel, onCreatePress, onSelectStory, }) => {
18
18
  const { text, color, radius } = useTheme();
19
19
  const { width } = useWindowDimensions();
20
20
  const columns = width >= 1200 ? 3 : width >= 768 ? 2 : 1;
@@ -51,5 +51,5 @@ export const StoriesScreen = ({ stories, title = 'UI Kit - Components', descript
51
51
  } })) : null] }), _jsx(SearchField, { label: "Recherche", placeholder: "Button, Tabs, Card...", value: query, onChangeText: setQuery }), _jsxs(Box, { display: "flex", gap: 16, style: {
52
52
  alignItems: 'flex-start',
53
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))))] }));
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] }));
55
55
  };
@@ -4,6 +4,7 @@ export type StoryDetailScreenProps = {
4
4
  story?: StorybookModule | null;
5
5
  notFoundMessage?: string;
6
6
  beforeContent?: React.ReactNode;
7
+ footerContent?: React.ReactNode;
7
8
  };
8
- export declare const StoryDetailScreen: ({ story, notFoundMessage, beforeContent, }: StoryDetailScreenProps) => React.JSX.Element;
9
+ export declare const StoryDetailScreen: ({ story, notFoundMessage, beforeContent, footerContent, }: StoryDetailScreenProps) => React.JSX.Element;
9
10
  //# sourceMappingURL=StoryDetailScreen.d.ts.map
@@ -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;CACjC,CAAC;AAiIF,eAAO,MAAM,iBAAiB,GAAI,4CAI/B,sBAAsB,sBAwJxB,CAAC"}
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"}
@@ -41,10 +41,10 @@ const DetailTabs = ({ tabs, defaultValue }) => {
41
41
  const activeTab = tabs.find(tab => tab.value === activeValue) ?? tabs[0];
42
42
  return (_jsxs(Box, { display: "flex", gap: 16, children: [_jsx(Box, { display: "flex", flexDirection: "row", flexWrap: "wrap", gap: 8, children: tabs.map(tab => (_jsx(Button, { title: tab.label, size: "sm", variant: "tertiary", selected: tab.value === activeTab?.value, onPress: () => setActiveValue(tab.value) }, tab.value))) }), activeTab?.scrollable ? (_jsx(ScrollView, { style: { flex: 1 }, contentContainerStyle: { paddingBottom: 16 }, keyboardShouldPersistTaps: "handled", showsVerticalScrollIndicator: true, children: activeTab.content })) : (activeTab?.content)] }));
43
43
  };
44
- export const StoryDetailScreen = ({ story, notFoundMessage = 'Story not found.', beforeContent, }) => {
44
+ export const StoryDetailScreen = ({ story, notFoundMessage = 'Story not found.', beforeContent, footerContent, }) => {
45
45
  const { text, color, radius } = useTheme();
46
46
  if (!story) {
47
- return (_jsx(Page, { title: "Story not found", description: notFoundMessage, beforeContent: beforeContent, children: _jsx(Section, { withPaddingY: true, children: _jsx(Typography, { style: text['Corps de texte'].MD.Regular, children: notFoundMessage }) }) }));
47
+ return (_jsx(Page, { title: "Story not found", description: notFoundMessage, beforeContent: beforeContent, footerContent: footerContent, children: _jsx(Section, { withPaddingY: true, children: _jsx(Typography, { style: text['Corps de texte'].MD.Regular, children: notFoundMessage }) }) }));
48
48
  }
49
49
  const meta = story.default;
50
50
  const flags = getStoryFlags(meta);
@@ -57,7 +57,7 @@ export const StoryDetailScreen = ({ story, notFoundMessage = 'Story not found.',
57
57
  minHeight: isTemplate ? 420 : undefined,
58
58
  }, children: _jsx(Example, {}) }), _jsx(Divider, { mt: "1W", mb: "1,5V" }), source ? _jsx(JsonBlock, { language: "tsx", value: source }) : null] }, key));
59
59
  }) }));
60
- return (_jsx(Page, { scrollable: true, title: meta.title, description: meta.description, beforeContent: beforeContent, 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: {
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
61
  alignItems: 'flex-start',
62
62
  flexDirection: 'row',
63
63
  justifyContent: 'space-between',
@@ -1,7 +1,9 @@
1
+ import React from 'react';
1
2
  export type ThemeConstantDetailScreenProps = {
2
3
  name: string;
3
4
  value: unknown;
4
5
  beforeContent?: React.ReactNode;
6
+ footerContent?: React.ReactNode;
5
7
  };
6
- export declare const ThemeConstantDetailScreen: ({ name, value, beforeContent }: ThemeConstantDetailScreenProps) => import("react").JSX.Element;
8
+ export declare const ThemeConstantDetailScreen: ({ name, value, beforeContent, footerContent, }: ThemeConstantDetailScreenProps) => React.JSX.Element;
7
9
  //# sourceMappingURL=ThemeConstantDetailScreen.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeConstantDetailScreen.d.ts","sourceRoot":"","sources":["../../src/screens/ThemeConstantDetailScreen.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,8BAA8B,GAAG;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACjC,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,gCAAgC,8BAA8B,gCAsBvG,CAAC"}
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"}
@@ -2,8 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Page, Section, Typography } from '@alveole/components';
3
3
  import { useTheme } from '@alveole/theme';
4
4
  import { JsonBlock } from '../components/JsonBlock';
5
- export const ThemeConstantDetailScreen = ({ name, value, beforeContent }) => {
5
+ export const ThemeConstantDetailScreen = ({ name, value, beforeContent, footerContent, }) => {
6
6
  const { text } = useTheme();
7
7
  const entries = typeof value === 'object' && value != null ? Object.entries(value) : [];
8
- return (_jsx(Page, { scrollable: true, title: name, description: name, beforeContent: beforeContent, 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)))) }) }) }));
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
9
  };
@@ -4,10 +4,11 @@ export type ThemeConstantsScreenProps = {
4
4
  title?: string;
5
5
  description?: string;
6
6
  beforeContent?: React.ReactNode;
7
+ footerContent?: React.ReactNode;
7
8
  onSelectConstant?: (entry: {
8
9
  name: string;
9
10
  value: unknown;
10
11
  }) => void;
11
12
  };
12
- export declare const ThemeConstantsScreen: ({ constants, title, description, beforeContent, onSelectConstant, }: ThemeConstantsScreenProps) => React.JSX.Element;
13
+ export declare const ThemeConstantsScreen: ({ constants, title, description, beforeContent, footerContent, onSelectConstant, }: ThemeConstantsScreenProps) => React.JSX.Element;
13
14
  //# sourceMappingURL=ThemeConstantsScreen.d.ts.map
@@ -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,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,qEAMlC,yBAAyB,sBAgC3B,CAAC"}
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"}
@@ -3,12 +3,12 @@ import { Box, Card, Page, 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
- export const ThemeConstantsScreen = ({ constants, title = 'UI Kit - Constants', description = 'Theme constants', beforeContent, onSelectConstant, }) => {
6
+ export const ThemeConstantsScreen = ({ constants, title = 'UI Kit - Constants', description = 'Theme constants', beforeContent, footerContent, onSelectConstant, }) => {
7
7
  const { text } = useTheme();
8
8
  const { width } = useWindowDimensions();
9
9
  const columns = width >= 1200 ? 3 : width >= 768 ? 2 : 1;
10
10
  const entries = React.useMemo(() => Object.entries(constants)
11
11
  .filter(([, value]) => typeof value === 'object' && value != null)
12
12
  .sort((left, right) => left[0].localeCompare(right[0])), [constants]);
13
- return (_jsx(Page, { scrollable: true, title: title, description: description, beforeContent: beforeContent, 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))) }) }) }));
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
14
  };
@@ -3,6 +3,7 @@ export type ThemeTypographyScreenProps = {
3
3
  title?: string;
4
4
  description?: string;
5
5
  beforeContent?: React.ReactNode;
6
+ footerContent?: React.ReactNode;
6
7
  };
7
- export declare const ThemeTypographyScreen: ({ typography, title, description, beforeContent, }: ThemeTypographyScreenProps) => import("react").JSX.Element;
8
+ export declare const ThemeTypographyScreen: ({ typography, title, description, beforeContent, footerContent, }: ThemeTypographyScreenProps) => import("react").JSX.Element;
8
9
  //# sourceMappingURL=ThemeTypographyScreen.d.ts.map
@@ -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;CACjC,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,oDAKnC,0BAA0B,gCAgC5B,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;AAEF,eAAO,MAAM,qBAAqB,GAAI,mEAMnC,0BAA0B,gCAsC5B,CAAC"}
@@ -3,9 +3,9 @@ import { Box, Card, Page, Section, Typography } from '@alveole/components';
3
3
  import { useTheme } from '@alveole/theme';
4
4
  import { useWindowDimensions } from 'react-native';
5
5
  import { JsonBlock } from '../components/JsonBlock';
6
- export const ThemeTypographyScreen = ({ typography, title = 'UI Kit - Theme typography', description = 'Theme text styles', beforeContent, }) => {
6
+ export const ThemeTypographyScreen = ({ typography, title = 'UI Kit - Theme typography', description = 'Theme text styles', beforeContent, footerContent, }) => {
7
7
  const { text } = useTheme();
8
8
  const { width } = useWindowDimensions();
9
9
  const columns = width >= 1200 ? 3 : width >= 768 ? 2 : 1;
10
- return (_jsx(Page, { scrollable: true, title: title, description: description, beforeContent: beforeContent, 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))) }) }) }));
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))) }) }) }));
11
11
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alveole/storybook",
3
- "version": "0.41.0",
3
+ "version": "0.42.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",