@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
|
@@ -1,20 +1,95 @@
|
|
|
1
|
+
<!-- AUTO-GENERATED by scripts/build-llms-guidelines.js. Do not edit manually. Run `yarn build-llms-guidelines` to regenerate. -->
|
|
2
|
+
|
|
1
3
|
## When to Use
|
|
2
4
|
|
|
3
|
-
- When
|
|
4
|
-
- When
|
|
5
|
-
- When the
|
|
5
|
+
- When options come from an API and the full list is too large to load at once (employees, locations, roles, etc.).
|
|
6
|
+
- When results should be narrowed by what the user types — search-as-you-type against a backend.
|
|
7
|
+
- When the option list is dynamic — it changes based on server state or another field's value.
|
|
6
8
|
|
|
7
9
|
## When Not to Use
|
|
8
10
|
|
|
9
|
-
- When the list
|
|
10
|
-
- When
|
|
11
|
-
- When the
|
|
12
|
-
- When the user needs to enter free-form text — use `TextField` instead
|
|
11
|
+
- When the option list is small and static — use `SelectField` instead; it takes a plain `options` array and has no loading overhead.
|
|
12
|
+
- When options are already available in memory — pass them directly to `SelectField` or filter them client-side.
|
|
13
|
+
- When the user needs to pick from a fixed set of weekdays — use `WeekSelectField`.
|
|
13
14
|
|
|
14
15
|
## Usage
|
|
15
16
|
|
|
16
|
-
###
|
|
17
|
+
### The `loadOptions` Callback
|
|
18
|
+
|
|
19
|
+
`loadOptions` is the only required prop unique to this component. It receives two arguments and must return a Promise:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
loadOptions: (
|
|
23
|
+
inputValue: string, // current search text (empty string on initial load)
|
|
24
|
+
cursor?: string | null // pagination cursor, null on the first call
|
|
25
|
+
) =>
|
|
26
|
+
Promise<{
|
|
27
|
+
options: SelectOption<T>[]; // the page of options to display
|
|
28
|
+
hasMore: boolean; // whether more pages exist
|
|
29
|
+
nextCursor?: string | null; // opaque cursor for the next page (omit or null if none)
|
|
30
|
+
}>;
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The component calls `loadOptions('', null)` automatically on mount to populate the initial list. There is no need to trigger a manual fetch.
|
|
34
|
+
|
|
35
|
+
### Pagination and Scroll-to-Load-More
|
|
36
|
+
|
|
37
|
+
When a `nextCursor` is returned, a spinner appears at the bottom of the menu as the user scrolls down. When the user reaches the bottom, the next page is fetched using that cursor and its options are **appended** to the current list — the previous options are not replaced.
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
// Page 1 response — signals more pages exist
|
|
41
|
+
{ options: firstPageOptions, hasMore: true, nextCursor: '20' }
|
|
42
|
+
|
|
43
|
+
// Page 2 response — called with cursor='20', no further pages
|
|
44
|
+
{ options: secondPageOptions, hasMore: false }
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
If `nextCursor` is omitted or `null`, or if `hasMore` is `false`, no further fetches are triggered on scroll. Omitting `nextCursor` entirely is the same as returning `null` — the component treats both as "no next page".
|
|
48
|
+
|
|
49
|
+
### Search Behavior
|
|
50
|
+
|
|
51
|
+
When the user types, `loadOptions` is called with the current input text and `null` as the cursor — pagination always resets to the first page on a new search. Accumulated options from previous scroll-loads are discarded and replaced with the fresh results.
|
|
52
|
+
|
|
53
|
+
**Client-side search optimisation:** If the very first `loadOptions` call returns `hasMore: false`, the component caches the full option list and all subsequent searches are filtered client-side — no further network calls are made regardless of what the user types. This makes single-page datasets feel instant without any extra code on the caller's side.
|
|
54
|
+
|
|
55
|
+
### Dependent Fields
|
|
56
|
+
|
|
57
|
+
Use the `key` prop to force a full reload whenever an external value changes — for example when a Location field controls which employees are shown:
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
<AsyncSelectField
|
|
61
|
+
loadOptions={(inputValue, cursor) =>
|
|
62
|
+
fetchEmployees(inputValue, cursor, location.value)
|
|
63
|
+
}
|
|
64
|
+
name="employee"
|
|
65
|
+
label="Employee"
|
|
66
|
+
key={location.value} // remounts (and re-fetches) when location changes
|
|
67
|
+
/>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
When `key` changes, React unmounts and remounts the component, which resets all accumulated options, the cursor, and the search input.
|
|
71
|
+
|
|
72
|
+
### Label, Caption, and Error
|
|
73
|
+
|
|
74
|
+
Always provide a `label` — it identifies the field and is linked to the input for screen readers. Use `caption` for supplementary guidance such as what the user should search for. Use `error` to surface validation messages; the field is marked as invalid for screen readers when an error is present.
|
|
75
|
+
|
|
76
|
+
### No Options and Loading States
|
|
77
|
+
|
|
78
|
+
The component handles loading and empty states automatically. A "Loading..." indicator appears while options are being fetched on initial load or after typing. When `loadOptions` resolves with an empty array and `hasMore: false`, react-select's default "No options" message is shown — this can be customised via the `noOptionsMessage` prop.
|
|
79
|
+
|
|
80
|
+
## Tips & Tricks
|
|
81
|
+
|
|
82
|
+
- If your API doesn't paginate, simply return `hasMore: false` and omit `nextCursor` — the scroll-load-more behaviour is disabled and the component behaves like a plain async select.
|
|
83
|
+
- The `cursor` parameter passed to `loadOptions` is whatever string you returned as `nextCursor` on the previous call. It is opaque to the component — you can use an offset, a page number, a keyset value, or any server-issued token. The component never inspects or modifies it.
|
|
84
|
+
- Debouncing is built in (500 ms, leading edge). There is no need to debounce `loadOptions` at the call site.
|
|
85
|
+
- Avoid returning `hasMore: true` without a `nextCursor`. The component uses the cursor to guard against duplicate fetches — if `hasMore` is `true` but `nextCursor` is `null`, scroll-to-load-more is silently disabled for that page.
|
|
86
|
+
- The `key` pattern is more reliable than updating `loadOptions` in a `useEffect`. React's remount guarantee means state is always fully reset, whereas updating the callback while keeping the component mounted may not clear accumulated options.
|
|
87
|
+
|
|
88
|
+
## Additional Rules
|
|
17
89
|
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
90
|
+
- `loadOptions` and `name` are required. All other props are inherited from `SelectField` (`label`, `onChange`, `value`, `caption`, `error`, `prefix`, etc.).
|
|
91
|
+
- `loadOptions` is called with `('', null)` on mount — the initial call always receives an empty string and a null cursor.
|
|
92
|
+
- The `cursor` argument is `string | null` — always `null` on the first call per search query, and the opaque `nextCursor` string on subsequent scroll-load calls.
|
|
93
|
+
- `nextCursor` in the response is optional and typed as `string | null`. Returning `undefined`, `null`, or omitting the field are all treated identically — no next page.
|
|
94
|
+
- `hasMore: false` stops all further scroll-triggered fetches for the current search, even if a `nextCursor` was returned (it is discarded).
|
|
95
|
+
- `filterOption` is set to `null` internally — react-select's built-in client-side filtering is disabled because the component manages the option list directly. Do not pass a `filterOption` prop.
|
|
@@ -98,7 +98,7 @@ Form components are used to collect user input and data.
|
|
|
98
98
|
|
|
99
99
|
### AsyncSelectField
|
|
100
100
|
|
|
101
|
-
A
|
|
101
|
+
A select field that fetches its options from an async source — an API, a search endpoint, or any function that returns a Promise. Use it when the option list is too large to load upfront or when options change based on server-side data. Supports scroll-to-load-more pagination: when the user scrolls to the bottom of the open menu and more results exist, the next page is fetched and appended automatically.
|
|
102
102
|
|
|
103
103
|
### CheckboxField
|
|
104
104
|
|
|
@@ -413,6 +413,7 @@ Most of the time you won't need to use these tokens because it is baked into Sou
|
|
|
413
413
|
| ------------------- | ----- |
|
|
414
414
|
| --border-radius-300 | 4px |
|
|
415
415
|
| --border-radius-400 | 8px |
|
|
416
|
+
| --border-radius-500 | 12px |
|
|
416
417
|
| --border-radius-600 | 20px |
|
|
417
418
|
|
|
418
419
|
## Z-index
|