labellife-design-tool 2.2.7 → 2.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useEffect, useCallback, useRef, memo, Fragment as Fragment$1 } from 'react';
2
- import { ButtonBase, Box, Typography, Button, IconButton, TextField, InputAdornment, ClickAwayListener, Paper, ListItem, ListItemIcon, ListItemText, List, Switch, Slider, CircularProgress, FormControlLabel, Checkbox, FormControl, InputLabel, Select, MenuItem, Divider, Alert, Chip, Autocomplete, Tooltip, ToggleButtonGroup, ToggleButton, Menu, Popover } from '@mui/material';
2
+ import { ButtonBase, Box, Typography, Button, IconButton, TextField, InputAdornment, ClickAwayListener, Paper, ListItem, ListItemIcon, ListItemText, List, Switch, Slider, CircularProgress, FormControlLabel, Checkbox, FormControl, InputLabel, Select, MenuItem, Divider, Alert, Chip, Autocomplete, Tooltip, ToggleButtonGroup, ToggleButton, Menu, Popover, FormGroup, RadioGroup, Radio } from '@mui/material';
3
3
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
4
  import { types, getParent, getRoot, getSnapshot, applySnapshot, destroy } from 'mobx-state-tree';
5
5
  import { v4 } from 'uuid';
@@ -28,6 +28,9 @@ import CloseIcon from '@mui/icons-material/Close';
28
28
  import InputIcon from '@mui/icons-material/Input';
29
29
  import CalendarTodayIcon from '@mui/icons-material/CalendarToday';
30
30
  import NumbersIcon from '@mui/icons-material/Numbers';
31
+ import RadioButtonCheckedIcon from '@mui/icons-material/RadioButtonChecked';
32
+ import FormatListBulletedIcon from '@mui/icons-material/FormatListBulleted';
33
+ import AddIcon from '@mui/icons-material/Add';
31
34
  import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
32
35
  import FileUploadIcon from '@mui/icons-material/FileUpload';
33
36
  import UndoIcon from '@mui/icons-material/Undo';
@@ -6897,7 +6900,7 @@ function ImagesGrid(_ref) {
6897
6900
  });
6898
6901
  }
6899
6902
 
6900
- var _excluded$2 = ["inputField", "promptText", "inputType", "required", "placeholder"];
6903
+ var _excluded$2 = ["inputField", "promptText", "inputType", "required", "placeholder", "options", "minSelections", "maxSelections"];
6901
6904
  var IMAGE_PLACEHOLDER_SRC = "data:image/svg+xml;charset=utf-8,".concat(encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"400\" height=\"400\" viewBox=\"0 0 400 400\">\n <rect width=\"400\" height=\"400\" fill=\"#f0f2f5\" rx=\"12\"/>\n <rect x=\"110\" y=\"90\" width=\"180\" height=\"145\" rx=\"10\" fill=\"#dde1e7\"/>\n <circle cx=\"158\" cy=\"135\" r=\"22\" fill=\"#f0f2f5\"/>\n <polygon points=\"110,235 168,163 210,205 250,163 290,235\" fill=\"#c8cdd6\"/>\n <rect x=\"140\" y=\"268\" width=\"120\" height=\"14\" rx=\"7\" fill=\"#c8cdd6\"/>\n <rect x=\"160\" y=\"292\" width=\"80\" height=\"10\" rx=\"5\" fill=\"#dde1e7\"/>\n </svg>"));
6902
6905
 
6903
6906
  // ── Date formatting helpers ──────────────────────────────────────────
@@ -6939,12 +6942,84 @@ function formatDate$1(date, format) {
6939
6942
  }
6940
6943
  }
6941
6944
 
6945
+ // ── Options list editor ──────────────────────────────────────────────
6946
+ var OptionsEditor = function OptionsEditor(_ref) {
6947
+ var options = _ref.options,
6948
+ _onChange = _ref.onChange;
6949
+ return /*#__PURE__*/jsxs(Box, {
6950
+ sx: {
6951
+ ml: 6.5,
6952
+ mr: 1,
6953
+ display: 'flex',
6954
+ flexDirection: 'column',
6955
+ gap: 0.75
6956
+ },
6957
+ children: [options.map(function (opt, i) {
6958
+ return /*#__PURE__*/jsxs(Box, {
6959
+ sx: {
6960
+ display: 'flex',
6961
+ gap: 0.5,
6962
+ alignItems: 'center'
6963
+ },
6964
+ children: [/*#__PURE__*/jsx(TextField, {
6965
+ size: "small",
6966
+ value: opt,
6967
+ onChange: function onChange(e) {
6968
+ var next = _toConsumableArray(options);
6969
+ next[i] = e.target.value;
6970
+ _onChange(next);
6971
+ },
6972
+ placeholder: "Option ".concat(i + 1),
6973
+ sx: {
6974
+ flex: 1,
6975
+ '& .MuiInputBase-input': {
6976
+ fontSize: 12,
6977
+ py: 0.75
6978
+ }
6979
+ }
6980
+ }), /*#__PURE__*/jsx(IconButton, {
6981
+ size: "small",
6982
+ onClick: function onClick() {
6983
+ return _onChange(options.filter(function (_, j) {
6984
+ return j !== i;
6985
+ }));
6986
+ },
6987
+ disabled: options.length <= 1,
6988
+ sx: {
6989
+ color: '#bbb',
6990
+ '&:hover': {
6991
+ color: '#e57373'
6992
+ }
6993
+ },
6994
+ children: /*#__PURE__*/jsx(DeleteIcon, {
6995
+ fontSize: "small"
6996
+ })
6997
+ })]
6998
+ }, i);
6999
+ }), /*#__PURE__*/jsx(Button, {
7000
+ size: "small",
7001
+ startIcon: /*#__PURE__*/jsx(AddIcon, {}),
7002
+ onClick: function onClick() {
7003
+ return _onChange([].concat(_toConsumableArray(options), ['']));
7004
+ },
7005
+ sx: {
7006
+ alignSelf: 'flex-start',
7007
+ fontSize: 11,
7008
+ textTransform: 'none',
7009
+ color: '#0d83cd',
7010
+ p: 0.5
7011
+ },
7012
+ children: "Add option"
7013
+ })]
7014
+ });
7015
+ };
7016
+
6942
7017
  // ── Card component ───────────────────────────────────────────────────
6943
- var InputFieldCard = function InputFieldCard(_ref) {
6944
- var icon = _ref.icon,
6945
- label = _ref.label,
6946
- description = _ref.description,
6947
- onClick = _ref.onClick;
7018
+ var InputFieldCard = function InputFieldCard(_ref2) {
7019
+ var icon = _ref2.icon,
7020
+ label = _ref2.label,
7021
+ description = _ref2.description,
7022
+ onClick = _ref2.onClick;
6948
7023
  return /*#__PURE__*/jsxs(Box, {
6949
7024
  onClick: onClick,
6950
7025
  sx: {
@@ -7000,8 +7075,8 @@ var InputFieldCard = function InputFieldCard(_ref) {
7000
7075
  };
7001
7076
 
7002
7077
  // ── Panel content ────────────────────────────────────────────────────
7003
- var InputFieldsPanelContent = observer(function (_ref2) {
7004
- var store = _ref2.store;
7078
+ var InputFieldsPanelContent = observer(function (_ref3) {
7079
+ var store = _ref3.store;
7005
7080
  var _useState = useState('MM-DD-YYYY'),
7006
7081
  _useState2 = _slicedToArray(_useState, 2),
7007
7082
  dateFormat = _useState2[0],
@@ -7038,6 +7113,34 @@ var InputFieldsPanelContent = observer(function (_ref2) {
7038
7113
  _useState16 = _slicedToArray(_useState15, 2),
7039
7114
  imageRequired = _useState16[0],
7040
7115
  setImageRequired = _useState16[1];
7116
+ var _useState17 = useState(''),
7117
+ _useState18 = _slicedToArray(_useState17, 2),
7118
+ radioPrompt = _useState18[0],
7119
+ setRadioPrompt = _useState18[1];
7120
+ var _useState19 = useState(false),
7121
+ _useState20 = _slicedToArray(_useState19, 2),
7122
+ radioRequired = _useState20[0],
7123
+ setRadioRequired = _useState20[1];
7124
+ var _useState21 = useState(['Option 1', 'Option 2']),
7125
+ _useState22 = _slicedToArray(_useState21, 2),
7126
+ radioOptions = _useState22[0],
7127
+ setRadioOptions = _useState22[1];
7128
+ var _useState23 = useState(''),
7129
+ _useState24 = _slicedToArray(_useState23, 2),
7130
+ listPrompt = _useState24[0],
7131
+ setListPrompt = _useState24[1];
7132
+ var _useState25 = useState(0),
7133
+ _useState26 = _slicedToArray(_useState25, 2),
7134
+ listMinSelections = _useState26[0],
7135
+ setListMinSelections = _useState26[1];
7136
+ var _useState27 = useState(2),
7137
+ _useState28 = _slicedToArray(_useState27, 2),
7138
+ listMaxSelections = _useState28[0],
7139
+ setListMaxSelections = _useState28[1];
7140
+ var _useState29 = useState(['Option 1', 'Option 2']),
7141
+ _useState30 = _slicedToArray(_useState29, 2),
7142
+ listOptions = _useState30[0],
7143
+ setListOptions = _useState30[1];
7041
7144
  var addInputElement = function addInputElement(inputType) {
7042
7145
  var extra = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7043
7146
  var page = store.activePage;
@@ -7080,6 +7183,16 @@ var InputFieldsPanelContent = observer(function (_ref2) {
7080
7183
  placeholder = t('sidePanel.inputFields.integerPlaceholder', 'Enter number');
7081
7184
  defaultPrompt = t('sidePanel.inputFields.defaultIntegerPrompt', 'Please enter a number');
7082
7185
  break;
7186
+ case 'radio':
7187
+ dummyText = (extra.options || []).filter(Boolean)[0] || 'Option 1';
7188
+ placeholder = t('sidePanel.inputFields.radioPlaceholder', 'Select an option');
7189
+ defaultPrompt = t('sidePanel.inputFields.defaultRadioPrompt', 'Please select an option');
7190
+ break;
7191
+ case 'list':
7192
+ dummyText = (extra.options || []).filter(Boolean).slice(0, 2).join(', ') || 'Option 1, Option 2';
7193
+ placeholder = t('sidePanel.inputFields.listPlaceholder', 'Select options');
7194
+ defaultPrompt = t('sidePanel.inputFields.defaultListPrompt', 'Please select options');
7195
+ break;
7083
7196
  default:
7084
7197
  dummyText = 'Input';
7085
7198
  placeholder = 'Input';
@@ -7098,7 +7211,7 @@ var InputFieldsPanelContent = observer(function (_ref2) {
7098
7211
  fontFamily: 'Roboto',
7099
7212
  align: 'center',
7100
7213
  fill: '#333333',
7101
- custom: _objectSpread2({
7214
+ custom: _objectSpread2(_objectSpread2(_objectSpread2({
7102
7215
  inputField: true,
7103
7216
  inputType: inputType,
7104
7217
  placeholder: placeholder,
@@ -7106,6 +7219,11 @@ var InputFieldsPanelContent = observer(function (_ref2) {
7106
7219
  required: extra.required || false
7107
7220
  }, inputType === 'date' ? {
7108
7221
  dateFormat: extra.dateFormat || 'MM-DD-YYYY'
7222
+ } : {}), ['radio', 'list'].includes(inputType) ? {
7223
+ options: (extra.options || []).filter(Boolean)
7224
+ } : {}), inputType === 'list' ? {
7225
+ minSelections: extra.minSelections || 0,
7226
+ maxSelections: extra.maxSelections || 0
7109
7227
  } : {})
7110
7228
  });
7111
7229
  }
@@ -7347,6 +7465,138 @@ var InputFieldsPanelContent = observer(function (_ref2) {
7347
7465
  sx: {
7348
7466
  ml: 5.5
7349
7467
  }
7468
+ }), /*#__PURE__*/jsx(InputFieldCard, {
7469
+ icon: /*#__PURE__*/jsx(RadioButtonCheckedIcon, {
7470
+ fontSize: "small"
7471
+ }),
7472
+ label: t('sidePanel.inputFields.radioInput', 'Radio Input'),
7473
+ description: t('sidePanel.inputFields.radioInputDesc', 'Single option selection'),
7474
+ onClick: function onClick() {
7475
+ return addInputElement('radio', {
7476
+ promptText: radioPrompt,
7477
+ required: radioRequired,
7478
+ options: radioOptions
7479
+ });
7480
+ }
7481
+ }), /*#__PURE__*/jsx(TextField, {
7482
+ size: "small",
7483
+ placeholder: t('sidePanel.inputFields.promptTextHint', 'Prompt text shown to user...'),
7484
+ value: radioPrompt,
7485
+ onChange: function onChange(e) {
7486
+ return setRadioPrompt(e.target.value);
7487
+ },
7488
+ sx: {
7489
+ ml: 6.5,
7490
+ mr: 1,
7491
+ '& .MuiInputBase-input': {
7492
+ fontSize: 12,
7493
+ py: 0.75
7494
+ }
7495
+ }
7496
+ }), /*#__PURE__*/jsx(FormControlLabel, {
7497
+ control: /*#__PURE__*/jsx(Checkbox, {
7498
+ size: "small",
7499
+ checked: radioRequired,
7500
+ onChange: function onChange(e) {
7501
+ return setRadioRequired(e.target.checked);
7502
+ }
7503
+ }),
7504
+ label: /*#__PURE__*/jsx(Typography, {
7505
+ sx: {
7506
+ fontSize: 12
7507
+ },
7508
+ children: t('sidePanel.inputFields.required', 'Required')
7509
+ }),
7510
+ sx: {
7511
+ ml: 5.5
7512
+ }
7513
+ }), /*#__PURE__*/jsx(OptionsEditor, {
7514
+ options: radioOptions,
7515
+ onChange: setRadioOptions
7516
+ }), /*#__PURE__*/jsx(InputFieldCard, {
7517
+ icon: /*#__PURE__*/jsx(FormatListBulletedIcon, {
7518
+ fontSize: "small"
7519
+ }),
7520
+ label: t('sidePanel.inputFields.listInput', 'List Input'),
7521
+ description: t('sidePanel.inputFields.listInputDesc', 'Multiple option selection'),
7522
+ onClick: function onClick() {
7523
+ return addInputElement('list', {
7524
+ promptText: listPrompt,
7525
+ minSelections: listMinSelections,
7526
+ maxSelections: listMaxSelections,
7527
+ options: listOptions
7528
+ });
7529
+ }
7530
+ }), /*#__PURE__*/jsx(TextField, {
7531
+ size: "small",
7532
+ placeholder: t('sidePanel.inputFields.promptTextHint', 'Prompt text shown to user...'),
7533
+ value: listPrompt,
7534
+ onChange: function onChange(e) {
7535
+ return setListPrompt(e.target.value);
7536
+ },
7537
+ sx: {
7538
+ ml: 6.5,
7539
+ mr: 1,
7540
+ '& .MuiInputBase-input': {
7541
+ fontSize: 12,
7542
+ py: 0.75
7543
+ }
7544
+ }
7545
+ }), /*#__PURE__*/jsx(OptionsEditor, {
7546
+ options: listOptions,
7547
+ onChange: setListOptions
7548
+ }), /*#__PURE__*/jsxs(Box, {
7549
+ sx: {
7550
+ display: 'flex',
7551
+ gap: 1,
7552
+ ml: 6.5,
7553
+ mr: 1
7554
+ },
7555
+ children: [/*#__PURE__*/jsx(TextField, {
7556
+ size: "small",
7557
+ type: "number",
7558
+ label: t('sidePanel.inputFields.minSelections', 'Min select'),
7559
+ value: listMinSelections,
7560
+ onChange: function onChange(e) {
7561
+ return setListMinSelections(Math.max(0, parseInt(e.target.value) || 0));
7562
+ },
7563
+ inputProps: {
7564
+ min: 0
7565
+ },
7566
+ sx: {
7567
+ flex: 1,
7568
+ '& .MuiInputBase-input': {
7569
+ fontSize: 12,
7570
+ py: 0.75
7571
+ }
7572
+ }
7573
+ }), /*#__PURE__*/jsx(TextField, {
7574
+ size: "small",
7575
+ type: "number",
7576
+ label: t('sidePanel.inputFields.maxSelections', 'Max select'),
7577
+ value: listMaxSelections,
7578
+ onChange: function onChange(e) {
7579
+ return setListMaxSelections(Math.max(0, parseInt(e.target.value) || 0));
7580
+ },
7581
+ inputProps: {
7582
+ min: 0
7583
+ },
7584
+ sx: {
7585
+ flex: 1,
7586
+ '& .MuiInputBase-input': {
7587
+ fontSize: 12,
7588
+ py: 0.75
7589
+ }
7590
+ }
7591
+ })]
7592
+ }), /*#__PURE__*/jsx(Typography, {
7593
+ variant: "caption",
7594
+ sx: {
7595
+ ml: 6.5,
7596
+ color: '#999',
7597
+ fontSize: 10
7598
+ },
7599
+ children: listMinSelections > 0 ? "Required \xB7 min ".concat(listMinSelections).concat(listMaxSelections > 0 ? ", max ".concat(listMaxSelections) : ', no max') : "Optional \xB7 max ".concat(listMaxSelections > 0 ? listMaxSelections : '∞')
7350
7600
  })]
7351
7601
  }), /*#__PURE__*/jsx(Divider, {
7352
7602
  sx: {
@@ -7376,21 +7626,33 @@ var InputFieldsPanelContent = observer(function (_ref2) {
7376
7626
  });
7377
7627
 
7378
7628
  // ── Mark-as-variable sub-form ─────────────────────────────────────────
7379
- var MarkAsVariableForm = observer(function (_ref3) {
7629
+ var MarkAsVariableForm = observer(function (_ref4) {
7380
7630
  var _selectedElement$cust;
7381
- var store = _ref3.store;
7382
- var _useState17 = useState(''),
7383
- _useState18 = _slicedToArray(_useState17, 2),
7384
- markLabel = _useState18[0],
7385
- setMarkLabel = _useState18[1];
7386
- var _useState19 = useState(false),
7387
- _useState20 = _slicedToArray(_useState19, 2),
7388
- markRequired = _useState20[0],
7389
- setMarkRequired = _useState20[1];
7390
- var _useState21 = useState('text'),
7391
- _useState22 = _slicedToArray(_useState21, 2),
7392
- markInputType = _useState22[0],
7393
- setMarkInputType = _useState22[1];
7631
+ var store = _ref4.store;
7632
+ var _useState31 = useState(''),
7633
+ _useState32 = _slicedToArray(_useState31, 2),
7634
+ markLabel = _useState32[0],
7635
+ setMarkLabel = _useState32[1];
7636
+ var _useState33 = useState(false),
7637
+ _useState34 = _slicedToArray(_useState33, 2),
7638
+ markRequired = _useState34[0],
7639
+ setMarkRequired = _useState34[1];
7640
+ var _useState35 = useState('text'),
7641
+ _useState36 = _slicedToArray(_useState35, 2),
7642
+ markInputType = _useState36[0],
7643
+ setMarkInputType = _useState36[1];
7644
+ var _useState37 = useState(['Option 1', 'Option 2']),
7645
+ _useState38 = _slicedToArray(_useState37, 2),
7646
+ markOptions = _useState38[0],
7647
+ setMarkOptions = _useState38[1];
7648
+ var _useState39 = useState(0),
7649
+ _useState40 = _slicedToArray(_useState39, 2),
7650
+ markMinSelections = _useState40[0],
7651
+ setMarkMinSelections = _useState40[1];
7652
+ var _useState41 = useState(2),
7653
+ _useState42 = _slicedToArray(_useState41, 2),
7654
+ markMaxSelections = _useState42[0],
7655
+ setMarkMaxSelections = _useState42[1];
7394
7656
  var selectedIds = store.selectedElementsIds || [];
7395
7657
  var selectedElement = selectedIds.length === 1 ? store.getElementById(selectedIds[0]) : null;
7396
7658
  var isImageElement = (selectedElement === null || selectedElement === void 0 ? void 0 : selectedElement.type) === 'image';
@@ -7399,37 +7661,52 @@ var MarkAsVariableForm = observer(function (_ref3) {
7399
7661
  var isAlreadyVariable = !!(selectedElement !== null && selectedElement !== void 0 && (_selectedElement$cust = selectedElement.custom) !== null && _selectedElement$cust !== void 0 && _selectedElement$cust.inputField);
7400
7662
  useEffect(function () {
7401
7663
  if (selectedElement && isSupportedElement) {
7402
- var _selectedElement$cust2, _selectedElement$cust3, _selectedElement$cust4;
7664
+ var _selectedElement$cust2, _selectedElement$cust3, _selectedElement$cust4, _selectedElement$cust5, _selectedElement$cust6, _selectedElement$cust7;
7403
7665
  setMarkLabel(((_selectedElement$cust2 = selectedElement.custom) === null || _selectedElement$cust2 === void 0 ? void 0 : _selectedElement$cust2.promptText) || '');
7404
7666
  setMarkRequired(!!((_selectedElement$cust3 = selectedElement.custom) !== null && _selectedElement$cust3 !== void 0 && _selectedElement$cust3.required));
7405
7667
  setMarkInputType(isImageElement ? 'image' : ((_selectedElement$cust4 = selectedElement.custom) === null || _selectedElement$cust4 === void 0 ? void 0 : _selectedElement$cust4.inputType) || 'text');
7668
+ setMarkOptions(((_selectedElement$cust5 = selectedElement.custom) === null || _selectedElement$cust5 === void 0 ? void 0 : _selectedElement$cust5.options) || ['Option 1', 'Option 2']);
7669
+ setMarkMinSelections(((_selectedElement$cust6 = selectedElement.custom) === null || _selectedElement$cust6 === void 0 ? void 0 : _selectedElement$cust6.minSelections) || 0);
7670
+ setMarkMaxSelections(((_selectedElement$cust7 = selectedElement.custom) === null || _selectedElement$cust7 === void 0 ? void 0 : _selectedElement$cust7.maxSelections) || 2);
7406
7671
  } else {
7407
7672
  setMarkLabel('');
7408
7673
  setMarkRequired(false);
7409
7674
  setMarkInputType('text');
7675
+ setMarkOptions(['Option 1', 'Option 2']);
7676
+ setMarkMinSelections(0);
7677
+ setMarkMaxSelections(2);
7410
7678
  }
7411
7679
  }, [selectedElement === null || selectedElement === void 0 ? void 0 : selectedElement.id]);
7412
7680
  var handleMark = function handleMark() {
7413
7681
  if (!selectedElement || !markLabel.trim()) return;
7682
+ var effectiveType = isImageElement ? 'image' : markInputType;
7414
7683
  selectedElement.set({
7415
- custom: _objectSpread2(_objectSpread2({}, selectedElement.custom), {}, {
7684
+ custom: _objectSpread2(_objectSpread2(_objectSpread2({}, selectedElement.custom), {}, {
7416
7685
  inputField: true,
7417
7686
  promptText: markLabel.trim(),
7418
- inputType: isImageElement ? 'image' : markInputType,
7687
+ inputType: effectiveType,
7419
7688
  required: markRequired
7420
- })
7689
+ }, ['radio', 'list'].includes(effectiveType) ? {
7690
+ options: markOptions.filter(Boolean)
7691
+ } : {}), effectiveType === 'list' ? {
7692
+ minSelections: markMinSelections,
7693
+ maxSelections: markMaxSelections
7694
+ } : {})
7421
7695
  });
7422
7696
  store.history.addUndoState();
7423
7697
  };
7424
7698
  var handleUnmark = function handleUnmark() {
7425
7699
  if (!selectedElement) return;
7426
- var _ref4 = selectedElement.custom || {};
7427
- _ref4.inputField;
7428
- _ref4.promptText;
7429
- _ref4.inputType;
7430
- _ref4.required;
7431
- _ref4.placeholder;
7432
- var rest = _objectWithoutProperties(_ref4, _excluded$2);
7700
+ var _ref5 = selectedElement.custom || {};
7701
+ _ref5.inputField;
7702
+ _ref5.promptText;
7703
+ _ref5.inputType;
7704
+ _ref5.required;
7705
+ _ref5.placeholder;
7706
+ _ref5.options;
7707
+ _ref5.minSelections;
7708
+ _ref5.maxSelections;
7709
+ var rest = _objectWithoutProperties(_ref5, _excluded$2);
7433
7710
  selectedElement.set({
7434
7711
  custom: rest
7435
7712
  });
@@ -7554,9 +7831,84 @@ var MarkAsVariableForm = observer(function (_ref3) {
7554
7831
  fontSize: 12
7555
7832
  },
7556
7833
  children: t('sidePanel.inputFields.dateInput', 'Date Input')
7834
+ }), /*#__PURE__*/jsx(MenuItem, {
7835
+ value: "radio",
7836
+ sx: {
7837
+ fontSize: 12
7838
+ },
7839
+ children: t('sidePanel.inputFields.radioInput', 'Radio Input')
7840
+ }), /*#__PURE__*/jsx(MenuItem, {
7841
+ value: "list",
7842
+ sx: {
7843
+ fontSize: 12
7844
+ },
7845
+ children: t('sidePanel.inputFields.listInput', 'List Input')
7557
7846
  })]
7558
7847
  })]
7559
- }), /*#__PURE__*/jsx(FormControlLabel, {
7848
+ }), isTextElement && (markInputType === 'radio' || markInputType === 'list') && /*#__PURE__*/jsxs(Fragment, {
7849
+ children: [/*#__PURE__*/jsx(Typography, {
7850
+ variant: "caption",
7851
+ sx: {
7852
+ color: '#888',
7853
+ fontSize: 11
7854
+ },
7855
+ children: "Options"
7856
+ }), /*#__PURE__*/jsx(OptionsEditor, {
7857
+ options: markOptions,
7858
+ onChange: setMarkOptions
7859
+ })]
7860
+ }), isTextElement && markInputType === 'list' && /*#__PURE__*/jsxs(Fragment, {
7861
+ children: [/*#__PURE__*/jsxs(Box, {
7862
+ sx: {
7863
+ display: 'flex',
7864
+ gap: 1
7865
+ },
7866
+ children: [/*#__PURE__*/jsx(TextField, {
7867
+ size: "small",
7868
+ type: "number",
7869
+ label: t('sidePanel.inputFields.minSelections', 'Min select'),
7870
+ value: markMinSelections,
7871
+ onChange: function onChange(e) {
7872
+ return setMarkMinSelections(Math.max(0, parseInt(e.target.value) || 0));
7873
+ },
7874
+ inputProps: {
7875
+ min: 0
7876
+ },
7877
+ sx: {
7878
+ flex: 1,
7879
+ '& .MuiInputBase-input': {
7880
+ fontSize: 12,
7881
+ py: 0.75
7882
+ }
7883
+ }
7884
+ }), /*#__PURE__*/jsx(TextField, {
7885
+ size: "small",
7886
+ type: "number",
7887
+ label: t('sidePanel.inputFields.maxSelections', 'Max select'),
7888
+ value: markMaxSelections,
7889
+ onChange: function onChange(e) {
7890
+ return setMarkMaxSelections(Math.max(0, parseInt(e.target.value) || 0));
7891
+ },
7892
+ inputProps: {
7893
+ min: 0
7894
+ },
7895
+ sx: {
7896
+ flex: 1,
7897
+ '& .MuiInputBase-input': {
7898
+ fontSize: 12,
7899
+ py: 0.75
7900
+ }
7901
+ }
7902
+ })]
7903
+ }), /*#__PURE__*/jsx(Typography, {
7904
+ variant: "caption",
7905
+ sx: {
7906
+ color: '#999',
7907
+ fontSize: 10
7908
+ },
7909
+ children: markMinSelections > 0 ? "Required \xB7 min ".concat(markMinSelections).concat(markMaxSelections > 0 ? ", max ".concat(markMaxSelections) : ', no max') : "Optional \xB7 max ".concat(markMaxSelections > 0 ? markMaxSelections : '∞')
7910
+ })]
7911
+ }), (!isTextElement || markInputType !== 'list') && /*#__PURE__*/jsx(FormControlLabel, {
7560
7912
  control: /*#__PURE__*/jsx(Checkbox, {
7561
7913
  size: "small",
7562
7914
  checked: markRequired,
@@ -9597,8 +9949,10 @@ var TextElementComponent = observer(function (_ref) {
9597
9949
  var scaleY = absScale.y;
9598
9950
  var cssFontStyle = element.fontStyle === 'italic' ? 'italic' : 'normal';
9599
9951
  var cssFontWeight = String(element.fontWeight || 'normal');
9952
+ var originalText = element.text;
9600
9953
  var textarea = document.createElement('textarea');
9601
- textarea.value = element.text;
9954
+ textarea.value = '';
9955
+ textarea.placeholder = originalText;
9602
9956
  textarea.style.position = 'absolute';
9603
9957
  textarea.style.top = "".concat(textPosition.y, "px");
9604
9958
  textarea.style.left = "".concat(textPosition.x, "px");
@@ -9631,15 +9985,21 @@ var TextElementComponent = observer(function (_ref) {
9631
9985
  textarea.style.wordBreak = 'break-word';
9632
9986
  textarea.style.minHeight = '0';
9633
9987
  textarea.style.minWidth = '0';
9988
+
9989
+ // Placeholder inherits the element's text color at 40% opacity
9990
+ var placeholderStyle = document.createElement('style');
9991
+ placeholderStyle.textContent = "\n textarea:placeholder-shown { opacity: 1; }\n textarea::placeholder { color: ".concat(element.fill, "; opacity: 0.4; }\n ");
9992
+ stageContainer.appendChild(placeholderStyle);
9634
9993
  stageContainer.appendChild(textarea);
9635
9994
  textarea.focus();
9636
- textarea.select();
9637
9995
  var removed = false;
9638
9996
  var removeTextarea = function removeTextarea() {
9997
+ var cancel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
9639
9998
  if (removed) return;
9640
9999
  removed = true;
10000
+ var newText = !cancel && textarea.value.length > 0 ? textarea.value : originalText;
9641
10001
  element.set({
9642
- text: textarea.value
10002
+ text: newText
9643
10003
  });
9644
10004
  element.toggleEditMode(false);
9645
10005
  if (grp) grp.show();
@@ -9647,12 +10007,15 @@ var TextElementComponent = observer(function (_ref) {
9647
10007
  if (textarea.parentNode) {
9648
10008
  textarea.parentNode.removeChild(textarea);
9649
10009
  }
10010
+ if (placeholderStyle.parentNode) {
10011
+ placeholderStyle.parentNode.removeChild(placeholderStyle);
10012
+ }
9650
10013
  };
9651
- textarea.addEventListener('blur', removeTextarea);
10014
+ textarea.addEventListener('blur', function () {
10015
+ return removeTextarea(false);
10016
+ });
9652
10017
  textarea.addEventListener('keydown', function (e) {
9653
- if (e.key === 'Escape') {
9654
- removeTextarea();
9655
- }
10018
+ if (e.key === 'Escape') removeTextarea(true);
9656
10019
  });
9657
10020
  };
9658
10021
 
@@ -10310,12 +10673,20 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
10310
10673
  imagePreview = _useState4[0],
10311
10674
  setImagePreview = _useState4[1];
10312
10675
  var fileInputRef = useRef(null);
10676
+ var _useState5 = useState([]),
10677
+ _useState6 = _slicedToArray(_useState5, 2),
10678
+ selectedItems = _useState6[0],
10679
+ setSelectedItems = _useState6[1];
10313
10680
  var config = getInputFieldsConfig();
10314
10681
  var custom = field.custom || {};
10315
10682
  var inputType = custom.inputType || 'text';
10316
10683
  var promptText = custom.promptText || custom.placeholder || 'Please provide input';
10317
10684
  var dateFormat = custom.dateFormat || 'MM-DD-YYYY';
10318
10685
  var isRequired = custom.required === true;
10686
+ var options = custom.options || [];
10687
+ var minSelections = custom.minSelections || 0;
10688
+ var maxSelections = custom.maxSelections || options.length;
10689
+ var isSubmitDisabled = inputType === 'list' ? selectedItems.length < minSelections : isRequired && !value;
10319
10690
  var logoUrl = config.logoUrl || null;
10320
10691
  var headerText = config.headerText || null;
10321
10692
  var accentColor = config.accentColor || '#0d83cd';
@@ -10323,6 +10694,7 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
10323
10694
  useEffect(function () {
10324
10695
  setValue('');
10325
10696
  setImagePreview(null);
10697
+ setSelectedItems([]);
10326
10698
  }, [field.id]);
10327
10699
  var handleImageSelect = function handleImageSelect(e) {
10328
10700
  var _e$target$files;
@@ -10342,12 +10714,14 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
10342
10714
  var dateObj = parseDateFromFormat(value);
10343
10715
  var formatted = formatDate(dateObj, dateFormat);
10344
10716
  onSubmit(field.id, formatted);
10717
+ } else if (inputType === 'list') {
10718
+ onSubmit(field.id, selectedItems.join(', '));
10345
10719
  } else {
10346
10720
  onSubmit(field.id, value);
10347
10721
  }
10348
10722
  };
10349
10723
  var handleKeyDown = function handleKeyDown(e) {
10350
- if (e.key === 'Enter' && inputType !== 'image') handleSubmit();
10724
+ if (e.key === 'Enter' && inputType !== 'image' && inputType !== 'list' && inputType !== 'radio') handleSubmit();
10351
10725
  };
10352
10726
  var renderInput = function renderInput() {
10353
10727
  var sharedSx = _objectSpread2({
@@ -10487,6 +10861,119 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
10487
10861
  })]
10488
10862
  })]
10489
10863
  });
10864
+ case 'radio':
10865
+ return /*#__PURE__*/jsx(RadioGroup, {
10866
+ value: value,
10867
+ onChange: function onChange(e) {
10868
+ return setValue(e.target.value);
10869
+ },
10870
+ sx: {
10871
+ mt: 1,
10872
+ gap: 1
10873
+ },
10874
+ children: options.map(function (opt) {
10875
+ return /*#__PURE__*/jsx(FormControlLabel, {
10876
+ value: opt,
10877
+ control: /*#__PURE__*/jsx(Radio, {
10878
+ sx: {
10879
+ color: '#d0d5dd',
10880
+ '&.Mui-checked': {
10881
+ color: accentColor
10882
+ }
10883
+ }
10884
+ }),
10885
+ label: /*#__PURE__*/jsx(Typography, {
10886
+ sx: {
10887
+ fontSize: 18
10888
+ },
10889
+ children: opt
10890
+ }),
10891
+ sx: {
10892
+ m: 0,
10893
+ border: '1px solid',
10894
+ borderColor: value === opt ? accentColor : '#d0d5dd',
10895
+ borderRadius: '8px',
10896
+ px: 2,
10897
+ py: 0.75,
10898
+ transition: 'all 0.15s ease',
10899
+ backgroundColor: value === opt ? 'rgba(13,131,205,0.04)' : 'transparent',
10900
+ '&:hover': {
10901
+ borderColor: accentColor,
10902
+ backgroundColor: 'rgba(13,131,205,0.03)'
10903
+ }
10904
+ }
10905
+ }, opt);
10906
+ })
10907
+ });
10908
+ case 'list':
10909
+ {
10910
+ var isAtMax = maxSelections > 0 && selectedItems.length >= maxSelections;
10911
+ return /*#__PURE__*/jsxs(Box, {
10912
+ sx: {
10913
+ mt: 1
10914
+ },
10915
+ children: [/*#__PURE__*/jsx(FormGroup, {
10916
+ sx: {
10917
+ gap: 1
10918
+ },
10919
+ children: options.map(function (opt) {
10920
+ var checked = selectedItems.includes(opt);
10921
+ var disabled = !checked && isAtMax;
10922
+ return /*#__PURE__*/jsx(FormControlLabel, {
10923
+ control: /*#__PURE__*/jsx(Checkbox, {
10924
+ checked: checked,
10925
+ disabled: disabled,
10926
+ onChange: function onChange(e) {
10927
+ if (e.target.checked) {
10928
+ setSelectedItems(function (prev) {
10929
+ return [].concat(_toConsumableArray(prev), [opt]);
10930
+ });
10931
+ } else {
10932
+ setSelectedItems(function (prev) {
10933
+ return prev.filter(function (i) {
10934
+ return i !== opt;
10935
+ });
10936
+ });
10937
+ }
10938
+ },
10939
+ sx: {
10940
+ color: '#d0d5dd',
10941
+ '&.Mui-checked': {
10942
+ color: accentColor
10943
+ }
10944
+ }
10945
+ }),
10946
+ label: /*#__PURE__*/jsx(Typography, {
10947
+ sx: {
10948
+ fontSize: 18,
10949
+ opacity: disabled ? 0.45 : 1
10950
+ },
10951
+ children: opt
10952
+ }),
10953
+ sx: {
10954
+ m: 0,
10955
+ border: '1px solid',
10956
+ borderColor: checked ? accentColor : '#d0d5dd',
10957
+ borderRadius: '8px',
10958
+ px: 2,
10959
+ py: 0.75,
10960
+ opacity: disabled ? 0.6 : 1,
10961
+ transition: 'all 0.15s ease',
10962
+ backgroundColor: checked ? 'rgba(13,131,205,0.04)' : 'transparent'
10963
+ }
10964
+ }, opt);
10965
+ })
10966
+ }), /*#__PURE__*/jsxs(Typography, {
10967
+ variant: "caption",
10968
+ sx: {
10969
+ color: '#999',
10970
+ display: 'block',
10971
+ mt: 1.5
10972
+ },
10973
+ children: [selectedItems.length, maxSelections > 0 ? "/".concat(maxSelections) : '', " selected", minSelections > 0 && " \xB7 min ".concat(minSelections, " required")]
10974
+ })]
10975
+ });
10976
+ }
10490
10977
  case 'text':
10491
10978
  default:
10492
10979
  return /*#__PURE__*/jsx(TextField, {
@@ -10629,7 +11116,7 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
10629
11116
  }), /*#__PURE__*/jsx(Button, {
10630
11117
  variant: "contained",
10631
11118
  onClick: handleSubmit,
10632
- disabled: isRequired && !value,
11119
+ disabled: isSubmitDisabled,
10633
11120
  sx: _objectSpread2({
10634
11121
  textTransform: 'none',
10635
11122
  fontWeight: 600,
@@ -10645,7 +11132,7 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
10645
11132
  }
10646
11133
  }, config.submitButtonStyle),
10647
11134
  children: config.submitButtonText || t('inputFieldsDialog.submit', 'Continue')
10648
- }), !isRequired && /*#__PURE__*/jsx(Button, {
11135
+ }), (inputType === 'list' ? minSelections === 0 : !isRequired) && /*#__PURE__*/jsx(Button, {
10649
11136
  variant: "outlined",
10650
11137
  onClick: function onClick() {
10651
11138
  return onSkip(field.id);
@@ -10682,10 +11169,10 @@ var InputFieldsDialog = observer(function (_ref2) {
10682
11169
  backTrigger = _ref2$backTrigger === void 0 ? 0 : _ref2$backTrigger;
10683
11170
  // displayIndex counts how many fields have been answered (for step indicator only).
10684
11171
  // Navigation always uses fields[0] — the first remaining pending field.
10685
- var _useState5 = useState(0),
10686
- _useState6 = _slicedToArray(_useState5, 2),
10687
- displayIndex = _useState6[0],
10688
- setDisplayIndex = _useState6[1];
11172
+ var _useState7 = useState(0),
11173
+ _useState8 = _slicedToArray(_useState7, 2),
11174
+ displayIndex = _useState8[0],
11175
+ setDisplayIndex = _useState8[1];
10689
11176
  var initialTotalRef = useRef(0);
10690
11177
  var completedHistoryRef = useRef([]);
10691
11178
  var isGoingBackRef = useRef(false);
@@ -10830,7 +11317,9 @@ var InputFieldsDialog = observer(function (_ref2) {
10830
11317
  text: config.CustomTextDialog,
10831
11318
  date: config.CustomDateDialog,
10832
11319
  integer: config.CustomIntegerDialog,
10833
- image: config.CustomImageDialog
11320
+ image: config.CustomImageDialog,
11321
+ radio: config.CustomRadioDialog,
11322
+ list: config.CustomListDialog
10834
11323
  };
10835
11324
  var fieldType = currentField.custom && currentField.custom.inputType || 'text';
10836
11325
  var PerTypeDialog = TYPE_DIALOG_MAP[fieldType];