@uistate/core 2.0.0 → 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,122 +1,68 @@
1
- # @uistate/core
1
+ # @uistate/core v3.0.0
2
2
 
3
- **author**: Ajdin Imsirovic <ajdika@live.com> (GitHub),
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 a number of other novel ideas. Focused heavily on DX and performance, in that order.
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
- - ~~🚀 44% faster state updates than Redux~~ Potentially O(1) state updates!
11
- - ~~📉 12.5% lower memory usage~~ Large memory usage savings (perf pending...)
18
+ - 🚀 O(1) state updates using CSS custom properties
19
+ - 📉 Significant memory savings compared to virtual DOM approaches
12
20
  - 🎯 Zero configuration
13
- - 🔄 Automatic reactivity
21
+ - 🔄 Automatic reactivity through CSS cascade
14
22
  - 🎨 Framework agnostic
15
- - 📦 Tiny bundle size (~1KB)
16
- - ~~💪 Full TypeScript support~~ Sorry, JS-only for a while...
17
- - ~~📊 Optional performance monitoring~~ In progress (perf pending...)
23
+ - 📦 Tiny bundle size (~2KB)
24
+ - 🧩 Modular architecture with dedicated modules for CSS state and templates
25
+ - 📝 Declarative HTML-in-CSS templates
18
26
 
19
27
  ## Installation
20
28
 
21
29
  ```bash
22
- # Install the core package
23
30
  npm install @uistate/core
24
-
25
- # Optional: Install performance monitoring
26
- npm install @uistate/performance
27
- ```
28
-
29
- ## Quick Start
30
-
31
- ```typescript
32
- import { UIState } from '@uistate/core';
33
-
34
- // Initialize state
35
- UIState.init();
36
-
37
- // Set state
38
- UIState.setState('count', 0);
39
-
40
- // Get state
41
- const count = UIState.getState('count');
42
-
43
- // Subscribe to changes
44
- const unsubscribe = UIState.observe('count', (newValue) => {
45
- console.log('Count changed:', newValue);
46
- });
47
-
48
- // React Hook
49
- import { useUIState } from '@uistate/core/react';
50
-
51
- function Counter() {
52
- const [count, setCount] = useUIState('count', 0);
53
- return (
54
- <button onClick={() => setCount(count + 1)}>
55
- Count: {count}
56
- </button>
57
- );
58
- }
59
31
  ```
60
32
 
61
33
  ## Why @uistate/core?
62
34
 
63
35
  ### Performance
64
36
 
65
- - **44% Faster Updates**: Leverages browser's CSS engine for optimal performance
66
- - **12.5% Lower Memory**: Efficient state storage using CSS custom properties
67
- - **Minimal Overhead**: No virtual DOM diffing for state updates
37
+ - **CSS-Driven Updates**: Leverages browser's CSS engine for optimal performance with O(1) complexity
38
+ - **DOM as Source of Truth**: Efficient state storage using CSS custom properties and data attributes
39
+ - **Minimal Overhead**: No virtual DOM diffing or shadow DOM needed
68
40
 
69
41
  ### Developer Experience
70
42
 
71
- - **Simple API**: Just `setState`, `getState`, and `observe`
72
- - **TypeScript Support**: Full type safety and autocompletion
73
- - **Framework Agnostic**: Works with any framework
43
+ - **Declarative API**: Define UI structure in CSS templates
44
+ - **Framework Agnostic**: Works with any framework or vanilla JavaScript
74
45
  - **Zero Config**: No store setup, no reducers, no actions
46
+ - **CSS-Native**: Leverages the power of CSS selectors and the cascade
75
47
 
76
- ## Performance Monitoring
77
-
78
- The `@uistate/performance` package provides detailed performance metrics for your application:
48
+ ### Core Concepts
79
49
 
80
- ```typescript
81
- import { PerformanceTracker } from '@uistate/performance';
82
- import { PerformanceDisplay } from '@uistate/performance';
83
-
84
- // Start tracking performance
85
- const tracker = PerformanceTracker.getInstance();
86
- tracker.start();
87
-
88
- // Optional: Add the performance display component to your React app
89
- function App() {
90
- return (
91
- <div>
92
- <YourApp />
93
- <PerformanceDisplay />
94
- </div>
95
- );
96
- }
97
- ```
98
-
99
- The performance tracker monitors:
100
- - State update duration
101
- - Component render time
102
- - FPS (Frames Per Second)
103
- - Memory usage
104
- - Long task duration
50
+ - **Attribute-Driven State Inheritance (ADSI)**: State represented both as CSS variables and data attributes
51
+ - **Declarative Templates**: Define UI components directly in CSS
52
+ - **Automatic State Propagation**: State changes automatically update the UI
105
53
 
