@vnejs/docs 0.2.65 → 0.2.67

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 (261) hide show
  1. package/README.md +35 -35
  2. package/architecture/backends.md +18 -0
  3. package/architecture/build.md +37 -0
  4. package/architecture/bundles.md +20 -0
  5. package/architecture/cli.md +25 -0
  6. package/architecture/compatibility.md +22 -0
  7. package/architecture/configs.md +19 -0
  8. package/architecture/contracts.md +30 -0
  9. package/architecture/dependencies.md +55 -0
  10. package/architecture/editor.md +7 -0
  11. package/architecture/games.md +38 -0
  12. package/architecture/helpers.md +14 -0
  13. package/architecture/model.md +43 -0
  14. package/architecture/modules.md +87 -0
  15. package/architecture/packages.md +43 -0
  16. package/architecture/plugins.md +36 -0
  17. package/architecture/uis.md +23 -0
  18. package/changelog/0.2.18.md +7 -0
  19. package/changelog/0.2.19.md +14 -0
  20. package/changelog/0.2.20.md +10 -0
  21. package/changelog/0.2.21.md +5 -0
  22. package/changelog/0.2.22.md +11 -0
  23. package/changelog/0.2.23.md +4 -0
  24. package/changelog/0.2.25.md +6 -0
  25. package/changelog/0.2.26.md +12 -0
  26. package/changelog/0.2.29.md +10 -0
  27. package/changelog/0.2.31.md +5 -0
  28. package/changelog/0.2.32.md +3 -0
  29. package/changelog/0.2.33.md +5 -0
  30. package/changelog/0.2.34.md +8 -0
  31. package/changelog/0.2.35.md +33 -0
  32. package/changelog/0.2.36.md +10 -0
  33. package/changelog/0.2.38.md +19 -0
  34. package/changelog/0.2.39.md +16 -0
  35. package/changelog/0.2.40.md +9 -0
  36. package/changelog/0.2.42.md +3 -0
  37. package/changelog/0.2.43.md +10 -0
  38. package/changelog/0.2.46.md +3 -0
  39. package/changelog/0.2.47.md +25 -0
  40. package/changelog/0.2.49.md +3 -0
  41. package/changelog/0.2.50.md +6 -0
  42. package/changelog/0.2.51.md +6 -0
  43. package/changelog/0.2.52.md +5 -0
  44. package/changelog/0.2.53.md +12 -0
  45. package/changelog/0.2.55.md +19 -0
  46. package/changelog/0.2.56.md +11 -0
  47. package/changelog/0.2.57.md +7 -0
  48. package/changelog/0.2.58.md +8 -0
  49. package/changelog/0.2.59.md +6 -0
  50. package/changelog/0.2.60.md +5 -0
  51. package/changelog/0.2.61.md +11 -0
  52. package/changelog/0.2.62.md +8 -0
  53. package/changelog/0.2.63.md +4 -0
  54. package/changelog/0.2.64.md +4 -0
  55. package/changelog/0.2.65.md +3 -0
  56. package/changelog/0.2.66.md +5 -0
  57. package/changelog/README.md +43 -0
  58. package/manifest.json +66 -5
  59. package/package.json +6 -4
  60. package/plugins/ai/ai.md +29 -29
  61. package/plugins/ai/checkers.md +26 -26
  62. package/plugins/audio/ambient.md +20 -20
  63. package/plugins/audio/audio.md +40 -40
  64. package/plugins/audio/music.md +20 -20
  65. package/plugins/audio/sound.md +20 -20
  66. package/plugins/audio/voice.md +23 -23
  67. package/plugins/canvas/bg.md +44 -44
  68. package/plugins/canvas/bg.speak.md +34 -34
  69. package/plugins/canvas/fill.md +33 -33
  70. package/plugins/canvas/layer.md +35 -35
  71. package/plugins/canvas/sprite.md +46 -46
  72. package/plugins/canvas/sprite.speak.md +33 -33
  73. package/plugins/canvas/text.md +37 -37
  74. package/plugins/canvas/video.md +37 -37
  75. package/plugins/canvas.layers/bl.md +33 -33
  76. package/plugins/canvas.layers/fl.md +33 -33
  77. package/plugins/canvas.layers/ml.md +33 -33
  78. package/plugins/canvas.layers/ul.md +32 -32
  79. package/plugins/canvas.props/animation.md +25 -25
  80. package/plugins/canvas.props/clip.md +22 -22
  81. package/plugins/canvas.props/filters.md +20 -20
  82. package/plugins/canvas.props/mask.md +23 -23
  83. package/plugins/canvas.props/scale.md +20 -20
  84. package/plugins/common/grid.md +23 -23
  85. package/plugins/common/turn.md +18 -18
  86. package/plugins/controls/controls.md +31 -31
  87. package/plugins/controls/cursor.md +54 -54
  88. package/plugins/controls/gamepad.md +56 -56
  89. package/plugins/controls/keyboard.md +17 -17
  90. package/plugins/core/components.md +28 -28
  91. package/plugins/core/interact.md +26 -26
  92. package/plugins/core/logs.md +28 -28
  93. package/plugins/core/media.md +38 -38
  94. package/plugins/core/memory.md +28 -28
  95. package/plugins/core/platforms.md +19 -19
  96. package/plugins/core/scenario.md +48 -48
  97. package/plugins/core/settings.md +24 -24
  98. package/plugins/core/stack.md +39 -39
  99. package/plugins/core/state.md +30 -30
  100. package/plugins/core/storage.md +56 -56
  101. package/plugins/core/system.md +37 -37
  102. package/plugins/core/vendors.md +19 -19
  103. package/plugins/entities/entities.md +16 -16
  104. package/plugins/entities/wallet.md +27 -27
  105. package/plugins/font/montserrat.md +16 -16
  106. package/plugins/game/checkers.md +38 -38
  107. package/plugins/platform/android.md +17 -17
  108. package/plugins/platform/electron.md +21 -21
  109. package/plugins/platform/metric.md +23 -23
  110. package/plugins/rpg/damage.md +22 -22
  111. package/plugins/rpg/hit.md +24 -24
  112. package/plugins/rpg/skills.md +26 -26
  113. package/plugins/save/auto.md +26 -26
  114. package/plugins/save/continue.md +23 -23
  115. package/plugins/save/quick.md +24 -24
  116. package/plugins/save/save.md +37 -37
  117. package/plugins/scales/health.md +17 -17
  118. package/plugins/scales/mana.md +17 -17
  119. package/plugins/scales/scales.md +31 -31
  120. package/plugins/scenario/autoread.md +36 -36
  121. package/plugins/scenario/choose.md +74 -65
  122. package/plugins/scenario/fastforward.md +46 -46
  123. package/plugins/scenario/history.md +41 -41
  124. package/plugins/scenario/pause.md +27 -27
  125. package/plugins/scenario/point_and_click.md +51 -51
  126. package/plugins/scenario/qte.md +54 -54
  127. package/plugins/scenario/random.md +17 -17
  128. package/plugins/settings/filter.md +19 -19
  129. package/plugins/settings/potato.md +22 -22
  130. package/plugins/settings/ratio.md +19 -19
  131. package/plugins/settings/textsize.md +19 -19
  132. package/plugins/settings/volume.md +21 -21
  133. package/plugins/text/inject.md +22 -22
  134. package/plugins/text/locs.md +36 -36
  135. package/plugins/text/meet.md +19 -19
  136. package/plugins/text/smooth.md +33 -33
  137. package/plugins/text/text.md +76 -69
  138. package/plugins/text/wall.md +20 -20
  139. package/plugins/time/date.md +22 -22
  140. package/plugins/time/time.md +23 -23
  141. package/plugins/vars/counters.md +28 -28
  142. package/plugins/vars/flags.md +24 -24
  143. package/plugins/vars/vars.md +29 -29
  144. package/plugins/views/achievement.md +44 -44
  145. package/plugins/views/comment.md +31 -31
  146. package/plugins/views/controls.hints.md +34 -34
  147. package/plugins/views/cursor.md +19 -19
  148. package/plugins/views/fps.md +33 -33
  149. package/plugins/views/gamepad.debug.md +32 -32
  150. package/plugins/views/settings.md +39 -39
  151. package/plugins/views/video.md +37 -37
  152. package/plugins/views.scenario/choose.md +41 -41
  153. package/plugins/views.scenario/interface.controls.md +31 -31
  154. package/plugins/views.scenario/interface.fastforward.md +29 -29
  155. package/plugins/views.scenario/interface.md +74 -74
  156. package/plugins/views.scenario/point_and_click.md +39 -39
  157. package/plugins/views.scenario/qte.md +51 -51
  158. package/plugins/views.screens/checkers.md +35 -35
  159. package/plugins/views.screens/confirm.md +35 -35
  160. package/plugins/views.screens/credits.md +31 -31
  161. package/plugins/views.screens/disclaimer.md +42 -42
  162. package/plugins/views.screens/eula.md +37 -37
  163. package/plugins/views.screens/gallery.full.md +41 -41
  164. package/plugins/views.screens/gallery.md +75 -75
  165. package/plugins/views.screens/gamemenu.md +41 -41
  166. package/plugins/views.screens/history.md +39 -39
  167. package/plugins/views.screens/intro.md +32 -32
  168. package/plugins/views.screens/loading.md +30 -30
  169. package/plugins/views.screens/mainmenu.md +49 -49
  170. package/plugins/views.screens/mainmenu.socials.md +25 -25
  171. package/plugins/views.screens/save.md +66 -66
  172. package/plugins/views.screens/settings.defaults.md +37 -37
  173. package/plugins/views.screens/settings.md +40 -40
  174. package/scenario.catalog/README.md +13 -13
  175. package/scenario.catalog/index.md +35 -35
  176. package/scenario.catalog/stubs/achievement.md +4 -4
  177. package/scenario.catalog/stubs/audio.ambient.md +4 -4
  178. package/scenario.catalog/stubs/audio.music.md +4 -4
  179. package/scenario.catalog/stubs/audio.sound.md +4 -4
  180. package/scenario.catalog/stubs/audio.voice.md +4 -4
  181. package/scenario.catalog/stubs/bl.animation.md +5 -5
  182. package/scenario.catalog/stubs/bl.bg.md +5 -5
  183. package/scenario.catalog/stubs/bl.clip.md +5 -5
  184. package/scenario.catalog/stubs/bl.fill.md +5 -5
  185. package/scenario.catalog/stubs/bl.filter.md +5 -5
  186. package/scenario.catalog/stubs/bl.mask.md +5 -5
  187. package/scenario.catalog/stubs/bl.scale.md +5 -5
  188. package/scenario.catalog/stubs/bl.sprite.md +5 -5
  189. package/scenario.catalog/stubs/bl.text.md +5 -5
  190. package/scenario.catalog/stubs/bl.video.md +5 -5
  191. package/scenario.catalog/stubs/choose.block.md +7 -7
  192. package/scenario.catalog/stubs/choose.md +4 -4
  193. package/scenario.catalog/stubs/choose.option.md +7 -7
  194. package/scenario.catalog/stubs/comment.md +5 -5
  195. package/scenario.catalog/stubs/counter.md +5 -5
  196. package/scenario.catalog/stubs/credits.md +4 -4
  197. package/scenario.catalog/stubs/date.md +4 -4
  198. package/scenario.catalog/stubs/disclaimer.md +5 -5
  199. package/scenario.catalog/stubs/fl.animation.md +5 -5
  200. package/scenario.catalog/stubs/fl.bg.md +5 -5
  201. package/scenario.catalog/stubs/fl.clip.md +5 -5
  202. package/scenario.catalog/stubs/fl.fill.md +5 -5
  203. package/scenario.catalog/stubs/fl.filter.md +5 -5
  204. package/scenario.catalog/stubs/fl.mask.md +5 -5
  205. package/scenario.catalog/stubs/fl.scale.md +5 -5
  206. package/scenario.catalog/stubs/fl.sprite.md +5 -5
  207. package/scenario.catalog/stubs/fl.text.md +5 -5
  208. package/scenario.catalog/stubs/fl.video.md +5 -5
  209. package/scenario.catalog/stubs/flag.md +13 -13
  210. package/scenario.catalog/stubs/interface.md +4 -4
  211. package/scenario.catalog/stubs/intro.md +4 -4
  212. package/scenario.catalog/stubs/mainmenu.md +4 -4
  213. package/scenario.catalog/stubs/ml.animation.md +5 -5
  214. package/scenario.catalog/stubs/ml.bg.md +5 -5
  215. package/scenario.catalog/stubs/ml.clip.md +5 -5
  216. package/scenario.catalog/stubs/ml.fill.md +5 -5
  217. package/scenario.catalog/stubs/ml.filter.md +5 -5
  218. package/scenario.catalog/stubs/ml.mask.md +5 -5
  219. package/scenario.catalog/stubs/ml.scale.md +5 -5
  220. package/scenario.catalog/stubs/ml.sprite.md +5 -5
  221. package/scenario.catalog/stubs/ml.text.md +5 -5
  222. package/scenario.catalog/stubs/ml.video.md +5 -5
  223. package/scenario.catalog/stubs/other.md +6 -6
  224. package/scenario.catalog/stubs/pause.md +5 -5
  225. package/scenario.catalog/stubs/point-and-click.block.md +4 -4
  226. package/scenario.catalog/stubs/point-and-click.md +4 -4
  227. package/scenario.catalog/stubs/point-and-click.option.md +4 -4
  228. package/scenario.catalog/stubs/qte.md +4 -4
  229. package/scenario.catalog/stubs/random.md +4 -4
  230. package/scenario.catalog/stubs/random.option.md +4 -4
  231. package/scenario.catalog/stubs/save.auto.md +4 -4
  232. package/scenario.catalog/stubs/save.md +5 -5
  233. package/scenario.catalog/stubs/scenario.md +4 -4
  234. package/scenario.catalog/stubs/settings.defaults.md +4 -4
  235. package/scenario.catalog/stubs/stack.md +4 -4
  236. package/scenario.catalog/stubs/text.meet.md +4 -4
  237. package/scenario.catalog/stubs/text.wall.md +4 -4
  238. package/scenario.catalog/stubs/time.md +4 -4
  239. package/scenario.catalog/stubs/ul.animation.md +5 -5
  240. package/scenario.catalog/stubs/ul.bg.md +5 -5
  241. package/scenario.catalog/stubs/ul.clip.md +5 -5
  242. package/scenario.catalog/stubs/ul.fill.md +5 -5
  243. package/scenario.catalog/stubs/ul.filter.md +5 -5
  244. package/scenario.catalog/stubs/ul.mask.md +5 -5
  245. package/scenario.catalog/stubs/ul.scale.md +5 -5
  246. package/scenario.catalog/stubs/ul.sprite.md +5 -5
  247. package/scenario.catalog/stubs/ul.text.md +5 -5
  248. package/scenario.catalog/stubs/video.md +4 -4
  249. package/scenario.catalog/stubs/wallet.md +4 -4
  250. package/scenario.guide/README.md +38 -38
  251. package/scenario.guide/audio.md +11 -11
  252. package/scenario.guide/canvas.md +23 -23
  253. package/scenario.guide/choose.md +28 -28
  254. package/scenario.guide/dialogue.md +23 -23
  255. package/scenario.guide/flow.md +21 -21
  256. package/scenario.guide/point-and-click.md +12 -12
  257. package/scenario.guide/qte-random.md +20 -20
  258. package/scenario.guide/vars.md +19 -19
  259. package/scenario.guide/views.md +20 -20
  260. package/CHANGELOG.md +0 -387
  261. package/architecture.md +0 -566
