Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
22e6b74c4f | |||
4de835474b | |||
024d8af40d | |||
808b74fa17 | |||
202881ef1a | |||
7de3d451ad | |||
f0e0430016 | |||
873579fc97 | |||
d321db363d | |||
73c1874e3f | |||
1aa06398a0 | |||
99b23236a1 | |||
d1e7e5447c | |||
4f22a98b78 |
17
changelog.md
17
changelog.md
@ -1,5 +1,22 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-06-22 - 1.9.0 - feat(form-inputs)
|
||||||
|
Improve form input consistency and auto spacing across inputs and buttons
|
||||||
|
|
||||||
|
- Add an 'insideForm' property to dees-button for auto-detection and proper margin adjustment in forms.
|
||||||
|
- Update dees-input-radio to include a 'name' property so that radio buttons in the same group are mutually exclusive.
|
||||||
|
- Enhance dees-form to group radio inputs properly when collecting form data.
|
||||||
|
- Revise readme.hints.md and readme.plan.md to document changes and provide guidance for dees-input-radio.
|
||||||
|
- Update demos for dees-button and dees-form to showcase correct spacing in vertical and horizontal layouts.
|
||||||
|
|
||||||
|
## 2025-06-20 - 1.8.20 - fix(deps)
|
||||||
|
Update dependency versions: bump @design.estate/dees-domtools from ^2.1.1 to ^2.3.3, @design.estate/dees-element from ^2.0.42 to ^2.0.44, lucide from ^0.515.0 to ^0.518.0, and @git.zone/tsbundle from ^2.0.15 to ^2.4.0
|
||||||
|
|
||||||
|
- Upgrade @design.estate/dees-domtools from ^2.1.1 to ^2.3.3
|
||||||
|
- Upgrade @design.estate/dees-element from ^2.0.42 to ^2.0.44
|
||||||
|
- Upgrade lucide from ^0.515.0 to ^0.518.0
|
||||||
|
- Upgrade @git.zone/tsbundle from ^2.0.15 to ^2.4.0
|
||||||
|
|
||||||
## 2025-06-10 - 1.8.1 - fix(dees-statsgrid)
|
## 2025-06-10 - 1.8.1 - fix(dees-statsgrid)
|
||||||
Adjust stats grid styling for better alignment and improved visualizations in gauge and trend tiles.
|
Adjust stats grid styling for better alignment and improved visualizations in gauge and trend tiles.
|
||||||
|
|
||||||
|
10
package.json
10
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@design.estate/dees-catalog",
|
"name": "@design.estate/dees-catalog",
|
||||||
"version": "1.8.13",
|
"version": "1.9.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.",
|
"description": "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.",
|
||||||
"main": "dist_ts_web/index.js",
|
"main": "dist_ts_web/index.js",
|
||||||
@ -15,8 +15,8 @@
|
|||||||
"author": "Lossless GmbH",
|
"author": "Lossless GmbH",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@design.estate/dees-domtools": "^2.1.1",
|
"@design.estate/dees-domtools": "^2.3.3",
|
||||||
"@design.estate/dees-element": "^2.0.42",
|
"@design.estate/dees-element": "^2.0.44",
|
||||||
"@design.estate/dees-wcctools": "^1.0.98",
|
"@design.estate/dees-wcctools": "^1.0.98",
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
||||||
@ -30,7 +30,7 @@
|
|||||||
"apexcharts": "^4.7.0",
|
"apexcharts": "^4.7.0",
|
||||||
"highlight.js": "11.11.1",
|
"highlight.js": "11.11.1",
|
||||||
"ibantools": "^4.5.1",
|
"ibantools": "^4.5.1",
|
||||||
"lucide": "^0.515.0",
|
"lucide": "^0.518.0",
|
||||||
"monaco-editor": "^0.52.2",
|
"monaco-editor": "^0.52.2",
|
||||||
"pdfjs-dist": "^4.10.38",
|
"pdfjs-dist": "^4.10.38",
|
||||||
"xterm": "^5.3.0",
|
"xterm": "^5.3.0",
|
||||||
@ -38,7 +38,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^2.6.4",
|
"@git.zone/tsbuild": "^2.6.4",
|
||||||
"@git.zone/tsbundle": "^2.0.15",
|
"@git.zone/tsbundle": "^2.4.0",
|
||||||
"@git.zone/tstest": "^2.3.1",
|
"@git.zone/tstest": "^2.3.1",
|
||||||
"@git.zone/tswatch": "^2.0.37",
|
"@git.zone/tswatch": "^2.0.37",
|
||||||
"@push.rocks/projectinfo": "^5.0.2",
|
"@push.rocks/projectinfo": "^5.0.2",
|
||||||
|
860
pnpm-lock.yaml
generated
860
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -58,4 +58,22 @@
|
|||||||
- View mode selectors
|
- View mode selectors
|
||||||
- Action grouping
|
- Action grouping
|
||||||
- Navigation options
|
- Navigation options
|
||||||
- Filter controls
|
- Filter controls
|
||||||
|
|
||||||
|
## Form Components
|
||||||
|
|
||||||
|
### dees-input-radio
|
||||||
|
- Radio button component with proper group behavior
|
||||||
|
- Properties:
|
||||||
|
- `name`: Group name for mutually exclusive selection
|
||||||
|
- `key`: Unique identifier for the radio option
|
||||||
|
- `value`: Boolean indicating selection state
|
||||||
|
- `label`: Display label
|
||||||
|
- Features:
|
||||||
|
- Automatic group management (radios with same name are mutually exclusive)
|
||||||
|
- Cannot be deselected by clicking (proper radio behavior)
|
||||||
|
- Form integration: Radio groups are collected by name, value is the selected radio's key
|
||||||
|
- Works both inside and outside forms
|
||||||
|
- Supports disabled state
|
||||||
|
- Fixed: Radio buttons now properly deselect others in the group on first click
|
||||||
|
- Note: When using in forms, set both `name` (for grouping) and `key` (for the value)
|
324
readme.plan.md
324
readme.plan.md
@ -1,213 +1,159 @@
|
|||||||
# Input Component Unification Plan
|
# Command: cat ~/.claude/CLAUDE.md
|
||||||
|
|
||||||
Command to reread guidelines: `cat /home/philkunz/.claude/CLAUDE.md`
|
# Margin Harmonization Plan for @design.estate/dees-catalog
|
||||||
|
|
||||||
## Problem Summary
|
## Implementation Status: Phase 1 Complete ✅
|
||||||
|
|
||||||
The dees-input components have inconsistent margin behavior causing vertical alignment issues in horizontal flexbox layouts:
|
Phase 1 has been successfully implemented. Buttons now auto-detect form context and apply appropriate spacing.
|
||||||
|
|
||||||
- **dees-input-text**: 8px top, 24px bottom margin
|
## Objective
|
||||||
- **dees-input-dropdown**: 0px top, 24px bottom margin
|
Implement consistent spacing across all form elements using auto-detection and CSS-based approach for buttons while maintaining the existing input spacing system.
|
||||||
- **dees-input-checkbox/radio**: 20px top, 20px bottom margin
|
|
||||||
- Different components use different label implementations (some use dees-label, others have built-in labels)
|
|
||||||
|
|
||||||
## Proposed Solution
|
## Current Issues
|
||||||
|
- Buttons have no default margins (inconsistent with inputs)
|
||||||
|
- Manual spacing required when mixing buttons with inputs in forms
|
||||||
|
- No unified spacing constants across components
|
||||||
|
|
||||||
### 1. Standardize Margin System
|
## Implementation Plan (Improved)
|
||||||
|
|
||||||
Create a unified margin approach for all input components:
|
### Phase 1: Add Auto-Detected Form Spacing to Buttons ✅
|
||||||
|
- [x] Update `dees-button.ts`
|
||||||
|
- Add `insideForm` property (boolean, reflected) with auto-detection
|
||||||
|
- Add connectedCallback for automatic form detection:
|
||||||
|
```typescript
|
||||||
|
@property({ type: Boolean, reflect: true })
|
||||||
|
public insideForm: boolean = false;
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
super.connectedCallback();
|
||||||
|
// Auto-detect if inside a form
|
||||||
|
if (!this.insideForm && this.closest('dees-form')) {
|
||||||
|
this.insideForm = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- Add margin styles for both vertical and horizontal form contexts:
|
||||||
|
```css
|
||||||
|
/* Default vertical form layout */
|
||||||
|
:host([inside-form]) {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: var(--dees-input-vertical-gap);
|
||||||
|
}
|
||||||
|
:host([inside-form]:last-child) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Horizontal form layout - auto-detected via parent */
|
||||||
|
:host([inside-form]):host-context(dees-form[horizontal-layout]) {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: var(--dees-input-horizontal-gap);
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
:host([inside-form]):host-context(dees-form[horizontal-layout]):last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- [x] Update `dees-form-submit.ts`
|
||||||
|
- Remove need for manual attribute setting (auto-detection handles it)
|
||||||
|
- Verify integration works correctly
|
||||||
|
|
||||||
```css
|
### Phase 2: Create Unified Spacing Constants (Optional Enhancement)
|
||||||
/* Default vertical stacking mode (for forms) */
|
- [ ] Add CSS custom properties to `dees-input-base.ts`:
|
||||||
:host {
|
```css
|
||||||
margin: 0;
|
:root {
|
||||||
margin-bottom: 16px; /* Reduced from 24px for better density */
|
--dees-form-gap: 16px;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- [ ] Update existing `--dees-input-vertical-gap` to use `--dees-form-gap`
|
||||||
|
- [ ] Update button margins to use the same variable
|
||||||
|
|
||||||
|
### Phase 3: Testing and Documentation
|
||||||
|
- [ ] Test mixed forms with inputs and buttons (both vertical and horizontal)
|
||||||
|
- [ ] Verify last-child margin removal works
|
||||||
|
- [ ] Test auto-detection behavior
|
||||||
|
- [ ] Update demos:
|
||||||
|
- `dees-form.demo.ts` - show buttons auto-detecting form context
|
||||||
|
- `dees-button.demo.ts` - add form context example with manual override
|
||||||
|
- [ ] Document the `insideForm` property and auto-detection in readme.md
|
||||||
|
|
||||||
|
### Phase 4: Clean Up
|
||||||
|
- [ ] Ensure all spacing uses consistent values (16px)
|
||||||
|
- [ ] Verify no breaking changes
|
||||||
|
- [ ] Update changelog.md
|
||||||
|
|
||||||
|
## Technical Details
|
||||||
|
|
||||||
|
### Button Form Integration
|
||||||
|
```typescript
|
||||||
|
// In dees-button.ts
|
||||||
|
@property({ type: Boolean, reflect: true })
|
||||||
|
public insideForm: boolean = false;
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
super.connectedCallback();
|
||||||
|
// Auto-detect if inside a form
|
||||||
|
if (!this.insideForm && this.closest('dees-form')) {
|
||||||
|
this.insideForm = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Last child in container should have no bottom margin */
|
// CSS addition
|
||||||
:host(:last-child) {
|
/* Default vertical form layout */
|
||||||
|
:host([inside-form]) {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: var(--dees-input-vertical-gap);
|
||||||
|
}
|
||||||
|
:host([inside-form]:last-child) {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Horizontal layout mode - activated by parent context or attribute */
|
/* Horizontal form layout - auto-detected via parent */
|
||||||
:host([horizontal-layout]) {
|
:host([inside-form]):host-context(dees-form[horizontal-layout]) {
|
||||||
margin: 0;
|
display: inline-block;
|
||||||
margin-right: 16px;
|
margin-right: var(--dees-input-horizontal-gap);
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
:host([inside-form]):host-context(dees-form[horizontal-layout]):last-child {
|
||||||
:host([horizontal-layout]:last-child) {
|
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Unified Label Architecture
|
### Usage Example
|
||||||
|
```html
|
||||||
|
<!-- Automatic detection - buttons get form spacing automatically -->
|
||||||
|
<dees-form>
|
||||||
|
<dees-input-text label="Name"></dees-input-text>
|
||||||
|
<dees-input-email label="Email"></dees-input-email>
|
||||||
|
<dees-button>Save Draft</dees-button> <!-- Auto-detects form context -->
|
||||||
|
<dees-form-submit>Submit</dees-form-submit> <!-- Auto-detects form context -->
|
||||||
|
</dees-form>
|
||||||
|
|
||||||
All input components should use the `dees-label` component for consistency:
|
<!-- Manual override if needed -->
|
||||||
|
<div class="custom-container">
|
||||||
|
<dees-button inside-form="true">Standalone button with form spacing</dees-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
- Move label rendering from built-in implementations to `dees-label` usage
|
<!-- Horizontal form - spacing adjusts automatically -->
|
||||||
- Add a `labelPosition` property to all inputs: `'top' | 'left' | 'right' | 'none'`
|
<dees-form horizontal-layout>
|
||||||
- Default to 'top' for text/dropdown, 'right' for checkbox/radio
|
<dees-input-text label="Search"></dees-input-text>
|
||||||
|
<dees-button>Search</dees-button> <!-- Gets right margin instead of bottom -->
|
||||||
### 3. Layout Mode Support
|
</dees-form>
|
||||||
|
|
||||||
Add a `layoutMode` property to all input components:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
@property({ type: String })
|
|
||||||
public layoutMode: 'vertical' | 'horizontal' | 'auto' = 'auto';
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- `vertical`: Traditional form layout (label on top)
|
## Success Criteria
|
||||||
- `horizontal`: Inline layout (label position configurable)
|
1. Buttons automatically detect form context and apply appropriate spacing
|
||||||
- `auto`: Detect from parent context
|
2. Manual override available via `insideForm` property
|
||||||
|
3. Supports both vertical and horizontal form layouts
|
||||||
|
4. No breaking changes for existing implementations
|
||||||
|
5. Consistent 16px spacing between all form elements
|
||||||
|
6. Clear documentation and examples
|
||||||
|
7. All tests pass
|
||||||
|
|
||||||
### 4. Implementation Steps
|
## Benefits of This Approach
|
||||||
|
- **Automatic behavior** - Works out of the box, no manual attributes needed
|
||||||
1. **Create base input class** (`DeesInputBase`):
|
- **Consistent with inputs** - Follows the same pattern as existing form elements
|
||||||
- Common margin styles
|
- **Layout aware** - Automatically adapts to vertical/horizontal forms
|
||||||
- Layout mode detection
|
- **Minimal code** - Simple CSS-based solution with light JS detection
|
||||||
- Label position handling
|
- **Backward compatible** - Existing code continues to work
|
||||||
- Shared properties (key, required, disabled, value)
|
- **Override capability** - Manual control when needed
|
||||||
|
- **Uses existing variables** - Leverages `--dees-input-vertical-gap` and `--dees-input-horizontal-gap`
|
||||||
2. **Update dees-input-text**:
|
|
||||||
- Extend from DeesInputBase
|
|
||||||
- Remove hardcoded margins
|
|
||||||
- Keep using dees-label component
|
|
||||||
|
|
||||||
3. **Update dees-input-dropdown**:
|
|
||||||
- Extend from DeesInputBase
|
|
||||||
- Remove hardcoded margins
|
|
||||||
- Switch from built-in label to dees-label
|
|
||||||
|
|
||||||
4. **Update dees-input-checkbox**:
|
|
||||||
- Extend from DeesInputBase
|
|
||||||
- Remove hardcoded margins
|
|
||||||
- Add support for label position (keep default as 'right')
|
|
||||||
- Switch to dees-label component
|
|
||||||
|
|
||||||
5. **Update dees-input-radio**:
|
|
||||||
- Same as checkbox
|
|
||||||
|
|
||||||
6. **Update dees-form**:
|
|
||||||
- Add property to control child input layout mode
|
|
||||||
- Ensure proper spacing context
|
|
||||||
|
|
||||||
### 5. CSS Variable System
|
|
||||||
|
|
||||||
Introduce CSS variables for consistent spacing:
|
|
||||||
|
|
||||||
```css
|
|
||||||
:host {
|
|
||||||
--dees-input-spacing-unit: 8px;
|
|
||||||
--dees-input-vertical-gap: calc(var(--dees-input-spacing-unit) * 2); /* 16px */
|
|
||||||
--dees-input-horizontal-gap: calc(var(--dees-input-spacing-unit) * 2); /* 16px */
|
|
||||||
--dees-input-label-gap: var(--dees-input-spacing-unit); /* 8px */
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Backward Compatibility
|
|
||||||
|
|
||||||
- Keep existing properties and methods
|
|
||||||
- Add deprecation notices for properties that will be removed
|
|
||||||
- Provide migration guide in documentation
|
|
||||||
|
|
||||||
### 7. Testing Requirements
|
|
||||||
|
|
||||||
- Test all inputs in vertical form layouts
|
|
||||||
- Test all inputs in horizontal flexbox containers
|
|
||||||
- Test mixed input types in same container
|
|
||||||
- Test with and without labels
|
|
||||||
- Test theme switching (light/dark)
|
|
||||||
- Test responsive behavior
|
|
||||||
|
|
||||||
## Expected Outcome
|
|
||||||
|
|
||||||
- All input components will align properly in horizontal layouts
|
|
||||||
- Consistent spacing in vertical forms
|
|
||||||
- Unified label handling across all inputs
|
|
||||||
- Better developer experience with predictable behavior
|
|
||||||
- Maintained backward compatibility
|
|
||||||
|
|
||||||
## Timeline
|
|
||||||
|
|
||||||
1. Phase 1: Create DeesInputBase class and update dees-input-text ✅
|
|
||||||
2. Phase 2: Update remaining input components ✅
|
|
||||||
3. Phase 3: Update documentation and examples ✅
|
|
||||||
4. Phase 4: Testing and refinement ✅
|
|
||||||
|
|
||||||
## Implementation Status
|
|
||||||
|
|
||||||
### Completed:
|
|
||||||
|
|
||||||
1. **Created DeesInputBase class** (`dees-input-base.ts`):
|
|
||||||
- Generic base class with unified margin system
|
|
||||||
- Layout mode support (vertical/horizontal/auto)
|
|
||||||
- Label position control
|
|
||||||
- Common properties and methods
|
|
||||||
- CSS variables for consistent spacing
|
|
||||||
|
|
||||||
2. **Updated all input components**:
|
|
||||||
- `dees-input-text`: Now extends DeesInputBase, margins removed
|
|
||||||
- `dees-input-dropdown`: Now extends DeesInputBase, uses dees-label
|
|
||||||
- `dees-input-checkbox`: Now extends DeesInputBase, uses dees-label (default label position: right)
|
|
||||||
- `dees-input-radio`: Now extends DeesInputBase, uses dees-label (default label position: right)
|
|
||||||
- `dees-input-phone`: Now extends DeesInputBase with phone formatting functionality
|
|
||||||
- `dees-input-iban`: Now extends DeesInputBase with IBAN validation
|
|
||||||
- `dees-input-quantityselector`: Now extends DeesInputBase
|
|
||||||
- `dees-input-multitoggle`: Now extends DeesInputBase with value property for forms
|
|
||||||
- `dees-input-typelist`: Now extends DeesInputBase
|
|
||||||
- `dees-input-fileupload`: Now extends DeesInputBase, uses dees-label
|
|
||||||
|
|
||||||
3. **Updated dees-form**:
|
|
||||||
- Added `horizontal-layout` property
|
|
||||||
- Auto-detection of layout mode for child inputs
|
|
||||||
- Added dropdown to form input types
|
|
||||||
|
|
||||||
4. **Fixed TypeScript errors**:
|
|
||||||
- Added value property to dropdown for form compatibility
|
|
||||||
- Fixed changeSubject typing
|
|
||||||
- Updated form value type to include dropdown options
|
|
||||||
- Fixed firstUpdated method signatures (phone, iban, fileupload)
|
|
||||||
- Fixed CSS-in-JS errors in quantityselector (removed dynamic references)
|
|
||||||
- Added value property to multitoggle for form compatibility
|
|
||||||
- Removed duplicate properties in fileupload (label, key, disabled, required)
|
|
||||||
|
|
||||||
### Result:
|
|
||||||
|
|
||||||
All input components now have:
|
|
||||||
- Unified 16px bottom margin in vertical layouts
|
|
||||||
- 16px right margin in horizontal layouts
|
|
||||||
- No margin on last child
|
|
||||||
- Consistent label handling via dees-label
|
|
||||||
- Flexible layout modes
|
|
||||||
- Better alignment in flexbox containers
|
|
||||||
|
|
||||||
## Demo Improvements
|
|
||||||
|
|
||||||
### Created external demo files:
|
|
||||||
1. **dees-input-text.demo.ts**: Comprehensive demos showing:
|
|
||||||
- Basic text inputs with descriptions
|
|
||||||
- Horizontal layout examples
|
|
||||||
- Label position variations
|
|
||||||
- Validation states
|
|
||||||
- Password input features
|
|
||||||
|
|
||||||
2. **dees-input-checkbox.demo.ts**: Interactive demos featuring:
|
|
||||||
- Basic checkbox usage
|
|
||||||
- Horizontal layout groups
|
|
||||||
- Feature selection with batch operations
|
|
||||||
- Real-world examples
|
|
||||||
|
|
||||||
3. **dees-input-radio.demo.ts**: Radio button demos including:
|
|
||||||
- Radio groups with proper behavior
|
|
||||||
- Horizontal yes/no questions
|
|
||||||
- Survey-style layouts
|
|
||||||
- Settings examples
|
|
||||||
|
|
||||||
### Updated existing demos:
|
|
||||||
1. **dees-input-dropdown.demo.ts**: Enhanced with dees-demowrapper and comprehensive examples
|
|
||||||
2. **dees-form.demo.ts**: Added horizontal form layout examples and advanced form features
|
|
||||||
3. **dees-simple-appdash.demo.ts**: Enhanced settings view with horizontal forms and radio groups
|
|
||||||
|
|
||||||
All demos now use the `dees-demowrapper` component for consistency and include proper styling for light/dark themes.
|
|
@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@design.estate/dees-catalog',
|
name: '@design.estate/dees-catalog',
|
||||||
version: '1.8.1',
|
version: '1.9.0',
|
||||||
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
|
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,42 @@
|
|||||||
import { html } from '@design.estate/dees-element';
|
import { html, css } from '@design.estate/dees-element';
|
||||||
|
|
||||||
export const demoFunc = () => html`
|
export const demoFunc = () => html`
|
||||||
|
<style>
|
||||||
|
${css`
|
||||||
|
h3 {
|
||||||
|
margin-top: 32px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
h3 {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-demo {
|
||||||
|
background: #f5f5f5;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.form-demo {
|
||||||
|
background: #1a1a1a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<h3>Button Types</h3>
|
||||||
<dees-button>This is a slotted Text</dees-button>
|
<dees-button>This is a slotted Text</dees-button>
|
||||||
<p>
|
<p>
|
||||||
<dees-button text="Highlighted: This text shows" type="highlighted">Highlighted</dees-button>
|
<dees-button text="Highlighted: This text shows" type="highlighted">Highlighted</dees-button>
|
||||||
@ -8,8 +44,34 @@ export const demoFunc = () => html`
|
|||||||
<p><dees-button type="discreet">This is discreete button</dees-button></p>
|
<p><dees-button type="discreet">This is discreete button</dees-button></p>
|
||||||
<p><dees-button disabled>This is a disabled button</dees-button></p>
|
<p><dees-button disabled>This is a disabled button</dees-button></p>
|
||||||
<p><dees-button type="big">This is a slotted Text</dees-button></p>
|
<p><dees-button type="big">This is a slotted Text</dees-button></p>
|
||||||
|
|
||||||
|
<h3>Button States</h3>
|
||||||
<p><dees-button status="normal">Normal Status</dees-button></p>
|
<p><dees-button status="normal">Normal Status</dees-button></p>
|
||||||
<p><dees-button disabled status="pending">Pending Status</dees-button></p>
|
<p><dees-button disabled status="pending">Pending Status</dees-button></p>
|
||||||
<p><dees-button disabled status="success">Success Status</dees-button></p>
|
<p><dees-button disabled status="success">Success Status</dees-button></p>
|
||||||
<p><dees-button disabled status="error">Error Status</dees-button></p>
|
<p><dees-button disabled status="error">Error Status</dees-button></p>
|
||||||
|
|
||||||
|
<h3>Buttons in Forms (Auto-spacing)</h3>
|
||||||
|
<div class="form-demo">
|
||||||
|
<dees-form>
|
||||||
|
<dees-input-text label="Name" key="name"></dees-input-text>
|
||||||
|
<dees-input-text label="Email" key="email"></dees-input-text>
|
||||||
|
<dees-button>Save Draft</dees-button>
|
||||||
|
<dees-button type="highlighted">Save and Continue</dees-button>
|
||||||
|
<dees-form-submit>Submit Form</dees-form-submit>
|
||||||
|
</dees-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>Buttons Outside Forms (No auto-spacing)</h3>
|
||||||
|
<div class="button-group">
|
||||||
|
<dees-button>Button 1</dees-button>
|
||||||
|
<dees-button>Button 2</dees-button>
|
||||||
|
<dees-button>Button 3</dees-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>Manual Form Spacing</h3>
|
||||||
|
<div>
|
||||||
|
<dees-button inside-form="true">Manually spaced button 1</dees-button>
|
||||||
|
<dees-button inside-form="true">Manually spaced button 2</dees-button>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
|
@ -55,10 +55,24 @@ export class DeesButton extends DeesElement {
|
|||||||
})
|
})
|
||||||
public status: 'normal' | 'pending' | 'success' | 'error' = 'normal';
|
public status: 'normal' | 'pending' | 'success' | 'error' = 'normal';
|
||||||
|
|
||||||
|
@property({
|
||||||
|
type: Boolean,
|
||||||
|
reflect: true
|
||||||
|
})
|
||||||
|
public insideForm: boolean = false;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async connectedCallback() {
|
||||||
|
await super.connectedCallback();
|
||||||
|
// Auto-detect if inside a form
|
||||||
|
if (!this.insideForm && this.closest('dees-form')) {
|
||||||
|
this.insideForm = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
css`
|
css`
|
||||||
@ -71,6 +85,27 @@ export class DeesButton extends DeesElement {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Form spacing styles */
|
||||||
|
/* Default vertical form layout */
|
||||||
|
:host([inside-form]) {
|
||||||
|
margin-bottom: 16px; /* Using standard 16px like inputs */
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([inside-form]:last-child) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Horizontal form layout - auto-detected via parent */
|
||||||
|
dees-form[horizontal-layout] :host([inside-form]) {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 16px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dees-form[horizontal-layout] :host([inside-form]:last-child) {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
transition: all 0.1s , color 0s;
|
transition: all 0.1s , color 0s;
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -181,7 +216,7 @@ export class DeesButton extends DeesElement {
|
|||||||
${this.status === 'normal' ? html``: html`
|
${this.status === 'normal' ? html``: html`
|
||||||
<dees-spinner .bnw=${true} status="${this.status}"></dees-spinner>
|
<dees-spinner .bnw=${true} status="${this.status}"></dees-spinner>
|
||||||
`}
|
`}
|
||||||
<div class="textbox">${this.text ? this.text : this.textContent}</div>
|
<div class="textbox">${this.text || html`<slot>Button</slot>`}</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -202,9 +237,6 @@ export class DeesButton extends DeesElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async firstUpdated() {
|
public async firstUpdated() {
|
||||||
if (!this.textContent) {
|
// Don't set default text here as it interferes with slotted content
|
||||||
this.textContent = 'Button';
|
|
||||||
this.performUpdate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
3
ts_web/elements/dees-form-submit.demo.ts
Normal file
3
ts_web/elements/dees-form-submit.demo.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { html } from '@design.estate/dees-element';
|
||||||
|
|
||||||
|
export const demoFunc = () => html`<dees-form-submit>Submit Form</dees-form-submit>`;
|
@ -1,3 +1,4 @@
|
|||||||
|
import { demoFunc } from './dees-form-submit.demo.js';
|
||||||
import {
|
import {
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
@ -5,10 +6,8 @@ import {
|
|||||||
css,
|
css,
|
||||||
cssManager,
|
cssManager,
|
||||||
property,
|
property,
|
||||||
type CSSResult,
|
|
||||||
} from '@design.estate/dees-element';
|
} from '@design.estate/dees-element';
|
||||||
import { DeesForm } from './dees-form.js';
|
import type { DeesForm } from './dees-form.js';
|
||||||
import './dees-button.js'; // Import to ensure dees-button is registered
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
@ -18,7 +17,7 @@ declare global {
|
|||||||
|
|
||||||
@customElement('dees-form-submit')
|
@customElement('dees-form-submit')
|
||||||
export class DeesFormSubmit extends DeesElement {
|
export class DeesFormSubmit extends DeesElement {
|
||||||
public static demo = () => html`<dees-form-submit>This is a sloted text</dees-form-submit>`;
|
public static demo = demoFunc;
|
||||||
|
|
||||||
@property({
|
@property({
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@ -39,17 +38,17 @@ export class DeesFormSubmit extends DeesElement {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static styles = [cssManager.defaultStyles, css``];
|
public static styles = [cssManager.defaultStyles, css``];
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
return html`
|
return html`
|
||||||
<dees-button
|
<dees-button
|
||||||
status=${this.status}
|
status="${this.status}"
|
||||||
@click=${this.submit}
|
@click="${this.submit}"
|
||||||
.disabled=${this.disabled}
|
?disabled="${this.disabled}"
|
||||||
.text=${this.text ? this.text : this.textContent}
|
|
||||||
>
|
>
|
||||||
|
${this.text || html`<slot></slot>`}
|
||||||
</dees-button>
|
</dees-button>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -59,13 +58,15 @@ export class DeesFormSubmit extends DeesElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const parentElement: DeesForm = this.parentElement as DeesForm;
|
const parentElement: DeesForm = this.parentElement as DeesForm;
|
||||||
parentElement.gatherAndDispatch();
|
if (parentElement && parentElement.gatherAndDispatch) {
|
||||||
|
parentElement.gatherAndDispatch();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async focus() {
|
public async focus() {
|
||||||
const domtools = await this.domtoolsPromise;
|
const domtools = await this.domtoolsPromise;
|
||||||
if (!this.disabled) {
|
if (!this.disabled) {
|
||||||
domtools.convenience.smartdelay.delayFor(0);
|
await domtools.convenience.smartdelay.delayFor(0);
|
||||||
this.submit();
|
this.submit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,234 +15,173 @@ export const demoFunc = () => html`
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.demo-section {
|
dees-panel {
|
||||||
background: #f8f9fa;
|
margin-bottom: 24px;
|
||||||
border-radius: 8px;
|
|
||||||
padding: 24px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
dees-panel:last-child {
|
||||||
.demo-section {
|
margin-bottom: 0;
|
||||||
background: #1a1a1a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.demo-section h3 {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
color: #0069f2;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.demo-section p {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
color: #666;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
.demo-section p {
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-container {
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid #e0e0e0;
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 24px;
|
|
||||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
.form-container {
|
|
||||||
background: #222;
|
|
||||||
border-color: #333;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal-form {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 16px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="demo-container">
|
<div class="demo-container">
|
||||||
<div class="demo-section">
|
<dees-panel .heading="Complete Form Example" .description="A comprehensive form with various input types, validation, and form submission handling">
|
||||||
<h3>Complete Form Example</h3>
|
<dees-form
|
||||||
<p>A comprehensive form with various input types, validation, and form submission handling</p>
|
@formData=${async (eventArg) => {
|
||||||
|
const form: DeesForm = eventArg.currentTarget;
|
||||||
<div class="form-container">
|
form.setStatus('pending', 'Processing...');
|
||||||
<dees-form
|
await domtools.plugins.smartdelay.delayFor(2000);
|
||||||
@formData=${async (eventArg) => {
|
form.setStatus('success', 'Form submitted successfully!');
|
||||||
const form: DeesForm = eventArg.currentTarget;
|
await domtools.plugins.smartdelay.delayFor(2000);
|
||||||
form.setStatus('pending', 'Processing...');
|
form.reset();
|
||||||
await domtools.plugins.smartdelay.delayFor(2000);
|
}}
|
||||||
form.setStatus('success', 'Form submitted successfully!');
|
>
|
||||||
await domtools.plugins.smartdelay.delayFor(2000);
|
<dees-input-text
|
||||||
form.reset();
|
.required=${true}
|
||||||
}}
|
key="firstName"
|
||||||
>
|
label="First Name"
|
||||||
<dees-input-text
|
.description=${'Your given name'}
|
||||||
.required=${true}
|
></dees-input-text>
|
||||||
key="firstName"
|
|
||||||
label="First Name"
|
<dees-input-text
|
||||||
.description=${'Your given name'}
|
.required=${true}
|
||||||
></dees-input-text>
|
key="lastName"
|
||||||
|
label="Last Name"
|
||||||
<dees-input-text
|
></dees-input-text>
|
||||||
.required=${true}
|
|
||||||
key="lastName"
|
<dees-input-text
|
||||||
label="Last Name"
|
.required=${true}
|
||||||
></dees-input-text>
|
key="email"
|
||||||
|
label="Email Address"
|
||||||
<dees-input-text
|
.description=${'We will use this to contact you'}
|
||||||
.required=${true}
|
></dees-input-text>
|
||||||
key="email"
|
|
||||||
label="Email Address"
|
<dees-input-dropdown
|
||||||
.description=${'We will use this to contact you'}
|
.required=${true}
|
||||||
></dees-input-text>
|
key="country"
|
||||||
|
.label=${'Country'}
|
||||||
<dees-input-dropdown
|
.options=${[
|
||||||
.required=${true}
|
{ option: 'United States', key: 'us' },
|
||||||
key="country"
|
{ option: 'Canada', key: 'ca' },
|
||||||
.label=${'Country'}
|
{ option: 'Germany', key: 'de' },
|
||||||
.options=${[
|
{ option: 'France', key: 'fr' },
|
||||||
{ option: 'United States', key: 'us' },
|
{ option: 'United Kingdom', key: 'uk' },
|
||||||
{ option: 'Canada', key: 'ca' },
|
]}
|
||||||
{ option: 'Germany', key: 'de' },
|
></dees-input-dropdown>
|
||||||
{ option: 'France', key: 'fr' },
|
|
||||||
{ option: 'United Kingdom', key: 'uk' },
|
<dees-input-text
|
||||||
]}
|
.required=${true}
|
||||||
></dees-input-dropdown>
|
key="password"
|
||||||
|
label="Password"
|
||||||
<dees-input-text
|
isPasswordBool
|
||||||
.required=${true}
|
.description=${'Minimum 8 characters'}
|
||||||
key="password"
|
></dees-input-text>
|
||||||
label="Password"
|
|
||||||
isPasswordBool
|
<dees-input-checkbox
|
||||||
.description=${'Minimum 8 characters'}
|
.required=${true}
|
||||||
></dees-input-text>
|
key="terms"
|
||||||
|
label="I agree to the Terms and Conditions"
|
||||||
<dees-input-checkbox
|
></dees-input-checkbox>
|
||||||
.required=${true}
|
|
||||||
key="terms"
|
<dees-input-checkbox
|
||||||
label="I agree to the Terms and Conditions"
|
key="newsletter"
|
||||||
></dees-input-checkbox>
|
label="Send me promotional emails"
|
||||||
|
.value=${true}
|
||||||
<dees-input-checkbox
|
></dees-input-checkbox>
|
||||||
key="newsletter"
|
|
||||||
label="Send me promotional emails"
|
<dees-form-submit>Create Account</dees-form-submit>
|
||||||
.value=${true}
|
</dees-form>
|
||||||
></dees-input-checkbox>
|
</dees-panel>
|
||||||
|
|
||||||
<dees-form-submit>Create Account</dees-form-submit>
|
|
||||||
</dees-form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="demo-section">
|
<dees-panel .heading="Horizontal Form Layout" .description="Compact form with inputs arranged horizontally - perfect for filters and quick forms">
|
||||||
<h3>Horizontal Form Layout</h3>
|
<dees-form horizontal-layout>
|
||||||
<p>Compact form with inputs arranged horizontally - perfect for filters and quick forms</p>
|
<dees-input-text
|
||||||
|
key="search"
|
||||||
<div class="form-container">
|
label="Search"
|
||||||
<dees-form horizontal-layout>
|
></dees-input-text>
|
||||||
<dees-input-text
|
|
||||||
key="search"
|
<dees-input-dropdown
|
||||||
label="Search"
|
key="category"
|
||||||
></dees-input-text>
|
.label=${'Category'}
|
||||||
|
.enableSearch=${false}
|
||||||
<dees-input-dropdown
|
.options=${[
|
||||||
key="category"
|
{ option: 'All', key: 'all' },
|
||||||
.label=${'Category'}
|
{ option: 'Products', key: 'products' },
|
||||||
.enableSearch=${false}
|
{ option: 'Services', key: 'services' },
|
||||||
.options=${[
|
{ option: 'Support', key: 'support' },
|
||||||
{ option: 'All', key: 'all' },
|
]}
|
||||||
{ option: 'Products', key: 'products' },
|
></dees-input-dropdown>
|
||||||
{ option: 'Services', key: 'services' },
|
|
||||||
{ option: 'Support', key: 'support' },
|
<dees-input-dropdown
|
||||||
]}
|
key="sort"
|
||||||
></dees-input-dropdown>
|
.label=${'Sort By'}
|
||||||
|
.enableSearch=${false}
|
||||||
<dees-input-dropdown
|
.options=${[
|
||||||
key="sort"
|
{ option: 'Newest', key: 'newest' },
|
||||||
.label=${'Sort By'}
|
{ option: 'Popular', key: 'popular' },
|
||||||
.enableSearch=${false}
|
{ option: 'Price: Low to High', key: 'price_asc' },
|
||||||
.options=${[
|
{ option: 'Price: High to Low', key: 'price_desc' },
|
||||||
{ option: 'Newest', key: 'newest' },
|
]}
|
||||||
{ option: 'Popular', key: 'popular' },
|
></dees-input-dropdown>
|
||||||
{ option: 'Price: Low to High', key: 'price_asc' },
|
|
||||||
{ option: 'Price: High to Low', key: 'price_desc' },
|
<dees-input-checkbox
|
||||||
]}
|
key="inStock"
|
||||||
></dees-input-dropdown>
|
label="In Stock Only"
|
||||||
|
.value=${true}
|
||||||
<dees-input-checkbox
|
></dees-input-checkbox>
|
||||||
key="inStock"
|
</dees-form>
|
||||||
label="In Stock Only"
|
</dees-panel>
|
||||||
.value=${true}
|
|
||||||
></dees-input-checkbox>
|
|
||||||
</dees-form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="demo-section">
|
<dees-panel .heading="Advanced Form Features" .description="Form with specialized input types and complex validation">
|
||||||
<h3>Advanced Form Features</h3>
|
<dees-form
|
||||||
<p>Form with specialized input types and complex validation</p>
|
@formData=${async (eventArg) => {
|
||||||
|
const form: DeesForm = eventArg.currentTarget;
|
||||||
<div class="form-container">
|
const data = eventArg.detail.data;
|
||||||
<dees-form
|
console.log('Form data:', data);
|
||||||
@formData=${async (eventArg) => {
|
form.setStatus('success', 'Data logged to console!');
|
||||||
const form: DeesForm = eventArg.currentTarget;
|
}}
|
||||||
const data = eventArg.detail.data;
|
>
|
||||||
console.log('Form data:', data);
|
<dees-input-iban
|
||||||
form.setStatus('success', 'Data logged to console!');
|
key="iban"
|
||||||
}}
|
label="IBAN"
|
||||||
>
|
.required=${true}
|
||||||
<dees-input-iban
|
></dees-input-iban>
|
||||||
key="iban"
|
|
||||||
label="IBAN"
|
<dees-input-phone
|
||||||
.required=${true}
|
key="phone"
|
||||||
></dees-input-iban>
|
label="Phone Number"
|
||||||
|
.required=${true}
|
||||||
<dees-input-phone
|
></dees-input-phone>
|
||||||
key="phone"
|
|
||||||
label="Phone Number"
|
<dees-input-multitoggle
|
||||||
.required=${true}
|
key="preferences"
|
||||||
></dees-input-phone>
|
.label=${'Notification Preferences'}
|
||||||
|
.options=${['Email', 'SMS', 'Push', 'In-App']}
|
||||||
<dees-input-multitoggle
|
.selectedOption=${'Email'}
|
||||||
key="preferences"
|
></dees-input-multitoggle>
|
||||||
.label=${'Notification Preferences'}
|
|
||||||
.options=${['Email', 'SMS', 'Push', 'In-App']}
|
<dees-input-multiselect
|
||||||
.selectedOption=${'Email'}
|
key="interests"
|
||||||
></dees-input-multitoggle>
|
.label=${'Areas of Interest'}
|
||||||
|
.options=${[
|
||||||
<dees-input-multiselect
|
{ option: 'Technology', key: 'tech' },
|
||||||
key="interests"
|
{ option: 'Design', key: 'design' },
|
||||||
.label=${'Areas of Interest'}
|
{ option: 'Business', key: 'business' },
|
||||||
.options=${[
|
{ option: 'Marketing', key: 'marketing' },
|
||||||
{ option: 'Technology', key: 'tech' },
|
{ option: 'Sales', key: 'sales' },
|
||||||
{ option: 'Design', key: 'design' },
|
]}
|
||||||
{ option: 'Business', key: 'business' },
|
></dees-input-multiselect>
|
||||||
{ option: 'Marketing', key: 'marketing' },
|
|
||||||
{ option: 'Sales', key: 'sales' },
|
<dees-input-fileupload
|
||||||
]}
|
key="documents"
|
||||||
></dees-input-multiselect>
|
.label=${'Upload Documents'}
|
||||||
|
.description=${'PDF, DOC, or DOCX files up to 10MB'}
|
||||||
<dees-input-fileupload
|
></dees-input-fileupload>
|
||||||
key="documents"
|
|
||||||
.label=${'Upload Documents'}
|
<dees-form-submit>Submit Application</dees-form-submit>
|
||||||
.description=${'PDF, DOC, or DOCX files up to 10MB'}
|
</dees-form>
|
||||||
></dees-input-fileupload>
|
</dees-panel>
|
||||||
|
|
||||||
<dees-form-submit>Submit Application</dees-form-submit>
|
|
||||||
</dees-form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</dees-demowrapper>
|
</dees-demowrapper>
|
||||||
`;
|
`;
|
@ -132,12 +132,31 @@ export class DeesForm extends DeesElement {
|
|||||||
public async collectFormData() {
|
public async collectFormData() {
|
||||||
const children = this.getFormElements();
|
const children = this.getFormElements();
|
||||||
const valueObject: { [key: string]: string | number | boolean | any[] | File[] | { option: string; key: string; payload?: any } } = {};
|
const valueObject: { [key: string]: string | number | boolean | any[] | File[] | { option: string; key: string; payload?: any } } = {};
|
||||||
|
const radioGroups = new Map<string, DeesInputRadio[]>();
|
||||||
|
|
||||||
for (const child of children) {
|
for (const child of children) {
|
||||||
if (!child.key) {
|
if (!child.key) {
|
||||||
console.log(`form element with label "${child.label}" has no key. skipping.`);
|
console.log(`form element with label "${child.label}" has no key. skipping.`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle radio buttons specially
|
||||||
|
if (child instanceof DeesInputRadio && child.name) {
|
||||||
|
if (!radioGroups.has(child.name)) {
|
||||||
|
radioGroups.set(child.name, []);
|
||||||
|
}
|
||||||
|
radioGroups.get(child.name).push(child);
|
||||||
|
} else {
|
||||||
|
valueObject[child.key] = child.value;
|
||||||
}
|
}
|
||||||
valueObject[child.key] = child.value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process radio groups - use the name as key and selected radio's key as value
|
||||||
|
for (const [groupName, radios] of radioGroups) {
|
||||||
|
const selectedRadio = radios.find(radio => radio.value === true);
|
||||||
|
valueObject[groupName] = selectedRadio ? selectedRadio.key : null;
|
||||||
|
}
|
||||||
|
|
||||||
return valueObject;
|
return valueObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,33 +3,7 @@ import '@design.estate/dees-wcctools/demotools';
|
|||||||
import type { DeesInputRadio } from './dees-input-radio.js';
|
import type { DeesInputRadio } from './dees-input-radio.js';
|
||||||
|
|
||||||
export const demoFunc = () => html`
|
export const demoFunc = () => html`
|
||||||
<dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
|
<dees-demowrapper>
|
||||||
// Implement radio group behavior
|
|
||||||
const radioGroups = new Map<string, DeesInputRadio[]>();
|
|
||||||
|
|
||||||
// Group radios by their container
|
|
||||||
const radioContainers = elementArg.querySelectorAll('.radio-group');
|
|
||||||
radioContainers.forEach((container) => {
|
|
||||||
const radios = Array.from(container.querySelectorAll('dees-input-radio')) as DeesInputRadio[];
|
|
||||||
const groupName = container.getAttribute('data-group') || 'default';
|
|
||||||
radioGroups.set(groupName, radios);
|
|
||||||
|
|
||||||
// Add click handlers for radio group behavior
|
|
||||||
radios.forEach((radio) => {
|
|
||||||
radio.addEventListener('click', () => {
|
|
||||||
if (!radio.disabled && !radio.value) {
|
|
||||||
// Uncheck all other radios in the group
|
|
||||||
radios.forEach((r) => {
|
|
||||||
if (r !== radio) {
|
|
||||||
r.value = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
radio.value = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}}>
|
|
||||||
<style>
|
<style>
|
||||||
${css`
|
${css`
|
||||||
.demo-container {
|
.demo-container {
|
||||||
@ -121,37 +95,43 @@ export const demoFunc = () => html`
|
|||||||
<h3>Basic Radio Groups</h3>
|
<h3>Basic Radio Groups</h3>
|
||||||
<p>Radio buttons for single-choice selections</p>
|
<p>Radio buttons for single-choice selections</p>
|
||||||
|
|
||||||
<div class="radio-group" data-group="plan">
|
<div class="radio-group">
|
||||||
<div class="radio-group-title">Select your subscription plan:</div>
|
<div class="radio-group-title">Select your subscription plan:</div>
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'Basic Plan - $9/month'}
|
.label=${'Basic Plan - $9/month'}
|
||||||
.value=${true}
|
.value=${true}
|
||||||
.key=${'plan-basic'}
|
.key=${'plan-basic'}
|
||||||
|
.name=${'plan'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'Pro Plan - $29/month'}
|
.label=${'Pro Plan - $29/month'}
|
||||||
.key=${'plan-pro'}
|
.key=${'plan-pro'}
|
||||||
|
.name=${'plan'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'Enterprise Plan - $99/month'}
|
.label=${'Enterprise Plan - $99/month'}
|
||||||
.key=${'plan-enterprise'}
|
.key=${'plan-enterprise'}
|
||||||
|
.name=${'plan'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="radio-group" data-group="priority">
|
<div class="radio-group">
|
||||||
<div class="radio-group-title">Task Priority:</div>
|
<div class="radio-group-title">Task Priority:</div>
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'High Priority'}
|
.label=${'High Priority'}
|
||||||
.key=${'priority-high'}
|
.key=${'priority-high'}
|
||||||
|
.name=${'priority'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'Medium Priority'}
|
.label=${'Medium Priority'}
|
||||||
.value=${true}
|
.value=${true}
|
||||||
.key=${'priority-medium'}
|
.key=${'priority-medium'}
|
||||||
|
.name=${'priority'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'Low Priority'}
|
.label=${'Low Priority'}
|
||||||
.key=${'priority-low'}
|
.key=${'priority-low'}
|
||||||
|
.name=${'priority'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -160,43 +140,49 @@ export const demoFunc = () => html`
|
|||||||
<h3>Horizontal Layout</h3>
|
<h3>Horizontal Layout</h3>
|
||||||
<p>Radio buttons arranged horizontally for yes/no questions</p>
|
<p>Radio buttons arranged horizontally for yes/no questions</p>
|
||||||
|
|
||||||
<div class="radio-group" data-group="agreement" style="flex-direction: row;">
|
<div class="radio-group" style="flex-direction: row;">
|
||||||
<div style="margin-right: 16px;">Do you agree?</div>
|
<div style="margin-right: 16px;">Do you agree?</div>
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'Yes'}
|
.label=${'Yes'}
|
||||||
.layoutMode=${'horizontal'}
|
.layoutMode=${'horizontal'}
|
||||||
.value=${true}
|
.value=${true}
|
||||||
.key=${'agree-yes'}
|
.key=${'agree-yes'}
|
||||||
|
.name=${'agreement'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'No'}
|
.label=${'No'}
|
||||||
.layoutMode=${'horizontal'}
|
.layoutMode=${'horizontal'}
|
||||||
.key=${'agree-no'}
|
.key=${'agree-no'}
|
||||||
|
.name=${'agreement'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'Maybe'}
|
.label=${'Maybe'}
|
||||||
.layoutMode=${'horizontal'}
|
.layoutMode=${'horizontal'}
|
||||||
.key=${'agree-maybe'}
|
.key=${'agree-maybe'}
|
||||||
|
.name=${'agreement'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="radio-group" data-group="experience" style="flex-direction: row;">
|
<div class="radio-group" style="flex-direction: row;">
|
||||||
<div style="margin-right: 16px;">Experience Level:</div>
|
<div style="margin-right: 16px;">Experience Level:</div>
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'Beginner'}
|
.label=${'Beginner'}
|
||||||
.layoutMode=${'horizontal'}
|
.layoutMode=${'horizontal'}
|
||||||
.key=${'exp-beginner'}
|
.key=${'exp-beginner'}
|
||||||
|
.name=${'experience'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'Intermediate'}
|
.label=${'Intermediate'}
|
||||||
.layoutMode=${'horizontal'}
|
.layoutMode=${'horizontal'}
|
||||||
.value=${true}
|
.value=${true}
|
||||||
.key=${'exp-intermediate'}
|
.key=${'exp-intermediate'}
|
||||||
|
.name=${'experience'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'Expert'}
|
.label=${'Expert'}
|
||||||
.layoutMode=${'horizontal'}
|
.layoutMode=${'horizontal'}
|
||||||
.key=${'exp-expert'}
|
.key=${'exp-expert'}
|
||||||
|
.name=${'experience'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -206,22 +192,22 @@ export const demoFunc = () => html`
|
|||||||
<p>Multiple radio groups in a survey format</p>
|
<p>Multiple radio groups in a survey format</p>
|
||||||
|
|
||||||
<div class="grid-layout">
|
<div class="grid-layout">
|
||||||
<div class="radio-group" data-group="satisfaction">
|
<div class="radio-group">
|
||||||
<div class="radio-group-title">How satisfied are you?</div>
|
<div class="radio-group-title">How satisfied are you?</div>
|
||||||
<dees-input-radio .label=${'Very Satisfied'} .key=${'sat-very'}></dees-input-radio>
|
<dees-input-radio .label=${'Very Satisfied'} .key=${'sat-very'} .name=${'satisfaction'}></dees-input-radio>
|
||||||
<dees-input-radio .label=${'Satisfied'} .value=${true} .key=${'sat-normal'}></dees-input-radio>
|
<dees-input-radio .label=${'Satisfied'} .value=${true} .key=${'sat-normal'} .name=${'satisfaction'}></dees-input-radio>
|
||||||
<dees-input-radio .label=${'Neutral'} .key=${'sat-neutral'}></dees-input-radio>
|
<dees-input-radio .label=${'Neutral'} .key=${'sat-neutral'} .name=${'satisfaction'}></dees-input-radio>
|
||||||
<dees-input-radio .label=${'Dissatisfied'} .key=${'sat-dis'}></dees-input-radio>
|
<dees-input-radio .label=${'Dissatisfied'} .key=${'sat-dis'} .name=${'satisfaction'}></dees-input-radio>
|
||||||
<dees-input-radio .label=${'Very Dissatisfied'} .key=${'sat-verydis'}></dees-input-radio>
|
<dees-input-radio .label=${'Very Dissatisfied'} .key=${'sat-verydis'} .name=${'satisfaction'}></dees-input-radio>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="radio-group" data-group="recommend">
|
<div class="radio-group">
|
||||||
<div class="radio-group-title">Would you recommend us?</div>
|
<div class="radio-group-title">Would you recommend us?</div>
|
||||||
<dees-input-radio .label=${'Definitely'} .key=${'rec-def'}></dees-input-radio>
|
<dees-input-radio .label=${'Definitely'} .key=${'rec-def'} .name=${'recommend'}></dees-input-radio>
|
||||||
<dees-input-radio .label=${'Probably'} .value=${true} .key=${'rec-prob'}></dees-input-radio>
|
<dees-input-radio .label=${'Probably'} .value=${true} .key=${'rec-prob'} .name=${'recommend'}></dees-input-radio>
|
||||||
<dees-input-radio .label=${'Not Sure'} .key=${'rec-unsure'}></dees-input-radio>
|
<dees-input-radio .label=${'Not Sure'} .key=${'rec-unsure'} .name=${'recommend'}></dees-input-radio>
|
||||||
<dees-input-radio .label=${'Probably Not'} .key=${'rec-probnot'}></dees-input-radio>
|
<dees-input-radio .label=${'Probably Not'} .key=${'rec-probnot'} .name=${'recommend'}></dees-input-radio>
|
||||||
<dees-input-radio .label=${'Definitely Not'} .key=${'rec-defnot'}></dees-input-radio>
|
<dees-input-radio .label=${'Definitely Not'} .key=${'rec-defnot'} .name=${'recommend'}></dees-input-radio>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -230,26 +216,30 @@ export const demoFunc = () => html`
|
|||||||
<h3>States</h3>
|
<h3>States</h3>
|
||||||
<p>Different radio button states</p>
|
<p>Different radio button states</p>
|
||||||
|
|
||||||
<div class="radio-group" data-group="states">
|
<div class="radio-group">
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'Normal Radio'}
|
.label=${'Normal Radio'}
|
||||||
.key=${'state-normal'}
|
.key=${'state-normal'}
|
||||||
|
.name=${'states'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'Selected Radio'}
|
.label=${'Selected Radio'}
|
||||||
.value=${true}
|
.value=${true}
|
||||||
.key=${'state-selected'}
|
.key=${'state-selected'}
|
||||||
|
.name=${'states'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'Disabled Unchecked'}
|
.label=${'Disabled Unchecked'}
|
||||||
.disabled=${true}
|
.disabled=${true}
|
||||||
.key=${'state-disabled1'}
|
.key=${'state-disabled1'}
|
||||||
|
.name=${'states2'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
<dees-input-radio
|
<dees-input-radio
|
||||||
.label=${'Disabled Checked'}
|
.label=${'Disabled Checked'}
|
||||||
.disabled=${true}
|
.disabled=${true}
|
||||||
.value=${true}
|
.value=${true}
|
||||||
.key=${'state-disabled2'}
|
.key=${'state-disabled2'}
|
||||||
|
.name=${'states2'}
|
||||||
></dees-input-radio>
|
></dees-input-radio>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -258,18 +248,18 @@ export const demoFunc = () => html`
|
|||||||
<h3>Settings Example</h3>
|
<h3>Settings Example</h3>
|
||||||
<p>Common radio button patterns in settings</p>
|
<p>Common radio button patterns in settings</p>
|
||||||
|
|
||||||
<div class="radio-group" data-group="theme">
|
<div class="radio-group">
|
||||||
<div class="radio-group-title">Theme Preference:</div>
|
<div class="radio-group-title">Theme Preference:</div>
|
||||||
<dees-input-radio .label=${'Light Theme'} .key=${'theme-light'}></dees-input-radio>
|
<dees-input-radio .label=${'Light Theme'} .key=${'theme-light'} .name=${'theme'}></dees-input-radio>
|
||||||
<dees-input-radio .label=${'Dark Theme'} .value=${true} .key=${'theme-dark'}></dees-input-radio>
|
<dees-input-radio .label=${'Dark Theme'} .value=${true} .key=${'theme-dark'} .name=${'theme'}></dees-input-radio>
|
||||||
<dees-input-radio .label=${'System Default'} .key=${'theme-system'}></dees-input-radio>
|
<dees-input-radio .label=${'System Default'} .key=${'theme-system'} .name=${'theme'}></dees-input-radio>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="radio-group" data-group="notifications">
|
<div class="radio-group">
|
||||||
<div class="radio-group-title">Notification Frequency:</div>
|
<div class="radio-group-title">Notification Frequency:</div>
|
||||||
<dees-input-radio .label=${'All Notifications'} .key=${'notif-all'}></dees-input-radio>
|
<dees-input-radio .label=${'All Notifications'} .key=${'notif-all'} .name=${'notifications'}></dees-input-radio>
|
||||||
<dees-input-radio .label=${'Important Only'} .value=${true} .key=${'notif-important'}></dees-input-radio>
|
<dees-input-radio .label=${'Important Only'} .value=${true} .key=${'notif-important'} .name=${'notifications'}></dees-input-radio>
|
||||||
<dees-input-radio .label=${'None'} .key=${'notif-none'}></dees-input-radio>
|
<dees-input-radio .label=${'None'} .key=${'notif-none'} .name=${'notifications'}></dees-input-radio>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,6 +17,8 @@ export class DeesInputRadio extends DeesInputBase<DeesInputRadio> {
|
|||||||
@property()
|
@property()
|
||||||
public value: boolean = false;
|
public value: boolean = false;
|
||||||
|
|
||||||
|
@property({ type: String })
|
||||||
|
public name: string = '';
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -95,7 +97,27 @@ export class DeesInputRadio extends DeesInputBase<DeesInputRadio> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async toggleSelected () {
|
public async toggleSelected () {
|
||||||
this.value = !this.value;
|
// Radio buttons can only be selected, not deselected by clicking
|
||||||
|
if (this.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this radio has a name, find and deselect other radios in the same group
|
||||||
|
if (this.name) {
|
||||||
|
// Try to find a form container first, then fall back to document
|
||||||
|
const container = this.closest('dees-form') ||
|
||||||
|
this.closest('dees-demowrapper') ||
|
||||||
|
this.closest('.radio-group')?.parentElement ||
|
||||||
|
document;
|
||||||
|
const allRadios = container.querySelectorAll(`dees-input-radio[name="${this.name}"]`);
|
||||||
|
allRadios.forEach((radio: DeesInputRadio) => {
|
||||||
|
if (radio !== this && radio.value) {
|
||||||
|
radio.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.value = true;
|
||||||
this.dispatchEvent(new CustomEvent('newValue', {
|
this.dispatchEvent(new CustomEvent('newValue', {
|
||||||
detail: this.value,
|
detail: this.value,
|
||||||
bubbles: true
|
bubbles: true
|
||||||
|
@ -100,7 +100,8 @@ export class DeesInputText extends DeesInputBase {
|
|||||||
|
|
||||||
input:focus {
|
input:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-bottom: 1px solid ${cssManager.bdTheme( colors.bright.blueActive, colors.dark.blueActive)};
|
border-bottom: 1px solid
|
||||||
|
${cssManager.bdTheme(colors.bright.blueActive, colors.dark.blueActive)};
|
||||||
cursor: text;
|
cursor: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,6 +118,7 @@ export class DeesInputText extends DeesInputBase {
|
|||||||
padding: 4px 0px;
|
padding: 4px 0px;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.showPassword:hover {
|
.showPassword:hover {
|
||||||
@ -146,18 +148,20 @@ export class DeesInputText extends DeesInputBase {
|
|||||||
letter-spacing: ${this.isPasswordBool ? '1px' : 'normal'};
|
letter-spacing: ${this.isPasswordBool ? '1px' : 'normal'};
|
||||||
color: ${this.goBright ? '#333' : '#ccc'};
|
color: ${this.goBright ? '#333' : '#ccc'};
|
||||||
}
|
}
|
||||||
${this.validationText ? css`
|
${this.validationText
|
||||||
.validationContainer {
|
? css`
|
||||||
height: 22px;
|
.validationContainer {
|
||||||
opacity: 1;
|
height: 22px;
|
||||||
}
|
opacity: 1;
|
||||||
` : css`
|
}
|
||||||
.validationContainer {
|
`
|
||||||
height: 4px;
|
: css`
|
||||||
padding: 2px !important;
|
.validationContainer {
|
||||||
opacity: 0;
|
height: 4px;
|
||||||
}
|
padding: 2px !important;
|
||||||
`}
|
opacity: 0;
|
||||||
|
}
|
||||||
|
`}
|
||||||
</style>
|
</style>
|
||||||
<div class="input-wrapper">
|
<div class="input-wrapper">
|
||||||
<dees-label .label=${this.label} .description=${this.description}></dees-label>
|
<dees-label .label=${this.label} .description=${this.description}></dees-label>
|
||||||
@ -168,9 +172,7 @@ export class DeesInputText extends DeesInputBase {
|
|||||||
@input="${this.updateValue}"
|
@input="${this.updateValue}"
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
/>
|
/>
|
||||||
<div class="validationContainer">
|
<div class="validationContainer">${this.validationText}</div>
|
||||||
${this.validationText}
|
|
||||||
</div>
|
|
||||||
${this.isPasswordBool
|
${this.isPasswordBool
|
||||||
? html`
|
? html`
|
||||||
<div class="showPassword" @click=${this.togglePasswordView}>
|
<div class="showPassword" @click=${this.togglePasswordView}>
|
||||||
|
@ -8,16 +8,8 @@ import {
|
|||||||
type TemplateResult,
|
type TemplateResult,
|
||||||
cssManager,
|
cssManager,
|
||||||
css,
|
css,
|
||||||
unsafeCSS,
|
|
||||||
type CSSResult,
|
|
||||||
state,
|
|
||||||
} from '@design.estate/dees-element';
|
} from '@design.estate/dees-element';
|
||||||
|
|
||||||
// Import components used in template
|
|
||||||
import './dees-form.js';
|
|
||||||
import './dees-input-text.js';
|
|
||||||
import './dees-form-submit.js';
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
'dees-simple-login': DeesSimpleLogin;
|
'dees-simple-login': DeesSimpleLogin;
|
||||||
@ -126,46 +118,19 @@ export class DeesSimpleLogin extends DeesElement {
|
|||||||
|
|
||||||
public async firstUpdated(_changedProperties: Map<string | number | symbol, unknown>): Promise<void> {
|
public async firstUpdated(_changedProperties: Map<string | number | symbol, unknown>): Promise<void> {
|
||||||
super.firstUpdated(_changedProperties);
|
super.firstUpdated(_changedProperties);
|
||||||
const domtools = await this.domtoolsPromise;
|
|
||||||
|
|
||||||
// Wait a tick to ensure child elements are rendered
|
|
||||||
await this.updateComplete;
|
|
||||||
|
|
||||||
const form = this.shadowRoot.querySelector('dees-form') as any;
|
const form = this.shadowRoot.querySelector('dees-form') as any;
|
||||||
|
if (form) {
|
||||||
if (!form) {
|
form.addEventListener('formData', (event: CustomEvent) => {
|
||||||
console.error('dees-form element not found in dees-simple-login');
|
this.dispatchEvent(new CustomEvent('login', {
|
||||||
return;
|
detail: event.detail,
|
||||||
|
bubbles: true,
|
||||||
|
composed: true
|
||||||
|
}));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the form has the readyDeferred property and wait for it
|
|
||||||
if (form.readyDeferred?.promise) {
|
|
||||||
try {
|
|
||||||
await form.readyDeferred.promise;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error waiting for form ready:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const username = this.shadowRoot.querySelector('dees-input-text[key="username"]');
|
|
||||||
const password = this.shadowRoot.querySelector('dees-input-text[key="password"]');
|
|
||||||
const submit = this.shadowRoot.querySelector('dees-form-submit');
|
|
||||||
|
|
||||||
// Add form data listener
|
|
||||||
form.addEventListener('formData', (event: CustomEvent) => {
|
|
||||||
this.dispatchEvent(new CustomEvent('login', {
|
|
||||||
detail: event.detail,
|
|
||||||
bubbles: true,
|
|
||||||
composed: true
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches a 'login' event when the form is submitted.
|
|
||||||
* Event detail structure: { data: { username: string, password: string } }
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* allows switching to slotted content
|
* allows switching to slotted content
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user