woocommerce/plugins/woocommerce-blocks/assets/js/base/components/quantity-selector/index.tsx

243 lines
6.4 KiB
TypeScript
Raw Normal View History

Cart block: line-items front end initial work (https://github.com/woocommerce/woocommerce-blocks/pull/1333) * render block on front end, add `Shopping cart` heading (baby steps) * fake data for editing full cart + show line count in header * add note about core/html using `is-active` class for toggle state * reinstate work-in-progress full cart component (lost in rebase) * reinstate full cart from master * component for full cart title & item count + margin tweaks: - add margin between main cart & sidebar - add margin after cart block * add cart items sample data + factor sample product image to module * use sample cart data for item count * basic table of cart line items (no styling) * prettification * show images for cart line items + initial table styling * cart quantity selector component (work in progress) * use state for cart product quantity, allow incr/decr from UI (WIP) * replace WIP custom quantity control with number edit (temporary) * correctly format cart line item total price * align cart item columns with headings + indent image on desktop * tweak css for cart line item padding on mobile so it's more explicit * show cart line item full price if discounted * add placeholder for cart remove item link * switch cart table to flex layout (was table)… This will allow us to move things around for mobile/responsive layout. * only show cart items table header on desktop * more cart items styling - row borders, appropriate padding + + move image width to variable + fix class name plurality for row (item not items) * use standard $gap instead of 1em for padding/margins * responsive (mobile) layout for cart line items: - shift line $ total to bottom right - stack quantity selector in product info column * remove extraneous cart table padding on mobile * comment about unused styles for quantity selector component * add follow up issue for todo * remove inappropriate href * render srcset & sizes for cart line item product image * remove todo comment * switch back to table markup for cart items (in progress): - table is more semantic, associates headers with columns * cart line items column widths - product column is larger (60%) * reinstate table row borders * bottom-align line item price on mobile * cart contents heading should be H2 + prettify * remove unused QuantitySelector code/styles, rename main class in line with BEM * defaults for QuantitySelector props * variable/property name tidies - match conventions/API * fix bug: line total price is only bottom-align on small screen * move QuantitySelector to root of components, intended to be generally useful * use lineItem directly for cart, specify shape in PropTypes * rename cart components to align with "line item" rather than "product" * rejig class names to better align with new component names & BEM style * show cart item image correct size: - use single column for product image and info, with flex container - specify image width (rem instead of px) * fix safari issue - cart product images displaying vertically stretched * shift product name left margin from image, to account for no-image case * experiment: bump bundlewatch size limit for cart temporarily: - our fake data inline image is heavy - when we switch to real API we will no longer need it * fix issue introduced when moving margin from image to details div: - product details needs margin on left (not right) * fix react props issues: - explicitly destructure image props for srcSet (vs srcset) - use API key field for line item key instead of id, fix duplicate test id - CartLineItemsTable takes an array of lineItems (incorrect PropTypes) * remove redundant divs + use conventional `null` (when no full price) * override editor styles to ensure cart product image is correct size * move cart items editor style override to editor.css * add an explicit readable heading for cart heading to match visual layout
2020-01-09 22:50:14 +00:00
/**
* External dependencies
*/
import { __, sprintf } from '@wordpress/i18n';
import { speak } from '@wordpress/a11y';
Cart block: line-items front end initial work (https://github.com/woocommerce/woocommerce-blocks/pull/1333) * render block on front end, add `Shopping cart` heading (baby steps) * fake data for editing full cart + show line count in header * add note about core/html using `is-active` class for toggle state * reinstate work-in-progress full cart component (lost in rebase) * reinstate full cart from master * component for full cart title & item count + margin tweaks: - add margin between main cart & sidebar - add margin after cart block * add cart items sample data + factor sample product image to module * use sample cart data for item count * basic table of cart line items (no styling) * prettification * show images for cart line items + initial table styling * cart quantity selector component (work in progress) * use state for cart product quantity, allow incr/decr from UI (WIP) * replace WIP custom quantity control with number edit (temporary) * correctly format cart line item total price * align cart item columns with headings + indent image on desktop * tweak css for cart line item padding on mobile so it's more explicit * show cart line item full price if discounted * add placeholder for cart remove item link * switch cart table to flex layout (was table)… This will allow us to move things around for mobile/responsive layout. * only show cart items table header on desktop * more cart items styling - row borders, appropriate padding + + move image width to variable + fix class name plurality for row (item not items) * use standard $gap instead of 1em for padding/margins * responsive (mobile) layout for cart line items: - shift line $ total to bottom right - stack quantity selector in product info column * remove extraneous cart table padding on mobile * comment about unused styles for quantity selector component * add follow up issue for todo * remove inappropriate href * render srcset & sizes for cart line item product image * remove todo comment * switch back to table markup for cart items (in progress): - table is more semantic, associates headers with columns * cart line items column widths - product column is larger (60%) * reinstate table row borders * bottom-align line item price on mobile * cart contents heading should be H2 + prettify * remove unused QuantitySelector code/styles, rename main class in line with BEM * defaults for QuantitySelector props * variable/property name tidies - match conventions/API * fix bug: line total price is only bottom-align on small screen * move QuantitySelector to root of components, intended to be generally useful * use lineItem directly for cart, specify shape in PropTypes * rename cart components to align with "line item" rather than "product" * rejig class names to better align with new component names & BEM style * show cart item image correct size: - use single column for product image and info, with flex container - specify image width (rem instead of px) * fix safari issue - cart product images displaying vertically stretched * shift product name left margin from image, to account for no-image case * experiment: bump bundlewatch size limit for cart temporarily: - our fake data inline image is heavy - when we switch to real API we will no longer need it * fix issue introduced when moving margin from image to details div: - product details needs margin on left (not right) * fix react props issues: - explicitly destructure image props for srcSet (vs srcset) - use API key field for line item key instead of id, fix duplicate test id - CartLineItemsTable takes an array of lineItems (incorrect PropTypes) * remove redundant divs + use conventional `null` (when no full price) * override editor styles to ensure cart product image is correct size * move cart items editor style override to editor.css * add an explicit readable heading for cart heading to match visual layout
2020-01-09 22:50:14 +00:00
import classNames from 'classnames';
import { useCallback, useLayoutEffect, useRef } from '@wordpress/element';
import { DOWN, UP } from '@wordpress/keycodes';
import { useDebouncedCallback } from 'use-debounce';
Cart block: line-items front end initial work (https://github.com/woocommerce/woocommerce-blocks/pull/1333) * render block on front end, add `Shopping cart` heading (baby steps) * fake data for editing full cart + show line count in header * add note about core/html using `is-active` class for toggle state * reinstate work-in-progress full cart component (lost in rebase) * reinstate full cart from master * component for full cart title & item count + margin tweaks: - add margin between main cart & sidebar - add margin after cart block * add cart items sample data + factor sample product image to module * use sample cart data for item count * basic table of cart line items (no styling) * prettification * show images for cart line items + initial table styling * cart quantity selector component (work in progress) * use state for cart product quantity, allow incr/decr from UI (WIP) * replace WIP custom quantity control with number edit (temporary) * correctly format cart line item total price * align cart item columns with headings + indent image on desktop * tweak css for cart line item padding on mobile so it's more explicit * show cart line item full price if discounted * add placeholder for cart remove item link * switch cart table to flex layout (was table)… This will allow us to move things around for mobile/responsive layout. * only show cart items table header on desktop * more cart items styling - row borders, appropriate padding + + move image width to variable + fix class name plurality for row (item not items) * use standard $gap instead of 1em for padding/margins * responsive (mobile) layout for cart line items: - shift line $ total to bottom right - stack quantity selector in product info column * remove extraneous cart table padding on mobile * comment about unused styles for quantity selector component * add follow up issue for todo * remove inappropriate href * render srcset & sizes for cart line item product image * remove todo comment * switch back to table markup for cart items (in progress): - table is more semantic, associates headers with columns * cart line items column widths - product column is larger (60%) * reinstate table row borders * bottom-align line item price on mobile * cart contents heading should be H2 + prettify * remove unused QuantitySelector code/styles, rename main class in line with BEM * defaults for QuantitySelector props * variable/property name tidies - match conventions/API * fix bug: line total price is only bottom-align on small screen * move QuantitySelector to root of components, intended to be generally useful * use lineItem directly for cart, specify shape in PropTypes * rename cart components to align with "line item" rather than "product" * rejig class names to better align with new component names & BEM style * show cart item image correct size: - use single column for product image and info, with flex container - specify image width (rem instead of px) * fix safari issue - cart product images displaying vertically stretched * shift product name left margin from image, to account for no-image case * experiment: bump bundlewatch size limit for cart temporarily: - our fake data inline image is heavy - when we switch to real API we will no longer need it * fix issue introduced when moving margin from image to details div: - product details needs margin on left (not right) * fix react props issues: - explicitly destructure image props for srcSet (vs srcset) - use API key field for line item key instead of id, fix duplicate test id - CartLineItemsTable takes an array of lineItems (incorrect PropTypes) * remove redundant divs + use conventional `null` (when no full price) * override editor styles to ensure cart product image is correct size * move cart items editor style override to editor.css * add an explicit readable heading for cart heading to match visual layout
2020-01-09 22:50:14 +00:00
/**
* Internal dependencies
*/
import './style.scss';
export interface QuantitySelectorProps {
/**
* Component wrapper classname
*
* @default 'wc-block-components-quantity-selector'
*/
className?: string;
/**
* Current quantity
*/
quantity?: number;
/**
* Minimum quantity
*/
minimum?: number;
/**
* Maximum quantity
*/
maximum: number;
/**
* Input step attribute.
*/
step?: number;
/**
* Event handler triggered when the quantity is changed
*/
onChange: ( newQuantity: number ) => void;
/**
* Name of the item the quantity selector refers to
*
* Used for a11y purposes
*/
itemName?: string;
/**
* Whether the component should be interactable or not
*/
disabled: boolean;
}
Cart block: line-items front end initial work (https://github.com/woocommerce/woocommerce-blocks/pull/1333) * render block on front end, add `Shopping cart` heading (baby steps) * fake data for editing full cart + show line count in header * add note about core/html using `is-active` class for toggle state * reinstate work-in-progress full cart component (lost in rebase) * reinstate full cart from master * component for full cart title & item count + margin tweaks: - add margin between main cart & sidebar - add margin after cart block * add cart items sample data + factor sample product image to module * use sample cart data for item count * basic table of cart line items (no styling) * prettification * show images for cart line items + initial table styling * cart quantity selector component (work in progress) * use state for cart product quantity, allow incr/decr from UI (WIP) * replace WIP custom quantity control with number edit (temporary) * correctly format cart line item total price * align cart item columns with headings + indent image on desktop * tweak css for cart line item padding on mobile so it's more explicit * show cart line item full price if discounted * add placeholder for cart remove item link * switch cart table to flex layout (was table)… This will allow us to move things around for mobile/responsive layout. * only show cart items table header on desktop * more cart items styling - row borders, appropriate padding + + move image width to variable + fix class name plurality for row (item not items) * use standard $gap instead of 1em for padding/margins * responsive (mobile) layout for cart line items: - shift line $ total to bottom right - stack quantity selector in product info column * remove extraneous cart table padding on mobile * comment about unused styles for quantity selector component * add follow up issue for todo * remove inappropriate href * render srcset & sizes for cart line item product image * remove todo comment * switch back to table markup for cart items (in progress): - table is more semantic, associates headers with columns * cart line items column widths - product column is larger (60%) * reinstate table row borders * bottom-align line item price on mobile * cart contents heading should be H2 + prettify * remove unused QuantitySelector code/styles, rename main class in line with BEM * defaults for QuantitySelector props * variable/property name tidies - match conventions/API * fix bug: line total price is only bottom-align on small screen * move QuantitySelector to root of components, intended to be generally useful * use lineItem directly for cart, specify shape in PropTypes * rename cart components to align with "line item" rather than "product" * rejig class names to better align with new component names & BEM style * show cart item image correct size: - use single column for product image and info, with flex container - specify image width (rem instead of px) * fix safari issue - cart product images displaying vertically stretched * shift product name left margin from image, to account for no-image case * experiment: bump bundlewatch size limit for cart temporarily: - our fake data inline image is heavy - when we switch to real API we will no longer need it * fix issue introduced when moving margin from image to details div: - product details needs margin on left (not right) * fix react props issues: - explicitly destructure image props for srcSet (vs srcset) - use API key field for line item key instead of id, fix duplicate test id - CartLineItemsTable takes an array of lineItems (incorrect PropTypes) * remove redundant divs + use conventional `null` (when no full price) * override editor styles to ensure cart product image is correct size * move cart items editor style override to editor.css * add an explicit readable heading for cart heading to match visual layout
2020-01-09 22:50:14 +00:00
const QuantitySelector = ( {
className,
quantity = 1,
Support updating quantity of cart items & sold_individually product option (https://github.com/woocommerce/woocommerce-blocks/pull/1824) * first cut - removing an item from cart: - add actions to cart store for removing an item and keeping track of pending removal API call - add reducer logic for storing pending state on an item, and removing an item - expose removeCartItem on new useStoreCartItems hook - hook it up to remove link / trashcan icon in row item * disable cart quantity picker/remove link while API request in progress: - expose cart item pending status from store using selector - use selector to disable quantity related components in line item row * add typedef for cart items store object provided by hook * allow user to change quantity of cart items (first cut): - add action for replacing a cart item in the store - add generator action for changing quantity - expose change quantity action on useStoreCartItems hook - hook up to quantity UI in cart block (work in progress) * post-rebase fixes & fix broken typedef: - rework cart item change quantity callback - now supplies item key like remove callback - fix hook StoreCartItem return value typedef - single item with specified key, was array of all items - add quantity JSDoc for changeCartItemQuantity action - remove changeQuantity callback from UI (currently infinite looping) * fix bug in recieveCartItem reducer - check keys for equality: - was key === object * fix invalid url in POST cart/items/quantity request * hook up cart line item quantity to API: - remove internal state/ref for QuantitySelector, is now a controlled component - call changeQuantity action from QuantitySelector change callback * QuantitySelector no longer needs a ref to wrangle number input value * hoist quantity state out of QuantitySelector into story (fix storybook) * add product sold_individually option to cart item API response * limit sold_individually items to 1 per cart/order: - support optional max value in QuantitySelector - set maximum dependent on sold_individually API field * prevent user from requesting zero x cart item (API 500 errors): - add minimum limit to QuantitySelector - default limit to 1 + fix bug with limiting to maximum value in number input change handler * remove useStoreCartItems, zombie hook coming back from rebase 🧟‍♂️ * address various review feedback: - inline undefined check, don't use lodash - quantityInputOnKeyDown callback hook depends on canIncrease/canDecrease - also removed undefined check for minimum, as minimum has default 0 * use safer typeof check for presence of maximum prop
2020-03-03 01:08:19 +00:00
minimum = 1,
maximum,
onChange = () => void 0,
step = 1,
itemName = '',
disabled,
}: QuantitySelectorProps ): JSX.Element => {
const classes = classNames(
'wc-block-components-quantity-selector',
className
);
const inputRef = useRef< HTMLInputElement | null >( null );
const decreaseButtonRef = useRef< HTMLButtonElement | null >( null );
const increaseButtonRef = useRef< HTMLButtonElement | null >( null );
Support updating quantity of cart items & sold_individually product option (https://github.com/woocommerce/woocommerce-blocks/pull/1824) * first cut - removing an item from cart: - add actions to cart store for removing an item and keeping track of pending removal API call - add reducer logic for storing pending state on an item, and removing an item - expose removeCartItem on new useStoreCartItems hook - hook it up to remove link / trashcan icon in row item * disable cart quantity picker/remove link while API request in progress: - expose cart item pending status from store using selector - use selector to disable quantity related components in line item row * add typedef for cart items store object provided by hook * allow user to change quantity of cart items (first cut): - add action for replacing a cart item in the store - add generator action for changing quantity - expose change quantity action on useStoreCartItems hook - hook up to quantity UI in cart block (work in progress) * post-rebase fixes & fix broken typedef: - rework cart item change quantity callback - now supplies item key like remove callback - fix hook StoreCartItem return value typedef - single item with specified key, was array of all items - add quantity JSDoc for changeCartItemQuantity action - remove changeQuantity callback from UI (currently infinite looping) * fix bug in recieveCartItem reducer - check keys for equality: - was key === object * fix invalid url in POST cart/items/quantity request * hook up cart line item quantity to API: - remove internal state/ref for QuantitySelector, is now a controlled component - call changeQuantity action from QuantitySelector change callback * QuantitySelector no longer needs a ref to wrangle number input value * hoist quantity state out of QuantitySelector into story (fix storybook) * add product sold_individually option to cart item API response * limit sold_individually items to 1 per cart/order: - support optional max value in QuantitySelector - set maximum dependent on sold_individually API field * prevent user from requesting zero x cart item (API 500 errors): - add minimum limit to QuantitySelector - default limit to 1 + fix bug with limiting to maximum value in number input change handler * remove useStoreCartItems, zombie hook coming back from rebase 🧟‍♂️ * address various review feedback: - inline undefined check, don't use lodash - quantityInputOnKeyDown callback hook depends on canIncrease/canDecrease - also removed undefined check for minimum, as minimum has default 0 * use safer typeof check for presence of maximum prop
2020-03-03 01:08:19 +00:00
const hasMaximum = typeof maximum !== 'undefined';
const canDecrease = ! disabled && quantity - step >= minimum;
const canIncrease =
! disabled && ( ! hasMaximum || quantity + step <= maximum );
/**
* The goal of this function is to normalize what was inserted,
* but after the customer has stopped typing.
*/
const normalizeQuantity = useCallback(
( initialValue: number ) => {
// We copy the starting value.
let value = initialValue;
// We check if we have a maximum value, and select the lowest between what was inserted and the maximum.
if ( hasMaximum ) {
value = Math.min(
value,
// the maximum possible value in step increments.
Math.floor( maximum / step ) * step
);
}
// Select the biggest between what's inserted, the the minimum value in steps.
value = Math.max( value, Math.ceil( minimum / step ) * step );
// We round off the value to our steps.
value = Math.floor( value / step ) * step;
// Only commit if the value has changed
if ( value !== initialValue ) {
onChange( value );
}
},
[ hasMaximum, maximum, minimum, onChange, step ]
);
/*
* It's important to wait before normalizing or we end up with
* a frustrating experience, for example, if the minimum is 2 and
* the customer is trying to type "10", premature normalizing would
* always kick in at "1" and turn that into 2.
*/
const debouncedNormalizeQuantity = useDebouncedCallback(
normalizeQuantity,
// This value is deliberately smaller than what's in useStoreCartItemQuantity so we don't end up with two requests.
300
);
/**
* Normalize qty on mount before render.
*/
useLayoutEffect( () => {
normalizeQuantity( quantity );
}, [ quantity, normalizeQuantity ] );
/**
* Handles keyboard up and down keys to change quantity value.
*
* @param {Object} event event data.
*/
const quantityInputOnKeyDown = useCallback(
( event ) => {
const isArrowDown =
typeof event.key !== undefined
? event.key === 'ArrowDown'
: event.keyCode === DOWN;
const isArrowUp =
typeof event.key !== undefined
? event.key === 'ArrowUp'
: event.keyCode === UP;
Support updating quantity of cart items & sold_individually product option (https://github.com/woocommerce/woocommerce-blocks/pull/1824) * first cut - removing an item from cart: - add actions to cart store for removing an item and keeping track of pending removal API call - add reducer logic for storing pending state on an item, and removing an item - expose removeCartItem on new useStoreCartItems hook - hook it up to remove link / trashcan icon in row item * disable cart quantity picker/remove link while API request in progress: - expose cart item pending status from store using selector - use selector to disable quantity related components in line item row * add typedef for cart items store object provided by hook * allow user to change quantity of cart items (first cut): - add action for replacing a cart item in the store - add generator action for changing quantity - expose change quantity action on useStoreCartItems hook - hook up to quantity UI in cart block (work in progress) * post-rebase fixes & fix broken typedef: - rework cart item change quantity callback - now supplies item key like remove callback - fix hook StoreCartItem return value typedef - single item with specified key, was array of all items - add quantity JSDoc for changeCartItemQuantity action - remove changeQuantity callback from UI (currently infinite looping) * fix bug in recieveCartItem reducer - check keys for equality: - was key === object * fix invalid url in POST cart/items/quantity request * hook up cart line item quantity to API: - remove internal state/ref for QuantitySelector, is now a controlled component - call changeQuantity action from QuantitySelector change callback * QuantitySelector no longer needs a ref to wrangle number input value * hoist quantity state out of QuantitySelector into story (fix storybook) * add product sold_individually option to cart item API response * limit sold_individually items to 1 per cart/order: - support optional max value in QuantitySelector - set maximum dependent on sold_individually API field * prevent user from requesting zero x cart item (API 500 errors): - add minimum limit to QuantitySelector - default limit to 1 + fix bug with limiting to maximum value in number input change handler * remove useStoreCartItems, zombie hook coming back from rebase 🧟‍♂️ * address various review feedback: - inline undefined check, don't use lodash - quantityInputOnKeyDown callback hook depends on canIncrease/canDecrease - also removed undefined check for minimum, as minimum has default 0 * use safer typeof check for presence of maximum prop
2020-03-03 01:08:19 +00:00
if ( isArrowDown && canDecrease ) {
event.preventDefault();
onChange( quantity - step );
}
Support updating quantity of cart items & sold_individually product option (https://github.com/woocommerce/woocommerce-blocks/pull/1824) * first cut - removing an item from cart: - add actions to cart store for removing an item and keeping track of pending removal API call - add reducer logic for storing pending state on an item, and removing an item - expose removeCartItem on new useStoreCartItems hook - hook it up to remove link / trashcan icon in row item * disable cart quantity picker/remove link while API request in progress: - expose cart item pending status from store using selector - use selector to disable quantity related components in line item row * add typedef for cart items store object provided by hook * allow user to change quantity of cart items (first cut): - add action for replacing a cart item in the store - add generator action for changing quantity - expose change quantity action on useStoreCartItems hook - hook up to quantity UI in cart block (work in progress) * post-rebase fixes & fix broken typedef: - rework cart item change quantity callback - now supplies item key like remove callback - fix hook StoreCartItem return value typedef - single item with specified key, was array of all items - add quantity JSDoc for changeCartItemQuantity action - remove changeQuantity callback from UI (currently infinite looping) * fix bug in recieveCartItem reducer - check keys for equality: - was key === object * fix invalid url in POST cart/items/quantity request * hook up cart line item quantity to API: - remove internal state/ref for QuantitySelector, is now a controlled component - call changeQuantity action from QuantitySelector change callback * QuantitySelector no longer needs a ref to wrangle number input value * hoist quantity state out of QuantitySelector into story (fix storybook) * add product sold_individually option to cart item API response * limit sold_individually items to 1 per cart/order: - support optional max value in QuantitySelector - set maximum dependent on sold_individually API field * prevent user from requesting zero x cart item (API 500 errors): - add minimum limit to QuantitySelector - default limit to 1 + fix bug with limiting to maximum value in number input change handler * remove useStoreCartItems, zombie hook coming back from rebase 🧟‍♂️ * address various review feedback: - inline undefined check, don't use lodash - quantityInputOnKeyDown callback hook depends on canIncrease/canDecrease - also removed undefined check for minimum, as minimum has default 0 * use safer typeof check for presence of maximum prop
2020-03-03 01:08:19 +00:00
if ( isArrowUp && canIncrease ) {
event.preventDefault();
onChange( quantity + step );
}
},
[ quantity, onChange, canIncrease, canDecrease, step ]
Cart block: line-items front end initial work (https://github.com/woocommerce/woocommerce-blocks/pull/1333) * render block on front end, add `Shopping cart` heading (baby steps) * fake data for editing full cart + show line count in header * add note about core/html using `is-active` class for toggle state * reinstate work-in-progress full cart component (lost in rebase) * reinstate full cart from master * component for full cart title & item count + margin tweaks: - add margin between main cart & sidebar - add margin after cart block * add cart items sample data + factor sample product image to module * use sample cart data for item count * basic table of cart line items (no styling) * prettification * show images for cart line items + initial table styling * cart quantity selector component (work in progress) * use state for cart product quantity, allow incr/decr from UI (WIP) * replace WIP custom quantity control with number edit (temporary) * correctly format cart line item total price * align cart item columns with headings + indent image on desktop * tweak css for cart line item padding on mobile so it's more explicit * show cart line item full price if discounted * add placeholder for cart remove item link * switch cart table to flex layout (was table)… This will allow us to move things around for mobile/responsive layout. * only show cart items table header on desktop * more cart items styling - row borders, appropriate padding + + move image width to variable + fix class name plurality for row (item not items) * use standard $gap instead of 1em for padding/margins * responsive (mobile) layout for cart line items: - shift line $ total to bottom right - stack quantity selector in product info column * remove extraneous cart table padding on mobile * comment about unused styles for quantity selector component * add follow up issue for todo * remove inappropriate href * render srcset & sizes for cart line item product image * remove todo comment * switch back to table markup for cart items (in progress): - table is more semantic, associates headers with columns * cart line items column widths - product column is larger (60%) * reinstate table row borders * bottom-align line item price on mobile * cart contents heading should be H2 + prettify * remove unused QuantitySelector code/styles, rename main class in line with BEM * defaults for QuantitySelector props * variable/property name tidies - match conventions/API * fix bug: line total price is only bottom-align on small screen * move QuantitySelector to root of components, intended to be generally useful * use lineItem directly for cart, specify shape in PropTypes * rename cart components to align with "line item" rather than "product" * rejig class names to better align with new component names & BEM style * show cart item image correct size: - use single column for product image and info, with flex container - specify image width (rem instead of px) * fix safari issue - cart product images displaying vertically stretched * shift product name left margin from image, to account for no-image case * experiment: bump bundlewatch size limit for cart temporarily: - our fake data inline image is heavy - when we switch to real API we will no longer need it * fix issue introduced when moving margin from image to details div: - product details needs margin on left (not right) * fix react props issues: - explicitly destructure image props for srcSet (vs srcset) - use API key field for line item key instead of id, fix duplicate test id - CartLineItemsTable takes an array of lineItems (incorrect PropTypes) * remove redundant divs + use conventional `null` (when no full price) * override editor styles to ensure cart product image is correct size * move cart items editor style override to editor.css * add an explicit readable heading for cart heading to match visual layout
2020-01-09 22:50:14 +00:00
);
return (
<div className={ classes }>
<input
ref={ inputRef }
className="wc-block-components-quantity-selector__input"
disabled={ disabled }
type="number"
step={ step }
min={ minimum }
max={ maximum }
value={ quantity }
onKeyDown={ quantityInputOnKeyDown }
onChange={ ( event ) => {
// Inputs values are strings, we parse them here.
let value = parseInt( event.target.value, 10 );
// parseInt would throw NaN for anything not a number,
// so we revert value to the quantity value.
value = isNaN( value ) ? quantity : value;
Support updating quantity of cart items & sold_individually product option (https://github.com/woocommerce/woocommerce-blocks/pull/1824) * first cut - removing an item from cart: - add actions to cart store for removing an item and keeping track of pending removal API call - add reducer logic for storing pending state on an item, and removing an item - expose removeCartItem on new useStoreCartItems hook - hook it up to remove link / trashcan icon in row item * disable cart quantity picker/remove link while API request in progress: - expose cart item pending status from store using selector - use selector to disable quantity related components in line item row * add typedef for cart items store object provided by hook * allow user to change quantity of cart items (first cut): - add action for replacing a cart item in the store - add generator action for changing quantity - expose change quantity action on useStoreCartItems hook - hook up to quantity UI in cart block (work in progress) * post-rebase fixes & fix broken typedef: - rework cart item change quantity callback - now supplies item key like remove callback - fix hook StoreCartItem return value typedef - single item with specified key, was array of all items - add quantity JSDoc for changeCartItemQuantity action - remove changeQuantity callback from UI (currently infinite looping) * fix bug in recieveCartItem reducer - check keys for equality: - was key === object * fix invalid url in POST cart/items/quantity request * hook up cart line item quantity to API: - remove internal state/ref for QuantitySelector, is now a controlled component - call changeQuantity action from QuantitySelector change callback * QuantitySelector no longer needs a ref to wrangle number input value * hoist quantity state out of QuantitySelector into story (fix storybook) * add product sold_individually option to cart item API response * limit sold_individually items to 1 per cart/order: - support optional max value in QuantitySelector - set maximum dependent on sold_individually API field * prevent user from requesting zero x cart item (API 500 errors): - add minimum limit to QuantitySelector - default limit to 1 + fix bug with limiting to maximum value in number input change handler * remove useStoreCartItems, zombie hook coming back from rebase 🧟‍♂️ * address various review feedback: - inline undefined check, don't use lodash - quantityInputOnKeyDown callback hook depends on canIncrease/canDecrease - also removed undefined check for minimum, as minimum has default 0 * use safer typeof check for presence of maximum prop
2020-03-03 01:08:19 +00:00
if ( value !== quantity ) {
// we commit this value immediately.
Support updating quantity of cart items & sold_individually product option (https://github.com/woocommerce/woocommerce-blocks/pull/1824) * first cut - removing an item from cart: - add actions to cart store for removing an item and keeping track of pending removal API call - add reducer logic for storing pending state on an item, and removing an item - expose removeCartItem on new useStoreCartItems hook - hook it up to remove link / trashcan icon in row item * disable cart quantity picker/remove link while API request in progress: - expose cart item pending status from store using selector - use selector to disable quantity related components in line item row * add typedef for cart items store object provided by hook * allow user to change quantity of cart items (first cut): - add action for replacing a cart item in the store - add generator action for changing quantity - expose change quantity action on useStoreCartItems hook - hook up to quantity UI in cart block (work in progress) * post-rebase fixes & fix broken typedef: - rework cart item change quantity callback - now supplies item key like remove callback - fix hook StoreCartItem return value typedef - single item with specified key, was array of all items - add quantity JSDoc for changeCartItemQuantity action - remove changeQuantity callback from UI (currently infinite looping) * fix bug in recieveCartItem reducer - check keys for equality: - was key === object * fix invalid url in POST cart/items/quantity request * hook up cart line item quantity to API: - remove internal state/ref for QuantitySelector, is now a controlled component - call changeQuantity action from QuantitySelector change callback * QuantitySelector no longer needs a ref to wrangle number input value * hoist quantity state out of QuantitySelector into story (fix storybook) * add product sold_individually option to cart item API response * limit sold_individually items to 1 per cart/order: - support optional max value in QuantitySelector - set maximum dependent on sold_individually API field * prevent user from requesting zero x cart item (API 500 errors): - add minimum limit to QuantitySelector - default limit to 1 + fix bug with limiting to maximum value in number input change handler * remove useStoreCartItems, zombie hook coming back from rebase 🧟‍♂️ * address various review feedback: - inline undefined check, don't use lodash - quantityInputOnKeyDown callback hook depends on canIncrease/canDecrease - also removed undefined check for minimum, as minimum has default 0 * use safer typeof check for presence of maximum prop
2020-03-03 01:08:19 +00:00
onChange( value );
// but once the customer has stopped typing, we make sure his value is respecting the bounds (maximum value, minimum value, step value), and commit the normalized value.
debouncedNormalizeQuantity( value );
Support updating quantity of cart items & sold_individually product option (https://github.com/woocommerce/woocommerce-blocks/pull/1824) * first cut - removing an item from cart: - add actions to cart store for removing an item and keeping track of pending removal API call - add reducer logic for storing pending state on an item, and removing an item - expose removeCartItem on new useStoreCartItems hook - hook it up to remove link / trashcan icon in row item * disable cart quantity picker/remove link while API request in progress: - expose cart item pending status from store using selector - use selector to disable quantity related components in line item row * add typedef for cart items store object provided by hook * allow user to change quantity of cart items (first cut): - add action for replacing a cart item in the store - add generator action for changing quantity - expose change quantity action on useStoreCartItems hook - hook up to quantity UI in cart block (work in progress) * post-rebase fixes & fix broken typedef: - rework cart item change quantity callback - now supplies item key like remove callback - fix hook StoreCartItem return value typedef - single item with specified key, was array of all items - add quantity JSDoc for changeCartItemQuantity action - remove changeQuantity callback from UI (currently infinite looping) * fix bug in recieveCartItem reducer - check keys for equality: - was key === object * fix invalid url in POST cart/items/quantity request * hook up cart line item quantity to API: - remove internal state/ref for QuantitySelector, is now a controlled component - call changeQuantity action from QuantitySelector change callback * QuantitySelector no longer needs a ref to wrangle number input value * hoist quantity state out of QuantitySelector into story (fix storybook) * add product sold_individually option to cart item API response * limit sold_individually items to 1 per cart/order: - support optional max value in QuantitySelector - set maximum dependent on sold_individually API field * prevent user from requesting zero x cart item (API 500 errors): - add minimum limit to QuantitySelector - default limit to 1 + fix bug with limiting to maximum value in number input change handler * remove useStoreCartItems, zombie hook coming back from rebase 🧟‍♂️ * address various review feedback: - inline undefined check, don't use lodash - quantityInputOnKeyDown callback hook depends on canIncrease/canDecrease - also removed undefined check for minimum, as minimum has default 0 * use safer typeof check for presence of maximum prop
2020-03-03 01:08:19 +00:00
}
} }
aria-label={ sprintf(
/* translators: %s refers to the item name in the cart. */
2023-12-12 23:05:20 +00:00
__( 'Quantity of %s in your cart.', 'woocommerce' ),
itemName
) }
/>
<button
ref={ decreaseButtonRef }
aria-label={ sprintf(
/* translators: %s refers to the item name in the cart. */
2023-12-12 23:05:20 +00:00
__( 'Reduce quantity of %s', 'woocommerce' ),
itemName
) }
className="wc-block-components-quantity-selector__button wc-block-components-quantity-selector__button--minus"
disabled={ ! canDecrease }
onClick={ () => {
const newQuantity = quantity - step;
Support updating quantity of cart items & sold_individually product option (https://github.com/woocommerce/woocommerce-blocks/pull/1824) * first cut - removing an item from cart: - add actions to cart store for removing an item and keeping track of pending removal API call - add reducer logic for storing pending state on an item, and removing an item - expose removeCartItem on new useStoreCartItems hook - hook it up to remove link / trashcan icon in row item * disable cart quantity picker/remove link while API request in progress: - expose cart item pending status from store using selector - use selector to disable quantity related components in line item row * add typedef for cart items store object provided by hook * allow user to change quantity of cart items (first cut): - add action for replacing a cart item in the store - add generator action for changing quantity - expose change quantity action on useStoreCartItems hook - hook up to quantity UI in cart block (work in progress) * post-rebase fixes & fix broken typedef: - rework cart item change quantity callback - now supplies item key like remove callback - fix hook StoreCartItem return value typedef - single item with specified key, was array of all items - add quantity JSDoc for changeCartItemQuantity action - remove changeQuantity callback from UI (currently infinite looping) * fix bug in recieveCartItem reducer - check keys for equality: - was key === object * fix invalid url in POST cart/items/quantity request * hook up cart line item quantity to API: - remove internal state/ref for QuantitySelector, is now a controlled component - call changeQuantity action from QuantitySelector change callback * QuantitySelector no longer needs a ref to wrangle number input value * hoist quantity state out of QuantitySelector into story (fix storybook) * add product sold_individually option to cart item API response * limit sold_individually items to 1 per cart/order: - support optional max value in QuantitySelector - set maximum dependent on sold_individually API field * prevent user from requesting zero x cart item (API 500 errors): - add minimum limit to QuantitySelector - default limit to 1 + fix bug with limiting to maximum value in number input change handler * remove useStoreCartItems, zombie hook coming back from rebase 🧟‍♂️ * address various review feedback: - inline undefined check, don't use lodash - quantityInputOnKeyDown callback hook depends on canIncrease/canDecrease - also removed undefined check for minimum, as minimum has default 0 * use safer typeof check for presence of maximum prop
2020-03-03 01:08:19 +00:00
onChange( newQuantity );
speak(
sprintf(
/* translators: %s refers to the item's new quantity in the cart. */
2023-12-12 23:05:20 +00:00
__( 'Quantity reduced to %s.', 'woocommerce' ),
newQuantity
)
);
normalizeQuantity( newQuantity );
} }
>
&#65293;
</button>
<button
ref={ increaseButtonRef }
aria-label={ sprintf(
/* translators: %s refers to the item's name in the cart. */
2023-12-12 23:05:20 +00:00
__( 'Increase quantity of %s', 'woocommerce' ),
itemName
) }
disabled={ ! canIncrease }
className="wc-block-components-quantity-selector__button wc-block-components-quantity-selector__button--plus"
onClick={ () => {
const newQuantity = quantity + step;
Support updating quantity of cart items & sold_individually product option (https://github.com/woocommerce/woocommerce-blocks/pull/1824) * first cut - removing an item from cart: - add actions to cart store for removing an item and keeping track of pending removal API call - add reducer logic for storing pending state on an item, and removing an item - expose removeCartItem on new useStoreCartItems hook - hook it up to remove link / trashcan icon in row item * disable cart quantity picker/remove link while API request in progress: - expose cart item pending status from store using selector - use selector to disable quantity related components in line item row * add typedef for cart items store object provided by hook * allow user to change quantity of cart items (first cut): - add action for replacing a cart item in the store - add generator action for changing quantity - expose change quantity action on useStoreCartItems hook - hook up to quantity UI in cart block (work in progress) * post-rebase fixes & fix broken typedef: - rework cart item change quantity callback - now supplies item key like remove callback - fix hook StoreCartItem return value typedef - single item with specified key, was array of all items - add quantity JSDoc for changeCartItemQuantity action - remove changeQuantity callback from UI (currently infinite looping) * fix bug in recieveCartItem reducer - check keys for equality: - was key === object * fix invalid url in POST cart/items/quantity request * hook up cart line item quantity to API: - remove internal state/ref for QuantitySelector, is now a controlled component - call changeQuantity action from QuantitySelector change callback * QuantitySelector no longer needs a ref to wrangle number input value * hoist quantity state out of QuantitySelector into story (fix storybook) * add product sold_individually option to cart item API response * limit sold_individually items to 1 per cart/order: - support optional max value in QuantitySelector - set maximum dependent on sold_individually API field * prevent user from requesting zero x cart item (API 500 errors): - add minimum limit to QuantitySelector - default limit to 1 + fix bug with limiting to maximum value in number input change handler * remove useStoreCartItems, zombie hook coming back from rebase 🧟‍♂️ * address various review feedback: - inline undefined check, don't use lodash - quantityInputOnKeyDown callback hook depends on canIncrease/canDecrease - also removed undefined check for minimum, as minimum has default 0 * use safer typeof check for presence of maximum prop
2020-03-03 01:08:19 +00:00
onChange( newQuantity );
speak(
sprintf(
/* translators: %s refers to the item's new quantity in the cart. */
2023-12-12 23:05:20 +00:00
__( 'Quantity increased to %s.', 'woocommerce' ),
newQuantity
)
);
normalizeQuantity( newQuantity );
} }
>
&#65291;
</button>
</div>
Cart block: line-items front end initial work (https://github.com/woocommerce/woocommerce-blocks/pull/1333) * render block on front end, add `Shopping cart` heading (baby steps) * fake data for editing full cart + show line count in header * add note about core/html using `is-active` class for toggle state * reinstate work-in-progress full cart component (lost in rebase) * reinstate full cart from master * component for full cart title & item count + margin tweaks: - add margin between main cart & sidebar - add margin after cart block * add cart items sample data + factor sample product image to module * use sample cart data for item count * basic table of cart line items (no styling) * prettification * show images for cart line items + initial table styling * cart quantity selector component (work in progress) * use state for cart product quantity, allow incr/decr from UI (WIP) * replace WIP custom quantity control with number edit (temporary) * correctly format cart line item total price * align cart item columns with headings + indent image on desktop * tweak css for cart line item padding on mobile so it's more explicit * show cart line item full price if discounted * add placeholder for cart remove item link * switch cart table to flex layout (was table)… This will allow us to move things around for mobile/responsive layout. * only show cart items table header on desktop * more cart items styling - row borders, appropriate padding + + move image width to variable + fix class name plurality for row (item not items) * use standard $gap instead of 1em for padding/margins * responsive (mobile) layout for cart line items: - shift line $ total to bottom right - stack quantity selector in product info column * remove extraneous cart table padding on mobile * comment about unused styles for quantity selector component * add follow up issue for todo * remove inappropriate href * render srcset & sizes for cart line item product image * remove todo comment * switch back to table markup for cart items (in progress): - table is more semantic, associates headers with columns * cart line items column widths - product column is larger (60%) * reinstate table row borders * bottom-align line item price on mobile * cart contents heading should be H2 + prettify * remove unused QuantitySelector code/styles, rename main class in line with BEM * defaults for QuantitySelector props * variable/property name tidies - match conventions/API * fix bug: line total price is only bottom-align on small screen * move QuantitySelector to root of components, intended to be generally useful * use lineItem directly for cart, specify shape in PropTypes * rename cart components to align with "line item" rather than "product" * rejig class names to better align with new component names & BEM style * show cart item image correct size: - use single column for product image and info, with flex container - specify image width (rem instead of px) * fix safari issue - cart product images displaying vertically stretched * shift product name left margin from image, to account for no-image case * experiment: bump bundlewatch size limit for cart temporarily: - our fake data inline image is heavy - when we switch to real API we will no longer need it * fix issue introduced when moving margin from image to details div: - product details needs margin on left (not right) * fix react props issues: - explicitly destructure image props for srcSet (vs srcset) - use API key field for line item key instead of id, fix duplicate test id - CartLineItemsTable takes an array of lineItems (incorrect PropTypes) * remove redundant divs + use conventional `null` (when no full price) * override editor styles to ensure cart product image is correct size * move cart items editor style override to editor.css * add an explicit readable heading for cart heading to match visual layout
2020-01-09 22:50:14 +00:00
);
};
export default QuantitySelector;