sag_components 2.0.0-beta329 → 2.0.0-beta330

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/index.d.ts CHANGED
@@ -1558,7 +1558,7 @@ declare function RangePop(props: any): react_jsx_runtime.JSX.Element;
1558
1558
 
1559
1559
  declare function SearchInput(props: any): react_jsx_runtime.JSX.Element;
1560
1560
 
1561
- declare function ItemManagerPanel({ width, height, disableSection, onSendForms, editMode, disabledSendForms, AllFormsSent, itemAndPackage, setItemAndPackage, linkColor, backgroundColor, buttonTooltipText, trashTooltipText, maxVisibleVendors, componentText, SubTitleColor, searchValue, onSearchChange, searchResults, filteredVendors, isSearchLoading, isLoading, isLoadingText, onLastRowsReached, lastRowsThreshold, onBackFromList, onPackageAdded, }: {
1561
+ declare function ItemManagerPanel({ width, height, disableSection, onSendForms, editMode, disabledSendForms, AllFormsSent, itemAndPackage, setItemAndPackage, linkColor, backgroundColor, buttonTooltipText, trashTooltipText, maxVisibleVendors, componentText, SubTitleColor, searchValue, onSearchChange, searchResults, filteredVendors, isSearchLoading, isLoading, isLoadingText, onLastRowsReached, lastRowsThreshold, onBackFromList, onPackageAdded, brandSuggestions, onBrandSaved, }: {
1562
1562
  width?: string;
1563
1563
  height?: string;
1564
1564
  disableSection?: boolean;
@@ -1586,6 +1586,8 @@ declare function ItemManagerPanel({ width, height, disableSection, onSendForms,
1586
1586
  lastRowsThreshold?: number;
1587
1587
  onBackFromList?: any;
1588
1588
  onPackageAdded?: any;
1589
+ brandSuggestions?: any[];
1590
+ onBrandSaved?: any;
1589
1591
  }): react_jsx_runtime.JSX.Element;
1590
1592
 
1591
1593
  /**
package/dist/index.esm.js CHANGED
@@ -12395,16 +12395,13 @@ const Td$1 = styled.td`
12395
12395
  `;
12396
12396
  const Tr = styled.tr`
12397
12397
  border-bottom: 1px solid #f3f4f6;
12398
- ${_ref => {
12399
- let {
12400
- enableHover,
12401
- selectHoverColor
12402
- } = _ref;
12403
- return enableHover && `&:hover {
12398
+ ${({
12399
+ enableHover,
12400
+ selectHoverColor
12401
+ }) => enableHover && `&:hover {
12404
12402
  background-color: ${selectHoverColor};
12405
12403
  cursor: pointer;
12406
- }`;
12407
- }}
12404
+ }`}
12408
12405
  `;
12409
12406
  const InfoText = styled.div`
12410
12407
  font-weight: 400;
@@ -49055,17 +49052,83 @@ const AddNegotiatedBrand = styled.label`
49055
49052
  font-family: Poppins;
49056
49053
  font-size: 15px;
49057
49054
  `;
49058
- const NegotiatedTextarea = styled.textarea`
49055
+ const AutocompleteWrapper = styled.div`
49056
+ position: relative;
49059
49057
  width: 90%;
49060
- min-height: 220px;
49061
49058
  margin-top: 8px;
49059
+ `;
49060
+ const NegotiatedTextarea = styled.textarea`
49061
+ width: 100%;
49062
+ min-height: 220px;
49062
49063
  border: 1px solid #e3e4e5;
49063
49064
  border-radius: 12px;
49064
49065
  padding: 16px;
49065
49066
  font-size: 15px;
49067
+ font-family: Poppins, sans-serif;
49068
+ line-height: 1.5;
49069
+ letter-spacing: normal;
49066
49070
  resize: vertical;
49067
- background: #fff;
49071
+ background: transparent;
49072
+ color: #212121;
49073
+ position: relative;
49074
+ z-index: 1;
49075
+ box-sizing: border-box;
49076
+ outline: none;
49077
+ `;
49078
+ const GhostSuggestion = styled.span`
49079
+ position: absolute;
49080
+ pointer-events: none;
49081
+ color: #b1b1b1;
49082
+ font-size: 15px;
49083
+ font-family: Poppins, sans-serif;
49084
+ line-height: 1.5;
49085
+ letter-spacing: normal;
49086
+ white-space: pre;
49087
+ z-index: 2;
49088
+ `;
49089
+ const MeasureSpan = styled.span`
49090
+ position: absolute;
49091
+ visibility: hidden;
49092
+ white-space: pre;
49093
+ font-size: 15px;
49094
+ font-family: Poppins, sans-serif;
49095
+ line-height: 1.5;
49096
+ letter-spacing: normal;
49097
+ `;
49098
+ const SuggestionDropdown = styled.ul`
49099
+ position: absolute;
49100
+ top: 100%;
49101
+ left: 0;
49102
+ z-index: 100;
49103
+ width: 100%;
49104
+ max-height: 240px;
49105
+ overflow-y: auto;
49106
+ list-style: none;
49107
+ margin: 4px 0 0 0;
49108
+ padding: 8px 0;
49109
+ background-color: #fff;
49110
+ border-radius: 8px;
49111
+ box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.1);
49112
+ box-sizing: border-box;
49113
+ font-family: Poppins, sans-serif;
49114
+ font-size: 15px;
49115
+
49116
+ &::-webkit-scrollbar { width: 4px; }
49117
+ &::-webkit-scrollbar-track { background: #E8E8E8; border-radius: 5px; }
49118
+ &::-webkit-scrollbar-thumb { background: #D0D0D0; border-radius: 5px; }
49119
+ `;
49120
+ const SuggestionItem = styled.li`
49121
+ padding: 8px 16px;
49122
+ cursor: pointer;
49068
49123
  color: #212121;
49124
+ font-size: 14px;
49125
+ font-weight: 400;
49126
+ transition: background-color 0.15s;
49127
+ background-color: ${props => props.$highlighted ? '#EDF6FF' : '#fff'};
49128
+
49129
+ &:hover {
49130
+ background-color: #EDF6FF;
49131
+ }
49069
49132
  `;
49070
49133
  const NegotiatedContainer = styled.div`
49071
49134
  display: flex;
@@ -49078,6 +49141,155 @@ const NegotiatedContainer = styled.div`
49078
49141
  margin-top: 8px;
49079
49142
  `;
49080
49143
 
49144
+ const MAX_VISIBLE_SUGGESTIONS = 4;
49145
+ const getMatchingSuggestions = (input, suggestions) => {
49146
+ const normalized = input.trim().toLowerCase().replace(/\s+/g, " ");
49147
+ if (!normalized || suggestions.length === 0) return [];
49148
+ const rank = (a, b) => b.frequency - a.frequency || (b.lastUsed || 0) - (a.lastUsed || 0);
49149
+ return suggestions.filter(s => {
49150
+ const norm = s.value.trim().toLowerCase().replace(/\s+/g, " ");
49151
+ return norm.startsWith(normalized) && norm !== normalized;
49152
+ }).sort(rank).slice(0, MAX_VISIBLE_SUGGESTIONS);
49153
+ };
49154
+ const BrandAutocomplete = ({
49155
+ value,
49156
+ onChange,
49157
+ suggestions = [],
49158
+ placeholder = "",
49159
+ maxLength = 200
49160
+ }) => {
49161
+ const measureRef = useRef(null);
49162
+ const dropdownRef = useRef(null);
49163
+ const blurTimeoutRef = useRef(null);
49164
+ const [textWidth, setTextWidth] = useState(0);
49165
+ const [highlightedIndex, setHighlightedIndex] = useState(-1);
49166
+ const [showDropdown, setShowDropdown] = useState(false);
49167
+ const matchingSuggestions = useMemo(() => getMatchingSuggestions(value, suggestions), [value, suggestions]);
49168
+ const activeSuggestion = highlightedIndex >= 0 ? matchingSuggestions[highlightedIndex] : matchingSuggestions[0] || null;
49169
+ const suggestionRemainder = activeSuggestion ? activeSuggestion.value.slice(value.length) : "";
49170
+
49171
+ // Measure typed text width after each change
49172
+ useEffect(() => {
49173
+ if (measureRef.current) {
49174
+ setTextWidth(measureRef.current.offsetWidth);
49175
+ }
49176
+ }, [value]);
49177
+
49178
+ // Close dropdown when no matches
49179
+ useEffect(() => {
49180
+ if (matchingSuggestions.length === 0) {
49181
+ setShowDropdown(false);
49182
+ setHighlightedIndex(-1);
49183
+ }
49184
+ }, [matchingSuggestions.length]);
49185
+
49186
+ // Scroll highlighted item into view
49187
+ useEffect(() => {
49188
+ if (highlightedIndex >= 0 && dropdownRef.current) {
49189
+ const items = dropdownRef.current.querySelectorAll("li");
49190
+ if (items[highlightedIndex]) {
49191
+ items[highlightedIndex].scrollIntoView({
49192
+ block: "nearest"
49193
+ });
49194
+ }
49195
+ }
49196
+ }, [highlightedIndex]);
49197
+
49198
+ // Cleanup blur timeout on unmount
49199
+ useEffect(() => {
49200
+ return () => {
49201
+ if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
49202
+ };
49203
+ }, []);
49204
+ const handleKeyDown = e => {
49205
+ const len = matchingSuggestions.length;
49206
+ if (e.key === "ArrowDown" && len > 0) {
49207
+ e.preventDefault();
49208
+ if (!showDropdown) {
49209
+ setShowDropdown(true);
49210
+ setHighlightedIndex(0);
49211
+ } else {
49212
+ setHighlightedIndex(prev => (prev + 1) % len);
49213
+ }
49214
+ return;
49215
+ }
49216
+ if (e.key === "ArrowUp" && len > 0 && showDropdown) {
49217
+ e.preventDefault();
49218
+ setHighlightedIndex(prev => prev <= 0 ? len - 1 : prev - 1);
49219
+ return;
49220
+ }
49221
+ if (e.key === "Enter" && showDropdown && highlightedIndex >= 0) {
49222
+ e.preventDefault();
49223
+ onChange(matchingSuggestions[highlightedIndex].value);
49224
+ setShowDropdown(false);
49225
+ setHighlightedIndex(-1);
49226
+ return;
49227
+ }
49228
+ if (e.key === "Escape" && showDropdown) {
49229
+ e.preventDefault();
49230
+ setShowDropdown(false);
49231
+ setHighlightedIndex(-1);
49232
+ return;
49233
+ }
49234
+ if (e.key === "Tab" && activeSuggestion && value.trim().length > 0) {
49235
+ e.preventDefault();
49236
+ onChange(activeSuggestion.value);
49237
+ setShowDropdown(false);
49238
+ setHighlightedIndex(-1);
49239
+ }
49240
+ };
49241
+ const handleChange = e => {
49242
+ const val = e.target.value;
49243
+ if (val.includes("$$")) return;
49244
+ const collapsed = val.replace(/ +/g, " ");
49245
+ onChange(collapsed);
49246
+ setHighlightedIndex(-1);
49247
+ setShowDropdown(collapsed.trim().length > 0);
49248
+ };
49249
+ const handleFocus = useCallback(() => {
49250
+ if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
49251
+ if (value.trim().length > 0 && matchingSuggestions.length > 0) {
49252
+ setShowDropdown(true);
49253
+ }
49254
+ }, [value, matchingSuggestions.length]);
49255
+ const handleBlur = useCallback(() => {
49256
+ blurTimeoutRef.current = setTimeout(() => {
49257
+ setShowDropdown(false);
49258
+ setHighlightedIndex(-1);
49259
+ }, 150);
49260
+ }, []);
49261
+ const handleSuggestionMouseDown = (e, suggestion) => {
49262
+ e.preventDefault();
49263
+ onChange(suggestion.value);
49264
+ setShowDropdown(false);
49265
+ setHighlightedIndex(-1);
49266
+ };
49267
+ const showGhost = activeSuggestion && value.length > 0;
49268
+ return /*#__PURE__*/React$1.createElement(AutocompleteWrapper, null, /*#__PURE__*/React$1.createElement(MeasureSpan, {
49269
+ ref: measureRef
49270
+ }, value), /*#__PURE__*/React$1.createElement(NegotiatedTextarea, {
49271
+ value: value,
49272
+ onChange: handleChange,
49273
+ onKeyDown: handleKeyDown,
49274
+ onFocus: handleFocus,
49275
+ onBlur: handleBlur,
49276
+ placeholder: placeholder,
49277
+ maxLength: maxLength,
49278
+ required: true
49279
+ }), showGhost && /*#__PURE__*/React$1.createElement(GhostSuggestion, {
49280
+ style: {
49281
+ top: 17,
49282
+ left: 17 + textWidth
49283
+ }
49284
+ }, suggestionRemainder), showDropdown && matchingSuggestions.length > 0 && /*#__PURE__*/React$1.createElement(SuggestionDropdown, {
49285
+ ref: dropdownRef
49286
+ }, matchingSuggestions.map((suggestion, index) => /*#__PURE__*/React$1.createElement(SuggestionItem, {
49287
+ key: suggestion.value,
49288
+ $highlighted: index === highlightedIndex,
49289
+ onMouseDown: e => handleSuggestionMouseDown(e, suggestion)
49290
+ }, suggestion.value))));
49291
+ };
49292
+
49081
49293
  const NewSubitem = ({
49082
49294
  packageObject,
49083
49295
  vendor,
@@ -49085,13 +49297,16 @@ const NewSubitem = ({
49085
49297
  addNewPackage,
49086
49298
  updateExistingPackage,
49087
49299
  componentText = "Scale",
49088
- itemAndPackage
49300
+ itemAndPackage,
49301
+ brandSuggestions = [],
49302
+ onBrandSaved
49089
49303
  }) => {
49090
49304
  const [negotiatedBrands, setNegotiatedBrands] = useState("");
49091
49305
  const [negotiatedComponent, setNegotiatedComponent] = useState(componentText);
49092
49306
  const [isPackageDuplicated, setIsPackageDuplicated] = useState(false);
49093
49307
  // Form state
49094
49308
  const [isApplyEnabled, setIsApplyEnabled] = useState(negotiatedBrands.trim().length > 2);
49309
+ const vendorSuggestions = useMemo(() => brandSuggestions.filter(s => s.vendor === vendor.name), [brandSuggestions, vendor.name]);
49095
49310
  useEffect(() => {
49096
49311
  if (!packageObject) return;
49097
49312
  if (!packageObject.brands) return;
@@ -49100,8 +49315,10 @@ const NewSubitem = ({
49100
49315
  }, [packageObject]);
49101
49316
  useEffect(() => {
49102
49317
  if (packageObject && packageObject.brands === negotiatedBrands) return;
49103
- setIsPackageDuplicated(itemAndPackage.some(obj => obj.name === vendor.name && obj.packages?.some(pkg => pkg.brands === negotiatedBrands)));
49104
- setIsApplyEnabled(negotiatedBrands.trim().length > 2 && !itemAndPackage.some(obj => obj.name === vendor.name && obj.packages?.some(pkg => pkg.brands === negotiatedBrands)));
49318
+ const normalizedInput = negotiatedBrands.trim().toLowerCase();
49319
+ const isDuplicate = itemAndPackage.some(obj => obj.packages?.some(pkg => pkg.brands?.trim().toLowerCase() === normalizedInput));
49320
+ setIsPackageDuplicated(isDuplicate);
49321
+ setIsApplyEnabled(negotiatedBrands.trim().length > 2 && !isDuplicate);
49105
49322
  }, [negotiatedBrands]);
49106
49323
  return /*#__PURE__*/React$1.createElement(NewSubitemContainer, null, /*#__PURE__*/React$1.createElement(Header, null, /*#__PURE__*/React$1.createElement(BackButton, {
49107
49324
  onClick: onBack
@@ -49125,6 +49342,9 @@ const NewSubitem = ({
49125
49342
  } else {
49126
49343
  addNewPackage(vendor.name, negotiatedBrands, negotiatedComponent);
49127
49344
  }
49345
+ if (onBrandSaved) {
49346
+ onBrandSaved(negotiatedBrands, vendor.name);
49347
+ }
49128
49348
  },
49129
49349
  rightIcon: "none",
49130
49350
  size: "small",
@@ -49140,12 +49360,14 @@ const NewSubitem = ({
49140
49360
  style: {
49141
49361
  color: "red"
49142
49362
  }
49143
- }, "*")), /*#__PURE__*/React$1.createElement(NegotiatedTextarea, {
49363
+ }, "*")), /*#__PURE__*/React$1.createElement(BrandAutocomplete, {
49144
49364
  value: negotiatedBrands,
49145
- onChange: e => setNegotiatedBrands(e.target.value),
49146
- required: true,
49147
- placeholder: "Specify by text the participated brands, divided by commas"
49148
- }), isPackageDuplicated ? /*#__PURE__*/React$1.createElement(ErrorLabel, null, "Package already exists for that vendor, Please enter a unique package.") : /*#__PURE__*/React$1.createElement(ErrorLabel, null)), /*#__PURE__*/React$1.createElement(NegotiatedContainer, null, /*#__PURE__*/React$1.createElement(AddNegotiatedBrand, null, "Component ", /*#__PURE__*/React$1.createElement("span", {
49365
+ onChange: val => setNegotiatedBrands(val),
49366
+ suggestions: vendorSuggestions,
49367
+ placeholder: "Specify by text the participated brands, divided by commas",
49368
+ maxLength: 200,
49369
+ hasError: isPackageDuplicated
49370
+ }), isPackageDuplicated ? /*#__PURE__*/React$1.createElement(ErrorLabel, null, "Package already exists in the event, Please enter a unique package") : /*#__PURE__*/React$1.createElement(ErrorLabel, null)), /*#__PURE__*/React$1.createElement(NegotiatedContainer, null, /*#__PURE__*/React$1.createElement(AddNegotiatedBrand, null, "Component ", /*#__PURE__*/React$1.createElement("span", {
49149
49371
  style: {
49150
49372
  color: "red"
49151
49373
  }
@@ -57834,7 +58056,9 @@ const ItemManagerPanel = _ref => {
57834
58056
  onLastRowsReached = () => {},
57835
58057
  lastRowsThreshold = 3,
57836
58058
  onBackFromList = null,
57837
- onPackageAdded = null
58059
+ onPackageAdded = null,
58060
+ brandSuggestions = [],
58061
+ onBrandSaved = null
57838
58062
  } = _ref;
57839
58063
  const [screen, setScreen] = useState("initial");
57840
58064
  const [selectedVendor, setSelectedVendor] = useState(null);
@@ -57846,6 +58070,7 @@ const ItemManagerPanel = _ref => {
57846
58070
  const scrollWrapperRef = useRef(null);
57847
58071
  const headerRef = useRef(null);
57848
58072
  useEffect(() => {
58073
+ console.log("brandSuggestions", brandSuggestions);
57849
58074
  if (headerRef.current) {
57850
58075
  setHeaderHeight(headerRef.current.offsetHeight);
57851
58076
  }
@@ -58049,7 +58274,9 @@ const ItemManagerPanel = _ref => {
58049
58274
  updateExistingPackage: updateExistingPackage,
58050
58275
  isEditingExisting: isEditingExisting,
58051
58276
  onBack: () => setScreen("subitem"),
58052
- componentText: componentText
58277
+ componentText: componentText,
58278
+ brandSuggestions: brandSuggestions,
58279
+ onBrandSaved: onBrandSaved
58053
58280
  }));
58054
58281
  }
58055
58282
  if (screen === "list") {