Update print statement from 'Hello' to 'Goodbye'
This commit is contained in:
116
Readme.md
116
Readme.md
@@ -122,7 +122,7 @@ count(5);
|
|||||||
count(prev => prev + 1); // Use function for previous value
|
count(prev => prev + 1); // Use function for previous value
|
||||||
|
|
||||||
// Read with dependency tracking (inside effect)
|
// Read with dependency tracking (inside effect)
|
||||||
$$(() => {
|
$e(() => {
|
||||||
console.log(count()); // Will be registered as dependency
|
console.log(count()); // Will be registered as dependency
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@@ -130,7 +130,7 @@ $$(() => {
|
|||||||
#### Computed Signal
|
#### Computed Signal
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { $, $$ } from 'sigpro';
|
import { $, $e } from 'sigpro';
|
||||||
|
|
||||||
const firstName = $('John');
|
const firstName = $('John');
|
||||||
const lastName = $('Doe');
|
const lastName = $('Doe');
|
||||||
@@ -178,20 +178,20 @@ type Signal<T> = {
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `$$(effect)` - Effects
|
### `$e(effect)` - Effects
|
||||||
|
|
||||||
Executes a function and automatically re-runs it when its dependencies change.
|
Executes a function and automatically re-runs it when its dependencies change.
|
||||||
|
|
||||||
#### Basic Effect
|
#### Basic Effect
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { $, $$ } from 'sigpro';
|
import { $, $e } from 'sigpro';
|
||||||
|
|
||||||
const count = $(0);
|
const count = $(0);
|
||||||
const name = $('World');
|
const name = $('World');
|
||||||
|
|
||||||
// Effect runs immediately and on dependency changes
|
// Effect runs immediately and on dependency changes
|
||||||
$$(() => {
|
$e(() => {
|
||||||
console.log(`Count is: ${count()}`); // Only depends on count
|
console.log(`Count is: ${count()}`); // Only depends on count
|
||||||
});
|
});
|
||||||
// Log: "Count is: 0"
|
// Log: "Count is: 0"
|
||||||
@@ -205,11 +205,11 @@ name('Universe'); // No log (name is not a dependency)
|
|||||||
#### Effect with Cleanup
|
#### Effect with Cleanup
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { $, $$ } from 'sigpro';
|
import { $, $e } from 'sigpro';
|
||||||
|
|
||||||
const userId = $(1);
|
const userId = $(1);
|
||||||
|
|
||||||
$$(() => {
|
$e(() => {
|
||||||
const id = userId();
|
const id = userId();
|
||||||
let isSubscribed = true;
|
let isSubscribed = true;
|
||||||
|
|
||||||
@@ -233,17 +233,17 @@ userId(2); // Previous subscription cleaned up, new one created
|
|||||||
#### Nested Effects
|
#### Nested Effects
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { $, $$ } from 'sigpro';
|
import { $, $e } from 'sigpro';
|
||||||
|
|
||||||
const show = $(true);
|
const show = $(true);
|
||||||
const count = $(0);
|
const count = $(0);
|
||||||
|
|
||||||
$$(() => {
|
$e(() => {
|
||||||
if (!show()) return;
|
if (!show()) return;
|
||||||
|
|
||||||
// This effect is nested inside the conditional
|
// This effect is nested inside the conditional
|
||||||
// It will only be active when show() is true
|
// It will only be active when show() is true
|
||||||
$$(() => {
|
$e(() => {
|
||||||
console.log('Count changed:', count());
|
console.log('Count changed:', count());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -256,12 +256,12 @@ show(true); // Inner effect recreated, logs "Count changed: 1"
|
|||||||
#### Manual Effect Control
|
#### Manual Effect Control
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { $, $$ } from 'sigpro';
|
import { $, $e } from 'sigpro';
|
||||||
|
|
||||||
const count = $(0);
|
const count = $(0);
|
||||||
|
|
||||||
// Stop effect manually
|
// Stop effect manually
|
||||||
const stop = $$(() => {
|
const stop = $e(() => {
|
||||||
console.log('Effect running:', count());
|
console.log('Effect running:', count());
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -438,7 +438,7 @@ html`<div class=${className}></div>`
|
|||||||
html`<a href="${href}" class="link ${className}">Link</a>`
|
html`<a href="${href}" class="link ${className}">Link</a>`
|
||||||
|
|
||||||
// Reactive attributes update when signal changes
|
// Reactive attributes update when signal changes
|
||||||
$$(() => {
|
$e(() => {
|
||||||
// The attribute updates automatically
|
// The attribute updates automatically
|
||||||
console.log('Class changed:', className());
|
console.log('Class changed:', className());
|
||||||
});
|
});
|
||||||
@@ -582,16 +582,16 @@ const Page = () => html`
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `$component(tagName, setupFunction, observedAttributes)` - Web Components
|
### `$c(tagName, setupFunction, observedAttributes)` - Web Components
|
||||||
|
|
||||||
Creates Custom Elements with reactive properties. Uses Light DOM (no Shadow DOM) and a slot system based on node filtering.
|
Creates Custom Elements with reactive properties. Uses Light DOM (no Shadow DOM) and a slot system based on node filtering.
|
||||||
|
|
||||||
#### Basic Component
|
#### Basic Component
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { $, $component, html } from 'sigpro';
|
import { $, $c, html } from 'sigpro';
|
||||||
|
|
||||||
$component('my-counter', (props, context) => {
|
$c('my-counter', (props, context) => {
|
||||||
// props contains signals for each observed attribute
|
// props contains signals for each observed attribute
|
||||||
// context: { slot, emit, host, onUnmount }
|
// context: { slot, emit, host, onUnmount }
|
||||||
|
|
||||||
@@ -628,9 +628,9 @@ Usage:
|
|||||||
#### Component with Named Slots
|
#### Component with Named Slots
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { $, $component, html } from 'sigpro';
|
import { $, $c, html } from 'sigpro';
|
||||||
|
|
||||||
$component('my-card', (props, { slot }) => {
|
$c('my-card', (props, { slot }) => {
|
||||||
return html`
|
return html`
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
@@ -666,9 +666,9 @@ Usage:
|
|||||||
#### Component with Props and Events
|
#### Component with Props and Events
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { $, $component, html } from 'sigpro';
|
import { $, $c, html } from 'sigpro';
|
||||||
|
|
||||||
$component('todo-item', (props, { emit, host }) => {
|
$c('todo-item', (props, { emit, host }) => {
|
||||||
const handleToggle = () => {
|
const handleToggle = () => {
|
||||||
props.completed(c => !c);
|
props.completed(c => !c);
|
||||||
emit('toggle', { id: props.id(), completed: props.completed() });
|
emit('toggle', { id: props.id(), completed: props.completed() });
|
||||||
@@ -708,13 +708,13 @@ Usage:
|
|||||||
#### Component with Cleanup
|
#### Component with Cleanup
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { $, $component, html, $$ } from 'sigpro';
|
import { $, $c, html, $e } from 'sigpro';
|
||||||
|
|
||||||
$component('timer-widget', (props, { onUnmount }) => {
|
$c('timer-widget', (props, { onUnmount }) => {
|
||||||
const seconds = $(0);
|
const seconds = $(0);
|
||||||
|
|
||||||
// Effect with automatic cleanup
|
// Effect with automatic cleanup
|
||||||
$$(() => {
|
$e(() => {
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
seconds(s => s + 1);
|
seconds(s => s + 1);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
@@ -740,9 +740,9 @@ $component('timer-widget', (props, { onUnmount }) => {
|
|||||||
#### Complete Context API
|
#### Complete Context API
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { $, $component, html } from 'sigpro';
|
import { $, $c, html } from 'sigpro';
|
||||||
|
|
||||||
$component('context-demo', (props, context) => {
|
$c('context-demo', (props, context) => {
|
||||||
// Context properties:
|
// Context properties:
|
||||||
// - slot(name) - Gets child nodes with matching slot attribute
|
// - slot(name) - Gets child nodes with matching slot attribute
|
||||||
// - emit(name, detail) - Dispatches custom event
|
// - emit(name, detail) - Dispatches custom event
|
||||||
@@ -784,9 +784,9 @@ $component('context-demo', (props, context) => {
|
|||||||
#### Practical Example: Todo App Component
|
#### Practical Example: Todo App Component
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { $, $component, html } from 'sigpro';
|
import { $, $c, html } from 'sigpro';
|
||||||
|
|
||||||
$component('todo-app', () => {
|
$c('todo-app', () => {
|
||||||
const todos = $([]);
|
const todos = $([]);
|
||||||
const newTodo = $('');
|
const newTodo = $('');
|
||||||
const filter = $('all');
|
const filter = $('all');
|
||||||
@@ -873,7 +873,7 @@ $component('todo-app', () => {
|
|||||||
}, []);
|
}, []);
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Key Points About `$component`:
|
#### Key Points About `$c`:
|
||||||
|
|
||||||
1. **Light DOM only** - No Shadow DOM, children are accessible and styleable from outside
|
1. **Light DOM only** - No Shadow DOM, children are accessible and styleable from outside
|
||||||
2. **Slot system** - `slot()` function filters child nodes by `slot` attribute
|
2. **Slot system** - `slot()` function filters child nodes by `slot` attribute
|
||||||
@@ -884,16 +884,16 @@ $component('todo-app', () => {
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `$router(routes)` - Router
|
### `$r(routes)` - Router
|
||||||
|
|
||||||
Hash-based router for SPAs with reactive integration.
|
Hash-based router for SPAs with reactive integration.
|
||||||
|
|
||||||
#### Basic Routing
|
#### Basic Routing
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { $router, html } from 'sigpro';
|
import { $r, html } from 'sigpro';
|
||||||
|
|
||||||
const router = $router([
|
const router = $r([
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
component: () => html`
|
component: () => html`
|
||||||
@@ -916,9 +916,9 @@ document.body.appendChild(router);
|
|||||||
#### Route Parameters
|
#### Route Parameters
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { $router, html } from 'sigpro';
|
import { $r, html } from 'sigpro';
|
||||||
|
|
||||||
const router = $router([
|
const router = $r([
|
||||||
{
|
{
|
||||||
path: '/user/:id',
|
path: '/user/:id',
|
||||||
component: (params) => html`
|
component: (params) => html`
|
||||||
@@ -945,9 +945,9 @@ const router = $router([
|
|||||||
#### Nested Routes
|
#### Nested Routes
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { $router, html, $ } from 'sigpro';
|
import { $r, html, $ } from 'sigpro';
|
||||||
|
|
||||||
const router = $router([
|
const router = $r([
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
component: () => html`
|
component: () => html`
|
||||||
@@ -961,7 +961,7 @@ const router = $router([
|
|||||||
path: '/dashboard',
|
path: '/dashboard',
|
||||||
component: () => {
|
component: () => {
|
||||||
// Nested router
|
// Nested router
|
||||||
const subRouter = $router([
|
const subRouter = $r([
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
component: () => html`<h2>Dashboard Home</h2>`
|
component: () => html`<h2>Dashboard Home</h2>`
|
||||||
@@ -994,19 +994,19 @@ const router = $router([
|
|||||||
#### Route Guards
|
#### Route Guards
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { $router, html, $ } from 'sigpro';
|
import { $r, html, $ } from 'sigpro';
|
||||||
|
|
||||||
const isAuthenticated = $(false);
|
const isAuthenticated = $(false);
|
||||||
|
|
||||||
const requireAuth = (component) => (params) => {
|
const requireAuth = (component) => (params) => {
|
||||||
if (!isAuthenticated()) {
|
if (!isAuthenticated()) {
|
||||||
$router.go('/login');
|
$r.go('/login');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return component(params);
|
return component(params);
|
||||||
};
|
};
|
||||||
|
|
||||||
const router = $router([
|
const router = $r([
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
component: () => html`<h1>Public Home</h1>`
|
component: () => html`<h1>Public Home</h1>`
|
||||||
@@ -1030,25 +1030,25 @@ const router = $router([
|
|||||||
#### Navigation
|
#### Navigation
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { $router } from 'sigpro';
|
import { $r } from 'sigpro';
|
||||||
|
|
||||||
// Navigate to path
|
// Navigate to path
|
||||||
$router.go('/user/42');
|
$r.go('/user/42');
|
||||||
|
|
||||||
// Navigate with replace
|
// Navigate with replace
|
||||||
$router.go('/dashboard', { replace: true });
|
$r.go('/dashboard', { replace: true });
|
||||||
|
|
||||||
// Go back
|
// Go back
|
||||||
$router.back();
|
$r.back();
|
||||||
|
|
||||||
// Go forward
|
// Go forward
|
||||||
$router.forward();
|
$r.forward();
|
||||||
|
|
||||||
// Get current path
|
// Get current path
|
||||||
const currentPath = $router.getCurrentPath();
|
const currentPath = $r.getCurrentPath();
|
||||||
|
|
||||||
// Listen to navigation
|
// Listen to navigation
|
||||||
$router.listen((path, oldPath) => {
|
$r.listen((path, oldPath) => {
|
||||||
console.log(`Navigated from ${oldPath} to ${path}`);
|
console.log(`Navigated from ${oldPath} to ${path}`);
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@@ -1056,9 +1056,9 @@ $router.listen((path, oldPath) => {
|
|||||||
#### Route Transitions
|
#### Route Transitions
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { $router, html, $$ } from 'sigpro';
|
import { $r, html, $e } from 'sigpro';
|
||||||
|
|
||||||
const router = $router([
|
const router = $r([
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
component: () => html`<div class="page home">Home</div>`
|
component: () => html`<div class="page home">Home</div>`
|
||||||
@@ -1070,7 +1070,7 @@ const router = $router([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
// Add transitions
|
// Add transitions
|
||||||
$$(() => {
|
$e(() => {
|
||||||
const currentPath = router.getCurrentPath();
|
const currentPath = router.getCurrentPath();
|
||||||
const pages = document.querySelectorAll('.page');
|
const pages = document.querySelectorAll('.page');
|
||||||
|
|
||||||
@@ -1092,7 +1092,7 @@ $$(() => {
|
|||||||
### Real-time Todo Application
|
### Real-time Todo Application
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { $, $$, html, $component } from 'sigpro';
|
import { $, $e, html, $c } from 'sigpro';
|
||||||
|
|
||||||
// Styles
|
// Styles
|
||||||
const styles = html`
|
const styles = html`
|
||||||
@@ -1178,7 +1178,7 @@ const styles = html`
|
|||||||
</style>
|
</style>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
$component('todo-app', () => {
|
$c('todo-app', () => {
|
||||||
// State
|
// State
|
||||||
const todos = $(() => {
|
const todos = $(() => {
|
||||||
const saved = localStorage.getItem('todos');
|
const saved = localStorage.getItem('todos');
|
||||||
@@ -1191,7 +1191,7 @@ $component('todo-app', () => {
|
|||||||
const editText = $('');
|
const editText = $('');
|
||||||
|
|
||||||
// Save to localStorage on changes
|
// Save to localStorage on changes
|
||||||
$$(() => {
|
$e(() => {
|
||||||
localStorage.setItem('todos', JSON.stringify(todos()));
|
localStorage.setItem('todos', JSON.stringify(todos()));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1363,7 +1363,7 @@ $component('todo-app', () => {
|
|||||||
### Data Dashboard with Real-time Updates
|
### Data Dashboard with Real-time Updates
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { $, $$, html, $component } from 'sigpro';
|
import { $, $e, html, $c } from 'sigpro';
|
||||||
|
|
||||||
// Simulated WebSocket connection
|
// Simulated WebSocket connection
|
||||||
class DataStream {
|
class DataStream {
|
||||||
@@ -1389,14 +1389,14 @@ class DataStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$component('data-dashboard', () => {
|
$c('data-dashboard', () => {
|
||||||
const stream = new DataStream();
|
const stream = new DataStream();
|
||||||
const dataPoints = $([]);
|
const dataPoints = $([]);
|
||||||
const selectedCategory = $('all');
|
const selectedCategory = $('all');
|
||||||
const timeWindow = $(60); // seconds
|
const timeWindow = $(60); // seconds
|
||||||
|
|
||||||
// Subscribe to data stream
|
// Subscribe to data stream
|
||||||
$$(() => {
|
$e(() => {
|
||||||
const unsubscribe = stream.subscribe((newData) => {
|
const unsubscribe = stream.subscribe((newData) => {
|
||||||
dataPoints(prev => {
|
dataPoints(prev => {
|
||||||
const updated = [...prev, newData];
|
const updated = [...prev, newData];
|
||||||
@@ -1501,14 +1501,14 @@ $component('data-dashboard', () => {
|
|||||||
### Custom Hooks
|
### Custom Hooks
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { $, $$ } from 'sigpro';
|
import { $, $e } from 'sigpro';
|
||||||
|
|
||||||
// useLocalStorage hook
|
// useLocalStorage hook
|
||||||
function useLocalStorage(key, initialValue) {
|
function useLocalStorage(key, initialValue) {
|
||||||
const stored = localStorage.getItem(key);
|
const stored = localStorage.getItem(key);
|
||||||
const signal = $(stored ? JSON.parse(stored) : initialValue);
|
const signal = $(stored ? JSON.parse(stored) : initialValue);
|
||||||
|
|
||||||
$$(() => {
|
$e(() => {
|
||||||
localStorage.setItem(key, JSON.stringify(signal()));
|
localStorage.setItem(key, JSON.stringify(signal()));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1520,7 +1520,7 @@ function useDebounce(signal, delay) {
|
|||||||
const debounced = $(signal());
|
const debounced = $(signal());
|
||||||
let timeout;
|
let timeout;
|
||||||
|
|
||||||
$$(() => {
|
$e(() => {
|
||||||
const value = signal();
|
const value = signal();
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
timeout = setTimeout(() => {
|
timeout = setTimeout(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user