beem-component 2.1.11 → 2.1.13

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,51 @@
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 = _interopRequireWildcard(require("styled-components"));
9
+ 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); }
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ const TabsContainer = _styledComponents.default.div.withConfig({
12
+ displayName: "BmTabv2__TabsContainer"
13
+ })(["width:100%;"]);
14
+ const TabsHeader = _styledComponents.default.div.withConfig({
15
+ displayName: "BmTabv2__TabsHeader"
16
+ })(["display:flex;justify-content:flex-start;align-items:center;margin-bottom:14px;padding:0 14px;border-radius:var(--radius-lg,12px);flex-wrap:wrap;"]);
17
+ const TabsList = _styledComponents.default.div.withConfig({
18
+ displayName: "BmTabv2__TabsList"
19
+ })(["width:100%;display:inline-flex;background-color:var(--color-muted,#f2f2f2);color:var(--color-muted-foreground,#666);align-items:center;justify-content:center;border-radius:var(--radius-lg,12px);padding:4px 4px;"]);
20
+ const TabsTriggerButton = _styledComponents.default.button.withConfig({
21
+ displayName: "BmTabv2__TabsTriggerButton"
22
+ })(["display:inline-flex;flex:1;align-items:center;justify-content:center;gap:6px;border:1px solid transparent;border-radius:var(--radius-lg,12px);padding:6px 12px;font-size:14px;font-weight:500;white-space:nowrap;transition:color 0.2s,box-shadow 0.2s,background-color 0.2s;cursor:pointer;", " &:focus-visible{outline:none;border-color:var(--color-ring,#2684ff);box-shadow:0 0 0 3px rgba(38,132,255,0.3);}&:disabled{pointer-events:none;opacity:0.5;}svg{flex-shrink:0;pointer-events:none;width:16px;height:16px;}"], _ref => {
23
+ let {
24
+ active
25
+ } = _ref;
26
+ return active ? (0, _styledComponents.css)(["background-color:var(--color-card,#fff);color:var(--color-foreground,#000);border-color:var(--color-border,#ddd);"]) : (0, _styledComponents.css)(["background-color:transparent;color:var(--color-muted-foreground,#666);"]);
27
+ });
28
+ const IconWrapper = _styledComponents.default.span.withConfig({
29
+ displayName: "BmTabv2__IconWrapper"
30
+ })(["display:flex;align-items:center;justify-content:center;"]);
31
+ const BmCustomTab = _ref2 => {
32
+ let {
33
+ value,
34
+ onValueChange,
35
+ tabs = [],
36
+ className
37
+ } = _ref2;
38
+ return /*#__PURE__*/_react.default.createElement(TabsContainer, {
39
+ className: className
40
+ }, /*#__PURE__*/_react.default.createElement(TabsHeader, null, /*#__PURE__*/_react.default.createElement(TabsList, null, tabs.map(tab => {
41
+ const Icon = tab.icon;
42
+ return /*#__PURE__*/_react.default.createElement(TabsTriggerButton, {
43
+ key: tab.value,
44
+ active: value === tab.value,
45
+ onClick: () => onValueChange(tab.value)
46
+ }, Icon && /*#__PURE__*/_react.default.createElement(IconWrapper, null, /*#__PURE__*/_react.default.createElement(Icon, {
47
+ fontSize: "small"
48
+ })), /*#__PURE__*/_react.default.createElement("span", null, tab.label));
49
+ }))));
50
+ };
51
+ var _default = exports.default = BmCustomTab;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.ExampleTabs = exports.ExampleCustomTabsUsage = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _CalendarTodayOutlined = _interopRequireDefault(require("@mui/icons-material/CalendarTodayOutlined"));
9
+ var _Group = _interopRequireDefault(require("@mui/icons-material/Group"));
10
+ var _Business = _interopRequireDefault(require("@mui/icons-material/Business"));
11
+ var _BmTabv = _interopRequireDefault(require("./BmTabv2"));
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
+ 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); }
14
+ const ExampleCustomTabsUsage = () => {
15
+ const [activeTab, setActiveTab] = (0, _react.useState)('departments');
16
+ const tabs = [{
17
+ value: 'departments',
18
+ label: 'Departments',
19
+ icon: _Business.default
20
+ }, {
21
+ value: 'resources',
22
+ label: 'Resources',
23
+ icon: _Group.default
24
+ }, {
25
+ value: 'events',
26
+ label: 'Events',
27
+ icon: _CalendarTodayOutlined.default
28
+ }];
29
+ return /*#__PURE__*/_react.default.createElement("div", {
30
+ style: {
31
+ padding: 20
32
+ }
33
+ }, /*#__PURE__*/_react.default.createElement(_BmTabv.default, {
34
+ value: activeTab,
35
+ onValueChange: setActiveTab,
36
+ tabs: tabs
37
+ }), /*#__PURE__*/_react.default.createElement("div", {
38
+ style: {
39
+ marginTop: 20
40
+ }
41
+ }, /*#__PURE__*/_react.default.createElement("strong", null, "Current Tab:"), " ", activeTab));
42
+ };
43
+ exports.ExampleCustomTabsUsage = ExampleCustomTabsUsage;
44
+ var _default = exports.default = {
45
+ title: 'Components/CustomTabs',
46
+ component: _BmTabv.default
47
+ };
48
+ const ExampleTabs = () => {
49
+ const [activeTab, setActiveTab] = (0, _react.useState)('departments');
50
+ const tabs = [{
51
+ value: 'departments',
52
+ label: 'Departments',
53
+ icon: _Business.default
54
+ }, {
55
+ value: 'resources',
56
+ label: 'Resources',
57
+ icon: _Group.default
58
+ }, {
59
+ value: 'events',
60
+ label: 'Events',
61
+ icon: _CalendarTodayOutlined.default
62
+ }];
63
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_BmTabv.default, {
64
+ value: activeTab,
65
+ onValueChange: setActiveTab,
66
+ tabs: tabs
67
+ }), /*#__PURE__*/_react.default.createElement("div", {
68
+ style: {
69
+ marginTop: '20px'
70
+ }
71
+ }, /*#__PURE__*/_react.default.createElement("p", null, "You have selected: ", /*#__PURE__*/_react.default.createElement("strong", null, activeTab))));
72
+ };
73
+ exports.ExampleTabs = ExampleTabs;
@@ -0,0 +1,131 @@
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 = _interopRequireWildcard(require("styled-components"));
9
+ var _AccessTime = _interopRequireDefault(require("@mui/icons-material/AccessTime"));
10
+ var _AttachMoney = _interopRequireDefault(require("@mui/icons-material/AttachMoney"));
11
+ var _LocationOnOutlined = _interopRequireDefault(require("@mui/icons-material/LocationOnOutlined"));
12
+ var _Link = _interopRequireDefault(require("@mui/icons-material/Link"));
13
+ var _Edit = _interopRequireDefault(require("@mui/icons-material/Edit"));
14
+ var _Delete = _interopRequireDefault(require("@mui/icons-material/Delete"));
15
+ var _Groups2Outlined = _interopRequireDefault(require("@mui/icons-material/Groups2Outlined"));
16
+ var _PeopleAltOutlined = _interopRequireDefault(require("@mui/icons-material/PeopleAltOutlined"));
17
+ var _lodash = require("lodash");
18
+ 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); }
19
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
20
+ const RowContainer = _styledComponents.default.div.withConfig({
21
+ displayName: "HorizontalCard__RowContainer"
22
+ })(["position:relative;border:1px solid rgba(0,0,0,0.1);border-radius:8px;padding:16px;transition:all 0.2s;display:flex;justify-content:space-between;align-items:flex-start;cursor:pointer;gap:12px;&:hover{border-color:rgba(0,0,0,0.2);}", " @media (max-width:600px){flex-direction:column;align-items:flex-start;}"], _ref => {
23
+ let {
24
+ isActive
25
+ } = _ref;
26
+ return !isActive && (0, _styledComponents.css)(["opacity:0.7;"]);
27
+ });
28
+ const ColorBar = _styledComponents.default.div.withConfig({
29
+ displayName: "HorizontalCard__ColorBar"
30
+ })(["position:absolute;top:0;left:0;width:4px;height:100%;border-top-left-radius:8px;border-bottom-left-radius:8px;background-color:", ";"], props => props.color || '#ccc');
31
+ const InfoContainer = _styledComponents.default.div.withConfig({
32
+ displayName: "HorizontalCard__InfoContainer"
33
+ })(["flex:1;padding-left:12px;"]);
34
+ const TitleRow = _styledComponents.default.div.withConfig({
35
+ displayName: "HorizontalCard__TitleRow"
36
+ })(["display:flex;align-items:center;gap:8px;flex-wrap:wrap;"]);
37
+ const Name = _styledComponents.default.h3.withConfig({
38
+ displayName: "HorizontalCard__Name"
39
+ })(["margin:0;font-weight:500;"]);
40
+ const Badge = _styledComponents.default.span.withConfig({
41
+ displayName: "HorizontalCard__Badge"
42
+ })(["display:inline-flex;align-items:center;padding:2px 6px;font-size:12px;border-radius:4px;", ""], _ref2 => {
43
+ let {
44
+ variant
45
+ } = _ref2;
46
+ return variant === 'outline' ? (0, _styledComponents.css)(["border:1px solid #d1d5db;color:#4b5563;background-color:rgba(0,0,0,0.04);"]) : (0, _styledComponents.css)(["background-color:#e6f4ea;color:#166534;border:none;"]);
47
+ });
48
+ const Description = _styledComponents.default.p.withConfig({
49
+ displayName: "HorizontalCard__Description"
50
+ })(["margin-top:4px;font-size:0.9rem;color:#6b7280;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"]);
51
+ const MetaRow = _styledComponents.default.div.withConfig({
52
+ displayName: "HorizontalCard__MetaRow"
53
+ })(["display:flex;flex-wrap:wrap;gap:16px;margin-top:12px;"]);
54
+ const MetaItem = _styledComponents.default.div.withConfig({
55
+ displayName: "HorizontalCard__MetaItem"
56
+ })(["display:flex;align-items:center;font-size:0.875rem;color:#374151;svg{margin-right:4px;width:18px;height:18px;}"]);
57
+ const ActionButtons = _styledComponents.default.div.withConfig({
58
+ displayName: "HorizontalCard__ActionButtons"
59
+ })(["display:flex;align-items:center;gap:4px;opacity:0;transition:opacity 0.2s;", ":hover &{opacity:1;}"], RowContainer);
60
+ const IconButton = _styledComponents.default.button.withConfig({
61
+ displayName: "HorizontalCard__IconButton"
62
+ })(["background:transparent;border:none;padding:4px;cursor:pointer;color:", ";transition:color 0.2s;&:hover{color:#111827;}&.danger:hover{color:#dc2626;}@media (max-width:600px){padding:2px;}"], _ref3 => {
63
+ let {
64
+ iconColor
65
+ } = _ref3;
66
+ return iconColor || '#111827';
67
+ });
68
+ const BmHorizontalCard = _ref4 => {
69
+ let {
70
+ onView,
71
+ onDelete,
72
+ onCopyLink,
73
+ name,
74
+ description,
75
+ price,
76
+ color,
77
+ isActive,
78
+ location,
79
+ paymentSettings,
80
+ selectedResources,
81
+ address,
82
+ duration,
83
+ guest_limit
84
+ } = _ref4;
85
+ return /*#__PURE__*/_react.default.createElement(RowContainer, {
86
+ isActive: isActive
87
+ }, /*#__PURE__*/_react.default.createElement(ColorBar, {
88
+ color: color
89
+ }), /*#__PURE__*/_react.default.createElement(InfoContainer, null, /*#__PURE__*/_react.default.createElement(TitleRow, null, /*#__PURE__*/_react.default.createElement(Name, null, name), !isActive && /*#__PURE__*/_react.default.createElement(Badge, {
90
+ variant: "outline"
91
+ }, "Inactive"), (paymentSettings === null || paymentSettings === void 0 ? void 0 : paymentSettings.requirePayment) && /*#__PURE__*/_react.default.createElement(Badge, null, /*#__PURE__*/_react.default.createElement(_AttachMoney.default, {
92
+ fontSize: "small"
93
+ }), "Payment Required")), /*#__PURE__*/_react.default.createElement(Description, null, description), /*#__PURE__*/_react.default.createElement(MetaRow, null, /*#__PURE__*/_react.default.createElement(MetaItem, null, /*#__PURE__*/_react.default.createElement(_AccessTime.default, {
94
+ fontSize: "small"
95
+ }), /*#__PURE__*/_react.default.createElement("span", null, duration, " mins")), /*#__PURE__*/_react.default.createElement(MetaItem, null, /*#__PURE__*/_react.default.createElement(_AttachMoney.default, {
96
+ fontSize: "small"
97
+ }), /*#__PURE__*/_react.default.createElement("span", null, price === 0 ? 'Free' : "$".concat(price))), /*#__PURE__*/_react.default.createElement(MetaItem, null, /*#__PURE__*/_react.default.createElement(_LocationOnOutlined.default, {
98
+ fontSize: "small"
99
+ }), /*#__PURE__*/_react.default.createElement("span", null, location, (0, _lodash.lowerCase)(location) === 'physical' && address ? " (".concat(address.split(',')[0], "...)") : '')), guest_limit && /*#__PURE__*/_react.default.createElement(MetaItem, null, /*#__PURE__*/_react.default.createElement(_Groups2Outlined.default, {
100
+ fontSize: "small"
101
+ }), /*#__PURE__*/_react.default.createElement("span", null, "Max ", guest_limit, " attendee", guest_limit > 1 ? 's' : '')), selectedResources && selectedResources.length > 0 && /*#__PURE__*/_react.default.createElement(MetaItem, null, /*#__PURE__*/_react.default.createElement(_PeopleAltOutlined.default, {
102
+ fontSize: "small"
103
+ }), /*#__PURE__*/_react.default.createElement("span", null, selectedResources.length, " resource", selectedResources.length > 1 ? 's' : '')))), /*#__PURE__*/_react.default.createElement(ActionButtons, null, /*#__PURE__*/_react.default.createElement(IconButton, {
104
+ onClick: e => {
105
+ e.stopPropagation();
106
+ onCopyLink();
107
+ },
108
+ title: "Copy shareable link"
109
+ }, /*#__PURE__*/_react.default.createElement(_Link.default, {
110
+ fontSize: "small"
111
+ })), /*#__PURE__*/_react.default.createElement(IconButton, {
112
+ onClick: e => {
113
+ e.stopPropagation();
114
+ onView();
115
+ },
116
+ title: "Edit appointment type"
117
+ }, /*#__PURE__*/_react.default.createElement(_Edit.default, {
118
+ fontSize: "small"
119
+ })), /*#__PURE__*/_react.default.createElement(IconButton, {
120
+ iconColor: "#dc2626",
121
+ className: "danger",
122
+ onClick: e => {
123
+ e.stopPropagation();
124
+ onDelete();
125
+ },
126
+ title: "Delete appointment type"
127
+ }, /*#__PURE__*/_react.default.createElement(_Delete.default, {
128
+ fontSize: "small"
129
+ }))));
130
+ };
131
+ var _default = exports.default = BmHorizontalCard;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.Example = void 0;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _addonActions = require("@storybook/addon-actions");
9
+ var _HorizontalCard = _interopRequireDefault(require("./HorizontalCard"));
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ var _default = exports.default = {
12
+ title: 'Components/BmHorizontalCard',
13
+ component: _HorizontalCard.default,
14
+ tags: ['autodocs']
15
+ };
16
+ const sampleResources = [{
17
+ id: 1
18
+ }, {
19
+ id: 2
20
+ }];
21
+ const Example = () => /*#__PURE__*/_react.default.createElement(_HorizontalCard.default, {
22
+ onView: (0, _addonActions.action)('View clicked'),
23
+ onDelete: (0, _addonActions.action)('Delete clicked'),
24
+ onCopyLink: (0, _addonActions.action)('Copy link clicked'),
25
+ name: "Strategy Session",
26
+ description: "Deep dive on your business strategy and next steps.",
27
+ price: 150,
28
+ color: "#10b981",
29
+ isActive: true,
30
+ location: "physical",
31
+ paymentSettings: {
32
+ requirePayment: true
33
+ },
34
+ selectedResources: sampleResources,
35
+ address: "456 Innovation Avenue, Tech City",
36
+ duration: 60,
37
+ guest_limit: 10
38
+ });
39
+ exports.Example = Example;
@@ -178,6 +178,12 @@ Object.defineProperty(exports, "BmCustomCardTitle", {
178
178
  return _CustomCardTitle.default;
179
179
  }
180
180
  });
