From 46215fafb6b3122f103a10e01443c942c31ee1ff Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Sat, 13 Oct 2018 12:42:58 +0300 Subject: [PATCH 001/133] Add MappedList --- snippets/MappedList.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 snippets/MappedList.md diff --git a/snippets/MappedList.md b/snippets/MappedList.md new file mode 100644 index 000000000..bcec0f75f --- /dev/null +++ b/snippets/MappedList.md @@ -0,0 +1,31 @@ +### MappedList + +Renders a list of elements from an array of data. + +Use the value of the `isOrderedList` prop to conditionally render a `
    ` or `
+ ) : ( -}; + ); +} ``` ```jsx const names = ['John', 'Paul', 'Mary']; ReactDOM.render(, document.getElementById('root')); const users = [ { id: 8, value: 'john' }, { id: 3, value: 'paul' }]; -ReactDOM.render(, document.getElementById('root')); +ReactDOM.render( + , + document.getElementById('root') +); ``` From 593d04bc823ecfdc017f4eb8a60c8f84a26948df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Feje=C5=A1?= Date: Sat, 13 Oct 2018 12:17:28 +0200 Subject: [PATCH 003/133] add MappedTable --- snippets/mapped-table.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 snippets/mapped-table.md diff --git a/snippets/mapped-table.md b/snippets/mapped-table.md new file mode 100644 index 000000000..6bb78a2e7 --- /dev/null +++ b/snippets/mapped-table.md @@ -0,0 +1,35 @@ +### MappedTable + +Generate a table with dynamic rows based on passed array of data. Optionally include headers. + +Conditionaly check weather to include table headers or not. Use `Array.prototype.map` to map over array of data and return `` for each entry. + +```jsx +function MappedTable(props) { + return ( + + {props.headers ? return({props.headers.map((h, i)=> (h))}) : return null} + {props.data.map((v, i) => { + return ( + + v.name + + ); + })} + + ); +} +``` + +```jsx +const people = [{ id: 841, name: 'John' }, { id: 241, name: 'Jesse' }]; +const headers = ['id', 'name']; +ReactDOM.render( + , + document.getElementById('root') +); +``` + + + + From 6b554932909efb3e991faffd71eaed2ab72ecc43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Feje=C5=A1?= Date: Sat, 13 Oct 2018 13:54:20 +0200 Subject: [PATCH 004/133] fix MappedTable --- snippets/mapped-table.md | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/snippets/mapped-table.md b/snippets/mapped-table.md index 6bb78a2e7..ee6e38509 100644 --- a/snippets/mapped-table.md +++ b/snippets/mapped-table.md @@ -1,22 +1,32 @@ ### MappedTable -Generate a table with dynamic rows based on passed array of data. Optionally include headers. +Renders a table with rows dynamically created from an array of data. -Conditionaly check weather to include table headers or not. Use `Array.prototype.map` to map over array of data and return `` for each entry. +Use the value of the `headers` prop to conditionally render a table with a header. Use `Array.prototype.map` to render every item in `data` as a `` element and give it a `key`. `data` can either be an array of objects with the `id` and `value` properties or an array of primitives. Omit the `headers` prop to render a `table` without headers. ```jsx function MappedTable(props) { return ( - - {props.headers ? return({props.headers.map((h, i)=> (h))}) : return null} - {props.data.map((v, i) => { - return ( - - v.name + + + {props.headers ? ( + + {props.headers.map((h, i) => ( + + ))} - ); - })} - + ) : null} + + + {props.data.map((v, i) => { + return ( + + + + ); + })} + +
h
v.name
); } ``` @@ -30,6 +40,6 @@ ReactDOM.render( ); ``` - + - + From 43ce691869e5d07395528b840149e7def4e85bb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Feje=C5=A1?= Date: Sat, 13 Oct 2018 16:48:53 +0200 Subject: [PATCH 005/133] ommit return keyword --- snippets/mapped-table.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/snippets/mapped-table.md b/snippets/mapped-table.md index ee6e38509..892fa4915 100644 --- a/snippets/mapped-table.md +++ b/snippets/mapped-table.md @@ -18,13 +18,13 @@ function MappedTable(props) { ) : null} - {props.data.map((v, i) => { - return ( + {props.data.map((v, i) => + ( v.name ); - })} + )} ); From 135dbcaedfc86f3608baa118378ab67994accfce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Feje=C5=A1?= Date: Mon, 15 Oct 2018 19:37:13 +0200 Subject: [PATCH 006/133] update mapped-table --- snippets/mapped-table.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/snippets/mapped-table.md b/snippets/mapped-table.md index 892fa4915..6a55a17b2 100644 --- a/snippets/mapped-table.md +++ b/snippets/mapped-table.md @@ -2,25 +2,26 @@ Renders a table with rows dynamically created from an array of data. -Use the value of the `headers` prop to conditionally render a table with a header. Use `Array.prototype.map` to render every item in `data` as a `` element and give it a `key`. `data` can either be an array of objects with the `id` and `value` properties or an array of primitives. Omit the `headers` prop to render a `table` without headers. +Use the value of the `headers` prop to conditionally render a table with a header. Use `Array.prototype.map` to render every item in `data` as a `` element and give it a `key`. `data` can either be an array of objects with the `id` and `name` properties or an array of primitives. Omit the `headers` prop to render a `table` without headers. ```jsx -function MappedTable(props) { +function MappedTable({ headers, data }) { return ( - {props.headers ? ( + {headers && ( - {props.headers.map((h, i) => ( + {headers.map((h, i) => ( ))} - ) : null} + )} - {props.data.map((v, i) => + {data.map((v, i) => ( + ); From 236ade6922d1de69b0be9f2111ccf6f3aed4e70f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Feje=C5=A1?= Date: Mon, 15 Oct 2018 19:56:40 +0200 Subject: [PATCH 007/133] fix to use shorter syntax --- snippets/mapped-table.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/mapped-table.md b/snippets/mapped-table.md index 6a55a17b2..eb8df3601 100644 --- a/snippets/mapped-table.md +++ b/snippets/mapped-table.md @@ -20,7 +20,7 @@ function MappedTable({ headers, data }) { {data.map((v, i) => ( - + From 5b077a0c77352d29c02246ab297ccaa10d3af0d0 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Wed, 17 Oct 2018 10:13:11 +0300 Subject: [PATCH 008/133] Update MappedList.md --- snippets/MappedList.md | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/snippets/MappedList.md b/snippets/MappedList.md index ca7eba5a6..17b9bba5f 100644 --- a/snippets/MappedList.md +++ b/snippets/MappedList.md @@ -8,20 +8,11 @@ Use `Array.prototype.map` to render every item in `data` as a `
  • ` element and Omit the `isOrderedList` prop to render a `
      ` list by default. ```jsx -function MappedList(props) { - return props.isOrderedList ? ( -
        - {props.data.map((v, i) => ( -
      1. {v.value ? v.value : v}
      2. - ))} -
      - ) : ( -
        - {props.data.map((v, i) => ( -
      • {v.value ? v.value : v}
      • - ))} -
      - ); +function MappedList({ isOrderedList, data}) { + const list = data.map((v, i) => ( +
    • {v.value ? v.value : v}
    • + )); + return isOrderedList ?
        {list}
      :
        {list}
      ; } ``` From fc726d85a676d39f73169309fe851a62ea7d48a2 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Wed, 17 Oct 2018 10:13:33 +0300 Subject: [PATCH 009/133] Update MappedList.md --- snippets/MappedList.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/MappedList.md b/snippets/MappedList.md index 17b9bba5f..b3b1c9c2a 100644 --- a/snippets/MappedList.md +++ b/snippets/MappedList.md @@ -8,7 +8,7 @@ Use `Array.prototype.map` to render every item in `data` as a `
    • ` element and Omit the `isOrderedList` prop to render a `
        ` list by default. ```jsx -function MappedList({ isOrderedList, data}) { +function MappedList({ isOrderedList, data }) { const list = data.map((v, i) => (
      • {v.value ? v.value : v}
      • )); From 8b54ea0cda1cf72f9753b8df9a73416b0c41f37f Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Wed, 17 Oct 2018 20:31:22 +0300 Subject: [PATCH 010/133] Update MappedList.md --- snippets/MappedList.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/snippets/MappedList.md b/snippets/MappedList.md index b3b1c9c2a..2d79ced35 100644 --- a/snippets/MappedList.md +++ b/snippets/MappedList.md @@ -2,17 +2,17 @@ Renders a list of elements from an array of data. -Use the value of the `isOrderedList` prop to conditionally render a `
          ` or `
            ` list. +Use the value of the `isOrdered` prop to conditionally render a `
              ` or `
                ` list. Use `Array.prototype.map` to render every item in `data` as a `
              • ` element and give it a `key`. `data` can either be an array of objects with the `id` and `value` properties or an array of primitives. -Omit the `isOrderedList` prop to render a `
                  ` list by default. +Omit the `isOrdered` prop to render a `
                    ` list by default. ```jsx -function MappedList({ isOrderedList, data }) { +function MappedList({ isOrdered, data }) { const list = data.map((v, i) => (
                  • {v.value ? v.value : v}
                  • )); - return isOrderedList ?
                      {list}
                    :
                      {list}
                    ; + return isOrdered ?
                      {list}
                    :
                      {list}
                    ; } ``` @@ -21,7 +21,7 @@ const names = ['John', 'Paul', 'Mary']; ReactDOM.render(, document.getElementById('root')); const users = [ { id: 8, value: 'john' }, { id: 3, value: 'paul' }]; ReactDOM.render( - , + , document.getElementById('root') ); ``` From e95a0d26c75b29f020062c1d6ef18e876ee7364b Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 18 Oct 2018 19:48:42 +0300 Subject: [PATCH 011/133] Add LimitedTextarea --- snippets/LimitedTextarea | 48 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 snippets/LimitedTextarea diff --git a/snippets/LimitedTextarea b/snippets/LimitedTextarea new file mode 100644 index 000000000..74859fa66 --- /dev/null +++ b/snippets/LimitedTextarea @@ -0,0 +1,48 @@ +### LimitedTextarea + +Renders a textarea component with a character limit. + +Use the value of the `value` prop to determine the initial `state.content` and `state.characterCount` and the value of the `limit` props to determine the value of `state.limit`. +Create a method, `handleChange`, which trims the `event.target.value` data if necessary and uses `Component.prototype.setState` to update `state.content` and `state.characterCount`, and bind it to the component's context. +In the`render()` method, use a`
                    ` to wrap both the` +

                    {this.state.characterCount}/{this.props.limit}

                    +
                    + ); + } +} +``` + +```jsx +ReactDOM.render( + , + document.getElementById('root') +); +``` + +< !--tags: input,state,class -- > + +< !--expertise: 0 -- > + From 4bfd7e9ccc6b689bc70f97feb215f5a824c98f77 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 18 Oct 2018 20:04:22 +0300 Subject: [PATCH 012/133] Add PasswordRevealer --- snippets/PasswordRevealer.md | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 snippets/PasswordRevealer.md diff --git a/snippets/PasswordRevealer.md b/snippets/PasswordRevealer.md new file mode 100644 index 000000000..79d2b321f --- /dev/null +++ b/snippets/PasswordRevealer.md @@ -0,0 +1,45 @@ +### PasswordRevealer + +Renders a password input field with a reveal button. + +Initially set `state.shown` to `false` to ensure that the password is not shown by default. +Create a method, `toggleShown`, which uses `Component.prototype.setState` to change the input's state from shown to hidden and vice versa, bind it to the component's context. +In the`render()` method, use a`
                    ` to wrap both the`` and the ` +
                    + ); + } +} +``` + +```jsx +ReactDOM.render(, document.getElementById('root')); +``` + +< !--tags: input,state,class -- > + +< !--expertise: 0 -- > + From 70cc11ab3be4b404c415c896ddf7a48b81dc287e Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Fri, 19 Oct 2018 09:11:59 +0300 Subject: [PATCH 013/133] Rename LimitedTextarea to LimitedTextarea.md --- snippets/{LimitedTextarea => LimitedTextarea.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename snippets/{LimitedTextarea => LimitedTextarea.md} (100%) diff --git a/snippets/LimitedTextarea b/snippets/LimitedTextarea.md similarity index 100% rename from snippets/LimitedTextarea rename to snippets/LimitedTextarea.md From 439a3b618947e9080cbe011fc14e66e57cafa823 Mon Sep 17 00:00:00 2001 From: russ_zhong Date: Fri, 26 Oct 2018 11:12:24 +0800 Subject: [PATCH 014/133] add modal/dialog --- snippets/ModalDialog.md | 106 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 snippets/ModalDialog.md diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md new file mode 100644 index 000000000..cec15cf4f --- /dev/null +++ b/snippets/ModalDialog.md @@ -0,0 +1,106 @@ +### Modal/Dialog + +Renders a dialog component with modal. + +This is a simple React ModalDialog Component.It owns 4 props: `show`、`close`、`title` and `clickModal2Hide`. + +* `show` prop determines the initial state of the dialog(show/hide).It can influence the `display` css property of `modal` class div.E +* `close` prop defines the method for closing the dialog. +* `title` prop determines the title of the dialog. +* `clickModal2Hide` prop determines whether we can close the dialog via clicking on modal. + +Create 3 methods and bind them to component: + +* `close` used to call the `close` prop to close the dialog. +* `modalClick` used to define the click event handler of the modal.When `clickModal2Hide` prop passed as `true`,the `modalClick` will close the dialog when modal clicked. +* `dialogClick` used to stop propagation of the modal click event.You can define more logics in this method. + +Use `children` prop to get the content of the dialog passed by Component User.Render the content in `dialog-content` class div. + +```css + .modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.6); + z-index: 9998; + display: flex; + justify-content: center; + align-items: center; + } + .dialog { + background-color: white; + border-radius: 5px; + overflow: hidden; + } + .dialog-title { + box-sizing: border-box; + width: 100%; + height: 48px; + padding: 0 16px; + border-bottom: 0.5px solid #c3c3c3; + display: flex; + justify-content: space-between; + align-items: center; + } + .dialog-close { + font-size: 32px; + color: #c3c3c3; + cursor: pointer; + transform: rotate(45deg); + user-select: none; + } + .dialog-close:hover { + color: red; + } + .dialog-content { + min-width: 300px; + } +``` + +```jsx + class Dialog extends React.Component { + constructor() { + super(); + this.close = this.close.bind(this); + this.modalClick = this.modalClick.bind(this); + this.dialogClick = this.dialogClick.bind(this); + } + render() { + return
                    +
                    +
                    { this.props.title }+
                    +
                    + { + this.props.children + } +
                    +
                    +
                    + } + close() { + this.props.close(); + } + modalClick() { + if (this.props.clickModal2Hide) { + this.close(); + } + } + dialogClick(e) { + e.stopPropagation(); + } + } +``` + +```jsx + let ModalDialog = {this.setState({visible: false})}}> + + ; + ReactDOM.render(, Node); +``` + + + + From 20b431295fb93929facc05d58d8de42377a4e754 Mon Sep 17 00:00:00 2001 From: Dani Date: Sat, 27 Oct 2018 14:35:37 -0300 Subject: [PATCH 015/133] Create Toggle.md snippet --- snippets/Toggle.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 snippets/Toggle.md diff --git a/snippets/Toggle.md b/snippets/Toggle.md new file mode 100644 index 000000000..f70a12fff --- /dev/null +++ b/snippets/Toggle.md @@ -0,0 +1,58 @@ +### Toggle + +Renders a toggle component. + +The `state` of the component default to `false` and bind the `handleClick` method to the component's context. +Use an object, `style`, to hold the styles for individual components and their states. +Create a method, `handleClick`, which uses `Component.prototype.setState` to change the component's `state` from toggleOn to toggleOff and vice versa. +In the `render()` method, destruct `state` and `style` to abbreviate typing, use a ` + ); + } +} +``` + +```jsx +ReactDOM.render(, document.getElementById('root')); +``` + + + + \ No newline at end of file From cea83f45b2c405eabe9658ab357a184223355b4c Mon Sep 17 00:00:00 2001 From: russ_zhong Date: Thu, 8 Nov 2018 14:31:10 +0800 Subject: [PATCH 016/133] support single instance, call dialog via custom event --- snippets/ModalDialog.md | 91 ++++++++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 32 deletions(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index cec15cf4f..a6e3114bf 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -61,44 +61,71 @@ Use `children` prop to get the content of the dialog passed by Component User.Re ``` ```jsx - class Dialog extends React.Component { - constructor() { - super(); - this.close = this.close.bind(this); - this.modalClick = this.modalClick.bind(this); - this.dialogClick = this.dialogClick.bind(this); - } - render() { - return
                    -
                    -
                    { this.props.title }+
                    -
                    - { - this.props.children - } -
                    +class Dialog extends React.Component { + constructor() { + super(); + this.modalHandler = (e) => { + this.setState({ + data: e.detail.data, + visible: true + }); + }; + this.state = { + data: { + title: '', + content: '' + }, + visible: false + }; + this.close = this.close.bind(this); + this.modalClick = this.modalClick.bind(this); + } + render() { + return
                    +
                    +
                    { this.state.data.title }+
                    +
                    + { + this.state.data.content + }
                    - } - close() { - this.props.close(); - } - modalClick() { - if (this.props.clickModal2Hide) { - this.close(); - } - } - dialogClick(e) { - e.stopPropagation(); - } +
                    } + componentDidMount() { + document.addEventListener('modal', this.modalHandler); + } + componentWillUnmount() { + document.removeEventListener('modal', this.modalHandler); + } + close() { + this.setState({ + visible: false + }); + } + static show(data) { + document.dispatchEvent(new CustomEvent('modal', { + detail: { + data + } + })); + } + modalClick() { + if (this.props.clickModal2Hide) this.close(); + } +} ``` ```jsx - let ModalDialog = {this.setState({visible: false})}}> - - ; - ReactDOM.render(, Node); +// add to render function + + +// every time you wanna call the dialog +// content is a jsx element +ModalDialog.show({ + title: 'Test', + content: +}); ``` From bb25e3a01a3aa6f90174e4b63fcc67103f3cb949 Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Thu, 8 Nov 2018 16:03:49 +0800 Subject: [PATCH 017/133] Delete show prop Co-Authored-By: zhongdeming428 --- snippets/ModalDialog.md | 1 - 1 file changed, 1 deletion(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index a6e3114bf..939803bed 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -4,7 +4,6 @@ Renders a dialog component with modal. This is a simple React ModalDialog Component.It owns 4 props: `show`、`close`、`title` and `clickModal2Hide`. -* `show` prop determines the initial state of the dialog(show/hide).It can influence the `display` css property of `modal` class div.E * `close` prop defines the method for closing the dialog. * `title` prop determines the title of the dialog. * `clickModal2Hide` prop determines whether we can close the dialog via clicking on modal. From bb4b5272fed90752134fc180e35f68c4379b5de1 Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Thu, 8 Nov 2018 16:05:30 +0800 Subject: [PATCH 018/133] modify clickModal2Hide prop to closeOnClick prop Co-Authored-By: zhongdeming428 --- snippets/ModalDialog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index 939803bed..486e7075f 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -6,7 +6,7 @@ This is a simple React ModalDialog Component.It owns 4 props: `show`、`close` * `close` prop defines the method for closing the dialog. * `title` prop determines the title of the dialog. -* `clickModal2Hide` prop determines whether we can close the dialog via clicking on modal. +* `closeOnClick` prop determines whether we can close the dialog via clicking on modal. Create 3 methods and bind them to component: From ae533920ea57fd2ad61b88038d62991e3ce055cb Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Thu, 8 Nov 2018 16:05:52 +0800 Subject: [PATCH 019/133] Update snippets/ModalDialog.md Co-Authored-By: zhongdeming428 --- snippets/ModalDialog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index 486e7075f..bcae5417c 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -110,7 +110,7 @@ class Dialog extends React.Component { })); } modalClick() { - if (this.props.clickModal2Hide) this.close(); + if (this.props.closeOnClick) this.close(); } } ``` From af0c37716345c409b6630b400429f3d591f5b0c9 Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Thu, 8 Nov 2018 16:05:58 +0800 Subject: [PATCH 020/133] Update snippets/ModalDialog.md Co-Authored-By: zhongdeming428 --- snippets/ModalDialog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index bcae5417c..22a71e51a 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -117,7 +117,7 @@ class Dialog extends React.Component { ```jsx // add to render function - + // every time you wanna call the dialog // content is a jsx element From fabbe845be133a36e758072555010552e0b2d2c7 Mon Sep 17 00:00:00 2001 From: russ_zhong Date: Thu, 8 Nov 2018 16:49:17 +0800 Subject: [PATCH 021/133] update the whole doc --- snippets/ModalDialog.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index 22a71e51a..d28b54ee6 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -2,19 +2,22 @@ Renders a dialog component with modal. -This is a simple React ModalDialog Component.It owns 4 props: `show`、`close`、`title` and `clickModal2Hide`. +This is a simple React ModalDialog Component.It owns only one prop: `closeOnClick`. -* `close` prop defines the method for closing the dialog. -* `title` prop determines the title of the dialog. * `closeOnClick` prop determines whether we can close the dialog via clicking on modal. -Create 3 methods and bind them to component: +Benefits from the CustomEvent API,this ModalDialog component supports single instance usage.We just need import `Dialog` once time,and can call the dialog everywhere.Every time we wanna show the dialog,we just call the static function `Dialog.show`.Passing our jsx templates and data as the parameter and then the dialog will show with the data and templates rendered. -* `close` used to call the `close` prop to close the dialog. -* `modalClick` used to define the click event handler of the modal.When `clickModal2Hide` prop passed as `true`,the `modalClick` will close the dialog when modal clicked. -* `dialogClick` used to stop propagation of the modal click event.You can define more logics in this method. +After the component mounted,Dialog binds a custom event called 'modal' to document element.The event handler defined in our component named `modalHandler`.It accepts and renders the data passed by users.When document node captured a `modal` event,`modalHandler` works. -Use `children` prop to get the content of the dialog passed by Component User.Render the content in `dialog-content` class div. +Before the component unmounted,Dialog removes the custom event from document element in case of memory leaks. + +Dialog exposed the `show` method via using `static` reserved keyword so that we can call it through Dialog class.The `show` method accepts a object parameter that contains two properties:`title` and `content`. + +* `title` is the text you wanna show as the title of the dialog,passed as a String. +* `content` is a jsx element.Dialog will render it.You can pass any content you want to show in the dialog. + +See the live demo on [stackblitz.com](https://stackblitz.com/edit/react-7yg2gr). ```css .modal { From ca9038c759c607926b0eb5e619d91de3c8aa7cdd Mon Sep 17 00:00:00 2001 From: russ_zhong Date: Thu, 8 Nov 2018 16:56:22 +0800 Subject: [PATCH 022/133] update the code --- snippets/ModalDialog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index d28b54ee6..0ffac7de1 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -124,7 +124,7 @@ class Dialog extends React.Component { // every time you wanna call the dialog // content is a jsx element -ModalDialog.show({ +Dialog.show({ title: 'Test', content: }); From 22529619a44144f1e91469c1eece182e260c3962 Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Fri, 9 Nov 2018 08:34:14 +0800 Subject: [PATCH 023/133] Update snippets/ModalDialog.md Co-Authored-By: zhongdeming428 --- snippets/ModalDialog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index 0ffac7de1..13eabc9f8 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -2,7 +2,7 @@ Renders a dialog component with modal. -This is a simple React ModalDialog Component.It owns only one prop: `closeOnClick`. +This is a simple React ModalDialog Component that is called and controlled through events * `closeOnClick` prop determines whether we can close the dialog via clicking on modal. From bbd7d943024d94443c98dbb378b5411e4d20b4a1 Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Fri, 9 Nov 2018 08:34:30 +0800 Subject: [PATCH 024/133] Update snippets/ModalDialog.md Co-Authored-By: zhongdeming428 --- snippets/ModalDialog.md | 1 - 1 file changed, 1 deletion(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index 13eabc9f8..eef6e9952 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -4,7 +4,6 @@ Renders a dialog component with modal. This is a simple React ModalDialog Component that is called and controlled through events -* `closeOnClick` prop determines whether we can close the dialog via clicking on modal. Benefits from the CustomEvent API,this ModalDialog component supports single instance usage.We just need import `Dialog` once time,and can call the dialog everywhere.Every time we wanna show the dialog,we just call the static function `Dialog.show`.Passing our jsx templates and data as the parameter and then the dialog will show with the data and templates rendered. From e65db00c4e4722fcfb33f1cccfdd2c1bcaa2644c Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Fri, 9 Nov 2018 08:35:14 +0800 Subject: [PATCH 025/133] Update snippets/ModalDialog.md Co-Authored-By: zhongdeming428 --- snippets/ModalDialog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index eef6e9952..3488a712b 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -11,7 +11,7 @@ After the component mounted,Dialog binds a custom event called 'modal' to docume Before the component unmounted,Dialog removes the custom event from document element in case of memory leaks. -Dialog exposed the `show` method via using `static` reserved keyword so that we can call it through Dialog class.The `show` method accepts a object parameter that contains two properties:`title` and `content`. +Dialog exposed the `show` method via using `static` reserved keyword so that we can call it through Dialog class.The `show` method accepts a object parameter that contains three properties: `title`, `closeOnClick`, and `content`. * `title` is the text you wanna show as the title of the dialog,passed as a String. * `content` is a jsx element.Dialog will render it.You can pass any content you want to show in the dialog. From 35e59b47e21fa7b96a7e7ec987f79e91ecec69fe Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Fri, 9 Nov 2018 08:35:55 +0800 Subject: [PATCH 026/133] Update snippets/ModalDialog.md Co-Authored-By: zhongdeming428 --- snippets/ModalDialog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index 3488a712b..9673f093d 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -14,6 +14,7 @@ Before the component unmounted,Dialog removes the custom event from document ele Dialog exposed the `show` method via using `static` reserved keyword so that we can call it through Dialog class.The `show` method accepts a object parameter that contains three properties: `title`, `closeOnClick`, and `content`. * `title` is the text you wanna show as the title of the dialog,passed as a String. +* `closeOnClick` is a boolean to determine if the modal should close when clicked on(true), or only when the X button is pressed(false). * `content` is a jsx element.Dialog will render it.You can pass any content you want to show in the dialog. See the live demo on [stackblitz.com](https://stackblitz.com/edit/react-7yg2gr). From 52a68f98509caada585241cc2521e055cf830555 Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Fri, 9 Nov 2018 08:36:11 +0800 Subject: [PATCH 027/133] Update snippets/ModalDialog.md Co-Authored-By: zhongdeming428 --- snippets/ModalDialog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index 9673f093d..cb1dd81ee 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -75,6 +75,7 @@ class Dialog extends React.Component { this.state = { data: { title: '', + closeOnClick: false, content: '' }, visible: false From d808d77ad28b25f6eb729f1c06bf112ab29c329a Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Fri, 9 Nov 2018 08:37:06 +0800 Subject: [PATCH 028/133] Update snippets/ModalDialog.md Co-Authored-By: zhongdeming428 --- snippets/ModalDialog.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index cb1dd81ee..6da38b46b 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -103,7 +103,12 @@ class Dialog extends React.Component { } close() { this.setState({ - visible: false + visible: false, + data: { + title: '', + closeOnClick: false, + content: '' + } }); } static show(data) { From 95c4c3524e6de117044b50f8c9b553a231152ec3 Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Fri, 9 Nov 2018 08:37:12 +0800 Subject: [PATCH 029/133] Update snippets/ModalDialog.md Co-Authored-By: zhongdeming428 --- snippets/ModalDialog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index 6da38b46b..302fd497d 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -119,7 +119,7 @@ class Dialog extends React.Component { })); } modalClick() { - if (this.props.closeOnClick) this.close(); + if (this.state.data.closeOnClick) this.close(); } } ``` From a5ac8bf24ceeb6fb278b722dfc6e39ca31c46d23 Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Fri, 9 Nov 2018 08:37:19 +0800 Subject: [PATCH 030/133] Update snippets/ModalDialog.md Co-Authored-By: zhongdeming428 --- snippets/ModalDialog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index 302fd497d..6647eb41b 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -126,7 +126,7 @@ class Dialog extends React.Component { ```jsx // add to render function - + // every time you wanna call the dialog // content is a jsx element From 9e1f036ddd35fcee884eaa3510975ac3ad8a173f Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Fri, 9 Nov 2018 08:37:29 +0800 Subject: [PATCH 031/133] Update snippets/ModalDialog.md Co-Authored-By: zhongdeming428 --- snippets/ModalDialog.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index 6647eb41b..121e22ac7 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -131,7 +131,8 @@ class Dialog extends React.Component { // every time you wanna call the dialog // content is a jsx element Dialog.show({ - title: 'Test', + title: 'Test', + closeOnClick: true, content: }); ``` From 16d28e31a253049f5ee0e12ef91a5578a16f737c Mon Sep 17 00:00:00 2001 From: "DM.Zhong" Date: Fri, 9 Nov 2018 08:45:56 +0800 Subject: [PATCH 032/133] Update ModalDialog.md --- snippets/ModalDialog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index 121e22ac7..e624cd639 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -2,12 +2,12 @@ Renders a dialog component with modal. -This is a simple React ModalDialog Component that is called and controlled through events +This is a simple React ModalDialog Component that is called and controlled through events. Benefits from the CustomEvent API,this ModalDialog component supports single instance usage.We just need import `Dialog` once time,and can call the dialog everywhere.Every time we wanna show the dialog,we just call the static function `Dialog.show`.Passing our jsx templates and data as the parameter and then the dialog will show with the data and templates rendered. -After the component mounted,Dialog binds a custom event called 'modal' to document element.The event handler defined in our component named `modalHandler`.It accepts and renders the data passed by users.When document node captured a `modal` event,`modalHandler` works. +After the component mounted,Dialog binds a custom event called `modal` to document element.The event handler defined in our component named `modalHandler`.It accepts and renders the data passed by users.When document node captured a `modal` event,`modalHandler` works. Before the component unmounted,Dialog removes the custom event from document element in case of memory leaks. From 9e6a9aacea48e187fb5b1dd372ad89cdb736aa58 Mon Sep 17 00:00:00 2001 From: Rishi Kumar Chawda Date: Tue, 13 Nov 2018 23:51:24 +0530 Subject: [PATCH 033/133] feat(snippets): Add tooltip snippet --- snippets/Tooltip.md | 69 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 snippets/Tooltip.md diff --git a/snippets/Tooltip.md b/snippets/Tooltip.md new file mode 100644 index 000000000..12362ae0d --- /dev/null +++ b/snippets/Tooltip.md @@ -0,0 +1,69 @@ +### Tooltip + +Renders a tooltip component. +

                    + + The `show` property on the component state is set to `false` as default. + + Use an object, `style`, to hold the styles for the component. + + Create a method, `toggleTooltip`, which uses `this.setState` to change the state's `show` property from `true` to `false` and vice versa. + + In the `render()` method, destructure `state` and `props`, compute if visibility style should be set to `visible` or not and apply the combined style + to the tooltip component. + + Render the `children` as sibling to the tooltip using [React.cloneElement](https://reactjs.org/docs/react-api.html#cloneelement) and pass down rest + props along with `onMouseEnter` and `onMouseLeave` events which we bind to the `toggleTooltip` call. + + +```jsx +class Tooltip extends React.Component { + constructor(props) { + super(props); + this.state = { + show: false + }; + this.style = { + tooltip: { + backgroundColor: "rgba(0,0,0,0.7)", + color: "white", + visibility: "hidden", + width: "fit-content", + padding: 5, + borderRadius: 5 + }, + visible: { + visibility: "visible" + } + }; + } + + toggleTooltip = tooltipState => { + this.setState({ + show: tooltipState + }); + }; + + render() { + const { children, ...rest } = this.props; + const { show } = this.state; + const { visible, tooltip } = this.style; + const showTooltip = show ? visible : {}; + return ( +
                    +
                    + This is a simple tooltip +
                    + {React.cloneElement(children, { + ...rest, + onMouseEnter: () => this.toggleTooltip(true), + onMouseLeave: () => this.toggleTooltip(false) + })} +
                    + ); + } +} +``` +```jsx + ReactDOM.render(, document.getElementById('root')); + ``` From c7df4b2e5c0d8cf5d1df50dde6eab450aa3776e4 Mon Sep 17 00:00:00 2001 From: Rishi Kumar Date: Wed, 14 Nov 2018 01:03:37 +0530 Subject: [PATCH 034/133] fix(snippets/tooltip): remove html line break --- snippets/Tooltip.md | 1 - 1 file changed, 1 deletion(-) diff --git a/snippets/Tooltip.md b/snippets/Tooltip.md index 12362ae0d..11d65925f 100644 --- a/snippets/Tooltip.md +++ b/snippets/Tooltip.md @@ -1,7 +1,6 @@ ### Tooltip Renders a tooltip component. -

                    The `show` property on the component state is set to `false` as default. From c473dc9e39b4b40a6193c29127e20e6e13eed375 Mon Sep 17 00:00:00 2001 From: Rishi Kumar Date: Wed, 14 Nov 2018 01:05:16 +0530 Subject: [PATCH 035/133] fix(snippet/tooltip): remove render lvl binding --- snippets/Tooltip.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/snippets/Tooltip.md b/snippets/Tooltip.md index 11d65925f..24dcac591 100644 --- a/snippets/Tooltip.md +++ b/snippets/Tooltip.md @@ -35,6 +35,8 @@ class Tooltip extends React.Component { visibility: "visible" } }; + this.showTooltip = this.toggleTooltip.bind(this, true); + this.hideTooltip = this.toggleTooltip.bind(this, false); } toggleTooltip = tooltipState => { @@ -55,8 +57,8 @@ class Tooltip extends React.Component {
                    {React.cloneElement(children, { ...rest, - onMouseEnter: () => this.toggleTooltip(true), - onMouseLeave: () => this.toggleTooltip(false) + onMouseEnter: this.showTooltip, + onMouseLeave: this.hideTooltip })}
                    ); From a8b40079c50fd32d99a883913d1cd3e8d314f337 Mon Sep 17 00:00:00 2001 From: Rishi Kumar Chawda Date: Wed, 14 Nov 2018 22:20:59 +0530 Subject: [PATCH 036/133] update tooltip.md --- snippets/Tooltip.md | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/snippets/Tooltip.md b/snippets/Tooltip.md index 24dcac591..22cc792d1 100644 --- a/snippets/Tooltip.md +++ b/snippets/Tooltip.md @@ -24,6 +24,7 @@ class Tooltip extends React.Component { }; this.style = { tooltip: { + position: 'relative', backgroundColor: "rgba(0,0,0,0.7)", color: "white", visibility: "hidden", @@ -31,9 +32,17 @@ class Tooltip extends React.Component { padding: 5, borderRadius: 5 }, + tooltipArrow: { + position: 'absolute', + top: '100%', + left: '50%', + borderWidth: 5, + borderStyle: 'solid', + borderColor: "rgba(0,0,0,0.7) transparent transparent", + }, visible: { visibility: "visible" - } + }, }; this.showTooltip = this.toggleTooltip.bind(this, true); this.hideTooltip = this.toggleTooltip.bind(this, false); @@ -46,25 +55,29 @@ class Tooltip extends React.Component { }; render() { - const { children, ...rest } = this.props; + const { children, text, ...rest } = this.props; const { show } = this.state; - const { visible, tooltip } = this.style; + const { visible, tooltip, tooltipArrow } = this.style; const showTooltip = show ? visible : {}; return (
                    - This is a simple tooltip + {text} + +
                    +
                    + {children}
                    - {React.cloneElement(children, { - ...rest, - onMouseEnter: this.showTooltip, - onMouseLeave: this.hideTooltip - })}
                    ); } } ``` ```jsx - ReactDOM.render(, document.getElementById('root')); + ReactDOM.render( + + + , + document.getElementById('root') + ); ``` From ed2e5a247de6ba61f667cb3b8389743dedf97a1b Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Thu, 15 Nov 2018 23:21:55 +0800 Subject: [PATCH 037/133] Update snippets/ModalDialog.md Co-Authored-By: zhongdeming428 --- snippets/ModalDialog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/ModalDialog.md b/snippets/ModalDialog.md index e624cd639..10ad93216 100644 --- a/snippets/ModalDialog.md +++ b/snippets/ModalDialog.md @@ -84,7 +84,7 @@ class Dialog extends React.Component { this.modalClick = this.modalClick.bind(this); } render() { - return
                    + return !this.state.visible ? null :
                    { this.state.data.title }+
                    From 122409279040da01f8851ad381dfc745a1828f5d Mon Sep 17 00:00:00 2001 From: Rishi Kumar Chawda Date: Wed, 14 Nov 2018 00:54:55 +0530 Subject: [PATCH 038/133] feat(snippets): Add carousel component --- snippets/Carousel.md | 90 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 snippets/Carousel.md diff --git a/snippets/Carousel.md b/snippets/Carousel.md new file mode 100644 index 000000000..472a60d7d --- /dev/null +++ b/snippets/Carousel.md @@ -0,0 +1,90 @@ +### Carousel + +Renders a carousel component. + +The `active` property on the component state is set to `0`th index as default. + +Use an object, `style`, to hold the styles for the individual components. + +Create a method, `setActiveItem`, which uses `this.setState` to change the state's `active` property to the index of the next item. +Create another method `changeItem`, which is called by `setActiveItem` after updating the state each time and also when the component +first renders (on `ComponentDidMount`). + +In the `render()` method, destructure `state`, `style` and `props`, compute if visibility style should be set to `visible` or not for each carousel +item while mapping over and apply the combined style to the carousel item component accordingly. + +Render the carousel items using [React.cloneElement](https://reactjs.org/docs/react-api.html#cloneelement) and pass down rest +props along with the computed styles. + +```jsx + +class Carousel extends React.Component { + constructor(props) { + super(props); + this.state = { + active: 0 + }; + this.scrollInterval = null; + this.style = { + carousel: { + position: "relative" + }, + carouselItem: { + position: "absolute", + visibility: "hidden" + }, + visible: { + visibility: "visible" + } + }; + } + + componentDidMount() { + this.changeItem(); + } + + setActiveItem = () => { + const { carouselItems } = this.props; + this.setState(prevState => ({ + active: (prevState.active + 1) % carouselItems.length + }), + this.changeItem + ); + }; + + changeItem = () => { + this.scrollInterval = setTimeout( + this.setActiveItem, 2000); + }; + + render() { + const { carouselItems, ...rest } = this.props; + const { active } = this.state; + const { visible, carousel, carouselItem } = this.style; + return ( +
                    + {carouselItems.map((item, index) => { + const activeStyle = active === index ? visible : {}; + return React.cloneElement(item, { + ...rest, + style: { + ...carouselItem, + ...activeStyle + } + }); + })} +
                    + ); + } +} + +``` + +```jsx + + ReactDOM.render(carousel item 1
                    , +
                    carousel item 2
                    , +
                    carousel item 3
                    ]} />, document.getElementById('root')); + + ``` From 316f7894279857a2d6fce45e99f6f1736863d5f6 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 29 Nov 2018 09:45:08 +0200 Subject: [PATCH 039/133] Update PasswordRevealer.md --- snippets/PasswordRevealer.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snippets/PasswordRevealer.md b/snippets/PasswordRevealer.md index 79d2b321f..848569c5c 100644 --- a/snippets/PasswordRevealer.md +++ b/snippets/PasswordRevealer.md @@ -39,7 +39,7 @@ class PasswordRevealer extends React.Component { ReactDOM.render(, document.getElementById('root')); ``` -< !--tags: input,state,class -- > + -< !--expertise: 0 -- > + From 84e7fe136fa763998a693266ec094db3b61c7852 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 29 Nov 2018 09:48:35 +0200 Subject: [PATCH 040/133] Update PasswordRevealer.md --- snippets/PasswordRevealer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/PasswordRevealer.md b/snippets/PasswordRevealer.md index 848569c5c..731f1030b 100644 --- a/snippets/PasswordRevealer.md +++ b/snippets/PasswordRevealer.md @@ -4,7 +4,7 @@ Renders a password input field with a reveal button. Initially set `state.shown` to `false` to ensure that the password is not shown by default. Create a method, `toggleShown`, which uses `Component.prototype.setState` to change the input's state from shown to hidden and vice versa, bind it to the component's context. -In the`render()` method, use a`
                    ` to wrap both the`` and the `
  • h
    v.id v.name
    v.id v.name
    ` element with two columns (`ID` and `Value`). +Use `Array.prototype.map` to render every item in `data` as a `` element, consisting of its index and value, give it a `key` produced from the concatenation of the two. + +```jsx +function DataTable({ data }) { + return ( +
    + + + + + + + + {data.map((val, i) => + + + + + )} + +
    IDValue
    {i}{val}
    + ); +} +``` + +```jsx +const people = ['John', 'Jesse']; +ReactDOM.render( + , + document.getElementById('root') +); +``` + + + + diff --git a/snippets/mapped-table.md b/snippets/mapped-table.md deleted file mode 100644 index eb8df3601..000000000 --- a/snippets/mapped-table.md +++ /dev/null @@ -1,46 +0,0 @@ -### MappedTable - -Renders a table with rows dynamically created from an array of data. - -Use the value of the `headers` prop to conditionally render a table with a header. Use `Array.prototype.map` to render every item in `data` as a `` element and give it a `key`. `data` can either be an array of objects with the `id` and `name` properties or an array of primitives. Omit the `headers` prop to render a `table` without headers. - -```jsx -function MappedTable({ headers, data }) { - return ( - - - {headers && ( - - {headers.map((h, i) => ( - - ))} - - )} - - - {data.map((v, i) => - ( - - - - - ); - )} - -
    h
    v.idv.name
    - ); -} -``` - -```jsx -const people = [{ id: 841, name: 'John' }, { id: 241, name: 'Jesse' }]; -const headers = ['id', 'name']; -ReactDOM.render( - , - document.getElementById('root') -); -``` - - - - From a3ac0855af4186a89a9ec530cf85358014bc561e Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 29 Nov 2018 11:42:43 +0200 Subject: [PATCH 047/133] Update DataTable.md --- snippets/DataTable.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/DataTable.md b/snippets/DataTable.md index 73f85cae6..93dfce73e 100644 --- a/snippets/DataTable.md +++ b/snippets/DataTable.md @@ -1,6 +1,6 @@ ### DataTable -Renders a table with rows dynamically created from an array of data. +Renders a table with rows dynamically created from an array of primitives. Render a `` element with two columns (`ID` and `Value`). Use `Array.prototype.map` to render every item in `data` as a `` element, consisting of its index and value, give it a `key` produced from the concatenation of the two. From 699673c938e23151a381abcf4de8abafad550fea Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 29 Nov 2018 11:50:10 +0200 Subject: [PATCH 048/133] Add MappedTable --- snippets/MappedTable.md | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 snippets/MappedTable.md diff --git a/snippets/MappedTable.md b/snippets/MappedTable.md new file mode 100644 index 000000000..67c5d0377 --- /dev/null +++ b/snippets/MappedTable.md @@ -0,0 +1,48 @@ +### MappedTable + +Renders a table with rows dynamically created from an array of objects and a list of property names. + +Use `Object.keys()`, `Array.prototype.filter()`, `Array.prototype.includes()` and `Array.prototype.reduce()` to produce a `filteredData` array, containing all objects with the keys specified in `propertyNames`. +Render a `
    ` element with a set of columns equal to the amount of values in `propertyNames`. +Use `Array.prototype.map` to render each value in the `propertyNames` array as a `` element, containing a `
    ` element. +Use `Array.prototype.map` to render each object in the `filteredData` array as a `
    ` for each key in the object. + +```jsx +function MappedTable({ data, propertyNames }) { + let filteredData = data.map(v => + Object.keys(v) + .filter(k => propertyNames.includes(k)) + .reduce((acc, key) => ((acc[key] = v[key]), acc), {}) + ); + return ( + + + {propertyNames.map(val => )} + + + {filteredData.map((val, i) => ( + + {propertyNames.map(p => )} + + ))} + +
    {val}
    {val[p]}
    + ); +} +``` + +```jsx +const people = [ + { name: 'John', surname: 'Smith', age: 42 }, + { name: 'Adam', surname: 'Smith', gender: 'male' } +]; +const propertyNames = ['name', 'surname', 'age']; +ReactDOM.render( + , + document.getElementById('root') +); +``` + + + + From 9fd7daddcc9d4993f13f6fd5dcd59443efee53c5 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 29 Nov 2018 11:55:30 +0200 Subject: [PATCH 049/133] Add a note about nested objects. --- snippets/MappedTable.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/snippets/MappedTable.md b/snippets/MappedTable.md index 67c5d0377..aada05e50 100644 --- a/snippets/MappedTable.md +++ b/snippets/MappedTable.md @@ -43,6 +43,9 @@ ReactDOM.render( ); ``` +#### Notes: +* This component does not work with nested objects and will break if there are nested objects inside any of the properties specified in `propertyNames`. + From 20af4e8a1cbf5825d1e38b0b0cd4cb43e7e00a6d Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 29 Nov 2018 12:02:48 +0200 Subject: [PATCH 050/133] Update formatting --- snippets/LimitedTextarea.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/snippets/LimitedTextarea.md b/snippets/LimitedTextarea.md index 74859fa66..2092ba7f8 100644 --- a/snippets/LimitedTextarea.md +++ b/snippets/LimitedTextarea.md @@ -26,7 +26,12 @@ class LimitedTextarea extends React.Component { render() { return (
    -

    {this.state.characterCount}/{this.props.limit}

    From 57ec6d4b6886eac4ace74a63206a24b9e0c2f1cc Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 29 Nov 2018 12:12:24 +0200 Subject: [PATCH 051/133] Simplify MappedList and rename to DataList --- snippets/DataList.md | 26 ++++++++++++++++++++++++++ snippets/MappedList.md | 31 ------------------------------- 2 files changed, 26 insertions(+), 31 deletions(-) create mode 100644 snippets/DataList.md delete mode 100644 snippets/MappedList.md diff --git a/snippets/DataList.md b/snippets/DataList.md new file mode 100644 index 000000000..99ee8980b --- /dev/null +++ b/snippets/DataList.md @@ -0,0 +1,26 @@ +### DataList + +Renders a list of elements from an array of primitives. + +Use the value of the `isOrdered` prop to conditionally render a `
      ` or `
        ` list. +Use `Array.prototype.map` to render every item in `data` as a `
      • ` element, give it a `key` produced from the concatenation of the its index and value. +Omit the `isOrdered` prop to render a `
          ` list by default. + +```jsx +function DataList({ isOrdered, data }) { + const list = data.map((val, i) => ( +
        • {val}
        • + )); + return isOrdered ?
            {list}
          :
            {list}
          ; +} +``` + +```jsx +const names = ['John', 'Paul', 'Mary']; +ReactDOM.render(, document.getElementById('root')); +ReactDOM.render(, document.getElementById('root')); +``` + + + + diff --git a/snippets/MappedList.md b/snippets/MappedList.md deleted file mode 100644 index 2d79ced35..000000000 --- a/snippets/MappedList.md +++ /dev/null @@ -1,31 +0,0 @@ -### MappedList - -Renders a list of elements from an array of data. - -Use the value of the `isOrdered` prop to conditionally render a `
            ` or `
              ` list. -Use `Array.prototype.map` to render every item in `data` as a `
            • ` element and give it a `key`. -`data` can either be an array of objects with the `id` and `value` properties or an array of primitives. -Omit the `isOrdered` prop to render a `
                ` list by default. - -```jsx -function MappedList({ isOrdered, data }) { - const list = data.map((v, i) => ( -
              • {v.value ? v.value : v}
              • - )); - return isOrdered ?
                  {list}
                :
                  {list}
                ; -} -``` - -```jsx -const names = ['John', 'Paul', 'Mary']; -ReactDOM.render(, document.getElementById('root')); -const users = [ { id: 8, value: 'john' }, { id: 3, value: 'paul' }]; -ReactDOM.render( - , - document.getElementById('root') -); -``` - - - - From 7538a593eafdcc21421f69e1ba888af335ed26b4 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Mon, 3 Dec 2018 20:35:24 +0200 Subject: [PATCH 052/133] Update Toggle.md --- snippets/Toggle.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/snippets/Toggle.md b/snippets/Toggle.md index f70a12fff..92e86ab16 100644 --- a/snippets/Toggle.md +++ b/snippets/Toggle.md @@ -2,11 +2,10 @@ Renders a toggle component. -The `state` of the component default to `false` and bind the `handleClick` method to the component's context. +Initialize `state.isToggleOn` to `false`, bind the `handleClick` method to the component's context. Use an object, `style`, to hold the styles for individual components and their states. -Create a method, `handleClick`, which uses `Component.prototype.setState` to change the component's `state` from toggleOn to toggleOff and vice versa. -In the `render()` method, destruct `state` and `style` to abbreviate typing, use a ` + + + ); + } + +} +``` + +```jsx +ReactDOM.render(, document.getElementById('root')); +``` \ No newline at end of file From 889ac4ff15b68988cc6993868fe16367cd3ad723 Mon Sep 17 00:00:00 2001 From: Arjun Mahishi Date: Thu, 27 Dec 2018 15:47:53 +0530 Subject: [PATCH 067/133] Fixed issue with multiple ticks --- snippets/Timer.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/snippets/Timer.md b/snippets/Timer.md index e82d8b241..79d7d7ec4 100644 --- a/snippets/Timer.md +++ b/snippets/Timer.md @@ -5,7 +5,7 @@ Renders a timer component. The timer state is initially set to zero. When the `Tick!` button is clicked, `timer` is incremented periodically at the given `interval`. The `setInterval` is cleared once the desired `time` is reached. `time` and `interval` are the required props. ```jsx -class Timer extends Component { +class App extends Component { constructor(props) { super(props); this.state = {timer: 0} @@ -13,6 +13,7 @@ class Timer extends Component { } tick = () => { + this.reset() this.interval = setInterval(() => { if (this.state.timer < this.props.time) { this.setState({timer: this.state.timer + 1}) @@ -22,19 +23,20 @@ class Timer extends Component { }, this.props.interval) } + reset = () => { + this.setState({timer: 0}) + clearInterval(this.interval) + } + render() { return (
                {this.state.timer} - +
                ); } - } ``` From 49285ae1b8076b49ba25554f6de94affa4424cfc Mon Sep 17 00:00:00 2001 From: Arjun Mahishi Date: Thu, 27 Dec 2018 15:51:40 +0530 Subject: [PATCH 068/133] Improved notes --- snippets/Timer.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/snippets/Timer.md b/snippets/Timer.md index 79d7d7ec4..df26454e0 100644 --- a/snippets/Timer.md +++ b/snippets/Timer.md @@ -2,7 +2,11 @@ Renders a timer component. -The timer state is initially set to zero. When the `Tick!` button is clicked, `timer` is incremented periodically at the given `interval`. The `setInterval` is cleared once the desired `time` is reached. `time` and `interval` are the required props. +- The timer state is initially set to zero +- When the `Tick!` button is clicked, `timer` is incremented periodically at the given `interval` +- When the `Reset` button is clicked, the value of the timer is set to zero and the `setInterval` is cleared +- The `setInterval` is cleared once the desired `time` is reached +- `time` and `interval` are the required props ```jsx class App extends Component { From 95d01fee1550a37352e3b18184b9698ed5408b55 Mon Sep 17 00:00:00 2001 From: Arjun Mahishi Date: Fri, 28 Dec 2018 11:08:09 +0530 Subject: [PATCH 069/133] Fixed the name of the component --- snippets/Timer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/Timer.md b/snippets/Timer.md index df26454e0..990ce0a54 100644 --- a/snippets/Timer.md +++ b/snippets/Timer.md @@ -9,7 +9,7 @@ Renders a timer component. - `time` and `interval` are the required props ```jsx -class App extends Component { +class Timer extends Component { constructor(props) { super(props); this.state = {timer: 0} From 18a92d1c24c80c8dc1e44e033354aced6bd7f84a Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Sun, 30 Dec 2018 18:12:39 +0530 Subject: [PATCH 070/133] Update snippets/Timer.md Co-Authored-By: arjunmahishi --- snippets/Timer.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snippets/Timer.md b/snippets/Timer.md index 990ce0a54..5e25334ef 100644 --- a/snippets/Timer.md +++ b/snippets/Timer.md @@ -20,7 +20,7 @@ class Timer extends Component { this.reset() this.interval = setInterval(() => { if (this.state.timer < this.props.time) { - this.setState({timer: this.state.timer + 1}) + this.setState(({ timer }) => ({timer: timer + 1})) }else{ clearInterval(this.interval) } @@ -46,4 +46,4 @@ class Timer extends Component { ```jsx ReactDOM.render(, document.getElementById('root')); -``` \ No newline at end of file +``` From fa4fd782919a806063b65b6711f17d8c1859ce1f Mon Sep 17 00:00:00 2001 From: Arjun Mahishi Date: Mon, 31 Dec 2018 11:05:12 +0530 Subject: [PATCH 071/133] Changed the name of the component to "Ticker" --- snippets/{Timer.md => Ticker.md} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename snippets/{Timer.md => Ticker.md} (82%) diff --git a/snippets/Timer.md b/snippets/Ticker.md similarity index 82% rename from snippets/Timer.md rename to snippets/Ticker.md index 5e25334ef..0bc1f89eb 100644 --- a/snippets/Timer.md +++ b/snippets/Ticker.md @@ -1,15 +1,15 @@ -### Timer +### Ticker -Renders a timer component. +Renders a ticker component. -- The timer state is initially set to zero +- The ticker state is initially set to zero - When the `Tick!` button is clicked, `timer` is incremented periodically at the given `interval` - When the `Reset` button is clicked, the value of the timer is set to zero and the `setInterval` is cleared - The `setInterval` is cleared once the desired `time` is reached - `time` and `interval` are the required props ```jsx -class Timer extends Component { +class Ticker extends Component { constructor(props) { super(props); this.state = {timer: 0} @@ -45,5 +45,5 @@ class Timer extends Component { ``` ```jsx -ReactDOM.render(, document.getElementById('root')); +ReactDOM.render(, document.getElementById('root')); ``` From a010c93050a3822c646c0e11ef7bc70c66d67852 Mon Sep 17 00:00:00 2001 From: Arjun Mahishi Date: Mon, 31 Dec 2018 11:10:21 +0530 Subject: [PATCH 072/133] Refactored some names --- snippets/Ticker.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/snippets/Ticker.md b/snippets/Ticker.md index 0bc1f89eb..d6e669559 100644 --- a/snippets/Ticker.md +++ b/snippets/Ticker.md @@ -12,15 +12,15 @@ Renders a ticker component. class Ticker extends Component { constructor(props) { super(props); - this.state = {timer: 0} + this.state = {ticker: 0} this.interval = null } tick = () => { this.reset() this.interval = setInterval(() => { - if (this.state.timer < this.props.time) { - this.setState(({ timer }) => ({timer: timer + 1})) + if (this.state.ticker < this.props.times) { + this.setState(({ ticker }) => ({ticker: ticker + 1})) }else{ clearInterval(this.interval) } @@ -28,14 +28,14 @@ class Ticker extends Component { } reset = () => { - this.setState({timer: 0}) + this.setState({ticker: 0}) clearInterval(this.interval) } render() { return (
                - {this.state.timer} + {this.state.ticker}
                @@ -45,5 +45,5 @@ class Ticker extends Component { ``` ```jsx -ReactDOM.render(, document.getElementById('root')); +ReactDOM.render(, document.getElementById('root')); ``` From e4b0e4dd33437569d469a8c73c2aa329862b0207 Mon Sep 17 00:00:00 2001 From: rishichawda Date: Sun, 27 Jan 2019 12:55:57 +0530 Subject: [PATCH 073/133] feat(snippets): add multiselect-checkbox list to snippets --- snippets/MultiselectCheckbox.md | 85 +++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 snippets/MultiselectCheckbox.md diff --git a/snippets/MultiselectCheckbox.md b/snippets/MultiselectCheckbox.md new file mode 100644 index 000000000..3222a1ed2 --- /dev/null +++ b/snippets/MultiselectCheckbox.md @@ -0,0 +1,85 @@ +### Multiple Checkbox + +## + +Renders a checkbox list with the options provided through `props`. + +Initially, all the items in the `options` array only have label ( and / or other data provided by the user ) and `checked` is `undefined` if not provided. On clicking any of the items, the `checked` value for the item is toggled and state is updated with the new list. + +The checkbox input in this case is kept as `readOnly` since click events are handled for the item ( label + input ) and not the `input` alone. An `onChange` prop can be passed to the `MultiCheckbox` component to get the updated list on every change event within the list. + + +```jsx +export default class MultiCheckbox extends React.Component { + constructor(props) { + super(props); + this.style = { + listContainer: { + listStyle: 'none', + paddingLeft: 0, + }, + itemStyle: { + cursor: 'pointer', + padding: 5, + } + } + this.state = { + options: props.options, + } + } + + toggle = (item) => { + const { options } = this.state; + const { onChange } = this.props; + options.map((_, key) => { + if(options[key].label === item.label) { + options[key].checked = !item.checked; + } + }); + this.setState({ + options, + }, () => { + onChange(options); + }); + } + + render() { + const { options } = this.state; + return ( +
                  + { + options.map(item => ( +
                • this.toggle(item)} + > + + {item.label} +
                • + )) + } +
                + ) + } +} +``` +```jsx + +const options = [ + { label: 'Item One' }, + { label: 'Item Two' } +]; + +ReactDOM.render( + { + console.log(data); + }} + />, + document.getElementById('root')); +``` \ No newline at end of file From 95b573a39ba08cf8c1fdefa29ecc21692f15b214 Mon Sep 17 00:00:00 2001 From: chenmeng Date: Sun, 27 Jan 2019 17:59:52 +0800 Subject: [PATCH 074/133] + add snippet Tabs --- snippets/Tabs.md | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 snippets/Tabs.md diff --git a/snippets/Tabs.md b/snippets/Tabs.md new file mode 100644 index 000000000..e981fc823 --- /dev/null +++ b/snippets/Tabs.md @@ -0,0 +1,69 @@ +### Tab +Render a menu and a view, change the content in the view by clicking the button in the menu and the callback will execute before render + +Define the `TabItem` as a middleware, pass it to the `Tab` and remove the useless nodes expect `TabItem` by identify the function's name in `props.children`, after that we will use the collected nodes to render the `tab-menu` and `tab-view` with map. Buttons in the `tab-menu` will execute `changeTab` +when been clicked, `changeTab` will execute the callback funciton(`onTabClick`) and change `bindIndex` to emit `render`,every node in `tab-view` use `bindIndex` and the `index` which ws passing from `TabItem` to judege whether it show of not(`itemStyle`) + + +```jsx +class Tab extends React.Component{ + constructor(props){ + super(props) + this.changeTab(props.defaultIndex) + this.state = { + bindIndex:'' + } + } + + changeTab(newIndex){ + if(typeof this.props.onTabClick === 'function'){ + this.props.onTabClick(newIndex) + } + this.setState({ + bindIndex: newIndex + }) + } + + itemStyle(index){ + return { + display:this.state.bindIndex === index?'block':'none' + } + } + + render(){ + const items = this.props.children + .filter(item=>item.type.name==='TabItem') + return ( +
                +
                + {items.map(({props:{index, label}})=>)} +
                +
                + {items.map(({props})=>( +
                ))} +
                +
                + ) + } +} + +function TabItem(props){ + return
                +} +``` +```jsx +ReactDOM.render( + + item1 + item2 + , + document.getElementById('root') +); +``` + + + + \ No newline at end of file From 1bbd643e160b39d53431ee1523dd12e5336048cd Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Mon, 28 Jan 2019 19:40:05 +0200 Subject: [PATCH 075/133] Update Tabs.md --- snippets/Tabs.md | 112 ++++++++++++++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 41 deletions(-) diff --git a/snippets/Tabs.md b/snippets/Tabs.md index e981fc823..8582e9974 100644 --- a/snippets/Tabs.md +++ b/snippets/Tabs.md @@ -1,69 +1,99 @@ ### Tab -Render a menu and a view, change the content in the view by clicking the button in the menu and the callback will execute before render +Renders a tabbed menu and view component. -Define the `TabItem` as a middleware, pass it to the `Tab` and remove the useless nodes expect `TabItem` by identify the function's name in `props.children`, after that we will use the collected nodes to render the `tab-menu` and `tab-view` with map. Buttons in the `tab-menu` will execute `changeTab` -when been clicked, `changeTab` will execute the callback funciton(`onTabClick`) and change `bindIndex` to emit `render`,every node in `tab-view` use `bindIndex` and the `index` which ws passing from `TabItem` to judege whether it show of not(`itemStyle`) +Define `TabItem` as a middleware, pass it to the `Tab` and remove unnecessary nodes expect for `TabItem` by identifying the function's name in `props.children`. +Use `Array.prototype.map` on the collected nodes to render the `tab-menu` and `tab-view`. +Define `changeTab`, which will be executed when clicking a `)} +
                +
                + {items.map(({ props: { index, label } }) => ( + + ))}
                -
                - {items.map(({props})=>( -
                ))} +
                + {items.map(({ props }) => ( +
                + ))}
                - ) + ); } } - -function TabItem(props){ - return
                +function TabItem(props) { + return
                ; } ``` ```jsx ReactDOM.render( - - item1 - item2 + + + Lorem ipsum + + + Dolor sit amet + , - document.getElementById('root') + document.getElementById("root") ); + ``` - \ No newline at end of file + From 07ff51629fba25d762cd08aa31594f9b682db922 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Mon, 28 Jan 2019 19:50:38 +0200 Subject: [PATCH 076/133] Update Carousel.md --- snippets/Carousel.md | 67 ++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/snippets/Carousel.md b/snippets/Carousel.md index 472a60d7d..7a7a344eb 100644 --- a/snippets/Carousel.md +++ b/snippets/Carousel.md @@ -2,24 +2,18 @@ Renders a carousel component. -The `active` property on the component state is set to `0`th index as default. - +Initially set `state.active` to `0` (index of the first item). Use an object, `style`, to hold the styles for the individual components. - -Create a method, `setActiveItem`, which uses `this.setState` to change the state's `active` property to the index of the next item. -Create another method `changeItem`, which is called by `setActiveItem` after updating the state each time and also when the component +Define a method, `setActiveItem`, which uses `this.setState` to change the state's `active` property to the index of the next item. +Define another method, `changeItem`, which is called by `setActiveItem` after updating the state each time and also when the component first renders (on `ComponentDidMount`). - -In the `render()` method, destructure `state`, `style` and `props`, compute if visibility style should be set to `visible` or not for each carousel -item while mapping over and apply the combined style to the carousel item component accordingly. - +In the `render()` method, destructure `state`, `style` and `props`, compute if visibility style should be set to `visible` or not for each carousel item while mapping over and applying the combined style to the carousel item component accordingly. Render the carousel items using [React.cloneElement](https://reactjs.org/docs/react-api.html#cloneelement) and pass down rest -props along with the computed styles. +`props` along with the computed styles. ```jsx - class Carousel extends React.Component { - constructor(props) { + constructor(props) { super(props); this.state = { active: 0 @@ -38,25 +32,21 @@ class Carousel extends React.Component { } }; } - - componentDidMount() { + componentDidMount() { this.changeItem(); - } - - setActiveItem = () => { - const { carouselItems } = this.props; - this.setState(prevState => ({ - active: (prevState.active + 1) % carouselItems.length - }), - this.changeItem - ); - }; - - changeItem = () => { - this.scrollInterval = setTimeout( - this.setActiveItem, 2000); - }; - + } + setActiveItem = () => { + const { carouselItems } = this.props; + this.setState( + prevState => ({ + active: (prevState.active + 1) % carouselItems.length + }), + this.changeItem + ); + }; + changeItem = () => { + this.scrollInterval = setTimeout(this.setActiveItem, 2000); + }; render() { const { carouselItems, ...rest } = this.props; const { active } = this.state; @@ -77,14 +67,17 @@ class Carousel extends React.Component { ); } } - ``` ```jsx - - ReactDOM.render(carousel item 1
                , -
                carousel item 2
                , -
                carousel item 3
                ]} />, document.getElementById('root')); - +ReactDOM.render( + carousel item 1
                , +
                carousel item 2
                , +
                carousel item 3
                + ]} + />, + document.getElementById("app") +); ``` From d2e90d5d6b94e241b89d889b8e0b03e2e4ba0123 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Mon, 28 Jan 2019 20:07:48 +0200 Subject: [PATCH 077/133] Update Carousel.md --- snippets/Carousel.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/snippets/Carousel.md b/snippets/Carousel.md index 7a7a344eb..ba6c43ee9 100644 --- a/snippets/Carousel.md +++ b/snippets/Carousel.md @@ -81,3 +81,8 @@ ReactDOM.render( document.getElementById("app") ); ``` + + + + + From e9f1b261960972fc7242fc0de712f9712347fb9d Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Mon, 28 Jan 2019 20:08:51 +0200 Subject: [PATCH 078/133] Update Carousel.md --- snippets/Carousel.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/Carousel.md b/snippets/Carousel.md index ba6c43ee9..6c1d7e467 100644 --- a/snippets/Carousel.md +++ b/snippets/Carousel.md @@ -78,7 +78,7 @@ ReactDOM.render(
                carousel item 3
                ]} />, - document.getElementById("app") + document.getElementById("root") ); ``` From b9382db30bd1725298eb11dc4c7ba6ad9906349d Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Mon, 28 Jan 2019 20:10:51 +0200 Subject: [PATCH 079/133] Create Mailto.md --- snippets/Mailto.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 snippets/Mailto.md diff --git a/snippets/Mailto.md b/snippets/Mailto.md new file mode 100644 index 000000000..24b5740dc --- /dev/null +++ b/snippets/Mailto.md @@ -0,0 +1,29 @@ +### Mailto + +Renders a link formatted to send an email. + +Destructure the component's props, use `email`, `subject` and `body` to create a `` element with an appropriate `href` attribute. +Render the link with `props.children` as its content. + +```jsx +function Mailto({ email, subject, body, ...props }) { + return ( + + {props.children} + + ); +} +``` + +```jsx +ReactDOM.render( + + Mail me! + , + document.getElementById("root") +); +``` + + + + From ee917a5bfb395caae0f7833748c36df718ce9945 Mon Sep 17 00:00:00 2001 From: rishichawda Date: Tue, 29 Jan 2019 09:57:47 +0530 Subject: [PATCH 080/133] style(snippets/MultiselectCheckbox.md): lint with prettier --- snippets/MultiselectCheckbox.md | 77 +++++++++++++++------------------ 1 file changed, 34 insertions(+), 43 deletions(-) diff --git a/snippets/MultiselectCheckbox.md b/snippets/MultiselectCheckbox.md index 3222a1ed2..86827fb86 100644 --- a/snippets/MultiselectCheckbox.md +++ b/snippets/MultiselectCheckbox.md @@ -4,82 +4,73 @@ Renders a checkbox list with the options provided through `props`. -Initially, all the items in the `options` array only have label ( and / or other data provided by the user ) and `checked` is `undefined` if not provided. On clicking any of the items, the `checked` value for the item is toggled and state is updated with the new list. +Initially, all the items in the `options` array only have label ( and / or other data provided by the user ) and `checked` is `undefined` if not provided. On clicking any of the items, the `checked` value for the item is toggled and state is updated with the new list. The checkbox input in this case is kept as `readOnly` since click events are handled for the item ( label + input ) and not the `input` alone. An `onChange` prop can be passed to the `MultiCheckbox` component to get the updated list on every change event within the list. - ```jsx export default class MultiCheckbox extends React.Component { constructor(props) { super(props); this.style = { listContainer: { - listStyle: 'none', - paddingLeft: 0, + listStyle: "none", + paddingLeft: 0 }, itemStyle: { - cursor: 'pointer', - padding: 5, + cursor: "pointer", + padding: 5 } - } + }; this.state = { - options: props.options, - } + options: props.options + }; } - toggle = (item) => { + toggle = item => { const { options } = this.state; const { onChange } = this.props; options.map((_, key) => { - if(options[key].label === item.label) { + if (options[key].label === item.label) { options[key].checked = !item.checked; } }); - this.setState({ - options, - }, () => { - onChange(options); - }); - } - + this.setState( + { + options + }, + () => { + onChange(options); + } + ); + }; + render() { const { options } = this.state; return (
                  - { - options.map(item => ( -
                • this.toggle(item)} - > - - {item.label} -
                • - )) - } + {options.map(item => ( +
                • this.toggle(item)}> + + {item.label} +
                • + ))}
                - ) + ); } } ``` -```jsx -const options = [ - { label: 'Item One' }, - { label: 'Item Two' } -]; +```jsx +const options = [{ label: "Item One" }, { label: "Item Two" }]; ReactDOM.render( { - console.log(data); + onChange={data => { + console.log(data); }} />, - document.getElementById('root')); -``` \ No newline at end of file + document.getElementById("root") +); +``` From a2228b8189921d8b9bf14aff22db2b715cacd268 Mon Sep 17 00:00:00 2001 From: le-mahf <46358903+le-mahf@users.noreply.github.com> Date: Thu, 31 Jan 2019 07:11:32 +0000 Subject: [PATCH 081/133] update button text to reflect state --- snippets/Collapse.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/Collapse.md b/snippets/Collapse.md index fd1202ae4..ffe696303 100644 --- a/snippets/Collapse.md +++ b/snippets/Collapse.md @@ -40,7 +40,7 @@ class Collapse extends React.Component { return (
                Date: Sat, 2 Feb 2019 10:40:16 +0200 Subject: [PATCH 082/133] Update Collapse.md --- snippets/Collapse.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/Collapse.md b/snippets/Collapse.md index ffe696303..4da570282 100644 --- a/snippets/Collapse.md +++ b/snippets/Collapse.md @@ -40,7 +40,7 @@ class Collapse extends React.Component { return (
                Date: Sat, 2 Feb 2019 12:17:27 +0200 Subject: [PATCH 083/133] Create FileDrop.md --- snippets/FileDrop.md | 117 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 snippets/FileDrop.md diff --git a/snippets/FileDrop.md b/snippets/FileDrop.md new file mode 100644 index 000000000..c64075fee --- /dev/null +++ b/snippets/FileDrop.md @@ -0,0 +1,117 @@ +### FileDrop + +Renders a file drag and drop component for a single file. + +Create a ref called `dropRef` for this component. +Initialize `state.drag` and `state.filename` to `false` and `''` respectively. +The variables `dragCounter` and `state.drag` are used to determine if a file is being dragged, while `state.filename` is used to store the dropped file's name. +Create the `handleDrag`, `handleDragIn`, `handleDragOut` and `handleDrop` methods to handle drag and drop functionality, bind them to the component's context. +Each of the methods will handle a specific event, the listeners for which are created and removed in `componentDidMount` and `componentWillUnmount` respectively. +`handleDrag` prevents the browser from opening the dragged file, `handleDragIn` and `handleDragOut` handle the dragged file entering and exiting the component, while `handleDrop` handles the file being dropped and passes it to `this.props.handleDrop`. +In the `render()` method, create an appropriately styled `
                ` and use `state.drag` and `state.filename` to determine its contents and style. +Finally, bind the `ref` of the created `
                ` to `dropRef`. + + +```css +.filedrop { + min-height: 120px; + border: 3px solid #D3D3D3; + text-align: center; + font-size: 24px; + padding: 32px; + border-radius: 4px; +} + +.filedrop.drag { + border: 3px dashed #1E90FF; +} + +.filedrop.ready { + border: 3px solid #32CD32; +} +``` + +```jsx +class FileDrop extends React.Component { + constructor(props) { + super(props); + this.dropRef = React.createRef(); + this.state = { + drag: false, + filename: '' + } + this.handleDrag = this.handleDrag.bind(this); + this.handleDragIn = this.handleDragIn.bind(this); + this.handleDragOut = this.handleDragOut.bind(this); + this.handleDrop = this.handleDrop.bind(this); + } + + handleDrag(e) { + e.preventDefault(); + e.stopPropagation(); + } + + handleDragIn(e) { + e.preventDefault(); + e.stopPropagation(); + this.dragCounter++; + if (e.dataTransfer.items && e.dataTransfer.items.length > 0) + this.setState({ drag: true }); + } + + handleDragOut(e) { + e.preventDefault(); + e.stopPropagation(); + this.dragCounter--; + if (this.dragCounter === 0) + this.setState({ drag: false }); + } + + handleDrop(e) { + e.preventDefault(); + e.stopPropagation(); + this.setState({ drag: false }); + if (e.dataTransfer.files && e.dataTransfer.files.length > 0) { + this.props.handleDrop(e.dataTransfer.files[0]); + this.setState({ filename : e.dataTransfer.files[0].name}); + e.dataTransfer.clearData(); + this.dragCounter = 0; + } + } + + componentDidMount() { + let div = this.dropRef.current; + div.addEventListener('dragenter', this.handleDragIn); + div.addEventListener('dragleave', this.handleDragOut); + div.addEventListener('dragover', this.handleDrag); + div.addEventListener('drop', this.handleDrop); + } + + componentWillUnmount() { + let div = this.dropRef.current; + div.removeEventListener('dragenter', this.handleDragIn); + div.removeEventListener('dragleave', this.handleDragOut); + div.removeEventListener('dragover', this.handleDrag); + div.removeEventListener('drop', this.handleDrop); + } + + render() { + return ( +
                + {this.state.filename && !this.state.drag ? +
                {this.state.filename}
                + :
                Drop files here!
                + } +
                + ) + } +} +``` + +```jsx +ReactDOM.render(, document.getElementById('root')); +``` + + + + From 9f3ff79952878a1ecf85d38435fcab96efcda7c0 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Sat, 2 Feb 2019 13:19:06 +0200 Subject: [PATCH 084/133] Fix some snippets, start creating scripts --- .gitignore | 1 + data/snippet_data.json | 301 +++++++++++++++++++++ package-lock.json | 521 ++++++++++++++++++++++++++++++++++++ package.json | 29 ++ scripts/extract.js | 59 ++++ scripts/util.js | 95 +++++++ snippets/LimitedTextarea.md | 4 +- snippets/Ticker.md | 4 + 8 files changed, 1012 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 data/snippet_data.json create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 scripts/extract.js create mode 100644 scripts/util.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..b512c09d4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/data/snippet_data.json b/data/snippet_data.json new file mode 100644 index 000000000..446e47d96 --- /dev/null +++ b/data/snippet_data.json @@ -0,0 +1,301 @@ +[ + { + "name": "AutoLink.md", + "title": "AutoLink", + "text": "Renders a string as plaintext, with URLs converted to appropriate `` elements.\n\nUse `String.prototype.split()` and `String.prototype.match()` with a regular expression to find URLs in a string.\nReturn a `` with matched URLs rendered as `` elements, dealing with missing protocol prefixes if necessary, and the rest of the string rendered as plaintext.\n\n", + "codeBlocks": [ + "```jsx\nfunction AutoLink({ text }) {\n const delimiter = /((?:https?:\\/\\/)?(?:(?:[a-z0-9]?(?:[a-z0-9\\-]{1,61}[a-z0-9])?\\.[^\\.|\\s])+[a-z\\.]*[a-z]+|(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3})(?::\\d{1,5})*[a-z0-9.,_\\/~#&=;%+?\\-\\\\(\\\\)]*)/gi;\n\n return (\n \n {text.split(delimiter).map(word => {\n let match = word.match(delimiter);\n if (match) {\n let url = match[0];\n return (\n {url}\n );\n }\n return word;\n })}\n \n );\n}\n```", + "```jsx\nReactDOM.render(\n ,\n document.getElementById('root')\n);\n```" + ], + "expertise": 2, + "tags": [ + "string", + "fragment", + "functional" + ], + "notes": [] + }, + { + "name": "Carousel.md", + "title": "Carousel", + "text": "Renders a carousel component.\n\nInitially set `state.active` to `0` (index of the first item).\nUse an object, `style`, to hold the styles for the individual components.\nDefine a method, `setActiveItem`, which uses `this.setState` to change the state's `active` property to the index of the next item.\nDefine another method, `changeItem`, which is called by `setActiveItem` after updating the state each time and also when the component\nfirst renders (on `ComponentDidMount`).\nIn the `render()` method, destructure `state`, `style` and `props`, compute if visibility style should be set to `visible` or not for each carousel item while mapping over and applying the combined style to the carousel item component accordingly.\nRender the carousel items using [React.cloneElement](https://reactjs.org/docs/react-api.html#cloneelement) and pass down rest\n`props` along with the computed styles.\n\n", + "codeBlocks": [ + "```jsx\nclass Carousel extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n active: 0\n };\n this.scrollInterval = null;\n this.style = {\n carousel: {\n position: \"relative\"\n },\n carouselItem: {\n position: \"absolute\",\n visibility: \"hidden\"\n },\n visible: {\n visibility: \"visible\"\n }\n };\n }\n componentDidMount() {\n this.changeItem();\n }\n setActiveItem = () => {\n const { carouselItems } = this.props;\n this.setState(\n prevState => ({\n active: (prevState.active + 1) % carouselItems.length\n }),\n this.changeItem\n );\n };\n changeItem = () => {\n this.scrollInterval = setTimeout(this.setActiveItem, 2000);\n };\n render() {\n const { carouselItems, ...rest } = this.props;\n const { active } = this.state;\n const { visible, carousel, carouselItem } = this.style;\n return (\n
                \n {carouselItems.map((item, index) => {\n const activeStyle = active === index ? visible : {};\n return React.cloneElement(item, {\n ...rest,\n style: {\n ...carouselItem,\n ...activeStyle\n }\n });\n })}\n
                \n );\n }\n}\n```", + "```jsx\nReactDOM.render(\n carousel item 1
                ,\n
                carousel item 2
                ,\n
                carousel item 3
                \n ]}\n />,\n document.getElementById(\"root\")\n);\n ```" + ], + "expertise": 2, + "tags": [ + "visual", + "children", + "state", + "class" + ], + "notes": [] + }, + { + "name": "Collapse.md", + "title": "Collapse", + "text": "Renders a component with collapsible content.\n\nUse the value of the `collapsed` prop to determine the initial state of the content (collapsed/expanded).\nSet the `state` of the component to the value of the `collapsed` prop (cast to a boolean value) and bind the `toggleCollapse` method to the component's context.\nUse an object, `style`, to hold the styles for individual components and their states.\nCreate a method, `toggleCollapse`, which uses `Component.prototype.setState` to change the component's `state` from collapsed to expanded and vice versa.\nIn the `render()` method, use a `
                ` to wrap both the `\n
                \n {this.props.children}\n
                \n
                \n );\n }\n}\n```", + "```jsx\nReactDOM.render(\n \n

                This is a collapse

                \n

                Hello world!

                \n
                ,\n document.getElementById('root')\n);\n```" + ], + "expertise": 2, + "tags": [ + "visual", + "children", + "state", + "class" + ], + "notes": [] + }, + { + "name": "DataList.md", + "title": "DataList", + "text": "Renders a list of elements from an array of primitives.\n\nUse the value of the `isOrdered` prop to conditionally render a `
                  ` or `
                    ` list.\nUse `Array.prototype.map` to render every item in `data` as a `
                  • ` element, give it a `key` produced from the concatenation of the its index and value.\nOmit the `isOrdered` prop to render a `
                      ` list by default.\n\n", + "codeBlocks": [ + "```jsx\nfunction DataList({ isOrdered, data }) {\n const list = data.map((val, i) => (\n
                    • {val}
                    • \n ));\n return isOrdered ?
                        {list}
                      :
                        {list}
                      ;\n}\n```", + "```jsx\nconst names = ['John', 'Paul', 'Mary'];\nReactDOM.render(, document.getElementById('root'));\nReactDOM.render(, document.getElementById('root'));\n```" + ], + "expertise": 0, + "tags": [ + "array", + "functional" + ], + "notes": [] + }, + { + "name": "DataTable.md", + "title": "DataTable", + "text": "Renders a table with rows dynamically created from an array of primitives.\n\nRender a `` element with two columns (`ID` and `Value`).\nUse `Array.prototype.map` to render every item in `data` as a `` element, consisting of its index and value, give it a `key` produced from the concatenation of the two.\n\n", + "codeBlocks": [ + "```jsx\nfunction DataTable({ data }) {\n return (\n
                      \n \n \n \n \n \n \n \n {data.map((val, i) =>\n \n \n \n \n )}\n \n
                      IDValue
                      {i}{val}
                      \n );\n}\n```", + "```jsx\nconst people = ['John', 'Jesse'];\nReactDOM.render(\n ,\n document.getElementById('root')\n);\n```" + ], + "expertise": 0, + "tags": [ + "array", + "functional" + ], + "notes": [] + }, + { + "name": "Input.md", + "title": "Input", + "text": "Renders an `` element that uses a callback function to pass its value to the parent component.\n\nUse object destructuring to set defaults for certain attributes of the `` element.\nRender an `` element with the appropriate attributes and use the `callback` function in the `onChange` event to pass the value of the input to the parent.\n\n", + "codeBlocks": [ + "```jsx\nfunction Input ({ callback, type = 'text', disabled = false, readOnly = false, placeholder = '' }) {\n return (\n callback(value)}\n />\n );\n}\n```", + "```jsx\nReactDOM.render(\n console.log(val)}/>,\n document.getElementById('root')\n);\n```" + ], + "expertise": 0, + "tags": [ + "input", + "functional" + ], + "notes": [] + }, + { + "name": "LimitedTextarea.md", + "title": "LimitedTextarea", + "text": "Renders a textarea component with a character limit.\n\nUse the value of the `value` prop to determine the initial `state.content` and `state.characterCount` and the value of the `limit` props to determine the value of `state.limit`.\nCreate a method, `handleChange`, which trims the `event.target.value` data if necessary and uses `Component.prototype.setState` to update `state.content` and `state.characterCount`, and bind it to the component's context.\nIn the`render()` method, use a`
                      ` to wrap both the`\n

                      {this.state.characterCount}/{this.props.limit}

                      \n
                      \n );\n }\n}\n```", + "```jsx\nReactDOM.render(\n ,\n document.getElementById('root')\n);\n```" + ], + "expertise": 0, + "tags": [ + "input", + "state", + "class" + ], + "notes": [] + }, + { + "name": "Mailto.md", + "title": "Mailto", + "text": "Renders a link formatted to send an email.\n\nDestructure the component's props, use `email`, `subject` and `body` to create a `` element with an appropriate `href` attribute.\nRender the link with `props.children` as its content.\n\n", + "codeBlocks": [ + "```jsx\nfunction Mailto({ email, subject, body, ...props }) {\n return (\n \n {props.children}\n \n );\n}\n```", + "```jsx\nReactDOM.render(\n \n Mail me!\n ,\n document.getElementById(\"root\")\n);\n```" + ], + "expertise": 0, + "tags": [ + "functional" + ], + "notes": [] + }, + { + "name": "MappedTable.md", + "title": "MappedTable", + "text": "Renders a table with rows dynamically created from an array of objects and a list of property names.\n\nUse `Object.keys()`, `Array.prototype.filter()`, `Array.prototype.includes()` and `Array.prototype.reduce()` to produce a `filteredData` array, containing all objects with the keys specified in `propertyNames`.\nRender a `` element with a set of columns equal to the amount of values in `propertyNames`.\nUse `Array.prototype.map` to render each value in the `propertyNames` array as a `` element, containing a `
                      ` element.\nUse `Array.prototype.map` to render each object in the `filteredData` array as a `
                      ` for each key in the object.\n\n", + "codeBlocks": [ + "```jsx\nfunction MappedTable({ data, propertyNames }) {\n let filteredData = data.map(v =>\n Object.keys(v)\n .filter(k => propertyNames.includes(k))\n .reduce((acc, key) => ((acc[key] = v[key]), acc), {})\n );\n return (\n \n \n {propertyNames.map(val => )}\n \n \n {filteredData.map((val, i) => (\n \n {propertyNames.map(p => )}\n \n ))}\n \n
                      {val}
                      {val[p]}
                      \n );\n}\n```", + "```jsx\nconst people = [\n { name: 'John', surname: 'Smith', age: 42 },\n { name: 'Adam', surname: 'Smith', gender: 'male' }\n];\nconst propertyNames = ['name', 'surname', 'age'];\nReactDOM.render(\n ,\n document.getElementById('root')\n);\n```" + ], + "expertise": 1, + "tags": [ + "array", + "object", + "functional" + ], + "notes": [ + "This component does not work with nested objects and will break if there are nested objects inside any of the properties specified in `propertyNames`.", + "", + "" + ] + }, + { + "name": "ModalDialog.md", + "title": "ModalDialog", + "text": "Renders a dialog component in a modal, controllable through events. \nTo use the component, import `ModalDialog` only once and then display it using `ModalDialog.show()`, passing the JSX templates and data as parameters.\n\nDefine `modalHandler`, a method that will handle showing the modal dialog, set `state` to the default values initially and bind the `close` and `modalClick` methods to the component's context.\nDefine `close` and `modalClick` to toggle the visibility of the modal dialog, based on `state.closeOnClick`.\nUse the CustomEvent API to listen for `modal` events, that can be dispatched from the `static` `show()` method, handle listeners appropriately from `componentDidMount` and `componentWillUnmount`.\n\nThe `show()` method accepts an argument, that should contain three parameters:\n* `title`, a string for the dialog's title\n* `closeOnClick`, `true` if the modal should close on click or `false` if it should only close when clicking the *X* button\n* `content`, which is the JSX content to be rendered inside the dialog\n\nFinally, in the `render()` method, use a `
                      ` to wrap everything and render the modal dialog with the content passed to `show()`.\n\n", + "codeBlocks": [ + "```css\n .modal {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.6);\n z-index: 9998;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n .dialog {\n background-color: white;\n border-radius: 5px;\n overflow: hidden;\n }\n .dialog-title {\n box-sizing: border-box;\n width: 100%;\n height: 48px;\n padding: 0 16px;\n border-bottom: 0.5px solid #c3c3c3;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .dialog-close {\n font-size: 32px;\n color: #c3c3c3;\n cursor: pointer;\n transform: rotate(45deg);\n user-select: none;\n }\n .dialog-close:hover {\n color: red;\n }\n .dialog-content {\n min-width: 300px;\n }\n```", + "```jsx\nclass ModalDialog extends React.Component {\n constructor() {\n super();\n this.modalHandler = (e) => {\n this.setState({\n data: e.detail.data,\n visible: true\n });\n };\n this.state = {\n data: {\n title: '',\n closeOnClick: false,\n content: ''\n },\n visible: false\n };\n this.close = this.close.bind(this);\n this.modalClick = this.modalClick.bind(this);\n }\n render() {\n return !this.state.visible ? null :
                      \n
                      \n
                      { this.state.data.title }+
                      \n
                      \n {\n this.state.data.content\n }\n
                      \n
                      \n
                      \n }\n componentDidMount() {\n document.addEventListener('modal', this.modalHandler);\n }\n componentWillUnmount() {\n document.removeEventListener('modal', this.modalHandler);\n }\n close() {\n this.setState({\n visible: false,\n data: {\n title: '',\n closeOnClick: false,\n content: ''\n }\n });\n }\n static show(data) {\n document.dispatchEvent(new CustomEvent('modal', {\n detail: {\n data\n }\n }));\n }\n modalClick() {\n if (this.state.data.closeOnClick) this.close();\n }\n}\n```", + "```jsx\n// add to render function\n\n\n// every time you wanna call the dialog\n// content is a jsx element\nModalDialog.show({\n title: 'Hello, world!',\n closeOnClick: true,\n content: \n}); \n```" + ], + "expertise": 1, + "tags": [ + "visual", + "static", + "children", + "state", + "class" + ], + "notes": [ + "This component includes a lot of CSS, which might conflict with other CSS in your project. It is recomended for the modal to be a direct child of the body tag.", + "A more up-to-date method with lower compatibility is to use [Portals](https://reactjs.org/docs/portals.html) in React 16+.", + "", + "" + ] + }, + { + "name": "PasswordRevealer.md", + "title": "PasswordRevealer", + "text": "Renders a password input field with a reveal button.\n\nInitially set `state.shown` to `false` to ensure that the password is not shown by default.\nCreate a method, `toggleShown`, which uses `Component.prototype.setState` to change the input's state from shown to hidden and vice versa, bind it to the component's context.\nIn the`render()` method, use a`
                      ` to wrap both the`` and the `\n
                      \n );\n }\n}\n```", + "```jsx\nReactDOM.render(, document.getElementById('root'));\n```" + ], + "expertise": 0, + "tags": [ + "input", + "state", + "class" + ], + "notes": [] + }, + { + "name": "Select.md", + "title": "Select", + "text": "Renders a `` element.\nRender a `` element.\n\n", + "codeBlocks": [ + "```jsx\nfunction Select ({ values, callback, disabled = false, readonly = false, selected }) {\n return (\n callback(value)}\n >\n {values.map(([value, text]) => )}\n \n );\n}\n```", + "```jsx\nlet choices = [\n ['grapefruit', 'Grapefruit'],\n ['lime', 'Lime'],\n ['coconut', 'Coconut'],\n ['mango', 'Mango']\n];\nReactDOM.render(\n +

                      {this.state.characterCount}/{this.props.limit}

                      +
                      + ); + } +} +``` + +
                      +Examples + +```jsx +ReactDOM.render( + , + document.getElementById('root') +); +``` +
                      + +
                      [⬆ Back to top](#table-of-contents) + +### PasswordRevealer + +Renders a password input field with a reveal button. + +Initially set `state.shown` to `false` to ensure that the password is not shown by default. +Create a method, `toggleShown`, which uses `Component.prototype.setState` to change the input's state from shown to hidden and vice versa, bind it to the component's context. +In the`render()` method, use a`
                      ` to wrap both the`` and the ` +
                      + ); + } +} +``` + +
                      +Examples + +```jsx +ReactDOM.render(, document.getElementById('root')); +``` +
                      + +
                      [⬆ Back to top](#table-of-contents) + +### Select + +Renders a `` element. +Render a `` element. + +```jsx +function Select ({ values, callback, disabled = false, readonly = false, selected }) { + return ( + + ); +} +``` + +
                      +Examples + +```jsx +let choices = [ + ['grapefruit', 'Grapefruit'], + ['lime', 'Lime'], + ['coconut', 'Coconut'], + ['mango', 'Mango'] +]; +ReactDOM.render( + -

                      {this.state.characterCount}/{this.props.limit}

                      - - ); - } -} -``` - -
                      -Examples - -```jsx -ReactDOM.render( - , - document.getElementById('root') -); -``` -
                      - -
                      [⬆ Back to top](#table-of-contents) - -### PasswordRevealer - -Renders a password input field with a reveal button. - -Initially set `state.shown` to `false` to ensure that the password is not shown by default. -Create a method, `toggleShown`, which uses `Component.prototype.setState` to change the input's state from shown to hidden and vice versa, bind it to the component's context. -In the`render()` method, use a`
                      ` to wrap both the`` and the ` -
                      - ); - } -} -``` - -
                      -Examples - -```jsx -ReactDOM.render(, document.getElementById('root')); -``` -
                      - -
                      [⬆ Back to top](#table-of-contents) - -### Select - -Renders a `` element. -Render a `` element. - -```jsx -function Select ({ values, callback, disabled = false, readonly = false, selected }) { - return ( - - ); -} -``` - -
                      -Examples - -```jsx -let choices = [ - ['grapefruit', 'Grapefruit'], - ['lime', 'Lime'], - ['coconut', 'Coconut'], - ['mango', 'Mango'] -]; -ReactDOM.render( - \n

                      {this.state.characterCount}/{this.props.limit}

                      \n \n );\n }\n}\n```", - "```jsx\nReactDOM.render(\n ,\n document.getElementById('root')\n);\n```" - ], - "expertise": 0, - "tags": [ - "input", - "state", - "class" - ], - "notes": [] - }, - { - "name": "Mailto.md", - "title": "Mailto", - "text": "Renders a link formatted to send an email.\n\nDestructure the component's props, use `email`, `subject` and `body` to create a `` element with an appropriate `href` attribute.\nRender the link with `props.children` as its content.\n\n", - "codeBlocks": [ - "```jsx\nfunction Mailto({ email, subject, body, ...props }) {\n return (\n \n {props.children}\n \n );\n}\n```", - "```jsx\nReactDOM.render(\n \n Mail me!\n ,\n document.getElementById(\"root\")\n);\n```" - ], - "expertise": 0, - "tags": [ - "visual", - "functional" - ], - "notes": [] - }, - { - "name": "MappedTable.md", - "title": "MappedTable", - "text": "Renders a table with rows dynamically created from an array of objects and a list of property names.\n\nUse `Object.keys()`, `Array.prototype.filter()`, `Array.prototype.includes()` and `Array.prototype.reduce()` to produce a `filteredData` array, containing all objects with the keys specified in `propertyNames`.\nRender a `` element with a set of columns equal to the amount of values in `propertyNames`.\nUse `Array.prototype.map` to render each value in the `propertyNames` array as a `` element, containing a `
                      ` element.\nUse `Array.prototype.map` to render each object in the `filteredData` array as a `
                      ` for each key in the object.\n\n", - "codeBlocks": [ - "```jsx\nfunction MappedTable({ data, propertyNames }) {\n let filteredData = data.map(v =>\n Object.keys(v)\n .filter(k => propertyNames.includes(k))\n .reduce((acc, key) => ((acc[key] = v[key]), acc), {})\n );\n return (\n \n \n {propertyNames.map(val => )}\n \n \n {filteredData.map((val, i) => (\n \n {propertyNames.map(p => )}\n \n ))}\n \n
                      {val}
                      {val[p]}
                      \n );\n}\n```", - "```jsx\nconst people = [\n { name: 'John', surname: 'Smith', age: 42 },\n { name: 'Adam', surname: 'Smith', gender: 'male' }\n];\nconst propertyNames = ['name', 'surname', 'age'];\nReactDOM.render(\n ,\n document.getElementById('root')\n);\n```" - ], - "expertise": 1, - "tags": [ - "array", - "object", - "functional" - ], - "notes": [ - "This component does not work with nested objects and will break if there are nested objects inside any of the properties specified in `propertyNames`.", - "", - "" - ] - }, - { - "name": "ModalDialog.md", - "title": "ModalDialog", - "text": "Renders a dialog component in a modal, controllable through events. \nTo use the component, import `ModalDialog` only once and then display it using `ModalDialog.show()`, passing the JSX templates and data as parameters.\n\nDefine `modalHandler`, a method that will handle showing the modal dialog, set `state` to the default values initially and bind the `close` and `modalClick` methods to the component's context.\nDefine `close` and `modalClick` to toggle the visibility of the modal dialog, based on `state.closeOnClick`.\nUse the CustomEvent API to listen for `modal` events, that can be dispatched from the `static` `show()` method, handle listeners appropriately from `componentDidMount` and `componentWillUnmount`.\n\nThe `show()` method accepts an argument, that should contain three parameters:\n* `title`, a string for the dialog's title\n* `closeOnClick`, `true` if the modal should close on click or `false` if it should only close when clicking the *X* button\n* `content`, which is the JSX content to be rendered inside the dialog\n\nFinally, in the `render()` method, use a `
                      ` to wrap everything and render the modal dialog with the content passed to `show()`.\n\n", - "codeBlocks": [ - "```css\n .modal {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.6);\n z-index: 9998;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n .dialog {\n background-color: white;\n border-radius: 5px;\n overflow: hidden;\n }\n .dialog-title {\n box-sizing: border-box;\n width: 100%;\n height: 48px;\n padding: 0 16px;\n border-bottom: 0.5px solid #c3c3c3;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .dialog-close {\n font-size: 32px;\n color: #c3c3c3;\n cursor: pointer;\n transform: rotate(45deg);\n user-select: none;\n }\n .dialog-close:hover {\n color: red;\n }\n .dialog-content {\n min-width: 300px;\n }\n```", - "```jsx\nclass ModalDialog extends React.Component {\n constructor() {\n super();\n this.modalHandler = (e) => {\n this.setState({\n data: e.detail.data,\n visible: true\n });\n };\n this.state = {\n data: {\n title: '',\n closeOnClick: false,\n content: ''\n },\n visible: false\n };\n this.close = this.close.bind(this);\n this.modalClick = this.modalClick.bind(this);\n }\n render() {\n return !this.state.visible ? null :
                      \n
                      \n
                      { this.state.data.title }+
                      \n
                      \n {\n this.state.data.content\n }\n
                      \n
                      \n
                      \n }\n componentDidMount() {\n document.addEventListener('modal', this.modalHandler);\n }\n componentWillUnmount() {\n document.removeEventListener('modal', this.modalHandler);\n }\n close() {\n this.setState({\n visible: false,\n data: {\n title: '',\n closeOnClick: false,\n content: ''\n }\n });\n }\n static show(data) {\n document.dispatchEvent(new CustomEvent('modal', {\n detail: {\n data\n }\n }));\n }\n modalClick() {\n if (this.state.data.closeOnClick) this.close();\n }\n}\n```", - "```jsx\n// add to render function\n\n\n// every time you wanna call the dialog\n// content is a jsx element\nModalDialog.show({\n title: 'Hello, world!',\n closeOnClick: true,\n content: \n}); \n```" - ], - "expertise": 1, - "tags": [ - "visual", - "static", - "children", - "state", - "class" - ], - "notes": [ - "This component includes a lot of CSS, which might conflict with other CSS in your project. It is recomended for the modal to be a direct child of the body tag.", - "A more up-to-date method with lower compatibility is to use [Portals](https://reactjs.org/docs/portals.html) in React 16+.", - "", - "" - ] - }, - { - "name": "PasswordRevealer.md", - "title": "PasswordRevealer", - "text": "Renders a password input field with a reveal button.\n\nInitially set `state.shown` to `false` to ensure that the password is not shown by default.\nCreate a method, `toggleShown`, which uses `Component.prototype.setState` to change the input's state from shown to hidden and vice versa, bind it to the component's context.\nIn the`render()` method, use a`
                      ` to wrap both the`` and the `\n
                      \n );\n }\n}\n```", - "```jsx\nReactDOM.render(, document.getElementById('root'));\n```" - ], - "expertise": 0, - "tags": [ - "input", - "state", - "class" - ], - "notes": [] - }, - { - "name": "Select.md", - "title": "Select", - "text": "Renders a `` element.\nRender a `` element.\n\n", - "codeBlocks": [ - "```jsx\nfunction Select ({ values, callback, disabled = false, readonly = false, selected }) {\n return (\n callback(value)}\n >\n {values.map(([value, text]) => )}\n \n );\n}\n```", - "```jsx\nlet choices = [\n ['grapefruit', 'Grapefruit'],\n ['lime', 'Lime'],\n ['coconut', 'Coconut'],\n ['mango', 'Mango']\n];\nReactDOM.render(\n +

                      {this.state.characterCount}/{this.props.limit}

                      +
                      + ); + } +} +``` + +
                      +Examples + +```jsx +ReactDOM.render( + , + document.getElementById('root') +); +``` +
                      + +
                      [⬆ Back to top](#table-of-contents) + +### PasswordRevealer + +Renders a password input field with a reveal button. + +Initially set `state.shown` to `false` to ensure that the password is not shown by default. +Create a method, `toggleShown`, which uses `Component.prototype.setState` to change the input's state from shown to hidden and vice versa, bind it to the component's context. +In the`render()` method, use a`
                      ` to wrap both the`` and the ` +
                      + ); + } +} +``` + +
                      +Examples + +```jsx +ReactDOM.render(, document.getElementById('root')); +``` +
                      + +
                      [⬆ Back to top](#table-of-contents) + +### Select + +Renders a `` element. +Render a `` element. + +```jsx +function Select ({ values, callback, disabled = false, readonly = false, selected }) { + return ( + + ); +} +``` + +
                      +Examples + +```jsx +let choices = [ + ['grapefruit', 'Grapefruit'], + ['lime', 'Lime'], + ['coconut', 'Coconut'], + ['mango', 'Mango'] +]; +ReactDOM.render( + \n

                      {this.state.characterCount}/{this.props.limit}

                      \n \n );\n }\n}\n```", + "```jsx\nReactDOM.render(\n ,\n document.getElementById('root')\n);\n```" + ], + "expertise": 0, + "tags": [ + "input", + "state", + "class" + ], + "notes": [] + }, + { + "name": "Mailto.md", + "title": "Mailto", + "text": "Renders a link formatted to send an email.\n\nDestructure the component's props, use `email`, `subject` and `body` to create a `` element with an appropriate `href` attribute.\nRender the link with `props.children` as its content.\n\n", + "codeBlocks": [ + "```jsx\nfunction Mailto({ email, subject, body, ...props }) {\n return (\n \n {props.children}\n \n );\n}\n```", + "```jsx\nReactDOM.render(\n \n Mail me!\n ,\n document.getElementById(\"root\")\n);\n```" + ], + "expertise": 0, + "tags": [ + "visual", + "functional" + ], + "notes": [] + }, + { + "name": "MappedTable.md", + "title": "MappedTable", + "text": "Renders a table with rows dynamically created from an array of objects and a list of property names.\n\nUse `Object.keys()`, `Array.prototype.filter()`, `Array.prototype.includes()` and `Array.prototype.reduce()` to produce a `filteredData` array, containing all objects with the keys specified in `propertyNames`.\nRender a `` element with a set of columns equal to the amount of values in `propertyNames`.\nUse `Array.prototype.map` to render each value in the `propertyNames` array as a `` element, containing a `
                      ` element.\nUse `Array.prototype.map` to render each object in the `filteredData` array as a `
                      ` for each key in the object.\n\n", + "codeBlocks": [ + "```jsx\nfunction MappedTable({ data, propertyNames }) {\n let filteredData = data.map(v =>\n Object.keys(v)\n .filter(k => propertyNames.includes(k))\n .reduce((acc, key) => ((acc[key] = v[key]), acc), {})\n );\n return (\n \n \n {propertyNames.map(val => )}\n \n \n {filteredData.map((val, i) => (\n \n {propertyNames.map(p => )}\n \n ))}\n \n
                      {val}
                      {val[p]}
                      \n );\n}\n```", + "```jsx\nconst people = [\n { name: 'John', surname: 'Smith', age: 42 },\n { name: 'Adam', surname: 'Smith', gender: 'male' }\n];\nconst propertyNames = ['name', 'surname', 'age'];\nReactDOM.render(\n ,\n document.getElementById('root')\n);\n```" + ], + "expertise": 1, + "tags": [ + "array", + "object", + "functional" + ], + "notes": [ + "This component does not work with nested objects and will break if there are nested objects inside any of the properties specified in `propertyNames`.", + "", + "" + ] + }, + { + "name": "ModalDialog.md", + "title": "ModalDialog", + "text": "Renders a dialog component in a modal, controllable through events. \nTo use the component, import `ModalDialog` only once and then display it using `ModalDialog.show()`, passing the JSX templates and data as parameters.\n\nDefine `modalHandler`, a method that will handle showing the modal dialog, set `state` to the default values initially and bind the `close` and `modalClick` methods to the component's context.\nDefine `close` and `modalClick` to toggle the visibility of the modal dialog, based on `state.closeOnClick`.\nUse the CustomEvent API to listen for `modal` events, that can be dispatched from the `static` `show()` method, handle listeners appropriately from `componentDidMount` and `componentWillUnmount`.\n\nThe `show()` method accepts an argument, that should contain three parameters:\n* `title`, a string for the dialog's title\n* `closeOnClick`, `true` if the modal should close on click or `false` if it should only close when clicking the *X* button\n* `content`, which is the JSX content to be rendered inside the dialog\n\nFinally, in the `render()` method, use a `
                      ` to wrap everything and render the modal dialog with the content passed to `show()`.\n\n", + "codeBlocks": [ + "```css\n .modal {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.6);\n z-index: 9998;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n .dialog {\n background-color: white;\n border-radius: 5px;\n overflow: hidden;\n }\n .dialog-title {\n box-sizing: border-box;\n width: 100%;\n height: 48px;\n padding: 0 16px;\n border-bottom: 0.5px solid #c3c3c3;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .dialog-close {\n font-size: 32px;\n color: #c3c3c3;\n cursor: pointer;\n transform: rotate(45deg);\n user-select: none;\n }\n .dialog-close:hover {\n color: red;\n }\n .dialog-content {\n min-width: 300px;\n }\n```", + "```jsx\nclass ModalDialog extends React.Component {\n constructor() {\n super();\n this.modalHandler = (e) => {\n this.setState({\n data: e.detail.data,\n visible: true\n });\n };\n this.state = {\n data: {\n title: '',\n closeOnClick: false,\n content: ''\n },\n visible: false\n };\n this.close = this.close.bind(this);\n this.modalClick = this.modalClick.bind(this);\n }\n render() {\n return !this.state.visible ? null :
                      \n
                      \n
                      { this.state.data.title }+
                      \n
                      \n {\n this.state.data.content\n }\n
                      \n
                      \n
                      \n }\n componentDidMount() {\n document.addEventListener('modal', this.modalHandler);\n }\n componentWillUnmount() {\n document.removeEventListener('modal', this.modalHandler);\n }\n close() {\n this.setState({\n visible: false,\n data: {\n title: '',\n closeOnClick: false,\n content: ''\n }\n });\n }\n static show(data) {\n document.dispatchEvent(new CustomEvent('modal', {\n detail: {\n data\n }\n }));\n }\n modalClick() {\n if (this.state.data.closeOnClick) this.close();\n }\n}\n```", + "```jsx\n// add to render function\n\n\n// every time you wanna call the dialog\n// content is a jsx element\nModalDialog.show({\n title: 'Hello, world!',\n closeOnClick: true,\n content: \n}); \n```" + ], + "expertise": 1, + "tags": [ + "visual", + "static", + "children", + "state", + "class" + ], + "notes": [ + "This component includes a lot of CSS, which might conflict with other CSS in your project. It is recomended for the modal to be a direct child of the body tag.", + "A more up-to-date method with lower compatibility is to use [Portals](https://reactjs.org/docs/portals.html) in React 16+.", + "", + "" + ] + }, + { + "name": "PasswordRevealer.md", + "title": "PasswordRevealer", + "text": "Renders a password input field with a reveal button.\n\nInitially set `state.shown` to `false` to ensure that the password is not shown by default.\nCreate a method, `toggleShown`, which uses `Component.prototype.setState` to change the input's state from shown to hidden and vice versa, bind it to the component's context.\nIn the`render()` method, use a`
                      ` to wrap both the`` and the `\n
                      \n );\n }\n}\n```", + "```jsx\nReactDOM.render(, document.getElementById('root'));\n```" + ], + "expertise": 0, + "tags": [ + "input", + "state", + "class" + ], + "notes": [] + }, + { + "name": "Select.md", + "title": "Select", + "text": "Renders a `` element.\nRender a `` element.\n\n", + "codeBlocks": [ + "```jsx\nfunction Select ({ values, callback, disabled = false, readonly = false, selected }) {\n return (\n callback(value)}\n >\n {values.map(([value, text]) => )}\n \n );\n}\n```", + "```jsx\nlet choices = [\n ['grapefruit', 'Grapefruit'],\n ['lime', 'Lime'],\n ['coconut', 'Coconut'],\n ['mango', 'Mango']\n];\nReactDOM.render(\n -

                      {this.state.characterCount}/{this.props.limit}

                      -
                      - ); - } +function LimitedTextArea(props) { + const { rows, cols, value, limit } = props; + + const setFormattedContent = text => { + text.length > limit ? setContent(text.slice(0, limit)) : setContent(text); + }; + + const [content, setContent] = useState(value); + // Run once to test if the initial value is greater than the limit + useEffect(() => { + setFormattedContent(content); + }, []); + + const handleChange = event => { + setFormattedContent(event.target.value); + }; + + return ( +
                      + -

                      {this.state.characterCount}/{this.props.limit}

                      -
                      - ); - } +function LimitedTextarea({ rows, cols, value, limit }) { + const [content, setContent] = React.useState(value); + + const setFormattedContent = text => { + text.length > limit ? setContent(text.slice(0, limit)) : setContent(text); + }; + + React.useEffect(() => { + setFormattedContent(content); + }, []); + + return ( +
                      + \n

                      {this.state.characterCount}/{this.props.limit}

                      \n
                      \n );\n }\n}\n```", + "```jsx\nfunction LimitedTextarea({ rows, cols, value, limit }) {\n const [content, setContent] = React.useState(value);\n\n const setFormattedContent = text => {\n text.length > limit ? setContent(text.slice(0, limit)) : setContent(text);\n };\n\n React.useEffect(() => {\n setFormattedContent(content);\n }, []);\n\n return (\n
                      \n setFormattedContent(event.target.value)}\n value={content}\n />\n

                      \n {content.length}/{limit}\n

                      \n
                      \n );\n}\n```", "```jsx\nReactDOM.render(\n ,\n document.getElementById('root')\n);\n```" ], "expertise": 0, @@ -190,9 +190,9 @@ { "name": "PasswordRevealer.md", "title": "PasswordRevealer", - "text": "Renders a password input field with a reveal button.\n\nInitially set `state.shown` to `false` to ensure that the password is not shown by default.\nCreate a method, `toggleShown`, which uses `Component.prototype.setState` to change the input's state from shown to hidden and vice versa, bind it to the component's context.\nIn the`render()` method, use a`
                      ` to wrap both the`` and the `\n
                      \n );\n }\n}\n```", + "```jsx\nfunction PasswordRevealer({ value }) {\n const [shown, setShown] = React.useState(false);\n\n return (\n
                      \n {}}\n />\n \n
                      \n );\n}\n```", "```jsx\nReactDOM.render(, document.getElementById('root'));\n```" ], "expertise": 0, @@ -320,10 +320,10 @@ { "name": "TreeView.md", "title": "TreeView", - "text": "Renders a tree view of a JSON object or array with collapsible content.\n\nUse `defaultProps` to set the default values of certain props.\nUse the value of the `toggled` prop to determine the initial state of the content (collapsed/expanded).\nSet the `state` of the component to the value of the `toggled` prop and bind the `toggle` method to the component's context.\nCreate a method, `toggle`, which uses `Component.prototype.setState` to change the component's `state` from collapsed to expanded and vice versa.\nIn the `render()` method, use a `
                      ` to wrap the contents of the component and the `` element, used to alter the component's `state`.\nDetermine the appearance of the component, based on `this.props.isParentToggled`, `this.state.toggled`, `this.props.name` and `Array.isArray()` on `this.props.data`. \nFor each child in `this.props.data`, determine if it is an object or array and recursively render a sub-tree.\nOtherwise, render a `

                      ` element with the appropriate style.\n\n", + "text": "Renders a tree view of a JSON object or array with collapsible content.\n\nUse object destructuring to set defaults for certain props. \nUse the value of the `toggled` prop to determine the initial state of the content (collapsed/expanded).\nUse the `React.setState()` hook to create the `isToggled` state variable and give it the value of the `toggled` prop initially.\nReturn a `

                      ` to wrap the contents of the component and the `` element, used to alter the component's `isToggled` state.\nDetermine the appearance of the component, based on `isParentToggled`, `isToggled`, `name` and `Array.isArray()` on `data`. \nFor each child in `data`, determine if it is an object or array and recursively render a sub-tree.\nOtherwise, render a `

                      ` element with the appropriate style.\n\n", "codeBlocks": [ "```css\n.tree-element {\n margin: 0;\n position: relative;\n}\n\ndiv.tree-element:before {\n content: '';\n position: absolute;\n top: 24px;\n left: 1px;\n height: calc(100% - 48px);\n border-left: 1px solid gray;\n}\n\n.toggler {\n position: absolute;\n top: 10px;\n left: 0px;\n width: 0; \n height: 0; \n border-top: 4px solid transparent;\n border-bottom: 4px solid transparent;\n border-left: 5px solid gray;\n cursor: pointer;\n}\n\n.toggler.closed {\n transform: rotate(90deg);\n}\n\n.collapsed {\n display: none;\n}\n```", - "```jsx\nclass TreeView extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n toggled: props.toggled\n };\n this.toggle = this.toggle.bind(this);\n }\n\n toggle() {\n this.setState(state => ({ toggled: !state.toggled }));\n }\n\n render() {\n return (\n \n \n {this.props.name ? (\n   {this.props.name}: \n ) : (\n   \n )}\n {Array.isArray(this.props.data) ? \"[\" : \"{\"}\n {!this.state.toggled && \"...\"}\n {Object.keys(this.props.data).map(\n (v, i, a) =>\n typeof this.props.data[v] == \"object\" ? (\n \n ) : (\n \n {Array.isArray(this.props.data) ? \"\" : {v}: }\n {this.props.data[v]}\n {i === a.length - 1 ? \"\" : \",\"}\n

                      \n )\n )}\n {Array.isArray(this.props.data) ? \"]\" : \"}\"}\n {!this.props.isLast ? \",\" : \"\"}\n
                      \n );\n }\n}\n\nTreeView.defaultProps = {\n isLast: true,\n toggled: true,\n name: null,\n isChildElement: false,\n isParentToggled: true\n}\n```", + "```jsx\nfunction TreeView({\n data,\n toggled = true,\n name = null,\n isLast = true,\n isChildElement = false,\n isParentToggled = true\n}) {\n const [isToggled, setIsToggled] = React.useState(toggled);\n\n return (\n \n setIsToggled(!isToggled)}\n />\n {name ?   {name}: :   }\n {Array.isArray(data) ? \"[\" : \"{\"}\n {!isToggled && \"...\"}\n {Object.keys(data).map(\n (v, i, a) =>\n typeof data[v] == \"object\" ? (\n \n ) : (\n \n {Array.isArray(data) ? \"\" : {v}: }\n {data[v]}\n {i === a.length - 1 ? \"\" : \",\"}\n

                      \n )\n )}\n {Array.isArray(data) ? \"]\" : \"}\"}\n {!isLast ? \",\" : \"\"}\n
                      \n );\n}\n```", "```jsx\nlet data = {\n lorem: {\n ipsum: \"dolor sit\",\n amet: {\n consectetur: \"adipiscing\",\n elit: [\n \"duis\",\n \"vitae\",\n {\n semper: \"orci\"\n },\n {\n est: \"sed ornare\"\n },\n \"etiam\",\n [\"laoreet\", \"tincidunt\"],\n [\"vestibulum\", \"ante\"]\n ]\n },\n ipsum: \"primis\"\n }\n};\nReactDOM.render(, document.getElementById(\"root\"));\n```" ], "expertise": 2, From be19eaadd163ce6e718857542b8a96c010b7f21a Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Tue, 12 Feb 2019 20:46:21 +0200 Subject: [PATCH 107/133] Update FileDrop to Hooks --- README.md | 111 +++++++++++++++++++---------------------- data/snippet_data.json | 4 +- snippets/FileDrop.md | 111 +++++++++++++++++++---------------------- 3 files changed, 102 insertions(+), 124 deletions(-) diff --git a/README.md b/README.md index 39e3adc24..c1b257ad1 100644 --- a/README.md +++ b/README.md @@ -714,12 +714,13 @@ ReactDOM.render( Renders a file drag and drop component for a single file. Create a ref called `dropRef` for this component. -Initialize `state.drag` and `state.filename` to `false` and `''` respectively. -The variables `dragCounter` and `state.drag` are used to determine if a file is being dragged, while `state.filename` is used to store the dropped file's name. +Use the `React.useState()` hook to create the `drag` and `filename` variables, initialized to `false` and `''` respectively. +The variables `dragCounter` and `drag` are used to determine if a file is being dragged, while `filename` is used to store the dropped file's name. + Create the `handleDrag`, `handleDragIn`, `handleDragOut` and `handleDrop` methods to handle drag and drop functionality, bind them to the component's context. -Each of the methods will handle a specific event, the listeners for which are created and removed in `componentDidMount` and `componentWillUnmount` respectively. -`handleDrag` prevents the browser from opening the dragged file, `handleDragIn` and `handleDragOut` handle the dragged file entering and exiting the component, while `handleDrop` handles the file being dropped and passes it to `this.props.handleDrop`. -In the `render()` method, create an appropriately styled `
                      ` and use `state.drag` and `state.filename` to determine its contents and style. +Each of the methods will handle a specific event, the listeners for which are created and removed in the `React.useEffect()` hook and its attached `cleanup()` method. +`handleDrag` prevents the browser from opening the dragged file, `handleDragIn` and `handleDragOut` handle the dragged file entering and exiting the component, while `handleDrop` handles the file being dropped and passes it to `props.handleDrop`. +Return an appropriately styled `
                      ` and use `drag` and `filename` to determine its contents and style. Finally, bind the `ref` of the created `
                      ` to `dropRef`. @@ -743,79 +744,67 @@ Finally, bind the `ref` of the created `
                      ` to `dropRef`. ``` ```jsx -class FileDrop extends React.Component { - constructor(props) { - super(props); - this.dropRef = React.createRef(); - this.state = { - drag: false, - filename: '' - } - this.handleDrag = this.handleDrag.bind(this); - this.handleDragIn = this.handleDragIn.bind(this); - this.handleDragOut = this.handleDragOut.bind(this); - this.handleDrop = this.handleDrop.bind(this); - } +function FileDrop(props) { + const [drag, setDrag] = React.useState(false); + const [filename, setFilename] = React.useState(''); + let dropRef = React.createRef(); + let dragCounter = 0; - handleDrag(e) { + const handleDrag = e => { e.preventDefault(); e.stopPropagation(); - } + }; - handleDragIn(e) { + const handleDragIn = e => { e.preventDefault(); e.stopPropagation(); - this.dragCounter++; - if (e.dataTransfer.items && e.dataTransfer.items.length > 0) - this.setState({ drag: true }); - } + dragCounter++; + if (e.dataTransfer.items && e.dataTransfer.items.length > 0) setDrag(true); + }; - handleDragOut(e) { + const handleDragOut = e => { e.preventDefault(); e.stopPropagation(); - this.dragCounter--; - if (this.dragCounter === 0) - this.setState({ drag: false }); - } + dragCounter--; + if (dragCounter === 0) setDrag(false); + }; - handleDrop(e) { + const handleDrop = e => { e.preventDefault(); e.stopPropagation(); - this.setState({ drag: false }); + setDrag(false); if (e.dataTransfer.files && e.dataTransfer.files.length > 0) { - this.props.handleDrop(e.dataTransfer.files[0]); - this.setState({ filename : e.dataTransfer.files[0].name}); + props.handleDrop(e.dataTransfer.files[0]); + setFilename(e.dataTransfer.files[0].name); e.dataTransfer.clearData(); - this.dragCounter = 0; + dragCounter = 0; } - } + }; - componentDidMount() { - let div = this.dropRef.current; - div.addEventListener('dragenter', this.handleDragIn); - div.addEventListener('dragleave', this.handleDragOut); - div.addEventListener('dragover', this.handleDrag); - div.addEventListener('drop', this.handleDrop); - } + React.useEffect(() => { + let div = dropRef.current; + div.addEventListener("dragenter", handleDragIn); + div.addEventListener("dragleave", handleDragOut); + div.addEventListener("dragover", handleDrag); + div.addEventListener("drop", handleDrop); + return function cleanup() { + div.removeEventListener("dragenter", handleDragIn); + div.removeEventListener("dragleave", handleDragOut); + div.removeEventListener("dragover", handleDrag); + div.removeEventListener("drop", handleDrop); + }; + }); - componentWillUnmount() { - let div = this.dropRef.current; - div.removeEventListener('dragenter', this.handleDragIn); - div.removeEventListener('dragleave', this.handleDragOut); - div.removeEventListener('dragover', this.handleDrag); - div.removeEventListener('drop', this.handleDrop); - } - - render() { - return ( -
                      - {this.state.filename && !this.state.drag ? -
                      {this.state.filename}
                      - :
                      Drop files here!
                      - } -
                      - ) - } + return ( +
                      + {filename && !drag ?
                      {filename}
                      :
                      Drop files here!
                      } +
                      + ); } ``` diff --git a/data/snippet_data.json b/data/snippet_data.json index 42be599d0..fdc493f20 100644 --- a/data/snippet_data.json +++ b/data/snippet_data.json @@ -82,10 +82,10 @@ { "name": "FileDrop.md", "title": "FileDrop", - "text": "Renders a file drag and drop component for a single file.\n\nCreate a ref called `dropRef` for this component.\nInitialize `state.drag` and `state.filename` to `false` and `''` respectively.\nThe variables `dragCounter` and `state.drag` are used to determine if a file is being dragged, while `state.filename` is used to store the dropped file's name.\nCreate the `handleDrag`, `handleDragIn`, `handleDragOut` and `handleDrop` methods to handle drag and drop functionality, bind them to the component's context.\nEach of the methods will handle a specific event, the listeners for which are created and removed in `componentDidMount` and `componentWillUnmount` respectively.\n`handleDrag` prevents the browser from opening the dragged file, `handleDragIn` and `handleDragOut` handle the dragged file entering and exiting the component, while `handleDrop` handles the file being dropped and passes it to `this.props.handleDrop`.\nIn the `render()` method, create an appropriately styled `
                      ` and use `state.drag` and `state.filename` to determine its contents and style. \nFinally, bind the `ref` of the created `
                      ` to `dropRef`.\n\n\n", + "text": "Renders a file drag and drop component for a single file.\n\nCreate a ref called `dropRef` for this component.\nUse the `React.useState()` hook to create the `drag` and `filename` variables, initialized to `false` and `''` respectively.\nThe variables `dragCounter` and `drag` are used to determine if a file is being dragged, while `filename` is used to store the dropped file's name.\n\nCreate the `handleDrag`, `handleDragIn`, `handleDragOut` and `handleDrop` methods to handle drag and drop functionality, bind them to the component's context.\nEach of the methods will handle a specific event, the listeners for which are created and removed in the `React.useEffect()` hook and its attached `cleanup()` method.\n`handleDrag` prevents the browser from opening the dragged file, `handleDragIn` and `handleDragOut` handle the dragged file entering and exiting the component, while `handleDrop` handles the file being dropped and passes it to `props.handleDrop`.\nReturn an appropriately styled `
                      ` and use `drag` and `filename` to determine its contents and style. \nFinally, bind the `ref` of the created `
                      ` to `dropRef`.\n\n\n", "codeBlocks": [ "```css\n.filedrop {\n min-height: 120px;\n border: 3px solid #D3D3D3;\n text-align: center;\n font-size: 24px;\n padding: 32px;\n border-radius: 4px;\n}\n\n.filedrop.drag {\n border: 3px dashed #1E90FF;\n}\n\n.filedrop.ready {\n border: 3px solid #32CD32;\n}\n```", - "```jsx\nclass FileDrop extends React.Component {\n constructor(props) {\n super(props);\n this.dropRef = React.createRef();\n this.state = {\n drag: false,\n filename: ''\n }\n this.handleDrag = this.handleDrag.bind(this);\n this.handleDragIn = this.handleDragIn.bind(this);\n this.handleDragOut = this.handleDragOut.bind(this);\n this.handleDrop = this.handleDrop.bind(this);\n }\n\n handleDrag(e) {\n e.preventDefault();\n e.stopPropagation();\n }\n\n handleDragIn(e) {\n e.preventDefault();\n e.stopPropagation();\n this.dragCounter++;\n if (e.dataTransfer.items && e.dataTransfer.items.length > 0) \n this.setState({ drag: true });\n }\n\n handleDragOut(e) {\n e.preventDefault();\n e.stopPropagation();\n this.dragCounter--;\n if (this.dragCounter === 0) \n this.setState({ drag: false });\n }\n\n handleDrop(e) {\n e.preventDefault();\n e.stopPropagation();\n this.setState({ drag: false });\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n this.props.handleDrop(e.dataTransfer.files[0]);\n this.setState({ filename : e.dataTransfer.files[0].name});\n e.dataTransfer.clearData();\n this.dragCounter = 0;\n }\n }\n\n componentDidMount() {\n let div = this.dropRef.current;\n div.addEventListener('dragenter', this.handleDragIn);\n div.addEventListener('dragleave', this.handleDragOut);\n div.addEventListener('dragover', this.handleDrag);\n div.addEventListener('drop', this.handleDrop);\n }\n\n componentWillUnmount() {\n let div = this.dropRef.current;\n div.removeEventListener('dragenter', this.handleDragIn);\n div.removeEventListener('dragleave', this.handleDragOut);\n div.removeEventListener('dragover', this.handleDrag);\n div.removeEventListener('drop', this.handleDrop);\n }\n\n render() {\n return (\n
                      \n {this.state.filename && !this.state.drag ? \n
                      {this.state.filename}
                      \n :
                      Drop files here!
                      \n }\n
                      \n )\n }\n}\n```", + "```jsx\nfunction FileDrop(props) {\n const [drag, setDrag] = React.useState(false);\n const [filename, setFilename] = React.useState('');\n let dropRef = React.createRef();\n let dragCounter = 0;\n\n const handleDrag = e => {\n e.preventDefault();\n e.stopPropagation();\n };\n\n const handleDragIn = e => {\n e.preventDefault();\n e.stopPropagation();\n dragCounter++;\n if (e.dataTransfer.items && e.dataTransfer.items.length > 0) setDrag(true);\n };\n\n const handleDragOut = e => {\n e.preventDefault();\n e.stopPropagation();\n dragCounter--;\n if (dragCounter === 0) setDrag(false);\n };\n\n const handleDrop = e => {\n e.preventDefault();\n e.stopPropagation();\n setDrag(false);\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n props.handleDrop(e.dataTransfer.files[0]);\n setFilename(e.dataTransfer.files[0].name);\n e.dataTransfer.clearData();\n dragCounter = 0;\n }\n };\n\n React.useEffect(() => {\n let div = dropRef.current;\n div.addEventListener(\"dragenter\", handleDragIn);\n div.addEventListener(\"dragleave\", handleDragOut);\n div.addEventListener(\"dragover\", handleDrag);\n div.addEventListener(\"drop\", handleDrop);\n return function cleanup() {\n div.removeEventListener(\"dragenter\", handleDragIn);\n div.removeEventListener(\"dragleave\", handleDragOut);\n div.removeEventListener(\"dragover\", handleDrag);\n div.removeEventListener(\"drop\", handleDrop);\n };\n });\n\n return (\n \n {filename && !drag ?
                      {filename}
                      :
                      Drop files here!
                      }\n
                      \n );\n}\n```", "```jsx\nReactDOM.render(, document.getElementById('root'));\n```" ], "expertise": 2, diff --git a/snippets/FileDrop.md b/snippets/FileDrop.md index c64075fee..7fefbb103 100644 --- a/snippets/FileDrop.md +++ b/snippets/FileDrop.md @@ -3,12 +3,13 @@ Renders a file drag and drop component for a single file. Create a ref called `dropRef` for this component. -Initialize `state.drag` and `state.filename` to `false` and `''` respectively. -The variables `dragCounter` and `state.drag` are used to determine if a file is being dragged, while `state.filename` is used to store the dropped file's name. +Use the `React.useState()` hook to create the `drag` and `filename` variables, initialized to `false` and `''` respectively. +The variables `dragCounter` and `drag` are used to determine if a file is being dragged, while `filename` is used to store the dropped file's name. + Create the `handleDrag`, `handleDragIn`, `handleDragOut` and `handleDrop` methods to handle drag and drop functionality, bind them to the component's context. -Each of the methods will handle a specific event, the listeners for which are created and removed in `componentDidMount` and `componentWillUnmount` respectively. -`handleDrag` prevents the browser from opening the dragged file, `handleDragIn` and `handleDragOut` handle the dragged file entering and exiting the component, while `handleDrop` handles the file being dropped and passes it to `this.props.handleDrop`. -In the `render()` method, create an appropriately styled `
                      ` and use `state.drag` and `state.filename` to determine its contents and style. +Each of the methods will handle a specific event, the listeners for which are created and removed in the `React.useEffect()` hook and its attached `cleanup()` method. +`handleDrag` prevents the browser from opening the dragged file, `handleDragIn` and `handleDragOut` handle the dragged file entering and exiting the component, while `handleDrop` handles the file being dropped and passes it to `props.handleDrop`. +Return an appropriately styled `
                      ` and use `drag` and `filename` to determine its contents and style. Finally, bind the `ref` of the created `
                      ` to `dropRef`. @@ -32,79 +33,67 @@ Finally, bind the `ref` of the created `
                      ` to `dropRef`. ``` ```jsx -class FileDrop extends React.Component { - constructor(props) { - super(props); - this.dropRef = React.createRef(); - this.state = { - drag: false, - filename: '' - } - this.handleDrag = this.handleDrag.bind(this); - this.handleDragIn = this.handleDragIn.bind(this); - this.handleDragOut = this.handleDragOut.bind(this); - this.handleDrop = this.handleDrop.bind(this); - } +function FileDrop(props) { + const [drag, setDrag] = React.useState(false); + const [filename, setFilename] = React.useState(''); + let dropRef = React.createRef(); + let dragCounter = 0; - handleDrag(e) { + const handleDrag = e => { e.preventDefault(); e.stopPropagation(); - } + }; - handleDragIn(e) { + const handleDragIn = e => { e.preventDefault(); e.stopPropagation(); - this.dragCounter++; - if (e.dataTransfer.items && e.dataTransfer.items.length > 0) - this.setState({ drag: true }); - } + dragCounter++; + if (e.dataTransfer.items && e.dataTransfer.items.length > 0) setDrag(true); + }; - handleDragOut(e) { + const handleDragOut = e => { e.preventDefault(); e.stopPropagation(); - this.dragCounter--; - if (this.dragCounter === 0) - this.setState({ drag: false }); - } + dragCounter--; + if (dragCounter === 0) setDrag(false); + }; - handleDrop(e) { + const handleDrop = e => { e.preventDefault(); e.stopPropagation(); - this.setState({ drag: false }); + setDrag(false); if (e.dataTransfer.files && e.dataTransfer.files.length > 0) { - this.props.handleDrop(e.dataTransfer.files[0]); - this.setState({ filename : e.dataTransfer.files[0].name}); + props.handleDrop(e.dataTransfer.files[0]); + setFilename(e.dataTransfer.files[0].name); e.dataTransfer.clearData(); - this.dragCounter = 0; + dragCounter = 0; } - } + }; - componentDidMount() { - let div = this.dropRef.current; - div.addEventListener('dragenter', this.handleDragIn); - div.addEventListener('dragleave', this.handleDragOut); - div.addEventListener('dragover', this.handleDrag); - div.addEventListener('drop', this.handleDrop); - } + React.useEffect(() => { + let div = dropRef.current; + div.addEventListener("dragenter", handleDragIn); + div.addEventListener("dragleave", handleDragOut); + div.addEventListener("dragover", handleDrag); + div.addEventListener("drop", handleDrop); + return function cleanup() { + div.removeEventListener("dragenter", handleDragIn); + div.removeEventListener("dragleave", handleDragOut); + div.removeEventListener("dragover", handleDrag); + div.removeEventListener("drop", handleDrop); + }; + }); - componentWillUnmount() { - let div = this.dropRef.current; - div.removeEventListener('dragenter', this.handleDragIn); - div.removeEventListener('dragleave', this.handleDragOut); - div.removeEventListener('dragover', this.handleDrag); - div.removeEventListener('drop', this.handleDrop); - } - - render() { - return ( -
                      - {this.state.filename && !this.state.drag ? -
                      {this.state.filename}
                      - :
                      Drop files here!
                      - } -
                      - ) - } + return ( +
                      + {filename && !drag ?
                      {filename}
                      :
                      Drop files here!
                      } +
                      + ); } ``` From a6cb089ed4b28b81ec52215132d4fcd946af9295 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Tue, 12 Feb 2019 21:01:31 +0200 Subject: [PATCH 108/133] Update StarRating --- README.md | 240 +++--------------- data/snippet_data.json | 28 +- snippets/StarRating.md | 96 +++---- {snippets => snippets_archive}/ModalDialog.md | 0 4 files changed, 80 insertions(+), 284 deletions(-) rename {snippets => snippets_archive}/ModalDialog.md (100%) diff --git a/README.md b/README.md index c1b257ad1..918e8a4f3 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,6 @@ * [Collapse](#collapse) * [FileDrop](#filedrop) * [Mailto](#mailto) -* [ModalDialog](#modaldialog) * [StarRating](#starrating) * [Tab](#tab) * [Ticker](#ticker) @@ -850,215 +849,54 @@ ReactDOM.render(
                      [⬆ Back to top](#table-of-contents) -### ModalDialog - -Renders a dialog component in a modal, controllable through events. -To use the component, import `ModalDialog` only once and then display it using `ModalDialog.show()`, passing the JSX templates and data as parameters. - -Define `modalHandler`, a method that will handle showing the modal dialog, set `state` to the default values initially and bind the `close` and `modalClick` methods to the component's context. -Define `close` and `modalClick` to toggle the visibility of the modal dialog, based on `state.closeOnClick`. -Use the CustomEvent API to listen for `modal` events, that can be dispatched from the `static` `show()` method, handle listeners appropriately from `componentDidMount` and `componentWillUnmount`. - -The `show()` method accepts an argument, that should contain three parameters: -* `title`, a string for the dialog's title -* `closeOnClick`, `true` if the modal should close on click or `false` if it should only close when clicking the *X* button -* `content`, which is the JSX content to be rendered inside the dialog - -Finally, in the `render()` method, use a `
                      ` to wrap everything and render the modal dialog with the content passed to `show()`. - -```css - .modal { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.6); - z-index: 9998; - display: flex; - justify-content: center; - align-items: center; - } - .dialog { - background-color: white; - border-radius: 5px; - overflow: hidden; - } - .dialog-title { - box-sizing: border-box; - width: 100%; - height: 48px; - padding: 0 16px; - border-bottom: 0.5px solid #c3c3c3; - display: flex; - justify-content: space-between; - align-items: center; - } - .dialog-close { - font-size: 32px; - color: #c3c3c3; - cursor: pointer; - transform: rotate(45deg); - user-select: none; - } - .dialog-close:hover { - color: red; - } - .dialog-content { - min-width: 300px; - } -``` - -```jsx -class ModalDialog extends React.Component { - constructor() { - super(); - this.modalHandler = (e) => { - this.setState({ - data: e.detail.data, - visible: true - }); - }; - this.state = { - data: { - title: '', - closeOnClick: false, - content: '' - }, - visible: false - }; - this.close = this.close.bind(this); - this.modalClick = this.modalClick.bind(this); - } - render() { - return !this.state.visible ? null :
                      -
                      -
                      { this.state.data.title }+
                      -
                      - { - this.state.data.content - } -
                      -
                      -
                      - } - componentDidMount() { - document.addEventListener('modal', this.modalHandler); - } - componentWillUnmount() { - document.removeEventListener('modal', this.modalHandler); - } - close() { - this.setState({ - visible: false, - data: { - title: '', - closeOnClick: false, - content: '' - } - }); - } - static show(data) { - document.dispatchEvent(new CustomEvent('modal', { - detail: { - data - } - })); - } - modalClick() { - if (this.state.data.closeOnClick) this.close(); - } -} -``` -#### Notes - -This component includes a lot of CSS, which might conflict with other CSS in your project. It is recomended for the modal to be a direct child of the body tag.,A more up-to-date method with lower compatibility is to use [Portals](https://reactjs.org/docs/portals.html) in React 16+.,, - -
                      -Examples - -```jsx -// add to render function - - -// every time you wanna call the dialog -// content is a jsx element -ModalDialog.show({ - title: 'Hello, world!', - closeOnClick: true, - content: -}); -``` -
                      - -
                      [⬆ Back to top](#table-of-contents) - ### StarRating Renders a star rating component. -Use and IIFE to define a functional component, called `Star` that will render each individual star with the appropriate appearance, based on the parent component's `state` and return the class component `StarRating`. -Use the value of the `rating` prop to determine if a valid rating is supplied and store it in `state.rating` (or `0` if invalid or not supplied). -Initialize `state.selection` to `0`. -Create two methods, `hoverOver` and `setRating`, that take an event as argument and update `state.selected` and `state.rating` according to it, bind them both to the component's context. -In the `render()` method, create a `
                      ` to wrap the `` components, which are created using `Array.prototype.map` on an array of 5 elements, created using `Array.from`, and handle the `onMouseLeave` event to set `state.selection` to `0`, the `onClick` event to set -the `state.rating` and the `onMouseOver` event to set `state.selection` to the `star-id` attribute of the `event.target` respectively. +Define a component, called `Star` that will render each individual star with the appropriate appearance, based on the parent component's state. +In the `StarRating` component, use the `React.setState()` hook to define the `rating` and `selection` state variables with the initial values of `props.rating` (or `0` if invalid or not supplied) and `0`. +Create a method, `hoverOver`, that updates `selected` and `rating` according to the provided `event`. +Create a `
                      ` to wrap the `` components, which are created using `Array.prototype.map` on an array of 5 elements, created using `Array.from`, and handle the `onMouseLeave` event to set `selection` to `0`, the `onClick` event to set the `rating` and the `onMouseOver` event to set `selection` to the `star-id` attribute of the `event.target` respectively. Finally, pass the appropriate values to each `` component (`starId` and `marked`). ```jsx -const StarRating = (function() { - function Star({ marked, starId }) { - return ( - - {marked ? '\u2605' : '\u2606'} - - ); - } +function Star({ marked, starId }) { + return ( + + {marked ? "\u2605" : "\u2606"} + + ); +} - return class StarRating extends React.Component { - constructor(props) { - super(props); - this.state = { - rating: typeof props.rating == 'number' ? props.rating : 0, - selection: 0 - }; - this.hoverOver = this.hoverOver.bind(this); - this.hoverOut = this.hoverOver.bind(this, null); - this.handleClick = this.handleClick.bind(this); - } - hoverOver(event) { - let val = 0; - if (event && event.target && event.target.getAttribute('star-id')) - val = event.target.getAttribute('star-id'); - this.setState(state => ({ selection: val })); - } - handleClick(event) { - const val = event.target.getAttribute('star-id') || this.state.rating; - this.setState(state => ({ rating: val })); - } - render() { - return ( -
                      - {Array.from({ length: 5 }, (v, i) => ( - = i+1 - : this.state.rating >= i+1 - } - /> - ))} -
                      - ); - } +function StarRating(props) { + const [rating, setRating] = React.useState( + typeof props.rating == "number" ? props.rating : 0 + ); + const [selection, setSelection] = React.useState(0); + const hoverOver = event => { + let val = 0; + if (event && event.target && event.target.getAttribute("star-id")) + val = event.target.getAttribute("star-id"); + setSelection(val); }; -})(); + return ( +
                      hoverOver(null)} + onClick={() => + setRating(event.target.getAttribute("star-id") || this.state.rating) + } + onMouseOver={hoverOver} + > + {Array.from({ length: 5 }, (v, i) => ( + = i + 1 : rating >= i + 1} + /> + ))} +
                      + ); +} ```
                      diff --git a/data/snippet_data.json b/data/snippet_data.json index fdc493f20..6c8de8b51 100644 --- a/data/snippet_data.json +++ b/data/snippet_data.json @@ -163,30 +163,6 @@ "" ] }, - { - "name": "ModalDialog.md", - "title": "ModalDialog", - "text": "Renders a dialog component in a modal, controllable through events. \nTo use the component, import `ModalDialog` only once and then display it using `ModalDialog.show()`, passing the JSX templates and data as parameters.\n\nDefine `modalHandler`, a method that will handle showing the modal dialog, set `state` to the default values initially and bind the `close` and `modalClick` methods to the component's context.\nDefine `close` and `modalClick` to toggle the visibility of the modal dialog, based on `state.closeOnClick`.\nUse the CustomEvent API to listen for `modal` events, that can be dispatched from the `static` `show()` method, handle listeners appropriately from `componentDidMount` and `componentWillUnmount`.\n\nThe `show()` method accepts an argument, that should contain three parameters:\n* `title`, a string for the dialog's title\n* `closeOnClick`, `true` if the modal should close on click or `false` if it should only close when clicking the *X* button\n* `content`, which is the JSX content to be rendered inside the dialog\n\nFinally, in the `render()` method, use a `
                      ` to wrap everything and render the modal dialog with the content passed to `show()`.\n\n", - "codeBlocks": [ - "```css\n .modal {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.6);\n z-index: 9998;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n .dialog {\n background-color: white;\n border-radius: 5px;\n overflow: hidden;\n }\n .dialog-title {\n box-sizing: border-box;\n width: 100%;\n height: 48px;\n padding: 0 16px;\n border-bottom: 0.5px solid #c3c3c3;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .dialog-close {\n font-size: 32px;\n color: #c3c3c3;\n cursor: pointer;\n transform: rotate(45deg);\n user-select: none;\n }\n .dialog-close:hover {\n color: red;\n }\n .dialog-content {\n min-width: 300px;\n }\n```", - "```jsx\nclass ModalDialog extends React.Component {\n constructor() {\n super();\n this.modalHandler = (e) => {\n this.setState({\n data: e.detail.data,\n visible: true\n });\n };\n this.state = {\n data: {\n title: '',\n closeOnClick: false,\n content: ''\n },\n visible: false\n };\n this.close = this.close.bind(this);\n this.modalClick = this.modalClick.bind(this);\n }\n render() {\n return !this.state.visible ? null :
                      \n
                      \n
                      { this.state.data.title }+
                      \n
                      \n {\n this.state.data.content\n }\n
                      \n
                      \n
                      \n }\n componentDidMount() {\n document.addEventListener('modal', this.modalHandler);\n }\n componentWillUnmount() {\n document.removeEventListener('modal', this.modalHandler);\n }\n close() {\n this.setState({\n visible: false,\n data: {\n title: '',\n closeOnClick: false,\n content: ''\n }\n });\n }\n static show(data) {\n document.dispatchEvent(new CustomEvent('modal', {\n detail: {\n data\n }\n }));\n }\n modalClick() {\n if (this.state.data.closeOnClick) this.close();\n }\n}\n```", - "```jsx\n// add to render function\n\n\n// every time you wanna call the dialog\n// content is a jsx element\nModalDialog.show({\n title: 'Hello, world!',\n closeOnClick: true,\n content: \n}); \n```" - ], - "expertise": 1, - "tags": [ - "visual", - "static", - "children", - "state", - "class" - ], - "notes": [ - "This component includes a lot of CSS, which might conflict with other CSS in your project. It is recomended for the modal to be a direct child of the body tag.", - "A more up-to-date method with lower compatibility is to use [Portals](https://reactjs.org/docs/portals.html) in React 16+.", - "", - "" - ] - }, { "name": "PasswordRevealer.md", "title": "PasswordRevealer", @@ -221,9 +197,9 @@ { "name": "StarRating.md", "title": "StarRating", - "text": "Renders a star rating component.\n\nUse and IIFE to define a functional component, called `Star` that will render each individual star with the appropriate appearance, based on the parent component's `state` and return the class component `StarRating`.\nUse the value of the `rating` prop to determine if a valid rating is supplied and store it in `state.rating` (or `0` if invalid or not supplied).\nInitialize `state.selection` to `0`.\nCreate two methods, `hoverOver` and `setRating`, that take an event as argument and update `state.selected` and `state.rating` according to it, bind them both to the component's context.\nIn the `render()` method, create a `
                      ` to wrap the `` components, which are created using `Array.prototype.map` on an array of 5 elements, created using `Array.from`, and handle the `onMouseLeave` event to set `state.selection` to `0`, the `onClick` event to set\nthe `state.rating` and the `onMouseOver` event to set `state.selection` to the `star-id` attribute of the `event.target` respectively. \nFinally, pass the appropriate values to each `` component (`starId` and `marked`).\n\n", + "text": "Renders a star rating component.\n\nDefine a component, called `Star` that will render each individual star with the appropriate appearance, based on the parent component's state.\nIn the `StarRating` component, use the `React.setState()` hook to define the `rating` and `selection` state variables with the initial values of `props.rating` (or `0` if invalid or not supplied) and `0`.\nCreate a method, `hoverOver`, that updates `selected` and `rating` according to the provided `event`.\nCreate a `
                      ` to wrap the `` components, which are created using `Array.prototype.map` on an array of 5 elements, created using `Array.from`, and handle the `onMouseLeave` event to set `selection` to `0`, the `onClick` event to set the `rating` and the `onMouseOver` event to set `selection` to the `star-id` attribute of the `event.target` respectively. \nFinally, pass the appropriate values to each `` component (`starId` and `marked`).\n\n", "codeBlocks": [ - "```jsx\nconst StarRating = (function() {\n function Star({ marked, starId }) {\n return (\n \n {marked ? '\\u2605' : '\\u2606'}\n \n );\n }\n\n return class StarRating extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n rating: typeof props.rating == 'number' ? props.rating : 0,\n selection: 0\n };\n this.hoverOver = this.hoverOver.bind(this);\n this.hoverOut = this.hoverOver.bind(this, null);\n this.handleClick = this.handleClick.bind(this);\n }\n hoverOver(event) {\n let val = 0;\n if (event && event.target && event.target.getAttribute('star-id'))\n val = event.target.getAttribute('star-id');\n this.setState(state => ({ selection: val }));\n }\n handleClick(event) {\n const val = event.target.getAttribute('star-id') || this.state.rating;\n this.setState(state => ({ rating: val }));\n }\n render() {\n return (\n \n {Array.from({ length: 5 }, (v, i) => (\n = i+1\n : this.state.rating >= i+1\n }\n />\n ))}\n
                      \n );\n }\n };\n})();\n```", + "```jsx\nfunction Star({ marked, starId }) {\n return (\n \n {marked ? \"\\u2605\" : \"\\u2606\"}\n \n );\n}\n\nfunction StarRating(props) {\n const [rating, setRating] = React.useState(\n typeof props.rating == \"number\" ? props.rating : 0\n );\n const [selection, setSelection] = React.useState(0);\n const hoverOver = event => {\n let val = 0;\n if (event && event.target && event.target.getAttribute(\"star-id\"))\n val = event.target.getAttribute(\"star-id\");\n setSelection(val);\n };\n return (\n hoverOver(null)}\n onClick={() =>\n setRating(event.target.getAttribute(\"star-id\") || this.state.rating)\n }\n onMouseOver={hoverOver}\n >\n {Array.from({ length: 5 }, (v, i) => (\n = i + 1 : rating >= i + 1}\n />\n ))}\n
                      \n );\n}\n```", "```jsx\nReactDOM.render(, document.getElementById('root'));\nReactDOM.render(, document.getElementById('root'));\n```" ], "expertise": 2, diff --git a/snippets/StarRating.md b/snippets/StarRating.md index 39bf22d34..60fe1309b 100644 --- a/snippets/StarRating.md +++ b/snippets/StarRating.md @@ -2,68 +2,50 @@ Renders a star rating component. -Use and IIFE to define a functional component, called `Star` that will render each individual star with the appropriate appearance, based on the parent component's `state` and return the class component `StarRating`. -Use the value of the `rating` prop to determine if a valid rating is supplied and store it in `state.rating` (or `0` if invalid or not supplied). -Initialize `state.selection` to `0`. -Create two methods, `hoverOver` and `setRating`, that take an event as argument and update `state.selected` and `state.rating` according to it, bind them both to the component's context. -In the `render()` method, create a `
                      ` to wrap the `` components, which are created using `Array.prototype.map` on an array of 5 elements, created using `Array.from`, and handle the `onMouseLeave` event to set `state.selection` to `0`, the `onClick` event to set -the `state.rating` and the `onMouseOver` event to set `state.selection` to the `star-id` attribute of the `event.target` respectively. +Define a component, called `Star` that will render each individual star with the appropriate appearance, based on the parent component's state. +In the `StarRating` component, use the `React.setState()` hook to define the `rating` and `selection` state variables with the initial values of `props.rating` (or `0` if invalid or not supplied) and `0`. +Create a method, `hoverOver`, that updates `selected` and `rating` according to the provided `event`. +Create a `
                      ` to wrap the `` components, which are created using `Array.prototype.map` on an array of 5 elements, created using `Array.from`, and handle the `onMouseLeave` event to set `selection` to `0`, the `onClick` event to set the `rating` and the `onMouseOver` event to set `selection` to the `star-id` attribute of the `event.target` respectively. Finally, pass the appropriate values to each `` component (`starId` and `marked`). ```jsx -const StarRating = (function() { - function Star({ marked, starId }) { - return ( - - {marked ? '\u2605' : '\u2606'} - - ); - } +function Star({ marked, starId }) { + return ( + + {marked ? "\u2605" : "\u2606"} + + ); +} - return class StarRating extends React.Component { - constructor(props) { - super(props); - this.state = { - rating: typeof props.rating == 'number' ? props.rating : 0, - selection: 0 - }; - this.hoverOver = this.hoverOver.bind(this); - this.hoverOut = this.hoverOver.bind(this, null); - this.handleClick = this.handleClick.bind(this); - } - hoverOver(event) { - let val = 0; - if (event && event.target && event.target.getAttribute('star-id')) - val = event.target.getAttribute('star-id'); - this.setState(state => ({ selection: val })); - } - handleClick(event) { - const val = event.target.getAttribute('star-id') || this.state.rating; - this.setState(state => ({ rating: val })); - } - render() { - return ( -
                      - {Array.from({ length: 5 }, (v, i) => ( - = i+1 - : this.state.rating >= i+1 - } - /> - ))} -
                      - ); - } +function StarRating(props) { + const [rating, setRating] = React.useState( + typeof props.rating == "number" ? props.rating : 0 + ); + const [selection, setSelection] = React.useState(0); + const hoverOver = event => { + let val = 0; + if (event && event.target && event.target.getAttribute("star-id")) + val = event.target.getAttribute("star-id"); + setSelection(val); }; -})(); + return ( +
                      hoverOver(null)} + onClick={() => + setRating(event.target.getAttribute("star-id") || this.state.rating) + } + onMouseOver={hoverOver} + > + {Array.from({ length: 5 }, (v, i) => ( + = i + 1 : rating >= i + 1} + /> + ))} +
                      + ); +} ``` ```jsx diff --git a/snippets/ModalDialog.md b/snippets_archive/ModalDialog.md similarity index 100% rename from snippets/ModalDialog.md rename to snippets_archive/ModalDialog.md From f485e78339a7adad338aa1509aa3ef12a24e5d7e Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Tue, 12 Feb 2019 21:10:05 +0200 Subject: [PATCH 109/133] Update tabs to Hooks --- README.md | 95 +++++++++++++++++------------------------- data/snippet_data.json | 6 +-- snippets/Tabs.md | 95 +++++++++++++++++------------------------- 3 files changed, 81 insertions(+), 115 deletions(-) diff --git a/README.md b/README.md index 918e8a4f3..78e729de2 100644 --- a/README.md +++ b/README.md @@ -914,10 +914,11 @@ ReactDOM.render(, document.getElementById('root')); Renders a tabbed menu and view component. -Define `TabItem` as a middleware, pass it to the `Tab` and remove unnecessary nodes expect for `TabItem` by identifying the function's name in `props.children`. +Define a `TabItem` component, pass it to the `Tab` and remove unnecessary nodes expect for `TabItem` by identifying the function's name in `props.children`. +Use the `React.useState()` hook to initialize the value of the `bindIndex` state variable to `props.defaultIndex`. Use `Array.prototype.map` on the collected nodes to render the `tab-menu` and `tab-view`. Define `changeTab`, which will be executed when clicking a ` - ))} -
                      -
                      - {items.map(({ props }) => ( -
                      - ))} -
                      -
                      - ); - } -} function TabItem(props) { return
                      ; } + +function Tabs(props) { + const [bindIndex, setBindIndex] = React.useState(props.defaultIndex); + const changeTab = newIndex => { + if (typeof props.onTabClick === "function") props.onTabClick(newIndex); + setBindIndex(newIndex); + }; + const items = props.children.filter(item => item.type.name === "TabItem"); + + return ( +
                      +
                      + {items.map(({ props: { index, label } }) => ( + + ))} +
                      +
                      + {items.map(({ props }) => ( +
                      + ))} +
                      +
                      + ); +} ```
                      @@ -998,14 +981,14 @@ function TabItem(props) { ```jsx ReactDOM.render( - + Lorem ipsum Dolor sit amet - , + , document.getElementById("root") ); diff --git a/data/snippet_data.json b/data/snippet_data.json index 6c8de8b51..648993aa6 100644 --- a/data/snippet_data.json +++ b/data/snippet_data.json @@ -215,11 +215,11 @@ { "name": "Tabs.md", "title": "Tab", - "text": "Renders a tabbed menu and view component.\n\nDefine `TabItem` as a middleware, pass it to the `Tab` and remove unnecessary nodes expect for `TabItem` by identifying the function's name in `props.children`.\nUse `Array.prototype.map` on the collected nodes to render the `tab-menu` and `tab-view`. \nDefine `changeTab`, which will be executed when clicking a `\n ))}\n
                      \n
                      \n {items.map(({ props }) => (\n \n ))}\n
                      \n
                      \n );\n }\n}\nfunction TabItem(props) {\n return
                      ;\n}\n```", - "```jsx\nReactDOM.render(\n \n \n Lorem ipsum\n \n \n Dolor sit amet\n \n ,\n document.getElementById(\"root\")\n);\n\n```" + "```jsx\nfunction TabItem(props) {\n return
                      ;\n}\n\nfunction Tabs(props) {\n const [bindIndex, setBindIndex] = React.useState(props.defaultIndex);\n const changeTab = newIndex => {\n if (typeof props.onTabClick === \"function\") props.onTabClick(newIndex);\n setBindIndex(newIndex);\n };\n const items = props.children.filter(item => item.type.name === \"TabItem\");\n\n return (\n
                      \n
                      \n {items.map(({ props: { index, label } }) => (\n changeTab(index)}\n className={bindIndex === index ? \"focus\" : \"\"}\n >\n {label}\n \n ))}\n
                      \n
                      \n {items.map(({ props }) => (\n \n ))}\n
                      \n
                      \n );\n}\n```", + "```jsx\nReactDOM.render(\n \n \n Lorem ipsum\n \n \n Dolor sit amet\n \n ,\n document.getElementById(\"root\")\n);\n\n```" ], "expertise": 1, "tags": [ diff --git a/snippets/Tabs.md b/snippets/Tabs.md index 8582e9974..e1847e625 100644 --- a/snippets/Tabs.md +++ b/snippets/Tabs.md @@ -1,10 +1,11 @@ ### Tab Renders a tabbed menu and view component. -Define `TabItem` as a middleware, pass it to the `Tab` and remove unnecessary nodes expect for `TabItem` by identifying the function's name in `props.children`. +Define a `TabItem` component, pass it to the `Tab` and remove unnecessary nodes expect for `TabItem` by identifying the function's name in `props.children`. +Use the `React.useState()` hook to initialize the value of the `bindIndex` state variable to `props.defaultIndex`. Use `Array.prototype.map` on the collected nodes to render the `tab-menu` and `tab-view`. Define `changeTab`, which will be executed when clicking a ` - ))} -
                      -
                      - {items.map(({ props }) => ( -
                      - ))} -
                      -
                      - ); - } -} function TabItem(props) { return
                      ; } + +function Tabs(props) { + const [bindIndex, setBindIndex] = React.useState(props.defaultIndex); + const changeTab = newIndex => { + if (typeof props.onTabClick === "function") props.onTabClick(newIndex); + setBindIndex(newIndex); + }; + const items = props.children.filter(item => item.type.name === "TabItem"); + + return ( +
                      +
                      + {items.map(({ props: { index, label } }) => ( + + ))} +
                      +
                      + {items.map(({ props }) => ( +
                      + ))} +
                      +
                      + ); +} ``` ```jsx ReactDOM.render( - + Lorem ipsum Dolor sit amet - , + , document.getElementById("root") ); From d170e23ec26f5abc960810379aaaa84282e128f0 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Tue, 12 Feb 2019 21:18:22 +0200 Subject: [PATCH 110/133] Update Ticker --- snippets/Ticker.md | 60 ++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/snippets/Ticker.md b/snippets/Ticker.md index e319fb69b..06373cd78 100644 --- a/snippets/Ticker.md +++ b/snippets/Ticker.md @@ -2,45 +2,37 @@ Renders a ticker component. -- The ticker state is initially set to zero -- When the `Tick!` button is clicked, `timer` is incremented periodically at the given `interval` -- When the `Reset` button is clicked, the value of the timer is set to zero and the `setInterval` is cleared -- The `setInterval` is cleared once the desired `time` is reached -- `time` and `interval` are the required props +Use the `React.useState()` hook to initialize the `ticker` state variable to `0`. +Define two methods, `tick` and `reset`, that will periodically increment `timer` based on `interval` and reset `interval` respectively. +Return a `
                      ` with two ` - -
                      - ); - } + return ( +
                      + {this.state.ticker} + + +
                      + ); } ``` From 8095487476f824acac8941e5d6edab7d3805f8d3 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Tue, 12 Feb 2019 21:22:50 +0200 Subject: [PATCH 111/133] Update Toggle --- snippets/Toggle.md | 59 ++++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 39 deletions(-) diff --git a/snippets/Toggle.md b/snippets/Toggle.md index 92e86ab16..fc28ef00d 100644 --- a/snippets/Toggle.md +++ b/snippets/Toggle.md @@ -2,49 +2,30 @@ Renders a toggle component. -Initialize `state.isToggleOn` to `false`, bind the `handleClick` method to the component's context. +Use the `React.useState()` to initialize the `isToggleOn` state variable to `false`. Use an object, `style`, to hold the styles for individual components and their states. -Create a method, `handleClick`, which uses `Component.prototype.setState` to change the component's `state.toggleOn`. -In the `render()` method, destructure `state` and `style`, create a ` - ); - } + return ( + + ); } ``` From c842d0eecb5c3abf7aa8172d5bb21ce7e323f8c3 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Tue, 12 Feb 2019 22:02:49 +0200 Subject: [PATCH 112/133] Update Tooltip --- README.md | 214 ++++++++++++++++------------------------- data/snippet_data.json | 13 +-- snippets/Tooltip.md | 94 +++++++----------- 3 files changed, 128 insertions(+), 193 deletions(-) diff --git a/README.md b/README.md index 78e729de2..1fa1288bf 100644 --- a/README.md +++ b/README.md @@ -1001,45 +1001,37 @@ ReactDOM.render( Renders a ticker component. -- The ticker state is initially set to zero -- When the `Tick!` button is clicked, `timer` is incremented periodically at the given `interval` -- When the `Reset` button is clicked, the value of the timer is set to zero and the `setInterval` is cleared -- The `setInterval` is cleared once the desired `time` is reached -- `time` and `interval` are the required props +Use the `React.useState()` hook to initialize the `ticker` state variable to `0`. +Define two methods, `tick` and `reset`, that will periodically increment `timer` based on `interval` and reset `interval` respectively. +Return a `
                      ` with two ` - -
                      - ); - } + return ( +
                      + {this.state.ticker} + + +
                      + ); } ``` @@ -1057,49 +1049,30 @@ ReactDOM.render(, document.getElementById('r Renders a toggle component. -Initialize `state.isToggleOn` to `false`, bind the `handleClick` method to the component's context. +Use the `React.useState()` to initialize the `isToggleOn` state variable to `false`. Use an object, `style`, to hold the styles for individual components and their states. -Create a method, `handleClick`, which uses `Component.prototype.setState` to change the component's `state.toggleOn`. -In the `render()` method, destructure `state` and `style`, create a ` - ); - } + return ( + + ); } ``` @@ -1117,67 +1090,48 @@ ReactDOM.render(, document.getElementById('root')); Renders a tooltip component. -Set the `state` of the component to `show: false` initially, define an object, `style`, to hold the styles for individual components and their states. -Create a method, `toggleTooltip`, which uses `this.setState` to change the state's `show` property from `true` to `false` and vice versa. -Bind `showTooltip` and `hideTooltip` to the component's context with the respective values of `true` and `false`. -In the `render()` method, compute if the tooltip should be shown or hidden, render the content of the tooltip and bind the `onMouseEnter` and `onMouseLeave` events to `showTooltip` and `hideTooltip` respectively. +Use the `React.useState()` hook to create the `show` variable and initialize it to `false`. +Return a `
                      ` element that contains the `
                      ` that will be the tooltip and the `children` passed to the component. +Handle the `onMouseEnter` and `onMouseLeave` methods, by altering the value of the `show` variable. +```css +.tooltip { + position: relative; + background: rgba(0, 0, 0, 0.7); + color: white; + visibility: hidden; + padding: 5px; + border-radius: 5px; +} +.tooltip-arrow { + position: absolute; + top: 100%; + left: 50%; + border-width: 5px; + border-style: solid; + border-color: rgba(0, 0, 0, 0.7) transparent transparent; +} +``` + ```jsx -class Tooltip extends React.Component { - constructor(props) { - super(props); - this.state = { - show: false - }; - this.style = { - tooltip: { - position: 'relative', - backgroundColor: "rgba(0,0,0,0.7)", - color: "white", - visibility: "hidden", - width: "fit-content", - padding: 5, - borderRadius: 5 - }, - tooltipArrow: { - position: 'absolute', - top: '100%', - left: '50%', - borderWidth: 5, - borderStyle: 'solid', - borderColor: "rgba(0,0,0,0.7) transparent transparent", - }, - visible: { - visibility: "visible" - }, - }; - this.showTooltip = this.toggleTooltip.bind(this, true); - this.hideTooltip = this.toggleTooltip.bind(this, false); - } +function Tooltip({ children, text, ...rest }) { + const [show, setShow] = React.useState(false); - toggleTooltip = tooltipState => { - this.setState({ - show: tooltipState - }); - }; - - render() { - const { children, text, ...rest } = this.props; - const { show } = this.state; - const { visible, tooltip, tooltipArrow } = this.style; - const showTooltip = show ? visible : {}; - return ( -
                      -
                      - {text} - -
                      -
                      - {children} -
                      + return ( +
                      +
                      + {text} +
                      - ); - } +
                      setShow(true)} + onMouseLeave={() => setShow(false)} + > + {children} +
                      +
                      + ); } ``` diff --git a/data/snippet_data.json b/data/snippet_data.json index 648993aa6..3b19501ad 100644 --- a/data/snippet_data.json +++ b/data/snippet_data.json @@ -247,9 +247,9 @@ { "name": "Ticker.md", "title": "Ticker", - "text": "Renders a ticker component.\n\n- The ticker state is initially set to zero \n- When the `Tick!` button is clicked, `timer` is incremented periodically at the given `interval`\n- When the `Reset` button is clicked, the value of the timer is set to zero and the `setInterval` is cleared\n- The `setInterval` is cleared once the desired `time` is reached\n- `time` and `interval` are the required props\n\n", + "text": "Renders a ticker component.\n\nUse the `React.useState()` hook to initialize the `ticker` state variable to `0`.\nDefine two methods, `tick` and `reset`, that will periodically increment `timer` based on `interval` and reset `interval` respectively.\nReturn a `
                      ` with two `\n\t\t\t\t\n\t\t\t
                      \n\t\t);\n\t}\n}\n```", + "```jsx\nfunction Ticker(props) {\n const [ticker, setTicker] = React.useState(0);\n let interval = null;\n\n const tick = () => {\n reset();\n interval = setInterval(() => {\n if (ticker < props.times) \n setTicker(ticker + 1);\n else \n clearInterval(interval);\n }, props.interval);\n }\n\n const reset = () => {\n setTicker(0);\n clearInterval(interval);\n }\n\n return (\n
                      \n {this.state.ticker}\n \n \n
                      \n );\n}\n```", "```jsx\nReactDOM.render(, document.getElementById('root'));\n```" ], "expertise": 1, @@ -263,9 +263,9 @@ { "name": "Toggle.md", "title": "Toggle", - "text": "Renders a toggle component.\n\nInitialize `state.isToggleOn` to `false`, bind the `handleClick` method to the component's context.\nUse an object, `style`, to hold the styles for individual components and their states.\nCreate a method, `handleClick`, which uses `Component.prototype.setState` to change the component's `state.toggleOn`.\nIn the `render()` method, destructure `state` and `style`, create a `\n );\n }\n}\n```", + "```jsx\nfunction Toggle(props) {\n const [isToggleOn, setIsToggleOn] = React.useState(false);\n style = {\n on: {\n backgroundColor: \"green\"\n },\n off: {\n backgroundColor: \"grey\"\n }\n };\n\n return (\n setIsToggleOn(!isToggleOn)}\n style={isToggleOn ? style.on : style.off}\n >\n {isToggleOn ? \"ON\" : \"OFF\"}\n \n );\n}\n```", "```jsx\nReactDOM.render(, document.getElementById('root'));\n```" ], "expertise": 0, @@ -279,9 +279,10 @@ { "name": "Tooltip.md", "title": "Tooltip", - "text": "Renders a tooltip component.\n\nSet the `state` of the component to `show: false` initially, define an object, `style`, to hold the styles for individual components and their states.\nCreate a method, `toggleTooltip`, which uses `this.setState` to change the state's `show` property from `true` to `false` and vice versa.\nBind `showTooltip` and `hideTooltip` to the component's context with the respective values of `true` and `false`.\nIn the `render()` method, compute if the tooltip should be shown or hidden, render the content of the tooltip and bind the `onMouseEnter` and `onMouseLeave` events to `showTooltip` and `hideTooltip` respectively.\n \n", + "text": "Renders a tooltip component.\n\nUse the `React.useState()` hook to create the `show` variable and initialize it to `false`.\nReturn a `
                      ` element that contains the `
                      ` that will be the tooltip and the `children` passed to the component.\nHandle the `onMouseEnter` and `onMouseLeave` methods, by altering the value of the `show` variable.\n \n", "codeBlocks": [ - "```jsx\nclass Tooltip extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n show: false\n };\n this.style = {\n tooltip: {\n position: 'relative',\n backgroundColor: \"rgba(0,0,0,0.7)\",\n color: \"white\",\n visibility: \"hidden\",\n width: \"fit-content\",\n padding: 5,\n borderRadius: 5\n },\n tooltipArrow: {\n position: 'absolute',\n top: '100%',\n left: '50%',\n borderWidth: 5,\n borderStyle: 'solid',\n borderColor: \"rgba(0,0,0,0.7) transparent transparent\",\n },\n visible: {\n visibility: \"visible\"\n },\n };\n this.showTooltip = this.toggleTooltip.bind(this, true);\n this.hideTooltip = this.toggleTooltip.bind(this, false);\n }\n\n toggleTooltip = tooltipState => {\n this.setState({\n show: tooltipState\n });\n };\n\n render() {\n const { children, text, ...rest } = this.props;\n const { show } = this.state;\n const { visible, tooltip, tooltipArrow } = this.style;\n const showTooltip = show ? visible : {};\n return (\n
                      \n
                      \n {text}\n \n
                      \n
                      \n {children}\n
                      \n
                      \n );\n }\n}\n```", + "```css\n.tooltip {\n position: relative;\n background: rgba(0, 0, 0, 0.7);\n color: white;\n visibility: hidden;\n padding: 5px;\n border-radius: 5px;\n}\n.tooltip-arrow {\n position: absolute;\n top: 100%;\n left: 50%;\n border-width: 5px;\n border-style: solid;\n border-color: rgba(0, 0, 0, 0.7) transparent transparent;\n}\n```", + "```jsx\nfunction Tooltip({ children, text, ...rest }) {\n const [show, setShow] = React.useState(false);\n\n return (\n
                      \n
                      \n {text}\n \n
                      \n setShow(true)}\n onMouseLeave={() => setShow(false)}\n >\n {children}\n
                      \n
                      \n );\n}\n```", "```jsx\n ReactDOM.render(\n \n \n ,\n document.getElementById('root')\n );\n```" ], "expertise": 1, diff --git a/snippets/Tooltip.md b/snippets/Tooltip.md index d99d1bca0..cf9e8285d 100644 --- a/snippets/Tooltip.md +++ b/snippets/Tooltip.md @@ -2,67 +2,47 @@ Renders a tooltip component. -Set the `state` of the component to `show: false` initially, define an object, `style`, to hold the styles for individual components and their states. -Create a method, `toggleTooltip`, which uses `this.setState` to change the state's `show` property from `true` to `false` and vice versa. -Bind `showTooltip` and `hideTooltip` to the component's context with the respective values of `true` and `false`. -In the `render()` method, compute if the tooltip should be shown or hidden, render the content of the tooltip and bind the `onMouseEnter` and `onMouseLeave` events to `showTooltip` and `hideTooltip` respectively. +Use the `React.useState()` hook to create the `show` variable and initialize it to `false`. +Return a `
                      ` element that contains the `
                      ` that will be the tooltip and the `children` passed to the component. +Handle the `onMouseEnter` and `onMouseLeave` methods, by altering the value of the `show` variable. +```css +.tooltip { + position: relative; + background: rgba(0, 0, 0, 0.7); + color: white; + visibility: hidden; + padding: 5px; + border-radius: 5px; +} +.tooltip-arrow { + position: absolute; + top: 100%; + left: 50%; + border-width: 5px; + border-style: solid; + border-color: rgba(0, 0, 0, 0.7) transparent transparent; +} +``` ```jsx -class Tooltip extends React.Component { - constructor(props) { - super(props); - this.state = { - show: false - }; - this.style = { - tooltip: { - position: 'relative', - backgroundColor: "rgba(0,0,0,0.7)", - color: "white", - visibility: "hidden", - width: "fit-content", - padding: 5, - borderRadius: 5 - }, - tooltipArrow: { - position: 'absolute', - top: '100%', - left: '50%', - borderWidth: 5, - borderStyle: 'solid', - borderColor: "rgba(0,0,0,0.7) transparent transparent", - }, - visible: { - visibility: "visible" - }, - }; - this.showTooltip = this.toggleTooltip.bind(this, true); - this.hideTooltip = this.toggleTooltip.bind(this, false); - } +function Tooltip({ children, text, ...rest }) { + const [show, setShow] = React.useState(false); - toggleTooltip = tooltipState => { - this.setState({ - show: tooltipState - }); - }; - - render() { - const { children, text, ...rest } = this.props; - const { show } = this.state; - const { visible, tooltip, tooltipArrow } = this.style; - const showTooltip = show ? visible : {}; - return ( -
                      -
                      - {text} - -
                      -
                      - {children} -
                      + return ( +
                      +
                      + {text} +
                      - ); - } +
                      setShow(true)} + onMouseLeave={() => setShow(false)} + > + {children} +
                      +
                      + ); } ``` From bc9bbacad3f625d2eb8e3afd0b4f298a6c7f5096 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Tue, 12 Feb 2019 22:07:13 +0200 Subject: [PATCH 113/133] Update tags --- README.md | 2 +- data/snippet_data.json | 56 ++++++++++++++---------------------- snippets/AutoLink.md | 2 +- snippets/Carousel.md | 2 +- snippets/Collapse.md | 2 +- snippets/DataList.md | 2 +- snippets/DataTable.md | 2 +- snippets/FileDrop.md | 2 +- snippets/Input.md | 2 +- snippets/LimitedTextarea.md | 2 +- snippets/Mailto.md | 2 +- snippets/MappedTable.md | 2 +- snippets/PasswordRevealer.md | 2 +- snippets/Select.md | 2 +- snippets/StarRating.md | 2 +- snippets/Tabs.md | 2 +- snippets/TextArea.md | 2 +- snippets/Ticker.md | 2 +- snippets/Toggle.md | 2 +- snippets/Tooltip.md | 2 +- snippets/TreeView.md | 2 +- 21 files changed, 41 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index 1fa1288bf..d1b03e367 100644 --- a/README.md +++ b/README.md @@ -182,7 +182,7 @@ function MappedTable({ data, propertyNames }) { ``` #### Notes -This component does not work with nested objects and will break if there are nested objects inside any of the properties specified in `propertyNames`.,, +This component does not work with nested objects and will break if there are nested objects inside any of the properties specified in `propertyNames`.,,
                      Examples diff --git a/data/snippet_data.json b/data/snippet_data.json index 3b19501ad..c984e6cdc 100644 --- a/data/snippet_data.json +++ b/data/snippet_data.json @@ -11,7 +11,7 @@ "tags": [ "string", "fragment", - "functional" + "regexp" ], "notes": [] }, @@ -28,7 +28,7 @@ "visual", "children", "state", - "class" + "effect" ], "notes": [] }, @@ -44,8 +44,7 @@ "tags": [ "visual", "children", - "state", - "class" + "state" ], "notes": [] }, @@ -59,8 +58,7 @@ ], "expertise": 0, "tags": [ - "array", - "functional" + "array" ], "notes": [] }, @@ -74,8 +72,7 @@ ], "expertise": 0, "tags": [ - "array", - "functional" + "array" ], "notes": [] }, @@ -93,7 +90,7 @@ "visual", "input", "state", - "class" + "effect" ], "notes": [] }, @@ -107,8 +104,7 @@ ], "expertise": 0, "tags": [ - "input", - "functional" + "input" ], "notes": [] }, @@ -124,7 +120,7 @@ "tags": [ "input", "state", - "class" + "effect" ], "notes": [] }, @@ -138,8 +134,7 @@ ], "expertise": 0, "tags": [ - "visual", - "functional" + "visual" ], "notes": [] }, @@ -154,12 +149,11 @@ "expertise": 1, "tags": [ "array", - "object", - "functional" + "object" ], "notes": [ "This component does not work with nested objects and will break if there are nested objects inside any of the properties specified in `propertyNames`.", - "", + "", "" ] }, @@ -174,8 +168,7 @@ "expertise": 0, "tags": [ "input", - "state", - "class" + "state" ], "notes": [] }, @@ -189,8 +182,7 @@ ], "expertise": 0, "tags": [ - "input", - "functional" + "input" ], "notes": [] }, @@ -207,8 +199,7 @@ "visual", "children", "input", - "state", - "class" + "state" ], "notes": [] }, @@ -224,8 +215,8 @@ "expertise": 1, "tags": [ "visual", - "children", - "class" + "state", + "children" ], "notes": [] }, @@ -239,8 +230,7 @@ ], "expertise": 0, "tags": [ - "input", - "functional" + "input" ], "notes": [] }, @@ -255,8 +245,7 @@ "expertise": 1, "tags": [ "visual", - "state", - "class" + "state" ], "notes": [] }, @@ -271,8 +260,7 @@ "expertise": 0, "tags": [ "visual", - "state", - "class" + "state" ], "notes": [] }, @@ -289,8 +277,7 @@ "tags": [ "visual", "state", - "children", - "class" + "children" ], "notes": [] }, @@ -307,9 +294,8 @@ "tags": [ "object", "visual", - "children", "state", - "class" + "recursion" ], "notes": [] } diff --git a/snippets/AutoLink.md b/snippets/AutoLink.md index 275cfe352..acfc046f2 100644 --- a/snippets/AutoLink.md +++ b/snippets/AutoLink.md @@ -33,6 +33,6 @@ ReactDOM.render( ); ``` - + diff --git a/snippets/Carousel.md b/snippets/Carousel.md index cb25268e3..ccf51ded0 100644 --- a/snippets/Carousel.md +++ b/snippets/Carousel.md @@ -61,7 +61,7 @@ ReactDOM.render( ); ``` - + diff --git a/snippets/Collapse.md b/snippets/Collapse.md index 04dd27182..a1f664798 100644 --- a/snippets/Collapse.md +++ b/snippets/Collapse.md @@ -55,6 +55,6 @@ ReactDOM.render( ); ``` - + diff --git a/snippets/DataList.md b/snippets/DataList.md index 99ee8980b..17cb6ccd3 100644 --- a/snippets/DataList.md +++ b/snippets/DataList.md @@ -21,6 +21,6 @@ ReactDOM.render(, document.getElementById('root')); ReactDOM.render(, document.getElementById('root')); ``` - + diff --git a/snippets/DataTable.md b/snippets/DataTable.md index 93dfce73e..53324bba3 100644 --- a/snippets/DataTable.md +++ b/snippets/DataTable.md @@ -36,6 +36,6 @@ ReactDOM.render( ); ``` - + diff --git a/snippets/FileDrop.md b/snippets/FileDrop.md index 7fefbb103..6f6a0daf9 100644 --- a/snippets/FileDrop.md +++ b/snippets/FileDrop.md @@ -101,6 +101,6 @@ function FileDrop(props) { ReactDOM.render(, document.getElementById('root')); ``` - + diff --git a/snippets/Input.md b/snippets/Input.md index d7734e36a..3278850eb 100644 --- a/snippets/Input.md +++ b/snippets/Input.md @@ -26,6 +26,6 @@ ReactDOM.render( ); ``` - + diff --git a/snippets/LimitedTextarea.md b/snippets/LimitedTextarea.md index 937746e81..e4be1428e 100644 --- a/snippets/LimitedTextarea.md +++ b/snippets/LimitedTextarea.md @@ -41,7 +41,7 @@ ReactDOM.render( document.getElementById('root') ); ``` - + diff --git a/snippets/Mailto.md b/snippets/Mailto.md index df3412efc..5b9b78fe3 100644 --- a/snippets/Mailto.md +++ b/snippets/Mailto.md @@ -24,6 +24,6 @@ ReactDOM.render( ); ``` - + diff --git a/snippets/MappedTable.md b/snippets/MappedTable.md index aada05e50..c97ec1b56 100644 --- a/snippets/MappedTable.md +++ b/snippets/MappedTable.md @@ -46,6 +46,6 @@ ReactDOM.render( #### Notes: * This component does not work with nested objects and will break if there are nested objects inside any of the properties specified in `propertyNames`. - + diff --git a/snippets/PasswordRevealer.md b/snippets/PasswordRevealer.md index 7e27c3e09..b00b0da53 100644 --- a/snippets/PasswordRevealer.md +++ b/snippets/PasswordRevealer.md @@ -26,7 +26,7 @@ function PasswordRevealer({ value }) { ReactDOM.render(, document.getElementById('root')); ``` - + diff --git a/snippets/Select.md b/snippets/Select.md index db4562517..114928c3c 100644 --- a/snippets/Select.md +++ b/snippets/Select.md @@ -33,6 +33,6 @@ ReactDOM.render( ); ``` - + diff --git a/snippets/StarRating.md b/snippets/StarRating.md index 60fe1309b..d1be76cad 100644 --- a/snippets/StarRating.md +++ b/snippets/StarRating.md @@ -53,6 +53,6 @@ ReactDOM.render(, document.getElementById('root')); ReactDOM.render(, document.getElementById('root')); ``` - + diff --git a/snippets/Tabs.md b/snippets/Tabs.md index e1847e625..d5d0268ae 100644 --- a/snippets/Tabs.md +++ b/snippets/Tabs.md @@ -77,6 +77,6 @@ ReactDOM.render( ``` - + diff --git a/snippets/TextArea.md b/snippets/TextArea.md index e67fac536..ac65e5943 100644 --- a/snippets/TextArea.md +++ b/snippets/TextArea.md @@ -27,6 +27,6 @@ ReactDOM.render( ); ``` - + diff --git a/snippets/Ticker.md b/snippets/Ticker.md index 06373cd78..3a6be6902 100644 --- a/snippets/Ticker.md +++ b/snippets/Ticker.md @@ -40,6 +40,6 @@ function Ticker(props) { ReactDOM.render(, document.getElementById('root')); ``` - + \ No newline at end of file diff --git a/snippets/Toggle.md b/snippets/Toggle.md index fc28ef00d..589958903 100644 --- a/snippets/Toggle.md +++ b/snippets/Toggle.md @@ -33,6 +33,6 @@ function Toggle(props) { ReactDOM.render(, document.getElementById('root')); ``` - + diff --git a/snippets/Tooltip.md b/snippets/Tooltip.md index cf9e8285d..39a2448c0 100644 --- a/snippets/Tooltip.md +++ b/snippets/Tooltip.md @@ -55,6 +55,6 @@ function Tooltip({ children, text, ...rest }) { ); ``` - + diff --git a/snippets/TreeView.md b/snippets/TreeView.md index 0a48dd5e2..6e8b7b8aa 100644 --- a/snippets/TreeView.md +++ b/snippets/TreeView.md @@ -123,6 +123,6 @@ let data = { ReactDOM.render(, document.getElementById("root")); ``` - + From 5fecba33a4e962eaaa4aff45c49ae1212f675742 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Tue, 12 Feb 2019 22:09:42 +0200 Subject: [PATCH 114/133] Update snippet template --- snippet-template.md | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/snippet-template.md b/snippet-template.md index d57150e6f..20398538c 100644 --- a/snippet-template.md +++ b/snippet-template.md @@ -6,18 +6,12 @@ Explain briefly how the snippet works. ```jsx function ComponentName(props) { + const [state, setState] = React.useState(null); + React.useEffect(() => { + setState(0); + }); return
                      {props}
                      ; }; -``` - -```jsx -class ComponentName extends React.Component { - constructor(props){} - render(){ - return
                      {props}
                      ; - } -} -``` ```jsx ReactDOM.render(, mountNode); From 77f218a3c22af963e4ca27238d42a8405b5411ca Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Tue, 12 Feb 2019 22:36:09 +0200 Subject: [PATCH 115/133] Update README, snippet-template, add CONTRIBUTING Resolve #36 Resolve #34 --- CONTRIBUTING.md | 81 ++++++++++++++++++++++++++++++++++++ README.md | 25 +++++++++++ snippet-template.md | 3 +- static-parts/README-start.md | 25 +++++++++++ 4 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..e7e82126a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,81 @@ +# Contribution Guidelines + +**30 seconds of React** is a community effort, so feel free to contribute in any way you can. Every contribution helps! + +Here's what you can do to help: + +- Submit [pull requests](https://github.com/30-seconds/30-seconds-of-react/pulls) with snippets that you have created (see below for guidelines). +- [Open issues](https://github.com/30-seconds/30-seconds-of-react/issues/new) for things you want to see added or modified. +- Be part of the discussion by helping out with [existing issues](https://github.com/30-seconds/30-seconds-of-react/issues). +- Fix typos in existing snippets, improve snippet descriptions and explanations or provide better examples. + +### Snippet submission and Pull request guidelines + +- **DO NOT MODIFY THE README.md or index.html FILES!** Make changes to individual snippet files. **Travis CI** will automatically build the `README.md` and `index.html` files when your pull request is merged. +- **Snippet filenames** must correspond to the title of the snippet. For example, if your snippet is titled `### AwesomeComponent` the filename should be `AwesomeComponent.md`. + - Use `TitleCase`, not `camelCase`, `kebab-case` or `snake_case` when naming components. + - Avoid capitalization of words, except if the whole word is capitalized (e.g. `URL` should be capitalized in the filename and the snippet title). +- **Snippet titles** should be the same as the name of the component that is present in the snippet. + - All snippet titles must be prefixed with `###` and be at the very first line of your snippet. + - Snippet titles must be unique (although if you cannot find a better title, just add some placeholder at the end of the filename and title and we will figure it out). + - Follow snippet titles with an empty line. +- **Snippet descriptions** must be short and to the point. Try to explain *what* the snippet does and *how* the snippet works and what Javascript/React features are used. Remember to include what functions you are using and why. + - Follow snippet descriptions with an empty line. +- **Snippet code** must be enclosed inside ` ```jsx ` and ` ``` `. + - If your snippet is accompanied by CSS code, enclose it inside ` ```css ` and ` ``` ` and present it before the JS/JSX code. + - Remember to start your snippet's code on a new line below the opening backticks. + - Use standard function notation to define your component. For example `function MyComponent(props) { ... }`. + - Do not write components using classes, use [React Hooks](https://reactjs.org/docs/hooks-intro.html) instead. + - Please use Javascript [Semi-Standard Style](https://github.com/Flet/semistandard). + - Try to keep your snippets' code short and to the point. Use modern techniques and features. Make sure to test your code before submitting. + - All snippets must be followed by one (more if necessary) test case after the code, in a new block enclosed inside ` ```jsx ` and ` ``` `. The syntax for this is `ReactDOM.render(, document.getElementById("root"));`. Use multiline examples only if necessary. + - Try to make your component name unique, so that it does not conflict with existing snippets. +- Snippets should be as brief as possible, without sacrificing functionality. If your snippet seems longer than most, you can still submit it, and we can help you shorten it or figure out ways to improve it. +- Snippets *should* solve real-world problems, no matter how simple. +- Snippets *should* be abstract enough to be applied to different scenarios. +- You can start creating a new snippet, by using the [snippet template](snippet-template.md) to format your snippets. + +### Additional guidelines and conventions regarding snippets + +- When describing snippets, refer to methods, using their full name. For example, use `Array.prototype.reduce()`, instead of `reduce()`. +- When using React Hooks, refer to the specific hooks with their full names, such as `React.useState()` and `React.useEffect()`. +- When using `React.useState()`, try matching the name of the state variable to the function that sets it. For example, use `[isShown, setIsShown]` instead of `[isShown, setShown]`. +- When using `React.useEffect()`, only return a function if you have to clean up. In that case, name that function `cleanup()`. +- Destructure your component's `props` whenever possible. If any of your props take default parameters, specify their default values in the destructured object. +- If your snippet uses recursion, explain the base cases. +- Always use `function MyComponent(props)` or `function MyComponent({ ... })` for function definitions. +- Use variables only when necessary. Prefer `const` when the values are not altered after assignment, otherwise, use `let`. Avoid using `var`. +- Use `camelCase` for function and variable names, if they consist of more than one word. +- Use `TitleCase` for component names. +- Try to give meaningful names to variables. For example use `letter`, instead of `lt`. Some exceptions to convention are: + - `arr` for arrays (usually as the snippet function's argument). + - `str` for strings. + - `num` or `n` for a numeric value (usually as the snippet function's argument). + - `el` for DOM elements (usually as the snippet function's argument). + - `val` or `v` for value (usually when iterating a list, mapping, sorting etc.). + - `acc` for accumulators in `Array.prototype.reduce()`. + - `(a,b)` for the two values compared when using `Array.prototype.sort()`. + - `i` for indexes. + - `fn` for function arguments. + - `nums` for arrays of numbers. +- Use `()` if your function takes no arguments. +- Use `_` if an argument inside some function (e.g. `Array.prototype.reduce()`) is not used anywhere in your code. +- Specify default parameters for arguments, if necessary. It is preferred to put default parameters last unless you have a pretty good reason not to. +- If your snippet's function takes variadic arguments, use `...args` or `...rest` (although in certain cases, it might be needed to use a different name). +- Always use soft tabs (2 spaces), never hard tabs. +- Omit curly braces (`{` and `}`) whenever possible. +- Always use single quotes for string literals. Use template literals, instead, if necessary. +- When rendering JSX, use double quotes, instead of single quotes. +- Prefer using `Array` methods whenever possible. +- Prefer `Array.prototype.concat()` instead of `Array.prototype.push()` when working with `Array.prototype.reduce()`. +- Use strict equality checking (`===` and `!==` instead of `==` and `!=`), unless you specifically have reason not to. +- Prefer using the ternary operator (`condition ? trueResult : falseResult`) instead of `if else` statements whenever possible. +- Avoid nesting ternary operators (but you can do it if you feel like you should). +- You should define multiple variables (e.g. `const x = 0, y = 0`) on the same line whenever possible. +- Do not use trailing or leading underscores in variable names. +- Use dot notation (`object.property`) for object properties, when possible. Use bracket notation (`object[variable]`) when accessing object properties using a variable. +- Use arrow functions as much as possible, except when you can't. +- Use semicolons whenever necessary. +- Leave a single space after a comma (`,`) character. +- Try to strike a balance between readability, brevity, and performance. +- Never use `eval()`. Your snippet will be disqualified immediately. \ No newline at end of file diff --git a/README.md b/README.md index d1b03e367..7ba36168c 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,31 @@ > Curated collection of useful React snippets that you can understand in 30 seconds or less. +* Use Ctrl + F or command + F to search for a snippet. +* Contributions welcome, please read the [contribution guide](CONTRIBUTING.md). +* Snippets are written in React 16.8+, using hooks. + +### Prerequisites + +To import a snippet into your project, you must import `React` and copy-paste the component's JavaScript code like this: +```js +import React from 'react'; + +function MyComponent(props) { + /* ... */ +} +``` + +If there is any CSS related to your component, copy-paste it to a new file with the same name and the appropriate extension, then import it like this: +```js +import './MyComponent.css'; +``` + +To render your component, make sure there is a node with and id of `"root"` present in your element (preferrably a `
                      `) and that you have imported `ReactDOM`, like this: +```js +import ReactDOM from 'react-dom'; +``` + #### Related projects * [30 Seconds of Code](https://30secondsofcode.org) diff --git a/snippet-template.md b/snippet-template.md index 20398538c..4acb54fcc 100644 --- a/snippet-template.md +++ b/snippet-template.md @@ -12,9 +12,10 @@ function ComponentName(props) { }); return
                      {props}
                      ; }; +``` ```jsx -ReactDOM.render(, mountNode); +ReactDOM.render(, document.getElementById("root")); ``` diff --git a/static-parts/README-start.md b/static-parts/README-start.md index c6bcd886d..4f524a7bb 100644 --- a/static-parts/README-start.md +++ b/static-parts/README-start.md @@ -4,6 +4,31 @@ > Curated collection of useful React snippets that you can understand in 30 seconds or less. +* Use Ctrl + F or command + F to search for a snippet. +* Contributions welcome, please read the [contribution guide](CONTRIBUTING.md). +* Snippets are written in React 16.8+, using hooks. + +### Prerequisites + +To import a snippet into your project, you must import `React` and copy-paste the component's JavaScript code like this: +```js +import React from 'react'; + +function MyComponent(props) { + /* ... */ +} +``` + +If there is any CSS related to your component, copy-paste it to a new file with the same name and the appropriate extension, then import it like this: +```js +import './MyComponent.css'; +``` + +To render your component, make sure there is a node with and id of `"root"` present in your element (preferrably a `
                      `) and that you have imported `ReactDOM`, like this: +```js +import ReactDOM from 'react-dom'; +``` + #### Related projects * [30 Seconds of Code](https://30secondsofcode.org) From 81f25f378ab9e6fe82c3f156315f6dad0fc665b3 Mon Sep 17 00:00:00 2001 From: raurir Date: Mon, 18 Feb 2019 15:35:57 +1100 Subject: [PATCH 116/133] fix vairable --- data/snippet_data.json | 2 +- snippets/PasswordRevealer.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/snippet_data.json b/data/snippet_data.json index c984e6cdc..c86fb17ac 100644 --- a/data/snippet_data.json +++ b/data/snippet_data.json @@ -160,7 +160,7 @@ { "name": "PasswordRevealer.md", "title": "PasswordRevealer", - "text": "Renders a password input field with a reveal button.\n\nUse the `React.useState()` hook to create the `shown` state vairable and set its value to `false`.\nUse a`
                      ` to wrap both the`` and the `\n
                      \n );\n}\n```", "```jsx\nReactDOM.render(, document.getElementById('root'));\n```" diff --git a/snippets/PasswordRevealer.md b/snippets/PasswordRevealer.md index b00b0da53..6f6be083d 100644 --- a/snippets/PasswordRevealer.md +++ b/snippets/PasswordRevealer.md @@ -2,7 +2,7 @@ Renders a password input field with a reveal button. -Use the `React.useState()` hook to create the `shown` state vairable and set its value to `false`. +Use the `React.useState()` hook to create the `shown` state variable and set its value to `false`. Use a`
                      ` to wrap both the`` and the `