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.
@@ -975,8 +975,10 @@ var TextElementComponent = mobxReactLite.observer(function (_ref) {
975
975
  var scaleY = absScale.y;
976
976
  var cssFontStyle = element.fontStyle === 'italic' ? 'italic' : 'normal';
977
977
  var cssFontWeight = String(element.fontWeight || 'normal');
978
+ var originalText = element.text;
978
979
  var textarea = document.createElement('textarea');
979
- textarea.value = element.text;
980
+ textarea.value = '';
981
+ textarea.placeholder = originalText;
980
982
  textarea.style.position = 'absolute';
981
983
  textarea.style.top = "".concat(textPosition.y, "px");
982
984
  textarea.style.left = "".concat(textPosition.x, "px");
@@ -1009,15 +1011,21 @@ var TextElementComponent = mobxReactLite.observer(function (_ref) {
1009
1011
  textarea.style.wordBreak = 'break-word';
1010
1012
  textarea.style.minHeight = '0';
1011
1013
  textarea.style.minWidth = '0';
1014
+
1015
+ // Placeholder inherits the element's text color at 40% opacity
1016
+ var placeholderStyle = document.createElement('style');
1017
+ placeholderStyle.textContent = "\n textarea:placeholder-shown { opacity: 1; }\n textarea::placeholder { color: ".concat(element.fill, "; opacity: 0.4; }\n ");
1018
+ stageContainer.appendChild(placeholderStyle);
1012
1019
  stageContainer.appendChild(textarea);
1013
1020
  textarea.focus();
1014
- textarea.select();
1015
1021
  var removed = false;
1016
1022
  var removeTextarea = function removeTextarea() {
1023
+ var cancel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
1017
1024
  if (removed) return;
1018
1025
  removed = true;
1026
+ var newText = !cancel && textarea.value.length > 0 ? textarea.value : originalText;
1019
1027
  element.set({
1020
- text: textarea.value
1028
+ text: newText
1021
1029
  });
1022
1030
  element.toggleEditMode(false);
1023
1031
  if (grp) grp.show();
@@ -1025,12 +1033,15 @@ var TextElementComponent = mobxReactLite.observer(function (_ref) {
1025
1033
  if (textarea.parentNode) {
1026
1034
  textarea.parentNode.removeChild(textarea);
1027
1035
  }
1036
+ if (placeholderStyle.parentNode) {
1037
+ placeholderStyle.parentNode.removeChild(placeholderStyle);
1038
+ }
1028
1039
  };
1029
- textarea.addEventListener('blur', removeTextarea);
1040
+ textarea.addEventListener('blur', function () {
1041
+ return removeTextarea(false);
1042
+ });
1030
1043
  textarea.addEventListener('keydown', function (e) {
1031
- if (e.key === 'Escape') {
1032
- removeTextarea();
1033
- }
1044
+ if (e.key === 'Escape') removeTextarea(true);
1034
1045
  });
1035
1046
  };
1036
1047
 
@@ -1688,12 +1699,20 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
1688
1699
  imagePreview = _useState4[0],
1689
1700
  setImagePreview = _useState4[1];
1690
1701
  var fileInputRef = react.useRef(null);
1702
+ var _useState5 = react.useState([]),
1703
+ _useState6 = _slicedToArray(_useState5, 2),
1704
+ selectedItems = _useState6[0],
1705
+ setSelectedItems = _useState6[1];
1691
1706
  var config = getInputFieldsConfig();
1692
1707
  var custom = field.custom || {};
1693
1708
  var inputType = custom.inputType || 'text';
1694
1709
  var promptText = custom.promptText || custom.placeholder || 'Please provide input';
1695
1710
  var dateFormat = custom.dateFormat || 'MM-DD-YYYY';
1696
1711
  var isRequired = custom.required === true;
1712
+ var options = custom.options || [];
1713
+ var minSelections = custom.minSelections || 0;
1714
+ var maxSelections = custom.maxSelections || options.length;
1715
+ var isSubmitDisabled = inputType === 'list' ? selectedItems.length < minSelections : isRequired && !value;
1697
1716
  var logoUrl = config.logoUrl || null;
1698
1717
  var headerText = config.headerText || null;
1699
1718
  var accentColor = config.accentColor || '#0d83cd';
@@ -1701,6 +1720,7 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
1701
1720
  react.useEffect(function () {
1702
1721
  setValue('');
1703
1722
  setImagePreview(null);
1723
+ setSelectedItems([]);
1704
1724
  }, [field.id]);
1705
1725
  var handleImageSelect = function handleImageSelect(e) {
1706
1726
  var _e$target$files;
@@ -1720,12 +1740,14 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
1720
1740
  var dateObj = parseDateFromFormat(value);
1721
1741
  var formatted = formatDate(dateObj, dateFormat);
1722
1742
  onSubmit(field.id, formatted);
1743
+ } else if (inputType === 'list') {
1744
+ onSubmit(field.id, selectedItems.join(', '));
1723
1745
  } else {
1724
1746
  onSubmit(field.id, value);
1725
1747
  }
1726
1748
  };
1727
1749
  var handleKeyDown = function handleKeyDown(e) {
1728
- if (e.key === 'Enter' && inputType !== 'image') handleSubmit();
1750
+ if (e.key === 'Enter' && inputType !== 'image' && inputType !== 'list' && inputType !== 'radio') handleSubmit();
1729
1751
  };
1730
1752
  var renderInput = function renderInput() {
1731
1753
  var sharedSx = _objectSpread2({
@@ -1865,6 +1887,119 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
1865
1887
  })]
1866
1888
  })]
1867
1889
  });
