pcm-shared-components 2.1.383 → 2.1.385
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/Reservation/AnimalVehicleDetailsEditor/index.js +518 -0
- package/dist/index.js +2 -1
- package/dist/languages/en/translations.json +6 -2
- package/dist/languages/es/translations.json +6 -2
- package/dist/languages/fr/translations.json +6 -2
- package/dist/styles/tailwind.css +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { TextField, Icon, IconButton, Button, Paper, Typography, InputAdornment, MenuItem, ToggleButton, ToggleButtonGroup, Checkbox, ListItemText, Chip, Alert, Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions } from '@mui/material';
|
|
4
|
+
import { ThemeProvider } from '@mui/system';
|
|
5
|
+
import { createTheme, useTheme, alpha } from '@mui/material/styles';
|
|
6
|
+
import AddIcon from '@mui/icons-material/Add';
|
|
7
|
+
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
|
|
8
|
+
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
|
9
|
+
import WarningAmberIcon from '@mui/icons-material/WarningAmber';
|
|
10
|
+
import * as i18nextLocal from 'i18next';
|
|
11
|
+
|
|
12
|
+
// Every visible string this component owns lives under these two pre-existing i18next namespaces
|
|
13
|
+
// (already shared across both PitchCamp apps via pcm-shared-components' translations.json). Keyed
|
|
14
|
+
// by itemType so one component serves animals and vehicles without the caller needing to resolve
|
|
15
|
+
// any text itself -- only field labels/placeholders/options come from the caller (they're
|
|
16
|
+
// admin-configured or item-specific, not something this component could know).
|
|
17
|
+
const KEYS = {
|
|
18
|
+
animal: {
|
|
19
|
+
sectionTitle: 'animal.section_title',
|
|
20
|
+
itemTitle: 'animal.client_animal_title',
|
|
21
|
+
count: 'animal.animal_count',
|
|
22
|
+
addItem: 'animal.add_animal',
|
|
23
|
+
requiredInformation: 'animal.required_information',
|
|
24
|
+
missingCount: 'animal.missing_count',
|
|
25
|
+
needsInformation: 'animal.needs_information',
|
|
26
|
+
maxReached: 'occupant_vehicle.max_animal',
|
|
27
|
+
removeConfirmTitle: 'animal.remove_confirm_title',
|
|
28
|
+
removeConfirmMessage: 'animal.remove_confirm_message'
|
|
29
|
+
},
|
|
30
|
+
vehicle: {
|
|
31
|
+
sectionTitle: 'client_vehicle.client_vehicle_title',
|
|
32
|
+
itemTitle: 'client_vehicle.vehicle_title',
|
|
33
|
+
count: 'client_vehicle.vehicle_count',
|
|
34
|
+
addItem: 'client_vehicle.add_vehicle',
|
|
35
|
+
requiredInformation: 'client_vehicle.required_information',
|
|
36
|
+
missingCount: 'client_vehicle.missing_count',
|
|
37
|
+
needsInformation: 'client_vehicle.needs_information',
|
|
38
|
+
maxReached: 'occupant_vehicle.max_vehicle',
|
|
39
|
+
removeConfirmTitle: 'client_vehicle.remove_confirm_title',
|
|
40
|
+
removeConfirmMessage: 'client_vehicle.remove_confirm_message'
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Type-aware required-field wording so the guest/staff knows what's actually missing -- "please
|
|
45
|
+
// select an option" reads very differently from "please enter a number". Not itemType-specific:
|
|
46
|
+
// a select field is a select field whether it belongs to an animal or a vehicle. Falls back to
|
|
47
|
+
// animal.required_error for text/textarea, where the generic "fill this in" copy already fits.
|
|
48
|
+
const REQUIRED_ERROR_KEY_BY_TYPE = {
|
|
49
|
+
select: 'animal.required_error_select',
|
|
50
|
+
select_multiple: 'animal.required_error_select_multiple',
|
|
51
|
+
number: 'animal.required_error_number',
|
|
52
|
+
date: 'animal.required_error_date',
|
|
53
|
+
yes_no: 'animal.required_error_yes_no'
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Tab-per-item editor for a lot's animal or vehicle detail fields: one tab per item (green
|
|
58
|
+
* check when every required field is answered, amber warning triangle otherwise), an "Add"
|
|
59
|
+
* button, the selected item's fields as a 2-column grid, and a sticky validation banner with a
|
|
60
|
+
* "Review" action that jumps to the first incomplete item and focuses its first invalid field.
|
|
61
|
+
*
|
|
62
|
+
* Fully controlled: this component owns no data, only the transient "which tab is selected" UI
|
|
63
|
+
* state. All actual mutation goes back through the callback props, so each host app keeps its own
|
|
64
|
+
* state management (Redux, local `useState`, whatever) as the source of truth.
|
|
65
|
+
*
|
|
66
|
+
* ## Importing the component in your project
|
|
67
|
+
*
|
|
68
|
+
```js
|
|
69
|
+
|
|
70
|
+
import {AnimalVehicleDetailsEditor} from 'pcm-shared-components';
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
*
|
|
74
|
+
*/
|
|
75
|
+
export const AnimalVehicleDetailsEditor = props => {
|
|
76
|
+
const {
|
|
77
|
+
itemType,
|
|
78
|
+
items,
|
|
79
|
+
fieldConfig,
|
|
80
|
+
isFieldAnswered,
|
|
81
|
+
onFieldChange,
|
|
82
|
+
onAddItem,
|
|
83
|
+
onRemoveItem,
|
|
84
|
+
canAddMore,
|
|
85
|
+
maxItems,
|
|
86
|
+
className,
|
|
87
|
+
theme,
|
|
88
|
+
i18next
|
|
89
|
+
} = props;
|
|
90
|
+
const compTheme = theme || useTheme();
|
|
91
|
+
const defaultTheme = createTheme(compTheme);
|
|
92
|
+
const keys = KEYS[itemType] || KEYS.animal;
|
|
93
|
+
const requiredErrorText = fieldType => i18next.t(REQUIRED_ERROR_KEY_BY_TYPE[fieldType] || 'animal.required_error');
|
|
94
|
+
const missingRequiredFields = item => fieldConfig.filter(f => f.required).filter(f => !isFieldAnswered(f.type, item.values?.[f.key] ?? (f.type === 'select_multiple' ? [] : '')));
|
|
95
|
+
|
|
96
|
+
// Any field answered (not just required ones) -- an optional field someone bothered to fill in
|
|
97
|
+
// is still real data that'd be silently thrown away by a bare-click delete.
|
|
98
|
+
const hasAnyData = item => fieldConfig.some(f => isFieldAnswered(f.type, item.values?.[f.key] ?? (f.type === 'select_multiple' ? [] : '')));
|
|
99
|
+
|
|
100
|
+
// Removing an item that actually has data goes through a confirmation step first; an empty one
|
|
101
|
+
// (nothing entered yet) is removed immediately, same as before -- no point prompting when
|
|
102
|
+
// there's nothing to lose.
|
|
103
|
+
const [pendingRemoveId, setPendingRemoveId] = useState(null);
|
|
104
|
+
const requestRemove = item => {
|
|
105
|
+
if (hasAnyData(item)) {
|
|
106
|
+
setPendingRemoveId(item.id);
|
|
107
|
+
} else {
|
|
108
|
+
onRemoveItem(item.id);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
const confirmRemove = () => {
|
|
112
|
+
onRemoveItem(pendingRemoveId);
|
|
113
|
+
setPendingRemoveId(null);
|
|
114
|
+
};
|
|
115
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
116
|
+
// Growing the list (Add) jumps to the newly-added last item, since that's the one the host just
|
|
117
|
+
// asked for and the one that needs filling in. Shrinking it (Remove) just clamps the current
|
|
118
|
+
// selection back into range instead of jumping anywhere.
|
|
119
|
+
const prevItemsLengthRef = useRef(items.length);
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
if (items.length > prevItemsLengthRef.current) {
|
|
122
|
+
setSelectedIndex(items.length - 1);
|
|
123
|
+
} else {
|
|
124
|
+
setSelectedIndex(prev => Math.min(prev, Math.max(0, items.length - 1)));
|
|
125
|
+
}
|
|
126
|
+
prevItemsLengthRef.current = items.length;
|
|
127
|
+
}, [items.length]);
|
|
128
|
+
|
|
129
|
+
// "Review" jumps to the first incomplete item and focuses its first invalid field. The field
|
|
130
|
+
// doesn't exist in the DOM until AFTER the tab switch commits, so this is a two-step dance:
|
|
131
|
+
// record which index we're waiting on, then once that index is actually selected, look inside
|
|
132
|
+
// fieldsContainerRef for the first data-field-invalid="true" control and focus it.
|
|
133
|
+
const fieldsContainerRef = useRef(null);
|
|
134
|
+
const [pendingFocusIndex, setPendingFocusIndex] = useState(null);
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
if (pendingFocusIndex === null || selectedIndex !== pendingFocusIndex) return;
|
|
137
|
+
const firstInvalid = fieldsContainerRef.current?.querySelector('[data-field-invalid="true"] input, [data-field-invalid="true"] textarea, [data-field-invalid="true"] [role="combobox"]');
|
|
138
|
+
firstInvalid?.focus();
|
|
139
|
+
setPendingFocusIndex(null);
|
|
140
|
+
}, [selectedIndex, pendingFocusIndex]);
|
|
141
|
+
const handleReview = () => {
|
|
142
|
+
const idx = items.findIndex(item => missingRequiredFields(item).length > 0);
|
|
143
|
+
if (idx === -1) return;
|
|
144
|
+
setSelectedIndex(idx);
|
|
145
|
+
setPendingFocusIndex(idx);
|
|
146
|
+
};
|
|
147
|
+
const selectedItem = items[selectedIndex];
|
|
148
|
+
return /*#__PURE__*/React.createElement(ThemeProvider, {
|
|
149
|
+
theme: defaultTheme
|
|
150
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
151
|
+
className: className
|
|
152
|
+
}, /*#__PURE__*/React.createElement(Paper, {
|
|
153
|
+
variant: "outlined",
|
|
154
|
+
sx: {
|
|
155
|
+
p: 1.5,
|
|
156
|
+
borderRadius: 2,
|
|
157
|
+
bgcolor: 'action.hover'
|
|
158
|
+
}
|
|
159
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
160
|
+
className: "flex items-center justify-between mb-8"
|
|
161
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
162
|
+
className: "flex items-center",
|
|
163
|
+
style: {
|
|
164
|
+
gap: 6
|
|
165
|
+
}
|
|
166
|
+
}, itemType === 'vehicle' ? /*#__PURE__*/React.createElement(Icon, {
|
|
167
|
+
sx: {
|
|
168
|
+
color: 'info.main'
|
|
169
|
+
}
|
|
170
|
+
}, "drive_eta") : /*#__PURE__*/React.createElement(Icon, {
|
|
171
|
+
sx: {
|
|
172
|
+
color: 'success.main'
|
|
173
|
+
}
|
|
174
|
+
}, "pets"), /*#__PURE__*/React.createElement(Typography, {
|
|
175
|
+
sx: {
|
|
176
|
+
fontWeight: 700
|
|
177
|
+
}
|
|
178
|
+
}, i18next.t(keys.sectionTitle))), /*#__PURE__*/React.createElement(Chip, {
|
|
179
|
+
size: "small",
|
|
180
|
+
label: i18next.t(keys.count, {
|
|
181
|
+
count: items.length
|
|
182
|
+
})
|
|
183
|
+
})), /*#__PURE__*/React.createElement("div", {
|
|
184
|
+
className: "flex flex-wrap items-center",
|
|
185
|
+
style: {
|
|
186
|
+
gap: 8
|
|
187
|
+
}
|
|
188
|
+
}, items.map((item, idx) => {
|
|
189
|
+
const complete = missingRequiredFields(item).length === 0;
|
|
190
|
+
const isSelected = selectedIndex === idx;
|
|
191
|
+
// Complete gets a green border/text + checkmark; incomplete gets a matching
|
|
192
|
+
// amber/orange border+text + warning triangle. Selection adds a light fill in that
|
|
193
|
+
// same color plus a heavier border + bold label, so it's clear which tab is "done"
|
|
194
|
+
// vs "current" at a glance.
|
|
195
|
+
return /*#__PURE__*/React.createElement(Button, {
|
|
196
|
+
key: item.id ?? idx,
|
|
197
|
+
variant: "outlined",
|
|
198
|
+
size: "small",
|
|
199
|
+
color: complete ? 'success' : 'warning',
|
|
200
|
+
onClick: () => setSelectedIndex(idx),
|
|
201
|
+
endIcon: complete ? /*#__PURE__*/React.createElement(CheckCircleIcon, {
|
|
202
|
+
fontSize: "small",
|
|
203
|
+
color: "success"
|
|
204
|
+
}) : /*#__PURE__*/React.createElement(WarningAmberIcon, {
|
|
205
|
+
fontSize: "small",
|
|
206
|
+
color: "warning"
|
|
207
|
+
}),
|
|
208
|
+
sx: {
|
|
209
|
+
whiteSpace: 'nowrap',
|
|
210
|
+
fontWeight: isSelected ? 700 : 400,
|
|
211
|
+
borderWidth: isSelected ? 2 : 1,
|
|
212
|
+
bgcolor: t => isSelected ? alpha(t.palette[complete ? 'success' : 'warning'].main, 0.12) : 'transparent'
|
|
213
|
+
}
|
|
214
|
+
}, `${i18next.t(keys.itemTitle)} ${idx + 1}`);
|
|
215
|
+
}), /*#__PURE__*/React.createElement(Button, {
|
|
216
|
+
variant: "outlined",
|
|
217
|
+
size: "small",
|
|
218
|
+
color: "inherit",
|
|
219
|
+
startIcon: /*#__PURE__*/React.createElement(AddIcon, {
|
|
220
|
+
fontSize: "small"
|
|
221
|
+
}),
|
|
222
|
+
disabled: !canAddMore,
|
|
223
|
+
onClick: onAddItem,
|
|
224
|
+
sx: {
|
|
225
|
+
whiteSpace: 'nowrap',
|
|
226
|
+
borderStyle: 'dashed'
|
|
227
|
+
}
|
|
228
|
+
}, i18next.t(keys.addItem))), !canAddMore && /*#__PURE__*/React.createElement(Typography, {
|
|
229
|
+
variant: "caption",
|
|
230
|
+
color: "error",
|
|
231
|
+
className: "block text-center mt-4"
|
|
232
|
+
}, `${i18next.t(keys.maxReached)} ${maxItems}`), selectedItem && /*#__PURE__*/React.createElement(Paper, {
|
|
233
|
+
variant: "outlined",
|
|
234
|
+
sx: {
|
|
235
|
+
mt: 1,
|
|
236
|
+
p: 1.5,
|
|
237
|
+
borderRadius: 2
|
|
238
|
+
}
|
|
239
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
240
|
+
className: "flex items-start justify-between mb-12"
|
|
241
|
+
}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Typography, {
|
|
242
|
+
sx: {
|
|
243
|
+
fontWeight: 700
|
|
244
|
+
}
|
|
245
|
+
}, `${i18next.t(keys.itemTitle)} ${selectedIndex + 1}`), /*#__PURE__*/React.createElement(Typography, {
|
|
246
|
+
variant: "caption",
|
|
247
|
+
color: "text.secondary"
|
|
248
|
+
}, i18next.t(keys.requiredInformation))), /*#__PURE__*/React.createElement(IconButton, {
|
|
249
|
+
size: "small",
|
|
250
|
+
color: "error",
|
|
251
|
+
onClick: () => requestRemove(selectedItem)
|
|
252
|
+
}, /*#__PURE__*/React.createElement(DeleteOutlineIcon, {
|
|
253
|
+
fontSize: "small"
|
|
254
|
+
}))), /*#__PURE__*/React.createElement("div", {
|
|
255
|
+
ref: fieldsContainerRef,
|
|
256
|
+
className: "grid grid-cols-2",
|
|
257
|
+
style: {
|
|
258
|
+
columnGap: 12,
|
|
259
|
+
rowGap: 16,
|
|
260
|
+
gridAutoFlow: 'row dense'
|
|
261
|
+
}
|
|
262
|
+
}, fieldConfig.map(field => {
|
|
263
|
+
const value = selectedItem.values?.[field.key] ?? '';
|
|
264
|
+
const showError = field.required && !isFieldAnswered(field.type, value);
|
|
265
|
+
const labelText = field.required ? `${field.label} *` : `${field.label} (${i18next.t('common.app.optional')})`;
|
|
266
|
+
const wrapperClassName = ['select', 'textarea', 'select_multiple', 'yes_no'].includes(field.type) ? 'col-span-full' : undefined;
|
|
267
|
+
let control;
|
|
268
|
+
if (field.type === 'number') {
|
|
269
|
+
control = /*#__PURE__*/React.createElement(TextField, {
|
|
270
|
+
name: field.key,
|
|
271
|
+
value: value,
|
|
272
|
+
onChange: e => onFieldChange(selectedItem.id, field.key, e.target.value),
|
|
273
|
+
onKeyDown: e => {
|
|
274
|
+
if (e.key === 'e' || e.key === 'E') e.preventDefault();
|
|
275
|
+
},
|
|
276
|
+
variant: "outlined",
|
|
277
|
+
size: "small",
|
|
278
|
+
error: showError,
|
|
279
|
+
helperText: showError ? requiredErrorText(field.type) : '',
|
|
280
|
+
inputProps: {
|
|
281
|
+
maxLength: field.maxLength || 45
|
|
282
|
+
},
|
|
283
|
+
type: "number",
|
|
284
|
+
placeholder: field.placeholder,
|
|
285
|
+
fullWidth: true,
|
|
286
|
+
InputProps: {
|
|
287
|
+
endAdornment: field.unit ? /*#__PURE__*/React.createElement(InputAdornment, {
|
|
288
|
+
position: "end"
|
|
289
|
+
}, field.unit) : undefined
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
} else if (field.type === 'select') {
|
|
293
|
+
control = /*#__PURE__*/React.createElement(TextField, {
|
|
294
|
+
select: true,
|
|
295
|
+
name: field.key,
|
|
296
|
+
value: value,
|
|
297
|
+
onChange: e => onFieldChange(selectedItem.id, field.key, e.target.value),
|
|
298
|
+
variant: "outlined",
|
|
299
|
+
size: "small",
|
|
300
|
+
error: showError,
|
|
301
|
+
helperText: showError ? requiredErrorText(field.type) : '',
|
|
302
|
+
fullWidth: true
|
|
303
|
+
}, /*#__PURE__*/React.createElement(MenuItem, {
|
|
304
|
+
value: ""
|
|
305
|
+
}, /*#__PURE__*/React.createElement("em", null, field.placeholder || i18next.t('common.app.select'))), (field.options || []).map(opt => /*#__PURE__*/React.createElement(MenuItem, {
|
|
306
|
+
key: opt,
|
|
307
|
+
value: opt
|
|
308
|
+
}, opt)));
|
|
309
|
+
} else if (field.type === 'textarea') {
|
|
310
|
+
control = /*#__PURE__*/React.createElement(TextField, {
|
|
311
|
+
name: field.key,
|
|
312
|
+
value: value,
|
|
313
|
+
onChange: e => onFieldChange(selectedItem.id, field.key, e.target.value),
|
|
314
|
+
variant: "outlined",
|
|
315
|
+
size: "small",
|
|
316
|
+
error: showError,
|
|
317
|
+
helperText: showError ? requiredErrorText(field.type) : '',
|
|
318
|
+
inputProps: {
|
|
319
|
+
maxLength: field.maxLength || 45
|
|
320
|
+
},
|
|
321
|
+
placeholder: field.placeholder,
|
|
322
|
+
multiline: true,
|
|
323
|
+
rows: 3,
|
|
324
|
+
fullWidth: true
|
|
325
|
+
});
|
|
326
|
+
} else if (field.type === 'select_multiple') {
|
|
327
|
+
const selectedValues = Array.isArray(value) ? value : [];
|
|
328
|
+
control = /*#__PURE__*/React.createElement(TextField, {
|
|
329
|
+
select: true,
|
|
330
|
+
name: field.key,
|
|
331
|
+
value: selectedValues,
|
|
332
|
+
onChange: e => onFieldChange(selectedItem.id, field.key, e.target.value),
|
|
333
|
+
variant: "outlined",
|
|
334
|
+
size: "small",
|
|
335
|
+
error: showError,
|
|
336
|
+
helperText: showError ? requiredErrorText(field.type) : '',
|
|
337
|
+
fullWidth: true,
|
|
338
|
+
SelectProps: {
|
|
339
|
+
multiple: true,
|
|
340
|
+
renderValue: selected => /*#__PURE__*/React.createElement("div", {
|
|
341
|
+
className: "flex flex-wrap gap-4"
|
|
342
|
+
}, selected.map(opt => /*#__PURE__*/React.createElement(Chip, {
|
|
343
|
+
key: opt,
|
|
344
|
+
label: opt,
|
|
345
|
+
size: "small"
|
|
346
|
+
})))
|
|
347
|
+
}
|
|
348
|
+
}, (field.options || []).map(opt => /*#__PURE__*/React.createElement(MenuItem, {
|
|
349
|
+
key: opt,
|
|
350
|
+
value: opt
|
|
351
|
+
}, /*#__PURE__*/React.createElement(Checkbox, {
|
|
352
|
+
checked: selectedValues.indexOf(opt) > -1
|
|
353
|
+
}), /*#__PURE__*/React.createElement(ListItemText, {
|
|
354
|
+
primary: opt
|
|
355
|
+
}))));
|
|
356
|
+
} else if (field.type === 'yes_no') {
|
|
357
|
+
const toggleValue = value === true ? 'yes' : value === false ? 'no' : null;
|
|
358
|
+
control = /*#__PURE__*/React.createElement(ToggleButtonGroup, {
|
|
359
|
+
value: toggleValue,
|
|
360
|
+
exclusive: true,
|
|
361
|
+
onChange: (_, val) => {
|
|
362
|
+
if (val !== null) onFieldChange(selectedItem.id, field.key, val === 'yes');
|
|
363
|
+
},
|
|
364
|
+
fullWidth: true,
|
|
365
|
+
size: "small"
|
|
366
|
+
}, /*#__PURE__*/React.createElement(ToggleButton, {
|
|
367
|
+
value: "yes"
|
|
368
|
+
}, i18next.t('common.app.yes')), /*#__PURE__*/React.createElement(ToggleButton, {
|
|
369
|
+
value: "no"
|
|
370
|
+
}, i18next.t('common.app.no')));
|
|
371
|
+
} else if (field.type === 'date') {
|
|
372
|
+
// Native date input, not each host app's own local DateTimeField wrapper --
|
|
373
|
+
// this component can't depend on either app's app-local component tree.
|
|
374
|
+
// Value is a plain 'YYYY-MM-DD' string in and out, same convention both apps
|
|
375
|
+
// already use for this field type.
|
|
376
|
+
control = /*#__PURE__*/React.createElement(TextField, {
|
|
377
|
+
name: field.key,
|
|
378
|
+
type: "date",
|
|
379
|
+
value: value,
|
|
380
|
+
onChange: e => onFieldChange(selectedItem.id, field.key, e.target.value),
|
|
381
|
+
variant: "outlined",
|
|
382
|
+
size: "small",
|
|
383
|
+
error: showError,
|
|
384
|
+
helperText: showError ? requiredErrorText(field.type) : '',
|
|
385
|
+
fullWidth: true,
|
|
386
|
+
InputLabelProps: {
|
|
387
|
+
shrink: true
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
} else {
|
|
391
|
+
// 'text' (default/unknown type too, for backward compat)
|
|
392
|
+
control = /*#__PURE__*/React.createElement(TextField, {
|
|
393
|
+
name: field.key,
|
|
394
|
+
value: value,
|
|
395
|
+
onChange: e => onFieldChange(selectedItem.id, field.key, e.target.value),
|
|
396
|
+
variant: "outlined",
|
|
397
|
+
size: "small",
|
|
398
|
+
error: showError,
|
|
399
|
+
helperText: showError ? requiredErrorText(field.type) : '',
|
|
400
|
+
inputProps: {
|
|
401
|
+
maxLength: field.maxLength || 45
|
|
402
|
+
},
|
|
403
|
+
type: "text",
|
|
404
|
+
placeholder: field.placeholder,
|
|
405
|
+
fullWidth: true
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
409
|
+
className: wrapperClassName,
|
|
410
|
+
key: `${selectedItem.id}_${field.key}`,
|
|
411
|
+
"data-field-invalid": showError ? 'true' : undefined
|
|
412
|
+
}, /*#__PURE__*/React.createElement(Typography, {
|
|
413
|
+
variant: "body2",
|
|
414
|
+
sx: {
|
|
415
|
+
fontWeight: 500,
|
|
416
|
+
mb: 0.5,
|
|
417
|
+
color: showError ? 'error.main' : 'text.primary'
|
|
418
|
+
}
|
|
419
|
+
}, labelText), control, field.type === 'yes_no' && showError && /*#__PURE__*/React.createElement(Typography, {
|
|
420
|
+
variant: "caption",
|
|
421
|
+
color: "error",
|
|
422
|
+
className: "block mt-4"
|
|
423
|
+
}, requiredErrorText(field.type)));
|
|
424
|
+
})))), (() => {
|
|
425
|
+
const incompleteCount = items.filter(item => missingRequiredFields(item).length > 0).length;
|
|
426
|
+
if (incompleteCount === 0) return null;
|
|
427
|
+
return /*#__PURE__*/React.createElement(Alert, {
|
|
428
|
+
severity: "error",
|
|
429
|
+
sx: {
|
|
430
|
+
position: 'sticky',
|
|
431
|
+
bottom: '-12px',
|
|
432
|
+
mt: 1,
|
|
433
|
+
py: 0.25,
|
|
434
|
+
alignItems: 'center',
|
|
435
|
+
zIndex: 1,
|
|
436
|
+
'& .MuiAlert-action': {
|
|
437
|
+
alignItems: 'center',
|
|
438
|
+
paddingTop: 0
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
action: /*#__PURE__*/React.createElement(Button, {
|
|
442
|
+
variant: "outlined",
|
|
443
|
+
color: "error",
|
|
444
|
+
size: "small",
|
|
445
|
+
onClick: handleReview,
|
|
446
|
+
sx: {
|
|
447
|
+
whiteSpace: 'nowrap',
|
|
448
|
+
alignSelf: 'center'
|
|
449
|
+
}
|
|
450
|
+
}, i18next.t('common.app.review'))
|
|
451
|
+
}, i18next.t(keys.needsInformation, {
|
|
452
|
+
count: incompleteCount
|
|
453
|
+
}));
|
|
454
|
+
})(), /*#__PURE__*/React.createElement(Dialog, {
|
|
455
|
+
open: pendingRemoveId !== null,
|
|
456
|
+
onClose: () => setPendingRemoveId(null),
|
|
457
|
+
maxWidth: "xs",
|
|
458
|
+
fullWidth: true
|
|
459
|
+
}, /*#__PURE__*/React.createElement(DialogTitle, null, i18next.t(keys.removeConfirmTitle)), /*#__PURE__*/React.createElement(DialogContent, null, /*#__PURE__*/React.createElement(DialogContentText, null, i18next.t(keys.removeConfirmMessage))), /*#__PURE__*/React.createElement(DialogActions, null, /*#__PURE__*/React.createElement(Button, {
|
|
460
|
+
onClick: () => setPendingRemoveId(null)
|
|
461
|
+
}, i18next.t('common.app.cancel')), /*#__PURE__*/React.createElement(Button, {
|
|
462
|
+
color: "error",
|
|
463
|
+
variant: "contained",
|
|
464
|
+
onClick: confirmRemove
|
|
465
|
+
}, i18next.t('common.app.remove'))))));
|
|
466
|
+
};
|
|
467
|
+
AnimalVehicleDetailsEditor.defaultProps = {
|
|
468
|
+
items: [],
|
|
469
|
+
fieldConfig: [],
|
|
470
|
+
onFieldChange: () => {},
|
|
471
|
+
onAddItem: () => {},
|
|
472
|
+
onRemoveItem: () => {},
|
|
473
|
+
canAddMore: true,
|
|
474
|
+
maxItems: 0,
|
|
475
|
+
className: 'w-full',
|
|
476
|
+
theme: undefined,
|
|
477
|
+
i18next: i18nextLocal
|
|
478
|
+
};
|
|
479
|
+
AnimalVehicleDetailsEditor.propTypes = {
|
|
480
|
+
/** Which chrome text set to use -- drives labels like "Animal"/"Vehicle", "Animals"/"Vehicles". */
|
|
481
|
+
itemType: PropTypes.oneOf(['animal', 'vehicle']).isRequired,
|
|
482
|
+
/** One entry per animal/vehicle. `values` is keyed by fieldConfig[].key. */
|
|
483
|
+
items: PropTypes.arrayOf(PropTypes.shape({
|
|
484
|
+
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
|
485
|
+
values: PropTypes.object
|
|
486
|
+
})),
|
|
487
|
+
/** Field definitions, already resolved to display strings (labels/placeholders/options) by the caller. */
|
|
488
|
+
fieldConfig: PropTypes.arrayOf(PropTypes.shape({
|
|
489
|
+
key: PropTypes.string.isRequired,
|
|
490
|
+
label: PropTypes.string.isRequired,
|
|
491
|
+
required: PropTypes.bool,
|
|
492
|
+
type: PropTypes.oneOf(['text', 'number', 'select', 'select_multiple', 'textarea', 'yes_no', 'date']),
|
|
493
|
+
options: PropTypes.arrayOf(PropTypes.string),
|
|
494
|
+
unit: PropTypes.string,
|
|
495
|
+
placeholder: PropTypes.string,
|
|
496
|
+
maxLength: PropTypes.number
|
|
497
|
+
})),
|
|
498
|
+
/** (type, value) => boolean. Injected rather than owned internally, so each host app's existing
|
|
499
|
+
* "has this field actually been answered" rule (yes_no's `false` counts, etc.) stays authoritative. */
|
|
500
|
+
isFieldAnswered: PropTypes.func.isRequired,
|
|
501
|
+
/** (itemId, fieldKey, value) => void */
|
|
502
|
+
onFieldChange: PropTypes.func,
|
|
503
|
+
/** () => void -- host owns the actual array/count mutation. */
|
|
504
|
+
onAddItem: PropTypes.func,
|
|
505
|
+
/** (itemId) => void -- host owns the actual array/count mutation. */
|
|
506
|
+
onRemoveItem: PropTypes.func,
|
|
507
|
+
/** Whether "Add" is enabled -- host computes this against its own per-lot/campground cap. */
|
|
508
|
+
canAddMore: PropTypes.bool,
|
|
509
|
+
/** Shown in the "max reached" message once canAddMore is false. */
|
|
510
|
+
maxItems: PropTypes.number,
|
|
511
|
+
/** Classes applied to the component's own wrapper div. */
|
|
512
|
+
className: PropTypes.string,
|
|
513
|
+
/** Theme object to use on this component, if none provided then the MUI5 theme provider theme is used. */
|
|
514
|
+
theme: PropTypes.object,
|
|
515
|
+
/** The i18next instance to translate with -- pass your own if the default singleton import isn't the one your app initialized. */
|
|
516
|
+
i18next: PropTypes.any
|
|
517
|
+
};
|
|
518
|
+
export default AnimalVehicleDetailsEditor;
|
package/dist/index.js
CHANGED
|
@@ -36,4 +36,5 @@ import HorizontalImageTile from './components/Images/HorizontalImageTile';
|
|
|
36
36
|
import VerticalImageTile from './components/Images/VerticalImageTile';
|
|
37
37
|
import EventCard from './components/Cards/EventCard';
|
|
38
38
|
import ImageAssets from './components/Icons/ImageAssets';
|
|
39
|
-
|
|
39
|
+
import AnimalVehicleDetailsEditor from './components/Reservation/AnimalVehicleDetailsEditor';
|
|
40
|
+
export { TestButton, CodeHighlight, CustomFab, HelpButton, GenericDialogWindow, PcSharedComponentThemeInheritor, ImageCanvasDraw, PCMScrollbar, TwoColumnDisplay, SimpleTab, HrefLink, GenericAppBar, ReusablePopupMenu, SearchBar, TillButton, ProductItemButton, DropdownButton, translationResources, coreLocals, currencySymbol, DateRangeCalendar, DateCalendar, SimpleLabel, CurrencyTextInput, ImageStack, PlatformPaymentPlans, PlatformPlanTitles, PlatformPlanPrices, LoadingBackdrop, SimpleAccordion, PricingCalendar, FancyDate, HorizontalImageTile, VerticalImageTile, EventCard, ImageAssets, AnimalVehicleDetailsEditor };
|
|
@@ -34,7 +34,9 @@
|
|
|
34
34
|
"needs_information": "{{count}} animal needs information",
|
|
35
35
|
"needs_information_plural": "{{count}} animals need information",
|
|
36
36
|
"complete_required_fields": "Complete {{count}} required field",
|
|
37
|
-
"complete_required_fields_plural": "Complete {{count}} required fields"
|
|
37
|
+
"complete_required_fields_plural": "Complete {{count}} required fields",
|
|
38
|
+
"remove_confirm_title": "Remove this animal?",
|
|
39
|
+
"remove_confirm_message": "All information entered for this animal will be lost. This can't be undone."
|
|
38
40
|
},
|
|
39
41
|
"app": {
|
|
40
42
|
"common": {
|
|
@@ -572,7 +574,9 @@
|
|
|
572
574
|
"needs_information": "{{count}} vehicle needs information",
|
|
573
575
|
"needs_information_plural": "{{count}} vehicles need information",
|
|
574
576
|
"complete_required_fields": "Complete {{count}} required field",
|
|
575
|
-
"complete_required_fields_plural": "Complete {{count}} required fields"
|
|
577
|
+
"complete_required_fields_plural": "Complete {{count}} required fields",
|
|
578
|
+
"remove_confirm_title": "Remove this vehicle?",
|
|
579
|
+
"remove_confirm_message": "All information entered for this vehicle will be lost. This can't be undone."
|
|
576
580
|
},
|
|
577
581
|
"common": {
|
|
578
582
|
"app": {
|
|
@@ -34,7 +34,9 @@
|
|
|
34
34
|
"needs_information": "{{count}} animal necesita información",
|
|
35
35
|
"needs_information_plural": "{{count}} animales necesitan información",
|
|
36
36
|
"complete_required_fields": "Complete {{count}} campo requerido",
|
|
37
|
-
"complete_required_fields_plural": "Complete {{count}} campos requeridos"
|
|
37
|
+
"complete_required_fields_plural": "Complete {{count}} campos requeridos",
|
|
38
|
+
"remove_confirm_title": "¿Eliminar este animal?",
|
|
39
|
+
"remove_confirm_message": "Toda la información ingresada para este animal se perderá. Esto no se puede deshacer."
|
|
38
40
|
},
|
|
39
41
|
"app": {
|
|
40
42
|
"common": {
|
|
@@ -572,7 +574,9 @@
|
|
|
572
574
|
"needs_information": "{{count}} vehículo necesita información",
|
|
573
575
|
"needs_information_plural": "{{count}} vehículos necesitan información",
|
|
574
576
|
"complete_required_fields": "Complete {{count}} campo requerido",
|
|
575
|
-
"complete_required_fields_plural": "Complete {{count}} campos requeridos"
|
|
577
|
+
"complete_required_fields_plural": "Complete {{count}} campos requeridos",
|
|
578
|
+
"remove_confirm_title": "¿Eliminar este vehículo?",
|
|
579
|
+
"remove_confirm_message": "Toda la información ingresada para este vehículo se perderá. Esto no se puede deshacer."
|
|
576
580
|
},
|
|
577
581
|
"common": {
|
|
578
582
|
"app": {
|
|
@@ -34,7 +34,9 @@
|
|
|
34
34
|
"needs_information": "{{count}} animal nécessite des informations",
|
|
35
35
|
"needs_information_plural": "{{count}} animaux nécessitent des informations",
|
|
36
36
|
"complete_required_fields": "Complétez {{count}} champ requis",
|
|
37
|
-
"complete_required_fields_plural": "Complétez {{count}} champs requis"
|
|
37
|
+
"complete_required_fields_plural": "Complétez {{count}} champs requis",
|
|
38
|
+
"remove_confirm_title": "Supprimer cet animal ?",
|
|
39
|
+
"remove_confirm_message": "Toutes les informations saisies pour cet animal seront perdues. Cela ne peut pas être annulé."
|
|
38
40
|
},
|
|
39
41
|
"app": {
|
|
40
42
|
"common": {
|
|
@@ -572,7 +574,9 @@
|
|
|
572
574
|
"needs_information": "{{count}} véhicule nécessite des informations",
|
|
573
575
|
"needs_information_plural": "{{count}} véhicules nécessitent des informations",
|
|
574
576
|
"complete_required_fields": "Complétez {{count}} champ requis",
|
|
575
|
-
"complete_required_fields_plural": "Complétez {{count}} champs requis"
|
|
577
|
+
"complete_required_fields_plural": "Complétez {{count}} champs requis",
|
|
578
|
+
"remove_confirm_title": "Supprimer ce véhicule ?",
|
|
579
|
+
"remove_confirm_message": "Toutes les informations saisies pour ce véhicule seront perdues. Cela ne peut pas être annulé."
|
|
576
580
|
},
|
|
577
581
|
"common": {
|
|
578
582
|
"app": {
|
package/dist/styles/tailwind.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2196f380;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.static{position:static}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.-top-2{top:-.2rem}.-top-6{top:-.6rem}.bottom-0{bottom:0}.left-0{left:0}.right-0{right:0}.top-0{top:0}.top-20{top:2rem}.top-64{top:6.4rem}.z-10{z-index:10}.z-99{z-index:99}.m-10{margin:1rem}.m-12{margin:1.2rem}.m-24{margin:2.4rem}.m-4{margin:.4rem}.m-6{margin:.6rem}.m-auto{margin:auto}.mx-0{margin-left:0;margin-right:0}.mx-12{margin-left:1.2rem;margin-right:1.2rem}.mx-2{margin-left:.2rem;margin-right:.2rem}.mx-4{margin-left:.4rem;margin-right:.4rem}.mx-6{margin-left:.6rem;margin-right:.6rem}.mx-8{margin-left:.8rem;margin-right:.8rem}.mx-auto{margin-left:auto;margin-right:auto}.my-12{margin-top:1.2rem;margin-bottom:1.2rem}.my-24{margin-top:2.4rem;margin-bottom:2.4rem}.my-4{margin-top:.4rem;margin-bottom:.4rem}.my-6{margin-top:.6rem;margin-bottom:.6rem}.my-auto{margin-top:auto;margin-bottom:auto}.-ml-10{margin-left:-1rem}.mb-0{margin-bottom:0}.mb-12{margin-bottom:1.2rem}.mb-2{margin-bottom:.2rem}.mb-24{margin-bottom:2.4rem}.mb-6{margin-bottom:.6rem}.ml-0{margin-left:0}.ml-1{margin-left:.1rem}.ml-12{margin-left:1.2rem}.ml-24{margin-left:2.4rem}.ml-6{margin-left:.6rem}.ml-8{margin-left:.8rem}.mr-0{margin-right:0}.mr-12{margin-right:1.2rem}.mr-24{margin-right:2.4rem}.mr-6{margin-right:.6rem}.mt-0{margin-top:0}.mt-12{margin-top:1.2rem}.mt-24{margin-top:2.4rem}.mt-4{margin-top:.4rem}.mt-6{margin-top:.6rem}.mt-auto{margin-top:auto}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-136{height:13.6rem}.h-200{height:20rem}.h-24{height:2.4rem}.h-400{height:40rem}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-32{max-height:3.2rem}.max-h-512{max-height:51.2rem}.min-h-160{min-height:16rem}.min-h-224{min-height:22.4rem}.min-h-256{min-height:25.6rem}.w-1\/2{width:50%}.w-2\/5{width:40%}.w-24{width:2.4rem}.w-3\/4{width:75%}.w-auto{width:auto}.w-full{width:100%}.max-w-full{max-width:100%}.max-w-min{max-width:-moz-min-content;max-width:min-content}.flex-shrink-0{flex-shrink:0}.grow{flex-grow:1}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-rows-2{grid-template-rows:repeat(2,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.gap-6{gap:.6rem}.space-x-10>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overscroll-none{overscroll-behavior:none}.truncate{overflow:hidden;white-space:nowrap}.overflow-ellipsis,.truncate{text-overflow:ellipsis}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.rounded{border-radius:.4rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.8rem}.rounded-md{border-radius:.6rem}.rounded-t-md{border-top-left-radius:.6rem;border-top-right-radius:.6rem}.rounded-bl-lg{border-bottom-left-radius:.8rem}.rounded-br-lg{border-bottom-right-radius:.8rem}.rounded-tl-lg{border-top-left-radius:.8rem}.rounded-tr-lg{border-top-right-radius:.8rem}.border{border-width:1px}.border-2{border-width:2px}.border-t-8{border-top-width:8px}.border-transparent{border-color:#0000}.bg-black{--tw-bg-opacity:1;background-color:rgb(34 41 47/var(--tw-bg-opacity,1))}.bg-blue{--tw-bg-opacity:1;background-color:rgb(33 150 243/var(--tw-bg-opacity,1))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(66 66 66/var(--tw-bg-opacity,1))}.bg-green-600{--tw-bg-opacity:1;background-color:rgb(67 160 71/var(--tw-bg-opacity,1))}.bg-grey-100{--tw-bg-opacity:1;background-color:rgb(245 245 245/var(--tw-bg-opacity,1))}.bg-grey-200{--tw-bg-opacity:1;background-color:rgb(238 238 238/var(--tw-bg-opacity,1))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-yellow-100\/50{background-color:#fff9c480}.bg-cover{background-size:cover}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-10{padding:1rem}.p-12{padding:1.2rem}.p-24{padding:2.4rem}.p-6{padding:.6rem}.px-2{padding-left:.2rem;padding-right:.2rem}.px-4{padding-left:.4rem;padding-right:.4rem}.px-6{padding-left:.6rem;padding-right:.6rem}.px-8{padding-left:.8rem;padding-right:.8rem}.py-2{padding-top:.2rem;padding-bottom:.2rem}.py-4{padding-top:.4rem;padding-bottom:.4rem}.py-6{padding-top:.6rem;padding-bottom:.6rem}.pb-4{padding-bottom:.4rem}.pl-0{padding-left:0}.pl-4{padding-left:.4rem}.pl-8{padding-left:.8rem}.pr-0{padding-right:0}.pr-6{padding-right:.6rem}.pt-0{padding-top:0}.pt-12{padding-top:1.2rem}.pt-4{padding-top:.4rem}.text-left{text-align:left}.text-center{text-align:center}.font-sans{font-family:Muli,Roboto,-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.font-serif{font-family:Georgia,Cambria,Times New Roman,Times,serif}.text-14{font-size:1.4rem}.text-16{font-size:1.6rem}.text-17{font-size:1.7rem}.text-24,.text-2xl{font-size:2.4rem}.text-2xl{line-height:3.2rem}.text-32{font-size:3.2rem}.text-4xl{font-size:3.6rem;line-height:4rem}.text-5xl{font-size:4.8rem;line-height:1}.text-6xl{font-size:6rem;line-height:1}.text-base{font-size:1.6rem;line-height:2.4rem}.text-sm{font-size:1.4rem;line-height:2rem}.text-xl{font-size:2rem;line-height:2.8rem}.font-500{font-weight:500}.font-600{font-weight:600}.font-800{font-weight:800}.font-900{font-weight:900}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.capitalize{text-transform:capitalize}.normal-case{text-transform:none}.leading-none{line-height:1}.leading-tight{line-height:1.25}.tracking-tight{letter-spacing:-.025em}.text-gray-300{--tw-text-opacity:1;color:rgb(224 224 224/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(158 158 158/var(--tw-text-opacity,1))}.text-gray-600{--tw-text-opacity:1;color:rgb(117 117 117/var(--tw-text-opacity,1))}.text-gray-700{--tw-text-opacity:1;color:rgb(97 97 97/var(--tw-text-opacity,1))}.text-green-600{--tw-text-opacity:1;color:rgb(67 160 71/var(--tw-text-opacity,1))}.text-green-700{--tw-text-opacity:1;color:rgb(56 142 60/var(--tw-text-opacity,1))}.text-grey-800{--tw-text-opacity:1;color:rgb(66 66 66/var(--tw-text-opacity,1))}.text-orange-600{--tw-text-opacity:1;color:rgb(251 140 0/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.underline{text-decoration-line:underline}.line-through{text-decoration-line:line-through}.no-underline{text-decoration-line:none}.decoration-gray-500{text-decoration-color:#9e9e9e}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px 0 #0000000f;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px 0 var(--tw-shadow-color)}.shadow,.shadow-1{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-1{--tw-shadow:0px 2px 1px -1px #0003,0px 1px 1px 0px #00000024,0px 1px 3px 0px #0000001f;--tw-shadow-colored:0px 2px 1px -1px var(--tw-shadow-color),0px 1px 1px 0px var(--tw-shadow-color),0px 1px 3px 0px var(--tw-shadow-color)}.shadow-2{--tw-shadow:0px 3px 1px -2px #0003,0px 2px 2px 0px #00000024,0px 1px 5px 0px #0000001f;--tw-shadow-colored:0px 3px 1px -2px var(--tw-shadow-color),0px 2px 2px 0px var(--tw-shadow-color),0px 1px 5px 0px var(--tw-shadow-color)}.shadow-2,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -1px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.blur{--tw-blur:blur(8px)}.blur,.contrast-0{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.contrast-0{--tw-contrast:contrast(0)}.drop-shadow{--tw-drop-shadow:drop-shadow(0 1px 2px #0000001a) drop-shadow(0 1px 1px #0000000f)}.drop-shadow,.drop-shadow-none{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow-none{--tw-drop-shadow:drop-shadow(0 0 #0000)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.hover\:translate-y-1:hover{--tw-translate-y:0.1rem}.hover\:rotate-3:hover,.hover\:translate-y-1:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:rotate-3:hover{--tw-rotate:3deg}.hover\:skew-y-3:hover{--tw-skew-y:3deg}.hover\:scale-105:hover,.hover\:skew-y-3:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05}.hover\:list-disc:hover{list-style-type:disc}.hover\:bg-gray-100\/75:hover{background-color:#f5f5f5bf}.hover\:bg-green-700:hover{--tw-bg-opacity:1;background-color:rgb(56 142 60/var(--tw-bg-opacity,1))}.hover\:bg-grey-300:hover{--tw-bg-opacity:1;background-color:rgb(224 224 224/var(--tw-bg-opacity,1))}.hover\:bg-indigo-100\/25:hover{background-color:#c5cae940}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(97 97 97/var(--tw-text-opacity,1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:brightness-75:hover{--tw-brightness:brightness(.75)}.hover\:brightness-75:hover,.hover\:drop-shadow-2xl:hover{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.hover\:drop-shadow-2xl:hover{--tw-drop-shadow:drop-shadow(0 25px 25px #00000026)}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-green-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(76 175 80/var(--tw-ring-opacity,1))}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px}@media (min-width:600px){.sm\:p-8{padding:.8rem}}@media (min-width:960px){.md\:mx-auto{margin-left:auto;margin-right:auto}.md\:ml-12{margin-left:1.2rem}.md\:flex{display:flex}.md\:hidden{display:none}.md\:max-w-288{max-width:28.8rem}.md\:flex-row{flex-direction:row}.md\:flex-col{flex-direction:column}.md\:pt-0{padding-top:0}}@media (prefers-color-scheme:dark){.dark\:text-gray-500{--tw-text-opacity:1;color:rgb(158 158 158/var(--tw-text-opacity,1))}.dark\:text-green-500{--tw-text-opacity:1;color:rgb(76 175 80/var(--tw-text-opacity,1))}.dark\:text-orange-500{--tw-text-opacity:1;color:rgb(255 152 0/var(--tw-text-opacity,1))}}
|
|
1
|
+
*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2196f380;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.visible{visibility:visible}.static{position:static}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.-top-2{top:-.2rem}.-top-6{top:-.6rem}.bottom-0{bottom:0}.left-0{left:0}.right-0{right:0}.top-0{top:0}.top-20{top:2rem}.top-64{top:6.4rem}.z-10{z-index:10}.z-99{z-index:99}.col-span-full{grid-column:1/-1}.m-10{margin:1rem}.m-12{margin:1.2rem}.m-24{margin:2.4rem}.m-4{margin:.4rem}.m-6{margin:.6rem}.m-auto{margin:auto}.mx-0{margin-left:0;margin-right:0}.mx-12{margin-left:1.2rem;margin-right:1.2rem}.mx-2{margin-left:.2rem;margin-right:.2rem}.mx-4{margin-left:.4rem;margin-right:.4rem}.mx-6{margin-left:.6rem;margin-right:.6rem}.mx-8{margin-left:.8rem;margin-right:.8rem}.mx-auto{margin-left:auto;margin-right:auto}.my-12{margin-top:1.2rem;margin-bottom:1.2rem}.my-24{margin-top:2.4rem;margin-bottom:2.4rem}.my-4{margin-top:.4rem;margin-bottom:.4rem}.my-6{margin-top:.6rem;margin-bottom:.6rem}.my-auto{margin-top:auto;margin-bottom:auto}.-ml-10{margin-left:-1rem}.mb-0{margin-bottom:0}.mb-12{margin-bottom:1.2rem}.mb-2{margin-bottom:.2rem}.mb-24{margin-bottom:2.4rem}.mb-6{margin-bottom:.6rem}.mb-8{margin-bottom:.8rem}.ml-0{margin-left:0}.ml-1{margin-left:.1rem}.ml-12{margin-left:1.2rem}.ml-24{margin-left:2.4rem}.ml-6{margin-left:.6rem}.ml-8{margin-left:.8rem}.mr-0{margin-right:0}.mr-12{margin-right:1.2rem}.mr-24{margin-right:2.4rem}.mr-6{margin-right:.6rem}.mt-0{margin-top:0}.mt-12{margin-top:1.2rem}.mt-24{margin-top:2.4rem}.mt-4{margin-top:.4rem}.mt-6{margin-top:.6rem}.mt-auto{margin-top:auto}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-136{height:13.6rem}.h-200{height:20rem}.h-24{height:2.4rem}.h-400{height:40rem}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-32{max-height:3.2rem}.max-h-512{max-height:51.2rem}.min-h-160{min-height:16rem}.min-h-224{min-height:22.4rem}.min-h-256{min-height:25.6rem}.w-1\/2{width:50%}.w-2\/5{width:40%}.w-24{width:2.4rem}.w-3\/4{width:75%}.w-auto{width:auto}.w-full{width:100%}.max-w-full{max-width:100%}.max-w-min{max-width:-moz-min-content;max-width:min-content}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.grow{flex-grow:1}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-rows-2{grid-template-rows:repeat(2,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.gap-4{gap:.4rem}.gap-6{gap:.6rem}.space-x-10>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overscroll-none{overscroll-behavior:none}.truncate{overflow:hidden;white-space:nowrap}.overflow-ellipsis,.truncate{text-overflow:ellipsis}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.rounded{border-radius:.4rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.8rem}.rounded-md{border-radius:.6rem}.rounded-t-md{border-top-left-radius:.6rem;border-top-right-radius:.6rem}.rounded-bl-lg{border-bottom-left-radius:.8rem}.rounded-br-lg{border-bottom-right-radius:.8rem}.rounded-tl-lg{border-top-left-radius:.8rem}.rounded-tr-lg{border-top-right-radius:.8rem}.border{border-width:1px}.border-2{border-width:2px}.border-t-8{border-top-width:8px}.border-transparent{border-color:#0000}.bg-black{--tw-bg-opacity:1;background-color:rgb(34 41 47/var(--tw-bg-opacity,1))}.bg-blue{--tw-bg-opacity:1;background-color:rgb(33 150 243/var(--tw-bg-opacity,1))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(66 66 66/var(--tw-bg-opacity,1))}.bg-green-600{--tw-bg-opacity:1;background-color:rgb(67 160 71/var(--tw-bg-opacity,1))}.bg-grey-100{--tw-bg-opacity:1;background-color:rgb(245 245 245/var(--tw-bg-opacity,1))}.bg-grey-200{--tw-bg-opacity:1;background-color:rgb(238 238 238/var(--tw-bg-opacity,1))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-yellow-100\/50{background-color:#fff9c480}.bg-cover{background-size:cover}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-10{padding:1rem}.p-12{padding:1.2rem}.p-24{padding:2.4rem}.p-6{padding:.6rem}.px-2{padding-left:.2rem;padding-right:.2rem}.px-4{padding-left:.4rem;padding-right:.4rem}.px-6{padding-left:.6rem;padding-right:.6rem}.px-8{padding-left:.8rem;padding-right:.8rem}.py-2{padding-top:.2rem;padding-bottom:.2rem}.py-4{padding-top:.4rem;padding-bottom:.4rem}.py-6{padding-top:.6rem;padding-bottom:.6rem}.pb-4{padding-bottom:.4rem}.pl-0{padding-left:0}.pl-4{padding-left:.4rem}.pl-8{padding-left:.8rem}.pr-0{padding-right:0}.pr-6{padding-right:.6rem}.pt-0{padding-top:0}.pt-12{padding-top:1.2rem}.pt-4{padding-top:.4rem}.text-left{text-align:left}.text-center{text-align:center}.font-sans{font-family:Muli,Roboto,-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.font-serif{font-family:Georgia,Cambria,Times New Roman,Times,serif}.text-14{font-size:1.4rem}.text-16{font-size:1.6rem}.text-17{font-size:1.7rem}.text-24,.text-2xl{font-size:2.4rem}.text-2xl{line-height:3.2rem}.text-32{font-size:3.2rem}.text-4xl{font-size:3.6rem;line-height:4rem}.text-5xl{font-size:4.8rem;line-height:1}.text-6xl{font-size:6rem;line-height:1}.text-base{font-size:1.6rem;line-height:2.4rem}.text-sm{font-size:1.4rem;line-height:2rem}.text-xl{font-size:2rem;line-height:2.8rem}.font-500{font-weight:500}.font-600{font-weight:600}.font-800{font-weight:800}.font-900{font-weight:900}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.capitalize{text-transform:capitalize}.normal-case{text-transform:none}.leading-none{line-height:1}.leading-tight{line-height:1.25}.tracking-tight{letter-spacing:-.025em}.text-gray-300{--tw-text-opacity:1;color:rgb(224 224 224/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(158 158 158/var(--tw-text-opacity,1))}.text-gray-600{--tw-text-opacity:1;color:rgb(117 117 117/var(--tw-text-opacity,1))}.text-gray-700{--tw-text-opacity:1;color:rgb(97 97 97/var(--tw-text-opacity,1))}.text-green-600{--tw-text-opacity:1;color:rgb(67 160 71/var(--tw-text-opacity,1))}.text-green-700{--tw-text-opacity:1;color:rgb(56 142 60/var(--tw-text-opacity,1))}.text-grey-800{--tw-text-opacity:1;color:rgb(66 66 66/var(--tw-text-opacity,1))}.text-orange-600{--tw-text-opacity:1;color:rgb(251 140 0/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.underline{text-decoration-line:underline}.line-through{text-decoration-line:line-through}.no-underline{text-decoration-line:none}.decoration-gray-500{text-decoration-color:#9e9e9e}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px 0 #0000000f;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px 0 var(--tw-shadow-color)}.shadow,.shadow-1{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-1{--tw-shadow:0px 2px 1px -1px #0003,0px 1px 1px 0px #00000024,0px 1px 3px 0px #0000001f;--tw-shadow-colored:0px 2px 1px -1px var(--tw-shadow-color),0px 1px 1px 0px var(--tw-shadow-color),0px 1px 3px 0px var(--tw-shadow-color)}.shadow-2{--tw-shadow:0px 3px 1px -2px #0003,0px 2px 2px 0px #00000024,0px 1px 5px 0px #0000001f;--tw-shadow-colored:0px 3px 1px -2px var(--tw-shadow-color),0px 2px 2px 0px var(--tw-shadow-color),0px 1px 5px 0px var(--tw-shadow-color)}.shadow-2,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -1px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.blur{--tw-blur:blur(8px)}.blur,.contrast-0{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.contrast-0{--tw-contrast:contrast(0)}.drop-shadow{--tw-drop-shadow:drop-shadow(0 1px 2px #0000001a) drop-shadow(0 1px 1px #0000000f)}.drop-shadow,.drop-shadow-none{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow-none{--tw-drop-shadow:drop-shadow(0 0 #0000)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.hover\:translate-y-1:hover{--tw-translate-y:0.1rem}.hover\:rotate-3:hover,.hover\:translate-y-1:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:rotate-3:hover{--tw-rotate:3deg}.hover\:skew-y-3:hover{--tw-skew-y:3deg}.hover\:scale-105:hover,.hover\:skew-y-3:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05}.hover\:list-disc:hover{list-style-type:disc}.hover\:bg-gray-100\/75:hover{background-color:#f5f5f5bf}.hover\:bg-green-700:hover{--tw-bg-opacity:1;background-color:rgb(56 142 60/var(--tw-bg-opacity,1))}.hover\:bg-grey-300:hover{--tw-bg-opacity:1;background-color:rgb(224 224 224/var(--tw-bg-opacity,1))}.hover\:bg-indigo-100\/25:hover{background-color:#c5cae940}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(97 97 97/var(--tw-text-opacity,1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:brightness-75:hover{--tw-brightness:brightness(.75)}.hover\:brightness-75:hover,.hover\:drop-shadow-2xl:hover{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.hover\:drop-shadow-2xl:hover{--tw-drop-shadow:drop-shadow(0 25px 25px #00000026)}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-green-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(76 175 80/var(--tw-ring-opacity,1))}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px}@media (min-width:600px){.sm\:p-8{padding:.8rem}}@media (min-width:960px){.md\:mx-auto{margin-left:auto;margin-right:auto}.md\:ml-12{margin-left:1.2rem}.md\:flex{display:flex}.md\:hidden{display:none}.md\:max-w-288{max-width:28.8rem}.md\:flex-row{flex-direction:row}.md\:flex-col{flex-direction:column}.md\:pt-0{padding-top:0}}@media (prefers-color-scheme:dark){.dark\:text-gray-500{--tw-text-opacity:1;color:rgb(158 158 158/var(--tw-text-opacity,1))}.dark\:text-green-500{--tw-text-opacity:1;color:rgb(76 175 80/var(--tw-text-opacity,1))}.dark\:text-orange-500{--tw-text-opacity:1;color:rgb(255 152 0/var(--tw-text-opacity,1))}}
|