create-pixi-vn 2.0.13 → 2.0.15

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 (205) hide show
  1. package/dist/index.mjs +36 -35
  2. package/package.json +1 -1
  3. package/template-react-vite-muijoy/components.json +1 -1
  4. package/template-react-vite-muijoy/package-lock.json +760 -1060
  5. package/template-react-vite-muijoy/package.json +11 -12
  6. package/template-react-vite-muijoy/src/components/dev-devtools.tsx +25 -0
  7. package/template-react-vite-muijoy/src/components/loading.tsx +11 -1
  8. package/template-react-vite-muijoy/src/components/menus/choice-menus.tsx +4 -0
  9. package/template-react-vite-muijoy/src/components/menus/main-menu.tsx +1 -6
  10. package/template-react-vite-muijoy/src/components/menus/settings/index.tsx +3 -1
  11. package/template-react-vite-muijoy/src/components/menus/settings/menus/history.tsx +78 -62
  12. package/template-react-vite-muijoy/src/components/modals/input-request-dialogues.tsx +1 -1
  13. package/template-react-vite-muijoy/src/components/modals/quick-actions-wheel.tsx +3 -1
  14. package/template-react-vite-muijoy/src/components/providers/alert-dialog-provider.tsx +3 -0
  15. package/template-react-vite-muijoy/src/components/screens/narration/index.tsx +5 -2
  16. package/template-react-vite-muijoy/src/components/screens/narration/narration-cards.tsx +40 -19
  17. package/template-react-vite-muijoy/src/components/ui/alert-dialog.tsx +3 -2
  18. package/template-react-vite-muijoy/src/components/ui/avatar.tsx +2 -2
  19. package/template-react-vite-muijoy/src/components/ui/breadcrumb.tsx +5 -4
  20. package/template-react-vite-muijoy/src/components/ui/button-group.tsx +3 -2
  21. package/template-react-vite-muijoy/src/components/ui/button.tsx +2 -2
  22. package/template-react-vite-muijoy/src/components/ui/card.tsx +6 -10
  23. package/template-react-vite-muijoy/src/components/ui/carousel.tsx +10 -7
  24. package/template-react-vite-muijoy/src/components/ui/drawer.tsx +2 -0
  25. package/template-react-vite-muijoy/src/components/ui/field.tsx +8 -5
  26. package/template-react-vite-muijoy/src/components/ui/input-group.tsx +4 -3
  27. package/template-react-vite-muijoy/src/components/ui/input.tsx +1 -1
  28. package/template-react-vite-muijoy/src/components/ui/item.tsx +9 -8
  29. package/template-react-vite-muijoy/src/components/ui/label.tsx +1 -1
  30. package/template-react-vite-muijoy/src/components/ui/radio-group.tsx +4 -1
  31. package/template-react-vite-muijoy/src/components/ui/scroll-area.tsx +5 -2
  32. package/template-react-vite-muijoy/src/components/ui/select.tsx +3 -2
  33. package/template-react-vite-muijoy/src/components/ui/separator.tsx +2 -0
  34. package/template-react-vite-muijoy/src/components/ui/sonner.tsx +4 -4
  35. package/template-react-vite-muijoy/src/components/ui/spinner.tsx +2 -1
  36. package/template-react-vite-muijoy/src/components/ui/switch.tsx +3 -0
  37. package/template-react-vite-muijoy/src/components/ui/textarea.tsx +2 -1
  38. package/template-react-vite-muijoy/src/components/ui/tooltip.tsx +2 -0
  39. package/template-react-vite-muijoy/src/lib/hooks/hotkeys-hooks.ts +113 -10
  40. package/template-react-vite-muijoy/src/lib/hooks/narration-hooks.ts +31 -10
  41. package/template-react-vite-muijoy/src/lib/hooks/navigation-hooks.ts +29 -10
  42. package/template-react-vite-muijoy/src/lib/query/narration-query.ts +32 -2
  43. package/template-react-vite-muijoy/src/lib/stores/alert-dialog-store.ts +13 -0
  44. package/template-react-vite-muijoy/src/lib/stores/text-display-settings-store.ts +20 -1
  45. package/template-react-vite-muijoy/src/locales/en.json +2 -0
  46. package/template-react-vite-muijoy/src/main.tsx +0 -1
  47. package/{template-react-vite-muijoy-tauri/src/pixi-vn-keys.gen.d.ts → template-react-vite-muijoy/src/pixi-vn.keys.gen.ts} +4 -2
  48. package/template-react-vite-muijoy/src/routeTree.gen.ts +3 -21
  49. package/template-react-vite-muijoy/src/routes/__root.tsx +10 -21
  50. package/template-react-vite-muijoy/src/styles.css +43 -43
  51. package/template-react-vite-muijoy/vite.config.ts +1 -1
  52. package/template-react-vite-muijoy-ink/components.json +1 -1
  53. package/template-react-vite-muijoy-ink/package-lock.json +721 -1059
  54. package/template-react-vite-muijoy-ink/package.json +12 -13
  55. package/template-react-vite-muijoy-ink/src/components/dev-devtools.tsx +25 -0
  56. package/template-react-vite-muijoy-ink/src/components/loading.tsx +11 -1
  57. package/template-react-vite-muijoy-ink/src/components/menus/choice-menus.tsx +4 -0
  58. package/template-react-vite-muijoy-ink/src/components/menus/main-menu.tsx +1 -6
  59. package/template-react-vite-muijoy-ink/src/components/menus/settings/index.tsx +3 -1
  60. package/template-react-vite-muijoy-ink/src/components/menus/settings/menus/history.tsx +78 -62
  61. package/template-react-vite-muijoy-ink/src/components/modals/input-request-dialogues.tsx +1 -1
  62. package/template-react-vite-muijoy-ink/src/components/modals/quick-actions-wheel.tsx +3 -1
  63. package/template-react-vite-muijoy-ink/src/components/providers/alert-dialog-provider.tsx +3 -0
  64. package/template-react-vite-muijoy-ink/src/components/screens/narration/index.tsx +5 -2
  65. package/template-react-vite-muijoy-ink/src/components/screens/narration/narration-cards.tsx +40 -19
  66. package/template-react-vite-muijoy-ink/src/components/ui/alert-dialog.tsx +3 -2
  67. package/template-react-vite-muijoy-ink/src/components/ui/avatar.tsx +2 -2
  68. package/template-react-vite-muijoy-ink/src/components/ui/breadcrumb.tsx +5 -4
  69. package/template-react-vite-muijoy-ink/src/components/ui/button-group.tsx +3 -2
  70. package/template-react-vite-muijoy-ink/src/components/ui/button.tsx +2 -2
  71. package/template-react-vite-muijoy-ink/src/components/ui/card.tsx +6 -10
  72. package/template-react-vite-muijoy-ink/src/components/ui/carousel.tsx +10 -7
  73. package/template-react-vite-muijoy-ink/src/components/ui/drawer.tsx +2 -0
  74. package/template-react-vite-muijoy-ink/src/components/ui/field.tsx +8 -5
  75. package/template-react-vite-muijoy-ink/src/components/ui/input-group.tsx +4 -3
  76. package/template-react-vite-muijoy-ink/src/components/ui/input.tsx +1 -1
  77. package/template-react-vite-muijoy-ink/src/components/ui/item.tsx +9 -8
  78. package/template-react-vite-muijoy-ink/src/components/ui/label.tsx +1 -1
  79. package/template-react-vite-muijoy-ink/src/components/ui/radio-group.tsx +4 -1
  80. package/template-react-vite-muijoy-ink/src/components/ui/scroll-area.tsx +5 -2
  81. package/template-react-vite-muijoy-ink/src/components/ui/select.tsx +3 -2
  82. package/template-react-vite-muijoy-ink/src/components/ui/separator.tsx +2 -0
  83. package/template-react-vite-muijoy-ink/src/components/ui/sonner.tsx +4 -4
  84. package/template-react-vite-muijoy-ink/src/components/ui/spinner.tsx +2 -1
  85. package/template-react-vite-muijoy-ink/src/components/ui/switch.tsx +3 -0
  86. package/template-react-vite-muijoy-ink/src/components/ui/textarea.tsx +2 -1
  87. package/template-react-vite-muijoy-ink/src/components/ui/tooltip.tsx +2 -0
  88. package/template-react-vite-muijoy-ink/src/content/ink/hashtag-commands.ts +2 -1
  89. package/template-react-vite-muijoy-ink/src/lib/hooks/hotkeys-hooks.ts +113 -10
  90. package/template-react-vite-muijoy-ink/src/lib/hooks/narration-hooks.ts +31 -10
  91. package/template-react-vite-muijoy-ink/src/lib/hooks/navigation-hooks.ts +29 -10
  92. package/template-react-vite-muijoy-ink/src/lib/query/narration-query.ts +32 -2
  93. package/template-react-vite-muijoy-ink/src/lib/stores/alert-dialog-store.ts +13 -0
  94. package/template-react-vite-muijoy-ink/src/lib/stores/text-display-settings-store.ts +20 -1
  95. package/template-react-vite-muijoy-ink/src/locales/en.json +2 -0
  96. package/template-react-vite-muijoy-ink/src/main.tsx +0 -1
  97. package/template-react-vite-muijoy-ink/src/pixi-vn.keys.gen.ts +24 -0
  98. package/template-react-vite-muijoy-ink/src/routeTree.gen.ts +3 -21
  99. package/template-react-vite-muijoy-ink/src/routes/__root.tsx +10 -21
  100. package/template-react-vite-muijoy-ink/src/styles.css +43 -43
  101. package/template-react-vite-muijoy-ink/vite.config.ts +1 -1
  102. package/template-react-vite-muijoy-ink-tauri/components.json +1 -1
  103. package/template-react-vite-muijoy-ink-tauri/package-lock.json +721 -1059
  104. package/template-react-vite-muijoy-ink-tauri/package.json +12 -13
  105. package/template-react-vite-muijoy-ink-tauri/src/components/dev-devtools.tsx +25 -0
  106. package/template-react-vite-muijoy-ink-tauri/src/components/loading.tsx +11 -1
  107. package/template-react-vite-muijoy-ink-tauri/src/components/menus/choice-menus.tsx +4 -0
  108. package/template-react-vite-muijoy-ink-tauri/src/components/menus/main-menu.tsx +1 -6
  109. package/template-react-vite-muijoy-ink-tauri/src/components/menus/settings/index.tsx +3 -1
  110. package/template-react-vite-muijoy-ink-tauri/src/components/menus/settings/menus/history.tsx +78 -62
  111. package/template-react-vite-muijoy-ink-tauri/src/components/modals/input-request-dialogues.tsx +1 -1
  112. package/template-react-vite-muijoy-ink-tauri/src/components/modals/quick-actions-wheel.tsx +3 -1
  113. package/template-react-vite-muijoy-ink-tauri/src/components/providers/alert-dialog-provider.tsx +3 -0
  114. package/template-react-vite-muijoy-ink-tauri/src/components/screens/narration/index.tsx +5 -2
  115. package/template-react-vite-muijoy-ink-tauri/src/components/screens/narration/narration-cards.tsx +40 -19
  116. package/template-react-vite-muijoy-ink-tauri/src/components/ui/alert-dialog.tsx +3 -2
  117. package/template-react-vite-muijoy-ink-tauri/src/components/ui/avatar.tsx +2 -2
  118. package/template-react-vite-muijoy-ink-tauri/src/components/ui/breadcrumb.tsx +5 -4
  119. package/template-react-vite-muijoy-ink-tauri/src/components/ui/button-group.tsx +3 -2
  120. package/template-react-vite-muijoy-ink-tauri/src/components/ui/button.tsx +2 -2
  121. package/template-react-vite-muijoy-ink-tauri/src/components/ui/card.tsx +6 -10
  122. package/template-react-vite-muijoy-ink-tauri/src/components/ui/carousel.tsx +10 -7
  123. package/template-react-vite-muijoy-ink-tauri/src/components/ui/drawer.tsx +2 -0
  124. package/template-react-vite-muijoy-ink-tauri/src/components/ui/field.tsx +8 -5
  125. package/template-react-vite-muijoy-ink-tauri/src/components/ui/input-group.tsx +4 -3
  126. package/template-react-vite-muijoy-ink-tauri/src/components/ui/input.tsx +1 -1
  127. package/template-react-vite-muijoy-ink-tauri/src/components/ui/item.tsx +9 -8
  128. package/template-react-vite-muijoy-ink-tauri/src/components/ui/label.tsx +1 -1
  129. package/template-react-vite-muijoy-ink-tauri/src/components/ui/radio-group.tsx +4 -1
  130. package/template-react-vite-muijoy-ink-tauri/src/components/ui/scroll-area.tsx +5 -2
  131. package/template-react-vite-muijoy-ink-tauri/src/components/ui/select.tsx +3 -2
  132. package/template-react-vite-muijoy-ink-tauri/src/components/ui/separator.tsx +2 -0
  133. package/template-react-vite-muijoy-ink-tauri/src/components/ui/sonner.tsx +4 -4
  134. package/template-react-vite-muijoy-ink-tauri/src/components/ui/spinner.tsx +2 -1
  135. package/template-react-vite-muijoy-ink-tauri/src/components/ui/switch.tsx +3 -0
  136. package/template-react-vite-muijoy-ink-tauri/src/components/ui/textarea.tsx +2 -1
  137. package/template-react-vite-muijoy-ink-tauri/src/components/ui/tooltip.tsx +2 -0
  138. package/template-react-vite-muijoy-ink-tauri/src/content/ink/hashtag-commands.ts +2 -1
  139. package/template-react-vite-muijoy-ink-tauri/src/lib/hooks/hotkeys-hooks.ts +113 -10
  140. package/template-react-vite-muijoy-ink-tauri/src/lib/hooks/narration-hooks.ts +31 -10
  141. package/template-react-vite-muijoy-ink-tauri/src/lib/hooks/navigation-hooks.ts +29 -10
  142. package/template-react-vite-muijoy-ink-tauri/src/lib/query/narration-query.ts +32 -2
  143. package/template-react-vite-muijoy-ink-tauri/src/lib/stores/alert-dialog-store.ts +13 -0
  144. package/template-react-vite-muijoy-ink-tauri/src/lib/stores/text-display-settings-store.ts +20 -1
  145. package/template-react-vite-muijoy-ink-tauri/src/locales/en.json +2 -0
  146. package/template-react-vite-muijoy-ink-tauri/src/main.tsx +0 -1
  147. package/{template-react-vite-muijoy-ink/src/pixi-vn-keys.gen.d.ts → template-react-vite-muijoy-ink-tauri/src/pixi-vn.keys.gen.ts} +4 -2
  148. package/template-react-vite-muijoy-ink-tauri/src/routeTree.gen.ts +3 -21
  149. package/template-react-vite-muijoy-ink-tauri/src/routes/__root.tsx +10 -21
  150. package/template-react-vite-muijoy-ink-tauri/src/styles.css +43 -43
  151. package/template-react-vite-muijoy-ink-tauri/vite.config.ts +1 -1
  152. package/template-react-vite-muijoy-tauri/components.json +1 -1
  153. package/template-react-vite-muijoy-tauri/package-lock.json +760 -1060
  154. package/template-react-vite-muijoy-tauri/package.json +11 -12
  155. package/template-react-vite-muijoy-tauri/src/components/dev-devtools.tsx +25 -0
  156. package/template-react-vite-muijoy-tauri/src/components/loading.tsx +11 -1
  157. package/template-react-vite-muijoy-tauri/src/components/menus/choice-menus.tsx +4 -0
  158. package/template-react-vite-muijoy-tauri/src/components/menus/main-menu.tsx +1 -6
  159. package/template-react-vite-muijoy-tauri/src/components/menus/settings/index.tsx +3 -1
  160. package/template-react-vite-muijoy-tauri/src/components/menus/settings/menus/history.tsx +78 -62
  161. package/template-react-vite-muijoy-tauri/src/components/modals/input-request-dialogues.tsx +1 -1
  162. package/template-react-vite-muijoy-tauri/src/components/modals/quick-actions-wheel.tsx +3 -1
  163. package/template-react-vite-muijoy-tauri/src/components/providers/alert-dialog-provider.tsx +3 -0
  164. package/template-react-vite-muijoy-tauri/src/components/screens/narration/index.tsx +5 -2
  165. package/template-react-vite-muijoy-tauri/src/components/screens/narration/narration-cards.tsx +40 -19
  166. package/template-react-vite-muijoy-tauri/src/components/ui/alert-dialog.tsx +3 -2
  167. package/template-react-vite-muijoy-tauri/src/components/ui/avatar.tsx +2 -2
  168. package/template-react-vite-muijoy-tauri/src/components/ui/breadcrumb.tsx +5 -4
  169. package/template-react-vite-muijoy-tauri/src/components/ui/button-group.tsx +3 -2
  170. package/template-react-vite-muijoy-tauri/src/components/ui/button.tsx +2 -2
  171. package/template-react-vite-muijoy-tauri/src/components/ui/card.tsx +6 -10
  172. package/template-react-vite-muijoy-tauri/src/components/ui/carousel.tsx +10 -7
  173. package/template-react-vite-muijoy-tauri/src/components/ui/drawer.tsx +2 -0
  174. package/template-react-vite-muijoy-tauri/src/components/ui/field.tsx +8 -5
  175. package/template-react-vite-muijoy-tauri/src/components/ui/input-group.tsx +4 -3
  176. package/template-react-vite-muijoy-tauri/src/components/ui/input.tsx +1 -1
  177. package/template-react-vite-muijoy-tauri/src/components/ui/item.tsx +9 -8
  178. package/template-react-vite-muijoy-tauri/src/components/ui/label.tsx +1 -1
  179. package/template-react-vite-muijoy-tauri/src/components/ui/radio-group.tsx +4 -1
  180. package/template-react-vite-muijoy-tauri/src/components/ui/scroll-area.tsx +5 -2
  181. package/template-react-vite-muijoy-tauri/src/components/ui/select.tsx +3 -2
  182. package/template-react-vite-muijoy-tauri/src/components/ui/separator.tsx +2 -0
  183. package/template-react-vite-muijoy-tauri/src/components/ui/sonner.tsx +4 -4
  184. package/template-react-vite-muijoy-tauri/src/components/ui/spinner.tsx +2 -1
  185. package/template-react-vite-muijoy-tauri/src/components/ui/switch.tsx +3 -0
  186. package/template-react-vite-muijoy-tauri/src/components/ui/textarea.tsx +2 -1
  187. package/template-react-vite-muijoy-tauri/src/components/ui/tooltip.tsx +2 -0
  188. package/template-react-vite-muijoy-tauri/src/lib/hooks/hotkeys-hooks.ts +113 -10
  189. package/template-react-vite-muijoy-tauri/src/lib/hooks/narration-hooks.ts +31 -10
  190. package/template-react-vite-muijoy-tauri/src/lib/hooks/navigation-hooks.ts +29 -10
  191. package/template-react-vite-muijoy-tauri/src/lib/query/narration-query.ts +32 -2
  192. package/template-react-vite-muijoy-tauri/src/lib/stores/alert-dialog-store.ts +13 -0
  193. package/template-react-vite-muijoy-tauri/src/lib/stores/text-display-settings-store.ts +20 -1
  194. package/template-react-vite-muijoy-tauri/src/locales/en.json +2 -0
  195. package/template-react-vite-muijoy-tauri/src/main.tsx +0 -1
  196. package/{template-react-vite-muijoy-ink-tauri/src/pixi-vn-keys.gen.d.ts → template-react-vite-muijoy-tauri/src/pixi-vn.keys.gen.ts} +4 -4
  197. package/template-react-vite-muijoy-tauri/src/routeTree.gen.ts +3 -21
  198. package/template-react-vite-muijoy-tauri/src/routes/__root.tsx +10 -21
  199. package/template-react-vite-muijoy-tauri/src/styles.css +43 -43
  200. package/template-react-vite-muijoy-tauri/vite.config.ts +1 -1
  201. package/template-react-vite-muijoy/src/pixi-vn-keys.gen.d.ts +0 -20
  202. package/template-react-vite-muijoy/src/routes/narration.tsx +0 -9
  203. package/template-react-vite-muijoy-ink/src/routes/narration.tsx +0 -9
  204. package/template-react-vite-muijoy-ink-tauri/src/routes/narration.tsx +0 -9
  205. package/template-react-vite-muijoy-tauri/src/routes/narration.tsx +0 -9
