beem-component 2.1.3 → 2.1.5

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,174 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _styledComponents = _interopRequireDefault(require("styled-components"));
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
+ const hexToRgba = function (hex) {
11
+ let opacity = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.6;
12
+ try {
13
+ const normalizedHex = hex === null || hex === void 0 ? void 0 : hex.replace('#', '');
14
+ if (!normalizedHex || normalizedHex.length !== 6 || !/^[0-9a-fA-F]{6}$/.test(normalizedHex)) {
15
+ throw new Error('Invalid hex');
16
+ }
17
+ const r = parseInt(normalizedHex.slice(0, 2), 16);
18
+ const g = parseInt(normalizedHex.slice(2, 4), 16);
19
+ const b = parseInt(normalizedHex.slice(4, 6), 16);
20
+ return "rgba(".concat(r, ", ").concat(g, ", ").concat(b, ", ").concat(opacity, ")");
21
+ } catch (e) {
22
+ return "rgba(0, 0, 0, ".concat(opacity, ")");
23
+ }
24
+ };
25
+ const BackgroundStripe = _styledComponents.default.div.withConfig({
26
+ displayName: "CustomCardTitle__BackgroundStripe"
27
+ })(["background-color:", ";padding-top:", ";padding-bottom:", ";padding-left:1rem;padding-right:1rem;@media (min-width:640px){padding-top:", ";padding-bottom:", ";padding-left:1.5rem;padding-right:1.5rem;}"], _ref => {
28
+ let {
29
+ themeColor
30
+ } = _ref;
31
+ return hexToRgba(themeColor, 0.1);
32
+ }, _ref2 => {
33
+ let {
34
+ variant
35
+ } = _ref2;
36
+ return variant === 'confirmation' ? '1rem' : '1.5rem';
37
+ }, _ref3 => {
38
+ let {
39
+ variant
40
+ } = _ref3;
41
+ return variant === 'confirmation' ? '1rem' : '2rem';
42
+ }, _ref4 => {
43
+ let {
44
+ variant
45
+ } = _ref4;
46
+ return variant === 'confirmation' ? '1.5rem' : '2rem';
47
+ }, _ref5 => {
48
+ let {
49
+ variant
50
+ } = _ref5;
51
+ return variant === 'confirmation' ? '1.5rem' : '2.5rem';
52
+ });
53
+ const CardContainer = _styledComponents.default.div.withConfig({
54
+ displayName: "CustomCardTitle__CardContainer"
55
+ })(["background-color:", ";padding:1rem;border-radius:0.75rem;@media (min-width:640px){padding:1.5rem;}"], hexToRgba('#ffffff', 0.7));
56
+ const IconWrapper = _styledComponents.default.div.withConfig({
57
+ displayName: "CustomCardTitle__IconWrapper"
58
+ })(["background-color:", ";border:2px solid ", ";height:", ";width:", ";border-radius:9999px;display:flex;align-items:center;justify-content:center;margin:0 auto ", ";@media (min-width:640px){height:", ";width:", ";margin-bottom:", ";}svg{height:", ";width:", ";color:", ";@media (min-width:640px){height:", ";width:", ";}}"], _ref6 => {
59
+ let {
60
+ themeColor
61
+ } = _ref6;
62
+ return hexToRgba(themeColor, 0.1);
63
+ }, _ref7 => {
64
+ let {
65
+ themeColor
66
+ } = _ref7;
67
+ return themeColor;
68
+ }, _ref8 => {
69
+ let {
70
+ variant
71
+ } = _ref8;
72
+ return variant === 'confirmation' ? '3.5rem' : '4rem';
73
+ }, _ref9 => {
74
+ let {
75
+ variant
76
+ } = _ref9;
77
+ return variant === 'confirmation' ? '3.5rem' : '4rem';
78
+ }, _ref0 => {
79
+ let {
80
+ variant
81
+ } = _ref0;
82
+ return variant === 'confirmation' ? '0.75rem' : '1rem';
83
+ }, _ref1 => {
84
+ let {
85
+ variant
86
+ } = _ref1;
87
+ return variant === 'confirmation' ? '4rem' : '5rem';
88
+ }, _ref10 => {
89
+ let {
90
+ variant
91
+ } = _ref10;
92
+ return variant === 'confirmation' ? '4rem' : '5rem';
93
+ }, _ref11 => {
94
+ let {
95
+ variant
96
+ } = _ref11;
97
+ return variant === 'confirmation' ? '1rem' : '1.25rem';
98
+ }, _ref12 => {
99
+ let {
100
+ variant
101
+ } = _ref12;
102
+ return variant === 'confirmation' ? '1.75rem' : '2rem';
103
+ }, _ref13 => {
104
+ let {
105
+ variant
106
+ } = _ref13;
107
+ return variant === 'confirmation' ? '1.75rem' : '2rem';
108
+ }, _ref14 => {
109
+ let {
110
+ themeColor
111
+ } = _ref14;
112
+ return themeColor;
113
+ }, _ref15 => {
114
+ let {
115
+ variant
116
+ } = _ref15;
117
+ return variant === 'confirmation' ? '2rem' : '2.5rem';
118
+ }, _ref16 => {
119
+ let {
120
+ variant
121
+ } = _ref16;
122
+ return variant === 'confirmation' ? '2rem' : '2.5rem';
123
+ });
124
+ const Title = _styledComponents.default.h2.withConfig({
125
+ displayName: "CustomCardTitle__Title"
126
+ })(["text-align:center;font-size:1.125rem;margin-bottom:", ";@media (min-width:640px){font-size:1.25rem;margin-bottom:", ";}"], _ref17 => {
127
+ let {
128
+ variant
129
+ } = _ref17;
130
+ return variant === 'confirmation' ? '0.25rem' : '0.5rem';
131
+ }, _ref18 => {
132
+ let {
133
+ variant
134
+ } = _ref18;
135
+ return variant === 'confirmation' ? '0.5rem' : '0.75rem';
136
+ });
137
+ const Description = _styledComponents.default.p.withConfig({
138
+ displayName: "CustomCardTitle__Description"
139
+ })(["text-align:center;font-size:", ";color:#6b7280;@media (min-width:640px){font-size:", ";}"], _ref19 => {
140
+ let {
141
+ variant
142
+ } = _ref19;
143
+ return variant === 'confirmation' ? '0.75rem' : '0.875rem';
144
+ }, _ref20 => {
145
+ let {
146
+ variant
147
+ } = _ref20;
148
+ return variant === 'confirmation' ? '0.875rem' : '1rem';
149
+ });
150
+ const BmCustomCardTitle = _ref21 => {
151
+ let {
152
+ icon: Icon,
153
+ themeColor = '#33B1BA',
154
+ title,
155
+ description,
156
+ variant = 'booking',
157
+ withStripe = false
158
+ } = _ref21;
159
+ const content = /*#__PURE__*/_react.default.createElement(CardContainer, {
160
+ variant: variant
161
+ }, /*#__PURE__*/_react.default.createElement(IconWrapper, {
162
+ themeColor: themeColor,
163
+ variant: variant
164
+ }, Icon && /*#__PURE__*/_react.default.createElement(Icon, null)), title && /*#__PURE__*/_react.default.createElement(Title, {
165
+ variant: variant
166
+ }, title), description && /*#__PURE__*/_react.default.createElement(Description, {
167
+ variant: variant
168
+ }, description));
169
+ return withStripe ? /*#__PURE__*/_react.default.createElement(BackgroundStripe, {
170
+ themeColor: themeColor,
171
+ variant: variant
172
+ }, content) : content;
173
+ };
174
+ var _default = exports.default = BmCustomCardTitle;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.Default = void 0;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _CalendarTodayOutlined = _interopRequireDefault(require("@mui/icons-material/CalendarTodayOutlined"));
9
+ var _Check = _interopRequireDefault(require("@mui/icons-material/Check"));
10
+ var _AccessTime = _interopRequireDefault(require("@mui/icons-material/AccessTime"));
11
+ var _Favorite = _interopRequireDefault(require("@mui/icons-material/Favorite"));
12
+ var _CustomCardTitle = _interopRequireDefault(require("./CustomCardTitle"));
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
+ // MUI icons
15
+
16
+ // Icon options mapped by name
17
+ const iconOptions = {
18
+ Calendar: _CalendarTodayOutlined.default,
19
+ Check: _Check.default,
20
+ Clock: _AccessTime.default,
21
+ Heart: _Favorite.default
22
+ };
23
+ const Template = args => {
24
+ var _Object$entries$find;
25
+ const iconName = (_Object$entries$find = Object.entries(iconOptions).find(_ref => {
26
+ let [, comp] = _ref;
27
+ return comp === args.icon;
28
+ })) === null || _Object$entries$find === void 0 ? void 0 : _Object$entries$find[0];
29
+ return /*#__PURE__*/_react.default.createElement("div", {
30
+ style: {
31
+ maxWidth: 500,
32
+ margin: '2rem auto'
33
+ }
34
+ }, /*#__PURE__*/_react.default.createElement(_CustomCardTitle.default, args), /*#__PURE__*/_react.default.createElement("div", {
35
+ style: {
36
+ marginTop: '2rem',
37
+ fontSize: '0.875rem'
38
+ }
39
+ }, /*#__PURE__*/_react.default.createElement("strong", null, "Example usage:"), /*#__PURE__*/_react.default.createElement("pre", {
40
+ style: {
41
+ background: '#f5f5f5',
42
+ padding: '1rem',
43
+ borderRadius: 8,
44
+ overflowX: 'auto'
45
+ }
46
+ }, "<BmCustomCardTitle\n icon={".concat(iconName, "}\n themeColor=\"").concat(args.themeColor, "\"\n title=\"").concat(args.title, "\"\n description=\"").concat(args.description, "\"\n variant=\"").concat(args.variant, "\"\n withStripe={").concat(args.withStripe, "}\n/>"))));
47
+ };
48
+ const Default = exports.Default = Template.bind({});
49
+ Default.args = {
50
+ icon: _CalendarTodayOutlined.default,
51
+ themeColor: '#33B1BA',
52
+ title: 'Book Your Medical Appointment',
53
+ description: 'Schedule a 30-minute consultation with our healthcare specialists',
54
+ variant: 'booking',
55
+ withStripe: true
56
+ };
57
+ Default.argTypes = {
58
+ icon: {
59
+ control: {
60
+ type: 'select',
61
+ labels: Object.keys(iconOptions)
62
+ },
63
+ options: Object.keys(iconOptions),
64
+ mapping: iconOptions
65
+ },
66
+ themeColor: {
67
+ control: 'color'
68
+ },
69
+ title: {
70
+ control: 'text'
71
+ },
72
+ description: {
73
+ control: 'text'
74
+ },
75
+ variant: {
76
+ control: {
77
+ type: 'radio'
78
+ },
79
+ options: ['booking', 'confirmation']
80
+ },
81
+ withStripe: {
82
+ control: {
83
+ type: 'boolean'
84
+ }
85
+ }
86
+ };
87
+ var _default = exports.default = {
88
+ title: 'Components/BmCustomCardTitle',
89
+ component: _CustomCardTitle.default,
90
+ argTypes: Default.argTypes
91
+ };
@@ -80,25 +80,35 @@ const RowContainer = _styledComponents.default.div.withConfig({
80
80
  })(["display:flex;justify-content:space-between;font-size:0.875rem;align-items:center;@media (max-width:42.8571rem){font-size:0.8rem;}"]);
