@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,83 @@
1
+ ---
2
+ name: composition-patterns
3
+ description:
4
+ React composition patterns that scale. Use when refactoring components with
5
+ boolean prop proliferation, building flexible component libraries, or
6
+ designing reusable APIs. Triggers on tasks involving compound components,
7
+ render props, context providers, or component architecture. Includes React 19
8
+ API changes.
9
+ ---
10
+
11
+ # React Composition Patterns
12
+
13
+ Composition patterns for building flexible, maintainable React components. Avoid
14
+ boolean prop proliferation by using compound components, lifting state, and
15
+ composing internals. These patterns make codebases easier for both humans and AI
16
+ agents to work with as they scale.
17
+
18
+ ## When to Apply
19
+
20
+ Reference these guidelines when:
21
+
22
+ - Refactoring components with many boolean props
23
+ - Building reusable component libraries
24
+ - Designing flexible component APIs
25
+ - Reviewing component architecture
26
+ - Working with compound components or context providers
27
+
28
+ ## Rule Categories by Priority
29
+
30
+ | Priority | Category | Impact | Prefix |
31
+ | -------- | ----------------------- | ------ | --------------- |
32
+ | 1 | Component Architecture | HIGH | `architecture-` |
33
+ | 2 | State Management | MEDIUM | `state-` |
34
+ | 3 | Implementation Patterns | MEDIUM | `patterns-` |
35
+ | 4 | React 19 APIs | MEDIUM | `react19-` |
36
+
37
+ ## Quick Reference
38
+
39
+ ### 1. Component Architecture (HIGH)
40
+
41
+ - `architecture-avoid-boolean-props` - Don't add boolean props to customize
42
+ behavior; use composition
43
+ - `architecture-compound-components` - Structure complex components with shared
44
+ context
45
+
46
+ ### 2. State Management (MEDIUM)
47
+
48
+ - `state-decouple-implementation` - Provider is the only place that knows how
49
+ state is managed
50
+ - `state-context-interface` - Define generic interface with state, actions, meta
51
+ for dependency injection
52
+ - `state-lift-state` - Move state into provider components for sibling access
53
+
54
+ ### 3. Implementation Patterns (MEDIUM)
55
+
56
+ - `patterns-explicit-variants` - Create explicit variant components instead of
57
+ boolean modes
58
+ - `patterns-children-over-render-props` - Use children for composition instead
59
+ of renderX props
60
+
61
+ ### 4. React 19 APIs (MEDIUM)
62
+
63
+ > **⚠️ React 19+ only.** Skip this section if using React 18 or earlier.
64
+
65
+ - `react19-no-forwardref` - Don't use `forwardRef`; use `use()` instead of `useContext()`
66
+
67
+ ## How to Use
68
+
69
+ Read individual rule files for detailed explanations and code examples:
70
+
71
+ ```
72
+ rules/architecture-avoid-boolean-props.md
73
+ rules/state-context-interface.md
74
+ ```
75
+
76
+ Each rule file contains:
77
+
78
+ - Brief explanation of why it matters
79
+ - Incorrect code example with explanation
80
+ - Correct code example with explanation
81
+ - Additional context and references
82
+
83
+ Use the matching files in `rules/` for the expanded guide.
@@ -0,0 +1,100 @@
1
+ ---
2
+ title: Avoid Boolean Prop Proliferation
3
+ impact: CRITICAL
4
+ impactDescription: prevents unmaintainable component variants
5
+ tags: composition, props, architecture
6
+ ---
7
+
8
+ ## Avoid Boolean Prop Proliferation
9
+
10
+ Don't add boolean props like `isThread`, `isEditing`, `isDMThread` to customize
11
+ component behavior. Each boolean doubles possible states and creates
12
+ unmaintainable conditional logic. Use composition instead.
13
+
14
+ **Incorrect (boolean props create exponential complexity):**
15
+
16
+ ```tsx
17
+ function Composer({
18
+ onSubmit,
19
+ isThread,
20
+ channelId,
21
+ isDMThread,
22
+ dmId,
23
+ isEditing,
24
+ isForwarding,
25
+ }: Props) {
26
+ return (
27
+ <form>
28
+ <Header />
29
+ <Input />
30
+ {isDMThread ? (
31
+ <AlsoSendToDMField id={dmId} />
32
+ ) : isThread ? (
33
+ <AlsoSendToChannelField id={channelId} />
34
+ ) : null}
35
+ {isEditing ? (
36
+ <EditActions />
37
+ ) : isForwarding ? (
38
+ <ForwardActions />
39
+ ) : (
40
+ <DefaultActions />
41
+ )}
42
+ <Footer onSubmit={onSubmit} />
43
+ </form>
44
+ )
45
+ }
46
+ ```
47
+
48
+ **Correct (composition eliminates conditionals):**
49
+
50
+ ```tsx
51
+ // Channel composer
52
+ function ChannelComposer() {
53
+ return (
54
+ <Composer.Frame>
55
+ <Composer.Header />
56
+ <Composer.Input />
57
+ <Composer.Footer>
58
+ <Composer.Attachments />
59
+ <Composer.Formatting />
60
+ <Composer.Emojis />
61
+ <Composer.Submit />
62
+ </Composer.Footer>
63
+ </Composer.Frame>
64
+ )
65
+ }
66
+
67
+ // Thread composer - adds "also send to channel" field
68
+ function ThreadComposer({ channelId }: { channelId: string }) {
69
+ return (
70
+ <Composer.Frame>
71
+ <Composer.Header />
72
+ <Composer.Input />
73
+ <AlsoSendToChannelField id={channelId} />
74
+ <Composer.Footer>
75
+ <Composer.Formatting />
76
+ <Composer.Emojis />
77
+ <Composer.Submit />
78
+ </Composer.Footer>
79
+ </Composer.Frame>
80
+ )
81
+ }
82
+
83
+ // Edit composer - different footer actions
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. We can share internals without
100
+ sharing a single monolithic parent.
@@ -0,0 +1,112 @@
1
+ ---
2
+ title: Use Compound Components
3
+ impact: HIGH
4
+ impactDescription: enables flexible composition without prop drilling
5
+ tags: composition, compound-components, architecture
6
+ ---
7
+
8
+ ## Use Compound Components
9
+
10
+ Structure complex components as compound components with a shared context. Each
11
+ subcomponent accesses shared state via context, not props. Consumers compose the
12
+ pieces they need.
13
+
14
+ **Incorrect (monolithic component with render props):**
15
+
16
+ ```tsx
17
+ function Composer({
18
+ renderHeader,
19
+ renderFooter,
20
+ renderActions,
21
+ showAttachments,
22
+ showFormatting,
23
+ showEmojis,
24
+ }: Props) {
25
+ return (
26
+ <form>
27
+ {renderHeader?.()}
28
+ <Input />
29
+ {showAttachments && <Attachments />}
30
+ {renderFooter ? (
31
+ renderFooter()
32
+ ) : (
33
+ <Footer>
34
+ {showFormatting && <Formatting />}
35
+ {showEmojis && <Emojis />}
36
+ {renderActions?.()}
37
+ </Footer>
38
+ )}
39
+ </form>
40
+ )
41
+ }
42
+ ```
43
+
44
+ **Correct (compound components with shared context):**
45
+
46
+ ```tsx
47
+ const ComposerContext = createContext<ComposerContextValue | null>(null)
48
+
49
+ function ComposerProvider({ children, state, actions, meta }: ProviderProps) {
50
+ return (
51
+ <ComposerContext value={{ state, actions, meta }}>
52
+ {children}
53
+ </ComposerContext>
54
+ )
55
+ }
56
+
57
+ function ComposerFrame({ children }: { children: React.ReactNode }) {
58
+ return <form>{children}</form>
59
+ }
60
+
61
+ function ComposerInput() {
62
+ const {
63
+ state,
64
+ actions: { update },
65
+ meta: { inputRef },
66
+ } = use(ComposerContext)
67
+ return (
68
+ <TextInput
69
+ ref={inputRef}
70
+ value={state.input}
71
+ onChangeText={(text) => update((s) => ({ ...s, input: text }))}
72
+ />
73
+ )
74
+ }
75
+
76
+ function ComposerSubmit() {
77
+ const {
78
+ actions: { submit },
79
+ } = use(ComposerContext)
80
+ return <Button onPress={submit}>Send</Button>
81
+ }
82
+
83
+ // Export as compound component
84
+ const Composer = {
85
+ Provider: ComposerProvider,
86
+ Frame: ComposerFrame,
87
+ Input: ComposerInput,
88
+ Submit: ComposerSubmit,
89
+ Header: ComposerHeader,
90
+ Footer: ComposerFooter,
91
+ Attachments: ComposerAttachments,
92
+ Formatting: ComposerFormatting,
93
+ Emojis: ComposerEmojis,
94
+ }
95
+ ```
96
+
97
+ **Usage:**
98
+
99
+ ```tsx
100
+ <Composer.Provider state={state} actions={actions} meta={meta}>
101
+ <Composer.Frame>
102
+ <Composer.Header />
103
+ <Composer.Input />
104
+ <Composer.Footer>
105
+ <Composer.Formatting />
106
+ <Composer.Submit />
107
+ </Composer.Footer>
108
+ </Composer.Frame>
109
+ </Composer.Provider>
110
+ ```
111
+
112
+ Consumers explicitly compose exactly what they need. No hidden conditionals. And the state, actions and meta are dependency-injected by a parent provider, allowing multiple usages of the same component structure.
@@ -0,0 +1,87 @@
1
+ ---
2
+ title: Prefer Composing Children Over Render Props
3
+ impact: MEDIUM
4
+ impactDescription: cleaner composition, better readability
5
+ tags: composition, children, render-props
6
+ ---
7
+
8
+ ## Prefer Children Over Render Props
9
+
10
+ Use `children` for composition instead of `renderX` props. Children are more
11
+ readable, compose naturally, and don't require understanding callback
12
+ signatures.
13
+
14
+ **Incorrect (render props):**
15
+
16
+ ```tsx
17
+ function Composer({
18
+ renderHeader,
19
+ renderFooter,
20
+ renderActions,
21
+ }: {
22
+ renderHeader?: () => React.ReactNode
23
+ renderFooter?: () => React.ReactNode
24
+ renderActions?: () => React.ReactNode
25
+ }) {
26
+ return (
27
+ <form>
28
+ {renderHeader?.()}
29
+ <Input />
30
+ {renderFooter ? renderFooter() : <DefaultFooter />}
31
+ {renderActions?.()}
32
+ </form>
33
+ )
34
+ }
35
+
36
+ // Usage is awkward and inflexible
37
+ return (
38
+ <Composer
39
+ renderHeader={() => <CustomHeader />}
40
+ renderFooter={() => (
41
+ <>
42
+ <Formatting />
43
+ <Emojis />
44
+ </>
45
+ )}
46
+ renderActions={() => <SubmitButton />}
47
+ />
48
+ )
49
+ ```
50
+
51
+ **Correct (compound components with children):**
52
+
53
+ ```tsx
54
+ function ComposerFrame({ children }: { children: React.ReactNode }) {
55
+ return <form>{children}</form>
56
+ }
57
+
58
+ function ComposerFooter({ children }: { children: React.ReactNode }) {
59
+ return <footer className='flex'>{children}</footer>
60
+ }
61
+
62
+ // Usage is flexible
63
+ return (
64
+ <Composer.Frame>
65
+ <CustomHeader />
66
+ <Composer.Input />
67
+ <Composer.Footer>
68
+ <Composer.Formatting />
69
+ <Composer.Emojis />
70
+ <SubmitButton />
71
+ </Composer.Footer>
72
+ </Composer.Frame>
73
+ )
74
+ ```
75
+
76
+ **When render props are appropriate:**
77
+
78
+ ```tsx
79
+ // Render props work well when you need to pass data back
80
+ <List
81
+ data={items}
82
+ renderItem={({ item, index }) => <Item item={item} index={index} />}
83
+ />
84
+ ```
85
+
86
+ Use render props when the parent needs to provide data or state to the child.
87
+ Use children when composing static structure.
@@ -0,0 +1,100 @@
1
+ ---
2
+ title: Create Explicit Component Variants
3
+ impact: MEDIUM
4
+ impactDescription: self-documenting code, no hidden conditionals
5
+ tags: composition, variants, architecture
6
+ ---
7
+
8
+ ## Create Explicit Component Variants
9
+
10
+ Instead of one component with many boolean props, create explicit variant
11
+ components. Each variant composes the pieces it needs. The code documents
12
+ itself.
13
+
14
+ **Incorrect (one component, many modes):**
15
+
16
+ ```tsx
17
+ // What does this component actually render?
18
+ <Composer
19
+ isThread
20
+ isEditing={false}
21
+ channelId='abc'
22
+ showAttachments
23
+ showFormatting={false}
24
+ />
25
+ ```
26
+
27
+ **Correct (explicit variants):**
28
+
29
+ ```tsx
30
+ // Immediately clear what this renders
31
+ <ThreadComposer channelId="abc" />
32
+
33
+ // Or
34
+ <EditMessageComposer messageId="xyz" />
35
+
36
+ // Or
37
+ <ForwardMessageComposer messageId="123" />
38
+ ```
39
+
40
+ Each implementation is unique, explicit and self-contained. Yet they can each
41
+ use shared parts.
42
+
43
+ **Implementation:**
44
+
45
+ ```tsx
46
+ function ThreadComposer({ channelId }: { channelId: string }) {
47
+ return (
48
+ <ThreadProvider channelId={channelId}>
49
+ <Composer.Frame>
50
+ <Composer.Input />
51
+ <AlsoSendToChannelField channelId={channelId} />
52
+ <Composer.Footer>
53
+ <Composer.Formatting />
54
+ <Composer.Emojis />
55
+ <Composer.Submit />
56
+ </Composer.Footer>
57
+ </Composer.Frame>
58
+ </ThreadProvider>
59
+ )
60
+ }
61
+
62
+ function EditMessageComposer({ messageId }: { messageId: string }) {
63
+ return (
64
+ <EditMessageProvider messageId={messageId}>
65
+ <Composer.Frame>
66
+ <Composer.Input />
67
+ <Composer.Footer>
68
+ <Composer.Formatting />
69
+ <Composer.Emojis />
70
+ <Composer.CancelEdit />
71
+ <Composer.SaveEdit />
72
+ </Composer.Footer>
73
+ </Composer.Frame>
74
+ </EditMessageProvider>
75
+ )
76
+ }
77
+
78
+ function ForwardMessageComposer({ messageId }: { messageId: string }) {
79
+ return (
80
+ <ForwardMessageProvider messageId={messageId}>
81
+ <Composer.Frame>
82
+ <Composer.Input placeholder="Add a message, if you'd like." />
83
+ <Composer.Footer>
84
+ <Composer.Formatting />
85
+ <Composer.Emojis />
86
+ <Composer.Mentions />
87
+ </Composer.Footer>
88
+ </Composer.Frame>
89
+ </ForwardMessageProvider>
90
+ )
91
+ }
92
+ ```
93
+
94
+ Each variant is explicit about:
95
+
96
+ - What provider/state it uses
97
+ - What UI elements it includes
98
+ - What actions are available
99
+
100
+ No boolean prop combinations to reason about. No impossible states.
@@ -0,0 +1,42 @@
1
+ ---
2
+ title: React 19 API Changes
3
+ impact: MEDIUM
4
+ impactDescription: cleaner component definitions and context usage
5
+ tags: react19, refs, context, hooks
6
+ ---
7
+
8
+ ## React 19 API Changes
9
+
10
+ > **⚠️ React 19+ only.** Skip this if you're on React 18 or earlier.
11
+
12
+ In React 19, `ref` is now a regular prop (no `forwardRef` wrapper needed), and `use()` replaces `useContext()`.
13
+
14
+ **Incorrect (forwardRef in React 19):**
15
+
16
+ ```tsx
17
+ const ComposerInput = forwardRef<TextInput, Props>((props, ref) => {
18
+ return <TextInput ref={ref} {...props} />
19
+ })
20
+ ```
21
+
22
+ **Correct (ref as a regular prop):**
23
+
24
+ ```tsx
25
+ function ComposerInput({ ref, ...props }: Props & { ref?: React.Ref<TextInput> }) {
26
+ return <TextInput ref={ref} {...props} />
27
+ }
28
+ ```
29
+
30
+ **Incorrect (useContext in React 19):**
31
+
32
+ ```tsx
33
+ const value = useContext(MyContext)
34
+ ```
35
+
36
+ **Correct (use instead of useContext):**
37
+
38
+ ```tsx
39
+ const value = use(MyContext)
40
+ ```
41
+
42
+ `use()` can also be called conditionally, unlike `useContext()`.
@@ -0,0 +1,191 @@
1
+ ---
2
+ title: Define Generic Context Interfaces for Dependency Injection
3
+ impact: HIGH
4
+ impactDescription: enables dependency-injectable state across use-cases
5
+ tags: composition, context, state, typescript, dependency-injection
6
+ ---
7
+
8
+ ## Define Generic Context Interfaces for Dependency Injection
9
+
10
+ Define a **generic interface** for your component context with three parts:
11
+ `state`, `actions`, and `meta`. This interface is a contract that any provider
12
+ can implement—enabling the same UI components to work with completely different
13
+ state implementations.
14
+
15
+ **Core principle:** Lift state, compose internals, make state
16
+ dependency-injectable.
17
+
18
+ **Incorrect (UI coupled to specific state implementation):**
19
+
20
+ ```tsx
21
+ function ComposerInput() {
22
+ // Tightly coupled to a specific hook
23
+ const { input, setInput } = useChannelComposerState()
24
+ return <TextInput value={input} onChangeText={setInput} />
25
+ }
26
+ ```
27
+
28
+ **Correct (generic interface enables dependency injection):**
29
+
30
+ ```tsx
31
+ // Define a GENERIC interface that any provider can implement
32
+ interface ComposerState {
33
+ input: string
34
+ attachments: Attachment[]
35
+ isSubmitting: boolean
36
+ }
37
+
38
+ interface ComposerActions {
39
+ update: (updater: (state: ComposerState) => ComposerState) => void
40
+ submit: () => void
41
+ }
42
+
43
+ interface ComposerMeta {
44
+ inputRef: React.RefObject<TextInput>
45
+ }
46
+
47
+ interface ComposerContextValue {
48
+ state: ComposerState
49
+ actions: ComposerActions
50
+ meta: ComposerMeta
51
+ }
52
+
53
+ const ComposerContext = createContext<ComposerContextValue | null>(null)
54
+ ```
55
+
56
+ **UI components consume the interface, not the implementation:**
57
+
58
+ ```tsx
59
+ function ComposerInput() {
60
+ const {
61
+ state,
62
+ actions: { update },
63
+ meta,
64
+ } = use(ComposerContext)
65
+
66
+ // This component works with ANY provider that implements the interface
67
+ return (
68
+ <TextInput
69
+ ref={meta.inputRef}
70
+ value={state.input}
71
+ onChangeText={(text) => update((s) => ({ ...s, input: text }))}
72
+ />
73
+ )
74
+ }
75
+ ```
76
+
77
+ **Different providers implement the same interface:**
78
+
79
+ ```tsx
80
+ // Provider A: Local state for ephemeral forms
81
+ function ForwardMessageProvider({ children }: { children: React.ReactNode }) {
82
+ const [state, setState] = useState(initialState)
83
+ const inputRef = useRef(null)
84
+ const submit = useForwardMessage()
85
+
86
+ return (
87
+ <ComposerContext
88
+ value={{
89
+ state,
90
+ actions: { update: setState, submit },
91
+ meta: { inputRef },
92
+ }}
93
+ >
94
+ {children}
95
+ </ComposerContext>
96
+ )
97
+ }
98
+
99
+ // Provider B: Global synced state for channels
100
+ function ChannelProvider({ channelId, children }: Props) {
101
+ const { state, update, submit } = useGlobalChannel(channelId)
102
+ const inputRef = useRef(null)
103
+
104
+ return (
105
+ <ComposerContext
106
+ value={{
107
+ state,
108
+ actions: { update, submit },
109
+ meta: { inputRef },
110
+ }}
111
+ >
112
+ {children}
113
+ </ComposerContext>
114
+ )
115
+ }
116
+ ```
117
+
118
+ **The same composed UI works with both:**
119
+
120
+ ```tsx
121
+ // Works with ForwardMessageProvider (local state)
122
+ <ForwardMessageProvider>
123
+ <Composer.Frame>
124
+ <Composer.Input />
125
+ <Composer.Submit />
126
+ </Composer.Frame>
127
+ </ForwardMessageProvider>
128
+
129
+ // Works with ChannelProvider (global synced state)
130
+ <ChannelProvider channelId="abc">
131
+ <Composer.Frame>
132
+ <Composer.Input />
133
+ <Composer.Submit />
134
+ </Composer.Frame>
135
+ </ChannelProvider>
136
+ ```
137
+
138
+ **Custom UI outside the component can access state and actions:**
139
+
140
+ The provider boundary is what matters—not the visual nesting. Components that
141
+ need shared state don't have to be inside the `Composer.Frame`. They just need
142
+ to be within the provider.
143
+
144
+ ```tsx
145
+ function ForwardMessageDialog() {
146
+ return (
147
+ <ForwardMessageProvider>
148
+ <Dialog>
149
+ {/* The composer UI */}
150
+ <Composer.Frame>
151
+ <Composer.Input placeholder="Add a message, if you'd like." />
152
+ <Composer.Footer>
153
+ <Composer.Formatting />
154
+ <Composer.Emojis />
155
+ </Composer.Footer>
156
+ </Composer.Frame>
157
+
158
+ {/* Custom UI OUTSIDE the composer, but INSIDE the provider */}
159
+ <MessagePreview />
160
+
161
+ {/* Actions at the bottom of the dialog */}
162
+ <DialogActions>
163
+ <CancelButton />
164
+ <ForwardButton />
165
+ </DialogActions>
166
+ </Dialog>
167
+ </ForwardMessageProvider>
168
+ )
169
+ }
170
+
171
+ // This button lives OUTSIDE Composer.Frame but can still submit based on its context!
172
+ function ForwardButton() {
173
+ const {
174
+ actions: { submit },
175
+ } = use(ComposerContext)
176
+ return <Button onPress={submit}>Forward</Button>
177
+ }
178
+
179
+ // This preview lives OUTSIDE Composer.Frame but can read composer's state!
180
+ function MessagePreview() {
181
+ const { state } = use(ComposerContext)
182
+ return <Preview message={state.input} attachments={state.attachments} />
183
+ }
184
+ ```
185
+
186
+ The `ForwardButton` and `MessagePreview` are not visually inside the composer
187
+ box, but they can still access its state and actions. This is the power of
188
+ lifting state into providers.
189
+
190
+ The UI is reusable bits you compose together. The state is dependency-injected
191
+ by the provider. Swap the provider, keep the UI.