Demonstrates ALL library features: model lists, sections, all input types Async
<!-- Material Design 3 Self-Contained Form -->
<style>
/* Material Design 3 Self-Contained Styles - Using !important to override any conflicting styles */
.md-form-container {
font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
max-width: 100% !important;
margin: 0 !important;
padding: 20px !important;
line-height: 1.5 !important;
color: #1c1b1f !important;
background: #fef7ff !important;
border: none !important;
box-sizing: border-box !important;
position: relative !important;
}
.md-form {
width: 100% !important;
background: #ffffff !important;
border-radius: 28px !important;
padding: 32px !important;
box-shadow: 0 1px 2px rgba(0,0,0,0.3), 0 2px 6px 2px rgba(0,0,0,0.15) !important;
border: none !important;
margin: 0 !important;
box-sizing: border-box !important;
font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
}
/* Reset any Bootstrap interference */
.md-form * {
box-sizing: border-box !important;
}
/* Material Design Form Fields */
.md-field {
margin-bottom: 32px !important;
position: relative !important;
width: 100% !important;
font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
}
/* Model list container styling to blend with Material Design */
.md-model-list-container {
background: transparent !important;
border: none !important;
padding: 0 !important;
margin: 0 !important;
font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
}
/* Override Bootstrap styles for model list items within Material Design */
.md-model-list-container .card {
border: 1px solid #79747e !important;
border-radius: 12px !important;
box-shadow: none !important;
margin-bottom: 16px !important;
background: #ffffff !important;
}
.md-model-list-container .card-header {
background: #f7f2fa !important;
border-bottom: 1px solid #e7e0ec !important;
border-radius: 12px 12px 0 0 !important;
color: #1c1b1f !important;
font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
font-weight: 500 !important;
}
.md-model-list-container .btn {
border-radius: 20px !important;
font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
font-weight: 500 !important;
text-transform: none !important;
}
.md-model-list-container .btn-primary {
background: #6750a4 !important;
border-color: #6750a4 !important;
}
.md-model-list-container .btn-danger {
background: #ba1a1a !important;
border-color: #ba1a1a !important;
}
.md-model-list-wrapper {
background: transparent !important;
margin-bottom: 32px !important;
}
.md-model-list-container {
border: 1px solid #e7e0ec !important;
border-radius: 24px !important;
padding: 16px 20px !important;
background: #fff !important;
box-shadow: 0 1px 3px rgba(0,0,0,0.08) !important;
}
.md-model-list-items {
display: flex !important;
flex-direction: column !important;
gap: 16px !important;
}
.md-model-card {
border: 1px solid #e7e0ec !important;
border-radius: 20px !important;
background: #ffffff !important;
padding: 16px 20px !important;
box-shadow: 0 1px 3px rgba(0,0,0,0.08) !important;
}
.md-model-card__header {
display: flex !important;
justify-content: space-between !important;
align-items: center !important;
margin-bottom: 12px !important;
}
.md-model-card__body {
padding: 0 !important;
}
.md-model-list-actions {
margin-top: 12px !important;
display: flex !important;
justify-content: flex-end !important;
}
.md-button-tonal {
background: #e8def8 !important;
color: #1c1b1f !important;
}
.md-button-tonal:hover {
background: #cdc2db !important;
}
.md-button__icon {
margin-right: 8px !important;
width: 20px !important;
height: 20px !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
flex: 0 0 20px !important;
fill: currentColor !important;
}
.md-button__label {
font-weight: 500 !important;
}
/* Layout card styling */
.md-layout-card {
background: #ffffff !important;
border-radius: 24px !important;
padding: 24px 28px !important;
margin-bottom: 32px !important;
box-shadow: 0 1px 3px rgba(0,0,0,0.2), 0 4px 8px rgba(0,0,0,0.1) !important;
border: 1px solid #e7e0ec !important;
}
.md-layout-card__header {
margin-bottom: 12px !important;
}
.md-layout-card__title {
font-size: 18px !important;
font-weight: 600 !important;
color: #1c1b1f !important;
}
.md-layout-card__help {
color: #49454f !important;
font-size: 14px !important;
margin-bottom: 12px !important;
}
.md-layout-card__content {
display: flex !important;
flex-direction: column !important;
gap: 16px !important;
}
.md-field-label {
display: block !important;
color: #49454f !important;
font-size: 14px !important;
font-weight: 500 !important;
margin-bottom: 8px !important;
position: relative !important;
font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
line-height: 1.4 !important;
}
.md-field-label.required::after {
content: ' *' !important;
color: #ba1a1a !important;
}
/* Material Design Outlined Text Fields */
.md-text-field {
position: relative;
width: 100%;
}
/* Field container */
.md-field {
margin: 16px 0;
}
/* Field with icon layout */
.md-field-with-icon {
display: flex !important;
align-items: flex-start !important;
gap: 12px !important;
font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
}
/* Input wrapper for proper label positioning */
.md-input-wrapper {
position: relative !important;
flex: 1 !important;
width: 100% !important;
}
.md-input {
width: 100% !important;
padding: 16px !important;
border: 1px solid #79747e !important;
border-radius: 4px !important;
background: transparent !important;
color: #1c1b1f !important;
font-size: 16px !important;
font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
outline: none !important;
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1) !important;
box-sizing: border-box !important;
line-height: 1.5 !important;
margin: 0 !important;
}
.md-input:focus {
border-color: #6750a4 !important;
border-width: 2px !important;
padding: 15px !important; /* Adjust for thicker border */
box-shadow: none !important;
}
/* Icon styling - positioned outside to the left of input */
.md-icon {
display: flex !important;
align-items: center !important;
justify-content: center !important;
width: 24px !important;
height: 24px !important;
margin-top: 16px !important; /* Align with input padding */
color: #49454f !important;
flex-shrink: 0 !important;
transition: color 0.15s cubic-bezier(0.4, 0, 0.2, 1) !important;
fill: currentColor !important;
}
.md-field-with-icon:focus-within .md-icon {
color: #6750a4 !important;
}
.md-input:focus + .md-floating-label,
.md-input:not(:placeholder-shown) + .md-floating-label,
.md-textarea:focus + .md-floating-label,
.md-textarea:not(:placeholder-shown) + .md-floating-label,
.md-select:focus + .md-floating-label {
transform: translateY(-28px) scale(0.75) !important;
color: #6750a4 !important;
background: #ffffff !important;
padding: 0 4px !important;
}
.md-floating-label {
position: absolute !important;
left: 16px !important;
top: 16px !important;
color: #49454f !important;
font-size: 16px !important;
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1) !important;
pointer-events: none !important;
background: transparent !important;
z-index: 1 !important;
transform-origin: left top !important;
font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
font-weight: 400 !important;
line-height: 1.4 !important;
}
.md-input:focus + .md-floating-label,
.md-input:not(:placeholder-shown) + .md-floating-label {
transform: translateY(-28px) scale(0.75) !important;
color: #6750a4;
background: #ffffff;
padding: 0 4px;
}
.md-input.error {
border-color: #ba1a1a;
}
.md-input.error:focus {
border-color: #ba1a1a;
}
.md-input.error + .md-floating-label {
color: #ba1a1a;
}
/* Material Design Select */
.md-select {
width: 100%;
padding: 16px;
border: 1px solid #79747e;
border-radius: 4px;
background: transparent;
color: #1c1b1f;
font-size: 16px;
font-family: inherit;
outline: none;
cursor: pointer;
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
box-sizing: border-box;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%2349454f' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
background-position: right 12px center;
background-repeat: no-repeat;
background-size: 16px;
padding-right: 40px;
}
.md-select:focus {
border-color: #6750a4;
border-width: 2px;
padding: 15px 39px 15px 15px; /* Adjust for thicker border */
}
.md-select:focus + .md-floating-label {
transform: translateY(-28px) scale(0.75);
color: #6750a4;
background: #ffffff;
padding: 0 4px;
}
/* Material Design Textarea */
.md-textarea {
width: 100%;
min-height: 120px;
padding: 16px;
border: 1px solid #79747e;
border-radius: 4px;
background: transparent;
color: #1c1b1f;
font-size: 16px;
font-family: inherit;
outline: none;
resize: vertical;
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
box-sizing: border-box;
}
.md-textarea:focus {
border-color: #6750a4;
border-width: 2px;
padding: 15px; /* Adjust for thicker border */
}
.md-textarea:focus + .md-floating-label,
.md-textarea:not(:placeholder-shown) + .md-floating-label {
transform: translateY(-28px) scale(0.75);
color: #6750a4;
background: #ffffff;
padding: 0 4px;
}
/* Material Design Checkboxes */
.md-checkbox-container {
display: flex;
align-items: flex-start;
gap: 16px;
margin: 16px 0;
cursor: pointer;
}
.md-checkbox {
width: 18px;
height: 18px;
border: 2px solid #79747e;
border-radius: 2px;
background: transparent;
cursor: pointer;
position: relative;
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
margin-top: 2px; /* Align with text baseline */
flex-shrink: 0;
}
.md-checkbox:checked {
background: #6750a4;
border-color: #6750a4;
}
.md-checkbox:checked::after {
content: '';
position: absolute;
top: 1px;
left: 4px;
width: 6px;
height: 10px;
border: solid white;
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
.md-checkbox-label {
color: #1c1b1f;
font-size: 16px;
cursor: pointer;
line-height: 1.5;
}
/* Material Design Buttons */
.md-button {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 10px 24px;
border: none;
border-radius: 20px;
font-size: 14px;
font-weight: 500;
font-family: inherit;
cursor: pointer;
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
text-decoration: none;
box-sizing: border-box;
min-width: 64px;
height: 40px;
position: relative;
overflow: hidden;
}
.md-button-filled {
background: #6750a4;
color: #ffffff;
box-shadow: 0 1px 2px rgba(0,0,0,0.3), 0 1px 3px 1px rgba(0,0,0,0.15);
}
.md-button-filled:hover {
background: #5a43a0;
box-shadow: 0 1px 2px rgba(0,0,0,0.3), 0 2px 6px 2px rgba(0,0,0,0.15);
transform: translateY(-1px);
}
.md-button-filled:active {
transform: translateY(0);
box-shadow: 0 1px 2px rgba(0,0,0,0.3), 0 1px 3px 1px rgba(0,0,0,0.15);
}
/* Help Text */
.md-help-text {
font-size: 12px;
color: #49454f;
margin-top: 4px;
line-height: 1.33;
padding-left: 16px;
}
/* Error Text */
.md-error-text {
font-size: 12px;
color: #ba1a1a;
margin-top: 4px;
line-height: 1.33;
font-weight: 400;
padding-left: 16px;
}
/* Number and Date Inputs */
.md-input[type="number"],
.md-input[type="date"],
.md-input[type="email"],
.md-input[type="password"],
.md-input[type="tel"],
.md-input[type="url"] {
/* Inherit all md-input styles */
}
.md-input[type="color"] {
height: 56px;
padding: 8px;
cursor: pointer;
}
.md-input[type="range"] {
padding: 16px 8px;
}
/* Placeholder styling */
.md-input::placeholder {
color: transparent;
}
.md-input:focus::placeholder {
color: #49454f;
}
/* State layers for interactive elements */
.md-button-filled::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: currentColor;
opacity: 0;
transition: opacity 0.15s cubic-bezier(0.4, 0, 0.2, 1);
border-radius: inherit;
}
.md-button-filled:hover::before {
opacity: 0.08;
}
.md-button-filled:focus::before {
opacity: 0.12;
}
.md-button-filled:active::before {
opacity: 0.16;
}
/* Responsive Design */
@media (max-width: 768px) {
.md-form {
padding: 24px 16px;
border-radius: 28px;
}
.md-field {
margin-bottom: 24px;
}
}
/* Typography Scale */
.md-headline-small {
font-size: 24px;
font-weight: 400;
line-height: 32px;
color: #1c1b1f;
}
.md-body-large {
font-size: 16px;
font-weight: 400;
line-height: 24px;
color: #1c1b1f;
}
.md-body-medium {
font-size: 14px;
font-weight: 400;
line-height: 20px;
color: #49454f;
}
.md-label-large {
font-size: 14px;
font-weight: 500;
line-height: 20px;
color: #1c1b1f;
}
/* Surface colors and elevation */
.md-surface {
background: #fef7ff;
color: #1c1b1f;
}
.md-surface-container {
background: #f3f0ff;
color: #1c1b1f;
}
.md-surface-container-high {
background: #e7e0ec;
color: #1c1b1f;
}
</style>
<div class="md-form-container">
<form id=""
class="pydantic-form md-form col s12"
style=""
method="POST"
action="/showcase"
novalidate>
<div class="md-field">
<div class="md-field-with-icon">
<svg class="material-icons md-icon" viewBox="0 0 24 24" focusable="false" aria-hidden="true"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" /></svg>
<div class="md-input-wrapper">
<input type="text"
name="first_name"
id="first_name"
class="md-input"
value="Alex"
placeholder=" " >
<label class="md-floating-label" for="first_name">First Name *</label>
</div>
</div>
<div class="md-help-text">Your given name as it appears on official documents</div>
</div>
<div class="md-field">
<div class="md-field-with-icon">
<svg class="material-icons md-icon" viewBox="0 0 24 24" focusable="false" aria-hidden="true"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" /></svg>
<div class="md-input-wrapper">
<input type="text"
name="last_name"
id="last_name"
class="md-input"
value="Johnson"
placeholder=" " >
<label class="md-floating-label" for="last_name">Last Name *</label>
</div>
</div>
<div class="md-help-text">Your family name or surname</div>
</div>
<div class="md-field">
<div class="md-field-with-icon">
<svg class="material-icons md-icon" viewBox="0 0 24 24" focusable="false" aria-hidden="true"><path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4-8 5-8-5V6l8 5 8-5v2z" /></svg>
<div class="md-input-wrapper">
<input type="email"
name="email"
id="email"
class="md-input"
value="alex.johnson@example.com"
placeholder=" " >
<label class="md-floating-label" for="email">Email Address *</label>
</div>
</div>
<div class="md-help-text">We'll use this to contact you about your registration</div>
</div>
<div class="md-field">
<div class="md-field-with-icon">
<span class="material-icons md-icon">phone</span>
<div class="md-input-wrapper">
<input type="tel"
name="phone"
id="phone"
class="md-input"
value="+1 (555) 234-5678"
placeholder=" " >
<label class="md-floating-label" for="phone">Phone Number</label>
</div>
</div>
<div class="md-help-text">Include country code for international numbers</div>
</div>
<div class="md-field">
<div class="md-field-with-icon">
<span class="material-icons md-icon">event</span>
<div class="md-input-wrapper">
<input type="date"
name="birth_date"
id="birth_date"
class="md-input"
value="1995-06-15"
placeholder=" " >
<label class="md-floating-label" for="birth_date">Date of Birth</label>
</div>
</div>
<div class="md-help-text">Used to verify age requirements (optional)</div>
</div>
<div class="md-field">
<div class="md-field-with-icon">
<span class="material-icons md-icon">numbers</span>
<div class="md-input-wrapper">
<input type="number"
name="age"
id="age"
class="md-input"
value="28"
placeholder=" " >
<label class="md-floating-label" for="age">Age</label>
</div>
</div>
<div class="md-help-text">Your current age in years</div>
</div>
<div class="md-field">
<div class="md-field-with-icon">
<span class="material-icons md-icon">palette</span>
<div class="md-input-wrapper">
<input type="color"
name="favorite_color"
id="favorite_color"
class="md-input"
value="#3498db"
placeholder=" " >
<label class="md-floating-label" for="favorite_color">Favorite Color</label>
</div>
</div>
<div class="md-help-text">Pick your favorite color</div>
</div>
<div class="md-field">
<div class="md-field-with-icon">
<span class="material-icons md-icon">emoji_events</span>
<div class="md-input-wrapper">
<select name="experience_level"
id="experience_level"
class="md-select">
<option value=""></option>
<option value="beginner">π± Beginner (0-1 years)</option>
<option value="intermediate" selected="selected">π Intermediate (2-5 years)</option>
<option value="advanced">π― Advanced (5-10 years)</option>
<option value="expert">π Expert (10+ years)</option>
</select>
<label class="md-floating-label" for="experience_level">Experience Level *</label>
</div>
</div>
<div class="md-help-text">Select your experience level</div>
</div>
<div class="md-field">
<div class="md-checkbox-container">
<input type="checkbox"
name="newsletter_subscription"
id="newsletter_subscription"
class="md-checkbox"
value="true"
checked="checked">
<label for="newsletter_subscription" class="md-checkbox-label">Subscribe to Newsletter</label>
</div>
<div class="md-help-text">Receive updates and news about our services</div>
</div>
<div class="md-field">
<div class="md-field-with-icon">
<span class="material-icons md-icon">star</span>
<div class="md-input-wrapper">
<input type="range"
name="rating"
id="rating"
class="md-input"
value="8"
placeholder=" " >
<label class="md-floating-label" for="rating">Rate Your Interest (1-10)</label>
</div>
</div>
<div class="md-help-text">How interested are you in our services?</div>
</div>
<div class="md-field">
<div class="md-field-with-icon">
<span class="material-icons md-icon">home</span>
<div class="md-input-wrapper">
<textarea name="address"
id="address"
class="md-textarea"
placeholder=" ">456 Oak Avenue
Unit 12
Downtown District</textarea>
<label class="md-floating-label" for="address">Street Address</label>
</div>
</div>
<div class="md-help-text">Your full mailing address (optional)</div>
</div>
<div class="md-field">
<div class="md-field-with-icon">
<span class="material-icons md-icon">public</span>
<div class="md-input-wrapper">
<select name="country"
id="country"
class="md-select">
<option value=""></option>
<option value="US" selected="selected">πΊπΈ United States</option>
<option value="CA">π¨π¦ Canada</option>
<option value="UK">π¬π§ United Kingdom</option>
<option value="DE">π©πͺ Germany</option>
<option value="FR">π«π· France</option>
<option value="AU">π¦πΊ Australia</option>
<option value="OTHER">π Other</option>
</select>
<label class="md-floating-label" for="country">Country</label>
</div>
</div>
<div class="md-help-text">Select your country of residence</div>
</div>
<div class="md-field">
<div class="md-model-list-container">
<section class="md-model-list-wrapper">
<label class="md-field-label required">Your Pets</label>
<div class="model-list-container md-model-list-container" data-field-name="pets" data-min-items="0" data-max-items="5">
<div class="model-list-items md-model-list-items" id="pets-items">
<div class="model-list-item card border mb-3"
data-index="0"
data-title-template="πΎ {name} the {species}"
data-field-name="pets">
<div class="card-header d-flex justify-content-between align-items-center">
<h6 class="mb-0">
<button class="btn btn-link text-decoration-none p-0 text-start"
type="button"
data-bs-toggle="collapse"
data-bs-target="#pets_item_0_content"
aria-expanded="false"
aria-controls="pets_item_0_content">
<i class="bi bi-chevron-right me-2"></i>
<i class="bi bi-card-list me-2"></i>
πΎ Buddy the dog
</button>
</h6>
<button type="button"
class="btn btn-outline-danger btn-sm remove-item-btn"
data-index="0"
data-field-name="pets"
title="Remove this item">
<i class="bi bi-trash"></i>
</button>
</div>
<div class="collapse collapse show" id="pets_item_0_content">
<div class="card-body"><div class="row">
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[0].name"><i class="material-icons">favorite_border</i> Pet's Name</label>
<input name="pets[0].name" id="pets[0].name" class="validate" value="Buddy" minlength="1" maxlength="11" placeholder="Enter your pet's name" pattern="\d{3}-\d{2}-\d{4}" inputmode="numeric" autocomplete="off" type="text" />
<div class="help-text">The name of your pet</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><div class="md-field">
<div class="md-field-with-icon">
<span class="md-icon material-icons">collections</span>
<div class="md-input-wrapper">
<select name="pets[0].species" id="pets[0].species" class="browser-default"><option value="Dog">Dog π</option>
<option value="Cat">Cat π±</option>
<option value="Bird">Bird π¦</option>
<option value="Fish">Fish π </option>
<option value="Rabbit">Rabbit π°</option>
<option value="Hamster">Hamster πΉ</option>
<option value="Reptile">Reptile π¦</option>
<option value="Other">Other πΎ</option></select>
<label class="md-floating-label" for="pets[0].species">Species</label>
</div>
</div>
<div class="md-help-text">What type of animal is your pet?</div>
</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[0].age"><i class="material-icons">calendar_today</i> Age</label>
<input name="pets[0].age" id="pets[0].age" class="validate" value="4" placeholder="Pet's age in years%" min="0" max="100" step="0.1" inputmode="numeric" type="number" />
<div class="help-text">How old is your pet? (optional)</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[0].weight"><i class="material-icons">speed</i> Weight (lbs)</label>
<input name="pets[0].weight" id="pets[0].weight" class="validate" value="70.0" placeholder="Pet's weight%" min="0" max="100" step="0.1" inputmode="numeric" type="number" />
<div class="help-text">Weight in pounds (optional - enter 0.01 for tiny pets like birds)</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[0].is_vaccinated"><i class="material-icons">verified_user</i> Vaccinated</label>
<input name="pets[0].is_vaccinated" id="pets[0].is_vaccinated" class="filled-in" value="1" type="checkbox" />
<div class="help-text">Is your pet up to date with vaccinations?</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[0].microchipped"><i class="material-icons">memory</i> Microchipped</label>
<input name="pets[0].microchipped" id="pets[0].microchipped" class="filled-in" checked="checked" value="1" type="checkbox" />
<div class="help-text">Does your pet have a microchip?</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[0].breed"><i class="material-icons">military_tech</i> Breed</label>
<input name="pets[0].breed" id="pets[0].breed" class="validate" value="Labrador" placeholder="e.g., Golden Retriever, Persian Cat" pattern="\d{3}-\d{2}-\d{4}" maxlength="11" inputmode="numeric" autocomplete="off" type="text" />
<div class="help-text">Specific breed of your pet (optional)</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[0].color"><i class="material-icons">palette</i> Primary Color</label>
<div class="color-input-group"><input name="pets[0].color" id="pets[0].color" class="validate" type="color" />
<div class="color-value-display" style="display: inline-flex; align-items: center; margin-left: 10px;">
<span id="pets[0].color_value" style="font-family: monospace;"></span>
<div id="pets[0].color_swatch" style="width: 20px; height: 20px; background-color: ; border: 1px solid #ccc; margin-left: 5px;"></div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const colorInput = document.getElementById('pets[0].color');
const valueSpan = document.getElementById('pets[0].color_value');
const swatch = document.getElementById('pets[0].color_swatch');
if (colorInput && valueSpan && swatch) {
colorInput.addEventListener('input', function() {
valueSpan.textContent = this.value;
swatch.style.backgroundColor = this.value;
});
}
});
</script>
</div>
<div class="help-text">Primary color of your pet (optional)</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[0].last_vet_visit"><i class="material-icons">event</i> Last Vet Visit</label>
<div class="birthdate-input-group"><input name="pets[0].last_vet_visit" id="pets[0].last_vet_visit" class="validate" max="2026-01-07" min="1876-01-01" type="date" />
<div class="age-display" id="pets[0].last_vet_visit_age" style="margin-top: 5px; font-size: 0.9em; color: #666;"></div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const birthdateField = document.getElementById('pets[0].last_vet_visit');
const ageDisplay = document.getElementById('pets[0].last_vet_visit_age');
function calculateAge() {
if (birthdateField.value && ageDisplay) {
const birthDate = new Date(birthdateField.value);
const today = new Date();
let age = today.getFullYear() - birthDate.getFullYear();
const monthDiff = today.getMonth() - birthDate.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
age--;
}
ageDisplay.textContent = age >= 0 ? `Age: ${age} years` : '';
}
}
if (birthdateField) {
birthdateField.addEventListener('change', calculateAge);
calculateAge(); // Calculate on load if value is set
}
});
</script>
</div>
<div class="help-text">When was the last veterinary checkup? (optional)</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[0].special_needs"><i class="material-icons">monitor_heart</i> Special Needs</label>
<textarea name="pets[0].special_needs" id="pets[0].special_needs" class="validate" placeholder="Any special care requirements, medications, allergies, etc.">Needs hip medication twice daily</textarea>
<div class="help-text">Describe any special care requirements (optional)</div></div>
</div></div>
</div>
</div>
</div>
<div class="model-list-item card border mb-3"
data-index="1"
data-title-template="πΎ {name} the {species}"
data-field-name="pets">
<div class="card-header d-flex justify-content-between align-items-center">
<h6 class="mb-0">
<button class="btn btn-link text-decoration-none p-0 text-start"
type="button"
data-bs-toggle="collapse"
data-bs-target="#pets_item_1_content"
aria-expanded="false"
aria-controls="pets_item_1_content">
<i class="bi bi-chevron-right me-2"></i>
<i class="bi bi-card-list me-2"></i>
πΎ Whiskers the cat
</button>
</h6>
<button type="button"
class="btn btn-outline-danger btn-sm remove-item-btn"
data-index="1"
data-field-name="pets"
title="Remove this item">
<i class="bi bi-trash"></i>
</button>
</div>
<div class="collapse collapse show" id="pets_item_1_content">
<div class="card-body"><div class="row">
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[1].name"><i class="material-icons">favorite_border</i> Pet's Name</label>
<input name="pets[1].name" id="pets[1].name" class="validate" value="Whiskers" minlength="1" maxlength="11" placeholder="Enter your pet's name" pattern="\d{3}-\d{2}-\d{4}" inputmode="numeric" autocomplete="off" type="text" />
<div class="help-text">The name of your pet</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><div class="md-field">
<div class="md-field-with-icon">
<span class="md-icon material-icons">collections</span>
<div class="md-input-wrapper">
<select name="pets[1].species" id="pets[1].species" class="browser-default"><option value="Dog">Dog π</option>
<option value="Cat">Cat π±</option>
<option value="Bird">Bird π¦</option>
<option value="Fish">Fish π </option>
<option value="Rabbit">Rabbit π°</option>
<option value="Hamster">Hamster πΉ</option>
<option value="Reptile">Reptile π¦</option>
<option value="Other">Other πΎ</option></select>
<label class="md-floating-label" for="pets[1].species">Species</label>
</div>
</div>
<div class="md-help-text">What type of animal is your pet?</div>
</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[1].age"><i class="material-icons">calendar_today</i> Age</label>
<input name="pets[1].age" id="pets[1].age" class="validate" value="5" placeholder="Pet's age in years%" min="0" max="100" step="0.1" inputmode="numeric" type="number" />
<div class="help-text">How old is your pet? (optional)</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[1].weight"><i class="material-icons">speed</i> Weight (lbs)</label>
<input name="pets[1].weight" id="pets[1].weight" class="validate" value="12.5" placeholder="Pet's weight%" min="0" max="100" step="0.1" inputmode="numeric" type="number" />
<div class="help-text">Weight in pounds (optional - enter 0.01 for tiny pets like birds)</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[1].is_vaccinated"><i class="material-icons">verified_user</i> Vaccinated</label>
<input name="pets[1].is_vaccinated" id="pets[1].is_vaccinated" class="filled-in" value="1" type="checkbox" />
<div class="help-text">Is your pet up to date with vaccinations?</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[1].microchipped"><i class="material-icons">memory</i> Microchipped</label>
<input name="pets[1].microchipped" id="pets[1].microchipped" class="filled-in" checked="checked" value="1" type="checkbox" />
<div class="help-text">Does your pet have a microchip?</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[1].breed"><i class="material-icons">military_tech</i> Breed</label>
<input name="pets[1].breed" id="pets[1].breed" class="validate" value="Maine Coon" placeholder="e.g., Golden Retriever, Persian Cat" pattern="\d{3}-\d{2}-\d{4}" maxlength="11" inputmode="numeric" autocomplete="off" type="text" />
<div class="help-text">Specific breed of your pet (optional)</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[1].color"><i class="material-icons">palette</i> Primary Color</label>
<div class="color-input-group"><input name="pets[1].color" id="pets[1].color" class="validate" type="color" />
<div class="color-value-display" style="display: inline-flex; align-items: center; margin-left: 10px;">
<span id="pets[1].color_value" style="font-family: monospace;"></span>
<div id="pets[1].color_swatch" style="width: 20px; height: 20px; background-color: ; border: 1px solid #ccc; margin-left: 5px;"></div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const colorInput = document.getElementById('pets[1].color');
const valueSpan = document.getElementById('pets[1].color_value');
const swatch = document.getElementById('pets[1].color_swatch');
if (colorInput && valueSpan && swatch) {
colorInput.addEventListener('input', function() {
valueSpan.textContent = this.value;
swatch.style.backgroundColor = this.value;
});
}
});
</script>
</div>
<div class="help-text">Primary color of your pet (optional)</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[1].last_vet_visit"><i class="material-icons">event</i> Last Vet Visit</label>
<div class="birthdate-input-group"><input name="pets[1].last_vet_visit" id="pets[1].last_vet_visit" class="validate" max="2026-01-07" min="1876-01-01" type="date" />
<div class="age-display" id="pets[1].last_vet_visit_age" style="margin-top: 5px; font-size: 0.9em; color: #666;"></div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const birthdateField = document.getElementById('pets[1].last_vet_visit');
const ageDisplay = document.getElementById('pets[1].last_vet_visit_age');
function calculateAge() {
if (birthdateField.value && ageDisplay) {
const birthDate = new Date(birthdateField.value);
const today = new Date();
let age = today.getFullYear() - birthDate.getFullYear();
const monthDiff = today.getMonth() - birthDate.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
age--;
}
ageDisplay.textContent = age >= 0 ? `Age: ${age} years` : '';
}
}
if (birthdateField) {
birthdateField.addEventListener('change', calculateAge);
calculateAge(); // Calculate on load if value is set
}
});
</script>
</div>
<div class="help-text">When was the last veterinary checkup? (optional)</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="pets[1].special_needs"><i class="material-icons">monitor_heart</i> Special Needs</label>
<textarea name="pets[1].special_needs" id="pets[1].special_needs" class="validate" placeholder="Any special care requirements, medications, allergies, etc.">Requires grain-free diet</textarea>
<div class="help-text">Describe any special care requirements (optional)</div></div>
</div></div>
</div>
</div>
</div>
</div>
<div class="md-model-list-actions">
<button type="button" class="md-button md-button-tonal add-item-btn" data-target="pets">
<svg class="material-icons md-button__icon" viewBox="0 0 24 24" focusable="false" aria-hidden="true"><path d="M19 13H13v6h-2v-6H5v-2h6V5h2v6h6v2z" /></svg>
<span class="md-button__label">Add Item</span>
</button>
</div>
</div>
<p class="md-help-text">Tell us about each of your beloved pets</p>
</section>
</div>
</div>
<div class="md-field">
<div class="md-model-list-container">
<section class="md-model-list-wrapper">
<label class="md-field-label required">Emergency Contacts</label>
<div class="model-list-container md-model-list-container" data-field-name="emergency_contacts" data-min-items="1" data-max-items="3">
<div class="model-list-items md-model-list-items" id="emergency_contacts-items">
<div class="model-list-item card border mb-3"
data-index="0"
data-title-template="π {name} ({relationship})"
data-field-name="emergency_contacts">
<div class="card-header d-flex justify-content-between align-items-center">
<h6 class="mb-0">
<button class="btn btn-link text-decoration-none p-0 text-start"
type="button"
data-bs-toggle="collapse"
data-bs-target="#emergency_contacts_item_0_content"
aria-expanded="true"
aria-controls="emergency_contacts_item_0_content">
<i class="bi bi-chevron-down me-2"></i>
<i class="bi bi-card-list me-2"></i>
π Emma Johnson (spouse)
</button>
</h6>
<button type="button"
class="btn btn-outline-danger btn-sm remove-item-btn"
data-index="0"
data-field-name="emergency_contacts"
title="Remove this item">
<i class="bi bi-trash"></i>
</button>
</div>
<div class="collapse show" id="emergency_contacts_item_0_content">
<div class="card-body"><div class="row">
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="emergency_contacts[0].name"><i class="material-icons">badge</i> Contact Name</label>
<input name="emergency_contacts[0].name" id="emergency_contacts[0].name" class="validate" value="Emma Johnson" minlength="2" maxlength="11" placeholder="John Doe" pattern="\d{3}-\d{2}-\d{4}" inputmode="numeric" autocomplete="off" type="text" />
<div class="help-text">Full name of emergency contact</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><div class="md-field">
<div class="md-field-with-icon">
<span class="md-icon material-icons">people</span>
<div class="md-input-wrapper">
<select name="emergency_contacts[0].relationship" id="emergency_contacts[0].relationship" class="browser-default"><option value="spouse" selected>π Spouse/Partner</option>
<option value="parent">π¨βπ©βπ§βπ¦ Parent</option>
<option value="child">πΆ Child</option>
<option value="sibling">π« Sibling</option>
<option value="friend">π₯ Friend</option>
<option value="colleague">πΌ Colleague</option>
<option value="other">π€ Other</option></select>
<label class="md-floating-label" for="emergency_contacts[0].relationship">Relationship</label>
</div>
</div>
<div class="md-help-text">Your relationship to this person</div>
</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="emergency_contacts[0].phone"><i class="material-icons">phone</i> Phone Number</label>
<input name="emergency_contacts[0].phone" id="emergency_contacts[0].phone" class="validate" value="+1 (555) 345-6789" minlength="10" maxlength="20" placeholder="+1 (555) 123-4567" inputmode="tel" autocomplete="tel" type="tel" />
<div class="help-text">Primary phone number for this contact</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="emergency_contacts[0].email"><i class="material-icons">email</i> Email Address</label>
<input name="emergency_contacts[0].email" id="emergency_contacts[0].email" class="validate" value="emma.johnson@example.com" placeholder="contact@example.com" inputmode="email" type="email" />
<div class="help-text">Email address (optional)</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="emergency_contacts[0].available_24_7"><i class="material-icons">schedule</i> Available 24/7</label>
<input name="emergency_contacts[0].available_24_7" id="emergency_contacts[0].available_24_7" class="filled-in" checked="checked" value="1" type="checkbox" />
<div class="help-text">Can this person be contacted at any time?</div></div>
</div></div>
</div>
</div>
</div>
<div class="model-list-item card border mb-3"
data-index="1"
data-title-template="π {name} ({relationship})"
data-field-name="emergency_contacts">
<div class="card-header d-flex justify-content-between align-items-center">
<h6 class="mb-0">
<button class="btn btn-link text-decoration-none p-0 text-start"
type="button"
data-bs-toggle="collapse"
data-bs-target="#emergency_contacts_item_1_content"
aria-expanded="true"
aria-controls="emergency_contacts_item_1_content">
<i class="bi bi-chevron-down me-2"></i>
<i class="bi bi-card-list me-2"></i>
π Robert Johnson (parent)
</button>
</h6>
<button type="button"
class="btn btn-outline-danger btn-sm remove-item-btn"
data-index="1"
data-field-name="emergency_contacts"
title="Remove this item">
<i class="bi bi-trash"></i>
</button>
</div>
<div class="collapse show" id="emergency_contacts_item_1_content">
<div class="card-body"><div class="row">
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="emergency_contacts[1].name"><i class="material-icons">badge</i> Contact Name</label>
<input name="emergency_contacts[1].name" id="emergency_contacts[1].name" class="validate" value="Robert Johnson" minlength="2" maxlength="11" placeholder="John Doe" pattern="\d{3}-\d{2}-\d{4}" inputmode="numeric" autocomplete="off" type="text" />
<div class="help-text">Full name of emergency contact</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><div class="md-field">
<div class="md-field-with-icon">
<span class="md-icon material-icons">people</span>
<div class="md-input-wrapper">
<select name="emergency_contacts[1].relationship" id="emergency_contacts[1].relationship" class="browser-default"><option value="spouse">π Spouse/Partner</option>
<option value="parent" selected>π¨βπ©βπ§βπ¦ Parent</option>
<option value="child">πΆ Child</option>
<option value="sibling">π« Sibling</option>
<option value="friend">π₯ Friend</option>
<option value="colleague">πΌ Colleague</option>
<option value="other">π€ Other</option></select>
<label class="md-floating-label" for="emergency_contacts[1].relationship">Relationship</label>
</div>
</div>
<div class="md-help-text">Your relationship to this person</div>
</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="emergency_contacts[1].phone"><i class="material-icons">phone</i> Phone Number</label>
<input name="emergency_contacts[1].phone" id="emergency_contacts[1].phone" class="validate" value="+1 (555) 456-7890" minlength="10" maxlength="20" placeholder="+1 (555) 123-4567" inputmode="tel" autocomplete="tel" type="tel" />
<div class="help-text">Primary phone number for this contact</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="emergency_contacts[1].email"><i class="material-icons">email</i> Email Address</label>
<input name="emergency_contacts[1].email" id="emergency_contacts[1].email" class="validate" value="robert.johnson@example.com" placeholder="contact@example.com" inputmode="email" type="email" />
<div class="help-text">Email address (optional)</div></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="input-field col s12"><label for="emergency_contacts[1].available_24_7"><i class="material-icons">schedule</i> Available 24/7</label>
<input name="emergency_contacts[1].available_24_7" id="emergency_contacts[1].available_24_7" class="filled-in" value="1" type="checkbox" />
<div class="help-text">Can this person be contacted at any time?</div></div>
</div></div>
</div>
</div>
</div>
</div>
<div class="md-model-list-actions">
<button type="button" class="md-button md-button-tonal add-item-btn" data-target="emergency_contacts">
<svg class="material-icons md-button__icon" viewBox="0 0 24 24" focusable="false" aria-hidden="true"><path d="M19 13H13v6h-2v-6H5v-2h6V5h2v6h6v2z" /></svg>
<span class="md-button__label">Add Item</span>
</button>
</div>
</div>
<p class="md-help-text">Add people we can contact in case of emergency</p>
</section>
</div>
</div>
<div class="md-field">
<div class="md-field-with-icon">
<span class="material-icons md-icon">chat_bubble_outline</span>
<div class="md-input-wrapper">
<textarea name="special_requests"
id="special_requests"
class="md-textarea"
placeholder=" ">Please contact me via email for all communications. I work night shifts and may not be available by phone during the day.</textarea>
<label class="md-floating-label" for="special_requests">Special Requests or Comments</label>
</div>
</div>
<div class="md-help-text">Let us know about any special accommodations you need</div>
</div>
<div class="md-field">
<div class="md-checkbox-container">
<input type="checkbox"
name="terms_accepted"
id="terms_accepted"
class="md-checkbox"
value="true"
checked="checked">
<label for="terms_accepted" class="md-checkbox-label">I accept the Terms and Conditions</label>
</div>
<div class="md-help-text">You must accept the terms to proceed</div>
</div>
<div class="md-field">
<button type="submit" class="md-button md-button-filled">Submit</button>
</div>
</form>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Material Design 3 form enhancements
// Floating label functionality for outlined text fields
function initializeFloatingLabels() {
const textFields = document.querySelectorAll('.md-input, .md-textarea, .md-select');
textFields.forEach(input => {
const label = input.nextElementSibling;
if (label && label.classList.contains('md-floating-label')) {
// Check initial state
function updateLabelState() {
const hasValue = input.value && input.value.trim() !== '';
const isFocused = document.activeElement === input;
if (hasValue || isFocused) {
label.style.transform = 'translateY(-28px) scale(0.75)';
label.style.color = isFocused ? '#6750a4' : '#49454f';
label.style.background = '#ffffff';
label.style.padding = '0 4px';
} else {
label.style.transform = 'translateY(0) scale(1)';
label.style.color = '#49454f';
label.style.background = 'transparent';
label.style.padding = '0';
}
}
// Set up event listeners
input.addEventListener('focus', updateLabelState);
input.addEventListener('blur', updateLabelState);
input.addEventListener('input', updateLabelState);
// Initial state check
updateLabelState();
}
});
}
// Enhanced focus and blur effects
const inputs = document.querySelectorAll('.md-input, .md-select, .md-textarea');
inputs.forEach(input => {
input.addEventListener('focus', function() {
this.style.transform = 'scale(1.01)';
this.style.transition = 'all 0.15s cubic-bezier(0.4, 0, 0.2, 1)';
});
input.addEventListener('blur', function() {
this.style.transform = 'scale(1)';
});
});
// Checkbox interactions with Material Design ripple effect
const checkboxes = document.querySelectorAll('.md-checkbox');
checkboxes.forEach(checkbox => {
checkbox.addEventListener('change', function() {
const container = this.closest('.md-checkbox-container');
if (this.checked) {
// Create ripple effect
const ripple = document.createElement('div');
ripple.style.position = 'absolute';
ripple.style.borderRadius = '50%';
ripple.style.background = 'rgba(103, 80, 164, 0.3)';
ripple.style.width = '40px';
ripple.style.height = '40px';
ripple.style.left = '-11px';
ripple.style.top = '-11px';
ripple.style.pointerEvents = 'none';
ripple.style.transform = 'scale(0)';
ripple.style.transition = 'transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)';
this.style.position = 'relative';
this.appendChild(ripple);
// Animate ripple
setTimeout(() => {
ripple.style.transform = 'scale(1)';
setTimeout(() => {
ripple.style.opacity = '0';
setTimeout(() => {
if (ripple.parentNode) {
ripple.parentNode.removeChild(ripple);
}
}, 300);
}, 200);
}, 10);
}
});
});
// Enhanced form validation with Material Design styling
const form = document.querySelector('.md-form');
if (form) {
form.addEventListener('submit', function(e) {
const requiredInputs = this.querySelectorAll('input[required], select[required], textarea[required]');
let hasErrors = false;
requiredInputs.forEach(input => {
const value = input.type === 'checkbox' ? input.checked : input.value.trim();
const fieldContainer = input.closest('.md-field');
if (!value) {
input.classList.add('error');
// Add error styling to label
const label = input.nextElementSibling;
if (label && label.classList.contains('md-floating-label')) {
label.style.color = '#ba1a1a';
}
// Create or update error message
let errorDiv = fieldContainer.querySelector('.md-error-text');
if (!errorDiv) {
errorDiv = document.createElement('div');
errorDiv.className = 'md-error-text';
fieldContainer.appendChild(errorDiv);
}
errorDiv.textContent = 'This field is required';
hasErrors = true;
} else {
input.classList.remove('error');
// Remove error styling from label
const label = input.nextElementSibling;
if (label && label.classList.contains('md-floating-label')) {
label.style.color = input === document.activeElement ? '#6750a4' : '#49454f';
}
// Remove error message if it was dynamically added
const errorDiv = fieldContainer.querySelector('.md-error-text');
if (errorDiv && errorDiv.textContent === 'This field is required') {
errorDiv.remove();
}
}
});
if (hasErrors) {
e.preventDefault();
// Scroll to first error with smooth animation
const firstError = this.querySelector('.error');
if (firstError) {
firstError.scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'nearest'
});
// Focus the field for better UX
setTimeout(() => {
firstError.focus();
}, 500);
}
}
});
// Real-time validation for better UX
const allInputs = form.querySelectorAll('input, select, textarea');
allInputs.forEach(input => {
input.addEventListener('blur', function() {
if (this.hasAttribute('required')) {
const value = this.type === 'checkbox' ? this.checked : this.value.trim();
const fieldContainer = this.closest('.md-field');
if (!value) {
this.classList.add('error');
const label = this.nextElementSibling;
if (label && label.classList.contains('md-floating-label')) {
label.style.color = '#ba1a1a';
}
} else {
this.classList.remove('error');
const label = this.nextElementSibling;
if (label && label.classList.contains('md-floating-label')) {
label.style.color = '#49454f';
}
}
}
});
});
}
# Initialize floating labels
initializeFloatingLabels();
# Reinitialize for dynamically added content
window.reinitializeMaterialForms = function() {
initializeFloatingLabels();
};
});
</script>
<script>
(function() {
document.addEventListener('DOMContentLoaded', function() {
// Prevent Enter key from submitting forms unless on submit button
const forms = document.querySelectorAll('form.md-form, form.pydantic-form');
forms.forEach(function(form) {
form.addEventListener('keydown', function(e) {
// Check if Enter key is pressed
if (e.key === 'Enter' || e.keyCode === 13) {
const target = e.target;
// Allow Enter in textareas (for multi-line input)
if (target.tagName === 'TEXTAREA') {
return;
}
// Allow Enter on submit buttons
if (target.tagName === 'BUTTON' && target.type === 'submit') {
return;
}
// Allow Enter on input type="submit"
if (target.tagName === 'INPUT' && target.type === 'submit') {
return;
}
// Prevent form submission for all other cases
e.preventDefault();
return false;
}
});
});
});
})();
</script>
<script>
(function() {
'use strict';
// Ensure this runs after DOM is loaded
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeModelLists);
} else {
initializeModelLists();
}
function initializeModelLists() {
// Add item functionality
const addButtons = document.querySelectorAll('.add-item-btn');
addButtons.forEach(button => {
if (!button.hasAttribute('data-initialized')) {
button.setAttribute('data-initialized', 'true');
button.addEventListener('click', handleAddItem);
}
});
// Remove item functionality - use direct event listeners
const removeButtons = document.querySelectorAll('.remove-item-btn');
removeButtons.forEach(button => {
if (!button.hasAttribute('data-initialized')) {
button.setAttribute('data-initialized', 'true');
button.addEventListener('click', handleRemoveItem);
}
});
// Also set up delegation for dynamically added buttons
document.addEventListener('click', function(e) {
if (e.target.closest('.remove-item-btn') && !e.target.closest('.remove-item-btn').hasAttribute('data-initialized')) {
const button = e.target.closest('.remove-item-btn');
button.setAttribute('data-initialized', 'true');
handleRemoveItem.call(button, e);
}
});
}
function handleAddItem(e) {
e.preventDefault();
e.stopPropagation();
const fieldName = this.dataset.target;
const container = document.querySelector(`[data-field-name="${fieldName}"]`);
if (!container) return;
const itemsContainer = container.querySelector('.model-list-items');
const maxItems = parseInt(container.dataset.maxItems || '10');
const currentItems = itemsContainer.querySelectorAll('.model-list-item').length;
if (currentItems >= maxItems) {
alert(`Maximum ${maxItems} items allowed.`);
return;
}
addNewListItem(fieldName, currentItems);
updateItemIndices(itemsContainer);
}
function handleRemoveItem(e) {
e.preventDefault();
e.stopPropagation();
const button = e.currentTarget || this;
const item = button.closest('.model-list-item');
if (!item) return;
const container = item.closest('.model-list-container');
if (!container) return;
const minItems = parseInt(container.dataset.minItems || '0');
const itemsContainer = container.querySelector('.model-list-items');
const currentItems = itemsContainer.querySelectorAll('.model-list-item').length;
if (currentItems <= minItems) {
alert(`Minimum ${minItems} items required.`);
return;
}
// Check if item has data
const hasData = Array.from(item.querySelectorAll('input, select, textarea')).some(input => {
if (input.type === 'checkbox' || input.type === 'radio') {
return input.checked;
}
return input.value && input.value.trim() !== '';
});
if (hasData) {
if (!confirm('Are you sure you want to remove this item? All data will be lost.')) {
return;
}
}
item.remove();
updateItemIndices(itemsContainer);
}
// Update titles when input fields change
document.addEventListener('input', function(e) {
if (e.target.name && (e.target.name.includes('.name') || e.target.name.includes('.relationship'))) {
updateItemTitle(e.target);
}
});
// Handle collapse icons
document.addEventListener('click', function(e) {
const collapseButton = e.target.closest('[data-bs-toggle="collapse"]');
if (collapseButton) {
const icon = collapseButton.querySelector('.bi-chevron-down, .bi-chevron-right');
if (icon) {
setTimeout(() => {
const isExpanded = collapseButton.getAttribute('aria-expanded') === 'true';
icon.className = isExpanded ? 'bi bi-chevron-down me-2' : 'bi bi-chevron-right me-2';
}, 50);
}
}
});
})();
function addNewListItem(fieldName, index) {
const container = document.querySelector(`[data-field-name="${fieldName}"]`);
const itemsContainer = container.querySelector('.model-list-items');
// Get the first item as a template if it exists
const firstItem = itemsContainer.querySelector('.model-list-item');
if (firstItem) {
const newItem = firstItem.cloneNode(true);
// Clear all input values
newItem.querySelectorAll('input, select, textarea').forEach(input => {
if (input.type === 'checkbox' || input.type === 'radio') {
input.checked = false;
} else {
input.value = '';
}
});
// Update data-index
newItem.dataset.index = index;
// Update field names and IDs
updateFieldNames(newItem, fieldName, index);
// Update collapse IDs
updateCollapseIds(newItem, fieldName, index);
// Expand the new item
const collapseDiv = newItem.querySelector('.collapse');
if (collapseDiv) {
collapseDiv.classList.add('show');
}
// Update collapse button aria-expanded
const collapseButton = newItem.querySelector('[data-bs-toggle="collapse"]');
if (collapseButton) {
collapseButton.setAttribute('aria-expanded', 'true');
const icon = collapseButton.querySelector('.bi-chevron-down, .bi-chevron-right');
if (icon) {
icon.className = 'bi bi-chevron-down me-2';
}
}
itemsContainer.appendChild(newItem);
}
}
function updateItemIndices(container) {
const items = container.querySelectorAll('.model-list-item');
items.forEach((item, index) => {
item.dataset.index = index;
// Update field names first
const fieldName = container.closest('.model-list-container').dataset.fieldName;
updateFieldNames(item, fieldName, index);
updateCollapseIds(item, fieldName, index);
// Update title using the dynamic template
updateItemTitleFromData(item, index);
});
}
function updateFieldNames(item, fieldName, index) {
item.querySelectorAll('input, select, textarea').forEach(input => {
if (input.name) {
// Update name attribute to use correct index
input.name = input.name.replace(/\[\d+\]/, `[${index}]`);
}
if (input.id) {
// Update id attribute
input.id = input.id.replace(/\[\d+\]/, `[${index}]`);
}
});
item.querySelectorAll('label').forEach(label => {
if (label.getAttribute('for')) {
label.setAttribute('for', label.getAttribute('for').replace(/\[\d+\]/, `[${index}]`));
}
});
}
function updateCollapseIds(item, fieldName, index) {
const collapseDiv = item.querySelector('.collapse');
const collapseButton = item.querySelector('[data-bs-toggle="collapse"]');
if (collapseDiv && collapseButton) {
const newId = `${fieldName}_item_${index}_content`;
collapseDiv.id = newId;
collapseButton.setAttribute('data-bs-target', `#${newId}`);
collapseButton.setAttribute('aria-controls', newId);
}
}
function updateItemTitle(inputElement) {
const item = inputElement.closest('.model-list-item');
if (!item) return;
updateItemTitleFromData(item);
}
function updateItemTitleFromData(item, forceIndex = null) {
const index = forceIndex !== null ? forceIndex : parseInt(item.dataset.index);
const titleTemplate = item.dataset.titleTemplate || 'Item #{index}';
const titleElement = item.querySelector('h6 button, h6 span');
if (!titleElement) return;
// Extract current form data from the item
const formData = { index: index + 1 };
item.querySelectorAll('input, select, textarea').forEach(input => {
if (input.name) {
// Extract field name (e.g., "pets[0].name" -> "name")
const fieldMatch = input.name.match(/\.([^.]+)$/);
if (fieldMatch) {
const fieldName = fieldMatch[1];
if (input.type === 'checkbox') {
formData[fieldName] = input.checked;
} else {
formData[fieldName] = input.value || '';
}
}
}
});
// Generate title from template
let newTitle;
try {
newTitle = titleTemplate.replace(/\{([^}]+)\}/g, (match, key) => {
return formData[key] || '';
});
} catch (e) {
newTitle = `Item #${index + 1}`;
}
// Update the title while preserving icons
const cardIcon = '<i class="bi bi-card-list me-2"></i>';
if (titleElement.tagName === 'BUTTON') {
const chevronIcon = titleElement.querySelector('.bi-chevron-down, .bi-chevron-right');
const chevronHtml = chevronIcon ? chevronIcon.outerHTML : '<i class="bi bi-chevron-down me-2"></i>';
titleElement.innerHTML = `${chevronHtml}${cardIcon}${newTitle}`;
} else {
titleElement.innerHTML = `${cardIcon}${newTitle}`;
}
}
</script>
class CompleteShowcaseForm(FormModel):
"""
Complete showcase form demonstrating all Pydantic SchemaForms capabilities:
- All input types (text, email, number, select, checkbox, date, color, etc.)
- Collapsible list layouts with cards
- Dynamic titles and field validation
- Icons and help text
- Multiple layout options
"""
# ======== PERSONAL INFORMATION SECTION ========
first_name: str = FormField(
title="First Name",
input_type="text",
placeholder="Enter your first name",
help_text="Your given name as it appears on official documents",
icon="person",
min_length=2,
max_length=50
)
last_name: str = FormField(
title="Last Name",
input_type="text",
placeholder="Enter your last name",
help_text="Your family name or surname",
icon="person",
min_length=2,
max_length=50
)
email: EmailStr = FormField(
title="Email Address",
input_type="email",
placeholder="your.email@example.com",
help_text="We'll use this to contact you about your registration",
icon="envelope"
)
phone: Optional[str] = FormField(
None,
title="Phone Number",
input_type="tel",
placeholder="+1 (555) 123-4567",
help_text="Include country code for international numbers",
icon="telephone",
pattern=r"^[\+]?[1-9][\d]{0,15}$"
)
birth_date: Optional[date] = FormField(
None,
title="Date of Birth",
input_type="date",
help_text="Used to verify age requirements (optional)",
icon="calendar-date"
)
age: Optional[int] = FormField(
None,
title="Age",
input_type="number",
placeholder="25",
help_text="Your current age in years",
icon="hash",
min_value=13,
max_value=120
)
# ======== PREFERENCES SECTION ========
favorite_color: Optional[str] = FormField(
"#3498db",
title="Favorite Color",
input_type="color",
help_text="Pick your favorite color",
icon="palette"
)
experience_level: str = FormField(
title="Experience Level",
input_type="select",
options=[
{"value": "beginner", "label": "π± Beginner (0-1 years)"},
{"value": "intermediate", "label": "π Intermediate (2-5 years)"},
{"value": "advanced", "label": "π― Advanced (5-10 years)"},
{"value": "expert", "label": "π Expert (10+ years)"}
],
help_text="Select your experience level",
icon="trophy"
)
newsletter_subscription: bool = FormField(
True,
title="Subscribe to Newsletter",
input_type="checkbox",
help_text="Receive updates and news about our services",
icon="mailbox"
)
rating: Optional[int] = FormField(
None,
title="Rate Your Interest (1-10)",
input_type="range",
help_text="How interested are you in our services?",
icon="star",
min_value=1,
max_value=10
)
# ======== ADDRESS INFORMATION ========
address: Optional[str] = FormField(
None,
title="Street Address",
input_type="textarea",
placeholder="123 Main Street\nApt 4B",
help_text="Your full mailing address (optional)",
icon="house",
max_length=500
)
country: Optional[Country] = FormField(
None,
title="Country",
input_type="select",
options=[
{"value": "US", "label": "πΊπΈ United States"},
{"value": "CA", "label": "π¨π¦ Canada"},
{"value": "UK", "label": "π¬π§ United Kingdom"},
{"value": "DE", "label": "π©πͺ Germany"},
{"value": "FR", "label": "π«π· France"},
{"value": "AU", "label": "π¦πΊ Australia"},
{"value": "OTHER", "label": "π Other"}
],
help_text="Select your country of residence",
icon="globe"
)
# ======== PETS SECTION (ENHANCED LIST) ========
pets: List[PetModel] = FormField(
default_factory=list,
title="Your Pets",
input_type="model_list",
help_text="Tell us about each of your beloved pets",
icon="heart-fill",
min_length=0,
max_length=5,
model_class=PetModel,
add_button_text="πΎ Add Another Pet",
remove_button_text="Remove Pet",
collapsible_items=True,
items_expanded=False,
item_title_template="πΎ {name} the {species}",
section_design={
"section_title": "Pet Registry",
"section_description": "Register each of your pets with detailed information for our records",
"icon": "bi bi-heart-fill",
"collapsible": True,
"collapsed": False
}
)
# ======== EMERGENCY CONTACTS (ANOTHER LIST) ========
emergency_contacts: List[EmergencyContactModel] = FormField(
default_factory=list,
title="Emergency Contacts",
input_type="model_list",
help_text="Add people we can contact in case of emergency",
icon="person-exclamation",
min_length=1,
max_length=3,
model_class=EmergencyContactModel,
add_button_text="β Add Emergency Contact",
remove_button_text="Remove Contact",
collapsible_items=True,
items_expanded=True,
item_title_template="π {name} ({relationship})",
section_design={
"section_title": "Emergency Contacts",
"section_description": "At least one emergency contact is required",
"icon": "bi bi-shield-exclamation",
"collapsible": False,
"collapsed": False
}
)
# ======== ADDITIONAL PREFERENCES ========
special_requests: Optional[str] = FormField(
None,
title="Special Requests or Comments",
input_type="textarea",
placeholder="Any special requests, dietary restrictions, accessibility needs, or additional comments...",
help_text="Let us know about any special accommodations you need",
icon="chat-dots",
max_length=1000
)
terms_accepted: bool = FormField(
False,
title="I accept the Terms and Conditions",
input_type="checkbox",
help_text="You must accept the terms to proceed",
icon="check-square"
)
@field_validator('terms_accepted')
@classmethod
def validate_terms(cls, v):
if not v:
raise ValueError('You must accept the terms and conditions')
return v
{
"$defs": {
"Country": {
"description": "Countries for selection.",
"enum": [
"United States",
"Canada",
"United Kingdom",
"Australia",
"Germany",
"France",
"Japan"
],
"title": "Country",
"type": "string"
},
"EmergencyContactModel": {
"description": "Emergency contact information model.",
"properties": {
"name": {
"autofocus": false,
"description": "Full name of emergency contact",
"disabled": false,
"help_text": "Full name of emergency contact",
"icon": "person-badge",
"input_type": "text",
"maxLength": 100,
"minLength": 2,
"placeholder": "John Doe",
"readonly": false,
"title": "Contact Name",
"type": "string"
},
"relationship": {
"autofocus": false,
"description": "Your relationship to this person",
"disabled": false,
"help_text": "Your relationship to this person",
"icon": "people",
"input_type": "select",
"options": [
{
"label": "\ud83d\udc91 Spouse/Partner",
"value": "spouse"
},
{
"label": "\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66 Parent",
"value": "parent"
},
{
"label": "\ud83d\udc76 Child",
"value": "child"
},
{
"label": "\ud83d\udc6b Sibling",
"value": "sibling"
},
{
"label": "\ud83d\udc65 Friend",
"value": "friend"
},
{
"label": "\ud83d\udcbc Colleague",
"value": "colleague"
},
{
"label": "\ud83e\udd1d Other",
"value": "other"
}
],
"readonly": false,
"title": "Relationship",
"type": "string"
},
"phone": {
"autofocus": false,
"description": "Primary phone number for this contact",
"disabled": false,
"help_text": "Primary phone number for this contact",
"icon": "telephone",
"input_type": "tel",
"maxLength": 20,
"minLength": 10,
"placeholder": "+1 (555) 123-4567",
"readonly": false,
"title": "Phone Number",
"type": "string"
},
"email": {
"anyOf": [
{
"format": "email",
"type": "string"
},
{
"type": "null"
}
],
"autofocus": false,
"default": null,
"description": "Email address (optional)",
"disabled": false,
"help_text": "Email address (optional)",
"icon": "envelope",
"input_type": "email",
"placeholder": "contact@example.com",
"readonly": false,
"title": "Email Address"
},
"available_24_7": {
"autofocus": false,
"default": false,
"description": "Can this person be contacted at any time?",
"disabled": false,
"help_text": "Can this person be contacted at any time?",
"icon": "clock",
"input_type": "checkbox",
"readonly": false,
"title": "Available 24/7",
"type": "boolean"
}
},
"required": [
"name",
"relationship",
"phone"
],
"title": "EmergencyContactModel",
"type": "object"
},
"PetModel": {
"description": "Enhanced pet information model showcasing various input types.",
"properties": {
"name": {
"autofocus": false,
"description": "The name of your pet",
"disabled": false,
"help_text": "The name of your pet",
"icon": "heart",
"input_type": "text",
"maxLength": 50,
"minLength": 1,
"placeholder": "Enter your pet's name",
"readonly": false,
"title": "Pet's Name",
"type": "string"
},
"species": {
"autofocus": false,
"description": "What type of animal is your pet?",
"disabled": false,
"help_text": "What type of animal is your pet?",
"icon": "collection",
"input_type": "select",
"options": [
{
"label": "Dog \ud83d\udc15",
"value": "Dog"
},
{
"label": "Cat \ud83d\udc31",
"value": "Cat"
},
{
"label": "Bird \ud83d\udc26",
"value": "Bird"
},
{
"label": "Fish \ud83d\udc20",
"value": "Fish"
},
{
"label": "Rabbit \ud83d\udc30",
"value": "Rabbit"
},
{
"label": "Hamster \ud83d\udc39",
"value": "Hamster"
},
{
"label": "Reptile \ud83e\udd8e",
"value": "Reptile"
},
{
"label": "Other \ud83d\udc3e",
"value": "Other"
}
],
"readonly": false,
"title": "Species",
"type": "string"
},
"age": {
"anyOf": [
{
"maximum": 50,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"autofocus": false,
"default": null,
"description": "How old is your pet? (optional)",
"disabled": false,
"help_text": "How old is your pet? (optional)",
"icon": "calendar",
"input_type": "number",
"placeholder": "Pet's age in years",
"readonly": false,
"title": "Age"
},
"weight": {
"anyOf": [
{
"maximum": 500.0,
"minimum": 0.01,
"type": "number"
},
{
"type": "null"
}
],
"autofocus": false,
"default": null,
"description": "Weight in pounds (optional - enter 0.01 for tiny pets like birds)",
"disabled": false,
"help_text": "Weight in pounds (optional - enter 0.01 for tiny pets like birds)",
"icon": "speedometer2",
"input_type": "number",
"placeholder": "Pet's weight",
"readonly": false,
"title": "Weight (lbs)"
},
"is_vaccinated": {
"autofocus": false,
"default": false,
"description": "Is your pet up to date with vaccinations?",
"disabled": false,
"help_text": "Is your pet up to date with vaccinations?",
"icon": "shield-check",
"input_type": "checkbox",
"readonly": false,
"title": "Vaccinated",
"type": "boolean"
},
"microchipped": {
"autofocus": false,
"default": false,
"description": "Does your pet have a microchip?",
"disabled": false,
"help_text": "Does your pet have a microchip?",
"icon": "cpu",
"input_type": "checkbox",
"readonly": false,
"title": "Microchipped",
"type": "boolean"
},
"breed": {
"anyOf": [
{
"maxLength": 100,
"type": "string"
},
{
"type": "null"
}
],
"autofocus": false,
"default": null,
"description": "Specific breed of your pet (optional)",
"disabled": false,
"help_text": "Specific breed of your pet (optional)",
"icon": "award",
"input_type": "text",
"placeholder": "e.g., Golden Retriever, Persian Cat",
"readonly": false,
"title": "Breed"
},
"color": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"autofocus": false,
"default": null,
"description": "Primary color of your pet (optional)",
"disabled": false,
"help_text": "Primary color of your pet (optional)",
"icon": "palette",
"input_type": "color",
"readonly": false,
"title": "Primary Color"
},
"last_vet_visit": {
"anyOf": [
{
"format": "date",
"type": "string"
},
{
"type": "null"
}
],
"autofocus": false,
"default": null,
"description": "When was the last veterinary checkup? (optional)",
"disabled": false,
"help_text": "When was the last veterinary checkup? (optional)",
"icon": "calendar-date",
"input_type": "date",
"readonly": false,
"title": "Last Vet Visit"
},
"special_needs": {
"anyOf": [
{
"maxLength": 500,
"type": "string"
},
{
"type": "null"
}
],
"autofocus": false,
"default": null,
"description": "Describe any special care requirements (optional)",
"disabled": false,
"help_text": "Describe any special care requirements (optional)",
"icon": "heart-pulse",
"input_type": "textarea",
"placeholder": "Any special care requirements, medications, allergies, etc.",
"readonly": false,
"title": "Special Needs"
}
},
"required": [
"name",
"species"
],
"title": "PetModel",
"type": "object"
}
},
"description": "Complete showcase form demonstrating all Pydantic SchemaForms capabilities:\n- All input types (text, email, number, select, checkbox, date, color, etc.)\n- Collapsible list layouts with cards\n- Dynamic titles and field validation\n- Icons and help text\n- Multiple layout options",
"properties": {
"first_name": {
"autofocus": false,
"description": "Your given name as it appears on official documents",
"disabled": false,
"help_text": "Your given name as it appears on official documents",
"icon": "person",
"input_type": "text",
"maxLength": 50,
"minLength": 2,
"placeholder": "Enter your first name",
"readonly": false,
"title": "First Name",
"type": "string"
},
"last_name": {
"autofocus": false,
"description": "Your family name or surname",
"disabled": false,
"help_text": "Your family name or surname",
"icon": "person",
"input_type": "text",
"maxLength": 50,
"minLength": 2,
"placeholder": "Enter your last name",
"readonly": false,
"title": "Last Name",
"type": "string"
},
"email": {
"autofocus": false,
"description": "We'll use this to contact you about your registration",
"disabled": false,
"format": "email",
"help_text": "We'll use this to contact you about your registration",
"icon": "envelope",
"input_type": "email",
"placeholder": "your.email@example.com",
"readonly": false,
"title": "Email Address",
"type": "string"
},
"phone": {
"anyOf": [
{
"pattern": "^[\\+]?[1-9][\\d]{0,15}$",
"type": "string"
},
{
"type": "null"
}
],
"autofocus": false,
"default": null,
"description": "Include country code for international numbers",
"disabled": false,
"help_text": "Include country code for international numbers",
"icon": "telephone",
"input_type": "tel",
"placeholder": "+1 (555) 123-4567",
"readonly": false,
"title": "Phone Number"
},
"birth_date": {
"anyOf": [
{
"format": "date",
"type": "string"
},
{
"type": "null"
}
],
"autofocus": false,
"default": null,
"description": "Used to verify age requirements (optional)",
"disabled": false,
"help_text": "Used to verify age requirements (optional)",
"icon": "calendar-date",
"input_type": "date",
"readonly": false,
"title": "Date of Birth"
},
"age": {
"anyOf": [
{
"maximum": 120,
"minimum": 13,
"type": "integer"
},
{
"type": "null"
}
],
"autofocus": false,
"default": null,
"description": "Your current age in years",
"disabled": false,
"help_text": "Your current age in years",
"icon": "hash",
"input_type": "number",
"placeholder": "25",
"readonly": false,
"title": "Age"
},
"favorite_color": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"autofocus": false,
"default": "#3498db",
"description": "Pick your favorite color",
"disabled": false,
"help_text": "Pick your favorite color",
"icon": "palette",
"input_type": "color",
"readonly": false,
"title": "Favorite Color"
},
"experience_level": {
"autofocus": false,
"description": "Select your experience level",
"disabled": false,
"help_text": "Select your experience level",
"icon": "trophy",
"input_type": "select",
"options": [
{
"label": "\ud83c\udf31 Beginner (0-1 years)",
"value": "beginner"
},
{
"label": "\ud83d\ude80 Intermediate (2-5 years)",
"value": "intermediate"
},
{
"label": "\ud83c\udfaf Advanced (5-10 years)",
"value": "advanced"
},
{
"label": "\ud83c\udfc6 Expert (10+ years)",
"value": "expert"
}
],
"readonly": false,
"title": "Experience Level",
"type": "string"
},
"newsletter_subscription": {
"autofocus": false,
"default": true,
"description": "Receive updates and news about our services",
"disabled": false,
"help_text": "Receive updates and news about our services",
"icon": "mailbox",
"input_type": "checkbox",
"readonly": false,
"title": "Subscribe to Newsletter",
"type": "boolean"
},
"rating": {
"anyOf": [
{
"maximum": 10,
"minimum": 1,
"type": "integer"
},
{
"type": "null"
}
],
"autofocus": false,
"default": null,
"description": "How interested are you in our services?",
"disabled": false,
"help_text": "How interested are you in our services?",
"icon": "star",
"input_type": "range",
"readonly": false,
"title": "Rate Your Interest (1-10)"
},
"address": {
"anyOf": [
{
"maxLength": 500,
"type": "string"
},
{
"type": "null"
}
],
"autofocus": false,
"default": null,
"description": "Your full mailing address (optional)",
"disabled": false,
"help_text": "Your full mailing address (optional)",
"icon": "house",
"input_type": "textarea",
"placeholder": "123 Main Street\nApt 4B",
"readonly": false,
"title": "Street Address"
},
"country": {
"anyOf": [
{
"$ref": "#/$defs/Country"
},
{
"type": "null"
}
],
"autofocus": false,
"default": null,
"description": "Select your country of residence",
"disabled": false,
"help_text": "Select your country of residence",
"icon": "globe",
"input_type": "select",
"options": [
{
"label": "\ud83c\uddfa\ud83c\uddf8 United States",
"value": "US"
},
{
"label": "\ud83c\udde8\ud83c\udde6 Canada",
"value": "CA"
},
{
"label": "\ud83c\uddec\ud83c\udde7 United Kingdom",
"value": "UK"
},
{
"label": "\ud83c\udde9\ud83c\uddea Germany",
"value": "DE"
},
{
"label": "\ud83c\uddeb\ud83c\uddf7 France",
"value": "FR"
},
{
"label": "\ud83c\udde6\ud83c\uddfa Australia",
"value": "AU"
},
{
"label": "\ud83c\udf0d Other",
"value": "OTHER"
}
],
"readonly": false,
"title": "Country"
},
"pets": {
"add_button_text": "\ud83d\udc3e Add Another Pet",
"autofocus": false,
"collapsible_items": true,
"default_factory": "builtins.list",
"description": "Tell us about each of your beloved pets",
"disabled": false,
"help_text": "Tell us about each of your beloved pets",
"icon": "heart-fill",
"input_type": "model_list",
"item_title_template": "\ud83d\udc3e {name} the {species}",
"items": {
"$ref": "#/$defs/PetModel"
},
"items_expanded": false,
"maxItems": 5,
"minItems": 0,
"model_class": "src.models.PetModel",
"readonly": false,
"remove_button_text": "Remove Pet",
"section_design": {
"collapsed": false,
"collapsible": true,
"icon": "bi bi-heart-fill",
"section_description": "Register each of your pets with detailed information for our records",
"section_title": "Pet Registry"
},
"title": "Your Pets",
"type": "array"
},
"emergency_contacts": {
"add_button_text": "\u2795 Add Emergency Contact",
"autofocus": false,
"collapsible_items": true,
"default_factory": "builtins.list",
"description": "Add people we can contact in case of emergency",
"disabled": false,
"help_text": "Add people we can contact in case of emergency",
"icon": "person-exclamation",
"input_type": "model_list",
"item_title_template": "\ud83d\udcde {name} ({relationship})",
"items": {
"$ref": "#/$defs/EmergencyContactModel"
},
"items_expanded": true,
"maxItems": 3,
"minItems": 1,
"model_class": "src.models.EmergencyContactModel",
"readonly": false,
"remove_button_text": "Remove Contact",
"section_design": {
"collapsed": false,
"collapsible": false,
"icon": "bi bi-shield-exclamation",
"section_description": "At least one emergency contact is required",
"section_title": "Emergency Contacts"
},
"title": "Emergency Contacts",
"type": "array"
},
"special_requests": {
"anyOf": [
{
"maxLength": 1000,
"type": "string"
},
{
"type": "null"
}
],
"autofocus": false,
"default": null,
"description": "Let us know about any special accommodations you need",
"disabled": false,
"help_text": "Let us know about any special accommodations you need",
"icon": "chat-dots",
"input_type": "textarea",
"placeholder": "Any special requests, dietary restrictions, accessibility needs, or additional comments...",
"readonly": false,
"title": "Special Requests or Comments"
},
"terms_accepted": {
"autofocus": false,
"default": false,
"description": "You must accept the terms to proceed",
"disabled": false,
"help_text": "You must accept the terms to proceed",
"icon": "check-square",
"input_type": "checkbox",
"readonly": false,
"title": "I accept the Terms and Conditions",
"type": "boolean"
}
},
"required": [
"first_name",
"last_name",
"email",
"experience_level",
"pets",
"emergency_contacts"
],
"title": "CompleteShowcaseForm",
"type": "object"
}{
"first_name": {
"required": true,
"type": "string",
"minLength": 2,
"maxLength": 50
},
"last_name": {
"required": true,
"type": "string",
"minLength": 2,
"maxLength": 50
},
"email": {
"required": true,
"type": "string",
"format": "email"
},
"phone": {
"required": false
},
"birth_date": {
"required": false
},
"age": {
"required": false
},
"favorite_color": {
"required": false
},
"experience_level": {
"required": true,
"type": "string"
},
"newsletter_subscription": {
"required": false,
"type": "boolean"
},
"rating": {
"required": false
},
"address": {
"required": false
},
"country": {
"required": false
},
"pets": {
"required": true,
"type": "array"
},
"emergency_contacts": {
"required": true,
"type": "array"
},
"special_requests": {
"required": false
},
"terms_accepted": {
"required": false,
"type": "boolean"
}
}{
"errors": {},
"data": {
"first_name": "Alex",
"last_name": "Johnson",
"email": "alex.johnson@example.com",
"phone": "+1 (555) 234-5678",
"birth_date": "1995-06-15",
"age": 28,
"favorite_color": "#3498db",
"experience_level": "intermediate",
"newsletter_subscription": true,
"rating": 8,
"address": "456 Oak Avenue\nUnit 12\nDowntown District",
"country": "US",
"pets": [
{
"name": "Buddy",
"species": "dog",
"breed": "Labrador",
"age": 4,
"weight": 70.0,
"microchipped": true,
"vaccination_date": "2024-03-10",
"special_needs": "Needs hip medication twice daily"
},
{
"name": "Whiskers",
"species": "cat",
"breed": "Maine Coon",
"age": 5,
"weight": 12.5,
"microchipped": true,
"vaccination_date": "2024-04-05",
"special_needs": "Requires grain-free diet"
}
],
"emergency_contacts": [
{
"name": "Emma Johnson",
"relationship": "spouse",
"phone": "+1 (555) 345-6789",
"email": "emma.johnson@example.com",
"available_24_7": true
},
{
"name": "Robert Johnson",
"relationship": "parent",
"phone": "+1 (555) 456-7890",
"email": "robert.johnson@example.com",
"available_24_7": false
}
],
"special_requests": "Please contact me via email for all communications. I work night shifts and may not be available by phone during the day.",
"terms_accepted": true
}
}