From 0e42d5539b6c65032348fc6386b3c6c05fa707b8 Mon Sep 17 00:00:00 2001 From: William Wong Date: Tue, 29 Sep 2020 03:27:04 -0700 Subject: [PATCH 01/21] Add API package --- CHANGELOG.md | 5 + docs/HOOKS.md | 5 + packages/api/.eslintignore | 9 + packages/api/.eslintrc.yml | 91 + packages/api/.gitignore | 2 + packages/api/.prettierrc.yml | 11 + packages/api/babel.config.json | 48 + packages/api/package-lock.json | 7667 +++++++++++++++++ packages/api/package.json | 78 + .../scripts/createPrecompiledGlobalize.js | 9 +- packages/api/src/defaultStyleOptions.js | 202 + packages/api/src/hooks/Composer.js | 709 ++ packages/api/src/hooks/Composer.oldjs | 29 + .../{component => api}/src/hooks/index.js | 41 +- .../BypassSpeechSynthesisPonyfill.js | 0 .../src/hooks/internal}/Dictation.js | 29 +- packages/api/src/hooks/internal/ErrorBox.js | 30 + .../src => api/src/hooks/internal}/Tracker.js | 2 +- .../src/hooks/internal/WebChatAPIContext.js} | 2 +- .../hooks/internal}/WebChatReduxContext.js | 0 .../src/hooks/internal}/defaultSelectVoice.js | 0 .../internal}/defaultSelectVoice.test.js | 0 .../useCreateActivityRendererInternal.js | 19 +- .../src/hooks/internal/useDebugDeps.js | 0 .../api/src/hooks/internal/useDirFromProps.js | 5 + .../src/hooks/internal/useErrorBoxClass.js | 7 + .../src/hooks/internal/useForceRender.js | 0 .../internal/useForceRenderAtInterval.js | 0 .../useGetTranscriptActivityElementByID.js | 0 .../hooks/internal/useLocalizedGlobalize.js | 5 + .../src/hooks/internal/useLocalizedStrings.js | 7 + .../api/src/hooks/internal/useMarkActivity.js | 5 + .../internal/useReadTelemetryDimensions.js | 4 +- .../src/hooks/internal/useReplaceEmoticon.js | 0 .../src/hooks/internal/useSendBoxFocusRef.js | 5 + .../src/hooks/internal/useSetDictateState.js | 5 + .../internal/useSettableDictateAbortable.js | 7 + .../src/hooks/internal/useTimePassed.js | 0 .../src/hooks/internal/useTimer.js | 0 .../src/hooks/internal/useTracker.js | 4 +- .../hooks/internal/useTranscriptFocusRef.js | 5 + .../hooks/internal/useWebChatAPIContext.js | 13 + .../src/hooks/middleware/UserlandBoundary.js | 31 + .../src/hooks/middleware/applyMiddleware.js | 63 + .../src/hooks/middleware/concatMiddleware.js | 19 + .../middleware/createActivityRenderer.js | 6 + .../createActivityStatusRenderer.js | 6 + .../middleware/createAttachmentRenderer.js | 12 + .../hooks/middleware/createAvatarRenderer.js | 6 + .../createDefaultGroupActivitiesMiddleware.js | 55 + .../middleware/createErrorBoundaryRenderer.js | 12 + .../hooks/middleware/createToastRenderer.js | 12 + .../createTypingIndicatorRenderer.js | 8 + .../src/hooks/useActiveTyping.js | 2 +- .../src/hooks/useActivities.js | 2 +- .../src/hooks/useAvatarForBot.js | 0 .../src/hooks/useAvatarForUser.js | 0 .../src/hooks/useByteFormatter.js | 0 .../src/hooks/useConnectivityStatus.js | 2 +- .../src/hooks/useCreateActivityRenderer.js | 0 .../hooks/useCreateActivityStatusRenderer.js | 4 +- .../src/hooks/useCreateAttachmentRenderer.js | 7 + .../src/hooks/useCreateAvatarRenderer.js | 4 +- .../src/hooks/useDateFormatter.js | 0 .../src/hooks/useDebouncedNotifications.js | 2 +- .../hooks/useDebouncedNotifications.spec.js | 0 .../src/hooks/useDictateAbortable.js | 0 packages/api/src/hooks/useDictateInterims.js | 6 + .../src/hooks/useDictateState.js | 2 +- .../src/hooks/useDirection.js | 2 +- packages/api/src/hooks/useDisabled.js | 5 + .../api/src/hooks/useDismissNotification.js | 5 + .../api/src/hooks/useEmitTypingIndicator.js | 5 + packages/api/src/hooks/useFocus.js | 5 + .../src/hooks/useFocusSendBox.js | 0 .../src/hooks/useGetSendTimeoutForActivity.js | 0 packages/api/src/hooks/useGrammars.js | 5 + packages/api/src/hooks/useGroupActivities.js | 5 + .../src/hooks/useGroupTimestamp.js | 0 .../src/hooks/useLanguage.js | 4 +- .../src/hooks/useLastTypingAt.js | 2 +- .../src/hooks/useLocalize.js | 2 +- .../src/hooks/useLocalizeDate.js | 2 +- .../src/hooks/useLocalizer.js | 4 +- .../src/hooks/useMarkActivityAsSpoken.js | 0 .../src/hooks/useNotifications.js | 2 +- .../api/src/hooks/usePerformCardAction.js | 5 + packages/api/src/hooks/usePostActivity.js | 5 + .../src/hooks/useReferenceGrammarID.js | 2 +- .../src/hooks/useRelativeTimeFormatter.js | 0 .../src/hooks/useRenderActivity.js | 0 .../src/hooks/useRenderActivityStatus.js | 4 +- packages/api/src/hooks/useRenderAttachment.js | 21 + .../src/hooks/useRenderAvatar.js | 0 .../src/hooks/useRenderMarkdownAsHTML.js | 4 +- packages/api/src/hooks/useRenderToast.js | 5 + .../api/src/hooks/useRenderTypingIndicator.js | 5 + packages/api/src/hooks/useSendBoxValue.js | 6 + packages/api/src/hooks/useSendEvent.js | 5 + .../src/hooks/useSendFiles.js | 6 +- packages/api/src/hooks/useSendMessage.js | 5 + packages/api/src/hooks/useSendMessageBack.js | 5 + packages/api/src/hooks/useSendPostBack.js | 5 + .../src/hooks/useSendTimeoutForActivity.js | 0 .../src/hooks/useSendTypingIndicator.js | 2 +- packages/api/src/hooks/useSetNotification.js | 5 + .../hooks/useShouldSpeakIncomingActivity.js | 6 +- packages/api/src/hooks/useStartDictate.js | 5 + packages/api/src/hooks/useStopDictate.js | 5 + packages/api/src/hooks/useStyleOptions.js | 5 + .../src/hooks/useSubmitSendBox.js | 4 +- .../src/hooks/useSuggestedActions.js | 6 +- .../src/hooks/useTimeoutForSend.js | 0 packages/api/src/hooks/useTrackDimension.js | 7 + .../src/hooks/useTrackEvent.js | 11 +- .../src/hooks/useTrackException.js | 6 +- .../src/hooks/useTrackTiming.js | 8 +- packages/api/src/hooks/useUserID.js | 5 + packages/api/src/hooks/useUsername.js | 5 + .../src/hooks/useVoiceSelector.js | 4 +- .../api/src/hooks/useWebSpeechPonyfill.js | 5 + .../src/hooks/utils}/ErrorBoundary.js | 19 +- packages/api/src/hooks/utils/singleToArray.js | 3 + packages/api/src/index.ts | 4 + .../src/localization}/Localize.js | 2 +- .../src/localization}/ar-EG.json | 0 .../src/localization}/ar-JO.json | 0 .../src/localization}/ar-SA.json | 0 .../src/localization}/bg-BG.json | 0 .../src/localization}/ca-ES.json | 0 .../src/localization}/cs-CZ.json | 0 .../src/localization}/da-DK.json | 0 .../src/localization}/de-DE.json | 0 .../src/localization}/el-GR.json | 0 .../src/localization}/en-US.json | 0 .../src/localization}/es-ES.json | 0 .../src/localization}/et-EE.json | 0 .../src/localization}/eu-ES.json | 0 .../src/localization}/fi-FI.json | 0 .../src/localization}/fr-FR.json | 0 .../localization}/getAllLocalizedStrings.js | 0 .../getAllLocalizedStrings.spec.js | 0 .../src/localization}/getLocaleString.js | 2 +- .../src/localization}/getRTLList.js | 0 .../src/localization}/gl-ES.json | 0 .../src/localization}/he-IL.json | 0 .../src/localization}/hi-IN.json | 0 .../src/localization}/hr-HR.json | 0 .../src/localization}/hu-HU.json | 0 .../src/localization}/id-ID.json | 0 .../src/localization}/it-IT.json | 0 .../src/localization}/ja-JP.json | 0 .../src/localization}/kk-KZ.json | 0 .../src/localization}/ko-KR.json | 0 .../src/localization}/lt-LT.json | 0 .../src/localization}/lv-LV.json | 0 .../localization}/mergeLocalizedStrings.js | 0 .../src/localization}/ms-MY.json | 0 .../src/localization}/nb-NO.json | 0 .../src/localization}/nl-NL.json | 0 .../src/localization}/overrides.json | 0 .../src/localization}/pl-PL.json | 0 .../src/localization}/pt-BR.json | 0 .../src/localization}/pt-PT.json | 0 .../src/localization}/ro-RO.json | 0 .../src/localization}/ru-RU.json | 0 .../src/localization}/sk-SK.json | 0 .../src/localization}/sl-SI.json | 0 .../src/localization}/sl-SL.json | 0 .../src/localization}/sr-Cyrl-CS.json | 0 .../src/localization}/sr-Cyrl.json | 0 .../src/localization}/sr-Latn-CS.json | 0 .../src/localization}/sr-Latn.json | 0 .../src/localization}/sv-SE.json | 0 .../src/localization}/th-TH.json | 0 .../src/localization}/tr-TR.json | 0 .../src/localization}/uk-UA.json | 0 .../src/localization}/vi-VN.json | 0 .../src/localization}/yue.json | 0 .../src/localization}/zh-CN.json | 0 .../src/localization}/zh-HK.json | 0 .../src/localization}/zh-TW.json | 0 packages/api/src/patchStyleOptions.js | 194 + packages/api/src/tsconfig.json | 13 + .../src/utils}/blobToArrayBuffer.js | 0 .../src/utils}/createCustomEvent.js | 0 .../src/utils}/downscaleImageToDataURL.js | 0 .../downscaleImageToDataURLUsingBrowser.js | 0 .../downscaleImageToDataURLUsingWorker.js | 0 ...wnscaleImageToDataURLUsingWorker.worker.js | 0 .../src/Utils => api/src/utils}/findMin.js | 0 .../Utils => api/src/utils}/findMin.spec.js | 0 .../src/Utils => api/src/utils}/isObject.js | 0 packages/api/src/utils/mapMap.js | 7 + packages/api/src/utils/mapMap.spec.js | 9 + .../src/utils}/normalizeLanguage.js | 0 .../src/utils}/normalizeLanguage.spec.js | 0 .../src/utils}/observableToPromise.js | 0 packages/api/src/utils/randomId.js | 7 + packages/bundle/package.json | 2 +- packages/bundle/src/FullComposer.js | 3 +- packages/component/package.json | 16 +- packages/component/src/Activity/Bubble.js | 5 +- .../src/Activity/CarouselFilmStrip.js | 8 +- .../component/src/Activity/CarouselLayout.js | 5 +- .../src/Activity/ScrollToEndButton.js | 7 +- packages/component/src/Activity/Speak.js | 6 +- .../component/src/Activity/StackedLayout.js | 10 +- .../component/src/Assets/TypingAnimation.js | 6 +- .../component/src/Attachment/FileContent.js | 6 +- .../component/src/Attachment/ImageContent.js | 4 +- .../component/src/Attachment/TextContent.js | 4 +- .../src/Attachment/VideoAttachment.js | 2 +- packages/component/src/Avatar/ImageAvatar.js | 5 +- .../component/src/Avatar/InitialsAvatar.js | 5 +- .../component/src/BasicConnectivityStatus.js | 4 +- packages/component/src/BasicSendBox.js | 8 +- packages/component/src/BasicToast.js | 5 +- packages/component/src/BasicToaster.js | 6 +- packages/component/src/BasicTranscript.js | 32 +- .../component/src/BasicTypingIndicator.js | 5 +- packages/component/src/BasicWebChat.js | 11 +- packages/component/src/Composer.js | 726 +- .../Assets/ErrorNotificationIcon.js | 3 +- .../Assets/SpinnerAnimation.js | 4 +- .../Assets/WarningNotificationIcon.js | 3 +- .../src/ConnectivityStatus/Connected.js | 4 +- .../src/ConnectivityStatus/Connecting.js | 12 +- .../src/ConnectivityStatus/FailedToConnect.js | 5 +- .../src/ConnectivityStatus/JavaScriptError.js | 5 +- packages/component/src/ErrorBox.js | 23 +- .../Activity/createCoreMiddleware.js | 90 +- .../Middleware/ActivityStatus/AbsoluteTime.js | 4 +- .../Middleware/ActivityStatus/RelativeTime.js | 8 +- .../SendStatus/SendFailedRetry.js | 4 +- .../ActivityStatus/SendStatus/SendStatus.js | 6 +- .../Middleware/ActivityStatus/Timestamp.js | 4 +- .../ActivityStatus/createCoreMiddleware.js | 3 +- .../createTimestampMiddleware.js | 2 + .../Attachment/createCoreMiddleware.js | 71 +- .../TypingIndicator/createCoreMiddleware.js | 5 +- .../src/Middleware/createActivityRenderer.js | 4 +- .../createActivityStatusRenderer.js | 2 +- .../component/src/ScreenReaderActivity.js | 7 +- .../component/src/SendBox/Assets/SendIcon.js | 4 +- .../src/SendBox/DictationInterims.js | 9 +- .../component/src/SendBox/MicrophoneButton.js | 24 +- packages/component/src/SendBox/SendButton.js | 8 +- .../component/src/SendBox/SuggestedAction.js | 11 +- .../component/src/SendBox/SuggestedActions.js | 6 +- packages/component/src/SendBox/TextBox.js | 22 +- .../component/src/SendBox/UploadButton.js | 10 +- .../component/src/Toast/NotificationIcon.js | 4 +- .../component/src/Utils/InlineMarkdown.js | 6 +- packages/component/src/Utils/singleToArray.js | 3 + .../Utils/upgradeLegacyRendererMiddleware.js | 20 + packages/component/src/connectToWebChat.js | 9 +- .../src/hooks/internal/WebChatUIContext.js | 5 + .../src/hooks/internal/useDirFromProps.js | 5 - .../hooks/internal/useDisableOnBlurEffect.js | 34 - .../hooks/internal/useLocalizeAccessKey.js | 4 +- .../hooks/internal/useLocalizedGlobalize.js | 5 - .../src/hooks/internal/useLocalizedStrings.js | 7 - .../src/hooks/internal/useMarkActivity.js | 5 - .../src/hooks/internal/useSendBoxFocusRef.js | 5 - .../src/hooks/internal/useSetDictateState.js | 5 - .../internal/useSettableDictateAbortable.js | 7 - .../hooks/internal/useStyleToEmotionObject.js | 1 + .../hooks/internal/useTranscriptFocusRef.js | 5 - .../src/hooks/internal/useWebChatUIContext.js | 2 +- .../component/src/hooks/useDictateInterims.js | 6 - packages/component/src/hooks/useDisabled.js | 5 - .../src/hooks/useDismissNotification.js | 5 - .../src/hooks/useEmitTypingIndicator.js | 5 - packages/component/src/hooks/useFocus.js | 5 - packages/component/src/hooks/useGrammars.js | 5 - .../component/src/hooks/useGroupActivities.js | 5 - .../src/hooks/usePerformCardAction.js | 5 - .../component/src/hooks/usePostActivity.js | 5 - .../src/hooks/useRenderAttachment.js | 5 - .../component/src/hooks/useRenderToast.js | 5 - .../src/hooks/useRenderTypingIndicator.js | 5 - .../component/src/hooks/useSendBoxValue.js | 6 - packages/component/src/hooks/useSendEvent.js | 5 - .../component/src/hooks/useSendMessage.js | 5 - .../component/src/hooks/useSendMessageBack.js | 5 - .../component/src/hooks/useSendPostBack.js | 5 - .../component/src/hooks/useSetNotification.js | 5 - .../component/src/hooks/useStartDictate.js | 5 - .../component/src/hooks/useStopDictate.js | 5 - .../component/src/hooks/useStyleOptions.js | 8 - .../component/src/hooks/useTrackDimension.js | 7 - packages/component/src/hooks/useUserID.js | 5 - packages/component/src/hooks/useUsername.js | 5 - .../src/hooks/useWebSpeechPonyfill.js | 5 - packages/component/src/index.tsx | 11 +- 296 files changed, 10105 insertions(+), 1225 deletions(-) create mode 100644 packages/api/.eslintignore create mode 100644 packages/api/.eslintrc.yml create mode 100644 packages/api/.gitignore create mode 100644 packages/api/.prettierrc.yml create mode 100644 packages/api/babel.config.json create mode 100644 packages/api/package-lock.json create mode 100644 packages/api/package.json rename packages/{component => api}/scripts/createPrecompiledGlobalize.js (81%) create mode 100644 packages/api/src/defaultStyleOptions.js create mode 100644 packages/api/src/hooks/Composer.js create mode 100644 packages/api/src/hooks/Composer.oldjs rename packages/{component => api}/src/hooks/index.js (83%) rename packages/{component/src/Speech => api/src/hooks/internal}/BypassSpeechSynthesisPonyfill.js (100%) rename packages/{component/src => api/src/hooks/internal}/Dictation.js (78%) create mode 100644 packages/api/src/hooks/internal/ErrorBox.js rename packages/{component/src => api/src/hooks/internal}/Tracker.js (61%) rename packages/{component/src/WebChatUIContext.js => api/src/hooks/internal/WebChatAPIContext.js} (73%) rename packages/{component/src => api/src/hooks/internal}/WebChatReduxContext.js (100%) rename packages/{component/src => api/src/hooks/internal}/defaultSelectVoice.js (100%) rename packages/{component/src => api/src/hooks/internal}/defaultSelectVoice.test.js (100%) rename packages/{component => api}/src/hooks/internal/useCreateActivityRendererInternal.js (55%) rename packages/{component => api}/src/hooks/internal/useDebugDeps.js (100%) create mode 100644 packages/api/src/hooks/internal/useDirFromProps.js create mode 100644 packages/api/src/hooks/internal/useErrorBoxClass.js rename packages/{component => api}/src/hooks/internal/useForceRender.js (100%) rename packages/{component => api}/src/hooks/internal/useForceRenderAtInterval.js (100%) rename packages/{component => api}/src/hooks/internal/useGetTranscriptActivityElementByID.js (100%) create mode 100644 packages/api/src/hooks/internal/useLocalizedGlobalize.js create mode 100644 packages/api/src/hooks/internal/useLocalizedStrings.js create mode 100644 packages/api/src/hooks/internal/useMarkActivity.js rename packages/{component => api}/src/hooks/internal/useReadTelemetryDimensions.js (61%) rename packages/{component => api}/src/hooks/internal/useReplaceEmoticon.js (100%) create mode 100644 packages/api/src/hooks/internal/useSendBoxFocusRef.js create mode 100644 packages/api/src/hooks/internal/useSetDictateState.js create mode 100644 packages/api/src/hooks/internal/useSettableDictateAbortable.js rename packages/{component => api}/src/hooks/internal/useTimePassed.js (100%) rename packages/{component => api}/src/hooks/internal/useTimer.js (100%) rename packages/{component => api}/src/hooks/internal/useTracker.js (92%) create mode 100644 packages/api/src/hooks/internal/useTranscriptFocusRef.js create mode 100644 packages/api/src/hooks/internal/useWebChatAPIContext.js create mode 100644 packages/api/src/hooks/middleware/UserlandBoundary.js create mode 100644 packages/api/src/hooks/middleware/applyMiddleware.js create mode 100644 packages/api/src/hooks/middleware/concatMiddleware.js create mode 100644 packages/api/src/hooks/middleware/createActivityRenderer.js create mode 100644 packages/api/src/hooks/middleware/createActivityStatusRenderer.js create mode 100644 packages/api/src/hooks/middleware/createAttachmentRenderer.js create mode 100644 packages/api/src/hooks/middleware/createAvatarRenderer.js create mode 100644 packages/api/src/hooks/middleware/createDefaultGroupActivitiesMiddleware.js create mode 100644 packages/api/src/hooks/middleware/createErrorBoundaryRenderer.js create mode 100644 packages/api/src/hooks/middleware/createToastRenderer.js create mode 100644 packages/api/src/hooks/middleware/createTypingIndicatorRenderer.js rename packages/{component => api}/src/hooks/useActiveTyping.js (95%) rename packages/{component => api}/src/hooks/useActivities.js (61%) rename packages/{component => api}/src/hooks/useAvatarForBot.js (100%) rename packages/{component => api}/src/hooks/useAvatarForUser.js (100%) rename packages/{component => api}/src/hooks/useByteFormatter.js (100%) rename packages/{component => api}/src/hooks/useConnectivityStatus.js (66%) rename packages/{component => api}/src/hooks/useCreateActivityRenderer.js (100%) rename packages/{component => api}/src/hooks/useCreateActivityStatusRenderer.js (95%) create mode 100644 packages/api/src/hooks/useCreateAttachmentRenderer.js rename packages/{component => api}/src/hooks/useCreateAvatarRenderer.js (86%) rename packages/{component => api}/src/hooks/useDateFormatter.js (100%) rename packages/{component => api}/src/hooks/useDebouncedNotifications.js (98%) rename packages/{component => api}/src/hooks/useDebouncedNotifications.spec.js (100%) rename packages/{component => api}/src/hooks/useDictateAbortable.js (100%) create mode 100644 packages/api/src/hooks/useDictateInterims.js rename packages/{component => api}/src/hooks/useDictateState.js (75%) rename packages/{component => api}/src/hooks/useDirection.js (91%) create mode 100644 packages/api/src/hooks/useDisabled.js create mode 100644 packages/api/src/hooks/useDismissNotification.js create mode 100644 packages/api/src/hooks/useEmitTypingIndicator.js create mode 100644 packages/api/src/hooks/useFocus.js rename packages/{component => api}/src/hooks/useFocusSendBox.js (100%) rename packages/{component => api}/src/hooks/useGetSendTimeoutForActivity.js (100%) create mode 100644 packages/api/src/hooks/useGrammars.js create mode 100644 packages/api/src/hooks/useGroupActivities.js rename packages/{component => api}/src/hooks/useGroupTimestamp.js (100%) rename packages/{component => api}/src/hooks/useLanguage.js (71%) rename packages/{component => api}/src/hooks/useLastTypingAt.js (86%) rename packages/{component => api}/src/hooks/useLocalize.js (81%) rename packages/{component => api}/src/hooks/useLocalizeDate.js (88%) rename packages/{component => api}/src/hooks/useLocalizer.js (95%) rename packages/{component => api}/src/hooks/useMarkActivityAsSpoken.js (100%) rename packages/{component => api}/src/hooks/useNotifications.js (63%) create mode 100644 packages/api/src/hooks/usePerformCardAction.js create mode 100644 packages/api/src/hooks/usePostActivity.js rename packages/{component => api}/src/hooks/useReferenceGrammarID.js (66%) rename packages/{component => api}/src/hooks/useRelativeTimeFormatter.js (100%) rename packages/{component => api}/src/hooks/useRenderActivity.js (100%) rename packages/{component => api}/src/hooks/useRenderActivityStatus.js (91%) create mode 100644 packages/api/src/hooks/useRenderAttachment.js rename packages/{component => api}/src/hooks/useRenderAvatar.js (100%) rename packages/{component => api}/src/hooks/useRenderMarkdownAsHTML.js (73%) create mode 100644 packages/api/src/hooks/useRenderToast.js create mode 100644 packages/api/src/hooks/useRenderTypingIndicator.js create mode 100644 packages/api/src/hooks/useSendBoxValue.js create mode 100644 packages/api/src/hooks/useSendEvent.js rename packages/{component => api}/src/hooks/useSendFiles.js (93%) create mode 100644 packages/api/src/hooks/useSendMessage.js create mode 100644 packages/api/src/hooks/useSendMessageBack.js create mode 100644 packages/api/src/hooks/useSendPostBack.js rename packages/{component => api}/src/hooks/useSendTimeoutForActivity.js (100%) rename packages/{component => api}/src/hooks/useSendTypingIndicator.js (67%) create mode 100644 packages/api/src/hooks/useSetNotification.js rename packages/{component => api}/src/hooks/useShouldSpeakIncomingActivity.js (74%) create mode 100644 packages/api/src/hooks/useStartDictate.js create mode 100644 packages/api/src/hooks/useStopDictate.js create mode 100644 packages/api/src/hooks/useStyleOptions.js rename packages/{component => api}/src/hooks/useSubmitSendBox.js (78%) rename packages/{component => api}/src/hooks/useSuggestedActions.js (69%) rename packages/{component => api}/src/hooks/useTimeoutForSend.js (100%) create mode 100644 packages/api/src/hooks/useTrackDimension.js rename packages/{component => api}/src/hooks/useTrackEvent.js (86%) rename packages/{component => api}/src/hooks/useTrackException.js (80%) rename packages/{component => api}/src/hooks/useTrackTiming.js (88%) create mode 100644 packages/api/src/hooks/useUserID.js create mode 100644 packages/api/src/hooks/useUsername.js rename packages/{component => api}/src/hooks/useVoiceSelector.js (62%) create mode 100644 packages/api/src/hooks/useWebSpeechPonyfill.js rename packages/{component/src => api/src/hooks/utils}/ErrorBoundary.js (51%) create mode 100644 packages/api/src/hooks/utils/singleToArray.js create mode 100644 packages/api/src/index.ts rename packages/{component/src/Localization => api/src/localization}/Localize.js (96%) rename packages/{component/src/Localization => api/src/localization}/ar-EG.json (100%) rename packages/{component/src/Localization => api/src/localization}/ar-JO.json (100%) rename packages/{component/src/Localization => api/src/localization}/ar-SA.json (100%) rename packages/{component/src/Localization => api/src/localization}/bg-BG.json (100%) rename packages/{component/src/Localization => api/src/localization}/ca-ES.json (100%) rename packages/{component/src/Localization => api/src/localization}/cs-CZ.json (100%) rename packages/{component/src/Localization => api/src/localization}/da-DK.json (100%) rename packages/{component/src/Localization => api/src/localization}/de-DE.json (100%) rename packages/{component/src/Localization => api/src/localization}/el-GR.json (100%) rename packages/{component/src/Localization => api/src/localization}/en-US.json (100%) rename packages/{component/src/Localization => api/src/localization}/es-ES.json (100%) rename packages/{component/src/Localization => api/src/localization}/et-EE.json (100%) rename packages/{component/src/Localization => api/src/localization}/eu-ES.json (100%) rename packages/{component/src/Localization => api/src/localization}/fi-FI.json (100%) rename packages/{component/src/Localization => api/src/localization}/fr-FR.json (100%) rename packages/{component/src/Localization => api/src/localization}/getAllLocalizedStrings.js (100%) rename packages/{component/src/Localization => api/src/localization}/getAllLocalizedStrings.spec.js (100%) rename packages/{component/src/Localization => api/src/localization}/getLocaleString.js (73%) rename packages/{component/src/Localization => api/src/localization}/getRTLList.js (100%) rename packages/{component/src/Localization => api/src/localization}/gl-ES.json (100%) rename packages/{component/src/Localization => api/src/localization}/he-IL.json (100%) rename packages/{component/src/Localization => api/src/localization}/hi-IN.json (100%) rename packages/{component/src/Localization => api/src/localization}/hr-HR.json (100%) rename packages/{component/src/Localization => api/src/localization}/hu-HU.json (100%) rename packages/{component/src/Localization => api/src/localization}/id-ID.json (100%) rename packages/{component/src/Localization => api/src/localization}/it-IT.json (100%) rename packages/{component/src/Localization => api/src/localization}/ja-JP.json (100%) rename packages/{component/src/Localization => api/src/localization}/kk-KZ.json (100%) rename packages/{component/src/Localization => api/src/localization}/ko-KR.json (100%) rename packages/{component/src/Localization => api/src/localization}/lt-LT.json (100%) rename packages/{component/src/Localization => api/src/localization}/lv-LV.json (100%) rename packages/{component/src/Localization => api/src/localization}/mergeLocalizedStrings.js (100%) rename packages/{component/src/Localization => api/src/localization}/ms-MY.json (100%) rename packages/{component/src/Localization => api/src/localization}/nb-NO.json (100%) rename packages/{component/src/Localization => api/src/localization}/nl-NL.json (100%) rename packages/{component/src/Localization => api/src/localization}/overrides.json (100%) rename packages/{component/src/Localization => api/src/localization}/pl-PL.json (100%) rename packages/{component/src/Localization => api/src/localization}/pt-BR.json (100%) rename packages/{component/src/Localization => api/src/localization}/pt-PT.json (100%) rename packages/{component/src/Localization => api/src/localization}/ro-RO.json (100%) rename packages/{component/src/Localization => api/src/localization}/ru-RU.json (100%) rename packages/{component/src/Localization => api/src/localization}/sk-SK.json (100%) rename packages/{component/src/Localization => api/src/localization}/sl-SI.json (100%) rename packages/{component/src/Localization => api/src/localization}/sl-SL.json (100%) rename packages/{component/src/Localization => api/src/localization}/sr-Cyrl-CS.json (100%) rename packages/{component/src/Localization => api/src/localization}/sr-Cyrl.json (100%) rename packages/{component/src/Localization => api/src/localization}/sr-Latn-CS.json (100%) rename packages/{component/src/Localization => api/src/localization}/sr-Latn.json (100%) rename packages/{component/src/Localization => api/src/localization}/sv-SE.json (100%) rename packages/{component/src/Localization => api/src/localization}/th-TH.json (100%) rename packages/{component/src/Localization => api/src/localization}/tr-TR.json (100%) rename packages/{component/src/Localization => api/src/localization}/uk-UA.json (100%) rename packages/{component/src/Localization => api/src/localization}/vi-VN.json (100%) rename packages/{component/src/Localization => api/src/localization}/yue.json (100%) rename packages/{component/src/Localization => api/src/localization}/zh-CN.json (100%) rename packages/{component/src/Localization => api/src/localization}/zh-HK.json (100%) rename packages/{component/src/Localization => api/src/localization}/zh-TW.json (100%) create mode 100644 packages/api/src/patchStyleOptions.js create mode 100644 packages/api/src/tsconfig.json rename packages/{component/src/Utils => api/src/utils}/blobToArrayBuffer.js (100%) rename packages/{component/src/Utils => api/src/utils}/createCustomEvent.js (100%) rename packages/{component/src/Utils => api/src/utils}/downscaleImageToDataURL.js (100%) rename packages/{component/src/Utils => api/src/utils}/downscaleImageToDataURLUsingBrowser.js (100%) rename packages/{component/src/Utils => api/src/utils}/downscaleImageToDataURLUsingWorker.js (100%) rename packages/{component/src/Utils => api/src/utils}/downscaleImageToDataURLUsingWorker.worker.js (100%) rename packages/{component/src/Utils => api/src/utils}/findMin.js (100%) rename packages/{component/src/Utils => api/src/utils}/findMin.spec.js (100%) rename packages/{component/src/Utils => api/src/utils}/isObject.js (100%) create mode 100644 packages/api/src/utils/mapMap.js create mode 100644 packages/api/src/utils/mapMap.spec.js rename packages/{component/src/Utils => api/src/utils}/normalizeLanguage.js (100%) rename packages/{component/src/Utils => api/src/utils}/normalizeLanguage.spec.js (100%) rename packages/{component/src/Utils => api/src/utils}/observableToPromise.js (100%) create mode 100644 packages/api/src/utils/randomId.js create mode 100644 packages/component/src/Utils/singleToArray.js create mode 100644 packages/component/src/Utils/upgradeLegacyRendererMiddleware.js create mode 100644 packages/component/src/hooks/internal/WebChatUIContext.js delete mode 100644 packages/component/src/hooks/internal/useDirFromProps.js delete mode 100644 packages/component/src/hooks/internal/useDisableOnBlurEffect.js delete mode 100644 packages/component/src/hooks/internal/useLocalizedGlobalize.js delete mode 100644 packages/component/src/hooks/internal/useLocalizedStrings.js delete mode 100644 packages/component/src/hooks/internal/useMarkActivity.js delete mode 100644 packages/component/src/hooks/internal/useSendBoxFocusRef.js delete mode 100644 packages/component/src/hooks/internal/useSetDictateState.js delete mode 100644 packages/component/src/hooks/internal/useSettableDictateAbortable.js delete mode 100644 packages/component/src/hooks/internal/useTranscriptFocusRef.js delete mode 100644 packages/component/src/hooks/useDictateInterims.js delete mode 100644 packages/component/src/hooks/useDisabled.js delete mode 100644 packages/component/src/hooks/useDismissNotification.js delete mode 100644 packages/component/src/hooks/useEmitTypingIndicator.js delete mode 100644 packages/component/src/hooks/useFocus.js delete mode 100644 packages/component/src/hooks/useGrammars.js delete mode 100644 packages/component/src/hooks/useGroupActivities.js delete mode 100644 packages/component/src/hooks/usePerformCardAction.js delete mode 100644 packages/component/src/hooks/usePostActivity.js delete mode 100644 packages/component/src/hooks/useRenderAttachment.js delete mode 100644 packages/component/src/hooks/useRenderToast.js delete mode 100644 packages/component/src/hooks/useRenderTypingIndicator.js delete mode 100644 packages/component/src/hooks/useSendBoxValue.js delete mode 100644 packages/component/src/hooks/useSendEvent.js delete mode 100644 packages/component/src/hooks/useSendMessage.js delete mode 100644 packages/component/src/hooks/useSendMessageBack.js delete mode 100644 packages/component/src/hooks/useSendPostBack.js delete mode 100644 packages/component/src/hooks/useSetNotification.js delete mode 100644 packages/component/src/hooks/useStartDictate.js delete mode 100644 packages/component/src/hooks/useStopDictate.js delete mode 100644 packages/component/src/hooks/useStyleOptions.js delete mode 100644 packages/component/src/hooks/useTrackDimension.js delete mode 100644 packages/component/src/hooks/useUserID.js delete mode 100644 packages/component/src/hooks/useUsername.js delete mode 100644 packages/component/src/hooks/useWebSpeechPonyfill.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 1684c15883..79e475d13c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Breaking changes + +- Specific hooks are only available when using HTML version of Web Chat +- `activityMiddleware`, `attachmentMiddleware`, etc, now support passing in an array for multiple middleware + ### Fixed - Fixes [#3489](https://github.com/microsoft/BotFramework-WebChat/issues/3489). [Accessibility]: Fix AT saying 'Bot undefined said', by [@corinagum](https://github.com/corinagum) in PR [#3524](https://github.com/microsoft/BotFramework-WebChat/pull/3524) diff --git a/docs/HOOKS.md b/docs/HOOKS.md index f5eef5f747..69d2ceaa25 100644 --- a/docs/HOOKS.md +++ b/docs/HOOKS.md @@ -65,6 +65,7 @@ Following is the list of hooks supported by Web Chat API. - [`useCreateAvatarRenderer`](#usecreateavatarrenderer) - [`useDateFormatter`](#useDateFormatter) - [`useDebouncedNotification`](#usedebouncednotification) +- [`useDictateAbortable`](#usedictateabortable) - [`useDictateInterims`](#usedictateinterims) - [`useDictateState`](#usedictatestate) - [`useDirection`](#useDirection) @@ -362,6 +363,10 @@ Due to debouncing, notifications retrieved using this hook may not be current. A For the debounce behavior, please read our [article regarding notification system](https://github.com/microsoft/BotFramework-WebChat/tree/master/docs/NOTIFICATION.md). +## `useDictateAbortable` + +(TODO: TBD) + ## `useDictateInterims` diff --git a/packages/api/.eslintignore b/packages/api/.eslintignore new file mode 100644 index 0000000000..8e2a691bcd --- /dev/null +++ b/packages/api/.eslintignore @@ -0,0 +1,9 @@ +/src/__tests__/**/* +/src/**/*.spec.js +/src/**/*.spec.jsx +/src/**/*.spec.ts +/src/**/*.spec.tsx +/src/**/*.test.js +/src/**/*.test.jsx +/src/**/*.test.ts +/src/**/*.test.tsx diff --git a/packages/api/.eslintrc.yml b/packages/api/.eslintrc.yml new file mode 100644 index 0000000000..3d1c9cc36d --- /dev/null +++ b/packages/api/.eslintrc.yml @@ -0,0 +1,91 @@ +extends: +- plugin:react/recommended +plugins: +- prettier +- react-hooks +rules: +# plugins + prettier/prettier: error + + react/button-has-type: error + react/default-props-match-prop-types: error + react/destructuring-assignment: error + react/display-name: off + react/forbid-component-props: + - error + - forbid: + - style + react/forbid-dom-props: + - error + - forbid: + - id + # react/forbid-prop-types: error // How to deal with Adaptive Card schema? + react/no-access-state-in-setstate: error + react/no-array-index-key: error + react/no-danger: error + react/no-did-mount-set-state: error + react/no-did-update-set-state: error + react/no-redundant-should-component-update: error + react/no-typos: error + react/no-this-in-sfc: error + react/no-unescaped-entities: error + react/no-unsafe: error + react/no-unused-prop-types: error + react/no-unused-state: error + react/no-will-update-set-state: error + react/prefer-es6-class: error + react/prefer-read-only-props: error + react/require-default-props: error + react/self-closing-comp: error + react/sort-prop-types: error + react/state-in-constructor: error + react/static-property-placement: + - error + - property assignment + react/style-prop-object: error + react/void-dom-elements-no-children: error + react/jsx-boolean-value: + - error + - always + react/jsx-closing-bracket-location: + - error + - tag-aligned + react/jsx-closing-tag-location: error + react/jsx-equals-spacing: + - error + - never + react/jsx-first-prop-new-line: + - error + - multiline-multiprop + react/jsx-handler-names: error + react/jsx-indent: + - error + - 2 + react/jsx-indent-props: + - error + - 2 + react/jsx-max-props-per-line: + - error + - maximum: 1 + when: multiline + react/jsx-no-bind: error + react/jsx-no-literals: error + # react/jsx-one-expression-per-line: #conflicts with prettier + # - error + # - allow: literal + react/jsx-fragments: + - error + - element + react/jsx-pascal-case: error + react/jsx-props-no-multi-spaces: error + react/jsx-sort-default-props: error + react/jsx-sort-props: error + react/jsx-tag-spacing: + - error + - afterOpening: never + beforeClosing: never + beforeSelfClosing: always + closingSlash: never + react/jsx-wrap-multilines: error # Conflict with no-extra-parens + react-hooks/rules-of-hooks: error + react-hooks/exhaustive-deps: warn diff --git a/packages/api/.gitignore b/packages/api/.gitignore new file mode 100644 index 0000000000..626c4f31ee --- /dev/null +++ b/packages/api/.gitignore @@ -0,0 +1,2 @@ +/lib +/node_modules diff --git a/packages/api/.prettierrc.yml b/packages/api/.prettierrc.yml new file mode 100644 index 0000000000..97987e7a58 --- /dev/null +++ b/packages/api/.prettierrc.yml @@ -0,0 +1,11 @@ +arrowParens: avoid +bracketSpacing: true +endOfLine: auto +jsxBracketSameLine: false +printWidth: 120 +proseWrap: preserve +quoteProps: as-needed +semi: true +singleQuote: true +tabWidth: 2 +trailingComma: none diff --git a/packages/api/babel.config.json b/packages/api/babel.config.json new file mode 100644 index 0000000000..e43758f909 --- /dev/null +++ b/packages/api/babel.config.json @@ -0,0 +1,48 @@ +{ + "env": { + "test": { + "exclude": ["src/**/*.worker.js"], + "plugins": ["babel-plugin-istanbul"] + } + }, + "overrides": [ + { + "plugins": [], + "presets": [ + [ + "@babel/preset-env", + { + "targets": { + "chrome": "69" + } + } + ] + ], + "test": "src/**/*.worker.js" + } + ], + "plugins": [ + "@babel/proposal-object-rest-spread", + [ + "transform-inline-environment-variables", + { + "include": ["npm_package_version"] + } + ] + ], + "presets": [ + "@babel/preset-typescript", + [ + "@babel/preset-env", + { + "modules": "commonjs", + "targets": { + "browsers": ["last 2 versions"] + } + } + ], + "@babel/react" + ], + "sourceMaps": "inline", + "sourceRoot": "component:///" +} diff --git a/packages/api/package-lock.json b/packages/api/package-lock.json new file mode 100644 index 0000000000..77dca1e680 --- /dev/null +++ b/packages/api/package-lock.json @@ -0,0 +1,7667 @@ +{ + "name": "botframework-webchat-api", + "version": "0.0.0-0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/cli": { + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.11.6.tgz", + "integrity": "sha512-+w7BZCvkewSmaRM6H4L2QM3RL90teqEIHDIFXAmrW33+0jhlymnDAEdqVeCZATvxhQuio1ifoGVlJJbIiH9Ffg==", + "dev": true, + "requires": { + "chokidar": "^2.1.8", + "commander": "^4.0.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "lodash": "^4.17.19", + "make-dir": "^2.1.0", + "slash": "^2.0.0", + "source-map": "^0.5.0" + } + }, + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/compat-data": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz", + "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==", + "requires": { + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "semver": "^5.5.0" + } + }, + "@babel/core": { + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz", + "integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.6", + "@babel/helper-module-transforms": "^7.11.0", + "@babel/helpers": "^7.10.4", + "@babel/parser": "^7.11.5", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.11.5", + "@babel/types": "^7.11.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", + "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", + "requires": { + "@babel/types": "^7.11.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", + "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", + "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", + "requires": { + "@babel/helper-explode-assignable-expression": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-builder-react-jsx": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.4.tgz", + "integrity": "sha512-5nPcIZ7+KKDxT1427oBivl9V9YTal7qk0diccnh7RrcgrT/pGFOjgGw1dgryyx1GvHEpXVfoDF6Ak3rTiWh8Rg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-builder-react-jsx-experimental": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.11.5.tgz", + "integrity": "sha512-Vc4aPJnRZKWfzeCBsqTBnzulVNjABVdahSPhtdMD3Vs80ykx4a87jTHtF/VR+alSrDmNvat7l13yrRHauGcHVw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-module-imports": "^7.10.4", + "@babel/types": "^7.11.5" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz", + "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==", + "requires": { + "@babel/compat-data": "^7.10.4", + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "levenary": "^1.1.1", + "semver": "^5.5.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz", + "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==", + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-member-expression-to-functions": "^7.10.5", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz", + "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-regex": "^7.10.4", + "regexpu-core": "^4.7.0" + } + }, + "@babel/helper-define-map": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", + "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz", + "integrity": "sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", + "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", + "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", + "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-module-transforms": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", + "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/template": "^7.10.4", + "@babel/types": "^7.11.0", + "lodash": "^4.17.19" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + }, + "@babel/helper-regex": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", + "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", + "requires": { + "lodash": "^4.17.19" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz", + "integrity": "sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-wrap-function": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-replace-supers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", + "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", + "requires": { + "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-simple-access": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", + "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", + "requires": { + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz", + "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==", + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" + }, + "@babel/helper-wrap-function": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz", + "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==", + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helpers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", + "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", + "requires": { + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==" + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz", + "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4", + "@babel/plugin-syntax-async-generators": "^7.8.0" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz", + "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz", + "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz", + "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz", + "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.0" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz", + "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz", + "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz", + "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz", + "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.10.4" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz", + "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz", + "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz", + "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz", + "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz", + "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz", + "integrity": "sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz", + "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.10.4.tgz", + "integrity": "sha512-oSAEz1YkBCAKr5Yiq8/BNtvSAPwkp/IyUnwZogd8p+F0RuYQQrLeRUzIQhueQTTBy/F+a40uS7OFKxnkRvmvFQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz", + "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz", + "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==", + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz", + "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz", + "integrity": "sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz", + "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-define-map": "^7.10.4", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz", + "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz", + "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz", + "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz", + "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz", + "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==", + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz", + "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz", + "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==", + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz", + "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz", + "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz", + "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==", + "requires": { + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz", + "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==", + "requires": { + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz", + "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==", + "requires": { + "@babel/helper-hoist-variables": "^7.10.4", + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz", + "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==", + "requires": { + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz", + "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz", + "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz", + "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz", + "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==", + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz", + "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.4.tgz", + "integrity": "sha512-Zd4X54Mu9SBfPGnEcaGcOrVAYOtjT2on8QZkLKEq1S/tHexG39d9XXGZv19VfRrDjPJzFmPfTAqOQS1pfFOujw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.4.tgz", + "integrity": "sha512-L+MfRhWjX0eI7Js093MM6MacKU4M6dnCRa/QPDwYMxjljzSCzzlzKzj9Pk4P3OtrPcxr2N3znR419nr3Xw+65A==", + "dev": true, + "requires": { + "@babel/helper-builder-react-jsx": "^7.10.4", + "@babel/helper-builder-react-jsx-experimental": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-jsx": "^7.10.4" + } + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.11.5.tgz", + "integrity": "sha512-cImAmIlKJ84sDmpQzm4/0q/2xrXlDezQoixy3qoz1NJeZL/8PRon6xZtluvr4H4FzwlDGI5tCcFupMnXGtr+qw==", + "dev": true, + "requires": { + "@babel/helper-builder-react-jsx-experimental": "^7.11.5", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-jsx": "^7.10.4" + } + }, + "@babel/plugin-transform-react-jsx-self": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.4.tgz", + "integrity": "sha512-yOvxY2pDiVJi0axdTWHSMi5T0DILN+H+SaeJeACHKjQLezEzhLx9nEF9xgpBLPtkZsks9cnb5P9iBEi21En3gg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-jsx": "^7.10.4" + } + }, + "@babel/plugin-transform-react-jsx-source": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.5.tgz", + "integrity": "sha512-wTeqHVkN1lfPLubRiZH3o73f4rfon42HpgxUSs86Nc+8QIcm/B9s8NNVXu/gwGcOyd7yDib9ikxoDLxJP0UiDA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-jsx": "^7.10.4" + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.4.tgz", + "integrity": "sha512-+njZkqcOuS8RaPakrnR9KvxjoG1ASJWpoIv/doyWngId88JoFlPlISenGXjrVacZUIALGUr6eodRs1vmPnF23A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz", + "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==", + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz", + "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz", + "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz", + "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz", + "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-regex": "^7.10.4" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz", + "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz", + "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.11.0.tgz", + "integrity": "sha512-edJsNzTtvb3MaXQwj8403B7mZoGu9ElDJQZOKjGUnvilquxBA3IQoEIOvkX/1O8xfAsnHS/oQhe2w/IXrr+w0w==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-typescript": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz", + "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz", + "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/preset-env": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.5.tgz", + "integrity": "sha512-kXqmW1jVcnB2cdueV+fyBM8estd5mlNfaQi6lwLgRwCby4edpavgbFhiBNjmWA3JpB/yZGSISa7Srf+TwxDQoA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.11.0", + "@babel/helper-compilation-targets": "^7.10.4", + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-proposal-async-generator-functions": "^7.10.4", + "@babel/plugin-proposal-class-properties": "^7.10.4", + "@babel/plugin-proposal-dynamic-import": "^7.10.4", + "@babel/plugin-proposal-export-namespace-from": "^7.10.4", + "@babel/plugin-proposal-json-strings": "^7.10.4", + "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", + "@babel/plugin-proposal-numeric-separator": "^7.10.4", + "@babel/plugin-proposal-object-rest-spread": "^7.11.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.10.4", + "@babel/plugin-proposal-optional-chaining": "^7.11.0", + "@babel/plugin-proposal-private-methods": "^7.10.4", + "@babel/plugin-proposal-unicode-property-regex": "^7.10.4", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.10.4", + "@babel/plugin-transform-arrow-functions": "^7.10.4", + "@babel/plugin-transform-async-to-generator": "^7.10.4", + "@babel/plugin-transform-block-scoped-functions": "^7.10.4", + "@babel/plugin-transform-block-scoping": "^7.10.4", + "@babel/plugin-transform-classes": "^7.10.4", + "@babel/plugin-transform-computed-properties": "^7.10.4", + "@babel/plugin-transform-destructuring": "^7.10.4", + "@babel/plugin-transform-dotall-regex": "^7.10.4", + "@babel/plugin-transform-duplicate-keys": "^7.10.4", + "@babel/plugin-transform-exponentiation-operator": "^7.10.4", + "@babel/plugin-transform-for-of": "^7.10.4", + "@babel/plugin-transform-function-name": "^7.10.4", + "@babel/plugin-transform-literals": "^7.10.4", + "@babel/plugin-transform-member-expression-literals": "^7.10.4", + "@babel/plugin-transform-modules-amd": "^7.10.4", + "@babel/plugin-transform-modules-commonjs": "^7.10.4", + "@babel/plugin-transform-modules-systemjs": "^7.10.4", + "@babel/plugin-transform-modules-umd": "^7.10.4", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4", + "@babel/plugin-transform-new-target": "^7.10.4", + "@babel/plugin-transform-object-super": "^7.10.4", + "@babel/plugin-transform-parameters": "^7.10.4", + "@babel/plugin-transform-property-literals": "^7.10.4", + "@babel/plugin-transform-regenerator": "^7.10.4", + "@babel/plugin-transform-reserved-words": "^7.10.4", + "@babel/plugin-transform-shorthand-properties": "^7.10.4", + "@babel/plugin-transform-spread": "^7.11.0", + "@babel/plugin-transform-sticky-regex": "^7.10.4", + "@babel/plugin-transform-template-literals": "^7.10.4", + "@babel/plugin-transform-typeof-symbol": "^7.10.4", + "@babel/plugin-transform-unicode-escapes": "^7.10.4", + "@babel/plugin-transform-unicode-regex": "^7.10.4", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.11.5", + "browserslist": "^4.12.0", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.1", + "semver": "^5.5.0" + } + }, + "@babel/preset-modules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/preset-react": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.10.4.tgz", + "integrity": "sha512-BrHp4TgOIy4M19JAfO1LhycVXOPWdDbTRep7eVyatf174Hff+6Uk53sDyajqZPu8W1qXRBiYOfIamek6jA7YVw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-transform-react-display-name": "^7.10.4", + "@babel/plugin-transform-react-jsx": "^7.10.4", + "@babel/plugin-transform-react-jsx-development": "^7.10.4", + "@babel/plugin-transform-react-jsx-self": "^7.10.4", + "@babel/plugin-transform-react-jsx-source": "^7.10.4", + "@babel/plugin-transform-react-pure-annotations": "^7.10.4" + } + }, + "@babel/preset-typescript": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.10.4.tgz", + "integrity": "sha512-SdYnvGPv+bLlwkF2VkJnaX/ni1sMNetcGI1+nThF1gyv6Ph8Qucc4ZZAjM5yZcE/AKRXIOTZz7eSRDWOEjPyRQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-transform-typescript": "^7.10.4" + } + }, + "@babel/runtime": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", + "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/traverse": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", + "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.5", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.5", + "@babel/types": "^7.11.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "@emotion/cache": { + "version": "10.0.29", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz", + "integrity": "sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==", + "requires": { + "@emotion/sheet": "0.9.4", + "@emotion/stylis": "0.8.5", + "@emotion/utils": "0.11.3", + "@emotion/weak-memoize": "0.2.5" + } + }, + "@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" + }, + "@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==" + }, + "@emotion/serialize": { + "version": "0.11.16", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.11.16.tgz", + "integrity": "sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg==", + "requires": { + "@emotion/hash": "0.8.0", + "@emotion/memoize": "0.7.4", + "@emotion/unitless": "0.7.5", + "@emotion/utils": "0.11.3", + "csstype": "^2.5.7" + }, + "dependencies": { + "csstype": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", + "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==" + } + } + }, + "@emotion/sheet": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-0.9.4.tgz", + "integrity": "sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA==" + }, + "@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, + "@emotion/utils": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.11.3.tgz", + "integrity": "sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw==" + }, + "@emotion/weak-memoize": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz", + "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==" + }, + "@eslint/eslintrc": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz", + "integrity": "sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + } + }, + "@istanbuljs/schema": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "dev": true + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==" + }, + "@types/node": { + "version": "14.11.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.2.tgz", + "integrity": "sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA==" + }, + "@types/prop-types": { + "version": "15.7.3", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==", + "dev": true + }, + "@types/react": { + "version": "16.9.49", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.49.tgz", + "integrity": "sha512-DtLFjSj0OYAdVLBbyjhuV9CdGVHCkHn2R+xr3XkBvK2rS1Y1tkc14XSGjYgm5Fjjr90AxH9tiSzc1pCFMGO06g==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "@types/unist": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", + "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==" + }, + "@types/vfile": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz", + "integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==", + "requires": { + "@types/node": "*", + "@types/unist": "*", + "@types/vfile-message": "*" + } + }, + "@types/vfile-message": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-2.0.0.tgz", + "integrity": "sha512-GpTIuDpb9u4zIO165fUy9+fXcULdD8HFRNli04GehoMVbeNq7D6OBnqSmg3lxZnC+UvgUhEWKxdKiwYUkGltIw==", + "requires": { + "vfile-message": "*" + } + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==" + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==" + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "requires": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "acorn": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, + "adm-zip": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz", + "integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==", + "dev": true + }, + "ajv": { + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "optional": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-includes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "array.prototype.flatmap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz", + "integrity": "sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", + "dev": true + }, + "babel-loader": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", + "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==", + "requires": { + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.4.0", + "mkdirp": "^0.5.3", + "pify": "^4.0.1", + "schema-utils": "^2.6.5" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-istanbul": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", + "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^4.0.0", + "test-exclude": "^6.0.0" + } + }, + "babel-plugin-transform-inline-environment-variables": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-environment-variables/-/babel-plugin-transform-inline-environment-variables-0.4.3.tgz", + "integrity": "sha1-o7CYgzU76LXiM24/8e+KXZP5xIk=", + "dev": true + }, + "bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "optional": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" + }, + "bowser": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz", + "integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.14.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.4.tgz", + "integrity": "sha512-7FOuawafVdEwa5Jv4nzeik/PepAjVte6HmVGHsjt2bC237jeL9QlcTBDF3PnHEvcC6uHwLGYPwZHNZMB7wWAnw==", + "requires": { + "caniuse-lite": "^1.0.30001135", + "electron-to-chromium": "^1.3.570", + "escalade": "^3.1.0", + "node-releases": "^1.1.61" + } + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "caniuse-lite": { + "version": "1.0.30001135", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001135.tgz", + "integrity": "sha512-ziNcheTGTHlu9g34EVoHQdIu5g4foc8EsxMGC7Xkokmvw0dqNtX8BS8RgCgFBaAiSp2IdjvBxNdh0ssib28eVQ==" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "ccount": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.5.tgz", + "integrity": "sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw==" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==" + }, + "character-entities-html4": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.4.tgz", + "integrity": "sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g==" + }, + "character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==" + }, + "character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" + }, + "cldr-data": { + "version": "36.0.0", + "resolved": "https://registry.npmjs.org/cldr-data/-/cldr-data-36.0.0.tgz", + "integrity": "sha512-F3n+9DUs41vhys8eF/hsCgkmYlgXMCiwaE75uGZjUbS/jkszBnLylXj7xW3bBlMU1d2IuAptpoNAb6lTCu/RSg==", + "dev": true, + "requires": { + "cldr-data-downloader": "0.3.x", + "glob": "5.x.x" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "cldr-data-downloader": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/cldr-data-downloader/-/cldr-data-downloader-0.3.5.tgz", + "integrity": "sha512-uyIMa1K98DAp/PE7dYpq2COIrkWn681Atjng1GgEzeJzYb1jANtugtp9wre6+voE+qzVC8jtWv6E/xZ1GTJdlw==", + "dev": true, + "requires": { + "adm-zip": "0.4.11", + "mkdirp": "0.5.0", + "nopt": "3.0.x", + "progress": "1.1.8", + "q": "1.0.1", + "request": "~2.87.0", + "request-progress": "0.3.1" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + } + } + }, + "cldrjs": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/cldrjs/-/cldrjs-0.5.4.tgz", + "integrity": "sha512-6QkI7oPLUZ9vA5BQAmUOfh5JIpESfnYy/M8d7Ddl9Yx+z2TAnQgnc3kbgjkIgxsk5Y0tOY+n6itMWXzQQQ2IWg==" + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "collapse-white-space": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "concurrently": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.3.0.tgz", + "integrity": "sha512-8MhqOB6PWlBfA2vJ8a0bSFKATOdWlHiQlk11IfmQBPaHVP8oP2gsh2MObE6UR3hqDHqvaIvLTyceNW6obVuFHQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "date-fns": "^2.0.1", + "lodash": "^4.17.15", + "read-pkg": "^4.0.1", + "rxjs": "^6.5.2", + "spawn-command": "^0.0.2-1", + "supports-color": "^6.1.0", + "tree-kill": "^1.2.2", + "yargs": "^13.3.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "core-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", + "dev": true + }, + "core-js-compat": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", + "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==", + "requires": { + "browserslist": "^4.8.5", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "create-emotion": { + "version": "10.0.27", + "resolved": "https://registry.npmjs.org/create-emotion/-/create-emotion-10.0.27.tgz", + "integrity": "sha512-fIK73w82HPPn/RsAij7+Zt8eCE8SptcJ3WoRMfxMtjteYxud8GDTKKld7MYwAX2TVhrw29uR1N/bVGxeStHILg==", + "requires": { + "@emotion/cache": "^10.0.27", + "@emotion/serialize": "^0.11.15", + "@emotion/sheet": "0.9.4", + "@emotion/utils": "0.11.3" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css-in-js-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz", + "integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==", + "requires": { + "hyphenate-style-name": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "csstype": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.3.tgz", + "integrity": "sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag==", + "dev": true + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-fns": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.16.1.tgz", + "integrity": "sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ==", + "dev": true + }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true + }, + "debounce": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz", + "integrity": "sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-serializer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.1.0.tgz", + "integrity": "sha512-ox7bvGXt2n+uLWtCRLybYx60IrOlWL/aCebWJk1T0d4m3y2tzf4U3ij9wBMUb6YJZpz06HCCYuyCDveE2xXmzQ==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0", + "entities": "^2.0.0" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" + }, + "domelementtype": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", + "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==" + }, + "domhandler": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.0.0.tgz", + "integrity": "sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==", + "requires": { + "domelementtype": "^2.0.1" + } + }, + "domutils": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.3.0.tgz", + "integrity": "sha512-xWC75PM3QF6MjE5e58OzwTX0B/rPQnlqH0YyXB/c056RtVJA+eu60da2I/bdnEHzEYC00g8QaZUlAbqOZVbOsw==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0" + } + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "dynamic-dedupe": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", + "integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=", + "dev": true, + "requires": { + "xtend": "^4.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "electron-to-chromium": { + "version": "1.3.571", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.571.tgz", + "integrity": "sha512-UYEQ2Gtc50kqmyOmOVtj6Oqi38lm5yRJY3pLuWt6UIot0No1L09uu6Ja6/1XKwmz/p0eJFZTUZi+khd1PV1hHA==" + }, + "elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "requires": { + "iconv-lite": "^0.6.2" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", + "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.18.0-next.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", + "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escalade": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz", + "integrity": "sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + } + } + }, + "eslint": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.9.0.tgz", + "integrity": "sha512-V6QyhX21+uXp4T+3nrNfI3hQNBDa/P8ga7LoQOenwrlEFXrEnUEE+ok1dMtaS3b6rmLXhT1TkTIsG75HMLbknA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@eslint/eslintrc": "^0.1.3", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.0", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^1.3.0", + "espree": "^7.3.0", + "esquery": "^1.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "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 + }, + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "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 + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "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" + } + } + } + }, + "eslint-plugin-prettier": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz", + "integrity": "sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-plugin-react": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.21.0.tgz", + "integrity": "sha512-WaieZZ4cayAfPBmy5KkEqFfLQf/VkzoUsvM5DfD9G1lrz+3LtZ8X6nToEUQiFe1X5ApNIzkMd+7NUy+2OmSTQQ==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flatmap": "^1.2.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.4.1", + "object.entries": "^1.1.2", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "resolve": "^1.17.0", + "string.prototype.matchall": "^4.0.2" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + } + } + }, + "eslint-plugin-react-hooks": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.1.2.tgz", + "integrity": "sha512-ykUeqkGyUGgwTtk78C0o8UG2fzwmgJ0qxBGPp2WqRKsTwcLuVf01kTDRAtOsd4u6whX2XOC8749n2vPydP82fg==", + "dev": true + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", + "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.3.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "event-as-promise": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/event-as-promise/-/event-as-promise-1.0.5.tgz", + "integrity": "sha512-z/WIlyou7oTvXBjm5YYjfklr2d8gUWtx8b5GAcrIs1n1D35f7NIK0CrcYSXbY3VYikG9bUan+wScPyGXL/NH4A==" + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, + "event-target-shim-es5": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/event-target-shim-es5/-/event-target-shim-es5-1.2.0.tgz", + "integrity": "sha512-Ki++m13aGuz86Ez7NgvP+JXoe1Jd5BZ4b9hte531pc+AMxVRlf4Lv4U30cGwK3bxlc/lxnvK8muHykVqDB369A==", + "requires": { + "@babel/core": "7.11.1", + "@babel/preset-env": "7.11.0", + "babel-loader": "8.1.0", + "webpack": "4.44.1", + "webpack-cli": "3.3.12" + }, + "dependencies": { + "@babel/core": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.1.tgz", + "integrity": "sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.0", + "@babel/helper-module-transforms": "^7.11.0", + "@babel/helpers": "^7.10.4", + "@babel/parser": "^7.11.1", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.11.0", + "@babel/types": "^7.11.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/preset-env": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.0.tgz", + "integrity": "sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg==", + "requires": { + "@babel/compat-data": "^7.11.0", + "@babel/helper-compilation-targets": "^7.10.4", + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-proposal-async-generator-functions": "^7.10.4", + "@babel/plugin-proposal-class-properties": "^7.10.4", + "@babel/plugin-proposal-dynamic-import": "^7.10.4", + "@babel/plugin-proposal-export-namespace-from": "^7.10.4", + "@babel/plugin-proposal-json-strings": "^7.10.4", + "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", + "@babel/plugin-proposal-numeric-separator": "^7.10.4", + "@babel/plugin-proposal-object-rest-spread": "^7.11.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.10.4", + "@babel/plugin-proposal-optional-chaining": "^7.11.0", + "@babel/plugin-proposal-private-methods": "^7.10.4", + "@babel/plugin-proposal-unicode-property-regex": "^7.10.4", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.10.4", + "@babel/plugin-transform-arrow-functions": "^7.10.4", + "@babel/plugin-transform-async-to-generator": "^7.10.4", + "@babel/plugin-transform-block-scoped-functions": "^7.10.4", + "@babel/plugin-transform-block-scoping": "^7.10.4", + "@babel/plugin-transform-classes": "^7.10.4", + "@babel/plugin-transform-computed-properties": "^7.10.4", + "@babel/plugin-transform-destructuring": "^7.10.4", + "@babel/plugin-transform-dotall-regex": "^7.10.4", + "@babel/plugin-transform-duplicate-keys": "^7.10.4", + "@babel/plugin-transform-exponentiation-operator": "^7.10.4", + "@babel/plugin-transform-for-of": "^7.10.4", + "@babel/plugin-transform-function-name": "^7.10.4", + "@babel/plugin-transform-literals": "^7.10.4", + "@babel/plugin-transform-member-expression-literals": "^7.10.4", + "@babel/plugin-transform-modules-amd": "^7.10.4", + "@babel/plugin-transform-modules-commonjs": "^7.10.4", + "@babel/plugin-transform-modules-systemjs": "^7.10.4", + "@babel/plugin-transform-modules-umd": "^7.10.4", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4", + "@babel/plugin-transform-new-target": "^7.10.4", + "@babel/plugin-transform-object-super": "^7.10.4", + "@babel/plugin-transform-parameters": "^7.10.4", + "@babel/plugin-transform-property-literals": "^7.10.4", + "@babel/plugin-transform-regenerator": "^7.10.4", + "@babel/plugin-transform-reserved-words": "^7.10.4", + "@babel/plugin-transform-shorthand-properties": "^7.10.4", + "@babel/plugin-transform-spread": "^7.11.0", + "@babel/plugin-transform-sticky-regex": "^7.10.4", + "@babel/plugin-transform-template-literals": "^7.10.4", + "@babel/plugin-transform-typeof-symbol": "^7.10.4", + "@babel/plugin-transform-unicode-escapes": "^7.10.4", + "@babel/plugin-transform-unicode-regex": "^7.10.4", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.11.0", + "browserslist": "^4.12.0", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.1", + "semver": "^5.5.0" + } + }, + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fbjs": { + "version": "0.8.17", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", + "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", + "requires": { + "core-js": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" + }, + "dependencies": { + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + } + } + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, + "filewatcher": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/filewatcher/-/filewatcher-3.0.1.tgz", + "integrity": "sha1-9KGVc1Xdr0Q8zXiolfPVXiPIoDQ=", + "dev": true, + "requires": { + "debounce": "^1.0.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==" + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glamor": { + "version": "2.20.40", + "resolved": "https://registry.npmjs.org/glamor/-/glamor-2.20.40.tgz", + "integrity": "sha512-DNXCd+c14N9QF8aAKrfl4xakPk5FdcFwmH7sD0qnC0Pr7xoZ5W9yovhUrY/dJc3psfGGXC58vqQyRtuskyUJxA==", + "requires": { + "fbjs": "^0.8.12", + "inline-style-prefixer": "^3.0.6", + "object-assign": "^4.1.1", + "prop-types": "^15.5.10", + "through": "^2.3.8" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "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" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "optional": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "requires": { + "global-prefix": "^3.0.0" + }, + "dependencies": { + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "globalize": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/globalize/-/globalize-1.5.0.tgz", + "integrity": "sha512-76fcPQO/WLthtSwjgIZ/Zv2XSXqv9ifvl1PwIxJNCZNFHigGCpg3fBZ0poJ30b2kdDgofPkYl478lVZA6esESQ==", + "requires": { + "cldrjs": "^0.5.0" + } + }, + "globalize-compiler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/globalize-compiler/-/globalize-compiler-1.1.1.tgz", + "integrity": "sha512-oZIwVp3L/waDidle7Qrw4FiCCmOLAqvdM9P7W8nEO4OfXO//l/abBiA+RL2+mYZPOpTAlRDVS2FLfFVWxHovWA==", + "dev": true, + "requires": { + "escodegen": "^1.6.1", + "esprima": "^2.3.0", + "nopt": "^3.0.3" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + } + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "dev": true, + "requires": { + "ajv": "^5.1.0", + "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + } + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "htmlparser2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz", + "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0", + "domutils": "^2.0.0", + "entities": "^2.0.0" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "hyphenate-style-name": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", + "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" + }, + "iana-tz-data": { + "version": "2019.1.0", + "resolved": "https://registry.npmjs.org/iana-tz-data/-/iana-tz-data-2019.1.0.tgz", + "integrity": "sha512-T7+26Skkyxqjp4mg20/O065j9J5qP39nWVQj/2ArxQ0gSPkL+T9lwerRmiOAzFRNsNXepX45QqchqTVENwNvig==", + "dev": true + }, + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "inline-style-prefixer": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-3.0.8.tgz", + "integrity": "sha1-hVG45bTVcyROZqNLBPfTIHaitTQ=", + "requires": { + "bowser": "^1.7.3", + "css-in-js-utils": "^2.0.0" + } + }, + "internal-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", + "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", + "dev": true, + "requires": { + "es-abstract": "^1.17.0-next.1", + "has": "^1.0.3", + "side-channel": "^1.0.2" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==" + }, + "is-alphanumeric": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", + "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=" + }, + "is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "requires": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + }, + "is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==" + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==" + }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=" + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-whitespace-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "is-word-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==" + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "requires": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "requires": { + "minimist": "^1.2.5" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jsx-ast-utils": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz", + "integrity": "sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "object.assign": "^4.1.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + }, + "levenary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", + "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", + "requires": { + "leven": "^3.1.0" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "linkify-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==", + "requires": { + "uc.micro": "^1.0.1" + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==" + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "longest-streak": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", + "integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "markdown-escapes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", + "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==" + }, + "markdown-it": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-11.0.0.tgz", + "integrity": "sha512-+CvOnmbSubmQFSA9dKz1BRiaSMV7rhexl3sngKqFyXSagoA3fBdJQ8oZWtRy2knXdpDXaBw44euz37DeJQ9asg==", + "requires": { + "argparse": "^1.0.7", + "entities": "~2.0.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "markdown-table": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", + "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==" + }, + "math-random": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-2.0.1.tgz", + "integrity": "sha512-oIEbWiVDxDpl5tIF4S6zYS9JExhh3bun3uLb3YAinHPTlRtW4g1S66LtJrJ4Npq8dgIa8CLK5iPVah5n4n0s2w==" + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdast-util-compact": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.4.tgz", + "integrity": "sha512-3YDMQHI5vRiS2uygEFYaqckibpJtKq5Sj2c8JioeOQBU6INpKbdWzfyLqFFnDwEcEnRFIdMsguzs5pC1Jp4Isg==", + "requires": { + "unist-util-visit": "^1.1.0" + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + }, + "memoize-one": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-4.0.3.tgz", + "integrity": "sha512-QmpUu4KqDmX0plH4u+tf0riMc1KHE1+lw95cMrLlXQAFOx/xnBtwhZ52XJxd9X2O6kwKBqX32kmhbhlobD0cuw==" + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "node-dev": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/node-dev/-/node-dev-5.2.0.tgz", + "integrity": "sha512-//aG1cBZsXhQeXbIcZokYsxktU9p+xnG0dzJaDmfwuX50NnjxRoScj6Ymm0JuWVA6180sYfkRGP38vf8fJ4j+Q==", + "dev": true, + "requires": { + "dateformat": "^3.0.3", + "dynamic-dedupe": "^0.3.0", + "filewatcher": "~3.0.0", + "minimist": "^1.1.3", + "node-notifier": "^5.4.0", + "resolve": "^1.0.0" + } + }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "node-notifier": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", + "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", + "dev": true, + "requires": { + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "node-releases": { + "version": "1.1.61", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz", + "integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==" + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "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" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "optional": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", + "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "object.fromentries": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", + "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-entities": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", + "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", + "requires": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + }, + "parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha1-8r0iH2zJcKk42IVWq8WJyqqiveE=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "optional": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "optional": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "postcss": { + "version": "7.0.34", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.34.tgz", + "integrity": "sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw==", + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", + "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "~2.0.3" + } + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "q": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.0.1.tgz", + "integrity": "sha1-EYcq7t7okmgRCxCnGESP+xARKhQ=", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "react-dictate-button": { + "version": "1.2.3-master.6b4fe72", + "resolved": "https://registry.npmjs.org/react-dictate-button/-/react-dictate-button-1.2.3-master.6b4fe72.tgz", + "integrity": "sha512-dAgitz+7jQTPx8aQRkggEchYxwzkpnd6pC35IztWrGlHgF70l35B8PA0d5m336E0G2suIEk4QFSDI1gVx9nLfw==", + "requires": { + "classnames": "^2.2.6", + "glamor": "^2.20.40", + "memoize-one": "^4.0.0" + } + }, + "react-film": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-film/-/react-film-3.0.0.tgz", + "integrity": "sha512-aBiMFc/srZWWRal/va39YZVMcQiqUAyJ+G6n5CADnpdS+MO73x/jY50Aawwx+Aqyf/LJFO3d/8fR1WE74DYqOw==", + "requires": { + "classnames": "2.2.6", + "create-emotion": "10.0.27", + "math-random": "2.0.1", + "memoize-one": "5.1.1", + "prop-types": "15.7.2" + }, + "dependencies": { + "memoize-one": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz", + "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==" + } + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "react-redux": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz", + "integrity": "sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA==", + "requires": { + "@babel/runtime": "^7.5.5", + "hoist-non-react-statics": "^3.3.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^16.9.0" + } + }, + "react-say": { + "version": "2.0.2-master.ee7cd76", + "resolved": "https://registry.npmjs.org/react-say/-/react-say-2.0.2-master.ee7cd76.tgz", + "integrity": "sha512-wTJleRlP5ojCuYGElAtBCrbeGgm2FB6De4/YilBWfDBNhPUHiiHgZSQpn8x+E9aEvx2vZINI7gH+1SrAcoazDA==", + "requires": { + "@babel/runtime": "^7.7.2", + "classnames": "^2.2.6", + "event-as-promise": "^1.0.5", + "memoize-one": "^5.1.1" + }, + "dependencies": { + "memoize-one": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz", + "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==" + } + } + }, + "react-scroll-to-bottom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/react-scroll-to-bottom/-/react-scroll-to-bottom-4.0.0.tgz", + "integrity": "sha512-7lOy14XbBdweO+8LMRp7F9nP0xWtf0mAt+I5rm1hbNZq5JcXJRn0dsZjz9ySDLleH+zMlyhPwinqFDmEEUdHtA==", + "requires": { + "classnames": "2.2.6", + "create-emotion": "10.0.27", + "math-random": "2.0.1", + "prop-types": "15.7.2", + "simple-update-in": "2.2.0" + } + }, + "read-pkg": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", + "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", + "dev": true, + "requires": { + "normalize-package-data": "^2.3.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "redux": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", + "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", + "requires": { + "loose-envify": "^1.4.0", + "symbol-observable": "^1.2.0" + } + }, + "regenerate": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", + "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==" + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, + "regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, + "regexpu-core": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + } + }, + "regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" + }, + "regjsparser": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", + "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + } + } + }, + "remark": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/remark/-/remark-10.0.1.tgz", + "integrity": "sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ==", + "requires": { + "remark-parse": "^6.0.0", + "remark-stringify": "^6.0.0", + "unified": "^7.0.0" + } + }, + "remark-parse": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-6.0.3.tgz", + "integrity": "sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg==", + "requires": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + } + }, + "remark-stringify": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-6.0.4.tgz", + "integrity": "sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg==", + "requires": { + "ccount": "^1.0.0", + "is-alphanumeric": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "longest-streak": "^2.0.1", + "markdown-escapes": "^1.0.0", + "markdown-table": "^1.1.0", + "mdast-util-compact": "^1.0.0", + "parse-entities": "^1.0.2", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "stringify-entities": "^1.0.1", + "unherit": "^1.0.4", + "xtend": "^4.0.1" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "optional": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" + }, + "request": { + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.6.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.1", + "forever-agent": "~0.6.1", + "form-data": "~2.3.1", + "har-validator": "~5.0.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.17", + "oauth-sign": "~0.8.2", + "performance-now": "^2.1.0", + "qs": "~6.5.1", + "safe-buffer": "^5.1.1", + "tough-cookie": "~2.3.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.1.0" + } + }, + "request-progress": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-0.3.1.tgz", + "integrity": "sha1-ByHBBdipasayzossia4tXs/Pazo=", + "dev": true, + "requires": { + "throttleit": "~0.0.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + } + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "dependencies": { + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + } + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "requires": { + "aproba": "^1.1.1" + } + }, + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sanitize-html": { + "version": "1.27.4", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.27.4.tgz", + "integrity": "sha512-VvY1hxVvMXzSos/LzqeBl9/KYu3mkEOtl5NMwz6jER318dSHDCig0AOjZOtnoCwAC3HMs9LhfWkPCmQGttb4ng==", + "requires": { + "htmlparser2": "^4.1.0", + "lodash": "^4.17.15", + "parse-srcset": "^1.0.2", + "postcss": "^7.0.27" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, + "side-channel": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.3.tgz", + "integrity": "sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g==", + "dev": true, + "requires": { + "es-abstract": "^1.18.0-next.0", + "object-inspect": "^1.8.0" + } + }, + "simple-update-in": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/simple-update-in/-/simple-update-in-2.2.0.tgz", + "integrity": "sha512-FrW41lLiOs82jKxwq39UrE1HDAHOvirKWk4Nv8tqnFFFknVbTxcHZzDS4vt02qqdU/5+KNsQHWzhKHznDBmrww==" + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", + "dev": true + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "state-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==" + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "string.prototype.matchall": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz", + "integrity": "sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "has-symbols": "^1.0.1", + "internal-slot": "^1.0.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.2" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "stringify-entities": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", + "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", + "requires": { + "character-entities-html4": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "strip-markdown": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/strip-markdown/-/strip-markdown-3.0.4.tgz", + "integrity": "sha512-O+0DAu96wofH82JPZN4RkGdi3Lruo0yveDCeXUg0uRNWztPcn/s1AD85584OYUsAcjW0qR4pBlh8OBl/hH4Erw==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "throttleit": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", + "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "timers-browserify": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", + "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", + "requires": { + "setimmediate": "^1.0.4" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "requires": { + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + }, + "trim-trailing-lines": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz", + "integrity": "sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA==" + }, + "trough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==" + }, + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typescript": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.3.tgz", + "integrity": "sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.22", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.22.tgz", + "integrity": "sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q==" + }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, + "unherit": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", + "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "requires": { + "inherits": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==" + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==" + }, + "unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==" + }, + "unified": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-7.1.0.tgz", + "integrity": "sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==", + "requires": { + "@types/unist": "^2.0.0", + "@types/vfile": "^3.0.0", + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^1.1.0", + "trough": "^1.0.0", + "vfile": "^3.0.0", + "x-is-string": "^0.1.0" + } + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unist-util-is": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==" + }, + "unist-util-remove-position": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", + "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", + "requires": { + "unist-util-visit": "^1.1.0" + } + }, + "unist-util-stringify-position": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", + "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "requires": { + "@types/unist": "^2.0.2" + } + }, + "unist-util-visit": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", + "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", + "requires": { + "unist-util-visit-parents": "^2.0.0" + } + }, + "unist-util-visit-parents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", + "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", + "requires": { + "unist-util-is": "^3.0.0" + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "optional": true + }, + "uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz", + "integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==", + "requires": { + "is-buffer": "^2.0.0", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-message": "^1.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" + }, + "unist-util-stringify-position": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", + "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==" + }, + "vfile-message": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", + "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", + "requires": { + "unist-util-stringify-position": "^1.1.1" + } + } + } + }, + "vfile-location": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", + "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==" + }, + "vfile-message": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", + "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^2.0.0" + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" + }, + "watchpack": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", + "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "optional": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "optional": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "optional": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", + "optional": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "optional": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "optional": true + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "optional": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "optional": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "optional": true + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "optional": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "optional": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "watchpack-chokidar2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", + "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", + "optional": true, + "requires": { + "chokidar": "^2.1.8" + } + }, + "webpack": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz", + "integrity": "sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.3.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==" + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "webpack-cli": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz", + "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==", + "requires": { + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "enhanced-resolve": "^4.1.1", + "findup-sync": "^3.0.0", + "global-modules": "^2.0.0", + "import-local": "^2.0.0", + "interpret": "^1.4.0", + "loader-utils": "^1.4.0", + "supports-color": "^6.1.0", + "v8-compile-cache": "^2.1.1", + "yargs": "^13.3.2" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "whatwg-fetch": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.4.1.tgz", + "integrity": "sha512-sofZVzE1wKwO+EYPbWfiwzaKovWiZXf4coEzjGP9b2GBVgQRLQUZ2QcuPpQExGDAW5GItpEm6Tl4OU5mywnAoQ==" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "x-is-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } +} diff --git a/packages/api/package.json b/packages/api/package.json new file mode 100644 index 0000000000..a25397bbd0 --- /dev/null +++ b/packages/api/package.json @@ -0,0 +1,78 @@ +{ + "name": "botframework-webchat-api", + "version": "0.0.0-0", + "description": "React DOM component of botframework-webchat", + "main": "lib/index.js", + "publishConfig": { + "access": "public" + }, + "author": "Microsoft Corporation", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/microsoft/BotFramework-WebChat.git" + }, + "bugs": { + "url": "https://github.com/microsoft/BotFramework-WebChat/issues" + }, + "homepage": "https://github.com/microsoft/BotFramework-WebChat/tree/master/packages/component#readme", + "scripts": { + "build": "npm run build:typescript && npm run build:babel && npm run build:globalize", + "build:babel": "babel src --copy-files --extensions .js,.ts,.tsx --ignore **/*.spec.js,**/*.spec.ts,**/*.spec.tsx,**/*.test.js,**/*.test.ts,**/*.test.tsx,__tests__/**/*.js,__tests__/**/*.ts,__tests__/**/*.tsx --no-copy-ignored --out-dir lib --verbose", + "build:globalize": "node scripts/createPrecompiledGlobalize.js", + "build:typescript": "tsc --project src/tsconfig.json", + "eslint": "eslint src/**/*.js src/**/*.ts", + "prestart": "npm run build:babel", + "start": "concurrently --kill-others --names \"babel,globalize,tsc\" \"npm run start:babel\" \"npm run start:globalize\" \"npm run start:typescript\"", + "start:babel": "npm run build:babel -- --skip-initial-build --watch", + "start:globalize": "node-dev --respawn scripts/createPrecompiledGlobalize.js", + "start:typescript": "npm run build:typescript -- --watch" + }, + "cldr-data-coverage": "full", + "devDependencies": { + "@babel/cli": "^7.11.6", + "@babel/core": "^7.11.6", + "@babel/preset-env": "^7.11.5", + "@babel/preset-react": "^7.10.4", + "@babel/preset-typescript": "^7.10.4", + "@types/node": "^14.11.2", + "@types/react": "^16.9.49", + "babel-plugin-istanbul": "^6.0.0", + "babel-plugin-transform-inline-environment-variables": "^0.4.3", + "cldr-data": "^36.0.0", + "concurrently": "^5.3.0", + "core-js": "^3.6.5", + "eslint": "^7.9.0", + "eslint-plugin-prettier": "^3.1.4", + "eslint-plugin-react": "^7.21.0", + "eslint-plugin-react-hooks": "^4.1.2", + "globalize-compiler": "^1.1.1", + "iana-tz-data": "^2019.1.0", + "node-dev": "^5.2.0", + "prettier": "^2.1.2", + "typescript": "^4.0.3" + }, + "dependencies": { + "botframework-webchat-core": "^0.0.0-0", + "classnames": "2.2.6", + "create-emotion": "10.0.27", + "event-target-shim": "5.0.1", + "event-target-shim-es5": "1.2.0", + "globalize": "1.5.0", + "markdown-it": "11.0.0", + "prop-types": "15.7.2", + "react-dictate-button": "1.2.3-master.6b4fe72", + "react-film": "3.0.0", + "react-redux": "7.2.0", + "react-say": "2.0.2-master.ee7cd76", + "react-scroll-to-bottom": "4.0.0", + "redux": "4.0.5", + "remark": "10.0.1", + "sanitize-html": "1.27.4", + "strip-markdown": "3.0.4" + }, + "peerDependencies": { + "react": "^16.8.6", + "react-dom": "^16.8.6" + } +} diff --git a/packages/component/scripts/createPrecompiledGlobalize.js b/packages/api/scripts/createPrecompiledGlobalize.js similarity index 81% rename from packages/component/scripts/createPrecompiledGlobalize.js rename to packages/api/scripts/createPrecompiledGlobalize.js index e1d18b0910..6a6bbc645a 100644 --- a/packages/component/scripts/createPrecompiledGlobalize.js +++ b/packages/api/scripts/createPrecompiledGlobalize.js @@ -1,9 +1,9 @@ const { format } = require('prettier'); -const { join, relative } = require('path'); -const { writeFileSync } = require('fs'); +const { dirname, join, relative } = require('path'); +const { existsSync, mkdirSync, writeFileSync } = require('fs'); const Globalize = require('globalize'); const globalizeCompiler = require('globalize-compiler'); -const languages = Object.values(require('../src/Localization/overrides.json')).map( +const languages = Object.values(require('../src/localization/overrides.json')).map( ({ GLOBALIZE_LANGUAGE }) => GLOBALIZE_LANGUAGE ); @@ -30,11 +30,12 @@ const formattersAndParsers = languages.reduce((formattersAndParsers, language) = }, []); const code = format(globalizeCompiler.compile(formattersAndParsers), { parser: 'babel' }); -const filename = join(__dirname, '../lib/Utils/PrecompiledGlobalize.js'); +const filename = join(__dirname, '../lib/external/PrecompiledGlobalize.js'); // globalize-compiler is emitting AMD code, pointing to "globalize-runtime" instead of "globalize/dist/globalize-runtime" const patchedCode = code.replace(/\"globalize-runtime\//g, '"globalize/dist/globalize-runtime/'); +existsSync(dirname(filename)) || mkdirSync(dirname(filename)); writeFileSync(filename, patchedCode); console.log(`Successfully compiled globalize to ${relative(process.cwd(), filename)}.`); diff --git a/packages/api/src/defaultStyleOptions.js b/packages/api/src/defaultStyleOptions.js new file mode 100644 index 0000000000..df315fad03 --- /dev/null +++ b/packages/api/src/defaultStyleOptions.js @@ -0,0 +1,202 @@ +/* eslint no-magic-numbers: "off" */ + +function fontFamily(fonts) { + return fonts.map(font => `'${font}'`).join(', '); +} + +const DEFAULT_ACCENT = '#0063B1'; +const DEFAULT_SUBTLE = '#767676'; // With contrast 4.5:1 to white +const PADDING_REGULAR = 10; + +const DEFAULT_OPTIONS = { + // Color and paddings + accent: DEFAULT_ACCENT, + backgroundColor: 'White', + cardEmphasisBackgroundColor: '#F0F0F0', + paddingRegular: PADDING_REGULAR, + paddingWide: PADDING_REGULAR * 2, + subtle: DEFAULT_SUBTLE, + + // Word break + messageActivityWordBreak: 'break-word', // 'normal' || 'break-all' || 'break-word' || 'keep-all' + + // Fonts + fontSizeSmall: '80%', + monospaceFont: fontFamily(['Consolas', 'Courier New', 'monospace']), + primaryFont: fontFamily(['Calibri', 'Helvetica Neue', 'Arial', 'sans-serif']), + + // Avatar + avatarBorderRadius: '50%', + avatarSize: 40, + botAvatarBackgroundColor: undefined, // defaults to accent color + botAvatarImage: undefined, // Or a string of URL. Can be a data URI or blob. + botAvatarInitials: undefined, // Or a string. Empty strings means it has avatar but not initials inside. + userAvatarBackgroundColor: undefined, // defaults to accent color + userAvatarImage: undefined, // Or a string of URL. Can be a data URI or blob. + userAvatarInitials: undefined, // Or a string. Empty strings means it has avatar but not initials inside. + showAvatarInGroup: 'status', // Or 'sender' or true (on every activity). + + // Bubble + // TODO: Should we make a bubbleFromBot* + bubbleBackground: 'White', + bubbleBorderColor: '#E6E6E6', + bubbleBorderRadius: 2, + bubbleBorderStyle: 'solid', + bubbleBorderWidth: 1, + bubbleFromUserBackground: 'White', + bubbleFromUserBorderColor: '#E6E6E6', + bubbleFromUserBorderRadius: 2, + bubbleFromUserBorderStyle: 'solid', + bubbleFromUserBorderWidth: 1, + bubbleFromUserNubOffset: 0, // Either a positive/negative number, or "bottom" + bubbleFromUserNubSize: undefined, // Or a number. 0 means a sharp corner. + bubbleFromUserTextColor: 'Black', + bubbleImageHeight: 240, + bubbleMaxWidth: 480, // screen width = 600px + bubbleMinHeight: 40, + bubbleMinWidth: 250, // min screen width = 300px, Edge requires 372px (https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/13621468/) + bubbleNubOffset: 0, // Either a positive/negative number, or "bottom" + bubbleNubSize: undefined, // Or a number. 0 means a sharp corner. + bubbleTextColor: 'Black', + + // Markdown + markdownRespectCRLF: true, + + // Rich Cards + richCardWrapTitle: false, // Applies to subtitles as well + + // Root + rootHeight: '100%', + rootWidth: '100%', + rootZIndex: 0, // "z-index" for the root container of Web Chat. This will form a new stacking context so "z-index" used in children won't pollute. + + // Scroll to end button + hideScrollToEndButton: false, + + // Send box + hideSendBox: false, + hideUploadButton: false, + microphoneButtonColorOnDictate: '#F33', + sendBoxBackground: 'White', + sendBoxButtonColor: undefined, // defaults to subtle + sendBoxButtonColorOnDisabled: '#CCC', + sendBoxButtonColorOnFocus: '#333', + sendBoxButtonColorOnHover: '#333', + sendBoxDisabledTextColor: undefined, // defaults to subtle + sendBoxHeight: 40, + sendBoxMaxHeight: 200, + sendBoxTextColor: 'Black', + // TODO: We should deprecate this because there isn't an easy way to make the width of the send box narrower than the transcript + sendBoxBorderBottom: '', + sendBoxBorderLeft: '', + sendBoxBorderRight: '', + sendBoxBorderTop: 'solid 1px #E6E6E6', + sendBoxPlaceholderColor: undefined, // defaults to subtle + sendBoxTextWrap: false, + + // Visually show spoken text + showSpokenText: false, + + // Suggested actions + suggestedActionBackground: 'White', + suggestedActionBorder: undefined, // split into 3, null + suggestedActionBorderColor: undefined, // defaults to accent + suggestedActionBorderRadius: 0, + suggestedActionBorderStyle: 'solid', + suggestedActionBorderWidth: 2, + suggestedActionDisabledBackground: undefined, // defaults to suggestedActionBackground + suggestedActionDisabledBorder: null, + suggestedActionDisabledBorderColor: '#E6E6E6', + suggestedActionDisabledBorderStyle: 'solid', + suggestedActionDisabledBorderWidth: 2, + suggestedActionDisabledTextColor: undefined, // defaults to subtle + suggestedActionHeight: 40, + suggestedActionImageHeight: 20, + suggestedActionLayout: 'carousel', // either 'carousel' or 'stacked' + suggestedActionTextColor: null, + + // Suggested actions carousel layout + suggestedActionsCarouselFlipperCursor: null, // Cursor when mouse over on flipper + suggestedActionsCarouselFlipperBoxWidth: 40, // Flipper bounding box size + suggestedActionsCarouselFlipperSize: 20, // Flipper visible size + + // Suggested actions stacked layout + suggestedActionsStackedHeight: undefined, // sets the container's max height. defaults to 'auto' + suggestedActionsStackedOverflow: undefined, // defaults to 'auto', + + // Timestamp + groupTimestamp: true, + sendTimeout: 20000, + sendTimeoutForAttachments: 120000, + timestampColor: undefined, // defaults to subtle + timestampFormat: 'relative', // 'absolute' + + // Transcript overlay buttons (e.g. carousel and suggested action flippers, scroll to bottom, etc.) + newMessagesButtonFontSize: '85%', + transcriptOverlayButtonBackground: 'rgba(0, 0, 0, .6)', + transcriptOverlayButtonBackgroundOnFocus: 'rgba(0, 0, 0, .8)', + transcriptOverlayButtonBackgroundOnHover: 'rgba(0, 0, 0, .8)', + transcriptOverlayButtonColor: 'White', + transcriptOverlayButtonColorOnFocus: undefined, // defaults to transcriptOverlayButtonColor + transcriptOverlayButtonColorOnHover: undefined, // defaults to transcriptOverlayButtonColor + + // Video + videoHeight: 270, // based on bubbleMaxWidth: 480 / 16 * 9 = 270 + + // Connectivity UI + connectivityIconPadding: PADDING_REGULAR * 1.2, + connectivityMarginLeftRight: PADDING_REGULAR * 1.4, + connectivityMarginTopBottom: PADDING_REGULAR * 0.8, + connectivityTextSize: '75%', + failedConnectivity: '#C50F1F', + slowConnectivity: '#EAA300', + notificationText: '#5E5E5E', + slowConnectionAfter: 15000, + + typingAnimationBackgroundImage: null, + typingAnimationDuration: 5000, + typingAnimationHeight: 20, + typingAnimationWidth: 64, + + spinnerAnimationBackgroundImage: null, + spinnerAnimationHeight: 16, + spinnerAnimationWidth: 16, + spinnerAnimationPadding: 12, + + enableUploadThumbnail: true, + uploadThumbnailContentType: 'image/jpeg', + uploadThumbnailHeight: 360, + uploadThumbnailQuality: 0.6, + uploadThumbnailWidth: 720, + + // deprecated; will be removed on or after 2021-02-01 + spinnerAnimationPaddingRight: undefined, + + // Toast UI + + // New debounce timeout value only affects new notifications. + notificationDebounceTimeout: 400, + + hideToaster: false, + toasterHeight: 32, + toasterMaxHeight: 32 * 5, + toasterSingularMaxHeight: 50, + toastFontSize: '87.5%', + toastIconWidth: 36, + toastSeparatorColor: '#E8EAEC', + toastTextPadding: 6, + + toastErrorBackgroundColor: '#FDE7E9', + toastErrorColor: '#A80000', + toastInfoBackgroundColor: '#CEF1FF', + toastInfoColor: '#105E7D', + toastSuccessBackgroundColor: '#DFF6DD', + toastSuccessColor: '#107C10', + toastWarnBackgroundColor: '#FFF4CE', + toastWarnColor: '#3B3A39', + + // Emoji + emojiSet: true // true || false || { ':)' : '😊'} +}; + +export default DEFAULT_OPTIONS; diff --git a/packages/api/src/hooks/Composer.js b/packages/api/src/hooks/Composer.js new file mode 100644 index 0000000000..24cbe639cd --- /dev/null +++ b/packages/api/src/hooks/Composer.js @@ -0,0 +1,709 @@ +import { Composer as SayComposer } from 'react-say'; + +import { Provider } from 'react-redux'; +import PropTypes from 'prop-types'; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import updateIn from 'simple-update-in'; + +// import createActivityRenderer from './Middleware/createActivityRenderer'; +// import createActivityStatusRenderer from './Middleware/createActivityStatusRenderer'; +// import createAttachmentRenderer from './Middleware/createAttachmentRenderer'; +// import createAvatarRenderer from './Middleware/createAvatarRenderer'; +import createCustomEvent from '../utils/createCustomEvent'; +// import createToastRenderer from './Middleware/createToastRenderer'; +// import createTypingIndicatorRenderer from './Middleware/createTypingIndicatorRenderer'; +import ErrorBoundary from './utils/ErrorBoundary'; +import getAllLocalizedStrings from '../localization/getAllLocalizedStrings'; +import isObject from '../utils/isObject'; +import normalizeLanguage from '../utils/normalizeLanguage'; +import PrecompiledGlobalize from '../external/PrecompiledGlobalize'; +import useReferenceGrammarID from './useReferenceGrammarID'; + +import { + clearSuggestedActions, + connect as createConnectAction, + createStore, + disconnect, + dismissNotification, + emitTypingIndicator, + markActivity, + postActivity, + sendEvent, + sendFiles, + sendMessage, + sendMessageBack, + sendPostBack, + setDictateInterims, + setDictateState, + setLanguage, + setNotification, + setSendBox, + setSendTimeout, + setSendTypingIndicator, + startDictate, + startSpeakingActivity, + stopDictate, + stopSpeakingActivity, + submitSendBox +} from 'botframework-webchat-core'; + +// import concatMiddleware from './Middleware/concatMiddleware'; +// import createCoreCardActionMiddleware from './Middleware/CardAction/createCoreMiddleware'; +// import createDefaultGroupActivitiesMiddleware from './Middleware/GroupActivities/createCoreMiddleware'; +import createDefaultGroupActivitiesMiddleware from './middleware/createDefaultGroupActivitiesMiddleware'; +import defaultSelectVoice from './internal/defaultSelectVoice'; +import Dictation from './internal/Dictation'; +import mapMap from '../utils/mapMap'; +// import observableToPromise from './utils/observableToPromise'; +import Tracker from './internal/Tracker'; +import WebChatReduxContext, { useDispatch } from './internal/WebChatReduxContext'; +import WebChatAPIContext from './internal/WebChatAPIContext'; + +import { + speechSynthesis as bypassSpeechSynthesis, + SpeechSynthesisUtterance as BypassSpeechSynthesisUtterance +} from './internal/BypassSpeechSynthesisPonyfill'; +import applyMiddleware, { forRenderer as applyMiddlewareForRenderer } from './middleware/applyMiddleware'; +import patchStyleOptions from '../patchStyleOptions'; +import singleToArray from './utils/singleToArray'; + +// List of Redux actions factory we are hoisting as Web Chat functions +const DISPATCHERS = { + clearSuggestedActions, + dismissNotification, + emitTypingIndicator, + markActivity, + postActivity, + sendEvent, + sendFiles, + sendMessage, + sendMessageBack, + sendPostBack, + setDictateInterims, + setDictateState, + setNotification, + setSendBox, + setSendTimeout, + startDictate, + startSpeakingActivity, + stopDictate, + stopSpeakingActivity, + submitSendBox +}; + +// TODO: Fix this +function createCardActionContext({ cardActionMiddleware, directLine, dispatch }) { + return { + onCardAction: () => { + throw new Error('Implement onCardAction'); + } + }; + + // const runMiddleware = concatMiddleware(cardActionMiddleware, createCoreCardActionMiddleware())({ dispatch }); + + // return { + // onCardAction: (cardAction, { target } = {}) => + // runMiddleware(({ cardAction: { type } }) => { + // throw new Error(`Web Chat: received unknown card action "${type}"`); + // })({ + // cardAction, + // getSignInUrl: + // cardAction.type === 'signin' + // ? () => { + // const { value } = cardAction; + + // if (directLine.getSessionId) { + // // TODO: [P3] We should change this one to async/await. + // // This is the first place in this project to use async. + // // Thus, we need to add @babel/plugin-transform-runtime and @babel/runtime. + + // return observableToPromise(directLine.getSessionId()).then( + // sessionId => `${value}${encodeURIComponent(`&code_challenge=${sessionId}`)}` + // ); + // } + + // console.warn('botframework-webchat: OAuth is not supported on this Direct Line adapter.'); + + // return value; + // } + // : null, + // target + // }) + // }; +} + +function createFocusContext({ sendBoxFocusRef, transcriptFocusRef }) { + return { + focus: where => { + const ref = where === 'sendBox' || where === 'sendBoxWithoutKeyboard' ? sendBoxFocusRef : transcriptFocusRef; + const { current } = ref || {}; + + if (current) { + if (where === 'sendBoxWithoutKeyboard') { + // To not activate the virtual keyboard while changing focus to an input, we will temporarily set it as read-only and flip it back. + // https://stackoverflow.com/questions/7610758/prevent-iphone-default-keyboard-when-focusing-an-input/7610923 + const readOnly = current.getAttribute('readonly'); + + current.setAttribute('readonly', 'readonly'); + + setTimeout(() => { + current.focus(); + readOnly ? current.setAttribute('readonly', readOnly) : current.removeAttribute('readonly'); + }, 0); + } else { + current.focus(); + } + } + } + }; +} + +function createGroupActivitiesContext({ groupActivitiesMiddleware, groupTimestamp }) { + const runMiddleware = applyMiddleware( + 'group activities', + groupActivitiesMiddleware, + createDefaultGroupActivitiesMiddleware({ groupTimestamp }) + ); + + return { + groupActivities: runMiddleware({}) + }; +} + +function mergeStringsOverrides(localizedStrings, language, overrideLocalizedStrings) { + if (!overrideLocalizedStrings) { + return localizedStrings; + } else if (typeof overrideLocalizedStrings === 'function') { + const merged = overrideLocalizedStrings(localizedStrings, language); + + if (!isObject(merged)) { + throw new Error('botframework-webchat: overrideLocalizedStrings function must return an object.'); + } + + return merged; + } + + if (!isObject(overrideLocalizedStrings)) { + throw new Error('botframework-webchat: overrideLocalizedStrings must be either a function, an object, or falsy.'); + } + + return { ...localizedStrings, ...overrideLocalizedStrings }; +} + +const Composer = ({ + activityMiddleware, + activityRenderer, + activityStatusMiddleware, + activityStatusRenderer, + attachmentMiddleware, + attachmentRenderer, + avatarMiddleware, + avatarRenderer, + cardActionMiddleware, + children, + dir, + directLine, + disabled, + grammars, + groupActivitiesMiddleware, + groupTimestamp, + internalErrorBoxClass, + locale, + onTelemetry, + overrideLocalizedStrings, + renderMarkdown, + selectVoice, + sendTimeout, + sendTypingIndicator, + styleOptions, + toastMiddleware, + toastRenderer, + typingIndicatorMiddleware, + typingIndicatorRenderer, + userID, + username, + webSpeechPonyfillFactory +}) => { + const [dictateAbortable, setDictateAbortable] = useState(); + const [referenceGrammarID] = useReferenceGrammarID(); + const dispatch = useDispatch(); + const sendBoxFocusRef = useRef(); + const telemetryDimensionsRef = useRef({}); + const transcriptFocusRef = useRef(); + + const patchedDir = useMemo(() => (dir === 'ltr' || dir === 'rtl' ? dir : 'auto'), [dir]); + const patchedGrammars = useMemo(() => grammars || [], [grammars]); + + const patchedStyleOptions = useMemo(() => patchStyleOptions(styleOptions, { groupTimestamp, sendTimeout }), [ + groupTimestamp, + sendTimeout, + styleOptions + ]); + + useEffect(() => { + dispatch(setLanguage(locale)); + }, [dispatch, locale]); + + useEffect(() => { + typeof sendTimeout === 'number' && dispatch(setSendTimeout(sendTimeout)); + }, [dispatch, sendTimeout]); + + useEffect(() => { + dispatch(setSendTypingIndicator(!!sendTypingIndicator)); + }, [dispatch, sendTypingIndicator]); + + useEffect(() => { + dispatch( + createConnectAction({ + directLine, + userID, + username + }) + ); + + return () => { + // TODO: [P3] disconnect() is an async call (pending -> fulfilled), we need to wait, or change it to reconnect() + dispatch(disconnect()); + }; + }, [dispatch, directLine, userID, username]); + + const cardActionContext = useMemo(() => createCardActionContext({ cardActionMiddleware, directLine, dispatch }), [ + cardActionMiddleware, + directLine, + dispatch + ]); + + const patchedSelectVoice = useMemo(() => selectVoice || defaultSelectVoice.bind(null, { language: locale }), [ + locale, + selectVoice + ]); + + const focusContext = useMemo(() => createFocusContext({ sendBoxFocusRef, transcriptFocusRef }), [ + sendBoxFocusRef, + transcriptFocusRef + ]); + + const groupActivitiesContext = useMemo( + () => + createGroupActivitiesContext({ + groupActivitiesMiddleware, + groupTimestamp: patchedStyleOptions.groupTimestamp + }), + [groupActivitiesMiddleware, patchedStyleOptions.groupTimestamp] + ); + + const hoistedDispatchers = useMemo( + () => mapMap(DISPATCHERS, dispatcher => (...args) => dispatch(dispatcher(...args))), + [dispatch] + ); + + const webSpeechPonyfill = useMemo(() => { + const ponyfill = webSpeechPonyfillFactory && webSpeechPonyfillFactory({ referenceGrammarID }); + const { speechSynthesis, SpeechSynthesisUtterance } = ponyfill || {}; + + return { + ...ponyfill, + speechSynthesis: speechSynthesis || bypassSpeechSynthesis, + SpeechSynthesisUtterance: SpeechSynthesisUtterance || BypassSpeechSynthesisUtterance + }; + }, [referenceGrammarID, webSpeechPonyfillFactory]); + + const dictationOnError = useCallback(err => { + console.error(err); + }, []); + + const patchedLocalizedStrings = useMemo( + () => mergeStringsOverrides(getAllLocalizedStrings()[normalizeLanguage(locale)], locale, overrideLocalizedStrings), + [locale, overrideLocalizedStrings] + ); + + const localizedGlobalize = useMemo(() => { + const { GLOBALIZE, GLOBALIZE_LANGUAGE } = patchedLocalizedStrings || {}; + + return GLOBALIZE || (GLOBALIZE_LANGUAGE && PrecompiledGlobalize(GLOBALIZE_LANGUAGE)) || PrecompiledGlobalize('en'); + }, [patchedLocalizedStrings]); + + const trackDimension = useCallback( + (name, data) => { + if (!name || typeof name !== 'string') { + return console.warn('botframework-webchat: Telemetry dimension name must be a string.'); + } + + const type = typeof data; + + if (type !== 'string' && type !== 'undefined') { + return console.warn('botframework-webchat: Telemetry dimension data must be a string or undefined.'); + } + + telemetryDimensionsRef.current = updateIn( + telemetryDimensionsRef.current, + [name], + type === 'undefined' ? data : () => data + ); + }, + [telemetryDimensionsRef] + ); + + const patchedActivityRenderer = useMemo(() => { + activityRenderer && + console.warn( + 'Web Chat: "activityRenderer" is deprecated and will be removed on 2022-06-15, please use "activityMiddleware" instead.' + ); + + // console.log({ activityMiddleware, activityRenderer }); + + return activityRenderer || applyMiddlewareForRenderer('activity', ...singleToArray(activityMiddleware))({}); + }, [activityMiddleware, activityRenderer]); + + // const patchedActivityRenderer = useMemo(() => { + // activityRenderer && + // console.warn( + // 'Web Chat: "activityRenderer" is deprecated and will be removed on 2022-06-15, please use "activityMiddleware" instead.' + // ); + + // return activityRenderer || createActivityRenderer(activityMiddleware); + // }, [activityMiddleware, activityRenderer]); + + const patchedActivityStatusRenderer = useMemo(() => { + activityStatusRenderer && + console.warn( + 'Web Chat: "activityStatusRenderer" is deprecated and will be removed on 2022-06-15, please use "activityStatusMiddleware" instead.' + ); + + return ( + activityStatusRenderer || + applyMiddlewareForRenderer( + 'activity status', + ...singleToArray(activityStatusMiddleware), + () => () => () => false + )({}) + ); + }, [activityStatusMiddleware, activityStatusRenderer]); + + // const patchedActivityStatusRenderer = useMemo(() => { + // activityStatusRenderer && + // console.warn( + // 'Web Chat: "activityStatusRenderer" is deprecated and will be removed on 2022-06-15, please use "activityStatusMiddleware" instead.' + // ); + + // return activityStatusRenderer || createActivityStatusRenderer(activityStatusMiddleware); + // }, [activityStatusMiddleware, activityStatusRenderer]); + + const patchedAttachmentRenderer = useMemo(() => { + if (attachmentRenderer) { + console.warn( + 'Web Chat: "attachmentRenderer" is deprecated and will be removed on 2022-06-15, please use "attachmentMiddleware" instead.' + ); + + return attachmentRenderer; + } + + return applyMiddlewareForRenderer( + 'attachment', + // TODO: [P2] Currently, attachmentMiddleware is on legacy middleware interface. + // For uniformity, we are patching the legacy interface into the current one. + ...singleToArray(attachmentMiddleware), + () => () => ({ attachment }) => () => { + if (attachment) { + throw new Error(`No renderer for attachment of type "${attachment.contentType}"`); + } else { + throw new Error('No attachment to render'); + } + } + )({}); + }, [attachmentMiddleware, attachmentRenderer]); + + // const patchedAttachmentRenderer = useMemo(() => { + // attachmentRenderer && + // console.warn( + // 'Web Chat: "attachmentRenderer" is deprecated and will be removed on 2022-06-15, please use "attachmentMiddleware" instead.' + // ); + + // return attachmentRenderer || createAttachmentRenderer(attachmentMiddleware); + // }, [attachmentMiddleware, attachmentRenderer]); + + const patchedAvatarRenderer = useMemo(() => { + avatarRenderer && + console.warn( + 'Web Chat: "avatarRenderer" is deprecated and will be removed on 2022-06-15, please use "avatarMiddleware" instead.' + ); + + return ( + avatarRenderer || + applyMiddlewareForRenderer('avatar', ...singleToArray(avatarMiddleware), () => () => () => false)({}) + ); + }, [avatarMiddleware, avatarRenderer]); + + // const patchedAvatarRenderer = useMemo(() => { + // avatarRenderer && + // console.warn( + // 'Web Chat: "avatarRenderer" is deprecated and will be removed on 2022-06-15, please use "avatarMiddleware" instead.' + // ); + + // return avatarRenderer || createAvatarRenderer(avatarMiddleware); + // }, [avatarMiddleware, avatarRenderer]); + + const patchedToastRenderer = useMemo(() => { + toastRenderer && + console.warn( + 'Web Chat: "toastRenderer" is deprecated and will be removed on 2022-06-15, please use "toastMiddleware" instead.' + ); + + return ( + toastRenderer || + applyMiddlewareForRenderer('toast', ...singleToArray(toastRenderer), () => () => ({ notification }) => { + if (notification) { + throw new Error(`No renderer for notification of type "${notification.contentType}"`); + } else { + throw new Error('No notification to render'); + } + })({}) + ); + }, [toastMiddleware, toastRenderer]); + + // const patchedToastRenderer = useMemo(() => { + // toastRenderer && + // console.warn( + // 'Web Chat: "toastRenderer" is deprecated and will be removed on 2022-06-15, please use "toastMiddleware" instead.' + // ); + + // return toastRenderer || createToastRenderer(toastMiddleware); + // }, [toastMiddleware, toastRenderer]); + + const patchedTypingIndicatorRenderer = useMemo(() => { + typingIndicatorRenderer && + console.warn( + 'Web Chat: "typingIndicatorRenderer" is deprecated and will be removed on 2022-06-15, please use "typingIndicatorMiddleware" instead.' + ); + + return ( + typingIndicatorRenderer || + applyMiddlewareForRenderer('typing indicator', ...singleToArray(typingIndicatorMiddleware))({}) + ); + }, [typingIndicatorMiddleware, typingIndicatorRenderer]); + + // const patchedTypingIndicatorRenderer = useMemo(() => { + // typingIndicatorRenderer && + // console.warn( + // 'Web Chat: "typingIndicatorRenderer" is deprecated and will be removed on 2022-06-15, please use "typingIndicatorMiddleware" instead.' + // ); + + // return typingIndicatorRenderer || createTypingIndicatorRenderer(typingIndicatorMiddleware); + // }, [typingIndicatorMiddleware, typingIndicatorRenderer]); + + // This is a heavy function, and it is expected to be only called when there is a need to recreate business logic, e.g. + // - User ID changed, causing all send* functions to be updated + // - send + + // TODO: [P3] We should think about if we allow the user to change onSendBoxValueChanged/sendBoxValue, e.g. + // 1. Turns text into UPPERCASE + // 2. Filter out profanity + + // TODO: [P4] Revisit all members of context + // This context should consist of members that are not in the Redux store + // i.e. members that are not interested in other types of UIs + const context = useMemo( + () => ({ + ...cardActionContext, + ...focusContext, + ...groupActivitiesContext, + ...hoistedDispatchers, + activityRenderer: patchedActivityRenderer, + activityStatusRenderer: patchedActivityStatusRenderer, + attachmentRenderer: patchedAttachmentRenderer, + avatarRenderer: patchedAvatarRenderer, + dictateAbortable, + dir: patchedDir, + directLine, + disabled, + grammars: patchedGrammars, + internalErrorBoxClass, + language: locale, + localizedGlobalizeState: [localizedGlobalize], + localizedStrings: patchedLocalizedStrings, + onTelemetry, + renderMarkdown, + selectVoice: patchedSelectVoice, + sendBoxFocusRef, + sendTypingIndicator, + setDictateAbortable, + styleOptions: patchedStyleOptions, + telemetryDimensionsRef, + toastRenderer: patchedToastRenderer, + trackDimension, + transcriptFocusRef, + typingIndicatorRenderer: patchedTypingIndicatorRenderer, + userID, + username, + webSpeechPonyfill + }), + [ + cardActionContext, + dictateAbortable, + directLine, + disabled, + focusContext, + groupActivitiesContext, + hoistedDispatchers, + internalErrorBoxClass, + locale, + localizedGlobalize, + onTelemetry, + renderMarkdown, + patchedActivityRenderer, + patchedActivityStatusRenderer, + patchedAttachmentRenderer, + patchedAvatarRenderer, + patchedDir, + patchedGrammars, + patchedLocalizedStrings, + patchedSelectVoice, + patchedStyleOptions, + patchedToastRenderer, + patchedTypingIndicatorRenderer, + sendBoxFocusRef, + sendTypingIndicator, + setDictateAbortable, + telemetryDimensionsRef, + trackDimension, + transcriptFocusRef, + userID, + username, + webSpeechPonyfill + ] + ); + + // TODO: Check if react-say support RN or not + + return ( + + + {typeof children === 'function' ? children(context) : children} + + + {onTelemetry && } + + ); +}; + +// We will create a Redux store if it was not passed in +const ComposeWithStore = ({ internalRenderErrorBox, onTelemetry, store, ...props }) => { + const [error, setError] = useState(); + + const handleError = useCallback( + error => { + console.error('botframework-webchat: Uncaught exception', { error }); + + onTelemetry && onTelemetry(createCustomEvent('exception', { error, fatal: true })); + setError(error); + }, + [onTelemetry, setError] + ); + + const memoizedStore = useMemo(() => store || createStore(), [store]); + + return error ? ( + !!internalRenderErrorBox && internalRenderErrorBox({ error, type: 'uncaught exception' }) + ) : ( + + + + + + ); +}; + +ComposeWithStore.defaultProps = { + onTelemetry: undefined, + store: undefined +}; + +ComposeWithStore.propTypes = { + onTelemetry: PropTypes.func, + store: PropTypes.any +}; + +export default ComposeWithStore; + +// TODO: [P3] We should consider moving some data from Redux store to props +// Although we use `connectToWebChat` to hide the details of accessor of Redux store, +// we should clean up the responsibility between Context and Redux store +// We should decide which data is needed for React but not in other environment such as CLI/VSCode + +Composer.defaultProps = { + activityMiddleware: undefined, + activityRenderer: undefined, + activityStatusMiddleware: undefined, + activityStatusRenderer: undefined, + attachmentMiddleware: undefined, + attachmentRenderer: undefined, + avatarMiddleware: undefined, + avatarRenderer: undefined, + cardActionMiddleware: undefined, + children: undefined, + dir: 'auto', + disabled: false, + grammars: [], + groupActivitiesMiddleware: undefined, + groupTimestamp: undefined, + locale: window.navigator.language || 'en-US', + onTelemetry: undefined, + overrideLocalizedStrings: undefined, + selectVoice: undefined, + sendTimeout: undefined, + sendTypingIndicator: false, + styleOptions: {}, + toastMiddleware: undefined, + toastRenderer: undefined, + typingIndicatorMiddleware: undefined, + typingIndicatorRenderer: undefined, + userID: '', + username: '', + webSpeechPonyfillFactory: undefined +}; + +Composer.propTypes = { + activityMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), + activityRenderer: PropTypes.func, + activityStatusMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), + activityStatusRenderer: PropTypes.func, + attachmentMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), + attachmentRenderer: PropTypes.func, + avatarMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), + avatarRenderer: PropTypes.func, + cardActionMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), + children: PropTypes.any, + dir: PropTypes.oneOf(['auto', 'ltr', 'rtl']), + directLine: PropTypes.shape({ + activity$: PropTypes.shape({ + subscribe: PropTypes.func.isRequired + }).isRequired, + connectionStatus$: PropTypes.shape({ + subscribe: PropTypes.func.isRequired + }).isRequired, + end: PropTypes.func, + getSessionId: PropTypes.func, + postActivity: PropTypes.func.isRequired, + referenceGrammarID: PropTypes.string, + token: PropTypes.string + }).isRequired, + disabled: PropTypes.bool, + internalErrorBoxClass: PropTypes.func, // This is for internal use only. We don't allow customization of error box. + grammars: PropTypes.arrayOf(PropTypes.string), + groupActivitiesMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), + groupTimestamp: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]), + locale: PropTypes.string, + onTelemetry: PropTypes.func, + overrideLocalizedStrings: PropTypes.oneOfType([PropTypes.any, PropTypes.func]), + selectVoice: PropTypes.func, + sendTimeout: PropTypes.number, + sendTypingIndicator: PropTypes.bool, + styleOptions: PropTypes.any, + toastMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), + toastRenderer: PropTypes.func, + typingIndicatorMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), + typingIndicatorRenderer: PropTypes.func, + userID: PropTypes.string, + username: PropTypes.string, + webSpeechPonyfillFactory: PropTypes.func +}; diff --git a/packages/api/src/hooks/Composer.oldjs b/packages/api/src/hooks/Composer.oldjs new file mode 100644 index 0000000000..f5ac3f4aab --- /dev/null +++ b/packages/api/src/hooks/Composer.oldjs @@ -0,0 +1,29 @@ +import { Provider } from 'react-redux'; +import PropTypes from 'prop-types'; +import React from 'react'; + +import WebChatReduxContext, { useDispatch } from './internal/WebChatReduxContext'; +import WebChatAPIContext from './internal/WebChatAPIContext'; + +const Composer = ({ children, store }) => { + const dispatch = useDispatch(); + const memoizedStore = useMemo(() => store || createStore(), [store]); + + return ( + + + {children} + + + ); +}; + +Composer.defaultProps = { + children: undefined +}; + +Composer.propTypes = { + children: PropTypes.any +}; + +export default Composer; diff --git a/packages/component/src/hooks/index.js b/packages/api/src/hooks/index.js similarity index 83% rename from packages/component/src/hooks/index.js rename to packages/api/src/hooks/index.js index 5b22d03271..321f725614 100644 --- a/packages/component/src/hooks/index.js +++ b/packages/api/src/hooks/index.js @@ -10,6 +10,7 @@ import useCreateAttachmentForScreenReaderRenderer from './useCreateAttachmentFor import useCreateAvatarRenderer from './useCreateAvatarRenderer'; import useDateFormatter from './useDateFormatter'; import useDebouncedNotifications from './useDebouncedNotifications'; +import useDictateAbortable from './useDictateAbortable'; import useDictateInterims from './useDictateInterims'; import useDictateState from './useDictateState'; import useDirection from './useDirection'; @@ -20,6 +21,7 @@ import useFocus from './useFocus'; import useFocusSendBox from './useFocusSendBox'; import useGetSendTimeoutForActivity from './useGetSendTimeoutForActivity'; import useGrammars from './useGrammars'; +import useGroupActivities from './useGroupActivities'; import useGroupTimestamp from './useGroupTimestamp'; import useLanguage from './useLanguage'; import useLastTypingAt from './useLastTypingAt'; @@ -27,7 +29,7 @@ import useLocalize from './useLocalize'; // Deprecated on or after 2022-02-12 import useLocalizeDate from './useLocalizeDate'; // Deprecated on or after 2022-02-12 import useLocalizer from './useLocalizer'; import useMarkActivityAsSpoken from './useMarkActivityAsSpoken'; -import useObserveScrollPosition from './useObserveScrollPosition'; +// import useObserveScrollPosition from './useObserveScrollPosition'; import usePerformCardAction from './usePerformCardAction'; import usePostActivity from './usePostActivity'; import useReferenceGrammarID from './useReferenceGrammarID'; @@ -39,8 +41,8 @@ import useRenderAvatar from './useRenderAvatar'; import useRenderMarkdownAsHTML from './useRenderMarkdownAsHTML'; import useRenderToast from './useRenderToast'; import useRenderTypingIndicator from './useRenderTypingIndicator'; -import useScrollTo from './useScrollTo'; -import useScrollToEnd from './useScrollToEnd'; +// import useScrollTo from './useScrollTo'; +// import useScrollToEnd from './useScrollToEnd'; import useSendBoxValue from './useSendBoxValue'; import useSendEvent from './useSendEvent'; import useSendFiles from './useSendFiles'; @@ -54,7 +56,8 @@ import useShouldSpeakIncomingActivity from './useShouldSpeakIncomingActivity'; import useStartDictate from './useStartDictate'; import useStopDictate from './useStopDictate'; import useStyleOptions from './useStyleOptions'; -import useStyleSet from './useStyleSet'; +// TODO: Move useStyleSet to component (DOM only) +// import useStyleSet from './useStyleSet'; import useSubmitSendBox from './useSubmitSendBox'; import useSuggestedActions from './useSuggestedActions'; import useTimeoutForSend from './useTimeoutForSend'; @@ -67,10 +70,10 @@ import useUsername from './useUsername'; import useVoiceSelector from './useVoiceSelector'; import useWebSpeechPonyfill from './useWebSpeechPonyfill'; -import { useMicrophoneButtonClick, useMicrophoneButtonDisabled } from '../SendBox/MicrophoneButton'; -import { useSendBoxSpeechInterimsVisible } from '../BasicSendBox'; -import { useTextBoxSubmit, useTextBoxValue } from '../SendBox/TextBox'; -import { useTypingIndicatorVisible } from '../BasicTypingIndicator'; +// import { useMicrophoneButtonClick, useMicrophoneButtonDisabled } from '../SendBox/MicrophoneButton'; +// import { useSendBoxSpeechInterimsVisible } from '../BasicSendBox'; +// import { useTextBoxSubmit, useTextBoxValue } from '../SendBox/TextBox'; +// import { useTypingIndicatorVisible } from '../BasicTypingIndicator'; export { useActiveTyping, @@ -85,6 +88,7 @@ export { useCreateAvatarRenderer, useDateFormatter, useDebouncedNotifications, + useDictateAbortable, useDictateInterims, useDictateState, useDirection, @@ -95,6 +99,7 @@ export { useFocusSendBox, useGetSendTimeoutForActivity, useGrammars, + useGroupActivities, useGroupTimestamp, useLanguage, useLastTypingAt, @@ -102,9 +107,9 @@ export { useLocalizeDate, useLocalizer, useMarkActivityAsSpoken, - useMicrophoneButtonClick, - useMicrophoneButtonDisabled, - useObserveScrollPosition, + // useMicrophoneButtonClick, + // useMicrophoneButtonDisabled, + // useObserveScrollPosition, usePerformCardAction, usePostActivity, useReferenceGrammarID, @@ -116,9 +121,9 @@ export { useRenderMarkdownAsHTML, useRenderToast, useRenderTypingIndicator, - useScrollTo, - useScrollToEnd, - useSendBoxSpeechInterimsVisible, + // useScrollTo, + // useScrollToEnd, + // useSendBoxSpeechInterimsVisible, useSendBoxValue, useSendEvent, useSendFiles, @@ -132,17 +137,17 @@ export { useStartDictate, useStopDictate, useStyleOptions, - useStyleSet, + // useStyleSet, useSubmitSendBox, useSuggestedActions, - useTextBoxSubmit, - useTextBoxValue, + // useTextBoxSubmit, + // useTextBoxValue, useTimeoutForSend, useTrackDimension, useTrackEvent, useTrackException, useTrackTiming, - useTypingIndicatorVisible, + // useTypingIndicatorVisible, useUserID, useUsername, useVoiceSelector, diff --git a/packages/component/src/Speech/BypassSpeechSynthesisPonyfill.js b/packages/api/src/hooks/internal/BypassSpeechSynthesisPonyfill.js similarity index 100% rename from packages/component/src/Speech/BypassSpeechSynthesisPonyfill.js rename to packages/api/src/hooks/internal/BypassSpeechSynthesisPonyfill.js diff --git a/packages/component/src/Dictation.js b/packages/api/src/hooks/internal/Dictation.js similarity index 78% rename from packages/component/src/Dictation.js rename to packages/api/src/hooks/internal/Dictation.js index 0c98889ede..046d860255 100644 --- a/packages/component/src/Dictation.js +++ b/packages/api/src/hooks/internal/Dictation.js @@ -1,22 +1,23 @@ import { Composer as DictateComposer } from 'react-dictate-button'; import { Constants } from 'botframework-webchat-core'; +// import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; import React, { useCallback, useMemo } from 'react'; -import useActivities from './hooks/useActivities'; -import useDictateInterims from './hooks/useDictateInterims'; -import useDictateState from './hooks/useDictateState'; -import useDisabled from './hooks/useDisabled'; -import useEmitTypingIndicator from './hooks/useEmitTypingIndicator'; -import useLanguage from './hooks/useLanguage'; -import useSendBoxValue from './hooks/useSendBoxValue'; -import useSendTypingIndicator from './hooks/useSendTypingIndicator'; -import useSetDictateState from './hooks/internal/useSetDictateState'; -import useSettableDictateAbortable from './hooks/internal/useSettableDictateAbortable'; -import useShouldSpeakIncomingActivity from './hooks/useShouldSpeakIncomingActivity'; -import useStopDictate from './hooks/useStopDictate'; -import useSubmitSendBox from './hooks/useSubmitSendBox'; -import useWebSpeechPonyfill from './hooks/useWebSpeechPonyfill'; +import useActivities from '../useActivities'; +import useDictateInterims from '../useDictateInterims'; +import useDictateState from '../useDictateState'; +import useDisabled from '../useDisabled'; +import useEmitTypingIndicator from '../useEmitTypingIndicator'; +import useLanguage from '../useLanguage'; +import useSendBoxValue from '../useSendBoxValue'; +import useSendTypingIndicator from '../useSendTypingIndicator'; +import useSetDictateState from './useSetDictateState'; +import useSettableDictateAbortable from './useSettableDictateAbortable'; +import useShouldSpeakIncomingActivity from '../useShouldSpeakIncomingActivity'; +import useStopDictate from '../useStopDictate'; +import useSubmitSendBox from '../useSubmitSendBox'; +import useWebSpeechPonyfill from '../useWebSpeechPonyfill'; const { DictateState: { DICTATING, IDLE, STARTING } diff --git a/packages/api/src/hooks/internal/ErrorBox.js b/packages/api/src/hooks/internal/ErrorBox.js new file mode 100644 index 0000000000..2b4c5d25a2 --- /dev/null +++ b/packages/api/src/hooks/internal/ErrorBox.js @@ -0,0 +1,30 @@ +import React, { useEffect } from 'react'; +import PropTypes from 'prop-types'; + +import useTrackException from '../useTrackException'; +import useErrorBoxClass from './useErrorBoxClass'; + +const ErrorBox = ({ error, type }) => { + const [errorBoxClass] = useErrorBoxClass(); + const trackException = useTrackException(); + + useEffect(() => { + trackException(error, false); + }, [error, trackException]); + + // console.log({ error, errorBoxClass, type }); + // console.trace(); + + return React.createElement(errorBoxClass, { error, type }); +}; + +ErrorBox.defaultProps = { + type: undefined +}; + +ErrorBox.propTypes = { + error: PropTypes.any.isRequired, + type: PropTypes.string +}; + +export default ErrorBox; diff --git a/packages/component/src/Tracker.js b/packages/api/src/hooks/internal/Tracker.js similarity index 61% rename from packages/component/src/Tracker.js rename to packages/api/src/hooks/internal/Tracker.js index 5144b9332f..3dffdab20f 100644 --- a/packages/component/src/Tracker.js +++ b/packages/api/src/hooks/internal/Tracker.js @@ -1,4 +1,4 @@ -import useTracker from './hooks/internal/useTracker'; +import useTracker from './useTracker'; const Tracker = () => { useTracker(); diff --git a/packages/component/src/WebChatUIContext.js b/packages/api/src/hooks/internal/WebChatAPIContext.js similarity index 73% rename from packages/component/src/WebChatUIContext.js rename to packages/api/src/hooks/internal/WebChatAPIContext.js index 27cf45b251..39f4b2db4f 100644 --- a/packages/component/src/WebChatUIContext.js +++ b/packages/api/src/hooks/internal/WebChatAPIContext.js @@ -4,6 +4,6 @@ const context = React.createContext({ sendFocusRef: null }); -context.displayName = 'WebChatUIContext'; +context.displayName = 'WebChatAPIContext'; export default context; diff --git a/packages/component/src/WebChatReduxContext.js b/packages/api/src/hooks/internal/WebChatReduxContext.js similarity index 100% rename from packages/component/src/WebChatReduxContext.js rename to packages/api/src/hooks/internal/WebChatReduxContext.js diff --git a/packages/component/src/defaultSelectVoice.js b/packages/api/src/hooks/internal/defaultSelectVoice.js similarity index 100% rename from packages/component/src/defaultSelectVoice.js rename to packages/api/src/hooks/internal/defaultSelectVoice.js diff --git a/packages/component/src/defaultSelectVoice.test.js b/packages/api/src/hooks/internal/defaultSelectVoice.test.js similarity index 100% rename from packages/component/src/defaultSelectVoice.test.js rename to packages/api/src/hooks/internal/defaultSelectVoice.test.js diff --git a/packages/component/src/hooks/internal/useCreateActivityRendererInternal.js b/packages/api/src/hooks/internal/useCreateActivityRendererInternal.js similarity index 55% rename from packages/component/src/hooks/internal/useCreateActivityRendererInternal.js rename to packages/api/src/hooks/internal/useCreateActivityRendererInternal.js index bdcd738db6..ce8f364ab1 100644 --- a/packages/component/src/hooks/internal/useCreateActivityRendererInternal.js +++ b/packages/api/src/hooks/internal/useCreateActivityRendererInternal.js @@ -1,13 +1,13 @@ import { useMemo } from 'react'; -import useRenderAttachment from '../useRenderAttachment'; -import useWebChatUIContext from './useWebChatUIContext'; +import useCreateAttachmentRenderer from '../useCreateAttachmentRenderer'; +import useWebChatAPIContext from './useWebChatAPIContext'; -export default function useCreateActivityRendererInternal(renderAttachmentOverride) { - const { activityRenderer: createActivityRenderer } = useWebChatUIContext(); - const defaultRenderAttachment = useRenderAttachment(); +export default function useCreateActivityRendererInternal(createAttachmentRendererOverride) { + const { activityRenderer: createActivityRenderer } = useWebChatAPIContext(); + const defaultCreateAttachmentRenderer = useCreateAttachmentRenderer(); - const renderAttachment = renderAttachmentOverride || defaultRenderAttachment; + const createAttachmentRenderer = createAttachmentRendererOverride || defaultCreateAttachmentRenderer; return useMemo( () => (...createActivityRendererOptions) => { @@ -18,7 +18,10 @@ export default function useCreateActivityRendererInternal(renderAttachmentOverri } return renderActivityOptions => { - const activityElement = renderActivity(renderAttachment, renderActivityOptions); + const activityElement = renderActivity( + (...renderAttachmentArgs) => createAttachmentRenderer(...renderAttachmentArgs), + renderActivityOptions + ); // "activityElement" cannot be false. If the middleware want to hide the "activityElement", it should return "false" when we call createActivityRenderer(). activityElement || @@ -29,6 +32,6 @@ export default function useCreateActivityRendererInternal(renderAttachmentOverri return activityElement; }; }, - [createActivityRenderer, renderAttachment] + [createActivityRenderer, createAttachmentRenderer] ); } diff --git a/packages/component/src/hooks/internal/useDebugDeps.js b/packages/api/src/hooks/internal/useDebugDeps.js similarity index 100% rename from packages/component/src/hooks/internal/useDebugDeps.js rename to packages/api/src/hooks/internal/useDebugDeps.js diff --git a/packages/api/src/hooks/internal/useDirFromProps.js b/packages/api/src/hooks/internal/useDirFromProps.js new file mode 100644 index 0000000000..f3ba76324f --- /dev/null +++ b/packages/api/src/hooks/internal/useDirFromProps.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './useWebChatAPIContext'; + +export default function useDirFromProps() { + return [useWebChatAPIContext().dir]; +} diff --git a/packages/api/src/hooks/internal/useErrorBoxClass.js b/packages/api/src/hooks/internal/useErrorBoxClass.js new file mode 100644 index 0000000000..fd1fabd41e --- /dev/null +++ b/packages/api/src/hooks/internal/useErrorBoxClass.js @@ -0,0 +1,7 @@ +import useWebChatAPIContext from './useWebChatAPIContext'; + +export default function useErrorBoxClass() { + const { internalErrorBoxClass } = useWebChatAPIContext(); + + return [internalErrorBoxClass]; +} diff --git a/packages/component/src/hooks/internal/useForceRender.js b/packages/api/src/hooks/internal/useForceRender.js similarity index 100% rename from packages/component/src/hooks/internal/useForceRender.js rename to packages/api/src/hooks/internal/useForceRender.js diff --git a/packages/component/src/hooks/internal/useForceRenderAtInterval.js b/packages/api/src/hooks/internal/useForceRenderAtInterval.js similarity index 100% rename from packages/component/src/hooks/internal/useForceRenderAtInterval.js rename to packages/api/src/hooks/internal/useForceRenderAtInterval.js diff --git a/packages/component/src/hooks/internal/useGetTranscriptActivityElementByID.js b/packages/api/src/hooks/internal/useGetTranscriptActivityElementByID.js similarity index 100% rename from packages/component/src/hooks/internal/useGetTranscriptActivityElementByID.js rename to packages/api/src/hooks/internal/useGetTranscriptActivityElementByID.js diff --git a/packages/api/src/hooks/internal/useLocalizedGlobalize.js b/packages/api/src/hooks/internal/useLocalizedGlobalize.js new file mode 100644 index 0000000000..e38989e8d9 --- /dev/null +++ b/packages/api/src/hooks/internal/useLocalizedGlobalize.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './useWebChatAPIContext'; + +export default function useLocalizedGlobalize() { + return useWebChatAPIContext().localizedGlobalizeState; +} diff --git a/packages/api/src/hooks/internal/useLocalizedStrings.js b/packages/api/src/hooks/internal/useLocalizedStrings.js new file mode 100644 index 0000000000..d29d7835b5 --- /dev/null +++ b/packages/api/src/hooks/internal/useLocalizedStrings.js @@ -0,0 +1,7 @@ +import useWebChatAPIContext from './useWebChatAPIContext'; + +export default function useLocalizedStrings() { + const { localizedStrings } = useWebChatAPIContext(); + + return localizedStrings; +} diff --git a/packages/api/src/hooks/internal/useMarkActivity.js b/packages/api/src/hooks/internal/useMarkActivity.js new file mode 100644 index 0000000000..6b34121bea --- /dev/null +++ b/packages/api/src/hooks/internal/useMarkActivity.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './useWebChatAPIContext'; + +export default function useMarkActivity() { + return useWebChatAPIContext().markActivity; +} diff --git a/packages/component/src/hooks/internal/useReadTelemetryDimensions.js b/packages/api/src/hooks/internal/useReadTelemetryDimensions.js similarity index 61% rename from packages/component/src/hooks/internal/useReadTelemetryDimensions.js rename to packages/api/src/hooks/internal/useReadTelemetryDimensions.js index 3c9dc06611..da4b5a485c 100644 --- a/packages/component/src/hooks/internal/useReadTelemetryDimensions.js +++ b/packages/api/src/hooks/internal/useReadTelemetryDimensions.js @@ -1,9 +1,9 @@ import { useCallback } from 'react'; -import useWebChatUIContext from './useWebChatUIContext'; +import useWebChatAPIContext from './useWebChatAPIContext'; export default function useReadTelemetryDimensions() { - const { telemetryDimensionsRef } = useWebChatUIContext(); + const { telemetryDimensionsRef } = useWebChatAPIContext(); return useCallback(() => ({ ...telemetryDimensionsRef.current }), [telemetryDimensionsRef]); } diff --git a/packages/component/src/hooks/internal/useReplaceEmoticon.js b/packages/api/src/hooks/internal/useReplaceEmoticon.js similarity index 100% rename from packages/component/src/hooks/internal/useReplaceEmoticon.js rename to packages/api/src/hooks/internal/useReplaceEmoticon.js diff --git a/packages/api/src/hooks/internal/useSendBoxFocusRef.js b/packages/api/src/hooks/internal/useSendBoxFocusRef.js new file mode 100644 index 0000000000..f86f831afc --- /dev/null +++ b/packages/api/src/hooks/internal/useSendBoxFocusRef.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './useWebChatAPIContext'; + +export default function useSendBoxFocusRef() { + return [useWebChatAPIContext().sendBoxFocusRef]; +} diff --git a/packages/api/src/hooks/internal/useSetDictateState.js b/packages/api/src/hooks/internal/useSetDictateState.js new file mode 100644 index 0000000000..03fb12c869 --- /dev/null +++ b/packages/api/src/hooks/internal/useSetDictateState.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './useWebChatAPIContext'; + +export default function useSetDictateState() { + return useWebChatAPIContext().setDictateState; +} diff --git a/packages/api/src/hooks/internal/useSettableDictateAbortable.js b/packages/api/src/hooks/internal/useSettableDictateAbortable.js new file mode 100644 index 0000000000..e973a88962 --- /dev/null +++ b/packages/api/src/hooks/internal/useSettableDictateAbortable.js @@ -0,0 +1,7 @@ +import useWebChatAPIContext from './useWebChatAPIContext'; + +export default function useSettableDictateAbortable() { + const { dictateAbortable, setDictateAbortable } = useWebChatAPIContext(); + + return [dictateAbortable, setDictateAbortable]; +} diff --git a/packages/component/src/hooks/internal/useTimePassed.js b/packages/api/src/hooks/internal/useTimePassed.js similarity index 100% rename from packages/component/src/hooks/internal/useTimePassed.js rename to packages/api/src/hooks/internal/useTimePassed.js diff --git a/packages/component/src/hooks/internal/useTimer.js b/packages/api/src/hooks/internal/useTimer.js similarity index 100% rename from packages/component/src/hooks/internal/useTimer.js rename to packages/api/src/hooks/internal/useTimer.js diff --git a/packages/component/src/hooks/internal/useTracker.js b/packages/api/src/hooks/internal/useTracker.js similarity index 92% rename from packages/component/src/hooks/internal/useTracker.js rename to packages/api/src/hooks/internal/useTracker.js index 276d0047b2..31c827843c 100644 --- a/packages/component/src/hooks/internal/useTracker.js +++ b/packages/api/src/hooks/internal/useTracker.js @@ -1,7 +1,7 @@ import { useEffect } from 'react'; -import { checkSupport as supportWorker } from '../../Utils/downscaleImageToDataURLUsingWorker'; -import { speechSynthesis } from '../../Speech/BypassSpeechSynthesisPonyfill'; +import { checkSupport as supportWorker } from '../../utils/downscaleImageToDataURLUsingWorker'; +import { speechSynthesis } from './BypassSpeechSynthesisPonyfill'; import useLanguage from '../useLanguage'; import useTrackDimension from '../useTrackDimension'; import useTrackEvent from '../useTrackEvent'; diff --git a/packages/api/src/hooks/internal/useTranscriptFocusRef.js b/packages/api/src/hooks/internal/useTranscriptFocusRef.js new file mode 100644 index 0000000000..d993eb4393 --- /dev/null +++ b/packages/api/src/hooks/internal/useTranscriptFocusRef.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './useWebChatAPIContext'; + +export default function useTranscriptFocusRef() { + return [useWebChatAPIContext().transcriptFocusRef]; +} diff --git a/packages/api/src/hooks/internal/useWebChatAPIContext.js b/packages/api/src/hooks/internal/useWebChatAPIContext.js new file mode 100644 index 0000000000..96ec39307f --- /dev/null +++ b/packages/api/src/hooks/internal/useWebChatAPIContext.js @@ -0,0 +1,13 @@ +import { useContext } from 'react'; + +import WebChatAPIContext from './WebChatAPIContext'; + +export default function useWebChatAPIContext() { + const context = useContext(WebChatAPIContext); + + if (!context) { + throw new Error('This hook can only be used on a component that is a descendant of '); + } + + return context; +} diff --git a/packages/api/src/hooks/middleware/UserlandBoundary.js b/packages/api/src/hooks/middleware/UserlandBoundary.js new file mode 100644 index 0000000000..3c27f046e9 --- /dev/null +++ b/packages/api/src/hooks/middleware/UserlandBoundary.js @@ -0,0 +1,31 @@ +import PropTypes from 'prop-types'; +import React, { useCallback, useState } from 'react'; + +import ErrorBoundary from '../utils/ErrorBoundary'; +import useErrorBoxClass from '../internal/useErrorBoxClass'; + +const UserlandBoundary = ({ children, type }) => { + const [error, setError] = useState(); + const [errorBoxClass] = useErrorBoxClass(); + const handleError = useCallback(({ error }) => setError(error)); + + // console.log('UserlandBoundary', { children }); + + return error ? ( + React.createElement(errorBoxClass, { error, type }) + ) : ( + {children} + ); +}; + +UserlandBoundary.defaultProps = { + children: undefined, + type: undefined +}; + +UserlandBoundary.propTypes = { + children: PropTypes.any, + type: PropTypes.string +}; + +export default UserlandBoundary; diff --git a/packages/api/src/hooks/middleware/applyMiddleware.js b/packages/api/src/hooks/middleware/applyMiddleware.js new file mode 100644 index 0000000000..c88de3c127 --- /dev/null +++ b/packages/api/src/hooks/middleware/applyMiddleware.js @@ -0,0 +1,63 @@ +import React from 'react'; + +import concatMiddleware from './concatMiddleware'; +import ErrorBox from '../internal/ErrorBox'; +import UserlandBoundary from './UserlandBoundary'; + +export default function applyMiddleware(type, ...middleware) { + return (...setupArgs) => + concatMiddleware(...middleware)(...setupArgs)(() => { + throw new Error(`reached terminator of ${type}`); + }); +} + +export function forRenderer(type, ...middleware) { + return (...setupArgs) => { + const runMiddleware = concatMiddleware(...middleware)(...setupArgs)(() => ( + + )); + + // console.log('forRenderer.runMiddleware', { runMiddleware, setupArgs }); + + // The createRendererArgs is "what to render", for example, activity. + // The function should return with only one of the two results: + // - Returns a function if there is a renderer *committed* to render; + // - Returns false if nothing should be rendered. + return (...createRendererArgs) => { + try { + const render = runMiddleware(...createRendererArgs); + + // console.log(`forRenderer[${type}]`, { args: createRendererArgs, render }); + + if (!render) { + return false; + } else if (React.isValidElement(render)) { + return {render}; + } else { + return ((...renderTimeArgs) => { + // console.log(`forRenderer.render[${type}]`, { render, renderTimeArgs }); + + return {render(...renderTimeArgs)}; + }) + } + + return ( + !!render && + // The renderTimeArgs is for "styling" or render-time arguments. + // These arguments must not cause the renderer hiding the element (a.k.a. not rendering). + // For example: + // - Should we show/hide the timestamp while rendering this activity? + ((...renderTimeArgs) => { + // console.log(`forRenderer.render[${type}]`, { render, renderTimeArgs }); + + return {render(...renderTimeArgs)}; + }) + ); + } catch (err) { + // The next line is not a React component. It is a render function. + // eslint-disable-next-line react/display-name + return () => ; + } + }; + }; +} diff --git a/packages/api/src/hooks/middleware/concatMiddleware.js b/packages/api/src/hooks/middleware/concatMiddleware.js new file mode 100644 index 0000000000..046d335408 --- /dev/null +++ b/packages/api/src/hooks/middleware/concatMiddleware.js @@ -0,0 +1,19 @@ +export default function concatMiddleware(...middleware) { + return setupArgs => { + const setup = middleware.reduce( + (setup, middleware) => (middleware ? [...setup, middleware(setupArgs)] : setup), + [] + ); + + return last => { + const stack = setup.slice(); + const work = index => (...runArgs) => { + const next = stack[index]; + + return (next ? next(work(index + 1)) : last)(...runArgs); + }; + + return work(0); + }; + }; +} diff --git a/packages/api/src/hooks/middleware/createActivityRenderer.js b/packages/api/src/hooks/middleware/createActivityRenderer.js new file mode 100644 index 0000000000..a1a39c4a3b --- /dev/null +++ b/packages/api/src/hooks/middleware/createActivityRenderer.js @@ -0,0 +1,6 @@ +import applyMiddleware from './applyMiddleware'; + +const createActivityRenderer = (...middleware) => + applyMiddleware('activity middleware', ...middleware); + +export default createActivityRenderer; diff --git a/packages/api/src/hooks/middleware/createActivityStatusRenderer.js b/packages/api/src/hooks/middleware/createActivityStatusRenderer.js new file mode 100644 index 0000000000..9c5f4d82a2 --- /dev/null +++ b/packages/api/src/hooks/middleware/createActivityStatusRenderer.js @@ -0,0 +1,6 @@ +import applyMiddleware from './applyMiddleware'; + +const createActivityStatusRenderer = (...middleware) => + applyMiddleware('activity status middleware', ...middleware, () => () => () => false); + +export default createActivityStatusRenderer; diff --git a/packages/api/src/hooks/middleware/createAttachmentRenderer.js b/packages/api/src/hooks/middleware/createAttachmentRenderer.js new file mode 100644 index 0000000000..a284d25f02 --- /dev/null +++ b/packages/api/src/hooks/middleware/createAttachmentRenderer.js @@ -0,0 +1,12 @@ +import applyMiddleware from './applyMiddleware'; + +const createAttachmentRenderer = (...middleware) => + applyMiddleware('attachment middleware', ...middleware, () => () => ({ attachment }) => { + if (attachment) { + throw new Error(`No renderer for attachment of type "${attachment.contentType}"`); + } else { + throw new Error('No attachment to render'); + } + }); + +export default createAttachmentRenderer; diff --git a/packages/api/src/hooks/middleware/createAvatarRenderer.js b/packages/api/src/hooks/middleware/createAvatarRenderer.js new file mode 100644 index 0000000000..6b33f9450f --- /dev/null +++ b/packages/api/src/hooks/middleware/createAvatarRenderer.js @@ -0,0 +1,6 @@ +import applyMiddleware from './applyMiddleware'; + +const createAvatarRenderer = (...middleware) => + applyMiddleware('avatar middleware', ...middleware, () => () => () => false); + +export default createAvatarRenderer; diff --git a/packages/api/src/hooks/middleware/createDefaultGroupActivitiesMiddleware.js b/packages/api/src/hooks/middleware/createDefaultGroupActivitiesMiddleware.js new file mode 100644 index 0000000000..2e93edf445 --- /dev/null +++ b/packages/api/src/hooks/middleware/createDefaultGroupActivitiesMiddleware.js @@ -0,0 +1,55 @@ +import { Constants } from 'botframework-webchat-core'; + +const { + ActivityClientState: { SENT } +} = Constants; + +function bin(items, grouping) { + let lastBin; + const bins = []; + let lastItem; + + items.forEach(item => { + if (lastItem && grouping(lastItem, item)) { + lastBin.push(item); + } else { + lastBin = [item]; + bins.push(lastBin); + } + + lastItem = item; + }); + + return bins; +} + +function sending(activity) { + return activity.from.role === 'user' && activity.channelData && activity.channelData.state !== SENT; +} + +function shouldGroupTimestamp(activityX, activityY, groupTimestamp) { + if (groupTimestamp === false) { + // Hide timestamp for all activities. + return true; + } else if (activityX && activityY) { + if (sending(activityX) !== sending(activityY)) { + return false; + } + + groupTimestamp = typeof groupTimestamp === 'number' ? groupTimestamp : Infinity; + + const timeX = new Date(activityX.timestamp).getTime(); + const timeY = new Date(activityY.timestamp).getTime(); + + return Math.abs(timeX - timeY) <= groupTimestamp; + } + + return false; +} + +export default function createDefaultGroupActivityMiddleware({ groupTimestamp }) { + return () => () => ({ activities }) => ({ + sender: bin(activities, (x, y) => x.from.role === y.from.role), + status: bin(activities, (x, y) => shouldGroupTimestamp(x, y, groupTimestamp)) + }); +} diff --git a/packages/api/src/hooks/middleware/createErrorBoundaryRenderer.js b/packages/api/src/hooks/middleware/createErrorBoundaryRenderer.js new file mode 100644 index 0000000000..a91464324c --- /dev/null +++ b/packages/api/src/hooks/middleware/createErrorBoundaryRenderer.js @@ -0,0 +1,12 @@ +export default function createErrorBoundaryRenderer(...errorBoundaryMiddleware) { + const render = concatMiddleware(...errorBoundaryMiddleware)({}); + + return (...args) => + render(({ error, type }) => { + console.warn(`botframework-webchat: Failed to "${type}".`, error); + + return false; + })( + ...args + ); +} diff --git a/packages/api/src/hooks/middleware/createToastRenderer.js b/packages/api/src/hooks/middleware/createToastRenderer.js new file mode 100644 index 0000000000..89284c89aa --- /dev/null +++ b/packages/api/src/hooks/middleware/createToastRenderer.js @@ -0,0 +1,12 @@ +import applyMiddleware from './applyMiddleware'; + +const createToastRenderer = (...middleware) => + applyMiddleware('toast middleware', ...middleware, () => () => ({ notification }) => { + if (notification) { + throw new Error(`No renderer for notification of type "${notification.contentType}"`); + } else { + throw new Error('No notification to render'); + } + }); + +export default createToastRenderer; diff --git a/packages/api/src/hooks/middleware/createTypingIndicatorRenderer.js b/packages/api/src/hooks/middleware/createTypingIndicatorRenderer.js new file mode 100644 index 0000000000..d403a05c21 --- /dev/null +++ b/packages/api/src/hooks/middleware/createTypingIndicatorRenderer.js @@ -0,0 +1,8 @@ +import applyMiddleware from './applyMiddleware'; + +const createTypingIndicator = (...middleware) => + applyMiddleware('typing indicator middleware', ...middleware, () => () => () => { + throw new Error(`No renderer for typing indicator`); + }); + +export default createTypingIndicator; diff --git a/packages/component/src/hooks/useActiveTyping.js b/packages/api/src/hooks/useActiveTyping.js similarity index 95% rename from packages/component/src/hooks/useActiveTyping.js rename to packages/api/src/hooks/useActiveTyping.js index 23617155f5..e845e3bf4f 100644 --- a/packages/component/src/hooks/useActiveTyping.js +++ b/packages/api/src/hooks/useActiveTyping.js @@ -1,6 +1,6 @@ import { useEffect } from 'react'; -import { useSelector } from '../WebChatReduxContext'; +import { useSelector } from './internal/WebChatReduxContext'; import useForceRender from './internal/useForceRender'; import useStyleOptions from './useStyleOptions'; diff --git a/packages/component/src/hooks/useActivities.js b/packages/api/src/hooks/useActivities.js similarity index 61% rename from packages/component/src/hooks/useActivities.js rename to packages/api/src/hooks/useActivities.js index 3ffec17032..b476d2f684 100644 --- a/packages/component/src/hooks/useActivities.js +++ b/packages/api/src/hooks/useActivities.js @@ -1,4 +1,4 @@ -import { useSelector } from '../WebChatReduxContext'; +import { useSelector } from './internal/WebChatReduxContext'; export default function useActivities() { return [useSelector(({ activities }) => activities)]; diff --git a/packages/component/src/hooks/useAvatarForBot.js b/packages/api/src/hooks/useAvatarForBot.js similarity index 100% rename from packages/component/src/hooks/useAvatarForBot.js rename to packages/api/src/hooks/useAvatarForBot.js diff --git a/packages/component/src/hooks/useAvatarForUser.js b/packages/api/src/hooks/useAvatarForUser.js similarity index 100% rename from packages/component/src/hooks/useAvatarForUser.js rename to packages/api/src/hooks/useAvatarForUser.js diff --git a/packages/component/src/hooks/useByteFormatter.js b/packages/api/src/hooks/useByteFormatter.js similarity index 100% rename from packages/component/src/hooks/useByteFormatter.js rename to packages/api/src/hooks/useByteFormatter.js diff --git a/packages/component/src/hooks/useConnectivityStatus.js b/packages/api/src/hooks/useConnectivityStatus.js similarity index 66% rename from packages/component/src/hooks/useConnectivityStatus.js rename to packages/api/src/hooks/useConnectivityStatus.js index 4cbd5f19d2..7decfdc4b6 100644 --- a/packages/component/src/hooks/useConnectivityStatus.js +++ b/packages/api/src/hooks/useConnectivityStatus.js @@ -1,4 +1,4 @@ -import { useSelector } from '../WebChatReduxContext'; +import { useSelector } from './internal/WebChatReduxContext'; export default function useConnectivityStatus() { return [useSelector(({ connectivityStatus }) => connectivityStatus)]; diff --git a/packages/component/src/hooks/useCreateActivityRenderer.js b/packages/api/src/hooks/useCreateActivityRenderer.js similarity index 100% rename from packages/component/src/hooks/useCreateActivityRenderer.js rename to packages/api/src/hooks/useCreateActivityRenderer.js diff --git a/packages/component/src/hooks/useCreateActivityStatusRenderer.js b/packages/api/src/hooks/useCreateActivityStatusRenderer.js similarity index 95% rename from packages/component/src/hooks/useCreateActivityStatusRenderer.js rename to packages/api/src/hooks/useCreateActivityStatusRenderer.js index 0a863ebee8..df6ee820b8 100644 --- a/packages/component/src/hooks/useCreateActivityStatusRenderer.js +++ b/packages/api/src/hooks/useCreateActivityStatusRenderer.js @@ -5,14 +5,14 @@ import React, { useMemo } from 'react'; import useGetSendTimeoutForActivity from './useGetSendTimeoutForActivity'; import useTimePassed from './internal/useTimePassed'; -import useWebChatUIContext from './internal/useWebChatUIContext'; +import useWebChatAPIContext from './internal/useWebChatAPIContext'; const { ActivityClientState: { SEND_FAILED, SENDING, SENT } } = Constants; const ActivityStatusContainer = ({ activity, hideTimestamp, nextVisibleActivity }) => { - const { activityStatusRenderer: createActivityStatusRenderer } = useWebChatUIContext(); + const { activityStatusRenderer: createActivityStatusRenderer } = useWebChatAPIContext(); const getSendTimeoutForActivity = useGetSendTimeoutForActivity(); // SEND_FAILED from the activity is ignored, and is instead based on styleOptions.sendTimeout. diff --git a/packages/api/src/hooks/useCreateAttachmentRenderer.js b/packages/api/src/hooks/useCreateAttachmentRenderer.js new file mode 100644 index 0000000000..a0203179d1 --- /dev/null +++ b/packages/api/src/hooks/useCreateAttachmentRenderer.js @@ -0,0 +1,7 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useCreateAttachmentRenderer() { + const { attachmentRenderer: createAttachmentRenderer } = useWebChatAPIContext(); + + return createAttachmentRenderer; +} diff --git a/packages/component/src/hooks/useCreateAvatarRenderer.js b/packages/api/src/hooks/useCreateAvatarRenderer.js similarity index 86% rename from packages/component/src/hooks/useCreateAvatarRenderer.js rename to packages/api/src/hooks/useCreateAvatarRenderer.js index 19f03e443d..16049e87ea 100644 --- a/packages/component/src/hooks/useCreateAvatarRenderer.js +++ b/packages/api/src/hooks/useCreateAvatarRenderer.js @@ -1,11 +1,11 @@ import { useMemo } from 'react'; import useStyleOptions from './useStyleOptions'; -import useWebChatUIContext from './internal/useWebChatUIContext'; +import useWebChatAPIContext from './internal/useWebChatAPIContext'; export default function useCreateAvatarRenderer() { const [styleOptions] = useStyleOptions(); - const { avatarRenderer } = useWebChatUIContext(); + const { avatarRenderer } = useWebChatAPIContext(); return useMemo( () => ({ activity }) => { diff --git a/packages/component/src/hooks/useDateFormatter.js b/packages/api/src/hooks/useDateFormatter.js similarity index 100% rename from packages/component/src/hooks/useDateFormatter.js rename to packages/api/src/hooks/useDateFormatter.js diff --git a/packages/component/src/hooks/useDebouncedNotifications.js b/packages/api/src/hooks/useDebouncedNotifications.js similarity index 98% rename from packages/component/src/hooks/useDebouncedNotifications.js rename to packages/api/src/hooks/useDebouncedNotifications.js index f963c51ed3..81dabb3f46 100644 --- a/packages/component/src/hooks/useDebouncedNotifications.js +++ b/packages/api/src/hooks/useDebouncedNotifications.js @@ -1,7 +1,7 @@ import { useRef } from 'react'; import updateIn from 'simple-update-in'; -import findMin from '../Utils/findMin'; +import findMin from '../utils/findMin'; import useForceRender from './internal/useForceRender'; import useNotifications from './useNotifications'; import useStyleOptions from './useStyleOptions'; diff --git a/packages/component/src/hooks/useDebouncedNotifications.spec.js b/packages/api/src/hooks/useDebouncedNotifications.spec.js similarity index 100% rename from packages/component/src/hooks/useDebouncedNotifications.spec.js rename to packages/api/src/hooks/useDebouncedNotifications.spec.js diff --git a/packages/component/src/hooks/useDictateAbortable.js b/packages/api/src/hooks/useDictateAbortable.js similarity index 100% rename from packages/component/src/hooks/useDictateAbortable.js rename to packages/api/src/hooks/useDictateAbortable.js diff --git a/packages/api/src/hooks/useDictateInterims.js b/packages/api/src/hooks/useDictateInterims.js new file mode 100644 index 0000000000..8348058fe0 --- /dev/null +++ b/packages/api/src/hooks/useDictateInterims.js @@ -0,0 +1,6 @@ +import { useSelector } from './internal/WebChatReduxContext'; +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useDictateInterims() { + return [useSelector(({ dictateInterims }) => dictateInterims) || [], useWebChatAPIContext().setDictateInterims]; +} diff --git a/packages/component/src/hooks/useDictateState.js b/packages/api/src/hooks/useDictateState.js similarity index 75% rename from packages/component/src/hooks/useDictateState.js rename to packages/api/src/hooks/useDictateState.js index 7603d527fa..c2b7474d52 100644 --- a/packages/component/src/hooks/useDictateState.js +++ b/packages/api/src/hooks/useDictateState.js @@ -1,4 +1,4 @@ -import { useSelector } from '../WebChatReduxContext'; +import { useSelector } from './internal/WebChatReduxContext'; // TODO: [P3] We should update this code to use core/src/selectors/dictateState.js export default function useDictateState() { diff --git a/packages/component/src/hooks/useDirection.js b/packages/api/src/hooks/useDirection.js similarity index 91% rename from packages/component/src/hooks/useDirection.js rename to packages/api/src/hooks/useDirection.js index cf456af16f..27d76038b3 100644 --- a/packages/component/src/hooks/useDirection.js +++ b/packages/api/src/hooks/useDirection.js @@ -1,6 +1,6 @@ import { useMemo } from 'react'; -import getRTLList from '../Localization/getRTLList'; +import getRTLList from '../localization/getRTLList'; import useDirFromProps from './internal/useDirFromProps'; import useLanguage from './useLanguage'; diff --git a/packages/api/src/hooks/useDisabled.js b/packages/api/src/hooks/useDisabled.js new file mode 100644 index 0000000000..e30e8d4ae4 --- /dev/null +++ b/packages/api/src/hooks/useDisabled.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useDisabled() { + return [useWebChatAPIContext().disabled]; +} diff --git a/packages/api/src/hooks/useDismissNotification.js b/packages/api/src/hooks/useDismissNotification.js new file mode 100644 index 0000000000..5b8eab1604 --- /dev/null +++ b/packages/api/src/hooks/useDismissNotification.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useDismissNotification() { + return useWebChatAPIContext().dismissNotification; +} diff --git a/packages/api/src/hooks/useEmitTypingIndicator.js b/packages/api/src/hooks/useEmitTypingIndicator.js new file mode 100644 index 0000000000..a8dd3d6d6c --- /dev/null +++ b/packages/api/src/hooks/useEmitTypingIndicator.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useEmitTypingIndicator() { + return useWebChatAPIContext().emitTypingIndicator; +} diff --git a/packages/api/src/hooks/useFocus.js b/packages/api/src/hooks/useFocus.js new file mode 100644 index 0000000000..5ad6092940 --- /dev/null +++ b/packages/api/src/hooks/useFocus.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useFocus() { + return useWebChatAPIContext().focus; +} diff --git a/packages/component/src/hooks/useFocusSendBox.js b/packages/api/src/hooks/useFocusSendBox.js similarity index 100% rename from packages/component/src/hooks/useFocusSendBox.js rename to packages/api/src/hooks/useFocusSendBox.js diff --git a/packages/component/src/hooks/useGetSendTimeoutForActivity.js b/packages/api/src/hooks/useGetSendTimeoutForActivity.js similarity index 100% rename from packages/component/src/hooks/useGetSendTimeoutForActivity.js rename to packages/api/src/hooks/useGetSendTimeoutForActivity.js diff --git a/packages/api/src/hooks/useGrammars.js b/packages/api/src/hooks/useGrammars.js new file mode 100644 index 0000000000..fb01abed12 --- /dev/null +++ b/packages/api/src/hooks/useGrammars.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useGrammars() { + return [useWebChatAPIContext().grammars]; +} diff --git a/packages/api/src/hooks/useGroupActivities.js b/packages/api/src/hooks/useGroupActivities.js new file mode 100644 index 0000000000..fad4dab54c --- /dev/null +++ b/packages/api/src/hooks/useGroupActivities.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useGroupActivities() { + return useWebChatAPIContext().groupActivities; +} diff --git a/packages/component/src/hooks/useGroupTimestamp.js b/packages/api/src/hooks/useGroupTimestamp.js similarity index 100% rename from packages/component/src/hooks/useGroupTimestamp.js rename to packages/api/src/hooks/useGroupTimestamp.js diff --git a/packages/component/src/hooks/useLanguage.js b/packages/api/src/hooks/useLanguage.js similarity index 71% rename from packages/component/src/hooks/useLanguage.js rename to packages/api/src/hooks/useLanguage.js index fba81ba961..400683a7df 100644 --- a/packages/component/src/hooks/useLanguage.js +++ b/packages/api/src/hooks/useLanguage.js @@ -1,8 +1,8 @@ import useLocalizedStrings from './internal/useLocalizedStrings'; -import useWebChatUIContext from './internal/useWebChatUIContext'; +import useWebChatAPIContext from './internal/useWebChatAPIContext'; export default function useLanguage(options) { - const { language } = useWebChatUIContext(); + const { language } = useWebChatAPIContext(); const localizedStrings = useLocalizedStrings(); if (options === 'speech') { diff --git a/packages/component/src/hooks/useLastTypingAt.js b/packages/api/src/hooks/useLastTypingAt.js similarity index 86% rename from packages/component/src/hooks/useLastTypingAt.js rename to packages/api/src/hooks/useLastTypingAt.js index 8839d7fc73..b464951014 100644 --- a/packages/component/src/hooks/useLastTypingAt.js +++ b/packages/api/src/hooks/useLastTypingAt.js @@ -1,4 +1,4 @@ -import { useSelector } from '../WebChatReduxContext'; +import { useSelector } from './internal/WebChatReduxContext'; let showDeprecationNotes = true; diff --git a/packages/component/src/hooks/useLocalize.js b/packages/api/src/hooks/useLocalize.js similarity index 81% rename from packages/component/src/hooks/useLocalize.js rename to packages/api/src/hooks/useLocalize.js index 68b7afc7ef..2c99e55ee4 100644 --- a/packages/component/src/hooks/useLocalize.js +++ b/packages/api/src/hooks/useLocalize.js @@ -1,6 +1,6 @@ import useLanguage from './useLanguage'; -import { localize } from '../Localization/Localize'; +import { localize } from '../localization/Localize'; export default function useLocalize(text, ...args) { const [language] = useLanguage(); diff --git a/packages/component/src/hooks/useLocalizeDate.js b/packages/api/src/hooks/useLocalizeDate.js similarity index 88% rename from packages/component/src/hooks/useLocalizeDate.js rename to packages/api/src/hooks/useLocalizeDate.js index f4c944d19e..3cf6de0849 100644 --- a/packages/component/src/hooks/useLocalizeDate.js +++ b/packages/api/src/hooks/useLocalizeDate.js @@ -1,6 +1,6 @@ import useLanguage from './useLanguage'; -import getLocaleString from '../Localization/getLocaleString'; +import getLocaleString from '../localization/getLocaleString'; let deprecationNotesShown; diff --git a/packages/component/src/hooks/useLocalizer.js b/packages/api/src/hooks/useLocalizer.js similarity index 95% rename from packages/component/src/hooks/useLocalizer.js rename to packages/api/src/hooks/useLocalizer.js index 6197c1ed37..dd50300ce3 100644 --- a/packages/component/src/hooks/useLocalizer.js +++ b/packages/api/src/hooks/useLocalizer.js @@ -1,9 +1,9 @@ import { useCallback } from 'react'; -import getAllLocalizedStrings from '../Localization/getAllLocalizedStrings'; +import getAllLocalizedStrings from '../localization/getAllLocalizedStrings'; import useLocalizedGlobalize from './internal/useLocalizedGlobalize'; import useLocalizedStrings from './internal/useLocalizedStrings'; -import isObject from '../Utils/isObject'; +import isObject from '../utils/isObject'; const DEFAULT_STRINGS = getAllLocalizedStrings()['en-US']; diff --git a/packages/component/src/hooks/useMarkActivityAsSpoken.js b/packages/api/src/hooks/useMarkActivityAsSpoken.js similarity index 100% rename from packages/component/src/hooks/useMarkActivityAsSpoken.js rename to packages/api/src/hooks/useMarkActivityAsSpoken.js diff --git a/packages/component/src/hooks/useNotifications.js b/packages/api/src/hooks/useNotifications.js similarity index 63% rename from packages/component/src/hooks/useNotifications.js rename to packages/api/src/hooks/useNotifications.js index 3c0bc5e046..2c4f60a94b 100644 --- a/packages/component/src/hooks/useNotifications.js +++ b/packages/api/src/hooks/useNotifications.js @@ -1,4 +1,4 @@ -import { useSelector } from '../WebChatReduxContext'; +import { useSelector } from './internal/WebChatReduxContext'; export default function useNotifications() { return [useSelector(({ notifications }) => notifications)]; diff --git a/packages/api/src/hooks/usePerformCardAction.js b/packages/api/src/hooks/usePerformCardAction.js new file mode 100644 index 0000000000..60e50a2b38 --- /dev/null +++ b/packages/api/src/hooks/usePerformCardAction.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function usePerformCardAction() { + return useWebChatAPIContext().onCardAction; +} diff --git a/packages/api/src/hooks/usePostActivity.js b/packages/api/src/hooks/usePostActivity.js new file mode 100644 index 0000000000..c0c24f0675 --- /dev/null +++ b/packages/api/src/hooks/usePostActivity.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function usePostActivity() { + return useWebChatAPIContext().postActivity; +} diff --git a/packages/component/src/hooks/useReferenceGrammarID.js b/packages/api/src/hooks/useReferenceGrammarID.js similarity index 66% rename from packages/component/src/hooks/useReferenceGrammarID.js rename to packages/api/src/hooks/useReferenceGrammarID.js index 95087dc9f4..7e1188319f 100644 --- a/packages/component/src/hooks/useReferenceGrammarID.js +++ b/packages/api/src/hooks/useReferenceGrammarID.js @@ -1,4 +1,4 @@ -import { useSelector } from '../WebChatReduxContext'; +import { useSelector } from './internal/WebChatReduxContext'; export default function useReferenceGrammarID() { return [useSelector(({ referenceGrammarID }) => referenceGrammarID)]; diff --git a/packages/component/src/hooks/useRelativeTimeFormatter.js b/packages/api/src/hooks/useRelativeTimeFormatter.js similarity index 100% rename from packages/component/src/hooks/useRelativeTimeFormatter.js rename to packages/api/src/hooks/useRelativeTimeFormatter.js diff --git a/packages/component/src/hooks/useRenderActivity.js b/packages/api/src/hooks/useRenderActivity.js similarity index 100% rename from packages/component/src/hooks/useRenderActivity.js rename to packages/api/src/hooks/useRenderActivity.js diff --git a/packages/component/src/hooks/useRenderActivityStatus.js b/packages/api/src/hooks/useRenderActivityStatus.js similarity index 91% rename from packages/component/src/hooks/useRenderActivityStatus.js rename to packages/api/src/hooks/useRenderActivityStatus.js index cda28ccba5..92daedd1a2 100644 --- a/packages/component/src/hooks/useRenderActivityStatus.js +++ b/packages/api/src/hooks/useRenderActivityStatus.js @@ -32,6 +32,8 @@ export default function useRenderActivityStatus({ activity, nextVisibleActivity return useMemo(() => { const renderActivityStatus = createActivityStatusRenderer({ activity, nextVisibleActivity }); - return renderActivityStatus || RETURN_FALSE; + console.log('useRenderActivityStatus', { renderActivityStatus }); + + return !!renderActivityStatus && renderActivityStatus; }, [activity, createActivityStatusRenderer, nextVisibleActivity]); } diff --git a/packages/api/src/hooks/useRenderAttachment.js b/packages/api/src/hooks/useRenderAttachment.js new file mode 100644 index 0000000000..4295676a4c --- /dev/null +++ b/packages/api/src/hooks/useRenderAttachment.js @@ -0,0 +1,21 @@ +import useCreateAttachmentRenderer from './useCreateAttachmentRenderer'; + +let showDeprecationNotes = true; + +export default function useRenderAttachment() { + if (showDeprecationNotes) { + console.warn( + 'botframework-webchat: "useRenderAttachment" is deprecated and will be removed on or after 2022-09-28. Please use "useCreateAttachmentRenderer()" instead.' + ); + + showDeprecationNotes = false; + } + + const createAttachmentRenderer = useCreateAttachmentRenderer(); + + return (...renderArgs) => { + const render = createAttachmentRenderer(...renderArgs); + + return !!render && render(); + }; +} diff --git a/packages/component/src/hooks/useRenderAvatar.js b/packages/api/src/hooks/useRenderAvatar.js similarity index 100% rename from packages/component/src/hooks/useRenderAvatar.js rename to packages/api/src/hooks/useRenderAvatar.js diff --git a/packages/component/src/hooks/useRenderMarkdownAsHTML.js b/packages/api/src/hooks/useRenderMarkdownAsHTML.js similarity index 73% rename from packages/component/src/hooks/useRenderMarkdownAsHTML.js rename to packages/api/src/hooks/useRenderMarkdownAsHTML.js index 250270429a..690ded2c29 100644 --- a/packages/component/src/hooks/useRenderMarkdownAsHTML.js +++ b/packages/api/src/hooks/useRenderMarkdownAsHTML.js @@ -1,10 +1,10 @@ import { useMemo } from 'react'; import useStyleOptions from '../hooks/useStyleOptions'; -import useWebChatUIContext from './internal/useWebChatUIContext'; +import useWebChatAPIContext from './internal/useWebChatAPIContext'; export default function useRenderMarkdownAsHTML() { - const { renderMarkdown } = useWebChatUIContext(); + const { renderMarkdown } = useWebChatAPIContext(); const [styleOptions] = useStyleOptions(); return useMemo(() => renderMarkdown && (markdown => renderMarkdown(markdown, styleOptions)), [ diff --git a/packages/api/src/hooks/useRenderToast.js b/packages/api/src/hooks/useRenderToast.js new file mode 100644 index 0000000000..5d64a57738 --- /dev/null +++ b/packages/api/src/hooks/useRenderToast.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useRenderToast() { + return useWebChatAPIContext().toastRenderer; +} diff --git a/packages/api/src/hooks/useRenderTypingIndicator.js b/packages/api/src/hooks/useRenderTypingIndicator.js new file mode 100644 index 0000000000..bb25d813f9 --- /dev/null +++ b/packages/api/src/hooks/useRenderTypingIndicator.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useRenderTypingIndicator() { + return useWebChatAPIContext().typingIndicatorRenderer; +} diff --git a/packages/api/src/hooks/useSendBoxValue.js b/packages/api/src/hooks/useSendBoxValue.js new file mode 100644 index 0000000000..ebc79211b5 --- /dev/null +++ b/packages/api/src/hooks/useSendBoxValue.js @@ -0,0 +1,6 @@ +import { useSelector } from './internal/WebChatReduxContext'; +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useSendBoxValue() { + return [useSelector(({ sendBoxValue }) => sendBoxValue), useWebChatAPIContext().setSendBox]; +} diff --git a/packages/api/src/hooks/useSendEvent.js b/packages/api/src/hooks/useSendEvent.js new file mode 100644 index 0000000000..c5608fa39d --- /dev/null +++ b/packages/api/src/hooks/useSendEvent.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useSendEvent() { + return useWebChatAPIContext().sendEvent; +} diff --git a/packages/component/src/hooks/useSendFiles.js b/packages/api/src/hooks/useSendFiles.js similarity index 93% rename from packages/component/src/hooks/useSendFiles.js rename to packages/api/src/hooks/useSendFiles.js index 989930f2d8..bee7806bc9 100644 --- a/packages/component/src/hooks/useSendFiles.js +++ b/packages/api/src/hooks/useSendFiles.js @@ -2,11 +2,11 @@ import { useCallback } from 'react'; -import downscaleImageToDataURL from '../Utils/downscaleImageToDataURL'; +import downscaleImageToDataURL from '../utils/downscaleImageToDataURL'; import useStyleOptions from '../hooks/useStyleOptions'; import useTrackEvent from '../hooks/useTrackEvent'; import useTrackTiming from '../hooks/useTrackTiming'; -import useWebChatUIContext from './internal/useWebChatUIContext'; +import useWebChatAPIContext from './internal/useWebChatAPIContext'; function canMakeThumbnail({ name }) { return /\.(gif|jpe?g|png)$/iu.test(name); @@ -21,7 +21,7 @@ async function makeThumbnail(file, width, height, contentType, quality) { } export default function useSendFiles() { - const { sendFiles } = useWebChatUIContext(); + const { sendFiles } = useWebChatAPIContext(); const [ { enableUploadThumbnail, diff --git a/packages/api/src/hooks/useSendMessage.js b/packages/api/src/hooks/useSendMessage.js new file mode 100644 index 0000000000..556f7832e7 --- /dev/null +++ b/packages/api/src/hooks/useSendMessage.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useSendMessage() { + return useWebChatAPIContext().sendMessage; +} diff --git a/packages/api/src/hooks/useSendMessageBack.js b/packages/api/src/hooks/useSendMessageBack.js new file mode 100644 index 0000000000..0670804a31 --- /dev/null +++ b/packages/api/src/hooks/useSendMessageBack.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useSendMessageBack() { + return useWebChatAPIContext().sendMessageBack; +} diff --git a/packages/api/src/hooks/useSendPostBack.js b/packages/api/src/hooks/useSendPostBack.js new file mode 100644 index 0000000000..94dbf9540c --- /dev/null +++ b/packages/api/src/hooks/useSendPostBack.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useSendPostBack() { + return useWebChatAPIContext().sendPostBack; +} diff --git a/packages/component/src/hooks/useSendTimeoutForActivity.js b/packages/api/src/hooks/useSendTimeoutForActivity.js similarity index 100% rename from packages/component/src/hooks/useSendTimeoutForActivity.js rename to packages/api/src/hooks/useSendTimeoutForActivity.js diff --git a/packages/component/src/hooks/useSendTypingIndicator.js b/packages/api/src/hooks/useSendTypingIndicator.js similarity index 67% rename from packages/component/src/hooks/useSendTypingIndicator.js rename to packages/api/src/hooks/useSendTypingIndicator.js index 2ddf79fa48..dcc67ad32e 100644 --- a/packages/component/src/hooks/useSendTypingIndicator.js +++ b/packages/api/src/hooks/useSendTypingIndicator.js @@ -1,4 +1,4 @@ -import { useSelector } from '../WebChatReduxContext'; +import { useSelector } from './internal/WebChatReduxContext'; export default function useSendTypingIndicator() { return [useSelector(({ sendTypingIndicator }) => sendTypingIndicator)]; diff --git a/packages/api/src/hooks/useSetNotification.js b/packages/api/src/hooks/useSetNotification.js new file mode 100644 index 0000000000..ea734c9940 --- /dev/null +++ b/packages/api/src/hooks/useSetNotification.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useSetNotification() { + return useWebChatAPIContext().setNotification; +} diff --git a/packages/component/src/hooks/useShouldSpeakIncomingActivity.js b/packages/api/src/hooks/useShouldSpeakIncomingActivity.js similarity index 74% rename from packages/component/src/hooks/useShouldSpeakIncomingActivity.js rename to packages/api/src/hooks/useShouldSpeakIncomingActivity.js index f63f520e2c..809eae19e5 100644 --- a/packages/component/src/hooks/useShouldSpeakIncomingActivity.js +++ b/packages/api/src/hooks/useShouldSpeakIncomingActivity.js @@ -1,10 +1,10 @@ import { useCallback } from 'react'; -import { useSelector } from '../WebChatReduxContext'; -import useWebChatUIContext from './internal/useWebChatUIContext'; +import { useSelector } from './internal/WebChatReduxContext'; +import useWebChatAPIContext from './internal/useWebChatAPIContext'; export default function useShouldSpeakIncomingActivity() { - const { startSpeakingActivity, stopSpeakingActivity } = useWebChatUIContext(); + const { startSpeakingActivity, stopSpeakingActivity } = useWebChatAPIContext(); return [ useSelector(({ shouldSpeakIncomingActivity }) => shouldSpeakIncomingActivity), diff --git a/packages/api/src/hooks/useStartDictate.js b/packages/api/src/hooks/useStartDictate.js new file mode 100644 index 0000000000..8b60dd7526 --- /dev/null +++ b/packages/api/src/hooks/useStartDictate.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useStartDictate() { + return useWebChatAPIContext().startDictate; +} diff --git a/packages/api/src/hooks/useStopDictate.js b/packages/api/src/hooks/useStopDictate.js new file mode 100644 index 0000000000..e9d1f5acd6 --- /dev/null +++ b/packages/api/src/hooks/useStopDictate.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useStopDictate() { + return useWebChatAPIContext().stopDictate; +} diff --git a/packages/api/src/hooks/useStyleOptions.js b/packages/api/src/hooks/useStyleOptions.js new file mode 100644 index 0000000000..257cc74d8a --- /dev/null +++ b/packages/api/src/hooks/useStyleOptions.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useStyleOptions() { + return [useWebChatAPIContext().styleOptions]; +} diff --git a/packages/component/src/hooks/useSubmitSendBox.js b/packages/api/src/hooks/useSubmitSendBox.js similarity index 78% rename from packages/component/src/hooks/useSubmitSendBox.js rename to packages/api/src/hooks/useSubmitSendBox.js index 67d1e11317..b63c8c4f25 100644 --- a/packages/component/src/hooks/useSubmitSendBox.js +++ b/packages/api/src/hooks/useSubmitSendBox.js @@ -1,10 +1,10 @@ import { useCallback } from 'react'; import useTrackEvent from './useTrackEvent'; -import useWebChatUIContext from './internal/useWebChatUIContext'; +import useWebChatAPIContext from './internal/useWebChatAPIContext'; export default function useSubmitSendBox() { - const { submitSendBox } = useWebChatUIContext(); + const { submitSendBox } = useWebChatAPIContext(); const trackEvent = useTrackEvent(); return useCallback( diff --git a/packages/component/src/hooks/useSuggestedActions.js b/packages/api/src/hooks/useSuggestedActions.js similarity index 69% rename from packages/component/src/hooks/useSuggestedActions.js rename to packages/api/src/hooks/useSuggestedActions.js index 5f8575a901..81037ca841 100644 --- a/packages/component/src/hooks/useSuggestedActions.js +++ b/packages/api/src/hooks/useSuggestedActions.js @@ -1,11 +1,11 @@ import { useCallback } from 'react'; -import { useSelector } from '../WebChatReduxContext'; -import useWebChatUIContext from './internal/useWebChatUIContext'; +import { useSelector } from './internal/WebChatReduxContext'; +import useWebChatAPIContext from './internal/useWebChatAPIContext'; export default function useSuggestedActions() { const value = useSelector(({ suggestedActions }) => suggestedActions); - const { clearSuggestedActions } = useWebChatUIContext(); + const { clearSuggestedActions } = useWebChatAPIContext(); return [ value, diff --git a/packages/component/src/hooks/useTimeoutForSend.js b/packages/api/src/hooks/useTimeoutForSend.js similarity index 100% rename from packages/component/src/hooks/useTimeoutForSend.js rename to packages/api/src/hooks/useTimeoutForSend.js diff --git a/packages/api/src/hooks/useTrackDimension.js b/packages/api/src/hooks/useTrackDimension.js new file mode 100644 index 0000000000..d40449fd98 --- /dev/null +++ b/packages/api/src/hooks/useTrackDimension.js @@ -0,0 +1,7 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useTrackDimension() { + const { trackDimension } = useWebChatAPIContext(); + + return trackDimension; +} diff --git a/packages/component/src/hooks/useTrackEvent.js b/packages/api/src/hooks/useTrackEvent.js similarity index 86% rename from packages/component/src/hooks/useTrackEvent.js rename to packages/api/src/hooks/useTrackEvent.js index 61aaea9180..77edbfbe7e 100644 --- a/packages/component/src/hooks/useTrackEvent.js +++ b/packages/api/src/hooks/useTrackEvent.js @@ -1,19 +1,16 @@ import { useCallback, useMemo } from 'react'; -import createCustomEvent from '../Utils/createCustomEvent'; +import createCustomEvent from '../utils/createCustomEvent'; +import isObject from '../utils/isObject'; import useReadTelemetryDimensions from './internal/useReadTelemetryDimensions'; -import useWebChatUIContext from './internal/useWebChatUIContext'; +import useWebChatAPIContext from './internal/useWebChatAPIContext'; function isNonNegativeFiniteNumberOrString(value) { return (typeof value === 'number' && isFinite(value) && value >= 0) || typeof value === 'string'; } -function isObject(value) { - return Object.prototype.toString.call(value) === '[object Object]'; -} - export default function useTrackEvent() { - const { onTelemetry } = useWebChatUIContext(); + const { onTelemetry } = useWebChatAPIContext(); const readTelemetryDimensions = useReadTelemetryDimensions(); const trackEvent = useCallback( diff --git a/packages/component/src/hooks/useTrackException.js b/packages/api/src/hooks/useTrackException.js similarity index 80% rename from packages/component/src/hooks/useTrackException.js rename to packages/api/src/hooks/useTrackException.js index 18e3134ad5..bff37e75b2 100644 --- a/packages/component/src/hooks/useTrackException.js +++ b/packages/api/src/hooks/useTrackException.js @@ -1,11 +1,11 @@ import { useCallback } from 'react'; -import createCustomEvent from '../Utils/createCustomEvent'; +import createCustomEvent from '../utils/createCustomEvent'; import useReadTelemetryDimensions from './internal/useReadTelemetryDimensions'; -import useWebChatUIContext from './internal/useWebChatUIContext'; +import useWebChatAPIContext from './internal/useWebChatAPIContext'; export default function useTrackException() { - const { onTelemetry } = useWebChatUIContext(); + const { onTelemetry } = useWebChatAPIContext(); const readTelemetryDimensions = useReadTelemetryDimensions(); return useCallback( diff --git a/packages/component/src/hooks/useTrackTiming.js b/packages/api/src/hooks/useTrackTiming.js similarity index 88% rename from packages/component/src/hooks/useTrackTiming.js rename to packages/api/src/hooks/useTrackTiming.js index ed92364df3..1bd8a66ee4 100644 --- a/packages/component/src/hooks/useTrackTiming.js +++ b/packages/api/src/hooks/useTrackTiming.js @@ -1,13 +1,13 @@ import { useCallback } from 'react'; -import createCustomEvent from '../Utils/createCustomEvent'; -import randomId from '../Utils/randomId'; +import createCustomEvent from '../utils/createCustomEvent'; +import randomId from '../utils/randomId'; import useReadTelemetryDimensions from './internal/useReadTelemetryDimensions'; import useTrackException from './useTrackException'; -import useWebChatUIContext from './internal/useWebChatUIContext'; +import useWebChatAPIContext from './internal/useWebChatAPIContext'; export default function useTrackTiming() { - const { onTelemetry } = useWebChatUIContext(); + const { onTelemetry } = useWebChatAPIContext(); const readTelemetryDimensions = useReadTelemetryDimensions(); const trackException = useTrackException(); diff --git a/packages/api/src/hooks/useUserID.js b/packages/api/src/hooks/useUserID.js new file mode 100644 index 0000000000..3ad52d62a5 --- /dev/null +++ b/packages/api/src/hooks/useUserID.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useUserID() { + return [useWebChatAPIContext().userID]; +} diff --git a/packages/api/src/hooks/useUsername.js b/packages/api/src/hooks/useUsername.js new file mode 100644 index 0000000000..50a1bbb973 --- /dev/null +++ b/packages/api/src/hooks/useUsername.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useUsername() { + return [useWebChatAPIContext().username]; +} diff --git a/packages/component/src/hooks/useVoiceSelector.js b/packages/api/src/hooks/useVoiceSelector.js similarity index 62% rename from packages/component/src/hooks/useVoiceSelector.js rename to packages/api/src/hooks/useVoiceSelector.js index 821b71f07c..1fcfb9c119 100644 --- a/packages/component/src/hooks/useVoiceSelector.js +++ b/packages/api/src/hooks/useVoiceSelector.js @@ -1,8 +1,8 @@ import { useCallback } from 'react'; -import useWebChatUIContext from './internal/useWebChatUIContext'; +import useWebChatAPIContext from './internal/useWebChatAPIContext'; export default function useVoiceSelector(activity) { - const context = useWebChatUIContext(); + const context = useWebChatAPIContext(); return useCallback(voices => context.selectVoice(voices, activity), [activity, context]); } diff --git a/packages/api/src/hooks/useWebSpeechPonyfill.js b/packages/api/src/hooks/useWebSpeechPonyfill.js new file mode 100644 index 0000000000..63ba5166a1 --- /dev/null +++ b/packages/api/src/hooks/useWebSpeechPonyfill.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useWebSpeechPonyfill() { + return [useWebChatAPIContext().webSpeechPonyfill]; +} diff --git a/packages/component/src/ErrorBoundary.js b/packages/api/src/hooks/utils/ErrorBoundary.js similarity index 51% rename from packages/component/src/ErrorBoundary.js rename to packages/api/src/hooks/utils/ErrorBoundary.js index 15a8dab035..a285dea34c 100644 --- a/packages/component/src/ErrorBoundary.js +++ b/packages/api/src/hooks/utils/ErrorBoundary.js @@ -2,24 +2,25 @@ import PropTypes from 'prop-types'; import React from 'react'; class ErrorBoundary extends React.Component { - // Currently, all errors caught are fatal errors. - // We will bubble up the error and let React unmount us. + constructor() { + super(); + + this.state = { error: undefined }; + } + componentDidCatch(error) { - const { onError } = this.props; - const errorEvent = new ErrorEvent('error', { error }); + this.setState({ error }); - onError && onError(errorEvent); + this.props.onError(error); } render() { - const { children } = this.props; - - return children; + return !this.state.error && this.props.children; } } ErrorBoundary.defaultProps = { - children: false, + children: undefined, onError: undefined }; diff --git a/packages/api/src/hooks/utils/singleToArray.js b/packages/api/src/hooks/utils/singleToArray.js new file mode 100644 index 0000000000..873ed8ef89 --- /dev/null +++ b/packages/api/src/hooks/utils/singleToArray.js @@ -0,0 +1,3 @@ +export default function singleToArray(singleOrArray) { + return singleOrArray ? (Array.isArray(singleOrArray) ? singleOrArray : [singleOrArray]) : []; +} diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts new file mode 100644 index 0000000000..3812cb9197 --- /dev/null +++ b/packages/api/src/index.ts @@ -0,0 +1,4 @@ +import * as hooks from './hooks'; +import Composer from './hooks/Composer'; + +export { Composer, hooks }; diff --git a/packages/component/src/Localization/Localize.js b/packages/api/src/localization/Localize.js similarity index 96% rename from packages/component/src/Localization/Localize.js rename to packages/api/src/localization/Localize.js index 41cce9cc4a..467b953a39 100644 --- a/packages/component/src/Localization/Localize.js +++ b/packages/api/src/localization/Localize.js @@ -4,7 +4,7 @@ import deprecatingGetLocaleString from './getLocaleString'; import getAllLocalizedStrings from './getAllLocalizedStrings'; import getRTLList from './getRTLList'; -import normalizeLanguage from '../Utils/normalizeLanguage'; +import normalizeLanguage from '../utils/normalizeLanguage'; import useLocalizer from '../hooks/useLocalizer'; let deprecationNotesShown; diff --git a/packages/component/src/Localization/ar-EG.json b/packages/api/src/localization/ar-EG.json similarity index 100% rename from packages/component/src/Localization/ar-EG.json rename to packages/api/src/localization/ar-EG.json diff --git a/packages/component/src/Localization/ar-JO.json b/packages/api/src/localization/ar-JO.json similarity index 100% rename from packages/component/src/Localization/ar-JO.json rename to packages/api/src/localization/ar-JO.json diff --git a/packages/component/src/Localization/ar-SA.json b/packages/api/src/localization/ar-SA.json similarity index 100% rename from packages/component/src/Localization/ar-SA.json rename to packages/api/src/localization/ar-SA.json diff --git a/packages/component/src/Localization/bg-BG.json b/packages/api/src/localization/bg-BG.json similarity index 100% rename from packages/component/src/Localization/bg-BG.json rename to packages/api/src/localization/bg-BG.json diff --git a/packages/component/src/Localization/ca-ES.json b/packages/api/src/localization/ca-ES.json similarity index 100% rename from packages/component/src/Localization/ca-ES.json rename to packages/api/src/localization/ca-ES.json diff --git a/packages/component/src/Localization/cs-CZ.json b/packages/api/src/localization/cs-CZ.json similarity index 100% rename from packages/component/src/Localization/cs-CZ.json rename to packages/api/src/localization/cs-CZ.json diff --git a/packages/component/src/Localization/da-DK.json b/packages/api/src/localization/da-DK.json similarity index 100% rename from packages/component/src/Localization/da-DK.json rename to packages/api/src/localization/da-DK.json diff --git a/packages/component/src/Localization/de-DE.json b/packages/api/src/localization/de-DE.json similarity index 100% rename from packages/component/src/Localization/de-DE.json rename to packages/api/src/localization/de-DE.json diff --git a/packages/component/src/Localization/el-GR.json b/packages/api/src/localization/el-GR.json similarity index 100% rename from packages/component/src/Localization/el-GR.json rename to packages/api/src/localization/el-GR.json diff --git a/packages/component/src/Localization/en-US.json b/packages/api/src/localization/en-US.json similarity index 100% rename from packages/component/src/Localization/en-US.json rename to packages/api/src/localization/en-US.json diff --git a/packages/component/src/Localization/es-ES.json b/packages/api/src/localization/es-ES.json similarity index 100% rename from packages/component/src/Localization/es-ES.json rename to packages/api/src/localization/es-ES.json diff --git a/packages/component/src/Localization/et-EE.json b/packages/api/src/localization/et-EE.json similarity index 100% rename from packages/component/src/Localization/et-EE.json rename to packages/api/src/localization/et-EE.json diff --git a/packages/component/src/Localization/eu-ES.json b/packages/api/src/localization/eu-ES.json similarity index 100% rename from packages/component/src/Localization/eu-ES.json rename to packages/api/src/localization/eu-ES.json diff --git a/packages/component/src/Localization/fi-FI.json b/packages/api/src/localization/fi-FI.json similarity index 100% rename from packages/component/src/Localization/fi-FI.json rename to packages/api/src/localization/fi-FI.json diff --git a/packages/component/src/Localization/fr-FR.json b/packages/api/src/localization/fr-FR.json similarity index 100% rename from packages/component/src/Localization/fr-FR.json rename to packages/api/src/localization/fr-FR.json diff --git a/packages/component/src/Localization/getAllLocalizedStrings.js b/packages/api/src/localization/getAllLocalizedStrings.js similarity index 100% rename from packages/component/src/Localization/getAllLocalizedStrings.js rename to packages/api/src/localization/getAllLocalizedStrings.js diff --git a/packages/component/src/Localization/getAllLocalizedStrings.spec.js b/packages/api/src/localization/getAllLocalizedStrings.spec.js similarity index 100% rename from packages/component/src/Localization/getAllLocalizedStrings.spec.js rename to packages/api/src/localization/getAllLocalizedStrings.spec.js diff --git a/packages/component/src/Localization/getLocaleString.js b/packages/api/src/localization/getLocaleString.js similarity index 73% rename from packages/component/src/Localization/getLocaleString.js rename to packages/api/src/localization/getLocaleString.js index 5a60db42ab..a5a59965cd 100644 --- a/packages/component/src/Localization/getLocaleString.js +++ b/packages/api/src/localization/getLocaleString.js @@ -1,4 +1,4 @@ -import PrecompiledGlobalize from '../Utils/PrecompiledGlobalize'; +import PrecompiledGlobalize from '../external/PrecompiledGlobalize'; export default function getLocaleString(value, language) { const globalize = PrecompiledGlobalize(language); diff --git a/packages/component/src/Localization/getRTLList.js b/packages/api/src/localization/getRTLList.js similarity index 100% rename from packages/component/src/Localization/getRTLList.js rename to packages/api/src/localization/getRTLList.js diff --git a/packages/component/src/Localization/gl-ES.json b/packages/api/src/localization/gl-ES.json similarity index 100% rename from packages/component/src/Localization/gl-ES.json rename to packages/api/src/localization/gl-ES.json diff --git a/packages/component/src/Localization/he-IL.json b/packages/api/src/localization/he-IL.json similarity index 100% rename from packages/component/src/Localization/he-IL.json rename to packages/api/src/localization/he-IL.json diff --git a/packages/component/src/Localization/hi-IN.json b/packages/api/src/localization/hi-IN.json similarity index 100% rename from packages/component/src/Localization/hi-IN.json rename to packages/api/src/localization/hi-IN.json diff --git a/packages/component/src/Localization/hr-HR.json b/packages/api/src/localization/hr-HR.json similarity index 100% rename from packages/component/src/Localization/hr-HR.json rename to packages/api/src/localization/hr-HR.json diff --git a/packages/component/src/Localization/hu-HU.json b/packages/api/src/localization/hu-HU.json similarity index 100% rename from packages/component/src/Localization/hu-HU.json rename to packages/api/src/localization/hu-HU.json diff --git a/packages/component/src/Localization/id-ID.json b/packages/api/src/localization/id-ID.json similarity index 100% rename from packages/component/src/Localization/id-ID.json rename to packages/api/src/localization/id-ID.json diff --git a/packages/component/src/Localization/it-IT.json b/packages/api/src/localization/it-IT.json similarity index 100% rename from packages/component/src/Localization/it-IT.json rename to packages/api/src/localization/it-IT.json diff --git a/packages/component/src/Localization/ja-JP.json b/packages/api/src/localization/ja-JP.json similarity index 100% rename from packages/component/src/Localization/ja-JP.json rename to packages/api/src/localization/ja-JP.json diff --git a/packages/component/src/Localization/kk-KZ.json b/packages/api/src/localization/kk-KZ.json similarity index 100% rename from packages/component/src/Localization/kk-KZ.json rename to packages/api/src/localization/kk-KZ.json diff --git a/packages/component/src/Localization/ko-KR.json b/packages/api/src/localization/ko-KR.json similarity index 100% rename from packages/component/src/Localization/ko-KR.json rename to packages/api/src/localization/ko-KR.json diff --git a/packages/component/src/Localization/lt-LT.json b/packages/api/src/localization/lt-LT.json similarity index 100% rename from packages/component/src/Localization/lt-LT.json rename to packages/api/src/localization/lt-LT.json diff --git a/packages/component/src/Localization/lv-LV.json b/packages/api/src/localization/lv-LV.json similarity index 100% rename from packages/component/src/Localization/lv-LV.json rename to packages/api/src/localization/lv-LV.json diff --git a/packages/component/src/Localization/mergeLocalizedStrings.js b/packages/api/src/localization/mergeLocalizedStrings.js similarity index 100% rename from packages/component/src/Localization/mergeLocalizedStrings.js rename to packages/api/src/localization/mergeLocalizedStrings.js diff --git a/packages/component/src/Localization/ms-MY.json b/packages/api/src/localization/ms-MY.json similarity index 100% rename from packages/component/src/Localization/ms-MY.json rename to packages/api/src/localization/ms-MY.json diff --git a/packages/component/src/Localization/nb-NO.json b/packages/api/src/localization/nb-NO.json similarity index 100% rename from packages/component/src/Localization/nb-NO.json rename to packages/api/src/localization/nb-NO.json diff --git a/packages/component/src/Localization/nl-NL.json b/packages/api/src/localization/nl-NL.json similarity index 100% rename from packages/component/src/Localization/nl-NL.json rename to packages/api/src/localization/nl-NL.json diff --git a/packages/component/src/Localization/overrides.json b/packages/api/src/localization/overrides.json similarity index 100% rename from packages/component/src/Localization/overrides.json rename to packages/api/src/localization/overrides.json diff --git a/packages/component/src/Localization/pl-PL.json b/packages/api/src/localization/pl-PL.json similarity index 100% rename from packages/component/src/Localization/pl-PL.json rename to packages/api/src/localization/pl-PL.json diff --git a/packages/component/src/Localization/pt-BR.json b/packages/api/src/localization/pt-BR.json similarity index 100% rename from packages/component/src/Localization/pt-BR.json rename to packages/api/src/localization/pt-BR.json diff --git a/packages/component/src/Localization/pt-PT.json b/packages/api/src/localization/pt-PT.json similarity index 100% rename from packages/component/src/Localization/pt-PT.json rename to packages/api/src/localization/pt-PT.json diff --git a/packages/component/src/Localization/ro-RO.json b/packages/api/src/localization/ro-RO.json similarity index 100% rename from packages/component/src/Localization/ro-RO.json rename to packages/api/src/localization/ro-RO.json diff --git a/packages/component/src/Localization/ru-RU.json b/packages/api/src/localization/ru-RU.json similarity index 100% rename from packages/component/src/Localization/ru-RU.json rename to packages/api/src/localization/ru-RU.json diff --git a/packages/component/src/Localization/sk-SK.json b/packages/api/src/localization/sk-SK.json similarity index 100% rename from packages/component/src/Localization/sk-SK.json rename to packages/api/src/localization/sk-SK.json diff --git a/packages/component/src/Localization/sl-SI.json b/packages/api/src/localization/sl-SI.json similarity index 100% rename from packages/component/src/Localization/sl-SI.json rename to packages/api/src/localization/sl-SI.json diff --git a/packages/component/src/Localization/sl-SL.json b/packages/api/src/localization/sl-SL.json similarity index 100% rename from packages/component/src/Localization/sl-SL.json rename to packages/api/src/localization/sl-SL.json diff --git a/packages/component/src/Localization/sr-Cyrl-CS.json b/packages/api/src/localization/sr-Cyrl-CS.json similarity index 100% rename from packages/component/src/Localization/sr-Cyrl-CS.json rename to packages/api/src/localization/sr-Cyrl-CS.json diff --git a/packages/component/src/Localization/sr-Cyrl.json b/packages/api/src/localization/sr-Cyrl.json similarity index 100% rename from packages/component/src/Localization/sr-Cyrl.json rename to packages/api/src/localization/sr-Cyrl.json diff --git a/packages/component/src/Localization/sr-Latn-CS.json b/packages/api/src/localization/sr-Latn-CS.json similarity index 100% rename from packages/component/src/Localization/sr-Latn-CS.json rename to packages/api/src/localization/sr-Latn-CS.json diff --git a/packages/component/src/Localization/sr-Latn.json b/packages/api/src/localization/sr-Latn.json similarity index 100% rename from packages/component/src/Localization/sr-Latn.json rename to packages/api/src/localization/sr-Latn.json diff --git a/packages/component/src/Localization/sv-SE.json b/packages/api/src/localization/sv-SE.json similarity index 100% rename from packages/component/src/Localization/sv-SE.json rename to packages/api/src/localization/sv-SE.json diff --git a/packages/component/src/Localization/th-TH.json b/packages/api/src/localization/th-TH.json similarity index 100% rename from packages/component/src/Localization/th-TH.json rename to packages/api/src/localization/th-TH.json diff --git a/packages/component/src/Localization/tr-TR.json b/packages/api/src/localization/tr-TR.json similarity index 100% rename from packages/component/src/Localization/tr-TR.json rename to packages/api/src/localization/tr-TR.json diff --git a/packages/component/src/Localization/uk-UA.json b/packages/api/src/localization/uk-UA.json similarity index 100% rename from packages/component/src/Localization/uk-UA.json rename to packages/api/src/localization/uk-UA.json diff --git a/packages/component/src/Localization/vi-VN.json b/packages/api/src/localization/vi-VN.json similarity index 100% rename from packages/component/src/Localization/vi-VN.json rename to packages/api/src/localization/vi-VN.json diff --git a/packages/component/src/Localization/yue.json b/packages/api/src/localization/yue.json similarity index 100% rename from packages/component/src/Localization/yue.json rename to packages/api/src/localization/yue.json diff --git a/packages/component/src/Localization/zh-CN.json b/packages/api/src/localization/zh-CN.json similarity index 100% rename from packages/component/src/Localization/zh-CN.json rename to packages/api/src/localization/zh-CN.json diff --git a/packages/component/src/Localization/zh-HK.json b/packages/api/src/localization/zh-HK.json similarity index 100% rename from packages/component/src/Localization/zh-HK.json rename to packages/api/src/localization/zh-HK.json diff --git a/packages/component/src/Localization/zh-TW.json b/packages/api/src/localization/zh-TW.json similarity index 100% rename from packages/component/src/Localization/zh-TW.json rename to packages/api/src/localization/zh-TW.json diff --git a/packages/api/src/patchStyleOptions.js b/packages/api/src/patchStyleOptions.js new file mode 100644 index 0000000000..f968e99dd0 --- /dev/null +++ b/packages/api/src/patchStyleOptions.js @@ -0,0 +1,194 @@ +import defaultStyleOptions from './defaultStyleOptions'; + +// TODO: [P4] We should add a notice for people who want to use "styleSet" instead of "styleOptions". +// "styleSet" is actually CSS stylesheet and it is based on the DOM tree. +// DOM tree may change from time to time, thus, maintaining "styleSet" becomes a constant effort. + +function parseBorder(border) { + const dummyElement = document.createElement('div'); + + dummyElement.setAttribute('style', `border: ${border}`); + + const { + style: { borderColor: color, borderStyle: style, borderWidth: width } + } = dummyElement; + + return { + color, + style, + width + }; +} + +const PIXEL_UNIT_PATTERN = /^\d+px$/u; + +export default function patchStyleOptions( + options, + { groupTimestamp: groupTimestampFromProps, sendTimeout: sendTimeoutFromProps } +) { + options = { ...defaultStyleOptions, ...options }; + + // Keep this list flat (no nested style) and serializable (no functions) + + // TODO: [P4] Deprecate this code after bump to v5 + const { + bubbleBorder, + bubbleFromUserBorder, + bubbleFromUserNubOffset, + bubbleNubOffset, + emojiSet, + groupTimestamp, + sendTimeout, + suggestedActionBorder, + suggestedActionDisabledBorder + } = options; + + if (bubbleBorder) { + console.warn( + 'botframework-webchat: "styleSet.bubbleBorder" is deprecated and will be removed on or after 2020-07-17. Please use "bubbleBorderColor", "bubbleBorderStyle", and, "bubbleBorderWidth.' + ); + + const { color, style, width } = parseBorder(bubbleBorder); + + if (color && color !== 'initial') { + options.bubbleBorderColor = color; + } + + if (style && style !== 'initial') { + options.bubbleBorderStyle = style; + } + + if (PIXEL_UNIT_PATTERN.test(width)) { + options.bubbleBorderWidth = parseInt(width, 10); + } + } + + if (bubbleFromUserBorder) { + console.warn( + 'botframework-webchat: "styleSet.bubbleFromUserBorder" is deprecated and will be removed on or after 2020-07-17. Please use "bubbleFromUserBorderColor", "bubbleFromUserBorderStyle", and, "bubbleFromUserBorderWidth".' + ); + + const { color, style, width } = parseBorder(bubbleFromUserBorder); + + if (color && color !== 'initial') { + options.bubbleFromUserBorderColor = color; + } + + if (style && style !== 'initial') { + options.bubbleFromUserBorderStyle = style; + } + + if (PIXEL_UNIT_PATTERN.test(width)) { + options.bubbleFromUserBorderWidth = parseInt(width, 10); + } + } + + if (suggestedActionBorder) { + console.warn( + 'botframework-webchat: "styleSet.suggestedActionBorder" is deprecated and will be removed on or after 2020-09-11. Please use "suggestedActionBorderColor", "suggestedActionBorderStyle", and, "suggestedActionBorderWidth".' + ); + + const { color, style, width } = parseBorder(suggestedActionBorder); + + if (color && color !== 'initial') { + options.suggestedActionBorderColor = color; + } + + if (style && style !== 'initial') { + options.suggestedActionBorderStyle = style; + } + + if (PIXEL_UNIT_PATTERN.test(width)) { + options.suggestedActionBorderWidth = parseInt(width, 10); + } + } + + if (suggestedActionDisabledBorder) { + console.warn( + 'botframework-webcaht: "styleSet.suggestedActionDisabledBorder" is deprecated and will be removed on or after 2020-09-11. Please use "suggestedActionDisabledBorderColor", "suggestedActionDisabledBorderStyle", and, "suggestedActionDisabledBorderWidth".' + ); + + const { color, style, width } = parseBorder(suggestedActionDisabledBorder); + + if (color && color !== 'initial') { + options.suggestedActionDisabledBorderColor = color; + } + + if (style && style !== 'initial') { + options.suggestedActionDisabledBorderStyle = style; + } + + if (PIXEL_UNIT_PATTERN.test(width)) { + options.suggestedActionDisabledBorderWidth = parseInt(width, 10); + } + } + + if (bubbleFromUserNubOffset === 'top') { + options.bubbleFromUserNubOffset = 0; + } else if (typeof bubbleFromUserNubOffset !== 'number') { + options.bubbleFromUserNubOffset = -0; + } + + if (bubbleNubOffset === 'top') { + options.bubbleNubOffset = 0; + } else if (typeof bubbleNubOffset !== 'number') { + options.bubbleNubOffset = -0; + } + + if (emojiSet === true) { + options.emojiSet = { + ':)': '😊', + ':-)': '😊', + '(:': '😊', + '(-:': '😊', + ':-|': '😐', + ':|': '😐', + ':-(': '☹️', + ':(': '☹️', + ':-D': '😀', + ':D': '😀', + ':-p': '😛', + ':p': '😛', + ':-P': '😛', + ':P': '😛', + ':-o': '😲', + ':o': '😲', + ':O': '😲', + ':-O': '😲', + ':-0': '😲', + ':0': '😲', + ';-)': '😉', + ';)': '😉', + '<3': '❤️', + ' { + result[key] = mapper(value, key); + + return result; + }, {}); +} diff --git a/packages/api/src/utils/mapMap.spec.js b/packages/api/src/utils/mapMap.spec.js new file mode 100644 index 0000000000..9132e2ce93 --- /dev/null +++ b/packages/api/src/utils/mapMap.spec.js @@ -0,0 +1,9 @@ +import mapMap from './mapMap'; + +test('multiple a map by 10', () => { + const map = { ten: 1, twenty: 2 }; + const actual = mapMap(map, value => value * 10); + + expect(actual).toEqual({ ten: 10, twenty: 20 }); + expect(actual).not.toBe(map); +}); diff --git a/packages/component/src/Utils/normalizeLanguage.js b/packages/api/src/utils/normalizeLanguage.js similarity index 100% rename from packages/component/src/Utils/normalizeLanguage.js rename to packages/api/src/utils/normalizeLanguage.js diff --git a/packages/component/src/Utils/normalizeLanguage.spec.js b/packages/api/src/utils/normalizeLanguage.spec.js similarity index 100% rename from packages/component/src/Utils/normalizeLanguage.spec.js rename to packages/api/src/utils/normalizeLanguage.spec.js diff --git a/packages/component/src/Utils/observableToPromise.js b/packages/api/src/utils/observableToPromise.js similarity index 100% rename from packages/component/src/Utils/observableToPromise.js rename to packages/api/src/utils/observableToPromise.js diff --git a/packages/api/src/utils/randomId.js b/packages/api/src/utils/randomId.js new file mode 100644 index 0000000000..73de08435b --- /dev/null +++ b/packages/api/src/utils/randomId.js @@ -0,0 +1,7 @@ +/* eslint no-magic-numbers: ["error", { "ignore": [2, 5, 36] }] */ + +import random from 'math-random'; + +export default function randomId(maxLength = 5) { + return random().toString(36).substr(2, maxLength); +} diff --git a/packages/bundle/package.json b/packages/bundle/package.json index b2d3af862a..fae26d6020 100644 --- a/packages/bundle/package.json +++ b/packages/bundle/package.json @@ -74,7 +74,7 @@ "isomorphic-react": "^0.0.0-0", "isomorphic-react-dom": "^0.0.0-0", "prettier": "^2.1.1", - "source-map-loader": "^1.0.2", + "source-map-loader": "^1.1.0", "terser-webpack-plugin": "^4.1.0", "typescript": "^4.0.2", "webpack": "^4.44.1", diff --git a/packages/bundle/src/FullComposer.js b/packages/bundle/src/FullComposer.js index 7991c5ccdf..24a1d10d97 100644 --- a/packages/bundle/src/FullComposer.js +++ b/packages/bundle/src/FullComposer.js @@ -1,9 +1,8 @@ +import { Components } from 'botframework-webchat-component'; import PropTypes from 'prop-types'; import React from 'react'; import AdaptiveCardsComposer from './adaptiveCards/AdaptiveCardsComposer'; -import { Components } from 'botframework-webchat-component'; - import useComposerProps from './useComposerProps'; const { Composer } = Components; diff --git a/packages/component/package.json b/packages/component/package.json index 56b6fcce9a..3e0e248745 100644 --- a/packages/component/package.json +++ b/packages/component/package.json @@ -17,18 +17,15 @@ }, "homepage": "https://github.com/microsoft/BotFramework-WebChat/tree/master/packages/component#readme", "scripts": { - "build": "npm run build:typescript && npm run build:babel && npm run build:globalize", + "build": "npm run build:typescript && npm run build:babel", "build:babel": "babel src --copy-files --extensions .js,.ts,.tsx --ignore **/*.spec.js,**/*.spec.ts,**/*.spec.tsx,**/*.test.js,**/*.test.ts,**/*.test.tsx,__tests__/**/*.js,__tests__/**/*.ts,__tests__/**/*.tsx --no-copy-ignored --out-dir lib --verbose", - "build:globalize": "node scripts/createPrecompiledGlobalize.js", "build:typescript": "tsc --project src/tsconfig.json", "eslint": "eslint src/**/*.js src/**/*.ts", "prestart": "npm run build:babel", - "start": "concurrently --kill-others --names \"babel,globalize,tsc\" \"npm run start:babel\" \"npm run start:globalize\" \"npm run start:typescript\"", + "start": "concurrently --kill-others --names \"babel,tsc\" \"npm run start:babel\" \"npm run start:typescript\"", "start:babel": "npm run build:babel -- --skip-initial-build --watch", - "start:globalize": "node-dev --respawn scripts/createPrecompiledGlobalize.js", "start:typescript": "npm run build:typescript -- --watch" }, - "cldr-data-coverage": "full", "devDependencies": { "@babel/cli": "^7.10.5", "@babel/core": "^7.11.0", @@ -39,37 +36,30 @@ "@types/react": "^16.9.47", "babel-plugin-istanbul": "^6.0.0", "babel-plugin-transform-inline-environment-variables": "^0.4.3", - "cldr-data": "^36.0.0", "concurrently": "^5.3.0", "core-js": "^3.6.5", "eslint": "^7.7.0", "eslint-plugin-prettier": "^3.1.4", "eslint-plugin-react": "^7.20.6", "eslint-plugin-react-hooks": "^4.1.0", - "globalize-compiler": "^1.1.1", - "iana-tz-data": "^2019.1.0", "node-dev": "^5.2.0", "prettier": "^2.1.1", "typescript": "^4.0.2" }, "dependencies": { "base64-js": "1.3.1", + "botframework-webchat-api": "^0.0.0-0", "botframework-webchat-core": "0.0.0-0", "classnames": "2.2.6", "create-emotion": "10.0.27", - "event-target-shim": "5.0.1", - "event-target-shim-es5": "1.2.0", - "globalize": "1.5.0", "markdown-it": "11.0.0", "math-random": "2.0.1", "memoize-one": "5.1.1", "prop-types": "15.7.2", "react-dictate-button": "1.2.3-master.6b4fe72", "react-film": "3.0.0", - "react-redux": "7.2.0", "react-say": "2.0.2-master.ee7cd76", "react-scroll-to-bottom": "4.0.0", - "redux": "4.0.5", "remark": "10.0.1", "sanitize-html": "^1.27.4", "simple-update-in": "2.2.0", diff --git a/packages/component/src/Activity/Bubble.js b/packages/component/src/Activity/Bubble.js index d0bde715a0..f395661063 100644 --- a/packages/component/src/Activity/Bubble.js +++ b/packages/component/src/Activity/Bubble.js @@ -1,15 +1,16 @@ /* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 1, 2, 10] }] */ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; import isZeroOrPositive from '../Utils/isZeroOrPositive'; -import useDirection from '../hooks/useDirection'; -import useStyleOptions from '../hooks/useStyleOptions'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; +const { useDirection, useStyleOptions } = hooks; + const ROOT_STYLE = { '&.webchat__bubble': { display: 'flex', diff --git a/packages/component/src/Activity/CarouselFilmStrip.js b/packages/component/src/Activity/CarouselFilmStrip.js index 547e5125c1..9fd5f939fd 100644 --- a/packages/component/src/Activity/CarouselFilmStrip.js +++ b/packages/component/src/Activity/CarouselFilmStrip.js @@ -1,5 +1,6 @@ /* eslint complexity: ["error", 30] */ +import { hooks } from 'botframework-webchat-api'; import { useItemContainerCallbackRef, useScrollableCallbackRef } from 'react-film'; import classNames from 'classnames'; import PropTypes from 'prop-types'; @@ -10,15 +11,12 @@ import connectToWebChat from '../connectToWebChat'; import isZeroOrPositive from '../Utils/isZeroOrPositive'; import ScreenReaderText from '../ScreenReaderText'; import textFormatToContentType from '../Utils/textFormatToContentType'; -import useAvatarForBot from '../hooks/useAvatarForBot'; -import useAvatarForUser from '../hooks/useAvatarForUser'; -import useDirection from '../hooks/useDirection'; -import useLocalizer from '../hooks/useLocalizer'; -import useStyleOptions from '../hooks/useStyleOptions'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; import useUniqueId from '../hooks/internal/useUniqueId'; +const { useAvatarForBot, useAvatarForUser, useDirection, useLocalizer, useStyleOptions } = hooks; + const ROOT_STYLE = { '&.webchat__carousel-filmstrip': { display: 'flex', diff --git a/packages/component/src/Activity/CarouselLayout.js b/packages/component/src/Activity/CarouselLayout.js index 8928497ede..f5bdf801b2 100644 --- a/packages/component/src/Activity/CarouselLayout.js +++ b/packages/component/src/Activity/CarouselLayout.js @@ -1,3 +1,4 @@ +import { hooks } from 'botframework-webchat-api'; import { Composer as FilmComposer, createBasicStyleSet as createBasicStyleSetForReactFilm, @@ -12,12 +13,12 @@ import PropTypes from 'prop-types'; import React, { useMemo } from 'react'; import CarouselFilmStrip from './CarouselFilmStrip'; -import useDirection from '../hooks/useDirection'; -import useLocalizer from '../hooks/useLocalizer'; import useNonce from '../hooks/internal/useNonce'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; +const { useDirection, useLocalizer } = hooks; + const ROOT_STYLE = { '&.webchat__carousel-layout': { overflow: 'hidden', diff --git a/packages/component/src/Activity/ScrollToEndButton.js b/packages/component/src/Activity/ScrollToEndButton.js index 48a206f90e..171453b841 100644 --- a/packages/component/src/Activity/ScrollToEndButton.js +++ b/packages/component/src/Activity/ScrollToEndButton.js @@ -1,13 +1,12 @@ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React, { forwardRef, useCallback } from 'react'; -import useDirection from '../hooks/useDirection'; -import useLocalizer from '../hooks/useLocalizer'; -import useScrollToEnd from '../hooks/useScrollToEnd'; +import { safari } from '../Utils/detectBrowser'; import useStyleSet from '../hooks/useStyleSet'; -import { safari } from '../Utils/detectBrowser'; +const { useDirection, useLocalizer, useScrollToEnd } = hooks; const ScrollToEndButton = forwardRef( ( diff --git a/packages/component/src/Activity/Speak.js b/packages/component/src/Activity/Speak.js index b083207152..feb9d8d015 100644 --- a/packages/component/src/Activity/Speak.js +++ b/packages/component/src/Activity/Speak.js @@ -1,12 +1,12 @@ +import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; import React, { useCallback, useMemo } from 'react'; import Say, { SayUtterance } from 'react-say'; import connectToWebChat from '../connectToWebChat'; import SayAlt from './SayAlt'; -import useMarkActivityAsSpoken from '../hooks/useMarkActivityAsSpoken'; -import useStyleOptions from '../hooks/useStyleOptions'; -import useVoiceSelector from '../hooks/useVoiceSelector'; + +const { useMarkActivityAsSpoken, useStyleOptions, useVoiceSelector } = hooks; // TODO: [P4] Consider moving this feature into BasicActivity // And it has better DOM position for showing visual spoken text diff --git a/packages/component/src/Activity/StackedLayout.js b/packages/component/src/Activity/StackedLayout.js index 79eacd82cf..2ff30119c4 100644 --- a/packages/component/src/Activity/StackedLayout.js +++ b/packages/component/src/Activity/StackedLayout.js @@ -1,5 +1,6 @@ /* eslint complexity: ["error", 30] */ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; @@ -9,14 +10,13 @@ import connectToWebChat from '../connectToWebChat'; import isZeroOrPositive from '../Utils/isZeroOrPositive'; import ScreenReaderText from '../ScreenReaderText'; import textFormatToContentType from '../Utils/textFormatToContentType'; -import useAvatarForBot from '../hooks/useAvatarForBot'; -import useAvatarForUser from '../hooks/useAvatarForUser'; -import useLocalizer from '../hooks/useLocalizer'; -import useStyleOptions from '../hooks/useStyleOptions'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; + import useUniqueId from '../hooks/internal/useUniqueId'; +const { useAvatarForBot, useAvatarForUser, useLocalizer, useStyleOptions } = hooks; + const ROOT_STYLE = { '&.webchat__stacked-layout': { position: 'relative', // This is to keep screen reader text in the destinated area. @@ -136,6 +136,8 @@ const StackedLayout = ({ const showAvatar = showCallout && hasAvatar && !!renderAvatar; const showNub = showCallout && hasNub && (topAlignedCallout || !attachments.length); + console.log('stackedlayout', { hideTimestamp, renderActivityStatus }); + return (
{ const [{ bubbleImageHeight }] = useStyleOptions(); diff --git a/packages/component/src/Attachment/TextContent.js b/packages/component/src/Attachment/TextContent.js index 0bae065248..79c188cd63 100644 --- a/packages/component/src/Attachment/TextContent.js +++ b/packages/component/src/Attachment/TextContent.js @@ -3,13 +3,15 @@ // The content rendered here is sanitized. +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; -import useRenderMarkdownAsHTML from '../hooks/useRenderMarkdownAsHTML'; import useStyleSet from '../hooks/useStyleSet'; +const { useRenderMarkdownAsHTML } = hooks; + const TextContent = ({ contentType, text }) => { const [{ textContent: textContentStyleSet }] = useStyleSet(); const renderMarkdownAsHTML = useRenderMarkdownAsHTML(); diff --git a/packages/component/src/Attachment/VideoAttachment.js b/packages/component/src/Attachment/VideoAttachment.js index bfce5249ab..a3873c84cc 100644 --- a/packages/component/src/Attachment/VideoAttachment.js +++ b/packages/component/src/Attachment/VideoAttachment.js @@ -2,9 +2,9 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; +import VideoContent from './VideoContent'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; -import VideoContent from './VideoContent'; const ROOT_STYLE = { display: 'flex', diff --git a/packages/component/src/Avatar/ImageAvatar.js b/packages/component/src/Avatar/ImageAvatar.js index 1a25ecc3c7..8ddfcd8d95 100644 --- a/packages/component/src/Avatar/ImageAvatar.js +++ b/packages/component/src/Avatar/ImageAvatar.js @@ -1,13 +1,14 @@ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; import CroppedImage from '../Utils/CroppedImage'; -import useAvatarForBot from '../hooks/useAvatarForBot'; -import useAvatarForUser from '../hooks/useAvatarForUser'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; +const { useAvatarForBot, useAvatarForUser } = hooks; + const ROOT_STYLE = { '& .webchat__imageAvatar__image': { width: '100%' diff --git a/packages/component/src/Avatar/InitialsAvatar.js b/packages/component/src/Avatar/InitialsAvatar.js index ad4a150475..ff0d5d925f 100644 --- a/packages/component/src/Avatar/InitialsAvatar.js +++ b/packages/component/src/Avatar/InitialsAvatar.js @@ -1,12 +1,13 @@ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; -import useAvatarForBot from '../hooks/useAvatarForBot'; -import useAvatarForUser from '../hooks/useAvatarForUser'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; +const { useAvatarForBot, useAvatarForUser } = hooks; + const ROOT_STYLE = { alignItems: 'center', display: 'flex', diff --git a/packages/component/src/BasicConnectivityStatus.js b/packages/component/src/BasicConnectivityStatus.js index eb97bf999b..2cf4e3da5d 100644 --- a/packages/component/src/BasicConnectivityStatus.js +++ b/packages/component/src/BasicConnectivityStatus.js @@ -1,10 +1,12 @@ +import { hooks } from 'botframework-webchat-api'; import React from 'react'; import ConnectivityStatusConnected from './ConnectivityStatus/Connected'; import ConnectivityStatusConnecting from './ConnectivityStatus/Connecting'; import ConnectivityStatusFailedToConnect from './ConnectivityStatus/FailedToConnect'; import ConnectivityStatusJavaScriptError from './ConnectivityStatus/JavaScriptError'; -import useDebouncedNotifications from './hooks/useDebouncedNotifications'; + +const { useDebouncedNotifications } = hooks; const BasicConnectivityStatus = () => { const [{ connectivitystatus: connectivityStatus }] = useDebouncedNotifications(); diff --git a/packages/component/src/BasicSendBox.js b/packages/component/src/BasicSendBox.js index 883be0ccdd..87cde75a2e 100644 --- a/packages/component/src/BasicSendBox.js +++ b/packages/component/src/BasicSendBox.js @@ -1,4 +1,5 @@ import { Constants } from 'botframework-webchat-core'; +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; @@ -9,18 +10,15 @@ import SendButton from './SendBox/SendButton'; import SuggestedActions from './SendBox/SuggestedActions'; import TextBox from './SendBox/TextBox'; import UploadButton from './SendBox/UploadButton'; -import useActivities from './hooks/useActivities'; -import useDirection from './hooks/useDirection'; -import useDictateState from './hooks/useDictateState'; -import useStyleOptions from './hooks/useStyleOptions'; import useStyleSet from './hooks/useStyleSet'; import useStyleToEmotionObject from './hooks/internal/useStyleToEmotionObject'; -import useWebSpeechPonyfill from './hooks/useWebSpeechPonyfill'; const { DictateState: { DICTATING, STARTING } } = Constants; +const { useActivities, useDirection, useDictateState, useStyleOptions, useWebSpeechPonyfill } = hooks; + const ROOT_STYLE = { '& > .main': { display: 'flex' diff --git a/packages/component/src/BasicToast.js b/packages/component/src/BasicToast.js index 7318e39ae5..ead8607fa5 100644 --- a/packages/component/src/BasicToast.js +++ b/packages/component/src/BasicToast.js @@ -1,6 +1,7 @@ /* eslint react/forbid-dom-props: "off" */ /* eslint react/no-danger: "off" */ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React, { useCallback, useMemo } from 'react'; @@ -9,12 +10,12 @@ import DismissIcon from './Toast/DismissIcon'; import NotificationIcon from './Toast/NotificationIcon'; import randomId from './Utils/randomId'; import ScreenReaderText from './ScreenReaderText'; -import useDismissNotification from './hooks/useDismissNotification'; import useInternalRenderMarkdownInline from './hooks/internal/useInternalRenderMarkdownInline'; -import useLocalizer from './hooks/useLocalizer'; import useStyleSet from './hooks/useStyleSet'; import useStyleToEmotionObject from './hooks/internal/useStyleToEmotionObject'; +const { useDismissNotification, useLocalizer } = hooks; + const ROOT_STYLE = { display: 'flex', diff --git a/packages/component/src/BasicToaster.js b/packages/component/src/BasicToaster.js index 13daaf475f..7b13c36d84 100644 --- a/packages/component/src/BasicToaster.js +++ b/packages/component/src/BasicToaster.js @@ -1,6 +1,7 @@ /* eslint no-magic-numbers: ["error", { "ignore": [0, 1, 2, 3, 4, 5] }] */ /* eslint react/forbid-dom-props: "off" */ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; @@ -8,12 +9,11 @@ import CollapseIcon from './Toast/CollapseIcon'; import ExpandIcon from './Toast/ExpandIcon'; import NotificationIcon from './Toast/NotificationIcon'; import randomId from './Utils/randomId'; -import useDebouncedNotifications from './hooks/useDebouncedNotifications'; -import useLocalizer from './hooks/useLocalizer'; -import useRenderToast from './hooks/useRenderToast'; import useStyleSet from './hooks/useStyleSet'; import useStyleToEmotionObject from './hooks/internal/useStyleToEmotionObject'; +const { useDebouncedNotifications, useLocalizer, useRenderToast } = hooks; + const ROOT_STYLE = { display: 'flex', flexDirection: 'column', diff --git a/packages/component/src/BasicTranscript.js b/packages/component/src/BasicTranscript.js index ccdc753656..5d5261fec1 100644 --- a/packages/component/src/BasicTranscript.js +++ b/packages/component/src/BasicTranscript.js @@ -1,5 +1,6 @@ /* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 1] }] */ +import { hooks } from 'botframework-webchat-api'; import { Panel as ScrollToBottomPanel, useAnimatingToEnd, useSticky } from 'react-scroll-to-bottom'; import classNames from 'classnames'; import PropTypes from 'prop-types'; @@ -15,20 +16,23 @@ import removeInline from './Utils/removeInline'; import ScreenReaderActivity from './ScreenReaderActivity'; import ScrollToEndButton from './Activity/ScrollToEndButton'; import SpeakActivity from './Activity/Speak'; -import useActivities from './hooks/useActivities'; -import useCreateActivityRenderer from './hooks/useCreateActivityRenderer'; -import useCreateActivityStatusRenderer from './hooks/useCreateActivityStatusRenderer'; -import useCreateAvatarRenderer from './hooks/useCreateAvatarRenderer'; -import useDirection from './hooks/useDirection'; -import useFocus from './hooks/useFocus'; -import useGroupActivities from './hooks/useGroupActivities'; -import useLocalizer from './hooks/useLocalizer'; import useMemoize from './hooks/internal/useMemoize'; -import useStyleOptions from './hooks/useStyleOptions'; import useStyleSet from './hooks/useStyleSet'; +import useStyleToEmotionObject from './hooks/internal/useStyleToEmotionObject'; import useTranscriptActivityElementsRef from './hooks/internal/useTranscriptActivityElementsRef'; import useTranscriptRootElementRef from './hooks/internal/useTranscriptRootElementRef'; -import useStyleToEmotionObject from './hooks/internal/useStyleToEmotionObject'; + +const { + useActivities, + useCreateActivityRenderer, + useCreateActivityStatusRenderer, + useCreateAvatarRenderer, + useDirection, + useFocus, + useGroupActivities, + useLocalizer, + useStyleOptions +} = hooks; const ROOT_STYLE = { '&.webchat__basic-transcript': { @@ -71,7 +75,7 @@ function validateAllActivitiesTagged(activities, bins) { return activities.every(activity => bins.some(bin => bin.includes(activity))); } -const BasicTranscript2 = ({ className }) => { +const BasicTranscript = ({ className }) => { const [{ activity: activityStyleSet }] = useStyleSet(); const [ { bubbleFromUserNubOffset, bubbleNubOffset, groupTimestamp, internalLiveRegionFadeAfter, showAvatarInGroup } @@ -381,11 +385,11 @@ const BasicTranscript2 = ({ className }) => { ); }; -BasicTranscript2.defaultProps = { +BasicTranscript.defaultProps = { className: '' }; -BasicTranscript2.propTypes = { +BasicTranscript.propTypes = { className: PropTypes.string }; @@ -522,4 +526,4 @@ InternalTranscriptScrollable.propTypes = { children: PropTypes.arrayOf(PropTypes.element).isRequired }; -export default BasicTranscript2; +export default BasicTranscript; diff --git a/packages/component/src/BasicTypingIndicator.js b/packages/component/src/BasicTypingIndicator.js index dba311c6c8..0c9f09e5f2 100644 --- a/packages/component/src/BasicTypingIndicator.js +++ b/packages/component/src/BasicTypingIndicator.js @@ -1,5 +1,6 @@ -import useActiveTyping from './hooks/useActiveTyping'; -import useRenderTypingIndicator from './hooks/useRenderTypingIndicator'; +import { hooks } from 'botframework-webchat-api'; + +const { useActiveTyping, useRenderTypingIndicator } = hooks; function useTypingIndicatorVisible() { const [activeTyping] = useActiveTyping(); diff --git a/packages/component/src/BasicWebChat.js b/packages/component/src/BasicWebChat.js index 4f062aa2cf..ecfc3460b9 100644 --- a/packages/component/src/BasicWebChat.js +++ b/packages/component/src/BasicWebChat.js @@ -1,23 +1,26 @@ /* eslint no-magic-numbers: ["error", { "ignore": [0, 1, 2] }] */ /* eslint react/no-unsafe: off */ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; +// TODO: No /lib/ +import useSendBoxFocusRef from 'botframework-webchat-api/lib/hooks/internal/useSendBoxFocusRef'; +import useTranscriptFocusRef from 'botframework-webchat-api/lib/hooks/internal/useTranscriptFocusRef'; + import AccessKeySinkSurface from './Utils/AccessKeySink/Surface'; import BasicConnectivityStatus from './BasicConnectivityStatus'; import BasicSendBox from './BasicSendBox'; import BasicToaster from './BasicToaster'; import BasicTranscript from './BasicTranscript'; import TypeFocusSinkBox from './Utils/TypeFocusSink'; -import useDisabled from './hooks/useDisabled'; -import useSendBoxFocusRef from './hooks/internal/useSendBoxFocusRef'; -import useStyleOptions from './hooks/useStyleOptions'; import useStyleSet from './hooks/useStyleSet'; -import useTranscriptFocusRef from './hooks/internal/useTranscriptFocusRef'; import useStyleToEmotionObject from './hooks/internal/useStyleToEmotionObject'; +const { useDisabled, useStyleOptions } = hooks; + const ROOT_STYLE = { display: 'flex', flexDirection: 'column' diff --git a/packages/component/src/Composer.js b/packages/component/src/Composer.js index 18128c6479..dde8ed1f82 100644 --- a/packages/component/src/Composer.js +++ b/packages/component/src/Composer.js @@ -1,100 +1,23 @@ -/* eslint-disable react/prop-types */ -/* eslint-disable react/destructuring-assignment */ -import { Composer as SayComposer } from 'react-say'; +import { Composer as APIComposer, hooks } from 'botframework-webchat-api'; import { Composer as ScrollToBottomComposer } from 'react-scroll-to-bottom'; - -import { Provider } from 'react-redux'; +import React, { useMemo, useRef } from 'react'; import createEmotion from 'create-emotion'; +import createStyleSet from './Styles/createStyleSet'; import MarkdownIt from 'markdown-it'; import PropTypes from 'prop-types'; -import React, { isValidElement, useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import updateIn from 'simple-update-in'; - -import applyAttachmentForScreenReaderMiddleware from './Middleware/applyAttachmentForScreenReaderMiddleware'; -import createActivityRenderer from './Middleware/createActivityRenderer'; -import createActivityStatusRenderer from './Middleware/createActivityStatusRenderer'; -import createAttachmentRenderer from './Middleware/createAttachmentRenderer'; -import createAvatarRenderer from './Middleware/createAvatarRenderer'; -import createCSSKey from './Utils/createCSSKey'; -import createCustomEvent from './Utils/createCustomEvent'; -import createToastRenderer from './Middleware/createToastRenderer'; -import createTypingIndicatorRenderer from './Middleware/createTypingIndicatorRenderer'; -import ErrorBoundary from './ErrorBoundary'; -import getAllLocalizedStrings from './Localization/getAllLocalizedStrings'; -import isObject from './Utils/isObject'; -import normalizeLanguage from './Utils/normalizeLanguage'; -import PrecompiledGlobalize from './Utils/PrecompiledGlobalize'; -import useReferenceGrammarID from './hooks/useReferenceGrammarID'; - -import { - clearSuggestedActions, - connect as createConnectAction, - createStore, - disconnect, - dismissNotification, - emitTypingIndicator, - markActivity, - postActivity, - sendEvent, - sendFiles, - sendMessage, - sendMessageBack, - sendPostBack, - setDictateInterims, - setDictateState, - setLanguage, - setNotification, - setSendBox, - setSendTimeout, - setSendTypingIndicator, - startDictate, - startSpeakingActivity, - stopDictate, - stopSpeakingActivity, - submitSendBox -} from 'botframework-webchat-core'; import addTargetBlankToHyperlinksMarkdown from './Utils/addTargetBlankToHyperlinksMarkdown'; -import concatMiddleware from './Middleware/concatMiddleware'; -import createCoreCardActionMiddleware from './Middleware/CardAction/createCoreMiddleware'; -import createDefaultGroupActivitiesMiddleware from './Middleware/GroupActivities/createCoreMiddleware'; -import createStyleSet from './Styles/createStyleSet'; -import defaultSelectVoice from './defaultSelectVoice'; -import Dictation from './Dictation'; +import createCSSKey from './Utils/createCSSKey'; +import createDefaultActivityMiddleware from './Middleware/Activity/createCoreMiddleware'; +import createDefaultActivityStatusMiddleware from './Middleware/ActivityStatus/createCoreMiddleware'; +import createDefaultAttachmentMiddleware from './Middleware/Attachment/createCoreMiddleware'; +import ErrorBox from './ErrorBox'; import mapMap from './Utils/mapMap'; -import observableToPromise from './Utils/observableToPromise'; -import Tracker from './Tracker'; -import WebChatReduxContext, { useDispatch } from './WebChatReduxContext'; -import WebChatUIContext from './WebChatUIContext'; +import singleToArray from './Utils/singleToArray'; +import upgradeLegacyRendererMiddleware from './Utils/upgradeLegacyRendererMiddleware'; +import WebChatUIContext from './hooks/internal/WebChatUIContext'; -import { - speechSynthesis as bypassSpeechSynthesis, - SpeechSynthesisUtterance as BypassSpeechSynthesisUtterance -} from './Speech/BypassSpeechSynthesisPonyfill'; - -// List of Redux actions factory we are hoisting as Web Chat functions -const DISPATCHERS = { - clearSuggestedActions, - dismissNotification, - emitTypingIndicator, - markActivity, - postActivity, - sendEvent, - sendFiles, - sendMessage, - sendMessageBack, - sendPostBack, - setDictateInterims, - setDictateState, - setNotification, - setSendBox, - setSendTimeout, - startDictate, - startSpeakingActivity, - stopDictate, - stopSpeakingActivity, - submitSendBox -}; +const { useStyleOptions } = hooks; const emotionPool = {}; @@ -102,204 +25,8 @@ function styleSetToEmotionObjects(styleToEmotionObject, styleSet) { return mapMap(styleSet, (style, key) => (key === 'options' ? style : styleToEmotionObject(style))); } -function createCardActionContext({ cardActionMiddleware, directLine, dispatch }) { - const runMiddleware = concatMiddleware(cardActionMiddleware, createCoreCardActionMiddleware())({ dispatch }); - - return { - onCardAction: (cardAction, { target } = {}) => - runMiddleware(({ cardAction: { type } }) => { - throw new Error(`Web Chat: received unknown card action "${type}"`); - })({ - cardAction, - getSignInUrl: - cardAction.type === 'signin' - ? () => { - const { value } = cardAction; - - if (directLine.getSessionId) { - // TODO: [P3] We should change this one to async/await. - // This is the first place in this project to use async. - // Thus, we need to add @babel/plugin-transform-runtime and @babel/runtime. - - return observableToPromise(directLine.getSessionId()).then( - sessionId => `${value}${encodeURIComponent(`&code_challenge=${sessionId}`)}` - ); - } - - console.warn( - 'botframework-webchat: No-magic-code OAuth flow is not supported on this Direct Line adapter.' - ); - - return Promise.resolve(value); - } - : null, - target - }) - }; -} - -function createFocusContext({ sendBoxFocusRef, transcriptFocusRef }) { - return { - focus: where => { - const ref = where === 'sendBox' || where === 'sendBoxWithoutKeyboard' ? sendBoxFocusRef : transcriptFocusRef; - const { current } = ref || {}; - - if (current) { - if (where === 'sendBoxWithoutKeyboard') { - // To not activate the virtual keyboard while changing focus to an input, we will temporarily set it as read-only and flip it back. - // https://stackoverflow.com/questions/7610758/prevent-iphone-default-keyboard-when-focusing-an-input/7610923 - const readOnly = current.getAttribute('readonly'); - - current.setAttribute('readonly', 'readonly'); - - setTimeout(() => { - current.focus(); - readOnly ? current.setAttribute('readonly', readOnly) : current.removeAttribute('readonly'); - }, 0); - } else { - current.focus(); - } - } - } - }; -} - -function createGroupActivitiesContext({ groupActivitiesMiddleware, groupTimestamp }) { - const runMiddleware = concatMiddleware( - groupActivitiesMiddleware, - createDefaultGroupActivitiesMiddleware({ groupTimestamp }) - )()(() => { - throw new Error('botframework-webchat internal: No middleware is execute for groupActivities.'); - }); - - return { - groupActivities: ({ activities }) => runMiddleware({ activities }) - }; -} - -function mergeStringsOverrides(localizedStrings, language, overrideLocalizedStrings) { - if (!overrideLocalizedStrings) { - return localizedStrings; - } else if (typeof overrideLocalizedStrings === 'function') { - const merged = overrideLocalizedStrings(localizedStrings, language); - - if (!isObject(merged)) { - throw new Error('botframework-webchat: overrideLocalizedStrings function must return an object.'); - } - - return merged; - } - - if (!isObject(overrideLocalizedStrings)) { - throw new Error('botframework-webchat: overrideLocalizedStrings must be either a function, an object, or falsy.'); - } - - return { ...localizedStrings, ...overrideLocalizedStrings }; -} - -const Composer = ({ - activityMiddleware, - activityRenderer, - activityStatusMiddleware, - activityStatusRenderer, - attachmentForScreenReaderMiddleware, - attachmentMiddleware, - attachmentRenderer, - avatarMiddleware, - avatarRenderer, - cardActionMiddleware, - children, - dir, - directLine, - disabled, - extraStyleSet, - grammars, - groupActivitiesMiddleware, - groupTimestamp, - locale, - nonce, - onTelemetry, - overrideLocalizedStrings, - renderMarkdown, - selectVoice, - sendTimeout, - sendTypingIndicator, - styleOptions, - styleSet, - suggestedActionsAccessKey, - toastMiddleware, - toastRenderer, - typingIndicatorMiddleware, - typingIndicatorRenderer, - userID, - username, - webSpeechPonyfillFactory -}) => { - const [dictateAbortable, setDictateAbortable] = useState(); - const [referenceGrammarID] = useReferenceGrammarID(); - const dispatch = useDispatch(); - const sendBoxFocusRef = useRef(); - const telemetryDimensionsRef = useRef({}); - const transcriptFocusRef = useRef(); - - const patchedDir = useMemo(() => (dir === 'ltr' || dir === 'rtl' ? dir : 'auto'), [dir]); - const patchedGrammars = useMemo(() => grammars || [], [grammars]); - - const patchedStyleOptions = useMemo(() => { - const patchedStyleOptions = { ...styleOptions }; - - if (typeof groupTimestamp !== 'undefined' && typeof patchedStyleOptions.groupTimestamp === 'undefined') { - console.warn( - 'Web Chat: "groupTimestamp" has been moved to "styleOptions". This deprecation migration will be removed on or after January 1 2022.' - ); - - patchedStyleOptions.groupTimestamp = groupTimestamp; - } - - if (typeof sendTimeout !== 'undefined' && typeof patchedStyleOptions.sendTimeout === 'undefined') { - console.warn( - 'Web Chat: "sendTimeout" has been moved to "styleOptions". This deprecation migration will be removed on or after January 1 2022.' - ); - - patchedStyleOptions.sendTimeout = sendTimeout; - } - - if (styleOptions.slowConnectionAfter < 0) { - console.warn('Web Chat: "slowConnectionAfter" cannot be negative, will set to 0.'); - - patchedStyleOptions.slowConnectionAfter = 0; - } - - return patchedStyleOptions; - }, [groupTimestamp, sendTimeout, styleOptions]); - - useEffect(() => { - dispatch(setLanguage(locale)); - }, [dispatch, locale]); - - useEffect(() => { - typeof sendTimeout === 'number' && dispatch(setSendTimeout(sendTimeout)); - }, [dispatch, sendTimeout]); - - useEffect(() => { - dispatch(setSendTypingIndicator(!!sendTypingIndicator)); - }, [dispatch, sendTypingIndicator]); - - useEffect(() => { - dispatch( - createConnectAction({ - directLine, - userID, - username - }) - ); - - return () => { - // TODO: [P3] disconnect() is an async call (pending -> fulfilled), we need to wait, or change it to reconnect() - dispatch(disconnect()); - }; - }, [dispatch, directLine, userID, username]); - +const ComposerCore = ({ children, extraStyleSet, nonce, renderMarkdown, styleSet, suggestedActionsAccessKey }) => { + const [styleOptions] = useStyleOptions(); const internalMarkdownIt = useMemo(() => new MarkdownIt(), []); const internalRenderMarkdownInline = useMemo( @@ -314,22 +41,6 @@ const Composer = ({ [internalMarkdownIt] ); - const cardActionContext = useMemo(() => createCardActionContext({ cardActionMiddleware, directLine, dispatch }), [ - cardActionMiddleware, - directLine, - dispatch - ]); - - const patchedSelectVoice = useMemo(() => selectVoice || defaultSelectVoice.bind(null, { language: locale }), [ - locale, - selectVoice - ]); - - const focusContext = useMemo(() => createFocusContext({ sendBoxFocusRef, transcriptFocusRef }), [ - sendBoxFocusRef, - transcriptFocusRef - ]); - const styleToEmotionObject = useMemo(() => { // Emotion doesn't hash with nonce. We need to provide the pooling mechanism. // 1. If 2 instances use different nonce, they should result in different hash; @@ -343,396 +54,115 @@ const Composer = ({ const patchedStyleSet = useMemo( () => styleSetToEmotionObjects(styleToEmotionObject, { - ...(styleSet || createStyleSet(patchedStyleOptions)), + ...(styleSet || createStyleSet(styleOptions)), ...extraStyleSet }), - [extraStyleSet, patchedStyleOptions, styleSet, styleToEmotionObject] - ); - - const groupActivitiesContext = useMemo( - () => - createGroupActivitiesContext({ - groupActivitiesMiddleware, - groupTimestamp: patchedStyleSet.options.groupTimestamp - }), - [groupActivitiesMiddleware, patchedStyleSet.options.groupTimestamp] - ); - - const hoistedDispatchers = useMemo( - () => mapMap(DISPATCHERS, dispatcher => (...args) => dispatch(dispatcher(...args))), - [dispatch] - ); - - const webSpeechPonyfill = useMemo(() => { - const ponyfill = webSpeechPonyfillFactory && webSpeechPonyfillFactory({ referenceGrammarID }); - const { speechSynthesis, SpeechSynthesisUtterance } = ponyfill || {}; - - return { - ...ponyfill, - speechSynthesis: speechSynthesis || bypassSpeechSynthesis, - SpeechSynthesisUtterance: SpeechSynthesisUtterance || BypassSpeechSynthesisUtterance - }; - }, [referenceGrammarID, webSpeechPonyfillFactory]); - - const dictationOnError = useCallback(err => { - console.error(err); - }, []); - - const patchedLocalizedStrings = useMemo( - () => mergeStringsOverrides(getAllLocalizedStrings()[normalizeLanguage(locale)], locale, overrideLocalizedStrings), - [locale, overrideLocalizedStrings] + [extraStyleSet, styleOptions, styleSet, styleToEmotionObject] ); - const localizedGlobalize = useMemo(() => { - const { GLOBALIZE, GLOBALIZE_LANGUAGE } = patchedLocalizedStrings || {}; - - return GLOBALIZE || (GLOBALIZE_LANGUAGE && PrecompiledGlobalize(GLOBALIZE_LANGUAGE)) || PrecompiledGlobalize('en'); - }, [patchedLocalizedStrings]); - - const trackDimension = useCallback( - (name, data) => { - if (!name || typeof name !== 'string') { - return console.warn('botframework-webchat: Telemetry dimension name must be a string.'); - } - - const type = typeof data; - - if (type !== 'string' && type !== 'undefined') { - return console.warn('botframework-webchat: Telemetry dimension data must be a string or undefined.'); - } - - telemetryDimensionsRef.current = updateIn( - telemetryDimensionsRef.current, - [name], - type === 'undefined' ? data : () => data - ); - }, - [telemetryDimensionsRef] - ); - - const patchedActivityRenderer = useMemo(() => { - activityRenderer && - console.warn( - 'Web Chat: "activityRenderer" is deprecated and will be removed on 2020-06-15, please use "activityMiddleware" instead.' - ); - - return activityRenderer || createActivityRenderer(activityMiddleware); - }, [activityMiddleware, activityRenderer]); - - const patchedActivityStatusRenderer = useMemo(() => { - activityStatusRenderer && - console.warn( - 'Web Chat: "activityStatusRenderer" is deprecated and will be removed on 2020-06-15, please use "activityStatusMiddleware" instead.' - ); - - return activityStatusRenderer || createActivityStatusRenderer(activityStatusMiddleware); - }, [activityStatusMiddleware, activityStatusRenderer]); - - const patchedAttachmentForScreenReaderRenderer = useMemo(() => { - const patchedAttachmentForScreenReaderRenderer = applyAttachmentForScreenReaderMiddleware( - attachmentForScreenReaderMiddleware - ); - - // The new function returned is for validating the result of attachmentForScreenReaderMiddleware. - return (...args) => { - const renderAttachmentForScreenReader = patchedAttachmentForScreenReaderRenderer(...args); - - if (renderAttachmentForScreenReader === false) { - return false; - } else if (typeof renderAttachmentForScreenReader === 'function') { - return (...renderArgs) => { - const element = renderAttachmentForScreenReader(...renderArgs); - - if (!isValidElement(element)) { - console.error( - 'botframework-webchat: Renderer of attachmentForScreenReaderMiddleware should return React element only.' - ); - } - - return element; - }; - } - - console.error( - 'botframework-webchat: attachmentForScreenReaderMiddleware should only return either false or a render function.' - ); - - return false; - }; - }, [attachmentForScreenReaderMiddleware]); - - const patchedAttachmentRenderer = useMemo(() => { - attachmentRenderer && - console.warn( - 'Web Chat: "attachmentRenderer" is deprecated and will be removed on 2020-06-15, please use "attachmentMiddleware" instead.' - ); - - return attachmentRenderer || createAttachmentRenderer(attachmentMiddleware); - }, [attachmentMiddleware, attachmentRenderer]); - - const patchedAvatarRenderer = useMemo(() => { - avatarRenderer && - console.warn( - 'Web Chat: "avatarRenderer" is deprecated and will be removed on 2020-06-15, please use "avatarMiddleware" instead.' - ); - - return avatarRenderer || createAvatarRenderer(avatarMiddleware); - }, [avatarMiddleware, avatarRenderer]); - - const patchedToastRenderer = useMemo(() => { - toastRenderer && - console.warn( - 'Web Chat: "toastRenderer" is deprecated and will be removed on 2020-06-15, please use "toastMiddleware" instead.' - ); - - return toastRenderer || createToastRenderer(toastMiddleware); - }, [toastMiddleware, toastRenderer]); - - const patchedTypingIndicatorRenderer = useMemo(() => { - typingIndicatorRenderer && - console.warn( - 'Web Chat: "typingIndicatorRenderer" is deprecated and will be removed on 2020-06-15, please use "typingIndicatorMiddleware" instead.' - ); - - return typingIndicatorRenderer || createTypingIndicatorRenderer(typingIndicatorMiddleware); - }, [typingIndicatorMiddleware, typingIndicatorRenderer]); - const transcriptActivityElementsRef = useRef([]); const transcriptRootElementRef = useRef(); - // This is a heavy function, and it is expected to be only called when there is a need to recreate business logic, e.g. - // - User ID changed, causing all send* functions to be updated - // - send - - // TODO: [P3] We should think about if we allow the user to change onSendBoxValueChanged/sendBoxValue, e.g. - // 1. Turns text into UPPERCASE - // 2. Filter out profanity - - // TODO: [P4] Revisit all members of context - // This context should consist of members that are not in the Redux store - // i.e. members that are not interested in other types of UIs const context = useMemo( () => ({ - ...cardActionContext, - ...focusContext, - ...groupActivitiesContext, - ...hoistedDispatchers, - activityRenderer: patchedActivityRenderer, - activityStatusRenderer: patchedActivityStatusRenderer, - attachmentRenderer: patchedAttachmentRenderer, - avatarRenderer: patchedAvatarRenderer, - createAttachmentForScreenReaderRenderer: patchedAttachmentForScreenReaderRenderer, - dictateAbortable, - dir: patchedDir, - directLine, - disabled, - grammars: patchedGrammars, internalMarkdownItState: [internalMarkdownIt], internalRenderMarkdownInline, - language: locale, - localizedGlobalizeState: [localizedGlobalize], - localizedStrings: patchedLocalizedStrings, nonce, - onTelemetry, - renderMarkdown, - selectVoice: patchedSelectVoice, - sendBoxFocusRef, - sendTypingIndicator, - setDictateAbortable, - styleOptions, styleSet: patchedStyleSet, styleToEmotionObject, suggestedActionsAccessKey, - telemetryDimensionsRef, - toastRenderer: patchedToastRenderer, - trackDimension, transcriptActivityElementsRef, - transcriptFocusRef, - transcriptRootElementRef, - typingIndicatorRenderer: patchedTypingIndicatorRenderer, - userID, - username, - webSpeechPonyfill + transcriptRootElementRef }), [ - cardActionContext, - dictateAbortable, - directLine, - disabled, - focusContext, - groupActivitiesContext, - hoistedDispatchers, internalMarkdownIt, internalRenderMarkdownInline, - locale, - localizedGlobalize, nonce, - onTelemetry, - patchedActivityRenderer, - patchedActivityStatusRenderer, - patchedAttachmentForScreenReaderRenderer, - patchedAttachmentRenderer, - patchedAvatarRenderer, - patchedDir, - patchedGrammars, - patchedLocalizedStrings, - patchedSelectVoice, patchedStyleSet, - patchedToastRenderer, - patchedTypingIndicatorRenderer, - renderMarkdown, - sendBoxFocusRef, - sendTypingIndicator, - setDictateAbortable, - styleOptions, styleToEmotionObject, suggestedActionsAccessKey, - telemetryDimensionsRef, - trackDimension, transcriptActivityElementsRef, - transcriptFocusRef, - transcriptRootElementRef, - userID, - username, - webSpeechPonyfill + transcriptRootElementRef ] ); return ( - - {typeof children === 'function' ? children(context) : children} - - - {onTelemetry && } + {children} ); }; -// We will create a Redux store if it was not passed in -const ComposeWithStore = ({ onTelemetry, store, ...props }) => { - const handleError = useCallback( - ({ error }) => { - onTelemetry && onTelemetry(createCustomEvent('exception', { error, fatal: true })); - }, - [onTelemetry] - ); - - const memoizedStore = useMemo(() => store || createStore(), [store]); - - return ( - - - - - - - - ); +ComposerCore.defaultProps = { + extraStyleSet: undefined, + nonce: undefined, + renderMarkdown: undefined, + styleSet: undefined, + suggestedActionsAccessKey: 'A a Å å' }; -ComposeWithStore.defaultProps = { - onTelemetry: undefined, - store: undefined +ComposerCore.propTypes = { + extraStyleSet: PropTypes.any, + nonce: PropTypes.string, + renderMarkdown: PropTypes.func, + styleSet: PropTypes.any, + suggestedActionsAccessKey: PropTypes.oneOfType([PropTypes.oneOf([false]), PropTypes.string]) }; -ComposeWithStore.propTypes = { - onTelemetry: PropTypes.func, - store: PropTypes.any -}; +const Composer = ({ + activityMiddleware, + activityStatusMiddleware, + attachmentMiddleware, + children, + errorBoundaryMiddleware, + ...props +}) => { + const patchedActivityMiddleware = useMemo( + () => [...singleToArray(activityMiddleware), ...createDefaultActivityMiddleware()].filter(middleware => middleware), + [activityMiddleware] + ); -export default ComposeWithStore; + const patchedActivityStatusMiddleware = useMemo( + () => + [...singleToArray(activityStatusMiddleware), ...createDefaultActivityStatusMiddleware()].filter( + middleware => middleware + ), + [activityStatusMiddleware] + ); + + const patchedAttachmentMiddleware = useMemo( + () => + [...singleToArray(attachmentMiddleware), ...createDefaultAttachmentMiddleware()].filter(middleware => middleware), + [attachmentMiddleware] + ); -// TODO: [P3] We should consider moving some data from Redux store to props -// Although we use `connectToWebChat` to hide the details of accessor of Redux store, -// we should clean up the responsibility between Context and Redux store -// We should decide which data is needed for React but not in other environment such as CLI/VSCode + return ( + + {children} + + ); +}; Composer.defaultProps = { + ...APIComposer.defaultProps, + ...ComposerCore.defaultProps, activityMiddleware: undefined, - activityRenderer: undefined, activityStatusMiddleware: undefined, - activityStatusRenderer: undefined, - attachmentForScreenReaderMiddleware: undefined, - attachmentMiddleware: undefined, - attachmentRenderer: undefined, - avatarMiddleware: undefined, - avatarRenderer: undefined, - cardActionMiddleware: undefined, - children: undefined, - dir: 'auto', - disabled: false, - extraStyleSet: undefined, - grammars: [], - groupActivitiesMiddleware: undefined, - groupTimestamp: undefined, - locale: window.navigator.language || 'en-US', - nonce: undefined, - onTelemetry: undefined, - overrideLocalizedStrings: undefined, - renderMarkdown: undefined, - selectVoice: undefined, - sendTimeout: undefined, - sendTypingIndicator: false, - styleOptions: {}, - styleSet: undefined, - suggestedActionsAccessKey: 'A a Å å', - toastMiddleware: undefined, - toastRenderer: undefined, - typingIndicatorMiddleware: undefined, - typingIndicatorRenderer: undefined, - userID: '', - username: '', - webSpeechPonyfillFactory: undefined + attachmentMiddleware: undefined }; Composer.propTypes = { - activityMiddleware: PropTypes.func, - activityRenderer: PropTypes.func, - activityStatusMiddleware: PropTypes.func, - activityStatusRenderer: PropTypes.func, - attachmentForScreenReaderMiddleware: PropTypes.func, - attachmentMiddleware: PropTypes.func, - attachmentRenderer: PropTypes.func, - avatarMiddleware: PropTypes.func, - avatarRenderer: PropTypes.func, - cardActionMiddleware: PropTypes.func, - children: PropTypes.any, - dir: PropTypes.oneOf(['auto', 'ltr', 'rtl']), - directLine: PropTypes.shape({ - activity$: PropTypes.shape({ - subscribe: PropTypes.func.isRequired - }).isRequired, - connectionStatus$: PropTypes.shape({ - subscribe: PropTypes.func.isRequired - }).isRequired, - end: PropTypes.func, - getSessionId: PropTypes.func, - postActivity: PropTypes.func.isRequired, - referenceGrammarID: PropTypes.string, - token: PropTypes.string - }).isRequired, - disabled: PropTypes.bool, - extraStyleSet: PropTypes.any, - grammars: PropTypes.arrayOf(PropTypes.string), - groupActivitiesMiddleware: PropTypes.func, - groupTimestamp: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]), - locale: PropTypes.string, - nonce: PropTypes.string, - onTelemetry: PropTypes.func, - overrideLocalizedStrings: PropTypes.oneOfType([PropTypes.any, PropTypes.func]), - renderMarkdown: PropTypes.func, - selectVoice: PropTypes.func, - sendTimeout: PropTypes.number, - sendTypingIndicator: PropTypes.bool, - styleOptions: PropTypes.any, - styleSet: PropTypes.any, - suggestedActionsAccessKey: PropTypes.oneOfType([PropTypes.oneOf([false]), PropTypes.string]), - toastMiddleware: PropTypes.func, - toastRenderer: PropTypes.func, - typingIndicatorMiddleware: PropTypes.func, - typingIndicatorRenderer: PropTypes.func, - userID: PropTypes.string, - username: PropTypes.string, - webSpeechPonyfillFactory: PropTypes.func + ...APIComposer.propTypes, + ...ComposerCore.propTypes, + activityMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), + activityStatusMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), + attachmentMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]) }; + +export default Composer; diff --git a/packages/component/src/ConnectivityStatus/Assets/ErrorNotificationIcon.js b/packages/component/src/ConnectivityStatus/Assets/ErrorNotificationIcon.js index 1796b0b392..51652a0320 100644 --- a/packages/component/src/ConnectivityStatus/Assets/ErrorNotificationIcon.js +++ b/packages/component/src/ConnectivityStatus/Assets/ErrorNotificationIcon.js @@ -1,8 +1,9 @@ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; -import useDirection from '../../hooks/useDirection'; +const { useDirection } = hooks; const ICON_SIZE_FACTOR = 16; diff --git a/packages/component/src/ConnectivityStatus/Assets/SpinnerAnimation.js b/packages/component/src/ConnectivityStatus/Assets/SpinnerAnimation.js index 3329131066..8d9cad9f31 100644 --- a/packages/component/src/ConnectivityStatus/Assets/SpinnerAnimation.js +++ b/packages/component/src/ConnectivityStatus/Assets/SpinnerAnimation.js @@ -1,9 +1,11 @@ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import React from 'react'; -import useDirection from '../../hooks/useDirection'; import useStyleSet from '../../hooks/useStyleSet'; +const { useDirection } = hooks; + const SpinnerAnimation = () => { const [{ spinnerAnimation: spinnerAnimationStyleSet }] = useStyleSet(); const [direction] = useDirection(); diff --git a/packages/component/src/ConnectivityStatus/Assets/WarningNotificationIcon.js b/packages/component/src/ConnectivityStatus/Assets/WarningNotificationIcon.js index 5d70632ced..ec0597fdac 100644 --- a/packages/component/src/ConnectivityStatus/Assets/WarningNotificationIcon.js +++ b/packages/component/src/ConnectivityStatus/Assets/WarningNotificationIcon.js @@ -1,8 +1,9 @@ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; -import useDirection from '../../hooks/useDirection'; +const { useDirection } = hooks; const ICON_SIZE_FACTOR = 16; diff --git a/packages/component/src/ConnectivityStatus/Connected.js b/packages/component/src/ConnectivityStatus/Connected.js index 117f4d0f67..0b753c40ab 100644 --- a/packages/component/src/ConnectivityStatus/Connected.js +++ b/packages/component/src/ConnectivityStatus/Connected.js @@ -1,7 +1,9 @@ +import { hooks } from 'botframework-webchat-api'; import React from 'react'; import ScreenReaderText from '../ScreenReaderText'; -import useLocalizer from '../hooks/useLocalizer'; + +const { useLocalizer } = hooks; const ConnectivityStatusConnected = () => { const localize = useLocalizer(); diff --git a/packages/component/src/ConnectivityStatus/Connecting.js b/packages/component/src/ConnectivityStatus/Connecting.js index 578175315c..53b6b33c2c 100644 --- a/packages/component/src/ConnectivityStatus/Connecting.js +++ b/packages/component/src/ConnectivityStatus/Connecting.js @@ -1,17 +1,19 @@ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React, { useState } from 'react'; +// TODO: No /lib/ +import useForceRender from 'botframework-webchat-api/lib/hooks/internal/useForceRender'; +import useTimer from 'botframework-webchat-api/lib/hooks/internal/useTimer'; + import ScreenReaderText from '../ScreenReaderText'; import SpinnerAnimation from './Assets/SpinnerAnimation'; -import useDirection from '../hooks/useDirection'; -import useForceRender from '../hooks/internal/useForceRender'; -import useLocalizer from '../hooks/useLocalizer'; -import useStyleOptions from '../hooks/useStyleOptions'; import useStyleSet from '../hooks/useStyleSet'; -import useTimer from '../hooks/internal/useTimer'; import WarningNotificationIcon from './Assets/WarningNotificationIcon'; +const { useDirection, useLocalizer, useStyleOptions } = hooks; + const ConnectivityStatusConnecting = ({ reconnect }) => { const [{ slowConnectionAfter }] = useStyleOptions(); const [ diff --git a/packages/component/src/ConnectivityStatus/FailedToConnect.js b/packages/component/src/ConnectivityStatus/FailedToConnect.js index b5e55788a1..716bc8fd06 100644 --- a/packages/component/src/ConnectivityStatus/FailedToConnect.js +++ b/packages/component/src/ConnectivityStatus/FailedToConnect.js @@ -1,12 +1,13 @@ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import React from 'react'; import ErrorNotificationIcon from './Assets/ErrorNotificationIcon'; import ScreenReaderText from '../ScreenReaderText'; -import useDirection from '../hooks/useDirection'; -import useLocalizer from '../hooks/useLocalizer'; import useStyleSet from '../hooks/useStyleSet'; +const { useDirection, useLocalizer } = hooks; + const ConnectivityStatusFailedToConnect = () => { const [{ errorNotification: errorNotificationStyleSet }] = useStyleSet(); const [direction] = useDirection(); diff --git a/packages/component/src/ConnectivityStatus/JavaScriptError.js b/packages/component/src/ConnectivityStatus/JavaScriptError.js index ef77b619b0..d2e298efeb 100644 --- a/packages/component/src/ConnectivityStatus/JavaScriptError.js +++ b/packages/component/src/ConnectivityStatus/JavaScriptError.js @@ -1,12 +1,13 @@ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import React from 'react'; import ErrorNotificationIcon from './Assets/ErrorNotificationIcon'; import ScreenReaderText from '../ScreenReaderText'; -import useDirection from '../hooks/useDirection'; -import useLocalizer from '../hooks/useLocalizer'; import useStyleSet from '../hooks/useStyleSet'; +const { useDirection, useLocalizer } = hooks; + const ConnectivityStatusJavaScriptError = () => { const [{ errorNotification: errorNotificationStyleSet }] = useStyleSet(); const [direction] = useDirection(); diff --git a/packages/component/src/ErrorBox.js b/packages/component/src/ErrorBox.js index 0b95f5c590..4eddcafbf1 100644 --- a/packages/component/src/ErrorBox.js +++ b/packages/component/src/ErrorBox.js @@ -1,34 +1,35 @@ /* eslint no-console: "off" */ +import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; import React, { useEffect } from 'react'; import ScreenReaderText from './ScreenReaderText'; -import useLocalizer from './hooks/useLocalizer'; import useStyleSet from './hooks/useStyleSet'; -import useTrackException from './hooks/useTrackException'; -const ErrorBox = ({ children, error, message }) => { +const { useLocalizer, useTrackException } = hooks; + +const ErrorBox = ({ error, type }) => { const [{ errorBox: errorBoxStyleSet }] = useStyleSet(); const localize = useLocalizer(); const trackException = useTrackException(); useEffect(() => { - const errorObject = error || new Error(message); + const errorObject = error || new Error(type); trackException(errorObject, false); - console.group(`botframework-webchat: ${message}`); + console.group(`botframework-webchat: ${type}`); console.error(errorObject); console.groupEnd(); - }, [error, message, trackException]); + }, [error, type, trackException]); return (
-
{message}
-
{children}
+
{type}
+
{error.stack}
); @@ -37,13 +38,13 @@ const ErrorBox = ({ children, error, message }) => { ErrorBox.defaultProps = { children: undefined, error: undefined, - message: '' + type: '' }; ErrorBox.propTypes = { children: PropTypes.any, - error: PropTypes.instanceOf(Error), - message: PropTypes.string + error: PropTypes.instanceOf(Error).isRequired, + type: PropTypes.string }; export default ErrorBox; diff --git a/packages/component/src/Middleware/Activity/createCoreMiddleware.js b/packages/component/src/Middleware/Activity/createCoreMiddleware.js index 98bd8c258a..538cca9e19 100644 --- a/packages/component/src/Middleware/Activity/createCoreMiddleware.js +++ b/packages/component/src/Middleware/Activity/createCoreMiddleware.js @@ -4,64 +4,68 @@ import CarouselLayout from '../../Activity/CarouselLayout'; import StackedLayout from '../../Activity/StackedLayout'; export default function createCoreMiddleware() { - return () => next => (...args) => { - const [{ activity }] = args; + return [ + () => next => (...args) => { + const [{ activity }] = args; - // TODO: [P4] Can we simplify these if-statement to something more readable? + // console.log('defaultActivity', { activity, args }); - const { type } = activity; + // TODO: [P4] Can we simplify these if-statement to something more readable? - // Filter out activities that should not be visible - if (type === 'conversationUpdate' || type === 'event' || type === 'invoke' || type === 'typing') { - return false; - } else if (type === 'message') { - const { attachments = [], channelData, text } = activity; + const { type } = activity; - if ( - // Do not show postback - (channelData && channelData.postBack) || - // Do not show messageBack if displayText is undefined - (channelData && channelData.messageBack && !channelData.messageBack.displayText) || - // Do not show empty bubbles (no text and attachments, and not "typing") - !(text || attachments.length) - ) { + // Filter out activities that should not be visible + if (type === 'conversationUpdate' || type === 'event' || type === 'invoke' || type === 'typing') { + return false; + } else if (type === 'message') { + const { attachments = [], channelData, text } = activity; + + if ( + // Do not show postback + (channelData && channelData.postBack) || + // Do not show messageBack if displayText is undefined + (channelData && channelData.messageBack && !channelData.messageBack.displayText) || + // Do not show empty bubbles (no text and attachments, and not "typing") + !(text || attachments.length) + ) { + return false; + } + } else if (type === 'typing' && activity.from.role === 'user') { + // Do not show typing by oneself return false; } - } else if (type === 'typing' && activity.from.role === 'user') { - // Do not show typing by oneself - return false; - } - if (type === 'message' || type === 'typing') { - if (type === 'message' && (activity.attachments || []).length > 1 && activity.attachmentLayout === 'carousel') { - // The following line is not a React functional component, it's a render function called by useCreateActivityRenderer() hook. - // The function signature need to be compatible with older version of activity middleware, which was: - // - // renderActivity( - // renderAttachment: ({ activity, attachment }) => React.Element - // ) => React.Element + if (type === 'message' || type === 'typing') { + if (type === 'message' && (activity.attachments || []).length > 1 && activity.attachmentLayout === 'carousel') { + // The following line is not a React functional component, it's a render function called by useCreateActivityRenderer() hook. + // The function signature need to be compatible with older version of activity middleware, which was: + // + // renderActivity( + // renderAttachment: ({ activity, attachment }) => React.Element + // ) => React.Element + + return function renderCarouselLayout(renderAttachment, props) { + typeof props === 'undefined' && + console.warn( + 'botframework-webchat: One or more arguments were missing after passing through the activity middleware. Please check your custom activity middleware to make sure it passthrough all arguments.' + ); - return function renderCarouselLayout(renderAttachment, props) { + return ; + }; + } + + // The following line is not a React functional component, it's a render function called by useCreateActivityRenderer() hook. + return function renderStackedLayout(renderAttachment, props) { typeof props === 'undefined' && console.warn( 'botframework-webchat: One or more arguments were missing after passing through the activity middleware. Please check your custom activity middleware to make sure it passthrough all arguments.' ); - return ; + return ; }; } - // The following line is not a React functional component, it's a render function called by useCreateActivityRenderer() hook. - return function renderStackedLayout(renderAttachment, props) { - typeof props === 'undefined' && - console.warn( - 'botframework-webchat: One or more arguments were missing after passing through the activity middleware. Please check your custom activity middleware to make sure it passthrough all arguments.' - ); - - return ; - }; + return next(...args); } - - return next(...args); - }; + ]; } diff --git a/packages/component/src/Middleware/ActivityStatus/AbsoluteTime.js b/packages/component/src/Middleware/ActivityStatus/AbsoluteTime.js index 7fe6a3639b..bc4022e176 100644 --- a/packages/component/src/Middleware/ActivityStatus/AbsoluteTime.js +++ b/packages/component/src/Middleware/ActivityStatus/AbsoluteTime.js @@ -1,10 +1,10 @@ +import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; import React from 'react'; import ScreenReaderText from '../../ScreenReaderText'; -import useDateFormatter from '../../hooks/useDateFormatter'; -import useLocalizer from '../../hooks/useLocalizer'; +const { useDateFormatter, useLocalizer } = hooks; const AbsoluteTime = ({ hide, value }) => { const localize = useLocalizer(); diff --git a/packages/component/src/Middleware/ActivityStatus/RelativeTime.js b/packages/component/src/Middleware/ActivityStatus/RelativeTime.js index 47a498ee30..01ef2b96aa 100644 --- a/packages/component/src/Middleware/ActivityStatus/RelativeTime.js +++ b/packages/component/src/Middleware/ActivityStatus/RelativeTime.js @@ -1,11 +1,11 @@ +import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; import React from 'react'; +import useForceRenderAtInterval from 'botframework-webchat-api/lib/hooks/internal/useForceRenderAtInterval'; import ScreenReaderText from '../../ScreenReaderText'; -import useDateFormatter from '../../hooks/useDateFormatter'; -import useForceRenderAtInterval from '../../hooks/internal/useForceRenderAtInterval'; -import useLocalizer from '../../hooks/useLocalizer'; -import useRelativeTimeFormatter from '../../hooks/useRelativeTimeFormatter'; + +const { useDateFormatter, useLocalizer, useRelativeTimeFormatter } = hooks; const TIMER_INTERVAL = 60000; diff --git a/packages/component/src/Middleware/ActivityStatus/SendStatus/SendFailedRetry.js b/packages/component/src/Middleware/ActivityStatus/SendStatus/SendFailedRetry.js index bab21a14f8..708c92dd00 100644 --- a/packages/component/src/Middleware/ActivityStatus/SendStatus/SendFailedRetry.js +++ b/packages/component/src/Middleware/ActivityStatus/SendStatus/SendFailedRetry.js @@ -1,8 +1,10 @@ +import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; import React, { useCallback } from 'react'; import InlineMarkdown from '../../../Utils/InlineMarkdown'; -import useLocalizer from '../../../hooks/useLocalizer'; + +const { useLocalizer } = hooks; const MARKDOWN_REFERENCES = ['RETRY']; diff --git a/packages/component/src/Middleware/ActivityStatus/SendStatus/SendStatus.js b/packages/component/src/Middleware/ActivityStatus/SendStatus/SendStatus.js index 639eb7e8c3..fa06e5dccf 100644 --- a/packages/component/src/Middleware/ActivityStatus/SendStatus/SendStatus.js +++ b/packages/component/src/Middleware/ActivityStatus/SendStatus/SendStatus.js @@ -1,15 +1,15 @@ import { Constants } from 'botframework-webchat-core'; +import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; import React, { useCallback } from 'react'; import connectToWebChat from '../../../connectToWebChat'; import ScreenReaderText from '../../../ScreenReaderText'; import SendFailedRetry from './SendFailedRetry'; -import useFocus from '../../../hooks/useFocus'; -import useLocalizer from '../../../hooks/useLocalizer'; -import usePostActivity from '../../../hooks/usePostActivity'; import useStyleSet from '../../../hooks/useStyleSet'; +const { useFocus, useLocalizer, usePostActivity } = hooks; + const { ActivityClientState: { SEND_FAILED, SENDING } } = Constants; diff --git a/packages/component/src/Middleware/ActivityStatus/Timestamp.js b/packages/component/src/Middleware/ActivityStatus/Timestamp.js index 3149522861..992cf996e4 100644 --- a/packages/component/src/Middleware/ActivityStatus/Timestamp.js +++ b/packages/component/src/Middleware/ActivityStatus/Timestamp.js @@ -1,12 +1,14 @@ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; import AbsoluteTime from './AbsoluteTime'; import RelativeTime from './RelativeTime'; -import useStyleOptions from '../../hooks/useStyleOptions'; import useStyleSet from '../../hooks/useStyleSet'; +const { useStyleOptions } = hooks; + const Timestamp = ({ activity: { timestamp }, className }) => { const [{ timestampFormat }] = useStyleOptions(); const [{ timestamp: timestampStyleSet, sendStatus: sendStatusStyleSet }] = useStyleSet(); diff --git a/packages/component/src/Middleware/ActivityStatus/createCoreMiddleware.js b/packages/component/src/Middleware/ActivityStatus/createCoreMiddleware.js index c157d820d2..080948748f 100644 --- a/packages/component/src/Middleware/ActivityStatus/createCoreMiddleware.js +++ b/packages/component/src/Middleware/ActivityStatus/createCoreMiddleware.js @@ -1,7 +1,6 @@ -import concatMiddleware from '../concatMiddleware'; import createSendStatusMiddleware from './createSendStatusMiddleware'; import createTimestampMiddleware from './createTimestampMiddleware'; export default function createCoreMiddleware() { - return concatMiddleware(createSendStatusMiddleware(), createTimestampMiddleware()); + return [createSendStatusMiddleware(), createTimestampMiddleware()]; } diff --git a/packages/component/src/Middleware/ActivityStatus/createTimestampMiddleware.js b/packages/component/src/Middleware/ActivityStatus/createTimestampMiddleware.js index 3007821409..e5fb7f54b9 100644 --- a/packages/component/src/Middleware/ActivityStatus/createTimestampMiddleware.js +++ b/packages/component/src/Middleware/ActivityStatus/createTimestampMiddleware.js @@ -7,6 +7,8 @@ export default function createTimestampMiddleware() { return () => () => (...args) => { const [{ activity, hideTimestamp }] = args; + console.log('createTimestampMiddleware', { args }); + if (hideTimestamp) { // If "hideTimestamp" is set, we will not render the visual timestamp. But continue to render the screen reader only version. return ; diff --git a/packages/component/src/Middleware/Attachment/createCoreMiddleware.js b/packages/component/src/Middleware/Attachment/createCoreMiddleware.js index 5d75af256c..9a3f8148b7 100644 --- a/packages/component/src/Middleware/Attachment/createCoreMiddleware.js +++ b/packages/component/src/Middleware/Attachment/createCoreMiddleware.js @@ -9,38 +9,45 @@ import VideoAttachment from '../../Attachment/VideoAttachment'; // TODO: [P4] Rename this file or the whole middleware, it looks either too simple or too comprehensive now export default function createCoreMiddleware() { - return () => next => { - const Attachment = ({ - activity = {}, - activity: { from: { role } = {} } = {}, - attachment, - attachment: { contentType, contentUrl, thumbnailUrl } = {} - }) => - role === 'user' && !/^text\//u.test(contentType) && !thumbnailUrl ? ( - - ) : /^audio\//u.test(contentType) ? ( - - ) : /^image\//u.test(contentType) ? ( - - ) : /^video\//u.test(contentType) ? ( - - ) : contentUrl || contentType === 'application/octet-stream' ? ( - - ) : /^text\//u.test(contentType) ? ( - - ) : ( - next({ activity, attachment }) - ); + return [ + () => next => { + const Attachment = args => { + // console.log('defaultAttachmentMiddleware', { activity, args, attachment }); - Attachment.propTypes = { - activity: PropTypes.any.isRequired, - attachment: PropTypes.shape({ - contentType: PropTypes.string.isRequired, - contentUrl: PropTypes.string, - thumbnailUrl: PropTypes.string - }).isRequired - }; + const { + activity = {}, + activity: { from: { role } = {} } = {}, + attachment, + attachment: { contentType, contentUrl, thumbnailUrl } = {} + } = args; - return Attachment; - }; + return role === 'user' && !/^text\//u.test(contentType) && !thumbnailUrl ? ( + + ) : /^audio\//u.test(contentType) ? ( + + ) : /^image\//u.test(contentType) ? ( + + ) : /^video\//u.test(contentType) ? ( + + ) : contentUrl || contentType === 'application/octet-stream' ? ( + + ) : /^text\//u.test(contentType) ? ( + + ) : ( + next({ activity, attachment }) + ); + }; + + Attachment.propTypes = { + activity: PropTypes.any.isRequired, + attachment: PropTypes.shape({ + contentType: PropTypes.string.isRequired, + contentUrl: PropTypes.string, + thumbnailUrl: PropTypes.string + }).isRequired + }; + + return Attachment; + } + ]; } diff --git a/packages/component/src/Middleware/TypingIndicator/createCoreMiddleware.js b/packages/component/src/Middleware/TypingIndicator/createCoreMiddleware.js index 3a7d8e84c0..6a7db62240 100644 --- a/packages/component/src/Middleware/TypingIndicator/createCoreMiddleware.js +++ b/packages/component/src/Middleware/TypingIndicator/createCoreMiddleware.js @@ -1,13 +1,14 @@ /* eslint react/prop-types: "off"*/ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import React from 'react'; import TypingAnimation from '../../Assets/TypingAnimation'; -import useDirection from '../../hooks/useDirection'; -import useLocalizer from '../../hooks/useLocalizer'; import useStyleSet from '../../hooks/useStyleSet'; +const { useDirection, useLocalizer } = hooks; + const DotIndicator = () => { const [{ typingIndicator: typingIndicatorStyleSet }] = useStyleSet(); const [direction] = useDirection(); diff --git a/packages/component/src/Middleware/createActivityRenderer.js b/packages/component/src/Middleware/createActivityRenderer.js index 10e193b79e..311edff4c4 100644 --- a/packages/component/src/Middleware/createActivityRenderer.js +++ b/packages/component/src/Middleware/createActivityRenderer.js @@ -1,12 +1,14 @@ /* eslint no-magic-numbers: ["error", { "ignore": [2] }] */ +import { hooks } from 'botframework-webchat-api'; import React, { useEffect } from 'react'; import PropTypes from 'prop-types'; import concatMiddleware from './concatMiddleware'; import createCoreActivityMiddleware from './Activity/createCoreMiddleware'; import ErrorBox from '../ErrorBox'; -import useTrackException from '../hooks/useTrackException'; + +const { useTrackException } = hooks; const SilentError = ({ message }) => { const trackException = useTrackException(); diff --git a/packages/component/src/Middleware/createActivityStatusRenderer.js b/packages/component/src/Middleware/createActivityStatusRenderer.js index 38c26eeb06..fa9dad9fdc 100644 --- a/packages/component/src/Middleware/createActivityStatusRenderer.js +++ b/packages/component/src/Middleware/createActivityStatusRenderer.js @@ -17,7 +17,7 @@ export default function createActivityStatusRenderer(additionalMiddleware) { // The next line is not a React component. It is a render function. // eslint-disable-next-line react/display-name return () => ( - +
{JSON.stringify({ message, stack }, null, 2)}
); diff --git a/packages/component/src/ScreenReaderActivity.js b/packages/component/src/ScreenReaderActivity.js index 1d81dcb6d5..bfe142b775 100644 --- a/packages/component/src/ScreenReaderActivity.js +++ b/packages/component/src/ScreenReaderActivity.js @@ -1,17 +1,16 @@ /* eslint no-magic-numbers: ["error", { "ignore": [2] }] */ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; import textFormatToContentType from './Utils/textFormatToContentType'; -import useAvatarForBot from './hooks/useAvatarForBot'; -import useCreateAttachmentForScreenReaderRenderer from './hooks/useCreateAttachmentForScreenReaderRenderer'; -import useDateFormatter from './hooks/useDateFormatter'; -import useLocalizer from './hooks/useLocalizer'; import useStripMarkdown from './hooks/internal/useStripMarkdown'; import useStyleToEmotionObject from './hooks/internal/useStyleToEmotionObject'; +const { useAvatarForBot, useCreateAttachmentForScreenReaderRenderer, useDateFormatter, useLocalizer } = hooks; + const ROOT_STYLE = { '&.webchat__screen-reader-activity': { color: 'transparent', diff --git a/packages/component/src/SendBox/Assets/SendIcon.js b/packages/component/src/SendBox/Assets/SendIcon.js index bc80b99524..b772b8cb68 100644 --- a/packages/component/src/SendBox/Assets/SendIcon.js +++ b/packages/component/src/SendBox/Assets/SendIcon.js @@ -1,9 +1,11 @@ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import React from 'react'; -import useDirection from '../../hooks/useDirection'; import useStyleToEmotionObject from '../../hooks/internal/useStyleToEmotionObject'; +const { useDirection } = hooks; + const ROOT_STYLE = { '&.webchat__send-icon': { '&.webchat__send-icon--rtl': { diff --git a/packages/component/src/SendBox/DictationInterims.js b/packages/component/src/SendBox/DictationInterims.js index dfebebe79d..c0bb89f6f8 100644 --- a/packages/component/src/SendBox/DictationInterims.js +++ b/packages/component/src/SendBox/DictationInterims.js @@ -1,15 +1,12 @@ /* eslint react/no-array-index-key: "off" */ +import { Constants } from 'botframework-webchat-core'; +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; -import { Constants } from 'botframework-webchat-core'; - import connectToWebChat from '../connectToWebChat'; -import useDictateInterims from '../hooks/useDictateInterims'; -import useDictateState from '../hooks/useDictateState'; -import useLocalizer from '../hooks/useLocalizer'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; @@ -17,6 +14,8 @@ const { DictateState: { DICTATING, STARTING, STOPPING } } = Constants; +const { useDictateInterims, useDictateState, useLocalizer } = hooks; + const ROOT_STYLE = { alignItems: 'center', display: 'flex' diff --git a/packages/component/src/SendBox/MicrophoneButton.js b/packages/component/src/SendBox/MicrophoneButton.js index ab81061e0b..065517a3f3 100644 --- a/packages/component/src/SendBox/MicrophoneButton.js +++ b/packages/component/src/SendBox/MicrophoneButton.js @@ -2,6 +2,7 @@ /* eslint react/forbid-dom-props: "off" */ import { Constants } from 'botframework-webchat-core'; +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import memoize from 'memoize-one'; import PropTypes from 'prop-types'; @@ -10,21 +11,24 @@ import React, { useCallback, useState } from 'react'; import connectToWebChat from '../connectToWebChat'; import IconButton from './IconButton'; import MicrophoneIcon from './Assets/MicrophoneIcon'; -import useDictateAbortable from '../hooks/useDictateAbortable'; -import useDictateInterims from '../hooks/useDictateInterims'; -import useDictateState from '../hooks/useDictateState'; -import useDisabled from '../hooks/useDisabled'; -import useLocalizer from '../hooks/useLocalizer'; -import useSendBoxValue from '../hooks/useSendBoxValue'; -import useShouldSpeakIncomingActivity from '../hooks/useShouldSpeakIncomingActivity'; -import useStartDictate from '../hooks/useStartDictate'; -import useStopDictate from '../hooks/useStopDictate'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; -import useWebSpeechPonyfill from '../hooks/useWebSpeechPonyfill'; const { DictateState } = Constants; +const { + useDictateAbortable, + useDictateInterims, + useDictateState, + useDisabled, + useLocalizer, + useSendBoxValue, + useShouldSpeakIncomingActivity, + useStartDictate, + useStopDictate, + useWebSpeechPonyfill +} = hooks; + const ROOT_STYLE = { display: 'flex', height: '100%', diff --git a/packages/component/src/SendBox/SendButton.js b/packages/component/src/SendBox/SendButton.js index ce5bf319cf..cee7992f61 100644 --- a/packages/component/src/SendBox/SendButton.js +++ b/packages/component/src/SendBox/SendButton.js @@ -1,13 +1,11 @@ +import { hooks } from 'botframework-webchat-api'; import React, { useCallback } from 'react'; import connectToWebChat from '../connectToWebChat'; import IconButton from './IconButton'; import SendIcon from './Assets/SendIcon'; -import useDisabled from '../hooks/useDisabled'; -import useFocus from '../hooks/useFocus'; -import useLocalizer from '../hooks/useLocalizer'; -import useScrollToEnd from '../hooks/useScrollToEnd'; -import useSubmitSendBox from '../hooks/useSubmitSendBox'; + +const { useDisabled, useFocus, useLocalizer, useScrollToEnd, useSubmitSendBox } = hooks; const connectSendButton = (...selectors) => connectToWebChat( diff --git a/packages/component/src/SendBox/SuggestedAction.js b/packages/component/src/SendBox/SuggestedAction.js index 353dde3565..0f06246828 100644 --- a/packages/component/src/SendBox/SuggestedAction.js +++ b/packages/component/src/SendBox/SuggestedAction.js @@ -1,20 +1,17 @@ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React, { useCallback, useRef } from 'react'; import AccessibleButton from '../Utils/AccessibleButton'; import connectToWebChat from '../connectToWebChat'; -import useDirection from '../hooks/useDirection'; -import useDisabled from '../hooks/useDisabled'; -import useFocus from '../hooks/useFocus'; import useFocusAccessKeyEffect from '../Utils/AccessKeySink/useFocusAccessKeyEffect'; import useLocalizeAccessKey from '../hooks/internal/useLocalizeAccessKey'; -import usePerformCardAction from '../hooks/usePerformCardAction'; -import useScrollToEnd from '../hooks/useScrollToEnd'; +import useSuggestedActionsAccessKey from '../hooks/internal/useSuggestedActionsAccessKey'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; -import useSuggestedActions from '../hooks/useSuggestedActions'; -import useSuggestedActionsAccessKey from '../hooks/internal/useSuggestedActionsAccessKey'; + +const { useDirection, useDisabled, useFocus, usePerformCardAction, useScrollToEnd, useSuggestedActions } = hooks; const ROOT_STYLE = { '&.webchat__suggested-action': { diff --git a/packages/component/src/SendBox/SuggestedActions.js b/packages/component/src/SendBox/SuggestedActions.js index d28bbe7525..ff073e0ea8 100644 --- a/packages/component/src/SendBox/SuggestedActions.js +++ b/packages/component/src/SendBox/SuggestedActions.js @@ -1,5 +1,6 @@ /* eslint react/no-array-index-key: "off" */ +import { hooks } from 'botframework-webchat-api'; import BasicFilm, { createBasicStyleSet as createBasicStyleSetForReactFilm } from 'react-film'; import classNames from 'classnames'; import PropTypes from 'prop-types'; @@ -8,16 +9,15 @@ import React, { useMemo } from 'react'; import connectToWebChat from '../connectToWebChat'; import ScreenReaderText from '../ScreenReaderText'; import SuggestedAction from './SuggestedAction'; -import useDirection from '../hooks/useDirection'; import useLocalizeAccessKey from '../hooks/internal/useLocalizeAccessKey'; -import useLocalizer from '../hooks/useLocalizer'; import useNonce from '../hooks/internal/useNonce'; -import useStyleOptions from '../hooks/useStyleOptions'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; import useSuggestedActionsAccessKey from '../hooks/internal/useSuggestedActionsAccessKey'; import useUniqueId from '../hooks/internal/useUniqueId'; +const { useDirection, useLocalizer, useStyleOptions } = hooks; + const ROOT_STYLE = { '&.webchat__suggested-actions .webchat__suggested-actions__stack': { display: 'flex', diff --git a/packages/component/src/SendBox/TextBox.js b/packages/component/src/SendBox/TextBox.js index afbdb71d92..d65e6d3fed 100644 --- a/packages/component/src/SendBox/TextBox.js +++ b/packages/component/src/SendBox/TextBox.js @@ -1,23 +1,29 @@ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import React, { forwardRef, useCallback, useEffect, useRef } from 'react'; +// TODO: No /lib/ +import useReplaceEmoticon from 'botframework-webchat-api/lib/hooks/internal/useReplaceEmoticon'; + import { Context as TypeFocusSinkContext } from '../Utils/TypeFocusSink'; import AccessibleInputText from '../Utils/AccessibleInputText'; import AccessibleTextArea from '../Utils/AccessibleTextArea'; import connectToWebChat from '../connectToWebChat'; -import useDisabled from '../hooks/useDisabled'; -import useFocus from '../hooks/useFocus'; -import useLocalizer from '../hooks/useLocalizer'; -import useReplaceEmoticon from '../hooks/internal/useReplaceEmoticon'; import useScrollToEnd from '../hooks/useScrollToEnd'; -import useSendBoxValue from '../hooks/useSendBoxValue'; -import useStopDictate from '../hooks/useStopDictate'; -import useStyleOptions from '../hooks/useStyleOptions'; import useStyleSet from '../hooks/useStyleSet'; -import useSubmitSendBox from '../hooks/useSubmitSendBox'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; +const { + useDisabled, + useFocus, + useLocalizer, + useSendBoxValue, + useStopDictate, + useStyleOptions, + useSubmitSendBox +} = hooks; + const ROOT_STYLE = { '&.webchat__send-box-text-box': { display: 'flex', diff --git a/packages/component/src/SendBox/UploadButton.js b/packages/component/src/SendBox/UploadButton.js index a37a158c0e..3e099500fc 100644 --- a/packages/component/src/SendBox/UploadButton.js +++ b/packages/component/src/SendBox/UploadButton.js @@ -1,16 +1,18 @@ +import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import React, { useCallback, useRef } from 'react'; +// TODO: No /lib/ +import downscaleImageToDataURL from 'botframework-webchat-api/lib/utils/downscaleImageToDataURL'; + import AttachmentIcon from './Assets/AttachmentIcon'; import connectToWebChat from '../connectToWebChat'; -import downscaleImageToDataURL from '../Utils/downscaleImageToDataURL'; import IconButton from './IconButton'; -import useDisabled from '../hooks/useDisabled'; -import useLocalizer from '../hooks/useLocalizer'; -import useSendFiles from '../hooks/useSendFiles'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; +const { useDisabled, useLocalizer, useSendFiles } = hooks; + const ROOT_STYLE = { overflow: 'hidden', position: 'relative', diff --git a/packages/component/src/Toast/NotificationIcon.js b/packages/component/src/Toast/NotificationIcon.js index af134e0972..d27b21bad9 100644 --- a/packages/component/src/Toast/NotificationIcon.js +++ b/packages/component/src/Toast/NotificationIcon.js @@ -1,9 +1,11 @@ +import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; import React from 'react'; import CheckMarkIcon from './CheckMarkIcon'; import ExclamationMarkIcon from './ExclamationMarkIcon'; -import useLocalizer from '../hooks/useLocalizer'; + +const { useLocalizer } = hooks; const NotificationIcon = ({ className, level }) => { const localize = useLocalizer(); diff --git a/packages/component/src/Utils/InlineMarkdown.js b/packages/component/src/Utils/InlineMarkdown.js index 85ace47525..93b2303d80 100644 --- a/packages/component/src/Utils/InlineMarkdown.js +++ b/packages/component/src/Utils/InlineMarkdown.js @@ -1,16 +1,18 @@ /* eslint react/no-danger: "off" */ +import { hooks } from 'botframework-webchat-api'; +import createCustomEvent from 'botframework-webchat-api/lib/utils/createCustomEvent'; import PropTypes from 'prop-types'; import React, { useCallback, useMemo } from 'react'; import updateIn from 'simple-update-in'; -import createCustomEvent from '../Utils/createCustomEvent'; import randomId from './randomId'; import useInternalMarkdownIt from '../hooks/internal/useInternalMarkdownIt'; -import useStyleOptions from '../hooks/useStyleOptions'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; import walkMarkdownTokens from './walkMarkdownTokens'; +const { useStyleOptions } = hooks; + function replaceAnchorWithButton(markdownTokens) { return walkMarkdownTokens(markdownTokens, markdownToken => { markdownToken = { ...markdownToken }; diff --git a/packages/component/src/Utils/singleToArray.js b/packages/component/src/Utils/singleToArray.js new file mode 100644 index 0000000000..873ed8ef89 --- /dev/null +++ b/packages/component/src/Utils/singleToArray.js @@ -0,0 +1,3 @@ +export default function singleToArray(singleOrArray) { + return singleOrArray ? (Array.isArray(singleOrArray) ? singleOrArray : [singleOrArray]) : []; +} diff --git a/packages/component/src/Utils/upgradeLegacyRendererMiddleware.js b/packages/component/src/Utils/upgradeLegacyRendererMiddleware.js new file mode 100644 index 0000000000..cb2bae7467 --- /dev/null +++ b/packages/component/src/Utils/upgradeLegacyRendererMiddleware.js @@ -0,0 +1,20 @@ +import { isValidElement } from 'react'; + +// For uniformity, we are patching legacy renderer middleware signature to newer one. +// - Legacy: () => next => args => next(args): React.Element +// - Current: () => next => args => next(args): false | () => React.Element +export default function upgradeLegacyRendererMiddleware(middleware) { + return (...setupArgs) => { + const setup = middleware(...setupArgs); + + return next => { + const runMiddleware = setup(next); + + return (...renderArgs) => { + const result = runMiddleware(...renderArgs); + + return !!result && (isValidElement(result) ? () => result : result); + }; + }; + }; +} diff --git a/packages/component/src/connectToWebChat.js b/packages/component/src/connectToWebChat.js index 84c1de44b8..58210d5516 100644 --- a/packages/component/src/connectToWebChat.js +++ b/packages/component/src/connectToWebChat.js @@ -1,8 +1,9 @@ import { connect } from 'react-redux'; import React from 'react'; -import WebChatReduxContext from './WebChatReduxContext'; -import WebChatUIContext from './WebChatUIContext'; +// TODO: Think about if we should also include WebChatUIContext. +import WebChatReduxContext from 'botframework-webchat-api/lib/hooks/internal/WebChatReduxContext'; +import WebChatAPIContext from 'botframework-webchat-api/lib/hooks/internal/WebChatAPIContext'; function removeUndefinedValues(map) { return Object.keys(map).reduce((result, key) => { @@ -43,9 +44,9 @@ export default function connectToWebChat(...selectors) { )(Component); const WebChatConnectedComponent = props => ( - + {context => } - + ); return WebChatConnectedComponent; diff --git a/packages/component/src/hooks/internal/WebChatUIContext.js b/packages/component/src/hooks/internal/WebChatUIContext.js new file mode 100644 index 0000000000..bcfb4e6924 --- /dev/null +++ b/packages/component/src/hooks/internal/WebChatUIContext.js @@ -0,0 +1,5 @@ +import { createContext } from 'react'; + +const context = createContext(); + +export default context; diff --git a/packages/component/src/hooks/internal/useDirFromProps.js b/packages/component/src/hooks/internal/useDirFromProps.js deleted file mode 100644 index 1eaa09b034..0000000000 --- a/packages/component/src/hooks/internal/useDirFromProps.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './useWebChatUIContext'; - -export default function useDirFromProps() { - return [useWebChatUIContext().dir]; -} diff --git a/packages/component/src/hooks/internal/useDisableOnBlurEffect.js b/packages/component/src/hooks/internal/useDisableOnBlurEffect.js deleted file mode 100644 index f2bf2ffee7..0000000000 --- a/packages/component/src/hooks/internal/useDisableOnBlurEffect.js +++ /dev/null @@ -1,34 +0,0 @@ -import { useEffect } from 'react'; - -// Because different browser handling disabled-but-focused UI different, we are implementing a more general solution. -// When the button is being disabled: -// - If it is not currently focused, we will set "disabled"; -// - If it is currently focused, we will not set "disabled" until it is blurred (focus moved away). -function disableElement(element) { - element.setAttribute('disabled', 'disabled'); -} - -export default function useDisableOnBlurEffect(targetRef, disabled) { - useEffect(() => { - if (disabled) { - const { current } = targetRef; - - if (current) { - if (document.activeElement !== current) { - current.setAttribute('disabled', 'disabled'); - - return () => current.removeAttribute('disabled'); - } - - const blurHandler = disableElement.bind(null, current); - - current.addEventListener('blur', blurHandler); - - return () => { - current.removeAttribute('disabled'); - current.removeEventListener('blur', blurHandler); - }; - } - } - }, [disabled, targetRef]); -} diff --git a/packages/component/src/hooks/internal/useLocalizeAccessKey.js b/packages/component/src/hooks/internal/useLocalizeAccessKey.js index 80c67ee6ae..e533b09fa7 100644 --- a/packages/component/src/hooks/internal/useLocalizeAccessKey.js +++ b/packages/component/src/hooks/internal/useLocalizeAccessKey.js @@ -1,8 +1,10 @@ import { useCallback } from 'react'; +import { hooks } from 'botframework-webchat-api'; -import useLocalizer from './../useLocalizer'; import useNavigatorPlatform from './useNavigatorPlatform'; +const { useLocalizer } = hooks; + export default function useLocalizeAccessKey() { const [{ apple }] = useNavigatorPlatform(); const localize = useLocalizer(); diff --git a/packages/component/src/hooks/internal/useLocalizedGlobalize.js b/packages/component/src/hooks/internal/useLocalizedGlobalize.js deleted file mode 100644 index 2aea086720..0000000000 --- a/packages/component/src/hooks/internal/useLocalizedGlobalize.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './useWebChatUIContext'; - -export default function useLocalizedGlobalize() { - return useWebChatUIContext().localizedGlobalizeState; -} diff --git a/packages/component/src/hooks/internal/useLocalizedStrings.js b/packages/component/src/hooks/internal/useLocalizedStrings.js deleted file mode 100644 index d62d6a4ce9..0000000000 --- a/packages/component/src/hooks/internal/useLocalizedStrings.js +++ /dev/null @@ -1,7 +0,0 @@ -import useWebChatUIContext from './useWebChatUIContext'; - -export default function useLocalizedStrings() { - const { localizedStrings } = useWebChatUIContext(); - - return localizedStrings; -} diff --git a/packages/component/src/hooks/internal/useMarkActivity.js b/packages/component/src/hooks/internal/useMarkActivity.js deleted file mode 100644 index 6c421b9635..0000000000 --- a/packages/component/src/hooks/internal/useMarkActivity.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './useWebChatUIContext'; - -export default function useMarkActivity() { - return useWebChatUIContext().markActivity; -} diff --git a/packages/component/src/hooks/internal/useSendBoxFocusRef.js b/packages/component/src/hooks/internal/useSendBoxFocusRef.js deleted file mode 100644 index 5c52290314..0000000000 --- a/packages/component/src/hooks/internal/useSendBoxFocusRef.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './useWebChatUIContext'; - -export default function useSendBoxFocusRef() { - return [useWebChatUIContext().sendBoxFocusRef]; -} diff --git a/packages/component/src/hooks/internal/useSetDictateState.js b/packages/component/src/hooks/internal/useSetDictateState.js deleted file mode 100644 index 40042b6110..0000000000 --- a/packages/component/src/hooks/internal/useSetDictateState.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './useWebChatUIContext'; - -export default function useSetDictateState() { - return useWebChatUIContext().setDictateState; -} diff --git a/packages/component/src/hooks/internal/useSettableDictateAbortable.js b/packages/component/src/hooks/internal/useSettableDictateAbortable.js deleted file mode 100644 index d5352421b1..0000000000 --- a/packages/component/src/hooks/internal/useSettableDictateAbortable.js +++ /dev/null @@ -1,7 +0,0 @@ -import useWebChatUIContext from './useWebChatUIContext'; - -export default function useSettableDictateAbortable() { - const { dictateAbortable, setDictateAbortable } = useWebChatUIContext(); - - return [dictateAbortable, setDictateAbortable]; -} diff --git a/packages/component/src/hooks/internal/useStyleToEmotionObject.js b/packages/component/src/hooks/internal/useStyleToEmotionObject.js index 257e34f982..ed9e4e1e52 100644 --- a/packages/component/src/hooks/internal/useStyleToEmotionObject.js +++ b/packages/component/src/hooks/internal/useStyleToEmotionObject.js @@ -1,3 +1,4 @@ +// TODO: No /lib/ import useWebChatUIContext from './useWebChatUIContext'; export default function useStyleToEmotionObject() { diff --git a/packages/component/src/hooks/internal/useTranscriptFocusRef.js b/packages/component/src/hooks/internal/useTranscriptFocusRef.js deleted file mode 100644 index 81b846a8a2..0000000000 --- a/packages/component/src/hooks/internal/useTranscriptFocusRef.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './useWebChatUIContext'; - -export default function useTranscriptFocusRef() { - return [useWebChatUIContext().transcriptFocusRef]; -} diff --git a/packages/component/src/hooks/internal/useWebChatUIContext.js b/packages/component/src/hooks/internal/useWebChatUIContext.js index 89797ee6b7..c33adb32b3 100644 --- a/packages/component/src/hooks/internal/useWebChatUIContext.js +++ b/packages/component/src/hooks/internal/useWebChatUIContext.js @@ -1,6 +1,6 @@ import { useContext } from 'react'; -import WebChatUIContext from '../../WebChatUIContext'; +import WebChatUIContext from './WebChatUIContext'; export default function useWebChatUIContext() { const context = useContext(WebChatUIContext); diff --git a/packages/component/src/hooks/useDictateInterims.js b/packages/component/src/hooks/useDictateInterims.js deleted file mode 100644 index 41bd858e67..0000000000 --- a/packages/component/src/hooks/useDictateInterims.js +++ /dev/null @@ -1,6 +0,0 @@ -import { useSelector } from '../WebChatReduxContext'; -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useDictateInterims() { - return [useSelector(({ dictateInterims }) => dictateInterims) || [], useWebChatUIContext().setDictateInterims]; -} diff --git a/packages/component/src/hooks/useDisabled.js b/packages/component/src/hooks/useDisabled.js deleted file mode 100644 index 998aa26b7c..0000000000 --- a/packages/component/src/hooks/useDisabled.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useDisabled() { - return [useWebChatUIContext().disabled]; -} diff --git a/packages/component/src/hooks/useDismissNotification.js b/packages/component/src/hooks/useDismissNotification.js deleted file mode 100644 index b5b7b9606f..0000000000 --- a/packages/component/src/hooks/useDismissNotification.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useDismissNotification() { - return useWebChatUIContext().dismissNotification; -} diff --git a/packages/component/src/hooks/useEmitTypingIndicator.js b/packages/component/src/hooks/useEmitTypingIndicator.js deleted file mode 100644 index 8407033d07..0000000000 --- a/packages/component/src/hooks/useEmitTypingIndicator.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useEmitTypingIndicator() { - return useWebChatUIContext().emitTypingIndicator; -} diff --git a/packages/component/src/hooks/useFocus.js b/packages/component/src/hooks/useFocus.js deleted file mode 100644 index dddf3c1607..0000000000 --- a/packages/component/src/hooks/useFocus.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useFocus() { - return useWebChatUIContext().focus; -} diff --git a/packages/component/src/hooks/useGrammars.js b/packages/component/src/hooks/useGrammars.js deleted file mode 100644 index 9c40af3436..0000000000 --- a/packages/component/src/hooks/useGrammars.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useGrammars() { - return [useWebChatUIContext().grammars]; -} diff --git a/packages/component/src/hooks/useGroupActivities.js b/packages/component/src/hooks/useGroupActivities.js deleted file mode 100644 index 766572d070..0000000000 --- a/packages/component/src/hooks/useGroupActivities.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useGroupActivities() { - return useWebChatUIContext().groupActivities; -} diff --git a/packages/component/src/hooks/usePerformCardAction.js b/packages/component/src/hooks/usePerformCardAction.js deleted file mode 100644 index b2b55b5b5b..0000000000 --- a/packages/component/src/hooks/usePerformCardAction.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function usePerformCardAction() { - return useWebChatUIContext().onCardAction; -} diff --git a/packages/component/src/hooks/usePostActivity.js b/packages/component/src/hooks/usePostActivity.js deleted file mode 100644 index 424f009352..0000000000 --- a/packages/component/src/hooks/usePostActivity.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function usePostActivity() { - return useWebChatUIContext().postActivity; -} diff --git a/packages/component/src/hooks/useRenderAttachment.js b/packages/component/src/hooks/useRenderAttachment.js deleted file mode 100644 index 85b0d4bc1e..0000000000 --- a/packages/component/src/hooks/useRenderAttachment.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useRenderAttachment() { - return useWebChatUIContext().attachmentRenderer; -} diff --git a/packages/component/src/hooks/useRenderToast.js b/packages/component/src/hooks/useRenderToast.js deleted file mode 100644 index c58aa2b571..0000000000 --- a/packages/component/src/hooks/useRenderToast.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useRenderToast() { - return useWebChatUIContext().toastRenderer; -} diff --git a/packages/component/src/hooks/useRenderTypingIndicator.js b/packages/component/src/hooks/useRenderTypingIndicator.js deleted file mode 100644 index a7fb615bce..0000000000 --- a/packages/component/src/hooks/useRenderTypingIndicator.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useRenderTypingIndicator() { - return useWebChatUIContext().typingIndicatorRenderer; -} diff --git a/packages/component/src/hooks/useSendBoxValue.js b/packages/component/src/hooks/useSendBoxValue.js deleted file mode 100644 index a0f7996155..0000000000 --- a/packages/component/src/hooks/useSendBoxValue.js +++ /dev/null @@ -1,6 +0,0 @@ -import { useSelector } from '../WebChatReduxContext'; -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useSendBoxValue() { - return [useSelector(({ sendBoxValue }) => sendBoxValue), useWebChatUIContext().setSendBox]; -} diff --git a/packages/component/src/hooks/useSendEvent.js b/packages/component/src/hooks/useSendEvent.js deleted file mode 100644 index 5b0cd5917c..0000000000 --- a/packages/component/src/hooks/useSendEvent.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useSendEvent() { - return useWebChatUIContext().sendEvent; -} diff --git a/packages/component/src/hooks/useSendMessage.js b/packages/component/src/hooks/useSendMessage.js deleted file mode 100644 index 9fc76ce578..0000000000 --- a/packages/component/src/hooks/useSendMessage.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useSendMessage() { - return useWebChatUIContext().sendMessage; -} diff --git a/packages/component/src/hooks/useSendMessageBack.js b/packages/component/src/hooks/useSendMessageBack.js deleted file mode 100644 index cab2adf271..0000000000 --- a/packages/component/src/hooks/useSendMessageBack.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useSendMessageBack() { - return useWebChatUIContext().sendMessageBack; -} diff --git a/packages/component/src/hooks/useSendPostBack.js b/packages/component/src/hooks/useSendPostBack.js deleted file mode 100644 index 3c8ae82a3a..0000000000 --- a/packages/component/src/hooks/useSendPostBack.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useSendPostBack() { - return useWebChatUIContext().sendPostBack; -} diff --git a/packages/component/src/hooks/useSetNotification.js b/packages/component/src/hooks/useSetNotification.js deleted file mode 100644 index 5c98e252db..0000000000 --- a/packages/component/src/hooks/useSetNotification.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useSetNotification() { - return useWebChatUIContext().setNotification; -} diff --git a/packages/component/src/hooks/useStartDictate.js b/packages/component/src/hooks/useStartDictate.js deleted file mode 100644 index d239864cb9..0000000000 --- a/packages/component/src/hooks/useStartDictate.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useStartDictate() { - return useWebChatUIContext().startDictate; -} diff --git a/packages/component/src/hooks/useStopDictate.js b/packages/component/src/hooks/useStopDictate.js deleted file mode 100644 index 755c39bd43..0000000000 --- a/packages/component/src/hooks/useStopDictate.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useStopDictate() { - return useWebChatUIContext().stopDictate; -} diff --git a/packages/component/src/hooks/useStyleOptions.js b/packages/component/src/hooks/useStyleOptions.js deleted file mode 100644 index 7370332786..0000000000 --- a/packages/component/src/hooks/useStyleOptions.js +++ /dev/null @@ -1,8 +0,0 @@ -import useStyleSet from './useStyleSet'; - -export default function useStyleOptions() { - // Today, the "styleSet.options" is patched with missing values and "styleOptions" are unpatched. - // Thus, we are using the "styleSet.options" version for now. - - return [useStyleSet()[0].options]; -} diff --git a/packages/component/src/hooks/useTrackDimension.js b/packages/component/src/hooks/useTrackDimension.js deleted file mode 100644 index a5c0c1480f..0000000000 --- a/packages/component/src/hooks/useTrackDimension.js +++ /dev/null @@ -1,7 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useTrackDimension() { - const { trackDimension } = useWebChatUIContext(); - - return trackDimension; -} diff --git a/packages/component/src/hooks/useUserID.js b/packages/component/src/hooks/useUserID.js deleted file mode 100644 index b081469fc4..0000000000 --- a/packages/component/src/hooks/useUserID.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useUserID() { - return [useWebChatUIContext().userID]; -} diff --git a/packages/component/src/hooks/useUsername.js b/packages/component/src/hooks/useUsername.js deleted file mode 100644 index 80c67e277a..0000000000 --- a/packages/component/src/hooks/useUsername.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useUsername() { - return [useWebChatUIContext().username]; -} diff --git a/packages/component/src/hooks/useWebSpeechPonyfill.js b/packages/component/src/hooks/useWebSpeechPonyfill.js deleted file mode 100644 index 2cde9d2fba..0000000000 --- a/packages/component/src/hooks/useWebSpeechPonyfill.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useWebSpeechPonyfill() { - return [useWebChatUIContext().webSpeechPonyfill]; -} diff --git a/packages/component/src/index.tsx b/packages/component/src/index.tsx index 9679c797ad..24590d29f1 100644 --- a/packages/component/src/index.tsx +++ b/packages/component/src/index.tsx @@ -7,7 +7,7 @@ import BasicWebChat from './BasicWebChat'; import Avatar from './Activity/Avatar'; import Bubble from './Activity/Bubble'; import ErrorBox from './ErrorBox'; -import Localize, { localize } from './Localization/Localize'; +// import Localize, { localize } from './Localization/Localize'; import SendStatus, { connectSendStatus } from './Middleware/ActivityStatus/SendStatus/SendStatus'; import SpeakActivity, { connectSpeakActivity } from './Activity/Speak'; import Timestamp from './Middleware/ActivityStatus/Timestamp'; @@ -30,7 +30,7 @@ import UploadButton, { connectUploadButton } from './SendBox/UploadButton'; import concatMiddleware from './Middleware/concatMiddleware'; import connectToWebChat from './connectToWebChat'; -import Context from './WebChatUIContext'; +import Context from './hooks/internal/WebChatUIContext'; import createCoreActivityMiddleware from './Middleware/Activity/createCoreMiddleware'; import createCoreActivityStatusMiddleware from './Middleware/ActivityStatus/createCoreMiddleware'; import createCoreAttachmentMiddleware from './Middleware/Attachment/createCoreMiddleware'; @@ -38,14 +38,15 @@ import createStyleSet from './Styles/createStyleSet'; import defaultStyleOptions from './Styles/defaultStyleOptions'; import getTabIndex from './Utils/TypeFocusSink/getTabIndex'; -import * as hooks from './hooks/index'; +// TODO: Add deprecation notes when someone is using hooks from bf-wc-component, instead of bf-wc-core. +import { hooks } from 'botframework-webchat-api'; const version = process.env.npm_package_version; const Components = { BasicWebChat, Composer, - Localize, + // Localize, // Components for recomposing activities and attachments AudioContent, @@ -98,6 +99,6 @@ export { defaultStyleOptions, getTabIndex, hooks, - localize, + // localize, version }; From 3dbd54c4520a681df0ea413ea83589e4b95ea464 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 5 Oct 2020 13:57:27 -0700 Subject: [PATCH 02/21] Continue refactoring --- packages/api/package-lock.json | 580 +----------------- packages/api/package.json | 10 +- packages/api/src/defaultStyleOptions.js | 1 + packages/api/src/hooks/Composer.js | 195 ++---- packages/api/src/hooks/Composer.oldjs | 29 - packages/api/src/hooks/index.js | 26 - packages/api/src/hooks/internal/ErrorBox.js | 6 +- .../src/hooks/internal/WebChatAPIContext.js | 4 +- .../internal/useDownscaleImageToDataURL.js | 7 + .../src/hooks/internal/useSendBoxFocusRef.js | 5 - packages/api/src/hooks/internal/useTracker.js | 5 - .../hooks/internal/useTranscriptFocusRef.js | 5 - .../src/hooks/middleware/UserlandBoundary.js | 4 +- .../src/hooks/middleware/applyMiddleware.js | 31 +- .../createDefaultCardActionMiddleware.js | 36 ++ packages/api/src/hooks/useFocus.js | 5 - packages/api/src/hooks/useSendFiles.js | 71 +-- packages/api/src/hooks/utils/ErrorBoundary.js | 4 +- .../{ => hooks}/utils/observableToPromise.js | 0 .../src/Activity/ScrollToEndButton.js | 3 +- .../component/src/Activity/StackedLayout.js | 2 - .../component/src/Attachment/TextContent.js | 4 +- packages/component/src/BasicTranscript.js | 2 +- packages/component/src/BasicWebChat.js | 6 +- packages/component/src/Composer.js | 146 ++++- .../src/ConnectivityStatus/Connecting.js | 6 +- .../Middleware/ActivityStatus/RelativeTime.js | 2 +- .../ActivityStatus/SendStatus/SendStatus.js | 3 +- .../createTimestampMiddleware.js | 2 - .../Middleware/Avatar/createCoreMiddleware.js | 19 +- .../CardAction/createCoreMiddleware.js | 90 ++- .../Middleware/Toast/createCoreMiddleware.js | 5 +- .../TypingIndicator/createCoreMiddleware.js | 2 +- packages/component/src/SendBox/SendButton.js | 4 +- .../component/src/SendBox/SuggestedAction.js | 4 +- packages/component/src/SendBox/TextBox.js | 15 +- .../component/src/SendBox/UploadButton.js | 7 +- .../component/src/Utils/InlineMarkdown.js | 8 +- .../src/Utils/TypeFocusSink/Context.js | 4 +- .../component/src/Utils/createCustomEvent.js | 17 + .../blobToArrayBuffer.js | 0 .../downscaleImageToDataURLUsingBrowser.js | 0 .../downscaleImageToDataURLUsingWorker.js | 57 +- ...wnscaleImageToDataURLUsingWorker.worker.js | 0 .../Utils/downscaleImageToDataURL/index.js} | 0 .../Utils/upgradeLegacyRendererMiddleware.js | 20 - packages/component/src/hooks/index.js | 30 + .../component/src/hooks/internal/UITracker.js | 19 + .../src/hooks/internal/useForceRender.js | 9 + .../internal/useForceRenderAtInterval.js | 0 .../useGetTranscriptActivityElementByID.js | 0 .../src/hooks/internal/useReplaceEmoticon.js | 3 +- .../src/hooks/internal/useSendBoxFocusRef.js | 5 + .../hooks/internal/useStyleToEmotionObject.js | 1 - .../component/src/hooks/internal/useTimer.js | 11 + .../hooks/internal/useTranscriptFocusRef.js | 5 + packages/component/src/hooks/useFocus.js | 5 + .../src/hooks/useFocusSendBox.js | 0 .../src/hooks/useRenderMarkdownAsHTML.js | 8 +- packages/component/src/hooks/useSendFiles.js | 82 +++ packages/component/src/index.tsx | 8 +- 61 files changed, 552 insertions(+), 1086 deletions(-) delete mode 100644 packages/api/src/hooks/Composer.oldjs create mode 100644 packages/api/src/hooks/internal/useDownscaleImageToDataURL.js delete mode 100644 packages/api/src/hooks/internal/useSendBoxFocusRef.js delete mode 100644 packages/api/src/hooks/internal/useTranscriptFocusRef.js create mode 100644 packages/api/src/hooks/middleware/createDefaultCardActionMiddleware.js delete mode 100644 packages/api/src/hooks/useFocus.js rename packages/api/src/{ => hooks}/utils/observableToPromise.js (100%) create mode 100644 packages/component/src/Utils/createCustomEvent.js rename packages/{api/src/utils => component/src/Utils/downscaleImageToDataURL}/blobToArrayBuffer.js (100%) rename packages/{api/src/utils => component/src/Utils/downscaleImageToDataURL}/downscaleImageToDataURLUsingBrowser.js (100%) rename packages/{api/src/utils => component/src/Utils/downscaleImageToDataURL}/downscaleImageToDataURLUsingWorker.js (74%) rename packages/{api/src/utils => component/src/Utils/downscaleImageToDataURL}/downscaleImageToDataURLUsingWorker.worker.js (100%) rename packages/{api/src/utils/downscaleImageToDataURL.js => component/src/Utils/downscaleImageToDataURL/index.js} (100%) delete mode 100644 packages/component/src/Utils/upgradeLegacyRendererMiddleware.js create mode 100644 packages/component/src/hooks/index.js create mode 100644 packages/component/src/hooks/internal/UITracker.js create mode 100644 packages/component/src/hooks/internal/useForceRender.js rename packages/{api => component}/src/hooks/internal/useForceRenderAtInterval.js (100%) rename packages/{api => component}/src/hooks/internal/useGetTranscriptActivityElementByID.js (100%) rename packages/{api => component}/src/hooks/internal/useReplaceEmoticon.js (96%) create mode 100644 packages/component/src/hooks/internal/useSendBoxFocusRef.js create mode 100644 packages/component/src/hooks/internal/useTimer.js create mode 100644 packages/component/src/hooks/internal/useTranscriptFocusRef.js create mode 100644 packages/component/src/hooks/useFocus.js rename packages/{api => component}/src/hooks/useFocusSendBox.js (100%) rename packages/{api => component}/src/hooks/useRenderMarkdownAsHTML.js (57%) create mode 100644 packages/component/src/hooks/useSendFiles.js diff --git a/packages/api/package-lock.json b/packages/api/package-lock.json index 77dca1e680..38b33de15b 100644 --- a/packages/api/package-lock.json +++ b/packages/api/package-lock.json @@ -1108,71 +1108,6 @@ "to-fast-properties": "^2.0.0" } }, - "@emotion/cache": { - "version": "10.0.29", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz", - "integrity": "sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==", - "requires": { - "@emotion/sheet": "0.9.4", - "@emotion/stylis": "0.8.5", - "@emotion/utils": "0.11.3", - "@emotion/weak-memoize": "0.2.5" - } - }, - "@emotion/hash": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", - "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" - }, - "@emotion/memoize": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", - "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==" - }, - "@emotion/serialize": { - "version": "0.11.16", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.11.16.tgz", - "integrity": "sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg==", - "requires": { - "@emotion/hash": "0.8.0", - "@emotion/memoize": "0.7.4", - "@emotion/unitless": "0.7.5", - "@emotion/utils": "0.11.3", - "csstype": "^2.5.7" - }, - "dependencies": { - "csstype": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", - "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==" - } - } - }, - "@emotion/sheet": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-0.9.4.tgz", - "integrity": "sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA==" - }, - "@emotion/stylis": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", - "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" - }, - "@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" - }, - "@emotion/utils": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.11.3.tgz", - "integrity": "sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw==" - }, - "@emotion/weak-memoize": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz", - "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==" - }, "@eslint/eslintrc": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz", @@ -1250,7 +1185,8 @@ "@types/node": { "version": "14.11.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.2.tgz", - "integrity": "sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA==" + "integrity": "sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA==", + "dev": true }, "@types/prop-types": { "version": "15.7.3", @@ -1268,29 +1204,6 @@ "csstype": "^3.0.2" } }, - "@types/unist": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", - "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==" - }, - "@types/vfile": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz", - "integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==", - "requires": { - "@types/node": "*", - "@types/unist": "*", - "@types/vfile-message": "*" - } - }, - "@types/vfile-message": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-2.0.0.tgz", - "integrity": "sha512-GpTIuDpb9u4zIO165fUy9+fXcULdD8HFRNli04GehoMVbeNq7D6OBnqSmg3lxZnC+UvgUhEWKxdKiwYUkGltIw==", - "requires": { - "vfile-message": "*" - } - }, "@webassemblyjs/ast": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", @@ -1552,6 +1465,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -1781,11 +1695,6 @@ "integrity": "sha1-o7CYgzU76LXiM24/8e+KXZP5xIk=", "dev": true }, - "bail": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", - "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==" - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -2118,11 +2027,6 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, - "ccount": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.5.tgz", - "integrity": "sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw==" - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -2133,26 +2037,6 @@ "supports-color": "^5.3.0" } }, - "character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==" - }, - "character-entities-html4": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.4.tgz", - "integrity": "sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g==" - }, - "character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==" - }, - "character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" - }, "chokidar": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", @@ -2305,11 +2189,6 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, - "collapse-white-space": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", - "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==" - }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -2480,17 +2359,6 @@ } } }, - "create-emotion": { - "version": "10.0.27", - "resolved": "https://registry.npmjs.org/create-emotion/-/create-emotion-10.0.27.tgz", - "integrity": "sha512-fIK73w82HPPn/RsAij7+Zt8eCE8SptcJ3WoRMfxMtjteYxud8GDTKKld7MYwAX2TVhrw29uR1N/bVGxeStHILg==", - "requires": { - "@emotion/cache": "^10.0.27", - "@emotion/serialize": "^0.11.15", - "@emotion/sheet": "0.9.4", - "@emotion/utils": "0.11.3" - } - }, "create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", @@ -2707,44 +2575,11 @@ "esutils": "^2.0.2" } }, - "dom-serializer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.1.0.tgz", - "integrity": "sha512-ox7bvGXt2n+uLWtCRLybYx60IrOlWL/aCebWJk1T0d4m3y2tzf4U3ij9wBMUb6YJZpz06HCCYuyCDveE2xXmzQ==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^3.0.0", - "entities": "^2.0.0" - } - }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" }, - "domelementtype": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", - "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==" - }, - "domhandler": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.0.0.tgz", - "integrity": "sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==", - "requires": { - "domelementtype": "^2.0.1" - } - }, - "domutils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.3.0.tgz", - "integrity": "sha512-xWC75PM3QF6MjE5e58OzwTX0B/rPQnlqH0YyXB/c056RtVJA+eu60da2I/bdnEHzEYC00g8QaZUlAbqOZVbOsw==", - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.0.1", - "domhandler": "^3.0.0" - } - }, "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -2857,11 +2692,6 @@ "ansi-colors": "^4.1.1" } }, - "entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" - }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -3451,7 +3281,8 @@ "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true }, "extend-shallow": { "version": "3.0.2", @@ -4095,17 +3926,6 @@ "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "dev": true }, - "htmlparser2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz", - "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^3.0.0", - "domutils": "^2.0.0", - "entities": "^2.0.0" - } - }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -4285,25 +4105,6 @@ } } }, - "is-alphabetical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==" - }, - "is-alphanumeric": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", - "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=" - }, - "is-alphanumerical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", - "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", - "requires": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - } - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -4352,11 +4153,6 @@ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" }, - "is-decimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==" - }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", @@ -4397,11 +4193,6 @@ "is-extglob": "^2.1.1" } }, - "is-hexadecimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==" - }, "is-negative-zero": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", @@ -4425,11 +4216,6 @@ } } }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" - }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -4471,21 +4257,11 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "is-whitespace-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", - "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==" - }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" }, - "is-word-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", - "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==" - }, "is-wsl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", @@ -4659,14 +4435,6 @@ "type-check": "~0.4.0" } }, - "linkify-it": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz", - "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==", - "requires": { - "uc.micro": "^1.0.1" - } - }, "loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -4706,11 +4474,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, - "longest-streak": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", - "integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==" - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4749,28 +4512,6 @@ "object-visit": "^1.0.0" } }, - "markdown-escapes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", - "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==" - }, - "markdown-it": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-11.0.0.tgz", - "integrity": "sha512-+CvOnmbSubmQFSA9dKz1BRiaSMV7rhexl3sngKqFyXSagoA3fBdJQ8oZWtRy2knXdpDXaBw44euz37DeJQ9asg==", - "requires": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - } - }, - "markdown-table": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", - "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==" - }, "math-random": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/math-random/-/math-random-2.0.1.tgz", @@ -4786,19 +4527,6 @@ "safe-buffer": "^5.1.2" } }, - "mdast-util-compact": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.4.tgz", - "integrity": "sha512-3YDMQHI5vRiS2uygEFYaqckibpJtKq5Sj2c8JioeOQBU6INpKbdWzfyLqFFnDwEcEnRFIdMsguzs5pC1Jp4Isg==", - "requires": { - "unist-util-visit": "^1.1.0" - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" - }, "memoize-one": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-4.0.3.tgz", @@ -5364,19 +5092,6 @@ "safe-buffer": "^5.1.1" } }, - "parse-entities": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", - "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", - "requires": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - } - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -5392,11 +5107,6 @@ "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" }, - "parse-srcset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", - "integrity": "sha1-8r0iH2zJcKk42IVWq8WJyqqiveE=" - }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -5509,31 +5219,6 @@ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, - "postcss": { - "version": "7.0.34", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.34.tgz", - "integrity": "sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -5703,25 +5388,6 @@ "memoize-one": "^4.0.0" } }, - "react-film": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/react-film/-/react-film-3.0.0.tgz", - "integrity": "sha512-aBiMFc/srZWWRal/va39YZVMcQiqUAyJ+G6n5CADnpdS+MO73x/jY50Aawwx+Aqyf/LJFO3d/8fR1WE74DYqOw==", - "requires": { - "classnames": "2.2.6", - "create-emotion": "10.0.27", - "math-random": "2.0.1", - "memoize-one": "5.1.1", - "prop-types": "15.7.2" - }, - "dependencies": { - "memoize-one": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz", - "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==" - } - } - }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -5757,18 +5423,6 @@ } } }, - "react-scroll-to-bottom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/react-scroll-to-bottom/-/react-scroll-to-bottom-4.0.0.tgz", - "integrity": "sha512-7lOy14XbBdweO+8LMRp7F9nP0xWtf0mAt+I5rm1hbNZq5JcXJRn0dsZjz9ySDLleH+zMlyhPwinqFDmEEUdHtA==", - "requires": { - "classnames": "2.2.6", - "create-emotion": "10.0.27", - "math-random": "2.0.1", - "prop-types": "15.7.2", - "simple-update-in": "2.2.0" - } - }, "read-pkg": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", @@ -5927,59 +5581,6 @@ } } }, - "remark": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/remark/-/remark-10.0.1.tgz", - "integrity": "sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ==", - "requires": { - "remark-parse": "^6.0.0", - "remark-stringify": "^6.0.0", - "unified": "^7.0.0" - } - }, - "remark-parse": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-6.0.3.tgz", - "integrity": "sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg==", - "requires": { - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^1.1.0", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^1.0.0", - "vfile-location": "^2.0.0", - "xtend": "^4.0.1" - } - }, - "remark-stringify": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-6.0.4.tgz", - "integrity": "sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg==", - "requires": { - "ccount": "^1.0.0", - "is-alphanumeric": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "longest-streak": "^2.0.1", - "markdown-escapes": "^1.0.0", - "markdown-table": "^1.1.0", - "mdast-util-compact": "^1.0.0", - "parse-entities": "^1.0.2", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "stringify-entities": "^1.0.1", - "unherit": "^1.0.4", - "xtend": "^4.0.1" - } - }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -5996,11 +5597,6 @@ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" - }, "request": { "version": "2.87.0", "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", @@ -6160,17 +5756,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "sanitize-html": { - "version": "1.27.4", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.27.4.tgz", - "integrity": "sha512-VvY1hxVvMXzSos/LzqeBl9/KYu3mkEOtl5NMwz6jER318dSHDCig0AOjZOtnoCwAC3HMs9LhfWkPCmQGttb4ng==", - "requires": { - "htmlparser2": "^4.1.0", - "lodash": "^4.17.15", - "parse-srcset": "^1.0.2", - "postcss": "^7.0.27" - } - }, "schema-utils": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", @@ -6476,7 +6061,8 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true }, "sshpk": { "version": "1.16.1", @@ -6503,11 +6089,6 @@ "figgy-pudding": "^3.5.1" } }, - "state-toggle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", - "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==" - }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -6673,17 +6254,6 @@ "safe-buffer": "~5.1.0" } }, - "stringify-entities": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", - "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", - "requires": { - "character-entities-html4": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-hexadecimal": "^1.0.0" - } - }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -6698,11 +6268,6 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, - "strip-markdown": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/strip-markdown/-/strip-markdown-3.0.4.tgz", - "integrity": "sha512-O+0DAu96wofH82JPZN4RkGdi3Lruo0yveDCeXUg0uRNWztPcn/s1AD85584OYUsAcjW0qR4pBlh8OBl/hH4Erw==" - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -6904,21 +6469,6 @@ "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true }, - "trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" - }, - "trim-trailing-lines": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz", - "integrity": "sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA==" - }, - "trough": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", - "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==" - }, "tslib": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", @@ -6975,20 +6525,6 @@ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.22.tgz", "integrity": "sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q==" }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" - }, - "unherit": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", - "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", - "requires": { - "inherits": "^2.0.0", - "xtend": "^4.0.0" - } - }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -7013,21 +6549,6 @@ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==" }, - "unified": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-7.1.0.tgz", - "integrity": "sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==", - "requires": { - "@types/unist": "^2.0.0", - "@types/vfile": "^3.0.0", - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^1.1.0", - "trough": "^1.0.0", - "vfile": "^3.0.0", - "x-is-string": "^0.1.0" - } - }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -7055,43 +6576,6 @@ "imurmurhash": "^0.1.4" } }, - "unist-util-is": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", - "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==" - }, - "unist-util-remove-position": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", - "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", - "requires": { - "unist-util-visit": "^1.1.0" - } - }, - "unist-util-stringify-position": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", - "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", - "requires": { - "@types/unist": "^2.0.2" - } - }, - "unist-util-visit": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", - "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", - "requires": { - "unist-util-visit-parents": "^2.0.0" - } - }, - "unist-util-visit-parents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", - "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", - "requires": { - "unist-util-is": "^3.0.0" - } - }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -7220,51 +6704,6 @@ "extsprintf": "^1.2.0" } }, - "vfile": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz", - "integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==", - "requires": { - "is-buffer": "^2.0.0", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-message": "^1.0.0" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" - }, - "unist-util-stringify-position": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", - "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==" - }, - "vfile-message": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", - "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", - "requires": { - "unist-util-stringify-position": "^1.1.1" - } - } - } - }, - "vfile-location": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", - "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==" - }, - "vfile-message": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", - "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", - "requires": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^2.0.0" - } - }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -7585,11 +7024,6 @@ "mkdirp": "^0.5.1" } }, - "x-is-string": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", - "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=" - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/packages/api/package.json b/packages/api/package.json index a25397bbd0..049db7d6d4 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -54,22 +54,16 @@ }, "dependencies": { "botframework-webchat-core": "^0.0.0-0", - "classnames": "2.2.6", - "create-emotion": "10.0.27", "event-target-shim": "5.0.1", "event-target-shim-es5": "1.2.0", "globalize": "1.5.0", - "markdown-it": "11.0.0", + "math-random": "2.0.1", "prop-types": "15.7.2", "react-dictate-button": "1.2.3-master.6b4fe72", - "react-film": "3.0.0", "react-redux": "7.2.0", "react-say": "2.0.2-master.ee7cd76", - "react-scroll-to-bottom": "4.0.0", "redux": "4.0.5", - "remark": "10.0.1", - "sanitize-html": "1.27.4", - "strip-markdown": "3.0.4" + "simple-update-in": "2.2.0" }, "peerDependencies": { "react": "^16.8.6", diff --git a/packages/api/src/defaultStyleOptions.js b/packages/api/src/defaultStyleOptions.js index df315fad03..63b1d36593 100644 --- a/packages/api/src/defaultStyleOptions.js +++ b/packages/api/src/defaultStyleOptions.js @@ -163,6 +163,7 @@ const DEFAULT_OPTIONS = { spinnerAnimationWidth: 16, spinnerAnimationPadding: 12, + // TODO: [PXX] This is only supported on HTML. enableUploadThumbnail: true, uploadThumbnailContentType: 'image/jpeg', uploadThumbnailHeight: 360, diff --git a/packages/api/src/hooks/Composer.js b/packages/api/src/hooks/Composer.js index 24cbe639cd..22104bc9b9 100644 --- a/packages/api/src/hooks/Composer.js +++ b/packages/api/src/hooks/Composer.js @@ -5,13 +5,7 @@ import PropTypes from 'prop-types'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import updateIn from 'simple-update-in'; -// import createActivityRenderer from './Middleware/createActivityRenderer'; -// import createActivityStatusRenderer from './Middleware/createActivityStatusRenderer'; -// import createAttachmentRenderer from './Middleware/createAttachmentRenderer'; -// import createAvatarRenderer from './Middleware/createAvatarRenderer'; import createCustomEvent from '../utils/createCustomEvent'; -// import createToastRenderer from './Middleware/createToastRenderer'; -// import createTypingIndicatorRenderer from './Middleware/createTypingIndicatorRenderer'; import ErrorBoundary from './utils/ErrorBoundary'; import getAllLocalizedStrings from '../localization/getAllLocalizedStrings'; import isObject from '../utils/isObject'; @@ -48,13 +42,13 @@ import { } from 'botframework-webchat-core'; // import concatMiddleware from './Middleware/concatMiddleware'; -// import createCoreCardActionMiddleware from './Middleware/CardAction/createCoreMiddleware'; +import createDefaultCardActionMiddleware from './middleware/createDefaultCardActionMiddleware'; // import createDefaultGroupActivitiesMiddleware from './Middleware/GroupActivities/createCoreMiddleware'; import createDefaultGroupActivitiesMiddleware from './middleware/createDefaultGroupActivitiesMiddleware'; import defaultSelectVoice from './internal/defaultSelectVoice'; import Dictation from './internal/Dictation'; import mapMap from '../utils/mapMap'; -// import observableToPromise from './utils/observableToPromise'; +import observableToPromise from './utils/observableToPromise'; import Tracker from './internal/Tracker'; import WebChatReduxContext, { useDispatch } from './internal/WebChatReduxContext'; import WebChatAPIContext from './internal/WebChatAPIContext'; @@ -63,6 +57,7 @@ import { speechSynthesis as bypassSpeechSynthesis, SpeechSynthesisUtterance as BypassSpeechSynthesisUtterance } from './internal/BypassSpeechSynthesisPonyfill'; + import applyMiddleware, { forRenderer as applyMiddlewareForRenderer } from './middleware/applyMiddleware'; import patchStyleOptions from '../patchStyleOptions'; import singleToArray from './utils/singleToArray'; @@ -91,77 +86,46 @@ const DISPATCHERS = { submitSendBox }; -// TODO: Fix this function createCardActionContext({ cardActionMiddleware, directLine, dispatch }) { - return { - onCardAction: () => { - throw new Error('Implement onCardAction'); - } - }; - - // const runMiddleware = concatMiddleware(cardActionMiddleware, createCoreCardActionMiddleware())({ dispatch }); - - // return { - // onCardAction: (cardAction, { target } = {}) => - // runMiddleware(({ cardAction: { type } }) => { - // throw new Error(`Web Chat: received unknown card action "${type}"`); - // })({ - // cardAction, - // getSignInUrl: - // cardAction.type === 'signin' - // ? () => { - // const { value } = cardAction; - - // if (directLine.getSessionId) { - // // TODO: [P3] We should change this one to async/await. - // // This is the first place in this project to use async. - // // Thus, we need to add @babel/plugin-transform-runtime and @babel/runtime. - - // return observableToPromise(directLine.getSessionId()).then( - // sessionId => `${value}${encodeURIComponent(`&code_challenge=${sessionId}`)}` - // ); - // } - - // console.warn('botframework-webchat: OAuth is not supported on this Direct Line adapter.'); - - // return value; - // } - // : null, - // target - // }) - // }; -} + const runMiddleware = applyMiddleware( + 'card action', + ...singleToArray(cardActionMiddleware), + createDefaultCardActionMiddleware() + )({ dispatch }); -function createFocusContext({ sendBoxFocusRef, transcriptFocusRef }) { return { - focus: where => { - const ref = where === 'sendBox' || where === 'sendBoxWithoutKeyboard' ? sendBoxFocusRef : transcriptFocusRef; - const { current } = ref || {}; - - if (current) { - if (where === 'sendBoxWithoutKeyboard') { - // To not activate the virtual keyboard while changing focus to an input, we will temporarily set it as read-only and flip it back. - // https://stackoverflow.com/questions/7610758/prevent-iphone-default-keyboard-when-focusing-an-input/7610923 - const readOnly = current.getAttribute('readonly'); - - current.setAttribute('readonly', 'readonly'); - - setTimeout(() => { - current.focus(); - readOnly ? current.setAttribute('readonly', readOnly) : current.removeAttribute('readonly'); - }, 0); - } else { - current.focus(); - } - } - } + onCardAction: (cardAction, { target } = {}) => + runMiddleware({ + cardAction, + getSignInUrl: + cardAction.type === 'signin' + ? () => { + const { value } = cardAction; + + if (directLine.getSessionId) { + // TODO: [P3] We should change this one to async/await. + // This is the first place in this project to use async. + // Thus, we need to add @babel/plugin-transform-runtime and @babel/runtime. + + return observableToPromise(directLine.getSessionId()).then( + sessionId => `${value}${encodeURIComponent(`&code_challenge=${sessionId}`)}` + ); + } + + console.warn('botframework-webchat: OAuth is not supported on this Direct Line adapter.'); + + return value; + } + : null, + target + }) }; } function createGroupActivitiesContext({ groupActivitiesMiddleware, groupTimestamp }) { const runMiddleware = applyMiddleware( 'group activities', - groupActivitiesMiddleware, + ...singleToArray(groupActivitiesMiddleware), createDefaultGroupActivitiesMiddleware({ groupTimestamp }) ); @@ -204,6 +168,7 @@ const Composer = ({ dir, directLine, disabled, + downscaleImageToDataURL, grammars, groupActivitiesMiddleware, groupTimestamp, @@ -227,13 +192,10 @@ const Composer = ({ const [dictateAbortable, setDictateAbortable] = useState(); const [referenceGrammarID] = useReferenceGrammarID(); const dispatch = useDispatch(); - const sendBoxFocusRef = useRef(); const telemetryDimensionsRef = useRef({}); - const transcriptFocusRef = useRef(); const patchedDir = useMemo(() => (dir === 'ltr' || dir === 'rtl' ? dir : 'auto'), [dir]); const patchedGrammars = useMemo(() => grammars || [], [grammars]); - const patchedStyleOptions = useMemo(() => patchStyleOptions(styleOptions, { groupTimestamp, sendTimeout }), [ groupTimestamp, sendTimeout, @@ -278,11 +240,6 @@ const Composer = ({ selectVoice ]); - const focusContext = useMemo(() => createFocusContext({ sendBoxFocusRef, transcriptFocusRef }), [ - sendBoxFocusRef, - transcriptFocusRef - ]); - const groupActivitiesContext = useMemo( () => createGroupActivitiesContext({ @@ -350,20 +307,9 @@ const Composer = ({ 'Web Chat: "activityRenderer" is deprecated and will be removed on 2022-06-15, please use "activityMiddleware" instead.' ); - // console.log({ activityMiddleware, activityRenderer }); - return activityRenderer || applyMiddlewareForRenderer('activity', ...singleToArray(activityMiddleware))({}); }, [activityMiddleware, activityRenderer]); - // const patchedActivityRenderer = useMemo(() => { - // activityRenderer && - // console.warn( - // 'Web Chat: "activityRenderer" is deprecated and will be removed on 2022-06-15, please use "activityMiddleware" instead.' - // ); - - // return activityRenderer || createActivityRenderer(activityMiddleware); - // }, [activityMiddleware, activityRenderer]); - const patchedActivityStatusRenderer = useMemo(() => { activityStatusRenderer && console.warn( @@ -372,23 +318,12 @@ const Composer = ({ return ( activityStatusRenderer || - applyMiddlewareForRenderer( - 'activity status', - ...singleToArray(activityStatusMiddleware), - () => () => () => false + applyMiddlewareForRenderer('activity status', ...singleToArray(activityStatusMiddleware), () => () => () => + false )({}) ); }, [activityStatusMiddleware, activityStatusRenderer]); - // const patchedActivityStatusRenderer = useMemo(() => { - // activityStatusRenderer && - // console.warn( - // 'Web Chat: "activityStatusRenderer" is deprecated and will be removed on 2022-06-15, please use "activityStatusMiddleware" instead.' - // ); - - // return activityStatusRenderer || createActivityStatusRenderer(activityStatusMiddleware); - // }, [activityStatusMiddleware, activityStatusRenderer]); - const patchedAttachmentRenderer = useMemo(() => { if (attachmentRenderer) { console.warn( @@ -400,8 +335,6 @@ const Composer = ({ return applyMiddlewareForRenderer( 'attachment', - // TODO: [P2] Currently, attachmentMiddleware is on legacy middleware interface. - // For uniformity, we are patching the legacy interface into the current one. ...singleToArray(attachmentMiddleware), () => () => ({ attachment }) => () => { if (attachment) { @@ -413,15 +346,6 @@ const Composer = ({ )({}); }, [attachmentMiddleware, attachmentRenderer]); - // const patchedAttachmentRenderer = useMemo(() => { - // attachmentRenderer && - // console.warn( - // 'Web Chat: "attachmentRenderer" is deprecated and will be removed on 2022-06-15, please use "attachmentMiddleware" instead.' - // ); - - // return attachmentRenderer || createAttachmentRenderer(attachmentMiddleware); - // }, [attachmentMiddleware, attachmentRenderer]); - const patchedAvatarRenderer = useMemo(() => { avatarRenderer && console.warn( @@ -434,15 +358,6 @@ const Composer = ({ ); }, [avatarMiddleware, avatarRenderer]); - // const patchedAvatarRenderer = useMemo(() => { - // avatarRenderer && - // console.warn( - // 'Web Chat: "avatarRenderer" is deprecated and will be removed on 2022-06-15, please use "avatarMiddleware" instead.' - // ); - - // return avatarRenderer || createAvatarRenderer(avatarMiddleware); - // }, [avatarMiddleware, avatarRenderer]); - const patchedToastRenderer = useMemo(() => { toastRenderer && console.warn( @@ -451,7 +366,7 @@ const Composer = ({ return ( toastRenderer || - applyMiddlewareForRenderer('toast', ...singleToArray(toastRenderer), () => () => ({ notification }) => { + applyMiddlewareForRenderer('toast', ...singleToArray(toastMiddleware), () => () => ({ notification }) => { if (notification) { throw new Error(`No renderer for notification of type "${notification.contentType}"`); } else { @@ -461,15 +376,6 @@ const Composer = ({ ); }, [toastMiddleware, toastRenderer]); - // const patchedToastRenderer = useMemo(() => { - // toastRenderer && - // console.warn( - // 'Web Chat: "toastRenderer" is deprecated and will be removed on 2022-06-15, please use "toastMiddleware" instead.' - // ); - - // return toastRenderer || createToastRenderer(toastMiddleware); - // }, [toastMiddleware, toastRenderer]); - const patchedTypingIndicatorRenderer = useMemo(() => { typingIndicatorRenderer && console.warn( @@ -482,15 +388,6 @@ const Composer = ({ ); }, [typingIndicatorMiddleware, typingIndicatorRenderer]); - // const patchedTypingIndicatorRenderer = useMemo(() => { - // typingIndicatorRenderer && - // console.warn( - // 'Web Chat: "typingIndicatorRenderer" is deprecated and will be removed on 2022-06-15, please use "typingIndicatorMiddleware" instead.' - // ); - - // return typingIndicatorRenderer || createTypingIndicatorRenderer(typingIndicatorMiddleware); - // }, [typingIndicatorMiddleware, typingIndicatorRenderer]); - // This is a heavy function, and it is expected to be only called when there is a need to recreate business logic, e.g. // - User ID changed, causing all send* functions to be updated // - send @@ -505,7 +402,6 @@ const Composer = ({ const context = useMemo( () => ({ ...cardActionContext, - ...focusContext, ...groupActivitiesContext, ...hoistedDispatchers, activityRenderer: patchedActivityRenderer, @@ -516,6 +412,7 @@ const Composer = ({ dir: patchedDir, directLine, disabled, + downscaleImageToDataURL, grammars: patchedGrammars, internalErrorBoxClass, language: locale, @@ -524,14 +421,12 @@ const Composer = ({ onTelemetry, renderMarkdown, selectVoice: patchedSelectVoice, - sendBoxFocusRef, sendTypingIndicator, setDictateAbortable, styleOptions: patchedStyleOptions, telemetryDimensionsRef, toastRenderer: patchedToastRenderer, trackDimension, - transcriptFocusRef, typingIndicatorRenderer: patchedTypingIndicatorRenderer, userID, username, @@ -542,14 +437,13 @@ const Composer = ({ dictateAbortable, directLine, disabled, - focusContext, + downscaleImageToDataURL, groupActivitiesContext, hoistedDispatchers, internalErrorBoxClass, locale, localizedGlobalize, onTelemetry, - renderMarkdown, patchedActivityRenderer, patchedActivityStatusRenderer, patchedAttachmentRenderer, @@ -561,20 +455,17 @@ const Composer = ({ patchedStyleOptions, patchedToastRenderer, patchedTypingIndicatorRenderer, - sendBoxFocusRef, + renderMarkdown, sendTypingIndicator, setDictateAbortable, telemetryDimensionsRef, trackDimension, - transcriptFocusRef, userID, username, webSpeechPonyfill ] ); - // TODO: Check if react-say support RN or not - return ( @@ -643,6 +534,7 @@ Composer.defaultProps = { children: undefined, dir: 'auto', disabled: false, + downscaleImageToDataURL: undefined, grammars: [], groupActivitiesMiddleware: undefined, groupTimestamp: undefined, @@ -688,10 +580,11 @@ Composer.propTypes = { token: PropTypes.string }).isRequired, disabled: PropTypes.bool, - internalErrorBoxClass: PropTypes.func, // This is for internal use only. We don't allow customization of error box. + downscaleImageToDataURL: PropTypes.func, grammars: PropTypes.arrayOf(PropTypes.string), groupActivitiesMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), groupTimestamp: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]), + internalErrorBoxClass: PropTypes.func.isRequired, // This is for internal use only. We don't allow customization of error box. locale: PropTypes.string, onTelemetry: PropTypes.func, overrideLocalizedStrings: PropTypes.oneOfType([PropTypes.any, PropTypes.func]), diff --git a/packages/api/src/hooks/Composer.oldjs b/packages/api/src/hooks/Composer.oldjs deleted file mode 100644 index f5ac3f4aab..0000000000 --- a/packages/api/src/hooks/Composer.oldjs +++ /dev/null @@ -1,29 +0,0 @@ -import { Provider } from 'react-redux'; -import PropTypes from 'prop-types'; -import React from 'react'; - -import WebChatReduxContext, { useDispatch } from './internal/WebChatReduxContext'; -import WebChatAPIContext from './internal/WebChatAPIContext'; - -const Composer = ({ children, store }) => { - const dispatch = useDispatch(); - const memoizedStore = useMemo(() => store || createStore(), [store]); - - return ( - - - {children} - - - ); -}; - -Composer.defaultProps = { - children: undefined -}; - -Composer.propTypes = { - children: PropTypes.any -}; - -export default Composer; diff --git a/packages/api/src/hooks/index.js b/packages/api/src/hooks/index.js index 321f725614..d9484664cd 100644 --- a/packages/api/src/hooks/index.js +++ b/packages/api/src/hooks/index.js @@ -17,8 +17,6 @@ import useDirection from './useDirection'; import useDisabled from './useDisabled'; import useDismissNotification from './useDismissNotification'; import useEmitTypingIndicator from './useEmitTypingIndicator'; -import useFocus from './useFocus'; -import useFocusSendBox from './useFocusSendBox'; import useGetSendTimeoutForActivity from './useGetSendTimeoutForActivity'; import useGrammars from './useGrammars'; import useGroupActivities from './useGroupActivities'; @@ -29,7 +27,6 @@ import useLocalize from './useLocalize'; // Deprecated on or after 2022-02-12 import useLocalizeDate from './useLocalizeDate'; // Deprecated on or after 2022-02-12 import useLocalizer from './useLocalizer'; import useMarkActivityAsSpoken from './useMarkActivityAsSpoken'; -// import useObserveScrollPosition from './useObserveScrollPosition'; import usePerformCardAction from './usePerformCardAction'; import usePostActivity from './usePostActivity'; import useReferenceGrammarID from './useReferenceGrammarID'; @@ -38,11 +35,8 @@ import useRenderActivity from './useRenderActivity'; import useRenderActivityStatus from './useRenderActivityStatus'; import useRenderAttachment from './useRenderAttachment'; import useRenderAvatar from './useRenderAvatar'; -import useRenderMarkdownAsHTML from './useRenderMarkdownAsHTML'; import useRenderToast from './useRenderToast'; import useRenderTypingIndicator from './useRenderTypingIndicator'; -// import useScrollTo from './useScrollTo'; -// import useScrollToEnd from './useScrollToEnd'; import useSendBoxValue from './useSendBoxValue'; import useSendEvent from './useSendEvent'; import useSendFiles from './useSendFiles'; @@ -56,8 +50,6 @@ import useShouldSpeakIncomingActivity from './useShouldSpeakIncomingActivity'; import useStartDictate from './useStartDictate'; import useStopDictate from './useStopDictate'; import useStyleOptions from './useStyleOptions'; -// TODO: Move useStyleSet to component (DOM only) -// import useStyleSet from './useStyleSet'; import useSubmitSendBox from './useSubmitSendBox'; import useSuggestedActions from './useSuggestedActions'; import useTimeoutForSend from './useTimeoutForSend'; @@ -70,11 +62,6 @@ import useUsername from './useUsername'; import useVoiceSelector from './useVoiceSelector'; import useWebSpeechPonyfill from './useWebSpeechPonyfill'; -// import { useMicrophoneButtonClick, useMicrophoneButtonDisabled } from '../SendBox/MicrophoneButton'; -// import { useSendBoxSpeechInterimsVisible } from '../BasicSendBox'; -// import { useTextBoxSubmit, useTextBoxValue } from '../SendBox/TextBox'; -// import { useTypingIndicatorVisible } from '../BasicTypingIndicator'; - export { useActiveTyping, useActivities, @@ -95,8 +82,6 @@ export { useDisabled, useDismissNotification, useEmitTypingIndicator, - useFocus, - useFocusSendBox, useGetSendTimeoutForActivity, useGrammars, useGroupActivities, @@ -107,9 +92,6 @@ export { useLocalizeDate, useLocalizer, useMarkActivityAsSpoken, - // useMicrophoneButtonClick, - // useMicrophoneButtonDisabled, - // useObserveScrollPosition, usePerformCardAction, usePostActivity, useReferenceGrammarID, @@ -118,12 +100,8 @@ export { useRenderActivityStatus, useRenderAttachment, useRenderAvatar, - useRenderMarkdownAsHTML, useRenderToast, useRenderTypingIndicator, - // useScrollTo, - // useScrollToEnd, - // useSendBoxSpeechInterimsVisible, useSendBoxValue, useSendEvent, useSendFiles, @@ -137,17 +115,13 @@ export { useStartDictate, useStopDictate, useStyleOptions, - // useStyleSet, useSubmitSendBox, useSuggestedActions, - // useTextBoxSubmit, - // useTextBoxValue, useTimeoutForSend, useTrackDimension, useTrackEvent, useTrackException, useTrackTiming, - // useTypingIndicatorVisible, useUserID, useUsername, useVoiceSelector, diff --git a/packages/api/src/hooks/internal/ErrorBox.js b/packages/api/src/hooks/internal/ErrorBox.js index 2b4c5d25a2..83325c1cdc 100644 --- a/packages/api/src/hooks/internal/ErrorBox.js +++ b/packages/api/src/hooks/internal/ErrorBox.js @@ -1,8 +1,8 @@ -import React, { useEffect } from 'react'; +import { createElement, useEffect } from 'react'; import PropTypes from 'prop-types'; -import useTrackException from '../useTrackException'; import useErrorBoxClass from './useErrorBoxClass'; +import useTrackException from '../useTrackException'; const ErrorBox = ({ error, type }) => { const [errorBoxClass] = useErrorBoxClass(); @@ -15,7 +15,7 @@ const ErrorBox = ({ error, type }) => { // console.log({ error, errorBoxClass, type }); // console.trace(); - return React.createElement(errorBoxClass, { error, type }); + return createElement(errorBoxClass, { error, type }); }; ErrorBox.defaultProps = { diff --git a/packages/api/src/hooks/internal/WebChatAPIContext.js b/packages/api/src/hooks/internal/WebChatAPIContext.js index 39f4b2db4f..c25d3d4c41 100644 --- a/packages/api/src/hooks/internal/WebChatAPIContext.js +++ b/packages/api/src/hooks/internal/WebChatAPIContext.js @@ -1,6 +1,6 @@ -import React from 'react'; +import { createContext } from 'react'; -const context = React.createContext({ +const context = createContext({ sendFocusRef: null }); diff --git a/packages/api/src/hooks/internal/useDownscaleImageToDataURL.js b/packages/api/src/hooks/internal/useDownscaleImageToDataURL.js new file mode 100644 index 0000000000..2c0b5a08e8 --- /dev/null +++ b/packages/api/src/hooks/internal/useDownscaleImageToDataURL.js @@ -0,0 +1,7 @@ +import useWebChatAPIContext from './useWebChatAPIContext'; + +export default function useDownscaleImageToDataURL() { + const { downscaleImageToDataURL } = useWebChatAPIContext(); + + return downscaleImageToDataURL; +} diff --git a/packages/api/src/hooks/internal/useSendBoxFocusRef.js b/packages/api/src/hooks/internal/useSendBoxFocusRef.js deleted file mode 100644 index f86f831afc..0000000000 --- a/packages/api/src/hooks/internal/useSendBoxFocusRef.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatAPIContext from './useWebChatAPIContext'; - -export default function useSendBoxFocusRef() { - return [useWebChatAPIContext().sendBoxFocusRef]; -} diff --git a/packages/api/src/hooks/internal/useTracker.js b/packages/api/src/hooks/internal/useTracker.js index 31c827843c..1c9607f182 100644 --- a/packages/api/src/hooks/internal/useTracker.js +++ b/packages/api/src/hooks/internal/useTracker.js @@ -1,6 +1,5 @@ import { useEffect } from 'react'; -import { checkSupport as supportWorker } from '../../utils/downscaleImageToDataURLUsingWorker'; import { speechSynthesis } from './BypassSpeechSynthesisPonyfill'; import useLanguage from '../useLanguage'; import useTrackDimension from '../useTrackDimension'; @@ -39,10 +38,6 @@ function useTracker() { trackDimension('prop:speechSynthesis', !!speechSynthesisCapability + ''); }, [trackDimension, speechSynthesisCapability]); - useEffect(() => { - trackDimension('capability:downscaleImage:workerType', supportWorker() ? 'web worker' : 'main'); - }, [trackDimension]); - useEffect(() => { trackEvent('init'); }, [trackEvent]); diff --git a/packages/api/src/hooks/internal/useTranscriptFocusRef.js b/packages/api/src/hooks/internal/useTranscriptFocusRef.js deleted file mode 100644 index d993eb4393..0000000000 --- a/packages/api/src/hooks/internal/useTranscriptFocusRef.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatAPIContext from './useWebChatAPIContext'; - -export default function useTranscriptFocusRef() { - return [useWebChatAPIContext().transcriptFocusRef]; -} diff --git a/packages/api/src/hooks/middleware/UserlandBoundary.js b/packages/api/src/hooks/middleware/UserlandBoundary.js index 3c27f046e9..43d968fa16 100644 --- a/packages/api/src/hooks/middleware/UserlandBoundary.js +++ b/packages/api/src/hooks/middleware/UserlandBoundary.js @@ -1,5 +1,5 @@ import PropTypes from 'prop-types'; -import React, { useCallback, useState } from 'react'; +import React, { createElement, useCallback, useState } from 'react'; import ErrorBoundary from '../utils/ErrorBoundary'; import useErrorBoxClass from '../internal/useErrorBoxClass'; @@ -12,7 +12,7 @@ const UserlandBoundary = ({ children, type }) => { // console.log('UserlandBoundary', { children }); return error ? ( - React.createElement(errorBoxClass, { error, type }) + createElement(errorBoxClass, { error, type }) ) : ( {children} ); diff --git a/packages/api/src/hooks/middleware/applyMiddleware.js b/packages/api/src/hooks/middleware/applyMiddleware.js index c88de3c127..36afd610f7 100644 --- a/packages/api/src/hooks/middleware/applyMiddleware.js +++ b/packages/api/src/hooks/middleware/applyMiddleware.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { isValidElement } from 'react'; import concatMiddleware from './concatMiddleware'; import ErrorBox from '../internal/ErrorBox'; @@ -14,11 +14,9 @@ export default function applyMiddleware(type, ...middleware) { export function forRenderer(type, ...middleware) { return (...setupArgs) => { const runMiddleware = concatMiddleware(...middleware)(...setupArgs)(() => ( - + )); - // console.log('forRenderer.runMiddleware', { runMiddleware, setupArgs }); - // The createRendererArgs is "what to render", for example, activity. // The function should return with only one of the two results: // - Returns a function if there is a renderer *committed* to render; @@ -27,32 +25,15 @@ export function forRenderer(type, ...middleware) { try { const render = runMiddleware(...createRendererArgs); - // console.log(`forRenderer[${type}]`, { args: createRendererArgs, render }); - if (!render) { return false; - } else if (React.isValidElement(render)) { + } else if (isValidElement(render)) { return {render}; } else { - return ((...renderTimeArgs) => { - // console.log(`forRenderer.render[${type}]`, { render, renderTimeArgs }); - - return {render(...renderTimeArgs)}; - }) + return (...renderTimeArgs) => ( + {render(...renderTimeArgs)} + ); } - - return ( - !!render && - // The renderTimeArgs is for "styling" or render-time arguments. - // These arguments must not cause the renderer hiding the element (a.k.a. not rendering). - // For example: - // - Should we show/hide the timestamp while rendering this activity? - ((...renderTimeArgs) => { - // console.log(`forRenderer.render[${type}]`, { render, renderTimeArgs }); - - return {render(...renderTimeArgs)}; - }) - ); } catch (err) { // The next line is not a React component. It is a render function. // eslint-disable-next-line react/display-name diff --git a/packages/api/src/hooks/middleware/createDefaultCardActionMiddleware.js b/packages/api/src/hooks/middleware/createDefaultCardActionMiddleware.js new file mode 100644 index 0000000000..a8fda34ece --- /dev/null +++ b/packages/api/src/hooks/middleware/createDefaultCardActionMiddleware.js @@ -0,0 +1,36 @@ +import { sendMessage, sendMessageBack, sendPostBack } from 'botframework-webchat-core'; + +export default function createDefaultCardActionMiddleware() { + return ({ dispatch }) => next => (...args) => { + const [ + { + cardAction: { displayText, text, type, value } + } + ] = args; + + switch (type) { + case 'imBack': + if (typeof value === 'string') { + // TODO: [P4] Instead of calling dispatch, we should move to dispatchers instead for completeness + dispatch(sendMessage(value, 'imBack')); + } else { + throw new Error('cannot send "imBack" with a non-string value'); + } + + break; + + case 'messageBack': + dispatch(sendMessageBack(value, text, displayText)); + + break; + + case 'postBack': + dispatch(sendPostBack(value)); + + break; + + default: + return next(...args); + } + }; +} diff --git a/packages/api/src/hooks/useFocus.js b/packages/api/src/hooks/useFocus.js deleted file mode 100644 index 5ad6092940..0000000000 --- a/packages/api/src/hooks/useFocus.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatAPIContext from './internal/useWebChatAPIContext'; - -export default function useFocus() { - return useWebChatAPIContext().focus; -} diff --git a/packages/api/src/hooks/useSendFiles.js b/packages/api/src/hooks/useSendFiles.js index bee7806bc9..c934322026 100644 --- a/packages/api/src/hooks/useSendFiles.js +++ b/packages/api/src/hooks/useSendFiles.js @@ -2,73 +2,17 @@ import { useCallback } from 'react'; -import downscaleImageToDataURL from '../utils/downscaleImageToDataURL'; -import useStyleOptions from '../hooks/useStyleOptions'; -import useTrackEvent from '../hooks/useTrackEvent'; -import useTrackTiming from '../hooks/useTrackTiming'; +import useTrackEvent from './useTrackEvent'; import useWebChatAPIContext from './internal/useWebChatAPIContext'; -function canMakeThumbnail({ name }) { - return /\.(gif|jpe?g|png)$/iu.test(name); -} - -async function makeThumbnail(file, width, height, contentType, quality) { - try { - return await downscaleImageToDataURL(file, width, height, contentType, quality); - } catch (error) { - console.warn(`Web Chat: Failed to downscale image due to ${error}.`); - } -} - export default function useSendFiles() { const { sendFiles } = useWebChatAPIContext(); - const [ - { - enableUploadThumbnail, - uploadThumbnailContentType, - uploadThumbnailHeight, - uploadThumbnailQuality, - uploadThumbnailWidth - } - ] = useStyleOptions(); const trackEvent = useTrackEvent(); - const trackTiming = useTrackTiming(); return useCallback( async files => { if (files && files.length) { - files = [].slice.call(files); - - // TODO: [P3] We need to find revokeObjectURL on the UI side - // Redux store should not know about the browser environment - // One fix is to use ArrayBuffer instead of object URL, but that would requires change to DirectLineJS - const attachments = await Promise.all( - [].map.call(files, async file => { - let thumbnail; - - if (enableUploadThumbnail && canMakeThumbnail(file)) { - thumbnail = await trackTiming( - 'sendFiles:makeThumbnail', - makeThumbnail( - file, - uploadThumbnailWidth, - uploadThumbnailHeight, - uploadThumbnailContentType, - uploadThumbnailQuality - ) - ); - } - - return { - name: file.name, - size: file.size, - url: window.URL.createObjectURL(file), - ...(thumbnail && { thumbnail }) - }; - }) - ); - - sendFiles(attachments); + sendFiles(files); trackEvent('sendFiles', { numFiles: files.length, @@ -76,15 +20,6 @@ export default function useSendFiles() { }); } }, - [ - enableUploadThumbnail, - sendFiles, - trackEvent, - trackTiming, - uploadThumbnailContentType, - uploadThumbnailHeight, - uploadThumbnailQuality, - uploadThumbnailWidth - ] + [sendFiles, trackEvent] ); } diff --git a/packages/api/src/hooks/utils/ErrorBoundary.js b/packages/api/src/hooks/utils/ErrorBoundary.js index a285dea34c..e801d62578 100644 --- a/packages/api/src/hooks/utils/ErrorBoundary.js +++ b/packages/api/src/hooks/utils/ErrorBoundary.js @@ -1,7 +1,7 @@ +import { Component } from 'react'; import PropTypes from 'prop-types'; -import React from 'react'; -class ErrorBoundary extends React.Component { +class ErrorBoundary extends Component { constructor() { super(); diff --git a/packages/api/src/utils/observableToPromise.js b/packages/api/src/hooks/utils/observableToPromise.js similarity index 100% rename from packages/api/src/utils/observableToPromise.js rename to packages/api/src/hooks/utils/observableToPromise.js diff --git a/packages/component/src/Activity/ScrollToEndButton.js b/packages/component/src/Activity/ScrollToEndButton.js index 171453b841..f2a89479b9 100644 --- a/packages/component/src/Activity/ScrollToEndButton.js +++ b/packages/component/src/Activity/ScrollToEndButton.js @@ -4,9 +4,10 @@ import PropTypes from 'prop-types'; import React, { forwardRef, useCallback } from 'react'; import { safari } from '../Utils/detectBrowser'; +import useScrollToEnd from '../hooks/useScrollToEnd'; import useStyleSet from '../hooks/useStyleSet'; -const { useDirection, useLocalizer, useScrollToEnd } = hooks; +const { useDirection, useLocalizer } = hooks; const ScrollToEndButton = forwardRef( ( diff --git a/packages/component/src/Activity/StackedLayout.js b/packages/component/src/Activity/StackedLayout.js index 2ff30119c4..e8e9f757cd 100644 --- a/packages/component/src/Activity/StackedLayout.js +++ b/packages/component/src/Activity/StackedLayout.js @@ -136,8 +136,6 @@ const StackedLayout = ({ const showAvatar = showCallout && hasAvatar && !!renderAvatar; const showNub = showCallout && hasNub && (topAlignedCallout || !attachments.length); - console.log('stackedlayout', { hideTimestamp, renderActivityStatus }); - return (
{ const [{ textContent: textContentStyleSet }] = useStyleSet(); const renderMarkdownAsHTML = useRenderMarkdownAsHTML(); diff --git a/packages/component/src/BasicTranscript.js b/packages/component/src/BasicTranscript.js index 5d5261fec1..4cf0ccb40f 100644 --- a/packages/component/src/BasicTranscript.js +++ b/packages/component/src/BasicTranscript.js @@ -16,6 +16,7 @@ import removeInline from './Utils/removeInline'; import ScreenReaderActivity from './ScreenReaderActivity'; import ScrollToEndButton from './Activity/ScrollToEndButton'; import SpeakActivity from './Activity/Speak'; +import useFocus from './hooks/useFocus'; import useMemoize from './hooks/internal/useMemoize'; import useStyleSet from './hooks/useStyleSet'; import useStyleToEmotionObject from './hooks/internal/useStyleToEmotionObject'; @@ -28,7 +29,6 @@ const { useCreateActivityStatusRenderer, useCreateAvatarRenderer, useDirection, - useFocus, useGroupActivities, useLocalizer, useStyleOptions diff --git a/packages/component/src/BasicWebChat.js b/packages/component/src/BasicWebChat.js index ecfc3460b9..5d834c721c 100644 --- a/packages/component/src/BasicWebChat.js +++ b/packages/component/src/BasicWebChat.js @@ -6,18 +6,16 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; -// TODO: No /lib/ -import useSendBoxFocusRef from 'botframework-webchat-api/lib/hooks/internal/useSendBoxFocusRef'; -import useTranscriptFocusRef from 'botframework-webchat-api/lib/hooks/internal/useTranscriptFocusRef'; - import AccessKeySinkSurface from './Utils/AccessKeySink/Surface'; import BasicConnectivityStatus from './BasicConnectivityStatus'; import BasicSendBox from './BasicSendBox'; import BasicToaster from './BasicToaster'; import BasicTranscript from './BasicTranscript'; import TypeFocusSinkBox from './Utils/TypeFocusSink'; +import useSendBoxFocusRef from './hooks/internal/useSendBoxFocusRef'; import useStyleSet from './hooks/useStyleSet'; import useStyleToEmotionObject from './hooks/internal/useStyleToEmotionObject'; +import useTranscriptFocusRef from './hooks/internal/useTranscriptFocusRef'; const { useDisabled, useStyleOptions } = hooks; diff --git a/packages/component/src/Composer.js b/packages/component/src/Composer.js index dde8ed1f82..aa32f8a653 100644 --- a/packages/component/src/Composer.js +++ b/packages/component/src/Composer.js @@ -11,16 +11,46 @@ import createCSSKey from './Utils/createCSSKey'; import createDefaultActivityMiddleware from './Middleware/Activity/createCoreMiddleware'; import createDefaultActivityStatusMiddleware from './Middleware/ActivityStatus/createCoreMiddleware'; import createDefaultAttachmentMiddleware from './Middleware/Attachment/createCoreMiddleware'; +import createDefaultAvatarMiddleware from './Middleware/Avatar/createCoreMiddleware'; +import createDefaultCardActionMiddleware from './Middleware/CardAction/createCoreMiddleware'; +import createDefaultToastMiddleware from './Middleware/Toast/createCoreMiddleware'; +import createDefaultTypingIndicatorMiddleware from './Middleware/TypingIndicator/createCoreMiddleware'; +import downscaleImageToDataURL from './Utils/downscaleImageToDataURL'; import ErrorBox from './ErrorBox'; import mapMap from './Utils/mapMap'; import singleToArray from './Utils/singleToArray'; -import upgradeLegacyRendererMiddleware from './Utils/upgradeLegacyRendererMiddleware'; import WebChatUIContext from './hooks/internal/WebChatUIContext'; const { useStyleOptions } = hooks; const emotionPool = {}; +function createFocusContext({ sendBoxFocusRef, transcriptFocusRef }) { + return { + focus: where => { + const ref = where === 'sendBox' || where === 'sendBoxWithoutKeyboard' ? sendBoxFocusRef : transcriptFocusRef; + const { current } = ref || {}; + + if (current) { + if (where === 'sendBoxWithoutKeyboard') { + // To not activate the virtual keyboard while changing focus to an input, we will temporarily set it as read-only and flip it back. + // https://stackoverflow.com/questions/7610758/prevent-iphone-default-keyboard-when-focusing-an-input/7610923 + const readOnly = current.getAttribute('readonly'); + + current.setAttribute('readonly', 'readonly'); + + setTimeout(() => { + current.focus(); + readOnly ? current.setAttribute('readonly', readOnly) : current.removeAttribute('readonly'); + }, 0); + } else { + current.focus(); + } + } + } + }; +} + function styleSetToEmotionObjects(styleToEmotionObject, styleSet) { return mapMap(styleSet, (style, key) => (key === 'options' ? style : styleToEmotionObject(style))); } @@ -28,6 +58,13 @@ function styleSetToEmotionObjects(styleToEmotionObject, styleSet) { const ComposerCore = ({ children, extraStyleSet, nonce, renderMarkdown, styleSet, suggestedActionsAccessKey }) => { const [styleOptions] = useStyleOptions(); const internalMarkdownIt = useMemo(() => new MarkdownIt(), []); + const sendBoxFocusRef = useRef(); + const transcriptFocusRef = useRef(); + + const focusContext = useMemo(() => createFocusContext({ sendBoxFocusRef, transcriptFocusRef }), [ + sendBoxFocusRef, + transcriptFocusRef + ]); const internalRenderMarkdownInline = useMemo( () => markdown => { @@ -65,32 +102,36 @@ const ComposerCore = ({ children, extraStyleSet, nonce, renderMarkdown, styleSet const context = useMemo( () => ({ + ...focusContext, internalMarkdownItState: [internalMarkdownIt], internalRenderMarkdownInline, nonce, + renderMarkdown, + sendBoxFocusRef, styleSet: patchedStyleSet, styleToEmotionObject, suggestedActionsAccessKey, transcriptActivityElementsRef, + transcriptFocusRef, transcriptRootElementRef }), [ + focusContext, internalMarkdownIt, internalRenderMarkdownInline, nonce, patchedStyleSet, + renderMarkdown, + sendBoxFocusRef, styleToEmotionObject, suggestedActionsAccessKey, transcriptActivityElementsRef, + transcriptFocusRef, transcriptRootElementRef ] ); - return ( - - {children} - - ); + return {children}; }; ComposerCore.defaultProps = { @@ -113,38 +154,79 @@ const Composer = ({ activityMiddleware, activityStatusMiddleware, attachmentMiddleware, + avatarMiddleware, + cardActionMiddleware, children, - errorBoundaryMiddleware, - ...props + extraStyleSet, + renderMarkdown, + styleSet, + suggestedActionsAccessKey, + toastMiddleware, + typingIndicatorMiddleware, + ...composerProps }) => { + const { nonce, onTelemetry } = composerProps; + const patchedActivityMiddleware = useMemo( - () => [...singleToArray(activityMiddleware), ...createDefaultActivityMiddleware()].filter(middleware => middleware), + () => [...singleToArray(activityMiddleware), ...createDefaultActivityMiddleware()], [activityMiddleware] ); const patchedActivityStatusMiddleware = useMemo( - () => - [...singleToArray(activityStatusMiddleware), ...createDefaultActivityStatusMiddleware()].filter( - middleware => middleware - ), + () => [...singleToArray(activityStatusMiddleware), ...createDefaultActivityStatusMiddleware()], [activityStatusMiddleware] ); const patchedAttachmentMiddleware = useMemo( - () => - [...singleToArray(attachmentMiddleware), ...createDefaultAttachmentMiddleware()].filter(middleware => middleware), + () => [...singleToArray(attachmentMiddleware), ...createDefaultAttachmentMiddleware()], [attachmentMiddleware] ); + const patchedAvatarMiddleware = useMemo( + () => [...singleToArray(avatarMiddleware), ...createDefaultAvatarMiddleware()], + [avatarMiddleware] + ); + + const patchedCardActionMiddleware = useMemo( + () => [...singleToArray(cardActionMiddleware), ...createDefaultCardActionMiddleware()], + [cardActionMiddleware] + ); + + const patchedToastMiddleware = useMemo(() => [...singleToArray(toastMiddleware), ...createDefaultToastMiddleware()], [ + toastMiddleware + ]); + + const patchedTypingIndicatorMiddleware = useMemo( + () => [...singleToArray(typingIndicatorMiddleware), ...createDefaultTypingIndicatorMiddleware()], + [typingIndicatorMiddleware] + ); + return ( - {children} + + + {children} + + + {onTelemetry && } ); }; @@ -153,16 +235,42 @@ Composer.defaultProps = { ...APIComposer.defaultProps, ...ComposerCore.defaultProps, activityMiddleware: undefined, + activityRenderer: undefined, activityStatusMiddleware: undefined, - attachmentMiddleware: undefined + activityStatusRenderer: undefined, + attachmentMiddleware: undefined, + attachmentRenderer: undefined, + avatarMiddleware: undefined, + avatarRenderer: undefined, + cardActionMiddleware: undefined, + children: undefined, + nonce: undefined, + renderMarkdown: undefined, + toastMiddleware: undefined, + toastRenderer: undefined, + typingIndicatorMiddleware: undefined, + typingIndicatorRenderer: undefined }; Composer.propTypes = { ...APIComposer.propTypes, ...ComposerCore.propTypes, activityMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), + activityRenderer: PropTypes.func, activityStatusMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), - attachmentMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]) + activityStatusRenderer: PropTypes.func, + attachmentMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), + attachmentRenderer: PropTypes.func, + avatarMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), + avatarRenderer: PropTypes.func, + cardActionMiddleware: PropTypes.func, + children: PropTypes.any, + nonce: PropTypes.string, + renderMarkdown: PropTypes.func, + toastMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), + toastRenderer: PropTypes.func, + typingIndicatorMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), + typingIndicatorRenderer: PropTypes.func }; export default Composer; diff --git a/packages/component/src/ConnectivityStatus/Connecting.js b/packages/component/src/ConnectivityStatus/Connecting.js index 53b6b33c2c..417016f9c1 100644 --- a/packages/component/src/ConnectivityStatus/Connecting.js +++ b/packages/component/src/ConnectivityStatus/Connecting.js @@ -3,13 +3,11 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; import React, { useState } from 'react'; -// TODO: No /lib/ -import useForceRender from 'botframework-webchat-api/lib/hooks/internal/useForceRender'; -import useTimer from 'botframework-webchat-api/lib/hooks/internal/useTimer'; - import ScreenReaderText from '../ScreenReaderText'; import SpinnerAnimation from './Assets/SpinnerAnimation'; +import useForceRender from '../hooks/internal/useForceRender'; import useStyleSet from '../hooks/useStyleSet'; +import useTimer from '../hooks/internal/useTimer'; import WarningNotificationIcon from './Assets/WarningNotificationIcon'; const { useDirection, useLocalizer, useStyleOptions } = hooks; diff --git a/packages/component/src/Middleware/ActivityStatus/RelativeTime.js b/packages/component/src/Middleware/ActivityStatus/RelativeTime.js index 01ef2b96aa..47282129ca 100644 --- a/packages/component/src/Middleware/ActivityStatus/RelativeTime.js +++ b/packages/component/src/Middleware/ActivityStatus/RelativeTime.js @@ -1,9 +1,9 @@ import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; import React from 'react'; -import useForceRenderAtInterval from 'botframework-webchat-api/lib/hooks/internal/useForceRenderAtInterval'; import ScreenReaderText from '../../ScreenReaderText'; +import useForceRenderAtInterval from '../../hooks/internal/useForceRenderAtInterval'; const { useDateFormatter, useLocalizer, useRelativeTimeFormatter } = hooks; diff --git a/packages/component/src/Middleware/ActivityStatus/SendStatus/SendStatus.js b/packages/component/src/Middleware/ActivityStatus/SendStatus/SendStatus.js index fa06e5dccf..8400f95310 100644 --- a/packages/component/src/Middleware/ActivityStatus/SendStatus/SendStatus.js +++ b/packages/component/src/Middleware/ActivityStatus/SendStatus/SendStatus.js @@ -6,9 +6,10 @@ import React, { useCallback } from 'react'; import connectToWebChat from '../../../connectToWebChat'; import ScreenReaderText from '../../../ScreenReaderText'; import SendFailedRetry from './SendFailedRetry'; +import useFocus from '../../../hooks/useFocus'; import useStyleSet from '../../../hooks/useStyleSet'; -const { useFocus, useLocalizer, usePostActivity } = hooks; +const { useLocalizer, usePostActivity } = hooks; const { ActivityClientState: { SEND_FAILED, SENDING } diff --git a/packages/component/src/Middleware/ActivityStatus/createTimestampMiddleware.js b/packages/component/src/Middleware/ActivityStatus/createTimestampMiddleware.js index e5fb7f54b9..3007821409 100644 --- a/packages/component/src/Middleware/ActivityStatus/createTimestampMiddleware.js +++ b/packages/component/src/Middleware/ActivityStatus/createTimestampMiddleware.js @@ -7,8 +7,6 @@ export default function createTimestampMiddleware() { return () => () => (...args) => { const [{ activity, hideTimestamp }] = args; - console.log('createTimestampMiddleware', { args }); - if (hideTimestamp) { // If "hideTimestamp" is set, we will not render the visual timestamp. But continue to render the screen reader only version. return ; diff --git a/packages/component/src/Middleware/Avatar/createCoreMiddleware.js b/packages/component/src/Middleware/Avatar/createCoreMiddleware.js index a9d46ace1f..7b45f25f32 100644 --- a/packages/component/src/Middleware/Avatar/createCoreMiddleware.js +++ b/packages/component/src/Middleware/Avatar/createCoreMiddleware.js @@ -2,7 +2,6 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; -import concatMiddleware from '../concatMiddleware'; import ImageAvatar from '../../Avatar/ImageAvatar'; import InitialsAvatar from '../../Avatar/InitialsAvatar'; import useStyleSet from '../../hooks/useStyleSet'; @@ -52,16 +51,18 @@ DefaultAvatar.propTypes = { }; export default function createCoreAvatarMiddleware() { - return concatMiddleware(() => () => ({ fromUser, styleOptions }) => { - const { botAvatarImage, botAvatarInitials, userAvatarImage, userAvatarInitials } = styleOptions; + return [ + () => () => ({ fromUser, styleOptions }) => { + const { botAvatarImage, botAvatarInitials, userAvatarImage, userAvatarInitials } = styleOptions; - if (fromUser ? userAvatarImage || userAvatarInitials : botAvatarImage || botAvatarInitials) { - // eslint-disable-next-line react/display-name - return () => ; - } + if (fromUser ? userAvatarImage || userAvatarInitials : botAvatarImage || botAvatarInitials) { + // eslint-disable-next-line react/display-name + return () => ; + } - return false; - }); + return false; + } + ]; } export { DefaultAvatar }; diff --git a/packages/component/src/Middleware/CardAction/createCoreMiddleware.js b/packages/component/src/Middleware/CardAction/createCoreMiddleware.js index d0d0bde5dd..20f588afb7 100644 --- a/packages/component/src/Middleware/CardAction/createCoreMiddleware.js +++ b/packages/component/src/Middleware/CardAction/createCoreMiddleware.js @@ -1,5 +1,3 @@ -import { sendMessage, sendMessageBack, sendPostBack } from 'botframework-webchat-core'; - // This code is adopted from sanitize-html/naughtyScheme. // sanitize-html is a dependency of Web Chat but the naughtScheme function is neither exposed nor reusable. // https://github.com/apostrophecms/sanitize-html/blob/master/src/index.js#L526 @@ -30,59 +28,47 @@ function getScheme(href) { const ALLOWED_SCHEMES = ['data', 'http', 'https', 'ftp', 'mailto', 'sip', 'tel']; export default function createDefaultCardActionMiddleware() { - return ({ dispatch }) => next => ({ cardAction, getSignInUrl }) => { - const { displayText, text, type, value } = cardAction; - - switch (type) { - case 'imBack': - if (typeof value === 'string') { - // TODO: [P4] Instead of calling dispatch, we should move to dispatchers instead for completeness - dispatch(sendMessage(value, 'imBack')); - } else { - throw new Error('cannot send "imBack" with a non-string value'); + return [ + () => next => (...args) => { + const [ + { + cardAction: { type, value }, + getSignInUrl } - - break; - - case 'messageBack': - dispatch(sendMessageBack(value, text, displayText)); - - break; - - case 'postBack': - dispatch(sendPostBack(value)); - - break; - - case 'call': - case 'downloadFile': - case 'openUrl': - case 'playAudio': - case 'playVideo': - case 'showImage': - if (ALLOWED_SCHEMES.includes(getScheme(value))) { - window.open(value, '_blank', 'noopener noreferrer'); - } else { - console.warn('botframework-webchat: Cannot open URL with disallowed schemes.', value); + ] = args; + + switch (type) { + case 'call': + case 'downloadFile': + case 'openUrl': + case 'playAudio': + case 'playVideo': + case 'showImage': + if (ALLOWED_SCHEMES.includes(getScheme(value))) { + window.open(value, '_blank', 'noopener noreferrer'); + } else { + console.warn('botframework-webchat: Cannot open URL with disallowed schemes.', value); + } + + break; + + case 'signin': { + // TODO: [P3] We should prime the URL into the OAuthCard directly, instead of calling getSessionId on-demand + // This is to eliminate the delay between window.open() and location.href call + + (async function () { + const popup = window.open(); + const url = await getSignInUrl(); + + popup.location.href = url; + })(); + + break; } - break; - - case 'signin': { - // TODO: [P3] We should prime the URL into the OAuthCard directly, instead of calling getSessionId on-demand - // This is to eliminate the delay between window.open() and location.href call - - const popup = window.open(); - - getSignInUrl().then(url => { - popup.location.href = url; - }); - - break; + default: + return next(...args); } - - default: - return next({ cardAction, getSignInUrl }); } - }; + ]; } diff --git a/packages/component/src/Middleware/Toast/createCoreMiddleware.js b/packages/component/src/Middleware/Toast/createCoreMiddleware.js index df8c194f00..0c85f6b0e0 100644 --- a/packages/component/src/Middleware/Toast/createCoreMiddleware.js +++ b/packages/component/src/Middleware/Toast/createCoreMiddleware.js @@ -1,8 +1,7 @@ -import concatMiddleware from '../concatMiddleware'; import createToastMiddleware from '../../Toast/createToastMiddleware'; function createCoreMiddleware() { - return concatMiddleware( + return [ () => next => (...args) => { const [ { @@ -15,7 +14,7 @@ function createCoreMiddleware() { return id !== 'connectivitystatus' && next(...args); }, createToastMiddleware() - ); + ]; } export default createCoreMiddleware; diff --git a/packages/component/src/Middleware/TypingIndicator/createCoreMiddleware.js b/packages/component/src/Middleware/TypingIndicator/createCoreMiddleware.js index 6a7db62240..e4f5f55a7b 100644 --- a/packages/component/src/Middleware/TypingIndicator/createCoreMiddleware.js +++ b/packages/component/src/Middleware/TypingIndicator/createCoreMiddleware.js @@ -23,5 +23,5 @@ const DotIndicator = () => { // TODO: [P4] Rename this file or the whole middleware, it looks either too simple or too comprehensive now export default function createCoreMiddleware() { - return () => () => ({ visible }) => visible && ; + return [() => () => ({ visible }) => visible && ]; } diff --git a/packages/component/src/SendBox/SendButton.js b/packages/component/src/SendBox/SendButton.js index cee7992f61..7d1afefb92 100644 --- a/packages/component/src/SendBox/SendButton.js +++ b/packages/component/src/SendBox/SendButton.js @@ -4,8 +4,10 @@ import React, { useCallback } from 'react'; import connectToWebChat from '../connectToWebChat'; import IconButton from './IconButton'; import SendIcon from './Assets/SendIcon'; +import useFocus from '../hooks/useFocus'; +import useScrollToEnd from '../hooks/useScrollToEnd'; -const { useDisabled, useFocus, useLocalizer, useScrollToEnd, useSubmitSendBox } = hooks; +const { useDisabled, useLocalizer, useSubmitSendBox } = hooks; const connectSendButton = (...selectors) => connectToWebChat( diff --git a/packages/component/src/SendBox/SuggestedAction.js b/packages/component/src/SendBox/SuggestedAction.js index 0f06246828..ea8c116cdc 100644 --- a/packages/component/src/SendBox/SuggestedAction.js +++ b/packages/component/src/SendBox/SuggestedAction.js @@ -5,13 +5,15 @@ import React, { useCallback, useRef } from 'react'; import AccessibleButton from '../Utils/AccessibleButton'; import connectToWebChat from '../connectToWebChat'; +import useFocus from '../hooks/useFocus'; import useFocusAccessKeyEffect from '../Utils/AccessKeySink/useFocusAccessKeyEffect'; import useLocalizeAccessKey from '../hooks/internal/useLocalizeAccessKey'; +import useScrollToEnd from '../hooks/useScrollToEnd'; import useSuggestedActionsAccessKey from '../hooks/internal/useSuggestedActionsAccessKey'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; -const { useDirection, useDisabled, useFocus, usePerformCardAction, useScrollToEnd, useSuggestedActions } = hooks; +const { useDirection, useDisabled, usePerformCardAction, useSuggestedActions } = hooks; const ROOT_STYLE = { '&.webchat__suggested-action': { diff --git a/packages/component/src/SendBox/TextBox.js b/packages/component/src/SendBox/TextBox.js index d65e6d3fed..5a1f997915 100644 --- a/packages/component/src/SendBox/TextBox.js +++ b/packages/component/src/SendBox/TextBox.js @@ -3,26 +3,17 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; import React, { forwardRef, useCallback, useEffect, useRef } from 'react'; -// TODO: No /lib/ -import useReplaceEmoticon from 'botframework-webchat-api/lib/hooks/internal/useReplaceEmoticon'; - import { Context as TypeFocusSinkContext } from '../Utils/TypeFocusSink'; import AccessibleInputText from '../Utils/AccessibleInputText'; import AccessibleTextArea from '../Utils/AccessibleTextArea'; import connectToWebChat from '../connectToWebChat'; +import useFocus from '../hooks/useFocus'; +import useReplaceEmoticon from '../hooks/internal/useReplaceEmoticon'; import useScrollToEnd from '../hooks/useScrollToEnd'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; -const { - useDisabled, - useFocus, - useLocalizer, - useSendBoxValue, - useStopDictate, - useStyleOptions, - useSubmitSendBox -} = hooks; +const { useDisabled, useLocalizer, useSendBoxValue, useStopDictate, useStyleOptions, useSubmitSendBox } = hooks; const ROOT_STYLE = { '&.webchat__send-box-text-box': { diff --git a/packages/component/src/SendBox/UploadButton.js b/packages/component/src/SendBox/UploadButton.js index 3e099500fc..995954a4d4 100644 --- a/packages/component/src/SendBox/UploadButton.js +++ b/packages/component/src/SendBox/UploadButton.js @@ -2,16 +2,15 @@ import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import React, { useCallback, useRef } from 'react'; -// TODO: No /lib/ -import downscaleImageToDataURL from 'botframework-webchat-api/lib/utils/downscaleImageToDataURL'; - import AttachmentIcon from './Assets/AttachmentIcon'; import connectToWebChat from '../connectToWebChat'; +import downscaleImageToDataURL from '../Utils/downscaleImageToDataURL/index'; import IconButton from './IconButton'; +import useSendFiles from '../hooks/useSendFiles'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; -const { useDisabled, useLocalizer, useSendFiles } = hooks; +const { useDisabled, useLocalizer } = hooks; const ROOT_STYLE = { overflow: 'hidden', diff --git a/packages/component/src/Utils/InlineMarkdown.js b/packages/component/src/Utils/InlineMarkdown.js index 93b2303d80..3bf918548f 100644 --- a/packages/component/src/Utils/InlineMarkdown.js +++ b/packages/component/src/Utils/InlineMarkdown.js @@ -1,11 +1,11 @@ /* eslint react/no-danger: "off" */ import { hooks } from 'botframework-webchat-api'; -import createCustomEvent from 'botframework-webchat-api/lib/utils/createCustomEvent'; import PropTypes from 'prop-types'; import React, { useCallback, useMemo } from 'react'; import updateIn from 'simple-update-in'; +import createCustomEvent from './createCustomEvent'; import randomId from './randomId'; import useInternalMarkdownIt from '../hooks/internal/useInternalMarkdownIt'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; @@ -89,11 +89,7 @@ const InlineMarkdown = ({ children, onReference, references }) => { const html = useMemo(() => { const tree = markdownIt.parseInline(children, { - references: references.reduce( - // (references, key) => ({ ...references, [key]: { href: `#${key}` } }), - (references, key) => ({ ...references, [key]: { href: `#${refToHref[key]}` } }), - {} - ) + references: references.reduce((references, key) => ({ ...references, [key]: { href: `#${refToHref[key]}` } }), {}) }); // Turn "Retry" into "" diff --git a/packages/component/src/Utils/TypeFocusSink/Context.js b/packages/component/src/Utils/TypeFocusSink/Context.js index cff54ee61e..575c41368d 100644 --- a/packages/component/src/Utils/TypeFocusSink/Context.js +++ b/packages/component/src/Utils/TypeFocusSink/Context.js @@ -1,6 +1,6 @@ -import React from 'react'; +import { createContext } from 'react'; -const context = React.createContext({ +const context = createContext({ focusableRef: undefined }); diff --git a/packages/component/src/Utils/createCustomEvent.js b/packages/component/src/Utils/createCustomEvent.js new file mode 100644 index 0000000000..d2fc3453c5 --- /dev/null +++ b/packages/component/src/Utils/createCustomEvent.js @@ -0,0 +1,17 @@ +export default function createCustomEvent(name, eventInitDict) { + let event; + + if (typeof CustomEvent === 'function') { + event = new CustomEvent(name); + } else { + event = document.createEvent('Event'); + + event.initEvent(name, true, true); + } + + Object.entries(eventInitDict).forEach(([key, value]) => { + event[key] = value; + }); + + return event; +} diff --git a/packages/api/src/utils/blobToArrayBuffer.js b/packages/component/src/Utils/downscaleImageToDataURL/blobToArrayBuffer.js similarity index 100% rename from packages/api/src/utils/blobToArrayBuffer.js rename to packages/component/src/Utils/downscaleImageToDataURL/blobToArrayBuffer.js diff --git a/packages/api/src/utils/downscaleImageToDataURLUsingBrowser.js b/packages/component/src/Utils/downscaleImageToDataURL/downscaleImageToDataURLUsingBrowser.js similarity index 100% rename from packages/api/src/utils/downscaleImageToDataURLUsingBrowser.js rename to packages/component/src/Utils/downscaleImageToDataURL/downscaleImageToDataURLUsingBrowser.js diff --git a/packages/api/src/utils/downscaleImageToDataURLUsingWorker.js b/packages/component/src/Utils/downscaleImageToDataURL/downscaleImageToDataURLUsingWorker.js similarity index 74% rename from packages/api/src/utils/downscaleImageToDataURLUsingWorker.js rename to packages/component/src/Utils/downscaleImageToDataURL/downscaleImageToDataURLUsingWorker.js index 8a73616f72..e92b7cc0fc 100644 --- a/packages/api/src/utils/downscaleImageToDataURLUsingWorker.js +++ b/packages/component/src/Utils/downscaleImageToDataURL/downscaleImageToDataURLUsingWorker.js @@ -1,5 +1,4 @@ import blobToArrayBuffer from './blobToArrayBuffer'; -import memoizeOne from 'memoize-one'; import workerFunction from './downscaleImageToDataURLUsingWorker.worker'; function createWorker(fn) { @@ -60,33 +59,47 @@ const checkSupportOffscreenCanvas = () => { return typeof window.createImageBitmap !== 'undefined' && hasOffscreenCanvas && isOffscreenCanvasSupportGetContext2D; }; -const checkSupportWebWorker = memoizeOne(async () => { - if (typeof window.MessageChannel === 'undefined' || typeof window.Worker === 'undefined') { - return false; - } +let checkSupportWebWorkerPromise; - let worker; +function checkSupportWebWorker() { + return ( + checkSupportWebWorkerPromise || + (checkSupportWebWorkerPromise = (async () => { + if (typeof window.MessageChannel === 'undefined' || typeof window.Worker === 'undefined') { + return false; + } - try { - worker = await createWorker('function(){postMessage("ready")}'); - } catch (err) { - return false; - } + let worker; + + try { + worker = await createWorker('function(){postMessage("ready")}'); + } catch (err) { + return false; + } - worker.terminate(); + worker.terminate(); - return true; -}); + return true; + })()) + ); +} -const checkSupport = memoizeOne(async () => { - try { - const results = await Promise.all([checkSupportOffscreenCanvas(), checkSupportWebWorker()]); +let checkSupportPromise; - return results.every(result => result); - } catch (err) { - return false; - } -}); +function checkSupport() { + return ( + checkSupportPromise || + (checkSupportPromise = (async () => { + try { + const results = await Promise.all([checkSupportOffscreenCanvas(), checkSupportWebWorker()]); + + return results.every(result => result); + } catch (err) { + return false; + } + })()) + ); +} export default function downscaleImageToDataURLUsingWorker(blob, maxWidth, maxHeight, type, quality) { return new Promise((resolve, reject) => { diff --git a/packages/api/src/utils/downscaleImageToDataURLUsingWorker.worker.js b/packages/component/src/Utils/downscaleImageToDataURL/downscaleImageToDataURLUsingWorker.worker.js similarity index 100% rename from packages/api/src/utils/downscaleImageToDataURLUsingWorker.worker.js rename to packages/component/src/Utils/downscaleImageToDataURL/downscaleImageToDataURLUsingWorker.worker.js diff --git a/packages/api/src/utils/downscaleImageToDataURL.js b/packages/component/src/Utils/downscaleImageToDataURL/index.js similarity index 100% rename from packages/api/src/utils/downscaleImageToDataURL.js rename to packages/component/src/Utils/downscaleImageToDataURL/index.js diff --git a/packages/component/src/Utils/upgradeLegacyRendererMiddleware.js b/packages/component/src/Utils/upgradeLegacyRendererMiddleware.js deleted file mode 100644 index cb2bae7467..0000000000 --- a/packages/component/src/Utils/upgradeLegacyRendererMiddleware.js +++ /dev/null @@ -1,20 +0,0 @@ -import { isValidElement } from 'react'; - -// For uniformity, we are patching legacy renderer middleware signature to newer one. -// - Legacy: () => next => args => next(args): React.Element -// - Current: () => next => args => next(args): false | () => React.Element -export default function upgradeLegacyRendererMiddleware(middleware) { - return (...setupArgs) => { - const setup = middleware(...setupArgs); - - return next => { - const runMiddleware = setup(next); - - return (...renderArgs) => { - const result = runMiddleware(...renderArgs); - - return !!result && (isValidElement(result) ? () => result : result); - }; - }; - }; -} diff --git a/packages/component/src/hooks/index.js b/packages/component/src/hooks/index.js new file mode 100644 index 0000000000..6ed5da539b --- /dev/null +++ b/packages/component/src/hooks/index.js @@ -0,0 +1,30 @@ +import useFocus from './useFocus'; +import useFocusSendBox from './useFocusSendBox'; +import useObserveScrollPosition from './useObserveScrollPosition'; +import useRenderMarkdownAsHTML from './useRenderMarkdownAsHTML'; +import useScrollTo from './useScrollTo'; +import useScrollToEnd from './useScrollToEnd'; +import useSendFiles from './useSendFiles'; +import useStyleSet from './useStyleSet'; + +import { useMicrophoneButtonClick, useMicrophoneButtonDisabled } from '../SendBox/MicrophoneButton'; +import { useSendBoxSpeechInterimsVisible } from '../BasicSendBox'; +import { useTextBoxSubmit, useTextBoxValue } from '../SendBox/TextBox'; +import { useTypingIndicatorVisible } from '../BasicTypingIndicator'; + +export { + useFocus, + useFocusSendBox, + useMicrophoneButtonClick, + useMicrophoneButtonDisabled, + useObserveScrollPosition, + useRenderMarkdownAsHTML, + useScrollTo, + useScrollToEnd, + useSendBoxSpeechInterimsVisible, + useSendFiles, + useStyleSet, + useTextBoxSubmit, + useTextBoxValue, + useTypingIndicatorVisible +}; diff --git a/packages/component/src/hooks/internal/UITracker.js b/packages/component/src/hooks/internal/UITracker.js new file mode 100644 index 0000000000..f7df22027f --- /dev/null +++ b/packages/component/src/hooks/internal/UITracker.js @@ -0,0 +1,19 @@ +import { hooks } from 'botframework-webchat-api'; +import { useEffect } from 'react'; + +import { checkSupport as supportWorker } from '../../Utils/downscaleImageToDataURLUsingWorker'; + +const { useTrackDimension } = hooks; + +const Tracker = () => { + const trackDimension = useTrackDimension(); + + useEffect(() => { + trackDimension('capability:downscaleImage:workerType', supportWorker() ? 'web worker' : 'main'); + trackDimension('capability:renderer', 'html'); + }, [trackDimension]); + + return false; +}; + +export default Tracker; diff --git a/packages/component/src/hooks/internal/useForceRender.js b/packages/component/src/hooks/internal/useForceRender.js new file mode 100644 index 0000000000..82a0f9ed74 --- /dev/null +++ b/packages/component/src/hooks/internal/useForceRender.js @@ -0,0 +1,9 @@ +import { useCallback, useState } from 'react'; + +function useForceRender() { + const [, setForceRender] = useState(); + + return useCallback(() => setForceRender({}), [setForceRender]); +} + +export default useForceRender; diff --git a/packages/api/src/hooks/internal/useForceRenderAtInterval.js b/packages/component/src/hooks/internal/useForceRenderAtInterval.js similarity index 100% rename from packages/api/src/hooks/internal/useForceRenderAtInterval.js rename to packages/component/src/hooks/internal/useForceRenderAtInterval.js diff --git a/packages/api/src/hooks/internal/useGetTranscriptActivityElementByID.js b/packages/component/src/hooks/internal/useGetTranscriptActivityElementByID.js similarity index 100% rename from packages/api/src/hooks/internal/useGetTranscriptActivityElementByID.js rename to packages/component/src/hooks/internal/useGetTranscriptActivityElementByID.js diff --git a/packages/api/src/hooks/internal/useReplaceEmoticon.js b/packages/component/src/hooks/internal/useReplaceEmoticon.js similarity index 96% rename from packages/api/src/hooks/internal/useReplaceEmoticon.js rename to packages/component/src/hooks/internal/useReplaceEmoticon.js index 3b653edcdb..6ca582a793 100644 --- a/packages/api/src/hooks/internal/useReplaceEmoticon.js +++ b/packages/component/src/hooks/internal/useReplaceEmoticon.js @@ -1,8 +1,9 @@ /*eslint require-unicode-regexp: "off" */ +import { hooks } from 'botframework-webchat-api'; import { useCallback } from 'react'; -import useStyleOptions from '../useStyleOptions'; +const { useStyleOptions } = hooks; export default function useReplaceEmoticon() { const [{ emojiSet }] = useStyleOptions(); diff --git a/packages/component/src/hooks/internal/useSendBoxFocusRef.js b/packages/component/src/hooks/internal/useSendBoxFocusRef.js new file mode 100644 index 0000000000..5c52290314 --- /dev/null +++ b/packages/component/src/hooks/internal/useSendBoxFocusRef.js @@ -0,0 +1,5 @@ +import useWebChatUIContext from './useWebChatUIContext'; + +export default function useSendBoxFocusRef() { + return [useWebChatUIContext().sendBoxFocusRef]; +} diff --git a/packages/component/src/hooks/internal/useStyleToEmotionObject.js b/packages/component/src/hooks/internal/useStyleToEmotionObject.js index ed9e4e1e52..257e34f982 100644 --- a/packages/component/src/hooks/internal/useStyleToEmotionObject.js +++ b/packages/component/src/hooks/internal/useStyleToEmotionObject.js @@ -1,4 +1,3 @@ -// TODO: No /lib/ import useWebChatUIContext from './useWebChatUIContext'; export default function useStyleToEmotionObject() { diff --git a/packages/component/src/hooks/internal/useTimer.js b/packages/component/src/hooks/internal/useTimer.js new file mode 100644 index 0000000000..95fc462c8e --- /dev/null +++ b/packages/component/src/hooks/internal/useTimer.js @@ -0,0 +1,11 @@ +import { useEffect } from 'react'; + +export default function useTimer(at, fn) { + useEffect(() => { + if (typeof at === 'number') { + const timeout = setTimeout(fn, Math.max(0, at - Date.now())); + + return () => clearTimeout(timeout); + } + }, [at, fn]); +} diff --git a/packages/component/src/hooks/internal/useTranscriptFocusRef.js b/packages/component/src/hooks/internal/useTranscriptFocusRef.js new file mode 100644 index 0000000000..81b846a8a2 --- /dev/null +++ b/packages/component/src/hooks/internal/useTranscriptFocusRef.js @@ -0,0 +1,5 @@ +import useWebChatUIContext from './useWebChatUIContext'; + +export default function useTranscriptFocusRef() { + return [useWebChatUIContext().transcriptFocusRef]; +} diff --git a/packages/component/src/hooks/useFocus.js b/packages/component/src/hooks/useFocus.js new file mode 100644 index 0000000000..dddf3c1607 --- /dev/null +++ b/packages/component/src/hooks/useFocus.js @@ -0,0 +1,5 @@ +import useWebChatUIContext from './internal/useWebChatUIContext'; + +export default function useFocus() { + return useWebChatUIContext().focus; +} diff --git a/packages/api/src/hooks/useFocusSendBox.js b/packages/component/src/hooks/useFocusSendBox.js similarity index 100% rename from packages/api/src/hooks/useFocusSendBox.js rename to packages/component/src/hooks/useFocusSendBox.js diff --git a/packages/api/src/hooks/useRenderMarkdownAsHTML.js b/packages/component/src/hooks/useRenderMarkdownAsHTML.js similarity index 57% rename from packages/api/src/hooks/useRenderMarkdownAsHTML.js rename to packages/component/src/hooks/useRenderMarkdownAsHTML.js index 690ded2c29..c82eb24ab8 100644 --- a/packages/api/src/hooks/useRenderMarkdownAsHTML.js +++ b/packages/component/src/hooks/useRenderMarkdownAsHTML.js @@ -1,10 +1,12 @@ +import { hooks } from 'botframework-webchat-api'; import { useMemo } from 'react'; -import useStyleOptions from '../hooks/useStyleOptions'; -import useWebChatAPIContext from './internal/useWebChatAPIContext'; +import useWebChatUIContext from './internal/useWebChatUIContext'; + +const { useStyleOptions } = hooks; export default function useRenderMarkdownAsHTML() { - const { renderMarkdown } = useWebChatAPIContext(); + const { renderMarkdown } = useWebChatUIContext(); const [styleOptions] = useStyleOptions(); return useMemo(() => renderMarkdown && (markdown => renderMarkdown(markdown, styleOptions)), [ diff --git a/packages/component/src/hooks/useSendFiles.js b/packages/component/src/hooks/useSendFiles.js new file mode 100644 index 0000000000..f369cde835 --- /dev/null +++ b/packages/component/src/hooks/useSendFiles.js @@ -0,0 +1,82 @@ +/* eslint no-magic-numbers: ["error", { "ignore": [0, 1024] }] */ + +import { hooks } from 'botframework-webchat-api'; +import { useCallback } from 'react'; + +import downscaleImageToDataURL from '../Utils/downscaleImageToDataURL/index'; + +const { useSendFiles: useAPISendFiles, useStyleOptions, useTrackTiming } = hooks; + +function canMakeThumbnail({ name }) { + return /\.(gif|jpe?g|png)$/iu.test(name); +} + +async function makeThumbnail(file, width, height, contentType, quality) { + try { + return await downscaleImageToDataURL(file, width, height, contentType, quality); + } catch (error) { + console.warn(`Web Chat: Failed to downscale image due to ${error}.`); + } +} + +export default function useSendFiles() { + const sendFiles = useAPISendFiles(); + const [ + { + enableUploadThumbnail, + uploadThumbnailContentType, + uploadThumbnailHeight, + uploadThumbnailQuality, + uploadThumbnailWidth + } + ] = useStyleOptions(); + const trackTiming = useTrackTiming(); + + return useCallback( + async files => { + if (files && files.length) { + files = [].slice.call(files); + + // TODO: [P3] We need to find revokeObjectURL on the UI side + // Redux store should not know about the browser environment + // One fix is to use ArrayBuffer instead of object URL, but that would requires change to DirectLineJS + const attachments = await Promise.all( + [].map.call(files, async file => { + let thumbnail; + + if (downscaleImageToDataURL && enableUploadThumbnail && canMakeThumbnail(file)) { + thumbnail = await trackTiming( + 'sendFiles:makeThumbnail', + makeThumbnail( + file, + uploadThumbnailWidth, + uploadThumbnailHeight, + uploadThumbnailContentType, + uploadThumbnailQuality + ) + ); + } + + return { + name: file.name, + size: file.size, + url: window.URL.createObjectURL(file), + ...(thumbnail && { thumbnail }) + }; + }) + ); + + sendFiles(attachments); + } + }, + [ + enableUploadThumbnail, + sendFiles, + trackTiming, + uploadThumbnailContentType, + uploadThumbnailHeight, + uploadThumbnailQuality, + uploadThumbnailWidth + ] + ); +} diff --git a/packages/component/src/index.tsx b/packages/component/src/index.tsx index 24590d29f1..be17cdfe7d 100644 --- a/packages/component/src/index.tsx +++ b/packages/component/src/index.tsx @@ -39,7 +39,13 @@ import defaultStyleOptions from './Styles/defaultStyleOptions'; import getTabIndex from './Utils/TypeFocusSink/getTabIndex'; // TODO: Add deprecation notes when someone is using hooks from bf-wc-component, instead of bf-wc-core. -import { hooks } from 'botframework-webchat-api'; +import { hooks as apiHooks } from 'botframework-webchat-api'; +import * as componentHooks from './hooks/index'; + +const hooks = { + ...apiHooks, + ...componentHooks +}; const version = process.env.npm_package_version; From e8d35d4e1b4e7338d5f8a130229c94204b9f9606 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 5 Oct 2020 16:03:38 -0700 Subject: [PATCH 03/21] Continue refactoring --- packages/api/src/hooks/Composer.js | 17 ++++++++---- .../useCreateActivityRendererInternal.js | 6 ++++- .../src/hooks/middleware/applyMiddleware.js | 2 +- .../Attachment/AdaptiveCardRenderer.js | 7 +---- .../Attachment/createCoreMiddleware.js | 2 -- .../Middleware/createAttachmentRenderer.js | 26 ------------------- 6 files changed, 19 insertions(+), 41 deletions(-) delete mode 100644 packages/component/src/Middleware/createAttachmentRenderer.js diff --git a/packages/api/src/hooks/Composer.js b/packages/api/src/hooks/Composer.js index 22104bc9b9..9645357852 100644 --- a/packages/api/src/hooks/Composer.js +++ b/packages/api/src/hooks/Composer.js @@ -41,9 +41,7 @@ import { submitSendBox } from 'botframework-webchat-core'; -// import concatMiddleware from './Middleware/concatMiddleware'; import createDefaultCardActionMiddleware from './middleware/createDefaultCardActionMiddleware'; -// import createDefaultGroupActivitiesMiddleware from './Middleware/GroupActivities/createCoreMiddleware'; import createDefaultGroupActivitiesMiddleware from './middleware/createDefaultGroupActivitiesMiddleware'; import defaultSelectVoice from './internal/defaultSelectVoice'; import Dictation from './internal/Dictation'; @@ -307,7 +305,16 @@ const Composer = ({ 'Web Chat: "activityRenderer" is deprecated and will be removed on 2022-06-15, please use "activityMiddleware" instead.' ); - return activityRenderer || applyMiddlewareForRenderer('activity', ...singleToArray(activityMiddleware))({}); + return ( + activityRenderer || + applyMiddlewareForRenderer('activity', ...singleToArray(activityMiddleware), () => () => ({ activity }) => { + if (activity) { + throw new Error(`No renderer for activity of type "${activity.type}"`); + } else { + throw new Error('No activity to render'); + } + })({}) + ); }, [activityMiddleware, activityRenderer]); const patchedActivityStatusRenderer = useMemo(() => { @@ -336,7 +343,7 @@ const Composer = ({ return applyMiddlewareForRenderer( 'attachment', ...singleToArray(attachmentMiddleware), - () => () => ({ attachment }) => () => { + () => () => ({ attachment }) => { if (attachment) { throw new Error(`No renderer for attachment of type "${attachment.contentType}"`); } else { @@ -384,7 +391,7 @@ const Composer = ({ return ( typingIndicatorRenderer || - applyMiddlewareForRenderer('typing indicator', ...singleToArray(typingIndicatorMiddleware))({}) + applyMiddlewareForRenderer('typing indicator', ...singleToArray(typingIndicatorMiddleware), () => () => () => false)({}) ); }, [typingIndicatorMiddleware, typingIndicatorRenderer]); diff --git a/packages/api/src/hooks/internal/useCreateActivityRendererInternal.js b/packages/api/src/hooks/internal/useCreateActivityRendererInternal.js index ce8f364ab1..dd5fa7e3ed 100644 --- a/packages/api/src/hooks/internal/useCreateActivityRendererInternal.js +++ b/packages/api/src/hooks/internal/useCreateActivityRendererInternal.js @@ -1,4 +1,4 @@ -import { useMemo } from 'react'; +import { isValidElement, useMemo } from 'react'; import useCreateAttachmentRenderer from '../useCreateAttachmentRenderer'; import useWebChatAPIContext from './useWebChatAPIContext'; @@ -18,6 +18,10 @@ export default function useCreateActivityRendererInternal(createAttachmentRender } return renderActivityOptions => { + if (isValidElement(renderActivity)) { + return renderActivity; + } + const activityElement = renderActivity( (...renderAttachmentArgs) => createAttachmentRenderer(...renderAttachmentArgs), renderActivityOptions diff --git a/packages/api/src/hooks/middleware/applyMiddleware.js b/packages/api/src/hooks/middleware/applyMiddleware.js index 36afd610f7..e89bd64381 100644 --- a/packages/api/src/hooks/middleware/applyMiddleware.js +++ b/packages/api/src/hooks/middleware/applyMiddleware.js @@ -37,7 +37,7 @@ export function forRenderer(type, ...middleware) { } catch (err) { // The next line is not a React component. It is a render function. // eslint-disable-next-line react/display-name - return () => ; + return ; } }; }; diff --git a/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.js b/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.js index 0eb327bcda..4d3c91310c 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.js +++ b/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardRenderer.js @@ -449,12 +449,7 @@ const AdaptiveCardRenderer = ({ actionPerformedClassName, adaptiveCard, disabled }, [actionsPerformed, actionPerformedClassName, lastRender]); return errors.length ? ( - - {errors.map(({ error, message }, index) => ( - /* eslint-disable-next-line react/no-array-index-key */ -
{JSON.stringify({ error, message }, null, 2)}
- ))} -
+ ) : (
next => { const Attachment = args => { - // console.log('defaultAttachmentMiddleware', { activity, args, attachment }); - const { activity = {}, activity: { from: { role } = {} } = {}, diff --git a/packages/component/src/Middleware/createAttachmentRenderer.js b/packages/component/src/Middleware/createAttachmentRenderer.js deleted file mode 100644 index c1dd461ab0..0000000000 --- a/packages/component/src/Middleware/createAttachmentRenderer.js +++ /dev/null @@ -1,26 +0,0 @@ -/* eslint no-magic-numbers: ["error", { "ignore": [2] }] */ - -import React from 'react'; -import concatMiddleware from './concatMiddleware'; -import createCoreAttachmentMiddleware from './Attachment/createCoreMiddleware'; -import ErrorBox from '../ErrorBox'; - -export default function createAttachmentRenderer(additionalMiddleware) { - const attachmentMiddleware = concatMiddleware(additionalMiddleware, createCoreAttachmentMiddleware())({}); - - return (...args) => { - try { - return attachmentMiddleware(({ attachment }) => ( - -
{JSON.stringify(attachment, null, 2)}
-
- ))(...args); - } catch (err) { - return ( - -
{JSON.stringify(err, null, 2)}
-
- ); - } - }; -} From 7fa38cb0490156c18d5cbf503319e1389005be26 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 5 Oct 2020 20:27:27 -0700 Subject: [PATCH 04/21] Fix tests --- __tests__/hooks/useTrackDimension.js | 4 ++++ __tests__/hooks/useTrackEvent.js | 5 +++++ __tests__/hooks/useTrackException.js | 2 ++ __tests__/hooks/useTrackTiming.js | 4 ++++ packages/component/src/Composer.js | 1 + 5 files changed, 16 insertions(+) diff --git a/__tests__/hooks/useTrackDimension.js b/__tests__/hooks/useTrackDimension.js index 9a23bd1434..85e946a3d6 100644 --- a/__tests__/hooks/useTrackDimension.js +++ b/__tests__/hooks/useTrackDimension.js @@ -48,6 +48,7 @@ describe('useTrackDimension', () => { "data": null, "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "hello": "aloha", "prop:locale": "en-US", "prop:speechRecognition": "false", @@ -62,6 +63,7 @@ describe('useTrackDimension', () => { "data": null, "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "prop:locale": "en-US", "prop:speechRecognition": "false", "prop:speechSynthesis": "false", @@ -85,6 +87,7 @@ describe('useTrackDimension', () => { "data": null, "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "prop:locale": "en-US", "prop:speechRecognition": "false", "prop:speechSynthesis": "false", @@ -108,6 +111,7 @@ describe('useTrackDimension', () => { "data": null, "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "prop:locale": "en-US", "prop:speechRecognition": "false", "prop:speechSynthesis": "false", diff --git a/__tests__/hooks/useTrackEvent.js b/__tests__/hooks/useTrackEvent.js index 6c5ce8762d..004b63e9a7 100644 --- a/__tests__/hooks/useTrackEvent.js +++ b/__tests__/hooks/useTrackEvent.js @@ -43,6 +43,7 @@ describe('useTrackEvent', () => { "data": null, "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "prop:locale": "en-US", "prop:speechRecognition": "false", "prop:speechSynthesis": "false", @@ -66,6 +67,7 @@ describe('useTrackEvent', () => { "data": null, "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "prop:locale": "en-US", "prop:speechRecognition": "false", "prop:speechSynthesis": "false", @@ -89,6 +91,7 @@ describe('useTrackEvent', () => { "data": 123, "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "prop:locale": "en-US", "prop:speechRecognition": "false", "prop:speechSynthesis": "false", @@ -112,6 +115,7 @@ describe('useTrackEvent', () => { "data": "aloha", "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "prop:locale": "en-US", "prop:speechRecognition": "false", "prop:speechSynthesis": "false", @@ -138,6 +142,7 @@ describe('useTrackEvent', () => { }, "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "prop:locale": "en-US", "prop:speechRecognition": "false", "prop:speechSynthesis": "false", diff --git a/__tests__/hooks/useTrackException.js b/__tests__/hooks/useTrackException.js index 1d54563d1a..ba57c55a81 100644 --- a/__tests__/hooks/useTrackException.js +++ b/__tests__/hooks/useTrackException.js @@ -43,6 +43,7 @@ describe('useTrackException', () => { "data": null, "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "prop:locale": "en-US", "prop:speechRecognition": "false", "prop:speechSynthesis": "false", @@ -68,6 +69,7 @@ describe('useTrackException', () => { "data": null, "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "prop:locale": "en-US", "prop:speechRecognition": "false", "prop:speechSynthesis": "false", diff --git a/__tests__/hooks/useTrackTiming.js b/__tests__/hooks/useTrackTiming.js index e995219dd0..452fa66984 100644 --- a/__tests__/hooks/useTrackTiming.js +++ b/__tests__/hooks/useTrackTiming.js @@ -49,6 +49,7 @@ describe('useTrackTiming', () => { "data": null, "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "prop:locale": "en-US", "prop:speechRecognition": "false", "prop:speechSynthesis": "false", @@ -62,6 +63,7 @@ describe('useTrackTiming', () => { "data": null, "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "prop:locale": "en-US", "prop:speechRecognition": "false", "prop:speechSynthesis": "false", @@ -92,6 +94,7 @@ describe('useTrackTiming', () => { "data": null, "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "prop:locale": "en-US", "prop:speechRecognition": "false", "prop:speechSynthesis": "false", @@ -105,6 +108,7 @@ describe('useTrackTiming', () => { "data": null, "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "prop:locale": "en-US", "prop:speechRecognition": "false", "prop:speechSynthesis": "false", diff --git a/packages/component/src/Composer.js b/packages/component/src/Composer.js index aa32f8a653..22fa1ebae4 100644 --- a/packages/component/src/Composer.js +++ b/packages/component/src/Composer.js @@ -19,6 +19,7 @@ import downscaleImageToDataURL from './Utils/downscaleImageToDataURL'; import ErrorBox from './ErrorBox'; import mapMap from './Utils/mapMap'; import singleToArray from './Utils/singleToArray'; +import UITracker from './hooks/internal/UITracker'; import WebChatUIContext from './hooks/internal/WebChatUIContext'; const { useStyleOptions } = hooks; From 322c348a07ac556ff05586af136800411a43bb22 Mon Sep 17 00:00:00 2001 From: William Wong Date: Fri, 9 Oct 2020 11:28:17 -0700 Subject: [PATCH 05/21] Fix DLSpeech --- __tests__/telemetry.js | 1 + packages/api/src/hooks/Composer.js | 4 +- packages/api/src/patchStyleOptions.js | 58 +++++++++---------- .../api/src/utils/normalizeLanguage.spec.js | 2 +- packages/core/src/sagas/postActivitySaga.js | 4 +- .../directlinespeech/src/DirectLineSpeech.js | 4 +- 6 files changed, 39 insertions(+), 34 deletions(-) diff --git a/__tests__/telemetry.js b/__tests__/telemetry.js index 7033f9f842..547ea89415 100644 --- a/__tests__/telemetry.js +++ b/__tests__/telemetry.js @@ -37,6 +37,7 @@ describe('telemetry', () => { "data": null, "dimensions": Object { "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", "prop:locale": "en-US", "prop:speechRecognition": "false", "prop:speechSynthesis": "false", diff --git a/packages/api/src/hooks/Composer.js b/packages/api/src/hooks/Composer.js index 9645357852..52d6c8831a 100644 --- a/packages/api/src/hooks/Composer.js +++ b/packages/api/src/hooks/Composer.js @@ -391,7 +391,9 @@ const Composer = ({ return ( typingIndicatorRenderer || - applyMiddlewareForRenderer('typing indicator', ...singleToArray(typingIndicatorMiddleware), () => () => () => false)({}) + applyMiddlewareForRenderer('typing indicator', ...singleToArray(typingIndicatorMiddleware), () => () => () => + false + )({}) ); }, [typingIndicatorMiddleware, typingIndicatorRenderer]); diff --git a/packages/api/src/patchStyleOptions.js b/packages/api/src/patchStyleOptions.js index f968e99dd0..b9d5500608 100644 --- a/packages/api/src/patchStyleOptions.js +++ b/packages/api/src/patchStyleOptions.js @@ -26,7 +26,7 @@ export default function patchStyleOptions( options, { groupTimestamp: groupTimestampFromProps, sendTimeout: sendTimeoutFromProps } ) { - options = { ...defaultStyleOptions, ...options }; + const patchedOptions = { ...defaultStyleOptions, ...options }; // Keep this list flat (no nested style) and serializable (no functions) @@ -37,11 +37,9 @@ export default function patchStyleOptions( bubbleFromUserNubOffset, bubbleNubOffset, emojiSet, - groupTimestamp, - sendTimeout, suggestedActionBorder, suggestedActionDisabledBorder - } = options; + } = patchedOptions; if (bubbleBorder) { console.warn( @@ -51,15 +49,15 @@ export default function patchStyleOptions( const { color, style, width } = parseBorder(bubbleBorder); if (color && color !== 'initial') { - options.bubbleBorderColor = color; + patchedOptions.bubbleBorderColor = color; } if (style && style !== 'initial') { - options.bubbleBorderStyle = style; + patchedOptions.bubbleBorderStyle = style; } if (PIXEL_UNIT_PATTERN.test(width)) { - options.bubbleBorderWidth = parseInt(width, 10); + patchedOptions.bubbleBorderWidth = parseInt(width, 10); } } @@ -71,15 +69,15 @@ export default function patchStyleOptions( const { color, style, width } = parseBorder(bubbleFromUserBorder); if (color && color !== 'initial') { - options.bubbleFromUserBorderColor = color; + patchedOptions.bubbleFromUserBorderColor = color; } if (style && style !== 'initial') { - options.bubbleFromUserBorderStyle = style; + patchedOptions.bubbleFromUserBorderStyle = style; } if (PIXEL_UNIT_PATTERN.test(width)) { - options.bubbleFromUserBorderWidth = parseInt(width, 10); + patchedOptions.bubbleFromUserBorderWidth = parseInt(width, 10); } } @@ -91,15 +89,15 @@ export default function patchStyleOptions( const { color, style, width } = parseBorder(suggestedActionBorder); if (color && color !== 'initial') { - options.suggestedActionBorderColor = color; + patchedOptions.suggestedActionBorderColor = color; } if (style && style !== 'initial') { - options.suggestedActionBorderStyle = style; + patchedOptions.suggestedActionBorderStyle = style; } if (PIXEL_UNIT_PATTERN.test(width)) { - options.suggestedActionBorderWidth = parseInt(width, 10); + patchedOptions.suggestedActionBorderWidth = parseInt(width, 10); } } @@ -111,32 +109,32 @@ export default function patchStyleOptions( const { color, style, width } = parseBorder(suggestedActionDisabledBorder); if (color && color !== 'initial') { - options.suggestedActionDisabledBorderColor = color; + patchedOptions.suggestedActionDisabledBorderColor = color; } if (style && style !== 'initial') { - options.suggestedActionDisabledBorderStyle = style; + patchedOptions.suggestedActionDisabledBorderStyle = style; } if (PIXEL_UNIT_PATTERN.test(width)) { - options.suggestedActionDisabledBorderWidth = parseInt(width, 10); + patchedOptions.suggestedActionDisabledBorderWidth = parseInt(width, 10); } } if (bubbleFromUserNubOffset === 'top') { - options.bubbleFromUserNubOffset = 0; + patchedOptions.bubbleFromUserNubOffset = 0; } else if (typeof bubbleFromUserNubOffset !== 'number') { - options.bubbleFromUserNubOffset = -0; + patchedOptions.bubbleFromUserNubOffset = -0; } if (bubbleNubOffset === 'top') { - options.bubbleNubOffset = 0; + patchedOptions.bubbleNubOffset = 0; } else if (typeof bubbleNubOffset !== 'number') { - options.bubbleNubOffset = -0; + patchedOptions.bubbleNubOffset = -0; } if (emojiSet === true) { - options.emojiSet = { + patchedOptions.emojiSet = { ':)': '😊', ':-)': '😊', '(:': '😊', @@ -163,32 +161,32 @@ export default function patchStyleOptions( ' Date: Fri, 9 Oct 2020 14:46:38 -0700 Subject: [PATCH 06/21] Fix speech support --- packages/api/package.json | 2 - packages/api/src/hooks/Composer.js | 50 +------ packages/api/src/hooks/index.js | 6 +- .../internal/useSettableDictateAbortable.js | 7 - packages/api/src/hooks/internal/useTracker.js | 17 --- .../api/src/hooks/useWebSpeechPonyfill.js | 5 - packages/component/src/BasicSendBox.js | 3 +- packages/component/src/Composer.js | 126 ++++++++++++------ .../internal => component/src}/Dictation.js | 35 ++--- .../component/src/SendBox/MicrophoneButton.js | 6 +- packages/component/src/hooks/index.js | 6 +- .../internal/BypassSpeechSynthesisPonyfill.js | 0 .../component/src/hooks/internal/UITracker.js | 15 ++- .../internal/useSettableDictateAbortable.js | 7 + .../src/hooks/useDictateAbortable.js | 0 .../src/hooks/useWebSpeechPonyfill.js | 5 + 16 files changed, 150 insertions(+), 140 deletions(-) delete mode 100644 packages/api/src/hooks/internal/useSettableDictateAbortable.js delete mode 100644 packages/api/src/hooks/useWebSpeechPonyfill.js rename packages/{api/src/hooks/internal => component/src}/Dictation.js (79%) rename packages/{api => component}/src/hooks/internal/BypassSpeechSynthesisPonyfill.js (100%) create mode 100644 packages/component/src/hooks/internal/useSettableDictateAbortable.js rename packages/{api => component}/src/hooks/useDictateAbortable.js (100%) create mode 100644 packages/component/src/hooks/useWebSpeechPonyfill.js diff --git a/packages/api/package.json b/packages/api/package.json index 049db7d6d4..74cc484404 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -59,9 +59,7 @@ "globalize": "1.5.0", "math-random": "2.0.1", "prop-types": "15.7.2", - "react-dictate-button": "1.2.3-master.6b4fe72", "react-redux": "7.2.0", - "react-say": "2.0.2-master.ee7cd76", "redux": "4.0.5", "simple-update-in": "2.2.0" }, diff --git a/packages/api/src/hooks/Composer.js b/packages/api/src/hooks/Composer.js index 52d6c8831a..262de9ff49 100644 --- a/packages/api/src/hooks/Composer.js +++ b/packages/api/src/hooks/Composer.js @@ -1,5 +1,3 @@ -import { Composer as SayComposer } from 'react-say'; - import { Provider } from 'react-redux'; import PropTypes from 'prop-types'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; @@ -11,7 +9,6 @@ import getAllLocalizedStrings from '../localization/getAllLocalizedStrings'; import isObject from '../utils/isObject'; import normalizeLanguage from '../utils/normalizeLanguage'; import PrecompiledGlobalize from '../external/PrecompiledGlobalize'; -import useReferenceGrammarID from './useReferenceGrammarID'; import { clearSuggestedActions, @@ -44,18 +41,12 @@ import { import createDefaultCardActionMiddleware from './middleware/createDefaultCardActionMiddleware'; import createDefaultGroupActivitiesMiddleware from './middleware/createDefaultGroupActivitiesMiddleware'; import defaultSelectVoice from './internal/defaultSelectVoice'; -import Dictation from './internal/Dictation'; import mapMap from '../utils/mapMap'; import observableToPromise from './utils/observableToPromise'; import Tracker from './internal/Tracker'; import WebChatReduxContext, { useDispatch } from './internal/WebChatReduxContext'; import WebChatAPIContext from './internal/WebChatAPIContext'; -import { - speechSynthesis as bypassSpeechSynthesis, - SpeechSynthesisUtterance as BypassSpeechSynthesisUtterance -} from './internal/BypassSpeechSynthesisPonyfill'; - import applyMiddleware, { forRenderer as applyMiddlewareForRenderer } from './middleware/applyMiddleware'; import patchStyleOptions from '../patchStyleOptions'; import singleToArray from './utils/singleToArray'; @@ -184,11 +175,8 @@ const Composer = ({ typingIndicatorMiddleware, typingIndicatorRenderer, userID, - username, - webSpeechPonyfillFactory + username }) => { - const [dictateAbortable, setDictateAbortable] = useState(); - const [referenceGrammarID] = useReferenceGrammarID(); const dispatch = useDispatch(); const telemetryDimensionsRef = useRef({}); @@ -252,21 +240,6 @@ const Composer = ({ [dispatch] ); - const webSpeechPonyfill = useMemo(() => { - const ponyfill = webSpeechPonyfillFactory && webSpeechPonyfillFactory({ referenceGrammarID }); - const { speechSynthesis, SpeechSynthesisUtterance } = ponyfill || {}; - - return { - ...ponyfill, - speechSynthesis: speechSynthesis || bypassSpeechSynthesis, - SpeechSynthesisUtterance: SpeechSynthesisUtterance || BypassSpeechSynthesisUtterance - }; - }, [referenceGrammarID, webSpeechPonyfillFactory]); - - const dictationOnError = useCallback(err => { - console.error(err); - }, []); - const patchedLocalizedStrings = useMemo( () => mergeStringsOverrides(getAllLocalizedStrings()[normalizeLanguage(locale)], locale, overrideLocalizedStrings), [locale, overrideLocalizedStrings] @@ -417,7 +390,6 @@ const Composer = ({ activityStatusRenderer: patchedActivityStatusRenderer, attachmentRenderer: patchedAttachmentRenderer, avatarRenderer: patchedAvatarRenderer, - dictateAbortable, dir: patchedDir, directLine, disabled, @@ -431,19 +403,16 @@ const Composer = ({ renderMarkdown, selectVoice: patchedSelectVoice, sendTypingIndicator, - setDictateAbortable, styleOptions: patchedStyleOptions, telemetryDimensionsRef, toastRenderer: patchedToastRenderer, trackDimension, typingIndicatorRenderer: patchedTypingIndicatorRenderer, userID, - username, - webSpeechPonyfill + username }), [ cardActionContext, - dictateAbortable, directLine, disabled, downscaleImageToDataURL, @@ -466,21 +435,16 @@ const Composer = ({ patchedTypingIndicatorRenderer, renderMarkdown, sendTypingIndicator, - setDictateAbortable, telemetryDimensionsRef, trackDimension, userID, - username, - webSpeechPonyfill + username ] ); return ( - - {typeof children === 'function' ? children(context) : children} - - + {typeof children === 'function' ? children(context) : children} {onTelemetry && } ); @@ -559,8 +523,7 @@ Composer.defaultProps = { typingIndicatorMiddleware: undefined, typingIndicatorRenderer: undefined, userID: '', - username: '', - webSpeechPonyfillFactory: undefined + username: '' }; Composer.propTypes = { @@ -606,6 +569,5 @@ Composer.propTypes = { typingIndicatorMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), typingIndicatorRenderer: PropTypes.func, userID: PropTypes.string, - username: PropTypes.string, - webSpeechPonyfillFactory: PropTypes.func + username: PropTypes.string }; diff --git a/packages/api/src/hooks/index.js b/packages/api/src/hooks/index.js index d9484664cd..be92e44884 100644 --- a/packages/api/src/hooks/index.js +++ b/packages/api/src/hooks/index.js @@ -10,7 +10,6 @@ import useCreateAttachmentForScreenReaderRenderer from './useCreateAttachmentFor import useCreateAvatarRenderer from './useCreateAvatarRenderer'; import useDateFormatter from './useDateFormatter'; import useDebouncedNotifications from './useDebouncedNotifications'; -import useDictateAbortable from './useDictateAbortable'; import useDictateInterims from './useDictateInterims'; import useDictateState from './useDictateState'; import useDirection from './useDirection'; @@ -60,7 +59,6 @@ import useTrackTiming from './useTrackTiming'; import useUserID from './useUserID'; import useUsername from './useUsername'; import useVoiceSelector from './useVoiceSelector'; -import useWebSpeechPonyfill from './useWebSpeechPonyfill'; export { useActiveTyping, @@ -75,7 +73,6 @@ export { useCreateAvatarRenderer, useDateFormatter, useDebouncedNotifications, - useDictateAbortable, useDictateInterims, useDictateState, useDirection, @@ -124,6 +121,5 @@ export { useTrackTiming, useUserID, useUsername, - useVoiceSelector, - useWebSpeechPonyfill + useVoiceSelector }; diff --git a/packages/api/src/hooks/internal/useSettableDictateAbortable.js b/packages/api/src/hooks/internal/useSettableDictateAbortable.js deleted file mode 100644 index e973a88962..0000000000 --- a/packages/api/src/hooks/internal/useSettableDictateAbortable.js +++ /dev/null @@ -1,7 +0,0 @@ -import useWebChatAPIContext from './useWebChatAPIContext'; - -export default function useSettableDictateAbortable() { - const { dictateAbortable, setDictateAbortable } = useWebChatAPIContext(); - - return [dictateAbortable, setDictateAbortable]; -} diff --git a/packages/api/src/hooks/internal/useTracker.js b/packages/api/src/hooks/internal/useTracker.js index 1c9607f182..c8a51c0748 100644 --- a/packages/api/src/hooks/internal/useTracker.js +++ b/packages/api/src/hooks/internal/useTracker.js @@ -1,14 +1,11 @@ import { useEffect } from 'react'; -import { speechSynthesis } from './BypassSpeechSynthesisPonyfill'; import useLanguage from '../useLanguage'; import useTrackDimension from '../useTrackDimension'; import useTrackEvent from '../useTrackEvent'; -import useWebSpeechPonyfill from '../useWebSpeechPonyfill'; function useTracker() { const [language] = useLanguage(); - const [webSpeechPonyfill] = useWebSpeechPonyfill(); const trackDimension = useTrackDimension(); const trackEvent = useTrackEvent(); @@ -20,24 +17,10 @@ function useTracker() { // - toastMiddleware // - styleOptions - const speechRecognitionCapability = !!webSpeechPonyfill.SpeechRecognition; - const speechSynthesisCapability = - webSpeechPonyfill.speechSynthesis && webSpeechPonyfill.speechSynthesis !== speechSynthesis; - useEffect(() => { trackDimension('prop:locale', language); }, [language, trackDimension]); - useEffect(() => { - // TODO: [P2] #2937 Differentiate between Cognitive Services and browser speech - trackDimension('prop:speechRecognition', !!speechRecognitionCapability + ''); - }, [trackDimension, speechRecognitionCapability]); - - useEffect(() => { - // TODO: [P2] #2937 Differentiate between Cognitive Services and browser speech - trackDimension('prop:speechSynthesis', !!speechSynthesisCapability + ''); - }, [trackDimension, speechSynthesisCapability]); - useEffect(() => { trackEvent('init'); }, [trackEvent]); diff --git a/packages/api/src/hooks/useWebSpeechPonyfill.js b/packages/api/src/hooks/useWebSpeechPonyfill.js deleted file mode 100644 index 63ba5166a1..0000000000 --- a/packages/api/src/hooks/useWebSpeechPonyfill.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatAPIContext from './internal/useWebChatAPIContext'; - -export default function useWebSpeechPonyfill() { - return [useWebChatAPIContext().webSpeechPonyfill]; -} diff --git a/packages/component/src/BasicSendBox.js b/packages/component/src/BasicSendBox.js index 87cde75a2e..2e1d7a41c7 100644 --- a/packages/component/src/BasicSendBox.js +++ b/packages/component/src/BasicSendBox.js @@ -12,12 +12,13 @@ import TextBox from './SendBox/TextBox'; import UploadButton from './SendBox/UploadButton'; import useStyleSet from './hooks/useStyleSet'; import useStyleToEmotionObject from './hooks/internal/useStyleToEmotionObject'; +import useWebSpeechPonyfill from './hooks/useWebSpeechPonyfill'; const { DictateState: { DICTATING, STARTING } } = Constants; -const { useActivities, useDirection, useDictateState, useStyleOptions, useWebSpeechPonyfill } = hooks; +const { useActivities, useDirection, useDictateState, useStyleOptions } = hooks; const ROOT_STYLE = { '& > .main': { diff --git a/packages/component/src/Composer.js b/packages/component/src/Composer.js index 22fa1ebae4..30fe088795 100644 --- a/packages/component/src/Composer.js +++ b/packages/component/src/Composer.js @@ -1,10 +1,11 @@ import { Composer as APIComposer, hooks } from 'botframework-webchat-api'; +import { Composer as SayComposer } from 'react-say'; import { Composer as ScrollToBottomComposer } from 'react-scroll-to-bottom'; -import React, { useMemo, useRef } from 'react'; import createEmotion from 'create-emotion'; import createStyleSet from './Styles/createStyleSet'; import MarkdownIt from 'markdown-it'; import PropTypes from 'prop-types'; +import React, { useCallback, useMemo, useRef, useState } from 'react'; import addTargetBlankToHyperlinksMarkdown from './Utils/addTargetBlankToHyperlinksMarkdown'; import createCSSKey from './Utils/createCSSKey'; @@ -15,6 +16,7 @@ import createDefaultAvatarMiddleware from './Middleware/Avatar/createCoreMiddlew import createDefaultCardActionMiddleware from './Middleware/CardAction/createCoreMiddleware'; import createDefaultToastMiddleware from './Middleware/Toast/createCoreMiddleware'; import createDefaultTypingIndicatorMiddleware from './Middleware/TypingIndicator/createCoreMiddleware'; +import Dictation from './Dictation'; import downscaleImageToDataURL from './Utils/downscaleImageToDataURL'; import ErrorBox from './ErrorBox'; import mapMap from './Utils/mapMap'; @@ -22,7 +24,7 @@ import singleToArray from './Utils/singleToArray'; import UITracker from './hooks/internal/UITracker'; import WebChatUIContext from './hooks/internal/WebChatUIContext'; -const { useStyleOptions } = hooks; +const { useReferenceGrammarID, useStyleOptions } = hooks; const emotionPool = {}; @@ -56,11 +58,27 @@ function styleSetToEmotionObjects(styleToEmotionObject, styleSet) { return mapMap(styleSet, (style, key) => (key === 'options' ? style : styleToEmotionObject(style))); } -const ComposerCore = ({ children, extraStyleSet, nonce, renderMarkdown, styleSet, suggestedActionsAccessKey }) => { +const ComposerCore = ({ + children, + extraStyleSet, + nonce, + renderMarkdown, + styleSet, + suggestedActionsAccessKey, + webSpeechPonyfillFactory +}) => { + const [dictateAbortable, setDictateAbortable] = useState(); + const [referenceGrammarID] = useReferenceGrammarID(); const [styleOptions] = useStyleOptions(); const internalMarkdownIt = useMemo(() => new MarkdownIt(), []); const sendBoxFocusRef = useRef(); + const transcriptActivityElementsRef = useRef([]); const transcriptFocusRef = useRef(); + const transcriptRootElementRef = useRef(); + + const dictationOnError = useCallback(err => { + console.error(err); + }, []); const focusContext = useMemo(() => createFocusContext({ sendBoxFocusRef, transcriptFocusRef }), [ sendBoxFocusRef, @@ -98,25 +116,37 @@ const ComposerCore = ({ children, extraStyleSet, nonce, renderMarkdown, styleSet [extraStyleSet, styleOptions, styleSet, styleToEmotionObject] ); - const transcriptActivityElementsRef = useRef([]); - const transcriptRootElementRef = useRef(); + const webSpeechPonyfill = useMemo(() => { + const ponyfill = webSpeechPonyfillFactory && webSpeechPonyfillFactory({ referenceGrammarID }); + const { speechSynthesis, SpeechSynthesisUtterance } = ponyfill || {}; + + return { + ...ponyfill, + speechSynthesis: speechSynthesis || bypassSpeechSynthesis, + SpeechSynthesisUtterance: SpeechSynthesisUtterance || BypassSpeechSynthesisUtterance + }; + }, [referenceGrammarID, webSpeechPonyfillFactory]); const context = useMemo( () => ({ ...focusContext, + dictateAbortable, internalMarkdownItState: [internalMarkdownIt], internalRenderMarkdownInline, nonce, renderMarkdown, sendBoxFocusRef, + setDictateAbortable, styleSet: patchedStyleSet, styleToEmotionObject, suggestedActionsAccessKey, transcriptActivityElementsRef, transcriptFocusRef, - transcriptRootElementRef + transcriptRootElementRef, + webSpeechPonyfill }), [ + dictateAbortable, focusContext, internalMarkdownIt, internalRenderMarkdownInline, @@ -124,15 +154,26 @@ const ComposerCore = ({ children, extraStyleSet, nonce, renderMarkdown, styleSet patchedStyleSet, renderMarkdown, sendBoxFocusRef, + setDictateAbortable, styleToEmotionObject, suggestedActionsAccessKey, transcriptActivityElementsRef, transcriptFocusRef, - transcriptRootElementRef + transcriptRootElementRef, + webSpeechPonyfill ] ); - return {children}; + return ( + + + + {children} + + + + + ); }; ComposerCore.defaultProps = { @@ -140,7 +181,8 @@ ComposerCore.defaultProps = { nonce: undefined, renderMarkdown: undefined, styleSet: undefined, - suggestedActionsAccessKey: 'A a Å å' + suggestedActionsAccessKey: 'A a Å å', + webSpeechPonyfillFactory: undefined }; ComposerCore.propTypes = { @@ -148,7 +190,8 @@ ComposerCore.propTypes = { nonce: PropTypes.string, renderMarkdown: PropTypes.func, styleSet: PropTypes.any, - suggestedActionsAccessKey: PropTypes.oneOfType([PropTypes.oneOf([false]), PropTypes.string]) + suggestedActionsAccessKey: PropTypes.oneOfType([PropTypes.oneOf([false]), PropTypes.string]), + webSpeechPonyfillFactory: PropTypes.func }; const Composer = ({ @@ -164,6 +207,7 @@ const Composer = ({ suggestedActionsAccessKey, toastMiddleware, typingIndicatorMiddleware, + webSpeechPonyfillFactory, ...composerProps }) => { const { nonce, onTelemetry } = composerProps; @@ -203,32 +247,35 @@ const Composer = ({ ); return ( - - - - {children} - - - {onTelemetry && } - + + + + + {children} + + + {onTelemetry && } + + ); }; @@ -250,7 +297,8 @@ Composer.defaultProps = { toastMiddleware: undefined, toastRenderer: undefined, typingIndicatorMiddleware: undefined, - typingIndicatorRenderer: undefined + typingIndicatorRenderer: undefined, + webSpeechPonyfillFactory: undefined }; Composer.propTypes = { @@ -271,7 +319,9 @@ Composer.propTypes = { toastMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), toastRenderer: PropTypes.func, typingIndicatorMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), - typingIndicatorRenderer: PropTypes.func + typingIndicatorRenderer: PropTypes.func, + // TODO: [PXX] Fix this PropTypes + webSpeechPonyfillFactory: PropTypes.any }; export default Composer; diff --git a/packages/api/src/hooks/internal/Dictation.js b/packages/component/src/Dictation.js similarity index 79% rename from packages/api/src/hooks/internal/Dictation.js rename to packages/component/src/Dictation.js index 046d860255..cd45cc7973 100644 --- a/packages/api/src/hooks/internal/Dictation.js +++ b/packages/component/src/Dictation.js @@ -1,23 +1,28 @@ import { Composer as DictateComposer } from 'react-dictate-button'; import { Constants } from 'botframework-webchat-core'; -// import { hooks } from 'botframework-webchat-api'; +import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; import React, { useCallback, useMemo } from 'react'; -import useActivities from '../useActivities'; -import useDictateInterims from '../useDictateInterims'; -import useDictateState from '../useDictateState'; -import useDisabled from '../useDisabled'; -import useEmitTypingIndicator from '../useEmitTypingIndicator'; -import useLanguage from '../useLanguage'; -import useSendBoxValue from '../useSendBoxValue'; -import useSendTypingIndicator from '../useSendTypingIndicator'; -import useSetDictateState from './useSetDictateState'; -import useSettableDictateAbortable from './useSettableDictateAbortable'; -import useShouldSpeakIncomingActivity from '../useShouldSpeakIncomingActivity'; -import useStopDictate from '../useStopDictate'; -import useSubmitSendBox from '../useSubmitSendBox'; -import useWebSpeechPonyfill from '../useWebSpeechPonyfill'; +import useSettableDictateAbortable from './hooks/internal/useSettableDictateAbortable'; +import useWebSpeechPonyfill from './hooks/useWebSpeechPonyfill'; + +// TODO: [PXX] No /lib/ +import useSetDictateState from 'botframework-webchat-api/lib/hooks/internal/useSetDictateState'; + +const { + useActivities, + useDictateInterims, + useDictateState, + useDisabled, + useEmitTypingIndicator, + useLanguage, + useSendBoxValue, + useSendTypingIndicator, + useShouldSpeakIncomingActivity, + useStopDictate, + useSubmitSendBox +} = hooks; const { DictateState: { DICTATING, IDLE, STARTING } diff --git a/packages/component/src/SendBox/MicrophoneButton.js b/packages/component/src/SendBox/MicrophoneButton.js index 065517a3f3..eadfdcbe3d 100644 --- a/packages/component/src/SendBox/MicrophoneButton.js +++ b/packages/component/src/SendBox/MicrophoneButton.js @@ -11,13 +11,14 @@ import React, { useCallback, useState } from 'react'; import connectToWebChat from '../connectToWebChat'; import IconButton from './IconButton'; import MicrophoneIcon from './Assets/MicrophoneIcon'; +import useDictateAbortable from '../hooks/useDictateAbortable'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; +import useWebSpeechPonyfill from '../hooks/useWebSpeechPonyfill'; const { DictateState } = Constants; const { - useDictateAbortable, useDictateInterims, useDictateState, useDisabled, @@ -25,8 +26,7 @@ const { useSendBoxValue, useShouldSpeakIncomingActivity, useStartDictate, - useStopDictate, - useWebSpeechPonyfill + useStopDictate } = hooks; const ROOT_STYLE = { diff --git a/packages/component/src/hooks/index.js b/packages/component/src/hooks/index.js index 6ed5da539b..2caa6486c9 100644 --- a/packages/component/src/hooks/index.js +++ b/packages/component/src/hooks/index.js @@ -1,3 +1,4 @@ +import useDictateAbortable from './useDictateAbortable'; import useFocus from './useFocus'; import useFocusSendBox from './useFocusSendBox'; import useObserveScrollPosition from './useObserveScrollPosition'; @@ -6,6 +7,7 @@ import useScrollTo from './useScrollTo'; import useScrollToEnd from './useScrollToEnd'; import useSendFiles from './useSendFiles'; import useStyleSet from './useStyleSet'; +import useWebSpeechPonyfill from './useWebSpeechPonyfill'; import { useMicrophoneButtonClick, useMicrophoneButtonDisabled } from '../SendBox/MicrophoneButton'; import { useSendBoxSpeechInterimsVisible } from '../BasicSendBox'; @@ -13,6 +15,7 @@ import { useTextBoxSubmit, useTextBoxValue } from '../SendBox/TextBox'; import { useTypingIndicatorVisible } from '../BasicTypingIndicator'; export { + useDictateAbortable, useFocus, useFocusSendBox, useMicrophoneButtonClick, @@ -26,5 +29,6 @@ export { useStyleSet, useTextBoxSubmit, useTextBoxValue, - useTypingIndicatorVisible + useTypingIndicatorVisible, + useWebSpeechPonyfill }; diff --git a/packages/api/src/hooks/internal/BypassSpeechSynthesisPonyfill.js b/packages/component/src/hooks/internal/BypassSpeechSynthesisPonyfill.js similarity index 100% rename from packages/api/src/hooks/internal/BypassSpeechSynthesisPonyfill.js rename to packages/component/src/hooks/internal/BypassSpeechSynthesisPonyfill.js diff --git a/packages/component/src/hooks/internal/UITracker.js b/packages/component/src/hooks/internal/UITracker.js index f7df22027f..ff8afb4366 100644 --- a/packages/component/src/hooks/internal/UITracker.js +++ b/packages/component/src/hooks/internal/UITracker.js @@ -1,17 +1,28 @@ import { hooks } from 'botframework-webchat-api'; import { useEffect } from 'react'; -import { checkSupport as supportWorker } from '../../Utils/downscaleImageToDataURLUsingWorker'; +import { checkSupport as supportWorker } from '../../Utils/downscaleImageToDataURL/downscaleImageToDataURLUsingWorker'; +import { speechSynthesis } from './BypassSpeechSynthesisPonyfill'; +import useWebSpeechPonyfill from '../useWebSpeechPonyfill'; const { useTrackDimension } = hooks; const Tracker = () => { + const [webSpeechPonyfill] = useWebSpeechPonyfill(); const trackDimension = useTrackDimension(); + const speechRecognitionCapability = !!webSpeechPonyfill.SpeechRecognition; + const speechSynthesisCapability = + webSpeechPonyfill.speechSynthesis && webSpeechPonyfill.speechSynthesis !== speechSynthesis; + useEffect(() => { trackDimension('capability:downscaleImage:workerType', supportWorker() ? 'web worker' : 'main'); trackDimension('capability:renderer', 'html'); - }, [trackDimension]); + + // TODO: [P2] #2937 Differentiate between Cognitive Services and browser speech + trackDimension('prop:speechRecognition', !!speechRecognitionCapability + ''); + trackDimension('prop:speechSynthesis', !!speechSynthesisCapability + ''); + }, [trackDimension, speechRecognitionCapability, speechSynthesisCapability]); return false; }; diff --git a/packages/component/src/hooks/internal/useSettableDictateAbortable.js b/packages/component/src/hooks/internal/useSettableDictateAbortable.js new file mode 100644 index 0000000000..d5352421b1 --- /dev/null +++ b/packages/component/src/hooks/internal/useSettableDictateAbortable.js @@ -0,0 +1,7 @@ +import useWebChatUIContext from './useWebChatUIContext'; + +export default function useSettableDictateAbortable() { + const { dictateAbortable, setDictateAbortable } = useWebChatUIContext(); + + return [dictateAbortable, setDictateAbortable]; +} diff --git a/packages/api/src/hooks/useDictateAbortable.js b/packages/component/src/hooks/useDictateAbortable.js similarity index 100% rename from packages/api/src/hooks/useDictateAbortable.js rename to packages/component/src/hooks/useDictateAbortable.js diff --git a/packages/component/src/hooks/useWebSpeechPonyfill.js b/packages/component/src/hooks/useWebSpeechPonyfill.js new file mode 100644 index 0000000000..2cde9d2fba --- /dev/null +++ b/packages/component/src/hooks/useWebSpeechPonyfill.js @@ -0,0 +1,5 @@ +import useWebChatUIContext from './internal/useWebChatUIContext'; + +export default function useWebSpeechPonyfill() { + return [useWebChatUIContext().webSpeechPonyfill]; +} From 83c0167607c7c042ff032392ad2ab93aa59c600c Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 14 Oct 2020 14:58:56 -0700 Subject: [PATCH 07/21] Fix tests --- ...card-actions-message-back-value-2-snap.png | Bin 0 -> 36855 bytes .../html/focusManagement.sendFailedRetry.js | 3 +- ...CreateAttachmentRenderer.customRender.html | 87 ++++++++++++++++++ ...chmentRenderer.customRenderDeprecated.html | 87 ++++++++++++++++++ .../hooks.useCreateAttachmentRenderer.html | 78 ++++++++++++++++ ...seCreateAttachmentRenderer.noRenderer.html | 74 +++++++++++++++ ...ks.useCreateAttachmentRenderer.remove.html | 79 ++++++++++++++++ __tests__/html/hooks.useRenderAttachment.html | 76 +++++++++++++++ __tests__/html/offlineUI.sendFailed.noAck.js | 2 +- .../html/offlineUI.sendFailed.notSend.js | 2 +- .../html/timestamp.attachmentSendTimeout.js | 3 +- __tests__/richCards.js | 2 +- __tests__/setup/conditions/mediaBuffered.js | 34 ++++--- __tests__/setup/web/index.html | 2 +- docs/HOOKS.md | 18 ++++ packages/api/src/hooks/Composer.js | 28 +++++- packages/api/src/hooks/index.js | 2 + packages/api/src/hooks/internal/ErrorBox.js | 7 +- .../useCreateActivityRendererInternal.js | 13 ++- .../src/hooks/middleware/UserlandBoundary.js | 17 +++- .../src/hooks/middleware/applyMiddleware.js | 5 +- packages/api/src/hooks/useRenderAttachment.js | 6 +- packages/api/src/hooks/utils/ErrorBoundary.js | 10 +- .../src/localization}/Localize.spec.js | 2 +- .../api/src/localization/getLocaleString.js | 2 +- .../src/localization}/getLocaleString.spec.js | 2 +- packages/component/babel.config.json | 2 +- packages/component/src/Composer.js | 14 ++- packages/component/src/ErrorBox.js | 15 +-- 29 files changed, 609 insertions(+), 63 deletions(-) create mode 100644 __tests__/__image_snapshots__/html/hero-card-actions-js-hero-card-actions-message-back-value-2-snap.png create mode 100644 __tests__/html/hooks.useCreateAttachmentRenderer.customRender.html create mode 100644 __tests__/html/hooks.useCreateAttachmentRenderer.customRenderDeprecated.html create mode 100644 __tests__/html/hooks.useCreateAttachmentRenderer.html create mode 100644 __tests__/html/hooks.useCreateAttachmentRenderer.noRenderer.html create mode 100644 __tests__/html/hooks.useCreateAttachmentRenderer.remove.html create mode 100644 __tests__/html/hooks.useRenderAttachment.html rename packages/{component/src/__tests__ => api/src/localization}/Localize.spec.js (94%) rename packages/{component/src/__tests__ => api/src/localization}/getLocaleString.spec.js (86%) diff --git a/__tests__/__image_snapshots__/html/hero-card-actions-js-hero-card-actions-message-back-value-2-snap.png b/__tests__/__image_snapshots__/html/hero-card-actions-js-hero-card-actions-message-back-value-2-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..69db1a955479d9472e47b62c46cc003e6208fafc GIT binary patch literal 36855 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
+ + + diff --git a/__tests__/html/hooks.useCreateAttachmentRenderer.customRenderDeprecated.html b/__tests__/html/hooks.useCreateAttachmentRenderer.customRenderDeprecated.html new file mode 100644 index 0000000000..c8a2366307 --- /dev/null +++ b/__tests__/html/hooks.useCreateAttachmentRenderer.customRenderDeprecated.html @@ -0,0 +1,87 @@ + + + + + + + +
+ + + diff --git a/__tests__/html/hooks.useCreateAttachmentRenderer.html b/__tests__/html/hooks.useCreateAttachmentRenderer.html new file mode 100644 index 0000000000..978465fffa --- /dev/null +++ b/__tests__/html/hooks.useCreateAttachmentRenderer.html @@ -0,0 +1,78 @@ + + + + + + + +
+ + + diff --git a/__tests__/html/hooks.useCreateAttachmentRenderer.noRenderer.html b/__tests__/html/hooks.useCreateAttachmentRenderer.noRenderer.html new file mode 100644 index 0000000000..22c02fdca5 --- /dev/null +++ b/__tests__/html/hooks.useCreateAttachmentRenderer.noRenderer.html @@ -0,0 +1,74 @@ + + + + + + + +
+ + + diff --git a/__tests__/html/hooks.useCreateAttachmentRenderer.remove.html b/__tests__/html/hooks.useCreateAttachmentRenderer.remove.html new file mode 100644 index 0000000000..b05561538c --- /dev/null +++ b/__tests__/html/hooks.useCreateAttachmentRenderer.remove.html @@ -0,0 +1,79 @@ + + + + + + + +
+ + + diff --git a/__tests__/html/hooks.useRenderAttachment.html b/__tests__/html/hooks.useRenderAttachment.html new file mode 100644 index 0000000000..e5255e7ec5 --- /dev/null +++ b/__tests__/html/hooks.useRenderAttachment.html @@ -0,0 +1,76 @@ + + + + + + + +
+ + + diff --git a/__tests__/html/offlineUI.sendFailed.noAck.js b/__tests__/html/offlineUI.sendFailed.noAck.js index dc9e90b0bd..f22b174d9f 100644 --- a/__tests__/html/offlineUI.sendFailed.noAck.js +++ b/__tests__/html/offlineUI.sendFailed.noAck.js @@ -4,5 +4,5 @@ describe('offline UI', () => { test('should display "Send failed. Retry" when activity is sent but not acknowledged', () => - runHTMLTest('offlineUI.sendFailed.noAck.html')); + runHTMLTest('offlineUI.sendFailed.noAck.html', { ignoreConsoleError: true })); }); diff --git a/__tests__/html/offlineUI.sendFailed.notSend.js b/__tests__/html/offlineUI.sendFailed.notSend.js index 721d93a5b9..eadc0529dd 100644 --- a/__tests__/html/offlineUI.sendFailed.notSend.js +++ b/__tests__/html/offlineUI.sendFailed.notSend.js @@ -4,5 +4,5 @@ describe('offline UI', () => { test('should display "Send failed. Retry" when activity is not able to send', () => - runHTMLTest('offlineUI.sendFailed.notSend.html')); + runHTMLTest('offlineUI.sendFailed.notSend.html', { ignoreConsoleError: true })); }); diff --git a/__tests__/html/timestamp.attachmentSendTimeout.js b/__tests__/html/timestamp.attachmentSendTimeout.js index 59e2febefc..09061dadf8 100644 --- a/__tests__/html/timestamp.attachmentSendTimeout.js +++ b/__tests__/html/timestamp.attachmentSendTimeout.js @@ -3,5 +3,6 @@ */ describe('timestamp', () => { - test('send timeout for attachment should be different', () => runHTMLTest('timestamp.attachmentSendTimeout.html')); + test('send timeout for attachment should be different', () => + runHTMLTest('timestamp.attachmentSendTimeout.html', { ignoreConsoleError: true })); }); diff --git a/__tests__/richCards.js b/__tests__/richCards.js index 1ae4e88d79..ebb54b170a 100644 --- a/__tests__/richCards.js +++ b/__tests__/richCards.js @@ -1,4 +1,4 @@ -import { By, until } from 'selenium-webdriver'; +import { By } from 'selenium-webdriver'; import { imageSnapshotOptions, timeouts } from './constants.json'; import allImagesLoaded from './setup/conditions/allImagesLoaded'; diff --git a/__tests__/setup/conditions/mediaBuffered.js b/__tests__/setup/conditions/mediaBuffered.js index 134d11774c..fac40fd40a 100644 --- a/__tests__/setup/conditions/mediaBuffered.js +++ b/__tests__/setup/conditions/mediaBuffered.js @@ -1,19 +1,31 @@ import { Condition } from 'selenium-webdriver'; +// We will check buffered duration for 5 times of each 300ms interval. +// If all 3 checks return the same buffered length, we will consider the buffering has stabilized. +const NUM_BUFFERED_CHECK = 5; +const BUFFERED_CHECK_INTERVAL = 300; + export default function mediaBuffered(mediaElement) { return new Condition('for audio to finish buffering', async driver => { - const result = await driver.executeScript(mediaElement => { - return ( - mediaElement.readyState === HTMLMediaElement.HAVE_ENOUGH_DATA && - mediaElement.buffered.length && - mediaElement.buffered.end(0) === mediaElement.duration - ); - }, mediaElement); + for (let index = 0; index < NUM_BUFFERED_CHECK; index++) { + const result = await driver.executeScript(mediaElement => { + const bufferedDuration = mediaElement.buffered.length && mediaElement.buffered.end(0); + const buffered = + mediaElement.readyState === HTMLMediaElement.HAVE_ENOUGH_DATA && + bufferedDuration === mediaElement.__lastBufferedDuration; + + mediaElement.__lastBufferedDuration = bufferedDuration; + + return buffered; + }, mediaElement); + + if (!result) { + return false; + } - // TODO: [P3] #3557 If the result is positive, audio finished buffering, we still need to wait for an unknown time to refresh the UI. - // Will be great if we can remove this sleep. - result && (await driver.sleep(2000)); + await driver.sleep(BUFFERED_CHECK_INTERVAL); + } - return result; + return true; }); } diff --git a/__tests__/setup/web/index.html b/__tests__/setup/web/index.html index 981fdb6dfe..4806b5762f 100644 --- a/__tests__/setup/web/index.html +++ b/__tests__/setup/web/index.html @@ -25,7 +25,7 @@ window.addEventListener('error', ({ colno, error, filename, lineno, message }) => { push( - 'onError', + 'error', JSON.stringify({ colno, error, diff --git a/docs/HOOKS.md b/docs/HOOKS.md index 69d2ceaa25..77c02c0d64 100644 --- a/docs/HOOKS.md +++ b/docs/HOOKS.md @@ -62,6 +62,7 @@ Following is the list of hooks supported by Web Chat API. - [`useCreateActivityRenderer`](#usecreateactivityrenderer) - [`useCreateActivityStatusRenderer`](#usecreateactivitystatusrenderer) - [`useCreateAttachmentForScreenReaderRenderer`](#useCreateAttachmentForScreenReaderRenderer) +- [`useCreateAttachmentRenderer`](#usecreateattachmentrenderer) - [`useCreateAvatarRenderer`](#usecreateavatarrenderer) - [`useDateFormatter`](#useDateFormatter) - [`useDebouncedNotification`](#usedebouncednotification) @@ -314,6 +315,23 @@ useCreateAttachmentForScreenReaderRenderer(): ({ This hook will return a function that, when called with activity and attachment, will either return a function to render the attachment used by screen reader, or `false` if the attachment should not be rendered. +## `useCreateAttachmentRenderer`` + + +```js +useCreateAttachmentRenderer(): ({ + activity: Activity, + attachment: Attachment +}) => + ( + false | + () => React.Element + ) +``` + + +([PXX] TBD) + ## `useCreateAvatarRenderer` diff --git a/packages/api/src/hooks/Composer.js b/packages/api/src/hooks/Composer.js index 262de9ff49..1f8007949b 100644 --- a/packages/api/src/hooks/Composer.js +++ b/packages/api/src/hooks/Composer.js @@ -1,6 +1,6 @@ import { Provider } from 'react-redux'; import PropTypes from 'prop-types'; -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { isValidElement, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import updateIn from 'simple-update-in'; import createCustomEvent from '../utils/createCustomEvent'; @@ -313,10 +313,10 @@ const Composer = ({ return attachmentRenderer; } - return applyMiddlewareForRenderer( + const renderer = applyMiddlewareForRenderer( 'attachment', ...singleToArray(attachmentMiddleware), - () => () => ({ attachment }) => { + () => () => ({ attachment }) => () => { if (attachment) { throw new Error(`No renderer for attachment of type "${attachment.contentType}"`); } else { @@ -324,6 +324,26 @@ const Composer = ({ } } )({}); + + let showDeprecationNotes = true; + + return (...args) => { + const result = renderer(...args); + + if (isValidElement(result)) { + if (showDeprecationNotes) { + console.warn( + 'botframework-webchat: Please upgrade the attachment middleware with a new signature. For details, please see HOOKS.md#usecreateattachmentrenderer.' + ); + + showDeprecationNotes = false; + } + + return () => result; + } else { + return result; + } + }; }, [attachmentMiddleware, attachmentRenderer]); const patchedAvatarRenderer = useMemo(() => { @@ -556,7 +576,7 @@ Composer.propTypes = { grammars: PropTypes.arrayOf(PropTypes.string), groupActivitiesMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), groupTimestamp: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]), - internalErrorBoxClass: PropTypes.func.isRequired, // This is for internal use only. We don't allow customization of error box. + internalErrorBoxClass: PropTypes.func, // This is for internal use only. We don't allow customization of error box. locale: PropTypes.string, onTelemetry: PropTypes.func, overrideLocalizedStrings: PropTypes.oneOfType([PropTypes.any, PropTypes.func]), diff --git a/packages/api/src/hooks/index.js b/packages/api/src/hooks/index.js index be92e44884..b429ec2143 100644 --- a/packages/api/src/hooks/index.js +++ b/packages/api/src/hooks/index.js @@ -7,6 +7,7 @@ import useConnectivityStatus from './useConnectivityStatus'; import useCreateActivityRenderer from './useCreateActivityRenderer'; import useCreateActivityStatusRenderer from './useCreateActivityStatusRenderer'; import useCreateAttachmentForScreenReaderRenderer from './useCreateAttachmentForScreenReaderRenderer'; +import useCreateAttachmentRenderer from './useCreateAttachmentRenderer'; import useCreateAvatarRenderer from './useCreateAvatarRenderer'; import useDateFormatter from './useDateFormatter'; import useDebouncedNotifications from './useDebouncedNotifications'; @@ -70,6 +71,7 @@ export { useCreateActivityRenderer, useCreateActivityStatusRenderer, useCreateAttachmentForScreenReaderRenderer, + useCreateAttachmentRenderer, useCreateAvatarRenderer, useDateFormatter, useDebouncedNotifications, diff --git a/packages/api/src/hooks/internal/ErrorBox.js b/packages/api/src/hooks/internal/ErrorBox.js index 83325c1cdc..726c3644e1 100644 --- a/packages/api/src/hooks/internal/ErrorBox.js +++ b/packages/api/src/hooks/internal/ErrorBox.js @@ -4,6 +4,8 @@ import PropTypes from 'prop-types'; import useErrorBoxClass from './useErrorBoxClass'; import useTrackException from '../useTrackException'; +// TODO: [PXX] Check if this class is used. + const ErrorBox = ({ error, type }) => { const [errorBoxClass] = useErrorBoxClass(); const trackException = useTrackException(); @@ -12,10 +14,7 @@ const ErrorBox = ({ error, type }) => { trackException(error, false); }, [error, trackException]); - // console.log({ error, errorBoxClass, type }); - // console.trace(); - - return createElement(errorBoxClass, { error, type }); + return !!errorBoxClass && createElement(errorBoxClass, { error, type }); }; ErrorBox.defaultProps = { diff --git a/packages/api/src/hooks/internal/useCreateActivityRendererInternal.js b/packages/api/src/hooks/internal/useCreateActivityRendererInternal.js index dd5fa7e3ed..30e82db6d0 100644 --- a/packages/api/src/hooks/internal/useCreateActivityRendererInternal.js +++ b/packages/api/src/hooks/internal/useCreateActivityRendererInternal.js @@ -22,10 +22,15 @@ export default function useCreateActivityRendererInternal(createAttachmentRender return renderActivity; } - const activityElement = renderActivity( - (...renderAttachmentArgs) => createAttachmentRenderer(...renderAttachmentArgs), - renderActivityOptions - ); + const activityElement = renderActivity((...renderAttachmentArgs) => { + // Currently, the API signature for renderActivity is: + // renderActivity(({ activity, attachment }) => React.Element) + // We will bridge newer version of createAttachmentRenderer to the older API for now. + const result = createAttachmentRenderer(...renderAttachmentArgs); + + // return isValidElement(result) ? () => result : result; + return isValidElement(result) ? result : result(); + }, renderActivityOptions); // "activityElement" cannot be false. If the middleware want to hide the "activityElement", it should return "false" when we call createActivityRenderer(). activityElement || diff --git a/packages/api/src/hooks/middleware/UserlandBoundary.js b/packages/api/src/hooks/middleware/UserlandBoundary.js index 43d968fa16..3a5b74cf4f 100644 --- a/packages/api/src/hooks/middleware/UserlandBoundary.js +++ b/packages/api/src/hooks/middleware/UserlandBoundary.js @@ -3,16 +3,27 @@ import React, { createElement, useCallback, useState } from 'react'; import ErrorBoundary from '../utils/ErrorBoundary'; import useErrorBoxClass from '../internal/useErrorBoxClass'; +import useTrackException from '../useTrackException'; const UserlandBoundary = ({ children, type }) => { const [error, setError] = useState(); const [errorBoxClass] = useErrorBoxClass(); - const handleError = useCallback(({ error }) => setError(error)); + const trackException = useTrackException(); - // console.log('UserlandBoundary', { children }); + const handleError = useCallback(error => { + setError(error); + + const errorObject = error || new Error(type); + + trackException(errorObject, false); + + console.group(`botframework-webchat: ${type}`); + console.error(errorObject); + console.groupEnd(); + }, [trackException]); return error ? ( - createElement(errorBoxClass, { error, type }) + !!errorBoxClass && createElement(errorBoxClass, { error, type }) ) : ( {children} ); diff --git a/packages/api/src/hooks/middleware/applyMiddleware.js b/packages/api/src/hooks/middleware/applyMiddleware.js index e89bd64381..2d1174dcea 100644 --- a/packages/api/src/hooks/middleware/applyMiddleware.js +++ b/packages/api/src/hooks/middleware/applyMiddleware.js @@ -10,7 +10,6 @@ export default function applyMiddleware(type, ...middleware) { throw new Error(`reached terminator of ${type}`); }); } - export function forRenderer(type, ...middleware) { return (...setupArgs) => { const runMiddleware = concatMiddleware(...middleware)(...setupArgs)(() => ( @@ -31,12 +30,10 @@ export function forRenderer(type, ...middleware) { return {render}; } else { return (...renderTimeArgs) => ( - {render(...renderTimeArgs)} + {() => render(...renderTimeArgs)} ); } } catch (err) { - // The next line is not a React component. It is a render function. - // eslint-disable-next-line react/display-name return ; } }; diff --git a/packages/api/src/hooks/useRenderAttachment.js b/packages/api/src/hooks/useRenderAttachment.js index 4295676a4c..41cbfcf606 100644 --- a/packages/api/src/hooks/useRenderAttachment.js +++ b/packages/api/src/hooks/useRenderAttachment.js @@ -1,3 +1,5 @@ +import { isValidElement } from 'react'; + import useCreateAttachmentRenderer from './useCreateAttachmentRenderer'; let showDeprecationNotes = true; @@ -14,8 +16,8 @@ export default function useRenderAttachment() { const createAttachmentRenderer = useCreateAttachmentRenderer(); return (...renderArgs) => { - const render = createAttachmentRenderer(...renderArgs); + const result = createAttachmentRenderer(...renderArgs); - return !!render && render(); + return !!result && isValidElement(result) ? result : result(); }; } diff --git a/packages/api/src/hooks/utils/ErrorBoundary.js b/packages/api/src/hooks/utils/ErrorBoundary.js index e801d62578..f7c90af392 100644 --- a/packages/api/src/hooks/utils/ErrorBoundary.js +++ b/packages/api/src/hooks/utils/ErrorBoundary.js @@ -1,21 +1,23 @@ -import { Component } from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; +const RenderChildrenFunction = ({ children }) => (typeof children === 'function' ? children() : children); + class ErrorBoundary extends Component { constructor() { super(); - this.state = { error: undefined }; + this.state = { hasError: false }; } componentDidCatch(error) { - this.setState({ error }); + this.setState({ hasError: true }); this.props.onError(error); } render() { - return !this.state.error && this.props.children; + return !this.state.hasError && {this.props.children}; } } diff --git a/packages/component/src/__tests__/Localize.spec.js b/packages/api/src/localization/Localize.spec.js similarity index 94% rename from packages/component/src/__tests__/Localize.spec.js rename to packages/api/src/localization/Localize.spec.js index de9ebe9077..a01b8425f4 100644 --- a/packages/component/src/__tests__/Localize.spec.js +++ b/packages/api/src/localization/Localize.spec.js @@ -1,4 +1,4 @@ -import { getLocaleString, localize } from '../../lib/Localization/Localize'; +import { getLocaleString, localize } from './Localize'; const originalWarn = console.warn; let warnings; diff --git a/packages/api/src/localization/getLocaleString.js b/packages/api/src/localization/getLocaleString.js index a5a59965cd..b582220670 100644 --- a/packages/api/src/localization/getLocaleString.js +++ b/packages/api/src/localization/getLocaleString.js @@ -1,4 +1,4 @@ -import PrecompiledGlobalize from '../external/PrecompiledGlobalize'; +import PrecompiledGlobalize from '../../lib/external/PrecompiledGlobalize'; export default function getLocaleString(value, language) { const globalize = PrecompiledGlobalize(language); diff --git a/packages/component/src/__tests__/getLocaleString.spec.js b/packages/api/src/localization/getLocaleString.spec.js similarity index 86% rename from packages/component/src/__tests__/getLocaleString.spec.js rename to packages/api/src/localization/getLocaleString.spec.js index 1a2381bca5..3fb06fc84b 100644 --- a/packages/component/src/__tests__/getLocaleString.spec.js +++ b/packages/api/src/localization/getLocaleString.spec.js @@ -1,4 +1,4 @@ -import getLocaleString from '../../lib/Localization/getLocaleString'; +import getLocaleString from './getLocaleString'; test('should return formatted date for "en"', async () => { const actual = getLocaleString(new Date(2000, 11, 23, 12, 34, 56, 789), 'en'); diff --git a/packages/component/babel.config.json b/packages/component/babel.config.json index e43758f909..cfadc9c45f 100644 --- a/packages/component/babel.config.json +++ b/packages/component/babel.config.json @@ -26,7 +26,7 @@ [ "transform-inline-environment-variables", { - "include": ["npm_package_version"] + "include": ["NODE_ENV", "node_env", "npm_package_version"] } ] ], diff --git a/packages/component/src/Composer.js b/packages/component/src/Composer.js index 30fe088795..a56cc4888b 100644 --- a/packages/component/src/Composer.js +++ b/packages/component/src/Composer.js @@ -7,6 +7,10 @@ import MarkdownIt from 'markdown-it'; import PropTypes from 'prop-types'; import React, { useCallback, useMemo, useRef, useState } from 'react'; +import { + speechSynthesis as bypassSpeechSynthesis, + SpeechSynthesisUtterance as BypassSpeechSynthesisUtterance +} from './hooks/internal/BypassSpeechSynthesisPonyfill'; import addTargetBlankToHyperlinksMarkdown from './Utils/addTargetBlankToHyperlinksMarkdown'; import createCSSKey from './Utils/createCSSKey'; import createDefaultActivityMiddleware from './Middleware/Activity/createCoreMiddleware'; @@ -26,6 +30,8 @@ import WebChatUIContext from './hooks/internal/WebChatUIContext'; const { useReferenceGrammarID, useStyleOptions } = hooks; +const node_env = process.env.node_env || process.env.NODE_ENV; + const emotionPool = {}; function createFocusContext({ sendBoxFocusRef, transcriptFocusRef }) { @@ -255,7 +261,8 @@ const Composer = ({ avatarMiddleware={patchedAvatarMiddleware} cardActionMiddleware={patchedCardActionMiddleware} downscaleImageToDataURL={downscaleImageToDataURL} - internalErrorBoxClass={ErrorBox} + // Under dev server of create-react-app, "NODE_ENV" will be set to "development". + internalErrorBoxClass={node_env === 'development' ? ErrorBox : undefined} nonce={nonce} toastMiddleware={patchedToastMiddleware} typingIndicatorMiddleware={patchedTypingIndicatorMiddleware} @@ -271,9 +278,9 @@ const Composer = ({ webSpeechPonyfillFactory={webSpeechPonyfillFactory} > {children} + {onTelemetry && } - {onTelemetry && } ); @@ -320,8 +327,7 @@ Composer.propTypes = { toastRenderer: PropTypes.func, typingIndicatorMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), typingIndicatorRenderer: PropTypes.func, - // TODO: [PXX] Fix this PropTypes - webSpeechPonyfillFactory: PropTypes.any + webSpeechPonyfillFactory: PropTypes.func }; export default Composer; diff --git a/packages/component/src/ErrorBox.js b/packages/component/src/ErrorBox.js index 4eddcafbf1..0dbac22054 100644 --- a/packages/component/src/ErrorBox.js +++ b/packages/component/src/ErrorBox.js @@ -2,27 +2,16 @@ import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; -import React, { useEffect } from 'react'; +import React from 'react'; import ScreenReaderText from './ScreenReaderText'; import useStyleSet from './hooks/useStyleSet'; -const { useLocalizer, useTrackException } = hooks; +const { useLocalizer } = hooks; const ErrorBox = ({ error, type }) => { const [{ errorBox: errorBoxStyleSet }] = useStyleSet(); const localize = useLocalizer(); - const trackException = useTrackException(); - - useEffect(() => { - const errorObject = error || new Error(type); - - trackException(errorObject, false); - - console.group(`botframework-webchat: ${type}`); - console.error(errorObject); - console.groupEnd(); - }, [error, type, trackException]); return ( From 740d68e6ec6409d5b382d9ff651e8746dac3573e Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 14 Oct 2020 15:02:55 -0700 Subject: [PATCH 08/21] Fix ESLint --- packages/api/src/hooks/Composer.js | 11 ++++++++--- packages/api/src/hooks/useRenderActivityStatus.js | 4 ---- packages/api/src/hooks/useSendFiles.js | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/api/src/hooks/Composer.js b/packages/api/src/hooks/Composer.js index 1f8007949b..970a1269cb 100644 --- a/packages/api/src/hooks/Composer.js +++ b/packages/api/src/hooks/Composer.js @@ -340,9 +340,9 @@ const Composer = ({ } return () => result; - } else { - return result; } + + return result; }; }, [attachmentMiddleware, attachmentRenderer]); @@ -491,18 +491,20 @@ const ComposeWithStore = ({ internalRenderErrorBox, onTelemetry, store, ...props ) : ( - + ); }; ComposeWithStore.defaultProps = { + internalRenderErrorBox: undefined, onTelemetry: undefined, store: undefined }; ComposeWithStore.propTypes = { + internalRenderErrorBox: PropTypes.any, onTelemetry: PropTypes.func, store: PropTypes.any }; @@ -531,9 +533,11 @@ Composer.defaultProps = { grammars: [], groupActivitiesMiddleware: undefined, groupTimestamp: undefined, + internalErrorBoxClass: undefined, locale: window.navigator.language || 'en-US', onTelemetry: undefined, overrideLocalizedStrings: undefined, + renderMarkdown: undefined, selectVoice: undefined, sendTimeout: undefined, sendTypingIndicator: false, @@ -580,6 +584,7 @@ Composer.propTypes = { locale: PropTypes.string, onTelemetry: PropTypes.func, overrideLocalizedStrings: PropTypes.oneOfType([PropTypes.any, PropTypes.func]), + renderMarkdown: PropTypes.func, selectVoice: PropTypes.func, sendTimeout: PropTypes.number, sendTypingIndicator: PropTypes.bool, diff --git a/packages/api/src/hooks/useRenderActivityStatus.js b/packages/api/src/hooks/useRenderActivityStatus.js index 92daedd1a2..95997f050e 100644 --- a/packages/api/src/hooks/useRenderActivityStatus.js +++ b/packages/api/src/hooks/useRenderActivityStatus.js @@ -14,8 +14,6 @@ import useCreateActivityStatusRenderer from './useCreateActivityStatusRenderer'; // Despite deprecation, useRenderActivityStatus() can be retrofitted using useCreateActivityStatusRenderer(). -const RETURN_FALSE = () => false; - let showDeprecationNotes = true; export default function useRenderActivityStatus({ activity, nextVisibleActivity }) { @@ -32,8 +30,6 @@ export default function useRenderActivityStatus({ activity, nextVisibleActivity return useMemo(() => { const renderActivityStatus = createActivityStatusRenderer({ activity, nextVisibleActivity }); - console.log('useRenderActivityStatus', { renderActivityStatus }); - return !!renderActivityStatus && renderActivityStatus; }, [activity, createActivityStatusRenderer, nextVisibleActivity]); } diff --git a/packages/api/src/hooks/useSendFiles.js b/packages/api/src/hooks/useSendFiles.js index c934322026..b43f8c5e63 100644 --- a/packages/api/src/hooks/useSendFiles.js +++ b/packages/api/src/hooks/useSendFiles.js @@ -10,7 +10,7 @@ export default function useSendFiles() { const trackEvent = useTrackEvent(); return useCallback( - async files => { + files => { if (files && files.length) { sendFiles(files); From f5bf5e59b86284823c567941fda48619bfae372c Mon Sep 17 00:00:00 2001 From: William Wong Date: Thu, 15 Oct 2020 12:55:11 -0700 Subject: [PATCH 09/21] Fix tests --- __tests__/attachmentMiddleware.js | 6 +- ...CreateAttachmentRenderer.customRender.html | 87 ------------------- ...chmentRenderer.customRenderDeprecated.html | 87 ------------------- .../hooks.useCreateAttachmentRenderer.html | 78 ----------------- ...seCreateAttachmentRenderer.noRenderer.html | 74 ---------------- ...ks.useCreateAttachmentRenderer.remove.html | 79 ----------------- packages/api/src/hooks/Composer.js | 67 +++++++++----- .../useCreateActivityRendererInternal.js | 23 ++--- .../src/hooks/middleware/applyMiddleware.js | 1 + .../src/hooks/useCreateAttachmentRenderer.js | 7 -- packages/api/src/hooks/useRenderAttachment.js | 38 ++++---- ...createAdaptiveCardsAttachmentMiddleware.js | 56 +++++------- .../Attachment/createCoreMiddleware.js | 52 +++++------ 13 files changed, 125 insertions(+), 530 deletions(-) delete mode 100644 __tests__/html/hooks.useCreateAttachmentRenderer.customRender.html delete mode 100644 __tests__/html/hooks.useCreateAttachmentRenderer.customRenderDeprecated.html delete mode 100644 __tests__/html/hooks.useCreateAttachmentRenderer.html delete mode 100644 __tests__/html/hooks.useCreateAttachmentRenderer.noRenderer.html delete mode 100644 __tests__/html/hooks.useCreateAttachmentRenderer.remove.html delete mode 100644 packages/api/src/hooks/useCreateAttachmentRenderer.js diff --git a/__tests__/attachmentMiddleware.js b/__tests__/attachmentMiddleware.js index 1821f2b20f..5f011f5f2f 100644 --- a/__tests__/attachmentMiddleware.js +++ b/__tests__/attachmentMiddleware.js @@ -37,10 +37,12 @@ test('file upload should show thumbnail and file name', async () => { attachments: patchedAttachments }); - return React.createElement(React.Fragment, {}, [ + return React.createElement( + React.Fragment, + {}, next({ activity, attachment }), next({ activity: patchedActivity, attachment: patchedAttachment }) - ]); + ); } return next({ activity, attachment }); diff --git a/__tests__/html/hooks.useCreateAttachmentRenderer.customRender.html b/__tests__/html/hooks.useCreateAttachmentRenderer.customRender.html deleted file mode 100644 index 7440c92743..0000000000 --- a/__tests__/html/hooks.useCreateAttachmentRenderer.customRender.html +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - -
- - - diff --git a/__tests__/html/hooks.useCreateAttachmentRenderer.customRenderDeprecated.html b/__tests__/html/hooks.useCreateAttachmentRenderer.customRenderDeprecated.html deleted file mode 100644 index c8a2366307..0000000000 --- a/__tests__/html/hooks.useCreateAttachmentRenderer.customRenderDeprecated.html +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - -
- - - diff --git a/__tests__/html/hooks.useCreateAttachmentRenderer.html b/__tests__/html/hooks.useCreateAttachmentRenderer.html deleted file mode 100644 index 978465fffa..0000000000 --- a/__tests__/html/hooks.useCreateAttachmentRenderer.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - -
- - - diff --git a/__tests__/html/hooks.useCreateAttachmentRenderer.noRenderer.html b/__tests__/html/hooks.useCreateAttachmentRenderer.noRenderer.html deleted file mode 100644 index 22c02fdca5..0000000000 --- a/__tests__/html/hooks.useCreateAttachmentRenderer.noRenderer.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - -
- - - diff --git a/__tests__/html/hooks.useCreateAttachmentRenderer.remove.html b/__tests__/html/hooks.useCreateAttachmentRenderer.remove.html deleted file mode 100644 index b05561538c..0000000000 --- a/__tests__/html/hooks.useCreateAttachmentRenderer.remove.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - -
- - - diff --git a/packages/api/src/hooks/Composer.js b/packages/api/src/hooks/Composer.js index 970a1269cb..3c15a4c735 100644 --- a/packages/api/src/hooks/Composer.js +++ b/packages/api/src/hooks/Composer.js @@ -304,6 +304,48 @@ const Composer = ({ ); }, [activityStatusMiddleware, activityStatusRenderer]); + // const patchedAttachmentRenderer = useMemo(() => { + // if (attachmentRenderer) { + // console.warn( + // 'Web Chat: "attachmentRenderer" is deprecated and will be removed on 2022-06-15, please use "attachmentMiddleware" instead.' + // ); + + // return attachmentRenderer; + // } + + // const renderer = applyMiddlewareForRenderer( + // 'attachment', + // ...singleToArray(attachmentMiddleware), + // () => () => ({ attachment }) => () => { + // if (attachment) { + // throw new Error(`No renderer for attachment of type "${attachment.contentType}"`); + // } else { + // throw new Error('No attachment to render'); + // } + // } + // )({}); + + // let showDeprecationNotes = true; + + // return (...args) => { + // const result = renderer(...args); + + // if (isValidElement(result)) { + // if (showDeprecationNotes) { + // console.warn( + // 'botframework-webchat: Please upgrade the attachment middleware with a new signature. For details, please see HOOKS.md#usecreateattachmentrenderer.' + // ); + + // showDeprecationNotes = false; + // } + + // return () => result; + // } + + // return result; + // }; + // }, [attachmentMiddleware, attachmentRenderer]); + const patchedAttachmentRenderer = useMemo(() => { if (attachmentRenderer) { console.warn( @@ -313,10 +355,11 @@ const Composer = ({ return attachmentRenderer; } - const renderer = applyMiddlewareForRenderer( + // Attachment renderer + return applyMiddleware( 'attachment', ...singleToArray(attachmentMiddleware), - () => () => ({ attachment }) => () => { + () => () => ({ attachment }) => { if (attachment) { throw new Error(`No renderer for attachment of type "${attachment.contentType}"`); } else { @@ -324,26 +367,6 @@ const Composer = ({ } } )({}); - - let showDeprecationNotes = true; - - return (...args) => { - const result = renderer(...args); - - if (isValidElement(result)) { - if (showDeprecationNotes) { - console.warn( - 'botframework-webchat: Please upgrade the attachment middleware with a new signature. For details, please see HOOKS.md#usecreateattachmentrenderer.' - ); - - showDeprecationNotes = false; - } - - return () => result; - } - - return result; - }; }, [attachmentMiddleware, attachmentRenderer]); const patchedAvatarRenderer = useMemo(() => { diff --git a/packages/api/src/hooks/internal/useCreateActivityRendererInternal.js b/packages/api/src/hooks/internal/useCreateActivityRendererInternal.js index 30e82db6d0..0a6ea49875 100644 --- a/packages/api/src/hooks/internal/useCreateActivityRendererInternal.js +++ b/packages/api/src/hooks/internal/useCreateActivityRendererInternal.js @@ -1,13 +1,13 @@ import { isValidElement, useMemo } from 'react'; -import useCreateAttachmentRenderer from '../useCreateAttachmentRenderer'; +import useRenderAttachment from '../useRenderAttachment'; import useWebChatAPIContext from './useWebChatAPIContext'; -export default function useCreateActivityRendererInternal(createAttachmentRendererOverride) { +export default function useCreateActivityRendererInternal(renderAttachmentOverride) { const { activityRenderer: createActivityRenderer } = useWebChatAPIContext(); - const defaultCreateAttachmentRenderer = useCreateAttachmentRenderer(); + const defaultRenderAttachment = useRenderAttachment(); - const createAttachmentRenderer = createAttachmentRendererOverride || defaultCreateAttachmentRenderer; + const renderAttachment = renderAttachmentOverride || defaultRenderAttachment; return useMemo( () => (...createActivityRendererOptions) => { @@ -22,15 +22,10 @@ export default function useCreateActivityRendererInternal(createAttachmentRender return renderActivity; } - const activityElement = renderActivity((...renderAttachmentArgs) => { - // Currently, the API signature for renderActivity is: - // renderActivity(({ activity, attachment }) => React.Element) - // We will bridge newer version of createAttachmentRenderer to the older API for now. - const result = createAttachmentRenderer(...renderAttachmentArgs); - - // return isValidElement(result) ? () => result : result; - return isValidElement(result) ? result : result(); - }, renderActivityOptions); + const activityElement = renderActivity( + (...renderAttachmentArgs) => renderAttachment(...renderAttachmentArgs), + renderActivityOptions + ); // "activityElement" cannot be false. If the middleware want to hide the "activityElement", it should return "false" when we call createActivityRenderer(). activityElement || @@ -41,6 +36,6 @@ export default function useCreateActivityRendererInternal(createAttachmentRender return activityElement; }; }, - [createActivityRenderer, createAttachmentRenderer] + [createActivityRenderer, renderAttachment] ); } diff --git a/packages/api/src/hooks/middleware/applyMiddleware.js b/packages/api/src/hooks/middleware/applyMiddleware.js index 2d1174dcea..97d90a588e 100644 --- a/packages/api/src/hooks/middleware/applyMiddleware.js +++ b/packages/api/src/hooks/middleware/applyMiddleware.js @@ -10,6 +10,7 @@ export default function applyMiddleware(type, ...middleware) { throw new Error(`reached terminator of ${type}`); }); } + export function forRenderer(type, ...middleware) { return (...setupArgs) => { const runMiddleware = concatMiddleware(...middleware)(...setupArgs)(() => ( diff --git a/packages/api/src/hooks/useCreateAttachmentRenderer.js b/packages/api/src/hooks/useCreateAttachmentRenderer.js deleted file mode 100644 index a0203179d1..0000000000 --- a/packages/api/src/hooks/useCreateAttachmentRenderer.js +++ /dev/null @@ -1,7 +0,0 @@ -import useWebChatAPIContext from './internal/useWebChatAPIContext'; - -export default function useCreateAttachmentRenderer() { - const { attachmentRenderer: createAttachmentRenderer } = useWebChatAPIContext(); - - return createAttachmentRenderer; -} diff --git a/packages/api/src/hooks/useRenderAttachment.js b/packages/api/src/hooks/useRenderAttachment.js index 41cbfcf606..74b70acf0e 100644 --- a/packages/api/src/hooks/useRenderAttachment.js +++ b/packages/api/src/hooks/useRenderAttachment.js @@ -1,23 +1,31 @@ -import { isValidElement } from 'react'; +// import { isValidElement } from 'react'; -import useCreateAttachmentRenderer from './useCreateAttachmentRenderer'; +// import useCreateAttachmentRenderer from './useCreateAttachmentRenderer'; -let showDeprecationNotes = true; +// let showDeprecationNotes = true; -export default function useRenderAttachment() { - if (showDeprecationNotes) { - console.warn( - 'botframework-webchat: "useRenderAttachment" is deprecated and will be removed on or after 2022-09-28. Please use "useCreateAttachmentRenderer()" instead.' - ); +// export default function useRenderAttachment() { +// if (showDeprecationNotes) { +// console.warn( +// 'botframework-webchat: "useRenderAttachment" is deprecated and will be removed on or after 2022-09-28. Please use "useCreateAttachmentRenderer()" instead.' +// ); + +// showDeprecationNotes = false; +// } + +// const createAttachmentRenderer = useCreateAttachmentRenderer(); - showDeprecationNotes = false; - } +// return (...renderArgs) => { +// const result = createAttachmentRenderer(...renderArgs); - const createAttachmentRenderer = useCreateAttachmentRenderer(); +// return !!result && (isValidElement(result) ? result : result()); +// }; +// } - return (...renderArgs) => { - const result = createAttachmentRenderer(...renderArgs); +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useRenderAttachment() { + const { attachmentRenderer } = useWebChatAPIContext(); - return !!result && isValidElement(result) ? result : result(); - }; + return attachmentRenderer; } diff --git a/packages/bundle/src/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.js b/packages/bundle/src/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.js index e8826bad0a..c14ed5580a 100644 --- a/packages/bundle/src/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.js +++ b/packages/bundle/src/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.js @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import React from 'react'; import AdaptiveCardAttachment from './Attachment/AdaptiveCardAttachment'; @@ -12,38 +11,29 @@ import ThumbnailCardAttachment from './Attachment/ThumbnailCardAttachment'; import VideoCardAttachment from './Attachment/VideoCardAttachment'; export default function createAdaptiveCardsAttachmentMiddleware() { - return () => next => { - function AdaptiveCardMiddleware({ activity, attachment }) { - return attachment.contentType === 'application/vnd.microsoft.card.hero' ? ( - - ) : attachment.contentType === 'application/vnd.microsoft.card.adaptive' ? ( - - ) : attachment.contentType === 'application/vnd.microsoft.card.animation' ? ( - - ) : attachment.contentType === 'application/vnd.microsoft.card.audio' ? ( - - ) : attachment.contentType === 'application/vnd.microsoft.card.oauth' ? ( - - ) : attachment.contentType === 'application/vnd.microsoft.card.receipt' ? ( - - ) : attachment.contentType === 'application/vnd.microsoft.card.signin' ? ( - - ) : attachment.contentType === 'application/vnd.microsoft.card.thumbnail' ? ( - - ) : attachment.contentType === 'application/vnd.microsoft.card.video' ? ( - - ) : ( - next({ activity, attachment }) - ); - } + return () => next => (...args) => { + const [{ activity, attachment }] = args; - AdaptiveCardMiddleware.propTypes = { - activity: PropTypes.any.isRequired, - attachment: PropTypes.shape({ - contentType: PropTypes.string.isRequired - }).isRequired - }; - - return AdaptiveCardMiddleware; + return attachment.contentType === 'application/vnd.microsoft.card.hero' ? ( + + ) : attachment.contentType === 'application/vnd.microsoft.card.adaptive' ? ( + + ) : attachment.contentType === 'application/vnd.microsoft.card.animation' ? ( + + ) : attachment.contentType === 'application/vnd.microsoft.card.audio' ? ( + + ) : attachment.contentType === 'application/vnd.microsoft.card.oauth' ? ( + + ) : attachment.contentType === 'application/vnd.microsoft.card.receipt' ? ( + + ) : attachment.contentType === 'application/vnd.microsoft.card.signin' ? ( + + ) : attachment.contentType === 'application/vnd.microsoft.card.thumbnail' ? ( + + ) : attachment.contentType === 'application/vnd.microsoft.card.video' ? ( + + ) : ( + next(...args) + ); }; } diff --git a/packages/component/src/Middleware/Attachment/createCoreMiddleware.js b/packages/component/src/Middleware/Attachment/createCoreMiddleware.js index 748b1a61b7..d2a5137568 100644 --- a/packages/component/src/Middleware/Attachment/createCoreMiddleware.js +++ b/packages/component/src/Middleware/Attachment/createCoreMiddleware.js @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import React from 'react'; import AudioAttachment from '../../Attachment/AudioAttachment'; @@ -10,42 +9,31 @@ import VideoAttachment from '../../Attachment/VideoAttachment'; // TODO: [P4] Rename this file or the whole middleware, it looks either too simple or too comprehensive now export default function createCoreMiddleware() { return [ - () => next => { - const Attachment = args => { - const { + () => next => (...args) => { + const [ + { activity = {}, activity: { from: { role } = {} } = {}, attachment, attachment: { contentType, contentUrl, thumbnailUrl } = {} - } = args; + } + ] = args; - return role === 'user' && !/^text\//u.test(contentType) && !thumbnailUrl ? ( - - ) : /^audio\//u.test(contentType) ? ( - - ) : /^image\//u.test(contentType) ? ( - - ) : /^video\//u.test(contentType) ? ( - - ) : contentUrl || contentType === 'application/octet-stream' ? ( - - ) : /^text\//u.test(contentType) ? ( - - ) : ( - next({ activity, attachment }) - ); - }; - - Attachment.propTypes = { - activity: PropTypes.any.isRequired, - attachment: PropTypes.shape({ - contentType: PropTypes.string.isRequired, - contentUrl: PropTypes.string, - thumbnailUrl: PropTypes.string - }).isRequired - }; - - return Attachment; + return role === 'user' && !/^text\//u.test(contentType) && !thumbnailUrl ? ( + + ) : /^audio\//u.test(contentType) ? ( + + ) : /^image\//u.test(contentType) ? ( + + ) : /^video\//u.test(contentType) ? ( + + ) : contentUrl || contentType === 'application/octet-stream' ? ( + + ) : /^text\//u.test(contentType) ? ( + + ) : ( + next(...args) + ); } ]; } From f47d9190601290097ad737263d334134d79e1415 Mon Sep 17 00:00:00 2001 From: William Wong Date: Thu, 15 Oct 2020 12:58:45 -0700 Subject: [PATCH 10/21] Fix ESLint --- packages/api/src/hooks/Composer.js | 18 +++++++----------- .../createAdaptiveCardsAttachmentMiddleware.js | 2 ++ .../Attachment/createCoreMiddleware.js | 2 ++ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/api/src/hooks/Composer.js b/packages/api/src/hooks/Composer.js index 3c15a4c735..224369d419 100644 --- a/packages/api/src/hooks/Composer.js +++ b/packages/api/src/hooks/Composer.js @@ -1,6 +1,6 @@ import { Provider } from 'react-redux'; import PropTypes from 'prop-types'; -import React, { isValidElement, useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import updateIn from 'simple-update-in'; import createCustomEvent from '../utils/createCustomEvent'; @@ -356,17 +356,13 @@ const Composer = ({ } // Attachment renderer - return applyMiddleware( - 'attachment', - ...singleToArray(attachmentMiddleware), - () => () => ({ attachment }) => { - if (attachment) { - throw new Error(`No renderer for attachment of type "${attachment.contentType}"`); - } else { - throw new Error('No attachment to render'); - } + return applyMiddleware('attachment', ...singleToArray(attachmentMiddleware), () => () => ({ attachment }) => { + if (attachment) { + throw new Error(`No renderer for attachment of type "${attachment.contentType}"`); + } else { + throw new Error('No attachment to render'); } - )({}); + })({}); }, [attachmentMiddleware, attachmentRenderer]); const patchedAvatarRenderer = useMemo(() => { diff --git a/packages/bundle/src/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.js b/packages/bundle/src/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.js index c14ed5580a..916c20a5f0 100644 --- a/packages/bundle/src/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.js +++ b/packages/bundle/src/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.js @@ -11,6 +11,8 @@ import ThumbnailCardAttachment from './Attachment/ThumbnailCardAttachment'; import VideoCardAttachment from './Attachment/VideoCardAttachment'; export default function createAdaptiveCardsAttachmentMiddleware() { + // This is not returning a React component, but a render function. + /* eslint-disable-next-line react/display-name */ return () => next => (...args) => { const [{ activity, attachment }] = args; diff --git a/packages/component/src/Middleware/Attachment/createCoreMiddleware.js b/packages/component/src/Middleware/Attachment/createCoreMiddleware.js index d2a5137568..7df54b5c19 100644 --- a/packages/component/src/Middleware/Attachment/createCoreMiddleware.js +++ b/packages/component/src/Middleware/Attachment/createCoreMiddleware.js @@ -9,6 +9,8 @@ import VideoAttachment from '../../Attachment/VideoAttachment'; // TODO: [P4] Rename this file or the whole middleware, it looks either too simple or too comprehensive now export default function createCoreMiddleware() { return [ + // This is not returning a React component, but a render function. + /* eslint-disable-next-line react/display-name */ () => next => (...args) => { const [ { From 20f4409d8a2b5c5318b725cfa5b99781378ddf8a Mon Sep 17 00:00:00 2001 From: William Wong Date: Thu, 15 Oct 2020 13:11:01 -0700 Subject: [PATCH 11/21] Fix all TODOs --- packages/api/src/defaultStyleOptions.js | 2 +- packages/api/src/hooks/internal/ErrorBox.js | 8 +++++-- .../src/hooks/middleware/UserlandBoundary.js | 21 ++++--------------- packages/component/src/Dictation.js | 2 +- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/packages/api/src/defaultStyleOptions.js b/packages/api/src/defaultStyleOptions.js index 63b1d36593..c90bba24be 100644 --- a/packages/api/src/defaultStyleOptions.js +++ b/packages/api/src/defaultStyleOptions.js @@ -163,7 +163,7 @@ const DEFAULT_OPTIONS = { spinnerAnimationWidth: 16, spinnerAnimationPadding: 12, - // TODO: [PXX] This is only supported on HTML. + // TODO: [P0] #3322 This is only supported on HTML. enableUploadThumbnail: true, uploadThumbnailContentType: 'image/jpeg', uploadThumbnailHeight: 360, diff --git a/packages/api/src/hooks/internal/ErrorBox.js b/packages/api/src/hooks/internal/ErrorBox.js index 726c3644e1..69d98ec578 100644 --- a/packages/api/src/hooks/internal/ErrorBox.js +++ b/packages/api/src/hooks/internal/ErrorBox.js @@ -4,8 +4,6 @@ import PropTypes from 'prop-types'; import useErrorBoxClass from './useErrorBoxClass'; import useTrackException from '../useTrackException'; -// TODO: [PXX] Check if this class is used. - const ErrorBox = ({ error, type }) => { const [errorBoxClass] = useErrorBoxClass(); const trackException = useTrackException(); @@ -14,6 +12,12 @@ const ErrorBox = ({ error, type }) => { trackException(error, false); }, [error, trackException]); + useEffect(() => { + console.group(`botframework-webchat: ${type}`); + console.error(error); + console.groupEnd(); + }, [error, type]); + return !!errorBoxClass && createElement(errorBoxClass, { error, type }); }; diff --git a/packages/api/src/hooks/middleware/UserlandBoundary.js b/packages/api/src/hooks/middleware/UserlandBoundary.js index 3a5b74cf4f..a7d44f21a2 100644 --- a/packages/api/src/hooks/middleware/UserlandBoundary.js +++ b/packages/api/src/hooks/middleware/UserlandBoundary.js @@ -1,29 +1,16 @@ import PropTypes from 'prop-types'; -import React, { createElement, useCallback, useState } from 'react'; +import React, { useCallback, useState } from 'react'; import ErrorBoundary from '../utils/ErrorBoundary'; -import useErrorBoxClass from '../internal/useErrorBoxClass'; -import useTrackException from '../useTrackException'; +import ErrorBox from '../internal/ErrorBox'; const UserlandBoundary = ({ children, type }) => { const [error, setError] = useState(); - const [errorBoxClass] = useErrorBoxClass(); - const trackException = useTrackException(); - const handleError = useCallback(error => { - setError(error); - - const errorObject = error || new Error(type); - - trackException(errorObject, false); - - console.group(`botframework-webchat: ${type}`); - console.error(errorObject); - console.groupEnd(); - }, [trackException]); + const handleError = useCallback(error => setError(error), []); return error ? ( - !!errorBoxClass && createElement(errorBoxClass, { error, type }) + ) : ( {children} ); diff --git a/packages/component/src/Dictation.js b/packages/component/src/Dictation.js index cd45cc7973..dffc34083c 100644 --- a/packages/component/src/Dictation.js +++ b/packages/component/src/Dictation.js @@ -7,7 +7,7 @@ import React, { useCallback, useMemo } from 'react'; import useSettableDictateAbortable from './hooks/internal/useSettableDictateAbortable'; import useWebSpeechPonyfill from './hooks/useWebSpeechPonyfill'; -// TODO: [PXX] No /lib/ +// TODO: [P1] #3350 No /lib/, we need to move setDictateState from bf-wc-core (Redux) to React Context. import useSetDictateState from 'botframework-webchat-api/lib/hooks/internal/useSetDictateState'; const { From b9127af74b03acdcbd2deef8bb317a4518f8c747 Mon Sep 17 00:00:00 2001 From: William Wong Date: Thu, 15 Oct 2020 14:09:11 -0700 Subject: [PATCH 12/21] Add back localize --- ...lize-should-localize-text-in-en-1-snap.png | Bin 0 -> 3843 bytes ...lize-text-in-navigator-language-1-snap.png | Bin 0 -> 3843 bytes ...ize-should-localize-text-in-yue-1-snap.png | Bin 0 -> 6103 bytes __tests__/html/deprecated.localize.html | 51 ++++++++++++++++++ __tests__/html/deprecated.localize.js | 9 ++++ packages/api/src/index.ts | 3 +- packages/component/src/index.tsx | 7 ++- 7 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 __tests__/__image_snapshots__/html/deprecated-localize-js-deprecated-localize-should-localize-text-in-en-1-snap.png create mode 100644 __tests__/__image_snapshots__/html/deprecated-localize-js-deprecated-localize-should-localize-text-in-navigator-language-1-snap.png create mode 100644 __tests__/__image_snapshots__/html/deprecated-localize-js-deprecated-localize-should-localize-text-in-yue-1-snap.png create mode 100644 __tests__/html/deprecated.localize.html create mode 100644 __tests__/html/deprecated.localize.js diff --git a/__tests__/__image_snapshots__/html/deprecated-localize-js-deprecated-localize-should-localize-text-in-en-1-snap.png b/__tests__/__image_snapshots__/html/deprecated-localize-js-deprecated-localize-should-localize-text-in-en-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..8f6964e75dead68402de3ac53386f81290f1a96d GIT binary patch literal 3843 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 + + + + + + +
+ + + diff --git a/__tests__/html/deprecated.localize.js b/__tests__/html/deprecated.localize.js new file mode 100644 index 0000000000..8ab1fc0309 --- /dev/null +++ b/__tests__/html/deprecated.localize.js @@ -0,0 +1,9 @@ +/** + * @jest-environment ./__tests__/html/__jest__/WebChatEnvironment.js + */ + +describe('deprecated ', () => { + test('should localize text in navigator language', () => runHTMLTest('deprecated.localize.html')); + test('should localize text in "en"', () => runHTMLTest('deprecated.localize.html#l=en')); + test('should localize text in "yue"', () => runHTMLTest('deprecated.localize.html#l=yue')); +}); diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index 3812cb9197..77edad8ea7 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -1,4 +1,5 @@ import * as hooks from './hooks'; import Composer from './hooks/Composer'; +import Localize, { localize } from './localization/Localize'; -export { Composer, hooks }; +export { Composer, hooks, Localize, localize }; diff --git a/packages/component/src/index.tsx b/packages/component/src/index.tsx index be17cdfe7d..702142a5c7 100644 --- a/packages/component/src/index.tsx +++ b/packages/component/src/index.tsx @@ -7,7 +7,6 @@ import BasicWebChat from './BasicWebChat'; import Avatar from './Activity/Avatar'; import Bubble from './Activity/Bubble'; import ErrorBox from './ErrorBox'; -// import Localize, { localize } from './Localization/Localize'; import SendStatus, { connectSendStatus } from './Middleware/ActivityStatus/SendStatus/SendStatus'; import SpeakActivity, { connectSpeakActivity } from './Activity/Speak'; import Timestamp from './Middleware/ActivityStatus/Timestamp'; @@ -39,7 +38,7 @@ import defaultStyleOptions from './Styles/defaultStyleOptions'; import getTabIndex from './Utils/TypeFocusSink/getTabIndex'; // TODO: Add deprecation notes when someone is using hooks from bf-wc-component, instead of bf-wc-core. -import { hooks as apiHooks } from 'botframework-webchat-api'; +import { hooks as apiHooks, Localize, localize } from 'botframework-webchat-api'; import * as componentHooks from './hooks/index'; const hooks = { @@ -52,7 +51,7 @@ const version = process.env.npm_package_version; const Components = { BasicWebChat, Composer, - // Localize, + Localize, // Components for recomposing activities and attachments AudioContent, @@ -105,6 +104,6 @@ export { defaultStyleOptions, getTabIndex, hooks, - // localize, + localize, version }; From c301e362f0554774ad74365d69a1561dfb9aaeff Mon Sep 17 00:00:00 2001 From: William Wong Date: Thu, 15 Oct 2020 14:52:57 -0700 Subject: [PATCH 13/21] Clean up --- ...-broken-card-of-invalid-version-1-snap.png | Bin 0 -> 42453 bytes .../upload-js-upload-a-picture-2-snap.png | Bin 0 -> 162626 bytes ...chment-should-render-attachment-1-snap.png | Bin 0 -> 80197 bytes __tests__/adaptiveCards.js | 13 +++ __tests__/html/hooks.useRenderAttachment.html | 1 + __tests__/html/hooks.useRenderAttachment.js | 7 ++ __tests__/upload.js | 96 ++++++++++++++++++ docs/HOOKS.md | 10 +- .../middleware}/concatMiddleware.spec.js | 0 .../middleware/createErrorBoundaryRenderer.js | 12 --- packages/api/src/hooks/useRenderAttachment.js | 24 ----- packages/api/src/index.ts | 3 +- packages/component/src/ErrorBox.js | 2 +- .../Activity/createCoreMiddleware.js | 2 - .../src/Middleware/concatMiddleware.js | 16 --- .../src/Middleware/createActivityRenderer.js | 45 -------- .../createActivityStatusRenderer.js | 26 ----- .../src/Middleware/createAvatarRenderer.js | 26 ----- .../src/Middleware/createToastRenderer.js | 30 ------ .../createTypingIndicatorRenderer.js | 30 ------ packages/component/src/connectToWebChat.js | 3 +- packages/component/src/hooks/index.js | 1 + packages/component/src/index.tsx | 4 +- 23 files changed, 131 insertions(+), 220 deletions(-) create mode 100644 __tests__/__image_snapshots__/chrome-docker/adaptive-cards-js-broken-card-of-invalid-version-1-snap.png create mode 100644 __tests__/__image_snapshots__/chrome-docker/upload-js-upload-a-picture-2-snap.png create mode 100644 __tests__/__image_snapshots__/html/hooks-use-render-attachment-js-use-render-attachment-should-render-attachment-1-snap.png create mode 100644 __tests__/html/hooks.useRenderAttachment.js rename packages/{component/src/Middleware => api/src/hooks/middleware}/concatMiddleware.spec.js (100%) delete mode 100644 packages/api/src/hooks/middleware/createErrorBoundaryRenderer.js delete mode 100644 packages/component/src/Middleware/concatMiddleware.js delete mode 100644 packages/component/src/Middleware/createActivityRenderer.js delete mode 100644 packages/component/src/Middleware/createActivityStatusRenderer.js delete mode 100644 packages/component/src/Middleware/createAvatarRenderer.js delete mode 100644 packages/component/src/Middleware/createToastRenderer.js delete mode 100644 packages/component/src/Middleware/createTypingIndicatorRenderer.js diff --git a/__tests__/__image_snapshots__/chrome-docker/adaptive-cards-js-broken-card-of-invalid-version-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/adaptive-cards-js-broken-card-of-invalid-version-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..90c3bb78622d43ca7b061f27cdb90adf538878b9 GIT binary patch literal 42453 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 z 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 n*U}WLz#YnbOa$(K)k#qICG%{Ee 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

T^6}if4AU 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 literal 0 HcmV?d00001 diff --git a/__tests__/adaptiveCards.js b/__tests__/adaptiveCards.js index c218ac51ee..dcc23b3002 100644 --- a/__tests__/adaptiveCards.js +++ b/__tests__/adaptiveCards.js @@ -139,3 +139,16 @@ test('disable card inputs', async () => { expect(await driver.takeScreenshot()).toMatchImageSnapshot(imageSnapshotOptions); }); + +test('broken card of invalid version', async () => { + const { driver, pageObjects } = await setupWebDriver(); + + await driver.wait(uiConnected(), timeouts.directLine); + await pageObjects.sendMessageViaSendBox('card broken', { waitForSend: true }); + + await driver.wait(minNumActivitiesShown(2), timeouts.directLine); + + const base64PNG = await driver.takeScreenshot(); + + expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions); +}); diff --git a/__tests__/html/hooks.useRenderAttachment.html b/__tests__/html/hooks.useRenderAttachment.html index e5255e7ec5..401092e683 100644 --- a/__tests__/html/hooks.useRenderAttachment.html +++ b/__tests__/html/hooks.useRenderAttachment.html @@ -63,6 +63,7 @@ await pageObjects.wait(conditions.uiConnected(), timeouts.directLine); await pageObjects.wait(() => document.querySelector('.done'), timeouts.ui); + await pageObjects.wait(conditions.allImagesLoaded(), timeouts.ui); await host.snapshot(); await host.done(); diff --git a/__tests__/html/hooks.useRenderAttachment.js b/__tests__/html/hooks.useRenderAttachment.js new file mode 100644 index 0000000000..630faa8bb2 --- /dev/null +++ b/__tests__/html/hooks.useRenderAttachment.js @@ -0,0 +1,7 @@ +/** + * @jest-environment ./__tests__/html/__jest__/WebChatEnvironment.js + */ + +describe('useRenderAttachment', () => { + test('should render attachment', () => runHTMLTest('hooks.useRenderAttachment.html')); +}); diff --git a/__tests__/upload.js b/__tests__/upload.js index 30f4c6942a..eff95cb6d3 100644 --- a/__tests__/upload.js +++ b/__tests__/upload.js @@ -12,6 +12,22 @@ jest.setTimeout(timeouts.test); describe('upload a picture', () => { test('', async () => { const { driver, pageObjects } = await setupWebDriver({ + props: { + onTelemetry: event => { + const { data, dimensions, duration, error, fatal, name, type, value } = event; + + (window.WebChatTest.telemetryMeasurements || (window.WebChatTest.telemetryMeasurements = [])).push({ + data, + dimensions, + duration, + error, + fatal, + name, + type, + value + }); + } + }, // TODO: [P3] Offline bot did not reply with a downloadable attachment, we need to use production bot useProductionBot: true }); @@ -22,6 +38,86 @@ describe('upload a picture', () => { await driver.wait(minNumActivitiesShown(2), timeouts.directLine); await driver.wait(allImagesLoaded(), timeouts.fetchImage); + const telemetryMeasurements = await driver.executeScript(() => window.WebChatTest.telemetryMeasurements); + + expect(telemetryMeasurements).toHaveProperty('length', 4); + expect(telemetryMeasurements[2]).toHaveProperty('name', 'sendFiles:makeThumbnail'); + expect(telemetryMeasurements[2]).toHaveProperty('type', 'timingend'); + + telemetryMeasurements[2].duration = 1000; + + expect(telemetryMeasurements).toMatchInlineSnapshot(` + Array [ + Object { + "data": null, + "dimensions": Object { + "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", + "prop:locale": "en-US", + "prop:speechRecognition": "false", + "prop:speechSynthesis": "false", + }, + "duration": null, + "error": null, + "fatal": null, + "name": "init", + "type": "event", + "value": null, + }, + Object { + "data": null, + "dimensions": Object { + "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", + "prop:locale": "en-US", + "prop:speechRecognition": "false", + "prop:speechSynthesis": "false", + }, + "duration": null, + "error": null, + "fatal": null, + "name": "sendFiles:makeThumbnail", + "type": "timingstart", + "value": null, + }, + Object { + "data": null, + "dimensions": Object { + "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", + "prop:locale": "en-US", + "prop:speechRecognition": "false", + "prop:speechSynthesis": "false", + }, + "duration": 1000, + "error": null, + "fatal": null, + "name": "sendFiles:makeThumbnail", + "type": "timingend", + "value": null, + }, + Object { + "data": Object { + "numFiles": 1, + "sumSizeInKB": 379, + }, + "dimensions": Object { + "capability:downscaleImage:workerType": "web worker", + "capability:renderer": "html", + "prop:locale": "en-US", + "prop:speechRecognition": "false", + "prop:speechSynthesis": "false", + }, + "duration": null, + "error": null, + "fatal": null, + "name": "sendFiles", + "type": "event", + "value": null, + }, + ] + `); + const base64PNG = await driver.takeScreenshot(); expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions); diff --git a/docs/HOOKS.md b/docs/HOOKS.md index 77c02c0d64..19a607c9e4 100644 --- a/docs/HOOKS.md +++ b/docs/HOOKS.md @@ -315,7 +315,7 @@ useCreateAttachmentForScreenReaderRenderer(): ({ This hook will return a function that, when called with activity and attachment, will either return a function to render the attachment used by screen reader, or `false` if the attachment should not be rendered. -## `useCreateAttachmentRenderer`` +## `useCreateAttachmentRenderer` ```js @@ -383,7 +383,13 @@ For the debounce behavior, please read our [article regarding notification syste ## `useDictateAbortable` -(TODO: TBD) + +```js +useDictateAbortable(): [boolean] +``` + + +When called, this hook will return `true` if current dictation is abortable, otherwise, `false`. ## `useDictateInterims` diff --git a/packages/component/src/Middleware/concatMiddleware.spec.js b/packages/api/src/hooks/middleware/concatMiddleware.spec.js similarity index 100% rename from packages/component/src/Middleware/concatMiddleware.spec.js rename to packages/api/src/hooks/middleware/concatMiddleware.spec.js diff --git a/packages/api/src/hooks/middleware/createErrorBoundaryRenderer.js b/packages/api/src/hooks/middleware/createErrorBoundaryRenderer.js deleted file mode 100644 index a91464324c..0000000000 --- a/packages/api/src/hooks/middleware/createErrorBoundaryRenderer.js +++ /dev/null @@ -1,12 +0,0 @@ -export default function createErrorBoundaryRenderer(...errorBoundaryMiddleware) { - const render = concatMiddleware(...errorBoundaryMiddleware)({}); - - return (...args) => - render(({ error, type }) => { - console.warn(`botframework-webchat: Failed to "${type}".`, error); - - return false; - })( - ...args - ); -} diff --git a/packages/api/src/hooks/useRenderAttachment.js b/packages/api/src/hooks/useRenderAttachment.js index 74b70acf0e..7179f64970 100644 --- a/packages/api/src/hooks/useRenderAttachment.js +++ b/packages/api/src/hooks/useRenderAttachment.js @@ -1,27 +1,3 @@ -// import { isValidElement } from 'react'; - -// import useCreateAttachmentRenderer from './useCreateAttachmentRenderer'; - -// let showDeprecationNotes = true; - -// export default function useRenderAttachment() { -// if (showDeprecationNotes) { -// console.warn( -// 'botframework-webchat: "useRenderAttachment" is deprecated and will be removed on or after 2022-09-28. Please use "useCreateAttachmentRenderer()" instead.' -// ); - -// showDeprecationNotes = false; -// } - -// const createAttachmentRenderer = useCreateAttachmentRenderer(); - -// return (...renderArgs) => { -// const result = createAttachmentRenderer(...renderArgs); - -// return !!result && (isValidElement(result) ? result : result()); -// }; -// } - import useWebChatAPIContext from './internal/useWebChatAPIContext'; export default function useRenderAttachment() { diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index 77edad8ea7..501e2d5659 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -1,5 +1,6 @@ import * as hooks from './hooks'; import Composer from './hooks/Composer'; +import concatMiddleware from './hooks/middleware/concatMiddleware'; import Localize, { localize } from './localization/Localize'; -export { Composer, hooks, Localize, localize }; +export { Composer, concatMiddleware, hooks, Localize, localize }; diff --git a/packages/component/src/ErrorBox.js b/packages/component/src/ErrorBox.js index 0dbac22054..89f623b698 100644 --- a/packages/component/src/ErrorBox.js +++ b/packages/component/src/ErrorBox.js @@ -18,7 +18,7 @@ const ErrorBox = ({ error, type }) => {

); diff --git a/packages/component/src/Middleware/Activity/createCoreMiddleware.js b/packages/component/src/Middleware/Activity/createCoreMiddleware.js index 538cca9e19..63b6eee3c4 100644 --- a/packages/component/src/Middleware/Activity/createCoreMiddleware.js +++ b/packages/component/src/Middleware/Activity/createCoreMiddleware.js @@ -8,8 +8,6 @@ export default function createCoreMiddleware() { () => next => (...args) => { const [{ activity }] = args; - // console.log('defaultActivity', { activity, args }); - // TODO: [P4] Can we simplify these if-statement to something more readable? const { type } = activity; diff --git a/packages/component/src/Middleware/concatMiddleware.js b/packages/component/src/Middleware/concatMiddleware.js deleted file mode 100644 index c5c89ca1f9..0000000000 --- a/packages/component/src/Middleware/concatMiddleware.js +++ /dev/null @@ -1,16 +0,0 @@ -export default function concatMiddleware(...middlewares) { - return options => { - const setup = middlewares.reduce((setup, middleware) => (middleware ? [...setup, middleware(options)] : setup), []); - - return last => { - const stack = setup.slice(); - const work = index => (...args) => { - const next = stack[index]; - - return (next ? next(work(index + 1)) : last)(...args); - }; - - return work(0); - }; - }; -} diff --git a/packages/component/src/Middleware/createActivityRenderer.js b/packages/component/src/Middleware/createActivityRenderer.js deleted file mode 100644 index 311edff4c4..0000000000 --- a/packages/component/src/Middleware/createActivityRenderer.js +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint no-magic-numbers: ["error", { "ignore": [2] }] */ - -import { hooks } from 'botframework-webchat-api'; -import React, { useEffect } from 'react'; -import PropTypes from 'prop-types'; - -import concatMiddleware from './concatMiddleware'; -import createCoreActivityMiddleware from './Activity/createCoreMiddleware'; -import ErrorBox from '../ErrorBox'; - -const { useTrackException } = hooks; - -const SilentError = ({ message }) => { - const trackException = useTrackException(); - - useEffect(() => { - trackException(new Error(message), false); - }, [message, trackException]); - - return false; -}; - -SilentError.propTypes = { - message: PropTypes.string.isRequired -}; - -export default function createActivityRenderer(additionalMiddleware) { - const activityMiddleware = concatMiddleware(additionalMiddleware, createCoreActivityMiddleware())({}); - - return (...args) => { - try { - return activityMiddleware(({ activity }) => () => ( - - ))(...args); - } catch (err) { - const FailedRenderActivity = () => ( - -
{JSON.stringify(err, null, 2)}
-
- ); - - return FailedRenderActivity; - } - }; -} diff --git a/packages/component/src/Middleware/createActivityStatusRenderer.js b/packages/component/src/Middleware/createActivityStatusRenderer.js deleted file mode 100644 index fa9dad9fdc..0000000000 --- a/packages/component/src/Middleware/createActivityStatusRenderer.js +++ /dev/null @@ -1,26 +0,0 @@ -/* eslint no-magic-numbers: ["error", { "ignore": [2] }] */ - -import React from 'react'; -import concatMiddleware from './concatMiddleware'; -import createCoreActivityStatusMiddleware from './ActivityStatus/createCoreMiddleware'; -import ErrorBox from '../ErrorBox'; - -export default function createActivityStatusRenderer(additionalMiddleware) { - const activityStatusMiddleware = concatMiddleware(additionalMiddleware, createCoreActivityStatusMiddleware())({}); - - return (...args) => { - try { - return activityStatusMiddleware(() => false)(...args); - } catch (err) { - const { message, stack } = err; - - // The next line is not a React component. It is a render function. - // eslint-disable-next-line react/display-name - return () => ( - -
{JSON.stringify({ message, stack }, null, 2)}
-
- ); - } - }; -} diff --git a/packages/component/src/Middleware/createAvatarRenderer.js b/packages/component/src/Middleware/createAvatarRenderer.js deleted file mode 100644 index 8f2b3d0529..0000000000 --- a/packages/component/src/Middleware/createAvatarRenderer.js +++ /dev/null @@ -1,26 +0,0 @@ -/* eslint no-magic-numbers: ["error", { "ignore": [2] }] */ - -import React from 'react'; -import concatMiddleware from './concatMiddleware'; -import createCoreAvatarMiddleware from './Avatar/createCoreMiddleware'; -import ErrorBox from '../ErrorBox'; - -export default function createAvatarRenderer(additionalMiddleware) { - const avatarMiddleware = concatMiddleware(additionalMiddleware, createCoreAvatarMiddleware())({}); - - return (...args) => { - try { - return avatarMiddleware(() => false)(...args); - } catch (err) { - const { message, stack } = err; - - console.error({ message, stack }); - - return ( - -
{JSON.stringify({ message, stack }, null, 2)}
-
- ); - } - }; -} diff --git a/packages/component/src/Middleware/createToastRenderer.js b/packages/component/src/Middleware/createToastRenderer.js deleted file mode 100644 index f69e78c50a..0000000000 --- a/packages/component/src/Middleware/createToastRenderer.js +++ /dev/null @@ -1,30 +0,0 @@ -/* eslint no-magic-numbers: ["error", { "ignore": [2] }] */ - -import React from 'react'; -import concatMiddleware from './concatMiddleware'; -import createCoreToastMiddleware from './Toast/createCoreMiddleware'; -import ErrorBox from '../ErrorBox'; - -export default function createToastRenderer(additionalMiddleware) { - const toastMiddleware = concatMiddleware(additionalMiddleware, createCoreToastMiddleware())({}); - - return (...args) => { - try { - return toastMiddleware(({ notification }) => ( - -
{JSON.stringify(notification, null, 2)}
-
- ))(...args); - } catch (err) { - const { message, stack } = err; - - console.error({ message, stack }); - - return ( - -
{JSON.stringify({ message, stack }, null, 2)}
-
- ); - } - }; -} diff --git a/packages/component/src/Middleware/createTypingIndicatorRenderer.js b/packages/component/src/Middleware/createTypingIndicatorRenderer.js deleted file mode 100644 index bc40ed3b77..0000000000 --- a/packages/component/src/Middleware/createTypingIndicatorRenderer.js +++ /dev/null @@ -1,30 +0,0 @@ -/* eslint no-magic-numbers: ["error", { "ignore": [2] }] */ - -import React from 'react'; -import concatMiddleware from './concatMiddleware'; -import createCoreTypingIndicatorMiddleware from './TypingIndicator/createCoreMiddleware'; -import ErrorBox from '../ErrorBox'; - -export default function createTypingIndicatorRenderer(additionalMiddleware) { - const typingIndicatorMiddleware = concatMiddleware(additionalMiddleware, createCoreTypingIndicatorMiddleware())({}); - - return (...args) => { - try { - return typingIndicatorMiddleware(({ activeTyping, typing, visible }) => ( - -
{JSON.stringify({ activeTyping, typing, visible }, null, 2)}
-
- ))(...args); - } catch (err) { - const { message, stack } = err; - - console.error({ message, stack }); - - return ( - -
{JSON.stringify({ message, stack }, null, 2)}
-
- ); - } - }; -} diff --git a/packages/component/src/connectToWebChat.js b/packages/component/src/connectToWebChat.js index 58210d5516..6e32ad3afc 100644 --- a/packages/component/src/connectToWebChat.js +++ b/packages/component/src/connectToWebChat.js @@ -1,9 +1,8 @@ import { connect } from 'react-redux'; import React from 'react'; -// TODO: Think about if we should also include WebChatUIContext. -import WebChatReduxContext from 'botframework-webchat-api/lib/hooks/internal/WebChatReduxContext'; import WebChatAPIContext from 'botframework-webchat-api/lib/hooks/internal/WebChatAPIContext'; +import WebChatReduxContext from 'botframework-webchat-api/lib/hooks/internal/WebChatReduxContext'; function removeUndefinedValues(map) { return Object.keys(map).reduce((result, key) => { diff --git a/packages/component/src/hooks/index.js b/packages/component/src/hooks/index.js index 2caa6486c9..bebd2a87cb 100644 --- a/packages/component/src/hooks/index.js +++ b/packages/component/src/hooks/index.js @@ -25,6 +25,7 @@ export { useScrollTo, useScrollToEnd, useSendBoxSpeechInterimsVisible, + // We are overwriting the `useSendFiles` hook from bf-wc-api and adding thumbnailing support. useSendFiles, useStyleSet, useTextBoxSubmit, diff --git a/packages/component/src/index.tsx b/packages/component/src/index.tsx index 702142a5c7..36f4848890 100644 --- a/packages/component/src/index.tsx +++ b/packages/component/src/index.tsx @@ -27,7 +27,6 @@ import SendTextBox, { connectSendTextBox } from './SendBox/TextBox'; import SuggestedActions, { connectSuggestedActions } from './SendBox/SuggestedActions'; import UploadButton, { connectUploadButton } from './SendBox/UploadButton'; -import concatMiddleware from './Middleware/concatMiddleware'; import connectToWebChat from './connectToWebChat'; import Context from './hooks/internal/WebChatUIContext'; import createCoreActivityMiddleware from './Middleware/Activity/createCoreMiddleware'; @@ -37,8 +36,7 @@ import createStyleSet from './Styles/createStyleSet'; import defaultStyleOptions from './Styles/defaultStyleOptions'; import getTabIndex from './Utils/TypeFocusSink/getTabIndex'; -// TODO: Add deprecation notes when someone is using hooks from bf-wc-component, instead of bf-wc-core. -import { hooks as apiHooks, Localize, localize } from 'botframework-webchat-api'; +import { concatMiddleware, hooks as apiHooks, Localize, localize } from 'botframework-webchat-api'; import * as componentHooks from './hooks/index'; const hooks = { From ab145f921f17fb8582c1ac86796fc45632c4725d Mon Sep 17 00:00:00 2001 From: William Wong Date: Thu, 15 Oct 2020 15:25:21 -0700 Subject: [PATCH 14/21] Add entry --- CHANGELOG.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79e475d13c..8dd5d2f8c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,8 +24,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Breaking changes -- Specific hooks are only available when using HTML version of Web Chat -- `activityMiddleware`, `attachmentMiddleware`, etc, now support passing in an array for multiple middleware +### Added + +- Resolves [#3316](https://github.com/microsoft/BotFramework-WebChat/issues/3316). Refactored platform-neutral APIs into the new `api` package, to be reused on React Native component, in PR [#3543](https://github.com/microsoft/BotFramework-WebChat/pull/3543) by [@compulim](https://github.com/compulim) + - The new layering is `core` -> `api` -> `component` (HTML-only) -> `bundle` + - Includes composition mode, platform-neutral React hooks, and localization resources + - Most hooks are available in the new `api` package. Some hooks are only available on the existing `component` package, due to their platform dependency or coupling with visual components. For example, Web Worker, 2D canvas, `useMicrophoneButton*` are not available on the `api` package + - Most implementation of middleware are only available on `component` package due to their coupling with visual components or platform features. Some implementations, such as, card action middleware and activity grouping middleware, are available on `api` package. For example: + - Carousel layout and stacked layout is only available on `component` package due to their coupling with their respective visual components + - For card action middleware, `imBack`, `messageBack` and `postBack` actions are available on `api` package, but `call`, `openUrl` and other platform-dependent actions are only available on `component` package + - `activityMiddleware`, `attachmentMiddleware`, etc, now support array for multiple middleware ### Fixed From bd57a2f801b9b0654b03ec630186f984e5534cc4 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 26 Oct 2020 12:48:11 -0700 Subject: [PATCH 15/21] Apply suggestions from code review Co-authored-by: Corina <14900841+corinagum@users.noreply.github.com> --- CHANGELOG.md | 4 ++-- docs/HOOKS.md | 2 +- packages/api/src/utils/mapMap.spec.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dd5d2f8c1..9382762a95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,10 +30,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - The new layering is `core` -> `api` -> `component` (HTML-only) -> `bundle` - Includes composition mode, platform-neutral React hooks, and localization resources - Most hooks are available in the new `api` package. Some hooks are only available on the existing `component` package, due to their platform dependency or coupling with visual components. For example, Web Worker, 2D canvas, `useMicrophoneButton*` are not available on the `api` package - - Most implementation of middleware are only available on `component` package due to their coupling with visual components or platform features. Some implementations, such as, card action middleware and activity grouping middleware, are available on `api` package. For example: + - Most implementations of middleware are only available in `component` package due to their coupling with visual components or platform features. Some implementations, (e.g. card action middleware and activity grouping middleware) are available on `api` package. For example: - Carousel layout and stacked layout is only available on `component` package due to their coupling with their respective visual components - For card action middleware, `imBack`, `messageBack` and `postBack` actions are available on `api` package, but `call`, `openUrl` and other platform-dependent actions are only available on `component` package - - `activityMiddleware`, `attachmentMiddleware`, etc, now support array for multiple middleware + - `activityMiddleware`, `attachmentMiddleware`, etc, now support arrays for multiple middleware ### Fixed diff --git a/docs/HOOKS.md b/docs/HOOKS.md index 19a607c9e4..559898835e 100644 --- a/docs/HOOKS.md +++ b/docs/HOOKS.md @@ -389,7 +389,7 @@ useDictateAbortable(): [boolean] ``` -When called, this hook will return `true` if current dictation is abortable, otherwise, `false`. +When called, this hook will return `true` if the current dictation is abortable, otherwise, `false`. ## `useDictateInterims` diff --git a/packages/api/src/utils/mapMap.spec.js b/packages/api/src/utils/mapMap.spec.js index 9132e2ce93..4ce08e6211 100644 --- a/packages/api/src/utils/mapMap.spec.js +++ b/packages/api/src/utils/mapMap.spec.js @@ -1,6 +1,6 @@ import mapMap from './mapMap'; -test('multiple a map by 10', () => { +test('multiply a map by 10', () => { const map = { ten: 1, twenty: 2 }; const actual = mapMap(map, value => value * 10); From 9948953ac2063f7b47de2e4ddc9b9a7c2f75860c Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 26 Oct 2020 12:50:29 -0700 Subject: [PATCH 16/21] Apply PR suggestions --- packages/component/src/Attachment/VideoAttachment.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/component/src/Attachment/VideoAttachment.js b/packages/component/src/Attachment/VideoAttachment.js index a3873c84cc..bfce5249ab 100644 --- a/packages/component/src/Attachment/VideoAttachment.js +++ b/packages/component/src/Attachment/VideoAttachment.js @@ -2,9 +2,9 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; -import VideoContent from './VideoContent'; import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; +import VideoContent from './VideoContent'; const ROOT_STYLE = { display: 'flex', From 438de1699ef5c891ce966831e37a955a860346b4 Mon Sep 17 00:00:00 2001 From: William Wong Date: Tue, 27 Oct 2020 03:59:33 -0700 Subject: [PATCH 17/21] Fix tests --- __tests__/cardActionMiddleware.js | 6 +- ...rning.returnRenderFunctionReturnFalse.html | 4 +- packages/api/src/hooks/Composer.js | 114 ++- packages/api/src/hooks/index.js | 2 - .../src/hooks/middleware/applyMiddleware.js | 24 +- .../middleware/createActivityRenderer.js | 6 - .../createActivityStatusRenderer.js | 6 - .../middleware/createAttachmentRenderer.js | 12 - .../hooks/middleware/createAvatarRenderer.js | 6 - .../hooks/middleware/createToastRenderer.js | 12 - .../createTypingIndicatorRenderer.js | 8 - ...CreateAttachmentForScreenReaderRenderer.js | 5 + .../Attachment/HeroCardAttachment.js | 2 +- .../Attachment/HeroCardContent.js | 2 +- packages/component/package-lock.json | 871 ++++-------------- packages/component/package.json | 4 + packages/component/src/Composer.js | 15 + .../AudioAttachment.js | 3 +- .../FileAttachment.js | 3 +- .../ImageAttachment.js | 3 +- .../TextAttachment.js | 3 +- .../VideoAttachment.js | 3 +- .../createCoreMiddleware.js | 42 +- ...pplyAttachmentForScreenReaderMiddleware.js | 25 - ...CreateAttachmentForScreenReaderRenderer.js | 5 - 25 files changed, 341 insertions(+), 845 deletions(-) delete mode 100644 packages/api/src/hooks/middleware/createActivityRenderer.js delete mode 100644 packages/api/src/hooks/middleware/createActivityStatusRenderer.js delete mode 100644 packages/api/src/hooks/middleware/createAttachmentRenderer.js delete mode 100644 packages/api/src/hooks/middleware/createAvatarRenderer.js delete mode 100644 packages/api/src/hooks/middleware/createToastRenderer.js delete mode 100644 packages/api/src/hooks/middleware/createTypingIndicatorRenderer.js create mode 100644 packages/api/src/hooks/useCreateAttachmentForScreenReaderRenderer.js delete mode 100644 packages/component/src/Middleware/applyAttachmentForScreenReaderMiddleware.js delete mode 100644 packages/component/src/hooks/useCreateAttachmentForScreenReaderRenderer.js diff --git a/__tests__/cardActionMiddleware.js b/__tests__/cardActionMiddleware.js index 1b13ab33b6..253359c2e6 100644 --- a/__tests__/cardActionMiddleware.js +++ b/__tests__/cardActionMiddleware.js @@ -1,4 +1,4 @@ -import { By } from 'selenium-webdriver'; +import { By, logging } from 'selenium-webdriver'; import { imageSnapshotOptions, timeouts } from './constants.json'; @@ -98,7 +98,7 @@ test('card action "signin" when directLine.getSessionId is falsy', async () => { props: { cardActionMiddleware: ({ dispatch }) => next => ({ cardAction, getSignInUrl }) => { if (cardAction.type === 'signin') { - getSignInUrl().then(url => { + Promise.resolve(getSignInUrl()).then(url => { dispatch({ type: 'WEB_CHAT/SEND_MESSAGE', payload: { @@ -138,6 +138,6 @@ test('card action "signin" when directLine.getSessionId is falsy', async () => { expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions); expect(await pageObjects.getConsoleErrors()).toEqual([]); expect(await pageObjects.getConsoleWarnings()).toEqual([ - 'botframework-webchat: No-magic-code OAuth flow is not supported on this Direct Line adapter.' + 'botframework-webchat: OAuth is not supported on this Direct Line adapter.' ]); }); diff --git a/__tests__/html/middleware.liveRegionAttachment.warning.returnRenderFunctionReturnFalse.html b/__tests__/html/middleware.liveRegionAttachment.warning.returnRenderFunctionReturnFalse.html index 5c2a1dae36..d6e12b266c 100644 --- a/__tests__/html/middleware.liveRegionAttachment.warning.returnRenderFunctionReturnFalse.html +++ b/__tests__/html/middleware.liveRegionAttachment.warning.returnRenderFunctionReturnFalse.html @@ -21,9 +21,7 @@ const RenderAttachmentForScreenReader = () => { const createAttachmentForScreenReaderRenderer = useCreateAttachmentForScreenReaderRenderer(); - createAttachmentForScreenReaderRenderer({ activity: {}, attachment: {} })(); - - return false; + return createAttachmentForScreenReaderRenderer({ activity: {}, attachment: {} })(); }; const attachmentForScreenReaderMiddleware = () => next => (...args) => { diff --git a/packages/api/src/hooks/Composer.js b/packages/api/src/hooks/Composer.js index 224369d419..40c6870834 100644 --- a/packages/api/src/hooks/Composer.js +++ b/packages/api/src/hooks/Composer.js @@ -149,6 +149,7 @@ const Composer = ({ activityStatusMiddleware, activityStatusRenderer, attachmentMiddleware, + attachmentForScreenReaderMiddleware, attachmentRenderer, avatarMiddleware, avatarRenderer, @@ -280,13 +281,18 @@ const Composer = ({ return ( activityRenderer || - applyMiddlewareForRenderer('activity', ...singleToArray(activityMiddleware), () => () => ({ activity }) => { - if (activity) { - throw new Error(`No renderer for activity of type "${activity.type}"`); - } else { - throw new Error('No activity to render'); + applyMiddlewareForRenderer( + 'activity', + { strict: false }, + ...singleToArray(activityMiddleware), + () => () => ({ activity }) => { + if (activity) { + throw new Error(`No renderer for activity of type "${activity.type}"`); + } else { + throw new Error('No activity to render'); + } } - })({}) + )({}) ); }, [activityMiddleware, activityRenderer]); @@ -298,53 +304,31 @@ const Composer = ({ return ( activityStatusRenderer || - applyMiddlewareForRenderer('activity status', ...singleToArray(activityStatusMiddleware), () => () => () => - false + applyMiddlewareForRenderer( + 'activity status', + { strict: false }, + ...singleToArray(activityStatusMiddleware), + () => () => () => false )({}) ); }, [activityStatusMiddleware, activityStatusRenderer]); - // const patchedAttachmentRenderer = useMemo(() => { - // if (attachmentRenderer) { - // console.warn( - // 'Web Chat: "attachmentRenderer" is deprecated and will be removed on 2022-06-15, please use "attachmentMiddleware" instead.' - // ); - - // return attachmentRenderer; - // } - - // const renderer = applyMiddlewareForRenderer( - // 'attachment', - // ...singleToArray(attachmentMiddleware), - // () => () => ({ attachment }) => () => { - // if (attachment) { - // throw new Error(`No renderer for attachment of type "${attachment.contentType}"`); - // } else { - // throw new Error('No attachment to render'); - // } - // } - // )({}); - - // let showDeprecationNotes = true; - - // return (...args) => { - // const result = renderer(...args); - - // if (isValidElement(result)) { - // if (showDeprecationNotes) { - // console.warn( - // 'botframework-webchat: Please upgrade the attachment middleware with a new signature. For details, please see HOOKS.md#usecreateattachmentrenderer.' - // ); - - // showDeprecationNotes = false; - // } - - // return () => result; - // } - - // return result; - // }; - // }, [attachmentMiddleware, attachmentRenderer]); + const patchedAttachmentForScreenReaderRenderer = useMemo( + () => + applyMiddlewareForRenderer( + 'attachment for screen reader', + { strict: true }, + ...singleToArray(attachmentForScreenReaderMiddleware), + () => () => ({ attachment }) => () => { + if (attachment) { + throw new Error(`No renderer for attachment of type "${attachment.contentType}"`); + } else { + throw new Error('No attachment to render'); + } + } + )({}), + [attachmentForScreenReaderMiddleware] + ); const patchedAttachmentRenderer = useMemo(() => { if (attachmentRenderer) { @@ -373,7 +357,9 @@ const Composer = ({ return ( avatarRenderer || - applyMiddlewareForRenderer('avatar', ...singleToArray(avatarMiddleware), () => () => () => false)({}) + applyMiddlewareForRenderer('avatar', { strict: false }, ...singleToArray(avatarMiddleware), () => () => () => + false + )({}) ); }, [avatarMiddleware, avatarRenderer]); @@ -385,13 +371,18 @@ const Composer = ({ return ( toastRenderer || - applyMiddlewareForRenderer('toast', ...singleToArray(toastMiddleware), () => () => ({ notification }) => { - if (notification) { - throw new Error(`No renderer for notification of type "${notification.contentType}"`); - } else { - throw new Error('No notification to render'); + applyMiddlewareForRenderer( + 'toast', + { strict: false }, + ...singleToArray(toastMiddleware), + () => () => ({ notification }) => { + if (notification) { + throw new Error(`No renderer for notification of type "${notification.contentType}"`); + } else { + throw new Error('No notification to render'); + } } - })({}) + )({}) ); }, [toastMiddleware, toastRenderer]); @@ -403,8 +394,11 @@ const Composer = ({ return ( typingIndicatorRenderer || - applyMiddlewareForRenderer('typing indicator', ...singleToArray(typingIndicatorMiddleware), () => () => () => - false + applyMiddlewareForRenderer( + 'typing indicator', + { strict: false }, + ...singleToArray(typingIndicatorMiddleware), + () => () => () => false )({}) ); }, [typingIndicatorMiddleware, typingIndicatorRenderer]); @@ -427,6 +421,7 @@ const Composer = ({ ...hoistedDispatchers, activityRenderer: patchedActivityRenderer, activityStatusRenderer: patchedActivityStatusRenderer, + attachmentForScreenReaderRenderer: patchedAttachmentForScreenReaderRenderer, attachmentRenderer: patchedAttachmentRenderer, avatarRenderer: patchedAvatarRenderer, dir: patchedDir, @@ -463,6 +458,7 @@ const Composer = ({ onTelemetry, patchedActivityRenderer, patchedActivityStatusRenderer, + patchedAttachmentForScreenReaderRenderer, patchedAttachmentRenderer, patchedAvatarRenderer, patchedDir, @@ -540,6 +536,7 @@ Composer.defaultProps = { activityRenderer: undefined, activityStatusMiddleware: undefined, activityStatusRenderer: undefined, + attachmentForScreenReaderMiddleware: undefined, attachmentMiddleware: undefined, attachmentRenderer: undefined, avatarMiddleware: undefined, @@ -574,6 +571,7 @@ Composer.propTypes = { activityRenderer: PropTypes.func, activityStatusMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), activityStatusRenderer: PropTypes.func, + attachmentForScreenReaderMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), attachmentMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), attachmentRenderer: PropTypes.func, avatarMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]), diff --git a/packages/api/src/hooks/index.js b/packages/api/src/hooks/index.js index b429ec2143..be92e44884 100644 --- a/packages/api/src/hooks/index.js +++ b/packages/api/src/hooks/index.js @@ -7,7 +7,6 @@ import useConnectivityStatus from './useConnectivityStatus'; import useCreateActivityRenderer from './useCreateActivityRenderer'; import useCreateActivityStatusRenderer from './useCreateActivityStatusRenderer'; import useCreateAttachmentForScreenReaderRenderer from './useCreateAttachmentForScreenReaderRenderer'; -import useCreateAttachmentRenderer from './useCreateAttachmentRenderer'; import useCreateAvatarRenderer from './useCreateAvatarRenderer'; import useDateFormatter from './useDateFormatter'; import useDebouncedNotifications from './useDebouncedNotifications'; @@ -71,7 +70,6 @@ export { useCreateActivityRenderer, useCreateActivityStatusRenderer, useCreateAttachmentForScreenReaderRenderer, - useCreateAttachmentRenderer, useCreateAvatarRenderer, useDateFormatter, useDebouncedNotifications, diff --git a/packages/api/src/hooks/middleware/applyMiddleware.js b/packages/api/src/hooks/middleware/applyMiddleware.js index 97d90a588e..5528cbb05c 100644 --- a/packages/api/src/hooks/middleware/applyMiddleware.js +++ b/packages/api/src/hooks/middleware/applyMiddleware.js @@ -11,10 +11,10 @@ export default function applyMiddleware(type, ...middleware) { }); } -export function forRenderer(type, ...middleware) { +export function forRenderer(type, { strict = false } = {}, ...middleware) { return (...setupArgs) => { const runMiddleware = concatMiddleware(...middleware)(...setupArgs)(() => ( - + )); // The createRendererArgs is "what to render", for example, activity. @@ -28,14 +28,30 @@ export function forRenderer(type, ...middleware) { if (!render) { return false; } else if (isValidElement(render)) { + if (strict) { + console.error(`botframework-webchat: ${type} should only return either false or a render function.`); + + return false; + } + return {render}; } else { return (...renderTimeArgs) => ( - {() => render(...renderTimeArgs)} + + {() => { + const element = render(...renderTimeArgs); + + if (strict && !isValidElement(element)) { + console.error(`botframework-webchat: ${type} should return React element only.`); + } + + return element; + }} + ); } } catch (err) { - return ; + return ; } }; }; diff --git a/packages/api/src/hooks/middleware/createActivityRenderer.js b/packages/api/src/hooks/middleware/createActivityRenderer.js deleted file mode 100644 index a1a39c4a3b..0000000000 --- a/packages/api/src/hooks/middleware/createActivityRenderer.js +++ /dev/null @@ -1,6 +0,0 @@ -import applyMiddleware from './applyMiddleware'; - -const createActivityRenderer = (...middleware) => - applyMiddleware('activity middleware', ...middleware); - -export default createActivityRenderer; diff --git a/packages/api/src/hooks/middleware/createActivityStatusRenderer.js b/packages/api/src/hooks/middleware/createActivityStatusRenderer.js deleted file mode 100644 index 9c5f4d82a2..0000000000 --- a/packages/api/src/hooks/middleware/createActivityStatusRenderer.js +++ /dev/null @@ -1,6 +0,0 @@ -import applyMiddleware from './applyMiddleware'; - -const createActivityStatusRenderer = (...middleware) => - applyMiddleware('activity status middleware', ...middleware, () => () => () => false); - -export default createActivityStatusRenderer; diff --git a/packages/api/src/hooks/middleware/createAttachmentRenderer.js b/packages/api/src/hooks/middleware/createAttachmentRenderer.js deleted file mode 100644 index a284d25f02..0000000000 --- a/packages/api/src/hooks/middleware/createAttachmentRenderer.js +++ /dev/null @@ -1,12 +0,0 @@ -import applyMiddleware from './applyMiddleware'; - -const createAttachmentRenderer = (...middleware) => - applyMiddleware('attachment middleware', ...middleware, () => () => ({ attachment }) => { - if (attachment) { - throw new Error(`No renderer for attachment of type "${attachment.contentType}"`); - } else { - throw new Error('No attachment to render'); - } - }); - -export default createAttachmentRenderer; diff --git a/packages/api/src/hooks/middleware/createAvatarRenderer.js b/packages/api/src/hooks/middleware/createAvatarRenderer.js deleted file mode 100644 index 6b33f9450f..0000000000 --- a/packages/api/src/hooks/middleware/createAvatarRenderer.js +++ /dev/null @@ -1,6 +0,0 @@ -import applyMiddleware from './applyMiddleware'; - -const createAvatarRenderer = (...middleware) => - applyMiddleware('avatar middleware', ...middleware, () => () => () => false); - -export default createAvatarRenderer; diff --git a/packages/api/src/hooks/middleware/createToastRenderer.js b/packages/api/src/hooks/middleware/createToastRenderer.js deleted file mode 100644 index 89284c89aa..0000000000 --- a/packages/api/src/hooks/middleware/createToastRenderer.js +++ /dev/null @@ -1,12 +0,0 @@ -import applyMiddleware from './applyMiddleware'; - -const createToastRenderer = (...middleware) => - applyMiddleware('toast middleware', ...middleware, () => () => ({ notification }) => { - if (notification) { - throw new Error(`No renderer for notification of type "${notification.contentType}"`); - } else { - throw new Error('No notification to render'); - } - }); - -export default createToastRenderer; diff --git a/packages/api/src/hooks/middleware/createTypingIndicatorRenderer.js b/packages/api/src/hooks/middleware/createTypingIndicatorRenderer.js deleted file mode 100644 index d403a05c21..0000000000 --- a/packages/api/src/hooks/middleware/createTypingIndicatorRenderer.js +++ /dev/null @@ -1,8 +0,0 @@ -import applyMiddleware from './applyMiddleware'; - -const createTypingIndicator = (...middleware) => - applyMiddleware('typing indicator middleware', ...middleware, () => () => () => { - throw new Error(`No renderer for typing indicator`); - }); - -export default createTypingIndicator; diff --git a/packages/api/src/hooks/useCreateAttachmentForScreenReaderRenderer.js b/packages/api/src/hooks/useCreateAttachmentForScreenReaderRenderer.js new file mode 100644 index 0000000000..2a0fe23642 --- /dev/null +++ b/packages/api/src/hooks/useCreateAttachmentForScreenReaderRenderer.js @@ -0,0 +1,5 @@ +import useWebChatAPIContext from './internal/useWebChatAPIContext'; + +export default function useCreateAttachmentForScreenReaderRenderer() { + return useWebChatAPIContext().attachmentForScreenReaderRenderer; +} diff --git a/packages/bundle/src/adaptiveCards/Attachment/HeroCardAttachment.js b/packages/bundle/src/adaptiveCards/Attachment/HeroCardAttachment.js index eb66864816..4ba7b71feb 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/HeroCardAttachment.js +++ b/packages/bundle/src/adaptiveCards/Attachment/HeroCardAttachment.js @@ -16,7 +16,7 @@ HeroCardAttachment.propTypes = { buttons: PropTypes.any, images: PropTypes.arrayOf( PropTypes.shape({ - alt: PropTypes.string.isRequired, + alt: PropTypes.string, tap: PropTypes.any, url: PropTypes.string.isRequired }) diff --git a/packages/bundle/src/adaptiveCards/Attachment/HeroCardContent.js b/packages/bundle/src/adaptiveCards/Attachment/HeroCardContent.js index d940b0e0c5..8bd89d2f5d 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/HeroCardContent.js +++ b/packages/bundle/src/adaptiveCards/Attachment/HeroCardContent.js @@ -44,7 +44,7 @@ HeroCardContent.propTypes = { content: PropTypes.shape({ images: PropTypes.arrayOf( PropTypes.shape({ - alt: PropTypes.string.isRequired, + alt: PropTypes.string, tap: PropTypes.any, url: PropTypes.string.isRequired }) diff --git a/packages/component/package-lock.json b/packages/component/package-lock.json index df46196bc4..128f4d925d 100644 --- a/packages/component/package-lock.json +++ b/packages/component/package-lock.json @@ -33,7 +33,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, "requires": { "@babel/highlight": "^7.10.4" } @@ -255,6 +254,33 @@ } } }, + "@babel/generator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz", + "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==", + "requires": { + "@babel/types": "^7.12.1", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz", + "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, "@babel/helper-annotate-as-pure": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", @@ -610,6 +636,48 @@ } } }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz", + "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "requires": { + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz", + "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, "@babel/helper-hoist-variables": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", @@ -1013,6 +1081,26 @@ } } }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "requires": { + "@babel/types": "^7.11.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz", + "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, "@babel/helper-validator-identifier": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", @@ -1252,13 +1340,17 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } }, + "@babel/parser": { + "version": "7.12.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.3.tgz", + "integrity": "sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw==" + }, "@babel/plugin-proposal-async-generator-functions": { "version": "7.10.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz", @@ -2558,6 +2650,56 @@ } } }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz", + "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/traverse": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.1.tgz", + "integrity": "sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.1", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.12.1", + "@babel/types": "^7.12.1", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "@babel/types": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz", + "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, "@babel/types": { "version": "7.8.7", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.7.tgz", @@ -2701,9 +2843,9 @@ "dev": true }, "@types/json-schema": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", - "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==" + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==" }, "@types/node": { "version": "14.6.0", @@ -2916,12 +3058,6 @@ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, "acorn": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", @@ -2934,12 +3070,6 @@ "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", "dev": true }, - "adm-zip": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz", - "integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==", - "dev": true - }, "ajv": { "version": "6.12.3", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", @@ -3061,23 +3191,15 @@ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", "requires": { "bn.js": "^4.0.0", "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" }, "dependencies": { "bn.js": { @@ -3111,12 +3233,6 @@ } } }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -3134,29 +3250,11 @@ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", "optional": true }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", - "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", - "dev": true - }, "babel-loader": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", @@ -3268,15 +3366,6 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -3303,9 +3392,9 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "bn.js": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz", - "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==" + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" }, "bowser": { "version": "1.9.4", @@ -3529,12 +3618,6 @@ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001118.tgz", "integrity": "sha512-RNKPLojZo74a0cP7jFMidQI7nvLER40HgNfgKQEJ2PFm225L0ectUungNQoK3Xk3StQcFbpBPNEvoWD59436Hg==" }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, "ccount": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.4.tgz", @@ -3638,74 +3721,6 @@ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" }, - "cldr-data": { - "version": "36.0.0", - "resolved": "https://registry.npmjs.org/cldr-data/-/cldr-data-36.0.0.tgz", - "integrity": "sha512-F3n+9DUs41vhys8eF/hsCgkmYlgXMCiwaE75uGZjUbS/jkszBnLylXj7xW3bBlMU1d2IuAptpoNAb6lTCu/RSg==", - "dev": true, - "requires": { - "cldr-data-downloader": "0.3.x", - "glob": "5.x.x" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "cldr-data-downloader": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/cldr-data-downloader/-/cldr-data-downloader-0.3.5.tgz", - "integrity": "sha512-uyIMa1K98DAp/PE7dYpq2COIrkWn681Atjng1GgEzeJzYb1jANtugtp9wre6+voE+qzVC8jtWv6E/xZ1GTJdlw==", - "dev": true, - "requires": { - "adm-zip": "0.4.11", - "mkdirp": "0.5.0", - "nopt": "3.0.x", - "progress": "1.1.8", - "q": "1.0.1", - "request": "~2.87.0", - "request-progress": "0.3.1" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", - "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "dev": true - } - } - }, - "cldrjs": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/cldrjs/-/cldrjs-0.5.1.tgz", - "integrity": "sha512-xyiP8uAm8K1IhmpDndZLraloW1yqu0L+HYdQ7O1aGPxx9Cr+BMnPANlNhSt++UKfxytL2hd2NPXgTjiy7k43Ew==" - }, "cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", @@ -3716,12 +3731,6 @@ "wrap-ansi": "^5.1.0" } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, "collapse-white-space": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.5.tgz", @@ -3749,15 +3758,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, "commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -3989,15 +3989,6 @@ "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "date-fns": { "version": "2.15.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.15.0.tgz", @@ -4085,12 +4076,6 @@ } } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, "des.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", @@ -4189,16 +4174,6 @@ "xtend": "^4.0.0" } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "electron-to-chromium": { "version": "1.3.549", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.549.tgz", @@ -4343,60 +4318,6 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, - "escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - } - } - }, "eslint": { "version": "7.7.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.7.0.tgz", @@ -4685,14 +4606,6 @@ "webpack-cli": "3.3.12" }, "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "requires": { - "@babel/highlight": "^7.10.4" - } - }, "@babel/core": { "version": "7.11.1", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.1.tgz", @@ -4716,87 +4629,10 @@ "source-map": "^0.5.0" } }, - "@babel/generator": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz", - "integrity": "sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==", - "requires": { - "@babel/types": "^7.11.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", - "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.2.tgz", - "integrity": "sha512-Vuj/+7vLo6l1Vi7uuO+1ngCDNeVmNbTngcJFKCR/oEtz8tKz0CJxZEGmPt9KcIloZhOZ3Zit6xbpXT2MDlS9Vw==" - }, - "@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/traverse": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", - "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.0", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.0", - "@babel/types": "^7.11.0", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" - } - }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz", + "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==", "requires": { "@babel/helper-validator-identifier": "^7.10.4", "lodash": "^4.17.19", @@ -4960,12 +4796,6 @@ } } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -5119,23 +4949,6 @@ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -5217,15 +5030,6 @@ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "glamor": { "version": "2.20.40", "resolved": "https://registry.npmjs.org/glamor/-/glamor-2.20.40.tgz", @@ -5322,33 +5126,6 @@ } } }, - "globalize": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/globalize/-/globalize-1.5.0.tgz", - "integrity": "sha512-76fcPQO/WLthtSwjgIZ/Zv2XSXqv9ifvl1PwIxJNCZNFHigGCpg3fBZ0poJ30b2kdDgofPkYl478lVZA6esESQ==", - "requires": { - "cldrjs": "^0.5.0" - } - }, - "globalize-compiler": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/globalize-compiler/-/globalize-compiler-1.1.1.tgz", - "integrity": "sha512-oZIwVp3L/waDidle7Qrw4FiCCmOLAqvdM9P7W8nEO4OfXO//l/abBiA+RL2+mYZPOpTAlRDVS2FLfFVWxHovWA==", - "dev": true, - "requires": { - "escodegen": "^1.6.1", - "esprima": "^2.3.0", - "nopt": "^3.0.3" - }, - "dependencies": { - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - } - } - }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -5365,48 +5142,6 @@ "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", "dev": true }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "dev": true, - "requires": { - "ajv": "^5.1.0", - "har-schema": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - } - } - }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -5534,17 +5269,6 @@ "entities": "^2.0.0" } }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", @@ -5555,12 +5279,6 @@ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz", "integrity": "sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ==" }, - "iana-tz-data": { - "version": "2019.1.0", - "resolved": "https://registry.npmjs.org/iana-tz-data/-/iana-tz-data-2019.1.0.tgz", - "integrity": "sha512-T7+26Skkyxqjp4mg20/O065j9J5qP39nWVQj/2ArxQ0gSPkL+T9lwerRmiOAzFRNsNXepX45QqchqTVENwNvig==", - "dev": true - }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -5884,12 +5602,6 @@ "has-symbols": "^1.0.1" } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, "is-whitespace-character": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.3.tgz", @@ -5934,12 +5646,6 @@ "whatwg-fetch": ">=0.10.0" } }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, "istanbul-lib-coverage": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", @@ -5981,12 +5687,6 @@ "esprima": "^4.0.0" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -5997,12 +5697,6 @@ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -6014,12 +5708,6 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, "json5": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", @@ -6028,18 +5716,6 @@ "minimist": "^1.2.5" } }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, "jsx-ast-utils": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz", @@ -6275,21 +5951,6 @@ } } }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "dev": true - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dev": true, - "requires": { - "mime-db": "1.44.0" - } - }, "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -6504,15 +6165,6 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==" }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -6531,12 +6183,6 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "optional": true }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -6721,13 +6367,12 @@ } }, "parse-asn1": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", - "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", "requires": { - "asn1.js": "^4.0.0", + "asn1.js": "^5.2.0", "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.0", "pbkdf2": "^3.0.3", "safe-buffer": "^5.1.1" @@ -6815,12 +6460,6 @@ "sha.js": "^2.4.8" } }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", @@ -6986,18 +6625,6 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, - "q": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.0.1.tgz", - "integrity": "sha1-EYcq7t7okmgRCxCnGESP+xARKhQ=", - "dev": true - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -7313,43 +6940,6 @@ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" }, - "request": { - "version": "2.87.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", - "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", - "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.17", - "oauth-sign": "~0.8.2", - "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "tough-cookie": "~2.3.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" - } - }, - "request-progress": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-0.3.1.tgz", - "integrity": "sha1-ByHBBdipasayzossia4tXs/Pazo=", - "dev": true, - "requires": { - "throttleit": "~0.0.2" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -7455,9 +7045,9 @@ } }, "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safe-regex": { "version": "1.1.0", @@ -7484,13 +7074,26 @@ } }, "schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", "requires": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + } } }, "semver": { @@ -7499,9 +7102,9 @@ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" }, "serialize-javascript": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", - "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", "requires": { "randombytes": "^2.1.0" } @@ -7828,23 +7431,6 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "ssri": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", @@ -8049,15 +7635,15 @@ } }, "terser-webpack-plugin": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz", - "integrity": "sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", "requires": { "cacache": "^12.0.2", "find-cache-dir": "^2.1.0", "is-wsl": "^1.1.0", "schema-utils": "^1.0.0", - "serialize-javascript": "^3.1.0", + "serialize-javascript": "^4.0.0", "source-map": "^0.6.1", "terser": "^4.1.2", "webpack-sources": "^1.4.0", @@ -8093,12 +7679,6 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "throttleit": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", - "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", - "dev": true - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -8174,23 +7754,6 @@ "repeat-string": "^1.6.1" } }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "dev": true, - "requires": { - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } - } - }, "tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -8222,21 +7785,6 @@ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -8481,12 +8029,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, "v8-compile-cache": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", @@ -8502,17 +8044,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "vfile": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz", @@ -8595,9 +8126,9 @@ } }, "chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", "optional": true, "requires": { "anymatch": "~3.1.1", @@ -8607,7 +8138,7 @@ "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" + "readdirp": "~3.5.0" } }, "fill-range": { @@ -8650,9 +8181,9 @@ "optional": true }, "readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", "optional": true, "requires": { "picomatch": "^2.2.1" @@ -8709,9 +8240,9 @@ }, "dependencies": { "acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==" + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" }, "eslint-scope": { "version": "4.0.3", diff --git a/packages/component/package.json b/packages/component/package.json index 3e0e248745..a47bb78939 100644 --- a/packages/component/package.json +++ b/packages/component/package.json @@ -52,14 +52,18 @@ "botframework-webchat-core": "0.0.0-0", "classnames": "2.2.6", "create-emotion": "10.0.27", + "event-target-shim": "5.0.1", + "event-target-shim-es5": "1.2.0", "markdown-it": "11.0.0", "math-random": "2.0.1", "memoize-one": "5.1.1", "prop-types": "15.7.2", "react-dictate-button": "1.2.3-master.6b4fe72", "react-film": "3.0.0", + "react-redux": "7.2.0", "react-say": "2.0.2-master.ee7cd76", "react-scroll-to-bottom": "4.0.0", + "redux": "4.0.5", "remark": "10.0.1", "sanitize-html": "^1.27.4", "simple-update-in": "2.2.0", diff --git a/packages/component/src/Composer.js b/packages/component/src/Composer.js index a56cc4888b..ace22debbf 100644 --- a/packages/component/src/Composer.js +++ b/packages/component/src/Composer.js @@ -1,3 +1,5 @@ +/* eslint-disable react/prop-types */ +/* eslint-disable react/destructuring-assignment */ import { Composer as APIComposer, hooks } from 'botframework-webchat-api'; import { Composer as SayComposer } from 'react-say'; import { Composer as ScrollToBottomComposer } from 'react-scroll-to-bottom'; @@ -15,6 +17,7 @@ import addTargetBlankToHyperlinksMarkdown from './Utils/addTargetBlankToHyperlin import createCSSKey from './Utils/createCSSKey'; import createDefaultActivityMiddleware from './Middleware/Activity/createCoreMiddleware'; import createDefaultActivityStatusMiddleware from './Middleware/ActivityStatus/createCoreMiddleware'; +import createDefaultAttachmentForScreenReaderMiddleware from './Middleware/AttachmentForScreenReader/createCoreMiddleware'; import createDefaultAttachmentMiddleware from './Middleware/Attachment/createCoreMiddleware'; import createDefaultAvatarMiddleware from './Middleware/Avatar/createCoreMiddleware'; import createDefaultCardActionMiddleware from './Middleware/CardAction/createCoreMiddleware'; @@ -203,6 +206,7 @@ ComposerCore.propTypes = { const Composer = ({ activityMiddleware, activityStatusMiddleware, + attachmentForScreenReaderMiddleware, attachmentMiddleware, avatarMiddleware, cardActionMiddleware, @@ -228,6 +232,14 @@ const Composer = ({ [activityStatusMiddleware] ); + const patchedAttachmentForScreenReaderMiddleware = useMemo( + () => [ + ...singleToArray(attachmentForScreenReaderMiddleware), + ...createDefaultAttachmentForScreenReaderMiddleware() + ], + [attachmentForScreenReaderMiddleware] + ); + const patchedAttachmentMiddleware = useMemo( () => [...singleToArray(attachmentMiddleware), ...createDefaultAttachmentMiddleware()], [attachmentMiddleware] @@ -257,6 +269,7 @@ const Composer = ({ { const localize = useLocalizer(); diff --git a/packages/component/src/Middleware/AttachmentForScreenReader/FileAttachment.js b/packages/component/src/Middleware/AttachmentForScreenReader/FileAttachment.js index ef846fcd11..7b9e5788f7 100644 --- a/packages/component/src/Middleware/AttachmentForScreenReader/FileAttachment.js +++ b/packages/component/src/Middleware/AttachmentForScreenReader/FileAttachment.js @@ -1,7 +1,8 @@ +import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; import React from 'react'; -import useLocalizer from '../../hooks/useLocalizer'; +const { useLocalizer } = hooks; const FileAttachment = ({ attachment: { name = '' } = {} }) => { const localize = useLocalizer(); diff --git a/packages/component/src/Middleware/AttachmentForScreenReader/ImageAttachment.js b/packages/component/src/Middleware/AttachmentForScreenReader/ImageAttachment.js index 804de52af2..cbebad14b9 100644 --- a/packages/component/src/Middleware/AttachmentForScreenReader/ImageAttachment.js +++ b/packages/component/src/Middleware/AttachmentForScreenReader/ImageAttachment.js @@ -1,6 +1,7 @@ +import { hooks } from 'botframework-webchat-api'; import React from 'react'; -import useLocalizer from '../../hooks/useLocalizer'; +const { useLocalizer } = hooks; const ImageAttachment = () => { const localize = useLocalizer(); diff --git a/packages/component/src/Middleware/AttachmentForScreenReader/TextAttachment.js b/packages/component/src/Middleware/AttachmentForScreenReader/TextAttachment.js index 66d8fcca6d..0c5164ffc2 100644 --- a/packages/component/src/Middleware/AttachmentForScreenReader/TextAttachment.js +++ b/packages/component/src/Middleware/AttachmentForScreenReader/TextAttachment.js @@ -1,7 +1,8 @@ +import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; import React from 'react'; -import useLocalizer from '../../hooks/useLocalizer'; +const { useLocalizer } = hooks; const TextAttachment = ({ attachment: { content = '' } = {} }) => { const localize = useLocalizer(); diff --git a/packages/component/src/Middleware/AttachmentForScreenReader/VideoAttachment.js b/packages/component/src/Middleware/AttachmentForScreenReader/VideoAttachment.js index 00d47970c1..b37da1040a 100644 --- a/packages/component/src/Middleware/AttachmentForScreenReader/VideoAttachment.js +++ b/packages/component/src/Middleware/AttachmentForScreenReader/VideoAttachment.js @@ -1,6 +1,7 @@ +import { hooks } from 'botframework-webchat-api'; import React from 'react'; -import useLocalizer from '../../hooks/useLocalizer'; +const { useLocalizer } = hooks; const VideoAttachment = () => { const localize = useLocalizer(); diff --git a/packages/component/src/Middleware/AttachmentForScreenReader/createCoreMiddleware.js b/packages/component/src/Middleware/AttachmentForScreenReader/createCoreMiddleware.js index c8d3e7d56d..e136d88c18 100644 --- a/packages/component/src/Middleware/AttachmentForScreenReader/createCoreMiddleware.js +++ b/packages/component/src/Middleware/AttachmentForScreenReader/createCoreMiddleware.js @@ -7,23 +7,29 @@ import TextAttachment from './TextAttachment'; import VideoAttachment from './VideoAttachment'; export default function createCoreMiddleware() { - return () => next => (...args) => { - const [ - { activity: { from: { role } = {} } = {}, attachment, attachment: { contentType, contentUrl, thumbnailUrl } = {} } - ] = args; + return [ + () => next => (...args) => { + const [ + { + activity: { from: { role } = {} } = {}, + attachment, + attachment: { contentType, contentUrl, thumbnailUrl } = {} + } + ] = args; - return role === 'user' && !/^text\//u.test(contentType) && !thumbnailUrl - ? () => - : /^audio\//u.test(contentType) - ? () => - : /^image\//u.test(contentType) - ? () => - : /^video\//u.test(contentType) - ? () => - : contentUrl || contentType === 'application/octet-stream' - ? () => - : /^text\//u.test(contentType) - ? () => - : next(...args); - }; + return role === 'user' && !/^text\//u.test(contentType) && !thumbnailUrl + ? () => + : /^audio\//u.test(contentType) + ? () => + : /^image\//u.test(contentType) + ? () => + : /^video\//u.test(contentType) + ? () => + : contentUrl || contentType === 'application/octet-stream' + ? () => + : /^text\//u.test(contentType) + ? () => + : next(...args); + } + ]; } diff --git a/packages/component/src/Middleware/applyAttachmentForScreenReaderMiddleware.js b/packages/component/src/Middleware/applyAttachmentForScreenReaderMiddleware.js deleted file mode 100644 index 60922c1c1f..0000000000 --- a/packages/component/src/Middleware/applyAttachmentForScreenReaderMiddleware.js +++ /dev/null @@ -1,25 +0,0 @@ -/* eslint no-magic-numbers: ["error", { "ignore": [2] }] */ - -import React from 'react'; - -import concatMiddleware from './concatMiddleware'; -import createCoreMiddleware from './AttachmentForScreenReader/createCoreMiddleware'; -import ErrorBox from '../ErrorBox'; - -export default function applyAttachmentForScreenReaderMiddleware(additionalMiddleware) { - const activityMiddleware = concatMiddleware(additionalMiddleware, createCoreMiddleware())({}); - - return (...args) => { - try { - return activityMiddleware(() => false)(...args); - } catch (err) { - const FailedRenderAttachmentForScreenReader = () => ( - -
{JSON.stringify(err, null, 2)}
-
- ); - - return FailedRenderAttachmentForScreenReader; - } - }; -} diff --git a/packages/component/src/hooks/useCreateAttachmentForScreenReaderRenderer.js b/packages/component/src/hooks/useCreateAttachmentForScreenReaderRenderer.js deleted file mode 100644 index f945ec439c..0000000000 --- a/packages/component/src/hooks/useCreateAttachmentForScreenReaderRenderer.js +++ /dev/null @@ -1,5 +0,0 @@ -import useWebChatUIContext from './internal/useWebChatUIContext'; - -export default function useCreateAttachmentForScreenReaderRenderer() { - return useWebChatUIContext().createAttachmentForScreenReaderRenderer; -} From 01fbc0e002e4fb5912724ce6d64c64cc8a5927d7 Mon Sep 17 00:00:00 2001 From: William Wong Date: Tue, 27 Oct 2020 12:00:06 -0700 Subject: [PATCH 18/21] Fix tests --- ...nts-in-live-region-unknown-card-1-snap.png | Bin 25966 -> 46369 bytes packages/api/src/hooks/Composer.js | 2 +- .../src/hooks/middleware/applyMiddleware.js | 14 +++++++++----- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/__tests__/__image_snapshots__/html/accessibility-live-region-attachment-unknown-card-js-accessibility-requirement-attachments-in-live-region-unknown-card-1-snap.png b/__tests__/__image_snapshots__/html/accessibility-live-region-attachment-unknown-card-js-accessibility-requirement-attachments-in-live-region-unknown-card-1-snap.png index d8dbb3c8bf24de7a59e30c1f95d7fb78724e84dc..7e35eaecd45a019795f6e561cffda2c5c0e49fd1 100644 GIT binary patch literal 46369 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 literal 25966 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 () => ({ attachment }) => () => { if (attachment) { - throw new Error(`No renderer for attachment of type "${attachment.contentType}"`); + throw new Error(`No renderer for attachment for screen reader of type "${attachment.contentType}"`); } else { throw new Error('No attachment to render'); } diff --git a/packages/api/src/hooks/middleware/applyMiddleware.js b/packages/api/src/hooks/middleware/applyMiddleware.js index 5528cbb05c..d3351084e9 100644 --- a/packages/api/src/hooks/middleware/applyMiddleware.js +++ b/packages/api/src/hooks/middleware/applyMiddleware.js @@ -39,13 +39,17 @@ export function forRenderer(type, { strict = false } = {}, ...middleware) { return (...renderTimeArgs) => ( {() => { - const element = render(...renderTimeArgs); + try { + const element = render(...renderTimeArgs); - if (strict && !isValidElement(element)) { - console.error(`botframework-webchat: ${type} should return React element only.`); - } + if (strict && !isValidElement(element)) { + console.error(`botframework-webchat: ${type} should return React element only.`); + } - return element; + return element; + } catch (err) { + return ; + } }} ); From 4dccb850bfd9bc917dc30bed54aa0df893e1302e Mon Sep 17 00:00:00 2001 From: William Wong Date: Tue, 27 Oct 2020 13:04:50 -0700 Subject: [PATCH 19/21] Fix tests --- ...nts-in-live-region-unknown-card-1-snap.png | Bin 46369 -> 30154 bytes packages/component/src/ErrorBox.js | 6 +++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/__tests__/__image_snapshots__/html/accessibility-live-region-attachment-unknown-card-js-accessibility-requirement-attachments-in-live-region-unknown-card-1-snap.png b/__tests__/__image_snapshots__/html/accessibility-live-region-attachment-unknown-card-js-accessibility-requirement-attachments-in-live-region-unknown-card-1-snap.png index 7e35eaecd45a019795f6e561cffda2c5c0e49fd1..9dbcad94058d7fa3dee9c0d4d006c311730ef26c 100644 GIT binary patch literal 30154 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 diff --git a/packages/component/src/ErrorBox.js b/packages/component/src/ErrorBox.js index 89f623b698..120c9dea8a 100644 --- a/packages/component/src/ErrorBox.js +++ b/packages/component/src/ErrorBox.js @@ -18,7 +18,11 @@ const ErrorBox = ({ error, type }) => {
{type}
-
{error.stack}
+ {/* The callstack between production and development are different, thus, we should hide it for visual regression test */} +
+ {error.message} +
{error.stack}
+
); From d8838f4a19503d8366f15731f1f55ce75f6fa44d Mon Sep 17 00:00:00 2001 From: William Wong Date: Tue, 27 Oct 2020 13:26:59 -0700 Subject: [PATCH 20/21] Fix tests --- ...-broken-card-of-invalid-version-1-snap.png | Bin 42453 -> 25972 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/__tests__/__image_snapshots__/chrome-docker/adaptive-cards-js-broken-card-of-invalid-version-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/adaptive-cards-js-broken-card-of-invalid-version-1-snap.png index 90c3bb78622d43ca7b061f27cdb90adf538878b9..df4476ba672c22baaabc54751d4e85f3be2c84e3 100644 GIT binary patch literal 25972 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
OvP>+g6(5V4>F9!7H=4L}_wVeGAeBBW(7uDh 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 z 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 Date: Tue, 27 Oct 2020 14:13:30 -0700 Subject: [PATCH 21/21] Remove eslint-disable --- packages/component/src/Composer.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/component/src/Composer.js b/packages/component/src/Composer.js index ace22debbf..5368f0693d 100644 --- a/packages/component/src/Composer.js +++ b/packages/component/src/Composer.js @@ -1,5 +1,3 @@ -/* eslint-disable react/prop-types */ -/* eslint-disable react/destructuring-assignment */ import { Composer as APIComposer, hooks } from 'botframework-webchat-api'; import { Composer as SayComposer } from 'react-say'; import { Composer as ScrollToBottomComposer } from 'react-scroll-to-bottom';

l2)iFJP5x~99VE0|T*JAidn^4Cz}+MSz)E9#yJXa3lW;bhMJd_`50-!IcP0pF zvI0g1FgrPg7SkH6?Ch_jIgFA`A>@{?3IZCdFH@1FacW8E0B*$( zF6vu-{cn{=i!px54B#?Ktjd;b5tX#O$G`@%XPZ3!;vl9&-}&{qn)SXs zD5kdRm18s^B~R|77&jn4$;JT!uws<);4M zX^{&4pIU1UO!UCPOdZOx23#B5_614bH?=@`+Fn~0@jcEQLW7(A!QWp}y;v0HVfA$J z;JIS|ra%6F_RxO}Dc)SQ zCM_S|NwMp`D02D|1TxxK$QVwL-%HHyKUqXUWd47Sy{_^n0+9?tD1Ll=JpcLOyq$X7 zb&&zGqVxPzvi;49EjHl#+jmf|g zu6tm{uBW|&105%4@ju_c3;lSbWLh6spVk>D?>U{fW}pIsLPK-&u-#*ktFl`yC8JpX zm(cv&e?ZrS<6%dG%j^UilXJb)}Fe6SDl(Q4&GVH0{zK~?m7nR-K-(LWkkX?Mv z-p#MWEty(a7z&xc58$MvkBu83%e{nI7vySZTboEqFOabYn$?vGX2c?DqZ9-^fMfJLuZw`c*oD_3 z8)BlTzY925fEJ={Hxg@Jr=pTEHD!cH`oXRlxSCC7_p9YbQy^J0sFDVtB|=OhIy?E3 zo|Uy8ZB`Qt=^{HjdszLVbFUo|q9dT?MuCDUE-qeZJm?31ujxRBqTBgG?%y4FEpvmI zxH*V|FOuJh4cK*6`r{w3D<%!d85@7g6VtMT( zWN(Qom)mCa0>T&f46SoYs&fBNYxT5FLLlEKKH0{PI_aPQ2DFEht+k9BB=Bg|eY@-~# zj!0Ii$VcyhMCJ!MkJEHSOX&b0csD^m!ae_xmuFS51c=Qw{DS~Z!Ih| zLcBNvUa7@Tg$d`20hX=m6J~8~?e(cD&_rYk*=kPe26CW}E_7-*Oh;ZZOWd3zlG`BP zE5ae?zAh^3c(y<6bU5pSYZHS2cs1bsbWBY<;Hr+6+0coKiWboi|NMytuLKJK;Tsfm zpPs%g*A<|^S(-Id+h=!Sh2fBK2EZ;}GrnNRsT8ra+_n?=#+g0H0yn7%2#v|fcNMaf zWY^r$3kK9ik@yNL?{fni1FXH*^FPp*V zfbCnqK3V`vS+htF_03S&L`}DSLKH-Lw_9lG6J7iakTYkJd?=Gae|owbCnqOgg0O;s z&uiF|h?d~Gg9VJepUurafYa;A(G;q0VFi>mMAApL%dZMmm>>&C#c(23t`CWsn=?aP zC`qLIagy#H1*GhHAN+LCN2R5u+lw(4Z14|2gx3Lb73=EN8BiM_YCp%sm@G%oN``OO zT$}}i)b=unck%`ygbpCdEBKVCYl(Ii+6b|+34pz*^~B1?Hun>gDiz{ti7VO1!<-)2 zX#@I=g@qij4p++sfJ^QSr(7bwT>^5oiMqR%)*VYs893_k%#H3p83B_wK$|SLGnts2 zM13^CnA^z*LLySNBkJkx?FHgvKd@G-fd%`o+>tP6I8ka5ha-@wZ_%tEo0r10T7 zR5dLXhiMC&@FIPEiX@FRxnPvQNeK?~Fy&P6<6N?AxJ&MPzX=jng%CyuU z4p|@#2|DfE!zJU)S~LD|J$Wjl!0Q7npZg39*gz;>>`u^B{F}w#TT)O^s4I$MgLZlE z8UwlZztLa)hY|7rYB&rWDXyRoTV(+7odERe8wG_SJr_6=Gbkk`Wod0)E?_rkFA6sU z0{v<}6Et_3X>3r>X_fm6i~2V|huwHO&d*McAhW)@^%2nU!SMnvQq<9o-c+h_7f?YGiOOEZ!AbSFIENAwAA(MvVeeg7gaIHtlPV!>30|DqT)`m` zhSUOI6P4p2A&`Y%0DD>2;Gzbe2H;nI4o?G^(EF+W1`ll*;|+gei0GXg9Nlj^ylM&Z zvsn9$YzM5Po6dV;Pt$ud^rKf4^_>EqXJ{E^DJEw;h;}lVd3QDSQgW$ZE~EAO7QR7E zz2D8Y+3>Aq&5G%6hnj?~pOuH}CoZN~#zoN(&&2{s8^f7Yd)D?VVR0f*7KQEBR2<;l z(Q@@WNrA*F4TVCCPQgcALvIkUNET2OV#Dv+!#U>!+ zf<0lr%}yV7&C}QSDgwd@`~_4lK7D<1*&0=CpQ)cB3_%yb9#ku}d^alJB`ga>c4##SN z3R1xda&ra}nUQ>3!dv$(nWQd#--#&}6{fB#nqx7OCySMl-FzkTxt>}`jBK|nmH zUHU-0<*Y2mv0^hxKxLzS|M5dEyZTk;;D{-w-c)&a;LwUKz+e4jQ^Y`m;0|ReKNS`h zuF4nF0X*g_RaHq*Q4HQVJQNIlti%F8F_Z^*y5cWhB$k&)gE`ir&+c^v*ZGGa7=+4( zw!)fK&SCz()Tb{1*NKriAAJ#Mgh39&Hw1hxeJA{N7 z!cZrcxu5X@&h>I4$i{)8p*~oG3MYh@Vaedpt4@wV81dDYS5Y}0NC;B}99^CGUk~!@ zm*lMLB8ACt6`G4jx5A6Rq9%_ElYO3+Cas{tN^ct_-hA`NV$>7~Kl;HdcQtM=HGP;b zW|Clrf)1D^C@#d(GEXC zhFm4ahNdPk1iQ=a)>=9`OtbglQ!Occ73+a4YFMNKj^4tfNnN(q2TW;2sQF?1gg&66|y1ox#9A?_jb1>wqEN$Gt77{L2qvA(u` z_^D-Blxtq>IR#Q|60FngMu9x-dhZ*AglUyBFJFq~46{RG*HZyOoY43Ki~78A9Ssg! z2A7m@0sS;JEv-mGsl@P8%Hx%N=RN1D9gURUnc3MVAavN(7^oX+;$EiHaBzeIA^wra zx$D9uUoaPl@YgP+gt?k_7TT@s?DQb~;Pnq9RhwbyMnZJ}TSFg~C#Y+i**Xj;NU^Z6 zw0C~B7MhI{p|%)GT>>h2VPSy;=L-06PlG81C`Y$I{eWk1h05cU71VwkJj4{g0Pw#c zY(Bh9pNA3!^89N#x%V+KWGGh>%=vQ zV5~MQv_~id9asf9r0oVy$PqAZ0cw8*6OVibAoOr2;Ujnf^cZ-%^MK5?UG8}Y0lK%$ z#sFb#VuC6(03+XM$~nKX(mM0g%V{MoB2;f_aS<#*bC7!wNaYWtQ9E={LqP$sw|u3p zM{Gp?7&0<4SMbPNz#a_~ggiG=Y(@saZj`=Q&CEf0oUr)dzB>NUx%cepdJ3$&tPeT8 zhNi!B-Lo(80uDSh^cLvs-`m@W8Az~dm5w2YhmHtH(%hCa2>ALS*{#=xn5r+%U8L?4 zK=JWYzaY>B>!F^vI$mpjzIfEqK($)sHi%66^(Cr}-@Wus! zQp?k8ClU*$lvYwAfh|9e@}k2tbU%%bv1h5bfL zd;5HPf_q(iJ2q?qJG;k_sYGFcLs_hsVMax_t8@xgj41j10yYDjQk5m)YZ@gZP+5|EO%K?DwUZ-!#FEsUYH zyPFP5qTcb9)z!9=xYRIH%%v3jS{DdyV@^DVVPIsom))X`oC=i*0ZBQ{&7@vWO zs#aki2qiE91qC4G9lmE}r9utgW(}|V{Mob1q=8ooMkll?+%$i@p$9y9;<^vSG0T-c zTDYZ4-3iTa^B!r}T~14V421`zgKSepd;0?dDjI6iw=6cW>mMJB@k4JSTdhn)TYL6( zf|hIcrLn=mu$Gn=K(S7{TQin+}>d>+(s&_Syod&cyJYpqlL46O8A~Bk3DF&%dQ!EE-xFp zUz|CBH~t%(6R2yTAnMeP_i4X$@JAt&Fmq5sS{fIdnAtWmy|_3WToIw->D=5$kX8-4 zVzqk`pP)36pxbexTt=zKg&=1PQUf_c84aIOrZ5nnWyxwiEvS5TsAVl*1&L}Y)oGWX z1s8#Q0dcS29pCv59rF-O8C1ccp`n42A*dHq$Rsm`>!iKV76w`M%jeI+5TRu=2cgnX zSm}P7_uwRr`Q!-gq+GC*_2!%vc-p9q3x{w*XoJevY4J{8s7jE_+yMg=Zev%xfTXZ6 z0`}hC`e;9VH}u|fjr9Jc{uK}+l^5qH`{76hq4Opwu>PTBsZa1Y7uVIj2bg!MXbvpL zZG7Q0xrfw;mNf^pZf_`{kXcROEK?pC)@}=Z7@Rfh?Cg9A|2-Qsb5Ln1xA{crlYdG# z2n^6^;~ddYSC^KRy-}dwDfg1J&TG5mLfeER`nh>Q<6Bt`p$*jMU)MeQCrZm2?vXVSZ;-gr~EZky{5cD1m&Qeq-@nl))dpoXG_qa4J%s4;JWmK&U_Mg(=E3m3+Lb+jmg*J=bB|&= zUBPbHAA|m#xTGWvJ-y%D+}j{Z0SUO;5J{mjLMaMZ)*vox$H!w%PhE@6#+x8ykTbt? ziPXqR2f+?;gdxIf6qkZG6xEc2FI!hvSL$}c2@%eAZAdyp6!Y@s&rwmRY-9vF5qbyk zDQQPkz9?j-Y1X*I_U;9CJg>uMz^G}HF54_5E-?Ke9OJDG=NPPyR5&kT5ry&6 z3%Y!{?q|-M(={^CMIm8*d)W&U|Gc@nzOL>8BjY`O{t0boxM1)P$@v{WL-?aN2%Mjr z3w4^CpBI1ma`u!hUV9kIveN;ItSCZ4MBSwtj34XH`#x0-TH+Vhm^zj28|ep zOATjCAV{HT_$*DqRMYG29vX0WA?$?;gDhHvUX(W6K^&4tGq-c%4s(elRPi^F^B z>gk2RhlA=D6e^-knu>>q=jFbdA>1*r8y-bTE$=%+$vH`XrXVjbD<>xcY73%y<^GT= zvTw^HWY8G(At8c%g_7hAJs~DO&k|5!uXW@k { - test('click on retry button should focus on main', () => runHTMLTest('focusManagement.sendFailedRetry.html')); + test('click on retry button should focus on main', () => + runHTMLTest('focusManagement.sendFailedRetry.html', { ignoreConsoleError: true })); }); diff --git a/__tests__/html/hooks.useCreateAttachmentRenderer.customRender.html b/__tests__/html/hooks.useCreateAttachmentRenderer.customRender.html new file mode 100644 index 0000000000..7440c92743 --- /dev/null +++ b/__tests__/html/hooks.useCreateAttachmentRenderer.customRender.html @@ -0,0 +1,87 @@ + + + + + + + +