1890
+ case 'radio':
1891
+ return /*#__PURE__*/jsxRuntime.jsx(material.RadioGroup, {
1892
+ value: value,
1893
+ onChange: function onChange(e) {
1894
+ return setValue(e.target.value);
1895
+ },
1896
+ sx: {
1897
+ mt: 1,
1898
+ gap: 1
1899
+ },
1900
+ children: options.map(function (opt) {
1901
+ return /*#__PURE__*/jsxRuntime.jsx(material.FormControlLabel, {
1902
+ value: opt,
1903
+ control: /*#__PURE__*/jsxRuntime.jsx(material.Radio, {
1904
+ sx: {
1905
+ color: '#d0d5dd',
1906
+ '&.Mui-checked': {
1907
+ color: accentColor
1908
+ }
1909
+ }
1910
+ }),
1911
+ label: /*#__PURE__*/jsxRuntime.jsx(material.Typography, {
1912
+ sx: {
1913
+ fontSize: 18
1914
+ },
1915
+ children: opt
1916
+ }),
1917
+ sx: {
1918
+ m: 0,
1919
+ border: '1px solid',
1920
+ borderColor: value === opt ? accentColor : '#d0d5dd',
1921
+ borderRadius: '8px',
1922
+ px: 2,
1923
+ py: 0.75,
1924
+ transition: 'all 0.15s ease',
1925
+ backgroundColor: value === opt ? 'rgba(13,131,205,0.04)' : 'transparent',
1926
+ '&:hover': {
1927
+ borderColor: accentColor,
1928
+ backgroundColor: 'rgba(13,131,205,0.03)'
1929
+ }
1930
+ }
1931
+ }, opt);
1932
+ })
1933
+ });
1934
+ case 'list':
1935
+ {
1936
+ var isAtMax = maxSelections > 0 && selectedItems.length >= maxSelections;
1937
+ return /*#__PURE__*/jsxRuntime.jsxs(material.Box, {
1938
+ sx: {
1939
+ mt: 1
1940
+ },
1941
+ children: [/*#__PURE__*/jsxRuntime.jsx(material.FormGroup, {
1942
+ sx: {
1943
+ gap: 1
1944
+ },
1945
+ children: options.map(function (opt) {
1946
+ var checked = selectedItems.includes(opt);
1947
+ var disabled = !checked && isAtMax;
1948
+ return /*#__PURE__*/jsxRuntime.jsx(material.FormControlLabel, {
1949
+ control: /*#__PURE__*/jsxRuntime.jsx(material.Checkbox, {
1950
+ checked: checked,
1951
+ disabled: disabled,
1952
+ onChange: function onChange(e) {
1953
+ if (e.target.checked) {
1954
+ setSelectedItems(function (prev) {
1955
+ return [].concat(_toConsumableArray(prev), [opt]);
1956
+ });
1957
+ } else {
1958
+ setSelectedItems(function (prev) {
1959
+ return prev.filter(function (i) {
1960
+ return i !== opt;
1961
+ });
1962
+ });
1963
+ }
1964
+ },
1965
+ sx: {
1966
+ color: '#d0d5dd',
1967
+ '&.Mui-checked': {
1968
+ color: accentColor
1969
+ }
1970
+ }
1971
+ }),
1972
+ label: /*#__PURE__*/jsxRuntime.jsx(material.Typography, {
1973
+ sx: {
1974
+ fontSize: 18,
1975
+ opacity: disabled ? 0.45 : 1
1976
+ },
1977
+ children: opt
1978
+ }),
1979
+ sx: {
1980
+ m: 0,
1981
+ border: '1px solid',
1982
+ borderColor: checked ? accentColor : '#d0d5dd',
1983
+ borderRadius: '8px',
1984
+ px: 2,
1985
+ py: 0.75,
1986
+ opacity: disabled ? 0.6 : 1,
1987
+ transition: 'all 0.15s ease',
1988
+ backgroundColor: checked ? 'rgba(13,131,205,0.04)' : 'transparent'
1989
+ }
1990
+ }, opt);
1991
+ })
1992
+ }), /*#__PURE__*/jsxRuntime.jsxs(material.Typography, {
1993
+ variant: "caption",
1994
+ sx: {
1995
+ color: '#999',
1996
+ display: 'block',
1997
+ mt: 1.5
1998
+ },
1999
+ children: [selectedItems.length, maxSelections > 0 ? "/".concat(maxSelections) : '', " selected", minSelections > 0 && " \xB7 min ".concat(minSelections, " required")]
2000
+ })]
2001
+ });
2002
+ }
1868
2003
  case 'text':
