claude-mpm 5.4.59__py3-none-any.whl → 5.4.64__py3-none-any.whl

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 claude-mpm might be problematic. Click here for more details.

Files changed (129) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +5 -0
  3. claude_mpm/cli/startup.py +14 -9
  4. claude_mpm/scripts/start_activity_logging.py +0 -0
  5. claude_mpm/services/agents/deployment/agent_template_builder.py +8 -0
  6. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  7. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  8. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  9. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  10. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  11. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  12. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  13. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  14. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  15. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  16. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  17. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  18. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  19. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  20. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  21. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  22. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  23. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  24. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  25. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  26. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  27. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  28. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  29. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  30. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  31. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  32. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  33. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  34. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  35. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  36. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  37. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  38. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  39. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  40. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  41. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  42. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  43. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  44. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  45. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  46. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  47. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  48. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  49. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  50. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  51. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  52. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  53. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  54. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  55. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  56. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  57. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  58. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  59. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  60. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  61. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  62. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  63. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  64. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  65. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  66. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  67. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  68. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  69. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  70. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  71. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  72. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  73. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  74. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  75. claude_mpm/skills/bundled/pm/pm-delegation-patterns/SKILL.md +167 -0
  76. claude_mpm/skills/bundled/pm/pm-git-file-tracking/SKILL.md +113 -0
  77. claude_mpm/skills/bundled/pm/pm-pr-workflow/SKILL.md +124 -0
  78. claude_mpm/skills/bundled/pm/pm-ticketing-integration/SKILL.md +154 -0
  79. claude_mpm/skills/bundled/pm/pm-verification-protocols/SKILL.md +198 -0
  80. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  81. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  82. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  83. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  84. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  85. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  86. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  87. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  88. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  89. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  90. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  91. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  92. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  93. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  94. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  95. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  96. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  97. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  98. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  99. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  100. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  101. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  102. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  103. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  104. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  105. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  106. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  107. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  108. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  109. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  110. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  111. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  112. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  113. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  114. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  115. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  116. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  117. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  118. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  119. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  120. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  121. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  122. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  123. {claude_mpm-5.4.59.dist-info → claude_mpm-5.4.64.dist-info}/METADATA +1 -1
  124. {claude_mpm-5.4.59.dist-info → claude_mpm-5.4.64.dist-info}/RECORD +128 -11
  125. {claude_mpm-5.4.59.dist-info → claude_mpm-5.4.64.dist-info}/WHEEL +0 -0
  126. {claude_mpm-5.4.59.dist-info → claude_mpm-5.4.64.dist-info}/entry_points.txt +0 -0
  127. {claude_mpm-5.4.59.dist-info → claude_mpm-5.4.64.dist-info}/licenses/LICENSE +0 -0
  128. {claude_mpm-5.4.59.dist-info → claude_mpm-5.4.64.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  129. {claude_mpm-5.4.59.dist-info → claude_mpm-5.4.64.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,742 @@
1
+ ---
2
+ name: flexlayout-react
3
+ description: FlexLayout for React - Advanced docking layout manager with drag-and-drop, tabs, splitters, and complex window management
4
+ version: 1.0.0
5
+ category: development
6
+ author: Claude MPM Team
7
+ license: MIT
8
+ progressive_disclosure:
9
+ entry_point:
10
+ summary: "Professional docking layout system: drag-and-drop panels, tabs, splitters, persistence, complex multi-pane interfaces"
11
+ when_to_use: "Building IDE-like interfaces, dashboard builders, multi-document editors, complex admin panels with draggable panes"
12
+ quick_start: "1. Create model with Model.fromJson() 2. Wrap app in Layout component 3. Define factory function 4. Persist with model.toJson()"
13
+ context_limit: 700
14
+ tags:
15
+ - react
16
+ - layout
17
+ - docking
18
+ - drag-drop
19
+ - ide
20
+ - dashboard
21
+ - flexlayout
22
+ requires_tools: []
23
+ ---
24
+
25
+ # FlexLayout-React - Professional Docking Layouts
26
+
27
+ ## Overview
28
+
29
+ FlexLayout-React provides IDE-quality docking layouts with drag-and-drop, tabs, splitters, and complex window management. Perfect for dashboards, IDEs, admin panels, and any interface requiring flexible, user-customizable layouts.
30
+
31
+ **Key Features**:
32
+ - Drag-and-drop panel repositioning
33
+ - Tabbed interfaces with close, maximize, minimize
34
+ - Splitters for resizable panes
35
+ - Border docking areas
36
+ - Layout persistence (save/restore)
37
+ - Programmatic layout control
38
+ - TypeScript support
39
+
40
+ **Installation**:
41
+ ```bash
42
+ npm install flexlayout-react
43
+ ```
44
+
45
+ ## Basic Setup
46
+
47
+ ### 1. Define Layout Model
48
+
49
+ ```typescript
50
+ import { Model, IJsonModel } from 'flexlayout-react';
51
+
52
+ const initialLayout: IJsonModel = {
53
+ global: {
54
+ tabEnableClose: true,
55
+ tabEnableRename: false,
56
+ },
57
+ borders: [],
58
+ layout: {
59
+ type: 'row',
60
+ weight: 100,
61
+ children: [
62
+ {
63
+ type: 'tabset',
64
+ weight: 50,
65
+ children: [
66
+ {
67
+ type: 'tab',
68
+ name: 'Explorer',
69
+ component: 'explorer',
70
+ }
71
+ ]
72
+ },
73
+ {
74
+ type: 'tabset',
75
+ weight: 50,
76
+ children: [
77
+ {
78
+ type: 'tab',
79
+ name: 'Editor',
80
+ component: 'editor',
81
+ }
82
+ ]
83
+ }
84
+ ]
85
+ }
86
+ };
87
+
88
+ // Create model
89
+ const model = Model.fromJson(initialLayout);
90
+ ```
91
+
92
+ ### 2. Create Layout Component
93
+
94
+ ```typescript
95
+ import React, { useRef } from 'react';
96
+ import { Layout, Model, TabNode, IJsonTabNode } from 'flexlayout-react';
97
+ import 'flexlayout-react/style/dark.css'; // or light.css
98
+
99
+ interface ComponentRegistry {
100
+ explorer: React.ComponentType;
101
+ editor: React.ComponentType;
102
+ terminal: React.ComponentType;
103
+ }
104
+
105
+ function App() {
106
+ const modelRef = useRef(Model.fromJson(initialLayout));
107
+
108
+ const factory = (node: TabNode) => {
109
+ const component = node.getComponent();
110
+
111
+ switch (component) {
112
+ case 'explorer':
113
+ return <ExplorerPanel />;
114
+ case 'editor':
115
+ return <EditorPanel />;
116
+ case 'terminal':
117
+ return <TerminalPanel />;
118
+ default:
119
+ return <div>Unknown component: {component}</div>;
120
+ }
121
+ };
122
+
123
+ return (
124
+ <div style={{ width: '100vw', height: '100vh' }}>
125
+ <Layout
126
+ model={modelRef.current}
127
+ factory={factory}
128
+ />
129
+ </div>
130
+ );
131
+ }
132
+ ```
133
+
134
+ ### 3. Component Implementation
135
+
136
+ ```typescript
137
+ function ExplorerPanel() {
138
+ return (
139
+ <div className="panel-explorer">
140
+ <h3>File Explorer</h3>
141
+ <ul>
142
+ <li>src/</li>
143
+ <li>public/</li>
144
+ <li>package.json</li>
145
+ </ul>
146
+ </div>
147
+ );
148
+ }
149
+
150
+ function EditorPanel() {
151
+ return (
152
+ <div className="panel-editor">
153
+ <textarea
154
+ style={{ width: '100%', height: '100%' }}
155
+ placeholder="Start typing..."
156
+ />
157
+ </div>
158
+ );
159
+ }
160
+ ```
161
+
162
+ ## Advanced Layout Configurations
163
+
164
+ ### Complex Multi-Pane Layout
165
+
166
+ ```typescript
167
+ const complexLayout: IJsonModel = {
168
+ global: {
169
+ tabEnableClose: true,
170
+ tabEnableRename: false,
171
+ tabEnableDrag: true,
172
+ tabEnableFloat: true,
173
+ borderSize: 200,
174
+ },
175
+ borders: [
176
+ {
177
+ type: 'border',
178
+ location: 'left',
179
+ size: 250,
180
+ children: [
181
+ {
182
+ type: 'tab',
183
+ name: 'Explorer',
184
+ component: 'explorer',
185
+ }
186
+ ]
187
+ },
188
+ {
189
+ type: 'border',
190
+ location: 'bottom',
191
+ size: 200,
192
+ children: [
193
+ {
194
+ type: 'tab',
195
+ name: 'Terminal',
196
+ component: 'terminal',
197
+ },
198
+ {
199
+ type: 'tab',
200
+ name: 'Output',
201
+ component: 'output',
202
+ }
203
+ ]
204
+ }
205
+ ],
206
+ layout: {
207
+ type: 'row',
208
+ weight: 100,
209
+ children: [
210
+ {
211
+ type: 'tabset',
212
+ weight: 70,
213
+ children: [
214
+ {
215
+ type: 'tab',
216
+ name: 'Editor 1',
217
+ component: 'editor',
218
+ },
219
+ {
220
+ type: 'tab',
221
+ name: 'Editor 2',
222
+ component: 'editor',
223
+ }
224
+ ]
225
+ },
226
+ {
227
+ type: 'tabset',
228
+ weight: 30,
229
+ children: [
230
+ {
231
+ type: 'tab',
232
+ name: 'Properties',
233
+ component: 'properties',
234
+ },
235
+ {
236
+ type: 'tab',
237
+ name: 'Outline',
238
+ component: 'outline',
239
+ }
240
+ ]
241
+ }
242
+ ]
243
+ }
244
+ };
245
+ ```
246
+
247
+ ### Nested Rows and Columns
248
+
249
+ ```typescript
250
+ const nestedLayout: IJsonModel = {
251
+ global: {},
252
+ borders: [],
253
+ layout: {
254
+ type: 'row',
255
+ children: [
256
+ {
257
+ type: 'col',
258
+ weight: 50,
259
+ children: [
260
+ {
261
+ type: 'tabset',
262
+ weight: 70,
263
+ children: [
264
+ { type: 'tab', name: 'Top Left', component: 'panel-a' }
265
+ ]
266
+ },
267
+ {
268
+ type: 'tabset',
269
+ weight: 30,
270
+ children: [
271
+ { type: 'tab', name: 'Bottom Left', component: 'panel-b' }
272
+ ]
273
+ }
274
+ ]
275
+ },
276
+ {
277
+ type: 'col',
278
+ weight: 50,
279
+ children: [
280
+ {
281
+ type: 'tabset',
282
+ weight: 30,
283
+ children: [
284
+ { type: 'tab', name: 'Top Right', component: 'panel-c' }
285
+ ]
286
+ },
287
+ {
288
+ type: 'tabset',
289
+ weight: 70,
290
+ children: [
291
+ { type: 'tab', name: 'Bottom Right', component: 'panel-d' }
292
+ ]
293
+ }
294
+ ]
295
+ }
296
+ ]
297
+ }
298
+ };
299
+ ```
300
+
301
+ ## Layout Persistence
302
+
303
+ ### Save and Restore Layout
304
+
305
+ ```typescript
306
+ import { useState, useEffect } from 'react';
307
+ import { Model, Actions } from 'flexlayout-react';
308
+
309
+ function LayoutManager() {
310
+ const [model, setModel] = useState(() => {
311
+ // Load from localStorage
312
+ const saved = localStorage.getItem('layout');
313
+ return saved
314
+ ? Model.fromJson(JSON.parse(saved))
315
+ : Model.fromJson(defaultLayout);
316
+ });
317
+
318
+ // Save on model change
319
+ const onModelChange = (newModel: Model) => {
320
+ const json = newModel.toJson();
321
+ localStorage.setItem('layout', JSON.stringify(json));
322
+ };
323
+
324
+ return (
325
+ <Layout
326
+ model={model}
327
+ factory={factory}
328
+ onModelChange={onModelChange}
329
+ />
330
+ );
331
+ }
332
+ ```
333
+
334
+ ### Reset to Default Layout
335
+
336
+ ```typescript
337
+ function LayoutControls({ model }: { model: Model }) {
338
+ const resetLayout = () => {
339
+ const newModel = Model.fromJson(defaultLayout);
340
+ // Need to replace model reference
341
+ window.location.reload(); // Simple approach
342
+ };
343
+
344
+ const saveLayout = () => {
345
+ const json = model.toJson();
346
+ const blob = new Blob([JSON.stringify(json, null, 2)], {
347
+ type: 'application/json'
348
+ });
349
+ const url = URL.createObjectURL(blob);
350
+ const a = document.createElement('a');
351
+ a.href = url;
352
+ a.download = 'layout.json';
353
+ a.click();
354
+ };
355
+
356
+ return (
357
+ <div className="layout-controls">
358
+ <button onClick={resetLayout}>Reset Layout</button>
359
+ <button onClick={saveLayout}>Export Layout</button>
360
+ </div>
361
+ );
362
+ }
363
+ ```
364
+
365
+ ## Dynamic Tab Management
366
+
367
+ ### Adding Tabs Programmatically
368
+
369
+ ```typescript
370
+ import { Actions, DockLocation } from 'flexlayout-react';
371
+
372
+ function addNewTab(model: Model, tabsetId: string) {
373
+ model.doAction(Actions.addNode(
374
+ {
375
+ type: 'tab',
376
+ name: `New Tab ${Date.now()}`,
377
+ component: 'editor',
378
+ },
379
+ tabsetId,
380
+ DockLocation.CENTER,
381
+ -1
382
+ ));
383
+ }
384
+
385
+ // Add to specific tabset
386
+ const addToExplorer = () => {
387
+ addNewTab(model, 'explorer-tabset-id');
388
+ };
389
+
390
+ // Add to active tabset
391
+ const addToActive = () => {
392
+ const activeTabset = model.getActiveTabset();
393
+ if (activeTabset) {
394
+ addNewTab(model, activeTabset.getId());
395
+ }
396
+ };
397
+ ```
398
+
399
+ ### Closing Tabs
400
+
401
+ ```typescript
402
+ function closeTab(model: Model, tabId: string) {
403
+ model.doAction(Actions.deleteTab(tabId));
404
+ }
405
+
406
+ function closeAllTabs(model: Model) {
407
+ const tabsets = model.getRoot().getChildren();
408
+ tabsets.forEach(tabset => {
409
+ if (tabset.getType() === 'tabset') {
410
+ const tabs = tabset.getChildren();
411
+ tabs.forEach(tab => {
412
+ if (tab.getType() === 'tab') {
413
+ model.doAction(Actions.deleteTab(tab.getId()));
414
+ }
415
+ });
416
+ }
417
+ });
418
+ }
419
+ ```
420
+
421
+ ## Tab Context and Props
422
+
423
+ ### Passing Data to Components
424
+
425
+ ```typescript
426
+ interface EditorTabProps {
427
+ node: TabNode;
428
+ }
429
+
430
+ function EditorTab({ node }: EditorTabProps) {
431
+ const filepath = node.getConfig()?.filepath as string;
432
+ const readonly = node.getConfig()?.readonly as boolean;
433
+
434
+ return (
435
+ <div>
436
+ <p>Editing: {filepath}</p>
437
+ <textarea readOnly={readonly} />
438
+ </div>
439
+ );
440
+ }
441
+
442
+ // Factory with data passing
443
+ const factory = (node: TabNode) => {
444
+ const component = node.getComponent();
445
+
446
+ switch (component) {
447
+ case 'editor':
448
+ return <EditorTab node={node} />;
449
+ default:
450
+ return <div>Unknown</div>;
451
+ }
452
+ };
453
+
454
+ // Create tab with config
455
+ const newTab: IJsonTabNode = {
456
+ type: 'tab',
457
+ name: 'my-file.ts',
458
+ component: 'editor',
459
+ config: {
460
+ filepath: '/src/my-file.ts',
461
+ readonly: false,
462
+ }
463
+ };
464
+ ```
465
+
466
+ ### Accessing Tab State
467
+
468
+ ```typescript
469
+ function SmartPanel({ node }: { node: TabNode }) {
470
+ const name = node.getName();
471
+ const isActive = node.isSelected();
472
+ const isVisible = node.isVisible();
473
+
474
+ return (
475
+ <div className={isActive ? 'active' : 'inactive'}>
476
+ <h3>{name}</h3>
477
+ {isVisible && <p>This tab is visible</p>}
478
+ </div>
479
+ );
480
+ }
481
+ ```
482
+
483
+ ## Styling and Theming
484
+
485
+ ### Custom CSS
486
+
487
+ ```css
488
+ /* Override FlexLayout styles */
489
+ .flexlayout__layout {
490
+ background: #1e1e1e;
491
+ }
492
+
493
+ .flexlayout__tab {
494
+ background: #2d2d2d;
495
+ color: #cccccc;
496
+ }
497
+
498
+ .flexlayout__tab:hover {
499
+ background: #3e3e3e;
500
+ }
501
+
502
+ .flexlayout__tab_button--selected {
503
+ background: #1e1e1e;
504
+ border-bottom: 2px solid #007acc;
505
+ }
506
+
507
+ .flexlayout__splitter {
508
+ background: #2d2d2d;
509
+ }
510
+
511
+ .flexlayout__splitter:hover {
512
+ background: #007acc;
513
+ }
514
+ ```
515
+
516
+ ### Dark/Light Theme Toggle
517
+
518
+ ```typescript
519
+ import 'flexlayout-react/style/dark.css';
520
+ // or
521
+ import 'flexlayout-react/style/light.css';
522
+
523
+ function ThemeToggle() {
524
+ const [theme, setTheme] = useState<'dark' | 'light'>('dark');
525
+
526
+ useEffect(() => {
527
+ // Dynamically load theme
528
+ const link = document.createElement('link');
529
+ link.rel = 'stylesheet';
530
+ link.href = `flexlayout-react/style/${theme}.css`;
531
+ document.head.appendChild(link);
532
+
533
+ return () => {
534
+ document.head.removeChild(link);
535
+ };
536
+ }, [theme]);
537
+
538
+ return (
539
+ <button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
540
+ Toggle Theme
541
+ </button>
542
+ );
543
+ }
544
+ ```
545
+
546
+ ## Integration with Tauri
547
+
548
+ ### Persisting Layout to Tauri Backend
549
+
550
+ ```typescript
551
+ import { invoke } from '@tauri-apps/api/core';
552
+
553
+ async function saveLayoutToTauri(model: Model) {
554
+ const json = model.toJson();
555
+ await invoke('save_layout', {
556
+ layout: JSON.stringify(json)
557
+ });
558
+ }
559
+
560
+ async function loadLayoutFromTauri(): Promise<Model> {
561
+ const layout = await invoke<string>('load_layout');
562
+ return Model.fromJson(JSON.parse(layout));
563
+ }
564
+
565
+ // Tauri command (Rust)
566
+ // #[tauri::command]
567
+ // async fn save_layout(layout: String) -> Result<(), String> {
568
+ // let app_dir = app.path_resolver().app_data_dir()?;
569
+ // let layout_file = app_dir.join("layout.json");
570
+ // tokio::fs::write(layout_file, layout).await?;
571
+ // Ok(())
572
+ // }
573
+ ```
574
+
575
+ ### Window-Specific Layouts
576
+
577
+ ```typescript
578
+ import { invoke } from '@tauri-apps/api/core';
579
+ import { getCurrent } from '@tauri-apps/api/window';
580
+
581
+ function WindowLayout() {
582
+ const [model, setModel] = useState<Model | null>(null);
583
+
584
+ useEffect(() => {
585
+ const currentWindow = getCurrent();
586
+ const windowLabel = currentWindow.label;
587
+
588
+ // Load layout for this specific window
589
+ invoke<string>('load_window_layout', { windowLabel })
590
+ .then(layout => {
591
+ setModel(Model.fromJson(JSON.parse(layout)));
592
+ })
593
+ .catch(() => {
594
+ setModel(Model.fromJson(defaultLayout));
595
+ });
596
+ }, []);
597
+
598
+ const onModelChange = (newModel: Model) => {
599
+ const currentWindow = getCurrent();
600
+ const json = newModel.toJson();
601
+
602
+ invoke('save_window_layout', {
603
+ windowLabel: currentWindow.label,
604
+ layout: JSON.stringify(json)
605
+ });
606
+ };
607
+
608
+ if (!model) return <div>Loading...</div>;
609
+
610
+ return (
611
+ <Layout
612
+ model={model}
613
+ factory={factory}
614
+ onModelChange={onModelChange}
615
+ />
616
+ );
617
+ }
618
+ ```
619
+
620
+ ## Advanced Patterns
621
+
622
+ ### Custom Tab Headers
623
+
624
+ ```typescript
625
+ import { Layout, Model, TabNode, ITabRenderValues } from 'flexlayout-react';
626
+
627
+ function App() {
628
+ const onRenderTab = (
629
+ node: TabNode,
630
+ renderValues: ITabRenderValues
631
+ ) => {
632
+ const modified = node.getConfig()?.modified as boolean;
633
+
634
+ renderValues.content = (
635
+ <div className="custom-tab-header">
636
+ <span>{node.getName()}</span>
637
+ {modified && <span className="modified-indicator">●</span>}
638
+ </div>
639
+ );
640
+ };
641
+
642
+ return (
643
+ <Layout
644
+ model={model}
645
+ factory={factory}
646
+ onRenderTab={onRenderTab}
647
+ />
648
+ );
649
+ }
650
+ ```
651
+
652
+ ### Tab Actions (Custom Buttons)
653
+
654
+ ```typescript
655
+ const onRenderTab = (node: TabNode, renderValues: ITabRenderValues) => {
656
+ renderValues.buttons.push(
657
+ <button
658
+ key="save"
659
+ onClick={() => saveTabContent(node)}
660
+ title="Save"
661
+ >
662
+ 💾
663
+ </button>
664
+ );
665
+
666
+ renderValues.buttons.push(
667
+ <button
668
+ key="duplicate"
669
+ onClick={() => duplicateTab(node)}
670
+ title="Duplicate"
671
+ >
672
+ 📋
673
+ </button>
674
+ );
675
+ };
676
+ ```
677
+
678
+ ## Best Practices
679
+
680
+ 1. **Persist layouts** - Save to localStorage or backend for user experience
681
+ 2. **Use unique component names** - Avoid collisions in factory function
682
+ 3. **Handle missing components** - Factory should have default case
683
+ 4. **Memoize factory function** - Prevent unnecessary re-renders
684
+ 5. **Use config for tab data** - Store tab-specific props in config
685
+ 6. **Provide reset mechanism** - Users can restore default layout
686
+ 7. **Test layout changes** - Verify persistence works correctly
687
+ 8. **Handle edge cases** - Empty tabsets, deleted components
688
+ 9. **Use borders wisely** - Left/right/top/bottom for tools, main area for content
689
+ 10. **Optimize large layouts** - Lazy-load components when possible
690
+
691
+ ## Common Pitfalls
692
+
693
+ ❌ **Not memoizing model**:
694
+ ```typescript
695
+ // WRONG - creates new model on every render
696
+ function App() {
697
+ const model = Model.fromJson(layout); // Bad!
698
+ return <Layout model={model} />;
699
+ }
700
+
701
+ // CORRECT
702
+ function App() {
703
+ const modelRef = useRef(Model.fromJson(layout));
704
+ return <Layout model={modelRef.current} />;
705
+ }
706
+ ```
707
+
708
+ ❌ **Forgetting CSS import**:
709
+ ```typescript
710
+ // WRONG - layout won't display correctly
711
+ import { Layout } from 'flexlayout-react';
712
+ // Missing: import 'flexlayout-react/style/dark.css';
713
+ ```
714
+
715
+ ❌ **Not handling onModelChange**:
716
+ ```typescript
717
+ // WRONG - layout changes not persisted
718
+ <Layout model={model} factory={factory} />
719
+
720
+ // CORRECT
721
+ <Layout
722
+ model={model}
723
+ factory={factory}
724
+ onModelChange={saveLayout}
725
+ />
726
+ ```
727
+
728
+ ## Resources
729
+
730
+ - **Documentation**: https://github.com/caplin/FlexLayout
731
+ - **Examples**: https://rawgit.com/caplin/FlexLayout/demos/demos/index.html
732
+ - **TypeScript Types**: Included in package
733
+
734
+ ## Summary
735
+
736
+ - **FlexLayout** provides IDE-quality docking layouts
737
+ - **Model-driven** - Define layout as JSON, control programmatically
738
+ - **Persistent** - Save/restore user layouts easily
739
+ - **Customizable** - Custom tabs, borders, themes
740
+ - **React-friendly** - Hooks, TypeScript support
741
+ - **Perfect for** - IDEs, dashboards, admin panels, complex UIs
742
+ - **Tauri integration** - Persist to backend, window-specific layouts