vasille-web 7.0.0-rc.2 → 7.0.0

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.
Files changed (210) hide show
  1. package/README.md +35 -16
  2. package/build/dev/communication.d.ts +9 -0
  3. package/build/dev/css-injector.d.ts +14 -0
  4. package/build/dev/css-injector.js +37 -0
  5. package/build/dev/css.d.ts +3 -0
  6. package/build/dev/css.js +32 -0
  7. package/build/dev/index.d.ts +55 -0
  8. package/build/dev/index.js +64 -0
  9. package/build/dev/inspector.d.ts +18 -0
  10. package/build/dev/inspector.js +226 -0
  11. package/build/dev/mount.d.ts +11 -0
  12. package/build/dev/mount.js +91 -0
  13. package/build/dev/router.d.ts +23 -0
  14. package/build/dev/router.js +67 -0
  15. package/build/dev/runner.d.ts +34 -0
  16. package/build/dev/runner.js +128 -0
  17. package/build/shadow/css.d.ts +23 -0
  18. package/build/shadow/css.js +77 -0
  19. package/build/shadow/index.d.ts +3 -0
  20. package/build/shadow/index.js +3 -0
  21. package/build/shadow/lib.d.ts +11 -0
  22. package/build/shadow/lib.js +145 -0
  23. package/build/shadow/types.d.ts +31 -0
  24. package/build/ssg/awaited.d.ts +3 -0
  25. package/build/ssg/awaited.js +24 -0
  26. package/build/ssg/css.d.ts +8 -0
  27. package/build/ssg/css.js +36 -0
  28. package/build/ssg/index.d.ts +21 -0
  29. package/build/ssg/index.js +37 -0
  30. package/build/ssg/router.d.ts +17 -0
  31. package/build/ssg/router.js +59 -0
  32. package/build/ssg/runner.d.ts +56 -0
  33. package/build/ssg/runner.js +337 -0
  34. package/build/types/index.d.ts +9 -0
  35. package/build/types/index.js +1 -0
  36. package/build/web/css/index.d.ts +21 -0
  37. package/build/web/css/index.js +53 -0
  38. package/build/web/css/lib.d.ts +10 -0
  39. package/build/web/css/lib.js +75 -0
  40. package/build/web/index.d.ts +6 -0
  41. package/build/web/index.js +6 -0
  42. package/{types → build/web/jsx}/jsx-runtime.d.ts +8 -7
  43. package/build/web/jsx/spec/css.d.ts +7 -0
  44. package/build/web/jsx/spec/css.js +1 -0
  45. package/{types → build/web/jsx}/spec/html.d.ts +2 -0
  46. package/build/web/jsx/spec/html.js +1 -0
  47. package/build/web/mount.d.ts +19 -0
  48. package/{lib/index.js → build/web/mount.js} +26 -21
  49. package/build/web/router/router.d.ts +45 -0
  50. package/build/web/router/router.js +131 -0
  51. package/build/web/runner/binding/attribute.d.ts +16 -0
  52. package/build/web/runner/binding/attribute.js +30 -0
  53. package/build/web/runner/binding/binding.d.ts +20 -0
  54. package/build/web/runner/binding/binding.js +28 -0
  55. package/build/web/runner/binding/class.d.ts +9 -0
  56. package/build/web/runner/binding/class.js +32 -0
  57. package/build/web/runner/binding/property.d.ts +16 -0
  58. package/build/web/runner/binding/property.js +20 -0
  59. package/build/web/runner/binding/style.d.ts +17 -0
  60. package/build/web/runner/binding/style.js +32 -0
  61. package/build/web/runner/runner.d.ts +45 -0
  62. package/build/web/runner/runner.js +176 -0
  63. package/coverage/clover.xml +754 -0
  64. package/coverage/coverage-final.json +20 -0
  65. package/coverage/lcov-report/base.css +224 -0
  66. package/coverage/lcov-report/block-navigation.js +87 -0
  67. package/coverage/lcov-report/dev/css-injector.ts.html +250 -0
  68. package/coverage/lcov-report/dev/css.ts.html +220 -0
  69. package/coverage/lcov-report/dev/index.html +131 -0
  70. package/coverage/lcov-report/favicon.png +0 -0
  71. package/coverage/lcov-report/index.html +221 -0
  72. package/coverage/lcov-report/prettify.css +1 -0
  73. package/coverage/lcov-report/prettify.js +2 -0
  74. package/coverage/lcov-report/shadow/css.ts.html +382 -0
  75. package/coverage/lcov-report/shadow/index.html +131 -0
  76. package/coverage/lcov-report/shadow/lib.ts.html +670 -0
  77. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  78. package/coverage/lcov-report/sorter.js +210 -0
  79. package/coverage/lcov-report/ssg/awaited.ts.html +169 -0
  80. package/coverage/lcov-report/ssg/css.ts.html +223 -0
  81. package/coverage/lcov-report/ssg/index.html +176 -0
  82. package/coverage/lcov-report/ssg/index.ts.html +370 -0
  83. package/coverage/lcov-report/ssg/router.ts.html +388 -0
  84. package/coverage/lcov-report/ssg/runner.ts.html +1405 -0
  85. package/coverage/lcov-report/web/css/index.html +131 -0
  86. package/coverage/lcov-report/web/css/index.ts.html +313 -0
  87. package/coverage/lcov-report/web/css/lib.ts.html +352 -0
  88. package/coverage/lcov-report/web/index.html +116 -0
  89. package/coverage/lcov-report/web/index.ts.html +574 -0
  90. package/coverage/lcov-report/web/mount.ts.html +454 -0
  91. package/coverage/lcov-report/web/router/index.html +116 -0
  92. package/coverage/lcov-report/web/router/router.ts.html +784 -0
  93. package/coverage/lcov-report/web/runner/binding/attribute.ts.html +190 -0
  94. package/coverage/lcov-report/web/runner/binding/binding.ts.html +193 -0
  95. package/coverage/lcov-report/web/runner/binding/class.ts.html +199 -0
  96. package/coverage/lcov-report/web/runner/binding/index.html +176 -0
  97. package/coverage/lcov-report/web/runner/binding/property.ts.html +154 -0
  98. package/coverage/lcov-report/web/runner/binding/style.ts.html +205 -0
  99. package/coverage/lcov-report/web/runner/index.html +116 -0
  100. package/coverage/lcov-report/web/runner/runner.ts.html +835 -0
  101. package/coverage/lcov.info +1554 -0
  102. package/jest.config.cjs +37 -0
  103. package/package.json +91 -60
  104. package/test/api/dev.test.ts +5 -0
  105. package/test/api/import-list.ts +106 -0
  106. package/test/api/shadow.test.ts +5 -0
  107. package/test/api/ssg.test.ts +5 -0
  108. package/test/api/web.test.ts +5 -0
  109. package/test/css/css-dev.test.ts +103 -0
  110. package/test/css/css.test.ts +27 -0
  111. package/test/mount/exported-web-router.test.ts +63 -0
  112. package/test/mount/modal-no-ctx.test.ts +14 -0
  113. package/test/mount/modal-which-throws.test.ts +33 -0
  114. package/test/mount/modal-with-slot.test.ts +39 -0
  115. package/test/mount/modal.test.ts +34 -0
  116. package/test/mount/prompt-error.test.ts +44 -0
  117. package/test/mount/prompt-timeout.test.ts +53 -0
  118. package/test/mount/prompt-which-trows.test.ts +33 -0
  119. package/test/mount/prompt.test.ts +44 -0
  120. package/test/page.ts +16 -0
  121. package/test/router/empty-router.test.ts +21 -0
  122. package/test/router/page.ts +19 -0
  123. package/test/router/router.test.ts +774 -0
  124. package/test/router/v7.test.ts +129 -0
  125. package/test/runner/destruction.test.ts +113 -0
  126. package/test/runner/runner.test.ts +403 -0
  127. package/test/shadow/components/Component.ts +72 -0
  128. package/test/shadow/css.test.ts +68 -0
  129. package/test/shadow/page.ts +21 -0
  130. package/test/shadow/shadow.test.ts +71 -0
  131. package/test/ssg/awaited/awaited.test.ts +11 -0
  132. package/test/ssg/awaited/element.test.ts +6 -0
  133. package/test/ssg/awaited/element.tsx +10 -0
  134. package/test/ssg/awaited/element.tsx.html +12 -0
  135. package/test/ssg/awaited/embed.test.ts +6 -0
  136. package/test/ssg/awaited/embed.tsx +14 -0
  137. package/test/ssg/awaited/embed.tsx.html +16 -0
  138. package/test/ssg/awaited/text.test.ts +6 -0
  139. package/test/ssg/awaited/text.tsx +8 -0
  140. package/test/ssg/awaited/text.tsx.html +7 -0
  141. package/test/ssg/awaited/throw-sync.tsx +10 -0
  142. package/test/ssg/awaited/throw-sync.tsx.html +7 -0
  143. package/test/ssg/awaited/throw.tsx +13 -0
  144. package/test/ssg/awaited/throw.tsx.html +7 -0
  145. package/test/ssg/compose/compose.test.ts +25 -0
  146. package/test/ssg/compose/modal.tsx +29 -0
  147. package/test/ssg/compose/modal.tsx.html +16 -0
  148. package/test/ssg/compose/view.tsx +35 -0
  149. package/test/ssg/compose/view.tsx.html +12 -0
  150. package/test/ssg/core/core.test.ts +31 -0
  151. package/test/ssg/core/div-embed.tsx +7 -0
  152. package/test/ssg/core/div-embed.tsx.html +9 -0
  153. package/test/ssg/core/div-with-class.tsx +5 -0
  154. package/test/ssg/core/div-with-class.tsx.html +9 -0
  155. package/test/ssg/core/div-with-text.tsx +5 -0
  156. package/test/ssg/core/div-with-text.tsx.html +9 -0
  157. package/test/ssg/core/div.tsx +5 -0
  158. package/test/ssg/core/div.tsx.html +7 -0
  159. package/test/ssg/core/text-join.tsx +9 -0
  160. package/test/ssg/core/text-join.tsx.html +10 -0
  161. package/test/ssg/core/text.tsx +5 -0
  162. package/test/ssg/core/text.tsx.html +7 -0
  163. package/test/ssg/css/css.test.ts +6 -0
  164. package/test/ssg/css/css.tsx +34 -0
  165. package/test/ssg/css/css.tsx.html +28 -0
  166. package/test/ssg/extra-tags/body.tsx +6 -0
  167. package/test/ssg/extra-tags/body.tsx.html +7 -0
  168. package/test/ssg/extra-tags/extra-tags.test.ts +11 -0
  169. package/test/ssg/extra-tags/head.tsx +9 -0
  170. package/test/ssg/extra-tags/head.tsx.html +12 -0
  171. package/test/ssg/markdown/blocks.tsx +12 -0
  172. package/test/ssg/markdown/blocks.tsx.md +12 -0
  173. package/test/ssg/markdown/css.tsx +11 -0
  174. package/test/ssg/markdown/css.tsx.md +1 -0
  175. package/test/ssg/markdown/external.tsx +7 -0
  176. package/test/ssg/markdown/external.tsx.md +3 -0
  177. package/test/ssg/markdown/heading.tsx +12 -0
  178. package/test/ssg/markdown/heading.tsx.md +13 -0
  179. package/test/ssg/markdown/hybrid.tsx +15 -0
  180. package/test/ssg/markdown/hybrid.tsx.md +11 -0
  181. package/test/ssg/markdown/lists.tsx +26 -0
  182. package/test/ssg/markdown/lists.tsx.md +16 -0
  183. package/test/ssg/markdown/markdown.test.ts +41 -0
  184. package/test/ssg/markdown/stylish.tsx +19 -0
  185. package/test/ssg/markdown/stylish.tsx.md +15 -0
  186. package/test/ssg/markdown/table.tsx +32 -0
  187. package/test/ssg/markdown/table.tsx.md +11 -0
  188. package/test/ssg/router/embed.html +7 -0
  189. package/test/ssg/router/embed.tsx +5 -0
  190. package/test/ssg/router/file-html.tsx +5 -0
  191. package/test/ssg/router/file.html +7 -0
  192. package/test/ssg/router/index.html +7 -0
  193. package/test/ssg/router/index.tsx +5 -0
  194. package/test/ssg/router/router.test.ts +26 -0
  195. package/test/ssg/run-test.ts +33 -0
  196. package/test/ssg/runner/attr.tsx +7 -0
  197. package/test/ssg/runner/attr.tsx.html +7 -0
  198. package/test/ssg/runner/class.tsx +8 -0
  199. package/test/ssg/runner/class.tsx.html +7 -0
  200. package/test/ssg/runner/runner.test.ts +16 -0
  201. package/test/ssg/runner/style.tsx +19 -0
  202. package/test/ssg/runner/style.tsx.html +7 -0
  203. package/test/tsconfig.json +20 -0
  204. package/lib/dev.js +0 -109
  205. package/types/dev.d.ts +0 -10
  206. package/types/index.d.ts +0 -21
  207. package/types/spec/css.d.ts +0 -7
  208. /package/{lib/spec/css.js → build/dev/communication.js} +0 -0
  209. /package/{lib/spec/html.js → build/shadow/types.js} +0 -0
  210. /package/{lib → build/web/jsx}/jsx-runtime.js +0 -0