81
81
  const Label = _styledComponents.default.span.withConfig({
82
82
  displayName: "InfoPanel__Label"
83
- })(["color:rgba(0,0,0,0.6);@media (max-width:42.8571rem){font-size:0.75rem;}"]);
83
+ })(["color:", ";@media (max-width:42.8571rem){font-size:0.75rem;}"], _ref6 => {
84
+ let {
85
+ labelTextColor
86
+ } = _ref6;
87
+ return hexToRgba(labelTextColor || '#000000', 0.6);
88
+ });
84
89
  const Value = _styledComponents.default.span.withConfig({
85
90
  displayName: "InfoPanel__Value"
86
- })(["font-weight:500;@media (max-width:42.8571rem){font-size:0.75rem;}"]);
91
+ })(["font-weight:500;color:", ";@media (max-width:42.8571rem){font-size:0.75rem;}"], _ref7 => {
92
+ let {
93
+ valueTextColor
94
+ } = _ref7;
95
+ return hexToRgba(valueTextColor || '#000000', 1);
96
+ });
87
97
  const Divider = _styledComponents.default.hr.withConfig({
88
98
  displayName: "InfoPanel__Divider"
89
- })(["border:none;border-top:", ";margin:1rem auto;max-width:97%;@media (max-width:42.8571rem){margin:0.75rem auto;max-width:97%;}"], _ref6 => {
99
+ })(["border:none;border-top:", ";margin:1rem auto;max-width:97%;@media (max-width:42.8571rem){margin:0.75rem auto;max-width:97%;}"], _ref8 => {
90
100
  let {
91
101
  showDivider,
92
102
  dividerColor = '#33b1ba',
93
103
  dividerType = 'dashed',
94
104
  dividerWitdh = '1px',
95
105
  dividerOpacity = '0.2'
96
- } = _ref6;
106
+ } = _ref8;
97
107
  if (showDivider) {
98
108
  return "".concat(dividerWitdh, " ").concat(dividerType, " ").concat(hexToRgba(dividerColor, dividerOpacity));
99
109
  }
100
110
  });
