@12ui/design 0.2.73 → 0.2.75

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 (142) hide show
  1. package/SKILL.md +1 -1
  2. package/dist/cli-codex-readiness.d.ts +19 -6
  3. package/dist/cli-codex-readiness.d.ts.map +1 -1
  4. package/dist/cli-codex-readiness.js +36 -16
  5. package/dist/cli-codex-readiness.js.map +1 -1
  6. package/dist/cli-help/design.d.ts +9 -2
  7. package/dist/cli-help/design.d.ts.map +1 -1
  8. package/dist/cli-help/design.js +17 -2
  9. package/dist/cli-help/design.js.map +1 -1
  10. package/dist/cli-help/index.d.ts +9 -2
  11. package/dist/cli-help/index.d.ts.map +1 -1
  12. package/dist/cli-run.d.ts.map +1 -1
  13. package/dist/cli-run.js +6 -0
  14. package/dist/cli-run.js.map +1 -1
  15. package/dist/cli-usage.d.ts.map +1 -1
  16. package/dist/cli-usage.js +1 -0
  17. package/dist/cli-usage.js.map +1 -1
  18. package/dist/cli-workspace-command.js +1 -1
  19. package/dist/cli-workspace-command.js.map +1 -1
  20. package/dist/cli-workspace-draw.d.ts +23 -0
  21. package/dist/cli-workspace-draw.d.ts.map +1 -0
  22. package/dist/cli-workspace-draw.js +97 -0
  23. package/dist/cli-workspace-draw.js.map +1 -0
  24. package/dist/codex-binary.d.ts +20 -0
  25. package/dist/codex-binary.d.ts.map +1 -0
  26. package/dist/codex-binary.js +46 -0
  27. package/dist/codex-binary.js.map +1 -0
  28. package/dist/mcp-slate-command.d.ts.map +1 -1
  29. package/dist/mcp-slate-command.js +6 -1
  30. package/dist/mcp-slate-command.js.map +1 -1
  31. package/dist/mcp-slate-tool-defs.js +3 -3
  32. package/dist/mcp-slate-tool-defs.js.map +1 -1
  33. package/dist/mcp-slate-ui-copy.d.ts +30 -19
  34. package/dist/mcp-slate-ui-copy.d.ts.map +1 -1
  35. package/dist/mcp-slate-ui-copy.js +51 -23
  36. package/dist/mcp-slate-ui-copy.js.map +1 -1
  37. package/dist/mcp-slate-ui-script-dialog.d.ts +15 -14
  38. package/dist/mcp-slate-ui-script-dialog.d.ts.map +1 -1
  39. package/dist/mcp-slate-ui-script-dialog.js +61 -72
  40. package/dist/mcp-slate-ui-script-dialog.js.map +1 -1
  41. package/dist/mcp-slate-ui-script-inline.d.ts.map +1 -1
  42. package/dist/mcp-slate-ui-script-inline.js +9 -6
  43. package/dist/mcp-slate-ui-script-inline.js.map +1 -1
  44. package/dist/mcp-slate-ui-script-inspiration.d.ts +3 -2
  45. package/dist/mcp-slate-ui-script-inspiration.d.ts.map +1 -1
  46. package/dist/mcp-slate-ui-script-inspiration.js +29 -9
  47. package/dist/mcp-slate-ui-script-inspiration.js.map +1 -1
  48. package/dist/mcp-slate-ui-script-more.d.ts +16 -14
  49. package/dist/mcp-slate-ui-script-more.d.ts.map +1 -1
  50. package/dist/mcp-slate-ui-script-more.js +120 -56
  51. package/dist/mcp-slate-ui-script-more.js.map +1 -1
  52. package/dist/mcp-slate-ui-script-remote.d.ts +2 -2
  53. package/dist/mcp-slate-ui-script-remote.js +2 -2
  54. package/dist/mcp-slate-ui-script-scribble.js +1 -1
  55. package/dist/mcp-slate-ui-script-stage.d.ts +3 -2
  56. package/dist/mcp-slate-ui-script-stage.d.ts.map +1 -1
  57. package/dist/mcp-slate-ui-script-stage.js +7 -8
  58. package/dist/mcp-slate-ui-script-stage.js.map +1 -1
  59. package/dist/mcp-slate-ui-script-state.js +3 -3
  60. package/dist/mcp-slate-ui-script.d.ts +1 -2
  61. package/dist/mcp-slate-ui-script.d.ts.map +1 -1
  62. package/dist/mcp-slate-ui-script.js +6 -4
  63. package/dist/mcp-slate-ui-script.js.map +1 -1
  64. package/dist/mcp-slate-ui-styles-dialog.d.ts +12 -9
  65. package/dist/mcp-slate-ui-styles-dialog.d.ts.map +1 -1
  66. package/dist/mcp-slate-ui-styles-dialog.js +48 -26
  67. package/dist/mcp-slate-ui-styles-dialog.js.map +1 -1
  68. package/dist/mcp-slate-ui-styles-stage.d.ts +15 -8
  69. package/dist/mcp-slate-ui-styles-stage.d.ts.map +1 -1
  70. package/dist/mcp-slate-ui-styles-stage.js +32 -18
  71. package/dist/mcp-slate-ui-styles-stage.js.map +1 -1
  72. package/dist/mcp-slate-ui-styles.d.ts +5 -0
  73. package/dist/mcp-slate-ui-styles.d.ts.map +1 -1
  74. package/dist/mcp-slate-ui-styles.js +21 -6
  75. package/dist/mcp-slate-ui-styles.js.map +1 -1
  76. package/dist/mcp-slate-ui.d.ts.map +1 -1
  77. package/dist/mcp-slate-ui.js +4 -3
  78. package/dist/mcp-slate-ui.js.map +1 -1
  79. package/dist/slate-actions.d.ts +7 -2
  80. package/dist/slate-actions.d.ts.map +1 -1
  81. package/dist/slate-actions.js +14 -8
  82. package/dist/slate-actions.js.map +1 -1
  83. package/dist/slate-handoff-options.d.ts +1 -1
  84. package/dist/slate-handoff-options.d.ts.map +1 -1
  85. package/dist/slate-handoff-options.js +8 -18
  86. package/dist/slate-handoff-options.js.map +1 -1
  87. package/dist/slate-image-executor.js +1 -1
  88. package/dist/slate-image-executor.js.map +1 -1
  89. package/dist/slate-inspiration.d.ts +1 -1
  90. package/dist/slate-inspiration.js +1 -1
  91. package/dist/slate-local-image.d.ts +3 -6
  92. package/dist/slate-local-image.d.ts.map +1 -1
  93. package/dist/slate-local-image.js +2 -18
  94. package/dist/slate-local-image.js.map +1 -1
  95. package/dist/slate-view-contract.d.ts +2 -3
  96. package/dist/slate-view-contract.d.ts.map +1 -1
  97. package/dist/slate-workspace-parse.d.ts.map +1 -1
  98. package/dist/slate-workspace-parse.js +6 -1
  99. package/dist/slate-workspace-parse.js.map +1 -1
  100. package/dist/workspace-draw-client.d.ts +69 -0
  101. package/dist/workspace-draw-client.d.ts.map +1 -0
  102. package/dist/workspace-draw-client.js +193 -0
  103. package/dist/workspace-draw-client.js.map +1 -0
  104. package/dist/workspace-draw-codex.d.ts +49 -0
  105. package/dist/workspace-draw-codex.d.ts.map +1 -0
  106. package/dist/workspace-draw-codex.js +89 -0
  107. package/dist/workspace-draw-codex.js.map +1 -0
  108. package/dist/workspace-draw-engine.d.ts +39 -0
  109. package/dist/workspace-draw-engine.d.ts.map +1 -0
  110. package/dist/workspace-draw-engine.js +72 -0
  111. package/dist/workspace-draw-engine.js.map +1 -0
  112. package/dist/workspace-draw-messages.d.ts +45 -0
  113. package/dist/workspace-draw-messages.d.ts.map +1 -0
  114. package/dist/workspace-draw-messages.js +48 -0
  115. package/dist/workspace-draw-messages.js.map +1 -0
  116. package/dist/workspace-draw-run.d.ts +43 -0
  117. package/dist/workspace-draw-run.d.ts.map +1 -0
  118. package/dist/workspace-draw-run.js +328 -0
  119. package/dist/workspace-draw-run.js.map +1 -0
  120. package/dist/workspace-draw-store.d.ts +23 -0
  121. package/dist/workspace-draw-store.d.ts.map +1 -0
  122. package/dist/workspace-draw-store.js +65 -0
  123. package/dist/workspace-draw-store.js.map +1 -0
  124. package/dist/workspace-draw-types.d.ts +121 -0
  125. package/dist/workspace-draw-types.d.ts.map +1 -0
  126. package/dist/workspace-draw-types.js +21 -0
  127. package/dist/workspace-draw-types.js.map +1 -0
  128. package/open-design.json +2 -2
  129. package/package.json +1 -1
  130. package/runtime/codex-conversion/src/codex/home.mjs +43 -14
  131. package/runtime/codex-conversion/src/images/native-files.mjs +20 -0
  132. package/runtime/codex-conversion/src/images/native-invoke.mjs +5 -2
  133. package/runtime/codex-conversion/src/images/native-records.mjs +75 -3
  134. package/runtime/codex-conversion/src/images/native.mjs +7 -4
  135. package/dist/mcp-slate-ui-script-thumbtools.d.ts +0 -23
  136. package/dist/mcp-slate-ui-script-thumbtools.d.ts.map +0 -1
  137. package/dist/mcp-slate-ui-script-thumbtools.js +0 -103
  138. package/dist/mcp-slate-ui-script-thumbtools.js.map +0 -1
  139. package/dist/mcp-slate-ui-styles-thumbtools.d.ts +0 -10
  140. package/dist/mcp-slate-ui-styles-thumbtools.d.ts.map +0 -1
  141. package/dist/mcp-slate-ui-styles-thumbtools.js +0 -25
  142. package/dist/mcp-slate-ui-styles-thumbtools.js.map +0 -1
