desktop-team-doc 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/README.md +89 -0
  2. package/content/docs/README.md +227 -0
  3. package/content/docs/index.md +352 -0
  4. package/content/docs/instructions/coding-conventions/.clang-format +65 -0
  5. package/content/docs/instructions/coding-conventions/cpp.md +132 -0
  6. package/content/docs/instructions/coding-conventions/frontend.md +612 -0
  7. package/content/docs/instructions/coding-conventions/team-wide.md +176 -0
  8. package/content/docs/instructions/workflows/assets/jira-1.png +0 -0
  9. package/content/docs/instructions/workflows/assets/jira-comment.png +0 -0
  10. package/content/docs/instructions/workflows/assets/jira-release-note.png +0 -0
  11. package/content/docs/instructions/workflows/assets/jira-tag.png +0 -0
  12. package/content/docs/instructions/workflows/code-review.md +451 -0
  13. package/content/docs/instructions/workflows/git-branch-convention.md +246 -0
  14. package/content/docs/instructions/workflows/git-commit.md +95 -0
  15. package/content/docs/instructions/workflows/jira-process.md +173 -0
  16. package/content/docs/instructions/workflows/jira-ticket-guide.md +105 -0
  17. package/content/docs/instructions/workflows/pull-request-generation.md +319 -0
  18. package/content/docs/instructions/workflows/scrum-process.md +104 -0
  19. package/content/docs/instructions/workflows/survey-project-setup.md +76 -0
  20. package/content/docs/knowledge/architecture/README.md +11 -0
  21. package/content/docs/knowledge/architecture/audio-plugin-architecture.md +213 -0
  22. package/content/docs/knowledge/architecture/cross-platform-design.md +176 -0
  23. package/content/docs/knowledge/architecture/frontend-native-bridge.md +193 -0
  24. package/content/docs/knowledge/architecture/native-command.md +189 -0
  25. package/content/docs/knowledge/architecture/state-management-architecture.md +105 -0
  26. package/content/docs/knowledge/component-library/ControlComponent/README.md +281 -0
  27. package/content/docs/knowledge/component-library/ControlComponent/accessibility/accessibility-implementation.md +503 -0
  28. package/content/docs/knowledge/component-library/ControlComponent/common-mechanisms.md +278 -0
  29. package/content/docs/knowledge/component-library/ControlComponent/core/error-handling.md +451 -0
  30. package/content/docs/knowledge/component-library/ControlComponent/core/native-interface.md +515 -0
  31. package/content/docs/knowledge/component-library/ControlComponent/core/state-management.md +509 -0
  32. package/content/docs/knowledge/component-library/ControlComponent/creating-new-controls.md +654 -0
  33. package/content/docs/knowledge/component-library/ControlComponent/design/api-design-reference.md +1142 -0
  34. package/content/docs/knowledge/component-library/ControlComponent/design/design-principles.md +336 -0
  35. package/content/docs/knowledge/component-library/ControlComponent/design/styling-architecture.md +595 -0
  36. package/content/docs/knowledge/component-library/ControlComponent/design/visual-feedback.md +456 -0
  37. package/content/docs/knowledge/component-library/ControlComponent/development-environment.md +213 -0
  38. package/content/docs/knowledge/component-library/ControlComponent/interaction/gesture-algorithms.md +705 -0
  39. package/content/docs/knowledge/component-library/ControlComponent/interaction/touch-support.md +525 -0
  40. package/content/docs/knowledge/component-library/ControlComponent/interaction/value-processing-patterns.md +801 -0
  41. package/content/docs/knowledge/component-library/ControlComponent/interaction/velocity-damping-systems.md +741 -0
  42. package/content/docs/knowledge/component-library/ControlComponent/knob/architecture.md +490 -0
  43. package/content/docs/knowledge/component-library/ControlComponent/knob/how-to-use.md +304 -0
  44. package/content/docs/knowledge/component-library/ControlComponent/knob/index.md +105 -0
  45. package/content/docs/knowledge/component-library/ControlComponent/optimization/performance-benchmarks.md +535 -0
  46. package/content/docs/knowledge/component-library/ControlComponent/optimization/performance-optimization.md +1092 -0
  47. package/content/docs/knowledge/component-library/ControlComponent/quick-start.md +345 -0
  48. package/content/docs/knowledge/component-library/ControlComponent/slider/architecture.md +444 -0
  49. package/content/docs/knowledge/component-library/ControlComponent/slider/how-to-use.md +470 -0
  50. package/content/docs/knowledge/component-library/ControlComponent/slider/index.md +107 -0
  51. package/content/docs/knowledge/component-library/ControlComponent/testing-guide.md +950 -0
  52. package/content/docs/knowledge/component-library/ControlComponent/troubleshooting.md +657 -0
  53. package/content/docs/knowledge/component-library/frontend-develop/LICENSE.txt +176 -0
  54. package/content/docs/knowledge/component-library/frontend-develop/SKILL.md +124 -0
  55. package/content/docs/knowledge/component-library/frontend-develop/references/code-organization.md +620 -0
  56. package/content/docs/knowledge/component-library/frontend-develop/references/coding-standards.md +275 -0
  57. package/content/docs/knowledge/component-library/frontend-develop/references/component-reusability.md +559 -0
  58. package/content/docs/knowledge/component-library/frontend-develop/references/examples.md +554 -0
  59. package/content/docs/knowledge/component-library/frontend-develop/references/layout-separation.md +638 -0
  60. package/content/docs/knowledge/component-library/frontend-develop/references/performance-optimization.md +678 -0
  61. package/content/docs/knowledge/component-library/frontend-develop/references/state-management.md +331 -0
  62. package/content/docs/knowledge/component-library/frontend-develop/references/styling-guidelines.md +349 -0
  63. package/content/docs/knowledge/component-library/frontend-develop/references/type-safety.md +493 -0
  64. package/content/docs/knowledge/development/assets/cyberduck-aws-credentials.png +0 -0
  65. package/content/docs/knowledge/development/assets/postman-environment-setup.png +0 -0
  66. package/content/docs/knowledge/development/aws-storage.md +95 -0
  67. package/content/docs/knowledge/development/crm-system.md +22 -0
  68. package/content/docs/knowledge/development/glossary.md +246 -0
  69. package/content/docs/knowledge/development/pg-api-guide.md +71 -0
  70. package/content/docs/knowledge/development/staging-license-management.md +44 -0
  71. package/content/docs/knowledge/development/tech-stack.md +240 -0
  72. package/content/docs/knowledge/domain/popup-system.md +106 -0
  73. package/content/docs/knowledge/domain/sigpath.md +264 -0
  74. package/content/docs/knowledge/environment-setup/aax-signing-update.md +149 -0
  75. package/content/docs/knowledge/environment-setup/assets/aax-1.png +0 -0
  76. package/content/docs/knowledge/environment-setup/assets/aax-2.png +0 -0
  77. package/content/docs/knowledge/environment-setup/assets/aax-3.png +0 -0
  78. package/content/docs/knowledge/environment-setup/assets/aax-4.png +0 -0
  79. package/content/docs/knowledge/environment-setup/assets/aax-5.png +0 -0
  80. package/content/docs/knowledge/environment-setup/assets/aax-6.png +0 -0
  81. package/content/docs/knowledge/environment-setup/assets/aax-7.png +0 -0
  82. package/content/docs/knowledge/environment-setup/assets/buildmachine-1.png +0 -0
  83. package/content/docs/knowledge/environment-setup/assets/buildmachine-10.png +0 -0
  84. package/content/docs/knowledge/environment-setup/assets/buildmachine-11.png +0 -0
  85. package/content/docs/knowledge/environment-setup/assets/buildmachine-12.png +0 -0
  86. package/content/docs/knowledge/environment-setup/assets/buildmachine-13.png +0 -0
  87. package/content/docs/knowledge/environment-setup/assets/buildmachine-14.png +0 -0
  88. package/content/docs/knowledge/environment-setup/assets/buildmachine-2.png +0 -0
  89. package/content/docs/knowledge/environment-setup/assets/buildmachine-3.png +0 -0
  90. package/content/docs/knowledge/environment-setup/assets/buildmachine-4.png +0 -0
  91. package/content/docs/knowledge/environment-setup/assets/buildmachine-5.png +0 -0
  92. package/content/docs/knowledge/environment-setup/assets/buildmachine-6.png +0 -0
  93. package/content/docs/knowledge/environment-setup/assets/buildmachine-7.png +0 -0
  94. package/content/docs/knowledge/environment-setup/assets/buildmachine-8.png +0 -0
  95. package/content/docs/knowledge/environment-setup/assets/buildmachine-9.png +0 -0
  96. package/content/docs/knowledge/environment-setup/build-machine-setup.md +224 -0
  97. package/content/docs/knowledge/environment-setup/build-machine-troubleshooting.md +193 -0
  98. package/content/docs/knowledge/implementation-guides/adding-amp.md +190 -0
  99. package/content/docs/knowledge/implementation-guides/adding-fx.md +111 -0
  100. package/content/docs/knowledge/implementation-guides/cab-integration.md +194 -0
  101. package/content/docs/knowledge/implementation-guides/custom-pedal-integration.md +309 -0
  102. package/content/docs/knowledge/projects/BIAS_ONE_GUI/README.md +17 -0
  103. package/content/manifest.json +122 -0
  104. package/content/rules/cpp.mdc +135 -0
  105. package/content/rules/frontend.mdc +615 -0
  106. package/content/rules/index.mdc +256 -0
  107. package/content/rules/knowledge.mdc +46 -0
  108. package/content/rules/team-wide.mdc +179 -0
  109. package/content/rules/workflows.mdc +43 -0
  110. package/content/tools/agents/context-compressor.md +357 -0
  111. package/content/tools/agents/context-writer.md +328 -0
  112. package/content/tools/agents/release-notes-generator.md +389 -0
  113. package/content/tools/agents/srs-writer-agent.md +63 -0
  114. package/content/tools/mcp/README.md +25 -0
  115. package/content/tools/mcp/mcp-desktop-team.example.json +13 -0
  116. package/content/tools/skills/frontend-develop/LICENSE.txt +176 -0
  117. package/content/tools/skills/frontend-develop/SKILL.md +124 -0
  118. package/content/tools/skills/frontend-develop/references/code-organization.md +620 -0
  119. package/content/tools/skills/frontend-develop/references/coding-standards.md +275 -0
  120. package/content/tools/skills/frontend-develop/references/component-reusability.md +559 -0
  121. package/content/tools/skills/frontend-develop/references/examples.md +554 -0
  122. package/content/tools/skills/frontend-develop/references/layout-separation.md +638 -0
  123. package/content/tools/skills/frontend-develop/references/performance-optimization.md +678 -0
  124. package/content/tools/skills/frontend-develop/references/state-management.md +331 -0
  125. package/content/tools/skills/frontend-develop/references/styling-guidelines.md +349 -0
  126. package/content/tools/skills/frontend-develop/references/type-safety.md +493 -0
  127. package/content/tools/slash-commands/commit.md +17 -0
  128. package/content/tools/slash-commands/context-compress.md +149 -0
  129. package/content/tools/slash-commands/context-write.md +92 -0
  130. package/content/tools/slash-commands/jira.md +12 -0
  131. package/content/tools/slash-commands/pr-gen.md +12 -0
  132. package/content/tools/slash-commands/pr-review.md +12 -0
  133. package/dist/commands/detect.d.ts +1 -0
  134. package/dist/commands/detect.js +33 -0
  135. package/dist/commands/install.d.ts +1 -0
  136. package/dist/commands/install.js +100 -0
  137. package/dist/commands/uninstall.d.ts +1 -0
  138. package/dist/commands/uninstall.js +132 -0
  139. package/dist/index.d.ts +2 -0
  140. package/dist/index.js +53 -0
  141. package/dist/lib/detect-env.d.ts +3 -0
  142. package/dist/lib/detect-env.js +52 -0
  143. package/dist/lib/prompt-env.d.ts +3 -0
  144. package/dist/lib/prompt-env.js +16 -0
  145. package/dist/lib/resolve-doc-repo.d.ts +14 -0
  146. package/dist/lib/resolve-doc-repo.js +61 -0
  147. package/dist/lib/symlink.d.ts +7 -0
  148. package/dist/lib/symlink.js +60 -0
  149. package/dist/lib/sync-from-manifest.d.ts +8 -0
  150. package/dist/lib/sync-from-manifest.js +64 -0
  151. package/package.json +46 -0
