@vetala/vetala 0.1.0-beta

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.

Potentially problematic release.


This version of @vetala/vetala might be problematic. Click here for more details.

Files changed (271) hide show
  1. package/CONTRIBUTING.md +77 -0
  2. package/LICENSE +184 -0
  3. package/README.md +136 -0
  4. package/THIRD_PARTY_LICENSES.md +17 -0
  5. package/dist/src/agent.d.ts +30 -0
  6. package/dist/src/agent.js +216 -0
  7. package/dist/src/agent.js.map +1 -0
  8. package/dist/src/approvals.d.ts +18 -0
  9. package/dist/src/approvals.js +81 -0
  10. package/dist/src/approvals.js.map +1 -0
  11. package/dist/src/cli.d.ts +2 -0
  12. package/dist/src/cli.js +87 -0
  13. package/dist/src/cli.js.map +1 -0
  14. package/dist/src/config.d.ts +12 -0
  15. package/dist/src/config.js +183 -0
  16. package/dist/src/config.js.map +1 -0
  17. package/dist/src/context-memory.d.ts +7 -0
  18. package/dist/src/context-memory.js +96 -0
  19. package/dist/src/context-memory.js.map +1 -0
  20. package/dist/src/ink/command-suggestions.d.ts +7 -0
  21. package/dist/src/ink/command-suggestions.js +179 -0
  22. package/dist/src/ink/command-suggestions.js.map +1 -0
  23. package/dist/src/ink/ink-terminal-ui.d.ts +36 -0
  24. package/dist/src/ink/ink-terminal-ui.js +79 -0
  25. package/dist/src/ink/ink-terminal-ui.js.map +1 -0
  26. package/dist/src/ink/repl-app.d.ts +9 -0
  27. package/dist/src/ink/repl-app.js +789 -0
  28. package/dist/src/ink/repl-app.js.map +1 -0
  29. package/dist/src/ink/transcript-cards.d.ts +6 -0
  30. package/dist/src/ink/transcript-cards.js +24 -0
  31. package/dist/src/ink/transcript-cards.js.map +1 -0
  32. package/dist/src/path-policy.d.ts +11 -0
  33. package/dist/src/path-policy.js +67 -0
  34. package/dist/src/path-policy.js.map +1 -0
  35. package/dist/src/process-utils.d.ts +13 -0
  36. package/dist/src/process-utils.js +52 -0
  37. package/dist/src/process-utils.js.map +1 -0
  38. package/dist/src/repl.d.ts +9 -0
  39. package/dist/src/repl.js +13 -0
  40. package/dist/src/repl.js.map +1 -0
  41. package/dist/src/sarvam/client.d.ts +15 -0
  42. package/dist/src/sarvam/client.js +208 -0
  43. package/dist/src/sarvam/client.js.map +1 -0
  44. package/dist/src/sarvam/models.d.ts +2 -0
  45. package/dist/src/sarvam/models.js +7 -0
  46. package/dist/src/sarvam/models.js.map +1 -0
  47. package/dist/src/search-provider.d.ts +6 -0
  48. package/dist/src/search-provider.js +8 -0
  49. package/dist/src/search-provider.js.map +1 -0
  50. package/dist/src/session-store.d.ts +19 -0
  51. package/dist/src/session-store.js +318 -0
  52. package/dist/src/session-store.js.map +1 -0
  53. package/dist/src/skills/runtime.d.ts +26 -0
  54. package/dist/src/skills/runtime.js +317 -0
  55. package/dist/src/skills/runtime.js.map +1 -0
  56. package/dist/src/skills/types.d.ts +25 -0
  57. package/dist/src/skills/types.js +2 -0
  58. package/dist/src/skills/types.js.map +1 -0
  59. package/dist/src/terminal-ui.d.ts +29 -0
  60. package/dist/src/terminal-ui.js +236 -0
  61. package/dist/src/terminal-ui.js.map +1 -0
  62. package/dist/src/tools/filesystem.d.ts +2 -0
  63. package/dist/src/tools/filesystem.js +622 -0
  64. package/dist/src/tools/filesystem.js.map +1 -0
  65. package/dist/src/tools/git.d.ts +2 -0
  66. package/dist/src/tools/git.js +326 -0
  67. package/dist/src/tools/git.js.map +1 -0
  68. package/dist/src/tools/index.d.ts +6 -0
  69. package/dist/src/tools/index.js +21 -0
  70. package/dist/src/tools/index.js.map +1 -0
  71. package/dist/src/tools/registry.d.ts +15 -0
  72. package/dist/src/tools/registry.js +59 -0
  73. package/dist/src/tools/registry.js.map +1 -0
  74. package/dist/src/tools/shell.d.ts +2 -0
  75. package/dist/src/tools/shell.js +97 -0
  76. package/dist/src/tools/shell.js.map +1 -0
  77. package/dist/src/tools/skill.d.ts +3 -0
  78. package/dist/src/tools/skill.js +130 -0
  79. package/dist/src/tools/skill.js.map +1 -0
  80. package/dist/src/tools/web.d.ts +3 -0
  81. package/dist/src/tools/web.js +144 -0
  82. package/dist/src/tools/web.js.map +1 -0
  83. package/dist/src/types.d.ts +236 -0
  84. package/dist/src/types.js +2 -0
  85. package/dist/src/types.js.map +1 -0
  86. package/dist/src/workspace-trust.d.ts +3 -0
  87. package/dist/src/workspace-trust.js +31 -0
  88. package/dist/src/workspace-trust.js.map +1 -0
  89. package/dist/src/xdg.d.ts +9 -0
  90. package/dist/src/xdg.js +77 -0
  91. package/dist/src/xdg.js.map +1 -0
  92. package/package.json +57 -0
  93. package/skill/agents-md-generator/SKILL.md +75 -0
  94. package/skill/agents-md-generator/references/agents_md_template.md +160 -0
  95. package/skill/agents-md-generator/references/loc_measurement.md +67 -0
  96. package/skill/agents-md-generator/references/monorepo_detection.md +78 -0
  97. package/skill/agents-md-generator/references/monorepo_strategy.md +60 -0
  98. package/skill/agents-md-generator/references/read_only_commands.md +151 -0
  99. package/skill/agents-md-generator/references/update_strategy.md +160 -0
  100. package/skill/agents-md-generator/references/working_agreements.md +53 -0
  101. package/skill/biz-opportunity-scout/SKILL.md +53 -0
  102. package/skill/biz-opportunity-scout/references/competitive_analysis.md +84 -0
  103. package/skill/biz-opportunity-scout/references/market_sizing.md +68 -0
  104. package/skill/biz-opportunity-scout/references/pmf_indicators.md +94 -0
  105. package/skill/biz-opportunity-scout/references/report_template.md +243 -0
  106. package/skill/biz-opportunity-scout/references/unit_economics.md +97 -0
  107. package/skill/code-review/SKILL.md +86 -0
  108. package/skill/code-review/references/change_analysis.md +116 -0
  109. package/skill/code-review/references/git_operations.md +115 -0
  110. package/skill/code-review/references/impact_detection.md +149 -0
  111. package/skill/code-review/references/output_format.md +137 -0
  112. package/skill/code-review/references/severity_criteria.md +100 -0
  113. package/skill/code-security-audit/SKILL.md +123 -0
  114. package/skill/code-security-audit/references/audit_process.md +277 -0
  115. package/skill/code-security-audit/references/remediation_patterns.md +599 -0
  116. package/skill/code-security-audit/references/report_format.md +391 -0
  117. package/skill/code-security-audit/references/security_domains.md +830 -0
  118. package/skill/code-security-audit/references/vulnerability_patterns.md +813 -0
  119. package/skill/composition-patterns/SKILL.md +83 -0
  120. package/skill/composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
  121. package/skill/composition-patterns/rules/architecture-compound-components.md +112 -0
  122. package/skill/composition-patterns/rules/patterns-children-over-render-props.md +87 -0
  123. package/skill/composition-patterns/rules/patterns-explicit-variants.md +100 -0
  124. package/skill/composition-patterns/rules/react19-no-forwardref.md +42 -0
  125. package/skill/composition-patterns/rules/state-context-interface.md +191 -0
  126. package/skill/composition-patterns/rules/state-decouple-implementation.md +113 -0
  127. package/skill/composition-patterns/rules/state-lift-state.md +125 -0
  128. package/skill/deploy-to-vercel/SKILL.md +293 -0
  129. package/skill/deploy-to-vercel/resources/deploy-sandbox.sh +301 -0
  130. package/skill/deploy-to-vercel/resources/deploy.sh +301 -0
  131. package/skill/doc/SKILL_GUIDELINES.md +138 -0
  132. package/skill/git-workflow/SKILL.md +94 -0
  133. package/skill/git-workflow/references/advanced-git.md +632 -0
  134. package/skill/git-workflow/references/branching-strategies.md +344 -0
  135. package/skill/git-workflow/references/ci-cd-integration.md +683 -0
  136. package/skill/git-workflow/references/code-quality-tools.md +351 -0
  137. package/skill/git-workflow/references/commit-conventions.md +439 -0
  138. package/skill/git-workflow/references/github-releases.md +288 -0
  139. package/skill/git-workflow/references/pull-request-workflow.md +773 -0
  140. package/skill/git-workflow/scripts/verify-git-workflow.sh +263 -0
  141. package/skill/jetbrains-vmoptions/SKILL.md +51 -0
  142. package/skill/jetbrains-vmoptions/references/common-options.md +357 -0
  143. package/skill/jetbrains-vmoptions/references/gc-options.md +350 -0
  144. package/skill/jetbrains-vmoptions/references/memory-options.md +339 -0
  145. package/skill/jetbrains-vmoptions/references/prerequisite-check.md +65 -0
  146. package/skill/kysely-converter/SKILL.md +62 -0
  147. package/skill/kysely-converter/references/delete.md +323 -0
  148. package/skill/kysely-converter/references/insert.md +386 -0
  149. package/skill/kysely-converter/references/operators.md +331 -0
  150. package/skill/kysely-converter/references/select.md +1000 -0
  151. package/skill/kysely-converter/references/update.md +349 -0
  152. package/skill/kysely-converter/references/window_function.md +537 -0
  153. package/skill/react-best-practices/SKILL.md +131 -0
  154. package/skill/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  155. package/skill/react-best-practices/rules/advanced-init-once.md +42 -0
  156. package/skill/react-best-practices/rules/advanced-use-latest.md +39 -0
  157. package/skill/react-best-practices/rules/async-api-routes.md +38 -0
  158. package/skill/react-best-practices/rules/async-defer-await.md +80 -0
  159. package/skill/react-best-practices/rules/async-dependencies.md +51 -0
  160. package/skill/react-best-practices/rules/async-parallel.md +28 -0
  161. package/skill/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  162. package/skill/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  163. package/skill/react-best-practices/rules/bundle-conditional.md +31 -0
  164. package/skill/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  165. package/skill/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  166. package/skill/react-best-practices/rules/bundle-preload.md +50 -0
  167. package/skill/react-best-practices/rules/client-event-listeners.md +74 -0
  168. package/skill/react-best-practices/rules/client-localstorage-schema.md +71 -0
  169. package/skill/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  170. package/skill/react-best-practices/rules/client-swr-dedup.md +56 -0
  171. package/skill/react-best-practices/rules/js-batch-dom-css.md +107 -0
  172. package/skill/react-best-practices/rules/js-cache-function-results.md +80 -0
  173. package/skill/react-best-practices/rules/js-cache-property-access.md +28 -0
  174. package/skill/react-best-practices/rules/js-cache-storage.md +70 -0
  175. package/skill/react-best-practices/rules/js-combine-iterations.md +32 -0
  176. package/skill/react-best-practices/rules/js-early-exit.md +50 -0
  177. package/skill/react-best-practices/rules/js-hoist-regexp.md +45 -0
  178. package/skill/react-best-practices/rules/js-index-maps.md +37 -0
  179. package/skill/react-best-practices/rules/js-length-check-first.md +49 -0
  180. package/skill/react-best-practices/rules/js-min-max-loop.md +82 -0
  181. package/skill/react-best-practices/rules/js-set-map-lookups.md +24 -0
  182. package/skill/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  183. package/skill/react-best-practices/rules/rendering-activity.md +26 -0
  184. package/skill/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  185. package/skill/react-best-practices/rules/rendering-conditional-render.md +40 -0
  186. package/skill/react-best-practices/rules/rendering-content-visibility.md +38 -0
  187. package/skill/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  188. package/skill/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  189. package/skill/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  190. package/skill/react-best-practices/rules/rendering-svg-precision.md +28 -0
  191. package/skill/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  192. package/skill/react-best-practices/rules/rerender-defer-reads.md +39 -0
  193. package/skill/react-best-practices/rules/rerender-dependencies.md +45 -0
  194. package/skill/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  195. package/skill/react-best-practices/rules/rerender-derived-state.md +29 -0
  196. package/skill/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  197. package/skill/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  198. package/skill/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  199. package/skill/react-best-practices/rules/rerender-memo.md +44 -0
  200. package/skill/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  201. package/skill/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  202. package/skill/react-best-practices/rules/rerender-transitions.md +40 -0
  203. package/skill/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  204. package/skill/react-best-practices/rules/server-after-nonblocking.md +73 -0
  205. package/skill/react-best-practices/rules/server-auth-actions.md +96 -0
  206. package/skill/react-best-practices/rules/server-cache-lru.md +41 -0
  207. package/skill/react-best-practices/rules/server-cache-react.md +76 -0
  208. package/skill/react-best-practices/rules/server-dedup-props.md +65 -0
  209. package/skill/react-best-practices/rules/server-hoist-static-io.md +142 -0
  210. package/skill/react-best-practices/rules/server-parallel-fetching.md +83 -0
  211. package/skill/react-best-practices/rules/server-serialization.md +38 -0
  212. package/skill/react-native-skills/SKILL.md +115 -0
  213. package/skill/react-native-skills/rules/animation-derived-value.md +53 -0
  214. package/skill/react-native-skills/rules/animation-gesture-detector-press.md +95 -0
  215. package/skill/react-native-skills/rules/animation-gpu-properties.md +65 -0
  216. package/skill/react-native-skills/rules/design-system-compound-components.md +66 -0
  217. package/skill/react-native-skills/rules/fonts-config-plugin.md +71 -0
  218. package/skill/react-native-skills/rules/imports-design-system-folder.md +68 -0
  219. package/skill/react-native-skills/rules/js-hoist-intl.md +61 -0
  220. package/skill/react-native-skills/rules/list-performance-callbacks.md +44 -0
  221. package/skill/react-native-skills/rules/list-performance-function-references.md +132 -0
  222. package/skill/react-native-skills/rules/list-performance-images.md +53 -0
  223. package/skill/react-native-skills/rules/list-performance-inline-objects.md +97 -0
  224. package/skill/react-native-skills/rules/list-performance-item-expensive.md +94 -0
  225. package/skill/react-native-skills/rules/list-performance-item-memo.md +82 -0
  226. package/skill/react-native-skills/rules/list-performance-item-types.md +104 -0
  227. package/skill/react-native-skills/rules/list-performance-virtualize.md +67 -0
  228. package/skill/react-native-skills/rules/monorepo-native-deps-in-app.md +46 -0
  229. package/skill/react-native-skills/rules/monorepo-single-dependency-versions.md +63 -0
  230. package/skill/react-native-skills/rules/navigation-native-navigators.md +188 -0
  231. package/skill/react-native-skills/rules/react-compiler-destructure-functions.md +50 -0
  232. package/skill/react-native-skills/rules/react-compiler-reanimated-shared-values.md +48 -0
  233. package/skill/react-native-skills/rules/react-state-dispatcher.md +91 -0
  234. package/skill/react-native-skills/rules/react-state-fallback.md +56 -0
  235. package/skill/react-native-skills/rules/react-state-minimize.md +65 -0
  236. package/skill/react-native-skills/rules/rendering-no-falsy-and.md +74 -0
  237. package/skill/react-native-skills/rules/rendering-text-in-text-component.md +36 -0
  238. package/skill/react-native-skills/rules/scroll-position-no-state.md +82 -0
  239. package/skill/react-native-skills/rules/state-ground-truth.md +80 -0
  240. package/skill/react-native-skills/rules/ui-expo-image.md +66 -0
  241. package/skill/react-native-skills/rules/ui-image-gallery.md +104 -0
  242. package/skill/react-native-skills/rules/ui-measure-views.md +78 -0
  243. package/skill/react-native-skills/rules/ui-menus.md +174 -0
  244. package/skill/react-native-skills/rules/ui-native-modals.md +77 -0
  245. package/skill/react-native-skills/rules/ui-pressable.md +61 -0
  246. package/skill/react-native-skills/rules/ui-safe-area-scroll.md +65 -0
  247. package/skill/react-native-skills/rules/ui-scrollview-content-inset.md +45 -0
  248. package/skill/react-native-skills/rules/ui-styling.md +87 -0
  249. package/skill/react-vite-guide/SKILL.md +101 -0
  250. package/skill/react-vite-guide/references/composition-patterns.md +709 -0
  251. package/skill/react-vite-guide/references/performance-optimization.md +1222 -0
  252. package/skill/react-vite-guide/references/vite-specific.md +385 -0
  253. package/skill/react-vite-guide/references/web-interface.md +146 -0
  254. package/skill/skill-maker/SKILL.md +52 -0
  255. package/skill/skill-maker/references/content_spec.md +67 -0
  256. package/skill/skill-maker/references/frontmatter_spec.md +96 -0
  257. package/skill/skill-maker/references/input_validation.md +90 -0
  258. package/skill/skill-maker/references/skill_structure.md +74 -0
  259. package/skill/system-prompt-creator/SKILL.md +50 -0
  260. package/skill/system-prompt-creator/references/data_format_selection.md +135 -0
  261. package/skill/system-prompt-creator/references/multi_prompt_architecture.md +386 -0
  262. package/skill/system-prompt-creator/references/prompt_structure.md +140 -0
  263. package/skill/system-prompt-creator/references/quality_criteria.md +83 -0
  264. package/skill/typst-creator/SKILL.md +51 -0
  265. package/skill/typst-creator/references/layout.md +401 -0
  266. package/skill/typst-creator/references/math.md +297 -0
  267. package/skill/typst-creator/references/scripting.md +237 -0
  268. package/skill/typst-creator/references/styling.md +217 -0
  269. package/skill/typst-creator/references/syntax.md +234 -0
  270. package/skill/web-design-guidelines/SKILL.md +35 -0
  271. package/terminal.png +0 -0
