pcm-shared-components 2.1.405 → 2.1.406

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.
@@ -1,155 +1,49 @@
1
- import React, { useLayoutEffect, useRef, useState } from 'react';
1
+ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { Typography, Paper, Button, Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material';
3
+ import { Typography } from '@mui/material';
4
4
  import { ThemeProvider } from '@mui/system';
5
5
  import { createTheme, useTheme } from '@mui/material/styles';
6
6
  import * as i18nextLocal from 'i18next';
7
7
  import { renderFieldTypeControl } from './fieldTypeControl';
8
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
9
  // 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);
10
+ // non-orphan fields (a dropdown/textarea/multi-select reads badly squeezed into a half column, and
11
+ // a notice's rich text + checkbox needs the same full row). This block skips that component's
12
+ // further wrapped-label-promotion pass (labelRefs/wrappedKeys in index.jsx) -- once-per-reservation
13
+ // fields are typically a handful at most, so the extra measurement machinery needed to keep a large
14
+ // tab-per-animal grid's columns aligned isn't worth carrying here too.
15
+ const isFullWidthField = field => ['select', 'textarea', 'select_multiple', 'notice'].includes(field.type);
25
16
 
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.
17
+ // `once_per_reservation` is read from the field object itself first (the flat, "normalized" shape
18
+ // this block's `fields` prop expects -- the same convention AnimalVehicleDetailsEditor's
19
+ // `fieldConfig` already uses for label/options/unit/placeholder: the caller resolves the raw
20
+ // lot_animal_fields.meta payload into flat props before handing fields to either component). A
21
+ // `field.meta.<key>` fallback is also accepted so a caller who instead passes the meta object
22
+ // through unflattened still works.
32
23
  const readFieldProp = (field, key) => field[key] !== undefined ? field[key] : field.meta?.[key];
33
24
 
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
25
  /**
127
26
  * Flat, non-tabbed block for a lot's "once per reservation" animal fields: no tabs, no per-animal
128
27
  * 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:
28
+ * one row per animal. Renders any field (any type, including 'notice') whose config opts into
29
+ * `once_per_reservation` -- reuses the exact same `renderFieldTypeControl` that
30
+ * AnimalVehicleDetailsEditor's tab-per-animal grid uses (see fieldTypeControl.jsx, this directory),
31
+ * so a once-per-reservation field looks and behaves identically to its per-animal counterpart, type
32
+ * for type. `once_per_reservation` is independent of `type` -- a 'notice' field can be either
33
+ * once-per-reservation (rendered here) or per-animal (rendered in the tab grid instead), exactly
34
+ * like any other field type.
130
35
  *
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.
36
+ * `fields` does NOT need to be pre-filtered: this component filters internally (any field whose
37
+ * `once_per_reservation` isn't `true` is silently skipped), so it's safe to pass the lot's whole
38
+ * field list straight through. Passing an already-filtered subset works identically, since the
39
+ * filter is idempotent.
144
40
  *
145
41
  * Two usage modes, both through this one component:
146
42
  * - Editable (staff/guest edit flow): pass `onChange`. Inputs render live and call
147
43
  * `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.
44
+ * - Read-only (review screen): omit `onChange` entirely. Every control renders disabled (MUI's own
45
+ * disabled/read-only appearance) instead of interactive -- there is no second "read-only
46
+ * variant" component to import, this is the same export either way.
153
47
  *
154
48
  * ## Importing the component in your project
155
49
  *
@@ -171,7 +65,7 @@ export const AnimalFieldsOnceBlock = props => {
171
65
  } = props;
172
66
  const compTheme = theme || useTheme();
173
67
  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);
68
+ const relevantFields = fields.filter(field => readFieldProp(field, 'once_per_reservation') === true);
175
69
  if (relevantFields.length === 0) return null;
176
70
  return /*#__PURE__*/React.createElement(ThemeProvider, {
177
71
  theme: defaultTheme
@@ -185,15 +79,6 @@ export const AnimalFieldsOnceBlock = props => {
185
79
  gridAutoFlow: 'row dense'
186
80
  }
187
81
  }, 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
82
  const rawValue = values?.[field.key] ?? (field.type === 'select_multiple' ? [] : '');
198
83
  const labelText = field.required ? `${field.label} *` : field.label;
199
84
  return /*#__PURE__*/React.createElement("div", {
@@ -231,8 +116,9 @@ AnimalFieldsOnceBlock.propTypes = {
231
116
  /** The lot's field configs -- does not need to be pre-filtered, see the component doc above.
232
117
  * Normalized to the same flat shape AnimalVehicleDetailsEditor's `fieldConfig` already uses
233
118
  * (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. */
119
+ * `once_per_reservation` (any type, independently admin-configurable) and `content_html` (type
120
+ * 'notice' only, read inside fieldTypeControl.jsx's notice control). Both are also read from
121
+ * `field.meta.<key>` as a fallback if a caller passes the meta object through unflattened. */
236
122
  fields: PropTypes.arrayOf(PropTypes.shape({
237
123
  key: PropTypes.string.isRequired,
238
124
  label: PropTypes.string.isRequired,
@@ -1,6 +1,6 @@
1
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';
2
+ import React, { useLayoutEffect, useRef, useState } from 'react';
3
+ import { TextField, InputAdornment, MenuItem, ToggleButton, ToggleButtonGroup, Checkbox, ListItemText, Chip, FormControlLabel, FormHelperText, Paper, Button, Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material';
4
4
 
5
5
  // A native <input type="date"> only opens its calendar popup on its own when the browser's tiny
6
6
  // built-in icon is clicked -- clicking anywhere else in the field just places the text caret
@@ -18,10 +18,116 @@ export const openNativeDatePicker = e => {
18
18
  }
19
19
  };
20
20
 
21
+ // Collapsed height for a notice's rich-text content before it needs a "View full ..." link. A
22
+ // handful of lines of admin-entered text/markup fits inside this without ever showing the link at
23
+ // all; anything longer gets clipped here and offered in full through the dialog below.
24
+ const NOTICE_COLLAPSED_MAX_HEIGHT = 160;
25
+
26
+ /**
27
+ * The control for a `notice` field: the admin's sanitized rich text inside a bounded-height
28
+ * container (only overflowing content gets a "View full {label}" link that opens the rest in a
29
+ * Dialog), plus a single "I have read this" checkbox whose checked state IS the field's value --
30
+ * stored the same way a `yes_no` field's boolean value is. Not exported -- only reached through
31
+ * `renderFieldTypeControl`'s `notice` case below, same as every other type-specific control in
32
+ * this switch.
33
+ *
34
+ * The field's own label is deliberately NOT rendered in here: both call sites
35
+ * (AnimalVehicleDetailsEditor's per-item grid and AnimalFieldsOnceBlock's flat layout) already
36
+ * render `field.label` above whatever control this function returns, same as for every other type.
37
+ */
38
+ const NoticeFieldControl = ({
39
+ field,
40
+ value,
41
+ onChange,
42
+ disabled,
43
+ error,
44
+ helperText,
45
+ i18next
46
+ }) => {
47
+ const contentRef = useRef(null);
48
+ const [overflowing, setOverflowing] = useState(false);
49
+ const [dialogOpen, setDialogOpen] = useState(false);
50
+ // Already HTML-sanitized server-side before this ever reaches the client -- safe to render as-is.
51
+ // `field.meta.content_html` fallback covers a caller passing the raw meta object through
52
+ // unflattened, same convention this feature's other `field.<key>` reads already follow.
53
+ const contentHtml = field.content_html !== undefined ? field.content_html : field.meta?.content_html || '';
54
+
55
+ // Measured after mount/paint (useLayoutEffect, not useEffect) so the "View full ..." link never
56
+ // flashes in for a heartbeat on content that turns out to fit. Re-checked on window resize too:
57
+ // the height bound is fixed in CSS, but at a narrower viewport the same HTML can wrap onto more
58
+ // lines and start overflowing where it didn't before.
59
+ useLayoutEffect(() => {
60
+ const checkOverflow = () => {
61
+ const el = contentRef.current;
62
+ if (!el) return;
63
+ setOverflowing(el.scrollHeight > el.clientHeight);
64
+ };
65
+ checkOverflow();
66
+ window.addEventListener('resize', checkOverflow);
67
+ return () => window.removeEventListener('resize', checkOverflow);
68
+ }, [contentHtml]);
69
+ return /*#__PURE__*/React.createElement("div", {
70
+ className: "flex flex-col",
71
+ style: {
72
+ gap: 4
73
+ }
74
+ }, /*#__PURE__*/React.createElement(Paper, {
75
+ variant: "outlined",
76
+ sx: {
77
+ p: 1.5,
78
+ borderRadius: 1,
79
+ bgcolor: 'action.hover',
80
+ maxHeight: NOTICE_COLLAPSED_MAX_HEIGHT,
81
+ overflow: 'hidden'
82
+ }
83
+ }, /*#__PURE__*/React.createElement("div", {
84
+ ref: contentRef,
85
+ dangerouslySetInnerHTML: {
86
+ __html: contentHtml
87
+ }
88
+ })), overflowing && /*#__PURE__*/React.createElement(Button, {
89
+ size: "small",
90
+ disabled: disabled,
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')))), /*#__PURE__*/React.createElement(FormControlLabel, {
115
+ control: /*#__PURE__*/React.createElement(Checkbox, {
116
+ checked: value === true,
117
+ onChange: e => onChange(e.target.checked),
118
+ disabled: disabled,
119
+ color: error ? 'error' : 'primary'
120
+ }),
121
+ label: i18next.t('animal.read_notice_confirmation')
122
+ }), helperText && /*#__PURE__*/React.createElement(FormHelperText, {
123
+ error: error
124
+ }, helperText));
125
+ };
126
+
21
127
  /**
22
128
  * 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
129
+ * this feature knows about: text / number / select / select_multiple / textarea / yes_no / date /
130
+ * notice (unknown/legacy types fall back to plain text, same as before). Pulled out of the per-item field
25
131
  * grid in `index.jsx` (AnimalVehicleDetailsEditor's tab-per-animal editor) so
26
132
  * `AnimalFieldsOnceBlock`'s flat once-per-reservation layout, in the same directory, can render the
27
133
  * exact same controls without a second copy of this switch. Both call sites feed it the same shape
@@ -40,7 +146,8 @@ export const openNativeDatePicker = e => {
40
146
  * Only `key`/`type` and the type-specific extras are read here; `label`/`required` are the
41
147
  * caller's concern (rendered outside this function).
42
148
  * @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).
149
+ * text/select/number/date, array for select_multiple, boolean|null for yes_no/notice -- for
150
+ * notice this is the "I have read this" checkbox's checked state, not the (read-only) content).
44
151
  * @param {(value: *) => void} params.onChange - Called with the new value in that same shape.
45
152
  * Callers needing an (itemId, key, value) or (key, value) signature wrap it, e.g.
46
153
  * `(v) => onFieldChange(item.id, field.key, v)`.
@@ -158,6 +265,16 @@ export const renderFieldTypeControl = ({
158
265
  value: "no"
159
266
  }, i18next.t('common.app.no')));
160
267
  }
268
+ case 'notice':
269
+ return /*#__PURE__*/React.createElement(NoticeFieldControl, {
270
+ field: field,
271
+ value: value,
272
+ onChange: onChange,
273
+ disabled: disabled,
274
+ error: error,
275
+ helperText: helperText,
276
+ i18next: i18next
277
+ });
161
278
  case 'date':
162
279
  // Native date input, not each host app's own local DateTimeField wrapper -- this component
163
280
  // can't depend on either app's app-local component tree. Value is a plain 'YYYY-MM-DD'
@@ -47,12 +47,17 @@ const KEYS = {
47
47
  // select an option" reads very differently from "please enter a number". Not itemType-specific:
48
48
  // a select field is a select field whether it belongs to an animal or a vehicle. Falls back to
49
49
  // animal.required_error for text/textarea, where the generic "fill this in" copy already fits.
50
+ // 'notice' gets its own message (animal.required_error_notice) rather than the generic one --
51
+ // its required-satisfying condition is stricter than every other type (see isFieldAnswered,
52
+ // injected by the caller): only a CHECKED "I have read this" box counts, so "please fill this in"
53
+ // would read wrong for what's actually a checkbox.
50
54
  const REQUIRED_ERROR_KEY_BY_TYPE = {
51
55
  select: 'animal.required_error_select',
52
56
  select_multiple: 'animal.required_error_select_multiple',
53
57
  number: 'animal.required_error_number',
54
58
  date: 'animal.required_error_date',
55
- yes_no: 'animal.required_error_yes_no'
59
+ yes_no: 'animal.required_error_yes_no',
60
+ notice: 'animal.required_error_notice'
56
61
  };
57
62
 
58
63
  /**
@@ -224,7 +229,7 @@ export const AnimalVehicleDetailsEditor = props => {
224
229
  return nextWrapped;
225
230
  });
226
231
  }, [fieldConfig, wrappedKeys]);
227
- const isFullWidthField = f => ['select', 'textarea', 'select_multiple'].includes(f.type) || wrappedKeys.has(f.key);
232
+ const isFullWidthField = f => ['select', 'textarea', 'select_multiple', 'notice'].includes(f.type) || wrappedKeys.has(f.key);
228
233
  return /*#__PURE__*/React.createElement(ThemeProvider, {
229
234
  theme: defaultTheme
230
235
  }, /*#__PURE__*/React.createElement("div", {
@@ -617,11 +622,14 @@ AnimalVehicleDetailsEditor.propTypes = {
617
622
  key: PropTypes.string.isRequired,
618
623
  label: PropTypes.string.isRequired,
619
624
  required: PropTypes.bool,
620
- type: PropTypes.oneOf(['text', 'number', 'select', 'select_multiple', 'textarea', 'yes_no', 'date']),
625
+ type: PropTypes.oneOf(['text', 'number', 'select', 'select_multiple', 'textarea', 'yes_no', 'date', 'notice']),
621
626
  options: PropTypes.arrayOf(PropTypes.string),
622
627
  unit: PropTypes.string,
623
628
  placeholder: PropTypes.string,
624
- maxLength: PropTypes.number
629
+ maxLength: PropTypes.number,
630
+ /** Type 'notice' only -- the admin's sanitized rich text, read inside fieldTypeControl.jsx's
631
+ * notice control. */
632
+ content_html: PropTypes.string
625
633
  })),
626
634
  /** (type, value) => boolean. Injected rather than owned internally, so each host app's existing
627
635
  * "has this field actually been answered" rule (yes_no's `false` counts, etc.) stays authoritative. */
@@ -39,16 +39,14 @@ export const classifyAnimalFieldValue = (fieldConfig, rawValue) => {
39
39
  options
40
40
  } = fieldConfig;
41
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';
51
- if (type === 'yes_no') {
42
+ // notice's control is a single "I have read this" checkbox, whose checked state IS the field's
43
+ // value -- stored as a real boolean in field_values, exactly like yes_no. Same classification as
44
+ // yes_no below: a stored `true`/`false` is 'answered' (a stray non-boolean leftover from before
45
+ // the field was retyped to/from 'notice' is 'drifted' rather than silently treated as answered),
46
+ // anything else is 'unanswered'. This is drift-detection shape-matching only -- it does NOT decide
47
+ // whether an unchecked (`false`) box satisfies a *required* notice, which is a stricter rule than
48
+ // yes_no's (see isFieldAnswered, injected by each caller, not this function).
49
+ if (type === 'yes_no' || type === 'notice') {
52
50
  if (typeof rawValue === 'boolean') return 'answered';
53
51
  return hasWrongShapeContent(rawValue) ? 'drifted' : 'unanswered';
54
52
  }
@@ -19,6 +19,8 @@
19
19
  "required_error": "Please fill this in.",
20
20
  "required_for_guests": "Required for guests",
21
21
  "section_intro": "Please tell us a bit about each animal traveling with you.",
22
+ "read_notice_confirmation": "I have read this",
23
+ "required_error_notice": "Please confirm you have read this.",
22
24
  "required_error_select": "Please select an option.",
23
25
  "required_error_select_multiple": "Please select at least one option.",
24
26
  "required_error_number": "Please enter a number.",
@@ -2469,7 +2471,7 @@
2469
2471
  "ask_once_per_reservation": "Ask once per reservation",
2470
2472
  "once_per_reservation_helper": "Shown once for the whole reservation instead of once per animal.",
2471
2473
  "notice_content_label": "Notice content",
2472
- "notice_preview_label": "Preview",
2474
+ "notice_empty_hint": "Add your notice text above to see it here.",
2473
2475
  "options_label": "Options",
2474
2476
  "add_option": "Add Option",
2475
2477
  "unit_label": "Unit",
@@ -19,6 +19,8 @@
19
19
  "required_error": "Por favor, complete este campo.",
20
20
  "required_for_guests": "Requerido para huéspedes",
21
21
  "section_intro": "Por favor, cuéntenos un poco sobre cada animal que viaja con usted.",
22
+ "read_notice_confirmation": "He leído esto",
23
+ "required_error_notice": "Por favor, confirme que ha leído esto.",
22
24
  "required_error_select": "Por favor, seleccione una opción.",
23
25
  "required_error_select_multiple": "Por favor, seleccione al menos una opción.",
24
26
  "required_error_number": "Por favor, ingrese un número.",
@@ -2469,7 +2471,7 @@
2469
2471
  "ask_once_per_reservation": "Preguntar una sola vez por reserva",
2470
2472
  "once_per_reservation_helper": "Se muestra una sola vez para toda la reserva, en lugar de una vez por animal.",
2471
2473
  "notice_content_label": "Contenido del aviso",
2472
- "notice_preview_label": "Vista previa",
2474
+ "notice_empty_hint": "Agregue el texto de su aviso arriba para verlo aquí.",
2473
2475
  "options_label": "Opciones",
2474
2476
  "add_option": "Agregar opción",
2475
2477
  "unit_label": "Unidad",
@@ -19,6 +19,8 @@
19
19
  "required_error": "Veuillez remplir ce champ.",
20
20
  "required_for_guests": "Requis pour les clients",
21
21
  "section_intro": "Merci de nous donner quelques informations sur chaque animal qui vous accompagne.",
22
+ "read_notice_confirmation": "J'ai lu ceci",
23
+ "required_error_notice": "Veuillez confirmer que vous avez lu ceci.",
22
24
  "required_error_select": "Veuillez sélectionner une option.",
23
25
  "required_error_select_multiple": "Veuillez sélectionner au moins une option.",
24
26
  "required_error_number": "Veuillez entrer un nombre.",
@@ -2469,7 +2471,7 @@
2469
2471
  "ask_once_per_reservation": "Demander une seule fois par réservation",
2470
2472
  "once_per_reservation_helper": "Affiché une seule fois pour toute la réservation, plutôt que pour chaque animal.",
2471
2473
  "notice_content_label": "Contenu de l'avis",
2472
- "notice_preview_label": "Aperçu",
2474
+ "notice_empty_hint": "Ajoutez le texte de votre avis ci-dessus pour le voir ici.",
2473
2475
  "options_label": "Options",
2474
2476
  "add_option": "Ajouter une option",
2475
2477
  "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}.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))}}
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}.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.405",
3
+ "version": "2.1.406",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "babel": {