Add UI web components and adjust .gitignore
This commit is contained in:
127
static/components/grid-selector/grid-selector.js
Normal file
127
static/components/grid-selector/grid-selector.js
Normal file
@@ -0,0 +1,127 @@
|
||||
// GridSelector component definition
|
||||
// This file should be loaded as a module (type="module") after the
|
||||
// corresponding HTML template (grid-selector.html) is present in the DOM.
|
||||
|
||||
class GridSelector extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
return ['grid-color', 'grid-size', 'grid-numbering'];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
// Attach a shadow root
|
||||
this.attachShadow({ mode: 'open' });
|
||||
|
||||
// Load the template defined in grid-selector.html
|
||||
const tmpl = document.getElementById('grid-selector-template');
|
||||
if (!tmpl) {
|
||||
console.error('GridSelector: template not found in DOM');
|
||||
return;
|
||||
}
|
||||
this.shadowRoot.appendChild(tmpl.content.cloneNode(true));
|
||||
|
||||
// Grab elements from the template
|
||||
this._colorInput = this.shadowRoot.querySelector('#grid-color');
|
||||
this._sizeInput = this.shadowRoot.querySelector('#grid-size');
|
||||
this._numberingInput = this.shadowRoot.querySelector('#grid-numbering');
|
||||
|
||||
// Bind event handlers
|
||||
this._onColorChange = this._onColorChange.bind(this);
|
||||
this._onSizeChange = this._onSizeChange.bind(this);
|
||||
this._onNumberingChange = this._onNumberingChange.bind(this);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
// Initialise values from attributes or defaults
|
||||
this._colorInput.value = this.getAttribute('grid-color') || '#000000';
|
||||
this._sizeInput.value = this.getAttribute('grid-size') || '25';
|
||||
const numbering = this.hasAttribute('grid-numbering')
|
||||
? this.getAttribute('grid-numbering') === 'true'
|
||||
: true;
|
||||
this._numberingInput.checked = numbering;
|
||||
|
||||
// Register listeners
|
||||
this._colorInput.addEventListener('input', this._onColorChange);
|
||||
this._sizeInput.addEventListener('input', this._onSizeChange);
|
||||
this._numberingInput.addEventListener('change', this._onNumberingChange);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this._colorInput.removeEventListener('input', this._onColorChange);
|
||||
this._sizeInput.removeEventListener('input', this._onSizeChange);
|
||||
this._numberingInput.removeEventListener('change', this._onNumberingChange);
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
if (oldValue === newValue) return;
|
||||
switch (name) {
|
||||
case 'grid-color':
|
||||
if (this._colorInput) this._colorInput.value = newValue;
|
||||
break;
|
||||
case 'grid-size':
|
||||
if (this._sizeInput) this._sizeInput.value = newValue;
|
||||
break;
|
||||
case 'grid-numbering':
|
||||
if (this._numberingInput) this._numberingInput.checked = newValue === 'true';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ----- Property getters / setters -----
|
||||
get gridColor() {
|
||||
return this._colorInput ? this._colorInput.value : this.getAttribute('grid-color');
|
||||
}
|
||||
set gridColor(v) {
|
||||
this.setAttribute('grid-color', v);
|
||||
}
|
||||
|
||||
get gridSize() {
|
||||
return this._sizeInput ? Number(this._sizeInput.value) : Number(this.getAttribute('grid-size'));
|
||||
}
|
||||
set gridSize(v) {
|
||||
this.setAttribute('grid-size', v);
|
||||
}
|
||||
|
||||
get gridNumbering() {
|
||||
return this._numberingInput ? this._numberingInput.checked : this.hasAttribute('grid-numbering') && this.getAttribute('grid-numbering') === 'true';
|
||||
}
|
||||
set gridNumbering(v) {
|
||||
this.setAttribute('grid-numbering', v);
|
||||
}
|
||||
|
||||
// ----- Internal event handlers -----
|
||||
_onColorChange(e) {
|
||||
const color = e.target.value;
|
||||
this.setAttribute('grid-color', color);
|
||||
this._dispatchChange();
|
||||
}
|
||||
|
||||
_onSizeChange(e) {
|
||||
const size = e.target.value;
|
||||
this.setAttribute('grid-size', size);
|
||||
this._dispatchChange();
|
||||
}
|
||||
|
||||
_onNumberingChange(e) {
|
||||
const checked = e.target.checked;
|
||||
this.setAttribute('grid-numbering', checked);
|
||||
this._dispatchChange();
|
||||
}
|
||||
|
||||
_dispatchChange() {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('gridchange', {
|
||||
detail: {
|
||||
color: this.gridColor,
|
||||
size: this.gridSize,
|
||||
numbering: this.gridNumbering,
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Register the custom element
|
||||
customElements.define('grid-selector', GridSelector);
|
||||
Reference in New Issue
Block a user