@@ -1,24 +1,25 @@
1
1
  /**
2
- * The four dialogs of the workspace: Design (new options or more like this,
3
- * an optional steer note, and the inspiration selected in its tab), Edit (an
4
- * instruction and a scribble over the image), Branch (what to build) and
5
- * Convert (which format, with only the options that format has). Each is opened
6
- * by its button, confirmed by one verb (Generate, Apply, Send, Send) and closed
7
- * by Cancel or Escape; Select has no dialog.
2
+ * The three dialogs of the workspace: Edit (a drawing over the image, an
3
+ * optional instruction, or both), Branch (an optional description of what to
4
+ * build) and Convert (which format, with only the options that format has).
5
+ * Each is opened by its button, confirmed by one verb (Apply, Send, Send) and
6
+ * closed by Cancel or Escape; Select has no dialog, and Generate more is a
7
+ * panel, not a dialog (mcp-slate-ui-script-more.ts).
8
8
  *
9
- * Common rules: a title, fields, an error line (role alert, empty by default),
10
- * then Cancel and the primary. The primary keeps its label and disables while a
11
- * call is in flight; on success the dialog closes at once. One id is minted
12
- * when the dialog opens (the op id of Design and Edit, the hand-off id of
13
- * Branch and Convert), so a double click sends one request.
9
+ * Common rules: a title, fields, one line that says what will happen, an error
10
+ * line (role alert, empty by default), then Cancel and the primary. The
11
+ * primary keeps its label and disables while a call is in flight; on success
12
+ * the dialog closes at once. One id is minted when the dialog opens (the op id
13
+ * of Edit, the hand-off id of Branch and Convert), so a double click sends one
14
+ * request.
14
15
  *
15
- * Design and Edit start work through the run tool, which returns as soon as
16
- * the work is committed; Branch and Convert hand off to the agent through
17
- * sendHandoff. Nothing here shows or asks for money.
16
+ * Edit starts work through the run tool, which returns as soon as the work is
17
+ * committed; Branch and Convert hand off to the agent through sendHandoff.
18
+ * Nothing here shows or asks for money.
18
19
  */
