react-shopping-cart
v1.9.5
Published
React shopping cart
Downloads
106
Readme
React shopping cart
Shopping cart package provides several components:
which can be used separately or in union. By default Redux is the framework to operate with data.
So, it's your choice to use Redux or not, but its reducers, actions and action types are already included.
Pay attention! All components are Pure.
Meta
- author: Oleg Nosov <[email protected]>
- license: MIT
Demo
Latest version demo (example1)
Usage
yarn add react-shopping-cart
npm i --save react-shopping-cart
Examples
In all cases you must include bootstrap version 4 (^alpha 0.6) in your project
import "bootstrap/dist/css/bootstrap.css";
And if you want to see animation, also include animate.css
import "animate.css/animate.min.css";
Also want some icons?
import "font-awesome/css/font-awesome.min.css";
With Redux. After store initialization you must dispatch setCartCurrency action or 'USD' will be used as cart's currency.
import React, { PureComponent } from "react";
import { Provider } from "react-redux";
import { createStore, combineReducers } from "redux";
import {
Cart,
Product,
CheckoutButton,
cartLocalization,
cartReducer,
setCartCurrency
} from "react-shopping-cart";
import "bootstrap/dist/css/bootstrap.css";
import "animate.css/animate.min.css";
import "font-awesome/css/font-awesome.min.css";
const { getDefaultLocalization } = cartLocalization;
// You may take localization object from wherever you want, that's just an example
// For more information, see localization section
const iPadCaseLocalization = {
color: "Color",
iPadCase: "iPad case",
red: "Red",
green: "Green",
yellow: "Yellow",
GBP: "£",
EUR: "€",
USD: "$"
};
const iPadPropertiesWithAdditionalCostLocalization = {
yellow: "Yellow (+{cost, number, CUR})"
};
const store = createStore(
combineReducers({
cart: cartReducer
// Your own reducers, sir
})
);
store.dispatch(setCartCurrency("USD"));
class App extends PureComponent {
state = {
product: {
name: "iPadCase",
id: "ipad-case",
path: "/shop/ipad-case/",
properties: {
color: [
"red",
"green",
{
additionalCost: {
GBP: 1,
EUR: 2,
USD: 3.5
},
value: "yellow"
}
]
},
propertiesToShowInCart: ["color"],
prices: { GBP: 70, EUR: 80, USD: 90 },
currency: "GBP",
imageSrc: "1-483x321.jpeg"
},
getProductLocalization: getDefaultLocalization("product", "en", {
...iPadCaseLocalization,
...iPadPropertiesWithAdditionalCostLocalization
}),
getCheckoutButtonLocalization: getDefaultLocalization(
"checkoutButton",
"en",
iPadCaseLocalization
),
getCartLocalization: getDefaultLocalization(
"cart",
"en",
iPadCaseLocalization
)
};
render() {
const {
product,
getCheckoutButtonLocalization,
getProductLocalization,
getCartLocalization
} = this.state;
const checkoutButtonElement = (
<CheckoutButton
getLocalization={getCheckoutButtonLocalization}
checkoutURL="/to/my/checkout"
/>
);
return (
<Provider store={store}>
<div className="container">
<Product
{...product}
checkoutButton={checkoutButtonElement}
getLocalization={getProductLocalization}
/>
<Cart
checkoutButton={checkoutButtonElement}
getLocalization={getCartLocalization}
/>
</div>
</Provider>
);
}
}
export default App;
// You may also import actions and actionTypes
import { cartActions, cartActionTypes } from "react-shopping-cart";
// And do some cool things with them
Without redux
import React, { PureComponent } from "react";
import {
CartComponent,
ProductComponent,
CheckoutButtonComponent,
cartLocalization
} from "react-shopping-cart";
import "bootstrap/dist/css/bootstrap.css";
import "animate.css/animate.min.css";
import "font-awesome/css/font-awesome.min.css";
const { getDefaultLocalization } = cartLocalization;
// You may take localization object from wherever you want, that's just an example
// For more information, see localization section
const iPadCaseLocalization = {
color: "Color",
iPadCase: "iPad case",
red: "Red",
green: "Green",
yellow: "Yellow",
GBP: "£",
EUR: "€",
USD: "$"
};
const iPadPropertiesWithAdditionalCostLocalization = {
yellow: "Yellow (+{cost, number, CUR})"
};
class App extends PureComponent {
state = {
products: {},
product: {
name: "iPadCase",
id: "ipad-case",
path: "/shop/ipad-case/",
properties: {
color: [
"red",
"green",
{
additionalCost: {
GBP: 1,
EUR: 2,
USD: 3.5
},
value: "yellow"
}
]
},
propertiesToShowInCart: ["color"],
prices: { GBP: 70, EUR: 80, USD: 90 },
currency: "GBP",
imageSrc: "1-483x321.jpeg"
},
getProductLocalization: getDefaultLocalization("product", "en", {
...iPadCaseLocalization,
...iPadPropertiesWithAdditionalCostLocalization
}),
getCheckoutButtonLocalization: getDefaultLocalization(
"checkoutButton",
"en",
iPadCaseLocalization
),
getCartLocalization: getDefaultLocalization(
"cart",
"en",
iPadCaseLocalization
)
};
addProduct = (key, product, currency) =>
void this.setState(
({
products: { [key]: cartProduct = { quantity: 0 }, ...restOfProducts }
}) => ({
products: {
...restOfProducts,
[key]: {
...product,
quantity: product.quantity + cartProduct.quantity
}
}
})
);
generateProductKey = (id, properties) =>
`${id}/${Object.entries(properties).join("_")}`;
updateProduct = (key, updatedProduct) => void console.log(":)");
removeProduct = key => void console.log(":C");
render() {
const {
addProduct,
generateProductKey,
updateProduct,
removeProduct,
state
} = this;
const {
getProductLocalization,
getCheckoutButtonLocalization,
getCartLocalization,
products,
product
} = state;
const checkoutButtonElement = (
<CheckoutButtonComponent
grandTotal={500}
hidden={false}
checkoutURL="/to/my/checkout"
currency="GBP"
getLocalization={getCheckoutButtonLocalization}
/>
);
return (
<div className="container">
<ProductComponent
{...product}
checkoutButton={checkoutButtonElement}
onAddProduct={
addProduct
// Help product to get into the cart
}
generateProductKey={
generateProductKey
// create product key as you wish
}
getLocalization={getProductLocalization}
/>
<CartComponent
products={
products
// Provide your own product's Object(Look at Products)
}
onUpdateProduct={
updateProduct
// Update something
}
getLocalization={getCartLocalization}
currency="GBP"
onRemoveProduct={
removeProduct
// Remove something
}
checkoutButton={checkoutButtonElement}
isCartEmpty={false}
getLocalization={getCartLocalization}
/>
</div>
);
}
}
export default App;
Localization
The default localization library is intl-messageformat. In order to localize your cart, you can chose one of the possible ways:
- Create your own getLocalization function and pass it as prop to the cart's components
- Create getLocalization function with bound localization using defaultLocalization object and getLocalization, getDefaultLocalization functions from cartLocalization module, pass it as prop to the cart's components
- Don't do anything and see only default language in your cart :C
Generally, components require a function, which takes id and params(optional) and returns string, based on received arguments.
The first one should look like that if you're also using intl-messageformat:
import React from 'react';
import IntlMessageFormat from 'intl-messageformat';
import { Cart } from 'react-shopping-cart';
const localization = {
en: {
cart : {
GBP: '£',
},
},
};
const getLocalization = (localizationPart, language, id, params = {}) =>
new IntlMessageFormat(localizationPart[id], language).format(params);
<Cart
getLocalization={(...args) => getLocalization(localization.en.cart, 'en', ...args)}
/>
Or you could use getDefaultLocalization function from cartLocalization:
import React from 'react';
import { Cart, cartLocalization } from 'react-shopping-cart';
const { getDefaultLocalization } = cartLocalization;
const localization = {
GBP: '£',
USD: '$',
};
<Cart
getLocalization={getDefaultLocalization('cart', 'en', localization)}
/>
Example usage of getLocalization function from cartLocalization:
import React from 'react';
import { Cart, cartLocalization } from 'react-shopping-cart';
const { getLocalization, defaultLocalization } = cartLocalization;
const localization = {
en: {
cart : {
GBP: '£',
},
},
};
const mergedEnCartLocalization = {
...localization.en.cart,
...defaultLocalization.en.cart,
};
<Cart
getLocalization={(...args) => getLocalization(mergedEnCartLocalization, 'en', ...args)}
/>
For built-in getLocalization function you may write your translation for default statements as a string or object in format { component : Function | string, text : string, props? : object }. Because all components are pure, in order to relocalize your components, you should pass new getLocalization function, not old with changed scope.
Localization default ids and params bindings:
cart:
no params
- shoppingCartTitle
{ quantity, price, total, currency, name, localizedName, localizedCurrency, }
- productName
- quantityLabel
- priceLabel
- priceValue
- totalLabel
- totalValue
- remove
- your currency
- your product's name
{name, value, localizedName, localizedValue,}
- productPropertyLabel
- productPropertyValue
- your product's property name
- your product's property value (if string of course)
checkoutButton
- {currency, total, localizedCurrency,}
- checkoutTotal
- your currency
- {currency, total, localizedCurrency,}
product
- {
name,
quantity,
price,
currency,
localizedName,
localizedCurrency,
}
- price
- quantityLabel
- propertyLabel
- addToCart
- your product's name
- your product's currency
- {
name,
currency,
localizedName,
localizedCurrency,
}
- your product's name
- your product's property name
- {(optional) cost}
- your product's property value (if string of course)
- {
name,
quantity,
price,
currency,
localizedName,
localizedCurrency,
}
Table of Contents
- Cart
- CartProduct
- ProductPropertyLabel
- CheckoutButton
- helpers
- Product
- ProductPropertiesOptions
- ScrollPosition
- ScrollFunction
- ProductPropertyInput
- OptionIndex
- OptionObject
- PropertyOption
- PropertyOptions
- OnChange
- ProductPropertyOption
- ProductProperties
- Prices
- ProductData
- Products
- GenerateProductKey
- AddProduct
- UpdateProduct
- RemoveProduct
- GetLocalization
- CartAddAction
- CartUpdateAction
- CartRemoveAction
- CartEmptyAction
- CartSetCurrencyAction
- CartAction
- LocalizationPattern
- Localization
- MultiLocalization
- CartState
- DefaultLinkComponentProps
- Link$Component
Cart
Extends React.PureComponent
Component which represents shopping cart.
Meta
- author: Oleg Nosov <[email protected]>
- license: MIT
Props
Type: Object
Properties
products
Products Products map. Required.currency
string Current currency. Required.isCartEmpty
boolean Display cart or not. Required.onUpdateProduct
UpdateProduct Function which will be called when product should be updated. First arg is product's key in products map, second - updated product. Required.onRemoveProduct
RemoveProduct Function to call when product should be removed from cart. One argument - product's key. Required.getLocalization
GetLocalization Required.hideHeader
boolean? Hide cart's header. Default is false.checkoutButton
ReactElement? Button to display in the bottom of cart. Default is null.iconTrashClassName
string? ClassName for trash icon on remove button. Default is 'fa fa-trash mx-1'.altProductImageSrc
string? Alt image src for products. Default is ''.cartCSSTransition
Object? Cart's config for react-transition-group/CSSTransition. Look at src/components/Cart/Cart.js for details.cartItemCSSTransition
Object? Cart item's config for react-transition-group/CSSTransition. Look at src/components/Cart/Cart.js for details.linkComponent
Link$Component? React Component, will receive propto="%your product's page%"
. I'd recommend you to take a look at react-router's Link.
CartProduct
Extends React.PureComponent
React component to display product in cart.
Meta
- author: Oleg Nosov <[email protected]>
- license: MIT
ProductPropertyLabel
Extends React.PureComponent
React component to display product's property value in cart.
Meta
- author: Oleg Nosov <[email protected]>
- license: MIT
CheckoutButton
Extends React.PureComponent
Checkout button with grand total.
Meta
- author: Oleg Nosov <[email protected]>
- license: MIT
Props
Type: Object
Properties
grandTotal
number Required.currency
string Current currency. Required.hidden
boolean Show or hide button. Required.checkoutURL
string Link to checkout page. Required.getLocalization
GetLocalization Required.iconCheckoutClassName
string? ClassName for cart icon on checkout button. Default is 'fa fa-shopping-cart mx-1'.buttonCSSTransition
Object? Transition's config for react-transition-group/CSSTransition.linkComponent
Link$Component? React Component, will receive propto="%your product's page%"
. I'd recommend you to take a look at react-router's Link.
helpers
Meta
- author: Oleg Nosov <[email protected]>
- license: MIT
configure
Parameters
Component
React$ComponentType<Props>configuration
Object
Returns React$ComponentType<Props>
isNaturalNumber
Parameters
num
number
Returns boolean
parseInteger
Parameters
num
string
Returns number
isObject
Parameters
value
any
Returns boolean
getAbsoluteOffsetTop
Parameters
$0
HTMLElement (optional, default{}
)$0.offsetTop
$0.offsetParent
Returns number
DefaultLinkComponent
Parameters
$0
DefaultLinkComponentProps$0.to
$0.otherProps
...any
Returns React$Element<any>
fixInputValueStartingWithZero
Parameters
target
HTMLInputElementquantity
number
scrollFunction
Parameters
target
EventTargetscrollPosition
(number | function (currentTarget: Element): number)scrollAnimationConfig
Object
Product
Extends React.PureComponent
React component - Product form with price.
Meta
- author: Oleg Nosov <[email protected]>
- license: MIT
Props
Type: Object
Properties
id
string Product's id. Required.name
string Name to display pattern. Required.path
string Path to product. Required.prices
Prices {currency: value}. RequiredimageSrc
string Path to main image. Required.currency
string Current price currency. Required.onAddProduct
AddProduct Function to call when user wants to add product in his cart. Required.generateProductKey
GenerateProductKey Required.getLocalization
GetLocalization Required.properties
ProductPropertiesOptions? Custom product properties. Each property option list consists of number, string or shape({ additionalCost(optional), onSelect(optional), value(required)})propertiesToShowInCart
Array<string>? Array of propery names to display in cart.scrollAnimationConfig
Object? Config for animateScroll (from react-scroll) scrollTo function.scrollPosition
ScrollPosition? Position to scroll after product add. May be number or function returning number.scrollFunction
ScrollFunction? Function which will be called when product has been added.iconAddProductClassName
string? ClassName for cart icon on add to button. Default is 'fa fa-cart-plus mx-1'.checkoutButton
ReactElement?descriptionNode
ReactNode? Node to display before price element.afterPriceNode
ReactNode? Node to display after price element.
ProductPropertiesOptions
Type: Object<string, PropertyOptions>
ScrollPosition
Type: (number | function (currentTarget: Element): number)
ScrollFunction
Type: function (currentTarget: EventTarget, scrollPosition: (number | function (currentTarget: Element): number), scrollAnimationConfig: Object): void
ProductPropertyInput
Extends React.PureComponent
React form for product property(options select only).
Meta
- author: Oleg Nosov <[email protected]>
- license: MIT
OptionIndex
OptionObject
Type: Object
PropertyOption
Type: (ProductPropertyOption | OptionObject)
PropertyOptions
Type: Array<PropertyOption>
OnChange
Type: function (obj: {value: OptionIndex}): void
Shopping cart's data types
Meta
- author: Oleg Nosov <[email protected]>
- license: MIT
ProductPropertyOption
ProductProperties
Type: Object<string, (string | number)>
Prices
ProductData
Properties
id
stringquantity
numberproperties
ProductPropertiesname
stringprices
PricesimageSrc
stringpath
stringpropertiesToShowInCart
Array<string>
Examples
{
id: 'macbook-case',
quantity: 3,
properties: {
color: 'red'
},
name: 'macbookCase',
prices: {
GBP: 50
},
path: '/shop/macbook-case/',
imageSrc: '/shop/macbook-case/1-483x321.jpeg',
propertiesToShowInCart: ['color']
}
Products
Type: Object<string, ProductData>
GenerateProductKey
Type: function (id: string, properties: ProductProperties): string
AddProduct
Type: function (key: string, product: ProductData, currency: string): void
UpdateProduct
Type: function (key: string, updatedProduct: ProductData): void
RemoveProduct
Type: function (key: string): void
GetLocalization
Type: function (id: string, params: Object): (string | React$Element<any>)
CartAddAction
Properties
type
"cart/ADD"
key
stringproduct
ProductDataproductCurrency
string
CartUpdateAction
Properties
type
"cart/UPDATE"
key
stringupdatedProduct
ProductData
CartRemoveAction
Properties
type
"cart/REMOVE"
key
string
CartEmptyAction
Properties
type
"cart/EMPTY"
CartSetCurrencyAction
Properties
type
"cart/SET_CURRENCY"
currency
string
CartAction
Type: (CartAddAction | CartUpdateAction | CartRemoveAction | CartEmptyAction | CartSetCurrencyAction)
LocalizationPattern
Type: (string | {component: (string | React$ComponentType<any>), props: Object?, text: string})
Localization
Type: Object<string, LocalizationPattern>
MultiLocalization
Type: Object<string, Object<string, Localization>>
CartState
Properties
DefaultLinkComponentProps
Properties
to
string
Link$Component
Type: function (DefaultLinkComponentProps): React$Element<any>
Development
Developer mode
Run webpack-dev-server for example1
yarn start
npm run start
Build
yarn build
npm run build
And then check dist folder
Build Example
yarn build_example
npm run build_example
And then check examples folder
Testing
Jest is used for tests
yarn test
npm run test
Linter
ESLint is used as a linter
yarn lint
npm run lint
Formatter
prettier-eslint is used as a formatter
yarn fmt
npm run fmt
Flow Type
Check types in project using Flow
yarn flow
npm run flow
Autodoc
Generate doc using documentation js
yarn doc
npm run doc
And then look at README.md