create-wakii-stack 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (998) hide show
  1. package/README.md +66 -2
  2. package/dist/chunk-7XGW4UJ5.js +75 -0
  3. package/dist/chunk-AKPWS7FJ.js +76 -0
  4. package/dist/chunk-ELM6GGC5.js +50 -0
  5. package/dist/chunk-ON2WTGZH.js +77 -0
  6. package/dist/index.js +385 -0
  7. package/dist/manifest-2JVLRMDB.js +10 -0
  8. package/dist/manifest-O35TPW73.js +10 -0
  9. package/dist/manifest-TXTY67BF.js +10 -0
  10. package/dist/manifest-XWHR7Y3F.js +10 -0
  11. package/package.json +23 -4
  12. package/stack-template/.changeset/config.json +15 -0
  13. package/stack-template/.changeset/vu53-ui-redesign.md +11 -0
  14. package/stack-template/.claude/agents/be-dev.md +56 -0
  15. package/stack-template/.claude/agents/contracts-keeper.md +51 -0
  16. package/stack-template/.claude/agents/e2e-runner.md +61 -0
  17. package/stack-template/.claude/agents/fe-dev.md +53 -0
  18. package/stack-template/.claude/settings.json +77 -0
  19. package/stack-template/.claude/settings.local.json +9 -0
  20. package/stack-template/.claude/skills/add-service/SKILL.md +81 -0
  21. package/stack-template/.claude/skills/sync-contracts/SKILL.md +74 -0
  22. package/stack-template/.editorconfig +21 -0
  23. package/stack-template/.gitattributes +10 -0
  24. package/stack-template/.github/pull_request_template.md +26 -0
  25. package/stack-template/.github/workflow-templates/services-ci.yml.example +69 -0
  26. package/stack-template/.github/workflows/contracts.yml +133 -0
  27. package/stack-template/.github/workflows/convergence.yml +209 -0
  28. package/stack-template/.github/workflows/git-guard.yml +44 -0
  29. package/stack-template/.github/workflows/publish-uikit.yml +96 -0
  30. package/stack-template/.github/workflows/remotes-activity.yml +82 -0
  31. package/stack-template/.github/workflows/remotes-tasks.yml +82 -0
  32. package/stack-template/.github/workflows/services-auth-svc.yml +153 -0
  33. package/stack-template/.github/workflows/services-go-svc.yml +281 -0
  34. package/stack-template/.github/workflows/services-node-svc.yml +173 -0
  35. package/stack-template/.github/workflows/services-spring-svc.yml +132 -0
  36. package/stack-template/.github/workflows/shell.yml +78 -0
  37. package/stack-template/.github/workflows/ui-kit.yml +51 -0
  38. package/stack-template/.husky/commit-msg +14 -0
  39. package/stack-template/.husky/pre-push +51 -0
  40. package/stack-template/.spectral.yaml +17 -0
  41. package/stack-template/AGENTS.md +197 -0
  42. package/stack-template/CLAUDE.md +114 -0
  43. package/stack-template/README.md +172 -0
  44. package/stack-template/app/admin/index.html +12 -0
  45. package/stack-template/app/admin/package.json +40 -0
  46. package/stack-template/app/admin/scripts/verify-chart.mjs +49 -0
  47. package/stack-template/app/admin/src/App.test.tsx +70 -0
  48. package/stack-template/app/admin/src/App.tsx +33 -0
  49. package/stack-template/app/admin/src/data/users.ts +47 -0
  50. package/stack-template/app/admin/src/layout/AdminLayout.tsx +212 -0
  51. package/stack-template/app/admin/src/main.tsx +17 -0
  52. package/stack-template/app/admin/src/pages/ComponentsDemo.tsx +138 -0
  53. package/stack-template/app/admin/src/pages/Dashboard.tsx +182 -0
  54. package/stack-template/app/admin/src/pages/HooksDemo.tsx +153 -0
  55. package/stack-template/app/admin/src/pages/Settings.tsx +156 -0
  56. package/stack-template/app/admin/src/pages/UploadPage.tsx +34 -0
  57. package/stack-template/app/admin/src/pages/Users.test.tsx +66 -0
  58. package/stack-template/app/admin/src/pages/Users.tsx +245 -0
  59. package/stack-template/app/admin/src/styles.css +9 -0
  60. package/stack-template/app/admin/src/tests/setup.ts +15 -0
  61. package/stack-template/app/admin/tsconfig.json +18 -0
  62. package/stack-template/app/admin/vite.config.ts +11 -0
  63. package/stack-template/app/admin/vitest.config.ts +14 -0
  64. package/stack-template/app/create-wakii-app/README.md +71 -0
  65. package/stack-template/app/create-wakii-app/package.json +27 -0
  66. package/stack-template/app/create-wakii-app/scripts/publish-npm.sh +38 -0
  67. package/stack-template/app/create-wakii-app/src/index.ts +127 -0
  68. package/stack-template/app/create-wakii-app/src/options.test.ts +80 -0
  69. package/stack-template/app/create-wakii-app/src/options.ts +117 -0
  70. package/stack-template/app/create-wakii-app/src/scaffold.test.ts +143 -0
  71. package/stack-template/app/create-wakii-app/src/scaffold.ts +194 -0
  72. package/stack-template/app/create-wakii-app/tsconfig.json +17 -0
  73. package/stack-template/app/create-wakii-app/vitest.config.ts +9 -0
  74. package/stack-template/app/create-wakii-stack/package.json +27 -0
  75. package/stack-template/app/create-wakii-stack/src/manifest.ts +101 -0
  76. package/stack-template/app/create-wakii-stack/src/options.ts +106 -0
  77. package/stack-template/app/create-wakii-stack/src/scaffold.ts +315 -0
  78. package/stack-template/app/create-wakii-stack/tsconfig.json +17 -0
  79. package/stack-template/app/create-wakii-stack/vitest.config.ts +9 -0
  80. package/stack-template/app/remotes/activity/Dockerfile +36 -0
  81. package/stack-template/app/remotes/activity/README.md +59 -0
  82. package/stack-template/app/remotes/activity/index.html +11 -0
  83. package/stack-template/app/remotes/activity/nginx.conf +35 -0
  84. package/stack-template/app/remotes/activity/package.json +40 -0
  85. package/stack-template/app/remotes/activity/rspack.config.mjs +152 -0
  86. package/stack-template/app/remotes/activity/src/ActivityPage.tsx +139 -0
  87. package/stack-template/app/remotes/activity/src/api.ts +63 -0
  88. package/stack-template/app/remotes/activity/src/app.css +7 -0
  89. package/stack-template/app/remotes/activity/src/components/FeedItem.tsx +39 -0
  90. package/stack-template/app/remotes/activity/src/components/StatTile.tsx +24 -0
  91. package/stack-template/app/remotes/activity/src/components/Timeline.tsx +53 -0
  92. package/stack-template/app/remotes/activity/src/components/time.ts +30 -0
  93. package/stack-template/app/remotes/activity/src/env.d.ts +5 -0
  94. package/stack-template/app/remotes/activity/src/index.tsx +12 -0
  95. package/stack-template/app/remotes/activity/src/standalone.tsx +36 -0
  96. package/stack-template/app/remotes/activity/tests/ActivityPage.test.tsx +260 -0
  97. package/stack-template/app/remotes/activity/tests/api.test.ts +61 -0
  98. package/stack-template/app/remotes/activity/tests/setup.ts +1 -0
  99. package/stack-template/app/remotes/activity/tests/test-utils.tsx +16 -0
  100. package/stack-template/app/remotes/activity/tsconfig.json +26 -0
  101. package/stack-template/app/remotes/activity/vitest.config.ts +38 -0
  102. package/stack-template/app/remotes/tasks/Dockerfile +36 -0
  103. package/stack-template/app/remotes/tasks/README.md +59 -0
  104. package/stack-template/app/remotes/tasks/index.html +11 -0
  105. package/stack-template/app/remotes/tasks/nginx.conf +35 -0
  106. package/stack-template/app/remotes/tasks/package.json +41 -0
  107. package/stack-template/app/remotes/tasks/rspack.config.mjs +153 -0
  108. package/stack-template/app/remotes/tasks/src/TasksPage.tsx +284 -0
  109. package/stack-template/app/remotes/tasks/src/api.ts +109 -0
  110. package/stack-template/app/remotes/tasks/src/app.css +7 -0
  111. package/stack-template/app/remotes/tasks/src/components/StatusBadge.tsx +20 -0
  112. package/stack-template/app/remotes/tasks/src/components/StatusSelect.tsx +27 -0
  113. package/stack-template/app/remotes/tasks/src/components/TaskForm.tsx +74 -0
  114. package/stack-template/app/remotes/tasks/src/components/TaskItem.tsx +199 -0
  115. package/stack-template/app/remotes/tasks/src/components/TaskList.tsx +60 -0
  116. package/stack-template/app/remotes/tasks/src/components/status.ts +23 -0
  117. package/stack-template/app/remotes/tasks/src/env.d.ts +5 -0
  118. package/stack-template/app/remotes/tasks/src/index.tsx +12 -0
  119. package/stack-template/app/remotes/tasks/src/standalone.tsx +38 -0
  120. package/stack-template/app/remotes/tasks/tests/TasksPage.test.tsx +445 -0
  121. package/stack-template/app/remotes/tasks/tests/api.test.ts +159 -0
  122. package/stack-template/app/remotes/tasks/tests/setup.ts +1 -0
  123. package/stack-template/app/remotes/tasks/tests/test-utils.tsx +16 -0
  124. package/stack-template/app/remotes/tasks/tsconfig.json +26 -0
  125. package/stack-template/app/remotes/tasks/vitest.config.ts +34 -0
  126. package/stack-template/app/shared/README.md +21 -0
  127. package/stack-template/app/shared/package.json +37 -0
  128. package/stack-template/app/shared/src/api-client.ts +66 -0
  129. package/stack-template/app/shared/src/error-envelope.ts +38 -0
  130. package/stack-template/app/shared/src/index.ts +21 -0
  131. package/stack-template/app/shared/src/mf-bootstrap.ts +89 -0
  132. package/stack-template/app/shared/src/refresh-client.ts +170 -0
  133. package/stack-template/app/shared/src/token-storage.ts +57 -0
  134. package/stack-template/app/shell/Dockerfile +37 -0
  135. package/stack-template/app/shell/README.md +79 -0
  136. package/stack-template/app/shell/index.html +11 -0
  137. package/stack-template/app/shell/nginx.conf +23 -0
  138. package/stack-template/app/shell/package.json +43 -0
  139. package/stack-template/app/shell/rspack.config.mjs +147 -0
  140. package/stack-template/app/shell/src/App.tsx +57 -0
  141. package/stack-template/app/shell/src/api.ts +36 -0
  142. package/stack-template/app/shell/src/app.css +11 -0
  143. package/stack-template/app/shell/src/bootstrap.tsx +24 -0
  144. package/stack-template/app/shell/src/components/Layout.tsx +35 -0
  145. package/stack-template/app/shell/src/components/NavBar.tsx +118 -0
  146. package/stack-template/app/shell/src/components/RemoteSlot.tsx +82 -0
  147. package/stack-template/app/shell/src/components/RequireAuth.tsx +14 -0
  148. package/stack-template/app/shell/src/env.d.ts +7 -0
  149. package/stack-template/app/shell/src/index.tsx +3 -0
  150. package/stack-template/app/shell/src/pages/HomePage.tsx +70 -0
  151. package/stack-template/app/shell/src/pages/LoginPage.tsx +217 -0
  152. package/stack-template/app/shell/src/remote-urls.ts +18 -0
  153. package/stack-template/app/shell/tests/a11y.test.tsx +53 -0
  154. package/stack-template/app/shell/tests/api-timeout.test.ts +43 -0
  155. package/stack-template/app/shell/tests/integration.test.tsx +93 -0
  156. package/stack-template/app/shell/tests/login.test.tsx +227 -0
  157. package/stack-template/app/shell/tests/mf-retry.test.ts +76 -0
  158. package/stack-template/app/shell/tests/refresh-client.test.ts +301 -0
  159. package/stack-template/app/shell/tests/remote-slot.test.tsx +109 -0
  160. package/stack-template/app/shell/tests/remote-urls.test.ts +26 -0
  161. package/stack-template/app/shell/tests/setup.ts +15 -0
  162. package/stack-template/app/shell/tests/shell-chrome.test.tsx +126 -0
  163. package/stack-template/app/shell/tsconfig.json +26 -0
  164. package/stack-template/app/shell/vitest.config.ts +42 -0
  165. package/stack-template/app/spike/README.md +35 -0
  166. package/stack-template/app/spike/host/index.html +11 -0
  167. package/stack-template/app/spike/host/package.json +17 -0
  168. package/stack-template/app/spike/host/rspack.config.mjs +34 -0
  169. package/stack-template/app/spike/host/src/bootstrap.jsx +26 -0
  170. package/stack-template/app/spike/host/src/index.jsx +3 -0
  171. package/stack-template/app/spike/remote/package.json +17 -0
  172. package/stack-template/app/spike/remote/rspack.config.mjs +36 -0
  173. package/stack-template/app/spike/remote/src/Hello.jsx +7 -0
  174. package/stack-template/app/spike/remote/src/index.js +2 -0
  175. package/stack-template/app/spike/serve.mjs +31 -0
  176. package/stack-template/app/starter-templates/template-feats/extras/carousel/src/DemoCarousel.tsx +99 -0
  177. package/stack-template/app/starter-templates/template-feats/extras/chart/src/DemoChart.tsx +84 -0
  178. package/stack-template/app/starter-templates/template-feats/extras/editor/src/DemoEditor.tsx +110 -0
  179. package/stack-template/app/starter-templates/template-feats/extras/schedule/src/DemoSchedule.tsx +81 -0
  180. package/stack-template/app/starter-templates/template-feats/router/src/App.tsx +332 -0
  181. package/stack-template/app/starter-templates/template-feats/router/src/main.tsx +14 -0
  182. package/stack-template/app/starter-templates/vite-js/README.md +72 -0
  183. package/stack-template/app/starter-templates/vite-js/index.html +12 -0
  184. package/stack-template/app/starter-templates/vite-js/jsconfig.json +10 -0
  185. package/stack-template/app/starter-templates/vite-js/package.json +22 -0
  186. package/stack-template/app/starter-templates/vite-js/src/App.jsx +158 -0
  187. package/stack-template/app/starter-templates/vite-js/src/main.jsx +10 -0
  188. package/stack-template/app/starter-templates/vite-js/src/styles.css +15 -0
  189. package/stack-template/app/starter-templates/vite-js/src/theme.js +21 -0
  190. package/stack-template/app/starter-templates/vite-js/vite.config.mjs +8 -0
  191. package/stack-template/app/starter-templates/vite-ts/README.md +53 -0
  192. package/stack-template/app/starter-templates/vite-ts/index.html +12 -0
  193. package/stack-template/app/starter-templates/vite-ts/package.json +29 -0
  194. package/stack-template/app/starter-templates/vite-ts/src/App.tsx +181 -0
  195. package/stack-template/app/starter-templates/vite-ts/src/main.tsx +12 -0
  196. package/stack-template/app/starter-templates/vite-ts/src/styles.css +21 -0
  197. package/stack-template/app/starter-templates/vite-ts/src/theme.ts +16 -0
  198. package/stack-template/app/starter-templates/vite-ts/tsconfig.json +25 -0
  199. package/stack-template/app/starter-templates/vite-ts/tsconfig.node.json +11 -0
  200. package/stack-template/app/starter-templates/vite-ts/vite.config.ts +10 -0
  201. package/stack-template/app/ui-kit/.storybook/main.ts +29 -0
  202. package/stack-template/app/ui-kit/.storybook/manager-head.html +97 -0
  203. package/stack-template/app/ui-kit/.storybook/manager.ts +138 -0
  204. package/stack-template/app/ui-kit/.storybook/preview-head.html +57 -0
  205. package/stack-template/app/ui-kit/.storybook/preview.ts +62 -0
  206. package/stack-template/app/ui-kit/.storybook/tailwind-preview.css +3 -0
  207. package/stack-template/app/ui-kit/.storybook/test-runner.config.ts +20 -0
  208. package/stack-template/app/ui-kit/CHANGELOG.md +137 -0
  209. package/stack-template/app/ui-kit/LICENSE +21 -0
  210. package/stack-template/app/ui-kit/MIGRATION.md +84 -0
  211. package/stack-template/app/ui-kit/README.md +173 -0
  212. package/stack-template/app/ui-kit/RELEASE.md +77 -0
  213. package/stack-template/app/ui-kit/USAGE.md +380 -0
  214. package/stack-template/app/ui-kit/eslint.config.js +47 -0
  215. package/stack-template/app/ui-kit/package.json +166 -0
  216. package/stack-template/app/ui-kit/scripts/publish-github.sh +39 -0
  217. package/stack-template/app/ui-kit/scripts/publish-npm.sh +76 -0
  218. package/stack-template/app/ui-kit/scripts/stamp-build.cjs +13 -0
  219. package/stack-template/app/ui-kit/src/KitchenSink.stories.tsx +576 -0
  220. package/stack-template/app/ui-kit/src/Tokens.stories.tsx +193 -0
  221. package/stack-template/app/ui-kit/src/entries/carousel.ts +7 -0
  222. package/stack-template/app/ui-kit/src/entries/chart.ts +4 -0
  223. package/stack-template/app/ui-kit/src/entries/editor.ts +4 -0
  224. package/stack-template/app/ui-kit/src/entries/experience3d.ts +5 -0
  225. package/stack-template/app/ui-kit/src/entries/schedule.ts +5 -0
  226. package/stack-template/app/ui-kit/src/env.d.ts +3 -0
  227. package/stack-template/app/ui-kit/src/hooks/form.stories.tsx +80 -0
  228. package/stack-template/app/ui-kit/src/hooks/hooks-new.stories.tsx +392 -0
  229. package/stack-template/app/ui-kit/src/hooks/hooks.stories.tsx +167 -0
  230. package/stack-template/app/ui-kit/src/hooks/useClickAway.test.tsx +63 -0
  231. package/stack-template/app/ui-kit/src/hooks/useClickAway.ts +30 -0
  232. package/stack-template/app/ui-kit/src/hooks/useControllableState.test.ts +36 -0
  233. package/stack-template/app/ui-kit/src/hooks/useControllableState.ts +41 -0
  234. package/stack-template/app/ui-kit/src/hooks/useCopyToClipboard.test.ts +89 -0
  235. package/stack-template/app/ui-kit/src/hooks/useCopyToClipboard.ts +20 -0
  236. package/stack-template/app/ui-kit/src/hooks/useCountdown.test.ts +88 -0
  237. package/stack-template/app/ui-kit/src/hooks/useCountdown.ts +38 -0
  238. package/stack-template/app/ui-kit/src/hooks/useDebounce.test.ts +71 -0
  239. package/stack-template/app/ui-kit/src/hooks/useDebounce.ts +14 -0
  240. package/stack-template/app/ui-kit/src/hooks/useDefault.test.ts +37 -0
  241. package/stack-template/app/ui-kit/src/hooks/useDefault.ts +15 -0
  242. package/stack-template/app/ui-kit/src/hooks/useEventListener.test.ts +47 -0
  243. package/stack-template/app/ui-kit/src/hooks/useEventListener.ts +28 -0
  244. package/stack-template/app/ui-kit/src/hooks/useFieldArray.test.tsx +160 -0
  245. package/stack-template/app/ui-kit/src/hooks/useFieldArray.ts +85 -0
  246. package/stack-template/app/ui-kit/src/hooks/useFocusTrap.ts +67 -0
  247. package/stack-template/app/ui-kit/src/hooks/useForm.test.tsx +192 -0
  248. package/stack-template/app/ui-kit/src/hooks/useForm.ts +119 -0
  249. package/stack-template/app/ui-kit/src/hooks/useFullscreen.test.tsx +71 -0
  250. package/stack-template/app/ui-kit/src/hooks/useFullscreen.ts +68 -0
  251. package/stack-template/app/ui-kit/src/hooks/useHover.test.tsx +30 -0
  252. package/stack-template/app/ui-kit/src/hooks/useHover.ts +23 -0
  253. package/stack-template/app/ui-kit/src/hooks/useInView.test.tsx +70 -0
  254. package/stack-template/app/ui-kit/src/hooks/useInView.ts +55 -0
  255. package/stack-template/app/ui-kit/src/hooks/useInfiniteScroll.test.tsx +72 -0
  256. package/stack-template/app/ui-kit/src/hooks/useInfiniteScroll.ts +45 -0
  257. package/stack-template/app/ui-kit/src/hooks/useIsFirstRender.test.ts +30 -0
  258. package/stack-template/app/ui-kit/src/hooks/useIsFirstRender.ts +14 -0
  259. package/stack-template/app/ui-kit/src/hooks/useKeyPress.test.ts +45 -0
  260. package/stack-template/app/ui-kit/src/hooks/useKeyPress.ts +31 -0
  261. package/stack-template/app/ui-kit/src/hooks/useLocalStorage.test.ts +102 -0
  262. package/stack-template/app/ui-kit/src/hooks/useLocalStorage.ts +34 -0
  263. package/stack-template/app/ui-kit/src/hooks/useLockBodyScroll.test.ts +42 -0
  264. package/stack-template/app/ui-kit/src/hooks/useLockBodyScroll.ts +13 -0
  265. package/stack-template/app/ui-kit/src/hooks/useMeasure.test.tsx +57 -0
  266. package/stack-template/app/ui-kit/src/hooks/useMeasure.ts +32 -0
  267. package/stack-template/app/ui-kit/src/hooks/useMediaQuery.test.ts +73 -0
  268. package/stack-template/app/ui-kit/src/hooks/useMediaQuery.ts +20 -0
  269. package/stack-template/app/ui-kit/src/hooks/useMountEffect.test.ts +22 -0
  270. package/stack-template/app/ui-kit/src/hooks/useMountEffect.ts +10 -0
  271. package/stack-template/app/ui-kit/src/hooks/useOnlineStatus.test.ts +36 -0
  272. package/stack-template/app/ui-kit/src/hooks/useOnlineStatus.ts +21 -0
  273. package/stack-template/app/ui-kit/src/hooks/usePrevious.test.ts +35 -0
  274. package/stack-template/app/ui-kit/src/hooks/usePrevious.ts +13 -0
  275. package/stack-template/app/ui-kit/src/hooks/useScrollProgress.test.ts +59 -0
  276. package/stack-template/app/ui-kit/src/hooks/useScrollProgress.ts +31 -0
  277. package/stack-template/app/ui-kit/src/hooks/useSessionStorage.test.ts +80 -0
  278. package/stack-template/app/ui-kit/src/hooks/useSessionStorage.ts +34 -0
  279. package/stack-template/app/ui-kit/src/hooks/useThrottle.test.ts +61 -0
  280. package/stack-template/app/ui-kit/src/hooks/useThrottle.ts +30 -0
  281. package/stack-template/app/ui-kit/src/hooks/useTimeout.test.ts +95 -0
  282. package/stack-template/app/ui-kit/src/hooks/useTimeout.ts +38 -0
  283. package/stack-template/app/ui-kit/src/hooks/useTitle.test.ts +34 -0
  284. package/stack-template/app/ui-kit/src/hooks/useTitle.ts +24 -0
  285. package/stack-template/app/ui-kit/src/hooks/useToggle.test.ts +46 -0
  286. package/stack-template/app/ui-kit/src/hooks/useToggle.ts +16 -0
  287. package/stack-template/app/ui-kit/src/hooks/useUpdateEffect.test.ts +25 -0
  288. package/stack-template/app/ui-kit/src/hooks/useUpdateEffect.ts +18 -0
  289. package/stack-template/app/ui-kit/src/hooks/useWindowSize.test.ts +33 -0
  290. package/stack-template/app/ui-kit/src/hooks/useWindowSize.ts +23 -0
  291. package/stack-template/app/ui-kit/src/index.ts +218 -0
  292. package/stack-template/app/ui-kit/src/intro-showcase.stories.tsx +272 -0
  293. package/stack-template/app/ui-kit/src/intro.docs.mdx +247 -0
  294. package/stack-template/app/ui-kit/src/motion/motion-showcase.stories.tsx +234 -0
  295. package/stack-template/app/ui-kit/src/motion/motion.md +38 -0
  296. package/stack-template/app/ui-kit/src/provider/index.tsx +77 -0
  297. package/stack-template/app/ui-kit/src/provider/provider.stories.tsx +87 -0
  298. package/stack-template/app/ui-kit/src/provider/provider.test.tsx +121 -0
  299. package/stack-template/app/ui-kit/src/styles/base.css +171 -0
  300. package/stack-template/app/ui-kit/src/styles/dark-theme.test.ts +21 -0
  301. package/stack-template/app/ui-kit/src/styles/tailwind.css +220 -0
  302. package/stack-template/app/ui-kit/src/styles/themes/dark.css +71 -0
  303. package/stack-template/app/ui-kit/src/styles/tokens.css +133 -0
  304. package/stack-template/app/ui-kit/src/styles/ui-kit.css +10 -0
  305. package/stack-template/app/ui-kit/src/templates/auth.stories.tsx +425 -0
  306. package/stack-template/app/ui-kit/src/templates/crud.stories.tsx +416 -0
  307. package/stack-template/app/ui-kit/src/templates/dashboard.stories.tsx +504 -0
  308. package/stack-template/app/ui-kit/src/templates/experience/chapters/ch1-deep-focus.tsx +96 -0
  309. package/stack-template/app/ui-kit/src/templates/experience/chapters/ch2-living-docs.tsx +134 -0
  310. package/stack-template/app/ui-kit/src/templates/experience/chapters/ch3-team-velocity.tsx +148 -0
  311. package/stack-template/app/ui-kit/src/templates/experience/chapters/ch4-ship-your-app.tsx +100 -0
  312. package/stack-template/app/ui-kit/src/templates/experience/chapters/ch5-future.tsx +67 -0
  313. package/stack-template/app/ui-kit/src/templates/experience/chapters/hero.tsx +434 -0
  314. package/stack-template/app/ui-kit/src/templates/experience/chapters/nav-footer.tsx +85 -0
  315. package/stack-template/app/ui-kit/src/templates/experience/hero.stories.tsx +27 -0
  316. package/stack-template/app/ui-kit/src/templates/experience/hero.test.tsx +108 -0
  317. package/stack-template/app/ui-kit/src/templates/experience/index.stories.tsx +51 -0
  318. package/stack-template/app/ui-kit/src/templates/experience/lib/ChapterShell.tsx +84 -0
  319. package/stack-template/app/ui-kit/src/templates/experience/lib/SideNav.tsx +173 -0
  320. package/stack-template/app/ui-kit/src/templates/experience/lib/chapter-shell.test.tsx +266 -0
  321. package/stack-template/app/ui-kit/src/templates/experience/lib/scroll-mood.tsx +143 -0
  322. package/stack-template/app/ui-kit/src/templates/experience/lib/starfield.test.tsx +31 -0
  323. package/stack-template/app/ui-kit/src/templates/experience/lib/starfield.tsx +190 -0
  324. package/stack-template/app/ui-kit/src/templates/experience/mood-engine.stories.tsx +114 -0
  325. package/stack-template/app/ui-kit/src/templates/experience/shell-nav.stories.tsx +113 -0
  326. package/stack-template/app/ui-kit/src/templates/kanban-project.stories.tsx +352 -0
  327. package/stack-template/app/ui-kit/src/templates/landing.stories.tsx +380 -0
  328. package/stack-template/app/ui-kit/src/templates/parallax-landing.stories.tsx +633 -0
  329. package/stack-template/app/ui-kit/src/templates/settings.stories.tsx +474 -0
  330. package/stack-template/app/ui-kit/src/ui/accordion/accordion.stories.tsx +91 -0
  331. package/stack-template/app/ui-kit/src/ui/accordion/accordion.test.tsx +99 -0
  332. package/stack-template/app/ui-kit/src/ui/accordion/index.tsx +107 -0
  333. package/stack-template/app/ui-kit/src/ui/affix/affix.stories.tsx +104 -0
  334. package/stack-template/app/ui-kit/src/ui/affix/affix.test.tsx +138 -0
  335. package/stack-template/app/ui-kit/src/ui/affix/index.tsx +89 -0
  336. package/stack-template/app/ui-kit/src/ui/alert/alert.stories.tsx +149 -0
  337. package/stack-template/app/ui-kit/src/ui/alert/alert.test.tsx +85 -0
  338. package/stack-template/app/ui-kit/src/ui/alert/index.tsx +118 -0
  339. package/stack-template/app/ui-kit/src/ui/anchor/anchor.stories.tsx +96 -0
  340. package/stack-template/app/ui-kit/src/ui/anchor/anchor.test.tsx +191 -0
  341. package/stack-template/app/ui-kit/src/ui/anchor/index.tsx +144 -0
  342. package/stack-template/app/ui-kit/src/ui/auto-complete/auto-complete.stories.tsx +67 -0
  343. package/stack-template/app/ui-kit/src/ui/auto-complete/auto-complete.test.tsx +94 -0
  344. package/stack-template/app/ui-kit/src/ui/auto-complete/index.tsx +54 -0
  345. package/stack-template/app/ui-kit/src/ui/avatar/avatar.stories.tsx +132 -0
  346. package/stack-template/app/ui-kit/src/ui/avatar/avatar.test.tsx +65 -0
  347. package/stack-template/app/ui-kit/src/ui/avatar/index.tsx +48 -0
  348. package/stack-template/app/ui-kit/src/ui/avatar-group/avatar-group.stories.tsx +113 -0
  349. package/stack-template/app/ui-kit/src/ui/avatar-group/avatar-group.test.tsx +71 -0
  350. package/stack-template/app/ui-kit/src/ui/avatar-group/index.tsx +66 -0
  351. package/stack-template/app/ui-kit/src/ui/backdrop/backdrop.stories.tsx +66 -0
  352. package/stack-template/app/ui-kit/src/ui/backdrop/backdrop.test.tsx +37 -0
  353. package/stack-template/app/ui-kit/src/ui/backdrop/index.tsx +29 -0
  354. package/stack-template/app/ui-kit/src/ui/badge/badge.stories.tsx +105 -0
  355. package/stack-template/app/ui-kit/src/ui/badge/badge.test.tsx +115 -0
  356. package/stack-template/app/ui-kit/src/ui/badge/index.tsx +154 -0
  357. package/stack-template/app/ui-kit/src/ui/blockui/blockui.stories.tsx +34 -0
  358. package/stack-template/app/ui-kit/src/ui/blockui/blockui.test.tsx +29 -0
  359. package/stack-template/app/ui-kit/src/ui/blockui/index.tsx +25 -0
  360. package/stack-template/app/ui-kit/src/ui/bottom-navigation/bottom-navigation.stories.tsx +70 -0
  361. package/stack-template/app/ui-kit/src/ui/bottom-navigation/bottom-navigation.test.tsx +68 -0
  362. package/stack-template/app/ui-kit/src/ui/bottom-navigation/index.tsx +82 -0
  363. package/stack-template/app/ui-kit/src/ui/branch-fill.test.tsx +245 -0
  364. package/stack-template/app/ui-kit/src/ui/breadcrumb/breadcrumb.stories.tsx +103 -0
  365. package/stack-template/app/ui-kit/src/ui/breadcrumb/breadcrumb.test.tsx +49 -0
  366. package/stack-template/app/ui-kit/src/ui/breadcrumb/index.tsx +37 -0
  367. package/stack-template/app/ui-kit/src/ui/busy-box/busy-box.stories.tsx +30 -0
  368. package/stack-template/app/ui-kit/src/ui/busy-box/busy-box.test.tsx +29 -0
  369. package/stack-template/app/ui-kit/src/ui/busy-box/index.tsx +25 -0
  370. package/stack-template/app/ui-kit/src/ui/button/button.stories.tsx +121 -0
  371. package/stack-template/app/ui-kit/src/ui/button/button.test.tsx +207 -0
  372. package/stack-template/app/ui-kit/src/ui/button/index.tsx +128 -0
  373. package/stack-template/app/ui-kit/src/ui/calendar/calendar.stories.tsx +100 -0
  374. package/stack-template/app/ui-kit/src/ui/calendar/calendar.test.tsx +92 -0
  375. package/stack-template/app/ui-kit/src/ui/calendar/index.tsx +163 -0
  376. package/stack-template/app/ui-kit/src/ui/card/card.stories.tsx +203 -0
  377. package/stack-template/app/ui-kit/src/ui/card/card.test.tsx +135 -0
  378. package/stack-template/app/ui-kit/src/ui/card/index.tsx +84 -0
  379. package/stack-template/app/ui-kit/src/ui/carousel/carousel.stories.tsx +533 -0
  380. package/stack-template/app/ui-kit/src/ui/carousel/carousel.test.tsx +148 -0
  381. package/stack-template/app/ui-kit/src/ui/carousel/index.tsx +195 -0
  382. package/stack-template/app/ui-kit/src/ui/cascade-select/cascade-select.stories.tsx +126 -0
  383. package/stack-template/app/ui-kit/src/ui/cascade-select/cascade-select.test.tsx +132 -0
  384. package/stack-template/app/ui-kit/src/ui/cascade-select/index.tsx +87 -0
  385. package/stack-template/app/ui-kit/src/ui/chart/chart-theme.test.tsx +79 -0
  386. package/stack-template/app/ui-kit/src/ui/chart/chart.stories.tsx +278 -0
  387. package/stack-template/app/ui-kit/src/ui/chart/chart.test.tsx +103 -0
  388. package/stack-template/app/ui-kit/src/ui/chart/index.tsx +172 -0
  389. package/stack-template/app/ui-kit/src/ui/checkbox/checkbox.stories.tsx +67 -0
  390. package/stack-template/app/ui-kit/src/ui/checkbox/checkbox.test.tsx +99 -0
  391. package/stack-template/app/ui-kit/src/ui/checkbox/index.tsx +52 -0
  392. package/stack-template/app/ui-kit/src/ui/chips/chips.stories.tsx +53 -0
  393. package/stack-template/app/ui-kit/src/ui/chips/chips.test.tsx +86 -0
  394. package/stack-template/app/ui-kit/src/ui/chips/index.tsx +44 -0
  395. package/stack-template/app/ui-kit/src/ui/collapse/collapse.stories.tsx +93 -0
  396. package/stack-template/app/ui-kit/src/ui/collapse/collapse.test.tsx +128 -0
  397. package/stack-template/app/ui-kit/src/ui/collapse/index.tsx +75 -0
  398. package/stack-template/app/ui-kit/src/ui/color-picker/color-picker.stories.tsx +48 -0
  399. package/stack-template/app/ui-kit/src/ui/color-picker/color-picker.test.tsx +68 -0
  400. package/stack-template/app/ui-kit/src/ui/color-picker/index.tsx +38 -0
  401. package/stack-template/app/ui-kit/src/ui/context-menu/context-menu.stories.tsx +73 -0
  402. package/stack-template/app/ui-kit/src/ui/context-menu/context-menu.test.tsx +93 -0
  403. package/stack-template/app/ui-kit/src/ui/context-menu/index.tsx +79 -0
  404. package/stack-template/app/ui-kit/src/ui/count-up/count-up.stories.tsx +80 -0
  405. package/stack-template/app/ui-kit/src/ui/count-up/count-up.test.tsx +121 -0
  406. package/stack-template/app/ui-kit/src/ui/count-up/index.tsx +70 -0
  407. package/stack-template/app/ui-kit/src/ui/date-picker/date-picker.stories.tsx +154 -0
  408. package/stack-template/app/ui-kit/src/ui/date-picker/date-picker.test.tsx +221 -0
  409. package/stack-template/app/ui-kit/src/ui/date-picker/index.tsx +287 -0
  410. package/stack-template/app/ui-kit/src/ui/date-picker/locale-constants.ts +90 -0
  411. package/stack-template/app/ui-kit/src/ui/date-picker/locale.tsx +15 -0
  412. package/stack-template/app/ui-kit/src/ui/deferred-content/deferred-content.stories.tsx +62 -0
  413. package/stack-template/app/ui-kit/src/ui/deferred-content/deferred-content.test.tsx +94 -0
  414. package/stack-template/app/ui-kit/src/ui/deferred-content/index.tsx +61 -0
  415. package/stack-template/app/ui-kit/src/ui/descriptions/descriptions.stories.tsx +114 -0
  416. package/stack-template/app/ui-kit/src/ui/descriptions/descriptions.test.tsx +75 -0
  417. package/stack-template/app/ui-kit/src/ui/descriptions/index.tsx +48 -0
  418. package/stack-template/app/ui-kit/src/ui/divider/divider.stories.tsx +66 -0
  419. package/stack-template/app/ui-kit/src/ui/divider/divider.test.tsx +83 -0
  420. package/stack-template/app/ui-kit/src/ui/divider/index.tsx +65 -0
  421. package/stack-template/app/ui-kit/src/ui/drag-drop/drag-drop.stories.tsx +145 -0
  422. package/stack-template/app/ui-kit/src/ui/drag-drop/drag-drop.test.tsx +352 -0
  423. package/stack-template/app/ui-kit/src/ui/drag-drop/index.tsx +456 -0
  424. package/stack-template/app/ui-kit/src/ui/drawer/drawer.stories.tsx +108 -0
  425. package/stack-template/app/ui-kit/src/ui/drawer/drawer.test.tsx +132 -0
  426. package/stack-template/app/ui-kit/src/ui/drawer/index.tsx +113 -0
  427. package/stack-template/app/ui-kit/src/ui/dropdown/dropdown.stories.tsx +61 -0
  428. package/stack-template/app/ui-kit/src/ui/dropdown/dropdown.test.tsx +101 -0
  429. package/stack-template/app/ui-kit/src/ui/dropdown/index.tsx +162 -0
  430. package/stack-template/app/ui-kit/src/ui/editor/EditorInner.tsx +93 -0
  431. package/stack-template/app/ui-kit/src/ui/editor/editor.stories.tsx +37 -0
  432. package/stack-template/app/ui-kit/src/ui/editor/editor.test.tsx +84 -0
  433. package/stack-template/app/ui-kit/src/ui/editor/index.tsx +58 -0
  434. package/stack-template/app/ui-kit/src/ui/empty-state/empty-state.stories.tsx +24 -0
  435. package/stack-template/app/ui-kit/src/ui/empty-state/empty-state.test.tsx +48 -0
  436. package/stack-template/app/ui-kit/src/ui/empty-state/index.tsx +22 -0
  437. package/stack-template/app/ui-kit/src/ui/experience3d/experience3d.stories.tsx +66 -0
  438. package/stack-template/app/ui-kit/src/ui/experience3d/experience3d.test.tsx +50 -0
  439. package/stack-template/app/ui-kit/src/ui/experience3d/index.tsx +457 -0
  440. package/stack-template/app/ui-kit/src/ui/field/field-array.stories.tsx +214 -0
  441. package/stack-template/app/ui-kit/src/ui/field/field.stories.tsx +158 -0
  442. package/stack-template/app/ui-kit/src/ui/field/field.test.tsx +68 -0
  443. package/stack-template/app/ui-kit/src/ui/field/index.tsx +48 -0
  444. package/stack-template/app/ui-kit/src/ui/fieldset/fieldset.stories.tsx +49 -0
  445. package/stack-template/app/ui-kit/src/ui/fieldset/fieldset.test.tsx +88 -0
  446. package/stack-template/app/ui-kit/src/ui/fieldset/index.tsx +62 -0
  447. package/stack-template/app/ui-kit/src/ui/flex/flex.stories.tsx +96 -0
  448. package/stack-template/app/ui-kit/src/ui/flex/flex.test.tsx +79 -0
  449. package/stack-template/app/ui-kit/src/ui/flex/index.tsx +45 -0
  450. package/stack-template/app/ui-kit/src/ui/float-button/float-button.stories.tsx +82 -0
  451. package/stack-template/app/ui-kit/src/ui/float-button/float-button.test.tsx +107 -0
  452. package/stack-template/app/ui-kit/src/ui/float-button/index.tsx +124 -0
  453. package/stack-template/app/ui-kit/src/ui/galleria/galleria.stories.tsx +78 -0
  454. package/stack-template/app/ui-kit/src/ui/galleria/galleria.test.tsx +67 -0
  455. package/stack-template/app/ui-kit/src/ui/galleria/index.tsx +47 -0
  456. package/stack-template/app/ui-kit/src/ui/grid/grid.stories.tsx +179 -0
  457. package/stack-template/app/ui-kit/src/ui/grid/grid.test.tsx +286 -0
  458. package/stack-template/app/ui-kit/src/ui/grid/index.tsx +104 -0
  459. package/stack-template/app/ui-kit/src/ui/icons/icons.stories.tsx +52 -0
  460. package/stack-template/app/ui-kit/src/ui/icons/icons.test.tsx +60 -0
  461. package/stack-template/app/ui-kit/src/ui/icons/index.tsx +294 -0
  462. package/stack-template/app/ui-kit/src/ui/image/image.stories.tsx +231 -0
  463. package/stack-template/app/ui-kit/src/ui/image/image.test.tsx +79 -0
  464. package/stack-template/app/ui-kit/src/ui/image/index.tsx +76 -0
  465. package/stack-template/app/ui-kit/src/ui/inplace/index.tsx +33 -0
  466. package/stack-template/app/ui-kit/src/ui/inplace/inplace.stories.tsx +75 -0
  467. package/stack-template/app/ui-kit/src/ui/inplace/inplace.test.tsx +58 -0
  468. package/stack-template/app/ui-kit/src/ui/input/index.tsx +133 -0
  469. package/stack-template/app/ui-kit/src/ui/input/input-search.stories.tsx +112 -0
  470. package/stack-template/app/ui-kit/src/ui/input/input-search.test.tsx +116 -0
  471. package/stack-template/app/ui-kit/src/ui/input/input-search.tsx +116 -0
  472. package/stack-template/app/ui-kit/src/ui/input/input.stories.tsx +176 -0
  473. package/stack-template/app/ui-kit/src/ui/input/input.test.tsx +106 -0
  474. package/stack-template/app/ui-kit/src/ui/input-mask/index.tsx +39 -0
  475. package/stack-template/app/ui-kit/src/ui/input-mask/input-mask.stories.tsx +46 -0
  476. package/stack-template/app/ui-kit/src/ui/input-mask/input-mask.test.tsx +57 -0
  477. package/stack-template/app/ui-kit/src/ui/input-number/index.tsx +125 -0
  478. package/stack-template/app/ui-kit/src/ui/input-number/input-number.stories.tsx +190 -0
  479. package/stack-template/app/ui-kit/src/ui/input-number/input-number.test.tsx +157 -0
  480. package/stack-template/app/ui-kit/src/ui/input-otp/index.tsx +57 -0
  481. package/stack-template/app/ui-kit/src/ui/input-otp/input-otp.stories.tsx +90 -0
  482. package/stack-template/app/ui-kit/src/ui/input-otp/input-otp.test.tsx +66 -0
  483. package/stack-template/app/ui-kit/src/ui/kanban/index.tsx +277 -0
  484. package/stack-template/app/ui-kit/src/ui/kanban/kanban.stories.tsx +219 -0
  485. package/stack-template/app/ui-kit/src/ui/kanban/kanban.test.tsx +234 -0
  486. package/stack-template/app/ui-kit/src/ui/knob/index.tsx +58 -0
  487. package/stack-template/app/ui-kit/src/ui/knob/knob.stories.tsx +49 -0
  488. package/stack-template/app/ui-kit/src/ui/knob/knob.test.tsx +42 -0
  489. package/stack-template/app/ui-kit/src/ui/layout/index.tsx +145 -0
  490. package/stack-template/app/ui-kit/src/ui/layout/layout.stories.tsx +158 -0
  491. package/stack-template/app/ui-kit/src/ui/layout/layout.test.tsx +154 -0
  492. package/stack-template/app/ui-kit/src/ui/link/index.tsx +61 -0
  493. package/stack-template/app/ui-kit/src/ui/link/link.stories.tsx +68 -0
  494. package/stack-template/app/ui-kit/src/ui/link/link.test.tsx +69 -0
  495. package/stack-template/app/ui-kit/src/ui/list/index.tsx +135 -0
  496. package/stack-template/app/ui-kit/src/ui/list/list.stories.tsx +194 -0
  497. package/stack-template/app/ui-kit/src/ui/list/list.test.tsx +164 -0
  498. package/stack-template/app/ui-kit/src/ui/listbox/index.tsx +27 -0
  499. package/stack-template/app/ui-kit/src/ui/listbox/listbox.stories.tsx +57 -0
  500. package/stack-template/app/ui-kit/src/ui/listbox/listbox.test.tsx +49 -0
  501. package/stack-template/app/ui-kit/src/ui/mega-menu/index.tsx +142 -0
  502. package/stack-template/app/ui-kit/src/ui/mega-menu/mega-menu.stories.tsx +137 -0
  503. package/stack-template/app/ui-kit/src/ui/mega-menu/mega-menu.test.tsx +130 -0
  504. package/stack-template/app/ui-kit/src/ui/mention/index.tsx +76 -0
  505. package/stack-template/app/ui-kit/src/ui/mention/mention.stories.tsx +44 -0
  506. package/stack-template/app/ui-kit/src/ui/mention/mention.test.tsx +87 -0
  507. package/stack-template/app/ui-kit/src/ui/menu/index.tsx +256 -0
  508. package/stack-template/app/ui-kit/src/ui/menu/menu.stories.tsx +124 -0
  509. package/stack-template/app/ui-kit/src/ui/menu/menu.test.tsx +251 -0
  510. package/stack-template/app/ui-kit/src/ui/menubar/index.tsx +42 -0
  511. package/stack-template/app/ui-kit/src/ui/menubar/menubar.stories.tsx +66 -0
  512. package/stack-template/app/ui-kit/src/ui/menubar/menubar.test.tsx +65 -0
  513. package/stack-template/app/ui-kit/src/ui/message/index.tsx +123 -0
  514. package/stack-template/app/ui-kit/src/ui/message/message.stories.tsx +104 -0
  515. package/stack-template/app/ui-kit/src/ui/message/message.test.tsx +109 -0
  516. package/stack-template/app/ui-kit/src/ui/modal/index.tsx +142 -0
  517. package/stack-template/app/ui-kit/src/ui/modal/modal.stories.tsx +128 -0
  518. package/stack-template/app/ui-kit/src/ui/modal/modal.test.tsx +166 -0
  519. package/stack-template/app/ui-kit/src/ui/notification/index.tsx +142 -0
  520. package/stack-template/app/ui-kit/src/ui/notification/notification.stories.tsx +155 -0
  521. package/stack-template/app/ui-kit/src/ui/notification/notification.test.tsx +83 -0
  522. package/stack-template/app/ui-kit/src/ui/order-list/index.tsx +38 -0
  523. package/stack-template/app/ui-kit/src/ui/order-list/order-list.stories.tsx +38 -0
  524. package/stack-template/app/ui-kit/src/ui/order-list/order-list.test.tsx +54 -0
  525. package/stack-template/app/ui-kit/src/ui/org-chart/index.tsx +138 -0
  526. package/stack-template/app/ui-kit/src/ui/org-chart/org-chart.stories.tsx +76 -0
  527. package/stack-template/app/ui-kit/src/ui/org-chart/org-chart.test.tsx +98 -0
  528. package/stack-template/app/ui-kit/src/ui/pagination/index.tsx +102 -0
  529. package/stack-template/app/ui-kit/src/ui/pagination/pagination.stories.tsx +103 -0
  530. package/stack-template/app/ui-kit/src/ui/pagination/pagination.test.tsx +112 -0
  531. package/stack-template/app/ui-kit/src/ui/panel-menu/index.tsx +59 -0
  532. package/stack-template/app/ui-kit/src/ui/panel-menu/panel-menu.stories.tsx +96 -0
  533. package/stack-template/app/ui-kit/src/ui/panel-menu/panel-menu.test.tsx +64 -0
  534. package/stack-template/app/ui-kit/src/ui/parallax/index.tsx +62 -0
  535. package/stack-template/app/ui-kit/src/ui/parallax/parallax.stories.tsx +115 -0
  536. package/stack-template/app/ui-kit/src/ui/parallax/parallax.test.tsx +148 -0
  537. package/stack-template/app/ui-kit/src/ui/password/index.tsx +67 -0
  538. package/stack-template/app/ui-kit/src/ui/password/password.stories.tsx +43 -0
  539. package/stack-template/app/ui-kit/src/ui/password/password.test.tsx +45 -0
  540. package/stack-template/app/ui-kit/src/ui/pick-list/index.tsx +103 -0
  541. package/stack-template/app/ui-kit/src/ui/pick-list/pick-list.stories.tsx +59 -0
  542. package/stack-template/app/ui-kit/src/ui/pick-list/pick-list.test.tsx +94 -0
  543. package/stack-template/app/ui-kit/src/ui/popconfirm/index.tsx +102 -0
  544. package/stack-template/app/ui-kit/src/ui/popconfirm/popconfirm.stories.tsx +73 -0
  545. package/stack-template/app/ui-kit/src/ui/popconfirm/popconfirm.test.tsx +127 -0
  546. package/stack-template/app/ui-kit/src/ui/popover/index.tsx +136 -0
  547. package/stack-template/app/ui-kit/src/ui/popover/popover.stories.tsx +114 -0
  548. package/stack-template/app/ui-kit/src/ui/popover/popover.test.tsx +172 -0
  549. package/stack-template/app/ui-kit/src/ui/progress/index.tsx +46 -0
  550. package/stack-template/app/ui-kit/src/ui/progress/progress.stories.tsx +57 -0
  551. package/stack-template/app/ui-kit/src/ui/progress/progress.test.tsx +90 -0
  552. package/stack-template/app/ui-kit/src/ui/qr-code/index.tsx +88 -0
  553. package/stack-template/app/ui-kit/src/ui/qr-code/qr-code.stories.tsx +109 -0
  554. package/stack-template/app/ui-kit/src/ui/qr-code/qr-code.test.tsx +155 -0
  555. package/stack-template/app/ui-kit/src/ui/qr-code/qrcode-core.ts +56 -0
  556. package/stack-template/app/ui-kit/src/ui/qr-code/qrcode-generator.vendor.ts +2300 -0
  557. package/stack-template/app/ui-kit/src/ui/radio/index.tsx +62 -0
  558. package/stack-template/app/ui-kit/src/ui/radio/radio.stories.tsx +94 -0
  559. package/stack-template/app/ui-kit/src/ui/radio/radio.test.tsx +83 -0
  560. package/stack-template/app/ui-kit/src/ui/rating/index.tsx +36 -0
  561. package/stack-template/app/ui-kit/src/ui/rating/rating.stories.tsx +42 -0
  562. package/stack-template/app/ui-kit/src/ui/rating/rating.test.tsx +45 -0
  563. package/stack-template/app/ui-kit/src/ui/result/index.tsx +72 -0
  564. package/stack-template/app/ui-kit/src/ui/result/result.stories.tsx +82 -0
  565. package/stack-template/app/ui-kit/src/ui/result/result.test.tsx +57 -0
  566. package/stack-template/app/ui-kit/src/ui/reveal/index.tsx +83 -0
  567. package/stack-template/app/ui-kit/src/ui/reveal/reveal.stories.tsx +91 -0
  568. package/stack-template/app/ui-kit/src/ui/reveal/reveal.test.tsx +148 -0
  569. package/stack-template/app/ui-kit/src/ui/schedule/index.tsx +104 -0
  570. package/stack-template/app/ui-kit/src/ui/schedule/schedule.fc.test.tsx +95 -0
  571. package/stack-template/app/ui-kit/src/ui/schedule/schedule.stories.tsx +61 -0
  572. package/stack-template/app/ui-kit/src/ui/schedule/schedule.test.tsx +41 -0
  573. package/stack-template/app/ui-kit/src/ui/scroll-page/index.tsx +46 -0
  574. package/stack-template/app/ui-kit/src/ui/scroll-page/scroll-page.stories.tsx +92 -0
  575. package/stack-template/app/ui-kit/src/ui/scroll-page/scroll-page.test.tsx +51 -0
  576. package/stack-template/app/ui-kit/src/ui/scroll-panel/index.tsx +16 -0
  577. package/stack-template/app/ui-kit/src/ui/scroll-panel/scroll-panel.stories.tsx +37 -0
  578. package/stack-template/app/ui-kit/src/ui/scroll-panel/scroll-panel.test.tsx +41 -0
  579. package/stack-template/app/ui-kit/src/ui/scrolltop/index.tsx +27 -0
  580. package/stack-template/app/ui-kit/src/ui/scrolltop/scrolltop.stories.tsx +41 -0
  581. package/stack-template/app/ui-kit/src/ui/scrolltop/scrolltop.test.tsx +37 -0
  582. package/stack-template/app/ui-kit/src/ui/segmented/index.tsx +47 -0
  583. package/stack-template/app/ui-kit/src/ui/segmented/segmented.stories.tsx +126 -0
  584. package/stack-template/app/ui-kit/src/ui/segmented/segmented.test.tsx +77 -0
  585. package/stack-template/app/ui-kit/src/ui/select/index.tsx +302 -0
  586. package/stack-template/app/ui-kit/src/ui/select/select.stories.tsx +268 -0
  587. package/stack-template/app/ui-kit/src/ui/select/select.test.tsx +226 -0
  588. package/stack-template/app/ui-kit/src/ui/sidebar/index.tsx +83 -0
  589. package/stack-template/app/ui-kit/src/ui/sidebar/sidebar.stories.tsx +71 -0
  590. package/stack-template/app/ui-kit/src/ui/sidebar/sidebar.test.tsx +101 -0
  591. package/stack-template/app/ui-kit/src/ui/skeleton/index.tsx +55 -0
  592. package/stack-template/app/ui-kit/src/ui/skeleton/skeleton.stories.tsx +110 -0
  593. package/stack-template/app/ui-kit/src/ui/skeleton/skeleton.test.tsx +74 -0
  594. package/stack-template/app/ui-kit/src/ui/slide-menu/index.tsx +103 -0
  595. package/stack-template/app/ui-kit/src/ui/slide-menu/slide-menu.stories.tsx +92 -0
  596. package/stack-template/app/ui-kit/src/ui/slide-menu/slide-menu.test.tsx +120 -0
  597. package/stack-template/app/ui-kit/src/ui/slider/index.tsx +90 -0
  598. package/stack-template/app/ui-kit/src/ui/slider/slider.stories.tsx +60 -0
  599. package/stack-template/app/ui-kit/src/ui/slider/slider.test.tsx +66 -0
  600. package/stack-template/app/ui-kit/src/ui/space/index.tsx +32 -0
  601. package/stack-template/app/ui-kit/src/ui/space/space.stories.tsx +66 -0
  602. package/stack-template/app/ui-kit/src/ui/space/space.test.tsx +56 -0
  603. package/stack-template/app/ui-kit/src/ui/speed-dial/index.tsx +32 -0
  604. package/stack-template/app/ui-kit/src/ui/speed-dial/speed-dial.stories.tsx +34 -0
  605. package/stack-template/app/ui-kit/src/ui/speed-dial/speed-dial.test.tsx +34 -0
  606. package/stack-template/app/ui-kit/src/ui/spinner/index.tsx +74 -0
  607. package/stack-template/app/ui-kit/src/ui/spinner/spinner.stories.tsx +64 -0
  608. package/stack-template/app/ui-kit/src/ui/spinner/spinner.test.tsx +66 -0
  609. package/stack-template/app/ui-kit/src/ui/split-button/index.tsx +155 -0
  610. package/stack-template/app/ui-kit/src/ui/split-button/split-button.stories.tsx +137 -0
  611. package/stack-template/app/ui-kit/src/ui/split-button/split-button.test.tsx +152 -0
  612. package/stack-template/app/ui-kit/src/ui/splitter/index.tsx +49 -0
  613. package/stack-template/app/ui-kit/src/ui/splitter/splitter.stories.tsx +24 -0
  614. package/stack-template/app/ui-kit/src/ui/splitter/splitter.test.tsx +21 -0
  615. package/stack-template/app/ui-kit/src/ui/statistic/index.tsx +28 -0
  616. package/stack-template/app/ui-kit/src/ui/statistic/statistic.stories.tsx +112 -0
  617. package/stack-template/app/ui-kit/src/ui/statistic/statistic.test.tsx +39 -0
  618. package/stack-template/app/ui-kit/src/ui/steps/index.tsx +50 -0
  619. package/stack-template/app/ui-kit/src/ui/steps/steps.stories.tsx +57 -0
  620. package/stack-template/app/ui-kit/src/ui/steps/steps.test.tsx +55 -0
  621. package/stack-template/app/ui-kit/src/ui/switch/index.tsx +87 -0
  622. package/stack-template/app/ui-kit/src/ui/switch/switch.stories.tsx +123 -0
  623. package/stack-template/app/ui-kit/src/ui/switch/switch.test.tsx +98 -0
  624. package/stack-template/app/ui-kit/src/ui/tab-menu/index.tsx +33 -0
  625. package/stack-template/app/ui-kit/src/ui/tab-menu/tab-menu.stories.tsx +49 -0
  626. package/stack-template/app/ui-kit/src/ui/tab-menu/tab-menu.test.tsx +50 -0
  627. package/stack-template/app/ui-kit/src/ui/table/index.tsx +690 -0
  628. package/stack-template/app/ui-kit/src/ui/table/table-advanced.stories.tsx +91 -0
  629. package/stack-template/app/ui-kit/src/ui/table/table-advanced.test.tsx +188 -0
  630. package/stack-template/app/ui-kit/src/ui/table/table-expandable.stories.tsx +91 -0
  631. package/stack-template/app/ui-kit/src/ui/table/table-expandable.test.tsx +143 -0
  632. package/stack-template/app/ui-kit/src/ui/table/table.stories.tsx +342 -0
  633. package/stack-template/app/ui-kit/src/ui/table/table.test.tsx +465 -0
  634. package/stack-template/app/ui-kit/src/ui/table/types.ts +173 -0
  635. package/stack-template/app/ui-kit/src/ui/tabs/index.tsx +118 -0
  636. package/stack-template/app/ui-kit/src/ui/tabs/tabs.stories.tsx +113 -0
  637. package/stack-template/app/ui-kit/src/ui/tabs/tabs.test.tsx +77 -0
  638. package/stack-template/app/ui-kit/src/ui/tag/index.tsx +68 -0
  639. package/stack-template/app/ui-kit/src/ui/tag/tag.stories.tsx +88 -0
  640. package/stack-template/app/ui-kit/src/ui/tag/tag.test.tsx +126 -0
  641. package/stack-template/app/ui-kit/src/ui/team/debt-board/debt-board.stories.tsx +52 -0
  642. package/stack-template/app/ui-kit/src/ui/team/debt-board/debt-board.test.tsx +72 -0
  643. package/stack-template/app/ui-kit/src/ui/team/debt-board/index.tsx +125 -0
  644. package/stack-template/app/ui-kit/src/ui/team/inbox-thread/inbox-thread.stories.tsx +70 -0
  645. package/stack-template/app/ui-kit/src/ui/team/inbox-thread/inbox-thread.test.tsx +56 -0
  646. package/stack-template/app/ui-kit/src/ui/team/inbox-thread/index.tsx +107 -0
  647. package/stack-template/app/ui-kit/src/ui/team/ping-feed/index.tsx +102 -0
  648. package/stack-template/app/ui-kit/src/ui/team/ping-feed/ping-feed.stories.tsx +57 -0
  649. package/stack-template/app/ui-kit/src/ui/team/ping-feed/ping-feed.test.tsx +60 -0
  650. package/stack-template/app/ui-kit/src/ui/team/stage-pipeline/index.tsx +60 -0
  651. package/stack-template/app/ui-kit/src/ui/team/stage-pipeline/stage-pipeline.stories.tsx +68 -0
  652. package/stack-template/app/ui-kit/src/ui/team/stage-pipeline/stage-pipeline.test.tsx +50 -0
  653. package/stack-template/app/ui-kit/src/ui/team/team-dashboard/index.tsx +103 -0
  654. package/stack-template/app/ui-kit/src/ui/team/team-dashboard/team-dashboard.stories.tsx +72 -0
  655. package/stack-template/app/ui-kit/src/ui/team/team-dashboard/team-dashboard.test.tsx +72 -0
  656. package/stack-template/app/ui-kit/src/ui/time-picker/index.tsx +143 -0
  657. package/stack-template/app/ui-kit/src/ui/time-picker/time-picker.stories.tsx +90 -0
  658. package/stack-template/app/ui-kit/src/ui/time-picker/time-picker.test.tsx +64 -0
  659. package/stack-template/app/ui-kit/src/ui/timeline/index.tsx +91 -0
  660. package/stack-template/app/ui-kit/src/ui/timeline/timeline.stories.tsx +209 -0
  661. package/stack-template/app/ui-kit/src/ui/timeline/timeline.test.tsx +116 -0
  662. package/stack-template/app/ui-kit/src/ui/timesheet/index.tsx +277 -0
  663. package/stack-template/app/ui-kit/src/ui/timesheet/timesheet.stories.tsx +97 -0
  664. package/stack-template/app/ui-kit/src/ui/timesheet/timesheet.test.tsx +103 -0
  665. package/stack-template/app/ui-kit/src/ui/toggle-button/index.tsx +28 -0
  666. package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button-group.stories.tsx +85 -0
  667. package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button-group.test.tsx +97 -0
  668. package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button-group.tsx +81 -0
  669. package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button.stories.tsx +46 -0
  670. package/stack-template/app/ui-kit/src/ui/toggle-button/toggle-button.test.tsx +38 -0
  671. package/stack-template/app/ui-kit/src/ui/toolbar/index.tsx +18 -0
  672. package/stack-template/app/ui-kit/src/ui/toolbar/toolbar.stories.tsx +35 -0
  673. package/stack-template/app/ui-kit/src/ui/toolbar/toolbar.test.tsx +11 -0
  674. package/stack-template/app/ui-kit/src/ui/tooltip/index.tsx +61 -0
  675. package/stack-template/app/ui-kit/src/ui/tooltip/tooltip.stories.tsx +81 -0
  676. package/stack-template/app/ui-kit/src/ui/tooltip/tooltip.test.tsx +120 -0
  677. package/stack-template/app/ui-kit/src/ui/tour/index.tsx +210 -0
  678. package/stack-template/app/ui-kit/src/ui/tour/tour.stories.tsx +153 -0
  679. package/stack-template/app/ui-kit/src/ui/tour/tour.test.tsx +131 -0
  680. package/stack-template/app/ui-kit/src/ui/transition/index.tsx +377 -0
  681. package/stack-template/app/ui-kit/src/ui/transition/transition.stories.tsx +254 -0
  682. package/stack-template/app/ui-kit/src/ui/transition/transition.test.tsx +285 -0
  683. package/stack-template/app/ui-kit/src/ui/tree/index.tsx +68 -0
  684. package/stack-template/app/ui-kit/src/ui/tree/tree.stories.tsx +139 -0
  685. package/stack-template/app/ui-kit/src/ui/tree/tree.test.tsx +77 -0
  686. package/stack-template/app/ui-kit/src/ui/tree-select/index.tsx +251 -0
  687. package/stack-template/app/ui-kit/src/ui/tree-select/tree-select.stories.tsx +105 -0
  688. package/stack-template/app/ui-kit/src/ui/tree-select/tree-select.test.tsx +174 -0
  689. package/stack-template/app/ui-kit/src/ui/tree-table/index.tsx +229 -0
  690. package/stack-template/app/ui-kit/src/ui/tree-table/tree-table.stories.tsx +111 -0
  691. package/stack-template/app/ui-kit/src/ui/tree-table/tree-table.test.tsx +137 -0
  692. package/stack-template/app/ui-kit/src/ui/typography/index.tsx +124 -0
  693. package/stack-template/app/ui-kit/src/ui/typography/typography.stories.tsx +65 -0
  694. package/stack-template/app/ui-kit/src/ui/typography/typography.test.tsx +117 -0
  695. package/stack-template/app/ui-kit/src/ui/upload/index.tsx +39 -0
  696. package/stack-template/app/ui-kit/src/ui/upload/upload-core.tsx +204 -0
  697. package/stack-template/app/ui-kit/src/ui/upload/upload-dropzone.tsx +79 -0
  698. package/stack-template/app/ui-kit/src/ui/upload/upload.stories.tsx +67 -0
  699. package/stack-template/app/ui-kit/src/ui/upload/upload.test.tsx +204 -0
  700. package/stack-template/app/ui-kit/src/ui/virtual-scroll/index.tsx +86 -0
  701. package/stack-template/app/ui-kit/src/ui/virtual-scroll/virtual-scroll.stories.tsx +111 -0
  702. package/stack-template/app/ui-kit/src/ui/virtual-scroll/virtual-scroll.test.tsx +125 -0
  703. package/stack-template/app/ui-kit/src/ui/watermark/index.tsx +182 -0
  704. package/stack-template/app/ui-kit/src/ui/watermark/watermark.stories.tsx +96 -0
  705. package/stack-template/app/ui-kit/src/ui/watermark/watermark.test.tsx +120 -0
  706. package/stack-template/app/ui-kit/src/utils/array.test.ts +88 -0
  707. package/stack-template/app/ui-kit/src/utils/array.ts +51 -0
  708. package/stack-template/app/ui-kit/src/utils/dom.test.tsx +69 -0
  709. package/stack-template/app/ui-kit/src/utils/dom.ts +38 -0
  710. package/stack-template/app/ui-kit/src/utils/format.test.ts +63 -0
  711. package/stack-template/app/ui-kit/src/utils/format.ts +81 -0
  712. package/stack-template/app/ui-kit/tests/setup.ts +15 -0
  713. package/stack-template/app/ui-kit/tsconfig.json +18 -0
  714. package/stack-template/app/ui-kit/tsup.config.ts +37 -0
  715. package/stack-template/app/ui-kit/vercel.json +6 -0
  716. package/stack-template/app/ui-kit/vitest.config.ts +22 -0
  717. package/stack-template/contracts/auth/token-contract.md +119 -0
  718. package/stack-template/contracts/auth/users.json +35 -0
  719. package/stack-template/contracts/db/tasks-schema.sql +62 -0
  720. package/stack-template/contracts/events/fixtures/task.assigned.json +11 -0
  721. package/stack-template/contracts/events/fixtures/task.assignment_failed.json +11 -0
  722. package/stack-template/contracts/events/fixtures/task.created.json +12 -0
  723. package/stack-template/contracts/events/fixtures/task.deleted.json +10 -0
  724. package/stack-template/contracts/events/fixtures/task.updated.json +12 -0
  725. package/stack-template/contracts/events/task-events.md +80 -0
  726. package/stack-template/contracts/openapi/activity.yaml +196 -0
  727. package/stack-template/contracts/openapi/auth.yaml +310 -0
  728. package/stack-template/contracts/openapi/tasks.yaml +316 -0
  729. package/stack-template/contracts/openapi/users.yaml +345 -0
  730. package/stack-template/docs/adr/0001-mixed-stack.md +14 -0
  731. package/stack-template/docs/adr/0002-mf-rspack.md +14 -0
  732. package/stack-template/docs/adr/0003-contract-first.md +14 -0
  733. package/stack-template/docs/adr/0004-readonly-schema-tradeoff.md +14 -0
  734. package/stack-template/docs/adr/0005-fail-closed.md +14 -0
  735. package/stack-template/docs/adr/0006-fire-and-forget-events.md +14 -0
  736. package/stack-template/docs/adr/0007-fork-not-upgrade.md +14 -0
  737. package/stack-template/docs/adr/0008-kafka-outbox-saga.md +24 -0
  738. package/stack-template/docs/adr/0009-ui-kit-split.md +39 -0
  739. package/stack-template/docs/adr/README.md +15 -0
  740. package/stack-template/docs/ai/recipes.md +956 -0
  741. package/stack-template/docs/ai/table-Theming.md +25 -0
  742. package/stack-template/docs/ai/table-datadisplay-mz.md +20 -0
  743. package/stack-template/docs/ai/table-feedback.md +20 -0
  744. package/stack-template/docs/ai/table-forms.md +26 -0
  745. package/stack-template/docs/git-flow.md +70 -0
  746. package/stack-template/docs/parity-matrix.md +102 -0
  747. package/stack-template/docs/superpowers/contexts/auth-real/gap-answer.md +195 -0
  748. package/stack-template/docs/superpowers/contexts/auth-real/sf-1.md +21 -0
  749. package/stack-template/docs/superpowers/contexts/auth-real/sf-2.md +21 -0
  750. package/stack-template/docs/superpowers/contexts/auth-real/sf-3.md +17 -0
  751. package/stack-template/docs/superpowers/contexts/auth-real/sf-4.md +20 -0
  752. package/stack-template/docs/superpowers/contexts/auth-real/sf-5.md +21 -0
  753. package/stack-template/docs/superpowers/contexts/experience-design.md +85 -0
  754. package/stack-template/docs/superpowers/contexts/sf-1.md +39 -0
  755. package/stack-template/docs/superpowers/contexts/sf-2.md +42 -0
  756. package/stack-template/docs/superpowers/contexts/sf-3.md +42 -0
  757. package/stack-template/docs/superpowers/contexts/sf-4.md +26 -0
  758. package/stack-template/docs/superpowers/contexts/sf-5.md +36 -0
  759. package/stack-template/docs/superpowers/contexts/sf-6.md +36 -0
  760. package/stack-template/docs/superpowers/contexts/sf-7.md +35 -0
  761. package/stack-template/docs/superpowers/contexts/sf-cin-overview.md +21 -0
  762. package/stack-template/docs/superpowers/contexts/ui-redesign/sf-1.md +46 -0
  763. package/stack-template/docs/superpowers/contexts/ui-redesign/sf-2.md +44 -0
  764. package/stack-template/docs/superpowers/contexts/ui-redesign/sf-3.md +47 -0
  765. package/stack-template/docs/superpowers/contexts/ui-redesign/sf-4.md +44 -0
  766. package/stack-template/docs/superpowers/contexts/ui-redesign/sf-5.md +36 -0
  767. package/stack-template/docs/superpowers/designs/direction-approved.md +11 -0
  768. package/stack-template/docs/superpowers/designs/ui-redesign/drafts/a-roulette-soundviz.html +353 -0
  769. package/stack-template/docs/superpowers/designs/ui-redesign/drafts/b-reference.html +347 -0
  770. package/stack-template/docs/superpowers/designs/ui-redesign/drafts/c-designer.html +375 -0
  771. package/stack-template/docs/superpowers/designs/ui-redesign/ds-demo.html +140 -0
  772. package/stack-template/docs/superpowers/designs/ui-redesign-direction.md +93 -0
  773. package/stack-template/docs/superpowers/improvements-log.md +158 -0
  774. package/stack-template/docs/superpowers/mindmaps/auth-real.wakii +115 -0
  775. package/stack-template/docs/superpowers/mindmaps/kafka-outbox-saga.wakii +110 -0
  776. package/stack-template/docs/superpowers/mindmaps/micro-boilerplate.wakii +171 -0
  777. package/stack-template/docs/superpowers/mindmaps/ui-redesign.wakii +116 -0
  778. package/stack-template/docs/superpowers/mindmaps/vu53-cinematic-experience.wakii +32 -0
  779. package/stack-template/docs/superpowers/plans/2026-10-12-sf-1-contracts-platform-plan.md +44 -0
  780. package/stack-template/docs/superpowers/plans/2026-10-12-sf-3-spring-svc-impact.md +69 -0
  781. package/stack-template/docs/superpowers/plans/2026-10-12-sf-3-spring-svc-plan.md +27 -0
  782. package/stack-template/docs/superpowers/plans/2026-10-12-sf-4-go-svc-plan.md +99 -0
  783. package/stack-template/docs/superpowers/plans/2026-10-12-sf-5-fe-shell-plan.md +64 -0
  784. package/stack-template/docs/superpowers/plans/2026-10-12-sf-6-fe-remotes-plan.md +83 -0
  785. package/stack-template/docs/superpowers/plans/2026-10-12-sf-7-convergence-plan.md +59 -0
  786. package/stack-template/docs/superpowers/plans/2026-10-12-sf2-node-svc-plan.md +19 -0
  787. package/stack-template/docs/superpowers/plans/2026-10-13-sf-1-kafka-foundation-plan.md +30 -0
  788. package/stack-template/docs/superpowers/plans/2026-10-13-sf-1-ui-redesign-plan.md +28 -0
  789. package/stack-template/docs/superpowers/plans/2026-10-13-sf-2-node-outbox-plan.md +46 -0
  790. package/stack-template/docs/superpowers/plans/2026-10-13-sf-3-go-consumer-plan.md +31 -0
  791. package/stack-template/docs/superpowers/plans/2026-10-13-sf-4-spring-tx-plan.md +96 -0
  792. package/stack-template/docs/superpowers/plans/2026-10-13-sf-5-convergence-plan.md +21 -0
  793. package/stack-template/docs/superpowers/plans/2026-10-14-sf-2-ui-redesign-plan.md +32 -0
  794. package/stack-template/docs/superpowers/plans/2026-10-14-sf-3-ui-redesign-plan.md +34 -0
  795. package/stack-template/docs/superpowers/plans/2026-10-14-sf-5-ui-redesign-plan.md +35 -0
  796. package/stack-template/docs/superpowers/plans/2026-10-17-auth-real-plan.md +112 -0
  797. package/stack-template/docs/superpowers/plans/2026-10-17-ui-kit-split-plan.md +18 -0
  798. package/stack-template/docs/superpowers/reviews/2026-10-18-data-display-coverage.md +52 -0
  799. package/stack-template/docs/superpowers/reviews/code-reviewer-sf-5-r1.md +65 -0
  800. package/stack-template/docs/superpowers/reviews/security-audit-sf-5-auth-real.md +39 -0
  801. package/stack-template/docs/superpowers/specs/2026-10-12-boilerplate-microservice-mfe.md +110 -0
  802. package/stack-template/docs/superpowers/specs/2026-10-12-sf-3-spring-svc-design.md +160 -0
  803. package/stack-template/docs/superpowers/specs/2026-10-12-sf-7-convergence-spec.md +114 -0
  804. package/stack-template/docs/superpowers/specs/2026-10-12-sf2-node-svc-spec.md +42 -0
  805. package/stack-template/docs/superpowers/specs/2026-10-13-kafka-outbox-saga.md +111 -0
  806. package/stack-template/docs/superpowers/specs/2026-10-13-ui-redesign.md +173 -0
  807. package/stack-template/docs/superpowers/specs/2026-10-14-sf-3-ui-redesign.md +46 -0
  808. package/stack-template/docs/superpowers/specs/2026-10-14-sf-5-ui-redesign.md +30 -0
  809. package/stack-template/docs/superpowers/specs/2026-10-17-antd-look-tokens.md +28 -0
  810. package/stack-template/docs/superpowers/specs/2026-10-17-auth-real-design.md +124 -0
  811. package/stack-template/docs/superpowers/specs/2026-10-17-tailwind-migration.md +32 -0
  812. package/stack-template/docs/superpowers/specs/2026-10-17-ui-kit-split.md +44 -0
  813. package/stack-template/docs/superpowers/specs/2026-10-18-0.3.0-release-notes.md +77 -0
  814. package/stack-template/docs/toolchain.md +28 -0
  815. package/stack-template/docs/wakii-playbook.md +172 -0
  816. package/stack-template/docs/walkthrough.md +204 -0
  817. package/stack-template/orca.yaml +146 -0
  818. package/stack-template/package.json +19 -0
  819. package/stack-template/platform/.env.example +72 -0
  820. package/stack-template/platform/conventions/01-dockerfile-pattern.md +78 -0
  821. package/stack-template/platform/conventions/02-healthcheck.md +26 -0
  822. package/stack-template/platform/conventions/03-logging.md +41 -0
  823. package/stack-template/platform/conventions/04-error-envelope.md +41 -0
  824. package/stack-template/platform/conventions/05-ports.md +38 -0
  825. package/stack-template/platform/conventions/06-configuration.md +25 -0
  826. package/stack-template/platform/conventions/07-cors.md +23 -0
  827. package/stack-template/platform/conventions/08-gateway-and-remotes.md +33 -0
  828. package/stack-template/platform/conventions/09-async-messaging.md +42 -0
  829. package/stack-template/platform/conventions/README.md +15 -0
  830. package/stack-template/platform/docker-compose.yml +255 -0
  831. package/stack-template/platform/gateway/nginx/nginx.conf +137 -0
  832. package/stack-template/platform/postgres/init/01-init.sh +55 -0
  833. package/stack-template/pnpm-lock.yaml +15992 -0
  834. package/stack-template/pnpm-workspace.yaml +24 -0
  835. package/stack-template/scripts/scaffold/scaffold.sh +110 -0
  836. package/stack-template/scripts/smoke/e2e.sh +305 -0
  837. package/stack-template/scripts/snapshot-stack-template.sh +84 -0
  838. package/stack-template/services/auth-svc/.dockerignore +5 -0
  839. package/stack-template/services/auth-svc/Dockerfile +32 -0
  840. package/stack-template/services/auth-svc/README.md +101 -0
  841. package/stack-template/services/auth-svc/drizzle/0000_init.sql +25 -0
  842. package/stack-template/services/auth-svc/drizzle/meta/0000_snapshot.json +190 -0
  843. package/stack-template/services/auth-svc/drizzle/meta/_journal.json +13 -0
  844. package/stack-template/services/auth-svc/drizzle.config.ts +10 -0
  845. package/stack-template/services/auth-svc/package.json +35 -0
  846. package/stack-template/services/auth-svc/pnpm-lock.yaml +2425 -0
  847. package/stack-template/services/auth-svc/src/app.test.ts +403 -0
  848. package/stack-template/services/auth-svc/src/app.ts +103 -0
  849. package/stack-template/services/auth-svc/src/auth-crypto.test.ts +32 -0
  850. package/stack-template/services/auth-svc/src/auth-crypto.ts +25 -0
  851. package/stack-template/services/auth-svc/src/db/client.ts +24 -0
  852. package/stack-template/services/auth-svc/src/db/migrate.ts +72 -0
  853. package/stack-template/services/auth-svc/src/db/schema.ts +39 -0
  854. package/stack-template/services/auth-svc/src/db/seed.ts +60 -0
  855. package/stack-template/services/auth-svc/src/env.test.ts +55 -0
  856. package/stack-template/services/auth-svc/src/env.ts +57 -0
  857. package/stack-template/services/auth-svc/src/logger.ts +31 -0
  858. package/stack-template/services/auth-svc/src/plugins/auth.ts +70 -0
  859. package/stack-template/services/auth-svc/src/repo.drizzle.integration.test.ts +182 -0
  860. package/stack-template/services/auth-svc/src/repo.drizzle.ts +144 -0
  861. package/stack-template/services/auth-svc/src/repo.test-support.ts +168 -0
  862. package/stack-template/services/auth-svc/src/repo.ts +60 -0
  863. package/stack-template/services/auth-svc/src/routes/auth.ts +193 -0
  864. package/stack-template/services/auth-svc/src/routes/health.ts +40 -0
  865. package/stack-template/services/auth-svc/src/server.ts +54 -0
  866. package/stack-template/services/auth-svc/tsconfig.json +20 -0
  867. package/stack-template/services/go-svc/.dockerignore +5 -0
  868. package/stack-template/services/go-svc/Dockerfile +19 -0
  869. package/stack-template/services/go-svc/README.md +93 -0
  870. package/stack-template/services/go-svc/cmd/server/main.go +105 -0
  871. package/stack-template/services/go-svc/go.mod +12 -0
  872. package/stack-template/services/go-svc/internal/api/auth.go +83 -0
  873. package/stack-template/services/go-svc/internal/api/auth_test.go +92 -0
  874. package/stack-template/services/go-svc/internal/api/envelope.go +61 -0
  875. package/stack-template/services/go-svc/internal/api/envelope_test.go +51 -0
  876. package/stack-template/services/go-svc/internal/api/fakes_test.go +105 -0
  877. package/stack-template/services/go-svc/internal/api/feed.go +98 -0
  878. package/stack-template/services/go-svc/internal/api/feed_test.go +118 -0
  879. package/stack-template/services/go-svc/internal/api/health.go +34 -0
  880. package/stack-template/services/go-svc/internal/api/health_test.go +46 -0
  881. package/stack-template/services/go-svc/internal/api/json.go +13 -0
  882. package/stack-template/services/go-svc/internal/api/middleware.go +82 -0
  883. package/stack-template/services/go-svc/internal/api/middleware_test.go +48 -0
  884. package/stack-template/services/go-svc/internal/api/openapi/activity.yaml +196 -0
  885. package/stack-template/services/go-svc/internal/api/openapi.go +29 -0
  886. package/stack-template/services/go-svc/internal/api/openapi_test.go +38 -0
  887. package/stack-template/services/go-svc/internal/api/router.go +86 -0
  888. package/stack-template/services/go-svc/internal/api/stats.go +63 -0
  889. package/stack-template/services/go-svc/internal/api/stats_test.go +83 -0
  890. package/stack-template/services/go-svc/internal/api/types.go +32 -0
  891. package/stack-template/services/go-svc/internal/apperr/apperr.go +9 -0
  892. package/stack-template/services/go-svc/internal/config/config.go +115 -0
  893. package/stack-template/services/go-svc/internal/config/config_test.go +92 -0
  894. package/stack-template/services/go-svc/internal/consumer/envelope.go +78 -0
  895. package/stack-template/services/go-svc/internal/consumer/envelope_test.go +154 -0
  896. package/stack-template/services/go-svc/internal/consumer/handler.go +91 -0
  897. package/stack-template/services/go-svc/internal/consumer/handler_test.go +136 -0
  898. package/stack-template/services/go-svc/internal/consumer/producer.go +117 -0
  899. package/stack-template/services/go-svc/internal/consumer/runner.go +194 -0
  900. package/stack-template/services/go-svc/internal/consumer/runner_test.go +351 -0
  901. package/stack-template/services/go-svc/internal/logging/logging.go +49 -0
  902. package/stack-template/services/go-svc/internal/model/model.go +37 -0
  903. package/stack-template/services/go-svc/internal/resolve/resolver.go +134 -0
  904. package/stack-template/services/go-svc/internal/resolve/resolver_test.go +82 -0
  905. package/stack-template/services/go-svc/internal/resolve/token.go +130 -0
  906. package/stack-template/services/go-svc/internal/resolve/token_test.go +151 -0
  907. package/stack-template/services/go-svc/internal/store/events.go +71 -0
  908. package/stack-template/services/go-svc/internal/store/migrate.go +90 -0
  909. package/stack-template/services/go-svc/internal/store/migrate_test.go +34 -0
  910. package/stack-template/services/go-svc/internal/store/migrations/0001_create_events.sql +20 -0
  911. package/stack-template/services/go-svc/internal/store/migrations/0002_widen_action_cascade.sql +14 -0
  912. package/stack-template/services/go-svc/internal/store/store.go +65 -0
  913. package/stack-template/services/go-svc/internal/store/tasks.go +109 -0
  914. package/stack-template/services/go-svc/internal/swagger/assets/LICENSE +202 -0
  915. package/stack-template/services/go-svc/internal/swagger/assets/NOTICE +2 -0
  916. package/stack-template/services/go-svc/internal/swagger/assets/favicon-16x16.png +0 -0
  917. package/stack-template/services/go-svc/internal/swagger/assets/favicon-32x32.png +0 -0
  918. package/stack-template/services/go-svc/internal/swagger/assets/swagger-ui-bundle.js +2 -0
  919. package/stack-template/services/go-svc/internal/swagger/assets/swagger-ui.css +3 -0
  920. package/stack-template/services/go-svc/internal/swagger/index.html +28 -0
  921. package/stack-template/services/go-svc/internal/swagger/swagger.go +38 -0
  922. package/stack-template/services/go-svc/test/integration/integration_test.go +523 -0
  923. package/stack-template/services/node-svc/.dockerignore +5 -0
  924. package/stack-template/services/node-svc/Dockerfile +27 -0
  925. package/stack-template/services/node-svc/README.md +155 -0
  926. package/stack-template/services/node-svc/drizzle/0000_init.sql +17 -0
  927. package/stack-template/services/node-svc/drizzle/0001_status-assignment-failed.sql +2 -0
  928. package/stack-template/services/node-svc/drizzle/0002_outbox-table.sql +7 -0
  929. package/stack-template/services/node-svc/drizzle/meta/0000_snapshot.json +136 -0
  930. package/stack-template/services/node-svc/drizzle/meta/0001_snapshot.json +136 -0
  931. package/stack-template/services/node-svc/drizzle/meta/0002_snapshot.json +180 -0
  932. package/stack-template/services/node-svc/drizzle/meta/_journal.json +27 -0
  933. package/stack-template/services/node-svc/drizzle.config.ts +10 -0
  934. package/stack-template/services/node-svc/package.json +39 -0
  935. package/stack-template/services/node-svc/pnpm-lock.yaml +2706 -0
  936. package/stack-template/services/node-svc/src/app.test.ts +611 -0
  937. package/stack-template/services/node-svc/src/app.ts +126 -0
  938. package/stack-template/services/node-svc/src/clients/spring.ts +53 -0
  939. package/stack-template/services/node-svc/src/compensation-consumer.test.ts +157 -0
  940. package/stack-template/services/node-svc/src/compensation-consumer.ts +170 -0
  941. package/stack-template/services/node-svc/src/db/client.ts +23 -0
  942. package/stack-template/services/node-svc/src/db/migrate.ts +63 -0
  943. package/stack-template/services/node-svc/src/db/schema-diff.test.ts +252 -0
  944. package/stack-template/services/node-svc/src/db/schema.ts +64 -0
  945. package/stack-template/services/node-svc/src/env.ts +52 -0
  946. package/stack-template/services/node-svc/src/logger.ts +18 -0
  947. package/stack-template/services/node-svc/src/outbox-relay.test.ts +141 -0
  948. package/stack-template/services/node-svc/src/outbox-relay.ts +182 -0
  949. package/stack-template/services/node-svc/src/plugins/auth.ts +76 -0
  950. package/stack-template/services/node-svc/src/repo.drizzle.test.ts +182 -0
  951. package/stack-template/services/node-svc/src/repo.drizzle.ts +158 -0
  952. package/stack-template/services/node-svc/src/repo.ts +73 -0
  953. package/stack-template/services/node-svc/src/routes/health.ts +42 -0
  954. package/stack-template/services/node-svc/src/routes/tasks.ts +287 -0
  955. package/stack-template/services/node-svc/src/server.ts +91 -0
  956. package/stack-template/services/node-svc/src/types/api.d.ts +391 -0
  957. package/stack-template/services/node-svc/src/types/log.ts +3 -0
  958. package/stack-template/services/node-svc/tsconfig.json +20 -0
  959. package/stack-template/services/spring-svc/.dockerignore +5 -0
  960. package/stack-template/services/spring-svc/.mvn/wrapper/maven-wrapper.properties +20 -0
  961. package/stack-template/services/spring-svc/Dockerfile +22 -0
  962. package/stack-template/services/spring-svc/README.md +121 -0
  963. package/stack-template/services/spring-svc/mvnw +332 -0
  964. package/stack-template/services/spring-svc/mvnw.cmd +206 -0
  965. package/stack-template/services/spring-svc/pom.xml +144 -0
  966. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/SpringSvcApplication.java +12 -0
  967. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/Team.java +64 -0
  968. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/TeamRepository.java +34 -0
  969. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/User.java +72 -0
  970. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/domain/UserRepository.java +10 -0
  971. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/logging/LowercaseLevelJsonProvider.java +24 -0
  972. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/security/JwtAuthFilter.java +89 -0
  973. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/security/JwtVerifier.java +48 -0
  974. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/service/TeamService.java +84 -0
  975. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ApiError.java +15 -0
  976. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ApiException.java +37 -0
  977. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/DevCorsConfig.java +41 -0
  978. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ErrorEnvelope.java +27 -0
  979. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/GlobalExceptionHandler.java +90 -0
  980. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/HealthController.java +46 -0
  981. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/ReadinessService.java +40 -0
  982. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/TeamController.java +79 -0
  983. package/stack-template/services/spring-svc/src/main/java/com/example/springsvc/web/UserController.java +187 -0
  984. package/stack-template/services/spring-svc/src/main/java/db/migration/V2__SeedUsers.java +66 -0
  985. package/stack-template/services/spring-svc/src/main/resources/application.yml +42 -0
  986. package/stack-template/services/spring-svc/src/main/resources/db/migration/V1__init.sql +24 -0
  987. package/stack-template/services/spring-svc/src/main/resources/logback-spring.xml +34 -0
  988. package/stack-template/services/spring-svc/src/main/resources/openapi/users.yaml +345 -0
  989. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/logging/LogShapeTest.java +39 -0
  990. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/security/JwtAuthFilterTest.java +106 -0
  991. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/seed/SeedMatchIntegrationTest.java +68 -0
  992. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/service/TeamServiceRollbackTest.java +122 -0
  993. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/DevCorsTest.java +45 -0
  994. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/HealthCheckTest.java +56 -0
  995. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/TeamApiTest.java +139 -0
  996. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/TestPingController.java +21 -0
  997. package/stack-template/services/spring-svc/src/test/java/com/example/springsvc/web/UserApiTest.java +182 -0
  998. package/stack-template/stack-manifest.json +285 -0