19
20
  export const SLATE_UI_DIALOG = String.raw `
20
- var DIALOG_TITLES = { design: COPY.design, edit: COPY.edit, branch: COPY.branch, convert: COPY.convert };
21
- var DIALOG_VERBS = { design: COPY.generate, edit: COPY.apply, branch: COPY.send, convert: COPY.send };
21
+ var DIALOG_TITLES = { edit: COPY.edit, branch: COPY.branch, convert: COPY.convert };
22
+ var DIALOG_VERBS = { edit: COPY.apply, branch: COPY.send, convert: COPY.send };
22
23
 
23
24
  function field(labelText, control, id) {
24
25
  var wrap = el("div", "field");
@@ -34,11 +35,14 @@ export const SLATE_UI_DIALOG = String.raw `
34
35
  wrap.appendChild(control);
35
36
  return wrap;
36
37
  }
37
- function textarea(id, rows, placeholder, max, onInput) {
38
+ // One muted line under a control: what it does, or what will happen.
39
+ function helpLine(text) { return el("p", "help", text); }
40
+ function textarea(id, rows, placeholder, max, onInput, ariaLabel) {
38
41
  var area = el("textarea");
39
42
  area.id = id;
40
43
  area.setAttribute("rows", String(rows));
41
44
  area.placeholder = placeholder;
45
+ area.setAttribute("aria-label", ariaLabel);
42
46
  area.setAttribute("maxlength", String(max));
43
47
  area.addEventListener("input", function () { onInput(area.value); updateDialogUi(); });
44
48
  return area;
@@ -69,12 +73,12 @@ export const SLATE_UI_DIALOG = String.raw `
69
73
  function openDialog(kind, opener) {
70
74
  if (state.dialog || !state.view) return;
71
75
  var v = selectedVersion();
72
- if (kind !== "design" && !v) return;
76
+ if (!v) return;
73
77
  if (kind === "edit" && !v.editable) return;
74
78
  state.dialog = {
75
- kind: kind, id: uuid4(), versionId: v ? v.versionId : null, opener: opener,
76
- mode: "new", note: "", prompt: "", explanation: "",
77
- format: CONVERT.choices[0].value, clean: "enhance", quality: "standard", width: "", layouts: "standard",
79
+ kind: kind, id: uuid4(), versionId: v.versionId, opener: opener,
80
+ prompt: "", explanation: "",
81
+ format: CONVERT.choices[0].value, quality: "standard", width: "", layouts: "standard",
78
82
  strokes: [], current: null, committing: false, error: "", els: {}
79
83
  };
80
84
  mountDialog();
@@ -88,17 +92,11 @@ export const SLATE_UI_DIALOG = String.raw `
88
92
  }
89
93
 
90
94
  // ---- what each dialog would send ----
91
- // The one round action: the Design dialog and the Generate more panel both build it here. Only the panel sets a count.
92
- function roundAction(request) {
93
- var action = { kind: "round", mode: request.mode };
94
- var note = (request.note || "").trim();
95
- if (note) action.note = note;
96
- if (request.count !== undefined) action.count = request.count;
97
- if (request.mode === "like") action.fromVersionId = request.fromVersionId;
98
- return action;
99
- }
95
+ // The instruction is optional when the edit carries marks: a drawing alone is sent with no words and the server infers them.
100
96
  function editAction(d) {
101
- var action = { kind: "edit", versionId: d.versionId, prompt: d.prompt.trim() };
97
+ var action = { kind: "edit", versionId: d.versionId };
98
+ var words = d.prompt.trim();
99
+ if (words) action.prompt = words;
102
100
  if (d.strokes.length > 0) action.strokes = d.strokes.map(function (s) { return s.map(function (p) { return [p[0], p[1]]; }); });
103
101
  return action;
104
102
  }
@@ -125,7 +123,7 @@ export const SLATE_UI_DIALOG = String.raw `
125
123
  var choice = convertChoice(d);
126
124
  // The hosted server has one engine and two outputs; nothing else is a choice.
127
125
  if (TARGET === "remote") return { engine: "local", output: choice.output };
128
- if (choice.engine === "local") return { engine: "local", output: choice.output, cleanAssets: d.clean };
126
+ if (choice.engine === "local") return { engine: "local", output: choice.output };
129
127
  var options = { engine: "service", output: choice.output, model: d.quality };
130
128
  var width = widthOf(d);
131
129
  if (width.value !== null) options.width = width.value;
@@ -134,9 +132,9 @@ export const SLATE_UI_DIALOG = String.raw `
134
132
  }
