chore(coldwired): update utils
This commit is contained in:
parent
0f608444b5
commit
c93141d8bb
7 changed files with 53 additions and 188 deletions
|
@ -1,4 +1,4 @@
|
||||||
import { isButtonElement } from '@utils';
|
import { isButtonElement } from '@coldwired/utils';
|
||||||
|
|
||||||
import { ApplicationController } from './application_controller';
|
import { ApplicationController } from './application_controller';
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
import {
|
import { isFormInputElement, matchInputElement } from '@coldwired/utils';
|
||||||
isSelectElement,
|
|
||||||
isCheckboxOrRadioInputElement,
|
|
||||||
isTextInputElement,
|
|
||||||
isDateInputElement
|
|
||||||
} from '@utils';
|
|
||||||
import { isFormInputElement } from '@coldwired/utils';
|
|
||||||
|
|
||||||
import { ApplicationController } from './application_controller';
|
import { ApplicationController } from './application_controller';
|
||||||
|
|
||||||
|
@ -28,14 +22,9 @@ export class AutosubmitController extends ApplicationController {
|
||||||
|
|
||||||
private onChange(event: Event) {
|
private onChange(event: Event) {
|
||||||
const target = this.findTargetElement(event);
|
const target = this.findTargetElement(event);
|
||||||
if (!target) return;
|
|
||||||
|
|
||||||
if (
|
matchInputElement(target, {
|
||||||
isSelectElement(target) ||
|
date: (target) => {
|
||||||
isCheckboxOrRadioInputElement(target) ||
|
|
||||||
isTextInputElement(target)
|
|
||||||
) {
|
|
||||||
if (isDateInputElement(target)) {
|
|
||||||
if (target.value.trim() == '' || !isNaN(Date.parse(target.value))) {
|
if (target.value.trim() == '' || !isNaN(Date.parse(target.value))) {
|
||||||
this.#dateTimeChangedInputs.add(target);
|
this.#dateTimeChangedInputs.add(target);
|
||||||
this.debounce(this.submit, AUTOSUBMIT_DATE_DEBOUNCE_DELAY);
|
this.debounce(this.submit, AUTOSUBMIT_DATE_DEBOUNCE_DELAY);
|
||||||
|
@ -43,34 +32,34 @@ export class AutosubmitController extends ApplicationController {
|
||||||
this.#dateTimeChangedInputs.delete(target);
|
this.#dateTimeChangedInputs.delete(target);
|
||||||
this.cancelDebounce(this.submit);
|
this.cancelDebounce(this.submit);
|
||||||
}
|
}
|
||||||
} else {
|
},
|
||||||
this.cancelDebounce(this.submit);
|
text: () => this.submitNow(),
|
||||||
this.submit();
|
changeable: () => this.submitNow()
|
||||||
}
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private onInput(event: Event) {
|
private onInput(event: Event) {
|
||||||
const target = this.findTargetElement(event);
|
const target = this.findTargetElement(event);
|
||||||
if (!target) return;
|
|
||||||
|
|
||||||
if (!isDateInputElement(target) && isTextInputElement(target)) {
|
matchInputElement(target, {
|
||||||
this.debounce(this.submit, AUTOSUBMIT_DEBOUNCE_DELAY);
|
date: () => {},
|
||||||
}
|
inputable: () => this.debounce(this.submit, AUTOSUBMIT_DEBOUNCE_DELAY)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private onBlur(event: Event) {
|
private onBlur(event: Event) {
|
||||||
const target = this.findTargetElement(event);
|
const target = this.findTargetElement(event);
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
|
|
||||||
if (isDateInputElement(target)) {
|
matchInputElement(target, {
|
||||||
Promise.resolve().then(() => {
|
date: () => {
|
||||||
if (this.#dateTimeChangedInputs.has(target)) {
|
Promise.resolve().then(() => {
|
||||||
this.cancelDebounce(this.submit);
|
if (this.#dateTimeChangedInputs.has(target)) {
|
||||||
this.submit();
|
this.submitNow();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private findTargetElement(event: Event) {
|
private findTargetElement(event: Event) {
|
||||||
|
@ -111,6 +100,11 @@ export class AutosubmitController extends ApplicationController {
|
||||||
return eventTypes.length == 0 ? true : eventTypes;
|
return eventTypes.length == 0 ? true : eventTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private submitNow() {
|
||||||
|
this.cancelDebounce(this.submit);
|
||||||
|
this.submit();
|
||||||
|
}
|
||||||
|
|
||||||
private submit() {
|
private submit() {
|
||||||
const submitter = this.hasSubmitterTarget ? this.submitterTarget : null;
|
const submitter = this.hasSubmitterTarget ? this.submitterTarget : null;
|
||||||
const form =
|
const form =
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
/* eslint-disable react-hooks/rules-of-hooks */
|
/* eslint-disable react-hooks/rules-of-hooks */
|
||||||
import { ActionEvent } from '@hotwired/stimulus';
|
import { ActionEvent } from '@hotwired/stimulus';
|
||||||
import {
|
import { httpRequest, getConfig } from '@utils';
|
||||||
httpRequest,
|
import { matchInputElement } from '@coldwired/utils';
|
||||||
isSelectElement,
|
|
||||||
isCheckboxOrRadioInputElement,
|
|
||||||
isTextInputElement,
|
|
||||||
getConfig
|
|
||||||
} from '@utils';
|
|
||||||
import { AutoUpload } from '../shared/activestorage/auto-upload';
|
import { AutoUpload } from '../shared/activestorage/auto-upload';
|
||||||
import { ApplicationController } from './application_controller';
|
import { ApplicationController } from './application_controller';
|
||||||
|
|
||||||
|
@ -59,29 +55,26 @@ export class TypeDeChampEditorController extends ApplicationController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private onChange(event: Event) {
|
private onChange(event: Event) {
|
||||||
const target = event.target as HTMLElement & { form?: HTMLFormElement };
|
matchInputElement(event.target, {
|
||||||
|
file: (target) => {
|
||||||
if (
|
if (target.files?.length) {
|
||||||
target.form &&
|
const autoupload = new AutoUpload(target, target.files[0]);
|
||||||
(isSelectElement(target) || isCheckboxOrRadioInputElement(target))
|
autoupload.start();
|
||||||
) {
|
}
|
||||||
this.save(target.form);
|
},
|
||||||
}
|
changeable: (target) => this.save(target.form)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private onInput(event: Event) {
|
private onInput(event: Event) {
|
||||||
const target = event.target as HTMLInputElement;
|
matchInputElement(event.target, {
|
||||||
|
inputable: (target) => {
|
||||||
// mark input as touched so we know to not overwrite it's value with next re-render
|
if (target.form) {
|
||||||
target.setAttribute('data-touched', 'true');
|
this.#dirtyForms.add(target.form);
|
||||||
|
this.debounce(this.save, AUTOSAVE_DEBOUNCE_DELAY);
|
||||||
if (target.form && isTextInputElement(target)) {
|
}
|
||||||
this.#dirtyForms.add(target.form);
|
}
|
||||||
this.debounce(this.save, AUTOSAVE_DEBOUNCE_DELAY);
|
});
|
||||||
} else if (target.form && target.type == 'file' && target.files?.length) {
|
|
||||||
const autoupload = new AutoUpload(target, target.files[0]);
|
|
||||||
autoupload.start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private onSortableEnd(event: CustomEvent<{ position: number }>) {
|
private onSortableEnd(event: CustomEvent<{ position: number }>) {
|
||||||
|
|
|
@ -1,14 +1,6 @@
|
||||||
import { suite, test, expect } from 'vitest';
|
import { suite, test, expect } from 'vitest';
|
||||||
|
|
||||||
import {
|
import { show, hide, toggle, toggleExpandIcon } from './utils';
|
||||||
show,
|
|
||||||
hide,
|
|
||||||
toggle,
|
|
||||||
toggleExpandIcon,
|
|
||||||
isSelectElement,
|
|
||||||
isTextInputElement,
|
|
||||||
isCheckboxOrRadioInputElement
|
|
||||||
} from './utils';
|
|
||||||
|
|
||||||
suite('@utils', () => {
|
suite('@utils', () => {
|
||||||
test('show', () => {
|
test('show', () => {
|
||||||
|
@ -46,79 +38,4 @@ suite('@utils', () => {
|
||||||
expect(icon.classList.contains('fr-icon-arrow-down-s-line')).toBeTruthy();
|
expect(icon.classList.contains('fr-icon-arrow-down-s-line')).toBeTruthy();
|
||||||
expect(icon.classList.contains('fr-icon-arrow-up-s-line')).toBeFalsy();
|
expect(icon.classList.contains('fr-icon-arrow-up-s-line')).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('isSelectElement', () => {
|
|
||||||
const select = document.createElement('select');
|
|
||||||
const input = document.createElement('input');
|
|
||||||
const textarea = document.createElement('textarea');
|
|
||||||
|
|
||||||
expect(isSelectElement(select)).toBeTruthy();
|
|
||||||
expect(isSelectElement(input)).toBeFalsy();
|
|
||||||
expect(isSelectElement(textarea)).toBeFalsy();
|
|
||||||
|
|
||||||
input.type = 'text';
|
|
||||||
expect(isSelectElement(input)).toBeFalsy();
|
|
||||||
|
|
||||||
input.type = 'email';
|
|
||||||
expect(isSelectElement(input)).toBeFalsy();
|
|
||||||
|
|
||||||
input.type = 'checkbox';
|
|
||||||
expect(isSelectElement(input)).toBeFalsy();
|
|
||||||
|
|
||||||
input.type = 'radio';
|
|
||||||
expect(isSelectElement(input)).toBeFalsy();
|
|
||||||
|
|
||||||
input.type = 'file';
|
|
||||||
expect(isSelectElement(input)).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('isTextInputElement', () => {
|
|
||||||
const select = document.createElement('select');
|
|
||||||
const input = document.createElement('input');
|
|
||||||
const textarea = document.createElement('textarea');
|
|
||||||
|
|
||||||
expect(isTextInputElement(select)).toBeFalsy();
|
|
||||||
expect(isTextInputElement(input)).toBeTruthy();
|
|
||||||
expect(isTextInputElement(textarea)).toBeTruthy();
|
|
||||||
|
|
||||||
input.type = 'text';
|
|
||||||
expect(isTextInputElement(input)).toBeTruthy();
|
|
||||||
|
|
||||||
input.type = 'email';
|
|
||||||
expect(isTextInputElement(input)).toBeTruthy();
|
|
||||||
|
|
||||||
input.type = 'checkbox';
|
|
||||||
expect(isTextInputElement(input)).toBeFalsy();
|
|
||||||
|
|
||||||
input.type = 'radio';
|
|
||||||
expect(isTextInputElement(input)).toBeFalsy();
|
|
||||||
|
|
||||||
input.type = 'file';
|
|
||||||
expect(isTextInputElement(input)).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('isCheckboxOrRadioInputElement', () => {
|
|
||||||
const select = document.createElement('select');
|
|
||||||
const input = document.createElement('input');
|
|
||||||
const textarea = document.createElement('textarea');
|
|
||||||
|
|
||||||
expect(isCheckboxOrRadioInputElement(select)).toBeFalsy();
|
|
||||||
expect(isCheckboxOrRadioInputElement(input)).toBeFalsy();
|
|
||||||
expect(isCheckboxOrRadioInputElement(textarea)).toBeFalsy();
|
|
||||||
|
|
||||||
input.type = 'text';
|
|
||||||
expect(isCheckboxOrRadioInputElement(input)).toBeFalsy();
|
|
||||||
|
|
||||||
input.type = 'email';
|
|
||||||
expect(isCheckboxOrRadioInputElement(input)).toBeFalsy();
|
|
||||||
|
|
||||||
input.type = 'checkbox';
|
|
||||||
expect(isCheckboxOrRadioInputElement(input)).toBeTruthy();
|
|
||||||
|
|
||||||
input.type = 'radio';
|
|
||||||
expect(isCheckboxOrRadioInputElement(input)).toBeTruthy();
|
|
||||||
|
|
||||||
input.type = 'file';
|
|
||||||
expect(isCheckboxOrRadioInputElement(input)).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -269,50 +269,6 @@ export function isNumeric(s: string) {
|
||||||
return !isNaN(n) && isFinite(n);
|
return !isNaN(n) && isFinite(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isButtonElement(
|
|
||||||
element: Element
|
|
||||||
): element is HTMLButtonElement {
|
|
||||||
return (
|
|
||||||
element.tagName == 'BUTTON' ||
|
|
||||||
(element.tagName == 'INPUT' &&
|
|
||||||
(element as HTMLInputElement).type == 'submit')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isSelectElement(
|
|
||||||
element: HTMLElement
|
|
||||||
): element is HTMLSelectElement {
|
|
||||||
return element.tagName == 'SELECT';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isCheckboxOrRadioInputElement(
|
|
||||||
element: HTMLElement & { type?: string }
|
|
||||||
): element is HTMLInputElement {
|
|
||||||
return (
|
|
||||||
element.tagName == 'INPUT' &&
|
|
||||||
(element.type == 'checkbox' || element.type == 'radio')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isDateInputElement(
|
|
||||||
element: HTMLElement & { type?: string }
|
|
||||||
): element is HTMLInputElement {
|
|
||||||
return (
|
|
||||||
element.tagName == 'INPUT' &&
|
|
||||||
(element.type == 'date' || element.type == 'datetime-local')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isTextInputElement(
|
|
||||||
element: HTMLElement & { type?: string }
|
|
||||||
): element is HTMLInputElement {
|
|
||||||
return (
|
|
||||||
['INPUT', 'TEXTAREA'].includes(element.tagName) &&
|
|
||||||
typeof element.type == 'string' &&
|
|
||||||
!['checkbox', 'radio', 'file'].includes(element.type)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fire<T>(obj: EventTarget, name: string, data?: T) {
|
export function fire<T>(obj: EventTarget, name: string, data?: T) {
|
||||||
const event = new CustomEvent(name, {
|
const event = new CustomEvent(name, {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@coldwired/actions": "^0.11.2",
|
"@coldwired/actions": "^0.11.2",
|
||||||
"@coldwired/turbo-stream": "^0.11.1",
|
"@coldwired/turbo-stream": "^0.11.1",
|
||||||
"@coldwired/utils": "^0.11.1",
|
"@coldwired/utils": "^0.11.4",
|
||||||
"@gouvfr/dsfr": "^1.10.1",
|
"@gouvfr/dsfr": "^1.10.1",
|
||||||
"@graphiql/plugin-explorer": "^0.3.4",
|
"@graphiql/plugin-explorer": "^0.3.4",
|
||||||
"@graphiql/toolkit": "^0.9.1",
|
"@graphiql/toolkit": "^0.9.1",
|
||||||
|
|
|
@ -1218,6 +1218,11 @@
|
||||||
resolved "https://registry.yarnpkg.com/@coldwired/utils/-/utils-0.11.1.tgz#d126246ab66591467e9e4c765769f133f6236ddb"
|
resolved "https://registry.yarnpkg.com/@coldwired/utils/-/utils-0.11.1.tgz#d126246ab66591467e9e4c765769f133f6236ddb"
|
||||||
integrity sha512-vuW1hVhD5U4NX/0dl+fT4RL92T5fEITwc9l/DnaBoP5SAuCAVRnHCWcdyROGz55E4WvSXFqAHD6qkxRwOKG2og==
|
integrity sha512-vuW1hVhD5U4NX/0dl+fT4RL92T5fEITwc9l/DnaBoP5SAuCAVRnHCWcdyROGz55E4WvSXFqAHD6qkxRwOKG2og==
|
||||||
|
|
||||||
|
"@coldwired/utils@^0.11.4":
|
||||||
|
version "0.11.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@coldwired/utils/-/utils-0.11.4.tgz#4889103dc73c1d86eff7d21574a0bde37b1f3c03"
|
||||||
|
integrity sha512-JvYosEc++zcuZmyfHAKG1cZ/jEIBM8ciJsD2ZcgFdzjSla1wtG+p6GOYiIVXZpCKO2oWGR4EmiYFYpBNIy3WDw==
|
||||||
|
|
||||||
"@emotion/is-prop-valid@^0.8.2":
|
"@emotion/is-prop-valid@^0.8.2":
|
||||||
version "0.8.8"
|
version "0.8.8"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a"
|
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a"
|
||||||
|
|
Loading…
Add table
Reference in a new issue