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.
@@ -1,7 +1,7 @@
1
1
  import { useRef, useState, useEffect, Fragment, useCallback } from 'react';
2
2
  import { Image, Group, Rect, Text, Arrow, Path, RegularPolygon, Star, Circle, Line, Shape, Transformer, Stage, Layer } from 'react-konva';
3
3
  import { observer } from 'mobx-react-lite';
4
- import { Box, Typography, IconButton, Button, TextField } from '@mui/material';
4
+ import { Box, Typography, IconButton, Button, TextField, FormGroup, FormControlLabel, Checkbox, RadioGroup, Radio } from '@mui/material';
5
5
  import CloseIcon from '@mui/icons-material/Close';
6
6
  import { jsxs, jsx, Fragment as Fragment$1 } from 'react/jsx-runtime';
7
7
  import Konva from 'konva';
@@ -971,8 +971,10 @@ var TextElementComponent = observer(function (_ref) {
971
971
  var scaleY = absScale.y;
972
972
  var cssFontStyle = element.fontStyle === 'italic' ? 'italic' : 'normal';
973
973
  var cssFontWeight = String(element.fontWeight || 'normal');
974
+ var originalText = element.text;
974
975
  var textarea = document.createElement('textarea');
975
- textarea.value = element.text;
976
+ textarea.value = '';
977
+ textarea.placeholder = originalText;
976
978
  textarea.style.position = 'absolute';
977
979
  textarea.style.top = "".concat(textPosition.y, "px");
978
980
  textarea.style.left = "".concat(textPosition.x, "px");
@@ -1005,15 +1007,21 @@ var TextElementComponent = observer(function (_ref) {
1005
1007
  textarea.style.wordBreak = 'break-word';
1006
1008
  textarea.style.minHeight = '0';
1007
1009
  textarea.style.minWidth = '0';
1010
+
1011
+ // Placeholder inherits the element's text color at 40% opacity
1012
+ var placeholderStyle = document.createElement('style');
1013
+ placeholderStyle.textContent = "\n textarea:placeholder-shown { opacity: 1; }\n textarea::placeholder { color: ".concat(element.fill, "; opacity: 0.4; }\n ");
1014
+ stageContainer.appendChild(placeholderStyle);
1008
1015
  stageContainer.appendChild(textarea);
1009
1016
  textarea.focus();
1010
- textarea.select();
1011
1017
  var removed = false;
1012
1018
  var removeTextarea = function removeTextarea() {
1019
+ var cancel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
1013
1020
  if (removed) return;
1014
1021
  removed = true;
1022
+ var newText = !cancel && textarea.value.length > 0 ? textarea.value : originalText;
1015
1023
  element.set({
1016
- text: textarea.value
1024
+ text: newText
1017
1025
  });
1018
1026
  element.toggleEditMode(false);
1019
1027
  if (grp) grp.show();
@@ -1021,12 +1029,15 @@ var TextElementComponent = observer(function (_ref) {
1021
1029
  if (textarea.parentNode) {
1022
1030
  textarea.parentNode.removeChild(textarea);
1023
1031
  }
1032
+ if (placeholderStyle.parentNode) {
1033
+ placeholderStyle.parentNode.removeChild(placeholderStyle);
1034
+ }
1024
1035
  };
1025
- textarea.addEventListener('blur', removeTextarea);
1036
+ textarea.addEventListener('blur', function () {
1037
+ return removeTextarea(false);
1038
+ });
1026
1039
  textarea.addEventListener('keydown', function (e) {
1027
- if (e.key === 'Escape') {
1028
- removeTextarea();
1029
- }
1040
+ if (e.key === 'Escape') removeTextarea(true);
1030
1041
  });
1031
1042
  };
1032
1043
 
@@ -1684,12 +1695,20 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
1684
1695
  imagePreview = _useState4[0],
1685
1696
  setImagePreview = _useState4[1];
1686
1697
  var fileInputRef = useRef(null);
1698
+ var _useState5 = useState([]),
1699
+ _useState6 = _slicedToArray(_useState5, 2),
1700
+ selectedItems = _useState6[0],
1701
+ setSelectedItems = _useState6[1];
1687
1702
  var config = getInputFieldsConfig();
1688
1703
  var custom = field.custom || {};
1689
1704
  var inputType = custom.inputType || 'text';
1690
1705
  var promptText = custom.promptText || custom.placeholder || 'Please provide input';
1691
1706
  var dateFormat = custom.dateFormat || 'MM-DD-YYYY';
1692
1707
  var isRequired = custom.required === true;
1708
+ var options = custom.options || [];
1709
+ var minSelections = custom.minSelections || 0;
1710
+ var maxSelections = custom.maxSelections || options.length;
1711
+ var isSubmitDisabled = inputType === 'list' ? selectedItems.length < minSelections : isRequired && !value;
1693
1712
  var logoUrl = config.logoUrl || null;
1694
1713
  var headerText = config.headerText || null;
1695
1714
  var accentColor = config.accentColor || '#0d83cd';
@@ -1697,6 +1716,7 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
1697
1716
  useEffect(function () {
1698
1717
  setValue('');
1699
1718
  setImagePreview(null);
1719
+ setSelectedItems([]);
1700
1720
  }, [field.id]);
1701
1721
  var handleImageSelect = function handleImageSelect(e) {
1702
1722
  var _e$target$files;
@@ -1716,12 +1736,14 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
1716
1736
  var dateObj = parseDateFromFormat(value);
1717
1737
  var formatted = formatDate(dateObj, dateFormat);
1718
1738
  onSubmit(field.id, formatted);
1739
+ } else if (inputType === 'list') {
1740
+ onSubmit(field.id, selectedItems.join(', '));
1719
1741
  } else {
1720
1742
  onSubmit(field.id, value);
1721
1743
  }
1722
1744
  };
1723
1745
  var handleKeyDown = function handleKeyDown(e) {
1724
- if (e.key === 'Enter' && inputType !== 'image') handleSubmit();
1746
+ if (e.key === 'Enter' && inputType !== 'image' && inputType !== 'list' && inputType !== 'radio') handleSubmit();
1725
1747
  };
1726
1748
  var renderInput = function renderInput() {
1727
1749
  var sharedSx = _objectSpread2({
@@ -1861,6 +1883,119 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
1861
1883
  })]
1862
1884
  })]
1863
1885
  });
