@temboplus/frontend-react-core 0.1.3-beta.0 → 0.1.3-beta.10

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.
Files changed (86) hide show
  1. package/dist/InfoCircleOutlined-B7d2aRfV.js +7 -0
  2. package/dist/InfoCircleOutlined-B7d2aRfV.js.map +1 -0
  3. package/dist/InfoCircleOutlined-DYs90hdV.js +7 -0
  4. package/dist/InfoCircleOutlined-DYs90hdV.js.map +1 -0
  5. package/dist/ZoomOutOutlined-CW-jqBMI.js +2 -0
  6. package/dist/ZoomOutOutlined-CW-jqBMI.js.map +1 -0
  7. package/dist/ZoomOutOutlined-Pw8hpWWK.js +2 -0
  8. package/dist/ZoomOutOutlined-Pw8hpWWK.js.map +1 -0
  9. package/dist/alerts/index.cjs.js +2 -0
  10. package/dist/alerts/index.cjs.js.map +1 -0
  11. package/dist/alerts/index.d.ts +1 -0
  12. package/dist/alerts/index.js +2 -0
  13. package/dist/alerts/index.js.map +1 -0
  14. package/dist/dialogs/index.cjs.js +2 -0
  15. package/dist/dialogs/index.cjs.js.map +1 -0
  16. package/dist/dialogs/index.d.ts +1 -0
  17. package/dist/dialogs/index.js +2 -0
  18. package/dist/dialogs/index.js.map +1 -0
  19. package/dist/features/alerts/alert.d.ts +12 -0
  20. package/dist/features/alerts/alert.js +95 -0
  21. package/dist/features/alerts/index.d.ts +1 -0
  22. package/dist/features/alerts/index.js +1 -0
  23. package/dist/features/dialogs/index.d.ts +1 -0
  24. package/dist/features/dialogs/index.js +1 -0
  25. package/dist/features/dialogs/modal-provider.d.ts +3 -0
  26. package/dist/features/dialogs/modal-provider.js +6 -0
  27. package/dist/features/dialogs/tembo-confirm.d.ts +63 -0
  28. package/dist/features/dialogs/tembo-confirm.js +111 -0
  29. package/dist/features/input-validation/account-name-validator.d.ts +13 -0
  30. package/dist/features/input-validation/account-name-validator.js +28 -0
  31. package/dist/features/input-validation/account-number-validator.d.ts +13 -0
  32. package/dist/features/input-validation/account-number-validator.js +65 -0
  33. package/dist/{antd-validators.d.ts → features/input-validation/amount-validator.d.ts} +1 -62
  34. package/dist/features/input-validation/amount-validator.js +100 -0
  35. package/dist/features/input-validation/index.d.ts +5 -0
  36. package/dist/features/input-validation/index.js +5 -0
  37. package/dist/features/input-validation/phone-number-validator.d.ts +25 -0
  38. package/dist/features/input-validation/phone-number-validator.js +79 -0
  39. package/dist/features/input-validation/swift-code-validator.d.ts +13 -0
  40. package/dist/features/input-validation/swift-code-validator.js +38 -0
  41. package/dist/features/notifications/index.d.ts +3 -0
  42. package/dist/features/notifications/index.js +3 -0
  43. package/dist/features/notifications/tembo-notify.d.ts +50 -0
  44. package/dist/features/notifications/tembo-notify.js +140 -0
  45. package/dist/features/notifications/toast-config.d.ts +12 -0
  46. package/dist/features/notifications/toast-config.js +60 -0
  47. package/dist/features/notifications/toast-container.d.ts +19 -0
  48. package/dist/features/notifications/toast-container.js +89 -0
  49. package/dist/index.cjs.js +1 -1
  50. package/dist/index.cjs.js.map +1 -1
  51. package/dist/index.d.ts +1 -1
  52. package/dist/index.esm.js +1 -1
  53. package/dist/index.esm.js.map +1 -1
  54. package/dist/index.js +1 -0
  55. package/dist/notifications/index.cjs.js +2 -0
  56. package/dist/notifications/index.cjs.js.map +1 -0
  57. package/dist/notifications/index.d.ts +1 -0
  58. package/dist/notifications/index.js +2 -0
  59. package/dist/notifications/index.js.map +1 -0
  60. package/dist/providers.d.ts +37 -0
  61. package/dist/providers.js +32 -0
  62. package/dist/tembo-notify-Bp14qngd.js +2 -0
  63. package/dist/tembo-notify-Bp14qngd.js.map +1 -0
  64. package/dist/tembo-notify-h5Xn66oA.js +2 -0
  65. package/dist/tembo-notify-h5Xn66oA.js.map +1 -0
  66. package/dist/theme/colors.d.ts +278 -0
  67. package/dist/theme/colors.js +212 -0
  68. package/dist/theme/constants.d.ts +143 -0
  69. package/dist/theme/constants.js +82 -0
  70. package/dist/theme/index.cjs.js +2 -0
  71. package/dist/theme/index.cjs.js.map +1 -0
  72. package/dist/theme/index.d.ts +3 -0
  73. package/dist/theme/index.js +2 -0
  74. package/dist/theme/index.js.map +1 -0
  75. package/dist/theme/theme-provider.d.ts +99 -0
  76. package/dist/theme/theme-provider.js +404 -0
  77. package/dist/theme-provider-Ca4P0Hcp.js +11 -0
  78. package/dist/theme-provider-Ca4P0Hcp.js.map +1 -0
  79. package/dist/theme-provider-RhAw3jw_.js +11 -0
  80. package/dist/theme-provider-RhAw3jw_.js.map +1 -0
  81. package/dist/validation/index.cjs.js +2 -0
  82. package/dist/validation/index.cjs.js.map +1 -0
  83. package/dist/validation/index.d.ts +1 -0
  84. package/dist/validation/index.js +2 -0
  85. package/dist/validation/index.js.map +1 -0
  86. package/package.json +31 -7
