pcm-shared-components 2.1.403 → 2.1.405

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,262 @@
1
+ import React, { useLayoutEffect, useRef, useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Typography, Paper, Button, Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material';
4
+ import { ThemeProvider } from '@mui/system';
5
+ import { createTheme, useTheme } from '@mui/material/styles';
6
+ import * as i18nextLocal from 'i18next';
7
+ import { renderFieldTypeControl } from './fieldTypeControl';
8
+
9
+ // Collapsed height for a notice block before it needs a "View full ..." link. A handful of lines
10
+ // of admin-entered text/markup fits inside this without ever showing the link at all; anything
11
+ // longer gets clipped here and offered in full through the dialog below.
12
+ const NOTICE_COLLAPSED_MAX_HEIGHT = 160;
13
+
14
+ // Field-type controls this block ever renders inline (everything else -- 'notice' -- gets its own
15
+ // read-only display, not a live input control).
16
+ const INPUT_FIELD_TYPES = ['text', 'select', 'select_multiple', 'number', 'textarea', 'yes_no', 'date'];
17
+
18
+ // Full-width field types, same rule AnimalVehicleDetailsEditor's per-item grid uses for its
19
+ // non-orphan fields (a dropdown/textarea/multi-select reads badly squeezed into a half column).
20
+ // This block skips that component's further wrapped-label-promotion pass (labelRefs/wrappedKeys in
21
+ // index.jsx) -- once-per-reservation fields are typically a handful at most, so the extra
22
+ // measurement machinery needed to keep a large tab-per-animal grid's columns aligned isn't worth
23
+ // carrying here too.
24
+ const isFullWidthField = field => ['select', 'textarea', 'select_multiple'].includes(field.type);
25
+
26
+ // `once_per_reservation`/`content_html` are read from the field object itself first (the flat,
27
+ // "normalized" shape this block's `fields` prop expects -- the same convention
28
+ // AnimalVehicleDetailsEditor's `fieldConfig` already uses for label/options/unit/placeholder: the
29
+ // caller resolves the raw lot_animal_fields.meta payload into flat props before handing fields to
30
+ // either component). A `field.meta.<key>` fallback is also accepted so a caller who instead passes
31
+ // the meta object through unflattened still works.
32
+ const readFieldProp = (field, key) => field[key] !== undefined ? field[key] : field.meta?.[key];
33
+
34
+ /**
35
+ * One read-only "View full {label}" notice block: renders `field`'s sanitized content_html inside
36
+ * a bounded-height container, and only if that content actually overflows the bound does it show a
37
+ * link that opens the full content in a Dialog. Not exported -- internal to AnimalFieldsOnceBlock,
38
+ * which is the only place a `type: 'notice'` field ever gets rendered.
39
+ */
40
+ const NoticeFieldBlock = ({
41
+ field,
42
+ i18next
43
+ }) => {
44
+ const contentRef = useRef(null);
45
+ const [overflowing, setOverflowing] = useState(false);
46
+ const [dialogOpen, setDialogOpen] = useState(false);
47
+ // Already HTML-sanitized server-side before this ever reaches the client -- safe to render as-is.
48
+ const contentHtml = readFieldProp(field, 'content_html') || '';
49
+
50
+ // Measured after mount/paint (useLayoutEffect, not useEffect) so the "View full ..." link never
51
+ // flashes in for a heartbeat on content that turns out to fit -- same reasoning
52
+ // AnimalVehicleDetailsEditor's own label-wrap measurement (wrappedKeys, index.jsx) already uses.
53
+ // Re-checked on window resize too: the height bound is fixed in CSS, but at a narrower viewport
54
+ // the same HTML can wrap onto more lines and start overflowing where it didn't before.
55
+ useLayoutEffect(() => {
56
+ const checkOverflow = () => {
57
+ const el = contentRef.current;
58
+ if (!el) return;
59
+ setOverflowing(el.scrollHeight > el.clientHeight);
60
+ };
61
+ checkOverflow();
62
+ window.addEventListener('resize', checkOverflow);
63
+ return () => window.removeEventListener('resize', checkOverflow);
64
+ }, [contentHtml]);
65
+ return /*#__PURE__*/React.createElement("div", {
66
+ className: "flex flex-col",
67
+ style: {
68
+ gap: 4
69
+ }
70
+ }, /*#__PURE__*/React.createElement(Typography, {
71
+ variant: "body2",
72
+ sx: {
73
+ fontWeight: 500
74
+ }
75
+ }, field.label), /*#__PURE__*/React.createElement(Paper, {
76
+ variant: "outlined",
77
+ sx: {
78
+ p: 1.5,
79
+ borderRadius: 1,
80
+ bgcolor: 'action.hover',
81
+ maxHeight: NOTICE_COLLAPSED_MAX_HEIGHT,
82
+ overflow: 'hidden'
83
+ }
84
+ }, /*#__PURE__*/React.createElement("div", {
85
+ ref: contentRef,
86
+ dangerouslySetInnerHTML: {
87
+ __html: contentHtml
88
+ }
89
+ })), overflowing && /*#__PURE__*/React.createElement(Button, {
90
+ size: "small",
91
+ onClick: () => setDialogOpen(true),
92
+ sx: {
93
+ alignSelf: 'flex-start',
94
+ textTransform: 'none',
95
+ minWidth: 0,
96
+ p: 0
97
+ }
98
+ }, i18next.t('animal.view_full_field', {
99
+ label: field.label
100
+ })), /*#__PURE__*/React.createElement(Dialog, {
101
+ open: dialogOpen,
102
+ onClose: () => setDialogOpen(false),
103
+ maxWidth: "sm",
104
+ fullWidth: true,
105
+ scroll: "paper"
106
+ }, /*#__PURE__*/React.createElement(DialogTitle, null, field.label), /*#__PURE__*/React.createElement(DialogContent, {
107
+ dividers: true
108
+ }, /*#__PURE__*/React.createElement("div", {
109
+ dangerouslySetInnerHTML: {
110
+ __html: contentHtml
111
+ }
112
+ })), /*#__PURE__*/React.createElement(DialogActions, null, /*#__PURE__*/React.createElement(Button, {
113
+ onClick: () => setDialogOpen(false)
114
+ }, i18next.t('common.app.close')))));
115
+ };
116
+ NoticeFieldBlock.propTypes = {
117
+ field: PropTypes.shape({
118
+ key: PropTypes.string.isRequired,
119
+ label: PropTypes.string.isRequired,
120
+ content_html: PropTypes.string,
121
+ meta: PropTypes.object
122
+ }).isRequired,
123
+ i18next: PropTypes.any.isRequired
124
+ };
125
+
126
+ /**
127
+ * Flat, non-tabbed block for a lot's "once per reservation" animal fields: no tabs, no per-animal
128
+ * chrome, no add/remove -- these are single shared values/notices for the whole reservation, not
129
+ * one row per animal. Renders two kinds of entries, in whatever order `fields` gives them:
130
+ *
131
+ * - Any input-type field (text/select/number/textarea/yes_no/date/select_multiple) whose config
132
+ * opts into `once_per_reservation` -- reuses the exact same `renderFieldTypeControl` that
133
+ * AnimalVehicleDetailsEditor's tab-per-animal grid uses (see fieldTypeControl.jsx, this
134
+ * directory), so a once-per-reservation field looks and behaves identically to its per-animal
135
+ * counterpart.
136
+ * - Any `field_type === 'notice'` field -- a read-only sanitized-HTML display, never an input.
137
+ * `once_per_reservation` doesn't apply to notices (they're never per-animal to begin with) and
138
+ * is ignored for this type.
139
+ *
140
+ * `fields` does NOT need to be pre-filtered: this component filters internally (any field that is
141
+ * neither a notice nor once_per_reservation is silently skipped), so it's safe to pass the lot's
142
+ * whole field list straight through. Passing an already-filtered subset works identically, since
143
+ * the filter is idempotent.
144
+ *
145
+ * Two usage modes, both through this one component:
146
+ * - Editable (staff/guest edit flow): pass `onChange`. Inputs render live and call
147
+ * `onChange(field.key, newValue)`.
148
+ * - Read-only (review screen): omit `onChange` entirely. Every input control renders disabled
149
+ * (MUI's own disabled/read-only appearance) instead of interactive -- there is no second
150
+ * "read-only variant" component to import, this is the same export either way. The notice
151
+ * block's "View full ..." link/dialog behaves identically in both modes, since it was never an
152
+ * input.
153
+ *
154
+ * ## Importing the component in your project
155
+ *
156
+ ```js
157
+
158
+ import {AnimalFieldsOnceBlock} from 'pcm-shared-components';
159
+
160
+ ```
161
+ *
162
+ */
163
+ export const AnimalFieldsOnceBlock = props => {
164
+ const {
165
+ fields,
166
+ values,
167
+ onChange,
168
+ className,
169
+ theme,
170
+ i18next
171
+ } = props;
172
+ const compTheme = theme || useTheme();
173
+ const defaultTheme = createTheme(compTheme);
174
+ const relevantFields = fields.filter(field => field.type === 'notice' || INPUT_FIELD_TYPES.includes(field.type) && readFieldProp(field, 'once_per_reservation') === true);
175
+ if (relevantFields.length === 0) return null;
176
+ return /*#__PURE__*/React.createElement(ThemeProvider, {
177
+ theme: defaultTheme
178
+ }, /*#__PURE__*/React.createElement("div", {
179
+ className: className
180
+ }, /*#__PURE__*/React.createElement("div", {
181
+ className: "grid grid-cols-2",
182
+ style: {
183
+ columnGap: 12,
184
+ rowGap: 16,
185
+ gridAutoFlow: 'row dense'
186
+ }
187
+ }, relevantFields.map(field => {
188
+ if (field.type === 'notice') {
189
+ return /*#__PURE__*/React.createElement("div", {
190
+ key: field.key,
191
+ className: "col-span-full"
192
+ }, /*#__PURE__*/React.createElement(NoticeFieldBlock, {
193
+ field: field,
194
+ i18next: i18next
195
+ }));
196
+ }
197
+ const rawValue = values?.[field.key] ?? (field.type === 'select_multiple' ? [] : '');
198
+ const labelText = field.required ? `${field.label} *` : field.label;
199
+ return /*#__PURE__*/React.createElement("div", {
200
+ key: field.key,
201
+ className: isFullWidthField(field) ? 'col-span-full' : undefined
202
+ }, /*#__PURE__*/React.createElement(Typography, {
203
+ variant: "body2",
204
+ sx: {
205
+ fontWeight: 500,
206
+ mb: 0.5
207
+ }
208
+ }, labelText), renderFieldTypeControl({
209
+ field,
210
+ value: rawValue,
211
+ // Read-only mode (no onChange prop): the control renders disabled, so this
212
+ // handler is unreachable -- still a no-op rather than undefined, in case a
213
+ // consumer's own event wiring calls it directly in a test.
214
+ onChange: onChange ? newValue => onChange(field.key, newValue) : () => {},
215
+ disabled: !onChange,
216
+ error: false,
217
+ helperText: '',
218
+ i18next
219
+ }));
220
+ }))));
221
+ };
222
+ AnimalFieldsOnceBlock.defaultProps = {
223
+ fields: [],
224
+ values: {},
225
+ onChange: undefined,
226
+ className: 'w-full',
227
+ theme: undefined,
228
+ i18next: i18nextLocal
229
+ };
230
+ AnimalFieldsOnceBlock.propTypes = {
231
+ /** The lot's field configs -- does not need to be pre-filtered, see the component doc above.
232
+ * Normalized to the same flat shape AnimalVehicleDetailsEditor's `fieldConfig` already uses
233
+ * (label/options/unit/placeholder resolved by the caller), plus this feature's two additions:
234
+ * `once_per_reservation` (input types) and `content_html` (type 'notice'). Both are also read
235
+ * from `field.meta.<key>` as a fallback if a caller passes the meta object through unflattened. */
236
+ fields: PropTypes.arrayOf(PropTypes.shape({
237
+ key: PropTypes.string.isRequired,
238
+ label: PropTypes.string.isRequired,
239
+ type: PropTypes.oneOf(['text', 'number', 'select', 'select_multiple', 'textarea', 'yes_no', 'date', 'notice']).isRequired,
240
+ required: PropTypes.bool,
241
+ options: PropTypes.arrayOf(PropTypes.string),
242
+ unit: PropTypes.string,
243
+ placeholder: PropTypes.string,
244
+ maxLength: PropTypes.number,
245
+ once_per_reservation: PropTypes.bool,
246
+ content_html: PropTypes.string,
247
+ meta: PropTypes.object
248
+ })),
249
+ /** One animal's `field_values`, keyed by field.key -- safe to read from any single animal row
250
+ * since once-per-reservation values are kept synced identically across every animal. */
251
+ values: PropTypes.object,
252
+ /** (fieldKey, value) => void. Omit entirely to render every input control disabled/read-only
253
+ * (review-screen usage) -- see the component doc above. */
254
+ onChange: PropTypes.func,
255
+ /** Classes applied to the component's own wrapper div. */
256
+ className: PropTypes.string,
257
+ /** Theme object to use on this component, if none provided then the MUI5 theme provider theme is used. */
258
+ theme: PropTypes.object,
259
+ /** The i18next instance to translate with -- pass your own if the default singleton import isn't the one your app initialized. */
260
+ i18next: PropTypes.any
261
+ };
262
+ export default AnimalFieldsOnceBlock;
@@ -0,0 +1,189 @@
1
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
+ import React from 'react';
3
+ import { TextField, InputAdornment, MenuItem, ToggleButton, ToggleButtonGroup, Checkbox, ListItemText, Chip } from '@mui/material';
4
+
5
+ // A native <input type="date"> only opens its calendar popup on its own when the browser's tiny
6
+ // built-in icon is clicked -- clicking anywhere else in the field just places the text caret
7
+ // (still lets someone type the year/month/day directly, which showPicker() doesn't change). Most
8
+ // people expect clicking anywhere in the box to open the calendar. showPicker() is Chrome/Edge/
9
+ // Firefox only as of this writing (not Safari) and throws if called on a disabled/read-only input
10
+ // or outside a user gesture, so this fails silently rather than breaking the click -- on an
11
+ // unsupported browser, the field just falls back to manual typing and the browser's own
12
+ // icon-click affordance, exactly as before.
13
+ export const openNativeDatePicker = e => {
14
+ try {
15
+ e.target.showPicker?.();
16
+ } catch {
17
+ // ignore -- unsupported browser or transient DOM state, typing/icon-click still work
18
+ }
19
+ };
20
+
21
+ /**
22
+ * Renders the single form control for one {field, value, onChange} triple across every field type
23
+ * this feature knows about: text / number / select / select_multiple / textarea / yes_no / date
24
+ * (unknown/legacy types fall back to plain text, same as before). Pulled out of the per-item field
25
+ * grid in `index.jsx` (AnimalVehicleDetailsEditor's tab-per-animal editor) so
26
+ * `AnimalFieldsOnceBlock`'s flat once-per-reservation layout, in the same directory, can render the
27
+ * exact same controls without a second copy of this switch. Both call sites feed it the same shape
28
+ * and get back one MUI element (`<TextField>` / `<ToggleButtonGroup>`).
29
+ *
30
+ * Deliberately NOT responsible for:
31
+ * - The "drifted value" read-only display (a stored value that no longer matches the field's
32
+ * current type/options) -- that's a meta-concern about which control to show at all, decided by
33
+ * the caller before it ever gets here, not part of "how do I render a control of this type".
34
+ * - The required-field error caption under a `yes_no` control -- both call sites render that
35
+ * themselves right after this control, since its spacing differs slightly between the tab grid
36
+ * and the flat once-block layout.
37
+ *
38
+ * @param {object} params
39
+ * @param {object} params.field - `{ key, type, label, options?, unit?, placeholder?, maxLength? }`.
40
+ * Only `key`/`type` and the type-specific extras are read here; `label`/`required` are the
41
+ * caller's concern (rendered outside this function).
42
+ * @param {*} params.value - Current value, already shaped for `field.type` (string for
43
+ * text/select/number/date, array for select_multiple, boolean|null for yes_no).
44
+ * @param {(value: *) => void} params.onChange - Called with the new value in that same shape.
45
+ * Callers needing an (itemId, key, value) or (key, value) signature wrap it, e.g.
46
+ * `(v) => onFieldChange(item.id, field.key, v)`.
47
+ * @param {boolean} [params.disabled] - Renders the control disabled (read-only review usage).
48
+ * @param {boolean} [params.error] - Error/invalid styling.
49
+ * @param {string} [params.helperText] - Helper/error text under the control. Caller decides
50
+ * whether that's a required-field message or blank -- this function doesn't compute it.
51
+ * @param {object} params.i18next - i18next instance, for this function's own small vocabulary
52
+ * (the select placeholder, Yes/No toggle labels).
53
+ * @returns {JSX.Element}
54
+ */
55
+ export const renderFieldTypeControl = ({
56
+ field,
57
+ value,
58
+ onChange,
59
+ disabled,
60
+ error,
61
+ helperText,
62
+ i18next
63
+ }) => {
64
+ const commonProps = {
65
+ name: field.key,
66
+ variant: 'outlined',
67
+ size: 'small',
68
+ error,
69
+ helperText,
70
+ fullWidth: true,
71
+ disabled
72
+ };
73
+ switch (field.type) {
74
+ case 'number':
75
+ return /*#__PURE__*/React.createElement(TextField, _extends({}, commonProps, {
76
+ value: value,
77
+ onChange: e => onChange(e.target.value),
78
+ onKeyDown: e => {
79
+ if (e.key === 'e' || e.key === 'E') e.preventDefault();
80
+ },
81
+ inputProps: {
82
+ maxLength: field.maxLength || 45
83
+ },
84
+ type: "number",
85
+ placeholder: field.placeholder,
86
+ InputProps: {
87
+ endAdornment: field.unit ? /*#__PURE__*/React.createElement(InputAdornment, {
88
+ position: "end"
89
+ }, field.unit) : undefined
90
+ }
91
+ }));
92
+ case 'select':
93
+ return /*#__PURE__*/React.createElement(TextField, _extends({
94
+ select: true
95
+ }, commonProps, {
96
+ value: value,
97
+ onChange: e => onChange(e.target.value)
98
+ }), /*#__PURE__*/React.createElement(MenuItem, {
99
+ value: ""
100
+ }, /*#__PURE__*/React.createElement("em", null, field.placeholder || i18next.t('common.app.select'))), (field.options || []).map(opt => /*#__PURE__*/React.createElement(MenuItem, {
101
+ key: opt,
102
+ value: opt
103
+ }, opt)));
104
+ case 'textarea':
105
+ return /*#__PURE__*/React.createElement(TextField, _extends({}, commonProps, {
106
+ value: value,
107
+ onChange: e => onChange(e.target.value),
108
+ inputProps: {
109
+ maxLength: field.maxLength || 45
110
+ },
111
+ placeholder: field.placeholder,
112
+ multiline: true,
113
+ rows: 3
114
+ }));
115
+ case 'select_multiple':
116
+ {
117
+ const selectedValues = Array.isArray(value) ? value : [];
118
+ return /*#__PURE__*/React.createElement(TextField, _extends({
119
+ select: true
120
+ }, commonProps, {
121
+ value: selectedValues,
122
+ onChange: e => onChange(e.target.value),
123
+ SelectProps: {
124
+ multiple: true,
125
+ renderValue: selected => /*#__PURE__*/React.createElement("div", {
126
+ className: "flex flex-wrap gap-4"
127
+ }, selected.map(opt => /*#__PURE__*/React.createElement(Chip, {
128
+ key: opt,
129
+ label: opt,
130
+ size: "small"
131
+ })))
132
+ }
133
+ }), (field.options || []).map(opt => /*#__PURE__*/React.createElement(MenuItem, {
134
+ key: opt,
135
+ value: opt
136
+ }, /*#__PURE__*/React.createElement(Checkbox, {
137
+ checked: selectedValues.indexOf(opt) > -1
138
+ }), /*#__PURE__*/React.createElement(ListItemText, {
139
+ primary: opt
140
+ }))));
141
+ }
142
+ case 'yes_no':
143
+ {
144
+ const toggleValue = value === true ? 'yes' : value === false ? 'no' : null;
145
+ return /*#__PURE__*/React.createElement(ToggleButtonGroup, {
146
+ value: toggleValue,
147
+ exclusive: true,
148
+ onChange: (_, val) => {
149
+ if (!disabled && val !== null) onChange(val === 'yes');
150
+ },
151
+ fullWidth: true,
152
+ size: "small",
153
+ color: error ? 'error' : 'standard',
154
+ disabled: disabled
155
+ }, /*#__PURE__*/React.createElement(ToggleButton, {
156
+ value: "yes"
157
+ }, i18next.t('common.app.yes')), /*#__PURE__*/React.createElement(ToggleButton, {
158
+ value: "no"
159
+ }, i18next.t('common.app.no')));
160
+ }
161
+ case 'date':
162
+ // Native date input, not each host app's own local DateTimeField wrapper -- this component
163
+ // can't depend on either app's app-local component tree. Value is a plain 'YYYY-MM-DD'
164
+ // string in and out, same convention both apps already use for this field type.
165
+ return /*#__PURE__*/React.createElement(TextField, _extends({}, commonProps, {
166
+ type: "date",
167
+ value: value,
168
+ onChange: e => onChange(e.target.value),
169
+ InputLabelProps: {
170
+ shrink: true
171
+ },
172
+ inputProps: {
173
+ onClick: openNativeDatePicker
174
+ }
175
+ }));
176
+ default:
177
+ // 'text' (default/unknown type too, for backward compat).
178
+ return /*#__PURE__*/React.createElement(TextField, _extends({}, commonProps, {
179
+ value: value,
180
+ onChange: e => onChange(e.target.value),
181
+ inputProps: {
182
+ maxLength: field.maxLength || 45
183
+ },
184
+ type: "text",
185
+ placeholder: field.placeholder
186
+ }));
187
+ }
188
+ };
189
+ export default renderFieldTypeControl;
@@ -1,6 +1,6 @@
1
1
  import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
2
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';
3
+ import { Icon, IconButton, Button, Paper, Typography, Chip, Alert, Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions } from '@mui/material';
4
4
  import { ThemeProvider } from '@mui/system';
5
5
  import { createTheme, useTheme, alpha } from '@mui/material/styles';
6
6
  import AddIcon from '@mui/icons-material/Add';
@@ -9,6 +9,7 @@ import CheckCircleIcon from '@mui/icons-material/CheckCircle';
9
9
  import WarningAmberIcon from '@mui/icons-material/WarningAmber';
10
10
  import * as i18nextLocal from 'i18next';
11
11
  import { classifyAnimalFieldValue } from '../animalFieldDrift';
12
+ import { renderFieldTypeControl } from './fieldTypeControl';
12
13
 
13
14
  // Every visible string this component owns lives under these two pre-existing i18next namespaces
14
15
  // (already shared across both PitchCamp apps via pcm-shared-components' translations.json). Keyed
@@ -54,22 +55,6 @@ const REQUIRED_ERROR_KEY_BY_TYPE = {
54
55
  yes_no: 'animal.required_error_yes_no'
55
56
  };
56
57
 
57
- // A native <input type="date"> only opens its calendar popup on its own when the browser's tiny
58
- // built-in icon is clicked -- clicking anywhere else in the field just places the text caret
59
- // (still lets someone type the year/month/day directly, which showPicker() doesn't change). Most
60
- // people expect clicking anywhere in the box to open the calendar. showPicker() is Chrome/Edge/
61
- // Firefox only as of this writing (not Safari) and throws if called on a disabled/read-only input
62
- // or outside a user gesture, so this fails silently rather than breaking the click -- on an
63
- // unsupported browser, the field just falls back to manual typing and the browser's own
64
- // icon-click affordance, exactly as before.
65
- const openNativeDatePicker = e => {
66
- try {
67
- e.target.showPicker?.();
68
- } catch {
69
- // ignore -- unsupported browser or transient DOM state, typing/icon-click still work
70
- }
71
- };
72
-
73
58
  /**
74
59
  * Tab-per-item editor for a lot's animal or vehicle detail fields: one tab per item (green
75
60
  * check when every required field is answered, amber warning triangle otherwise), an "Add"
@@ -419,148 +404,19 @@ export const AnimalVehicleDetailsEditor = props => {
419
404
  p: 0
420
405
  }
421
406
  }, i18next.t('animal.field_drifted_replace'))));
422
- } else if (field.type === 'number') {
423
- control = /*#__PURE__*/React.createElement(TextField, {
424
- name: field.key,
425
- value: value,
426
- onChange: e => onFieldChange(selectedItem.id, field.key, e.target.value),
427
- onKeyDown: e => {
428
- if (e.key === 'e' || e.key === 'E') e.preventDefault();
429
- },
430
- variant: "outlined",
431
- size: "small",
432
- error: showError,
433
- helperText: showError ? requiredErrorText(field.type) : '',
434
- inputProps: {
435
- maxLength: field.maxLength || 45
436
- },
437
- type: "number",
438
- placeholder: field.placeholder,
439
- fullWidth: true,
440
- InputProps: {
441
- endAdornment: field.unit ? /*#__PURE__*/React.createElement(InputAdornment, {
442
- position: "end"
443
- }, field.unit) : undefined
444
- }
445
- });
446
- } else if (field.type === 'select') {
447
- control = /*#__PURE__*/React.createElement(TextField, {
448
- select: true,
449
- name: field.key,
450
- value: value,
451
- onChange: e => onFieldChange(selectedItem.id, field.key, e.target.value),
452
- variant: "outlined",
453
- size: "small",
454
- error: showError,
455
- helperText: showError ? requiredErrorText(field.type) : '',
456
- fullWidth: true
457
- }, /*#__PURE__*/React.createElement(MenuItem, {
458
- value: ""
459
- }, /*#__PURE__*/React.createElement("em", null, field.placeholder || i18next.t('common.app.select'))), (field.options || []).map(opt => /*#__PURE__*/React.createElement(MenuItem, {
460
- key: opt,
461
- value: opt
462
- }, opt)));
463
- } else if (field.type === 'textarea') {
464
- control = /*#__PURE__*/React.createElement(TextField, {
465
- name: field.key,
466
- value: value,
467
- onChange: e => onFieldChange(selectedItem.id, field.key, e.target.value),
468
- variant: "outlined",
469
- size: "small",
470
- error: showError,
471
- helperText: showError ? requiredErrorText(field.type) : '',
472
- inputProps: {
473
- maxLength: field.maxLength || 45
474
- },
475
- placeholder: field.placeholder,
476
- multiline: true,
477
- rows: 3,
478
- fullWidth: true
479
- });
480
- } else if (field.type === 'select_multiple') {
481
- const selectedValues = Array.isArray(value) ? value : [];
482
- control = /*#__PURE__*/React.createElement(TextField, {
483
- select: true,
484
- name: field.key,
485
- value: selectedValues,
486
- onChange: e => onFieldChange(selectedItem.id, field.key, e.target.value),
487
- variant: "outlined",
488
- size: "small",
489
- error: showError,
490
- helperText: showError ? requiredErrorText(field.type) : '',
491
- fullWidth: true,
492
- SelectProps: {
493
- multiple: true,
494
- renderValue: selected => /*#__PURE__*/React.createElement("div", {
495
- className: "flex flex-wrap gap-4"
496
- }, selected.map(opt => /*#__PURE__*/React.createElement(Chip, {
497
- key: opt,
498
- label: opt,
499
- size: "small"
500
- })))
501
- }
502
- }, (field.options || []).map(opt => /*#__PURE__*/React.createElement(MenuItem, {
503
- key: opt,
504
- value: opt
505
- }, /*#__PURE__*/React.createElement(Checkbox, {
506
- checked: selectedValues.indexOf(opt) > -1
507
- }), /*#__PURE__*/React.createElement(ListItemText, {
508
- primary: opt
509
- }))));
510
- } else if (field.type === 'yes_no') {
511
- const toggleValue = value === true ? 'yes' : value === false ? 'no' : null;
512
- control = /*#__PURE__*/React.createElement(ToggleButtonGroup, {
513
- value: toggleValue,
514
- exclusive: true,
515
- onChange: (_, val) => {
516
- if (val !== null) onFieldChange(selectedItem.id, field.key, val === 'yes');
517
- },
518
- fullWidth: true,
519
- size: "small",
520
- color: showError ? 'error' : 'standard'
521
- }, /*#__PURE__*/React.createElement(ToggleButton, {
522
- value: "yes"
523
- }, i18next.t('common.app.yes')), /*#__PURE__*/React.createElement(ToggleButton, {
524
- value: "no"
525
- }, i18next.t('common.app.no')));
526
- } else if (field.type === 'date') {
527
- // Native date input, not each host app's own local DateTimeField wrapper --
528
- // this component can't depend on either app's app-local component tree.
529
- // Value is a plain 'YYYY-MM-DD' string in and out, same convention both apps
530
- // already use for this field type.
531
- control = /*#__PURE__*/React.createElement(TextField, {
532
- name: field.key,
533
- type: "date",
534
- value: value,
535
- onChange: e => onFieldChange(selectedItem.id, field.key, e.target.value),
536
- variant: "outlined",
537
- size: "small",
538
- error: showError,
539
- helperText: showError ? requiredErrorText(field.type) : '',
540
- fullWidth: true,
541
- InputLabelProps: {
542
- shrink: true
543
- },
544
- inputProps: {
545
- onClick: openNativeDatePicker
546
- }
547
- });
548
407
  } else {
549
- // 'text' (default/unknown type too, for backward compat)
550
- control = /*#__PURE__*/React.createElement(TextField, {
551
- name: field.key,
552
- value: value,
553
- onChange: e => onFieldChange(selectedItem.id, field.key, e.target.value),
554
- variant: "outlined",
555
- size: "small",
408
+ // Every live (non-drifted) control, for every field type this component
409
+ // knows about, is one call into the extracted, reusable renderer -- see
410
+ // fieldTypeControl.jsx in this same directory. AnimalFieldsOnceBlock (also
411
+ // in this directory) calls the exact same function for its once-per-
412
+ // reservation fields, so the two never carry separate copies of this switch.
413
+ control = renderFieldTypeControl({
414
+ field,
415
+ value,
416
+ onChange: newValue => onFieldChange(selectedItem.id, field.key, newValue),
556
417
  error: showError,
557
418
  helperText: showError ? requiredErrorText(field.type) : '',
558
- inputProps: {
559
- maxLength: field.maxLength || 45
560
- },
561
- type: "text",
562
- placeholder: field.placeholder,
563
- fullWidth: true
419
+ i18next
564
420
  });
565
421
  }
566
422
  return /*#__PURE__*/React.createElement("div", {
@@ -38,6 +38,16 @@ export const classifyAnimalFieldValue = (fieldConfig, rawValue) => {
38
38
  type,
39
39
  options
40
40
  } = fieldConfig;
41
+
42
+ // notice fields are never per-animal and never have a value to hold in the first place (see the
43
+ // shared lot_animal_fields.meta contract) -- always 'unanswered' regardless of any stray content
44
+ // that might still be sitting in field_values under this key (e.g. left over from before the
45
+ // field was retyped to 'notice'), so a caller filtering on `!== 'unanswered'` never shows a
46
+ // spurious 'drifted' warning for a field that was never answerable to begin with. Every consumer
47
+ // in the app/ repo already excludes 'notice' from this call entirely (see DetailsSummary.jsx /
48
+ // Occupant.js's per-animal vs. once-per-reservation field split), so this is a defensive fallback
49
+ // for any other/future caller that passes one through unfiltered.
50
+ if (type === 'notice') return 'unanswered';
41
51
  if (type === 'yes_no') {
42
52
  if (typeof rawValue === 'boolean') return 'answered';
43
53
  return hasWrongShapeContent(rawValue) ? 'drifted' : 'unanswered';
package/dist/index.js CHANGED
@@ -37,5 +37,6 @@ 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
+ import { AnimalFieldsOnceBlock } from './components/Reservation/AnimalVehicleDetailsEditor/AnimalFieldsOnceBlock';
40
41
  import { classifyAnimalFieldValue } from './components/Reservation/animalFieldDrift';
41
- 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, classifyAnimalFieldValue };
42
+ 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, AnimalFieldsOnceBlock, classifyAnimalFieldValue };
@@ -41,7 +41,8 @@
41
41
  "field_drifted_replace": "Enter a new answer",
42
42
  "field_removed": "This question no longer exists in this lot's setup.",
43
43
  "historical_answers_title": "Historical Answers",
44
- "historical_answers_hint": "These questions are no longer part of this lot's setup and can't be edited."
44
+ "historical_answers_hint": "These questions are no longer part of this lot's setup and can't be edited.",
45
+ "view_full_field": "View full {{label}}"
45
46
  },
46
47
  "app": {
47
48
  "common": {
@@ -2464,6 +2465,11 @@
2464
2465
  "field_type_yes_no": "Yes / No",
2465
2466
  "field_type_date": "Date",
2466
2467
  "field_type_select_multiple": "Dropdown (Select Multiple)",
2468
+ "field_type_notice": "Notice",
2469
+ "ask_once_per_reservation": "Ask once per reservation",
2470
+ "once_per_reservation_helper": "Shown once for the whole reservation instead of once per animal.",
2471
+ "notice_content_label": "Notice content",
2472
+ "notice_preview_label": "Preview",
2467
2473
  "options_label": "Options",
2468
2474
  "add_option": "Add Option",
2469
2475
  "unit_label": "Unit",
@@ -41,7 +41,8 @@
41
41
  "field_drifted_replace": "Ingrese una nueva respuesta",
42
42
  "field_removed": "Esta pregunta ya no existe en la configuración de este lote.",
43
43
  "historical_answers_title": "Respuestas Históricas",
44
- "historical_answers_hint": "Estas preguntas ya no forman parte de la configuración de este lote y no se pueden editar."
44
+ "historical_answers_hint": "Estas preguntas ya no forman parte de la configuración de este lote y no se pueden editar.",
45
+ "view_full_field": "Ver {{label}} completo"
45
46
  },
46
47
  "app": {
47
48
  "common": {
@@ -2464,6 +2465,11 @@
2464
2465
  "field_type_yes_no": "Sí / No",
2465
2466
  "field_type_date": "Fecha",
2466
2467
  "field_type_select_multiple": "Desplegable (Seleccionar varios)",
2468
+ "field_type_notice": "Aviso",
2469
+ "ask_once_per_reservation": "Preguntar una sola vez por reserva",
2470
+ "once_per_reservation_helper": "Se muestra una sola vez para toda la reserva, en lugar de una vez por animal.",
2471
+ "notice_content_label": "Contenido del aviso",
2472
+ "notice_preview_label": "Vista previa",
2467
2473
  "options_label": "Opciones",
2468
2474
  "add_option": "Agregar opción",
2469
2475
  "unit_label": "Unidad",
@@ -41,7 +41,8 @@
41
41
  "field_drifted_replace": "Entrez une nouvelle réponse",
42
42
  "field_removed": "Cette question n'existe plus dans la configuration de ce terrain.",
43
43
  "historical_answers_title": "Réponses Historiques",
44
- "historical_answers_hint": "Ces questions ne font plus partie de la configuration de ce terrain et ne peuvent pas être modifiées."
44
+ "historical_answers_hint": "Ces questions ne font plus partie de la configuration de ce terrain et ne peuvent pas être modifiées.",
45
+ "view_full_field": "Voir {{label}} en entier"
45
46
  },
46
47
  "app": {
47
48
  "common": {
@@ -2464,6 +2465,11 @@
2464
2465
  "field_type_yes_no": "Oui / Non",
2465
2466
  "field_type_date": "Date",
2466
2467
  "field_type_select_multiple": "Liste déroulante (Sélectionner plusieurs)",
2468
+ "field_type_notice": "Avis",
2469
+ "ask_once_per_reservation": "Demander une seule fois par réservation",
2470
+ "once_per_reservation_helper": "Affiché une seule fois pour toute la réservation, plutôt que pour chaque animal.",
2471
+ "notice_content_label": "Contenu de l'avis",
2472
+ "notice_preview_label": "Aperçu",
2467
2473
  "options_label": "Options",
2468
2474
  "add_option": "Ajouter une option",
2469
2475
  "unit_label": "Unité",
@@ -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: }.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))}}
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}.fixed{position:fixed}.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}.inline{display:inline}.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}.resize{resize:both}.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))}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pcm-shared-components",
3
- "version": "2.1.403",
3
+ "version": "2.1.405",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "babel": {