jsswift 1.0.54 → 2.0.1
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/AI.md +40 -72
- package/README.md +2 -2
- package/dist/css/animation.css +36 -36
- package/dist/css/base.css +374 -374
- package/dist/css/docs.css +54 -54
- package/dist/css/fonts-nunito.css +2 -2
- package/dist/css/min-ui.css +1 -1
- package/dist/css/responsive-base.css +549 -549
- package/dist/css/responsive.css +3225 -3225
- package/dist/css/ui-components.css +2902 -2930
- package/dist/css/ui-light.css +3853 -3881
- package/dist/css/ui-light.min.css +1 -1
- package/dist/css/ui.css +6530 -6558
- package/dist/css/ui.min.css +1 -1
- package/dist/documentions/AI.md +40 -72
- package/dist/documentions/README.md +4 -2
- package/dist/documentions/application-rules.md +2 -2
- package/dist/documentions/components/table.md +13 -0
- package/dist/documentions/components/toolbar.md +1 -1
- package/dist/documentions/examples/crud.md +21 -8
- package/dist/documentions/getting-started.md +6 -0
- package/dist/documentions/knowledge-map.json +22 -1
- package/dist/documentions/ui/data-feedback-overlays.md +2 -0
- package/dist/documentions/ui/forms.md +2 -0
- package/dist/documentions/ui/themes.md +39 -0
- package/dist/jsswift.js +5685 -12485
- package/dist/jsswift.min.js +12 -12
- package/dist/min-jsswift.js +12 -12
- package/package.json +2 -2
package/AI.md
CHANGED
|
@@ -23,52 +23,32 @@ The map locates a contract; it does not replace it. Avoid reading all of `ui/com
|
|
|
23
23
|
|
|
24
24
|
## Import, create, mount
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
With Vite, provide `<div id="app"></div>` and a module entrypoint:
|
|
27
27
|
|
|
28
28
|
```js
|
|
29
29
|
import 'jsswift';
|
|
30
30
|
import 'jsswift/css/ui-light.css';
|
|
31
31
|
const _ = window._;
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (!name.value.trim()) {
|
|
48
|
-
errors.replaceChildren(_.p('Il nome è obbligatorio.'));
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
errors.replaceChildren();
|
|
52
|
-
console.log({ name: name.value, category: category.value });
|
|
53
|
-
dialog.close();
|
|
54
|
-
}}, 'Salva');
|
|
55
|
-
dialog.update({ actions: [
|
|
56
|
-
_.Button({ onClick: () => dialog.close() }, 'Annulla'), save
|
|
57
|
-
] });
|
|
58
|
-
const edit = _.Button({ onClick: () => dialog.open() }, 'Modifica');
|
|
59
|
-
const table = _.Table({
|
|
60
|
-
rows: [{ id: 1, name: 'Prodotto 01', price: 10 }], rowKey: 'id',
|
|
61
|
-
columns: [
|
|
62
|
-
{ key: 'name', label: 'Nome', render: (row, { value }) => _.strong(value) },
|
|
63
|
-
{ key: 'price', label: 'Prezzo', format: value => `${value} EUR` }
|
|
64
|
-
],
|
|
65
|
-
pagination: false, hideFooter: true, hideStatus: true, minTableWidth: 700
|
|
66
|
-
});
|
|
67
|
-
const page = _.Page({}, _.div({}, _.h1('Prodotti'), edit, table));
|
|
68
|
-
_.mount('#app', page);
|
|
32
|
+
const name = _.rod('Prodotto 01'), category = _.rod('Casa');
|
|
33
|
+
const input = _.Input({label:'Nome', required:true, model:name});
|
|
34
|
+
const select = _.Select({label:'Categoria', model:category,
|
|
35
|
+
options:[{value:'Casa',label:'Casa'},{value:'Ufficio',label:'Ufficio'}]});
|
|
36
|
+
const dialog = _.Dialog({title:'Prodotto', ariaLabel:'Prodotto',
|
|
37
|
+
content:_.div({}, input, select), trapFocus:true, closeOnEsc:true,
|
|
38
|
+
onOpen:() => input.focus()});
|
|
39
|
+
dialog.update({actions:[_.Button({onClick:() => {
|
|
40
|
+
console.log({name:name.value, category:category.value}); dialog.close();
|
|
41
|
+
}}, 'Salva')]});
|
|
42
|
+
const table = _.Table({rows:[{id:1,name:'Prodotto 01'}], rowKey:'id',
|
|
43
|
+
columns:[{key:'name',label:'Nome',sortable:false,render:(row,ctx) => _.strong(ctx.value)}],
|
|
44
|
+
pagination:false, hideFooter:true, hideStatus:true, minTableWidth:600});
|
|
45
|
+
_.mount('#app', _.div({}, _.Card({title:'Prodotti'},
|
|
46
|
+
_.Button({color:'primary',onClick:() => dialog.open()}, 'Modifica')), table));
|
|
69
47
|
```
|
|
70
48
|
|
|
71
|
-
This
|
|
49
|
+
This logs values; it does not implement validation or persistence. For product editing use [the executable CRUD example](examples/crud.md) instead of reading forms, overlays or component contracts first.
|
|
50
|
+
|
|
51
|
+
Prefer `_.rod(initial)` for bidirectional fields: read/write `model.value`. `_.signal(initial)` remains supported. Input/Select expose `focus(options?)`; avoid private `_input`/`_select`. Use `label`, `required`, `ariaLabel`, `ariaLabelledBy`, `ariaDescribedBy`, `ariaInvalid`, and `error: _.rod('')`. Input accepts `min`, `max`, `step`, `pattern`, `minLength`, `maxLength`.
|
|
72
52
|
|
|
73
53
|
## Exact callback arguments
|
|
74
54
|
|
|
@@ -87,62 +67,50 @@ Dialog returns an API object, not a node to mount: `open(overrides?)`, `close()`
|
|
|
87
67
|
|
|
88
68
|
## Existing CSS and optional assets
|
|
89
69
|
|
|
90
|
-
The
|
|
70
|
+
The light import includes base tokens, colors, component styles, dense/outline and unprefixed layout utilities. Add `jsswift/css/responsive.css` **after** it for tablet/pc/desktop or legacy breakpoint classes. `ui.css` is the complete alternative; do not import full and light together. Component-specific mobile rules remain in light.
|
|
91
71
|
|
|
92
|
-
|
|
72
|
+
Prefer public props to rebuilding controls: `_.Button({color:'primary',outline:true,dense:true}, 'Modifica')`. For breakpoint props use `_.Row({gap:'md',tablet:{gap:'lg'}})` with the responsive addon. Consult common props only for an additional inherited API.
|
|
93
73
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
System fonts are the default. Import `jsswift/css/fonts-nunito.css`, `jsswift/css/fonts-material.css`, or `jsswift/tabler` only when required; Material Symbols loads a remote Google font. See [setup](getting-started.md).
|
|
74
|
+
Classes and theme variables use `jss-`; migrate old `cms-` overrides. Fonts are system defaults. Import `jsswift/css/fonts-nunito.css`, `fonts-material.css`, or `jsswift/tabler` only when required; Material Symbols downloads a remote font.
|
|
97
75
|
|
|
98
76
|
## Accessibility and verification
|
|
99
77
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
Run the app's build after implementation and check values, validation, dialog keyboard behavior, and persistence when required. Start one development server on an explicit available port; with Vite use `npm run dev -- --port <port> --strictPort`. Report checks actually performed.
|
|
103
|
-
|
|
104
|
-
## Read only what the task needs
|
|
105
|
-
|
|
106
|
-
- Exact APIs: [Input](components/input.md), [Select](components/select.md), [Button](components/btn.md), [Card](components/card.md), [Table](components/table.md), [Dialog](components/dialog.md).
|
|
107
|
-
- Extra behavior: [forms](ui/forms.md), [reactivity](reactivity.md), [layout](ui/layout-and-responsive.md), [overlays](ui/data-feedback-overlays.md).
|
|
108
|
-
- Other components: [index](components/README.md). MCP: read `guide:AI`, then search only for additional features.
|
|
109
|
-
|
|
110
|
-
For a complete application flow, read [the compact CRUD example](examples/crud.md) only when the task needs editing, validation, persistence and focus restoration together.
|
|
78
|
+
String labels name Input/Select; set Dialog `ariaLabel`. Field errors are associated automatically. Dialog preserves focus assigned in `onOpen`. If rendering replaces the trigger, restore its current replacement in `onClose`; see CRUD.
|
|
111
79
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
Check whether browser tooling and server permissions are available before launching checks. Run Git commands only in a Git worktree; for example test `git rev-parse --is-inside-work-tree` before requesting a diff. Keep build, pure-logic tests and server startup results separate. An HTTP response confirms a reachable server, not that your startup command succeeded or that browser interactions work. Report environment failures separately from application failures. Test the implemented functions rather than rebuilding equivalent data inside an assertion.
|
|
115
|
-
|
|
116
|
-
Dialog autofocus preserves focus assigned inside `onOpen`; verify initial focus after the deferred autofocus has run, separately from validation focus and return focus. Record each check separately: initial field, Tab/Shift+Tab containment, Escape, and return to the current trigger. A focus-trap result does not prove initial focus. Field messages are associated with Input/Select through `aria-describedby` automatically.
|
|
117
|
-
|
|
118
|
-
## Focus CSS and targeted reads
|
|
119
|
-
|
|
120
|
-
Apply focus indicators to every selector through `:is`, rather than placing the pseudo-class on only the final selector in a comma-separated list:
|
|
80
|
+
Build is not a browser test. Verify initial focus after deferred autofocus, Tab/Shift+Tab containment, Escape, return focus, validation, persistence, mobile overflow and borders separately. Report unverified checks. Use this custom focus CSS:
|
|
121
81
|
|
|
122
82
|
```css
|
|
123
|
-
:is(button,
|
|
83
|
+
:is(button,a,input,select,[tabindex]):focus-visible {
|
|
124
84
|
outline: 3px solid #2563eb;
|
|
125
85
|
outline-offset: 3px;
|
|
126
86
|
}
|
|
127
87
|
```
|
|
128
88
|
|
|
129
|
-
|
|
89
|
+
Keep build, logic assertions and server startup in separate commands. Check tooling/permissions first; use an explicit Vite port with `--strictPort`. Environment failures are not application failures; HTTP alone does not verify interactions.
|
|
130
90
|
|
|
91
|
+
## Additional APIs only
|
|
92
|
+
|
|
93
|
+
Use the map for the missing API, then read its focused contract. Button is `components/btn.md` (`button.md` redirects). With configured MCP: `jsswift_read({id:"component:table",section:"props",keys:["pagination","hideFooter"]})`; sections include props/events/methods/slots and resolve inherited props. No MCP setup is required for local documentation.
|
|
131
94
|
|
|
132
95
|
## Catalogue surfaces and field styling
|
|
133
96
|
|
|
134
|
-
|
|
97
|
+
`_.Kpi({title:'Disponibili',value:9,note:'Con quantità maggiore di zero'})` supplies dashboard metrics. Update KPI when inventory changes, not on each filter; see CRUD. Read the Kpi contract only for additional options.
|
|
135
98
|
|
|
136
|
-
Table
|
|
99
|
+
Table returns a Card; use a structural container. Card props include `shadow:'none'`, `radius:'12px'`, and `padding`. For a fixed light surface: `style:{background:'#fff'}`, `tableStyle:{background:'#fff','--set-color-1':'#fff'}`. This does not provide automatic dark theming.
|
|
137
100
|
|
|
138
|
-
|
|
101
|
+
For external pagination use `pagination:false`, `hideFooter:true`, `hideStatus:true`, `emptyText:'Nessun prodotto trovato'`, `minTableWidth:600`. Set each data column's `sortable:false`: built-in sorting sees only the supplied page. Sort the full filtered dataset before slicing if needed.
|
|
139
102
|
|
|
140
|
-
|
|
103
|
+
Input's native input is transparent; preserve that background to keep the outer curved border visible. Set height on an application container:
|
|
141
104
|
|
|
142
105
|
```css
|
|
143
106
|
.catalogue-filters {
|
|
144
|
-
--
|
|
107
|
+
--jss-input-height-default: 40px;
|
|
145
108
|
}
|
|
146
109
|
```
|
|
110
|
+
Use the field's `radius` prop if it should not inherit a surface radius. Avoid clipping controls/focus indicators with overflow:hidden. Check borders, labels, errors and focus at desktop/mobile sizes.
|
|
111
|
+
|
|
112
|
+
## Theme and lifecycle essentials
|
|
113
|
+
|
|
114
|
+
base.css is already included. Use `_.setTheme('dark')` or `_.setTheme('light')`; persistence defaults to `jsswift:theme`. At startup restore with `_.setTheme(_.getTheme())`. Customize the existing `--jss-primary-600`/`--jss-primary-700` palette values after the UI import. See [base CSS and themes](ui/themes.md) only for additional theme requirements.
|
|
147
115
|
|
|
148
|
-
|
|
116
|
+
Replace component subtrees with `_.mount(host, nextContent)` (default clear:true), which cleans up previous effects and subscriptions. Native `replaceChildren`/`innerHTML` alone do not run JSswift cleanup. Keep shared models owned by the application alive.
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# JSswift
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**First read only [AI.md](AI.md), in a separate read operation.** It covers imports, rod field models, Input, Select, Button, Card, Table and Dialog. Implement its supported examples before opening additional contracts.
|
|
4
4
|
|
|
5
5
|
For an API absent from that guide, use [knowledge-map.json](dist/documentions/knowledge-map.json) to locate the exact document. Read only the relevant contract; avoid concatenating the component catalog or searching runtime bundles for documentation.
|
|
6
6
|
|
|
7
|
-
Import `jsswift` and `jsswift/css/ui.css
|
|
7
|
+
Import `jsswift` and `jsswift/css/ui-light.css`; add `jsswift/css/responsive.css` when using breakpoint props. `ui.css` remains the complete alternative. Component CSS is included; fonts and Tabler are optional. The read-only `@jsswift/knowledge-mcp` is an optional discovery interface when configured in your AI client.
|
package/dist/css/animation.css
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
1
|
:root {
|
|
2
|
-
--
|
|
3
|
-
--
|
|
4
|
-
--
|
|
5
|
-
--
|
|
6
|
-
--
|
|
7
|
-
--
|
|
2
|
+
--jss-anim-dur: 500ms;
|
|
3
|
+
--jss-anim-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
|
|
4
|
+
--jss-anim-distance: 12px;
|
|
5
|
+
--jss-anim-scale: 0.98;
|
|
6
|
+
--jss-anim-in: jss-fade-in;
|
|
7
|
+
--jss-anim-out: jss-fade-out;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
.
|
|
11
|
-
animation-duration: var(--
|
|
12
|
-
animation-timing-function: var(--
|
|
10
|
+
.jss-animate {
|
|
11
|
+
animation-duration: var(--jss-anim-dur);
|
|
12
|
+
animation-timing-function: var(--jss-anim-ease);
|
|
13
13
|
animation-fill-mode: both;
|
|
14
14
|
will-change: opacity, transform;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
.
|
|
18
|
-
animation-name: var(--
|
|
17
|
+
.jss-animate.in {
|
|
18
|
+
animation-name: var(--jss-anim-in);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
.
|
|
22
|
-
animation-name: var(--
|
|
21
|
+
.jss-animate.out {
|
|
22
|
+
animation-name: var(--jss-anim-out);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
.
|
|
26
|
-
animation-name:
|
|
25
|
+
.jss-animate.fade.in {
|
|
26
|
+
animation-name: jss-fade-in;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
.
|
|
30
|
-
animation-name:
|
|
29
|
+
.jss-animate.fade.out {
|
|
30
|
+
animation-name: jss-fade-out;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
.
|
|
34
|
-
animation-name:
|
|
33
|
+
.jss-animate.slide.in {
|
|
34
|
+
animation-name: jss-slide-in;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
.
|
|
38
|
-
animation-name:
|
|
37
|
+
.jss-animate.slide.out {
|
|
38
|
+
animation-name: jss-slide-out;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
.
|
|
42
|
-
animation-name:
|
|
41
|
+
.jss-animate.scale.in {
|
|
42
|
+
animation-name: jss-scale-in;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
.
|
|
46
|
-
animation-name:
|
|
45
|
+
.jss-animate.scale.out {
|
|
46
|
+
animation-name: jss-scale-out;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
@keyframes
|
|
49
|
+
@keyframes jss-fade-in {
|
|
50
50
|
from {
|
|
51
51
|
opacity: 0;
|
|
52
52
|
}
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
@keyframes
|
|
59
|
+
@keyframes jss-fade-out {
|
|
60
60
|
from {
|
|
61
61
|
opacity: 1;
|
|
62
62
|
}
|
|
@@ -66,10 +66,10 @@
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
@keyframes
|
|
69
|
+
@keyframes jss-slide-in {
|
|
70
70
|
from {
|
|
71
71
|
opacity: 0;
|
|
72
|
-
transform: translateY(var(--
|
|
72
|
+
transform: translateY(var(--jss-anim-distance));
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
to {
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
@keyframes
|
|
81
|
+
@keyframes jss-slide-out {
|
|
82
82
|
from {
|
|
83
83
|
opacity: 1;
|
|
84
84
|
transform: translateY(0);
|
|
@@ -86,14 +86,14 @@
|
|
|
86
86
|
|
|
87
87
|
to {
|
|
88
88
|
opacity: 0;
|
|
89
|
-
transform: translateY(var(--
|
|
89
|
+
transform: translateY(var(--jss-anim-distance));
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
@keyframes
|
|
93
|
+
@keyframes jss-scale-in {
|
|
94
94
|
from {
|
|
95
95
|
opacity: 0;
|
|
96
|
-
transform: scale(var(--
|
|
96
|
+
transform: scale(var(--jss-anim-scale));
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
to {
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
@keyframes
|
|
105
|
+
@keyframes jss-scale-out {
|
|
106
106
|
from {
|
|
107
107
|
opacity: 1;
|
|
108
108
|
transform: scale(1);
|
|
@@ -110,12 +110,12 @@
|
|
|
110
110
|
|
|
111
111
|
to {
|
|
112
112
|
opacity: 0;
|
|
113
|
-
transform: scale(var(--
|
|
113
|
+
transform: scale(var(--jss-anim-scale));
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
@media (prefers-reduced-motion: reduce) {
|
|
118
|
-
.
|
|
118
|
+
.jss-animate {
|
|
119
119
|
animation-duration: 1ms;
|
|
120
120
|
}
|
|
121
121
|
}
|