silentium-components 0.0.5 → 0.0.7
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/CHANGELOG.md +22 -0
- package/dist/silentium-components.cjs +134 -483
- package/dist/silentium-components.cjs.map +1 -1
- package/dist/silentium-components.d.ts +8 -190
- package/dist/silentium-components.js +130 -467
- package/dist/silentium-components.js.map +1 -1
- package/dist/silentium-components.min.js +1 -1
- package/dist/silentium-components.min.mjs +1 -1
- package/dist/silentium-components.min.mjs.map +1 -1
- package/dist/silentium-components.mjs +130 -467
- package/dist/silentium-components.mjs.map +1 -1
- package/docs/build.sh +3 -4
- package/docs/index.html +3 -3
- package/docs/pages/behaviors/deadline.html +60 -0
- package/docs/pages/behaviors.html +5 -0
- package/docs/routes.json +1 -1
- package/eslint.config.mjs +1 -0
- package/package.json +7 -5
- package/src/behaviors/Deadline._value.test.ts +27 -0
- package/src/behaviors/Deadline.test.ts +28 -0
- package/src/behaviors/Deadline.ts +49 -0
- package/src/behaviors/Dirty.test.ts +5 -5
- package/src/behaviors/Dirty.ts +48 -54
- package/src/behaviors/Loading.test.ts +8 -8
- package/src/behaviors/Loading.ts +21 -31
- package/src/behaviors/Path.index.test.ts +5 -5
- package/src/behaviors/Path.nested.test.ts +5 -5
- package/src/behaviors/Path.test.ts +5 -5
- package/src/behaviors/Path.ts +26 -30
- package/src/behaviors/index.ts +1 -1
- package/src/controls/GroupActiveClass.test.ts +16 -13
- package/src/controls/GroupActiveClass.ts +19 -22
- package/src/controls/index.ts +0 -5
- package/src/index.ts +0 -2
- package/src/navigation/Router.test.ts +47 -0
- package/src/navigation/Router.ts +43 -111
- package/src/navigation/index.ts +0 -6
- package/src/strings/Concatenated.test.ts +11 -0
- package/src/strings/Concatenated.ts +18 -0
- package/src/structures/HashTable.test.ts +5 -5
- package/src/structures/HashTable.ts +14 -25
- package/src/system/RegexpMatched.test.ts +14 -0
- package/src/system/RegexpMatched.ts +17 -0
- package/src/system/index.ts +1 -0
- package/src/behaviors/Touched.ts +0 -1
- package/src/controls/ComputedElement.ts +0 -51
- package/src/controls/Input.ts +0 -45
- package/src/controls/Link.ts +0 -53
- package/src/controls/Text.ts +0 -16
- package/src/controls/Visible.ts +0 -16
- package/src/jsdom/JSDomDocument.ts +0 -15
- package/src/jsdom/JSDomElement.ts +0 -28
- package/src/jsdom/JSDomQuerySelector.ts +0 -28
- package/src/navigation/CurrentPage.ts +0 -27
- package/src/navigation/Navigation.default.test.ts +0 -54
- package/src/navigation/Navigation.main.test.ts +0 -47
- package/src/navigation/Navigation.ts +0 -92
- package/src/navigation/Navigation.wildcard.test.ts +0 -52
- package/src/navigation/PageFetchTransport.ts +0 -26
- package/src/navigation/RouteDisplay.ts +0 -18
- package/src/navigation/RoutePageType.ts +0 -3
- package/src/page/EntryPointPage.ts +0 -20
- package/src/page/Page.ts +0 -12
- package/src/page/PageFake.ts +0 -8
- package/src/page/index.ts +0 -2
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Path } from "../behaviors/Path";
|
|
1
|
+
import { sourceSync } from "silentium";
|
|
3
2
|
import { expect, test } from "vitest";
|
|
3
|
+
import { path } from "../behaviors/Path";
|
|
4
4
|
|
|
5
5
|
test("Path.test", () => {
|
|
6
|
-
const record =
|
|
6
|
+
const record = {
|
|
7
7
|
name: "Peter",
|
|
8
8
|
surname: "Parker",
|
|
9
|
-
}
|
|
10
|
-
const name =
|
|
9
|
+
};
|
|
10
|
+
const name = sourceSync(path(record, "name"));
|
|
11
11
|
expect(name.syncValue()).toBe("Peter");
|
|
12
12
|
});
|
package/src/behaviors/Path.ts
CHANGED
|
@@ -1,38 +1,34 @@
|
|
|
1
1
|
import {
|
|
2
2
|
give,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
SourceObjectType,
|
|
3
|
+
patron,
|
|
4
|
+
sourceAll,
|
|
5
|
+
sourceOf,
|
|
7
6
|
SourceType,
|
|
7
|
+
subSourceMany,
|
|
8
8
|
value,
|
|
9
9
|
} from "silentium";
|
|
10
10
|
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
) {}
|
|
11
|
+
export const path = <T extends Record<string, unknown>, K extends string>(
|
|
12
|
+
baseSrc: SourceType<T>,
|
|
13
|
+
keySrc: SourceType<K>,
|
|
14
|
+
) => {
|
|
15
|
+
const pathSrc = sourceOf<T[K]>();
|
|
16
|
+
subSourceMany(pathSrc, [baseSrc, keySrc]);
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
keyChunks.forEach((keyChunk) => {
|
|
28
|
-
value = (value as T)[keyChunk];
|
|
29
|
-
});
|
|
18
|
+
value(
|
|
19
|
+
sourceAll([baseSrc, keySrc]),
|
|
20
|
+
patron(([base, key]) => {
|
|
21
|
+
const keyChunks = key.split(".");
|
|
22
|
+
let value: unknown = base;
|
|
23
|
+
keyChunks.forEach((keyChunk) => {
|
|
24
|
+
value = (value as T)[keyChunk];
|
|
25
|
+
});
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
27
|
+
if (value !== undefined && value !== base) {
|
|
28
|
+
give(value as T[K], pathSrc);
|
|
29
|
+
}
|
|
30
|
+
}),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
return pathSrc.value;
|
|
34
|
+
};
|
package/src/behaviors/index.ts
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { sourceOf, sourceSync, value } from "silentium";
|
|
2
|
+
import { jsdomDocument } from "silentium-jsdom";
|
|
3
|
+
import { element } from "silentium-web-api";
|
|
3
4
|
import { expect, test } from "vitest";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
5
|
+
import { path } from "../behaviors";
|
|
6
|
+
import { groupActiveClass } from "./GroupActiveClass";
|
|
6
7
|
|
|
7
8
|
test("GroupActiveClass.test", () => {
|
|
8
|
-
const document =
|
|
9
|
+
const document = sourceSync(
|
|
10
|
+
jsdomDocument(`<div class="menu">
|
|
9
11
|
<div id="prev-active" class="menu-link active">One</div>
|
|
10
12
|
<div class="menu-link">Two</div>
|
|
11
13
|
<div id="next-active" class="menu-link">Three</div>
|
|
12
|
-
</div>`)
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
const
|
|
14
|
+
</div>`),
|
|
15
|
+
).syncValue();
|
|
16
|
+
const groupElements = path(<any>element(".menu", document), "childNodes");
|
|
17
|
+
const activeElement = sourceOf<HTMLElement>();
|
|
18
|
+
sourceSync(groupActiveClass("active", activeElement, groupElements));
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
document.value(g);
|
|
20
|
+
value(element("#next-active", document), activeElement);
|
|
19
21
|
|
|
20
|
-
expect(
|
|
22
|
+
expect(document.body.outerHTML).toContain(
|
|
21
23
|
'id="next-active" class="menu-link active"',
|
|
22
24
|
);
|
|
23
|
-
|
|
25
|
+
|
|
26
|
+
expect(document.body.innerHTML).toContain(
|
|
24
27
|
'id="prev-active" class="menu-link"',
|
|
25
28
|
);
|
|
26
29
|
});
|
|
@@ -1,29 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { patron, sourceAll, SourceType, value } from "silentium";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Sets activeClass to one element of group
|
|
5
5
|
* and resets activeClass on other group elements
|
|
6
6
|
* suitable for menu active class
|
|
7
|
-
*
|
|
8
|
-
* @deprecated heavily related to web api needs refactoring
|
|
9
7
|
*/
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
export const groupActiveClass = (
|
|
9
|
+
activeClassSrc: SourceType<string>,
|
|
10
|
+
activeElementSrc: SourceType<HTMLElement>,
|
|
11
|
+
groupElementsSrc: SourceType<HTMLElement[]>,
|
|
12
|
+
) => {
|
|
13
|
+
value(
|
|
14
|
+
sourceAll([activeClassSrc, activeElementSrc, groupElementsSrc]),
|
|
15
|
+
patron(([activeClass, activeElement, groupElements]) => {
|
|
16
|
+
groupElements.forEach((el) => {
|
|
17
|
+
if (el.classList) {
|
|
18
|
+
el.classList.remove(activeClass);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
activeElement.classList.add(activeClass);
|
|
22
|
+
}),
|
|
23
|
+
);
|
|
16
24
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
this.document,
|
|
20
|
-
new PatronOnce((document) => {
|
|
21
|
-
document.querySelectorAll(this.groupSelector).forEach((el) => {
|
|
22
|
-
el.classList.remove(this.activeClass);
|
|
23
|
-
});
|
|
24
|
-
element.classList.add(this.activeClass);
|
|
25
|
-
}),
|
|
26
|
-
);
|
|
27
|
-
return this;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
25
|
+
return groupElementsSrc;
|
|
26
|
+
};
|
package/src/controls/index.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { source, sourceApplied, sourceOf, sourceSync } from "silentium";
|
|
2
|
+
import { expect, test } from "vitest";
|
|
3
|
+
import { router } from "../navigation/Router";
|
|
4
|
+
|
|
5
|
+
const drop = (dropPart: string) => (value: string) => {
|
|
6
|
+
return value.replace(dropPart, "");
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
test("Router.test", () => {
|
|
10
|
+
const urlSrc = sourceOf<string>("http://domain.com/some/url/");
|
|
11
|
+
const urlClearedSrc = sourceApplied(urlSrc, drop("http://domain.com"));
|
|
12
|
+
|
|
13
|
+
const template = sourceSync(
|
|
14
|
+
router(
|
|
15
|
+
urlClearedSrc,
|
|
16
|
+
[
|
|
17
|
+
{
|
|
18
|
+
pattern: "^/$",
|
|
19
|
+
template: source("page/home.html"),
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
pattern: "/some/url",
|
|
23
|
+
template: "page/home.html",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
pattern: "/some/contacts",
|
|
27
|
+
template: "page/contacts.html",
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
source("page/404.html"),
|
|
31
|
+
),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
expect(template.syncValue()).toBe("page/home.html");
|
|
35
|
+
|
|
36
|
+
urlSrc.give("http://domain.com/some/contacts/");
|
|
37
|
+
|
|
38
|
+
expect(template.syncValue()).toBe("page/contacts.html");
|
|
39
|
+
|
|
40
|
+
urlSrc.give("http://domain.com/some/unknown/");
|
|
41
|
+
|
|
42
|
+
expect(template.syncValue()).toBe("page/404.html");
|
|
43
|
+
|
|
44
|
+
urlSrc.give("http://domain.com/");
|
|
45
|
+
|
|
46
|
+
expect(template.syncValue()).toBe("page/home.html");
|
|
47
|
+
});
|
package/src/navigation/Router.ts
CHANGED
|
@@ -1,118 +1,50 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
PrivateClass,
|
|
7
|
-
SourceChangeable,
|
|
8
|
-
give,
|
|
2
|
+
patron,
|
|
3
|
+
sourceAny,
|
|
4
|
+
sourceChain,
|
|
5
|
+
sourceFiltered,
|
|
9
6
|
sourceOf,
|
|
7
|
+
SourceType,
|
|
8
|
+
value,
|
|
10
9
|
} from "silentium";
|
|
11
|
-
import {
|
|
12
|
-
import { ComputedElement, GroupActiveClass, Link, Visible } from "../controls";
|
|
13
|
-
import { CurrentPage } from "../navigation/CurrentPage";
|
|
14
|
-
import { Navigation } from "../navigation/Navigation";
|
|
15
|
-
import { PageFetchTransport } from "../navigation/PageFetchTransport";
|
|
16
|
-
import { RouteDisplay } from "../navigation/RouteDisplay";
|
|
10
|
+
import { regexpMatched } from "../system/RegexpMatched";
|
|
17
11
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export class Router {
|
|
26
|
-
public constructor(
|
|
27
|
-
private loaderSelector: string,
|
|
28
|
-
private navigationResultSelector: string,
|
|
29
|
-
private menuSelector: string,
|
|
30
|
-
) {}
|
|
31
|
-
|
|
32
|
-
public routes(
|
|
33
|
-
routes: Route[],
|
|
34
|
-
currentPage: any,
|
|
35
|
-
basePathSource: any,
|
|
36
|
-
afterPageLoaded?: () => void,
|
|
37
|
-
) {
|
|
38
|
-
if (!currentPage) {
|
|
39
|
-
currentPage = new CurrentPage();
|
|
40
|
-
}
|
|
41
|
-
currentPage.value(new Patron(new HistoryNewPage()));
|
|
42
|
-
|
|
43
|
-
const [basePath] = location.href.replace(location.origin, "").split("#");
|
|
44
|
-
if (!basePathSource) {
|
|
45
|
-
basePathSource = new SourceChangeable(
|
|
46
|
-
`${basePath}#`.replace("index.html", "").replace("//", "/"),
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const pageLoading = new SourceChangeable(false);
|
|
51
|
-
pageLoading.value(new Patron(new Visible(this.loaderSelector)));
|
|
52
|
-
|
|
53
|
-
const historyPoppedPage = new HistoryPoppedPage(currentPage);
|
|
54
|
-
historyPoppedPage.watchPop();
|
|
55
|
-
|
|
56
|
-
const navigation = new Navigation(
|
|
57
|
-
pageLoading,
|
|
58
|
-
basePathSource,
|
|
59
|
-
currentPage,
|
|
60
|
-
new RouteDisplay(this.navigationResultSelector),
|
|
61
|
-
new PrivateClass(PageFetchTransport),
|
|
62
|
-
);
|
|
63
|
-
navigation.routes(routes);
|
|
64
|
-
|
|
65
|
-
const link = new Link(currentPage, basePathSource);
|
|
66
|
-
link.watchClick(this.menuSelector);
|
|
12
|
+
export interface Route<T> {
|
|
13
|
+
pattern: string;
|
|
14
|
+
patternFlags?: string;
|
|
15
|
+
template: T | SourceType<T>;
|
|
16
|
+
}
|
|
67
17
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Router component what will return template if url matches pattern
|
|
20
|
+
*/
|
|
21
|
+
export const router = <T = "string">(
|
|
22
|
+
urlSrc: SourceType<string>,
|
|
23
|
+
routesSrc: SourceType<Route<T>[]>,
|
|
24
|
+
defaultSrc: SourceType<T>,
|
|
25
|
+
) => {
|
|
26
|
+
const resultSrc = sourceOf<T>();
|
|
27
|
+
|
|
28
|
+
value(
|
|
29
|
+
routesSrc,
|
|
30
|
+
patron((routes) => {
|
|
31
|
+
value(
|
|
32
|
+
sourceAny([
|
|
33
|
+
sourceChain(urlSrc, defaultSrc as T),
|
|
34
|
+
...routes.map((r) =>
|
|
35
|
+
sourceChain(
|
|
36
|
+
sourceFiltered(
|
|
37
|
+
regexpMatched(r.pattern, urlSrc, r.patternFlags),
|
|
38
|
+
Boolean,
|
|
39
|
+
),
|
|
40
|
+
r.template,
|
|
41
|
+
),
|
|
42
|
+
),
|
|
43
|
+
]),
|
|
44
|
+
patron(resultSrc),
|
|
76
45
|
);
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
const activeLink = new ComputedElement(
|
|
80
|
-
[{ source: url, placeholder: "{url}" }],
|
|
81
|
-
`${this.menuSelector} a[href="{url}"]`,
|
|
82
|
-
);
|
|
83
|
-
activeLink.element(
|
|
84
|
-
new Patron(
|
|
85
|
-
new GroupActiveClass(
|
|
86
|
-
"active",
|
|
87
|
-
`${this.menuSelector} a`,
|
|
88
|
-
sourceOf(document),
|
|
89
|
-
),
|
|
90
|
-
),
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
pageLoading.value(
|
|
94
|
-
new Patron((isInLoading) => {
|
|
95
|
-
if (isInLoading) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
46
|
+
}),
|
|
47
|
+
);
|
|
98
48
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const divDestination = document.querySelector(
|
|
104
|
-
this.navigationResultSelector,
|
|
105
|
-
);
|
|
106
|
-
if (divDestination) {
|
|
107
|
-
// Оживляем script тэги
|
|
108
|
-
divDestination.querySelectorAll("script").forEach((x) => {
|
|
109
|
-
const sc = document.createElement("script");
|
|
110
|
-
sc.setAttribute("type", "module");
|
|
111
|
-
sc.appendChild(document.createTextNode(x.innerText));
|
|
112
|
-
divDestination.appendChild(sc);
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
}),
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
49
|
+
return resultSrc.value;
|
|
50
|
+
};
|
package/src/navigation/index.ts
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { sourceSync } from "silentium";
|
|
2
|
+
import { concatenated } from "../strings/Concatenated";
|
|
3
|
+
import { expect, test } from "vitest";
|
|
4
|
+
|
|
5
|
+
test("Concatenated.test", () => {
|
|
6
|
+
const concatenatedSrc = sourceSync(
|
|
7
|
+
concatenated(["one", "two", "three"], "-"),
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
expect(concatenatedSrc.syncValue()).toBe("one-two-three");
|
|
11
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { give, GuestType, sourceCombined, SourceType } from "silentium";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Join sources of strings to one source
|
|
5
|
+
*/
|
|
6
|
+
export const concatenated = (
|
|
7
|
+
sources: SourceType<string>[],
|
|
8
|
+
joinPartSrc: SourceType<string> = "",
|
|
9
|
+
): SourceType<string> => {
|
|
10
|
+
const result = sourceCombined(
|
|
11
|
+
joinPartSrc,
|
|
12
|
+
...sources,
|
|
13
|
+
)((g: GuestType<string>, joinPart, ...strings) => {
|
|
14
|
+
give(strings.join(joinPart), g);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
return result;
|
|
18
|
+
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { HashTable } from "../structures/HashTable";
|
|
1
|
+
import { sourceOf, sourceSync } from "silentium";
|
|
3
2
|
import { expect, test } from "vitest";
|
|
3
|
+
import { hashTable } from "../structures/HashTable";
|
|
4
4
|
|
|
5
5
|
test("HashTable.test", () => {
|
|
6
|
-
const entrySource =
|
|
7
|
-
const
|
|
6
|
+
const entrySource = sourceOf<[string, string]>();
|
|
7
|
+
const hashTableSrc = sourceSync(hashTable(entrySource));
|
|
8
8
|
entrySource.give(["key-one", "value-one"]);
|
|
9
9
|
entrySource.give(["key-two", "value-two"]);
|
|
10
10
|
|
|
11
|
-
expect(
|
|
11
|
+
expect(hashTableSrc.syncValue()).toStrictEqual({
|
|
12
12
|
"key-one": "value-one",
|
|
13
13
|
"key-two": "value-two",
|
|
14
14
|
});
|
|
@@ -1,31 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
GuestType,
|
|
3
|
-
Patron,
|
|
4
|
-
SourceObjectType,
|
|
5
|
-
SourceType,
|
|
6
|
-
SourceChangeable,
|
|
7
|
-
value,
|
|
8
|
-
} from "silentium";
|
|
1
|
+
import { patron, sourceOf, SourceType, subSource, value } from "silentium";
|
|
9
2
|
|
|
10
3
|
/**
|
|
11
4
|
* https://silentium-lab.github.io/silentium-components/#/structures/hash-table
|
|
12
5
|
*/
|
|
13
|
-
export
|
|
14
|
-
|
|
6
|
+
export const hashTable = (baseSource: SourceType<[string, unknown]>) => {
|
|
7
|
+
const result = sourceOf<Record<string, unknown>>({});
|
|
8
|
+
subSource(result, baseSource);
|
|
15
9
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
);
|
|
25
|
-
}
|
|
10
|
+
value(
|
|
11
|
+
baseSource,
|
|
12
|
+
patron(([key, value]) => {
|
|
13
|
+
result.value((lastRecord) => {
|
|
14
|
+
lastRecord[key] = value;
|
|
15
|
+
});
|
|
16
|
+
}),
|
|
17
|
+
);
|
|
26
18
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return this;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
19
|
+
return result.value;
|
|
20
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { sourceOf, sourceSync } from "silentium";
|
|
2
|
+
import { regexpMatched } from "../system/RegexpMatched";
|
|
3
|
+
import { expect, test } from "vitest";
|
|
4
|
+
|
|
5
|
+
test("RegexpMatched.test", () => {
|
|
6
|
+
const urlSrc = sourceOf<string>("http://domain.com/some/url/");
|
|
7
|
+
const matchedSrc = sourceSync(regexpMatched("/some/url", urlSrc));
|
|
8
|
+
|
|
9
|
+
expect(matchedSrc.syncValue()).toBe(true);
|
|
10
|
+
|
|
11
|
+
urlSrc.give("http://domain.com/changed");
|
|
12
|
+
|
|
13
|
+
expect(matchedSrc.syncValue()).toBe(false);
|
|
14
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { give, GuestType, sourceCombined, SourceType } from "silentium";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Boolean source what checks what string matches pattern
|
|
5
|
+
*/
|
|
6
|
+
export const regexpMatched = (
|
|
7
|
+
patternSrc: SourceType<string>,
|
|
8
|
+
valueSrc: SourceType<string>,
|
|
9
|
+
flagsSrc: SourceType<string> = "",
|
|
10
|
+
): SourceType<boolean> =>
|
|
11
|
+
sourceCombined(
|
|
12
|
+
patternSrc,
|
|
13
|
+
valueSrc,
|
|
14
|
+
flagsSrc,
|
|
15
|
+
)((g: GuestType<boolean>, pattern, value, flags) => {
|
|
16
|
+
give(new RegExp(pattern, flags).test(value), g);
|
|
17
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./RegexpMatched";
|
package/src/behaviors/Touched.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export class Touched {}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
give,
|
|
3
|
-
SourceAll,
|
|
4
|
-
SourceObjectType,
|
|
5
|
-
GuestCast,
|
|
6
|
-
GuestType,
|
|
7
|
-
} from "silentium";
|
|
8
|
-
|
|
9
|
-
type SourceDetailType = {
|
|
10
|
-
source: SourceObjectType<any>;
|
|
11
|
-
placeholder: string;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @deprecated use https://kosukhin.github.io/patron-web-api/#/dom/element
|
|
16
|
-
*/
|
|
17
|
-
export class ComputedElement {
|
|
18
|
-
public constructor(
|
|
19
|
-
private sources: SourceDetailType[],
|
|
20
|
-
private selectorTemplate: string,
|
|
21
|
-
) {}
|
|
22
|
-
|
|
23
|
-
public element(guest: GuestType<HTMLElement>) {
|
|
24
|
-
const chain = new SourceAll();
|
|
25
|
-
this.sources.forEach((source) => {
|
|
26
|
-
source.source.value(
|
|
27
|
-
new GuestCast(guest as GuestType, chain.guestKey(source.placeholder)),
|
|
28
|
-
);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
chain.value(
|
|
32
|
-
new GuestCast(
|
|
33
|
-
guest as GuestType,
|
|
34
|
-
(placeholders: Record<string, string>) => {
|
|
35
|
-
let selectorTemplate = this.selectorTemplate;
|
|
36
|
-
|
|
37
|
-
Object.entries(placeholders).map((entry) => {
|
|
38
|
-
selectorTemplate = selectorTemplate.replaceAll(entry[0], entry[1]);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
const element = document.querySelector(
|
|
42
|
-
selectorTemplate,
|
|
43
|
-
) as HTMLElement;
|
|
44
|
-
if (element) {
|
|
45
|
-
give(element, guest);
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
),
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
}
|
package/src/controls/Input.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
GuestType,
|
|
3
|
-
Patron,
|
|
4
|
-
SourceChangeable,
|
|
5
|
-
SourceChangeableType,
|
|
6
|
-
} from "silentium";
|
|
7
|
-
|
|
8
|
-
type InputValue = number | string;
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @deprecated move to web api
|
|
12
|
-
*/
|
|
13
|
-
export class Input implements SourceChangeableType<InputValue> {
|
|
14
|
-
public constructor(
|
|
15
|
-
private source: SourceChangeable<InputValue>,
|
|
16
|
-
selector: string,
|
|
17
|
-
) {
|
|
18
|
-
const el = document.querySelector(selector) as HTMLInputElement;
|
|
19
|
-
this.source.value(
|
|
20
|
-
new Patron((value) => {
|
|
21
|
-
el.value = String(value);
|
|
22
|
-
}),
|
|
23
|
-
);
|
|
24
|
-
el.addEventListener("keyup", () => {
|
|
25
|
-
this.give(el.value);
|
|
26
|
-
});
|
|
27
|
-
el.addEventListener("change", () => {
|
|
28
|
-
this.give(el.value);
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
public value(guest: GuestType<InputValue>) {
|
|
33
|
-
this.source.value(guest);
|
|
34
|
-
return this;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
public give(value: InputValue) {
|
|
38
|
-
this.source.give(value);
|
|
39
|
-
return this;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
public pool() {
|
|
43
|
-
return this.source.pool();
|
|
44
|
-
}
|
|
45
|
-
}
|