beem-component 2.1.9 → 2.1.11

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.
@@ -147,6 +147,9 @@ const Description = _styledComponents.default.p.withConfig({
147
147
  } = _ref20;
148
148
  return variant === 'confirmation' ? '0.875rem' : '1rem';
149
149
  });
150
+ const ImageWrapper = _styledComponents.default.div.withConfig({
151
+ displayName: "CustomCardTitle__ImageWrapper"
152
+ })(["width:100%;aspect-ratio:1 / 1;overflow:hidden;border-radius:0.75rem;margin-top:1rem;img{width:100%;height:100%;object-fit:cover;display:block;}"]);
150
153
  const BmCustomCardTitle = _ref21 => {
151
154
  let {
152
155
  icon: Icon,
@@ -154,7 +157,8 @@ const BmCustomCardTitle = _ref21 => {
154
157
  title,
155
158
  description,
156
159
  variant = 'booking',
157
- withStripe = false
160
+ withStripe = false,
161
+ imageSrc
158
162
  } = _ref21;
159
163
  const content = /*#__PURE__*/_react.default.createElement(CardContainer, {
160
164
  variant: variant
@@ -165,7 +169,10 @@ const BmCustomCardTitle = _ref21 => {
165
169
  variant: variant
166
170
  }, title), description && /*#__PURE__*/_react.default.createElement(Description, {
167
171
  variant: variant
168
- }, description));
172
+ }, description), imageSrc && /*#__PURE__*/_react.default.createElement(ImageWrapper, null, /*#__PURE__*/_react.default.createElement("img", {
173
+ src: imageSrc,
174
+ alt: title || 'Card image'
175
+ })));
169
176
  return withStripe ? /*#__PURE__*/_react.default.createElement(BackgroundStripe, {
170
177
  themeColor: themeColor,
171
178
  variant: variant
@@ -20,6 +20,7 @@ const iconOptions = {
20
20
  Clock: _AccessTime.default,
21
21
  Heart: _Favorite.default
22
22
  };
23
+ const imgs = 'https://i.imgur.com/HiAzUHl.jpeg';
23
24
  const Template = args => {
24
25
  return /*#__PURE__*/_react.default.createElement("div", {
25
26
  style: {
@@ -35,7 +36,8 @@ Default.args = {
35
36
  title: 'Book Your Medical Appointment',
36
37
  description: 'Schedule a 30-minute consultation with our healthcare specialists',
37
38
  variant: 'booking',
38
- withStripe: true
39
+ withStripe: true,
40
+ imageSrc: imgs
39
41
  };
40
42
  Default.argTypes = {
41
43
  icon: {
@@ -65,6 +67,10 @@ Default.argTypes = {
65
67
  control: {
66
68
  type: 'boolean'
67
69
  }
70
+ },
71
+ imageSrc: {
72
+ control: 'text',
73
+ description: 'URL of the image to display in the card'
68
74
  }
69
75
  };
70
76
  var _default = exports.default = {
@@ -73,13 +79,14 @@ var _default = exports.default = {
73
79
  argTypes: Default.argTypes
74
80
  };
75
81
  const Example = () => {
76
- /*#__PURE__*/_react.default.createElement(_CustomCardTitle.default, {
82
+ return /*#__PURE__*/_react.default.createElement(_CustomCardTitle.default, {
77
83
  icon: _CalendarTodayOutlined.default,
78
84
  themeColor: "#33B1BA",
79
85
  title: "Book Your Medical Appointment",
80
86
  description: "Schedule a 30-minute consultation with our healthcare specialists",
81
87
  variant: "booking",
82
- withStripe: true
88
+ withStripe: true,
89
+ imageSrc: imgs
83
90
  });
84
91
  };
85
92
  exports.Example = Example;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ 'use client';
3
+
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.TabPanel = TabPanel;
8
+ exports.Tabs = Tabs;
9
+ var _react = _interopRequireWildcard(require("react"));
10
+ var _styledComponents = _interopRequireWildcard(require("styled-components"));
11
+ 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); }
12
+ // Utility
13
+ const cn = function () {
14
+ for (var _len = arguments.length, classes = new Array(_len), _key = 0; _key < _len; _key++) {
15
+ classes[_key] = arguments[_key];
16
+ }
17
+ return classes.filter(Boolean).join(' ');
18
+ };
19
+
20
+ // Styled components
21
+
22
+ const TabsContainer = _styledComponents.default.div.withConfig({
23
+ displayName: "BmTabV2__TabsContainer"
24
+ })(["display:flex;flex-direction:column;gap:0.5rem;@media (max-width:640px){gap:0.25rem;}"]);
25
+ const TabsList = _styledComponents.default.div.withConfig({
26
+ displayName: "BmTabV2__TabsList"
27
+ })(["display:flex;flex-wrap:nowrap;background:#f5f5f5;overflow-x:auto;padding:3px;border-radius:8px;&::-webkit-scrollbar{display:none;}"]);
28
+ const TabButton = _styledComponents.default.button.withConfig({
29
+ displayName: "BmTabV2__TabButton"
30
+ })(["flex:1 0 auto;display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:0.5rem 0.75rem;font-size:0.875rem;font-weight:500;white-space:nowrap;border:1px solid transparent;border-radius:8px;background:transparent;color:#333;cursor:pointer;transition:all 0.2s;", " &:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;}&:disabled{pointer-events:none;opacity:0.5;}svg{flex-shrink:0;pointer-events:none;width:1rem;height:1rem;}"], _ref => {
31
+ let {
32
+ active
33
+ } = _ref;
34
+ return active && (0, _styledComponents.css)(["background:#ffffff;color:#111111;border-color:#ddd;"]);
35
+ });
36
+ const TabContent = _styledComponents.default.div.withConfig({
37
+ displayName: "BmTabV2__TabContent"
38
+ })(["flex:1;padding:0.5rem 0;"]);
39
+
40
+ // Main Tabs component
41
+
42
+ // eslint-disable-next-line func-style
43
+ function Tabs(_ref2) {
44
+ let {
45
+ defaultValue = 0,
46
+ children,
47
+ className
48
+ } = _ref2;
49
+ const [activeIndex, setActiveIndex] = (0, _react.useState)(defaultValue);
50
+
51
+ // Get all children that are type of TabPanel (so we can match titles & content)
52
+ const tabPanels = _react.default.Children.toArray(children).filter(child => child.type.displayName === 'TabPanel');
53
+ return /*#__PURE__*/_react.default.createElement(TabsContainer, {
54
+ className: cn(className)
55
+ }, /*#__PURE__*/_react.default.createElement(TabsList, null, tabPanels.map((panel, index) => /*#__PURE__*/_react.default.createElement(TabButton
56
+ // eslint-disable-next-line react/no-array-index-key
57
+ , {
58
+ key: index,
59
+ active: activeIndex === index,
60
+ onClick: () => setActiveIndex(index)
61
+ }, panel.props.title))), /*#__PURE__*/_react.default.createElement(TabContent, null, tabPanels[activeIndex] && tabPanels[activeIndex].props.children));
62
+ }
63
+
64
+ // Individual Tab panel component
65
+ // eslint-disable-next-line func-style
66
+ function TabPanel(_ref3) {
67
+ let {
68
+ children
69
+ } = _ref3;
70
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, children);
71
+ }
72
+ TabPanel.displayName = 'TabPanel';
@@ -92,7 +92,7 @@ const BmDepartmentCard = _ref6 => {
92
92
  onClick: onDelete
93
93
  }, DeleteIcon && /*#__PURE__*/_react.default.createElement(DeleteIcon, {
94
94
  fontSize: "small"
95
- })))), /*#__PURE__*/_react.default.createElement(CardDescription, null, description)), /*#__PURE__*/_react.default.createElement(Content, null, resourcesCount && /*#__PURE__*/_react.default.createElement(ResourceText, null, resourcesCount, " Resources"), /*#__PURE__*/_react.default.createElement(StatusRow, null, /*#__PURE__*/_react.default.createElement(StatusDot, {
95
+ })))), /*#__PURE__*/_react.default.createElement(CardDescription, null, description)), /*#__PURE__*/_react.default.createElement(Content, null, /*#__PURE__*/_react.default.createElement(ResourceText, null, resourcesCount, " Resources"), /*#__PURE__*/_react.default.createElement(StatusRow, null, /*#__PURE__*/_react.default.createElement(StatusDot, {
96
96
  isActive: isActive
97
97
  }), /*#__PURE__*/_react.default.createElement(StatusText, null, isActive ? 'Active' : 'Inactive'))));
