juxscript 1.1.266 → 1.1.268

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.
@@ -1,32 +1,16 @@
1
1
  declare class PageState {
2
2
  private _registry;
3
3
  private _proxy;
4
+ static readonly WIRE_EVENTS: readonly ["blur", "focus", "click", "dblclick", "change", "input", "keydown", "keyup", "keypress", "mouseenter", "mouseleave", "submit"];
4
5
  constructor();
5
6
  private _createComponentProxy;
6
- /**
7
- * Register a component with pageState.
8
- * Called automatically by jux components on creation.
9
- */
10
7
  private _register;
11
8
  private _wireEvent;
9
+ private _findElement;
12
10
  private _unregister;
13
- /**
14
- * Notify all reactive blocks that depend on this key
15
- */
16
11
  private _notify;
17
- /**
18
- * Create a reactive block that re-runs when its dependencies change.
19
- *
20
- * Usage:
21
- * pageState.__watch(() => {
22
- * if (pageState['input1'].value === 'blueberry') {
23
- * pageState['input2'].value = 'raspberry';
24
- * }
25
- * });
26
- */
27
12
  private _watch;
28
13
  getProxy(): Record<string, any>;
29
- __notify(depKey: string): void;
30
14
  }
31
15
  export declare const pageState: Record<string, any>;
32
16
  export { PageState };
