├── .all-contributorsrc
├── .eslintignore
├── .eslintrc.json
├── .gitattributes
├── .github
└── workflows
│ ├── node.js.yml
│ └── storybook.yml
├── .gitignore
├── .npmrc
├── .prettierrc.cjs
├── .storybook
├── main.ts
├── manager.ts
├── preview.css
└── preview.tsx
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── __test__
└── data
│ ├── jsonp.test.html
│ └── response.test.html
├── index.html
├── package-lock.json
├── package.json
├── sample
├── demo.tsx
└── sample.png
├── sonar-project.properties
├── src
├── components
│ ├── Book.module.css
│ ├── Book.test.tsx
│ ├── Book.tsx
│ ├── BookList.module.css
│ ├── BookList.test.tsx
│ ├── BookList.tsx
│ ├── Cover.module.css
│ ├── Cover.test.tsx
│ ├── Cover.tsx
│ ├── GoodreadsBookshelf.module.css
│ ├── GoodreadsBookshelf.test.tsx
│ ├── GoodreadsBookshelf.tsx
│ ├── Loader.tsx
│ ├── Placeholder.test.tsx
│ ├── Placeholder.tsx
│ ├── Rating.test.tsx
│ └── Rating.tsx
├── globals.d.ts
├── hooks
│ ├── useGoodreadsShelf.test.tsx
│ └── useGoodreadsShelf.ts
├── index.ts
├── types
│ ├── api.ts
│ ├── book.ts
│ ├── index.ts
│ └── props.ts
└── util
│ ├── api.test.ts
│ ├── api.ts
│ ├── get-url.ts
│ ├── html-utils.test.ts
│ ├── html-utils.ts
│ └── index.ts
├── stories
├── 0-GoodreadsBookshelf.stories.tsx
└── GoodreadBookshelf.mdx
├── tsconfig.json
├── vite.config.ts
└── vitest.setup.ts
/.all-contributorsrc:
--------------------------------------------------------------------------------
1 | {
2 | "files": [
3 | "README.md"
4 | ],
5 | "imageSize": 100,
6 | "commit": false,
7 | "commitType": "docs",
8 | "commitConvention": "angular",
9 | "contributors": [
10 | {
11 | "login": "kylekarpack",
12 | "name": "Kyle",
13 | "avatar_url": "https://avatars.githubusercontent.com/u/2429580?v=4",
14 | "profile": "http://www.kylekarpack.com",
15 | "contributions": [
16 | "code"
17 | ]
18 | },
19 | {
20 | "login": "thedaviddias",
21 | "name": "David Dias",
22 | "avatar_url": "https://avatars.githubusercontent.com/u/237229?v=4",
23 | "profile": "https://thedaviddias.dev",
24 | "contributions": [
25 | "a11y"
26 | ]
27 | },
28 | {
29 | "login": "eligundry",
30 | "name": "Eli Gundry",
31 | "avatar_url": "https://avatars.githubusercontent.com/u/439936?v=4",
32 | "profile": "https://eligundry.com/",
33 | "contributions": [
34 | "code"
35 | ]
36 | },
37 | {
38 | "login": "BassemMohamed",
39 | "name": "Bassem Ibrahim",
40 | "avatar_url": "https://avatars.githubusercontent.com/u/17043634?v=4",
41 | "contributions": [
42 | "code"
43 | ]
44 | }
45 | ],
46 | "contributorsPerLine": 7,
47 | "skipCi": true,
48 | "repoType": "github",
49 | "repoHost": "https://github.com",
50 | "projectName": "react-goodreads-shelf",
51 | "projectOwner": "kylekarpack"
52 | }
53 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | build/
2 | dist/
3 | stories/
4 | jest.setup.js
5 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "./node_modules/gts/",
4 | "plugin:storybook/recommended"
5 | ],
6 | "rules": {
7 | "quotes": [
8 | "warn",
9 | "double"
10 | ]
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Exclude some test files from language stats
5 | __test__/* linguist-generated
6 | __test__/data/response.test.html linguist-generated
7 | __test__/data/jsonp.test.html linguist-generated
8 | response.test.html linguist-generated
9 | jsonp.test.html linguist-generated
10 |
--------------------------------------------------------------------------------
/.github/workflows/node.js.yml:
--------------------------------------------------------------------------------
1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3 |
4 | name: Build and Test
5 |
6 | on:
7 | push:
8 | branches: [main]
9 | pull_request:
10 | branches: [main]
11 |
12 | jobs:
13 | build:
14 | runs-on: ubuntu-latest
15 |
16 | strategy:
17 | matrix:
18 | node-version: [18.x]
19 |
20 | steps:
21 | - uses: actions/checkout@v2
22 | - name: Use Node.js ${{ matrix.node-version }}
23 | uses: actions/setup-node@v1
24 | with:
25 | node-version: ${{ matrix.node-version }}
26 | - name: Install Packages
27 | run: npm ci
28 | - name: Build
29 | run: npm run build
30 | - name: Run Tests
31 | run: npm run test -- --coverage --update
32 | - name: Analyze with SonarCloud
33 | uses: sonarsource/sonarcloud-github-action@master
34 | env:
35 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
37 |
--------------------------------------------------------------------------------
/.github/workflows/storybook.yml:
--------------------------------------------------------------------------------
1 | name: Deploy Storybook
2 | on:
3 | push:
4 | branches: [main]
5 | paths: ["stories/**", "src/components/**", "./.storybook/**"] # Trigger the action only when files change in the folders defined here
6 | jobs:
7 | build-and-deploy:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: Checkout 🛎️
11 | uses: actions/checkout@v2.3.1
12 | with:
13 | persist-credentials: false
14 | - name: Install and Build 🔧
15 | run: | # Install npm packages and build the Storybook files
16 | npm ci
17 | BASE_PATH=/react-goodreads-shelf/ npm run build-storybook
18 | - name: Deploy 🚀
19 | uses: JamesIves/github-pages-deploy-action@3.6.2
20 | with:
21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22 | BRANCH: gh-pages # The branch the action should deploy to.
23 | FOLDER: docs-build # The folder that the build-storybook script generates files.
24 | CLEAN: true # Automatically remove deleted files from the deploy branch
25 | TARGET_FOLDER: docs # The folder that we serve our Storybook files from
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # parcel-bundler cache (https://parceljs.org/)
61 | .cache
62 |
63 | # next.js build output
64 | .next
65 |
66 | # nuxt.js build output
67 | .nuxt
68 |
69 | # vuepress build output
70 | .vuepress/dist
71 |
72 | # Serverless directories
73 | .serverless
74 |
75 | # FuseBox cache
76 | .fusebox/
77 |
78 | dist/
79 | __snapshots__/
80 | test-report.xml
81 | docs-build/
82 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | legacy-peer-deps=true
2 | registry=https://registry.npmjs.org
3 |
--------------------------------------------------------------------------------
/.prettierrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | ...require("gts/.prettierrc.json"),
3 | bracketSpacing: true,
4 | semi: true,
5 | arrowParens: "always",
6 | trailingComma: "none",
7 | singleQuote: false,
8 | printWidth: 120,
9 | useTabs: false,
10 | tabWidth: 2,
11 | eol: "lf"
12 | };
13 |
--------------------------------------------------------------------------------
/.storybook/main.ts:
--------------------------------------------------------------------------------
1 | import type { StorybookConfig } from "@storybook/react-vite";
2 | import { mergeConfig } from "vite";
3 |
4 | const config: StorybookConfig = {
5 | stories: ["../stories/**/*.stories.{ts,tsx}", "../stories/**/*.mdx"],
6 | addons: ["@storybook/addon-controls", "@storybook/addon-links", "@storybook/addon-essentials", "storybook-dark-mode"],
7 | typescript: {
8 | check: false
9 | },
10 | async viteFinal(config) {
11 | return mergeConfig(config, {
12 | base: process.env.BASE_PATH || config.base
13 | });
14 | },
15 | framework: {
16 | name: "@storybook/react-vite",
17 | options: {}
18 | },
19 | docs: {
20 | autodocs: "tag"
21 | }
22 | };
23 | export default config;
24 |
--------------------------------------------------------------------------------
/.storybook/manager.ts:
--------------------------------------------------------------------------------
1 | import { addons } from "@storybook/addons";
2 |
3 | addons.setConfig({
4 | isFullscreen: false,
5 | showNav: true,
6 | showPanel: true,
7 | showToolbar: true,
8 | panelPosition: "right",
9 | sidebarAnimations: true,
10 | enableShortcuts: true,
11 | isToolshown: true,
12 | theme: undefined,
13 | selectedPanel: "controls",
14 | initialActive: "controls",
15 | sidebar: {
16 | showRoots: false
17 | }
18 | });
19 |
--------------------------------------------------------------------------------
/.storybook/preview.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: "Nunito Sans", -apple-system, ".SFNSText-Regular", "San Francisco", BlinkMacSystemFont, "Segoe UI",
3 | "Helvetica Neue", Helvetica, Arial, sans-serif;
4 | }
5 |
6 | .lights-out {
7 | background-color: #222;
8 | color: #fff;
9 | }
10 |
--------------------------------------------------------------------------------
/.storybook/preview.tsx:
--------------------------------------------------------------------------------
1 | import { themes } from "@storybook/theming";
2 | import "./preview.css";
3 |
4 | const parameters = {
5 | darkMode: {
6 | // Override the default dark theme
7 | dark: { ...themes.dark, appBg: "black", appContentBg: "black" },
8 | // Override the default light theme
9 | light: { ...themes.normal, appBg: "white" },
10 | darkClass: "lights-out",
11 | lightClass: "lights-on",
12 | stylePreview: true
13 | }
14 | };
15 |
16 | const preview = {
17 | parameters
18 | };
19 |
20 | export default preview;
21 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": true,
3 | "typescript.tsdk": "node_modules/typescript/lib",
4 | "typescript.enablePromptUseWorkspaceTsdk": true
5 | }
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Kyle Karpack
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-goodreads-shelf
2 |  
3 | [](https://sonarcloud.io/dashboard?id=kylekarpack_react-goodreads-shelf) [](https://sonarcloud.io/dashboard?id=kylekarpack_react-goodreads-shelf)
4 |
5 | This React component allows you to display a public Goodreads shelf in a React application. It's a lot like the Goodreads JavaScript widget, but allows for more customization, better async loading, and React-like usage.
6 |
7 | ## Demo
8 | [Live Demo](https://kylekarpack.github.io/react-goodreads-shelf)
9 |
10 | Preview
11 |
12 | 
13 |
14 | ## Installation
15 |
16 | ```
17 | npm install --save react-goodreads-shelf
18 | ```
19 | or
20 | ```
21 | yarn add react-goodreads-shelf
22 | ```
23 |
24 | ## Usage
25 |
26 | ```jsx
27 | import React from "react";
28 | import GoodreadsBookshelf from "react-goodreads-shelf";
29 |
30 | export default function App() {
31 | return (
32 |
Kyle 💻 |
66 | David Dias ️️️️♿️ |
67 | Eli Gundry 💻 |
68 | Bassem Ibrahim 💻 |
69 |
4 |
5 | |
7 |
11 | 12 | 13 | 22 | | 23 |24 | 25 | 26 | | 27 |
28 |
29 |
30 | Lloyd, Ellery
31 | *
32 |
33 | |
34 |
38 |
42 |
46 |
55 |
56 |
57 | 3.39
58 | |
59 |
63 |
67 |
71 |
72 |
73 |
74 | liked it
79 |
80 | |
81 |
82 |
83 |
84 |
97 |
98 |
99 |
103 |
100 | add to shelves
101 |
102 | |
104 |
111 |
117 |
123 |
129 |
135 |
139 |
149 |
150 |
151 |
152 |
158 |
153 |
157 |
154 | Aug 30, 2022
155 |
156 | |
159 |
160 |
161 |
162 | Aug 30, 2022
163 |
164 | |
165 |
169 |
173 |
177 |
181 |
185 |
186 |
187 |
188 |
192 |
189 | view
190 |
191 | |
193 |
197 |
198 | |
200 |
204 | 205 | 206 | 215 | | 216 |217 | 218 | 223 | | 224 |
225 |
226 |
227 | Comer, John Mark
228 | *
229 |
230 | |
231 |
235 |
239 |
243 |
252 |
253 |
254 | 4.46
255 | |
256 |
260 |
264 |
268 |
269 |
270 |
271 | it was amazing
276 |
277 | |
278 |
279 |
280 |
281 |
294 |
295 |
296 |
300 |
297 | add to shelves
298 |
299 | |
301 |
308 |
314 |
320 |
326 |
332 |
336 |
346 |
347 |
348 |
349 |
355 |
350 |
354 |
351 | Aug 15, 2022
352 |
353 | |
356 |
357 |
358 |
359 | Jan 19, 2020
360 |
361 | |
362 |
366 |
370 |
374 |
378 |
382 |
383 |
384 |
385 |
389 |
386 | view
387 |
388 | |
390 |
394 |
395 | |
397 |
401 | 402 | 403 | 412 | | 413 |414 | 415 | 421 | | 422 |423 | 424 | 425 | | 426 | 430 | 434 | 438 | 447 |
448 |
449 | 4.01
450 | |
451 |
455 |
459 |
463 |
464 |
465 |
466 |
471 |
472 | |
473 |
474 |
475 |
476 |
489 |
490 |
491 |
495 |
492 | add to shelves
493 |
494 | |
496 |
503 |
509 |
515 |
521 |
527 |
531 |
541 |
542 |
543 |
544 |
550 |
545 |
549 |
546 | Jul 11, 2022
547 |
548 | |
551 |
552 |
553 |
554 | Jul 03, 2022
555 |
556 | |
557 |
561 |
565 |
569 |
573 |
577 |
578 |
579 |
580 |
584 |
581 | view
582 |
583 | |
585 |
589 |
590 | |
592 |
596 | 597 | 598 | 607 | | 608 |
609 |
610 |
611 |
612 | Great Lodges of the National Parks
613 |
614 |
615 | |
616 | 617 | 618 | 619 | | 620 | 624 | 628 | 632 | 641 |
642 |
643 | 4.25
644 | |
645 |
649 |
653 |
657 |
658 |
659 |
660 |
665 |
666 | |
667 |
668 |
669 |
670 |
683 |
684 |
685 |
689 |
686 | add to shelves
687 |
688 | |
690 |
697 |
703 |
709 |
715 |
721 |
725 |
735 |
736 |
737 |
738 |
744 |
739 |
743 |
740 | Jul 03, 2022
741 |
742 | |
745 |
746 |
747 |
748 | Jun 20, 2022
749 |
750 | |
751 |
755 |
759 |
763 |
767 |
771 |
772 |
773 |
774 |
778 |
775 | view
776 |
777 | |
779 |
783 |
784 | |
786 |
790 | 791 | 792 | 801 | | 802 |803 | 804 | 812 | | 813 |814 | 815 | 816 | | 817 | 821 | 825 | 829 | 838 |
839 |
840 | 4.33
841 | |
842 |
846 |
850 |
854 |
855 |
856 |
857 |
862 |
863 | |
864 |
865 |
866 |
867 |
880 |
881 |
882 |
886 |
883 | add to shelves
884 |
885 | |
887 |
894 |
900 |
906 |
912 |
918 |
922 |
932 |
933 |
934 |
935 |
941 |
936 |
940 |
937 | Jun 20, 2022
938 |
939 | |
942 |
943 |
944 |
945 | Jun 20, 2022
946 |
947 | |
948 |
952 |
956 |
960 |
964 |
968 |
969 |
970 |
971 |
975 |
972 | view
973 |
974 | |
976 |