@alveole/storybook 0.42.1 → 0.43.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 +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.1",
3
+ "version": "0.43.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",