101
- const SectionSummary = _ref7 => {
111
+ const SectionSummary = _ref9 => {
102
112
  let {
103
113
  icon: Icon,
104
114
  title,
@@ -106,7 +116,7 @@ const SectionSummary = _ref7 => {
106
116
  textColor,
107
117
  subtitle,
108
118
  iconBackgroundColor
109
- } = _ref7;
119
+ } = _ref9;
110
120
  return /*#__PURE__*/_react.default.createElement(SectionSummaryContainer, null, Icon && /*#__PURE__*/_react.default.createElement(IconBox, {
111
121
  iconColor: iconColor,
112
122
  iconBackgroundColor: iconBackgroundColor
@@ -116,13 +126,13 @@ const SectionSummary = _ref7 => {
116
126
  textColor: textColor
117
127
  }, subtitle)));
118
128
  };
119
- const BmInfoPanel = _ref8 => {
129
+ const BmInfoPanel = _ref0 => {
120
130
  let {
121
131
  children
122
- } = _ref8;
132
+ } = _ref0;
123
133
  return /*#__PURE__*/_react.default.createElement(Panel, null, children);
124
134
  };
125
- const Section = _ref9 => {
135
+ const Section = _ref1 => {
126
136
  let {
127
137
  title,
128
138
  icon: Icon,
@@ -135,7 +145,7 @@ const Section = _ref9 => {
135
145
  dividerWitdh,
136
146
  dividerType,
137
147
  dividerOpacity
138
- } = _ref9;
148
+ } = _ref1;
139
149
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, showDivider && /*#__PURE__*/_react.default.createElement(Divider, {
140
150
  dividerColor: dividerColor,
141
151
  showDivider: showDivider,
@@ -149,12 +159,18 @@ const Section = _ref9 => {
149
159
  iconBackgroundColor: iconBackgroundColor
150
160
  }, /*#__PURE__*/_react.default.createElement(Icon, null)), /*#__PURE__*/_react.default.createElement(SectionTitle, null, title)), /*#__PURE__*/_react.default.createElement(SectionBody, null, children));
151
161
  };
152
- const Row = _ref0 => {
162
+ const Row = _ref10 => {
153
163
  let {
154
164
  label,
155
- value
156
- } = _ref0;
157
- return /*#__PURE__*/_react.default.createElement(RowContainer, null, /*#__PURE__*/_react.default.createElement(Label, null, label, ":"), /*#__PURE__*/_react.default.createElement(Value, null, value));
165
+ value,
166
+ labelTextColor,
167
+ valueTextColor
168
+ } = _ref10;
169
+ return /*#__PURE__*/_react.default.createElement(RowContainer, null, /*#__PURE__*/_react.default.createElement(Label, {
170
+ labelTextColor: labelTextColor
171
+ }, label, ":"), /*#__PURE__*/_react.default.createElement(Value, {
172
+ valueTextColor: valueTextColor
173
+ }, value));
158
174
  };
159
175
  BmInfoPanel.Section = Section;
160
176
  BmInfoPanel.Row = Row;
@@ -70,6 +70,12 @@ var _default = exports.default = {
70
70
  },
71
71
  options: ['dashed', 'solid'],
72
72
  defaultValue: 'dashed'
73
+ },
74
+ labelTextColor: {
75
+ control: 'color'
76
+ },
77
+ valueTextColor: {
78
+ control: 'color'
73
79
  }
