@riosst100/pwa-marketplace 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/package.json +1 -1
  2. package/src/componentOverrideMapping.js +5 -1
  3. package/src/components/BecomeSeller/becomeSeller.js +184 -81
  4. package/src/components/BecomeSeller/becomeSeller.module.css +2 -3
  5. package/src/components/BecomeSellerLink/becomeSellerLink.js +45 -0
  6. package/src/components/BecomeSellerLink/becomeSellerLink.module.css +13 -0
  7. package/src/components/BecomeSellerPage/becomeSellerPage.js +9 -13
  8. package/src/components/BecomeSellerPage/becomeSellerPage.module.css +21 -0
  9. package/src/components/SellerAccountPage/index.js +1 -0
  10. package/src/components/SellerAccountPage/sellerAccountPage.js +138 -0
  11. package/src/components/SellerAccountPage/sellerAccountPage.module.css +55 -0
  12. package/src/components/SellerVerification/index.js +1 -0
  13. package/src/components/SellerVerification/sellerVerification.js +198 -0
  14. package/src/components/SellerVerification/sellerVerification.module.css +47 -0
  15. package/src/components/SellerVerificationPage/index.js +1 -0
  16. package/src/components/SellerVerificationPage/sellerVerificationPage.js +43 -0
  17. package/src/components/SellerVerificationPage/sellerVerificationPage.module.css +21 -0
  18. package/src/components/WebsiteSwitcher/websiteSwitcher.js +109 -0
  19. package/src/components/WebsiteSwitcher/websiteSwitcher.module.css +111 -0
  20. package/src/components/WebsiteSwitcher/websiteSwitcher.shimmer.js +6 -0
  21. package/src/components/WebsiteSwitcher/websiteSwitcherItem.js +47 -0
  22. package/src/components/WebsiteSwitcher/websiteSwitcherItem.module.css +20 -0
  23. package/src/intercept.js +40 -37
  24. package/src/overwrites/peregrine/lib/store/actions/user/asyncActions.js +96 -0
  25. package/src/overwrites/peregrine/lib/talons/AccountMenu/useAccountMenuItems.js +65 -0
  26. package/src/overwrites/peregrine/lib/talons/SignIn/signIn.gql.js +56 -0
  27. package/src/overwrites/peregrine/lib/talons/SignIn/useSignIn.js +226 -0
  28. package/src/overwrites/venia-ui/lib/components/Header/header.js +2 -2
  29. package/src/overwrites/venia-ui/lib/components/Header/storeSwitcher.js +2 -2
  30. package/src/talons/BecomeSeller/becomeSeller.gql.js +46 -0
  31. package/src/talons/BecomeSeller/useBecomeSeller.js +146 -0
  32. package/src/talons/BecomeSellerLink/useBecomeSellerLink.js +11 -0
  33. package/src/talons/BecomeSellerPage/useBecomeSellerPage.js +66 -0
  34. package/src/talons/SellerAccountPage/useSellerAccountPage.js +174 -0
  35. package/src/talons/WebsiteByIp/useWebsiteByIp.js +2 -0
  36. package/src/talons/WebsiteSwitcher/useWebsiteSwitcher.js +218 -0
  37. package/src/talons/WebsiteSwitcher/websiteSwitcher.gql.js +45 -0