@@ -18,22 +18,15 @@
18
18
  "ui:reinit": "npx shadcn@latest init -f -b base --reinstall && npm run format"
19
19
  },
20
20
  "dependencies": {
21
- "@base-ui/react": "^1.5.0",
22
- "@drincs/pixi-vn": "^1.8.13",
23
- "@drincs/pixi-vn-spine": "^0.2.1",
21
+ "@base-ui/react": "^1.6.0",
22
+ "@drincs/pixi-vn": "^1.8.16",
24
23
  "@tailwindcss/vite": "^4.3.0",
25
24
  "@tanstack/hotkeys": "^0.8.0",
26
- "@tanstack/react-devtools": "^0.10.5",
27
25
  "@tanstack/react-hotkeys": "^0.10.0",
28
- "@tanstack/react-hotkeys-devtools": "^0.7.0",
29
26
  "@tanstack/react-pacer": "^0.22.1",
30
- "@tanstack/react-pacer-devtools": "^0.7.1",
31
27
  "@tanstack/react-query": "latest",
32
- "@tanstack/react-query-devtools": "latest",
33
28
  "@tanstack/react-router": "latest",
34
- "@tanstack/react-router-devtools": "latest",
35
29
  "@tanstack/react-store": "latest",
36
- "@tanstack/router-plugin": "latest",
37
30
  "@tanstack/store": "latest",
38
31
  "@unpic/react": "^1.0.2",
39
32
  "class-variance-authority": "^0.7.1",
@@ -43,18 +36,18 @@
43
36
  "i18next-browser-languagedetector": "^8.2.1",
44
37
  "i18next-chained-backend": "^5.0.4",
45
38
  "i18next-resources-to-backend": "^1.2.1",
46
- "lucide-react": "^1.17.0",
39
+ "lucide-react": "^1.21.0",
47
40
  "next-themes": "^0.4.6",
48
41
  "react": "^19.2.6",
49
42
  "react-color-palette": "^7.3.1",
50
43
  "react-dom": "^19.2.6",
51
44
  "react-i18next": "^17.0.8",
52
45
  "react-markdown": "^10.1.0",
53
- "react-markdown-typewriter": "^1.2.0",
46
+ "react-markdown-typewriter": "^1.3.4",
54
47
  "react-resizable-panels": "^4.11.2",
55
48
  "rehype-raw": "^7.0.0",
56
49
  "remark-gfm": "^4.0.1",
57
- "shadcn": "^4.10.0",
50
+ "shadcn": "^4.11.0",
58
51
  "shade-generator": "^1.2.7",
59
52
  "sonner": "^2.0.7",
60
53
  "tailwind-animations": "^1.0.1",
@@ -68,6 +61,12 @@
68
61
  "@biomejs/biome": "latest",
69
62
  "@tailwindcss/typography": "^0.5.19",
70
63
  "@tanstack/devtools-vite": "latest",
64
+ "@tanstack/react-devtools": "^0.10.7",
65
+ "@tanstack/react-hotkeys-devtools": "^0.7.0",
66
+ "@tanstack/react-pacer-devtools": "^0.7.1",
67
+ "@tanstack/react-query-devtools": "latest",
68
+ "@tanstack/react-router-devtools": "latest",
69
+ "@tanstack/router-plugin": "latest",
71
70
  "@types/node": "^25.9.1",
72
71
  "@types/react": "^19.2.15",
73
72
  "@types/react-dom": "^19.2.3",
@@ -0,0 +1,25 @@
1
+ import { TanStackDevtools } from "@tanstack/react-devtools";
2
+ import { hotkeysDevtoolsPlugin } from "@tanstack/react-hotkeys-devtools";
3
+ import { ReactQueryDevtoolsPanel } from "@tanstack/react-query-devtools";
4
+ import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools";
5
+
6
+ export default function DevDevtools() {
7
+ return (
8
+ <TanStackDevtools
9
+ config={{
10
+ position: "bottom-right",
11
+ }}
12
+ plugins={[
13
+ {
14
+ name: "UI screens",
15
+ render: <TanStackRouterDevtoolsPanel />,
16
+ },
17
+ { ...hotkeysDevtoolsPlugin(), name: "Hotkeys" },
18
+ {
19
+ name: "UI cache",
20
+ render: <ReactQueryDevtoolsPanel />,
21
+ },
22
+ ]}
23
+ />
24
+ );
25
+ }
@@ -1,4 +1,5 @@
1
1
  import { Spinner } from "@/components/ui/spinner";
2
+ import { useEffect, useState } from "react";
2
3
 
3
4
  export function PendingComponent() {
4
5
  return (
@@ -12,10 +13,19 @@ export function PendingComponent() {
12
13
 
13
14
  export function AnimatedDots() {
14
15
  return (
15
- <span className="flex pointer-events-none select-none">
16
+ <span className="inline-flex pointer-events-none select-none">
16
17
  <span className="animate-bounce [animation-delay:0s]">.</span>
17
18
  <span className="animate-bounce [animation-delay:0.2s]">.</span>
18
19
  <span className="animate-bounce [animation-delay:0.4s]">.</span>
19
20
  </span>
20
21
  );
21
22
  }
23
+
24
+ export function DelayedAnimatedDots({ delay = 300 }: { delay?: number }) {
25
+ const [visible, setVisible] = useState(false);
26
+ useEffect(() => {
27
+ const id = setTimeout(() => setVisible(true), delay);
28
+ return () => clearTimeout(id);
29
+ }, [delay]);
30
+ return visible ? <AnimatedDots /> : null;
31
+ }
@@ -1,4 +1,5 @@
1
1
  import { Button } from "@/components/ui/button";
2
+ import { useChoiceMenuHotkeys } from "@/lib/hooks/hotkeys-hooks";
2
3
  import { useNarrationFunctions } from "@/lib/hooks/narration-hooks";
3
4
  import { useQueryChoiceMenuOptions } from "@/lib/query/narration-query";
4
5
  import { GameStatus } from "@/lib/stores/game-status-store";
@@ -13,9 +14,11 @@ export function ChoiceMenu() {
13
14
  const isTyping = useSelector(TextDisplaySettings.store, (state) => state.inProgress);
14
15
  const { selectChoice } = useNarrationFunctions();
15
16
  const [debouncedMenu] = useDebouncedValue(isTyping ? [] : menu, { wait: 50 });
17
+ const { menuRef } = useChoiceMenuHotkeys(debouncedMenu.length);
16
18
 
17
19
  return (
18
20
  <div
21
+ ref={menuRef}
19
22
  className="flex flex-col items-center justify-center gap-2 w-full h-full overflow-auto"
20
23
  role="menu"
21
24
  >
@@ -28,6 +31,7 @@ export function ChoiceMenu() {
28
31
  style={{ animationDelay: `${index * 150}ms` }}
29
32
  >
30
33
  <Button
34
+ role="menuitem"
31
35
  disabled={loading}
32
36
  onClick={() => selectChoice(item)}
33
37
  size="sm"
@@ -26,7 +26,6 @@ const menuButtonClass =
26
26
  "justify-start hover:scale-105 focus-visible:scale-105 transition-transform duration-150 ease-out";
27
27
 
28
28
  export function MainMenu() {
29
- const queryClient = useQueryClient();
30
29
  const gameProps = useGameProps();
31
30
  const { uiTransition: t, navigate } = gameProps;
32
31
  const setSettings = useSetSearchParamState<boolean>("settings");
@@ -147,11 +146,7 @@ export function MainMenu() {
147
146
  setLoading(true);
148
147
  await navigate({ to: "/game/narration" });
149
148
  Game.start("start", gameProps)
150
- .then(() =>
151
- queryClient.invalidateQueries({
152
- queryKey: [INTERFACE_DATA_USE_QUERY_KEY],
153
- }),
154
- )
149
+ .then(() => gameProps.invalidateInterfaceData())
155
150
  .finally(() => setLoading(false));
156
151
  }}
157
152
  disabled={loading}
@@ -208,7 +208,9 @@ export function SettingsDialogue() {
208
208
  onOpenChange={(isOpen) => {
209
209
  setOpen(isOpen || undefined);
210
210
  if (!isOpen) {
211
- setSettingsTab(undefined);
211
+ // Delay clearing the tab until after the 100ms close animation
212
+ // to avoid briefly flashing the main settings view during close.
213
+ setTimeout(() => setSettingsTab(undefined), 150);
212
214
  }
213
215
  }}
214
216
  >
@@ -15,7 +15,7 @@ import { useQueryNarrativeHistory } from "@/lib/query/narration-query";
15
15
  import { cn } from "@/lib/utils";
16
16
  import { useDebouncedValue } from "@tanstack/react-pacer";
17
17
  import { Check, Search } from "lucide-react";
18
- import { useState } from "react";
18
+ import { useEffect, useRef, useState } from "react";
19
19
  import { useTranslation } from "react-i18next";
20
20
  import Markdown from "react-markdown";
21
21
  import rehypeRaw from "rehype-raw";
@@ -33,80 +33,96 @@ function HistoryItemAvatar({ icon, character }: { icon?: string; character: stri
33
33
 
34
34
  export function HistoryList({ searchString }: { searchString?: string }) {
35
35
  const { data = [] } = useQueryNarrativeHistory({ searchString });
36
+ const bottomRef = useRef<HTMLDivElement>(null);
37
+
38
+ useEffect(() => {
39
+ if (data.length > 0) {
40
+ bottomRef.current?.scrollIntoView();
41
+ }
42
+ }, [data]);
36
43
 
37
44
  return (
38
- <ItemGroup>
39
- {data.map((item, index) => {
40
- const key = `${item.character ?? "unknown"}-${item.text}-${index}`;
41
- return (
42
- <Item key={key} variant="outline">
43
- {item.character && (
44
- <ItemMedia variant="image">
45
- <HistoryItemAvatar icon={item.icon} character={item.character} />
46
- </ItemMedia>
47
- )}
48
- <ItemContent
49
- className={!item.character ? "items-center text-center" : undefined}
50
- >
51
- {item.character && <ItemTitle>{item.character}</ItemTitle>}
52
- <Markdown
53
- remarkPlugins={[remarkGfm]}
54
- rehypePlugins={[rehypeRaw]}
55
- components={{
56
- p: ({ children, id }) => (
57
- <p key={id} className="m-0 text-sm text-muted-foreground">
58
- {children}
59
- </p>
60
- ),
61
- }}
45
+ <>
46
+ <ItemGroup>
47
+ {data.map((item, index) => {
48
+ const key = `${item.character ?? "unknown"}-${item.text}-${index}`;
49
+ return (
50
+ <Item key={key} variant="outline">
51
+ {item.character && (
52
+ <ItemMedia variant="image">
53
+ <HistoryItemAvatar
54
+ icon={item.icon}
55
+ character={item.character}
56
+ />
57
+ </ItemMedia>
58
+ )}
59
+ <ItemContent
60
+ className={!item.character ? "items-center text-center" : undefined}
62
61
  >
63
- {item.text}
64
- </Markdown>
65
- </ItemContent>
66
- {(item.choices?.some((c) => !c.hidden) || item.inputValue) && (
67
- <ItemFooter className="flex-wrap justify-start gap-1.5">
68
- {item.choices?.map((choice) => {
69
- const choiceKey = `${choice.text}-${choice.isResponse ? "1" : "0"}-${choice.hidden ? "1" : "0"}`;
70
- if (choice.hidden) {
71
- return null;
72
- }
73
- if (choice.isResponse) {
62
+ {item.character && <ItemTitle>{item.character}</ItemTitle>}
63
+ <Markdown
64
+ remarkPlugins={[remarkGfm]}
65
+ rehypePlugins={[rehypeRaw]}
66
+ components={{
67
+ p: ({ children, id }) => (
68
+ <p
69
+ key={id}
70
+ className="m-0 text-sm text-muted-foreground"
71
+ >
72
+ {children}
73
+ </p>
74
+ ),
75
+ }}
76
+ >
77
+ {item.text}
78
+ </Markdown>
79
+ </ItemContent>
80
+ {(item.choices?.some((c) => !c.hidden) || item.inputValue) && (
81
+ <ItemFooter className="flex-wrap justify-center gap-1.5">
82
+ {item.choices?.map((choice) => {
83
+ const choiceKey = `${choice.text}-${choice.isResponse ? "1" : "0"}-${choice.hidden ? "1" : "0"}`;
84
+ if (choice.hidden) {
85
+ return null;
86
+ }
87
+ if (choice.isResponse) {
88
+ return (
89
+ <Kbd
90
+ key={`choices-success-${choiceKey}`}
91
+ className={cn(
92
+ "h-auto border px-2 py-1",
93
+ "border-green-500/30 bg-green-500/10 text-green-700 dark:text-green-400",
94
+ )}
95
+ >
96
+ {choice.text}
97
+ <Check className="size-3" />
98
+ </Kbd>
99
+ );
100
+ }
74
101
  return (
75
102
  <Kbd
76
- key={`choices-success-${choiceKey}`}
103
+ key={`choices-${choiceKey}`}
77
104
  className={cn(
78
105
  "h-auto border px-2 py-1",
79
- "border-green-500/30 bg-green-500/10 text-green-700 dark:text-green-400",
106
+ "border-primary/30 bg-primary/10 text-primary",
80
107
  )}
81
108
  >
82
109
  {choice.text}
83
- <Check className="size-3" />
84
110
  </Kbd>
85
111
  );
86
- }
87
- return (
88
- <Kbd
89
- key={`choices-${choiceKey}`}
90
- className={cn(
91
- "h-auto border px-2 py-1",
92
- "border-primary/30 bg-primary/10 text-primary",
93
- )}
94
- >
95
- {choice.text}
112
+ })}
113
+ {item.inputValue && (
114
+ <Kbd className="h-auto px-2 py-1">
115
+ {item.inputValue.toString()}
96
116
  </Kbd>
97
- );
98
- })}
99
- {item.inputValue && (
100
- <Kbd className="h-auto px-2 py-1">
101
- {item.inputValue.toString()}
102
- </Kbd>
103
- )}
104
- </ItemFooter>
105
- )}
106
- </Item>
107
- );
108
- })}
109
- </ItemGroup>
117
+ )}
118
+ </ItemFooter>
119
+ )}
120
+ </Item>
121
+ );
122
+ })}
123
+ </ItemGroup>
124
+ <div ref={bottomRef} />
125
+ </>
110
126
  );
111
127
  }
112
128
 
@@ -14,7 +14,7 @@ import rehypeRaw from "rehype-raw";
14
14
  import remarkGfm from "remark-gfm";
15
15
 
16
16
  export function InputRequestDialog() {
17
- const { data: { animatedText: text } = {} } = useQueryDialogue();
17
+ const { data: { lastText: text } = {} } = useQueryDialogue();
18
18
  const {
19
19
  data: { isRequired, type, currentValue } = { currentValue: undefined, isRequired: false },
20
20
  } = useQueryInputValue<string | number>();
@@ -223,7 +223,9 @@ function QuickActionsWheelContent({
223
223
  >
224
224
  <span className="font-semibold">{registration.label}</span>
225
225
  <span className="text-[11px] opacity-85">
226
- {registration.hotkeyLabel}
226
+ {registration.hotkeyLabel.length > 15
227
+ ? `${registration.hotkeyLabel.slice(0, 12)}…`
228
+ : registration.hotkeyLabel}
227
229
  </span>
228
230
  </button>
229
231
  );
@@ -1,3 +1,4 @@
1
+ import { AlertDialogState } from "@/lib/stores/alert-dialog-store";
1
2
  import { createContext, type ReactNode, useCallback, useContext, useState } from "react";
2
3
  import { useTranslation } from "react-i18next";
3
4
  import {
@@ -47,6 +48,7 @@ export function AlertDialogProvider({ children }: { children: ReactNode }) {
47
48
 
48
49
  const closeDialog = useCallback((id: string) => {
49
50
  setDialogs((prev) => prev.map((d) => (d.id === id ? { ...d, open: false } : d)));
51
+ AlertDialogState.decrement();
50
52
  setTimeout(() => {
51
53
  setDialogs((prev) => prev.filter((d) => d.id !== id));
52
54
  }, DIALOG_CLOSE_ANIMATION_DURATION_MS);
@@ -54,6 +56,7 @@ export function AlertDialogProvider({ children }: { children: ReactNode }) {
54
56
 
55
57
  const openAlertDialog = useCallback((options: AlertDialogOptions) => {
56
58
  const id = generateId();
59
+ AlertDialogState.increment();
57
60
  setDialogs((prev) => [...prev, { id, open: true, loading: false, options }]);
58
61
  }, []);
59
62
 
@@ -1,10 +1,12 @@
1
1
  import { ChoiceMenu } from "@/components/menus/choice-menus";
2
2
  import { NarrationCards } from "@/components/screens/narration/narration-cards";
3
3
  import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable";
4
+ import { QuickTools } from "@/components/quick-tools";
4
5
  import { useQueryDialogue } from "@/lib/query/narration-query";
5
6
 
6
7
  export function NarrationScreen() {
7
8
  const { data: { animatedText, text } = {} } = useQueryDialogue();
9
+ const hasText = !!(animatedText || text);
8
10
 
9
11
  return (
10
12
  <div className="absolute flex h-full w-full flex-col">
@@ -13,17 +15,18 @@ export function NarrationScreen() {
13
15
  <ResizablePanel>
14
16
  <ChoiceMenu />
15
17
  </ResizablePanel>
16
- {(animatedText || text) && (
18
+ {hasText && (
17
19
  <div className="mx-4">
18
20
  <ResizableHandle />
19
21
  </div>
20
22
  )}
21
- {(animatedText || text) && (
23
+ {hasText && (
22
24
  <ResizablePanel defaultSize={"40%"}>
23
25
  <NarrationCards />
24
26
  </ResizablePanel>
25
27
  )}
26
28
  </ResizablePanelGroup>
29
+ {!hasText && <QuickTools />}
27
30
  </div>
28
31
  </div>
29
32
  );
@@ -1,4 +1,4 @@
1
- import { AnimatedDots } from "@/components/loading";
1
+ import { DelayedAnimatedDots } from "@/components/loading";
2
2
  import { QuickTools } from "@/components/quick-tools";
3
3
  import { Card, CardContent } from "@/components/ui/card";
4
4
  import { Image } from "@/components/ui/image";
@@ -8,7 +8,7 @@ import { useNarrationPointerHandlers } from "@/lib/hooks/narration-hooks";
8
8
  import { useQueryDialogue } from "@/lib/query/narration-query";
9
9
  import { TextDisplaySettings } from "@/lib/stores/text-display-settings-store";
10
10
  import { useSelector } from "@tanstack/react-store";
11
- import { type RefObject, useCallback, useRef } from "react";
11
+ import { type RefObject, memo, useCallback, useMemo, useRef } from "react";
12
12
  import Markdown from "react-markdown";
13
13
  import { MarkdownTypewriterHooks } from "react-markdown-typewriter";
14
14
  import rehypeRaw from "rehype-raw";
@@ -63,9 +63,13 @@ export function NarrationCards() {
63
63
  );
64
64
  }
65
65
 
66
- export function Text({ paragraphRef }: { paragraphRef: RefObject<HTMLDivElement | null> }) {
66
+ export const Text = memo(function Text({
67
+ paragraphRef,
68
+ }: {
69
+ paragraphRef: RefObject<HTMLDivElement | null>;
70
+ }) {
67
71
  const typewriterDelay = useSelector(TextDisplaySettings.store, (state) => state.delay);
68
- const { data: { animatedText, text } = {} } = useQueryDialogue();
72
+ const { data: { animatedText, text } = {}, finalizeDialogue } = useQueryDialogue();
69
73
 
70
74
  const handleCharacterAnimationComplete = useCallback(
71
75
  (ref: { current: HTMLSpanElement | null }) => {
@@ -74,7 +78,6 @@ export function Text({ paragraphRef }: { paragraphRef: RefObject<HTMLDivElement
74
78
  if (container && char) {
75
79
  const containerRect = container.getBoundingClientRect();
76
80
  const charRect = char.getBoundingClientRect();
77
- // Position of the character relative to the top of the scroll container
78
81
  const charOffsetInContainer =
79
82
  charRect.top - containerRect.top + container.scrollTop;
80
83
  const scrollTop = charOffsetInContainer - container.clientHeight / 2;
@@ -87,15 +90,40 @@ export function Text({ paragraphRef }: { paragraphRef: RefObject<HTMLDivElement
87
90
  [paragraphRef],
88
91
  );
89
92
 
93
+ const markdownComponents = useMemo(() => ({ p: (props: object) => <span {...props} /> }), []);
94
+
95
+ const motionProps = useMemo(
96
+ () => ({
97
+ onAnimationStart: TextDisplaySettings.start,
98
+ onAnimationComplete: (definition: "visible" | "hidden") => {
99
+ if (definition === "visible") {
100
+ finalizeDialogue();
101
+ TextDisplaySettings.end();
102
+ }
103
+ },
104
+ onCharacterAnimationComplete: handleCharacterAnimationComplete,
105
+ }),
106
+ [finalizeDialogue, handleCharacterAnimationComplete],
107
+ );
108
+
109
+ const specialCharacters = useMemo(
110
+ () => ({
111
+ ".": { delayAfter: typewriterDelay + 300 },
112
+ "!": { delayAfter: typewriterDelay + 300 },
113
+ "?": { delayAfter: typewriterDelay + 300 },
114
+ ",": { delayAfter: typewriterDelay + 75 },
115
+ ":": { delay: typewriterDelay + 50, delayAfter: typewriterDelay + 150 },
116
+ }),
117
+ [typewriterDelay],
118
+ );
119
+
90
120
  return (
91
121
  <p className="prose dark:prose-invert m-0 max-w-full p-0">
92
122
  <span>
93
123
  <Markdown
94
124
  remarkPlugins={[remarkGfm]}
95
125
  rehypePlugins={[rehypeRaw]}
96
- components={{
97
- p: (props) => <span {...props} />,
98
- }}
126
+ components={markdownComponents}
99
127
  >
100
128
  {text}
101
129
  </Markdown>
@@ -106,23 +134,16 @@ export function Text({ paragraphRef }: { paragraphRef: RefObject<HTMLDivElement
106
134
  remarkPlugins={[remarkGfm]}
107
135
  rehypePlugins={[rehypeRaw]}
108
136
  delay={typewriterDelay}
109
- motionProps={{
110
- onAnimationStart: TextDisplaySettings.start,
111
- onAnimationComplete: (definition: "visible" | "hidden") => {
112
- if (definition === "visible") {
113
- TextDisplaySettings.end();
114
- }
115
- },
116
- onCharacterAnimationComplete: handleCharacterAnimationComplete,
117
- }}
118
- fallback={<AnimatedDots />}
137
+ motionProps={motionProps}
138
+ fallback={<DelayedAnimatedDots />}
139
+ specialCharacters={specialCharacters}
119
140
  >
120
141
  {animatedText}
121
142
  </MarkdownTypewriterHooks>
122
143
  </span>
123
144
  </p>
124
145
  );
125
- }
146
+ });
126
147
 
127
148
  export function CharacterIcon({ alt, icon }: { icon: string; alt: string }) {
128
149
  return (
@@ -1,7 +1,8 @@
1
+ import * as React from "react";
1
2
  import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog";
2
- import type * as React from "react";
3
- import { Button } from "@/components/ui/button";
3
+
4
4
  import { cn } from "@/lib/utils";
5
+ import { Button } from "@/components/ui/button";
5
6
 
6
7
  function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {
7
8
  return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
@@ -1,5 +1,5 @@
1
+ import * as React from "react";
1
2
  import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar";
2
- import type * as React from "react";
3
3
 
4
4
  import { cn } from "@/lib/utils";
5
5
 
@@ -88,4 +88,4 @@ function AvatarGroupCount({ className, ...props }: React.ComponentProps<"div">)
88
88
  );
89
89
  }
90
90
 
91
- export { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage };
91
+ export { Avatar, AvatarImage, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarBadge };
@@ -1,8 +1,9 @@
1
- import { cn } from "@/lib/utils";
1
+ import * as React from "react";
2
2
  import { mergeProps } from "@base-ui/react/merge-props";
3
3
  import { useRender } from "@base-ui/react/use-render";
4
+
5
+ import { cn } from "@/lib/utils";
4
6
  import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react";
5
- import type * as React from "react";
6
7
 
7
8
  function Breadcrumb({ className, ...props }: React.ComponentProps<"nav">) {
8
9
  return (
@@ -93,10 +94,10 @@ function BreadcrumbEllipsis({ className, ...props }: React.ComponentProps<"span"
93
94
 
94
95
  export {
95
96
  Breadcrumb,
96
- BreadcrumbEllipsis,
97
+ BreadcrumbList,
97
98
  BreadcrumbItem,
98
99
  BreadcrumbLink,
99
- BreadcrumbList,
100
100
  BreadcrumbPage,
101
101
  BreadcrumbSeparator,
102
+ BreadcrumbEllipsis,
102
103
  };
@@ -1,9 +1,10 @@
1
- import { Separator } from "@/components/ui/separator";
2
- import { cn } from "@/lib/utils";
3
1
  import { mergeProps } from "@base-ui/react/merge-props";
4
2
  import { useRender } from "@base-ui/react/use-render";
5
3
  import { cva, type VariantProps } from "class-variance-authority";
6
4
 
5
+ import { cn } from "@/lib/utils";
6
+ import { Separator } from "@/components/ui/separator";
7
+
7
8
  const buttonGroupVariants = cva(
8
9
  "flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-lg [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
9
10
  {
@@ -8,11 +8,11 @@ const buttonVariants = cva(
8
8
  {
9
9
  variants: {
10
10
  variant: {
11
- default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
11
+ default: "bg-primary text-primary-foreground hover:bg-primary/80",
12
12
  outline:
13
13
  "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
14
14
  secondary:
15
- "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
15
+ "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
16
16
  ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
17
17
  destructive:
18
18
  "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",