- import { LitElement, html, css } from 'lit';
- import { customElement, property, state, queryAssignedNodes } from 'lit/decorators.js';
-
- interface FormField {
- name: string;
- type: string;
- label?: string;
- placeholder?: string;
- }
-
- @customElement('iu-form')
-
- export class Form extends LitElement {
- static override styles = css`
- input {
- padding: 8px;
- font-size: 1rem;
- width: 100%;
- box-sizing: border-box;
- }
- div{
- margin-bottom: 20px;
- }
- label{
- font-weight: bold;
- margin-bottom: 4px;
- display: block;
- }
- button {
- position: relative;
- display: inline-flex;
- align-items: center;
- background: var(--iu-color-grey-100);
- padding: 0.375rem 0.75rem;
- color: var(--iu-color-black);
- text-decoration: none;
- border: 0;
- font: var(--iu-f-sm);
- cursor: pointer;
- margin-top: 20px;
- &:hover{
- background: var(--iu-color-black);
- color: var(--iu-color-white);
- }
- margin-top: var(--iu-spacing-4);
- }
- ::slotted(iu-heading){
- --iu-heading-margin-top: var(--iu-spacing-7);
- }
- `;
-
- // Define the structure of form fields
- @property({ type: Array }) fields: FormField[] = [];
-
- // Reactive state to hold form values
- @state() private formData: Record<string, string> = {};
-
- // Query slot content to check if sections are provided
- @queryAssignedNodes() private slottedElements?: NodeList;
-
- private handleInput(event: Event) {
- const target = event.target as HTMLInputElement;
- this.formData = { ...this.formData, [target.name]: target.value };
- }
-
- private handleSubmit(event: Event) {
- event.preventDefault();
- console.log('Form Data:', this.formData);
-
- // Dispatch custom event with form data
- this.dispatchEvent(new CustomEvent('form-submit', {
- detail: this.formData,
- bubbles: true,
- composed: true,
- }));
- }
-
- // make sure that every component inside this has <iu-container> set
- // to nested to disable padding left on the container itself
- private updateSlottedElements() {
- if (!this.slottedElements) return;
-
- this.slottedElements.forEach((slot) => {
- if (slot instanceof HTMLElement) {
- // Set the `nested` attribute or property
- slot.setAttribute('nested', 'true');
- }
- });
- }
-
- override firstUpdated() {
- super.firstUpdated();
- this.updateSlottedElements();
- }
-
- constructor() {
- super();
- // Initialize form data with empty values
- this.fields.forEach(field => {
- this.formData[field.name] = '';
- });
- }
-
-
- override render() {
- const hasSections = this.slottedElements && this.slottedElements.length > 0;
- return html`
- <iu-container columns-md="2">
- <form @submit="${this.handleSubmit}">
- <slot></slot>
- ${!hasSections && this.fields.length > 0
- ? this.fields.map(
- field => html`
- <div>
- <label for="${field.name}">${field.label}</label>
- <input
- type="${field.type}"
- name="${field.name}"
- placeholder="${field.placeholder || ''}"
- @input="${this.handleInput}"
- .value="${this.formData[field.name] || ''}"
- required
- />
- </div>
- `)
- : ''
- }
- <button type="submit">Invia</button>
- </form>
- </iu-container>
- `;
- }
- }
-
- declare global {
- interface HTMLElementTagNameMap {
- 'iu-form': Form;
- }
- }