targetj 1.0.259 → 1.0.260

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/Export.js CHANGED
@@ -19,6 +19,10 @@ export * from "./build/AnimationUtil.js";
19
19
  export * from "./build/VisibilityUtil.js";
20
20
  export * from "./build/ScheduleUtil.js";
21
21
  export * from "./build/StateUtil.js";
22
+ export * from "./build/ParticleTModel.js";
23
+ export * from "./build/ParticleRenderer.js";
24
+ export * from "./build/ParticleRuntime.js";
25
+ export * from "./build/ParticleUtil.js";
22
26
 
23
27
  import * as AppModule from "./build/App.js";
24
28
  import * as TModelModule from "./build/TModel.js";
@@ -41,6 +45,10 @@ import * as AnimationUtilModule from "./build/AnimationUtil.js";
41
45
  import * as VisibilityUtilModule from "./build/VisibilityUtil.js";
42
46
  import * as ScheduleUtilModule from "./build/ScheduleUtil.js";
43
47
  import * as StateUtilModule from "./build/StateUtil.js";
48
+ import * as ParticleTModelModule from "./build/ParticleTModel.js";
49
+ import * as ParticleRendererModule from "./build/ParticleRenderer.js";
50
+ import * as ParticleRuntimeModule from "./build/ParticleRuntime.js";
51
+ import * as ParticleUtilModule from "./build/ParticleUtil.js";
44
52
 