1886
+ case 'radio':
1887
+ return /*#__PURE__*/jsx(RadioGroup, {
1888
+ value: value,
1889
+ onChange: function onChange(e) {
1890
+ return setValue(e.target.value);
1891
+ },
1892
+ sx: {
1893
+ mt: 1,
1894
+ gap: 1
1895
+ },
1896
+ children: options.map(function (opt) {
1897
+ return /*#__PURE__*/jsx(FormControlLabel, {
1898
+ value: opt,
1899
+ control: /*#__PURE__*/jsx(Radio, {
1900
+ sx: {
1901
+ color: '#d0d5dd',
1902
+ '&.Mui-checked': {
1903
+ color: accentColor
1904
+ }
1905
+ }
1906
+ }),
1907
+ label: /*#__PURE__*/jsx(Typography, {
1908
+ sx: {
1909
+ fontSize: 18
1910
+ },
1911
+ children: opt
1912
+ }),
1913
+ sx: {
1914
+ m: 0,
1915
+ border: '1px solid',
1916
+ borderColor: value === opt ? accentColor : '#d0d5dd',
1917
+ borderRadius: '8px',
1918
+ px: 2,
1919
+ py: 0.75,
1920
+ transition: 'all 0.15s ease',
1921
+ backgroundColor: value === opt ? 'rgba(13,131,205,0.04)' : 'transparent',
1922
+ '&:hover': {
1923
+ borderColor: accentColor,
1924
+ backgroundColor: 'rgba(13,131,205,0.03)'
1925
+ }
1926
+ }
1927
+ }, opt);
1928
+ })
1929
+ });
1930
+ case 'list':
1931
+ {
1932
+ var isAtMax = maxSelections > 0 && selectedItems.length >= maxSelections;
1933
+ return /*#__PURE__*/jsxs(Box, {
1934
+ sx: {
1935
+ mt: 1
1936
+ },
1937
+ children: [/*#__PURE__*/jsx(FormGroup, {
1938
+ sx: {
1939
+ gap: 1
1940
+ },
1941
+ children: options.map(function (opt) {
1942
+ var checked = selectedItems.includes(opt);
1943
+ var disabled = !checked && isAtMax;
1944
+ return /*#__PURE__*/jsx(FormControlLabel, {
1945
+ control: /*#__PURE__*/jsx(Checkbox, {
1946
+ checked: checked,
1947
+ disabled: disabled,
1948
+ onChange: function onChange(e) {
1949
+ if (e.target.checked) {
1950
+ setSelectedItems(function (prev) {
1951
+ return [].concat(_toConsumableArray(prev), [opt]);
1952
+ });
1953
+ } else {
1954
+ setSelectedItems(function (prev) {
1955
+ return prev.filter(function (i) {
1956
+ return i !== opt;
1957
+ });
1958
+ });
1959
+ }
1960
+ },
1961
+ sx: {
1962
+ color: '#d0d5dd',
1963
+ '&.Mui-checked': {
1964
+ color: accentColor
1965
+ }
1966
+ }
1967
+ }),
1968
+ label: /*#__PURE__*/jsx(Typography, {
1969
+ sx: {
1970
+ fontSize: 18,
1971
+ opacity: disabled ? 0.45 : 1
1972
+ },
1973
+ children: opt
1974
+ }),
1975
+ sx: {
1976
+ m: 0,
1977
+ border: '1px solid',
1978
+ borderColor: checked ? accentColor : '#d0d5dd',
1979
+ borderRadius: '8px',
1980
+ px: 2,
1981
+ py: 0.75,
1982
+ opacity: disabled ? 0.6 : 1,
1983
+ transition: 'all 0.15s ease',
1984
+ backgroundColor: checked ? 'rgba(13,131,205,0.04)' : 'transparent'
1985
+ }
1986
+ }, opt);
1987
+ })
1988
+ }), /*#__PURE__*/jsxs(Typography, {
1989
+ variant: "caption",
1990
+ sx: {
1991
+ color: '#999',
1992
+ display: 'block',
1993
+ mt: 1.5
1994
+ },
1995
+ children: [selectedItems.length, maxSelections > 0 ? "/".concat(maxSelections) : '', " selected", minSelections > 0 && " \xB7 min ".concat(minSelections, " required")]
1996
+ })]
1997
+ });
1998
+ }
1864
1999
  case 'text':
