xmlui 0.10.24 → 0.10.26

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.
Files changed (47) hide show
  1. package/dist/lib/{index-DoIVkz5T.mjs → index-DHXWMb-6.mjs} +12924 -12882
  2. package/dist/lib/index.css +1 -1
  3. package/dist/lib/{initMock-CSGEd746.mjs → initMock-TxnkId6_.mjs} +1 -1
  4. package/dist/lib/language-server-web-worker.mjs +1 -1
  5. package/dist/lib/language-server.mjs +1 -1
  6. package/dist/lib/{metadata-utils-Dx-2qZBh.mjs → metadata-utils-DXUdlyja.mjs} +6 -6
  7. package/dist/lib/{server-common--BHVvP1o.mjs → server-common-CtpN0Z4h.mjs} +1 -1
  8. package/dist/lib/xmlui.d.ts +1 -0
  9. package/dist/lib/xmlui.mjs +1 -1
  10. package/dist/metadata/{collectedComponentMetadata-B3Hs8_cV.mjs → collectedComponentMetadata-BgHIc2Iu.mjs} +12871 -12829
  11. package/dist/metadata/{initMock-DQrGwkya.mjs → initMock-B3UDa-rw.mjs} +1 -1
  12. package/dist/metadata/style.css +1 -1
  13. package/dist/metadata/xmlui-metadata.mjs +1 -1
  14. package/dist/metadata/xmlui-metadata.umd.js +3 -3
  15. package/dist/scripts/package.json +1 -1
  16. package/dist/scripts/src/components/App/App.spec.js +100 -0
  17. package/dist/scripts/src/components/App/AppNative.js +13 -2
  18. package/dist/scripts/src/components/AppHeader/AppHeader.js +1 -6
  19. package/dist/scripts/src/components/AppHeader/AppHeaderNative.js +7 -7
  20. package/dist/scripts/src/components/AutoComplete/AutoComplete.spec.js +1 -1
  21. package/dist/scripts/src/components/AutoComplete/AutoCompleteNative.js +30 -5
  22. package/dist/scripts/src/components/Form/Form.spec.js +2 -2
  23. package/dist/scripts/src/components/FormItem/FormItemNative.js +5 -1
  24. package/dist/scripts/src/components/Heading/Heading.js +45 -5
  25. package/dist/scripts/src/components/Heading/Heading.spec.js +82 -0
  26. package/dist/scripts/src/components/ModalDialog/ModalDialog.js +4 -6
  27. package/dist/scripts/src/components/ModalDialog/ModalDialog.spec.js +19 -0
  28. package/dist/scripts/src/components/NavGroup/NavGroup.spec.js +103 -11
  29. package/dist/scripts/src/components/NavGroup/NavGroupNative.js +6 -1
  30. package/dist/scripts/src/components/Option/Option.spec.js +3 -1
  31. package/dist/scripts/src/components/Select/HiddenOption.js +3 -3
  32. package/dist/scripts/src/components/Select/Select.js +2 -3
  33. package/dist/scripts/src/components/Select/Select.spec.js +4 -6
  34. package/dist/scripts/src/components/Select/SelectNative.js +187 -47
  35. package/dist/scripts/src/components-core/rendering/ComponentAdapter.js +11 -0
  36. package/dist/scripts/src/components-core/rendering/Container.js +3 -4
  37. package/dist/scripts/src/components-core/rendering/StateContainer.js +16 -18
  38. package/dist/scripts/src/components-core/rendering/reducer.js +6 -3
  39. package/dist/scripts/src/components-core/rendering/valueExtractor.js +9 -1
  40. package/dist/scripts/src/components-core/utils/extractParam.js +2 -1
  41. package/dist/scripts/src/testing/ComponentDrivers.js +1 -1
  42. package/dist/standalone/xmlui-standalone.es.d.ts +1 -0
  43. package/dist/standalone/xmlui-standalone.umd.js +35 -35
  44. package/package.json +1 -1
  45. package/dist/scripts/src/components/Select/MultiSelectOption.js +0 -42
  46. package/dist/scripts/src/components/Select/SelectOption.js +0 -34
  47. package/dist/scripts/src/components/Select/SimpleSelect.js +0 -57
@@ -9,7 +9,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- const component_test_helpers_1 = require("../../testing/component-test-helpers");
13
12
  const fixtures_1 = require("../../testing/fixtures");
