@growth-labs/cms 0.5.19 → 0.5.20

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/README.md CHANGED
@@ -177,6 +177,15 @@ envelope means "no structured body, render the markdown".
177
177
  re-serializes byte-identically), and the `citation` annotation
178
178
  (`markDef { _type: 'citation', href }`, markdown form `[[label]](href)`).
179
179
  Editor node specs live in `src/ui/editor/blocks.ts`.
180
+ - Editor UX: a `/` slash menu at line start inserts any block
181
+ (`src/ui/editor/slash-menu.ts` — the item list + filter are pure and
182
+ tested), a drag handle reorders blocks
183
+ (`@tiptap/extension-drag-handle`; its collaboration peer set is a hard
184
+ static-import requirement at 3.24.0 and ships in the admin bundle only),
185
+ and toolbar buttons cover callout / pull quote / citation.
186
+ - Site tooling imports the serializer quartet from
187
+ `@growth-labs/cms/content` (backfills, HTML-diff gates, importers) —
188
+ never from deep `ui/editor` paths.
180
189
 
181
190
  ### How to add a new block type
182
191
 
@@ -0,0 +1,4 @@
1
+ export { PORTABLE_TEXT_VERSION, type PortableTextEnvelope, type PortableTextObject, parsePortableTextEnvelope, wrapPortableText, } from '../schema/portable-text.js';
2
+ export { docToPortableText, portableTextToDoc } from '../ui/editor/portable-text.js';
3
+ export { docToMarkdown, markdownToDoc } from '../ui/editor/serialize.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/content/index.ts"],"names":[],"mappings":"AAOA,OAAO,EACN,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,yBAAyB,EACzB,gBAAgB,GAChB,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAA;AACpF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA"}
@@ -0,0 +1,10 @@
1
+ // src/content/index.ts
2
+ // Site-side content tooling surface (`@growth-labs/cms/content`): the pure
3
+ // serializer quartet plus the envelope contract, for backfills, gates, and
4
+ // import tooling that must convert between markdown, Tiptap JSON, and
5
+ // Portable Text OUTSIDE the editor. No Editor/EditorView/DOM anywhere on
6
+ // this import path.
7
+ export { PORTABLE_TEXT_VERSION, parsePortableTextEnvelope, wrapPortableText, } from '../schema/portable-text.js';
8
+ export { docToPortableText, portableTextToDoc } from '../ui/editor/portable-text.js';
9
+ export { docToMarkdown, markdownToDoc } from '../ui/editor/serialize.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/content/index.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,2EAA2E;AAC3E,2EAA2E;AAC3E,sEAAsE;AACtE,yEAAyE;AACzE,oBAAoB;AAEpB,OAAO,EACN,qBAAqB,EAGrB,yBAAyB,EACzB,gBAAgB,GAChB,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAA;AACpF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA"}
@@ -2774,21 +2774,6 @@ export declare const InsightsIngestPayloadSchema: z.ZodEffects<z.ZodObject<{
2774
2774
  beat: "defense" | "intelligence" | "diplomacy" | "analysis" | null;
2775
2775
  }>, "many">;
