swordev / suid

A port of Material-UI (MUI) built with SolidJS.
https://suid.io
MIT License
660 stars 47 forks source link

ReactToSolid Error #265

Open wakaztahir opened 10 months ago

wakaztahir commented 10 months ago

Many errors occurred during conversion from react to solid, I am trying to convert remix-ui, I think its the best ui library that if converted to solid would benefit a lot and also after shadcn-ui

Here's the error ``` throw new ManipulationError(sourceFile.getFilePath(), oldFileText, newFileText, message); ^ ManipulationError: Manipulation error: A syntax error was inserted. file.tsx:244:26 - error TS1003: Identifier expected. 244 ~ file.tsx:244:78 - error TS1382: Unexpected token. Did you mean `{'>'}` or `>`? 244 ~ Error replacing tree: The children of the old and new trees were expected to have the same count (5:3). -- Details -- Path: /file.tsx Text: "... should return to the open button\r\n \r\n\r\n
\r\n \r\n \r\n \r\n' + '
\r\n' + '\r\n' + ' {open ? (\r\n' + ' {\r\n' + ' if (dismissOnEscape === false) {\r\n' + ' event.preventDefault();\r\n' + ' }\r\n' + ' }}\r\n' + ' onPointerDownOutside={(event) => {\r\n' + ' if (dismissOnPointerDownOutside === false || event.target === openButtonRef.current) {\r\n' + ' event.preventDefault();\r\n' + ' }\r\n' + ' }}\r\n' + ' onFocusOutside={(event) => {\r\n' + ' if (dismissOnFocusOutside === false) {\r\n' + ' event.preventDefault();\r\n' + ' }\r\n' + ' }}\r\n' + ' disableOutsidePointerEvents={disabledOutsidePointerEvents}\r\n' + ' onDismiss={() => setOpen(false)}\r\n' + ' style={{\r\n' + " display: 'inline-flex',\r\n" + " justifyContent: 'center',\r\n" + " alignItems: 'center',\r\n" + " verticalAlign: 'middle',\r\n" + ' width: 400,\r\n' + ' height: 300,\r\n' + " backgroundColor: 'black',\r\n" + ' borderRadius: 10,\r\n' + ' marginBottom: 20,\r\n' + ' }}\r\n' + ' >\r\n' + ' \r\n' + ' \r\n' + ' ) : null}\r\n' + '\r\n' + '
\r\n' + ' \r\n' + ` \r\n' + '
\r\n' + '
\r\n' + ' );\r\n' + '};\r\n' + '\r\n' + 'export const Nested = () => {\r\n' + ' return (\r\n' + "
\r\n" + '

DismissableLayer (nested)

\r\n' + ' \r\n' + '
\r\n' + ' );\r\n' + '};\r\n' + '\r\n' + 'export const WithFocusScope = () => {\r\n' + ' const [open, setOpen] = React.useState(false);\r\n' + ' const openButtonRef = React.useRef(null);\r\n' + '\r\n' + ' return (\r\n' + "
\r\n" + '

DismissableLayer + FocusScope

\r\n' + '
\r\n' + ' \r\n' + '
\r\n' + '\r\n' + ' {open ? (\r\n' + ' {\r\n' + ' if (event.target === openButtonRef.current) {\r\n' + ' event.preventDefault();\r\n' + ' }\r\n' + ' }}\r\n' + ' disableOutsidePointerEvents\r\n' + ' onDismiss={() => setOpen(false)}\r\n' + ' >\r\n' + ' \r\n' + ' \r\n' + ' \r\n' + ' \r\n' + ' ) : null}\r\n' + '\r\n' + '
\r\n' + ' \r\n' + ` \r\n' + '
\r\n' + '
\r\n' + ' );\r\n' + '};\r\n' + '\r\n' + "type DismissableBoxProps = Omit;\r\n" + '\r\n' + 'function DismissableBox(props: DismissableBoxProps) {\r\n' + ' const [open, setOpen] = React.useState(false);\r\n' + ' const openButtonRef = React.useRef(null);\r\n' + '\r\n' + ' return (\r\n' + ' \r\n' + '
\r\n' + ' \r\n' + '
\r\n' + '\r\n' + ' {open ? (\r\n' + ' {\r\n' + ' if (event.target === openButtonRef.current) {\r\n' + ' event.preventDefault();\r\n' + ' }\r\n' + ' }}\r\n' + ' onFocusOutside={(event) => event.preventDefault()}\r\n' + ' onDismiss={() => setOpen(false)}\r\n' + ' />\r\n' + ' ) : null}\r\n' + ' \r\n' + ' );\r\n' + '}\r\n' + '\r\n' + 'export const DialogExample = () => (\r\n' + "
\r\n" + '

Dialog (fully modal example)

\r\n' + "
    \r\n" + '
  • ✅ focus should move inside `Dialog` when mounted
  • \r\n' + '
  • ✅ focus should be trapped inside `Dialog`
  • \r\n' + '
  • ✅ scrolling outside `Dialog` should be disabled
  • \r\n' + '
  • ✅ should be able to dismiss `Dialog` on pressing escape
  • \r\n' + '
  • ✅ focus should return to the open button
  • \r\n' + '
  • \r\n' + ' ✅ interacting outside `Dialog` should be disabled (clicking the "alert me" button shouldn\'t\r\n' + ' do anything)\r\n' + '
  • \r\n' + '
  • \r\n' + '
  • ✅ should be able to dismiss `Dialog` when interacting outside
  • \r\n' + '
  • ✅ focus should return to the open button
  • \r\n' + '
\r\n' + '\r\n' + "
\r\n" + ' \r\n' + ' \r\n' + ` \r\n' + '
\r\n' + '
\r\n' + ');\r\n' + '\r\n' + 'export const PopoverFullyModal = () => (\r\n' + "
\r\n" + '

Popover (fully modal example)

\r\n' + "
    \r\n" + '
  • ✅ focus should move inside `Popover` when mounted
  • \r\n' + '
  • ✅ focus should be trapped inside `Popover`
  • \r\n' + '
  • ✅ scrolling outside `Popover` should be disabled
  • \r\n' + '
  • ✅ should be able to dismiss `Popover` on pressing escape
  • \r\n' + '
  • ✅ focus should return to the open button
  • \r\n' + '
  • \r\n' + ' ✅ interacting outside `Popover` should be disabled (clicking the "alert me" button\r\n' + " shouldn't do anything)\r\n" + '
  • \r\n' + '
  • \r\n' + '
  • ✅ should be able to dismiss `Popover` when interacting outside
  • \r\n' + '
  • ✅ focus should return to the open button
  • \r\n' + '
\r\n' + '\r\n' + "
\r\n" + ' \r\n' + ' \r\n' + ` \r\n' + '
\r\n' + '
\r\n' + ');\r\n' + '\r\n' + 'export const PopoverSemiModal = () => {\r\n' + " const [color, setColor] = React.useState('royalblue');\r\n" + ' const changeColorButtonRef = React.useRef(null);\r\n' + ' return (\r\n' + "
\r\n" + '

Popover (semi-modal example)

\r\n' + "
    ;\r\n' + 'type FocusScopeProps = React.ComponentProps;\r\n' + '\r\n' + "export default { title: 'Utilities/DismissableLayer' };\r\n" + '\r\n' + 'const SYSTEM_FONT =\r\n' + ` '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"';\r\n` + '\r\n' + 'export const Basic = () => {\r\n' + ' const [open, setOpen] = React.useState(false);\r\n' + ' const openButtonRef = React.useRef(null);\r\n' + '\r\n' + ' const [dismissOnEscape, setDismissOnEscape] = React.useState(false);\r\n' + ' const [dismissOnPointerDownOutside, setDismissOnPointerDownOutside] = React.useState(false);\r\n' + ' const [dismissOnFocusOutside, setDismissOnFocusOutside] = React.useState(false);\r\n' + ' const [disabledOutsidePointerEvents, setDisableOutsidePointerEvents] = React.useState(false);\r\n' + '\r\n' + ' return (\r\n' + "
    \r\n" + '

    DismissableLayer

    \r\n' + '\r\n' + "
    \r\n" + " \r\n' + '\r\n' + " \r\n' + '\r\n' + " \r\n' + '\r\n' + '
    \r\n' + '\r\n' + " \r\n' + '
    \r\n' + '\r\n' + '
    \r\n' + ' \r\n' + '
    \r\n' + '\r\n' + ' {open ? (\r\n' + ' {\r\n' + ' if (dismissOnEscape === false) {\r\n' + ' event.preventDefault();\r\n' + ' }\r\n' + ' }}\r\n' + ' onPointerDownOutside={(event) => {\r\n' + ' if (dismissOnPointerDownOutside === false || event.target === openButtonRef.current) {\r\n' + ' event.preventDefault();\r\n' + ' }\r\n' + ' }}\r\n' + ' onFocusOutside={(event) => {\r\n' + ' if (dismissOnFocusOutside === false) {\r\n' + ' event.preventDefault();\r\n' + ' }\r\n' + ' }}\r\n' + ' disableOutsidePointerEvents={disabledOutsidePointerEvents}\r\n' + ' onDismiss={() => setOpen(false)}\r\n' + ' style={{\r\n' + " display: 'inline-flex',\r\n" + " justifyContent: 'center',\r\n" + " alignItems: 'center',\r\n" + " verticalAlign: 'middle',\r\n" + ' width: 400,\r\n' + ' height: 300,\r\n' + " backgroundColor: 'black',\r\n" + ' borderRadius: 10,\r\n' + ' marginBottom: 20,\r\n' + ' }}\r\n' + ' >\r\n' + ' \r\n' + ' \r\n' + ' ) : null}\r\n' + '\r\n' + '
    \r\n' + ' \r\n' + ` \r\n' + '
    \r\n' + '
    \r\n' + ' );\r\n' + '};\r\n' + '\r\n' + 'export const Nested = () => {\r\n' + ' return (\r\n' + "
    \r\n" + '

    DismissableLayer (nested)

    \r\n' + ' \r\n' + '
    \r\n' + ' );\r\n' + '};\r\n' + '\r\n' + 'export const WithFocusScope = () => {\r\n' + ' const [open, setOpen] = React.useState(false);\r\n' + ' const openButtonRef = React.useRef(null);\r\n' + '\r\n' + ' return (\r\n' + "
    \r\n" + '

    DismissableLayer + FocusScope

    \r\n' + '
    \r\n' + ' \r\n' + '
    \r\n' + '\r\n' + ' {open ? (\r\n' + ' {\r\n' + ' if (event.target === openButtonRef.current) {\r\n' + ' event.preventDefault();\r\n' + ' }\r\n' + ' }}\r\n' + ' disableOutsidePointerEvents\r\n' + ' onDismiss={() => setOpen(false)}\r\n' + ' >\r\n' + ' \r\n' + ' \r\n' + ' \r\n' + ' \r\n' + ' ) : null}\r\n' + '\r\n' + '
    \r\n' + ' \r\n' + ` \r\n' + '
    \r\n' + '
    \r\n' + ' );\r\n' + '};\r\n' + '\r\n' + "type DismissableBoxProps = Omit;\r\n" + '\r\n' + 'function DismissableBox(props: DismissableBoxProps) {\r\n' + ' const [open, setOpen] = React.useState(false);\r\n' + ' const openButtonRef = React.useRef(null);\r\n' + '\r\n' + ' return (\r\n' + ' \r\n' + '
    \r\n' + ' \r\n' + '
    \r\n' + '\r\n' + ' {open ? (\r\n' + ' {\r\n' + ' if (event.target === openButtonRef.current) {\r\n' + ' event.preventDefault();\r\n' + ' }\r\n' + ' }}\r\n' + ' onFocusOutside={(event) => event.preventDefault()}\r\n' + ' onDismiss={() => setOpen(false)}\r\n' + ' />\r\n' + ' ) : null}\r\n' + ' \r\n' + ' );\r\n' + '}\r\n' + '\r\n' + 'export const DialogExample = () => (\r\n' + "
    \r\n" + '

    Dialog (fully modal example)

    \r\n' + "
      \r\n" + '
    • ✅ focus should move inside `Dialog` when mounted
    • \r\n' + '
    • ✅ focus should be trapped inside `Dialog`
    • \r\n' + '
    • ✅ scrolling outside `Dialog` should be disabled
    • \r\n' + '
    • ✅ should be able to dismiss `Dialog` on pressing escape
    • \r\n' + '
    • ✅ focus should return to the open button
    • \r\n' + '
    • \r\n' + ' ✅ interacting outside `Dialog` should be disabled (clicking the "alert me" button shouldn\'t\r\n' + ' do anything)\r\n' + '
    • \r\n' + '
    • \r\n' + '
    • ✅ should be able to dismiss `Dialog` when interacting outside
    • \r\n' + '
    • ✅ focus should return to the open button
    • \r\n' + '
    \r\n' + '\r\n' + "
    \r\n" + ' \r\n' + ' \r\n' + ` \r\n' + '
    \r\n' + '
    \r\n' + ');\r\n' + '\r\n' + 'export const PopoverFullyModal = () => (\r\n' + "
    \r\n" + '

    Popover (fully modal example)

    \r\n' + "
      \r\n" + '
    • ✅ focus should move inside `Popover` when mounted
    • \r\n' + '
    • ✅ focus should be trapped inside `Popover`
    • \r\n' + '
    • ✅ scrolling outside `Popover` should be disabled
    • \r\n' + '
    • ✅ should be able to dismiss `Popover` on pressing escape
    • \r\n' + '
    • ✅ focus should return to the open button
    • \r\n' + '
    • \r\n' + ' ✅ interacting outside `Popover` should be disabled (clicking the "alert me" button\r\n' + " shouldn't do anything)\r\n" + '
    • \r\n' + '
    • \r\n' + '
    • ✅ should be able to dismiss `Popover` when interacting outside
    • \r\n' + '
    • ✅ focus should return to the open button
    • \r\n' + '
    \r\n' + '\r\n' + "
    \r\n" + ' \r\n' + ' \r\n' + ` \r\n' + '
    \r\n' + '
    \r\n' + ');\r\n' + '\r\n' + 'export const PopoverSemiModal = () => {\r\n' + " const [color, setColor] = React.useState('royalblue');\r\n" + ' const changeColorButtonRef = React.useRef(null);\r\n' + ' return (\r\n' + "
    \r\n" + '

    Popover (semi-modal example)

    \r\n' + "
wakaztahir commented 10 months ago

here's the whole file

Code ``` /* eslint-disable jsx-a11y/accessible-emoji */ import React from 'react'; import ReactDOM from 'react-dom'; import { FocusScope } from '../focus-scope'; import * as Popper from '../popper'; import { Portal } from '../portal'; import { FocusGuards } from '../focus-guards'; import { RemoveScroll } from 'react-remove-scroll'; import { DismissableLayer } from '../dismissable-layer'; import { Slot } from '../slot'; type DismissableLayerProps = React.ComponentProps; type FocusScopeProps = React.ComponentProps; export default { title: 'Utilities/DismissableLayer' }; const SYSTEM_FONT = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"'; export const Basic = () => { const [open, setOpen] = React.useState(false); const openButtonRef = React.useRef(null); const [dismissOnEscape, setDismissOnEscape] = React.useState(false); const [dismissOnPointerDownOutside, setDismissOnPointerDownOutside] = React.useState(false); const [dismissOnFocusOutside, setDismissOnFocusOutside] = React.useState(false); const [disabledOutsidePointerEvents, setDisableOutsidePointerEvents] = React.useState(false); return (

DismissableLayer


{open ? ( { if (dismissOnEscape === false) { event.preventDefault(); } }} onPointerDownOutside={(event) => { if (dismissOnPointerDownOutside === false || event.target === openButtonRef.current) { event.preventDefault(); } }} onFocusOutside={(event) => { if (dismissOnFocusOutside === false) { event.preventDefault(); } }} disableOutsidePointerEvents={disabledOutsidePointerEvents} onDismiss={() => setOpen(false)} style={{ display: 'inline-flex', justifyContent: 'center', alignItems: 'center', verticalAlign: 'middle', width: 400, height: 300, backgroundColor: 'black', borderRadius: 10, marginBottom: 20, }} > ) : null}
); }; export const Nested = () => { return (

DismissableLayer (nested)

); }; export const WithFocusScope = () => { const [open, setOpen] = React.useState(false); const openButtonRef = React.useRef(null); return (

DismissableLayer + FocusScope

{open ? ( { if (event.target === openButtonRef.current) { event.preventDefault(); } }} disableOutsidePointerEvents onDismiss={() => setOpen(false)} > ) : null}
); }; type DismissableBoxProps = Omit; function DismissableBox(props: DismissableBoxProps) { const [open, setOpen] = React.useState(false); const openButtonRef = React.useRef(null); return (
{open ? ( { if (event.target === openButtonRef.current) { event.preventDefault(); } }} onFocusOutside={(event) => event.preventDefault()} onDismiss={() => setOpen(false)} /> ) : null}
); } export const DialogExample = () => (

Dialog (fully modal example)

  • ✅ focus should move inside `Dialog` when mounted
  • ✅ focus should be trapped inside `Dialog`
  • ✅ scrolling outside `Dialog` should be disabled
  • ✅ should be able to dismiss `Dialog` on pressing escape
  • ✅ focus should return to the open button
  • ✅ interacting outside `Dialog` should be disabled (clicking the "alert me" button shouldn't do anything)
  • ✅ should be able to dismiss `Dialog` when interacting outside
  • ✅ focus should return to the open button
); export const PopoverFullyModal = () => (

Popover (fully modal example)

  • ✅ focus should move inside `Popover` when mounted
  • ✅ focus should be trapped inside `Popover`
  • ✅ scrolling outside `Popover` should be disabled
  • ✅ should be able to dismiss `Popover` on pressing escape
  • ✅ focus should return to the open button
  • ✅ interacting outside `Popover` should be disabled (clicking the "alert me" button shouldn't do anything)
  • ✅ should be able to dismiss `Popover` when interacting outside
  • ✅ focus should return to the open button
); export const PopoverSemiModal = () => { const [color, setColor] = React.useState('royalblue'); const changeColorButtonRef = React.useRef(null); return (

Popover (semi-modal example)

  • ✅ focus should move inside `Popover` when mounted
  • ✅ focus should be trapped inside `Popover`
  • ✅ scrolling outside `Popover` should be allowed
  • ✅ should be able to dismiss `Popover` on pressing escape
  • ✅ focus should return to the open button
  • ✅ interacting outside `Popover` should be allowed (clicking the "alert me" button should trigger)
  • ✅ should be able to dismiss `Popover` when interacting outside{' '} unless specified (ie. change color button)
  • ✅ focus should NOT return to the open button when unmounted, natural focus should occur
{ if (event.target === changeColorButtonRef.current) { event.preventDefault(); } }} />
); }; export const PopoverNonModal = () => (

Popover (non modal example)

  • ✅ focus should move inside `Popover` when mounted
  • ✅ focus should NOT be trapped inside `Popover`
  • ✅ scrolling outside `Popover` should be allowed
  • ✅ should be able to dismiss `Popover` on pressing escape
  • ✅ focus should return to the open button
  • ✅ interacting outside `Popover` should be allowed (clicking the "alert me" button should trigger)
  • ✅ should be able to dismiss `Popover` when clicking outside
  • ✅ focus should NOT return to the open button when unmounted, natural focus should occur
  • ✅ should be able to dismiss `Popover` when focus leaves it
  • ❓ focus should move to next tabbable element after open button
    notes:
    • I have left this one out for now as I am still unsure in which case it should do this
    • for the moment, focus will be returned to the open button when `FocusScope` unmounts
    • Need to do some more thinking, in the meantime, I think this behavior is ok
); export const PopoverInDialog = () => (

Popover (semi-modal) in Dialog (fully modal)

  • ✅ dismissing `Popover` by pressing escape should{' '} NOT dismiss `Dialog`
  • ✅ dismissing `Popover` by clicking outside should also dismiss `Dialog`
); export const PopoverNested = () => (

Popover (nested example)

  • ✅ dismissing a `Popover` by pressing escape should only dismiss that given `Popover`, not its parents
  • ✅ interacting outside the blue `Popover` should only dismiss itself and not its parents
  • ✅ interacting outside the red `Popover` should dismiss itself and the black one
  • ✅ unless the click wasn't outside the black one
  • ✅ when the blue `Popover` is open, there should be{' '} NO text cursor above the red or black inputs
  • ✅ when the red `Popover` is open, there should be a text cursor above the black input but not the one on the page behind
{ console.log('interact outside black'); }} > { console.log('interact outside red'); }} > { console.log('interact outside blue'); }} >
); /* ------------------------------------------------------------------------------------------------- * Dummy components * -----------------------------------------------------------------------------------------------*/ type DummyDialogProps = { children?: React.ReactNode; openLabel?: string; closeLabel?: string; }; function DummyDialog({ children, openLabel = 'Open', closeLabel = 'Close' }: DummyDialogProps) { const [open, setOpen] = React.useState(false); return ( <> {open ? (
setOpen(false)} > {children} ) : null} ); } type DummyPopoverOwnProps = { children?: React.ReactNode; openLabel?: string; closeLabel?: string; color?: string; preventScroll?: boolean; }; type DummyPopoverProps = DummyPopoverOwnProps & Omit & Omit; function DummyPopover({ children, openLabel = 'Open', closeLabel = 'Close', color = '#333', trapped = true, onEscapeKeyDown, onPointerDownOutside, onFocusOutside, onInteractOutside, disableOutsidePointerEvents = false, preventScroll = false, }: DummyPopoverProps) { const [skipUnmountAutoFocus, setSkipUnmountAutoFocus] = React.useState(false); const [open, setOpen] = React.useState(false); const openButtonRef = React.useRef(null); const ScrollContainer = preventScroll ? RemoveScroll : React.Fragment; const scrollLockWrapperProps = preventScroll ? { as: Slot } : undefined; return ( {open ? ( { setSkipUnmountAutoFocus(!disableOutsidePointerEvents); if (event.target === openButtonRef.current) { event.preventDefault(); } else { onPointerDownOutside?.(event); } }} onFocusOutside={onFocusOutside} onInteractOutside={onInteractOutside} onDismiss={() => setOpen(false)} > { if (skipUnmountAutoFocus) { event.preventDefault(); } setSkipUnmountAutoFocus(false); }} > {children} ) : null} ); } export const InPopupWindow = () => { const handlePopupClick = React.useCallback(() => { const popupWindow = window.open(undefined, undefined, 'width=300,height=300,top=100,left=100'); if (!popupWindow) { console.error('Failed to open popup window, check your popup blocker settings'); return; } const containerNode = popupWindow.document.createElement('div'); popupWindow.document.body.append(containerNode); ReactDOM.render(, containerNode); }, []); return (
); }; ```
juanrgm commented 10 months ago

There are some problems:

  1. Convert import React from 'react'; to import * as React from 'react';.
  2. Remove the emoji icons.
  3. Don't destruct the component props at DummyDialog/DummyPopover.

I will keep it in mind for future versions.

Remember that ReactToSolid is only a conversion approximation, if the code is complex, manual adaptations will need to be carried out.

wakaztahir commented 9 months ago

I came across useAssets hook , which is undocumented hook being used here

Being used here https://github.com/swordev/suid/blob/main/packages/styled-engine/src/createStyle.tsx#L81

I used the useAssets hook and it works in SolidStart, however not in Astro