@1agh/maude 0.19.1 → 0.21.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 (105) hide show
  1. package/README.md +7 -0
  2. package/cli/bin/maude.mjs +5 -1
  3. package/cli/commands/design-link.test.mjs +207 -0
  4. package/cli/commands/design.mjs +42 -12
  5. package/cli/commands/doctor.mjs +350 -0
  6. package/cli/commands/doctor.test.mjs +185 -0
  7. package/cli/commands/help.mjs +24 -0
  8. package/cli/commands/hub.mjs +231 -0
  9. package/cli/commands/hub.test.mjs +87 -0
  10. package/cli/lib/config-lint.mjs +141 -0
  11. package/cli/lib/config-lint.test.mjs +117 -0
  12. package/cli/lib/design-link.mjs +216 -0
  13. package/cli/lib/hubs-config.mjs +123 -0
  14. package/cli/lib/hubs-config.test.mjs +100 -0
  15. package/cli/lib/preflight.mjs +232 -0
  16. package/cli/lib/stack-detect.mjs +344 -0
  17. package/cli/lib/stack-detect.test.mjs +121 -0
  18. package/package.json +17 -9
  19. package/plugins/design/dependencies.json +147 -0
  20. package/plugins/design/dependencies.schema.json +107 -0
  21. package/plugins/design/dev-server/ai-banner.tsx +188 -0
  22. package/plugins/design/dev-server/annotations-context-toolbar.tsx +115 -41
  23. package/plugins/design/dev-server/annotations-layer.tsx +256 -107
  24. package/plugins/design/dev-server/api.ts +17 -1
  25. package/plugins/design/dev-server/artboard-marquee.tsx +10 -6
  26. package/plugins/design/dev-server/bin/asset-sweep.sh +180 -0
  27. package/plugins/design/dev-server/bin/preflight.sh +32 -0
  28. package/plugins/design/dev-server/bin/runtime-health.sh +169 -0
  29. package/plugins/design/dev-server/bin/visual-sanity.sh +221 -0
  30. package/plugins/design/dev-server/canvas-lib.tsx +534 -32
  31. package/plugins/design/dev-server/canvas-shell.tsx +479 -29
  32. package/plugins/design/dev-server/client/app.jsx +72 -0
  33. package/plugins/design/dev-server/client/hmr.mjs +28 -0
  34. package/plugins/design/dev-server/collab/ai-activity.ts +127 -0
  35. package/plugins/design/dev-server/collab/git-lifecycle.ts +124 -0
  36. package/plugins/design/dev-server/collab/index.ts +47 -0
  37. package/plugins/design/dev-server/collab/persistence.ts +123 -0
  38. package/plugins/design/dev-server/collab/protocol.ts +108 -0
  39. package/plugins/design/dev-server/collab/registry.ts +110 -0
  40. package/plugins/design/dev-server/collab/room.ts +215 -0
  41. package/plugins/design/dev-server/commands/annotation-strokes-command.ts +127 -0
  42. package/plugins/design/dev-server/commands/equal-spacing-command.ts +28 -0
  43. package/plugins/design/dev-server/commands/move-artboards-command.ts +158 -0
  44. package/plugins/design/dev-server/comments-overlay.tsx +41 -4
  45. package/plugins/design/dev-server/contextual-toolbar.tsx +241 -0
  46. package/plugins/design/dev-server/cursors-overlay.tsx +296 -0
  47. package/plugins/design/dev-server/dist/client.bundle.js +75 -3
  48. package/plugins/design/dev-server/dist/runtime/motion.js +165 -0
  49. package/plugins/design/dev-server/dist/runtime/motion_react.js +409 -0
  50. package/plugins/design/dev-server/dist/runtime/y-protocols_awareness.js +587 -0
  51. package/plugins/design/dev-server/dist/runtime/y-protocols_sync.js +257 -0
  52. package/plugins/design/dev-server/dist/runtime/yjs.js +7107 -0
  53. package/plugins/design/dev-server/equal-spacing-detector.ts +98 -0
  54. package/plugins/design/dev-server/equal-spacing-handles.tsx +289 -0
  55. package/plugins/design/dev-server/export-dialog.tsx +1 -1
  56. package/plugins/design/dev-server/handoff.ts +24 -0
  57. package/plugins/design/dev-server/hmr-broadcast.ts +15 -2
  58. package/plugins/design/dev-server/http.ts +91 -1
  59. package/plugins/design/dev-server/input-router.tsx +52 -2
  60. package/plugins/design/dev-server/marquee-overlay.tsx +282 -0
  61. package/plugins/design/dev-server/participants-chrome.tsx +261 -0
  62. package/plugins/design/dev-server/runtime-bundle.ts +15 -0
  63. package/plugins/design/dev-server/server.ts +78 -11
  64. package/plugins/design/dev-server/test/ai-activity.test.ts +113 -0
  65. package/plugins/design/dev-server/test/annotation-strokes-command.test.ts +149 -0
  66. package/plugins/design/dev-server/test/annotations-layer.test.ts +44 -0
  67. package/plugins/design/dev-server/test/canvas-lib-motion.test.ts +131 -0
  68. package/plugins/design/dev-server/test/collab-annotations-bridge.test.ts +55 -0
  69. package/plugins/design/dev-server/test/collab-bridge.test.ts +81 -0
  70. package/plugins/design/dev-server/test/collab-loopback.test.ts +63 -0
  71. package/plugins/design/dev-server/test/collab-protocol.test.ts +146 -0
  72. package/plugins/design/dev-server/test/collab-room.test.ts +182 -0
  73. package/plugins/design/dev-server/test/collab-stress.test.ts +121 -0
  74. package/plugins/design/dev-server/test/equal-spacing-detector.test.ts +93 -0
  75. package/plugins/design/dev-server/test/git-lifecycle.test.ts +101 -0
  76. package/plugins/design/dev-server/test/input-router.test.ts +87 -1
  77. package/plugins/design/dev-server/test/marquee-overlay.test.ts +94 -0
  78. package/plugins/design/dev-server/test/move-artboards-command.test.ts +108 -0
  79. package/plugins/design/dev-server/test/participants-chrome.test.ts +30 -0
  80. package/plugins/design/dev-server/test/undo-stack.test.ts +211 -0
  81. package/plugins/design/dev-server/test/use-collab.test.ts +71 -0
  82. package/plugins/design/dev-server/test/use-cursor-modifiers.test.ts +59 -0
  83. package/plugins/design/dev-server/test/use-keyboard-discipline.test.ts +27 -0
  84. package/plugins/design/dev-server/test/use-undo-stack.test.tsx +193 -0
  85. package/plugins/design/dev-server/tool-palette.tsx +7 -7
  86. package/plugins/design/dev-server/undo-hud.tsx +95 -0
  87. package/plugins/design/dev-server/undo-stack.ts +240 -0
  88. package/plugins/design/dev-server/use-annotation-resize.tsx +1 -1
  89. package/plugins/design/dev-server/use-artboard-drag.tsx +6 -3
  90. package/plugins/design/dev-server/use-collab.tsx +478 -0
  91. package/plugins/design/dev-server/use-cursor-modifiers.tsx +122 -0
  92. package/plugins/design/dev-server/use-keyboard-discipline.tsx +125 -0
  93. package/plugins/design/dev-server/use-undo-stack.tsx +355 -0
  94. package/plugins/design/dev-server/ws.ts +123 -7
  95. package/plugins/design/templates/_shell.html +51 -6
  96. package/plugins/design/templates/design-system-inspiration/SUB-AGENT-PROMPTS.md +245 -0
  97. package/plugins/design/templates/design-system-inspiration/_MAPPING.md +2 -2
  98. package/plugins/design/templates/design-system-inspiration/core/preview/_components.css.tpl +129 -0
  99. package/plugins/design/templates/design-system-inspiration/core/preview/_motion-readme.md.tpl +63 -0
  100. package/plugins/design/templates/design-system-inspiration/core/preview/motion.css.tpl +106 -0
  101. package/plugins/design/templates/design-system-inspiration/core/preview/motion.tsx.tpl +208 -0
  102. package/plugins/flow/.claude-plugin/config.schema.json +12 -0
  103. package/plugins/flow/dependencies.json +143 -0
  104. package/plugins/flow/dependencies.schema.json +107 -0
  105. /package/plugins/design/templates/design-system-inspiration/core/preview/{motion.html → .archive/motion.html} +0 -0
