mautourco-components 0.2.161 → 0.2.163

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.
Files changed (25) hide show
  1. package/dist/components/atoms/SelectedValue/SelectedValue.d.ts +3 -0
  2. package/dist/components/atoms/SelectedValue/SelectedValue.js +3 -5
  3. package/dist/components/molecules/DocketPrices/DocketPrices.js +0 -1
  4. package/dist/components/organisms/DialogSaveQuotation/DialogSaveQuotation.css +185 -0
  5. package/dist/components/organisms/DialogSaveQuotation/DialogSaveQuotation.d.ts +52 -0
  6. package/dist/components/organisms/DialogSaveQuotation/DialogSaveQuotation.js +164 -0
  7. package/dist/components/organisms/DialogSaveQuotation/index.d.ts +2 -0
  8. package/dist/components/organisms/DialogSaveQuotation/index.js +1 -0
  9. package/dist/components/organisms/DialogSaveQuotation/save-quotation-schema.d.ts +8 -0
  10. package/dist/components/organisms/DialogSaveQuotation/save-quotation-schema.js +7 -0
  11. package/dist/index.d.ts +1 -0
  12. package/dist/index.js +1 -0
  13. package/dist/styles/components/forms.css +5 -5
  14. package/dist/styles/components/organism/docket.css +1 -0
  15. package/dist/styles/components/selected-value.css +24 -18
  16. package/package.json +1 -1
  17. package/src/components/atoms/SelectedValue/SelectedValue.tsx +7 -5
  18. package/src/components/molecules/DocketPrices/DocketPrices.tsx +0 -2
  19. package/src/components/organisms/DialogSaveQuotation/DialogSaveQuotation.css +181 -0
  20. package/src/components/organisms/DialogSaveQuotation/DialogSaveQuotation.tsx +410 -0
  21. package/src/components/organisms/DialogSaveQuotation/index.ts +6 -0
  22. package/src/components/organisms/DialogSaveQuotation/save-quotation-schema.ts +10 -0
  23. package/src/styles/components/forms.css +5 -5
  24. package/src/styles/components/organism/docket.css +1 -0
  25. package/src/styles/components/selected-value.css +21 -18