14
13
  fixtures_1.test.describe("smoke tests", { tag: "@smoke" }, () => {
15
14
  (0, fixtures_1.test)("displays menuitems after click", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
@@ -103,19 +102,26 @@ fixtures_1.test.describe("smoke tests", { tag: "@smoke" }, () => {
103
102
  yield (0, fixtures_1.expect)(page.getByRole("menuitem", { name: "Page 1" })).toBeVisible();
104
103
  yield (0, fixtures_1.expect)(page.getByRole("menuitem", { name: "inner page 2" })).not.toBeVisible();
105
104
  }));
106
- fixtures_1.test.fixme("nested initiallyExpanded works", component_test_helpers_1.SKIP_REASON.XMLUI_BUG("see https://github.com/radix-ui/primitives/issues/2551#issuecomment-2457236467 . The suggested workaround does not work for us, if you were to do it, you would see the hover effect not working for the inner most menu items."), (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
105
+ (0, fixtures_1.test)("nested initiallyExpanded works", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
107
106
  yield initTestBed(`
108
- <NavGroup label="Pages" initiallyExpanded="true">
109
- <NavLink label="Page 1" />
110
- <NavGroup label="subpages" initiallyExpanded="true">
111
- <NavLink label="inner page 2" />
112
- <NavLink label="inner page 3" />
107
+ <Stack testId="stack">
108
+ <NavGroup label="Pages" initiallyExpanded="true">
109
+ <NavLink label="Page 1" />
110
+ <NavGroup label="subpages" initiallyExpanded="true">
111
+ <NavLink label="inner page 2" />
112
+ <NavLink label="inner page 3" />
113
+ </NavGroup>
114
+ <NavLink label="Page 4" />
113
115
  </NavGroup>
114
- <NavLink label="Page 4" />
115
- </NavGroup>
116
+ </Stack>
116
117
  `);
117
- yield (0, fixtures_1.expect)(page.getByRole("menuitem", { name: "Page 1" })).toBeVisible();
118
- yield (0, fixtures_1.expect)(page.getByRole("menuitem", { name: "inner page 2" })).toBeVisible();
118
+ const stack = page.getByTestId("stack");
119
+ yield (0, fixtures_1.expect)(stack).toBeVisible();
120
+ const items = page.getByRole("menuitem");
121
+ yield (0, fixtures_1.expect)(items).toHaveCount(3);
122
+ (0, fixtures_1.expect)(items.nth(0)).toHaveText("Page 1");
123
+ (0, fixtures_1.expect)(items.nth(1)).toHaveText("subpages");
124
+ (0, fixtures_1.expect)(items.nth(2)).toHaveText("Page 4");
119
125
  }));
120
126
  (0, fixtures_1.test)("expands even without label", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
121
127
  yield initTestBed(`
@@ -210,3 +216,89 @@ fixtures_1.test.describe("icon props", () => {
210
216
  yield (0, fixtures_1.expect)(eye).not.toBeVisible();
211
217
  }));
212
218
  });
219
+ // =============================================================================
220
+ // DRAWER INTERACTION TESTS
221
+ // =============================================================================
222
+ fixtures_1.test.describe("Drawer Interaction", () => {
223
+ (0, fixtures_1.test)("clicking NavGroup toggle in drawer does not close drawer", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page, }) {
224
+ // Set small viewport to trigger drawer mode
225
+ yield page.setViewportSize({ width: 400, height: 600 });
226
+ yield initTestBed(`
227
+ <App layout="condensed">
228
+ <AppHeader testId="appHeader"/>
229
+ <NavPanel>
230
+ <NavGroup label="Pages">
231
+ <NavLink label="Page 1" to="/page1"/>
232
+ <NavLink label="Page 2" to="/page2"/>
233
+ </NavGroup>
234
+ </NavPanel>
235
+ <Pages fallbackPath="/">
236
+ <Page url="/">
237
+ <Text value="Home" />
238
+ </Page>
239
+ <Page url="/page1">
240
+ <Text value="Page 1" />
241
+ </Page>
242
+ <Page url="/page2">
243
+ <Text value="Page 2" />
244
+ </Page>
245
+ </Pages>
246
+ </App>
247
+ `);
248
+ // Open drawer by clicking hamburger button
249
+ const appHeader = page.getByTestId("appHeader");
250
+ const hamburgerButton = appHeader.locator('[data-part-id="hamburger"]').first();
251
+ yield hamburgerButton.click();
252
+ const dialog = page.getByRole("dialog");
253
+ yield (0, fixtures_1.expect)(dialog).toBeVisible();
254
+ // finst the first element in the dialog with a text of "Pages"
255
+ const navGroupToggle = dialog.getByRole("button", { name: "Pages" });
256
+ yield navGroupToggle.click();
257
+ yield page.waitForTimeout(200);
258
+ yield (0, fixtures_1.expect)(dialog).toBeVisible();
259
+ // There must be a text "Page1"
260
+ yield (0, fixtures_1.expect)(dialog).toContainText("Page 1");
261
+ yield (0, fixtures_1.expect)(dialog).toContainText("Page 2");
262
+ }));
263
+ (0, fixtures_1.test)("clicking NavLink in drawer closes drawer", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
264
+ // Set small viewport to trigger drawer mode
265
+ yield page.setViewportSize({ width: 400, height: 600 });
266
+ yield initTestBed(`
267
+ <App layout="condensed">
268
+ <AppHeader />
269
+ <NavPanel>
270
+ <NavGroup label="Pages">
271
+ <NavLink label="Page 1" to="/page1"/>
272
+ <NavLink label="Page 2" to="/page2"/>
273
+ </NavGroup>
274
+ </NavPanel>
275
+ <Pages fallbackPath="/">
276
+ <Page url="/">
277
+ <Text value="Home" />
278
+ </Page>
279
+ <Page url="/page1">
280
+ <Text value="Page 1 Content" />
281
+ </Page>
282
+ <Page url="/page2">
283
+ <Text value="Page 2" />
284
+ </Page>
285
+ </Pages>
286
+ </App>
287
+ `);
288
+ // Open drawer
289
+ const hamburgerButton = page.locator('[data-part-id="hamburger"]');
290
+ yield hamburgerButton.click();
291
+ const dialog = page.getByRole("dialog");
292
+ yield (0, fixtures_1.expect)(dialog).toBeVisible();
293
+ // Expand NavGroup
294
+ const navGroupToggle = dialog.getByRole("button", { name: "Pages" });
295
+ yield navGroupToggle.click();
296
+ yield page.waitForTimeout(200);
297
+ // Click a NavLink to navigate
298
+ yield dialog.getByRole("link", { name: "Page 1" }).click();
299
+ // Verify navigation occurred
300
+ yield (0, fixtures_1.expect)(page.getByText("Page 1 Content")).toBeVisible();
301
+ // Verify drawer is closed
302
+ yield (0, fixtures_1.expect)(dialog).not.toBeVisible();
303
+ }));
304
+ });
@@ -83,7 +83,12 @@ const ExpandableNavGroup = (0, react_1.forwardRef)(function ExpandableNavGroup(_
83
83
  }
84
84
  }, [pathname]);
85
85
  const toggleStyle = Object.assign(Object.assign({}, style), { "--nav-link-level": layoutIsVertical ? level : 0 });
86
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(NavLinkNative_1.NavLink, Object.assign({}, rest, { style: toggleStyle, onClick: () => setExpanded((prev) => !prev), icon: icon, to: to, disabled: disabled, "aria-expanded": expanded, children: [label, (0, jsx_runtime_1.jsx)("div", { style: { flex: 1 } }), (0, jsx_runtime_1.jsx)(IconNative_1.Icon, { name: expanded ? iconVerticalExpanded : iconVerticalCollapsed })] })), (0, jsx_runtime_1.jsx)("div", { "aria-hidden": !expanded, className: (0, classnames_1.default)(NavGroup_module_scss_1.default.groupContent, {
86
+ const handleClick = (e) => {
87
+ e.preventDefault();
88
+ e.stopPropagation();
89
+ setExpanded((prev) => !prev);
90
+ };
91
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(NavLinkNative_1.NavLink, Object.assign({}, rest, { style: toggleStyle, onClick: handleClick, icon: icon, to: to, disabled: disabled, "aria-expanded": expanded, children: [label, (0, jsx_runtime_1.jsx)("div", { style: { flex: 1 } }), (0, jsx_runtime_1.jsx)(IconNative_1.Icon, { name: expanded ? iconVerticalExpanded : iconVerticalCollapsed })] })), (0, jsx_runtime_1.jsx)("div", { "aria-hidden": !expanded, className: (0, classnames_1.default)(NavGroup_module_scss_1.default.groupContent, {
87
92
  [NavGroup_module_scss_1.default.expanded]: expanded,
88
93
  }), children: (0, jsx_runtime_1.jsx)("div", { className: NavGroup_module_scss_1.default.groupContentInner, ref: groupContentInnerRef, children: renderChild(node.children) }) })] }));
89
94
  });
@@ -340,6 +340,8 @@ fixtures_1.test.describe("Accessibility", () => {
340
340
  yield page.waitForTimeout(200);
341
341
  yield page.keyboard.press("ArrowDown");
342
342
  yield page.waitForTimeout(200);
343
+ yield page.keyboard.press("ArrowDown");
344
+ yield page.waitForTimeout(200);
343
345
  // Select with Enter
344
346
  yield page.keyboard.press("Enter");
345
347
  yield page.waitForTimeout(200);
@@ -445,7 +447,7 @@ fixtures_1.test.describe("Other Edge Cases", () => {
445
447
  // The object label should be visible with some string representation
446
448
  yield (0, fixtures_1.expect)(page.getByRole("option")).toHaveCount(2);
447
449
  }));
448
- (0, fixtures_1.test)("null values are handled gracefully", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page, createSelectDriver, }) {
450
+ (0, fixtures_1.test)("null values are handled gracefully", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page, createSelectDriver }) {
449
451
  yield initTestBed(`
450
452
  <Select>
451
453
  <Option label="{null}" value="null_label" />
@@ -6,7 +6,7 @@ const OptionContext_1 = require("./OptionContext");
6
6
  const react_1 = require("react");
7
7
  function HiddenOption(option) {
8
8
  const { label } = option;
9
- const { onOptionRemove, onOptionAdd } = (0, OptionContext_1.useOption)();
9
+ const { onOptionAdd } = (0, OptionContext_1.useOption)();
10
10
  const [node, setNode] = (0, react_1.useState)(null);
11
11
  const opt = (0, react_1.useMemo)(() => {
12
12
  var _a, _b;
@@ -14,7 +14,7 @@ function HiddenOption(option) {
14
14
  }, [option, node, label]);
15
15
  (0, react_1.useEffect)(() => {
16
16
  onOptionAdd(opt);
17
- return () => onOptionRemove(opt);
18
- }, [opt, onOptionAdd, onOptionRemove]);
17
+ // Don't remove options when component unmounts - they should persist
18
+ }, [opt, onOptionAdd]);
19
19
  return ((0, jsx_runtime_1.jsx)("div", { ref: (el) => setNode(el), style: { display: "none" }, children: option.children }));
20
20
  }
@@ -11,7 +11,6 @@ const themeVars_1 = require("../../components-core/theming/themeVars");
11
11
  const metadata_helpers_1 = require("../metadata-helpers");
12
12
  const container_helpers_1 = require("../container-helpers");
13
13
  const SelectNative_1 = require("./SelectNative");
14
- const react_select_1 = require("@radix-ui/react-select");
15
14
  const COMP = "Select";
16
15
  exports.SelectMd = (0, metadata_helpers_1.createMetadata)({
17
16
  status: "stable",
@@ -115,7 +114,7 @@ exports.selectComponentRenderer = (0, renderers_1.createComponentRenderer)(COMP,
115
114
  const multiSelect = extractValue.asOptionalBoolean(node.props.multiSelect);
116
115
  const searchable = extractValue.asOptionalBoolean(node.props.searchable);
117
116
  const isControlled = node.props.value !== undefined;
118
- return ((0, jsx_runtime_1.jsx)(SelectNative_1.Select, { multiSelect: multiSelect, className: className, inProgress: extractValue.asOptionalBoolean(node.props.inProgress), inProgressNotificationMessage: extractValue.asOptionalString(node.props.inProgressNotificationMessage), readOnly: extractValue.asOptionalBoolean(node.props.readOnly), updateState: isControlled ? undefined : updateState, searchable: searchable, initialValue: extractValue(node.props.initialValue), value: isControlled ? extractValue(node.props.value) : state === null || state === void 0 ? void 0 : state.value, autoFocus: extractValue.asOptionalBoolean(node.props.autoFocus), enabled: extractValue.asOptionalBoolean(node.props.enabled), placeholder: extractValue.asOptionalString(node.props.placeholder), validationStatus: extractValue(node.props.validationStatus), onDidChange: lookupEventHandler("didChange"), onFocus: lookupEventHandler("gotFocus"), onBlur: lookupEventHandler("lostFocus"), registerComponentApi: registerComponentApi, emptyListTemplate: renderChild(node.props.emptyListTemplate), dropdownHeight: extractValue(node.props.dropdownHeight), required: extractValue.asOptionalBoolean(node.props.required), valueRenderer: node.props.valueTemplate
117
+ return ((0, jsx_runtime_1.jsx)(SelectNative_1.Select, { multiSelect: multiSelect, className: className, inProgress: extractValue.asOptionalBoolean(node.props.inProgress), inProgressNotificationMessage: extractValue.asOptionalString(node.props.inProgressNotificationMessage), readOnly: extractValue.asOptionalBoolean(node.props.readOnly), updateState: isControlled ? undefined : updateState, searchable: searchable, initialValue: extractValue(node.props.initialValue), value: state === null || state === void 0 ? void 0 : state.value, autoFocus: extractValue.asOptionalBoolean(node.props.autoFocus), enabled: extractValue.asOptionalBoolean(node.props.enabled), placeholder: extractValue.asOptionalString(node.props.placeholder), validationStatus: extractValue(node.props.validationStatus), onDidChange: lookupEventHandler("didChange"), onFocus: lookupEventHandler("gotFocus"), onBlur: lookupEventHandler("lostFocus"), registerComponentApi: registerComponentApi, emptyListTemplate: renderChild(node.props.emptyListTemplate), dropdownHeight: extractValue(node.props.dropdownHeight), required: extractValue.asOptionalBoolean(node.props.required), valueRenderer: node.props.valueTemplate
119
118
  ? (item, removeItem) => {
120
119
  return ((0, jsx_runtime_1.jsx)(container_helpers_1.MemoizedItem, { contextVars: {
121
120
  $itemContext: { removeItem },
@@ -126,7 +125,7 @@ exports.selectComponentRenderer = (0, renderers_1.createComponentRenderer)(COMP,
126
125
  return ((0, jsx_runtime_1.jsx)(container_helpers_1.MemoizedItem, { node: node.props.optionTemplate, item: item, contextVars: {
127
126
  $selectedValue: val,
128
127
  $inTrigger: inTrigger,
129
- }, renderChild: (...args) => multiSelect || searchable ? (renderChild(...args)) : ((0, jsx_runtime_1.jsx)(react_select_1.SelectItemText, { children: renderChild(...args) })) }));
128
+ }, renderChild: renderChild }));
130
129
  }
131
130
  : undefined, children: renderChild(node.children) }));
132
131
  });
@@ -38,10 +38,10 @@ fixtures_1.test.describe("Basic Functionality", () => {
38
38
  </FormItem>
39
39
  </Form>`);
40
40
  const driver = yield createSelectDriver("mySelect");
41
- yield (0, fixtures_1.expect)(driver.component.locator("select")).toHaveValue("opt1");
41
+ yield (0, fixtures_1.expect)(driver.component).toHaveText("first");
42
42
  yield driver.toggleOptionsVisibility();
43
43
  yield driver.selectLabel("second");
44
- yield (0, fixtures_1.expect)(driver.component.locator("select")).toHaveValue("opt2");
44
+ yield (0, fixtures_1.expect)(driver.component).toHaveText("second");
45
45
  }));
46
46
  // --- initialValue prop
47
47
  (0, fixtures_1.test)("initialValue set to first valid value", (_a) => __awaiter(void 0, [_a], void 0, function* ({ page, initTestBed }) {
@@ -133,12 +133,10 @@ fixtures_1.test.describe("Basic Functionality", () => {
133
133
  </Select>
134
134
  `);
135
135
  const driver = yield createSelectDriver();
136
- yield (0, fixtures_1.expect)(page.getByText("Two")).not.toBeVisible();
137
- yield (0, fixtures_1.expect)(page.getByText("One")).toBeVisible();
136
+ yield (0, fixtures_1.expect)(driver.component).toHaveText("One");
138
137
  yield driver.toggleOptionsVisibility();
139
138
  yield driver.selectLabel("Two");
140
- yield (0, fixtures_1.expect)(page.getByText("Two")).not.toBeVisible();
141
- yield (0, fixtures_1.expect)(page.getByText("One")).toBeVisible();
139
+ yield (0, fixtures_1.expect)(driver.component).toHaveText("One");
142
140
  // verify dropdown is not visible but value is shown
143
141
  }));
144
142
  (0, fixtures_1.test)("readOnly multi-Select shows options, but value cannot be changed", (_a) => __awaiter(void 0, [_a], void 0, function* ({ page, initTestBed, createSelectDriver, }) {
@@ -15,15 +15,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.Select = exports.defaultProps = void 0;
18
- const react_1 = require("react");
19
18
  const jsx_runtime_1 = require("react/jsx-runtime");
20
- const react_2 = require("react");
21
- const react_compose_refs_1 = require("@radix-ui/react-compose-refs");
19
+ const react_1 = require("react");
22
20
  const react_popover_1 = require("@radix-ui/react-popover");
23
21
  const classnames_1 = __importDefault(require("classnames"));
24
- const react_focus_scope_1 = require("@radix-ui/react-focus-scope");
25
- const SelectOption_1 = require("./SelectOption");
26
22
  const Select_module_scss_1 = __importDefault(require("./Select.module.scss"));
23
+ const react_compose_refs_1 = require("@radix-ui/react-compose-refs");
27
24
  const constants_1 = require("../../components-core/constants");
28
25
  const ThemeContext_1 = require("../../components-core/theming/ThemeContext");
29
26
  const misc_1 = require("../../components-core/utils/misc");
@@ -32,9 +29,7 @@ const SelectContext_1 = require("./SelectContext");
32
29
  const OptionTypeProvider_1 = __importDefault(require("../Option/OptionTypeProvider"));
33
30
  const OptionContext_1 = require("./OptionContext");
34
31
  const HiddenOption_1 = require("./HiddenOption");
35
- const FormContext_1 = require("../Form/FormContext");
36
- const SimpleSelect_1 = require("./SimpleSelect");
37
- const MultiSelectOption_1 = require("./MultiSelectOption");
32
+ const PART_LIST_WRAPPER = "listWrapper";
38
33
  exports.defaultProps = {
39
34
  enabled: true,
40
35
  placeholder: "",
@@ -80,7 +75,7 @@ const SelectTriggerActions = ({ value, multiSelect, enabled, readOnly, clearValu
80
75
  clearValue();
81
76
  }, children: (0, jsx_runtime_1.jsx)(IconNative_1.default, { name: "close" }) })), showChevron && ((0, jsx_runtime_1.jsx)("span", { className: Select_module_scss_1.default.action, children: (0, jsx_runtime_1.jsx)(IconNative_1.default, { name: "chevrondown" }) }))] }));
82
77
  };
83
- exports.Select = (0, react_2.forwardRef)(function Select(_a, forwardedRef) {
78
+ exports.Select = (0, react_1.forwardRef)(function Select(_a, forwardedRef) {
84
79
  var {
85
80
  // Basic props
86
81
  id, initialValue, value, enabled = exports.defaultProps.enabled, placeholder = exports.defaultProps.placeholder, autoFocus = exports.defaultProps.autoFocus, readOnly = false, required = exports.defaultProps.required,
@@ -96,17 +91,16 @@ exports.Select = (0, react_2.forwardRef)(function Select(_a, forwardedRef) {
96
91
  inProgress = exports.defaultProps.inProgress, inProgressNotificationMessage = exports.defaultProps.inProgressNotificationMessage,
97
92
  // Internal
98
93
  updateState = constants_1.noop, registerComponentApi, children } = _a, rest = __rest(_a, ["id", "initialValue", "value", "enabled", "placeholder", "autoFocus", "readOnly", "required", "style", "className", "dropdownHeight", "validationStatus", "onDidChange", "onFocus", "onBlur", "searchable", "multiSelect", "emptyListTemplate", "valueRenderer", "optionRenderer", "inProgress", "inProgressNotificationMessage", "updateState", "registerComponentApi", "children"]);
99
- const [referenceElement, setReferenceElement] = (0, react_2.useState)(null);
100
- const [open, setOpen] = (0, react_2.useState)(false);
101
- const [width, setWidth] = (0, react_2.useState)(0);
102
- const observer = (0, react_2.useRef)();
94
+ const [referenceElement, setReferenceElement] = (0, react_1.useState)(null);
95
+ const [open, setOpen] = (0, react_1.useState)(false);
96
+ const [width, setWidth] = (0, react_1.useState)(0);
97
+ const observer = (0, react_1.useRef)();
103
98
  const { root } = (0, ThemeContext_1.useTheme)();
104
- const [options, setOptions] = (0, react_2.useState)(new Set());
105
- const isInForm = (0, FormContext_1.useIsInsideForm)();
106
- const [searchTerm, setSearchTerm] = (0, react_2.useState)("");
107
- const [selectedIndex, setSelectedIndex] = (0, react_2.useState)(-1);
99
+ const [options, setOptions] = (0, react_1.useState)(new Set());
100
+ const [searchTerm, setSearchTerm] = (0, react_1.useState)("");
101
+ const [selectedIndex, setSelectedIndex] = (0, react_1.useState)(-1);
108
102
  // Filter options based on search term
109
- const filteredOptions = (0, react_2.useMemo)(() => {
103
+ const filteredOptions = (0, react_1.useMemo)(() => {
110
104
  if (!searchTerm || searchTerm.trim() === "") {
111
105
  return Array.from(options);
112
106
  }
@@ -117,20 +111,20 @@ exports.Select = (0, react_2.forwardRef)(function Select(_a, forwardedRef) {
117
111
  });
118
112
  }, [options, searchTerm]);
119
113
  // Reset selected index when options change or dropdown closes
120
- (0, react_2.useEffect)(() => {
114
+ (0, react_1.useEffect)(() => {
121
115
  if (!open) {
122
116
  setSelectedIndex(-1);
123
117
  setSearchTerm("");
124
118
  }
125
119
  }, [open]);
126
120
  // Set initial state based on the initialValue prop
127
- (0, react_2.useEffect)(() => {
121
+ (0, react_1.useEffect)(() => {
128
122
  if (initialValue !== undefined) {
129
123
  updateState({ value: initialValue }, { initial: true });
130
124
  }
131
125
  }, [initialValue, updateState]);
132
126
  // Observe the size of the reference element
133
- (0, react_2.useEffect)(() => {
127
+ (0, react_1.useEffect)(() => {
134
128
  var _a;
135
129
  const current = referenceElement;
136
130
  (_a = observer.current) === null || _a === void 0 ? void 0 : _a.disconnect();
@@ -144,7 +138,7 @@ exports.Select = (0, react_2.forwardRef)(function Select(_a, forwardedRef) {
144
138
  };
145
139
  }, [referenceElement]);
146
140
  // Handle option selection
147
- const toggleOption = (0, react_2.useCallback)((selectedValue) => {
141
+ const toggleOption = (0, react_1.useCallback)((selectedValue) => {
148
142
  const newSelectedValue = multiSelect
149
143
  ? Array.isArray(value)
150
144
  ? value.map((v) => String(v)).includes(String(selectedValue))
@@ -161,46 +155,50 @@ exports.Select = (0, react_2.forwardRef)(function Select(_a, forwardedRef) {
161
155
  }
162
156
  }, [multiSelect, value, updateState, onDidChange]);
163
157
  // Clear selected value
164
- const clearValue = (0, react_2.useCallback)(() => {
158
+ const clearValue = (0, react_1.useCallback)(() => {
165
159
  const newValue = multiSelect ? [] : "";
166
160
  updateState({ value: newValue });
167
161
  onDidChange(newValue);
168
162
  }, [multiSelect, updateState, onDidChange]);
169
163
  // Helper functions to find next/previous enabled option
170
- const findNextEnabledIndex = (0, react_2.useCallback)((currentIndex) => {
164
+ const findNextEnabledIndex = (0, react_1.useCallback)((currentIndex) => {
165
+ if (filteredOptions.length === 0)
166
+ return -1;
171
167
  for (let i = currentIndex + 1; i < filteredOptions.length; i++) {
172
168
  const item = filteredOptions[i];
173
- if (item.enabled !== false) {
169
+ if (item && item.enabled !== false) {
174
170
  return i;
175
171
  }
176
172
  }
177
173
  // Wrap around to beginning
178
174
  for (let i = 0; i <= currentIndex; i++) {
179
175
  const item = filteredOptions[i];
180
- if (item.enabled !== false) {
176
+ if (item && item.enabled !== false) {
181
177
  return i;
182
178
  }
183
179
  }
184
180
  return -1;
185
181
  }, [filteredOptions]);
186
- const findPreviousEnabledIndex = (0, react_2.useCallback)((currentIndex) => {
182
+ const findPreviousEnabledIndex = (0, react_1.useCallback)((currentIndex) => {
183
+ if (filteredOptions.length === 0)
184
+ return -1;
187
185
  for (let i = currentIndex - 1; i >= 0; i--) {
188
186
  const item = filteredOptions[i];
189
- if (item.enabled !== false) {
187
+ if (item && item.enabled !== false) {
190
188
  return i;
191
189
  }
192
190
  }
193
191
  // Wrap around to end
194
192
  for (let i = filteredOptions.length - 1; i >= currentIndex; i--) {
195
193
  const item = filteredOptions[i];
196
- if (item.enabled !== false) {
194
+ if (item && item.enabled !== false) {
197
195
  return i;
198
196
  }
199
197
  }
200
198
  return -1;
201
199
  }, [filteredOptions]);
202
200
  // Keyboard navigation
203
- const handleKeyDown = (0, react_2.useCallback)((event) => {
201
+ const handleKeyDown = (0, react_1.useCallback)((event) => {
204
202
  if (!open)
205
203
  return;
206
204
  switch (event.key) {
@@ -222,8 +220,12 @@ exports.Select = (0, react_2.forwardRef)(function Select(_a, forwardedRef) {
222
220
  event.preventDefault();
223
221
  if (selectedIndex >= 0 && selectedIndex < filteredOptions.length) {
224
222
  const selectedItem = filteredOptions[selectedIndex];
225
- if (selectedItem.enabled !== false) {
223
+ if (selectedItem && selectedItem.enabled !== false) {
226
224
  toggleOption(selectedItem.value);
225
+ // Close dropdown after selecting in single-select mode
226
+ if (!multiSelect) {
227
+ setOpen(false);
228
+ }
227
229
  }
228
230
  }
229
231
  break;
@@ -237,11 +239,12 @@ exports.Select = (0, react_2.forwardRef)(function Select(_a, forwardedRef) {
237
239
  selectedIndex,
238
240
  filteredOptions,
239
241
  toggleOption,
242
+ multiSelect,
240
243
  findNextEnabledIndex,
241
244
  findPreviousEnabledIndex,
242
245
  ]);
243
246
  // Register component API for external interactions
244
- const focus = (0, react_2.useCallback)(() => {
247
+ const focus = (0, react_1.useCallback)(() => {
245
248
  referenceElement === null || referenceElement === void 0 ? void 0 : referenceElement.focus();
246
249
  }, [referenceElement]);
247
250
  const setValue = (0, misc_1.useEvent)((newValue) => {
@@ -256,7 +259,7 @@ exports.Select = (0, react_2.forwardRef)(function Select(_a, forwardedRef) {
256
259
  clearValue();
257
260
  }
258
261
  });
259
- (0, react_2.useEffect)(() => {
262
+ (0, react_1.useEffect)(() => {
260
263
  registerComponentApi === null || registerComponentApi === void 0 ? void 0 : registerComponentApi({
261
264
  focus,
262
265
  setValue,
@@ -264,37 +267,174 @@ exports.Select = (0, react_2.forwardRef)(function Select(_a, forwardedRef) {
264
267
  });
265
268
  }, [focus, registerComponentApi, setValue, reset]);
266
269
  // Render the "empty list" message
267
- const emptyListNode = (0, react_2.useMemo)(() => emptyListTemplate !== null && emptyListTemplate !== void 0 ? emptyListTemplate : ((0, jsx_runtime_1.jsxs)("div", { className: Select_module_scss_1.default.selectEmpty, children: [(0, jsx_runtime_1.jsx)(IconNative_1.default, { name: "noresult" }), (0, jsx_runtime_1.jsx)("span", { children: "List is empty" })] })), [emptyListTemplate]);
268
- const onOptionAdd = (0, react_2.useCallback)((option) => {
269
- setOptions((prev) => new Set(prev).add(option));
270
+ const emptyListNode = (0, react_1.useMemo)(() => emptyListTemplate !== null && emptyListTemplate !== void 0 ? emptyListTemplate : ((0, jsx_runtime_1.jsxs)("div", { className: Select_module_scss_1.default.selectEmpty, children: [(0, jsx_runtime_1.jsx)(IconNative_1.default, { name: "noresult" }), (0, jsx_runtime_1.jsx)("span", { children: "List is empty" })] })), [emptyListTemplate]);
271
+ const onOptionAdd = (0, react_1.useCallback)((option) => {
272
+ setOptions((prev) => {
273
+ // Check if option with same value already exists
274
+ const exists = Array.from(prev).some((opt) => opt.value === option.value);
275
+ if (exists) {
276
+ return prev;
277
+ }
278
+ const newSet = new Set(prev);
279
+ newSet.add(option);
280
+ return newSet;
281
+ });
270
282
  }, []);
271
- const onOptionRemove = (0, react_2.useCallback)((option) => {
283
+ const onOptionRemove = (0, react_1.useCallback)((option) => {
272
284
  setOptions((prev) => {
273
285
  const optionsSet = new Set(prev);
274
286
  optionsSet.delete(option);
275
287
  return optionsSet;
276
288
  });
277
289
  }, []);
278
- const optionContextValue = (0, react_2.useMemo)(() => ({
290
+ const optionContextValue = (0, react_1.useMemo)(() => ({
279
291
  onOptionAdd,
280
292
  onOptionRemove,
281
293
  }), [onOptionAdd, onOptionRemove]);
282
- const selectContextValue = (0, react_2.useMemo)(() => ({
294
+ const selectContextValue = (0, react_1.useMemo)(() => ({
283
295
  multiSelect,
296
+ readOnly,
284
297
  value,
285
298
  onChange: toggleOption,
286
299
  setOpen,
287
300
  setSelectedIndex,
288
301
  options,
302
+ highlightedValue: selectedIndex >= 0 &&
303
+ selectedIndex < filteredOptions.length &&
304
+ filteredOptions[selectedIndex]
305
+ ? filteredOptions[selectedIndex].value
306
+ : undefined,
289
307
  optionRenderer,
290
- }), [multiSelect, toggleOption, value, options, optionRenderer]);
291
- return ((0, jsx_runtime_1.jsx)(SelectContext_1.SelectContext.Provider, { value: selectContextValue, children: (0, jsx_runtime_1.jsx)(OptionContext_1.OptionContext.Provider, { value: optionContextValue, children: searchable || multiSelect ? ((0, jsx_runtime_1.jsxs)(OptionTypeProvider_1.default, { Component: HiddenOption_1.HiddenOption, children: [(0, jsx_runtime_1.jsxs)(react_popover_1.Popover, { open: open, onOpenChange: setOpen, modal: false, children: [(0, jsx_runtime_1.jsxs)(react_popover_1.PopoverTrigger, Object.assign({}, rest, { ref: (0, react_compose_refs_1.composeRefs)(setReferenceElement, forwardedRef), id: id, "aria-haspopup": "listbox", style: style, onFocus: onFocus, onBlur: onBlur, disabled: !enabled, "aria-expanded": open, onClick: (event) => {
292
- // Prevent event propagation to parent elements (e.g., DropdownMenu)
293
- // This ensures that clicking the Select trigger doesn't close the containing DropdownMenu
294
- event.stopPropagation();
295
- setOpen((prev) => !prev);
296
- }, className: (0, classnames_1.default)(Select_module_scss_1.default.selectTrigger, Select_module_scss_1.default[validationStatus], {
308
+ }), [
309
+ multiSelect,
310
+ readOnly,
311
+ value,
312
+ toggleOption,
313
+ options,
314
+ selectedIndex,
315
+ filteredOptions,
316
+ optionRenderer,
317
+ ]);
318
+ return ((0, jsx_runtime_1.jsx)(SelectContext_1.SelectContext.Provider, { value: selectContextValue, children: (0, jsx_runtime_1.jsxs)(OptionContext_1.OptionContext.Provider, { value: optionContextValue, children: [(0, jsx_runtime_1.jsx)(OptionTypeProvider_1.default, { Component: VisibleSelectOption, children: (0, jsx_runtime_1.jsxs)(react_popover_1.Popover, { open: open, onOpenChange: (isOpen) => {
319
+ if (!enabled)
320
+ return;
321
+ setOpen(isOpen);
322
+ // Reset highlighted option when dropdown closes
323
+ setSelectedIndex(-1);
324
+ }, modal: false, children: [(0, jsx_runtime_1.jsxs)(react_popover_1.PopoverTrigger, Object.assign({}, rest, { ref: (0, react_compose_refs_1.composeRefs)(setReferenceElement, forwardedRef), id: id, "aria-haspopup": "listbox", style: style, onFocus: onFocus, onBlur: onBlur, disabled: !enabled, "aria-expanded": open, "data-part-id": PART_LIST_WRAPPER, className: (0, classnames_1.default)(className, Select_module_scss_1.default.selectTrigger, Select_module_scss_1.default[validationStatus], {
297
325
  [Select_module_scss_1.default.disabled]: !enabled,
298
326
  [Select_module_scss_1.default.multi]: multiSelect,
299
- }, className), autoFocus: autoFocus, children: [(0, jsx_runtime_1.jsx)(SelectTriggerValue, { value: value, placeholder: placeholder, readOnly: readOnly, multiSelect: multiSelect, options: options, valueRenderer: valueRenderer, toggleOption: toggleOption }), (0, jsx_runtime_1.jsx)(SelectTriggerActions, { value: value, multiSelect: multiSelect, enabled: enabled, readOnly: readOnly, clearValue: clearValue })] })), open && ((0, jsx_runtime_1.jsx)(react_popover_1.Portal, { container: root, children: (0, jsx_runtime_1.jsx)(react_focus_scope_1.FocusScope, { asChild: true, loop: true, trapped: true, children: (0, jsx_runtime_1.jsx)(react_popover_1.PopoverContent, { style: { minWidth: width, height: dropdownHeight }, className: Select_module_scss_1.default.selectContent, onKeyDown: handleKeyDown, children: (0, jsx_runtime_1.jsxs)("div", { className: Select_module_scss_1.default.command, children: [searchable ? ((0, jsx_runtime_1.jsxs)("div", { className: Select_module_scss_1.default.commandInputContainer, children: [(0, jsx_runtime_1.jsx)(IconNative_1.default, { name: "search" }), (0, jsx_runtime_1.jsx)("input", { role: "combobox", className: (0, classnames_1.default)(Select_module_scss_1.default.commandInput), placeholder: "Search...", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), autoFocus: true })] })) : ((0, jsx_runtime_1.jsx)("button", { autoFocus: true, "aria-hidden": "true", className: Select_module_scss_1.default.srOnly })), (0, jsx_runtime_1.jsxs)("div", { role: "listbox", className: Select_module_scss_1.default.commandList, children: [inProgress && ((0, jsx_runtime_1.jsx)("div", { className: Select_module_scss_1.default.loading, children: inProgressNotificationMessage })), filteredOptions.map(({ value, label, enabled, keywords }, index) => ((0, jsx_runtime_1.jsx)(MultiSelectOption_1.MultiSelectOption, { readOnly: readOnly, value: value, label: label, enabled: enabled, keywords: keywords, isHighlighted: selectedIndex === index, itemIndex: index }, value))), !inProgress && filteredOptions.length === 0 && ((0, jsx_runtime_1.jsx)("div", { children: emptyListNode }))] })] }) }) }) }))] }), children] })) : ((0, jsx_runtime_1.jsx)(OptionTypeProvider_1.default, { Component: SelectOption_1.SelectOption, children: (0, react_1.createElement)(SimpleSelect_1.SimpleSelect, Object.assign({}, rest, { readOnly: !!readOnly, ref: forwardedRef, key: isInForm ? (value ? `status-${value}` : "status-initial") : undefined, value: value, onValueChange: toggleOption, id: id, style: style, className: className, onFocus: onFocus, onBlur: onBlur, enabled: enabled, validationStatus: validationStatus, triggerRef: setReferenceElement, autoFocus: autoFocus, placeholder: placeholder, height: dropdownHeight, width: width, emptyListNode: emptyListNode }), children) })) }) }));
327
+ }), role: "combobox", onClick: (event) => {
328
+ if (!enabled)
329
+ return;
330
+ event.stopPropagation();
331
+ setOpen((prev) => !prev);
332
+ }, onKeyDown: (event) => {
333
+ if (!enabled || readOnly)
334
+ return;
335
+ // Handle opening dropdown with keyboard
336
+ if (!open &&
337
+ (event.key === "ArrowDown" ||
338
+ event.key === "ArrowUp" ||
339
+ event.key === " " ||
340
+ event.key === "Enter")) {
341
+ event.preventDefault();
342
+ setOpen(true);
343
+ // Set initial selectedIndex to first enabled option if options exist
344
+ if (filteredOptions.length > 0) {
345
+ const firstEnabledIndex = findNextEnabledIndex(-1);
346
+ setSelectedIndex(firstEnabledIndex !== -1 ? firstEnabledIndex : 0);
347
+ }
348
+ return;
349
+ }
350
+ // Handle keyboard navigation when dropdown is open
351
+ if (open) {
352
+ handleKeyDown(event);
353
+ }
354
+ }, autoFocus: autoFocus, children: [(0, jsx_runtime_1.jsx)(SelectTriggerValue, { value: value, placeholder: placeholder, readOnly: readOnly, multiSelect: multiSelect, options: options, valueRenderer: valueRenderer, toggleOption: toggleOption }), (0, jsx_runtime_1.jsx)(SelectTriggerActions, { value: value, multiSelect: multiSelect, enabled: enabled, readOnly: readOnly, clearValue: clearValue })] })), open && ((0, jsx_runtime_1.jsx)(react_popover_1.Portal, { container: root, children: (0, jsx_runtime_1.jsx)(react_popover_1.PopoverContent, { style: { minWidth: width, height: dropdownHeight }, className: Select_module_scss_1.default.selectContent, onKeyDown: handleKeyDown, children: (0, jsx_runtime_1.jsxs)("div", { className: Select_module_scss_1.default.command, children: [searchable ? ((0, jsx_runtime_1.jsxs)("div", { className: Select_module_scss_1.default.commandInputContainer, children: [(0, jsx_runtime_1.jsx)(IconNative_1.default, { name: "search" }), (0, jsx_runtime_1.jsx)("input", { role: "searchbox", className: (0, classnames_1.default)(Select_module_scss_1.default.commandInput), placeholder: "Search...", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value) })] })) : ((0, jsx_runtime_1.jsx)("button", { "aria-hidden": "true", className: Select_module_scss_1.default.srOnly })), (0, jsx_runtime_1.jsx)("div", { role: "listbox", className: Select_module_scss_1.default.commandList, children: inProgress ? ((0, jsx_runtime_1.jsx)("div", { className: Select_module_scss_1.default.loading, children: inProgressNotificationMessage })) : searchable && searchTerm ? (
355
+ // When searching, show only filtered options
356
+ filteredOptions.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { children: emptyListNode })) : (filteredOptions.map(({ value, label, enabled, keywords }, index) => ((0, jsx_runtime_1.jsx)(SelectOptionItem, { readOnly: readOnly, value: value, label: label, enabled: enabled, keywords: keywords, isHighlighted: selectedIndex === index, itemIndex: index }, value))))) : (
357
+ // When not searching, show all children (includes Options and other components like Button)
358
+ (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [children, options.size === 0 && (0, jsx_runtime_1.jsx)("div", { children: emptyListNode })] })) })] }) }) }))] }) }), !open && ((0, jsx_runtime_1.jsx)("div", { style: { display: "none" }, children: (0, jsx_runtime_1.jsx)(OptionTypeProvider_1.default, { Component: HiddenOption_1.HiddenOption, children: children }) }))] }) }));
300
359
  });
360
+ // Visible option component for rendering items in the dropdown (used by OptionTypeProvider)
361
+ function VisibleSelectOption(option) {
362
+ const { value, label, enabled = true, children } = option;
363
+ const { onOptionAdd } = (0, OptionContext_1.useOption)();
364
+ const { value: selectedValue, onChange, multiSelect, readOnly, setOpen, highlightedValue, optionRenderer, } = (0, SelectContext_1.useSelect)();
365
+ const optionRef = (0, react_1.useRef)(null);
366
+ const opt = (0, react_1.useMemo)(() => {
367
+ return Object.assign(Object.assign({}, option), { label: label !== null && label !== void 0 ? label : "", keywords: option.keywords || [label !== null && label !== void 0 ? label : ""] });
368
+ }, [option, label]);
369
+ (0, react_1.useEffect)(() => {
370
+ onOptionAdd(opt);
371
+ // Don't remove options when component unmounts - they should persist
372
+ }, [opt, onOptionAdd]);
373
+ const selected = (0, react_1.useMemo)(() => {
374
+ return Array.isArray(selectedValue) && multiSelect
375
+ ? selectedValue.map((v) => String(v)).includes(value)
376
+ : String(selectedValue) === String(value);
377
+ }, [selectedValue, value, multiSelect]);
378
+ const isHighlighted = (0, react_1.useMemo)(() => {
379
+ return highlightedValue !== undefined && String(highlightedValue) === String(value);
380
+ }, [highlightedValue, value]);
381
+ // Scroll into view when highlighted
382
+ (0, react_1.useEffect)(() => {
383
+ if (isHighlighted && optionRef.current) {
384
+ optionRef.current.scrollIntoView({ block: "nearest", behavior: "smooth" });
385
+ }
386
+ }, [isHighlighted]);
387
+ const handleClick = () => {
388
+ if (readOnly) {
389
+ setOpen(false);
390
+ return;
391
+ }
392
+ if (enabled) {
393
+ onChange(value);
394
+ }
395
+ };
396
+ return ((0, jsx_runtime_1.jsx)("div", { ref: optionRef, role: "option", "aria-disabled": !enabled, "aria-selected": selected, className: (0, classnames_1.default)(Select_module_scss_1.default.multiSelectOption, {
397
+ [Select_module_scss_1.default.disabledOption]: !enabled,
398
+ [Select_module_scss_1.default.highlighted]: isHighlighted,
399
+ }), onMouseDown: (e) => {
400
+ e.preventDefault();
401
+ e.stopPropagation();
402
+ }, onClick: handleClick, "data-state": selected ? "checked" : undefined, children: (0, jsx_runtime_1.jsx)("div", { className: Select_module_scss_1.default.multiSelectOptionContent, children: optionRenderer ? (optionRenderer({ label, value, enabled }, selectedValue, false)) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [children || label, selected && (0, jsx_runtime_1.jsx)(IconNative_1.default, { name: "checkmark" })] })) }) }));
403
+ }
404
+ // Internal option component for rendering items in the dropdown
405
+ function SelectOptionItem(option) {
406
+ const { value, label, enabled = true, readOnly, children, isHighlighted = false, itemIndex, } = option;
407
+ const { value: selectedValue, onChange, multiSelect, setOpen, setSelectedIndex, optionRenderer, } = (0, SelectContext_1.useSelect)();
408
+ const optionRef = (0, react_1.useRef)(null);
409
+ const selected = (0, react_1.useMemo)(() => {
410
+ return Array.isArray(selectedValue) && multiSelect
411
+ ? selectedValue.map((v) => String(v)).includes(value)
412
+ : String(selectedValue) === String(value);
413
+ }, [selectedValue, value, multiSelect]);
414
+ // Scroll into view when highlighted
415
+ (0, react_1.useEffect)(() => {
416
+ if (isHighlighted && optionRef.current) {
417
+ optionRef.current.scrollIntoView({ block: "nearest", behavior: "smooth" });
418
+ }
419
+ }, [isHighlighted]);
420
+ const handleClick = () => {
421
+ if (readOnly) {
422
+ setOpen(false);
423
+ return;
424
+ }
425
+ if (enabled) {
426
+ onChange(value);
427
+ }
428
+ };
429
+ return ((0, jsx_runtime_1.jsx)("div", { ref: optionRef, role: "option", "aria-disabled": !enabled, "aria-selected": selected, className: (0, classnames_1.default)(Select_module_scss_1.default.multiSelectOption, {
430
+ [Select_module_scss_1.default.disabledOption]: !enabled,
431
+ [Select_module_scss_1.default.highlighted]: isHighlighted,
432
+ }), onMouseDown: (e) => {
433
+ e.preventDefault();
434
+ e.stopPropagation();
435
+ }, onMouseEnter: () => {
436
+ if (itemIndex !== undefined && setSelectedIndex && enabled) {
437
+ setSelectedIndex(itemIndex);
438
+ }
439
+ }, onClick: handleClick, "data-state": selected ? "checked" : undefined, children: (0, jsx_runtime_1.jsx)("div", { className: Select_module_scss_1.default.multiSelectOptionContent, children: optionRenderer ? (optionRenderer({ label, value, enabled }, selectedValue, false)) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [children || label, selected && (0, jsx_runtime_1.jsx)(IconNative_1.default, { name: "checkmark" })] })) }) }));
440
+ }