I am using react-codemirror and want to highlight the text 'Hello' in the Codemirror but the match-highlighter addon is not highlighting the same. Below is the code for the same.
import React, { Component } from 'react';
import { render } from 'react-dom';
import CodeMirror from 'react-codemirror';
import 'codemirror/lib/codemirror.css';
import 'codemirror/addon/search/match-highlighter';
import 'codemirror/mode/javascript/javascript';
class App extends Component {
constructor() {
super();
this.state = {
name: 'CodeMirror',
code: '//Test Codemirror'
};
}
updateCode(newCode) {
this.setState({
code: newCode,
});
}
render() {
let options = {
lineNumbers: true,
mode: 'javascript',
highlightSelectionMatches: {
minChars: 2,
showToken: /Hello/,
style:'matchhighlight'
},
styleActiveLine: true,
styleActiveSelected: true,
};
return (
<div>
<CodeMirror value={this.state.code} onChange={this.updateCode.bind(this)} options={options}/>
</div>
);
}
}
render(<App />, document.getElementById('root'));
Current output is in the screenshot below and the word is not highlighted.
I found a solution for this issue. Inorder to enable the highlighting one need to add a css corresponding to the style property. I added the below code in css file and it started working
.cm-matchhighlight {
background: red !important
}
Now it highlights the token properly
Related
I am developing a react app which uses Editor.js as an editor and that page is working fine. But when ever i try to access other pages it gives Unhandled Rejection. This is confusing because i am importing editorjs packages only to the editor page, but it's asking for element with id "element-js".
This is editor connfig file.
const editor = new EditorJS({
holder: 'editorjs',
autofocus: true,
tools: {
paragraph: {
class: Paragraph,
inlineToolbar: true,
config: {
placeholder: 'Write Here....'
},
},
table: {
class: Table,
inlineToolbar: true,
config: {
rows: 2,
cols: 3,
},
},
header: {
class: Header,
/**
* This property will override the common settings
* That means that this tool will have only Marker and Link inline tools
* If 'true', the common settings will be used.
* If 'false' or omitted, the Inline Toolbar wont be shown
*/
inlineToolbar: true,
config: {
placeholder: 'Header'
},
shortcut: 'CMD+SHIFT+H'
},
delimiter: Delimiter,
warning: Warning,
list: {
class: List,
inlineToolbar: [
'link',
'bold'
]
},
quote: Quote,
checklist: {
class: Checklist,
inlineToolbar: true,
},
Marker: {
class: Marker,
shortcut: 'CMD+SHIFT+M',
},
embed: {
class: Embed,
inlineToolbar: false,
config: {
services: {
youtube: true,
coub: true
},
},
},
image: ImageTool,
}
});
And how i am importing:
import EditorJS from '#editorjs/editorjs';
import Header from '#editorjs/header';
import List from '#editorjs/list';
import Checklist from '#editorjs/checklist';
import Embed from '#editorjs/embed';
import Marker from '#editorjs/marker';
import Warning from '#editorjs/warning';
import Quote from '#editorjs/quote';
import Delimiter from '#editorjs/delimiter';
import ImageTool from '#editorjs/image';
import Table from "#editorjs/table";
import Paragraph from "#editorjs/paragraph";
I don't know what's the problem here. In my opinion these imports are importing globally to the whole app.
I know this is a bit late but some other people like me still arrive here with the same issue and some of us don't want to use an unofficial editor.js component.
So the issue is pretty simple, that error means that you must have an element with id editorjs in the DOM but since Im using Next.js I will explain how to use it step by step. (you won't need extra steps if you are only using React)
Create a component that looks like this: (You have to install plugins otherwise you will get some errors)
import Embed from '#editorjs/embed'
import Table from '#editorjs/table'
import List from '#editorjs/list'
import Warning from '#editorjs/warning'
import Code from '#editorjs/code'
import LinkTool from '#editorjs/link'
import Image from '#editorjs/image'
import Raw from '#editorjs/raw'
import Header from '#editorjs/header'
import Quote from '#editorjs/quote'
import Marker from '#editorjs/marker'
import CheckList from '#editorjs/checklist'
import Delimiter from '#editorjs/delimiter'
import InlineCode from '#editorjs/inline-code'
import SimpleImage from '#editorjs/simple-image'
import EditorJS from '#editorjs/editorjs'
const EditorNoSSR = ({ type }) => {
const TOOLS = {
embed: Embed,
table: Table,
marker: Marker,
list: List,
warning: Warning,
code: Code,
linkTool: LinkTool,
image: Image,
raw: Raw,
header: Header,
quote: Quote,
checklist: CheckList,
delimiter: Delimiter,
inlineCode: InlineCode,
simpleImage: SimpleImage,
}
const editor = new EditorJS({
/**
* Id of Element that should contain the Editor
*/
holder: 'editorjs',
tools: TOOLS,
})
return (<>
<div>
<div id="editorjs">
</div>
</div>
</>);
}
export default EditorNoSSR;
That is a component that you will import using next/dynamic and it will work perfectly. And to share data from this component to another you can use react's context.
Now a page where you call the component will look like this:
import { useState, useEffect } from "react";
import dynamic from "next/dynamic";
const EditorNoSSR = dynamic(() => import("../../../components/EditorNoSSR"), { ssr: false })
const EditorPage = () => {
return (<>
<EditorNoSSR />
</>);
}
export default EditorPage;
Now I have used React-editor-js and it's working fine.
https://www.npmjs.com/package/react-editor-js
I have just started using Storybook for a UI component lib I am working on. I wanted to extract JSDoc written for JS class methods and properties into Storybook and create a Doc.
Storybook does support creating doc for React components by reading its propTypes. Is there addon or someway to do the same for a JS class.
I am using the latest storybook 6.
Thanks in advance
You can do it like a normal component:
form-validators.stories.ts
import { FormValidators } from './path';
export default {
title: 'Components/Form Validators',
component: FormValidators,
parameters: {
previewTabs: { canvas: { hidden: true } },
docsOnly: true,
},
} as Meta;
export const Default: Story = () => ({
template: '<div>Test</div>',
});
Or I prefer an MDX file.
form-validators.stories.mdx
import { ArgsTable } from '#storybook/addon-docs/blocks';
import { Meta } from '#storybook/addon-docs/blocks';
import { FormValidators } from './path';
<Meta
title="Components/Form Validators"
parameters={{ previewTabs: { canvas: { hidden: true } } }}
/>
<ArgsTable of={FormValidators} />
I've been searching for a proper guidance for integrating lightgallery.js library into my application, but after several hours I did not find any solutions. Since I'm using React, I don't want to mix it with JQuery.
I've stumbled across many similar questions like this one, but since all of them are using JQuery, I can't use their solutions.
Also, I've found react-lightgallery package (React wrapper for lightgallery.js), but it does not include video support yet.
In the lightgallery.js documentation, there is the installation guidance. After completing all of the steps, importing lightgallery.js and trying to print it (as suggested here by the library owner), empty object is being shown.
What would be the best solution for this? Are there any good alternatives?
Thanks!
I have handled it this way. May be it's not complete and the best practice, but it gives you a general view to how to handle it
import React, { PureComponent } from "react";
import Gallery from "lightgallery.js";
import "lightgallery.js/dist/css/lightgallery.min.css";
class _Gallery extends PureComponent {
constructor(props) {
super(props);
this.state = {};
}
componentDidMount() {
let self = this;
this.gallery = document.getElementById("lightgallery");
lightGallery(this.gallery, {
dynamic: true,
dynamicEl: [
{
src:
"1.jpg",
thumb: "1.jpg",
subHtml:
"<h4>Fading Light</h4><p>Classic view</p>"
},
{
src:
"2.jpg",
thumb: "2.jpg",
subHtml:
"<h4>Bowness Bay</h4><p>A beautiful Sunrise</p>"
},
{
src:
"3.jpg",
thumb: "3.jpg",
subHtml: "<h4>Coniston Calmness</h4><p>Beautiful morning</p>"
}
]
});
this.gallery.addEventListener("onCloseAfter", function(event) {
window.lgData[self.gallery.getAttribute("lg-uid")].destroy(true);
self.props.onCloseGallery();
});
}
render() {
return <div id="lightgallery" />;
}
}
export default _Gallery;
Here is a working example with cloudinary at Cloudinary LightGallery
The code for the Cloundinary LightGallery React Component using Styled Components and styled css grid is below.
The Code for the upload component is in my GitHub Repo at.
UploadWidget
/* eslint-disable indent */
import React, { Component, Fragment } from 'react'
import { LightgalleryProvider, LightgalleryItem } from 'react-lightgallery'
import axios from 'axios'
import styled from 'styled-components'
import { CloudinaryContext, Transformation, Image } from 'cloudinary-react'
import { Grid, Cell } from 'styled-css-grid'
import { media } from '../../utils/mediaQuery'
import 'lightgallery.js/dist/css/lightgallery.css'
import 'lg-autoplay.js'
const SectionTitle = styled.h3`
font-size: 1em;
margin: 0.67em 0;
${media.xs`
font-size: .85em;
`}
`
class Gallery extends Component {
constructor (props) {
super(props)
this.link = React.createRef()
this.state = {
gallery: [],
isOpen: false,
link: this.href,
}
}
componentDidMount () {
// Request for images tagged cats
axios.get('https://res.cloudinary.com/mansbooks/image/list/v1557911334/cats.json')
.then(res => {
console.log(res.data.resources)
this.setState({ gallery: res.data.resources })
})
}
onLink (event) {
this.setState({ link: this.href =
`https://res.cloudinary.com/mansbooks/image/upload/${data.public_id}.jpg` })
}
uploadWidget () {
let _this = this
cloudinary.openUploadWidget({ cloud_name: 'mansbooks', upload_preset: 'photos-
preset', tags: ['cats'], sources: ['local', 'url', 'camera', 'image_search',
'facebook', 'dropbox', 'instagram'], dropboxAppKey: 'Your API Key', googleApiKey:
'Your API Key' },
function (error, result) {
// Update gallery state with newly uploaded image
_this.setState({ gallery: _this.state.gallery.concat(result) })
})
}
render () {
return (
<div>
<Fragment>
<SectionTitle>Gallery by Cloudinary</SectionTitle>
<div>
<CloudinaryContext cloudName='mansbooks'>
<Grid columns='repeat(auto-fit,minmax(260px,1fr))' id='hash'>
<LightgalleryProvider>
{
this.state.gallery.map(data => {
return (
<Cell key={data.public_id}>
<LightgalleryItem group='group1' src={`https://res.cloudinary.com/mansbooks/image/upload/${data.public_id}.jpg`} data-sub-html={'data.public_id'}>
<Image publicId={data.public_id} onClick={() => this.setState({ isOpen: true })}>
<Transformation
crop='scale'
width='250'
height='170'
radius='6'
dpr='auto'
fetchFormat='auto'
responsive_placeholder='blank'
/>
</Image>
</LightgalleryItem>
</Cell>
)
})
}
</LightgalleryProvider>
</Grid>
</CloudinaryContext>
</div>
</Fragment>
</div>
)
}
}
export default Gallery
I'm a newbie with ReactJS and I'm doing a project with ReactJS ES6. In my project, I use Froala Editor, it works perfectly. But now, I have a new feature requires Froala Editor adding input text, text area so Froala need more configuration. I don't know where to place configuration in ReactJS component. Here is my React component.
import FroalaEditor from 'react-froala-wysiwyg'
import FroalaEditorView from 'react-froala-wysiwyg/FroalaEditorView'
class RequestFormComponent extends Component {
constructor(props) {
super(props);
this.handleModelChange = this.handleModelChange.bind(this);
$.FroalaEditor.DefineIcon('insertInputField', {NAME: 'plus'});
$.FroalaEditor.RegisterCommand('insertInputField', {
title: 'Insert InputField',
focus: true,
undo: true,
refreshAfterCallback: true,
callback: function () {
this.html.insert(some input text);
}
});
this.state = this._getState();
}
_getState() {
return {
content: "Some text",
config: {
toolbarButtons: ['undo', 'redo', 'clearFormatting', 'selectAll', 'html', 'insertInputField']
}
}
}
handleModelChange(model) {
this.setState({content: model});
}
render() {
return (
<FroalaEditor
model={this.state.content}
onModelChange={this.handleModelChange}
config = {this.state.config}
/>
)
}
If I config like this, console will show error message "Cannot read property 'DefineIcon' of undefined"
I researched a lot but got nothing.
Please give me some advices to fix this issue.
I think you should import jquery:
import $ from 'jquery';
You have to import jQuery.
import $ from 'jquery';
Install jQuery by npm i jquery -s command.
And have to trigger the jQuery in componentDidMount method.
componentDidMount() {
$.FroalaEditor.DefineIcon('insertInputField', {NAME: 'plus'});
$.FroalaEditor.RegisterCommand('insertInputField', {
title: 'Insert InputField',
focus: true,
undo: true,
refreshAfterCallback: true,
callback: function () {
this.html.insert(some input text);
}
});
this.state = this._getState();
}
How do I use velocity.js UI pack effects in my react app?
With the following code thefadeOut animation is working, but slideRightIn is not.
import { VelocityTransitionGroup } from 'velocity-react';
import 'velocity-animate/velocity.ui';
class ShowForm extends React.Component {
[...]
render() {
return (
<div>
<VelocityTransitionGroup enter={{animation: "slideRightIn"}} leave={{animation: "fadeOut"}} duration="1">
{this.getActiveStep()}
</VelocityTransitionGroup>
</div>
);
}
}
The error in console is Velocity: First argument (slideRightIn) was not a property map, a known action, or a registered redirect
So the reason for this roblem was that animation name is transition.slideRightIn, not just slideRightIn.
I've been struggling with this issue for a few days...very frustrating...velocity 1.5...I've been upgrading to react 16.2. The following component code stopped working with the above mentioned error...the component is just a span wrapped in a ...Inside velocity the Velocity.Redirects[propertiesMap] only had fadeIn,fadeOut etc...not transition.xxx
import React from 'react';
import ReactDOM from 'react-dom';
import Velocity from 'velocity-animate';
import PropTypes from 'prop-types';
class StatusMessage extends React.Component {...
_animateText(text) {
var textNode = ReactDOM.findDOMNode(this.refs.textSpan),
that = this;
Velocity(textNode, "transition.shrinkIn", {
duration: 150,
delay: 50,
begin: function() {
that.setState({
text: text
});
that.animating = true;
},
complete: function() {
that.animating = false;
that.forceUpdate();
}
});
}
}
To fix it I added one import statement to my root App component...
import 'velocity-animate/velocity.ui';
class App extends React.Component { ...
I hope this helps someone else too.
Cheers!