-
Notifications
You must be signed in to change notification settings - Fork 33
How can I get common props from rSuiteComponents? #57
-
- I want to customize an existing RsTextArea in
rSuiteComponents.
Is there a way for me to get the common props to declare them in thedefine?
Because I want to inject some of my custompropsinto RsTextArea
const CustomRsTextare = define(RsTextArea, 'Custom RsTextArea') .name('Custom RsTextArea') .category('fields') .props({ // i want to get common props of RsTextarea ...commonPropsRsTextarea })
- For styling, I also want to know how to inject the common style props you implemented into my custom component?
Thank you
Beta Was this translation helpful? Give feedback.
All reactions
What is your issue with common properties? If you provide the correct definition, it should work. Below is an example of how it is implemented internally for some components.
export const inputProps = { placeholder: string.hinted('Input placeholder'), size, disabled: boolean.hinted('Disabled component').default(false), readOnly, onChange: event, } export const rsInput = define(RsInput, 'RsInput') .name('Input') .props({ label: string.default('Input').hinted('Input label'), ...inputProps, type: oneOf('text', 'password', 'email', 'number', 'search', 'tel', 'url', 'time').default('text'), value: string.valued, passwordMask: boolean.default(...
Replies: 3 comments 8 replies
-
What is your issue with common properties? If you provide the correct definition, it should work. Below is an example of how it is implemented internally for some components.
export const inputProps = { placeholder: string.hinted('Input placeholder'), size, disabled: boolean.hinted('Disabled component').default(false), readOnly, onChange: event, } export const rsInput = define(RsInput, 'RsInput') .name('Input') .props({ label: string.default('Input').hinted('Input label'), ...inputProps, type: oneOf('text', 'password', 'email', 'number', 'search', 'tel', 'url', 'time').default('text'), value: string.valued, passwordMask: boolean.default(false) })
All definitions are chainable and merge with existing definitions, allowing you to redefine or extend current components.
export const rsTextAreaDefault = define(RsTextArea, 'RsTextArea') .name('Text area') .props({ label: string.default('Text area'), value: string.default('').valued, placeholder: string, rows: positiveNumber.default(5), size, disabled: boolean.hinted('Disabled component').default(false), readOnly, onChange: event, onPressEnter: event }) export const rsTextArea = rsTextAreaDefault.name('Hinted Input').props({ hint: string.default('I am the clue!') })
Beta Was this translation helpful? Give feedback.
All reactions
-
You can define common CSS properties in the same way:
export const rsTextAreaDefault = define(RsTextArea, 'RsTextArea') .name('Text area') .props({ label: string.default('Text area'), value: string.default('').valued, placeholder: string, rows: positiveNumber.default(5), size, disabled: boolean.hinted('Disabled component').default(false), readOnly, onChange: event, onPressEnter: event }) const commonCssProps = { width: cssSize.setup({default: '100%'}).hinted('Width of the map'), padding: cssSize.setup({default: '1em'}).hinted('Padding'), border: string.setup({default: '2px solid green'}).hinted('Border'), } export const rsTextArea = rsTextAreaDefault.name('Hinted Input').props({ // @ts-ignore redefine currently broken hint: string.default('I am the clue!') }).css({ ...commonCssProps })
While the extension of wrapper styles definition is currently not implemented, it is doable.
Beta Was this translation helpful? Give feedback.
All reactions
-
The Container component is a special kind of component and is not easily extensible. Its primary purpose is to render items from the component tree. We have no current plans to change this. However, you can try overriding the computeChildren method to append content to its output. Please note that this method is part of the internal API and may change in the future.
Another option is to create a custom component, which can be composed of existing components or include drop zones. Check out this example; it is incomplete but serves as a proof of concept.
import styled from '@emotion/styled' import {containerStyles, define, node, number, useBuilderContext, useComponentData} from '@react-form-builder/core' import {useCallback, useEffect, useMemo, useState} from 'react' const SContainer = styled.div` display: flex; position: relative; z-index: 100 !important; ` const {flexDirection, gap} = containerStyles const minWidth = 50 const minHeight = 50 const CustomContainer = ({pane, width: _w, height: _h, ...rest}) => { const {store} = useComponentData() const {builderMode} = useBuilderContext() const inDesigner = builderMode === 'builder' const width = store.props?.width?.value || _w const height = store.props?.height?.value || _h const style = useMemo(() => ({ width: `${width}px`, height: `${height}px` }), [height, width]) const [isDragging, setIsDragging] = useState(false) const [startPos, setStartPos] = useState({x: 0, y: 0}) console.log({width, height, builderMode}) const handleMouseDown = useCallback((e) => { setIsDragging(true) setStartPos({x: e.clientX, y: e.clientY}) e.preventDefault() }, []) const handleMouseUp = useCallback((e) => { setIsDragging(false) e.preventDefault() }, []) useEffect(() => { const handleMouseMove = (e) => { if (!isDragging) return const deltaX = e.clientX - startPos.x const deltaY = e.clientY - startPos.y const newWidth = Math.max(width + deltaX, minWidth) const newHeight = Math.max(height + deltaY, minHeight) console.log({newWidth, newHeight}) store.props ??= {} store.props.width ??= {} store.props.width.value = newWidth store.props.height ??= {} store.props.height.value = newHeight } const handleMouseUp = () => setIsDragging(false) document.addEventListener('mousemove', handleMouseMove) document.addEventListener('mouseup', handleMouseUp) return () => { document.removeEventListener('mousemove', handleMouseMove) document.removeEventListener('mouseup', handleMouseUp) } }, [store, height, isDragging, startPos, width]) return <SContainer {...rest} style={style}> {pane} {inDesigner && <div style={{ position: 'absolute', right: 0, bottom: 0, border: '2px solid green', width: '20px', height: '20px', cursor: 'se-resize', backgroundColor: '#ccc', zIndex: 1000 }} onMouseDown={handleMouseDown} onMouseUp={handleMouseUp} />} </SContainer> } export const customContainer = define(CustomContainer, 'CustomContainer') .name('Container2') .props({ width: number.default(400), height: number.default(300), pane: node .calculable(false).hinted('A child component'), }) .css({ ...containerStyles, flexDirection: flexDirection.default('column'), gap: gap.default('10px') })
Beta Was this translation helpful? Give feedback.
All reactions
-
Thank you so much @cherepanov . One more question. I would like the width of a component, such as the Header, to always be set to max-content by default when I drag and drop it, instead of being set to 100%. How can I do this?
image
Beta Was this translation helpful? Give feedback.
All reactions
-
@tuthanhoancanh012 you need to override defaults for css property annotation
import {cssSize, define, string} from '@react-form-builder/core' ///... export const rsHeader = define(RsHeader, 'RsHeader') .name('Header') .props({ content: string.required.default('Header'), headerSize }) .css({ backgroundColor, textAlign, color, width: cssSize.setup({default: 'max-content'}).hinted('Width of the component') })
Beta Was this translation helpful? Give feedback.
All reactions
-
Hi @cherepanov, I tried following your setup, but I received a new width attribute, and the container is still 100% full
image
Based on the schema I reviewed, it only changes the CSS. What I want is to also change the wrapper CSS.
image
Beta Was this translation helpful? Give feedback.
All reactions
-
Hello @cherepanov, Can you please help check this?
Beta Was this translation helpful? Give feedback.
All reactions
-
Hi! Sorry for the delay, we've added this feature to our roadmap.
Beta Was this translation helpful? Give feedback.