@@ -0,0 +1,138 @@
1
+ import React, { Fragment, Suspense } from 'react';
2
+ import { shape, string } from 'prop-types';
3
+ import { FormattedMessage, useIntl } from 'react-intl';
4
+
5
+ import { useSellerAccountPage } from '@riosst100/pwa-marketplace/src/talons/SellerAccountPage/useSellerAccountPage';
6
+ import { useStyle } from '@magento/venia-ui/lib/classify';
7
+ // import SellerAccount from '@riosst100/pwa-marketplace/src/components/SellerAccount';
8
+ import { StoreTitle } from '@magento/venia-ui/lib/components/Head';
9
+ import defaultClasses from './sellerAccountPage.module.css';
10
+ import { fullPageLoadingIndicator } from '@magento/venia-ui/lib/components/LoadingIndicator';
11
+ import AccountInformationPageOperations from '@magento/venia-ui/lib/components/AccountInformationPage/accountInformationPage.gql.js';
12
+ import Button from '@magento/venia-ui/lib/components/Button';
13
+
14
+ const SellerAccountPage = props => {
15
+ const classes = useStyle(defaultClasses, props.classes);
16
+ const sellerAccountProps = useSellerAccountPage({
17
+ ...AccountInformationPageOperations
18
+ });
19
+ const {
20
+ handleCancel,
21
+ formErrors,
22
+ handleChangePassword,
23
+ handleSubmit,
24
+ initialValues,
25
+ isDisabled,
26
+ isUpdateMode,
27
+ loadDataError,
28
+ shouldShowNewPassword,
29
+ showUpdateMode,
30
+ recaptchaWidgetProps
31
+ } = sellerAccountProps;
32
+ const { formatMessage } = useIntl();
33
+
34
+ let sellerAccountDetails = null;
35
+ let sellerLoginAccount = null;
36
+ if (!initialValues) {
37
+ return fullPageLoadingIndicator;
38
+ } else {
39
+ const { customer } = initialValues;
40
+ const customerName = `${customer.firstname} ${customer.lastname}`;
41
+ const passwordValue = 'Same as current';
42
+
43
+ sellerAccountDetails = (
44
+ <Fragment>
45
+ <div className={classes.accountDetails}>
46
+ <span className={classes.nameLabel}>
47
+ <FormattedMessage
48
+ id={'global.sellerAccountDetailsText'}
49
+ defaultMessage={'Seller Account Details'}
50
+ />
51
+ </span>
52
+ <div className={classes.lineItemsContainer}>
53
+ <span className={classes.nameLabel}>
54
+ <FormattedMessage
55
+ id={'global.status'}
56
+ defaultMessage={'Status'}
57
+ />
58
+ </span>
59
+ <span className={classes.nameValue}>
60
+ Not Verified
61
+ </span>
62
+ </div>
63
+ </div>
64
+ </Fragment>
65
+ );
66
+
67
+ sellerLoginAccount = (
68
+ <Fragment>
69
+ <div className={classes.accountDetails}>
70
+ <span className={classes.nameLabel}>
71
+ <FormattedMessage
72
+ id={'global.sellerDashboardLoginAccountText'}
73
+ defaultMessage={'Seller Dashboard Login Account'}
74
+ />
75
+ </span>
76
+ <div className={classes.lineItemsContainer}>
77
+ <span className={classes.emailLabel}>
78
+ <FormattedMessage
79
+ id={'global.email'}
80
+ defaultMessage={'Email'}
81
+ />
82
+ </span>
83
+ <span className={classes.emailValue}>
84
+ {customer.email}
85
+ </span>
86
+ <span className={classes.passwordLabel}>
87
+ <FormattedMessage
88
+ id={'global.password'}
89
+ defaultMessage={'Password'}
90
+ />
91
+ </span>
92
+ <span className={classes.passwordValue}>
93
+ {passwordValue}
94
+ </span>
95
+ </div>
96
+ <div className={classes.editButtonContainer}>
97
+ <a href="https://seller-local.tcgcollective.co/lofmarketplace/seller/login/"
98
+ className={classes.editInformationButton}
99
+ >
100
+ <FormattedMessage
101
+ id={'global.sellerDashboardText'}
102
+ defaultMessage={'Seller Dashboard'}
103
+ />
104
+ </a>
105
+ </div>
106
+ </div>
107
+ </Fragment>
108
+ );
109
+ }
110
+
111
+ return (
112
+ <div className={classes.root}>
113
+ <StoreTitle>
114
+ {formatMessage({
115
+ id: 'sellerAccountPage.title',
116
+ defaultMessage: 'Seller Account'
117
+ })}
118
+ </StoreTitle>
119
+ {sellerAccountDetails}
120
+ <br />
121
+ {sellerLoginAccount}
122
+ </div>
123
+ )
124
+ }
125
+
126
+ export default SellerAccountPage;
127
+
128
+ SellerAccountPage.defaultProps = {
129
+ signedInRedirectUrl: '/seller-account',
130
+ signInPageUrl: '/sign-in'
131
+ };
132
+
133
+ SellerAccountPage.propTypes = {
134
+ classes: shape({
135
+ root: string
136
+ }),
137
+ signedInRedirectUrl: string
138
+ };
@@ -0,0 +1,55 @@
1
+ .root {
2
+ composes: grid from global;
3
+ composes: gap-y-md from global;
4
+ composes: px-lg from global;
5
+ composes: py-md from global;
6
+ }
7
+
8
+ .title {
9
+ composes: font-bold from global;
10
+ composes: font-serif from global;
11
+ composes: justify-self-center from global;
12
+ }
13
+
14
+ .accountDetails {
15
+ composes: gap-y-md from global;
16
+ composes: grid from global;
17
+ composes: grid-cols-1 from global;
18
+
19
+ composes: lg_grid-cols-3 from global;
20
+ }
21
+
22
+ .lineItemsContainer {
23
+ composes: gap-3 from global;
24
+ composes: grid from global;
25
+ composes: grid-cols-1 from global;
26
+ composes: leading-normal from global;
27
+ grid-column: 1 / span 1;
28
+
29
+ composes: lg_gap-xs from global;
30
+ composes: lg_grid-cols-2 from global;
31
+ }
32
+
33
+ .lineItemLabel {
34
+ composes: font-bold from global;
35
+ }
36
+
37
+ .nameLabel,
38
+ .emailLabel,
39
+ .passwordLabel {
40
+ composes: font-bold from global;
41
+ }
42
+
43
+ .nameValue,
44
+ .emailValue,
45
+ .passwordValue {
46
+ }
47
+
48
+ .editButtonContainer {
49
+ grid-column: 1 / span 1;
50
+ composes: text-center from global;
51
+ }
52
+
53
+ .editInformationButton {
54
+ composes: root_normalPriority from '@magento/venia-ui/lib/components/Button/button.module.css';
55
+ }
@@ -0,0 +1 @@
1
+ export {default} from './sellerVerification';
@@ -0,0 +1,198 @@
1
+ import React from 'react';
2
+ import { FormattedMessage, useIntl } from 'react-intl';
3
+ import { Form } from 'informed';
4
+ import { func, shape, string, bool } from 'prop-types';
5
+ import { useBecomeSeller } from '@riosst100/pwa-marketplace/src/talons/BecomeSeller/useBecomeSeller';
6
+
7
+ import { useStyle } from '@magento/venia-ui/lib/classify';
8
+ import combine from '@magento/venia-ui/lib/util/combineValidators';
9
+ import {
10
+ hasLengthAtLeast,
11
+ isRequired,
12
+ validatePassword
13
+ } from '@magento/venia-ui/lib/util/formValidators';
14
+ import Button from '@magento/venia-ui/lib/components/Button';
15
+ import Checkbox from '@magento/venia-ui/lib/components/Checkbox';
16
+ import Field from '@magento/venia-ui/lib/components/Field';
17
+ import Select from '@magento/venia-ui/lib/components/Select';
18
+ import TextInput from '@magento/venia-ui/lib/components/TextInput';
19
+ import defaultClasses from './sellerVerification.module.css';
20
+ import FormError from '@magento/venia-ui/lib/components/FormError';
21
+ import Password from '@magento/venia-ui/lib/components/Password';
22
+ import GoogleRecaptcha from '@magento/venia-ui/lib/components/GoogleReCaptcha';
23
+
24
+ const BecomeSeller = props => {
25
+ const talonProps = useBecomeSeller({
26
+ initialValues: props.initialValues,
27
+ onSubmit: props.onSubmit,
28
+ onCancel: props.onCancel
29
+ });
30
+
31
+ const {
32
+ errors,
33
+ handleSubmit,
34
+ handleEnterKeyPress,
35
+ isDisabled,
36
+ initialValues,
37
+ recaptchaWidgetProps
38
+ } = talonProps;
39
+ const { formatMessage } = useIntl();
40
+ const classes = useStyle(defaultClasses, props.classes);
41
+
42
+ const submitButton = (
43
+ <Button
44
+ className={classes.submitButton}
45
+ disabled={isDisabled}
46
+ type="submit"
47
+ priority="high"
48
+ onKeyDown={handleEnterKeyPress}
49
+ data-cy="BecomeSeller-submitButton"
50
+ >
51
+ <FormattedMessage
52
+ id={'sellerVerification.sellerVerificationText'}
53
+ defaultMessage={'Become a Seller'}
54
+ />
55
+ </Button>
56
+ );
57
+
58
+ const sellerTypeOptions = [
59
+ {
60
+ value: "individual",
61
+ label: "Individual"
62
+ },
63
+ {
64
+ value: "company",
65
+ label: "Company"
66
+ }
67
+ ];
68
+
69
+ return (
70
+ <Form
71
+ data-cy="BecomeSeller-form"
72
+ className={classes.root}
73
+ initialValues={initialValues}
74
+ onSubmit={handleSubmit}
75
+ >
76
+ <h2 data-cy="BecomeSeller-title" className={classes.title}>
77
+ <FormattedMessage
78
+ id={'sellerVerification.sellerVerificationText'}
79
+ defaultMessage={'Become a Seller'}
80
+ />
81
+ </h2>
82
+ <FormError errors={Array.from(errors.values())} />
83
+ <Field
84
+ id="sellerType"
85
+ label={formatMessage({
86
+ id: 'sellerVerification.sellerTypeText',
87
+ defaultMessage: 'Seller Type'
88
+ })}
89
+ >
90
+ <Select
91
+ field="seller.seller_type"
92
+ id={classes.root}
93
+ items={sellerTypeOptions}
94
+ />
95
+ </Field>
96
+ <Field
97
+ id="sellerProfileName"
98
+ label={formatMessage({
99
+ id: 'sellerVerification.sellerProfileNameText',
100
+ defaultMessage: 'Seller Profile Name'
101
+ })}
102
+ >
103
+ <TextInput
104
+ id="sellerProfileName"
105
+ field="seller.seller_profile_name"
106
+ validate={isRequired}
107
+ validateOnBlur
108
+ mask={value => value && value.trim()}
109
+ maskOnBlur={true}
110
+ data-cy="seller-profilename"
111
+ aria-label={formatMessage({
112
+ id: 'global.sellerProfileNameRequired',
113
+ defaultMessage: 'Seller Profile Name is required.'
114
+ })}
115
+ />
116
+ </Field>
117
+ <Field
118
+ id="companyName"
119
+ label={formatMessage({
120
+ id: 'sellerVerification.companyNameText',
121
+ defaultMessage: 'Company Name'
122
+ })}
123
+ >
124
+ <TextInput
125
+ id="companyName"
126
+ field="seller.company_name"
127
+ validate={isRequired}
128
+ validateOnBlur
129
+ mask={value => value && value.trim()}
130
+ maskOnBlur={true}
131
+ data-cy="seller-companyname"
132
+ aria-label={formatMessage({
133
+ id: 'global.companyNameRequired',
134
+ defaultMessage: 'Company Name Required'
135
+ })}
136
+ />
137
+ </Field>
138
+ <Field
139
+ id="storeURL"
140
+ label={formatMessage({
141
+ id: 'sellerVerification.storeURLText',
142
+ defaultMessage: 'Store URL'
143
+ })}
144
+ >
145
+ <TextInput
146
+ id="storeUrl"
147
+ field="seller.store_url"
148
+ validate={isRequired}
149
+ validateOnBlur
150
+ mask={value => value && value.trim()}
151
+ maskOnBlur={true}
152
+ data-cy="seller-storeurl"
153
+ aria-label={formatMessage({
154
+ id: 'global.storeUrlRequired',
155
+ defaultMessage: 'Store URL is required.'
156
+ })}
157
+ />
158
+ </Field>
159
+ <div className={classes.subscribe}>
160
+ <Checkbox
161
+ field="become_seller_agreement"
162
+ id="sellerVerificationAgreement"
163
+ label={formatMessage({
164
+ id: 'sellerVerification.sellerVerificationAgreementText',
165
+ defaultMessage: 'I agree the Terms and Condition (Terms and Conditions)'
166
+ })}
167
+ />
168
+ </div>
169
+ <GoogleRecaptcha {...recaptchaWidgetProps} />
170
+ <div className={classes.actions}>
171
+ {submitButton}
172
+ </div>
173
+ </Form>
174
+ );
175
+ };
176
+
177
+ BecomeSeller.propTypes = {
178
+ classes: shape({
179
+ actions: string,
180
+ lead: string,
181
+ root: string,
182
+ subscribe: string
183
+ }),
184
+ initialValues: shape({
185
+ sellerProfileName: string,
186
+ companyName: string
187
+ }),
188
+ isCancelButtonHidden: bool,
189
+ onSubmit: func,
190
+ onCancel: func
191
+ };
192
+
193
+ BecomeSeller.defaultProps = {
194
+ onCancel: () => {},
195
+ isCancelButtonHidden: true
196
+ };
197
+
198
+ export default BecomeSeller;
@@ -0,0 +1,47 @@
1
+ .root {
2
+ composes: gap-xs from global;
3
+ composes: grid from global;
4
+ composes: justify-items-stretch from global;
5
+ composes: px-sm from global;
6
+ composes: py-xs from global;
7
+ }
8
+
9
+ .message {
10
+ composes: bg-subtle from global;
11
+ composes: leading-tight from global;
12
+ composes: p-xs from global;
13
+ composes: rounded from global;
14
+ composes: text-sm from global;
15
+ }
16
+
17
+ /* TODO @TW: cannot compose */
18
+ .message:empty {
19
+ display: none;
20
+ }
21
+
22
+ .actions {
23
+ composes: gap-xs from global;
24
+ composes: grid from global;
25
+ composes: grid-flow-row from global;
26
+ composes: justify-center from global;
27
+ composes: mt-xs from global;
28
+ composes: text-center from global;
29
+
30
+ composes: lg_grid-flow-col from global;
31
+ }
32
+
33
+ .cancelButton {
34
+ composes: root_lowPriority from '@magento/venia-ui/lib/components/Button/button.module.css';
35
+ }
36
+
37
+ .submitButton {
38
+ composes: root_highPriority from '@magento/venia-ui/lib/components/Button/button.module.css';
39
+
40
+ composes: col-start-auto from global;
41
+
42
+ composes: lg_col-start-2 from global;
43
+ }
44
+
45
+ .subscribe {
46
+ composes: -ml-1.5 from global;
47
+ }
@@ -0,0 +1 @@
1
+ export {default} from './sellerVerificationPage';
@@ -0,0 +1,43 @@
1
+ import React from 'react';
2
+ import { shape, string } from 'prop-types';
3
+ import { FormattedMessage, useIntl } from 'react-intl';
4
+
5
+ import { useBecomeSellerPage } from '@riosst100/pwa-marketplace/src/talons/BecomeSellerPage/useBecomeSellerPage';
6
+ import { useStyle } from '@magento/venia-ui/lib/classify';
7
+ import BecomeSeller from '@riosst100/pwa-marketplace/src/components/BecomeSeller';
8
+ import { StoreTitle } from '@magento/venia-ui/lib/components/Head';
9
+ import defaultClasses from './sellerVerificationPage.module.css';
10
+
11
+ const BecomeSellerPage = props => {
12
+ const classes = useStyle(defaultClasses, props.classes);
13
+ const { sellerVerificationProps } = useBecomeSellerPage(props);
14
+ const { formatMessage } = useIntl();
15
+
16
+ return (
17
+ <div className={classes.root}>
18
+ <StoreTitle>
19
+ {formatMessage({
20
+ id: 'sellerVerificationPage.title',
21
+ defaultMessage: 'Become a Seller'
22
+ })}
23
+ </StoreTitle>
24
+ <div className={classes.contentContainer}>
25
+ <BecomeSeller {...sellerVerificationProps} />
26
+ </div>
27
+ </div>
28
+ );
29
+ }
30
+
31
+ export default BecomeSellerPage;
32
+
33
+ BecomeSellerPage.defaultProps = {
34
+ signedInRedirectUrl: '/seller-verification',
35
+ signInPageUrl: '/become-seller'
36
+ };
37
+
38
+ BecomeSellerPage.propTypes = {
39
+ classes: shape({
40
+ root: string
41
+ }),
42
+ signedInRedirectUrl: string
43
+ };
@@ -0,0 +1,21 @@
1
+ .root {
2
+ composes: gap-y-md from global;
3
+ composes: grid from global;
4
+ composes: justify-center from global;
5
+ composes: px-0 from global;
6
+ composes: py-md from global;
7
+ composes: text-center from global;
8
+ grid-template-columns: minmax(auto, 512px);
9
+ }
10
+
11
+ .header {
12
+ composes: font-serif from global;
13
+ }
14
+
15
+ .contentContainer {
16
+ composes: lg_border-2 from global;
17
+ composes: lg_border-solid from global;
18
+ composes: lg_border-subtle from global;
19
+ composes: lg_pb-md from global;
20
+ composes: lg_rounded-md from global;
21
+ }
@@ -0,0 +1,109 @@
1
+ import React from 'react';
2
+ import { shape, string } from 'prop-types';
3
+
4
+ import { useWebsiteSwitcher } from '@riosst100/pwa-marketplace/src/talons/WebsiteSwitcher/useWebsiteSwitcher';
5
+ import { availableRoutes } from '@magento/venia-ui/lib/components/Routes/routes';
6
+
7
+ import { useStyle } from '@magento/venia-ui/lib/classify';
8
+ import defaultClasses from './websiteSwitcher.module.css';
9
+ import WebsiteSwitcherItem from './websiteSwitcherItem';
10
+ import Shimmer from './websiteSwitcher.shimmer';
11
+
12
+ const WebsiteSwitcher = props => {
13
+ const {
14
+ availableStores,
15
+ currentGroupName,
16
+ currentWebsiteName,
17
+ handleSwitchWebsite,
18
+ storeGroups,
19
+ storeMenuRef,
20
+ storeMenuTriggerRef,
21
+ storeMenuIsOpen,
22
+ handleTriggerClick
23
+ } = useWebsiteSwitcher({ availableRoutes });
24
+
25
+ const classes = useStyle(defaultClasses, props.classes);
26
+ const menuClassName = storeMenuIsOpen ? classes.menu_open : classes.menu;
27
+
28
+ if (!availableStores) return <Shimmer />;
29
+
30
+ if (availableStores.size <= 1) return null;
31
+
32
+ const groups = [];
33
+ const hasOnlyOneGroup = storeGroups.size === 1;
34
+
35
+ storeGroups.forEach((group, key) => {
36
+ const stores = [];
37
+ group.forEach(({ storeGroupName, websiteCode, websiteName, isCurrent, storeCode }) => {
38
+ let label = `${websiteName}`;
39
+ stores.push(
40
+ <li
41
+ aria-selected={currentWebsiteName}
42
+ role="option"
43
+ key={storeCode}
44
+ className={classes.menuItem}
45
+ data-cy="WebsiteSwitcher-view"
46
+ >
47
+ <WebsiteSwitcherItem
48
+ active={isCurrent}
49
+ onClick={handleSwitchWebsite}
50
+ option={storeCode}
51
+ option2={websiteCode}
52
+ >
53
+ {label}
54
+ </WebsiteSwitcherItem>
55
+ </li>
56
+ );
57
+ });
58
+
59
+ groups.push(
60
+ <ul
61
+ role="listbox"
62
+ className={classes.groupList}
63
+ key={key}
64
+ data-cy="WebsiteSwitcher-group"
65
+ >
66
+ {stores}
67
+ </ul>
68
+ );
69
+ });
70
+
71
+ let triggerLabel = currentWebsiteName ? `${currentWebsiteName}` : '';
72
+
73
+ return (
74
+ <div className={classes.root} data-cy="WebsiteSwitcher-root">
75
+ <button
76
+ data-cy="WebsiteSwitcher-triggerButton"
77
+ className={classes.trigger}
78
+ aria-label={currentWebsiteName || ''}
79
+ onClick={handleTriggerClick}
80
+ ref={storeMenuTriggerRef}
81
+ data-cy="WebsiteSwitcher-trigger"
82
+ aria-expanded={storeMenuIsOpen}
83
+ >
84
+ {triggerLabel || ''}
85
+ </button>
86
+ <div
87
+ ref={storeMenuRef}
88
+ className={menuClassName}
89
+ data-cy="WebsiteSwitcher-menu"
90
+ >
91
+ <div className={classes.groups}>{groups}</div>
92
+ </div>
93
+ </div>
94
+ );
95
+ };
96
+
97
+ export default WebsiteSwitcher;
98
+
99
+ WebsiteSwitcher.propTypes = {
100
+ classes: shape({
101
+ groupList: string,
102
+ groups: string,
103
+ menu: string,
104
+ menu_open: string,
105
+ menuItem: string,
106
+ root: string,
107
+ trigger: string
108
+ })
109
+ };