Skip to content

Commit 903e8c6

Browse files
Convert dropdown to a full component
1 parent d5c4f33 commit 903e8c6

3 files changed

Lines changed: 95 additions & 62 deletions

File tree

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
1+
import * as React from "react";
2+
import { ChangeEvent } from "react";
13
import styled from "styled-components";
24

5+
const StyledDropdown = styled.select`
6+
width: 100%;
7+
height: calc(var(--input-height) * 1px);
8+
background: var(--dropdown-background);
9+
color: var(--foreground);
10+
font-family: var(--font-family);
11+
border: none;
12+
padding: 2px 6px 2px 8px;
13+
`;
14+
15+
type Props = {
16+
value: string | undefined;
17+
options: Array<{ value: string; label: string }>;
18+
disabled?: boolean;
19+
onChange: (event: ChangeEvent<HTMLSelectElement>) => void;
20+
};
21+
322
/**
4-
* Styled to look like a `VSCodeDropdown`.
23+
* A dropdown implementation styled to look like `VSCodeDropdown`.
524
*
625
* The reason for doing this is that `VSCodeDropdown` doesn't handle fitting into
726
* available space and truncating content, and this leads to breaking the
@@ -10,12 +29,22 @@ import styled from "styled-components";
1029
* See https://github.com/github/vscode-codeql/pull/2582#issuecomment-1622164429
1130
* for more info on the problem and other potential solutions.
1231
*/
13-
export const Dropdown = styled.select`
14-
width: 100%;
15-
height: calc(var(--input-height) * 1px);
16-
background: var(--dropdown-background);
17-
color: var(--foreground);
18-
font-family: var(--font-family);
19-
border: none;
20-
padding: 2px 6px 2px 8px;
21-
`;
32+
export function Dropdown({ value, options, disabled, onChange }: Props) {
33+
return (
34+
<StyledDropdown
35+
value={disabled ? undefined : value}
36+
disabled={disabled}
37+
onChange={onChange}
38+
>
39+
{!disabled && (
40+
<>
41+
{options.map((option) => (
42+
<option key={option.value} value={option.value}>
43+
{option.label}
44+
</option>
45+
))}
46+
</>
47+
)}
48+
</StyledDropdown>
49+
);
50+
}

extensions/ql-vscode/src/view/data-extensions-editor/KindInput.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from "react";
2-
import { ChangeEvent, useCallback, useEffect } from "react";
2+
import { ChangeEvent, useCallback, useEffect, useMemo } from "react";
33

44
import type { ModeledMethod } from "../../data-extensions-editor/modeled-method";
55
import { Dropdown } from "../common/Dropdown";
@@ -13,6 +13,11 @@ type Props = {
1313
};
1414