@@ -0,0 +1,75 @@
1
+ let common;
2
+ export let mobile;
3
+ export let tablet;
4
+ export let desktop;
5
+ let dark;
6
+ let light;
7
+ export let mobileMaxWidth = 440;
8
+ export let tabletMaxWidth = 880;
9
+ export let laptopMaxWidth = 1320;
10
+ export function setMobileMaxWidth(value) {
11
+ mobileMaxWidth = value;
12
+ }
13
+ export function setTabletMaxWidth(value) {
14
+ tabletMaxWidth = value;
15
+ }
16
+ export function setLaptopMaxWidth(value) {
17
+ laptopMaxWidth = value;
18
+ }
19
+ function createStyleSheet(media) {
20
+ const style = document.createElement("style");
21
+ style.media = media;
22
+ document.head.append(style);
23
+ return style.sheet;
24
+ }
25
+ export function insertRule(target, rule) {
26
+ let sheet;
27
+ switch (target) {
28
+ case 0:
29
+ /* istanbul ignore else */
30
+ if (!common) {
31
+ common = createStyleSheet("");
32
+ }
33
+ sheet = common;
34
+ break;
35
+ case 1:
36
+ /* istanbul ignore else */
37
+ if (!mobile) {
38
+ mobile = createStyleSheet(`(max-width:${mobileMaxWidth}px)`);
39
+ }
40
+ sheet = mobile;
41
+ break;
42
+ case 2:
43
+ /* istanbul ignore else */
44
+ if (!tablet) {
45
+ tablet = createStyleSheet(`(min-width:${mobileMaxWidth}px) and (max-width:${tabletMaxWidth}px)`);
46
+ }
47
+ sheet = tablet;
48
+ break;
49
+ case 3:
50
+ /* istanbul ignore else */
51
+ if (!desktop) {
52
+ desktop = createStyleSheet(`(min-width:${tabletMaxWidth}px) and (max-width:${laptopMaxWidth}px)`);
53
+ }
54
+ sheet = desktop;
55
+ break;
56
+ case 4:
57
+ /* istanbul ignore else */
58
+ if (!dark) {
59
+ dark = createStyleSheet("(prefers-color-scheme:dark)");
60
+ }
61
+ sheet = dark;
62
+ break;
63
+ case 5:
64
+ /* istanbul ignore else */
65
+ if (!light) {
66
+ light = createStyleSheet("(prefers-color-scheme:light)");
67
+ }
68
+ sheet = light;
69
+ break;
70
+ }
71
+ /* istanbul ignore else */
72
+ if (sheet) {
73
+ sheet.insertRule(rule, sheet.cssRules.length);
74
+ }
75
+ }
@@ -0,0 +1,6 @@
1
+ export { safe } from "vasille";
2
+ export { view, view as component, view as compose, ensure, ref, ref as state, expr, expr as bind, expr as calculate, expr as watch, expr as effect, expr as live, set, Delay, For, Slot, Watch, awaited, store, model, setModel, mapModel, arrayModel, Switch, setErrorHandler, match, ArrayView, ArrayModelView, MapModelView, SetModelView, QueuedRender, debounceRef as debounced, safeExpr as safeLive, safeRef as safeState, safeInit, toDeepFieldRef, toFieldRef, Zombie, abortSignal, SteelContext, Model, } from "vasille";
3
+ export { screen, screen as page } from "vasille";
4
+ export { setMobileMaxWidth, setTabletMaxWidth, setLaptopMaxWidth, styleSheet } from "./css/index.js";
5
+ export { context, impute, receive, share, receiveOptional } from "vasille";
6
+ export { Prompt, showPrompt, prompt, mount, modal, routerApp } from "./mount.js";
@@ -0,0 +1,6 @@
1
+ export { safe } from "vasille";
2
+ export { view, view as component, view as compose, ensure, ref, ref as state, expr, expr as bind, expr as calculate, expr as watch, expr as effect, expr as live, set, Delay, For, Slot, Watch, awaited, store, model, setModel, mapModel, arrayModel, Switch, setErrorHandler, match, ArrayView, ArrayModelView, MapModelView, SetModelView, QueuedRender, debounceRef as debounced, safeExpr as safeLive, safeRef as safeState, safeInit, toDeepFieldRef, toFieldRef, Zombie, abortSignal, SteelContext, Model, } from "vasille";
3
+ export { screen, screen as page } from "vasille";
4
+ export { setMobileMaxWidth, setTabletMaxWidth, setLaptopMaxWidth, styleSheet } from "./css/index.js";
5
+ export { context, impute, receive, share, receiveOptional } from "vasille";
6
+ export { Prompt, showPrompt, prompt, mount, modal, routerApp } from "./mount.js";
@@ -1,5 +1,6 @@
1
- import type { RawStyleProps } from "./spec/css.ts";
1
+ import type { ElementStyleProps } from "./spec/css.ts";
2
2
  import type { HtmlTagMap } from "./spec/html.ts";
