@blankdotpage/cake 0.1.37 → 0.1.39

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.
@@ -32,20 +32,11 @@ function cx(...parts) {
32
32
  return parts.filter(Boolean).join(" ");
33
33
  }
34
34
  export function CakeLinkPopover({ editor, styles, }) {
35
- const container = editor.getContainer();
36
35
  const contentRoot = editor.getContentRoot();
37
36
  if (!contentRoot) {
38
37
  return null;
39
38
  }
40
- const toOverlayRect = useCallback((rect) => {
41
- const containerRect = container.getBoundingClientRect();
42
- return {
43
- top: rect.top - containerRect.top,
44
- left: rect.left - containerRect.left,
45
- width: rect.width,
46
- height: rect.height,
47
- };
48
- }, [container]);
39
+ const toOverlayRect = useCallback((rect) => editor.toOverlayRect(rect), [editor]);
49
40
  const getSelection = useCallback(() => {
50
41
  const selection = editor.getSelection();
51
42
  const focus = selection.start === selection.end
@@ -200,13 +191,14 @@ export function CakeLinkPopover({ editor, styles, }) {
200
191
  if (state.status !== "open") {
201
192
  return;
202
193
  }
194
+ const container = editor.getContainer();
203
195
  container.addEventListener("scroll", close, { passive: true });
204
196
  window.addEventListener("resize", reposition);
205
197
  return () => {
206
198
  container.removeEventListener("scroll", close);
207
199
  window.removeEventListener("resize", reposition);
208
200
  };
209
- }, [close, container, reposition, state.status]);
201
+ }, [close, editor, reposition, state.status]);
210
202
  const handleMouseDown = useCallback((event) => {
211
203
  event.stopPropagation();
212
204
  if (event.target instanceof HTMLInputElement) {
@@ -0,0 +1,2 @@
1
+ export * from "./mention";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/mention/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
@@ -0,0 +1 @@
1
+ export * from "./mention";
@@ -0,0 +1,61 @@
1
+ import { type ReactNode } from "react";
2
+ import type { CakeExtension } from "../../core/runtime";
3
+ export type MentionItem = {
4
+ id: string;
5
+ label: string;
6
+ };
7
+ export type MentionExtensionOptions<Item extends MentionItem = MentionItem> = {
8
+ getItems: (query: string) => Promise<Item[]>;
9
+ /**
10
+ * Optional item accessors, for non-standard item shapes.
11
+ * Defaults assume { id, label }.
12
+ */
13
+ getItemId?: (item: Item) => string;
14
+ getItemLabel?: (item: Item) => string;
15
+ /**
16
+ * Customize how mentions are encoded in markdown.
17
+ *
18
+ * Default: "@[id](label)".
19
+ */
20
+ serializeMention?: (mention: {
21
+ id: string;
22
+ label: string;
23
+ }) => string;
24
+ /**
25
+ * Customize how mentions are parsed from markdown.
26
+ *
27
+ * Return null to indicate no match at `start`.
28
+ */
29
+ parseMention?: (source: string, start: number, end: number) => {
30
+ mention: {
31
+ id: string;
32
+ label: string;
33
+ };
34
+ nextPos: number;
35
+ } | null;
36
+ renderItem?: (item: Item, context: {
37
+ query: string;
38
+ isActive: boolean;
39
+ }) => ReactNode;
40
+ /**
41
+ * Allows callers to add attributes/classes/styles to the mention element.
42
+ *
43
+ * Note: the element must remain a single cursor unit; do not add extra text nodes.
44
+ */
45
+ decorateMentionElement?: (params: {
46
+ element: HTMLSpanElement;
47
+ mention: {
48
+ id: string;
49
+ label: string;
50
+ };
51
+ }) => void;
52
+ styles?: {
53
+ popover?: string;
54
+ popoverList?: string;
55
+ popoverItem?: string;
56
+ popoverItemActive?: string;
57
+ mention?: string;
58
+ };
59
+ };
60
+ export declare function mentionExtension<Item extends MentionItem = MentionItem>(options: MentionExtensionOptions<Item>): CakeExtension;
61
+ //# sourceMappingURL=mention.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mention.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/mention/mention.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EACV,aAAa,EAGd,MAAM,oBAAoB,CAAC;AAK5B,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,uBAAuB,CAAC,IAAI,SAAS,WAAW,GAAG,WAAW,IAAI;IAC5E,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7C;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC;IACnC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC;IACtC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC;IACtE;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK;QAC7D,OAAO,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QACvC,OAAO,EAAE,MAAM,CAAC;KACjB,GAAG,IAAI,CAAC;IACT,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,KAAK,SAAS,CAAC;IACtF;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE;QAChC,OAAO,EAAE,eAAe,CAAC;QACzB,OAAO,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KACxC,KAAK,IAAI,CAAC;IACX,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,IAAI,SAAS,WAAW,GAAG,WAAW,EACrE,OAAO,EAAE,uBAAuB,CAAC,IAAI,CAAC,GACrC,aAAa,CAsHf"}
@@ -0,0 +1,460 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from "react";
3
+ import { CursorSourceBuilder } from "../../core/mapping/cursor-source-map";
4
+ export function mentionExtension(options) {
5
+ const getItemId = options.getItemId ?? ((item) => String(item.id ?? ""));
6
+ const getItemLabel = options.getItemLabel ?? ((item) => String(item.label ?? ""));
7
+ const serializeMention = options.serializeMention ??
8
+ ((mention) => `@[${mention.id}](${mention.label})`);
9
+ const parseMention = options.parseMention ?? defaultParseMention;
10
+ return (editor) => {
11
+ const disposers = [];
12
+ disposers.push(editor.registerParseInline((source, start, end) => {
13
+ const result = parseMention(source, start, end);
14
+ if (!result) {
15
+ return null;
16
+ }
17
+ return {
18
+ inline: {
19
+ type: "inline-atom",
20
+ kind: "mention",
21
+ data: result.mention,
22
+ },
23
+ nextPos: result.nextPos,
24
+ };
25
+ }));
26
+ disposers.push(editor.registerSerializeInline((inline) => {
27
+ if (inline.type !== "inline-atom" || inline.kind !== "mention") {
28
+ return null;
29
+ }
30
+ const data = inline.data;
31
+ const id = typeof data?.id === "string" ? data.id : "";
32
+ const label = typeof data?.label === "string" ? data.label : "";
33
+ const source = serializeMention({ id, label });
34
+ const builder = new CursorSourceBuilder();
35
+ builder.appendCursorAtom(source, 1);
36
+ return builder.build();
37
+ }));
38
+ disposers.push(editor.registerNormalizeInline((inline) => {
39
+ if (inline.type !== "inline-atom" || inline.kind !== "mention") {
40
+ return inline;
41
+ }
42
+ const data = inline.data;
43
+ if (typeof data?.id !== "string") {
44
+ return null;
45
+ }
46
+ return inline;
47
+ }));
48
+ disposers.push(editor.registerInlineRenderer((inline, context) => {
49
+ if (inline.type !== "inline-atom" || inline.kind !== "mention") {
50
+ return null;
51
+ }
52
+ const data = inline.data;
53
+ const id = typeof data?.id === "string" ? data.id : "";
54
+ const label = typeof data?.label === "string" ? data.label : "";
55
+ const element = document.createElement("span");
56
+ element.className = [
57
+ "cake-inline-atom",
58
+ "cake-inline-atom--mention",
59
+ "cake-mention",
60
+ options.styles?.mention,
61
+ ]
62
+ .filter(Boolean)
63
+ .join(" ");
64
+ element.setAttribute("data-cake-mention", "true");
65
+ element.setAttribute("data-mention-id", id);
66
+ element.setAttribute("data-mention-label", label);
67
+ options.decorateMentionElement?.({
68
+ element,
69
+ mention: { id, label },
70
+ });
71
+ // IMPORTANT: keep exactly one text node so DOM<->cursor mapping stays 1:1.
72
+ const placeholder = document.createTextNode(" ");
73
+ context.createTextRun(placeholder);
74
+ element.append(placeholder);
75
+ return element;
76
+ }));
77
+ const MentionUI = ({ editor }) => (_jsx(CakeMentionUI, { editor: editor, getItems: options.getItems, getItemId: getItemId, getItemLabel: getItemLabel, serializeMention: serializeMention, renderItem: options.renderItem, styles: options.styles }));
78
+ disposers.push(editor.registerUI(MentionUI));
79
+ return () => disposers.reverse().forEach((d) => d());
80
+ };
81
+ }
82
+ function defaultParseMention(source, start, end) {
83
+ // Default format: @[id](label)
84
+ if (source[start] !== "@" || source[start + 1] !== "[") {
85
+ return null;
86
+ }
87
+ const idStart = start + 2;
88
+ const idClose = source.indexOf("]", idStart);
89
+ if (idClose === -1 || idClose >= end) {
90
+ return null;
91
+ }
92
+ if (source[idClose + 1] !== "(") {
93
+ return null;
94
+ }
95
+ const labelStart = idClose + 2;
96
+ const labelClose = source.indexOf(")", labelStart);
97
+ if (labelClose === -1 || labelClose >= end) {
98
+ return null;
99
+ }
100
+ const id = source.slice(idStart, idClose);
101
+ const label = source.slice(labelStart, labelClose);
102
+ return {
103
+ mention: { id, label },
104
+ nextPos: labelClose + 1,
105
+ };
106
+ }
107
+ function ensureMentionStyles() {
108
+ const id = "cake-mention-styles";
109
+ if (document.getElementById(id)) {
110
+ return;
111
+ }
112
+ const style = document.createElement("style");
113
+ style.id = id;
114
+ style.textContent = `
115
+ .cake-mention {
116
+ display: inline-flex;
117
+ align-items: center;
118
+ border-radius: 9999px;
119
+ padding: 0 6px;
120
+ background: rgba(59, 130, 246, 0.15);
121
+ color: rgb(37, 99, 235);
122
+ font-weight: 500;
123
+ white-space: nowrap;
124
+ }
125
+ .cake-mention::before {
126
+ content: "@" attr(data-mention-label);
127
+ }
128
+ .cake-mention > * {
129
+ display: none;
130
+ }
131
+ .cake-mention-popover {
132
+ min-width: 220px;
133
+ max-width: 320px;
134
+ max-height: 220px;
135
+ overflow: auto;
136
+ background: white;
137
+ border: 1px solid rgba(0,0,0,0.12);
138
+ border-radius: 10px;
139
+ box-shadow: 0 12px 32px rgba(0,0,0,0.16);
140
+ padding: 6px;
141
+ }
142
+ .cake-mention-popover button {
143
+ width: 100%;
144
+ text-align: left;
145
+ border: 0;
146
+ background: transparent;
147
+ padding: 6px 8px;
148
+ border-radius: 8px;
149
+ cursor: pointer;
150
+ }
151
+ .cake-mention-popover button:hover {
152
+ background: rgba(0,0,0,0.06);
153
+ }
154
+ .cake-mention-popover button[aria-selected="true"] {
155
+ background: rgba(59, 130, 246, 0.12);
156
+ }
157
+ `;
158
+ document.head.appendChild(style);
159
+ }
160
+ function getTriggerQuery(textBeforeCursor) {
161
+ // Require the trigger to be at the start or preceded by a non-word character
162
+ // to avoid matching emails/words like "foo@bar", while still supporting
163
+ // punctuation boundaries like "(@alice".
164
+ const match = textBeforeCursor.match(/(?:^|[^\w])@([^\s@]*)$/);
165
+ return match ? match[1] ?? "" : null;
166
+ }
167
+ function getPopoverPositionFromCaret(editor) {
168
+ const rect = editor.getCursorOverlayRect();
169
+ if (!rect) {
170
+ return null;
171
+ }
172
+ return {
173
+ top: rect.top + rect.height + 6,
174
+ left: rect.left,
175
+ };
176
+ }
177
+ function getPopoverPositionFromElement(editor, anchor) {
178
+ const rect = editor.toOverlayRect(anchor.getBoundingClientRect());
179
+ return {
180
+ top: rect.top + rect.height + 6,
181
+ left: rect.left,
182
+ };
183
+ }
184
+ function CakeMentionUI({ editor, getItems, getItemId, getItemLabel, serializeMention, renderItem, styles, }) {
185
+ const container = editor.getContainer();
186
+ const requestIdRef = useRef(0);
187
+ const stateRef = useRef({ status: "closed" });
188
+ const [state, setState] = useState({
189
+ status: "closed",
190
+ });
191
+ useEffect(() => {
192
+ ensureMentionStyles();
193
+ }, []);
194
+ useLayoutEffect(() => {
195
+ stateRef.current = state;
196
+ }, [state]);
197
+ const close = useCallback(() => {
198
+ setState({ status: "closed" });
199
+ }, []);
200
+ const handleChoose = useCallback((item) => {
201
+ const current = stateRef.current;
202
+ if (current.status !== "open") {
203
+ return;
204
+ }
205
+ if (current.replaceAdvanceCursor > 0) {
206
+ const sel = editor.getSelection();
207
+ const cursorLength = editor.getCursorLength();
208
+ const next = Math.min(Math.max(0, sel.start + current.replaceAdvanceCursor), cursorLength);
209
+ editor.setSelection({ start: next, end: next, affinity: "forward" });
210
+ }
211
+ const id = getItemId(item);
212
+ const label = getItemLabel(item);
213
+ const text = serializeMention({ id, label });
214
+ editor.replaceTextBeforeCursor(current.replaceChars, text);
215
+ close();
216
+ editor.focus();
217
+ }, [close, editor, getItemId, getItemLabel, serializeMention]);
218
+ const open = useCallback((next) => {
219
+ setState({
220
+ status: "open",
221
+ mode: next.mode,
222
+ query: next.query,
223
+ replaceChars: next.replaceChars,
224
+ replaceAdvanceCursor: next.replaceAdvanceCursor ?? 0,
225
+ position: next.position,
226
+ items: next.items ?? [],
227
+ loading: true,
228
+ activeIndex: 0,
229
+ });
230
+ }, []);
231
+ const fetch = useCallback((query) => {
232
+ const requestId = (requestIdRef.current += 1);
233
+ let promise;
234
+ try {
235
+ promise = Promise.resolve(getItems(query));
236
+ }
237
+ catch {
238
+ promise = Promise.resolve([]);
239
+ }
240
+ return promise
241
+ .then((items) => {
242
+ if (requestId !== requestIdRef.current) {
243
+ return;
244
+ }
245
+ setState((current) => {
246
+ if (current.status !== "open") {
247
+ return current;
248
+ }
249
+ return {
250
+ ...current,
251
+ items,
252
+ loading: false,
253
+ activeIndex: Math.min(current.activeIndex, Math.max(0, items.length - 1)),
254
+ };
255
+ });
256
+ })
257
+ .catch(() => {
258
+ if (requestId !== requestIdRef.current) {
259
+ return;
260
+ }
261
+ setState((current) => {
262
+ if (current.status !== "open") {
263
+ return current;
264
+ }
265
+ return { ...current, items: [], loading: false };
266
+ });
267
+ });
268
+ }, [getItems]);
269
+ useLayoutEffect(() => {
270
+ // Trigger mode: driven by typing in the editor.
271
+ const updateFromEditor = () => {
272
+ const selection = editor.getSelection();
273
+ if (selection.start !== selection.end) {
274
+ if (stateRef.current.status === "open" &&
275
+ stateRef.current.mode === "trigger") {
276
+ close();
277
+ }
278
+ return;
279
+ }
280
+ const query = getTriggerQuery(editor.getTextBeforeCursor(80));
281
+ if (query === null) {
282
+ if (stateRef.current.status === "open" &&
283
+ stateRef.current.mode === "trigger") {
284
+ close();
285
+ }
286
+ return;
287
+ }
288
+ const position = getPopoverPositionFromCaret(editor);
289
+ if (!position) {
290
+ return;
291
+ }
292
+ const replaceChars = query.length + 1;
293
+ open({
294
+ status: "open",
295
+ mode: "trigger",
296
+ query,
297
+ replaceChars,
298
+ replaceAdvanceCursor: 0,
299
+ position,
300
+ });
301
+ fetch(query);
302
+ };
303
+ const unsubscribe = editor.onChange(updateFromEditor);
304
+ // In case the user typed before React effects ran, sync from current state.
305
+ updateFromEditor();
306
+ return unsubscribe;
307
+ }, [close, editor, fetch, open]);
308
+ useEffect(() => {
309
+ function handleClick(event) {
310
+ const target = event.target;
311
+ if (!(target instanceof Element)) {
312
+ close();
313
+ return;
314
+ }
315
+ // Ignore clicks inside the popover itself.
316
+ if (target.closest("[data-testid=\"cake-mention-popover\"]")) {
317
+ return;
318
+ }
319
+ const mention = target.closest("[data-cake-mention]");
320
+ if (!mention) {
321
+ if (stateRef.current.status === "open" &&
322
+ stateRef.current.mode === "replace") {
323
+ close();
324
+ }
325
+ return;
326
+ }
327
+ const rect = mention.getBoundingClientRect();
328
+ const midpoint = rect.left + rect.width / 2;
329
+ const placeBefore = event.clientX < midpoint;
330
+ queueMicrotask(() => {
331
+ const domSelection = window.getSelection();
332
+ if (!domSelection) {
333
+ return;
334
+ }
335
+ const walker = document.createTreeWalker(mention, NodeFilter.SHOW_TEXT);
336
+ const node = walker.nextNode();
337
+ const placeholder = node instanceof Text ? node : null;
338
+ const range = document.createRange();
339
+ if (placeholder && placeholder.data.length >= 1) {
340
+ const offset = placeBefore ? 0 : 1;
341
+ range.setStart(placeholder, offset);
342
+ range.setEnd(placeholder, offset);
343
+ domSelection.removeAllRanges();
344
+ domSelection.addRange(range);
345
+ editor.syncSelectionFromDOM();
346
+ }
347
+ // Defer opening until the next frame so any caret auto-scroll triggered
348
+ // by the selection sync finishes before we show the popover.
349
+ requestAnimationFrame(() => {
350
+ const position = getPopoverPositionFromCaret(editor) ??
351
+ getPopoverPositionFromElement(editor, mention);
352
+ open({
353
+ status: "open",
354
+ mode: "replace",
355
+ query: "",
356
+ replaceChars: 1,
357
+ replaceAdvanceCursor: placeBefore ? 1 : 0,
358
+ position,
359
+ });
360
+ fetch("");
361
+ });
362
+ });
363
+ }
364
+ container.addEventListener("click", handleClick);
365
+ return () => {
366
+ container.removeEventListener("click", handleClick);
367
+ };
368
+ }, [close, container, editor, fetch, open]);
369
+ useEffect(() => {
370
+ return editor.registerKeyDownInterceptor((event) => {
371
+ const current = stateRef.current;
372
+ if (current.status !== "open") {
373
+ return false;
374
+ }
375
+ if (event.key === "Escape") {
376
+ event.preventDefault();
377
+ close();
378
+ return true;
379
+ }
380
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
381
+ event.preventDefault();
382
+ const delta = event.key === "ArrowDown" ? 1 : -1;
383
+ setState((prev) => {
384
+ if (prev.status !== "open") {
385
+ return prev;
386
+ }
387
+ const length = prev.items.length;
388
+ if (length === 0) {
389
+ return prev;
390
+ }
391
+ const nextIndex = (prev.activeIndex + delta + length) % length;
392
+ return { ...prev, activeIndex: nextIndex };
393
+ });
394
+ return true;
395
+ }
396
+ if (event.key === "Enter") {
397
+ event.preventDefault();
398
+ editor.suppressNextBeforeInput();
399
+ const item = current.items[current.activeIndex];
400
+ if (item) {
401
+ handleChoose(item);
402
+ }
403
+ return true;
404
+ }
405
+ return false;
406
+ });
407
+ }, [close, editor, handleChoose]);
408
+ useEffect(() => {
409
+ if (state.status !== "open") {
410
+ return;
411
+ }
412
+ container.addEventListener("scroll", close, { passive: true });
413
+ window.addEventListener("resize", close);
414
+ return () => {
415
+ container.removeEventListener("scroll", close);
416
+ window.removeEventListener("resize", close);
417
+ };
418
+ }, [close, container, state.status]);
419
+ const className = useMemo(() => ["cake-mention-popover", styles?.popover]
420
+ .filter(Boolean)
421
+ .join(" "), [styles?.popover]);
422
+ if (state.status !== "open") {
423
+ return null;
424
+ }
425
+ return (_jsx("div", { "data-testid": "cake-mention-popover", className: className, style: {
426
+ position: "absolute",
427
+ top: state.position.top,
428
+ left: state.position.left,
429
+ pointerEvents: "auto",
430
+ zIndex: 10,
431
+ }, onMouseDown: (event) => {
432
+ // Keep focus from leaving the editor on click-drag.
433
+ event.stopPropagation();
434
+ event.preventDefault();
435
+ }, children: _jsxs("div", { className: styles?.popoverList, children: [state.items.map((item, index) => {
436
+ const label = getItemLabel(item);
437
+ const isActive = index === state.activeIndex;
438
+ const itemClass = [
439
+ styles?.popoverItem,
440
+ isActive ? styles?.popoverItemActive : null,
441
+ ]
442
+ .filter(Boolean)
443
+ .join(" ");
444
+ const content = renderItem
445
+ ? renderItem(item, { query: state.query, isActive })
446
+ : label;
447
+ return (_jsx("button", { type: "button", className: itemClass, "aria-label": label, "aria-selected": isActive, "data-active": isActive ? "true" : undefined, onMouseEnter: () => {
448
+ setState((prev) => {
449
+ if (prev.status !== "open") {
450
+ return prev;
451
+ }
452
+ return { ...prev, activeIndex: index };
453
+ });
454
+ }, onClick: (event) => {
455
+ event.preventDefault();
456
+ event.stopPropagation();
457
+ handleChoose(item);
458
+ }, children: content }, getItemId(item) || String(index)));
459
+ }), state.items.length === 0 && !state.loading ? (_jsx("div", { style: { padding: 8, opacity: 0.6 }, children: "No results" })) : null, state.items.length === 0 && state.loading ? (_jsx("div", { style: { padding: 8, opacity: 0.6 }, children: "Searching\u2026" })) : null] }) }));
460
+ }
@@ -19,6 +19,8 @@ export interface CakeEditorProps {
19
19
  spellCheck?: boolean;
20
20
  className?: string;
21
21
  style?: React.CSSProperties;
22
+ scrollerStyle?: React.CSSProperties;
23
+ scrollerClassName?: string;
22
24
  extensions: CakeExtension[];
23
25
  onBlur?: (event?: FocusEvent) => void;
24
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cake/react/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cake/react/index.tsx"],"names":[],"mappings":"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"}