181
+ Object.defineProperty(exports, "BmCustomTab", {
182
+ enumerable: true,
183
+ get: function () {
184
+ return _BmTabv.default;
185
+ }
186
+ });
181
187
  Object.defineProperty(exports, "BmDepartmentCard", {
182
188
  enumerable: true,
183
189
  get: function () {
@@ -202,6 +208,12 @@ Object.defineProperty(exports, "BmFooterRight", {
202
208
  return _ContentTitle.BmFooterRight;
203
209
  }
204
210
  });
211
+ Object.defineProperty(exports, "BmHorizontalCard", {
212
+ enumerable: true,
213
+ get: function () {
214
+ return _HorizontalCard.default;
215
+ }
216
+ });
205
217
  Object.defineProperty(exports, "BmIcons", {
206
218
  enumerable: true,
207
219
  get: function () {
@@ -493,5 +505,7 @@ var _CustomCardTitle = _interopRequireDefault(require("./BmCustomCardTitle/Custo
493
505
  var _Alert = _interopRequireDefault(require("./Alert/Alert"));
494
506
  var _DepartmentCard = _interopRequireDefault(require("./DepartmentCard/DepartmentCard"));
495
507
  var _ResourceCard = _interopRequireDefault(require("./ResourceCard/ResourceCard"));
508
+ var _BmTabv = _interopRequireDefault(require("./BmTabv2/BmTabv2"));
509
+ var _HorizontalCard = _interopRequireDefault(require("./HorizontalCard/HorizontalCard"));
496
510
  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); }
497
511
  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.11",
3
+ "version": "2.1.13",
4
4
  "private": false,
5
5
  "main": "dist/components/index.js",
6
6
  "scripts": {
package/src/App.js CHANGED
@@ -8,6 +8,10 @@ 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
10
  import CalendarTodayOutlinedIcon from '@mui/icons-material/CalendarTodayOutlined';
11
+
12
+ import GroupIcon from '@mui/icons-material/Group';
13
+ // import BusinessIcon from '@mui/icons-material/Business';
14
+
11
15
  import CheckIcon from '@mui/icons-material/Check';
12
16
  import EditIcon from '@mui/icons-material/Edit';
13
17
  import DeleteIcon from '@mui/icons-material/Delete';
@@ -41,9 +45,11 @@ import {
41
45
  BmCustomCardTitle,
42
46
  BmDepartmentCard,
43
47
  BmResourceCard,
48
+ BmCustomTab,
49
+ BmHorizontalCard,
44
50
  } from './lib/components';
45
51
  import AlertBox from './lib/components/Alert/Alert';
46
- import { TabPanel, Tabs } from './lib/components/BmTabv2/BmTabV2.';
52
+
47
53
  // import ProgressIndicator from './lib/components/newProgress';
48
54
 
49
55
  // const datsa = JSON.stringify({
@@ -64,6 +70,11 @@ import { TabPanel, Tabs } from './lib/components/BmTabv2/BmTabV2.';
64
70
  // },
65
71
  // });
66
72
  // console.log(datsa);
73
+ const tabs = [
74
+ { value: 'departments', label: 'Departments' },
75
+ { value: 'resources', label: 'Resources', icon: GroupIcon },
76
+ { value: 'events', label: 'Events', icon: CalendarTodayOutlinedIcon },
77
+ ];
67
78
  const Chat = () => {
68
79
  const message = {
69
80
  id: 75681,
@@ -1010,25 +1021,97 @@ const Chat = () => {
1010
1021
  value: { startDate: '5:10 PM', endDate: '5:50 PM' },
1011
1022
  },
1012
1023
  ];
1024
+ const sampleAppointmentTypes = [
1025
+ {
1026
+ id: 1,
1027
+ name: 'ConsulTation Call',
1028
+ description: 'Discuss project requirements and timelines.',
1029
+ price: 0,
1030
+ color: '#3b82f6', // blue
1031
+ isActive: true,
1032
+ location: 'Virtual',
1033
+ paymentSettings: { requirePayment: false },
1034
+ selectedResources: [],
1035
+ address: '',
1036
+ duration: '60', // in minutes
1037
+ guest_limit: '2', // max number of guests allowed
1038
+ },
1039
+ {
1040
+ id: 2,
1041
+ name: 'Strategy Session',
1042
+ description: 'Deep dive session for business strategy and growth.',
1043
+ price: 150,
1044
+ color: '#10b981', // green
1045
+ isActive: true,
1046
+ location: 'Physical',
1047
+ paymentSettings: { requirePayment: true },
1048
+ selectedResources: [{ id: 1 }],
1049
+ address: '456 Innovation Avenue, Tech City',
1050
+ duration: '90', // in minutes
1051
+ guest_limit: '5', // max number of guests allowed
1052
+ },
1053
+ {
1054
+ id: 3,
1055
+ name: 'Follow-up Meeting',
1056
+ description: 'Review progress and next steps with the team.',
1057
+ price: 75,
1058
+ color: '#f59e0b', // amber
1059
+ isActive: false,
1060
+ location: 'Virtual',
1061
+ paymentSettings: { requirePayment: true },
1062
+ selectedResources: [{ id: 1 }, { id: 2 }],
1063
+ address: '',
1064
+ duration: '30', // in minutes
1065
+ },
1066
+ ];
1013
1067
 
1014
1068
  const [selectedSlotId, setSelectedSlotId] = useState(null);
1015
1069
  console.log({ selectedSlotId });
1016
1070
  const imgs = 'https://i.imgur.com/HiAzUHl.jpeg';
1071
+ const [activeTab, setActiveTab] = useState('departments');
1072
+ const handleView = (id) => console.log('View', id);
1073
+ const handleDelete = (type) => console.log('Delete', type);
1074
+ const handleCopyLink = (id) => console.log('Copy Link', id);
1017
1075
  return (
1018
1076
  <>
1019
1077
  <GlobalStyle />
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>
1078
+
1079
+ <div
1080
+ style={{
1081
+ display: 'flex',
1082
+ flexDirection: 'column',
1083
+ gap: '2rem',
1084
+ width: '50%',
1085
+ }}
1086
+ >
1087
+ <BmCustomTab
1088
+ value={activeTab}
1089
+ onValueChange={setActiveTab}
1090
+ tabs={tabs}
1091
+ />
1092
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
1093
+ {sampleAppointmentTypes.map((type) => (
1094
+ <BmHorizontalCard
1095
+ name={type.name}
1096
+ description={type.description}
1097
+ price={type.price}
1098
+ color={type.color}
1099
+ isActive={type.isActive}
1100
+ location={type.location}
1101
+ paymentSettings={type.paymentSettings}
1102
+ selectedResources={type.selectedResources}
1103
+ address={type.address}
1104
+ duration={type.duration}
1105
+ guest_limit={type.guest_limit}
1106
+ key={type.id}
1107
+ onView={() => handleView(type.id)}
1108
+ onDelete={() => handleDelete(type)}
1109
+ onCopyLink={() => handleCopyLink(type.id)}
1110
+ data={type}
1111
+ />
1112
+ ))}
1113
+ </div>
1114
+
1032
1115
  <div style={{ width: '100%', maxWidth: '900px', margin: '2rem auto' }}>
1033
1116
  <div style={{ maxWidth: 400, margin: '2rem auto' }}>
1034
1117
  <BmDepartmentCard
@@ -0,0 +1,109 @@
1
+ import React from 'react';
2
+ import styled, { css } from 'styled-components';
3
+
4
+ const TabsContainer = styled.div`
5
+ width: 100%;
6
+ `;
7
+
8
+ const TabsHeader = styled.div`
9
+ display: flex;
10
+ justify-content: flex-start;
11
+ align-items: center;
12
+ margin-bottom: 14px;
13
+ padding: 0 14px;
14
+ border-radius: var(--radius-lg, 12px);
15
+ flex-wrap: wrap;
16
+ `;
17
+
18
+ const TabsList = styled.div`
19
+ width: 100%;
20
+ display: inline-flex;
21
+ background-color: var(--color-muted, #f2f2f2);
22
+ color: var(--color-muted-foreground, #666);
23
+ align-items: center;
24
+ justify-content: center;
25
+ border-radius: var(--radius-lg, 12px);
26
+ padding: 4px 4px;
27
+ `;
28
+
29
+ const TabsTriggerButton = styled.button`
30
+ display: inline-flex;
31
+ flex: 1;
32
+ align-items: center;
33
+ justify-content: center;
34
+ gap: 6px;
35
+ border: 1px solid transparent;
36
+ border-radius: var(--radius-lg, 12px);
37
+ padding: 6px 12px;
38
+ font-size: 14px;
39
+ font-weight: 500;
40
+ white-space: nowrap;
41
+ transition: color 0.2s, box-shadow 0.2s, background-color 0.2s;
42
+ cursor: pointer;
43
+
44
+ ${({ active }) =>
45
+ active
46
+ ? css`
47
+ background-color: var(--color-card, #fff);
48
+ color: var(--color-foreground, #000);
49
+ border-color: var(--color-border, #ddd);
50
+ `
51
+ : css`
52
+ background-color: transparent;
53
+ color: var(--color-muted-foreground, #666);
54
+ `}
55
+
56
+ &:focus-visible {
57
+ outline: none;
58
+ border-color: var(--color-ring, #2684ff);
59
+ box-shadow: 0 0 0 3px rgba(38, 132, 255, 0.3);
60
+ }
61
+
62
+ &:disabled {
63
+ pointer-events: none;
64
+ opacity: 0.5;
65
+ }
66
+
67
+ svg {
68
+ flex-shrink: 0;
69
+ pointer-events: none;
70
+ width: 16px;
71
+ height: 16px;
72
+ }
73
+ `;
74
+
75
+ const IconWrapper = styled.span`
76
+ display: flex;
77
+ align-items: center;
78
+ justify-content: center;
79
+ `;
80
+
81
+ const BmCustomTab = ({ value, onValueChange, tabs = [], className }) => {
82
+ return (
83
+ <TabsContainer className={className}>
84
+ <TabsHeader>
85
+ <TabsList>
86
+ {tabs.map((tab) => {
87
+ const Icon = tab.icon;
88
+ return (
89
+ <TabsTriggerButton
90
+ key={tab.value}
91
+ active={value === tab.value}
92
+ onClick={() => onValueChange(tab.value)}
93
+ >
94
+ {Icon && (
95
+ <IconWrapper>
96
+ <Icon fontSize="small" />
97
+ </IconWrapper>
98
+ )}
99
+ <span>{tab.label}</span>
100
+ </TabsTriggerButton>
101
+ );
102
+ })}
103
+ </TabsList>
104
+ </TabsHeader>
105
+ </TabsContainer>
106
+ );
107
+ };
108
+
109
+ export default BmCustomTab;
@@ -0,0 +1,51 @@
1
+ import React, { useState } from 'react';
2
+
3
+ import CalendarTodayOutlinedIcon from '@mui/icons-material/CalendarTodayOutlined';
4
+ import GroupIcon from '@mui/icons-material/Group';
5
+ import BusinessIcon from '@mui/icons-material/Business';
6
+ import BmCustomTab from './BmTabv2';
7
+
8
+ export const ExampleCustomTabsUsage = () => {
9
+ const [activeTab, setActiveTab] = useState('departments');
10
+
11
+ const tabs = [
12
+ { value: 'departments', label: 'Departments', icon: BusinessIcon },
13
+ { value: 'resources', label: 'Resources', icon: GroupIcon },
14
+ { value: 'events', label: 'Events', icon: CalendarTodayOutlinedIcon },
15
+ ];
16
+
17
+ return (
18
+ <div style={{ padding: 20 }}>
19
+ <BmCustomTab value={activeTab} onValueChange={setActiveTab} tabs={tabs} />
20
+ <div style={{ marginTop: 20 }}>
21
+ <strong>Current Tab:</strong> {activeTab}
22
+ </div>
23
+ </div>
24
+ );
25
+ };
26
+
27
+ export default {
28
+ title: 'Components/CustomTabs',
29
+ component: BmCustomTab,
30
+ };
31
+
32
+ export const ExampleTabs = () => {
33
+ const [activeTab, setActiveTab] = useState('departments');
34
+
35
+ const tabs = [
36
+ { value: 'departments', label: 'Departments', icon: BusinessIcon },
37
+ { value: 'resources', label: 'Resources', icon: GroupIcon },
38
+ { value: 'events', label: 'Events', icon: CalendarTodayOutlinedIcon },
39
+ ];
40
+
41
+ return (
42
+ <>
43
+ <BmCustomTab value={activeTab} onValueChange={setActiveTab} tabs={tabs} />
44
+ <div style={{ marginTop: '20px' }}>
45
+ <p>
46
+ You have selected: <strong>{activeTab}</strong>
47
+ </p>
48
+ </div>
49
+ </>
50
+ );
51
+ };
@@ -0,0 +1,259 @@
1
+ import React from 'react';
2
+ import styled, { css } from 'styled-components';
3
+ import AccessTimeIcon from '@mui/icons-material/AccessTime';
4
+ import AttachMoneyIcon from '@mui/icons-material/AttachMoney';
5
+ import LocationOnOutlinedIcon from '@mui/icons-material/LocationOnOutlined';
6
+ import LinkIcon from '@mui/icons-material/Link';
7
+ import EditIcon from '@mui/icons-material/Edit';
8
+ import DeleteIcon from '@mui/icons-material/Delete';
9
+ import Groups2OutlinedIcon from '@mui/icons-material/Groups2Outlined';
10
+ import PeopleAltOutlinedIcon from '@mui/icons-material/PeopleAltOutlined';
11
+ import { lowerCase } from 'lodash';
12
+
13
+ const RowContainer = styled.div`
14
+ position: relative;
15
+ border: 1px solid rgba(0, 0, 0, 0.1);
16
+ border-radius: 8px;
17
+ padding: 16px;
18
+ transition: all 0.2s;
19
+ display: flex;
20
+ justify-content: space-between;
21
+ align-items: flex-start;
22
+ cursor: pointer;
23
+ gap: 12px;
24
+
25
+ &:hover {
26
+ border-color: rgba(0, 0, 0, 0.2);
27
+ }
28
+
29
+ ${({ isActive }) =>
30
+ !isActive &&
31
+ css`
32
+ opacity: 0.7;
33
+ `}
34
+
35
+ @media (max-width: 600px) {
36
+ flex-direction: column;
37
+ align-items: flex-start;
38
+ }
39
+ `;
40
+
41
+ const ColorBar = styled.div`
42
+ position: absolute;
43
+ top: 0;
44
+ left: 0;
45
+ width: 4px;
46
+ height: 100%;
47
+ border-top-left-radius: 8px;
48
+ border-bottom-left-radius: 8px;
49
+ background-color: ${(props) => props.color || '#ccc'};
50
+ `;
51
+
52
+ const InfoContainer = styled.div`
53
+ flex: 1;
54
+ padding-left: 12px;
55
+ `;
56
+
57
+ const TitleRow = styled.div`
58
+ display: flex;
59
+ align-items: center;
60
+ gap: 8px;
61
+ flex-wrap: wrap;
62
+ `;
63
+
64
+ const Name = styled.h3`
65
+ margin: 0;
66
+ font-weight: 500;
67
+ `;
68
+
69
+ const Badge = styled.span`
70
+ display: inline-flex;
71
+ align-items: center;
72
+ padding: 2px 6px;
73
+ font-size: 12px;
74
+ border-radius: 4px;
75
+ ${({ variant }) =>
76
+ variant === 'outline'
77
+ ? css`
78
+ border: 1px solid #d1d5db;
79
+ color: #4b5563;
80
+ background-color: rgba(0, 0, 0, 0.04);
81
+ `
82
+ : css`
83
+ background-color: #e6f4ea;
84
+ color: #166534;
85
+ border: none;
86
+ `}
87
+ `;
88
+
89
+ const Description = styled.p`
90
+ margin-top: 4px;
91
+ font-size: 0.9rem;
92
+ color: #6b7280;
93
+ overflow: hidden;
94
+ text-overflow: ellipsis;
95
+ white-space: nowrap;
96
+ `;
97
+
98
+ const MetaRow = styled.div`
99
+ display: flex;
100
+ flex-wrap: wrap;
101
+ gap: 16px;
102
+ margin-top: 12px;
103
+ `;
104
+
105
+ const MetaItem = styled.div`
106
+ display: flex;
107
+ align-items: center;
108
+ font-size: 0.875rem;
109
+ color: #374151;
110
+
111
+ svg {
112
+ margin-right: 4px;
113
+ width: 18px;
114
+ height: 18px;
115
+ }
116
+ `;
117
+
118
+ const ActionButtons = styled.div`
119
+ display: flex;
120
+ align-items: center;
121
+ gap: 4px;
122
+ opacity: 0;
123
+ transition: opacity 0.2s;
124
+ ${RowContainer}:hover & {
125
+ opacity: 1;
126
+ }
127
+ `;
128
+
129
+ const IconButton = styled.button`
130
+ background: transparent;
131
+ border: none;
132
+ padding: 4px;
133
+ cursor: pointer;
134
+ color: ${({ iconColor }) => iconColor || '#111827'};
135
+ transition: color 0.2s;
136
+
137
+ &:hover {
138
+ color: #111827;
139
+ }
140
+
141
+ &.danger:hover {
142
+ color: #dc2626;
143
+ }
144
+
145
+ @media (max-width: 600px) {
146
+ padding: 2px;
147
+ }
148
+ `;
149
+
150
+ const BmHorizontalCard = ({
151
+ onView,
152
+ onDelete,
153
+ onCopyLink,
154
+ name,
155
+ description,
156
+ price,
157
+ color,
158
+ isActive,
159
+ location,
160
+ paymentSettings,
161
+ selectedResources,
162
+ address,
163
+ duration,
164
+ guest_limit,
165
+ }) => {
166
+ return (
167
+ <RowContainer isActive={isActive}>
168
+ <ColorBar color={color} />
169
+
170
+ <InfoContainer>
171
+ <TitleRow>
172
+ <Name>{name}</Name>
173
+
174
+ {!isActive && <Badge variant="outline">Inactive</Badge>}
175
+
176
+ {paymentSettings?.requirePayment && (
177
+ <Badge>
178
+ <AttachMoneyIcon fontSize="small" />
179
+ Payment Required
180
+ </Badge>
181
+ )}
182
+ </TitleRow>
183
+
184
+ <Description>{description}</Description>
185
+
186
+ <MetaRow>
187
+ <MetaItem>
188
+ <AccessTimeIcon fontSize="small" />
189
+ <span>{duration} mins</span>
190
+ </MetaItem>
191
+ <MetaItem>
192
+ <AttachMoneyIcon fontSize="small" />
193
+ <span>{price === 0 ? 'Free' : `$${price}`}</span>
194
+ </MetaItem>
195
+ <MetaItem>
196
+ <LocationOnOutlinedIcon fontSize="small" />
197
+ <span>
198
+ {location}
199
+ {lowerCase(location) === 'physical' && address
200
+ ? ` (${address.split(',')[0]}...)`
201
+ : ''}
202
+ </span>
203
+ </MetaItem>
204
+ {guest_limit && (
205
+ <MetaItem>
206
+ <Groups2OutlinedIcon fontSize="small" />
207
+ <span>
208
+ Max {guest_limit} attendee{guest_limit > 1 ? 's' : ''}
209
+ </span>
210
+ </MetaItem>
211
+ )}
212
+ {selectedResources && selectedResources.length > 0 && (
213
+ <MetaItem>
214
+ <PeopleAltOutlinedIcon fontSize="small" />
215
+ <span>
216
+ {selectedResources.length} resource
217
+ {selectedResources.length > 1 ? 's' : ''}
218
+ </span>
219
+ </MetaItem>
220
+ )}
221
+ </MetaRow>
222
+ </InfoContainer>
223
+
224
+ <ActionButtons>
225
+ <IconButton
226
+ onClick={(e) => {
227
+ e.stopPropagation();
228
+ onCopyLink();
229
+ }}
230
+ title="Copy shareable link"
231
+ >
232
+ <LinkIcon fontSize="small" />
233
+ </IconButton>
234
+ <IconButton
235
+ onClick={(e) => {
236
+ e.stopPropagation();
237
+ onView();
238
+ }}
239
+ title="Edit appointment type"
240
+ >
241
+ <EditIcon fontSize="small" />
242
+ </IconButton>
243
+ <IconButton
244
+ iconColor="#dc2626"
245
+ className="danger"
246
+ onClick={(e) => {
247
+ e.stopPropagation();
248
+ onDelete();
249
+ }}
250
+ title="Delete appointment type"
251
+ >
252
+ <DeleteIcon fontSize="small" />
253
+ </IconButton>
254
+ </ActionButtons>
255
+ </RowContainer>
256
+ );
257
+ };
258
+
259
+ export default BmHorizontalCard;
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import { action } from '@storybook/addon-actions';
3
+ import BmHorizontalCard from './HorizontalCard';
4
+
5
+ export default {
6
+ title: 'Components/BmHorizontalCard',
7
+ component: BmHorizontalCard,
8
+ tags: ['autodocs'],
9
+ };
10
+
11
+ const sampleResources = [{ id: 1 }, { id: 2 }];
12
+
13
+ export const Example = () => (
14
+ <BmHorizontalCard
15
+ onView={action('View clicked')}
16
+ onDelete={action('Delete clicked')}
17
+ onCopyLink={action('Copy link clicked')}
18
+ name="Strategy Session"
19
+ description="Deep dive on your business strategy and next steps."
20
+ price={150}
21
+ color="#10b981"
22
+ isActive
23
+ location="physical"
24
+ paymentSettings={{ requirePayment: true }}
25
+ selectedResources={sampleResources}
26
+ address="456 Innovation Avenue, Tech City"
27
+ duration={60}
28
+ guest_limit={10}
29
+ />
30
+ );
@@ -86,6 +86,9 @@ import BmAlertBox from './Alert/Alert';
86
86
  import BmDepartmentCard from './DepartmentCard/DepartmentCard';
87
87
  import BmResourceCard from './ResourceCard/ResourceCard';
88
88
 
89
+ import BmCustomTab from './BmTabv2/BmTabv2';
90
+ import BmHorizontalCard from './HorizontalCard/HorizontalCard';
91
+
89
92
  export {
90
93
  BmAccordion,
91
94
  BmAvatar,
@@ -167,4 +170,6 @@ export {
167
170
  BmAlertBox,
168
171
  BmDepartmentCard,
169
172
  BmResourceCard,
173
+ BmCustomTab,
174
+ BmHorizontalCard,
170
175
  };
@@ -1,72 +0,0 @@
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';
@@ -1,122 +0,0 @@
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 };