mautourco-components 0.2.74 → 0.2.76
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/molecules/FeatureRow/FeatureRow.css +4 -0
- package/dist/components/molecules/FeatureRow/FeatureRow.d.ts +2 -0
- package/dist/components/molecules/FeatureRow/FeatureRow.js +10 -4
- package/dist/components/organisms/CarBookingCard/CarBookingCard.js +38 -2
- package/package.json +1 -1
- package/src/components/molecules/FeatureRow/FeatureRow.css +4 -0
- package/src/components/molecules/FeatureRow/FeatureRow.tsx +14 -3
- package/src/components/organisms/CarBookingCard/CarBookingCard.tsx +54 -10
|
@@ -10,6 +10,8 @@ export interface FeatureRowProps {
|
|
|
10
10
|
icon?: IconName;
|
|
11
11
|
/** Size of the icon */
|
|
12
12
|
iconSize?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
13
|
+
/** State variant: 'not-applicable' applies error/danger styling to the value */
|
|
14
|
+
state?: 'default' | 'not-applicable';
|
|
13
15
|
/** Additional CSS classes */
|
|
14
16
|
className?: string;
|
|
15
17
|
}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import Icon from '../../atoms/Icon/Icon';
|
|
3
2
|
import Divider from '../../atoms/Divider/Divider';
|
|
3
|
+
import Icon from '../../atoms/Icon/Icon';
|
|
4
4
|
import './FeatureRow.css';
|
|
5
5
|
var FeatureRow = function (_a) {
|
|
6
|
-
var label = _a.label, value = _a.value, icon = _a.icon, _b = _a.iconSize, iconSize = _b === void 0 ? 'sm' : _b, _c = _a.className, className =
|
|
6
|
+
var label = _a.label, value = _a.value, icon = _a.icon, _b = _a.iconSize, iconSize = _b === void 0 ? 'sm' : _b, _c = _a.state, state = _c === void 0 ? 'default' : _c, _d = _a.className, className = _d === void 0 ? '' : _d;
|
|
7
7
|
var baseClass = 'feature-row';
|
|
8
|
-
var classes = [
|
|
9
|
-
|
|
8
|
+
var classes = [
|
|
9
|
+
baseClass,
|
|
10
|
+
state === 'not-applicable' ? "".concat(baseClass, "--not-applicable") : '',
|
|
11
|
+
className,
|
|
12
|
+
]
|
|
13
|
+
.filter(Boolean)
|
|
14
|
+
.join(' ');
|
|
15
|
+
return (_jsxs("div", { className: classes, children: [_jsx("div", { className: "feature-row__label", children: _jsx("span", { className: "feature-row__label-text", children: label }) }), _jsx(Divider, { orientation: "vertical", className: "feature-row__divider" }), _jsxs("div", { className: "feature-row__value", children: [icon && (_jsx(Icon, { name: icon, size: iconSize, className: "feature-row__value-icon" })), _jsx("span", { className: "feature-row__value-text ".concat(state === 'not-applicable' ? 'feature-row__value-text--not-applicable' : '').trim(), children: value })] })] }));
|
|
10
16
|
};
|
|
11
17
|
export default FeatureRow;
|
|
@@ -10,6 +10,7 @@ var __assign = (this && this.__assign) || function () {
|
|
|
10
10
|
return __assign.apply(this, arguments);
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
import { useState } from 'react';
|
|
13
14
|
import Button from '../../atoms/Button/Button';
|
|
14
15
|
import Divider from '../../atoms/Divider/Divider';
|
|
15
16
|
import DropdownInput from '../../atoms/Inputs/DropdownInput/DropdownInput';
|
|
@@ -19,13 +20,48 @@ import './CarBookingCard.css';
|
|
|
19
20
|
var CarBookingCard = function (_a) {
|
|
20
21
|
var _b;
|
|
21
22
|
var imageSrc = _a.imageSrc, title = _a.title, _c = _a.size, size = _c === void 0 ? 'large' : _c, _d = _a.state, state = _d === void 0 ? 'default' : _d, _e = _a.type, type = _e === void 0 ? 'default' : _e, features = _a.features, infoText = _a.infoText, _f = _a.priceTitle, priceTitle = _f === void 0 ? 'Price breakdown' : _f, _g = _a.priceRows, priceRows = _g === void 0 ? [] : _g, showSupplement = _a.showSupplement, supplementMessage = _a.supplementMessage, _h = _a.supplementLabel, supplementLabel = _h === void 0 ? 'Supplement' : _h, _j = _a.supplementPlaceholder, supplementPlaceholder = _j === void 0 ? 'Select a supplement' : _j, supplementValue = _a.supplementValue, _k = _a.supplementState, supplementState = _k === void 0 ? 'default' : _k, _l = _a.supplementOptions, supplementOptions = _l === void 0 ? [] : _l, onSupplementSelect = _a.onSupplementSelect, totalPrice = _a.totalPrice, _m = _a.totalPriceLabel, totalPriceLabel = _m === void 0 ? 'Total price' : _m, ctaLabel = _a.ctaLabel, ctaButtonProps = _a.ctaButtonProps, onCtaClick = _a.onCtaClick, _o = _a.readonly, readonly = _o === void 0 ? false : _o, _p = _a.className, className = _p === void 0 ? '' : _p;
|
|
23
|
+
var _q = useState(state === 'selected'), isSelected = _q[0], setIsSelected = _q[1];
|
|
24
|
+
var _r = useState(false), isHovered = _r[0], setIsHovered = _r[1];
|
|
22
25
|
var resolvedShowSupplement = showSupplement !== null && showSupplement !== void 0 ? showSupplement : Boolean(supplementLabel || supplementPlaceholder || supplementOptions.length > 0);
|
|
23
26
|
var resolvedSupplementState = supplementMessage ? 'disabled' : supplementState;
|
|
27
|
+
// Handle CTA click: toggle between "Add to quote" and "Selected"
|
|
28
|
+
var handleCtaClick = function (e) {
|
|
29
|
+
setIsSelected(!isSelected);
|
|
30
|
+
onCtaClick === null || onCtaClick === void 0 ? void 0 : onCtaClick(e);
|
|
31
|
+
};
|
|
32
|
+
// Determine button state based on selection and hover
|
|
33
|
+
var shouldShowRemove = isSelected && isHovered;
|
|
34
|
+
var shouldShowSelected = isSelected && !isHovered;
|
|
35
|
+
var resolvedCtaLabel = shouldShowRemove
|
|
36
|
+
? 'Remove'
|
|
37
|
+
: shouldShowSelected
|
|
38
|
+
? 'Selected'
|
|
39
|
+
: ctaLabel;
|
|
40
|
+
var resolvedCtaButtonProps = shouldShowRemove
|
|
41
|
+
? {
|
|
42
|
+
variant: 'destructive',
|
|
43
|
+
size: 'sm',
|
|
44
|
+
leadingIcon: 'close',
|
|
45
|
+
iconSize: 'sm',
|
|
46
|
+
}
|
|
47
|
+
: shouldShowSelected
|
|
48
|
+
? {
|
|
49
|
+
variant: 'secondary',
|
|
50
|
+
size: 'sm',
|
|
51
|
+
leadingIcon: 'check-circle',
|
|
52
|
+
iconSize: 'sm',
|
|
53
|
+
}
|
|
54
|
+
: {
|
|
55
|
+
variant: 'primary',
|
|
56
|
+
size: 'sm',
|
|
57
|
+
};
|
|
58
|
+
// Update card state class based on selection
|
|
59
|
+
var resolvedState = isSelected ? 'selected' : state;
|
|
24
60
|
var baseClass = 'car-booking-card';
|
|
25
61
|
var classes = [
|
|
26
62
|
baseClass,
|
|
27
63
|
"".concat(baseClass, "--").concat(size),
|
|
28
|
-
"".concat(baseClass, "--").concat(
|
|
64
|
+
"".concat(baseClass, "--").concat(resolvedState),
|
|
29
65
|
"".concat(baseClass, "--").concat(type),
|
|
30
66
|
readonly ? "".concat(baseClass, "--readonly") : '',
|
|
31
67
|
className,
|
|
@@ -35,6 +71,6 @@ var CarBookingCard = function (_a) {
|
|
|
35
71
|
return (_jsxs("article", { className: classes, children: [_jsx("div", { className: "car-booking-card__image-wrap", children: _jsx("img", { className: "car-booking-card__image", src: imageSrc, alt: "" }) }), _jsx("div", { className: "car-booking-card__active-divider" }), _jsxs("div", { className: "car-booking-card__body", children: [_jsxs("section", { className: "car-booking-card__section car-booking-card__section--content", children: [_jsxs("div", { className: "car-booking-card__title", children: [_jsx("span", { className: "car-booking-card__title-marker", "aria-hidden": "true" }), _jsx(Heading, { level: 4, variant: "bold", color: "accent", className: "car-booking-card__title-text", children: title })] }), _jsx("div", { className: "car-booking-card__features", children: features.map(function (feature, idx) {
|
|
36
72
|
var _a;
|
|
37
73
|
return (_jsx(FeatureRow, __assign({}, feature, { className: "car-booking-card__feature-row ".concat((_a = feature.className) !== null && _a !== void 0 ? _a : '').trim() }), "".concat(feature.label, "-").concat(idx)));
|
|
38
|
-
}) }), infoText && !readonly && (_jsxs("div", { className: "car-booking-card__info", children: [_jsx("span", { className: "car-booking-card__info-icon", "aria-hidden": "true", children: "i" }), _jsx(Text, { size: "sm", leading: "5", variant: "regular", color: "default", className: "car-booking-card__info-text", children: infoText })] }))] }), resolvedShowSupplement && !readonly && (_jsxs("section", { className: "car-booking-card__section car-booking-card__section--supplement", children: [_jsx(Divider, { variant: "dashed", className: "car-booking-card__dashed-divider" }), _jsxs("div", { className: "car-booking-card__supplement-header", children: [_jsx(Text, { as: "h3", size: "md", variant: "bold", leading: "none", color: "default", className: "car-booking-card__section-title", children: supplementLabel }), supplementMessage && (_jsx(Text, { as: "p", size: "sm", leading: "5", variant: "regular", className: "car-booking-card__supplement-message", children: supplementMessage }))] }), readonly ? (_jsx(Text, { size: "sm", leading: "5", variant: "regular", color: supplementValue ? "default" : "subtle", className: "car-booking-card__supplement-value", children: supplementValue || supplementPlaceholder })) : (_jsx(DropdownInput, { placeholder: supplementPlaceholder, value: supplementValue, state: resolvedSupplementState, options: supplementOptions, onSelect: onSupplementSelect }))] })), priceRows.length > 0 && !readonly && (_jsxs("section", { className: "car-booking-card__section car-booking-card__section--price", children: [_jsx(Divider, { variant: "dashed", className: "car-booking-card__dashed-divider" }), _jsxs("div", { className: "car-booking-card__price-content", children: [_jsx(Text, { as: "h3", size: "md", variant: "bold", leading: "none", color: "default", className: "car-booking-card__section-title", children: priceTitle }), _jsx("div", { className: "car-booking-card__price-rows", children: priceRows.map(function (row, idx) { return (_jsxs("div", { className: "car-booking-card__price-row", children: [_jsx(Text, { size: "sm", leading: "5", variant: "regular", color: "subtle", className: "car-booking-card__price-label", children: row.label }), _jsx(Text, { size: "sm", leading: "5", variant: "bold", color: "subtle", className: "car-booking-card__price-value", children: row.value })] }, "".concat(row.label, "-").concat(idx))); }) })] }), _jsx(Divider, { variant: "dashed", className: "car-booking-card__dashed-divider" })] })), !readonly && _jsxs("footer", { className: "car-booking-card__footer", children: [_jsxs("div", { className: "car-booking-card__total", children: [_jsx(Text, { size: "base", variant: "bold", color: "accent", className: "car-booking-card__total-price", children: totalPrice }), _jsx(Text, { size: "sm", variant: "regular", color: "subtle", className: "car-booking-card__total-label", children: totalPriceLabel })] }), !readonly && (_jsx(
|
|
74
|
+
}) }), infoText && !readonly && (_jsxs("div", { className: "car-booking-card__info", children: [_jsx("span", { className: "car-booking-card__info-icon", "aria-hidden": "true", children: "i" }), _jsx(Text, { size: "sm", leading: "5", variant: "regular", color: "default", className: "car-booking-card__info-text", children: infoText })] }))] }), resolvedShowSupplement && !readonly && (_jsxs("section", { className: "car-booking-card__section car-booking-card__section--supplement", children: [_jsx(Divider, { variant: "dashed", className: "car-booking-card__dashed-divider" }), _jsxs("div", { className: "car-booking-card__supplement-header", children: [_jsx(Text, { as: "h3", size: "md", variant: "bold", leading: "none", color: "default", className: "car-booking-card__section-title", children: supplementLabel }), supplementMessage && (_jsx(Text, { as: "p", size: "sm", leading: "5", variant: "regular", className: "car-booking-card__supplement-message", children: supplementMessage }))] }), readonly ? (_jsx(Text, { size: "sm", leading: "5", variant: "regular", color: supplementValue ? "default" : "subtle", className: "car-booking-card__supplement-value", children: supplementValue || supplementPlaceholder })) : (_jsx(DropdownInput, { placeholder: supplementPlaceholder, value: supplementValue, state: resolvedSupplementState, options: supplementOptions, onSelect: onSupplementSelect }))] })), priceRows.length > 0 && !readonly && (_jsxs("section", { className: "car-booking-card__section car-booking-card__section--price", children: [_jsx(Divider, { variant: "dashed", className: "car-booking-card__dashed-divider" }), _jsxs("div", { className: "car-booking-card__price-content", children: [_jsx(Text, { as: "h3", size: "md", variant: "bold", leading: "none", color: "default", className: "car-booking-card__section-title", children: priceTitle }), _jsx("div", { className: "car-booking-card__price-rows", children: priceRows.map(function (row, idx) { return (_jsxs("div", { className: "car-booking-card__price-row", children: [_jsx(Text, { size: "sm", leading: "5", variant: "regular", color: "subtle", className: "car-booking-card__price-label", children: row.label }), _jsx(Text, { size: "sm", leading: "5", variant: "bold", color: "subtle", className: "car-booking-card__price-value", children: row.value })] }, "".concat(row.label, "-").concat(idx))); }) })] }), _jsx(Divider, { variant: "dashed", className: "car-booking-card__dashed-divider" })] })), !readonly && _jsxs("footer", { className: "car-booking-card__footer", children: [_jsxs("div", { className: "car-booking-card__total", children: [_jsx(Text, { size: "base", variant: "bold", color: "accent", className: "car-booking-card__total-price", children: totalPrice }), _jsx(Text, { size: "sm", variant: "regular", color: "subtle", className: "car-booking-card__total-label", children: totalPriceLabel })] }), !readonly && (_jsx("div", { onMouseEnter: function () { return setIsHovered(true); }, onMouseLeave: function () { return setIsHovered(false); }, className: "car-booking-card__cta-wrapper", children: _jsx(Button, __assign({}, resolvedCtaButtonProps, { onClick: handleCtaClick, className: "car-booking-card__cta ".concat((_b = resolvedCtaButtonProps === null || resolvedCtaButtonProps === void 0 ? void 0 : resolvedCtaButtonProps.className) !== null && _b !== void 0 ? _b : '').trim(), children: resolvedCtaLabel })) }))] })] })] }));
|
|
39
75
|
};
|
|
40
76
|
export default CarBookingCard;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import Icon, { IconName } from '../../atoms/Icon/Icon';
|
|
3
2
|
import Divider from '../../atoms/Divider/Divider';
|
|
3
|
+
import Icon, { IconName } from '../../atoms/Icon/Icon';
|
|
4
4
|
import './FeatureRow.css';
|
|
5
5
|
|
|
6
6
|
export interface FeatureRowProps {
|
|
@@ -12,6 +12,8 @@ export interface FeatureRowProps {
|
|
|
12
12
|
icon?: IconName;
|
|
13
13
|
/** Size of the icon */
|
|
14
14
|
iconSize?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
15
|
+
/** State variant: 'not-applicable' applies error/danger styling to the value */
|
|
16
|
+
state?: 'default' | 'not-applicable';
|
|
15
17
|
/** Additional CSS classes */
|
|
16
18
|
className?: string;
|
|
17
19
|
}
|
|
@@ -21,10 +23,17 @@ const FeatureRow: React.FC<FeatureRowProps> = ({
|
|
|
21
23
|
value,
|
|
22
24
|
icon,
|
|
23
25
|
iconSize = 'sm',
|
|
26
|
+
state = 'default',
|
|
24
27
|
className = '',
|
|
25
28
|
}) => {
|
|
26
29
|
const baseClass = 'feature-row';
|
|
27
|
-
const classes = [
|
|
30
|
+
const classes = [
|
|
31
|
+
baseClass,
|
|
32
|
+
state === 'not-applicable' ? `${baseClass}--not-applicable` : '',
|
|
33
|
+
className,
|
|
34
|
+
]
|
|
35
|
+
.filter(Boolean)
|
|
36
|
+
.join(' ');
|
|
28
37
|
|
|
29
38
|
return (
|
|
30
39
|
<div className={classes}>
|
|
@@ -36,7 +45,9 @@ const FeatureRow: React.FC<FeatureRowProps> = ({
|
|
|
36
45
|
{icon && (
|
|
37
46
|
<Icon name={icon} size={iconSize} className="feature-row__value-icon" />
|
|
38
47
|
)}
|
|
39
|
-
<span className=
|
|
48
|
+
<span className={`feature-row__value-text ${state === 'not-applicable' ? 'feature-row__value-text--not-applicable' : ''}`.trim()}>
|
|
49
|
+
{value}
|
|
50
|
+
</span>
|
|
40
51
|
</div>
|
|
41
52
|
</div>
|
|
42
53
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
import Button, { ButtonProps } from '../../atoms/Button/Button';
|
|
3
3
|
import Divider from '../../atoms/Divider/Divider';
|
|
4
4
|
import DropdownInput from '../../atoms/Inputs/DropdownInput/DropdownInput';
|
|
@@ -90,16 +90,56 @@ const CarBookingCard: React.FC<CarBookingCardProps> = ({
|
|
|
90
90
|
readonly = false,
|
|
91
91
|
className = '',
|
|
92
92
|
}) => {
|
|
93
|
+
const [isSelected, setIsSelected] = useState(state === 'selected');
|
|
94
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
95
|
+
|
|
93
96
|
const resolvedShowSupplement =
|
|
94
97
|
showSupplement ?? Boolean(supplementLabel || supplementPlaceholder || supplementOptions.length > 0);
|
|
95
98
|
const resolvedSupplementState =
|
|
96
99
|
supplementMessage ? 'disabled' : supplementState;
|
|
97
100
|
|
|
101
|
+
// Handle CTA click: toggle between "Add to quote" and "Selected"
|
|
102
|
+
const handleCtaClick = (e: React.MouseEvent<HTMLButtonElement>) => {
|
|
103
|
+
setIsSelected(!isSelected);
|
|
104
|
+
onCtaClick?.(e);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Determine button state based on selection and hover
|
|
108
|
+
const shouldShowRemove = isSelected && isHovered;
|
|
109
|
+
const shouldShowSelected = isSelected && !isHovered;
|
|
110
|
+
|
|
111
|
+
const resolvedCtaLabel = shouldShowRemove
|
|
112
|
+
? 'Remove'
|
|
113
|
+
: shouldShowSelected
|
|
114
|
+
? 'Selected'
|
|
115
|
+
: ctaLabel;
|
|
116
|
+
|
|
117
|
+
const resolvedCtaButtonProps: Omit<ButtonProps, 'children'> = shouldShowRemove
|
|
118
|
+
? {
|
|
119
|
+
variant: 'destructive',
|
|
120
|
+
size: 'sm',
|
|
121
|
+
leadingIcon: 'close',
|
|
122
|
+
iconSize: 'sm',
|
|
123
|
+
}
|
|
124
|
+
: shouldShowSelected
|
|
125
|
+
? {
|
|
126
|
+
variant: 'secondary',
|
|
127
|
+
size: 'sm',
|
|
128
|
+
leadingIcon: 'check-circle',
|
|
129
|
+
iconSize: 'sm',
|
|
130
|
+
}
|
|
131
|
+
: {
|
|
132
|
+
variant: 'primary',
|
|
133
|
+
size: 'sm',
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// Update card state class based on selection
|
|
137
|
+
const resolvedState = isSelected ? 'selected' : state;
|
|
98
138
|
const baseClass = 'car-booking-card';
|
|
99
139
|
const classes = [
|
|
100
140
|
baseClass,
|
|
101
141
|
`${baseClass}--${size}`,
|
|
102
|
-
`${baseClass}--${
|
|
142
|
+
`${baseClass}--${resolvedState}`,
|
|
103
143
|
`${baseClass}--${type}`,
|
|
104
144
|
readonly ? `${baseClass}--readonly` : '',
|
|
105
145
|
className,
|
|
@@ -236,15 +276,19 @@ const CarBookingCard: React.FC<CarBookingCardProps> = ({
|
|
|
236
276
|
</div>
|
|
237
277
|
|
|
238
278
|
{!readonly && (
|
|
239
|
-
<
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
onClick={onCtaClick}
|
|
244
|
-
className={`car-booking-card__cta ${ctaButtonProps?.className ?? ''}`.trim()}
|
|
279
|
+
<div
|
|
280
|
+
onMouseEnter={() => setIsHovered(true)}
|
|
281
|
+
onMouseLeave={() => setIsHovered(false)}
|
|
282
|
+
className="car-booking-card__cta-wrapper"
|
|
245
283
|
>
|
|
246
|
-
|
|
247
|
-
|
|
284
|
+
<Button
|
|
285
|
+
{...resolvedCtaButtonProps}
|
|
286
|
+
onClick={handleCtaClick}
|
|
287
|
+
className={`car-booking-card__cta ${resolvedCtaButtonProps?.className ?? ''}`.trim()}
|
|
288
|
+
>
|
|
289
|
+
{resolvedCtaLabel}
|
|
290
|
+
</Button>
|
|
291
|
+
</div>
|
|
248
292
|
)}
|
|
249
293
|
</footer>}
|
|
250
294
|
</div>
|