Replies: 6 comments 4 replies
-
You can use This works: import {create, props} from '@stylexjs/stylex'; I do want to remove the named export for the import {stylex} from '@stylexjs/stylex'; incorrectly. |
Beta Was this translation helpful? Give feedback.
-
Actually, the parsing fails with my code.
If I rename create to createStyles, it works. import { create as createStyles, props } from "@stylexjs/stylex"; The mismatched code is: const { update, create: foo } = useEvolu(); Note when I rename create to foo, parsing works. So I have to use |
Beta Was this translation helpful? Give feedback.
-
@steida Can you share a full example of how the function was actually used? I just tested it and this works file: import { create, props } from '@stylexjs/stylex';
const styles = create({
foo: {...}
});
<div {...props(styles.foo)} />; Based on the error, it seems like you tried to use |
Beta Was this translation helpful? Give feedback.
-
@nmn Sorry I did not describe it well. Yes, your example works, but in my code, I have a variable with the same name, This is an affected file. import * as S from "@effect/schema/Schema";
import {
ExtractRow,
QueryResult,
cast,
useEvolu,
useQuery,
} from "@evolu/react";
import { AutoFocusPlugin } from "@lexical/react/LexicalAutoFocusPlugin";
import {
InitialConfigType,
LexicalComposer,
} from "@lexical/react/LexicalComposer";
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
import LexicalErrorBoundary from "@lexical/react/LexicalErrorBoundary";
import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
import { PlainTextPlugin } from "@lexical/react/LexicalPlainTextPlugin";
import * as stylex from "@stylexjs/stylex";
import { Either, Function } from "effect";
import {
$createParagraphNode,
$getRoot,
COMMAND_PRIORITY_LOW,
EditorState,
KEY_ENTER_COMMAND,
LexicalEditor,
} from "lexical";
import {
FC,
forwardRef,
useCallback,
useEffect,
useImperativeHandle,
useMemo,
useRef,
useState,
} from "react";
import { EntryId, evolu } from "../lib/Db";
import {
ContentMax10kFromContent,
Root,
contentFromEditorState,
emptyRoot,
} from "../lib/Lexical";
const newEntryId = S.parseSync(EntryId)("0".repeat(21));
export const newEntry = evolu.createQuery((db) =>
db.selectFrom("_entry").selectAll().where("id", "=", newEntryId),
);
type NewEntryRow = ExtractRow<typeof newEntry>;
type EntryEditorProps = {
autoFocus?: boolean;
localRowPromise: Promise<QueryResult<NewEntryRow>>;
} & ({ _tag: "new" } | { _tag: "edit" });
export const EntryEditor: FC<EntryEditorProps> = (props) => {
const [editorState, setEditorState] = useState<EditorState | null>(null);
const handleChange = useCallback((editorState: EditorState) => {
setEditorState(editorState);
}, []);
const content = useMemo(
() => editorState && contentFromEditorState(editorState),
[editorState],
);
const { update, create } = useEvolu();
useEffect(() => {
if (!content) return;
Either.match(content, {
// This should never happen. If EditorState can't be parsed to
// Content, it means there is something wrong with Lexical.
onLeft: (error) => {
// eslint-disable-next-line no-console
console.error(error);
},
onRight: (content) => {
update("_entry", { id: newEntryId, content });
},
});
}, [content, props, update]);
const clearEditorPluginRef = useRef<ClearEditorPluginRef>(null);
const handleKeyEnter = useCallback(() => {
if (!content) return;
content.pipe(
Either.flatMap(S.decodeEither(ContentMax10kFromContent)),
Either.match({
// TODO: Tell the user that the content is too long.
onLeft: Function.constVoid,
onRight: (content) => {
create("entry", { content, start: cast(new Date()) }, () => {
clearEditorPluginRef.current?.clear();
});
},
}),
);
}, [content, create]);
const { row } = useQuery(newEntry, { promise: props.localRowPromise });
const root = row?.content?.root;
return (
<LexicalComposer initialConfig={makeInitialEditorConfig(root)}>
<HistoryPlugin />
<EditorPlainTextPlugin />
<OnChangePlugin onChange={handleChange} />
<OnKeyEnterPlugin onKeyEnter={handleKeyEnter} />
<ClearEditorPlugin ref={clearEditorPluginRef} />
{props.autoFocus ? <AutoFocusPlugin /> : <></>}
</LexicalComposer>
);
};
export const makeInitialEditorConfig = (
root: Root = emptyRoot,
): InitialConfigType => ({
namespace: "Entry",
onError: (error: unknown) => {
// eslint-disable-next-line no-console
console.error(error);
},
theme: {
ltr: "ltr",
// min-w-[2px] to ensure caret/cursor is visible in Chrome.
paragraph: "min-w-[2px] font-sans text-base text-[#37352f] dark:text-white",
},
editorState: (editorState: LexicalEditor) => {
editorState.setEditorState(editorState.parseEditorState({ root }));
},
});
const EditorPlainTextPlugin: FC = () => {
return (
<div {...stylex.props(editorPlainTextPluginStyles.wrapper)}>
<PlainTextPlugin
contentEditable={
<ContentEditable
autoCapitalize="none"
autoCorrect="off"
// className={clsx(
// "flex flex-1 p-2 font-sans text-base text-[#37352f] dark:text-white",
// className,
// )}
/>
}
placeholder={
<div className="pointer-events-none absolute left-2 top-2 select-none overflow-hidden text-base text-[#37352f] opacity-50 dark:text-white">
What are you up to?
</div>
}
ErrorBoundary={LexicalErrorBoundary}
/>
</div>
);
};
const editorPlainTextPluginStyles = stylex.create({
wrapper: {
// display: "flex",
position: "relative",
// flexGrow: 1,
// flexShrink: 1,
// flexBasis: "0%",
},
});
const OnChangePlugin: FC<{
onChange: (editorState: EditorState) => void;
}> = ({ onChange }) => {
const [editor] = useLexicalComposerContext();
useEffect(() => {
return editor.registerUpdateListener(({ editorState }) => {
onChange(editorState);
});
}, [editor, onChange]);
return null;
};
const OnKeyEnterPlugin: FC<{
onKeyEnter: () => void;
}> = ({ onKeyEnter }) => {
const [editor] = useLexicalComposerContext();
useEffect(() => {
return editor.registerCommand(
KEY_ENTER_COMMAND,
(event: KeyboardEvent) => {
event.preventDefault();
onKeyEnter();
return true;
},
COMMAND_PRIORITY_LOW,
);
}, [editor, onKeyEnter]);
return null;
};
interface ClearEditorPluginRef {
clear: () => void;
}
const ClearEditorPlugin = forwardRef<ClearEditorPluginRef>(
function ClearEditorPlugin(props, ref) {
const [editor] = useLexicalComposerContext();
useImperativeHandle(
ref,
() => ({
clear: () => {
editor.update(() => {
const p = $createParagraphNode();
$getRoot().clear().append(p);
// Select ensures the correct caret position.
p.select();
});
},
}),
[editor],
);
return null;
},
); |
Beta Was this translation helpful? Give feedback.
-
Oh! Yeah if you already have a named import for
But I understand that this can't be auto-imported. I don't think there's any easy workaround for this. |
Beta Was this translation helpful? Give feedback.
-
I think using default exports will be useful, I am not sure if using named imports here will do tree-shaking, but it will be easier for people to straight up do: import stylex from '@stylexjs/stylex'; This can also leverage VSCode auto-import because VSCode will take the identifier name of the default export iirc. Another advantage of using default exports is that it will prevent name-clashing, because |
Beta Was this translation helpful? Give feedback.
-
We must manually write
import * as stylex from '@stylexjs/stylex'
whenever we want to style something. It's not a big deal, but it would be nice to leverage VSCode autoimport. MaybecreateStyles
andapplyStyles
would be better? Or does that belong to userland? I'm not sure how reliable compiler detection is. What do you do in Meta? Thank youBeta Was this translation helpful? Give feedback.
All reactions