@toife/vue 2.2.0 → 3.0.1

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 (364) hide show
  1. package/README.md +224 -0
  2. package/package.json +39 -10
  3. package/src/components/action/action.composable.ts +32 -0
  4. package/src/components/action/action.html +25 -0
  5. package/src/components/action/action.md +115 -0
  6. package/src/components/action/action.scss +105 -0
  7. package/src/components/action/action.type.ts +35 -0
  8. package/src/components/action/action.vue +70 -0
  9. package/src/components/action/index.ts +9 -0
  10. package/src/components/app/app.constants.ts +1 -0
  11. package/src/components/app/app.html +24 -0
  12. package/src/components/app/app.md +77 -0
  13. package/src/components/app/app.scss +27 -0
  14. package/src/components/app/app.type.ts +21 -0
  15. package/src/components/app/app.vue +45 -0
  16. package/src/components/app/index.ts +3 -0
  17. package/src/components/avatar/avatar.html +3 -0
  18. package/src/components/avatar/avatar.md +64 -0
  19. package/src/components/avatar/avatar.scss +35 -0
  20. package/src/components/avatar/avatar.type.ts +6 -0
  21. package/src/components/avatar/avatar.vue +45 -0
  22. package/src/components/avatar/index.ts +2 -0
  23. package/src/components/button/button.html +6 -0
  24. package/src/components/button/button.md +66 -0
  25. package/src/components/button/button.scss +113 -0
  26. package/src/components/button/button.type.ts +14 -0
  27. package/src/components/button/button.vue +61 -0
  28. package/src/components/button/index.ts +2 -0
  29. package/src/components/cable/cable.constants.ts +1 -0
  30. package/src/components/cable/cable.html +3 -0
  31. package/src/components/cable/cable.md +57 -0
  32. package/src/components/cable/cable.scss +37 -0
  33. package/src/components/cable/cable.type.ts +11 -0
  34. package/src/components/cable/cable.vue +33 -0
  35. package/src/components/cable/index.ts +3 -0
  36. package/src/components/card/card/card.constants.ts +1 -0
  37. package/src/components/card/card/card.html +3 -0
  38. package/src/components/card/card/card.md +57 -0
  39. package/src/components/card/card/card.scss +34 -0
  40. package/src/components/card/card/card.type.ts +14 -0
  41. package/src/components/card/card/card.vue +62 -0
  42. package/src/components/card/card/index.ts +3 -0
  43. package/src/components/card/card-body/card-body.html +3 -0
  44. package/src/components/card/card-body/card-body.md +34 -0
  45. package/src/components/card/card-body/card-body.scss +23 -0
  46. package/src/components/card/card-body/card-body.vue +9 -0
  47. package/src/components/card/card-body/index.ts +1 -0
  48. package/src/components/card/card-footer/card-footer.html +3 -0
  49. package/src/components/card/card-footer/card-footer.md +42 -0
  50. package/src/components/card/card-footer/card-footer.scss +31 -0
  51. package/src/components/card/card-footer/card-footer.vue +25 -0
  52. package/src/components/card/card-footer/index.ts +1 -0
  53. package/src/components/card/card-header/card-header.html +3 -0
  54. package/src/components/card/card-header/card-header.md +44 -0
  55. package/src/components/card/card-header/card-header.scss +31 -0
  56. package/src/components/card/card-header/card-header.vue +25 -0
  57. package/src/components/card/card-header/index.ts +1 -0
  58. package/src/components/card/index.ts +4 -0
  59. package/src/components/checkbox/checkbox.html +13 -0
  60. package/src/components/checkbox/checkbox.md +60 -0
  61. package/src/components/checkbox/checkbox.scss +138 -0
  62. package/src/components/checkbox/checkbox.type.ts +17 -0
  63. package/src/components/checkbox/checkbox.vue +78 -0
  64. package/src/components/checkbox/index.ts +2 -0
  65. package/src/components/collapse/collapse.html +16 -0
  66. package/src/components/collapse/collapse.md +59 -0
  67. package/src/components/collapse/collapse.scss +59 -0
  68. package/src/components/collapse/collapse.type.ts +11 -0
  69. package/src/components/collapse/collapse.vue +131 -0
  70. package/src/components/collapse/index.ts +2 -0
  71. package/src/components/container/container.html +1 -0
  72. package/src/components/container/container.md +38 -0
  73. package/src/components/container/container.scss +10 -0
  74. package/src/components/container/container.vue +9 -0
  75. package/src/components/container/index.ts +1 -0
  76. package/src/components/decision-modal/decision-modal.composable.ts +32 -0
  77. package/src/components/decision-modal/decision-modal.html +29 -0
  78. package/src/components/decision-modal/decision-modal.md +79 -0
  79. package/src/components/decision-modal/decision-modal.scss +136 -0
  80. package/src/components/decision-modal/decision-modal.type.ts +35 -0
  81. package/src/components/decision-modal/decision-modal.vue +98 -0
  82. package/src/components/decision-modal/index.ts +9 -0
  83. package/src/components/divider/divider.html +1 -0
  84. package/src/components/divider/divider.md +42 -0
  85. package/src/components/divider/divider.scss +29 -0
  86. package/src/components/divider/divider.type.ts +6 -0
  87. package/src/components/divider/divider.vue +31 -0
  88. package/src/components/divider/index.ts +2 -0
  89. package/src/components/field/field.html +1 -0
  90. package/src/components/field/field.md +68 -0
  91. package/src/components/field/field.type.ts +43 -0
  92. package/src/components/field/field.vue +85 -0
  93. package/src/components/field/index.ts +2 -0
  94. package/src/components/field/outline/index.ts +1 -0
  95. package/src/components/field/outline/outline-field.md +44 -0
  96. package/src/components/field/outline/outline.html +32 -0
  97. package/src/components/field/outline/outline.scss +224 -0
  98. package/src/components/field/outline/outline.vue +243 -0
  99. package/src/components/form-group/form-group.html +3 -0
  100. package/src/components/form-group/form-group.md +41 -0
  101. package/src/components/form-group/form-group.scss +91 -0
  102. package/src/components/form-group/form-group.type.ts +5 -0
  103. package/src/components/form-group/form-group.vue +21 -0
  104. package/src/components/form-group/index.ts +2 -0
  105. package/src/components/gesture-indicator/gesture-indicator.html +1 -0
  106. package/src/components/gesture-indicator/gesture-indicator.md +42 -0
  107. package/src/components/gesture-indicator/gesture-indicator.scss +45 -0
  108. package/{dist/components/gesture-indicator/gesture-indicator.type.d.ts → src/components/gesture-indicator/gesture-indicator.type.ts} +2 -1
  109. package/src/components/gesture-indicator/gesture-indicator.vue +29 -0
  110. package/src/components/gesture-indicator/index.ts +1 -0
  111. package/src/components/image/image.html +1 -0
  112. package/src/components/image/image.md +41 -0
  113. package/src/components/image/image.scss +1 -0
  114. package/src/components/image/image.type.ts +5 -0
  115. package/src/components/image/image.vue +25 -0
  116. package/src/components/image/index.ts +2 -0
  117. package/src/components/index.ts +27 -0
  118. package/src/components/modal/index.ts +2 -0
  119. package/src/components/modal/modal.html +20 -0
  120. package/src/components/modal/modal.md +65 -0
  121. package/src/components/modal/modal.scss +78 -0
  122. package/src/components/modal/modal.type.ts +21 -0
  123. package/src/components/modal/modal.vue +186 -0
  124. package/src/components/page/index.ts +1 -0
  125. package/src/components/page/page.html +3 -0
  126. package/src/components/page/page.md +39 -0
  127. package/src/components/page/page.scss +17 -0
  128. package/src/components/page/page.vue +9 -0
  129. package/src/components/present/index.ts +3 -0
  130. package/src/components/present/present.composable.ts +21 -0
  131. package/src/components/present/present.html +9 -0
  132. package/src/components/present/present.md +60 -0
  133. package/src/components/present/present.scss +81 -0
  134. package/src/components/present/present.type.ts +26 -0
  135. package/src/components/present/present.vue +198 -0
  136. package/src/components/radio/index.ts +2 -0
  137. package/src/components/radio/radio/index.ts +2 -0
  138. package/src/components/radio/radio/radio.html +11 -0
  139. package/src/components/radio/radio/radio.md +53 -0
  140. package/src/components/radio/radio/radio.scss +125 -0
  141. package/src/components/radio/radio/radio.type.ts +11 -0
  142. package/src/components/radio/radio/radio.vue +99 -0
  143. package/src/components/radio/radio-group/index.ts +7 -0
  144. package/src/components/radio/radio-group/radio-group.constants.ts +1 -0
  145. package/src/components/radio/radio-group/radio-group.html +3 -0
  146. package/src/components/radio/radio-group/radio-group.md +62 -0
  147. package/src/components/radio/radio-group/radio-group.scss +16 -0
  148. package/src/components/radio/radio-group/radio-group.type.ts +28 -0
  149. package/src/components/radio/radio-group/radio-group.vue +57 -0
  150. package/src/components/refresher/index.ts +2 -0
  151. package/src/components/refresher/refresher.html +6 -0
  152. package/src/components/refresher/refresher.md +53 -0
  153. package/src/components/refresher/refresher.scss +36 -0
  154. package/src/components/refresher/refresher.type.ts +16 -0
  155. package/src/components/refresher/refresher.vue +137 -0
  156. package/src/components/route/index.ts +5 -0
  157. package/src/components/route/route-navigator/index.ts +2 -0
  158. package/src/components/route/route-navigator/route-navigator.html +19 -0
  159. package/src/components/route/route-navigator/route-navigator.md +50 -0
  160. package/src/components/route/route-navigator/route-navigator.scss +127 -0
  161. package/src/components/route/route-navigator/route-navigator.type.ts +12 -0
  162. package/src/components/route/route-navigator/route-navigator.vue +255 -0
  163. package/src/components/route/route-outlet/index.ts +1 -0
  164. package/src/components/route/route-outlet/route-outlet.html +1 -0
  165. package/src/components/route/route-outlet/route-outlet.md +30 -0
  166. package/src/components/route/route-outlet/route-outlet.vue +30 -0
  167. package/src/components/route/route-provider/index.ts +3 -0
  168. package/src/components/route/route-provider/route-provider.constant.ts +1 -0
  169. package/src/components/route/route-provider/route-provider.html +1 -0
  170. package/src/components/route/route-provider/route-provider.md +46 -0
  171. package/src/components/route/route-provider/route-provider.type.ts +10 -0
  172. package/src/components/route/route-provider/route-provider.vue +20 -0
  173. package/src/components/route/route-wrapper/index.ts +3 -0
  174. package/src/components/route/route-wrapper/route-wrapper.composable.ts +58 -0
  175. package/src/components/route/route-wrapper/route-wrapper.html +3 -0
  176. package/src/components/route/route-wrapper/route-wrapper.md +45 -0
  177. package/src/components/route/route-wrapper/route-wrapper.type.ts +7 -0
  178. package/src/components/route/route-wrapper/route-wrapper.vue +51 -0
  179. package/src/components/route/route.type.ts +8 -0
  180. package/src/components/route/route.util.ts +8 -0
  181. package/src/components/segmented-field/index.ts +7 -0
  182. package/src/components/segmented-field/segmented-field.html +17 -0
  183. package/src/components/segmented-field/segmented-field.md +58 -0
  184. package/src/components/segmented-field/segmented-field.scss +52 -0
  185. package/src/components/segmented-field/segmented-field.type.ts +29 -0
  186. package/src/components/segmented-field/segmented-field.vue +145 -0
  187. package/src/components/skeleton/index.ts +2 -0
  188. package/src/components/skeleton/skeleton.html +1 -0
  189. package/src/components/skeleton/skeleton.md +47 -0
  190. package/src/components/skeleton/skeleton.scss +45 -0
  191. package/src/components/skeleton/skeleton.type.ts +7 -0
  192. package/src/components/skeleton/skeleton.vue +38 -0
  193. package/src/components/switch/index.ts +2 -0
  194. package/src/components/switch/switch.html +15 -0
  195. package/src/components/switch/switch.md +57 -0
  196. package/src/components/switch/switch.scss +134 -0
  197. package/src/components/switch/switch.type.ts +13 -0
  198. package/src/components/switch/switch.vue +81 -0
  199. package/src/components/tabs/index.ts +2 -0
  200. package/src/components/tabs/tab/index.ts +2 -0
  201. package/src/components/tabs/tab/tab.html +5 -0
  202. package/src/components/tabs/tab/tab.md +52 -0
  203. package/src/components/tabs/tab/tab.type.ts +5 -0
  204. package/src/components/tabs/tab/tab.vue +38 -0
  205. package/src/components/tabs/tabs/index.ts +9 -0
  206. package/src/components/tabs/tabs/tabs.constants.ts +1 -0
  207. package/src/components/tabs/tabs/tabs.html +3 -0
  208. package/src/components/tabs/tabs/tabs.md +59 -0
  209. package/src/components/tabs/tabs/tabs.scss +270 -0
  210. package/src/components/tabs/tabs/tabs.type.ts +36 -0
  211. package/src/components/tabs/tabs/tabs.vue +157 -0
  212. package/src/components/toast/index.ts +4 -0
  213. package/src/components/toast/toast/index.ts +1 -0
  214. package/src/components/toast/toast/toast.html +9 -0
  215. package/src/components/toast/toast/toast.md +56 -0
  216. package/src/components/toast/toast/toast.scss +61 -0
  217. package/src/components/toast/toast/toast.vue +34 -0
  218. package/src/components/toast/toast-content/index.ts +1 -0
  219. package/src/components/toast/toast-content/toast-content.html +1 -0
  220. package/src/components/toast/toast-content/toast-content.md +41 -0
  221. package/src/components/toast/toast-content/toast-content.scss +41 -0
  222. package/src/components/toast/toast-content/toast-content.vue +53 -0
  223. package/src/components/toast/toast.composable.ts +22 -0
  224. package/src/components/toast/toast.type.ts +25 -0
  225. package/src/components/toolbar/index.ts +2 -0
  226. package/src/components/toolbar/toolbar.html +5 -0
  227. package/src/components/toolbar/toolbar.md +57 -0
  228. package/src/components/toolbar/toolbar.scss +79 -0
  229. package/src/components/toolbar/toolbar.type.ts +7 -0
  230. package/src/components/toolbar/toolbar.vue +41 -0
  231. package/src/env.d.ts +7 -0
  232. package/src/factory.ts +83 -0
  233. package/src/index.ts +4 -0
  234. package/{dist/type.d.ts → src/type.ts} +1 -1
  235. package/src/utils/element.md +33 -0
  236. package/src/utils/element.ts +16 -0
  237. package/src/utils/events.md +29 -0
  238. package/src/utils/events.ts +12 -0
  239. package/src/utils/index.ts +3 -0
  240. package/src/utils/style/index.ts +42 -0
  241. package/src/utils/style.md +49 -0
  242. package/dist/components/action/action.type.d.ts +0 -17
  243. package/dist/components/action/action.vue.d.ts +0 -14
  244. package/dist/components/action/factory.d.ts +0 -3
  245. package/dist/components/action/index.d.ts +0 -2
  246. package/dist/components/alert/alert.type.d.ts +0 -16
  247. package/dist/components/alert/alert.vue.d.ts +0 -14
  248. package/dist/components/alert/factory.d.ts +0 -3
  249. package/dist/components/alert/index.d.ts +0 -2
  250. package/dist/components/app/app.type.d.ts +0 -1
  251. package/dist/components/app/app.vue.d.ts +0 -3
  252. package/dist/components/app/index.d.ts +0 -1
  253. package/dist/components/avatar/avatar.type.d.ts +0 -4
  254. package/dist/components/avatar/avatar.vue.d.ts +0 -6
  255. package/dist/components/avatar/index.d.ts +0 -1
  256. package/dist/components/back-button/back-button.type.d.ts +0 -4
  257. package/dist/components/back-button/back-button.vue.d.ts +0 -3
  258. package/dist/components/back-button/index.d.ts +0 -1
  259. package/dist/components/button/button.type.d.ts +0 -10
  260. package/dist/components/button/button.vue.d.ts +0 -12
  261. package/dist/components/button/index.d.ts +0 -1
  262. package/dist/components/cable/cable.type.d.ts +0 -4
  263. package/dist/components/cable/cable.vue.d.ts +0 -6
  264. package/dist/components/cable/index.d.ts +0 -1
  265. package/dist/components/card/card.type.d.ts +0 -3
  266. package/dist/components/card/card.vue.d.ts +0 -5
  267. package/dist/components/card/index.d.ts +0 -1
  268. package/dist/components/checkbox/checkbox.type.d.ts +0 -12
  269. package/dist/components/checkbox/checkbox.vue.d.ts +0 -14
  270. package/dist/components/checkbox/index.d.ts +0 -1
  271. package/dist/components/collapse/collapse.type.d.ts +0 -6
  272. package/dist/components/collapse/collapse.vue.d.ts +0 -7
  273. package/dist/components/collapse/index.d.ts +0 -1
  274. package/dist/components/content/content.type.d.ts +0 -1
  275. package/dist/components/content/content.vue.d.ts +0 -3
  276. package/dist/components/content/index.d.ts +0 -1
  277. package/dist/components/divider/divider.type.d.ts +0 -3
  278. package/dist/components/divider/divider.vue.d.ts +0 -5
  279. package/dist/components/divider/index.d.ts +0 -1
  280. package/dist/components/flex/flex.type.d.ts +0 -4
  281. package/dist/components/flex/flex.vue.d.ts +0 -6
  282. package/dist/components/flex/index.d.ts +0 -1
  283. package/dist/components/gesture-indicator/gesture-indicator.vue.d.ts +0 -5
  284. package/dist/components/gesture-indicator/index.d.ts +0 -1
  285. package/dist/components/grid/grid.type.d.ts +0 -4
  286. package/dist/components/grid/grid.vue.d.ts +0 -6
  287. package/dist/components/grid/index.d.ts +0 -1
  288. package/dist/components/icon-spinner/icon-spinner.type.d.ts +0 -4
  289. package/dist/components/icon-spinner/icon-spinner.vue.d.ts +0 -6
  290. package/dist/components/icon-spinner/index.d.ts +0 -1
  291. package/dist/components/image/image.type.d.ts +0 -4
  292. package/dist/components/image/image.vue.d.ts +0 -3
  293. package/dist/components/image/index.d.ts +0 -1
  294. package/dist/components/index.d.ts +0 -36
  295. package/dist/components/input/index.d.ts +0 -1
  296. package/dist/components/input/input.type.d.ts +0 -15
  297. package/dist/components/input/input.vue.d.ts +0 -16
  298. package/dist/components/keyboard-space/factory.d.ts +0 -3
  299. package/dist/components/keyboard-space/index.d.ts +0 -2
  300. package/dist/components/keyboard-space/keyboard-space.type.d.ts +0 -1
  301. package/dist/components/keyboard-space/keyboard-space.vue.d.ts +0 -3
  302. package/dist/components/loading/factory.d.ts +0 -4
  303. package/dist/components/loading/index.d.ts +0 -2
  304. package/dist/components/loading/loading.type.d.ts +0 -6
  305. package/dist/components/loading/loading.vue.d.ts +0 -12
  306. package/dist/components/present/factory.d.ts +0 -1
  307. package/dist/components/present/index.d.ts +0 -2
  308. package/dist/components/present/present.type.d.ts +0 -13
  309. package/dist/components/present/present.vue.d.ts +0 -17
  310. package/dist/components/refresher/index.d.ts +0 -1
  311. package/dist/components/refresher/refresher.type.d.ts +0 -11
  312. package/dist/components/refresher/refresher.vue.d.ts +0 -17
  313. package/dist/components/richtext/index.d.ts +0 -1
  314. package/dist/components/richtext/richtext.type.d.ts +0 -1
  315. package/dist/components/richtext/richtext.vue.d.ts +0 -3
  316. package/dist/components/ripple/index.d.ts +0 -1
  317. package/dist/components/ripple/ripple.type.d.ts +0 -3
  318. package/dist/components/ripple/ripple.vue.d.ts +0 -5
  319. package/dist/components/screen/index.d.ts +0 -1
  320. package/dist/components/screen/screen.type.d.ts +0 -1
  321. package/dist/components/screen/screen.vue.d.ts +0 -3
  322. package/dist/components/screen-router/factory.d.ts +0 -19
  323. package/dist/components/screen-router/index.d.ts +0 -2
  324. package/dist/components/screen-router/screen-router.type.d.ts +0 -8
  325. package/dist/components/screen-router/screen-router.vue.d.ts +0 -9
  326. package/dist/components/sheet/index.d.ts +0 -1
  327. package/dist/components/sheet/sheet.type.d.ts +0 -18
  328. package/dist/components/sheet/sheet.vue.d.ts +0 -18
  329. package/dist/components/skeleton/index.d.ts +0 -1
  330. package/dist/components/skeleton/skeleton.type.d.ts +0 -6
  331. package/dist/components/skeleton/skeleton.vue.d.ts +0 -8
  332. package/dist/components/switch/index.d.ts +0 -1
  333. package/dist/components/switch/switch.type.d.ts +0 -7
  334. package/dist/components/switch/switch.vue.d.ts +0 -9
  335. package/dist/components/tab/index.d.ts +0 -1
  336. package/dist/components/tab/tab.type.d.ts +0 -4
  337. package/dist/components/tab/tab.vue.d.ts +0 -5
  338. package/dist/components/tabs/index.d.ts +0 -1
  339. package/dist/components/tabs/tabs.type.d.ts +0 -13
  340. package/dist/components/tabs/tabs.vue.d.ts +0 -15
  341. package/dist/components/text/index.d.ts +0 -1
  342. package/dist/components/text/text.type.d.ts +0 -4
  343. package/dist/components/text/text.vue.d.ts +0 -6
  344. package/dist/components/textarea/index.d.ts +0 -1
  345. package/dist/components/textarea/textarea.type.d.ts +0 -1
  346. package/dist/components/textarea/textarea.vue.d.ts +0 -3
  347. package/dist/components/toast/factory.d.ts +0 -3
  348. package/dist/components/toast/index.d.ts +0 -2
  349. package/dist/components/toast/toast.type.d.ts +0 -11
  350. package/dist/components/toast/toast.vue.d.ts +0 -16
  351. package/dist/components/toggle-password/index.d.ts +0 -1
  352. package/dist/components/toggle-password/toggle-password.type.d.ts +0 -6
  353. package/dist/components/toggle-password/toggle-password.vue.d.ts +0 -9
  354. package/dist/components/toolbar/index.d.ts +0 -1
  355. package/dist/components/toolbar/toolbar.type.d.ts +0 -5
  356. package/dist/components/toolbar/toolbar.vue.d.ts +0 -7
  357. package/dist/factory.d.ts +0 -4
  358. package/dist/index.css +0 -1
  359. package/dist/index.d.ts +0 -4
  360. package/dist/index.es.js +0 -1836
  361. package/dist/index.umd.js +0 -1
  362. package/dist/utils/element.d.ts +0 -2
  363. package/dist/utils/events.d.ts +0 -1
  364. package/dist/utils/index.d.ts +0 -2
