fluentui-extended 2026.8.30 → 2026.8.31

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/README.md CHANGED
@@ -293,6 +293,45 @@ Run the test harness with `npm run harness` to see all examples in action.
293
293
  | `disabled` | `boolean` | `false` | Disable the lookup |
294
294
  | `open` | `boolean` | - | Controlled open state for the dropdown |
295
295
  | `onOpenChange` | `(open: boolean) => void` | - | Callback when dropdown open state changes |
296
+ | `disableClientFilter` | `boolean` | `false` | Disable client-side filtering of options. Use this when filtering is performed server-side via `onSearchChange` |
297
+ | `searchFields` | `string` | - | Hidden searchable text (never rendered). Use this to include additional searchable content (codes, IDs) while displaying JSX in `secondaryText` |
298
+
299
+ ### Client-Side Filtering
300
+
301
+ By default, the Lookup component filters options client-side as the user types. The filtering logic works as follows:
302
+
303
+ 1. **Primary field (`text`)** — Always searched, regardless of other props
304
+ 2. **Search fields (`searchFields`)** — If provided, this hidden text is searched (useful when `secondaryText` is JSX)
305
+ 3. **Secondary text (`secondaryText`)** — Only searched if it's a string (JSX elements are skipped)
306
+
307
+ This allows you to use rich JSX (badges, icons) in `secondaryText` while still providing searchable text via `searchFields`:
308
+
309
+ ```tsx
310
+ const options: LookupOption[] = [
311
+ {
312
+ key: 'PROD-001',
313
+ text: 'Acme Widget', // Always searchable
314
+ searchFields: 'PROD-001 SKU-12345 acme-widget', // Hidden searchable text
315
+ secondaryText: ( // Rich display (not searchable)
316
+ <span style={{ display: 'flex', gap: 4 }}>
317
+ <Badge size="small">PROD-001</Badge>
318
+ <Badge size="small" color="brand">SKU-12345</Badge>
319
+ </span>
320
+ ),
321
+ },
322
+ ];
323
+ ```
324
+
325
+ **Server-Side Filtering:** When using `onSearchChange` to fetch results from an API, set `disableClientFilter={true}` to prevent the client from re-filtering server results:
326
+
327
+ ```tsx
328
+ <Lookup
329
+ options={apiResults}
330
+ onSearchChange={(searchText) => fetchFromApi(searchText)}
331
+ disableClientFilter={true} // API already filtered the results
332
+ loading={isLoading}
333
+ />
334
+ ```
296
335
 
297
336
  ### Cross-Document Support (Dynamics 365 Iframes)
298
337
 
