From 8c74ec7837594bf77277005694ab6b05729d16a7 Mon Sep 17 00:00:00 2001 From: Sagar Jadhav Date: Mon, 7 Oct 2024 10:44:53 +0530 Subject: [PATCH 1/4] Web component: Number Spinner --- src/number-spinner/README.md | 41 ++++++++++++ src/number-spinner/index.html | 64 +++++++++++++++++++ src/number-spinner/index.ts | 20 ++++++ src/number-spinner/style.scss | 3 + .../tp-number-spinner-decrement.ts | 56 ++++++++++++++++ .../tp-number-spinner-increment.ts | 57 +++++++++++++++++ src/number-spinner/tp-number-spinner-input.ts | 5 ++ src/number-spinner/tp-number-spinner.ts | 5 ++ webpack.config.js | 1 + 9 files changed, 252 insertions(+) create mode 100644 src/number-spinner/README.md create mode 100644 src/number-spinner/index.html create mode 100644 src/number-spinner/index.ts create mode 100644 src/number-spinner/style.scss create mode 100644 src/number-spinner/tp-number-spinner-decrement.ts create mode 100644 src/number-spinner/tp-number-spinner-increment.ts create mode 100644 src/number-spinner/tp-number-spinner-input.ts create mode 100644 src/number-spinner/tp-number-spinner.ts diff --git a/src/number-spinner/README.md b/src/number-spinner/README.md new file mode 100644 index 0000000..820dbc0 --- /dev/null +++ b/src/number-spinner/README.md @@ -0,0 +1,41 @@ +# Form + + + + + + +
+

Built by the super talented team at Travelopia.

+
+ +
+ +## Sample Usage + +This is a number spinner component that is designed to be highly extendable. + +Example: + +```js +// Import the component as needed: +import '@travelopia/web-components/dist/number-spinner'; + +// TypeScript usage: +import { TPNumberSpinner, TPNumberSpinnerInput, TPNumberSpinnerIncrement, TPNumberSpinnerDecrement } from '@travelopia/web-components'; + +... + +const form: TPFormElement = document.querySelector( 'tp-form' ); +form.resetValidation(); +``` + +```html + + + + + + + +``` diff --git a/src/number-spinner/index.html b/src/number-spinner/index.html new file mode 100644 index 0000000..8b9152b --- /dev/null +++ b/src/number-spinner/index.html @@ -0,0 +1,64 @@ + + + + + + + Web Component: Number Spinner + + + + + + +
+ + + + + + + + +

+ + + + + + + + + +

+ + + + + + + + + +

+ + + + + + + + + +

