fluentui-extended 2026.6.12 → 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
@@ -38,6 +38,7 @@ An Advanced Find-style query builder for Dynamics 365. Build complex filter cond
38
38
  ## Quick Start
39
39
 
40
40
  ```tsx
41
+ import { useState } from 'react';
41
42
  import { Lookup, LookupOption } from 'fluentui-extended';
42
43
  import { FluentProvider, webLightTheme } from '@fluentui/react-components';
43
44
 
@@ -161,6 +162,113 @@ import { AddRegular, PersonSearchRegular } from '@fluentui/react-icons';
161
162
  />
162
163
  ```
163
164
 
165
+ ### Multi-Entity Lookup with Filter Buttons
166
+
167
+ Replicate the native Dynamics 365 lookup pattern where users can filter between entity types:
168
+
169
+ ```tsx
170
+ import { Text, Button, Link, ToggleButton } from '@fluentui/react-components';
171
+ import { BuildingRegular, PersonRegular, ArrowLeftRegular } from '@fluentui/react-icons';
172
+
173
+ function MultiEntityLookup() {
174
+ const [showAccounts, setShowAccounts] = useState(true);
175
+ const [showContacts, setShowContacts] = useState(true);
176
+
177
+ const options: LookupOption[] = [
178
+ { key: 'acc-1', text: 'Contoso Ltd', icon: <BuildingRegular />, details: [...] },
179
+ { key: 'con-1', text: 'John Smith', icon: <PersonRegular />, details: [...] },
180
+ ];
181
+
182
+ // Filter based on key prefix
183
+ const filteredOptions = useMemo(() =>
184
+ options.filter(opt => {
185
+ if (opt.key.startsWith('acc-')) return showAccounts;
186
+ if (opt.key.startsWith('con-')) return showContacts;
187
+ return true;
188
+ }), [showAccounts, showContacts]
189
+ );
190
+
191
+ return (
192
+ <Lookup
193
+ options={filteredOptions}
194
+ header={
195
+ // Drill-down view when single entity selected
196
+ showAccounts !== showContacts ? (
197
+ <>
198
+ <Link onClick={() => { setShowAccounts(true); setShowContacts(true); }}>
199
+ <ArrowLeftRegular /> All
200
+ </Link>
201
+ <Text weight="semibold">{showAccounts ? 'Accounts' : 'Contacts'}</Text>
202
+ </>
203
+ ) : (
204
+ // Filter toggles when showing all
205
+ <>
206
+ <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
207
+ <Text size={200}>Results from:</Text>
208
+ <ToggleButton size="small" checked={showAccounts}
209
+ onClick={() => { setShowAccounts(true); setShowContacts(false); }}>
210
+ Accounts
211
+ </ToggleButton>
212
+ <ToggleButton size="small" checked={showContacts}
213
+ onClick={() => { setShowAccounts(false); setShowContacts(true); }}>
214
+ Contacts
215
+ </ToggleButton>
216
+ </div>
217
+ <Button size="small">Recent records</Button>
218
+ </>
219
+ )
220
+ }
221
+ />
222
+ );
223
+ }
224
+ ```
225
+
226
+ ### Rich Secondary Text with React Elements
227
+
228
+ Both `secondaryText` and `details` support React elements, not just strings:
229
+
230
+ ```tsx
231
+ import { Badge } from '@fluentui/react-components';
232
+ import { CheckmarkCircleRegular } from '@fluentui/react-icons';
233
+
234
+ const options: LookupOption[] = [
235
+ {
236
+ key: '1',
237
+ text: 'John Smith',
238
+ secondaryText: (
239
+ <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
240
+ <Badge appearance="tint" color="success" size="small" icon={<CheckmarkCircleRegular />}>
241
+ Active
242
+ </Badge>
243
+ <span>john.smith@contoso.com</span>
244
+ </span>
245
+ ),
246
+ icon: <PersonRegular />,
247
+ details: [
248
+ { label: 'Status', value: <Badge appearance="filled" color="success" size="small">Verified</Badge> },
249
+ { label: 'Role', value: <Badge appearance="tint" color="brand" size="small">Decision Maker</Badge> },
250
+ { value: <span style={{ color: '#0078d4' }}>View full profile →</span> },
251
+ ],
252
+ },
253
+ ];
254
+ ```
255
+
256
+ ---
257
+
258
+ ## Test Harness Examples
259
+
260
+ Run the test harness with `npm run harness` to see all examples in action.
261
+
262
+ | Example | Description |
263
+ |---------|-------------|
264
+ | **Basic Lookup** | Simple lookup with expandable details, no header/footer |
265
+ | **Header & Footer** | D365-style with "Accounts" header and "New" / "Advanced" footer links |
266
+ | **Details Only (No Secondary Text)** | Options with icons + details but no secondary text; demonstrates icon centering on single-line text |
267
+ | **Multi-Entity Filter** | Toggle between Accounts/Contacts with drill-down header pattern (← All) |
268
+ | **Dynamic Search (Async API)** | Simulated 800ms API delay with loading spinner; auto-loads top 5 on open |
269
+ | **Live Dynamics Lookup** | Connects to real D365 environment via Xrm.WebApi (when connected) |
270
+ | **QueryBuilder** | Full Advanced Find-style query builder with FetchXML serialization |
271
+
164
272
  ## API Reference
