├── .gitattributes ├── 9781484270516.jpg ├── Contributing.md ├── LICENSE.txt ├── README.md ├── ch01 └── react-d3-hello-world │ ├── README.md │ ├── README_CRA.md │ ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ └── README │ ├── components │ │ ├── HelloD3 │ │ │ ├── HelloD3.scss │ │ │ ├── HelloD3.test.tsx │ │ │ └── HelloD3.tsx │ │ ├── HelloD3Class │ │ │ ├── HelloD3Class.scss │ │ │ ├── HelloD3Class.test.tsx │ │ │ └── HelloD3Class.tsx │ │ └── README │ ├── features │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ └── README │ ├── logo.svg │ ├── model │ │ └── README │ ├── pages │ │ └── README │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ └── README │ │ └── selectors │ │ │ └── README │ ├── redux │ │ └── store.ts │ ├── serviceWorker.ts │ └── setupTests.ts │ ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ ├── d3 │ │ └── component.tsx │ ├── d3class │ │ └── component.tsx │ ├── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx │ └── recoil │ │ ├── component.tsx │ │ └── test.tsx │ ├── tsconfig.json │ └── yarn.lock ├── ch02 ├── README.md ├── README_CRA.md ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js ├── generate-react-cli.json ├── jest-puppeteer.config.js ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── .DS_Store │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ └── README │ ├── components │ │ ├── CircleWithEvents │ │ │ ├── CircleWithD3Events.tsx │ │ │ ├── CircleWithEvents.scss │ │ │ └── CircleWithEvents.tsx │ │ ├── HelloD3 │ │ │ ├── HelloD3.scss │ │ │ ├── HelloD3.test.tsx │ │ │ └── HelloD3.tsx │ │ ├── HelloD3Class │ │ │ ├── HelloD3Class.scss │ │ │ ├── HelloD3Class.test.tsx │ │ │ └── HelloD3Class.tsx │ │ ├── HelloD3Data │ │ │ ├── HelloD3Data.scss │ │ │ ├── HelloD3Data.test.tsx │ │ │ └── HelloD3Data.tsx │ │ ├── HelloJSXData │ │ │ ├── HelloJSXData.scss │ │ │ ├── HelloJSXData.test.tsx │ │ │ └── HelloJSXData.tsx │ │ ├── HelloSVG │ │ │ ├── HelloSVG.scss │ │ │ ├── HelloSVG.test.tsx │ │ │ └── HelloSVG.tsx │ │ ├── JSXCanvas │ │ │ ├── JSXCanvas.scss │ │ │ ├── JSXCanvas.test.tsx │ │ │ └── JSXCanvas.tsx │ │ ├── PulsatingCircle │ │ │ ├── PulsatingCircle.tsx │ │ │ └── PulsatingCircleD3.tsx │ │ ├── README │ │ └── SimpleChart │ │ │ ├── SimpleChart.scss │ │ │ ├── SimpleChart.test.tsx │ │ │ └── SimpleChart.tsx │ ├── features │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ └── README │ ├── logo.svg │ ├── model │ │ └── README │ ├── pages │ │ └── README │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ └── README │ │ └── selectors │ │ │ └── README │ ├── redux │ │ └── store.ts │ ├── serviceWorker.ts │ └── setupTests.ts ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ ├── d3 │ │ └── component.tsx │ ├── d3class │ │ └── component.tsx │ ├── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx │ └── recoil │ │ ├── component.tsx │ │ └── test.tsx ├── tsconfig.json └── yarn.lock ├── ch03 ├── README.md ├── README_CRA.md ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js ├── generate-react-cli.json ├── jest-puppeteer.config.js ├── package.json ├── public │ ├── data │ │ ├── area.csv │ │ ├── bar.csv │ │ ├── line.csv │ │ ├── pie.csv │ │ └── scatter.csv │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ └── README │ ├── components │ │ ├── BasicAreaChart │ │ │ ├── BasicAreaChart.scss │ │ │ ├── BasicAreaChart.test.tsx │ │ │ ├── BasicAreaChart.tsx │ │ │ └── types.ts │ │ ├── BasicBarChart │ │ │ ├── BasicBarChart.scss │ │ │ ├── BasicBarChart.test.tsx │ │ │ ├── BasicBarChart.tsx │ │ │ └── types.ts │ │ ├── BasicDonutChart │ │ │ ├── BasicDonutChart.tsx │ │ │ └── types.ts │ │ ├── BasicLineChart │ │ │ ├── BasicLineChart.scss │ │ │ ├── BasicLineChart.test.tsx │ │ │ ├── BasicLineChart.tsx │ │ │ └── types.ts │ │ ├── BasicPieChart │ │ │ ├── BasicPieChart.scss │ │ │ ├── BasicPieChart.test.tsx │ │ │ ├── BasicPieChart.tsx │ │ │ └── types.ts │ │ ├── BasicScatterChart │ │ │ ├── BasicScatterChart.scss │ │ │ ├── BasicScatterChart.test.tsx │ │ │ ├── BasicScatterChart.tsx │ │ │ └── types.ts │ │ └── README │ ├── features │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ └── README │ ├── logo.svg │ ├── model │ │ └── README │ ├── pages │ │ └── README │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ └── README │ │ └── selectors │ │ │ └── README │ ├── redux │ │ └── store.ts │ ├── serviceWorker.ts │ └── setupTests.ts ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ ├── d3 │ │ └── component.tsx │ ├── d3class │ │ └── component.tsx │ ├── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx │ └── recoil │ │ ├── component.tsx │ │ └── test.tsx └── tsconfig.json ├── ch04-05 └── histogram-d3-ts │ ├── .env │ ├── .eslintignore │ ├── .eslintrc │ ├── .gitignore │ ├── .prettierrc │ ├── README.md │ ├── README_CRA.md │ ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ ├── data │ │ ├── README │ │ └── historicalPrice.csv │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ └── README │ ├── components │ │ ├── Histogram │ │ │ ├── Histogram.scss │ │ │ ├── Histogram.test.tsx │ │ │ ├── Histogram.tsx │ │ │ └── types.ts │ │ ├── PriceTableList │ │ │ ├── PriceTableList.scss │ │ │ ├── PriceTableList.test.tsx │ │ │ ├── PriceTableList.tsx │ │ │ └── types.ts │ │ └── README │ ├── features │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ └── README │ ├── logo.svg │ ├── model │ │ ├── README │ │ ├── historicalPriceObject.ts │ │ └── index.ts │ ├── pages │ │ └── README │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ ├── README │ │ │ └── historicalPriceAtoms.ts │ │ └── selectors │ │ │ ├── README │ │ │ └── historicalPriceSelectors.ts │ ├── redux │ │ └── store.ts │ ├── serviceWorker.ts │ ├── setupTests.ts │ └── widgets │ │ ├── HistogramWidget │ │ ├── HistogramWidget.scss │ │ ├── HistogramWidget.test.tsx │ │ └── HistogramWidget.tsx │ │ └── README │ ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ ├── d3 │ │ └── component.tsx │ ├── d3class │ │ └── component.tsx │ ├── materialui │ │ └── materialui.tsx │ ├── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx │ ├── recoil │ │ ├── component.tsx │ │ └── test.tsx │ ├── templates │ │ ├── component │ │ │ ├── component.js │ │ │ ├── component.tsx │ │ │ ├── style.scss │ │ │ ├── test.js │ │ │ └── test.tsx │ │ ├── d3 │ │ │ └── component.tsx │ │ ├── d3class │ │ │ └── component.tsx │ │ ├── materialui │ │ │ └── materialui.tsx │ │ ├── page │ │ │ ├── component.tsx │ │ │ ├── style.scss │ │ │ └── test.tsx │ │ ├── recoil │ │ │ ├── component.tsx │ │ │ └── test.tsx │ │ └── widget │ │ │ └── Widget.tsx │ └── widget │ │ └── Widget.tsx │ └── tsconfig.json ├── ch06 └── world-map-chart │ ├── README.md │ ├── README_CRA.md │ ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ ├── data │ │ ├── coordinates.csv │ │ └── world-110m.json │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ └── README │ ├── components │ │ ├── README │ │ └── WorldMap │ │ │ ├── RotatingRoundWorldMap.tsx │ │ │ ├── RotatingRoundWorldMapWithCoordinates.tsx │ │ │ ├── RoundWorldMap.tsx │ │ │ ├── WorldMap.scss │ │ │ ├── WorldMap.test.tsx │ │ │ ├── WorldMap.tsx │ │ │ ├── WorldMapAtlas.tsx │ │ │ └── types.tsx │ ├── features │ │ └── README │ ├── hooks │ │ ├── AnimationFrame.tsx │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ └── README │ ├── logo.svg │ ├── model │ │ └── README │ ├── pages │ │ └── README │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ └── README │ │ └── selectors │ │ │ └── README │ ├── redux │ │ └── store.ts │ ├── serviceWorker.ts │ ├── setupTests.ts │ └── widgets │ │ └── README │ ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ ├── d3 │ │ └── component.tsx │ ├── d3class │ │ └── component.tsx │ ├── materialui │ │ └── materialui.tsx │ ├── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx │ ├── recoil │ │ ├── component.tsx │ │ └── test.tsx │ └── widget │ │ └── Widget.tsx │ ├── tsconfig.json │ └── yarn.lock ├── ch07 └── world-map-widget │ ├── README.md │ ├── README_CRA.md │ ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ ├── clients-logo │ │ ├── Allocadia.png │ │ ├── CiaoBellaGelato.png │ │ ├── EsteeLauder.png │ │ ├── KickApps.png │ │ ├── MTV.png │ │ ├── MotionBox.png │ │ ├── NBC.png │ │ ├── README │ │ ├── RockSoul.png │ │ ├── UPMC.png │ │ ├── Vitaminwater.png │ │ ├── WeightWatchers.png │ │ ├── att.png │ │ ├── chatand.png │ │ ├── digitallyspeaking.png │ │ ├── friesens.png │ │ ├── gantto.png │ │ ├── gdconf.png │ │ ├── hbo.png │ │ ├── iheart.png │ │ ├── monbijouparis.png │ │ ├── ritani.png │ │ └── surgiview.png │ ├── data │ │ ├── client-list.csv │ │ └── world-110m.json │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ ├── README │ │ └── about │ │ │ └── EliEladElrom.jpg │ ├── components │ │ ├── ClientList │ │ │ ├── ClientList.scss │ │ │ ├── ClientList.test.tsx │ │ │ └── ClientList.tsx │ │ ├── ClientListDetail │ │ │ ├── ClientListDetail.scss │ │ │ ├── ClientListDetail.test.tsx │ │ │ └── ClientListDetail.tsx │ │ ├── PulsatingCircle │ │ │ ├── PulsatingCircle.scss │ │ │ ├── PulsatingCircle.test.tsx │ │ │ └── PulsatingCircle.tsx │ │ ├── README │ │ └── WorldMap │ │ │ ├── WorldMap.scss │ │ │ ├── WorldMap.test.tsx │ │ │ ├── WorldMap.tsx │ │ │ └── types.tsx │ ├── features │ │ └── README │ ├── hooks │ │ ├── AnimationFrame.tsx │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ └── README │ ├── logo.svg │ ├── model │ │ ├── README │ │ ├── clientsObject.ts │ │ ├── index.ts │ │ └── mapObject.ts │ ├── pages │ │ └── README │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ └── README │ │ └── selectors │ │ │ ├── README │ │ │ ├── clientsSelectors.ts │ │ │ └── mapSelectors.ts │ ├── redux │ │ └── store.ts │ ├── serviceWorker.ts │ ├── setupTests.ts │ └── widgets │ │ ├── ClientsWidget │ │ ├── ClientsWidget.scss │ │ ├── ClientsWidget.test.tsx │ │ └── ClientsWidget.tsx │ │ └── README │ ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ ├── d3 │ │ └── component.tsx │ ├── d3class │ │ └── component.tsx │ ├── materialui │ │ └── materialui.tsx │ ├── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx │ ├── recoil │ │ ├── component.tsx │ │ └── test.tsx │ └── widget │ │ └── Widget.tsx │ ├── tsconfig.json │ └── yarn.lock ├── ch08 └── bubble-chart │ ├── .env │ ├── .eslintignore │ ├── .eslintrc │ ├── .gitignore │ ├── .prettierrc │ ├── README.md │ ├── README_CRA.md │ ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ └── README │ ├── components │ │ ├── BubbleChart │ │ │ ├── BubbleChart.scss │ │ │ ├── BubbleChart.test.tsx │ │ │ ├── BubbleChart.tsx │ │ │ ├── BubbleChartWithAnimation.tsx │ │ │ └── types.tsx │ │ └── README │ ├── features │ │ └── README │ ├── hooks │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ └── README │ ├── logo.svg │ ├── model │ │ └── README │ ├── pages │ │ └── README │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ └── README │ │ └── selectors │ │ │ └── README │ ├── redux │ │ └── store.ts │ ├── serviceWorker.ts │ ├── setupTests.ts │ └── widgets │ │ └── README │ ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ ├── d3 │ │ └── component.tsx │ ├── d3class │ │ └── component.tsx │ ├── materialui │ │ └── materialui.tsx │ ├── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx │ ├── recoil │ │ ├── component.tsx │ │ └── test.tsx │ └── widget │ │ └── Widget.tsx │ └── tsconfig.json ├── ch09 └── force-chart │ ├── README.md │ ├── README_CRA.md │ ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ ├── data │ │ └── power_network.json │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ └── README │ ├── components │ │ ├── README │ │ └── SimpleForceGraph │ │ │ ├── Circle.tsx │ │ │ ├── Circles.tsx │ │ │ ├── Label.tsx │ │ │ ├── Labels.tsx │ │ │ ├── Link.tsx │ │ │ ├── Links.tsx │ │ │ ├── SimpleForceGraph.scss │ │ │ ├── SimpleForceGraph.tsx │ │ │ └── types.ts │ ├── features │ │ └── README │ ├── hooks │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ └── README │ ├── logo.svg │ ├── model │ │ └── README │ ├── pages │ │ └── README │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ └── README │ │ └── selectors │ │ │ ├── README │ │ │ └── powerChartSelectors.ts │ ├── redux │ │ └── store.ts │ ├── serviceWorker.ts │ ├── setupTests.ts │ └── widgets │ │ ├── NetworksWidget │ │ ├── NetworksWidget.scss │ │ └── NetworksWidget.tsx │ │ └── README │ ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ ├── d3 │ │ └── component.tsx │ ├── d3class │ │ └── component.tsx │ ├── materialui │ │ └── materialui.tsx │ ├── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx │ ├── recoil │ │ ├── component.tsx │ │ └── test.tsx │ └── widget │ │ └── Widget.tsx │ ├── tsconfig.json │ └── yarn.lock ├── ch10 └── react-chart-libraries │ ├── README.md │ ├── README_CRA.md │ ├── build │ ├── asset-manifest.json │ ├── data │ │ ├── area.csv │ │ ├── bar.csv │ │ ├── calendar.json │ │ ├── line.csv │ │ ├── pie.csv │ │ └── scatter.csv │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ ├── precache-manifest.d31aea694f13a98c79a18199b156b1b0.js │ ├── report.html │ ├── robots.txt │ ├── service-worker.js │ └── static │ │ ├── css │ │ ├── 2.5a2f7233.chunk.css │ │ ├── 2.5a2f7233.chunk.css.map │ │ ├── main.7a4fb01d.chunk.css │ │ └── main.7a4fb01d.chunk.css.map │ │ └── js │ │ ├── 2.d6ebf2ae.chunk.js │ │ ├── 2.d6ebf2ae.chunk.js.LICENSE.txt │ │ ├── 2.d6ebf2ae.chunk.js.map │ │ ├── main.b4acb14e.chunk.js │ │ ├── main.b4acb14e.chunk.js.map │ │ ├── runtime-main.e2745115.js │ │ └── runtime-main.e2745115.js.map │ ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ ├── data │ │ ├── area.csv │ │ ├── bar.csv │ │ ├── calendar.json │ │ ├── line.csv │ │ ├── pie.csv │ │ └── scatter.csv │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ └── README │ ├── components │ │ ├── README │ │ ├── SimpleBarGraph │ │ │ └── SimpleBarGraph.tsx │ │ ├── SimpleCalendarChart │ │ │ └── SimpleCalendarChart.tsx │ │ ├── SimpleLineChart │ │ │ ├── SimpleLineChart.tsx │ │ │ └── types.ts │ │ ├── SimplePie │ │ │ └── SimplePie.tsx │ │ └── SimpleReactVizChart │ │ │ └── SimpleReactVizChart.tsx │ ├── features │ │ └── README │ ├── hooks │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ └── README │ ├── logo.svg │ ├── model │ │ └── README │ ├── pages │ │ └── README │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ └── README │ │ └── selectors │ │ │ ├── README │ │ │ ├── calendarDataSelectors.ts │ │ │ └── lineDataSelectors.ts │ ├── redux │ │ └── store.ts │ ├── serviceWorker.ts │ ├── setupTests.ts │ └── widgets │ │ └── README │ ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ ├── d3 │ │ └── component.tsx │ ├── d3class │ │ └── component.tsx │ ├── materialui │ │ └── materialui.tsx │ ├── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx │ ├── recoil │ │ ├── component.tsx │ │ └── test.tsx │ └── widget │ │ └── Widget.tsx │ ├── tsconfig.json │ ├── yarn-error.log │ └── yarn.lock ├── ch11 └── knick-knacks │ ├── README.md │ ├── README_CRA.md │ ├── build │ ├── 200.html │ ├── 404.html │ ├── Rectangle │ │ └── index.html │ ├── asset-manifest.json │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ ├── precache-manifest.c3bcfa4a722d25579c0220494ee6f547.js │ ├── robots.txt │ ├── service-worker.js │ └── static │ │ ├── css │ │ ├── main.5c815069.chunk.css │ │ └── main.5c815069.chunk.css.map │ │ └── js │ │ ├── 2.d9a1b4ed.chunk.js │ │ ├── 2.d9a1b4ed.chunk.js.LICENSE.txt │ │ ├── 2.d9a1b4ed.chunk.js.map │ │ ├── 3.ff43eb1d.chunk.js │ │ ├── 3.ff43eb1d.chunk.js.map │ │ ├── main.f0d19790.chunk.js │ │ ├── main.f0d19790.chunk.js.map │ │ ├── runtime-main.efe5e15b.js │ │ └── runtime-main.efe5e15b.js.map │ ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ └── README │ ├── components │ │ ├── HelloD3Data │ │ │ ├── HelloD3Data.tsx │ │ │ └── HelloD3DataCloned.tsx │ │ ├── HelloD3DataClass │ │ │ └── HelloD3DataClass.tsx │ │ ├── README │ │ └── Rectangle │ │ │ └── Rectangle.tsx │ ├── features │ │ └── README │ ├── hooks │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ └── README │ ├── logo.svg │ ├── model │ │ └── README │ ├── pages │ │ └── README │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ └── README │ │ └── selectors │ │ │ └── README │ ├── redux │ │ └── store.ts │ ├── serviceWorker.ts │ ├── setupTests.ts │ └── widgets │ │ └── README │ ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ ├── d3 │ │ └── component.tsx │ ├── d3class │ │ └── component.tsx │ ├── materialui │ │ └── materialui.tsx │ ├── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx │ ├── recoil │ │ ├── component.tsx │ │ └── test.tsx │ └── widget │ │ └── Widget.tsx │ ├── tsconfig.json │ ├── yarn-error.log │ └── yarn.lock ├── ch12 └── nextjs-ts-chart │ ├── .gitignore │ ├── README.md │ ├── next-env.d.ts │ ├── package.json │ ├── server.js │ ├── tsconfig.json │ └── yarn.lock └── errata.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /9781484270516.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/9781484270516.jpg -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to Apress Source Code 2 | 3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. 4 | 5 | ## How to Contribute 6 | 7 | 1. Make sure you have a GitHub account. 8 | 2. Fork the repository for the relevant book. 9 | 3. Create a new branch on which to make your change, e.g. 10 | `git checkout -b my_code_contribution` 11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. 12 | 5. Submit a pull request. 13 | 14 | Thank you for your contribution! -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/e2e/global.d.ts: -------------------------------------------------------------------------------- 1 | // globals defined in jest.config.js need to be included in this `d.ts` 2 | // file to avoid TS lint errors 3 | declare let SERVER_URL: string 4 | declare let JEST_TIMEOUT: number -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/e2e/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'jest-puppeteer', 3 | globals: { 4 | SERVER_URL: 'http://localhost:3000', 5 | JEST_TIMEOUT: 50000 6 | }, 7 | testRegex: './*\\.test\\.tsx$' 8 | } 9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE') -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/jest-puppeteer.config.js: -------------------------------------------------------------------------------- 1 | // jest-puppeteer.config.js 2 | module.exports = { 3 | server: { 4 | command: `yarn start`, 5 | port: 3000, 6 | launchTimeout: 20000, 7 | debug: true, 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch01/react-d3-hello-world/public/favicon.ico -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch01/react-d3-hello-world/public/logo192.png -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch01/react-d3-hello-world/public/logo512.png -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/App.scss: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | // src/App.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import App from './App' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1) 14 | }) 15 | }) 16 | 17 | /* 18 | Update this file once it's changed. For instance to check if a component you added 19 | include in App.tsx; 20 | 21 | import { shallow } from "enzyme"; 22 | import Calculator from "./components/SomeComponent/SomeComponent"; 23 | 24 | test('should render SomeComponent', () => { 25 | const wrapper = shallow(); 26 | const calculator = wrapper.find(SomeComponent); 27 | expect(calculator.exists()).toBe(true); 28 | }) 29 | */ 30 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './App.scss' 3 | import HelloD3 from './components/HelloD3/HelloD3' 4 | 5 | function App() { 6 | return ( 7 |
8 |
9 | 10 |
11 |
12 | ) 13 | } 14 | 15 | export default App 16 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/AppRouter.test.tsx: -------------------------------------------------------------------------------- 1 | // src/AppRouter.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import AppRouter from './AppRouter' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | 13 | test('renders without crashing', () => { 14 | expect(component.length).toBe(1) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/assets/README: -------------------------------------------------------------------------------- 1 | Break down your assets by names: about, home, etc. -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/components/HelloD3/HelloD3.scss: -------------------------------------------------------------------------------- 1 | .HelloD3 { 2 | } 3 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/components/HelloD3/HelloD3.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/HelloD3/HelloD3.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import HelloD3 from './HelloD3' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }) 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/components/HelloD3Class/HelloD3Class.scss: -------------------------------------------------------------------------------- 1 | .HelloD3Class { 2 | } -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/components/HelloD3Class/HelloD3Class.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/HelloD3Class/HelloD3Class.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import HelloD3Class from './HelloD3Class' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }); 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/components/README: -------------------------------------------------------------------------------- 1 | components goes here, you can generate with generate-react-cli, examples; 2 | $ npx generate-react-cli component UserButton 3 | $ npx generate-react-cli component Rectangle --type=d3class 4 | $ npx generate-react-cli component Rectangle --type=d3 5 | $ npx generate-react-cli component Login --type=recoil -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/features/README: -------------------------------------------------------------------------------- 1 | features components goes here. -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/index.scss: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 4 | -webkit-font-smoothing: antialiased; 5 | -moz-osx-font-smoothing: grayscale; 6 | } 7 | 8 | code { 9 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; 10 | } 11 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/layout/README: -------------------------------------------------------------------------------- 1 | layout components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component BoxLayout --type=layout -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/model/README: -------------------------------------------------------------------------------- 1 | Place all your object model files here, for example: userObject.ts 2 | 3 | /* 4 | Author: Eli Elad Elrom 5 | Website: https://EliElrom.com 6 | License: MIT License 7 | File: src/model/userObject.ts 8 | */ 9 | 10 | export interface userObject { 11 | email: string 12 | password: string 13 | } 14 | 15 | export const initUser = (): userObject => ({ 16 | email: '', 17 | password: '', 18 | }) 19 | 20 | Next, create an index and add model object for easy access, example: index.ts 21 | 22 | /* 23 | Author: Eli Elad Elrom 24 | Website: https://EliElrom.com 25 | License: MIT License 26 | File: src/model/index.ts 27 | */ 28 | 29 | export * from './userObject' -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/pages/README: -------------------------------------------------------------------------------- 1 | Pages components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component HomePage --type=page -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/recoil/atoms/README: -------------------------------------------------------------------------------- 1 | Recoil atoms goes here, example: userAtoms.ts; 2 | 3 | /* 4 | Author: Eli Elad Elrom 5 | Website: https://EliElrom.com 6 | License: MIT License 7 | File: src/recoil/atoms/userAtoms.ts 8 | */ 9 | 10 | import { atom } from 'recoil' 11 | import { initUser } from '../../model' 12 | 13 | export const userState = atom({ 14 | key: 'UserState', 15 | default: initUser(), 16 | }) -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/redux/store.ts: -------------------------------------------------------------------------------- 1 | // src/redux/store.ts 2 | 3 | import { configureStore, combineReducers } from '@reduxjs/toolkit' 4 | 5 | const store = configureStore({ 6 | reducer: combineReducers({ 7 | // your reducers goes here 8 | }), 9 | }) 10 | 11 | export default store 12 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect' 6 | 7 | import { configure } from 'enzyme' 8 | import Adapter from 'enzyme-adapter-react-16' 9 | 10 | configure({ adapter: new Adapter() }) 11 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/templates/component/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/templates/component/test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import TemplateName from './TemplateName'; 4 | 5 | describe('', () => { 6 | let component; 7 | 8 | beforeEach(() => { 9 | component = shallow(); 10 | }); 11 | 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/templates/component/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import TemplateName from './TemplateName' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }); 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/templates/page/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/templates/recoil/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import { RecoilRoot } from 'recoil' 11 | import TemplateName from './TemplateName' 12 | 13 | describe('', () => { 14 | let component 15 | 16 | beforeEach(() => { 17 | component = shallow() 18 | }) 19 | 20 | test('It should mount', () => { 21 | expect(component.length).toBe(1) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /ch01/react-d3-hello-world/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "es6", "dom", 6 | "dom", 7 | "dom.iterable", 8 | "esnext" 9 | ], 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitThis": true, 13 | "strictNullChecks": true, 14 | "allowJs": true, 15 | "skipLibCheck": true, 16 | "esModuleInterop": true, 17 | "allowSyntheticDefaultImports": true, 18 | "strict": true, 19 | "forceConsistentCasingInFileNames": true, 20 | "module": "esnext", 21 | "moduleResolution": "node", 22 | "resolveJsonModule": true, 23 | "isolatedModules": true, 24 | "noEmit": true, 25 | "jsx": "react" 26 | }, 27 | "include": [ 28 | "src", 29 | "e2e" 30 | ], 31 | "exclude": [ 32 | "**/templates/*", 33 | "**/node_modules/*" 34 | ] 35 | } 36 | 37 | -------------------------------------------------------------------------------- /ch02/e2e/global.d.ts: -------------------------------------------------------------------------------- 1 | // globals defined in jest.config.js need to be included in this `d.ts` 2 | // file to avoid TS lint errors 3 | declare let SERVER_URL: string 4 | declare let JEST_TIMEOUT: number -------------------------------------------------------------------------------- /ch02/e2e/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'jest-puppeteer', 3 | globals: { 4 | SERVER_URL: 'http://localhost:3000', 5 | JEST_TIMEOUT: 50000 6 | }, 7 | testRegex: './*\\.test\\.tsx$' 8 | } 9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE') -------------------------------------------------------------------------------- /ch02/e2e/puppeteer_standalone.js: -------------------------------------------------------------------------------- 1 | const puppeteer = require('puppeteer'); 2 | const SERVER_URL = 'http://localhost:3000'; 3 | 4 | (async function main(){ 5 | try { 6 | const browser = await puppeteer.launch({ headless: false }); 7 | const page = await browser.newPage(); 8 | await page.goto(SERVER_URL, {waitUntil: 'domcontentloaded'}); 9 | 10 | const urlLink = await page.$('a[href*="https://github.com"]'); 11 | if (urlLink) { 12 | await urlLink.click(); 13 | } else { 14 | console.log('No "urlLink" found on page'); 15 | } 16 | // wait 2 secs and shut down! 17 | await new Promise(resolve => setTimeout(resolve, 2000)); 18 | await browser.close(); 19 | } catch (error) { 20 | if (error.message.includes('ERR_CONNECTION_REFUSED')) 21 | console.log('Make sure you have React running: $ yarn start'); 22 | console.log('Error message', error.message); 23 | } 24 | })(); -------------------------------------------------------------------------------- /ch02/jest-puppeteer.config.js: -------------------------------------------------------------------------------- 1 | // jest-puppeteer.config.js 2 | module.exports = { 3 | server: { 4 | command: `yarn start`, 5 | port: 3000, 6 | launchTimeout: 20000, 7 | debug: true, 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /ch02/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch02/public/favicon.ico -------------------------------------------------------------------------------- /ch02/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch02/public/logo192.png -------------------------------------------------------------------------------- /ch02/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch02/public/logo512.png -------------------------------------------------------------------------------- /ch02/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /ch02/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /ch02/src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch02/src/.DS_Store -------------------------------------------------------------------------------- /ch02/src/App.scss: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ch02/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | // src/App.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import App from './App' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1) 14 | }) 15 | }) 16 | 17 | /* 18 | Update this file once it's changed. For instance to check if a component you added 19 | include in App.tsx; 20 | 21 | import { shallow } from "enzyme"; 22 | import Calculator from "./components/SomeComponent/SomeComponent"; 23 | 24 | test('should render SomeComponent', () => { 25 | const wrapper = shallow(); 26 | const calculator = wrapper.find(SomeComponent); 27 | expect(calculator.exists()).toBe(true); 28 | }) 29 | */ 30 | -------------------------------------------------------------------------------- /ch02/src/AppRouter.test.tsx: -------------------------------------------------------------------------------- 1 | // src/AppRouter.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import AppRouter from './AppRouter' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | 13 | test('renders without crashing', () => { 14 | expect(component.length).toBe(1) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /ch02/src/assets/README: -------------------------------------------------------------------------------- 1 | Break down your assets by names: about, home, etc. -------------------------------------------------------------------------------- /ch02/src/components/CircleWithEvents/CircleWithEvents.scss: -------------------------------------------------------------------------------- 1 | .circle { 2 | cursor: pointer; 3 | width: 150px; 4 | height: 150px; 5 | fill: #6666; 6 | } 7 | -------------------------------------------------------------------------------- /ch02/src/components/HelloD3/HelloD3.scss: -------------------------------------------------------------------------------- 1 | .HelloD3 { 2 | } 3 | -------------------------------------------------------------------------------- /ch02/src/components/HelloD3/HelloD3.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/HelloD3/HelloD3.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import HelloD3 from './HelloD3' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }) 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch02/src/components/HelloD3Class/HelloD3Class.scss: -------------------------------------------------------------------------------- 1 | .HelloD3Class { 2 | } 3 | -------------------------------------------------------------------------------- /ch02/src/components/HelloD3Class/HelloD3Class.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/HelloD3Class/HelloD3Class.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import HelloD3Class from './HelloD3Class' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }) 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch02/src/components/HelloD3Data/HelloD3Data.scss: -------------------------------------------------------------------------------- 1 | .HelloD3Data { 2 | } 3 | -------------------------------------------------------------------------------- /ch02/src/components/HelloD3Data/HelloD3Data.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/HelloD3Data/HelloD3Data.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import HelloD3Data from './HelloD3Data' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }) 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch02/src/components/HelloD3Data/HelloD3Data.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/HelloD3Data/HelloD3Data.tsx 6 | */ 7 | 8 | import React, { useEffect } from 'react' 9 | import './HelloD3Data.scss' 10 | import * as d3 from 'd3' // yarn add d3 @types/d3 11 | 12 | const HelloD3Data = (props: IHelloD3DataProps) => { 13 | useEffect(() => { 14 | draw() 15 | }) 16 | 17 | const draw = () => { 18 | d3.select('.HelloD3Data') 19 | .selectAll('p') 20 | .data(props.data) 21 | .enter() 22 | .append('p') 23 | .text((d) => `d3 ${d}`) 24 | } 25 | 26 | return
27 | } 28 | 29 | interface IHelloD3DataProps { 30 | data: string[] 31 | } 32 | 33 | export default HelloD3Data 34 | -------------------------------------------------------------------------------- /ch02/src/components/HelloJSXData/HelloJSXData.scss: -------------------------------------------------------------------------------- 1 | .HelloJSXData { 2 | } 3 | -------------------------------------------------------------------------------- /ch02/src/components/HelloJSXData/HelloJSXData.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/HelloJSXData/HelloJSXData.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import HelloJSXData from './HelloJSXData' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }) 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch02/src/components/HelloJSXData/HelloJSXData.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/HelloJSXData/HelloJSXData.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import './HelloJSXData.scss' 10 | 11 | const HelloJSXData = (props: IHelloJSXDataProps) => { 12 | return ( 13 |
14 | {props.data.map((d, index) => ( 15 |

jsx {d}

16 | ))} 17 |
18 | ) 19 | } 20 | 21 | interface IHelloJSXDataProps { 22 | data: string[] 23 | } 24 | 25 | export default HelloJSXData 26 | -------------------------------------------------------------------------------- /ch02/src/components/HelloSVG/HelloSVG.scss: -------------------------------------------------------------------------------- 1 | .myRect { 2 | fill: #ba2121; 3 | } 4 | -------------------------------------------------------------------------------- /ch02/src/components/HelloSVG/HelloSVG.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/HelloSVG/HelloSVG.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import HelloSVG from './HelloSVG' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }) 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch02/src/components/JSXCanvas/JSXCanvas.scss: -------------------------------------------------------------------------------- 1 | .JSXCanvas { 2 | } 3 | -------------------------------------------------------------------------------- /ch02/src/components/JSXCanvas/JSXCanvas.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/JSXCanvas/JSXCanvas.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import JSXCanvas from './JSXCanvas' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }) 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch02/src/components/README: -------------------------------------------------------------------------------- 1 | components goes here, you can generate with generate-react-cli, examples; 2 | $ npx generate-react-cli component UserButton 3 | $ npx generate-react-cli component Rectangle --type=d3class 4 | $ npx generate-react-cli component Rectangle --type=d3 5 | $ npx generate-react-cli component Login --type=recoil -------------------------------------------------------------------------------- /ch02/src/components/SimpleChart/SimpleChart.scss: -------------------------------------------------------------------------------- 1 | .SimpleChart { 2 | } 3 | -------------------------------------------------------------------------------- /ch02/src/components/SimpleChart/SimpleChart.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/SimpleChart/SimpleChart.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import SimpleChart from './SimpleChart' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }) 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch02/src/features/README: -------------------------------------------------------------------------------- 1 | features components goes here. -------------------------------------------------------------------------------- /ch02/src/index.scss: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 4 | -webkit-font-smoothing: antialiased; 5 | -moz-osx-font-smoothing: grayscale; 6 | } 7 | 8 | code { 9 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; 10 | } 11 | -------------------------------------------------------------------------------- /ch02/src/layout/README: -------------------------------------------------------------------------------- 1 | layout components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component BoxLayout --type=layout -------------------------------------------------------------------------------- /ch02/src/model/README: -------------------------------------------------------------------------------- 1 | Place all your object model files here, for example: userObject.ts 2 | 3 | /* 4 | Author: Eli Elad Elrom 5 | Website: https://EliElrom.com 6 | License: MIT License 7 | File: src/model/userObject.ts 8 | */ 9 | 10 | export interface userObject { 11 | email: string 12 | password: string 13 | } 14 | 15 | export const initUser = (): userObject => ({ 16 | email: '', 17 | password: '', 18 | }) 19 | 20 | Next, create an index and add model object for easy access, example: index.ts 21 | 22 | /* 23 | Author: Eli Elad Elrom 24 | Website: https://EliElrom.com 25 | License: MIT License 26 | File: src/model/index.ts 27 | */ 28 | 29 | export * from './userObject' -------------------------------------------------------------------------------- /ch02/src/pages/README: -------------------------------------------------------------------------------- 1 | Pages components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component HomePage --type=page -------------------------------------------------------------------------------- /ch02/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /ch02/src/recoil/atoms/README: -------------------------------------------------------------------------------- 1 | Recoil atoms goes here, example: userAtoms.ts; 2 | 3 | /* 4 | Author: Eli Elad Elrom 5 | Website: https://EliElrom.com 6 | License: MIT License 7 | File: src/recoil/atoms/userAtoms.ts 8 | */ 9 | 10 | import { atom } from 'recoil' 11 | import { initUser } from '../../model' 12 | 13 | export const userState = atom({ 14 | key: 'UserState', 15 | default: initUser(), 16 | }) -------------------------------------------------------------------------------- /ch02/src/redux/store.ts: -------------------------------------------------------------------------------- 1 | // src/redux/store.ts 2 | 3 | import { configureStore, combineReducers } from '@reduxjs/toolkit' 4 | 5 | const store = configureStore({ 6 | reducer: combineReducers({ 7 | // your reducers goes here 8 | }), 9 | }) 10 | 11 | export default store 12 | -------------------------------------------------------------------------------- /ch02/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect' 6 | 7 | import { configure } from 'enzyme' 8 | import Adapter from 'enzyme-adapter-react-16' 9 | 10 | configure({ adapter: new Adapter() }) 11 | -------------------------------------------------------------------------------- /ch02/templates/component/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch02/templates/component/test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import TemplateName from './TemplateName'; 4 | 5 | describe('', () => { 6 | let component; 7 | 8 | beforeEach(() => { 9 | component = shallow(); 10 | }); 11 | 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ch02/templates/component/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import TemplateName from './TemplateName' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }); 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch02/templates/page/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch02/templates/recoil/component.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.tsx 6 | */ 7 | 8 | import React, { useEffect } from 'react' 9 | import './TemplateName.scss' 10 | // import { useRecoilValue } from 'recoil' 11 | 12 | const TemplateName = () /* or ( props : ITemplateNameProps ) */ => { 13 | const results: boolean = true // useRecoilValue( getMethod ) 14 | useEffect(() => { 15 | // TODO 16 | }) 17 | return ( 18 | <> 19 | {results ? ( 20 |
21 | TemplateName Loaded 22 |
23 | ) : ( 24 | <>Loading 25 | )} 26 | 27 | ) 28 | } 29 | 30 | /* 31 | interface ITemplateNameProps { 32 | // TODO 33 | } 34 | */ 35 | 36 | export default TemplateName 37 | -------------------------------------------------------------------------------- /ch02/templates/recoil/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import { RecoilRoot } from 'recoil' 11 | import TemplateName from './TemplateName' 12 | 13 | describe('', () => { 14 | let component 15 | 16 | beforeEach(() => { 17 | component = shallow() 18 | }) 19 | 20 | test('It should mount', () => { 21 | expect(component.length).toBe(1) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /ch02/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "es6", "dom", 6 | "dom", 7 | "dom.iterable", 8 | "esnext" 9 | ], 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitThis": true, 13 | "strictNullChecks": true, 14 | "allowJs": true, 15 | "skipLibCheck": true, 16 | "esModuleInterop": true, 17 | "allowSyntheticDefaultImports": true, 18 | "strict": true, 19 | "forceConsistentCasingInFileNames": true, 20 | "module": "esnext", 21 | "moduleResolution": "node", 22 | "resolveJsonModule": true, 23 | "isolatedModules": true, 24 | "noEmit": true, 25 | "jsx": "react" 26 | }, 27 | "include": [ 28 | "src", 29 | "e2e" 30 | ], 31 | "exclude": [ 32 | "**/templates/*", 33 | "**/node_modules/*" 34 | ] 35 | } 36 | 37 | -------------------------------------------------------------------------------- /ch03/e2e/global.d.ts: -------------------------------------------------------------------------------- 1 | // globals defined in jest.config.js need to be included in this `d.ts` 2 | // file to avoid TS lint errors 3 | declare let SERVER_URL: string 4 | declare let JEST_TIMEOUT: number -------------------------------------------------------------------------------- /ch03/e2e/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'jest-puppeteer', 3 | globals: { 4 | SERVER_URL: 'http://localhost:3000', 5 | JEST_TIMEOUT: 50000 6 | }, 7 | testRegex: './*\\.test\\.tsx$' 8 | } 9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE') -------------------------------------------------------------------------------- /ch03/e2e/puppeteer_standalone.js: -------------------------------------------------------------------------------- 1 | const puppeteer = require('puppeteer'); 2 | const SERVER_URL = 'http://localhost:3000'; 3 | 4 | (async function main(){ 5 | try { 6 | const browser = await puppeteer.launch({ headless: false }); 7 | const page = await browser.newPage(); 8 | await page.goto(SERVER_URL, {waitUntil: 'domcontentloaded'}); 9 | 10 | const urlLink = await page.$('a[href*="https://github.com"]'); 11 | if (urlLink) { 12 | await urlLink.click(); 13 | } else { 14 | console.log('No "urlLink" found on page'); 15 | } 16 | // wait 2 secs and shut down! 17 | await new Promise(resolve => setTimeout(resolve, 2000)); 18 | await browser.close(); 19 | } catch (error) { 20 | if (error.message.includes('ERR_CONNECTION_REFUSED')) 21 | console.log('Make sure you have React running: $ yarn start'); 22 | console.log('Error message', error.message); 23 | } 24 | })(); -------------------------------------------------------------------------------- /ch03/jest-puppeteer.config.js: -------------------------------------------------------------------------------- 1 | // jest-puppeteer.config.js 2 | module.exports = { 3 | server: { 4 | command: `yarn start`, 5 | port: 3000, 6 | launchTimeout: 20000, 7 | debug: true, 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /ch03/public/data/bar.csv: -------------------------------------------------------------------------------- 1 | framework,carat 2 | jQuery,43.3 3 | React.js,35.9 4 | Angular,25.1 5 | ASP.NET,21.9 6 | Express,21.2 7 | .NET Core,19.1 8 | Vue.js,17.3 9 | Spring,16.4 10 | Angular.js,16.1 11 | Django,14.2 12 | Flask,14.2 13 | Laravel,11.1 14 | Rails,7.0 15 | Symfony,14.4 16 | Gatsby, 4.0 17 | Drupal, 3.2 -------------------------------------------------------------------------------- /ch03/public/data/pie.csv: -------------------------------------------------------------------------------- 1 | name,value 2 | a,25 3 | b,3 4 | c,45 5 | d,7 6 | e,20 -------------------------------------------------------------------------------- /ch03/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch03/public/favicon.ico -------------------------------------------------------------------------------- /ch03/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch03/public/logo192.png -------------------------------------------------------------------------------- /ch03/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch03/public/logo512.png -------------------------------------------------------------------------------- /ch03/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /ch03/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /ch03/src/App.scss: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ch03/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | // src/App.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import App from './App' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1) 14 | }) 15 | }) 16 | 17 | /* 18 | Update this file once it's changed. For instance to check if a component you added 19 | include in App.tsx; 20 | 21 | import { shallow } from "enzyme"; 22 | import Calculator from "./components/SomeComponent/SomeComponent"; 23 | 24 | test('should render SomeComponent', () => { 25 | const wrapper = shallow(); 26 | const calculator = wrapper.find(SomeComponent); 27 | expect(calculator.exists()).toBe(true); 28 | }) 29 | */ 30 | -------------------------------------------------------------------------------- /ch03/src/AppRouter.test.tsx: -------------------------------------------------------------------------------- 1 | // src/AppRouter.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import AppRouter from './AppRouter' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | 13 | test('renders without crashing', () => { 14 | expect(component.length).toBe(1) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /ch03/src/assets/README: -------------------------------------------------------------------------------- 1 | Break down your assets by names: about, home, etc. -------------------------------------------------------------------------------- /ch03/src/components/BasicAreaChart/BasicAreaChart.scss: -------------------------------------------------------------------------------- 1 | .basicBarChart { 2 | } 3 | -------------------------------------------------------------------------------- /ch03/src/components/BasicAreaChart/BasicAreaChart.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/BasicAreaChart/BasicAreaChart.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import BasicAreaChart from './BasicAreaChart' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }) 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch03/src/components/BasicAreaChart/types.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/BasicAreaChart/types.ts 6 | */ 7 | 8 | export namespace Types { 9 | // eslint-disable-next-line @typescript-eslint/naming-convention 10 | export type data = { 11 | date: string 12 | value: number 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch03/src/components/BasicBarChart/BasicBarChart.scss: -------------------------------------------------------------------------------- 1 | .basicBarChart { 2 | } 3 | 4 | .bar { 5 | fill: tomato; 6 | } 7 | -------------------------------------------------------------------------------- /ch03/src/components/BasicBarChart/BasicBarChart.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/BasicBarChart/BasicBarChart.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import BasicBarChart from './BasicBarChart' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }) 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch03/src/components/BasicBarChart/types.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/BasicBarChart/types.ts 6 | */ 7 | 8 | export namespace Types { 9 | export type Data = { 10 | framework: string 11 | value: number 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ch03/src/components/BasicDonutChart/types.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/BasicDonutChart/types.ts 6 | */ 7 | 8 | export namespace Types { 9 | export type Data = { 10 | name: string 11 | value: number 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ch03/src/components/BasicLineChart/BasicLineChart.scss: -------------------------------------------------------------------------------- 1 | .basicLineChart { 2 | } 3 | -------------------------------------------------------------------------------- /ch03/src/components/BasicLineChart/BasicLineChart.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/BasicLineChart/BasicLineChart.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import BasicLineChart from './BasicLineChart' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }) 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch03/src/components/BasicLineChart/types.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/BasicLineChart/types.ts 6 | */ 7 | 8 | export namespace Types { 9 | export type Data = { 10 | date: string 11 | value: number 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ch03/src/components/BasicPieChart/BasicPieChart.scss: -------------------------------------------------------------------------------- 1 | .basicPieChart { 2 | } 3 | -------------------------------------------------------------------------------- /ch03/src/components/BasicPieChart/BasicPieChart.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/BasicPieChart/BasicPieChart.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import BasicPieChart from './BasicPieChart' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }) 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch03/src/components/BasicPieChart/types.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/BasicPieChart/types.ts 6 | */ 7 | 8 | export namespace Types { 9 | export type Data = { 10 | name: string 11 | value: number 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ch03/src/components/BasicScatterChart/BasicScatterChart.scss: -------------------------------------------------------------------------------- 1 | .basicScatterChart { 2 | } 3 | -------------------------------------------------------------------------------- /ch03/src/components/BasicScatterChart/BasicScatterChart.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/BasicScatterChart/BasicScatterChart.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import BasicScatterChart from './BasicScatterChart' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }) 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch03/src/components/BasicScatterChart/types.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/BasicScatterChart/types.ts 6 | */ 7 | 8 | export namespace Types { 9 | export type Data = { 10 | price: number 11 | carat: number 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ch03/src/components/README: -------------------------------------------------------------------------------- 1 | components goes here, you can generate with generate-react-cli, examples; 2 | $ npx generate-react-cli component UserButton 3 | $ npx generate-react-cli component Rectangle --type=d3class 4 | $ npx generate-react-cli component Rectangle --type=d3 5 | $ npx generate-react-cli component Login --type=recoil -------------------------------------------------------------------------------- /ch03/src/features/README: -------------------------------------------------------------------------------- 1 | features components goes here. -------------------------------------------------------------------------------- /ch03/src/index.scss: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 4 | -webkit-font-smoothing: antialiased; 5 | -moz-osx-font-smoothing: grayscale; 6 | } 7 | 8 | code { 9 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; 10 | } 11 | -------------------------------------------------------------------------------- /ch03/src/layout/README: -------------------------------------------------------------------------------- 1 | layout components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component BoxLayout --type=layout -------------------------------------------------------------------------------- /ch03/src/model/README: -------------------------------------------------------------------------------- 1 | Place all your object model files here, for example: userObject.ts 2 | 3 | /* 4 | Author: Eli Elad Elrom 5 | Website: https://EliElrom.com 6 | License: MIT License 7 | File: src/model/userObject.ts 8 | */ 9 | 10 | export interface userObject { 11 | email: string 12 | password: string 13 | } 14 | 15 | export const initUser = (): userObject => ({ 16 | email: '', 17 | password: '', 18 | }) 19 | 20 | Next, create an index and add model object for easy access, example: index.ts 21 | 22 | /* 23 | Author: Eli Elad Elrom 24 | Website: https://EliElrom.com 25 | License: MIT License 26 | File: src/model/index.ts 27 | */ 28 | 29 | export * from './userObject' -------------------------------------------------------------------------------- /ch03/src/pages/README: -------------------------------------------------------------------------------- 1 | Pages components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component HomePage --type=page -------------------------------------------------------------------------------- /ch03/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /ch03/src/recoil/atoms/README: -------------------------------------------------------------------------------- 1 | Recoil atoms goes here, example: userAtoms.ts; 2 | 3 | /* 4 | Author: Eli Elad Elrom 5 | Website: https://EliElrom.com 6 | License: MIT License 7 | File: src/recoil/atoms/userAtoms.ts 8 | */ 9 | 10 | import { atom } from 'recoil' 11 | import { initUser } from '../../model' 12 | 13 | export const userState = atom({ 14 | key: 'UserState', 15 | default: initUser(), 16 | }) -------------------------------------------------------------------------------- /ch03/src/redux/store.ts: -------------------------------------------------------------------------------- 1 | // src/redux/store.ts 2 | 3 | import { configureStore, combineReducers } from '@reduxjs/toolkit' 4 | 5 | const store = configureStore({ 6 | reducer: combineReducers({ 7 | // your reducers goes here 8 | }), 9 | }) 10 | 11 | export default store 12 | -------------------------------------------------------------------------------- /ch03/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect' 6 | 7 | import { configure } from 'enzyme' 8 | import Adapter from 'enzyme-adapter-react-16' 9 | 10 | configure({ adapter: new Adapter() }) 11 | -------------------------------------------------------------------------------- /ch03/templates/component/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch03/templates/component/test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import TemplateName from './TemplateName'; 4 | 5 | describe('', () => { 6 | let component; 7 | 8 | beforeEach(() => { 9 | component = shallow(); 10 | }); 11 | 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ch03/templates/component/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import TemplateName from './TemplateName' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }); 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch03/templates/page/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch03/templates/recoil/component.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.tsx 6 | */ 7 | 8 | import React, { useEffect } from 'react' 9 | import './TemplateName.scss' 10 | // import { useRecoilValue } from 'recoil' 11 | 12 | const TemplateName = () /* or ( props : ITemplateNameProps ) */ => { 13 | const results: boolean = true // useRecoilValue( getMethod ) 14 | useEffect(() => { 15 | // TODO 16 | }) 17 | return ( 18 | <> 19 | {results ? ( 20 |
21 | TemplateName Loaded 22 |
23 | ) : ( 24 | <>Loading 25 | )} 26 | 27 | ) 28 | } 29 | 30 | /* 31 | interface ITemplateNameProps { 32 | // TODO 33 | } 34 | */ 35 | 36 | export default TemplateName 37 | -------------------------------------------------------------------------------- /ch03/templates/recoil/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import { RecoilRoot } from 'recoil' 11 | import TemplateName from './TemplateName' 12 | 13 | describe('', () => { 14 | let component 15 | 16 | beforeEach(() => { 17 | component = shallow() 18 | }) 19 | 20 | test('It should mount', () => { 21 | expect(component.length).toBe(1) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /ch03/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "es6", "dom", 6 | "dom", 7 | "dom.iterable", 8 | "esnext" 9 | ], 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitThis": true, 13 | "strictNullChecks": true, 14 | "allowJs": true, 15 | "skipLibCheck": true, 16 | "esModuleInterop": true, 17 | "allowSyntheticDefaultImports": true, 18 | "strict": true, 19 | "forceConsistentCasingInFileNames": true, 20 | "module": "esnext", 21 | "moduleResolution": "node", 22 | "resolveJsonModule": true, 23 | "isolatedModules": true, 24 | "noEmit": true, 25 | "jsx": "react" 26 | }, 27 | "include": [ 28 | "src", 29 | "e2e" 30 | ], 31 | "exclude": [ 32 | "**/templates/*", 33 | "**/node_modules/*" 34 | ] 35 | } 36 | 37 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | BROWSER=none 3 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/.eslintignore: -------------------------------------------------------------------------------- 1 | build/* 2 | public/* 3 | docs/* 4 | templates/* 5 | src/react-app-env.d.ts 6 | src/serviceWorker.ts 7 | e2e/jest.config.js 8 | e2e/puppeteer_standalone.js 9 | jest-puppeteer.config.js -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/.gitignore: -------------------------------------------------------------------------------- 1 | # misc 2 | .DS_Store 3 | package-lock.json 4 | yarn-error.log 5 | yarn.lock 6 | docs 7 | 8 | # IDEs 9 | .vscode 10 | .idea 11 | 12 | # dependencies 13 | /node_modules 14 | /.pnp 15 | .pnp.js 16 | 17 | # testing 18 | /coverage 19 | .nyc_output 20 | 21 | # production 22 | /build 23 | 24 | # misc 25 | .DS_Store 26 | .env.local 27 | .env.development.local 28 | .env.test.local 29 | .env.production.local 30 | 31 | npm-debug.log* 32 | yarn-debug.log* 33 | yarn-error.log* 34 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "printWidth": 200, 4 | "semi": false, 5 | "singleQuote": true, 6 | "tabWidth": 2 7 | } 8 | 9 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/e2e/global.d.ts: -------------------------------------------------------------------------------- 1 | // globals defined in jest.config.js need to be included in this `d.ts` 2 | // file to avoid TS lint errors 3 | declare let SERVER_URL: string 4 | declare let JEST_TIMEOUT: number -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/e2e/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'jest-puppeteer', 3 | globals: { 4 | SERVER_URL: 'http://localhost:3000', 5 | JEST_TIMEOUT: 50000 6 | }, 7 | testRegex: './*\\.test\\.tsx$' 8 | } 9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE') -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/jest-puppeteer.config.js: -------------------------------------------------------------------------------- 1 | // jest-puppeteer.config.js 2 | module.exports = { 3 | server: { 4 | command: `yarn start`, 5 | port: 3000, 6 | launchTimeout: 20000, 7 | debug: true, 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/public/data/README: -------------------------------------------------------------------------------- 1 | Date source: 2 | https://ethereumprice.org/history/?start=2020-01-01&end=2020-12-12¤cy=USD -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch04-05/histogram-d3-ts/public/favicon.ico -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch04-05/histogram-d3-ts/public/logo192.png -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch04-05/histogram-d3-ts/public/logo512.png -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/App.scss: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | // src/App.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import App from './App' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1) 14 | }) 15 | }) 16 | 17 | /* 18 | Update this file once it's changed. For instance to check if a component you added 19 | include in App.tsx; 20 | 21 | import { shallow } from "enzyme"; 22 | import Calculator from "./components/SomeComponent/SomeComponent"; 23 | 24 | test('should render SomeComponent', () => { 25 | const wrapper = shallow(); 26 | const calculator = wrapper.find(SomeComponent); 27 | expect(calculator.exists()).toBe(true); 28 | }) 29 | */ 30 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/AppRouter.test.tsx: -------------------------------------------------------------------------------- 1 | // src/AppRouter.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import AppRouter from './AppRouter' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | 13 | test('renders without crashing', () => { 14 | expect(component.length).toBe(1) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/assets/README: -------------------------------------------------------------------------------- 1 | Break down your assets by names: about, home, etc. -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/components/Histogram/Histogram.scss: -------------------------------------------------------------------------------- 1 | .histogram { 2 | padding-top: 50px; 3 | } 4 | .sliderDiv { 5 | width: 400px; 6 | padding-left: 50px; 7 | padding-top: 20px; 8 | } 9 | svg text { 10 | fill: white; 11 | } 12 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/components/Histogram/Histogram.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/Histogram/Histogram.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import { RecoilRoot } from 'recoil' 11 | import Histogram from './Histogram' 12 | 13 | describe('', () => { 14 | let component 15 | 16 | beforeEach(() => { 17 | component = shallow( 18 | 19 | 20 | 21 | ) 22 | }) 23 | 24 | test('It should mount', () => { 25 | expect(component.length).toBe(1) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/components/Histogram/types.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/Histogram/types.ts 6 | */ 7 | 8 | export namespace Types { 9 | export type Data = { 10 | price: number 11 | } 12 | export type BarsNode = { 13 | x0: number 14 | x1: number 15 | length: number 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/components/PriceTableList/PriceTableList.scss: -------------------------------------------------------------------------------- 1 | .priceTableListTableCellHead { 2 | background-color: #343434; 3 | } 4 | 5 | .priceTableListTableCell { 6 | background-color: #515151; 7 | } 8 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/components/PriceTableList/PriceTableList.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/PriceTableList/PriceTableList.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import PriceTableList from './PriceTableList' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }) 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/components/PriceTableList/types.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/PriceTableList/types.ts 6 | */ 7 | 8 | export namespace Types { 9 | export type Data = { 10 | price: number 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/components/README: -------------------------------------------------------------------------------- 1 | components goes here, you can generate with generate-react-cli, examples; 2 | $ npx generate-react-cli component UserButton 3 | $ npx generate-react-cli component Rectangle --type=d3class 4 | $ npx generate-react-cli component Rectangle --type=d3 5 | $ npx generate-react-cli component Login --type=recoil 6 | $ npx generate-react-cli component MyButton --type=materialui 7 | $ npx generate-react-cli component MyWidget --type=widget -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/features/README: -------------------------------------------------------------------------------- 1 | features components goes here. -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/index.scss: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 4 | -webkit-font-smoothing: antialiased; 5 | -moz-osx-font-smoothing: grayscale; 6 | } 7 | 8 | code { 9 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; 10 | } 11 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/layout/README: -------------------------------------------------------------------------------- 1 | layout components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component BoxLayout --type=layout -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/model/README: -------------------------------------------------------------------------------- 1 | Place all your object model files here, for example: userObject.ts 2 | 3 | /* 4 | Author: Eli Elad Elrom 5 | Website: https://EliElrom.com 6 | License: MIT License 7 | File: src/model/userObject.ts 8 | */ 9 | 10 | export interface userObject { 11 | email: string 12 | password: string 13 | } 14 | 15 | export const initUser = (): userObject => ({ 16 | email: '', 17 | password: '', 18 | }) 19 | 20 | Next, create an index and add model object for easy access, example: index.ts 21 | 22 | /* 23 | Author: Eli Elad Elrom 24 | Website: https://EliElrom.com 25 | License: MIT License 26 | File: src/model/index.ts 27 | */ 28 | 29 | export * from './userObject' -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/model/historicalPriceObject.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | File: src/model/historicalPriceObject.ts 6 | */ 7 | 8 | // eslint-disable-next-line @typescript-eslint/naming-convention 9 | export interface historicalPriceObject { 10 | price: number 11 | } 12 | 13 | export const initHistoricalPrice = (): historicalPriceObject => ({ 14 | price: 0, 15 | }) 16 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/model/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | File: src/model/index.ts 6 | */ 7 | 8 | export * from './historicalPriceObject' 9 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/pages/README: -------------------------------------------------------------------------------- 1 | Pages components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component HomePage --type=page -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/recoil/atoms/README: -------------------------------------------------------------------------------- 1 | Recoil atoms goes here, example: userAtoms.ts; 2 | 3 | /* 4 | Author: Eli Elad Elrom 5 | Website: https://EliElrom.com 6 | License: MIT License 7 | File: src/recoil/atoms/userAtoms.ts 8 | */ 9 | 10 | import { atom } from 'recoil' 11 | import { initUser } from '../../model' 12 | 13 | export const userState = atom({ 14 | key: 'UserState', 15 | default: initUser(), 16 | }) -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/recoil/atoms/historicalPriceAtoms.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | File: src/recoil/atoms/historicalPriceAtoms.ts 6 | */ 7 | 8 | import { atom } from 'recoil' 9 | import { initHistoricalPrice } from '../../model' 10 | 11 | export const historicalPriceState = atom({ 12 | key: 'historicalPriceState', 13 | default: initHistoricalPrice(), 14 | }) 15 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/recoil/selectors/historicalPriceSelectors.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | File: src/model/historicalPriceSelectors.ts 6 | */ 7 | 8 | import { selector } from 'recoil' 9 | import * as d3 from 'd3' 10 | 11 | import { historicalPriceObject } from '../../model' 12 | 13 | export const getHistoricalPriceData = selector({ 14 | key: 'getHistoricalPriceData', 15 | get: async () => { 16 | return getData() 17 | }, 18 | }) 19 | 20 | const getData = () => 21 | new Promise((resolve) => 22 | d3 23 | .dsv(',', '/data/historicalPrice.csv', function results(d) { 24 | return { 25 | price: d.open, 26 | } 27 | }) 28 | .then(function results(data) { 29 | resolve((data as unknown) as historicalPriceObject[]) 30 | }) 31 | ) 32 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/redux/store.ts: -------------------------------------------------------------------------------- 1 | // src/redux/store.ts 2 | 3 | import { configureStore, combineReducers } from '@reduxjs/toolkit' 4 | 5 | const store = configureStore({ 6 | reducer: combineReducers({ 7 | // your reducers goes here 8 | }), 9 | }) 10 | 11 | export default store 12 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect' 6 | 7 | import { configure } from 'enzyme' 8 | import Adapter from 'enzyme-adapter-react-16' 9 | 10 | configure({ adapter: new Adapter() }) 11 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/widgets/HistogramWidget/HistogramWidget.scss: -------------------------------------------------------------------------------- 1 | .priceTableListDivWrapper { 2 | padding-top: 100px; 3 | width: 500px; 4 | height: 500px; 5 | } 6 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/widgets/HistogramWidget/HistogramWidget.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/widgets/HistogramWidget/HistogramWidget.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import { RecoilRoot } from 'recoil' 11 | import HistogramWidget from './HistogramWidget' 12 | 13 | describe('', () => { 14 | let component 15 | 16 | beforeEach(() => { 17 | component = shallow( 18 | 19 | 20 | 21 | ) 22 | }) 23 | 24 | test('It should mount', () => { 25 | expect(component.length).toBe(1) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/src/widgets/README: -------------------------------------------------------------------------------- 1 | components goes here, you can generate with generate-react-cli, examples; 2 | $ npx generate-react-cli component MyWidget --type=widget -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/templates/component/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/templates/component/test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import TemplateName from './TemplateName'; 4 | 5 | describe('', () => { 6 | let component; 7 | 8 | beforeEach(() => { 9 | component = shallow(); 10 | }); 11 | 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/templates/component/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import TemplateName from './TemplateName' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }); 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/templates/page/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/templates/recoil/component.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.tsx 6 | */ 7 | 8 | import React, { useEffect } from 'react' 9 | import './TemplateName.scss' 10 | // import { useRecoilValue } from 'recoil' 11 | 12 | const TemplateName = () /* or ( props : ITemplateNameProps ) */ => { 13 | const results: boolean = true // useRecoilValue( getMethod ) 14 | useEffect(() => { 15 | // TODO 16 | }) 17 | return ( 18 | <> 19 | {results ? ( 20 |
21 | TemplateName Loaded 22 |
23 | ) : ( 24 | <>Loading 25 | )} 26 | 27 | ) 28 | } 29 | 30 | /* 31 | interface ITemplateNameProps { 32 | // TODO 33 | } 34 | */ 35 | 36 | export default TemplateName 37 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/templates/recoil/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import { RecoilRoot } from 'recoil' 11 | import TemplateName from './TemplateName' 12 | 13 | describe('', () => { 14 | let component 15 | 16 | beforeEach(() => { 17 | component = shallow() 18 | }) 19 | 20 | test('It should mount', () => { 21 | expect(component.length).toBe(1) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/templates/templates/component/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/templates/templates/component/test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import TemplateName from './TemplateName'; 4 | 5 | describe('', () => { 6 | let component; 7 | 8 | beforeEach(() => { 9 | component = shallow(); 10 | }); 11 | 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/templates/templates/component/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import TemplateName from './TemplateName' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }); 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/templates/templates/page/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/templates/templates/recoil/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import { RecoilRoot } from 'recoil' 11 | import TemplateName from './TemplateName' 12 | 13 | describe('', () => { 14 | let component 15 | 16 | beforeEach(() => { 17 | component = shallow() 18 | }) 19 | 20 | test('It should mount', () => { 21 | expect(component.length).toBe(1) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /ch04-05/histogram-d3-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "es6", "dom", 6 | "dom", 7 | "dom.iterable", 8 | "esnext" 9 | ], 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitThis": true, 13 | "strictNullChecks": true, 14 | "allowJs": true, 15 | "skipLibCheck": true, 16 | "esModuleInterop": true, 17 | "allowSyntheticDefaultImports": true, 18 | "strict": true, 19 | "forceConsistentCasingInFileNames": true, 20 | "module": "esnext", 21 | "moduleResolution": "node", 22 | "resolveJsonModule": true, 23 | "isolatedModules": true, 24 | "noEmit": true, 25 | "jsx": "react" 26 | }, 27 | "include": [ 28 | "src", 29 | "e2e" 30 | ], 31 | "exclude": [ 32 | "**/templates/*", 33 | "**/node_modules/*" 34 | ] 35 | } 36 | 37 | -------------------------------------------------------------------------------- /ch06/world-map-chart/e2e/global.d.ts: -------------------------------------------------------------------------------- 1 | // globals defined in jest.config.js need to be included in this `d.ts` 2 | // file to avoid TS lint errors 3 | declare let SERVER_URL: string 4 | declare let JEST_TIMEOUT: number -------------------------------------------------------------------------------- /ch06/world-map-chart/e2e/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'jest-puppeteer', 3 | globals: { 4 | SERVER_URL: 'http://localhost:3000', 5 | JEST_TIMEOUT: 50000 6 | }, 7 | testRegex: './*\\.test\\.tsx$' 8 | } 9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE') -------------------------------------------------------------------------------- /ch06/world-map-chart/jest-puppeteer.config.js: -------------------------------------------------------------------------------- 1 | // jest-puppeteer.config.js 2 | module.exports = { 3 | server: { 4 | command: `yarn start`, 5 | port: 3000, 6 | launchTimeout: 20000, 7 | debug: true, 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /ch06/world-map-chart/public/data/coordinates.csv: -------------------------------------------------------------------------------- 1 | id,latitude,longitude 2 | 1,-73.9919,40.7529 3 | 2,-70.0007884457405,40.75509010847814 4 | -------------------------------------------------------------------------------- /ch06/world-map-chart/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch06/world-map-chart/public/favicon.ico -------------------------------------------------------------------------------- /ch06/world-map-chart/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch06/world-map-chart/public/logo192.png -------------------------------------------------------------------------------- /ch06/world-map-chart/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch06/world-map-chart/public/logo512.png -------------------------------------------------------------------------------- /ch06/world-map-chart/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /ch06/world-map-chart/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /ch06/world-map-chart/src/App.scss: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #ffffff; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ch06/world-map-chart/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | // src/App.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import App from './App' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1) 14 | }) 15 | }) 16 | 17 | /* 18 | Update this file once it's changed. For instance to check if a component you added 19 | include in App.tsx; 20 | 21 | import { shallow } from "enzyme"; 22 | import Calculator from "./components/SomeComponent/SomeComponent"; 23 | 24 | test('should render SomeComponent', () => { 25 | const wrapper = shallow(); 26 | const calculator = wrapper.find(SomeComponent); 27 | expect(calculator.exists()).toBe(true); 28 | }) 29 | */ 30 | -------------------------------------------------------------------------------- /ch06/world-map-chart/src/AppRouter.test.tsx: -------------------------------------------------------------------------------- 1 | // src/AppRouter.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import AppRouter from './AppRouter' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | 13 | test('renders without crashing', () => { 14 | expect(component.length).toBe(1) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /ch06/world-map-chart/src/assets/README: -------------------------------------------------------------------------------- 1 | Break down your assets by names: about, home, etc. -------------------------------------------------------------------------------- /ch06/world-map-chart/src/components/README: -------------------------------------------------------------------------------- 1 | Components goes here, you can generate with generate-react-cli, examples; 2 | $ npx generate-react-cli component UserButton 3 | $ npx generate-react-cli component Rectangle --type=d3class 4 | $ npx generate-react-cli component Rectangle --type=d3 5 | $ npx generate-react-cli component Login --type=recoil 6 | $ npx generate-react-cli component MyButton --type=materialui 7 | $ npx generate-react-cli component MyWidget --type=widget -------------------------------------------------------------------------------- /ch06/world-map-chart/src/components/WorldMap/WorldMap.scss: -------------------------------------------------------------------------------- 1 | .WorldMap { 2 | } 3 | -------------------------------------------------------------------------------- /ch06/world-map-chart/src/components/WorldMap/WorldMap.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/WorldMap/WorldMap.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import WorldMapAtlas from './WorldMapAtlas' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }) 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch06/world-map-chart/src/components/WorldMap/types.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/BasicScatterChart/types.ts 6 | */ 7 | 8 | import { Feature, Geometry } from 'geojson' 9 | 10 | export namespace Types { 11 | export type CoordinatesData = { 12 | id: number 13 | latitude: number 14 | longitude: number 15 | } 16 | 17 | export type MapObject = { 18 | mapFeatures: Array> 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch06/world-map-chart/src/features/README: -------------------------------------------------------------------------------- 1 | features components goes here. -------------------------------------------------------------------------------- /ch06/world-map-chart/src/hooks/README: -------------------------------------------------------------------------------- 1 | Hooks goes here. Check out some hooks examples here: 2 | https://github.com/EliEladElrom/react-tutorials -------------------------------------------------------------------------------- /ch06/world-map-chart/src/index.scss: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 4 | -webkit-font-smoothing: antialiased; 5 | -moz-osx-font-smoothing: grayscale; 6 | } 7 | 8 | code { 9 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; 10 | } 11 | -------------------------------------------------------------------------------- /ch06/world-map-chart/src/layout/README: -------------------------------------------------------------------------------- 1 | layout components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component BoxLayout --type=layout -------------------------------------------------------------------------------- /ch06/world-map-chart/src/model/README: -------------------------------------------------------------------------------- 1 | Place all your object model files here, for example: userObject.ts 2 | 3 | /* 4 | Author: Eli Elad Elrom 5 | Website: https://EliElrom.com 6 | License: MIT License 7 | File: src/model/userObject.ts 8 | */ 9 | 10 | export interface userObject { 11 | email: string 12 | password: string 13 | } 14 | 15 | export const initUser = (): userObject => ({ 16 | email: '', 17 | password: '', 18 | }) 19 | 20 | Next, create an index and add model object for easy access, example: index.ts 21 | 22 | /* 23 | Author: Eli Elad Elrom 24 | Website: https://EliElrom.com 25 | License: MIT License 26 | File: src/model/index.ts 27 | */ 28 | 29 | export * from './userObject' -------------------------------------------------------------------------------- /ch06/world-map-chart/src/pages/README: -------------------------------------------------------------------------------- 1 | Pages components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component HomePage --type=page -------------------------------------------------------------------------------- /ch06/world-map-chart/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /ch06/world-map-chart/src/recoil/atoms/README: -------------------------------------------------------------------------------- 1 | Recoil atoms goes here, example: userAtoms.ts; 2 | 3 | /* 4 | Author: Eli Elad Elrom 5 | Website: https://EliElrom.com 6 | License: MIT License 7 | File: src/recoil/atoms/userAtoms.ts 8 | */ 9 | 10 | import { atom } from 'recoil' 11 | import { initUser } from '../../model' 12 | 13 | export const userState = atom({ 14 | key: 'UserState', 15 | default: initUser(), 16 | }) -------------------------------------------------------------------------------- /ch06/world-map-chart/src/redux/store.ts: -------------------------------------------------------------------------------- 1 | // src/redux/store.ts 2 | 3 | import { configureStore, combineReducers } from '@reduxjs/toolkit' 4 | 5 | const store = configureStore({ 6 | reducer: combineReducers({ 7 | // your reducers goes here 8 | }), 9 | }) 10 | 11 | export default store 12 | -------------------------------------------------------------------------------- /ch06/world-map-chart/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect' 6 | 7 | import { configure } from 'enzyme' 8 | import Adapter from 'enzyme-adapter-react-16' 9 | 10 | configure({ adapter: new Adapter() }) 11 | -------------------------------------------------------------------------------- /ch06/world-map-chart/src/widgets/README: -------------------------------------------------------------------------------- 1 | components goes here, you can generate with generate-react-cli, examples; 2 | $ npx generate-react-cli component MyWidget --type=widget -------------------------------------------------------------------------------- /ch06/world-map-chart/templates/component/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch06/world-map-chart/templates/component/test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import TemplateName from './TemplateName'; 4 | 5 | describe('', () => { 6 | let component; 7 | 8 | beforeEach(() => { 9 | component = shallow(); 10 | }); 11 | 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ch06/world-map-chart/templates/component/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import TemplateName from './TemplateName' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }); 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch06/world-map-chart/templates/page/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch06/world-map-chart/templates/recoil/component.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.tsx 6 | */ 7 | 8 | import React, { useEffect } from 'react' 9 | import './TemplateName.scss' 10 | // import { useRecoilValue } from 'recoil' 11 | 12 | const TemplateName = () /* or ( props : ITemplateNameProps ) */ => { 13 | const results: boolean = true // useRecoilValue( getMethod ) 14 | useEffect(() => { 15 | // TODO 16 | }) 17 | return ( 18 | <> 19 | {results ? ( 20 |
21 | TemplateName Loaded 22 |
23 | ) : ( 24 | <>Loading 25 | )} 26 | 27 | ) 28 | } 29 | 30 | /* 31 | interface ITemplateNameProps { 32 | // TODO 33 | } 34 | */ 35 | 36 | export default TemplateName 37 | -------------------------------------------------------------------------------- /ch06/world-map-chart/templates/recoil/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import { RecoilRoot } from 'recoil' 11 | import TemplateName from './TemplateName' 12 | 13 | describe('', () => { 14 | let component 15 | 16 | beforeEach(() => { 17 | component = shallow() 18 | }) 19 | 20 | test('It should mount', () => { 21 | expect(component.length).toBe(1) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /ch06/world-map-chart/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "es6", "dom", 6 | "dom", 7 | "dom.iterable", 8 | "esnext" 9 | ], 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitThis": true, 13 | "strictNullChecks": true, 14 | "allowJs": true, 15 | "skipLibCheck": true, 16 | "esModuleInterop": true, 17 | "allowSyntheticDefaultImports": true, 18 | "strict": true, 19 | "forceConsistentCasingInFileNames": true, 20 | "module": "esnext", 21 | "moduleResolution": "node", 22 | "resolveJsonModule": true, 23 | "isolatedModules": true, 24 | "noEmit": true, 25 | "jsx": "react" 26 | }, 27 | "include": [ 28 | "src", 29 | "e2e" 30 | ], 31 | "exclude": [ 32 | "**/templates/*", 33 | "**/node_modules/*" 34 | ] 35 | } 36 | 37 | -------------------------------------------------------------------------------- /ch07/world-map-widget/e2e/global.d.ts: -------------------------------------------------------------------------------- 1 | // globals defined in jest.config.js need to be included in this `d.ts` 2 | // file to avoid TS lint errors 3 | declare let SERVER_URL: string 4 | declare let JEST_TIMEOUT: number -------------------------------------------------------------------------------- /ch07/world-map-widget/e2e/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'jest-puppeteer', 3 | globals: { 4 | SERVER_URL: 'http://localhost:3000', 5 | JEST_TIMEOUT: 50000 6 | }, 7 | testRegex: './*\\.test\\.tsx$' 8 | } 9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE') -------------------------------------------------------------------------------- /ch07/world-map-widget/jest-puppeteer.config.js: -------------------------------------------------------------------------------- 1 | // jest-puppeteer.config.js 2 | module.exports = { 3 | server: { 4 | command: `yarn start`, 5 | port: 3000, 6 | launchTimeout: 20000, 7 | debug: true, 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/Allocadia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/Allocadia.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/CiaoBellaGelato.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/CiaoBellaGelato.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/EsteeLauder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/EsteeLauder.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/KickApps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/KickApps.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/MTV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/MTV.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/MotionBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/MotionBox.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/NBC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/NBC.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/README: -------------------------------------------------------------------------------- 1 | LOGOs goes here -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/RockSoul.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/RockSoul.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/UPMC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/UPMC.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/Vitaminwater.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/Vitaminwater.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/WeightWatchers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/WeightWatchers.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/att.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/att.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/chatand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/chatand.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/digitallyspeaking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/digitallyspeaking.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/friesens.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/friesens.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/gantto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/gantto.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/gdconf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/gdconf.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/hbo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/hbo.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/iheart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/iheart.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/monbijouparis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/monbijouparis.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/ritani.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/ritani.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/clients-logo/surgiview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/clients-logo/surgiview.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/data/client-list.csv: -------------------------------------------------------------------------------- 1 | id,name,logo,description,address,city,state,country,latitude,longitude,website 2 | 1,Company,company.png,description,address,New York,NY,USA,-70,40,https://company.com/ -------------------------------------------------------------------------------- /ch07/world-map-widget/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/favicon.ico -------------------------------------------------------------------------------- /ch07/world-map-widget/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/logo192.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/public/logo512.png -------------------------------------------------------------------------------- /ch07/world-map-widget/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /ch07/world-map-widget/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/App.scss: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #ffffff; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | // src/App.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import App from './App' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1) 14 | }) 15 | }) 16 | 17 | /* 18 | Update this file once it's changed. For instance to check if a component you added 19 | include in App.tsx; 20 | 21 | import { shallow } from "enzyme"; 22 | import Calculator from "./components/SomeComponent/SomeComponent"; 23 | 24 | test('should render SomeComponent', () => { 25 | const wrapper = shallow(); 26 | const calculator = wrapper.find(SomeComponent); 27 | expect(calculator.exists()).toBe(true); 28 | }) 29 | */ 30 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/App.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/App.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import './App.scss' 10 | import ClientsWidget from './widgets/ClientsWidget/ClientsWidget' 11 | 12 | function App() { 13 | return ( 14 |
15 |
16 | 17 |
18 |
19 | ) 20 | } 21 | 22 | export default App 23 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/AppRouter.test.tsx: -------------------------------------------------------------------------------- 1 | // src/AppRouter.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import AppRouter from './AppRouter' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | 13 | test('renders without crashing', () => { 14 | expect(component.length).toBe(1) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/assets/README: -------------------------------------------------------------------------------- 1 | Break down your assets by names: about, home, etc. -------------------------------------------------------------------------------- /ch07/world-map-widget/src/assets/about/EliEladElrom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch07/world-map-widget/src/assets/about/EliEladElrom.jpg -------------------------------------------------------------------------------- /ch07/world-map-widget/src/components/ClientList/ClientList.scss: -------------------------------------------------------------------------------- 1 | .ClientList { 2 | } 3 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/components/ClientList/ClientList.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/ClientList/ClientList.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import { RecoilRoot } from 'recoil' 11 | import ClientList from './ClientList' 12 | 13 | describe('', () => { 14 | let component 15 | 16 | beforeEach(() => { 17 | component = shallow( 18 | 19 | 20 | 21 | ) 22 | }) 23 | 24 | test('It should mount', () => { 25 | expect(component.length).toBe(1) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/components/ClientListDetail/ClientListDetail.scss: -------------------------------------------------------------------------------- 1 | .ClientListDetail { 2 | } 3 | 4 | .about-image { 5 | padding-left: 20px; 6 | padding-right: 20px; 7 | width: 100px; 8 | -webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */ 9 | filter: grayscale(100%); 10 | } 11 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/components/ClientListDetail/ClientListDetail.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/ClientListDetail/ClientListDetail.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import { RecoilRoot } from 'recoil' 11 | import ClientListDetail from './ClientListDetail' 12 | 13 | describe('', () => { 14 | let component 15 | 16 | beforeEach(() => { 17 | component = shallow( 18 | 19 | 20 | 21 | ) 22 | }) 23 | 24 | test('It should mount', () => { 25 | expect(component.length).toBe(1) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/components/PulsatingCircle/PulsatingCircle.scss: -------------------------------------------------------------------------------- 1 | .PulsatingCircle { 2 | } 3 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/components/PulsatingCircle/PulsatingCircle.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { shallow } from 'enzyme' 3 | import PulsatingCircle from './PulsatingCircle' 4 | 5 | describe('', () => { 6 | let component 7 | 8 | beforeEach(() => { 9 | component = shallow() 10 | }) 11 | 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1) 14 | }) 15 | }) 16 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/components/README: -------------------------------------------------------------------------------- 1 | Components goes here, you can generate with generate-react-cli, examples; 2 | $ npx generate-react-cli component UserButton 3 | $ npx generate-react-cli component Rectangle --type=d3class 4 | $ npx generate-react-cli component Rectangle --type=d3 5 | $ npx generate-react-cli component Login --type=recoil 6 | $ npx generate-react-cli component MyButton --type=materialui 7 | $ npx generate-react-cli component MyWidget --type=widget -------------------------------------------------------------------------------- /ch07/world-map-widget/src/components/WorldMap/WorldMap.scss: -------------------------------------------------------------------------------- 1 | .WorldMap { 2 | } 3 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/components/WorldMap/types.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/BasicScatterChart/types.ts 6 | */ 7 | 8 | import { Feature, Geometry } from 'geojson' 9 | 10 | export namespace Types { 11 | export type ClientData = { 12 | id: number 13 | latitude: number 14 | longitude: number 15 | name: string 16 | logo: string 17 | description: string 18 | address: string 19 | city: string 20 | state: string 21 | country: string 22 | website: string 23 | } 24 | 25 | export type MapObject = { 26 | mapFeatures: Array> 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/features/README: -------------------------------------------------------------------------------- 1 | features components goes here. -------------------------------------------------------------------------------- /ch07/world-map-widget/src/hooks/README: -------------------------------------------------------------------------------- 1 | Hooks goes here. Check out some hooks examples here: 2 | https://github.com/EliEladElrom/react-tutorials -------------------------------------------------------------------------------- /ch07/world-map-widget/src/index.scss: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 4 | -webkit-font-smoothing: antialiased; 5 | -moz-osx-font-smoothing: grayscale; 6 | } 7 | 8 | code { 9 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; 10 | } 11 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/layout/README: -------------------------------------------------------------------------------- 1 | layout components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component BoxLayout --type=layout -------------------------------------------------------------------------------- /ch07/world-map-widget/src/model/README: -------------------------------------------------------------------------------- 1 | Place all your object model files here, for example: userObject.ts 2 | 3 | /* 4 | Author: Eli Elad Elrom 5 | Website: https://EliElrom.com 6 | License: MIT License 7 | File: src/model/userObject.ts 8 | */ 9 | 10 | export interface userObject { 11 | email: string 12 | password: string 13 | } 14 | 15 | export const initUser = (): userObject => ({ 16 | email: '', 17 | password: '', 18 | }) 19 | 20 | Next, create an index and add model object for easy access, example: index.ts 21 | 22 | /* 23 | Author: Eli Elad Elrom 24 | Website: https://EliElrom.com 25 | License: MIT License 26 | File: src/model/index.ts 27 | */ 28 | 29 | export * from './userObject' -------------------------------------------------------------------------------- /ch07/world-map-widget/src/model/clientsObject.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | File: src/model/clientsObject.ts 6 | */ 7 | 8 | // eslint-disable-next-line @typescript-eslint/naming-convention 9 | export interface clientsObject { 10 | id: number 11 | latitude: number 12 | longitude: number 13 | name: string 14 | logo: string 15 | description: string 16 | address: string 17 | city: string 18 | state: string 19 | country: string 20 | website: string 21 | } 22 | 23 | export const initClientsObject = (): clientsObject => ({ 24 | id: -1, 25 | latitude: 0, 26 | longitude: 0, 27 | name: '', 28 | logo: '', 29 | description: '', 30 | address: '', 31 | city: '', 32 | state: '', 33 | country: '', 34 | website: '', 35 | }) 36 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/model/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/model/index.ts 6 | */ 7 | 8 | export * from './mapObject' 9 | export * from './clientsObject' 10 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/model/mapObject.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | File: src/model/mapObject.ts 6 | */ 7 | 8 | import { Feature, Geometry } from 'geojson' 9 | 10 | // eslint-disable-next-line @typescript-eslint/naming-convention 11 | export interface mapObject { 12 | mapFeatures: Array> 13 | } 14 | 15 | export const initMapObject = (): mapObject => ({ 16 | mapFeatures: Array>(), 17 | }) 18 | 19 | export const setMapObject = (data: Array>): mapObject => ({ 20 | mapFeatures: data, 21 | }) 22 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/pages/README: -------------------------------------------------------------------------------- 1 | Pages components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component HomePage --type=page -------------------------------------------------------------------------------- /ch07/world-map-widget/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/recoil/atoms/README: -------------------------------------------------------------------------------- 1 | Recoil atoms goes here, example: userAtoms.ts; 2 | 3 | /* 4 | Author: Eli Elad Elrom 5 | Website: https://EliElrom.com 6 | License: MIT License 7 | File: src/recoil/atoms/userAtoms.ts 8 | */ 9 | 10 | import { atom } from 'recoil' 11 | import { initUser } from '../../model' 12 | 13 | export const userState = atom({ 14 | key: 'UserState', 15 | default: initUser(), 16 | }) -------------------------------------------------------------------------------- /ch07/world-map-widget/src/recoil/selectors/clientsSelectors.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | File: src/recoil/selectors/clientsSelectors.ts 6 | */ 7 | 8 | import { selector } from 'recoil' 9 | import * as d3 from 'd3' 10 | 11 | import { clientsObject } from '../../model' 12 | 13 | export const getPreviousClientListData = selector({ 14 | key: 'GetPreviousClientListData', 15 | get: async () => { 16 | return getData() 17 | }, 18 | }) 19 | 20 | const getData = () => 21 | new Promise((resolve) => 22 | d3 23 | .dsv(',', '/data/client-list.csv', function results(d) { 24 | return d 25 | }) 26 | .then(function results(data) { 27 | resolve((data as unknown) as clientsObject[]) 28 | }) 29 | ) 30 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/redux/store.ts: -------------------------------------------------------------------------------- 1 | // src/redux/store.ts 2 | 3 | import { configureStore, combineReducers } from '@reduxjs/toolkit' 4 | 5 | const store = configureStore({ 6 | reducer: combineReducers({ 7 | // your reducers goes here 8 | }), 9 | }) 10 | 11 | export default store 12 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect' 6 | 7 | import { configure } from 'enzyme' 8 | import Adapter from 'enzyme-adapter-react-16' 9 | 10 | configure({ adapter: new Adapter() }) 11 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/widgets/ClientsWidget/ClientsWidget.scss: -------------------------------------------------------------------------------- 1 | .PreviousClients { 2 | } 3 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/widgets/ClientsWidget/ClientsWidget.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/ClientsWidget/ClientsWidget.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import { RecoilRoot } from 'recoil' 11 | import ClientsWidget from './ClientsWidget' 12 | 13 | describe('', () => { 14 | let component 15 | 16 | beforeEach(() => { 17 | component = shallow( 18 | 19 | 20 | 21 | ) 22 | }) 23 | 24 | test('It should mount', () => { 25 | expect(component.length).toBe(1) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /ch07/world-map-widget/src/widgets/README: -------------------------------------------------------------------------------- 1 | components goes here, you can generate with generate-react-cli, examples; 2 | $ npx generate-react-cli component MyWidget --type=widget -------------------------------------------------------------------------------- /ch07/world-map-widget/templates/component/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch07/world-map-widget/templates/component/test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import TemplateName from './TemplateName'; 4 | 5 | describe('', () => { 6 | let component; 7 | 8 | beforeEach(() => { 9 | component = shallow(); 10 | }); 11 | 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ch07/world-map-widget/templates/component/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import TemplateName from './TemplateName' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }); 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch07/world-map-widget/templates/page/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch07/world-map-widget/templates/recoil/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import { RecoilRoot } from 'recoil' 11 | import TemplateName from './TemplateName' 12 | 13 | describe('', () => { 14 | let component 15 | 16 | beforeEach(() => { 17 | component = shallow() 18 | }) 19 | 20 | test('It should mount', () => { 21 | expect(component.length).toBe(1) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /ch07/world-map-widget/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "es6", "dom", 6 | "dom", 7 | "dom.iterable", 8 | "esnext" 9 | ], 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitThis": true, 13 | "strictNullChecks": true, 14 | "allowJs": true, 15 | "skipLibCheck": true, 16 | "esModuleInterop": true, 17 | "allowSyntheticDefaultImports": true, 18 | "strict": true, 19 | "forceConsistentCasingInFileNames": true, 20 | "module": "esnext", 21 | "moduleResolution": "node", 22 | "resolveJsonModule": true, 23 | "isolatedModules": true, 24 | "noEmit": true, 25 | "jsx": "react" 26 | }, 27 | "include": [ 28 | "src", 29 | "e2e" 30 | ], 31 | "exclude": [ 32 | "**/templates/*", 33 | "**/node_modules/*" 34 | ] 35 | } 36 | 37 | -------------------------------------------------------------------------------- /ch08/bubble-chart/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | BROWSER=none 3 | -------------------------------------------------------------------------------- /ch08/bubble-chart/.eslintignore: -------------------------------------------------------------------------------- 1 | build/* 2 | public/* 3 | docs/* 4 | templates/* 5 | src/react-app-env.d.ts 6 | src/serviceWorker.ts 7 | e2e/jest.config.js 8 | e2e/puppeteer_standalone.js 9 | jest-puppeteer.config.js -------------------------------------------------------------------------------- /ch08/bubble-chart/.gitignore: -------------------------------------------------------------------------------- 1 | # misc 2 | .DS_Store 3 | package-lock.json 4 | yarn-error.log 5 | yarn.lock 6 | docs 7 | 8 | # IDEs 9 | .vscode 10 | .idea 11 | 12 | # dependencies 13 | /node_modules 14 | /.pnp 15 | .pnp.js 16 | 17 | # testing 18 | /coverage 19 | .nyc_output 20 | 21 | # production 22 | /build 23 | 24 | # misc 25 | .DS_Store 26 | .env.local 27 | .env.development.local 28 | .env.test.local 29 | .env.production.local 30 | 31 | npm-debug.log* 32 | yarn-debug.log* 33 | yarn-error.log* 34 | -------------------------------------------------------------------------------- /ch08/bubble-chart/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "printWidth": 200, 4 | "semi": false, 5 | "singleQuote": true, 6 | "tabWidth": 2 7 | } 8 | 9 | -------------------------------------------------------------------------------- /ch08/bubble-chart/e2e/global.d.ts: -------------------------------------------------------------------------------- 1 | // globals defined in jest.config.js need to be included in this `d.ts` 2 | // file to avoid TS lint errors 3 | declare let SERVER_URL: string 4 | declare let JEST_TIMEOUT: number -------------------------------------------------------------------------------- /ch08/bubble-chart/e2e/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'jest-puppeteer', 3 | globals: { 4 | SERVER_URL: 'http://localhost:3000', 5 | JEST_TIMEOUT: 50000 6 | }, 7 | testRegex: './*\\.test\\.tsx$' 8 | } 9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE') -------------------------------------------------------------------------------- /ch08/bubble-chart/jest-puppeteer.config.js: -------------------------------------------------------------------------------- 1 | // jest-puppeteer.config.js 2 | module.exports = { 3 | server: { 4 | command: `yarn start`, 5 | port: 3000, 6 | launchTimeout: 20000, 7 | debug: true, 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /ch08/bubble-chart/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch08/bubble-chart/public/favicon.ico -------------------------------------------------------------------------------- /ch08/bubble-chart/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch08/bubble-chart/public/logo192.png -------------------------------------------------------------------------------- /ch08/bubble-chart/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch08/bubble-chart/public/logo512.png -------------------------------------------------------------------------------- /ch08/bubble-chart/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /ch08/bubble-chart/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /ch08/bubble-chart/src/App.scss: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .appButtonFixed { 17 | position: fixed; 18 | left: -100px; 19 | top: 60px; 20 | } 21 | 22 | .App-header { 23 | background-color: #ffffff; 24 | min-height: 100vh; 25 | display: flex; 26 | flex-direction: column; 27 | align-items: center; 28 | justify-content: center; 29 | font-size: calc(10px + 2vmin); 30 | color: white; 31 | } 32 | 33 | .App-link { 34 | color: #61dafb; 35 | } 36 | 37 | @keyframes App-logo-spin { 38 | from { 39 | transform: rotate(0deg); 40 | } 41 | to { 42 | transform: rotate(360deg); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ch08/bubble-chart/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | // src/App.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import App from './App' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1) 14 | }) 15 | }) 16 | 17 | /* 18 | Update this file once it's changed. For instance to check if a component you added 19 | include in App.tsx; 20 | 21 | import { shallow } from "enzyme"; 22 | import Calculator from "./components/SomeComponent/SomeComponent"; 23 | 24 | test('should render SomeComponent', () => { 25 | const wrapper = shallow(); 26 | const calculator = wrapper.find(SomeComponent); 27 | expect(calculator.exists()).toBe(true); 28 | }) 29 | */ 30 | -------------------------------------------------------------------------------- /ch08/bubble-chart/src/AppRouter.test.tsx: -------------------------------------------------------------------------------- 1 | // src/AppRouter.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import AppRouter from './AppRouter' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | 13 | test('renders without crashing', () => { 14 | expect(component.length).toBe(1) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /ch08/bubble-chart/src/assets/README: -------------------------------------------------------------------------------- 1 | Break down your assets by names: about, home, etc. -------------------------------------------------------------------------------- /ch08/bubble-chart/src/components/BubbleChart/BubbleChart.scss: -------------------------------------------------------------------------------- 1 | .buttonFixed { 2 | position: fixed; 3 | top: 25px; 4 | left: 25px; 5 | } 6 | 7 | .bubbleText { 8 | text-shadow: 1px 0 0 darkslategrey, 0 1px 0 darkslategrey, -1px 0 0 darkslategrey, 0 -1px 0 darkslategrey; 9 | } 10 | -------------------------------------------------------------------------------- /ch08/bubble-chart/src/components/BubbleChart/BubbleChart.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/BubbleChart/BubbleChart.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import { RecoilRoot } from 'recoil' 11 | import BubbleChart from './BubbleChart' 12 | 13 | describe('', () => { 14 | let component 15 | 16 | beforeEach(() => { 17 | component = shallow( 18 | 19 | 20 | 21 | ) 22 | }) 23 | 24 | test('It should mount', () => { 25 | expect(component.length).toBe(1) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /ch08/bubble-chart/src/components/BubbleChart/types.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/BubbleChart/types.ts 6 | */ 7 | 8 | export namespace Types { 9 | export type Data = { 10 | id: number 11 | name: string 12 | size: number 13 | fillColor: string 14 | } 15 | 16 | export type ForceData = { 17 | size: number 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch08/bubble-chart/src/components/README: -------------------------------------------------------------------------------- 1 | Components goes here, you can generate with generate-react-cli, examples; 2 | $ npx generate-react-cli component UserButton 3 | $ npx generate-react-cli component Rectangle --type=d3class 4 | $ npx generate-react-cli component Rectangle --type=d3 5 | $ npx generate-react-cli component Login --type=recoil 6 | $ npx generate-react-cli component MyButton --type=materialui 7 | $ npx generate-react-cli component MyWidget --type=widget -------------------------------------------------------------------------------- /ch08/bubble-chart/src/features/README: -------------------------------------------------------------------------------- 1 | features components goes here. -------------------------------------------------------------------------------- /ch08/bubble-chart/src/hooks/README: -------------------------------------------------------------------------------- 1 | Hooks goes here. Check out some hooks examples here: 2 | https://github.com/EliEladElrom/react-tutorials -------------------------------------------------------------------------------- /ch08/bubble-chart/src/index.scss: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 4 | -webkit-font-smoothing: antialiased; 5 | -moz-osx-font-smoothing: grayscale; 6 | } 7 | 8 | code { 9 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; 10 | } 11 | -------------------------------------------------------------------------------- /ch08/bubble-chart/src/layout/README: -------------------------------------------------------------------------------- 1 | layout components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component BoxLayout --type=layout -------------------------------------------------------------------------------- /ch08/bubble-chart/src/model/README: -------------------------------------------------------------------------------- 1 | Place all your object model files here, for example: userObject.ts 2 | 3 | /* 4 | Author: Eli Elad Elrom 5 | Website: https://EliElrom.com 6 | License: MIT License 7 | File: src/model/userObject.ts 8 | */ 9 | 10 | export interface userObject { 11 | email: string 12 | password: string 13 | } 14 | 15 | export const initUser = (): userObject => ({ 16 | email: '', 17 | password: '', 18 | }) 19 | 20 | Next, create an index and add model object for easy access, example: index.ts 21 | 22 | /* 23 | Author: Eli Elad Elrom 24 | Website: https://EliElrom.com 25 | License: MIT License 26 | File: src/model/index.ts 27 | */ 28 | 29 | export * from './userObject' -------------------------------------------------------------------------------- /ch08/bubble-chart/src/pages/README: -------------------------------------------------------------------------------- 1 | Pages components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component HomePage --type=page -------------------------------------------------------------------------------- /ch08/bubble-chart/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /ch08/bubble-chart/src/recoil/atoms/README: -------------------------------------------------------------------------------- 1 | Recoil atoms goes here, example: userAtoms.ts; 2 | 3 | /* 4 | Author: Eli Elad Elrom 5 | Website: https://EliElrom.com 6 | License: MIT License 7 | File: src/recoil/atoms/userAtoms.ts 8 | */ 9 | 10 | import { atom } from 'recoil' 11 | import { initUser } from '../../model' 12 | 13 | export const userState = atom({ 14 | key: 'UserState', 15 | default: initUser(), 16 | }) -------------------------------------------------------------------------------- /ch08/bubble-chart/src/redux/store.ts: -------------------------------------------------------------------------------- 1 | // src/redux/store.ts 2 | 3 | import { configureStore, combineReducers } from '@reduxjs/toolkit' 4 | 5 | const store = configureStore({ 6 | reducer: combineReducers({ 7 | // your reducers goes here 8 | }), 9 | }) 10 | 11 | export default store 12 | -------------------------------------------------------------------------------- /ch08/bubble-chart/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect' 6 | 7 | import { configure } from 'enzyme' 8 | import Adapter from 'enzyme-adapter-react-16' 9 | 10 | configure({ adapter: new Adapter() }) 11 | -------------------------------------------------------------------------------- /ch08/bubble-chart/src/widgets/README: -------------------------------------------------------------------------------- 1 | components goes here, you can generate with generate-react-cli, examples; 2 | $ npx generate-react-cli component MyWidget --type=widget -------------------------------------------------------------------------------- /ch08/bubble-chart/templates/component/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch08/bubble-chart/templates/component/test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import TemplateName from './TemplateName'; 4 | 5 | describe('', () => { 6 | let component; 7 | 8 | beforeEach(() => { 9 | component = shallow(); 10 | }); 11 | 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ch08/bubble-chart/templates/component/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import TemplateName from './TemplateName' 11 | 12 | describe('', () => { 13 | let component 14 | 15 | beforeEach(() => { 16 | component = shallow() 17 | }); 18 | 19 | test('It should mount', () => { 20 | expect(component.length).toBe(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /ch08/bubble-chart/templates/page/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /ch08/bubble-chart/templates/recoil/component.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.tsx 6 | */ 7 | 8 | import React, { useEffect } from 'react' 9 | import './TemplateName.scss' 10 | // import { useRecoilValue } from 'recoil' 11 | 12 | const TemplateName = () /* or ( props : ITemplateNameProps ) */ => { 13 | const results: boolean = true // useRecoilValue( getMethod ) 14 | useEffect(() => { 15 | // TODO 16 | }) 17 | return ( 18 | <> 19 | {results ? ( 20 |
21 | TemplateName Loaded 22 |
23 | ) : ( 24 | <>Loading 25 | )} 26 | 27 | ) 28 | } 29 | 30 | /* 31 | interface ITemplateNameProps { 32 | // TODO 33 | } 34 | */ 35 | 36 | export default TemplateName 37 | -------------------------------------------------------------------------------- /ch08/bubble-chart/templates/recoil/test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/TemplateName/TemplateName.test.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import { shallow } from 'enzyme' 10 | import { RecoilRoot } from 'recoil' 11 | import TemplateName from './TemplateName' 12 | 13 | describe('', () => { 14 | let component 15 | 16 | beforeEach(() => { 17 | component = shallow() 18 | }) 19 | 20 | test('It should mount', () => { 21 | expect(component.length).toBe(1) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /ch08/bubble-chart/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "es6", "dom", 6 | "dom", 7 | "dom.iterable", 8 | "esnext" 9 | ], 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitThis": true, 13 | "strictNullChecks": true, 14 | "allowJs": true, 15 | "skipLibCheck": true, 16 | "esModuleInterop": true, 17 | "allowSyntheticDefaultImports": true, 18 | "strict": true, 19 | "forceConsistentCasingInFileNames": true, 20 | "module": "esnext", 21 | "moduleResolution": "node", 22 | "resolveJsonModule": true, 23 | "isolatedModules": true, 24 | "noEmit": true, 25 | "jsx": "react" 26 | }, 27 | "include": [ 28 | "src", 29 | "e2e" 30 | ], 31 | "exclude": [ 32 | "**/templates/*", 33 | "**/node_modules/*" 34 | ] 35 | } 36 | 37 | -------------------------------------------------------------------------------- /ch09/force-chart/e2e/global.d.ts: -------------------------------------------------------------------------------- 1 | // globals defined in jest.config.js need to be included in this `d.ts` 2 | // file to avoid TS lint errors 3 | declare let SERVER_URL: string 4 | declare let JEST_TIMEOUT: number -------------------------------------------------------------------------------- /ch09/force-chart/e2e/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'jest-puppeteer', 3 | globals: { 4 | SERVER_URL: 'http://localhost:3000', 5 | JEST_TIMEOUT: 50000 6 | }, 7 | testRegex: './*\\.test\\.tsx$' 8 | } 9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE') -------------------------------------------------------------------------------- /ch09/force-chart/jest-puppeteer.config.js: -------------------------------------------------------------------------------- 1 | // jest-puppeteer.config.js 2 | module.exports = { 3 | server: { 4 | command: `yarn start`, 5 | port: 3000, 6 | launchTimeout: 20000, 7 | debug: true, 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /ch09/force-chart/public/data/power_network.json: -------------------------------------------------------------------------------- 1 | { 2 | "results": [ 3 | { 4 | "nodes": [ 5 | { 6 | "name": "JavaScript / TypeScript", 7 | "radiusSize": 20, 8 | "fillColor": "#fa6502" 9 | } 10 | ], 11 | "links": [ 12 | { 13 | "source": "Erase a character", 14 | "target": "JavaScript / TypeScript", 15 | "value": "How would you erase a character from a string?" 16 | } 17 | ] 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /ch09/force-chart/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch09/force-chart/public/favicon.ico -------------------------------------------------------------------------------- /ch09/force-chart/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch09/force-chart/public/logo192.png -------------------------------------------------------------------------------- /ch09/force-chart/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/integrating-d3.js-with-react/f4cdad62693a1d576e9f6371be7fb4640d71e264/ch09/force-chart/public/logo512.png -------------------------------------------------------------------------------- /ch09/force-chart/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /ch09/force-chart/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /ch09/force-chart/src/App.scss: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #ffffff; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ch09/force-chart/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | // src/App.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import App from './App' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1) 14 | }) 15 | }) 16 | 17 | /* 18 | Update this file once it's changed. For instance to check if a component you added 19 | include in App.tsx; 20 | 21 | import { shallow } from "enzyme"; 22 | import Calculator from "./components/SomeComponent/SomeComponent"; 23 | 24 | test('should render SomeComponent', () => { 25 | const wrapper = shallow(); 26 | const calculator = wrapper.find(SomeComponent); 27 | expect(calculator.exists()).toBe(true); 28 | }) 29 | */ 30 | -------------------------------------------------------------------------------- /ch09/force-chart/src/App.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/App.tsx 6 | */ 7 | 8 | import React from 'react' 9 | import './App.scss' 10 | import NetworksWidget from './widgets/NetworksWidget/NetworksWidget' 11 | 12 | function App() { 13 | return ( 14 |
15 |
16 | 17 |
18 |
19 | ) 20 | } 21 | 22 | export default App 23 | -------------------------------------------------------------------------------- /ch09/force-chart/src/AppRouter.test.tsx: -------------------------------------------------------------------------------- 1 | // src/AppRouter.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import AppRouter from './AppRouter' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | 13 | test('renders without crashing', () => { 14 | expect(component.length).toBe(1) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /ch09/force-chart/src/assets/README: -------------------------------------------------------------------------------- 1 | Break down your assets by names: about, home, etc. -------------------------------------------------------------------------------- /ch09/force-chart/src/components/README: -------------------------------------------------------------------------------- 1 | Components goes here, you can generate with generate-react-cli, examples; 2 | $ npx generate-react-cli component UserButton 3 | $ npx generate-react-cli component Rectangle --type=d3class 4 | $ npx generate-react-cli component Rectangle --type=d3 5 | $ npx generate-react-cli component Login --type=recoil 6 | $ npx generate-react-cli component MyButton --type=materialui 7 | $ npx generate-react-cli component MyWidget --type=widget -------------------------------------------------------------------------------- /ch09/force-chart/src/components/SimpleForceGraph/Circle.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/SimpleForceGraph/Circle.tsx 6 | */ 7 | 8 | import * as React from 'react' 9 | import * as d3 from 'd3' 10 | import { Types } from './types' 11 | 12 | export default class Circle extends React.PureComponent<{ node: Types.node }> { 13 | ref: SVGCircleElement | undefined 14 | 15 | componentDidMount() { 16 | if (this.ref) d3.select(this.ref).data([this.props.node]) 17 | } 18 | 19 | render() { 20 | return ( 21 | // eslint-disable-next-line no-return-assign 22 | (this.ref = ref)}> 23 | {this.props.node.name} 24 | 25 | ) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ch09/force-chart/src/components/SimpleForceGraph/Labels.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eli Elad Elrom 3 | Website: https://EliElrom.com 4 | License: MIT License 5 | Component: src/component/SimpleForceGraph/Labels.tsx 6 | */ 7 | 8 | import * as React from 'react' 9 | import { Dispatch, SetStateAction } from 'react' 10 | import Label from './Label' 11 | import { Types } from './types' 12 | 13 | const uuid = require('react-uuid') 14 | 15 | export default class Labels extends React.PureComponent { 16 | render() { 17 | const labels = this.props.nodes.map((node: Types.node) => { 18 | return