targetj 1.0.225 → 1.0.227

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,4 +1,4 @@
1
- # TargetJS: UI Development as a Sequence
1
+ # TargetJS: State as Destination, UI as Sequence
2
2
 
3
3
  **[targetjs.io](https://targetjs.io)**
4
4
  [![MIT LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/livetrails/targetjs/blob/main/LICENSE)
@@ -10,19 +10,31 @@ TargetJS is a high-performance JavaScript UI framework with ultra-compact syntax
10
10
  It can be used as a full-featured framework or as a lightweight library alongside other frameworks. It is also a highly performant web framework, as shown in the [framework benchmark](https://krausest.github.io/js-framework-benchmark/current.html).
11
11
 
12
12
 
13
- ## The Philosophy Behind TargetJS
13
+ ## What problems TargetJS solves
14
14
 
15
- Traditional frameworks model the UI as a function of state: change state, re-render the UI. When state changes from A to B, the UI immediately jumps to B. The framework doesn’t naturally represent the *journey* from A to B. But modern, rich user experiences are journeys, not jumps. They are built on sequences that unfold over time. For example:
15
+ **UI frameworks model the final result, not transition**
16
16
 
17
- > Click Animate button Chain secondary animation Fetch data Render listAnimate itemsPauseAnimate an important item
17
+ 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.
18
18
 
19
- TargetJS is built for this reality. Instead of managing complex flags, your code structure mirrors these sequences directly.
19
+ TargetJS treats state as a destination. Values are not only assigned. They can be approached over time through configurable steps. This makes transitions a native part of state change rather than an afterthought. TargetJS also delivers CSS-level transition efficiency.
20
20
 
21
- It achieves this through Targets. A Target is a self-contained unit that merges data (fields) and logic (methods) into a single reactive block. Each Target has its own internal state, timing, and lifecycle, acting like a living cell within your app. By simply ordering them in your code, you create complex asynchronous workflows without async/await or .then() chains.
21
+ **Fragmentation across multiple mental models**
22
22
 
23
- In addition, efficient animation is built directly into the framework using the Web Animations API, delivering CSS-level efficiency.
23
+ In many applications, state, animation, events, loading, timing, and callbacks are all handled through separate concepts or APIs. This creates glue code and a mental split between them.
24
24
 
25
- By adopting a compact style, TargetJS makes the journey from A to B efficient and explicit, with significantly less code than traditional frameworks.
25
+ TargetJS unifies them under one concept and one model. Methods and fields are unified and both become reactive units with their own state, lifecycle, timing, execution conditions, looping, and callbacks. This shifts fields from passive values to active participants, reducing boilerplate and keeping application logic consolidated.
26
+
27
+ **UI sequences are difficult to trace in code**
28
+
29
+ UIs often follow sequences like this:
30
+
31
+ Click → animate button → fetch data → render results → animate items → highlight one item
32
+
33
+ In traditional code, that sequence is often scattered across different places such as event handlers, effects, promises, and callbacks.
34
+
35
+ TargetJS code order and target reactivity allow the implementation to more closely mirror the actual UI sequence.
36
+
37
+ With its compact style, TargetJS makes the journey from A → B efficient and explicit, with significantly less code than traditional frameworks.
26
38
 
27
39
  ## ⚡ Quick Start (30 Seconds)
28
40
 
@@ -48,17 +60,39 @@ App({
48
60
  }).mount("#app");
49
61
  ```
50
62
 
51
- ## Understanding TargetJS Syntax
63
+ ## Targets
64
+
65
+ In TargetJS, targets are the fundamental unit of behavior.
66
+ Methods, properties, and objects are internally transformed into targets that the framework schedules and executes.
67
+
68
+
69
+ ### Execution Syntax
52
70
 
53
- These symbols tell the framework **when** a target should run.
71
+ Target names can include special symbols that determine **when they execute**.
54
72
 
55
- | Symbol | Name | Behavior |
56
- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------|
57
- | `name` | Standard | Runs immediately in the order it appears. |
58
- | `name$` | Reactive | Runs every time the previous sibling target runs. |
59
- | `name$$` | Deferred | Runs only after the entire preceding target chain including children, animations, and API calls has fully completed. |
60
- | `_name` | Inactive | Does not run automatically. Trigger it manually via `.activateTarget()`. |
61
-
73
+ | Symbol | Name | Behavior |
74
+ |------|------|------|
75
+ | `name` | Standard | Runs immediately in the order it appears. |
76
+ | `name$` | Reactive | Runs every time the previous sibling target runs. |
77
+ | `name$$` | Deferred | Runs only after the entire preceding target chain (including children, animations, and API calls) completes. |
78
+ | `_name` | Inactive | Does not run automatically. Trigger it manually via `.activateTarget()`. |
79
+
80
+
81
+ ### Target Controls
82
+
83
+ A target can also be defined as an object with optional controls that manage its lifecycle and execution.
84
+
85
+ | Property | Description |
86
+ |------|------|
87
+ | `value` | The data or function that determines the target's state. |
88
+ | `steps` | Turns a value change into an animation. |
89
+ | `interval` | Delay (ms) between steps or executions. |
90
+ | `cycles` | Number of times the target repeats. |
91
+ | `loop` | Boolean form of repetition for continuous execution. |
92
+ | `enabledOn` | Determines whether the target is enabled for execution. |
93
+ | `easing` | Predefined easing function controlling how values update over steps. |
94
+ | `onComplete` | Callback triggered when this target (and its children) finishes. |
95
+ | `onValueChange` | Callback triggered when the target emits a new value. |
62
96
 
63
97
  ## Examples: Like Button → Animated Like (in 3 Steps)
64
98
 
@@ -112,7 +146,7 @@ App({
112
146
  this.setTarget('backgroundColor', { value: [ '#ffe8ec', '#f5f5f5' ], steps: 12, interval: 12 });
113
147
  },
114
148
  heart$$: { // Wait for the button animation to finish, THEN add and animate the heart.
115
- html: "♥", color: "crimson", fontSize: 20;
149
+ html: "♥", color: "crimson", fontSize: 20,
116
150
  fly() {
117
151
  const cx = (this.parent.getWidth() - this.getWidth()) / 2;
118
152
  this.setTarget('x', { value: [cx, cx + 22, cx - 16, cx + 10, cx ], steps: 50, cycles: 2 }); // Repeat it twice
@@ -172,7 +206,6 @@ Each target has its own state and lifecycle. Targets execute automatically in th
172
206
  1. Deeper Examples:
173
207
  - [Loading Five Users Example](#loading-five-users-example)
174
208
  - [Infinite Loading and Scrolling Example](#infinite-loading-and-scrolling-example)
175
- 1. [Target Methods](#target-methods)
176
209
  1. [Special Target Names](#special-target-names)
177
210
  1. [How to Debug in TargetJS](#how-to-debug-in-targetjs)
178
211
  1. [Documentation](#documentation)
@@ -421,46 +454,42 @@ App({
421
454
  ```
422
455
  ---
423
456
 
424
- ## Technical Reference
425
-
426
- ### Target Methods
427
-
428
- Every target can be an object with these optional controls:
429
-
430
- 1. **value**
431
- The data or function that determines the target's state.
457
+ ## Special Target Names
432
458
 
433
- 1. **steps**
434
- Turns a value change into an animation (e.g., steps: 20).
459
+ Some target names have built-in meaning and interact directly with the DOM, layout system, or browser events.
460
+ Because these behaviors are expressed as targets, they still participate in the same execution system and dependency flows as any other target.
435
461
 
436
- 1. **interval**
437
- The delay (ms) between steps or executions.
462
+ **Styles**
438
463
 
439
- 1. **cycles**
440
- How many times to repeat the target.
464
+ These targets update CSS properties and transforms:
441
465
 
442
- 1. **onComplete**
443
- Callback when this target (and its children) finishes.
466
+ - `width`, `height`
467
+ - `opacity`
468
+ - `x`, `y`, `z`
469
+ - `rotate`, `rotateX`, `rotateY`, `rotateZ`
470
+ - `scale`
471
+ - `backgroundColor`, `color`
444
472
 
445
- 1. **enabledOn**
446
- Determines whether the target is enabled for execution.
473
+ These can be animated simply by adding `steps`.
447
474
 
448
- 1. **loop**
449
- Managed the repetition of target execution. Similar to `cycles` but uses boolean instead.
475
+ **Structure**
450
476
 
451
- 1. **easing**
452
- A string that defines a predefined easing function that controls how the actual value is updated in relation to the steps.
477
+ These targets define the structure of the interface:
453
478
 
454
- 1. **onValueChange**
455
- This callback is triggered when `value` emits a new value.
479
+ - `children` or `addChildren` – adds new children each time the target executes
480
+ - `html` inner HTML content, often simple text
481
+ - `element` – specify the DOM element type (e.g., `div`, `canvas`)
456
482
 
457
- ### Special Target Names
483
+ **Events**
458
484
 
459
- TargetJS maps directly to the DOM for zero-friction styling. For example:
485
+ These targets respond to browser events:
460
486
 
461
- - **Styles**: `width`, `height`, `opacity`, `x`, `y`, `rotate`, `scale`, `backgroundColor`.
462
- - **Structure**: `html`, `children`, `element`, `domHolder`.
463
- - **Events**: `onClick`, `onScroll`, `onKey`, `onVisibleChildrenChange`, `onResize`.
487
+ - `onClick`
488
+ - `onScroll`
489
+ - `onKey`
490
+ - `onResize`
491
+ - `onEnter` / `onLeave`
492
+ - `onVisibleChildrenChange`
464
493
 
465
494
  ## How to Debug in TargetJS
466
495
 
@@ -124,16 +124,11 @@ var LoadingManager = exports.LoadingManager = /*#__PURE__*/function () {
124
124
  value: function getTModelKey(tmodel, targetName) {
125
125
  return "".concat(document.URL, "_").concat(tmodel.oid, "_").concat(targetName);
126
126
  }
127
- }, {
128
- key: "getLoadTargetName",
129
- value: function getLoadTargetName(targetName) {
130
- return "load-".concat(targetName);
131
- }
132
127
  }, {
133
128
  key: "addToTModelKeyMap",
134
129
  value: function addToTModelKeyMap(tmodel, targetName, fetchId, cacheId) {
135
130
  var key = this.getTModelKey(tmodel, targetName);
136
- var loadTargetName = this.getLoadTargetName(targetName);
131
+ var loadTargetName = _TUtil.TUtil.getLoadTargetName(targetName);
137
132
  var loadingComplete = this.isLoadingComplete(tmodel, targetName);
138
133
  if (loadingComplete || !this.tmodelKeyMap[key]) {
139
134
  var _this$tmodelKeyMap, _this$tmodelKeyMap$ke;
@@ -215,7 +210,7 @@ var LoadingManager = exports.LoadingManager = /*#__PURE__*/function () {
215
210
  if (!modelEntry) {
216
211
  return false;
217
212
  }
218
- var loadTargetName = this.getLoadTargetName(targetName);
213
+ var loadTargetName = _TUtil.TUtil.getLoadTargetName(targetName);
219
214
  var targetValue = tmodel.val(loadTargetName);
220
215
  return Array.isArray(targetValue) && _TUtil.TUtil.isDefined(targetValue[modelEntry.activeIndex]);
221
216
  }
@@ -227,7 +222,7 @@ var LoadingManager = exports.LoadingManager = /*#__PURE__*/function () {
227
222
  if (!tmodelEntry || tmodelEntry.accessIndex >= tmodelEntry.resultCount) {
228
223
  return undefined;
229
224
  }
230
- var loadTargetName = this.getLoadTargetName(prevTargetName);
225
+ var loadTargetName = _TUtil.TUtil.getLoadTargetName(prevTargetName);
231
226
  var targetValue = tmodel.val(loadTargetName);
232
227
  var result;
233
228
  if (targetValue) {
@@ -290,7 +285,7 @@ var LoadingManager = exports.LoadingManager = /*#__PURE__*/function () {
290
285
  targetName = _ref.targetName;
291
286
  var key = _this4.getTModelKey(tmodel, targetName);
292
287
  var tmodelEntry = _this4.tmodelKeyMap[key];
293
- var loadTargetName = _this4.getLoadTargetName(targetName);
288
+ var loadTargetName = _TUtil.TUtil.getLoadTargetName(targetName);
294
289
  if (!tmodelEntry || !tmodelEntry.fetchMap[fetchId]) {
295
290
  return;
296
291
  }
@@ -300,12 +295,12 @@ var LoadingManager = exports.LoadingManager = /*#__PURE__*/function () {
300
295
  }));
301
296
  var targetResults = tmodel.val(loadTargetName);
302
297
  if (targetResults) {
303
- if (!targetResults[fetchEntry.order]) {
298
+ if (!_TUtil.TUtil.isDefined(targetResults[fetchEntry.order])) {
304
299
  tmodelEntry.resultCount++;
305
300
  }
306
301
  targetResults[fetchEntry.order] = res.result;
307
302
  }
308
- tmodel.val(targetName, (targetResults === null || targetResults === void 0 ? void 0 : targetResults.length) === 1 && tmodel.getTargetCycles(targetName) <= 1 ? targetResults[0] : targetResults);
303
+ tmodel.val(targetName, res.result);
309
304
  var newStatus = _this4.calculateTargetStatus(tmodel, targetName);
310
305
  tmodel.setTargetStatus(targetName, newStatus);
311
306
  tmodel.setLastUpdate(targetName);
@@ -332,7 +327,7 @@ var LoadingManager = exports.LoadingManager = /*#__PURE__*/function () {
332
327
  targetName = _ref2.targetName;
333
328
  var key = _this5.getTModelKey(tmodel, targetName);
334
329
  var tmodelEntry = _this5.tmodelKeyMap[key];
335
- var loadTargetName = _this5.getLoadTargetName(targetName);
330
+ var loadTargetName = _TUtil.TUtil.getLoadTargetName(targetName);
336
331
  if (!tmodelEntry || !tmodelEntry.fetchMap[fetchId]) {
337
332
  return;
338
333
  }
@@ -345,12 +340,12 @@ var LoadingManager = exports.LoadingManager = /*#__PURE__*/function () {
345
340
  };
346
341
  var targetResults = tmodel.val(loadTargetName);
347
342
  if (targetResults) {
348
- if (!targetResults[fetchEntry.order]) {
343
+ if (!_TUtil.TUtil.isDefined(targetResults[fetchEntry.order])) {
349
344
  tmodelEntry.resultCount++;
350
345
  }
351
346
  targetResults[fetchEntry.order] = res;
352
347
  }
353
- tmodel.val(targetName, (targetResults === null || targetResults === void 0 ? void 0 : targetResults.length) === 1 && tmodel.getTargetCycles(targetName) <= 1 ? targetResults[0] : targetResults);
348
+ tmodel.val(targetName, res);
354
349
  tmodelEntry.errorCount++;
355
350
  _this5.callOnErrorHandler(tmodel, targetName);
356
351
  var newStatus = _this5.calculateTargetStatus(tmodel, targetName);
package/build/TModel.js CHANGED
@@ -134,6 +134,7 @@ var TModel = exports.TModel = /*#__PURE__*/function (_BaseModel) {
134
134
  this.deletedChildren.push(child);
135
135
  this.removeFromUpdatingChildren(child);
136
136
  this.removeFromActiveChildren(child);
137
+ this.removeFromAnimatingChildren(child);
137
138
  this.childrenUpdateFlag = true;
138
139
  (0, _App.getLocationManager)().calcChildren(this);
139
140
  this.markLayoutDirty('removeChild');
@@ -501,6 +502,11 @@ var TModel = exports.TModel = /*#__PURE__*/function (_BaseModel) {
501
502
  }
502
503
  return parentValue;
503
504
  }
505
+ }, {
506
+ key: "getLoadedItems",
507
+ value: function getLoadedItems(targetName) {
508
+ return this.val(_TUtil.TUtil.getLoadTargetName(targetName));
509
+ }
504
510
  }, {
505
511
  key: "delVal",
506
512
  value: function delVal(key) {
@@ -226,7 +226,7 @@ var TModelManager = exports.TModelManager = /*#__PURE__*/function () {
226
226
  }, {
227
227
  key: "needsRerender",
228
228
  value: function needsRerender(tmodel) {
229
- if (tmodel.hasDom() && _TUtil.TUtil.isDefined(tmodel.getHtml()) && (tmodel.$dom.html() !== tmodel.getHtml() || tmodel.$dom.textOnly !== tmodel.isTextOnly())) {
229
+ if (tmodel.hasDom() && _TUtil.TUtil.isDefined(tmodel.getHtml()) && (tmodel.$dom.innerHTML() !== tmodel.getHtml() || tmodel.$dom.textOnly !== tmodel.isTextOnly())) {
230
230
  return true;
231
231
  }
232
232
  return false;
@@ -217,6 +217,7 @@ var TModelUtil = exports.TModelUtil = /*#__PURE__*/function () {
217
217
  if (width > 0 || width === 0 && child.lastVal('width') > 0) {
218
218
  child.addToStyleTargetList('width');
219
219
  }
220
+ child.markLayoutDirty('width');
220
221
  (0, _App.getRunScheduler)().schedule(15, 'resize');
221
222
  }
222
223
  }
@@ -239,6 +240,7 @@ var TModelUtil = exports.TModelUtil = /*#__PURE__*/function () {
239
240
  if (height > 0 || height === 0 && child.lastVal('height') > 0) {
240
241
  child.addToStyleTargetList('height');
241
242
  }
243
+ child.markLayoutDirty('height');
242
244
  (0, _App.getRunScheduler)().schedule(15, 'resize');
243
245
  }
244
246
  }
package/build/TUtil.js CHANGED
@@ -165,6 +165,11 @@ var TUtil = exports.TUtil = /*#__PURE__*/function () {
165
165
  value: function capitalizeFirstLetter(val) {
166
166
  return val.charAt(0).toUpperCase() + val.slice(1);
167
167
  }
168
+ }, {
169
+ key: "getLoadTargetName",
170
+ value: function getLoadTargetName(targetName) {
171
+ return "load-".concat(targetName);
172
+ }
168
173
  }, {
169
174
  key: "formatNum",
170
175
  value: function formatNum(num, precision) {
@@ -405,6 +405,9 @@ var TargetUtil = exports.TargetUtil = /*#__PURE__*/function () {
405
405
  if (tmodel.isTargetImperative(targetName)) {
406
406
  continue;
407
407
  }
408
+ if (tmodel.activatedTargets.indexOf(targetName) >= 0) {
409
+ return "activated targets";
410
+ }
408
411
  if (tmodel.hasUpdatingImperativeTargets(targetName)) {
409
412
  return tmodel.oid + "." + targetName + ": " + tmodel.getUpdatingImperativeTargets(targetName);
410
413
  }
package/build/Viewport.js CHANGED
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.Viewport = void 0;
7
+ var _TModelUtil = require("./TModelUtil.js");
7
8
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
8
9
  function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
9
10
  function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
@@ -130,7 +131,7 @@ var Viewport = exports.Viewport = /*#__PURE__*/function () {
130
131
  var scale = child.getMeasuringScale();
131
132
  var topBaseHeight = child.getTopBaseHeight() * scale;
132
133
  var maxHeight = child.getHeight() * scale + this.currentChild.getTopMargin() + this.currentChild.getBottomMargin();
133
- var maxWidth = child.getItemOverflowMode() === 'always' ? this.container.getWidth() : child.getBaseWidth() * scale + this.currentChild.getLeftMargin() + this.currentChild.getRightMargin();
134
+ var maxWidth = child.getItemOverflowMode() === 'always' && _TModelUtil.TModelUtil.isWidthDefined(this.container) ? this.container.getWidth() : child.getBaseWidth() * scale + this.currentChild.getLeftMargin() + this.currentChild.getRightMargin();
134
135
  if (child.type !== 'BI' && this.container.type === 'BI') {
135
136
  var layout = this.computeBoundary(child, 'layout');
136
137
  var animated = this.computeBoundary(child, 'animated');