@bendyline/squisq-editor-react 2.11.21 → 2.11.23

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.
@@ -18,7 +18,7 @@ import {
18
18
  useDictationState,
19
19
  useEditorContext,
20
20
  useEditorContextOptional
21
- } from "./chunk-UCYZBMCG.js";
21
+ } from "./chunk-TRBNNRLK.js";
22
22
  import {
23
23
  monacoLanguageRequestKey,
24
24
  monacoLanguagesForDocument,
@@ -4013,6 +4013,7 @@ function PreviewToolbarControls({
4013
4013
  {
4014
4014
  label: "Summarize",
4015
4015
  labelTooltip: SUMMARIZE_TOOLTIP,
4016
+ style: { ...selectStyle, padding: "3px 6px" },
4016
4017
  value: s.activeTransformStyle,
4017
4018
  options: TRANSFORM_STYLE_OPTIONS,
4018
4019
  onChange: (v2) => s.setSelectedTransformStyle(v2),
@@ -4226,7 +4227,8 @@ function PreviewSelect({
4226
4227
  options,
4227
4228
  onChange,
4228
4229
  compact,
4229
- children
4230
+ children,
4231
+ style = selectStyle
4230
4232
  }) {
4231
4233
  return /* @__PURE__ */ jsxs6("div", { className: `squisq-preview-control${compact ? " squisq-preview-control--compact" : ""}`, children: [
4232
4234
  /* @__PURE__ */ jsxs6("label", { style: labelStyle, title: labelTooltip, children: [
@@ -4239,7 +4241,7 @@ function PreviewSelect({
4239
4241
  "aria-label": label,
4240
4242
  value,
4241
4243
  onChange: (e2) => onChange(e2.target.value),
4242
- style: selectStyle,
4244
+ style,
4243
4245
  children: options.map((o) => /* @__PURE__ */ jsx7("option", { value: o.key, children: o.label }, o.key))
4244
4246
  }
4245
4247
  ),
@@ -9880,34 +9882,28 @@ function buildIconCategory(family, label) {
9880
9882
  id: `fa-${family}`,
9881
9883
  label,
9882
9884
  tab: tabIcon,
9883
- entries: familyIcons.map(
9884
- (i) => ({
9885
- kind: "icon",
9886
- family: i.family,
9887
- name: i.name,
9888
- label: i.label,
9889
- keywords: i.keywords,
9890
- token: canonicalIconToken(i)
9891
- })
9892
- )
9885
+ entries: familyIcons.map((i) => ({
9886
+ kind: "icon",
9887
+ family: i.family,
9888
+ name: i.name,
9889
+ label: i.label,
9890
+ keywords: i.keywords,
9891
+ token: canonicalIconToken(i)
9892
+ }))
9893
9893
  };
9894
9894
  }
9895
9895
  var PICKER_CATEGORIES = [
9896
- ...EMOJI_CATEGORIES.map(
9897
- (c) => ({
9898
- id: c.id,
9899
- label: c.label,
9900
- tab: { kind: "emoji", char: c.icon },
9901
- entries: c.emojis.map(
9902
- (e2) => ({
9903
- kind: "emoji",
9904
- char: e2.char,
9905
- name: e2.name,
9906
- keywords: e2.keywords
9907
- })
9908
- )
9909
- })
9910
- ),
9896
+ ...EMOJI_CATEGORIES.map((c) => ({
9897
+ id: c.id,
9898
+ label: c.label,
9899
+ tab: { kind: "emoji", char: c.icon },
9900
+ entries: c.emojis.map((e2) => ({
9901
+ kind: "emoji",
9902
+ char: e2.char,
9903
+ name: e2.name,
9904
+ keywords: e2.keywords
9905
+ }))
9906
+ })),
9911
9907
  buildIconCategory("brands", "Brands"),
9912
9908
  buildIconCategory("solid", "Solid"),
9913
9909
  buildIconCategory("regular", "Regular")
@@ -17942,14 +17938,27 @@ import { useCallback as useCallback30, useEffect as useEffect27, useId as useId1
17942
17938
 
17943
17939
  // src/find/FindHighlightExtension.ts
17944
17940
  import { Extension as Extension3 } from "@tiptap/core";
17945
- import { Plugin as Plugin3, PluginKey as PluginKey3 } from "@tiptap/pm/state";
17941
+ import { Plugin as Plugin3, PluginKey as PluginKey3, TextSelection } from "@tiptap/pm/state";
17946
17942
  import { Decoration as Decoration3, DecorationSet as DecorationSet3 } from "@tiptap/pm/view";
17947
17943
 
17948
17944
  // src/find/findModel.ts
17949
- function findTextMatches(text, query) {
17950
- const needle = query.trim();
17951
- if (!needle || !text) return [];
17952
- const matcher = new RegExp(escapeRegExp(needle), "giu");
17945
+ var WORD_CHARACTER = /^[\p{L}\p{N}\p{M}_]$/u;
17946
+ var WORD_BOUNDARY_BEFORE = "(?<![\\p{L}\\p{N}\\p{M}_])";
17947
+ var WORD_BOUNDARY_AFTER = "(?![\\p{L}\\p{N}\\p{M}_])";
17948
+ function createFindMatcher(query, options = {}) {
17949
+ const needle = query.trim().normalize("NFC");
17950
+ if (!needle) return null;
17951
+ let source = escapeRegExp(needle);
17952
+ if (options.wholeWord) {
17953
+ const characters = [...needle];
17954
+ if (WORD_CHARACTER.test(characters[0])) source = WORD_BOUNDARY_BEFORE + source;
17955
+ if (WORD_CHARACTER.test(characters[characters.length - 1])) source += WORD_BOUNDARY_AFTER;
17956
+ }
17957
+ return new RegExp(source, options.matchCase ? "gu" : "giu");
17958
+ }
17959
+ function findTextMatches(text, query, options = {}) {
17960
+ const matcher = text ? createFindMatcher(query, options) : null;
17961
+ if (!matcher) return [];
17953
17962
  const matches = [];
17954
17963
  let match;
17955
17964
  while ((match = matcher.exec(text)) !== null) {
@@ -17962,7 +17971,11 @@ function normalizeFindIndex(index2, count) {
17962
17971
  if (count <= 0) return 0;
17963
17972
  return (index2 % count + count) % count;
17964
17973
  }
17965
- function findProseMirrorMatches(doc, query) {
17974
+ function nextFindIndexAfter(matches, offset) {
17975
+ const index2 = matches.findIndex((match) => match.from >= offset);
17976
+ return index2 < 0 ? 0 : index2;
17977
+ }
17978
+ function findProseMirrorMatches(doc, query, options = {}) {
17966
17979
  const matches = [];
17967
17980
  doc.descendants((node2, blockPos) => {
17968
17981
  if (!node2.isTextblock) return true;
@@ -17978,7 +17991,7 @@ function findProseMirrorMatches(doc, query) {
17978
17991
  }
17979
17992
  return true;
17980
17993
  });
17981
- for (const match of findTextMatches(text, query)) {
17994
+ for (const match of findTextMatches(text, query, options)) {
17982
17995
  const startSpan = spans.find((span) => match.from >= span.from && match.from < span.to);
17983
17996
  const endOffset = match.to - 1;
17984
17997
  const endSpan = spans.find((span) => endOffset >= span.from && endOffset < span.to);
@@ -17993,13 +18006,13 @@ function findProseMirrorMatches(doc, query) {
17993
18006
  return matches;
17994
18007
  }
17995
18008
  function escapeRegExp(value) {
17996
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
18009
+ return value.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
17997
18010
  }
17998
18011
 
17999
18012
  // src/find/FindHighlightExtension.ts
18000
18013
  var FIND_HIGHLIGHT_KEY = new PluginKey3("squisq-find-highlight");
18001
- function buildState(doc, query, selectedIndex) {
18002
- const matches = findProseMirrorMatches(doc, query);
18014
+ function buildState(doc, query, options, selectedIndex) {
18015
+ const matches = findProseMirrorMatches(doc, query, options);
18003
18016
  const selected = normalizeFindIndex(selectedIndex, matches.length);
18004
18017
  const decorations = matches.map(
18005
18018
  (match, index2) => Decoration3.inline(match.from, match.to, {
@@ -18008,6 +18021,7 @@ function buildState(doc, query, selectedIndex) {
18008
18021
  );
18009
18022
  return {
18010
18023
  query,
18024
+ options,
18011
18025
  selectedIndex: selected,
18012
18026
  decorations: DecorationSet3.create(doc, decorations)
18013
18027
  };
@@ -18019,13 +18033,14 @@ var FindHighlightExtension = Extension3.create({
18019
18033
  new Plugin3({
18020
18034
  key: FIND_HIGHLIGHT_KEY,
18021
18035
  state: {
18022
- init: (_2, state) => buildState(state.doc, "", 0),
18036
+ init: (_2, state) => buildState(state.doc, "", {}, 0),
18023
18037
  apply: (transaction, previous, _oldState, newState) => {
18024
18038
  const meta = transaction.getMeta(FIND_HIGHLIGHT_KEY);
18025
18039
  if (!meta && !transaction.docChanged) return previous;
18026
18040
  return buildState(
18027
18041
  newState.doc,
18028
18042
  meta?.query ?? previous.query,
18043
+ meta?.options ?? previous.options,
18029
18044
  meta?.selectedIndex ?? previous.selectedIndex
18030
18045
  );
18031
18046
  }
@@ -18037,35 +18052,93 @@ var FindHighlightExtension = Extension3.create({
18037
18052
  ];
18038
18053
  }
18039
18054
  });
18040
- function updateTiptapFindHighlights(editor, query, selectedIndex) {
18041
- const matches = findProseMirrorMatches(editor.state.doc, query);
18042
- editor.view.dispatch(
18043
- editor.state.tr.setMeta(FIND_HIGHLIGHT_KEY, {
18044
- query,
18045
- selectedIndex: normalizeFindIndex(selectedIndex, matches.length)
18046
- })
18047
- );
18055
+ function updateTiptapFindHighlights(editor, query, selectedIndex, options = {}, { select = false } = {}) {
18056
+ const matches = findProseMirrorMatches(editor.state.doc, query, options);
18057
+ const selected = normalizeFindIndex(selectedIndex, matches.length);
18058
+ let transaction = editor.state.tr.setMeta(FIND_HIGHLIGHT_KEY, {
18059
+ query,
18060
+ options,
18061
+ selectedIndex: selected
18062
+ });
18063
+ const match = select ? matches[selected] : void 0;
18064
+ if (match) {
18065
+ transaction = transaction.setSelection(
18066
+ TextSelection.create(transaction.doc, match.from, match.to)
18067
+ );
18068
+ }
18069
+ editor.view.dispatch(transaction);
18070
+ return matches.length;
18071
+ }
18072
+ function replaceTiptapFindMatch(editor, query, selectedIndex, replacement, options = {}) {
18073
+ const matches = findProseMirrorMatches(editor.state.doc, query, options);
18074
+ const match = matches[normalizeFindIndex(selectedIndex, matches.length)];
18075
+ if (!match) return null;
18076
+ const transaction = editor.state.tr.insertText(replacement, match.from, match.to);
18077
+ editor.view.dispatch(transaction);
18078
+ const after = match.from + replacement.length;
18079
+ return nextFindIndexAfter(findProseMirrorMatches(editor.state.doc, query, options), after);
18080
+ }
18081
+ function replaceAllTiptapFindMatches(editor, query, replacement, options = {}) {
18082
+ const matches = findProseMirrorMatches(editor.state.doc, query, options);
18083
+ if (matches.length === 0) return 0;
18084
+ const transaction = editor.state.tr;
18085
+ for (let index2 = matches.length - 1; index2 >= 0; index2 -= 1) {
18086
+ transaction.insertText(replacement, matches[index2].from, matches[index2].to);
18087
+ }
18088
+ editor.view.dispatch(transaction);
18048
18089
  return matches.length;
18049
18090
  }
18050
18091
 
18051
18092
  // src/find/FindToolbar.tsx
18052
- import { jsx as jsx45, jsxs as jsxs35 } from "react/jsx-runtime";
18053
- function FindToolbar({ onClose }) {
18054
- const { activeView, markdownSource, tiptapEditor, monacoEditor } = useEditorContext();
18055
- const [query, setQuery] = useState35("");
18056
- const [selectedIndex, setSelectedIndex] = useState35(0);
18093
+ import { Fragment as Fragment14, jsx as jsx45, jsxs as jsxs35 } from "react/jsx-runtime";
18094
+ var MAX_SEEDED_QUERY = 200;
18095
+ function FindToolbar({
18096
+ onClose,
18097
+ allowReplace = false,
18098
+ replaceOpen = false,
18099
+ onReplaceOpenChange,
18100
+ focusRequest = 0
18101
+ }) {
18102
+ const { activeView, markdownSource, tiptapEditor, monacoEditor, findRequest } = useEditorContext();
18103
+ const [initial] = useState35(
18104
+ () => initialFindState(findRequest, activeView, tiptapEditor, monacoEditor)
18105
+ );
18106
+ const [query, setQuery] = useState35(initial.query);
18107
+ const [matchCase, setMatchCase] = useState35(initial.matchCase ?? false);
18108
+ const [wholeWord, setWholeWord] = useState35(initial.wholeWord ?? false);
18109
+ const [selectedIndex, setSelectedIndex] = useState35(initial.occurrence ?? 0);
18057
18110
  const [matchCount, setMatchCount] = useState35(0);
18111
+ const [replacement, setReplacement] = useState35("");
18058
18112
  const inputRef = useRef32(null);
18113
+ const replaceInputRef = useRef32(null);
18059
18114
  const reactId = useId12().replace(/[^a-zA-Z0-9_-]/g, "");
18060
18115
  const previewHighlightName = `squisq-find-${reactId}`;
18061
18116
  const previewSelectedName = `${previewHighlightName}-selected`;
18117
+ const canReplace = allowReplace && activeView !== "preview";
18118
+ const showReplace = canReplace && replaceOpen;
18119
+ const options = { matchCase, wholeWord };
18120
+ const lastNavigationRef = useRef32("");
18121
+ const pendingRevealRef = useRef32(false);
18062
18122
  useEffect27(() => {
18063
18123
  inputRef.current?.focus();
18064
- }, []);
18124
+ inputRef.current?.select();
18125
+ }, [focusRequest]);
18126
+ useEffect27(() => {
18127
+ if (showReplace) replaceInputRef.current?.focus();
18128
+ }, [showReplace, focusRequest]);
18129
+ const appliedRequestRef = useRef32(findRequest);
18130
+ useEffect27(() => {
18131
+ if (!findRequest || findRequest === appliedRequestRef.current) return;
18132
+ appliedRequestRef.current = findRequest;
18133
+ setQuery(findRequest.query);
18134
+ setMatchCase(findRequest.matchCase ?? false);
18135
+ setWholeWord(findRequest.wholeWord ?? false);
18136
+ setSelectedIndex(findRequest.occurrence ?? 0);
18137
+ }, [findRequest]);
18065
18138
  useEffect27(() => {
18066
18139
  const style = document.createElement("style");
18067
18140
  style.dataset.squisqFindHighlight = reactId;
18068
- style.textContent = `::highlight(${previewHighlightName}) { background: #fde68a; color: inherit; } ::highlight(${previewSelectedName}) { background: #f59e0b; color: #111827; }`;
18141
+ style.textContent = `::highlight(${previewHighlightName}) { background: var(--squisq-find-match, #fde68a); color: inherit; } ::highlight(${previewSelectedName}) { background: var(--squisq-find-match-current, #f59e0b); color: var(--squisq-find-match-text, #111827); }`;
18069
18142
  document.head.append(style);
18070
18143
  return () => style.remove();
18071
18144
  }, [previewHighlightName, previewSelectedName, reactId]);
@@ -18073,25 +18146,36 @@ function FindToolbar({ onClose }) {
18073
18146
  let cleanup = () => {
18074
18147
  };
18075
18148
  let count = 0;
18149
+ const navigationKey = [activeView, query, matchCase, wholeWord, selectedIndex].join("\0");
18150
+ if (navigationKey !== lastNavigationRef.current) {
18151
+ lastNavigationRef.current = navigationKey;
18152
+ pendingRevealRef.current = true;
18153
+ }
18154
+ const reveal = pendingRevealRef.current;
18155
+ const findOptions = { matchCase, wholeWord };
18076
18156
  if (activeView === "raw" && monacoEditor) {
18077
18157
  const model2 = monacoEditor.getModel();
18078
- const matches = model2 ? model2.findMatches(query.trim(), false, false, false, null, false) : [];
18079
- count = query.trim() ? matches.length : 0;
18158
+ const ranges = model2 ? findMonacoRanges(model2, query, findOptions) : [];
18159
+ count = ranges.length;
18080
18160
  const selected = normalizeFindIndex(selectedIndex, count);
18081
18161
  const decorations = monacoEditor.createDecorationsCollection(
18082
- matches.slice(0, count).map((match, index2) => ({
18083
- range: match.range,
18162
+ ranges.map((range, index2) => ({
18163
+ range,
18084
18164
  options: monacoDecorationOptions(index2 === selected)
18085
18165
  }))
18086
18166
  );
18087
- if (count > 0) monacoEditor.revealRangeInCenter(matches[selected].range);
18167
+ if (reveal && count > 0) {
18168
+ monacoEditor.setSelection(ranges[selected]);
18169
+ monacoEditor.revealRangeInCenter(ranges[selected]);
18170
+ }
18088
18171
  cleanup = () => decorations.clear();
18089
18172
  } else if (activeView === "wysiwyg" && tiptapEditor && !tiptapEditor.isDestroyed) {
18090
- count = updateTiptapFindHighlights(tiptapEditor, query, selectedIndex);
18091
- const selected = tiptapEditor.view.dom.querySelector(
18092
- ".squisq-find-match--selected"
18093
- );
18094
- selected?.scrollIntoView?.({ block: "center", inline: "nearest" });
18173
+ count = updateTiptapFindHighlights(tiptapEditor, query, selectedIndex, findOptions, {
18174
+ select: reveal
18175
+ });
18176
+ if (reveal) {
18177
+ tiptapEditor.view.dom.querySelector(".squisq-find-match--selected")?.scrollIntoView?.({ block: "center", inline: "nearest" });
18178
+ }
18095
18179
  cleanup = () => {
18096
18180
  if (!tiptapEditor.isDestroyed) updateTiptapFindHighlights(tiptapEditor, "", 0);
18097
18181
  };
@@ -18101,26 +18185,31 @@ function FindToolbar({ onClose }) {
18101
18185
  const result = applyPreviewHighlights(
18102
18186
  root,
18103
18187
  query,
18188
+ findOptions,
18104
18189
  selectedIndex,
18105
18190
  previewHighlightName,
18106
- previewSelectedName
18191
+ previewSelectedName,
18192
+ reveal
18107
18193
  );
18108
18194
  count = result.count;
18109
18195
  cleanup = result.cleanup;
18110
18196
  }
18111
18197
  }
18198
+ if (count > 0) pendingRevealRef.current = false;
18112
18199
  setMatchCount(count);
18113
- setSelectedIndex((current) => normalizeFindIndex(current, count));
18200
+ setSelectedIndex((current) => count === 0 ? current : normalizeFindIndex(current, count));
18114
18201
  return cleanup;
18115
18202
  }, [
18116
18203
  activeView,
18117
18204
  markdownSource,
18205
+ matchCase,
18118
18206
  monacoEditor,
18119
18207
  previewHighlightName,
18120
18208
  previewSelectedName,
18121
18209
  query,
18122
18210
  selectedIndex,
18123
- tiptapEditor
18211
+ tiptapEditor,
18212
+ wholeWord
18124
18213
  ]);
18125
18214
  const moveSelection = useCallback30(
18126
18215
  (delta) => {
@@ -18129,8 +18218,48 @@ function FindToolbar({ onClose }) {
18129
18218
  },
18130
18219
  [matchCount]
18131
18220
  );
18221
+ const replaceCurrent = () => {
18222
+ if (!canReplace || matchCount === 0) return;
18223
+ let next = null;
18224
+ if (activeView === "raw" && monacoEditor) {
18225
+ next = replaceMonacoMatch(monacoEditor, query, selectedIndex, replacement, options);
18226
+ } else if (activeView === "wysiwyg" && tiptapEditor && !tiptapEditor.isDestroyed) {
18227
+ next = replaceTiptapFindMatch(tiptapEditor, query, selectedIndex, replacement, options);
18228
+ }
18229
+ if (next === null) return;
18230
+ pendingRevealRef.current = true;
18231
+ setSelectedIndex(next);
18232
+ };
18233
+ const replaceAll = () => {
18234
+ if (!canReplace || matchCount === 0) return;
18235
+ if (activeView === "raw" && monacoEditor) {
18236
+ replaceAllMonacoMatches(monacoEditor, query, replacement, options);
18237
+ } else if (activeView === "wysiwyg" && tiptapEditor && !tiptapEditor.isDestroyed) {
18238
+ replaceAllTiptapFindMatches(tiptapEditor, query, replacement, options);
18239
+ }
18240
+ setSelectedIndex(0);
18241
+ };
18242
+ const close = () => {
18243
+ if (activeView === "raw") monacoEditor?.focus();
18244
+ else if (activeView === "wysiwyg" && tiptapEditor && !tiptapEditor.isDestroyed) {
18245
+ tiptapEditor.commands.focus();
18246
+ }
18247
+ onClose();
18248
+ };
18132
18249
  const resultLabel = query.trim() === "" ? "0 of 0" : matchCount === 0 ? "No results" : `${normalizeFindIndex(selectedIndex, matchCount) + 1} of ${matchCount}`;
18133
18250
  return /* @__PURE__ */ jsxs35("div", { className: "squisq-find-toolbar", role: "search", "aria-label": "Find in document", children: [
18251
+ canReplace && /* @__PURE__ */ jsx45(
18252
+ "button",
18253
+ {
18254
+ type: "button",
18255
+ className: "squisq-find-button squisq-find-replace-toggle",
18256
+ "aria-label": "Toggle replace",
18257
+ "aria-expanded": showReplace,
18258
+ "data-tooltip": "Toggle replace",
18259
+ onClick: () => onReplaceOpenChange?.(!replaceOpen),
18260
+ children: /* @__PURE__ */ jsx45(Icon, { icon: showReplace ? "fa-solid fa-chevron-down" : "fa-solid fa-chevron-right" })
18261
+ }
18262
+ ),
18134
18263
  /* @__PURE__ */ jsxs35("div", { className: "squisq-find-field", children: [
18135
18264
  /* @__PURE__ */ jsx45(Icon, { icon: "fa-solid fa-magnifying-glass" }),
18136
18265
  /* @__PURE__ */ jsx45(
@@ -18154,13 +18283,43 @@ function FindToolbar({ onClose }) {
18154
18283
  moveSelection(event.shiftKey ? -1 : 1);
18155
18284
  } else if (event.key === "Escape") {
18156
18285
  event.preventDefault();
18157
- onClose();
18286
+ close();
18158
18287
  }
18159
18288
  }
18160
18289
  }
18161
18290
  ),
18162
18291
  /* @__PURE__ */ jsx45("span", { className: "squisq-find-count", "aria-live": "polite", "aria-atomic": "true", children: resultLabel })
18163
18292
  ] }),
18293
+ /* @__PURE__ */ jsx45(
18294
+ "button",
18295
+ {
18296
+ type: "button",
18297
+ className: "squisq-find-button squisq-find-option",
18298
+ "aria-label": "Match case",
18299
+ "aria-pressed": matchCase,
18300
+ "data-tooltip": "Match case",
18301
+ onClick: () => {
18302
+ setMatchCase((value) => !value);
18303
+ setSelectedIndex(0);
18304
+ },
18305
+ children: /* @__PURE__ */ jsx45("span", { "aria-hidden": "true", children: "Aa" })
18306
+ }
18307
+ ),
18308
+ /* @__PURE__ */ jsx45(
18309
+ "button",
18310
+ {
18311
+ type: "button",
18312
+ className: "squisq-find-button squisq-find-option squisq-find-option--word",
18313
+ "aria-label": "Match whole word",
18314
+ "aria-pressed": wholeWord,
18315
+ "data-tooltip": "Match whole word",
18316
+ onClick: () => {
18317
+ setWholeWord((value) => !value);
18318
+ setSelectedIndex(0);
18319
+ },
18320
+ children: /* @__PURE__ */ jsx45("span", { "aria-hidden": "true", children: "ab" })
18321
+ }
18322
+ ),
18164
18323
  /* @__PURE__ */ jsx45(
18165
18324
  "button",
18166
18325
  {
@@ -18185,6 +18344,59 @@ function FindToolbar({ onClose }) {
18185
18344
  children: /* @__PURE__ */ jsx45(Icon, { icon: "fa-solid fa-chevron-down" })
18186
18345
  }
18187
18346
  ),
18347
+ showReplace && /* @__PURE__ */ jsxs35(Fragment14, { children: [
18348
+ /* @__PURE__ */ jsxs35("div", { className: "squisq-find-field squisq-replace-field", children: [
18349
+ /* @__PURE__ */ jsx45(Icon, { icon: "fa-solid fa-right-left" }),
18350
+ /* @__PURE__ */ jsx45(
18351
+ "input",
18352
+ {
18353
+ ref: replaceInputRef,
18354
+ type: "text",
18355
+ value: replacement,
18356
+ className: "squisq-find-input",
18357
+ "aria-label": "Replace with",
18358
+ placeholder: "Replace",
18359
+ autoComplete: "off",
18360
+ spellCheck: false,
18361
+ onChange: (event) => setReplacement(event.target.value),
18362
+ onKeyDown: (event) => {
18363
+ if (event.key === "Enter") {
18364
+ event.preventDefault();
18365
+ if (event.ctrlKey || event.metaKey) replaceAll();
18366
+ else replaceCurrent();
18367
+ } else if (event.key === "Escape") {
18368
+ event.preventDefault();
18369
+ close();
18370
+ }
18371
+ }
18372
+ }
18373
+ )
18374
+ ] }),
18375
+ /* @__PURE__ */ jsx45(
18376
+ "button",
18377
+ {
18378
+ type: "button",
18379
+ className: "squisq-find-button",
18380
+ "aria-label": "Replace",
18381
+ "data-tooltip": "Replace (Enter)",
18382
+ disabled: matchCount === 0,
18383
+ onClick: replaceCurrent,
18384
+ children: /* @__PURE__ */ jsx45(Icon, { icon: "fa-solid fa-arrow-right-long" })
18385
+ }
18386
+ ),
18387
+ /* @__PURE__ */ jsx45(
18388
+ "button",
18389
+ {
18390
+ type: "button",
18391
+ className: "squisq-find-button",
18392
+ "aria-label": "Replace all",
18393
+ "data-tooltip": "Replace all (Ctrl+Enter)",
18394
+ disabled: matchCount === 0,
18395
+ onClick: replaceAll,
18396
+ children: /* @__PURE__ */ jsx45(Icon, { icon: "fa-solid fa-angles-right" })
18397
+ }
18398
+ )
18399
+ ] }),
18188
18400
  /* @__PURE__ */ jsx45(
18189
18401
  "button",
18190
18402
  {
@@ -18192,19 +18404,81 @@ function FindToolbar({ onClose }) {
18192
18404
  className: "squisq-find-button squisq-find-close",
18193
18405
  "aria-label": "Close find",
18194
18406
  "data-tooltip": "Close find (Esc)",
18195
- onClick: onClose,
18407
+ onClick: close,
18196
18408
  children: /* @__PURE__ */ jsx45(Icon, { icon: "fa-solid fa-xmark" })
18197
18409
  }
18198
18410
  )
18199
18411
  ] });
18200
18412
  }
18413
+ function initialFindState(request, activeView, tiptapEditor, monacoEditor) {
18414
+ if (request) return request;
18415
+ let text = "";
18416
+ let index2 = 0;
18417
+ if (activeView === "raw" && monacoEditor) {
18418
+ const selection = monacoEditor.getSelection();
18419
+ const model2 = monacoEditor.getModel();
18420
+ if (selection && model2 && !selection.isEmpty()) {
18421
+ text = model2.getValueInRange(selection);
18422
+ const start = model2.getOffsetAt(selection.getStartPosition());
18423
+ index2 = nextFindIndexAfter(findTextMatches(model2.getValue(), text), start);
18424
+ }
18425
+ } else if (activeView === "wysiwyg" && tiptapEditor && !tiptapEditor.isDestroyed) {
18426
+ const { from, to } = tiptapEditor.state.selection;
18427
+ if (from !== to) {
18428
+ text = tiptapEditor.state.doc.textBetween(from, to, "\n");
18429
+ index2 = nextFindIndexAfter(findProseMirrorMatches(tiptapEditor.state.doc, text), from);
18430
+ }
18431
+ }
18432
+ if (!text.trim() || text.includes("\n") || text.length > MAX_SEEDED_QUERY) return { query: "" };
18433
+ return { query: text, occurrence: index2 };
18434
+ }
18435
+ function findMonacoRanges(model2, query, options) {
18436
+ return findTextMatches(model2.getValue(), query, options).map((match) => {
18437
+ const start = model2.getPositionAt(match.from);
18438
+ const end = model2.getPositionAt(match.to);
18439
+ return {
18440
+ startLineNumber: start.lineNumber,
18441
+ startColumn: start.column,
18442
+ endLineNumber: end.lineNumber,
18443
+ endColumn: end.column
18444
+ };
18445
+ });
18446
+ }
18447
+ function replaceMonacoMatch(editor, query, selectedIndex, replacement, options) {
18448
+ const model2 = editor.getModel();
18449
+ if (!model2) return null;
18450
+ const ranges = findMonacoRanges(model2, query, options);
18451
+ const range = ranges[normalizeFindIndex(selectedIndex, ranges.length)];
18452
+ if (!range) return null;
18453
+ const start = model2.getOffsetAt({ lineNumber: range.startLineNumber, column: range.startColumn });
18454
+ editor.pushUndoStop();
18455
+ editor.executeEdits("squisq-find", [{ range, text: replacement }]);
18456
+ editor.pushUndoStop();
18457
+ return nextFindIndexAfter(
18458
+ findTextMatches(model2.getValue(), query, options),
18459
+ start + replacement.length
18460
+ );
18461
+ }
18462
+ function replaceAllMonacoMatches(editor, query, replacement, options) {
18463
+ const model2 = editor.getModel();
18464
+ if (!model2) return 0;
18465
+ const ranges = findMonacoRanges(model2, query, options);
18466
+ if (ranges.length === 0) return 0;
18467
+ editor.pushUndoStop();
18468
+ editor.executeEdits(
18469
+ "squisq-find",
18470
+ ranges.map((range) => ({ range, text: replacement }))
18471
+ );
18472
+ editor.pushUndoStop();
18473
+ return ranges.length;
18474
+ }
18201
18475
  function monacoDecorationOptions(selected) {
18202
18476
  return {
18203
18477
  inlineClassName: selected ? "squisq-find-match squisq-find-match--selected" : "squisq-find-match"
18204
18478
  };
18205
18479
  }
18206
- function applyPreviewHighlights(root, query, selectedIndex, highlightName, selectedName) {
18207
- const ranges = collectTextRanges(root, query);
18480
+ function applyPreviewHighlights(root, query, options, selectedIndex, highlightName, selectedName, reveal) {
18481
+ const ranges = collectTextRanges(root, query, options);
18208
18482
  const selected = normalizeFindIndex(selectedIndex, ranges.length);
18209
18483
  const css = globalThis.CSS;
18210
18484
  const HighlightConstructor = globalThis.Highlight;
@@ -18212,7 +18486,7 @@ function applyPreviewHighlights(root, query, selectedIndex, highlightName, selec
18212
18486
  css.highlights.set(highlightName, new HighlightConstructor(...ranges));
18213
18487
  if (ranges.length > 0) {
18214
18488
  css.highlights.set(selectedName, new HighlightConstructor(ranges[selected]));
18215
- scrollRangeIntoView(ranges[selected]);
18489
+ if (reveal) scrollRangeIntoView(ranges[selected]);
18216
18490
  } else {
18217
18491
  css.highlights.delete(selectedName);
18218
18492
  }
@@ -18225,10 +18499,12 @@ function applyPreviewHighlights(root, query, selectedIndex, highlightName, selec
18225
18499
  };
18226
18500
  }
18227
18501
  const marks = markPreviewRanges(ranges, selected);
18228
- marks.find((mark) => mark.classList.contains("squisq-find-match--selected"))?.scrollIntoView?.({
18229
- block: "center",
18230
- inline: "nearest"
18231
- });
18502
+ if (reveal) {
18503
+ marks.find((mark) => mark.classList.contains("squisq-find-match--selected"))?.scrollIntoView?.({
18504
+ block: "center",
18505
+ inline: "nearest"
18506
+ });
18507
+ }
18232
18508
  return {
18233
18509
  count: ranges.length,
18234
18510
  cleanup: () => {
@@ -18243,7 +18519,7 @@ function applyPreviewHighlights(root, query, selectedIndex, highlightName, selec
18243
18519
  }
18244
18520
  };
18245
18521
  }
18246
- function collectTextRanges(root, query) {
18522
+ function collectTextRanges(root, query, options) {
18247
18523
  if (!query.trim()) return [];
18248
18524
  const doc = root.ownerDocument;
18249
18525
  const showText = doc.defaultView?.NodeFilter.SHOW_TEXT ?? 4;
@@ -18256,7 +18532,7 @@ function collectTextRanges(root, query) {
18256
18532
  if (parent && !parent.closest(
18257
18533
  'button, input, textarea, select, script, style, [aria-hidden="true"], [data-squisq-find-ignore]'
18258
18534
  )) {
18259
- for (const match of findTextMatches(text.data, query)) {
18535
+ for (const match of findTextMatches(text.data, query, options)) {
18260
18536
  const range = doc.createRange();
18261
18537
  range.setStart(text, match.from);
18262
18538
  range.setEnd(text, match.to);
@@ -18669,8 +18945,8 @@ function isTiptapActive(editor, id) {
18669
18945
  }
18670
18946
 
18671
18947
  // src/toolbar/sceneBlockInserts.ts
18672
- import { Fragment as Fragment14 } from "@tiptap/pm/model";
18673
- import { TextSelection } from "@tiptap/pm/state";
18948
+ import { Fragment as Fragment15 } from "@tiptap/pm/model";
18949
+ import { TextSelection as TextSelection2 } from "@tiptap/pm/state";
18674
18950
 
18675
18951
  // src/codeSnippet/codeSnippetFocus.ts
18676
18952
  var CODE_SNIPPET_FOCUS_INSERTED_META = "squisq-code-snippet-focus-inserted";
@@ -18754,16 +19030,16 @@ function insertChartBlock(editor, opts) {
18754
19030
  const cell = (type, text) => type.create(null, paragraph.create(null, text ? state.schema.text(text) : void 0));
18755
19031
  const headerRow = tableRow.create(
18756
19032
  null,
18757
- Fragment14.fromArray(opts.table.headers.map((h2) => cell(tableHeader, h2)))
19033
+ Fragment15.fromArray(opts.table.headers.map((h2) => cell(tableHeader, h2)))
18758
19034
  );
18759
19035
  const bodyRows = opts.table.rows.map(
18760
- (row) => tableRow.create(null, Fragment14.fromArray(row.map((c) => cell(tableCell, c))))
19036
+ (row) => tableRow.create(null, Fragment15.fromArray(row.map((c) => cell(tableCell, c))))
18761
19037
  );
18762
- nodes.push(table.create(null, Fragment14.fromArray([headerRow, ...bodyRows])));
19038
+ nodes.push(table.create(null, Fragment15.fromArray([headerRow, ...bodyRows])));
18763
19039
  }
18764
19040
  if (dispatch) {
18765
- tr.insert(insertPos, Fragment14.fromArray(nodes));
18766
- tr.setSelection(TextSelection.create(tr.doc, insertPos + 1));
19041
+ tr.insert(insertPos, Fragment15.fromArray(nodes));
19042
+ tr.setSelection(TextSelection2.create(tr.doc, insertPos + 1));
18767
19043
  }
18768
19044
  return true;
18769
19045
  }).run();
@@ -18783,7 +19059,7 @@ function insertTemplateHeading(editor, opts) {
18783
19059
  );
18784
19060
  if (dispatch) {
18785
19061
  tr.insert(insertPos, heading);
18786
- tr.setSelection(TextSelection.create(tr.doc, insertPos + 1));
19062
+ tr.setSelection(TextSelection2.create(tr.doc, insertPos + 1));
18787
19063
  }
18788
19064
  return true;
18789
19065
  }).run();
@@ -18807,8 +19083,8 @@ function insertLayoutBlock(editor) {
18807
19083
  });
18808
19084
  const body = paragraphType.create(null, state.schema.text("Layout"));
18809
19085
  if (dispatch) {
18810
- tr.insert(insertPos, Fragment14.fromArray([parent, child, body]));
18811
- tr.setSelection(TextSelection.create(tr.doc, insertPos + 1));
19086
+ tr.insert(insertPos, Fragment15.fromArray([parent, child, body]));
19087
+ tr.setSelection(TextSelection2.create(tr.doc, insertPos + 1));
18812
19088
  }
18813
19089
  return true;
18814
19090
  }).run();
@@ -18925,13 +19201,13 @@ ${chartTableMarkdown(entry.table)}
18925
19201
  }
18926
19202
 
18927
19203
  // src/chart/ChartTypeThumbnail.tsx
18928
- import { Fragment as Fragment15, jsx as jsx47, jsxs as jsxs36 } from "react/jsx-runtime";
19204
+ import { Fragment as Fragment16, jsx as jsx47, jsxs as jsxs36 } from "react/jsx-runtime";
18929
19205
  function ChartTypeThumbnail({ preview }) {
18930
19206
  const common = { fill: "none", stroke: "currentColor", strokeWidth: 2 };
18931
19207
  let art;
18932
19208
  switch (preview) {
18933
19209
  case "bar":
18934
- art = /* @__PURE__ */ jsxs36(Fragment15, { children: [
19210
+ art = /* @__PURE__ */ jsxs36(Fragment16, { children: [
18935
19211
  /* @__PURE__ */ jsx47("path", { d: "M14 8v48" }),
18936
19212
  /* @__PURE__ */ jsx47("rect", { x: "14", y: "12", width: "80", height: "9", fill: "currentColor", opacity: ".55" }),
18937
19213
  /* @__PURE__ */ jsx47("rect", { x: "14", y: "27", width: "52", height: "9", fill: "currentColor", opacity: ".35" }),
@@ -18939,7 +19215,7 @@ function ChartTypeThumbnail({ preview }) {
18939
19215
  ] });
18940
19216
  break;
18941
19217
  case "column":
18942
- art = /* @__PURE__ */ jsxs36(Fragment15, { children: [
19218
+ art = /* @__PURE__ */ jsxs36(Fragment16, { children: [
18943
19219
  /* @__PURE__ */ jsx47("path", { d: "M10 54h100" }),
18944
19220
  /* @__PURE__ */ jsx47("rect", { x: "22", y: "26", width: "14", height: "28", fill: "currentColor", opacity: ".45" }),
18945
19221
  /* @__PURE__ */ jsx47("rect", { x: "44", y: "14", width: "14", height: "40", fill: "currentColor", opacity: ".55" }),
@@ -18948,14 +19224,14 @@ function ChartTypeThumbnail({ preview }) {
18948
19224
  ] });
18949
19225
  break;
18950
19226
  case "pie":
18951
- art = /* @__PURE__ */ jsxs36(Fragment15, { children: [
19227
+ art = /* @__PURE__ */ jsxs36(Fragment16, { children: [
18952
19228
  /* @__PURE__ */ jsx47("circle", { cx: "60", cy: "32", r: "24" }),
18953
19229
  /* @__PURE__ */ jsx47("path", { d: "M60 32V8a24 24 0 0 1 22.6 31.9Z", fill: "currentColor", opacity: ".45" }),
18954
19230
  /* @__PURE__ */ jsx47("path", { d: "M60 32 82.6 39.9A24 24 0 0 1 46 53.4Z", fill: "currentColor", opacity: ".25" })
18955
19231
  ] });
18956
19232
  break;
18957
19233
  case "donut":
18958
- art = /* @__PURE__ */ jsxs36(Fragment15, { children: [
19234
+ art = /* @__PURE__ */ jsxs36(Fragment16, { children: [
18959
19235
  /* @__PURE__ */ jsx47("circle", { cx: "60", cy: "32", r: "24" }),
18960
19236
  /* @__PURE__ */ jsx47("circle", { cx: "60", cy: "32", r: "11" }),
18961
19237
  /* @__PURE__ */ jsx47(
@@ -18969,7 +19245,7 @@ function ChartTypeThumbnail({ preview }) {
18969
19245
  ] });
18970
19246
  break;
18971
19247
  case "line":
18972
- art = /* @__PURE__ */ jsxs36(Fragment15, { children: [
19248
+ art = /* @__PURE__ */ jsxs36(Fragment16, { children: [
18973
19249
  /* @__PURE__ */ jsx47("path", { d: "M10 54h100M10 8v46", opacity: ".4" }),
18974
19250
  /* @__PURE__ */ jsx47("path", { d: "M16 46l24-16 24 8 24-20 20 6", strokeWidth: "3" }),
18975
19251
  /* @__PURE__ */ jsx47("circle", { cx: "40", cy: "30", r: "3", fill: "currentColor" }),
@@ -18978,7 +19254,7 @@ function ChartTypeThumbnail({ preview }) {
18978
19254
  ] });
18979
19255
  break;
18980
19256
  case "area":
18981
- art = /* @__PURE__ */ jsxs36(Fragment15, { children: [
19257
+ art = /* @__PURE__ */ jsxs36(Fragment16, { children: [
18982
19258
  /* @__PURE__ */ jsx47("path", { d: "M10 54h100", opacity: ".4" }),
18983
19259
  /* @__PURE__ */ jsx47(
18984
19260
  "path",
@@ -18993,7 +19269,7 @@ function ChartTypeThumbnail({ preview }) {
18993
19269
  ] });
18994
19270
  break;
18995
19271
  case "scatter":
18996
- art = /* @__PURE__ */ jsxs36(Fragment15, { children: [
19272
+ art = /* @__PURE__ */ jsxs36(Fragment16, { children: [
18997
19273
  /* @__PURE__ */ jsx47("path", { d: "M14 8v46h92", opacity: ".4" }),
18998
19274
  /* @__PURE__ */ jsx47("circle", { cx: "30", cy: "42", r: "3.5", fill: "currentColor", opacity: ".5" }),
18999
19275
  /* @__PURE__ */ jsx47("circle", { cx: "42", cy: "30", r: "3.5", fill: "currentColor" }),
@@ -19008,7 +19284,7 @@ function ChartTypeThumbnail({ preview }) {
19008
19284
  }
19009
19285
 
19010
19286
  // src/Toolbar.tsx
19011
- import { Fragment as Fragment16, jsx as jsx48, jsxs as jsxs37 } from "react/jsx-runtime";
19287
+ import { Fragment as Fragment17, jsx as jsx48, jsxs as jsxs37 } from "react/jsx-runtime";
19012
19288
  var BLOCK_META_KEYS = new Set(Object.keys(KNOWN_BLOCK_META_KEYS));
19013
19289
  function findBlockBySourceLine(blocks, lineNumber) {
19014
19290
  for (const block of blocks) {
@@ -19043,6 +19319,9 @@ function keepBlockMetaParamString(inner) {
19043
19319
  const params = keepBlockMetaParamTokens(tokenizeAttrTokens2(inner));
19044
19320
  return params.length > 0 ? params.join(" ") : null;
19045
19321
  }
19322
+ function isApplePlatform() {
19323
+ return typeof navigator !== "undefined" && /Mac|iPhone|iPad|iPod/u.test(navigator.platform);
19324
+ }
19046
19325
  function Toolbar({
19047
19326
  className,
19048
19327
  showFiles,
@@ -19055,7 +19334,9 @@ function Toolbar({
19055
19334
  showPlayTab = true,
19056
19335
  showFormattingControls = true,
19057
19336
  showInsertControls = true,
19058
- hostMode = "document"
19337
+ hostMode = "document",
19338
+ readOnly = false,
19339
+ findShortcut = false
19059
19340
  }) {
19060
19341
  const {
19061
19342
  activeView,
@@ -19238,6 +19519,32 @@ function Toolbar({
19238
19519
  closeInsertMenu();
19239
19520
  closeEmojiPicker();
19240
19521
  }, [closeEmojiPicker, closeInsertMenu, findMode]);
19522
+ const toolbarRootRef = useRef33(null);
19523
+ const [replaceOpen, setReplaceOpen] = useState36(false);
19524
+ const [findFocusRequest, setFindFocusRequest] = useState36(0);
19525
+ useEffect28(() => {
19526
+ if (!findMode) setReplaceOpen(false);
19527
+ }, [findMode]);
19528
+ useEffect28(() => {
19529
+ if (!findShortcut || editorMode === "image") return;
19530
+ const apple = isApplePlatform();
19531
+ const onKeyDown = (event) => {
19532
+ if (event.shiftKey) return;
19533
+ const accel = event.ctrlKey || event.metaKey;
19534
+ const find = accel && !event.altKey && event.code === "KeyF";
19535
+ const replace = apple ? event.metaKey && event.altKey && event.code === "KeyF" : event.ctrlKey && !event.altKey && event.code === "KeyH";
19536
+ if (!find && !replace) return;
19537
+ const shell = toolbarRootRef.current?.closest(".squisq-editor-shell");
19538
+ if (!shell || !(event.target instanceof Node) || !shell.contains(event.target)) return;
19539
+ event.preventDefault();
19540
+ event.stopPropagation();
19541
+ if (replace && !readOnly) setReplaceOpen(true);
19542
+ setFindMode(true);
19543
+ setFindFocusRequest((request) => request + 1);
19544
+ };
19545
+ window.addEventListener("keydown", onKeyDown, true);
19546
+ return () => window.removeEventListener("keydown", onKeyDown, true);
19547
+ }, [editorMode, findShortcut, readOnly, setFindMode]);
19241
19548
  const actionsLaneShown = !findMode && activeView !== "preview" && !isCodeMode && (showFormattingControls || showInsertControls);
19242
19549
  const collapsed = new Set(actionsLaneShown && collapsedKey ? collapsedKey.split("|") : []);
19243
19550
  const clippedContextual = new Set(
@@ -20393,6 +20700,7 @@ ${TASK_LIST_MARKDOWN}
20393
20700
  return /* @__PURE__ */ jsxs37(
20394
20701
  "div",
20395
20702
  {
20703
+ ref: toolbarRootRef,
20396
20704
  className: `squisq-toolbar${findMode ? " squisq-toolbar--find" : ""} ${className || ""}`,
20397
20705
  role: "toolbar",
20398
20706
  "aria-label": findMode ? "Find toolbar" : showFormattingControls ? "Formatting toolbar" : "Editor toolbar",
@@ -20426,7 +20734,16 @@ ${TASK_LIST_MARKDOWN}
20426
20734
  ),
20427
20735
  !findMode && slotLeft,
20428
20736
  /* @__PURE__ */ jsx48(EditorViewTabs, { showPlayTab, hostMode }),
20429
- findMode ? /* @__PURE__ */ jsx48(FindToolbar, { onClose: () => setFindMode(false) }) : slotAfterTabs,
20737
+ findMode ? /* @__PURE__ */ jsx48(
20738
+ FindToolbar,
20739
+ {
20740
+ onClose: () => setFindMode(false),
20741
+ allowReplace: !readOnly,
20742
+ replaceOpen: replaceOpen && !readOnly,
20743
+ onReplaceOpenChange: setReplaceOpen,
20744
+ focusRequest: findFocusRequest
20745
+ }
20746
+ ) : slotAfterTabs,
20430
20747
  actionsLaneShown && /* @__PURE__ */ jsxs37("div", { className: "squisq-toolbar-actions", ref: actionsRef, children: [
20431
20748
  showFormattingControls && groups.map((group) => /* @__PURE__ */ jsxs37(
20432
20749
  "div",
@@ -20835,7 +21152,7 @@ ${TASK_LIST_MARKDOWN}
20835
21152
  ]
20836
21153
  }
20837
21154
  ),
20838
- showBlockSectionInOverflow && /* @__PURE__ */ jsxs37(Fragment16, { children: [
21155
+ showBlockSectionInOverflow && /* @__PURE__ */ jsxs37(Fragment17, { children: [
20839
21156
  /* @__PURE__ */ jsx48(
20840
21157
  "div",
20841
21158
  {
@@ -20870,7 +21187,7 @@ ${TASK_LIST_MARKDOWN}
20870
21187
  accentColor: previewSettings?.activeTheme.colors.primary
20871
21188
  }
20872
21189
  ) }),
20873
- showFormattingControls && isInTable && clippedContextual.has("table") && /* @__PURE__ */ jsxs37(Fragment16, { children: [
21190
+ showFormattingControls && isInTable && clippedContextual.has("table") && /* @__PURE__ */ jsxs37(Fragment17, { children: [
20874
21191
  /* @__PURE__ */ jsx48(
20875
21192
  "div",
20876
21193
  {
@@ -20927,7 +21244,7 @@ ${TASK_LIST_MARKDOWN}
20927
21244
  !findMode && slotAfterActions,
20928
21245
  isCodeMode && !findMode && /* @__PURE__ */ jsx48("div", { style: { flex: 1 } }),
20929
21246
  versioning && !isCodeMode && /* @__PURE__ */ jsx48(VersionHistoryPanel, {}),
20930
- allowRecording && !isCodeMode && mediaProvider && /* @__PURE__ */ jsxs37(Fragment16, { children: [
21247
+ allowRecording && !isCodeMode && mediaProvider && /* @__PURE__ */ jsxs37(Fragment17, { children: [
20931
21248
  /* @__PURE__ */ jsx48(RecorderEntry, { open: recorderOpen, onOpenChange: setRecorderOpen, showTrigger: false }),
20932
21249
  /* @__PURE__ */ jsx48(
20933
21250
  RecorderEntry,
@@ -21025,7 +21342,7 @@ ${TASK_LIST_MARKDOWN}
21025
21342
  },
21026
21343
  role: "menu",
21027
21344
  children: [
21028
- showConvertActions && /* @__PURE__ */ jsxs37(Fragment16, { children: [
21345
+ showConvertActions && /* @__PURE__ */ jsxs37(Fragment17, { children: [
21029
21346
  /* @__PURE__ */ jsx48("div", { className: "squisq-insert-menu-header", children: "Convert" }),
21030
21347
  CONVERT_BUTTONS.map((btn) => {
21031
21348
  const label = btn.id === "table" ? "Table" : "Task List";
@@ -26921,7 +27238,7 @@ function setMermaidFlowchartDirection(source, direction) {
26921
27238
 
26922
27239
  // src/mermaid/MermaidDiagramWidget.tsx
26923
27240
  import { DEFAULT_THEME as DEFAULT_THEME3 } from "@bendyline/squisq/doc";
26924
- import { Fragment as Fragment17, jsx as jsx56, jsxs as jsxs44 } from "react/jsx-runtime";
27241
+ import { Fragment as Fragment18, jsx as jsx56, jsxs as jsxs44 } from "react/jsx-runtime";
26925
27242
  var MIN_DIAGRAM_HEIGHT2 = 160;
26926
27243
  var DEFAULT_DIAGRAM_HEIGHT2 = 420;
26927
27244
  var DIRECTION_PICKER_WIDTH = 344;
@@ -27583,7 +27900,7 @@ function MermaidPropertiesPalette({
27583
27900
  }
27584
27901
  ),
27585
27902
  /* @__PURE__ */ jsx56("span", { children: property.label })
27586
- ] }) : /* @__PURE__ */ jsxs44(Fragment17, { children: [
27903
+ ] }) : /* @__PURE__ */ jsxs44(Fragment18, { children: [
27587
27904
  /* @__PURE__ */ jsx56("span", { children: property.label }),
27588
27905
  property.type === "select" ? /* @__PURE__ */ jsx56(
27589
27906
  "select",
@@ -29840,7 +30157,7 @@ var VideoEmbedExtension = Extension11.create({
29840
30157
  });
29841
30158
 
29842
30159
  // src/videoEmbed/videoEmbedPaste.ts
29843
- import { TextSelection as TextSelection2 } from "@tiptap/pm/state";
30160
+ import { TextSelection as TextSelection3 } from "@tiptap/pm/state";
29844
30161
  import { parseVideoEmbedInput as parseVideoEmbedInput3 } from "@bendyline/squisq/markdown";
29845
30162
  function looksLikeEmbedCode(text) {
29846
30163
  return /^<(?!https?:)/i.test(text) && /<iframe\b/i.test(text);
@@ -29862,7 +30179,7 @@ function insertTopLevelBlock(state, node2) {
29862
30179
  tr.insert(start, node2);
29863
30180
  }
29864
30181
  }
29865
- tr.setSelection(TextSelection2.near(tr.doc.resolve(start + node2.nodeSize - 1), -1));
30182
+ tr.setSelection(TextSelection3.near(tr.doc.resolve(start + node2.nodeSize - 1), -1));
29866
30183
  return tr.scrollIntoView();
29867
30184
  }
29868
30185
  function pasteVideoEmbedCode(view, text) {
@@ -31106,7 +31423,7 @@ function applyTimelineCommand(editor, blockId, command) {
31106
31423
  }
31107
31424
 
31108
31425
  // src/timeline/TimelineEditorWidget.tsx
31109
- import { Fragment as Fragment18, jsx as jsx61, jsxs as jsxs48 } from "react/jsx-runtime";
31426
+ import { Fragment as Fragment19, jsx as jsx61, jsxs as jsxs48 } from "react/jsx-runtime";
31110
31427
  var clamp01 = (value) => Math.max(0, Math.min(1, value));
31111
31428
  function TimelineEditorWidget({ editor, blockId }) {
31112
31429
  const view = useTimelineData(editor, blockId);
@@ -31145,14 +31462,12 @@ function TimelineEditorWidget({ editor, blockId }) {
31145
31462
  const normalized = asciiTimelineToTemplateData(view.timeline).tracks;
31146
31463
  return view.timeline.tracks.flatMap((track, trackIndex) => {
31147
31464
  const templateTrack = normalized[trackIndex];
31148
- return track.events.map(
31149
- (event, eventIndex) => ({
31150
- event,
31151
- trackId: track.id,
31152
- trackIndex,
31153
- position: templateTrack?.events[eventIndex]?.position ?? 0
31154
- })
31155
- );
31465
+ return track.events.map((event, eventIndex) => ({
31466
+ event,
31467
+ trackId: track.id,
31468
+ trackIndex,
31469
+ position: templateTrack?.events[eventIndex]?.position ?? 0
31470
+ }));
31156
31471
  });
31157
31472
  }, [view]);
31158
31473
  const displayedPositioned = useMemo37(
@@ -31329,7 +31644,7 @@ function TimelineEditorWidget({ editor, blockId }) {
31329
31644
  onFinish: () => setEditingTrackId(null)
31330
31645
  }
31331
31646
  ),
31332
- editable ? /* @__PURE__ */ jsxs48(Fragment18, { children: [
31647
+ editable ? /* @__PURE__ */ jsxs48(Fragment19, { children: [
31333
31648
  /* @__PURE__ */ jsx61(
31334
31649
  "button",
31335
31650
  {
@@ -32295,7 +32610,7 @@ function normalizeMalformedAssetUrl(src) {
32295
32610
  }
32296
32611
 
32297
32612
  // src/ImageNodeView.tsx
32298
- import { Fragment as Fragment19, jsx as jsx63, jsxs as jsxs50 } from "react/jsx-runtime";
32613
+ import { Fragment as Fragment20, jsx as jsx63, jsxs as jsxs50 } from "react/jsx-runtime";
32299
32614
  function ImageComponent({ node: node2, selected, editor, updateAttributes }) {
32300
32615
  const { src, alt, title, width } = node2.attrs;
32301
32616
  const { mediaProvider, imageDisplayMode, openImageEdit, mediaRevision } = useEditorContext();
@@ -32422,11 +32737,11 @@ function ImageComponent({ node: node2, selected, editor, updateAttributes }) {
32422
32737
  strokeLinecap: "round",
32423
32738
  strokeLinejoin: "round",
32424
32739
  "aria-hidden": "true",
32425
- children: failed ? /* @__PURE__ */ jsxs50(Fragment19, { children: [
32740
+ children: failed ? /* @__PURE__ */ jsxs50(Fragment20, { children: [
32426
32741
  /* @__PURE__ */ jsx63("rect", { x: "3", y: "3", width: "18", height: "18", rx: "3" }),
32427
32742
  /* @__PURE__ */ jsx63("circle", { cx: "8", cy: "8", r: "1.5" }),
32428
32743
  /* @__PURE__ */ jsx63("path", { d: "m4 17 5-5 4 4 3-3 4 4M3 3l18 18" })
32429
- ] }) : /* @__PURE__ */ jsxs50(Fragment19, { children: [
32744
+ ] }) : /* @__PURE__ */ jsxs50(Fragment20, { children: [
32430
32745
  /* @__PURE__ */ jsx63("path", { d: "M6 3h12M6 21h12M7 3v4c0 2 3 3 5 5-2 2-5 3-5 5v4M17 3v4c0 2-3 3-5 5 2 2 5 3 5 5v4" }),
32431
32746
  /* @__PURE__ */ jsx63("path", { d: "M9 6h6M9 18h6" })
32432
32747
  ] })
@@ -32477,7 +32792,7 @@ function ImageComponent({ node: node2, selected, editor, updateAttributes }) {
32477
32792
  ]
32478
32793
  }
32479
32794
  ),
32480
- showResize && /* @__PURE__ */ jsxs50(Fragment19, { children: [
32795
+ showResize && /* @__PURE__ */ jsxs50(Fragment20, { children: [
32481
32796
  /* @__PURE__ */ jsx63(
32482
32797
  "span",
32483
32798
  {
@@ -32609,7 +32924,7 @@ function usePlaybackSrc(src, kind, fx) {
32609
32924
  }
32610
32925
 
32611
32926
  // src/mediaEdit/MediaEditButton.tsx
32612
- import { Fragment as Fragment20, jsx as jsx64, jsxs as jsxs51 } from "react/jsx-runtime";
32927
+ import { Fragment as Fragment21, jsx as jsx64, jsxs as jsxs51 } from "react/jsx-runtime";
32613
32928
  function MediaEditButton({ src, kind, fx, className }) {
32614
32929
  const editor = useEditorContextOptional();
32615
32930
  const manager = editor?.mediaEditRenders;
@@ -32630,7 +32945,7 @@ function MediaEditButton({ src, kind, fx, className }) {
32630
32945
  onClick: () => editor.openMediaEdit({ src, kind }),
32631
32946
  children: [
32632
32947
  kind === "video" ? "Edit clip" : "Edit audio",
32633
- progress && /* @__PURE__ */ jsxs51(Fragment20, { children: [
32948
+ progress && /* @__PURE__ */ jsxs51(Fragment21, { children: [
32634
32949
  /* @__PURE__ */ jsx64("span", { className: "squisq-media-edit-button__spinner", "aria-hidden": "true" }),
32635
32950
  /* @__PURE__ */ jsxs51("span", { className: "squisq-media-edit-button__progress", children: [
32636
32951
  /* @__PURE__ */ jsx64("span", { className: "squisq-sr-only", children: ", processing " }),
@@ -34469,7 +34784,7 @@ function usePreviewProjection(doc, transformStyle, workspaceContainer, documentT
34469
34784
  }
34470
34785
 
34471
34786
  // src/InlinePreviewGutter.tsx
34472
- import { Fragment as Fragment21, jsx as jsx68, jsxs as jsxs55 } from "react/jsx-runtime";
34787
+ import { Fragment as Fragment22, jsx as jsx68, jsxs as jsxs55 } from "react/jsx-runtime";
34473
34788
  function isAnnotated(block) {
34474
34789
  const annotation = block.sourceHeading?.templateAnnotation;
34475
34790
  if (!annotation) return false;
@@ -34855,7 +35170,7 @@ function InlinePreviewGutter({
34855
35170
  children: [
34856
35171
  /* @__PURE__ */ jsxs55("div", { className: "squisq-inline-preview-card-label", children: [
34857
35172
  /* @__PURE__ */ jsx68("span", { className: "squisq-inline-preview-card-template", children: templateLabel(item.template) }),
34858
- item.headingText && /* @__PURE__ */ jsxs55(Fragment21, { children: [
35173
+ item.headingText && /* @__PURE__ */ jsxs55(Fragment22, { children: [
34859
35174
  /* @__PURE__ */ jsx68("span", { className: "squisq-inline-preview-card-sep", children: "\u2014" }),
34860
35175
  /* @__PURE__ */ jsx68("span", { className: "squisq-inline-preview-card-title", children: item.headingText })
34861
35176
  ] })
@@ -35677,7 +35992,7 @@ function CodeContextSectionView({
35677
35992
  }
35678
35993
 
35679
35994
  // src/codeContext/CodeContextZones.tsx
35680
- import { Fragment as Fragment22, jsx as jsx71 } from "react/jsx-runtime";
35995
+ import { Fragment as Fragment23, jsx as jsx71 } from "react/jsx-runtime";
35681
35996
  function CodeContextZones({ options }) {
35682
35997
  const { monacoEditor } = useEditorContext();
35683
35998
  const [manager, setManager] = useState65(null);
@@ -35746,7 +36061,7 @@ function CodeContextZones({ options }) {
35746
36061
  [monacoEditor]
35747
36062
  );
35748
36063
  if (!manager) return null;
35749
- return /* @__PURE__ */ jsx71(Fragment22, { children: resolved.map(({ section }) => {
36064
+ return /* @__PURE__ */ jsx71(Fragment23, { children: resolved.map(({ section }) => {
35750
36065
  const domNode = manager.getDomNode(section.id);
35751
36066
  if (!domNode) return null;
35752
36067
  return createPortal14(
@@ -36317,7 +36632,7 @@ function timelineBars(clips) {
36317
36632
  // src/TimelineItemMenu.tsx
36318
36633
  import { useEffect as useEffect56, useLayoutEffect as useLayoutEffect11, useRef as useRef54, useState as useState67 } from "react";
36319
36634
  import { createPortal as createPortal15 } from "react-dom";
36320
- import { Fragment as Fragment23, jsx as jsx73, jsxs as jsxs59 } from "react/jsx-runtime";
36635
+ import { Fragment as Fragment24, jsx as jsx73, jsxs as jsxs59 } from "react/jsx-runtime";
36321
36636
  function TimelineItemMenu({
36322
36637
  anchor,
36323
36638
  target,
@@ -36390,7 +36705,7 @@ function TimelineItemMenu({
36390
36705
  onStartTime: onBlockStartTime,
36391
36706
  onTransition: onBlockTransition
36392
36707
  }
36393
- ) : /* @__PURE__ */ jsxs59(Fragment23, { children: [
36708
+ ) : /* @__PURE__ */ jsxs59(Fragment24, { children: [
36394
36709
  /* @__PURE__ */ jsx73(VideoMenu, { target, onPatch: onVideoPatch }),
36395
36710
  onEditMedia && /* @__PURE__ */ jsx73(
36396
36711
  "button",
@@ -36536,7 +36851,7 @@ function VideoMenu({
36536
36851
  }
36537
36852
  )
36538
36853
  ] }),
36539
- placed && /* @__PURE__ */ jsxs59(Fragment23, { children: [
36854
+ placed && /* @__PURE__ */ jsxs59(Fragment24, { children: [
36540
36855
  /* @__PURE__ */ jsxs59("label", { className: "squisq-timeline-item-menu-check", children: [
36541
36856
  /* @__PURE__ */ jsx73(
36542
36857
  "input",
@@ -36554,7 +36869,7 @@ function VideoMenu({
36554
36869
  ),
36555
36870
  /* @__PURE__ */ jsx73("span", { children: "Lock to block" })
36556
36871
  ] }),
36557
- placement === "picture-in-picture" && /* @__PURE__ */ jsxs59(Fragment23, { children: [
36872
+ placement === "picture-in-picture" && /* @__PURE__ */ jsxs59(Fragment24, { children: [
36558
36873
  /* @__PURE__ */ jsxs59("label", { className: "squisq-timeline-item-menu-field", children: [
36559
36874
  /* @__PURE__ */ jsx73("span", { className: "squisq-timeline-item-menu-label", children: "PIP size" }),
36560
36875
  /* @__PURE__ */ jsxs59(
@@ -39312,7 +39627,7 @@ function collectSlideshowDataSources(doc) {
39312
39627
  }
39313
39628
 
39314
39629
  // src/slideshow/SlideshowDataGrid.tsx
39315
- import { Fragment as Fragment24, jsx as jsx82 } from "react/jsx-runtime";
39630
+ import { Fragment as Fragment25, jsx as jsx82 } from "react/jsx-runtime";
39316
39631
  var EMPTY_CONTEXT = {
39317
39632
  container: null,
39318
39633
  mediaRevision: 0,
@@ -39442,7 +39757,7 @@ function SlideshowDataGridRenderer({
39442
39757
  const initialView = ready?.initialView ?? EMPTY_VIEW;
39443
39758
  const [view, setView] = useState72(initialView);
39444
39759
  useEffect62(() => setView(initialView), [initialView, provider]);
39445
- if (!provider || !ingest || !gridModule) return /* @__PURE__ */ jsx82(Fragment24, { children: fallback });
39760
+ if (!provider || !ingest || !gridModule) return /* @__PURE__ */ jsx82(Fragment25, { children: fallback });
39446
39761
  const { style } = layer.content;
39447
39762
  const rowHeight = Math.max(32, style.fontSize * 2.1);
39448
39763
  const footerHeight = Math.max(28, style.fontSize * 1.5);
@@ -40325,7 +40640,7 @@ ${formatSize(entry.size)}`,
40325
40640
 
40326
40641
  // src/DropZoneOverlay.tsx
40327
40642
  import { useState as useState75 } from "react";
40328
- import { Fragment as Fragment25, jsx as jsx85, jsxs as jsxs69 } from "react/jsx-runtime";
40643
+ import { Fragment as Fragment26, jsx as jsx85, jsxs as jsxs69 } from "react/jsx-runtime";
40329
40644
  function DropZoneOverlay({
40330
40645
  dragContentType,
40331
40646
  zoneProps,
@@ -40346,7 +40661,7 @@ function DropZoneOverlay({
40346
40661
  variant: "media"
40347
40662
  }
40348
40663
  ),
40349
- showText && /* @__PURE__ */ jsxs69(Fragment25, { children: [
40664
+ showText && /* @__PURE__ */ jsxs69(Fragment26, { children: [
40350
40665
  /* @__PURE__ */ jsx85(
40351
40666
  DropZone,
40352
40667
  {
@@ -40841,7 +41156,7 @@ function centeredCrop(ratio, frameWidth, frameHeight) {
40841
41156
  }
40842
41157
 
40843
41158
  // src/mediaEdit/MediaEditAudioSection.tsx
40844
- import { Fragment as Fragment26, jsx as jsx89, jsxs as jsxs71 } from "react/jsx-runtime";
41159
+ import { Fragment as Fragment27, jsx as jsx89, jsxs as jsxs71 } from "react/jsx-runtime";
40845
41160
  var STAGES = [
40846
41161
  {
40847
41162
  id: "highpass",
@@ -41148,7 +41463,7 @@ function MediaEditAudioSection({
41148
41463
  children: previewing ? "Rendering preview\u2026" : preview ? "Update preview" : "Create preview"
41149
41464
  }
41150
41465
  ) }),
41151
- preview != null && player.duration > 0 && /* @__PURE__ */ jsxs71(Fragment26, { children: [
41466
+ preview != null && player.duration > 0 && /* @__PURE__ */ jsxs71(Fragment27, { children: [
41152
41467
  /* @__PURE__ */ jsxs71("div", { className: "squisq-media-edit-playback", "data-playing": player.playing ?? void 0, children: [
41153
41468
  /* @__PURE__ */ jsx89("span", { className: "squisq-media-edit-playback__label", children: player.playing ? `${player.playing === "original" ? "Original" : "Processed"} from ${Math.round(preview.startSec)} s` : "Stopped" }),
41154
41469
  /* @__PURE__ */ jsx89(
@@ -41494,7 +41809,7 @@ function MediaEditFrameSection({ item, draft, onChange }) {
41494
41809
  }
41495
41810
 
41496
41811
  // src/mediaEdit/MediaEditModal.tsx
41497
- import { Fragment as Fragment27, jsx as jsx92, jsxs as jsxs74 } from "react/jsx-runtime";
41812
+ import { Fragment as Fragment28, jsx as jsx92, jsxs as jsxs74 } from "react/jsx-runtime";
41498
41813
  var TABS = [
41499
41814
  { id: "audio", label: "Audio cleanup" },
41500
41815
  { id: "timing", label: "Timing" },
@@ -41529,16 +41844,16 @@ function RenderStatusText({
41529
41844
  }) {
41530
41845
  switch (status.state) {
41531
41846
  case "ready":
41532
- return /* @__PURE__ */ jsx92(Fragment27, { children: "Processed audio is in use." });
41847
+ return /* @__PURE__ */ jsx92(Fragment28, { children: "Processed audio is in use." });
41533
41848
  case "queued":
41534
- return /* @__PURE__ */ jsx92(Fragment27, { children: "Waiting to process\u2026" });
41849
+ return /* @__PURE__ */ jsx92(Fragment28, { children: "Waiting to process\u2026" });
41535
41850
  case "rendering":
41536
- return /* @__PURE__ */ jsxs74(Fragment27, { children: [
41851
+ return /* @__PURE__ */ jsxs74(Fragment28, { children: [
41537
41852
  "Processing\u2026 ",
41538
41853
  percent(status)
41539
41854
  ] });
41540
41855
  case "failed":
41541
- return /* @__PURE__ */ jsxs74(Fragment27, { children: [
41856
+ return /* @__PURE__ */ jsxs74(Fragment28, { children: [
41542
41857
  "Processing failed: ",
41543
41858
  status.error,
41544
41859
  " ",
@@ -41626,7 +41941,7 @@ function MediaEditModal({ target, onClose }) {
41626
41941
  }
41627
41942
  )
41628
41943
  ] }),
41629
- !item ? /* @__PURE__ */ jsx92("p", { className: "squisq-media-edit-modal__empty", children: "This clip is no longer in the document." }) : !mediaEditRenders ? /* @__PURE__ */ jsx92("p", { className: "squisq-media-edit-modal__empty", children: "Media editing needs a media folder for this document." }) : /* @__PURE__ */ jsxs74(Fragment27, { children: [
41944
+ !item ? /* @__PURE__ */ jsx92("p", { className: "squisq-media-edit-modal__empty", children: "This clip is no longer in the document." }) : !mediaEditRenders ? /* @__PURE__ */ jsx92("p", { className: "squisq-media-edit-modal__empty", children: "Media editing needs a media folder for this document." }) : /* @__PURE__ */ jsxs74(Fragment28, { children: [
41630
41945
  /* @__PURE__ */ jsx92("div", { className: "squisq-media-edit-tabs", role: "tablist", "aria-label": "Edit sections", children: tabs.map((tab, index2) => {
41631
41946
  const selected = tab.id === activeTab;
41632
41947
  const edited = tabHasEdits(tab.id, draft);
@@ -41989,7 +42304,7 @@ import {
41989
42304
  createMediaEditRenderManager,
41990
42305
  useProcessedAudio as useProcessedAudio4
41991
42306
  } from "@bendyline/squisq-video-react/media-edit";
41992
- import { Fragment as Fragment28, jsx as jsx93, jsxs as jsxs75 } from "react/jsx-runtime";
42307
+ import { Fragment as Fragment29, jsx as jsx93, jsxs as jsxs75 } from "react/jsx-runtime";
41993
42308
  function EditorShell({
41994
42309
  initialMarkdown = "",
41995
42310
  initialView = "wysiwyg",
@@ -42045,6 +42360,8 @@ function EditorShell({
42045
42360
  language,
42046
42361
  findMode,
42047
42362
  onFindModeChange,
42363
+ findRequest,
42364
+ findShortcut = false,
42048
42365
  mentionProvider,
42049
42366
  proofing = null,
42050
42367
  proofingDefaultEnabled = true,
@@ -42128,6 +42445,7 @@ function EditorShell({
42128
42445
  language,
42129
42446
  findMode,
42130
42447
  onFindModeChange,
42448
+ findRequest,
42131
42449
  inlinePreview,
42132
42450
  showStatusBar,
42133
42451
  outline,
@@ -42176,6 +42494,7 @@ function EditorShell({
42176
42494
  thinMargins,
42177
42495
  writeCanvasSettings,
42178
42496
  readOnly,
42497
+ findShortcut,
42179
42498
  imageSrc,
42180
42499
  imageAlt,
42181
42500
  imageMode,
@@ -42199,7 +42518,7 @@ function UseModeToolbarControls({
42199
42518
  }) {
42200
42519
  const printMode = usePrintMode();
42201
42520
  if (printMode.active) return /* @__PURE__ */ jsx93(PrintPreviewToolbar, {});
42202
- return /* @__PURE__ */ jsxs75(Fragment28, { children: [
42521
+ return /* @__PURE__ */ jsxs75(Fragment29, { children: [
42203
42522
  /* @__PURE__ */ jsx93(PreviewToolbarControls, { summarizationDesigner }),
42204
42523
  /* @__PURE__ */ jsx93(PresentationModeControl, {}),
42205
42524
  allowPrint && /* @__PURE__ */ jsx93(PrintModeControl, {})
@@ -42259,6 +42578,7 @@ function EditorShellInner({
42259
42578
  thinMargins,
42260
42579
  writeCanvasSettings,
42261
42580
  readOnly,
42581
+ findShortcut,
42262
42582
  imageSrc,
42263
42583
  imageAlt,
42264
42584
  imageMode,
@@ -42636,7 +42956,9 @@ function EditorShellInner({
42636
42956
  showPlayTab,
42637
42957
  showFormattingControls,
42638
42958
  showInsertControls,
42639
- hostMode
42959
+ hostMode,
42960
+ readOnly,
42961
+ findShortcut
42640
42962
  }
42641
42963
  ) }),
42642
42964
  /* @__PURE__ */ jsxs75(