135
133
  function dialogReady(d) {
136
134
  var v = ver(d.versionId);
137
- if (d.kind === "design") return localImage().ready && (d.mode === "new" || pickable(v));
138
- if (d.kind === "edit") return localImage().ready && !!v && v.editable && !!d.prompt.trim();
139
- if (d.kind === "branch") return !!d.explanation.trim();
135
+ // An edit needs a drawing, words or both; Branch has no required field.
136
+ if (d.kind === "edit") return localImage().ready && !!v && v.editable && (d.strokes.length > 0 || !!d.prompt.trim());
137
+ if (d.kind === "branch") return true;
140
138
  return !!convertChoice(d) && widthOf(d).ok;
141
139
  }
142
140
 
@@ -150,10 +148,6 @@ export const SLATE_UI_DIALOG = String.raw `
150
148
  return sc;
151
149
  });
152
150
  }
153
- // The one way a round starts: the selection is committed first, so the round uses the inspiration the person sees.
154
- function startRound(opId, request) {
155
- return whenSelectionSettled().then(function () { return runAction(roundAction(request), opId); });
156
- }
157
151
  function commitDialog() {
158
152
  var d = state.dialog;
159
153
  if (!d || d.committing || !dialogReady(d)) return;
@@ -164,13 +158,13 @@ export const SLATE_UI_DIALOG = String.raw `
164
158
  var work;
165
159
  if (d.kind === "branch") work = sendHandoff("branch", version, d.id, { explanation: d.explanation.trim() });
166
160
  else if (d.kind === "convert") work = sendHandoff("convert", version, d.id, convertOptions(d));