@@ -0,0 +1,137 @@
1
+ <style lang="scss" src="./refresher.scss" scoped></style>
2
+ <template src="./refresher.html"></template>
3
+ <script lang="ts" setup>
4
+ import { ref, onUnmounted, watch, computed } from "vue";
5
+ import { gesture } from "@toife/gesture";
6
+ import type { RefresherProps, RefresherEmit } from "./refresher.type";
7
+ import { property, withPrefix } from "../../utils";
8
+
9
+ /// Define
10
+ /// ------------------------------------------------------------
11
+ const emit = defineEmits<RefresherEmit>();
12
+ const props = withDefaults(defineProps<RefresherProps>(), {
13
+ threshold: 120,
14
+ variant: "max",
15
+ offset: undefined,
16
+ });
17
+
18
+ /// State
19
+ /// ------------------------------------------------------------
20
+ const moveOffset = ref(0);
21
+ const refreshing = ref(false);
22
+ const container = ref();
23
+ let cleanup: unknown;
24
+ let locked = false;
25
+
26
+ /// Computed
27
+ /// ------------------------------------------------------------
28
+ const calculateOffset = computed(() => {
29
+ return props.offset !== undefined ? props.offset : moveOffset.value / 2;
30
+ });
31
+
32
+ const refresherAttrs = computed(() => {
33
+ return {
34
+ style: {
35
+ [property("refresher-offset")]: `${calculateOffset.value}px`,
36
+ },
37
+ class: [
38
+ withPrefix("refresher"),
39
+ {
40
+ moving: calculateOffset.value > 0,
41
+ },
42
+ ],
43
+ };
44
+ });
45
+
46
+ const containerAttrs = computed(() => {
47
+ return {
48
+ class: [withPrefix("refresher-container")],
49
+ };
50
+ });
51
+
52
+ /// Methods
53
+ /// ------------------------------------------------------------
54
+ const close = () => {
55
+ refreshing.value = false;
56
+ moveOffset.value = 0;
57
+ locked = false;
58
+ };
59
+
60
+ const start = () => {
61
+ locked = true;
62
+ refreshing.value = true;
63
+ moveOffset.value = props.threshold;
64
+ emit("refresh", close);
65
+ };
66
+
67
+ const cancel = () => {
68
+ moveOffset.value = 0;
69
+ refreshing.value = false;
70
+ locked = false;
71
+ emit("cancel");
72
+ };
73
+
74
+ /// Lifecycle
75
+ /// ------------------------------------------------------------
76
+ watch(
77
+ () => container.value,
78
+ () => {
79
+ cleanup && (cleanup as { destroy: () => void }).destroy();
80
+ if (!container.value) return;
81
+ cleanup = gesture(
82
+ container.value,
83
+ {
84
+ options: {
85
+ minMove: 20,
86
+ },
87
+
88
+ beforeEvent() {
89
+ if (container.value.scrollTop > 0) return false;
90
+ return true;
91
+ },
92
+
93
+ down() {
94
+ if (refreshing.value || locked) return;
95
+ emit("start");
96
+ },
97
+
98
+ move({ deltaY, initialDirection }: unknown) {
99
+ if (refreshing.value || locked || initialDirection != "down") return;
100
+
101
+ const v = deltaY < 0 ? 0 : deltaY;
102
+ moveOffset.value = v;
103
+ emit("move", v);
104
+
105
+ if (props.variant == "max") {
106
+ if (deltaY >= props.threshold) {
107
+ start();
108
+ return;
109
+ }
110
+ }
111
+ },
112
+ up({ deltaY, initialDirection }: unknown) {
113
+ if (refreshing.value || locked || initialDirection != "down") return;
114
+
115
+ // max
116
+ if (props.variant == "up" && deltaY >= props.threshold) {
117
+ start();
118
+ } else {
119
+ cancel();
120
+ }
121
+ },
122
+ cancel() {
123
+ if (refreshing.value || locked) return;
124
+ cancel();
125
+ },
126
+ },
127
+ {
128
+ passive: false,
129
+ }
130
+ );
131
+ }
132
+ );
133
+
134
+ onUnmounted(() => {
135
+ cleanup && (cleanup as { destroy: () => void }).destroy();
136
+ });
137
+ </script>
@@ -0,0 +1,5 @@
1
+ export * from "./route-navigator";
2
+ export * from "./route-wrapper";
3
+ export * from "./route-provider";
4
+ export * from "./route-outlet";
5
+ export * from "./route.type";
@@ -0,0 +1,2 @@
1
+ export { default as RouteNavigator } from "./route-navigator.vue";
2
+ export * from "./route-navigator.type";
@@ -0,0 +1,19 @@
1
+ <div v-bind="navigatorAttrs" ref="navigatorRef">
2
+ <div
3
+ v-for="(item, index) in stack"
4
+ :key="item.name"
5
+ v-bind="componentAttrs"
6
+ :style="{zIndex: index * 2}"
7
+ :name="item.name"
8
+ :class="{
9
+ active: index === activeIndex,
10
+ prepare: index === activeIndex + 1,
11
+ back: index === activeIndex - 1,
12
+ }"
13
+ >
14
+ <RouteProvider :stack="item.stack">
15
+ <RouteOutlet :component="item.component" />
16
+ </RouteProvider>
17
+ </div>
18
+ <div v-bind="backdropAttrs"></div>
19
+ </div>
@@ -0,0 +1,50 @@
1
+ # `<t-route-navigator>`
2
+
3
+ > Default prefix is `t-` — change via `createToife({ prefix: "..." })`.
4
+
5
+ ## Description
6
+
7
+ Displays a stack of screens with transitions and optional edge swipe to `router.back()` when `variant="swipe"`. Listens to `stack` from `RouteProvider`.
8
+
9
+ ## Requirements / dependencies
10
+
11
+ | Item | Notes |
12
+ | ------------ | ------------------------------------------------------------------------ |
13
+ | Vue | ^3.5 |
14
+ | `vue-router` | **Required** |
15
+ | Other | `@toife/gesture`; `RouteProvider` ancestor (usually via `RouteWrapper`). |
16
+
17
+ ## Basic usage
18
+
19
+ ```vue
20
+ <t-route-wrapper>
21
+ <t-route-navigator variant="swipe" direction="right" />
22
+ </t-route-wrapper>
23
+ ```
24
+
25
+ ## Props
26
+
27
+ | Prop | Type | Default | Description |
28
+ | ----------- | ------------------- | --------- | ----------------------------------------- |
29
+ | `direction` | `"left" \| "right"` | `"right"` | Gesture / animation direction. |
30
+ | `variant` | `"none" \| "swipe"` | `"none"` | Enables swipe navigation when not `none`. |
31
+ | `keepalive` | `boolean` | `false` | Reserved for stack/DOM retention. |
32
+
33
+ **Type source:** `src/components/route/route-navigator/route-navigator.type.ts`
34
+
35
+ ## Events (emits)
36
+
37
+ _None._
38
+
39
+ ## Slots
40
+
41
+ _None_ — fixed structure: stack loop → `RouteProvider` + `RouteOutlet`.
42
+
43
+ ## Special behavior
44
+
45
+ - Swipe along `direction`: preview transform; release past ~60% width → `goBack()`.
46
+ - `fast` swipe calls `router.back()`.
47
+
48
+ ## See also
49
+
50
+ - Source: `src/components/route/route-navigator`
@@ -0,0 +1,127 @@
1
+ @use "@toife/sass-layer-generator" as sass;
2
+
3
+ // Classes
4
+ $navigator: sass.fn-naming-prefix("route-navigator");
5
+ $navigator-component: sass.fn-naming-prefix("route-navigator-component");
6
+ $navigator-backdrop: sass.fn-naming-prefix("route-navigator-backdrop");
7
+
8
+ // Property name
9
+ $background-color: sass.fn-naming-var("app", "background-color");
10
+ $transition-duration: sass.fn-naming-dvar(
11
+ ("route-navigator-transition-duration"),
12
+ sass.fn-naming-var("motion", "duration")
13
+ );
14
+ $transform-back: sass.fn-naming-var("route-navigator-transform", "back");
15
+ $transform-prepare: sass.fn-naming-var("route-navigator-transform", "prepare");
16
+ $transform-active: sass.fn-naming-var("route-navigator-transform", "active");
17
+ $backdrop-percent: sass.fn-naming-var("route-navigator-backdrop-percent");
18
+ $backdrop-opacity: sass.fn-naming-var("backdrop", "opacity");
19
+ $backdrop-background-color: sass.fn-naming-var("backdrop", "background-color");
20
+
21
+ // Properties
22
+ .#{$navigator} {
23
+ width: 100%;
24
+ height: 100%;
25
+ display: flex;
26
+ flex-wrap: nowrap;
27
+ overflow: hidden;
28
+ justify-content: flex-end;
29
+ position: relative;
30
+
31
+ &.right {
32
+ flex-direction: row;
33
+ }
34
+
35
+ &.left {
36
+ flex-direction: row-reverse;
37
+ }
38
+
39
+ &.up {
40
+ flex-direction: column;
41
+ }
42
+
43
+ &.down {
44
+ flex-direction: column-reverse;
45
+ }
46
+
47
+ .#{$navigator-backdrop} {
48
+ position: absolute;
49
+ width: 100%;
50
+ height: 100%;
51
+ top: 0;
52
+ left: 0;
53
+ background-color: rgb(#{$backdrop-background-color});
54
+ opacity: calc(#{$backdrop-opacity} * (#{$backdrop-percent} / 100));
55
+ transition: opacity #{$transition-duration} ease;
56
+ }
57
+
58
+ .#{$navigator-component} {
59
+ width: 100%;
60
+ height: 100%;
61
+ position: absolute;
62
+ max-width: 100%;
63
+ max-height: 100%;
64
+ top: 0;
65
+ left: 0;
66
+ flex: none;
67
+ background-color: rgb(#{$background-color});
68
+ transform: translate(0, 0);
69
+ transition:
70
+ transform #{$transition-duration} ease,
71
+ background-color #{$transition-duration} ease;
72
+
73
+ &.active {
74
+ &.right {
75
+ transform: translateX(#{$transform-active});
76
+ }
77
+
78
+ &.left {
79
+ transform: translateX(calc(-1 * #{$transform-active}));
80
+ }
81
+
82
+ &.up {
83
+ transform: translateY(calc(-1 * #{$transform-active}));
84
+ }
85
+
86
+ &.down {
87
+ transform: translateY(#{$transform-active});
88
+ }
89
+ }
90
+
91
+ &.prepare {
92
+ &.right {
93
+ transform: translateX(#{$transform-prepare});
94
+ }
95
+
96
+ &.left {
97
+ transform: translateX(calc(-1 * #{$transform-prepare}));
98
+ }
99
+
100
+ &.up {
101
+ transform: translateY(calc(-1 * #{$transform-prepare}));
102
+ }
103
+
104
+ &.down {
105
+ transform: translateY(#{$transform-prepare});
106
+ }
107
+ }
108
+
109
+ &.back {
110
+ &.right {
111
+ transform: translateX(calc(-1 * #{$transform-back}));
112
+ }
113
+
114
+ &.left {
115
+ transform: translateX(#{$transform-back});
116
+ }
117
+
118
+ &.up {
119
+ transform: translateY(#{$transform-back});
120
+ }
121
+
122
+ &.down {
123
+ transform: translateY(calc(-1 * #{$transform-back}));
124
+ }
125
+ }
126
+ }
127
+ }
@@ -0,0 +1,12 @@
1
+ export type RouteNavigatorVariant = "none" | "swipe";
2
+
3
+ export type RouteNavigatorProps = {
4
+ direction?: "left" | "right";
5
+ variant?: RouteNavigatorVariant;
6
+ keepalive?: boolean;
7
+ };
8
+
9
+ export type RouteNavigatorGesture = {
10
+ deltaX: number;
11
+ deltaY: number;
12
+ };
@@ -0,0 +1,255 @@
1
+ <style lang="scss" src="./route-navigator.scss" scoped></style>
2
+ <template src="./route-navigator.html"></template>
3
+ <script lang="ts" setup>
4
+ import { computed, inject, onMounted, onUnmounted, reactive, ref, watch } from "vue";
5
+ import { gesture } from "@toife/gesture";
6
+ import { withPrefix, property } from "../../../utils";
7
+ import type { RouteNavigatorProps } from "./route-navigator.type";
8
+ import {
9
+ ROUTE_PROVIDER_STATE_KEY,
10
+ RouteProvider,
11
+ type RouteProviderState,
12
+ } from "../route-provider";
13
+ import { RouteOutlet } from "../route-outlet";
14
+ import type { RouteNavigatorGesture } from "./route-navigator.type";
15
+ import type { RouteStack } from "../route.type";
16
+ import { useRouter } from "vue-router";
17
+ import { clone } from "../route.util";
18
+
19
+ // Max translate offset (%) for the layer behind the active page during swipe.
20
+ // Active uses 0–100%; back uses (peek)*(100−percent)/100, so a peek of 40 makes the
21
+ // back layer move 2.5× slower than the active layer (parallax). Use 100 for 1:1 motion
22
+ // (no edge peek at rest: back starts at -100%).
23
+ const BACK_LAYER_PEEK_PCT = 40;
24
+
25
+ /// Define
26
+ /// ------------------------------------------------------------
27
+ const props = withDefaults(defineProps<RouteNavigatorProps>(), {
28
+ direction: "right",
29
+ variant: "none",
30
+ keepalive: false,
31
+ });
32
+ const provider = inject<RouteProviderState>(ROUTE_PROVIDER_STATE_KEY);
33
+ const router = useRouter();
34
+ /// State
35
+ /// ------------------------------------------------------------
36
+ const navigatorRef = ref<HTMLElement>();
37
+ const ges = ref<unknown>(null);
38
+ const transform = reactive({
39
+ back: BACK_LAYER_PEEK_PCT,
40
+ prepare: 100,
41
+ active: 0,
42
+ backdrop: 0,
43
+ duration: undefined as string | undefined,
44
+ });
45
+ const stack = ref<RouteStack[]>([]);
46
+ const activeIndex = ref(0);
47
+ const backdropIndex = ref(0);
48
+
49
+ /// Computed
50
+ /// ------------------------------------------------------------
51
+ const navigatorAttrs = computed(() => {
52
+ let duration =
53
+ transform.duration !== undefined ? transform.duration : transform.active > 0 ? "0s" : undefined;
54
+
55
+ if (props.variant === "none") {
56
+ duration = "0s";
57
+ }
58
+
59
+ return {
60
+ class: [withPrefix("route-navigator"), props.direction, props.variant],
61
+ style: {
62
+ [property("route-navigator-transform-back")]: transform.back + "%",
63
+ [property("route-navigator-transform-prepare")]: transform.prepare + "%",
64
+ [property("route-navigator-transform-active")]: transform.active + "%",
65
+ [property("route-navigator-transition-duration")]: duration,
66
+ [property("route-navigator-backdrop-percent")]: transform.backdrop,
67
+ },
68
+ };
69
+ });
70
+
71
+ const componentAttrs = computed(() => {
72
+ return {
73
+ class: [withPrefix("route-navigator-component"), props.direction],
74
+ };
75
+ });
76
+
77
+ const backdropAttrs = computed(() => {
78
+ return {
79
+ class: [withPrefix("route-navigator-backdrop"), withPrefix(["layer", "backdrop"])],
80
+ style: {
81
+ zIndex: backdropIndex.value * 2 - 1,
82
+ },
83
+ };
84
+ });
85
+
86
+ const prevPage = computed(() => {
87
+ if (activeIndex.value > 0) {
88
+ return stack.value.at(activeIndex.value - 1) ?? null;
89
+ }
90
+ return null;
91
+ });
92
+
93
+ /// Methods
94
+ /// ------------------------------------------------------------
95
+ const changeRoute = (value: RouteStack[]) => {
96
+ const data = clone(value);
97
+
98
+ // Case: first time
99
+ if (stack.value.length === 0) {
100
+ stack.value = data;
101
+ return;
102
+ }
103
+
104
+ // Case: update
105
+ if (stack.value.length === data.length) {
106
+ const ln = stack.value.length - 1;
107
+ stack.value[ln].stack = data[ln].stack;
108
+ }
109
+ // Case: back
110
+ else if (stack.value.length > data.length) {
111
+ const newIndex = activeIndex.value - 1;
112
+ resetTransform();
113
+ activeIndex.value = newIndex;
114
+ transform.backdrop = 0;
115
+ setTimeout(() => {
116
+ stack.value = stack.value.slice(0, -1);
117
+ backdropIndex.value = newIndex;
118
+ transform.backdrop = 100;
119
+ }, 250);
120
+ }
121
+ // Case: next
122
+ else {
123
+ stack.value.push(data[data.length - 1]);
124
+ transform.duration = "0s";
125
+ transform.backdrop = 0;
126
+
127
+ setTimeout(() => {
128
+ backdropIndex.value = backdropIndex.value + 1;
129
+ transform.duration = undefined;
130
+ }, 10);
131
+
132
+ setTimeout(() => {
133
+ transform.backdrop = 100;
134
+ activeIndex.value = stack.value.length - 1;
135
+ }, 100);
136
+ }
137
+ };
138
+
139
+ const goBack = () => {
140
+ const url = stack.value[activeIndex.value - 1].fullPath;
141
+ router.push(url);
142
+ };
143
+
144
+ const resetTransform = () => {
145
+ transform.back = BACK_LAYER_PEEK_PCT;
146
+ transform.prepare = 100;
147
+ transform.active = 0;
148
+ };
149
+
150
+ const move = (data: RouteNavigatorGesture) => {
151
+ console.log(stack.value);
152
+ const width = navigatorRef.value?.offsetWidth ?? 0;
153
+ let percent = 0;
154
+
155
+ if (props.direction == "left" || props.direction == "right") {
156
+ percent = (Math.abs(data.deltaX) / width) * 100;
157
+ } else {
158
+ percent = (Math.abs(data.deltaY) / width) * 100;
159
+ }
160
+
161
+ transform.back = ((100 - percent) * BACK_LAYER_PEEK_PCT) / 100;
162
+ transform.active = percent;
163
+ transform.backdrop = 100 - transform.active;
164
+ };
165
+
166
+ const up = (data: RouteNavigatorGesture) => {
167
+ const width = navigatorRef.value?.offsetWidth ?? 0;
168
+ let percent = 0;
169
+
170
+ if (props.direction == "left" || props.direction == "right") {
171
+ percent = (Math.abs(data.deltaX) / width) * 100;
172
+ } else {
173
+ percent = (Math.abs(data.deltaY) / width) * 100;
174
+ }
175
+
176
+ if (percent >= 60) {
177
+ goBack();
178
+ } else {
179
+ resetTransform();
180
+ }
181
+ };
182
+
183
+ /// Lifecycle
184
+ /// ------------------------------------------------------------
185
+ watch(
186
+ () => provider?.stack.value,
187
+ (value) => {
188
+ changeRoute(value as RouteStack[]);
189
+ }
190
+ );
191
+
192
+ onMounted(() => {
193
+ changeRoute(provider?.stack.value as RouteStack[]);
194
+
195
+ // Initialize gesture
196
+ ges.value =
197
+ navigatorRef.value &&
198
+ gesture(navigatorRef.value, {
199
+ beforeEvent(e: Event) {
200
+ const target = e.target as HTMLElement | null;
201
+ const isEditable = target?.closest("input, textarea, select, button, [contenteditable]");
202
+ if (isEditable || props.variant === "none") return false;
203
+ e.stopPropagation();
204
+ return prevPage.value;
205
+ },
206
+
207
+ fast({ initialDirection, event }: { initialDirection: string; event: Event }) {
208
+ if (initialDirection !== props.direction) return;
209
+ event.stopPropagation();
210
+ event.preventDefault();
211
+ goBack();
212
+ },
213
+
214
+ move({
215
+ deltaX,
216
+ deltaY,
217
+ initialDirection,
218
+ event,
219
+ }: {
220
+ deltaX: number;
221
+ deltaY: number;
222
+ initialDirection: string;
223
+ event: Event;
224
+ }) {
225
+ if (initialDirection !== props.direction) return;
226
+ event.preventDefault();
227
+ move({ deltaX, deltaY });
228
+ },
229
+
230
+ up({
231
+ deltaX,
232
+ deltaY,
233
+ initialDirection,
234
+ event,
235
+ }: {
236
+ deltaX: number;
237
+ deltaY: number;
238
+ initialDirection: string;
239
+ event: Event;
240
+ }) {
241
+ if (initialDirection !== props.direction) return;
242
+ event.preventDefault();
243
+ up({ deltaX, deltaY });
244
+ },
245
+
246
+ cancel() {
247
+ resetTransform();
248
+ },
249
+ });
250
+ });
251
+
252
+ onUnmounted(() => {
253
+ if (ges.value) (ges.value as { destroy: () => void }).destroy();
254
+ });
255
+ </script>
@@ -0,0 +1 @@
1
+ export { default as RouteOutlet } from "./route-outlet.vue";
@@ -0,0 +1 @@
1
+ <component :is="renderComponent" v-if="renderComponent"></component>
@@ -0,0 +1,30 @@
1
+ # `<t-route-outlet>`
2
+
3
+ > Default prefix is `t-` — change via `createToife({ prefix: "..." })`.
4
+
5
+ ## Description
6
+
7
+ Resolves and renders a route component (sync or async dynamic import).
8
+
9
+ ## Requirements / dependencies
10
+
11
+ | Item | Notes |
12
+ | ----- | ------------------------------------------------------------- |
13
+ | Vue | ^3.5 |
14
+ | Other | Used inside `RouteNavigator` with `component` from the stack. |
15
+
16
+ ## Props
17
+
18
+ | Prop | Type | Description |
19
+ | ----------- | --------- | ---------------------------------------------------------- |
20
+ | `component` | `unknown` | Route component (may be `{ default: () => import(...) }`). |
21
+
22
+ _(Inline type in `route-outlet.vue`.)_
23
+
24
+ ## Slots
25
+
26
+ _None_ — renders `<component :is="…">`.
27
+
28
+ ## See also
29
+
30
+ - Source: `src/components/route/route-outlet`
@@ -0,0 +1,30 @@
1
+ <template src="./route-outlet.html"></template>
2
+ <script lang="ts" setup>
3
+ import { markRaw, onMounted, ref } from "vue";
4
+
5
+ /// Define
6
+ /// ------------------------------------------------------------
7
+ const props = defineProps<{
8
+ component: unknown;
9
+ }>();
10
+
11
+ /// State
12
+ /// ------------------------------------------------------------
13
+ const renderComponent = ref<unknown | null>(null);
14
+
15
+ /// Methods
16
+ /// ------------------------------------------------------------
17
+ const resolveComponent = async (raw: unknown): Promise<unknown> => {
18
+ if (typeof raw !== "function") return raw;
19
+ const mod = await (raw as () => Promise<{ default?: unknown }>)();
20
+ return mod?.default ?? mod;
21
+ };
22
+
23
+ /// Lifecycle
24
+ /// ------------------------------------------------------------
25
+ onMounted(async () => {
26
+ const c = props.component as { default?: unknown };
27
+ const component = await resolveComponent(c?.default);
28
+ renderComponent.value = component ? markRaw(component) : null;
29
+ });
30
+ </script>
@@ -0,0 +1,3 @@
1
+ export { default as RouteProvider } from "./route-provider.vue";
2
+ export * from "./route-provider.type";
3
+ export * from "./route-provider.constant";
@@ -0,0 +1 @@
1
+ export const ROUTE_PROVIDER_STATE_KEY = "route-provider-state";