@maxio-com/react-ui-components 9.26.0 → 9.27.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.
@@ -91,6 +91,37 @@ const [account, setAccount] = React.useState('acme');
91
91
  </ComboBox>
92
92
  ```
93
93
 
94
+ ## Async Loading
95
+
96
+ Pass fetched options through `items` and set `isLoading` while fetching initial
97
+ results, searching, or loading another page. ComboBox uses ListBox's loading
98
+ spinner and calls `onLoadMore` when the user scrolls near the bottom. Use
99
+ `scrollOffset` to adjust how early the next page loads (default: one scroll-area
100
+ height). Omit `onLoadMore` when no pages remain, or use a callback such as
101
+ `useAsyncList`'s `loadMore`, which stops at the end.
102
+
103
+ For async search, connect `inputValue` and `onInputChange` to your query state and
104
+ pass the matching results through `items`. Unlike `defaultItems`, `items` are not
105
+ filtered locally. The **Async Loading** story demonstrates this with `useAsyncList`.
106
+
107
+ ```tsx
108
+ <ComboBox
109
+ label="Account"
110
+ items={list.items}
111
+ inputValue={list.filterText}
112
+ onInputChange={list.setFilterText}
113
+ isLoading={list.isLoading}
114
+ onLoadMore={list.loadMore}
115
+ renderEmptyState={() => 'No accounts found.'}
116
+ >
117
+ {(account) => <ComboBox.Item id={account.id}>{account.name}</ComboBox.Item>}
118
+ </ComboBox>
119
+ ```
120
+
121
+ The popup can open with no options while `isLoading`, `onLoadMore`, or
122
+ `renderEmptyState` is provided. Set `allowsEmptyCollection` explicitly to override
123
+ this behavior. The empty state appears only when loading has finished.
124
+
94
125
  ## Imports
95
126
 
96
127
  ```tsx
@@ -131,6 +162,54 @@ const DynamicItems = (args) => (
131
162
  );
