katanakit-js 2.1.5

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 (153) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/LICENSE +22 -0
  3. package/README.md +446 -0
  4. package/dist/adapters/astro/astro.service.d.ts +18 -0
  5. package/dist/adapters/astro/astro.service.d.ts.map +1 -0
  6. package/dist/adapters/astro/astro.service.js +83 -0
  7. package/dist/adapters/astro/astro.service.js.map +1 -0
  8. package/dist/adapters/astro/index.d.ts +4 -0
  9. package/dist/adapters/astro/index.d.ts.map +1 -0
  10. package/dist/adapters/astro/index.js +4 -0
  11. package/dist/adapters/astro/index.js.map +1 -0
  12. package/dist/adapters/astro/rss.service.d.ts +115 -0
  13. package/dist/adapters/astro/rss.service.d.ts.map +1 -0
  14. package/dist/adapters/astro/rss.service.js +231 -0
  15. package/dist/adapters/astro/rss.service.js.map +1 -0
  16. package/dist/adapters/express/app.d.ts +4 -0
  17. package/dist/adapters/express/app.d.ts.map +1 -0
  18. package/dist/adapters/express/app.js +4 -0
  19. package/dist/adapters/express/app.js.map +1 -0
  20. package/dist/adapters/express/index.d.ts +5 -0
  21. package/dist/adapters/express/index.d.ts.map +1 -0
  22. package/dist/adapters/express/index.js +5 -0
  23. package/dist/adapters/express/index.js.map +1 -0
  24. package/dist/adapters/express/main.d.ts +2 -0
  25. package/dist/adapters/express/main.d.ts.map +1 -0
  26. package/dist/adapters/express/main.js +3 -0
  27. package/dist/adapters/express/main.js.map +1 -0
  28. package/dist/adapters/express/products.controller.d.ts +10 -0
  29. package/dist/adapters/express/products.controller.d.ts.map +1 -0
  30. package/dist/adapters/express/products.controller.js +53 -0
  31. package/dist/adapters/express/products.controller.js.map +1 -0
  32. package/dist/adapters/express/router.d.ts +3 -0
  33. package/dist/adapters/express/router.d.ts.map +1 -0
  34. package/dist/adapters/express/router.js +14 -0
  35. package/dist/adapters/express/router.js.map +1 -0
  36. package/dist/adapters/express/server.d.ts +15 -0
  37. package/dist/adapters/express/server.d.ts.map +1 -0
  38. package/dist/adapters/express/server.js +59 -0
  39. package/dist/adapters/express/server.js.map +1 -0
  40. package/dist/adapters/index.d.ts +2 -0
  41. package/dist/adapters/index.d.ts.map +1 -0
  42. package/dist/adapters/index.js +2 -0
  43. package/dist/adapters/index.js.map +1 -0
  44. package/dist/adapters/nuxt/index.d.ts +2 -0
  45. package/dist/adapters/nuxt/index.d.ts.map +1 -0
  46. package/dist/adapters/nuxt/index.js +2 -0
  47. package/dist/adapters/nuxt/index.js.map +1 -0
  48. package/dist/adapters/nuxt/nuxt.service.d.ts +83 -0
  49. package/dist/adapters/nuxt/nuxt.service.d.ts.map +1 -0
  50. package/dist/adapters/nuxt/nuxt.service.js +104 -0
  51. package/dist/adapters/nuxt/nuxt.service.js.map +1 -0
  52. package/dist/config/index.d.ts +3 -0
  53. package/dist/config/index.d.ts.map +1 -0
  54. package/dist/config/index.js +3 -0
  55. package/dist/config/index.js.map +1 -0
  56. package/dist/config/seo.service.d.ts +72 -0
  57. package/dist/config/seo.service.d.ts.map +1 -0
  58. package/dist/config/seo.service.js +190 -0
  59. package/dist/config/seo.service.js.map +1 -0
  60. package/dist/config/site.config.d.ts +89 -0
  61. package/dist/config/site.config.d.ts.map +1 -0
  62. package/dist/config/site.config.js +59 -0
  63. package/dist/config/site.config.js.map +1 -0
  64. package/dist/core/index.d.ts +13 -0
  65. package/dist/core/index.d.ts.map +1 -0
  66. package/dist/core/index.js +13 -0
  67. package/dist/core/index.js.map +1 -0
  68. package/dist/core/services/dates.service.d.ts +24 -0
  69. package/dist/core/services/dates.service.d.ts.map +1 -0
  70. package/dist/core/services/dates.service.js +64 -0
  71. package/dist/core/services/dates.service.js.map +1 -0
  72. package/dist/core/services/error.service.d.ts +25 -0
  73. package/dist/core/services/error.service.d.ts.map +1 -0
  74. package/dist/core/services/error.service.js +39 -0
  75. package/dist/core/services/error.service.js.map +1 -0
  76. package/dist/core/services/formatter.service.d.ts +36 -0
  77. package/dist/core/services/formatter.service.d.ts.map +1 -0
  78. package/dist/core/services/formatter.service.js +64 -0
  79. package/dist/core/services/formatter.service.js.map +1 -0
  80. package/dist/core/services/generator.service.d.ts +34 -0
  81. package/dist/core/services/generator.service.d.ts.map +1 -0
  82. package/dist/core/services/generator.service.js +83 -0
  83. package/dist/core/services/generator.service.js.map +1 -0
  84. package/dist/core/services/geometry.service.d.ts +45 -0
  85. package/dist/core/services/geometry.service.d.ts.map +1 -0
  86. package/dist/core/services/geometry.service.js +100 -0
  87. package/dist/core/services/geometry.service.js.map +1 -0
  88. package/dist/core/services/http.service.d.ts +22 -0
  89. package/dist/core/services/http.service.d.ts.map +1 -0
  90. package/dist/core/services/http.service.js +124 -0
  91. package/dist/core/services/http.service.js.map +1 -0
  92. package/dist/core/services/logger.service.d.ts +36 -0
  93. package/dist/core/services/logger.service.d.ts.map +1 -0
  94. package/dist/core/services/logger.service.js +60 -0
  95. package/dist/core/services/logger.service.js.map +1 -0
  96. package/dist/core/services/reactive.service.d.ts +22 -0
  97. package/dist/core/services/reactive.service.d.ts.map +1 -0
  98. package/dist/core/services/reactive.service.js +167 -0
  99. package/dist/core/services/reactive.service.js.map +1 -0
  100. package/dist/core/services/timing.service.d.ts +23 -0
  101. package/dist/core/services/timing.service.d.ts.map +1 -0
  102. package/dist/core/services/timing.service.js +217 -0
  103. package/dist/core/services/timing.service.js.map +1 -0
  104. package/dist/core/services/utils.service.d.ts +44 -0
  105. package/dist/core/services/utils.service.d.ts.map +1 -0
  106. package/dist/core/services/utils.service.js +143 -0
  107. package/dist/core/services/utils.service.js.map +1 -0
  108. package/dist/index.d.ts +6 -0
  109. package/dist/index.d.ts.map +1 -0
  110. package/dist/index.js +6 -0
  111. package/dist/index.js.map +1 -0
  112. package/dist/infrastructure/dom/dom.service.d.ts +49 -0
  113. package/dist/infrastructure/dom/dom.service.d.ts.map +1 -0
  114. package/dist/infrastructure/dom/dom.service.js +133 -0
  115. package/dist/infrastructure/dom/dom.service.js.map +1 -0
  116. package/dist/infrastructure/index.d.ts +11 -0
  117. package/dist/infrastructure/index.d.ts.map +1 -0
  118. package/dist/infrastructure/index.js +11 -0
  119. package/dist/infrastructure/index.js.map +1 -0
  120. package/dist/infrastructure/observer/observer.service.d.ts +34 -0
  121. package/dist/infrastructure/observer/observer.service.d.ts.map +1 -0
  122. package/dist/infrastructure/observer/observer.service.js +145 -0
  123. package/dist/infrastructure/observer/observer.service.js.map +1 -0
  124. package/dist/infrastructure/sensors/sensors.service.d.ts +25 -0
  125. package/dist/infrastructure/sensors/sensors.service.d.ts.map +1 -0
  126. package/dist/infrastructure/sensors/sensors.service.js +133 -0
  127. package/dist/infrastructure/sensors/sensors.service.js.map +1 -0
  128. package/dist/infrastructure/storage/storage.service.d.ts +48 -0
  129. package/dist/infrastructure/storage/storage.service.d.ts.map +1 -0
  130. package/dist/infrastructure/storage/storage.service.js +108 -0
  131. package/dist/infrastructure/storage/storage.service.js.map +1 -0
  132. package/dist/infrastructure/theme/theme.service.d.ts +30 -0
  133. package/dist/infrastructure/theme/theme.service.d.ts.map +1 -0
  134. package/dist/infrastructure/theme/theme.service.js +104 -0
  135. package/dist/infrastructure/theme/theme.service.js.map +1 -0
  136. package/dist/infrastructure/viewport/viewport.service.d.ts +38 -0
  137. package/dist/infrastructure/viewport/viewport.service.d.ts.map +1 -0
  138. package/dist/infrastructure/viewport/viewport.service.js +145 -0
  139. package/dist/infrastructure/viewport/viewport.service.js.map +1 -0
  140. package/dist/infrastructure/worker/worker.service.d.ts +42 -0
  141. package/dist/infrastructure/worker/worker.service.d.ts.map +1 -0
  142. package/dist/infrastructure/worker/worker.service.js +151 -0
  143. package/dist/infrastructure/worker/worker.service.js.map +1 -0
  144. package/dist/prisma/db.d.ts +4 -0
  145. package/dist/prisma/db.d.ts.map +1 -0
  146. package/dist/prisma/db.js +12 -0
  147. package/dist/prisma/db.js.map +1 -0
  148. package/dist/prisma/schema.json +411 -0
  149. package/dist/types/index.d.ts +436 -0
  150. package/dist/types/index.d.ts.map +1 -0
  151. package/dist/types/index.js +2 -0
  152. package/dist/types/index.js.map +1 -0
  153. package/package.json +117 -0
