diff --git a/packages/ecc-utils-design/demo/form/index.html b/packages/ecc-utils-design/demo/form/index.html index 70891167..96f05374 100644 --- a/packages/ecc-utils-design/demo/form/index.html +++ b/packages/ecc-utils-design/demo/form/index.html @@ -23,14 +23,14 @@ @ecc-utils-submit=${async (e) => { try { console.log("form - submitted", e.detail); - document.querySelector("ecc-utils-design-form").loading(); + document.querySelector("ecc-d-form").loading(); await fetch("https://jsonplaceholder.typicode.com/posts"); document - .querySelector("ecc-utils-design-form") + .querySelector("ecc-d-form") .success({ message: "Data fetched successfully" }); } catch (error) { document - .querySelector("ecc-utils-design-form") + .querySelector("ecc-d-form") .error({ message: "Error fetching data" }); } }} diff --git a/packages/ecc-utils-design/src/components/form/form.styles.ts b/packages/ecc-utils-design/src/components/form/form.styles.ts index fa9654e3..beb5829e 100644 --- a/packages/ecc-utils-design/src/components/form/form.styles.ts +++ b/packages/ecc-utils-design/src/components/form/form.styles.ts @@ -68,7 +68,7 @@ const styles = css` .group-content { padding-top: var(--ecc-spacing-medium); } - .group-item { + .group { min-height: var(--ecc-input-height-3xlarge); } /* Array Styles */ @@ -78,12 +78,12 @@ const styles = css` font-weight: var(--ecc-input-font-weight); letter-spacing: var(--ecc-input-letter-spacing); } - .array-item { + .array { border-style: solid; border-width: 0px 0px var(--ecc-input-border-width) 0px; border-color: var(--ecc-input-border-color-disabled); } - .array-item { + .array { display: flex; flex-direction: row; align-items: center; diff --git a/packages/ecc-utils-design/src/components/form/form.ts b/packages/ecc-utils-design/src/components/form/form.ts index c5cdb76f..6c0b207e 100644 --- a/packages/ecc-utils-design/src/components/form/form.ts +++ b/packages/ecc-utils-design/src/components/form/form.ts @@ -86,7 +86,7 @@ export default class EccUtilsDesignForm extends LitElement { @state() private form: object = {}; @state() private formState: "idle" | "loading" | "error" | "success" = "idle"; - @state() private canSubmit = false; + @state() private canSubmit = true; @state() private submitDisabledByUser = false; @state() private errorMessage = "Something went wrong"; @state() private successMessage = "Form submitted successfully"; @@ -178,6 +178,7 @@ export default class EccUtilsDesignForm extends LitElement { private handleSubmit(e: Event) { e.preventDefault(); + const form = this.shadowRoot?.querySelector("form"); const isValid = form?.reportValidity(); if (!isValid) { @@ -198,8 +199,26 @@ export default class EccUtilsDesignForm extends LitElement { } render() { + // const toggleButtonState = () => { + // if (this.requiredButEmpty.length > 0) { + // this.canSubmit = false; + // } else { + // this.canSubmit = true; + // } + + // return ""; + // }; + + if (this.formState === "success") { + return html` ${this.renderSuccessTemplate()} `; + } + + if (this.formState === "error") { + return html` ${this.renderErrorTemplate()} `; + } + return html` -
+
${repeat( this.items, () => _.uniqueId("ecc-form-item-"), @@ -218,43 +237,7 @@ export default class EccUtilsDesignForm extends LitElement { > Submit -
+ `; - // if (!this.fields || this.fields.length === 0) { - // throw new Error("Fields is required & should not be empty array"); - // } - // if (this.formState === "success") { - // return html` ${this.renderSuccessTemplate()} `; - // } - - // const toggleButtonState = () => { - // if (this.requiredButEmpty.length > 0) { - // this.canSubmit = false; - // } else { - // this.canSubmit = true; - // } - - // return ""; - // }; - - // return html` - //
- // ${this.fields.map((field) => this.renderTemplate(field, "data"))} - // ${this.renderErrorTemplate()} ${toggleButtonState()} - - // - // Submit - // - //
- // `; } } diff --git a/packages/ecc-utils-design/src/components/form/formGroup.ts b/packages/ecc-utils-design/src/components/form/formGroup.ts index 2654b1ae..d4157ae4 100644 --- a/packages/ecc-utils-design/src/components/form/formGroup.ts +++ b/packages/ecc-utils-design/src/components/form/formGroup.ts @@ -2,18 +2,13 @@ import { LitElement, html, TemplateResult } from "lit"; import { property, state } from "lit/decorators.js"; import { repeat } from "lit/directives/repeat.js"; import * as _ from "lodash-es"; -import { noKeyWarning, renderInTooltip, toCamelCase } from "./utils.js"; +import { noKeyWarning, renderInTooltip } from "./utils.js"; import "@shoelace-style/shoelace/dist/components/details/details.js"; import "@shoelace-style/shoelace/dist/components/button/button.js"; import formStyles from "./form.styles.js"; export default class EccUtilsDesignFormGroup extends LitElement { - static styles = [ - // primitiveStylesheet, - // sholelaceStyles, - // hostStyles, - formStyles, - ]; + static styles = [formStyles]; // TODO // build required but empty functionality @@ -23,14 +18,14 @@ export default class EccUtilsDesignFormGroup extends LitElement { @property({ type: Boolean, reflect: true }) required = ""; @property({ type: String, reflect: true }) tooltip = ""; - // array item options + // array options @property({ type: Number, reflect: true }) instances = 0; @property({ type: Number, attribute: "max" }) maxInstances = ""; @property({ type: Number, attribute: "min" }) minInstances = ""; - // group item options + // group options @property({ type: Boolean, reflect: true }) collapsible = false; @state() private arrayInstances: Array<{ @@ -64,7 +59,7 @@ export default class EccUtilsDesignFormGroup extends LitElement { super.connectedCallback(); if (!this.key) { noKeyWarning("ecc-d-form-group", this.label); - this.key = toCamelCase(this.label); + this.key = _.camelCase(this.label); } this.findNearestFormGroup(); diff --git a/packages/ecc-utils-design/src/components/form/formInput.ts b/packages/ecc-utils-design/src/components/form/formInput.ts index daadd093..34f28fa9 100644 --- a/packages/ecc-utils-design/src/components/form/formInput.ts +++ b/packages/ecc-utils-design/src/components/form/formInput.ts @@ -1,7 +1,8 @@ +import * as _ from "lodash-es"; import { html, LitElement, TemplateResult } from "lit"; -import { property, state } from "lit/decorators.js"; +import { property, state, query } from "lit/decorators.js"; import { repeat } from "lit/directives/repeat.js"; -import { renderInTooltip, toCamelCase, noKeyWarning } from "./utils.js"; +import { renderInTooltip, noKeyWarning } from "./utils.js"; import "@shoelace-style/shoelace/dist/components/alert/alert.js"; import "@shoelace-style/shoelace/dist/components/icon/icon.js"; import "@shoelace-style/shoelace/dist/components/input/input.js"; @@ -44,23 +45,24 @@ export default class EccUtilsDesignFormInput extends LitElement { @property({ type: String, reflect: true }) default = ""; @property({ type: Boolean, reflect: true }) checked = false; @property({ type: Boolean, reflect: true }) multiple = false; + @property({ type: String, reflect: true }) value: any; @property({ type: String, reflect: true }) accept = "*"; - @property({ type: String, attribute: "tus-endpoint" }) tusEndpoint = ""; + @property({ type: String, attribute: "endpoint" }) tusEndpoint = ""; @property({ type: String, reflect: true }) protocol: "native" | "tus" = "native"; - @property({ type: String, reflect: true }) value: any; - @state() private alertText = "Something went wrong"; @state() private alertType: AlertType = "info"; @state() private showAlert = false; @state() path = ""; + @query("sl-input") input!: HTMLInputElement; + connectedCallback(): void { super.connectedCallback(); if (!this.key) { noKeyWarning("ecc-d-form-group", this.label); - this.key = toCamelCase(this.label); + this.key = _.camelCase(this.label); } this.findNearestFormGroup(); @@ -88,10 +90,12 @@ export default class EccUtilsDesignFormInput extends LitElement { const parentPath = parentElement.getAttribute("path"); this.path = parentPath ? `${parentPath}.${this.key}` : this.key; } + + this.findNearestFormGroup(parentElement); } private handleDismissAlert() { - this.alertText = ""; // reset error text + this.alertText = ""; this.showAlert = false; this.requestUpdate(); } @@ -103,6 +107,18 @@ export default class EccUtilsDesignFormInput extends LitElement { this.requestUpdate(); } + validity() { + return this.input.validity; + } + + checkValidity() { + return this.input.checkValidity(); + } + + reportValidity() { + return this.input.reportValidity(); + } + private handleFireChangeEvent() { this.dispatchEvent( new CustomEvent("ecc-utils-change", { @@ -121,10 +137,7 @@ export default class EccUtilsDesignFormInput extends LitElement { const target = e.target as HTMLInputElement; this.value = this.type === "switch" ? target.checked : target.value; - // fire change event this.handleFireChangeEvent(); - - // update this.requestUpdate(); } diff --git a/packages/ecc-utils-design/src/components/form/utils.ts b/packages/ecc-utils-design/src/components/form/utils.ts index 1189a2f5..0f30ed2e 100644 --- a/packages/ecc-utils-design/src/components/form/utils.ts +++ b/packages/ecc-utils-design/src/components/form/utils.ts @@ -13,20 +13,6 @@ export function renderInTooltip( : content; } -// write a function that takes any string and converts it to a camelCase variable name -export function toCamelCase(str: string): string { - return str - .replace(/[^a-zA-Z0-9\s]/g, "") // Remove special characters - .split(/[\s_-]+/) // Split on spaces, underscores, and hyphens - .map((word, index) => { - if (index === 0) { - return word.toLowerCase(); - } - return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); - }) - .join(""); -} - // write a function to console.warn a string that is sent as a param, only when app is in dev mode export function devWarn(message: string): void { // eslint-disable-next-line turbo/no-undeclared-env-vars @@ -44,42 +30,3 @@ export function noKeyWarning(Element: string, label: string): void { export function isShadowElement(element: Element): boolean { return element.getRootNode() instanceof ShadowRoot; } - -/** - * Finds the nearest form group and returns its path. - * @param element The starting element to search from. - * @param key The key of the current element (if applicable). - * @returns The path of the nearest form group, or null if not found. - */ -export function findNearestFormGroup( - element: HTMLElement, - key?: string, - groupItem = false -): string | null { - if (!element) return null; - - if (element.matches("ecc-d-form") || element.matches("ecc-d-form-group")) { - return null; - } - - const { parentElement } = element; - if (!parentElement) return null; - - const specialAttributes = [ - "ecc-array-item", - "ecc-form-item", - "ecc-group-item", - ]; - const hasSpecialAttribute = specialAttributes.some((attr) => - parentElement.hasAttribute(attr) - ); - - if (hasSpecialAttribute) { - const parentPath = parentElement.getAttribute("path"); - return parentPath && key - ? `${parentPath}.${key}` - : key || parentPath || null; - } - - return findNearestFormGroup(parentElement, key, groupItem); -}