Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

How can I get common props from rSuiteComponents? #57

Discussion options

  1. I want to customize an existing RsTextArea in rSuiteComponents.
    Is there a way for me to get the common props to declare them in the define?
    Because I want to inject some of my custom props into RsTextArea
const CustomRsTextare = define(RsTextArea, 'Custom RsTextArea')
 .name('Custom RsTextArea')
 .category('fields')
 .props({
 // i want to get common props of RsTextarea
 ...commonPropsRsTextarea
 })
image
  1. For styling, I also want to know how to inject the common style props you implemented into my custom component?
image

Thank you

You must be logged in to vote

@tuthanhoancanh012

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

Comment options

@tuthanhoancanh012

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!')
})
You must be logged in to vote
0 replies
Answer selected by sergeythrees
Comment options

@tuthanhoancanh012

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
})

image

While the extension of wrapper styles definition is currently not implemented, it is doable.

You must be logged in to vote
8 replies
Comment options

@tuthanhoancanh012

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')
 })
Comment options

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

Comment options

@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')
 
 })
Comment options

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

Comment options

Hello @cherepanov, Can you please help check this?

Comment options

Hi! Sorry for the delay, we've added this feature to our roadmap.

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /