diff --git a/package.json b/package.json index 285576e4c7d..f6c4685eab8 100644 --- a/package.json +++ b/package.json @@ -105,4 +105,4 @@ "$root$": false } } -} \ No newline at end of file +} diff --git a/src/components/ParserOpenRPC/InteractiveBox/fields/ConditionalField.tsx b/src/components/ParserOpenRPC/InteractiveBox/fields/ConditionalField.tsx new file mode 100644 index 00000000000..70aa82fce1c --- /dev/null +++ b/src/components/ParserOpenRPC/InteractiveBox/fields/ConditionalField.tsx @@ -0,0 +1,96 @@ +import React, { useContext, useEffect, useState } from "react"; +import { FieldTemplateProps } from "@rjsf/utils"; +import { BaseInputTemplate } from "@site/src/components/ParserOpenRPC/InteractiveBox/templates/BaseInputTemplate"; +import { SelectWidget } from "@site/src/components/ParserOpenRPC/InteractiveBox/widgets/SelectWidget"; +import styles from "@site/src/components/ParserOpenRPC/InteractiveBox/styles.module.css"; +import { ParserOpenRPCContext } from "@site/src/components/ParserOpenRPC"; +import clsx from "clsx"; + +export const ConditionalField = (props: FieldTemplateProps) => { + const [isOpened, setIsOpened] = useState(false); + const [selectedTypeSchema, setSelectedTypeSchema] = useState(null); + const [isEditView, setIsEditView] = useState(false); + const { setIsDrawerContentFixed, setDrawerLabel, isComplexTypeView, setIsComplexTypeView } = useContext(ParserOpenRPCContext); + const { formData, schema, name, onChange } = props; + const listItems = schema?.anyOf ? schema?.anyOf : schema?.oneOf; + const checkForNullTypeSchema = (type) => type === "null"; + const showComplexTypeView = () => { + setDrawerLabel(name); + setIsDrawerContentFixed(true); + setIsEditView(true); + setIsComplexTypeView(true); + } + const onDropdownOptionClick = (e) => { + const selectedSchema = listItems.find(({ title }) => title === e.target.dataset.value); + const isNullTypeSchema = checkForNullTypeSchema(selectedSchema?.type); + if (isNullTypeSchema) { + onChange(null); + } else { + setSelectedTypeSchema(listItems.find(({ title }) => title === e.target.dataset.value)); + showComplexTypeView(); + } + setIsOpened(false); + } + const selectWidgetProps = { + ...props, + schema: selectedTypeSchema, + label: name, + value: formData, + ...(selectedTypeSchema?.enum && { + options:{ + enumOptions: selectedTypeSchema?.enum.map(item => ({ label: item, value: item })) + } + }) + } + const baseInputProps = { + ...props, + schema: selectedTypeSchema + } + + useEffect(() => { + if(!isComplexTypeView) { + setIsEditView(false); + setSelectedTypeSchema(null); + } + }, [isComplexTypeView]) + + return listItems?.length > 0 ? ( + <> +
+
+ +
+
+
+ {formData === undefined ? "" : String(formData)} + + { setIsOpened(!isOpened); }}> + {schema?.anyOf ? "anyOf" : "oneOf"} + + + +
    + {listItems?.map((listItem, index) => ( +
  • + {`${listItem.title}: ${listItem?.enum ? "enum" : listItem.type}`} +
  • + ))} +
+
+
+
+
+ {isComplexTypeView && isEditView && selectedTypeSchema && selectedTypeSchema.type !== "null" ? +
+ {selectedTypeSchema?.enum ? : } +
+ : null + } + + ) : null; +} diff --git a/src/components/ParserOpenRPC/InteractiveBox/index.tsx b/src/components/ParserOpenRPC/InteractiveBox/index.tsx index e65493999b2..3236bb53404 100644 --- a/src/components/ParserOpenRPC/InteractiveBox/index.tsx +++ b/src/components/ParserOpenRPC/InteractiveBox/index.tsx @@ -1,30 +1,44 @@ -import React, { useEffect, useRef, useState } from "react"; +import React, { useContext, useEffect, useRef, useState } from "react"; import Form from "@rjsf/core"; import clsx from "clsx"; -import { RJSFSchema, UiSchema, RegistryWidgetsType } from "@rjsf/utils"; +import {RJSFSchema, UiSchema, RegistryWidgetsType, RegistryFieldsType} from "@rjsf/utils"; import validator from "@rjsf/validator-ajv8"; import $RefParser from "@apidevtools/json-schema-ref-parser"; import { MethodExample, MethodParam, SchemaComponents } from "@site/src/components/ParserOpenRPC/interfaces"; import styles from "./styles.module.css"; +import global from "../global.module.css"; import { BaseInputTemplate } from "@site/src/components/ParserOpenRPC/InteractiveBox/templates/BaseInputTemplate"; import { ArrayFieldTemplate } from "@site/src/components/ParserOpenRPC/InteractiveBox/templates/ArrayFieldTemplate"; +import { ConditionalField } from "@site/src/components/ParserOpenRPC/InteractiveBox/fields/ConditionalField"; import { DropdownWidget } from "@site/src/components/ParserOpenRPC/InteractiveBox/widgets/DropdownWidget"; +import { SelectWidget } from "@site/src/components/ParserOpenRPC/InteractiveBox/widgets/SelectWidget"; import { Tooltip } from "@site/src/components/ParserOpenRPC/Tooltip"; import { useColorMode } from "@docusaurus/theme-common"; +import { ParserOpenRPCContext } from "@site/src/components/ParserOpenRPC"; interface InteractiveBoxProps { params: MethodParam[]; components: SchemaComponents; examples: MethodExample[]; onParamChange: (data) => void; + drawerLabel?: string | null + closeComplexTypeView?: () => void; } -export default function InteractiveBox({ params, components, examples, onParamChange }: InteractiveBoxProps) { +export default function InteractiveBox({ + params, + components, + examples, + onParamChange, + drawerLabel, + closeComplexTypeView +}:InteractiveBoxProps) { const [parsedSchema, setParsedSchema] = useState(null); const [defaultFormData, setDefaultFormData] = useState({}); const [isFormReseted, setIsFormReseted] = useState(false); const formRef = useRef(null); const { colorMode } = useColorMode(); + const { isComplexTypeView } = useContext(ParserOpenRPCContext); const defaultExampleFormData = examples ? Object.fromEntries(examples[0].params.map(({ name, value }) => [name, value])) : {}; const schema: RJSFSchema = { @@ -40,10 +54,20 @@ export default function InteractiveBox({ params, components, examples, onParamCh }, "ui:widget": "checkbox", }; + const templates = { + BaseInputTemplate, + ArrayFieldTemplate, + FieldErrorTemplate: () => null, + ErrorListTemplate: () => null, + } const widgets: RegistryWidgetsType = { CheckboxWidget: DropdownWidget, + SelectWidget: SelectWidget, + }; + const fields: RegistryFieldsType = { + AnyOfField: ConditionalField, + OneOfField: ConditionalField, }; - const log = (type) => console.log.bind(console, type); const handleResetForm = (e) => { e.preventDefault(); setDefaultFormData(defaultExampleFormData); @@ -76,8 +100,34 @@ export default function InteractiveBox({ params, components, examples, onParamCh const onChangeHandler = (data) => { onParamChange(data); + setDefaultFormData(data); }; + const cloneAndSetNullIfExists = (obj, key) => { + if (typeof obj !== 'object' || obj === null) return obj; + const newObj = Array.isArray(obj) ? [] : {}; + for (let prop in obj) { + if (obj.hasOwnProperty(prop)) { + if (prop === key) { + newObj[prop] = []; + } else if (typeof obj[prop] === 'object' && obj[prop] !== null) { + newObj[prop] = cloneAndSetNullIfExists(obj[prop], key); + } else { + newObj[prop] = obj[prop]; + } + } + } + return newObj; + } + + const handleCancelClick = () => { + if (drawerLabel) { + const upData = cloneAndSetNullIfExists(defaultFormData, drawerLabel); + setDefaultFormData(upData) + } + closeComplexTypeView(); + } + return parsedSchema ? ( <>
@@ -95,38 +145,40 @@ export default function InteractiveBox({ params, components, examples, onParamCh validator={validator} liveValidate noHtml5Validate - onChange={(data) => { - onChangeHandler(data.formData); - setDefaultFormData(data.formData); - }} - onSubmit={() => {log("submitted");}} - onError={log("errors")} - templates={{ - BaseInputTemplate, - ArrayFieldTemplate, - FieldErrorTemplate: () => null, - ErrorListTemplate: () => null, - }} + onChange={(data) => { onChangeHandler(data.formData); }} + templates={templates} uiSchema={uiSchema} widgets={widgets} ref={formRef} + fields={fields} >
-
- - - +
+ {isComplexTypeView ? +
+ + +
: + null + }
diff --git a/src/components/ParserOpenRPC/InteractiveBox/styles.module.css b/src/components/ParserOpenRPC/InteractiveBox/styles.module.css index f3aa2759774..5627e664e24 100644 --- a/src/components/ParserOpenRPC/InteractiveBox/styles.module.css +++ b/src/components/ParserOpenRPC/InteractiveBox/styles.module.css @@ -26,10 +26,14 @@ height: 100%; padding: 12px 16px 12px 12px; border-left: 4px solid transparent; + line-height: 28px; } .tableColumnParamFocused { border-left: 4px solid rgba(16, 152, 252, 1); } +.tableColumnParamError { + border-left: 4px solid rgba(224, 100, 112, 1); +} .tableColumn:first-child { border-right: 1px solid rgba(132, 140, 150, 1); } @@ -40,9 +44,10 @@ justify-content: space-between; align-items: center; position: relative; + font-size: 14px; } .tableValueRowPadding { - padding: 12px 56px 12px 16px; + padding: 12px 72px 12px 16px; } .tableColumnType { display: flex; @@ -56,26 +61,53 @@ line-height: 24px; font-size: 14px; } -.tableColumnTypeErrorIcon { - position: absolute; - right: 13px; +.tableLabelIconError { width: 11px; height: 11px; + margin-left: 8px; background: url("/img/icons/error-icon.svg") no-repeat 50% 50%; } -.chevronIcon { +.tableColumnIcon { position: absolute; right: 13px; width: 11px; height: 11px; - background: url("/img/icons/chevron-icon.svg") no-repeat 50% 50%; } -.chevronIcon:hover { +.tableColumnIcon:hover { cursor: pointer; } +.tableColumnIconRemove { + background: url("/img/icons/remove-icon.svg") no-repeat 50% 50%; +} +.chevronIcon { + background: url("/img/icons/chevron-icon.svg") no-repeat 50% 50%; + transition: 0.2s transform; +} .chevronIconDown { transform: rotate(180deg); } +.chevronIconRight { + transform: rotate(90deg); +} +.chevronIcon:hover { + cursor: pointer; +} +.deleteIcon { + position: absolute; + transform: translateY(-50%); + right: 12px; + width: 14px; + height: 14px; + margin-top: -1px; + cursor: pointer; + background: url("/img/icons/delete-icon.svg") no-repeat 50% 50%; +} +.deleteIconCentered { + top: 50%; +} +.deleteIconComplex { + top: 27px; +} .dropdown { display: flex; align-items: center; @@ -92,7 +124,7 @@ .dropdownList { position: absolute; right: 0; - opacity: 1; + visibility: visible; list-style: none; border-radius: 10px; padding: 0; @@ -100,19 +132,20 @@ top: 35px; overflow: hidden; border: 1px solid rgba(132, 140, 150, 1); - transition: 0.4s opacity; + z-index: 2; } .dropdownListClosed { - opacity: 0; + visibility: hidden; } .dropdownList li + li { margin-top: 0; } .dropdownItem { - width: 102px; + width: 100%; padding: 16px; background-color: rgba(36, 39, 42, 1); color: #FFFFFF; + white-space: nowrap; } .dropdownItem:hover { background-color: rgba(20, 22, 24, 1); @@ -124,7 +157,8 @@ .tableFooterRow { position: fixed; display: flex; - padding: 21px 16px; + justify-content: space-between; + padding: 16px; width: 100%; bottom: 0; } @@ -134,6 +168,33 @@ .tableFooterRowLight { background-color: #F2F4F6; } +.tableButton { + display: flex; + background: none; + border: none; +} +.tableButtonAddNewArray { + margin: 08px 0 8px 16px; + padding: 8px 0; + color: rgba(16, 152, 252, 1); +} +.tableButtonAddArrayItemName { + margin-left: 8px; + font-size: 14px; + font-weight: 500; +} +.tableComplexType { + position: absolute; + top: 0; + width: 100%; + height: 332px; + background-color: #292A36; + overflow-y: scroll; + z-index: 1; +} +.tableComplexTypeItem { + position: relative; +} .formControl { width: 100%; padding: 12px 72px 12px 16px; @@ -165,10 +226,14 @@ } .footerButtons { display: flex; +} +.footerButtonsLeft { width: 48px; + align-items: center; justify-content: space-between; + padding: 6px 0; } -.footerButton { +.footerButtonLeft { display: flex; width: 16px; height: 22px; @@ -178,21 +243,22 @@ border: none; border-radius: 0; } -.footerButton:hover { - cursor: pointer; +.footerButtonRight { + padding: 5px 16px!important; +} +.footerButtonRightOutline { + margin-right: 16px; } .footerButtonIcon { width: 100%; border-radius: 0; } - .arrayParentRow { position: relative; width: 100%; height: 100%; padding: 12px 72px 12px 16px; } - .arrayColumnType { position: absolute; top: 0; @@ -205,13 +271,13 @@ font-size: 14px; cursor: pointer; } - .arrayFormDataWrap { + display: block; + max-width: 395px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } - .addItemBtnWrap { min-height: 52px; display: flex; @@ -219,7 +285,6 @@ padding: 12px; border-bottom: 1px solid rgba(132, 140, 150, 1); } - .addItemBtn { display: flex; align-items: center; @@ -232,7 +297,6 @@ line-height: 1; cursor: pointer; } - .addItemIcon { display: inline-flex; align-items: center; @@ -246,7 +310,6 @@ line-height: 1; margin-right: 10px; } - .arrayItemIcon { position: absolute; top: 50%; @@ -256,21 +319,8 @@ line-height: 1; font-weight: bold; } - .arrayItemRowWrap { position: relative; padding-left: 40px; border-bottom: 1px dashed #848C96; } - -.deleteIcon { - position: absolute; - top: 50%; - transform: translateY(-50%); - right: 12px; - width: 14px; - height: 14px; - margin-top: -1px; - cursor: pointer; - background: url("/img/icons/delete-icon.svg") no-repeat 50% 50%; -} \ No newline at end of file diff --git a/src/components/ParserOpenRPC/InteractiveBox/templates/ArrayFieldTemplate.tsx b/src/components/ParserOpenRPC/InteractiveBox/templates/ArrayFieldTemplate.tsx index b3fc3f982f1..b0e18bf64b7 100644 --- a/src/components/ParserOpenRPC/InteractiveBox/templates/ArrayFieldTemplate.tsx +++ b/src/components/ParserOpenRPC/InteractiveBox/templates/ArrayFieldTemplate.tsx @@ -1,79 +1,114 @@ -import React from "react"; +import React, { useContext, useState } from "react"; import { useCollapsible, Collapsible } from "@docusaurus/theme-common"; import { ArrayFieldTemplateProps } from "@rjsf/utils"; import { BaseInputTemplate } from "@site/src/components/ParserOpenRPC/InteractiveBox/templates/BaseInputTemplate"; -import clsx from "clsx"; import styles from "@site/src/components/ParserOpenRPC/InteractiveBox/styles.module.css"; +import clsx from "clsx"; +import { ParserOpenRPCContext } from "@site/src/components/ParserOpenRPC"; -export const ArrayFieldTemplate = ({ - title, - formData, - items, - canAdd, - onAddClick -}: ArrayFieldTemplateProps) => { +export const ArrayFieldTemplate = ({ items, canAdd, onAddClick, title, schema, formData, formContext }: ArrayFieldTemplateProps) => { + const [isComplexArrayEditView, setIsComplexArrayEditView] = useState(false); + const { setIsDrawerContentFixed, setDrawerLabel, isComplexTypeView, setIsComplexTypeView } = useContext(ParserOpenRPCContext); const { collapsed, toggleCollapsed } = useCollapsible({ initialState: true }); + const itemsType = schema?.items?.type; + const isSimpleArray = itemsType === "string" || itemsType === "boolean" || itemsType === "number" || itemsType === "integer"; + const addComplexArray = () => { + onAddClick(); + setDrawerLabel(title); + setIsDrawerContentFixed(true); + setIsComplexArrayEditView(true); + setIsComplexTypeView(true); + } + return ( - <> +
- +
-
+
{JSON.stringify(formData, null, " ")}
- - array - + + + {schema.type} +
- - <> - {items.map((el, i) => { - const props = { - ...el.children.props, - isArray: true - } - const { index, hasRemove, onDropIndexClick, schema } = el; - const isNumber = schema.type === "number" || schema.type === "integer"; - return ( -
- {i+1} - - {hasRemove && ( - + {isComplexTypeView && isComplexArrayEditView && !isSimpleArray ? +
+ {items.map(({ children, index, onDropIndexClick, hasRemove }) => ( +
+ {children} + {hasRemove && ( + + + )} +
+ ))} + {canAdd ? + : + null + } +
: + + <> + {items.map((el, i) => { + const baseInputTemplateProps = { + ...el.children.props, + isArray: true, + value: formData, + } + const { index, hasRemove, onDropIndexClick, schema } = el; + const isNumber = schema.type === "number" || schema.type === "integer"; + return ( +
+ {i+1} + + {hasRemove && ( + - )} + )} +
+ ) + })} + {canAdd && ( +
+
- ) - })} - {canAdd && ( -
- -
- )} - -
- + )} + + + } +
); -}; +} diff --git a/src/components/ParserOpenRPC/InteractiveBox/templates/BaseInputTemplate.tsx b/src/components/ParserOpenRPC/InteractiveBox/templates/BaseInputTemplate.tsx index 358aadf6142..be8eef24c90 100644 --- a/src/components/ParserOpenRPC/InteractiveBox/templates/BaseInputTemplate.tsx +++ b/src/components/ParserOpenRPC/InteractiveBox/templates/BaseInputTemplate.tsx @@ -10,18 +10,18 @@ interface ExtendedInputProps extends BaseInputTemplateProps { } export const BaseInputTemplate = ({ - schema, - id, - name, - value = "", - disabled, - onChange, - rawErrors, - hideError, - required, - formContext, - isArray -}: ExtendedInputProps) => { + schema, + id, + name, + value = "", + disabled, + onChange, + rawErrors, + hideError, + required, + formContext, + isArray + }: ExtendedInputProps) => { const isNumber = schema.type === "number" || schema.type === "integer"; const [isFocused, setIsFocused] = useState(false); const [inputValue, setInputValue] = useState(isNumber ? 0 : ""); @@ -52,8 +52,9 @@ export const BaseInputTemplate = ({
{!isArray && (
-
)} @@ -73,15 +74,14 @@ export const BaseInputTemplate = ({ /> {schema.type} - {hasErrors && !isNumber ? : null} {isNumber ? ( <> { onInputNumberChange(Number((+inputValue || 0) + 1)); }} /> { inputValue >= 1 && onInputNumberChange(Number((+inputValue || 0) - 1)); }} /> diff --git a/src/components/ParserOpenRPC/InteractiveBox/widgets/DropdownWidget.tsx b/src/components/ParserOpenRPC/InteractiveBox/widgets/DropdownWidget.tsx index aa0a50afac0..0c7e3842920 100644 --- a/src/components/ParserOpenRPC/InteractiveBox/widgets/DropdownWidget.tsx +++ b/src/components/ParserOpenRPC/InteractiveBox/widgets/DropdownWidget.tsx @@ -17,6 +17,7 @@ export const DropdownWidget = ({ name, value, onChange, schema, options }: Widge { setIsOpened(!isOpened); }}> {schema.type} +
    diff --git a/src/components/ParserOpenRPC/InteractiveBox/widgets/SelectWidget.tsx b/src/components/ParserOpenRPC/InteractiveBox/widgets/SelectWidget.tsx new file mode 100644 index 00000000000..029e6b3e912 --- /dev/null +++ b/src/components/ParserOpenRPC/InteractiveBox/widgets/SelectWidget.tsx @@ -0,0 +1,43 @@ +import React, { useState } from "react"; +import { WidgetProps } from "@rjsf/utils"; +import clsx from "clsx"; +import styles from "@site/src/components/ParserOpenRPC/InteractiveBox/styles.module.css"; + +export const SelectWidget = ({ value, onChange, schema, options, label }: WidgetProps) => { + const [isOpened, setIsOpened] = useState(false); + const emptyValue = value === undefined || !options?.enumOptions.some(({ label }) => label === value); + + return ( +
    +
    + +
    +
    +
    + {emptyValue ? "" : String(value)} + + { setIsOpened(!isOpened); }}> + {schema?.enum ? 'enum' : schema?.type} + + + +
      + {options?.enumOptions?.map(({ label, value }, index) => ( +
    • { + onChange(value); + setIsOpened(false); + }} + > + {String(label)} +
    • + ))} +
    +
    +
    +
    +
    + ); +}; diff --git a/src/components/ParserOpenRPC/ModalDrawer/index.tsx b/src/components/ParserOpenRPC/ModalDrawer/index.tsx index cd70e29b3c1..16208dab86a 100644 --- a/src/components/ParserOpenRPC/ModalDrawer/index.tsx +++ b/src/components/ParserOpenRPC/ModalDrawer/index.tsx @@ -1,30 +1,45 @@ -import React, { useState, useEffect } from "react"; +import React, {useState, useEffect, useRef} from "react"; import clsx from "clsx"; import { useColorMode } from "@docusaurus/theme-common"; import styles from "./styles.module.css"; interface ModalDrawerProps { - title: string; + title: string | React.ReactNode; isOpen: boolean; onClose: () => void; children: React.ReactNode; + isContentFixed?: boolean; + headerLabel?: string | null; } -export const ModalDrawer = ({ title, isOpen, onClose, children }: ModalDrawerProps) => { +export const ModalDrawer = ({ title, isOpen, onClose, children, isContentFixed = false, headerLabel }: ModalDrawerProps) => { const [showModal, setShowModal] = useState(isOpen); + const contentRef = useRef(null); const { colorMode } = useColorMode(); useEffect(() => { setShowModal(isOpen); }, [isOpen]); + useEffect(() => { + if (isContentFixed && contentRef?.current) { + contentRef?.current?.scrollTo(0, 0); + } + }, [isContentFixed]); + return (
    - {title} +
    + {title} + {headerLabel ? {headerLabel} : null} +
    -
    +
    {children}
    diff --git a/src/components/ParserOpenRPC/ModalDrawer/styles.module.css b/src/components/ParserOpenRPC/ModalDrawer/styles.module.css index faf662cc29f..4fcd5412374 100644 --- a/src/components/ParserOpenRPC/ModalDrawer/styles.module.css +++ b/src/components/ParserOpenRPC/ModalDrawer/styles.module.css @@ -41,6 +41,40 @@ font-weight: 500; } +.modalTitleContainer { + display: flex; + align-items: center; +} + +.modalHeaderIcon { + display: flex; + background: none; + border: none; + padding: 0; + margin-right: 8px; +} + +.modalHeaderIconBack { + width: 16px; + height: 16px; +} + +.modalHeaderLabels { + display: flex; + align-items: center; +} + +.modalHeaderLabel { + display: flex; + justify-content: center; + margin-left: 8px; + padding: 2px 8px; + border: 1px solid #848C96; + border-radius: 999px; + font-size: 12px; + line-height: 18px; +} + .modalCloseBtn { display: block; padding: 0; @@ -53,10 +87,17 @@ .modalContent { height: 394px; +} + +.modalContentScrolled { overflow-y: auto; } -@media (width <= 1200px) { +.modalContentFixed { + overflow-y: hidden; +} + +@media (width <= 996px) { .modalContainer { position: fixed; left: 0; diff --git a/src/components/ParserOpenRPC/Tooltip/Tooltip.module.css b/src/components/ParserOpenRPC/Tooltip/Tooltip.module.css index 5f0553c5c4c..f899638b910 100644 --- a/src/components/ParserOpenRPC/Tooltip/Tooltip.module.css +++ b/src/components/ParserOpenRPC/Tooltip/Tooltip.module.css @@ -1,6 +1,5 @@ .tooltipContainer { max-width: 180px; - max-height: 60px; font-size: 16px; } .tooltipContainer:first-letter { diff --git a/src/components/ParserOpenRPC/Tooltip/index.tsx b/src/components/ParserOpenRPC/Tooltip/index.tsx index 510e4688ef2..40348046f92 100644 --- a/src/components/ParserOpenRPC/Tooltip/index.tsx +++ b/src/components/ParserOpenRPC/Tooltip/index.tsx @@ -7,14 +7,12 @@ interface TooltipProps { children: ReactNode; message: string; disabled?: boolean; - theme?: "light" | "dark"; } -export const Tooltip = ({ children, message, disabled, theme = "light" }: TooltipProps) => ( +export const Tooltip = ({ children, message, disabled }: TooltipProps) => ( {message}
    )} @@ -23,4 +21,4 @@ export const Tooltip = ({ children, message, disabled, theme = "light" }: Toolti > {children} -); +) diff --git a/src/components/ParserOpenRPC/global.module.css b/src/components/ParserOpenRPC/global.module.css index b90a9d70f52..cbf763225ff 100644 --- a/src/components/ParserOpenRPC/global.module.css +++ b/src/components/ParserOpenRPC/global.module.css @@ -24,7 +24,7 @@ text-decoration: none; color: #141618; background-color: #26A2FC; - box-shadow: 0px 2px 8px 0px rgba(16, 152, 252, 0.40); + box-shadow: 0 2px 8px 0 rgba(16, 152, 252, 0.40); } .primaryBtn:disabled { @@ -35,6 +35,31 @@ box-shadow: none; } +.secondaryBtn { + background: none; + border-radius: 999px; + outline: none; + font-size: 14px; + font-weight: 500; + line-height: 22px; + border: 1px solid rgba(3, 118, 201, 1); + color: rgba(3, 118, 201, 1); +} + +.secondaryBtn:hover { + text-decoration: none; + color: #141618; + background-color: #26A2FC; + box-shadow: 0 2px 8px 0 rgba(16, 152, 252, 0.40); +} + +.secondaryBtn:disabled { + cursor: not-allowed; + text-decoration: none; + box-shadow: none; + opacity: 0.5; +} + .linkBtn { background: none; border: 0; diff --git a/src/components/ParserOpenRPC/index.tsx b/src/components/ParserOpenRPC/index.tsx index c053e044408..7bcdad5729b 100644 --- a/src/components/ParserOpenRPC/index.tsx +++ b/src/components/ParserOpenRPC/index.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useState, useEffect } from "react"; +import React, { createContext, useEffect, useMemo, useState } from 'react' import { usePluginData } from "@docusaurus/useGlobalData"; import { ResponseItem, NETWORK_NAMES } from "@site/src/plugins/plugin-json-rpc"; import DetailsBox from "@site/src/components/ParserOpenRPC/DetailsBox"; @@ -8,18 +8,34 @@ import RequestBox from "@site/src/components/ParserOpenRPC/RequestBox"; import ErrorsBox from "@site/src/components/ParserOpenRPC/ErrorsBox"; import { ModalDrawer } from "@site/src/components/ParserOpenRPC/ModalDrawer"; import global from "./global.module.css"; +import modalDrawerStyles from "./ModalDrawer/styles.module.css"; +import clsx from "clsx"; +import { useColorMode } from "@docusaurus/theme-common"; interface ParserProps { network: NETWORK_NAMES; method?: string; } +interface ParserOpenRPCContextProps { + setIsDrawerContentFixed?: (isFixed: boolean) => void + setDrawerLabel?: (label: string) => void; + isComplexTypeView: boolean; + setIsComplexTypeView: (isComplexTypeView: boolean) => void; +} + +export const ParserOpenRPCContext = createContext(null) + export default function ParserOpenRPC({ network, method }: ParserProps) { if (!method || !network) return null; const [metamaskInstalled, setMetamaskInstalled] = useState(false); const [isModalOpen, setModalOpen] = useState(false); const [reqResult, setReqResult] = useState(null); const [paramsData, setParamsData] = useState([]); + const [isDrawerContentFixed, setIsDrawerContentFixed] = useState(false); + const [drawerLabel, setDrawerLabel] = useState(null); + const [isComplexTypeView, setIsComplexTypeView] = useState(false); + const { colorMode } = useColorMode(); const openModal = () => setModalOpen(true); const closeModal = () => setModalOpen(false); @@ -80,50 +96,81 @@ export default function ParserOpenRPC({ network, method }: ParserProps) { setReqResult(response); } catch (e) { setReqResult(e); - }; + } }; + const closeComplexTypeView = () => { + setIsComplexTypeView(false); + setIsDrawerContentFixed(false); + setDrawerLabel(null); + } + + const onModalClose = () => { + closeModal(); + closeComplexTypeView(); + } + return ( -
    -
    -
    - - + +
    +
    +
    + + +
    + + + Editing Param + + : + "Customize request"} + isOpen={isModalOpen} + onClose={onModalClose} + isContentFixed={isDrawerContentFixed} + headerLabel={drawerLabel ? drawerLabel : null} + > + +
    - - - -
    -
    -
    - - +
    +
    + + +
    -
    +
    ); } \ No newline at end of file diff --git a/src/css/custom.css b/src/css/custom.css index c0ce063a4fe..7307122adda 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -293,7 +293,38 @@ html[data-theme="light"] .api-card:hover { transition: all 0.3s; } +form { + position: relative; +} + fieldset { - border: 0; + border: none; padding: 0; -} \ No newline at end of file + margin: 0; +} + +fieldset#root { + position: relative; + padding-bottom: 10px; +} + +button:hover { + cursor: pointer; +} + +[data-theme="light"] .tippy-tooltip { + background-color: rgba(20, 22, 24, 1); +} + +[data-theme="light"] .tippy-popper[x-placement^=top] [x-arrow] { + border-top-color: rgba(20, 22, 24, 1); +} + +[data-theme="dark"] .tippy-tooltip { + background-color: rgba(255, 255, 255, 1); + color: rgba(20, 22, 24, 1); +} + +[data-theme="dark"] .tippy-popper[x-placement^=top] [x-arrow] { + border-top-color: rgba(255, 255, 255, 1); +} diff --git a/static/img/icons/chevron-left-dark-icon.svg b/static/img/icons/chevron-left-dark-icon.svg new file mode 100644 index 00000000000..bb1932ab02c --- /dev/null +++ b/static/img/icons/chevron-left-dark-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/img/icons/chevron-left-light-icon.svg b/static/img/icons/chevron-left-light-icon.svg new file mode 100644 index 00000000000..7bc727bf07f --- /dev/null +++ b/static/img/icons/chevron-left-light-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/img/icons/plus-icon.svg b/static/img/icons/plus-icon.svg new file mode 100644 index 00000000000..a1b01bb2bb1 --- /dev/null +++ b/static/img/icons/plus-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/img/icons/remove-icon.svg b/static/img/icons/remove-icon.svg new file mode 100644 index 00000000000..eee1c47bfd1 --- /dev/null +++ b/static/img/icons/remove-icon.svg @@ -0,0 +1,3 @@ + + +