165
273
 
166
274
  ### Lookup Props
@@ -185,6 +293,45 @@ import { AddRegular, PersonSearchRegular } from '@fluentui/react-icons';
185
293
  | `disabled` | `boolean` | `false` | Disable the lookup |
186
294
  | `open` | `boolean` | - | Controlled open state for the dropdown |
187
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
+ ```
188
335
 
189
336
  ### Cross-Document Support (Dynamics 365 Iframes)
190
337
 
@@ -216,21 +363,24 @@ The Lookup component extends Fluent UI's `Input` and supports these standard pro
216
363
 
217
364
  ```ts
218
365
  interface LookupOption {
219
- key: string; // Unique identifier (required)
220
- text: string; // Display text (required)
221
- secondaryText?: string; // Secondary line of text
222
- icon?: ReactNode; // Icon component
223
- details?: LookupOptionDetail[]; // Expandable details (chevron appears)
224
- data?: unknown; // Custom data payload
225
- disabled?: boolean; // Disable this option
366
+ key: string; // Unique identifier (required)
367
+ text: string; // Display text (required)
368
+ secondaryText?: ReactNode; // Secondary line - string, Badge, or JSX
369
+ searchFields?: string; // Hidden searchable text (never rendered)
370
+ icon?: ReactNode; // Icon component (e.g., <BuildingRegular />)
371
+ details?: LookupOptionDetail[]; // Expandable details (chevron appears)
372
+ data?: unknown; // Custom data payload for your app
373
+ disabled?: boolean; // Disable this option
226
374
  }
227
375
 
228
376
  interface LookupOptionDetail {
229
- label?: string; // Optional label (e.g., "Phone:")
230
- value: string; // Detail value
377
+ label?: ReactNode; // Optional label (e.g., "Phone:" or a Badge)
378
+ value: ReactNode; // Detail value - string or JSX element
231
379
  }
