diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index b818007..b487337 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -14,6 +14,9 @@ jobs: node-version: [16.x] steps: + - uses: browser-actions/setup-chrome@latest + - run: chrome --version + - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} diff --git a/.gitignore b/.gitignore index 746b3c8..fd83653 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ data/ current/ difference/ storybook-static/ +reg-diff/ +reg.json +report.html diff --git a/Makefile b/Makefile index 0d8b0ee..53891fc 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ install: npx lerna bootstrap --hoist -lint: +test: npx lerna run test diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/BurgerBtn/default.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/BurgerBtn/default.png new file mode 100644 index 0000000..713767e Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/BurgerBtn/default.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/ContentSkeleton/dark.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/ContentSkeleton/dark.png new file mode 100644 index 0000000..00f50c2 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/ContentSkeleton/dark.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/ContentSkeleton/light.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/ContentSkeleton/light.png new file mode 100644 index 0000000..ae2bd74 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/ContentSkeleton/light.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/MyDropDown/default.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyDropDown/default.png new file mode 100644 index 0000000..2d19db7 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyDropDown/default.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/ModalActionBtn/delete.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/ModalActionBtn/delete.png new file mode 100644 index 0000000..5b1b9e8 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/ModalActionBtn/delete.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/ModalActionBtn/mark.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/ModalActionBtn/mark.png new file mode 100644 index 0000000..2445730 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/ModalActionBtn/mark.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/ModalActionBtn/preview.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/ModalActionBtn/preview.png new file mode 100644 index 0000000..e4630a9 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/ModalActionBtn/preview.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/ModalActionBtn/reload.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/ModalActionBtn/reload.png new file mode 100644 index 0000000..cab91eb Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/ModalActionBtn/reload.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/simple_dark.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/simple_dark.png new file mode 100644 index 0000000..2b01cbb Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/simple_dark.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/simple_light.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/simple_light.png new file mode 100644 index 0000000..5f525a4 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/simple_light.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/with_image_dark.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/with_image_dark.png new file mode 100644 index 0000000..4333e7d Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/with_image_dark.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/with_image_light.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/with_image_light.png new file mode 100644 index 0000000..72fca23 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/MyModal/with_image_light.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/Notification/error.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/Notification/error.png new file mode 100644 index 0000000..386230b Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/Notification/error.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/Notification/success.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/Notification/success.png new file mode 100644 index 0000000..059e956 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/Notification/success.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/biggest_middle_dark.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/biggest_middle_dark.png new file mode 100644 index 0000000..7e5d9b1 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/biggest_middle_dark.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/biggest_middle_light.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/biggest_middle_light.png new file mode 100644 index 0000000..74ca3b0 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/biggest_middle_light.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_first_dark.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_first_dark.png new file mode 100644 index 0000000..21f98c9 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_first_dark.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_first_light.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_first_light.png new file mode 100644 index 0000000..183818e Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_first_light.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_last_dark.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_last_dark.png new file mode 100644 index 0000000..1675b49 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_last_dark.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_last_light.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_last_light.png new file mode 100644 index 0000000..514f846 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_last_light.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_middle_dark.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_middle_dark.png new file mode 100644 index 0000000..ea64ee3 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_middle_dark.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_middle_light.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_middle_light.png new file mode 100644 index 0000000..19463b1 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/extra_middle_light.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/simple_dark.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/simple_dark.png new file mode 100644 index 0000000..0a0e427 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/simple_dark.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/simple_light.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/simple_light.png new file mode 100644 index 0000000..c84ff42 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/simple_light.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/simple_with_arrows_dark.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/simple_with_arrows_dark.png new file mode 100644 index 0000000..b9ced65 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/simple_with_arrows_dark.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/simple_with_arrows_light.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/simple_with_arrows_light.png new file mode 100644 index 0000000..7be284f Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/Paginator/simple_with_arrows_light.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/ScrollTopBtn/loki_test_only.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/ScrollTopBtn/loki_test_only.png new file mode 100644 index 0000000..697cec0 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/ScrollTopBtn/loki_test_only.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/danger.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/danger.png new file mode 100644 index 0000000..37695d8 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/danger.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/lang.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/lang.png new file mode 100644 index 0000000..563d0c6 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/lang.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/microphone_off.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/microphone_off.png new file mode 100644 index 0000000..d0eb325 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/microphone_off.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/microphone_on.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/microphone_on.png new file mode 100644 index 0000000..86a71d0 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/microphone_on.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/reload.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/reload.png new file mode 100644 index 0000000..4e10ad5 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/reload.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/sign_out.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/sign_out.png new file mode 100644 index 0000000..912cb88 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/sign_out.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/sort.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/sort.png new file mode 100644 index 0000000..405e13f Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/sort.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/sort_reverse.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/sort_reverse.png new file mode 100644 index 0000000..35faa9d Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/sort_reverse.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/success.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/success.png new file mode 100644 index 0000000..20fbabb Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/success.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/user.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/user.png new file mode 100644 index 0000000..97e798b Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/user.png differ diff --git a/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/wi_fi_off.png b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/wi_fi_off.png new file mode 100644 index 0000000..7fa3c68 Binary files /dev/null and b/apps/client/.loki/reference/chrome.iphone7/components/UI/SvgIcon/wi_fi_off.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/BurgerBtn/default.png b/apps/client/.loki/reference/chrome.laptop/components/UI/BurgerBtn/default.png new file mode 100644 index 0000000..1aa3346 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/BurgerBtn/default.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/ContentSkeleton/dark.png b/apps/client/.loki/reference/chrome.laptop/components/UI/ContentSkeleton/dark.png new file mode 100644 index 0000000..277b011 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/ContentSkeleton/dark.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/ContentSkeleton/light.png b/apps/client/.loki/reference/chrome.laptop/components/UI/ContentSkeleton/light.png new file mode 100644 index 0000000..ae34fbc Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/ContentSkeleton/light.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/MyDropDown/default.png b/apps/client/.loki/reference/chrome.laptop/components/UI/MyDropDown/default.png new file mode 100644 index 0000000..01ba6c6 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/MyDropDown/default.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/ModalActionBtn/delete.png b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/ModalActionBtn/delete.png new file mode 100644 index 0000000..cbb153d Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/ModalActionBtn/delete.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/ModalActionBtn/mark.png b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/ModalActionBtn/mark.png new file mode 100644 index 0000000..887b82a Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/ModalActionBtn/mark.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/ModalActionBtn/preview.png b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/ModalActionBtn/preview.png new file mode 100644 index 0000000..9fb2844 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/ModalActionBtn/preview.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/ModalActionBtn/reload.png b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/ModalActionBtn/reload.png new file mode 100644 index 0000000..fb67bdd Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/ModalActionBtn/reload.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/simple_dark.png b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/simple_dark.png new file mode 100644 index 0000000..c8b3065 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/simple_dark.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/simple_light.png b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/simple_light.png new file mode 100644 index 0000000..00e560e Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/simple_light.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/with_image_dark.png b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/with_image_dark.png new file mode 100644 index 0000000..5e4c235 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/with_image_dark.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/with_image_light.png b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/with_image_light.png new file mode 100644 index 0000000..d63de5d Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/MyModal/with_image_light.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/Notification/error.png b/apps/client/.loki/reference/chrome.laptop/components/UI/Notification/error.png new file mode 100644 index 0000000..8357fe2 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/Notification/error.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/Notification/success.png b/apps/client/.loki/reference/chrome.laptop/components/UI/Notification/success.png new file mode 100644 index 0000000..0370cdc Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/Notification/success.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/biggest_middle_dark.png b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/biggest_middle_dark.png new file mode 100644 index 0000000..3a1effa Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/biggest_middle_dark.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/biggest_middle_light.png b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/biggest_middle_light.png new file mode 100644 index 0000000..835f642 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/biggest_middle_light.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_first_dark.png b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_first_dark.png new file mode 100644 index 0000000..1de2e77 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_first_dark.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_first_light.png b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_first_light.png new file mode 100644 index 0000000..2991631 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_first_light.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_last_dark.png b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_last_dark.png new file mode 100644 index 0000000..5be41b9 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_last_dark.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_last_light.png b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_last_light.png new file mode 100644 index 0000000..56bd224 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_last_light.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_middle_dark.png b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_middle_dark.png new file mode 100644 index 0000000..b4550fb Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_middle_dark.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_middle_light.png b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_middle_light.png new file mode 100644 index 0000000..c7a0c79 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/extra_middle_light.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/simple_dark.png b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/simple_dark.png new file mode 100644 index 0000000..33eeb47 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/simple_dark.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/simple_light.png b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/simple_light.png new file mode 100644 index 0000000..a822920 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/simple_light.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/simple_with_arrows_dark.png b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/simple_with_arrows_dark.png new file mode 100644 index 0000000..6bf906b Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/simple_with_arrows_dark.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/simple_with_arrows_light.png b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/simple_with_arrows_light.png new file mode 100644 index 0000000..c7d5e22 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/Paginator/simple_with_arrows_light.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/ScrollTopBtn/loki_test_only.png b/apps/client/.loki/reference/chrome.laptop/components/UI/ScrollTopBtn/loki_test_only.png new file mode 100644 index 0000000..5f64fb5 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/ScrollTopBtn/loki_test_only.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/danger.png b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/danger.png new file mode 100644 index 0000000..f98e3ed Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/danger.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/lang.png b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/lang.png new file mode 100644 index 0000000..bf9b349 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/lang.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/microphone_off.png b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/microphone_off.png new file mode 100644 index 0000000..f4837d8 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/microphone_off.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/microphone_on.png b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/microphone_on.png new file mode 100644 index 0000000..5d6469c Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/microphone_on.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/reload.png b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/reload.png new file mode 100644 index 0000000..cdb5c02 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/reload.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/sign_out.png b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/sign_out.png new file mode 100644 index 0000000..1e6834b Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/sign_out.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/sort.png b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/sort.png new file mode 100644 index 0000000..ed5183d Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/sort.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/sort_reverse.png b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/sort_reverse.png new file mode 100644 index 0000000..990762c Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/sort_reverse.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/success.png b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/success.png new file mode 100644 index 0000000..5b3e395 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/success.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/user.png b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/user.png new file mode 100644 index 0000000..7f08182 Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/user.png differ diff --git a/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/wi_fi_off.png b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/wi_fi_off.png new file mode 100644 index 0000000..87fcc9c Binary files /dev/null and b/apps/client/.loki/reference/chrome.laptop/components/UI/SvgIcon/wi_fi_off.png differ diff --git a/apps/client/.loki/reference/chrome_iphone7_Example_Notification_Primary.png b/apps/client/.loki/reference/chrome_iphone7_Example_Notification_Primary.png deleted file mode 100644 index 59af593..0000000 Binary files a/apps/client/.loki/reference/chrome_iphone7_Example_Notification_Primary.png and /dev/null differ diff --git a/apps/client/.loki/reference/chrome_laptop_Example_Notification_Primary.png b/apps/client/.loki/reference/chrome_laptop_Example_Notification_Primary.png deleted file mode 100644 index 0b41d80..0000000 Binary files a/apps/client/.loki/reference/chrome_laptop_Example_Notification_Primary.png and /dev/null differ diff --git a/apps/client/.storybook/main.js b/apps/client/.storybook/main.js index 295ac76..e157ef7 100644 --- a/apps/client/.storybook/main.js +++ b/apps/client/.storybook/main.js @@ -1,34 +1,54 @@ const path = require('path'); -const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); module.exports = { stories: [ - "../src/**/*.stories.mdx", - "../src/**/*.stories.@(js|jsx|ts|tsx)" + '../src/**/*.stories.mdx', + '../src/**/*.stories.@(js|jsx|ts|tsx)' ], addons: [ - "@storybook/addon-links", - "@storybook/addon-essentials", - "@storybook/addon-interactions", + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + '@storybook/addon-a11y', + 'storybook-react-intl', ], - framework: "@storybook/react", + framework: '@storybook/react', core: { - builder: "@storybook/builder-webpack5" + builder: '@storybook/builder-webpack5' + }, + features: { + interactionsDebugger: true, }, webpackFinal: async (config) => { - config.resolve.plugins = [ - ...(config.resolve.plugins || []), - new TsconfigPathsPlugin({ - extensions: config.resolve.extensions, - }), - ]; + config.resolve.alias = { + ...config.resolve.alias, + "@": path.resolve(__dirname, "../src/"), + }; + config.resolve.extensions.push(".ts", ".tsx"); config.module.rules.push({ - test: /\.scss$/, - use: ['style-loader', 'css-loader', 'sass-loader'], + test: /\.module\.s(a|c)ss$/, + use: ['style-loader', { + loader: 'css-loader', + options: { + modules: { + localIdentName: '[local]_[hash:base64:5]', + }, + }, + }, 'sass-loader'], include: path.resolve(__dirname, '../'), }); + config.module.rules.push({ + test: /\.s(a|c)ss$/, + exclude: /\.module.(s(a|c)ss)$/, + use: [ + 'style-loader', + 'css-loader', + 'sass-loader', + ], + }); + return config; }, } diff --git a/apps/client/.storybook/preview.js b/apps/client/.storybook/preview.js index b243f8e..1031f03 100644 --- a/apps/client/.storybook/preview.js +++ b/apps/client/.storybook/preview.js @@ -1,4 +1,6 @@ -import '!style-loader!css-loader!sass-loader!../src/styles/main.scss'; +import '@/styles/main.scss'; +import { LOCALES } from '@/i18n/locales'; +import reactIntl from './reactIntl'; export const parameters = { actions: { argTypesRegex: "^on[A-Z].*" }, @@ -7,5 +9,28 @@ export const parameters = { color: /(background|color)$/i, date: /Date$/, }, + }, + reactIntl, + locale: reactIntl.defaultLocale, + locales: { + [LOCALES.ENGLISH]: {title: "English", left: '🇬🇧'}, + [LOCALES.RUSSIAN]: {title: "Русский", left: '🇷🇺'}, + }, + backgrounds: { + default: 'light', + values: [ + { + name: 'light', + value: '#ffffff', + }, + { + name: 'dark', + value: '#212529', + }, + { + name: 'gray', + value: '#6c757d', + }, + ], }, } diff --git a/apps/client/.storybook/reactIntl.js b/apps/client/.storybook/reactIntl.js new file mode 100644 index 0000000..bb6ecfd --- /dev/null +++ b/apps/client/.storybook/reactIntl.js @@ -0,0 +1,13 @@ +import { LOCALES } from '../src/i18n/locales'; +import { messages } from '../src/i18n/messages'; + +const locales = [LOCALES.ENGLISH, LOCALES.RUSSIAN]; + +const reactIntl = { + defaultLocale: LOCALES.ENGLISH, + locales, + messages, + formats: {}, +}; + +export default reactIntl; diff --git a/apps/client/jest.config.js b/apps/client/jest.config.js index 7176726..7d5461b 100644 --- a/apps/client/jest.config.js +++ b/apps/client/jest.config.js @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/no-var-requires */ const tsconfig = require('./tsconfig.json'); -const moduleNameMapper = require('tsconfig-paths-jest')(tsconfig); /** @type {import('jest').Config} */ module.exports = { @@ -15,5 +14,8 @@ module.exports = { transform: { '^.+\\.[t|j]sx?$': 'babel-jest', }, - moduleNameMapper, + moduleNameMapper: { + ...require('tsconfig-paths-jest')(tsconfig), + '.+\\.(css|sass|scss)$': 'identity-obj-proxy', + }, }; diff --git a/apps/client/loki.config.js b/apps/client/loki.config.js index ce5d870..a7c521b 100644 --- a/apps/client/loki.config.js +++ b/apps/client/loki.config.js @@ -1,15 +1,22 @@ module.exports = { + diffingEngine: 'pixelmatch', + chromeSelector: '#root > *', configurations: { 'chrome.laptop': { - target: 'chrome.docker', + target: 'chrome.app', width: 1366, height: 768, deviceScaleFactor: 1, mobile: false, }, 'chrome.iphone7': { - target: 'chrome.docker', + target: 'chrome.app', preset: 'iPhone 7', }, }, + fileNameFormatter: ({ configurationName, kind, story }) => { + const formattedStoryName = story.replaceAll(' ', '_').toLowerCase(); + + return `${configurationName.toLowerCase()}/${kind}/${formattedStoryName}`; + }, }; diff --git a/apps/client/package-lock.json b/apps/client/package-lock.json index daea1a8..404edcd 100644 --- a/apps/client/package-lock.json +++ b/apps/client/package-lock.json @@ -1,12 +1,12 @@ { "name": "@rss-reader/client", - "version": "1.13.2", + "version": "1.13.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@rss-reader/client", - "version": "1.13.2", + "version": "1.13.6", "license": "ISC", "dependencies": { "@reduxjs/toolkit": "^1.6.2", @@ -42,12 +42,14 @@ "@babel/preset-react": "^7.16.0", "@babel/preset-typescript": "^7.16.0", "@babel/runtime": "^7.16.3", + "@storybook/addon-a11y": "^6.5.12", "@storybook/addon-actions": "^6.5.12", "@storybook/addon-essentials": "^6.5.12", "@storybook/addon-interactions": "^6.5.12", "@storybook/addon-links": "^6.5.12", "@storybook/addons": "^6.5.12", "@storybook/builder-webpack5": "^6.5.12", + "@storybook/jest": "^0.0.10", "@storybook/manager-webpack5": "^6.5.12", "@storybook/react": "^6.5.12", "@storybook/testing-library": "^0.0.13", @@ -84,6 +86,7 @@ "file-loader": "^6.2.0", "fork-ts-checker-webpack-plugin": "^6.4.0", "html-webpack-plugin": "^5.5.0", + "identity-obj-proxy": "^3.0.0", "jest": "^29.1.2", "jest-environment-jsdom": "^29.1.2", "loki": "^0.30.3", @@ -96,14 +99,15 @@ "prettier": "^2.7.1", "prettier-eslint": "^15.0.1", "react-helmet": "^6.1.0", + "reg-cli": "^0.17.7", "sass-loader": "^12.3.0", + "storybook-react-intl": "^1.1.1", "style-loader": "^3.3.1", "stylelint": "^14.13.0", "stylelint-config-standard-scss": "^5.0.0", "terser-webpack-plugin": "^5.2.4", "ts-loader": "^9.2.6", "tsconfig-paths-jest": "^0.0.1", - "tsconfig-paths-webpack-plugin": "^4.0.0", "typescript": "^4.4.4", "webpack": "^5.61.0", "webpack-bundle-analyzer": "^4.5.0", @@ -4469,6 +4473,46 @@ "@speechly/browser-client": "^2.4.1" } }, + "node_modules/@storybook/addon-a11y": { + "version": "6.5.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-6.5.12.tgz", + "integrity": "sha512-uCMak9yP5gaYC/umSwyjqILTOhMEgTGCNDoa4+F3XhdFKZbX6PUpy++2upmm7pBqz6r4sokcxGSmHTkRMqm2yw==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.5.12", + "@storybook/api": "6.5.12", + "@storybook/channels": "6.5.12", + "@storybook/client-logger": "6.5.12", + "@storybook/components": "6.5.12", + "@storybook/core-events": "6.5.12", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/theming": "6.5.12", + "axe-core": "^4.2.0", + "core-js": "^3.8.2", + "global": "^4.4.0", + "lodash": "^4.17.21", + "react-sizeme": "^3.0.1", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/@storybook/addon-actions": { "version": "6.5.12", "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.5.12.tgz", @@ -8951,6 +8995,15 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/expect": { + "version": "27.5.2-0", + "resolved": "https://registry.npmjs.org/@storybook/expect/-/expect-27.5.2-0.tgz", + "integrity": "sha512-cP99mhWN/JeCp7VSIiymvj5tmuMY050iFohvp8Zq+kewKsBSZ6/qpTJAGCCZk6pneTcp4S0Fm5BSqyxzbyJ3gw==", + "dev": true, + "dependencies": { + "@types/jest": ">=26.0.0" + } + }, "node_modules/@storybook/instrumenter": { "version": "6.5.12", "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-6.5.12.tgz", @@ -8968,6 +9021,126 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/jest": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@storybook/jest/-/jest-0.0.10.tgz", + "integrity": "sha512-qeYLIplpcOUQXboJde5pRCjTvkGmF80jEszRUoNYCNcEPfC2sMK68Wq6Ct8EQj3CoEdJqsK54O2YYh+7D9S+ag==", + "dev": true, + "dependencies": { + "@storybook/expect": "storybook-jest", + "@storybook/instrumenter": "^6.4.0", + "@testing-library/jest-dom": "^5.16.2", + "jest-mock": "^27.3.0" + } + }, + "node_modules/@storybook/jest/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@storybook/jest/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@storybook/jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@storybook/jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@storybook/jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@storybook/jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@storybook/jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/jest/node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@storybook/jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@storybook/manager-webpack4": { "version": "6.5.12", "resolved": "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.5.12.tgz", @@ -11780,6 +11953,15 @@ "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", "dev": true }, + "node_modules/@types/mkdirp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.2.tgz", + "integrity": "sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "18.8.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.3.tgz", @@ -11834,6 +12016,24 @@ "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==", "dev": true }, + "node_modules/@types/pixelmatch": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@types/pixelmatch/-/pixelmatch-5.2.4.tgz", + "integrity": "sha512-HDaSHIAv9kwpMN7zlmwfTv6gax0PiporJOipcrGsVNF3Ba+kryOZc0Pio5pn6NhisgWr7TaajlPEKTbTAypIBQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/pngjs": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/pngjs/-/pngjs-6.0.1.tgz", + "integrity": "sha512-J39njbdW1U/6YyVXvC9+1iflZghP8jgRf2ndYghdJb5xL49LYDB+1EuAxfbuJ2IBbWIL3AjHPQhgaTxT3YaYeg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/prettier": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz", @@ -13048,7 +13248,6 @@ "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", "dev": true, - "optional": true, "engines": { "node": ">=0.10.0" } @@ -13468,6 +13667,15 @@ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", "dev": true }, + "node_modules/axe-core": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz", + "integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/axios": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", @@ -13877,6 +14085,12 @@ "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", "dev": true }, + "node_modules/batch-processor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz", + "integrity": "sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA==", + "dev": true + }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -15179,6 +15393,15 @@ "node": ">=8" } }, + "node_modules/cli-spinner": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/cli-spinner/-/cli-spinner-0.2.10.tgz", + "integrity": "sha512-U0sSQ+JJvSLi1pAYuJykwiA8Dsr15uHEy85iCJ6A+0DjVxivr3d+N2Wjvodeg89uP5K6TswFkKBfAD7B3YSn/Q==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, "node_modules/cli-table3": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", @@ -16727,7 +16950,6 @@ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", "dev": true, - "optional": true, "dependencies": { "array-find-index": "^1.0.1" }, @@ -16821,6 +17043,12 @@ "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==", "dev": true }, + "node_modules/decode-tiff": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/decode-tiff/-/decode-tiff-0.2.1.tgz", + "integrity": "sha512-v/7hQBv/DrOVQ+Eljg0BLMRbXZYuuw3YZ8duZuFxYpo6qUkdn7oFRkN95RZKbnh08EHNjrMXMbEUNhTLuhPvvA==", + "dev": true + }, "node_modules/decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -17573,6 +17801,15 @@ "integrity": "sha512-EpuHPqu8YhonqLBXHoU6hDJCD98FCe6KDoet3/gY1qsQ6usjJoHqBH2YIVs8FXaAtHwVL8Uqa/fsYao/vq9VWQ==", "dev": true }, + "node_modules/element-resize-detector": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.4.tgz", + "integrity": "sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==", + "dev": true, + "dependencies": { + "batch-processor": "1.0.0" + } + }, "node_modules/elliptic": { "version": "6.5.4", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", @@ -20219,6 +20456,12 @@ "node": ">=6" } }, + "node_modules/harmony-reflect": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", + "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==", + "dev": true + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -20919,6 +21162,18 @@ "integrity": "sha512-Wsk07aAxDsntgYJY4h0knZJuTxM73eQ4reRAO+Z1liOh8eMCJ/MoDS8fCui1vGT9mnjtl1sOu3I2i/W1swPYZg==", "dev": true }, + "node_modules/identity-obj-proxy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", + "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", + "dev": true, + "dependencies": { + "harmony-reflect": "^1.4.6" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", @@ -20940,6 +21195,38 @@ "node": ">= 4" } }, + "node_modules/img-diff-js": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/img-diff-js/-/img-diff-js-0.5.2.tgz", + "integrity": "sha512-edvMoyVOrEFC/evz/DYBJ0tmvQ0YeQ+qQZdN4r6LIFxDq1vBd/Pt/+pPOlu9h/whBDiAdQrDkNWtnrpyBMpFOw==", + "dev": true, + "dependencies": { + "@types/mkdirp": "^1.0.1", + "@types/node": "^14.11.2", + "@types/pixelmatch": "^5.2.2", + "@types/pngjs": "^6.0.0", + "decode-tiff": "^0.2.0", + "jpeg-js": "^0.4.2", + "mkdirp": "^1.0.4", + "pixelmatch": "^5.2.1", + "pngjs": "^6.0.0" + } + }, + "node_modules/img-diff-js/node_modules/@types/node": { + "version": "14.18.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.33.tgz", + "integrity": "sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==", + "dev": true + }, + "node_modules/img-diff-js/node_modules/pngjs": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", + "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", + "dev": true, + "engines": { + "node": ">=12.13.0" + } + }, "node_modules/immer": { "version": "9.0.15", "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz", @@ -21635,7 +21922,6 @@ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", "dev": true, - "optional": true, "engines": { "node": ">=0.10.0" }, @@ -21953,8 +22239,7 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", - "dev": true, - "optional": true + "dev": true }, "node_modules/is-weakref": { "version": "1.0.2", @@ -24221,6 +24506,12 @@ "@sideway/pinpoint": "^2.0.0" } }, + "node_modules/jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", + "dev": true + }, "node_modules/js-base64": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", @@ -24547,7 +24838,6 @@ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", "dev": true, - "optional": true, "dependencies": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", @@ -24564,7 +24854,6 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", "dev": true, - "optional": true, "dependencies": { "error-ex": "^1.2.0" }, @@ -24577,7 +24866,6 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, - "optional": true, "engines": { "node": ">=0.10.0" } @@ -24587,7 +24875,6 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", "dev": true, - "optional": true, "dependencies": { "is-utf8": "^0.2.0" }, @@ -24843,7 +25130,6 @@ "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ==", "dev": true, - "optional": true, "dependencies": { "currently-unhandled": "^0.4.1", "signal-exit": "^3.0.0" @@ -24998,6 +25284,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/md5-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-4.0.0.tgz", + "integrity": "sha512-UC0qFwyAjn4YdPpKaDNw6gNxRf7Mcx7jC1UGCY4boCzgvU2Aoc1mOGzTtrjjLKhM5ivsnhoKpQVxKPp+1j1qwg==", + "dev": true, + "bin": { + "md5-file": "cli.js" + }, + "engines": { + "node": ">=6.0" + } + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -25579,6 +25877,15 @@ "multicast-dns": "cli.js" } }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "dev": true, + "bin": { + "mustache": "bin/mustache" + } + }, "node_modules/nan": { "version": "2.16.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", @@ -29836,6 +30143,18 @@ "react": "^16.3.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-sizeme": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/react-sizeme/-/react-sizeme-3.0.2.tgz", + "integrity": "sha512-xOIAOqqSSmKlKFJLO3inBQBdymzDuXx4iuwkNcJmC96jeiOg5ojByvL+g3MW9LPEsojLbC6pf68zOfobK8IPlw==", + "dev": true, + "dependencies": { + "element-resize-detector": "^1.2.2", + "invariant": "^2.2.4", + "shallowequal": "^1.1.0", + "throttle-debounce": "^3.0.1" + } + }, "node_modules/react-speech-recognition": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/react-speech-recognition/-/react-speech-recognition-3.10.0.tgz", @@ -30022,6 +30341,398 @@ "redux": "^4" } }, + "node_modules/reg-cli": { + "version": "0.17.7", + "resolved": "https://registry.npmjs.org/reg-cli/-/reg-cli-0.17.7.tgz", + "integrity": "sha512-cwAJ7Zf/0tv6TArIIrZExJrnmiaTjiZj74ajXpYi8FLux6yOqFdfFfOOUJEIW1DP0zFASuG8HBf1v6m+dY575g==", + "dev": true, + "dependencies": { + "bluebird": "3.7.2", + "chalk": "4.1.2", + "cli-spinner": "0.2.10", + "cross-spawn": "7.0.3", + "del": "6.0.0", + "glob": "7.2.0", + "img-diff-js": "0.5.2", + "jpeg-js": "^0.4.0", + "lodash": "4.17.21", + "make-dir": "3.1.0", + "md5-file": "4.0.0", + "meow": "3.7.0", + "mustache": "4.2.0", + "x-img-diff-js": "0.3.5", + "yargs-parser": "^21.0.1" + }, + "bin": { + "reg-cli": "dist/cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/reg-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/reg-cli/node_modules/camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reg-cli/node_modules/camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha512-bA/Z/DERHKqoEOrp+qeGKw1QlvEQkGZSc0XaY6VnTxZr+Kv1G5zFwttpjv8qxZ/sBPT4nthwZaAcsAZTJlSKXQ==", + "dev": true, + "dependencies": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reg-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/reg-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/reg-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/reg-cli/node_modules/del": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "dev": true, + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/reg-cli/node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", + "dev": true, + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reg-cli/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/reg-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/reg-cli/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/reg-cli/node_modules/indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==", + "dev": true, + "dependencies": { + "repeating": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reg-cli/node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/reg-cli/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reg-cli/node_modules/meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==", + "dev": true, + "dependencies": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reg-cli/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/reg-cli/node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/reg-cli/node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "dev": true, + "dependencies": { + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reg-cli/node_modules/path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reg-cli/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reg-cli/node_modules/read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", + "dev": true, + "dependencies": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reg-cli/node_modules/read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", + "dev": true, + "dependencies": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reg-cli/node_modules/redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g==", + "dev": true, + "dependencies": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reg-cli/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/reg-cli/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/reg-cli/node_modules/strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha512-I5iQq6aFMM62fBEAIB/hXzwJD6EEZ0xEGCX2t7oXqaKPIRgt4WruAQ285BISgdkP+HLGWyeGmNJcpIwFeRYRUA==", + "dev": true, + "dependencies": { + "get-stdin": "^4.0.1" + }, + "bin": { + "strip-indent": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reg-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reg-cli/node_modules/trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha512-Nm4cF79FhSTzrLKGDMi3I4utBtFv8qKy4sq1enftf2gMdpqI8oVQTAfySkTz5r49giVzDj88SVZXP4CeYQwjaw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reg-cli/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -30375,7 +31086,6 @@ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==", "dev": true, - "optional": true, "dependencies": { "is-finite": "^1.0.0" }, @@ -31649,6 +32359,12 @@ "node": ">=8" } }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "dev": true + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -32412,6 +33128,56 @@ "integrity": "sha512-siT1RiqlfQnGqgT/YzXVUNsom9S0H1OX+dpdGN1xkyYATo4I6sep5NmsRD/40s3IIOvlCq6akxkqG82urIZW1w==", "dev": true }, + "node_modules/storybook-i18n": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/storybook-i18n/-/storybook-i18n-1.1.4.tgz", + "integrity": "sha512-0xD005aEBWhuDFU9oO5Yf+33MZQa/NWa2CWjkBODhcqC+N5WJhEPGUSQs8o9AqzQoRpIBOMQ3CS0cbRGbBuTxQ==", + "dev": true, + "peerDependencies": { + "@storybook/addons": ">=6.5.0", + "@storybook/api": ">=6.5.0", + "@storybook/components": ">=6.5.0", + "@storybook/core-events": ">=6.5.0", + "@storybook/theming": ">=6.5.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/storybook-react-intl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/storybook-react-intl/-/storybook-react-intl-1.1.1.tgz", + "integrity": "sha512-KD1G7TPo3+9nBXMkg6lk9MpS3RYMjUxam8d5S/NhHwzom0cnTk2AW4bd0zRmJkdjds1xuIhwZxet7Ebp9dggzw==", + "dev": true, + "dependencies": { + "storybook-i18n": "^1.1.2" + }, + "peerDependencies": { + "@storybook/addons": ">=6.5.0", + "@storybook/api": ">=6.5.0", + "@storybook/components": ">=6.5.0", + "@storybook/core-events": ">=6.5.0", + "@storybook/theming": ">=6.5.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-intl": "^5.24.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", @@ -33325,6 +34091,15 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/throttle-debounce": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", + "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -33686,119 +34461,12 @@ } } }, - "node_modules/tsconfig-paths": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.1.0.tgz", - "integrity": "sha512-AHx4Euop/dXFC+Vx589alFba8QItjF+8hf8LtmuiCwHyI4rHXQtOOENaM8kvYf5fR0dRChy3wzWIZ9WbB7FWow==", - "dev": true, - "dependencies": { - "json5": "^2.2.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/tsconfig-paths-jest": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tsconfig-paths-jest/-/tsconfig-paths-jest-0.0.1.tgz", "integrity": "sha512-YKhUKqbteklNppC2NqL7dv1cWF8eEobgHVD5kjF1y9Q4ocqpBiaDlYslQ9eMhtbqIPRrA68RIEXqknEjlxdwxw==", "dev": true }, - "node_modules/tsconfig-paths-webpack-plugin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.0.0.tgz", - "integrity": "sha512-fw/7265mIWukrSHd0i+wSwx64kYUSAKPfxRDksjKIYTxSAp9W9/xcZVBF4Kl0eqQd5eBpAQ/oQrc5RyM/0c1GQ==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.7.0", - "tsconfig-paths": "^4.0.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/tsconfig-paths-webpack-plugin/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/tsconfig-paths-webpack-plugin/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/tsconfig-paths-webpack-plugin/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/tsconfig-paths-webpack-plugin/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/tsconfig-paths-webpack-plugin/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/tsconfig-paths-webpack-plugin/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -36170,6 +36838,12 @@ "default-browser-id": "^1.0.4" } }, + "node_modules/x-img-diff-js": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/x-img-diff-js/-/x-img-diff-js-0.3.5.tgz", + "integrity": "sha512-B97ztoc2JeM+62HH1zFhmTyilsVqL486WMm8X3oQz16lTCGITY1cz+H57mTsNG0QuyVxv1yGq06qC8wy6UPCmQ==", + "dev": true + }, "node_modules/xml-name-validator": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", @@ -39565,6 +40239,30 @@ "@speechly/browser-client": "^2.4.1" } }, + "@storybook/addon-a11y": { + "version": "6.5.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-6.5.12.tgz", + "integrity": "sha512-uCMak9yP5gaYC/umSwyjqILTOhMEgTGCNDoa4+F3XhdFKZbX6PUpy++2upmm7pBqz6r4sokcxGSmHTkRMqm2yw==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.12", + "@storybook/api": "6.5.12", + "@storybook/channels": "6.5.12", + "@storybook/client-logger": "6.5.12", + "@storybook/components": "6.5.12", + "@storybook/core-events": "6.5.12", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/theming": "6.5.12", + "axe-core": "^4.2.0", + "core-js": "^3.8.2", + "global": "^4.4.0", + "lodash": "^4.17.21", + "react-sizeme": "^3.0.1", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + } + }, "@storybook/addon-actions": { "version": "6.5.12", "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.5.12.tgz", @@ -42992,6 +43690,15 @@ "regenerator-runtime": "^0.13.7" } }, + "@storybook/expect": { + "version": "27.5.2-0", + "resolved": "https://registry.npmjs.org/@storybook/expect/-/expect-27.5.2-0.tgz", + "integrity": "sha512-cP99mhWN/JeCp7VSIiymvj5tmuMY050iFohvp8Zq+kewKsBSZ6/qpTJAGCCZk6pneTcp4S0Fm5BSqyxzbyJ3gw==", + "dev": true, + "requires": { + "@types/jest": ">=26.0.0" + } + }, "@storybook/instrumenter": { "version": "6.5.12", "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-6.5.12.tgz", @@ -43005,6 +43712,101 @@ "global": "^4.4.0" } }, + "@storybook/jest": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@storybook/jest/-/jest-0.0.10.tgz", + "integrity": "sha512-qeYLIplpcOUQXboJde5pRCjTvkGmF80jEszRUoNYCNcEPfC2sMK68Wq6Ct8EQj3CoEdJqsK54O2YYh+7D9S+ag==", + "dev": true, + "requires": { + "@storybook/expect": "storybook-jest", + "@storybook/instrumenter": "^6.4.0", + "@testing-library/jest-dom": "^5.16.2", + "jest-mock": "^27.3.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "@storybook/manager-webpack4": { "version": "6.5.12", "resolved": "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.5.12.tgz", @@ -45218,6 +46020,15 @@ "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", "dev": true }, + "@types/mkdirp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.2.tgz", + "integrity": "sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/node": { "version": "18.8.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.3.tgz", @@ -45271,6 +46082,24 @@ "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==", "dev": true }, + "@types/pixelmatch": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@types/pixelmatch/-/pixelmatch-5.2.4.tgz", + "integrity": "sha512-HDaSHIAv9kwpMN7zlmwfTv6gax0PiporJOipcrGsVNF3Ba+kryOZc0Pio5pn6NhisgWr7TaajlPEKTbTAypIBQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/pngjs": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/pngjs/-/pngjs-6.0.1.tgz", + "integrity": "sha512-J39njbdW1U/6YyVXvC9+1iflZghP8jgRf2ndYghdJb5xL49LYDB+1EuAxfbuJ2IBbWIL3AjHPQhgaTxT3YaYeg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/prettier": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz", @@ -46286,8 +47115,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", - "dev": true, - "optional": true + "dev": true }, "array-flatten": { "version": "1.1.1", @@ -46610,6 +47438,12 @@ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", "dev": true }, + "axe-core": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz", + "integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==", + "dev": true + }, "axios": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", @@ -46929,6 +47763,12 @@ "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", "dev": true }, + "batch-processor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz", + "integrity": "sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA==", + "dev": true + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -47922,6 +48762,12 @@ "restore-cursor": "^3.1.0" } }, + "cli-spinner": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/cli-spinner/-/cli-spinner-0.2.10.tgz", + "integrity": "sha512-U0sSQ+JJvSLi1pAYuJykwiA8Dsr15uHEy85iCJ6A+0DjVxivr3d+N2Wjvodeg89uP5K6TswFkKBfAD7B3YSn/Q==", + "dev": true + }, "cli-table3": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", @@ -49104,7 +49950,6 @@ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", "dev": true, - "optional": true, "requires": { "array-find-index": "^1.0.1" } @@ -49174,6 +50019,12 @@ "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==", "dev": true }, + "decode-tiff": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/decode-tiff/-/decode-tiff-0.2.1.tgz", + "integrity": "sha512-v/7hQBv/DrOVQ+Eljg0BLMRbXZYuuw3YZ8duZuFxYpo6qUkdn7oFRkN95RZKbnh08EHNjrMXMbEUNhTLuhPvvA==", + "dev": true + }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -49775,6 +50626,15 @@ "integrity": "sha512-EpuHPqu8YhonqLBXHoU6hDJCD98FCe6KDoet3/gY1qsQ6usjJoHqBH2YIVs8FXaAtHwVL8Uqa/fsYao/vq9VWQ==", "dev": true }, + "element-resize-detector": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.4.tgz", + "integrity": "sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==", + "dev": true, + "requires": { + "batch-processor": "1.0.0" + } + }, "elliptic": { "version": "6.5.4", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", @@ -51782,6 +52642,12 @@ "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", "dev": true }, + "harmony-reflect": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", + "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==", + "dev": true + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -52314,6 +53180,15 @@ "integrity": "sha512-Wsk07aAxDsntgYJY4h0knZJuTxM73eQ4reRAO+Z1liOh8eMCJ/MoDS8fCui1vGT9mnjtl1sOu3I2i/W1swPYZg==", "dev": true }, + "identity-obj-proxy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", + "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", + "dev": true, + "requires": { + "harmony-reflect": "^1.4.6" + } + }, "ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", @@ -52332,6 +53207,37 @@ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true }, + "img-diff-js": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/img-diff-js/-/img-diff-js-0.5.2.tgz", + "integrity": "sha512-edvMoyVOrEFC/evz/DYBJ0tmvQ0YeQ+qQZdN4r6LIFxDq1vBd/Pt/+pPOlu9h/whBDiAdQrDkNWtnrpyBMpFOw==", + "dev": true, + "requires": { + "@types/mkdirp": "^1.0.1", + "@types/node": "^14.11.2", + "@types/pixelmatch": "^5.2.2", + "@types/pngjs": "^6.0.0", + "decode-tiff": "^0.2.0", + "jpeg-js": "^0.4.2", + "mkdirp": "^1.0.4", + "pixelmatch": "^5.2.1", + "pngjs": "^6.0.0" + }, + "dependencies": { + "@types/node": { + "version": "14.18.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.33.tgz", + "integrity": "sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==", + "dev": true + }, + "pngjs": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", + "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", + "dev": true + } + } + }, "immer": { "version": "9.0.15", "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz", @@ -52827,8 +53733,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true, - "optional": true + "dev": true }, "is-fullwidth-code-point": { "version": "1.0.0", @@ -53043,8 +53948,7 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", - "dev": true, - "optional": true + "dev": true }, "is-weakref": { "version": "1.0.2", @@ -54746,6 +55650,12 @@ "@sideway/pinpoint": "^2.0.0" } }, + "jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", + "dev": true + }, "js-base64": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", @@ -55008,7 +55918,6 @@ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", "dev": true, - "optional": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", @@ -55022,7 +55931,6 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", "dev": true, - "optional": true, "requires": { "error-ex": "^1.2.0" } @@ -55031,15 +55939,13 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "optional": true + "dev": true }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", "dev": true, - "optional": true, "requires": { "is-utf8": "^0.2.0" } @@ -55237,7 +56143,6 @@ "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ==", "dev": true, - "optional": true, "requires": { "currently-unhandled": "^0.4.1", "signal-exit": "^3.0.0" @@ -55356,6 +56261,12 @@ "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", "dev": true }, + "md5-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-4.0.0.tgz", + "integrity": "sha512-UC0qFwyAjn4YdPpKaDNw6gNxRf7Mcx7jC1UGCY4boCzgvU2Aoc1mOGzTtrjjLKhM5ivsnhoKpQVxKPp+1j1qwg==", + "dev": true + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -55808,6 +56719,12 @@ "thunky": "^1.0.2" } }, + "mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "dev": true + }, "nan": { "version": "2.16.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", @@ -59043,6 +59960,18 @@ "dev": true, "requires": {} }, + "react-sizeme": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/react-sizeme/-/react-sizeme-3.0.2.tgz", + "integrity": "sha512-xOIAOqqSSmKlKFJLO3inBQBdymzDuXx4iuwkNcJmC96jeiOg5ojByvL+g3MW9LPEsojLbC6pf68zOfobK8IPlw==", + "dev": true, + "requires": { + "element-resize-detector": "^1.2.2", + "invariant": "^2.2.4", + "shallowequal": "^1.1.0", + "throttle-debounce": "^3.0.1" + } + }, "react-speech-recognition": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/react-speech-recognition/-/react-speech-recognition-3.10.0.tgz", @@ -59197,6 +60126,295 @@ "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", "requires": {} }, + "reg-cli": { + "version": "0.17.7", + "resolved": "https://registry.npmjs.org/reg-cli/-/reg-cli-0.17.7.tgz", + "integrity": "sha512-cwAJ7Zf/0tv6TArIIrZExJrnmiaTjiZj74ajXpYi8FLux6yOqFdfFfOOUJEIW1DP0zFASuG8HBf1v6m+dY575g==", + "dev": true, + "requires": { + "bluebird": "3.7.2", + "chalk": "4.1.2", + "cli-spinner": "0.2.10", + "cross-spawn": "7.0.3", + "del": "6.0.0", + "glob": "7.2.0", + "img-diff-js": "0.5.2", + "jpeg-js": "^0.4.0", + "lodash": "4.17.21", + "make-dir": "3.1.0", + "md5-file": "4.0.0", + "meow": "3.7.0", + "mustache": "4.2.0", + "x-img-diff-js": "0.3.5", + "yargs-parser": "^21.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha512-bA/Z/DERHKqoEOrp+qeGKw1QlvEQkGZSc0XaY6VnTxZr+Kv1G5zFwttpjv8qxZ/sBPT4nthwZaAcsAZTJlSKXQ==", + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "del": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "dev": true, + "requires": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==", + "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g==", + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha512-I5iQq6aFMM62fBEAIB/hXzwJD6EEZ0xEGCX2t7oXqaKPIRgt4WruAQ285BISgdkP+HLGWyeGmNJcpIwFeRYRUA==", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha512-Nm4cF79FhSTzrLKGDMi3I4utBtFv8qKy4sq1enftf2gMdpqI8oVQTAfySkTz5r49giVzDj88SVZXP4CeYQwjaw==", + "dev": true + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + } + } + }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -59475,7 +60693,6 @@ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==", "dev": true, - "optional": true, "requires": { "is-finite": "^1.0.0" } @@ -60490,6 +61707,12 @@ "kind-of": "^6.0.2" } }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "dev": true + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -61117,6 +62340,22 @@ "integrity": "sha512-siT1RiqlfQnGqgT/YzXVUNsom9S0H1OX+dpdGN1xkyYATo4I6sep5NmsRD/40s3IIOvlCq6akxkqG82urIZW1w==", "dev": true }, + "storybook-i18n": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/storybook-i18n/-/storybook-i18n-1.1.4.tgz", + "integrity": "sha512-0xD005aEBWhuDFU9oO5Yf+33MZQa/NWa2CWjkBODhcqC+N5WJhEPGUSQs8o9AqzQoRpIBOMQ3CS0cbRGbBuTxQ==", + "dev": true, + "requires": {} + }, + "storybook-react-intl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/storybook-react-intl/-/storybook-react-intl-1.1.1.tgz", + "integrity": "sha512-KD1G7TPo3+9nBXMkg6lk9MpS3RYMjUxam8d5S/NhHwzom0cnTk2AW4bd0zRmJkdjds1xuIhwZxet7Ebp9dggzw==", + "dev": true, + "requires": { + "storybook-i18n": "^1.1.2" + } + }, "stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", @@ -61816,6 +63055,12 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "throttle-debounce": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", + "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==", + "dev": true + }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -62087,93 +63332,12 @@ "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==", "dev": true }, - "tsconfig-paths": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.1.0.tgz", - "integrity": "sha512-AHx4Euop/dXFC+Vx589alFba8QItjF+8hf8LtmuiCwHyI4rHXQtOOENaM8kvYf5fR0dRChy3wzWIZ9WbB7FWow==", - "dev": true, - "requires": { - "json5": "^2.2.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - } - } - }, "tsconfig-paths-jest": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tsconfig-paths-jest/-/tsconfig-paths-jest-0.0.1.tgz", "integrity": "sha512-YKhUKqbteklNppC2NqL7dv1cWF8eEobgHVD5kjF1y9Q4ocqpBiaDlYslQ9eMhtbqIPRrA68RIEXqknEjlxdwxw==", "dev": true }, - "tsconfig-paths-webpack-plugin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.0.0.tgz", - "integrity": "sha512-fw/7265mIWukrSHd0i+wSwx64kYUSAKPfxRDksjKIYTxSAp9W9/xcZVBF4Kl0eqQd5eBpAQ/oQrc5RyM/0c1GQ==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.7.0", - "tsconfig-paths": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -64019,6 +65183,12 @@ "default-browser-id": "^1.0.4" } }, + "x-img-diff-js": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/x-img-diff-js/-/x-img-diff-js-0.3.5.tgz", + "integrity": "sha512-B97ztoc2JeM+62HH1zFhmTyilsVqL486WMm8X3oQz16lTCGITY1cz+H57mTsNG0QuyVxv1yGq06qC8wy6UPCmQ==", + "dev": true + }, "xml-name-validator": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", diff --git a/apps/client/package.json b/apps/client/package.json index 90f50d7..7edcebe 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -1,6 +1,6 @@ { "name": "@rss-reader/client", - "version": "1.13.4", + "version": "1.13.6", "description": "frontend part", "browserslist": "> 0.25%, not dead", "scripts": { @@ -12,8 +12,9 @@ "test:jest:watch": "npx jest --watch", "test:jest:coverage": "npx jest --coverage", "test:screenshots": "npx loki test", - "test:screenshots-ci": "npm run build-storybook && npx loki --requireReference --reactUri file:./storybook-static && rm -rf storybook-static", - "test": "npm run test:eslint && npm run test:stylelint && npm run test:jest", + "test:screenshots-ci": "npm run build-storybook && npx loki --requireReference --reactUri file:./storybook-static && rm -rf ./storybook-static", + "test:screenshots-report": "cd .loki && reg-cli ./current/ ./reference/ ./reg-diff/ -R ./report.html -I && cp -r difference/ reg-diff && open ./report.html", + "test": "npm run test:eslint && npm run test:stylelint && npm run test:jest && npm run test:screenshots-ci", "dev": "cross-env NODE_ENV=development npx webpack --mode development", "build": "cross-env NODE_ENV=production npx webpack --mode production", "heroku-postbuild": "npm run build", @@ -32,12 +33,14 @@ "@babel/preset-react": "^7.16.0", "@babel/preset-typescript": "^7.16.0", "@babel/runtime": "^7.16.3", + "@storybook/addon-a11y": "^6.5.12", "@storybook/addon-actions": "^6.5.12", "@storybook/addon-essentials": "^6.5.12", "@storybook/addon-interactions": "^6.5.12", "@storybook/addon-links": "^6.5.12", "@storybook/addons": "^6.5.12", "@storybook/builder-webpack5": "^6.5.12", + "@storybook/jest": "^0.0.10", "@storybook/manager-webpack5": "^6.5.12", "@storybook/react": "^6.5.12", "@storybook/testing-library": "^0.0.13", @@ -74,6 +77,7 @@ "file-loader": "^6.2.0", "fork-ts-checker-webpack-plugin": "^6.4.0", "html-webpack-plugin": "^5.5.0", + "identity-obj-proxy": "^3.0.0", "jest": "^29.1.2", "jest-environment-jsdom": "^29.1.2", "loki": "^0.30.3", @@ -86,14 +90,15 @@ "prettier": "^2.7.1", "prettier-eslint": "^15.0.1", "react-helmet": "^6.1.0", + "reg-cli": "^0.17.7", "sass-loader": "^12.3.0", + "storybook-react-intl": "^1.1.1", "style-loader": "^3.3.1", "stylelint": "^14.13.0", "stylelint-config-standard-scss": "^5.0.0", "terser-webpack-plugin": "^5.2.4", "ts-loader": "^9.2.6", "tsconfig-paths-jest": "^0.0.1", - "tsconfig-paths-webpack-plugin": "^4.0.0", "typescript": "^4.4.4", "webpack": "^5.61.0", "webpack-bundle-analyzer": "^4.5.0", diff --git a/apps/client/src/assets/imgs/creepy-aurora.jpg b/apps/client/src/assets/imgs/creepy-aurora.jpg new file mode 100644 index 0000000..8404ad7 Binary files /dev/null and b/apps/client/src/assets/imgs/creepy-aurora.jpg differ diff --git a/apps/client/src/components/UI/burger-btn/BurgerBtn.stories.tsx b/apps/client/src/components/UI/burger-btn/BurgerBtn.stories.tsx new file mode 100644 index 0000000..16967ad --- /dev/null +++ b/apps/client/src/components/UI/burger-btn/BurgerBtn.stories.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import type { ComponentMeta, ComponentStory } from '@storybook/react'; + +import { BurgerBtn } from '@/components/UI/burger-btn'; + +export default { + title: 'components/UI/BurgerBtn', + component: BurgerBtn, + parameters: { + layout: 'centered', + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Default = Template.bind({}); + +Default.args = { + isActive: false, + onClick: () => alert('click'), +}; diff --git a/apps/client/src/components/UI/burger-btn/BurgerBtn.test.tsx b/apps/client/src/components/UI/burger-btn/BurgerBtn.test.tsx index 22009bb..81ba785 100644 --- a/apps/client/src/components/UI/burger-btn/BurgerBtn.test.tsx +++ b/apps/client/src/components/UI/burger-btn/BurgerBtn.test.tsx @@ -1,19 +1,20 @@ import React from 'react'; -import { IntlProvider } from 'react-intl'; import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; -import { messages } from '@/i18n/messages'; +import withIntl from '@/hocs/withIntl'; +import type { BurgerBtnProps } from './BurgerBtn'; import { BurgerBtn } from './BurgerBtn'; -it('должен отрендерить компонент', () => { - const lang = 'ru'; +it('should call onClick', () => { + const BurgerBtnSmart = withIntl(BurgerBtn); + const onClick = jest.fn(); - render( - - 'kek'} /> - , - ); + render(); - expect(screen.getByRole('button')).toBeInTheDocument(); + const btn = screen.getByRole('button', { name: 'Settings', expanded: false }); + userEvent.click(btn); + + expect(onClick).toHaveBeenCalledTimes(1); }); diff --git a/apps/client/src/components/UI/burger-btn/BurgerBtn.tsx b/apps/client/src/components/UI/burger-btn/BurgerBtn.tsx index aa088f2..a615ba1 100644 --- a/apps/client/src/components/UI/burger-btn/BurgerBtn.tsx +++ b/apps/client/src/components/UI/burger-btn/BurgerBtn.tsx @@ -4,7 +4,10 @@ import { useIntl } from 'react-intl'; import { MESSAGES } from '@/i18n/types'; -import type { BurgerBtnProps } from './types'; +export interface BurgerBtnProps { + isActive: boolean; + onClick: () => void; +} export const BurgerBtn: FC = ({ isActive, onClick }) => { const intl = useIntl(); diff --git a/apps/client/src/components/UI/burger-btn/types.ts b/apps/client/src/components/UI/burger-btn/types.ts deleted file mode 100644 index 3aac9c4..0000000 --- a/apps/client/src/components/UI/burger-btn/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface BurgerBtnProps { - isActive: boolean; - onClick: () => void; -} diff --git a/apps/client/src/components/UI/content-skeleton/ContentSkeleton.stories.tsx b/apps/client/src/components/UI/content-skeleton/ContentSkeleton.stories.tsx new file mode 100644 index 0000000..33f3fa9 --- /dev/null +++ b/apps/client/src/components/UI/content-skeleton/ContentSkeleton.stories.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import { configureStore } from '@reduxjs/toolkit'; +import type { ComponentMeta, ComponentStory } from '@storybook/react'; + +import { ContentSkeleton } from '@/components/UI/content-skeleton'; +import settingsReducer from '@/store/slices/settingsSlice'; +import type { SettingsState } from '@/store/types'; + +export default { + title: 'components/UI/ContentSkeleton', + component: ContentSkeleton, +} as ComponentMeta; + +const Template: ComponentStory = () => ( + +); + +export const Light = Template.bind({}); +export const Dark = Template.bind({}); + +const componentsData = [ + { + Component: Light, + preloadedState: {}, + backgroundColor: 'transparent', + }, + { + Component: Dark, + preloadedState: { settings: { isDarkTheme: true } as SettingsState }, + backgroundColor: '#6c757d', + }, +]; + +componentsData.forEach(({ Component, preloadedState, backgroundColor }) => { + Component.decorators = [ + (Story) => { + const store = configureStore({ + reducer: { settings: settingsReducer }, + preloadedState, + }); + + const isDarkTheme = preloadedState.settings?.isDarkTheme; + + return ( + +
+ +
+
+ ); + }, + ]; +}); diff --git a/apps/client/src/components/UI/my-drop-down/MyDropDown.stories.tsx b/apps/client/src/components/UI/my-drop-down/MyDropDown.stories.tsx new file mode 100644 index 0000000..4499c75 --- /dev/null +++ b/apps/client/src/components/UI/my-drop-down/MyDropDown.stories.tsx @@ -0,0 +1,67 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import { configureStore } from '@reduxjs/toolkit'; +import type { ComponentMeta, ComponentStory } from '@storybook/react'; +import { userEvent, within } from '@storybook/testing-library'; + +import { MyDropDown } from '@/components/UI/my-drop-down'; +import settingsReducer from '@/store/slices/settingsSlice'; +import type { SettingsState } from '@/store/types'; +import { POST_STATES } from '@/store/types'; + +export default { + title: 'components/UI/MyDropDown', + component: MyDropDown, + parameters: { + layout: 'centered', + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Default = Template.bind({}); + +// TODO: @loki/create-async-callback +// wait for this package to work to test asynchronous actions +// export const ExpandedLight = Template.bind({}); +// export const ExpandedDark = Template.bind({}); + +const Components = [Default /* ExpandedLight, ExpandedDark */]; + +Components.forEach((Component, index) => { + Component.decorators = [ + (Story) => { + const store = configureStore({ + reducer: { settings: settingsReducer }, + preloadedState: { + settings: { isDarkTheme: Boolean(index === 2) } as SettingsState, + }, + }); + + return ( + +
+ +
+
+ ); + }, + ]; + + if (index) { + Component.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await userEvent.click(canvas.getByRole('button')); + }; + } + + Component.args = { + activeValue: POST_STATES.ALL, + title: 'All', + values: Object.values(POST_STATES), + variant: 'outline-secondary', + }; +}); diff --git a/apps/client/src/components/UI/my-drop-down/MyDropDown.test.tsx b/apps/client/src/components/UI/my-drop-down/MyDropDown.test.tsx new file mode 100644 index 0000000..7097615 --- /dev/null +++ b/apps/client/src/components/UI/my-drop-down/MyDropDown.test.tsx @@ -0,0 +1,42 @@ +import type { ComponentType } from 'react'; +import React from 'react'; +import { compose } from '@reduxjs/toolkit'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import withIntl from '@/hocs/withIntl'; +import withStateProvider from '@/hocs/withStateProvider'; +import settingsReducer from '@/store/slices/settingsSlice'; +import type { POST_STATE_TYPE } from '@/store/types'; +import { POST_STATES } from '@/store/types'; + +import type { MyDropDownProps } from './MyDropDown'; +import { MyDropDown } from './MyDropDown'; + +it('should toggle drop-down on click', async () => { + const MyDropDownSmart = compose< + ComponentType> + >( + withStateProvider({ settings: settingsReducer }), + withIntl, + )(MyDropDown); + + const values = Object.values(POST_STATES); + + const { container } = render( + , + ); + + expect(container).toMatchSnapshot(); + + const toggleEl = screen.getByRole('button', { name: 'LOL', expanded: false }); + await userEvent.click(toggleEl); + + expect(container).toMatchSnapshot(); +}); diff --git a/apps/client/src/components/UI/my-drop-down/MyDropDown.tsx b/apps/client/src/components/UI/my-drop-down/MyDropDown.tsx index e960271..a9e5832 100644 --- a/apps/client/src/components/UI/my-drop-down/MyDropDown.tsx +++ b/apps/client/src/components/UI/my-drop-down/MyDropDown.tsx @@ -1,20 +1,27 @@ import type { FC } from 'react'; import React from 'react'; import { Dropdown, DropdownButton } from 'react-bootstrap'; +import type { Variant } from 'react-bootstrap/esm/types'; import { FormattedMessage } from 'react-intl'; import { useTypedSelector } from '@/hooks'; import { selectSettings } from '@/store/selectors/settingsSelectors'; import type { POST_STATE_TYPE } from '@/store/types'; -import type { MyDropDownProps } from './types'; +export interface MyDropDownProps { + variant: Variant; + title: string; + values: Array; + activeValue: T; + onItemClick: (value: T) => () => void; +} export const MyDropDown: FC> = ({ variant, title, values, activeValue, - handleSetActiveValue, + onItemClick, }) => { const { isDarkTheme } = useTypedSelector(selectSettings); @@ -28,7 +35,7 @@ export const MyDropDown: FC> = ({ diff --git a/apps/client/src/components/UI/my-drop-down/__snapshots__/MyDropDown.test.tsx.snap b/apps/client/src/components/UI/my-drop-down/__snapshots__/MyDropDown.test.tsx.snap new file mode 100644 index 0000000..c541843 --- /dev/null +++ b/apps/client/src/components/UI/my-drop-down/__snapshots__/MyDropDown.test.tsx.snap @@ -0,0 +1,73 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should toggle drop-down on click 1`] = ` +
+ +
+`; + +exports[`should toggle drop-down on click 2`] = ` +
+ +
+`; diff --git a/apps/client/src/components/UI/my-drop-down/types.ts b/apps/client/src/components/UI/my-drop-down/types.ts deleted file mode 100644 index 7d57511..0000000 --- a/apps/client/src/components/UI/my-drop-down/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Variant } from 'react-bootstrap/esm/types'; - -export interface MyDropDownProps { - variant: Variant; - title: string; - values: Array; - activeValue: T; - handleSetActiveValue: (value: T) => () => void; -} diff --git a/apps/client/src/components/UI/my-modal/MyModal.stories.tsx b/apps/client/src/components/UI/my-modal/MyModal.stories.tsx new file mode 100644 index 0000000..2f93691 --- /dev/null +++ b/apps/client/src/components/UI/my-modal/MyModal.stories.tsx @@ -0,0 +1,102 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import { configureStore } from '@reduxjs/toolkit'; +import type { ComponentMeta, ComponentStory } from '@storybook/react'; + +import imgSrc from '@/assets/imgs/creepy-aurora.jpg'; +import { MyModal } from '@/components/UI/my-modal'; +import { AppRootElContext } from '@/contexts'; +import settingsReducer from '@/store/slices/settingsSlice'; +import type { SettingsState } from '@/store/types'; + +import { MODAL_TYPES } from './types'; + +export default { + title: 'components/UI/MyModal', + component: MyModal, + parameters: { + layout: 'centered', + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const SimpleLight = Template.bind({}); +export const SimpleDark = Template.bind({}); +export const WithImageLight = Template.bind({}); +export const WithImageDark = Template.bind({}); + +const componentsData = [ + { + Component: SimpleLight, + preloadedState: {}, + type: MODAL_TYPES.PREVIEW, + imgSrc: '', + url: 'https://rss-reader-web-client.herokuapp.com/', + }, + { + Component: SimpleDark, + preloadedState: { + settings: { isDarkTheme: true } as SettingsState, + }, + type: MODAL_TYPES.PREVIEW, + imgSrc: '', + url: 'asd', + }, + { + Component: WithImageLight, + preloadedState: {}, + type: MODAL_TYPES.PREVIEW, + imgSrc, + url: 'https://rss-reader-web-client.herokuapp.com/', + }, + { + Component: WithImageDark, + preloadedState: { + settings: { isDarkTheme: true } as SettingsState, + }, + type: MODAL_TYPES.PREVIEW, + imgSrc, + url: 'asd', + }, +]; + +componentsData.forEach(({ Component, preloadedState, type, imgSrc, url }) => { + Component.decorators = [ + (Story) => { + const store = configureStore({ + reducer: { + settings: settingsReducer, + rssMeta: settingsReducer, + }, + preloadedState, + }); + + preloadedState.settings?.isDarkTheme + ? document.body.classList.add('dark-theme') + : document.body.classList.remove('dark-theme'); + + return ( + + + + + + ); + }, + ]; + + Component.args = { + title: 'Lorem ipsum', + description: + 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Consectetur, a maiores nulla vel laborum voluptatibus maxime provident hic commodi qui eius accusamus nihil eveniet delectus earum vitae. Harum, beatae suscipit?', + isShow: true, + imgSrc, + url, + type, + handleClose: () => alert('close'), + handleAction: () => alert('action'), + }; +}); diff --git a/apps/client/src/components/UI/my-modal/MyModal.test.tsx b/apps/client/src/components/UI/my-modal/MyModal.test.tsx new file mode 100644 index 0000000..e21c75d --- /dev/null +++ b/apps/client/src/components/UI/my-modal/MyModal.test.tsx @@ -0,0 +1,77 @@ +import type { ComponentType } from 'react'; +import React from 'react'; +import { compose } from '@reduxjs/toolkit'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import withIntl from '@/hocs/withIntl'; +import withStateProvider from '@/hocs/withStateProvider'; +import rssMetaReducer from '@/store/slices/rssMetaSlice'; +import settingsReducer from '@/store/slices/settingsSlice'; + +import type { MyModalProps } from './MyModal'; +import { MyModal } from './MyModal'; +import { MODAL_TYPES } from './types'; + +const setMatchMediaMock = (matches?: boolean) => + jest.fn().mockReturnValue({ matches }); + +beforeEach(() => { + global.window.matchMedia = setMatchMediaMock(); +}); + +it('should not render modal if prop isShow = false', () => { + renderComponent({ isShow: false }); + + expect(screen.queryByRole('dialog')).toBe(null); +}); + +it('should center modal on layout if isTouchDevice', () => { + global.window.matchMedia = setMatchMediaMock(true); + + renderComponent({ isShow: true }); + + expect(document.querySelector('.modal-dialog-centered')).toBeInTheDocument(); +}); + +it('should call handleClose on click', async () => { + const handleClose = jest.fn(); + + renderComponent({ isShow: true, handleClose }); + + await userEvent.click(screen.getByRole('button', { name: 'Close' })); + await userEvent.click( + screen.getByRole('button', { name: 'Close modal window' }), + ); + + const modalBackropEl = document.querySelector('.modal-backdrop') as Element; + await userEvent.click(modalBackropEl); + + expect(handleClose).toHaveBeenCalledTimes(3); +}); + +function renderComponent( + props: Partial = {}, + preloadedState = {}, +) { + const MyModalSmart = compose>( + withStateProvider( + { + rssMeta: rssMetaReducer, + settings: settingsReducer, + }, + preloadedState, + ), + withIntl, + )(MyModal); + + return render( + , + ); +} diff --git a/apps/client/src/components/UI/my-modal/MyModal.tsx b/apps/client/src/components/UI/my-modal/MyModal.tsx index e4f4e2b..461ddae 100644 --- a/apps/client/src/components/UI/my-modal/MyModal.tsx +++ b/apps/client/src/components/UI/my-modal/MyModal.tsx @@ -1,17 +1,27 @@ import type { FC } from 'react'; +import { useContext } from 'react'; import React from 'react'; import { Button, Modal } from 'react-bootstrap'; import { FormattedMessage, useIntl } from 'react-intl'; +import { AppRootElContext } from '@/contexts'; import { useTypedSelector } from '@/hooks'; import { MESSAGES } from '@/i18n/types'; import { selectSettings } from '@/store/selectors/settingsSelectors'; +import type { ModalActionBtnProps } from './modal-action-btn/ModalActionBtn'; import { ModalActionBtn } from './modal-action-btn'; -import type { MyModalProps } from './types'; import styles from './styles.module.scss'; +export type MyModalProps = ModalActionBtnProps & { + isShow?: boolean; + handleClose: () => void; + title: string; + description: string; + imgSrc?: string; +}; + export const MyModal: FC = ({ type, isShow, @@ -27,9 +37,12 @@ export const MyModal: FC = ({ const intl = useIntl(); + const appRootEl = useContext(AppRootElContext); + return ( ; + +const Template: ComponentStory = (args) => ( + +); + +export const Preview = Template.bind({}); +export const Mark = Template.bind({}); +export const Delete = Template.bind({}); +export const DeleteInProcess = Template.bind({}); +export const Reload = Template.bind({}); + +const componentsData = [ + { + Component: Preview, + preloadedState: {}, + type: MODAL_TYPES.PREVIEW, + url: 'https://rss-reader-web-client.herokuapp.com/', + parameters: {}, + }, + { + Component: Mark, + preloadedState: {}, + type: MODAL_TYPES.MARK, + url: '', + parameters: {}, + }, + { + Component: Delete, + preloadedState: {}, + type: MODAL_TYPES.DELETE, + url: '', + parameters: {}, + }, + { + Component: DeleteInProcess, + preloadedState: { + rssMeta: { isFeedDeleteInProcess: true } as RssState, + }, + type: MODAL_TYPES.DELETE, + url: '', + parameters: { loki: { skip: true } }, + }, + { + Component: Reload, + preloadedState: {}, + type: MODAL_TYPES.RELOAD, + url: '', + parameters: {}, + }, +]; + +componentsData.forEach( + ({ Component, preloadedState, type, url, parameters }) => { + Component.decorators = [ + (Story) => { + const store = configureStore({ + reducer: { rssMeta: rssMetaReducer }, + preloadedState, + }); + + return ( + +
+ +
+
+ ); + }, + ]; + + Component.args = { + type, + url, + }; + + Component.story = { + parameters, + }; + }, +); diff --git a/apps/client/src/components/UI/my-modal/modal-action-btn/ModalActionBtn.test.tsx b/apps/client/src/components/UI/my-modal/modal-action-btn/ModalActionBtn.test.tsx new file mode 100644 index 0000000..b58c4fc --- /dev/null +++ b/apps/client/src/components/UI/my-modal/modal-action-btn/ModalActionBtn.test.tsx @@ -0,0 +1,59 @@ +import type { ComponentType } from 'react'; +import React from 'react'; +import { compose } from '@reduxjs/toolkit'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import withIntl from '@/hocs/withIntl'; +import withStateProvider from '@/hocs/withStateProvider'; +import rssMetaReducer from '@/store/slices/rssMetaSlice'; + +import { MODAL_TYPES } from '../types'; + +import type { ModalActionBtnProps } from './ModalActionBtn'; +import { ModalActionBtn } from './ModalActionBtn'; + +const URL = 'https://kek.wut'; + +it('should render preview button with link', () => { + renderComponent({ type: MODAL_TYPES.PREVIEW, url: URL }); + + expect(screen.getByRole('link')).toHaveAttribute('href', URL); +}); + +it('should not render preview button without link', () => { + renderComponent({ type: MODAL_TYPES.PREVIEW }); + + expect(screen.queryByRole('link')).not.toBeInTheDocument(); +}); + +it('should render disabled delete button with loader', () => { + renderComponent( + { type: MODAL_TYPES.DELETE }, + { rssMeta: { isFeedDeleteInProcess: true } }, + ); + + expect(screen.getByRole('button')).toHaveAttribute('disabled'); + expect(document.querySelector('.spinner')).toBeInTheDocument(); +}); + +it('should call handleAction on click', async () => { + const handleAction = jest.fn(); + + renderComponent({ type: MODAL_TYPES.MARK, handleAction }); + + await userEvent.click(screen.getByRole('button')); + expect(handleAction).toHaveBeenCalledTimes(1); +}); + +function renderComponent( + props = {} as ModalActionBtnProps, + preloadedState = {}, +) { + const ModalActionBtnSmart = compose>( + withStateProvider({ rssMeta: rssMetaReducer }, preloadedState), + withIntl, + )(ModalActionBtn); + + return render(); +} diff --git a/apps/client/src/components/UI/my-modal/modal-action-btn/ModalActionBtn.tsx b/apps/client/src/components/UI/my-modal/modal-action-btn/ModalActionBtn.tsx index 01e53db..1f3ac87 100644 --- a/apps/client/src/components/UI/my-modal/modal-action-btn/ModalActionBtn.tsx +++ b/apps/client/src/components/UI/my-modal/modal-action-btn/ModalActionBtn.tsx @@ -8,9 +8,15 @@ import { useTypedSelector } from '@/hooks'; import { MESSAGES } from '@/i18n/types'; import { selectRssMeta } from '@/store/selectors/rssMetaSelectors'; -import type { ModalActionBtnProps } from '../types'; +import type { MODAL_TYPE } from '../types'; import { MODAL_TYPES } from '../types'; +export interface ModalActionBtnProps { + type: MODAL_TYPE; + handleAction?: () => void; + url?: string; +} + export const ModalActionBtn: FC = ({ type, handleAction, diff --git a/apps/client/src/components/UI/my-modal/types.ts b/apps/client/src/components/UI/my-modal/types.ts index 66394e5..d0bea2e 100644 --- a/apps/client/src/components/UI/my-modal/types.ts +++ b/apps/client/src/components/UI/my-modal/types.ts @@ -6,17 +6,3 @@ export enum MODAL_TYPES { } export type MODAL_TYPE = typeof MODAL_TYPES[keyof typeof MODAL_TYPES]; - -export interface ModalActionBtnProps { - type: MODAL_TYPE; - handleAction?: () => void; - url?: string; -} - -export type MyModalProps = ModalActionBtnProps & { - isShow: boolean; - handleClose: () => void; - title: string; - description: string; - imgSrc?: string; -}; diff --git a/apps/client/src/components/UI/my-spinner/MySpinner.stories.tsx b/apps/client/src/components/UI/my-spinner/MySpinner.stories.tsx new file mode 100644 index 0000000..34b4cd2 --- /dev/null +++ b/apps/client/src/components/UI/my-spinner/MySpinner.stories.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import type { ComponentMeta, ComponentStory } from '@storybook/react'; + +import { MySpinner } from '@/components/UI/my-spinner'; + +export default { + title: 'components/UI/MySpinner', + component: MySpinner, + parameters: { + layout: 'centered', + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Default = Template.bind({}); + +Default.args = { + isDark: false, + small: false, +}; + +Default.decorators = [ + (Story) => ( +
+ +
+ ), +]; + +Default.story = { + parameters: { loki: { skip: true } }, +}; diff --git a/apps/client/src/components/UI/my-spinner/MySpinner.test.tsx b/apps/client/src/components/UI/my-spinner/MySpinner.test.tsx new file mode 100644 index 0000000..7b0f6e4 --- /dev/null +++ b/apps/client/src/components/UI/my-spinner/MySpinner.test.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { render } from '@testing-library/react'; + +import withIntl from '@/hocs/withIntl'; + +import type { MySpinnerProps } from './MySpinner'; +import { MySpinner } from './MySpinner'; + +it('should render with ARIA-attributes', () => { + const MySpinnerSmart = withIntl(MySpinner); + + render(); + + const spinnerEl = document.querySelector('.spinner'); + + expect(spinnerEl).toHaveAttribute('role', 'status'); + expect(spinnerEl).toHaveAttribute('aria-hidden', 'true'); +}); diff --git a/apps/client/src/components/UI/my-spinner/MySpinner.tsx b/apps/client/src/components/UI/my-spinner/MySpinner.tsx index 58eaf8b..a8e2339 100644 --- a/apps/client/src/components/UI/my-spinner/MySpinner.tsx +++ b/apps/client/src/components/UI/my-spinner/MySpinner.tsx @@ -5,10 +5,13 @@ import cn from 'classnames'; import { MESSAGES } from '@/i18n/types'; -import type { MySpinnerProps } from './types'; - import styles from './styles.module.scss'; +export interface MySpinnerProps { + small?: boolean; + isDark?: boolean; +} + export const MySpinner: FC = ({ small = false, isDark = false, diff --git a/apps/client/src/components/UI/my-spinner/types.ts b/apps/client/src/components/UI/my-spinner/types.ts deleted file mode 100644 index 0bb16eb..0000000 --- a/apps/client/src/components/UI/my-spinner/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface MySpinnerProps { - small?: boolean; - isDark?: boolean; -} diff --git a/apps/client/src/components/UI/notification/Notification.stories.tsx b/apps/client/src/components/UI/notification/Notification.stories.tsx new file mode 100644 index 0000000..be5a4d8 --- /dev/null +++ b/apps/client/src/components/UI/notification/Notification.stories.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import type { ComponentMeta, ComponentStory } from '@storybook/react'; + +import { Notification } from '@/components/UI/notification'; +import { NOTIFICATION_VARIANT } from '@/components/UI/notification/types'; + +export default { + title: 'components/UI/Notification', + component: Notification, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Success = Template.bind({}); +export const Error = Template.bind({}); + +const baseArgs = { + isShow: true, + onClose: () => alert('close'), +}; + +const componentsData = [ + { + Component: Success, + args: { + ...baseArgs, + data: { + variant: NOTIFICATION_VARIANT.SUCCESS, + message: 'Success', + }, + }, + }, + { + Component: Error, + args: { + ...baseArgs, + data: { + variant: NOTIFICATION_VARIANT.ERROR, + message: 'Error', + }, + }, + }, +]; + +componentsData.forEach(({ Component, args }) => { + Component.args = args; +}); diff --git a/apps/client/src/components/UI/notification/Notification.test.tsx b/apps/client/src/components/UI/notification/Notification.test.tsx new file mode 100644 index 0000000..0b7538b --- /dev/null +++ b/apps/client/src/components/UI/notification/Notification.test.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { Notification } from './Notification'; +import { NOTIFICATION_VARIANT } from './types'; + +it('should render if isShow = true', () => { + render( + , + ); + + expect(screen.getByText('Success')).toBeInTheDocument(); +}); + +it('should not render if isShow = false', () => { + render( + , + ); + + expect(screen.queryByText('Success')).toBe(null); +}); + +it('should call onClose', () => { + const onClose = jest.fn(); + + render( + , + ); + + const closeBtn = screen.getByRole('button'); + userEvent.click(closeBtn); + + expect(onClose).toHaveBeenCalledTimes(1); +}); diff --git a/apps/client/src/components/UI/notification/Notification.tsx b/apps/client/src/components/UI/notification/Notification.tsx index 182c2a1..6979800 100644 --- a/apps/client/src/components/UI/notification/Notification.tsx +++ b/apps/client/src/components/UI/notification/Notification.tsx @@ -5,10 +5,18 @@ import cn from 'classnames'; import { SvgIcon } from '@/components/UI/svg-icon'; -import type { NotificationProps } from './types'; +import type { SVG_ICON_TYPE } from '../svg-icon/types'; + +import type { NotificationData } from './types'; import styles from './styles.module.scss'; +export interface NotificationProps { + data: NotificationData; + isShow: boolean; + onClose: () => void; +} + export const Notification: FC = ({ data, isShow, @@ -25,7 +33,7 @@ export const Notification: FC = ({ onClose={onClose} >
- +
{message} diff --git a/apps/client/src/components/UI/notification/types.ts b/apps/client/src/components/UI/notification/types.ts index 046c372..7537f9c 100644 --- a/apps/client/src/components/UI/notification/types.ts +++ b/apps/client/src/components/UI/notification/types.ts @@ -9,9 +9,3 @@ export interface NotificationData { variant: Variant; message: string; } - -export interface NotificationProps { - data: NotificationData; - isShow: boolean; - onClose: () => void; -} diff --git a/apps/client/src/components/UI/paginator/Paginator.stories.tsx b/apps/client/src/components/UI/paginator/Paginator.stories.tsx new file mode 100644 index 0000000..02a573e --- /dev/null +++ b/apps/client/src/components/UI/paginator/Paginator.stories.tsx @@ -0,0 +1,130 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import { configureStore } from '@reduxjs/toolkit'; +import type { ComponentMeta, ComponentStory } from '@storybook/react'; + +import { Paginator } from '@/components/UI/paginator'; +import settingsReducer from '@/store/slices/settingsSlice'; +import type { SettingsState } from '@/store/types'; + +export default { + title: 'components/UI/Paginator', + component: Paginator, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const SimpleLight = Template.bind({}); +export const SimpleDark = Template.bind({}); +export const SimpleWithArrowsLight = Template.bind({}); +export const SimpleWithArrowsDark = Template.bind({}); +export const ExtraFirstLight = Template.bind({}); +export const ExtraFirstDark = Template.bind({}); +export const ExtraMiddleLight = Template.bind({}); +export const ExtraMiddleDark = Template.bind({}); +export const ExtraLastLight = Template.bind({}); +export const ExtraLastDark = Template.bind({}); +export const BiggestMiddleLight = Template.bind({}); +export const BiggestMiddleDark = Template.bind({}); + +const componentsData = [ + { + Component: SimpleLight, + preloadedState: {}, + totalPages: 4, + }, + { + Component: SimpleDark, + preloadedState: { settings: { isDarkTheme: true } as SettingsState }, + totalPages: 4, + }, + { + Component: SimpleWithArrowsLight, + preloadedState: {}, + totalPages: 7, + }, + { + Component: SimpleWithArrowsDark, + preloadedState: { settings: { isDarkTheme: true } as SettingsState }, + totalPages: 7, + }, + { + Component: ExtraFirstLight, + preloadedState: {}, + totalPages: 8, + }, + { + Component: ExtraFirstDark, + preloadedState: { settings: { isDarkTheme: true } as SettingsState }, + totalPages: 8, + }, + { + Component: ExtraMiddleLight, + preloadedState: {}, + totalPages: 8, + activePage: 5, + }, + { + Component: ExtraMiddleDark, + preloadedState: { settings: { isDarkTheme: true } as SettingsState }, + totalPages: 8, + activePage: 5, + }, + { + Component: ExtraLastLight, + preloadedState: {}, + totalPages: 8, + activePage: 8, + }, + { + Component: ExtraLastDark, + preloadedState: { settings: { isDarkTheme: true } as SettingsState }, + totalPages: 8, + activePage: 8, + }, + { + Component: BiggestMiddleLight, + preloadedState: {}, + totalPages: 10, + activePage: 5, + }, + { + Component: BiggestMiddleDark, + preloadedState: { settings: { isDarkTheme: true } as SettingsState }, + totalPages: 10, + activePage: 5, + }, +]; + +componentsData.forEach( + ({ Component, preloadedState, totalPages, activePage = 1 }) => { + Component.decorators = [ + (Story) => { + const store = configureStore({ + reducer: { settings: settingsReducer }, + preloadedState, + }); + + const isDarkTheme = preloadedState.settings?.isDarkTheme; + + return ( + +
+ +
+
+ ); + }, + ]; + + Component.args = { + activePage, + totalPages, + }; + }, +); diff --git a/apps/client/src/components/UI/paginator/Paginator.test.tsx b/apps/client/src/components/UI/paginator/Paginator.test.tsx new file mode 100644 index 0000000..656d1a7 --- /dev/null +++ b/apps/client/src/components/UI/paginator/Paginator.test.tsx @@ -0,0 +1,52 @@ +import type { ComponentType } from 'react'; +import React from 'react'; +import { compose } from '@reduxjs/toolkit'; +import { render } from '@testing-library/react'; + +import withIntl from '@/hocs/withIntl'; +import withStateProvider from '@/hocs/withStateProvider'; +import settingsReducer from '@/store/slices/settingsSlice'; + +import type { PaginatorProps } from './Paginator'; +import { Paginator } from './Paginator'; + +it('should not render paginator', () => { + const { container } = renderComponent({ totalPages: 1 }); + + expect(container.firstChild).toBe(null); +}); + +it('should be disabled "Previous" arrow', () => { + renderComponent({ totalPages: 5, activePage: 1 }); + + expect(document.querySelectorAll('.page-link')[0]).toHaveAttribute( + 'disabled', + ); +}); + +it('should be disabled "Next" arrow', () => { + renderComponent({ totalPages: 5, activePage: 5 }); + + const pageLinks = document.querySelectorAll('.page-link'); + + expect(pageLinks[pageLinks.length - 1]).toHaveAttribute('disabled'); +}); + +function renderComponent({ + totalPages = 3, + activePage = 1, + onClick = () => jest.fn(), +}: Partial) { + const SimplePaginationSmart = compose>( + withStateProvider({ settings: settingsReducer }), + withIntl, + )(Paginator); + + return render( + , + ); +} diff --git a/apps/client/src/components/UI/paginator/Paginator.tsx b/apps/client/src/components/UI/paginator/Paginator.tsx index 3fcd90e..5749668 100644 --- a/apps/client/src/components/UI/paginator/Paginator.tsx +++ b/apps/client/src/components/UI/paginator/Paginator.tsx @@ -10,46 +10,34 @@ import { PAGINATOR_CAPACITY } from './types'; // not a module because only bootsrap's classNames import './style.scss'; -interface PaginatorProps { - withScroll?: boolean; +export interface PaginatorProps { totalPages: number; activePage: number; - setActivePage: (page: number) => void; + onClick: (page: number) => () => void; } export const Paginator: FC = React.memo( - ({ totalPages, activePage, setActivePage, withScroll }) => { + ({ totalPages, activePage, onClick }) => { if (totalPages < PAGINATOR_CAPACITY.MIN) { return null; } - const pagesColl: number[] = getPagesColl(totalPages); + const pagesColl = getPagesColl(totalPages); - const handleSetActivePage = (pageNumber: number) => () => { - setActivePage(pageNumber); - - if (withScroll) { - const postContainerEl = document.getElementById('post-container'); - - window.scrollTo({ - top: postContainerEl?.offsetTop, - behavior: 'smooth', - }); - } + const props = { + activePage, + pages: pagesColl, + onClick, }; - return totalPages < PAGINATOR_CAPACITY.EXTRA ? ( - - ) : ( - + return ( + ); }, ); diff --git a/apps/client/src/components/UI/paginator/pagination-inner/PaginationInner.tsx b/apps/client/src/components/UI/paginator/pagination-inner/PaginationInner.tsx index fa75ed5..bbe46c9 100644 --- a/apps/client/src/components/UI/paginator/pagination-inner/PaginationInner.tsx +++ b/apps/client/src/components/UI/paginator/pagination-inner/PaginationInner.tsx @@ -1,28 +1,21 @@ import type { FC } from 'react'; import React from 'react'; import { Pagination } from 'react-bootstrap'; -import cn from 'classnames'; -import type { PaginationInnerProps } from '../types'; +import type { PaginationProps } from '../types'; -export const PaginationInner: FC = ({ +export const PaginationInner: FC = ({ pages, activePage, - handleSetActivePage, - disableAnimation = false, + onClick, }) => ( <> {pages.map((page: number) => { - const classes = cn({ - animated: !disableAnimation && page === activePage, - }); - return ( {page} diff --git a/apps/client/src/components/UI/paginator/style.scss b/apps/client/src/components/UI/paginator/style.scss index 4f8a1d0..38fe9f5 100644 --- a/apps/client/src/components/UI/paginator/style.scss +++ b/apps/client/src/components/UI/paginator/style.scss @@ -30,10 +30,6 @@ background-color: $primary !important; } -.animated .page-link { - animation: smooth-color-change 0.2s; -} - .dark-theme { .page-link { color: $white !important; @@ -49,10 +45,6 @@ background-color: $material-darkgrey !important; border-color: $darkgrey !important; } - - .animated .page-link { - animation: none; - } } @include media-breakpoint-down(sm) { diff --git a/apps/client/src/components/UI/paginator/types.ts b/apps/client/src/components/UI/paginator/types.ts index 4f3f31f..a54b283 100644 --- a/apps/client/src/components/UI/paginator/types.ts +++ b/apps/client/src/components/UI/paginator/types.ts @@ -8,9 +8,5 @@ export enum PAGINATOR_CAPACITY { export interface PaginationProps { pages: number[]; activePage: number; - handleSetActivePage: (page: number) => () => void; + onClick: (page: number) => () => void; } - -export type PaginationInnerProps = PaginationProps & { - disableAnimation?: boolean; -}; diff --git a/apps/client/src/components/UI/paginator/variants/extra-paginaton/ExtraPagination.tsx b/apps/client/src/components/UI/paginator/variants/extra-paginaton/ExtraPagination.tsx index 7f1ae07..37838d7 100644 --- a/apps/client/src/components/UI/paginator/variants/extra-paginaton/ExtraPagination.tsx +++ b/apps/client/src/components/UI/paginator/variants/extra-paginaton/ExtraPagination.tsx @@ -12,39 +12,39 @@ import { PAGINATOR_CAPACITY } from '../../types'; export const ExtraPagination: FC = ({ pages, activePage, - handleSetActivePage, + onClick, }) => { const intl = useIntl(); + const isFirstPageActive = activePage === 1; + // first pages of pagination if (activePage < PAGINATOR_CAPACITY.MIDPOINT) { const firstPages = pages.slice(0, PAGINATOR_CAPACITY.MIDPOINT); return ( - + + + + + + {pages.length} + + + ); } @@ -59,21 +59,19 @@ export const ExtraPagination: FC = ({ role="navigation" > - - {1} - + {1} @@ -99,32 +97,28 @@ export const ExtraPagination: FC = ({ role="navigation" > - + {1} {pages.length} diff --git a/apps/client/src/components/UI/paginator/variants/simple-paginaton/SimplePagination.tsx b/apps/client/src/components/UI/paginator/variants/simple-paginaton/SimplePagination.tsx index ef875a7..704e757 100644 --- a/apps/client/src/components/UI/paginator/variants/simple-paginaton/SimplePagination.tsx +++ b/apps/client/src/components/UI/paginator/variants/simple-paginaton/SimplePagination.tsx @@ -7,38 +7,39 @@ import { MESSAGES } from '@/i18n/types'; import { PaginationInner } from '../../pagination-inner'; import type { PaginationProps } from '../../types'; +import { PAGINATOR_CAPACITY } from '../../types'; export const SimplePagination: FC = ({ pages, activePage, - handleSetActivePage, + onClick, }) => { const intl = useIntl(); + const shouldShowArrows = pages.length >= PAGINATOR_CAPACITY.MIDPOINT; + return ( - + )} + ); }; diff --git a/apps/client/src/components/UI/scroll-top-btn/ScrollTopBtn.stories.tsx b/apps/client/src/components/UI/scroll-top-btn/ScrollTopBtn.stories.tsx new file mode 100644 index 0000000..35f2da6 --- /dev/null +++ b/apps/client/src/components/UI/scroll-top-btn/ScrollTopBtn.stories.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import type { ComponentMeta, ComponentStory } from '@storybook/react'; + +import { ScrollTopBtn } from '@/components/UI/scroll-top-btn'; + +export default { + title: 'components/UI/ScrollTopBtn', + component: ScrollTopBtn, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const Light = Template.bind({}); +export const Dark = Template.bind({}); +export const LokiTestOnly = Template.bind({}); + +const componentsData = [ + { + Component: Light, + className: 'dark-theme', + backgroundColor: '#6c757d', + }, + { + Component: Dark, + className: '', + backgroundColor: 'transparent', + }, +]; + +componentsData.forEach(({ Component, className, backgroundColor }) => { + Component.decorators = [ + (Story) => ( +
+

Scroll to bottom to see

+ +
+ ), + ]; + + Component.story = { + parameters: { loki: { skip: true } }, + }; +}); diff --git a/apps/client/src/components/UI/scroll-top-btn/styles.module.scss b/apps/client/src/components/UI/scroll-top-btn/styles.module.scss index 29cb2bb..93c7a5e 100644 --- a/apps/client/src/components/UI/scroll-top-btn/styles.module.scss +++ b/apps/client/src/components/UI/scroll-top-btn/styles.module.scss @@ -33,3 +33,8 @@ } } } + +// screenshot tests only +*[loki-test] .scroll-top { + display: block; +} diff --git a/apps/client/src/components/UI/svg-icon/SvgIcon.stories.tsx b/apps/client/src/components/UI/svg-icon/SvgIcon.stories.tsx new file mode 100644 index 0000000..1e4b3c3 --- /dev/null +++ b/apps/client/src/components/UI/svg-icon/SvgIcon.stories.tsx @@ -0,0 +1,82 @@ +import React from 'react'; +import type { ComponentMeta, ComponentStory } from '@storybook/react'; + +import { SvgIcon } from '@/components/UI/svg-icon'; +import { SVG_ICON_VARIANTS } from '@/components/UI/svg-icon/types'; + +export default { + title: 'components/UI/SvgIcon', + component: SvgIcon, + parameters: { + layout: 'centered', + }, + argTypes: { + width: { + type: 'number', + defaultValue: 24, + }, + height: { + type: 'number', + defaultValue: 24, + }, + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const WiFiOff = Template.bind({}); +WiFiOff.args = { + variant: SVG_ICON_VARIANTS.WIFI_OFF, +}; + +export const Sort = Template.bind({}); +Sort.args = { + variant: SVG_ICON_VARIANTS.SORT, +}; + +export const SortReverse = Template.bind({}); +SortReverse.args = { + variant: SVG_ICON_VARIANTS.SORT_REVERSE, +}; + +export const User = Template.bind({}); +User.args = { + variant: SVG_ICON_VARIANTS.USER, +}; + +export const Lang = Template.bind({}); +Lang.args = { + variant: SVG_ICON_VARIANTS.LANG, +}; + +export const Reload = Template.bind({}); +Reload.args = { + variant: SVG_ICON_VARIANTS.RELOAD, +}; + +export const MicrophoneOn = Template.bind({}); +MicrophoneOn.args = { + variant: SVG_ICON_VARIANTS.MICROPHONE_ON, +}; + +export const MicrophoneOff = Template.bind({}); +MicrophoneOff.args = { + variant: SVG_ICON_VARIANTS.MICROPHONE_OFF, +}; + +export const SignOut = Template.bind({}); +SignOut.args = { + variant: SVG_ICON_VARIANTS.SIGN_OUT, +}; + +export const Success = Template.bind({}); +Success.args = { + variant: SVG_ICON_VARIANTS.SUCCESS, +}; + +export const Danger = Template.bind({}); +Danger.args = { + variant: SVG_ICON_VARIANTS.DANGER, +}; diff --git a/apps/client/src/components/UI/svg-icon/SvgIcon.test.tsx b/apps/client/src/components/UI/svg-icon/SvgIcon.test.tsx new file mode 100644 index 0000000..d4ce931 --- /dev/null +++ b/apps/client/src/components/UI/svg-icon/SvgIcon.test.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { render } from '@testing-library/react'; + +import { SvgIcon } from './SvgIcon'; + +it('should render default variant', () => { + const { container } = render(); + + expect(container).toMatchSnapshot(); +}); diff --git a/apps/client/src/components/UI/svg-icon/SvgIcon.tsx b/apps/client/src/components/UI/svg-icon/SvgIcon.tsx index 8905c60..acc8da4 100644 --- a/apps/client/src/components/UI/svg-icon/SvgIcon.tsx +++ b/apps/client/src/components/UI/svg-icon/SvgIcon.tsx @@ -1,9 +1,17 @@ import type { FC, ReactElement } from 'react'; import React, { useRef } from 'react'; -import type { SvgIconProps } from './types'; +import type { SVG_ICON_TYPE } from './types'; import { SVG_ICON_VARIANTS } from './types'; +export interface SvgIconProps { + variant?: SVG_ICON_TYPE; + className?: string; + width?: string | number; + height?: string | number; + fill?: string; +} + export const SvgIcon: FC = ({ variant, className, diff --git a/apps/client/src/components/UI/svg-icon/__snapshots__/SvgIcon.test.tsx.snap b/apps/client/src/components/UI/svg-icon/__snapshots__/SvgIcon.test.tsx.snap new file mode 100644 index 0000000..bbbfb8f --- /dev/null +++ b/apps/client/src/components/UI/svg-icon/__snapshots__/SvgIcon.test.tsx.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render default variant 1`] = ` +
+ +
+`; diff --git a/apps/client/src/components/UI/svg-icon/types.ts b/apps/client/src/components/UI/svg-icon/types.ts index 6f21823..0c10b52 100644 --- a/apps/client/src/components/UI/svg-icon/types.ts +++ b/apps/client/src/components/UI/svg-icon/types.ts @@ -14,11 +14,3 @@ export enum SVG_ICON_VARIANTS { export type SVG_ICON_TYPE = typeof SVG_ICON_VARIANTS[keyof typeof SVG_ICON_VARIANTS]; - -export interface SvgIconProps { - variant: SVG_ICON_TYPE | string; - className?: string; - width?: string | number; - height?: string | number; - fill?: string; -} diff --git a/apps/client/src/components/app/App.tsx b/apps/client/src/components/app/App.tsx index f99061b..9dd75c6 100644 --- a/apps/client/src/components/app/App.tsx +++ b/apps/client/src/components/app/App.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react'; -import React, { useEffect } from 'react'; +import React, { useEffect, useRef } from 'react'; import { IntlProvider } from 'react-intl'; import LoadingBar from 'react-redux-loading-bar'; import { BrowserRouter } from 'react-router-dom'; @@ -10,7 +10,7 @@ import { Footer } from '@/components/footer'; import { Header } from '@/components/header'; import { NetworkTooltip } from '@/components/network-tooltip'; import { MySpinner } from '@/components/UI/my-spinner'; -import { AuthContext } from '@/contexts'; +import { AppRootElContext, AuthContext } from '@/contexts'; import { useNetwork, useTypedDispatch, useTypedSelector } from '@/hooks'; import { messages } from '@/i18n/messages'; import userAPI from '@/services/UserService'; @@ -41,11 +41,15 @@ export const App: FC = () => { const userToken = userData.token; + const AppRootElRef = useRef(null); + useEffect(() => { const SpeechlySpeechRecognition = createSpeechlySpeechRecognition(SPEECHLY_APP_ID); SpeechRecognition.applyPolyfill(SpeechlySpeechRecognition); + + AppRootElRef.current = document.querySelector('#root'); }, []); useEffect(() => { @@ -62,22 +66,24 @@ export const App: FC = () => { return ( - - - - {!isOnline && } -
- {isAuthPending ? ( -
- -
- ) : ( - - - - )} -