From 7105fd4beb22691d04ba78a298263e369a6f178d Mon Sep 17 00:00:00 2001 From: Vladimir Nikitin Date: Tue, 12 Oct 2021 12:39:32 +0300 Subject: [PATCH 1/7] add basic confetti sandbox with confetti number and radius inputs --- package.json | 3 ++- site/index.tsx | 66 +++++++++++++++++++++++++++++++++++++++++++---- static/styles.css | 7 +++++ yarn.lock | 5 ++++ 4 files changed, 75 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 263562a..120850b 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ ], "dependencies": { "react": "^17.0.2", - "react-dom": "^17.0.2" + "react-dom": "^17.0.2", + "react-hook-form": "^7.17.2" } } diff --git a/site/index.tsx b/site/index.tsx index e21ce21..0901114 100644 --- a/site/index.tsx +++ b/site/index.tsx @@ -1,5 +1,6 @@ import ReactDOM from 'react-dom' import React, { useCallback, useEffect, useRef } from 'react' +import { useForm } from 'react-hook-form' import JSConfetti from '../src/index' import { generateRandomArrayElement } from '../src/generateRandomArrayElement' @@ -24,9 +25,17 @@ const CONFETTI_ARGS: IAddConfettiConfig[] = [ }, ] +// TODO: randomize default values +const defaultValues = { + confettiNumber: 50, + confettiRadius: 20, + useEmoji: false, +} + function App(): JSX.Element { const jsConfettiRef = useRef() + const { register, handleSubmit } = useForm({ defaultValues }) useEffect(() => { jsConfettiRef.current = new JSConfetti() @@ -40,16 +49,63 @@ function App(): JSX.Element { return () => clearTimeout(timeoutId) }, []) - const onButtonClick = useCallback(() => { + const onSubmit = useCallback((formData) => { + const { confettiNumber, confettiRadius, useEmoji } = formData if (jsConfettiRef.current) { - jsConfettiRef.current.addConfetti(generateRandomArrayElement(CONFETTI_ARGS)) + const addConfettiArgs = { + confettiNumber, + confettiRadius, + } + + // TODO: fix typescript + if (useEmoji) { + addConfettiArgs.emojis = ['🌈', '⚡️', '💥', '✨', '💫', '🌸'] + } else { + addConfettiArgs.confettiColors = ['#ffbe0b', '#fb5607', '#ff006e', '#8338ec', '#3a86ff'] + } + + jsConfettiRef.current.addConfetti(addConfettiArgs) } }, [jsConfettiRef]) return ( - <> - - +
+ + +
+ + +
+ +
+ + +
+ +
+ + +
+ + {/* TODO: add emoji select */} + {/* TODO: add confetti color select */} +
) } diff --git a/static/styles.css b/static/styles.css index 9c475e3..9f6fce7 100644 --- a/static/styles.css +++ b/static/styles.css @@ -22,6 +22,13 @@ body { justify-content: center; } +.sandbox-form { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + .button { /* reset button styles */ all: initial; diff --git a/yarn.lock b/yarn.lock index 85f2e89..43a8f28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4708,6 +4708,11 @@ react-dom@^17.0.2: object-assign "^4.1.1" scheduler "^0.20.2" +react-hook-form@^7.17.2: + version "7.17.2" + resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.17.2.tgz#235f15bb65c13e7a1198d33f2db24bcc9e27b303" + integrity sha512-oBaHwlYnbpzSFdNrs43QpcM+K2A0kUeNjV86ECYkCimlR1Ctl+tz4oQQd9plfGYkO7PJGLVMOVpUtL5EHjAcYQ== + react@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" From c0d59d04f07d64c624861a01742896802472a4e5 Mon Sep 17 00:00:00 2001 From: Vladimir Nikitin Date: Mon, 18 Oct 2021 12:34:19 +0300 Subject: [PATCH 2/7] watch useEmoji form state --- site/index.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/site/index.tsx b/site/index.tsx index 0901114..967438f 100644 --- a/site/index.tsx +++ b/site/index.tsx @@ -35,7 +35,9 @@ const defaultValues = { function App(): JSX.Element { const jsConfettiRef = useRef() - const { register, handleSubmit } = useForm({ defaultValues }) + const { register, handleSubmit, watch } = useForm({ defaultValues }) + + const watchUseEmoji = watch('useEmoji') useEffect(() => { jsConfettiRef.current = new JSConfetti() @@ -103,6 +105,16 @@ function App(): JSX.Element { /> + {watchUseEmoji ? ( +
+ EMOJI SELECT +
+ ) : ( +
+ COLORS SELECT +
+ )} + {/* TODO: add emoji select */} {/* TODO: add confetti color select */} From 45cfccf9de2aef0e66eb66be54d7b4ba531166da Mon Sep 17 00:00:00 2001 From: Vladimir Nikitin Date: Mon, 18 Oct 2021 12:41:45 +0300 Subject: [PATCH 3/7] add emoji select to sandbox --- site/index.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/site/index.tsx b/site/index.tsx index 967438f..f55c9fb 100644 --- a/site/index.tsx +++ b/site/index.tsx @@ -30,6 +30,7 @@ const defaultValues = { confettiNumber: 50, confettiRadius: 20, useEmoji: false, + emojis: ['🌈', '⚡️', '💥', '✨', '💫', '🦄'].join(' '), } @@ -52,7 +53,7 @@ function App(): JSX.Element { }, []) const onSubmit = useCallback((formData) => { - const { confettiNumber, confettiRadius, useEmoji } = formData + const { confettiNumber, confettiRadius, useEmoji, emojis } = formData if (jsConfettiRef.current) { const addConfettiArgs = { confettiNumber, @@ -61,7 +62,7 @@ function App(): JSX.Element { // TODO: fix typescript if (useEmoji) { - addConfettiArgs.emojis = ['🌈', '⚡️', '💥', '✨', '💫', '🌸'] + addConfettiArgs.emojis = emojis.split(' ') } else { addConfettiArgs.confettiColors = ['#ffbe0b', '#fb5607', '#ff006e', '#8338ec', '#3a86ff'] } @@ -107,16 +108,19 @@ function App(): JSX.Element { {watchUseEmoji ? (
- EMOJI SELECT + +
) : (
COLORS SELECT + {/* TODO: add confetti color select */}
)} - - {/* TODO: add emoji select */} - {/* TODO: add confetti color select */} ) } From 9dbd0e72e98b5fd1a8200d943d28cbc71f0289c9 Mon Sep 17 00:00:00 2001 From: Vladimir Nikitin Date: Mon, 18 Oct 2021 13:41:06 +0300 Subject: [PATCH 4/7] add ColorsSelect prototype --- site/index.tsx | 67 +++++++++++++++++++++++++++++++++++++++++------ static/styles.css | 15 +++++++++++ 2 files changed, 74 insertions(+), 8 deletions(-) diff --git a/site/index.tsx b/site/index.tsx index f55c9fb..b167a31 100644 --- a/site/index.tsx +++ b/site/index.tsx @@ -1,6 +1,6 @@ import ReactDOM from 'react-dom' import React, { useCallback, useEffect, useRef } from 'react' -import { useForm } from 'react-hook-form' +import { useForm, useFieldArray } from 'react-hook-form' import JSConfetti from '../src/index' import { generateRandomArrayElement } from '../src/generateRandomArrayElement' @@ -25,20 +25,73 @@ const CONFETTI_ARGS: IAddConfettiConfig[] = [ }, ] + +interface IColorInputProps { + color: string, + onChange: (color: string) => void, +} + +function ColorInput(props: IColorInputProps): JSX.Element { + const { color, onChange } = props + const colorPreviewStyles = { backgroundColor: color } + + return ( +
+ + {color} + DELETE BUTTON (TODO) +
+ ) +} + + +interface IColorSelectProps { + // TODO add typings + fields: any, + register: any, + colors: string[], +} + +function ColorsSelect(props: IColorSelectProps): JSX.Element { + const { fields, register, colors } = props + + return ( +
+ {fields.map((field, index) => ( +
+ + +
+ ))} +
+ ) +} + + + // TODO: randomize default values const defaultValues = { confettiNumber: 50, confettiRadius: 20, useEmoji: false, emojis: ['🌈', '⚡️', '💥', '✨', '💫', '🦄'].join(' '), + colors: ['#9b5de5', '#f15bb5', '#fee440', '#00bbf9', '#00f5d4'], } function App(): JSX.Element { const jsConfettiRef = useRef() - const { register, handleSubmit, watch } = useForm({ defaultValues }) + const { register, handleSubmit, watch, control } = useForm({ defaultValues }) + + // TODO implement add / remove + const { fields, append, prepend, remove, swap, move, insert } = useFieldArray({ + control, // control props comes from useForm (optional: if you are using FormContext) + name: "colors", // unique name for your Field Array + // keyName: "id", default to "id", you can change the key name + }) const watchUseEmoji = watch('useEmoji') + const watchColors = watch('colors') useEffect(() => { jsConfettiRef.current = new JSConfetti() @@ -53,7 +106,7 @@ function App(): JSX.Element { }, []) const onSubmit = useCallback((formData) => { - const { confettiNumber, confettiRadius, useEmoji, emojis } = formData + const { confettiNumber, confettiRadius, useEmoji, emojis, colors } = formData if (jsConfettiRef.current) { const addConfettiArgs = { confettiNumber, @@ -64,7 +117,7 @@ function App(): JSX.Element { if (useEmoji) { addConfettiArgs.emojis = emojis.split(' ') } else { - addConfettiArgs.confettiColors = ['#ffbe0b', '#fb5607', '#ff006e', '#8338ec', '#3a86ff'] + addConfettiArgs.confettiColors = colors } jsConfettiRef.current.addConfetti(addConfettiArgs) @@ -116,10 +169,8 @@ function App(): JSX.Element { /> ) : ( -
- COLORS SELECT - {/* TODO: add confetti color select */} -
+ // TODO rename fields + )} ) diff --git a/static/styles.css b/static/styles.css index 9f6fce7..ba36940 100644 --- a/static/styles.css +++ b/static/styles.css @@ -53,3 +53,18 @@ body { .button:active { background-color: #d21e99; } + +/* --------------------------------------------- */ +/* Color select */ +/* --------------------------------------------- */ +.color-input-wrapper { + display: flex; + align-items: center; +} + +.color-input-color-preview { + width: 15px; + height: 15px; + margin-right: 5px; + border-radius: 3px; +} \ No newline at end of file From f71a57558af9b31128d3151f85ac8c44c18e73a6 Mon Sep 17 00:00:00 2001 From: Vladimir Nikitin Date: Mon, 18 Oct 2021 14:21:18 +0300 Subject: [PATCH 5/7] add button to add new colors to ColorsSelect --- site/index.tsx | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/site/index.tsx b/site/index.tsx index b167a31..18dd4f8 100644 --- a/site/index.tsx +++ b/site/index.tsx @@ -49,20 +49,30 @@ interface IColorSelectProps { // TODO add typings fields: any, register: any, + append: any, + remove: any, colors: string[], } function ColorsSelect(props: IColorSelectProps): JSX.Element { - const { fields, register, colors } = props + const { fields, register, append, remove, colors } = props + + function onAddColorClick(event): void { + event.preventDefault() + + append({ value: '#ff12ab' }) + } return (
{fields.map((field, index) => (
- - + +
))} + {/* TODO: randomize new color! */} +
) } @@ -75,7 +85,7 @@ const defaultValues = { confettiRadius: 20, useEmoji: false, emojis: ['🌈', '⚡️', '💥', '✨', '💫', '🦄'].join(' '), - colors: ['#9b5de5', '#f15bb5', '#fee440', '#00bbf9', '#00f5d4'], + colors: ['#9b5de5', '#f15bb5', '#fee440', '#00bbf9', '#00f5d4'].map((color) => ({ value: color })), } @@ -117,7 +127,7 @@ function App(): JSX.Element { if (useEmoji) { addConfettiArgs.emojis = emojis.split(' ') } else { - addConfettiArgs.confettiColors = colors + addConfettiArgs.confettiColors = colors.map(({ value }) => value) } jsConfettiRef.current.addConfetti(addConfettiArgs) @@ -170,7 +180,13 @@ function App(): JSX.Element { ) : ( // TODO rename fields - + )} ) From afd69ee0db8cc0bd75ad47492094e03270e29a05 Mon Sep 17 00:00:00 2001 From: Vladimir Nikitin Date: Mon, 18 Oct 2021 14:30:49 +0300 Subject: [PATCH 6/7] implement color removing in ColorsSelect --- site/index.tsx | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/site/index.tsx b/site/index.tsx index 18dd4f8..a052b00 100644 --- a/site/index.tsx +++ b/site/index.tsx @@ -25,26 +25,6 @@ const CONFETTI_ARGS: IAddConfettiConfig[] = [ }, ] - -interface IColorInputProps { - color: string, - onChange: (color: string) => void, -} - -function ColorInput(props: IColorInputProps): JSX.Element { - const { color, onChange } = props - const colorPreviewStyles = { backgroundColor: color } - - return ( -
- - {color} - DELETE BUTTON (TODO) -
- ) -} - - interface IColorSelectProps { // TODO add typings fields: any, @@ -63,12 +43,19 @@ function ColorsSelect(props: IColorSelectProps): JSX.Element { append({ value: '#ff12ab' }) } + function onDeleteButtonClick(event, colorId) { + event.preventDefault() + + remove(colorId) + } + return (
{fields.map((field, index) => (
+
))} {/* TODO: randomize new color! */} From a5e50f891f10daf871c66d11dfd85ed4cfce448f Mon Sep 17 00:00:00 2001 From: Vladimir Nikitin Date: Mon, 18 Oct 2021 18:02:27 +0300 Subject: [PATCH 7/7] WIP move ColorsSelect to separate file and refactor --- site/ColorsSelect.tsx | 44 ++++++++++++++++++++++++++++++++++++++++++ site/index.tsx | 45 +++---------------------------------------- 2 files changed, 47 insertions(+), 42 deletions(-) create mode 100644 site/ColorsSelect.tsx diff --git a/site/ColorsSelect.tsx b/site/ColorsSelect.tsx new file mode 100644 index 0000000..7fd56d9 --- /dev/null +++ b/site/ColorsSelect.tsx @@ -0,0 +1,44 @@ +import React from 'react' + + +interface IProps { + // TODO add typings + fields: any, + register: any, + append: any, + remove: any, + colors: string[], +} + +function ColorsSelect(props: IProps): JSX.Element { + const { fields, register, append, remove, colors } = props + + function onAddColorClick(event: React.MouseEvent): void { + event.preventDefault() + + // TODO: randomize new color! + append({ value: '#ff12ab' }) + } + + function onDeleteButtonClick(event: React.MouseEvent, colorIndex: number) { + event.preventDefault() + + remove(colorIndex) + } + + return ( +
+ {fields.map((field, index: number) => ( +
+ + + +
+ ))} + + +
+ ) +} + +export default ColorsSelect diff --git a/site/index.tsx b/site/index.tsx index a052b00..f7d50f5 100644 --- a/site/index.tsx +++ b/site/index.tsx @@ -6,6 +6,7 @@ import JSConfetti from '../src/index' import { generateRandomArrayElement } from '../src/generateRandomArrayElement' import { IAddConfettiConfig } from '../src/types' +import ColorsSelect from './ColorsSelect' const CONFETTI_ARGS: IAddConfettiConfig[] = [ {}, @@ -25,46 +26,6 @@ const CONFETTI_ARGS: IAddConfettiConfig[] = [ }, ] -interface IColorSelectProps { - // TODO add typings - fields: any, - register: any, - append: any, - remove: any, - colors: string[], -} - -function ColorsSelect(props: IColorSelectProps): JSX.Element { - const { fields, register, append, remove, colors } = props - - function onAddColorClick(event): void { - event.preventDefault() - - append({ value: '#ff12ab' }) - } - - function onDeleteButtonClick(event, colorId) { - event.preventDefault() - - remove(colorId) - } - - return ( -
- {fields.map((field, index) => ( -
- - - -
- ))} - {/* TODO: randomize new color! */} - -
- ) -} - - // TODO: randomize default values const defaultValues = { @@ -81,9 +42,9 @@ function App(): JSX.Element { const { register, handleSubmit, watch, control } = useForm({ defaultValues }) // TODO implement add / remove - const { fields, append, prepend, remove, swap, move, insert } = useFieldArray({ + const { fields, append, remove } = useFieldArray({ control, // control props comes from useForm (optional: if you are using FormContext) - name: "colors", // unique name for your Field Array + name: 'colors", // unique name for your Field Array // keyName: "id", default to "id", you can change the key name })