3
+ import { CssStyleInjector } from "../css/index.js";
3
4
  export type { TagEvents, TagAttrs, TagProps } from "./spec/html.ts";
4
5
  export type prefixedObject<T, P extends string> = {
5
6
  [K in keyof T as K extends string ? `${P}${K}` : never]?: T[K];
@@ -7,19 +8,19 @@ export type prefixedObject<T, P extends string> = {
7
8
  export type EventHandlers<T> = {
8
9
  [K in keyof T]: T[K] | [T[K], boolean | AddEventListenerOptions];
9
10
  };
10
- export type ClassItem = string | Record<string, boolean> | false;
11
+ export type ClassItem = string | CssStyleInjector | false | null | undefined;
11
12
  declare const internal: unique symbol;
12
13
  export interface VasilleElement {
13
14
  [internal]: typeof internal;
14
15
  }
15
16
  export type VasilleChild = VasilleElement | string | number | boolean | null | undefined;
16
- export type VasilleSlot = VasilleChild | VasilleChild[];
17
+ export type VasilleSlot = VasilleChild | VasilleChild[] | void[];
17
18
  type HtmlInput<K extends keyof HTMLElementTagNameMap & keyof HtmlTagMap> = {
18
- callback?: (node: HTMLElementTagNameMap[K]) => unknown;
19
- class?: ClassItem[] | string;
20
- style?: RawStyleProps | string;
19
+ callback?: (node: HTMLElementTagNameMap[K]) => void | HTMLElementTagNameMap[K] | (() => void);
20
+ class?: ClassItem[] | string | CssStyleInjector;
21
+ style?: ElementStyleProps | string;
21
22
  "vasille:slot"?: VasilleSlot;
22
- } & Partial<HtmlTagMap[K]["attrs"]> & prefixedObject<EventHandlers<HtmlTagMap[K]["events"]>, "on"> & Partial<prefixedObject<HtmlTagMap[K]["props"], "bind:">>;
23
+ } & Partial<HtmlTagMap[K]["attrs"]> & prefixedObject<EventHandlers<HtmlTagMap[K]["events"]>, "on"> & Partial<prefixedObject<HtmlTagMap[K]["props"], "property:">>;
23
24
  export declare namespace JSX {
24
25
  type ElementType = keyof IntrinsicElements | ((props: any) => void);
25
26
  type Element = VasilleElement;
@@ -0,0 +1,7 @@
1
+ import type { ObsoletePropertiesHyphen, StandardPropertiesHyphen, VendorPropertiesHyphen } from "csstype";
2
+ export type ElementStyleProps = StandardPropertiesHyphen<string | number | number[]> & VendorPropertiesHyphen<string | number | number[]> & ObsoletePropertiesHyphen<string | number | number[]> & {
3
+ [variable: `--${string}`]: string;
4
+ };
5
+ export type StyleSheetProps = {
6
+ [K in keyof ElementStyleProps]: ElementStyleProps[K] | ElementStyleProps[K][];
7
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -28,6 +28,7 @@ export interface TagAttrs {
28
28
  lang: string;
29
29
  nonce: string;
30
30
  part: string;
31
+ role: string;
31
32
  slot: string;
32
33
  spellcheck: "true" | "false" | "" | boolean;
33
34
  tabindex: number;
@@ -132,6 +133,7 @@ interface ImgAttrs extends TagAttrs {
132
133
  referrerpolicy: string;
133
134
  decoding: string;
134
135
  loading: string;
136
+ fetchpriority: "high" | "low" | "auto";
135
137
  }
136
138
  interface IframeAttrs extends TagAttrs {
137
139
  src: string;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ import { AppNode, CompositionProps, Fragment, PortalNode } from "vasille";
2
+ import { WebTagOptions } from "./runner/runner.js";
3
+ import { WebRouterInitialization } from "./router/router.js";
4
+ export declare function modal<T extends CompositionProps>(modal: (node: Fragment<Node, Element, WebTagOptions>, input: T) => void, create?: (node: Fragment<Node, Element, WebTagOptions>) => PortalNode<Node, Element, WebTagOptions>): (input: T, node?: Fragment<Node, Element, WebTagOptions>, slot?: T["slot"]) => void;
5
+ export interface PromptProps {
6
+ resolve(data: unknown): void;
7
+ reject(err: unknown): void;
8
+ }
9
+ export declare class Prompt<T extends PromptProps, Extra extends [number, ...unknown[]]> {
10
+ private readonly modal;
11
+ private readonly create;
12
+ private readonly debugProps?;
13
+ constructor(modal: (node: Fragment<Node, Element, WebTagOptions>, input: T) => void, create: (node: Fragment<Node, Element, WebTagOptions>, extra: Extra) => PortalNode<Node, Element, WebTagOptions>, debugProps?: PromptProps | undefined);
14
+ show(node: Fragment<Node, Element, WebTagOptions>, input: Omit<T, "resolve" | "reject">, ...extra: Extra): Promise<unknown>;
15
+ }
16
+ export declare function prompt<T extends PromptProps, Extra extends [number, ...unknown[]]>(modal: (node: Fragment<Node, Element, WebTagOptions>, input: T) => void, create?: (node: Fragment<Node, Element, WebTagOptions>) => PortalNode<Node, Element, WebTagOptions>): Prompt<T, Extra>;
17
+ export declare function showPrompt<T extends PromptProps, Extra extends [number, ...unknown[]]>(ctx: Fragment<Node, Element, WebTagOptions>, prompt: Prompt<T, Extra>, input: Omit<T, "resolve" | "reject">, ...args: Extra): Promise<unknown>;
18
+ export declare function mount<T>(element: Element, component: ($: T, node: Fragment<Node, Element, WebTagOptions>) => void, input: T): AppNode<Node, Element, WebTagOptions>;
19
+ export declare function routerApp<Routes extends string>(init: WebRouterInitialization<Routes>, element?: Element): AppNode<Node, Element, WebTagOptions>;
@@ -1,17 +1,9 @@
1
- import { Portal, reportError } from "vasille";
2
- import { Runner } from "vasille/web-runner";
3
- import { mount as coreMount } from "vasille-jsx";
4
- import { routeApp as coreRouteApp } from "vasille-router/web-router";
5
- export { styleSheet } from "vasille-css";
6
- export { safe } from "vasille";
7
- export { view, view as component, view as compose, ensure, ref, expr, expr as bind, expr as calculate, expr as watch, set, Delay, For, Slot, Watch, awaited, store, model, setModel, mapModel, arrayModel, Switch, setErrorHandler, match, ArrayView, ArrayModelView, MapModelView, SetModelView, QueuedRender, } from "vasille-jsx";
8
- export { screen, screen as page, } from "vasille-router";
9
- export { Router } from "vasille-router/web-router";
10
- export { setMobileMaxWidth, setTabletMaxWidth, setLaptopMaxWidth } from "vasille-css";
11
- export { context, impute, receive, share, receiveOptional } from "vasille-context";
1
+ import { mountApp, PortalNode, reportError } from "vasille";
2
+ import { WebRunner } from "./runner/runner.js";
3
+ import { webRouterApp } from "./router/router.js";
12
4
  function createPortal(node) {
13
- const portal = new Portal({ node: document.body }, node.runner, node.sDeep + 1);
14
- node.create(portal);
5
+ const portal = new PortalNode(document.body, node.runner, node.sDeep + 1);
6
+ node.child(portal);
15
7
  return portal;
16
8
  }
17
9
  export function modal(modal, create = createPortal) {
@@ -31,15 +23,21 @@ export function modal(modal, create = createPortal) {
31
23
  }
32
24
  };
33
25
  }
34
- export function prompt(modal, create = createPortal) {
35
- return function (node, input, timeout, debugProps) {
26
+ export class Prompt {
27
+ constructor(modal, create, debugProps) {
28
+ this.modal = modal;
29
+ this.create = create;
30
+ this.debugProps = debugProps;
31
+ }
32
+ show(node, input, ...extra) {
33
+ const { modal, create, debugProps } = this;
36
34
  return new Promise((resolve, reject) => {
37
- const portal = create(node);
38
- const timer = timeout &&
35
+ const portal = create(node, extra);
36
+ const timer = extra[0] &&
39
37
  setTimeout(() => {
40
38
  destroy();
41
39
  reject(new Error("Timeout"));
42
- }, timeout);
40
+ }, extra[0]);
43
41
  function destroy() {
44
42
  timer && clearTimeout(timer);
45
43
  portal.destroy(portal.sDeep);
@@ -56,6 +54,7 @@ export function prompt(modal, create = createPortal) {
56
54
  destroy();
57
55
  debugProps?.reject(error);
58
56
  reject(error);
57
+ reject(error);
59
58
  },
60
59
  });
61
60
  }
@@ -64,11 +63,17 @@ export function prompt(modal, create = createPortal) {
64
63
  reject(e);
65
64
  }
66
65
  });
67
- };
66
+ }
67
+ }
68
+ export function prompt(modal, create = createPortal) {
69
+ return new Prompt(modal, create);
70
+ }
71
+ export function showPrompt(ctx, prompt, input, ...args) {
72
+ return prompt.show(ctx, input, ...args);
68
73
  }
69
74
  export function mount(element, component, input) {
70
- return coreMount(element, component, new Runner(window.document), input);
75
+ return mountApp(element, component, new WebRunner(window.document), input);
71
76
  }
72
77
  export function routerApp(init, element) {
73
- return coreRouteApp(element ?? document.body, window, window.location, init);
78
+ return webRouterApp(element ?? document.body, window, window.location, init);
74
79
  }
@@ -0,0 +1,45 @@
1
+ import { Answer, Fragment, QueryParams, Reference, Router, RouteRenderScope, RouterInitialization, ScreenProps } from "vasille";
2
+ import { WebTagOptions } from "../runner/runner.js";
3
+ export interface WebRouterInitialization<Routes extends string> extends RouterInitialization<Node, Element, WebTagOptions, Routes, {}> {
4
+ loadingScreen?(props: object, node: Fragment<Node, Element, WebTagOptions>): void;
5
+ loadingOverlay?(props: object, node: Fragment<Node, Element, WebTagOptions>): void;
6
+ Wrapper?(data: {
7
+ slot(data: object, ctx: Fragment<Node, Element, WebTagOptions>): void;
8
+ }, ctx: Fragment<Node, Element, WebTagOptions>): void;
9
+ }
10
+ export type NavigationMode = "silent" | "loading-screen" | "loading-overlay";
11
+ export declare class WebRouter<Routes extends string> extends Router<Node, Element, WebTagOptions, Routes, {}, [
12
+ NavigationMode
13
+ ]> {
14
+ readonly $currentUrl: Reference<string, unknown>;
15
+ readonly $loadingUrl: Reference<string | null, unknown>;
16
+ protected readonly webInit: WebRouterInitialization<Routes>;
17
+ protected readonly window: Window;
18
+ protected readonly location: Location;
19
+ protected readonly node: Fragment<Node, Element, WebTagOptions>;
20
+ protected loadingNode: Fragment<Node, Element, WebTagOptions>;
21
+ protected contentNode: Fragment<Node, Element, WebTagOptions>;
22
+ protected overlayNode: Fragment<Node, Element, WebTagOptions>;
23
+ constructor(window: Window, location: Location, node: Fragment<Node, Element, WebTagOptions>, init: WebRouterInitialization<Routes>);
24
+ /**
25
+ * Navigate to a new page, showing the loading screen
26
+ */
27
+ goTo(url: string): void;
28
+ /**
29
+ * Navigate to a new page in an AJAX way, showing a loading overlay
30
+ */
31
+ ajax(url: string): void;
32
+ /**
33
+ * Load the new page in the background, will throw on errors
34
+ */
35
+ load(url: string): Promise<void>;
36
+ reload(): void;
37
+ protected doNavigate(url: string, canNavigate: boolean, mode: NavigationMode): void;
38
+ protected parseUrl(url: string): [string, QueryParams, string];
39
+ protected loadTarget<Route extends string>(target: Answer<Node, Element, WebTagOptions, Route, {}>, props: ScreenProps<Route>, mode: NavigationMode): Promise<void>;
40
+ protected renderScreen<Props>(screen: (props: Props, ctx: Fragment<Node, Element, WebTagOptions>) => void | Promise<void>, props: Props, scope: RouteRenderScope): Promise<void>;
41
+ protected clearLoadings(): void;
42
+ protected clearNode(node: Fragment<Node, Element, WebTagOptions>): void;
43
+ protected build(node: Fragment<Node, Element, WebTagOptions>, run?: (node: Fragment<Node, Element, WebTagOptions>) => void): void;
44
+ }
45
+ export declare function webRouterApp<Routes extends string>(node: Element, window: Window, location: Location, init: WebRouterInitialization<Routes>): import("vasille").AppNode<Node, Element, WebTagOptions, import("vasille").IRunner<Node, Element, WebTagOptions>>;
@@ -0,0 +1,131 @@
1
+ import { Fragment, mountApp, Reference, reportError, Router, } from "vasille";
2
+ import { WebRunner } from "../runner/runner.js";
3
+ export class WebRouter extends Router {
4
+ constructor(window, location, node, init) {
5
+ super(init);
6
+ this.$currentUrl = new Reference("");
7
+ this.$loadingUrl = new Reference(null);
8
+ this.webInit = init;
9
+ this.window = window;
10
+ this.location = location;
11
+ this.node = node;
12
+ this.$currentUrl.V = location.pathname;
13
+ let routerNode = node;
14
+ if (init.Wrapper) {
15
+ init.Wrapper({
16
+ slot(_data, ctx) {
17
+ routerNode = ctx;
18
+ },
19
+ }, node);
20
+ }
21
+ this.build(routerNode, node => (this.loadingNode = node));
22
+ this.build(routerNode, node => (this.contentNode = node));
23
+ this.build(routerNode, node => (this.overlayNode = node));
24
+ window.addEventListener("popstate", () => {
25
+ this.doNavigate(location.href, false, "loading-screen");
26
+ });
27
+ this.doNavigate(location.href, true, "loading-screen");
28
+ }
29
+ /**
30
+ * Navigate to a new page, showing the loading screen
31
+ */
32
+ goTo(url) {
33
+ this.doNavigate(url, true, "loading-screen");
34
+ }
35
+ /**
36
+ * Navigate to a new page in an AJAX way, showing a loading overlay
37
+ */
38
+ ajax(url) {
39
+ this.doNavigate(url, true, "loading-overlay");
40
+ }
41
+ /**
42
+ * Load the new page in the background, will throw on errors
43
+ */
44
+ load(url) {
45
+ return this.prepareNavigation(url, true, true, "silent");
46
+ }
47
+ reload() {
48
+ this.doNavigate(this.$currentUrl.V, true, "loading-screen");
49
+ }
50
+ doNavigate(url, canNavigate, mode) {
51
+ this.prepareNavigation(url, canNavigate, false, mode).catch(e => {
52
+ this.clearLoadings();
53
+ reportError(e);
54
+ });
55
+ }
56
+ parseUrl(url) {
57
+ const parsed = new URL(url, this.location.origin);
58
+ const query = [...parsed.searchParams].reduce((prev, [key]) => {
59
+ return { ...prev, [key]: parsed.searchParams.getAll(key) };
60
+ }, {});
61
+ return [parsed.pathname, query, parsed.hash];
62
+ }
63
+ async loadTarget(target, props, mode) {
64
+ this.$loadingUrl.V = props.path;
65
+ try {
66
+ const { loadingScreen, loadingOverlay } = this.webInit;
67
+ if (mode === "loading-screen" && loadingScreen) {
68
+ this.clearNode(this.contentNode);
69
+ this.build(this.loadingNode, node => loadingScreen({}, node));
70
+ }
71
+ if (mode === "loading-overlay" && loadingOverlay) {
72
+ this.build(this.overlayNode, node => loadingOverlay({}, node));
73
+ }
74
+ await this.renderScreen(target.screen, props, "found");
75
+ this.$currentUrl.V = props.url;
76
+ if (this.location.href !== props.url && this.location.hash !== "#" + props.url) {
77
+ this.window.history.pushState({}, "", props.url);
78
+ }
79
+ }
80
+ catch (error) {
81
+ if (mode !== "silent") {
82
+ this.clearNode(this.contentNode);
83
+ }
84
+ throw error;
85
+ }
86
+ finally {
87
+ this.clearLoadings();
88
+ this.$loadingUrl.V = null;
89
+ }
90
+ }
91
+ async renderScreen(screen, props, scope) {
92
+ const children = this.contentNode.children;
93
+ const oldChildren = [...children];
94
+ let ctx = null;
95
+ this.build(this.contentNode, node => (ctx = node));
96
+ /* istanbul ignore else */
97
+ if (ctx) {
98
+ await screen(props, ctx);
99
+ }
100
+ oldChildren.forEach(node => {
101
+ node.destroy(node.sDeep);
102
+ });
103
+ children.splice(0, oldChildren.length);
104
+ if (scope === "not-found") {
105
+ this.window.history.replaceState({}, "", "/");
106
+ }
107
+ }
108
+ clearLoadings() {
109
+ this.clearNode(this.loadingNode);
110
+ this.clearNode(this.overlayNode);
111
+ }
112
+ clearNode(node) {
113
+ const { children } = node;
114
+ children.forEach(node => node.destroy(node.sDeep));
115
+ children.splice(0);
116
+ }
117
+ build(node, run) {
118
+ const child = new Fragment(node.runner, node.sDeep + 1);
119
+ node.child(child, run);
120
+ }
121
+ }
122
+ export function webRouterApp(node, window, location, init) {
123
+ const runner = new WebRunner(window.document);
124
+ return mountApp(node, (_data, node) => {
125
+ const router = new WebRouter(window, location, node, init);
126
+ Object.defineProperty(runner, "router", {
127
+ value: router,
128
+ writable: false,
129
+ });
130
+ }, runner, {});
131
+ }
@@ -0,0 +1,16 @@
1
+ import { Binding } from "./binding.js";
2
+ import { IValue, Tag } from "vasille";
3
+ /**
4
+ * Represents an Attribute binding description
5
+ * @class AttributeBinding
6
+ * @extends Binding
7
+ */
8
+ export declare class AttributeBinding extends Binding<string | number | boolean | null | undefined> {
9
+ /**
10
+ * Constructs an attribute binding description
11
+ * @param node {INode} the vasille node
12
+ * @param name {String} the name of attribute
13
+ * @param value {IValue} value to bind
14
+ */
15
+ constructor(node: Tag<Node, Element, object>, name: string, value: IValue<string | number | boolean | null | undefined, unknown>);
16
+ }
@@ -0,0 +1,30 @@
1
+ import { Binding } from "./binding.js";
2
+ /**
3
+ * Represents an Attribute binding description
4
+ * @class AttributeBinding
5
+ * @extends Binding
6
+ */
7
+ export class AttributeBinding extends Binding {
8
+ /**
9
+ * Constructs an attribute binding description
10
+ * @param node {INode} the vasille node
11
+ * @param name {String} the name of attribute
12
+ * @param value {IValue} value to bind
13
+ */
14
+ constructor(node, name, value) {
15
+ super(value);
16
+ this.init((value) => {
17
+ if (value || value === 0) {
18
+ if (typeof value === "boolean") {
19
+ node.node.setAttribute(name, "");
20
+ }
21
+ else {
22
+ node.node.setAttribute(name, `${value}`);
23
+ }
24
+ }
25
+ else {
26
+ node.node.removeAttribute(name);
27
+ }
28
+ });
29
+ }
30
+ }
@@ -0,0 +1,20 @@
1
+ import { IValue, Destroyable } from "vasille";
2
+ /**
3
+ * Describe a common binding logic
4
+ * @class Binding
5
+ */
6
+ export declare class Binding<T> implements Destroyable {
7
+ readonly rDeep: number;
8
+ private binding;
9
+ private func;
10
+ /**
11
+ * Constructs a common binding logic
12
+ * @param value {IValue} the value to bind
13
+ */
14
+ constructor(value: IValue<T, unknown>);
15
+ protected init(bounded: (v: T) => void): void;
16
+ /**
17
+ * Just clear bindings
18
+ */
19
+ destroy(deep: number): void;
20
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Describe a common binding logic
3
+ * @class Binding
4
+ */
5
+ export class Binding {
6
+ /**
7
+ * Constructs a common binding logic
8
+ * @param value {IValue} the value to bind
9
+ */
10
+ constructor(value) {
11
+ this.binding = value;
12
+ this.rDeep = value.rDeep;
13
+ }
14
+ init(bounded) {
15
+ this.func = bounded;
16
+ this.binding.on(this.func);
17
+ this.func(this.binding.V);
18
+ }
19
+ /**
20
+ * Just clear bindings
21
+ */
22
+ destroy(deep) {
23
+ /* istanbul ignore else */
24
+ if (this.binding.rDeep < deep) {
25
+ this.binding.off(this.func);
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,9 @@
1
+ import { Binding } from "./binding.js";
2
+ import { CssStyleInjector } from "../../css/index.js";
3
+ import { IValue, Tag } from "vasille";
4
+ export declare function addClass(node: Tag<Node, Element, object>, cl: string): void;
5
+ export declare function removeClass(node: Tag<Node, Element, object>, cl: string): void;
6
+ export declare class DynamicalClassBinding extends Binding<string | CssStyleInjector | false | null | undefined> {
7
+ private current;
8
+ constructor(node: Tag<Node, Element, object>, value: IValue<string | CssStyleInjector | false | null | undefined, unknown>);
9
+ }
@@ -0,0 +1,32 @@
1
+ import { Binding } from "./binding.js";
2
+ import { CssStyleInjector } from "../../css/index.js";
3
+ export function addClass(node, cl) {
4
+ node.node?.classList.add(cl);
5
+ }
6
+ export function removeClass(node, cl) {
7
+ node.node?.classList.remove(cl);
8
+ }
9
+ export class DynamicalClassBinding extends Binding {
10
+ constructor(node, value) {
11
+ super(value);
12
+ this.current = "";
13
+ this.init(value => {
14
+ /* istanbul ignore else */
15
+ if (this.current != value) {
16
+ if (this.current.length) {
17
+ removeClass(node, this.current);
18
+ }
19
+ /* istanbul ignore else */
20
+ if (value instanceof CssStyleInjector) {
21
+ addClass(node, (this.current = value.inject()));
22
+ }
23
+ else if (typeof value === "string" && value.length) {
24
+ addClass(node, (this.current = value));
25
+ }
26
+ else {
27
+ this.current = "";
28
+ }
29
+ }
30
+ });
31
+ }
32
+ }
@@ -0,0 +1,16 @@
1
+ import { Binding } from "./binding.js";
2
+ import { IValue, Tag } from "vasille";
3
+ /**
4
+ * Represents a property binding
5
+ * @class PropertyBinding
6
+ * @extends Binding
7
+ */
8
+ export declare class PropertyBinding<T> extends Binding<T> {
9
+ /**
10
+ * Constructs a property binding description
11
+ * @param node the vasille node
12
+ * @param name the name of property
13
+ * @param value the value of property
14
+ */
15
+ constructor(node: Tag<Node, Element, object>, name: string, value: IValue<T, unknown>);
16
+ }
@@ -0,0 +1,20 @@
1
+ import { Binding } from "./binding.js";
2
+ /**
3
+ * Represents a property binding
4
+ * @class PropertyBinding
5
+ * @extends Binding
6
+ */
7
+ export class PropertyBinding extends Binding {
8
+ /**
9
+ * Constructs a property binding description
10
+ * @param node the vasille node
11
+ * @param name the name of property
12
+ * @param value the value of property
13
+ */
14
+ constructor(node, name, value) {
15
+ super(value);
16
+ this.init(value => {
17
+ node.node[name] = value;
18
+ });
19
+ }
20
+ }
@@ -0,0 +1,17 @@
1
+ import { Binding } from "./binding.js";
2
+ import { IValue, Tag } from "vasille";
3
+ export declare function stringifyStyleValue(value: string | number | number[]): string;
4
+ /**
5
+ * Describes a style attribute binding
6
+ * @class StyleBinding
7
+ * @extends Binding
8
+ */
9
+ export declare class StyleBinding extends Binding<string | number | number[] | false | null | undefined> {
10
+ /**
11
+ * Constructs a style binding attribute
12
+ * @param node {Tag} the vasille node
13
+ * @param name {string} the name of style property
14
+ * @param value {IValue} the value to bind
15
+ */
16
+ constructor(node: Tag<Node, Element, object>, name: string, value: IValue<string | number | number[] | undefined, unknown>);
17
+ }