@@ -327,6 +366,7 @@ interface LookupOption {
327
366
  key: string; // Unique identifier (required)
328
367
  text: string; // Display text (required)
329
368
  secondaryText?: ReactNode; // Secondary line - string, Badge, or JSX
369
+ searchFields?: string; // Hidden searchable text (never rendered)
330
370
  icon?: ReactNode; // Icon component (e.g., <BuildingRegular />)
331
371
  details?: LookupOptionDetail[]; // Expandable details (chevron appears)
332
372
  data?: unknown; // Custom data payload for your app
@@ -339,7 +379,7 @@ interface LookupOptionDetail {
339
379
  }
340
380
  ```
341
381
 
342
- > **Note:** Both `secondaryText` and `details` support React elements, not just strings. See [Rich Secondary Text](#rich-secondary-text-with-react-elements) for examples.
382
+ > **Note:** Both `secondaryText` and `details` support React elements, not just strings. See [Rich Secondary Text](#rich-secondary-text-with-react-elements) for examples. When using JSX in `secondaryText`, use `searchFields` to provide hidden searchable text (see [Client-Side Filtering](#client-side-filtering)).
343
383
 
344
384
  ## Keyboard Navigation
345
385
 
package/dist/index.d.mts CHANGED
@@ -14,6 +14,13 @@ interface LookupOption {
14
14
  text: string;
15
15
  /** Optional secondary text - can be a string or React element */
16
16
  secondaryText?: React.ReactNode;
17
+ /**
18
+ * Optional searchable text that is never rendered. Use this to include
19
+ * additional searchable content (codes, IDs, etc.) without affecting display.
20
+ * Client-side filtering will search this field in addition to `text` and
21
+ * string `secondaryText`.
22
+ */
23
+ searchFields?: string;
17
24
  /** Optional icon to display */
18
25
  icon?: React.ReactNode;
19
26
  /** Optional expandable details */
@@ -64,6 +71,12 @@ interface LookupProps extends Omit<InputProps, 'onChange' | 'value'> {
64
71
  * Use together with `open` for controlled mode, or standalone to observe changes.
65
72
  */
66
73
  onOpenChange?: (open: boolean) => void;
74
+ /**
75
+ * Disable client-side filtering of options. Use this when filtering is
76
+ * performed server-side via `onSearchChange` and the returned options are
77
+ * already filtered. Defaults to `false` (client-side filtering enabled).
78
+ */
79
+ disableClientFilter?: boolean;
67
80
  }
68
81
 
69
82
  declare const Lookup: React.FC<LookupProps>;
package/dist/index.d.ts CHANGED
@@ -14,6 +14,13 @@ interface LookupOption {
14
14
  text: string;
15
15
  /** Optional secondary text - can be a string or React element */
16
16
  secondaryText?: React.ReactNode;
17
+ /**
18
+ * Optional searchable text that is never rendered. Use this to include
19
+ * additional searchable content (codes, IDs, etc.) without affecting display.
20
+ * Client-side filtering will search this field in addition to `text` and
21
+ * string `secondaryText`.
22
+ */
23
+ searchFields?: string;
17
24
  /** Optional icon to display */
18
25
  icon?: React.ReactNode;
19
26
  /** Optional expandable details */
@@ -64,6 +71,12 @@ interface LookupProps extends Omit<InputProps, 'onChange' | 'value'> {
64
71
  * Use together with `open` for controlled mode, or standalone to observe changes.
65
72
  */
66
73
  onOpenChange?: (open: boolean) => void;
74
+ /**
75
+ * Disable client-side filtering of options. Use this when filtering is
76
+ * performed server-side via `onSearchChange` and the returned options are
77
+ * already filtered. Defaults to `false` (client-side filtering enabled).
78
+ */
79
+ disableClientFilter?: boolean;
67
80
  }
68
81
 
69
82
  declare const Lookup: React.FC<LookupProps>;
package/dist/index.js CHANGED
@@ -281,6 +281,7 @@ var Lookup = ({
281
281
  footer,
282
282
  open: controlledOpen,
283
283
  onOpenChange,
284
+ disableClientFilter = false,
284
285
  ...inputProps
285
286
  }) => {
286
287
  const styles = useLookupStyles();
@@ -316,6 +317,9 @@ var Lookup = ({
316
317
  [selectedOptionProp, options, selectedKey, internalSelectedOption]
317
318
  );
318
319
  const filteredOptions = React3__namespace.useMemo(() => {
320
+ if (disableClientFilter) {
321
+ return options;
322
+ }
319
323
  if (!searchText || searchText.length < minSearchLength) {
320
324
  return options;
321
325
  }
@@ -324,12 +328,15 @@ var Lookup = ({
324
328
  if (opt.text.toLowerCase().includes(lowerSearch)) {
325
329
  return true;
326
330
  }
331
+ if (opt.searchFields && opt.searchFields.toLowerCase().includes(lowerSearch)) {
332
+ return true;
333
+ }
327
334
  if (typeof opt.secondaryText === "string") {
328
335
  return opt.secondaryText.toLowerCase().includes(lowerSearch);
329
336
  }
330
337
  return false;
331
338
  });
332
- }, [options, searchText, minSearchLength]);
339
+ }, [options, searchText, minSearchLength, disableClientFilter]);
333
340
  const highlightedOptionId = React3__namespace.useMemo(() => {
334
341
  if (!isOpen || highlightedIndex < 0 || highlightedIndex >= filteredOptions.length) {
335
342
  return void 0;