jsswift 1.0.46 → 1.0.47

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,6 +1,6 @@
1
1
  # JSswift AI quick start
2
2
 
3
- Start here for a small page using Input, Select, Button, Card, Table, and Dialog. The example and callback table below are a supported subset; read a component contract only when using additional APIs. Do not read the whole catalog or search runtime bundles for documentation.
3
+ Start here for a small page using Input, Select, Button, Card, Table, and Dialog. The example and callback table below are a supported subset; read a component contract only when using additional APIs. Do not read the whole catalog or search runtime bundles for documentation. Button’s full contract is `components/btn.md`; `components/button.md` redirects to it.
4
4
 
5
5
  ## Import, create, mount
6
6
 
@@ -11,8 +11,8 @@ import 'jsswift';
11
11
  import 'jsswift/css/ui.css';
12
12
  const _ = window._;
13
13
 
14
- const name = _.signal('Prodotto 01');
15
- const category = _.signal('Casa');
14
+ const name = _.rod('Prodotto 01');
15
+ const category = _.rod('Casa');
16
16
  const nameInput = _.Input({ label: 'Nome prodotto', model: name });
17
17
  const categorySelect = _.Select({
18
18
  label: 'Categoria', model: category,
@@ -25,12 +25,12 @@ const dialog = _.Dialog({
25
25
  closeOnEsc: true, trapFocus: true, autoFocus: true
26
26
  });
27
27
  const save = _.Button({ color: 'primary', onClick: () => {
28
- if (!name[0]().trim()) {
28
+ if (!name.value.trim()) {
29
29
  errors.replaceChildren(_.p('Il nome è obbligatorio.'));
30
30
  return;
31
31
  }
32
32
  errors.replaceChildren();
33
- console.log({ name: name[0](), category: category[0]() });
33
+ console.log({ name: name.value, category: category.value });
34
34
  dialog.close();
35
35
  }}, 'Salva');
36
36
  dialog.update({ actions: [
@@ -49,7 +49,7 @@ const page = _.Page({}, _.Card({ title: 'Prodotti' }, edit, table));
49
49
  _.mount('#app', page);
50
50
  ```
51
51
 
52
- This demonstrates composition and validation; saving logs the values. Add application persistence and refresh the table when your task requires them. `_.signal` returns `[get, set, dispose]`: read `name[0]()`, write `name[1]('Nuovo nome')`; `model` synchronizes the control. This avoids reading private `_input` or `_select` references. The current controls do not document public `focus/getValue/setValue` methods; do not invent them.
52
+ This demonstrates composition and validation; saving logs the values. Add application persistence and refresh the table when your task requires them. Prefer `_.rod(initial)` for bidirectional field models: read `name.value`, write `name.value = 'Nuovo nome'`; `model` synchronizes the control. Use `_.signal(initial)` when explicit getter/setter functions suit the state, and `_.useForm()` for structured form validation and errors. This avoids reading private `_input` or `_select` references. The current controls do not document public `focus/getValue/setValue` methods; do not invent them.
53
53
 
54
54
  ## Exact callback arguments
55
55
 
@@ -0,0 +1,3 @@
1
+ # Button
2
+
3
+ The canonical complete contract is [btn.md](btn.md). Use `_.Button`; `_.Btn` is a compatible alias. This path is a documentation alias, not a separate component.
@@ -78,3 +78,17 @@ _.Select({
78
78
  ```
79
79
 
80
80
  An empty-string option is a valid selected value. Read `multiple` and `model` contracts when those modes are needed. Verify the rendered control's accessible name.
81
+
82
+ ## Signal model
83
+
84
+ Pass the full public tuple from `_.signal(initial)` directly as `model`; `[get, set]` is also supported. Choosing an option updates the model synchronously before `onChange` runs. Updating the model updates the displayed option.
85
+
86
+ ```js
87
+ const category = _.signal('');
88
+ const field = _.Select({ model: category, options: [
89
+ { value: '', label: 'Seleziona' }, { value: 'Casa', label: 'Casa' }
90
+ ] });
91
+ const save = _.Button({ onClick: () => console.log(category[0]()) }, 'Salva');
92
+ ```
93
+
94
+ Mount both controls; choose Casa through the menu, then save. The logged model value must be Casa.
@@ -73,7 +73,11 @@
73
73
  "_.effect",
74
74
  "_.computed",
75
75
  "_.untracked",
76
- "_.batch"
76
+ "_.batch",
77
+ "rod",
78
+ "_.rod",
79
+ "bidirezionale",
80
+ "two-way binding"
77
81
  ],
78
82
  "paths": [
79
83
  "reactivity.md"
@@ -961,5 +965,8 @@
961
965
  ]
962
966
  }
963
967
  ],
964
- "packageVersion": "1.0.46"
968
+ "documentAliases": {
969
+ "components/button.md": "components/btn.md"
970
+ },
971
+ "packageVersion": "1.0.47"
965
972
  }
@@ -1,13 +1,27 @@
1
1
  # Reactivity and models
2
2
 
3
- `_.signal(initial)` returns `[get, set, dispose]`. Use `_.computed` for derived values, `_.effect` for side effects, `_.untracked` for a non-subscribing read, and `_.batch` for grouped updates.
3
+ Prefer `_.rod(initial)` for bidirectional control models. Pass the rod as `model`, read and update its public `.value`; do not manually mutate the control DOM.
4
4
 
5
- These direct aliases are exposed by the core runtime footer. Use them in application code.
5
+ ```js
6
+ const name = _.rod('');
7
+ const category = _.rod('');
8
+ const input = _.Input({ label: 'Nome prodotto', model: name });
9
+ const select = _.Select({ model: category, options: [
10
+ { value: '', label: 'Seleziona' }, { value: 'Casa', label: 'Casa' }
11
+ ] });
12
+ const save = _.Button({ onClick: () => console.log(name.value, category.value) }, 'Salva');
13
+ name.value = 'Prodotto 01';
14
+ // Choosing Casa in Select updates category.value; changing category.value updates Select.
15
+ ```
6
16
 
7
- Example:
17
+ Rod control notifications are scheduled through microtasks; wait for the control update before inspecting DOM after a programmatic assignment. Rod values themselves can be read immediately. Use `_.useForm()` for values, validation, touched/dirty flags and submit state; see [forms](ui/forms.md). Follow each component's documented model contract.
8
18
 
9
- const [getCount, setCount] = _.signal(0);
10
- _.Button({ onClick: () => setCount(getCount() + 1) }, "Add");
11
- _.Badge({ label: () => String(getCount()) });
19
+ `_.signal(initial)` remains supported and returns `[get, set, dispose]`. Use it when explicit getter/setter functions are useful. Pass the full tuple as `model` to a control supporting signals; `[get, set]` is also supported.
12
20
 
13
- For a documented controlled component, pass a signal tuple as model; do not manually mutate DOM values. Use _.useForm for form values, validation, touched/dirty flags, and submit state.
21
+ ```js
22
+ const [getCount, setCount] = _.signal(0);
23
+ _.Button({ onClick: () => setCount(getCount() + 1) }, 'Add');
24
+ _.Badge({ label: () => String(getCount()) });
25
+ ```
26
+
27
+ Use `_.computed` for derived values, `_.effect` for side effects, `_.untracked` for a non-subscribing read, and `_.batch` for grouped updates. These direct aliases are exposed by the core runtime footer.
package/dist/jsswift.js CHANGED
@@ -6644,7 +6644,7 @@ const unitCover = (v, name = 'size') => {
6644
6644
  };
6645
6645
 
6646
6646
  function uiIsSignal(v) {
6647
- return Array.isArray(v) && v.length === 2 && typeof v[0] === "function" && typeof v[1] === "function";
6647
+ return Array.isArray(v) && (v.length === 2 || (v.length === 3 && typeof v[2] === "function")) && typeof v[0] === "function" && typeof v[1] === "function";
6648
6648
  }
6649
6649
 
6650
6650
  function uiIsRod(v) {