@thecb/components 10.12.6 → 11.0.0-beta.0
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.
- package/README.md +14 -6
- package/dist/index.cjs.js +1309 -1481
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +1309 -1482
- package/dist/index.esm.js.map +1 -1
- package/package.json +25 -13
- package/src/.DS_Store +0 -0
- package/src/components/.DS_Store +0 -0
- package/src/components/atoms/.DS_Store +0 -0
- package/src/components/atoms/alert/Alert.mdx +19 -0
- package/src/components/atoms/alert/Alert.stories.js +148 -26
- package/src/components/atoms/badge/Badge.js +2 -2
- package/src/components/atoms/badge/Badge.mdx +27 -0
- package/src/components/atoms/badge/Badge.stories.js +143 -29
- package/src/components/atoms/breadcrumb/Breadcrumb.mdx +21 -0
- package/src/components/atoms/breadcrumb/Breadcrumb.stories.js +38 -29
- package/src/components/atoms/button-with-action/ButtonWithAction.stories.js +108 -55
- package/src/components/atoms/button-with-link/ButtonWithLink.mdx +21 -0
- package/src/components/atoms/button-with-link/ButtonWithLink.stories.js +160 -31
- package/src/components/atoms/card/Card.mdx +41 -0
- package/src/components/atoms/card/Card.stories.js +351 -0
- package/src/components/atoms/checkbox/Checkbox.mdx +15 -0
- package/src/components/atoms/checkbox/Checkbox.oldstories.js +34 -0
- package/src/components/atoms/checkbox/Checkbox.stories.js +140 -25
- package/src/components/atoms/country-dropdown/CountryDropdown.mdx +36 -0
- package/src/components/atoms/country-dropdown/CountryDropdown.stories.js +61 -27
- package/src/components/atoms/detail/Detail.js +0 -26
- package/src/components/atoms/detail/Detail.mdx +32 -0
- package/src/components/atoms/detail/Detail.stories.js +156 -0
- package/src/components/atoms/display-box/DisplayBox.mdx +11 -0
- package/src/components/atoms/display-box/DisplayBox.stories.js +65 -21
- package/src/components/atoms/display-card/DisplayCard.mdx +13 -0
- package/src/components/atoms/display-card/DisplayCard.stories.js +163 -22
- package/src/components/atoms/dropdown/Dropdown.mdx +65 -0
- package/src/components/atoms/dropdown/Dropdown.stories.js +91 -10
- package/src/components/atoms/form-layouts/FormInput.mdx +38 -0
- package/src/components/atoms/form-layouts/FormInput.stories.js +212 -26
- package/src/components/atoms/form-select/FormSelect.mdx +42 -0
- package/src/components/atoms/form-select/FormSelect.stories.js +55 -29
- package/src/components/atoms/formatted-address/FormattedAddress.mdx +13 -0
- package/src/components/atoms/formatted-address/FormattedAddress.stories.js +133 -27
- package/src/components/atoms/formatted-bank-account/FormattedBankAccount.mdx +17 -0
- package/src/components/atoms/formatted-bank-account/FormattedBankAccount.stories.js +57 -0
- package/src/components/atoms/formatted-credit-card/FormattedCreditCard.mdx +40 -0
- package/src/components/atoms/formatted-credit-card/FormattedCreditCard.stories.js +74 -0
- package/src/components/atoms/icons/Icons.mdx +40 -0
- package/src/components/atoms/icons/Icons.stories.js +325 -0
- package/src/components/atoms/labeled-amount/LabeledAmount.mdx +23 -0
- package/src/components/atoms/labeled-amount/LabeledAmount.stories.js +110 -34
- package/src/components/atoms/line-item/LineItem.mdx +28 -0
- package/src/components/atoms/line-item/LineItem.stories.js +89 -22
- package/src/components/atoms/link/Link.mdx +19 -0
- package/src/components/atoms/link/Link.stories.js +155 -49
- package/src/components/atoms/loading/Loading.mdx +13 -0
- package/src/components/atoms/loading/Loading.stories.js +22 -0
- package/src/components/atoms/loading-line/LoadingLine.js +14 -10
- package/src/components/atoms/loading-line/LoadingLine.mdx +15 -0
- package/src/components/atoms/loading-line/LoadingLine.stories.js +132 -28
- package/src/components/atoms/nav-footer/.DS_Store +0 -0
- package/src/components/atoms/nav-footer/NavFooter.mdx +15 -0
- package/src/components/atoms/nav-footer/NavFooter.stories.js +235 -22
- package/src/components/atoms/nav-header/NavHeader.mdx +13 -0
- package/src/components/atoms/nav-header/NavHeader.stories.js +122 -21
- package/src/components/atoms/nav-tabs/NavTabs.mdx +30 -0
- package/src/components/atoms/nav-tabs/NavTabs.stories.js +49 -0
- package/src/components/atoms/password-requirements/PasswordRequirements.mdx +39 -0
- package/src/components/atoms/password-requirements/PasswordRequirements.stories.js +108 -44
- package/src/components/atoms/placeholder/Placeholder.mdx +19 -0
- package/src/components/atoms/placeholder/Placeholder.stories.js +164 -36
- package/src/components/atoms/searchable-select/SearchableSelect.mdx +44 -0
- package/src/components/atoms/searchable-select/SearchableSelect.stories.js +103 -28
- package/src/components/atoms/state-province-dropdown/StateProvinceDropdown.mdx +36 -0
- package/src/components/atoms/state-province-dropdown/StateProvinceDropdown.stories.js +65 -40
- package/src/components/atoms/table/Table.mdx +71 -0
- package/src/components/atoms/table/Table.oldstories.js +84 -0
- package/src/components/atoms/table/Table.stories.js +59 -75
- package/src/components/atoms/table/TableRow.js +1 -0
- package/src/components/atoms/title/Title.js +0 -23
- package/src/components/atoms/title/Title.mdx +26 -0
- package/src/components/atoms/title/Title.stories.js +144 -0
- package/src/components/atoms/toggle-switch/ToggleSwitch.mdx +17 -0
- package/src/components/atoms/toggle-switch/ToggleSwitch.stories.js +103 -20
- package/src/components/atoms/toggle-switch/ToggleSwitch.theme.js +8 -5
- package/src/components/atoms/typeahead-input/TypeaheadInput.mdx +13 -0
- package/src/components/atoms/typeahead-input/TypeaheadInput.stories.js +63 -0
- package/src/components/molecules/.DS_Store +0 -0
- package/src/components/molecules/address-form/AddressForm.mdx +18 -0
- package/src/components/molecules/address-form/AddressForm.stories.js +223 -20
- package/src/components/molecules/banner/Banner.mdx +23 -0
- package/src/components/molecules/banner/Banner.stories.js +122 -26
- package/src/components/molecules/change-password-form/ChangePasswordForm.mdx +15 -0
- package/src/components/molecules/change-password-form/ChangePasswordForm.stories.js +203 -19
- package/src/components/molecules/collapsible-section/CollapsibleSection.mdx +15 -0
- package/src/components/molecules/collapsible-section/CollapsibleSection.stories.js +210 -61
- package/src/components/molecules/edit-name-form/EditNameForm.mdx +13 -0
- package/src/components/molecules/edit-name-form/EditNameForm.stories.js +117 -0
- package/src/components/molecules/idle-modal/IdleModal.js +101 -0
- package/src/components/molecules/idle-modal/IdleModal.mdx +17 -0
- package/src/components/molecules/idle-modal/IdleModal.stories.js +180 -0
- package/src/components/molecules/idle-modal/index.d.ts +16 -0
- package/src/components/molecules/idle-modal/index.js +3 -0
- package/src/components/molecules/index.js +1 -0
- package/src/components/molecules/link-card/LinkCard.mdx +17 -0
- package/src/components/molecules/link-card/LinkCard.stories.js +287 -72
- package/src/components/molecules/login-form/LoginForm.mdx +16 -0
- package/src/components/molecules/login-form/LoginForm.stories.js +117 -21
- package/src/components/molecules/modal/Modal.mdx +17 -0
- package/src/components/molecules/modal/Modal.stories.js +342 -128
- package/src/components/molecules/module/Module.mdx +17 -0
- package/src/components/molecules/module/Module.stories.js +267 -25
- package/src/components/molecules/obligation/.DS_Store +0 -0
- package/src/components/molecules/obligation/Obligation.mdx +23 -0
- package/src/components/molecules/obligation/Obligation.stories.js +460 -0
- package/src/components/molecules/obligation/icons/PropertyPersonalIcon.js +1 -1
- package/src/components/molecules/pagination/Pagination.mdx +15 -0
- package/src/components/molecules/pagination/Pagination.stories.js +177 -28
- package/src/components/molecules/popover/Popover.mdx +15 -0
- package/src/components/molecules/popover/Popover.stories.js +220 -0
- package/src/components/molecules/tabs/Tabs.mdx +17 -0
- package/src/components/molecules/tabs/Tabs.stories.js +135 -227
- package/src/components/molecules/toast-notification/Toast.mdx +15 -0
- package/src/components/molecules/toast-notification/Toast.stories.js +183 -0
- package/src/util/idleTimerUtils.js +36 -0
- package/src/util/index.js +3 -1
- package/src/components/molecules/edit-name-form/EdidNameForm.stories.js +0 -24
- package/src/components/molecules/toast-notification/ToastNotification.stories.js +0 -105
- /package/src/components/atoms/add-obligation/{AddObligation.stories.js → AddObligation.oldstories.js} +0 -0
- /package/src/components/atoms/amount-callout/{AmountCallout.stories.js → AmountCallout.oldstories.js} +0 -0
- /package/src/components/atoms/checkbox-list/{CheckboxList.stories.js → CheckboxList.oldstories.js} +0 -0
- /package/src/components/atoms/form-layouts/{FormLayouts.stories.js → FormLayouts.oldstories.js} +0 -0
- /package/src/components/atoms/hamburger-button/{HamburgerButton.stories.js → HamburgerButton.oldstories.js} +0 -0
- /package/src/components/atoms/heading/{Heading.stories.js → Heading.oldstories.js} +0 -0
- /package/src/components/atoms/icons/{icons.stories.js → icons.oldstories.js} +0 -0
- /package/src/components/atoms/layouts/examples/box-example/{BoxExample.stories.js → BoxExample.oldstories.js} +0 -0
- /package/src/components/atoms/layouts/examples/center-example/{CenterExample.stories.js → CenterExample.oldstories.js} +0 -0
- /package/src/components/atoms/layouts/examples/cluster-example/{ClusterExample.stories.js → ClusterExample.oldstories.js} +0 -0
- /package/src/components/atoms/layouts/examples/cover-example/{CoverExample.stories.js → CoverExample.oldstories.js} +0 -0
- /package/src/components/atoms/layouts/examples/frame-example/{FrameExample.stories.js → FrameExample.oldstories.js} +0 -0
- /package/src/components/atoms/layouts/examples/grid-example/{GridExample.stories.js → GridExample.oldstories.js} +0 -0
- /package/src/components/atoms/layouts/examples/imposter-example/{ImposterExample.stories.js → ImposterExample.oldstories.js} +0 -0
- /package/src/components/atoms/layouts/examples/motion-example/{MotionExample.stories.js → MotionExample.oldstories.js} +0 -0
- /package/src/components/atoms/layouts/examples/reel-example/{ReelExample.stories.js → ReelExample.oldstories.js} +0 -0
- /package/src/components/atoms/layouts/examples/sidebar-example/{SidebarExample.stories.js → SidebarExample.oldstories.js} +0 -0
- /package/src/components/atoms/layouts/examples/stack-example/{StackExample.stories.js → StackExample.oldstories.js} +0 -0
- /package/src/components/atoms/layouts/examples/switcher-example/{SwitcherExample.stories.js → SwitcherExample.oldstories.js} +0 -0
- /package/src/components/atoms/paragraph/{Paragraph.stories.js → Paragraph.oldstories.js} +0 -0
- /package/src/components/atoms/processing-fee/{ProcessingFee.stories.js → ProcessingFee.oldstories.js} +0 -0
- /package/src/components/atoms/search/{Search.stories.js → Search.oldstories.js} +0 -0
- /package/src/components/atoms/solid-divider/{SolidDivider.stories.js → SolidDivider.oldstories.js} +0 -0
- /package/src/components/atoms/sortable-table-heading/{SortableTableHeading.stories.js → SortableTableHeading.oldstories.js} +0 -0
- /package/src/components/atoms/spinner/{Spinner.stories.js → Spinner.oldstories.js} +0 -0
- /package/src/components/atoms/tab/{Tab.stories.js → Tab.oldstories.js} +0 -0
- /package/src/components/atoms/text/{Text.stories.js → Text.oldstories.js} +0 -0
- /package/src/components/atoms/typeahead-input/{TypeaheadIinput.stories.js → TypeaheadIinput.oldstories.js} +0 -0
- /package/src/components/atoms/wallet-name/{WalletName.stories.js → WalletName.oldstories.js} +0 -0
- /package/src/components/molecules/account-and-routing-modal/{AccountAndRoutingModal.stories.js → AccountAndRoutingModal.oldstories.js} +0 -0
- /package/src/components/molecules/editable-list/{EditableList.stories.js → EditableList.oldstories.js} +0 -0
- /package/src/components/molecules/email-form/{EmailForm.stories.js → EmailForm.oldstories.js} +0 -0
- /package/src/components/molecules/forgot-password-form/{ForgotPasswordForm.stories.js → ForgotPasswordForm.oldstories.js} +0 -0
- /package/src/components/molecules/highlight-tab-row/{HighlightTabRow.stories.js → HighlightTabRow.oldstories.js} +0 -0
- /package/src/components/molecules/multiple-select-filter/{MultipleSelectFilter.stories.js → MultipleSelectFilter.oldstories.js} +0 -0
- /package/src/components/molecules/obligation/modules/{AmountModule.stories.js → AmountModule.oldstories.js} +0 -0
- /package/src/components/molecules/payment-button-bar/{PaymentButtonBar.stories.js → PaymentButtonBar.oldstories.js} +0 -0
- /package/src/components/molecules/payment-details/{PaymentDetails.stories.js → PaymentDetails.oldstories.js} +0 -0
- /package/src/components/molecules/payment-form-ach/{PaymentFormACH.stories.js → PaymentFormACH.oldstories.js} +0 -0
- /package/src/components/molecules/payment-form-card/{PaymentFormCard.stories.js → PaymentFormCard.oldstories.js} +0 -0
- /package/src/components/molecules/periscope-dashboard-iframe/{PeriscopeDashBoardIframe.stories.js → PeriscopeDashBoardIframe.oldstories.js} +0 -0
- /package/src/components/molecules/phone-form/{PhoneForm.stories.js → PhoneForm.oldstories.js} +0 -0
- /package/src/components/molecules/popup-menu/{PopupMenu.stories.js → PopupMenu.oldstories.js} +0 -0
- /package/src/components/molecules/radio-group/{RadioGroup.stories.js → RadioGroup.oldstories.js} +0 -0
- /package/src/components/molecules/radio-section/{RadioSection.stories.js → RadioSection.oldstories.js} +0 -0
- /package/src/components/molecules/registration-form/{RegistrationForm.stories.js → RegistrationForm.oldstories.js} +0 -0
- /package/src/components/molecules/reset-confirmation-form/{ResetConfirmationForm.stories.js → ResetConfirmationForm.oldstories.js} +0 -0
- /package/src/components/molecules/reset-password-form/{ResetPasswordForm.stories.js → ResetPasswordForm.oldstories.js} +0 -0
- /package/src/components/molecules/reset-password-success/{ResetPasswordSuccess.stories.js → ResetPasswordSuccess.oldstories.js} +0 -0
- /package/src/components/molecules/tab-sidebar/{TabSidebar.stories.js → TabSidebar.oldstories.js} +0 -0
- /package/src/components/molecules/terms-and-conditions/{TermsAndConditions.stories.js → TermsAndConditions.oldstories.js} +0 -0
- /package/src/components/molecules/terms-and-conditions-modal/{TermsAndConditionsModal.stories.js → TermsAndConditionsModal.oldstories.js} +0 -0
- /package/src/components/molecules/workflow-tile/{WorkflowTile.stories.js → WorkflowTile.oldstories.js} +0 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { Box, Cluster } from "../layouts";
|
|
3
|
+
import { FormInput, FormContainer, FormInputColumn } from "../form-layouts";
|
|
3
4
|
import PasswordRequirements from "./PasswordRequirements";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import page from "../../../../.storybook/page";
|
|
7
|
-
import { connect } from "react-redux";
|
|
5
|
+
import { connect, Provider } from "react-redux";
|
|
6
|
+
import { createStore } from "redux";
|
|
8
7
|
import {
|
|
9
8
|
createFormState,
|
|
10
9
|
required,
|
|
@@ -12,10 +11,11 @@ import {
|
|
|
12
11
|
hasNumber,
|
|
13
12
|
hasLowercaseLetter,
|
|
14
13
|
hasUppercaseLetter,
|
|
15
|
-
hasSpecialCharacter
|
|
14
|
+
hasSpecialCharacter,
|
|
15
|
+
matchesField
|
|
16
16
|
} from "redux-freeform";
|
|
17
17
|
|
|
18
|
-
const
|
|
18
|
+
const { mapStateToProps, mapDispatchToProps, reducer } = createFormState({
|
|
19
19
|
password: {
|
|
20
20
|
validators: [
|
|
21
21
|
required(),
|
|
@@ -25,51 +25,115 @@ const formConfig = {
|
|
|
25
25
|
hasUppercaseLetter(),
|
|
26
26
|
hasSpecialCharacter()
|
|
27
27
|
]
|
|
28
|
+
},
|
|
29
|
+
confirmPassword: {
|
|
30
|
+
validators: [required(), matchesField("password")]
|
|
28
31
|
}
|
|
29
|
-
};
|
|
32
|
+
});
|
|
30
33
|
|
|
31
|
-
const
|
|
34
|
+
const store = createStore(
|
|
35
|
+
reducer,
|
|
36
|
+
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
|
|
37
|
+
);
|
|
32
38
|
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
const passwordErrorMessages = {
|
|
40
|
+
[required.error]: "Password field is required.",
|
|
41
|
+
[hasLength.error]: "Your password must have at least 8 characters",
|
|
42
|
+
[hasNumber.error]: "Your password must contain at least one number",
|
|
43
|
+
[hasLowercaseLetter.error]:
|
|
44
|
+
"Your password must contain at least one lowercase letter",
|
|
45
|
+
[hasUppercaseLetter.error]:
|
|
46
|
+
"Your password must contain at least one uppercase letter",
|
|
47
|
+
[hasSpecialCharacter.error]:
|
|
48
|
+
"Your password must contain at least one special character (!@#$%^&*.?)"
|
|
49
|
+
};
|
|
50
|
+
const confirmPasswordErrorMessages = {
|
|
51
|
+
[matchesField.error]: "Confirm password must match your password"
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const FormWrapper = props => (
|
|
55
|
+
<FormContainer
|
|
56
|
+
role="form"
|
|
57
|
+
aria-label="Change password"
|
|
58
|
+
extraStyles={`padding: 0;`}
|
|
59
|
+
>
|
|
60
|
+
<FormInputColumn>
|
|
47
61
|
<FormInput
|
|
48
|
-
labelTextWhenNoError="
|
|
62
|
+
labelTextWhenNoError="Password"
|
|
49
63
|
errorMessages={passwordErrorMessages}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
64
|
+
type="password"
|
|
65
|
+
field={props.fields.password}
|
|
66
|
+
fieldActions={props.actions.fields.password}
|
|
67
|
+
/>
|
|
68
|
+
<FormInput
|
|
69
|
+
labelTextWhenNoError="Confirm Password"
|
|
70
|
+
errorMessages={confirmPasswordErrorMessages}
|
|
71
|
+
type="password"
|
|
72
|
+
field={props.fields.confirmPassword}
|
|
73
|
+
fieldActions={props.actions.fields.confirmPassword}
|
|
53
74
|
/>
|
|
54
|
-
|
|
75
|
+
</FormInputColumn>
|
|
76
|
+
<Box padding={props.isMobile ? "1rem 0 0" : "1.5rem 0 0"}>
|
|
77
|
+
<Cluster justify="center" align="center">
|
|
78
|
+
<PasswordRequirements
|
|
79
|
+
isMobile={props.isMobile}
|
|
80
|
+
password={props.fields.password}
|
|
81
|
+
/>
|
|
82
|
+
</Cluster>
|
|
55
83
|
</Box>
|
|
56
|
-
|
|
57
|
-
|
|
84
|
+
</FormContainer>
|
|
85
|
+
);
|
|
58
86
|
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
mapStateToProps: passwordForm.mapStateToProps,
|
|
64
|
-
mapDispatchToProps: passwordForm.mapDispatchToProps
|
|
65
|
-
});
|
|
66
|
-
export default story;
|
|
87
|
+
const ConnectedPasswordRequirements = connect(
|
|
88
|
+
mapStateToProps,
|
|
89
|
+
mapDispatchToProps
|
|
90
|
+
)(FormWrapper);
|
|
67
91
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
92
|
+
export default {
|
|
93
|
+
title: "Atoms/PasswordRequirements",
|
|
94
|
+
component: ConnectedPasswordRequirements,
|
|
95
|
+
tags: ["!autodocs"],
|
|
96
|
+
parameters: {
|
|
97
|
+
layout: "centered",
|
|
98
|
+
controls: { expanded: true }
|
|
99
|
+
},
|
|
100
|
+
args: {
|
|
101
|
+
password: undefined,
|
|
102
|
+
isMobile: false
|
|
103
|
+
},
|
|
104
|
+
argTypes: {
|
|
105
|
+
password: {
|
|
106
|
+
description: "A Redux Freeform field for a password",
|
|
107
|
+
table: {
|
|
108
|
+
type: { summary: "Redux Freeform field object" },
|
|
109
|
+
defaultValue: { summary: undefined }
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
isMobile: {
|
|
113
|
+
description:
|
|
114
|
+
"Whether user is on a mobile device (typically screen size <768px)",
|
|
115
|
+
table: {
|
|
116
|
+
type: { summary: "boolean" },
|
|
117
|
+
defaultValue: { summary: false }
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
decorators: [
|
|
122
|
+
Story => (
|
|
123
|
+
<Provider store={store}>
|
|
124
|
+
<Story />
|
|
125
|
+
</Provider>
|
|
126
|
+
)
|
|
127
|
+
]
|
|
128
|
+
};
|
|
72
129
|
|
|
73
|
-
export const
|
|
74
|
-
<
|
|
130
|
+
export const BasicPasswordRequirements = args => (
|
|
131
|
+
<ConnectedPasswordRequirements {...args} />
|
|
75
132
|
);
|
|
133
|
+
|
|
134
|
+
export const MobilePasswordRequirements = {
|
|
135
|
+
args: {
|
|
136
|
+
isMobile: true
|
|
137
|
+
},
|
|
138
|
+
render: args => <ConnectedPasswordRequirements {...args} />
|
|
139
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Canvas, Meta, Title, Story, Controls } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
import * as PlaceholderStories from './Placeholder.stories.js';
|
|
4
|
+
|
|
5
|
+
<Meta of={PlaceholderStories} />
|
|
6
|
+
|
|
7
|
+
<Title />
|
|
8
|
+
|
|
9
|
+
The Placeholder component is a component that is used to occupy space that would normally contain some sort of data, like user accounts or payment methods. When the data is in an empty state, the Placeholder can be rendered to inform the user about what content would normally appear, and provide the user with an opportunity to take an action or visit a destination. If the action is unavailable, a Placeholder can be set to a disabled state.
|
|
10
|
+
|
|
11
|
+
Placeholders come with two variants: default and large. The default variant uses only text and a generic plus icon, while the large variant displays text and an icon specific to the Placeholder's use. Currently large Placeholders are only used in NFE in the following varieties: accounts, properties, and payments. New types of large Placeholders can be added by updating the large icons function inside of the Placeholder component.
|
|
12
|
+
|
|
13
|
+
The Placeholder uses flexbox styling and takes its width from its parent container.
|
|
14
|
+
|
|
15
|
+
<Controls />
|
|
16
|
+
|
|
17
|
+
<div style={{ marginBottom: "2em"}}>
|
|
18
|
+
<Story />
|
|
19
|
+
</div>
|
|
@@ -1,42 +1,170 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { boolean, text, select } from "@storybook/addon-knobs";
|
|
3
1
|
import Placeholder from "./Placeholder";
|
|
4
|
-
import
|
|
2
|
+
import { Box } from "../layouts";
|
|
5
3
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
const meta = {
|
|
5
|
+
title: "Atoms/Placeholder",
|
|
6
|
+
component: Placeholder,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: "centered"
|
|
9
|
+
},
|
|
10
|
+
tags: ["!autodocs"],
|
|
11
|
+
args: {
|
|
12
|
+
text: "Add an Account",
|
|
13
|
+
action: undefined,
|
|
14
|
+
visible: true,
|
|
15
|
+
isLink: false,
|
|
16
|
+
destination: "/",
|
|
17
|
+
variant: undefined,
|
|
18
|
+
largeIcon: undefined,
|
|
19
|
+
isDisabled: false
|
|
20
|
+
},
|
|
21
|
+
argTypes: {
|
|
22
|
+
text: {
|
|
23
|
+
description: "Text to be displayed inside the Placeholder",
|
|
24
|
+
table: {
|
|
25
|
+
type: { summary: "string" },
|
|
26
|
+
defaultValue: { summary: undefined }
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
action: {
|
|
30
|
+
description:
|
|
31
|
+
"Function to execute when clicking on Placeholder. Only used if isLink is false.",
|
|
32
|
+
table: {
|
|
33
|
+
type: { summary: "function" },
|
|
34
|
+
defaultValue: { summary: undefined }
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
visible: {
|
|
38
|
+
description: "Whether the Placeholder is visible",
|
|
39
|
+
table: {
|
|
40
|
+
type: { summary: "boolean" },
|
|
41
|
+
defaultValue: { summary: true }
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
isLink: {
|
|
45
|
+
description:
|
|
46
|
+
"Whether the Placeholder links to a destination, instead of using an action",
|
|
47
|
+
table: {
|
|
48
|
+
type: { summary: "boolean" },
|
|
49
|
+
defaultValue: { summary: false }
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
variant: {
|
|
53
|
+
description: "Variant of the Placeholder either `default` or `large`.",
|
|
54
|
+
table: {
|
|
55
|
+
type: { summary: "string" },
|
|
56
|
+
defaultValue: { summary: "default" }
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
largeIcon: {
|
|
60
|
+
description:
|
|
61
|
+
"Name of icon to use with 'large' Placeholder variant. One of 'accounts', 'properties', or 'payments'. If not provided and Placeholder variant is set to large, will default to 'accounts'."
|
|
62
|
+
},
|
|
63
|
+
table: {
|
|
64
|
+
type: { summary: "string" },
|
|
65
|
+
defaultValue: { summary: "accounts" }
|
|
66
|
+
},
|
|
67
|
+
destination: {
|
|
68
|
+
description:
|
|
69
|
+
"URL for Placeholder to navigate to if it is a link. Only used if isLink is true.",
|
|
70
|
+
table: {
|
|
71
|
+
type: { summary: "string" },
|
|
72
|
+
defaultValue: { summary: undefined }
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
isDisabled: {
|
|
76
|
+
description: "Whether the Placeholder is disabled",
|
|
77
|
+
table: {
|
|
78
|
+
type: { summary: "boolean" },
|
|
79
|
+
defaultValue: { summary: false }
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
10
83
|
};
|
|
11
|
-
const defaultValue = "default";
|
|
12
|
-
const groupId = "props";
|
|
13
84
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
85
|
+
export default meta;
|
|
86
|
+
|
|
87
|
+
export const DefaultPlaceholder = {
|
|
88
|
+
args: {
|
|
89
|
+
action: () => {},
|
|
90
|
+
variant: "default"
|
|
91
|
+
},
|
|
92
|
+
render: args => (
|
|
93
|
+
<Box minWidth="400px">
|
|
94
|
+
<Placeholder {...args} />
|
|
95
|
+
</Box>
|
|
96
|
+
)
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const LinkPlaceholder = {
|
|
100
|
+
args: {
|
|
101
|
+
text: "Add an Email Address",
|
|
102
|
+
variant: "default",
|
|
103
|
+
isLink: true,
|
|
104
|
+
destination: "/"
|
|
105
|
+
},
|
|
106
|
+
render: args => (
|
|
107
|
+
<Box minWidth="400px">
|
|
108
|
+
<Placeholder {...args} />
|
|
109
|
+
</Box>
|
|
110
|
+
)
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export const LargePlaceholder = {
|
|
114
|
+
args: {
|
|
115
|
+
text: "Add or Edit Your Payment Methods",
|
|
116
|
+
variant: "large",
|
|
117
|
+
largeIcon: "payments",
|
|
118
|
+
action: () => {}
|
|
119
|
+
},
|
|
120
|
+
render: args => (
|
|
121
|
+
<Box minWidth="650px">
|
|
122
|
+
<Placeholder {...args} />
|
|
123
|
+
</Box>
|
|
124
|
+
)
|
|
18
125
|
};
|
|
19
126
|
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
127
|
+
export const LargeLinkPlaceholder = {
|
|
128
|
+
args: {
|
|
129
|
+
text: "Add New Property",
|
|
130
|
+
variant: "large",
|
|
131
|
+
largeIcon: "properties",
|
|
132
|
+
isLink: true,
|
|
133
|
+
destination: "/"
|
|
134
|
+
},
|
|
135
|
+
render: args => (
|
|
136
|
+
<Box minWidth="650px">
|
|
137
|
+
<Placeholder {...args} />
|
|
138
|
+
</Box>
|
|
139
|
+
)
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
export const DisabledPlaceholder = {
|
|
143
|
+
args: {
|
|
144
|
+
text: "Edit Payment Information",
|
|
145
|
+
action: () => {},
|
|
146
|
+
variant: "default",
|
|
147
|
+
isDisabled: true,
|
|
148
|
+
destination: "/"
|
|
149
|
+
},
|
|
150
|
+
render: args => (
|
|
151
|
+
<Box minWidth="400px">
|
|
152
|
+
<Placeholder {...args} />
|
|
153
|
+
</Box>
|
|
154
|
+
)
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
export const DisabledLargePlaceholder = {
|
|
158
|
+
args: {
|
|
159
|
+
text: "Add More to Cart",
|
|
160
|
+
variant: "large",
|
|
161
|
+
isLink: true,
|
|
162
|
+
isDisabled: true,
|
|
163
|
+
destination: "/"
|
|
164
|
+
},
|
|
165
|
+
render: args => (
|
|
166
|
+
<Box minWidth="650px">
|
|
167
|
+
<Placeholder {...args} />
|
|
168
|
+
</Box>
|
|
169
|
+
)
|
|
170
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Canvas, Meta, Title, Story, Controls } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
import * as SearchableSelectStories from './SearchableSelect.stories.js';
|
|
4
|
+
|
|
5
|
+
<Meta of={SearchableSelectStories} />
|
|
6
|
+
|
|
7
|
+
<Title />
|
|
8
|
+
|
|
9
|
+
SearchableSelect creates a list of checkboxes from an array of options that is filterable through an input.
|
|
10
|
+
|
|
11
|
+
## Notes
|
|
12
|
+
|
|
13
|
+
- the `items` array will be sorted by the `name` property
|
|
14
|
+
- a `SELECT_ALL` constant is also exported by SearchableSelect
|
|
15
|
+
- if an item with a name matching `SELECT_ALL` is included in `items` it will be rendered to the top
|
|
16
|
+
- filtering through the input is _always_ case-insensitive
|
|
17
|
+
|
|
18
|
+
## Form Integration
|
|
19
|
+
|
|
20
|
+
SearchableSelect requires a `fields` and `actions` prop. Both are objects that _can_ be generated with [redux-freeform](https://github.com/CityBaseInc/redux-freeform).
|
|
21
|
+
|
|
22
|
+
Unlike other similar form components where the specific `field` and `fieldActions` for one field are passed as props, SearchableSelect expect the `fields` and `fieldActions` from the entire form to be passed, with a field named `searchTerm`. Below are example values for each prop with the minimum properties needed for a FormSelect component.
|
|
23
|
+
|
|
24
|
+
### fields
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
{
|
|
28
|
+
searchTerm: {
|
|
29
|
+
"rawValue": ""
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### actions
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
{
|
|
38
|
+
searchTerm: {
|
|
39
|
+
set: (value) => {...}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`actions.searchTerm.set()` is used to to update the filter term in the input.
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import { connect } from "react-redux";
|
|
3
|
-
import { text } from "@storybook/addon-knobs";
|
|
4
|
-
import { createFormState } from "redux-freeform";
|
|
5
|
-
|
|
1
|
+
import React from "react";
|
|
6
2
|
import SearchableSelect, { SELECT_ALL } from "./SearchableSelect";
|
|
7
|
-
import
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { connect, Provider } from "react-redux";
|
|
5
|
+
import { createStore } from "redux";
|
|
6
|
+
import { createFormState } from "redux-freeform";
|
|
8
7
|
|
|
9
8
|
const { mapStateToProps, mapDispatchToProps, reducer } = createFormState({
|
|
10
9
|
searchTerm: {
|
|
@@ -12,51 +11,127 @@ const { mapStateToProps, mapDispatchToProps, reducer } = createFormState({
|
|
|
12
11
|
}
|
|
13
12
|
});
|
|
14
13
|
|
|
14
|
+
const store = createStore(
|
|
15
|
+
reducer,
|
|
16
|
+
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const selectAllItem = { name: SELECT_ALL, value: SELECT_ALL };
|
|
20
|
+
|
|
15
21
|
const items = [
|
|
16
22
|
{ name: "Foo", value: "foo-value" },
|
|
17
23
|
{ name: "Baz", value: "baz-value" },
|
|
18
|
-
|
|
24
|
+
selectAllItem,
|
|
19
25
|
{ name: "Bar", value: "bar-value" }
|
|
20
26
|
];
|
|
21
27
|
|
|
22
28
|
const FormWrapper = props => {
|
|
23
29
|
const [selectedItems, setSelectedItems] = useState(props.selectedItems || []);
|
|
24
|
-
const selectValues = items => items.map(item => item.value);
|
|
25
30
|
|
|
26
|
-
const selectItem =
|
|
27
|
-
if (
|
|
28
|
-
const
|
|
29
|
-
|
|
31
|
+
const selectItem = selection => {
|
|
32
|
+
if (selectedItems.find(l => l.value === selection.value)) {
|
|
33
|
+
const filtered = selectedItems.filter(
|
|
34
|
+
l => l.value !== selection.value && l.value !== SELECT_ALL
|
|
30
35
|
);
|
|
31
|
-
setSelectedItems(
|
|
36
|
+
setSelectedItems(filtered);
|
|
37
|
+
} else {
|
|
38
|
+
if (selectedItems.length + 1 === items.length - 1) {
|
|
39
|
+
setSelectedItems([...selectedItems, selection, selectAllItem]);
|
|
40
|
+
} else {
|
|
41
|
+
setSelectedItems([...selectedItems, selection]);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const toggleSelectAllItems = selectAll => {
|
|
47
|
+
if (selectAll) {
|
|
48
|
+
setSelectedItems(items);
|
|
32
49
|
} else {
|
|
33
|
-
|
|
34
|
-
setSelectedItems(moreItems);
|
|
50
|
+
setSelectedItems([]);
|
|
35
51
|
}
|
|
36
52
|
};
|
|
37
53
|
|
|
54
|
+
const allSelected = selectedItems.length === items.length ?? false;
|
|
55
|
+
|
|
38
56
|
return (
|
|
39
57
|
<SearchableSelect
|
|
58
|
+
{...props}
|
|
40
59
|
autocompleteValue={props.autocompleteValue}
|
|
41
|
-
items={items}
|
|
60
|
+
items={props.items}
|
|
61
|
+
selectedItems={selectedItems}
|
|
62
|
+
selectItem={selectItem}
|
|
42
63
|
fields={props.fields}
|
|
43
64
|
actions={props.actions}
|
|
44
|
-
|
|
45
|
-
|
|
65
|
+
allSelected={allSelected}
|
|
66
|
+
toggleSelectAllItems={toggleSelectAllItems}
|
|
46
67
|
/>
|
|
47
68
|
);
|
|
48
69
|
};
|
|
49
70
|
|
|
50
|
-
const
|
|
51
|
-
title: "Components|Atoms/SearchableSelect",
|
|
52
|
-
Component: SearchableSelect,
|
|
53
|
-
reducer,
|
|
71
|
+
const ConnectedSearchableSelect = connect(
|
|
54
72
|
mapStateToProps,
|
|
55
73
|
mapDispatchToProps
|
|
56
|
-
|
|
74
|
+
)(FormWrapper);
|
|
57
75
|
|
|
58
|
-
export default
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
76
|
+
export default {
|
|
77
|
+
title: "Atoms/SearchableSelect",
|
|
78
|
+
component: ConnectedSearchableSelect,
|
|
79
|
+
tags: ["!autodocs"],
|
|
80
|
+
parameters: {
|
|
81
|
+
controls: { expanded: true }
|
|
82
|
+
},
|
|
83
|
+
args: {
|
|
84
|
+
autocompleteValue: undefined,
|
|
85
|
+
items: items,
|
|
86
|
+
disabled: false,
|
|
87
|
+
themeValues: {},
|
|
88
|
+
placeholder: "Search agencies"
|
|
89
|
+
},
|
|
90
|
+
argTypes: {
|
|
91
|
+
fieldActions: { type: "object" },
|
|
92
|
+
field: { type: "object" },
|
|
93
|
+
selectedItems: {
|
|
94
|
+
description: "Array of objects representing the selected items.",
|
|
95
|
+
table: {
|
|
96
|
+
type: { summary: "array" }
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
selectItem: {
|
|
100
|
+
description:
|
|
101
|
+
"Function that will be called when a non-`SELECT_ALL` checkbox is changed.",
|
|
102
|
+
table: {
|
|
103
|
+
type: { summary: "array" }
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
allSelected: {
|
|
107
|
+
description:
|
|
108
|
+
"Whether all all items are selected or not. This affects what parameter `toggleSelectAllItems` is called with",
|
|
109
|
+
table: {
|
|
110
|
+
type: { summary: "boolean" }
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
toggleSelectAllItems: {
|
|
114
|
+
description:
|
|
115
|
+
"Function called when a checkbox with the name `SELECT_ALL` is changed.",
|
|
116
|
+
table: {
|
|
117
|
+
type: { summary: "function" }
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
decorators: [
|
|
122
|
+
Story => (
|
|
123
|
+
<Provider store={store}>
|
|
124
|
+
<Story />
|
|
125
|
+
</Provider>
|
|
126
|
+
)
|
|
127
|
+
]
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export const Basic = args => <ConnectedSearchableSelect {...args} />;
|
|
131
|
+
|
|
132
|
+
export const Disabled = {
|
|
133
|
+
args: {
|
|
134
|
+
disabled: true
|
|
135
|
+
},
|
|
136
|
+
render: args => <ConnectedSearchableSelect {...args} />
|
|
137
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Canvas, Meta, Title, Story, Controls } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
import * as StateProvinceDropdownStories from './StateProvinceDropdown.stories.js';
|
|
4
|
+
|
|
5
|
+
<Meta of={StateProvinceDropdownStories} />
|
|
6
|
+
|
|
7
|
+
<Title />
|
|
8
|
+
|
|
9
|
+
StateProvinceDropdown is a wrapper for [FormSelect](?path=/docs/atoms-formselect--docs) that adds a pre-defined array of states or provinces for options. The state/provinces loaded are determined by the `countryCode` prop. These options cannot be modified. A "placeholder" option is added to the top of the list with a value of "". The display name of the placeholder is determined by the country code.
|
|
10
|
+
|
|
11
|
+
## Form Integration
|
|
12
|
+
|
|
13
|
+
FormInput requires a `field` and `fieldActions` prop. Both are objects that _can_ be generated with [redux-freeform](https://github.com/CityBaseInc/redux-freeform). Below are example values for each prop with the minimum properties needed for a CountryDropdown component.
|
|
14
|
+
|
|
15
|
+
### field
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
{
|
|
19
|
+
"dirty": false,
|
|
20
|
+
"rawValue": "",
|
|
21
|
+
"errors": [
|
|
22
|
+
"error/REQUIRED"
|
|
23
|
+
],
|
|
24
|
+
"hasErrors": true
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### fieldActions
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
{
|
|
32
|
+
set: (value) => {...}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`fieldActions.set()` is called when an option is selected in the underlying Dropdown component, unless a function is defined for the `onChange` prop.
|