@brytdesigns/web-component-form-sync 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main/components/form-sync.js +62 -0
- package/dist/main/components/form-sync.js.map +1 -0
- package/dist/main/components/index.js +3 -0
- package/dist/main/components/index.js.map +1 -0
- package/dist/main/index.d.ts +3 -0
- package/dist/main/index.js +13 -0
- package/dist/main/index.js.map +1 -0
- package/dist/main/utils.js +50 -0
- package/dist/main/utils.js.map +1 -0
- package/package.json +35 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { createMemo, createEffect, on, onCleanup } from 'solid-js';
|
|
2
|
+
import { receiveUpdate, receiveReset } from '../utils.js';
|
|
3
|
+
|
|
4
|
+
const FormSync = (props, { element }) => {
|
|
5
|
+
if (!props.name && !props.formId) return;
|
|
6
|
+
const form = createMemo(
|
|
7
|
+
() => element.querySelector(`#${props.formId}`)
|
|
8
|
+
);
|
|
9
|
+
const UPDATE = createMemo(() => `form.update.${props.name}`);
|
|
10
|
+
const RESET = createMemo(() => `form.reset.${props.name}`);
|
|
11
|
+
const handleUpdate = (form2) => (event) => {
|
|
12
|
+
dispatchEvent(
|
|
13
|
+
new CustomEvent(UPDATE(), {
|
|
14
|
+
detail: {
|
|
15
|
+
relatedTarget: form2,
|
|
16
|
+
changedTarget: event.target
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
const handleReset = (form2) => (event) => {
|
|
22
|
+
setTimeout(() => {
|
|
23
|
+
dispatchEvent(
|
|
24
|
+
new CustomEvent(RESET(), {
|
|
25
|
+
detail: {
|
|
26
|
+
relatedForm: form2,
|
|
27
|
+
resetForm: event.target
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
);
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
createEffect(
|
|
34
|
+
on(form, (form2) => {
|
|
35
|
+
if (!form2 || !props.name) return;
|
|
36
|
+
const controller = new AbortController();
|
|
37
|
+
const handleFormUpdate = handleUpdate(form2);
|
|
38
|
+
const handleReceiveUpdate = receiveUpdate(form2);
|
|
39
|
+
const handleFormReset = handleReset(form2);
|
|
40
|
+
const handleReceiveReset = receiveReset(form2);
|
|
41
|
+
element.addEventListener("input", handleFormUpdate, {
|
|
42
|
+
signal: controller.signal
|
|
43
|
+
});
|
|
44
|
+
element.addEventListener("reset", handleFormReset, {
|
|
45
|
+
signal: controller.signal
|
|
46
|
+
});
|
|
47
|
+
addEventListener(UPDATE(), handleReceiveUpdate, {
|
|
48
|
+
signal: controller.signal
|
|
49
|
+
});
|
|
50
|
+
addEventListener(RESET(), handleReceiveReset, {
|
|
51
|
+
signal: controller.signal
|
|
52
|
+
});
|
|
53
|
+
onCleanup(() => {
|
|
54
|
+
controller.abort("Resetting event listeners");
|
|
55
|
+
});
|
|
56
|
+
})
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export { FormSync };
|
|
61
|
+
//# sourceMappingURL=form-sync.js.map
|
|
62
|
+
//# sourceMappingURL=form-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/form-sync.ts"],"names":["form"],"mappings":";;;AAWO,MAAM,QAAgD,GAAA,CAC3D,KACA,EAAA,EAAE,SACC,KAAA;AACH,EAAA,IAAI,CAAC,KAAA,CAAM,IAAQ,IAAA,CAAC,MAAM,MAAQ,EAAA;AAClC,EAAA,MAAM,IAAO,GAAA,UAAA;AAAA,IAAW,MACtB,OAAQ,CAAA,aAAA,CAA+B,CAAI,CAAA,EAAA,KAAA,CAAM,MAAM,CAAE,CAAA;AAAA,GAC3D;AACA,EAAA,MAAM,SAAS,UAAW,CAAA,MAAM,CAAe,YAAA,EAAA,KAAA,CAAM,IAAI,CAAE,CAAA,CAAA;AAC3D,EAAA,MAAM,QAAQ,UAAW,CAAA,MAAM,CAAc,WAAA,EAAA,KAAA,CAAM,IAAI,CAAE,CAAA,CAAA;AAEzD,EAAA,MAAM,YAAe,GAAA,CAACA,KAA0B,KAAA,CAAC,KAAiB,KAAA;AAChE,IAAA,aAAA;AAAA,MACE,IAAI,WAAY,CAAA,MAAA,EAAU,EAAA;AAAA,QACxB,MAAQ,EAAA;AAAA,UACN,aAAeA,EAAAA,KAAAA;AAAA,UACf,eAAe,KAAM,CAAA;AAAA;AACvB,OACD;AAAA,KACH;AAAA,GACF;AAEA,EAAA,MAAM,WAAc,GAAA,CAACA,KAA0B,KAAA,CAAC,KAAiB,KAAA;AAC/D,IAAA,UAAA,CAAW,MAAM;AACf,MAAA,aAAA;AAAA,QACE,IAAI,WAAY,CAAA,KAAA,EAAS,EAAA;AAAA,UACvB,MAAQ,EAAA;AAAA,YACN,WAAaA,EAAAA,KAAAA;AAAA,YACb,WAAW,KAAM,CAAA;AAAA;AACnB,SACD;AAAA,OACH;AAAA,KACD,CAAA;AAAA,GACH;AAEA,EAAA,YAAA;AAAA,IACE,EAAA,CAAG,IAAM,EAAA,CAACA,KAAS,KAAA;AACjB,MAAA,IAAI,CAACA,KAAAA,IAAQ,CAAC,KAAA,CAAM,IAAM,EAAA;AAC1B,MAAM,MAAA,UAAA,GAAa,IAAI,eAAgB,EAAA;AACvC,MAAM,MAAA,gBAAA,GAAmB,aAAaA,KAAI,CAAA;AAC1C,MAAM,MAAA,mBAAA,GAAsB,cAAcA,KAAI,CAAA;AAE9C,MAAM,MAAA,eAAA,GAAkB,YAAYA,KAAI,CAAA;AACxC,MAAM,MAAA,kBAAA,GAAqB,aAAaA,KAAI,CAAA;AAE5C,MAAQ,OAAA,CAAA,gBAAA,CAAiB,SAAS,gBAAkB,EAAA;AAAA,QAClD,QAAQ,UAAW,CAAA;AAAA,OACpB,CAAA;AACD,MAAQ,OAAA,CAAA,gBAAA,CAAiB,SAAS,eAAiB,EAAA;AAAA,QACjD,QAAQ,UAAW,CAAA;AAAA,OACpB,CAAA;AAGD,MAAiB,gBAAA,CAAA,MAAA,IAAU,mBAAqB,EAAA;AAAA,QAC9C,QAAQ,UAAW,CAAA;AAAA,OACpB,CAAA;AAED,MAAiB,gBAAA,CAAA,KAAA,IAAS,kBAAoB,EAAA;AAAA,QAC5C,QAAQ,UAAW,CAAA;AAAA,OACpB,CAAA;AAED,MAAA,SAAA,CAAU,MAAM;AACd,QAAA,UAAA,CAAW,MAAM,2BAA2B,CAAA;AAAA,OAC7C,CAAA;AAAA,KACF;AAAA,GACH;AACF","file":"form-sync.js","sourcesContent":["import type { CorrectComponentType } from \"@brytdesigns/web-component-utils\";\n\nimport { createEffect, createMemo, on, onCleanup } from \"solid-js\";\n\nimport { receiveUpdate, receiveReset } from \"../utils.js\";\n\ntype FormSyncProps = {\n name: string;\n formId: string;\n};\n\nexport const FormSync: CorrectComponentType<FormSyncProps> = (\n props,\n { element }\n) => {\n if (!props.name && !props.formId) return;\n const form = createMemo(() =>\n element.querySelector<HTMLFormElement>(`#${props.formId}`)\n );\n const UPDATE = createMemo(() => `form.update.${props.name}`);\n const RESET = createMemo(() => `form.reset.${props.name}`);\n\n const handleUpdate = (form: HTMLFormElement) => (event: Event) => {\n dispatchEvent(\n new CustomEvent(UPDATE(), {\n detail: {\n relatedTarget: form,\n changedTarget: event.target,\n },\n })\n );\n };\n\n const handleReset = (form: HTMLFormElement) => (event: Event) => {\n setTimeout(() => {\n dispatchEvent(\n new CustomEvent(RESET(), {\n detail: {\n relatedForm: form,\n resetForm: event.target,\n },\n })\n );\n });\n };\n\n createEffect(\n on(form, (form) => {\n if (!form || !props.name) return;\n const controller = new AbortController();\n const handleFormUpdate = handleUpdate(form);\n const handleReceiveUpdate = receiveUpdate(form);\n\n const handleFormReset = handleReset(form);\n const handleReceiveReset = receiveReset(form);\n\n element.addEventListener(\"input\", handleFormUpdate, {\n signal: controller.signal,\n });\n element.addEventListener(\"reset\", handleFormReset, {\n signal: controller.signal,\n });\n\n //@ts-ignore\n addEventListener(UPDATE(), handleReceiveUpdate, {\n signal: controller.signal,\n });\n //@ts-ignore\n addEventListener(RESET(), handleReceiveReset, {\n signal: controller.signal,\n });\n\n onCleanup(() => {\n controller.abort(\"Resetting event listeners\");\n });\n })\n );\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { customShadowlessElement, correctElementType } from '@brytdesigns/web-component-utils';
|
|
2
|
+
import { FormSync } from './components/index.js';
|
|
3
|
+
|
|
4
|
+
customShadowlessElement(
|
|
5
|
+
"form-sync",
|
|
6
|
+
{
|
|
7
|
+
name: "",
|
|
8
|
+
formId: ""
|
|
9
|
+
},
|
|
10
|
+
correctElementType(FormSync)
|
|
11
|
+
);
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts"],"names":[],"mappings":";;;AAMA,uBAAA;AAAA,EACE,WAAA;AAAA,EACA;AAAA,IACE,IAAM,EAAA,EAAA;AAAA,IACN,MAAQ,EAAA;AAAA,GACV;AAAA,EACA,mBAAmB,QAAQ;AAC7B,CAAA","file":"index.js","sourcesContent":["import {\n customShadowlessElement,\n correctElementType,\n} from \"@brytdesigns/web-component-utils\";\nimport { FormSync } from \"./components/index.js\";\n\ncustomShadowlessElement(\n \"form-sync\",\n {\n name: \"\",\n formId: \"\",\n },\n correctElementType(FormSync)\n);\n"]}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
function handleRadioOrCheckboxChange(form, input) {
|
|
2
|
+
const element = Array.from(form.elements).find((elem) => {
|
|
3
|
+
return (
|
|
4
|
+
//@ts-ignore
|
|
5
|
+
elem.name === input.name && elem.value === input.value && !elem.checked
|
|
6
|
+
);
|
|
7
|
+
});
|
|
8
|
+
if (!element) return;
|
|
9
|
+
element.checked = true;
|
|
10
|
+
element.dispatchEvent(new Event("change", { bubbles: true }));
|
|
11
|
+
element.dispatchEvent(new Event("input", { bubbles: true }));
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
function handleDefaultChange(form, input) {
|
|
15
|
+
const element = Array.from(form.elements).find(
|
|
16
|
+
//@ts-ignore
|
|
17
|
+
(elem) => elem.name === input.name && elem.value !== input.value
|
|
18
|
+
);
|
|
19
|
+
if (!element) return;
|
|
20
|
+
element.value = input.value;
|
|
21
|
+
element.dispatchEvent(new Event("change", { bubbles: true }));
|
|
22
|
+
element.dispatchEvent(new Event("input", { bubbles: true }));
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
function receiveUpdate(form) {
|
|
26
|
+
return function(event) {
|
|
27
|
+
if (event.detail.relatedTarget === form) return;
|
|
28
|
+
const input = event.detail.changedTarget;
|
|
29
|
+
if (input.type === "checkbox")
|
|
30
|
+
return handleRadioOrCheckboxChange(form, input);
|
|
31
|
+
if (input.type === "radio") return handleRadioOrCheckboxChange(form, input);
|
|
32
|
+
return handleDefaultChange(form, input);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function receiveReset(form) {
|
|
36
|
+
return function(event) {
|
|
37
|
+
if (event.detail.relatedForm === form) return;
|
|
38
|
+
const isReset = Array.from(form.elements).filter(
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
(elem) => elem.checked && !elem.hasAttribute("checked")
|
|
41
|
+
).length === 0;
|
|
42
|
+
if (isReset) return;
|
|
43
|
+
if (typeof form.reset === "function") form.reset();
|
|
44
|
+
else form.reset.click();
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { handleDefaultChange, handleRadioOrCheckboxChange, receiveReset, receiveUpdate };
|
|
49
|
+
//# sourceMappingURL=utils.js.map
|
|
50
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils.ts"],"names":[],"mappings":"AAUO,SAAS,2BAAA,CACd,MACA,KACA,EAAA;AACA,EAAM,MAAA,OAAA,GAAU,MAAM,IAAK,CAAA,IAAA,CAAK,QAAQ,CAAE,CAAA,IAAA,CAAK,CAAC,IAAS,KAAA;AACvD,IAAA;AAAA;AAAA,MAEE,IAAA,CAAK,SAAS,KAAM,CAAA,IAAA,IAAQ,KAAK,KAAU,KAAA,KAAA,CAAM,KAAS,IAAA,CAAC,IAAK,CAAA;AAAA;AAAA,GAEnE,CAAA;AACD,EAAA,IAAI,CAAC,OAAS,EAAA;AACd,EAAA,OAAA,CAAQ,OAAU,GAAA,IAAA;AAClB,EAAQ,OAAA,CAAA,aAAA,CAAc,IAAI,KAAM,CAAA,QAAA,EAAU,EAAE,OAAS,EAAA,IAAA,EAAM,CAAC,CAAA;AAC5D,EAAQ,OAAA,CAAA,aAAA,CAAc,IAAI,KAAM,CAAA,OAAA,EAAS,EAAE,OAAS,EAAA,IAAA,EAAM,CAAC,CAAA;AAC3D,EAAO,OAAA,IAAA;AACT;AAEO,SAAS,mBAAA,CACd,MACA,KACA,EAAA;AACA,EAAA,MAAM,OAAU,GAAA,KAAA,CAAM,IAAK,CAAA,IAAA,CAAK,QAAQ,CAAE,CAAA,IAAA;AAAA;AAAA,IAExC,CAAC,SAAS,IAAK,CAAA,IAAA,KAAS,MAAM,IAAQ,IAAA,IAAA,CAAK,UAAU,KAAM,CAAA;AAAA,GAC7D;AACA,EAAA,IAAI,CAAC,OAAS,EAAA;AACd,EAAA,OAAA,CAAQ,QAAQ,KAAM,CAAA,KAAA;AAEtB,EAAQ,OAAA,CAAA,aAAA,CAAc,IAAI,KAAM,CAAA,QAAA,EAAU,EAAE,OAAS,EAAA,IAAA,EAAM,CAAC,CAAA;AAC5D,EAAQ,OAAA,CAAA,aAAA,CAAc,IAAI,KAAM,CAAA,OAAA,EAAS,EAAE,OAAS,EAAA,IAAA,EAAM,CAAC,CAAA;AAC3D,EAAO,OAAA,IAAA;AACT;AAEO,SAAS,cAAc,IAAuB,EAAA;AACnD,EAAA,OAAO,SAAU,KAA4B,EAAA;AAC3C,IAAI,IAAA,KAAA,CAAM,MAAO,CAAA,aAAA,KAAkB,IAAM,EAAA;AACzC,IAAM,MAAA,KAAA,GAAQ,MAAM,MAAO,CAAA,aAAA;AAE3B,IAAA,IAAI,MAAM,IAAS,KAAA,UAAA;AACjB,MAAO,OAAA,2BAAA,CAA4B,MAAM,KAAK,CAAA;AAChD,IAAA,IAAI,MAAM,IAAS,KAAA,OAAA,EAAgB,OAAA,2BAAA,CAA4B,MAAM,KAAK,CAAA;AAE1E,IAAO,OAAA,mBAAA,CAAoB,MAAM,KAAK,CAAA;AAAA,GACxC;AACF;AAEO,SAAS,aAAa,IAAuB,EAAA;AAClD,EAAA,OAAO,SAAU,KAA2B,EAAA;AAC1C,IAAI,IAAA,KAAA,CAAM,MAAO,CAAA,WAAA,KAAgB,IAAM,EAAA;AACvC,IAAA,MAAM,OACJ,GAAA,KAAA,CAAM,IAAK,CAAA,IAAA,CAAK,QAAQ,CAAE,CAAA,MAAA;AAAA;AAAA,MAExB,CAAC,IAAS,KAAA,IAAA,CAAK,WAAW,CAAC,IAAA,CAAK,aAAa,SAAS;AAAA,MACtD,MAAW,KAAA,CAAA;AAEf,IAAA,IAAI,OAAS,EAAA;AAEb,IAAA,IAAI,OAAO,IAAA,CAAK,KAAU,KAAA,UAAA,OAAiB,KAAM,EAAA;AAAA,SAG5C,IAAA,CAAK,MAAM,KAAM,EAAA;AAAA,GACxB;AACF","file":"utils.js","sourcesContent":["export type FormSyncUpdateEvent = CustomEvent<{\n relatedTarget: HTMLFormElement;\n changedTarget: HTMLInputElement;\n}>;\n\nexport type FormSyncResetEvent = CustomEvent<{\n relatedForm: HTMLFormElement;\n resetForm: HTMLFormElement;\n}>;\n\nexport function handleRadioOrCheckboxChange(\n form: HTMLFormElement,\n input: HTMLInputElement\n) {\n const element = Array.from(form.elements).find((elem) => {\n return (\n //@ts-ignore\n elem.name === input.name && elem.value === input.value && !elem.checked\n );\n }) as HTMLInputElement;\n if (!element) return;\n element.checked = true;\n element.dispatchEvent(new Event(\"change\", { bubbles: true }));\n element.dispatchEvent(new Event(\"input\", { bubbles: true }));\n return true;\n}\n\nexport function handleDefaultChange(\n form: HTMLFormElement,\n input: HTMLInputElement\n) {\n const element = Array.from(form.elements).find(\n //@ts-ignore\n (elem) => elem.name === input.name && elem.value !== input.value\n ) as HTMLInputElement;\n if (!element) return;\n element.value = input.value;\n\n element.dispatchEvent(new Event(\"change\", { bubbles: true }));\n element.dispatchEvent(new Event(\"input\", { bubbles: true }));\n return true;\n}\n\nexport function receiveUpdate(form: HTMLFormElement) {\n return function (event: FormSyncUpdateEvent) {\n if (event.detail.relatedTarget === form) return;\n const input = event.detail.changedTarget;\n\n if (input.type === \"checkbox\")\n return handleRadioOrCheckboxChange(form, input);\n if (input.type === \"radio\") return handleRadioOrCheckboxChange(form, input);\n\n return handleDefaultChange(form, input);\n };\n}\n\nexport function receiveReset(form: HTMLFormElement) {\n return function (event: FormSyncResetEvent) {\n if (event.detail.relatedForm === form) return;\n const isReset =\n Array.from(form.elements).filter(\n // @ts-ignore\n (elem) => elem.checked && !elem.hasAttribute(\"checked\")\n ).length === 0;\n\n if (isReset) return;\n\n if (typeof form.reset === \"function\") form.reset();\n // If reset button is present, trigger its click event\n // @ts-ignore\n else form.reset.click();\n };\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@brytdesigns/web-component-form-sync",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Web component for syncing the values of multiple forms",
|
|
5
|
+
"main": "./dist/main/index.js",
|
|
6
|
+
"module": "./dist/main/index.js",
|
|
7
|
+
"types": "./dist/main/index.d.ts",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/main/index.d.ts",
|
|
12
|
+
"module": "./dist/main/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"keywords": [],
|
|
19
|
+
"author": "Bryt Designs",
|
|
20
|
+
"license": "ISC",
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"component-register": "^0.8.7",
|
|
23
|
+
"solid-element": "^1.9.1",
|
|
24
|
+
"solid-js": "^1.9.5",
|
|
25
|
+
"@brytdesigns/web-component-utils": "0.1.8"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"dts-bundle-generator": "^9.5.1",
|
|
29
|
+
"tsup": "^8.4.0"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsup --clean",
|
|
33
|
+
"typecheck": "tsc --noEmit"
|
|
34
|
+
}
|
|
35
|
+
}
|