@@ -25,9 +25,25 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
25
25
  import { type Stroke, useStrokesStore } from './annotations-layer.tsx';
26
26
  import { useAnnotationSelectionOptional } from './use-annotation-selection.tsx';
27
27
 
28
- const PALETTE = ['#d63b1f', '#f5a623', '#1a8f3e', '#1d6cf0', '#7a4ad3', '#1a1a1a'] as const;
28
+ // G6 FigJam-style 11-color palette. Same colors for both stroke and fill
29
+ // so the swatch row identity stays consistent when the user flips the
30
+ // Stroke|Fill mode toggle (only the target attribute changes, not the
31
+ // visual vocabulary).
32
+ const PALETTE = [
33
+ '#1E1E1E', // black
34
+ '#757575', // gray
35
+ '#E03E3E', // red
36
+ '#F26B3F', // orange
37
+ '#F2C744', // yellow
38
+ '#4CAF50', // green
39
+ '#14B8A6', // teal
40
+ '#3B82F6', // blue
41
+ '#8B5CF6', // purple
42
+ '#EC4899', // pink
43
+ '#FFFFFF', // white
44
+ ] as const;
29
45
 
30
- const FILL_PALETTE = ['#fff4d6', '#e6f4ea', '#e3edff', '#f0e8fb', '#ffe5e0', '#f4f1ee'] as const;
46
+ const FILL_PALETTE = PALETTE;
31
47
 
