amateras 0.5.0 → 0.7.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 (290) hide show
  1. package/README.md +23 -26
  2. package/index.ts +1 -0
  3. package/package.json +32 -27
  4. package/packages/core/package.json +32 -0
  5. package/packages/core/src/env.browser.ts +21 -0
  6. package/packages/core/src/env.node.ts +21 -0
  7. package/packages/core/src/global.ts +18 -0
  8. package/packages/core/src/index.ts +96 -0
  9. package/packages/core/src/lib/assignNodeProperties.ts +11 -0
  10. package/packages/core/src/lib/assignProperties.ts +57 -0
  11. package/packages/core/src/lib/chain.ts +17 -0
  12. package/packages/core/src/lib/dom.ts +20 -0
  13. package/packages/core/src/main.ts +4 -0
  14. package/{src → packages/core/src}/node/$Element.ts +25 -47
  15. package/packages/core/src/node/$EventTarget.ts +48 -0
  16. package/{src → packages/core/src}/node/$HTMLElement.ts +1 -1
  17. package/{src → packages/core/src}/node/$Node.ts +64 -73
  18. package/packages/core/src/node/$Virtual.ts +65 -0
  19. package/packages/css/package.json +17 -0
  20. package/{ext/css/src/lib → packages/css/src/ext}/colors/amber.ts +2 -2
  21. package/{ext/css/src/lib → packages/css/src/ext}/colors/blackwhite.ts +2 -2
  22. package/{ext/css/src/lib → packages/css/src/ext}/colors/blue.ts +2 -2
  23. package/{ext/css/src/lib → packages/css/src/ext}/colors/cyan.ts +2 -2
  24. package/{ext/css/src/lib → packages/css/src/ext}/colors/emerald.ts +2 -2
  25. package/{ext/css/src/lib → packages/css/src/ext}/colors/fuchsia.ts +2 -2
  26. package/{ext/css/src/lib → packages/css/src/ext}/colors/gray.ts +2 -2
  27. package/{ext/css/src/lib → packages/css/src/ext}/colors/green.ts +2 -2
  28. package/{ext/css/src/lib → packages/css/src/ext}/colors/indigo.ts +2 -2
  29. package/{ext/css/src/lib → packages/css/src/ext}/colors/lime.ts +2 -2
  30. package/{ext/css/src/lib → packages/css/src/ext}/colors/neutral.ts +2 -2
  31. package/{ext/css/src/lib → packages/css/src/ext}/colors/orange.ts +2 -2
  32. package/{ext/css/src/lib → packages/css/src/ext}/colors/pink.ts +2 -2
  33. package/{ext/css/src/lib → packages/css/src/ext}/colors/purple.ts +2 -2
  34. package/{ext/css/src/lib → packages/css/src/ext}/colors/red.ts +2 -2
  35. package/{ext/css/src/lib → packages/css/src/ext}/colors/rose.ts +2 -2
  36. package/{ext/css/src/lib → packages/css/src/ext}/colors/sky.ts +2 -2
  37. package/{ext/css/src/lib → packages/css/src/ext}/colors/slate.ts +2 -2
  38. package/{ext/css/src/lib → packages/css/src/ext}/colors/stone.ts +2 -2
  39. package/{ext/css/src/lib → packages/css/src/ext}/colors/teal.ts +2 -2
  40. package/{ext/css/src/lib → packages/css/src/ext}/colors/violet.ts +2 -2
  41. package/{ext/css/src/lib → packages/css/src/ext}/colors/yellow.ts +2 -2
  42. package/{ext/css/src/lib → packages/css/src/ext}/colors/zinc.ts +2 -2
  43. package/packages/css/src/ext/container.ts +32 -0
  44. package/packages/css/src/ext/keyframes.ts +54 -0
  45. package/packages/css/src/ext/media.ts +32 -0
  46. package/packages/css/src/ext/property.ts +48 -0
  47. package/packages/css/src/ext/variable.ts +51 -0
  48. package/{ext → packages}/css/src/index.ts +107 -183
  49. package/{ext → packages}/css/src/lib/colorAssign.ts +1 -1
  50. package/packages/css/src/lib/utils.ts +11 -0
  51. package/{ext → packages}/css/src/structure/$CSSContainerRule.ts +1 -1
  52. package/{ext → packages}/css/src/structure/$CSSKeyframesRule.ts +0 -1
  53. package/{ext → packages}/css/src/structure/$CSSMediaRule.ts +1 -1
  54. package/packages/css/src/structure/$CSSProperty.ts +19 -0
  55. package/{ext → packages}/css/src/structure/$CSSRule.ts +1 -1
  56. package/{ext → packages}/css/src/structure/$CSSStyleRule.ts +1 -1
  57. package/packages/css/src/structure/$CSSVariable.ts +30 -0
  58. package/packages/dom/package.json +20 -0
  59. package/packages/dom/src/lib/HTMLElementMap.ts +213 -0
  60. package/packages/dom/src/lib/assignAttributes.ts +16 -0
  61. package/packages/dom/src/structure/CSS.ts +7 -0
  62. package/packages/dom/src/structure/CSSStyleSheet.ts +10 -0
  63. package/packages/dom/src/structure/DOMTokenList.ts +19 -0
  64. package/packages/dom/src/structure/Document.ts +36 -0
  65. package/packages/dom/src/structure/Element.ts +106 -0
  66. package/packages/dom/src/structure/HTMLElement.ts +34 -0
  67. package/packages/dom/src/structure/History.ts +11 -0
  68. package/packages/dom/src/structure/Location.ts +9 -0
  69. package/packages/dom/src/structure/Node.ts +51 -0
  70. package/packages/dom/src/structure/NodeList.ts +10 -0
  71. package/packages/dom/src/structure/Storage.ts +8 -0
  72. package/packages/dom/src/structure/Text.ts +20 -0
  73. package/packages/dom/src/structure/Window.ts +14 -0
  74. package/packages/dom/src/structure/html/HTMLAbbrElement.ts +16 -0
  75. package/packages/dom/src/structure/html/HTMLAddressElement.ts +16 -0
  76. package/packages/dom/src/structure/html/HTMLAnchorElement.ts +25 -0
  77. package/packages/dom/src/structure/html/HTMLAreaElement.ts +26 -0
  78. package/packages/dom/src/structure/html/HTMLArticleElement.ts +16 -0
  79. package/packages/dom/src/structure/html/HTMLAsideElement.ts +16 -0
  80. package/packages/dom/src/structure/html/HTMLAudioElement.ts +16 -0
  81. package/packages/dom/src/structure/html/HTMLBDIElement.ts +16 -0
  82. package/packages/dom/src/structure/html/HTMLBDOElement.ts +16 -0
  83. package/packages/dom/src/structure/html/HTMLBElement.ts +16 -0
  84. package/packages/dom/src/structure/html/HTMLBRElement.ts +17 -0
  85. package/packages/dom/src/structure/html/HTMLBaseElement.ts +18 -0
  86. package/packages/dom/src/structure/html/HTMLBodyElement.ts +22 -0
  87. package/packages/dom/src/structure/html/HTMLButtonElement.ts +26 -0
  88. package/packages/dom/src/structure/html/HTMLCanvasElement.ts +18 -0
  89. package/packages/dom/src/structure/html/HTMLCiteElement.ts +16 -0
  90. package/packages/dom/src/structure/html/HTMLCodeElement.ts +16 -0
  91. package/packages/dom/src/structure/html/HTMLDDElement.ts +16 -0
  92. package/packages/dom/src/structure/html/HTMLDFNElement.ts +16 -0
  93. package/packages/dom/src/structure/html/HTMLDListElement.ts +17 -0
  94. package/packages/dom/src/structure/html/HTMLDTElement.ts +16 -0
  95. package/packages/dom/src/structure/html/HTMLDataElement.ts +17 -0
  96. package/packages/dom/src/structure/html/HTMLDataListElement.ts +16 -0
  97. package/packages/dom/src/structure/html/HTMLDetailsElement.ts +17 -0
  98. package/packages/dom/src/structure/html/HTMLDialogElement.ts +18 -0
  99. package/packages/dom/src/structure/html/HTMLDivElement.ts +17 -0
  100. package/packages/dom/src/structure/html/HTMLEMElement.ts +16 -0
  101. package/packages/dom/src/structure/html/HTMLEmbedElement.ts +20 -0
  102. package/packages/dom/src/structure/html/HTMLFieldSetElement.ts +19 -0
  103. package/packages/dom/src/structure/html/HTMLFigCaptionElement.ts +16 -0
  104. package/packages/dom/src/structure/html/HTMLFigureElement.ts +16 -0
  105. package/packages/dom/src/structure/html/HTMLFooterElement.ts +16 -0
  106. package/packages/dom/src/structure/html/HTMLFormElement.ts +24 -0
  107. package/packages/dom/src/structure/html/HTMLHGroupElement.ts +16 -0
  108. package/packages/dom/src/structure/html/HTMLHRElement.ts +21 -0
  109. package/packages/dom/src/structure/html/HTMLHeadElement.ts +16 -0
  110. package/packages/dom/src/structure/html/HTMLHeaderElement.ts +16 -0
  111. package/packages/dom/src/structure/html/HTMLHeadingElement.ts +17 -0
  112. package/packages/dom/src/structure/html/HTMLHtmlElement.ts +18 -0
  113. package/packages/dom/src/structure/html/HTMLIElement.ts +16 -0
  114. package/packages/dom/src/structure/html/HTMLIFrameElement.ts +31 -0
  115. package/packages/dom/src/structure/html/HTMLImageElement.ts +38 -0
  116. package/packages/dom/src/structure/html/HTMLInputElement.ts +55 -0
  117. package/packages/dom/src/structure/html/HTMLKBDElement.ts +16 -0
  118. package/packages/dom/src/structure/html/HTMLLIElement.ts +18 -0
  119. package/packages/dom/src/structure/html/HTMLLabelElement.ts +18 -0
  120. package/packages/dom/src/structure/html/HTMLLegendElement.ts +17 -0
  121. package/packages/dom/src/structure/html/HTMLLinkElement.ts +31 -0
  122. package/packages/dom/src/structure/html/HTMLMainElement.ts +16 -0
  123. package/packages/dom/src/structure/html/HTMLMapElement.ts +17 -0
  124. package/packages/dom/src/structure/html/HTMLMarkElement.ts +16 -0
  125. package/packages/dom/src/structure/html/HTMLMediaElement.ts +48 -0
  126. package/packages/dom/src/structure/html/HTMLMenuElement.ts +18 -0
  127. package/packages/dom/src/structure/html/HTMLMetaElement.ts +22 -0
  128. package/packages/dom/src/structure/html/HTMLMeterElement.ts +23 -0
  129. package/packages/dom/src/structure/html/HTMLModElement.ts +18 -0
  130. package/packages/dom/src/structure/html/HTMLNavElement.ts +16 -0
  131. package/packages/dom/src/structure/html/HTMLNoscriptElement.ts +16 -0
  132. package/packages/dom/src/structure/html/HTMLOListElement.ts +20 -0
  133. package/packages/dom/src/structure/html/HTMLObjectElement.ts +34 -0
  134. package/packages/dom/src/structure/html/HTMLOptGroupElement.ts +18 -0
  135. package/packages/dom/src/structure/html/HTMLOptionElement.ts +20 -0
  136. package/packages/dom/src/structure/html/HTMLOutputElement.ts +20 -0
  137. package/packages/dom/src/structure/html/HTMLParagraphElement.ts +17 -0
  138. package/packages/dom/src/structure/html/HTMLPictureElement.ts +16 -0
  139. package/packages/dom/src/structure/html/HTMLPreElement.ts +17 -0
  140. package/packages/dom/src/structure/html/HTMLProgressElement.ts +19 -0
  141. package/packages/dom/src/structure/html/HTMLQuoteElement.ts +17 -0
  142. package/packages/dom/src/structure/html/HTMLRPElement.ts +16 -0
  143. package/packages/dom/src/structure/html/HTMLRTElement.ts +16 -0
  144. package/packages/dom/src/structure/html/HTMLRubyElement.ts +16 -0
  145. package/packages/dom/src/structure/html/HTMLSElement.ts +16 -0
  146. package/packages/dom/src/structure/html/HTMLSampElement.ts +16 -0
  147. package/packages/dom/src/structure/html/HTMLScriptElement.ts +27 -0
  148. package/packages/dom/src/structure/html/HTMLSectionElement.ts +16 -0
  149. package/packages/dom/src/structure/html/HTMLSelectElement.ts +27 -0
  150. package/packages/dom/src/structure/html/HTMLSlotElement.ts +17 -0
  151. package/packages/dom/src/structure/html/HTMLSmallElement.ts +16 -0
  152. package/packages/dom/src/structure/html/HTMLSourceElement.ts +21 -0
  153. package/packages/dom/src/structure/html/HTMLSpanElement.ts +16 -0
  154. package/packages/dom/src/structure/html/HTMLStrongElement.ts +16 -0
  155. package/packages/dom/src/structure/html/HTMLStyleElement.ts +18 -0
  156. package/packages/dom/src/structure/html/HTMLSubElement.ts +16 -0
  157. package/packages/dom/src/structure/html/HTMLSummaryElement.ts +16 -0
  158. package/packages/dom/src/structure/html/HTMLSupElement.ts +16 -0
  159. package/packages/dom/src/structure/html/HTMLTableCaptionElement.ts +17 -0
  160. package/packages/dom/src/structure/html/HTMLTableCellElement.ts +31 -0
  161. package/packages/dom/src/structure/html/HTMLTableColElement.ts +23 -0
  162. package/packages/dom/src/structure/html/HTMLTableElement.ts +26 -0
  163. package/packages/dom/src/structure/html/HTMLTableRowElement.ts +23 -0
  164. package/packages/dom/src/structure/html/HTMLTableSectionElement.ts +20 -0
  165. package/packages/dom/src/structure/html/HTMLTemplateElement.ts +17 -0
  166. package/packages/dom/src/structure/html/HTMLTextAreaElement.ts +33 -0
  167. package/packages/dom/src/structure/html/HTMLTimeElement.ts +17 -0
  168. package/packages/dom/src/structure/html/HTMLTitleElement.ts +17 -0
  169. package/packages/dom/src/structure/html/HTMLTrackElement.ts +21 -0
  170. package/packages/dom/src/structure/html/HTMLUElement.ts +16 -0
  171. package/packages/dom/src/structure/html/HTMLUListElement.ts +18 -0
  172. package/packages/dom/src/structure/html/HTMLVarElement.ts +16 -0
  173. package/packages/dom/src/structure/html/HTMLVideoElement.ts +22 -0
  174. package/packages/dom/src/structure/html/HTMLWBRElement.ts +16 -0
  175. package/packages/html/package.json +18 -0
  176. package/{ext/html/html.ts → packages/html/src/index.ts} +1 -1
  177. package/{ext/html → packages/html/src}/node/$Anchor.ts +4 -4
  178. package/packages/html/src/node/$Canvas.ts +38 -0
  179. package/{ext/html → packages/html/src}/node/$Dialog.ts +4 -4
  180. package/{ext/html → packages/html/src}/node/$Form.ts +4 -4
  181. package/{ext/html → packages/html/src}/node/$Image.ts +4 -4
  182. package/{ext/html → packages/html/src}/node/$Input.ts +4 -4
  183. package/{ext/html → packages/html/src}/node/$Label.ts +4 -4
  184. package/{ext/html → packages/html/src}/node/$Media.ts +4 -4
  185. package/{ext/html → packages/html/src}/node/$OptGroup.ts +4 -4
  186. package/{ext/html → packages/html/src}/node/$Option.ts +4 -4
  187. package/{ext/html → packages/html/src}/node/$Select.ts +4 -4
  188. package/{ext/html → packages/html/src}/node/$TextArea.ts +4 -4
  189. package/{ext → packages}/i18n/README.md +20 -0
  190. package/packages/i18n/package.json +19 -0
  191. package/packages/i18n/src/index.ts +140 -0
  192. package/{ext → packages}/i18n/src/structure/I18n.ts +12 -8
  193. package/{ext → packages}/i18n/src/structure/I18nDictionary.ts +1 -1
  194. package/packages/i18n/src/structure/I18nTranslation.ts +41 -0
  195. package/packages/idb/package.json +19 -0
  196. package/{ext → packages}/idb/src/index.ts +2 -2
  197. package/{ext → packages}/idb/src/lib/$IDBRequest.ts +1 -1
  198. package/{ext → packages}/idb/src/structure/$IDB.ts +1 -1
  199. package/{ext → packages}/idb/src/structure/$IDBCursor.ts +1 -1
  200. package/{ext → packages}/idb/src/structure/$IDBIndex.ts +1 -1
  201. package/{ext → packages}/idb/src/structure/$IDBStore.ts +1 -1
  202. package/{ext → packages}/idb/src/structure/$IDBStoreBase.ts +1 -1
  203. package/{ext → packages}/idb/src/structure/$IDBTransaction.ts +1 -1
  204. package/{ext → packages}/idb/src/structure/builder/$IDBBuilder.ts +9 -10
  205. package/{ext → packages}/idb/src/structure/builder/$IDBStoreBuilder.ts +1 -1
  206. package/packages/markdown/README.md +53 -0
  207. package/packages/markdown/package.json +19 -0
  208. package/packages/markdown/src/index.ts +3 -0
  209. package/packages/markdown/src/lib/type.ts +26 -0
  210. package/packages/markdown/src/lib/util.ts +21 -0
  211. package/packages/markdown/src/structure/Markdown.ts +54 -0
  212. package/packages/markdown/src/structure/MarkdownLexer.ts +111 -0
  213. package/packages/markdown/src/structure/MarkdownParser.ts +34 -0
  214. package/packages/markdown/src/syntax/alert.ts +46 -0
  215. package/packages/markdown/src/syntax/blockquote.ts +35 -0
  216. package/packages/markdown/src/syntax/bold.ts +11 -0
  217. package/packages/markdown/src/syntax/code.ts +11 -0
  218. package/packages/markdown/src/syntax/codeblock.ts +44 -0
  219. package/packages/markdown/src/syntax/heading.ts +14 -0
  220. package/packages/markdown/src/syntax/horizontalRule.ts +11 -0
  221. package/packages/markdown/src/syntax/image.ts +23 -0
  222. package/packages/markdown/src/syntax/italic.ts +11 -0
  223. package/packages/markdown/src/syntax/link.ts +46 -0
  224. package/packages/markdown/src/syntax/list.ts +121 -0
  225. package/packages/markdown/src/syntax/table.ts +67 -0
  226. package/packages/markdown/src/syntax/text.ts +19 -0
  227. package/packages/router/README.md +175 -0
  228. package/packages/router/package.json +19 -0
  229. package/packages/router/src/index.ts +68 -0
  230. package/packages/router/src/node/Page.ts +38 -0
  231. package/packages/router/src/node/Router.ts +212 -0
  232. package/{ext/router → packages/router/src}/node/RouterAnchor.ts +13 -2
  233. package/packages/router/src/structure/PageBuilder.ts +24 -0
  234. package/packages/router/src/structure/Route.ts +105 -0
  235. package/packages/signal/README.md +93 -0
  236. package/packages/signal/package.json +18 -0
  237. package/packages/signal/src/index.ts +221 -0
  238. package/{src → packages/signal/src}/structure/Signal.ts +6 -10
  239. package/packages/ssr/package.json +19 -0
  240. package/packages/ssr/src/index.ts +38 -0
  241. package/packages/ui/lib/VirtualScroll.ts +25 -0
  242. package/packages/ui/node/Accordian.ts +97 -0
  243. package/packages/ui/node/Carousel.ts +20 -0
  244. package/packages/ui/node/Form.ts +54 -0
  245. package/packages/ui/node/Grid.ts +0 -0
  246. package/packages/ui/node/Modal.ts +45 -0
  247. package/packages/ui/node/Table.ts +43 -0
  248. package/packages/ui/node/Tabs.ts +129 -0
  249. package/packages/ui/node/Toast.ts +16 -0
  250. package/packages/ui/node/Waterfall.ts +94 -0
  251. package/packages/ui/package.json +21 -0
  252. package/packages/utils/package.json +17 -0
  253. package/{src → packages/utils/src}/global.ts +9 -15
  254. package/packages/utils/src/index.ts +90 -0
  255. package/tsconfig.json +1 -1
  256. package/ext/css/package.json +0 -9
  257. package/ext/css/src/structure/$CSSVariable.ts +0 -12
  258. package/ext/html/node/$Canvas.ts +0 -16
  259. package/ext/i18n/package.json +0 -10
  260. package/ext/i18n/src/index.ts +0 -54
  261. package/ext/i18n/src/node/I18nText.ts +0 -35
  262. package/ext/idb/package.json +0 -13
  263. package/ext/markdown/index.ts +0 -121
  264. package/ext/markdown/package.json +0 -8
  265. package/ext/router/README.md +0 -81
  266. package/ext/router/index.ts +0 -73
  267. package/ext/router/node/Page.ts +0 -27
  268. package/ext/router/node/Route.ts +0 -54
  269. package/ext/router/node/Router.ts +0 -149
  270. package/ext/ssr/env.ts +0 -61
  271. package/ext/ssr/index.ts +0 -49
  272. package/ext/ssr/package.json +0 -10
  273. package/src/core.ts +0 -114
  274. package/src/index.ts +0 -3
  275. package/src/lib/assign.ts +0 -38
  276. package/src/lib/assignHelper.ts +0 -18
  277. package/src/lib/chain.ts +0 -13
  278. package/src/lib/debounce.ts +0 -7
  279. package/src/lib/env.ts +0 -2
  280. package/src/lib/native.ts +0 -40
  281. package/src/lib/randomId.ts +0 -9
  282. package/src/lib/sleep.ts +0 -3
  283. package/src/lib/toArray.ts +0 -9
  284. package/src/lib/trycatch.ts +0 -17
  285. package/src/node.ts +0 -10
  286. /package/{ext → packages}/css/README.md +0 -0
  287. /package/{ext/css/src/lib → packages/css/src/ext}/colors.ts +0 -0
  288. /package/{ext → packages}/css/src/structure/$CSSDeclaration.ts +0 -0
  289. /package/{ext → packages}/idb/README.md +0 -0
  290. /package/{ext → packages}/idb/src/core.ts +0 -0
