@abgov/ui-components-common
Version:
Government of Alberta - UI Web components
437 lines (436 loc) • 13 kB
JavaScript
var S = Object.defineProperty;
var g = (r) => {
throw TypeError(r);
};
var M = (r, t, e) => t in r ? S(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
var l = (r, t, e) => M(r, typeof t != "symbol" ? t + "" : t, e), w = (r, t, e) => t.has(r) || g("Cannot " + e);
var y = (r, t, e) => t.has(r) ? g("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(r) : t.set(r, e);
var _ = (r, t, e) => (w(r, t, "access private method"), e);
class x {
constructor(t) {
l(this, "validators");
this.validators = t || {};
}
add(t, ...e) {
this.validators[t] = e;
}
validate(t) {
const e = {};
return Object.entries(this.validators).forEach(([n, i]) => {
const a = i.map((s) => s(t[n])).find((s) => !!s);
a && (e[n] = a);
}), e;
}
}
function I() {
return [
c("Day is required"),
h({
min: 1,
max: 31,
minMsg: "Day must be between 1 and 31",
maxMsg: "Day must be between 1 and 31"
})
];
}
function L() {
return [
c("Month is required"),
h({
min: 0,
max: 11,
minMsg: "Month must be between Jan and Dec",
maxMsg: "Month must be between Jan and Dec"
})
];
}
function U() {
const r = (/* @__PURE__ */ new Date()).getFullYear();
return [
c("Year is required"),
h({
min: 1900,
max: r,
minMsg: "Year must be greater than 1900",
maxMsg: `Year must be less than ${r}`
})
];
}
function c(r) {
return (t) => (r = r || "Required", typeof t == "number" && !isNaN(t) || t ? "" : r);
}
function T(r) {
const t = new RegExp(/^\+?[\d-() ]{10,18}$/);
return m(t, r || "Invalid phone number");
}
function q(r) {
const t = new RegExp(
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
);
return m(t, r || "Invalid email address");
}
function Y() {
return (r) => {
if (!r) return "";
const t = "121212121".split("").map((i) => parseInt(i)), e = r.replace(/\D/g, "");
return e.length !== 9 ? "SIN must contain 9 numbers" : e.split("").map((i) => parseInt(i)).map((i, a) => {
const s = i * t[a];
return s < 10 ? s : `${s}`.split("").map((u) => parseInt(u)).reduce((u, f) => u + f, 0);
}).reduce((i, a) => i + a, 0) % 10 === 0 ? "" : "Invalid SIN";
};
}
function J() {
return m(
/^[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ -]?\d[ABCEGHJ-NPRSTV-Z]\d$/i,
"Invalid postal code"
);
}
function m(r, t) {
return (e) => !e || e.match(r) ? "" : t;
}
function O({
invalidMsg: r,
minMsg: t,
maxMsg: e,
min: n,
max: i
} = {}) {
return (a) => {
let s = /* @__PURE__ */ new Date(-1);
return `${a || ""}`.length === 0 ? "" : (typeof a == "string" && (s = new Date(a)), typeof a == "number" && (s = new Date(a)), a.toDateString && (s = a), s.getDate() === -1 ? r || "Invalid date" : n && s < n ? t || `Must be after ${n}` : i && s > i ? e || `Must be before ${i}` : "");
};
}
function h({
invalidTypeMsg: r,
minMsg: t,
maxMsg: e,
min: n = -Number.MAX_VALUE,
max: i = Number.MAX_VALUE
} = {}) {
return (a) => {
let s = Number.MAX_VALUE;
return `${a ?? ""}`.length === 0 ? "" : (typeof a == "string" && (s = parseFloat(a)), typeof a == "number" && (s = a), isNaN(s) ? r || "Must be a numeric value" : s > i ? e || `Must be less than or equal to ${i}` : s < n ? t || `Must be greater than or equal to ${n}` : "");
};
}
function X({
invalidTypeMsg: r,
minMsg: t,
maxMsg: e,
min: n = -Number.MAX_VALUE,
max: i = Number.MAX_VALUE
}) {
return (a) => `${a || ""}`.length === 0 ? "" : typeof a != "string" ? r || "Invalid type" : a.length > i ? e || `Must be less than ${i} characters` : a.length < n ? t || `Must be greater than ${n} characters` : "";
}
function v(r, t, e, n) {
if (!r) {
console.error("dispatch element is null");
return;
}
r.dispatchEvent(
new CustomEvent(t, {
composed: !0,
bubbles: n == null ? void 0 : n.bubbles,
detail: e
})
);
}
function o(r, t, e, n) {
if (!r) {
console.error("dispatch element is null");
return;
}
r.dispatchEvent(
new CustomEvent("msg", {
composed: !0,
bubbles: n == null ? void 0 : n.bubbles,
detail: {
action: t,
data: e
}
})
);
}
var d, E, A;
class j {
constructor(t) {
y(this, d);
l(this, "state");
l(this, "_formData");
l(this, "_formRef");
l(this, "_isCompleting", !1);
this.type = t;
}
// Obtain reference to the form element
init(t) {
if (this._formRef) {
console.warn("init: form element has already been set");
return;
}
this._formRef = t.detail.el, this.state = {
uuid: crypto.randomUUID(),
form: {},
history: [],
editting: "",
status: "not-started"
};
}
initList(t) {
this._formRef = t.detail.el, this.state = [];
}
// Public method to allow for the initialization of the state
initState(t, e) {
o(this._formRef, "external::init:state", t), typeof t == "string" ? this.state = JSON.parse(t) : Array.isArray(t) || (this.state = t), e && setTimeout(e, 200);
}
updateListState(t) {
const e = t.detail;
Array.isArray(e.data) && (this.state = e.data);
}
updateObjectState(t) {
var n, i;
if (Array.isArray(this.state))
return;
const e = t.detail;
e.type === "list" ? this.state = {
...this.state,
form: { ...((n = this.state) == null ? void 0 : n.form) || {}, [e.id]: e.data }
} : this.state = {
...this.state,
...e.data,
form: { ...((i = this.state) == null ? void 0 : i.form) || {}, ...e.data.form },
history: e.data.history
};
}
getStateList() {
return this.state ? Array.isArray(this.state) ? this.state.length === 0 ? [] : this.state.map((t) => Object.values(t.form).filter((e) => {
var n;
return ((n = e == null ? void 0 : e.data) == null ? void 0 : n.type) === "details";
}).map((e) => {
var n;
return e.data.type === "details" && ((n = e.data) == null ? void 0 : n.fieldsets) || {};
}).reduce(
(e, n) => {
for (const [i, a] of Object.entries(n))
e[i] = a.value;
return e;
},
{}
)) : (console.warn(
"Utils:getStateList: unable to update the state of a non-multi form type",
this.state
), []) : [];
}
// getStateItems(group: string): Record<string, FieldsetItemState>[] {
// if (Array.isArray(this.state)) {
// console.error(
// "Utils:getStateItems: unable to update the state of a multi form type",
// );
// return [];
// }
// if (!this.state) {
// console.error("Utils:getStateItems: state has not yet been set");
// return [];
// }
//
// const data = this.state.form[group].data;
// if (data.type !== "list") {
// return [];
// }
//
// return data.items.;
// }
// Public method to allow for the retrieval of the state value
getStateValue(t, e) {
if (Array.isArray(this.state))
return console.error("getStateValue: unable to update the state of a multi form type"), "";
if (!this.state)
return console.error("getStateValue: state has not yet been set"), "";
const n = this.state.form[t].data;
return n.type !== "details" ? "" : n.fieldsets[e].value;
}
// Public method to allow for the continuing to the next page
continueTo(t) {
if (!t) {
console.error("continueTo [name] is undefined");
return;
}
o(this._formRef, "external::continue", { next: t });
}
// Public method to perform validation and send the appropriate messages to the form elements
validate(t, e, n, i) {
var b;
const { el: a, state: s, cancelled: u } = t.detail, f = (b = s == null ? void 0 : s[e]) == null ? void 0 : b.value;
if (window.scrollTo({ top: 0, behavior: "smooth" }), u)
return [!0, f];
for (const V of n) {
const p = V(f);
if (_(this, d, A).call(this, a, e, p, i), p)
return [!1, ""];
}
return [!0, f];
}
/**
* Validates a group of fields ensuring that at least `minPassCount` of the items within the group
* passes. This is useful in the scenario when n number fields are required out of n+m number of fields.
*
* @param {string[]} fields - An array of field names to be validated.
* @param {Event} e - The event object associated with the validation trigger.
* @param {FieldValidator[]} validators - An array of validator functions to apply to the fields.
* @return {[number, Record<string, boolean>]} - Returns back the number of fields that passed and a record of the fields and their pass status.
*/
validateGroup(t, e, n) {
let i = 0;
const a = {};
for (const s of e) {
const [u] = this.validate(t, s, n, { grouped: !0 });
u && (a[s] = !0, i++);
}
return [i, a];
}
edit(t) {
o(this._formRef, "external::alter:state", { index: t, operation: "edit" });
}
remove(t) {
o(this._formRef, "external::alter:state", {
index: t,
operation: "remove"
});
}
/**
* Completes the form and triggers the onComplete callback.
* This method should be used when you want to complete a form without navigating to a summary page.
*
* @important Developers must validate the form before calling this method.
*
* @example
* // Validate first, then complete
* const [isValid] = this.validate(e, "firstName", [
* requiredValidator("First name is required.")
* ]);
* if (isValid) {
* this.complete();
* }
* @returns void
*/
complete() {
if (!this._formRef) {
console.error("complete: form ref is not set");
return;
}
if (this._isCompleting) {
console.warn("complete: completion already in progress");
return;
}
this._isCompleting = !0, o(this._formRef, "fieldset::submit", null, { bubbles: !0 }), this._isCompleting = !1;
}
/**
* Completes a subform and returns control to the parent form.
* This method should be used when working with subforms that need to complete without a summary page.
*
* @important Developers must validate the subform before calling this method.
*
* @example
* // Validate first, then complete the subform
* const [isValid] = this._childFormController.validate(e, "fullName", [
* requiredValidator("Please enter the dependent's full name.")
* ]);
* if (isValid) {
* this._childFormController.completeSubform();
* }
* @returns void
*/
completeSubform() {
if (!this._formRef) {
console.error("completeSubform: form ref is not set");
return;
}
if (this._isCompleting) {
console.warn("completeSubform: completion already in progress");
return;
}
const t = this._formRef;
this._isCompleting = !0;
const e = (n) => {
t.removeEventListener("_stateChange", e), v(t, "_complete", {}, { bubbles: !0 }), this._isCompleting = !1;
};
t.addEventListener("_stateChange", e), v(t, "_continue", null, { bubbles: !0 });
}
// removes any data collected that doesn't correspond with the final history path
clean(t) {
return t.history.reduce((e, n) => (e[n] = t.form[n], e), {});
}
}
d = new WeakSet(), E = function(t) {
var e;
Array.isArray(t.data) && (Array.isArray(this.state) || (this.state = {
...this.state,
form: {
...((e = this.state) == null ? void 0 : e.form) || {},
[t.id]: t.data
}
}));
}, // Private method to dispatch the error message to the form element
A = function(t, e, n, i) {
t.dispatchEvent(
new CustomEvent("msg", {
composed: !0,
detail: {
action: "external::set:error",
data: {
name: e,
msg: n,
grouped: i == null ? void 0 : i.grouped
}
}
})
);
};
const R = ["basic", "success", "failure"];
function C(r, t) {
const e = crypto.randomUUID();
return t = { uuid: e, type: "basic", ...t || {} }, !t.duration && t.type && R.includes(t.type) && (t.duration = "short"), o(
document.body,
"goa:temp-notification",
{ message: r, ...t },
{ bubbles: !0 }
), e;
}
function N(r) {
o(
document.body,
"goa:temp-notification:dismiss",
r,
{ bubbles: !0 }
);
}
function D(r, t) {
o(
document.body,
"goa:temp-notification:progress",
{ uuid: r, progress: t },
{ bubbles: !0 }
);
}
const G = {
show: C,
dismiss: N,
setProgress: D
};
export {
x as FormValidator,
j as PublicFormController,
Y as SINValidator,
G as TemporaryNotification,
I as birthDayValidator,
L as birthMonthValidator,
U as birthYearValidator,
O as dateValidator,
v as dispatch,
q as emailValidator,
X as lengthValidator,
h as numericValidator,
T as phoneNumberValidator,
J as postalCodeValidator,
m as regexValidator,
o as relay,
c as requiredValidator
};