45
53
  const TargetJS = {
46
54
  ...AppModule,
@@ -63,7 +71,11 @@ const TargetJS = {
63
71
  ...AnimationUtilModule,
64
72
  ...VisibilityUtilModule,
65
73
  ...ScheduleUtilModule,
66
- ...StateUtilModule
74
+ ...StateUtilModule,
75
+ ...ParticleTModelModule,
76
+ ...ParticleRendererModule,
77
+ ...ParticleRuntimeModule,
78
+ ...ParticleUtilModule
67
79
  };
68
80
 
69
81
  if (typeof window !== "undefined") {
package/README.md CHANGED
@@ -1,17 +1,13 @@
1
- # TargetJS: State Includes the Journey
1
+ # TargetJS: The "State → Transition → Render" Framework
2
2
 
3
3
  **Code order defines the UI sequence.**
4
4
 
5
- Most frameworks are great at rendering state. TargetJS is designed for the journey between states.
6
-
7
5
  **[targetjs.io](https://targetjs.io)**
8
6
  [![MIT LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/livetrails/targetjs/blob/main/LICENSE)
9
7
  [![Stars](https://img.shields.io/github/stars/livetrails/targetjs.svg)](https://github.com/livetrails/targetjs/stargazers)
10
8
  [![npm version](https://img.shields.io/npm/v/targetj.svg)](https://www.npmjs.com/package/targetj)
11
9
 
12
- TargetJS is a JavaScript UI framework that replaces the "State → Render" model with "State → Transition → Render".
13
-
14
- Transitions are part of the state itself. This allows the entire UI, including an animation in progress, to be captured and later restored from the exact point at which it was saved.
10
+ TargetJS is a JavaScript UI framework that transforms how applications handle state and execution flow. Instead of treating state merely as data for rendering, TargetJS integrates the active UI runtime including in-progress animation and execution flow directly into the state itself. This unified state approach allows developers to capture and restore the exact state of an interface at any millisecond.
15
11
 
16
12
  TargetJS also lets code order directly define the UI sequence. UI, transitions, API calls, event handling, and state are unified into self-contained Targets that chain together through Code-Ordered Reactivity.
17
13
 
@@ -22,13 +18,9 @@ It can be used as a full-featured framework or as a lightweight library alongsid
22
18
 
23
19
  **UI frameworks model the final result, not the transition**
24
20
 
25
- Traditional frameworks model the UI as a function of state: change state, re-render the UI. When state changes from A → B, the UI immediately jumps to B. The framework doesn’t naturally represent the journey from A → B. But modern, rich user experiences are more like: A → transition → B.
26
-
27
- TargetJS makes that transition part of the state change itself. Values are not limited to being assigned immediately. They can move toward their destination over configurable steps, intervals, and easing. Transitions therefore become a native part of the UI model rather than effects added after rendering. TargetJS also delivers CSS-level transition efficiency.
28
-
29
- Because each Target has its own lifecycle, transitions can also adapt dynamically. For example, pausing when an element leaves the screen or changing speed on scroll.
21
+ Traditional frameworks model the UI as a function of data: change data, re-render the UI. When data changes from A → B, the UI immediately jumps to render B. The framework doesn’t naturally represent the journey from A → B. But modern, rich user experiences are more like: A → transition → B.
30
22
 
31
- Since the transition belongs to the runtime state, the UI can be captured while a transition is in progress. That state can later be restored, allowing the transition to resume from the point at which it was saved.
23
+ TargetJS redefines state to include both the transition and the active UI runtime. This allows transitions to adapt dynamically on the fly, for example, pausing when an element leaves the screen or changing speed on scroll. It also allows the entire UI to be captured mid-animation and restored later, resuming exactly where it left off.
32
24
 
33
25
  **Fragmentation across multiple mental models**
34
26
 
@@ -46,14 +38,12 @@ In traditional code, that sequence is often scattered across different places su
46
38
 
47
39
  TargetJS code order and target reactivity allow the implementation to more closely mirror the actual UI sequence.
48
40
 
49
- With its compact style, TargetJS makes the journey from A → B explicit and efficient, with significantly less code than traditional frameworks.
50
-
51
41
  ## 🚀 Why TargetJS?
52
42
 
53
- 1. Unified State: One single state. Transitions are state too.
54
- 1. Adaptive Transitions: Transitions can pause, resume, change speed, and respond to input.
55
- 1. Restorable UI: Capture the UI during a transition and later resume the complete state including the transition from the saved point.
43
+ 1. Unified State: UI values, transitions, and runtime execution are part of the same state.
44
+ 1. Restorable UI and Runtime: UI and runtime state can be captured and later the complete state can be restored including transitions and execution flow from the saved point.
56
45
  1. UI as Sequence: Code describes the UI story from top to bottom, just like the user experiences the interaction: "When this finishes, do that."
46
+ 1. Adaptive Transitions: Transitions can pause, resume, change speed, and respond to input.
57
47
  1. Ultra-Compact: Minimal code, with no coordination variables.
58
48
  1. Zero Boilerplate Async: Targets handle waiting for nested asynchronous operations automatically.
59
49
  1. Animation by Default: Turn value into high-performance animations simply by adding `steps`.
@@ -76,7 +66,9 @@ bounce → move → turn red → log
76
66
 
77
67
  Notice how the code reads in the same order as the UI sequence. The `$$` suffix makes each target wait for all preceding targets to complete.
78
68
 
79
- There is only one state, and the transitions are part of that state. Click the square while it is animating to save its current state. Click it again to restore the state and resume the animation from the exact point at which it was saved.
69
+ Click the square while it is animating to capture its current state. Click it again to restore that state and resume the animation from the exact point at which it was saved.
70
+
71
+ The checkpoint captures more than the square's visual state. It captures the runtime behind it including transition progress and pending targets. Restoring it resumes the whole sequence from that exact point, not just what was on screen. You can try the example at https://targetjs.io/examples/firstExample.html
80
72
 
81
73
  ```javascript
82
74
  import { App, state } from "targetj";
@@ -91,19 +83,18 @@ App({
91
83
  scale: { value: [0.5, 1.2, 1], steps: 100 },
92
84
 
93
85
  // $$ waits for the previous target to finish.
94
- x$$: { value: [0, 180], steps: 100 },
86
+ x$$: { value: [0, 180], steps: 200 },
95
87
 
96
88
  backgroundColor$$: {
97
89
  value: "crimson",
98
- steps: 100
90
+ steps: 200
99
91
  },
100
92
 
101
93
  done$$() {
102
94
  console.log("Sequence complete");
103
95
  },
104
96
 
105
- // Click once to save the state.
106
- // Click again to restore it including animation progress.
97
+ // 1st click: save a checkpoint. 2nd click: restore it and resume.
107
98
  onClick() {
108
99
  state().toggle();
109
100
  }
@@ -159,7 +150,7 @@ Target names can include special suffixes that determine when they execute. This
159
150
  | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
160
151
  | `name` | Standard | Runs immediately in code order unless `active` is `false`. |
161
152
  | `name$` | Reactive | Runs whenever the preceding sibling Target updates. Similar to activating the next Target from `onValueChange()` or `on<PropertyName>Step()`. |
162
- | `name$$` | Deferred | Runs after the entire preceding Target chain—including children, animations, and API calls—has completed. Similar to activating the next Target from `onComplete()`. |
153
+ | `name$$` | Deferred | Runs after the entire preceding Target chain including children, animations, and API calls has completed. Similar to activating the next Target from `onComplete()`. |
163
154
 
164
155
  To prevent a Target from running automatically, set `active: false` and activate it later with `.activateTarget()`.
165
156
 
@@ -255,8 +246,10 @@ App({
255
246
  this.setTarget('y', { value: [0, -120], steps: 400 });
256
247
  }
257
248
  },
258
- fetch$$: { method: "POST", id: 123, url: "/api/like" }, // Wait for the heart to finish, THEN fetch
259
- removeHearts$$() { this.removeChildren(); }, // Wait for fetch to finish, THEN cleanup
249
+ // Wait for the nested animation in heart$$ to finish , then fetch
250
+ fetch$$: { method: "POST", id: 123, url: "/api/like" },
251
+ // Wait for fetch to finish, then cleanup
252
+ removeHearts$$() { this.removeChildren(); },
260
253
  onKey(e) { if (e.key === "Enter") this.activateTarget("onClick"); }
261
254
  }).mount("#likeButton");
262
255
  ```
@@ -239,17 +239,10 @@ var AnimationUtil = /*#__PURE__*/function () {
239
239
  } finally {
240
240
  _iterator2.f();
241
241
  }
242
- var now = TUtil.now();
243
242
  for (var _i4 = 0, _records2 = records; _i4 < _records2.length; _i4++) {
244
243
  var record = _records2[_i4];
245
244
  var originalKey = record.originalKey;
246
- var targetValue = tmodel.targetValues[originalKey];
247
- if (!targetValue) {
248
- continue;
249
- }
250
- targetValue.catchupAt = now;
251
- tmodel.removeFromAnimatingMap(originalKey);
252
- (tmodel.noDomUpdatingTargets || (tmodel.noDomUpdatingTargets = new Set())).add(originalKey);
245
+ tmodel.addToNoDomUpdatingTargets(originalKey);
253
246
  }
254
247
  }
255
248
  }, {
package/build/App.js CHANGED
@@ -25,6 +25,7 @@ import { TUtil } from "./TUtil.js";
25
25
  import { DomInit } from "./DomInit.js";
26
26
  import { SearchUtil } from "./SearchUtil.js";
27
27
  import { TModelUtil } from "./TModelUtil.js";
28
+ import "./ParticleTModel.js";
28
29
  var tApp;
29
30
  var queuedAppCalls = [];
30
31
  var AppFn = function AppFn() {
@@ -85,7 +86,7 @@ var AppFn = function AppFn() {
85
86
  if (t.val('sourceDom')) {
86
87
  return;
87
88
  }
88
- var child = new TModel(t.type, t.targets);
89
+ var child = TargetExecutor.createTModel(t.type, t.targets);
89
90
  tmodel.addChild(child);
90
91
  });
91
92
  }
@@ -199,7 +200,7 @@ var App = function App(firstChild) {
199
200
  if (!firstChild) {
200
201
  return;
201
202
  }
202
- var tmodel = firstChild instanceof TModel ? firstChild : new TModel("App", firstChild);
203
+ var tmodel = firstChild instanceof TModel ? firstChild : TargetExecutor.createTModel("App", firstChild);
203
204
  if (!((_tApp2 = tApp) !== null && _tApp2 !== void 0 && _tApp2.tRoot)) {
204
205
  if (document.readyState === "loading") {
205
206
  queuedAppCalls.push(tmodel);
@@ -1027,6 +1027,27 @@ var BaseModel = /*#__PURE__*/function () {
1027
1027
  (_this$getParent4 = this.getParent()) === null || _this$getParent4 === void 0 || _this$getParent4.addToUpdatingChildren(this);
1028
1028
  }
1029
1029
  }
1030
+ }, {
1031
+ key: "addToNoDomUpdatingTargets",
1032
+ value: function addToNoDomUpdatingTargets(key) {
1033
+ var _this$getParent5;
1034
+ var targetValue = this.targetValues[key];
1035
+ if (!targetValue) {
1036
+ return false;
1037
+ }
1038
+ var noDomTargets = this.noDomUpdatingTargets || (this.noDomUpdatingTargets = new Set());
1039
+ if (noDomTargets.has(key)) {
1040
+ return false;
1041
+ }
1042
+ targetValue.catchupAt = TUtil.now();
1043
+ noDomTargets.add(key);
1044
+ this.removeFromAnimatingMap(key);
1045
+ this.removeFromUpdatingTargets(key);
1046
+ this.resetScheduleTimeStamp(key);
1047
+ this.resetScheduleRemainingTime(key);
1048
+ (_this$getParent5 = this.getParent()) === null || _this$getParent5 === void 0 || _this$getParent5.addToUpdatingChildren(this);
1049
+ return true;
1050
+ }
1030
1051
  }, {
1031
1052
  key: "removeFromUpdatingTargets",
1032
1053
  value: function removeFromUpdatingTargets(key) {
@@ -1038,8 +1059,8 @@ var BaseModel = /*#__PURE__*/function () {
1038
1059
  }
1039
1060
  }
1040
1061
  if (this.updatingTargetList.length === 0) {
1041
- var _this$getParent5;
1042
- (_this$getParent5 = this.getParent()) === null || _this$getParent5 === void 0 || _this$getParent5.removeFromUpdatingChildren(this);
1062
+ var _this$getParent6;
1063
+ (_this$getParent6 = this.getParent()) === null || _this$getParent6 === void 0 || _this$getParent6.removeFromUpdatingChildren(this);
1043
1064
  }
1044
1065
  }
1045
1066
  }, {
@@ -1096,8 +1117,8 @@ var BaseModel = /*#__PURE__*/function () {
1096
1117
  }, {
1097
1118
  key: "hasAnyUpdates",
1098
1119
  value: function hasAnyUpdates() {
1099
- var _this$animatingMap$si, _this$animatingMap3;
1100
- return this.updatingTargetList.length !== 0 || this.activeTargetList.length !== 0 || ((_this$animatingMap$si = (_this$animatingMap3 = this.animatingMap) === null || _this$animatingMap3 === void 0 ? void 0 : _this$animatingMap3.size) !== null && _this$animatingMap$si !== void 0 ? _this$animatingMap$si : 0) !== 0;
1120
+ var _this$animatingMap$si, _this$animatingMap3, _this$noDomUpdatingTa, _this$noDomUpdatingTa2;
1121
+ return this.updatingTargetList.length !== 0 || this.activeTargetList.length !== 0 || ((_this$animatingMap$si = (_this$animatingMap3 = this.animatingMap) === null || _this$animatingMap3 === void 0 ? void 0 : _this$animatingMap3.size) !== null && _this$animatingMap$si !== void 0 ? _this$animatingMap$si : 0) !== 0 || ((_this$noDomUpdatingTa = (_this$noDomUpdatingTa2 = this.noDomUpdatingTargets) === null || _this$noDomUpdatingTa2 === void 0 ? void 0 : _this$noDomUpdatingTa2.size) !== null && _this$noDomUpdatingTa !== void 0 ? _this$noDomUpdatingTa : 0) !== 0;
1101
1122
  }
1102
1123
  }, {
1103
1124
  key: "removeFromAnimatingMap",
@@ -1106,28 +1127,28 @@ var BaseModel = /*#__PURE__*/function () {
1106
1127
  if ((_this$animatingMap4 = this.animatingMap) !== null && _this$animatingMap4 !== void 0 && _this$animatingMap4.has(key)) {
1107
1128
  this.animatingMap.delete(key);
1108
1129
  if (this.animatingMap.size === 0) {
1109
- var _this$getParent6;
1110
- (_this$getParent6 = this.getParent()) === null || _this$getParent6 === void 0 || _this$getParent6.removeFromAnimatingChildren(this);
1130
+ var _this$getParent7;
1131
+ (_this$getParent7 = this.getParent()) === null || _this$getParent7 === void 0 || _this$getParent7.removeFromAnimatingChildren(this);
1111
1132
  }
1112
1133
  }
1113
1134
  }
1114
1135
  }, {
1115
1136
  key: "clearAnimatingMap",
1116
1137
  value: function clearAnimatingMap() {
1117
- var _this$animatingMap5, _this$getParent7;
1138
+ var _this$animatingMap5, _this$getParent8;
1118
1139
  (_this$animatingMap5 = this.animatingMap) === null || _this$animatingMap5 === void 0 || _this$animatingMap5.clear();
1119
- (_this$getParent7 = this.getParent()) === null || _this$getParent7 === void 0 || _this$getParent7.removeFromAnimatingChildren(this);
1140
+ (_this$getParent8 = this.getParent()) === null || _this$getParent8 === void 0 || _this$getParent8.removeFromAnimatingChildren(this);
1120
1141
  }
1121
1142
  }, {
1122
1143
  key: "addToAnimatingMap",
1123
1144
  value: function addToAnimatingMap(key) {
1124
- var _this$targetValues$ke24, _this$getParent8;
1145
+ var _this$targetValues$ke24, _this$getParent9;
1125
1146
  if ((_this$targetValues$ke24 = this.targetValues[key]) !== null && _this$targetValues$ke24 !== void 0 && _this$targetValues$ke24.snapAnimation) {
1126
1147
  return;
1127
1148
  }
1128
1149
  this.animatingMap || (this.animatingMap = new Map());
1129
1150
  this.animatingMap.set(key, true);
1130
- (_this$getParent8 = this.getParent()) === null || _this$getParent8 === void 0 || _this$getParent8.addToAnimatingChildren(this);
1151
+ (_this$getParent9 = this.getParent()) === null || _this$getParent9 === void 0 || _this$getParent9.addToAnimatingChildren(this);
1131
1152
  }
1132
1153
  }, {
1133
1154
  key: "getAnimatingTargets",