UNPKG

@gleb.askerko/componentkit-js

Version:

Lightweight, framework-agnostic JavaScript component library with progress gift components

182 lines (145 loc) 4.36 kB
export class Card { constructor(options = {}) { this.options = { title: '', content: '', variant: 'default', actions: [], className: '', ...options }; this.element = null; this.container = null; this.actionButtons = []; } render(selector) { this.container = typeof selector === 'string' ? document.querySelector(selector) : selector; if (!this.container) { throw new Error(`Container not found: ${selector}`); } this.element = this.createElement(); this.container.appendChild(this.element); this.bindEvents(); return this; } createElement() { const card = document.createElement('div'); card.className = this.getCardClasses(); if (this.options.title) { const header = this.createHeader(); card.appendChild(header); } if (this.options.content) { const body = this.createBody(); card.appendChild(body); } if (this.options.actions && this.options.actions.length > 0) { const footer = this.createFooter(); card.appendChild(footer); } return card; } createHeader() { const header = document.createElement('div'); header.className = 'ck-card-header'; const title = document.createElement('h3'); title.className = 'ck-card-title'; title.textContent = this.options.title; header.appendChild(title); return header; } createBody() { const body = document.createElement('div'); body.className = 'ck-card-body'; if (typeof this.options.content === 'string') { const content = document.createElement('p'); content.className = 'ck-card-content'; content.textContent = this.options.content; body.appendChild(content); } else if (this.options.content instanceof HTMLElement) { body.appendChild(this.options.content); } return body; } createFooter() { const footer = document.createElement('div'); footer.className = 'ck-card-footer'; this.options.actions.forEach((action, index) => { const button = this.createActionButton(action, index); footer.appendChild(button); this.actionButtons.push(button); }); return footer; } createActionButton(action, index) { const button = document.createElement('button'); button.className = `ck-button ck-card-action ${action.variant ? `ck-button--${action.variant}` : 'ck-button--primary'}`; button.textContent = action.text || 'Action'; button.disabled = action.disabled || false; if (action.onClick) { button.addEventListener('click', (e) => { action.onClick(e, index); }); } return button; } getCardClasses() { const baseClasses = 'ck-card'; const variantClasses = { default: 'ck-card--default', elevated: 'ck-card--elevated', outlined: 'ck-card--outlined' }; return [ baseClasses, variantClasses[this.options.variant] || variantClasses.default, this.options.className ].filter(Boolean).join(' '); } bindEvents() { // Card-level events can be added here } update(newOptions) { this.options = { ...this.options, ...newOptions }; if (this.element) { // Remove old element and create new one const parent = this.element.parentNode; parent.removeChild(this.element); this.actionButtons = []; this.element = this.createElement(); parent.appendChild(this.element); this.bindEvents(); } return this; } setTitle(title) { return this.update({ title }); } setContent(content) { return this.update({ content }); } addAction(action) { const actions = [...this.options.actions, action]; return this.update({ actions }); } removeAction(index) { const actions = this.options.actions.filter((_, i) => i !== index); return this.update({ actions }); } destroy() { // Clean up action button event listeners this.actionButtons.forEach(button => { if (button.parentNode) { button.parentNode.removeChild(button); } }); if (this.element && this.element.parentNode) { this.element.parentNode.removeChild(this.element); } this.element = null; this.container = null; this.actionButtons = []; } }