zudoku 0.25.2 → 0.26.0
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/app/demo.js +0 -1
- package/dist/app/demo.js.map +1 -1
- package/dist/app/standalone.js +0 -1
- package/dist/app/standalone.js.map +1 -1
- package/dist/cli/dev/handler.js +2 -2
- package/dist/cli/dev/handler.js.map +1 -1
- package/dist/config/validators/InputSidebarSchema.d.ts +2 -2
- package/dist/config/validators/common.d.ts +28 -28
- package/dist/config/validators/icon-types.d.ts +1 -1
- package/dist/config/validators/validate.d.ts +16 -16
- package/dist/lib/components/navigation/SidebarCategory.js +1 -1
- package/dist/lib/components/navigation/SidebarCategory.js.map +1 -1
- package/dist/lib/oas/graphql/index.d.ts +3 -0
- package/dist/lib/oas/graphql/index.js +12 -13
- package/dist/lib/oas/graphql/index.js.map +1 -1
- package/dist/lib/plugins/openapi/ColorizedParam.d.ts +10 -2
- package/dist/lib/plugins/openapi/ColorizedParam.js +16 -7
- package/dist/lib/plugins/openapi/ColorizedParam.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationList.js +3 -0
- package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
- package/dist/lib/plugins/openapi/ParameterListItem.js +3 -2
- package/dist/lib/plugins/openapi/ParameterListItem.js.map +1 -1
- package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js +2 -0
- package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js.map +1 -1
- package/dist/lib/plugins/openapi/RequestBodySidecarBox.d.ts +3 -2
- package/dist/lib/plugins/openapi/RequestBodySidecarBox.js +3 -6
- package/dist/lib/plugins/openapi/RequestBodySidecarBox.js.map +1 -1
- package/dist/lib/plugins/openapi/ResponsesSidecarBox.js +2 -6
- package/dist/lib/plugins/openapi/ResponsesSidecarBox.js.map +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js +9 -6
- package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
- package/dist/lib/plugins/openapi/SidecarBox.js +1 -1
- package/dist/lib/plugins/openapi/SidecarBox.js.map +1 -1
- package/dist/lib/plugins/openapi/{ExampleDisplay.d.ts → SidecarExamples.d.ts} +3 -6
- package/dist/lib/plugins/openapi/SidecarExamples.js +65 -0
- package/dist/lib/plugins/openapi/SidecarExamples.js.map +1 -0
- package/dist/lib/plugins/openapi/client/GraphQLClient.d.ts +1 -1
- package/dist/lib/plugins/openapi/client/GraphQLClient.js +22 -93
- package/dist/lib/plugins/openapi/client/GraphQLClient.js.map +1 -1
- package/dist/lib/plugins/openapi/client/createServer.d.ts +2 -1
- package/dist/lib/plugins/openapi/client/createServer.js +5 -2
- package/dist/lib/plugins/openapi/client/createServer.js.map +1 -1
- package/dist/lib/plugins/openapi/client/useCreateQuery.d.ts +1 -1
- package/dist/lib/plugins/openapi/client/useCreateQuery.js +2 -13
- package/dist/lib/plugins/openapi/client/useCreateQuery.js.map +1 -1
- package/dist/lib/plugins/openapi/index.d.ts +2 -1
- package/dist/lib/plugins/openapi/index.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/EnumSelector.d.ts +8 -0
- package/dist/lib/plugins/openapi/playground/EnumSelector.js +21 -0
- package/dist/lib/plugins/openapi/playground/EnumSelector.js.map +1 -0
- package/dist/lib/plugins/openapi/playground/PathParams.js +9 -4
- package/dist/lib/plugins/openapi/playground/PathParams.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/Playground.d.ts +3 -0
- package/dist/lib/plugins/openapi/playground/Playground.js +5 -2
- package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/QueryParams.js +23 -8
- package/dist/lib/plugins/openapi/playground/QueryParams.js.map +1 -1
- package/dist/lib/plugins/openapi/schema/SchemaComponents.js +2 -1
- package/dist/lib/plugins/openapi/schema/SchemaComponents.js.map +1 -1
- package/dist/lib/plugins/openapi/util/generateSchemaExample.js +19 -11
- package/dist/lib/plugins/openapi/util/generateSchemaExample.js.map +1 -1
- package/dist/lib/ui/Badge.d.ts +1 -1
- package/dist/lib/ui/Badge.js +2 -1
- package/dist/lib/ui/Badge.js.map +1 -1
- package/dist/lib/ui/Button.d.ts +1 -1
- package/dist/lib/ui/Checkbox.d.ts +8 -2
- package/dist/lib/ui/Checkbox.js +13 -1
- package/dist/lib/ui/Checkbox.js.map +1 -1
- package/dist/lib/util/traverse.d.ts +8 -1
- package/dist/lib/util/traverse.js +7 -3
- package/dist/lib/util/traverse.js.map +1 -1
- package/dist/vite/api/schema-codegen.d.ts +12 -0
- package/dist/vite/api/schema-codegen.js +62 -0
- package/dist/vite/api/schema-codegen.js.map +1 -0
- package/dist/vite/api/schema-codegen.test.d.ts +1 -0
- package/dist/vite/api/schema-codegen.test.js +247 -0
- package/dist/vite/api/schema-codegen.test.js.map +1 -0
- package/dist/vite/config.js +0 -7
- package/dist/vite/config.js.map +1 -1
- package/dist/vite/config.test.js +5 -1
- package/dist/vite/config.test.js.map +1 -1
- package/dist/vite/plugin-api.js +110 -82
- package/dist/vite/plugin-api.js.map +1 -1
- package/dist/vite/plugin-component.js +0 -1
- package/dist/vite/plugin-component.js.map +1 -1
- package/lib/{AnchorLink-DFZZbmvr.js → AnchorLink-_Vu02ceN.js} +3 -3
- package/lib/{AnchorLink-DFZZbmvr.js.map → AnchorLink-_Vu02ceN.js.map} +1 -1
- package/lib/{AuthenticationPlugin-D7G3me8L.js → AuthenticationPlugin-DNXBcsVN.js} +4 -4
- package/lib/{AuthenticationPlugin-D7G3me8L.js.map → AuthenticationPlugin-DNXBcsVN.js.map} +1 -1
- package/lib/{Button-DeAoTouo.js → Button-oroWHXAy.js} +3 -3
- package/lib/{Button-DeAoTouo.js.map → Button-oroWHXAy.js.map} +1 -1
- package/lib/{CategoryHeading-CBconmtI.js → CategoryHeading-MYL1u_6K.js} +3 -3
- package/lib/{CategoryHeading-CBconmtI.js.map → CategoryHeading-MYL1u_6K.js.map} +1 -1
- package/lib/Command-D5DE0DD7.js +611 -0
- package/lib/Command-D5DE0DD7.js.map +1 -0
- package/lib/{Markdown-CZDLNOFc.js → Markdown-BrfrjEk_.js} +1041 -1041
- package/lib/{Markdown-CZDLNOFc.js.map → Markdown-BrfrjEk_.js.map} +1 -1
- package/lib/{MdxPage-DKMbBROv.js → MdxPage-LNZLj_A5.js} +24 -24
- package/lib/{MdxPage-DKMbBROv.js.map → MdxPage-LNZLj_A5.js.map} +1 -1
- package/lib/{OperationList-BLdHAQ39.js → OperationList-PCwzTp1r.js} +1899 -1877
- package/lib/OperationList-PCwzTp1r.js.map +1 -0
- package/lib/{Route-DYwKZ_c_.js → Route-Pzk6qwIk.js} +5 -5
- package/lib/{Route-DYwKZ_c_.js.map → Route-Pzk6qwIk.js.map} +1 -1
- package/lib/{Select-B_IxRUUC.js → Select-DkOpAG0c.js} +36 -36
- package/lib/{Select-B_IxRUUC.js.map → Select-DkOpAG0c.js.map} +1 -1
- package/lib/{SlotletProvider-pfc9oejW.js → SlotletProvider-DPbx9KdU.js} +53 -53
- package/lib/{SlotletProvider-pfc9oejW.js.map → SlotletProvider-DPbx9KdU.js.map} +1 -1
- package/lib/{Spinner-DuxJLLNE.js → Spinner-C5gHXrVz.js} +2 -2
- package/lib/{Spinner-DuxJLLNE.js.map → Spinner-C5gHXrVz.js.map} +1 -1
- package/lib/{SyntaxHighlight-Bz-lOJtH.js → SyntaxHighlight-CJCSPG1F.js} +297 -301
- package/lib/{SyntaxHighlight-Bz-lOJtH.js.map → SyntaxHighlight-CJCSPG1F.js.map} +1 -1
- package/lib/{ZudokuContext-hmLMUdf2.js → ZudokuContext-D3ayHjP-.js} +357 -356
- package/lib/ZudokuContext-D3ayHjP-.js.map +1 -0
- package/lib/{chunk-D52XG6IA-Dl7HLe6j.js → chunk-SYFQ2XB5-KWlHsT7t.js} +407 -410
- package/lib/chunk-SYFQ2XB5-KWlHsT7t.js.map +1 -0
- package/lib/context-rwLGh-6_.js +22 -0
- package/lib/{context-h_UkBLvr.js.map → context-rwLGh-6_.js.map} +1 -1
- package/lib/{createServer-Bf5_6o6G.js → createServer-BcaswoFO.js} +4363 -5302
- package/lib/createServer-BcaswoFO.js.map +1 -0
- package/lib/{hook-CHq7pFyz.js → hook-DUyACbIK.js} +17 -17
- package/lib/{hook-CHq7pFyz.js.map → hook-DUyACbIK.js.map} +1 -1
- package/lib/index-CaILD1AV.js +1292 -0
- package/lib/index-CaILD1AV.js.map +1 -0
- package/lib/index-Djenk2Hj.js +36 -0
- package/lib/{index-CPNSgwSb.js.map → index-Djenk2Hj.js.map} +1 -1
- package/lib/{index-CBXSgjaE.js → index-Dl3Yl0yb.js} +65 -69
- package/lib/index-Dl3Yl0yb.js.map +1 -0
- package/lib/index-TaRXY2w1.js +43 -0
- package/lib/index-TaRXY2w1.js.map +1 -0
- package/lib/{index.esm-BSV1C092.js → index.esm-9-TF9KQB.js} +52 -52
- package/lib/{index.esm-BSV1C092.js.map → index.esm-9-TF9KQB.js.map} +1 -1
- package/lib/index.esm-CrSoEshU.js +1207 -0
- package/lib/index.esm-CrSoEshU.js.map +1 -0
- package/lib/{jsx-runtime-Dx-03ztt.js → jsx-runtime-Bdg6XQ1m.js} +135 -135
- package/lib/{jsx-runtime-Dx-03ztt.js.map → jsx-runtime-Bdg6XQ1m.js.map} +1 -1
- package/lib/post-processors/removeExtensions.js +3 -3
- package/lib/post-processors/traverse.js +11 -8
- package/lib/post-processors/traverse.js.map +1 -1
- package/lib/{prism-bash.min-DadFsM4Z.js → prism-bash.min-HHIMdNJ_.js} +4 -4
- package/lib/{prism-bash.min-DadFsM4Z.js.map → prism-bash.min-HHIMdNJ_.js.map} +1 -1
- package/lib/{prism-csharp.min-DUwvItt4.js → prism-csharp.min-bQAo2pmx.js} +33 -33
- package/lib/{prism-csharp.min-DUwvItt4.js.map → prism-csharp.min-bQAo2pmx.js.map} +1 -1
- package/lib/{prism-java.min-BtgBR4yd.js → prism-java.min-BpvsOuIa.js} +12 -12
- package/lib/{prism-java.min-BtgBR4yd.js.map → prism-java.min-BpvsOuIa.js.map} +1 -1
- package/lib/{prism-markdown.min-F3U-vPBi.js → prism-markdown.min-C0Qn0m-5.js} +30 -30
- package/lib/{prism-markdown.min-F3U-vPBi.js.map → prism-markdown.min-C0Qn0m-5.js.map} +1 -1
- package/lib/{prism-ruby.min-DeDXCp1r.js → prism-ruby.min-Dx9KO9ds.js} +16 -16
- package/lib/{prism-ruby.min-DeDXCp1r.js.map → prism-ruby.min-Dx9KO9ds.js.map} +1 -1
- package/lib/prism-typescript.min-CD7H2IYQ.js.map +1 -1
- package/lib/state-mM7uaXTW.js +202 -0
- package/lib/state-mM7uaXTW.js.map +1 -0
- package/lib/ui/Accordion.js +1 -1
- package/lib/ui/ActionButton.js +3 -3
- package/lib/ui/Alert.js +2 -2
- package/lib/ui/AlertDialog.js +1 -1
- package/lib/ui/Badge.js +4 -3
- package/lib/ui/Badge.js.map +1 -1
- package/lib/ui/Breadcrumb.js +1 -1
- package/lib/ui/Button.js +2 -2
- package/lib/ui/Callout.js +1 -1
- package/lib/ui/Card.js +1 -1
- package/lib/ui/Carousel.js +3 -3
- package/lib/ui/Carousel.js.map +1 -1
- package/lib/ui/Checkbox.js +26 -15
- package/lib/ui/Checkbox.js.map +1 -1
- package/lib/ui/Command.js +14 -550
- package/lib/ui/Command.js.map +1 -1
- package/lib/ui/Dialog.js +1 -1
- package/lib/ui/Drawer.js +520 -519
- package/lib/ui/Drawer.js.map +1 -1
- package/lib/ui/DropdownMenu.js +1 -1
- package/lib/ui/Form.js +2 -2
- package/lib/ui/HoverCard.js +1 -1
- package/lib/ui/Input.js +1 -1
- package/lib/ui/Label.js +2 -2
- package/lib/ui/Pagination.js +7 -7
- package/lib/ui/Popover.js +1 -1
- package/lib/ui/Progress.js +1 -1
- package/lib/ui/RadioGroup.js +1 -1
- package/lib/ui/ScrollArea.js +1 -1
- package/lib/ui/Select.js +1 -1
- package/lib/ui/Skeleton.js +1 -1
- package/lib/ui/Slider.js +1 -1
- package/lib/ui/Switch.js +1 -1
- package/lib/ui/Tabs.js +1 -1
- package/lib/ui/Textarea.js +1 -1
- package/lib/ui/Toggle.js +2 -2
- package/lib/ui/ToggleGroup.js +1 -1
- package/lib/ui/Tooltip.js +1 -1
- package/lib/{useExposedProps-DE9lR6MF.js → useExposedProps-BBHR7aLM.js} +2 -2
- package/lib/{useExposedProps-DE9lR6MF.js.map → useExposedProps-BBHR7aLM.js.map} +1 -1
- package/lib/zudoku.auth-auth0.js +1 -1
- package/lib/zudoku.auth-clerk.js +18 -18
- package/lib/zudoku.auth-openid.js +5 -5
- package/lib/zudoku.components.js +492 -477
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.plugin-api-catalog.js +5 -5
- package/lib/zudoku.plugin-api-keys.js +7 -7
- package/lib/zudoku.plugin-custom-pages.js +3 -3
- package/lib/zudoku.plugin-markdown.js +2 -2
- package/lib/zudoku.plugin-openapi.js +5 -5
- package/lib/zudoku.plugin-redirect.js +1 -1
- package/lib/zudoku.plugin-search-inkeep.js +9 -9
- package/package.json +48 -53
- package/src/app/demo.tsx +0 -1
- package/src/app/standalone.tsx +0 -1
- package/src/lib/components/navigation/SidebarCategory.tsx +2 -2
- package/src/lib/oas/graphql/index.ts +19 -15
- package/src/lib/plugins/openapi/ColorizedParam.tsx +29 -12
- package/src/lib/plugins/openapi/OperationList.tsx +4 -0
- package/src/lib/plugins/openapi/ParameterListItem.tsx +5 -7
- package/src/lib/plugins/openapi/PlaygroundDialogWrapper.tsx +2 -0
- package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +9 -8
- package/src/lib/plugins/openapi/ResponsesSidecarBox.tsx +5 -8
- package/src/lib/plugins/openapi/Sidecar.tsx +14 -7
- package/src/lib/plugins/openapi/SidecarBox.tsx +1 -1
- package/src/lib/plugins/openapi/SidecarExamples.tsx +163 -0
- package/src/lib/plugins/openapi/client/GraphQLClient.tsx +28 -120
- package/src/lib/plugins/openapi/client/createServer.ts +6 -2
- package/src/lib/plugins/openapi/client/useCreateQuery.ts +2 -17
- package/src/lib/plugins/openapi/index.tsx +2 -1
- package/src/lib/plugins/openapi/playground/EnumSelector.tsx +86 -0
- package/src/lib/plugins/openapi/playground/PathParams.tsx +72 -64
- package/src/lib/plugins/openapi/playground/Playground.tsx +26 -13
- package/src/lib/plugins/openapi/playground/QueryParams.tsx +102 -73
- package/src/lib/plugins/openapi/schema/SchemaComponents.tsx +4 -7
- package/src/lib/plugins/openapi/util/generateSchemaExample.ts +26 -11
- package/src/lib/ui/Badge.tsx +2 -1
- package/src/lib/ui/Checkbox.tsx +24 -7
- package/src/lib/util/traverse.ts +15 -5
- package/dist/lib/plugins/openapi/ExampleDisplay.js +0 -78
- package/dist/lib/plugins/openapi/ExampleDisplay.js.map +0 -1
- package/dist/lib/plugins/openapi/client/worker.d.ts +0 -4
- package/dist/lib/plugins/openapi/client/worker.js +0 -29
- package/dist/lib/plugins/openapi/client/worker.js.map +0 -1
- package/dist/lib/plugins/openapi-worker.d.ts +0 -1
- package/dist/lib/plugins/openapi-worker.js +0 -8
- package/dist/lib/plugins/openapi-worker.js.map +0 -1
- package/lib/Dialog-Bxv1yEIg.js +0 -67
- package/lib/Dialog-Bxv1yEIg.js.map +0 -1
- package/lib/OperationList-BLdHAQ39.js.map +0 -1
- package/lib/ZudokuContext-hmLMUdf2.js.map +0 -1
- package/lib/assets/index-C7jnHK4b.js +0 -4841
- package/lib/assets/index-C7jnHK4b.js.map +0 -1
- package/lib/assets/worker-Cbp2r2BQ.js +0 -18592
- package/lib/assets/worker-Cbp2r2BQ.js.map +0 -1
- package/lib/chunk-D52XG6IA-Dl7HLe6j.js.map +0 -1
- package/lib/context-h_UkBLvr.js +0 -22
- package/lib/createServer-Bf5_6o6G.js.map +0 -1
- package/lib/index-BNx95gkf.js +0 -1284
- package/lib/index-BNx95gkf.js.map +0 -1
- package/lib/index-CBXSgjaE.js.map +0 -1
- package/lib/index-CPNSgwSb.js +0 -36
- package/lib/index-DyBL--Kz.js +0 -826
- package/lib/index-DyBL--Kz.js.map +0 -1
- package/lib/index.esm-BnnBRKJX.js +0 -1214
- package/lib/index.esm-BnnBRKJX.js.map +0 -1
- package/lib/state-CFQsUZUP.js +0 -202
- package/lib/state-CFQsUZUP.js.map +0 -1
- package/lib/zudoku.openapi-worker.js +0 -15
- package/lib/zudoku.openapi-worker.js.map +0 -1
- package/src/lib/plugins/openapi/ExampleDisplay.tsx +0 -163
- package/src/lib/plugins/openapi/client/worker.ts +0 -44
- package/src/lib/plugins/openapi-worker.ts +0 -11
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
2
2
|
import { HTTPSnippet } from "@zudoku/httpsnippet";
|
|
3
|
-
import { Fragment, useMemo, useTransition } from "react";
|
|
3
|
+
import { Fragment, useMemo, useState, useTransition } from "react";
|
|
4
4
|
import { useSearchParams } from "react-router";
|
|
5
5
|
import { useSelectedServerStore } from "../../authentication/state.js";
|
|
6
6
|
import { SyntaxHighlight } from "../../components/SyntaxHighlight.js";
|
|
@@ -107,6 +107,7 @@ export const Sidecar = ({
|
|
|
107
107
|
|
|
108
108
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
109
109
|
const [, startTransition] = useTransition();
|
|
110
|
+
const [selectedExample, setSelectedExample] = useState<unknown>();
|
|
110
111
|
|
|
111
112
|
const selectedLang = searchParams.get("lang") ?? "shell";
|
|
112
113
|
|
|
@@ -141,9 +142,11 @@ export const Sidecar = ({
|
|
|
141
142
|
const { selectedServer } = useSelectedServerStore();
|
|
142
143
|
|
|
143
144
|
const code = useMemo(() => {
|
|
144
|
-
const example =
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
const example =
|
|
146
|
+
selectedExample ??
|
|
147
|
+
(requestBodyContent?.[0]?.schema
|
|
148
|
+
? generateSchemaExample(requestBodyContent[0].schema as SchemaObject)
|
|
149
|
+
: undefined);
|
|
147
150
|
|
|
148
151
|
const snippet = new HTTPSnippet({
|
|
149
152
|
method: operation.method.toLocaleUpperCase(),
|
|
@@ -166,6 +169,7 @@ export const Sidecar = ({
|
|
|
166
169
|
|
|
167
170
|
return getConverted(snippet, selectedLang);
|
|
168
171
|
}, [
|
|
172
|
+
selectedExample,
|
|
169
173
|
requestBodyContent,
|
|
170
174
|
operation.method,
|
|
171
175
|
operation.path,
|
|
@@ -181,7 +185,7 @@ export const Sidecar = ({
|
|
|
181
185
|
className="flex flex-col overflow-hidden sticky top-[--scroll-padding] gap-4"
|
|
182
186
|
>
|
|
183
187
|
<SidecarBox.Root>
|
|
184
|
-
<SidecarBox.Head className="flex justify-between items-center flex-nowrap py-
|
|
188
|
+
<SidecarBox.Head className="flex justify-between items-center flex-nowrap py-2.5 gap-2 text-xs">
|
|
185
189
|
<span className="font-mono break-words">
|
|
186
190
|
<span className={cn("font-semibold", methodTextColor)}>
|
|
187
191
|
{operation.method.toLocaleUpperCase()}
|
|
@@ -209,7 +213,7 @@ export const Sidecar = ({
|
|
|
209
213
|
/>
|
|
210
214
|
</CollapsibleCode>
|
|
211
215
|
</SidecarBox.Body>
|
|
212
|
-
<SidecarBox.Footer className="flex items-center text-xs gap-2 justify-end py-
|
|
216
|
+
<SidecarBox.Footer className="flex items-center text-xs gap-2 justify-end py-2.5">
|
|
213
217
|
<span>Show example in</span>
|
|
214
218
|
<SimpleSelect
|
|
215
219
|
className="self-start max-w-[150px]"
|
|
@@ -229,7 +233,10 @@ export const Sidecar = ({
|
|
|
229
233
|
)}
|
|
230
234
|
</SidecarBox.Root>
|
|
231
235
|
{isOnScreen && requestBodyContent && (
|
|
232
|
-
<RequestBodySidecarBox
|
|
236
|
+
<RequestBodySidecarBox
|
|
237
|
+
content={requestBodyContent}
|
|
238
|
+
onExampleChange={setSelectedExample}
|
|
239
|
+
/>
|
|
233
240
|
)}
|
|
234
241
|
{isOnScreen && operation.responses.length > 0 && (
|
|
235
242
|
<ResponsesSidecarBox
|
|
@@ -16,7 +16,7 @@ export const Root = ({ children, className }: BaseComponentProps) => (
|
|
|
16
16
|
export const Head = ({ children, className }: BaseComponentProps) => (
|
|
17
17
|
<div
|
|
18
18
|
className={cn(
|
|
19
|
-
"border-b bg-muted dark:bg-transparent text-card-foreground p-3",
|
|
19
|
+
"border-b bg-muted dark:bg-transparent text-card-foreground p-3 py-2.5",
|
|
20
20
|
className,
|
|
21
21
|
)}
|
|
22
22
|
>
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { SyntaxHighlight } from "../../components/SyntaxHighlight.js";
|
|
3
|
+
import { type SchemaObject } from "../../oas/graphql/index.js";
|
|
4
|
+
import { CollapsibleCode } from "./CollapsibleCode.js";
|
|
5
|
+
import type { OperationListItemResult } from "./OperationList.js";
|
|
6
|
+
import * as SidecarBox from "./SidecarBox.js";
|
|
7
|
+
import { SimpleSelect } from "./SimpleSelect.js";
|
|
8
|
+
import { generateSchemaExample } from "./util/generateSchemaExample.js";
|
|
9
|
+
|
|
10
|
+
export type Content = NonNullable<
|
|
11
|
+
NonNullable<OperationListItemResult["requestBody"]>["content"]
|
|
12
|
+
>;
|
|
13
|
+
export type Example = NonNullable<
|
|
14
|
+
NonNullable<Content[number]["examples"]>
|
|
15
|
+
>[number];
|
|
16
|
+
|
|
17
|
+
const formatForDisplay = (value: unknown): string => {
|
|
18
|
+
if (value == null) return "No example";
|
|
19
|
+
if (typeof value === "string") return value.trim();
|
|
20
|
+
return JSON.stringify(value, null, 2);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const getLanguage = (mediaType?: string): string => {
|
|
24
|
+
if (!mediaType) return "plain";
|
|
25
|
+
const languages: Record<string, string> = {
|
|
26
|
+
"application/json": "json",
|
|
27
|
+
"application/xml": "xml",
|
|
28
|
+
"application/x-yaml": "yaml",
|
|
29
|
+
"text/csv": "csv",
|
|
30
|
+
"application/javascript": "javascript",
|
|
31
|
+
"application/graphql": "graphql",
|
|
32
|
+
};
|
|
33
|
+
return languages[mediaType] ?? "plain";
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type SidecarExamplesProps = {
|
|
37
|
+
content: Content;
|
|
38
|
+
description?: string;
|
|
39
|
+
onExampleChange?: (example: unknown) => void;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const SidecarExamples = ({
|
|
43
|
+
content,
|
|
44
|
+
description,
|
|
45
|
+
onExampleChange,
|
|
46
|
+
}: SidecarExamplesProps) => {
|
|
47
|
+
const [selectedContentTypeIndex, setSelectedContentTypeIndex] = useState(0);
|
|
48
|
+
const [selectedExampleIndex, setSelectedExampleIndex] = useState(0);
|
|
49
|
+
|
|
50
|
+
// Get the effective content (handle single item array case)
|
|
51
|
+
const effectiveContent =
|
|
52
|
+
Array.isArray(content) && content.length === 1
|
|
53
|
+
? content[0]
|
|
54
|
+
: content[selectedContentTypeIndex];
|
|
55
|
+
|
|
56
|
+
// Get example value, with fallback to schema-generated example
|
|
57
|
+
const examples = effectiveContent?.examples ?? [];
|
|
58
|
+
const selectedExample = examples[selectedExampleIndex];
|
|
59
|
+
|
|
60
|
+
let exampleValue = undefined;
|
|
61
|
+
if (selectedExample) {
|
|
62
|
+
// If it's a wrapped example with a value field, use that
|
|
63
|
+
exampleValue =
|
|
64
|
+
"value" in selectedExample ? selectedExample.value : selectedExample;
|
|
65
|
+
} else if (effectiveContent?.schema) {
|
|
66
|
+
// No example provided, generate one from schema
|
|
67
|
+
exampleValue = generateSchemaExample(
|
|
68
|
+
effectiveContent.schema as SchemaObject,
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
onExampleChange?.(exampleValue);
|
|
74
|
+
}, [exampleValue, onExampleChange]);
|
|
75
|
+
|
|
76
|
+
const formattedExample = formatForDisplay(exampleValue);
|
|
77
|
+
const language = getLanguage(effectiveContent?.mediaType);
|
|
78
|
+
|
|
79
|
+
const hasContent = examples.length > 0 || content.length > 0;
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<>
|
|
83
|
+
<SidecarBox.Body className="p-0">
|
|
84
|
+
{selectedExample?.externalValue ? (
|
|
85
|
+
<div className="p-2">
|
|
86
|
+
<a
|
|
87
|
+
href={selectedExample.externalValue}
|
|
88
|
+
target="_blank"
|
|
89
|
+
rel="noopener noreferrer"
|
|
90
|
+
className="text-xs text-primary hover:underline"
|
|
91
|
+
>
|
|
92
|
+
View External Example →
|
|
93
|
+
</a>
|
|
94
|
+
</div>
|
|
95
|
+
) : (
|
|
96
|
+
<CollapsibleCode>
|
|
97
|
+
<SyntaxHighlight
|
|
98
|
+
language={language}
|
|
99
|
+
noBackground
|
|
100
|
+
copyable
|
|
101
|
+
className="[--scrollbar-color:gray] text-xs max-h-[500px] p-2"
|
|
102
|
+
code={formattedExample}
|
|
103
|
+
/>
|
|
104
|
+
</CollapsibleCode>
|
|
105
|
+
)}
|
|
106
|
+
{selectedExample?.description && (
|
|
107
|
+
<div className="border-t text-xs px-3 py-1.5 text-muted-foreground">
|
|
108
|
+
{selectedExample.description}
|
|
109
|
+
</div>
|
|
110
|
+
)}
|
|
111
|
+
</SidecarBox.Body>
|
|
112
|
+
{hasContent && (
|
|
113
|
+
<SidecarBox.Footer className="text-xs p-0">
|
|
114
|
+
{description && (
|
|
115
|
+
<div className="text-muted-foreground text-xs border-b px-3 py-2">
|
|
116
|
+
{description}
|
|
117
|
+
</div>
|
|
118
|
+
)}
|
|
119
|
+
<div className="flex items-center gap-2 justify-between min-w-0 px-3 py-2">
|
|
120
|
+
<div className="flex items-center gap-2 min-w-0">
|
|
121
|
+
{content.length > 1 ? (
|
|
122
|
+
<SimpleSelect
|
|
123
|
+
className="max-w-[200px]"
|
|
124
|
+
value={selectedContentTypeIndex.toString()}
|
|
125
|
+
onChange={(e) =>
|
|
126
|
+
setSelectedContentTypeIndex(Number(e.target.value))
|
|
127
|
+
}
|
|
128
|
+
options={content.map((c, index) => ({
|
|
129
|
+
value: index.toString(),
|
|
130
|
+
label: c.mediaType,
|
|
131
|
+
}))}
|
|
132
|
+
/>
|
|
133
|
+
) : (
|
|
134
|
+
<span className="font-mono text-[11px]">
|
|
135
|
+
{content[0]?.mediaType}
|
|
136
|
+
</span>
|
|
137
|
+
)}
|
|
138
|
+
</div>
|
|
139
|
+
{examples.length > 1 && (
|
|
140
|
+
<div className="flex items-center gap-1">
|
|
141
|
+
<SimpleSelect
|
|
142
|
+
className="max-w-[180px]"
|
|
143
|
+
value={selectedExampleIndex.toString()}
|
|
144
|
+
onChange={(e) =>
|
|
145
|
+
setSelectedExampleIndex(Number(e.target.value))
|
|
146
|
+
}
|
|
147
|
+
options={examples.map((example, index) => ({
|
|
148
|
+
value: index.toString(),
|
|
149
|
+
label:
|
|
150
|
+
example.summary ||
|
|
151
|
+
example.name ||
|
|
152
|
+
example.description ||
|
|
153
|
+
`Example ${index + 1}`,
|
|
154
|
+
}))}
|
|
155
|
+
/>
|
|
156
|
+
</div>
|
|
157
|
+
)}
|
|
158
|
+
</div>
|
|
159
|
+
</SidecarBox.Footer>
|
|
160
|
+
)}
|
|
161
|
+
</>
|
|
162
|
+
);
|
|
163
|
+
};
|
|
@@ -1,34 +1,16 @@
|
|
|
1
1
|
import type { GraphQLError } from "graphql/error/index.js";
|
|
2
|
-
import { ulid } from "ulidx";
|
|
3
|
-
import { initializeWorker } from "zudoku/openapi-worker";
|
|
4
2
|
import { ZudokuError } from "../../../util/invariant.js";
|
|
5
3
|
import type { TypedDocumentString } from "../graphql/graphql.js";
|
|
6
4
|
import type { OpenApiPluginOptions } from "../index.js";
|
|
7
5
|
import type { LocalServer } from "./createServer.js";
|
|
8
|
-
import type { WorkerGraphQLMessage } from "./worker.js";
|
|
9
6
|
|
|
10
7
|
let localServerPromise: Promise<LocalServer> | undefined;
|
|
11
|
-
let worker: SharedWorker | undefined;
|
|
12
8
|
|
|
13
9
|
type GraphQLResponse<TResult> = {
|
|
14
10
|
errors?: GraphQLError[];
|
|
15
11
|
data: TResult;
|
|
16
12
|
};
|
|
17
13
|
|
|
18
|
-
const resolveVariables = async (variables?: unknown) => {
|
|
19
|
-
if (!variables) return;
|
|
20
|
-
|
|
21
|
-
if (
|
|
22
|
-
typeof variables === "object" &&
|
|
23
|
-
"type" in variables &&
|
|
24
|
-
variables.type === "file" &&
|
|
25
|
-
"input" in variables &&
|
|
26
|
-
typeof variables.input === "function"
|
|
27
|
-
) {
|
|
28
|
-
variables.input = await variables.input();
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
14
|
const throwIfError = (response: GraphQLResponse<unknown>) => {
|
|
33
15
|
if (!response.errors?.[0]) return;
|
|
34
16
|
|
|
@@ -39,119 +21,45 @@ const throwIfError = (response: GraphQLResponse<unknown>) => {
|
|
|
39
21
|
};
|
|
40
22
|
|
|
41
23
|
export class GraphQLClient {
|
|
42
|
-
readonly
|
|
43
|
-
#pendingRequests = new Map<string, (value: any) => void>();
|
|
44
|
-
#port: MessagePort | undefined;
|
|
24
|
+
constructor(private readonly config: OpenApiPluginOptions) {}
|
|
45
25
|
|
|
46
|
-
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
} else {
|
|
52
|
-
this.#mode = "worker";
|
|
26
|
+
#getLocalServer = async () => {
|
|
27
|
+
if (!localServerPromise) {
|
|
28
|
+
localServerPromise = import("./createServer.js").then((m) =>
|
|
29
|
+
m.createServer(this.config),
|
|
30
|
+
);
|
|
53
31
|
}
|
|
54
|
-
|
|
32
|
+
return localServerPromise;
|
|
33
|
+
};
|
|
55
34
|
|
|
56
|
-
#
|
|
57
|
-
|
|
35
|
+
#executeFetch = async (init: RequestInit): Promise<Response> => {
|
|
36
|
+
if (this.config.server) {
|
|
37
|
+
return fetch(this.config.server, init);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const localServer = await this.#getLocalServer();
|
|
41
|
+
return localServer.fetch("http://localhost/graphql", init);
|
|
42
|
+
};
|
|
58
43
|
|
|
59
44
|
fetch = async <TResult, TVariables>(
|
|
60
45
|
query: TypedDocumentString<TResult, TVariables>,
|
|
61
46
|
...[variables]: TVariables extends Record<string, never> ? [] : [TVariables]
|
|
62
|
-
) => {
|
|
47
|
+
): Promise<TResult> => {
|
|
63
48
|
const operationName = query.match(/query (\w+)/)?.[1];
|
|
64
49
|
|
|
65
|
-
await
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
case "remote": {
|
|
71
|
-
const response = await fetch(this.config.server!, {
|
|
72
|
-
method: "POST",
|
|
73
|
-
body,
|
|
74
|
-
headers: { "Content-Type": "application/json" },
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
if (!response.ok) {
|
|
78
|
-
throw new Error("Network response was not ok");
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const result = (await response.json()) as GraphQLResponse<TResult>;
|
|
82
|
-
throwIfError(result);
|
|
83
|
-
|
|
84
|
-
return result.data;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
case "in-memory": {
|
|
88
|
-
if (!localServerPromise) {
|
|
89
|
-
localServerPromise = this.#initializeLocalServer();
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const localServer = await localServerPromise;
|
|
93
|
-
if (!localServer) throw new Error("Local server not initialized");
|
|
50
|
+
const response = await this.#executeFetch({
|
|
51
|
+
method: "POST",
|
|
52
|
+
body: JSON.stringify({ query, variables, operationName }),
|
|
53
|
+
headers: { "Content-Type": "application/json" },
|
|
54
|
+
});
|
|
94
55
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
body,
|
|
99
|
-
headers: { "Content-Type": "application/json" },
|
|
100
|
-
}),
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
if (!response.ok) {
|
|
104
|
-
throw new Error("Network response was not ok");
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const result = (await response.json()) as GraphQLResponse<TResult>;
|
|
108
|
-
throwIfError(result);
|
|
109
|
-
|
|
110
|
-
return result.data;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
case "worker": {
|
|
114
|
-
if (!worker) {
|
|
115
|
-
worker = initializeWorker();
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (!this.#port) {
|
|
119
|
-
const channel = new MessageChannel();
|
|
120
|
-
|
|
121
|
-
worker.port.postMessage({ port: channel.port2 }, [channel.port2]);
|
|
122
|
-
|
|
123
|
-
this.#port = channel.port1;
|
|
124
|
-
|
|
125
|
-
this.#port.onmessage = (e: MessageEvent<WorkerGraphQLMessage>) => {
|
|
126
|
-
const { id, body } = e.data;
|
|
127
|
-
const resolve = this.#pendingRequests.get(id);
|
|
128
|
-
if (resolve) {
|
|
129
|
-
const result = JSON.parse(body);
|
|
130
|
-
resolve(result);
|
|
131
|
-
this.#pendingRequests.delete(id);
|
|
132
|
-
} else {
|
|
133
|
-
// eslint-disable-next-line no-console
|
|
134
|
-
console.error(`No pending request found for id: ${id}`);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
this.#port.start();
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const id = ulid();
|
|
142
|
-
|
|
143
|
-
const resultPromise = new Promise<GraphQLResponse<TResult>>(
|
|
144
|
-
(resolve) => {
|
|
145
|
-
this.#pendingRequests.set(id, resolve);
|
|
146
|
-
this.#port!.postMessage({ id, body } as WorkerGraphQLMessage);
|
|
147
|
-
},
|
|
148
|
-
);
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
throw new Error("Network response was not ok");
|
|
58
|
+
}
|
|
149
59
|
|
|
150
|
-
|
|
151
|
-
|
|
60
|
+
const result = (await response.json()) as GraphQLResponse<TResult>;
|
|
61
|
+
throwIfError(result);
|
|
152
62
|
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
}
|
|
63
|
+
return result.data;
|
|
156
64
|
};
|
|
157
65
|
}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { useLogger } from "@envelop/core";
|
|
2
2
|
import { createGraphQLServer } from "../../../oas/graphql/index.js";
|
|
3
|
+
import type { OpenApiPluginOptions } from "../index.js";
|
|
3
4
|
|
|
4
5
|
const map = new Map<string, number>();
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Creates the GraphQL server
|
|
8
9
|
*/
|
|
9
|
-
export const createServer = () =>
|
|
10
|
+
export const createServer = (config: OpenApiPluginOptions) =>
|
|
10
11
|
createGraphQLServer({
|
|
12
|
+
context: {
|
|
13
|
+
schemaImports: config.schemaImports,
|
|
14
|
+
},
|
|
11
15
|
plugins: [
|
|
12
16
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
13
17
|
useLogger({
|
|
@@ -22,7 +26,7 @@ export const createServer = () =>
|
|
|
22
26
|
if (start) {
|
|
23
27
|
// eslint-disable-next-line no-console
|
|
24
28
|
console.log(
|
|
25
|
-
|
|
29
|
+
`[zudoku:debug] ${args.operationName} query took ${performance.now() - start}ms`,
|
|
26
30
|
);
|
|
27
31
|
map.delete(`${startEvent}-${args.operationName}`);
|
|
28
32
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { useContext, useMemo } from "react";
|
|
1
|
+
import { useContext } from "react";
|
|
3
2
|
import type { TypedDocumentString } from "../graphql/graphql.js";
|
|
4
3
|
import { GraphQLContext } from "./GraphQLContext.js";
|
|
5
4
|
|
|
@@ -12,22 +11,8 @@ export const useCreateQuery = <TResult, TVariables>(
|
|
|
12
11
|
throw new Error("useGraphQL must be used within a GraphQLProvider");
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
const hash = useMemo(() => {
|
|
16
|
-
if (
|
|
17
|
-
typeof variables[0] === "object" &&
|
|
18
|
-
variables[0] != null &&
|
|
19
|
-
"input" in variables[0] &&
|
|
20
|
-
typeof variables[0].input === "function"
|
|
21
|
-
) {
|
|
22
|
-
// This is a pre-hashed name to ensure that the query key is consistent across server and client
|
|
23
|
-
return variables[0].input.name;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return hashit(variables[0] ?? {});
|
|
27
|
-
}, [variables]);
|
|
28
|
-
|
|
29
14
|
return {
|
|
30
15
|
queryFn: () => graphQLClient.fetch(query, ...variables),
|
|
31
|
-
queryKey: [query,
|
|
16
|
+
queryKey: [query, variables[0]],
|
|
32
17
|
} as const;
|
|
33
18
|
};
|
|
@@ -7,6 +7,7 @@ import { CirclePlayIcon, LogInIcon } from "lucide-react";
|
|
|
7
7
|
import type { SidebarItem } from "../../../config/validators/SidebarSchema.js";
|
|
8
8
|
import { useAuth } from "../../authentication/hook.js";
|
|
9
9
|
import { ColorMap } from "../../components/navigation/SidebarBadge.js";
|
|
10
|
+
import type { SchemaImports } from "../../oas/graphql/index.js";
|
|
10
11
|
import { Button } from "../../ui/Button.js";
|
|
11
12
|
import { joinPath } from "../../util/joinPath.js";
|
|
12
13
|
import { GraphQLClient } from "./client/GraphQLClient.js";
|
|
@@ -35,7 +36,7 @@ const GetCategoriesQuery = graphql(`
|
|
|
35
36
|
}
|
|
36
37
|
`);
|
|
37
38
|
|
|
38
|
-
type InternalOasPluginConfig = {
|
|
39
|
+
type InternalOasPluginConfig = { schemaImports?: SchemaImports };
|
|
39
40
|
|
|
40
41
|
const MethodColorMap: Record<string, keyof typeof ColorMap> = {
|
|
41
42
|
get: "green",
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Command,
|
|
4
|
+
CommandEmpty,
|
|
5
|
+
CommandInput,
|
|
6
|
+
CommandItem,
|
|
7
|
+
CommandList,
|
|
8
|
+
} from "../../../ui/Command.js";
|
|
9
|
+
import {
|
|
10
|
+
Popover,
|
|
11
|
+
PopoverContent,
|
|
12
|
+
PopoverTrigger,
|
|
13
|
+
} from "../../../ui/Popover.js";
|
|
14
|
+
import { cn } from "../../../util/cn.js";
|
|
15
|
+
|
|
16
|
+
interface EnumSelectorProps {
|
|
17
|
+
value: string;
|
|
18
|
+
enumValues: string[];
|
|
19
|
+
onChange: (value: string) => void;
|
|
20
|
+
onValueSelected: () => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const EnumSelector = ({
|
|
24
|
+
value,
|
|
25
|
+
enumValues,
|
|
26
|
+
onChange,
|
|
27
|
+
onValueSelected,
|
|
28
|
+
}: EnumSelectorProps) => {
|
|
29
|
+
const [searchValue, setSearchValue] = useState("");
|
|
30
|
+
const [open, setOpen] = useState(false);
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
34
|
+
<PopoverTrigger asChild>
|
|
35
|
+
<button
|
|
36
|
+
type="button"
|
|
37
|
+
role="combobox"
|
|
38
|
+
className={cn(
|
|
39
|
+
"px-3 py-2 w-full border-0 shadow-none text-xs font-mono text-start hover:bg-accent/40 rounded border-transparent hover:bg-accent",
|
|
40
|
+
!value && "text-muted-foreground",
|
|
41
|
+
)}
|
|
42
|
+
>
|
|
43
|
+
{value || "Select value"}
|
|
44
|
+
</button>
|
|
45
|
+
</PopoverTrigger>
|
|
46
|
+
<PopoverContent
|
|
47
|
+
className="p-0 w-[--radix-popover-trigger-width] "
|
|
48
|
+
align="start"
|
|
49
|
+
sideOffset={3}
|
|
50
|
+
alignOffset={-3}
|
|
51
|
+
side="bottom"
|
|
52
|
+
>
|
|
53
|
+
<Command className="max-h-[180px]">
|
|
54
|
+
<CommandInput
|
|
55
|
+
placeholder="Enter value"
|
|
56
|
+
className="h-9 bg-transparent "
|
|
57
|
+
onValueChange={setSearchValue}
|
|
58
|
+
onKeyDown={(e) => {
|
|
59
|
+
if (e.key === "Enter") {
|
|
60
|
+
onChange(searchValue);
|
|
61
|
+
onValueSelected();
|
|
62
|
+
setOpen(false);
|
|
63
|
+
}
|
|
64
|
+
}}
|
|
65
|
+
/>
|
|
66
|
+
<CommandList>
|
|
67
|
+
<CommandEmpty>Use "{searchValue}"</CommandEmpty>
|
|
68
|
+
{enumValues.map((enumValue) => (
|
|
69
|
+
<CommandItem
|
|
70
|
+
key={enumValue}
|
|
71
|
+
value={enumValue}
|
|
72
|
+
onSelect={(selected) => {
|
|
73
|
+
onChange(selected);
|
|
74
|
+
onValueSelected();
|
|
75
|
+
setOpen(false);
|
|
76
|
+
}}
|
|
77
|
+
>
|
|
78
|
+
{enumValue}
|
|
79
|
+
</CommandItem>
|
|
80
|
+
))}
|
|
81
|
+
</CommandList>
|
|
82
|
+
</Command>
|
|
83
|
+
</PopoverContent>
|
|
84
|
+
</Popover>
|
|
85
|
+
);
|
|
86
|
+
};
|