@@ -0,0 +1,132 @@
1
+ name: services-spring-svc
2
+
3
+ # SF-3 (FI-71) — copy từ .github/workflow-templates/services-ci.yml.example
4
+ # path-filter THÊM contracts/openapi/users.yaml (drift-guard không mù khi đổi contract)
5
+ on:
6
+ push:
7
+ branches: ["**"]
8
+ paths:
9
+ - "services/spring-svc/**"
10
+ - "platform/docker-compose.yml"
11
+ - ".github/workflows/services-spring-svc.yml"
12
+ - "contracts/openapi/users.yaml"
13
+ pull_request:
14
+ paths:
15
+ - "services/spring-svc/**"
16
+ - "platform/docker-compose.yml"
17
+ - ".github/workflows/services-spring-svc.yml"
18
+ - "contracts/openapi/users.yaml"
19
+
20
+ permissions:
21
+ contents: read # least-privilege (P2 security-audit SF-7 — follow-up repo-wide)
22
+
23
+ jobs:
24
+ build-test:
25
+ name: build + test (mvnw verify — Postgres thật)
26
+ runs-on: ubuntu-latest
27
+ services:
28
+ postgres:
29
+ image: postgres:16-alpine
30
+ env:
31
+ # ĐỦ cho platform/postgres/init/01-init.sh (set -euo pipefail) chạy trọn
32
+ POSTGRES_USER: boilerplate
33
+ POSTGRES_PASSWORD: change-me-postgres
34
+ POSTGRES_DB: boilerplate
35
+ NODE_SVC_DB_PASSWORD: change-me-node
36
+ SPRING_SVC_DB_PASSWORD: change-me-spring
37
+ GO_SVC_DB_PASSWORD: change-me-go
38
+ GO_READONLY_DB_PASSWORD: change-me-goreadonly
39
+ AUTH_SVC_DB_PASSWORD: change-me-auth
40
+ ports:
41
+ - 5432:5432
42
+ options: >-
43
+ --health-cmd "pg_isready -U boilerplate -d boilerplate"
44
+ --health-interval 5s
45
+ --health-timeout 3s
46
+ --health-retries 12
47
+ env:
48
+ JWT_SECRET: ci-smoke-secret-placeholder-not-real-32chars
49
+ USERS_FIXTURE_PATH: ${{ github.workspace }}/contracts/auth/users.json
50
+ SPRING_DATASOURCE_URL: jdbc:postgresql://localhost:5432/boilerplate
51
+ SPRING_DATASOURCE_USERNAME: spring_svc
52
+ SPRING_DATASOURCE_PASSWORD: change-me-spring
53
+ steps:
54
+ - uses: actions/checkout@v4
55
+ - name: Apply postgres init script SF-1 (schemas + roles + search_path — nguyên văn platform/postgres/init)
56
+ # Service container KHÔNG mount init (mount workspace trước checkout = dir root-owned
57
+ # → checkout EACCES); chạy script sau checkout qua psql client của runner.
58
+ env:
59
+ PGHOST: localhost
60
+ PGPASSWORD: change-me-postgres
61
+ POSTGRES_USER: boilerplate
62
+ POSTGRES_DB: boilerplate
63
+ NODE_SVC_DB_PASSWORD: change-me-node
64
+ SPRING_SVC_DB_PASSWORD: change-me-spring
65
+ GO_SVC_DB_PASSWORD: change-me-go
66
+ GO_READONLY_DB_PASSWORD: change-me-goreadonly
67
+ AUTH_SVC_DB_PASSWORD: change-me-auth
68
+ run: bash platform/postgres/init/01-init.sh
69
+ - uses: actions/setup-java@v4
70
+ with:
71
+ distribution: temurin
72
+ java-version: 21
73
+ cache: maven
74
+ - name: mvnw verify (Flyway seed + seed-id-match + JWT + users/teams + health/log/cors)
75
+ working-directory: services/spring-svc
76
+ run: ./mvnw -B verify
77
+
78
+ docker-build:
79
+ name: docker build (multi-stage — conventions/01)
80
+ runs-on: ubuntu-latest
81
+ steps:
82
+ - uses: actions/checkout@v4
83
+ - name: Build image (codegen snapshot users.yaml nằm trong context)
84
+ run: docker build -t spring-svc:ci services/spring-svc
85
+
86
+ boot-smoke:
87
+ name: boot-smoke (up + health + login + 401-from-service)
88
+ runs-on: ubuntu-latest
89
+ env:
90
+ JWT_SECRET: ci-smoke-secret-placeholder-not-real-32chars
91
+ steps:
92
+ - uses: actions/checkout@v4
93
+ - name: Boot postgres + auth-svc + gateway + spring-svc (compose thật, init script chạy)
94
+ run: |
95
+ docker compose -f platform/docker-compose.yml --env-file platform/.env.example \
96
+ up -d --build postgres auth-svc gateway spring-svc
97
+ - name: Smoke — naked /healthz + /readyz (Flyway + seed xong) theo conventions/02
98
+ run: |
99
+ for i in $(seq 1 60); do
100
+ curl -sf http://localhost:8081/readyz >/dev/null && break
101
+ sleep 2
102
+ done
103
+ curl -sf http://localhost:8081/healthz | grep -q '"status":"ok"'
104
+ curl -sf http://localhost:8081/readyz | grep -q '"status":"ok"'
105
+ - name: Smoke — api-docs phục vụ + chứa FINAL paths (swagger acceptance, host-port)
106
+ run: |
107
+ curl -sf http://localhost:8081/v3/api-docs | grep -q '/api/users/users'
108
+ curl -sf http://localhost:8081/v3/api-docs | grep -q '/api/users/teams'
109
+ - name: Login auth-svc qua gateway → GET fixture user (seed id khớp token sub)
110
+ run: |
111
+ TOKEN=$(curl -sf -X POST http://localhost:8080/api/auth/login \
112
+ -H 'Content-Type: application/json' \
113
+ -d '{"email":"alice@demo.local","password":"demo-password"}' | jq -r '.accessToken')
114
+ test -n "$TOKEN" && test "$TOKEN" != "null"
115
+ curl -sf http://localhost:8080/api/users/users/11111111-1111-4111-8111-111111111111 \
116
+ -H "Authorization: Bearer $TOKEN" | jq -e '.email == "alice@demo.local"'
117
+ - name: 401 TỪ SERVICE — direct :8081 bypass gateway presence-check (acceptance sf-3)
118
+ run: |
119
+ no_token=$(curl -s -o /dev/null -w '%{http_code}' http://localhost:8081/api/users/users/11111111-1111-4111-8111-111111111111)
120
+ echo "no-token → $no_token"; test "$no_token" = "401"
121
+ garbage=$(curl -s -o /dev/null -w '%{http_code}' -H "Authorization: Bearer garbage" http://localhost:8081/api/users/users/11111111-1111-4111-8111-111111111111)
122
+ echo "garbage-token → $garbage"; test "$garbage" = "401"
123
+
124
+ drift-guard:
125
+ name: drift-guard — snapshot users.yaml bit-identical contracts
126
+ runs-on: ubuntu-latest
127
+ steps:
128
+ - uses: actions/checkout@v4
129
+ - name: diff snapshot vs contract (lệch = fail)
130
+ run: |
131
+ diff contracts/openapi/users.yaml services/spring-svc/src/main/resources/openapi/users.yaml \
132
+ || { echo "::error::snapshot lệch contracts — copy lại (README ADR #2)"; exit 1; }
@@ -0,0 +1,78 @@
1
+ name: shell
2
+
3
+ # SF-5 (FI-73) — shell MF host: typecheck + vitest + rspack build + boot-smoke (docker build + up + HTTP 200).
4
+ # Lưu ý: job chạy trên pnpm-lock.yaml của NHÁNH — nếu SF-6 đang regenerate song song, lockfile
5
+ # stale là việc coordinator resolve khi merge, KHÔNG phải bug code (P2 plan-critic note).
6
+ on:
7
+ push:
8
+ branches: ["**"]
9
+ paths:
10
+ - "app/shell/**"
11
+ - "app/shared/**"
12
+ - "pnpm-workspace.yaml"
13
+ - "pnpm-lock.yaml"
14
+ - ".github/workflows/shell.yml"
15
+ pull_request:
16
+ paths:
17
+ - "app/shell/**"
18
+ - "app/shared/**"
19
+ - "pnpm-workspace.yaml"
20
+ - "pnpm-lock.yaml"
21
+ - ".github/workflows/shell.yml"
22
+
23
+ permissions:
24
+ contents: read # least-privilege (P2 security-audit SF-7 — follow-up repo-wide)
25
+
26
+ jobs:
27
+ build-test:
28
+ name: typecheck + vitest + build
29
+ runs-on: ubuntu-latest
30
+ steps:
31
+ - uses: actions/checkout@v4
32
+ - uses: pnpm/action-setup@v4
33
+ with:
34
+ version: 9.15.9
35
+ - uses: actions/setup-node@v4
36
+ with:
37
+ node-version: 22
38
+ cache: pnpm
39
+ - name: Install (workspace, frozen lockfile)
40
+ run: pnpm install --frozen-lockfile
41
+ - name: Typecheck
42
+ run: pnpm --filter @wakii/shell typecheck
43
+ - name: Tests (vitest + testing-library)
44
+ run: pnpm --filter @wakii/shell test
45
+ - name: coverage gate (ngưỡng trong vitest.config — chống rơi tự do)
46
+ run: pnpm --filter @wakii/shell exec vitest run --coverage
47
+ - name: Build (rspack production)
48
+ run: pnpm --filter @wakii/shell build
49
+ - uses: actions/upload-artifact@v4
50
+ with:
51
+ name: shell-dist
52
+ path: app/shell/dist/
53
+ retention-days: 3
54
+
55
+ boot-smoke:
56
+ name: boot-smoke (docker build + up + 200)
57
+ runs-on: ubuntu-latest
58
+ needs: build-test
59
+ steps:
60
+ - uses: actions/checkout@v4
61
+ - name: Docker build (multi-stage node→nginx, context = repo root)
62
+ run: docker build -f app/shell/Dockerfile -t boilerplate-shell .
63
+ - name: Up container
64
+ run: docker run -d --name shell -p 3000:3000 boilerplate-shell
65
+ - name: Smoke — HTTP 200 trên / (SPA index)
66
+ run: |
67
+ for i in $(seq 1 24); do
68
+ if curl -fsS -o /dev/null -w "%{http_code}" http://localhost:3000/ | grep -q 200; then
69
+ echo "boot-smoke OK (HTTP 200)"; exit 0
70
+ fi
71
+ sleep 2
72
+ done
73
+ echo "boot-smoke FAILED — shell không trả 200 sau 48s"; docker logs shell; exit 1
74
+ - name: Smoke — SPA deep-link fallback (/tasks → 200 index)
75
+ run: |
76
+ code=$(curl -fsS -o /dev/null -w "%{http_code}" http://localhost:3000/tasks)
77
+ [ "$code" = "200" ] || { echo "SPA fallback FAILED ($code)"; exit 1; }
78
+ echo "SPA fallback OK (HTTP 200)"
@@ -0,0 +1,51 @@
1
+ name: ui-kit
2
+
3
+ # ADR-0009 (2026-10-17) — ui-kit design system tách khỏi fe-shared: typecheck + vitest
4
+ # + storybook build gate (docs sống cho primitives + tokens; KHÔNG publish, KHÔNG chromatic).
5
+ # Shell workflow tiếp theo dõi shared/** (logic) — ui-kit đổi chỉ chạy workflow này.
6
+ on:
7
+ push:
8
+ branches: ["**"]
9
+ paths:
10
+ - "app/ui-kit/**"
11
+ - "pnpm-workspace.yaml"
12
+ - "pnpm-lock.yaml"
13
+ - ".github/workflows/ui-kit.yml"
14
+ pull_request:
15
+ paths:
16
+ - "app/ui-kit/**"
17
+ - "pnpm-workspace.yaml"
18
+ - "pnpm-lock.yaml"
19
+ - ".github/workflows/ui-kit.yml"
20
+
21
+ permissions:
22
+ contents: read # least-privilege (chuẩn 8/8 workflows từ 2026-10-17)
23
+
24
+ jobs:
25
+ build-test:
26
+ name: typecheck + vitest + storybook build
27
+ runs-on: ubuntu-latest
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ - uses: pnpm/action-setup@v4
31
+ with:
32
+ version: 9.15.9
33
+ - uses: actions/setup-node@v4
34
+ with:
35
+ node-version: 22
36
+ cache: pnpm
37
+ - name: Install (workspace, frozen lockfile)
38
+ run: pnpm install --frozen-lockfile
39
+ - name: Typecheck
40
+ run: pnpm --filter @wakii/ui-kit typecheck
41
+ - name: Tests (vitest + testing-library)
42
+ run: pnpm --filter @wakii/ui-kit test
43
+ - name: coverage gate (ngưỡng trong vitest.config — chống rơi tự do)
44
+ run: pnpm --filter @wakii/ui-kit exec vitest run --coverage
45
+ - name: Storybook build (gate "build được" — không publish)
46
+ run: pnpm --filter @wakii/ui-kit build-storybook
47
+ - uses: actions/upload-artifact@v4
48
+ with:
49
+ name: ui-kit-storybook-static
50
+ path: app/ui-kit/storybook-static/
51
+ retention-days: 3
@@ -0,0 +1,14 @@
1
+ # husky commit-msg — validate conventional commit (docs/git-flow.md). LỊCH SỬ: trước
2
+ # đây mirror git-guard CI — 2026-10-17 Actions DISABLE (billing) → hook + pre-push
3
+ # là lớp chính; git-guard.yml giữ trong repo để re-active khi CI trở lại.
4
+ MSG="$(head -1 "$1")"
5
+
6
+ # merge commits ("Merge pull request #N" / "Merge remote-tracking...") — ngoại lệ
7
+ echo "$MSG" | grep -qE '^Merge ' && exit 0
8
+
9
+ if ! echo "$MSG" | grep -qE '^(feat|fix|refactor|docs|test|chore|style|perf|build|ci|revert)(\([a-z0-9./-]+\))?!?: .+'; then
10
+ echo "✗ Commit message vi phạm convention (docs/git-flow.md): \"$MSG\"" >&2
11
+ echo ' Đúng: <type>(<scope>): <mô tả> — vd: fix(go-svc): recentEvents test chết theo lịch' >&2
12
+ echo ' Bỏ qua khẩn: git commit --no-verify (git-guard CI vẫn chặn trên PR)' >&2
13
+ exit 1
14
+ fi
@@ -0,0 +1,51 @@
1
+ # pre-push — branch rule + FE checks cho package bị đổi (husky hoá git-guard + CI shell/remotes/ui-kit)
2
+ # CI Actions đã DISABLE (billing) → hook này là lớp chính. Cài: pnpm install (root prepare).
3
+ BRANCH="$(git rev-parse --abbrev-ref HEAD)"
4
+
5
+ # 1) Branch rule — mirror git-guard (docs/git-flow.md)
6
+ if ! echo "$BRANCH" | grep -qE '^wakii-dev/(story|sf|fix|docs|chore|feat)-[a-z0-9][a-z0-9-]*$'; then
7
+ echo "✗ pre-push: branch '$BRANCH' vi phạm rule wakii-dev/<story|sf|fix|docs|chore|feat>-<slug>" >&2
8
+ exit 1
9
+ fi
10
+
11
+ # 2) FE checks theo path đổi (so với origin/main; fallback HEAD@{push})
12
+ BASE="origin/main"
13
+ git fetch origin main --quiet 2>/dev/null || true
14
+ CHANGED="$(git diff --name-only "$BASE...HEAD" 2>/dev/null || git diff --name-only "$BASE")"
15
+
16
+ run_pkg() { # $1=filter-name $2...=lệnh
17
+ local pkg="$1"; shift
18
+ echo "▸ checks: @wakii/$pkg — $*"
19
+ pnpm --filter "@wakii/$pkg" "$@" || { echo "✗ FAIL @wakii/$pkg $*" >&2; exit 1; }
20
+ }
21
+
22
+ PKG_RUN=0
23
+ case "$CHANGED" in
24
+ *app/ui-kit*|*pnpm-lock.yaml*|*pnpm-workspace.yaml*)
25
+ run_pkg ui-kit typecheck
26
+ run_pkg ui-kit test
27
+ run_pkg ui-kit build-storybook
28
+ PKG_RUN=1 ;;
29
+ esac
30
+ case "$CHANGED" in
31
+ *app/shell*|*app/ui-kit*|*app/shared*|*pnpm-lock.yaml*|*pnpm-workspace.yaml*)
32
+ run_pkg shell typecheck
33
+ run_pkg shell test
34
+ run_pkg shell build
35
+ PKG_RUN=1 ;;
36
+ esac
37
+ case "$CHANGED" in
38
+ *app/remotes/tasks*|*app/ui-kit*|*app/shared*|*pnpm-lock.yaml*|*pnpm-workspace.yaml*)
39
+ run_pkg remote-tasks typecheck
40
+ run_pkg remote-tasks test
41
+ PKG_RUN=1 ;;
42
+ esac
43
+ case "$CHANGED" in
44
+ *app/remotes/activity*|*app/ui-kit*|*app/shared*|*pnpm-lock.yaml*|*pnpm-workspace.yaml*)
45
+ run_pkg remote-activity typecheck
46
+ run_pkg remote-activity test
47
+ PKG_RUN=1 ;;
48
+ esac
49
+
50
+ [ "$PKG_RUN" = "1" ] || echo "▸ không có thay đổi FE — bỏ qua package checks"
51
+ echo "✓ pre-push OK ($BRANCH)"
@@ -0,0 +1,17 @@
1
+ # Spectral ruleset — lint contracts/openapi/*.yaml trong CI (workflows/contracts.yml)
2
+ extends:
3
+ - spectral:oas
4
+
5
+ # Boilerplate điều chỉnh: specs tự-contained (mỗi repo-con copy đi độc lập được —
6
+ # không $ref chéo file), nên tắt các rule khuyến-khích không áp dụng cho template nội bộ.
7
+ # Error envelope chung (conventions/04) là convention-by-review — mirror kiểm tay
8
+ # trong components.schemas.Error của cả 4 specs (đồng bộ khi đổi).
9
+ rules:
10
+ # Không bắt buộc license trên sample API
11
+ info-license: off
12
+ # Contact = epic FI-62 nội bộ — không cần contact object formal
13
+ info-contact: off
14
+ # Tag tự do — sample domain nhỏ, không cần gắn liên kết ngoài
15
+ oas3-api-servers: off
16
+ # Mọi operation đã có summary + description cấp path/info — không ép description riêng từng op
17
+ operation-description: off
@@ -0,0 +1,197 @@
1
+ # AGENTS.md — design system `@wakii/ui-kit` cho AI agents
2
+
3
+ Tài liệu này cho AI agent đọc TRƯỚC khi viết UI dùng ui-kit. Recipes code đầy đủ:
4
+ [docs/ai/recipes.md](docs/ai/recipes.md). API sống: Storybook :6006. Đổi behavior:
5
+ [app/ui-kit/CHANGELOG.md](app/ui-kit/CHANGELOG.md).
6
+
7
+ ## Bản đồ feature → components
8
+
9
+ | Feature cần làm | Dùng components |
10
+ |---|---|
11
+ | Login / Register / form có validate | `useForm` + `zod` (schema) + `Field` + `Input` + `Button` — recipe 1 |
12
+ | Trang CRUD (bảng + tìm kiếm + sửa) | `Table` + `Select` (filter) + `Pagination` + `Modal` (form) + `message` — recipe 2 |
13
+ | Thanh filter | `Select` + `Input` (allowClear) + `Button` reset — recipe 3 |
14
+ | Wizard nhiều bước | `Steps` + state `current` + `Button` — recipe 4 |
15
+ | Upload kèm preview | `Upload` / `UploadDropzone` + `Progress` + `Image` — recipe 5 |
16
+ | Dashboard | `Card` + `Icon` + pill delta + `Chart` + `Timeline` + `EmptyState` — recipe 6 |
17
+ | Master-detail | `List`/`Avatar` + `Drawer` — recipe 7 |
18
+ | Thông báo | `message.*` (toast gọn) / `notification` (có title) / `Badge` trên bell — recipe 8 |
19
+ | Trang settings | `Tabs` + `Switch` + `Field`/`Input` — recipe 9 |
20
+ | Landing hero | `Button` + `Tag` + `Typography` + `Divider` + `Space` — recipe 10 |
21
+ | Landing sống động (hero trôi + block hiện dần + KPI đếm số + panel thu/mở) | `Parallax` + `Reveal` + `CountUp` trong `Statistic`/`Row`/`Col` — recipe 16 · kết hợp `Fade`/`Zoom`/`CollapseTransition` — recipe 17 |
22
+ | Nav app | `Sidebar` (collapsible) + `Menu` đa cấp + `MenuCompactContext` tự icon-only |
23
+ | Menu ngang | `Menubar` (hover dropdown) · `MegaMenu` (panel multi-column mega) · `TabMenu` (tabs nav) · `SplitButton` · `Dropdown` · `ContextMenu` |
24
+ | Menu trượt cấp (panel/hamburger) | `SlideMenu` (translateX giữa cấp, back + ESC) — recipe 18 |
25
+ | Date/time | `DatePicker` (range/showTime, locale vi/en) · `TimePicker` · `Calendar` |
26
+
27
+ ## Layout & Nav — khi nào dùng
28
+
29
+ | Component | Use when | Most valuable prop | Common combos |
30
+ |---|---|---|---|
31
+ | `Row`/`Col` | 24-col responsive grid — KPI rows, dashboard card mosaics, form column splits | `gutter` on `Row` (number or `[h, v]` px — antd mechanic: negative margin + col padding) | `Col span={24} md={12} xl={6}` mobile-first (xs→xl resolve qua matchMedia) · wrap `Card`/`Statistic` dashboards · nest rows for sub-layouts |
32
+ | `Flex` | One-axis layout fast — toolbars, button rows, stacked forms (skip 24-col math) | `gap` (`'small' \| 'middle' \| 'large'` \| px, default 8) | `vertical` for stacked form fields · justify/align raw CSS values · lighter than `Row`/`Col` when columns don't matter |
33
+ | `Anchor` | In-page TOC with scroll-spy — docs, long settings, detail pages | `items` (`href: '#section-id'` + nested `children` for sub-levels) | `affix` sticky rail beside long content · `offsetTop` to clear sticky headers · `onClick` for analytics · `getContainer` for inner scroll areas |
34
+ | `Layout` | App frame — Header/Content/Footer/Sider zones (antd Layout parity) | `Layout.Sider` (`width`/`collapsed`/`collapsedWidth` — mặc định 200↔80 khớp Sidebar) | `Layout hasSider` + `Sidebar` inside Sider · `Header sticky` top bar · `useSiderCollapsed()` cho UI đọc trạng thái thu gọn |
35
+
36
+ ## Menu family — khi nào dùng
37
+
38
+ | Component | Use when | Most valuable prop | Common combos |
39
+ |---|---|---|---|
40
+ | `MegaMenu` | Top bar + panel dropdown MULTI-COLUMN (2 cấp: group = cột → leaf) — landing/app header nhiều nhóm chức năng | `items[].children` (mỗi group render 1 cột, grid tự theo số group) | hover HOẶC click mở · ESC/click-ngoài/leave đóng (trả focus trigger) · `role=menu` + `aria-expanded` · leaf `danger` đỏ · `icon` từ bộ Icon |
41
+ | `SlideMenu` | Menu trượt ngang GIỮA CÁC CẤP (panel hẹp, mobile/hamburger, cây sâu không giới hạn) | `items[].children` (đệ quy — translateX(-100%×depth), 0 deps) | back bar chevron-left + nhãn cấp cha · ESC pop cấp · trang ẩn `inert` + `aria-hidden` · `ariaLabel` cho landmark nav |
42
+
43
+ So sánh nhanh: `Menubar` = dropdown 1 cấp gọn · `MegaMenu` = panel đa cột duyệt theo nhóm · `SlideMenu` = cấp sâu trong không gian hẹp — recipe 18.
44
+
45
+ ## Data Display — khi nào dùng
46
+
47
+ | Component | Use when | Most valuable prop | Common combos |
48
+ |---|---|---|---|
49
+ | `Avatar` | Identity chip for a user/entity — letter initials by default, photo when `src` loads (fade-in; broken src falls back to initials) | `src` (falls back to initials children — on load fail too) | `AvatarGroup` (stacks) · `List` rows · `Card` extra |
50
+ | `AvatarGroup` | Stacked team/assignee faces with overflow | `max` — folds the rest into a "+N" pill whose tooltip lists hidden names | `Card` head extra · `Table` assignee cell · `Tooltip` built-in per avatar |
51
+ | `Badge` | Status pill (task/activity variants) OR antd-style count badge — corner count on children, standalone status dot | `variant` pill · `count`+`overflowCount` (99+) · `dot` · `status`+`text` · `offset` | `Table` status cells · bell `count` corner · filter status legend |
52
+ | `Card` | Grouped content panel with head/body/actions | `title` (pair with `hoverable` for clickable cards) · `loading` skeleton body · `size="small"` dense | `Card`+`Statistic` dashboard · `Card`+`Chart` · `Card`+`List` |
53
+ | `Carousel` | Sliding content — hero banner, media strip, onboarding steps | `itemsPerView` (1 = hero, 3-4 = card rail) | `Carousel`+`Image` gallery · built-in indicators/navigators/keyboard |
54
+ | `Chart` | Data viz: bar/line/pie/doughnut/radar | `config` (chart.js shape, per-dataset colors; per-dataset `type` for mixed) | `Card`+`Chart` dashboard · `fallback` node for missing peer-dep `chart.js` |
55
+ | `Collapse` | Progressive disclosure — FAQ, settings sections, logs | `items` (key/label/children, per-item `disabled`) · `accordion` (one open at a time) | inside `Card` body · default-open key via `defaultActiveKeys` |
56
+ | `Descriptions` | Label:value readout of an entity (task detail, meta panel) | `items` · `size="small"` + `colon` | `Drawer`/`Modal` detail pane · `Card` body · `bordered` for dense data |
57
+ | `Divider` | Separate/space content sections | `children` — text label embedded in the rule · `orientation="left|right"` | `Typography` sections · landing hero · settings groups |
58
+ | `Draggable` / `DropZone` | Native HTML5 drag & drop primitives — reorder lists, drop targets (0 deps) | `Draggable data` (JSON payload qua dataTransfer, MIME riêng) · `DropZone onDrop(data)` parse ngược | `DragDropProvider` + keyboard: Space nhặt (`aria-pressed`) → Arrows zone → Enter thả / Esc hủy · `Draggable handle` giới hạn vùng kéo · `disabled` khoá card · `DropZone activeClass` thay highlight · `accept` lọc theo `dataTransfer.types` · ⚠️ không hỗ trợ touch — peer-dep dnd-kit nếu cần |
59
+ | `Galleria` | Swipeable image gallery with dot indicators | `images` (per-image `caption` optional) | `Image` (click-to-zoom) for detail view · `Carousel` for non-image slides |
60
+ | `Image` (`UiImage`) | Image with click-to-zoom preview overlay | `alt` (also the preview dialog's aria-label) | `Galleria` grids · `Upload` preview · `Table` attachment cells |
61
+ | `KanbanBoard` | Kanban board — `columns` controlled (consumer sở hữu state), card kéo thả giữa/vị trí trong cột | `onCardMove(cardKey, fromColKey, toColKey, toIndex)` — toIndex là vị trí CUỐI sau khi card rời nguồn | `wipLimit` cột đầy từ chối drop + `border-st-fail` + aria-live · `tag`→Tag · `left` slot→Avatar · `renderCard` custom body · keyboard full (Tab → Space → ↑↓ vị trí / ←→ cột → Enter/Esc) · ⚠️ native DnD không touch |
62
+ | `List` | Repeating rows from data — feeds, task digests | `renderItem` (full row control) | `List`+`Avatar`+`Tag` rows · `pagination` client-side · built-in `loading` skeleton + `EmptyState` |
63
+ | `OrgChart` | Org tree dọc — company/team hierarchy, approval chains, reporting lines | `data` root đơn (`type` `'dept'\|'person'` đổi nền+icon) · `defaultCollapsedKeys` gập nhánh sẵn | `selectedKey`+`onSelect` highlight node (viền accent + aria-selected) · chevron góc card collapse subtree · connector line thuần CSS (0 đo đạc) · `role=tree/treeitem/group` |
64
+ | `Schedule` | Month calendar (FullCalendar dayGrid) for date-driven events — sprints, deadlines, bookings | `events` (+ `onEventClick`) | `fallback` node when peer-dep `@fullcalendar/*` missing · `Card` wrapper · heavy: subpath `@wakii/ui-kit/schedule` |
65
+ | `Segmented` | Compact single-choice switcher with no panels — view period, density, sort mode | `options` (`disabled` per-option) + controlled `value`/`onChange` | swap for `Tabs` when you don't need content panels · toolbar/filter-bar headers |
66
+ | `Skeleton` | Loading placeholder mirroring the real layout before data lands | `variant` (text/row/card/circle/button) + `count` | stack `circle`+`text`+`row` to compose a card · `Table loading` renders its own — prefer that for grids · `classNames` slots (`wrapper`/`bone`) |
67
+ | `Statistic` | Big-number KPI readout (title + value + prefix/suffix) | `value` (+ `prefix`/`suffix`) | `Card` dashboards · `valueStyle` to color by status · tabular-nums built in |
68
+ | `Steps` | Horizontal wizard progress header (done/current/waiting) | `current` (prop-driven, no internal state) | `Button` next/back beneath it (recipe 4) · `aria-current="step"` built in |
69
+ | `Table` | Data grid — sort/filter/paginate/select for CRUD backbones | `columns` (`sortable`/`filterable`/`render`/`align`) | recipe 2 CRUD · `virtual` for 5k+ rows · `selectionMode` for bulk actions · `globalFilter` · `expandable` master-detail rows (recipe 13) · `classNames` slots (`wrapper`/`header`/`row`/`cell`) |
70
+ | `Timesheet` | Weekly hours grid — rows = tasks/projects × 7 day columns (always Mon-start), cell = hours; row/column/grand totals built in for timesheet approval | `rows` (+ `editable` → `onCellChange(rowKey, dayIndex, value)`, clamp 0–24 step 0.5) | `Statistic` weekly total (recipe 15) · `week` + `onWeekChange` prev/next nav · `locale` vi/en · weekend columns shaded · `loading` skeleton |
71
+ | `Tabs` | Switch between content panels in place — settings, detail views | `items` (+ controlled `activeKey`/`onChange`) | settings pages (recipe 9) · `Segmented` when panels aren't needed · `classNames` slots (`wrapper`/`tablist`/`tab`/`panel`) |
72
+ | `Tag` | Tiny label chip — statuses, metadata; `Tag.Checkable` for filter chips | `closable`+`onClose` (consumer removes) · Checkable `checked`+`onChange` | `Table` status cells · `Checkable` chip groups in filter bars · `List` row meta |
73
+ | `Timeline` | Vertical activity feed — dot + text + time per entry | `items` (per-item `color` dot, `label` time) · `mode="alternate|left|right"` (label column) · `pending` hollow dot | `Card` body feeds · audit/history panels (recipe 6) · deploy logs with "rolling out…" tail |
74
+ | `Tree` | Expand/collapse hierarchy — file trees, category nav | `data` (+ `defaultExpandedKeys`; uncontrolled expand state) · `showLine` connector borders | side navigation panels · use `TreeSelect` when a value must be picked |
75
+ | `TreeTable` | Hierarchical data as a grid — file trees with columns, WBS/org with metadata | `data` (recursive `{key, children?, values}`) + `columns` (`header`/`align`/`render`) | `defaultExpandedKeys`/`expandedKeys` + `onRowToggle` · `selectionMode` single/checkbox (+ select-all đếm cả node gập) · indent `--sp-4` × depth · expand animate grid-rows 3-tier clip |
76
+ | `VirtualScroll` | Windowed list for 10k+ rows — mount only the visible window + buffer, GPU translate | `itemSize` (FIXED row height px — dynamic height is a known backlog) | `height` px or `'100%'` (measured after mount) · `onScrollEnd` fires once per bottom-hit for load-more · pair with `List`-style rows · NOT for `Table` (use `Table virtual`) |
77
+
78
+
79
+ ## Forms — khi nào dùng
80
+
81
+ | Component | Use when | Most valuable prop | Common combos |
82
+ |---|---|---|---|
83
+ | `AutoComplete` | Free-text input with type-to-filter suggestions (search-as-type) | `suggestions` — `onChange` gives raw text, `onSelect` gives the picked value | `Field` wrap · `Button` submit · empty `suggestions` → dropdown never opens |
84
+ | `Calendar` | Month grid for inline date browsing/picking (no trigger field) | `value` + `onChange` (controlled selected day) | `locale="vi"\|"en"` · `range` + `onDayHover` (drives DatePicker) · `bare` inside panels |
85
+ | `CascadeSelect` | Hierarchical pick (region → city → ward) through expanding panel columns | `options` (nested `children` define the levels) | `value` is a path array `["hn","bd"]` · keyboard ↑↓/Enter/Esc on the trigger |
86
+ | `Checkbox` | Single on/off decision with a visible label · tri-state parent (chọn một phần) | `checked` boolean\|`null` (null = indeterminate — dash + `aria-checked="mixed"`) · `indeterminate` override kiểu antd + `onChange(bool)` | `disabled` · inside `Field` · select-all header điều khiển list con (cycle true→null→false) · prefer `Switch` for instant-apply settings |
87
+ | `Chips` | Multi-value tag input — Enter adds, × removes, Backspace pops the last | `value: string[]` + `onChange` | `placeholder` hint · `disabled` hides input + remove buttons · duplicates ignored |
88
+ | `ColorPicker` | Color choice: swatch + preset grid + native picker + hex field | `presets` (curated palette; `[]` = native + hex only) | `value` hex · `onChange` fires from preset/native/hex alike |
89
+ | `DatePicker` | Date pick through a trigger + calendar panel | `range` + `showTime` (with `locale` vi/en) | `value: Date \| [Date, Date]` · `now` injectable for tests · `prefix` icon · footer "Today"/OK |
90
+ | `Inplace` | Click-to-edit inline value (read mode → edit form → close) | `display` + `children` (the edit form) | `Input`/`Textarea` inside · `onClose` after closing the form |
91
+ | `Input.Search` | Search box with an attached search button — filter bars, toolbars | `onSearch` (fires on Enter AND button click) | `enterButton` true→primary icon button, ReactNode→default button with content · `loading` swaps in Spinner + blocks extra submits · shares `size`/`invalid`/`disabled` with `Input` |
92
+ | `InputMask` | Constrained format typing — `9`=digit, `a`=letter, `*`=alnum, others literal | `mask` | `placeholder` showing the format · `ariaLabel` for the accessible name · typing past an invalid char just stops |
93
+ | `InputNumber` | Numeric input with vertical stepper + ↑↓ + min/max clamp | `min`/`max`/`step` | `invalid` red border · blur snaps the display to the clamp · `value` is read at mount (uncontrolled internal) |
94
+ | `InputOTP` | N single-char cells with auto-advance + multi-cell paste | `length` | `value`/`onChange` as one joined string · `ariaLabel` per cell ("code 1…") · digits only · Backspace walks back |
95
+ | `Mention` | Textarea with @-triggered mention list | `suggestions` (filtered by the text after @) | ↑↓ + Enter/Esc keyboard pick · `value`/`onChange` is the full text · picks insert `"@Name "` |
96
+ | `Password` | Password field with show/hide toggle (+ optional strength meter) | `showStrength` | `ariaLabel` · `value`/`onChange` · wraps `Input` |
97
+ | `PickList` | Two-column transfer (source ⇄ target) | `source`/`target` + `onChange(source, target)` | multi-pick then chevron move · each listbox keyboard-navigable (↑↓ + Enter/Space) · `aria-multiselectable` |
98
+ | `Radio`/`RadioGroup` | Single choice among a few always-visible options | `RadioGroup options` + `value` | per-option `disabled` · standalone `Radio` for one-offs · prefer `Select` when options are many |
99
+ | `Slider` | Numeric pick on a track — single value or a range | `range: [lo, hi]` + `onRangeChange` | `step` snapping · keyboard ←↓/→↑ (clamped) · `ariaLabel` required (`role="slider"`) |
100
+ | `Switch` | Instant on/off setting toggle | `checked` + `onChange` | `size="small"` for dense rows · inside `Field`/settings `Tabs` · `role="switch"` + `aria-checked` built-in |
101
+ | `TimePicker` | HH:mm pick via stepper panel (+ "Now" shortcut) | `value` — Date keeps its date-part on change, string `"HH:mm"` emits epoch-day | `locale` vi/en · `now` injectable for tests · pairs with `DatePicker` `showTime` |
102
+ | `ToggleButton` | Button with a pressed state (on/off action) | `checked` (exposed as `aria-pressed`) | `disabled` · clusters of toggles (filters/view switches) · unchecked = default variant look |
103
+ | `TreeSelect` | Pick a LEAF from a hierarchy, with search + clear | `treeData` (nested `children`; parents are headers, not pickable) | `searchable` filters by label/path · `clearable` × resets · trigger shows the `"A / B"` path |
104
+
105
+ ## General — bổ sung parity P0/P1 (2026-10-18, worker W6)
106
+
107
+ | Component | Use when | Most valuable prop | Common combos |
108
+ |---|---|---|---|
109
+ | `Link` | Inline anchor trong câu văn / standalone nav link — màu accent tự hover | `underline` (`'none'|'hover'|'always'`, mặc định `'hover'`) | `disabled` bỏ href + `aria-disabled` + swallow click · passthrough `target`/`rel` cho external · focus ring chuẩn |
110
+ | `Affix` | Sticky wrapper bám mép khi scroll — toolbar/filter-bar nổi | `offsetTop` (mặc định 0; `offsetBottom` → bottom mode) | `onChange(affixed)` chỉ fire khi ĐỔI (không fire lúc mount) · CSS sticky thuần 0 deps · `target()` chỉ đích danh scroll container |
111
+ | `QRCode` | SVG QR cho link thanh toán / chia sẻ / check-in | `value` (`size` mặc định 160) | `errorLevel` L/M/Q/H (mặc định M) · màu tokens `--ink` trên `--c-s1` (dark tự cascade) · `role="img"` + aria-label theo value · vendored qrcode-generator MIT — không deps runtime |
112
+
113
+ ## Theming & Hooks — when to use
114
+
115
+ | Component / Hook | Use when | Most valuable prop / arg | Common combos |
116
+ |---|---|---|---|
117
+ | `UiKitProvider` | Scope a theme subtree — dark mode or runtime token overrides without re-render | `theme` — `'dark'` or object `{ accent, accentHi, canvas, s1/s2/s3, ink/ink2/ink3, line, done/doing/fail }` (13 keys → CSS vars cascade) | wrap app root or a panel · `accent`/`accentHover` shorthand for brand swap |
118
+ | `useFieldArray` | Dynamic rows in `useForm` (antd Form.List parity) — invite lists, line items | `nameAt(i, key)` → name `list.<i>.<key>` keeps form auto-focus-first-invalid working | `fields`/`count` render · `append(row)`/`remove(i)`/`move(from,to)`/`swap(a,b)`/`update(i,patch)` · errors follow ROWS (rebuilt from fresh snapshot per op) · recipe 17 |
119
+ | `useForm` | Form state + zod validation (RHF-style minimal API) | `schema` (zod = source of truth; `mode` = onSubmit/onBlur/onChange) | `Field`+`Input`+`Button` · errors land on `errors.field` + auto-focus first invalid |
120
+ | `useClickAway` | Close on outside interaction — dropdown, popover, menu | returned `ref` (attach to the inside element) | `Dropdown`/`Menu` builds · `useRef`-based popovers |
121
+ | `useFocusTrap` | Lock Tab focus inside a dialog, restore focus on close | `(ref, active)` — focus first focusable (or container), cycle Tab, restore to trigger | `Modal`/`Drawer` (built-in) · any custom `role="dialog"` |
122
+ | `useCopyToClipboard` | Copy-to-clipboard with feedback | returned `[copiedText, copy]` — `copy(text)` → boolean | `Button`+"Copied!" flash · `Input` copy-affordance |
123
+ | `useCountdown` | Ticking countdown — OTP resend, cooldown | `initialSeconds` (+ `intervalMs`) → `{ remaining, restart, … }` | `Button` disabled while counting · OTP/2FA UIs |
124
+ | `useDebounce` | Delayed value — search-as-you-type, expensive derivations | `delayMs` (default 500) | `Input` search → `Table`/`List` filter · API calls |
125
+ | `useThrottle` | Rate-limited value — scroll/resize handlers | `intervalMs` (default 500) | `useWindowSize` consumers · infinite-scroll triggers |
126
+ | `useTimeout` | Timeout as a component-safe effect | `delayMs` + `callback` (returns `{ start, clear, … }`) | toasts auto-dismiss · tooltip delays |
127
+ | `useToggle` | Boolean on/off state | `initialValue` (returns `[value, toggle]`) | `Collapse` custom triggers · sidebar collapsed · any show/hide |
128
+ | `useDefault` | State that falls back to a default when value is undefined | `defaultValue` | controlled/uncontrolled bridge · form field fallbacks |
129
+ | `usePrevious` | Value from the previous render | — (single arg) | transition/diff animations · change detection in effects |
130
+ | `useHover` | Hover state without CSS (JS-driven visuals) | returned `ref` | drag handles · canvas-like interactions CSS can't express |
131
+ | `useKeyPress` | Reactive "is key pressed" + optional callback | `targetKey` (`'Escape'`, `'Enter'`…) + `onPress` | dialog ESC handlers (prefer built-in) · shortcut hints |
132
+ | `useLockBodyScroll` | Prevent background scroll while open | `locked` (default true) | `Modal`/`Drawer` (built-in) · fullscreen previews |
133
+ | `useMediaQuery` | Reactive matchMedia boolean | `query` (e.g. `'(min-width: 768px)'`) | responsive JS behavior · `prefers-reduced-motion` branches |
134
+ | `useWindowSize` | Live viewport width/height | — (no args) | virtualized lists · breakpoint-adjacent JS logic |
135
+ | `useLocalStorage` / `useSessionStorage` | Persistent (tab) / session state without effect boilerplate | `key` + `initialValue` | theme preference · drafts · wizard step memory |
136
+
137
+ ## Theming & Motion — khi nào dùng
138
+
139
+ | Component | Use when | Most valuable prop | Common combos |
140
+ |---|---|---|---|
141
+ | `Parallax` | Scroll-linked drift — hero ảnh/banner landing trôi chậm hơn trang, tạo chiều sâu | `speed` (0–1; 0.3 phổ biến; `scale` phóng nhẹ theo drift) | wrap ảnh hero/section trong landing (recipe 16) · **an toàn a11y: tự tắt khi `prefers-reduced-motion`** (qua `useMediaQuery`) hoặc `disabled` · 0 deps — style ghi thẳng node, 0 re-render/frame |
142
+ | `Reveal` | Block hiện dần khi vào viewport — section landing, card list, KPI row | `direction` (`up` mặc định — dùng keyframe `bp-slide-up-in` có sẵn; `down/left/right` = fade + transition transform) | `delay` (stagger 0/150/300ms — fill backwards giữ ẩn trong lúc trễ) · `once` mặc định true (IO disconnect sau lần đầu), `once={false}` replay mỗi lần vào · fallback hiện luôn khi môi trường không có IntersectionObserver · reduced-motion tự tắt nhờ block global |
143
+ | `CountUp` | Đếm số ease-out cho KPI/metric — dashboard, landing stats | `value` (+ `duration` giây, mặc định 1.2; `0` = chạm đích ngay) | `decimals`/`format` (locale vi-VN, đơn vị) · `onDone` đúng 1 lần · `Statistic value={<CountUp …/>}` dashboard (recipe 16) · đổi `value` → animate tiếp từ số đang hiển thị (không nhảy về 0) · `tabular-nums` sẵn |
144
+ | `Fade` / `Zoom` | Wrapper enter/exit kiểu MUI cho card/popover nhỏ — hiện/thu có animation thay vì biến mất cứng | `in` (exit chạy XONG mới unmount — state machine kiểu Modal) | `unmountOnExit={false}` giữ DOM, hold `opacity-0` · `duration` ms override qua inline style (class giữ literal cho Tailwind) · keyframe `bp-fade/zoom-in/out` có sẵn · reduced-motion tắt nhờ block global |
145
+ | `CollapseTransition` | Thu/mở theo chiều cho FAQ/details panel dưới nút — height động không đo DOM | `in` | grid-rows `0fr↔1fr` (0 keyframe height) · **padding đặt SẶC trong children — tầng `overflow-hidden` phải clip sạch** · barrel đổi tên tránh trùng `Collapse` (precedent `UiImage`) · reduced-motion tắt nhờ block global |
146
+ | `Backdrop` | Scrim toàn màn đứng sau modal/composer/loading — bấm ra ngoài để đóng | `open` + `onClick` (controlled — consumer giữ state) | nền token `--scrim-4` + `z-[var(--z-modal)]` (không `bg-black/85`) · children slot cho Spinner giữa màn · không tự portal — đặt trong portal consumer (pattern Modal/Drawer) |
147
+
148
+ ## Feedback & Overlay — khi nào dùng
149
+
150
+ | Component | Use when | Most valuable prop | Common combos |
151
+ |---|---|---|---|
152
+ | `Alert` | Inline status banner that stays in the page flow (not transient) | `type` (`success`/`info`/`warning`/`error`) + `variant` (`filled` default; `outlined` for tinted look) | `description` detail line · `closable`+`onClose` dismissible · `classNames` slots (antd v5) |
153
+ | `BlockUI` | Lock a region in place while it is busy | `blocked` + `message` (label centered on the scrim) | wrap `Table`/`Card` during fetch · pair with `Spinner` outside the lock |
154
+ | `ContextMenu` | Right-click menu on a region — positioned at the pointer | `items` (key `'---'` = divider; `danger`/`disabled` per item) | `onItemClick` switch by key · arrow-key nav + ESC + outside-click built-in |
155
+ | `Drawer` | Side panel for detail/form without leaving context (portal, focus trap, scroll lock) | `open` + `onClose` (ESC, mask click, × wired) | `width` (default 378 antd) · `footer` action row · `Descriptions` as body · `classNames` slots |
156
+ | `Dropdown` | Button-triggered action menu | `items` + `onItemClick` | `trigger` = `Button` · `'---'` divider · `danger`/`disabled` per item · ArrowUp/Down/Home/End + `role=menu/menuitem` built-in |
157
+ | `Message` | Transient global toast — static API, 3s auto-dismiss | `message.success\|info\|warning\|error(content)` | call anywhere (no React state) · `classNames` slots |
158
+ | `Modal` | Blocking confirm/dialog on top of the page (portal, focus trap, scroll lock) | `open` + `onOk`/`onCancel` (ESC + mask + × all cancel) | `danger` red OK · `confirmLoading` locks both buttons · `okText`/`cancelText` · `classNames` slots |
159
+ | `Notification` | Rich toast with title + description — static API, 4.5s | `notification.success(title, description?)` | manual × close built-in · `classNames` slots |
160
+ | `Popconfirm` | Confirm bubble anchored to a trigger (delete guard) | `open` (controlled) + `onConfirm`/`onCancel` | `danger` red icon/OK · `title` + `description` · ESC = cancel · `okText`/`cancelText` |
161
+ | `Popover` | Rich anchored panel — free `content` ReactNode (lists, links, mini actions), unlike Tooltip's text-only hint | `content` (any ReactNode; pair with `title` for the divider head) | `trigger` `hover\|click\|focus` (default hover) · controlled `open`/`onOpenChange` · `placement` top/bottom · ESC + click-outside close built in |
162
+ | `Progress` | Line progress bar with % readout | `percent` (clamped 0–100) | `status="exception\|success"` recolors bar · `showInfo={false}` hides % |
163
+ | `Result` | Full-area status page (success/error/404/500/warning/info) | `status` (drives icon, color, default title) | `title`/`subTitle` override · `extra` action buttons |
164
+ | `Spinner` | Inline busy indicator (ring/dots/bars) | `label` (REQUIRED aria-label) | `size` (`sm`/`md`/`lg`) + `color` (`inverse` on dark surfaces) · pair with `BlockUI` scrim |
165
+ | `Tooltip` | Hover/focus hint bubble (top/bottom) — portal-free, wraps the trigger in place | `title` (bubble content) · `placement` `top`/`bottom` | wrap any focusable trigger · `aria-describedby` auto-wired · ESC dismisses |
166
+ | `Watermark` | Content guard overlay — repeated diagonal text tile over previews/documents/drafts | `content` (string or `string[]` for multi-line) | wraps any block (children stay interactive — overlay `pointer-events-none`) · `rotate`/`opacity`/`font`/`fontColor` custom tile · corner-anchored via `left`/`top`/`width`/`height` · dark theme re-bakes the tile automatically |
167
+
168
+ ## Quy tắc BẮT BUỘC (vi phạm = review fail)
169
+
170
+ 1. **Tokens-only** — không hex/arbitrary màu trong className: dùng `bg-s1/s2/s3`, `text-ink/ink2/ink3/ink4`, `border-line/line2`, `text-accent`, `text-st-fail/done/doing`, `bg-canvas`. Cần biến thể → opacity của token (`bg-accent/10`), không tự chế.
171
+ 2. **Dark theme** — `data-bp-theme="dark"` trên `<html>` hoặc node bao; host import `styles/themes/dark.css` 1 lần. Component KHÔNG code riêng cho dark (CSS var tự cascade).
172
+ 3. **Z-index** — chỉ `z-[var(--z-dropdown|popover|modal|toast|tooltip)]` (1000<1030<1050<1070<1090). Cấm `z-30`/số cứng.
173
+ 4. **Focus** — `focus-visible:ring-2 focus-visible:ring-accent/40` (KHÔNG ring-offset — chuẩn user duyệt, hết "viền đôi"). Cấm `focus-visible:outline-2 outline-accent` lệch chuẩn.
174
+ 5. **Sizes** — control cao `h-8` (small) / `h-9` (middle mặc định) / `h-10` (large).
175
+ 6. **Motion** — 150–200ms + easing token (`--ease-enter/exit`); keyframes dùng sẵn `bp-fade-in`, `bp-zoom-in`, `bp-slide-up-in`, `bp-switch-pop` (vd `animate-[bp-zoom-in_var(--motion-fast)_var(--ease-enter)]`). `prefers-reduced-motion` tự tắt nhờ block global.
176
+ 7. **Radius** — controls `rounded-lg` · cards/modal/panel `rounded-xl` · switch/tag/handle `rounded-pill`.
177
+ 8. **Shadow** — chỉ `var(--shadow-pop|lift)`; micro-shadow riêng phải có lý do ghi rõ.
178
+ 9. **Icon** — luôn `<Icon name="…" size={n} />` từ bộ primeicons (48 tên — xem `src/ui/icons`). Cấm tự vẽ SVG chevron/glyph.
179
+ 10. **A11y tối thiểu** — icon-only button phải có `aria-label`; menu: `role=menu/menuitem` + `aria-expanded`; selected: `aria-current`; switch: `role="switch"` + `aria-checked`; icon badge trang trí: `aria-hidden`.
180
+
181
+ ## Anti-patterns (đã xảy ra — đừng lặp)
182
+
183
+ - ❌ Tự vẽ `<svg>` chevron/glyph thay `<Icon>` (lệch bộ, trùng path)
184
+ - ❌ `rounded-2`/`rounded-3` (legacy — chuẩn `rounded-lg` control / `rounded-xl` card)
185
+ - ❌ `rgba(0,0,0,…)` cứng ngoài shadow (dark vỡ) — dùng `bg-black/85` hoặc token `ink/*`
186
+ - ❌ ClassName string surgery ghép điều kiện (dễ mâu thuẫn utility) — viết tường minh từng biến thể
187
+ - ❌ `!important`/`!bg-…` trừ khi override CSS third-party
188
+ - ❌ State kéo theo re-render churn cho thư viện so-tham-chiếu-theo-reference (vd swiper/react) — dùng imperative ref + classList
189
+ - ❌ Story file 0 `export const` (indexer drop — phải có ≥1 story mỗi file)
190
+ - ❌ Story meta gắn `component:` khi story chỉ có `render: () => …` và component có required props — StoryObj suy `args` BẮT BUỘC → TS2322 chặn push. Fix: meta không gắn `component` (`satisfies Meta` không generic — pattern `image.stories`); chỉ gắn `component:` khi mọi story truyền đủ `args` (pattern `galleria.stories`)
191
+
192
+ ## Ghi nhớ vận hành
193
+
194
+ - ui-kit **consumed qua source** (`main/types → src/`): sửa là thấy ngay, KHÔNG build.
195
+ - Peer-dep consumer tự cài: `zod` (useForm) · `swiper` (subpath carousel) · `chart.js` · `@tiptap/*` · `@fullcalendar/*` (optional).
196
+ - Component nặng import qua **subpath**: `@wakii/ui-kit/carousel|chart|schedule|editor`.
197
+ - Zod schema = source of truth validate; `mode: 'onSubmit' | 'onBlur' | 'onChange'`; sai → `errors.field` + focus tự vào `[name=…]` đầu tiên.