@uistate/core 2.0.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,72 +1,35 @@
1
- # @uistate/core
1
+ # @uistate/core v3.0.0
2
2
 
3
3
  **author**: Ajdin Imsirovic <ajdika@live.com> (GitHub)
4
4
  **maintainer**: uistate <ajdika.i@gmail.com> (npm)
5
5
 
6
- High-performance UI state management using CSS custom properties and ADSI (Attribute-Driven State Inheritance). Focused heavily on DX and performance.
6
+ High-performance UI state management using CSS custom properties and ADSI (Attribute-Driven State Inheritance). Focused heavily on DX and performance with a fully declarative approach.
7
+
8
+ ## What's New in v3.0.0
9
+
10
+ - 🔄 Fully declarative state management approach
11
+ - 🧩 Enhanced template system with CSS-based templates
12
+ - 🚀 Improved performance through optimized state propagation
13
+ - 📦 New state serialization and inspection capabilities
14
+ - 🔍 Telemetry plugin for better debugging
7
15
 
8
16
  ## Features
9
17
 
10
- - 🚀 Potentially O(1) state updates using CSS custom properties
18
+ - 🚀 O(1) state updates using CSS custom properties
11
19
  - 📉 Significant memory savings compared to virtual DOM approaches
12
20
  - 🎯 Zero configuration
13
21
  - 🔄 Automatic reactivity through CSS cascade
14
22
  - 🎨 Framework agnostic
15
23
  - 📦 Tiny bundle size (~2KB)
16
- - 🧩 Modular architecture with dedicated modules for CSS state and events
24
+ - 🧩 Modular architecture with dedicated modules for CSS state and templates
25
+ - 📝 Declarative HTML-in-CSS templates
17
26
 
18
27
  ## Installation
19
28
 
20
29
  ```bash
21
- # Install the core package
22
30
  npm install @uistate/core
23
31
  ```
24
32
 
25
- ## Quick Start
26
-
27
- ```javascript
28
- import { cssState, eventState } from '@uistate/core';
29
-
30
- // Initialize state
31
- cssState.init();
32
-
33
- // Set state via CSS variables
34
- cssState.set('--counter-value', '0');
35
-
36
- // Get state
37
- const count = parseInt(cssState.get('--counter-value'));
38
-
39
- // Subscribe to changes
40
- const unsubscribe = eventState.on('counter:change', (newValue) => {
41
- console.log('Counter changed:', newValue);
42
- });
43
-
44
- // Set state with an attribute
45
- document.documentElement.dataset.counterValue = count + 1;
46
- ```
47
-
48
- ### HTML Usage Example
49
-
50
- ```html
51
- <button data-counter-value="0" id="counter-btn">Count: 0</button>
52
- ```
53
-
54
- ```css
55
- [data-counter-value] {
56
- /* Style based on state */
57
- }
58
- ```
59
-
60
- ```javascript
61
- document.getElementById('counter-btn').addEventListener('click', () => {
62
- const btn = document.getElementById('counter-btn');
63
- const currentValue = parseInt(btn.dataset.counterValue);
64
- btn.dataset.counterValue = currentValue + 1;
65
- btn.textContent = `Count: ${currentValue + 1}`;
66
- eventState.emit('counter:change', currentValue + 1);
67
- });
68
- ```
69
-
70
33
  ## Why @uistate/core?
71
34
 
72
35
  ### Performance
