Giter Site home page Giter Site logo

jodhman / react-eyedrop Goto Github PK

View Code? Open in Web Editor NEW
23.0 2.0 10.0 5.45 MB

Seamlessly integrate a static typed, fully-tested color-picking React component/hook!

HTML 52.48% CSS 3.36% JavaScript 4.28% TypeScript 39.87%
react eye-dropper zero-config tested custom hook component reactjs javascript

react-eyedrop's Introduction

React EyeDrop

A highly customizable, fully typed & tested color eye-dropper for your React project.

With flexibility in mind, let your users eye drop anything in your app within a minute.


React Component or React Hook, you have both at your disposal.

A example project is included for basic usage of both Component & Hook.

Credits to Sharon for such splendid taste in color.

Installation

Yarn:

yarn add react-eyedrop

NPM:

npm install --save react-eyedrop

API Reference

Table of contents

React Component

onChange

required
Expects function
Returns an object:
Available properties{ rgb: string, hex: string, customProps: object }
This returns the picked color data and the user's passed in data object, see customProps for usage.

Example:

function onChange({ rgb, hex }) {
    /* Do stuff */
}
<!-------->
<EyeDropper onChange={onChange} />

wrapperClasses

Expects string

Example:

<EyeDropper wrapperClasses="my-css-class" />
/* or even */
<EyeDropper wrapperClasses={`my-css-class ${active ? 'my-active-css-class' : ''}`} />

buttonClasses

Expects string

Example:

<EyeDropper buttonClasses="my-css-class" />
/* or even */
<EyeDropper buttonClasses={`my-css-class ${active ? 'my-active-css-class' : ''}`} />

customComponent

Expects React Node
Use your own component for your EyeDropping business.
Use the onClick prop which gets passed down.

Example:

const Button = ({ onClick }) => 
    <button className="btn" onClick={onClick} >My custom button</button>
<!-------->
<EyeDropper customComponent={Button} />

customProps

Expects object
Requires customComponent to be set
User can pass in their own data to the customComponent, the data can then be retrieved along with the color values in the onChange handler.

Example:

const onChange = ({ rgb, hex, customProps }) => {
    const { data1, data2, } = customProps
}
<!-------->
<Eyedropper customComponent={Button} customProps={{data1, data2, data3}} onChange={onChange}/>

colorsPassThrough

Expects string
Provides access to the picked color value object { rgb, hex } for the eyedropper component.
Name provided here will be the name of the color object

Example:

const Button = ({ onClick, pixelColors }) => 
    <button className="btn" onClick={onClick} style={{backgroundColor: pixelColors.hex}}>My custom button</button>
<!-------->
<EyeDropper customComponent={Button} colorsPassThrough='pixelColors' />

disabled

Expects boolean
Internal property provided by the eyedropper component for passing down to the customComponent. It gives control disabling the button element while color picking is active

Example:

const Button = ({ onClick, disabled }) => 
    <button className="btn" onClick={onClick} disabled={disabled} >My custom button</button>

once

Expects boolean
Defaults to true
Decide if EyeDropping should stop after having pressed once. Dynamically changing this property during runtime will remove event listener & set cursorInactive. (if false -> true during runtime)

Example:

<EyeDropper once />

/* or */

<EyeDropper once={false} />

pickRadius

Expects number
Range 0-450
Size of the pick radius. The final value will be the average sum of all the pixels within the radius.
radius = 1 <=> 3 x 3 blocks <=> 9 pixels
radius = 2 <=> 5 x 5 blocks <=> 25 pixels
radius = 3 <=> 7 x 7 blocks <=> 49 pixels

Example:

<EyeDropper pickRadius={1} />

cursorActive

Expects string
Defaults to copy
Decide what CSS cursor to use when actively EyeDropping.

Example:

<EyeDropper cursorActive="cursor" />

cursorInactive

Expects string
Defaults to auto
Decide what CSS cursor to revert back to once finished with EyeDropping business.

Example:

<EyeDropper cursorActive="auto" />

onInit

Expects function
Callback for componentDidMount

Example:

function getPeanut() {
    console.log('Mmm... Definately overrated.')
}

<!-------->

<EyeDropper onInit={getPeanut} />
/* Will be called when component is mounted */

onPickStart

Expects function
Callback for when you start Eyedropping

Example:

function getBananas() {
    console.log('Ahhh... Much better.')
}

<!-------->

<EyeDropper onPickStart={getBananas} />

/* Will be called when starting to EyeDrop */

onPickEnd

Expects function
Callback for when you stop EyeDropping

Example:

function buyBurritos() {
    console.log('Yum!')
}

<!-------->

<EyeDropper onPickEnd={buyBurritos} />

/* Will be called when you finish EyeDropping */

React Hook

Usage

