rooibos 0.5.0 → 0.6.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 (169) hide show
  1. checksums.yaml +4 -4
  2. data/.builds/ruby-3.2.yml +9 -5
  3. data/.builds/ruby-3.3.yml +9 -5
  4. data/.builds/ruby-3.4.yml +9 -5
  5. data/.builds/ruby-4.0.0.yml +9 -5
  6. data/AGENTS.md +1 -1
  7. data/CHANGELOG.md +46 -0
  8. data/README.md +2 -2
  9. data/README.rdoc +374 -0
  10. data/REUSE.toml +5 -0
  11. data/Rakefile +1 -1
  12. data/doc/best_practices/forms_and_validation.md +20 -0
  13. data/doc/best_practices/http_workflows.md +20 -0
  14. data/doc/best_practices/index.md +26 -0
  15. data/doc/best_practices/lists_and_tables.md +20 -0
  16. data/doc/best_practices/modal_dialogs.md +20 -0
  17. data/doc/best_practices/no_stateful_widgets.md +184 -0
  18. data/doc/best_practices/orchestration.md +20 -0
  19. data/doc/best_practices/streaming_data.md +20 -0
  20. data/doc/contributors/design/commands_and_outlets.md +1 -1
  21. data/doc/contributors/documentation_plan.md +616 -0
  22. data/doc/contributors/documentation_stub_audit.md +112 -0
  23. data/doc/contributors/documentation_style.md +275 -0
  24. data/doc/contributors/e2e_pty.md +168 -0
  25. data/doc/contributors/specs/earliest_tutorial_steps_per_story.md +70 -0
  26. data/doc/contributors/specs/file_browser.md +789 -0
  27. data/doc/contributors/specs/file_browser_stories.md +774 -0
  28. data/doc/contributors/specs/tutorials_to_stories.rb +167 -0
  29. data/doc/contributors/todo/scrollbar.md +118 -0
  30. data/doc/contributors/tutorial_old/01_project_setup.md +20 -0
  31. data/doc/contributors/tutorial_old/02_hello_world.md +24 -0
  32. data/doc/contributors/tutorial_old/03_adding_state.md +26 -0
  33. data/doc/contributors/tutorial_old/06_organizing_your_code.md +20 -0
  34. data/doc/contributors/tutorial_old/07_your_first_command.md +21 -0
  35. data/doc/contributors/tutorial_old/08_the_preview_pane.md +20 -0
  36. data/doc/contributors/tutorial_old/09_loading_states.md +20 -0
  37. data/doc/contributors/tutorial_old/10_testing_your_app.md +20 -0
  38. data/doc/contributors/tutorial_old/11_polish_and_refine.md +20 -0
  39. data/doc/contributors/tutorial_old/12_going_further.md +20 -0
  40. data/doc/contributors/tutorial_old/index.md +20 -0
  41. data/doc/essentials/commands.md +20 -0
  42. data/doc/essentials/index.md +31 -0
  43. data/doc/essentials/messages.md +21 -0
  44. data/doc/essentials/models.md +21 -0
  45. data/doc/essentials/shortcuts.md +19 -0
  46. data/doc/essentials/the_elm_architecture.md +24 -0
  47. data/doc/essentials/the_runtime.md +21 -0
  48. data/doc/essentials/update_functions.md +20 -0
  49. data/doc/essentials/views.md +22 -0
  50. data/doc/getting_started/for_go_developers.md +16 -0
  51. data/doc/getting_started/for_python_developers.md +16 -0
  52. data/doc/getting_started/for_react_developers.md +17 -0
  53. data/doc/getting_started/index.md +52 -0
  54. data/doc/getting_started/install.md +20 -0
  55. data/doc/getting_started/quickstart.md +9 -45
  56. data/doc/getting_started/ruby_primer.md +19 -0
  57. data/doc/getting_started/why_rooibos.md +20 -0
  58. data/doc/index.md +79 -11
  59. data/doc/scaling_up/async_patterns.md +20 -0
  60. data/doc/scaling_up/command_composition.md +20 -0
  61. data/doc/scaling_up/custom_commands.md +21 -0
  62. data/doc/scaling_up/fractal_architecture.md +20 -0
  63. data/doc/scaling_up/index.md +30 -0
  64. data/doc/scaling_up/message_routing.md +20 -0
  65. data/doc/scaling_up/ractor_safety.md +20 -0
  66. data/doc/scaling_up/testing.md +21 -0
  67. data/doc/troubleshooting/common_errors.md +20 -0
  68. data/doc/troubleshooting/debugging.md +21 -0
  69. data/doc/troubleshooting/index.md +23 -0
  70. data/doc/troubleshooting/performance.md +20 -0
  71. data/doc/tutorial/01_project_setup.md +44 -0
  72. data/doc/tutorial/02_hello_world.md +45 -0
  73. data/doc/tutorial/03_static_file_list.md +44 -0
  74. data/doc/tutorial/04_arrow_navigation.md +47 -0
  75. data/doc/tutorial/05_real_files.md +45 -0
  76. data/doc/tutorial/06_safe_refactoring.md +21 -0
  77. data/doc/tutorial/07_red_first_tdd.md +26 -0
  78. data/doc/tutorial/08_file_metadata.md +42 -0
  79. data/doc/tutorial/09_text_preview.md +44 -0
  80. data/doc/tutorial/10_directory_tree.md +42 -0
  81. data/doc/tutorial/11_pane_focus.md +40 -0
  82. data/doc/tutorial/12_sorting.md +41 -0
  83. data/doc/tutorial/13_filtering.md +43 -0
  84. data/doc/tutorial/14_toggle_hidden.md +41 -0
  85. data/doc/tutorial/15_text_input_widget.md +43 -0
  86. data/doc/tutorial/16_rename_files.md +42 -0
  87. data/doc/tutorial/17_confirmation_dialogs.md +43 -0
  88. data/doc/tutorial/18_progress_indicators.md +43 -0
  89. data/doc/tutorial/19_atomic_operations.md +42 -0
  90. data/doc/tutorial/20_external_editor.md +42 -0
  91. data/doc/tutorial/21_modal_overlays.md +41 -0
  92. data/doc/tutorial/22_error_handling.md +43 -0
  93. data/doc/tutorial/23_terminal_capabilities.md +53 -0
  94. data/doc/tutorial/24_mouse_events.md +43 -0
  95. data/doc/tutorial/25_resize_events.md +43 -0
  96. data/doc/tutorial/26_loading_states.md +42 -0
  97. data/doc/tutorial/27_performance.md +43 -0
  98. data/doc/tutorial/28_color_schemes.md +47 -0
  99. data/doc/tutorial/29_configuration.md +124 -0
  100. data/doc/tutorial/30_going_further.md +17 -0
  101. data/doc/tutorial/index.md +17 -0
  102. data/examples/app_file_browser/app.rb +40 -0
  103. data/examples/app_fractal_dashboard/dashboard/update_manual.rb +7 -7
  104. data/examples/app_fractal_dashboard/fragments/custom_shell_input.rb +5 -5
  105. data/examples/app_fractal_dashboard/fragments/custom_shell_modal.rb +1 -1
  106. data/examples/app_fractal_dashboard/fragments/disk_usage.rb +2 -2
  107. data/examples/app_fractal_dashboard/fragments/network_panel.rb +4 -4
  108. data/examples/app_fractal_dashboard/fragments/ping.rb +2 -2
  109. data/examples/app_fractal_dashboard/fragments/stats_panel.rb +4 -4
  110. data/examples/app_fractal_dashboard/fragments/system_info.rb +2 -2
  111. data/examples/app_fractal_dashboard/fragments/uptime.rb +2 -2
  112. data/examples/verify_website_first_app/app.rb +85 -0
  113. data/examples/verify_website_hello_mvu/app.rb +31 -0
  114. data/examples/widget_command_system/app.rb +15 -13
  115. data/exe/rooibos +10 -0
  116. data/generate_tutorial_stubs.rb +126 -0
  117. data/lib/rooibos/cli/commands/new.rb +373 -0
  118. data/lib/rooibos/cli/commands/run.rb +98 -0
  119. data/lib/rooibos/cli.rb +78 -0
  120. data/lib/rooibos/command/all.rb +25 -20
  121. data/lib/rooibos/command/batch.rb +26 -25
  122. data/lib/rooibos/command/custom.rb +84 -1
  123. data/lib/rooibos/command/http.rb +59 -55
  124. data/lib/rooibos/command/lifecycle.rb +5 -5
  125. data/lib/rooibos/command/open.rb +86 -0
  126. data/lib/rooibos/command/outlet.rb +105 -3
  127. data/lib/rooibos/command/wait.rb +5 -5
  128. data/lib/rooibos/command.rb +57 -74
  129. data/lib/rooibos/message/batch.rb +39 -0
  130. data/lib/rooibos/message/canceled.rb +51 -0
  131. data/lib/rooibos/message/error.rb +48 -0
  132. data/lib/rooibos/message/open.rb +30 -0
  133. data/lib/rooibos/message.rb +84 -4
  134. data/lib/rooibos/router.rb +11 -14
  135. data/lib/rooibos/runtime.rb +40 -43
  136. data/lib/rooibos/shortcuts.rb +47 -0
  137. data/lib/rooibos/test_helper.rb +71 -6
  138. data/lib/rooibos/version.rb +1 -1
  139. data/lib/rooibos/welcome.rb +237 -0
  140. data/lib/rooibos.rb +4 -3
  141. data/mise.toml +1 -1
  142. data/rbs_collection.lock.yaml +2 -2
  143. data/sig/concurrent.rbs +3 -0
  144. data/sig/gem.rbs +20 -0
  145. data/sig/rooibos/cli.rbs +42 -0
  146. data/sig/rooibos/command.rbs +48 -0
  147. data/sig/rooibos/message.rbs +60 -0
  148. data/sig/rooibos/shortcuts.rbs +14 -0
  149. data/sig/rooibos/test_helper.rbs +6 -2
  150. data/sig/rooibos/welcome.rbs +75 -0
  151. data/tasks/install.rake +29 -0
  152. data/tasks/resources/build.yml.erb +2 -0
  153. metadata +272 -38
  154. data/doc/concepts/application_architecture.md +0 -197
  155. data/doc/concepts/application_testing.md +0 -49
  156. data/doc/concepts/async_work.md +0 -164
  157. data/doc/concepts/commands.md +0 -530
  158. data/doc/concepts/message_processing.md +0 -51
  159. data/doc/contributors/WIP/decomposition_strategies_analysis.md +0 -258
  160. data/doc/contributors/WIP/implementation_plan.md +0 -409
  161. data/doc/contributors/WIP/init_callable_proposal.md +0 -344
  162. data/doc/contributors/WIP/runtime_refactoring_status.md +0 -47
  163. data/doc/contributors/WIP/task.md +0 -36
  164. data/doc/contributors/WIP/v0.4.0_todo.md +0 -468
  165. data/doc/contributors/kit-no-outlet.md +0 -238
  166. data/doc/contributors/priorities.md +0 -38
  167. data/doc/images/.gitkeep +0 -0
  168. data/exe/.gitkeep +0 -0
  169. /data/doc/contributors/{WIP → design}/mvu_tea_implementations_research.md +0 -0
