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.
- package/dist/lib/{index-DoIVkz5T.mjs → index-DHXWMb-6.mjs} +12924 -12882
- package/dist/lib/index.css +1 -1
- package/dist/lib/{initMock-CSGEd746.mjs → initMock-TxnkId6_.mjs} +1 -1
- package/dist/lib/language-server-web-worker.mjs +1 -1
- package/dist/lib/language-server.mjs +1 -1
- package/dist/lib/{metadata-utils-Dx-2qZBh.mjs → metadata-utils-DXUdlyja.mjs} +6 -6
- package/dist/lib/{server-common--BHVvP1o.mjs → server-common-CtpN0Z4h.mjs} +1 -1
- package/dist/lib/xmlui.d.ts +1 -0
- package/dist/lib/xmlui.mjs +1 -1
- package/dist/metadata/{collectedComponentMetadata-B3Hs8_cV.mjs → collectedComponentMetadata-BgHIc2Iu.mjs} +12871 -12829
- package/dist/metadata/{initMock-DQrGwkya.mjs → initMock-B3UDa-rw.mjs} +1 -1
- package/dist/metadata/style.css +1 -1
- package/dist/metadata/xmlui-metadata.mjs +1 -1
- package/dist/metadata/xmlui-metadata.umd.js +3 -3
- package/dist/scripts/package.json +1 -1
- package/dist/scripts/src/components/App/App.spec.js +100 -0
- package/dist/scripts/src/components/App/AppNative.js +13 -2
- package/dist/scripts/src/components/AppHeader/AppHeader.js +1 -6
- package/dist/scripts/src/components/AppHeader/AppHeaderNative.js +7 -7
- package/dist/scripts/src/components/AutoComplete/AutoComplete.spec.js +1 -1
- package/dist/scripts/src/components/AutoComplete/AutoCompleteNative.js +30 -5
- package/dist/scripts/src/components/Form/Form.spec.js +2 -2
- package/dist/scripts/src/components/FormItem/FormItemNative.js +5 -1
- package/dist/scripts/src/components/Heading/Heading.js +45 -5
- package/dist/scripts/src/components/Heading/Heading.spec.js +82 -0
- package/dist/scripts/src/components/ModalDialog/ModalDialog.js +4 -6
- package/dist/scripts/src/components/ModalDialog/ModalDialog.spec.js +19 -0
- package/dist/scripts/src/components/NavGroup/NavGroup.spec.js +103 -11
- package/dist/scripts/src/components/NavGroup/NavGroupNative.js +6 -1
- package/dist/scripts/src/components/Option/Option.spec.js +3 -1
- package/dist/scripts/src/components/Select/HiddenOption.js +3 -3
- package/dist/scripts/src/components/Select/Select.js +2 -3
- package/dist/scripts/src/components/Select/Select.spec.js +4 -6
- package/dist/scripts/src/components/Select/SelectNative.js +187 -47
- package/dist/scripts/src/components-core/rendering/ComponentAdapter.js +11 -0
- package/dist/scripts/src/components-core/rendering/Container.js +3 -4
- package/dist/scripts/src/components-core/rendering/StateContainer.js +16 -18
- package/dist/scripts/src/components-core/rendering/reducer.js +6 -3
- package/dist/scripts/src/components-core/rendering/valueExtractor.js +9 -1
- package/dist/scripts/src/components-core/utils/extractParam.js +2 -1
- package/dist/scripts/src/testing/ComponentDrivers.js +1 -1
- package/dist/standalone/xmlui-standalone.es.d.ts +1 -0
- package/dist/standalone/xmlui-standalone.umd.js +35 -35
- package/package.json +1 -1
- package/dist/scripts/src/components/Select/MultiSelectOption.js +0 -42
- package/dist/scripts/src/components/Select/SelectOption.js +0 -34
- 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
|
|
105
|
+
(0, fixtures_1.test)("nested initiallyExpanded works", (_a) => __awaiter(void 0, [_a], void 0, function* ({ initTestBed, page }) {
|
|
107
106
|
yield initTestBed(`
|
|
108
|
-
<
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
<
|
|
112
|
-
|
|
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
|
-
|
|
115
|
-
</NavGroup>
|
|
116
|
+
</Stack>
|
|
116
117
|
`);
|
|
117
|
-
|
|
118
|
-
yield (0, fixtures_1.expect)(
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
18
|
-
}, [opt, onOptionAdd
|
|
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:
|
|
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:
|
|
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
|
|
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
|
|
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)(
|
|
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)(
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
100
|
-
const [open, setOpen] = (0,
|
|
101
|
-
const [width, setWidth] = (0,
|
|
102
|
-
const observer = (0,
|
|
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,
|
|
105
|
-
const
|
|
106
|
-
const [
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
268
|
-
const onOptionAdd = (0,
|
|
269
|
-
setOptions((prev) =>
|
|
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,
|
|
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,
|
|
290
|
+
const optionContextValue = (0, react_1.useMemo)(() => ({
|
|
279
291
|
onOptionAdd,
|
|
280
292
|
onOptionRemove,
|
|
281
293
|
}), [onOptionAdd, onOptionRemove]);
|
|
282
|
-
const selectContextValue = (0,
|
|
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
|
-
}), [
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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
|
-
}
|
|
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
|
+
}
|