@@ -3,7 +3,10 @@ interface SelectedValueProps {
3
3
  value: string;
4
4
  className?: string;
5
5
  iconSize?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
6
+ /** Chip size - controls padding and gap (Figma: chip/spacing/lg = 16px, 4px, 4px) */
6
7
  size?: 'xs' | 'sm' | 'md' | 'lg';
8
+ /** Text size - defaults to same as size. Use 'md' for Figma body-md (16px, leading-24) */
9
+ textSize?: 'xs' | 'sm' | 'md' | 'lg';
7
10
  variant?: 'filled' | 'text';
8
11
  color?: 'accent' | 'neutral';
9
12
  onRemove?: () => void;
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import Icon from '../Icon/Icon';
3
3
  import { Text } from '../Typography/Typography';
4
4
  var SelectedValue = function (_a) {
5
- var value = _a.value, _b = _a.className, className = _b === void 0 ? '' : _b, _c = _a.iconSize, iconSize = _c === void 0 ? 'xs' : _c, _d = _a.size, size = _d === void 0 ? 'md' : _d, _e = _a.variant, variant = _e === void 0 ? 'filled' : _e, _f = _a.color, color = _f === void 0 ? 'accent' : _f, onRemove = _a.onRemove, onSelect = _a.onSelect;
5
+ var value = _a.value, _b = _a.className, className = _b === void 0 ? '' : _b, _c = _a.iconSize, iconSize = _c === void 0 ? 'xs' : _c, _d = _a.size, size = _d === void 0 ? 'md' : _d, textSize = _a.textSize, _e = _a.variant, variant = _e === void 0 ? 'filled' : _e, _f = _a.color, color = _f === void 0 ? 'accent' : _f, onRemove = _a.onRemove, onSelect = _a.onSelect;
6
6
  var handleRemove = function (event) {
7
7
  event.stopPropagation();
8
8
  if (onRemove) {
@@ -10,9 +10,7 @@ var SelectedValue = function (_a) {
10
10
  }
11
11
  };
12
12
  var classes = "selected-value selected-value--".concat(size, " selected-value--").concat(color, " selected-value--").concat(variant, " ").concat(className, " ").concat(onSelect ? 'cursor-pointer' : '').trim();
13
- var getTextSize = function () {
14
- return size; // Utilise directement la taille passée en prop
15
- };
16
- return (_jsxs("div", { className: classes, onClick: onSelect, children: [_jsx(Text, { size: getTextSize(), variant: "medium", leading: "4", className: "selected-value__text", children: value }), variant !== 'text' && onRemove && (_jsx("button", { type: "button", className: "selected-value__remove", onClick: handleRemove, "aria-label": "Remove ".concat(value), children: _jsx(Icon, { name: "close", size: iconSize, className: "selected-value__remove-icon" }) }))] }));
13
+ var effectiveTextSize = textSize !== null && textSize !== void 0 ? textSize : size;
14
+ return (_jsxs("div", { className: classes, onClick: onSelect, children: [_jsx(Text, { size: effectiveTextSize, variant: "medium", leading: "6", className: "selected-value__text", children: value }), variant !== 'text' && onRemove && (_jsx("button", { type: "button", className: "selected-value__remove", onClick: handleRemove, "aria-label": "Remove ".concat(value), children: _jsx(Icon, { name: "close", size: iconSize, className: "selected-value__remove-icon" }) }))] }));
17
15
  };
18
16
  export default SelectedValue;
@@ -15,7 +15,6 @@ export var DocketPrices = function (_a) {
15
15
  if (!prices || prices.length === 0) {
16
16
  return null;
17
17
  }
18
- console.log('prices', prices);
19
18
  return (_jsxs("div", { className: "docket-prices ".concat(className), children: [_jsx(Text, { variant: "bold", size: "sm", color: "default", className: "docket-prices__label", children: label }), _jsx("div", { className: "docket-prices__price-list", children: prices.map(function (price, index) { return (_jsxs(Text, { variant: "bold", size: "sm", color: "default", children: [price.Currency, " ", formatAmount(price.Amount)] }, index)); }) })] }));
20
19
  };
21
20
  export default DocketPrices;
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Do not edit directly, this file was auto-generated.
3
+ */
4
+
5
+ /* ===== DialogSaveQuotation - Tokens from Figma ===== */
6
+ /* Uses CSS variables from tokens.css */
7
+
8
+ .dialog-save-quotation {
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: var(--spacing-gap-gap-6, 24px);
12
+ }
13
+
14
+ /* Animated view wrapper (form vs success) */
15
+ .dialog-save-quotation__view {
16
+ display: flex;
17
+ flex-direction: column;
18
+ gap: var(--spacing-gap-gap-6, 24px);
19
+ width: 100%;
20
+ }
21
+
22
+ /* Selected quotes section - tags + select all */
23
+ .dialog-save-quotation__quotes-section {
24
+ display: flex;
25
+ padding: var(--spacing-gap-gap-4, 16px) 0 var(--spacing-gap-gap-2, 8px) 0;
26
+ justify-content: space-between;
27
+ align-items: flex-start;
28
+ gap: var(--spacing-gap-gap-4, 16px);
29
+ flex-wrap: wrap;
30
+ }
31
+
32
+ .dialog-save-quotation__quotes-list {
33
+ display: flex;
34
+ flex-wrap: wrap;
35
+ gap: var(--spacing-gap-gap-2, 8px);
36
+ flex: 1;
37
+ min-width: 0;
38
+ }
39
+
40
+ .dialog-save-quotation__select-all {
41
+ flex-shrink: 0;
42
+ }
43
+
44
+ /* All quotations section header */
45
+ .dialog-save-quotation__section-title {
46
+ font-family:
47
+ var(--font-font-family-body), 'Satoshi', 'Inter', 'Segoe UI', system-ui, sans-serif;
48
+ font-size: var(--font-size-text-base, 16px);
49
+ font-weight: var(--font-weight-font-bold, 700);
50
+ line-height: var(--font-leading-leading-md, 24px);
51
+ color: var(--color-text-default);
52
+ margin: 0;
53
+ }
54
+
55
+ /* Form fields grid */
56
+ .dialog-save-quotation__form {
57
+ display: flex;
58
+ flex-direction: column;
59
+ gap: var(--spacing-gap-gap-6, 24px);
60
+ }
61
+
62
+ .dialog-save-quotation__form-row {
63
+ display: grid;
64
+ grid-template-columns: repeat(3, 1fr);
65
+ gap: var(--spacing-gap-gap-4, 16px);
66
+ }
67
+
68
+ .dialog-save-quotation__form-row--single {
69
+ grid-template-columns: 1fr;
70
+ }
71
+
72
+ @media (max-width: 768px) {
73
+ .dialog-save-quotation__form-row {
74
+ grid-template-columns: 1fr;
75
+ }
76
+ }
77
+
78
+ /* Form field */
79
+ .dialog-save-quotation__field {
80
+ display: flex;
81
+ flex-direction: column;
82
+ gap: var(--spacing-gap-gap-2, 8px);
83
+ }
84
+
85
+ .dialog-save-quotation__label {
86
+ font-family:
87
+ var(--font-font-family-body), 'Satoshi', 'Inter', 'Segoe UI', system-ui, sans-serif;
88
+ font-size: var(--font-size-text-sm, 14px);
89
+ font-weight: var(--font-weight-font-medium, 500);
90
+ line-height: var(--font-leading-leading-sm, 20px);
91
+ color: var(--color-text-default);
92
+ }
93
+
94
+ .dialog-save-quotation__label--required::after {
95
+ content: ' *';
96
+ color: var(--color-text-state-error);
97
+ }
98
+
99
+ /* Disabled label – matches Figma / input design token */
100
+ .dialog-save-quotation__label--disabled {
101
+ color: var(--input-color-label-disabled, var(--color-text-state-disabled));
102
+ cursor: not-allowed;
103
+ }
104
+
105
+ .dialog-save-quotation__label--disabled.dialog-save-quotation__label--required::after {
106
+ color: var(--input-color-label-disabled, var(--color-text-state-disabled));
107
+ }
108
+
109
+ /* Form error message – displayed below the form when validation fails */
110
+ .dialog-save-quotation__error {
111
+ font-family:
112
+ var(--font-font-family-body), 'Satoshi', 'Inter', 'Segoe UI', system-ui, sans-serif;
113
+ font-size: var(--font-size-text-sm, 14px);
114
+ font-weight: var(--font-weight-font-regular, 400);
115
+ line-height: var(--font-leading-leading-sm, 20px);
116
+ color: var(--color-text-state-error, #dc2626);
117
+ margin: 0;
118
+ padding: var(--spacing-gap-gap-2, 8px) 0;
119
+ }
120
+
121
+ /* Footer - buttons full width, side by side */
122
+ .dialog-save-quotation__footer {
123
+ display: flex;
124
+ flex-direction: row;
125
+ align-items: stretch;
126
+ gap: var(--spacing-gap-gap-4, 16px);
127
+ padding: var(--spacing-gap-gap-2, 8px) 0 var(--spacing-gap-gap-4, 16px) 0;
128
+ width: 100%;
129
+ }
130
+
131
+ .dialog-save-quotation__footer > * {
132
+ flex: 1;
133
+ min-width: 0;
134
+ }
135
+
136
+ /* ===== Success state content (Figma 4700-366717 – Shared-flows) ===== */
137
+ .dialog-save-quotation__content {
138
+ display: flex;
139
+ flex-direction: column;
140
+ align-items: center;
141
+ gap: var(--spacing-gap-gap-4, 16px);
142
+ text-align: center;
143
+ padding: var(--spacing-gap-gap-2, 8px) 0 0;
144
+ }
145
+
146
+ .dialog-save-quotation__content-image-container {
147
+ display: flex;
148
+ align-items: center;
149
+ justify-content: center;
150
+ }
151
+
152
+ .dialog-save-quotation__content-image {
153
+ width: 150px;
154
+ height: 150px;
155
+ object-fit: contain;
156
+ }
157
+
158
+ .dialog-save-quotation__content-text {
159
+ display: flex;
160
+ flex-direction: column;
161
+ gap: var(--spacing-gap-gap-2, 8px);
162
+ }
163
+
164
+ .dialog-save-quotation__content-title {
165
+ color: var(--color-text-default, #262626);
166
+ text-align: center;
167
+
168
+ /* heading-sm/medium */
169
+ font-family: var(--font-font-family-heading, Satoshi);
170
+ font-size: var(--font-size-text-2xl, 24px);
171
+ font-style: normal;
172
+ font-weight: var(--font-weight-font-medium, 500);
173
+ line-height: var(--font-leading-leading-xl, 32px); /* 133.333% */
174
+ letter-spacing: var(--font-tracking-tracking-normal, 0);
175
+ }
176
+
177
+ .dialog-save-quotation__content-message {
178
+ font-family:
179
+ var(--font-font-family-body), 'Satoshi', 'Inter', 'Segoe UI', system-ui, sans-serif;
180
+ font-size: var(--font-size-text-sm, 14px);
181
+ font-weight: var(--font-weight-font-regular, 400);
182
+ line-height: var(--font-leading-leading-md, 24px);
183
+ color: var(--color-text-default, #262626);
184
+ margin: 0;
185
+ }
@@ -0,0 +1,52 @@
1
+ import './DialogSaveQuotation.css';
2
+ import { SaveQuotationSchema } from './save-quotation-schema';
3
+ export interface SaveQuotationQuote {
4
+ id: string;
5
+ name: string;
6
+ }
7
+ export interface DialogSaveQuotationProps {
8
+ /** Whether the dialog is open */
9
+ open: boolean;
10
+ /** Callback to control dialog open state */
11
+ setOpen: (open: boolean) => void;
12
+ /** List of quotations to save (displayed as removable chips) */
13
+ quotations: SaveQuotationQuote[];
14
+ /** Callback when form is submitted */
15
+ onSubmit: (data: {
16
+ selectedQuotationIds: string[];
17
+ formData: SaveQuotationSchema;
18
+ }) => void;
19
+ /** Callback when the book now button is clicked */
20
+ onHandleBookNow?: () => void;
21
+ /** Callback when the view on quotation grid button is clicked */
22
+ onHandleViewOnQuotationGrid?: () => void;
23
+ /** Optional default values for the form */
24
+ defaultValues?: Partial<SaveQuotationSchema>;
25
+ /** Which form inputs to disable. Omit or set to false to keep an input enabled. */
26
+ disabledInputs?: Partial<Record<keyof SaveQuotationSchema, boolean>>;
27
+ /** Whether the form is loading */
28
+ loading?: boolean;
29
+ /** Whether the form is successful */
30
+ successful?: boolean;
31
+ /** The error message to display */
32
+ errorMessage?: string;
33
+ /** The image to display when the form is successful */
34
+ imgSuccess?: string;
35
+ /** The image to display */
36
+ imgSuccessAlt?: string;
37
+ }
38
+ /**
39
+ * DialogSaveQuotation - Modal to save quotations with agent and quotation details.
40
+ * Based on Figma "Save quotation" design with tokens.
41
+ *
42
+ * @example
43
+ * ```tsx
44
+ * <DialogSaveQuotation
45
+ * open={open}
46
+ * setOpen={setOpen}
47
+ * quotations={[{ id: '1', name: 'Quote 1' }]}
48
+ * onSubmit={(data) => console.log(data)}
49
+ * />
50
+ * ```
51
+ */
52
+ export declare function DialogSaveQuotation(props: DialogSaveQuotationProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,164 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
13
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
14
+ if (ar || !(i in from)) {
15
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
16
+ ar[i] = from[i];
17
+ }
18
+ }
19
+ return to.concat(ar || Array.prototype.slice.call(from));
20
+ };
21
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
22
+ import { AnimatePresence } from 'motion/react';
23
+ import * as motion from 'motion/react-m';
24
+ import { useEffect, useMemo, useState } from 'react';
25
+ import Button from '../../atoms/Button/Button';
26
+ import Checkbox from '../../atoms/Checkbox/Checkbox';
27
+ import Input from '../../atoms/Inputs/Input/Input';
28
+ import SelectedValue from '../../atoms/SelectedValue/SelectedValue';
29
+ import { Text } from '../../atoms/Typography/Typography';
30
+ import { DialogBookingConfirm } from '../DialogBookingConfirm';
31
+ import './DialogSaveQuotation.css';
32
+ import { saveQuotationSchema } from './save-quotation-schema';
33
+ /**
34
+ * DialogSaveQuotation - Modal to save quotations with agent and quotation details.
35
+ * Based on Figma "Save quotation" design with tokens.
36
+ *
37
+ * @example
38
+ * ```tsx
39
+ * <DialogSaveQuotation
40
+ * open={open}
41
+ * setOpen={setOpen}
42
+ * quotations={[{ id: '1', name: 'Quote 1' }]}
43
+ * onSubmit={(data) => console.log(data)}
44
+ * />
45
+ * ```
46
+ */
47
+ export function DialogSaveQuotation(props) {
48
+ var _a, _b, _c, _d;
49
+ var open = props.open, setOpen = props.setOpen, quotations = props.quotations, onSubmit = props.onSubmit, defaultValues = props.defaultValues, disabledInputs = props.disabledInputs, errorMessage = props.errorMessage, successful = props.successful, loading = props.loading, imgSuccess = props.imgSuccess, imgSuccessAlt = props.imgSuccessAlt, onHandleBookNow = props.onHandleBookNow, onHandleViewOnQuotationGrid = props.onHandleViewOnQuotationGrid;
50
+ var _e = useState(quotations), remainingQuotations = _e[0], setRemainingQuotations = _e[1];
51
+ var _f = useState([]), selectedQuotationIds = _f[0], setSelectedQuotationIds = _f[1];
52
+ var _g = useState(false), isSelectAll = _g[0], setIsSelectAll = _g[1];
53
+ var _h = useState((_a = defaultValues === null || defaultValues === void 0 ? void 0 : defaultValues.agentForename) !== null && _a !== void 0 ? _a : ''), agentForename = _h[0], setAgentForename = _h[1];
54
+ var _j = useState((_b = defaultValues === null || defaultValues === void 0 ? void 0 : defaultValues.agentLastname) !== null && _b !== void 0 ? _b : ''), agentLastname = _j[0], setAgentLastname = _j[1];
55
+ var _k = useState((_c = defaultValues === null || defaultValues === void 0 ? void 0 : defaultValues.agency) !== null && _c !== void 0 ? _c : ''), agency = _k[0], setAgency = _k[1];
56
+ var _l = useState((_d = defaultValues === null || defaultValues === void 0 ? void 0 : defaultValues.quotationName) !== null && _d !== void 0 ? _d : ''), quotationName = _l[0], setQuotationName = _l[1];
57
+ var _m = useState({}), fieldErrors = _m[0], setFieldErrors = _m[1];
58
+ var _o = useState(null), formErrorMessage = _o[0], setFormErrorMessage = _o[1];
59
+ var remainingQuotationsFiltered = useMemo(function () { return remainingQuotations.filter(function (q) { return selectedQuotationIds.includes(q.id); }); }, [remainingQuotations, selectedQuotationIds]);
60
+ useEffect(function () {
61
+ setRemainingQuotations(quotations);
62
+ setSelectedQuotationIds(quotations.map(function (q) { return q.id; }));
63
+ }, [quotations]);
64
+ useEffect(function () {
65
+ setIsSelectAll(remainingQuotations.length > 0 &&
66
+ selectedQuotationIds.length === remainingQuotations.length);
67
+ }, [selectedQuotationIds, remainingQuotations]);
68
+ var handleRemoveQuotation = function (id) {
69
+ if (remainingQuotations.length > 1) {
70
+ setRemainingQuotations(function (prev) { return prev.filter(function (q) { return q.id !== id; }); });
71
+ setSelectedQuotationIds(function (prev) { return prev.filter(function (quoteId) { return quoteId !== id; }); });
72
+ }
73
+ };
74
+ var handleSelectQuotation = function (id) {
75
+ if (remainingQuotations.length > 1) {
76
+ setSelectedQuotationIds(function (prev) {
77
+ if (prev.includes(id)) {
78
+ return prev.length > 1 ? prev.filter(function (q) { return q !== id; }) : prev;
79
+ }
80
+ return __spreadArray(__spreadArray([], prev, true), [id], false);
81
+ });
82
+ }
83
+ };
84
+ var clearFieldError = function (field) {
85
+ setFieldErrors(function (prev) {
86
+ var next = __assign({}, prev);
87
+ delete next[field];
88
+ return next;
89
+ });
90
+ setFormErrorMessage(null);
91
+ };
92
+ var handleSelectAll = function () {
93
+ if (isSelectAll) {
94
+ setSelectedQuotationIds(remainingQuotations.length > 1 ? [remainingQuotations[0].id] : []);
95
+ }
96
+ else {
97
+ setSelectedQuotationIds(remainingQuotations.map(function (q) { return q.id; }));
98
+ }
99
+ setIsSelectAll(!isSelectAll);
100
+ };
101
+ var handleSubmit = function () {
102
+ var _a;
103
+ setFieldErrors({});
104
+ setFormErrorMessage(null);
105
+ var formData = {
106
+ agentForename: agentForename,
107
+ agentLastname: agentLastname,
108
+ agency: agency,
109
+ quotationName: quotationName,
110
+ };
111
+ var result = saveQuotationSchema.safeParse(formData);
112
+ if (!result.success) {
113
+ var errors_1 = {};
114
+ var messages_1 = [];
115
+ result.error.issues.forEach(function (issue) {
116
+ var path = issue.path[0];
117
+ if (path &&
118
+ (path === 'agentForename' ||
119
+ path === 'agentLastname' ||
120
+ path === 'agency' ||
121
+ path === 'quotationName')) {
122
+ errors_1[path] = issue.message;
123
+ messages_1.push(issue.message);
124
+ }
125
+ });
126
+ setFieldErrors(errors_1);
127
+ setFormErrorMessage((_a = messages_1[0]) !== null && _a !== void 0 ? _a : 'Please correct the errors below.');
128
+ return;
129
+ }
130
+ onSubmit({
131
+ selectedQuotationIds: remainingQuotationsFiltered.map(function (q) { return q.id; }),
132
+ formData: result.data,
133
+ });
134
+ };
135
+ return (_jsx(DialogBookingConfirm, { open: open, setOpen: setOpen, title: !successful ? 'Save quotation' : undefined, className: "!max-w-[800px]", closeOnOverlayClick: true, children: _jsx(motion.div, { className: "dialog-save-quotation", children: _jsx(AnimatePresence, { mode: "wait", initial: false, children: !successful ? (_jsxs(motion.div, { className: "dialog-save-quotation__view", initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2, ease: 'easeInOut' }, children: [_jsxs("div", { className: "dialog-save-quotation__quotes-section", children: [_jsx("div", { className: "dialog-save-quotation__quotes-list", children: remainingQuotations.map(function (quote) { return (_jsx(SelectedValue, { value: quote.name, color: selectedQuotationIds.includes(quote.id) ? 'accent' : 'neutral', onSelect: function () { return handleSelectQuotation(quote.id); }, onRemove: function () { return handleRemoveQuotation(quote.id); }, size: "lg", textSize: "md" }, quote.id)); }) }), _jsx("div", { className: "dialog-save-quotation__select-all", children: _jsx(Checkbox, { label: "Select all quotations", checked: isSelectAll || remainingQuotations.length === 1, disabled: remainingQuotations.length === 1, onChange: handleSelectAll, labelPosition: "leading" }) })] }), _jsx("h3", { className: "dialog-save-quotation__section-title", children: "All quotations" }), _jsxs("div", { className: "dialog-save-quotation__form", children: [_jsxs("div", { className: "dialog-save-quotation__form-row", children: [_jsxs("div", { className: "dialog-save-quotation__field", children: [_jsx("label", { htmlFor: "agent-forename", className: "dialog-save-quotation__label dialog-save-quotation__label--required".concat((disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.agentForename) ? ' dialog-save-quotation__label--disabled' : ''), children: "Agent Forename" }), _jsx(Input, { id: "agent-forename", value: agentForename, onChange: function (e) {
136
+ setAgentForename(e.target.value);
137
+ clearFieldError('agentForename');
138
+ }, placeholder: "Mautourco", variant: (disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.agentForename)
139
+ ? 'disabled'
140
+ : fieldErrors.agentForename || errorMessage
141
+ ? 'error'
142
+ : 'default' })] }), _jsxs("div", { className: "dialog-save-quotation__field", children: [_jsx("label", { htmlFor: "agent-lastname", className: "dialog-save-quotation__label dialog-save-quotation__label--required".concat((disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.agentLastname) ? ' dialog-save-quotation__label--disabled' : ''), children: "Agent Lastname" }), _jsx(Input, { id: "agent-lastname", value: agentLastname, onChange: function (e) {
143
+ setAgentLastname(e.target.value);
144
+ clearFieldError('agentLastname');
145
+ }, placeholder: "B2B", variant: (disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.agentLastname)
146
+ ? 'disabled'
147
+ : fieldErrors.agentLastname || errorMessage
148
+ ? 'error'
149
+ : 'default' })] }), _jsxs("div", { className: "dialog-save-quotation__field", children: [_jsx("label", { htmlFor: "agency", className: "dialog-save-quotation__label".concat((disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.agency) ? ' dialog-save-quotation__label--disabled' : ''), children: "Agency" }), _jsx(Input, { id: "agency", value: agency, onChange: function (e) {
150
+ setAgency(e.target.value);
151
+ clearFieldError('agency');
152
+ }, placeholder: "Mautourco Ltd", variant: (disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.agency)
153
+ ? 'disabled'
154
+ : fieldErrors.agency || errorMessage
155
+ ? 'error'
156
+ : 'default' })] })] }), _jsx("div", { className: "dialog-save-quotation__form-row dialog-save-quotation__form-row--single", children: _jsxs("div", { className: "dialog-save-quotation__field", children: [_jsx("label", { htmlFor: "quotation-name", className: "dialog-save-quotation__label dialog-save-quotation__label--required".concat((disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.quotationName) ? ' dialog-save-quotation__label--disabled' : ''), children: "Quotation name" }), _jsx(Input, { id: "quotation-name", value: quotationName, onChange: function (e) {
157
+ setQuotationName(e.target.value);
158
+ clearFieldError('quotationName');
159
+ }, placeholder: "Insert client's name", variant: (disabledInputs === null || disabledInputs === void 0 ? void 0 : disabledInputs.quotationName)
160
+ ? 'disabled'
161
+ : fieldErrors.quotationName || errorMessage
162
+ ? 'error'
163
+ : 'default' })] }) })] }), (formErrorMessage || errorMessage) && (_jsx("p", { className: "dialog-save-quotation__error", role: "alert", children: formErrorMessage !== null && formErrorMessage !== void 0 ? formErrorMessage : errorMessage })), _jsxs("div", { className: "dialog-save-quotation__footer", children: [_jsx(Button, { variant: "outline-secondary", size: "sm", onClick: function () { return setOpen(false); }, disabled: loading, children: "Cancel" }), _jsx(Button, { variant: "secondary", size: "sm", onClick: handleSubmit, disabled: loading, children: loading ? 'Saving…' : 'Save quotation' })] })] }, "form")) : (_jsxs(motion.div, { className: "dialog-save-quotation__view", initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2, ease: 'easeInOut' }, children: [_jsxs("div", { className: "dialog-save-quotation__content", children: [_jsx("div", { className: "dialog-save-quotation__content-image-container", "aria-hidden": true, children: _jsx("img", { src: imgSuccess, alt: imgSuccessAlt, className: "dialog-save-quotation__content-image" }) }), _jsxs("div", { className: "dialog-save-quotation__content-text", children: [_jsx(Text, { variant: "bold", size: "xl", as: "h2", className: "dialog-save-quotation__content-title ", children: "Quotation saved" }), _jsxs(Text, { size: "lg", children: [_jsxs(Text, { size: "lg", variant: "bold", as: "span", children: ["\"", quotationName, "\""] }), ' ', "quotation"] })] })] }), _jsxs("div", { className: "dialog-save-quotation__footer", children: [_jsx(Button, { variant: "outline-secondary", size: "sm", onClick: onHandleViewOnQuotationGrid, children: "View on quotation grid" }), _jsx(Button, { variant: "secondary", size: "sm", onClick: onHandleBookNow, children: "Book now" })] })] }, "success")) }) }) }));
164
+ }
@@ -0,0 +1,2 @@
1
+ export { DialogSaveQuotation, type DialogSaveQuotationProps, type SaveQuotationQuote, } from './DialogSaveQuotation';
2
+ export type { SaveQuotationSchema } from './save-quotation-schema';
@@ -0,0 +1 @@
1
+ export { DialogSaveQuotation, } from './DialogSaveQuotation';
@@ -0,0 +1,8 @@
1
+ import z from 'zod';
2
+ export declare const saveQuotationSchema: z.ZodObject<{
3
+ agentForename: z.ZodString;
4
+ agentLastname: z.ZodString;
5
+ agency: z.ZodOptional<z.ZodString>;
6
+ quotationName: z.ZodString;
7
+ }, z.core.$strip>;
8
+ export type SaveQuotationSchema = z.infer<typeof saveQuotationSchema>;
@@ -0,0 +1,7 @@
1
+ import z from 'zod';
2
+ export var saveQuotationSchema = z.object({
3
+ agentForename: z.string().min(1, 'Agent forename is required'),
4
+ agentLastname: z.string().min(1, 'Agent lastname is required'),
5
+ agency: z.string().optional(),
6
+ quotationName: z.string().min(1, 'Quotation name is required'),
7
+ });
package/dist/index.d.ts CHANGED
@@ -64,6 +64,7 @@ export { DialogComparison } from './components/organisms/DialogComparison/Dialog
64
64
  export * from './components/organisms/DialogDeleteConfirm';
65
65
  export { DialogDeleteConfirm } from './components/organisms/DialogDeleteConfirm/DialogDeleteConfirm';
66
66
  export { DialogQuoteRename } from './components/organisms/DialogQuoteRename/DialogQuoteRename';
67
+ export * from './components/organisms/DialogSaveQuotation';
67
68
  export * from './components/organisms/DialogSendingMail';
68
69
  export { default as Docket } from './components/organisms/Docket/Docket';
69
70
  export { DocketAccordion, type DocketAccordionProps, } from './components/organisms/DocketAccordion';
package/dist/index.js CHANGED
@@ -66,6 +66,7 @@ export { DialogComparison } from './components/organisms/DialogComparison/Dialog
66
66
  export * from './components/organisms/DialogDeleteConfirm';
67
67
  export { DialogDeleteConfirm } from './components/organisms/DialogDeleteConfirm/DialogDeleteConfirm';
68
68
  export { DialogQuoteRename } from './components/organisms/DialogQuoteRename/DialogQuoteRename';
69
+ export * from './components/organisms/DialogSaveQuotation';
69
70
  export * from './components/organisms/DialogSendingMail';
70
71
  export { default as Docket } from './components/organisms/Docket/Docket';
71
72
  export { DocketAccordion, } from './components/organisms/DocketAccordion';
@@ -107,17 +107,17 @@
107
107
  color: var(--color-red-400);
108
108
  }
109
109
 
110
- /* État disabled */
110
+ /* État disabled – Mautourco Foundations tokens */
111
111
 
112
112
  .input-field--disabled {
113
- background-color: var(--color-slate-100);
114
- border-color: var(--color-slate-200);
115
- color: var(--color-slate-400);
113
+ background-color: var(--color-elevation-state-disabled, #fbfbfb);
114
+ border-color: var(--color-border-input-disabled, #d1d5db);
115
+ color: var(--color-text-state-disabled, #a3a3a3);
116
116
  cursor: not-allowed;
117
117
  }
118
118
 
119
119
  .input-field--disabled::placeholder {
120
- color: var(--color-slate-300);
120
+ color: var(--color-text-state-disabled, #a3a3a3);
121
121
  }
122
122
 
123
123
  /* Styles pour le showcase */
@@ -235,6 +235,7 @@
235
235
 
236
236
  .docket__footer-button {
237
237
  flex: 1;
238
+ white-space: nowrap;
238
239
  }
239
240
 
240
241
  .docket__footer-button--full {
@@ -4,19 +4,21 @@
4
4
 
5
5
  /* SelectedValue Component Styles */
6
6
 
7
+ /* Base uses sm as default; tokens: chip-spacing-*-* from Figma */
8
+
7
9
  .selected-value {
8
10
  display: inline-flex;
9
11
  align-items: center;
10
- gap: var(--chip-spacing-gap, 0.5rem);
11
- padding: var(--chip-spacing-sm-padding-y, 0.375rem) var(--chip-spacing-sm-padding-x);
12
- border-radius: var(--chip-border-radius-pill, 1.375rem);
12
+ gap: var(--chip-spacing-sm-gap, 4px);
13
+ padding: var(--chip-spacing-sm-padding-y, 4px) var(--chip-spacing-sm-padding-x, 8px);
14
+ border-radius: var(--chip-border-radius-pill, 9999px);
13
15
  /* Typography is now handled by the Text component */
14
16
  cursor: default;
15
17
  -webkit-user-select: none;
16
18
  user-select: none;
17
19
  max-width: 200px;
18
20
  width: auto;
19
- opacity: var(--opacity-opacity-100);
21
+ opacity: var(--opacity-opacity-100, 1);
20
22
  /* Variant: text-only (no background, no padding) */
21
23
  .selected-value--text {
22
24
  background: transparent;
@@ -63,32 +65,36 @@
63
65
  /* Size variants */
64
66
 
65
67
  .selected-value--xs {
66
- padding: var(--chip-spacing-xs-padding-y, 0.25rem)
67
- var(--chip-spacing-xs-padding-x, 0.5rem);
68
- gap: var(--chip-spacing-xs-gap, 0.25rem);
68
+ padding: var(--chip-spacing-xs-padding-y, 2px)
69
+ var(--chip-spacing-xs-padding-x, 6px);
70
+ gap: var(--chip-spacing-xs-gap, 2px);
69
71
  }
70
72
 
71
73
  .selected-value--sm {
72
- padding: var(--chip-spacing-sm-padding-y, 0.375rem)
73
- var(--chip-spacing-sm-padding-x, 0.75rem);
74
- gap: var(--chip-spacing-sm-gap, 0.375rem);
74
+ padding: var(--chip-spacing-sm-padding-y, 4px)
75
+ var(--chip-spacing-sm-padding-x, 8px);
76
+ gap: var(--chip-spacing-sm-gap, 4px);
75
77
  }
76
78
 
77
79
  .selected-value--md {
78
- padding: var(--chip-spacing-md-padding-y, 0.5rem)
79
- var(--chip-spacing-md-padding-x, 0.875rem);
80
- gap: var(--chip-spacing-md-gap, 0.5rem);
80
+ padding: var(--chip-spacing-md-padding-y, 4px)
81
+ var(--chip-spacing-md-padding-x, 12px);
82
+ gap: var(--chip-spacing-md-gap, 4px);
81
83
  }
82
84
 
85
+ /* Figma chip/lg: padding-x 16px, padding-y 4px, gap 4px */
86
+
83
87
  .selected-value--lg {
84
- padding: var(--chip-spacing-lg-padding-y, 0.625rem)
85
- var(--chip-spacing-lg-padding-x, 1rem);
86
- gap: var(--chip-spacing-lg-gap, 0.625rem);
88
+ padding: var(--chip-spacing-lg-padding-y, 4px)
89
+ var(--chip-spacing-lg-padding-x, 16px);
90
+ gap: var(--chip-spacing-lg-gap, 4px);
87
91
  }
88
92
 
93
+ /* Figma chip/color/accent/filled: bg #0f7173, fg #ffffff */
94
+
89
95
  .selected-value--accent {
90
- background: var(--color-atoll-green-800);
91
- color: var(--color-white);
96
+ background: var(--chip-color-accent-filled-background, var(--color-atoll-green-800));
97
+ color: var(--chip-color-accent-filled-foreground, var(--color-white));
92
98
  }
93
99
 
94
100
  .selected-value--neutral {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mautourco-components",
3
- "version": "0.2.161",
3
+ "version": "0.2.163",
4
4
  "private": false,
5
5
  "description": "Bibliothèque de composants Mautourco pour le redesign",
6
6
  "main": "dist/index.js",
@@ -6,7 +6,10 @@ interface SelectedValueProps {
6
6
  value: string;
7
7
  className?: string;
8
8
  iconSize?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
9
+ /** Chip size - controls padding and gap (Figma: chip/spacing/lg = 16px, 4px, 4px) */
9
10
  size?: 'xs' | 'sm' | 'md' | 'lg';
11
+ /** Text size - defaults to same as size. Use 'md' for Figma body-md (16px, leading-24) */
12
+ textSize?: 'xs' | 'sm' | 'md' | 'lg';
10
13
  variant?: 'filled' | 'text';
11
14
  color?: 'accent' | 'neutral';
12
15
  onRemove?: () => void;
@@ -18,6 +21,7 @@ const SelectedValue: React.FC<SelectedValueProps> = ({
18
21
  className = '',
19
22
  iconSize = 'xs',
20
23
  size = 'md',
24
+ textSize,
21
25
  variant = 'filled',
22
26
  color = 'accent',
23
27
  onRemove,
@@ -33,16 +37,14 @@ const SelectedValue: React.FC<SelectedValueProps> = ({
33
37
  const classes =
34
38
  `selected-value selected-value--${size} selected-value--${color} selected-value--${variant} ${className} ${onSelect ? 'cursor-pointer' : ''}`.trim();
35
39
 
36
- const getTextSize = () => {
37
- return size; // Utilise directement la taille passée en prop
38
- };
40
+ const effectiveTextSize = textSize ?? size;
39
41
 
40
42
  return (
41
43
  <div className={classes} onClick={onSelect}>
42
44
  <Text
43
- size={getTextSize() as any}
45
+ size={effectiveTextSize}
44
46
  variant="medium"
45
- leading="4"
47
+ leading="6"
46
48
  className="selected-value__text">
47
49
  {value}
48
50
  </Text>