98
98
  };
@@ -63,19 +63,19 @@ const IconButton = _styledComponents.default.button.withConfig({
63
63
  });
64
64
  const Content = _styledComponents.default.div.withConfig({
65
65
  displayName: "ResourceCard__Content"
66
- })(["padding:0 1rem 0.5rem 1rem;display:flex;flex-direction:column;gap:0.5rem;font-size:0.875rem;"]);
66
+ })(["margin-top:1rem;padding:0 1rem 0.5rem 1rem;display:flex;flex-direction:column;gap:0.5rem;font-size:0.875rem;"]);
67
67
  const InfoRow = _styledComponents.default.div.withConfig({
68
68
  displayName: "ResourceCard__InfoRow"
69
69
  })(["display:flex;flex-wrap:wrap;gap:0.25rem;"]);
70
70
  const Label = _styledComponents.default.span.withConfig({
71
71
  displayName: "ResourceCard__Label"
72
- })(["color:#6b7280;"]);
72
+ })(["color:#6b7280;font-size:0.875rem;"]);
73
73
  const Value = _styledComponents.default.span.withConfig({
74
74
  displayName: "ResourceCard__Value"
75
- })(["color:#374151;"]);
75
+ })(["color:#374151;font-size:0.875rem;"]);
76
76
  const Footer = _styledComponents.default.div.withConfig({
77
77
  displayName: "ResourceCard__Footer"
78
- })(["display:flex;justify-content:flex-end;align-items:center;padding:0 1rem 0.75rem 1rem;"]);
78
+ })(["display:flex;justify-content:flex-end;align-items:center;margin-top:1rem;padding:0 1rem 0.75rem 1rem;"]);
79
79
  const StatusDot = _styledComponents.default.span.withConfig({
80
80
  displayName: "ResourceCard__StatusDot"
81
81
  })(["flex-shrink:0;width:0.5rem;height:0.5rem;margin-right:0.5rem;border-radius:9999px;background-color:", ";"], _ref6 => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beem-component",
3
- "version": "2.1.9",
3
+ "version": "2.1.11",
4
4
  "private": false,
5
5
  "main": "dist/components/index.js",
6
6
  "scripts": {
package/src/App.js CHANGED
@@ -43,6 +43,7 @@ import {
43
43
  BmResourceCard,
44
44
  } from './lib/components';
45
45
  import AlertBox from './lib/components/Alert/Alert';
46
+ import { TabPanel, Tabs } from './lib/components/BmTabv2/BmTabV2.';
46
47
  // import ProgressIndicator from './lib/components/newProgress';
47
48
 
48
49
  // const datsa = JSON.stringify({
@@ -1012,10 +1013,22 @@ const Chat = () => {
1012
1013
 
1013
1014
  const [selectedSlotId, setSelectedSlotId] = useState(null);
1014
1015
  console.log({ selectedSlotId });
1016
+ const imgs = 'https://i.imgur.com/HiAzUHl.jpeg';
1015
1017
  return (
1016
1018
  <>
1017
1019
  <GlobalStyle />
1018
1020
  <div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
1021
+ <Tabs defaultValue={0}>
1022
+ <TabPanel title="Overview">
1023
+ <p>This is the Overview content.</p>
1024
+ </TabPanel>
1025
+ <TabPanel title="Details">
1026
+ <p>This is the Details content.</p>
1027
+ </TabPanel>
1028
+ <TabPanel title="Settings">
1029
+ <p>This is the Settings content.</p>
1030
+ </TabPanel>
1031
+ </Tabs>
1019
1032
  <div style={{ width: '100%', maxWidth: '900px', margin: '2rem auto' }}>
1020
1033
  <div style={{ maxWidth: 400, margin: '2rem auto' }}>
1021
1034
  <BmDepartmentCard
@@ -1023,7 +1036,7 @@ const Chat = () => {
1023
1036
  isActive="true"
1024
1037
  name="Radiology Department"
1025
1038
  description="Handles imaging and diagnostic scans"
1026
- // resourcesCount={8}
1039
+ resourcesCount={0}
1027
1040
  onEdit={() => alert('Edit department')}
1028
1041
  onDelete={() => alert('Delete department')}
1029
1042
  EditIcon={EditIcon}
@@ -1086,6 +1099,7 @@ const Chat = () => {
1086
1099
  description="Schedule a 30-minute consultation with our healThcare specialists"
1087
1100
  variant="booking"
1088
1101
  withStripe
1102
+ imageSrc={imgs}
1089
1103
  />
1090
1104
  </div>
1091
1105
  <div>
@@ -110,6 +110,20 @@ const Description = styled.p`
110
110
  }
111
111
  `;
112
112
 
113
+ const ImageWrapper = styled.div`
114
+ width: 100%;
115
+ aspect-ratio: 1 / 1;
116
+ overflow: hidden;
117
+ border-radius: 0.75rem;
118
+ margin-top: 1rem;
119
+
120
+ img {
121
+ width: 100%;
122
+ height: 100%;
123
+ object-fit: cover;
124
+ display: block;
125
+ }
126
+ `;
113
127
  const BmCustomCardTitle = ({
114
128
  icon: Icon,
115
129
  themeColor = '#33B1BA',
@@ -117,6 +131,7 @@ const BmCustomCardTitle = ({
117
131
  description,
118
132
  variant = 'booking',
119
133
  withStripe = false,
134
+ imageSrc,
120
135
  }) => {
121
136
  const content = (
122
137
  <CardContainer variant={variant}>
@@ -127,6 +142,11 @@ const BmCustomCardTitle = ({
127
142
  {description && (
128
143
  <Description variant={variant}>{description}</Description>
129
144
  )}
145
+ {imageSrc && (
146
+ <ImageWrapper>
147
+ <img src={imageSrc} alt={title || 'Card image'} />
148
+ </ImageWrapper>
149
+ )}
130
150
  </CardContainer>
131
151
  );
132
152
 
@@ -15,6 +15,7 @@ const iconOptions = {
15
15
  Heart: FavoriteIcon,
16
16
  };
17
17
 
18
+ const imgs = 'https://i.imgur.com/HiAzUHl.jpeg';
18
19
  const Template = (args) => {
19
20
  return (
20
21
  <div style={{ maxWidth: 500, margin: '2rem auto' }}>
@@ -32,6 +33,7 @@ Default.args = {
32
33
  'Schedule a 30-minute consultation with our healthcare specialists',
33
34
  variant: 'booking',
34
35
  withStripe: true,
36
+ imageSrc: imgs,
35
37
  };
36
38
 
37
39
  Default.argTypes = {
@@ -63,6 +65,10 @@ Default.argTypes = {
63
65
  type: 'boolean',
64
66
  },
65
67
  },
68
+ imageSrc: {
69
+ control: 'text',
70
+ description: 'URL of the image to display in the card',
71
+ },
66
72
  };
67
73
 
68
74
  export default {
@@ -72,12 +78,15 @@ export default {
72
78
  };
73
79
 
74
80
  export const Example = () => {
75
- <BmCustomCardTitle
76
- icon={CalendarTodayOutlinedIcon}
77
- themeColor="#33B1BA"
78
- title="Book Your Medical Appointment"
79
- description="Schedule a 30-minute consultation with our healthcare specialists"
80
- variant="booking"
81
- withStripe
82
- />;
81
+ return (
82
+ <BmCustomCardTitle
83
+ icon={CalendarTodayOutlinedIcon}
84
+ themeColor="#33B1BA"
85
+ title="Book Your Medical Appointment"
86
+ description="Schedule a 30-minute consultation with our healthcare specialists"
87
+ variant="booking"
88
+ withStripe
89
+ imageSrc={imgs}
90
+ />
91
+ );
83
92
  };
@@ -0,0 +1,122 @@
1
+ 'use client';
2
+
3
+ import React, { useState } from 'react';
4
+ import styled, { css } from 'styled-components';
5
+
6
+ // Utility
7
+ const cn = (...classes) => classes.filter(Boolean).join(' ');
8
+
9
+ // Styled components
10
+
11
+ const TabsContainer = styled.div`
12
+ display: flex;
13
+ flex-direction: column;
14
+ gap: 0.5rem;
15
+
16
+ @media (max-width: 640px) {
17
+ gap: 0.25rem;
18
+ }
19
+ `;
20
+
21
+ const TabsList = styled.div`
22
+ display: flex;
23
+ flex-wrap: nowrap;
24
+ background: #f5f5f5;
25
+ overflow-x: auto;
26
+ padding: 3px;
27
+ border-radius: 8px;
28
+
29
+ &::-webkit-scrollbar {
30
+ display: none;
31
+ }
32
+ `;
33
+
34
+ const TabButton = styled.button`
35
+ flex: 1 0 auto;
36
+ display: inline-flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ gap: 6px;
40
+ padding: 0.5rem 0.75rem;
41
+ font-size: 0.875rem;
42
+ font-weight: 500;
43
+ white-space: nowrap;
44
+ border: 1px solid transparent;
45
+ border-radius: 8px;
46
+ background: transparent;
47
+ color: #333;
48
+ cursor: pointer;
49
+ transition: all 0.2s;
50
+
51
+ ${({ active }) =>
52
+ active &&
53
+ css`
54
+ background: #ffffff;
55
+ color: #111111;
56
+ border-color: #ddd;
57
+ `}
58
+
59
+ &:focus-visible {
60
+ outline: 2px solid #3b82f6;
61
+ outline-offset: 2px;
62
+ }
63
+
64
+ &:disabled {
65
+ pointer-events: none;
66
+ opacity: 0.5;
67
+ }
68
+
69
+ svg {
70
+ flex-shrink: 0;
71
+ pointer-events: none;
72
+ width: 1rem;
73
+ height: 1rem;
74
+ }
75
+ `;
76
+
77
+ const TabContent = styled.div`
78
+ flex: 1;
79
+ padding: 0.5rem 0;
80
+ `;
81
+
82
+ // Main Tabs component
83
+
84
+ // eslint-disable-next-line func-style
85
+ function Tabs({ defaultValue = 0, children, className }) {
86
+ const [activeIndex, setActiveIndex] = useState(defaultValue);
87
+
88
+ // Get all children that are type of TabPanel (so we can match titles & content)
89
+ const tabPanels = React.Children.toArray(children).filter(
90
+ (child) => child.type.displayName === 'TabPanel'
91
+ );
92
+
93
+ return (
94
+ <TabsContainer className={cn(className)}>
95
+ <TabsList>
96
+ {tabPanels.map((panel, index) => (
97
+ <TabButton
98
+ // eslint-disable-next-line react/no-array-index-key
99
+ key={index}
100
+ active={activeIndex === index}
101
+ onClick={() => setActiveIndex(index)}
102
+ >
103
+ {panel.props.title}
104
+ </TabButton>
105
+ ))}
106
+ </TabsList>
107
+ <TabContent>
108
+ {tabPanels[activeIndex] && tabPanels[activeIndex].props.children}
109
+ </TabContent>
110
+ </TabsContainer>
111
+ );
112
+ }
113
+
114
+ // Individual Tab panel component
115
+ // eslint-disable-next-line func-style
116
+ function TabPanel({ children }) {
117
+ return <>{children}</>;
118
+ }
119
+
120
+ TabPanel.displayName = 'TabPanel';
121
+
122
+ export { Tabs, TabPanel };
@@ -116,9 +116,8 @@ const BmDepartmentCard = ({
116
116
  <CardDescription>{description}</CardDescription>
117
117
  </Header>
118
118
  <Content>
119
- {resourcesCount && (
120
- <ResourceText>{resourcesCount} Resources</ResourceText>
121
- )}
119
+ <ResourceText>{resourcesCount} Resources</ResourceText>
120
+
122
121
  <StatusRow>
123
122
  <StatusDot isActive={isActive} />
124
123
  <StatusText>{isActive ? 'Active' : 'Inactive'}</StatusText>
@@ -73,6 +73,7 @@ const IconButton = styled.button`
73
73
  `;
74
74
 
75
75
  const Content = styled.div`
76
+ margin-top: 1rem;
76
77
  padding: 0 1rem 0.5rem 1rem;
77
78
  display: flex;
78
79
  flex-direction: column;
@@ -88,16 +89,19 @@ const InfoRow = styled.div`
88
89
 
89
90
  const Label = styled.span`
90
91
  color: #6b7280;
92
+ font-size: 0.875rem;
91
93
  `;
92
94
 
93
95
  const Value = styled.span`
94
96
  color: #374151;
97
+ font-size: 0.875rem;
95
98
  `;
96
99
 
97
100
  const Footer = styled.div`
98
101
  display: flex;
99
102
  justify-content: flex-end;
100
103
  align-items: center;
104
+ margin-top: 1rem;
101
105
  padding: 0 1rem 0.75rem 1rem;
102
106
  `;
103
107