arrmatura 4.3.2 → 5.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/README.md +22 -22
- package/commons/auth/UserService.ts +107 -0
- package/commons/auth/index.ts +4 -0
- package/commons/auth/user.xml +66 -0
- package/commons/components/buttons.xml +23 -0
- package/commons/components/index.ts +13 -0
- package/commons/components/inputs.xml +33 -0
- package/commons/components/layouts.xml +77 -0
- package/commons/components/media.xml +21 -0
- package/commons/components/modal.xml +37 -0
- package/commons/components/navigation.xml +59 -0
- package/commons/components/popups.xml +12 -0
- package/commons/components/searchbar.xml +40 -0
- package/commons/components/table.xml +120 -0
- package/commons/components/toasts.xml +13 -0
- package/commons/components/viewport.xml +48 -0
- package/commons/forms/FieldItem.xml +20 -0
- package/commons/forms/FormController.ts +73 -0
- package/commons/forms/Item.ts +68 -0
- package/commons/forms/ItemCollection.ts +152 -0
- package/commons/forms/ItemController.ts +62 -0
- package/commons/forms/MetadataService.ts +45 -0
- package/commons/forms/MultiEnumField.xml +44 -0
- package/commons/forms/MultivalueController.ts +49 -0
- package/commons/forms/SmartareaField.xml +51 -0
- package/commons/forms/SuggestionController.ts +80 -0
- package/commons/forms/SuggestionField.xml +28 -0
- package/commons/forms/fields.xml +138 -0
- package/commons/forms/form.xml +37 -0
- package/commons/forms/index.ts +29 -0
- package/commons/index.ts +6 -0
- package/commons/pipes/index.ts +21 -0
- package/commons/pipes/showCounts.ts +16 -0
- package/commons/services/ErrorHandlingService.ts +11 -0
- package/commons/services/FirebaseService.ts +185 -0
- package/commons/services/GSheetsService.ts +92 -0
- package/commons/services/HeartbeatService.ts +35 -0
- package/commons/services/Invoke.ts +13 -0
- package/commons/services/JsonpService.ts +18 -0
- package/commons/services/Loader.ts +17 -0
- package/commons/services/LocalStorage.ts +46 -0
- package/commons/services/NavigationService.ts +55 -0
- package/commons/services/Service.ts +68 -0
- package/commons/services/ServiceWorker.ts +111 -0
- package/commons/services/ToastService.ts +49 -0
- package/commons/services/index.ts +14 -0
- package/core/Arrmatura.ts +79 -0
- package/core/CNode.ts +112 -0
- package/core/Component.ts +431 -0
- package/core/Platform.ts +3 -0
- package/core/cnodes/composition.ts +100 -0
- package/core/cnodes/conditionals.ts +51 -0
- package/core/cnodes/elementary.ts +45 -0
- package/core/cnodes/iterations.ts +94 -0
- package/core/cnodes/routing.ts +25 -0
- package/core/compileNode.ts +39 -0
- package/core/expression.ts +73 -0
- package/core/index.ts +2 -0
- package/core/register.ts +43 -0
- package/core/utils.ts +25 -0
- package/docs/index.js +191 -4069
- package/lib/arrayGroupBy.ts +19 -0
- package/lib/arraySortBy.ts +49 -0
- package/lib/arrayToObject.ts +18 -0
- package/lib/codus.ts +25 -0
- package/lib/consts.ts +3 -0
- package/lib/createListeners.ts +12 -0
- package/lib/curry.ts +8 -0
- package/lib/dateFormat.ts +69 -0
- package/lib/dateOf.ts +31 -0
- package/lib/dateParseISO8601.ts +27 -0
- package/lib/fx.ts +62 -0
- package/lib/guid.ts +7 -0
- package/lib/index.ts +19 -0
- package/lib/l10n.ts +40 -0
- package/lib/nextId.ts +9 -0
- package/lib/noop.ts +8 -0
- package/lib/obj.ts +62 -0
- package/lib/predicat.ts +26 -0
- package/lib/resources.ru.ts +20 -0
- package/lib/resources.ts +20 -0
- package/lib/scalar.ts +25 -0
- package/lib/str.ts +76 -0
- package/lib/urls.ts +91 -0
- package/lib/xml.ts +117 -0
- package/package.json +19 -8
- package/docs/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
# Arrmatura
|
|
2
2
|
|
|
3
|
-
`Arrmatura`
|
|
4
|
-
|
|
5
|
-
`Arrmatura` is intended to be
|
|
3
|
+
`Arrmatura` is a ultimate `specification-as-a-code` component framework.
|
|
6
4
|
|
|
7
5
|
- declarative and codeless
|
|
8
6
|
- non-obtrusive, platform-independent
|
|
9
7
|
- reactive and functional oriented
|
|
10
8
|
- easy to learn and get started.
|
|
11
9
|
|
|
12
|
-
`Arrmatura` is a minimalistic UI framework, that enriches the pure HTML with components, arrows and pipes.
|
|
13
|
-
|
|
14
|
-
Born-for-dom, it is also may be adopted to develop wide range of modular component-based applications.
|
|
15
|
-
|
|
16
10
|
# Get Started
|
|
17
11
|
|
|
18
12
|
npm i arrmatura
|
|
19
13
|
|
|
20
14
|
```javascript
|
|
21
|
-
import {
|
|
15
|
+
import { launchWeb } from 'arrmatura';
|
|
22
16
|
|
|
23
|
-
const components =
|
|
24
|
-
<Button title=":send_title|upper">
|
|
25
|
-
</component>`;
|
|
17
|
+
const components = `
|
|
26
18
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
<component id="Application">
|
|
20
|
+
<Main name="Joe"/>
|
|
21
|
+
</component>
|
|
22
|
+
|
|
23
|
+
<component id="Main">
|
|
24
|
+
<Button title="{:greeting}, {name|upper}">
|
|
25
|
+
</component>
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
launchWeb('<Application />', {
|
|
29
|
+
types: [components],
|
|
30
30
|
resources: {
|
|
31
|
-
|
|
31
|
+
greeting: 'Hello!',
|
|
32
32
|
},
|
|
33
33
|
pipes: {
|
|
34
34
|
upper: (x) => x.toUpperCase(),
|
|
@@ -36,14 +36,14 @@ launch({
|
|
|
36
36
|
});
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
Please take a look into [Todo App](https://alitskevich.github.io/arrmatura/todo.html) to get very basic insight how it works.
|
|
40
|
-
|
|
41
39
|
# Documentation
|
|
42
40
|
|
|
43
|
-
- [Glossary](
|
|
44
|
-
- [Templates](
|
|
45
|
-
- [Custom components](
|
|
41
|
+
- [Glossary](manuals/GLOSSARY.md)
|
|
42
|
+
- [Templates](manuals/TEMPLATE.md)
|
|
43
|
+
- [Custom components](manuals/CUSTOM.md)
|
|
46
44
|
|
|
47
|
-
#
|
|
45
|
+
# Samples
|
|
48
46
|
|
|
49
|
-
- [
|
|
47
|
+
- [TodoMVC](https://alitskevich.github.io/arrmatura/todo.html)
|
|
48
|
+
- [Tasks](https://alitskevich.github.io/arrmatura/task.html)
|
|
49
|
+
- [TicTacToe](https://alitskevich.github.io/arrmatura/tictactoe.html)
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Service } from '../services/Service';
|
|
2
|
+
import { urlAppendParams } from 'urls';
|
|
3
|
+
import { LocalStorage } from '../services/LocalStorage';
|
|
4
|
+
|
|
5
|
+
export class UserService extends Service {
|
|
6
|
+
url: string = '';
|
|
7
|
+
kind: string = '$user';
|
|
8
|
+
local: LocalStorage = new LocalStorage('local');
|
|
9
|
+
token: any;
|
|
10
|
+
$info: unknown;
|
|
11
|
+
|
|
12
|
+
init() {
|
|
13
|
+
return this.syncUserInfo();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
syncUserInfo() {
|
|
17
|
+
const token = this.token || this.local?.get('$token');
|
|
18
|
+
|
|
19
|
+
return !token
|
|
20
|
+
? null
|
|
21
|
+
: {
|
|
22
|
+
isLoading: true,
|
|
23
|
+
'*': fetch(urlAppendParams(this.url, { action: 'user', token }), { redirect: 'follow' })
|
|
24
|
+
.then((res) => res.json())
|
|
25
|
+
.then(({ info, error }) => {
|
|
26
|
+
if (error) throw error;
|
|
27
|
+
this.log('sync' + this.kind, info);
|
|
28
|
+
this.local?.set('$token', token);
|
|
29
|
+
return { info, isLoading: false };
|
|
30
|
+
})
|
|
31
|
+
.catch((err) => {
|
|
32
|
+
this.toast({ mode: 'error', message: 'Ошибка: ' + JSON.stringify(err?.message || err || 'unknown') });
|
|
33
|
+
return { info: null, isLoading: false };
|
|
34
|
+
}),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
set info(info: unknown) {
|
|
39
|
+
this.$info = info;
|
|
40
|
+
this.local?.set(this.kind, info);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get info() {
|
|
44
|
+
const info = this.$info || this.local?.get(this.kind);
|
|
45
|
+
return info;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get isSignedIn() {
|
|
49
|
+
return this.info?.id;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async update(delta: Delta) {
|
|
53
|
+
const now = Date.now();
|
|
54
|
+
const { since, items: items0 = [] } = this.local?.get(this.kind) || { since: 0, items: {} };
|
|
55
|
+
|
|
56
|
+
this.log('update', delta);
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
busy: true,
|
|
60
|
+
'*': fetch(this.url, {
|
|
61
|
+
method: 'POST',
|
|
62
|
+
mode: 'cors',
|
|
63
|
+
redirect: 'follow',
|
|
64
|
+
body: JSON.stringify({ action: 'upsert', delta }),
|
|
65
|
+
})
|
|
66
|
+
.then((res) => res.json())
|
|
67
|
+
.then(({ id, error }) => {
|
|
68
|
+
if (error) throw error;
|
|
69
|
+
// items: items1 }
|
|
70
|
+
this.log('update sync' + this.kind, now, id);
|
|
71
|
+
// const items = { ...items0, ...arrayToObject(items1) };
|
|
72
|
+
this.toast('Сохранено успешно');
|
|
73
|
+
|
|
74
|
+
// this.local?.set(this.kind, { since: now, items });
|
|
75
|
+
return { busy: false }; //items,
|
|
76
|
+
})
|
|
77
|
+
.catch((err) => {
|
|
78
|
+
this.toast({ mode: 'error', message: 'Ошибка: update ' + JSON.stringify(err?.message || err || 'unknown') });
|
|
79
|
+
return { busy: false };
|
|
80
|
+
}),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
onUpdate(data, { info }) {
|
|
85
|
+
return {
|
|
86
|
+
info: { ...info, ...data },
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
onLogin() {
|
|
91
|
+
return {
|
|
92
|
+
info: { id: 1, name: 'Me' },
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
onShowProfile(showProfile = false) {
|
|
97
|
+
return {
|
|
98
|
+
showProfile,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
onLogout() {
|
|
103
|
+
return {
|
|
104
|
+
info: { id: 0, name: 'Me222' },
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<component id="UserBar">
|
|
2
|
+
<div class="float-right">
|
|
3
|
+
<UserLoading ui:if="<-user.isLoading">
|
|
4
|
+
<ui:else>
|
|
5
|
+
<NoUserPanel ui:if="<-user.isSignedIn|not">
|
|
6
|
+
<ui:else>
|
|
7
|
+
<UserPanel ui:props="<-user.info" defaultImage="assets/img/avatar-1.png"/>
|
|
8
|
+
</ui:else>
|
|
9
|
+
</NoUserPanel>
|
|
10
|
+
</ui:else>
|
|
11
|
+
</UserLoading>
|
|
12
|
+
</div>
|
|
13
|
+
</component>
|
|
14
|
+
|
|
15
|
+
<component id="UserLoading">
|
|
16
|
+
<div class="tile tile-centered">
|
|
17
|
+
<div class="tile-action">
|
|
18
|
+
<div class="dropdown dropdown-right">
|
|
19
|
+
<a class="btn btn-link dropdown-toggle" tabindex="0">
|
|
20
|
+
<div class="mx-2 loading"></div>
|
|
21
|
+
</a>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</component>
|
|
26
|
+
|
|
27
|
+
<component id="UserPanel">
|
|
28
|
+
<div class="tile tile-centered">
|
|
29
|
+
<div class="tile-icon">
|
|
30
|
+
<div class="example-tile-icon c-hand" click="-> user.showProfile|truthy">
|
|
31
|
+
<figure class="avatar">
|
|
32
|
+
<img src="{image|or:@defaultImage}" alt="{name}" />
|
|
33
|
+
</figure>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
<div class="tile-action">
|
|
37
|
+
<div class="dropdown dropdown-right">
|
|
38
|
+
<a class="btn btn-link dropdown-toggle" tabindex="0">
|
|
39
|
+
<i class="icon icon-more-vert"></i >
|
|
40
|
+
</a>
|
|
41
|
+
<ul class="menu">
|
|
42
|
+
<li class="menu-item">
|
|
43
|
+
<a click="-> user.logout">⏹️Vyxod</a>
|
|
44
|
+
</li>
|
|
45
|
+
</ul>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
</component>
|
|
50
|
+
|
|
51
|
+
<component id="NoUserPanel">
|
|
52
|
+
<div class="tile tile-centered">
|
|
53
|
+
<div class="tile-action">
|
|
54
|
+
<div class="dropdown dropdown-right">
|
|
55
|
+
<a class="btn btn-link dropdown-toggle" tabindex="0">
|
|
56
|
+
<i class="icon icon-more-vert"></i >
|
|
57
|
+
</a>
|
|
58
|
+
<ul class="menu">
|
|
59
|
+
<li class="menu-item">
|
|
60
|
+
<a click="-> user.login">▶️Vxod</a>
|
|
61
|
+
</li>
|
|
62
|
+
</ul>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</component>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<component id="Btn">
|
|
2
|
+
<button class="
|
|
3
|
+
btn btn-{mode}
|
|
4
|
+
{primary|then:btn-primary}
|
|
5
|
+
{disabled|or:@busy|then:disabled}
|
|
6
|
+
{class}
|
|
7
|
+
{large|then:btn-lg}
|
|
8
|
+
{link|then:btn-link}
|
|
9
|
+
c-hand
|
|
10
|
+
" style="{style}" data={data} click="{action}">
|
|
11
|
+
<span ui:if="{busy}" class="mx-2">
|
|
12
|
+
<i class="loading"></i>
|
|
13
|
+
</span>
|
|
14
|
+
<Icon ui:if="{icon}" bundle="{iconBundle}" type="{icon}" class="mr-2" />
|
|
15
|
+
<span ui:if="{title}" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">{title}</span>
|
|
16
|
+
</button>
|
|
17
|
+
</component>
|
|
18
|
+
|
|
19
|
+
<component id="FAB">
|
|
20
|
+
<button class="btn {tooltip|then:tooltip} tooltip-left fixed bg-error s-circle centroid c-hand {class} {disabled|or:@busy|then:disabled} {busy|then:loading}" style="position: fixed; border: none; right: 1.5rem; bottom: 1.5rem; width: 2.5rem; height: 2.5rem;" data="{data}" data-tooltip="{tooltip|or:}" click="{action}">
|
|
21
|
+
<Icon type="{icon|or:plus}" />
|
|
22
|
+
</button>
|
|
23
|
+
</component>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import buttons from './buttons.xml';
|
|
2
|
+
import table from './table.xml';
|
|
3
|
+
import inputs from './inputs.xml';
|
|
4
|
+
import media from './media.xml';
|
|
5
|
+
import modal from './modal.xml';
|
|
6
|
+
import navigation from './navigation.xml';
|
|
7
|
+
import layouts from './layouts.xml';
|
|
8
|
+
import viewport from './viewport.xml';
|
|
9
|
+
import toasts from './toasts.xml';
|
|
10
|
+
import searchbar from './searchbar.xml';
|
|
11
|
+
import popups from './popups.xml';
|
|
12
|
+
|
|
13
|
+
export default [buttons, media, table, modal, navigation, toasts, viewport, layouts, inputs, searchbar, popups];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<component id="Select">
|
|
2
|
+
<select class="{class}" change="{change}" multiple="{multiple}" disabled="{disabled}" data="{data}">
|
|
3
|
+
<option selected="{value|not}" value="" ui:if="{value|not|or:@emptyCaption}">{emptyCaption}</option>
|
|
4
|
+
<option ui:for="option of options" selected="{option.id|equals:@value}" value="{option.id}">{option.name}</option>
|
|
5
|
+
</select>
|
|
6
|
+
</component>
|
|
7
|
+
|
|
8
|
+
<component id="RadioGroup">
|
|
9
|
+
<div class="{class}">
|
|
10
|
+
<label class="form-radio" ui:for="option of options">
|
|
11
|
+
<input type="radio" name="{id|or:rg}" value="{option.id}" checked="{option.id|equals:@value}" change="{change}" data="{data}" disabled="{disabled}" />
|
|
12
|
+
<i class="form-icon"></i>{option.name}
|
|
13
|
+
</label>
|
|
14
|
+
</div>
|
|
15
|
+
</component>
|
|
16
|
+
|
|
17
|
+
<component id="Dropdown">
|
|
18
|
+
<div class="dropdown">
|
|
19
|
+
<a href="#" class="btn btn-link dropdown-toggle" tabindex="0">
|
|
20
|
+
{data|selectedName}<i class="icon icon-caret"></i>
|
|
21
|
+
</a>
|
|
22
|
+
<!-- menu component -->
|
|
23
|
+
<ul class="menu" style="right: 0; left: auto">
|
|
24
|
+
<li ui:for="item of data" class="menu-item {item.id|equals:@value|then:active}" data-id="{item.id}" data-name="{item.name}" click="{change}">
|
|
25
|
+
<a>{item.name}</a>
|
|
26
|
+
</li>
|
|
27
|
+
</ul>
|
|
28
|
+
</div>
|
|
29
|
+
</component>
|
|
30
|
+
|
|
31
|
+
<component id="DateTimeInput">
|
|
32
|
+
<input class="form-input flatpickr-input" init="{:support.initFlatpickr}" disabled="{disabled}" type="text" placeholder="{placeholder}" value="{value|support.setFlatpickrValue}" change="{change}" />
|
|
33
|
+
</component>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<component id="Container">
|
|
2
|
+
<div class="container {class}" style="max-width: 720px;">
|
|
3
|
+
<a name="top"></a>
|
|
4
|
+
<ui:slot />
|
|
5
|
+
</div>
|
|
6
|
+
</component>
|
|
7
|
+
|
|
8
|
+
<component id="Panel">
|
|
9
|
+
<h6 class="mt-2 pt-2 px-2 text-gray" ui:if="caption">{caption}</h6>
|
|
10
|
+
<div class="panel {class}" style="{style}">
|
|
11
|
+
<small class="p-2 bg-secondary" ui:if="{hint}">{hint}</small>
|
|
12
|
+
<div class="panel-header" ui:if="slot(title)">
|
|
13
|
+
<div class="panel-title">
|
|
14
|
+
<ui:slot id="title" key="panel-title" />
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="panel-nav" ui:if="slot(nav)">
|
|
18
|
+
<ui:slot id="nav" />
|
|
19
|
+
</div>
|
|
20
|
+
<div class="panel-body p-2">
|
|
21
|
+
<ui:slot />
|
|
22
|
+
</div>
|
|
23
|
+
<div class="panel-footer" ui:if="slot(footer)">
|
|
24
|
+
<ui:slot id="footer" />
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</component>
|
|
28
|
+
|
|
29
|
+
<component id="Tile">
|
|
30
|
+
<div class="tile {centered|then:tile-centered} m-2 {class}">
|
|
31
|
+
<div class="tile-icon" ui:if="{image}">
|
|
32
|
+
<Avatar src="{image}" />
|
|
33
|
+
</div>
|
|
34
|
+
<div class="tile-icon" ui:if="{icon}">
|
|
35
|
+
<Icon type="{icon}" />
|
|
36
|
+
</div>
|
|
37
|
+
<div class="tile-content">
|
|
38
|
+
<div class="tile-title text-bold" ui:if="{title}">{title}</div>
|
|
39
|
+
<div class="tile-subtitle" ui:if="{subtitle}">{subtitle}</div>
|
|
40
|
+
<ui:slot />
|
|
41
|
+
</div>
|
|
42
|
+
<div class="tile-action btn-group" ui:if="slot(actions)">
|
|
43
|
+
<ui:slot id="actions" />
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</component>
|
|
47
|
+
|
|
48
|
+
<component id="Card">
|
|
49
|
+
<div class="card" style="{style}">
|
|
50
|
+
<div class="card-image" ui:if="{image}">
|
|
51
|
+
<img src="{image}" class="img-responsive" />
|
|
52
|
+
</div>
|
|
53
|
+
<div class="card-header">
|
|
54
|
+
<a ui:if="{title}" href="{link}">
|
|
55
|
+
<h5 class="card-title">{title}</h5>
|
|
56
|
+
</a>
|
|
57
|
+
<div ui:if="{subtitle}" class="card-subtitle text-gray">{subtitle}</div>
|
|
58
|
+
<ui:slot id="header" />
|
|
59
|
+
</div>
|
|
60
|
+
<div class="card-body">
|
|
61
|
+
<ui:slot />
|
|
62
|
+
</div>
|
|
63
|
+
<div class="card-footer">
|
|
64
|
+
<ui:slot id="footer" />
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</component>
|
|
68
|
+
|
|
69
|
+
<component id="Hero">
|
|
70
|
+
<div class="hero bg-dark p-0">
|
|
71
|
+
<div class="hero-body px-2">
|
|
72
|
+
<h1>{title}</h1>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</component>
|
|
76
|
+
|
|
77
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<component id="Icon">
|
|
2
|
+
<i class="icon icon-{type} {class}" style="{style}" data="{data}" click="{click}"></i>
|
|
3
|
+
</component>
|
|
4
|
+
|
|
5
|
+
<component id="Img">
|
|
6
|
+
<img src="{src|or:@default}" alt="{alt}" class="img {class}" style="{style}" />
|
|
7
|
+
</component>
|
|
8
|
+
|
|
9
|
+
<component id="ImgLogo">
|
|
10
|
+
<img src="{src}" class="{class}" error="->" data-src="/assets/logo.jpg" />
|
|
11
|
+
</component>
|
|
12
|
+
|
|
13
|
+
<component id="IFrame">
|
|
14
|
+
<iframe width="100%" height="450" frameborder="0" style="border: 0;" src="{src}" allowfullscreen="1"></iframe>
|
|
15
|
+
</component>
|
|
16
|
+
|
|
17
|
+
<component id="Avatar">
|
|
18
|
+
<figure class="avatar {large|then:avatar-lg}">
|
|
19
|
+
<img src="{src}" alt="{alt}" default="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" />
|
|
20
|
+
</figure>
|
|
21
|
+
</component>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<component id="Modal">
|
|
2
|
+
<!--
|
|
3
|
+
|
|
4
|
+
Modal component:
|
|
5
|
+
|
|
6
|
+
Slots:
|
|
7
|
+
- header
|
|
8
|
+
- default
|
|
9
|
+
- footer
|
|
10
|
+
|
|
11
|
+
Properties:
|
|
12
|
+
- open: boolean
|
|
13
|
+
- close: procedure
|
|
14
|
+
- title: string
|
|
15
|
+
- mode: lg|sm
|
|
16
|
+
|
|
17
|
+
-->
|
|
18
|
+
<div class="modal modal-{mode} {open|then:active}">
|
|
19
|
+
<a class="modal-overlay" aria-label="Close" click="{close}"></a>
|
|
20
|
+
<div class="modal-container" style="padding:0;max-height: {mode|equals:lg|then:100:70}vh">
|
|
21
|
+
<div class="modal-header" style="padding-bottom:0;">
|
|
22
|
+
<a class="btn btn-clear float-right" aria-label=":close" click="{close}"></a>
|
|
23
|
+
<div class="modal-title h5" ui:if="{title}">{title}</div>
|
|
24
|
+
<ui:slot id="header" />
|
|
25
|
+
</div>
|
|
26
|
+
<div class="modal-body" style="">
|
|
27
|
+
<div class="content">
|
|
28
|
+
<ui:slot />
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="modal-footer">
|
|
32
|
+
<ui:slot id="footer" />
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</component>
|
|
37
|
+
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<component id="Tabs">
|
|
2
|
+
<ul class="tab tab-block">
|
|
3
|
+
<li class="tab-item {item.id|equals:@value|then:active} c-hand" ui:for="item of items">
|
|
4
|
+
<a data-id="{item.id}" click="{change}">
|
|
5
|
+
<Icon ui:if="{item.icon}" type="{item.icon}" bundle="{item.iconBundle}" class="mx-2" />
|
|
6
|
+
{item.name|or:@item.id}
|
|
7
|
+
</a>
|
|
8
|
+
</li>
|
|
9
|
+
</ul>
|
|
10
|
+
</component>
|
|
11
|
+
|
|
12
|
+
<component id="BackButton">
|
|
13
|
+
<a class="mx-2" style="border: none; width: 1.5rem; z-index: 5" href="{href}">
|
|
14
|
+
<Icon type="back" />
|
|
15
|
+
</a>
|
|
16
|
+
</component>
|
|
17
|
+
|
|
18
|
+
<component id="Navbar">
|
|
19
|
+
<header class="navbar sticky {class} bg-secondary" style="min-height: 48px;flex-wrap: nowrap;margin:0;">
|
|
20
|
+
<section class="navbar-section">
|
|
21
|
+
<div class="m-2 flexoid items-center">
|
|
22
|
+
<ui:slot id="left" />
|
|
23
|
+
<h5 class="m-1 text-dark {badge|then:badge}" style="vertical-align: middle" data-badge="{badge}" ui:if="{caption}">{caption}</h5>
|
|
24
|
+
</div>
|
|
25
|
+
</section>
|
|
26
|
+
<section class="navbar-center" ui:if="{logo}">
|
|
27
|
+
<img src="{logo}" style="max-height: 44px" />
|
|
28
|
+
</section>
|
|
29
|
+
<section class="navbar-section flex-0 mx-2" ui:if="slot(right)">
|
|
30
|
+
<ui:slot id="right" />
|
|
31
|
+
</section>
|
|
32
|
+
</header>
|
|
33
|
+
</component>
|
|
34
|
+
|
|
35
|
+
<component id="PageRouter">
|
|
36
|
+
<ui:tag tag="{host|capitalize|or:Loader}Page" path={path} ui:props="{params}" params="{params}" />
|
|
37
|
+
</component>
|
|
38
|
+
|
|
39
|
+
<component id="LoaderPage">
|
|
40
|
+
<LoadingIndicator />
|
|
41
|
+
</component>
|
|
42
|
+
|
|
43
|
+
<component id="NavTree">
|
|
44
|
+
<ul class="nav">
|
|
45
|
+
<li class="nav-item {item.class}" ui:for="item of data">
|
|
46
|
+
<NavLink href="{item.id}">
|
|
47
|
+
<span>{item.name}</span>
|
|
48
|
+
<span ui:if="{item.label}" class="label label-error">{item.label}</span>
|
|
49
|
+
</NavLink>
|
|
50
|
+
<NavTree ui:if="{item.subs}" data="{item.subs}" />
|
|
51
|
+
</li>
|
|
52
|
+
</ul>
|
|
53
|
+
</component>
|
|
54
|
+
|
|
55
|
+
<component id="NavLink">
|
|
56
|
+
<a data-value="{href}" click="-> nav.hash" class="c-hand {class}">
|
|
57
|
+
<ui:slot />
|
|
58
|
+
</a>
|
|
59
|
+
</component>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<component id="SearchBar">
|
|
2
|
+
<span class="ant-input-search ant-input-affix-wrapper">
|
|
3
|
+
<input placeholder="Поиск..." class="ant-input" type="text" value="{value}" enter="{action}" style="min-height: 40px" />
|
|
4
|
+
<span class="ant-input-suffix">
|
|
5
|
+
<i class="anticon anticon-search ant-input-search-icon" style="margin-top: 4px"></i>
|
|
6
|
+
</span>
|
|
7
|
+
</span>
|
|
8
|
+
</component>
|
|
9
|
+
|
|
10
|
+
<component id="SearchBarWithSuggestions">
|
|
11
|
+
<ui:fragment ui:if="opened.value">
|
|
12
|
+
<ui:then>
|
|
13
|
+
<div class="form-autocomplete mx-2">
|
|
14
|
+
<!-- autocomplete input container -->
|
|
15
|
+
<div class="form-autocomplete-input form-input input-sm">
|
|
16
|
+
<div class="input-group input-inline">
|
|
17
|
+
<input class="form-input" type="search" autofocus placeholder=":kluq_poshuku" keypress="{input}" value="{value}" style="max-width:120px;width:inherit" />
|
|
18
|
+
<i class="icon icon-cross m-2 c-hand" data-value="" click="{enter}" ui:if="value"></i>
|
|
19
|
+
<i class="icon icon-search m-2 c-hand" click="->opened|assignKeyValue:value:false" ui:if="value|not"></i>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
<ul class="menu" style="min-width: 120px;max-height:7rem;overflow-y:auto;" ui:if="{suggestions}">
|
|
23
|
+
<li class="menu-item" ui:for="item of suggestions" data-value="{item.id}" click="{enter}">
|
|
24
|
+
<a>
|
|
25
|
+
<div class="tile tile-centered">
|
|
26
|
+
<div class="tile-content">{item.name}</div>
|
|
27
|
+
</div>
|
|
28
|
+
</a>
|
|
29
|
+
</li>
|
|
30
|
+
</ul>
|
|
31
|
+
</div>
|
|
32
|
+
</ui:then>
|
|
33
|
+
<ui:else>
|
|
34
|
+
<div class="mx-2" click="{open|bindArgs:true}">
|
|
35
|
+
<i class="icon icon-search m-2 c-hand" click="->opened|assignKeyValue:value:true"></i>
|
|
36
|
+
</div>
|
|
37
|
+
</ui:else>
|
|
38
|
+
</ui:fragment>
|
|
39
|
+
|
|
40
|
+
</component>
|