Check my daily-scrum library: https://lesstalkmorecode.github.io/react-daily-scrum/
NPM: https://www.npmjs.com/package/@lesstalkmorecode/react-daily-scrum
Github repository: https://github.com/lesstalkmorecode/react-daily-scrum
Check my daily-scrum library: https://lesstalkmorecode.github.io/react-daily-scrum/
NPM: https://www.npmjs.com/package/@lesstalkmorecode/react-daily-scrum
Github repository: https://github.com/lesstalkmorecode/react-daily-scrum
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"> <path fill="white" stroke="black" stroke-width="4" class="path" d="M 10 10 H 90 V 90 H 10 L 10 10"/> <!-- Points --> <circle cx="10" cy="10" r="2" fill="red"/> <circle cx="90" cy="90" r="2" fill="red"/> <circle cx="90" cy="10" r="2" fill="red"/> <circle cx="10" cy="90" r="2" fill="red"/> </svg>
.path { stroke-dasharray: 320; stroke-dashoffset: 320; animation: dash 8s linear infinite; } @keyframes dash { from { stroke-dashoffset: 320; } to { stroke-dashoffset: 0; } }
const ingredients = { salad: 2, tomato: 1, cheese: 3, meat: 2 } const transformedIngredients = Object.keys(ingredients) .map(iKey => { return [...Array(ingredients[iKey])].map((_, i) => { return iKey ; }); }); console.log(transformedIngredients.toString());
{ test: cssRegex, exclude: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, sourceMap: isEnvProduction && shouldUseSourceMap, }), sideEffects: true, },
{ test: cssRegex, exclude: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, modules: true, localIdentName: "[name]__[local]___[hash:base64:5]", sourceMap: isEnvProduction && shouldUseSourceMap, }), sideEffects: true, },
./src/index.css (./node_modules/css-loader/dist/cjs.js??ref--6-oneOf-3-1!./node_modules/postcss-loader/src??postcss!./src/index.css) ValidationError: Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'localIdentName'. These properties are valid: object { url?, import?, modules?, sourceMap?, importLoaders?, localsConvention?, onlyLocals?, esModule? }
{ test: cssRegex, exclude: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, modules: { localIdentName: "[name]__[local]___[hash:base64:5]", }, sourceMap: isEnvProduction && shouldUseSourceMap, }), sideEffects: true, },
import React from 'react'; import { LightTooltip } from '../tooltip/lightTooltip'; interface IOwnProps { messageToBeCopied: string | null; } export default class CopyToClipboard extends React.Component<IOwnProps> { render() { const { messageToBeCopied, children } = this.props; let isCopySuccess = false; if (messageToBeCopied) { try { const textField = document.createElement('textarea'); textField.innerText = messageToBeCopied; document.body.appendChild(textField); textField.select(); isCopySuccess = document.execCommand('copy'); textField.remove(); } catch (e) { isCopySuccess = false; } return ( <LightTooltip leaveDelay={1} leaveTouchDelay={1} title={isCopySuccess === false ? 'Failed to copy.' : 'Copied.'} > {children as React.ReactElement} </LightTooltip> ); } return <>{children}</>; } }
import { withStyles, Theme } from '@material-ui/core/styles'; import Tooltip from '@material-ui/core/Tooltip'; export const LightTooltip = withStyles((theme: Theme) => ({ tooltip: { backgroundColor: theme.palette.common.white, color: 'rgba(0, 0, 0, 0.87)', boxShadow: theme.shadows[1], fontSize: 12, fontFamily: 'Rubik-Regular', }, }))(Tooltip);
import React from 'react'; import CopyToClipboard from '../copyToClipboard/copyToClipboard'; interface IState { clipboardMessage: string | null; } class Example extends React.Component<null, IState> { constructor(props) { super(props); this.state = { clipboardMessage: null, }; } setClipboardMessage() { const message = 'Message for copy to clipboard'; this.setState({ clipboardMessage: message, }); } render() { return ( <CopyToClipboard messageToBeCopied={this.state.clipboardMessage}> <a onClick={() => this.setClipboardMessage()}>Copy</a> </CopyToClipboard> ); } } export default Example;
@font-face { font-family: 'Rubik-Regular'; src: local('Rubik'), url(../static/font/Rubik/Rubik-Regular.ttf) format('truetype'); } @font-face { font-family: 'Rubik-Medium'; src: local('Rubik'), url(../static/font/Rubik/Rubik-Medium.ttf) format('truetype'); }
import { currencyMap } from './currencyMap'; export default function getSymbolFromCurrencyCode(currencyCode : string) { const code = currencyCode && currencyCode.toUpperCase(); if (!currencyMap.hasOwnProperty(code)) { return currencyCode; } return currencyMap[code]; }
export const currencyMap = { 'AED': 'د.إ', 'AFN': '؋', 'ALL': 'L', 'AMD': '֏', 'ANG': 'ƒ', 'AOA': 'Kz', 'ARS': '$', 'AUD': '$', 'AWG': 'ƒ', 'AZN': '₼', 'BAM': 'KM', 'BBD': '$', 'BDT': '৳', 'BGN': 'лв', 'BHD': '.د.ب', 'BIF': 'FBu', 'BMD': '$', 'BND': '$', 'BOB': '$b', 'BRL': 'R$', 'BSD': '$', 'BTC': '฿', 'BTN': 'Nu.', 'BWP': 'P', 'BYR': 'Br', 'BYN': 'Br', 'BZD': 'BZ$', 'CAD': '$', 'CDF': 'FC', 'CHF': 'CHF', 'CLP': '$', 'CNY': '¥', 'COP': '$', 'CRC': '₡', 'CUC': '$', 'CUP': '₱', 'CVE': '$', 'CZK': 'Kč', 'DJF': 'Fdj', 'DKK': 'kr', 'DOP': 'RD$', 'DZD': 'دج', 'EEK': 'kr', 'EGP': '£', 'ERN': 'Nfk', 'ETB': 'Br', 'ETH': 'Ξ', 'EUR': '€', 'FJD': '$', 'FKP': '£', 'GBP': '£', 'GEL': '₾', 'GGP': '£', 'GHC': '₵', 'GHS': 'GH₵', 'GIP': '£', 'GMD': 'D', 'GNF': 'FG', 'GTQ': 'Q', 'GYD': '$', 'HKD': '$', 'HNL': 'L', 'HRK': 'kn', 'HTG': 'G', 'HUF': 'Ft', 'IDR': 'Rp', 'ILS': '₪', 'IMP': '£', 'INR': '₹', 'IQD': 'ع.د', 'IRR': '﷼', 'ISK': 'kr', 'JEP': '£', 'JMD': 'J$', 'JOD': 'JD', 'JPY': '¥', 'KES': 'KSh', 'KGS': 'лв', 'KHR': '៛', 'KMF': 'CF', 'KPW': '₩', 'KRW': '₩', 'KWD': 'KD', 'KYD': '$', 'KZT': 'лв', 'LAK': '₭', 'LBP': '£', 'LKR': '₨', 'LRD': '$', 'LSL': 'M', 'LTC': 'Ł', 'LTL': 'Lt', 'LVL': 'Ls', 'LYD': 'LD', 'MAD': 'MAD', 'MDL': 'lei', 'MGA': 'Ar', 'MKD': 'ден', 'MMK': 'K', 'MNT': '₮', 'MOP': 'MOP$', 'MRO': 'UM', 'MRU': 'UM', 'MUR': '₨', 'MVR': 'Rf', 'MWK': 'MK', 'MXN': '$', 'MYR': 'RM', 'MZN': 'MT', 'NAD': '$', 'NGN': '₦', 'NIO': 'C$', 'NOK': 'kr', 'NPR': '₨', 'NZD': '$', 'OMR': '﷼', 'PAB': 'B/.', 'PEN': 'S/.', 'PGK': 'K', 'PHP': '₱', 'PKR': '₨', 'PLN': 'zł', 'PYG': 'Gs', 'QAR': '﷼', 'RMB': '¥', 'RON': 'lei', 'RSD': 'Дин.', 'RUB': '₽', 'RWF': 'R₣', 'SAR': '﷼', 'SBD': '$', 'SCR': '₨', 'SDG': 'ج.س.', 'SEK': 'kr', 'SGD': '$', 'SHP': '£', 'SLL': 'Le', 'SOS': 'S', 'SRD': '$', 'SSP': '£', 'STD': 'Db', 'STN': 'Db', 'SVC': '$', 'SYP': '£', 'SZL': 'E', 'THB': '฿', 'TJS': 'SM', 'TMT': 'T', 'TND': 'د.ت', 'TOP': 'T$', 'TRL': '₤', 'TRY': '₺', 'TL': '₺', 'TTD': 'TT$', 'TVD': '$', 'TWD': 'NT$', 'TZS': 'TSh', 'UAH': '₴', 'UGX': 'USh', 'USD': '$', 'UYU': '$U', 'UZS': 'лв', 'VEF': 'Bs', 'VND': '₫', 'VUV': 'VT', 'WST': 'WS$', 'XAF': 'FCFA', 'XBT': 'Ƀ', 'XCD': '$', 'XOF': 'CFA', 'XPF': '₣', 'YER': '﷼', 'ZAR': 'R', 'ZWD': 'Z$', }
import getSymbolFromCurrencyCode from '../commons/currencySymbol/currencySymbolMap'; ... getSymbolFromCurrencyCode('TRY'); ...
import Example1 from '../../components/……....'; import Example2 from '../../components/…....'; interface ExampleInfos { name: any; param1: string; param2?: boolean; } interface ExampleLayout { [key:string]: ExampleInfos; } export const exampleMap: ExampleLayout = { example1: { name: Example1, param1: 'medium', }, example2: { name: Example2, param1: 'medium', param2: false, }, }
import { exampleMap } from './exampleMap'; ... const myMap= exampleMap['example1']; const myComponent = myMap && myMap.name; ...
import React from 'react'; import Loading from '../../commons/loading/loading'; import ErrorBoundary from '../../commons/error/errorBoundary'; import EmptyHint from '../../commons/empty/emptyHint'; export interface WithRenderCtrlProp { isDataReady: boolean; isLoading: boolean; customEmptyMessage?: string | null; errorMessage: string | null; } const withRenderCtrl = <P extends object>(Component: React.ComponentType<P>) => class WithLoading extends React.Component<P & WithRenderCtrlProp> { render() { const { isDataReady, isLoading, errorMessage, customEmptyMessage, ...props } = this.props; if (isDataReady) return <Component {...props as P} />; if (errorMessage) return <ErrorBoundary errorMessage={errorMessage}/>; if (isLoading) return <Loading />; return <EmptyHint customMessage={customEmptyMessage}/>; } } export default withRenderCtrl;
import React from 'react'; interface IProps { customMessage?: string | null; } // custom message is not necessary, if it is not given then a common message will be shown const EmptyHint = ({ customMessage = null }: IProps) => ( <div> <div>{customMessage ? customMessage : 'common message for no data found '}</div> </div> ); export default EmptyHint;
import React from 'react'; interface IState { error: any; info: any; } interface IProps { errorMessage: any | null; } // also it has componentDidCatch method class ErrorBoundary extends React.Component<IProps, IState> { constructor(props) { super(props); this.state = { error: null, info: null, }; } componentDidCatch(error, info) { this.setState({ error: error, info: info, }); } render() { if (this.state.error || this.props.errorMessage) { return ( <div> <h1>...... :( </h1> {this.state.error && this.state.error.toString()} {this.props.errorMessage && this.props.errorMessage.toString()} </div> ); } return this.props.children; } } export default ErrorBoundary;
import React from 'react'; const Loading = () => ( <div>Wait for loading....</div> ); export default Loading;
import React from 'react'; // define props, states vs. ... class Example extends React.PureComponent { // ... // when you calling your api, you should set loading, error props. async componentDidMount() { const { setMyData, setLoader, setError } = this.props; setLoader(true); const myData = await getMyData() .catch((error) => { setError(error); }); setLoader(false); setMyData(myData); } render(){ const { myData, isLoading, error } = this.props; // usually your main component gets data, sets error & loading cases. It has callback methods vs. // The component named with Body includes html, css stuffs. // and you should define your body component as following. (with wraping our HOC named as withRenderCtrl) // export default withRenderCtrl(ExampleBody); return( <ExampleBody myData={myData} isLoading={isLoading} errorMessage={error} isDataReady={myData && !myData.isEmpty()} customEmptyMessage="my custom empty data >> this props is not necessary" /> ); } } export default Example;
import axios from 'axios'; import I from 'immutable'; const apiURL = axios.create({ baseURL: process.env.MY_API_URL, // example: localhost:8080/ }); const request = function (options) { const onSuccess = function (response) { const data = response.data; if (data.myErrorFromApiAsSuccessStatus) { return myStructureError(data.myErrorFromApiAsSuccessStatus); } return I.fromJS({ data }); }; const onError = function (error) { if (error.response && error.response.data && error.response.data.myErrorFromApiAsSuccessStatus) { return myStructureError(error.response.data.myErrorFromApiAsSuccessStatus); } console.log(` url: ${options.url} message: ${error.message} stackTrace: ${error.stack} `); return Promise.reject(error.message); }; function myStructureError(myErrorFromApiAsSuccessStatus) { const error = (` url: ${options.url} message: ${myErrorFromApiAsSuccessStatus.message} `); console.log(error); return Promise.reject(error); } return apiURL(options) .then(onSuccess) .catch(onError); }; export default request;
import request from '../request'; export const getMyData = async(mydata: string) => { return request({ url: '/my-data', method: 'POST', data: { mydata : mydata, }, }); };