From 6c5ca10642c30ecda40ef14d5b6a9431d86caa2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20H=C3=B8egh?= Date: Wed, 24 Mar 2021 23:20:52 +0100 Subject: [PATCH] fix: fix #autocomplete content support for React Elements --- .../uilib/components/autocomplete/Examples.js | 12 ++- .../components/autocomplete/properties.md | 16 +++- .../stories/components/Autocomplete.js | 19 ++++- .../components/autocomplete/Autocomplete.js | 84 +++++++++++-------- .../components/number-format/NumberFormat.js | 2 +- 5 files changed, 91 insertions(+), 42 deletions(-) diff --git a/packages/dnb-design-system-portal/src/docs/uilib/components/autocomplete/Examples.js b/packages/dnb-design-system-portal/src/docs/uilib/components/autocomplete/Examples.js index 8e5438af08f..8c26364e3d8 100644 --- a/packages/dnb-design-system-portal/src/docs/uilib/components/autocomplete/Examples.js +++ b/packages/dnb-design-system-portal/src/docs/uilib/components/autocomplete/Examples.js @@ -5,6 +5,7 @@ import React from 'react' import ComponentBox from 'Src/shared/tags/ComponentBox' +import { Autocomplete, IconPrimary } from '@dnb/eufemia/src/components' import styled from '@emotion/styled' const Wrapper = styled.div` @@ -27,6 +28,7 @@ export const AutocompleteDefaultExample = () => ( ` } @@ -313,7 +315,15 @@ export const AutocompleteOpened = () => { } const topMovies = [ - { content: 'The Shawshank Redemption', year: 1994 }, + { + content: ( + + + The Shawshank Redemption + + ), + year: 1994 + }, { content: 'The Godfather', year: 1972 }, { content: 'The Godfather: Part II', year: 1974 }, { content: 'The Dark Knight', year: 2008 }, diff --git a/packages/dnb-design-system-portal/src/docs/uilib/components/autocomplete/properties.md b/packages/dnb-design-system-portal/src/docs/uilib/components/autocomplete/properties.md index e347f937605..015c2ded63d 100644 --- a/packages/dnb-design-system-portal/src/docs/uilib/components/autocomplete/properties.md +++ b/packages/dnb-design-system-portal/src/docs/uilib/components/autocomplete/properties.md @@ -65,19 +65,29 @@ const data = [ // (optional) is show insted of "content", once selected selected_value: 'Item 1 Value', - // Item content as a string or array + // Item content as a string, array or React Element content: 'Item 1 Content' }, // more items ... { selected_key: 'key_1', - content: ['Item 2 Value', 'Item 2 Content'] + content: ( + <> + + Searchable content + + ) }, { selected_key: 'key_2', selected_value: 'Item 3 Value', - content: ['Item 3 Content A', 'Item 3 Content B'] + content: ( + + + Searchable content + + ) }, { selected_key: 'key_3', diff --git a/packages/dnb-eufemia-sandbox/stories/components/Autocomplete.js b/packages/dnb-eufemia-sandbox/stories/components/Autocomplete.js index 6b656a73532..ec75666f76d 100644 --- a/packages/dnb-eufemia-sandbox/stories/components/Autocomplete.js +++ b/packages/dnb-eufemia-sandbox/stories/components/Autocomplete.js @@ -10,6 +10,7 @@ import styled from '@emotion/styled' import { Autocomplete, NumberFormat, + IconPrimary, Button } from '@dnb/eufemia/src/components' import { Anchor } from '@dnb/eufemia/src/elements' @@ -481,8 +482,22 @@ const autocompleteDataScrollable = [ ] const topMovies = [ - { content: 'The Shawshank Redemption', year: 1994 }, - { content: 'The Godfather the godfather The Godfather', year: 1972 }, + { + content: ( + <> + + The Shawshank Redemption + + + + ), + year: 1994 + }, + { content: 'The Godfather', year: 1972 }, { content: 'The Godfather: Part II', year: 1974 }, { content: 'The Dark Knight', year: 2008 }, { content: '12 Angry Men', year: 1957 }, diff --git a/packages/dnb-eufemia/src/components/autocomplete/Autocomplete.js b/packages/dnb-eufemia/src/components/autocomplete/Autocomplete.js index e9d21ee33ec..bfc16ca85e8 100644 --- a/packages/dnb-eufemia/src/components/autocomplete/Autocomplete.js +++ b/packages/dnb-eufemia/src/components/autocomplete/Autocomplete.js @@ -1145,31 +1145,32 @@ class AutocompleteInstance extends React.PureComponent { return this._rC[cacheHash] } - let Component = null + const isComponent = + typeof children !== 'string' && React.isValidElement(children) - // it can be an object, React element or an array - if (typeof children !== 'string') { - if (!Array.isArray(children)) { - children = [children] - } - - // keep the original for later - Component = children - - // make string out of it - children = children.map((child) => convertJsxToString(child)) + if (!Array.isArray(children)) { + children = [children] // for a while we had split this into separate words children.split(' ') but this is not needed anymore } - if (typeof children === 'string') { - children = [children] // for a while we had split this into seperate words children.split(' ') but this is not needed anymore - } + // make string out of it + children = children.map((component) => ({ + component, + segment: convertJsxToString(component) + })) - children = children - .map((segment, sIndex) => { + children = children.map( + ( + { component, segment }, + idx + // , arr + ) => { + // console.log('segment', idx, segment) if (skipHighlight || this.state.skipHighlight) { return segment } + const origSegment = segment + listOfFoundWords.forEach(({ word, wordIndex }) => { if (wordIndex > this.inWordIndex) { segment = segment.replace( @@ -1184,6 +1185,8 @@ class AutocompleteInstance extends React.PureComponent { } }) + let result = segment + if (segment.includes(S)) { // to make sure we don't have several in a row const __html = segment @@ -1193,35 +1196,46 @@ class AutocompleteInstance extends React.PureComponent { .replace(new RegExp(S, 'g'), tagS) .replace(new RegExp(E, 'g'), tagE) - return ( + result = ( ) + } else { + result = segment } - return segment - }) - .map((c, i, a) => (i < a.length - 1 ? [c, ' '] : c)) // add back the skiped spaces - - if (Component) { - children = Array.isArray(Component) - ? Component.map((Comp, i) => - React.cloneElement( - Comp, - { key: 'clone' + cacheHash + i }, - children[i] + // If we get a component, replace the one we use as the string comparison + // This way we can still have an icon before or after + if (isComponent ) { + if(Array.isArray(component.props.children)){ + + result = component.props.children.map((Comp) => + Comp === origSegment || + (Comp.props && Comp.props.children === origSegment) + ? result + : Comp ) - ) - : React.cloneElement( - Component, + } + + result = React.cloneElement( + component, { key: 'clone' + cacheHash }, - children + result ) - } + } + + // add back the skipped spaces + // if(idx < arr.length - 1){ + // result = [result, ' '] + // } + + return result + } + ) return (this._rC[cacheHash] = children) } diff --git a/packages/dnb-eufemia/src/components/number-format/NumberFormat.js b/packages/dnb-eufemia/src/components/number-format/NumberFormat.js index 422f437d171..490da685d1d 100644 --- a/packages/dnb-eufemia/src/components/number-format/NumberFormat.js +++ b/packages/dnb-eufemia/src/components/number-format/NumberFormat.js @@ -226,7 +226,7 @@ export default class NumberFormat extends React.PureComponent { let link = _link let value = _value - if (children !== null) { + if (value === null && children !== null) { value = children }