@@ -0,0 +1,23 @@
1
+ # uis/
2
+
3
+ **Презентационный слой** для view-плагинов — не плагин, не в `VNE`.
4
+
5
+ | Часть | Назначение |
6
+ | --------------------------- | ----------------------------- |
7
+ | **`uis/utils/`** | `cn`, `injectStyles`, `sel` |
8
+ | **`uis/react/primitives/`** | Атомы (button, text, icon, …) |
9
+ | **`uis/react/composites/`** | Составные компоненты |
10
+ | **`uis/react/complex/`** | Крупные UI-блоки |
11
+ | **`uis/react/hooks/`** | React-хуки |
12
+ | **`uis/react/base/`** | Barrel **`@vnejs/uis.react`** |
13
+
14
+ View-плагины в `plugins/`: **`ModuleView`** + render на компонентах из `uis/`.
15
+
16
+ ```mermaid
17
+ flowchart TD
18
+ VP[plugins/ view / ModuleView]
19
+ VP --> UIR["@vnejs/uis.react"]
20
+ VP --> UU["@vnejs/uis.utils"]
21
+ VP --> OBS[Observer]
22
+ UIR -.->|"не использует"| VNE
23
+ ```
@@ -0,0 +1,7 @@
1
+ # 0.2.18
2
+
3
+ - `views.screens/mainmenu` — vertical arrows live in the module `mainmenu.controller.arrows` on `@vnejs/module.controller.arrows.vertical`. The index in state is `currentArrowVerticalItem` (ACCEPT reads it, not the base `currentItem`). The `ACCEPT` / `INTERACT` buttons and the `ACCEPT` handler → `CLICK` live in `mainmenu.controller.accept` on `@vnejs/module.controller.accept` (a mirror of `STATE_UPDATE`). `mainmenu.controller` pushes an empty `controls` on `ZINDEX`, so it stops the layers below. `STATE.SET` / `STATE.CLEAR` emit `HIDE` with `{ isForce: true }` from the module `mainmenu.hide` on `@vnejs/module.controller.hide.on.state`. Accept / arrows / backgrounds no longer listen to `STATE.SET` / `STATE.CLEAR` directly. They listen only to `HIDE`.
4
+ - `views/settings` — horizontal navigation of TextControls: arrows cycle `options` (`selector_texts` calls `SETTINGS.SET` at once). `INTERACT` is for `actions` that have no `settingKey`.
5
+ - `views.screens/settings` — overlay BGM on SHOW starts at the volume `SETTINGS.MUSIC.VOLUME`.
6
+ - `views.screens/gallery` — overlay BGM on SHOW starts at the volume `SETTINGS.MUSIC.VOLUME`.
7
+ - `views.screens/save` — overlay BGM on SHOW starts at the volume `SETTINGS.MUSIC.VOLUME`.
@@ -0,0 +1,14 @@
1
+ # 0.2.19
2
+
3
+ - `views.screens/gamemenu` — vertical arrows live in the module `gameMenu.controller.arrows` on `@vnejs/module.controller.arrows.vertical`. The index in state is `currentArrowVerticalItem`. `ACCEPT` / `INTERACT` and the `ACCEPT` handler → `CLICK` live in `gameMenu.controller.accept` on `@vnejs/module.controller.accept`. `BACK` / `MENU` / `GAMEMENU` → `HIDE` in `gameMenu.hide.controls` on `@vnejs/module.controller.hide.on.controls`. `STATE.SET` / `STATE.CLEAR` emit `HIDE` with `{ isForce: true }` from the module `gameMenu.hide.state` on `@vnejs/module.controller.hide.on.state`. API: `EVENTS.GAMEMENU.STATE_UPDATE`, `EVENTS.GAMEMENU.UPDATE_FAST`.
4
+ - `views.screens/history` — vertical arrows live in the module `history.controller.arrows` on `@vnejs/module.controller.arrows.vertical`. The index in state is `currentArrowVerticalItem`. `ACCEPT` / `INTERACT` and the `ACCEPT` handler → `CLICK` live in `history.controller.accept` on `@vnejs/module.controller.accept`. `BACK` / `MENU` / `GAMEMENU` → `HIDE` in `history.hide.controls` on `@vnejs/module.controller.hide.on.controls`. API: `EVENTS.HISTORY.STATE_UPDATE`, `EVENTS.HISTORY.UPDATE_FAST`.
5
+ - `views.screens/settings` — `BACK` / `MENU` / `GAMEMENU` → `HIDE` in `settings.hide.controls` on `@vnejs/module.controller.hide.on.controls`.
6
+ - `views.screens/gallery` — `BACK` / `MENU` / `GAMEMENU` → `HIDE` in `gallery.hide.controls` on `@vnejs/module.controller.hide.on.controls`.
7
+ - `views.screens/gallery.full` — `BACK` / `MENU` / `GAMEMENU` → `HIDE` in `gallery.full.hide.controls` on `@vnejs/module.controller.hide.on.controls`.
8
+ - `views.screens/save` — `BACK` / `MENU` / `GAMEMENU` → `HIDE` in `save.hide.controls` on `@vnejs/module.controller.hide.on.controls`.
9
+ - `views.scenario/choose` — vertical arrows live in the module `choose_view.controller.arrows` on `@vnejs/module.controller.arrows.vertical`. `hided` is skipped through `isArrowItemAvailable` (the index stays the source index). `ACCEPT` / `INTERACT` → `CHOOSE.OPTION` in `choose_view.controller.accept` on `@vnejs/module.controller.accept`. API: `EVENTS.CHOOSE_VIEW.STATE_UPDATE`, `EVENTS.CHOOSE_VIEW.UPDATE_FAST`, `EVENTS.CHOOSE_VIEW.ACCEPT`.
10
+ - `views.screens/confirm` — `ACCEPT` / `INTERACT` live in `confirm.controller.accept` on `@vnejs/module.controller.accept`. With `currentItem`, index 0 is `ACCEPT` and any other index is `DECLINE`. With no selection, it is `ACCEPT`. API: `EVENTS.CONFIRM.SUBMIT`, `EVENTS.CONFIRM.STATE_UPDATE`.
11
+ - `views.screens/eula` — `ACCEPT` (`IS_INTERACT_ENABLED = false`) lives in `eula.controller.accept` on `@vnejs/module.controller.accept` → `EULA.ACCEPT` → `ACCEPTED_VERSION`, `HIDE`.
12
+ - `views.screens/settings.defaults` — `ACCEPT` (`IS_INTERACT_ENABLED = false`) lives in `settings.defaults.controller.accept` on `@vnejs/module.controller.accept` → `CONFIRM` → `INITED`, `HIDE`, `emitNext`.
13
+ - `views/comment` — `STATE.SET` / `STATE.CLEAR` emit `HIDE` with `{ isForce: true }` from the module `comment.hide` on `@vnejs/module.controller.hide.on.state`.
14
+ - `views.screens/mainmenu.socials` — direct subscriptions to `STATE.SET` / `STATE.CLEAR` are gone. Hide goes through `MAINMENU.HIDE` from `mainmenu.hide`.
@@ -0,0 +1,10 @@
1
+ # 0.2.20
2
+
3
+ - `views.screens/confirm` — horizontal arrows live in the module `confirm.controller.arrows` on `@vnejs/module.controller.arrows.horizontal`. The index in state is `currentArrowHorizontalItem`. `ACCEPT` / `INTERACT` read it, not `currentItem`. `STATE.CLEAR` → `HIDE` with `{ isForce: true }` in `confirm.hide.state` on `@vnejs/module.controller.hide.on.state` (`IS_STATE_SET_ENABLED = false`). API: `EVENTS.CONFIRM.UPDATE_FAST`.
4
+ - `views.screens/disclaimer` — `ACCEPT` / `INTERACT` live in `disclaimer.controller.accept` on `@vnejs/module.controller.accept` → `DISCLAIMER.ACCEPT` → `HIDE`, `emitNext`.
5
+ - `views.screens/credits` — `ACCEPT` / `INTERACT` → `HIDE` in `credits.controller.accept` on `@vnejs/module.controller.accept`. `BACK` / `MENU` / `GAMEMENU` → `HIDE` in `credits.hide.controls` on `@vnejs/module.controller.hide.on.controls`. `STATE.SET` / `STATE.CLEAR` → `HIDE` with `{ isForce: true }` in `credits.hide.state` on `@vnejs/module.controller.hide.on.state`.
6
+ - `views/settings` — vertical arrows live in the module `settings.fields.controller.arrows` on `@vnejs/module.controller.arrows.vertical`. The index in state is `currentArrowVerticalItem`. `TAB_SET` resets the index. API: `EVENTS.SETTINGS_VIEW.STATE_UPDATE`, `EVENTS.SETTINGS_VIEW.UPDATE_FAST`.
7
+ - `views.screens/eula` — vertical arrows over the text live in `eula.controller.arrows` on `@vnejs/module.controller.arrows.vertical`. Empty lines go through `isArrowItemAvailable`. The index is `currentArrowVerticalItem`. `STATE.SET` / `STATE.CLEAR` → `HIDE` in `eula.hide.state` on `@vnejs/module.controller.hide.on.state`. API: `EVENTS.EULA.STATE_UPDATE`, `EVENTS.EULA.UPDATE_FAST`.
8
+ - `views.screens/gallery` — `STATE.SET` / `STATE.CLEAR` → `HIDE` with `{ isForce: true }` in `gallery.hide.state` on `@vnejs/module.controller.hide.on.state`.
9
+ - `views/video` — `STATE.CLEAR` → `HIDE` with `{ isForce: true }` in `video.hide.state` on `@vnejs/module.controller.hide.on.state` (`IS_STATE_SET_ENABLED = false`).
10
+ - `canvas/sprite` — an empty string and other falsy values in `getSrc` become transparent (`EMPTY_IMG`), with no `MEDIA.GET` / `MEDIA.LOAD`. `indexSrc` is taken from the first non-empty overlay.
@@ -0,0 +1,5 @@
1
+ # 0.2.21
2
+
3
+ - `core/media` — a fetch error or timeout does not take a semaphore slot and does not store a broken blob in memory. `GET` does not wait forever. It returns `null` for a missing or broken asset.
4
+ - `core/scenario` — `LABEL_GET` / `LINE_GET` finish even when the preload of one line fails.
5
+ - `cli/desktop` — closing the last window quits Electron on macOS too (Steam does not keep the game running). Fastify closes on quit. If the process does not exit, `app.exit(0)`. API: `runServer` returns `{ port, close }`, `runElectron` takes `onBeforeQuit`.
@@ -0,0 +1,11 @@
1
+ # 0.2.22
2
+
3
+ - `scenario/fastforward` — the autoclick loop lives in the module `fastforward.emit`. A failed `CHECK` emits `STOP`. `isFastforwardOn` is reset through `setValue(false)` in `init`, not on `SYSTEM.STARTED`. Visits live in `shared.fastforwardStorage`. Disk writes live in `fastforward.storage`. API: `shared.fastforwardStorage`, `EVENTS.FASTFORWARD.VISIT_ADD`, modules `fastforward.emit`, `fastforward.scenario`, `fastforward.storage`.
4
+ - `core/vendors` — the events `UID`, `HASH`, `DATE`, `DEBOUNCE` are removed. `CLONE` and `SCREEN` remain. Use `crypto.randomUUID()`, `hashSha256`, `formatTimestamp`, `debounce` instead.
5
+ - `helpers/hash-sha256` — SHA-256 of an object: `hashSha256(value, maxLength?)`. Keys are canonicalized. `maxLength` is not passed yet.
6
+ - `helpers/format-timestamp` — `formatTimestamp({ ts, format })`. Tokens `YYYY`, `MM`, `DD`, `HH`, `mm`, `ss`.
7
+ - `helpers/debounce` — `debounce({ fn, wait, maxWait, leading, trailing })`.
8
+ - `core/logs`, `text/text`, `canvas/bg`, `canvas/video`, `views.screens/history` — uid comes from `crypto.randomUUID()`, not `VENDORS.UID`.
9
+ - `core/scenario`, `core/state`, `scenario/fastforward` — a line hash / visits go through `hashSha256`, not `VENDORS.HASH`.
10
+ - `views.screens/save` — the slot date and time go through `formatTimestamp`, not `VENDORS.DATE`.
11
+ - `platform/electron` — state saves go through `debounce`, not `VENDORS.DEBOUNCE`.
@@ -0,0 +1,4 @@
1
+ # 0.2.23
2
+
3
+ - `cli/desktop`, `cli/tools` — Fastify `~5.12.3` (security 5.12.2+). The API does not change.
4
+ - `cli/monorepo` — `run-changed` can run scripts in parallel through `p-limit`. After the window, concurrency drops to 1. The first command is optionally strict serial. `publish:changed:*` and `bump` phase 3: `--concurrency 8`, `--parallel-ms 270000`, `--first-serial` (the npm-key window is about 5 minutes). API: `--concurrency`, `--parallel-ms`, `--first-serial`.
@@ -0,0 +1,6 @@
1
+ # 0.2.25
2
+
3
+ - `module.components` — `updateEvent` → `EVENT_UPDATE_VIEW`. On `ModuleView`: `locLabel` → `LOC_LABEL`, `animationTime` → `TRANSITION`, `updateHandler` defaults to `onUpdateStoreComponent`. On `ModuleController`: `bgName` → `BGNAME`, `controls` / `controlsIndex` / `controlsCheckNext` → `CONTROLS` / `CONTROLS_INDEX` / `CONTROLS_CHECK_NEXT` (plus `CONTROLS_UNVISIBLE` on interface). The same `CONTROLS` field is on accept / hide.on.controls / arrows / tabs.
4
+ - `module.controller.audio` — `SHOW_EVENT` / `HIDE_EVENT` / `LOAD_EVENT` → `EVENT_SHOW` / `EVENT_HIDE` / `EVENT_LOAD`.
5
+ - Module names now use the slug `PLUGIN_NAME`: `gamemenu.*`, `point_and_click.*` (not a hyphen), `metric`, `locs`, `scale_health` / `scale_mana`, `settings.screen.*`, `settings.default.*`, `choose.option.before`, `text.emit.before`, `cursor.view.set`, `layer.video.src.get`. Scenario commands (`% point-and-click`, `$ settings.defaults`) did not change. `$ settings.defaults` is registered through `execName`.
6
+ - Module classes are CamelCase of `name` (segments `.` `_` `-`): `GamemenuControllerAccept`, `CursorViewSet`, `Metric`, `Locs`, `SettingsScreenView`. Compatibility: `CompatibilityTextWithAudioVoice`. Not `GameMenu*` / `YaMetrika` / `TextLocs`. When the name matches a global constructor, add the suffix `Module`: `DateModule`, `TextModule`, `CommentModule`, `HistoryModule`, `StorageModule` (not `Date` / `Text` / `Comment` / `History` / `Storage`).
@@ -0,0 +1,12 @@
1
+ # 0.2.26
2
+
3
+ - `compatibility/views.scenario.interface/text` — TEXT → INTERFACE: `CHANGED` / `SPEAKER_CHANGED` / `EMIT_BEFORE` → `TEXT_CHANGED` / `SPEAKER_CHANGED` / `SHOW`. Init sets `shared.interfaceTextShowAllTokensOnChange`. API: `@vnejs/compatibility.views.scenario.interface-with-text`.
4
+ - `compatibility/views.scenario.interface/text.smooth` — `TEXT_SMOOTH.CHANGED` → `INTERFACE.TEXT_CHANGED` (`tokens` from `globalState.text`, `tokensVisible`, `uid`).
5
+ - `views.scenario/interface` — direct subscriptions to `TEXT.CHANGED` / `TEXT.SPEAKER_CHANGED` and `TEXT.EMIT_BEFORE_REG` are gone. The link goes through the compatibility package above. Removed `EVENTS.INTERFACE.VISIBLE_TOKENS_CHANGED` / `InterfaceVisibleTokensChangedPayload`. Use `EVENTS.INTERFACE.TEXT_CHANGED` instead. `$ interface` show/hide/view lives in the module `interface.scenario` through `CONST.INTERFACE.EXEC_ACTIONS`. SHOW / HIDE / VISIBLE / TEXT_HIDE / VIEW live in `interface.actions` through `globalState.interface`. API: `CONST.INTERFACE.EXEC_ACTIONS`.
6
+ - `views.screens/history` — `STATE.SET` → `HIDE` with `{ isForce: true }` in `history.hide.state` on `@vnejs/module.controller.hide.on.state` (`IS_STATE_CLEAR_ENABLED = false`).
7
+ - `views.screens/settings` — `STATE.SET` / `STATE.CLEAR` → `HIDE` with `{ isForce: true }` in `settings.screen.hide.state` on `@vnejs/module.controller.hide.on.state`.
8
+ - `views.screens/save` — `STATE.SET` / `STATE.CLEAR` → `HIDE` with `{ isForce: true }` in `save.hide.state`. `ACCEPT` / `INTERACT` live in `save.controller.accept` on `@vnejs/module.controller.accept` → `SAVE_VIEW.ACCEPT` → `CREATE` / `LOAD`. API: `EVENTS.SAVE_VIEW.ACCEPT`, `EVENTS.SAVE_VIEW.STATE_UPDATE`.
9
+ - `views.screens/gallery` — `ACCEPT` / `INTERACT` live in `gallery.controller.accept` on `@vnejs/module.controller.accept` → `GALLERY.ACCEPT` → `CHOOSE` for the open slot. API: `EVENTS.GALLERY.ACCEPT`, `EVENTS.GALLERY.STATE_UPDATE`.
10
+ - `views.scenario/qte` — `ACCEPT` / `INTERACT` live in `qte_view.controller.accept` on `@vnejs/module.controller.accept` → `QTE_VIEW.ACTION`.
11
+ - `views.scenario/interface` — `ACCEPT` / `INTERACT` live in `interface.controller.accept` on `@vnejs/module.controller.accept` → `INTERFACE.INTERACT`: a visible layer → `INTERACT.EMIT`, a hidden layer → `INTERFACE.VISIBLE`.
12
+ - `views.screens/credits` — `ACCEPT` / `INTERACT` live in `credits.controller.accept` → `CREDITS.ACCEPT` → `HIDE`. API: `EVENTS.CREDITS.ACCEPT`.
@@ -0,0 +1,10 @@
1
+ # 0.2.29
2
+
3
+ - `core/memory` — `GET` / `SET` / `KEYS` no longer wait for `waitForModuleReg`. Every `MEMORY.REG` runs in `setup`: `scenario.label` / `line` / `lines`, `media.memory` (together with `#media`), `locs`, `history`. An unregistered namespace: `GET` → `null`, `SET` is a no-op, `KEYS` → `[]`. The registry is only `shared.memory` (created in `Memory.postinject`). `GET` / `SET` / `KEYS` live in `memory.store`, `CLEAR` lives in `memory.clear`. API: `shared.memory`.
4
+ - `modules_extensions/base` — at the end of `inject`, `postinject` is called when the method exists. API: `Module.postinject()`.
5
+ - `packages/core`, `modules_extensions/base` — the `start` phase runs after every `init`, instead of `EVENTS.SYSTEM.STARTED` (`vne:system:started`). Moved: `scenario.autostart`, `vendors.screen`, `cursor`, `cursor.view.set`, `layer.viewport`, `ratio`, `fps`, `gamepad.debug`, `electron`, `android`, `controls.hints.controller`, `interface.fastforward.controller`, the mainmenu/save/intro/loading controllers, `mainmenu.socials.controller`, `gallery.controller`, compatibility text.smooth and canvas.layer/save. API: `Module.start()`, `window.unstartedModules`.
6
+ - `core/storage`, `core/settings`, `core/media`, `core/components` — providers are prepared in `setup`: localforage / `shared.settings` / semaphore / `#components`. `STORAGE.INIT` and `SETTINGS.SET` / `INIT` wait for `ensureReady`. Removed `waitIsReady` / `isReady` guards on `memory`, `media`, `mainmenu`, `logs`, `eula`, `scenario.label`, `settings.screen.controller`, `interface.fastforward.controller`. `logs` / `eula` register `SETTINGS.INIT` in `setup`. `ModuleView` (`RENDER`) and `electron` (`STORAGE.CHANGED`) stay.
7
+ - `packages/core`, `modules_extensions/base` — every module has a `setup` phase before `init`: `inject → subscribe → setup → init → start`. Every `setup` finishes before any `init`. API: `Module.setup()`, `window.unsetupModules`.
8
+ - `core/stack` — before `EMIT` / `CALL` / `JUMP`, and before a preload jump/call on `LINE_LOAD`, the chain `PROHIBIT_REPLACE` (`isProhibited`) runs. When it is forbidden, `PROHIBITED` fires (`label`, `args`, `event` — `JUMP` / `CALL` / `EMIT`, so the call can be repeated), with no `LABEL_GET` and no `emitNext` on `$ stack jump/call`. `EMIT` / `JUMP` / `CALL` return `false` when forbidden, and `true` after a successful `EMIT`. Handlers go through `PROHIBIT_REPLACE_REG` (`return isProhibited || ownCheck`). Module `stack.replace`. API: `EVENTS.STACK.PROHIBIT_REPLACE`, `EVENTS.STACK.PROHIBIT_REPLACE_REG`, `EVENTS.STACK.PROHIBITED`, `CONST.STACK.LOGS_ACTIONS.PROHIBITED`, `StackProhibitReplacePayload`, `StackProhibitedPayload`.
9
+ - `vars/counters` — CHANGE / COMPARE live in `vars.counters.handlers`. EXEC_INFO / EXEC_CHECK / EXEC_GET live in `vars.counters.exec`. `LINE_EXEC` registration lives in `vars.counters.scenario` (was `vars.counters.exec`). Events and payloads are unchanged.
10
+ - `cli/monorepo` — `run-changed` runs scripts in dependency-graph layers. Inside a layer they run in parallel (`--concurrency`). The next layer waits for the previous one. `publish:changed:*` no longer builds a dependent package while a dependency is clearing `dist`. API: layers show up in dry-run / confirm. `--concurrency`, `--parallel-ms`, `--first-serial` are unchanged.
@@ -0,0 +1,5 @@
1
+ # 0.2.31
2
+
3
+ - `core/logs` — `SETTINGS.INIT` `ENABLED` runs in `setup`. Before `isReady`, `EMIT` is only buffered. In `init` the queue is flushed by `ENABLED` (otherwise it is cleared). API: buffer `LOGS.EMIT` until ready.
4
+ - every plugin that registers settings — `SETTINGS.INIT` runs in `setup` (not in `init`): eula, save.auto, autoread, fastforward (+visits), voice.lang, locs, text.process.enabled, text.smooth.cycle, volume/ratio/filter/textsize/potato, cursor scroll/shift, layer.quality, layer.animation, fps, gamepad.debug, settings.defaults, settings.screen.controller, electron (`CONFIG_APPLIED`). Applying values / REG / DOM stays in `init` where it was.
5
+ - sync `shared.*` with no I/O — in `postinject`: `audioNoSmoothSources`, `layerBgSpeakSources`, `layerSpriteSpeakSources`, `textProcessSkipSources`, `isTextSmoothInProcess`, `isTextWallSetStateInProcess`, `isInteractInProcess`, `mediaNoTimeoutSources`, `autosaveDisableSources`, `pauseDisableSources`, `autoreadDisableSources`, `voiceDisableSources`, `viewForceAnimationSources`, `interfaceTextShowAllTokensOnChange`, `shouldAutostartScenario`. API: fields are created in `Module.postinject()` instead of `init` / `setup`.
@@ -0,0 +1,3 @@
1
+ # 0.2.32
2
+
3
+ - `canvas/layer` — removed the module `layer.viewport` (it set the viewport meta to the canvas size, `width=1920,height=1080`). The viewport and the ban on document scroll live in the game `entry/index.html`: `width=device-width, initial-scale=1`, `overflow: hidden` on `html` / `body`. That is how `games/coraline` and `games/vn.skeleton` do it. The canvas resolution still lives in `--vne-canvas-width` / `--vne-canvas-height`.
@@ -0,0 +1,5 @@
1
+ # 0.2.33
2
+
3
+ - `views.scenario/point_and_click` — `SETTINGS.CHANGED` updates the view only when `state.isShow` (`point_and_click_view.controller`).
4
+ - `core/memory` — `MEMORY.CLEAR` before the `memory.clear` module is `isReady` is ignored (no clear, and no `CLEARED`).
5
+ - `text/locs` — `SETTINGS.CHANGED` does not call `setTextLang` until `locs` is `isReady`. The language is applied by `LOCS.SET` (`init`, and `SETTINGS.CHANGED` after `isReady`), not by a module method. In `postinject`, `shared.textLang = PARAMS.LOCS.DEFAULT_LANG`. The wait for a frame before the language is gone. Reads and writes of an already loaded dictionary go through events of the module `locs.memory`, not a direct `MEMORY` call from the loader. `LOCS.MEMORY_SET` accepts `{ label, group, lang?, value }`. The module computes the key. API: `LOCS.SET`, `LOCS.MEMORY_GET`, `LOCS.MEMORY_SET`, `shared.textLang`.
@@ -0,0 +1,8 @@
1
+ # 0.2.34
2
+
3
+ - `scenario/pause` — logs live in the module `pause.logs`, not in `emitLog` from the step. `$ pause` is handled by the module `pause.scenario`: `LINE_EXEC_REG`, then `EVENTS.PAUSE.EMIT` and `emitNext`. Locks live in the module `pause.emit`: in `postinject` it creates `shared.pauseDisableSources`. `EVENTS.PAUSE.EMIT` (`vne:pause:emit`) emits `START` when the set is empty. `START` no longer checks locks and does not call `emitNext`. `STATE.CLEAR` no longer calls `END`. API: `EVENTS.PAUSE.EMIT`, `CONST.PAUSE.LOGS_ACTIONS` (`EMIT` / `emit`, `START` / `start`, `END` / `end`).
4
+ - `scenario/autoread` — the timer is set and cleared through events, not through module methods. `TIMEOUT_CREATE` sets a timer for `SETTINGS.AUTOREAD.DELAY` and then emits `AUTOREAD.EMIT`. `TIMEOUT_CLEAR` clears the timer. PUSH / POP / `STATE.SET` / `STATE.CLEAR` go through these events. The autoread step is the module `autoread.emit` on `EVENTS.AUTOREAD.EMIT` (`vne:autoread:emit`). The timer is the module `autoread.timeout` (`TIMEOUT_CREATE` / `TIMEOUT_CLEAR`; `STATE.CLEAR` → `TIMEOUT_CLEAR`, `STATE.SET` → `TIMEOUT_CLEAR` then `TIMEOUT_CREATE`). Locks are the module `autoread.sources`: `postinject` creates `shared.autoreadDisableSources`, `PUSH` / `POP` change the set, `STATE.SET` clears it. Replaces `EVENTS.AUTOREAD.TRY` (`vne:autoread:try`). Logs are the module `autoread.logs`, not `emitLog` from the step. `CONST.AUTOREAD.LOGS_ACTIONS`: `EMIT` (`emit`), `PUSH` (`push`), `POP` (`pop`), `TIMEOUT_CREATE` (`timeout_create`), `TIMEOUT_CLEAR` (`timeout_clear`). `PUSH` / `POP` write `source`. API: `EVENTS.AUTOREAD.EMIT`, `EVENTS.AUTOREAD.TIMEOUT_CREATE`, `EVENTS.AUTOREAD.TIMEOUT_CLEAR`, `CONST.AUTOREAD.LOGS_ACTIONS`.
5
+ - `scenario/history` — the snapshot log moved out of the screen (`@vnejs/plugins.scenario.history`). A step back is `EVENTS.HISTORY.BACK`. A record is `EVENTS.HISTORY.ADD` / `GET` / `SET` / `LOAD` / `KEYS` / `KEYS_UPDATE`. A snapshot goes to memory through `EVENTS.HISTORY.SET` (`{ uid, value }`), not a direct `MEMORY.SET`. Key warmup is `EVENTS.HISTORY.KEYS_UPDATE`. The load flag is `shared.isHistoryLoadInProcess`, not a field on the module. Logs are `CONST.HISTORY.LOGS_ACTIONS` (`ADD`, `LOAD_START`, `LOAD_DELETED`, `LOAD_END`). `PARAMS.HISTORY.MAX_LENGTH`. The bridge to `MEMORY` is the module `history.memory` (`MEMORY.REG` / `GET` / `SET` / `KEYS`, key `module: this.name`). Snapshot load is the module `history.load` (`EVENTS.HISTORY.LOAD`, flag `shared.isHistoryLoadInProcess`). A step back is the module `history.back` (`EVENTS.HISTORY.BACK`, the last record from `globalState.history`). The plugin and the write links are in `bundles/vn.skeleton`. Replaces `HISTORY.ADD` from the screen `views.screens/history`.
6
+ - `views.screens/history` — the history screen: namespace `HISTORY_VIEW` (`@vnejs/plugins.views.screens.history`), in `bundles/vn.base`. API: `EVENTS.HISTORY_VIEW.SHOW`, `EVENTS.HISTORY_VIEW.HIDE`, `EVENTS.HISTORY_VIEW.CLICK`, `EVENTS.HISTORY_VIEW.UPDATE`, `EVENTS.HISTORY_VIEW.STATE_UPDATE`, `EVENTS.HISTORY_VIEW.UPDATE_FAST`, `EVENTS.HISTORY_VIEW.ACCEPT`, `PARAMS.HISTORY_VIEW.ZINDEX`, `PARAMS.HISTORY_VIEW.TRANSITION`, `PARAMS.HISTORY_VIEW.LOC_LABEL`, `PARAMS.HISTORY_VIEW.VIEW_PROPS`. Replaces `EVENTS.HISTORY.SHOW` and the other view events of `HISTORY`.
7
+ - `compatibility/text/scenario.history` — `@vnejs/compatibility.text-with-scenario.history` replaces `@vnejs/compatibility.text-with-views.screens.history`. On `TEXT.EMIT_NEXT` it emits `EVENTS.HISTORY.ADD`.
8
+ - `compatibility/scenario.choose/scenario.history` — `@vnejs/compatibility.scenario.choose-with-scenario.history` replaces `@vnejs/compatibility.scenario.choose-with-views.screens.history`. On `CHOOSE.OPTION_BEFORE_REG` it emits `EVENTS.HISTORY.ADD` with `{ locKey: "choice" }`.
@@ -0,0 +1,33 @@
1
+ # 0.2.35
2
+
3
+ - `scenario/qte` — `RESULT` is handled in the module `qte.result` (`CLOSED` + `applyResult` / `emitNext`). `qte` only does `EMIT` → `OPENED` and `shared.qteScenarioSkip`.
4
+ - `scenario/qte` — the embedded-mode flag is `shared.qteScenarioSkip`, not a field on the module. In `postinject` it is `false`. `qte.logs` reads the same shared value. API: `shared.qteScenarioSkip`.
5
+ - `scenario/qte` — logs live in the module `qte.logs`, not in `emitLog` from `qte`. `EMIT` / `RESULT` write `skipScenario` (for `RESULT`, from `shared.qteScenarioSkip`). `MISSING` comes from `qte.scenario` through `CONST.QTE.LOGS_ACTIONS.MISSING`. API: `CONST.QTE.LOGS_ACTIONS` (`EMIT` / `emit`, `RESULT` / `result`, `MISSING` / `missing`).
6
+ - `helpers/get-block-skip-shift` — `getBlockSkipShift(lines, curLine)` moves the cursor past the indent subtree (`indent > parent`). Call sites: `scenario/choose` / `point_and_click` (`*.skip`), `scenario/qte` (fail), `vars` (do not enter the block). Do not confuse it with `getOptionExecShift` (`>=`, skip one option branch).
7
+ - `helpers/get-block-options` — `getBlockOptions(lines, curLine, optionPrefix)` collects `% ….option` at `parentIndent + 2` inside the block → `{ index, optionLine }[]`. Call sites: `scenario/choose` / `point_and_click` / `random` (scenario).
8
+ - `module.controller.arrows.grid` — `cachedItemsCount` does not count slots with `isStub`. After `GRID_UPDATE_ITEMS`, invalid `gridRow` / `gridColumn` (including a stub after a `gridIndex` change) snap to the nearest valid cell. API: `getGridItemsCount`, `snapSelectionToGrid`, `findNearestValidCell`.
9
+ - `views/settings` — a constant for the default-settings tab key. API: `CONST.SETTINGS_VIEW.DEFAULT_TAB` (`"DEFAULT"`).
10
+ - `views.screens/settings` — fields show on `SHOW_BEFORE` in `settings.screen.controller.fields` (`STATE_UPDATE` tabs/tab → `SETTINGS_VIEW.SHOW`). Main only emits `SHOW_BEFORE`, and `HIDE` → `SETTINGS_VIEW.HIDE`.
11
+ - `views.screens/settings.defaults` — fields show on `SHOW_BEFORE` in `settings.default.controller.fields` with `CONST.SETTINGS_VIEW.DEFAULT_TAB`.
12
+ - `module.controller.bg` — the static-background base `@vnejs/module.controller.bg`: `SHOW_BEFORE` → `STATE_UPDATE` `{ bgSrc }`. Optional `EVENT_PRELOAD` / `start` / `STATE.CLEAR`. `MEMORY.CLEARED` uses the preload and/or refresh flags when `isShow`. Abstract: `EVENT_SHOW` / `HIDE` / `SHOW_BEFORE` / `STATE_UPDATE` / `UPDATE_FAST`, `BGNAME`, `QUALITY_SETTING`. API: `IS_START_PRELOAD_ENABLED`, `IS_STATE_CLEAR_PRELOAD_ENABLED`, `IS_MEMORY_CLEARED_PRELOAD_ENABLED`, `IS_MEMORY_CLEARED_UPDATE_ENABLED`, `loadBg`.
13
+ - `views.screens/gallery` — the background moved to `gallery.controller.bg`. Main `beforeShow` emits `SHOW_BEFORE`, then `TAB_SET`. API: `EVENTS.GALLERY.SHOW_BEFORE`.
14
+ - `views.screens/save` — the background is in `save.controller.bg` (`PRELOAD` / `start` / `MEMORY.CLEARED`). Main `beforeShow` → `SHOW_BEFORE` + `TAB_SET`. API: `EVENTS.SAVE_VIEW.SHOW_BEFORE`.
15
+ - `views.screens/settings` — the background is in `settings.screen.controller.bg`. API: `EVENTS.SETTINGS_SCREEN_VIEW.SHOW_BEFORE`, `EVENTS.SETTINGS_SCREEN_VIEW.UPDATE_FAST`.
16
+ - `views.screens/settings.defaults` — the background is in `settings.default.controller.bg`. API: `EVENTS.SETTINGS_DEFAULT_VIEW.SHOW_BEFORE`, `EVENTS.SETTINGS_DEFAULT_VIEW.STATE_UPDATE`, `EVENTS.SETTINGS_DEFAULT_VIEW.UPDATE_FAST`.
17
+ - `views.screens/intro` — the background is in `intro.controller.bg` (`start` preload). API: `EVENTS.INTRO.SHOW_BEFORE`, `EVENTS.INTRO.STATE_UPDATE`, `EVENTS.INTRO.UPDATE_FAST`.
18
+ - `views.screens/loading` — the background is in `loading.controller.bg` (`start` / `MEMORY.CLEARED`). API: `EVENTS.LOADING.SHOW_BEFORE`, `EVENTS.LOADING.STATE_UPDATE`, `EVENTS.LOADING.UPDATE_FAST`.
19
+ - `views.screens/mainmenu` — the initial background is in `mainmenu.controller.bg` (`start` / `STATE.CLEAR`). Rotation stays in `mainmenu.backgrounds`. API: `EVENTS.MAINMENU.SHOW_BEFORE`.
20
+ - `module.controller.tabs` — abstract `EVENT_STATE_UPDATE`. Entrypoint `onTabSetEvent` (guard for an empty or same tab) → `applyTab` (`STATE_UPDATE` `{ tab }`) → abstract `onTabSet` (like `onAccept`). API: `EVENT_STATE_UPDATE`, `applyTab`, `onTabSetEvent`, `onTabSet`.
21
+ - `module.controller.pages` — pagination base `@vnejs/module.controller.pages`: `PAGE_SET` / `PAGE_NEXT` / `PAGE_PREV` → `setPage` → abstract `applyPage` + `UPDATE_FAST`. State `pageIndex` / `pagesCount`. Abstract: `EVENT_PAGE_SET` / `PAGE_NEXT` / `PAGE_PREV` / `STATE_UPDATE` / `UPDATE_FAST`, `applyPage`. API: `setPage`, `onPageSet`, `onPageNext`, `onPagePrev`, `applyPage`.
22
+ - `views.screens/gallery` — `gallery.controller.pages.items` on `PAGE_ITEMS_GET` (`vne:gallery:page_items_get`) builds a UI slot (`CHECK` + media), instead of `ITEM_CREATE` / `vne:gallery:item_create`. Call sites: grid `getGridItems`, preload. API: `EVENTS.GALLERY.PAGE_ITEMS_GET`.
23
+ - `views.screens/gallery` — `gallery.controller.preload`: PRELOAD / `MEMORY.CLEARED` preload tab content through `PAGE_ITEMS_GET`. The background is `gallery.controller.bg`.
24
+ - `views.screens/save` / `views.screens/gallery` — `isDisableGridChangeVertical = true` in `*.controller.grid`. Vertical arrows do not emit `GRID_NEXT` / `PREV` (they do not turn pages). Horizontal arrows still can.
25
+ - `views.screens/save` — `save.controller.actions`: `CREATE` → `SAVE.CREATE`, `DELETE` → `SAVE.DELETE`. `group` comes from the payload or from `getSaveGroup` (autosave / `pageIndex`). Then `GRID_UPDATE_ITEMS` + `UPDATE_FAST`. Main handles SHOW/HIDE/PRELOAD.
26
+ - `views.screens/save` — `save.controller.pages` extends `@vnejs/module.controller.pages`. `EVENT_PAGE_NEXT` / `PREV` = `GRID_NEXT` / `PREV`. `applyPage` → `STATE_UPDATE` `{ gridIndex, gridsCount }` + `GRID_UPDATE_ITEMS`. State `pageIndex` / `pagesCount`. `PAGE_SET` `{ pageIndex }`. `init` writes `pagesCount`. Main handles SHOW/HIDE/PRELOAD. API: `EVENTS.SAVE_VIEW.PAGE_SET` payload `{ pageIndex }`.
27
+ - `views.screens/save` — `TAB_SET` is handled by `save.controller.tabs` (`pageIndex: 0`, `GRID_CLEAR`, `STATE_UPDATE` `{ gridIndex, gridsCount }`, `GRID_UPDATE_ITEMS`, and optional `UPDATE_FAST`). `beforeShow` emits `TAB_SET` with `isForce` / `isUpdateView: false`.
28
+ - `views.screens/gallery` — `gallery.controller.pages` extends `@vnejs/module.controller.pages`. `EVENT_PAGE_NEXT` / `PREV` = `GRID_NEXT` / `PREV`. `applyPage` → `STATE_UPDATE` `{ gridIndex, gridsCount }` + `GRID_UPDATE_ITEMS` + `MEMORY.CLEAR`. State `pageIndex` / `pagesCount` (was `currentPage` / `pages`). `PAGE_SET` `{ pageIndex }`. Tabs write `pagesCount` on `TAB_SET`. Main handles SHOW/HIDE/PRELOAD. API: `EVENTS.GALLERY.PAGE_SET` payload `{ pageIndex }`.
29
+ - `views.screens/gallery` — `gallery.controller.grid` is on `@vnejs/module.controller.arrows.grid`. State `gridRow` / `gridColumn` / `gridItems` (was `current*`). `TAB_SET` in tabs: `GRID_CLEAR` + `STATE_UPDATE` `{ gridIndex, gridsCount }` + `GRID_UPDATE_ITEMS` + optional `UPDATE_FAST`. `MEMORY.CLEAR` / `UPDATE_FAST` run only when `isUpdateView` (not in `beforeShow`), so SHOW does not fall under `viewForceAnimationSources`. API: `EVENTS.GALLERY.UPDATE_FAST`, `EVENTS.GALLERY.GRID_NEXT`, `EVENTS.GALLERY.GRID_PREV`, `EVENTS.GALLERY.GRID_CLEAR`, `EVENTS.GALLERY.GRID_UPDATE_ITEMS`, `EVENTS.GALLERY.PAGE_ITEMS_GET`.
30
+ - `views.screens/settings` — `TAB_SET` is in `settings.screen.controller.tabs` (`applyTab` + `SETTINGS_VIEW.TAB_SET` + `UPDATE_FAST`). Main on `STATE_UPDATE` only calls `updateState`. API: `EVENTS.SETTINGS_SCREEN_VIEW.STATE_UPDATE`.
31
+ - `module.controller.arrows.grid` — grid-navigation base `@vnejs/module.controller.arrows.grid`: four arrows, PUSH/POP on SHOW/HIDE, `STATE_UPDATE` `{ gridRow, gridColumn }` + `UPDATE_FAST`, `GRID_NEXT` / `GRID_PREV` at the edge, reset through `GRID_CLEAR` (`gridRow` / `gridColumn` → `null` + `STATE_UPDATE`). Abstract: `EVENT_SHOW` / `HIDE` / `STATE_UPDATE` / `UPDATE_FAST` / `GRID_NEXT` / `GRID_PREV` / `GRID_CLEAR`, `CONTROLS_ZINDEX`, `getMaxRows` / `getMaxColumns`. `STATE_UPDATE` mirrors state (`updateState`) and the cache. `GRID_UPDATE_ITEMS` has no payload → `getGridItems` from state → `STATE_UPDATE` `{ gridItems }`. Flags `isDisableGridChangeHorizontal` / `isDisableGridChangeVertical` (default `false`).
32
+ - `views.screens/save` — `save.controller.grid` extends `@vnejs/module.controller.arrows.grid`. Inside the grid, `STATE_UPDATE` carries `{ gridRow, gridColumn }` and `UPDATE_FAST`. At the edge, `GRID_NEXT` / `GRID_PREV` (`save.controller.pages` maps them to pagination). A tab change is `EVENTS.SAVE_VIEW.GRID_CLEAR`. Grid meta is `STATE_UPDATE` (`gridIndex` / `gridsCount` / `tab`). `GRID_UPDATE_ITEMS` has no payload. Slots load in `getGridItems` through `emitOne(EVENTS.SAVE_VIEW.SLOT_CREATE)`. The module `save.view.slot` on `SLOT_CREATE` (`{ key, group, index }`) → `SAVE.GET` plus date and time. API: `EVENTS.SAVE_VIEW.UPDATE_FAST`, `EVENTS.SAVE_VIEW.GRID_NEXT`, `EVENTS.SAVE_VIEW.GRID_PREV`, `EVENTS.SAVE_VIEW.GRID_CLEAR`, `EVENTS.SAVE_VIEW.GRID_UPDATE_ITEMS`, `EVENTS.SAVE_VIEW.SLOT_CREATE`.
33
+ - `module.controller.tabs` / `views.screens/settings` / `views.screens/gallery` — the tab field in state is `tab`, not `currentTab`.
@@ -0,0 +1,10 @@
1
+ # 0.2.36
2
+
3
+ - `views.screens/checkers` — a Russian-checkers screen: `$ checkers show`, a grid on `@vnejs/module.controller.arrows.grid`. API: `EVENTS.CHECKERS.*` (`SHOW` / `HIDE` / `ACCEPT` / `CELL_CLICK` / `FINISH` / `AI_TURN` / grid), `PARAMS.CHECKERS.ROWS` / `COLUMNS`, `CONST.CHECKERS.EXEC_ACTIONS`.
4
+ - `views.screens/checkers` — side AI: `$ checkers ai <white|black> <player|sacrifice|random|strong>`. The config lives in `shared.checkersAi` (default both `player`) and is copied into state `ai` on SHOW. AI vs AI starts after the board is ready. `playMove` always looks up a move through `getAllMoves` (an empty `legalMoves: []` no longer blocks the AI). The pause before an AI move is `PARAMS.CHECKERS.AI_DELAY` (1000 ms). API: `CONST.CHECKERS.AI_COLORS`, `CONST.CHECKERS.AI_TYPES`, `EVENTS.CHECKERS.AI_TURN`, `PARAMS.CHECKERS.AI_DELAY`, `shared.checkersAi`, `shared.checkersAiBusy`.
5
+ - `views.screens/checkers` — board cells use `vne-cursor-type="pointer"` instead of a CSS `cursor`.
6
+ - `views.screens/checkers` — the board is a CSS grid 8×8. Cell size comes from `getVneLength(PARAMS.CHECKERS.CELL_SIZE)`, with no flex-wrap (before, cells were in px and a row broke at about 6).
7
+ - `views.screens/checkers` — animations `PARAMS.CHECKERS.TRANSITION` (300 ms): a piece move (`transform`), a selection (opacity 70%), a capture that slides to the graveyard (white on the left, black on the right; `PARAMS.CHECKERS.GRAVEYARD_GAP`), and a cell color change. Positions are `calc(n * cellLen)`. The overlay is outside the grid children.
8
+ - `bundles/checkers` — the bundle: core + `canvas.layer` + controls/keyboard/gamepad/cursor + `text` + choose + `views.cursor` + gamepad↔cursor + `views.screens/checkers`.
9
+ - `games/checkers` — a test game: two `% choose` with `title` (white/black) and the options «Игрок» / «… ИИ» → `$ checkers show`. The cursor comes from Coraline (`icons/original-4k/cursor/default`). Scripts `resize:*` / `build:media:cp` / vercel-target match Coraline.
10
+ - `views.scenario/choose` — an optional title from `args.title` (`title: "…"` on `% choose`). API: `PARAMS.CHOOSE_VIEW.VIEW_PROPS.title` / `wrap`.
@@ -0,0 +1,19 @@
1
+ # 0.2.38
2
+
3
+ - `ai/checkers` — algorithm keys use a domain prefix: `CONST.CHECKERS_AI.AI_TYPES` → `checkers:sacrifice` / `checkers:random` / `checkers:strong` (was `sacrifice` / `random` / `strong`). `$ checkers.ai set <color> checkers:strong`.
4
+ - `ai/checkers` — the default algorithms `checkers:sacrifice` / `checkers:random` / `checkers:strong` register in `PARAMS.AI.ALGORITHMS` when the contract loads (a side effect, like `SCALE_MANA` → `PARAMS.SCALES.TYPES`). They are no longer set in `games/checkers` scripts. API: export `CheckersAiArgs`, `sacrifice` / `random` / `strong`.
5
+ - `ai/checkers` — checkers AI orchestration moved out of `game/checkers` into `@vnejs/plugins.ai.checkers` (`PLUGIN_NAME` `CHECKERS_AI`). API: `EVENTS.CHECKERS_AI.INTERACT` / `SET` / `UNSET` (`vne:checkers_ai:*`); `CONST.CHECKERS_AI.SOURCE` (`"checkers.ai.interact"`); `CONST.CHECKERS_AI.EXEC_ACTIONS` / `AI_TYPES`; `PARAMS.CHECKERS_AI.AI_DELAY`; `shared.checkersAi`; modules `checkers.ai` / `checkers.ai.start` / `checkers.ai.interact` / `checkers.ai.move.played`. Replaces `EVENTS.CHECKERS.AI_INTERACT` / `AI_SET` / `AI_UNSET`, `PARAMS.CHECKERS.AI_DELAY`, `CONST.CHECKERS.AI_EXEC_ACTIONS` / `AI_TYPES`, and the modules `checkers.ai.show` / `checkers.move.played`. `$ checkers.ai` keeps the same syntax. Bundle: `@vnejs/plugins.ai.checkers`.
6
+ - `game/checkers` — only the rules, the board, the moves, and `$ checkers`. The colors `AI_COLORS` / `AI_COLOR_VALUES` and `shared.checkersInteractDisableSources` stay here.
7
+ - `game/checkers` — `BOARD_CHANGE` / `BOARD_CHANGED` / `BOARD_GET` no longer carry `ai`. Side config lives only in `shared.checkersAi` (`AI_SET` / `AI_UNSET`).
8
+ - `views.screens/checkers` — ACCEPT no longer emits `CHECKERS.FINISH` (it only selects a cell).
9
+ - `game/checkers` — `PARAMS.CHECKERS.FINISH_DELAY` replaces `TRANSITION` for the pause on `FINISH`.
10
+ - `views.screens/checkers` — `EVENTS.CHECKERS_VIEW.PLAYER_SELECT` / `CheckersPlayerSelectPayload`. Module `checkers_view.player.select` (was `patchSelection`).
11
+ - `game/checkers` — `MOVE_PLAY` itself emits `MOVE_PLAYED` `{ move, … }`, or `FINISH` on a win. Call sites no longer emit `MOVE_PLAYED` by hand. API: `CheckersMovePlayPayload` = `CheckersMovePlayedPayload` + `move`.
12
+ - `views.screens/checkers` — `statusText` lives only in the view (from `turn` / `winner` on `BOARD_CHANGED`). The game model has no `statusText`.
13
+ - `game/checkers` / `views.screens/checkers` — `selected` / `legalMoves` live only in the view (`CHECKERS_VIEW.STATE_UPDATE`). `BOARD_CHANGE` / `BOARD_CHANGED` do not carry them.
14
+ - `game/checkers` — rules, AI, and `$ checkers` moved out of `views.screens/checkers` into `@vnejs/plugins.game.checkers` (`PLUGIN_NAME` `CHECKERS`). API: `EVENTS.CHECKERS.BOARD_CHANGED` / `BOARD_GET`; `PARAMS.CHECKERS.TRANSITION` (settle on `FINISH`); the board is inited on `SHOW` (`checkers.show`) → `START`. `PLAYER_INTERACT` is gone from game.
15
+ - `views.screens/checkers` — UI only: `PLUGIN_NAME` `CHECKERS_VIEW`. Events `vne:checkers_view:*`. `EVENTS.CHECKERS_VIEW.PLAYER_INTERACT` / `CLICK` / grid. Bridge SHOW/HIDE. Mirror `BOARD_CHANGED` → grid. `player.interact` talks to the game through `MOVES_GET` / `MOVE_PLAY` / `BOARD_CHANGE`.
16
+ - `bundles/checkers` — import `@vnejs/plugins.game.checkers` + `@vnejs/plugins.views.screens.checkers`.
17
+ - `ai/ai` — dispatcher: `emitOne(EVENTS.AI.EMIT, { type, args })` → `PARAMS.AI.ALGORITHMS[type](args, module)`. The default `PARAMS.AI.ALGORITHMS` is `{}`. API: `EVENTS.AI.EMIT`, `PARAMS.AI.ALGORITHMS`, `CONST.AI.PLAYER_TYPE` (`"player"`), types `AiAlgorithm` / `AiAlgorithmContext` / `AiEmitPayload` (`type` instead of `id`).
18
+ - `views.screens/checkers` — (before the split) `EVENTS.CHECKERS.MOVES_GET` / `MOVE_PLAY` / `MOVE_PLAYED` / `BOARD_CHANGE` / `PLAYER_INTERACT` / `AI_SET` / `AI_UNSET` / `AI_INTERACT` / `START`; `CONST.CHECKERS.AI_COLOR_VALUES` / `AI_EXEC_ACTIONS` / `EXEC_ACTIONS` (`show` / `hide`); modules `checkers.board`, `checkers.moves`, `checkers.move.play`, `checkers.move.played`, `checkers.player.interact`, `checkers.ai`, `checkers.ai.interact`, `checkers.ai.show`, `checkers.click`, `checkers.finish`, `checkers.controller.accept`. Algorithms lived in `games/checkers`. `$ checkers.ai set|unset` replaced `$ checkers ai`. `$ checkers show` has no `emitNext` (the scenario waits for `FINISH`). `$ checkers hide` → `HIDE` + `emitNext`. `FINISH` does not `HIDE`. Removed the local `utils/ai` / `pickMove`. API: `EVENTS.CHECKERS.PLAYER_INTERACT`, `CheckersPlayerInteractPayload`; `EVENTS.CHECKERS.CLICK` instead of `CELL_CLICK` (`vne:checkers:click`) → `GRID_CLEAR` + `PLAYER_INTERACT`; `EVENTS.CHECKERS.AI_SET` / `CheckersAiSetPayload`; `EVENTS.CHECKERS.AI_UNSET` / `CheckersAiUnsetPayload` (`color`); `$ checkers.ai unset <color>` → the side becomes `CONST.AI.PLAYER_TYPE`; `CONST.CHECKERS.AI_EXEC_ACTIONS` (`set` / `unset`); `CONST.AI.PLAYER_TYPE` instead of `CONST.CHECKERS.AI_TYPES.PLAYER`; `EVENTS.CHECKERS.START` (`afterShow`) → `AI_INTERACT` (`checkers.ai.show`); `EVENTS.CHECKERS.AI_INTERACT` instead of `AI_TURN`; `EVENTS.CHECKERS.MOVE_PLAYED` / `CheckersMovePlayedPayload` (`controllerType`); after a move, `MOVE_PLAY` / `AI.EMIT` → `MOVE_PLAYED` → `AI_INTERACT` (`checkers.move.played`); `shared.checkersInteractDisableSources` (`SourcesSet`) instead of `checkersAiBusy` (source = `this.name` on `checkers.ai.interact`); the `AI.EMIT` call uses `{ type, args }`.
19
+ - `bundles/checkers` — imports `@vnejs/plugins.ai`.
@@ -0,0 +1,16 @@
1
+ # 0.2.39
2
+
3
+ - `game/checkers` — presets `FLIPPED` (white on top / black on the bottom, all kings) and `RANDOM` (12+12 on random dark cells; each `SHOW` gets a new layout). API: `PARAMS.CHECKERS.PRESETS.FLIPPED` / `RANDOM`, `createFlippedPreset`, `createRandomPreset`.
4
+ - `games/checkers` — `% choose` «Партия»: 6 options (COMMON / FLIPPED / RANDOM × white or black moves first) → `$ checkers show` with args.
5
+ - `game/checkers` — `$ checkers show` reads `initialOwner` / `initialPreset` from indent args (`initialOwner: black`, `initialPreset: COMMON`), not from positional tokens.
6
+ - `game/checkers` — `PARAMS.CHECKERS.PRESETS` (`COMMON` = the standard start). `SHOW.initialPreset` → cells from the preset (missing or unknown → `COMMON`). API: `PARAMS.CHECKERS.PRESETS`, `CheckersShowPayload.initialPreset`, `createCommonPreset`.
7
+ - `game/checkers` — `EVENTS.CHECKERS.SHOW` payload `CheckersShowPayload` `{ initialOwner?, initialPreset? }`. A missing or invalid `initialOwner` means white. API: `CheckersShowPayload`.
8
+ - `game/checkers` — `EVENTS.CHECKERS.SET` / `UNSET` (`vne:checkers:set` / `unset`): `{ cells, owner }` → `GRID.SET` + `TURNS.SET` (id / rows / columns from `GRID_ID` / `TURN_ID` / `PARAMS`). `UNSET` → `GRID.UNSET` + `TURNS.UNSET`. Module `checkers.set`. Call sites: `SHOW` / `MOVE_PLAY` → `SET`, `HIDE` → `UNSET`.
9
+ - `common/grid` — square-grid plugin `@vnejs/plugins.common.grid` (`PLUGIN_NAME` `GRID`). API: `EVENTS.GRID.SET` / `GET` / `UNSET` / `CHANGED` / `PUT` / `MOVE` / `REMOVE` (`vne:grid:*`). An element is an object with `id`. State is a map `id → { rows, columns, cells }` (a dense `(item | null)[][]`). `STATE.SET` / `CLEAR` diff through `SET` / `UNSET`.
10
+ - `game/checkers` — the board goes through `GRID.*` instead of `BOARD_CHANGE` / `BOARD_CHANGED` / `BOARD_GET`. The module `checkers.board` is removed. API: `CONST.CHECKERS.GRID_ID` (`"checkers"`). `SHOW` → `GRID.SET` + `TURNS.SET`. `HIDE` → `GRID.UNSET` + `TURNS.UNSET`. `MOVE_PLAY` reads `GRID.GET` and writes `GRID.SET`.
11
+ - `views.screens/checkers` / `ai/checkers` — `board` comes from `GRID.CHANGED` / `UNSET` (`cells`, filter `GRID_ID`).
12
+ - `bundles/checkers` — import `@vnejs/plugins.common.grid`.
13
+ - `common/turn` — turn plugin `@vnejs/plugins.common.turn` (`PLUGIN_NAME` `TURNS`). API: `EVENTS.TURNS.SET` / `GET` / `UNSET` / `CHANGED` (`vne:turns:*`). Payload `{ id, owner }` (`UNSET` is `{ id }`). State is a map `id → owner` (parallel games). `STATE.SET` / `CLEAR` diff the map through `SET` / `UNSET`.
14
+ - `game/checkers` — `turn` / `winner` are removed from state and from `BOARD_CHANGE` / `BOARD_CHANGED` / `BOARD_GET`. The turn goes through `TURNS.*`. A win goes through `FINISH` `{ winner }` (`CheckersFinishPayload`). API: `CONST.CHECKERS.TURN_ID` (`"checkers"`). `CONST.CHECKERS.COLORS` / `COLOR_VALUES` (were `AI_COLORS` / `AI_COLOR_VALUES`). Type `CheckersColor` (was `CheckersAiColor`).
15
+ - `views.screens/checkers` / `ai/checkers` — `turn` comes from `TURNS.CHANGED` / `UNSET`. `winner` comes from `CHECKERS.FINISH` and resets on `SHOW`. `BOARD_CHANGED` / `STATE_UPDATE` carry only `board`. View: `checkers_view.status` (status text).
16
+ - `bundles/checkers` — import `@vnejs/plugins.common.turn`.
@@ -0,0 +1,9 @@
1
+ # 0.2.40
2
+
3
+ - `canvas/layer` — quality `90p` (`CONST.LAYER.QUALITIES.nnHD`, 160×90). `360p` (`nHD`) was already there. API: `QUALITIES.nnHD`, `SCREEN_SIZES["90p"]`.
4
+ - `games/coraline` — the screen-quality selector (WEB): `90p` / `360p` / `720p` / `1080p` / `1440p` / `2160p` (6 items, `optionsWidthModifier: 3`).
5
+ - `cli/tools` resize image/video — `90p` / `1440p` when the target is `all` (and `90` / `1440`). `360p` for `all` / `mobile` / `360`. The old 720/1080/2160 stay.
6
+ - `uis.react` Cursor — the default `size` is 180 (was 120). The default `transition` is 300 (was 500).
7
+ - `scenario/point_and_click` — `% point-and-click.option {icon} {iconHover} x y` (the hover icon is required). Optional args `imgWidth` / `imgHeight` (canvas px). API: `PointAndClickOption.iconHover`, `imgWidth`, `imgHeight`.
8
+ - `views.scenario/point_and_click` — loads `iconHoverSrc`. Hover swaps the hotspot. Size comes from `imgWidth` / `imgHeight`. `PARAMS.POINT_AND_CLICK_VIEW.TRANSITION` (300) → `Image.transition` for the hover animation.
9
+ - `uis.react` Image — prop `srcHover` (CSS swap on `[vne-cursor-target]`, same as Icon).
@@ -0,0 +1,3 @@
1
+ # 0.2.42
2
+
3
+ - `cli/tools` resize image — flag `-d` / `--desktop` (webp quality 90). `--web` → 80. No flags → 100. API: `--desktop`.
@@ -0,0 +1,10 @@
1
+ # 0.2.43
2
+
3
+ - `core/stack` — `STACK.EMIT` (`$ stack jump` / `call`) waits for `MEMORY.CLEAR` to finish before it returns, so the first line of the new label does not race `CLEARED`.
4
+ - `canvas/bg` — `$ <layer>.bg change … <duration>`: `transition` → `waitRerender` → change `src` (same as `sprite.move`). A bg `Image` has `isSwitchDisabled` (overlays are not a slideshow).
5
+ - `uis.react` Image — `transition` works like Cursor (`background-image` + `opacity`). The switcher does not advance frames without `duration`, and not when `isAllSrcRendered`. `isAllSrcRendered` writes layers into `--vne-image-src`, not into an inline `backgroundImage`.
6
+ - `module.layer` — `updateChildren` waits for `updateStateAndViewFast` before `waitTimeout`.
7
+ - `save/quick` — the quick-save slot (`SAVE_QUICK`): `MAKE` / `LOAD` / `PRELOAD`. `CONST.SAVE_QUICK.SAVE_GROUP` (`"quick"`). `shared.hasQuickSave`.
8
+ - `views.screens/gamemenu` — items come from `GameMenuItemFactory[]`. `EVENTS.GAMEMENU.ITEMS`. `isDisabled` / `isHided` (was `disabled` / `hided`). API: `GameMenuItemFactory`, `EVENTS.GAMEMENU.ITEMS`, `GameMenuItem.isDisabled` / `isHided`.
9
+ - `views.screens/settings.defaults` — hover on the Accept button: `PARAMS.SETTINGS_DEFAULT_VIEW.VIEW_PROPS.accept.isHoverable` (`true`).
10
+ - `views.screens/settings` — on `TAB_SET`, `UPDATE_FAST` runs first (chrome), then `SETTINGS_VIEW.TAB_SET` (content).
@@ -0,0 +1,3 @@
1
+ # 0.2.46
2
+
3
+ - `uis.react` Cursor — `vne-cursor-target` is set or cleared only on elements whose set under the cursor actually changed.
@@ -0,0 +1,25 @@
1
+ # 0.2.47
2
+
3
+ - `views.screens/save` — `SLOT_CREATE` result: `SaveViewSlotCreateResult` (in contracts). `views.screens/confirm` — `onAccept` / `onDecline`: `() => unknown`.
4
+ - `views/*`, `views.scenario/*`, `views.screens/*` plugins — local `*PluginState` types moved from `utils` into the plugin `types.ts`.
5
+ - `canvas/*` contracts (`bg`, `bg.speak`, `fill`, `layer`, `sprite`, `sprite.speak`, `text`, `video`) — `VneEventPayloadMap` + `VneEventResultMap` on every `SUBSCRIBE_EVENTS`. Payload and result types live in contracts (promoted from plugins / `module.layer`). API: payload/result types on the events `LAYER_BG`, `LAYER_BG_SPEAK`, `LAYER_FILL`, `LAYER`, `LAYER_SPRITE`, `LAYER_SPRITE_SPEAK`, `LAYER_TEXT`, `LAYER_VIDEO`; `LayerChildRmPayload.duration`, `SpriteSrcGetPayload.mediaType`, `SpritePreloadPayload.priority` (`number | string`).
6
+ - `canvas.layers/*` (`bl`, `fl`, `ml`, `ul`) — `VneEventPayloadMap` + `VneEventResultMap` on `UPDATE`. API: payload/result types on the events `LAYER_BL`, `LAYER_FL`, `LAYER_ML`, `LAYER_UL`.
7
+ - `canvas.props/*` (`animation`, `clip`, `filter`, `mask`, `scale`) — `VneEventPayloadMap` + `VneEventResultMap` on every `SUBSCRIBE_EVENTS`. Payload types live in contracts. API: payload/result types on the events `LAYER_ANIMATION`, `LAYER_CLIP`, `LAYER_FILTER`, `LAYER_MASK`, `LAYER_SCALE`.
8
+ - `views/*`, `views.scenario/*`, `views.screens/*` contracts — `VneEventPayloadMap` + `VneEventResultMap` on every `SUBSCRIBE_EVENTS`. Payload and result types live in contracts (promoted from plugins; local `*PluginState` stays in the plugin `types.ts`). API: payload/result types on the events of views / views.scenario / views.screens. Cursor has no `SUBSCRIBE_EVENTS`, so it has no maps.
9
+ - `audio/audio`, `controls/controls`, `controls/cursor`, `controls/gamepad`, `save/save`, `save/auto`, `save/continue`, `save/quick`, `scales/scales`, `common/grid`, `common/turn`, `platform/electron`, `platform/metric`, `entities/wallet` — `VneEventPayloadMap` + `VneEventResultMap` on every `SUBSCRIBE_EVENTS`. Payload and result types live in contracts (promoted from plugins where needed). API: payload/result types on the events `AUDIO`, `CONTROLS`, `CURSOR`, `GAMEPAD`, `SAVE`, `SAVE_AUTO`, `SAVE_CONTINUE`, `SAVE_QUICK`, `SCALES`, `GRID`, `TURNS`, `ELECTRON`, `METRIC`, `WALLET`.
10
+ - `ai/ai`, `ai/checkers`, `game/checkers`, `rpg/damage`, `rpg/hit`, `rpg/skills` — `VneEventPayloadMap` + `VneEventResultMap` on every `SUBSCRIBE_EVENTS`. Payload and result types live in contracts (`payloads.ts`). API: payload/result types on the events `AI`, `CHECKERS_AI`, `CHECKERS`, `DAMAGE`, `HIT`, `SKILLS` (including `SkillsCheckPayload`, `CheckersStateUpdatePayload`).
11
+ - `scenario/choose`, `scenario/point_and_click` — `ChooseOptionLine` / `PointAndClickOptionLine` = `ScenarioLineObj` (`@vnejs/contracts.core.scenario`). Removed the casts on `SCENARIO.LINES_GET`.
12
+ - `vars/flags` — `GET` / `EXEC_GET` result: `boolean | undefined` (was `boolean`). The `GET` handler normalizes `VARS.GET`.
13
+ - `vars/counters` — `EXEC_CHECK` result: `boolean | undefined`. `GET` normalizes `VARS.GET` → `number | undefined`.
14
+ - `vars/vars`, `vars/flags`, `vars/counters`, `time/time`, `time/date`, `settings/potato` — `VneEventPayloadMap` + `VneEventResultMap` on `SUBSCRIBE_EVENTS`. Payload and result types live in contracts (flags/counters promoted from plugins). API: payload/result types on the events `VARS`, `VARS_FLAGS`, `VARS_COUNTERS`, `TIME`, `DATE`, `POTATO`.
15
+ - `text/*` contracts (`text`, `locs`, `inject`, `wall`, `smooth`, `meet`) — `VneEventPayloadMap` + `VneEventResultMap` on every `SUBSCRIBE_EVENTS`. Payload and result types live in contracts (promoted from plugins). API: payload/result types on the events `TEXT`, `LOCS`, `TEXT_INJECT`, `TEXT_WALL`, `TEXT_SMOOTH`, `TEXT_MEET`.
16
+ - `module.handlers` — `EmitHandler` return: `void | Promise<unknown>` (was `Promise<void>`), so a handler can `return this.emit(...)`. API: `EmitHandler`.
17
+ - `scenario/*` contracts (except `random`) — `VneEventPayloadMap` + `VneEventResultMap` on every `SUBSCRIBE_EVENTS`. Payload and result types live in contracts. API: payload/result types on the events `CHOOSE`, `POINT_AND_CLICK`, `QTE`, `PAUSE`, `AUTOREAD`, `HISTORY`, `FASTFORWARD`.
18
+ - plugin `utils` — removed contract type re-exports (`export type { … } from "@vnejs/contracts…"`). Import payload and handler types from the matching `@vnejs/contracts.*` package (aliases such as `LogQueueItem` / `ExecDelayPayload` / `FileLoadPayload` / `MigrateHandler` → contract names `LogsEmitPayload` / `ScenarioExecDelayPayload` / `SystemFileLoadPayload` / `StateMigrateHandler`).
19
+ - `shared` / `observer` / `module` — typed `emit` / `on` through `VneEventPayloadMap` (contracts augment an event string → payload). API: `VneEventPayloadMap`, `EmitArgs`, `HandlerArgs`.
20
+ - `shared` / `observer` / `module` — typed `emit*` return through `VneEventResultMap` (contracts augment an event string → handler result). API: `VneEventResultMap`, `EmitResult`, `EmitResults`.
21
+ - `shared` — `EmitArgs`: the payload argument is optional when the payload type is empty-object-compatible (`{} extends Payload`). `HandlerArgs` stays `unknown[]` (handlers are not narrowed through the map).
22
+ - `core/*` contracts (except `platforms`) — `VneEventPayloadMap` + `VneEventResultMap` on every `SUBSCRIBE_EVENTS`. Payload and result types live in contracts (promoted from plugins). API: payload/result types on the events `SYSTEM`, `MEMORY`, `STACK`, `SCENARIO`, `VENDORS`, `STORAGE`, `COMPONENTS`, `MEDIA`, `INTERACT`, `LOGS`, `SETTINGS`, `STATE`.
23
+ - `core/state` — migrate/load state uses `ModuleGlobalState` (was a separate `StateMigrateState`).
24
+ - `core/system` — `ModuleGlobalState["system.version"]` (`ModuleGlobalStateSystemVersion`: `major`, `minor`).
25
+ - `module` — `getStateSlice` always returns `TState` (`payload[name] as TState`). API: `getStateSlice(payload): TState`.
@@ -0,0 +1,3 @@
1
+ # 0.2.49
2
+
3
+ - `cli/monorepo` — when `run-changed` / `publish` fails, the error shows the package, the path, and the exit code (and `!!!` on stderr for `publish`), not only `N package script(s) failed`.
@@ -0,0 +1,6 @@
1
+ # 0.2.50
2
+
3
+ - `observer` — `SubscriberOptions.priority` (default `0`). Handler groups are built in `subscribe`. `emit` walks them by rising priority (inside a group, in parallel). Answers come from every group. API: `SubscriberOptions.priority`, `SubscriberGroup`.
4
+ - `module.handlers` — the package `@vnejs/module.handlers` / `ModuleHandlers` is removed. Instead of `*_REG`, use `on(event, handler, { priority })`.
5
+ - `text/text` — removed `EMIT_BEFORE_REG` / `EMIT_NEXT_REG` and the module `text.emit.before`. Subscribe to `EMIT_BEFORE` / `EMIT_NEXT` with `priority`. API: removed `EVENTS.TEXT.EMIT_BEFORE_REG`, `EVENTS.TEXT.EMIT_NEXT_REG`.
6
+ - `scenario/choose` — removed `OPTION_BEFORE_REG` and the module `choose.option.before`. Subscribe to `OPTION_BEFORE` with `priority`. API: removed `EVENTS.CHOOSE.OPTION_BEFORE_REG`.
@@ -0,0 +1,6 @@
1
+ # 0.2.51
2
+
3
+ - `observer` / `module` — `Observer.emit(event, payload, params)` replaces rest-args. `Module.emit(event, payload?)` builds `params = { module: this.name }` itself. API: `EmitParams`, `EmitPayload`.
4
+ - `core/scenario` — the `NEXT` payload is `void`. The caller module name is in `EmitParams` (through `Module.emit`). API: `ScenarioNextPayload` → `void`.
5
+ - `module.core` — removed `emitNext`. Use `emit(EVENTS.SCENARIO.NEXT)` instead. API: removed `ModuleCore.emitNext`.
6
+ - `text/text` — on `EMIT_NEXT`, the scenario advances in `text.emit.next` through `onTextEmitNext` → `EVENTS.SCENARIO.NEXT`.
@@ -0,0 +1,5 @@
1
+ # 0.2.52
2
+
3
+ - `core/logs` — `LogsEmitPayload` = `LogsValue` plus an optional `level` (no `value` wrapper). There is no `module` in the payload (the emitter name comes from `EmitParams`). API: `LogsValue`, `LogsEmitPayload`, `LogsPushPayload.log`.
4
+ - `module.core` — removed `emitLog`. Log through `emit(EVENTS.LOGS.EMIT, { action, … })`. API: removed `ModuleCore.emitLog`.
5
+ - Plugins that log — `action` comes only from `CONST.*.LOGS_ACTIONS` (the legacy `type` is gone on stack/components/save/random). `LOGS_ACTIONS` were extended or added on scenario, components, system, skills, storage, intro, loading, meet, ratio, random, disclaimer.
@@ -0,0 +1,12 @@
1
+ # 0.2.53
2
+
3
+ - `module.controller.hide.on.controls`, `module.controller.accept`, `module.controller.arrows.*` — PUSH/POP controls only when the local `isShow` changes (as on `ModuleController`), with no extra POP on HIDE before SHOW.
4
+ - `controls/controls` — the EMIT lock flag is `shared.isControlsLocked` (created in `controls.postinject`). On `CONTROLS.EMIT` the console prints the `keys` list.
5
+ - `controls/cursor` — a DOM click from a touch emits `CURSOR.HIDE` (the click itself has `pointerType === "touch"`, or the click follows a touch `pointerdown`, or `sourceCapabilities.firesTouchEvents`).
6
+ - `uis.react` — `vne-cursor-target` is set only on nodes that have `vne-cursor-target-possible` (the same moment as a non-empty `vne-cursor-type`). API: `vne-cursor-target-possible`.
7
+ - `views.screens/checkers` — board cells are marked `vne-cursor-target-possible`.
8
+ - `views.scenario/qte` — the default UI is a horizontal line and a marker that moves left to right, not a circle. The QTE rail has `vne-cursor-target-possible`. Auto-fail happens only at the end of `duration`, not when the marker leaves the zone. The `intro` / `outro` phases are gone. Show and hide go only through `Screen` (`TRANSITION`). The scenario API `start` / `size` / `duration` is unchanged.
9
+ - `module` — `setStateFromGlobalState` → `setClonedState`: `setState(structuredClone(getStateSlice(payload)))`. `getStateSlice`: no slice in the payload → `getDefaultState()` (empty modules are cut out of the save). API: `setClonedState`, `getStateSlice`.
10
+ - `module.core` — removed `onSetStateClone`. Use `setClonedState` instead. Removed `emitClone`. Use `structuredClone` instead. Removed `emitInteractPushPop`. Use `emit(EVENTS.INTERACT.PUSH_POP, …)` instead. API: removed `ModuleCore.onSetStateClone`, `ModuleCore.emitClone`, `ModuleCore.emitInteractPushPop`.
11
+ - `core/logs` — extra `LogsValue` fields are `LogsCloneable` (strings, numbers, boolean, bigint, null, arrays, plain objects), not `unknown`. API: `LogsCloneable`, `LogsValue`.
12
+ - `core/vendors` — removed the `CLONE` event and the `vendors` module (lodash `cloneDeep`). API: removed `EVENTS.VENDORS.CLONE`.
@@ -0,0 +1,19 @@
1
+ # 0.2.55
2
+
3
+ - `observer` — `SubscriberOptions.breakFollowing`: a truthy handler result does not run the next priority groups. API: `SubscriberOptions.breakFollowing`.
4
+ - `core/components`, `module.components` — the `SETUP` phase is renamed to `GATE`. On `GATE` the controller returns `state.isShow` (`SHOW`) or `!state.isShow` (`HIDE`) and, with `breakFollowing`, stops the other phases when the cycle has not started. The `SHOW` / `HIDE` log is written on `BEFORE`. Removed `showCycle` and `hideCycle`. API: `CONST.COMPONENTS.LIFECYCLE_PRIORITY.SHOW.GATE`, `CONST.COMPONENTS.LIFECYCLE_PRIORITY.HIDE.GATE`. Removed `ModuleController.showCycle`, `ModuleController.hideCycle`.
5
+ - `module.components` — `ModuleController` no longer stores or calls `onClose` from the `SHOW` payload. API: removed `ModuleController.onClose`, `ViewActionPayload.onClose`.
6
+ - `views/comment`, `views.screens/confirm` — the auto-hide timer and the accept/decline callbacks are cleared on `HIDE.MAIN`. If the controller stopped `HIDE` on `GATE`, the cleanup does not run. `COMMENT.SHOW` and `CONFIRM.SHOW` no longer receive `onClose`.
7
+ - `module.components` — `ModuleController.EVENT_SHOW` and `ModuleController.EVENT_HIDE` are required. The SHOW/HIDE lifecycle always subscribes. API: `ModuleController.EVENT_SHOW`, `ModuleController.EVENT_HIDE`.
8
+ - `views/achievement`, `views/controls.hints`, `canvas.layers/bl`, `canvas.layers/fl`, `canvas.layers/ml`, `canvas.layers/ul` — added `SHOW` / `HIDE`. API: `EVENTS.ACHIEVEMENT.SHOW`, `EVENTS.ACHIEVEMENT.HIDE`, `EVENTS.CONTROLS_HINTS.SHOW`, `EVENTS.CONTROLS_HINTS.HIDE`, `EVENTS.LAYER_BL.SHOW`, `EVENTS.LAYER_BL.HIDE`, `EVENTS.LAYER_FL.SHOW`, `EVENTS.LAYER_FL.HIDE`, `EVENTS.LAYER_ML.SHOW`, `EVENTS.LAYER_ML.HIDE`, `EVENTS.LAYER_UL.SHOW`, `EVENTS.LAYER_UL.HIDE`.
9
+ - `module.controller.accept`, `module.controller.arrows.vertical`, `module.controller.arrows.horizontal`, `module.controller.arrows.grid`, `module.controller.hide.on.controls`, `module.controller.backgrounds`, `module.controller.bg`, `module.controller.preload`, `module.controller.audio`, `module.controller.tabs` — `isShow` is written to state on show and cleared on hide. A repeated `SHOW`, and a `HIDE` while hidden, stop the controller on `GATE`. API: `state.isShow`.
10
+ - `core/components` — view show and hide phases: `CONST.COMPONENTS.LIFECYCLE_PRIORITY.SHOW` (`GATE`, `BEFORE`, `MAIN`, `CONTROLS`, `AFTER`, `CLEANUP`) and `CONST.COMPONENTS.LIFECYCLE_PRIORITY.HIDE` (`GATE`, `BEFORE`, `CONTROLS`, `MAIN`, `AFTER`, `CLEANUP`). The shift inside a phase is `± 1`. API: `CONST.COMPONENTS.LIFECYCLE_PRIORITY`.
11
+ - `module.components` — the required `ModuleController.EVENT_UPDATE_FORCE` subscribes to `updateViewForce`. `ModuleController.CONTROLS_EXTENSIONS` (default `{}`) is merged into `CONTROLS` in `init`. API: `ModuleController.EVENT_UPDATE_FORCE`, `ModuleController.CONTROLS_EXTENSIONS`.
12
+ - view contracts — added `UPDATE_FORCE` (`*:update_force`), with the same payload as `UPDATE_FAST`: `EVENTS.GALLERY.UPDATE_FORCE`, `EVENTS.SAVE_VIEW.UPDATE_FORCE`, `EVENTS.SETTINGS_SCREEN_VIEW.UPDATE_FORCE`, `EVENTS.SETTINGS_DEFAULT_VIEW.UPDATE_FORCE`, `EVENTS.SETTINGS_VIEW.UPDATE_FORCE`, `EVENTS.CHOOSE_VIEW.UPDATE_FORCE`, `EVENTS.EULA.UPDATE_FORCE`, `EVENTS.CONFIRM.UPDATE_FORCE`, `EVENTS.HISTORY_VIEW.UPDATE_FORCE`, `EVENTS.GAMEMENU.UPDATE_FORCE`, `EVENTS.CHECKERS_VIEW.UPDATE_FORCE`, `EVENTS.INTRO.UPDATE_FORCE`, `EVENTS.LOADING.UPDATE_FORCE`, `EVENTS.VIDEO.UPDATE_FORCE`, `EVENTS.COMMENT.UPDATE_FORCE`, `EVENTS.ACHIEVEMENT.UPDATE_FORCE`, `EVENTS.FPS.UPDATE_FORCE`, `EVENTS.CONTROLS_HINTS.UPDATE_FORCE`, `EVENTS.GAMEPAD_DEBUG.UPDATE_FORCE`, `EVENTS.CREDITS.UPDATE_FORCE`, `EVENTS.DISCLAIMER.UPDATE_FORCE`, `EVENTS.GALLERY_FULL_VIEW.UPDATE_FORCE`, `EVENTS.MAINMENU_SOCIALS_VIEW.UPDATE_FORCE`, `EVENTS.INTERFACE.UPDATE_FORCE`, `EVENTS.INTERFACE_CONTROLS_VIEW.UPDATE_FORCE`, `EVENTS.INTERFACE_FASTFORWARD_VIEW.UPDATE_FORCE`, `EVENTS.POINT_AND_CLICK_VIEW.UPDATE_FORCE`, `EVENTS.QTE_VIEW.UPDATE_FORCE`, `EVENTS.LAYER_BL.UPDATE_FORCE`, `EVENTS.LAYER_FL.UPDATE_FORCE`, `EVENTS.LAYER_ML.UPDATE_FORCE`, `EVENTS.LAYER_UL.UPDATE_FORCE`, `EVENTS.CURSOR.UPDATE_FORCE`. The main menu already had the event: `EVENTS.MAINMENU.UPDATE_FORCE`.
13
+ - `module.components` — removed the hooks `ModuleController.beforeShow`, `ModuleController.afterShow`, `ModuleController.beforeHide`, `ModuleController.afterHide`. The controller subscribes to its own `EVENT_SHOW` / `EVENT_HIDE` by phase. On `HIDE.CLEANUP` it calls `setDefaultState` when `ModuleController.SHOULD_CLEAR_STATE_ON_CLEANUP` is set (default `true`; `false` on `cursor.controller` and `interface.controller`). Required `EVENT_UPDATE_STATE` and `EVENT_UPDATE_FAST`: `UPDATE_STATE` merges a partial into state, `UPDATE_FAST` calls `updateViewFast`. `EVENTS.COMPONENTS.EXTERNAL_UPDATE` in the base: `state.isShow && updateViewFast()`. API: `CONST.COMPONENTS.LIFECYCLE_PRIORITY.SHOW.CLEANUP`, `CONST.COMPONENTS.LIFECYCLE_PRIORITY.HIDE.CLEANUP`, `ModuleController.SHOULD_CLEAR_STATE_ON_CLEANUP`.
14
+ - `module.components` — navigation by `currentItem` is removed from the base `ModuleController` (`incCurrentItem`, `decCurrentItem`, `setCurrentItem`, `unsetCurrentItem`, and the reset on `SHOW.GATE` and `HIDE.CLEANUP + 1`). The item index is `currentArrowVerticalItem` / `currentArrowHorizontalItem` in `@vnejs/module.controller.arrows.vertical` and `@vnejs/module.controller.arrows.horizontal`. API: removed `ModuleController.currentItem`, `ModuleController.maxCurrentItem`, `ModuleController.incCurrentItem`, `ModuleController.decCurrentItem`, `ModuleController.setCurrentItem`, `ModuleController.unsetCurrentItem`, `ModuleControllerState.currentItem`.
15
+ - view contracts — `STATE_UPDATE` is renamed to `UPDATE_STATE` (`*:state_update` → `*:update_state`): `EVENTS.GALLERY.UPDATE_STATE`, `EVENTS.MAINMENU.UPDATE_STATE`, `EVENTS.INTRO.UPDATE_STATE`, `EVENTS.LOADING.UPDATE_STATE`, `EVENTS.SAVE_VIEW.UPDATE_STATE`, `EVENTS.SETTINGS_SCREEN_VIEW.UPDATE_STATE`, `EVENTS.SETTINGS_DEFAULT_VIEW.UPDATE_STATE`, `EVENTS.SETTINGS_VIEW.UPDATE_STATE`, `EVENTS.CHOOSE_VIEW.UPDATE_STATE`, `EVENTS.EULA.UPDATE_STATE`, `EVENTS.CONFIRM.UPDATE_STATE`, `EVENTS.HISTORY_VIEW.UPDATE_STATE`, `EVENTS.GAMEMENU.UPDATE_STATE`, `EVENTS.CHECKERS_VIEW.UPDATE_STATE`. Added `UPDATE_STATE` and `UPDATE_FAST`: `EVENTS.VIDEO.UPDATE_STATE`, `EVENTS.VIDEO.UPDATE_FAST`, `EVENTS.COMMENT.UPDATE_STATE`, `EVENTS.COMMENT.UPDATE_FAST`, `EVENTS.ACHIEVEMENT.UPDATE_STATE`, `EVENTS.ACHIEVEMENT.UPDATE_FAST`, `EVENTS.FPS.UPDATE_STATE`, `EVENTS.FPS.UPDATE_FAST`, `EVENTS.CONTROLS_HINTS.UPDATE_STATE`, `EVENTS.CONTROLS_HINTS.UPDATE_FAST`, `EVENTS.GAMEPAD_DEBUG.UPDATE_STATE`, `EVENTS.GAMEPAD_DEBUG.UPDATE_FAST`, `EVENTS.CREDITS.UPDATE_STATE`, `EVENTS.CREDITS.UPDATE_FAST`, `EVENTS.DISCLAIMER.UPDATE_STATE`, `EVENTS.DISCLAIMER.UPDATE_FAST`, `EVENTS.GALLERY_FULL_VIEW.UPDATE_STATE`, `EVENTS.GALLERY_FULL_VIEW.UPDATE_FAST`, `EVENTS.MAINMENU_SOCIALS_VIEW.UPDATE_STATE`, `EVENTS.MAINMENU_SOCIALS_VIEW.UPDATE_FAST`, `EVENTS.INTERFACE.UPDATE_STATE`, `EVENTS.INTERFACE.UPDATE_FAST`, `EVENTS.INTERFACE_CONTROLS_VIEW.UPDATE_STATE`, `EVENTS.INTERFACE_CONTROLS_VIEW.UPDATE_FAST`, `EVENTS.INTERFACE_FASTFORWARD_VIEW.UPDATE_STATE`, `EVENTS.INTERFACE_FASTFORWARD_VIEW.UPDATE_FAST`, `EVENTS.POINT_AND_CLICK_VIEW.UPDATE_STATE`, `EVENTS.POINT_AND_CLICK_VIEW.UPDATE_FAST`, `EVENTS.QTE_VIEW.UPDATE_STATE`, `EVENTS.QTE_VIEW.UPDATE_FAST`, `EVENTS.LAYER_BL.UPDATE_STATE`, `EVENTS.LAYER_BL.UPDATE_FAST`, `EVENTS.LAYER_FL.UPDATE_STATE`, `EVENTS.LAYER_FL.UPDATE_FAST`, `EVENTS.LAYER_ML.UPDATE_STATE`, `EVENTS.LAYER_ML.UPDATE_FAST`, `EVENTS.LAYER_UL.UPDATE_STATE`, `EVENTS.LAYER_UL.UPDATE_FAST`, `EVENTS.CURSOR.UPDATE_STATE`, `EVENTS.CURSOR.UPDATE_FAST`.
16
+ - `module.controller.bg` — the background loads on `SHOW` with `CONST.COMPONENTS.LIFECYCLE_PRIORITY.SHOW.BEFORE`. The `isShow` flag is set on `MAIN`. Removed `EVENT_SHOW_BEFORE`.
17
+ - `module.controller.accept`, `module.controller.arrows.vertical`, `module.controller.arrows.horizontal`, `module.controller.arrows.grid`, `module.controller.tabs`, `module.controller.hide.on.controls` — PUSH/POP run on the `CONTROLS` phase.
18
+ - `module.controller.audio`, `module.controller.backgrounds` — SHOW/HIDE run on `AFTER`. `module.controller.preload` — SHOW runs on `BEFORE`.
19
+ - `views.screens/gallery`, `views.screens/mainmenu`, `views.screens/intro`, `views.screens/loading`, `views.screens/save`, `views.screens/settings`, `views.screens/settings.defaults`, `views.scenario/choose`, `views.scenario/qte`, `views.scenario/point_and_click` — removed the `SHOW_BEFORE` event. Screen setup subscribes to `SHOW` with `CONST.COMPONENTS.LIFECYCLE_PRIORITY.SHOW.BEFORE`. API: removed `EVENTS.GALLERY.SHOW_BEFORE`, `EVENTS.MAINMENU.SHOW_BEFORE`, `EVENTS.INTRO.SHOW_BEFORE`, `EVENTS.LOADING.SHOW_BEFORE`, `EVENTS.SAVE_VIEW.SHOW_BEFORE`, `EVENTS.SETTINGS_SCREEN_VIEW.SHOW_BEFORE`, `EVENTS.SETTINGS_DEFAULT_VIEW.SHOW_BEFORE`, `EVENTS.CHOOSE_VIEW.SHOW_BEFORE`, `EVENTS.QTE_VIEW.SHOW_BEFORE`, `EVENTS.POINT_AND_CLICK_VIEW.SHOW_BEFORE`.
@@ -0,0 +1,11 @@
1
+ # 0.2.56
2
+
3
+ - `module.components` — `ModuleController` always subscribes to `EVENT_SHOW` / `EVENT_HIDE` with `CONST.COMPONENTS.LIFECYCLE_PRIORITY.SHOW.BEFORE` / `SHOW.AFTER` / `HIDE.BEFORE` / `HIDE.AFTER`, and to `EVENTS.SETTINGS.CHANGED` (`state.isShow && updateViewFast()`). Children override methods instead of calling `this.on`. API: `ModuleController.onShowBefore`, `ModuleController.onShowAfter`, `ModuleController.onHideBefore`, `ModuleController.onHideAfter`, `ModuleController.onSettingChange`.
4
+ - `views.screens/settings`, `views.screens/settings.defaults` — on `HIDE.BEFORE` the emit of `EVENTS.SETTINGS_VIEW.HIDE` is not awaited. `onHideBefore` uses `void this.emit`, so hiding the fields runs in parallel with the other handlers of the phase.
5
+ - `views.screens/history` — `HISTORY_VIEW.CLICK` lives in `history.controller.click`. The uid check uses `EVENTS.HISTORY.KEYS`, not `state.historyKeys`.
6
+ - `views.screens/eula` — `eula.controller` overrides `onSettingChange` (language plus a reset of the arrow). The separate subscription to `SETTINGS.CHANGED` is gone.
7
+ - `views/video` — `VIDEO.SET_SRC` lives in `video.controller.src` (`UPDATE_STATE` + `UPDATE_FAST`).
8
+ - `views/fps` — removed `EVENTS.FPS.CHANGE`. `fps` writes `UPDATE_STATE` `{ text }` and `UPDATE_FAST`. API: removed `EVENTS.FPS.CHANGE`, `FpsChangePayload`.
9
+ - `views/gamepad.debug` — removed `EVENTS.GAMEPAD_DEBUG.CHANGE`. `gamepad.debug` writes `UPDATE_STATE` `{ text }` and `UPDATE_FAST`. API: removed `EVENTS.GAMEPAD_DEBUG.CHANGE`, `GamepadDebugChangePayload`.
10
+ - `views/cursor` — `CURSOR.MOVED` / `VIEW_SET` / `MEMORY.CLEARED` live in `cursor.controller.sync`.
11
+ - `controls/cursor` — `EVENTS.CURSOR.UPDATE_STATE` accepts a partial of the cursor state. API: `CursorUpdatePayload`.
@@ -0,0 +1,7 @@
1
+ # 0.2.57
2
+
3
+ - `module.controller.arrows.horizontal` — buttons call overridable `onArrowLeft` / `onArrowRight` (default `decCurrentItem` / `incCurrentItem`). A hook may return a `Promise`. `getMaxCurrentItem` is no longer abstract. The default is `0`. `EVENT_UPDATE_STATE` merges a partial into the module state. API: `ModuleControllerArrowsHorizontal.onArrowLeft`, `ModuleControllerArrowsHorizontal.onArrowRight`, `ModuleControllerArrowsHorizontal.getMaxCurrentItem`.
4
+ - `module.controller.arrows.vertical` — buttons call overridable `onArrowUp` / `onArrowBottom` (default `decCurrentItem` / `incCurrentItem`). A hook may return a `Promise`. `getMaxCurrentItem` is no longer abstract. The default is `0`. API: `ModuleControllerArrowsVertical.onArrowUp`, `ModuleControllerArrowsVertical.onArrowBottom`, `ModuleControllerArrowsVertical.getMaxCurrentItem`.
5
+ - `module.controller.arrows.grid` — buttons call overridable `onArrowUp` / `onArrowRight` / `onArrowBottom` / `onArrowLeft`. A hook may return a `Promise`. API: `ModuleControllerArrowsGrid.onArrowUp`, `ModuleControllerArrowsGrid.onArrowRight`, `ModuleControllerArrowsGrid.onArrowBottom`, `ModuleControllerArrowsGrid.onArrowLeft`.
6
+ - `views.screens/gallery.full` — horizontal arrows live in `gallery.full.controller.arrows`. `onArrowLeft` / `onArrowRight` emit `EVENTS.GALLERY_FULL_VIEW.PREV` / `EVENTS.GALLERY_FULL_VIEW.NEXT`. `gallery.full.variation` extends `@vnejs/module.controller.pages`: `PREV` / `NEXT` / `PAGE_SET`, `applyPage` → `LOAD`. The variation index in state is `pageIndex` / `pagesCount` (was `variationIndex` / `variantsCount`). `LOAD` payload is `{ pageIndex }`. For an open variation it emits `LOAD_SRC`. `gallery.full.load.src` loads the src. The controller writes the item context (`itemFullName`, `itemMediaType`, `itemLayerChildType`, `variants`) into `EVENTS.GALLERY_FULL_VIEW.UPDATE_STATE`. `GALLERY.CHOOSE` → `SHOW` in `gallery.full.bridge`. Removed `EVENTS.GALLERY_FULL_VIEW.VARIATION_PREV`, `EVENTS.GALLERY_FULL_VIEW.VARIATION_NEXT`, `EVENTS.GALLERY_FULL_VIEW.VARIATION_LOAD`. API: `EVENTS.GALLERY_FULL_VIEW.LOAD`, `EVENTS.GALLERY_FULL_VIEW.LOAD_SRC`, `EVENTS.GALLERY_FULL_VIEW.PREV`, `EVENTS.GALLERY_FULL_VIEW.NEXT`, `EVENTS.GALLERY_FULL_VIEW.PAGE_SET`, `GalleryFullLoadPayload`, `GalleryFullLoadSrcPayload`, `GalleryFullLoadSrcResult`, `GalleryFullImageSrcItem`, `GalleryFullPageSetPayload`.
7
+ - `views/settings` — horizontal arrows live in `settings.fields.controller.arrows.horizontal`. `onArrowLeft` / `onArrowRight` emit `EVENTS.SETTINGS_VIEW.ARROW_LEFT` / `EVENTS.SETTINGS_VIEW.ARROW_RIGHT`. Handlers stay on `settings.fields.controller`. API: `EVENTS.SETTINGS_VIEW.ARROW_LEFT`, `EVENTS.SETTINGS_VIEW.ARROW_RIGHT`.
@@ -0,0 +1,8 @@
1
+ # 0.2.58
2
+
3
+ - `text/text` — `STATE.SET` and `STATE.CLEAR` emit `TEXT.EMIT` with `isKeepProcessState`, so a restore does not overwrite `text.process.state`. `TEXT.EMIT_END` with this flag does not emit `TEXT.PROCESS_STATE` or `TEXT.EMIT_NEXT`. A scenario `TEXT.EMIT` does not set the flag. API: `TextEmitPayload.isKeepProcessState`, `TextEmitEndPayload.isKeepProcessState`.
4
+ - `scenario/choose` — each opening of a choice has its own `id` (`crypto.randomUUID()` on `EMIT`, `""` after close). `STATE.SET` while another choice is open writes the slice and emits `HIDE`, then `SHOW` with `{ isForce: true }`. A change of `isShow` emits one `EVENTS.CHOOSE.HIDE` or `EVENTS.CHOOSE.SHOW` with `{ isForce: true }`. API: `ChoosePluginModelState.id`.
5
+ - `module.controller.interact` — `BUTTONS.ANY` → `EVENTS.INTERACT.EMIT`. After show, `EVENTS.INTERACT.PUSH` with `onInteract`. Before hide, `EVENTS.INTERACT.POP`. Controls PUSH/POP on `SHOW.CONTROLS` / `HIDE.CONTROLS`. API: `ModuleControllerInteract.onInteract`, `ModuleControllerInteract.EVENT_SHOW`, `ModuleControllerInteract.EVENT_HIDE`, `ModuleControllerInteract.CONTROLS_ZINDEX`, `ModuleControllerInteract.CONTROLS_CHECK_NEXT`.
6
+ - `views/video` — `BUTTONS.ANY` and `INTERACT.PUSH` / `POP` live in `video.controller.interact` on `@vnejs/module.controller.interact`. `onInteract` returns a promise of `EVENTS.VIDEO.HIDE`. `video.controller` emits `EVENTS.INTERFACE.TEXT_HIDE` on `SHOW.BEFORE`, and `EVENTS.VIDEO.SET_SRC` plus `EVENTS.SCENARIO.NEXT` on `HIDE.AFTER`.
7
+ - `views.screens/intro` — `BUTTONS.ANY` and `INTERACT.PUSH` / `POP` live in `intro.controller.interact` on `@vnejs/module.controller.interact`. `onInteract` → `EVENTS.INTRO.INTERACT`.
8
+ - `views.screens/credits` — `credits.controller.accept` is replaced by `credits.controller.interact` on `@vnejs/module.controller.interact`. `onInteract` → `EVENTS.CREDITS.HIDE`. Removed `EVENTS.CREDITS.ACCEPT`.
@@ -0,0 +1,6 @@
1
+ # 0.2.59
2
+
3
+ - `views.scenario/interface.controls`, `views.scenario/interface.fastforward` — hide does not clear local state (`SHOULD_CLEAR_STATE_ON_CLEANUP` = `false`). Otherwise `$ interface show` after a choice published `isVisible: false`, and the buttons with the scroll indicator stayed transparent. API: `InterfaceControlsController.SHOULD_CLEAR_STATE_ON_CLEANUP`, `InterfaceFastforwardController.SHOULD_CLEAR_STATE_ON_CLEANUP`.
4
+ - `module.controller.hide.on.controls`, `module.controller.accept`, `module.controller.interact`, `module.controller.arrows.vertical`, `module.controller.arrows.horizontal`, `module.controller.arrows.grid`, `module.controller.tabs`, `module.controller.audio` — their own `state.isShow` is gone. A repeated `SHOW` / `HIDE` stops `ModuleController` on `GATE`. Extensions no longer skip `POP` because of a local flag. API: removed `state.isShow` from `ModuleControllerHideOnControlsState`, `ModuleControllerAcceptState`, `ModuleControllerInteractState`, `ModuleControllerArrowsVerticalState`, `ModuleControllerArrowsHorizontalState`, `ModuleControllerArrowsGridState`, `ModuleControllerTabsState`, `ModuleControllerAudioState`.
5
+ - `module.components` — `ModuleController.setShow` writes `{ isShow }` through `EVENT_UPDATE_STATE`, then calls `updateView(isForce, false)`.
6
+ - `module.controller.backgrounds`, `module.controller.bg`, `module.controller.preload` — they subscribe to `EVENT_UPDATE_STATE` (`updateState`). Their own `isShow` on `SHOW` / `HIDE` is gone. `backgrounds` always clears the rotation timer on `HIDE.AFTER`. API: `ModuleControllerPreload.EVENT_UPDATE_STATE`.
@@ -0,0 +1,5 @@
1
+ # 0.2.60
2
+
3
+ - `backends/auth`, `backends/content` — workers for the Steam token and for serving `dist/label`. Content is served only with a JWT where `ownsApp` is true.
4
+ - `views.screens/history` — close with the cross at the top right. The click emits `EVENTS.HISTORY_VIEW.HIDE`. The text button at the bottom is gone. The line list is 1800 tall, centered on the vertical axis of the screen. API: `PARAMS.HISTORY_VIEW.VIEW_PROPS.close` is now `{ position, svg }`.
5
+ - `module.controller.arrows.vertical`, `module.controller.arrows.horizontal`, `module.controller.arrows.grid` — on `HIDE.CLEANUP` the item position in state becomes `undefined` through `UPDATE_STATE`, then `UPDATE_FAST` redraws the view. API: `currentArrowVerticalItem`, `currentArrowHorizontalItem`, `gridRow`, `gridColumn`, `CONST.COMPONENTS.LIFECYCLE_PRIORITY.HIDE.CLEANUP`.
@@ -0,0 +1,11 @@
1
+ # 0.2.61
2
+
3
+ - `views.scenario/interface` — `INTERFACE.SHOW` and `INTERFACE.HIDE` subscribe in the module `interface.actions.show`. On `GATE` they stop the other subscribers when the interface is already shown or already hidden, or when show/hide is already running. Showing a hidden layer emits `EVENTS.INTERFACE.VISIBLE`. API: `InterfaceShow.onShowGate`, `InterfaceShow.onHideGate`, `InterfaceShow.isInShowOrHideProcess`, `InterfaceShow.setShow`, `CONST.COMPONENTS.LIFECYCLE_PRIORITY.SHOW.GATE`, `CONST.COMPONENTS.LIFECYCLE_PRIORITY.HIDE.GATE`.
4
+ - `views/controls.hints` — show/hide of a group by `showEvents` / `hideEvents` keeps `isForce` from the source event. `isForce: true` updates the view through `UPDATE_FORCE`, otherwise through `UPDATE_FAST`. API: `ControlsHintsController.onGroupShow`, `ControlsHintsController.onGroupHide`, `ControlsHintsController.updateGroupStateAndView`.
5
+ - `backends/auth`, `backends/content` — local run: `npm run dev` (`npm start` is the same), auth `127.0.0.1:8787`, content `127.0.0.1:8788`. The secret comes from `.env`. An empty `AUTH_SECRET` returns `500`, not a WebCrypto error.
6
+ - `backends/auth` — `GET /` shows login status and a button to `/steam/start`. The worker's own origin is allowed for this page together with `ALLOWED_ORIGINS`.
7
+ - `backends/auth` — `isOwnedByUser` (was `isPurchasedByUser`): `ownsApp` is set in the JWT without requiring `permanent` in the CheckAppOwnership response. `sitelicense` and a foreign `ownersteamid` are still rejected.
8
+ - `backends/auth` — env `APP_DEMO_ID` (default `5081630`). CheckAppOwnership runs for the demo. In the JWT and on the test page `GET /`, `ownsDemoApp` is separate from `ownsApp`.
9
+ - `backends/auth` — the test page and `/session` show the name (`GetPlayerSummaries`) and the local JWT end time (`expiresAt`, format `DD.MM hh:mm:ss`), plus a button labeled «Обновить сессию» (`GET /session`).
10
+ - `backends/shared` — `TOKEN_TTL_SECONDS`: the JWT lives for 3 days.
11
+ - `backends/auth`, `backends/content` — HTTP on Fastify. Locally, `npm run dev` (`node --env-file=.env` + `tsx`, ports 8787/8788). Optional `npm run dev:worker` (Wrangler + Fastify through `inject`).
@@ -0,0 +1,8 @@
1
+ # 0.2.62
2
+
3
+ - `module.components` — when `isForce` is set, `onUpdateStoreComponent` waits for `ViewStoreApi.notifyIsForce(true)` and then writes `isForce: false`. The fixed `waitTimeout(100)` is gone. API: `ViewStoreApi.notifyIsForce`, `ViewIsForceNotify`.
4
+ - `uis/react/hooks/use-store-state` — the subscription uses `useSyncExternalStore`. After a commit of state with `isForce`, it calls `store.notifyIsForce(true)`. That is the only signal that releases the wait in `onUpdateStoreComponent`.
5
+ - `uis/react/hooks/use-is-force-hook` — the timeout that clears `isRealForce` is cancelled if `isForce` becomes `true` again.
6
+ - `views/fps`, `views/gamepad.debug`, `views/achievement` — `View` receives `isForce` from the store. `View` itself delays the frame.
7
+ - `views.scenario/interface` — `isForce` reaches `SmoothText` in `InterfaceViewDialog`, `InterfaceViewLine`, and `InterfaceViewWall`. Otherwise a forced frame keeps the character-by-character transition.
8
+ - `uis/react/composites/smooth-text` — a change of `tokens` is drawn with no `opacity` transition. Later growth of `tokensVisibleForce` still animates when several characters appear in one frame. `tokensVisibleForce` is applied before paint.
@@ -0,0 +1,4 @@
1
+ # 0.2.63
2
+
3
+ - `uis/react/hooks/use-store-state` — `notifyIsForce(true)` runs from `useLayoutEffect`, in the same commit where React wrote `isForce`. `useEffect` was a later task and sometimes did not run. `interface.controller` stayed in `uninitedModules`, so the engine never reached `start`.
4
+ - `module.components` — several waits for `isForce` on one view resolve together. Before, a second `onUpdateStoreComponent` overwrote the first resolver, and the first wait never finished.
@@ -0,0 +1,4 @@
1
+ # 0.2.64
2
+
3
+ - `views.screens/credits` — the end of the scroll and a click on the screen emit `CREDITS.HIDE`. Before, the view passed `onClose`. `ScrollContent` waits for `onFinish` and `Screen` waits for `onClick`, so after the credits `SCENARIO.NEXT` never fired and the scenario did not continue.
4
+ - `text/text` — `STATE.CLEAR` clears the text and emits `TEXT.CHANGED`, without `TEXT.EMIT`. Before, clear went through `TEXT.EMIT` → `TEXT.EMIT_BEFORE` → `INTERFACE.SHOW` and opened an empty interface. `STATE.SET` still emits `TEXT.EMIT` with `isKeepProcessState`.
@@ -0,0 +1,3 @@
1
+ # 0.2.65
2
+
3
+ - `compatibility/text/scenario.history`, `views.screens/history` — the history log looks up a translation by the scenario line, including `{…}` markers (`{i}`, `{/i}`). Before, markers were stripped before `TEXT.REPLACE`. The key missed the dictionary, so the log kept the source text. Markers are still stripped from the shown line after translation.
@@ -0,0 +1,5 @@
1
+ # 0.2.66
2
+
3
+ - `scenario/choose` — option text no longer calls `TEXT.REPLACE` inside the plugin. `CHOOSE.OPTION_TEXT` / `CHOOSE.OPTION_TEXT_REG` replace the `text` field through `@vnejs/module.replace`. Without handlers the scenario literal stays.
4
+ - `compatibility/scenario.choose/text` — `@vnejs/compatibility.scenario.choose-with-text` registers an `OPTION_TEXT` handler that returns `TEXT.REPLACE`. Wired in `bundles/vn.skeleton`.
5
+ - `bundles/checkers` — drop `@vnejs/plugins.text` and `@vnejs/compatibility.scenario.choose-with-text`. Choose option labels stay the scenario literals.