@xcons/widget
Version:
XCon Studio widget utilities with advanced template rendering, reactive binding system and registry pattern support
539 lines (431 loc) ⢠15.1 kB
Markdown
# /widget
[](https://badge.fury.io/js/%40xcons%2Fwidget)
[](https://www.typescriptlang.org/)
[](https://opensource.org/licenses/MIT)
XCon Studio widget tools offering advanced template rendering engine, reactive binding system, lifecycle interfaces and registry pattern support for modern web applications. Designed with the **"Write once, run everywhere"** philosophy.
## Features
- šÆ **Decorator-Based Widget System** - Simple `` decorator for component registration
- š **Advanced Reactive System** - `` and `` decorators with automatic dependency tracking
- š **Template Rendering Engine** - Dynamic template processing with reactive data binding
- š **Registry Pattern** - Centralized widget management and automatic DOM scanning
- š§ **Lifecycle Hooks** - Flexible lifecycle interfaces (`OnWidgetInit`, `OnWidgetDestroy`, etc.)
- šØ **Style Encapsulation** - Multiple encapsulation modes (none, emulated, shadow, component)
- š **Dependency Injection** - Service injection with `` decorator
- š **Two-Way Data Binding** - Model binding with `x:model` directive
- š **SEO Friendly** - Static HTML rendering support and search engine friendly structure
- š± **TypeScript First** - Full TypeScript support with comprehensive type definitions
- š **Zero Dependencies** - Lightweight and performant
## Installation
```bash
npm install /widget
```
## Quick Start
### 1. Creating a Basic Widget with Reactive Properties
```typescript
import { Widget, xproperty, xcomputed, OnWidgetInit } from '@xcons/widget';
export class HelloWidget implements OnWidgetInit {
name: string = 'World';
firstName: string = 'John';
lastName: string = 'Doe';
count: number = 0;
get fullName(): string {
return `${this.firstName} ${this.lastName}`;
}
onWidgetInit(): void {
console.log('HelloWidget initialized!');
}
incrementCount(): void {
this.count++;
}
}
```
### 2. Bootstrap Your Application
```typescript
import { XConBootstrap } from '@xcons/widget';
import { HelloWidget } from './hello-widget';
// Bootstrap the application with widgets
XConBootstrap.run({
widgets: [
{ widget: HelloWidget, initMode: 'auto' }
]
});
```
### 3. Using Widget in HTML
```html
<div class="hello-widget"></div>
```
## Advanced Usage
### Services with Dependency Injection
```typescript
import { xinjectable, xsingleton, xinject } from '@xcons/widget';
// Service definition
export class UserService {
users: User[] = [];
async loadUsers(): Promise<void> {
// Load users from API
this.users = await fetch('/api/users').then(r => r.json());
}
getUsers(): User[] {
return this.users;
}
}
// Using service in widget
export class UserListWidget implements OnWidgetInit, OnWidgetReady {
searchQuery: string = '';
selectedUserId: number | null = null;
private userService: UserService;
get userCount(): number {
return this.userService.getUsers().length;
}
get filteredUsers(): User[] {
if (!this.searchQuery) {
return this.userService.getUsers();
}
const query = this.searchQuery.toLowerCase();
return this.userService.getUsers().filter(user =>
user.name.toLowerCase().includes(query)
);
}
onWidgetInit(): void {
console.log('UserListWidget initialized');
}
async onWidgetReady(templateReady: boolean): Promise<void> {
if (templateReady) {
await this.userService.loadUsers();
}
}
selectUser(userId: number): void {
this.selectedUserId = userId;
}
}
// Start the application
XConBootstrap.run({
widgets: [
{ widget: UserListWidget, initMode: 'auto' }
],
services: [
{ service: UserService }
]
});
```
### SEO and Search Engine Compatibility
XCon Widget allows you to create SEO-friendly web applications with its search engine optimized structure:
```typescript
export class ProductWidget implements OnWidgetInit {
product: Product = {
name: 'Product Name',
description: 'Product description',
imageUrl: '/images/product.jpg',
price: '199.99'
};
onWidgetInit(): void {
// Load initial data for server-side rendering
this.loadProductData();
}
async loadProductData(): Promise<void> {
// Render critical content first for SEO
const productId = this.getProductIdFromUrl();
this.product = await this.fetchProduct(productId);
}
}
```
**SEO Advantages:**
- ā
Static HTML content support - Search engines can read content directly
- ā
Semantic HTML structure - Use of meaningful HTML elements
- ā
Structured Data support - Rich snippets with Schema.org markups
- ā
Progressive Enhancement - Basic content can be displayed without JavaScript
- ā
Fast initial render - Widgets bind on top of existing HTML
## Template Syntax
### Text Binding (x:text)
```html
<span x:text="message"></span>
<div x:text="username"></div>
<p x:text="computedValue"></p>
```
### HTML Binding (x:html)
ā ļø **Security Warning:** Be careful when using x:html, it can lead to XSS (Cross-Site Scripting) vulnerabilities with untrusted content. Only use with trusted or sanitized HTML content.
```html
<div x:html="trustedHtmlContent"></div>
```
**Example Usage:**
```typescript
export class ContentWidget {
articleContent: string = '<h2>Title</h2><p>Content text</p>';
// Example of creating safe HTML content
setSafeContent(userInput: string): void {
// Sanitize content first
this.articleContent = this.sanitizeHtml(userInput);
}
private sanitizeHtml(html: string): string {
// Use HTML sanitization library (e.g., DOMPurify)
// return DOMPurify.sanitize(html);
return html;
}
}
```
### Directives
#### Conditional Rendering (x:if)
```html
<div x:if="isVisible">This content is visible</div>
<div x:if="count > 0">Counter is greater than zero</div>
```
#### List Rendering (x:for)
```html
<template x:for="item in items">
<li x:text="item.name"></li>
</template>
<!-- With index -->
<template x:for="item, index in items">
<div>
<span x:text="index"></span>: <span x:text="item.name"></span>
</div>
</template>
```
#### Switch Cases (x:switch)
```html
<div x:switch="status">
<div x:switch:case="loading">Loading...</div>
<div x:switch:case="success">Successful!</div>
<div x:switch:case="error">An error occurred</div>
<div x:switch:default>Unknown state</div>
</div>
```
#### Event Binding (x:on:*)
```html
<button x:on:click="handleClick">Click</button>
<button x:on:click="handleClickWithArgs('hello', 123)">With Arguments</button>
<input x:on:input="handleInput" />
<form x:on:submit="handleSubmit">...</form>
```
#### Attribute Binding (x:attr:*)
```html
<input x:attr:disabled="isDisabled" x:attr:placeholder="placeholderText" />
<img x:attr:src="imageUrl" x:attr:alt="imageAlt" />
<a x:attr:href="linkUrl" x:attr:target="linkTarget"></a>
```
#### Class Binding (x:class:*)
```html
<div x:class:active="isActive" x:class:highlighted="isHighlighted">Content</div>
<button x:class:disabled="!isEnabled" x:class:primary="isPrimary">Button</button>
```
#### Two-Way Binding (x:model)
```html
<input x:model="username" />
<textarea x:model="description"></textarea>
<select x:model="selectedOption">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
</select>
<!-- With configuration -->
<input x:model="username" x:model:config='{"debounce": 500, "trim": true}' />
```
#### Isolation (x:isolate)
Ensures child widgets maintain their own independent binding contexts:
```html
<div class="parent-widget">
<p x:text="parentProperty">Parent content</p>
<!-- This area and its child elements are isolated from parent binding -->
<div x:isolate class="child-widget">
<p x:text="childProperty">Child content</p>
</div>
</div>
```
## API Reference
### Decorators
####
Widget class decorator:
```typescript
```
####
Reactive property decorator:
```typescript
```
####
Computed property decorator:
```typescript
```
####
Service injection decorator:
```typescript
// Inject by class
// Inject by token
```
####
Service registration decorator:
```typescript
```
### Lifecycle Interfaces
```typescript
interface OnWidgetInit {
onWidgetInit(): void;
}
interface OnWidgetReady {
onWidgetReady(templateReady: boolean): void;
}
interface OnWidgetDestroy {
onWidgetDestroy(): void;
}
interface OnWidgetRendered {
onWidgetRendered(container: HTMLElement): void;
}
interface OnWidgetDataUpdated {
onWidgetDataUpdated(): void;
}
interface OnWidgetResize {
onWidgetResize(): void;
}
interface OnWidgetEditModeChanged {
onWidgetEditModeChanged(): void;
}
interface OnWidgetMobileModeChanged {
onWidgetMobileModeChanged(): void;
}
interface OnWidgetPropertyChanged {
onWidgetPropertyChanged(propertyKey?: string, oldValue?: any, newValue?: any): void;
}
interface OnWidgetInitializationError {
onWidgetInitializationError(error: any): void;
}
```
### Bootstrap API
```typescript
// Bootstrap configuration
interface BootstrapConfig {
rootWidget?: any; // Single root widget
widgets?: BootstrapWidget[]; // Widget list
services?: BootstrapService[]; // Services to register
providers?: BootstrapProvider[]; // Custom providers
}
// Start the application
XConBootstrap.run(config: BootstrapConfig): Promise<void>
// Rescan DOM for new widgets
XConBootstrap.rescanDOM(): void
// Setup auto-scan for dynamic content
XConBootstrap.setupAutoScan(): void
// Get widget instance from DOM element
XConBootstrap.getWidgetInstance(element: HTMLElement): any
// Destroy widget on element
XConBootstrap.destroyWidget(element: HTMLElement): boolean
```
### Global XConWidgets API
The framework provides a global `XConWidgets` object for widget management:
```typescript
// Registry access
XConWidgets.registry // Widget registry instance
XConWidgets.domManager // DOM management instance
// Widget registration
XConWidgets.registerWidget(selector, widgetClass, config, initMode)
// Widget activation
XConWidgets.activateWidget(widgetClass, context)
// Registry queries
XConWidgets.isRegistered(selector) // Check if registered
XConWidgets.getWidgets() // Get all selectors
XConWidgets.getRegisteredWidgets() // Get all with details
XConWidgets.getWidgetBySelector(selector) // Get widget by selector
// DOM management
XConWidgets.scanDOM() // Scan DOM for widgets
XConWidgets.rescanDOM() // Rescan DOM
XConWidgets.setupAutoScan() // Setup auto-scan
```
## Browser Support
- Chrome 60+
- Firefox 60+
- Safari 12+
- Edge 79+
## Dependencies
### Peer Dependencies
- `/core ^2.0.1`
- `/common ^2.0.16`
- `typescript >=4.5.0`
### Zero Runtime Dependencies
The package has no runtime dependencies to be lightweight and performant.
## š License
MIT License - see [LICENSE](LICENSE) file for details.
**XCon Studio Team** | [š Documentation](https://xcon.studio/)
---
**Made with ā¤ļø by XCon Studio Team**