74
80
  }
75
81
  };
@@ -84,7 +90,9 @@ const Template = _ref => {
84
90
  dividerColor,
85
91
  dividerOpacity,
86
92
  dividerType,
87
- dividerWidth
93
+ dividerWidth,
94
+ labelTextColor,
95
+ valueTextColor
88
96
  } = _ref;
89
97
  if (variant === 'summary') {
90
98
  return /*#__PURE__*/_react.default.createElement(_InfoPanel.default, {
@@ -126,6 +134,8 @@ const Template = _ref => {
126
134
  label: "Date",
127
135
  value: "Monday, June 24, 2025"
128
136
  }), /*#__PURE__*/_react.default.createElement(_InfoPanel.default.Row, {
137
+ labelTextColor: labelTextColor,
138
+ valueTextColor: valueTextColor,
129
139
  label: "Time",
130
140
  value: "09:00 AM"
131
141
  })), /*#__PURE__*/_react.default.createElement(_InfoPanel.default.Section, {
@@ -159,7 +169,9 @@ Default.args = {
159
169
  dividerColor: '#33b1ba',
160
170
  dividerType: 'dashed',
161
171
  dividerWidth: '1px',
162
- dividerOpacity: '0.2'
172
+ dividerOpacity: '0.2',
173
+ labelTextColor: '#e46a8e',
174
+ valueTextColor: '#235e92'
163
175
  };
164
176
  const ExampleSummary = () => {
165
177
  return /*#__PURE__*/_react.default.createElement(_InfoPanel.default, null, /*#__PURE__*/_react.default.createElement(_InfoPanel.default.Section, {
@@ -196,6 +208,8 @@ const ExampleDetails = () => {
196
208
  label: "Resource",
197
209
  value: formData.resourceName
198
210
  }), /*#__PURE__*/_react.default.createElement(_InfoPanel.default.Row, {
211
+ labelTextColor: "#e46a8e",
212
+ valueTextColor: "#235e92",
199
213
  label: "Duration",
200
214
  value: appointmentDetails.duration
201
215
  }), /*#__PURE__*/_react.default.createElement(_InfoPanel.default.Row, {
@@ -166,6 +166,12 @@ Object.defineProperty(exports, "BmCounter", {
166
166
  return _messageCounter.default;
167
167
  }
168
168
  });
169
+ Object.defineProperty(exports, "BmCustomCardTitle", {
170
+ enumerable: true,
171
+ get: function () {
172
+ return _CustomCardTitle.default;
173
+ }
174
+ });
169
175
  Object.defineProperty(exports, "BmEmojiIcon", {
170
176
  enumerable: true,
171
177
  get: function () {
@@ -465,5 +471,6 @@ var _LabelWithIcon = _interopRequireDefault(require("./LabelWithIcon/LabelWithIc
465
471
  var _Card = require("./Card_v2/Card");
466
472
  var _InfoPanel = _interopRequireDefault(require("./InfoPanel/InfoPanel"));
467
473
  var _BmSelector = _interopRequireDefault(require("./BmSelector/BmSelector"));
474
+ var _CustomCardTitle = _interopRequireDefault(require("./BmCustomCardTitle/CustomCardTitle"));
468
475
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
469
476
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beem-component",
3
- "version": "2.1.3",
3
+ "version": "2.1.5",
4
4
  "private": false,
5
5
  "main": "dist/components/index.js",
6
6
  "scripts": {
package/src/App.js CHANGED
@@ -7,6 +7,8 @@ import React, { useState } from 'react';
7
7
  // import CalendarTodayIcon from '@mui/icons-material/CalendarToday';
8
8
  import AccessTimeIcon from '@mui/icons-material/AccessTime';
9
9
  import PersonIcon from '@mui/icons-material/Person';
10
+ import CalendarTodayOutlinedIcon from '@mui/icons-material/CalendarTodayOutlined';
11
+ import CheckIcon from '@mui/icons-material/Check';
10
12
  // import { Tooltip } from '@mui/material';
11
13
  import PeopleIcon from '@mui/icons-material/People';
12
14
  // import BusinessIcon from '@mui/icons-material/Business';
@@ -33,6 +35,7 @@ import {
33
35
  BmButton,
34
36
  BmSelectionNotice,
35
37
  BmSelector,
38
+ BmCustomCardTitle,
36
39
  } from './lib/components';
37
40
  // import ProgressIndicator from './lib/components/newProgress';
38
41
 
@@ -1006,7 +1009,28 @@ const Chat = () => {
1006
1009
  return (
1007
1010
  <>
1008
1011
  <GlobalStyle />
1009
-
1012
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
1013
+ <div>
1014
+ <BmCustomCardTitle
1015
+ icon={CalendarTodayOutlinedIcon}
1016
+ themeColor="#33B1BA"
1017
+ title="Book Your Medical Appointment"
1018
+ description="Schedule a 30-minute consultation with our healthcare specialists"
1019
+ variant="booking"
1020
+ withStripe
1021
+ />
1022
+ </div>
1023
+ <div>
1024
+ <BmCustomCardTitle
1025
+ icon={CheckIcon}
1026
+ themeColor="#33B1BA"
1027
+ title="Appointment Confirmed!"
1028
+ description="Your booking has been successfully scheduled"
1029
+ variant="confirmation"
1030
+ withStripe
1031
+ />
1032
+ </div>
1033
+ </div>
1010
1034
  <div style={{ maxWidth: '600px', margin: '2rem auto' }}>
1011
1035
  <div style={{ padding: '2rem' }}>
1012
1036
  <h1>Progress Indicator Demo</h1>
@@ -0,0 +1,142 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ const hexToRgba = (hex, opacity = 0.6) => {
5
+ try {
6
+ const normalizedHex = hex?.replace('#', '');
7
+ if (
8
+ !normalizedHex ||
9
+ normalizedHex.length !== 6 ||
10
+ !/^[0-9a-fA-F]{6}$/.test(normalizedHex)
11
+ ) {
12
+ throw new Error('Invalid hex');
13
+ }
14
+
15
+ const r = parseInt(normalizedHex.slice(0, 2), 16);
16
+ const g = parseInt(normalizedHex.slice(2, 4), 16);
17
+ const b = parseInt(normalizedHex.slice(4, 6), 16);
18
+ return `rgba(${r}, ${g}, ${b}, ${opacity})`;
19
+ } catch (e) {
20
+ return `rgba(0, 0, 0, ${opacity})`;
21
+ }
22
+ };
23
+
24
+ const BackgroundStripe = styled.div`
25
+ background-color: ${({ themeColor }) => hexToRgba(themeColor, 0.1)};
26
+ padding-top: ${({ variant }) =>
27
+ variant === 'confirmation' ? '1rem' : '1.5rem'};
28
+ padding-bottom: ${({ variant }) =>
29
+ variant === 'confirmation' ? '1rem' : '2rem'};
30
+ padding-left: 1rem;
31
+ padding-right: 1rem;
32
+
33
+ @media (min-width: 640px) {
34
+ padding-top: ${({ variant }) =>
35
+ variant === 'confirmation' ? '1.5rem' : '2rem'};
36
+ padding-bottom: ${({ variant }) =>
37
+ variant === 'confirmation' ? '1.5rem' : '2.5rem'};
38
+ padding-left: 1.5rem;
39
+ padding-right: 1.5rem;
40
+ }
41
+ `;
42
+
43
+ const CardContainer = styled.div`
44
+ background-color: ${hexToRgba('#ffffff', 0.7)};
45
+ padding: 1rem;
46
+ border-radius: 0.75rem;
47
+
48
+ @media (min-width: 640px) {
49
+ padding: 1.5rem;
50
+ }
51
+ `;
52
+
53
+ const IconWrapper = styled.div`
54
+ background-color: ${({ themeColor }) => hexToRgba(themeColor, 0.1)};
55
+ border: 2px solid ${({ themeColor }) => themeColor};
56
+ height: ${({ variant }) => (variant === 'confirmation' ? '3.5rem' : '4rem')};
57
+ width: ${({ variant }) => (variant === 'confirmation' ? '3.5rem' : '4rem')};
58
+ border-radius: 9999px;
59
+ display: flex;
60
+ align-items: center;
61
+ justify-content: center;
62
+ margin: 0 auto
63
+ ${({ variant }) => (variant === 'confirmation' ? '0.75rem' : '1rem')};
64
+
65
+ @media (min-width: 640px) {
66
+ height: ${({ variant }) => (variant === 'confirmation' ? '4rem' : '5rem')};
67
+ width: ${({ variant }) => (variant === 'confirmation' ? '4rem' : '5rem')};
68
+ margin-bottom: ${({ variant }) =>
69
+ variant === 'confirmation' ? '1rem' : '1.25rem'};
70
+ }
71
+
72
+ svg {
73
+ height: ${({ variant }) =>
74
+ variant === 'confirmation' ? '1.75rem' : '2rem'};
75
+ width: ${({ variant }) =>
76
+ variant === 'confirmation' ? '1.75rem' : '2rem'};
77
+ color: ${({ themeColor }) => themeColor};
78
+
79
+ @media (min-width: 640px) {
80
+ height: ${({ variant }) =>
81
+ variant === 'confirmation' ? '2rem' : '2.5rem'};
82
+ width: ${({ variant }) =>
83
+ variant === 'confirmation' ? '2rem' : '2.5rem'};
84
+ }
85
+ }
86
+ `;
87
+
88
+ const Title = styled.h2`
89
+ text-align: center;
90
+ font-size: 1.125rem;
91
+ margin-bottom: ${({ variant }) =>
92
+ variant === 'confirmation' ? '0.25rem' : '0.5rem'};
93
+
94
+ @media (min-width: 640px) {
95
+ font-size: 1.25rem;
96
+ margin-bottom: ${({ variant }) =>
97
+ variant === 'confirmation' ? '0.5rem' : '0.75rem'};
98
+ }
99
+ `;
100
+
101
+ const Description = styled.p`
102
+ text-align: center;
103
+ font-size: ${({ variant }) =>
104
+ variant === 'confirmation' ? '0.75rem' : '0.875rem'};
105
+ color: #6b7280;
106
+
107
+ @media (min-width: 640px) {
108
+ font-size: ${({ variant }) =>
109
+ variant === 'confirmation' ? '0.875rem' : '1rem'};
110
+ }
111
+ `;
112
+
113
+ const BmCustomCardTitle = ({
114
+ icon: Icon,
115
+ themeColor = '#33B1BA',
116
+ title,
117
+ description,
118
+ variant = 'booking',
119
+ withStripe = false,
120
+ }) => {
121
+ const content = (
122
+ <CardContainer variant={variant}>
123
+ <IconWrapper themeColor={themeColor} variant={variant}>
124
+ {Icon && <Icon />}
125
+ </IconWrapper>
126
+ {title && <Title variant={variant}>{title}</Title>}
127
+ {description && (
128
+ <Description variant={variant}>{description}</Description>
129
+ )}
130
+ </CardContainer>
131
+ );
132
+
133
+ return withStripe ? (
134
+ <BackgroundStripe themeColor={themeColor} variant={variant}>
135
+ {content}
136
+ </BackgroundStripe>
137
+ ) : (
138
+ content
139
+ );
140
+ };
141
+
142
+ export default BmCustomCardTitle;
@@ -0,0 +1,96 @@
1
+ import React from 'react';
2
+
3
+ // MUI icons
4
+ import CalendarTodayOutlinedIcon from '@mui/icons-material/CalendarTodayOutlined';
5
+ import CheckIcon from '@mui/icons-material/Check';
6
+ import AccessTimeIcon from '@mui/icons-material/AccessTime';
7
+ import FavoriteIcon from '@mui/icons-material/Favorite';
8
+ import BmCustomCardTitle from './CustomCardTitle';
9
+
10
+ // Icon options mapped by name
11
+ const iconOptions = {
12
+ Calendar: CalendarTodayOutlinedIcon,
13
+ Check: CheckIcon,
14
+ Clock: AccessTimeIcon,
15
+ Heart: FavoriteIcon,
16
+ };
17
+
18
+ const Template = (args) => {
19
+ const iconName = Object.entries(iconOptions).find(
20
+ ([, comp]) => comp === args.icon
21
+ )?.[0];
22
+
23
+ return (
24
+ <div style={{ maxWidth: 500, margin: '2rem auto' }}>
25
+ <BmCustomCardTitle {...args} />
26
+ <div style={{ marginTop: '2rem', fontSize: '0.875rem' }}>
27
+ <strong>Example usage:</strong>
28
+ <pre
29
+ style={{
30
+ background: '#f5f5f5',
31
+ padding: '1rem',
32
+ borderRadius: 8,
33
+ overflowX: 'auto',
34
+ }}
35
+ >
36
+ {`<BmCustomCardTitle
37
+ icon={${iconName}}
38
+ themeColor="${args.themeColor}"
39
+ title="${args.title}"
40
+ description="${args.description}"
41
+ variant="${args.variant}"
42
+ withStripe={${args.withStripe}}
43
+ />`}
44
+ </pre>
45
+ </div>
46
+ </div>
47
+ );
48
+ };
49
+
50
+ export const Default = Template.bind({});
51
+ Default.args = {
52
+ icon: CalendarTodayOutlinedIcon,
53
+ themeColor: '#33B1BA',
54
+ title: 'Book Your Medical Appointment',
55
+ description:
56
+ 'Schedule a 30-minute consultation with our healthcare specialists',
57
+ variant: 'booking',
58
+ withStripe: true,
59
+ };
60
+
61
+ Default.argTypes = {
62
+ icon: {
63
+ control: {
64
+ type: 'select',
65
+ labels: Object.keys(iconOptions),
66
+ },
67
+ options: Object.keys(iconOptions),
68
+ mapping: iconOptions,
69
+ },
70
+ themeColor: {
71
+ control: 'color',
72
+ },
73
+ title: {
74
+ control: 'text',
75
+ },
76
+ description: {
77
+ control: 'text',
78
+ },
79
+ variant: {
80
+ control: {
81
+ type: 'radio',
82
+ },
83
+ options: ['booking', 'confirmation'],
84
+ },
85
+ withStripe: {
86
+ control: {
87
+ type: 'boolean',
88
+ },
89
+ },
90
+ };
91
+
92
+ export default {
93
+ title: 'Components/BmCustomCardTitle',
94
+ component: BmCustomCardTitle,
95
+ argTypes: Default.argTypes,
96
+ };
@@ -134,8 +134,7 @@ const RowContainer = styled.div`
134
134
  `;
135
135
 
136
136
  const Label = styled.span`
137
- color: rgba(0, 0, 0, 0.6);
138
-
137
+ color: ${({ labelTextColor }) => hexToRgba(labelTextColor || '#000000', 0.6)};
139
138
  @media (max-width: 42.8571rem) {
140
139
  font-size: 0.75rem;
141
140
  }
@@ -143,7 +142,7 @@ const Label = styled.span`
143
142
 
144
143
  const Value = styled.span`
145
144
  font-weight: 500;
146
-
145
+ color: ${({ valueTextColor }) => hexToRgba(valueTextColor || '#000000', 1)};
147
146
  @media (max-width: 42.8571rem) {
148
147
  font-size: 0.75rem;
149
148
  }
@@ -232,10 +231,10 @@ const Section = ({
232
231
  </>
233
232
  );
234
233
 
235
- const Row = ({ label, value }) => (
234
+ const Row = ({ label, value, labelTextColor, valueTextColor }) => (
236
235
  <RowContainer>
237
- <Label>{label}:</Label>
238
- <Value>{value}</Value>
236
+ <Label labelTextColor={labelTextColor}>{label}:</Label>
237
+ <Value valueTextColor={valueTextColor}>{value}</Value>
239
238
  </RowContainer>
240
239
  );
241
240
 
@@ -39,6 +39,8 @@ export default {
39
39
  options: ['dashed', 'solid'],
40
40
  defaultValue: 'dashed',
41
41
  },
42
+ labelTextColor: { control: 'color' },
43
+ valueTextColor: { control: 'color' },
42
44
  },
43
45
  };
44
46
 
@@ -53,6 +55,8 @@ const Template = ({
53
55
  dividerOpacity,
54
56
  dividerType,
55
57
  dividerWidth,
58
+ labelTextColor,
59
+ valueTextColor,
56
60
  }) => {
57
61
  if (variant === 'summary') {
58
62
  return (
@@ -90,7 +94,12 @@ const Template = ({
90
94
  <BmInfoPanel.Row label="Resource" value="Dr. Smith" />
91
95
  <BmInfoPanel.Row label="Duration" value="30 minutes" />
92
96
  <BmInfoPanel.Row label="Date" value="Monday, June 24, 2025" />
93
- <BmInfoPanel.Row label="Time" value="09:00 AM" />
97
+ <BmInfoPanel.Row
98
+ labelTextColor={labelTextColor}
99
+ valueTextColor={valueTextColor}
100
+ label="Time"
101
+ value="09:00 AM"
102
+ />
94
103
  </BmInfoPanel.Section>
95
104
 
96
105
  <BmInfoPanel.Section
@@ -123,6 +132,8 @@ Default.args = {
123
132
  dividerType: 'dashed',
124
133
  dividerWidth: '1px',
125
134
  dividerOpacity: '0.2',
135
+ labelTextColor: '#e46a8e',
136
+ valueTextColor: '#235e92',
126
137
  };
127
138
 
128
139
  export const ExampleSummary = () => {
@@ -162,7 +173,12 @@ export const ExampleDetails = () => {
162
173
  <BmInfoPanel.Row label="Type" value={appointmentDetails.title} />
163
174
  <BmInfoPanel.Row label="Department" value={formData.departmentName} />
164
175
  <BmInfoPanel.Row label="Resource" value={formData.resourceName} />
165
- <BmInfoPanel.Row label="Duration" value={appointmentDetails.duration} />
176
+ <BmInfoPanel.Row
177
+ labelTextColor="#e46a8e"
178
+ valueTextColor="#235e92"
179
+ label="Duration"
180
+ value={appointmentDetails.duration}
181
+ />
166
182
  <BmInfoPanel.Row label="Date" value={formData.date.toDateString()} />
167
183
  <BmInfoPanel.Row
168
184
  label="Time"
@@ -81,6 +81,7 @@ import BmLabelWithIcon from './LabelWithIcon/LabelWithIcon';
81
81
  import { BmCardv2 } from './Card_v2/Card';
82
82
  import BmInfoPanel from './InfoPanel/InfoPanel';
83
83
  import BmSelector from './BmSelector/BmSelector';
84
+ import BmCustomCardTitle from './BmCustomCardTitle/CustomCardTitle';
84
85
 
85
86
  export {
86
87
  BmAccordion,
@@ -159,4 +160,5 @@ export {
159
160
  BmInfoPanel,
160
161
  BmProgressIndicator,
161
162
  BmSelector,
163
+ BmCustomCardTitle,
162
164
  };