1515
export const KindInput = ({ kinds, value, disabled, onChange }: Props) => {
16+
const options = useMemo(
17+
() => kinds.map((kind) => ({ value: kind, label: kind })),
18+
[kinds],
19+
);
20+
1621
const handleInput = useCallback(
1722
(e: ChangeEvent<HTMLSelectElement>) => {
1823
const target = e.target as HTMLSelectElement;
@@ -33,16 +38,11 @@ export const KindInput = ({ kinds, value, disabled, onChange }: Props) => {
3338
}, [value, kinds, onChange]);
3439

3540
return (
36-
<Dropdown value={value} disabled={disabled} onChange={handleInput}>
37-
{!disabled && (
38-
<>
39-
{kinds.map((kind) => (
40-
<option key={kind} value={kind}>
41-
{kind}
42-
</option>
43-
))}
44-
</>
45-
)}
46-
</Dropdown>
41+
<Dropdown
42+
value={value}
43+
options={options}
44+
disabled={disabled}
45+
onChange={handleInput}
46+
/>
4747
);
4848
};

extensions/ql-vscode/src/view/data-extensions-editor/MethodRow.tsx

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,44 @@ export const MethodRow = ({
141141
const showModelTypeCell =
142142
!externalApiUsage.supported ||
143143
(modeledMethod && modeledMethod?.type !== "none");
144+
const modelTypeOptions = useMemo(
145+
() => [
146+
{ value: "none", label: "Unmodeled" },
147+
{ value: "source", label: "Source" },
148+
{ value: "sink", label: "Sink" },
149+
{ value: "summary", label: "Flow summary" },
150+
{ value: "neutral", label: "Neutral" },
151+
],
152+
[],
153+
);
154+
144155
const showInputCell =
145156
modeledMethod?.type && ["sink", "summary"].includes(modeledMethod?.type);
157+
const inputOptions = useMemo(
158+
() => [
159+
{ value: "Argument[this]", label: "Argument[this]" },
160+
...argumentsList.map((argument, index) => ({
161+
value: `Argument[${index}]`,
162+
label: `Argument[${index}]: ${argument}`,
163+
})),
164+
],
165+
[argumentsList],
166+
);
167+
146168
const showOutputCell =
147169
modeledMethod?.type && ["source", "summary"].includes(modeledMethod?.type);
170+
const outputOptions = useMemo(
171+
() => [
172+
{ value: "ReturnValue", label: "ReturnValue" },
173+
{ value: "Argument[this]", label: "Argument[this]" },
174+
...argumentsList.map((argument, index) => ({
175+
value: `Argument[${index}]`,
176+
label: `Argument[${index}]: ${argument}`,
177+
})),
178+
],
179+
[argumentsList],
180+
);
181+
148182
const showKindCell = predicate?.supportedKinds;
149183

150184
return (
@@ -165,62 +199,32 @@ export const MethodRow = ({
165199
</ApiOrMethodCell>
166200
<VSCodeDataGridCell gridColumn={2}>
167201
<Dropdown
168-
value={showModelTypeCell ? modeledMethod?.type ?? "none" : undefined}
202+
value={modeledMethod?.type ?? "none"}
203+
options={modelTypeOptions}
169204
disabled={!showModelTypeCell}
170205
onChange={handleTypeInput}
171-
>
172-
{showModelTypeCell && (
173-
<>
174-
<option value="none">Unmodeled</option>
175-
<option value="source">Source</option>
176-
<option value="sink">Sink</option>
177-
<option value="summary">Flow summary</option>
178-
<option value="neutral">Neutral</option>
179-
</>
180-
)}
181-
</Dropdown>
206+
/>
182207
</VSCodeDataGridCell>
183208
<VSCodeDataGridCell gridColumn={3}>
184209
<Dropdown
185-
value={showInputCell ? modeledMethod?.input : undefined}
210+
value={modeledMethod?.input}
211+
options={inputOptions}
186212
disabled={!showInputCell}
187213
onChange={handleInputInput}
188-
>
189-
{showInputCell && (
190-
<>
191-
<option value="Argument[this]">Argument[this]</option>
192-
{argumentsList.map((argument, index) => (
193-
<option key={argument} value={`Argument[${index}]`}>
194-
Argument[{index}]: {argument}
195-
</option>
196-
))}
197-
</>
198-
)}
199-
</Dropdown>
214+
/>
200215
</VSCodeDataGridCell>
201216
<VSCodeDataGridCell gridColumn={4}>
202217
<Dropdown
203-
value={showOutputCell ? modeledMethod?.output : undefined}
218+
value={modeledMethod?.output}
219+
options={outputOptions}
204220
disabled={!showOutputCell}
205221
onChange={handleOutputInput}
206-
>
207-
{showOutputCell && (
208-
<>
209-
<option value="ReturnValue">ReturnValue</option>
210-
<option value="Argument[this]">Argument[this]</option>
211-
{argumentsList.map((argument, index) => (
212-
<option key={argument} value={`Argument[${index}]`}>
213-
Argument[{index}]: {argument}
214-
</option>
215-
))}
216-
</>
217-
)}
218-
</Dropdown>
222+
/>
219223
</VSCodeDataGridCell>
220224
<VSCodeDataGridCell gridColumn={5}>
221225
<KindInput
222226
kinds={predicate?.supportedKinds || []}
223-
value={showKindCell && modeledMethod?.kind}
227+
value={modeledMethod?.kind}
224228
disabled={!showKindCell}
225229
onChange={handleKindChange}
226230
/>

0 commit comments

Comments
 (0)