colors will contain whatever is clicked once pickColor is called.
Call cancelPickColor to stop picking colors. ๐Ÿคช

Example:

import { useEyeDrop } from 'react-eyedrop'

const [colors, pickColor, cancelPickColor] = useEyeDrop({
  once: boolean,
  pickRadius: number,
  cursorActive: CSS Cursors,
  cursorInactive: CSS Cursors,
  onPickStart?: () => void
  onPickEnd?: () => void
  onPickCancel?: () => void
})

Link to CSS Cursors

Development setup

Run the unit tests locally:

npm i
/* or */
yarn

/* and then */

npm run test

Release History

  • 5.4.2
    • Fixed bug with color picking HTML elements
    • Now functions with React 18
  • 5.4.1
    • Added onPickStart, onPickEnd and onPickCancel to hook
  • 5.3.0
    • Now handles any HTML element with background property
  • 5.2.1
    • Added onPickEnd property
  • 5.1.3
    • Pretty serious bugfix
  • 5.0.4
    • Rewritten in TypeScript
    • Introduced useEyeDrop React hook
  • 4.2.0
    • Fixed fundamental issue with color picking
    • Now handles cross-origin images
  • 4.1.3
    • Bug fix related to color picking from the correct target
  • 4.1.2
    • No longer inline styling
  • 4.1.1
    • Added Unit test Coverage badges in README
  • 4.1.0
    • 100% Unit Test Coverage
  • 4.0.0
    • Removed property onPickEnd since same functionality can be achieved with handleChange
  • 3.4.2
    • Now supports color-picking images presented through img tags on the DOM
  • 3.0.0
    • Updated pickRadius feature to work with different units; radius & pixel.
  • 2.1.2
    • Fixed a typo in documentation
  • 2.1.1
    • Added pickRadius feature
  • 2.0.1
    • Updated documentation
  • 2.0.0
    • Changed prop name from buttonComponent to customComponent
  • 1.0.0
    • Initial release

Meta

Manjodh "Mango" Singh โ€“ [email protected]

Distributed under the MIT license. See license for more information.

https://github.com/jodhman/