@@ -1 +1 @@
1
- {"version":3,"file":"pageState.d.ts","sourceRoot":"","sources":["../../../lib/state/pageState.ts"],"names":[],"mappings":"AAaA,cAAM,SAAS;IACX,OAAO,CAAC,SAAS,CAA0C;IAC3D,OAAO,CAAC,MAAM,CAAsB;;IA6BpC,OAAO,CAAC,qBAAqB;IAkE7B;;;OAGG;IACH,OAAO,CAAC,SAAS;IA4CjB,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,OAAO,CAAC,OAAO;IAQf;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM;IAgBd,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAI/B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;CAOjC;AAID,eAAO,MAAM,SAAS,qBAAuB,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"pageState.d.ts","sourceRoot":"","sources":["../../../lib/state/pageState.ts"],"names":[],"mappings":"AAaA,cAAM,SAAS;IACX,OAAO,CAAC,SAAS,CAA0C;IAC3D,OAAO,CAAC,MAAM,CAAsB;IAEpC,MAAM,CAAC,QAAQ,CAAC,WAAW,2IAOhB;;IA2BX,OAAO,CAAC,qBAAqB;IAyD7B,OAAO,CAAC,SAAS;IA6CjB,OAAO,CAAC,UAAU;IAwBlB,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,OAAO;IAQf,OAAO,CAAC,MAAM;IAcd,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;CAGlC;AAID,eAAO,MAAM,SAAS,qBAAuB,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,CAAC"}
@@ -19,11 +19,9 @@ class PageState {
19
19
  const entry = this._registry.get(id);
20
20
  if (!entry)
21
21
  return undefined;
22
- // Return a proxy for the component's state slice
23
22
  return this._createComponentProxy(id, entry);
24
23
  },
25
24
  set: (_, id, value) => {
26
- // pageState['input1'] = someComponent — register it
27
25
  if (value && typeof value === 'object' && value.id) {
28
26
  this._register(value);
29
27
  return true;
@@ -36,27 +34,22 @@ class PageState {
36
34
  return new Proxy({}, {
37
35
  get: (_, prop) => {
38
36
  const depKey = `${id}.${prop}`;
39
- // Track dependency if inside a reactive block
40
37
  if (activeReaction) {
41
38
  if (!reactionDeps.has(activeReaction)) {
42
39
  reactionDeps.set(activeReaction, new Set());
43
40
  }
44
41
  reactionDeps.get(activeReaction).add(depKey);
45
42
  }
46
- // Event flags (blur, focus, hover, etc.)
47
43
  if (prop in entry.events) {
48
44
  return entry.events[prop];
49
45
  }
50
- // Component props (value, disabled, checked, etc.)
51
46
  if (prop in entry.props) {
52
47
  return entry.props[prop];
53
48
  }
54
- // ✅ Expose component methods directly (refresh, fetch, etc.)
55
49
  const comp = entry.component;
56
50
  if (typeof comp[prop] === 'function') {
57
51
  return comp[prop].bind(comp);
58
52
  }
59
- // Fallback: try getter pattern
60
53
  const getterName = `get${prop.charAt(0).toUpperCase()}${prop.slice(1)}`;
61
54
  if (typeof comp[getterName] === 'function') {
62
55
  return comp[getterName]();
@@ -68,7 +61,6 @@ class PageState {
68
61
  },
69
62
  set: (_, prop, value) => {
70
63
  const depKey = `${id}.${prop}`;
71
- // Update component via fluent API or setter
72
64
  const comp = entry.component;
73
65
  const setterName = `set${prop.charAt(0).toUpperCase()}${prop.slice(1)}`;
74
66
  if (typeof comp[setterName] === 'function') {
@@ -77,18 +69,12 @@ class PageState {
77
69
  else if (typeof comp[prop] === 'function') {
78
70
  comp[prop](value);
79
71
  }
80
- // Update tracked props
81
72
  entry.props[prop] = value;
82
- // Notify listeners
83
73
  this._notify(depKey);
84
74
  return true;
85
75
  }
86
76
  });
87
77
  }
88
- /**
89
- * Register a component with pageState.
90
- * Called automatically by jux components on creation.
91
- */
92
78
  _register(component) {
93
79
  const id = component.id;
94
80
  if (!id)
@@ -99,7 +85,6 @@ class PageState {
99
85
  events: {},
100
86
  listeners: new Map()
101
87
  };
102
- // Seed initial props from component
103
88
  if (component.getValue)
104
89
  entry.props.value = component.getValue();
105
90
  if (component.getValues)
@@ -115,7 +100,6 @@ class PageState {
115
100
  }
116
101
  entry.props.id = id;
117
102
  this._registry.set(id, entry);
118
- // Wire component onChange to update pageState
119
103
  if (typeof component.onChange === 'function') {
120
104
  const originalOnChange = component._onChange;
121
105
  component.onChange((val, e) => {
@@ -123,6 +107,10 @@ class PageState {
123
107
  entry.props.values = val;
124
108
  this._notify(`${id}.values`);
125
109
  }
110
+ else if (typeof val === 'boolean') {
111
+ entry.props.checked = val;
112
+ this._notify(`${id}.checked`);
113
+ }
126
114
  else {
127
115
  entry.props.value = val;
128
116
  this._notify(`${id}.value`);
@@ -131,31 +119,53 @@ class PageState {
131
119
  originalOnChange(val, e);
132
120
  });
133
121
  }
134
- // Wire common DOM events as boolean flags
135
- this._wireEvent(id, entry, 'blur');
136
- this._wireEvent(id, entry, 'focus');
122
+ for (const eventName of PageState.WIRE_EVENTS) {
123
+ this._wireEvent(id, entry, eventName);
124
+ }
137
125
  }
138
126
  _wireEvent(id, entry, eventName) {
139
127
  entry.events[eventName] = false;
140
- // Find the DOM element
141
- const el = entry.component._element || entry.component.getElement?.();
142
- if (!el || !(el instanceof HTMLElement))
128
+ const el = this._findElement(entry.component);
129
+ if (!el)
143
130
  return;
144
- el.addEventListener(eventName, () => {
131
+ el.addEventListener(eventName, (e) => {
145
132
  entry.events[eventName] = true;
133
+ if ((eventName === 'input' || eventName === 'change') && el instanceof HTMLInputElement) {
134
+ entry.props.value = el.value;
135
+ }
136
+ if ((eventName === 'input' || eventName === 'change') && el instanceof HTMLSelectElement) {
137
+ entry.props.value = el.value;
138
+ }
146
139
  this._notify(`${id}.${eventName}`);
147
- // Reset after reactions run
148
140
  queueMicrotask(() => {
149
141
  entry.events[eventName] = false;
150
142
  });
151
143
  });
152
144
  }
145
+ _findElement(component) {
146
+ if (component._element instanceof HTMLElement)
147
+ return component._element;
148
+ if (typeof component.getElement === 'function') {
149
+ const el = component.getElement();
150
+ if (el instanceof HTMLElement)
151
+ return el;
152
+ }
153
+ if (component._wrapper instanceof HTMLElement) {
154
+ const input = component._wrapper.querySelector('input, select, textarea, button');
155
+ if (input)
156
+ return input;
157
+ return component._wrapper;
158
+ }
159
+ if (component.id && typeof document !== 'undefined') {
160
+ const el = document.getElementById(component.id);
161
+ if (el)
162
+ return el;
163
+ }
164
+ return null;
165
+ }
153
166
  _unregister(id) {
154
167
  this._registry.delete(id);
155
168
  }
156
- /**
157
- * Notify all reactive blocks that depend on this key
158
- */
159
169
  _notify(depKey) {
160
170
  for (const [reaction, deps] of reactionDeps.entries()) {
161
171
  if (deps.has(depKey)) {
@@ -163,19 +173,8 @@ class PageState {
163
173
  }
164
174
  }
165
175
  }
166
- /**
167
- * Create a reactive block that re-runs when its dependencies change.
168
- *
169
- * Usage:
170
- * pageState.__watch(() => {
171
- * if (pageState['input1'].value === 'blueberry') {
172
- * pageState['input2'].value = 'raspberry';
173
- * }
174
- * });
175
- */
176
176
  _watch(fn) {
177
177
  const reaction = () => {
178
- // Clear old deps, track new ones during execution
179
178
  reactionDeps.set(reaction, new Set());
180
179
  activeReaction = reaction;
181
180
  try {
@@ -185,20 +184,20 @@ class PageState {
185
184
  activeReaction = null;
186
185
  }
187
186
  };
188
- // Run once immediately to collect initial dependencies
189
187
  reaction();
190
188
  }
191
189
  getProxy() {
192
190
  return this._proxy;
193
191
  }
194
- __notify(depKey) {
195
- for (const [reaction, deps] of reactionDeps.entries()) {
196
- if (deps.has(depKey)) {
197
- reaction();
198
- }
199
- }
200
- }
201
192
  }
193
+ PageState.WIRE_EVENTS = [
194
+ 'blur', 'focus',
195
+ 'click', 'dblclick',
196
+ 'change', 'input',
197
+ 'keydown', 'keyup', 'keypress',
198
+ 'mouseenter', 'mouseleave',
199
+ 'submit'
200
+ ];
202
201
  // Singleton
203
202
  const _instance = new PageState();
204
203
  export const pageState = _instance.getProxy();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "juxscript",
3
- "version": "1.1.266",
3
+ "version": "1.1.268",
4
4
  "type": "module",
5
5
  "description": "A JavaScript UX authorship platform",
6
6
  "main": "./dist/lib/index.js",