@alveole/storybook 0.42.0 → 0.42.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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;AAqBF,eAAO,MAAM,WAAW,GAAI,sBAAsB,gBAAgB,gCA+CjE,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,6 +1,7 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Box, Header, 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 React from 'react';
4
5
  import { Pressable } from 'react-native';
5
6
  const AlveoleLogo = () => {
6
7
  const { color, radius, text } = useTheme();
@@ -15,22 +16,30 @@ const AlveoleLogo = () => {
15
16
  }, children: _jsx(Typography, { style: { ...text['Corps de texte'].XS.Bold, color: '#fff' }, children: "A" }) }));
16
17
  };
17
18
  export const UIKitTopBar = ({ activeKey, items }) => {
18
- const { color, radius, text } = useTheme();
19
- const right = (_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
- }) }));
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))) }));
35
44
  return _jsx(Header, { logo: _jsx(AlveoleLogo, {}), title: "Alveole UI Kit", right: right });
36
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
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"UIKitPage.d.ts","sourceRoot":"","sources":["../../src/pages/UIKitPage.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,KAAK,SAAS,GAAG;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;CAC/B,CAAC;AAaF,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAwGF,eAAO,MAAM,SAAS,GAAI,6EAQvB,cAAc,6BAmHhB,CAAC"}
1
+ {"version":3,"file":"UIKitPage.d.ts","sourceRoot":"","sources":["../../src/pages/UIKitPage.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C,KAAK,SAAS,GAAG;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;CAC/B,CAAC;AAcF,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AA2GF,eAAO,MAAM,SAAS,GAAI,6EAQvB,cAAc,6BAwHhB,CAAC"}
@@ -8,6 +8,7 @@ import { ThemeConstantDetailScreen } from '../screens/ThemeConstantDetailScreen'
8
8
  import { ThemeConstantsScreen } from '../screens/ThemeConstantsScreen';
9
9
  import { ThemePaletteScreen } from '../screens/ThemePaletteScreen';
10
10
  import { ThemeTypographyScreen } from '../screens/ThemeTypographyScreen';
11
+ import { PhilosophyPage } from './PhilosophyPage';
11
12
  const MenuCard = ({ title, description, onPress }) => {
12
13
  const { text } = useTheme();
13
14
  return (_jsx(Card, { onPress: onPress, children: _jsxs(Box, { display: "flex", gap: 8, p: '150', children: [_jsx(Typography, { style: text.Titres['H4 - SM'], children: title }), _jsx(Typography, { style: text['Corps de texte'].SM.Regular, children: description })] }) }));
@@ -17,8 +18,8 @@ const InternalHeader = ({ canGoBack, onBack }) => {
17
18
  return null;
18
19
  return (_jsx(Section, { withPaddingY: true, children: _jsx(Box, { children: _jsx(Button, { title: "Retour", variant: "tertiary", size: "sm", onPress: onBack }) }) }));
19
20
  };
20
- const HomeScreen = ({ title, description, blankPage, onOpenComponents, onOpenTheme, onOpenConstants, onOpenBlank, }) => {
21
- return (_jsx(Page, { scrollable: true, title: title, description: description, children: _jsx(Section, { withPaddingY: true, children: _jsxs(Box, { display: "flex", gap: 16, children: [_jsx(MenuCard, { title: "Composants", description: "Catalogue des composants et de leurs variantes.", onPress: onOpenComponents }), _jsx(MenuCard, { title: "Th\u00E8me", description: "Couleurs et typographies du design system.", onPress: onOpenTheme }), _jsx(MenuCard, { title: "Constantes", description: "Constantes expos\u00E9es par le th\u00E8me.", onPress: onOpenConstants }), blankPage ? (_jsx(MenuCard, { title: blankPage.title ?? 'Page vierge', description: blankPage.description ?? 'Espace de test libre pour expérimenter.', onPress: onOpenBlank })) : null] }) }) }));
21
+ const HomeScreen = ({ title, description, blankPage, onOpenComponents, onOpenTheme, onOpenConstants, onOpenBlank, onOpenPhilosophy, }) => {
22
+ return (_jsx(Page, { scrollable: true, title: title, description: description, children: _jsx(Section, { withPaddingY: true, children: _jsxs(Box, { display: "flex", gap: 16, children: [_jsx(MenuCard, { title: "Composants", description: "Catalogue des composants et de leurs variantes.", onPress: onOpenComponents }), _jsx(MenuCard, { title: "Th\u00E8me", description: "Couleurs et typographies du design system.", onPress: onOpenTheme }), _jsx(MenuCard, { title: "Constantes", description: "Constantes expos\u00E9es par le th\u00E8me.", onPress: onOpenConstants }), _jsx(MenuCard, { title: "Philosophie", description: "Les principes qui guident Alveole.", onPress: onOpenPhilosophy }), blankPage ? (_jsx(MenuCard, { title: blankPage.title ?? 'Page vierge', description: blankPage.description ?? 'Espace de test libre pour expérimenter.', onPress: onOpenBlank })) : null] }) }) }));
22
23
  };
23
24
  const ThemeHomeScreen = ({ onOpenColors, onOpenTypography, beforeContent, }) => {
24
25
  return (_jsx(Page, { scrollable: true, title: "UI Kit - Th\u00E8me", description: "Tokens du th\u00E8me", beforeContent: beforeContent, children: _jsx(Section, { withPaddingY: true, children: _jsxs(Box, { display: "flex", gap: 16, children: [_jsx(MenuCard, { title: "Couleurs", description: "Palette et couleurs du th\u00E8me.", onPress: onOpenColors }), _jsx(MenuCard, { title: "Typographies", description: "Styles de texte et hi\u00E9rarchie typographique.", onPress: onOpenTypography })] }) }) }));
@@ -35,7 +36,7 @@ export const UIKitPage = ({ stories, constants, palette = CustomPalette, typogra
35
36
  }, []);
36
37
  const beforeContent = _jsx(InternalHeader, { canGoBack: canGoBack, onBack: goBack });
37
38
  if (route.name === 'home') {
38
- 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' }) }));
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' }) }));
39
40
  }
40
41
  if (route.name === 'components') {
41
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 }) }));
@@ -58,6 +59,9 @@ export const UIKitPage = ({ stories, constants, palette = CustomPalette, typogra
58
59
  if (route.name === 'constant-detail') {
59
60
  return (_jsx(ThemeConstantDetailScreen, { beforeContent: beforeContent, name: route.constantName, value: route.constantValue }));
60
61
  }
62
+ if (route.name === 'philosophy') {
63
+ return _jsx(PhilosophyPage, { beforeContent: beforeContent });
64
+ }
61
65
  if (route.name === 'blank' && blankPage) {
62
66
  return (_jsx(Page, { scrollable: true, title: blankPage.title ?? 'Page vierge', description: blankPage.description ?? 'Zone de test libre', beforeContent: beforeContent, children: _jsx(Section, { withPaddingY: true, children: blankPage.render() }) }));
63
67
  }
@@ -1,13 +1,10 @@
1
- interface PaletteScale {
2
- [key: string]: PaletteValue;
3
- }
4
- type PaletteValue = string | PaletteScale;
1
+ import React from 'react';
5
2
  export type ThemePaletteScreenProps = {
6
- palette: Record<string, PaletteValue>;
3
+ palette: Record<string, unknown>;
7
4
  title?: string;
8
5
  description?: string;
9
6
  beforeContent?: React.ReactNode;
7
+ footerContent?: React.ReactNode;
10
8
  };
11
- export declare const ThemePaletteScreen: ({ palette, title, description, beforeContent, }: ThemePaletteScreenProps) => import("react").JSX.Element;
12
- export {};
9
+ export declare const ThemePaletteScreen: ({ palette, title, description, beforeContent, footerContent, }: ThemePaletteScreenProps) => React.JSX.Element;
13
10
  //# sourceMappingURL=ThemePaletteScreen.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ThemePaletteScreen.d.ts","sourceRoot":"","sources":["../../src/screens/ThemePaletteScreen.tsx"],"names":[],"mappings":"AAKA,UAAU,YAAY;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC;CAC7B;AAED,KAAK,YAAY,GAAG,MAAM,GAAG,YAAY,CAAC;AAmB1C,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACjC,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,iDAKhC,uBAAuB,gCAuBzB,CAAC"}
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,17 +1,117 @@
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, Page, Section, Typography, useToast } from '@alveole/components';
3
3
  import { useTheme } from '@alveole/theme';
4
- import { useWindowDimensions } from 'react-native';
5
- import { JsonBlock } from '../components/JsonBlock';
6
- const PaletteValueView = ({ label, value }) => {
7
- const { text } = useTheme();
8
- return (_jsxs(Box, { display: "flex", gap: 8, children: [label ? _jsx(Typography, { style: text['Corps de texte'].XS.SemiBold, children: label }) : null, typeof value === 'string' ? _jsx(Box, { height: 48, width: 48, borderRadius: 8, backgroundColor: value }) : null, _jsx(JsonBlock, { value: value }), typeof value === 'object'
9
- ? Object.entries(value).map(([childLabel, childValue]) => (_jsx(PaletteValueView, { label: childLabel, value: childValue }, childLabel)))
10
- : null] }));
4
+ import React from 'react';
5
+ import { Pressable } from 'react-native';
6
+ function flattenColors(obj, prefix = '') {
7
+ const entries = [];
8
+ for (const [key, val] of Object.entries(obj)) {
9
+ const path = prefix ? `${prefix}.${key}` : key;
10
+ if (typeof val === 'string') {
11
+ entries.push({ path, value: val });
12
+ }
13
+ else if (val && typeof val === 'object') {
14
+ entries.push(...flattenColors(val, path));
15
+ }
16
+ }
17
+ return entries;
18
+ }
19
+ const DEPRECATED_KEYS = [
20
+ 'primary',
21
+ 'transparent',
22
+ 'danger',
23
+ 'info',
24
+ 'success',
25
+ 'warning',
26
+ 'link',
27
+ 'text',
28
+ 'border',
29
+ 'background',
30
+ 'system',
31
+ ];
32
+ function buildSections(palette) {
33
+ const sections = [];
34
+ for (const [modeKey, modeVal] of Object.entries(palette)) {
35
+ if (modeKey === 'light' || modeKey === 'dark') {
36
+ if (modeVal && typeof modeVal === 'object') {
37
+ for (const [groupKey, groupVal] of Object.entries(modeVal)) {
38
+ const entries = flattenColors({ [groupKey]: groupVal }, modeKey);
39
+ if (entries.length > 0) {
40
+ sections.push({ title: `${modeKey} / ${groupKey}`, entries });
41
+ }
42
+ }
43
+ }
44
+ }
45
+ }
46
+ const deprecatedEntries = [];
47
+ for (const key of DEPRECATED_KEYS) {
48
+ const val = palette[key];
49
+ if (val !== undefined) {
50
+ if (typeof val === 'string') {
51
+ deprecatedEntries.push({ path: key, value: val });
52
+ }
53
+ else if (val && typeof val === 'object') {
54
+ deprecatedEntries.push(...flattenColors(val, key));
55
+ }
56
+ }
57
+ }
58
+ if (deprecatedEntries.length > 0) {
59
+ sections.push({ title: 'Deprecated', entries: deprecatedEntries, deprecated: true });
60
+ }
61
+ return sections;
62
+ }
63
+ const ColorSwatch = ({ entry }) => {
64
+ const toast = useToast();
65
+ const { color, radius } = useTheme();
66
+ const tokenName = entry.path.split('.').pop() ?? entry.path;
67
+ const handleCopy = () => {
68
+ if (typeof navigator !== 'undefined' && navigator.clipboard) {
69
+ navigator.clipboard.writeText(entry.value).then(() => {
70
+ toast.present('Copié !', entry.value, { variant: 'success', duration: 1500 });
71
+ });
72
+ }
73
+ };
74
+ return (_jsx(Pressable, { onPress: handleCopy, style: { width: 120, marginBottom: 8 }, children: ({ pressed }) => (_jsxs(Box, { style: {
75
+ borderRadius: radius('md'),
76
+ overflow: 'hidden',
77
+ opacity: pressed ? 0.8 : 1,
78
+ borderWidth: 1,
79
+ borderColor: color.light.border['default-grey'],
80
+ }, children: [_jsx(Box, { style: { height: 56, backgroundColor: entry.value } }), _jsxs(Box, { style: {
81
+ paddingHorizontal: 8,
82
+ paddingVertical: 6,
83
+ backgroundColor: color.light.background['default-grey'],
84
+ }, children: [_jsx(Typography, { style: { fontSize: 11, fontWeight: '600', color: color.light.text['title-grey'], lineHeight: 14 }, numberOfLines: 1, children: tokenName }), _jsx(Typography, { style: {
85
+ fontSize: 10,
86
+ color: color.light.text['mention-grey'],
87
+ fontFamily: 'monospace',
88
+ lineHeight: 14,
89
+ marginTop: 2,
90
+ }, numberOfLines: 1, children: entry.value })] })] })) }));
11
91
  };
12
- export const ThemePaletteScreen = ({ palette, title = 'UI Kit - Theme colors', description = 'Theme palette', beforeContent, }) => {
13
- const { text } = useTheme();
14
- const { width } = useWindowDimensions();
15
- const columns = width >= 1200 ? 3 : width >= 768 ? 2 : 1;
16
- 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(palette).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 }), _jsx(PaletteValueView, { value: value })] }) }) }, key))) }) }) }));
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
+ export const ThemePaletteScreen = ({ palette, title = 'UI Kit - Couleurs du thème', description = 'Palette et couleurs du thème', beforeContent, footerContent, }) => {
114
+ const { color } = useTheme();
115
+ 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)))] }) }));
17
117
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alveole/storybook",
3
- "version": "0.42.0",
3
+ "version": "0.42.2",
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",