arrmatura 6.3.2 → 6.3.3
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 +9 -15
- package/dist/index.cjs +6 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.js +5 -1
- package/dist/index.js.map +4 -4
- package/docs/components.md +89 -0
- package/docs/{hello.md → getstarted.md} +21 -4
- package/docs/manual.md +7 -310
- package/docs/templates.md +222 -0
- package/index.ts +4 -4
- package/package.json +8 -6
- package/src/core/Arrmatron.ts +47 -41
- package/src/core/Component.ts +19 -21
- package/src/core/ManifestNode.ts +22 -19
- package/src/core/resolveExpression.ts +7 -3
- package/src/registry/{iterations.ts → Iterative.ts} +11 -16
- package/src/registry/composition.ts +7 -4
- package/src/registry/conditionals.ts +8 -5
- package/src/registry/connector.ts +7 -6
- package/src/registry/index.ts +2 -5
- package/src/registry/root.ts +1 -1
- package/src/registry/routing.ts +6 -1
- package/src/utils/FingerprintMashine.ts +18 -20
- package/src/utils/compileExpression.ts +11 -90
- package/src/utils/narrowData.ts +15 -0
- package/types.ts +35 -27
- package/docs/glossary.md +0 -19
package/docs/manual.md
CHANGED
|
@@ -1,312 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Arrmatura
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This documentation provides a detailed overview of the Template syntax, control flow mechanisms,
|
|
4
|
+
dynamic tags, property bindings, connectors, slots, and custom component creation,
|
|
5
|
+
offering a comprehensive guide for developers to create and manage components effectively.
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
<component id="NavTreeItem">
|
|
10
|
-
<a href="id">
|
|
11
|
-
<span>{name | slice:0:50 | capitalize}</span>
|
|
12
|
-
<span If="label" class="label label-{type}">{label}</span>
|
|
13
|
-
</a>
|
|
14
|
-
</component>
|
|
15
|
-
|
|
16
|
-
<component id="NavTree">
|
|
17
|
-
<ul class="nav">
|
|
18
|
-
<li class="nav-item {item.class}" Each="item of data">
|
|
19
|
-
<NavTreeItem (...)="{item}">
|
|
20
|
-
<NavTree If="item.subs" data="{item.subs}" />
|
|
21
|
-
</li>
|
|
22
|
-
</ul>
|
|
23
|
-
</component>
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## Composition Control flow.
|
|
27
|
-
|
|
28
|
-
### Conditionals.
|
|
29
|
-
|
|
30
|
-
With `if` attribute, an element(and its inner context) presents only if value of expression is truthy.
|
|
31
|
-
|
|
32
|
-
```html
|
|
33
|
-
<div ... If="enabled">...</div>
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
#### full `then-else` syntax
|
|
37
|
-
|
|
38
|
-
```html
|
|
39
|
-
<Fragment If="enabled">
|
|
40
|
-
<Then><Case1 /></Then>
|
|
41
|
-
<Else><Case2 /></Else>
|
|
42
|
-
</Fragment>
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### Iterations.
|
|
46
|
-
|
|
47
|
-
`each` attribute multiplies component instances along items from given array.
|
|
48
|
-
|
|
49
|
-
```html
|
|
50
|
-
<ul>
|
|
51
|
-
<li Each="item of data">
|
|
52
|
-
<a href="/item/{item.id}">{item.position}. {item.name}</span>
|
|
53
|
-
</li>
|
|
54
|
-
</ul>
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
> - items MUST HAVE unique `id` field
|
|
58
|
-
|
|
59
|
-
### Fragment.
|
|
60
|
-
|
|
61
|
-
`<Fragment>` is a transparent container and works just like a parens for multiple components.
|
|
62
|
-
|
|
63
|
-
```html
|
|
64
|
-
<Fragment If="enabled"> <innerContent1 />...<innerContentN /> </Fragment>
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## Dynamic tags.
|
|
68
|
-
|
|
69
|
-
Used to calculate tag dunamically at runtime.
|
|
70
|
-
|
|
71
|
-
```html
|
|
72
|
-
<Dynamic As="Field.{type}" ...></Dynamic>
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
> it will fallback to a `Field` if a specific type not found.
|
|
76
|
-
|
|
77
|
-
## Properties.
|
|
78
|
-
|
|
79
|
-
Component state can be mutated different ways listed below.
|
|
80
|
-
State updates lead to redraw UI and notify subscribers(left arrows)
|
|
81
|
-
Updating data is compared with existing state values for 'sameness' (same set of same values).
|
|
82
|
-
|
|
83
|
-
### with scalar literals
|
|
84
|
-
|
|
85
|
-
`prop1="'somestring'"` puts a literal into `prop1` property.
|
|
86
|
-
|
|
87
|
-
> - 'true', 'false' values are narrowed to boolean,
|
|
88
|
-
> - numbers has been narrowed to number type.
|
|
89
|
-
|
|
90
|
-
### with resources values
|
|
91
|
-
|
|
92
|
-
`R`-prefix used to refer any value in the resource bundle.
|
|
93
|
-
|
|
94
|
-
`prop="R.resId"` assigns `resId` resource value to `prop`.
|
|
95
|
-
|
|
96
|
-
### with result of expression
|
|
97
|
-
|
|
98
|
-
`prop="{prop2}"` assigns value of `prop2` property of the current scope.
|
|
99
|
-
|
|
100
|
-
`prop="{data.key}"` assigns value of `data.key`.
|
|
101
|
-
|
|
102
|
-
`prop="{!prop2}"` assigns inverted value of `prop2`
|
|
103
|
-
|
|
104
|
-
`(...)="{data}"` special `(...)` notation used to spread keys/values of `data` into properties of a target entity.
|
|
105
|
-
|
|
106
|
-
### with result of chain of pipes
|
|
107
|
-
|
|
108
|
-
`prop="{some | pipeFn1 : 'strLiteral1' : 1 : true | pipeFn2 : property2 | pipeFn2 : R.resourceId}` applies chain of pipes.
|
|
109
|
-
|
|
110
|
-
> - Pipe functions can be chained. Result of the previous one passed as a first argument to the next one.
|
|
111
|
-
> - Optional colon-separated arguments can be passed to a pipe function as second, third arguments.
|
|
112
|
-
> - Use shortcuts like `==, && , ??, ?, >, <, []` for `equals, and, or, then, less, greater, dot` functions respectively.
|
|
113
|
-
> - There is no operation priority, they applied in left-to-right order.
|
|
114
|
-
|
|
115
|
-
### `data-*` attributes
|
|
116
|
-
|
|
117
|
-
All `data-[key]` attributes will be collected into single `data` object property under its keys.
|
|
118
|
-
|
|
119
|
-
### References.
|
|
120
|
-
|
|
121
|
-
Add `Ref` attribute to any component to get refer it in `arrows` expressions.
|
|
122
|
-
|
|
123
|
-
```html
|
|
124
|
-
<UserService Ref="user" /> <UserAvatar data="<- user.profile" onSave="-> user.update" />
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
## Left arrow expression
|
|
128
|
-
|
|
129
|
-
`data="<- ref.prop"` makes a hot subscription to any property of orbitrary component in the current or upper scopes.
|
|
130
|
-
|
|
131
|
-
> use pipes to adapt received value `data="<- ref.prop | adjustFn"`.
|
|
132
|
-
|
|
133
|
-
## Right arrow expression
|
|
134
|
-
|
|
135
|
-
Right arrow creates a function, that
|
|
136
|
-
|
|
137
|
-
- `action="data-> ref.submit(data)"` invokes `scope.refs[ref].submit(data)` action with an `data` object as parameter.
|
|
138
|
-
|
|
139
|
-
- `action="-> ref.submit(prop1)"` invokes `scope.refs[ref].submit(data)` action with a value of property `prop1` as parameter.
|
|
140
|
-
|
|
141
|
-
- `action="-> ref.prop1"` updates container state for given key `scope.refs[ref].up({ prop1: data })`.
|
|
142
|
-
|
|
143
|
-
> `action="data-> ref.action(data | prepare)` pipes will be applied on `data`-object before it passed to the action.
|
|
144
|
-
|
|
145
|
-
> `click="-> opened"` if `ref` is omitted, then a target will be a scope component `scope.up({opened:data})`
|
|
146
|
-
|
|
147
|
-
> `click="-> *"` will spread data to state of a scope component `scope.up(data)`
|
|
148
|
-
|
|
149
|
-
#### Right arrows with inline payload
|
|
150
|
-
|
|
151
|
-
Often, it is shorter to pass payload inline instead of using `data` property.
|
|
152
|
-
|
|
153
|
-
- `click="data-> * = data | assignKeyValue:'key':value"` updates a scope properties with `data` object.
|
|
154
|
-
- `click="-> prop" data="data"` updates a given scope property of owner with `data` object.
|
|
155
|
-
- `click="-> prop='literalValue'"` updates a given scope property of owner with literal.
|
|
156
|
-
|
|
157
|
-
## Connector
|
|
158
|
-
|
|
159
|
-
Special build-in `Connector` component serves for async data binding
|
|
160
|
-
It acts with timeout(0 by default) and debounces if any:
|
|
161
|
-
|
|
162
|
-
```html
|
|
163
|
-
<!-- `data` works as a `trigger`, if none specified. -->
|
|
164
|
-
<Connector data="<- todo.shownItems|adjust" change="-> someData" />
|
|
165
|
-
|
|
166
|
-
<!-- `change` is invokes with `data` on `trigger` changed. -->
|
|
167
|
-
<Connector
|
|
168
|
-
data="someData"
|
|
169
|
-
trigger="<- todo.shownItemsCount"
|
|
170
|
-
timeout="100"
|
|
171
|
-
change="data-> discriminant=data|calculate"
|
|
172
|
-
/>
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
## Slots
|
|
176
|
-
|
|
177
|
-
Slots are placeholders to inject an inner content of component usage tag.
|
|
178
|
-
|
|
179
|
-
```html
|
|
180
|
-
<Comp>
|
|
181
|
-
<!-- inner content of component usage -->
|
|
182
|
-
<InnerContent />
|
|
183
|
-
</Comp>
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
```html
|
|
187
|
-
<component id="Comp">
|
|
188
|
-
<div class="container">
|
|
189
|
-
<!-- Inner content will replace <Slot/> -->
|
|
190
|
-
<Slot>
|
|
191
|
-
</div>
|
|
192
|
-
</component>
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
### Multi-part extra content.
|
|
196
|
-
|
|
197
|
-
Inner content could be multiple-part and thus, distributed separately inside component template.
|
|
198
|
-
|
|
199
|
-
```html
|
|
200
|
-
<Comp>
|
|
201
|
-
<Comp:key1><Extra1 /></Comp:key1>
|
|
202
|
-
<Comp:key2><Extra2 /></Comp:key2>
|
|
203
|
-
<DefaultSlotContent />
|
|
204
|
-
</Comp>
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
```html
|
|
208
|
-
<div class="component template">
|
|
209
|
-
|
|
210
|
-
<!-- <Extra1/> will be placed here-->
|
|
211
|
-
<Slot Key="key1">
|
|
212
|
-
|
|
213
|
-
<!-- special `slot(key)` conditional expression may be used to check if non-empty slot content passed. -->
|
|
214
|
-
<div class="comp" If="slot(key2)">
|
|
215
|
-
<!-- <Extra2/> will be placed here -->
|
|
216
|
-
<Slot Key="key2">
|
|
217
|
-
</div>
|
|
218
|
-
|
|
219
|
-
<!-- <DefaultContent/> will be placed here -->
|
|
220
|
-
<Slot>
|
|
221
|
-
</div>
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
# Custom components
|
|
225
|
-
|
|
226
|
-
There is a [Component] class that could be used an base ancestor for custom components.
|
|
227
|
-
|
|
228
|
-
While designing custom components you can
|
|
229
|
-
|
|
230
|
-
- to define life-cycle hooks;
|
|
231
|
-
- to add getters/setter for its properties;
|
|
232
|
-
- to define `__getProperty(propName)` to return value of any property by its name
|
|
233
|
-
- to define `__stateChanged(changes)` to intercept appluing state changes
|
|
234
|
-
- to define action handlers like `doSomethig(data: any): object`, which may return a delta object for updating a component state;
|
|
235
|
-
- to use context methods like `up(delta)`, `emit('ref-target', data)`, `defer(fn)`.
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
class MyService extends Component {
|
|
239
|
-
|
|
240
|
-
constructor(initials: Hash, ctx: ICtx) {
|
|
241
|
-
Object.asign(this, initials);
|
|
242
|
-
this.ctx = ctx;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// life-cycle hook called once on component is inited
|
|
246
|
-
init() {
|
|
247
|
-
this.cancel = api.listen(this)
|
|
248
|
-
// ...or using $.defer()
|
|
249
|
-
this.ctx.defer(api.listen2(this));
|
|
250
|
-
|
|
251
|
-
// will update component state with returned result
|
|
252
|
-
return {
|
|
253
|
-
prop1:'value',
|
|
254
|
-
// can be promise as well
|
|
255
|
-
prop2: Promise.resolve(2)
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// life-cycle hook called once on component is done
|
|
260
|
-
done (){
|
|
261
|
-
this.cancel();
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// to intercept getting of any property
|
|
265
|
-
__getProperty(key: string) {
|
|
266
|
-
this.log('getProperty', key)
|
|
267
|
-
return this[key]
|
|
268
|
-
|
|
269
|
-
// to intercept state changes
|
|
270
|
-
__stateChanged(changes: Map) {
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// property getter
|
|
274
|
-
getSrc(){
|
|
275
|
-
return this.url.toString()
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// property setter
|
|
279
|
-
setSrc(value){
|
|
280
|
-
this.url = URL.parse(value)
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// getter can return promise
|
|
284
|
-
async getData() {
|
|
285
|
-
return this.fetchData()
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// action handler. To be invoked with '-> ref.someAction' notation
|
|
289
|
-
onSomeAction(data: any) {
|
|
290
|
-
if (asyncMode) {
|
|
291
|
-
return promise.then(() => delta)
|
|
292
|
-
}
|
|
293
|
-
// delta object to update component state
|
|
294
|
-
return {
|
|
295
|
-
// instant value for 'prop'
|
|
296
|
-
prop: data.value,
|
|
297
|
-
// async evaluation for 'prop'. 'Promise' postfix is optional.
|
|
298
|
-
propPromise: T.fetchProp(),
|
|
299
|
-
// async spread
|
|
300
|
-
'...': Promise.resolve({
|
|
301
|
-
prop1: 'val1'
|
|
302
|
-
prop2: 'val2'
|
|
303
|
-
})
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
toast (message) {
|
|
308
|
-
// emit action event
|
|
309
|
-
this.emit('toasters.onSend(data)', { message });
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
```
|
|
7
|
+
- [Get started](./getstarted.md)
|
|
8
|
+
- [Templates](./templates.md)
|
|
9
|
+
- [Custom components](./components.md)
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# Templates
|
|
2
|
+
|
|
3
|
+
**Template** is a xml-based formal notation, which defining components composition, connections, logic and flow.
|
|
4
|
+
|
|
5
|
+
## Insight
|
|
6
|
+
|
|
7
|
+
```html
|
|
8
|
+
|
|
9
|
+
<component id="NavTreeItem">
|
|
10
|
+
<a href="id">
|
|
11
|
+
<span>{name | slice:0:50 | capitalize}</span>
|
|
12
|
+
<span If="label" class="label label-{type}">{label}</span>
|
|
13
|
+
</a>
|
|
14
|
+
</component>
|
|
15
|
+
|
|
16
|
+
<component id="NavTree">
|
|
17
|
+
<ul class="nav">
|
|
18
|
+
<li class="nav-item {item.class}" Each="item of data">
|
|
19
|
+
<NavTreeItem Props="{item}">
|
|
20
|
+
<NavTree If="item.subs" data="{item.subs}" />
|
|
21
|
+
</li>
|
|
22
|
+
</ul>
|
|
23
|
+
</component>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Composition Control flow.
|
|
27
|
+
|
|
28
|
+
### Conditionals.
|
|
29
|
+
|
|
30
|
+
With `If` attribute, an element(and its inner context) presents only if value of expression is truthy.
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<div ... If="enabled">...</div>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
#### full `then-else` syntax
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<Fragment If="enabled">
|
|
40
|
+
<Then><Case1 /></Then>
|
|
41
|
+
<Else><Case2 /></Else>
|
|
42
|
+
</Fragment>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Iterations.
|
|
46
|
+
|
|
47
|
+
`Each` attribute multiplies component instances along items from given array.
|
|
48
|
+
|
|
49
|
+
```html
|
|
50
|
+
<ul>
|
|
51
|
+
<li Each="item of data">
|
|
52
|
+
<a href="/item/{item.id}">{item.position}. {item.name}</span>
|
|
53
|
+
</li>
|
|
54
|
+
</ul>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
> - items MUST HAVE unique `id` field
|
|
58
|
+
|
|
59
|
+
### Fragment.
|
|
60
|
+
|
|
61
|
+
`<Fragment>` is a transparent container and works just like a parens for multiple components.
|
|
62
|
+
|
|
63
|
+
```html
|
|
64
|
+
<Fragment If="enabled"> <innerContent1 />...<innerContentN /> </Fragment>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Dynamic tags.
|
|
68
|
+
|
|
69
|
+
Used to calculate tag dunamically at runtime.
|
|
70
|
+
|
|
71
|
+
```html
|
|
72
|
+
<Dynamic As="Field.{type}" ...></Dynamic>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
> it will fallback to a `Field` if a specific type not found.
|
|
76
|
+
|
|
77
|
+
## Properties.
|
|
78
|
+
|
|
79
|
+
Component state can be mutated different ways listed below.
|
|
80
|
+
State updates lead to redraw UI and notify subscribers(left arrows)
|
|
81
|
+
Updating data is compared with existing state values for 'sameness' (same set of same values).
|
|
82
|
+
|
|
83
|
+
### with scalar literals
|
|
84
|
+
|
|
85
|
+
`prop1="'somestring'"` puts a literal into `prop1` property.
|
|
86
|
+
|
|
87
|
+
> - 'true', 'false' values are narrowed to boolean,
|
|
88
|
+
> - numbers has been narrowed to number type.
|
|
89
|
+
|
|
90
|
+
### with resources values
|
|
91
|
+
|
|
92
|
+
`R`-prefix used to refer any value in the resource bundle.
|
|
93
|
+
|
|
94
|
+
`prop="R.resId"` assigns `resId` resource value to `prop`.
|
|
95
|
+
|
|
96
|
+
### with result of expression
|
|
97
|
+
|
|
98
|
+
`prop="{prop2}"` assigns value of `prop2` property of the current scope.
|
|
99
|
+
|
|
100
|
+
`prop="{data.key}"` assigns value of `data.key`.
|
|
101
|
+
|
|
102
|
+
`prop="{!prop2}"` assigns inverted value of `prop2`
|
|
103
|
+
|
|
104
|
+
`Props="{data}"` special `Props` property used to spread keys/values of `data` into properties of a target entity.
|
|
105
|
+
|
|
106
|
+
### with result of chain of pipes
|
|
107
|
+
|
|
108
|
+
`prop="{some | pipeFn1 : 'strLiteral1' : 1 : true | pipeFn2 : property2 | pipeFn2 : R.resourceId}` applies chain of pipes.
|
|
109
|
+
|
|
110
|
+
> - Pipe functions can be chained. Result of the previous one passed as a first argument to the next one.
|
|
111
|
+
> - Optional colon-separated arguments can be passed to a pipe function as second, third arguments.
|
|
112
|
+
> - Use shortcuts like `==, && , ??, ?, >, <, []` for `equals, and, or, then, less, greater, dot` functions respectively.
|
|
113
|
+
> - There is no operation priority, they applied in left-to-right order.
|
|
114
|
+
|
|
115
|
+
### `data-*` attributes
|
|
116
|
+
|
|
117
|
+
All `data-[key]` attributes will be collected into single `data` object property under its keys.
|
|
118
|
+
|
|
119
|
+
### References.
|
|
120
|
+
|
|
121
|
+
Add `Ref` attribute to any component to get refer it in `arrows` expressions.
|
|
122
|
+
|
|
123
|
+
```html
|
|
124
|
+
<UserService Ref="user" /> <UserAvatar data="<- user.profile" onSave="-> user.update" />
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
> use comma to separate multiple aliases `Ref="api,db,auth"`
|
|
128
|
+
|
|
129
|
+
## Left arrow expression
|
|
130
|
+
|
|
131
|
+
`data="<- ref.prop"` makes a hot subscription to any property of orbitrary component in the current or upper scopes.
|
|
132
|
+
|
|
133
|
+
> use pipes to adapt received value `data="<- ref.prop | adjustFn"`.
|
|
134
|
+
|
|
135
|
+
## Right arrow expression
|
|
136
|
+
|
|
137
|
+
Right arrow creates a function, that
|
|
138
|
+
|
|
139
|
+
- `action="data-> ref.submit(data)"` invokes `scope.refs[ref].submit(data)` action with an `data` object as parameter.
|
|
140
|
+
|
|
141
|
+
- `action="-> ref.submit(prop1)"` invokes `scope.refs[ref].submit(data)` action with a value of property `prop1` as parameter.
|
|
142
|
+
|
|
143
|
+
- `action="-> ref.prop1"` updates container state for given key `scope.refs[ref].up({ prop1: data })`.
|
|
144
|
+
|
|
145
|
+
> `action="data-> ref.action(data | prepare)` pipes will be applied on `data`-object before it passed to the action.
|
|
146
|
+
|
|
147
|
+
> `click="-> opened"` if `ref` is omitted, then a target will be a scope component `scope.up({opened:data})`
|
|
148
|
+
|
|
149
|
+
> `click="->"` spreads data to state of a scope component `scope.up(data)`
|
|
150
|
+
|
|
151
|
+
- `click="data-> * = data | assignKeyValue:'key':value"` updates a scope properties with result of `assignKeyValue` function on `data` object and other args.
|
|
152
|
+
|
|
153
|
+
- `click="-> prop" data="{data}"` updates a `prop` property with `data` object.
|
|
154
|
+
|
|
155
|
+
- `click="-> prop='literalValue'"` updates a given scope property with literal.
|
|
156
|
+
|
|
157
|
+
## Connector
|
|
158
|
+
|
|
159
|
+
Special build-in `Connector` component serves for async data binding
|
|
160
|
+
It acts with timeout(0 by default) and debounces if any:
|
|
161
|
+
|
|
162
|
+
```html
|
|
163
|
+
<!-- `data` works as a `trigger`, if none specified. -->
|
|
164
|
+
<Connector data="<- todo.shownItems|adjust" change="-> someData" />
|
|
165
|
+
|
|
166
|
+
<!-- `change` is invokes with `data` on `trigger` changed. -->
|
|
167
|
+
<Connector
|
|
168
|
+
data="someData"
|
|
169
|
+
trigger="<- todo.shownItemsCount"
|
|
170
|
+
timeout="100"
|
|
171
|
+
change="data-> discriminant=data|calculate"
|
|
172
|
+
/>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Slots
|
|
176
|
+
|
|
177
|
+
Slots are placeholders to inject an inner content of component usage tag.
|
|
178
|
+
|
|
179
|
+
```html
|
|
180
|
+
<Comp>
|
|
181
|
+
<!-- inner content of component usage -->
|
|
182
|
+
<InnerContent />
|
|
183
|
+
</Comp>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
```html
|
|
187
|
+
<component id="Comp">
|
|
188
|
+
<div class="container">
|
|
189
|
+
<!-- Inner content will replace <Slot/> -->
|
|
190
|
+
<Slot>
|
|
191
|
+
</div>
|
|
192
|
+
</component>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Multi-part extra content.
|
|
196
|
+
|
|
197
|
+
Inner content could be multiple-part and thus, distributed separately inside component template.
|
|
198
|
+
|
|
199
|
+
```html
|
|
200
|
+
<Comp>
|
|
201
|
+
<Comp:key1><Extra1 /></Comp:key1>
|
|
202
|
+
<Comp:key2><Extra2 /></Comp:key2>
|
|
203
|
+
<DefaultSlotContent />
|
|
204
|
+
</Comp>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
```html
|
|
208
|
+
<div class="component template">
|
|
209
|
+
|
|
210
|
+
<!-- <Extra1/> will be placed here-->
|
|
211
|
+
<Slot Key="key1">
|
|
212
|
+
|
|
213
|
+
<!-- special `slot(key)` conditional expression may be used to check if non-empty slot content passed. -->
|
|
214
|
+
<div class="comp" If="slot(key2)">
|
|
215
|
+
<!-- <Extra2/> will be placed here -->
|
|
216
|
+
<Slot Key="key2">
|
|
217
|
+
</div>
|
|
218
|
+
|
|
219
|
+
<!-- <DefaultContent/> will be placed here -->
|
|
220
|
+
<Slot>
|
|
221
|
+
</div>
|
|
222
|
+
```
|
package/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { IArrmatronRoot, IPlatform } from "arrmatura/types";
|
|
2
2
|
|
|
3
3
|
import { CRootNode } from "./src/registry/root";
|
|
4
4
|
|
|
@@ -11,12 +11,12 @@ export * from "./src/core/Component";
|
|
|
11
11
|
*
|
|
12
12
|
* @param {IPlatform} platform - The platform on which to launch the template.
|
|
13
13
|
* @param {string} template - The template to launch with.
|
|
14
|
-
* @return {
|
|
14
|
+
* @return {IArrmatronRoot} The root context object.
|
|
15
15
|
*/
|
|
16
|
-
export const launch = (platform: IPlatform, template: string):
|
|
16
|
+
export const launch = (platform: IPlatform, template: string): IArrmatronRoot => {
|
|
17
17
|
const root = new CRootNode(template).createArrmatron(platform);
|
|
18
18
|
|
|
19
|
-
root.
|
|
19
|
+
root.touch();
|
|
20
20
|
|
|
21
21
|
return root;
|
|
22
22
|
};
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arrmatura",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.3",
|
|
4
4
|
"description": "Arrmatura runtime engine",
|
|
5
5
|
"author": "alitskevich@gmail.com",
|
|
6
6
|
"license": "ISC",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"exports": {
|
|
9
|
-
"import": "./index.
|
|
10
|
-
"require": "./dist/index.
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"require": "./dist/index.cjs"
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
13
|
"src",
|
|
@@ -17,11 +17,13 @@
|
|
|
17
17
|
"docs/**/*"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"arrmatura": "6.3.
|
|
21
|
-
"ultimus": "2.1.
|
|
20
|
+
"arrmatura": "6.3.3",
|
|
21
|
+
"ultimus": "2.1.11"
|
|
22
22
|
},
|
|
23
23
|
"scripts": {
|
|
24
|
-
"esbuild": "
|
|
24
|
+
"esbuild": "npm run esbuild:esm && npm run esbuild:cjs",
|
|
25
|
+
"esbuild:esm": "esbuild index.ts --bundle --outfile=./dist/index.js --platform=browser --format=esm --sourcemap --target=esnext --minify",
|
|
26
|
+
"esbuild:cjs": "esbuild index.ts --bundle --outfile=./dist/index.cjs --platform=node --format=cjs --sourcemap --target=es2021 --minify",
|
|
25
27
|
"pnpm:publish": "pnpm publish --no-git-checks"
|
|
26
28
|
}
|
|
27
29
|
}
|