Skip to content

Commit 7199f61

Browse files
committed
Updated Dropdown component, it is now called zephyr-dropdown.
1 parent 7fda4ca commit 7199f61

File tree

4 files changed

+137
-84
lines changed

4 files changed

+137
-84
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ ZephyrJS comes with several pre-built components:
6767
```
6868
<basic-card>
6969
<custom-button>
70-
<custom-dropdown>
70+
<zephyr-dropdown>
7171
<custom-input>
7272
<modal-dialog>
7373
<notification-box>

zephyrtemplates/Dropdown.js

Lines changed: 90 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -7,81 +7,115 @@ export default class Dropdown extends ZephyrJS {
77

88
constructor() {
99
super();
10-
11-
if (!this.shadowRoot) {
12-
this.attachShadow({ mode: 'open' });
13-
this.initializeTemplate();
14-
}
15-
16-
// Initialize component state
17-
this._state = { value: '' };
18-
this.state = new Proxy(this._state, {
19-
set: (target, property, value) => {
20-
target[property] = value;
21-
this.updateBindings();
22-
return true;
23-
}
24-
});
10+
this.state = {
11+
options: [],
12+
selectedOption: null,
13+
placeholder: 'Select an option'
14+
};
15+
console.log('Dropdown constructor called');
2516
}
2617

27-
connectedCallback() {
28-
this.setupEventListeners();
29-
this.updateSlotContent();
30-
}
18+
async connectedCallback() {
19+
console.log('Dropdown connectedCallback started');
20+
await super.connectedCallback();
21+
console.log('Dropdown super.connectedCallback completed');
3122

32-
initializeTemplate() {
33-
const template = document.getElementById('dropdown').content.cloneNode(true);
34-
this.shadowRoot.innerHTML = ''; // Clear any existing content
35-
this.shadowRoot.appendChild(template);
36-
}
23+
this.setOptions(JSON.parse(this.getAttribute('options') || '[]'));
24+
this.state.placeholder = this.getAttribute('placeholder') || this.state.placeholder;
25+
this.state.selectedOption = this.getAttribute('selected') || null;
3726

38-
setupEventListeners() {
39-
const selectElement = this.shadowRoot.querySelector('select');
40-
if (selectElement) {
41-
selectElement.addEventListener('change', (event) => {
42-
this.state.value = event.target.value;
43-
this.dispatchEvent(new CustomEvent('change', { detail: { value: this.state.value } }));
44-
});
45-
}
27+
console.log('Dropdown state after attribute processing:', this.state);
28+
29+
await this.renderAndAddListeners();
30+
console.log('Dropdown renderAndAddListeners completed');
4631
}
4732

48-
static get observedAttributes() {
49-
return ['disabled', 'value'];
33+
setOptions(options) {
34+
this.setState({ options });
35+
this.renderAndAddListeners();
5036
}
5137

52-
attributeChangedCallback(name, oldValue, newValue) {
53-
this.updateAttributes();
38+
async renderAndAddListeners() {
39+
console.log('renderAndAddListeners started');
40+
await this.render();
41+
this.addEventListeners();
42+
console.log('renderAndAddListeners completed');
5443
}
5544

56-
updateAttributes() {
57-
const selectElement = this.shadowRoot.querySelector('select');
58-
if (selectElement) {
59-
selectElement.disabled = this.hasAttribute('disabled');
45+
async render() {
46+
console.log('Render started');
47+
if (!this.shadowRoot) {
48+
console.error('Shadow root not found');
49+
return;
50+
}
6051

61-
if (this.hasAttribute('value')) {
62-
selectElement.value = this.getAttribute('value');
63-
this.state.value = selectElement.value;
52+
let select = this.shadowRoot.querySelector('select');
53+
if (!select) {
54+
console.log('Select element not found, inserting template content');
55+
if (this.template && this.template.content) {
56+
const templateContent = this.template.content.cloneNode(true);
57+
console.log('Cloned template content:', templateContent);
58+
this.shadowRoot.appendChild(templateContent);
59+
select = this.shadowRoot.querySelector('select');
60+
console.log('Select element after insertion:', select);
61+
} else {
62+
console.error('Template content not available');
63+
return;
6464
}
6565
}
66-
}
6766

68-
updateBindings() {
69-
const selectElement = this.shadowRoot.querySelector('select');
70-
if (selectElement) {
71-
selectElement.value = this.state.value;
67+
if (!select) {
68+
console.error('Select element still not found after inserting template');
69+
console.log('Shadow root content:', this.shadowRoot.innerHTML);
70+
return;
71+
}
72+
73+
// Clear existing options
74+
select.innerHTML = '';
75+
76+
// Add placeholder option if needed
77+
if (this.state.placeholder) {
78+
const placeholderOption = document.createElement('option');
79+
placeholderOption.value = '';
80+
placeholderOption.textContent = this.state.placeholder;
81+
placeholderOption.disabled = true;
82+
placeholderOption.selected = !this.state.selectedOption;
83+
select.appendChild(placeholderOption);
7284
}
85+
86+
// Add options
87+
this.state.options.forEach(option => {
88+
const optionElement = document.createElement('option');
89+
optionElement.value = option.value;
90+
optionElement.textContent = option.label;
91+
optionElement.selected = option.value === this.state.selectedOption;
92+
select.appendChild(optionElement);
93+
});
94+
95+
console.log('Render completed, select content:', select.innerHTML);
7396
}
7497

75-
updateSlotContent() {
76-
const selectElement = this.shadowRoot.querySelector('select');
77-
if (selectElement) {
78-
const options = this.querySelectorAll('option');
79-
selectElement.innerHTML = ''; // Clear existing options
80-
options.forEach(option => {
81-
selectElement.appendChild(option.cloneNode(true));
98+
addEventListeners() {
99+
console.log('Adding event listeners');
100+
const select = this.shadowRoot.querySelector('select');
101+
102+
if (select) {
103+
select.addEventListener('change', (e) => {
104+
this.state.selectedOption = e.target.value;
105+
this.dispatchCustomEvent('optionSelected', { option: this.state.selectedOption });
82106
});
107+
console.log('Change listener added to select element');
108+
} else {
109+
console.error('Select element not found');
83110
}
111+
112+
console.log('Event listeners added');
113+
}
114+
115+
disconnectedCallback() {
116+
super.disconnectedCallback();
117+
console.log('Dropdown disconnected');
84118
}
85119
}
86120

87-
defineCustomElement('custom-dropdown', Dropdown);
121+
defineCustomElement('zephyr-dropdown', Dropdown);

zephyrtemplates/ZephyrCore.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ export function setTheme(themeName) {
2424
}
2525
}
2626

27+
// Expose setTheme to the global scope
28+
window.Themes = Themes;
29+
window.setTheme = setTheme;
30+
2731
import BasicCard from "../zephyrtemplates/BasicCard.js";
2832
import ModalDialog from "../zephyrtemplates/ModalDialog.js";
2933
import Notification from "../zephyrtemplates/Notification.js";
@@ -50,7 +54,4 @@ import TooltipComponent from "../zephyrtemplates/TooltipComponent.js";
5054
import MarkdownShowcase from "../zephyrtemplates/MarkdownShowcase.js";
5155
import TimelineView from "../zephyrtemplates/TimelineView.js";
5256
import TimelineItem from "../zephyrtemplates/TimelineItem.js";
53-
import Modal from "../zephyrtemplates/Modal.js";
54-
// Expose setTheme to the global scope
55-
window.Themes = Themes;
56-
window.setTheme = setTheme;
57+
import Modal from "../zephyrtemplates/Modal.js";
Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,50 @@
1-
<template id="dropdown">
1+
<template id="dropdown-template">
22
<style>
33
:host {
44
display: inline-block;
5+
}
6+
.dropdown-container {
57
position: relative;
6-
font-family: var(--font-family-sans-serif);
8+
width: 200px;
9+
font-family: Arial, sans-serif;
10+
}
11+
.dropdown-toggle {
12+
padding: 10px;
13+
border: 1px solid var(--neutral-color, #ccc);
14+
background-color: var(--light-color, #fff);
15+
color: var(--dark-text, #333);
16+
cursor: pointer;
17+
user-select: none;
18+
}
19+
.dropdown-options {
20+
display: none;
21+
position: absolute;
22+
top: 100%;
23+
left: 0;
24+
right: 0;
25+
background-color: var(--light-color, #fff);
26+
border: 1px solid var(--neutral-color, #ccc);
27+
border-top: none;
28+
list-style-type: none;
29+
padding: 0;
30+
margin: 0;
31+
max-height: 200px;
32+
overflow-y: auto;
33+
z-index: 1000;
34+
}
35+
.dropdown-options.open {
36+
display: block;
737
}
8-
select {
9-
width: 100%;
10-
padding: var(--dropdown-padding);
11-
border: var(--dropdown-border-radius);
12-
border-radius: var(--dropdown-border-radius);
13-
font-size: var(--dropdown-font-size);
14-
appearance: none;
15-
background: var(--dropdown-background);
16-
color: var(--light-text);
17-
background-image: var(--dropdown-arrow);
18-
background-repeat: no-repeat;
19-
background-position: right 10px center;
20-
background-size: 12px;
21-
transition: border-color 0.3s ease;
38+
.dropdown-option {
39+
padding: 10px;
40+
cursor: pointer;
2241
}
23-
select:focus {
24-
border-color: var(--dropdown-border-radius);
25-
outline: none;
26-
box-shadow: 0 0 0 2px rgba(126, 189, 194, 0.2);
42+
.dropdown-option:hover {
43+
background-color: var(--secondary-color, #f0f0f0);
2744
}
2845
</style>
29-
<select>
30-
<slot></slot>
31-
</select>
46+
<div class="dropdown-container">
47+
<div class="dropdown-toggle"></div>
48+
<ul class="dropdown-options"></ul>
49+
</div>
3250
</template>

0 commit comments

Comments
 (0)