beem-component 2.1.10 → 2.1.12
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.
- package/dist/components/BmCustomCardTitle/CustomCardTitle.js +9 -2
- package/dist/components/BmCustomCardTitle/CustomCardTitle.stories.js +10 -3
- package/dist/components/BmTabv2/BmTabv2.js +51 -0
- package/dist/components/BmTabv2/BmTabv2.stories.js +73 -0
- package/dist/components/HorizontalCard/HorizontalCard.js +130 -0
- package/dist/components/HorizontalCard/HorizontalCard.stories.js +39 -0
- package/dist/components/index.js +14 -0
- package/package.json +1 -1
- package/src/App.js +91 -12
- package/src/lib/components/BmCustomCardTitle/CustomCardTitle.js +20 -0
- package/src/lib/components/BmCustomCardTitle/CustomCardTitle.stories.jsx +17 -8
- package/src/lib/components/BmTabv2/BmTabv2.js +108 -0
- package/src/lib/components/BmTabv2/BmTabv2.stories.jsx +51 -0
- package/src/lib/components/HorizontalCard/HorizontalCard.js +258 -0
- package/src/lib/components/HorizontalCard/HorizontalCard.stories.jsx +30 -0
- package/src/lib/components/index.js +5 -0
- package/dist/components/BmTabv2/BmTabV2..js +0 -72
- package/src/lib/components/BmTabv2/BmTabV2..js +0 -122
|
@@ -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,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
|
+
})(["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,130 @@
|
|
|
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
|
+
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); }
|
|
18
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
19
|
+
const RowContainer = _styledComponents.default.div.withConfig({
|
|
20
|
+
displayName: "HorizontalCard__RowContainer"
|
|
21
|
+
})(["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 => {
|
|
22
|
+
let {
|
|
23
|
+
isActive
|
|
24
|
+
} = _ref;
|
|
25
|
+
return !isActive && (0, _styledComponents.css)(["opacity:0.7;"]);
|
|
26
|
+
});
|
|
27
|
+
const ColorBar = _styledComponents.default.div.withConfig({
|
|
28
|
+
displayName: "HorizontalCard__ColorBar"
|
|
29
|
+
})(["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');
|
|
30
|
+
const InfoContainer = _styledComponents.default.div.withConfig({
|
|
31
|
+
displayName: "HorizontalCard__InfoContainer"
|
|
32
|
+
})(["flex:1;padding-left:12px;"]);
|
|
33
|
+
const TitleRow = _styledComponents.default.div.withConfig({
|
|
34
|
+
displayName: "HorizontalCard__TitleRow"
|
|
35
|
+
})(["display:flex;align-items:center;gap:8px;flex-wrap:wrap;"]);
|
|
36
|
+
const Name = _styledComponents.default.h3.withConfig({
|
|
37
|
+
displayName: "HorizontalCard__Name"
|
|
38
|
+
})(["margin:0;font-weight:500;"]);
|
|
39
|
+
const Badge = _styledComponents.default.span.withConfig({
|
|
40
|
+
displayName: "HorizontalCard__Badge"
|
|
41
|
+
})(["display:inline-flex;align-items:center;padding:2px 6px;font-size:12px;border-radius:4px;", ""], _ref2 => {
|
|
42
|
+
let {
|
|
43
|
+
variant
|
|
44
|
+
} = _ref2;
|
|
45
|
+
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;"]);
|
|
46
|
+
});
|
|
47
|
+
const Description = _styledComponents.default.p.withConfig({
|
|
48
|
+
displayName: "HorizontalCard__Description"
|
|
49
|
+
})(["margin-top:4px;font-size:0.9rem;color:#6b7280;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"]);
|
|
50
|
+
const MetaRow = _styledComponents.default.div.withConfig({
|
|
51
|
+
displayName: "HorizontalCard__MetaRow"
|
|
52
|
+
})(["display:flex;flex-wrap:wrap;gap:16px;margin-top:12px;"]);
|
|
53
|
+
const MetaItem = _styledComponents.default.div.withConfig({
|
|
54
|
+
displayName: "HorizontalCard__MetaItem"
|
|
55
|
+
})(["display:flex;align-items:center;font-size:0.875rem;color:#374151;svg{margin-right:4px;width:18px;height:18px;}"]);
|
|
56
|
+
const ActionButtons = _styledComponents.default.div.withConfig({
|
|
57
|
+
displayName: "HorizontalCard__ActionButtons"
|
|
58
|
+
})(["display:flex;align-items:center;gap:4px;opacity:0;transition:opacity 0.2s;", ":hover &{opacity:1;}"], RowContainer);
|
|
59
|
+
const IconButton = _styledComponents.default.button.withConfig({
|
|
60
|
+
displayName: "HorizontalCard__IconButton"
|
|
61
|
+
})(["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 => {
|
|
62
|
+
let {
|
|
63
|
+
iconColor
|
|
64
|
+
} = _ref3;
|
|
65
|
+
return iconColor || '#111827';
|
|
66
|
+
});
|
|
67
|
+
const BmHorizontalCard = _ref4 => {
|
|
68
|
+
let {
|
|
69
|
+
onView,
|
|
70
|
+
onDelete,
|
|
71
|
+
onCopyLink,
|
|
72
|
+
name,
|
|
73
|
+
description,
|
|
74
|
+
price,
|
|
75
|
+
color,
|
|
76
|
+
isActive,
|
|
77
|
+
location,
|
|
78
|
+
paymentSettings,
|
|
79
|
+
selectedResources,
|
|
80
|
+
address,
|
|
81
|
+
duration,
|
|
82
|
+
guest_limit
|
|
83
|
+
} = _ref4;
|
|
84
|
+
return /*#__PURE__*/_react.default.createElement(RowContainer, {
|
|
85
|
+
isActive: isActive
|
|
86
|
+
}, /*#__PURE__*/_react.default.createElement(ColorBar, {
|
|
87
|
+
color: color
|
|
88
|
+
}), /*#__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, {
|
|
89
|
+
variant: "outline"
|
|
90
|
+
}, "Inactive"), (paymentSettings === null || paymentSettings === void 0 ? void 0 : paymentSettings.requirePayment) && /*#__PURE__*/_react.default.createElement(Badge, null, /*#__PURE__*/_react.default.createElement(_AttachMoney.default, {
|
|
91
|
+
fontSize: "small"
|
|
92
|
+
}), "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, {
|
|
93
|
+
fontSize: "small"
|
|
94
|
+
}), /*#__PURE__*/_react.default.createElement("span", null, duration, " mins")), /*#__PURE__*/_react.default.createElement(MetaItem, null, /*#__PURE__*/_react.default.createElement(_AttachMoney.default, {
|
|
95
|
+
fontSize: "small"
|
|
96
|
+
}), /*#__PURE__*/_react.default.createElement("span", null, price === 0 ? 'Free' : "$".concat(price))), /*#__PURE__*/_react.default.createElement(MetaItem, null, /*#__PURE__*/_react.default.createElement(_LocationOnOutlined.default, {
|
|
97
|
+
fontSize: "small"
|
|
98
|
+
}), /*#__PURE__*/_react.default.createElement("span", null, location, location === 'physical' && address ? " (".concat(address.split(',')[0], "...)") : '')), guest_limit && /*#__PURE__*/_react.default.createElement(MetaItem, null, /*#__PURE__*/_react.default.createElement(_Groups2Outlined.default, {
|
|
99
|
+
fontSize: "small"
|
|
100
|
+
}), /*#__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, {
|
|
101
|
+
fontSize: "small"
|
|
102
|
+
}), /*#__PURE__*/_react.default.createElement("span", null, selectedResources.length, " resource", selectedResources.length > 1 ? 's' : '')))), /*#__PURE__*/_react.default.createElement(ActionButtons, null, /*#__PURE__*/_react.default.createElement(IconButton, {
|
|
103
|
+
onClick: e => {
|
|
104
|
+
e.stopPropagation();
|
|
105
|
+
onCopyLink();
|
|
106
|
+
},
|
|
107
|
+
title: "Copy shareable link"
|
|
108
|
+
}, /*#__PURE__*/_react.default.createElement(_Link.default, {
|
|
109
|
+
fontSize: "small"
|
|
110
|
+
})), /*#__PURE__*/_react.default.createElement(IconButton, {
|
|
111
|
+
onClick: e => {
|
|
112
|
+
e.stopPropagation();
|
|
113
|
+
onView();
|
|
114
|
+
},
|
|
115
|
+
title: "Edit appointment type"
|
|
116
|
+
}, /*#__PURE__*/_react.default.createElement(_Edit.default, {
|
|
117
|
+
fontSize: "small"
|
|
118
|
+
})), /*#__PURE__*/_react.default.createElement(IconButton, {
|
|
119
|
+
iconColor: "#dc2626",
|
|
120
|
+
className: "danger",
|
|
121
|
+
onClick: e => {
|
|
122
|
+
e.stopPropagation();
|
|
123
|
+
onDelete();
|
|
124
|
+
},
|
|
125
|
+
title: "Delete appointment type"
|
|
126
|
+
}, /*#__PURE__*/_react.default.createElement(_Delete.default, {
|
|
127
|
+
fontSize: "small"
|
|
128
|
+
}))));
|
|
129
|
+
};
|
|
130
|
+
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;
|
package/dist/components/index.js
CHANGED
|
@@ -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
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
|
-
|
|
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', icon: BusinessIcon },
|
|
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,24 +1021,91 @@ 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 });
|
|
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);
|
|
1016
1075
|
return (
|
|
1017
1076
|
<>
|
|
1018
1077
|
<GlobalStyle />
|
|
1019
1078
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
|
1020
|
-
<
|
|
1021
|
-
|
|
1022
|
-
<
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1079
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
|
|
1080
|
+
{sampleAppointmentTypes.map((type) => (
|
|
1081
|
+
<BmHorizontalCard
|
|
1082
|
+
name={type.name}
|
|
1083
|
+
description={type.description}
|
|
1084
|
+
price={type.price}
|
|
1085
|
+
color={type.color}
|
|
1086
|
+
isActive={type.isActive}
|
|
1087
|
+
location={type.location}
|
|
1088
|
+
paymentSettings={type.paymentSettings}
|
|
1089
|
+
selectedResources={type.selectedResources}
|
|
1090
|
+
address={type.address}
|
|
1091
|
+
duration={type.duration}
|
|
1092
|
+
guest_limit={type.guest_limit}
|
|
1093
|
+
key={type.id}
|
|
1094
|
+
onView={() => handleView(type.id)}
|
|
1095
|
+
onDelete={() => handleDelete(type)}
|
|
1096
|
+
onCopyLink={() => handleCopyLink(type.id)}
|
|
1097
|
+
data={type}
|
|
1098
|
+
/>
|
|
1099
|
+
))}
|
|
1100
|
+
</div>
|
|
1101
|
+
|
|
1102
|
+
<BmCustomTab
|
|
1103
|
+
value={activeTab}
|
|
1104
|
+
onValueChange={setActiveTab}
|
|
1105
|
+
tabs={tabs}
|
|
1106
|
+
className="event-types-tabs"
|
|
1107
|
+
/>
|
|
1108
|
+
|
|
1031
1109
|
<div style={{ width: '100%', maxWidth: '900px', margin: '2rem auto' }}>
|
|
1032
1110
|
<div style={{ maxWidth: 400, margin: '2rem auto' }}>
|
|
1033
1111
|
<BmDepartmentCard
|
|
@@ -1098,6 +1176,7 @@ const Chat = () => {
|
|
|
1098
1176
|
description="Schedule a 30-minute consultation with our healThcare specialists"
|
|
1099
1177
|
variant="booking"
|
|
1100
1178
|
withStripe
|
|
1179
|
+
imageSrc={imgs}
|
|
1101
1180
|
/>
|
|
1102
1181
|
</div>
|
|
1103
1182
|
<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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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,108 @@
|
|
|
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
|
+
display: inline-flex;
|
|
20
|
+
background-color: var(--color-muted, #f2f2f2);
|
|
21
|
+
color: var(--color-muted-foreground, #666);
|
|
22
|
+
align-items: center;
|
|
23
|
+
justify-content: center;
|
|
24
|
+
border-radius: var(--radius-lg, 12px);
|
|
25
|
+
padding: 4px 4px;
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
const TabsTriggerButton = styled.button`
|
|
29
|
+
display: inline-flex;
|
|
30
|
+
flex: 1;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: center;
|
|
33
|
+
gap: 6px;
|
|
34
|
+
border: 1px solid transparent;
|
|
35
|
+
border-radius: var(--radius-lg, 12px);
|
|
36
|
+
padding: 6px 12px;
|
|
37
|
+
font-size: 14px;
|
|
38
|
+
font-weight: 500;
|
|
39
|
+
white-space: nowrap;
|
|
40
|
+
transition: color 0.2s, box-shadow 0.2s, background-color 0.2s;
|
|
41
|
+
cursor: pointer;
|
|
42
|
+
|
|
43
|
+
${({ active }) =>
|
|
44
|
+
active
|
|
45
|
+
? css`
|
|
46
|
+
background-color: var(--color-card, #fff);
|
|
47
|
+
color: var(--color-foreground, #000);
|
|
48
|
+
border-color: var(--color-border, #ddd);
|
|
49
|
+
`
|
|
50
|
+
: css`
|
|
51
|
+
background-color: transparent;
|
|
52
|
+
color: var(--color-muted-foreground, #666);
|
|
53
|
+
`}
|
|
54
|
+
|
|
55
|
+
&:focus-visible {
|
|
56
|
+
outline: none;
|
|
57
|
+
border-color: var(--color-ring, #2684ff);
|
|
58
|
+
box-shadow: 0 0 0 3px rgba(38, 132, 255, 0.3);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
&:disabled {
|
|
62
|
+
pointer-events: none;
|
|
63
|
+
opacity: 0.5;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
svg {
|
|
67
|
+
flex-shrink: 0;
|
|
68
|
+
pointer-events: none;
|
|
69
|
+
width: 16px;
|
|
70
|
+
height: 16px;
|
|
71
|
+
}
|
|
72
|
+
`;
|
|
73
|
+
|
|
74
|
+
const IconWrapper = styled.span`
|
|
75
|
+
display: flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
justify-content: center;
|
|
78
|
+
`;
|
|
79
|
+
|
|
80
|
+
const BmCustomTab = ({ value, onValueChange, tabs = [], className }) => {
|
|
81
|
+
return (
|
|
82
|
+
<TabsContainer className={className}>
|
|
83
|
+
<TabsHeader>
|
|
84
|
+
<TabsList>
|
|
85
|
+
{tabs.map((tab) => {
|
|
86
|
+
const Icon = tab.icon;
|
|
87
|
+
return (
|
|
88
|
+
<TabsTriggerButton
|
|
89
|
+
key={tab.value}
|
|
90
|
+
active={value === tab.value}
|
|
91
|
+
onClick={() => onValueChange(tab.value)}
|
|
92
|
+
>
|
|
93
|
+
{Icon && (
|
|
94
|
+
<IconWrapper>
|
|
95
|
+
<Icon fontSize="small" />
|
|
96
|
+
</IconWrapper>
|
|
97
|
+
)}
|
|
98
|
+
<span>{tab.label}</span>
|
|
99
|
+
</TabsTriggerButton>
|
|
100
|
+
);
|
|
101
|
+
})}
|
|
102
|
+
</TabsList>
|
|
103
|
+
</TabsHeader>
|
|
104
|
+
</TabsContainer>
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
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,258 @@
|
|
|
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
|
+
|
|
12
|
+
const RowContainer = styled.div`
|
|
13
|
+
position: relative;
|
|
14
|
+
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
15
|
+
border-radius: 8px;
|
|
16
|
+
padding: 16px;
|
|
17
|
+
transition: all 0.2s;
|
|
18
|
+
display: flex;
|
|
19
|
+
justify-content: space-between;
|
|
20
|
+
align-items: flex-start;
|
|
21
|
+
cursor: pointer;
|
|
22
|
+
gap: 12px;
|
|
23
|
+
|
|
24
|
+
&:hover {
|
|
25
|
+
border-color: rgba(0, 0, 0, 0.2);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
${({ isActive }) =>
|
|
29
|
+
!isActive &&
|
|
30
|
+
css`
|
|
31
|
+
opacity: 0.7;
|
|
32
|
+
`}
|
|
33
|
+
|
|
34
|
+
@media (max-width: 600px) {
|
|
35
|
+
flex-direction: column;
|
|
36
|
+
align-items: flex-start;
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
const ColorBar = styled.div`
|
|
41
|
+
position: absolute;
|
|
42
|
+
top: 0;
|
|
43
|
+
left: 0;
|
|
44
|
+
width: 4px;
|
|
45
|
+
height: 100%;
|
|
46
|
+
border-top-left-radius: 8px;
|
|
47
|
+
border-bottom-left-radius: 8px;
|
|
48
|
+
background-color: ${(props) => props.color || '#ccc'};
|
|
49
|
+
`;
|
|
50
|
+
|
|
51
|
+
const InfoContainer = styled.div`
|
|
52
|
+
flex: 1;
|
|
53
|
+
padding-left: 12px;
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
const TitleRow = styled.div`
|
|
57
|
+
display: flex;
|
|
58
|
+
align-items: center;
|
|
59
|
+
gap: 8px;
|
|
60
|
+
flex-wrap: wrap;
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
const Name = styled.h3`
|
|
64
|
+
margin: 0;
|
|
65
|
+
font-weight: 500;
|
|
66
|
+
`;
|
|
67
|
+
|
|
68
|
+
const Badge = styled.span`
|
|
69
|
+
display: inline-flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
padding: 2px 6px;
|
|
72
|
+
font-size: 12px;
|
|
73
|
+
border-radius: 4px;
|
|
74
|
+
${({ variant }) =>
|
|
75
|
+
variant === 'outline'
|
|
76
|
+
? css`
|
|
77
|
+
border: 1px solid #d1d5db;
|
|
78
|
+
color: #4b5563;
|
|
79
|
+
background-color: rgba(0, 0, 0, 0.04);
|
|
80
|
+
`
|
|
81
|
+
: css`
|
|
82
|
+
background-color: #e6f4ea;
|
|
83
|
+
color: #166534;
|
|
84
|
+
border: none;
|
|
85
|
+
`}
|
|
86
|
+
`;
|
|
87
|
+
|
|
88
|
+
const Description = styled.p`
|
|
89
|
+
margin-top: 4px;
|
|
90
|
+
font-size: 0.9rem;
|
|
91
|
+
color: #6b7280;
|
|
92
|
+
overflow: hidden;
|
|
93
|
+
text-overflow: ellipsis;
|
|
94
|
+
white-space: nowrap;
|
|
95
|
+
`;
|
|
96
|
+
|
|
97
|
+
const MetaRow = styled.div`
|
|
98
|
+
display: flex;
|
|
99
|
+
flex-wrap: wrap;
|
|
100
|
+
gap: 16px;
|
|
101
|
+
margin-top: 12px;
|
|
102
|
+
`;
|
|
103
|
+
|
|
104
|
+
const MetaItem = styled.div`
|
|
105
|
+
display: flex;
|
|
106
|
+
align-items: center;
|
|
107
|
+
font-size: 0.875rem;
|
|
108
|
+
color: #374151;
|
|
109
|
+
|
|
110
|
+
svg {
|
|
111
|
+
margin-right: 4px;
|
|
112
|
+
width: 18px;
|
|
113
|
+
height: 18px;
|
|
114
|
+
}
|
|
115
|
+
`;
|
|
116
|
+
|
|
117
|
+
const ActionButtons = styled.div`
|
|
118
|
+
display: flex;
|
|
119
|
+
align-items: center;
|
|
120
|
+
gap: 4px;
|
|
121
|
+
opacity: 0;
|
|
122
|
+
transition: opacity 0.2s;
|
|
123
|
+
${RowContainer}:hover & {
|
|
124
|
+
opacity: 1;
|
|
125
|
+
}
|
|
126
|
+
`;
|
|
127
|
+
|
|
128
|
+
const IconButton = styled.button`
|
|
129
|
+
background: transparent;
|
|
130
|
+
border: none;
|
|
131
|
+
padding: 4px;
|
|
132
|
+
cursor: pointer;
|
|
133
|
+
color: ${({ iconColor }) => iconColor || '#111827'};
|
|
134
|
+
transition: color 0.2s;
|
|
135
|
+
|
|
136
|
+
&:hover {
|
|
137
|
+
color: #111827;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
&.danger:hover {
|
|
141
|
+
color: #dc2626;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@media (max-width: 600px) {
|
|
145
|
+
padding: 2px;
|
|
146
|
+
}
|
|
147
|
+
`;
|
|
148
|
+
|
|
149
|
+
const BmHorizontalCard = ({
|
|
150
|
+
onView,
|
|
151
|
+
onDelete,
|
|
152
|
+
onCopyLink,
|
|
153
|
+
name,
|
|
154
|
+
description,
|
|
155
|
+
price,
|
|
156
|
+
color,
|
|
157
|
+
isActive,
|
|
158
|
+
location,
|
|
159
|
+
paymentSettings,
|
|
160
|
+
selectedResources,
|
|
161
|
+
address,
|
|
162
|
+
duration,
|
|
163
|
+
guest_limit,
|
|
164
|
+
}) => {
|
|
165
|
+
return (
|
|
166
|
+
<RowContainer isActive={isActive}>
|
|
167
|
+
<ColorBar color={color} />
|
|
168
|
+
|
|
169
|
+
<InfoContainer>
|
|
170
|
+
<TitleRow>
|
|
171
|
+
<Name>{name}</Name>
|
|
172
|
+
|
|
173
|
+
{!isActive && <Badge variant="outline">Inactive</Badge>}
|
|
174
|
+
|
|
175
|
+
{paymentSettings?.requirePayment && (
|
|
176
|
+
<Badge>
|
|
177
|
+
<AttachMoneyIcon fontSize="small" />
|
|
178
|
+
Payment Required
|
|
179
|
+
</Badge>
|
|
180
|
+
)}
|
|
181
|
+
</TitleRow>
|
|
182
|
+
|
|
183
|
+
<Description>{description}</Description>
|
|
184
|
+
|
|
185
|
+
<MetaRow>
|
|
186
|
+
<MetaItem>
|
|
187
|
+
<AccessTimeIcon fontSize="small" />
|
|
188
|
+
<span>{duration} mins</span>
|
|
189
|
+
</MetaItem>
|
|
190
|
+
<MetaItem>
|
|
191
|
+
<AttachMoneyIcon fontSize="small" />
|
|
192
|
+
<span>{price === 0 ? 'Free' : `$${price}`}</span>
|
|
193
|
+
</MetaItem>
|
|
194
|
+
<MetaItem>
|
|
195
|
+
<LocationOnOutlinedIcon fontSize="small" />
|
|
196
|
+
<span>
|
|
197
|
+
{location}
|
|
198
|
+
{location === 'physical' && address
|
|
199
|
+
? ` (${address.split(',')[0]}...)`
|
|
200
|
+
: ''}
|
|
201
|
+
</span>
|
|
202
|
+
</MetaItem>
|
|
203
|
+
{guest_limit && (
|
|
204
|
+
<MetaItem>
|
|
205
|
+
<Groups2OutlinedIcon fontSize="small" />
|
|
206
|
+
<span>
|
|
207
|
+
Max {guest_limit} attendee{guest_limit > 1 ? 's' : ''}
|
|
208
|
+
</span>
|
|
209
|
+
</MetaItem>
|
|
210
|
+
)}
|
|
211
|
+
{selectedResources && selectedResources.length > 0 && (
|
|
212
|
+
<MetaItem>
|
|
213
|
+
<PeopleAltOutlinedIcon fontSize="small" />
|
|
214
|
+
<span>
|
|
215
|
+
{selectedResources.length} resource
|
|
216
|
+
{selectedResources.length > 1 ? 's' : ''}
|
|
217
|
+
</span>
|
|
218
|
+
</MetaItem>
|
|
219
|
+
)}
|
|
220
|
+
</MetaRow>
|
|
221
|
+
</InfoContainer>
|
|
222
|
+
|
|
223
|
+
<ActionButtons>
|
|
224
|
+
<IconButton
|
|
225
|
+
onClick={(e) => {
|
|
226
|
+
e.stopPropagation();
|
|
227
|
+
onCopyLink();
|
|
228
|
+
}}
|
|
229
|
+
title="Copy shareable link"
|
|
230
|
+
>
|
|
231
|
+
<LinkIcon fontSize="small" />
|
|
232
|
+
</IconButton>
|
|
233
|
+
<IconButton
|
|
234
|
+
onClick={(e) => {
|
|
235
|
+
e.stopPropagation();
|
|
236
|
+
onView();
|
|
237
|
+
}}
|
|
238
|
+
title="Edit appointment type"
|
|
239
|
+
>
|
|
240
|
+
<EditIcon fontSize="small" />
|
|
241
|
+
</IconButton>
|
|
242
|
+
<IconButton
|
|
243
|
+
iconColor="#dc2626"
|
|
244
|
+
className="danger"
|
|
245
|
+
onClick={(e) => {
|
|
246
|
+
e.stopPropagation();
|
|
247
|
+
onDelete();
|
|
248
|
+
}}
|
|
249
|
+
title="Delete appointment type"
|
|
250
|
+
>
|
|
251
|
+
<DeleteIcon fontSize="small" />
|
|
252
|
+
</IconButton>
|
|
253
|
+
</ActionButtons>
|
|
254
|
+
</RowContainer>
|
|
255
|
+
);
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
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 };
|