@@ -0,0 +1,456 @@
1
+ # 視覺回饋指南
2
+
3
+ 本文件說明 Audio Plugin 控制元件的視覺回饋設計原則與實作方法。
4
+
5
+ ---
6
+
7
+ ## 設計原則
8
+
9
+ ### 1. 即時性
10
+
11
+ 視覺回饋必須在使用者操作後立即呈現,延遲不應超過 16ms (60fps)。
12
+
13
+ ### 2. 一致性
14
+
15
+ 所有控制元件應使用統一的視覺語言表達相同的狀態。
16
+
17
+ ### 3. 專業性
18
+
19
+ 模擬實體音訊設備的視覺回饋,提供專業的操作感。
20
+
21
+ ---
22
+
23
+ ## 狀態視覺化
24
+
25
+ ### 互動狀態
26
+
27
+ | 狀態 | 視覺表現 | CSS 實作 |
28
+ |------|---------|---------|
29
+ | **Idle** | 預設樣式 | 無特殊處理 |
30
+ | **Hover** | 輕微高亮 | `filter: brightness(1.1)` |
31
+ | **Active/Dragging** | 明顯高亮 + 游標變更 | `filter: brightness(1.2)`, `cursor: grabbing` |
32
+ | **Focus** | 焦點環 | `outline: 2px solid var(--focus-color)` |
33
+ | **Disabled** | 降低透明度 | `opacity: 0.5`, `pointer-events: none` |
34
+
35
+ ### CSS 變數系統
36
+
37
+ ```css
38
+ /* 定義狀態變數 */
39
+ .audio-control {
40
+ --is-hovering: 0;
41
+ --is-dragging: 0;
42
+ --is-focused: 0;
43
+ --is-disabled: 0;
44
+
45
+ /* 視覺屬性 */
46
+ --brightness: calc(1 + var(--is-hovering) * 0.1 + var(--is-dragging) * 0.2);
47
+ --cursor: grab;
48
+
49
+ filter: brightness(var(--brightness));
50
+ cursor: var(--cursor);
51
+ }
52
+
53
+ .audio-control[data-hovering="true"] {
54
+ --is-hovering: 1;
55
+ }
56
+
57
+ .audio-control[data-dragging="true"] {
58
+ --is-dragging: 1;
59
+ --cursor: grabbing;
60
+ }
61
+
62
+ .audio-control:focus-visible {
63
+ --is-focused: 1;
64
+ outline: 2px solid var(--focus-color, #d3cd36);
65
+ outline-offset: 2px;
66
+ }
67
+
68
+ .audio-control[data-disabled="true"] {
69
+ --is-disabled: 1;
70
+ opacity: 0.5;
71
+ pointer-events: none;
72
+ }
73
+ ```
74
+
75
+ ---
76
+
77
+ ## Knob 視覺回饋
78
+
79
+ ### 旋轉動畫
80
+
81
+ ```css
82
+ /* 旋鈕指示器 */
83
+ .knob__indicator {
84
+ transform: rotate(var(--rotation, 0deg));
85
+ transform-origin: var(--rotate-center, 50% 50%);
86
+
87
+ /* 拖曳時無過渡 */
88
+ transition: transform 0ms;
89
+ }
90
+
91
+ /* 非拖曳時的平滑過渡 */
92
+ .knob:not([data-dragging="true"]) .knob__indicator {
93
+ transition: transform 100ms ease-out;
94
+ }
95
+ ```
96
+
97
+ ### 圖片幀動畫
98
+
99
+ ```typescript
100
+ // 根據值切換圖片幀
101
+ const updateKnobFrame = (value: number, frames: number, basePath: string) => {
102
+ const frameIndex = Math.round(value * (frames - 1));
103
+ const paddedIndex = String(frameIndex).padStart(4, '0');
104
+ return `${basePath}/${paddedIndex}.png`;
105
+ };
106
+
107
+ // 使用
108
+ const imageSrc = updateKnobFrame(normalizedValue, 64, '/images/knobs/vintage');
109
+ knobImage.src = imageSrc;
110
+ ```
111
+
112
+ ### 層疊效果
113
+
114
+ 對於 `FrameMode: 'Layer'` 的旋鈕:
115
+
116
+ ```css
117
+ /* 三層結構 */
118
+ .knob--layered {
119
+ position: relative;
120
+ }
121
+
122
+ /* 底層:背景 */
123
+ .knob__layer-bg {
124
+ position: absolute;
125
+ z-index: 0;
126
+ }
127
+
128
+ /* 中層:指示器 (會旋轉) */
129
+ .knob__layer-indicator {
130
+ position: absolute;
131
+ z-index: 1;
132
+ transform: rotate(var(--rotation));
133
+ }
134
+
135
+ /* 頂層:高光/陰影 */
136
+ .knob__layer-overlay {
137
+ position: absolute;
138
+ z-index: 2;
139
+ pointer-events: none;
140
+ }
141
+ ```
142
+
143
+ ---
144
+
145
+ ## Slider 視覺回饋
146
+
147
+ ### 填充動畫
148
+
149
+ ```css
150
+ /* 滑桿填充 */
151
+ .slider__fill {
152
+ /* 水平滑桿 */
153
+ width: calc(var(--value-normalized, 0) * 100%);
154
+
155
+ /* 或垂直滑桿 */
156
+ height: calc(var(--value-normalized, 0) * 100%);
157
+
158
+ background: linear-gradient(
159
+ 90deg,
160
+ var(--fill-color-start, #4a4a4a),
161
+ var(--fill-color-end, #f2f2f2)
162
+ );
163
+
164
+ transition: none;
165
+ }
166
+
167
+ /* 非拖曳時平滑過渡 */
168
+ .slider:not([data-dragging="true"]) .slider__fill {
169
+ transition: width 100ms ease-out, height 100ms ease-out;
170
+ }
171
+ ```
172
+
173
+ ### 音量條漸層
174
+
175
+ ```css
176
+ /* 專業音量表漸層 */
177
+ .volume-bar__fill {
178
+ background: linear-gradient(
179
+ to top,
180
+ #22c55e 0%, /* 綠色:安全區 */
181
+ #22c55e 60%,
182
+ #eab308 60%, /* 黃色:警告區 */
183
+ #eab308 85%,
184
+ #ef4444 85%, /* 紅色:過載區 */
185
+ #ef4444 100%
186
+ );
187
+ }
188
+
189
+ /* 過載指示燈 */
190
+ .volume-bar__peak-indicator {
191
+ background: #ef4444;
192
+ opacity: var(--is-clipping, 0);
193
+ transition: opacity 50ms;
194
+ }
195
+
196
+ .volume-bar__peak-indicator.active {
197
+ --is-clipping: 1;
198
+ }
199
+ ```
200
+
201
+ ### 把手效果
202
+
203
+ ```css
204
+ /* 滑桿把手 */
205
+ .slider__thumb {
206
+ position: absolute;
207
+ width: 16px;
208
+ height: 16px;
209
+ background: var(--thumb-color, #fff);
210
+ border-radius: 50%;
211
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
212
+
213
+ /* 位置由 CSS 變數控制 */
214
+ left: calc(var(--value-normalized) * 100% - 8px);
215
+
216
+ /* 懸停效果 */
217
+ transition: transform 100ms, box-shadow 100ms;
218
+ }
219
+
220
+ .slider__thumb:hover,
221
+ .slider[data-dragging="true"] .slider__thumb {
222
+ transform: scale(1.2);
223
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
224
+ }
225
+ ```
226
+
227
+ ---
228
+
229
+ ## 數值顯示
230
+
231
+ ### 即時數值提示
232
+
233
+ ```typescript
234
+ // 拖曳時顯示數值標籤
235
+ const ValueTooltip: React.FC<{
236
+ value: number;
237
+ isVisible: boolean;
238
+ format: (v: number) => string;
239
+ }> = ({ value, isVisible, format }) => {
240
+ return (
241
+ <div
242
+ className="value-tooltip"
243
+ style={{
244
+ opacity: isVisible ? 1 : 0,
245
+ transform: `translateY(${isVisible ? 0 : 10}px)`,
246
+ transition: 'opacity 150ms, transform 150ms',
247
+ }}
248
+ >
249
+ {format(value)}
250
+ </div>
251
+ );
252
+ };
253
+ ```
254
+
255
+ ### Native Label 整合
256
+
257
+ ```typescript
258
+ // 使用原生標籤系統
259
+ const { setNativeLabel } = useNativeLabel();
260
+
261
+ // 拖曳開始時顯示
262
+ const handleDragStart = () => {
263
+ setNativeLabel(true);
264
+ };
265
+
266
+ // 拖曳結束後延遲隱藏
267
+ const handleDragEnd = () => {
268
+ setTimeout(() => {
269
+ setNativeLabel(false);
270
+ }, 1000); // 1 秒後隱藏
271
+ };
272
+ ```
273
+
274
+ ---
275
+
276
+ ## 精確模式視覺
277
+
278
+ ### 模式指示
279
+
280
+ ```css
281
+ /* 精確模式指示 */
282
+ .audio-control[data-precise-mode="true"]::after {
283
+ content: 'FINE';
284
+ position: absolute;
285
+ top: -20px;
286
+ left: 50%;
287
+ transform: translateX(-50%);
288
+ font-size: 10px;
289
+ color: var(--precise-indicator-color, #d3cd36);
290
+ opacity: 1;
291
+ transition: opacity 150ms;
292
+ }
293
+ ```
294
+
295
+ ### 靈敏度視覺回饋
296
+
297
+ ```typescript
298
+ // 精確模式下的視覺提示
299
+ const PreciseModeIndicator: React.FC<{ isActive: boolean }> = ({ isActive }) => {
300
+ return (
301
+ <div
302
+ className={`precise-indicator ${isActive ? 'active' : ''}`}
303
+ aria-hidden="true"
304
+ >
305
+ <span className="precise-indicator__icon">🎯</span>
306
+ <span className="precise-indicator__text">Fine Adjust</span>
307
+ </div>
308
+ );
309
+ };
310
+ ```
311
+
312
+ ---
313
+
314
+ ## 錯誤與警告視覺
315
+
316
+ ### 邊界錯誤動畫
317
+
318
+ ```css
319
+ /* 錯誤閃爍動畫 */
320
+ @keyframes errorSplash {
321
+ 0%, 100% {
322
+ border-color: transparent;
323
+ background-color: transparent;
324
+ }
325
+ 50% {
326
+ border-color: #ef4444;
327
+ background-color: rgba(239, 68, 68, 0.1);
328
+ }
329
+ }
330
+
331
+ .input-error {
332
+ animation: errorSplash 300ms linear 3;
333
+ }
334
+ ```
335
+
336
+ ### 超出範圍提示
337
+
338
+ ```css
339
+ /* 超出範圍視覺提示 */
340
+ .value-display.out-of-range {
341
+ color: #ef4444;
342
+ }
343
+
344
+ .value-display.out-of-range::before {
345
+ content: '⚠️ ';
346
+ }
347
+ ```
348
+
349
+ ---
350
+
351
+ ## 過渡動畫
352
+
353
+ ### 值變更過渡
354
+
355
+ ```css
356
+ /* 外部值變更時的平滑過渡 */
357
+ .audio-control:not([data-dragging="true"]) {
358
+ --value-transition: 100ms ease-out;
359
+ }
360
+
361
+ .knob__indicator {
362
+ transition: transform var(--value-transition, 0ms);
363
+ }
364
+
365
+ .slider__fill {
366
+ transition: width var(--value-transition, 0ms),
367
+ height var(--value-transition, 0ms);
368
+ }
369
+ ```
370
+
371
+ ### 預設載入動畫
372
+
373
+ ```css
374
+ /* 預設載入時的動畫 */
375
+ @keyframes valueSet {
376
+ 0% {
377
+ filter: brightness(1.5);
378
+ }
379
+ 100% {
380
+ filter: brightness(1);
381
+ }
382
+ }
383
+
384
+ .audio-control.preset-loading {
385
+ animation: valueSet 300ms ease-out;
386
+ }
387
+ ```
388
+
389
+ ---
390
+
391
+ ## 效能考量
392
+
393
+ ### 使用 GPU 加速
394
+
395
+ ```css
396
+ /* 使用 transform 而非直接改變位置 */
397
+ .knob__indicator {
398
+ /* ✅ 好:使用 transform */
399
+ transform: rotate(var(--rotation));
400
+
401
+ /* ❌ 避免:直接旋轉可能觸發重排 */
402
+ /* rotate: var(--rotation); */
403
+ }
404
+
405
+ /* 啟用 GPU 加速 */
406
+ .slider__fill {
407
+ will-change: transform;
408
+ transform: scaleX(var(--value-normalized));
409
+ transform-origin: left center;
410
+ }
411
+ ```
412
+
413
+ ### 避免 Layout Thrashing
414
+
415
+ ```typescript
416
+ // ✅ 好:批次讀取後批次寫入
417
+ const updateMultipleControls = (updates: ControlUpdate[]) => {
418
+ // 先批次讀取
419
+ const measurements = updates.map(u => ({
420
+ rect: u.element.getBoundingClientRect(),
421
+ ...u,
422
+ }));
423
+
424
+ // 再批次寫入
425
+ requestAnimationFrame(() => {
426
+ measurements.forEach(m => {
427
+ m.element.style.setProperty('--value', String(m.value));
428
+ });
429
+ });
430
+ };
431
+
432
+ // ❌ 避免:交錯讀寫
433
+ updates.forEach(u => {
434
+ const rect = u.element.getBoundingClientRect(); // 讀
435
+ u.element.style.setProperty('--value', String(u.value)); // 寫
436
+ // 每次循環都會觸發重排
437
+ });
438
+ ```
439
+
440
+ ---
441
+
442
+ ## 最佳實踐
443
+
444
+ 1. **使用 CSS 變數** - 透過 CSS 變數更新視覺,避免 React 重新渲染
445
+ 2. **區分拖曳與非拖曳** - 拖曳時無過渡,外部更新時有過渡
446
+ 3. **使用 transform** - 優先使用 transform 進行視覺變化
447
+ 4. **批次更新** - 將多個 DOM 更新合併到同一 RAF 回調
448
+ 5. **適當的過渡時長** - 過渡動畫不超過 150ms,保持即時感
449
+
450
+ ---
451
+
452
+ ## 相關文件
453
+
454
+ - [樣式系統架構](./styling-architecture.md) - CSS 架構設計
455
+ - [效能最佳化策略](../optimization/performance-optimization.md) - 視覺更新效能
456
+ - [API 設計參考](./api-design-reference.md) - 視覺相關 Props
@@ -0,0 +1,213 @@
1
+ # 開發環境與專案結構指南
2
+
3
+ 本文件說明如何建立一個高效的 Audio Plugin 控制元件開發環境,包含推薦的專案結構以及互動式遊樂場 (Playground) 的設置。
4
+
5
+ ---
6
+
7
+ ## 推薦專案結構
8
+
9
+ 為了確保元件的獨立性與可維護性,建議採用以下目錄結構:
10
+
11
+ ```
12
+ src/
13
+ ├── components/ # UI 元件庫
14
+ │ ├── Knob/ # Knob 元件
15
+ │ │ ├── index.tsx # 元件入口
16
+ │ │ ├── Knob.tsx # 實作邏輯
17
+ │ │ ├── types.ts # 類型定義
18
+ │ │ ├── constants.ts # 常數配置
19
+ │ │ └── styles.module.css
20
+ │ ├── Slider/ # Slider 元件
21
+ │ │ └── ...
22
+ │ └── shared/ # 共用子元件 (如 Label, ValueDisplay)
23
+
24
+ ├── hooks/ # 共用 Hooks
25
+ │ ├── useAudioControl.ts # 核心互動邏輯
26
+ │ ├── useParameter.ts # Native Interface 綁定
27
+ │ ├── usePreciseMode.ts # 精確模式處理
28
+ │ └── usePlatform.ts # 平台檢測
29
+
30
+ ├── core/ # 核心定義
31
+ │ ├── NativeInterface.ts # 介面契約定義
32
+ │ └── MockHost.ts # 開發用 Mock 實作
33
+
34
+ ├── contexts/ # React Contexts
35
+ │ └── NativeInterfaceContext.tsx
36
+
37
+ ├── utils/ # 工具函數
38
+ │ ├── math.ts # 數值運算 (clamp, normalize)
39
+ │ ├── platform.ts # 平台檢測工具
40
+ │ └── css.ts # CSS 變數操作
41
+
42
+ ├── styles/ # 全域樣式
43
+ │ ├── variables.css # CSS 變數定義
44
+ │ └── reset.css # 樣式重置
45
+
46
+ └── playground/ # 開發遊樂場 (App Entry)
47
+ ├── App.tsx # 遊樂場主程式
48
+ └── main.tsx # 入口點
49
+ ```
50
+
51
+ ---
52
+
53
+ ## 互動式遊樂場 (Playground)
54
+
55
+ 在開發 Audio Plugin UI 時,我們通常無法隨時連接真實的 DSP 後端。因此,建立一個「互動式遊樂場」至關重要。
56
+
57
+ ### 1. 建立 Mock Host
58
+
59
+ 首先,我們需要一個模擬的 Host 來實作 `NativeInterface`。這個 Mock Host 應該將狀態儲存在記憶體中,並模擬 DAW 的行為。
60
+
61
+ ```typescript
62
+ // core/MockHost.ts
63
+ import { NativeInterface } from './NativeInterface';
64
+
65
+ class MockHost implements NativeInterface {
66
+ private values = new Map<number, number>();
67
+ private listeners = new Map<number, Set<(v: number) => void>>();
68
+
69
+ constructor() {
70
+ // 初始化一些預設值
71
+ this.values.set(0, 0.5); // Gain
72
+ this.values.set(1, 0.0); // Volume
73
+ }
74
+
75
+ parameter = {
76
+ getValue: (pid: number) => this.values.get(pid) ?? 0,
77
+
78
+ setValue: (pid: number, value: number) => {
79
+ this.values.set(pid, value);
80
+ this.notifyListeners(pid, value);
81
+ console.log(`[MockHost] Set Param ${pid} = ${value.toFixed(3)}`);
82
+ },
83
+
84
+ getDisplayValue: (pid: number) => {
85
+ const val = this.values.get(pid) ?? 0;
86
+ return `${(val * 100).toFixed(1)} %`;
87
+ },
88
+
89
+ beginGesture: (pid: number) => console.log(`[MockHost] Begin Gesture ${pid}`),
90
+ endGesture: (pid: number) => console.log(`[MockHost] End Gesture ${pid}`),
91
+ };
92
+
93
+ subscribe(pid: number, callback: (value: number) => void) {
94
+ if (!this.listeners.has(pid)) {
95
+ this.listeners.set(pid, new Set());
96
+ }
97
+ this.listeners.get(pid)!.add(callback);
98
+
99
+ // 立即回調當前值
100
+ callback(this.parameter.getValue(pid));
101
+
102
+ return () => {
103
+ this.listeners.get(pid)?.delete(callback);
104
+ };
105
+ }
106
+
107
+ private notifyListeners(pid: number, value: number) {
108
+ this.listeners.get(pid)?.forEach((cb) => cb(value));
109
+ }
110
+ }
111
+
112
+ export const mockHost = new MockHost();
113
+ ```
114
+
115
+ ### 2. 設定 Storybook (推薦)
116
+
117
+ Storybook 是最適合 UI 元件開發的環境。它允許你獨立開發每個元件,並提供控制項來測試不同狀態。
118
+
119
+ **安裝 Storybook:**
120
+
121
+ ```bash
122
+ npx storybook@latest init
123
+ ```
124
+
125
+ **編寫 Story (Knob.stories.tsx):**
126
+
127
+ ```typescript
128
+ import type { Meta, StoryObj } from '@storybook/react';
129
+ import { Knob } from './Knob';
130
+ import { NativeInterfaceProvider } from '../contexts/NativeInterfaceContext';
131
+ import { mockHost } from '../core/MockHost';
132
+
133
+ const meta: Meta<typeof Knob> = {
134
+ component: Knob,
135
+ decorators: [
136
+ (Story) => (
137
+ <NativeInterfaceProvider value={mockHost}>
138
+ <div style={{ padding: '2rem', background: '#222' }}>
139
+ <Story />
140
+ </div>
141
+ </NativeInterfaceProvider>
142
+ ),
143
+ ],
144
+ };
145
+
146
+ export default meta;
147
+ type Story = StoryObj<typeof Knob>;
148
+
149
+ export const Default: Story = {
150
+ args: {
151
+ pid: 0,
152
+ label: 'Gain',
153
+ },
154
+ };
155
+
156
+ export const Large: Story = {
157
+ args: {
158
+ pid: 0,
159
+ label: 'Master',
160
+ size: 'large',
161
+ },
162
+ };
163
+ ```
164
+
165
+ ### 3. 簡易開發頁面 (Alternative)
166
+
167
+ 如果你不想使用 Storybook,也可以建立一個簡單的 `App.tsx` 作為開發頁面。
168
+
169
+ ```typescript
170
+ // playground/App.tsx
171
+ import React from 'react';
172
+ import { NativeInterfaceProvider } from '../contexts/NativeInterfaceContext';
173
+ import { mockHost } from '../core/MockHost';
174
+ import { Knob } from '../components/Knob';
175
+ import { Slider } from '../components/Slider';
176
+
177
+ export const App = () => {
178
+ return (
179
+ <NativeInterfaceProvider value={mockHost}>
180
+ <div className="playground">
181
+ <h1>Audio Control Playground</h1>
182
+
183
+ <section className="control-group">
184
+ <h2>Knobs</h2>
185
+ <div className="row">
186
+ <Knob pid={0} label="Gain" />
187
+ <Knob pid={1} label="Drive" size="large" />
188
+ <Knob pid={2} label="Tone" size="small" />
189
+ </div>
190
+ </section>
191
+
192
+ <section className="control-group">
193
+ <h2>Sliders</h2>
194
+ <div className="row">
195
+ <Slider pid={3} label="Volume" orientation="vertical" />
196
+ <Slider pid={4} label="Mix" orientation="horizontal" />
197
+ </div>
198
+ </section>
199
+ </div>
200
+ </NativeInterfaceProvider>
201
+ );
202
+ };
203
+ ```
204
+
205
+ ---
206
+
207
+ ## 開發流程建議
208
+
209
+ 1. **定義 API**: 先在 `types.ts` 定義好元件的 Props。
210
+ 2. **建立 Mock**: 在 `MockHost` 中準備好測試用的參數 ID 和預設值。
211
+ 3. **Storybook 開發**: 使用 Storybook 建立元件的各種狀態 (Normal, Disabled, Large, etc.)。
212
+ 4. **互動測試**: 在 Storybook 或 Playground 中測試拖曳、滾輪、精確模式等互動。
213
+ 5. **整合測試**: 最後再整合到真實的 Plugin Host 環境中。