+ + + + + + + + +
+ + diff --git a/src/number-spinner/index.ts b/src/number-spinner/index.ts new file mode 100644 index 0000000..de0506e --- /dev/null +++ b/src/number-spinner/index.ts @@ -0,0 +1,20 @@ +/** + * Styles. + */ +import './style.scss'; + +/** + * Components. + */ +import { TPNumberSpinnerInput } from './tp-number-spinner-input'; +import { TPNumberSpinnerIncrement } from './tp-number-spinner-increment'; +import { TPNumberSpinnerDecrement } from './tp-number-spinner-decrement'; +import { TPNumberSpinner } from './tp-number-spinner'; + +/** + * Register Components. + */ +customElements.define( 'tp-number-spinner-input', TPNumberSpinnerInput ); +customElements.define( 'tp-number-spinner-increment', TPNumberSpinnerIncrement ); +customElements.define( 'tp-number-spinner-decrement', TPNumberSpinnerDecrement ); +customElements.define( 'tp-number-spinner', TPNumberSpinner ); diff --git a/src/number-spinner/style.scss b/src/number-spinner/style.scss new file mode 100644 index 0000000..6d02b9a --- /dev/null +++ b/src/number-spinner/style.scss @@ -0,0 +1,3 @@ +tp-number-spinner { + display: contents; +} diff --git a/src/number-spinner/tp-number-spinner-decrement.ts b/src/number-spinner/tp-number-spinner-decrement.ts new file mode 100644 index 0000000..972b197 --- /dev/null +++ b/src/number-spinner/tp-number-spinner-decrement.ts @@ -0,0 +1,56 @@ +/** + * TP Number Spinner Decrement Element. + */ +export class TPNumberSpinnerDecrement extends HTMLElement { + private min: number = 0; + private step: number = 1; + private value: number = 0; + private inputElement: HTMLInputElement | null = null; + + /** + * Constructor. + */ + constructor() { + // Initialize parent. + super(); + + // Get the input element from the closest tp-number-spinner. + this.inputElement = this.closest( 'tp-number-spinner' )?.querySelector( 'tp-number-spinner-input input' ) as HTMLInputElement | null; + + // If the input element is found, initialize min, max, step, and value. + if ( this.inputElement ) { + this.min = parseInt( this.inputElement.getAttribute('min') || '0', 10 ); + this.step = parseInt( this.inputElement.getAttribute('step') || '1', 10 ); + this.value = parseInt( this.inputElement.value || '0', 10 ); + + // Initialize the input element with the value. + this.inputElement.value = this.value.toString(); + } + + // Attach click event for decrement. + this.querySelector( 'button' )?.addEventListener( 'click', this.decrement.bind( this ) ); + } + + /** + * Decrement the value. + */ + decrement(): void { + // Check for input element. + if ( ! this.inputElement ) { + return; + } + + // Parse the current value from the input. + const currentValue: number = parseInt( this.inputElement.value, 10 ) || this.value; + + // Calculate the new value. + const newValue: number = currentValue - this.step; + + // Check if the new value is within the min limit. + if ( newValue >= this.min ) { + // Update the value and input field. + this.value = newValue; + this.inputElement.value = this.value.toString(); + } + } +} diff --git a/src/number-spinner/tp-number-spinner-increment.ts b/src/number-spinner/tp-number-spinner-increment.ts new file mode 100644 index 0000000..a76cfc0 --- /dev/null +++ b/src/number-spinner/tp-number-spinner-increment.ts @@ -0,0 +1,57 @@ +/** + * TP Number Spinner Increment Element. + */ +export class TPNumberSpinnerIncrement extends HTMLElement { + private min: number = 0; + private max: number = 100; + private step: number = 1; + private value: number = 0; + private inputElement: HTMLInputElement | null = null; + + /** + * Constructor. + */ + constructor() { + // Initialize parent. + super(); + + // Get the input element from the closest tp-number-spinner. + this.inputElement = this.closest( 'tp-number-spinner' )?.querySelector( 'tp-number-spinner-input input' ) as HTMLInputElement | null; + + // If the input element is found, initialize min, max, step, and value from the input attributes. + if ( this.inputElement ) { + this.min = parseInt( this.inputElement.getAttribute( 'min' ) || '0', 10 ); + this.max = parseInt( this.inputElement.getAttribute( 'max' ) || '100', 10 ); + this.step = parseInt( this.inputElement.getAttribute( 'step' ) || '1', 10 ); + this.value = parseInt( this.inputElement.value || this.min.toString(), 10 ); + + // Initialize the input element with the value. + this.inputElement.value = this.value.toString(); + } + + // Attach click event for increment. + this.querySelector( 'button' )?.addEventListener( 'click', this.increment.bind( this ) ); + } + + /** + * Increment the value. + */ + increment(): void { + if ( ! this.inputElement ) { + return; + } + + // Parse the current value from the input. + const currentValue: number = parseInt( this.inputElement.value, 10 ) || this.value; + + // Calculate the new value. + const newValue: number = currentValue + this.step; + + // Check if the new value is within the max limit. + if ( newValue <= this.max ) { + // Update the value and input field. + this.value = newValue; + this.inputElement.value = this.value.toString(); + } + } +} diff --git a/src/number-spinner/tp-number-spinner-input.ts b/src/number-spinner/tp-number-spinner-input.ts new file mode 100644 index 0000000..b5b16aa --- /dev/null +++ b/src/number-spinner/tp-number-spinner-input.ts @@ -0,0 +1,5 @@ +/** + * TP Number Spinner Input. + */ +export class TPNumberSpinnerInput extends HTMLElement { +} diff --git a/src/number-spinner/tp-number-spinner.ts b/src/number-spinner/tp-number-spinner.ts new file mode 100644 index 0000000..2af79e6 --- /dev/null +++ b/src/number-spinner/tp-number-spinner.ts @@ -0,0 +1,5 @@ +/** + * TP Number Spinner Element. + */ +export class TPNumberSpinner extends HTMLElement { +} diff --git a/webpack.config.js b/webpack.config.js index 67df031..a347deb 100755 --- a/webpack.config.js +++ b/webpack.config.js @@ -84,6 +84,7 @@ module.exports = ( env ) => { 'multi-select': './src/multi-select/index.ts', lightbox: './src/lightbox/index.ts', 'toggle-attribute': './src/toggle-attribute/index.ts', + 'number-spinner': './src/number-spinner/index.ts', }, module: { rules: [ From 4f8f98820c6f80a86bb82920c6f910e18fec2f52 Mon Sep 17 00:00:00 2001 From: Sagar Jadhav Date: Mon, 7 Oct 2024 10:46:09 +0530 Subject: [PATCH 2/4] Web component: Number Spinner --- src/number-spinner/README.md | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/number-spinner/README.md b/src/number-spinner/README.md index 820dbc0..8dd25d7 100644 --- a/src/number-spinner/README.md +++ b/src/number-spinner/README.md @@ -24,18 +24,14 @@ import '@travelopia/web-components/dist/number-spinner'; // TypeScript usage: import { TPNumberSpinner, TPNumberSpinnerInput, TPNumberSpinnerIncrement, TPNumberSpinnerDecrement } from '@travelopia/web-components'; -... - -const form: TPFormElement = document.querySelector( 'tp-form' ); -form.resetValidation(); ``` ```html - - - - - - - + + + + + + + ``` From 84a40412644269f63ba71ae817373342c5f0b6c6 Mon Sep 17 00:00:00 2001 From: Sagar Jadhav Date: Mon, 7 Oct 2024 10:52:39 +0530 Subject: [PATCH 3/4] Fixes - lint issues --- src/number-spinner/tp-number-spinner-decrement.ts | 8 +++++--- src/number-spinner/tp-number-spinner-increment.ts | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/number-spinner/tp-number-spinner-decrement.ts b/src/number-spinner/tp-number-spinner-decrement.ts index 972b197..9748925 100644 --- a/src/number-spinner/tp-number-spinner-decrement.ts +++ b/src/number-spinner/tp-number-spinner-decrement.ts @@ -19,8 +19,9 @@ export class TPNumberSpinnerDecrement extends HTMLElement { // If the input element is found, initialize min, max, step, and value. if ( this.inputElement ) { - this.min = parseInt( this.inputElement.getAttribute('min') || '0', 10 ); - this.step = parseInt( this.inputElement.getAttribute('step') || '1', 10 ); + // set the values. + this.min = parseInt( this.inputElement.getAttribute( 'min' ) || '0', 10 ); + this.step = parseInt( this.inputElement.getAttribute( 'step' ) || '1', 10 ); this.value = parseInt( this.inputElement.value || '0', 10 ); // Initialize the input element with the value. @@ -35,8 +36,9 @@ export class TPNumberSpinnerDecrement extends HTMLElement { * Decrement the value. */ decrement(): void { - // Check for input element. + // Check if the input element exists. if ( ! this.inputElement ) { + // Return if the input element does not exist. return; } diff --git a/src/number-spinner/tp-number-spinner-increment.ts b/src/number-spinner/tp-number-spinner-increment.ts index a76cfc0..529aea5 100644 --- a/src/number-spinner/tp-number-spinner-increment.ts +++ b/src/number-spinner/tp-number-spinner-increment.ts @@ -20,6 +20,7 @@ export class TPNumberSpinnerIncrement extends HTMLElement { // If the input element is found, initialize min, max, step, and value from the input attributes. if ( this.inputElement ) { + // set the values. this.min = parseInt( this.inputElement.getAttribute( 'min' ) || '0', 10 ); this.max = parseInt( this.inputElement.getAttribute( 'max' ) || '100', 10 ); this.step = parseInt( this.inputElement.getAttribute( 'step' ) || '1', 10 ); @@ -37,7 +38,9 @@ export class TPNumberSpinnerIncrement extends HTMLElement { * Increment the value. */ increment(): void { + // Check if the input element exists. if ( ! this.inputElement ) { + // Return if the input element does not exist. return; } From a557659cb547dbf4b21bed9233539dac2d73eb0f Mon Sep 17 00:00:00 2001 From: Junaid Bhura Date: Mon, 7 Oct 2024 17:17:38 +1100 Subject: [PATCH 4/4] refactor component --- src/number-spinner/README.md | 12 +- src/number-spinner/index.html | 30 +--- .../tp-number-spinner-decrement.ts | 45 ++---- .../tp-number-spinner-increment.ts | 47 ++---- src/number-spinner/tp-number-spinner.ts | 135 ++++++++++++++++++ 5 files changed, 166 insertions(+), 103 deletions(-) diff --git a/src/number-spinner/README.md b/src/number-spinner/README.md index 8dd25d7..a844f3e 100644 --- a/src/number-spinner/README.md +++ b/src/number-spinner/README.md @@ -27,11 +27,19 @@ import { TPNumberSpinner, TPNumberSpinnerInput, TPNumberSpinnerIncrement, TPNumb ``` ```html - + - + ``` + +## Attributes + +| Attribute | Required | Values | Notes | +|-----------|----------|-----------------------|----------------------------------------| +| min | No | | The minimum value of the spinner | +| max | No | | The maxium value of the spinner | +| step | No | | The step of the spinner. Defaults to 1 | diff --git a/src/number-spinner/index.html b/src/number-spinner/index.html index 8b9152b..fd8c011 100644 --- a/src/number-spinner/index.html +++ b/src/number-spinner/index.html @@ -15,47 +15,27 @@ - +

- - - - - - - - -

- - + - +

- - - - - - - - -

- - + - + diff --git a/src/number-spinner/tp-number-spinner-decrement.ts b/src/number-spinner/tp-number-spinner-decrement.ts index 9748925..a5d8cb4 100644 --- a/src/number-spinner/tp-number-spinner-decrement.ts +++ b/src/number-spinner/tp-number-spinner-decrement.ts @@ -1,12 +1,12 @@ +/** + * Internal dependencies. + */ +import { TPNumberSpinner } from './tp-number-spinner'; + /** * TP Number Spinner Decrement Element. */ export class TPNumberSpinnerDecrement extends HTMLElement { - private min: number = 0; - private step: number = 1; - private value: number = 0; - private inputElement: HTMLInputElement | null = null; - /** * Constructor. */ @@ -14,20 +14,6 @@ export class TPNumberSpinnerDecrement extends HTMLElement { // Initialize parent. super(); - // Get the input element from the closest tp-number-spinner. - this.inputElement = this.closest( 'tp-number-spinner' )?.querySelector( 'tp-number-spinner-input input' ) as HTMLInputElement | null; - - // If the input element is found, initialize min, max, step, and value. - if ( this.inputElement ) { - // set the values. - this.min = parseInt( this.inputElement.getAttribute( 'min' ) || '0', 10 ); - this.step = parseInt( this.inputElement.getAttribute( 'step' ) || '1', 10 ); - this.value = parseInt( this.inputElement.value || '0', 10 ); - - // Initialize the input element with the value. - this.inputElement.value = this.value.toString(); - } - // Attach click event for decrement. this.querySelector( 'button' )?.addEventListener( 'click', this.decrement.bind( this ) ); } @@ -36,23 +22,8 @@ export class TPNumberSpinnerDecrement extends HTMLElement { * Decrement the value. */ decrement(): void { - // Check if the input element exists. - if ( ! this.inputElement ) { - // Return if the input element does not exist. - return; - } - - // Parse the current value from the input. - const currentValue: number = parseInt( this.inputElement.value, 10 ) || this.value; - - // Calculate the new value. - const newValue: number = currentValue - this.step; - - // Check if the new value is within the min limit. - if ( newValue >= this.min ) { - // Update the value and input field. - this.value = newValue; - this.inputElement.value = this.value.toString(); - } + // Run function on parent. + const numberSpinner: TPNumberSpinner | null = this.closest( 'tp-number-spinner' ); + numberSpinner?.decrement(); } } diff --git a/src/number-spinner/tp-number-spinner-increment.ts b/src/number-spinner/tp-number-spinner-increment.ts index 529aea5..ace0abc 100644 --- a/src/number-spinner/tp-number-spinner-increment.ts +++ b/src/number-spinner/tp-number-spinner-increment.ts @@ -1,13 +1,12 @@ +/** + * Internal dependencies. + */ +import { TPNumberSpinner } from './tp-number-spinner'; + /** * TP Number Spinner Increment Element. */ export class TPNumberSpinnerIncrement extends HTMLElement { - private min: number = 0; - private max: number = 100; - private step: number = 1; - private value: number = 0; - private inputElement: HTMLInputElement | null = null; - /** * Constructor. */ @@ -15,21 +14,6 @@ export class TPNumberSpinnerIncrement extends HTMLElement { // Initialize parent. super(); - // Get the input element from the closest tp-number-spinner. - this.inputElement = this.closest( 'tp-number-spinner' )?.querySelector( 'tp-number-spinner-input input' ) as HTMLInputElement | null; - - // If the input element is found, initialize min, max, step, and value from the input attributes. - if ( this.inputElement ) { - // set the values. - this.min = parseInt( this.inputElement.getAttribute( 'min' ) || '0', 10 ); - this.max = parseInt( this.inputElement.getAttribute( 'max' ) || '100', 10 ); - this.step = parseInt( this.inputElement.getAttribute( 'step' ) || '1', 10 ); - this.value = parseInt( this.inputElement.value || this.min.toString(), 10 ); - - // Initialize the input element with the value. - this.inputElement.value = this.value.toString(); - } - // Attach click event for increment. this.querySelector( 'button' )?.addEventListener( 'click', this.increment.bind( this ) ); } @@ -38,23 +22,8 @@ export class TPNumberSpinnerIncrement extends HTMLElement { * Increment the value. */ increment(): void { - // Check if the input element exists. - if ( ! this.inputElement ) { - // Return if the input element does not exist. - return; - } - - // Parse the current value from the input. - const currentValue: number = parseInt( this.inputElement.value, 10 ) || this.value; - - // Calculate the new value. - const newValue: number = currentValue + this.step; - - // Check if the new value is within the max limit. - if ( newValue <= this.max ) { - // Update the value and input field. - this.value = newValue; - this.inputElement.value = this.value.toString(); - } + // Run function on parent. + const numberSpinner: TPNumberSpinner | null = this.closest( 'tp-number-spinner' ); + numberSpinner?.increment(); } } diff --git a/src/number-spinner/tp-number-spinner.ts b/src/number-spinner/tp-number-spinner.ts index 2af79e6..931489c 100644 --- a/src/number-spinner/tp-number-spinner.ts +++ b/src/number-spinner/tp-number-spinner.ts @@ -2,4 +2,139 @@ * TP Number Spinner Element. */ export class TPNumberSpinner extends HTMLElement { + /** + * Get minimum value. + * + * @return {number|null} The minimum value. + */ + get min(): number | null { + // Get minimum attribute. + const min: string | null = this.getAttribute( 'min' ); + + // Check if we have an attribute. + if ( min ) { + // Yep, return its value. + return parseInt( min ); + } + + // Nope, return null. + return null; + } + + /** + * Set minimum value. + * + * @param {number} min Minimum value. + */ + set min( min: number ) { + // Set attribute. + this.setAttribute( 'min', min.toString() ); + } + + /** + * Get maximum value. + * + * @return {number|null} The maximum value. + */ + get max(): number | null { + // Get maximum attribute. + const max: string | null = this.getAttribute( 'max' ); + + // Check if we have an attribute. + if ( max ) { + // Yep, return its value. + return parseInt( max ); + } + + // Nope, return null. + return null; + } + + /** + * Set maximum value. + * + * @param {number} max Maximum value. + */ + set max( max: number ) { + // Set attribute. + this.setAttribute( 'max', max.toString() ); + } + + /** + * Get current step. + * + * @return {number} Current step. + */ + get step(): number { + // Get step from attribute. + return parseInt( this.getAttribute( 'step' ) ?? '1' ); + } + + /** + * Set current step. + * + * @param {number} step Current step. + */ + set step( step: number ) { + // Set attribute. + this.setAttribute( 'step', step.toString() ); + } + + /** + * Get value. + * + * @return {number} The value. + */ + get value(): number { + // Get value from input. + return parseInt( this.querySelector( 'tp-number-spinner-input input' )?.getAttribute( 'value' ) ?? '0' ); + } + + /** + * Set current value. + * + * @param {number} value Current value. + */ + set value( value: number ) { + // Set input's value. + this.querySelector( 'tp-number-spinner-input input' )?.setAttribute( 'value', value.toString() ); + } + + /** + * Increment. + */ + increment(): void { + // Calculate new value. + const currentValue: number = this.value; + const max: number | null = this.max; + const newValue: number = currentValue + this.step; + + // Check if new value is greater than the maximum. + if ( max && newValue > max ) { + // Yes, that's not allowed. + return; + } + + // No, set its value. + this.value = newValue; + } + + /** + * Decrement. + */ + decrement(): void { + // Calculate new value. + const currentValue: number = this.value; + const min: number | null = this.min; + const newValue: number = currentValue - this.step; + + // Check if new value is less than the minumum. + if ( min && newValue < min ) { + // Yes, that's not allowed. + return; + } + + // No, set its value. + this.value = newValue; + } }