@@ -77,7 +40,7 @@ document.getElementById('counter-btn').addEventListener('click', () => {
77
40
 
78
41
  ### Developer Experience
79
42
 
80
- - **Simple API**: Modular `cssState` and `eventState` for clear separation of concerns
43
+ - **Declarative API**: Define UI structure in CSS templates
81
44
  - **Framework Agnostic**: Works with any framework or vanilla JavaScript
82
45
  - **Zero Config**: No store setup, no reducers, no actions
83
46
  - **CSS-Native**: Leverages the power of CSS selectors and the cascade
@@ -85,21 +48,21 @@ document.getElementById('counter-btn').addEventListener('click', () => {
85
48
  ### Core Concepts
86
49
 
87
50
  - **Attribute-Driven State Inheritance (ADSI)**: State represented both as CSS variables and data attributes
88
- - **Hierarchical State Machines**: Model complex UI states with nested state machines
89
- - **CSS-Driven State Derivation**: Derive complex states using CSS without JavaScript
51
+ - **Declarative Templates**: Define UI components directly in CSS
52
+ - **Automatic State Propagation**: State changes automatically update the UI
90
53
 
91
54
  ## Project Structure
92
55
 
93
56
  ```
94
57
  @uistate/core/
95
- ├── src/ # Core library
96
- │ ├── index.js # Main entry
97
- │ ├── cssState.js # CSS variables management
98
- │ ├── eventState.js # Event-based state transitions
99
- └── templateManager.js # Component management
100
- └── examples/ # Example applications
101
- ├── basic/ # Simple examples (range sliders, toggles, etc)
102
- └── advanced/ # Advanced patterns and techniques
58
+ ├── src/ # Core library
59
+ │ ├── index.js # Main entry
60
+ │ ├── cssState.js # CSS variables management
61
+ │ ├── templateManager.js # Declarative template management
62
+ ├── stateInspector.js # State inspection tools
63
+ └── stateSerializer.js # State serialization
64
+ └── examples/ # Example applications
65
+ └── 001-slider-and-cards/ # Advanced slider example
103
66
  ```
104
67
 
105
68
  ## Browser Support
@@ -111,63 +74,36 @@ document.getElementById('counter-btn').addEventListener('click', () => {
111
74
 
112
75
  # Core Ideas Behind UIstate
113
76
 
114
- UIstate is a JavaScript-based UI state management system that leverages CSS custom properties and data attributes as the storage mechanism, paired with event-based state transitions.
77
+ UIstate is a JavaScript-based UI state management system that leverages CSS custom properties and HTML-in-CSS templates for a fully declarative approach to building UIs.
115
78
 
116
79
  ## Key Components
117
80
 
118
- ### cssState
119
-
120
- The `cssState` module provides methods to manage state through CSS custom properties:
121
-
122
- ```javascript
123
- // Initialize CSS state management
124
- cssState.init();
125
-
126
- // Set a CSS custom property
127
- cssState.set('--theme-mode', 'dark');
128
-
129
- // Get a CSS custom property value
130
- const theme = cssState.get('--theme-mode');
131
- ```
132
-
133
- ### eventState
81
+ ### UIstate Core
134
82
 
135
- The `eventState` module provides an event system for state transitions:
83
+ The main UIstate object provides methods to manage state and templates:
136
84
 
137
- ```javascript
138
- // Listen for state changes
139
- eventState.on('theme:change', (newTheme) => {
140
- console.log('Theme changed to:', newTheme);
141
- });
85
+ - **init()**: Initialize the UIstate system
86
+ - **setState()**: Set state values
87
+ - **getState()**: Get state values
88
+ - **subscribe()**: Subscribe to state changes
89
+ - **observe()**: Observe state paths for changes
142
90
 
143
- // Trigger state changes
144
- eventState.emit('theme:change', 'light');
145
-
146
- // Clean up listeners
147
- eventState.off('theme:change');
148
- ```
91
+ ### Template Manager
149
92
 
150
- ### templateManager
93
+ The template manager provides tools for declarative UI rendering:
151
94
 
152
- The `templateManager` module helps with component initialization and templating:
153
-
154
- ```javascript
155
- // Initialize components from templates
156
- templateManager.init();
157
-
158
- // Create a component from a template
159
- const button = templateManager.createFromTemplate('button-template');
160
- document.body.appendChild(button);
161
- ```
95
+ - **renderTemplateFromCss()**: Render UI components from CSS-defined templates
96
+ - **registerActions()**: Register event handlers for UI components
97
+ - **attachDelegation()**: Set up event delegation for efficient event handling
162
98
 
163
99
  ## Key Features
164
100
 
165
101
  1. Uses CSS custom properties as a storage mechanism, making state changes automatically trigger UI updates
166
102
  2. Provides a clear separation between state storage (CSS) and behavior (JavaScript)
167
103
  3. Implements a pub/sub pattern for reactive updates
168
- 4. Leverages the CSS cascade for hierarchical state inheritance
104
+ 4. Leverages CSS templates for declarative UI definition
169
105
 
170
- This implementation is particularly useful for building UI components with clean separation of concerns and optimal performance.
106
+ This implementation is particularly useful for building UI components with clean separation of concerns, optimal performance, and a fully declarative approach.
171
107
 
172
108
  ## Contributing
173
109
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uistate/core",
3
- "version": "2.0.1",
3
+ "version": "3.0.0",
4
4
  "description": "High-performance UI state management using CSS custom properties and ADSI (Attribute-Driven State Inheritance)",
5
5
  "main": "src/index.js",
6
6
  "module": "src/index.js",
package/src/cssState.js CHANGED
@@ -1,12 +1,16 @@
1
1
  /**
2
- * UIstate - CSS-based state management module
2
+ * UIstate - CSS-based state management module with integrated serialization
3
3
  * Part of the UIstate declarative state management system
4
4
  * Uses CSS custom properties and data attributes for state representation
5
+ * Includes built-in serialization for complex objects and special characters
5
6
  */
6
- const createCssState = (initialState = {}) => {
7
+ import StateSerializer from './stateSerializer.js';
8
+
9
+ const createCssState = (initialState = {}, serializer = StateSerializer) => {
7
10
  const state = {
8
11
  _sheet: null,
9
12
  _observers: new Map(),
13
+ _serializer: serializer,
10
14
 
11
15
  init() {
12
16
  if (!this._sheet) {
@@ -27,20 +31,52 @@ const createCssState = (initialState = {}) => {
27
31
  },
28
32
 
29
33
  setState(key, value) {
30
- const cssValue = typeof value === 'string' ? value : JSON.stringify(value);
34
+ // Use serializer for CSS variables
35
+ const cssValue = this._serializer.serialize(key, value);
31
36
  document.documentElement.style.setProperty(`--${key}`, cssValue);
32
- document.documentElement.setAttribute(`data-${key}`, value);
37
+
38
+ // For data attributes, handle objects specially
39
+ if (value !== null && value !== undefined) {
40
+ if (typeof value === 'object') {
41
+ // Use the serializer for the data attribute value
42
+ document.documentElement.setAttribute(`data-${key}`, this._serializer.serialize(key, value));
43
+
44
+ // For objects, also set each property as a separate data attribute
45
+ if (!Array.isArray(value)) {
46
+ Object.entries(value).forEach(([propKey, propValue]) => {
47
+ const attributeKey = `data-${key}-${propKey.toLowerCase()}`;
48
+ if (propValue !== null && propValue !== undefined) {
49
+ if (typeof propValue === 'object') {
50
+ document.documentElement.setAttribute(
51
+ attributeKey,
52
+ this._serializer.serialize(`${key}.${propKey}`, propValue)
53
+ );
54
+ } else {
55
+ document.documentElement.setAttribute(attributeKey, propValue);
56
+ }
57
+ } else {
58
+ document.documentElement.removeAttribute(attributeKey);
59
+ }
60
+ });
61
+ }
62
+ } else {
63
+ // For primitives, set directly
64
+ document.documentElement.setAttribute(`data-${key}`, value);
65
+ }
66
+ } else {
67
+ document.documentElement.removeAttribute(`data-${key}`);
68
+ }
69
+
33
70
  this._notifyObservers(key, value);
34
71
  return value;
35
72
  },
36
73
 
37
74
  getState(key) {
38
75
  const value = getComputedStyle(document.documentElement).getPropertyValue(`--${key}`).trim();
39
- try {
40
- return JSON.parse(value);
41
- } catch (e) {
42
- return value;
43
- }
76
+ if (!value) return '';
77
+
78
+ // Use serializer for deserialization
79
+ return this._serializer.deserialize(key, value);
44
80
  },
45
81
 
46
82
  observe(key, callback) {
@@ -69,6 +105,14 @@ const createCssState = (initialState = {}) => {
69
105
  }
70
106
  },
71
107
 
108
+ // Add serializer configuration method
109
+ configureSerializer(config) {
110
+ if (this._serializer.configure) {
111
+ this._serializer.configure(config);
112
+ }
113
+ return this;
114
+ },
115
+
72
116
  // Clean up resources
73
117
  destroy() {
74
118
  this._observers.clear();