106
54
  ## Project Structure
107
55
 
108
56
  ```
109
57
  @uistate/core/
110
- ├── src/ # Core library
111
- │ ├── index.ts # Main entry
112
- │ ├── UIState.ts # Core implementation
113
- └── react/ # React bindings
114
- └── index.ts # React hooks
115
- ├── packages/
116
- └── performance/ # Performance monitoring package
117
- └── examples/ # Example applications
118
- ├── traditional/ # Traditional Redux app
119
- └── uistate/ # UIState implementation
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
120
66
  ```
121
67
 
122
68
  ## Browser Support
@@ -126,72 +72,38 @@ The performance tracker monitors:
126
72
  - Safari 10.1+
127
73
  - Edge 79+
128
74
 
129
- # Explanation of the Core Ideas Behind the UI State Management System
75
+ # Core Ideas Behind UIstate
130
76
 
131
- A TypeScript-based UI state management system that leverages CSS custom properties (CSS variables) as the storage mechanism.
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.
132
78
 
133
79
  ## Key Components
134
80
 
135
- ### Type Definitions
136
-
137
- ```typescript
138
- type StateObserver<T> = (value: T) => void;
139
- interface UIStateType { ... }
140
- ```
141
-
142
- - Defines a type for state change observers (callbacks)
143
- - Defines the interface for the state management system
144
-
145
- ## Core Functionality
146
-
147
- The `UIState` object provides several key methods:
81
+ ### UIstate Core
148
82
 
149
- ### `init()`
150
- - Creates a style element in the document head
151
- - Initializes a CSS stylesheet for managing custom properties
152
- - Returns the UIState instance for chaining
83
+ The main UIstate object provides methods to manage state and templates:
153
84
 
154
- ### `setState<T>(key: string, value: T)`
155
- - Stores values as CSS custom properties (--key)
156
- - Converts non-string values to JSON strings
157
- - Notifies observers when values change
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
158
90
 
159
- ### `getState<T>(key: string)`
160
- - Retrieves values from CSS custom properties
161
- - Attempts to parse JSON values back to their original type
162
- - Falls back to raw string if parsing fails
91
+ ### Template Manager
163
92
 
164
- ### `observe<T>(key: string, callback)`
165
- - Implements an observer pattern for state changes
166
- - Returns a cleanup function to remove the observer
167
- - Allows multiple observers per state key
93
+ The template manager provides tools for declarative UI rendering:
168
94
 
169
- ## Internal Mechanisms
170
-
171
- ```typescript
172
- _sheet: CSSStyleSheet | null // Stores the stylesheet reference
173
- _observers: Map<string, Set<StateObserver>> // Stores observers per key
174
- ```
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
175
98
 
176
99
  ## Key Features
177
100
 
178
101
  1. Uses CSS custom properties as a storage mechanism, making state changes automatically trigger UI updates
179
- 2. Provides type safety through TypeScript generics
180
- 3. Implements the observer pattern for reactive updates
181
- 4. Handles serialization/deserialization of complex data types through JSON
182
-
183
- ## Example Usage
184
-
185
- ```typescript
186
- UIState.init();
187
- UIState.setState('theme', 'dark');
188
- UIState.observe('theme', (newValue) => {
189
- console.log('Theme changed to:', newValue);
190
- });
191
- const currentTheme = UIState.getState<string>('theme');
192
- ```
102
+ 2. Provides a clear separation between state storage (CSS) and behavior (JavaScript)
103
+ 3. Implements a pub/sub pattern for reactive updates
104
+ 4. Leverages CSS templates for declarative UI definition
193
105
 
194
- This implementation is particularly useful for managing global UI state like themes, layout preferences, or any other state that might affect multiple components simultaneously.
106
+ This implementation is particularly useful for building UI components with clean separation of concerns, optimal performance, and a fully declarative approach.
195
107
 
196
108
  ## Contributing
197
109
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uistate/core",
3
- "version": "2.0.0",
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();