167
- else if (d.kind === "edit") {
161
+ else {
168
162
  var edited = cand(version.candidateId);
169
163
  work = editActionFor(d, version).then(function (action) { return runAction(action, d.id); }).then(function () {
170
164
  // The new version is shown the moment it lands.
171
165
  state.awaitEdit = { candidateId: version.candidateId, count: edited ? edited.versionIds.length : 0 };
172
166
  });
173
- } else work = startRound(d.id, { mode: d.mode, note: d.note, fromVersionId: d.versionId });
167
+ }
174
168
  work.then(function () {
175
169
  closeDialog();
176
170
  }, function (err) {
@@ -182,26 +176,6 @@ export const SLATE_UI_DIALOG = String.raw `
182
176
  }
183
177
 
184
178
  // ---- the dialog's elements ----
185
- function designBody(d, box) {
186
- var v = ver(d.versionId);
187
- var modes = [{ value: "new", label: COPY.newOptions }, { value: "like", label: COPY.moreLikeThis, disabled: !pickable(v) }];
188
- box.appendChild(radioRow("mode", modes, d.mode, function (value) { d.mode = value; }));
189
- box.appendChild(field(COPY.noteLabel, textarea("dialognote", 2, COPY.notePlaceholder, 600, function (value) { d.note = value; }), "dialognote"));
190
- var line = el("div", "refline");
191
- var chosen = currentSelected().slice(0, MAX_SELECTED);
192
- if (chosen.length > 0) {
193
- var thumbs = el("span", "refthumbs");
194
- chosen.forEach(function (id) {
195
- var img = el("img", "refmini empty");
196
- img.alt = "";
197
- thumbs.appendChild(img);
198
- bindReference(img, id, "thumb");
199
- });
200
- line.appendChild(thumbs);
201
- }
202
- line.appendChild(el("span", "", chosen.length > 0 ? COPY.usingSelected : COPY.usingFresh));
203
- box.appendChild(line);
204
- }
205
179
  function editBody(d, box) {
206
180
  var v = ver(d.versionId);
207
181
  var wrap = el("div", "imgwrap");
@@ -215,16 +189,21 @@ export const SLATE_UI_DIALOG = String.raw `
215
189
  if (cached) img.src = cached;
216
190
  scribbleAttach(wrap, d);
217
191
  box.appendChild(wrap);
192
+ // Under the image: the hint that it can be drawn on, and the two drawing controls.
218
193
  var tools = el("div", "dialogtools");
194
+ tools.appendChild(el("p", "hint", COPY.scribbleHint));
219
195
  d.els.undo = button(COPY.undo, "", function () { scribbleUndo(d); });
220
196
  d.els.clear = button(COPY.clear, "", function () { scribbleClear(d); });
221
197
  tools.appendChild(d.els.undo);
222
198
  tools.appendChild(d.els.clear);
223
199
  box.appendChild(tools);
224
- box.appendChild(field(COPY.editLabel, textarea("dialogedit", 3, COPY.editPlaceholder, 6000, function (value) { d.prompt = value; }), "dialogedit"));
200
+ box.appendChild(textarea("dialogedit", 3, COPY.editPlaceholder, 6000, function (value) { d.prompt = value; }, COPY.editAria));
201
+ d.els.help = helpLine("");
202
+ box.appendChild(d.els.help);
225
203
  }
226
204
  function branchBody(d, box) {
227
- box.appendChild(field(COPY.branchLabel, textarea("dialogbranch", 4, COPY.branchPlaceholder, 2000, function (value) { d.explanation = value; }), "dialogbranch"));
205
+ box.appendChild(textarea("dialogbranch", 4, COPY.branchPlaceholder, 2000, function (value) { d.explanation = value; }, COPY.branchAria));
206
+ box.appendChild(helpLine(COPY.branchHelp));
228
207
  }
229
208
  function convertBody(d, box) {
230
209
  var select = el("select");
@@ -240,11 +219,14 @@ export const SLATE_UI_DIALOG = String.raw `
240
219
  if (service.childNodes.length > 0) select.appendChild(service);
241
220
  select.addEventListener("change", function () { d.format = select.value; updateDialogUi(); });
242
221
  box.appendChild(field(COPY.convertLabel, select, "dialogformat"));
243
- // The hosted server builds from the image and has nothing else to ask: no assets, quality, width or layouts.
222
+ // One line that follows the choice: what the person gets.
223
+ d.els.formatHelp = helpLine("");
224
+ box.appendChild(d.els.formatHelp);
225
+ // The hosted server builds from the image and has nothing else to ask: no quality, width or layouts.
244
226
  if (TARGET === "remote") return;
245
- // Only the options the chosen format has are shown; the rest are hidden, not disabled.
246
- d.els.local = group(COPY.cleanLabel, radioRow("clean", [{ value: "crop", label: COPY.crop }, { value: "enhance", label: COPY.enhance }], d.clean, function (value) { d.clean = value; }));
227
+ // Only the options the chosen format has are shown; the rest are hidden, not disabled. Each says what it does in one line.
247
228
  d.els.quality = group(COPY.qualityLabel, radioRow("quality", [{ value: "fast", label: COPY.fast }, { value: "standard", label: COPY.standard }, { value: "pro", label: COPY.pro }], d.quality, function (value) { d.quality = value; }));
229
+ d.els.quality.appendChild(helpLine(COPY.qualityHelp));
248
230
  var width = el("input");
249
231
  width.type = "number";
250
232
  width.id = "dialogwidth";
@@ -254,8 +236,10 @@ export const SLATE_UI_DIALOG = String.raw `
254
236
  width.setAttribute("inputmode", "numeric");
255
237
  width.addEventListener("input", function () { d.width = width.value; updateDialogUi(); });
256
238
  d.els.width = field(COPY.widthLabel, width, "dialogwidth");
239
+ d.els.width.appendChild(helpLine(COPY.widthHelp));
257
240
  d.els.layouts = group(COPY.layoutsLabel, radioRow("layouts", [{ value: "standard", label: COPY.standard }, { value: "pro", label: COPY.pro }], d.layouts, function (value) { d.layouts = value; }));
258
- [d.els.local, d.els.quality, d.els.width, d.els.layouts].forEach(function (node) { box.appendChild(node); });
241
+ d.els.layouts.appendChild(helpLine(COPY.layoutsHelp));
242
+ [d.els.quality, d.els.width, d.els.layouts].forEach(function (node) { box.appendChild(node); });
259
243
  }
260
244
 
261
245
  function mountDialog() {
@@ -269,8 +253,7 @@ export const SLATE_UI_DIALOG = String.raw `
269
253
  box.setAttribute("aria-modal", "true");
270
254
  box.setAttribute("aria-label", DIALOG_TITLES[d.kind]);
271
255
  box.appendChild(el("h2", "", DIALOG_TITLES[d.kind]));
272
- if (d.kind === "design") designBody(d, box);
273
- else if (d.kind === "edit") editBody(d, box);
256
+ if (d.kind === "edit") editBody(d, box);
274
257
  else if (d.kind === "branch") branchBody(d, box);
275
258
  else convertBody(d, box);
276
259
  d.els.alert = el("p", "alert");
@@ -296,15 +279,21 @@ export const SLATE_UI_DIALOG = String.raw `
296
279
  d.els.primary.disabled = d.committing || !dialogReady(d);
297
280
  // A dialog that cannot run on this Mac says why, in the same line an error would use.
298
281
  var local = localImage();
299
- var blockedByLocal = (d.kind === "design" || d.kind === "edit") && !local.ready;
282
+ var blockedByLocal = d.kind === "edit" && !local.ready;
300
283
  d.els.alert.textContent = d.error || (blockedByLocal && local.reason ? local.reason : "");
301
284
  d.els.alert.classList.toggle("hidden", !d.els.alert.textContent);
302
285
  if (d.els.undo) d.els.undo.disabled = d.strokes.length === 0 || d.committing;
303
286
  if (d.els.clear) d.els.clear.disabled = d.strokes.length === 0 || d.committing;
304
- if (d.kind === "convert" && TARGET !== "remote") {
287
+ if (d.els.help) {
288
+ var marksOnly = d.strokes.length > 0 && !d.prompt.trim();
289
+ d.els.help.textContent = marksOnly ? COPY.editHelpMarks : tpl(COPY.editHelp, { label: (ver(d.versionId) || {}).label || "" });
290
+ }
291
+ if (d.kind === "convert") {
305
292
  var choice = convertChoice(d);
293
+ d.els.formatHelp.textContent = (choice && CONVERT.descriptions[choice.value]) || "";
294
+ }
295
+ if (d.kind === "convert" && TARGET !== "remote") {
306
296
  var isLocal = !!choice && choice.engine === "local";
307
- d.els.local.classList.toggle("hidden", !isLocal);
308
297
  d.els.quality.classList.toggle("hidden", isLocal);
309
298
  d.els.width.classList.toggle("hidden", isLocal);
310
299
  d.els.layouts.classList.toggle("hidden", isLocal || choice.output !== "html");
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-slate-ui-script-dialog.js","sourceRoot":"","sources":["../src/mcp-slate-ui-script-dialog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwTxC,CAAC"}
1
+ {"version":3,"file":"mcp-slate-ui-script-dialog.js","sourceRoot":"","sources":["../src/mcp-slate-ui-script-dialog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4SxC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-slate-ui-script-inline.d.ts","sourceRoot":"","sources":["../src/mcp-slate-ui-script-inline.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,QAmN3B,CAAC"}
1
+ {"version":3,"file":"mcp-slate-ui-script-inline.d.ts","sourceRoot":"","sources":["../src/mcp-slate-ui-script-inline.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,QAsN3B,CAAC"}
@@ -15,7 +15,6 @@ export const SLATE_UI_INLINE = String.raw `
15
15
  if (prev && prev.runDir !== view.runDir) {
16
16
  state.sel = { candidateId: null, versionId: null, followLatest: true };
17
17
  state.dialog = null;
18
- state.wantEdit = null;
19
18
  resetMore();
20
19
  state.insp.local = null;
21
20
  state.awaitEdit = null;
@@ -53,8 +52,6 @@ export const SLATE_UI_INLINE = String.raw `
53
52
  $("app").classList.toggle("hidden", full);
54
53
  $("stage").classList.toggle("hidden", !full);
55
54
  if (full) renderStage(); else renderInline();
56
- // Edit asked for from a thumbnail in the card: the workspace is showing now, so its dialog opens.
57
- if (full) openWantedEdit();
58
55
  // A dialog that is open follows the view: what this Mac can do now, for one.
59
56
  if (state.dialog) updateDialogUi();
60
57
  syncMore();
@@ -86,6 +83,9 @@ export const SLATE_UI_INLINE = String.raw `
86
83
  wrap.textContent = "";
87
84
  wrap.classList.remove("note");
88
85
  wrap.style.removeProperty("--ar");
86
+ // The workspace's action row is as wide as the picture, so Select sits under its right edge: the shared parent carries the ratio too.
87
+ var shared = wrap.parentElement;
88
+ if (shared) shared.style.removeProperty("--ar");
89
89
  if (!c) return;
90
90
  if (!v || v.fileState !== "ok") {
91
91
  wrap.classList.add("note");
@@ -94,6 +94,7 @@ export const SLATE_UI_INLINE = String.raw `
94
94
  return;
95
95
  }
96
96
  wrap.style.setProperty("--ar", String(v.width / v.height));
97
+ if (shared) shared.style.setProperty("--ar", String(v.width / v.height));
97
98
  var img = el("img", "heroimg empty");
98
99
  img.alt = COPY.versionPrefix + v.label;
99
100
  img.setAttribute("draggable", "false");
@@ -157,13 +158,15 @@ export const SLATE_UI_INLINE = String.raw `
157
158
  var sel = selectedVersion();
158
159
  setIfChanged($("hero"), heroSignature(c, sel), function (node) { heroInto(node, c, sel); });
159
160
  var strip = $("strip");
160
- // Where keyboard focus sits among the strip's buttons (a thumbnail, its two controls, the tile), so a rebuild can put it back.
161
+ // Where keyboard focus sits among the strip's buttons (the thumbnails), so a rebuild can put it back.
161
162
  var focusAt = strip.contains(document.activeElement) ? Array.prototype.indexOf.call(strip.querySelectorAll("button"), document.activeElement) : -1;
162
163
  var options = inlineCandidates();
163
164
  var rebuilt = setIfChanged(strip, JSON.stringify([state.sel.candidateId, options.map(thumbSignature)]), function (node) {
164
- options.forEach(function (x) { node.appendChild(thumbCell(x, "thumbbtn")); });
165
- node.appendChild(moreTile());
165
+ options.forEach(function (x) { node.appendChild(thumbButton(x, "thumbbtn")); });
166
166
  });
167
+ // The Generate more tile is pinned beside the strip, outside its scroll, so it is never pushed out of view; built once.
168
+ var wrap = $("stripwrap");
169
+ if (!wrap.querySelector(".moretile")) wrap.appendChild(moreTile());
167
170
  // Choosing a thumbnail rebuilds the strip: keep keyboard focus at the same place in it.
168
171
  var stripButtons = strip.querySelectorAll("button");
169
172
  if (rebuilt && focusAt >= 0 && stripButtons[focusAt]) stripButtons[focusAt].focus();
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-slate-ui-script-inline.js","sourceRoot":"","sources":["../src/mcp-slate-ui-script-inline.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmNxC,CAAC"}
1
+ {"version":3,"file":"mcp-slate-ui-script-inline.js","sourceRoot":"","sources":["../src/mcp-slate-ui-script-inline.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsNxC,CAAC"}
@@ -5,8 +5,9 @@
5
5
  * produced its options. Every reference is a toggle. The selection lives in
6
6
  * the view (`inspiration.selected`, at most eight, in click order) and is
7
7
  * written whole through the inspiration tool, one write in flight at a time,
8
- * last click wins locally; the next Design round reads it at commit. Nothing
9
- * in this tab starts work.
8
+ * last click wins locally; the next round reads it at commit. Nothing in this
9
+ * tab starts work. While a search runs the newest-search slot is skeleton
10
+ * tiles; a search with no results says so.
10
11
  */
11
12
  export declare const SLATE_UI_INSPIRATION: string;
12
13
  //# sourceMappingURL=mcp-slate-ui-script-inspiration.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-slate-ui-script-inspiration.d.ts","sourceRoot":"","sources":["../src/mcp-slate-ui-script-inspiration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,QA4MhC,CAAC"}
1
+ {"version":3,"file":"mcp-slate-ui-script-inspiration.d.ts","sourceRoot":"","sources":["../src/mcp-slate-ui-script-inspiration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,QA+NhC,CAAC"}
@@ -5,8 +5,9 @@
5
5
  * produced its options. Every reference is a toggle. The selection lives in
6
6
  * the view (`inspiration.selected`, at most eight, in click order) and is
7
7
  * written whole through the inspiration tool, one write in flight at a time,
8
- * last click wins locally; the next Design round reads it at commit. Nothing
9
- * in this tab starts work.
8
+ * last click wins locally; the next round reads it at commit. Nothing in this
9
+ * tab starts work. While a search runs the newest-search slot is skeleton
10
+ * tiles; a search with no results says so.
10
11
  */
11
12
  export const SLATE_UI_INSPIRATION = String.raw `
12
13
  var MAX_SELECTED = 8;
@@ -44,10 +45,11 @@ export const SLATE_UI_INSPIRATION = String.raw `
44
45
  return state.insp.local || (state.view && state.view.inspiration ? state.view.inspiration.selected : []);
45
46
  }
46
47
  function refMeta(id) { return (state.view.references && state.view.references[id]) || null; }
47
- function refName(id) {
48
+ function refDescription(id) {
48
49
  var m = refMeta(id);
49
- return COPY.referencePrefix + String((m && m.description) || id).slice(0, 40);
50
+ return String((m && m.description) || id).slice(0, 40);
50
51
  }
52
+ function refName(id) { return COPY.referencePrefix + refDescription(id); }
51
53
  function newestSearch() {
52
54
  var searches = (state.view.inspiration && state.view.inspiration.searches) || [];
53
55
  var best = null;
@@ -105,7 +107,7 @@ export const SLATE_UI_INSPIRATION = String.raw `
105
107
  waiting.forEach(function (resolve) { resolve(); });
106
108
  });
107
109
  }
108
- // Resolves when no selection write is in flight, so a Design round commits the selection the person sees.
110
+ // Resolves when no selection write is in flight, so a round commits the selection the person sees.
109
111
  function whenSelectionSettled() {
110
112
  if (!state.insp.writing) return Promise.resolve();
111
113
  return new Promise(function (resolve) { state.insp.waiters.push(resolve); });
@@ -119,11 +121,15 @@ export const SLATE_UI_INSPIRATION = String.raw `
119
121
  var q = state.query.trim();
120
122
  if (!q || state.insp.searching || !state.view) return;
121
123
  state.insp.searching = true;
122
- setInspStatus("", "");
124
+ state.insp.noMatch = "";
125
+ setInspStatus(COPY.searching, "");
123
126
  renderAll();
124
127
  callTool(TOOLS.inspire, { runDir: state.view.runDir, query: q }).then(function (result) {
125
128
  var sc = result.structuredContent || {};
126
129
  if (sc.view) applyView(sc.view, true);
130
+ setInspStatus("", "");
131
+ var found = sc.search || newestSearch();
132
+ if (found && found.referenceIds.length === 0) state.insp.noMatch = found.searchId;
127
133
  }, function (err) {
128
134
  setInspStatus(err.code === "rate_limited" && err.retryAfterSeconds !== undefined ? tpl(COPY.tryAgain, { n: err.retryAfterSeconds }) : tpl(COPY.searchFailed, { message: errText(err) }), "err");
129
135
  }).then(function () { state.insp.searching = false; renderAll(); });
@@ -134,7 +140,8 @@ export const SLATE_UI_INSPIRATION = String.raw `
134
140
  var b = button("", "refbtn");
135
141
  b.setAttribute("aria-label", refName(id));
136
142
  b.setAttribute("data-ref", id);
137
- var img = el("img", "thumb empty");
143
+ // The picture's own skeleton shows until it lands, so a tile that has arrived never flashes a grey square.
144
+ var img = el("img", "thumb empty shimmer");
138
145
  img.alt = "";
139
146
  b.appendChild(img);
140
147
  bindReference(img, id, "thumb");
@@ -156,11 +163,23 @@ export const SLATE_UI_INSPIRATION = String.raw `
156
163
  sec.appendChild(grid);
157
164
  return sec;
158
165
  }
166
+ // The same tiles as the results, at the same size, where the results will land.
167
+ var SKELETON_TILES = 12;
168
+ function skeletonSection() {
169
+ var sec = el("section", "refsec");
170
+ var grid = el("div", "refgrid");
171
+ for (var i = 0; i < SKELETON_TILES; i++) grid.appendChild(el("div", "skeleton shimmer"));
172
+ sec.appendChild(grid);
173
+ return sec;
174
+ }
159
175
  function buildResults(box) {
160
176
  var v = state.view;
161
177
  var any = false;
162
178
  var search = newestSearch();
163
- if (search && search.referenceIds.length > 0) { box.appendChild(refSection("", "", search.referenceIds)); any = true; }
179
+ // The newest search's slot: skeleton tiles while it runs, else its references, or the line that it found none.
180
+ if (state.insp.searching) { box.appendChild(skeletonSection()); any = true; }
181
+ else if (search && search.referenceIds.length === 0 && state.insp.noMatch === search.searchId) { box.appendChild(el("div", "placeholder", COPY.inspirationNoMatches)); any = true; }
182
+ else if (search && search.referenceIds.length > 0) { box.appendChild(refSection("", "", search.referenceIds)); any = true; }
164
183
  v.rounds.slice().sort(function (a, b) { return b.index - a.index; }).forEach(function (round) {
165
184
  if (round.referenceIds.length === 0) return;
166
185
  box.appendChild(refSection(COPY.roundPrefix + round.index, roundTitle(round), round.referenceIds));
@@ -206,7 +225,8 @@ export const SLATE_UI_INSPIRATION = String.raw `
206
225
  syncSearchButton(pane);
207
226
  var v = state.view;
208
227
  var search = newestSearch();
209
- var sig = JSON.stringify([search && [search.searchId, search.referenceIds], v.rounds.map(function (r) { return [r.index, r.kind, r.fromVersionId, r.referenceIds]; }), v.references]);
228
+ pane.__results.setAttribute("aria-busy", state.insp.searching ? "true" : "false");
229
+ var sig = JSON.stringify([state.insp.searching, state.insp.noMatch, search && [search.searchId, search.referenceIds], v.rounds.map(function (r) { return [r.index, r.kind, r.fromVersionId, r.referenceIds]; }), v.references]);
210
230
  setIfChanged(pane.__results, sig, buildResults);
211
231
  var chosen = currentSelected();
212
232
  var buttons = pane.__results.querySelectorAll(".refbtn");
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-slate-ui-script-inspiration.js","sourceRoot":"","sources":["../src/mcp-slate-ui-script-inspiration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4M7C,CAAC"}
1
+ {"version":3,"file":"mcp-slate-ui-script-inspiration.js","sourceRoot":"","sources":["../src/mcp-slate-ui-script-inspiration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+N7C,CAAC"}
@@ -1,22 +1,24 @@
1
1
  /**
2
2
  * Generate more: the last tile of the thumbnails (the card's strip, the
3
3
  * workspace's selection) and the panel it opens directly below them. The tile
4
- * is an empty, very light thumbnail-sized box with a plus and no words; the
5
- * panel is the heading, an optional note, how many (a segmented control) and
6
- * Generate or Cancel. Clicking the tile again, Cancel or Escape collapses it.
4
+ * is a dashed, thumbnail-sized box with a plus and the words Generate more, pinned outside any scroll so it is always in view; the
5
+ * panel is the only way to start a round, and it says what it will do:
7
6
  *
8
- * Generate starts a round through startRound, the very function the Design
9
- * dialog uses for New options, so the run tool, the mode, the note and the
10
- * selected inspiration are the same; the panel only adds the count.
7
+ * - a heading and one helper line that follows the state (fresh references,
8
+ * the selected inspiration, or close to the shown design);
9
+ * - a switch, with a picture of the design at its left, "Based on <code>", off by default: off draws new options, on
10
+ * draws options close to the design that is shown (mode "like" from the
11
+ * shown version at the moment of Generate);
12
+ * - the selected inspiration as small chips, each with a remove button that is
13
+ * the same selection write as the Inspiration tab's toggle (adding is done
14
+ * in that tab);
15
+ * - an optional note, how many (1, 2, 4, 8 or 12, default 4) and Cancel and
16
+ * Generate.
11
17
  *
12
- * The same panel serves a thumbnail's plus (mcp-slate-ui-script-thumbtools.ts):
13
- * "More like E2", with a tiny picture of that design, starts a round in mode
14
- * "like" from that design's latest version. The tile opens the plain panel
15
- * (mode "new"); opening either replaces the other, so neither carries the
16
- * other's reference. While a
17
- * round runs (or the request is in flight) the tile is off; the new round's
18
- * pending options are already in the thumbnails, because the returned view
19
- * carries them.
18
+ * Clicking the tile again, Cancel or Escape collapses it. While a round runs
19
+ * (or the request is in flight) the tile is off; the new round's pending
20
+ * options are already in the thumbnails, because the returned view carries
21
+ * them.
20
22
  *
21
23
  * In the card the panel takes its room from the large image rather than
22
24
  * growing the frame. The host grows the frame downward and does not scroll
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-slate-ui-script-more.d.ts","sourceRoot":"","sources":["../src/mcp-slate-ui-script-more.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,aAAa,QAmMzB,CAAC"}
1
+ {"version":3,"file":"mcp-slate-ui-script-more.d.ts","sourceRoot":"","sources":["../src/mcp-slate-ui-script-more.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,aAAa,QAiQzB,CAAC"}