1865
2000
  default:
1866
2001
  return /*#__PURE__*/jsx(TextField, {
@@ -2003,7 +2138,7 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
2003
2138
  }), /*#__PURE__*/jsx(Button, {
2004
2139
  variant: "contained",
2005
2140
  onClick: handleSubmit,
2006
- disabled: isRequired && !value,
2141
+ disabled: isSubmitDisabled,
2007
2142
  sx: _objectSpread2({
2008
2143
  textTransform: 'none',
2009
2144
  fontWeight: 600,
@@ -2019,7 +2154,7 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
2019
2154
  }
2020
2155
  }, config.submitButtonStyle),
2021
2156
  children: config.submitButtonText || t('inputFieldsDialog.submit', 'Continue')
2022
- }), !isRequired && /*#__PURE__*/jsx(Button, {
2157
+ }), (inputType === 'list' ? minSelections === 0 : !isRequired) && /*#__PURE__*/jsx(Button, {
2023
2158
  variant: "outlined",
2024
2159
  onClick: function onClick() {
2025
2160
  return onSkip(field.id);
@@ -2056,10 +2191,10 @@ var InputFieldsDialog = observer(function (_ref2) {
2056
2191
  backTrigger = _ref2$backTrigger === void 0 ? 0 : _ref2$backTrigger;
2057
2192
  // displayIndex counts how many fields have been answered (for step indicator only).
2058
2193
  // Navigation always uses fields[0] — the first remaining pending field.
2059
- var _useState5 = useState(0),
2060
- _useState6 = _slicedToArray(_useState5, 2),
2061
- displayIndex = _useState6[0],
2062
- setDisplayIndex = _useState6[1];
2194
+ var _useState7 = useState(0),
2195
+ _useState8 = _slicedToArray(_useState7, 2),
2196
+ displayIndex = _useState8[0],
2197
+ setDisplayIndex = _useState8[1];
2063
2198
  var initialTotalRef = useRef(0);
2064
2199
  var completedHistoryRef = useRef([]);
2065
2200
  var isGoingBackRef = useRef(false);
@@ -2204,7 +2339,9 @@ var InputFieldsDialog = observer(function (_ref2) {
2204
2339
  text: config.CustomTextDialog,
2205
2340
  date: config.CustomDateDialog,
2206
2341
  integer: config.CustomIntegerDialog,
2207
- image: config.CustomImageDialog
2342
+ image: config.CustomImageDialog,
2343
+ radio: config.CustomRadioDialog,
2344
+ list: config.CustomListDialog
2208
2345
  };
2209
2346
  var fieldType = currentField.custom && currentField.custom.inputType || 'text';
2210
2347
  var PerTypeDialog = TYPE_DIALOG_MAP[fieldType];