32
48
  const TOOLBAR_CSS = `
33
49
  .dc-annot-ctx {
@@ -57,7 +73,7 @@ const TOOLBAR_CSS = `
57
73
  appearance: none;
58
74
  }
59
75
  .dc-annot-ctx-sw[aria-pressed="true"] {
60
- box-shadow: 0 0 0 2px var(--accent, #d63b1f);
76
+ box-shadow: 0 0 0 2px var(--maude-hud-accent, #d63b1f);
61
77
  border-color: transparent;
62
78
  }
63
79
  .dc-annot-ctx-fill--none {
@@ -87,13 +103,49 @@ const TOOLBAR_CSS = `
87
103
  cursor: pointer;
88
104
  }
89
105
  .dc-annot-ctx-btn[aria-pressed="true"] {
90
- background: var(--accent, #d63b1f);
91
- color: var(--accent-fg, #fff);
106
+ background: var(--maude-hud-accent, #d63b1f);
107
+ color: var(--maude-hud-accent-fg, #fff);
92
108
  border-color: transparent;
93
109
  }
94
110
  .dc-annot-ctx-btn:hover { background: rgba(0,0,0,0.04); }
95
111
  .dc-annot-ctx-btn--danger { color: #b3271a; }
96
112
  .dc-annot-ctx-btn--danger:hover { background: rgba(214,59,31,0.08); }
113
+
114
+ /* T30 / G_S1 — collapsed Stroke|Fill mode toggle. Shown only when the
115
+ selection supports both stroke + fill (rect / ellipse). When the toggle is
116
+ present the swatch row beneath shows ONE palette at a time. */
117
+ .dc-annot-ctx-mode {
118
+ display: inline-flex;
119
+ border-radius: 6px;
120
+ overflow: hidden;
121
+ border: 1px solid rgba(0,0,0,0.18);
122
+ }
123
+ .dc-annot-ctx-mode-btn {
124
+ appearance: none;
125
+ background: transparent;
126
+ border: 0;
127
+ padding: 3px 8px;
128
+ font: inherit;
129
+ color: inherit;
130
+ cursor: pointer;
131
+ font-size: 11px;
132
+ letter-spacing: 0.02em;
133
+ text-transform: uppercase;
134
+ line-height: 1;
135
+ }
136
+ .dc-annot-ctx-mode-btn[aria-pressed="true"] {
137
+ background: color-mix(in oklab, var(--maude-hud-accent, #d63b1f) 14%, transparent);
138
+ color: var(--maude-hud-accent, #d63b1f);
139
+ font-weight: 600;
140
+ }
141
+ .dc-annot-ctx-mode-btn:not([aria-pressed="true"]):hover {
142
+ background: rgba(0,0,0,0.04);
143
+ }
144
+ /* Trailing overflow Delete — quiet by default, expressive on hover.
145
+ Keyboard Backspace remains the primary delete affordance. */
146
+ .dc-annot-ctx-overflow {
147
+ margin-left: auto;
148
+ }
97
149
  `.trim();
98
150
 
99
151
  function ensureToolbarStyles(): void {
@@ -122,6 +174,8 @@ function unionRect(rects: DOMRect[]): { x: number; y: number; w: number; h: numb
122
174
  return { x: xMin, y: yMin, w: xMax - xMin, h: yMax - yMin };
123
175
  }
124
176
 
177
+ type SwatchMode = 'stroke' | 'fill';
178
+
125
179
  export function AnnotationContextToolbar() {
126
180
  ensureToolbarStyles();
127
181
  const annotSel = useAnnotationSelectionOptional();
@@ -129,6 +183,10 @@ export function AnnotationContextToolbar() {
129
183
  const ref = useRef<HTMLDivElement | null>(null);
130
184
  const rafRef = useRef<number | null>(null);
131
185
  const [, force] = useState({});
186
+ // T30 / G_S1 — collapsed Stroke|Fill toggle state. Defaults to 'stroke';
187
+ // auto-reverts to 'stroke' whenever caps.fill is false so the toggle
188
+ // can't get stranded on a hidden mode after the selection changes type.
189
+ const [swatchMode, setSwatchMode] = useState<SwatchMode>('stroke');
132
190
 
133
191
  const selectedStrokes = useMemo<Stroke[]>(() => {
134
192
  if (!annotSel || !store) return [];
@@ -278,6 +336,15 @@ export function AnnotationContextToolbar() {
278
336
  ? uniformValue(selectedStrokes.map((s) => (s.tool === 'text' ? s.fontSize : undefined)))
279
337
  : undefined;
280
338
 
339
+ // T30 / G_S1 — when caps.fill is false we never enter fill mode. The
340
+ // useEffect below could call setSwatchMode('stroke') but reading the
341
+ // effective mode inline avoids an extra render cycle.
342
+ const effectiveMode: SwatchMode = caps.fill ? swatchMode : 'stroke';
343
+ const showPalette = effectiveMode === 'stroke' ? PALETTE : FILL_PALETTE;
344
+ const onSwatchClick =
345
+ effectiveMode === 'stroke' ? (c: string) => setColor(c) : (c: string) => setFill(c);
346
+ const activeValue = effectiveMode === 'stroke' ? uniqColor : (uniqFill ?? null);
347
+
281
348
  return (
282
349
  <div
283
350
  ref={ref}
@@ -286,52 +353,60 @@ export function AnnotationContextToolbar() {
286
353
  aria-label="Annotation properties"
287
354
  style={{ display: 'flex', top: -9999, left: -9999 }}
288
355
  >
289
- {PALETTE.map((c) => (
356
+ {caps.fill ? (
357
+ <>
358
+ <div className="dc-annot-ctx-mode" role="radiogroup" aria-label="Swatch target">
359
+ <button
360
+ type="button"
361
+ className="dc-annot-ctx-mode-btn"
362
+ aria-pressed={effectiveMode === 'stroke'}
363
+ onClick={() => setSwatchMode('stroke')}
364
+ >
365
+ Stroke
366
+ </button>
367
+ <button
368
+ type="button"
369
+ className="dc-annot-ctx-mode-btn"
370
+ aria-pressed={effectiveMode === 'fill'}
371
+ onClick={() => setSwatchMode('fill')}
372
+ >
373
+ Fill
374
+ </button>
375
+ </div>
376
+ <div className="dc-annot-ctx-sep" />
377
+ </>
378
+ ) : null}
379
+ {effectiveMode === 'fill' ? (
380
+ <button
381
+ type="button"
382
+ className="dc-annot-ctx-sw dc-annot-ctx-fill--none"
383
+ aria-label="No fill"
384
+ aria-pressed={uniqFill == null}
385
+ title="No fill"
386
+ onClick={() => setFill(null)}
387
+ />
388
+ ) : null}
389
+ {showPalette.map((c) => (
290
390
  <button
291
391
  key={c}
292
392
  type="button"
293
393
  className="dc-annot-ctx-sw"
294
- aria-label={`Color ${c}`}
295
- aria-pressed={uniqColor === c}
296
- title={`Color ${c}`}
394
+ aria-label={`${effectiveMode === 'stroke' ? 'Color' : 'Fill'} ${c}`}
395
+ aria-pressed={activeValue === c}
396
+ title={`${effectiveMode === 'stroke' ? 'Color' : 'Fill'} ${c}`}
297
397
  style={{ background: c }}
298
- onClick={() => setColor(c)}
398
+ onClick={() => onSwatchClick(c)}
299
399
  />
300
400
  ))}
301
- {caps.fill ? (
302
- <>
303
- <div className="dc-annot-ctx-sep" />
304
- <button
305
- type="button"
306
- className="dc-annot-ctx-sw dc-annot-ctx-fill--none"
307
- aria-label="No fill"
308
- aria-pressed={uniqFill == null}
309
- title="No fill"
310
- onClick={() => setFill(null)}
311
- />
312
- {FILL_PALETTE.map((c) => (
313
- <button
314
- key={c}
315
- type="button"
316
- className="dc-annot-ctx-sw"
317
- aria-label={`Fill ${c}`}
318
- aria-pressed={uniqFill === c}
319
- title={`Fill ${c}`}
320
- style={{ background: c }}
321
- onClick={() => setFill(c)}
322
- />
323
- ))}
324
- </>
325
- ) : null}
326
- {caps.thickness ? (
401
+ {caps.thickness && effectiveMode === 'stroke' ? (
327
402
  <>
328
403
  <div className="dc-annot-ctx-sep" />
329
404
  <button
330
405
  type="button"
331
406
  className="dc-annot-ctx-btn"
332
- aria-pressed={uniqThickness === 2}
333
- title="Thin (2px)"
334
- onClick={() => setThickness(2)}
407
+ aria-pressed={uniqThickness === 3}
408
+ title="Thin (3px)"
409
+ onClick={() => setThickness(3)}
335
410
  >
336
411
  Thin
337
412
  </button>
@@ -378,10 +453,9 @@ export function AnnotationContextToolbar() {
378
453
  </button>
379
454
  </>
380
455
  ) : null}
381
- <div className="dc-annot-ctx-sep" />
382
456
  <button
383
457
  type="button"
384
- className="dc-annot-ctx-btn dc-annot-ctx-btn--danger"
458
+ className="dc-annot-ctx-btn dc-annot-ctx-btn--danger dc-annot-ctx-overflow"
385
459
  title="Delete (Backspace)"
386
460
  aria-label="Delete selected annotations"
387
461
  onClick={remove}