Contributing

  1. Fork it (https://github.com/jodhman/react-eyedrop/fork)
  2. Create your feature branch (git checkout -b feature/fooBar)
  3. Commit your changes (git commit -am 'Add some fooBar')
  4. Push to the branch (git push origin feature/fooBar)
  5. Create a new Pull Request

react-eyedrop's People

Contributors

chanatorns avatar dependabot[bot] avatar edolyne avatar gundamftw avatar jodhman avatar paulm17 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

react-eyedrop's Issues

Example not working + errors in my own implementation

I opened #21 a while ago, and now that I am back to implementing the component using this library, I'm having issues again. The example always returns black as the color no matter what image I upload, and locally I see weird behavior again on DOM elements.

Uncaught (in promise) DOMException: Index or size is negative or greater than the allowed amount

Uncaught (in promise) DOMException: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The source width is 0.

The previously working storybook stories I had setup are now just returning these errors. Same thing in the app itself. Is anyone out there successfully using this lib?

Excessive looping on customComponent when populating eyedropper buttons using map

I am populating a bunch of eyedropper buttons using array map. Each button has 2 functions, on change, it will grab the rgb value and a value that I passed in. The second function is changing the button background color to the sampled color.

const onChange = fieldName => ({rgb, hex}) => {                
    console.log("I am from onChange");      
}

const Button = ({ onClick, colors }) => {
    console.log("I am from Button");
    return (
        <button className="btn-cls" onClick={onClick} style={{backgroundColor: colors.hex}} />
        )
}

const ButtonList = Object.keys(myItems).map((keyName, index) =>
    <td key={index}>           
        <EyeDropper            
            customComponent={Button}
            onChange={onChange(keyName)}                
            passThrough='colors'
        >
        </EyeDropper>
    </td>
 );

The problem with this is that every time I sampled a color, the Button component will be mapped again for the entire array. If I have like 20 elements in the array, it will run 20 times even though I was only using one eyedropper. In comparison, the function I passed into onChange doesn't have this problem.

Usage examples

Thanks so much for offering this library!

I was wondering if you could link to a working demo, maybe at Codesandbox or somewhere.

From the Readme, I haven't been able to figure out how to get this working.

If I use <EyeDropper pickRadius={1} onChange={onChange} /> and

function onChange({ rgb, hex }) {
    console.log({ hex });
  }

Then I just see a black oval, and clicking it just logs hex: '#000000' but never opens an eyedropper.

Thanks.

onPickStart, onPickEnd for hook

Thanks for taking the time to build this. ๐Ÿ‘

Would be awesome if you could include the events onPickStart and onPickEnd to the hook.

I have a use case where I'm using my own UI and want to know when the picker is activated or a color has been picked or feedback when cancelPickColor has been executed.

Thanks!

Allowing inline styling on the Eyedropper component?

My app has a lot of Eyedropper buttons, and I want each button itself to change to the color of its dropped color. So I need the Eyedropper button itself to take inline styling, store the sampled color to a state, and then set the button's background-color to that state.

Uncaught TypeError: html2canvas_1.default is not a function

Hello!
I'm getting this error: Uncaught TypeError: html2canvas_1.default is not a function when the click event target is anything other than the image.
If I go into node_modules/react-eyedrop/dist/useEyeDrop.js and remove .default from line 38, everything works fine.
I know you are using TypeScript for your library, and I found this issue which might be related to the issue I am opening here:
niklasvh/html2canvas#1440 (comment)

Thanks for your work and for a very useful tool!

Can't change button text to empty

I want the button to display without any text, but passing in nothing to the Eyedropper component will revert it back to the default 'eye-drop' text

<EyeDropper></EyeDropper>

Using in webview always return white as the color

I am using this library in my react app and all is working as expected, but when I open the web app in a web view in my React Native project the color returned is always white. However, when I run the web app in the mobile browser the color is returned correctly. Would you be able to provide some insight into this issue?

EDIT: Is there anyway I could get the x and y coordinates of the selected pixels? That could help debug the issue.

Better documentation?

The examples are very hard to follow. For example, the customComponent example, I copied everything and ran it. I clicked the button and click on any area in the browser to get a color, and it gave me the error

Uncaught (in promise) TypeError: y.props.onChange is not a function

I need more detail on what to do.

Invalid Hook Call

Been trying to get this package to work inside a functional component to no avail. Keep getting an invalid hook call warning.
I've tried importing both two ways.

import {Eyedropper} from 'react-eyedrop
&
import Eyedropper from 'react-eyedrop'

and then in my return am using the base example onChange call.

<Eyedropper onChange={myOnChange} />

No way to remove listener when using once={false}

I appreciate you adding the optional event listener argument once, as our designer wants our eye dropper tool to allow continuous selection, without disabling the tool, however it seems that the current implementation isn't usable.

The biggest issue is that the component has no logic for removing the click listener it adds, and relies on the listener being automatically removed once the click is completed. However, if you pass the optional argument once={false}, this tells the listener not to remove the handler after the first call (as documented here https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters). This means that if I set this prop to false, then there is no way at all to remove the event listener, so any further clicks in the browser will call the change handler and this will stack if you click the button again, which is a clear data-leak, as well as being a very broken UI.

The second, smaller issue is that the body style is set to cursorInactive whenever a selection is made, regardless of whether or not the user has opted to have once={false}. This means that, while subsequent clicks will trigger another onChange call, the cursor will not reflect that behaviour and will instead always go back to the specified inactive state, despite still being active.

Great job on this though, it's really helped me out having this publicly available

Option to define a radius when sampling color?

I want to sample color from images so a single-pixel sampling wasn't very useful. It would be better to have an option to define a sampling radius, like 3x3, and then return the averaged color.

reset cursor to default on unmounting

The cursor remains in active state even when the component unmounts (if the user did not pick any color).

Steps to reproduce:

  1. use react-eyedrop within a dialog box (eg: Popper) and set cursorActive to "crosshair"
  2. enable picking state (onPickStart), but don't pick any color
  3. Trigger closing of the Popper dialog
  4. body's cursor remains "crosshair" instead of reverting to "default"

Color selection is offset

I set up a basic example in both storybook and my own app, but both seem to have trouble grabbing colors. I tested HTML elements, a .jpg, and an .svg in multiple scenarios and the accuracy is always off. Tried in latest FF/Chrome.

I found this issue which was closed but the reporter still seemed to be having trouble. Can you please confirm that the library is working?

EyeDropper getting the wrong color

The plugin in giving me the wrong color, I have body background color set to lightgray and the eyedropper is reading it as rgb(255, 255, 255).

class App extends Component {
	handleChangeColor ({ rgb, hex }) {
		console.log(rgb);
	}
	render() {
		return (
			<div>				
				<EyeDropper
					onChange={this.handleChangeColor} />
			</div>
		);
	}
}

support compatibility with React 18

Currently with React 18, the picker selects the color as soon as you click the EyeDropper (also the case with the hook).

I checked the local example with both React17 & 18, 17 works as expected and 18 has the above mentioned issue.

Could you please support this soon? If not, I can look for alternatives.

Thanks for the nice library @jodhman ๐ŸŽ‰

Eyedrop does not work on background image

When I'm trying to use eyedrop on an element with background-image I keep getting this value:
{rgb: 'rgb(255, 255, 255)', hex: '#ffffff'}
Is it possible to inspect background-image? if not, is there any workaround to achieve the expected results?

Thanks in advance!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.