232
380
  ```
233
381
 
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)).
383
+
234
384
  ## Keyboard Navigation
235
385
 
236
386
  | Key | Action |
@@ -526,14 +676,6 @@ if (!result.isValid) {
526
676
 
527
677
  ---
528
678
 
529
- ## Contributing
530
-
531
- 1. Fork the repository
532
- 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
533
- 3. Commit your changes (`git commit -m 'Add amazing feature'`)
534
- 4. Push to the branch (`git push origin feature/amazing-feature`)
535
- 5. Open a Pull Request
536
-
537
679
  ## Acknowledgments
538
680
 
539
681
  This library extends [Microsoft's Fluent UI React v9](https://react.fluentui.dev/) components. Thank you to Microsoft and the Fluent UI team for creating and maintaining such an excellent design system.
@@ -542,6 +684,83 @@ This library extends [Microsoft's Fluent UI React v9](https://react.fluentui.dev
542
684
  - [Fluent UI GitHub](https://github.com/microsoft/fluentui)
543
685
  - [Fluent 2 Design System](https://fluent2.microsoft.design/)
544
686
 
687
+ ---
688
+
689
+ ## Changelog
690
+
691
+ > Version format: `YYYY.M.DD` (e.g., `2026.8.30` = August 30, 2026)
692
+
693
+ ### 2026.8.30
694
+
695
+ - ✨ Added multi-entity filter pattern with drill-down header ("← All" back button) in test harness
696
+ - ✨ Added "Details Only (No Secondary Text)" example to test harness
697
+ - ✨ Support for React elements in `secondaryText` and `details[].value` (Badges, icons, styled text)
698
+ - ♻️ Improved `aria-selected`/`aria-disabled` attribute handling
699
+ - 📝 Documentation overhaul with complete API reference and examples
700
+
701
+ ### 2026.6.12
702
+
703
+ - ✨ Added React 19 support to peerDependencies
704
+ - 📝 Updated README with cross-document support documentation
705
+
706
+ ### 2026.2.19
707
+
708
+ - 🐛 Fixed cross-document dismiss in Dynamics 365 iframes using `ownerDocument`
709
+
710
+ ### 2026.2.17
711
+
712
+ - 🐛 Removed `requestAnimationFrame` — handler registers immediately
713
+ - 🐛 Switched to capture phase for dismiss handler to prevent D365 DOM interference
714
+
715
+ ### 2026.2.15
716
+
717
+ - ✨ Added controlled `open` and `onOpenChange` props for programmatic dropdown control
718
+ - 🐛 Removed `requestAnimationFrame` from dismiss handler
719
+
720
+ ### 2026.2.13
721
+
722
+ - ♻️ Rebuilt popup from scratch using custom element (Fluent UI Popover had unexpected behavior)
723
+
724
+ ### 2026.2.11
725
+
726
+ - 🐛 Added `onOpenChange` callback to sync internal state with Popover dismiss events (outside click, Escape, focus loss)
727
+
728
+ ### 2026.2.10
729
+
730
+ - 🐛 Fixed Lookup not allowing space character in search input
731
+
732
+ ### 2026.2.8
733
+
734
+ - ✨ **QueryBuilder**: Native API integration for field metadata
735
+ - ✨ **QueryBuilder**: Lookup field support with related entity validation
736
+
737
+ ### 2026.2.7
738
+
739
+ - ♻️ Removed `Xrm` global dependency — now uses native `/api/data/v9.2/` fetch calls
740
+
741
+ ### 2026.2.6
742
+
743
+ - ♻️ **QueryBuilder**: Refactored to reuse shared components and styles
744
+
745
+ ### 2026.2.5
746
+
747
+ - ✨ **QueryBuilder**: Initial release (beta) — Advanced Find-style query builder
748
+ - ♻️ **Lookup**: Changed from options-only to popup-based rendering
749
+
750
+ ### 2026.2.3
751
+
752
+ - ✨ Added `id` prop — auto-generated if not provided
753
+
754
+ ### 2026.2.2
755
+
756
+ - 🐛 Fixed classic JSX transform for React 16 compatibility
757
+ - ✨ Added React 16.8+ support
758
+
759
+ ### 2026.2.1
760
+
761
+ - 🎉 Initial release
762
+ - ✨ Lookup component with async search, expandable details, header/footer
763
+
545
764
  ## License
546
765
 
547
766
  MIT
package/dist/index.d.mts CHANGED
@@ -2,18 +2,25 @@ import * as React from 'react';
2
2
  import { InputProps } from '@fluentui/react-components';
3
3
 
4
4
  interface LookupOptionDetail {
5
- /** Label for the detail row */
6
- label?: string;
7
- /** Value for the detail row */
8
- value: string;
5
+ /** Label for the detail row - can be a string or React element */
6
+ label?: React.ReactNode;
7
+ /** Value for the detail row - can be a string or React element */
8
+ value: React.ReactNode;
9
9
  }
10
10
  interface LookupOption {
11
11
  /** Unique identifier for the option */
12
12
  key: string;
13
13
  /** Display text for the option */
14
14
  text: string;
15
- /** Optional secondary text */
16
- secondaryText?: string;
15
+ /** Optional secondary text - can be a string or React element */
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
@@ -2,18 +2,25 @@ import * as React from 'react';
2
2
  import { InputProps } from '@fluentui/react-components';
3
3
 
4
4
  interface LookupOptionDetail {
5
- /** Label for the detail row */
6
- label?: string;
7
- /** Value for the detail row */
8
- value: string;
5
+ /** Label for the detail row - can be a string or React element */
6
+ label?: React.ReactNode;
7
+ /** Value for the detail row - can be a string or React element */
8
+ value: React.ReactNode;
9
9
  }
10
10
  interface LookupOption {
11
11
  /** Unique identifier for the option */
12
12
  key: string;
13
13
  /** Display text for the option */
14
14
  text: string;
15
- /** Optional secondary text */
16
- secondaryText?: string;
15
+ /** Optional secondary text - can be a string or React element */
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
@@ -88,15 +88,19 @@ var useLookupStyles = reactComponents.makeStyles({
88
88
  flexDirection: "row",
89
89
  alignItems: "flex-start",
90
90
  boxSizing: "border-box",
91
- padding: "8px 12px",
91
+ paddingTop: "6px",
92
+ paddingBottom: "6px",
93
+ paddingLeft: "12px",
94
+ paddingRight: "8px",
92
95
  cursor: "pointer",
93
- borderRadius: reactComponents.tokens.borderRadiusSmall,
96
+ borderRadius: reactComponents.tokens.borderRadiusNone,
94
97
  backgroundColor: "transparent",
95
98
  border: "none",
96
99
  width: "100%",
97
100
  overflow: "hidden",
98
101
  textAlign: "left",
99
- gap: "8px",
102
+ gap: "10px",
103
+ minHeight: "40px",
100
104
  "&:hover": {
101
105
  backgroundColor: reactComponents.tokens.colorNeutralBackground1Hover
102
106
  },
@@ -110,16 +114,24 @@ var useLookupStyles = reactComponents.makeStyles({
110
114
  display: "flex",
111
115
  alignItems: "center",
112
116
  justifyContent: "center",
113
- width: "20px",
114
- height: "20px",
117
+ width: "24px",
118
+ height: "24px",
119
+ fontSize: "20px",
115
120
  flexShrink: 0,
116
- color: reactComponents.tokens.colorNeutralForeground3
121
+ color: reactComponents.tokens.colorNeutralForeground1,
122
+ marginTop: "0px"
123
+ // Centered on single text row
124
+ },
125
+ optionIconWithSecondary: {
126
+ marginTop: "6px"
127
+ // Centered between text + secondaryText rows
117
128
  },
118
129
  optionContent: {
119
130
  display: "flex",
120
131
  flexDirection: "column",
121
132
  flex: "1 1 auto",
122
- minWidth: 0
133
+ minWidth: 0,
134
+ gap: "2px"
123
135
  },
124
136
  optionExpandButton: {
125
137
  display: "flex",
@@ -128,6 +140,7 @@ var useLookupStyles = reactComponents.makeStyles({
128
140
  width: "24px",
129
141
  height: "24px",
130
142
  marginLeft: "auto",
143
+ marginTop: "2px",
131
144
  flexShrink: 0,
132
145
  cursor: "pointer",
133
146
  borderRadius: reactComponents.tokens.borderRadiusSmall,
@@ -161,14 +174,15 @@ var useLookupStyles = reactComponents.makeStyles({
161
174
  },
162
175
  optionText: {
163
176
  fontSize: reactComponents.tokens.fontSizeBase300,
164
- fontWeight: reactComponents.tokens.fontWeightRegular,
165
- color: reactComponents.tokens.colorNeutralForeground1
177
+ fontWeight: reactComponents.tokens.fontWeightSemibold,
178
+ color: reactComponents.tokens.colorNeutralForeground1,
179
+ lineHeight: reactComponents.tokens.lineHeightBase300
166
180
  },
167
181
  optionSecondaryText: {
168
182
  fontSize: reactComponents.tokens.fontSizeBase200,
169
183
  fontWeight: reactComponents.tokens.fontWeightRegular,
170
- color: reactComponents.tokens.colorNeutralForeground3,
171
- marginTop: "2px"
184
+ color: reactComponents.tokens.colorNeutralForeground2,
185
+ lineHeight: reactComponents.tokens.lineHeightBase200
172
186
  },
173
187
  optionDetails: {
174
188
  display: "flex",
@@ -267,6 +281,7 @@ var Lookup = ({
267
281
  footer,
268
282
  open: controlledOpen,
269
283
  onOpenChange,
284
+ disableClientFilter = false,
270
285
  ...inputProps
271
286
  }) => {
272
287
  const styles = useLookupStyles();
@@ -302,14 +317,26 @@ var Lookup = ({
302
317
  [selectedOptionProp, options, selectedKey, internalSelectedOption]
303
318
  );
304
319
  const filteredOptions = React3__namespace.useMemo(() => {
320
+ if (disableClientFilter) {
321
+ return options;
322
+ }
305
323
  if (!searchText || searchText.length < minSearchLength) {
306
324
  return options;
307
325
  }
308
326
  const lowerSearch = searchText.toLowerCase();
309
- return options.filter(
310
- (opt) => opt.text.toLowerCase().includes(lowerSearch) || opt.secondaryText?.toLowerCase().includes(lowerSearch)
311
- );
312
- }, [options, searchText, minSearchLength]);
327
+ return options.filter((opt) => {
328
+ if (opt.text.toLowerCase().includes(lowerSearch)) {
329
+ return true;
330
+ }
331
+ if (opt.searchFields && opt.searchFields.toLowerCase().includes(lowerSearch)) {
332
+ return true;
333
+ }
334
+ if (typeof opt.secondaryText === "string") {
335
+ return opt.secondaryText.toLowerCase().includes(lowerSearch);
336
+ }
337
+ return false;
338
+ });
339
+ }, [options, searchText, minSearchLength, disableClientFilter]);
313
340
  const highlightedOptionId = React3__namespace.useMemo(() => {
314
341
  if (!isOpen || highlightedIndex < 0 || highlightedIndex >= filteredOptions.length) {
315
342
  return void 0;
@@ -580,8 +607,8 @@ var Lookup = ({
580
607
  id: `${lookupId}-option-${option.key}`,
581
608
  role: "option",
582
609
  "data-index": index,
583
- "aria-selected": option.key === selectedOption?.key ? true : false,
584
- "aria-disabled": option.disabled === true ? true : void 0,
610
+ "aria-selected": option.key === selectedOption?.key,
611
+ "aria-disabled": option.disabled || void 0,
585
612
  className: reactComponents.mergeClasses(
586
613
  styles.option,
587
614
  index === highlightedIndex && styles.optionHighlighted,
@@ -591,7 +618,10 @@ var Lookup = ({
591
618
  onClick: () => handleSelectOption(option),
592
619
  onMouseEnter: () => setHighlightedIndex(index)
593
620
  },
594
- option.icon && /* @__PURE__ */ React3__namespace.createElement("span", { className: styles.optionIcon }, option.icon),
621
+ option.icon && /* @__PURE__ */ React3__namespace.createElement("span", { className: reactComponents.mergeClasses(
622
+ styles.optionIcon,
623
+ !!option.secondaryText && styles.optionIconWithSecondary
624
+ ) }, option.icon),
595
625
  /* @__PURE__ */ React3__namespace.createElement("span", { className: styles.optionContent }, /* @__PURE__ */ React3__namespace.createElement("span", { className: styles.optionText }, option.text), option.secondaryText && /* @__PURE__ */ React3__namespace.createElement("span", { className: styles.optionSecondaryText }, option.secondaryText), isExpanded && hasDetails && /* @__PURE__ */ React3__namespace.createElement("div", { className: styles.optionDetails }, option.details.map((detail, detailIndex) => /* @__PURE__ */ React3__namespace.createElement("div", { key: detailIndex, className: styles.optionDetailRow }, detail.label && /* @__PURE__ */ React3__namespace.createElement("span", { className: styles.optionDetailLabel }, detail.label, ":"), /* @__PURE__ */ React3__namespace.createElement("span", { className: styles.optionDetailValue }, detail.value))))),
596
626
  hasDetails && /* @__PURE__ */ React3__namespace.createElement(
597
627
  "span",