@@ -0,0 +1,100 @@
1
+ import { Amount } from "@temboplus/frontend-core";
2
+ /**
3
+ * Creates a validator for monetary amounts using the Amount class.
4
+ * Validates format, currency, and range constraints with currency-specific defaults.
5
+ * Only allows positive amounts (including zero).
6
+ *
7
+ * **Default Range Constraints by Currency:**
8
+ * - **TZS (Tanzanian Shilling)**: Min: 1,000 TZS, Max: 1,000,000 TZS
9
+ * - **KES (Kenyan Shilling)**: Min: 40 KES, Max: 40,000,000 KES
10
+ * - **Other Currencies**: Min: 1, Max: 1,000,000 (in respective currency units)
11
+ *
12
+ * These defaults are applied only when `min` and/or `max` options are not explicitly provided.
13
+ * You can override these defaults by providing explicit `min` and `max` values in the options.
14
+ * Set `min` or `max` to `null` to completely disable that constraint.
15
+ *
16
+ * @param options - Configuration options for amount validation
17
+ * @returns Validator function for AntD form rules
18
+ *
19
+ * @example
20
+ * // Basic validation with TZS currency (uses default min: 1,000 TZS, max: 1,000,000 TZS)
21
+ * rules: [{ required: true, validator: AMOUNT_VALIDATOR() }]
22
+ *
23
+ * @example
24
+ * // Basic validation with KES currency (uses default min: 40 KES, max: 40,000,000 KES)
25
+ * rules: [{ required: true, validator: AMOUNT_VALIDATOR({ currencyCode: 'KES' }) }]
26
+ *
27
+ * @example
28
+ * // Override default ranges with custom min/max values
29
+ * rules: [{
30
+ * required: true,
31
+ * validator: AMOUNT_VALIDATOR({
32
+ * currencyCode: 'USD',
33
+ * min: 1, // Custom minimum (overrides default)
34
+ * max: 10000, // Custom maximum (overrides default)
35
+ * })
36
+ * }]
37
+ *
38
+ * @example
39
+ * // Disable range validation by setting min and max to null
40
+ * rules: [{
41
+ * required: true,
42
+ * validator: AMOUNT_VALIDATOR({
43
+ * currencyCode: 'USD',
44
+ * min: null, // No minimum constraint
45
+ * max: null, // No maximum constraint
46
+ * })
47
+ * }]
48
+ *
49
+ * @example
50
+ * // Disable only minimum constraint, keep maximum
51
+ * rules: [{
52
+ * required: true,
53
+ * validator: AMOUNT_VALIDATOR({
54
+ * currencyCode: 'TZS',
55
+ * min: null, // No minimum constraint
56
+ * // max uses default (1,000,000 TZS)
57
+ * })
58
+ * }]
59
+ */
60
+ export const AMOUNT_VALIDATOR = (options = {}) => {
61
+ const { currencyCode = "TZS", invalidFormatMessage, minMessage, maxMessage, } = options;
62
+ const { min: defaultMin, max: defaultMax } = Amount.getTransactionLimits(currencyCode);
63
+ // Use provided values, or fall back to currency-specific defaults
64
+ // If explicitly set to null, no constraint will be applied
65
+ const min = options.min !== undefined ? options.min : defaultMin;
66
+ const max = options.max !== undefined ? options.max : defaultMax;
67
+ return (rule, value) => {
68
+ // Convert value to string for processing
69
+ const amountString = value === null || value === void 0 ? void 0 : value.toString().trim();
70
+ // If field is empty/undefined/null
71
+ if (!amountString) {
72
+ if (rule.required) {
73
+ return Promise.reject(new Error("Amount is required."));
74
+ }
75
+ return Promise.resolve(undefined);
76
+ }
77
+ // Try to create Amount instance
78
+ const amountInstance = Amount.from(amountString, currencyCode);
79
+ if (!amountInstance) {
80
+ return Promise.reject(new Error(invalidFormatMessage ||
81
+ `Invalid amount format. Please enter a valid monetary amount (e.g., "1000", "1,234.56").`));
82
+ }
83
+ // Reject negative amounts (always not allowed)
84
+ if (amountInstance.isNegative()) {
85
+ return Promise.reject(new Error("Negative amounts are not allowed. Please enter a positive amount."));
86
+ }
87
+ // Check minimum constraint (only if min is not null)
88
+ if (min !== null && amountInstance.lessThan(min)) {
89
+ return Promise.reject(new Error(minMessage ||
90
+ `Amount must be at least ${(defaultMin === null || defaultMin === void 0 ? void 0 : defaultMin.label) || min}. Please enter a higher amount.`));
91
+ }
92
+ // Check maximum constraint (only if max is not null)
93
+ if (max !== null && amountInstance.greaterThan(max)) {
94
+ return Promise.reject(new Error(maxMessage ||
95
+ `Amount must not exceed ${(defaultMax === null || defaultMax === void 0 ? void 0 : defaultMax.label) || max}. Please enter a lower amount.`));
96
+ }
97
+ // Return the formatted numeric value (normalized)
98
+ return Promise.resolve(amountInstance.formattedNumericValue);
99
+ };
100
+ };
@@ -0,0 +1,5 @@
1
+ export * from "./account-name-validator.js";
2
+ export * from "./account-number-validator.js";
3
+ export * from "./amount-validator.js";
4
+ export * from "./phone-number-validator.js";
5
+ export * from "./swift-code-validator.js";
@@ -0,0 +1,5 @@
1
+ export * from "./account-name-validator.js";
2
+ export * from "./account-number-validator.js";
3
+ export * from "./amount-validator.js";
4
+ export * from "./phone-number-validator.js";
5
+ export * from "./swift-code-validator.js";
@@ -0,0 +1,25 @@
1
+ import { ISO2CountryCode } from "@temboplus/frontend-core";
2
+ /**
3
+ * Creates a validator for general phone numbers that validates format and country.
4
+ * Uses PhoneNumberFactory.canCreate() for validation.
5
+ *
6
+ * @param countryCode - The ISO2 country code for validation context
7
+ * @returns Validator function for AntD form rules
8
+ *
9
+ * @example
10
+ * // In form rules
11
+ * rules: [{ required: true, validator: PHONE_NUMBER_VALIDATOR('TZ') }]
12
+ */
13
+ export declare const PHONE_NUMBER_VALIDATOR: (countryCode?: ISO2CountryCode) => (rule: any, value: string | null | undefined) => Promise<string | undefined>;
14
+ /**
15
+ * Creates a validator for mobile phone numbers eligible for payout operations.
16
+ * Uses PhoneNumberFactory.checkPayoutEligibility() for validation.
17
+ *
18
+ * @param countryCode - The ISO2 country code for validation context
19
+ * @returns Validator function for AntD form rules
20
+ *
21
+ * @example
22
+ * // In form rules
23
+ * rules: [{ required: true, validator: MOBILE_PHONE_VALIDATOR('TZ') }]
24
+ */
25
+ export declare const MOBILE_PHONE_VALIDATOR: (countryCode?: ISO2CountryCode) => (rule: any, value: string | null | undefined) => Promise<string | undefined>;
@@ -0,0 +1,79 @@
1
+ import { Country, PhoneNumberFactory } from "@temboplus/frontend-core";
2
+ /**
3
+ * Creates a validator for general phone numbers that validates format and country.
4
+ * Uses PhoneNumberFactory.canCreate() for validation.
5
+ *
6
+ * @param countryCode - The ISO2 country code for validation context
7
+ * @returns Validator function for AntD form rules
8
+ *
9
+ * @example
10
+ * // In form rules
11
+ * rules: [{ required: true, validator: PHONE_NUMBER_VALIDATOR('TZ') }]
12
+ */
13
+ export const PHONE_NUMBER_VALIDATOR = (countryCode) => {
14
+ return (rule, value) => {
15
+ var _a;
16
+ const phoneString = value === null || value === void 0 ? void 0 : value.toString().trim();
17
+ // If field is empty/undefined/null
18
+ if (!phoneString) {
19
+ if (rule.required) {
20
+ return Promise.reject(new Error("Phone number is required."));
21
+ }
22
+ return Promise.resolve(undefined);
23
+ }
24
+ const isValid = PhoneNumberFactory.canCreate(phoneString, {
25
+ defaultCountry: countryCode,
26
+ });
27
+ if (isValid) {
28
+ // Return normalized phone number
29
+ const phoneInstance = PhoneNumberFactory.create(phoneString, {
30
+ defaultCountry: countryCode,
31
+ });
32
+ return Promise.resolve((phoneInstance === null || phoneInstance === void 0 ? void 0 : phoneInstance.e164Format) || phoneString);
33
+ }
34
+ if (countryCode) {
35
+ const countryName = (_a = Country.from(countryCode)) === null || _a === void 0 ? void 0 : _a.name;
36
+ return Promise.reject(new Error(`Invalid ${countryName} phone number format. Please enter a valid ${countryName} phone number.`));
37
+ }
38
+ return Promise.reject(new Error("This phone number is invalid."));
39
+ };
40
+ };
41
+ /**
42
+ * Creates a validator for mobile phone numbers eligible for payout operations.
43
+ * Uses PhoneNumberFactory.checkPayoutEligibility() for validation.
44
+ *
45
+ * @param countryCode - The ISO2 country code for validation context
46
+ * @returns Validator function for AntD form rules
47
+ *
48
+ * @example
49
+ * // In form rules
50
+ * rules: [{ required: true, validator: MOBILE_PHONE_VALIDATOR('TZ') }]
51
+ */
52
+ export const MOBILE_PHONE_VALIDATOR = (countryCode) => {
53
+ return (rule, value) => {
54
+ var _a;
55
+ const phoneString = value === null || value === void 0 ? void 0 : value.toString().trim();
56
+ // If field is empty/undefined/null
57
+ if (!phoneString) {
58
+ if (rule.required) {
59
+ return Promise.reject(new Error("Mobile phone number is required."));
60
+ }
61
+ return Promise.resolve(undefined);
62
+ }
63
+ const phoneInstance = PhoneNumberFactory.create(phoneString, {
64
+ defaultCountry: countryCode,
65
+ });
66
+ if (!phoneInstance) {
67
+ return Promise.reject(new Error("This phone number is invalid."));
68
+ }
69
+ const isEligibleForPayout = PhoneNumberFactory.checkPayoutEligibility(phoneInstance);
70
+ if (isEligibleForPayout) {
71
+ return Promise.resolve((phoneInstance === null || phoneInstance === void 0 ? void 0 : phoneInstance.e164Format) || phoneString);
72
+ }
73
+ if (countryCode) {
74
+ const countryName = (_a = Country.from(countryCode)) === null || _a === void 0 ? void 0 : _a.name;
75
+ return Promise.reject(new Error(`Invalid ${countryName} phone number format. Please enter a valid ${countryName} phone number.`));
76
+ }
77
+ return Promise.reject(new Error("This phone number is invalid."));
78
+ };
79
+ };
@@ -0,0 +1,13 @@
1
+ import { ISO2CountryCode } from "@temboplus/frontend-core";
2
+ /**
3
+ * Creates a validator for SWIFT/BIC codes specific to a country.
4
+ * Uses BankValidation.validateSwiftCode() for validation.
5
+ *
6
+ * @param countryCode - The ISO2 country code for validation context
7
+ * @returns Validator function for AntD form rules
8
+ *
9
+ * @example
10
+ * // In form rules
11
+ * rules: [{ required: true, validator: SWIFT_CODE_VALIDATOR('TZ') }]
12
+ */
13
+ export declare const SWIFT_CODE_VALIDATOR: (countryCode?: ISO2CountryCode) => (rule: any, value: string | null | undefined) => Promise<string | undefined>;
@@ -0,0 +1,38 @@
1
+ import { BankValidation, Country } from "@temboplus/frontend-core";
2
+ /**
3
+ * Creates a validator for SWIFT/BIC codes specific to a country.
4
+ * Uses BankValidation.validateSwiftCode() for validation.
5
+ *
6
+ * @param countryCode - The ISO2 country code for validation context
7
+ * @returns Validator function for AntD form rules
8
+ *
9
+ * @example
10
+ * // In form rules
11
+ * rules: [{ required: true, validator: SWIFT_CODE_VALIDATOR('TZ') }]
12
+ */
13
+ export const SWIFT_CODE_VALIDATOR = (countryCode) => {
14
+ return (rule, value) => {
15
+ var _a;
16
+ const swiftCodeString = value === null || value === void 0 ? void 0 : value.toString().trim().toUpperCase();
17
+ // If field is empty/undefined/null
18
+ if (!swiftCodeString) {
19
+ if (rule.required) {
20
+ return Promise.reject(new Error("SWIFT code is required."));
21
+ }
22
+ return Promise.resolve(undefined);
23
+ }
24
+ if (countryCode) {
25
+ const isValid = BankValidation.validateSwiftCode(swiftCodeString, countryCode);
26
+ if (isValid) {
27
+ return Promise.resolve(swiftCodeString);
28
+ }
29
+ const countryName = (_a = Country.from(countryCode)) === null || _a === void 0 ? void 0 : _a.name;
30
+ return Promise.reject(new Error(`Invalid ${countryName} SWIFT code. Please enter a valid ${countryName} bank SWIFT/BIC code.`));
31
+ }
32
+ const isValid = BankValidation.validateSwiftCodeForAnyCountry(swiftCodeString);
33
+ if (isValid) {
34
+ return Promise.resolve(swiftCodeString);
35
+ }
36
+ return Promise.reject(new Error(`Invalid SWIFT code. Please enter a valid supported bank SWIFT/BIC code.`));
37
+ };
38
+ };
@@ -0,0 +1,3 @@
1
+ export * from "./tembo-notify.js";
2
+ export * from "./toast-config.js";
3
+ export * from "./toast-container.js";
@@ -0,0 +1,3 @@
1
+ export * from "./tembo-notify.js";
2
+ export * from "./toast-config.js";
3
+ export * from "./toast-container.js";
@@ -0,0 +1,50 @@
1
+ import { ToastOptions, ToastContent, Id } from 'react-toastify';
2
+ import { TemboColorPalette, TemboUIConstants } from '../../theme/index.js';
3
+ /**
4
+ * Message input - can be simple string or object with title and description
5
+ */
6
+ export type NotifyMessage = ToastContent | {
7
+ title?: string;
8
+ description?: string;
9
+ };
10
+ export interface NotifyOptions extends Omit<ToastOptions, 'type'> {
11
+ toastId?: Id;
12
+ duration?: number | false;
13
+ onClick?: () => void;
14
+ onClose?: () => void;
15
+ }
16
+ /**
17
+ * TemboNotify - Unified notification system
18
+ */
19
+ export declare class TemboNotify {
20
+ private static configs;
21
+ static init(colors: TemboColorPalette, constants: TemboUIConstants): void;
22
+ private static getConfigs;
23
+ /**
24
+ * Format message content for display
25
+ * - title only → bold
26
+ * - description only → weight 500
27
+ * - title + description → stacked
28
+ */
29
+ private static formatMessage;
30
+ private static buildOptions;
31
+ private static getSuccessConfig;
32
+ private static getErrorConfig;
33
+ private static getWarningConfig;
34
+ private static getInfoConfig;
35
+ private static getLoadingConfig;
36
+ static success(message: NotifyMessage, options?: NotifyOptions): Id;
37
+ static error(message: NotifyMessage, options?: NotifyOptions): Id;
38
+ static warning(message: NotifyMessage, options?: NotifyOptions): Id;
39
+ static info(message: NotifyMessage, options?: NotifyOptions): Id;
40
+ static loading(message: NotifyMessage, options?: Omit<NotifyOptions, 'duration'>): Id;
41
+ static update(id: Id, options: {
42
+ type?: 'success' | 'error' | 'warning' | 'info';
43
+ message?: NotifyMessage;
44
+ autoClose?: number | false;
45
+ render?: ToastContent;
46
+ }): void;
47
+ static dismiss(id?: Id): void;
48
+ static dismissAll(): void;
49
+ static isActive(id: Id): boolean;
50
+ }
@@ -0,0 +1,140 @@
1
+ import { __rest } from "tslib";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { toast } from 'react-toastify';
4
+ import { buildToastConfigs } from './toast-config.js';
5
+ /**
6
+ * Simple fallback config when TemboNotify.init hasn't been called yet.
7
+ */
8
+ const FALLBACK_BASE_CONFIG = {
9
+ position: 'top-right',
10
+ autoClose: 4000, // ~4 seconds for everything except loading
11
+ hideProgressBar: true,
12
+ closeOnClick: true,
13
+ pauseOnHover: true,
14
+ draggable: true,
15
+ closeButton: false,
16
+ };
17
+ /**
18
+ * TemboNotify - Unified notification system
19
+ */
20
+ export class TemboNotify {
21
+ static init(colors, constants) {
22
+ this.configs = buildToastConfigs(colors, constants);
23
+ }
24
+ static getConfigs() {
25
+ return this.configs;
26
+ }
27
+ /**
28
+ * Format message content for display
29
+ * - title only → bold
30
+ * - description only → weight 500
31
+ * - title + description → stacked
32
+ */
33
+ static formatMessage(message) {
34
+ if (message && typeof message === 'object' && !('$$typeof' in message)) {
35
+ const hasTitle = !!message.title;
36
+ const hasDescription = !!message.description;
37
+ if (hasTitle && hasDescription) {
38
+ return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx("div", { style: { fontWeight: 600, fontSize: 14 }, children: message.title }), _jsx("div", { style: { fontSize: 13, fontWeight: 400, opacity: 0.95 }, children: message.description })] }));
39
+ }
40
+ if (hasTitle && !hasDescription) {
41
+ return (_jsx("div", { style: { fontWeight: 600, fontSize: 14 }, children: message.title }));
42
+ }
43
+ if (!hasTitle && hasDescription) {
44
+ return (_jsx("div", { style: { fontSize: 13, fontWeight: 500 }, children: message.description }));
45
+ }
46
+ // Empty object case
47
+ return '';
48
+ }
49
+ return message;
50
+ }
51
+ static buildOptions(baseConfig, options) {
52
+ const _a = options || {}, { duration, toastId, onClick, onClose } = _a, restOptions = __rest(_a, ["duration", "toastId", "onClick", "onClose"]);
53
+ const effectiveBase = baseConfig !== null && baseConfig !== void 0 ? baseConfig : FALLBACK_BASE_CONFIG;
54
+ return Object.assign(Object.assign(Object.assign({}, effectiveBase), restOptions), { // includes custom icon if provided
55
+ toastId, autoClose: duration !== undefined
56
+ ? duration || false
57
+ : effectiveBase.autoClose, onClick,
58
+ onClose });
59
+ }
60
+ static getSuccessConfig() {
61
+ var _a, _b;
62
+ const configs = this.getConfigs();
63
+ return (_b = (_a = configs === null || configs === void 0 ? void 0 : configs.successConfig) !== null && _a !== void 0 ? _a : configs === null || configs === void 0 ? void 0 : configs.baseConfig) !== null && _b !== void 0 ? _b : undefined;
64
+ }
65
+ static getErrorConfig() {
66
+ var _a, _b;
67
+ const configs = this.getConfigs();
68
+ return (_b = (_a = configs === null || configs === void 0 ? void 0 : configs.errorConfig) !== null && _a !== void 0 ? _a : configs === null || configs === void 0 ? void 0 : configs.baseConfig) !== null && _b !== void 0 ? _b : undefined;
69
+ }
70
+ static getWarningConfig() {
71
+ var _a, _b;
72
+ const configs = this.getConfigs();
73
+ return (_b = (_a = configs === null || configs === void 0 ? void 0 : configs.warningConfig) !== null && _a !== void 0 ? _a : configs === null || configs === void 0 ? void 0 : configs.baseConfig) !== null && _b !== void 0 ? _b : undefined;
74
+ }
75
+ static getInfoConfig() {
76
+ var _a, _b;
77
+ const configs = this.getConfigs();
78
+ return (_b = (_a = configs === null || configs === void 0 ? void 0 : configs.infoConfig) !== null && _a !== void 0 ? _a : configs === null || configs === void 0 ? void 0 : configs.baseConfig) !== null && _b !== void 0 ? _b : undefined;
79
+ }
80
+ static getLoadingConfig() {
81
+ var _a, _b;
82
+ const configs = this.getConfigs();
83
+ return (_b = (_a = configs === null || configs === void 0 ? void 0 : configs.loadingConfig) !== null && _a !== void 0 ? _a : configs === null || configs === void 0 ? void 0 : configs.baseConfig) !== null && _b !== void 0 ? _b : undefined;
84
+ }
85
+ static success(message, options) {
86
+ const content = this.formatMessage(message);
87
+ const toastOptions = this.buildOptions(this.getSuccessConfig(), options);
88
+ return toast.success(content, toastOptions);
89
+ }
90
+ static error(message, options) {
91
+ const content = this.formatMessage(message);
92
+ const toastOptions = this.buildOptions(this.getErrorConfig(), options);
93
+ return toast.error(content, toastOptions);
94
+ }
95
+ static warning(message, options) {
96
+ const content = this.formatMessage(message);
97
+ const toastOptions = this.buildOptions(this.getWarningConfig(), options);
98
+ return toast.warning(content, toastOptions);
99
+ }
100
+ static info(message, options) {
101
+ const content = this.formatMessage(message);
102
+ const toastOptions = this.buildOptions(this.getInfoConfig(), options);
103
+ return toast.info(content, toastOptions);
104
+ }
105
+ static loading(message, options) {
106
+ var _a;
107
+ const content = this.formatMessage(message);
108
+ const _b = options || {}, { toastId, onClick, onClose } = _b, restOptions = __rest(_b, ["toastId", "onClick", "onClose"]);
109
+ const baseConfig = (_a = this.getLoadingConfig()) !== null && _a !== void 0 ? _a : FALLBACK_BASE_CONFIG;
110
+ return toast.loading(content, Object.assign(Object.assign(Object.assign({}, baseConfig), restOptions), { toastId,
111
+ onClick,
112
+ onClose }));
113
+ }
114
+ static update(id, options) {
115
+ var _a, _b;
116
+ const configs = this.getConfigs();
117
+ const typeConfig = options.type && configs
118
+ ? {
119
+ success: configs.successConfig,
120
+ error: configs.errorConfig,
121
+ warning: configs.warningConfig,
122
+ info: configs.infoConfig,
123
+ }[options.type]
124
+ : undefined;
125
+ const content = options.message
126
+ ? this.formatMessage(options.message)
127
+ : options.render;
128
+ toast.update(id, Object.assign({ render: content, type: options.type, isLoading: false, autoClose: (_b = (_a = options.autoClose) !== null && _a !== void 0 ? _a : typeConfig === null || typeConfig === void 0 ? void 0 : typeConfig.autoClose) !== null && _b !== void 0 ? _b : FALLBACK_BASE_CONFIG.autoClose }, (typeConfig !== null && typeConfig !== void 0 ? typeConfig : {})));
129
+ }
130
+ static dismiss(id) {
131
+ toast.dismiss(id);
132
+ }
133
+ static dismissAll() {
134
+ toast.dismiss();
135
+ }
136
+ static isActive(id) {
137
+ return toast.isActive(id);
138
+ }
139
+ }
140
+ TemboNotify.configs = null;
@@ -0,0 +1,12 @@
1
+ import { ToastOptions } from 'react-toastify';
2
+ import { TemboColorPalette, TemboUIConstants } from '../../theme/index.js';
3
+ export declare const buildToastConfigs: (colors: TemboColorPalette, constants: TemboUIConstants) => {
4
+ loadingConfig: ToastOptions<unknown>;
5
+ infoConfig: ToastOptions<unknown>;
6
+ warningConfig: ToastOptions<unknown>;
7
+ errorConfig: ToastOptions<unknown>;
8
+ successConfig: ToastOptions<unknown>;
9
+ baseConfig: ToastOptions<unknown>;
10
+ colors: TemboColorPalette;
11
+ };
12
+ export type ToastConfigs = ReturnType<typeof buildToastConfigs>;
@@ -0,0 +1,60 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { CheckCircleOutlined, CloseCircleOutlined, ExclamationCircleOutlined, InfoCircleOutlined, LoadingOutlined, } from '@ant-design/icons';
3
+ export const buildToastConfigs = (colors, constants) => {
4
+ /**
5
+ * Base = WHITE background for everything unless overridden
6
+ */
7
+ const baseConfig = {
8
+ position: 'top-right',
9
+ autoClose: 4000,
10
+ hideProgressBar: true,
11
+ closeOnClick: true,
12
+ pauseOnHover: true,
13
+ draggable: true,
14
+ closeButton: false,
15
+ style: {
16
+ fontFamily: constants.typography.fontFamily,
17
+ fontSize: 14,
18
+ borderRadius: 10,
19
+ padding: '10px 14px',
20
+ boxShadow: '0 12px 24px rgba(15, 23, 42, 0.12)',
21
+ border: 'none',
22
+ minHeight: 56,
23
+ backgroundColor: colors.surface.elevated,
24
+ color: colors.text.primary,
25
+ display: 'flex',
26
+ alignItems: 'center',
27
+ gap: 8,
28
+ },
29
+ };
30
+ /**
31
+ * SUCCESS → success colors
32
+ */
33
+ const successConfig = Object.assign(Object.assign({}, baseConfig), { icon: (_jsx(CheckCircleOutlined, { style: { fontSize: 18, color: colors.success.main } })), style: Object.assign(Object.assign({}, baseConfig.style), { backgroundColor: colors.success.bg, color: colors.success.text }), className: 'toast-success' });
34
+ /**
35
+ * ERROR → error colors
36
+ */
37
+ const errorConfig = Object.assign(Object.assign({}, baseConfig), { icon: (_jsx(CloseCircleOutlined, { style: { fontSize: 18, color: colors.error.main } })), style: Object.assign(Object.assign({}, baseConfig.style), { backgroundColor: colors.error.bg, color: colors.error.text }), className: 'toast-error' });
38
+ /**
39
+ * WARNING → warning colors
40
+ */
41
+ const warningConfig = Object.assign(Object.assign({}, baseConfig), { icon: (_jsx(ExclamationCircleOutlined, { style: { fontSize: 18, color: colors.warning.main } })), style: Object.assign(Object.assign({}, baseConfig.style), { backgroundColor: colors.warning.bg, color: colors.warning.text }), className: 'toast-warning' });
42
+ /**
43
+ * INFO → *white background*, blue accents only
44
+ * (no colored background)
45
+ */
46
+ const infoConfig = Object.assign(Object.assign({}, baseConfig), { icon: (_jsx(InfoCircleOutlined, { style: { fontSize: 18, color: colors.info.main } })), style: Object.assign(Object.assign({}, baseConfig.style), { backgroundColor: colors.surface.elevated, color: colors.text.primary }), className: 'toast-info' });
47
+ /**
48
+ * LOADING (unchanged)
49
+ */
50
+ const loadingConfig = Object.assign(Object.assign({}, baseConfig), { icon: (_jsx(LoadingOutlined, { style: { fontSize: 18, color: colors.primary.main } })), style: Object.assign(Object.assign({}, baseConfig.style), { backgroundColor: colors.surface.elevated, color: colors.text.primary }), autoClose: false, closeButton: false, hideProgressBar: true, className: 'toast-loading' });
51
+ return {
52
+ loadingConfig,
53
+ infoConfig,
54
+ warningConfig,
55
+ errorConfig,
56
+ successConfig,
57
+ baseConfig,
58
+ colors,
59
+ };
60
+ };
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { ToastContainerProps as RTToastContainerProps } from 'react-toastify';
3
+ export interface TemboToastContainerProps extends Omit<RTToastContainerProps, 'closeButton' | 'hideProgressBar'> {
4
+ /**
5
+ * Show the X close button on each toast
6
+ * @default false
7
+ */
8
+ showCloseButton?: boolean;
9
+ /**
10
+ * Show the progress bar at the bottom of each toast
11
+ * @default false
12
+ */
13
+ showProgressBar?: boolean;
14
+ }
15
+ /**
16
+ * Toast container with Tembo styling
17
+ */
18
+ declare const TemboToastContainer: React.FC<TemboToastContainerProps>;
19
+ export default TemboToastContainer;
@@ -0,0 +1,89 @@
1
+ import { __rest } from "tslib";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect } from 'react';
4
+ import { ToastContainer, } from 'react-toastify';
5
+ import { useTemboTheme } from '../../theme/index.js';
6
+ import { TemboNotify } from './tembo-notify.js';
7
+ /**
8
+ * Toast container with Tembo styling
9
+ */
10
+ const TemboToastContainer = (_a) => {
11
+ var { showCloseButton = false, showProgressBar = false } = _a, rest = __rest(_a, ["showCloseButton", "showProgressBar"]);
12
+ const { colors, constants } = useTemboTheme();
13
+ useEffect(() => {
14
+ TemboNotify.init(colors, constants);
15
+ }, [colors, constants]);
16
+ return (_jsxs(_Fragment, { children: [_jsx(ToastContainer, Object.assign({ closeButton: showCloseButton, hideProgressBar: !showProgressBar }, rest)), _jsx("style", { children: `
17
+ .Toastify__toast {
18
+ font-family: ${constants.typography.fontFamily};
19
+ line-height: 1.5;
20
+ display: flex;
21
+ align-items: center; /* center icon + content */
22
+ }
23
+
24
+ .Toastify__toast-body {
25
+ padding: 0;
26
+ margin: 0;
27
+ display: flex;
28
+ align-items: flex-start;
29
+ }
30
+
31
+ .Toastify__toast-icon {
32
+ width: 18px;
33
+ display: flex;
34
+ align-items: center;
35
+ justify-content: center;
36
+ margin-inline-end: 6px; /* tighter spacing */
37
+ }
38
+
39
+ .Toastify__progress-bar {
40
+ display: none;
41
+ }
42
+
43
+ .Toastify__close-button {
44
+ opacity: 0.5;
45
+ transition: opacity 0.2s ease;
46
+ }
47
+
48
+ .Toastify__close-button:hover {
49
+ opacity: 1;
50
+ }
51
+
52
+ /* Force progress bar hidden in case someone enables it unintentionally */
53
+ .Toastify__progress-bar {
54
+ display: none;
55
+ }
56
+
57
+ /* Smooth entrance animation */
58
+ @keyframes toastSlideIn {
59
+ from {
60
+ transform: translateX(110%);
61
+ opacity: 0;
62
+ }
63
+ to {
64
+ transform: translateX(0);
65
+ opacity: 1;
66
+ }
67
+ }
68
+
69
+ .Toastify__toast--top-right {
70
+ animation: toastSlideIn 0.3s ease-out;
71
+ }
72
+
73
+ /* Optional: full-width mobile behaviour */
74
+ @media (max-width: 480px) {
75
+ .Toastify__toast-container--top-right {
76
+ right: 0;
77
+ left: 0;
78
+ padding: 0;
79
+ width: 100vw;
80
+ }
81
+
82
+ .Toastify__toast {
83
+ margin-bottom: 0;
84
+ border-radius: 0;
85
+ }
86
+ }
87
+ ` })] }));
88
+ };
89
+ export default TemboToastContainer;