Gathering detailed insights and metrics for rc-marked-input
Gathering detailed insights and metrics for rc-marked-input
Gathering detailed insights and metrics for rc-marked-input
Gathering detailed insights and metrics for rc-marked-input
Сombine editable text with any component via annotations.
npm install rc-marked-input
Typescript
Module System
Node Version
NPM Version
TypeScript (97.33%)
JavaScript (1.49%)
CSS (0.98%)
HTML (0.21%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
11 Stars
219 Commits
2 Forks
1 Watchers
3 Branches
1 Contributors
Updated on Jul 15, 2025
Latest Version
3.1.0
Package Id
rc-marked-input@3.1.0
Unpacked Size
64.22 kB
Size
18.44 kB
File Count
5
NPM Version
10.8.2
Node Version
20.19.3
Published on
Jul 15, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
1
A React component that lets you combine editable text with any component using annotated text.
You can install the package via npm:
npm install rc-marked-input
There are many examples available in the Storybook. You can also try a template on CodeSandbox.
Here are a few examples to get you started:
1import {MarkedInput} from "rc-marked-input"; 2 3const Mark = (props) => <mark onClick={_ => alert(props.value)}>{props.label}</mark> 4 5const Marked = () => { 6 const [value, setValue] = useState("Hello, clickable marked @[world](Hello! Hello!)!") 7 return <MarkedInput Mark={Mark} value={value} onChange={setValue}/> 8}
The library allows you to configure the MarkedInput
component in two ways.
Let's declare markups and suggestions data:
1const Data = ["First", "Second", "Third", "Fourth", "Fifth", "Sixth"] 2const AnotherData = ["Seventh", "Eight", "Ninth"] 3const Primary = "@[__label__](primary:__value__)" 4const Default = "@[__label__](default)"
Using the components
1import {MarkedInput} from "rc-marked-input"; 2 3export const App = () => { 4 const [value, setValue] = useState( 5 "Enter the '@' for creating @[Primary Mark](primary:Hello!) or '/' for @[Default mark](default)!" 6 ) 7 8 return ( 9 <MarkedInput Mark={Button} value={value} onChange={setValue} options={[{ 10 markup: Primary, 11 data: Data, 12 initMark: ({label, value}) => ({label, primary: true, onClick: () => alert(value)}) 13 }, { 14 trigger: '/', 15 markup: Default, 16 data: AnotherData 17 }]}/> 18 ) 19}
Using the createMarkedInput
:
1import {createMarkedInput} from "rc-marked-input"; 2 3const ConfiguredMarkedInput = createMarkedInput({ 4 Mark: Button, 5 options: [{ 6 markup: Primary, 7 data: ['First', 'Second', 'Third', 'Fourth', 'Fifth', 'Sixth'], 8 initMark: ({label, value}) => ({label, primary: true, onClick: () => alert(value)}) 9 }, { 10 markup: Default, 11 trigger: '/', 12 data: ['Seventh', 'Eight', 'Ninth'], 13 initMark: ({label}) => ({label}) 14 }], 15}) 16 17const App = () => { 18 const [value, setValue] = useState( 19 "Enter the '@' for creating @[Primary Mark](primary:Hello!) or '/' for @[Default mark](default)!" 20 ) 21 return <ConfiguredMarkedInput value={value} onChange={setValue}/> 22}
Marks can be dynamic: editable, removable, etc. via the useMark
hook helper.
1import {MarkedInput, useMark} from "rc-marked-input"; 2 3const Mark = () => { 4 const {label, change} = useMark() 5 6 const handleInput = (e) => 7 change({label: e.currentTarget.textContent ?? "", value: " "}, {silent: true}) 8 9 return <mark contentEditable onInput={handleInput} children={label}/> 10} 11 12export const Dynamic = () => { 13 const [value, setValue] = useState("Hello, dynamical mark @[world]( )!") 14 return <MarkedInput Mark={Mark} value={value} onChange={setValue}/> 15}
Note: The silent option used to prevent re-rendering itself.
1const RemovableMark = () => { 2 const {label, remove} = useMark() 3 return <mark onClick={remove} children={label}/> 4} 5 6export const Removable = () => { 7 const [value, setValue] = useState("I @[contain]( ) @[removable]( ) by click @[marks]( )!") 8 return <MarkedInput Mark={RemovableMark} value={value} onChange={setValue}/> 9}
If passed the ref
prop of the useMark
hook in ref of a component then it component can be focused by key operations.
A default overlay is the suggestion component, but it can be easily replaced for any other.
1export const DefaultOverlay = () => { 2 const [value, setValue] = useState("Hello, default - suggestion overlay by trigger @!") 3 return <MarkedInput Mark={Mark} value={value} onChange={setValue} options={[{data: ['First', 'Second', 'Third']}]}/> 4}
1const Overlay = () => <h1>I am the overlay</h1> 2export const CustomOverlay = () => { 3 const [value, setValue] = useState("Hello, custom overlay by trigger @!") 4 return <MarkedInput Mark={Mark} Overlay={Overlay} value={value} onChange={setValue}/> 5}
1export const CustomTrigger = () => { 2 const [value, setValue] = useState("Hello, custom overlay by trigger /!") 3 return <MarkedInput Mark={() => null} Overlay={Overlay} value={value} onChange={setValue} 4 options={[{trigger: '/'}]}/> 5}
The useOverlay
has a left and right absolute coordinate of a current caret position in the style
prop.
1const Tooltip = () => { 2 const {style} = useOverlay() 3 return <div style={{position: 'absolute', ...style}}>I am the overlay</div>; 4} 5export const PositionedOverlay = () => { 6 const [value, setValue] = useState("Hello, positioned overlay by trigger @!") 7 return <MarkedInput Mark={Mark} Overlay={Tooltip} value={value} onChange={setValue}/> 8}
The useOverlay
hook provide some methods like select
for creating a new annotation.
1const List = () => { 2 const {select} = useOverlay() 3 return <ul> 4 <li onClick={() => select({label: 'First'})}>Clickable First</li> 5 <li onClick={() => select({label: 'Second'})}>Clickable Second</li> 6 </ul>; 7} 8 9export const SelectableOverlay = () => { 10 const [value, setValue] = useState("Hello, suggest overlay by trigger @!") 11 return <MarkedInput Mark={Mark} Overlay={List} value={value} onChange={setValue}/> 12}
Note: Recommend to pass the
ref
for an overlay component. It used to detect outside click.
The children
prop allows to pass elements to overrides internal components.
The div
tag for container. The span
tag for text cell.
1<ConfiguredMarkedInput value={value} onChange={setValue}> 2 <div 3 onClick={(e) => console.log('onCLick')} 4 onInput={(e) => console.log('onInput')} 5 /* other props */ 6 onBlur={(e) => console.log('onBlur')} 7 onFocus={(e) => console.log('onFocus')} 8 onKeyDown={(e) => console.log('onKeyDown')} 9 /> 10 <span className='span-class'/> 11</>
1<MarkedInput Mark={Mark} Overlay={Overlay} value={value} onChange={setValue}> option={[{ 2 trigger: '@', 3 markup: '@[__label__](__value__)', 4 data: Data, 5 initMark: getCustomMarkProps, 6}, { 7 trigger: '/', 8 markup: '@(__label__)[__value__]', 9 data: AnotherData, 10 initMark: getAnotherCustomMarkProps, 11}]}/>
Or
1const MarkedInput = createMarkedInput({ 2 Mark, Overlay, options: [{ 3 trigger: '@', 4 markup: '@[__label__](__value__)', 5 data: Data, 6 initMark: getCustomMarkProps, 7 }, { 8 trigger: '/', 9 markup: '@(__label__)[__value__]', 10 data: AnotherData, 11 initMark: getAnotherCustomMarkProps, 12 }] 13}) 14 15const App = () => <MarkedInput value={value} onChange={setValue}/>
Name | Type | Default | Description |
---|---|---|---|
value | string | undefined | Annotated text with markups for mark |
defaultValue | string | undefined | Default value |
onChange | (value: string) => void | undefined | Change event |
Mark | ComponentType<T = MarkProps> | undefined | Component that used for render markups |
Overlay | ComponentType | Suggestions | Component that is rendered by trigger |
readOnly | boolean | undefined | Prevents from changing the value |
options | OptionProps[] | [{}] | Passed options for configure |
trigger | OverlayTrigger | change | Triggering events for overlay |
Name | Type | Description |
---|---|---|
createMarkedInput | <T = MarkStruct>(configs: MarkedInputProps | Create the configured MarkedInput component. |
annotate | (markup: Markup, label: string, value?: string) => string | Make annotation from the markup |
denote | (value: string, callback: (mark: Mark) => string, ...markups: Markup[]) => string | Transform the annotated text |
useMark | () => MarkHandler | Allow to use dynamic mark |
useOverlay | () => OverlayHandler | Use overlay props |
useListener | (type, listener, deps) => void | Event listener |
1type OverlayTrigger = 2 | Array<'change' | 'selectionChange'> 3 | 'change' 4 | 'selectionChange' 5 | 'none';
1interface MarkStruct { 2 label: string 3 value?: string 4}
1interface OverlayHandler { 2 /** 3 * Style with caret absolute position. Used for placing an overlay. 4 */ 5 style: { 6 left: number; 7 top: number; 8 }; 9 /** 10 * Used for close overlay. 11 */ 12 close: () => void; 13 /** 14 * Used for insert an annotation instead a triggered value. 15 */ 16 select: (value: MarkStruct) => void; 17 /** 18 * Overlay match details 19 */ 20 match: OverlayMatch; 21 ref: RefObject<HTMLElement>; 22}
1interface MarkHandler<T> extends MarkStruct { 2 /** 3 * MarkStruct ref. Used for focusing and key handling operations. 4 */ 5 ref: RefObject<T> 6 /** 7 * Change mark. 8 * @options.silent doesn't change itself label and value, only pass change event. 9 */ 10 change: (props: MarkStruct, options?: { silent: boolean }) => void 11 /** 12 * Remove itself. 13 */ 14 remove: () => void 15 /** 16 * Passed the readOnly prop value 17 */ 18 readOnly?: boolean 19}
1type OverlayMatch = { 2 /** 3 * Found value via a overlayMatch 4 */ 5 value: string; 6 /** 7 * Triggered value 8 */ 9 source: string; 10 /** 11 * Piece of text, in which was a overlayMatch 12 */ 13 span: string; 14 /** 15 * Html element, in which was a overlayMatch 16 */ 17 node: Node; 18 /** 19 * Start position of a overlayMatch 20 */ 21 index: number; 22 /** 23 * OverlayMatch's option 24 */ 25 option: Option; 26}
1export interface Option<T = Record<string, any>> { 2 /** 3 * Template string instead of which the mark is rendered. 4 * Must contain placeholders: `__label__` and optional `__value__` 5 * @default "@[__label__](__value__)" 6 */ 7 markup?: Markup; 8 /** 9 * Sequence of symbols for calling the overlay. 10 * @default "@" 11 */ 12 trigger?: string; 13 /** 14 * Data for an overlay component. By default, it is suggestions. 15 */ 16 data?: string[]; 17 /** 18 * Function to initialize props for the mark component. Gets arguments from found markup 19 */ 20 initMark?: (props: MarkStruct) => T; 21}
If you want to contribute, you are welcome! Create an issue or start a discussion.
No vulnerabilities found.
No security vulnerabilities found.