@7shifts/sous-chef 4.11.0 → 4.12.0
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/forms/AsyncSelectField/AsyncSelectField.d.ts +4 -3
- package/dist/forms/AsyncSelectField/CustomList/CustomList.d.ts +2 -1
- package/dist/forms/AsyncSelectField/types.d.ts +1 -0
- package/dist/index.js +143 -64
- package/dist/index.js.map +1 -1
- package/dist/index.modern.js +124 -54
- package/dist/index.modern.js.map +1 -1
- package/llms-instructions/guidelines/AsyncSelectField.guidelines.md +86 -11
- package/llms-instructions/llms-components.md +1 -1
- package/llms-instructions/llms-tokens.md +1 -0
- package/package.json +1 -1
package/dist/index.modern.js
CHANGED
|
@@ -16,7 +16,6 @@ import originalStylers from 'react-day-picker/dist/style.module.css';
|
|
|
16
16
|
import 'react-toastify/dist/ReactToastify.css';
|
|
17
17
|
import { isSupportedCountry, parsePhoneNumber, AsYouType, getCountryCallingCode, isValidPhoneNumber as isValidPhoneNumber$1 } from 'libphonenumber-js';
|
|
18
18
|
import Select, { components } from 'react-select';
|
|
19
|
-
import AsyncSelect from 'react-select/async';
|
|
20
19
|
import { startOfDay as startOfDay$1, isDate } from 'date-fns';
|
|
21
20
|
import getDay from 'date-fns/getDay';
|
|
22
21
|
import getDate from 'date-fns/getDate';
|
|
@@ -17622,12 +17621,13 @@ const MultiSelectField = ({
|
|
|
17622
17621
|
|
|
17623
17622
|
var styles$r = {"custom-list":"_cSkvD"};
|
|
17624
17623
|
|
|
17625
|
-
const _excluded$b4 = ["children", "hasMoreOptions", "hasMoreOptionsFirstLoad"];
|
|
17624
|
+
const _excluded$b4 = ["children", "hasMoreOptions", "hasMoreOptionsFirstLoad", "isLoadingMore"];
|
|
17626
17625
|
const CustomList = _ref => {
|
|
17627
17626
|
let {
|
|
17628
17627
|
children,
|
|
17629
17628
|
hasMoreOptions,
|
|
17630
|
-
hasMoreOptionsFirstLoad
|
|
17629
|
+
hasMoreOptionsFirstLoad,
|
|
17630
|
+
isLoadingMore
|
|
17631
17631
|
} = _ref,
|
|
17632
17632
|
props = _objectWithoutPropertiesLoose(_ref, _excluded$b4);
|
|
17633
17633
|
const __ = useTranslation('AsyncSelectField');
|
|
@@ -17635,7 +17635,11 @@ const CustomList = _ref => {
|
|
|
17635
17635
|
if (props.selectProps.inputValue === '' && typeof hasMoreOptionsFirstLoad === 'boolean') {
|
|
17636
17636
|
showFooter = hasMoreOptionsFirstLoad;
|
|
17637
17637
|
}
|
|
17638
|
-
return React__default.createElement(components.MenuList, _extends({}, props), React__default.createElement(Fragment, null, children,
|
|
17638
|
+
return React__default.createElement(components.MenuList, _extends({}, props), React__default.createElement(Fragment, null, children, isLoadingMore ? React__default.createElement(Inline, {
|
|
17639
|
+
justifyContent: "center"
|
|
17640
|
+
}, React__default.createElement(Spinner, {
|
|
17641
|
+
size: 20
|
|
17642
|
+
})) : showFooter && props.options.length > 0 && React__default.createElement(Inline, {
|
|
17639
17643
|
justifyContent: "center"
|
|
17640
17644
|
}, React__default.createElement("div", {
|
|
17641
17645
|
className: styles$r['custom-list']
|
|
@@ -17643,54 +17647,105 @@ const CustomList = _ref => {
|
|
|
17643
17647
|
};
|
|
17644
17648
|
|
|
17645
17649
|
const _excluded$b3 = ["loadOptions"];
|
|
17650
|
+
const MenuListContext = React__default.createContext({
|
|
17651
|
+
hasMoreOptions: false,
|
|
17652
|
+
hasMoreOptionsFirstLoad: null,
|
|
17653
|
+
isLoadingMore: false
|
|
17654
|
+
});
|
|
17655
|
+
// Defined outside the component so the reference is stable — prevents MenuList from
|
|
17656
|
+
// unmounting/remounting (and losing scroll position) on every state change.
|
|
17657
|
+
const AsyncMenuList = menuListProps => {
|
|
17658
|
+
const ctx = React__default.useContext(MenuListContext);
|
|
17659
|
+
return React__default.createElement(CustomList, _extends({}, menuListProps, ctx));
|
|
17660
|
+
};
|
|
17646
17661
|
/**
|
|
17647
17662
|
* A variation of select field that loads a dynamic list of options from a source rather than a fixed set of options. Use when you need to select from a dynamic list that can change such as roles, employees, locations, etc.
|
|
17648
|
-
* Instead of passing
|
|
17663
|
+
* Instead of passing an `options` prop, this component requires a `loadOptions` prop.
|
|
17664
|
+
* Supports scroll-to-load-more: when the user scrolls to the bottom of the menu and a `nextCursor` is returned, the next page is automatically fetched and appended.
|
|
17649
17665
|
* */
|
|
17650
17666
|
const AsyncSelectField = _ref => {
|
|
17651
17667
|
let {
|
|
17652
17668
|
loadOptions
|
|
17653
17669
|
} = _ref,
|
|
17654
17670
|
props = _objectWithoutPropertiesLoose(_ref, _excluded$b3);
|
|
17655
|
-
const [
|
|
17656
|
-
const [
|
|
17657
|
-
const [
|
|
17671
|
+
const [displayedOptions, setDisplayedOptions] = useState([]);
|
|
17672
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
17673
|
+
const [isLoadingMore, setIsLoadingMore] = useState(false);
|
|
17674
|
+
const [inputValue, setInputValue] = useState('');
|
|
17675
|
+
const [hasMore, setHasMore] = useState(false);
|
|
17676
|
+
const [nextCursor, setNextCursor] = useState(null);
|
|
17658
17677
|
const [localOptions, setLocalOptions] = useState(null);
|
|
17659
|
-
const
|
|
17660
|
-
const
|
|
17661
|
-
|
|
17662
|
-
|
|
17663
|
-
|
|
17664
|
-
|
|
17665
|
-
|
|
17666
|
-
|
|
17667
|
-
const
|
|
17668
|
-
|
|
17669
|
-
|
|
17670
|
-
|
|
17678
|
+
const [hasMoreOptionsFirstLoad, setHasMoreOptionsFirstLoad] = useState(null);
|
|
17679
|
+
const loadOptionsRef = useRef(loadOptions);
|
|
17680
|
+
useEffect(() => {
|
|
17681
|
+
loadOptionsRef.current = loadOptions;
|
|
17682
|
+
}, [loadOptions]);
|
|
17683
|
+
const fetchIdRef = useRef(0);
|
|
17684
|
+
const firstLoadDoneRef = useRef(false);
|
|
17685
|
+
// All dependencies are refs and stable state setters — safe with empty dep array.
|
|
17686
|
+
const fetchOptions = useCallback(input => {
|
|
17687
|
+
const id = ++fetchIdRef.current;
|
|
17688
|
+
setIsLoading(true);
|
|
17689
|
+
loadOptionsRef.current(input, null).then(({
|
|
17690
|
+
options,
|
|
17691
|
+
hasMore: more,
|
|
17692
|
+
nextCursor: resultCursor
|
|
17693
|
+
}) => {
|
|
17694
|
+
if (id !== fetchIdRef.current) return;
|
|
17695
|
+
if (!firstLoadDoneRef.current) {
|
|
17696
|
+
firstLoadDoneRef.current = true;
|
|
17697
|
+
setHasMoreOptionsFirstLoad(more && resultCursor == null);
|
|
17698
|
+
if (!more) setLocalOptions(options);
|
|
17699
|
+
}
|
|
17700
|
+
setDisplayedOptions(options);
|
|
17701
|
+
setHasMore(more);
|
|
17702
|
+
setNextCursor(resultCursor != null ? resultCursor : null);
|
|
17703
|
+
setIsLoading(false);
|
|
17704
|
+
}).catch(() => {
|
|
17705
|
+
if (id !== fetchIdRef.current) return;
|
|
17706
|
+
setIsLoading(false);
|
|
17707
|
+
});
|
|
17708
|
+
},
|
|
17709
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
17710
|
+
[]);
|
|
17711
|
+
const debouncedFetchOptions = useMemo(() => debounce(fetchOptions, 500, {
|
|
17712
|
+
leading: true
|
|
17713
|
+
}), [fetchOptions]);
|
|
17714
|
+
useEffect(() => {
|
|
17715
|
+
fetchOptions('');
|
|
17716
|
+
}, [fetchOptions]);
|
|
17717
|
+
const handleSearch = value => {
|
|
17718
|
+
++fetchIdRef.current;
|
|
17719
|
+
setIsLoadingMore(false);
|
|
17671
17720
|
if (localOptions) {
|
|
17672
|
-
|
|
17721
|
+
const filtered = localOptions.filter(option => option.label.toLowerCase().includes(value.toLowerCase()));
|
|
17722
|
+
setDisplayedOptions(filtered);
|
|
17673
17723
|
return;
|
|
17674
17724
|
}
|
|
17675
|
-
|
|
17676
|
-
|
|
17677
|
-
|
|
17725
|
+
setDisplayedOptions([]);
|
|
17726
|
+
setHasMore(false);
|
|
17727
|
+
setNextCursor(null);
|
|
17728
|
+
setIsLoading(true);
|
|
17729
|
+
debouncedFetchOptions(value);
|
|
17730
|
+
};
|
|
17731
|
+
const handleScrollToBottom = () => {
|
|
17732
|
+
if (isLoadingMore || !hasMore || !nextCursor) return;
|
|
17733
|
+
// Capture the search generation so a concurrent query change can invalidate this response.
|
|
17734
|
+
const id = fetchIdRef.current;
|
|
17735
|
+
setIsLoadingMore(true);
|
|
17736
|
+
loadOptionsRef.current(inputValue, nextCursor).then(({
|
|
17737
|
+
options,
|
|
17738
|
+
hasMore: more,
|
|
17739
|
+
nextCursor: resultCursor
|
|
17678
17740
|
}) => {
|
|
17679
|
-
|
|
17680
|
-
|
|
17681
|
-
|
|
17682
|
-
|
|
17683
|
-
|
|
17684
|
-
|
|
17685
|
-
|
|
17686
|
-
|
|
17687
|
-
}
|
|
17688
|
-
}
|
|
17689
|
-
setHasMoreOptions(hasMore);
|
|
17690
|
-
if (hasMoreOptionsFirstLoad === undefined) {
|
|
17691
|
-
setHasMoreOptionsFirstLoad(hasMore);
|
|
17692
|
-
}
|
|
17693
|
-
callback(options);
|
|
17741
|
+
if (id !== fetchIdRef.current) return;
|
|
17742
|
+
setDisplayedOptions(prev => [...prev, ...options]);
|
|
17743
|
+
setHasMore(more);
|
|
17744
|
+
setNextCursor(resultCursor != null ? resultCursor : null);
|
|
17745
|
+
setIsLoadingMore(false);
|
|
17746
|
+
}).catch(() => {
|
|
17747
|
+
if (id !== fetchIdRef.current) return;
|
|
17748
|
+
setIsLoadingMore(false);
|
|
17694
17749
|
});
|
|
17695
17750
|
};
|
|
17696
17751
|
const {
|
|
@@ -17699,22 +17754,37 @@ const AsyncSelectField = _ref => {
|
|
|
17699
17754
|
} = useSelectField(_extends({}, props, {
|
|
17700
17755
|
options: []
|
|
17701
17756
|
}));
|
|
17702
|
-
|
|
17757
|
+
const menuListComponents = useMemo(() => _extends({}, selectProps.components, {
|
|
17758
|
+
MenuList: AsyncMenuList
|
|
17759
|
+
}),
|
|
17760
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
17761
|
+
[selectProps.components]);
|
|
17762
|
+
return React__default.createElement(MenuListContext.Provider, {
|
|
17763
|
+
value: {
|
|
17764
|
+
hasMoreOptions: hasMore && nextCursor === null,
|
|
17765
|
+
hasMoreOptionsFirstLoad,
|
|
17766
|
+
isLoadingMore
|
|
17767
|
+
}
|
|
17768
|
+
}, React__default.createElement(Field, _extends({}, fieldProps), React__default.createElement(AffixContainer, {
|
|
17703
17769
|
prefix: props.prefix
|
|
17704
|
-
}, React__default.createElement(
|
|
17705
|
-
components:
|
|
17706
|
-
|
|
17707
|
-
|
|
17708
|
-
|
|
17709
|
-
|
|
17710
|
-
|
|
17711
|
-
|
|
17712
|
-
|
|
17713
|
-
|
|
17714
|
-
|
|
17715
|
-
|
|
17716
|
-
|
|
17717
|
-
|
|
17770
|
+
}, React__default.createElement(Select, _extends({}, selectProps, {
|
|
17771
|
+
components: menuListComponents,
|
|
17772
|
+
options: displayedOptions,
|
|
17773
|
+
isLoading: isLoading,
|
|
17774
|
+
inputValue: inputValue,
|
|
17775
|
+
onInputChange: (value, {
|
|
17776
|
+
action
|
|
17777
|
+
}) => {
|
|
17778
|
+
if (action !== 'input-blur' && action !== 'menu-close') {
|
|
17779
|
+
setInputValue(value);
|
|
17780
|
+
}
|
|
17781
|
+
if (action === 'input-change') {
|
|
17782
|
+
handleSearch(value);
|
|
17783
|
+
}
|
|
17784
|
+
},
|
|
17785
|
+
onMenuScrollToBottom: handleScrollToBottom,
|
|
17786
|
+
filterOption: null
|
|
17787
|
+
})))));
|
|
17718
17788
|
};
|
|
17719
17789
|
|
|
17720
17790
|
const useDateFieldControllers = ({
|