@temboplus/frontend-react-core 0.1.3-beta.1 → 0.1.3-beta.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,149 @@
1
+ import { toast } from 'react-toastify';
2
+ import { buildToastConfigs } from './toast-config.js';
3
+ /**
4
+ * TemboNotify - Unified notification system
5
+ *
6
+ * Wraps react-toastify with consistent styling and behavior
7
+ * aligned with Tembo's design system.
8
+ *
9
+ * Note: This class needs to be initialized with theme tokens before use.
10
+ * Call TemboNotify.init(colors, constants) in your app setup.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * // In your app setup (e.g., App.tsx)
15
+ * const { colors, constants } = useTemboTheme();
16
+ * useEffect(() => {
17
+ * TemboNotify.init(colors, constants);
18
+ * }, [colors, constants]);
19
+ *
20
+ * // Then use anywhere in your app
21
+ * TemboNotify.success('Payment sent successfully!');
22
+ *
23
+ * // With options
24
+ * TemboNotify.error('Payment failed', {
25
+ * duration: 8000,
26
+ * onClick: () => console.log('Error clicked')
27
+ * });
28
+ *
29
+ * // Loading with promise
30
+ * const loadingId = TemboNotify.loading('Processing payment...');
31
+ * await processPayment();
32
+ * TemboNotify.success('Payment complete!', { id: loadingId });
33
+ *
34
+ * // Promise-based
35
+ * TemboNotify.promise(
36
+ * apiCall(),
37
+ * {
38
+ * pending: 'Processing...',
39
+ * success: 'Done!',
40
+ * error: 'Failed!'
41
+ * }
42
+ * );
43
+ * ```
44
+ */
45
+ export class TemboNotify {
46
+ /**
47
+ * Initialize TemboNotify with theme tokens
48
+ * Must be called before using any notification methods
49
+ */
50
+ static init(colors, constants) {
51
+ this.configs = buildToastConfigs(colors, constants);
52
+ }
53
+ /**
54
+ * Get current toast configs, throws if not initialized
55
+ */
56
+ static getConfigs() {
57
+ if (!this.configs) {
58
+ throw new Error('TemboNotify not initialized. Call TemboNotify.init(colors, constants) before using notifications.');
59
+ }
60
+ return this.configs;
61
+ }
62
+ /**
63
+ * Display a success notification
64
+ */
65
+ static success(message, options) {
66
+ var _a;
67
+ const configs = this.getConfigs();
68
+ return toast.success(message, Object.assign(Object.assign({}, configs.successConfig), { autoClose: (_a = options === null || options === void 0 ? void 0 : options.duration) !== null && _a !== void 0 ? _a : configs.successConfig.autoClose, position: options === null || options === void 0 ? void 0 : options.position, onClick: options === null || options === void 0 ? void 0 : options.onClick, onClose: options === null || options === void 0 ? void 0 : options.onClose }));
69
+ }
70
+ /**
71
+ * Display an error notification
72
+ */
73
+ static error(message, options) {
74
+ var _a;
75
+ const configs = this.getConfigs();
76
+ return toast.error(message, Object.assign(Object.assign({}, configs.errorConfig), { autoClose: (_a = options === null || options === void 0 ? void 0 : options.duration) !== null && _a !== void 0 ? _a : configs.errorConfig.autoClose, position: options === null || options === void 0 ? void 0 : options.position, onClick: options === null || options === void 0 ? void 0 : options.onClick, onClose: options === null || options === void 0 ? void 0 : options.onClose }));
77
+ }
78
+ /**
79
+ * Display a warning notification
80
+ */
81
+ static warning(message, options) {
82
+ var _a;
83
+ const configs = this.getConfigs();
84
+ return toast.warning(message, Object.assign(Object.assign({}, configs.warningConfig), { autoClose: (_a = options === null || options === void 0 ? void 0 : options.duration) !== null && _a !== void 0 ? _a : configs.warningConfig.autoClose, position: options === null || options === void 0 ? void 0 : options.position, onClick: options === null || options === void 0 ? void 0 : options.onClick, onClose: options === null || options === void 0 ? void 0 : options.onClose }));
85
+ }
86
+ /**
87
+ * Display an info notification
88
+ */
89
+ static info(message, options) {
90
+ var _a;
91
+ const configs = this.getConfigs();
92
+ return toast.info(message, Object.assign(Object.assign({}, configs.infoConfig), { autoClose: (_a = options === null || options === void 0 ? void 0 : options.duration) !== null && _a !== void 0 ? _a : configs.infoConfig.autoClose, position: options === null || options === void 0 ? void 0 : options.position, onClick: options === null || options === void 0 ? void 0 : options.onClick, onClose: options === null || options === void 0 ? void 0 : options.onClose }));
93
+ }
94
+ /**
95
+ * Display a loading notification
96
+ * Returns an ID that can be used to update/dismiss it
97
+ */
98
+ static loading(message, options) {
99
+ const configs = this.getConfigs();
100
+ return toast.loading(message, Object.assign(Object.assign({}, configs.loadingConfig), { position: options === null || options === void 0 ? void 0 : options.position, onClick: options === null || options === void 0 ? void 0 : options.onClick, onClose: options === null || options === void 0 ? void 0 : options.onClose }));
101
+ }
102
+ /**
103
+ * Update an existing notification
104
+ */
105
+ static update(id, options) {
106
+ var _a;
107
+ const configs = this.getConfigs();
108
+ const config = options.type ? {
109
+ success: configs.successConfig,
110
+ error: configs.errorConfig,
111
+ warning: configs.warningConfig,
112
+ info: configs.infoConfig,
113
+ }[options.type] : undefined;
114
+ toast.update(id, Object.assign({ render: options.message, type: options.type, isLoading: false, autoClose: (_a = options.autoClose) !== null && _a !== void 0 ? _a : config === null || config === void 0 ? void 0 : config.autoClose }, config));
115
+ }
116
+ /**
117
+ * Dismiss a specific notification by ID
118
+ */
119
+ static dismiss(id) {
120
+ toast.dismiss(id);
121
+ }
122
+ /**
123
+ * Dismiss all notifications
124
+ */
125
+ static dismissAll() {
126
+ toast.dismiss();
127
+ }
128
+ /**
129
+ * Check if a notification is active
130
+ */
131
+ static isActive(id) {
132
+ return toast.isActive(id);
133
+ }
134
+ /**
135
+ * Handle promise-based operations with notifications
136
+ */
137
+ static promise(promise, messages, options) {
138
+ var _a, _b;
139
+ const configs = this.getConfigs();
140
+ return toast.promise(promise, {
141
+ pending: Object.assign({ render: messages.pending }, configs.loadingConfig),
142
+ success: Object.assign(Object.assign({ render: messages.success }, configs.successConfig), { autoClose: (_a = options === null || options === void 0 ? void 0 : options.duration) !== null && _a !== void 0 ? _a : configs.successConfig.autoClose }),
143
+ error: Object.assign(Object.assign({ render: messages.error }, configs.errorConfig), { autoClose: (_b = options === null || options === void 0 ? void 0 : options.duration) !== null && _b !== void 0 ? _b : configs.errorConfig.autoClose }),
144
+ }, {
145
+ position: options === null || options === void 0 ? void 0 : options.position,
146
+ });
147
+ }
148
+ }
149
+ TemboNotify.configs = null;
@@ -0,0 +1,53 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { CheckCircleOutlined, CloseCircleOutlined, ExclamationCircleOutlined, InfoCircleOutlined, } from '@ant-design/icons';
3
+ /**
4
+ * Build toast configurations from theme tokens
5
+ * This function is called with theme values to generate toast configs
6
+ */
7
+ export const buildToastConfigs = (colors, constants) => {
8
+ /**
9
+ * Common toast configuration aligned with Tembo theme
10
+ */
11
+ const baseConfig = {
12
+ position: 'top-right',
13
+ autoClose: 4000,
14
+ hideProgressBar: false,
15
+ closeOnClick: true,
16
+ pauseOnHover: true,
17
+ draggable: true,
18
+ progress: undefined,
19
+ style: {
20
+ fontFamily: constants.typography.fontFamily,
21
+ fontSize: constants.typography.fontSize.base,
22
+ borderRadius: constants.radius.base,
23
+ },
24
+ };
25
+ /**
26
+ * Success notification configuration
27
+ */
28
+ const successConfig = Object.assign(Object.assign({}, baseConfig), { icon: _jsx(CheckCircleOutlined, { style: { fontSize: 20, color: colors.success.main } }), style: Object.assign(Object.assign({}, baseConfig.style), { border: `1px solid ${colors.success.border}` }) });
29
+ /**
30
+ * Error notification configuration
31
+ */
32
+ const errorConfig = Object.assign(Object.assign({}, baseConfig), { icon: _jsx(CloseCircleOutlined, { style: { fontSize: 20, color: colors.error.main } }), style: Object.assign(Object.assign({}, baseConfig.style), { border: `1px solid ${colors.error.border}` }), autoClose: 6000 });
33
+ /**
34
+ * Warning notification configuration
35
+ */
36
+ const warningConfig = Object.assign(Object.assign({}, baseConfig), { icon: _jsx(ExclamationCircleOutlined, { style: { fontSize: 20, color: colors.warning.main } }), style: Object.assign(Object.assign({}, baseConfig.style), { border: `1px solid ${colors.warning.border}` }) });
37
+ /**
38
+ * Info notification configuration
39
+ */
40
+ const infoConfig = Object.assign(Object.assign({}, baseConfig), { icon: _jsx(InfoCircleOutlined, { style: { fontSize: 20, color: colors.info.main } }), style: Object.assign(Object.assign({}, baseConfig.style), { border: `1px solid ${colors.info.border}` }) });
41
+ /**
42
+ * Loading notification configuration
43
+ */
44
+ const loadingConfig = Object.assign(Object.assign({}, baseConfig), { autoClose: false, closeButton: false });
45
+ return {
46
+ loadingConfig,
47
+ infoConfig,
48
+ warningConfig,
49
+ errorConfig,
50
+ successConfig,
51
+ baseConfig,
52
+ };
53
+ };
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect } from 'react';
3
+ import { ToastContainer } from 'react-toastify';
4
+ import { useTemboTheme } from '../../theme/index.js';
5
+ import { TemboNotify } from './tembo-notify.js';
6
+ /**
7
+ * Toast container that automatically initializes TemboNotify with current theme
8
+ * Reinitializes when theme changes to respect color/constant overrides
9
+ */
10
+ const TemboToastContainer = (props) => {
11
+ const { colors, constants } = useTemboTheme();
12
+ // Initialize/update TemboNotify whenever theme changes
13
+ useEffect(() => {
14
+ TemboNotify.init(colors, constants);
15
+ }, [colors, constants]);
16
+ return _jsx(ToastContainer, Object.assign({}, props));
17
+ };
18
+ export default TemboToastContainer;
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from "./providers.js";
@@ -0,0 +1 @@
1
+ export * from "../features/notifications";
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import TemboModalProvider from './features/dialogs/modal-provider.js';
3
+ import TemboToastContainer from './features/notifications/toast-container.js';
4
+ import { TemboThemeProvider } from './theme/index.js';
5
+ /**
6
+ * Top-level provider that wires up theme, modal and notifications
7
+ * for all Tembo UI components.
8
+ *
9
+ * Supports theme customization through colors and constants props.
10
+ * TemboToastContainer automatically syncs with theme changes.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * // Basic usage
15
+ * <TemboUIProviders>
16
+ * <App />
17
+ * </TemboUIProviders>
18
+ *
19
+ * // With custom colors
20
+ * <TemboUIProviders
21
+ * colors={{
22
+ * primary: { main: '#007bff' },
23
+ * action: { main: '#28a745' }
24
+ * }}
25
+ * >
26
+ * <App />
27
+ * </TemboUIProviders>
28
+ * ```
29
+ */
30
+ export const TemboUIProviders = ({ children, colors, constants, themeOverrides, }) => {
31
+ return (_jsx(TemboThemeProvider, { colors: colors, constants: constants, themeOverrides: themeOverrides, children: _jsxs(TemboModalProvider, { children: [children, _jsx(TemboToastContainer, {})] }) }));
32
+ };
@@ -0,0 +1,138 @@
1
+ import { merge } from "lodash";
2
+ /**
3
+ * Default Tembo color palette
4
+ * Light theme with professional, accessible colors
5
+ */
6
+ export const defaultColorPalette = {
7
+ primary: {
8
+ main: '#000000',
9
+ hover: '#1a1a1a',
10
+ active: '#000000',
11
+ light: '#666666',
12
+ lighter: '#999999',
13
+ contrast: '#FFFFFF',
14
+ },
15
+ action: {
16
+ main: '#1a6985',
17
+ hover: '#145268',
18
+ active: '#0f3d4f',
19
+ light: '#e8f2f5',
20
+ lighter: '#f4f9fa',
21
+ disabled: '#a3c9d6',
22
+ contrast: '#FFFFFF',
23
+ },
24
+ neutral: {
25
+ 50: '#ffffff',
26
+ 100: '#fafafa',
27
+ 200: '#f5f5f5',
28
+ 300: '#f0f0f0',
29
+ 400: '#e5e5e5',
30
+ 500: '#d4d4d4',
31
+ 600: '#b3b3b3',
32
+ 700: '#999999',
33
+ 800: '#666666',
34
+ 900: '#1a1a1a',
35
+ 950: '#000000',
36
+ },
37
+ success: {
38
+ main: '#10b981',
39
+ bg: '#ecfdf5',
40
+ border: '#a7f3d0',
41
+ text: '#047857',
42
+ },
43
+ error: {
44
+ main: '#ef4444',
45
+ bg: '#fef2f2',
46
+ border: '#fecaca',
47
+ text: '#dc2626',
48
+ },
49
+ warning: {
50
+ main: '#f59e0b',
51
+ bg: '#fffbeb',
52
+ border: '#fde68a',
53
+ text: '#d97706',
54
+ },
55
+ info: {
56
+ main: '#1a6985',
57
+ bg: '#e8f2f5',
58
+ border: '#b8d9e6',
59
+ text: '#0f3d4f',
60
+ },
61
+ surface: {
62
+ background: '#ffffff',
63
+ main: '#ffffff',
64
+ elevated: '#ffffff',
65
+ hover: '#fafafa',
66
+ subtle: '#f9fafb',
67
+ },
68
+ text: {
69
+ primary: '#000000',
70
+ secondary: '#666666',
71
+ tertiary: '#999999',
72
+ quaternary: '#b3b3b3',
73
+ disabled: '#d4d4d4',
74
+ inverse: '#ffffff',
75
+ },
76
+ border: {
77
+ main: '#e5e5e5',
78
+ light: '#f0f0f0',
79
+ strong: '#d4d4d4',
80
+ divider: '#e5e5e5',
81
+ },
82
+ components: {
83
+ button: {
84
+ primary: {
85
+ bg: '#1a6985',
86
+ hover: '#145268',
87
+ text: '#FFFFFF',
88
+ },
89
+ default: {
90
+ bg: '#FFFFFF',
91
+ border: '#d4d4d4',
92
+ text: '#000000',
93
+ hover: '#fafafa',
94
+ },
95
+ },
96
+ input: {
97
+ bg: '#ffffff',
98
+ border: '#d4d4d4',
99
+ borderHover: '#999999',
100
+ borderFocus: '#1a6985',
101
+ placeholder: '#999999',
102
+ },
103
+ table: {
104
+ bg: '#ffffff',
105
+ headerBg: '#fafafa',
106
+ headerText: '#000000',
107
+ border: '#e5e5e5',
108
+ rowHover: '#fafafa',
109
+ },
110
+ sidebar: {
111
+ bg: '#000000',
112
+ hover: 'rgba(255, 255, 255, 0.08)',
113
+ selected: 'rgba(255, 255, 255, 0.12)',
114
+ text: '#FFFFFF',
115
+ textSecondary: 'rgba(255, 255, 255, 0.65)',
116
+ },
117
+ },
118
+ utility: {
119
+ white: '#ffffff',
120
+ black: '#000000',
121
+ transparent: 'transparent',
122
+ link: '#1a6985',
123
+ linkHover: '#145268',
124
+ linkActive: '#0f3d4f',
125
+ },
126
+ };
127
+ /**
128
+ * Build a complete color palette by merging overrides with defaults
129
+ * Performs deep merge to allow partial nested overrides
130
+ *
131
+ * @param overrides - Partial color palette overrides
132
+ * @returns Complete color palette with overrides applied
133
+ */
134
+ export const buildColorPalette = (overrides) => {
135
+ if (!overrides)
136
+ return defaultColorPalette;
137
+ return merge(defaultColorPalette, overrides);
138
+ };
@@ -0,0 +1,82 @@
1
+ import { merge } from 'lodash';
2
+ /**
3
+ * Default UI constants
4
+ * Professional, accessible defaults suitable for most applications
5
+ */
6
+ export const defaultUIConstants = {
7
+ typography: {
8
+ fontFamily: "Avenir, MarkPro, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
9
+ fontSize: {
10
+ xs: 12,
11
+ sm: 13,
12
+ base: 14,
13
+ lg: 16,
14
+ xl: 18,
15
+ },
16
+ fontWeight: {
17
+ normal: 400,
18
+ medium: 500,
19
+ semibold: 600,
20
+ bold: 700,
21
+ },
22
+ lineHeight: {
23
+ tight: 1.25,
24
+ base: 1.5715,
25
+ relaxed: 1.75,
26
+ },
27
+ },
28
+ spacing: {
29
+ xs: 4,
30
+ sm: 8,
31
+ md: 12,
32
+ lg: 16,
33
+ xl: 24,
34
+ '2xl': 32,
35
+ '3xl': 48,
36
+ },
37
+ radius: {
38
+ none: 0,
39
+ sm: 8,
40
+ base: 12,
41
+ md: 14,
42
+ lg: 16,
43
+ xl: 20,
44
+ full: 9999,
45
+ button: 24,
46
+ input: 10,
47
+ card: 16,
48
+ },
49
+ shadow: {
50
+ sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
51
+ base: '0 1px 3px 0 rgba(0, 0, 0, 0.08), 0 1px 2px -1px rgba(0, 0, 0, 0.08)',
52
+ md: '0 4px 6px -1px rgba(0, 0, 0, 0.08), 0 2px 4px -2px rgba(0, 0, 0, 0.08)',
53
+ lg: '0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -4px rgba(0, 0, 0, 0.08)',
54
+ xl: '0 20px 25px -5px rgba(0, 0, 0, 0.08), 0 8px 10px -6px rgba(0, 0, 0, 0.08)',
55
+ card: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
56
+ elevated: '0 4px 6px -1px rgba(0, 0, 0, 0.08), 0 2px 4px -2px rgba(0, 0, 0, 0.08)',
57
+ dropdown: '0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -4px rgba(0, 0, 0, 0.08)',
58
+ },
59
+ zIndex: {
60
+ dropdown: 1000,
61
+ modal: 1050,
62
+ popover: 1060,
63
+ tooltip: 1070,
64
+ notification: 1080,
65
+ },
66
+ transition: {
67
+ fast: '150ms cubic-bezier(0.4, 0, 0.2, 1)',
68
+ base: '200ms cubic-bezier(0.4, 0, 0.2, 1)',
69
+ slow: '300ms cubic-bezier(0.4, 0, 0.2, 1)',
70
+ },
71
+ };
72
+ /**
73
+ * Build complete UI constants by merging overrides with defaults
74
+ *
75
+ * @param overrides - Partial UI constants overrides
76
+ * @returns Complete UI constants with overrides applied
77
+ */
78
+ export const buildUIConstants = (overrides) => {
79
+ if (!overrides)
80
+ return defaultUIConstants;
81
+ return merge(defaultUIConstants, overrides);
82
+ };