@@ -1,51 +0,0 @@
1
- <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
4
- -->
5
-
6
- # Message Processing
7
-
8
- The runtime processes messages one at a time.
9
-
10
- You build interactive apps. Events arrive from everywhere: keyboard, mouse,
11
- timers, HTTP responses. Coordinating concurrent results feels complex.
12
-
13
- Rooibos handles the concurrency. Your `update` function handles exactly one message
14
- per invocation. The runtime schedules everything else.
15
-
16
- ## Recurring Ticks
17
-
18
- For animations or polling, re-dispatch the tick in your update function:
19
-
20
- ```ruby
21
- def update(msg, model)
22
- case msg
23
- when [:tick, _elapsed]
24
- [model.with(frame: model.frame + 1), Command.tick(0.016, :tick)]
25
- end
26
- end
27
- ```
28
-
29
- Can a tick and a keyboard event arrive at the same time?
30
-
31
- No. The runtime serializes all messages. Each frame, it polls for user input,
32
- calls `update` with any event it finds, and dispatches the returned command.
33
- Then it drains the background channel, calling `update` once for each queued
34
- message. Two events that occur in the same frame become two sequential calls.
35
- Each returns its own command. They never collide.
36
-
37
- ## When to Use Command.batch
38
-
39
- Use `Command.batch` when a single message triggers multiple effects:
40
-
41
- ```ruby
42
- when :init
43
- [model, Command.batch(
44
- Command.tick(0.016, :tick),
45
- Command.http(get: "/api/data", :loaded)
46
- )]
47
- ```
48
-
49
- This differs from "two messages arrived simultaneously." Here, you send two
50
- commands at once. Even if both complete in exactly the same time, their results
51
- arrive as two distinct calls to `update`.
@@ -1,258 +0,0 @@
1
- <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
-
4
- SPDX-License-Identifier: CC-BY-SA-4.0
5
- -->
6
-
7
- # MVU/TEA Decomposition Strategies Analysis
8
-
9
- ## Decomposition Style Categories
10
-
11
- ### FRACTAL Style (Recursive MVU Triads)
12
- Each component/module is a complete MVU unit with its own Model, Update, and View. Components nest recursively, parent delegates to children. Child components are self-contained and can be composed.
13
-
14
- ### SLICE Style (Domain-Segregated State)
15
- State is partitioned by domain/feature, but update/view logic may be centralized or cross-cutting. Each slice typically has Model + Update, with views potentially pulling from multiple slices.
16
-
17
- ### HYBRID
18
- Combines both patterns - some aspects use fractal composition, others use slice partitioning.
19
-
20
- ### NO DECOMPOSITION
21
- Framework does not provide explicit support for breaking down complex applications.
22
-
23
- ---
24
-
25
- ## Framework Categorization
26
-
27
- ### 🟢 FRACTAL Decomposition
28
-
29
- #### **1. Elm (Original TEA)**
30
- - **Style**: Fractal (historically, with evolution)
31
- - **Terminology**: "Nested TEA", "Modules", "Translator Pattern" / "OutMsg Pattern"
32
- - **Details**:
33
- - Originally promoted recursive MVU triads (child modules with own Model/Msg/update/view)
34
- - Parent uses `Html.map` and `Cmd.map` to transform child messages
35
- - **Evolution**: Elm 0.19 de-emphasized deep nesting due to boilerplate
36
- - Current recommendation: Shallow nesting, reusable view functions over deep component trees
37
- - "Translator Pattern" for child-to-parent communication (child returns OutMsg for parent)
38
- - **Composition**: Yes, via `Html.map` / `Cmd.map` and OutMsg pattern
39
-
40
- #### **2. Bubble Tea (Go)**
41
- - **Style**: Fractal
42
- - **Terminology**: "Tree of Models", "Nested Models", "Child Components"
43
- - **Details**:
44
- - Each component has its own `Model` struct with `Init()`, `Update()`, `View()` methods
45
- - Parent embeds child models as fields
46
- - Parent routes messages to children based on state (often using session/state enum)
47
- - View composition combines child view strings
48
- - Uses "Bubbles" library for pre-built components
49
- - **Composition**: Yes, explicit message routing in parent's Update
50
-
51
- #### **3. Iced (Rust)**
52
- - **Style**: Fractal
53
- - **Terminology**: "Nested components", "Message routing", "`.map()` transformation"
54
- - **Details**:
55
- - Each component can have State + Message enum + update + view
56
- - Parent's Message enum wraps child Message types
57
- - Uses `.map()` to transform child messages/commands/elements to parent context
58
- - `Subscription::batch()` for combining child subscriptions
59
- - Note: `Component` trait deprecated in 0.13+ (violated single source of truth)
60
- - **Composition**: Yes, via `.map()` transformation
61
-
62
- #### **4. Elmish (F#/Fable)**
63
- - **Style**: Fractal
64
- - **Terminology**: "Nested TEA", "Child modules"
65
- - **Details**:
66
- - Direct port of Elm Architecture to F#
67
- - Each module has `Model * Cmd<Msg>` init, `update`, `view`
68
- - Parent maps child messages and commands
69
- - Used with React for rendering
70
- - **Composition**: Yes, same as Elm
71
-
72
- #### **5. Hyperapp (JavaScript)**
73
- - **Style**: Fractal-lite
74
- - **Terminology**: No specific term (minimal framework)
75
- - **Details**:
76
- - Unified global state, but can be structured recursively
77
- - Effects can be nested in init array `[state, effect1, effect2]`
78
- - Very lightweight (1KB), minimal opinions
79
- - **Composition**: Limited, more state-tree focused than component-focused
80
-
81
- ---
82
-
83
- ### 🔵 SLICE Decomposition
84
-
85
- #### **6. Redux (JavaScript/React)**
86
- - **Style**: PURE SLICE
87
- - **Terminology**: "Slices", "Reducers", "State combination"
88
- - **Details**:
89
- - `createSlice` creates domain-specific state + reducers
90
- - Each slice has `name`, `initialState`, `reducers`
91
- - Slices combined via `configureStore({ reducer: { user: userSlice, posts: postsSlice } })`
92
- - Views (React components) can access any slice via selectors
93
- - **NOT strictly MVU** (no built-in effects), but pattern is similar
94
- - **Composition**: Yes, via `combineReducers` / `configureStore`
95
- - **Notable**: Slices have reducers, but no dedicated views - views are separate React components
96
-
97
- ---
98
-
99
- ### 🟡 HYBRID Decomposition
100
-
101
- #### **7. TCA (Swift - The Composable Architecture)**
102
- - **Style**: HYBRID (Fractal-ish with powerful scoping)
103
- - **Terminology**: "Reducers", "Scoping", "Pullback", "Child features", "Composition"
104
- - **Details**:
105
- - Each "feature" is a `Reducer` with nested `State` and `Action` types
106
- - Uses `.scope()` to focus parent state/actions on child domain
107
- - Can compose reducers horizontally (siblings) or vertically (parent-child)
108
- - **More sophisticated than pure fractal**: dependency injection, effects management, testing tools
109
- - Parent doesn't just delegate - uses lenses/scoping to project state
110
- - **Composition**: Yes, via `Reducer` composition operators and scoping
111
-
112
- #### **8. Flutter Bloc**
113
- - **Style**: HYBRID
114
- - **Terminology**: "BloC per feature/screen", "Nested BloCs", "BlocProvider", "MultiBlocProvider"
115
- - **Details**:
116
- - Recommended pattern: one Bloc/Cubit per screen or feature
117
- - BloCs can be nested via `BlocProvider` (dependency injection)
118
- - `MultiBlocProvider` for multiple BloCs in widget tree
119
- - **Not pure fractal**: BloCs don't nest MVU triads, they're separate event-driven state machines
120
- - **Not pure slice**: Each BloC is feature-specific, views are Flutter widgets
121
- - **Composition**: Yes, via provider pattern (DI), not via direct delegation
122
-
123
- #### **9. Android MVI (Kotlin)**
124
- - **Style**: HYBRID
125
- - **Terminology**: "ViewModel per feature", "StateFlow", "Intent channels"
126
- - **Details**:
127
- - Each ViewModel manages feature state via `StateFlow`
128
- - Intents sent to ViewModel via `SharedFlow` or `Channel`
129
- - ViewModels can be scoped to fragments/activities
130
- - **Not pure fractal**: ViewModels are independent state machines, not nested MVU
131
- - **Not pure slice**: Each ViewModel is feature-bound
132
- - **Composition**: Limited, mostly via ViewModel scoping and shared state
133
-
134
- #### **10. Meiosis (JavaScript)**
135
- - **Style**: HYBRID
136
- - **Terminology**: "Services", "Nested components" (optional), "Initial model composition"
137
- - **Details**:
138
- - Flexible pattern, not opinionated
139
- - Can compose via `initialModel` merging
140
- - "meiosis-setup" library helps with nested components and services
141
- - View-library agnostic
142
- - **Composition**: Yes, but flexible/manual
143
-
144
- ---
145
-
146
- ### ⚫ NO EXPLICIT DECOMPOSITION
147
-
148
- #### **11. SAM Pattern (JavaScript)**
149
- - **Style**: No explicit decomposition support
150
- - **Terminology**: N/A
151
- - **Details**:
152
- - Single Model (state tree)
153
- - Single State Representation function
154
- - Actions propose mutations
155
- - Based on TLA+ formalism
156
- - **Philosophical**: Focused on temporal logic and correctness, less on composition
157
- - **Composition**: Not a focus
158
-
159
- ---
160
-
161
- ### 🟣 OTHER / MINIMAL DOCUMENTATION
162
-
163
- #### **12-16. .NET Implementations**
164
- - **Fabulous (F#/MAUI)**: Likely **FRACTAL** (F# MVU port, similar to Elmish)
165
- - **BlazorMVU (C#/Blazor)**: Likely **FRACTAL** (Elm-inspired)
166
- - **MauiReactor (C#/MAUI)**: Likely **FRACTAL** (MVU for .NET MAUI)
167
- - **MVUX (.NET/Uno)**: **HYBRID** (Model-View-Update eXtended, data binding focus)
168
- - **ngx-mvu (Angular)**: Likely **HYBRID** (Angular + MVU concepts)
169
-
170
- ---
171
-
172
- ## Summary Table
173
-
174
- | Framework | Style | Terminology |
175
- |-----------|-------|-------------|
176
- | **Elm** | Fractal (evolved) | Nested TEA, Modules, Translator/OutMsg Pattern |
177
- | **Bubble Tea** | Fractal | Tree of Models, Nested Models, Child Components |
178
- | **Iced** | Fractal | Nested components, Message routing, `.map()` |
179
- | **Elmish** | Fractal | Nested TEA, Child modules |
180
- | **Hyperapp** | Fractal-lite | (minimal framework, no specific term) |
181
- | **Redux** | **SLICE** | **Slices**, Reducers, State combination |
182
- | **TCA** | **HYBRID** | Reducers, Scoping, Pullback, Child features |
183
- | **Flutter Bloc** | **HYBRID** | BloC per feature, Nested BloCs, Providers |
184
- | **Android MVI** | **HYBRID** | ViewModel per feature, StateFlow, Intents |
185
- | **Meiosis** | **HYBRID** | Services, Nested components (optional) |
186
- | **SAM** | None | N/A (TLA+ formalism focus) |
187
- | Fabulous | Fractal (likely) | (F# MVU) |
188
- | BlazorMVU | Fractal (likely) | (Elm-inspired) |
189
- | MauiReactor | Fractal (likely) | (MVU for MAUI) |
190
- | MVUX | Hybrid (likely) | (Extended MVU, data binding) |
191
- | ngx-mvu | Hybrid (likely) | (Angular + MVU) |
192
-
193
- ---
194
-
195
- ## Key Insights
196
-
197
- ### Fractal Pattern Characteristics:
198
- 1. ✅ **Complete MVU triads** for each component
199
- 2. ✅ **Recursive composition** (components contain components)
200
- 3. ✅ **Message delegation** (parent forwards to child)
201
- 4. ✅ **View composition** (parent combines child views)
202
- 5. ❌ **High boilerplate** (Elm community moved away from deep nesting)
203
-
204
- **Examples**: Elm (original), Bubble Tea, Iced, Elmish
205
-
206
- ### Slice Pattern Characteristics:
207
- 1. ✅ **Domain-partitioned state** (slices by feature)
208
- 2. ✅ **Flat composition** (slices are siblings, not nested)
209
- 3. ✅ **Centralized view** (views pull from multiple slices)
210
- 4. ✅ **Low boilerplate** (slices are simple)
211
- 5. ❌ **No per-slice views** (views are separate layer)
212
-
213
- **Example**: Redux (pure slice pattern)
214
-
215
- ### Hybrid Pattern Characteristics:
216
- 1. ✅ **Feature-scoped state** (like slices)
217
- 2. ✅ **Independent update logic** (like fractal)
218
- 3. ✅ **Flexible composition** (dependency injection, scoping)
219
- 4. ✅ **Reduced boilerplate** (compared to pure fractal)
220
- 5. ⚠️ **Framework-specific** (each does it differently)
221
-
222
- **Examples**: TCA (scoping/pullback), Flutter Bloc (providers), Android MVI (ViewModels)
223
-
224
- ---
225
-
226
- ## Where Does Rooibos Fit?
227
-
228
- ### Current State: **FRACTAL**
229
- - Fragments have `Model`, `INITIAL`, `UPDATE`, `VIEW`
230
- - Parents delegate to children via `Rooibos.delegate`
231
- - Message routing via `Rooibos.route`
232
- - Router DSL for declarative composition
233
-
234
- ### With Init Callable: **ENHANCED FRACTAL**
235
- Your `Init` proposal strengthens the fractal pattern by:
236
- 1. ✅ Enabling **parameterized initialization** (like Iced's `flags`)
237
- 2. ✅ Supporting **initial commands** (like Elm's `(Model, Cmd)`)
238
- 3. ✅ Allowing **parent-to-child props** (React-style, but fractal)
239
- 4. ✅ Maintaining **complete MVU triads** (Model, Init, Update, View)
240
-
241
- This is **closer to Iced** (Rust) than Elm, as Iced explicitly supports flags for initialization and has evolved beyond Elm's original design.
242
-
243
- ---
244
-
245
- ## Recommendation
246
-
247
- Rooibos should **embrace the modern fractal pattern** with:
248
- - **Complete MVU triads per fragment**: `Model`, `Init`, `Update`, `View`
249
- - **Parameterized initialization**: `Init` accepts flags/props
250
- - **Explicit composition**: Parent calls child `Init`, routes messages, composes views
251
-
252
- This positions Rooibos as:
253
- - **Functional** (like Elm/Elmish/Iced)
254
- - **Composable** (fractal pattern)
255
- - **Modern** (Init callable, not static constants)
256
- - **Parameterizable** (flags/props support)
257
-
258
- **NOT** like Redux (slice pattern) or TCA/Bloc (OOP/hybrid patterns).