@@ -0,0 +1,212 @@
1
+ import { Route, type RouteBuilder, type RoutePath, type RouteParamsResolver, type RouteParams, type RouteParamsStrings, type AsyncPageBuilder } from "../structure/Route";
2
+ import type { AnchorTarget } from "../../../html/src/node/$Anchor";
3
+ import { Page, type PageParams } from "./Page";
4
+ import type { PageBuilder, PageBuilderFunction } from "#structure/PageBuilder";
5
+ import { _document } from "@amateras/core/env";
6
+ import { $HTMLElement } from "@amateras/core/node/$HTMLElement";
7
+ import { _instanceof, startsWith, _JSON_parse, forEach, _Object_entries, _JSON_stringify, isFunction } from "@amateras/utils";
8
+ // history index
9
+ let index = 0;
10
+ const _addEventListener = addEventListener;
11
+ const _location = location;
12
+ const {origin} = _location;
13
+ const _history = history;
14
+ const _sessionStorage = sessionStorage;
15
+ const documentElement = _document.documentElement;
16
+ const [PUSH, REPLACE] = [1, 2] as const;
17
+ const [FORWARD, BACK] = ['forward', 'back'] as const;
18
+ const scrollStorageKey = '__scroll__';
19
+ /** convert path string to URL object */
20
+ const toURL = (path: string | URL) =>
21
+ _instanceof(path, URL) ? path : startsWith(path, 'http') ? new URL(path) : new URL(startsWith(path, origin) ? path : origin + path);
22
+
23
+ type ScrollData = {[key: number]: {x: number, y: number}};
24
+ const scrollRecord = (e?: Event) => {
25
+ const data = _JSON_parse(_sessionStorage.getItem(scrollStorageKey) ?? '{}') as ScrollData;
26
+ data[index] = { x: documentElement.scrollLeft, y: documentElement.scrollTop };
27
+ // e is Event when called from scroll or beforeload
28
+ if (!e) forEach(_Object_entries(data), ([i]) => +i > index && delete data[+i])
29
+ _sessionStorage.setItem(scrollStorageKey, _JSON_stringify(data));
30
+ }
31
+ /** handle history state with push and replace state. */
32
+ const historyHandler = async (path: string | URL | Nullish, mode: 1 | 2, target?: AnchorTarget) => {
33
+ if (!path) return;
34
+ const url = toURL(path);
35
+ if (url.href === _location.href) return;
36
+ if (target && target !== '_self') return open(url, target);
37
+ if (url.origin !== origin) return open(url, target);
38
+ scrollRecord();
39
+ if (mode === PUSH) index += 1;
40
+ Router.direction = FORWARD;
41
+ Router.prevUrl = toURL(_location.href);
42
+ _history[mode === PUSH ? 'pushState' : 'replaceState']({index}, '' , url);
43
+ Router.url = url;
44
+ forEach(Router.routers, router => router.resolve(path))
45
+ }
46
+ // disable browser scroll restoration
47
+ _history.scrollRestoration = 'manual';
48
+
49
+ type RouteData = { route: Route, params: PageParams, pathId: string }
50
+ export class Router extends $HTMLElement {
51
+ static direction: 'back' | 'forward' = FORWARD;
52
+ static routers = new Set<Router>();
53
+ static url: URL = toURL(_location.href);
54
+ static prevUrl: URL | null = null;
55
+ routes = new Map<RoutePath, Route>();
56
+ pages = new Map<string, Page>();
57
+ constructor(page?: Page) {
58
+ super('router');
59
+ if (page) page.router = this;
60
+ else Router.routers.add(this);
61
+ }
62
+
63
+ static open(path: string | URL | Nullish, target?: AnchorTarget) {
64
+ historyHandler(path, PUSH, target);
65
+ return this;
66
+ }
67
+
68
+ static back() {
69
+ _history.back();
70
+ return this;
71
+ }
72
+
73
+ static forward() {
74
+ _history.forward();
75
+ return this;
76
+ }
77
+
78
+ static replace(path: string | URL | Nullish) {
79
+ historyHandler(path, REPLACE);
80
+ return this;
81
+ }
82
+
83
+ static get scroll(): ScrollData[number] {
84
+ return _JSON_parse(_sessionStorage.getItem(scrollStorageKey) ?? '{}')[index] ?? {x: 0, y: 0}
85
+ }
86
+
87
+ listen() {
88
+ const resolve = () => {
89
+ const stateIndex = _history.state?.index ?? 0;
90
+ if (index > stateIndex) Router.direction = BACK;
91
+ if (index < stateIndex) Router.direction = FORWARD;
92
+ index = stateIndex;
93
+ Router.prevUrl = Router.url;
94
+ Router.url = toURL(_location.href);
95
+ this.resolve(_location.href);
96
+ }
97
+ _addEventListener('popstate', resolve);
98
+ _addEventListener('beforeunload', scrollRecord);
99
+ _addEventListener('scroll', scrollRecord, false);
100
+ resolve();
101
+ return this;
102
+ }
103
+
104
+ async resolve(path: string | URL, force = false): Promise<this> {
105
+ const {pathname, href} = toURL(path);
106
+ const routes = this.getRoutes(this.routes, pathname);
107
+ const routerPageMap = new Map<Router, Page>();
108
+ let prevRouter: Router | null = this;
109
+ let pathIdStr = '';
110
+ let paramsData = {}
111
+ await forEach(routes, async ({route, params, pathId}) => {
112
+ pathIdStr += pathId;
113
+ paramsData = {...paramsData, ...params}
114
+ // skip route group
115
+ const builderResolver = route.builder;
116
+ if (!builderResolver) return;
117
+ // get page from cache or create new page
118
+ const page = route.pages.get(pathId) ?? new Page(pathIdStr, paramsData);
119
+ // resolve builder
120
+ if (!page.built) await builderResolver.build(page);
121
+ page.built = true;
122
+ // set router to page map
123
+ if (prevRouter) routerPageMap.set(prevRouter, page)
124
+ // set cache
125
+ if (!force) route.pages.set(pathId, page);
126
+ prevRouter = page.router;
127
+ })
128
+
129
+ forEach(routerPageMap, ([router, page]) => {
130
+ // set title
131
+ _document && (_document.title = page.pageTitle() ?? _document.title ?? '');
132
+ // check location is still same, page parent is not router before insert page
133
+ if (force || (href === _location.href && page.parentNode !== router.node)) router.content(page);
134
+ })
135
+ // handle scroll restoration
136
+ let { x, y } = Router.scroll ?? {x: 0, y: 0};
137
+ scrollTo(x, y);
138
+ // event
139
+ this.dispatchEvent(new Event('routeopen', {bubbles: true}));
140
+ return this;
141
+ }
142
+
143
+ protected getRoutes(routes: typeof this.routes, targetPath: string): RouteData[] {
144
+ const split = (p: string) => p.replaceAll(/\/+/g, '/').replace(/^\//, '').split('/').map(path => `/${path}`);
145
+ let targetPathSplit = split(targetPath);
146
+ if (!routes.size) return [];
147
+ // check each route
148
+ for (const [_, route] of routes) {
149
+ // check each path pass
150
+ routePathLoop: for (const [path, paramsHandle] of route.paths) {
151
+ let routePathSplit = split(path);
152
+ let targetPathNodePosition = 0;
153
+ let params: { [key: string]: string } = isFunction(paramsHandle) ? paramsHandle() : paramsHandle ?? {};
154
+ let pathId = '';
155
+ // check each path node
156
+ pathNodeLoop: for (let i = 0; i < routePathSplit.length; i++) {
157
+ // reset target path node position
158
+ targetPathNodePosition = i;
159
+ const routeNode = routePathSplit[i];
160
+ const targetNode = targetPathSplit[i];
161
+ // path node undefined, break path loop
162
+ if (!routeNode || !targetNode) continue routePathLoop;
163
+ // path node is params node
164
+ if (routeNode.includes(':')) {
165
+ // target not matched
166
+ if (targetNode === '/') continue routePathLoop;
167
+ const [prefix, paramName] = routeNode.split(':') as [string, string];
168
+ if (!startsWith(targetNode, prefix)) continue routePathLoop;
169
+ params[paramName] = targetNode.replace(`${prefix}`, '');
170
+ pathId += targetNode;
171
+ continue pathNodeLoop;
172
+ }
173
+ // path node not matched, next path
174
+ if (routeNode !== targetNode) continue routePathLoop;
175
+ pathId += targetNode;
176
+ }
177
+ // target path node longer than route, next route
178
+ if (targetPathSplit[targetPathNodePosition + 1] && !route.routes.size) continue routePathLoop;
179
+ // all path node passed, route found
180
+ return [{route, params, pathId}, ...this.getRoutes(route.routes, targetPathSplit.slice(targetPathNodePosition + 1).join('/'))]
181
+ }
182
+ }
183
+ // no route passed
184
+ const notfound = routes.get('notfound');
185
+ if (notfound) return [{route: notfound, params: {}, pathId: 'notfound'}]
186
+ return [];
187
+ }
188
+
189
+ protected getPage() {
190
+
191
+ }
192
+ }
193
+
194
+ export interface Router {
195
+ route<
196
+ P extends RoutePath,
197
+ B extends PageBuilder
198
+ >(path: P, builder: B, handle?: (route: Route<P, B['params']>) => Route<P>): Router
199
+ route<
200
+ K extends RoutePath,
201
+ P extends RouteParamsStrings<K>,
202
+ F extends PageBuilderFunction<P>
203
+ >(path: K, builder: F, handle?: (route: Route<K, P>) => Route<K, P>): this
204
+ route<
205
+ K extends RoutePath,
206
+ P extends RouteParamsStrings<K>,
207
+ F extends AsyncPageBuilder<P>
208
+ >(path: K, builder: F, handle?: (route: Route<K, P>) => Route<K, P>): this
209
+ route<P extends RoutePath>(path: P, builder: RouteBuilder<RouteParamsResolver<P>>, handle?: (route: Route<P>) => Route<P>): Router
210
+ group<P extends RoutePath>(path: P, handle: <R extends Route<P>>(route: R) => R): this;
211
+ notFound(builder: RouteBuilder<RouteParamsResolver<RoutePath>>): this;
212
+ }
@@ -1,13 +1,24 @@
1
- import { $Anchor } from "#html/$Anchor";
1
+ import { $Anchor } from "@amateras/html/node/$Anchor";
2
2
 
3
3
  export class RouterAnchor extends $Anchor {
4
4
  constructor() {
5
5
  super();
6
6
  this.on('click', e => {
7
+ if (e.shiftKey || e.ctrlKey) return;
7
8
  e.preventDefault();
8
9
  this.target() === '_replace'
9
10
  ? $.replace(this.href())
10
11
  : $.open(this.href(), this.target())
11
12
  })
12
13
  }
13
- }
14
+ }
15
+
16
+ declare module '@amateras/core' {
17
+ export namespace $ {
18
+ export interface $NodeMap {
19
+ 'ra': typeof RouterAnchor;
20
+ }
21
+ }
22
+ }
23
+
24
+ $.assign(['ra', RouterAnchor]);
@@ -0,0 +1,24 @@
1
+ import { Page } from "#node/Page";
2
+ import type { $NodeContentResolver } from "@amateras/core/node/$Node";
3
+ import { _instanceof, _Promise } from "@amateras/utils";
4
+ import type { AsyncPageBuilder, RouteParams } from "./Route";
5
+
6
+ export class PageBuilder<Params extends RouteParams = any> {
7
+ params!: Params
8
+ #builder: PageBuilderFunction<Params> | AsyncPageBuilder<Params>;
9
+ constructor(builder: PageBuilderFunction<Params>) {
10
+ this.#builder = builder;
11
+ }
12
+
13
+ async build(page: Page<Params>): Promise<Page<Params>> {
14
+ const resolver = this.#builder(page)
15
+ const handle = async (result: any) => {
16
+ if (_instanceof(result, Page)) return result;
17
+ else if (result[Symbol.toStringTag] === 'Module') return await result.default.build(page);
18
+ else return page.content(result);
19
+ }
20
+ return handle(_instanceof(resolver, _Promise) ? await resolver : resolver);
21
+ }
22
+ }
23
+
24
+ export type PageBuilderFunction<Params extends RouteParams> = (page: Page<Params>) => OrPromise<Page<Params> | $NodeContentResolver<Page<Params>>>
@@ -0,0 +1,105 @@
1
+ import type { Page } from "#node/Page";
2
+ import { _null, _instanceof, isUndefined } from "@amateras/utils";
3
+ import { PageBuilder, type PageBuilderFunction } from "./PageBuilder";
4
+
5
+ export class Route<Path extends RoutePath = RoutePath, Params extends RouteParams = []> {
6
+ readonly routes = new Map<RoutePath, Route>();
7
+ readonly path: Path;
8
+ readonly builder: PageBuilder<any> | undefined;
9
+ readonly paths = new Map<string, RouteAliasParams<RoutePath, Params> | null>()
10
+ readonly pages = new Map<string, Page>();
11
+ redirectURL: string | null = null
12
+ constructor(path: Path, builder?: RouteBuilder<Params>) {
13
+ this.path = path;
14
+ this.paths.set(path, _null);
15
+ this.builder = _instanceof(builder, PageBuilder<any>) || isUndefined(builder) ? builder : new PageBuilder(builder as any);
16
+ }
17
+
18
+
19
+ alias<K extends string, P extends RouteAliasParams<K, Params>>(path: K, ...params: RequireKeys<P> extends never ? [] : [Prettify<P>]): this
20
+ alias(path: string, params: RouteAliasParams<RoutePath, Params> | null = _null) {
21
+ this.paths.set(path, params);
22
+ return this;
23
+ }
24
+ }
25
+
26
+ export interface Route<Path extends RoutePath = RoutePath, Params extends RouteParams = []> {
27
+ route<
28
+ P extends RoutePath,
29
+ B extends PageBuilder
30
+ >(path: P, builder: B, handle?: (route: Route<`${Path}${P}`, B['params']>) => Route<`${Path}${P}`, B['params']>): this
31
+ route<
32
+ K extends RoutePath,
33
+ P extends [...Params, ...RouteParamsStrings<K>],
34
+ F extends PageBuilderFunction<P>
35
+ >(path: K, builder: F, handle?: (route: Route<`${Path}${K}`, P>) => Route<`${Path}${K}`, P>): this
36
+ route<
37
+ K extends RoutePath,
38
+ P extends [...Params, ...RouteParamsStrings<K>],
39
+ F extends AsyncPageBuilder<P>
40
+ >(path: K, builder: F, handle?: (route: Route<`${Path}${K}`, P>) => Route<`${Path}${K}`, P>): this
41
+ route<P extends RoutePath>(path: P, builder: RouteBuilder<RouteParamsResolver<`${Path}${P}`>>, handle?: <R extends Route<`${Path}${P}`>>(route: R) => R): this;
42
+ group<P extends RoutePath>(path: P, handle: <R extends Route<`${Path}${P}`>>(route: R) => R): this;
43
+ notFound(builder: RouteBuilder<RouteParamsResolver<`${Path}`>>): this;
44
+ }
45
+
46
+ export type RouteBuilder<Params extends RouteParams = []> = PageBuilder<Params | `${string}?`[]> | AsyncPageBuilder<Params | `${string}?`[]> | PageBuilderFunction<Params>;
47
+ export type RoutePath = string;
48
+ export type RouteParams = string[]
49
+ export type AsyncPageBuilder<Params extends RouteParams = any> = () => Promise<{default: PageBuilder<Params>}>
50
+
51
+ export type RouteParamsResolver<Path extends RoutePath> = RouteParamsOptional<RouteParamsStrings<Path>>
52
+
53
+ /** Convert route path to literals array */
54
+ export type RouteParamsStrings<Path extends string> =
55
+ Path extends `${infer Segment}/${infer Rest}`
56
+ ? Segment extends `${string}:${infer Param}`
57
+ ? [Param, ...RouteParamsStrings<Rest>]
58
+ : [...RouteParamsStrings<Rest>]
59
+ : Path extends `${string}:${infer Param}?${infer Query}`
60
+ ? [Param]
61
+ : Path extends `${string}:${infer Param}`
62
+ ? [Param]
63
+ : []
64
+ /** Convert route path to object structure */
65
+ export type RouteParamsConfig<Path extends string> =
66
+ Path extends `${infer Segment}/${infer Rest}`
67
+ ? Segment extends `${string}:${infer Param}`
68
+ ? { [key in Param]: string } & RouteParamsConfig<Rest>
69
+ : RouteParamsConfig<Rest>
70
+ : Path extends `${string}:${infer Param}?${infer Query}`
71
+ ? { [key in Param]: string }
72
+ : Path extends `${string}:${infer Param}`
73
+ ? { [key in Param]: string }
74
+ : {}
75
+ /** Convert literals array to optional literals arrays */
76
+ export type RouteParamsOptional<Params extends string[]> =
77
+ Params extends [infer A, ...infer Rest]
78
+ ? Rest extends string[]
79
+ ? A extends string
80
+ ? [A | `${A}?`, ...RouteParamsOptional<Rest>] | RouteParamsOptional<Rest>
81
+ : never
82
+ : never
83
+ : []
84
+
85
+ export type RouteAliasPath<Path extends string, RoutePath extends string> = RouteParamsStrings<RoutePath> extends RouteParamsStrings<Path> ? Route<RoutePath> : never
86
+
87
+ type RouteParamsConfigByArrayString<RouteParams extends string[]> =
88
+ RouteParams extends [`${infer A}`, ...infer Rest]
89
+ ? Rest extends string[]
90
+ ? A extends `${infer P}?`
91
+ ? { [key in P]?: string } & RouteParamsConfigByArrayString<Rest>
92
+ : { [key in A]: string } & RouteParamsConfigByArrayString<Rest>
93
+ : never
94
+ : {}
95
+
96
+
97
+ type RouteAliasParams<Path extends string, Params extends RouteParams> = Omit<RouteParamsConfigByArrayString<Params>, keyof RouteParamsConfig<Path>>
98
+
99
+ type a<T> = T[keyof T] extends (string | undefined) ? true : false
100
+
101
+ type b = RequireKeys<{t: string, a?: string, b?: string}> & {}
102
+
103
+ type RequireKeys<T> = {
104
+ [K in keyof T]: {} extends Pick<T, K> ? never : K
105
+ }[keyof T];
@@ -0,0 +1,93 @@
1
+ # amateras/signal
2
+
3
+ ## Usage
4
+
5
+ ```ts
6
+ import 'amateras';
7
+ import 'amateras/signal';
8
+
9
+ // define a signal with value 0
10
+ const count$ = $.signal(0);
11
+
12
+ // this variable will be auto recalculate when count$ changes
13
+ const doubleCount$ = $.compute(() => count$() * 2);
14
+
15
+ // the console message will fired when count$ changes
16
+ $.effect(() => console.log( count$() ))
17
+
18
+ $(document.body).content([
19
+ // Display Counts
20
+ $('p').content( $`Counts: ${count$}` ),
21
+
22
+ // Display Double Counts
23
+ $('p').content( $`Double Counts: ${doubleCount$}` ),
24
+
25
+ // Create a button that make counts plus 1 on click
26
+ $('button').content('Add Count').on('click', () => count$.set(value => value + 1))
27
+ ])
28
+ ```
29
+
30
+ ## Read and Write
31
+
32
+ ```ts
33
+ const number$ = $.signal(0);
34
+ const string$ = $.singal('');
35
+ const boolean$ = $.signal(false);
36
+ const object$ = $.signal({ number: 1 });
37
+
38
+ // write value
39
+ number$.set(42);
40
+ string$.set('New Content');
41
+ boolean$.set(true);
42
+ object$.set({ number: 42 });
43
+
44
+ // read value
45
+ number$(); // 42
46
+ string$(); // 'New Content'
47
+ boolean$(); // true
48
+ object$(); // { number: 42 }
49
+ ```
50
+
51
+ ## Use in attribute methods
52
+
53
+ ```ts
54
+ const src$ = $.signal('/image-1.png');
55
+
56
+ $(document.body).content([
57
+ // you can set signal variable in attribute
58
+ $('img').src( src$ ),
59
+
60
+ $('button').content('Change Image').on('click', () => src$.set('/image-2.png'))
61
+ ])
62
+ ```
63
+
64
+ ## Reactive object
65
+
66
+ ```ts
67
+ const user$ = $.signal({
68
+ name: 'Amateras',
69
+ age: 16,
70
+ avatar: {
71
+ url: '/amateras/avatar.png',
72
+ size: '350x350'
73
+ }
74
+ })
75
+
76
+ $(document.body).content([
77
+ // Display name and age
78
+ $('h1').content( $`${user$.name$} (${user$.age$})` ),
79
+ // Display avatar image
80
+ $('img').src( user$.avatar$.url$ ),
81
+ // Change the user$ when button is clicked
82
+ $('button')
83
+ .content('Change User')
84
+ .on('click', () => user$.set({
85
+ name: 'Tsukimi',
86
+ age: 10,
87
+ avatar: {
88
+ url: '/tsukimi/avatar.png',
89
+ size: '350x350'
90
+ }
91
+ }))
92
+ ])
93
+ ```
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@amateras/signal",
3
+ "peerDependencies": {
4
+ "@amateras/core": "workspace:*",
5
+ "@amateras/utils": "workspace:*"
6
+ },
7
+ "imports": {
8
+ "#structure/*": "./src/structure/*.ts",
9
+ "#lib/*": "./src/lib/*.ts",
10
+ "#node/*": "./src/node/*.ts"
11
+ },
12
+ "exports": {
13
+ ".": "./src/index.ts",
14
+ "./structure/*": "./src/structure/*.ts",
15
+ "./lib/*": "./src/lib/*.ts",
16
+ "./node/*": "./src/node/*.ts"
17
+ }
18
+ }