2776
2776
  }, "strip", z.ZodTypeAny, {
2777
- meta: {
2778
- status: "failed" | "running" | "completed" | "partial";
2779
- counts: {
2780
- demand_count: number;
2781
- opportunity_count: number;
2782
- };
2783
- site_id: string;
2784
- run_date: string;
2785
- event_id: string;
2786
- run_id: string;
2787
- run_attempt: number;
2788
- generated_at: number;
2789
- content_hash: string;
2790
- error?: string | null | undefined;
2791
- };
2792
2777
  rows: {
2793
2778
  site_id: string;
2794
2779
  run_date: string;
@@ -2913,7 +2898,6 @@ export declare const InsightsIngestPayloadSchema: z.ZodEffects<z.ZodObject<{
2913
2898
  intent_key: string;
2914
2899
  beat: "defense" | "intelligence" | "diplomacy" | "analysis" | null;
2915
2900
  }[];
2916
- }, {
2917
2901
  meta: {
2918
2902
  status: "failed" | "running" | "completed" | "partial";
2919
2903
  counts: {
@@ -2929,6 +2913,7 @@ export declare const InsightsIngestPayloadSchema: z.ZodEffects<z.ZodObject<{
2929
2913
  content_hash: string;
2930
2914
  error?: string | null | undefined;
2931
2915
  };
2916
+ }, {
2932
2917
  rows: {
2933
2918
  site_id: string;
2934
2919
  run_date: string;
@@ -3053,7 +3038,6 @@ export declare const InsightsIngestPayloadSchema: z.ZodEffects<z.ZodObject<{
3053
3038
  intent_key: string;
3054
3039
  beat: "defense" | "intelligence" | "diplomacy" | "analysis" | null;
3055
3040
  }[];
3056
- }>, {
3057
3041
  meta: {
3058
3042
  status: "failed" | "running" | "completed" | "partial";
3059
3043
  counts: {
@@ -3069,6 +3053,7 @@ export declare const InsightsIngestPayloadSchema: z.ZodEffects<z.ZodObject<{
3069
3053
  content_hash: string;
3070
3054
  error?: string | null | undefined;
3071
3055
  };
3056
+ }>, {
3072
3057
  rows: {
3073
3058
  site_id: string;
3074
3059
  run_date: string;
@@ -3193,7 +3178,6 @@ export declare const InsightsIngestPayloadSchema: z.ZodEffects<z.ZodObject<{
3193
3178
  intent_key: string;
3194
3179
  beat: "defense" | "intelligence" | "diplomacy" | "analysis" | null;
3195
3180
  }[];
3196
- }, {
3197
3181
  meta: {
3198
3182
  status: "failed" | "running" | "completed" | "partial";
3199
3183
  counts: {
@@ -3209,6 +3193,7 @@ export declare const InsightsIngestPayloadSchema: z.ZodEffects<z.ZodObject<{
3209
3193
  content_hash: string;
3210
3194
  error?: string | null | undefined;
3211
3195
  };
3196
+ }, {
3212
3197
  rows: {
3213
3198
  site_id: string;
3214
3199
  run_date: string;
@@ -3333,6 +3318,21 @@ export declare const InsightsIngestPayloadSchema: z.ZodEffects<z.ZodObject<{
3333
3318
  intent_key: string;
3334
3319
  beat: "defense" | "intelligence" | "diplomacy" | "analysis" | null;
3335
3320
  }[];
3321
+ meta: {
3322
+ status: "failed" | "running" | "completed" | "partial";
3323
+ counts: {
3324
+ demand_count: number;
3325
+ opportunity_count: number;
3326
+ };
3327
+ site_id: string;
3328
+ run_date: string;
3329
+ event_id: string;
3330
+ run_id: string;
3331
+ run_attempt: number;
3332
+ generated_at: number;
3333
+ content_hash: string;
3334
+ error?: string | null | undefined;
3335
+ };
3336
3336
  }>;
3337
3337
  export type InsightsIngestPayload = z.infer<typeof InsightsIngestPayloadSchema>;
3338
3338
  export type InsightsIngestMeta = z.infer<typeof InsightsIngestMetaSchema>;
@@ -1 +1 @@
1
- {"version":3,"file":"Rte.d.ts","sourceRoot":"","sources":["../../../src/ui/editor/Rte.tsx"],"names":[],"mappings":"AAsGA,MAAM,WAAW,QAAQ;IACxB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B;;;;OAIG;IACH,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;IACpD,wFAAwF;IACxF,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACxD,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB;AAMD,wBAAgB,GAAG,CAAC,EACnB,KAAK,EACL,YAAmB,EACnB,QAAQ,EACR,aAAa,EACb,WAAW,EAAE,YAAY,EACzB,QAAgB,GAChB,EAAE,QAAQ,+BA+IV"}
1
+ {"version":3,"file":"Rte.d.ts","sourceRoot":"","sources":["../../../src/ui/editor/Rte.tsx"],"names":[],"mappings":"AA4GA,MAAM,WAAW,QAAQ;IACxB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B;;;;OAIG;IACH,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;IACpD,wFAAwF;IACxF,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACxD,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB;AAMD,wBAAgB,GAAG,CAAC,EACnB,KAAK,EACL,YAAmB,EACnB,QAAQ,EACR,aAAa,EACb,WAAW,EAAE,YAAY,EACzB,QAAgB,GAChB,EAAE,QAAQ,+BA+IV"}
@@ -50,7 +50,10 @@ const RTE_TOOLS = [
50
50
  { cmd: 'bullet', label: 'Bullet list', icon: 'rows' },
51
51
  { cmd: 'ordered', label: 'Ordered list', icon: 'rows' },
52
52
  { cmd: 'link', label: 'Link', icon: 'link' },
53
+ { cmd: 'citation', label: 'Citation', icon: 'globe' },
53
54
  { cmd: 'image', label: 'Image', icon: 'image' },
55
+ { cmd: 'callout', label: 'Callout', icon: 'flag' },
56
+ { cmd: 'pullquote', label: 'Pull quote', icon: 'star' },
54
57
  { cmd: 'table', label: 'Insert table', icon: 'grid' },
55
58
  ];
56
59
  /** Shown only while the selection sits inside a table. */
@@ -222,6 +225,19 @@ function ToolButton({ tool, editor, onImageUploadClick, disabled = false, }) {
222
225
  }
223
226
  break;
224
227
  }
228
+ case 'callout':
229
+ chain.toggleWrap('callout', { tone: 'note' }).run();
230
+ break;
231
+ case 'pullquote':
232
+ chain.toggleWrap('pullQuote').run();
233
+ break;
234
+ case 'citation': {
235
+ const href = window.prompt('Citation URL');
236
+ if (href) {
237
+ chain.toggleMark('citation', { href }).run();
238
+ }
239
+ break;
240
+ }
225
241
  case 'table':
226
242
  chain.insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run();
227
243
  break;
@@ -267,6 +283,12 @@ function ToolButton({ tool, editor, onImageUploadClick, disabled = false, }) {
267
283
  return editor.isActive('bulletList');
268
284
  case 'ordered':
269
285
  return editor.isActive('orderedList');
286
+ case 'callout':
287
+ return editor.isActive('callout');
288
+ case 'pullquote':
289
+ return editor.isActive('pullQuote');
290
+ case 'citation':
291
+ return editor.isActive('citation');
270
292
  case 'table':
271
293
  return editor.isActive('table');
272
294
  default:
@@ -1 +1 @@
1
- {"version":3,"file":"Rte.js","sourceRoot":"","sources":["../../../src/ui/editor/Rte.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Rte.js","sourceRoot":"","sources":["../../../src/ui/editor/Rte.tsx"],"names":[],"mappings":";AAAA,2DAA2D;AAC3D,EAAE;AACF,wEAAwE;AACxE,6EAA6E;AAC7E,uEAAuE;AACvE,EAAE;AACF,yEAAyE;AACzE,uEAAuE;AACvE,0EAA0E;AAC1E,4EAA4E;AAC5E,wEAAwE;AACxE,kEAAkE;AAClE,EAAE;AACF,gEAAgE;AAChE,EAAE;AACF,4EAA4E;AAC5E,sFAAsF;AAEtF,OAAO,EAAE,MAAM,EAAoB,MAAM,cAAc,CAAA;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACnD,OAAO,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAC3F,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACzE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAE7D,6EAA6E;AAC7E,SAAS,aAAa,CAAC,EAAU,EAAE,YAAuC;IACzE,MAAM,QAAQ,GAAG,yBAAyB,CAAC,YAAY,IAAI,IAAI,CAAC,CAAA;IAChE,IAAI,QAAQ,EAAE,CAAC;QACd,IAAI,CAAC;YACJ,OAAO,iBAAiB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC3C,CAAC;QAAC,MAAM,CAAC;YACR,yEAAyE;QAC1E,CAAC;IACF,CAAC;IACD,OAAO,aAAa,CAAC,EAAE,CAAC,CAAA;AACzB,CAAC;AAED,SAAS,wBAAwB,CAAC,GAAgB;IACjD,OAAO,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAChE,CAAC;AAmCD,MAAM,SAAS,GAAc;IAC5B,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;IAC5C,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE;IAChD,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE;IACvD,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE;IACtD,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE;IAC9C,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE;IAC9C,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE;IACvD,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE;IACrD,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE;IACvD,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;IAC5C,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE;IACrD,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE;IAC/C,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;IAClD,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE;IACvD,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE;CACrD,CAAA;AAED,0DAA0D;AAC1D,MAAM,WAAW,GAAc;IAC9B,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE;IAC5D,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,SAAS,EAAE;IAClE,EAAE,GAAG,EAAE,gBAAgB,EAAE,KAAK,EAAE,mBAAmB,EAAE,IAAI,EAAE,QAAQ,EAAE;IACrE,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,EAAE;IACtD,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,GAAG,EAAE;IACzD,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,EAAE;CAC5D,CAAA;AA4BD,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,MAAM,UAAU,GAAG,CAAC,EACnB,KAAK,EACL,YAAY,GAAG,IAAI,EACnB,QAAQ,EACR,aAAa,EACb,WAAW,EAAE,YAAY,EACzB,QAAQ,GAAG,KAAK,GACN;IACV,MAAM,QAAQ,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAA;IAC7C,MAAM,SAAS,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAA;IAC7C,MAAM,aAAa,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAA;IACpD,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC3D,4EAA4E;IAC5E,MAAM,CAAC,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IAE/B,yEAAyE;IACzE,2EAA2E;IAC3E,2EAA2E;IAC3E,eAAe;IACf,MAAM,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IACrC,MAAM,sBAAsB,GAAG,MAAM,CAAC,YAAY,CAAC,CAAA;IACnD,MAAM,mBAAmB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IACzC,MAAM,0BAA0B,GAAG,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC,CAAA;IAC7D,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,CAAC,CAAA;IAC5C,eAAe,CAAC,OAAO,GAAG,YAAY,CAAA;IACtC,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAA;IACpC,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAA;IAE9B,SAAS,CAAC,GAAG,EAAE;QACd,0CAA0C;QAC1C,IAAI,OAAO,QAAQ,KAAK,WAAW;YAAE,OAAM;QAC3C,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAA;QAC3B,IAAI,CAAC,EAAE;YAAE,OAAM;QAEf,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC;YACzB,OAAO,EAAE,EAAE;YACX,UAAU,EAAE,mBAAmB,EAAE;YACjC,OAAO,EAAE,aAAa,CAAC,eAAe,CAAC,OAAO,EAAE,sBAAsB,CAAC,OAAO,CAAC;YAC/E,QAAQ,EAAE,CAAC,QAAQ;YACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;gBACrB,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,CAAA;gBACxB,MAAM,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;gBAC9B,MAAM,EAAE,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAA;gBACzC,kEAAkE;gBAClE,mEAAmE;gBACnE,IAAI,EAAE,KAAK,mBAAmB,CAAC,OAAO,IAAI,EAAE,KAAK,0BAA0B,CAAC,OAAO,EAAE,CAAC;oBACrF,OAAM;gBACP,CAAC;gBACD,mBAAmB,CAAC,OAAO,GAAG,EAAE,CAAA;gBAChC,0BAA0B,CAAC,OAAO,GAAG,EAAE,CAAA;gBACvC,WAAW,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;YAC5B,CAAC;YACD,iBAAiB;gBAChB,2DAA2D;gBAC3D,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YACtB,CAAC;YACD,aAAa;gBACZ,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YACtB,CAAC;SACD,CAAC,CAAA;QAEF,SAAS,CAAC,OAAO,GAAG,MAAM,CAAA;QAE1B,OAAO,GAAG,EAAE;YACX,MAAM,CAAC,OAAO,EAAE,CAAA;YAChB,SAAS,CAAC,OAAO,GAAG,IAAI,CAAA;QACzB,CAAC,CAAA;IACF,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,SAAS,CAAC,GAAG,EAAE;QACd,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAA;QAChC,IAAI,CAAC,MAAM;YAAE,OAAM;QACnB,IAAI,KAAK,KAAK,mBAAmB,CAAC,OAAO;YAAE,OAAM;QACjD,mBAAmB,CAAC,OAAO,GAAG,KAAK,CAAA;QACnC,sEAAsE;QACtE,yEAAyE;QACzE,qEAAqE;QACrE,oEAAoE;QACpE,MAAM,oBAAoB,GAAG,eAAe,CAAC,OAAO,IAAI,EAAE,CAAA;QAC1D,MAAM,iBAAiB,GACtB,oBAAoB,KAAK,EAAE,IAAI,oBAAoB,KAAK,0BAA0B,CAAC,OAAO;YACzF,CAAC,CAAC,oBAAoB;YACtB,CAAC,CAAC,IAAI,CAAA;QACR,IAAI,iBAAiB,KAAK,IAAI;YAAE,0BAA0B,CAAC,OAAO,GAAG,iBAAiB,CAAA;QACtF,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAA;IACpE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IAEX,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAA;IAEhC,KAAK,UAAU,qBAAqB,CAAC,KAA0C;QAC9E,MAAM,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAA;QAC3C,KAAK,CAAC,aAAa,CAAC,KAAK,GAAG,EAAE,CAAA;QAC9B,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,CAAC,aAAa;YAAE,OAAM;QACzD,iBAAiB,CAAC,IAAI,CAAC,CAAA;QACvB,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;YAC1C,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAA;QACxE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;gBACnC,MAAM,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAA;YACzE,CAAC;QACF,CAAC;gBAAS,CAAC;YACV,iBAAiB,CAAC,KAAK,CAAC,CAAA;QACzB,CAAC;IACF,CAAC;IAED,OAAO,CACN,eAAK,KAAK,EAAE,OAAO,aAEjB,CAAC,QAAQ,IAAI,CACb,eAAK,KAAK,EAAE,YAAY,aACtB,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACxB,KAAC,UAAU,IAEV,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,kBAAkB,EACjB,IAAI,CAAC,GAAG,KAAK,OAAO,IAAI,aAAa;4BACpC,CAAC,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,EAAE;4BACtC,CAAC,CAAC,SAAS,EAEb,QAAQ,EAAE,IAAI,CAAC,GAAG,KAAK,OAAO,IAAI,cAAc,IAR3C,IAAI,CAAC,GAAG,CASZ,CACF,CAAC,EACD,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,CAC7B,8BACC,eAAM,KAAK,EAAE,cAAc,iBAAc,MAAM,GAAG,EACjD,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAC1B,KAAC,UAAU,IAAgB,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,IAApC,IAAI,CAAC,GAAG,CAAgC,CACzD,CAAC,IACA,CACH,EACA,aAAa,IAAI,CACjB,gBACC,GAAG,EAAE,aAAa,EAClB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,SAAS,EAChB,QAAQ,EAAE,qBAAqB,EAC/B,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,iBACd,MAAM,EAClB,QAAQ,EAAE,CAAC,CAAC,GACX,CACF,IACI,CACN,EAGD,cAAK,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,GAAI,IACrC,CACN,CAAA;AACF,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E,SAAS,UAAU,CAAC,EACnB,IAAI,EACJ,MAAM,EACN,kBAAkB,EAClB,QAAQ,GAAG,KAAK,GAMhB;IACA,SAAS,WAAW;QACnB,IAAI,QAAQ;YAAE,OAAM;QACpB,IAAI,IAAI,CAAC,GAAG,KAAK,OAAO,IAAI,kBAAkB,EAAE,CAAC;YAChD,kBAAkB,EAAE,CAAA;YACpB,OAAM;QACP,CAAC;QACD,IAAI,CAAC,MAAM;YAAE,OAAM;QACnB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAA;QAEpC,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC;YAClB,KAAK,MAAM;gBACV,KAAK,CAAC,UAAU,EAAE,CAAC,GAAG,EAAE,CAAA;gBACxB,MAAK;YACN,KAAK,QAAQ;gBACZ,KAAK,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,CAAA;gBAC1B,MAAK;YACN,KAAK,QAAQ;gBACZ,KAAK,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,CAAA;gBAC1B,MAAK;YACN,KAAK,MAAM;gBACV,KAAK,CAAC,UAAU,EAAE,CAAC,GAAG,EAAE,CAAA;gBACxB,MAAK;YACN,KAAK,IAAI;gBACR,KAAK,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAA;gBACvC,MAAK;YACN,KAAK,IAAI;gBACR,KAAK,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAA;gBACvC,MAAK;YACN,KAAK,OAAO;gBACX,KAAK,CAAC,gBAAgB,EAAE,CAAC,GAAG,EAAE,CAAA;gBAC9B,MAAK;YACN,KAAK,QAAQ;gBACZ,KAAK,CAAC,gBAAgB,EAAE,CAAC,GAAG,EAAE,CAAA;gBAC9B,MAAK;YACN,KAAK,SAAS;gBACb,KAAK,CAAC,iBAAiB,EAAE,CAAC,GAAG,EAAE,CAAA;gBAC/B,MAAK;YACN,KAAK,MAAM,CAAC,CAAC,CAAC;gBACb,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;gBACvC,IAAI,IAAI,EAAE,CAAC;oBACV,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,CAAA;gBAC9B,CAAC;gBACD,MAAK;YACN,CAAC;YACD,KAAK,OAAO,CAAC,CAAC,CAAC;gBACd,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAA;gBAC5C,IAAI,GAAG,EAAE,CAAC;oBACT,KAAK,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAA;gBAC9B,CAAC;gBACD,MAAK;YACN,CAAC;YACD,KAAK,SAAS;gBACb,KAAK,CAAC,UAAU,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE,CAAA;gBACnD,MAAK;YACN,KAAK,WAAW;gBACf,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,GAAG,EAAE,CAAA;gBACnC,MAAK;YACN,KAAK,UAAU,CAAC,CAAC,CAAC;gBACjB,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;gBAC1C,IAAI,IAAI,EAAE,CAAC;oBACV,KAAK,CAAC,UAAU,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,CAAA;gBAC7C,CAAC;gBACD,MAAK;YACN,CAAC;YACD,KAAK,OAAO;gBACX,KAAK,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,CAAA;gBAClE,MAAK;YACN,KAAK,aAAa;gBACjB,KAAK,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,CAAA;gBACzB,MAAK;YACN,KAAK,aAAa;gBACjB,KAAK,CAAC,cAAc,EAAE,CAAC,GAAG,EAAE,CAAA;gBAC5B,MAAK;YACN,KAAK,gBAAgB;gBACpB,KAAK,CAAC,eAAe,EAAE,CAAC,GAAG,EAAE,CAAA;gBAC7B,MAAK;YACN,KAAK,aAAa;gBACjB,KAAK,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,CAAA;gBACvB,MAAK;YACN,KAAK,aAAa;gBACjB,KAAK,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,CAAA;gBAC1B,MAAK;YACN,KAAK,aAAa;gBACjB,KAAK,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,CAAA;gBACzB,MAAK;QACP,CAAC;IACF,CAAC;IAED,SAAS,QAAQ;QAChB,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAA;QACzB,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC;YAClB,KAAK,MAAM;gBACV,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;YAC/B,KAAK,QAAQ;gBACZ,OAAO,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;YACjC,KAAK,QAAQ;gBACZ,OAAO,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;YACjC,KAAK,MAAM;gBACV,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;YAC/B,KAAK,IAAI;gBACR,OAAO,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;YAChD,KAAK,IAAI;gBACR,OAAO,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;YAChD,KAAK,OAAO;gBACX,OAAO,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAA;YACrC,KAAK,QAAQ;gBACZ,OAAO,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAA;YACrC,KAAK,SAAS;gBACb,OAAO,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAA;YACtC,KAAK,SAAS;gBACb,OAAO,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;YAClC,KAAK,WAAW;gBACf,OAAO,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;YACpC,KAAK,UAAU;gBACd,OAAO,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;YACnC,KAAK,OAAO;gBACX,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;YAChC;gBACC,OAAO,KAAK,CAAA;QACd,CAAC;IACF,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAA;IAEzB,OAAO,CACN,iBACC,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE;YAClB,oDAAoD;YACpD,CAAC,CAAC,cAAc,EAAE,CAAA;YAClB,WAAW,EAAE,CAAA;QACd,CAAC,EACD,KAAK,EAAE;YACN,OAAO,EAAE,aAAa;YACtB,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,QAAQ;YACxB,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,EAAE;YACV,OAAO,EAAE,CAAC;YACV,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,aAAa;YACzD,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,iBAAiB;YACnD,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,uBAAuB;YACzE,YAAY,EAAE,CAAC;YACf,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;YACzC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC3B,QAAQ,EAAE,EAAE;YACZ,UAAU,EAAE,GAAG;SACf,YAED,KAAC,IAAI,IAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,GAAI,GAC3B,CACT,CAAA;AACF,CAAC;AAED,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E,MAAM,OAAO,GAAwB;IACpC,MAAM,EAAE,+BAA+B;IACvC,YAAY,EAAE,CAAC;IACf,UAAU,EAAE,cAAc;IAC1B,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,MAAM;IACf,aAAa,EAAE,QAAQ;IACvB,SAAS,EAAE,GAAG;CACd,CAAA;AAED,MAAM,cAAc,GAAwB;IAC3C,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,EAAE;IACV,MAAM,EAAE,OAAO;IACf,SAAS,EAAE,QAAQ;IACnB,UAAU,EAAE,eAAe;CAC3B,CAAA;AAED,MAAM,YAAY,GAAwB;IACzC,OAAO,EAAE,MAAM;IACf,QAAQ,EAAE,MAAM;IAChB,GAAG,EAAE,CAAC;IACN,OAAO,EAAE,CAAC;IACV,YAAY,EAAE,yBAAyB;IACvC,UAAU,EAAE,gBAAgB;IAC5B,QAAQ,EAAE,QAAQ;IAClB,GAAG,EAAE,CAAC;IACN,MAAM,EAAE,CAAC;CACT,CAAA;AAED,MAAM,WAAW,GAAwB;IACxC,IAAI,EAAE,CAAC;IACP,OAAO,EAAE,WAAW;IACpB,SAAS,EAAE,MAAM;IACjB,UAAU,EAAE,cAAc;IAC1B,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE,IAAI;IAChB,KAAK,EAAE,YAAY;CACnB,CAAA"}
@@ -6,5 +6,5 @@
6
6
  * and interleaved underscores through link syntax (the recurring "hyperlinks
7
7
  * formatted incorrectly" incidents). With no underline extension, TipTap
8
8
  * silently drops underline styling on paste — Word documents come in clean. */
9
- export declare function createRteExtensions(): (import("@tiptap/core").Node<any, any> | import("@tiptap/core").Mark<any, any> | import("@tiptap/core").Extension<any, any> | import("@tiptap/core").Extension<import("@tiptap/starter-kit").StarterKitOptions, any> | import("@tiptap/core").Mark<import("@tiptap/extension-link").LinkOptions, any> | import("@tiptap/core").Node<import("@tiptap/extension-image").ImageOptions, any> | import("@tiptap/core").Extension<import("@tiptap/extension-table").TableKitOptions, any>)[];
9
+ export declare function createRteExtensions(): (import("@tiptap/core").Extension<any, any> | import("@tiptap/core").Node<any, any> | import("@tiptap/core").Mark<any, any> | import("@tiptap/core").Extension<import("@tiptap/starter-kit").StarterKitOptions, any> | import("@tiptap/core").Mark<import("@tiptap/extension-link").LinkOptions, any> | import("@tiptap/core").Node<import("@tiptap/extension-image").ImageOptions, any> | import("@tiptap/core").Extension<import("@tiptap/extension-table").TableKitOptions, any> | import("@tiptap/core").Extension<import("@tiptap/extension-drag-handle").DragHandleOptions, any>)[];
10
10
  //# sourceMappingURL=extensions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../../src/ui/editor/extensions.ts"],"names":[],"mappings":"AAQA;;;;;;;+EAO+E;AAC/E,wBAAgB,mBAAmB,2dAelC"}
1
+ {"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../../src/ui/editor/extensions.ts"],"names":[],"mappings":"AAiBA;;;;;;;+EAO+E;AAC/E,wBAAgB,mBAAmB,8jBAqBlC"}
@@ -1,10 +1,18 @@
1
+ import { DragHandle } from '@tiptap/extension-drag-handle';
1
2
  import Image from '@tiptap/extension-image';
2
3
  import Link from '@tiptap/extension-link';
3
4
  import { TableKit } from '@tiptap/extension-table';
4
5
  import StarterKit from '@tiptap/starter-kit';
5
6
  import { Callout, Citation, GeneratedFaq, PullQuote } from './blocks.js';
7
+ import { SlashMenu } from './slash-menu.js';
6
8
  import { TrimBoundaryMarks } from './trim-boundary-marks.js';
7
9
  import { TweetEmbed } from './tweet-embed.js';
10
+ function renderDragHandle() {
11
+ const handle = document.createElement('div');
12
+ handle.className = 'drag-handle';
13
+ handle.textContent = '⋮⋮';
14
+ return handle;
15
+ }
8
16
  /** The single extension set used by Masthead and its behavioral editor tests.
9
17
  *
10
18
  * Underline is deliberately ABSENT. It has no markdown form — the serializer
@@ -27,6 +35,12 @@ export function createRteExtensions() {
27
35
  PullQuote,
28
36
  GeneratedFaq,
29
37
  Citation,
38
+ SlashMenu,
39
+ // DragHandle constructs its handle element (render()) during plugin
40
+ // setup, not lazily — browser-only, unlike every other extension here.
41
+ ...(typeof document !== 'undefined'
42
+ ? [DragHandle.configure({ render: renderDragHandle })]
43
+ : []),
30
44
  ];
31
45
  }
32
46
  //# sourceMappingURL=extensions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"extensions.js","sourceRoot":"","sources":["../../../src/ui/editor/extensions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,yBAAyB,CAAA;AAC3C,OAAO,IAAI,MAAM,wBAAwB,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAClD,OAAO,UAAU,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C;;;;;;;+EAO+E;AAC/E,MAAM,UAAU,mBAAmB;IAClC,OAAO;QACN,UAAU,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QACvD,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;QACtC,iBAAiB;QACjB,KAAK;QACL,UAAU;QACV,2EAA2E;QAC3E,sEAAsE;QACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC;QAClD,OAAO;QACP,SAAS;QACT,YAAY;QACZ,QAAQ;KACR,CAAA;AACF,CAAC"}
1
+ {"version":3,"file":"extensions.js","sourceRoot":"","sources":["../../../src/ui/editor/extensions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAC1D,OAAO,KAAK,MAAM,yBAAyB,CAAA;AAC3C,OAAO,IAAI,MAAM,wBAAwB,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAClD,OAAO,UAAU,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,SAAS,gBAAgB;IACxB,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IAC5C,MAAM,CAAC,SAAS,GAAG,aAAa,CAAA;IAChC,MAAM,CAAC,WAAW,GAAG,IAAI,CAAA;IACzB,OAAO,MAAM,CAAA;AACd,CAAC;AAED;;;;;;;+EAO+E;AAC/E,MAAM,UAAU,mBAAmB;IAClC,OAAO;QACN,UAAU,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QACvD,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;QACtC,iBAAiB;QACjB,KAAK;QACL,UAAU;QACV,2EAA2E;QAC3E,sEAAsE;QACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC;QAClD,OAAO;QACP,SAAS;QACT,YAAY;QACZ,QAAQ;QACR,SAAS;QACT,oEAAoE;QACpE,uEAAuE;QACvE,GAAG,CAAC,OAAO,QAAQ,KAAK,WAAW;YAClC,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;YACtD,CAAC,CAAC,EAAE,CAAC;KACN,CAAA;AACF,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { type Editor, Extension, type Range } from '@tiptap/core';
2
+ export interface SlashMenuItem {
3
+ title: string;
4
+ hint: string;
5
+ /** Lowercase match terms beyond the title. */
6
+ keywords: string;
7
+ run: (editor: Editor, range: Range) => void;
8
+ }
9
+ export declare const SLASH_MENU_ITEMS: SlashMenuItem[];
10
+ /** Case-insensitive filter over titles + keywords; empty query returns all. */
11
+ export declare function filterSlashMenuItems(query: string): SlashMenuItem[];
12
+ /** `/` at the start of a line opens the block-insert menu. */
13
+ export declare const SlashMenu: Extension<any, any>;
14
+ //# sourceMappingURL=slash-menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slash-menu.d.ts","sourceRoot":"","sources":["../../../src/ui/editor/slash-menu.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,MAAM,EAAE,SAAS,EAAE,KAAK,KAAK,EAAE,MAAM,cAAc,CAAA;AAIjE,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAC3C;AAED,eAAO,MAAM,gBAAgB,EAAE,aAAa,EA+E3C,CAAA;AAED,+EAA+E;AAC/E,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,EAAE,CAOnE;AA6FD,8DAA8D;AAC9D,eAAO,MAAM,SAAS,qBAgBpB,CAAA"}
@@ -0,0 +1,200 @@
1
+ // src/ui/editor/slash-menu.ts
2
+ // `/` block-insert menu for the rich-text editor, built on @tiptap/suggestion.
3
+ // The item list + filter are pure and unit-tested; the dropdown itself is a
4
+ // vanilla-DOM renderer created only when the Suggestion plugin runs inside a
5
+ // live (browser) editor, so this module stays importable in Node.
6
+ import { Extension } from '@tiptap/core';
7
+ import { PluginKey } from '@tiptap/pm/state';
8
+ import Suggestion, {} from '@tiptap/suggestion';
9
+ export const SLASH_MENU_ITEMS = [
10
+ {
11
+ title: 'Heading 2',
12
+ hint: 'Section heading',
13
+ keywords: 'h2 title section',
14
+ run: (editor, range) => editor.chain().focus().deleteRange(range).setNode('heading', { level: 2 }).run(),
15
+ },
16
+ {
17
+ title: 'Heading 3',
18
+ hint: 'Sub-section heading',
19
+ keywords: 'h3 subtitle',
20
+ run: (editor, range) => editor.chain().focus().deleteRange(range).setNode('heading', { level: 3 }).run(),
21
+ },
22
+ {
23
+ title: 'Bullet list',
24
+ hint: 'Unordered list',
25
+ keywords: 'ul bullets',
26
+ run: (editor, range) => editor.chain().focus().deleteRange(range).toggleBulletList().run(),
27
+ },
28
+ {
29
+ title: 'Numbered list',
30
+ hint: 'Ordered list',
31
+ keywords: 'ol ordered numbers',
32
+ run: (editor, range) => editor.chain().focus().deleteRange(range).toggleOrderedList().run(),
33
+ },
34
+ {
35
+ title: 'Quote',
36
+ hint: 'Blockquote',
37
+ keywords: 'blockquote',
38
+ run: (editor, range) => editor.chain().focus().deleteRange(range).toggleBlockquote().run(),
39
+ },
40
+ {
41
+ title: 'Callout',
42
+ hint: 'Highlighted aside with a tone',
43
+ keywords: 'aside note warning tip alert',
44
+ run: (editor, range) => editor.chain().focus().deleteRange(range).toggleWrap('callout', { tone: 'note' }).run(),
45
+ },
46
+ {
47
+ title: 'Pull quote',
48
+ hint: 'Large excerpted quote',
49
+ keywords: 'pullquote excerpt',
50
+ run: (editor, range) => editor.chain().focus().deleteRange(range).toggleWrap('pullQuote').run(),
51
+ },
52
+ {
53
+ title: 'Table',
54
+ hint: '3×3 table with a header row',
55
+ keywords: 'grid rows columns',
56
+ run: (editor, range) => editor
57
+ .chain()
58
+ .focus()
59
+ .deleteRange(range)
60
+ .insertTable({ rows: 3, cols: 3, withHeaderRow: true })
61
+ .run(),
62
+ },
63
+ {
64
+ title: 'Divider',
65
+ hint: 'Horizontal rule',
66
+ keywords: 'hr rule separator',
67
+ run: (editor, range) => editor.chain().focus().deleteRange(range).setHorizontalRule().run(),
68
+ },
69
+ {
70
+ title: 'Tweet embed',
71
+ hint: 'Embed a post by URL',
72
+ keywords: 'twitter x embed',
73
+ run: (editor, range) => {
74
+ const url = typeof window !== 'undefined' ? window.prompt('Tweet URL') : null;
75
+ if (!url)
76
+ return;
77
+ editor
78
+ .chain()
79
+ .focus()
80
+ .deleteRange(range)
81
+ .insertContent({ type: 'tweetEmbed', attrs: { url } })
82
+ .run();
83
+ },
84
+ },
85
+ ];
86
+ /** Case-insensitive filter over titles + keywords; empty query returns all. */
87
+ export function filterSlashMenuItems(query) {
88
+ const needle = query.trim().toLowerCase();
89
+ if (!needle)
90
+ return SLASH_MENU_ITEMS;
91
+ return SLASH_MENU_ITEMS.filter((item) => item.title.toLowerCase().includes(needle) || item.keywords.toLowerCase().includes(needle));
92
+ }
93
+ function createSlashMenuRenderer() {
94
+ let container = null;
95
+ let items = [];
96
+ let selected = 0;
97
+ let executeSelected = null;
98
+ function paint(props) {
99
+ items = props.items;
100
+ selected = Math.min(selected, Math.max(0, items.length - 1));
101
+ executeSelected = () => {
102
+ const item = items[selected];
103
+ if (item)
104
+ props.command(item);
105
+ };
106
+ if (!container)
107
+ return;
108
+ container.innerHTML = '';
109
+ if (items.length === 0) {
110
+ container.style.display = 'none';
111
+ return;
112
+ }
113
+ container.style.display = 'block';
114
+ items.forEach((item, index) => {
115
+ const button = document.createElement('button');
116
+ button.type = 'button';
117
+ button.className = `slash-menu-item${index === selected ? ' is-selected' : ''}`;
118
+ const title = document.createElement('span');
119
+ title.className = 'slash-menu-title';
120
+ title.textContent = item.title;
121
+ const hint = document.createElement('span');
122
+ hint.className = 'slash-menu-hint';
123
+ hint.textContent = item.hint;
124
+ button.append(title, hint);
125
+ button.addEventListener('mousedown', (event) => {
126
+ event.preventDefault();
127
+ props.command(item);
128
+ });
129
+ container?.append(button);
130
+ });
131
+ const rect = props.clientRect?.();
132
+ if (rect) {
133
+ container.style.left = `${rect.left + window.scrollX}px`;
134
+ container.style.top = `${rect.bottom + window.scrollY + 4}px`;
135
+ }
136
+ }
137
+ return {
138
+ onStart(props) {
139
+ selected = 0;
140
+ container = document.createElement('div');
141
+ container.className = 'slash-menu';
142
+ document.body.append(container);
143
+ paint(props);
144
+ },
145
+ onUpdate(props) {
146
+ paint(props);
147
+ },
148
+ onKeyDown({ event }) {
149
+ if (event.key === 'ArrowDown') {
150
+ selected = items.length ? (selected + 1) % items.length : 0;
151
+ refreshSelection();
152
+ return true;
153
+ }
154
+ if (event.key === 'ArrowUp') {
155
+ selected = items.length ? (selected - 1 + items.length) % items.length : 0;
156
+ refreshSelection();
157
+ return true;
158
+ }
159
+ if (event.key === 'Enter') {
160
+ executeSelected?.();
161
+ return true;
162
+ }
163
+ if (event.key === 'Escape') {
164
+ container?.remove();
165
+ container = null;
166
+ return true;
167
+ }
168
+ return false;
169
+ },
170
+ onExit() {
171
+ container?.remove();
172
+ container = null;
173
+ },
174
+ };
175
+ function refreshSelection() {
176
+ if (!container)
177
+ return;
178
+ container.querySelectorAll('.slash-menu-item').forEach((el, index) => {
179
+ el.classList.toggle('is-selected', index === selected);
180
+ });
181
+ }
182
+ }
183
+ /** `/` at the start of a line opens the block-insert menu. */
184
+ export const SlashMenu = Extension.create({
185
+ name: 'slashMenu',
186
+ addProseMirrorPlugins() {
187
+ return [
188
+ Suggestion({
189
+ editor: this.editor,
190
+ pluginKey: new PluginKey('slashMenu'),
191
+ char: '/',
192
+ startOfLine: true,
193
+ items: ({ query }) => filterSlashMenuItems(query),
194
+ command: ({ editor, range, props }) => props.run(editor, range),
195
+ render: createSlashMenuRenderer,
196
+ }),
197
+ ];
198
+ },
199
+ });
200
+ //# sourceMappingURL=slash-menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slash-menu.js","sourceRoot":"","sources":["../../../src/ui/editor/slash-menu.ts"],"names":[],"mappings":"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"}
@@ -413,3 +413,13 @@ input, textarea, select { font-family: inherit; }
413
413
  .ProseMirror figure[data-pull-quote][data-attribution]::after { content: "— " attr(data-attribution); display: block; font-size: 0.8em; font-style: normal; color: var(--ink-faint); margin-top: 6px; }
414
414
  .ProseMirror div[data-generated-faq] { border: 1px dashed var(--border); border-radius: 6px; padding: 8px 12px; margin: 1em 0; color: var(--ink-faint); font-size: 0.85em; user-select: none; }
415
415
  .ProseMirror a[data-citation] { text-decoration: underline dotted; color: var(--accent); }
416
+
417
+ /* ── Slash menu + drag handle ─────────────────────────────────────────── */
418
+ .slash-menu { position: absolute; z-index: 90; min-width: 240px; max-height: 320px; overflow-y: auto; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 8px 24px rgba(0,0,0,0.18); padding: 4px; }
419
+ .slash-menu-item { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; width: 100%; padding: 6px 10px; border: 0; border-radius: 6px; background: transparent; cursor: pointer; text-align: left; }
420
+ .slash-menu-item.is-selected, .slash-menu-item:hover { background: var(--hover); }
421
+ .slash-menu-title { font-size: 13px; font-weight: 600; color: var(--ink); }
422
+ .slash-menu-hint { font-size: 11px; color: var(--ink-faint); }
423
+ .drag-handle { display: flex; align-items: center; justify-content: center; width: 18px; height: 22px; border-radius: 4px; color: var(--ink-faint); font-size: 11px; letter-spacing: -2px; cursor: grab; user-select: none; }
424
+ .drag-handle:hover { background: var(--hover); color: var(--ink-soft); }
425
+ .drag-handle:active { cursor: grabbing; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growth-labs/cms",
3
- "version": "0.5.19",
3
+ "version": "0.5.20",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "growth-labs-cms-migrations": "./dist/cli/migrations.js"
@@ -15,6 +15,10 @@
15
15
  "types": "./dist/schema/index.d.ts",
16
16
  "import": "./dist/schema/index.js"
17
17
  },
18
+ "./content": {
19
+ "types": "./dist/content/index.d.ts",
20
+ "import": "./dist/content/index.js"
21
+ },
18
22
  "./engine": {
19
23
  "types": "./dist/engine/index.d.ts",
20
24
  "import": "./dist/engine/index.js"
@@ -60,11 +64,17 @@
60
64
  },
61
65
  "dependencies": {
62
66
  "@tiptap/core": "3.24.0",
67
+ "@tiptap/extension-collaboration": "3.24.0",
68
+ "@tiptap/extension-drag-handle": "3.24.0",
63
69
  "@tiptap/extension-image": "3.24.0",
64
70
  "@tiptap/extension-link": "3.24.0",
71
+ "@tiptap/extension-node-range": "3.24.0",
65
72
  "@tiptap/extension-table": "3.24.0",
66
73
  "@tiptap/pm": "3.24.0",
67
74
  "@tiptap/starter-kit": "3.24.0",
75
+ "@tiptap/suggestion": "3.24.0",
76
+ "@tiptap/y-tiptap": "^3.0.9",
77
+ "yjs": "^13.6.32",
68
78
  "zod": "^3.24.0"
69
79
  },
70
80
  "devDependencies": {
@@ -0,0 +1,16 @@
1
+ // src/content/index.ts
2
+ // Site-side content tooling surface (`@growth-labs/cms/content`): the pure
3
+ // serializer quartet plus the envelope contract, for backfills, gates, and
4
+ // import tooling that must convert between markdown, Tiptap JSON, and
5
+ // Portable Text OUTSIDE the editor. No Editor/EditorView/DOM anywhere on
6
+ // this import path.
7
+
8
+ export {
9
+ PORTABLE_TEXT_VERSION,
10
+ type PortableTextEnvelope,
11
+ type PortableTextObject,
12
+ parsePortableTextEnvelope,
13
+ wrapPortableText,
14
+ } from '../schema/portable-text.js'
15
+ export { docToPortableText, portableTextToDoc } from '../ui/editor/portable-text.js'
16
+ export { docToMarkdown, markdownToDoc } from '../ui/editor/serialize.js'
@@ -57,6 +57,9 @@ type ToolCmd =
57
57
  | 'ordered'
58
58
  | 'link'
59
59
  | 'image'
60
+ | 'callout'
61
+ | 'pullquote'
62
+ | 'citation'
60
63
  | 'table'
61
64
  | 'tableAddRow'
62
65
  | 'tableAddCol'
@@ -82,7 +85,10 @@ const RTE_TOOLS: ToolDef[] = [
82
85
  { cmd: 'bullet', label: 'Bullet list', icon: 'rows' },
83
86
  { cmd: 'ordered', label: 'Ordered list', icon: 'rows' },
84
87
  { cmd: 'link', label: 'Link', icon: 'link' },
88
+ { cmd: 'citation', label: 'Citation', icon: 'globe' },
85
89
  { cmd: 'image', label: 'Image', icon: 'image' },
90
+ { cmd: 'callout', label: 'Callout', icon: 'flag' },
91
+ { cmd: 'pullquote', label: 'Pull quote', icon: 'star' },
86
92
  { cmd: 'table', label: 'Insert table', icon: 'grid' },
87
93
  ]
88
94
 
@@ -344,6 +350,19 @@ function ToolButton({
344
350
  }
345
351
  break
346
352
  }
353
+ case 'callout':
354
+ chain.toggleWrap('callout', { tone: 'note' }).run()
355
+ break
356
+ case 'pullquote':
357
+ chain.toggleWrap('pullQuote').run()
358
+ break
359
+ case 'citation': {
360
+ const href = window.prompt('Citation URL')
361
+ if (href) {
362
+ chain.toggleMark('citation', { href }).run()
363
+ }
364
+ break
365
+ }
347
366
  case 'table':
348
367
  chain.insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()
349
368
  break
@@ -389,6 +408,12 @@ function ToolButton({
389
408
  return editor.isActive('bulletList')
390
409
  case 'ordered':
391
410
  return editor.isActive('orderedList')
411
+ case 'callout':
412
+ return editor.isActive('callout')
413
+ case 'pullquote':
414
+ return editor.isActive('pullQuote')
415
+ case 'citation':
416
+ return editor.isActive('citation')
392
417
  case 'table':
393
418
  return editor.isActive('table')
394
419
  default:
@@ -1,11 +1,20 @@
1
+ import { DragHandle } from '@tiptap/extension-drag-handle'
1
2
  import Image from '@tiptap/extension-image'
2
3
  import Link from '@tiptap/extension-link'
3
4
  import { TableKit } from '@tiptap/extension-table'
4
5
  import StarterKit from '@tiptap/starter-kit'
5
6
  import { Callout, Citation, GeneratedFaq, PullQuote } from './blocks.js'
7
+ import { SlashMenu } from './slash-menu.js'
6
8
  import { TrimBoundaryMarks } from './trim-boundary-marks.js'
7
9
  import { TweetEmbed } from './tweet-embed.js'
8
10
 
11
+ function renderDragHandle(): HTMLElement {
12
+ const handle = document.createElement('div')
13
+ handle.className = 'drag-handle'
14
+ handle.textContent = '⋮⋮'
15
+ return handle
16
+ }
17
+
9
18
  /** The single extension set used by Masthead and its behavioral editor tests.
10
19
  *
11
20
  * Underline is deliberately ABSENT. It has no markdown form — the serializer
@@ -28,5 +37,11 @@ export function createRteExtensions() {
28
37
  PullQuote,
29
38
  GeneratedFaq,
30
39
  Citation,
40
+ SlashMenu,
41
+ // DragHandle constructs its handle element (render()) during plugin
42
+ // setup, not lazily — browser-only, unlike every other extension here.
43
+ ...(typeof document !== 'undefined'
44
+ ? [DragHandle.configure({ render: renderDragHandle })]
45
+ : []),
31
46
  ]
32
47
  }
@@ -0,0 +1,218 @@
1
+ // src/ui/editor/slash-menu.ts
2
+ // `/` block-insert menu for the rich-text editor, built on @tiptap/suggestion.
3
+ // The item list + filter are pure and unit-tested; the dropdown itself is a
4
+ // vanilla-DOM renderer created only when the Suggestion plugin runs inside a
5
+ // live (browser) editor, so this module stays importable in Node.
6
+
7
+ import { type Editor, Extension, type Range } from '@tiptap/core'
8
+ import { PluginKey } from '@tiptap/pm/state'
9
+ import Suggestion, { type SuggestionKeyDownProps, type SuggestionProps } from '@tiptap/suggestion'
10
+
11
+ export interface SlashMenuItem {
12
+ title: string
13
+ hint: string
14
+ /** Lowercase match terms beyond the title. */
15
+ keywords: string
16
+ run: (editor: Editor, range: Range) => void
17
+ }
18
+
19
+ export const SLASH_MENU_ITEMS: SlashMenuItem[] = [
20
+ {
21
+ title: 'Heading 2',
22
+ hint: 'Section heading',
23
+ keywords: 'h2 title section',
24
+ run: (editor, range) =>
25
+ editor.chain().focus().deleteRange(range).setNode('heading', { level: 2 }).run(),
26
+ },
27
+ {
28
+ title: 'Heading 3',
29
+ hint: 'Sub-section heading',
30
+ keywords: 'h3 subtitle',
31
+ run: (editor, range) =>
32
+ editor.chain().focus().deleteRange(range).setNode('heading', { level: 3 }).run(),
33
+ },
34
+ {
35
+ title: 'Bullet list',
36
+ hint: 'Unordered list',
37
+ keywords: 'ul bullets',
38
+ run: (editor, range) => editor.chain().focus().deleteRange(range).toggleBulletList().run(),
39
+ },
40
+ {
41
+ title: 'Numbered list',
42
+ hint: 'Ordered list',
43
+ keywords: 'ol ordered numbers',
44
+ run: (editor, range) => editor.chain().focus().deleteRange(range).toggleOrderedList().run(),
45
+ },
46
+ {
47
+ title: 'Quote',
48
+ hint: 'Blockquote',
49
+ keywords: 'blockquote',
50
+ run: (editor, range) => editor.chain().focus().deleteRange(range).toggleBlockquote().run(),
51
+ },
52
+ {
53
+ title: 'Callout',
54
+ hint: 'Highlighted aside with a tone',
55
+ keywords: 'aside note warning tip alert',
56
+ run: (editor, range) =>
57
+ editor.chain().focus().deleteRange(range).toggleWrap('callout', { tone: 'note' }).run(),
58
+ },
59
+ {
60
+ title: 'Pull quote',
61
+ hint: 'Large excerpted quote',
62
+ keywords: 'pullquote excerpt',
63
+ run: (editor, range) => editor.chain().focus().deleteRange(range).toggleWrap('pullQuote').run(),
64
+ },
65
+ {
66
+ title: 'Table',
67
+ hint: '3×3 table with a header row',
68
+ keywords: 'grid rows columns',
69
+ run: (editor, range) =>
70
+ editor
71
+ .chain()
72
+ .focus()
73
+ .deleteRange(range)
74
+ .insertTable({ rows: 3, cols: 3, withHeaderRow: true })
75
+ .run(),
76
+ },
77
+ {
78
+ title: 'Divider',
79
+ hint: 'Horizontal rule',
80
+ keywords: 'hr rule separator',
81
+ run: (editor, range) => editor.chain().focus().deleteRange(range).setHorizontalRule().run(),
82
+ },
83
+ {
84
+ title: 'Tweet embed',
85
+ hint: 'Embed a post by URL',
86
+ keywords: 'twitter x embed',
87
+ run: (editor, range) => {
88
+ const url = typeof window !== 'undefined' ? window.prompt('Tweet URL') : null
89
+ if (!url) return
90
+ editor
91
+ .chain()
92
+ .focus()
93
+ .deleteRange(range)
94
+ .insertContent({ type: 'tweetEmbed', attrs: { url } })
95
+ .run()
96
+ },
97
+ },
98
+ ]
99
+
100
+ /** Case-insensitive filter over titles + keywords; empty query returns all. */
101
+ export function filterSlashMenuItems(query: string): SlashMenuItem[] {
102
+ const needle = query.trim().toLowerCase()
103
+ if (!needle) return SLASH_MENU_ITEMS
104
+ return SLASH_MENU_ITEMS.filter(
105
+ (item) =>
106
+ item.title.toLowerCase().includes(needle) || item.keywords.toLowerCase().includes(needle),
107
+ )
108
+ }
109
+
110
+ function createSlashMenuRenderer() {
111
+ let container: HTMLDivElement | null = null
112
+ let items: SlashMenuItem[] = []
113
+ let selected = 0
114
+ let executeSelected: (() => void) | null = null
115
+
116
+ function paint(props: SuggestionProps<SlashMenuItem, SlashMenuItem>) {
117
+ items = props.items
118
+ selected = Math.min(selected, Math.max(0, items.length - 1))
119
+ executeSelected = () => {
120
+ const item = items[selected]
121
+ if (item) props.command(item)
122
+ }
123
+ if (!container) return
124
+ container.innerHTML = ''
125
+ if (items.length === 0) {
126
+ container.style.display = 'none'
127
+ return
128
+ }
129
+ container.style.display = 'block'
130
+ items.forEach((item, index) => {
131
+ const button = document.createElement('button')
132
+ button.type = 'button'
133
+ button.className = `slash-menu-item${index === selected ? ' is-selected' : ''}`
134
+ const title = document.createElement('span')
135
+ title.className = 'slash-menu-title'
136
+ title.textContent = item.title
137
+ const hint = document.createElement('span')
138
+ hint.className = 'slash-menu-hint'
139
+ hint.textContent = item.hint
140
+ button.append(title, hint)
141
+ button.addEventListener('mousedown', (event) => {
142
+ event.preventDefault()
143
+ props.command(item)
144
+ })
145
+ container?.append(button)
146
+ })
147
+ const rect = props.clientRect?.()
148
+ if (rect) {
149
+ container.style.left = `${rect.left + window.scrollX}px`
150
+ container.style.top = `${rect.bottom + window.scrollY + 4}px`
151
+ }
152
+ }
153
+
154
+ return {
155
+ onStart(props: SuggestionProps<SlashMenuItem, SlashMenuItem>) {
156
+ selected = 0
157
+ container = document.createElement('div')
158
+ container.className = 'slash-menu'
159
+ document.body.append(container)
160
+ paint(props)
161
+ },
162
+ onUpdate(props: SuggestionProps<SlashMenuItem, SlashMenuItem>) {
163
+ paint(props)
164
+ },
165
+ onKeyDown({ event }: SuggestionKeyDownProps): boolean {
166
+ if (event.key === 'ArrowDown') {
167
+ selected = items.length ? (selected + 1) % items.length : 0
168
+ refreshSelection()
169
+ return true
170
+ }
171
+ if (event.key === 'ArrowUp') {
172
+ selected = items.length ? (selected - 1 + items.length) % items.length : 0
173
+ refreshSelection()
174
+ return true
175
+ }
176
+ if (event.key === 'Enter') {
177
+ executeSelected?.()
178
+ return true
179
+ }
180
+ if (event.key === 'Escape') {
181
+ container?.remove()
182
+ container = null
183
+ return true
184
+ }
185
+ return false
186
+ },
187
+ onExit() {
188
+ container?.remove()
189
+ container = null
190
+ },
191
+ }
192
+
193
+ function refreshSelection() {
194
+ if (!container) return
195
+ container.querySelectorAll('.slash-menu-item').forEach((el, index) => {
196
+ el.classList.toggle('is-selected', index === selected)
197
+ })
198
+ }
199
+ }
200
+
201
+ /** `/` at the start of a line opens the block-insert menu. */
202
+ export const SlashMenu = Extension.create({
203
+ name: 'slashMenu',
204
+
205
+ addProseMirrorPlugins() {
206
+ return [
207
+ Suggestion<SlashMenuItem, SlashMenuItem>({
208
+ editor: this.editor,
209
+ pluginKey: new PluginKey('slashMenu'),
210
+ char: '/',
211
+ startOfLine: true,
212
+ items: ({ query }) => filterSlashMenuItems(query),
213
+ command: ({ editor, range, props }) => props.run(editor, range),
214
+ render: createSlashMenuRenderer,
215
+ }),
216
+ ]
217
+ },
218
+ })
@@ -413,3 +413,13 @@ input, textarea, select { font-family: inherit; }
413
413
  .ProseMirror figure[data-pull-quote][data-attribution]::after { content: "— " attr(data-attribution); display: block; font-size: 0.8em; font-style: normal; color: var(--ink-faint); margin-top: 6px; }
414
414
  .ProseMirror div[data-generated-faq] { border: 1px dashed var(--border); border-radius: 6px; padding: 8px 12px; margin: 1em 0; color: var(--ink-faint); font-size: 0.85em; user-select: none; }
415
415
  .ProseMirror a[data-citation] { text-decoration: underline dotted; color: var(--accent); }
416
+
417
+ /* ── Slash menu + drag handle ─────────────────────────────────────────── */
418
+ .slash-menu { position: absolute; z-index: 90; min-width: 240px; max-height: 320px; overflow-y: auto; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 8px 24px rgba(0,0,0,0.18); padding: 4px; }
419
+ .slash-menu-item { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; width: 100%; padding: 6px 10px; border: 0; border-radius: 6px; background: transparent; cursor: pointer; text-align: left; }
420
+ .slash-menu-item.is-selected, .slash-menu-item:hover { background: var(--hover); }
421
+ .slash-menu-title { font-size: 13px; font-weight: 600; color: var(--ink); }
422
+ .slash-menu-hint { font-size: 11px; color: var(--ink-faint); }
423
+ .drag-handle { display: flex; align-items: center; justify-content: center; width: 18px; height: 22px; border-radius: 4px; color: var(--ink-faint); font-size: 11px; letter-spacing: -2px; cursor: grab; user-select: none; }
424
+ .drag-handle:hover { background: var(--hover); color: var(--ink-soft); }
425
+ .drag-handle:active { cursor: grabbing; }