Skip to content

Commit

Permalink
feat(range): add example
Browse files Browse the repository at this point in the history
Signed-off-by: Alexandre Esteves <alexandre.esteves.ae@gmail.com>
  • Loading branch information
aesteves60 authored and dpellier committed Nov 28, 2024
1 parent 03d24b8 commit 31b6f4b
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 63 deletions.
10 changes: 5 additions & 5 deletions packages/examples/react-webpack/src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import React, { type ReactElement } from 'react';
import styles from './app.scss';
// import { Gallery } from './components/gallery/Gallery';
import { FormFormik } from './components/formFormik/FormFormik';
// import { FormFormik } from './components/formFormik/FormFormik';
// import { FormHookForm } from './components/formHookForm/FormHookForm';
// import { FormNative } from './components/formNative/FormNative';
import { FormNative } from './components/formNative/FormNative';
// import { TestModal } from './components/testModal/TestModal';
// import { TestSelect } from './components/testSelect/TestSelect';

Expand All @@ -14,9 +14,9 @@ function App(): ReactElement {
return (
<div className={ styles.app }>
{/*<Gallery />*/}
<FormFormik />
{/*<FormHookForm />*/}
{/*<FormNative />*/}
{/* <FormFormik /> */}
{/* <FormHookForm /> */}
<FormNative />
{/*<QueryClientProvider client={queryClient}>*/}
{/* <TestSelect />*/}
{/*</QueryClientProvider>*/}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ODS_INPUT_TYPE } from '@ovhcloud/ods-components';
import { OdsButton, OdsCheckbox, OdsDatepicker, OdsInput, OdsPassword, OdsPhoneNumber, OdsQuantity, OdsRadio, OdsSelect, OdsSwitch, OdsSwitchItem, OdsTextarea, OdsTimepicker } from '@ovhcloud/ods-components/react';
import { OdsButton, OdsCheckbox, OdsDatepicker, OdsInput, OdsPassword, OdsPhoneNumber, OdsQuantity, OdsRadio, OdsRange, OdsSelect, OdsSwitch, OdsSwitchItem, OdsTextarea, OdsTimepicker } from '@ovhcloud/ods-components/react';
import { useFormik } from 'formik';
import React, { type ReactElement, useState } from 'react';
import * as yup from 'yup';
Expand All @@ -16,6 +16,7 @@ type FormData = {
phoneNumberWithCountries: string,
quantity: number,
radio: string,
range: number,
select: string,
switch: string,
textarea: string,
Expand All @@ -33,6 +34,7 @@ const validationSchema = yup.object<FormData>({
quantity: yup.number().nullable(),//.required(),
radio: yup.string().nullable(),//.required(),
radioTest: yup.string().nullable(),//.required(),
range: yup.number().nullable(),//.required(),
select: yup.string().nullable(),//.required(),
switch: yup.string().nullable(),//.required(),
textarea: yup.string().nullable(),//.required(),
Expand All @@ -53,6 +55,7 @@ function FormFormik(): ReactElement {
phoneNumberWithCountries: '+33123456789',
quantity: 0,
radio: 'radio1',
range: 0,
select: 'cat',
switch: 'switch1',
textarea: 'default textarea',
Expand All @@ -64,9 +67,9 @@ function FormFormik(): ReactElement {
validateOnMount: true,
validationSchema,
});
const [areAllRequired, setAreAllRequired] = useState(false);
const [areAllRequired, setAreAllRequired] = useState(true);

function onAllRequiredToggle() {
function onAllRequiredToggle(): void {
setAreAllRequired(() => !areAllRequired);
}

Expand All @@ -75,8 +78,9 @@ function FormFormik(): ReactElement {
className={ styles['form-formik'] }
onSubmit={ formik.handleSubmit }>
<div>
<button onClick={ onAllRequiredToggle }
type="button">
<button
onClick={ onAllRequiredToggle }
type="button">
Toggle All Required (broken)
</button>
</div>
Expand Down Expand Up @@ -212,7 +216,7 @@ function FormFormik(): ReactElement {
name="radio"
onOdsBlur={ formik.handleBlur }
onOdsChange={ (e) => {
formik.setFieldValue('radio', e.detail.checked ? e.detail.value : null);
formik.setFieldValue('radio', e.detail.checked ? e.detail.value : null);
}}
value="radio1"
/>
Expand All @@ -225,13 +229,23 @@ function FormFormik(): ReactElement {
name="radio"
onOdsBlur={ formik.handleBlur }
onOdsChange={ (e) => {
formik.setFieldValue('radio', e.detail.checked ? e.detail.value : null);
formik.setFieldValue('radio', e.detail.checked ? e.detail.value : null);
}}
value="radio2"
/>
<label htmlFor="radio2">Radio 2</label>
</div>

<div style={{ display: 'inline-flex' }}>
<OdsRange
hasError={ formik.touched.range && !!formik.errors.range }
isRequired={ areAllRequired }
name="range"
onOdsBlur={ formik.handleBlur }
onOdsChange={ formik.handleChange}
></OdsRange>
</div>

<OdsSelect
defaultValue={ formik.initialValues.select }
hasError={ formik.touched.select && !!formik.errors.select }
Expand All @@ -251,7 +265,7 @@ function FormFormik(): ReactElement {
<OdsSwitch
isRequired={ areAllRequired }
name="switch"
onOdsChange={ (e)=> {
onOdsChange={ (e) => {
formik.setFieldValue('switch', e.detail.value || '');
}}
>
Expand Down Expand Up @@ -293,12 +307,14 @@ function FormFormik(): ReactElement {
</p>

<div>
<OdsButton label="Reset button"
type="reset"
variant="outline" />
<OdsButton
label="Reset button"
type="reset"
variant="outline" />

<OdsButton label="Submit button"
type="submit" />
<OdsButton
label="Submit button"
type="submit" />
</div>
</form>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ODS_INPUT_TYPE } from '@ovhcloud/ods-components';
import { OdsButton, OdsCheckbox, OdsDatepicker, OdsInput, OdsPassword, OdsPhoneNumber, OdsQuantity, OdsRadio, OdsSelect, OdsSwitch, OdsSwitchItem, OdsTextarea, OdsTimepicker } from '@ovhcloud/ods-components/react';
import { OdsButton, OdsCheckbox, OdsDatepicker, OdsRange, OdsInput, OdsPassword, OdsPhoneNumber, OdsQuantity, OdsRadio, OdsSelect, OdsSwitch, OdsSwitchItem, OdsTextarea, OdsTimepicker } from '@ovhcloud/ods-components/react';
import React, { type ReactElement, useState } from 'react';
import { Controller, useForm } from 'react-hook-form';
import styles from './formHookForm.scss';
Expand All @@ -15,6 +15,7 @@ type FormData = {
phoneNumberWithCountries: string,
quantity: number,
radio: string,
range: number,
select: string,
switch: string,
textarea: string,
Expand All @@ -33,6 +34,7 @@ const defaultValue: FormData = {
phoneNumberWithCountries: '+33123456789',
quantity: 0,
radio: 'radio1',
range: 0,
select: 'cat',
switch: 'switch1',
textarea: 'default textarea',
Expand Down Expand Up @@ -296,6 +298,24 @@ function FormHookForm(): ReactElement {
}
/>

<div style={{ display: 'inline-flex' }}>
<Controller
control={ control }
name="range"
rules={{ required: areAllRequired }}
render={({ field }) =>
<OdsRange
defaultValue={ defaultValue.range }
isRequired={ areAllRequired }
name={ field.name }
onOdsBlur={ field.onBlur }
onOdsChange={ field.onChange }
>
</OdsRange>
}
/>
</div>

<Controller
control={ control }
name="select"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ODS_INPUT_TYPE } from '@ovhcloud/ods-components';
import { OdsButton, OdsCheckbox, OdsDatepicker, OdsInput, OdsPassword, OdsPhoneNumber, OdsQuantity, OdsRadio, OdsSelect, OdsSwitch, OdsSwitchItem, OdsTextarea, OdsTimepicker } from '@ovhcloud/ods-components/react';
import { OdsButton, OdsCheckbox, OdsDatepicker, OdsInput, OdsPassword, OdsPhoneNumber, OdsQuantity, OdsRadio, OdsRange, OdsSelect, OdsSwitch, OdsSwitchItem, OdsTextarea, OdsTimepicker } from '@ovhcloud/ods-components/react';
import React, { type FormEvent, type ReactElement, useRef, useState } from 'react';
import styles from './formNative.scss';

Expand Down Expand Up @@ -129,6 +129,14 @@ function FormNative(): ReactElement {
<label htmlFor="radio2">Radio 2</label>
</div>

<div style={{ display: 'inline-flex' }}>
<OdsRange
isRequired={ areAllRequired }
name="range"
value={70}
/>
</div>

<OdsSelect
isRequired={ areAllRequired }
name="select"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export class OdsRange {
private inputRangeId = 'input-range';
private inputRangeDualId = 'input-range-dual';
private observable?: MutationObserver;
private shouldEmitOdsChange = false;
private shouldUpdateIsInvalidState: boolean = false;
private tooltip?: OdsTooltip;
private tooltipDual?: OdsTooltip;
Expand Down Expand Up @@ -71,6 +70,7 @@ export class OdsRange {
this.value = null;
}
this.odsClear.emit();
this.emitOdsChange();
}

@Method()
Expand Down Expand Up @@ -101,6 +101,7 @@ export class OdsRange {
this.value = this.defaultValue ?? null;
}
this.odsReset.emit();
this.emitOdsChange();
}

@Method()
Expand Down Expand Up @@ -144,42 +145,32 @@ export class OdsRange {
}

@Watch('value')
private onValueChange(): void {
if (isDualRange(this.value)) {
private onValueChange(value: number | [number, number] | [ null, null] | null = this.value): void {
if (isDualRange(value)) {
this.isDualRange = true;
this.changeValues(this.value[0], this.value[1]);
this.fillInputs(value[0], value[1]);
} else {
this.isDualRange = false;
this.changeValues(this.value ?? null);
this.fillInputs(value);
}

updateInternals(this.internals, this.value, this.isRequired);
updateInternals(this.internals, value, this.isRequired);

// In case the value gets updated from an other source than a blur event
// we may have to perform an internal validity state update
if (this.shouldUpdateIsInvalidState) {
this.isInvalid = !this.internals.validity.valid;
this.shouldUpdateIsInvalidState = false;
}

if (!this.shouldEmitOdsChange) {
return;
}

this.odsChange.emit({
name: this.name,
validity: this.internals.validity,
value: this.value,
});
}

componentWillLoad(): void {
this.hostId = this.el.id || getRandomHTMLId();
this.value = getInitialValue(this.value, this.min, this.max, this.defaultValue);
this.shouldEmitOdsChange = true;

this.onMinOrMaxChange();
this.onValueChange();
this.emitOdsChange();

this.observable = new MutationObserver((mutations) => {
for (const mutation of mutations) {
Expand Down Expand Up @@ -213,7 +204,7 @@ export class OdsRange {
await this.reset();
}

private changeValues(currentValue: number | null, dualValue?: number | null): number | [number, number]| [null, null] | undefined {
private fillInputs(currentValue: number | null, dualValue?: number | null): number | [number, number]| [null, null] | undefined {
let value: number | [number, number] | [null, null] | undefined;

if (this.isDualRange) {
Expand All @@ -227,35 +218,38 @@ export class OdsRange {
return value;
}

private emitOdsChange(): void {
this.odsChange.emit({
name: this.name,
validity: this.internals.validity,
value: this.value,
});
}

private onBlur(): void {
this.isInvalid = !this.internals.validity.valid;
this.odsBlur.emit();
}

private onInput(isDualInput: boolean): void {
if (!this.inputEl || (isDualInput && !this.inputElDual)) {
return;
}
const step = this.step ?? 1;
const isInputsValuesEqual = Number(this.inputElDual?.value) - Number(this.inputEl?.value) < step;
const isInputsValuesEqual = (this.inputElDual?.valueAsNumber ?? 0) - this.inputEl?.valueAsNumber < step;
if (isInputsValuesEqual) {
if (isDualInput) {
this.onInputElDual(step);
this.setInputElDualValue(step);
} else {
this.onInputEl(step);
this.setInputElValue(step);
}
}

this.isDualRange = isDualRange(this.value);
this.value = this.changeValues(Number(this.inputEl?.value), Number(this.inputElDual?.value)) ?? null;
}

private onInputEl(step : number): void {
if (this.inputEl && this.inputElDual) {
this.inputEl.value = `${(Number(this.inputElDual.value) ?? 0) - step}`;
}
}

private onInputElDual(step : number): void {
if (this.inputEl && this.inputElDual) {
this.inputElDual.value = `${(Number(this.inputEl.value) ?? 0) + step}`;
if (this.isDualRange) {
this.value = [this.inputEl.valueAsNumber, this.inputElDual?.valueAsNumber ?? 0];
} else {
this.value = this.inputEl.valueAsNumber;
}
}

Expand All @@ -271,6 +265,18 @@ export class OdsRange {
this.tooltip?.show();
}

private setInputElValue(step : number): void {
if (this.inputEl && this.inputElDual) {
this.inputEl.valueAsNumber = (this.inputElDual?.valueAsNumber ?? 0) - step;
}
}

private setInputElDualValue(step : number): void {
if (this.inputEl && this.inputElDual) {
this.inputElDual.valueAsNumber = (this.inputEl?.valueAsNumber ?? 0) + step;
}
}

private showTooltipDual(): void {
this.tooltipDual?.show();
}
Expand Down Expand Up @@ -304,6 +310,7 @@ export class OdsRange {
max={ this.max }
min={ this.min }
onBlur={ () => this.onBlur() }
onChange={ () => this.emitOdsChange() }
onFocus={ () => this.odsFocus.emit() }
onFocusin={ () => this.showTooltip() }
onFocusout={ () => this.hideTooltip() }
Expand Down Expand Up @@ -352,6 +359,7 @@ export class OdsRange {
id={ this.inputRangeDualId }
max={ this.max }
min={ this.min }
onChange={ () => this.emitOdsChange() }
onFocusin={ () => this.showTooltipDual() }
onFocusout={ () => this.hideTooltipDual() }
onInput={ () => this.onInput(true) }
Expand Down
Loading

0 comments on commit 31b6f4b

Please sign in to comment.
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy