feat: number range slider
This commit is contained in:
@@ -25,6 +25,100 @@ class NodeDetailsComponent extends Component {
|
||||
return (r << 16) + (g << 8) + b;
|
||||
}
|
||||
|
||||
// Parameter component renderers
|
||||
renderSelectComponent(p, formId, pidx) {
|
||||
return `<select id="${formId}-field-${pidx}" data-param-name="${p.name}" data-param-location="${p.location || 'body'}" data-param-type="${p.type || 'string'}" data-param-required="${p.required ? '1' : '0'}" class="param-input">${p.values.map(v => `<option value="${v}">${v}</option>`).join('')}</select>`;
|
||||
}
|
||||
|
||||
renderColorComponent(p, formId, pidx) {
|
||||
const defaultValue = p.default !== undefined ? p.default : (Array.isArray(p.values) && p.values.length === 1) ? p.values[0] : 0;
|
||||
return `<div class="color-input-container">
|
||||
<input id="${formId}-field-${pidx}"
|
||||
data-param-name="${p.name}"
|
||||
data-param-location="${p.location || 'body'}"
|
||||
data-param-type="${p.type || 'string'}"
|
||||
data-param-required="${p.required ? '1' : '0'}"
|
||||
class="param-input color-picker"
|
||||
type="color"
|
||||
value="${this.rgbIntToHex(defaultValue)}">
|
||||
<input type="text"
|
||||
class="color-rgb-display"
|
||||
readonly
|
||||
value="${defaultValue}"
|
||||
style="margin-left: 5px; width: 80px; font-size: 0.8em;">
|
||||
</div>`;
|
||||
}
|
||||
|
||||
renderNumberRangeComponent(p, formId, pidx) {
|
||||
const defaultValue = p.default !== undefined ? p.default : 0;
|
||||
const maxValue = p.value || 100;
|
||||
return `<div class="number-range-container">
|
||||
<input id="${formId}-field-${pidx}"
|
||||
data-param-name="${p.name}"
|
||||
data-param-location="${p.location || 'body'}"
|
||||
data-param-type="${p.type || 'string'}"
|
||||
data-param-required="${p.required ? '1' : '0'}"
|
||||
class="param-input range-slider"
|
||||
type="range"
|
||||
min="0"
|
||||
max="${maxValue}"
|
||||
value="${defaultValue}">
|
||||
<div class="range-display">
|
||||
<span class="range-value">${defaultValue}</span>
|
||||
<span class="range-max">/ ${maxValue}</span>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
renderTextComponent(p, formId, pidx) {
|
||||
const defaultValue = p.default !== undefined ? p.default : (Array.isArray(p.values) && p.values.length === 1) ? p.values[0] : '';
|
||||
return `<input id="${formId}-field-${pidx}"
|
||||
data-param-name="${p.name}"
|
||||
data-param-location="${p.location || 'body'}"
|
||||
data-param-type="${p.type || 'string'}"
|
||||
data-param-required="${p.required ? '1' : '0'}"
|
||||
class="param-input"
|
||||
type="text"
|
||||
placeholder="${p.location || 'body'} • ${p.type || 'string'}"
|
||||
value="${defaultValue}">`;
|
||||
}
|
||||
|
||||
// Component map for parameter types
|
||||
getParameterComponentMap() {
|
||||
const components = {
|
||||
select: this.renderSelectComponent,
|
||||
color: this.renderColorComponent,
|
||||
numberRange: this.renderNumberRangeComponent,
|
||||
text: this.renderTextComponent
|
||||
};
|
||||
|
||||
// Bind all methods to this context
|
||||
return Object.fromEntries(
|
||||
Object.entries(components).map(([key, method]) => [key, method.bind(this)])
|
||||
);
|
||||
}
|
||||
|
||||
// Component type determination rules
|
||||
getComponentType(p) {
|
||||
const typeRules = [
|
||||
{ condition: () => Array.isArray(p.values) && p.values.length > 1, type: 'select' },
|
||||
{ condition: () => p.type === 'color', type: 'color' },
|
||||
{ condition: () => p.type === 'numberRange', type: 'numberRange' }
|
||||
];
|
||||
|
||||
const matchedRule = typeRules.find(rule => rule.condition());
|
||||
return matchedRule ? matchedRule.type : 'text';
|
||||
}
|
||||
|
||||
// Main parameter renderer that uses the component map
|
||||
renderParameterComponent(p, formId, pidx) {
|
||||
const componentMap = this.getParameterComponentMap();
|
||||
const componentType = this.getComponentType(p);
|
||||
const renderer = componentMap[componentType];
|
||||
|
||||
return renderer(p, formId, pidx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
setupViewModelListeners() {
|
||||
@@ -441,34 +535,7 @@ class NodeDetailsComponent extends Component {
|
||||
? `<div class="endpoint-params">${ep.params.map((p, pidx) => `
|
||||
<label class="endpoint-param" for="${formId}-field-${pidx}">
|
||||
<span class="param-name">${p.name}${p.required ? ' *' : ''}</span>
|
||||
${ (Array.isArray(p.values) && p.values.length > 1)
|
||||
? `<select id="${formId}-field-${pidx}" data-param-name="${p.name}" data-param-location="${p.location || 'body'}" data-param-type="${p.type || 'string'}" data-param-required="${p.required ? '1' : '0'}" class="param-input">${p.values.map(v => `<option value="${v}">${v}</option>`).join('')}</select>`
|
||||
: (p.type === 'color')
|
||||
? `<div class="color-input-container">
|
||||
<input id="${formId}-field-${pidx}"
|
||||
data-param-name="${p.name}"
|
||||
data-param-location="${p.location || 'body'}"
|
||||
data-param-type="${p.type || 'string'}"
|
||||
data-param-required="${p.required ? '1' : '0'}"
|
||||
class="param-input color-picker"
|
||||
type="color"
|
||||
value="${this.rgbIntToHex(p.default !== undefined ? p.default : (Array.isArray(p.values) && p.values.length === 1) ? p.values[0] : 0)}">
|
||||
<input type="text"
|
||||
class="color-rgb-display"
|
||||
readonly
|
||||
value="${p.default !== undefined ? p.default : (Array.isArray(p.values) && p.values.length === 1) ? p.values[0] : 0}"
|
||||
style="margin-left: 5px; width: 80px; font-size: 0.8em;">
|
||||
</div>`
|
||||
: `<input id="${formId}-field-${pidx}"
|
||||
data-param-name="${p.name}"
|
||||
data-param-location="${p.location || 'body'}"
|
||||
data-param-type="${p.type || 'string'}"
|
||||
data-param-required="${p.required ? '1' : '0'}"
|
||||
class="param-input"
|
||||
type="text"
|
||||
placeholder="${p.location || 'body'} • ${p.type || 'string'}"
|
||||
value="${p.default !== undefined ? p.default : (Array.isArray(p.values) && p.values.length === 1) ? p.values[0] : ''}">`
|
||||
}
|
||||
${this.renderParameterComponent(p, formId, pidx)}
|
||||
</label>
|
||||
`).join('')}</div>`
|
||||
: '<div class="endpoint-params none">No parameters</div>';
|
||||
@@ -608,6 +675,17 @@ class NodeDetailsComponent extends Component {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Add event listeners for range sliders
|
||||
const rangeSliders = this.findAllElements('.range-slider');
|
||||
rangeSliders.forEach(rangeInput => {
|
||||
this.addEventListener(rangeInput, 'input', (e) => {
|
||||
const rangeDisplay = rangeInput.parentElement.querySelector('.range-display .range-value');
|
||||
if (rangeDisplay) {
|
||||
rangeDisplay.textContent = e.target.value;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
escapeHtml(str) {
|
||||
|
||||
Reference in New Issue
Block a user