1869
2004
  default:
1870
2005
  return /*#__PURE__*/jsxRuntime.jsx(material.TextField, {
@@ -2007,7 +2142,7 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
2007
2142
  }), /*#__PURE__*/jsxRuntime.jsx(material.Button, {
2008
2143
  variant: "contained",
2009
2144
  onClick: handleSubmit,
2010
- disabled: isRequired && !value,
2145
+ disabled: isSubmitDisabled,
2011
2146
  sx: _objectSpread2({
2012
2147
  textTransform: 'none',
2013
2148
  fontWeight: 600,
@@ -2023,7 +2158,7 @@ var SingleFieldDialog = function SingleFieldDialog(_ref) {
2023
2158
  }
2024
2159
  }, config.submitButtonStyle),
2025
2160
  children: config.submitButtonText || t('inputFieldsDialog.submit', 'Continue')
2026
- }), !isRequired && /*#__PURE__*/jsxRuntime.jsx(material.Button, {
2161
+ }), (inputType === 'list' ? minSelections === 0 : !isRequired) && /*#__PURE__*/jsxRuntime.jsx(material.Button, {
2027
2162
  variant: "outlined",
2028
2163
  onClick: function onClick() {
2029
2164
  return onSkip(field.id);
@@ -2060,10 +2195,10 @@ var InputFieldsDialog = mobxReactLite.observer(function (_ref2) {
2060
2195
  backTrigger = _ref2$backTrigger === void 0 ? 0 : _ref2$backTrigger;
2061
2196
  // displayIndex counts how many fields have been answered (for step indicator only).
2062
2197
  // Navigation always uses fields[0] — the first remaining pending field.
2063
- var _useState5 = react.useState(0),
2064
- _useState6 = _slicedToArray(_useState5, 2),
2065
- displayIndex = _useState6[0],
2066
- setDisplayIndex = _useState6[1];
2198
+ var _useState7 = react.useState(0),
2199
+ _useState8 = _slicedToArray(_useState7, 2),
2200
+ displayIndex = _useState8[0],
2201
+ setDisplayIndex = _useState8[1];
2067
2202
  var initialTotalRef = react.useRef(0);
2068
2203
  var completedHistoryRef = react.useRef([]);
2069
2204
  var isGoingBackRef = react.useRef(false);
@@ -2208,7 +2343,9 @@ var InputFieldsDialog = mobxReactLite.observer(function (_ref2) {
2208
2343
  text: config.CustomTextDialog,
2209
2344
  date: config.CustomDateDialog,
2210
2345
  integer: config.CustomIntegerDialog,
2211
- image: config.CustomImageDialog
2346
+ image: config.CustomImageDialog,
2347
+ radio: config.CustomRadioDialog,
2348
+ list: config.CustomListDialog
2212
2349
  };
2213
2350
  var fieldType = currentField.custom && currentField.custom.inputType || 'text';
2214
2351
  var PerTypeDialog = TYPE_DIALOG_MAP[fieldType];