@@ -0,0 +1,104 @@
1
+ import { useAddClass, useGetRoot, useOn, useRemoveClass, useSetAttribute, } from "../dom/dom.service.js";
2
+ import { useGetStorage, useRemoveStorage, useSetStorage } from "../storage/storage.service.js";
3
+ /**
4
+ * Theme facade (Singleton) over the DOM and Storage, with a media-query listener.
5
+ */
6
+ export class ThemeService {
7
+ static instance;
8
+ mode = "system";
9
+ storageKey = "theme";
10
+ attribute = "data-theme";
11
+ target = null;
12
+ onChange;
13
+ mediaQuery = null;
14
+ cleanMediaQueryListener = null;
15
+ constructor() { }
16
+ static getInstance() {
17
+ if (!ThemeService.instance) {
18
+ ThemeService.instance = new ThemeService();
19
+ }
20
+ return ThemeService.instance;
21
+ }
22
+ IS_BROWSER = () => {
23
+ return typeof window !== "undefined" && typeof document !== "undefined";
24
+ };
25
+ useInitTheme = (options = {}) => {
26
+ if (!this.IS_BROWSER())
27
+ return;
28
+ this.storageKey = options.storageKey ?? "theme";
29
+ this.attribute = options.attribute ?? "data-theme";
30
+ this.target = options.target ?? useGetRoot();
31
+ this.onChange = options.onChange;
32
+ const stored = useGetStorage(this.storageKey);
33
+ this.mode = stored ?? options.defaultMode ?? "system";
34
+ this.APPLY_THEME();
35
+ this.SETUP_MEDIA_QUERY_LISTENER();
36
+ };
37
+ useSetThemeMode = (mode) => {
38
+ if (!this.IS_BROWSER())
39
+ return;
40
+ this.mode = mode ?? "system";
41
+ useSetStorage(this.storageKey, this.mode, "localStorage");
42
+ this.APPLY_THEME();
43
+ };
44
+ useGetThemeMode = () => this.mode;
45
+ useGetResolved = () => {
46
+ if (this.mode !== "system")
47
+ return this.mode;
48
+ return this.usePrefersColorScheme() ? "dark" : "light";
49
+ };
50
+ usePrefersColorScheme = () => {
51
+ if (!this.IS_BROWSER() || !window.matchMedia)
52
+ return false;
53
+ return window.matchMedia("(prefers-color-scheme: dark)").matches;
54
+ };
55
+ useToggleTheme = () => {
56
+ const current = this.useGetResolved();
57
+ this.useSetThemeMode(current === "light" ? "dark" : "light");
58
+ };
59
+ useResetTheme = () => {
60
+ if (!this.IS_BROWSER())
61
+ return;
62
+ useRemoveStorage(this.storageKey);
63
+ this.mode = "system";
64
+ this.APPLY_THEME();
65
+ };
66
+ useDestroyTheme = () => {
67
+ if (this.cleanMediaQueryListener) {
68
+ this.cleanMediaQueryListener();
69
+ this.cleanMediaQueryListener = null;
70
+ this.mediaQuery = null;
71
+ }
72
+ };
73
+ APPLY_THEME = () => {
74
+ if (!this.target)
75
+ return;
76
+ const resolved = this.useGetResolved();
77
+ // Set the attribute, e.g. data-theme="dark".
78
+ useSetAttribute(this.target, this.attribute, resolved);
79
+ // Toggle CSS classes.
80
+ useRemoveClass(this.target, ["light", "dark"]);
81
+ useAddClass(this.target, resolved);
82
+ this.onChange?.(this.mode, resolved);
83
+ };
84
+ SETUP_MEDIA_QUERY_LISTENER = () => {
85
+ if (!this.IS_BROWSER() || !window.matchMedia)
86
+ return;
87
+ // Clean up any existing listener before registering a new one.
88
+ if (this.cleanMediaQueryListener) {
89
+ this.cleanMediaQueryListener();
90
+ this.cleanMediaQueryListener = null;
91
+ }
92
+ this.mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
93
+ // Register the listener using DomService.
94
+ this.cleanMediaQueryListener = useOn(this.mediaQuery, "change", () => {
95
+ if (this.mode === "system") {
96
+ this.APPLY_THEME();
97
+ }
98
+ });
99
+ };
100
+ }
101
+ // Singleton instance and safe export.
102
+ export const THEME_SERVICE = ThemeService.getInstance();
103
+ export const { useInitTheme, useSetThemeMode, useGetThemeMode, useGetResolved, usePrefersColorScheme, useToggleTheme, useResetTheme, useDestroyTheme, } = THEME_SERVICE;
104
+ //# sourceMappingURL=theme.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.service.js","sourceRoot":"","sources":["../../../src/infrastructure/theme/theme.service.ts"],"names":[],"mappings":"AACA,OAAO,EACN,WAAW,EACX,UAAU,EACV,KAAK,EACL,cAAc,EACd,eAAe,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAE/F;;GAEG;AACH,MAAM,OAAO,YAAY;IAChB,MAAM,CAAC,QAAQ,CAAe;IAE9B,IAAI,GAAc,QAAQ,CAAC;IAC3B,UAAU,GAAG,OAAO,CAAC;IACrB,SAAS,GAAG,YAAY,CAAC;IACzB,MAAM,GAAuB,IAAI,CAAC;IAClC,QAAQ,CAAyD;IACjE,UAAU,GAA0B,IAAI,CAAC;IACzC,uBAAuB,GAAwB,IAAI,CAAC;IAE5D,gBAAuB,CAAC;IAEjB,MAAM,CAAC,WAAW;QACxB,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;YAC5B,YAAY,CAAC,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;QAC5C,CAAC;QACD,OAAO,YAAY,CAAC,QAAQ,CAAC;IAC9B,CAAC;IAEO,UAAU,GAAG,GAAY,EAAE;QAClC,OAAO,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,QAAQ,KAAK,WAAW,CAAC;IACzE,CAAC,CAAC;IAEK,YAAY,GAAG,CAAC,OAAO,GAAiB,EAAE,EAAQ,EAAE;QAC1D,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YAAE,OAAO;QAE/B,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC;QAChD,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,YAAY,CAAC;QACnD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;QAC7C,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QAEjC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,UAAU,CAAqB,CAAC;QAClE,IAAI,CAAC,IAAI,GAAG,MAAM,IAAI,OAAO,CAAC,WAAW,IAAI,QAAQ,CAAC;QAEtD,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,0BAA0B,EAAE,CAAC;IACnC,CAAC,CAAC;IAEK,eAAe,GAAG,CAAC,IAAe,EAAQ,EAAE;QAClD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YAAE,OAAO;QAE/B,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,QAAQ,CAAC;QAC7B,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAC1D,IAAI,CAAC,WAAW,EAAE,CAAC;IACpB,CAAC,CAAC;IAEK,eAAe,GAAG,GAAc,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;IAE7C,cAAc,GAAG,GAAqB,EAAE;QAC9C,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC,IAAI,CAAC;QAC7C,OAAO,IAAI,CAAC,qBAAqB,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IACxD,CAAC,CAAC;IAEK,qBAAqB,GAAG,GAAY,EAAE;QAC5C,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,OAAO,KAAK,CAAC;QAC3D,OAAO,MAAM,CAAC,UAAU,CAAC,8BAA8B,CAAC,CAAC,OAAO,CAAC;IAClE,CAAC,CAAC;IAEK,cAAc,GAAG,GAAS,EAAE;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACtC,IAAI,CAAC,eAAe,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC9D,CAAC,CAAC;IAEK,aAAa,GAAG,GAAS,EAAE;QACjC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YAAE,OAAO;QAC/B,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC;QACrB,IAAI,CAAC,WAAW,EAAE,CAAC;IACpB,CAAC,CAAC;IAEK,eAAe,GAAG,GAAS,EAAE;QACnC,IAAI,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAClC,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAC/B,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC;YACpC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACxB,CAAC;IACF,CAAC,CAAC;IAEM,WAAW,GAAG,GAAS,EAAE;QAChC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QAEzB,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAEvC,6CAA6C;QAC7C,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAEvD,sBAAsB;QACtB,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QAC/C,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAEnC,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACtC,CAAC,CAAC;IAEM,0BAA0B,GAAG,GAAS,EAAE;QAC/C,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,OAAO;QAErD,+DAA+D;QAC/D,IAAI,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAClC,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAC/B,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC;QACrC,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,8BAA8B,CAAC,CAAC;QAEpE,0CAA0C;QAC1C,IAAI,CAAC,uBAAuB,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE;YACpE,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC5B,IAAI,CAAC,WAAW,EAAE,CAAC;YACpB,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC;CACF;AAED,sCAAsC;AACtC,MAAM,CAAC,MAAM,aAAa,GAAiB,YAAY,CAAC,WAAW,EAAE,CAAC;AAEtE,MAAM,CAAC,MAAM,EACZ,YAAY,EACZ,eAAe,EACf,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,eAAe,GACf,GAAiB,aAAa,CAAC"}
@@ -0,0 +1,38 @@
1
+ import type { ScrollOptions, ScrollPosition, ViewportSize } from "../../types/index.js";
2
+ /**
3
+ * Viewport, scroll and window utilities. All methods are SSR-safe.
4
+ */
5
+ export default class ViewportService {
6
+ private static instance;
7
+ private constructor();
8
+ static getInstance(): ViewportService;
9
+ private isBrowser;
10
+ useGetViewportSize: () => ViewportSize;
11
+ useMatchesMedia: (query: string) => boolean;
12
+ usePrefersReducedMotion: () => boolean;
13
+ usePrefersDarkMode: () => boolean;
14
+ useGetScrollY: () => number;
15
+ useGetScrollX: () => number;
16
+ useGetScrollPosition: () => ScrollPosition;
17
+ useGetScrollProgress: () => number;
18
+ useIsAtTop: (threshold?: number) => boolean;
19
+ useIsAtBottom: (threshold?: number) => boolean;
20
+ useScrollTo: (x?: number, y?: number, behavior?: ScrollBehavior) => void;
21
+ useScrollToTop: (smooth?: boolean) => void;
22
+ useScrollToBottom: (smooth?: boolean) => void;
23
+ useScrollToElement: (target: HTMLElement | string, options?: ScrollOptions) => boolean;
24
+ usePrintPage: () => void;
25
+ useFocusElement: (target: HTMLElement | string) => boolean;
26
+ useBlurActiveElement: () => void;
27
+ useGetActiveElement: () => Element | null;
28
+ useRequestFullscreen: (target?: HTMLElement) => Promise<void>;
29
+ useExitFullscreen: () => Promise<void>;
30
+ useIsFullscreen: () => boolean;
31
+ useIsDocumentVisible: () => boolean;
32
+ useOnVisibilityChange: (callback: (isVisible: boolean) => void) => (() => void);
33
+ useGetTitle: () => string;
34
+ useSetTitle: (title: string) => void;
35
+ useSetTempTitle: (tempTitle: string, durationMs?: number) => void;
36
+ }
37
+ export declare const useGetViewportSize: () => ViewportSize, useMatchesMedia: (query: string) => boolean, usePrefersReducedMotion: () => boolean, usePrefersDarkMode: () => boolean, useGetScrollY: () => number, useGetScrollX: () => number, useGetScrollPosition: () => ScrollPosition, useGetScrollProgress: () => number, useIsAtTop: (threshold?: number) => boolean, useIsAtBottom: (threshold?: number) => boolean, useScrollTo: (x?: number, y?: number, behavior?: ScrollBehavior) => void, useScrollToTop: (smooth?: boolean) => void, useScrollToBottom: (smooth?: boolean) => void, useScrollToElement: (target: HTMLElement | string, options?: ScrollOptions) => boolean, usePrintPage: () => void, useFocusElement: (target: HTMLElement | string) => boolean, useBlurActiveElement: () => void, useGetActiveElement: () => Element | null, useRequestFullscreen: (target?: HTMLElement) => Promise<void>, useExitFullscreen: () => Promise<void>, useIsFullscreen: () => boolean, useIsDocumentVisible: () => boolean, useOnVisibilityChange: (callback: (isVisible: boolean) => void) => (() => void), useGetTitle: () => string, useSetTitle: (title: string) => void, useSetTempTitle: (tempTitle: string, durationMs?: number) => void;
38
+ //# sourceMappingURL=viewport.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewport.service.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/viewport/viewport.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAExF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,eAAe;IACnC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkB;IAEzC,OAAO,eAAiB;IAExB,OAAc,WAAW,IAAI,eAAe,CAK3C;IAED,OAAO,CAAC,SAAS,CACiD;IAE3D,kBAAkB,QAAO,YAAY,CAG1C;IAEK,eAAe,UAAW,MAAM,KAAG,OAAO,CAG/C;IAEK,uBAAuB,QAAO,OAAO,CACc;IAEnD,kBAAkB,QAAO,OAAO,CAAyD;IAEzF,aAAa,QAAO,MAAM,CAA4C;IAEtE,aAAa,QAAO,MAAM,CAA4C;IAEtE,oBAAoB,QAAO,cAAc,CAG7C;IAEI,oBAAoB,QAAO,MAAM,CAKtC;IAEK,UAAU,0BAAoB,OAAO,CAAsC;IAE3E,aAAa,0BAAqB,OAAO,CAI9C;IAEK,WAAW,sCAA4B,cAAc,KAAc,IAAI,CAI5E;IAEK,cAAc,wBAAoB,IAAI,CAI3C;IAEK,iBAAiB,wBAAoB,IAAI,CAK9C;IAEK,kBAAkB,WAChB,WAAW,GAAG,MAAM,YACnB,aAAa,KACpB,OAAO,CAkBR;IAEK,YAAY,QAAO,IAAI,CAE5B;IAEK,eAAe,WAAY,WAAW,GAAG,MAAM,KAAG,OAAO,CAS9D;IAEK,oBAAoB,QAAO,IAAI,CAGpC;IAEK,mBAAmB,QAAO,OAAO,GAAG,IAAI,CACG;IAE3C,oBAAoB,YAAmB,WAAW,KAAG,OAAO,CAAC,IAAI,CAAC,CAOvE;IAEK,iBAAiB,QAAa,OAAO,CAAC,IAAI,CAAC,CAGhD;IAEK,eAAe,QAAO,OAAO,CAAqD;IAElF,oBAAoB,QAAO,OAAO,CAGvC;IAEK,qBAAqB,aAAc,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC,CAOnF;IAEK,WAAW,QAAO,MAAM,CAA6C;IAErE,WAAW,UAAW,MAAM,KAAG,IAAI,CAExC;IAEK,eAAe,cAAe,MAAM,0BAAsB,IAAI,CAWnE;CACF;AAGD,eAAO,MACN,kBAAkB,QA5Jc,YAAY,EA6J5C,eAAe,UAxJkB,MAAM,KAAG,OAAO,EAyJjD,uBAAuB,QApJc,OAAO,EAqJ5C,kBAAkB,QAlJc,OAAO,EAmJvC,aAAa,QAjJc,MAAM,EAkJjC,aAAa,QAhJc,MAAM,EAiJjC,oBAAoB,QA/Ic,cAAc,EAgJhD,oBAAoB,QA3Ic,MAAM,EA4IxC,UAAU,0BArI2B,OAAO,EAsI5C,aAAa,0BApI4B,OAAO,EAqIhD,WAAW,sCA/HmC,cAAc,KAAc,IAAI,EAgI9E,cAAc,wBA1H2B,IAAI,EA2H7C,iBAAiB,wBArH2B,IAAI,EAsHhD,kBAAkB,WA9GT,WAAW,GAAG,MAAM,YACnB,aAAa,KACpB,OAAO,EA6GV,YAAY,QAzFc,IAAI,EA0F9B,eAAe,WAtFmB,WAAW,GAAG,MAAM,KAAG,OAAO,EAuFhE,oBAAoB,QA5Ec,IAAI,EA6EtC,mBAAmB,QAxEc,OAAO,GAAG,IAAI,EAyE/C,oBAAoB,YAtE0B,WAAW,KAAG,OAAO,CAAC,IAAI,CAAC,EAuEzE,iBAAiB,QA9DoB,OAAO,CAAC,IAAI,CAAC,EA+DlD,eAAe,QA1Dc,OAAO,EA2DpC,oBAAoB,QAzDc,OAAO,EA0DzC,qBAAqB,aArDqB,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC,EAsDrF,WAAW,QA7Cc,MAAM,EA8C/B,WAAW,UA5CkB,MAAM,KAAG,IAAI,EA6C1C,eAAe,cAzCsB,MAAM,0BAAsB,IA0ChB,CAAC"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Viewport, scroll and window utilities. All methods are SSR-safe.
3
+ */
4
+ export default class ViewportService {
5
+ static instance;
6
+ constructor() { }
7
+ static getInstance() {
8
+ if (!ViewportService.instance) {
9
+ ViewportService.instance = new ViewportService();
10
+ }
11
+ return ViewportService.instance;
12
+ }
13
+ isBrowser = () => typeof window !== "undefined" && typeof document !== "undefined";
14
+ useGetViewportSize = () => {
15
+ if (!this.isBrowser())
16
+ return { width: 0, height: 0 };
17
+ return { width: window.innerWidth, height: window.innerHeight };
18
+ };
19
+ useMatchesMedia = (query) => {
20
+ if (!this.isBrowser() || !window.matchMedia)
21
+ return false;
22
+ return window.matchMedia(query).matches;
23
+ };
24
+ usePrefersReducedMotion = () => this.useMatchesMedia("(prefers-reduced-motion: reduce)");
25
+ usePrefersDarkMode = () => this.useMatchesMedia("(prefers-color-scheme: dark)");
26
+ useGetScrollY = () => (this.isBrowser() ? window.scrollY : 0);
27
+ useGetScrollX = () => (this.isBrowser() ? window.scrollX : 0);
28
+ useGetScrollPosition = () => ({
29
+ x: this.useGetScrollX(),
30
+ y: this.useGetScrollY(),
31
+ });
32
+ useGetScrollProgress = () => {
33
+ if (!this.isBrowser())
34
+ return 0;
35
+ const scrollHeight = document.documentElement.scrollHeight - window.innerHeight;
36
+ if (scrollHeight <= 0)
37
+ return 0;
38
+ return Math.min(1, Math.max(0, window.scrollY / scrollHeight));
39
+ };
40
+ useIsAtTop = (threshold = 0) => this.useGetScrollY() <= threshold;
41
+ useIsAtBottom = (threshold = 50) => {
42
+ if (!this.isBrowser())
43
+ return false;
44
+ const scrollHeight = document.documentElement.scrollHeight;
45
+ return window.scrollY + window.innerHeight >= scrollHeight - threshold;
46
+ };
47
+ useScrollTo = (x = 0, y = 0, behavior = "smooth") => {
48
+ if (!this.isBrowser())
49
+ return;
50
+ const finalBehavior = this.usePrefersReducedMotion() ? "auto" : behavior;
51
+ window.scrollTo({ top: y, left: x, behavior: finalBehavior });
52
+ };
53
+ useScrollToTop = (smooth = true) => {
54
+ if (!this.isBrowser())
55
+ return;
56
+ const behavior = smooth && !this.usePrefersReducedMotion() ? "smooth" : "auto";
57
+ window.scrollTo({ top: 0, behavior });
58
+ };
59
+ useScrollToBottom = (smooth = true) => {
60
+ if (!this.isBrowser())
61
+ return;
62
+ const behavior = smooth && !this.usePrefersReducedMotion() ? "smooth" : "auto";
63
+ const scrollHeight = document.documentElement.scrollHeight;
64
+ window.scrollTo({ top: scrollHeight, behavior });
65
+ };
66
+ useScrollToElement = (target, options = {}) => {
67
+ if (!this.isBrowser())
68
+ return false;
69
+ const element = typeof target === "string" ? document.querySelector(target) : target;
70
+ if (!element)
71
+ return false;
72
+ const behavior = this.usePrefersReducedMotion()
73
+ ? "auto"
74
+ : (options.behavior ?? "smooth");
75
+ element.scrollIntoView({
76
+ behavior,
77
+ block: options.block ?? "start",
78
+ inline: options.inline ?? "nearest",
79
+ });
80
+ return true;
81
+ };
82
+ usePrintPage = () => {
83
+ if (this.isBrowser())
84
+ window.print();
85
+ };
86
+ useFocusElement = (target) => {
87
+ if (!this.isBrowser())
88
+ return false;
89
+ const element = typeof target === "string" ? document.querySelector(target) : target;
90
+ if (!element)
91
+ return false;
92
+ element.focus();
93
+ return true;
94
+ };
95
+ useBlurActiveElement = () => {
96
+ if (!this.isBrowser())
97
+ return;
98
+ document.activeElement?.blur();
99
+ };
100
+ useGetActiveElement = () => this.isBrowser() ? document.activeElement : null;
101
+ useRequestFullscreen = async (target) => {
102
+ if (!this.isBrowser() || !document.fullscreenEnabled) {
103
+ throw new Error("Fullscreen not supported");
104
+ }
105
+ const element = target ?? document.documentElement;
106
+ await element.requestFullscreen();
107
+ };
108
+ useExitFullscreen = async () => {
109
+ if (!this.isBrowser() || !document.fullscreenElement)
110
+ return;
111
+ await document.exitFullscreen();
112
+ };
113
+ useIsFullscreen = () => this.isBrowser() && !!document.fullscreenElement;
114
+ useIsDocumentVisible = () => {
115
+ if (!this.isBrowser())
116
+ return true;
117
+ return document.visibilityState === "visible";
118
+ };
119
+ useOnVisibilityChange = (callback) => {
120
+ if (!this.isBrowser())
121
+ return () => { };
122
+ const handler = () => callback(this.useIsDocumentVisible());
123
+ document.addEventListener("visibilitychange", handler);
124
+ return () => document.removeEventListener("visibilitychange", handler);
125
+ };
126
+ useGetTitle = () => (this.isBrowser() ? document.title : "");
127
+ useSetTitle = (title) => {
128
+ if (this.isBrowser())
129
+ document.title = title;
130
+ };
131
+ useSetTempTitle = (tempTitle, durationMs = 3000) => {
132
+ if (!this.isBrowser())
133
+ return;
134
+ const original = document.title;
135
+ document.title = tempTitle;
136
+ setTimeout(() => {
137
+ if (document.title === tempTitle) {
138
+ document.title = original;
139
+ }
140
+ }, durationMs);
141
+ };
142
+ }
143
+ // Singleton instance and destructured exports.
144
+ export const { useGetViewportSize, useMatchesMedia, usePrefersReducedMotion, usePrefersDarkMode, useGetScrollY, useGetScrollX, useGetScrollPosition, useGetScrollProgress, useIsAtTop, useIsAtBottom, useScrollTo, useScrollToTop, useScrollToBottom, useScrollToElement, usePrintPage, useFocusElement, useBlurActiveElement, useGetActiveElement, useRequestFullscreen, useExitFullscreen, useIsFullscreen, useIsDocumentVisible, useOnVisibilityChange, useGetTitle, useSetTitle, useSetTempTitle, } = ViewportService.getInstance();
145
+ //# sourceMappingURL=viewport.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewport.service.js","sourceRoot":"","sources":["../../../src/infrastructure/viewport/viewport.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import type { WorkerFunc } from "../../types/index.js";
2
+ /**
3
+ * Worker facade (Singleton + Pool pattern) for running pure functions off the
4
+ * main thread, with an SSR/main-thread fallback when Worker is unavailable.
5
+ */
6
+ export default class WorkerService {
7
+ private static instance;
8
+ private pools;
9
+ private constructor();
10
+ static getInstance(): WorkerService;
11
+ static useIsSupported(): boolean;
12
+ /**
13
+ * Runs a pure function in a one-shot Worker and destroys it afterwards.
14
+ */
15
+ useRun<TInput, TOutput>(workerFunc: WorkerFunc<TInput, TOutput>, data: TInput): Promise<TOutput>;
16
+ /**
17
+ * Creates a reusable Worker pool under a unique key.
18
+ */
19
+ useCreatePool<TInput, TOutput>(key: string, workerFunc: WorkerFunc<TInput, TOutput>): this;
20
+ /**
21
+ * Runs a task on an existing pool. Tasks are queued to prevent race conditions
22
+ * when multiple calls target the same pool key concurrently.
23
+ */
24
+ useRunPool<TInput, TOutput>(key: string, data: TInput): Promise<TOutput>;
25
+ /**
26
+ * Terminates a specific pool.
27
+ */
28
+ useTerminate(key: string): this;
29
+ /**
30
+ * Terminates all active pools.
31
+ */
32
+ useTerminateAll(): this;
33
+ /**
34
+ * Checks whether a pool exists.
35
+ */
36
+ useHasWorker(key: string): boolean;
37
+ /**
38
+ * Lists all active pool keys.
39
+ */
40
+ useKeys(): string[];
41
+ }
42
+ //# sourceMappingURL=worker.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.service.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/worker/worker.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,sBAAsB,CAAC;AAExE;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,aAAa;IACjC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAgB;IACvC,OAAO,CAAC,KAAK,CAA2C;IAExD,OAAO,eAAiB;IAExB,MAAM,CAAC,WAAW,IAAI,aAAa,CAKlC;IAED,MAAM,CAAC,cAAc,IAAI,OAAO,CAE/B;IAED;;OAEG;IACG,MAAM,CAAC,MAAM,EAAE,OAAO,EAC3B,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,IAAI,EAAE,MAAM,GACV,OAAO,CAAC,OAAO,CAAC,CAgDlB;IAED;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAuBzF;IAED;;;OAGG;IACH,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA6BvE;IAED;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAQ9B;IAED;;OAEG;IACH,eAAe,IAAI,IAAI,CAKtB;IAED;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEjC;IAED;;OAEG;IACH,OAAO,IAAI,MAAM,EAAE,CAElB;CACD"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Worker facade (Singleton + Pool pattern) for running pure functions off the
3
+ * main thread, with an SSR/main-thread fallback when Worker is unavailable.
4
+ */
5
+ export default class WorkerService {
6
+ static instance;
7
+ pools = new Map();
8
+ constructor() { }
9
+ static getInstance() {
10
+ if (!WorkerService.instance) {
11
+ WorkerService.instance = new WorkerService();
12
+ }
13
+ return WorkerService.instance;
14
+ }
15
+ static useIsSupported() {
16
+ return typeof window !== "undefined" && "Worker" in window;
17
+ }
18
+ /**
19
+ * Runs a pure function in a one-shot Worker and destroys it afterwards.
20
+ */
21
+ async useRun(workerFunc, data) {
22
+ if (!WorkerService.useIsSupported()) {
23
+ // SSR/Node fallback: run on the main thread.
24
+ return Promise.resolve(workerFunc(data));
25
+ }
26
+ return new Promise((resolve, reject) => {
27
+ let worker;
28
+ let workerUrl;
29
+ const cleanup = () => {
30
+ if (worker) {
31
+ worker.terminate();
32
+ worker = undefined;
33
+ }
34
+ if (workerUrl) {
35
+ URL.revokeObjectURL(workerUrl);
36
+ workerUrl = undefined;
37
+ }
38
+ };
39
+ try {
40
+ const funcString = workerFunc.toString();
41
+ const blob = new Blob([`self.onmessage = (e) => self.postMessage((${funcString})(e.data))`], {
42
+ type: "application/javascript",
43
+ });
44
+ workerUrl = URL.createObjectURL(blob);
45
+ worker = new Worker(workerUrl);
46
+ worker.onmessage = (event) => {
47
+ cleanup();
48
+ resolve(event.data);
49
+ };
50
+ worker.onerror = (error) => {
51
+ cleanup();
52
+ reject(new Error(`Worker error: ${error.message}`));
53
+ };
54
+ worker.onmessageerror = () => {
55
+ cleanup();
56
+ reject(new Error("Worker returned a non-cloneable value."));
57
+ };
58
+ worker.postMessage(data);
59
+ }
60
+ catch (error) {
61
+ cleanup();
62
+ reject(error);
63
+ }
64
+ });
65
+ }
66
+ /**
67
+ * Creates a reusable Worker pool under a unique key.
68
+ */
69
+ useCreatePool(key, workerFunc) {
70
+ if (!WorkerService.useIsSupported())
71
+ return this;
72
+ if (this.pools.has(key)) {
73
+ this.useTerminate(key);
74
+ }
75
+ const funcString = workerFunc.toString();
76
+ const blob = new Blob([
77
+ `self.onmessage = (e) => self.postMessage({ __taskId: e.data.__taskId, payload: (${funcString})(e.data.payload) })`,
78
+ ], { type: "application/javascript" });
79
+ const workerUrl = URL.createObjectURL(blob);
80
+ const worker = new Worker(workerUrl);
81
+ this.pools.set(key, {
82
+ worker,
83
+ workerUrl,
84
+ func: workerFunc,
85
+ });
86
+ return this;
87
+ }
88
+ /**
89
+ * Runs a task on an existing pool. Tasks are queued to prevent race conditions
90
+ * when multiple calls target the same pool key concurrently.
91
+ */
92
+ useRunPool(key, data) {
93
+ const entry = this.pools.get(key);
94
+ if (!entry) {
95
+ return Promise.reject(new Error(`Worker pool "${key}" not found`));
96
+ }
97
+ if (!WorkerService.useIsSupported()) {
98
+ return Promise.resolve(entry.func(data));
99
+ }
100
+ // Queue the task to prevent onmessage race conditions.
101
+ const taskId = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
102
+ return new Promise((resolve, reject) => {
103
+ const handler = (event) => {
104
+ if (event.data?.__taskId === taskId) {
105
+ entry.worker.removeEventListener("message", handler);
106
+ resolve(event.data.payload);
107
+ }
108
+ };
109
+ entry.worker.addEventListener("message", handler);
110
+ entry.worker.onerror = (error) => {
111
+ entry.worker.removeEventListener("message", handler);
112
+ reject(new Error(`Worker error: ${error.message}`));
113
+ };
114
+ entry.worker.postMessage({ __taskId: taskId, payload: data });
115
+ });
116
+ }
117
+ /**
118
+ * Terminates a specific pool.
119
+ */
120
+ useTerminate(key) {
121
+ const entry = this.pools.get(key);
122
+ if (!entry)
123
+ return this;
124
+ entry.worker.terminate();
125
+ URL.revokeObjectURL(entry.workerUrl);
126
+ this.pools.delete(key);
127
+ return this;
128
+ }
129
+ /**
130
+ * Terminates all active pools.
131
+ */
132
+ useTerminateAll() {
133
+ for (const key of this.pools.keys()) {
134
+ this.useTerminate(key);
135
+ }
136
+ return this;
137
+ }
138
+ /**
139
+ * Checks whether a pool exists.
140
+ */
141
+ useHasWorker(key) {
142
+ return this.pools.has(key);
143
+ }
144
+ /**
145
+ * Lists all active pool keys.
146
+ */
147
+ useKeys() {
148
+ return Array.from(this.pools.keys());
149
+ }
150
+ }
151
+ //# sourceMappingURL=worker.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.service.js","sourceRoot":"","sources":["../../../src/infrastructure/worker/worker.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import "dotenv/config";
2
+ import type { Contract } from "./schema.d.js";
3
+ export declare const db: import("@prisma/orm-postgres/runtime").PostgresClient<Contract>;
4
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/prisma/db.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAQ9C,eAAO,MAAM,EAAE,iEAGb,CAAC"}
@@ -0,0 +1,12 @@
1
+ import "dotenv/config";
2
+ import postgres from "@prisma/orm-postgres/runtime";
3
+ import contractJson from "./schema.json" with { type: "json" };
4
+ const DATABASE_URL = process.env.DATABASE_URL;
5
+ if (!DATABASE_URL) {
6
+ throw new Error("[db] DATABASE_URL is not set. Copy .env.example to .env and configure it.");
7
+ }
8
+ export const db = postgres({
9
+ contractJson,
10
+ url: DATABASE_URL,
11
+ });
12
+ //# sourceMappingURL=db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/prisma/db.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AACvB,OAAO,QAAQ,MAAM,8BAA8B,CAAC;AAEpD,OAAO,YAAY,MAAM,eAAe,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAE/D,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;AAC9C,IAAI,CAAC,YAAY,EAAE,CAAC;IACnB,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;AAC9F,CAAC;AAED,MAAM,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAW;IACpC,YAAY;IACZ,GAAG,EAAE,YAAY;CACjB,CAAC,CAAC"}