132
163
  ```
133
164
 
165
+ ### Async Loading
166
+
167
+ Search asynchronously and load additional options as users scroll. This example
168
+ simulates an API with 60 accounts and 20 results per page.
169
+
170
+ ```tsx
171
+ const AsyncLoading = () => {
172
+ const list = useAsyncList<Account>({
173
+ async load({ cursor, filterText }) {
174
+ await new Promise((resolve) => setTimeout(resolve, 1000));
175
+
176
+ const matchingAccounts = Array.from({ length: 60 }, (_, index) => ({
177
+ id: String(index + 1),
178
+ name: `Account ${index + 1}`,
179
+ })).filter((account) =>
180
+ account.name.toLowerCase().includes(filterText.toLowerCase())
181
+ );
182
+ const start = Number(cursor ?? 0);
183
+ const end = start + 20;
184
+
185
+ return {
186
+ items: matchingAccounts.slice(start, end),
187
+ cursor: end < matchingAccounts.length ? String(end) : undefined,
188
+ };
189
+ },
190
+ });
191
+
192
+ return (
193
+ <ComboBox<Account>
194
+ label="Account"
195
+ placeholder="Search accounts"
196
+ menuTrigger="focus"
197
+ items={list.items}
198
+ inputValue={list.filterText}
199
+ onInputChange={list.setFilterText}
200
+ isLoading={list.isLoading}
201
+ onLoadMore={list.loadMore}
202
+ renderEmptyState={() => 'No accounts found.'}
203
+ onChange={action('onChange')}
204
+ >
205
+ {(account) => (
206
+ <ComboBox.Item id={account.id}>{account.name}</ComboBox.Item>
207
+ )}
208
+ </ComboBox>
209
+ );
210
+ };
211
+ ```
212
+
134
213
  ### With Sections
135
214
 
136
215
  Use sections when the option set mixes statuses, categories, or other groups
@@ -1 +1 @@
1
- {"version":3,"file":"ComboBox.d.ts","sourceRoot":"","sources":["../../../../../../src/components/forms/ComboBox/ComboBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAGxC,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AA4LpE,KAAK,iBAAiB,GAAG,CAAC,CACxB,CAAC,SAAS,MAAM,GAAG,MAAM,EACzB,CAAC,SAAS,qBAAqB,GAAG,QAAQ,EAE1C,KAAK,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,KACvB,KAAK,CAAC,YAAY,CAAC,GAAG;IACzB,IAAI,EAAE,OAAO,OAAO,CAAC,IAAI,CAAC;IAC1B,OAAO,EAAE,OAAO,OAAO,CAAC,OAAO,CAAC;IAChC,MAAM,EAAE,OAAO,OAAO,CAAC,MAAM,CAAC;CAC/B,CAAC;AAEF,QAAA,MAAM,QAAQ,EAIR,iBAAiB,CAAC;AAExB,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"ComboBox.d.ts","sourceRoot":"","sources":["../../../../../../src/components/forms/ComboBox/ComboBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAGxC,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAyMpE,KAAK,iBAAiB,GAAG,CAAC,CACxB,CAAC,SAAS,MAAM,GAAG,MAAM,EACzB,CAAC,SAAS,qBAAqB,GAAG,QAAQ,EAE1C,KAAK,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,KACvB,KAAK,CAAC,YAAY,CAAC,GAAG;IACzB,IAAI,EAAE,OAAO,OAAO,CAAC,IAAI,CAAC;IAC1B,OAAO,EAAE,OAAO,OAAO,CAAC,OAAO,CAAC;IAChC,MAAM,EAAE,OAAO,OAAO,CAAC,MAAM,CAAC;CAC/B,CAAC;AAEF,QAAA,MAAM,QAAQ,EAIR,iBAAiB,CAAC;AAExB,eAAe,QAAQ,CAAC"}
@@ -12,6 +12,9 @@ export interface ComboBoxProps<T extends object = object, M extends ComboBoxSele
12
12
  leadingElement?: ReactNode;
13
13
  children: ReactNode | ((item: T) => ReactNode);
14
14
  renderEmptyState?: ListBoxProps<T>['renderEmptyState'];
15
+ isLoading?: ListBoxProps<T>['isLoading'];
16
+ onLoadMore?: ListBoxProps<T>['onLoadMore'];
17
+ scrollOffset?: ListBoxProps<T>['scrollOffset'];
15
18
  className?: string;
16
19
  }
17
20
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/components/forms/ComboBox/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EACV,aAAa,IAAI,iBAAiB,EAClC,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE1D,MAAM,WAAW,aAAa,CAC5B,CAAC,SAAS,MAAM,GAAG,MAAM,EACzB,CAAC,SAAS,qBAAqB,GAAG,QAAQ,CAC1C,SAAQ,IAAI,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;IAI/D,KAAK,CAAC,EAAE,MAAM,CAAC;IAIf,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAIjC,SAAS,CAAC,EAAE,OAAO,CAAC;IAIpB,WAAW,CAAC,EAAE,MAAM,CAAC;IAIrB,YAAY,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,UAAU,EAAE,gBAAgB,KAAK,MAAM,CAAC,CAAC;IAInE,WAAW,CAAC,EAAE,MAAM,CAAC;IAIrB,cAAc,CAAC,EAAE,SAAS,CAAC;IAI3B,QAAQ,EAAE,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC,CAAC;IAI/C,gBAAgB,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAIvD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/components/forms/ComboBox/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EACV,aAAa,IAAI,iBAAiB,EAClC,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE1D,MAAM,WAAW,aAAa,CAC5B,CAAC,SAAS,MAAM,GAAG,MAAM,EACzB,CAAC,SAAS,qBAAqB,GAAG,QAAQ,CAC1C,SAAQ,IAAI,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;IAI/D,KAAK,CAAC,EAAE,MAAM,CAAC;IAIf,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAIjC,SAAS,CAAC,EAAE,OAAO,CAAC;IAIpB,WAAW,CAAC,EAAE,MAAM,CAAC;IAIrB,YAAY,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,UAAU,EAAE,gBAAgB,KAAK,MAAM,CAAC,CAAC;IAInE,WAAW,CAAC,EAAE,MAAM,CAAC;IAIrB,cAAc,CAAC,EAAE,SAAS,CAAC;IAI3B,QAAQ,EAAE,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC,CAAC;IAI/C,gBAAgB,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAEvD,SAAS,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAEzC,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IAE3C,YAAY,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;IAI/C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maxio-com/react-ui-components",
3
- "version": "9.26.0",
3
+ "version": "9.27.0",
4
4
  "description": "React UI components",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -65,5 +65,5 @@
65
65
  "publishConfig": {
66
66
  "access": "public"
67
67
  },
68
- "gitHead": "d142e871d70bc9f58d2e35904ebef8b00ac307be"
68
+ "gitHead": "7195ec2e6d3a2162254662d25aa7ff0a56a8d211"
69
69
  }
@@ -735,6 +735,9 @@ interface ComboBoxProps<T extends object = object, M extends ComboBoxSelectionMo
735
735
  leadingElement?: ReactNode;
736
736
  children: ReactNode | ((item: T) => ReactNode);
737
737
  renderEmptyState?: ListBoxProps<T>['renderEmptyState'];
738
+ isLoading?: ListBoxProps<T>['isLoading'];
739
+ onLoadMore?: ListBoxProps<T>['onLoadMore'];
740
+ scrollOffset?: ListBoxProps<T>['scrollOffset'];
738
741
  className?: string;
739
742
  }
740
743