@@ -0,0 +1,709 @@
1
+ # React Composition Patterns
2
+
3
+ Composition patterns for flexible, maintainable React 19 components. Covers compound components, state lifting, and internal composition as alternatives to boolean prop proliferation.
4
+
5
+ ---
6
+
7
+ ## 1. Component Architecture
8
+
9
+ **Impact: HIGH**
10
+
11
+ ### 1.1 Avoid Boolean Prop Proliferation
12
+
13
+ **Impact: CRITICAL**
14
+
15
+ Boolean props like `isThread`, `isEditing`, `isDMThread` double possible states per flag and create exponential conditional logic. Composition patterns provide an alternative by extracting explicit variants.
16
+
17
+ **Incorrect: boolean props create exponential complexity**
18
+
19
+ ```tsx
20
+ function Composer({
21
+ onSubmit,
22
+ isThread,
23
+ channelId,
24
+ isDMThread,
25
+ dmId,
26
+ isEditing,
27
+ isForwarding,
28
+ }: Props) {
29
+ return (
30
+ <form>
31
+ <Header />
32
+ <Input />
33
+ {isDMThread ? (
34
+ <AlsoSendToDMField id={dmId} />
35
+ ) : isThread ? (
36
+ <AlsoSendToChannelField id={channelId} />
37
+ ) : null}
38
+ {isEditing ? (
39
+ <EditActions />
40
+ ) : isForwarding ? (
41
+ <ForwardActions />
42
+ ) : (
43
+ <DefaultActions />
44
+ )}
45
+ <Footer onSubmit={onSubmit} />
46
+ </form>
47
+ )
48
+ }
49
+ ```
50
+
51
+ **Correct: composition eliminates conditionals**
52
+
53
+ ```tsx
54
+ function ChannelComposer() {
55
+ return (
56
+ <Composer.Frame>
57
+ <Composer.Header />
58
+ <Composer.Input />
59
+ <Composer.Footer>
60
+ <Composer.Attachments />
61
+ <Composer.Formatting />
62
+ <Composer.Emojis />
63
+ <Composer.Submit />
64
+ </Composer.Footer>
65
+ </Composer.Frame>
66
+ )
67
+ }
68
+
69
+ function ThreadComposer({ channelId }: { channelId: string }) {
70
+ return (
71
+ <Composer.Frame>
72
+ <Composer.Header />
73
+ <Composer.Input />
74
+ <AlsoSendToChannelField id={channelId} />
75
+ <Composer.Footer>
76
+ <Composer.Formatting />
77
+ <Composer.Emojis />
78
+ <Composer.Submit />
79
+ </Composer.Footer>
80
+ </Composer.Frame>
81
+ )
82
+ }
83
+
84
+ function EditComposer() {
85
+ return (
86
+ <Composer.Frame>
87
+ <Composer.Input />
88
+ <Composer.Footer>
89
+ <Composer.Formatting />
90
+ <Composer.Emojis />
91
+ <Composer.CancelEdit />
92
+ <Composer.SaveEdit />
93
+ </Composer.Footer>
94
+ </Composer.Frame>
95
+ )
96
+ }
97
+ ```
98
+
99
+ Each variant is explicit about what it renders. Share internals without sharing a single monolithic parent.
100
+
101
+ ### 1.2 Use Compound Components
102
+
103
+ **Impact: HIGH**
104
+
105
+ Compound components structure complex UI with a shared context. Each subcomponent accesses shared state via context, not props.
106
+
107
+ **Incorrect: monolithic component with render props**
108
+
109
+ ```tsx
110
+ function Composer({
111
+ renderHeader,
112
+ renderFooter,
113
+ renderActions,
114
+ showAttachments,
115
+ showFormatting,
116
+ showEmojis,
117
+ }: Props) {
118
+ return (
119
+ <form>
120
+ {renderHeader?.()}
121
+ <Input />
122
+ {showAttachments && <Attachments />}
123
+ {renderFooter ? (
124
+ renderFooter()
125
+ ) : (
126
+ <Footer>
127
+ {showFormatting && <Formatting />}
128
+ {showEmojis && <Emojis />}
129
+ {renderActions?.()}
130
+ </Footer>
131
+ )}
132
+ </form>
133
+ )
134
+ }
135
+ ```
136
+
137
+ **Correct: compound components with shared context**
138
+
139
+ ```tsx
140
+ const ComposerContext = createContext<ComposerContextValue | null>(null)
141
+
142
+ function ComposerProvider({ children, state, actions, meta }: ProviderProps) {
143
+ return (
144
+ <ComposerContext value={{ state, actions, meta }}>
145
+ {children}
146
+ </ComposerContext>
147
+ )
148
+ }
149
+
150
+ function ComposerFrame({ children }: { children: React.ReactNode }) {
151
+ return <form>{children}</form>
152
+ }
153
+
154
+ function ComposerInput() {
155
+ const {
156
+ state,
157
+ actions: { update },
158
+ meta: { inputRef },
159
+ } = use(ComposerContext)
160
+ return (
161
+ <input
162
+ ref={inputRef}
163
+ value={state.input}
164
+ onChange={(e) => update((s) => ({ ...s, input: e.target.value }))}
165
+ />
166
+ )
167
+ }
168
+
169
+ function ComposerSubmit() {
170
+ const {
171
+ actions: { submit },
172
+ } = use(ComposerContext)
173
+ return <button onClick={submit}>Send</button>
174
+ }
175
+
176
+ const Composer = {
177
+ Provider: ComposerProvider,
178
+ Frame: ComposerFrame,
179
+ Input: ComposerInput,
180
+ Submit: ComposerSubmit,
181
+ Header: ComposerHeader,
182
+ Footer: ComposerFooter,
183
+ Attachments: ComposerAttachments,
184
+ Formatting: ComposerFormatting,
185
+ Emojis: ComposerEmojis,
186
+ }
187
+ ```
188
+
189
+ **Usage:**
190
+
191
+ ```tsx
192
+ <Composer.Provider state={state} actions={actions} meta={meta}>
193
+ <Composer.Frame>
194
+ <Composer.Header />
195
+ <Composer.Input />
196
+ <Composer.Footer>
197
+ <Composer.Formatting />
198
+ <Composer.Submit />
199
+ </Composer.Footer>
200
+ </Composer.Frame>
201
+ </Composer.Provider>
202
+ ```
203
+
204
+ ---
205
+
206
+ ## 2. State Management
207
+
208
+ **Impact: MEDIUM**
209
+
210
+ ### 2.1 Decouple State Management from UI
211
+
212
+ **Impact: MEDIUM**
213
+
214
+ The provider is the single location that manages state. UI components consume the context interface — agnostic to whether state comes from `useState`, Zustand, or a server sync.
215
+
216
+ **Incorrect: UI coupled to state implementation**
217
+
218
+ ```tsx
219
+ function ChannelComposer({ channelId }: { channelId: string }) {
220
+ const state = useGlobalChannelState(channelId)
221
+ const { submit, updateInput } = useChannelSync(channelId)
222
+
223
+ return (
224
+ <Composer.Frame>
225
+ <Composer.Input
226
+ value={state.input}
227
+ onChange={(text) => sync.updateInput(text)}
228
+ />
229
+ <Composer.Submit onPress={() => sync.submit()} />
230
+ </Composer.Frame>
231
+ )
232
+ }
233
+ ```
234
+
235
+ **Correct: state management isolated in provider**
236
+
237
+ ```tsx
238
+ function ChannelProvider({
239
+ channelId,
240
+ children,
241
+ }: {
242
+ channelId: string
243
+ children: React.ReactNode
244
+ }) {
245
+ const { state, update, submit } = useGlobalChannel(channelId)
246
+ const inputRef = useRef(null)
247
+
248
+ return (
249
+ <Composer.Provider
250
+ state={state}
251
+ actions={{ update, submit }}
252
+ meta={{ inputRef }}
253
+ >
254
+ {children}
255
+ </Composer.Provider>
256
+ )
257
+ }
258
+
259
+ function ChannelComposer() {
260
+ return (
261
+ <Composer.Frame>
262
+ <Composer.Header />
263
+ <Composer.Input />
264
+ <Composer.Footer>
265
+ <Composer.Submit />
266
+ </Composer.Footer>
267
+ </Composer.Frame>
268
+ )
269
+ }
270
+
271
+ function Channel({ channelId }: { channelId: string }) {
272
+ return (
273
+ <ChannelProvider channelId={channelId}>
274
+ <ChannelComposer />
275
+ </ChannelProvider>
276
+ )
277
+ }
278
+ ```
279
+
280
+ **Different providers, same UI:**
281
+
282
+ ```tsx
283
+ // Local state for ephemeral forms
284
+ function ForwardMessageProvider({ children }) {
285
+ const [state, setState] = useState(initialState)
286
+ const forwardMessage = useForwardMessage()
287
+
288
+ return (
289
+ <Composer.Provider
290
+ state={state}
291
+ actions={{ update: setState, submit: forwardMessage }}
292
+ >
293
+ {children}
294
+ </Composer.Provider>
295
+ )
296
+ }
297
+
298
+ // Global synced state for channels
299
+ function ChannelProvider({ channelId, children }) {
300
+ const { state, update, submit } = useGlobalChannel(channelId)
301
+
302
+ return (
303
+ <Composer.Provider state={state} actions={{ update, submit }}>
304
+ {children}
305
+ </Composer.Provider>
306
+ )
307
+ }
308
+ ```
309
+
310
+ ### 2.2 Define Generic Context Interfaces for Dependency Injection
311
+
312
+ **Impact: HIGH**
313
+
314
+ A generic interface with `state`, `actions`, and `meta` enables any provider to implement it — the same UI components work with different state implementations.
315
+
316
+ **Core pattern:** Lifted state, composed internals, dependency-injectable state.
317
+
318
+ **Incorrect: UI coupled to specific state implementation**
319
+
320
+ ```tsx
321
+ function ComposerInput() {
322
+ const { input, setInput } = useChannelComposerState()
323
+ return <input value={input} onChange={(e) => setInput(e.target.value)} />
324
+ }
325
+ ```
326
+
327
+ **Correct: generic interface enables dependency injection**
328
+
329
+ ```tsx
330
+ interface ComposerState {
331
+ input: string
332
+ attachments: Attachment[]
333
+ isSubmitting: boolean
334
+ }
335
+
336
+ interface ComposerActions {
337
+ update: (updater: (state: ComposerState) => ComposerState) => void
338
+ submit: () => void
339
+ }
340
+
341
+ interface ComposerMeta {
342
+ inputRef: React.RefObject<HTMLInputElement>
343
+ }
344
+
345
+ interface ComposerContextValue {
346
+ state: ComposerState
347
+ actions: ComposerActions
348
+ meta: ComposerMeta
349
+ }
350
+
351
+ const ComposerContext = createContext<ComposerContextValue | null>(null)
352
+ ```
353
+
354
+ **UI components consume the interface, not the implementation:**
355
+
356
+ ```tsx
357
+ function ComposerInput() {
358
+ const {
359
+ state,
360
+ actions: { update },
361
+ meta,
362
+ } = use(ComposerContext)
363
+
364
+ return (
365
+ <input
366
+ ref={meta.inputRef}
367
+ value={state.input}
368
+ onChange={(e) => update((s) => ({ ...s, input: e.target.value }))}
369
+ />
370
+ )
371
+ }
372
+ ```
373
+
374
+ **Different providers implement the same interface:**
375
+
376
+ ```tsx
377
+ // Provider A: Local state for ephemeral forms
378
+ function ForwardMessageProvider({ children }: { children: React.ReactNode }) {
379
+ const [state, setState] = useState(initialState)
380
+ const inputRef = useRef(null)
381
+ const submit = useForwardMessage()
382
+
383
+ return (
384
+ <ComposerContext
385
+ value={{
386
+ state,
387
+ actions: { update: setState, submit },
388
+ meta: { inputRef },
389
+ }}
390
+ >
391
+ {children}
392
+ </ComposerContext>
393
+ )
394
+ }
395
+
396
+ // Provider B: Global synced state for channels
397
+ function ChannelProvider({ channelId, children }: Props) {
398
+ const { state, update, submit } = useGlobalChannel(channelId)
399
+ const inputRef = useRef(null)
400
+
401
+ return (
402
+ <ComposerContext
403
+ value={{
404
+ state,
405
+ actions: { update, submit },
406
+ meta: { inputRef },
407
+ }}
408
+ >
409
+ {children}
410
+ </ComposerContext>
411
+ )
412
+ }
413
+ ```
414
+
415
+ **Custom UI outside the component can access state and actions:**
416
+
417
+ ```tsx
418
+ function ForwardMessageDialog() {
419
+ return (
420
+ <ForwardMessageProvider>
421
+ <Dialog>
422
+ <Composer.Frame>
423
+ <Composer.Input placeholder="Add a message, if you'd like." />
424
+ <Composer.Footer>
425
+ <Composer.Formatting />
426
+ <Composer.Emojis />
427
+ </Composer.Footer>
428
+ </Composer.Frame>
429
+
430
+ <MessagePreview />
431
+
432
+ <DialogActions>
433
+ <CancelButton />
434
+ <ForwardButton />
435
+ </DialogActions>
436
+ </Dialog>
437
+ </ForwardMessageProvider>
438
+ )
439
+ }
440
+
441
+ function ForwardButton() {
442
+ const {
443
+ actions: { submit },
444
+ } = use(ComposerContext)
445
+ return <button onClick={submit}>Forward</button>
446
+ }
447
+
448
+ function MessagePreview() {
449
+ const { state } = use(ComposerContext)
450
+ return <Preview message={state.input} attachments={state.attachments} />
451
+ }
452
+ ```
453
+
454
+ The provider boundary is what matters — not the visual nesting. Components that need shared state just need to be within the provider.
455
+
456
+ ### 2.3 Lift State into Provider Components
457
+
458
+ **Impact: HIGH**
459
+
460
+ Dedicated provider components hold state management. Sibling components outside the main UI access and modify state without prop drilling.
461
+
462
+ **Incorrect: state trapped inside component**
463
+
464
+ ```tsx
465
+ function ForwardMessageComposer() {
466
+ const [state, setState] = useState(initialState)
467
+ const forwardMessage = useForwardMessage()
468
+
469
+ return (
470
+ <Composer.Frame>
471
+ <Composer.Input />
472
+ <Composer.Footer />
473
+ </Composer.Frame>
474
+ )
475
+ }
476
+
477
+ // Problem: How does this button access composer state?
478
+ function ForwardMessageDialog() {
479
+ return (
480
+ <Dialog>
481
+ <ForwardMessageComposer />
482
+ <MessagePreview /> {/* Needs composer state */}
483
+ <DialogActions>
484
+ <CancelButton />
485
+ <ForwardButton /> {/* Needs to call submit */}
486
+ </DialogActions>
487
+ </Dialog>
488
+ )
489
+ }
490
+ ```
491
+
492
+ **Correct: state lifted to provider**
493
+
494
+ ```tsx
495
+ function ForwardMessageProvider({ children }: { children: React.ReactNode }) {
496
+ const [state, setState] = useState(initialState)
497
+ const forwardMessage = useForwardMessage()
498
+ const inputRef = useRef(null)
499
+
500
+ return (
501
+ <Composer.Provider
502
+ state={state}
503
+ actions={{ update: setState, submit: forwardMessage }}
504
+ meta={{ inputRef }}
505
+ >
506
+ {children}
507
+ </Composer.Provider>
508
+ )
509
+ }
510
+
511
+ function ForwardMessageDialog() {
512
+ return (
513
+ <ForwardMessageProvider>
514
+ <Dialog>
515
+ <ForwardMessageComposer />
516
+ <MessagePreview />
517
+ <DialogActions>
518
+ <CancelButton />
519
+ <ForwardButton />
520
+ </DialogActions>
521
+ </Dialog>
522
+ </ForwardMessageProvider>
523
+ )
524
+ }
525
+
526
+ function ForwardButton() {
527
+ const { actions } = use(Composer.Context)
528
+ return <button onClick={actions.submit}>Forward</button>
529
+ }
530
+ ```
531
+
532
+ **Key insight:** Components that need shared state don't have to be visually nested inside each other — they just need to be within the same provider.
533
+
534
+ ---
535
+
536
+ ## 3. Implementation Patterns
537
+
538
+ **Impact: MEDIUM**
539
+
540
+ ### 3.1 Create Explicit Component Variants
541
+
542
+ **Impact: MEDIUM**
543
+
544
+ Explicit variant components replace a single component with many boolean props. Each variant composes the pieces it needs.
545
+
546
+ **Incorrect: one component, many modes**
547
+
548
+ ```tsx
549
+ <Composer
550
+ isThread
551
+ isEditing={false}
552
+ channelId='abc'
553
+ showAttachments
554
+ showFormatting={false}
555
+ />
556
+ ```
557
+
558
+ **Correct: explicit variants**
559
+
560
+ ```tsx
561
+ <ThreadComposer channelId="abc" />
562
+ <EditMessageComposer messageId="xyz" />
563
+ <ForwardMessageComposer messageId="123" />
564
+ ```
565
+
566
+ **Implementation:**
567
+
568
+ ```tsx
569
+ function ThreadComposer({ channelId }: { channelId: string }) {
570
+ return (
571
+ <ThreadProvider channelId={channelId}>
572
+ <Composer.Frame>
573
+ <Composer.Input />
574
+ <AlsoSendToChannelField channelId={channelId} />
575
+ <Composer.Footer>
576
+ <Composer.Formatting />
577
+ <Composer.Emojis />
578
+ <Composer.Submit />
579
+ </Composer.Footer>
580
+ </Composer.Frame>
581
+ </ThreadProvider>
582
+ )
583
+ }
584
+
585
+ function EditMessageComposer({ messageId }: { messageId: string }) {
586
+ return (
587
+ <EditMessageProvider messageId={messageId}>
588
+ <Composer.Frame>
589
+ <Composer.Input />
590
+ <Composer.Footer>
591
+ <Composer.Formatting />
592
+ <Composer.Emojis />
593
+ <Composer.CancelEdit />
594
+ <Composer.SaveEdit />
595
+ </Composer.Footer>
596
+ </Composer.Frame>
597
+ </EditMessageProvider>
598
+ )
599
+ }
600
+ ```
601
+
602
+ Each variant is explicit about what provider/state it uses, what UI elements it includes, and what actions are available.
603
+
604
+ ### 3.2 Children vs Render Props
605
+
606
+ **Impact: MEDIUM**
607
+
608
+ `children` provides composition for static structure; `renderX` props are suited for cases where the parent passes data back to the child.
609
+
610
+ **Incorrect: render props**
611
+
612
+ ```tsx
613
+ <Composer
614
+ renderHeader={() => <CustomHeader />}
615
+ renderFooter={() => (
616
+ <>
617
+ <Formatting />
618
+ <Emojis />
619
+ </>
620
+ )}
621
+ renderActions={() => <SubmitButton />}
622
+ />
623
+ ```
624
+
625
+ **Correct: compound components with children**
626
+
627
+ ```tsx
628
+ <Composer.Frame>
629
+ <CustomHeader />
630
+ <Composer.Input />
631
+ <Composer.Footer>
632
+ <Composer.Formatting />
633
+ <Composer.Emojis />
634
+ <SubmitButton />
635
+ </Composer.Footer>
636
+ </Composer.Frame>
637
+ ```
638
+
639
+ **When render props are appropriate:**
640
+
641
+ ```tsx
642
+ // Render props work well when you need to pass data back
643
+ <List
644
+ data={items}
645
+ renderItem={({ item, index }) => <Item item={item} index={index} />}
646
+ />
647
+ ```
648
+
649
+ Use render props when the parent needs to provide data to the child. Use children when composing static structure.
650
+
651
+ ---
652
+
653
+ ## 4. React 19 APIs
654
+
655
+ **Impact: MEDIUM**
656
+
657
+ ### 4.1 React 19 API Changes
658
+
659
+ > **React 19+ only.** These patterns require React 19.
660
+
661
+ **ref is a regular prop (no forwardRef)**
662
+
663
+ ```tsx
664
+ // ❌ Don't use forwardRef in React 19
665
+ const ComposerInput = forwardRef<HTMLInputElement, Props>((props, ref) => {
666
+ return <input ref={ref} {...props} />
667
+ })
668
+
669
+ // ✅ ref as a regular prop
670
+ function ComposerInput({ ref, ...props }: Props & { ref?: React.Ref<HTMLInputElement> }) {
671
+ return <input ref={ref} {...props} />
672
+ }
673
+ ```
674
+
675
+ **use() replaces useContext()**
676
+
677
+ ```tsx
678
+ // ❌ Don't use useContext in React 19
679
+ const value = useContext(MyContext)
680
+
681
+ // ✅ use() — can also be called conditionally
682
+ const value = use(MyContext)
683
+ ```
684
+
685
+ `use()` can also unwrap promises, enabling new data fetching patterns with Suspense:
686
+
687
+ ```tsx
688
+ function DataDisplay({ dataPromise }: { dataPromise: Promise<Data> }) {
689
+ const data = use(dataPromise)
690
+ return <div>{data.content}</div>
691
+ }
692
+
693
+ function Page() {
694
+ const dataPromise = fetchData()
695
+ return (
696
+ <Suspense fallback={<Skeleton />}>
697
+ <DataDisplay dataPromise={dataPromise} />
698
+ </Suspense>
699
+ )
700
+ }
701
+ ```
702
+
703
+ ---
704
+
705
+ ## References
706
+
707
+ 1. [https://react.dev](https://react.dev)
708
+ 2. [https://react.dev/learn/passing-data-deeply-with-context](https://react.dev/learn/passing-data-deeply-with-context)
709
+ 3. [https://react.dev/reference/react/use](https://react.dev/reference/react/use)