initial commit

This commit is contained in:
2021-12-10 12:03:04 +00:00
commit c46c7ddbf0
3643 changed files with 582794 additions and 0 deletions

View File

@ -0,0 +1,159 @@
/**
* External dependencies
*/
import { __, sprintf } from '@wordpress/i18n';
import { speak } from '@wordpress/a11y';
import classNames from 'classnames';
import { useCallback } from '@wordpress/element';
import { DOWN, UP } from '@wordpress/keycodes';
import { isNumber } from '@woocommerce/types';
/**
* Internal dependencies
*/
import './style.scss';
interface QuantitySelectorProps {
className?: string;
quantity?: number;
minimum?: number;
maximum: number;
onChange: ( newQuantity: number ) => void;
itemName?: string;
disabled: boolean;
}
const QuantitySelector = ( {
className,
quantity = 1,
minimum = 1,
maximum,
onChange = () => {
/* Do nothing. */
},
itemName = '',
disabled,
}: QuantitySelectorProps ): JSX.Element => {
const classes = classNames(
'wc-block-components-quantity-selector',
className
);
const hasMaximum = typeof maximum !== 'undefined';
const canDecrease = quantity > minimum;
const canIncrease = ! hasMaximum || quantity < maximum;
/**
* 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;
if ( isArrowDown && canDecrease ) {
event.preventDefault();
onChange( quantity - 1 );
}
if ( isArrowUp && canIncrease ) {
event.preventDefault();
onChange( quantity + 1 );
}
},
[ quantity, onChange, canIncrease, canDecrease ]
);
return (
<div className={ classes }>
<input
className="wc-block-components-quantity-selector__input"
disabled={ disabled }
type="number"
step="1"
min="0"
value={ quantity }
onKeyDown={ quantityInputOnKeyDown }
onChange={ ( event ) => {
let value =
! isNumber( event.target.value ) || ! event.target.value
? 0
: parseInt( event.target.value, 10 );
if ( hasMaximum ) {
value = Math.min( value, maximum );
}
value = Math.max( value, minimum );
if ( value !== quantity ) {
onChange( value );
}
} }
aria-label={ sprintf(
/* translators: %s refers to the item name in the cart. */
__(
'Quantity of %s in your cart.',
'woo-gutenberg-products-block'
),
itemName
) }
/>
<button
aria-label={ __(
'Reduce quantity',
'woo-gutenberg-products-block'
) }
className="wc-block-components-quantity-selector__button wc-block-components-quantity-selector__button--minus"
disabled={ disabled || ! canDecrease }
onClick={ () => {
const newQuantity = quantity - 1;
onChange( newQuantity );
speak(
sprintf(
/* translators: %s refers to the item name in the cart. */
__(
'Quantity reduced to %s.',
'woo-gutenberg-products-block'
),
newQuantity
)
);
} }
>
&#65293;
</button>
<button
aria-label={ __(
'Increase quantity',
'woo-gutenberg-products-block'
) }
disabled={ disabled || ! canIncrease }
className="wc-block-components-quantity-selector__button wc-block-components-quantity-selector__button--plus"
onClick={ () => {
const newQuantity = quantity + 1;
onChange( newQuantity );
speak(
sprintf(
/* translators: %s refers to the item name in the cart. */
__(
'Quantity increased to %s.',
'woo-gutenberg-products-block'
),
newQuantity
)
);
} }
>
&#65291;
</button>
</div>
);
};
export default QuantitySelector;

View File

@ -0,0 +1,30 @@
/**
* External dependencies
*/
import { boolean } from '@storybook/addon-knobs';
import { useState } from 'react';
/**
* Internal dependencies
*/
import QuantitySelector from '../';
export default {
title: 'WooCommerce Blocks/@base-components/QuantitySelector',
component: QuantitySelector,
};
export const Default = () => {
const [ quantity, changeQuantity ] = useState();
return (
<div style={ { width: 100 } }>
<QuantitySelector
disabled={ boolean( 'Disabled', false ) }
quantity={ quantity }
onChange={ changeQuantity }
itemName="widgets"
/>
</div>
);
};

View File

@ -0,0 +1,121 @@
@mixin reset-button {
border: 0;
padding: 0;
margin: 0;
background: none transparent;
box-shadow: none;
&:focus {
outline: 2px solid $gray-300;
}
}
.wc-block-components-quantity-selector {
display: flex;
width: 107px;
border: 1px solid $gray-300;
background: #fff;
border-radius: 4px;
// needed so that buttons fill the container.
box-sizing: content-box;
margin: 0 0 0.25em 0;
.has-dark-controls & {
background-color: transparent;
border-color: $input-border-dark;
}
// Extra label for specificity needed in the editor.
input.wc-block-components-quantity-selector__input {
@include font-size(regular);
order: 2;
min-width: 40px;
flex: 1 1 auto;
border: 0;
padding: 0.4em 0;
margin: 0;
text-align: center;
background: transparent;
box-shadow: none;
color: #000;
line-height: 1;
vertical-align: middle;
-moz-appearance: textfield;
&:focus {
background: $gray-100;
outline: 1px solid $gray-300;
}
&:disabled {
color: $gray-600;
}
.has-dark-controls & {
color: $input-text-dark;
background: transparent;
&:focus {
background: transparent;
}
&:disabled {
color: $input-disabled-dark;
}
}
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.wc-block-components-quantity-selector__button {
@include reset-button;
@include font-size(regular);
min-width: 30px;
cursor: pointer;
color: $gray-900;
font-style: normal;
text-align: center;
text-decoration: none;
&:hover,
&:focus {
@include reset-button;
color: $gray-900;
}
&:disabled {
color: $gray-600;
cursor: default;
@include reset-button;
}
.has-dark-controls & {
color: $input-text-dark;
&:hover,
&:focus {
color: $input-text-dark;
}
&:disabled {
color: $input-disabled-dark;
}
}
}
> .wc-block-components-quantity-selector__button--minus {
order: 1;
}
> .wc-block-components-quantity-selector__button--plus {
order: 3;
}
}
.theme-twentyseventeen {
.wc-block-components-quantity-selector .wc-block-components-quantity-selector__button {
&:hover,
&:focus {
background: none transparent;
}
}
}