@ai-matrx/rich-editor 0.4.1 → 0.4.2

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.2
4
+ ### A short toolbar keeps what people reach for (2026-10-08)
5
+
6
+ - `FormatButtons` folds by priority, not position: Bold, Italic, Text style, Bulleted list, Checklist and Link stay in view longest; history, inserts and the rest fold into More first. Display order never changes; dividers sit only between visible groups. The text-style menu is narrower (88px). Live: notes beside the chat panel showed only Undo, Redo, Text style and More.
7
+
8
+ Consumer action: none.
9
+
3
10
  ## 0.4.1
4
11
  ### Edit in place: Write, Split, Source, Preview (2026-10-08)
5
12
 
@@ -54,15 +54,41 @@ const FORMAT_GROUPS = [
54
54
  ];
55
55
  const FORMAT_BUTTONS = FORMAT_GROUPS.flat();
56
56
  const ESSENTIAL_COMMANDS = ["bold", "italic", "bulletList", "taskList", "link"];
57
+ const KEEP = {
58
+ bold: 20,
59
+ italic: 19,
60
+ style: 18,
61
+ bulletList: 17,
62
+ taskList: 16,
63
+ link: 15,
64
+ orderedList: 14,
65
+ undo: 13,
66
+ redo: 12,
67
+ strike: 11,
68
+ code: 10,
69
+ quote: 9,
70
+ codeBlock: 8,
71
+ table: 7,
72
+ horizontalRule: 6
73
+ };
74
+ const keepOf = (slot) => slot.kind === "button" ? KEEP[slot.spec.command] ?? 0 : slot.kind === "style" ? KEEP.style : 0;
57
75
  function slotsOf(variant) {
58
76
  if (variant === "essential") {
59
77
  return [{ kind: "style" }, ...ESSENTIAL_COMMANDS.map((command) => ({ kind: "button", spec: FORMAT_BUTTONS.find((b) => b.command === command) }))];
60
78
  }
61
79
  const out = [];
62
80
  FORMAT_GROUPS.forEach((group, index) => {
63
- if (index > 0) out.push({ kind: "divider" });
64
- out.push(...group.map((b) => ({ kind: "button", spec: b })));
65
- if (index === 0) out.push({ kind: "divider" }, { kind: "style" });
81
+ const g = index === 0 ? 0 : index + 1;
82
+ out.push(...group.map((b) => ({ kind: "button", spec: b, group: g })));
83
+ if (index === 0) out.push({ kind: "style", group: 1 });
84
+ });
85
+ return out;
86
+ }
87
+ function withDividers(slots) {
88
+ const out = [];
89
+ slots.forEach((slot, i) => {
90
+ if (i > 0 && slot.group !== void 0 && slot.group !== slots[i - 1].group) out.push({ kind: "divider" });
91
+ out.push(slot);
66
92
  });
67
93
  return out;
68
94
  }
@@ -123,27 +149,23 @@ function FormatButtons({ resolve, disabled = false, className, size = "sm", vari
123
149
  resolve()?.run(command);
124
150
  };
125
151
  const button = size === "xs" ? 26 : 30;
126
- const styleWidth = variant === "essential" ? size === "xs" ? 40 : 44 : 102;
152
+ const styleWidth = variant === "essential" ? size === "xs" ? 40 : 44 : 90;
127
153
  const widthOf = (slot) => slot.kind === "button" ? button : slot.kind === "style" ? styleWidth : 11;
128
154
  const all = slotsOf(variant);
129
- let shown = all;
155
+ let kept = all;
130
156
  let folded = variant === "essential" ? slotsOf("full").filter((s) => s.kind === "button" && !ESSENTIAL_COMMANDS.includes(s.spec.command)) : [];
131
- if (width > 0) {
132
- const total = all.reduce((sum, s) => sum + widthOf(s), 0) + (folded.length ? button : 0);
133
- if (total > width + 4) {
134
- const budget = width - button;
135
- let used = 0;
136
- let count = 0;
137
- for (const slot of all) {
138
- if (used + widthOf(slot) > budget) break;
139
- used += widthOf(slot);
140
- count += 1;
141
- }
142
- shown = all.slice(0, count);
143
- folded = [...all.slice(count), ...folded];
157
+ const rowWidth = (slots, more) => withDividers(slots).reduce((sum, s) => sum + widthOf(s), 0) + (more ? button : 0);
158
+ if (width > 0 && rowWidth(kept, folded.length > 0) > width + 4) {
159
+ const byKeep = [...all].sort((x, y) => keepOf(x) - keepOf(y));
160
+ const dropped = /* @__PURE__ */ new Set();
161
+ for (const slot of byKeep) {
162
+ if (rowWidth(all.filter((s) => !dropped.has(s)), true) <= width + 4) break;
163
+ dropped.add(slot);
144
164
  }
165
+ kept = all.filter((s) => !dropped.has(s));
166
+ folded = [...all.filter((s) => dropped.has(s)), ...folded];
145
167
  }
146
- while (shown.length && shown[shown.length - 1].kind === "divider") shown = shown.slice(0, -1);
168
+ const shown = withDividers(kept);
147
169
  const foldedButtons = folded.filter((s) => s.kind === "button");
148
170
  const styleFolded = folded.some((s) => s.kind === "style");
149
171
  const iconClass = size === "xs" ? "h-3.5 w-3.5" : "h-4 w-4";
@@ -178,7 +200,7 @@ function FormatButtons({ resolve, disabled = false, className, size = "sm", vari
178
200
  className: cn(
179
201
  "inline-flex shrink-0 items-center gap-1 rounded-md px-1.5 text-xs font-medium text-muted-foreground hover:bg-accent hover:text-foreground",
180
202
  size === "xs" ? "h-6" : "h-7",
181
- variant === "full" && "w-[100px] justify-between"
203
+ variant === "full" && "w-[88px] justify-between"
182
204
  ),
183
205
  children: [
184
206
  variant === "essential" ? /* @__PURE__ */ jsx(StyleIcon, { className: iconClass }) : /* @__PURE__ */ jsx("span", { className: "truncate", children: BLOCK_SHORT[currentStyle.command] }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-matrx/rich-editor",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "The AI Matrx editor: Visual (Tiptap), Source (CodeMirror), Preview, the markdown formatting command layer, and edit-in-place — over @ai-matrx/rich-content. Consumers that only render never install it.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -90,13 +90,13 @@
90
90
  "@tiptap/suggestion": "^3.31.3",
91
91
  "github-slugger": "^2.0.0",
92
92
  "lucide-react": "^1.48.0",
93
- "@ai-matrx/agents": "latest",
94
- "@ai-matrx/alchemy": "latest",
95
93
  "@ai-matrx/content-ir": "latest",
94
+ "@ai-matrx/agents": "latest",
95
+ "@ai-matrx/design-system": "latest",
96
96
  "@ai-matrx/kit": "latest",
97
97
  "@ai-matrx/print": "latest",
98
- "@ai-matrx/design-system": "latest",
99
- "@ai-matrx/rich-content": "latest"
98
+ "@ai-matrx/rich-content": "latest",
99
+ "@ai-matrx/alchemy": "latest"
100
100
  },
101
101
  "peerDependencies": {
102
102
  "react": ">=19.0.0",