quoin-editor 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/ai.cjs +168 -249
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +37 -121
- package/dist/ai.js.map +1 -1
- package/dist/catalogue.cjs +28 -43
- package/dist/catalogue.cjs.map +1 -1
- package/dist/catalogue.js +20 -37
- package/dist/catalogue.js.map +1 -1
- package/dist/{chunk-DUE3HCZD.js → chunk-2EQ6FKSK.js} +19 -28
- package/dist/chunk-2EQ6FKSK.js.map +1 -0
- package/dist/{chunk-RJRX34BZ.js → chunk-3BXUGX5F.js} +4 -18
- package/dist/chunk-3BXUGX5F.js.map +1 -0
- package/dist/chunk-3QRVAI53.cjs +27 -0
- package/dist/chunk-3QRVAI53.cjs.map +1 -0
- package/dist/{chunk-U3LOLYAU.js → chunk-7FAVFJAS.js} +4 -10
- package/dist/chunk-7FAVFJAS.js.map +1 -0
- package/dist/{chunk-6V6GGBDK.cjs → chunk-7SVKLWDT.cjs} +24 -31
- package/dist/chunk-7SVKLWDT.cjs.map +1 -0
- package/dist/{chunk-EH5KXQXY.cjs → chunk-A6PGQVTR.cjs} +36 -20
- package/dist/chunk-A6PGQVTR.cjs.map +1 -0
- package/dist/{chunk-P6KYXFZC.cjs → chunk-ACSEYJJF.cjs} +426 -534
- package/dist/chunk-ACSEYJJF.cjs.map +1 -0
- package/dist/{chunk-4SLJNZSM.cjs → chunk-AIS37SL2.cjs} +201 -198
- package/dist/chunk-AIS37SL2.cjs.map +1 -0
- package/dist/{chunk-X4HDKFW5.cjs → chunk-DTQFYHDJ.cjs} +56 -105
- package/dist/chunk-DTQFYHDJ.cjs.map +1 -0
- package/dist/{chunk-O4Z2WMFF.js → chunk-HDJ653LM.js} +25 -18
- package/dist/chunk-HDJ653LM.js.map +1 -0
- package/dist/chunk-HQ43EIYO.cjs +94 -0
- package/dist/chunk-HQ43EIYO.cjs.map +1 -0
- package/dist/{chunk-6NULZPVC.js → chunk-HTLWPSMU.js} +8 -61
- package/dist/chunk-HTLWPSMU.js.map +1 -0
- package/dist/{chunk-ADSJ42DO.js → chunk-HWEK7EX5.js} +17 -69
- package/dist/chunk-HWEK7EX5.js.map +1 -0
- package/dist/{chunk-623AOJM2.js → chunk-ITXCE6KL.js} +7 -25
- package/dist/chunk-ITXCE6KL.js.map +1 -0
- package/dist/{chunk-AUOEM3SF.cjs → chunk-IXVGHH7F.cjs} +102 -155
- package/dist/chunk-IXVGHH7F.cjs.map +1 -0
- package/dist/{chunk-NEZJ7ZP5.js → chunk-JZJIWRF3.js} +4 -8
- package/dist/chunk-JZJIWRF3.js.map +1 -0
- package/dist/{chunk-C23RQVRK.js → chunk-KSF2HILJ.js} +66 -216
- package/dist/chunk-KSF2HILJ.js.map +1 -0
- package/dist/{chunk-OBMBSU2S.js → chunk-L4D23LM2.js} +5 -184
- package/dist/chunk-L4D23LM2.js.map +1 -0
- package/dist/{chunk-4XFXB37X.js → chunk-L6OW2FL3.js} +7 -90
- package/dist/chunk-L6OW2FL3.js.map +1 -0
- package/dist/chunk-LE5XMIFJ.cjs +4 -3
- package/dist/chunk-LE5XMIFJ.cjs.map +1 -1
- package/dist/{chunk-5MAYUGTE.cjs → chunk-LY2D45F2.cjs} +233 -363
- package/dist/chunk-LY2D45F2.cjs.map +1 -0
- package/dist/{chunk-VCLL5C7J.js → chunk-MGMA5PEL.js} +14 -57
- package/dist/chunk-MGMA5PEL.js.map +1 -0
- package/dist/chunk-MQUCCSWG.js +2 -3
- package/dist/chunk-MQUCCSWG.js.map +1 -1
- package/dist/chunk-NO3KTZDY.cjs +33 -0
- package/dist/chunk-NO3KTZDY.cjs.map +1 -0
- package/dist/{chunk-TLGX43P6.cjs → chunk-OM7E43ZN.cjs} +89 -86
- package/dist/chunk-OM7E43ZN.cjs.map +1 -0
- package/dist/{chunk-JHQUHFLX.js → chunk-PJCHSHM3.js} +38 -120
- package/dist/chunk-PJCHSHM3.js.map +1 -0
- package/dist/{chunk-EPARJI4V.js → chunk-QC35D2AU.js} +107 -262
- package/dist/chunk-QC35D2AU.js.map +1 -0
- package/dist/{chunk-CW3AFJBR.cjs → chunk-QEMGOL5L.cjs} +1302 -1773
- package/dist/chunk-QEMGOL5L.cjs.map +1 -0
- package/dist/chunk-QWS7KH3K.cjs +483 -0
- package/dist/chunk-QWS7KH3K.cjs.map +1 -0
- package/dist/{chunk-IQBMAE3F.js → chunk-RHQPAW4W.js} +34 -92
- package/dist/chunk-RHQPAW4W.js.map +1 -0
- package/dist/chunk-RIIXJWBR.cjs +24 -0
- package/dist/chunk-RIIXJWBR.cjs.map +1 -0
- package/dist/{chunk-VRS6WCEK.js → chunk-SAEQMDAU.js} +60 -167
- package/dist/chunk-SAEQMDAU.js.map +1 -0
- package/dist/chunk-SKZC4K5S.cjs +612 -0
- package/dist/chunk-SKZC4K5S.cjs.map +1 -0
- package/dist/{chunk-N4FGA3H4.js → chunk-TBCHYHNU.js} +38 -105
- package/dist/chunk-TBCHYHNU.js.map +1 -0
- package/dist/{chunk-OSHZQR3W.js → chunk-TNN6Z52D.js} +13 -45
- package/dist/chunk-TNN6Z52D.js.map +1 -0
- package/dist/{chunk-YBMUEEM5.js → chunk-TYZSB7JT.js} +4 -8
- package/dist/chunk-TYZSB7JT.js.map +1 -0
- package/dist/{chunk-ZKVOS57Q.cjs → chunk-VFSVN5IQ.cjs} +495 -551
- package/dist/chunk-VFSVN5IQ.cjs.map +1 -0
- package/dist/{chunk-FDRUAL3Z.cjs → chunk-WDO6DBYU.cjs} +90 -153
- package/dist/chunk-WDO6DBYU.cjs.map +1 -0
- package/dist/{chunk-WEYDDIBQ.cjs → chunk-WHV5ZSIO.cjs} +36 -64
- package/dist/chunk-WHV5ZSIO.cjs.map +1 -0
- package/dist/{chunk-T43RZTUT.js → chunk-XJDPQFPU.js} +693 -1247
- package/dist/chunk-XJDPQFPU.js.map +1 -0
- package/dist/{chunk-BQANU5BH.cjs → chunk-ZTLYHRZT.cjs} +34 -44
- package/dist/chunk-ZTLYHRZT.cjs.map +1 -0
- package/dist/chunk-ZWB7SZVI.cjs +200 -0
- package/dist/chunk-ZWB7SZVI.cjs.map +1 -0
- package/dist/comments.cjs +209 -290
- package/dist/comments.cjs.map +1 -1
- package/dist/comments.js +81 -186
- package/dist/comments.js.map +1 -1
- package/dist/diff.cjs +48 -65
- package/dist/diff.cjs.map +1 -1
- package/dist/diff.d.cts +2 -2
- package/dist/diff.d.ts +2 -2
- package/dist/diff.js +8 -32
- package/dist/diff.js.map +1 -1
- package/dist/docx.cjs +50 -63
- package/dist/docx.cjs.map +1 -1
- package/dist/docx.js +7 -22
- package/dist/docx.js.map +1 -1
- package/dist/embed.cjs +18 -12
- package/dist/embed.cjs.map +1 -1
- package/dist/embed.js +9 -16
- package/dist/embed.js.map +1 -1
- package/dist/emoji-data.cjs +7 -5
- package/dist/emoji-data.cjs.map +1 -1
- package/dist/emoji-data.js +3 -5
- package/dist/emoji-data.js.map +1 -1
- package/dist/emoji.cjs +25 -17
- package/dist/emoji.cjs.map +1 -1
- package/dist/emoji.js +8 -17
- package/dist/emoji.js.map +1 -1
- package/dist/engine.cjs +229 -118
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.js +4 -118
- package/dist/engine.js.map +1 -1
- package/dist/find.cjs +29 -19
- package/dist/find.cjs.map +1 -1
- package/dist/find.js +8 -19
- package/dist/find.js.map +1 -1
- package/dist/headless.cjs +290 -151
- package/dist/headless.cjs.map +1 -1
- package/dist/headless.d.cts +5 -1
- package/dist/headless.d.ts +5 -1
- package/dist/headless.js +5 -151
- package/dist/headless.js.map +1 -1
- package/dist/index.cjs +348 -183
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -4
- package/dist/index.d.ts +14 -4
- package/dist/index.js +7 -183
- package/dist/index.js.map +1 -1
- package/dist/math.cjs +19 -13
- package/dist/math.cjs.map +1 -1
- package/dist/math.js +10 -17
- package/dist/math.js.map +1 -1
- package/dist/mention.cjs +19 -13
- package/dist/mention.cjs.map +1 -1
- package/dist/mention.js +10 -17
- package/dist/mention.js.map +1 -1
- package/dist/presence.cjs +98 -132
- package/dist/presence.cjs.map +1 -1
- package/dist/presence.js +21 -78
- package/dist/presence.js.map +1 -1
- package/dist/{registry-CWBOSAHm.d.ts → registry-CXegaw5k.d.cts} +25 -2
- package/dist/{registry-CWBOSAHm.d.cts → registry-CXegaw5k.d.ts} +25 -2
- package/dist/stats.cjs +26 -18
- package/dist/stats.cjs.map +1 -1
- package/dist/stats.js +9 -18
- package/dist/stats.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/table.cjs +89 -49
- package/dist/table.cjs.map +1 -1
- package/dist/table.js +8 -49
- package/dist/table.js.map +1 -1
- package/dist/toc.cjs +25 -17
- package/dist/toc.cjs.map +1 -1
- package/dist/toc.js +8 -17
- package/dist/toc.js.map +1 -1
- package/dist/view.cjs +13 -16
- package/dist/view.cjs.map +1 -1
- package/dist/view.d.cts +2 -2
- package/dist/view.d.ts +2 -2
- package/dist/view.js +7 -16
- package/dist/view.js.map +1 -1
- package/dist/yjs.cjs +186 -228
- package/dist/yjs.cjs.map +1 -1
- package/dist/yjs.js +12 -80
- package/dist/yjs.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-4SLJNZSM.cjs.map +0 -1
- package/dist/chunk-4XFXB37X.js.map +0 -1
- package/dist/chunk-5MAYUGTE.cjs.map +0 -1
- package/dist/chunk-623AOJM2.js.map +0 -1
- package/dist/chunk-6NULZPVC.js.map +0 -1
- package/dist/chunk-6V6GGBDK.cjs.map +0 -1
- package/dist/chunk-73653CJ4.cjs +0 -34
- package/dist/chunk-73653CJ4.cjs.map +0 -1
- package/dist/chunk-ADSJ42DO.js.map +0 -1
- package/dist/chunk-AUOEM3SF.cjs.map +0 -1
- package/dist/chunk-BQANU5BH.cjs.map +0 -1
- package/dist/chunk-C23RQVRK.js.map +0 -1
- package/dist/chunk-CW3AFJBR.cjs.map +0 -1
- package/dist/chunk-DUE3HCZD.js.map +0 -1
- package/dist/chunk-EH5KXQXY.cjs.map +0 -1
- package/dist/chunk-EPARJI4V.js.map +0 -1
- package/dist/chunk-FDRUAL3Z.cjs.map +0 -1
- package/dist/chunk-IQBMAE3F.js.map +0 -1
- package/dist/chunk-JHQUHFLX.js.map +0 -1
- package/dist/chunk-KUYZMSMF.cjs +0 -100
- package/dist/chunk-KUYZMSMF.cjs.map +0 -1
- package/dist/chunk-LLTEGXWZ.cjs +0 -562
- package/dist/chunk-LLTEGXWZ.cjs.map +0 -1
- package/dist/chunk-N4FGA3H4.js.map +0 -1
- package/dist/chunk-NEZJ7ZP5.js.map +0 -1
- package/dist/chunk-O4Z2WMFF.js.map +0 -1
- package/dist/chunk-OBMBSU2S.js.map +0 -1
- package/dist/chunk-OSHZQR3W.js.map +0 -1
- package/dist/chunk-P6KYXFZC.cjs.map +0 -1
- package/dist/chunk-R2BLBV43.cjs +0 -239
- package/dist/chunk-R2BLBV43.cjs.map +0 -1
- package/dist/chunk-RJRX34BZ.js.map +0 -1
- package/dist/chunk-T43RZTUT.js.map +0 -1
- package/dist/chunk-TLGX43P6.cjs.map +0 -1
- package/dist/chunk-U3LOLYAU.js.map +0 -1
- package/dist/chunk-UEKXVCKC.cjs +0 -716
- package/dist/chunk-UEKXVCKC.cjs.map +0 -1
- package/dist/chunk-VCLL5C7J.js.map +0 -1
- package/dist/chunk-VRS6WCEK.js.map +0 -1
- package/dist/chunk-WEYDDIBQ.cjs.map +0 -1
- package/dist/chunk-X4HDKFW5.cjs.map +0 -1
- package/dist/chunk-X4P4TQXH.cjs +0 -30
- package/dist/chunk-X4P4TQXH.cjs.map +0 -1
- package/dist/chunk-XA3UEJIW.cjs +0 -25
- package/dist/chunk-XA3UEJIW.cjs.map +0 -1
- package/dist/chunk-YBMUEEM5.js.map +0 -1
- package/dist/chunk-ZKVOS57Q.cjs.map +0 -1
|
@@ -1,144 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
regionInline,
|
|
18
|
-
textDiff,
|
|
19
|
-
useBlockDomId,
|
|
20
|
-
useEditorState,
|
|
21
|
-
useIsomorphicLayoutEffect,
|
|
22
|
-
useOrderedNumber,
|
|
23
|
-
useQuoinEditor,
|
|
24
|
-
useReadOnly,
|
|
25
|
-
useRegionDomId,
|
|
26
|
-
useToggleOpen,
|
|
27
|
-
visibleBlockIndexes,
|
|
28
|
-
wholeState
|
|
29
|
-
} from "./chunk-EPARJI4V.js";
|
|
30
|
-
import {
|
|
31
|
-
blockByType,
|
|
32
|
-
defineBlock,
|
|
33
|
-
devWarn,
|
|
34
|
-
highlightedLines,
|
|
35
|
-
paletteBlocks,
|
|
36
|
-
tokenColour
|
|
37
|
-
} from "./chunk-O4Z2WMFF.js";
|
|
38
|
-
import {
|
|
39
|
-
HISTORY_GROUP,
|
|
40
|
-
LINE_JOIN,
|
|
41
|
-
LINE_SPLIT,
|
|
42
|
-
Transaction,
|
|
43
|
-
blockRangeSelection,
|
|
44
|
-
caretMarks,
|
|
45
|
-
coreExtensions,
|
|
46
|
-
createBlock,
|
|
47
|
-
createPluginKey,
|
|
48
|
-
defineExtension,
|
|
49
|
-
deleteBlocks,
|
|
50
|
-
descendantsEnd,
|
|
51
|
-
detectMac,
|
|
52
|
-
duplicateBlocks,
|
|
53
|
-
endOf,
|
|
54
|
-
getPluginState,
|
|
55
|
-
headBlockId,
|
|
56
|
-
indent,
|
|
57
|
-
insertBlockAfter,
|
|
58
|
-
insertBlocksStep,
|
|
59
|
-
insertText,
|
|
60
|
-
isActive,
|
|
61
|
-
isCollapsed,
|
|
62
|
-
isParagraph,
|
|
63
|
-
isTextFlow,
|
|
64
|
-
keyName,
|
|
65
|
-
markExtent,
|
|
66
|
-
markRanges,
|
|
67
|
-
moveBlocksDown,
|
|
68
|
-
moveBlocksTo,
|
|
69
|
-
moveBlocksUp,
|
|
70
|
-
movedBlockIds,
|
|
71
|
-
nodeSelection,
|
|
72
|
-
normalizeKey,
|
|
73
|
-
orderedRange,
|
|
74
|
-
outdent,
|
|
75
|
-
primaryRegion,
|
|
76
|
-
rangeContent,
|
|
77
|
-
redo,
|
|
78
|
-
regionLength,
|
|
79
|
-
removeMarkStep,
|
|
80
|
-
replaceBlockStep,
|
|
81
|
-
replaceInlineStep,
|
|
82
|
-
runCommands,
|
|
83
|
-
sameSelection,
|
|
84
|
-
selectAll,
|
|
85
|
-
selectedBlockIds,
|
|
86
|
-
selectedBlockRange,
|
|
87
|
-
setAttrs,
|
|
88
|
-
setAttrsStep,
|
|
89
|
-
setBlockColor,
|
|
90
|
-
setBlockType,
|
|
91
|
-
setLink,
|
|
92
|
-
setMark,
|
|
93
|
-
setSelection,
|
|
94
|
-
setTextAlign,
|
|
95
|
-
startOf,
|
|
96
|
-
textSelection,
|
|
97
|
-
toMarkdown,
|
|
98
|
-
toggleMark,
|
|
99
|
-
undo,
|
|
100
|
-
unsetLink,
|
|
101
|
-
unsetMark,
|
|
102
|
-
validateSelection
|
|
103
|
-
} from "./chunk-OBMBSU2S.js";
|
|
104
|
-
import {
|
|
105
|
-
sameValue
|
|
106
|
-
} from "./chunk-RJRX34BZ.js";
|
|
107
|
-
import {
|
|
108
|
-
PALETTE,
|
|
109
|
-
SCHEME,
|
|
110
|
-
addMark,
|
|
111
|
-
alignOrUndefined,
|
|
112
|
-
blockById,
|
|
113
|
-
blockPlainText,
|
|
114
|
-
createBlockCodec,
|
|
115
|
-
createDoc,
|
|
116
|
-
hasMark,
|
|
117
|
-
headingLevel,
|
|
118
|
-
inlineLength,
|
|
119
|
-
inlineText,
|
|
120
|
-
newId,
|
|
121
|
-
optionalNumber,
|
|
122
|
-
paletteOrUndefined,
|
|
123
|
-
parseInline,
|
|
124
|
-
requireBlockIndex,
|
|
125
|
-
sameItems,
|
|
126
|
-
sanitizeAssetUrl,
|
|
127
|
-
sanitizeHref,
|
|
128
|
-
sliceInline,
|
|
129
|
-
specFor,
|
|
130
|
-
str,
|
|
131
|
-
text
|
|
132
|
-
} from "./chunk-4XFXB37X.js";
|
|
133
|
-
|
|
134
|
-
// src/canvas/BlockCanvas.tsx
|
|
135
|
-
import { forwardRef as forwardRef8, useImperativeHandle as useImperativeHandle2, useMemo as useMemo17, useState as useState19 } from "react";
|
|
136
|
-
|
|
137
|
-
// src/blocks/core.ts
|
|
138
|
-
import { Code, FileText, Image, MessageSquare, Paperclip } from "lucide-react";
|
|
139
|
-
|
|
140
|
-
// src/context.tsx
|
|
141
|
-
import * as React from "react";
|
|
1
|
+
import { useQuoinEditor, EditorView, useIsomorphicLayoutEffect, useReadOnly, useEditorState, listen, wholeState, NODE_ENTRY, useBlockDomId, useToggleOpen, ToggleChevron, EditableRegion, drawnBlockCount, isComposingKey, NATIVE_INTERACTION, useRegionDomId, TaskCheckbox, useOrderedNumber, createAutoScroll, domMapOf, dispatchSelection, regionInline, onBlock, hostKey, BlockErrorContext, textDiff, moveToNeighbour, visibleBlockIndexes } from './chunk-QC35D2AU.js';
|
|
2
|
+
import { defineBlock, devWarn, highlightedLines, blockByType, paletteBlocks, tokenColour, seedData, parsedData } from './chunk-HDJ653LM.js';
|
|
3
|
+
import { createPluginKey, coreExtensions, defineExtension, duplicateBlocks, primaryRegion, regionLength, headBlockId, sameSelection, Transaction, insertBlocksStep, startOf, replaceBlockStep, descendantsEnd, LINE_JOIN, detectMac, selectedBlockIds, blockRangeSelection, runCommands, setSelection, selectedBlockRange, toMarkdown, isCollapsed, createBlock, isParagraph, nodeSelection, setAttrsStep, LINE_SPLIT, validateSelection, endOf, insertBlockAfter, insertText, isTextFlow, markRanges, setTextAlign, orderedRange, unsetLink, textSelection, toggleMark, isActive, setBlockType, getPluginState, rangeContent, unsetMark, setMark, markExtent, setLink, deleteBlocks, setAttrs, HISTORY_GROUP, setBlockColor, removeMarkStep, caretMarks, replaceInlineStep, keyName, normalizeKey, movedBlockIds, moveBlocksUp, moveBlocksDown, selectAll, redo, undo, moveBlocksTo, indent, outdent } from './chunk-L4D23LM2.js';
|
|
4
|
+
import { sameValue } from './chunk-3BXUGX5F.js';
|
|
5
|
+
import { str, blockPlainText, sanitizeHref, inlineText, parseInline, newId, createDoc, sameItems, headingLevel, sanitizeAssetUrl, blockById, sliceInline, specFor, createBlockCodec, hasMark, alignOrUndefined, optionalNumber, requireBlockIndex, SCHEME, inlineLength, paletteOrUndefined, PALETTE, addMark, text } from './chunk-L6OW2FL3.js';
|
|
6
|
+
import * as React7 from 'react';
|
|
7
|
+
import { createContext, forwardRef, useRef, useImperativeHandle, useState, useMemo, useEffect, Fragment as Fragment$1, useContext, useSyncExternalStore, useCallback, useId, createElement } from 'react';
|
|
8
|
+
import { FileText, MessageSquare, Code, Image, Paperclip, CopyPlus, Copy, Link, ArrowUp, ArrowDown, Trash, Keyboard, Plus, GripVertical, Minus, Check, ExternalLink, Unlink, ChevronRightIcon, CircleIcon, ChevronDown, ListCollapse, Heading1, Heading2, Heading3, Baseline, AlignLeft, AlignJustify, AlignRight, AlignCenter, CheckIcon, Pencil, XIcon, Upload, Download, Repeat2, Palette, Droplet, Sticker, FileIcon, FileImage, FileMusic, FilePlay, FileArchive, Subscript, Superscript, Bold, Italic, Underline, Strikethrough, Type, List, ListOrdered, ListTodo, TextQuote, ListIndentIncrease, ListIndentDecrease, Undo2, Redo2 } from 'lucide-react';
|
|
9
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
10
|
+
import * as ContextMenuPrimitive from '@radix-ui/react-context-menu';
|
|
11
|
+
import { clsx } from 'clsx';
|
|
12
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
13
|
+
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
14
|
+
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
15
|
+
import { createPortal } from 'react-dom';
|
|
16
|
+
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
142
17
|
|
|
143
18
|
// src/blocks/file/format-size.ts
|
|
144
19
|
var UNITS = ["B", "KB", "MB", "GB", "TB"];
|
|
@@ -315,6 +190,7 @@ var englishLabels = {
|
|
|
315
190
|
selectedContent: "Selected content",
|
|
316
191
|
editBlock: (label) => `Edit ${label}`,
|
|
317
192
|
unsupportedBlock: "Unsupported block",
|
|
193
|
+
blockError: "Block could not be drawn",
|
|
318
194
|
uploading: "Uploading...",
|
|
319
195
|
uploaded: (name) => `Uploaded ${name}`,
|
|
320
196
|
uploadFailed: "Upload failed.",
|
|
@@ -335,6 +211,8 @@ var englishLabels = {
|
|
|
335
211
|
altTextHint: "Required. Describe what the image shows for anyone who cannot see it.",
|
|
336
212
|
save: "Save",
|
|
337
213
|
imageNoAlt: "Image, no description",
|
|
214
|
+
decorativeImage: "Decorative image",
|
|
215
|
+
noAltBadge: "No alt text",
|
|
338
216
|
uploadFile: "Upload file",
|
|
339
217
|
dropFile: "Or drop or paste a file here.",
|
|
340
218
|
fileTools: "File tools",
|
|
@@ -352,16 +230,13 @@ var englishLabels = {
|
|
|
352
230
|
emptyMarkdown: "Empty markdown block",
|
|
353
231
|
emptyCallout: "Empty callout"
|
|
354
232
|
};
|
|
355
|
-
|
|
356
|
-
// src/context.tsx
|
|
357
|
-
import { jsx } from "react/jsx-runtime";
|
|
358
|
-
var QuoinContext = React.createContext(null);
|
|
233
|
+
var QuoinContext = React7.createContext(null);
|
|
359
234
|
function QuoinProvider({
|
|
360
235
|
value,
|
|
361
236
|
children
|
|
362
237
|
}) {
|
|
363
238
|
const { blockTypes, upload, resolveAssetUrl, onError, highlight, controller = null, labels = englishLabels } = value;
|
|
364
|
-
const config =
|
|
239
|
+
const config = React7.useMemo(
|
|
365
240
|
() => ({
|
|
366
241
|
blockTypes,
|
|
367
242
|
upload,
|
|
@@ -378,7 +253,7 @@ function QuoinProvider({
|
|
|
378
253
|
return /* @__PURE__ */ jsx(QuoinContext.Provider, { value: config, children });
|
|
379
254
|
}
|
|
380
255
|
function useQuoin() {
|
|
381
|
-
const config =
|
|
256
|
+
const config = React7.useContext(QuoinContext);
|
|
382
257
|
if (!config) throw new Error("useQuoin must be used inside a QuoinProvider.");
|
|
383
258
|
return config;
|
|
384
259
|
}
|
|
@@ -390,20 +265,16 @@ function useLabels() {
|
|
|
390
265
|
|
|
391
266
|
// src/blocks/caption-markdown.ts
|
|
392
267
|
var captionText = (markdown) => inlineText(parseInline(markdown), () => "");
|
|
393
|
-
|
|
394
|
-
// src/blocks/code/HighlightOverlay.tsx
|
|
395
|
-
import { Fragment, useMemo as useMemo2 } from "react";
|
|
396
|
-
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
397
268
|
function Token({ text: text2, color, className }) {
|
|
398
|
-
return /* @__PURE__ */
|
|
269
|
+
return /* @__PURE__ */ jsx("span", { style: { color: tokenColour(color) }, className, children: text2 });
|
|
399
270
|
}
|
|
400
271
|
function HighlightOverlay({ code, language: language2, drawnRef, ...props }) {
|
|
401
272
|
const { highlight } = useQuoin();
|
|
402
|
-
const lines =
|
|
273
|
+
const lines = useMemo(() => highlightedLines(highlight, code, language2), [highlight, code, language2]);
|
|
403
274
|
return /* @__PURE__ */ jsxs("pre", { ...props, ref: drawnRef, className: "quoin-code-text", children: [
|
|
404
|
-
/* @__PURE__ */
|
|
275
|
+
/* @__PURE__ */ jsx("code", { children: lines === null ? code : lines.map((line, index) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
405
276
|
index > 0 && "\n",
|
|
406
|
-
line.map((token, at) => /* @__PURE__ */
|
|
277
|
+
line.map((token, at) => /* @__PURE__ */ jsx(Token, { ...token }, at))
|
|
407
278
|
] }, index)) }),
|
|
408
279
|
"\n"
|
|
409
280
|
] });
|
|
@@ -426,9 +297,6 @@ function imageSource(attrs, resolveAssetUrl) {
|
|
|
426
297
|
const url = str(attrs.url);
|
|
427
298
|
return url === "" ? assetHref(resolveAssetUrl, str(attrs.storageKey)) : sanitizeHref(url);
|
|
428
299
|
}
|
|
429
|
-
|
|
430
|
-
// src/blocks/previews.tsx
|
|
431
|
-
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
432
300
|
var HINT = "text-sm text-muted-foreground";
|
|
433
301
|
var TONE = {
|
|
434
302
|
info: "border-info bg-info/15",
|
|
@@ -440,35 +308,35 @@ var TONE = {
|
|
|
440
308
|
function MarkdownPreview({ data }) {
|
|
441
309
|
const labels = useLabels();
|
|
442
310
|
const markdown = str(data.markdown);
|
|
443
|
-
if (markdown.trim() === "") return /* @__PURE__ */
|
|
444
|
-
return /* @__PURE__ */
|
|
311
|
+
if (markdown.trim() === "") return /* @__PURE__ */ jsx("p", { className: HINT, children: labels.emptyMarkdown });
|
|
312
|
+
return /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap text-base leading-7", children: markdown });
|
|
445
313
|
}
|
|
446
314
|
function CodePreview({ data }) {
|
|
447
|
-
return /* @__PURE__ */
|
|
315
|
+
return /* @__PURE__ */ jsx("div", { dir: "ltr", className: "quoin-code quoin-code-scroll pt-3", children: /* @__PURE__ */ jsx(HighlightOverlay, { code: str(data.code), language: str(data.language) }) });
|
|
448
316
|
}
|
|
449
317
|
function ImagePreview({ data }) {
|
|
450
318
|
const { resolveAssetUrl, labels } = useQuoin();
|
|
451
319
|
const src = imageSource(data, resolveAssetUrl);
|
|
452
|
-
if (src === null) return /* @__PURE__ */
|
|
320
|
+
if (src === null) return /* @__PURE__ */ jsx("p", { className: HINT, children: labels.emptyImage });
|
|
453
321
|
const caption = captionText(str(data.caption));
|
|
454
|
-
return /* @__PURE__ */
|
|
455
|
-
/* @__PURE__ */
|
|
456
|
-
caption && /* @__PURE__ */
|
|
322
|
+
return /* @__PURE__ */ jsxs("figure", { children: [
|
|
323
|
+
/* @__PURE__ */ jsx("img", { src, alt: str(data.alt) || labels.imageNoAlt, className: "max-w-full rounded-md" }),
|
|
324
|
+
caption && /* @__PURE__ */ jsx("figcaption", { className: HINT, children: caption })
|
|
457
325
|
] });
|
|
458
326
|
}
|
|
459
327
|
function FilePreview({ data }) {
|
|
460
328
|
const labels = useLabels();
|
|
461
329
|
const name = str(data.filename);
|
|
462
|
-
if (name === "") return /* @__PURE__ */
|
|
463
|
-
return /* @__PURE__ */
|
|
330
|
+
if (name === "") return /* @__PURE__ */ jsx("p", { className: HINT, children: labels.emptyFile });
|
|
331
|
+
return /* @__PURE__ */ jsx("p", { className: "text-sm", children: name });
|
|
464
332
|
}
|
|
465
333
|
function CalloutPreview({ data }) {
|
|
466
334
|
const labels = useLabels();
|
|
467
335
|
const body = str(data.body);
|
|
468
|
-
if (body.trim() === "") return /* @__PURE__ */
|
|
336
|
+
if (body.trim() === "") return /* @__PURE__ */ jsx("p", { className: HINT, children: labels.emptyCallout });
|
|
469
337
|
const tone = str(data.tone) || "info";
|
|
470
338
|
const paint = TONE[tone] ?? "border-border bg-muted/50";
|
|
471
|
-
return /* @__PURE__ */
|
|
339
|
+
return /* @__PURE__ */ jsx("div", { "data-tone": tone, className: `rounded-md border-l-4 ${paint} p-3 text-sm`, children: body });
|
|
472
340
|
}
|
|
473
341
|
|
|
474
342
|
// src/blocks/core.ts
|
|
@@ -510,9 +378,6 @@ var coreBlocks = [
|
|
|
510
378
|
})
|
|
511
379
|
];
|
|
512
380
|
|
|
513
|
-
// src/blocks/void/use-void-editing.ts
|
|
514
|
-
import { createContext as createContext2, useCallback, useContext as useContext2, useEffect, useState } from "react";
|
|
515
|
-
|
|
516
381
|
// src/blocks/void/select-node.ts
|
|
517
382
|
function selectNode(controller, blockId) {
|
|
518
383
|
const { editor } = controller;
|
|
@@ -526,9 +391,9 @@ function focusNode(controller, blockId) {
|
|
|
526
391
|
}
|
|
527
392
|
|
|
528
393
|
// src/blocks/void/use-void-editing.ts
|
|
529
|
-
var VoidEditingContext =
|
|
394
|
+
var VoidEditingContext = createContext(null);
|
|
530
395
|
function useVoidEditing(controller, blockId, canEdit = true) {
|
|
531
|
-
const voidEditing =
|
|
396
|
+
const voidEditing = useContext(VoidEditingContext);
|
|
532
397
|
const [editing, setEditing] = useState(false);
|
|
533
398
|
if (editing && !canEdit) setEditing(false);
|
|
534
399
|
const start = useCallback(() => {
|
|
@@ -588,9 +453,6 @@ function createVoidEditing() {
|
|
|
588
453
|
};
|
|
589
454
|
}
|
|
590
455
|
|
|
591
|
-
// src/gutter/BlockContextMenu.tsx
|
|
592
|
-
import { useRef as useRef17 } from "react";
|
|
593
|
-
|
|
594
456
|
// src/blocks/text/return-focus-to-text.ts
|
|
595
457
|
function focusBelongsInText(controller, focused) {
|
|
596
458
|
if (!focused || focused === focused.ownerDocument.body) return true;
|
|
@@ -602,9 +464,6 @@ function returnFocusToText(controller) {
|
|
|
602
464
|
if (focusBelongsInText(controller, controller.root?.ownerDocument.activeElement)) controller.focus();
|
|
603
465
|
};
|
|
604
466
|
}
|
|
605
|
-
|
|
606
|
-
// src/canvas/ui-store.ts
|
|
607
|
-
import { createContext as createContext3, useContext as useContext3, useSyncExternalStore } from "react";
|
|
608
467
|
var INITIAL = {
|
|
609
468
|
hoveredBlock: null,
|
|
610
469
|
blockMenu: null,
|
|
@@ -614,18 +473,18 @@ var INITIAL = {
|
|
|
614
473
|
};
|
|
615
474
|
function createCanvasUiStore() {
|
|
616
475
|
let state = INITIAL;
|
|
617
|
-
const
|
|
476
|
+
const listeners2 = /* @__PURE__ */ new Set();
|
|
618
477
|
return {
|
|
619
478
|
get: () => state,
|
|
620
479
|
set(patch) {
|
|
621
480
|
const keys = Object.keys(patch);
|
|
622
481
|
if (keys.every((key) => Object.is(state[key], patch[key]))) return;
|
|
623
482
|
state = { ...state, ...patch };
|
|
624
|
-
for (const listener of [...
|
|
483
|
+
for (const listener of [...listeners2]) listener();
|
|
625
484
|
},
|
|
626
485
|
subscribe(listener) {
|
|
627
|
-
|
|
628
|
-
return () => void
|
|
486
|
+
listeners2.add(listener);
|
|
487
|
+
return () => void listeners2.delete(listener);
|
|
629
488
|
}
|
|
630
489
|
};
|
|
631
490
|
}
|
|
@@ -633,21 +492,13 @@ function useCanvasUi(store, selector) {
|
|
|
633
492
|
const read2 = () => selector(store.get());
|
|
634
493
|
return useSyncExternalStore(store.subscribe, read2, read2);
|
|
635
494
|
}
|
|
636
|
-
var CanvasUiContext =
|
|
495
|
+
var CanvasUiContext = createContext(null);
|
|
637
496
|
var CanvasUiProvider = CanvasUiContext.Provider;
|
|
638
497
|
function useCanvasUiStore() {
|
|
639
|
-
const store =
|
|
498
|
+
const store = useContext(CanvasUiContext);
|
|
640
499
|
if (store === null) throw new Error("useCanvasUiStore must be used inside a BlockCanvas.");
|
|
641
500
|
return store;
|
|
642
501
|
}
|
|
643
|
-
|
|
644
|
-
// src/ui/context-menu.tsx
|
|
645
|
-
import * as React2 from "react";
|
|
646
|
-
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
|
|
647
|
-
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
|
|
648
|
-
|
|
649
|
-
// src/ui/cn.ts
|
|
650
|
-
import { clsx } from "clsx";
|
|
651
502
|
var DISPLAY = /* @__PURE__ */ new Set(["block", "inline", "flex", "inline-flex", "grid", "contents", "hidden"]);
|
|
652
503
|
var FONT_SIZE = /^text-(xs|sm|base|lg|\d?xl)(\/.+)?$/;
|
|
653
504
|
var TEXT_NOT_COLOR = /^text-(left|center|right|justify|start|end|wrap|nowrap|balance|pretty|ellipsis|clip|shadow-.+|opacity-.+|[[(].*)$/;
|
|
@@ -715,20 +566,17 @@ var MENU_SUB_TRIGGER = [
|
|
|
715
566
|
var MENU_LABEL = "px-2 py-1.5 text-sm font-medium data-[inset]:pl-8";
|
|
716
567
|
var MENU_SEPARATOR = "bg-border -mx-1 my-1 h-px";
|
|
717
568
|
var MENU_SHORTCUT = "text-muted-foreground ml-auto text-xs tracking-widest";
|
|
718
|
-
|
|
719
|
-
// src/ui/context-menu.tsx
|
|
720
|
-
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
721
569
|
function ContextMenu({ modal = false, ...props }) {
|
|
722
|
-
return /* @__PURE__ */
|
|
570
|
+
return /* @__PURE__ */ jsx(ContextMenuPrimitive.Root, { modal, ...props });
|
|
723
571
|
}
|
|
724
572
|
function ContextMenuSub(props) {
|
|
725
|
-
return /* @__PURE__ */
|
|
573
|
+
return /* @__PURE__ */ jsx(ContextMenuPrimitive.Sub, { ...props });
|
|
726
574
|
}
|
|
727
|
-
var ContextMenuTrigger = /* @__PURE__ */
|
|
728
|
-
return /* @__PURE__ */
|
|
575
|
+
var ContextMenuTrigger = /* @__PURE__ */ React7.forwardRef(function ContextMenuTrigger2(props, ref) {
|
|
576
|
+
return /* @__PURE__ */ jsx(ContextMenuPrimitive.Trigger, { ref, "data-slot": "context-menu-trigger", ...props });
|
|
729
577
|
});
|
|
730
|
-
var ContextMenuContent = /* @__PURE__ */
|
|
731
|
-
return /* @__PURE__ */
|
|
578
|
+
var ContextMenuContent = /* @__PURE__ */ React7.forwardRef(function ContextMenuContent2({ className, ...props }, ref) {
|
|
579
|
+
return /* @__PURE__ */ jsx(ContextMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
732
580
|
ContextMenuPrimitive.Content,
|
|
733
581
|
{
|
|
734
582
|
ref,
|
|
@@ -738,11 +586,11 @@ var ContextMenuContent = /* @__PURE__ */ React2.forwardRef(function ContextMenuC
|
|
|
738
586
|
}
|
|
739
587
|
) });
|
|
740
588
|
});
|
|
741
|
-
var ContextMenuGroup = /* @__PURE__ */
|
|
742
|
-
return /* @__PURE__ */
|
|
589
|
+
var ContextMenuGroup = /* @__PURE__ */ React7.forwardRef(function ContextMenuGroup2(props, ref) {
|
|
590
|
+
return /* @__PURE__ */ jsx(ContextMenuPrimitive.Group, { ref, "data-slot": "context-menu-group", ...props });
|
|
743
591
|
});
|
|
744
|
-
var ContextMenuItem = /* @__PURE__ */
|
|
745
|
-
return /* @__PURE__ */
|
|
592
|
+
var ContextMenuItem = /* @__PURE__ */ React7.forwardRef(function ContextMenuItem2({ className, inset, ...props }, ref) {
|
|
593
|
+
return /* @__PURE__ */ jsx(
|
|
746
594
|
ContextMenuPrimitive.Item,
|
|
747
595
|
{
|
|
748
596
|
ref,
|
|
@@ -753,11 +601,11 @@ var ContextMenuItem = /* @__PURE__ */ React2.forwardRef(function ContextMenuItem
|
|
|
753
601
|
}
|
|
754
602
|
);
|
|
755
603
|
});
|
|
756
|
-
var ContextMenuRadioGroup = /* @__PURE__ */
|
|
757
|
-
return /* @__PURE__ */
|
|
604
|
+
var ContextMenuRadioGroup = /* @__PURE__ */ React7.forwardRef(function ContextMenuRadioGroup2(props, ref) {
|
|
605
|
+
return /* @__PURE__ */ jsx(ContextMenuPrimitive.RadioGroup, { ref, "data-slot": "context-menu-radio-group", ...props });
|
|
758
606
|
});
|
|
759
|
-
var ContextMenuRadioItem = /* @__PURE__ */
|
|
760
|
-
return /* @__PURE__ */
|
|
607
|
+
var ContextMenuRadioItem = /* @__PURE__ */ React7.forwardRef(function ContextMenuRadioItem2({ className, children, indicator = /* @__PURE__ */ jsx(CircleIcon, { className: "size-2 fill-current" }), ...props }, ref) {
|
|
608
|
+
return /* @__PURE__ */ jsxs(
|
|
761
609
|
ContextMenuPrimitive.RadioItem,
|
|
762
610
|
{
|
|
763
611
|
ref,
|
|
@@ -765,14 +613,14 @@ var ContextMenuRadioItem = /* @__PURE__ */ React2.forwardRef(function ContextMen
|
|
|
765
613
|
className: cn(MENU_CHECKABLE_ITEM, className),
|
|
766
614
|
...props,
|
|
767
615
|
children: [
|
|
768
|
-
/* @__PURE__ */
|
|
616
|
+
/* @__PURE__ */ jsx("span", { className: MENU_ITEM_INDICATOR, children: /* @__PURE__ */ jsx(ContextMenuPrimitive.ItemIndicator, { children: indicator }) }),
|
|
769
617
|
children
|
|
770
618
|
]
|
|
771
619
|
}
|
|
772
620
|
);
|
|
773
621
|
});
|
|
774
|
-
var ContextMenuLabel = /* @__PURE__ */
|
|
775
|
-
return /* @__PURE__ */
|
|
622
|
+
var ContextMenuLabel = /* @__PURE__ */ React7.forwardRef(function ContextMenuLabel2({ className, inset, ...props }, ref) {
|
|
623
|
+
return /* @__PURE__ */ jsx(
|
|
776
624
|
ContextMenuPrimitive.Label,
|
|
777
625
|
{
|
|
778
626
|
ref,
|
|
@@ -783,8 +631,8 @@ var ContextMenuLabel = /* @__PURE__ */ React2.forwardRef(function ContextMenuLab
|
|
|
783
631
|
}
|
|
784
632
|
);
|
|
785
633
|
});
|
|
786
|
-
var ContextMenuSeparator = /* @__PURE__ */
|
|
787
|
-
return /* @__PURE__ */
|
|
634
|
+
var ContextMenuSeparator = /* @__PURE__ */ React7.forwardRef(function ContextMenuSeparator2({ className, ...props }, ref) {
|
|
635
|
+
return /* @__PURE__ */ jsx(
|
|
788
636
|
ContextMenuPrimitive.Separator,
|
|
789
637
|
{
|
|
790
638
|
ref,
|
|
@@ -794,11 +642,11 @@ var ContextMenuSeparator = /* @__PURE__ */ React2.forwardRef(function ContextMen
|
|
|
794
642
|
}
|
|
795
643
|
);
|
|
796
644
|
});
|
|
797
|
-
var ContextMenuShortcut = /* @__PURE__ */
|
|
798
|
-
return /* @__PURE__ */
|
|
645
|
+
var ContextMenuShortcut = /* @__PURE__ */ React7.forwardRef(function ContextMenuShortcut2({ className, ...props }, ref) {
|
|
646
|
+
return /* @__PURE__ */ jsx("span", { ref, "data-slot": "context-menu-shortcut", className: cn(MENU_SHORTCUT, className), ...props });
|
|
799
647
|
});
|
|
800
|
-
var ContextMenuSubTrigger = /* @__PURE__ */
|
|
801
|
-
return /* @__PURE__ */
|
|
648
|
+
var ContextMenuSubTrigger = /* @__PURE__ */ React7.forwardRef(function ContextMenuSubTrigger2({ className, inset, children, ...props }, ref) {
|
|
649
|
+
return /* @__PURE__ */ jsxs(
|
|
802
650
|
ContextMenuPrimitive.SubTrigger,
|
|
803
651
|
{
|
|
804
652
|
ref,
|
|
@@ -808,13 +656,13 @@ var ContextMenuSubTrigger = /* @__PURE__ */ React2.forwardRef(function ContextMe
|
|
|
808
656
|
...props,
|
|
809
657
|
children: [
|
|
810
658
|
children,
|
|
811
|
-
/* @__PURE__ */
|
|
659
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, { className: "ml-auto size-4" })
|
|
812
660
|
]
|
|
813
661
|
}
|
|
814
662
|
);
|
|
815
663
|
});
|
|
816
|
-
var ContextMenuSubContent = /* @__PURE__ */
|
|
817
|
-
return /* @__PURE__ */
|
|
664
|
+
var ContextMenuSubContent = /* @__PURE__ */ React7.forwardRef(function ContextMenuSubContent2({ className, ...props }, ref) {
|
|
665
|
+
return /* @__PURE__ */ jsx(
|
|
818
666
|
ContextMenuPrimitive.SubContent,
|
|
819
667
|
{
|
|
820
668
|
ref,
|
|
@@ -825,9 +673,6 @@ var ContextMenuSubContent = /* @__PURE__ */ React2.forwardRef(function ContextMe
|
|
|
825
673
|
);
|
|
826
674
|
});
|
|
827
675
|
|
|
828
|
-
// src/gutter/block-menu-items.ts
|
|
829
|
-
import { ArrowDown, ArrowUp, Copy, CopyPlus, Link, Trash } from "lucide-react";
|
|
830
|
-
|
|
831
676
|
// src/gutter/copy-text.ts
|
|
832
677
|
function copyThroughTextArea(text2, doc) {
|
|
833
678
|
const previous = doc.activeElement instanceof HTMLElement ? doc.activeElement : null;
|
|
@@ -984,12 +829,6 @@ function closeBlockMenu(store) {
|
|
|
984
829
|
store.set({ blockMenu: null, hoveredBlock: null });
|
|
985
830
|
}
|
|
986
831
|
|
|
987
|
-
// src/gutter/BlockMenuItems.tsx
|
|
988
|
-
import { Fragment as Fragment6 } from "react";
|
|
989
|
-
|
|
990
|
-
// src/gutter/CalloutMenus.tsx
|
|
991
|
-
import { CheckIcon as CheckIcon2, Droplet, Sticker } from "lucide-react";
|
|
992
|
-
|
|
993
832
|
// src/blocks/text/callout-tone.ts
|
|
994
833
|
var CALLOUT_TONES = ["info", "tip", "success", "warning", "danger"];
|
|
995
834
|
var CALLOUT_ICONS = ["\u{1F4A1}", "\u26A0\uFE0F", "\u2705", "\u2757", "\u2139\uFE0F", "\u{1F4CC}"];
|
|
@@ -1006,15 +845,9 @@ function calloutTone(value) {
|
|
|
1006
845
|
function calloutIcon(attrs, tone) {
|
|
1007
846
|
return typeof attrs.icon === "string" && attrs.icon !== "" ? attrs.icon : TONE_ICONS[tone];
|
|
1008
847
|
}
|
|
1009
|
-
|
|
1010
|
-
// src/gutter/MenuIcon.tsx
|
|
1011
|
-
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
1012
848
|
function MenuIcon({ icon: Icon }) {
|
|
1013
|
-
return /* @__PURE__ */
|
|
849
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "flex shrink-0", children: /* @__PURE__ */ jsx(Icon, { className: "size-4" }) });
|
|
1014
850
|
}
|
|
1015
|
-
|
|
1016
|
-
// src/gutter/CalloutMenus.tsx
|
|
1017
|
-
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1018
851
|
var sharedTone = (blocks) => {
|
|
1019
852
|
const tones = new Set(blocks.map((block) => calloutTone(block.attrs.tone)));
|
|
1020
853
|
return tones.size === 1 ? [...tones][0] : "";
|
|
@@ -1023,51 +856,46 @@ function CalloutMenus({ kit, controller, blocks }) {
|
|
|
1023
856
|
const labels = useLabels();
|
|
1024
857
|
const blockIds = blocks.map((block) => block.id);
|
|
1025
858
|
const apply = (patch) => runOnBlocks(controller, blockIds, setAttrs(patch));
|
|
1026
|
-
return /* @__PURE__ */
|
|
1027
|
-
/* @__PURE__ */
|
|
1028
|
-
/* @__PURE__ */
|
|
1029
|
-
/* @__PURE__ */
|
|
859
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
860
|
+
/* @__PURE__ */ jsxs(kit.Sub, { children: [
|
|
861
|
+
/* @__PURE__ */ jsxs(kit.SubTrigger, { children: [
|
|
862
|
+
/* @__PURE__ */ jsx(MenuIcon, { icon: Droplet }),
|
|
1030
863
|
labels.tone
|
|
1031
864
|
] }),
|
|
1032
|
-
/* @__PURE__ */
|
|
865
|
+
/* @__PURE__ */ jsx(kit.SubContent, { children: /* @__PURE__ */ jsx(kit.RadioGroup, { value: sharedTone(blocks), onValueChange: (tone) => apply({ tone }), children: CALLOUT_TONES.map((tone) => /* @__PURE__ */ jsx(kit.RadioItem, { value: tone, indicator: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }), children: labels.calloutTones[tone] }, tone)) }) })
|
|
1033
866
|
] }),
|
|
1034
|
-
/* @__PURE__ */
|
|
1035
|
-
/* @__PURE__ */
|
|
1036
|
-
/* @__PURE__ */
|
|
867
|
+
/* @__PURE__ */ jsxs(kit.Sub, { children: [
|
|
868
|
+
/* @__PURE__ */ jsxs(kit.SubTrigger, { children: [
|
|
869
|
+
/* @__PURE__ */ jsx(MenuIcon, { icon: Sticker }),
|
|
1037
870
|
labels.icon
|
|
1038
871
|
] }),
|
|
1039
|
-
/* @__PURE__ */
|
|
872
|
+
/* @__PURE__ */ jsx(kit.SubContent, { className: "min-w-0", children: CALLOUT_ICONS.map((icon) => /* @__PURE__ */ jsx(kit.Item, { className: "justify-center text-base", onSelect: () => apply({ icon }), children: icon }, icon)) })
|
|
1040
873
|
] })
|
|
1041
874
|
] });
|
|
1042
875
|
}
|
|
1043
|
-
|
|
1044
|
-
// src/gutter/ColorMenu.tsx
|
|
1045
|
-
import { useId } from "react";
|
|
1046
|
-
import { CheckIcon as CheckIcon3, Palette } from "lucide-react";
|
|
1047
|
-
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1048
876
|
function sharedColor(blocks, key) {
|
|
1049
877
|
const coloured = blocks.filter((block) => block.type === "MARKDOWN");
|
|
1050
878
|
const colors = new Set(coloured.map((block) => paletteOrUndefined(block.attrs[key]) ?? "default"));
|
|
1051
879
|
return colors.size === 1 ? [...colors][0] : "";
|
|
1052
880
|
}
|
|
1053
881
|
var swatches = {
|
|
1054
|
-
color: (name) => /* @__PURE__ */
|
|
1055
|
-
background: (name) => /* @__PURE__ */
|
|
882
|
+
color: (name) => /* @__PURE__ */ jsx("span", { "aria-hidden": "true", "data-color": name, className: "w-4 text-center font-medium", children: "A" }),
|
|
883
|
+
background: (name) => /* @__PURE__ */ jsx("span", { "aria-hidden": "true", "data-bg": name, className: "size-4 rounded-sm border border-border" })
|
|
1056
884
|
};
|
|
1057
885
|
function ColorGroups({ kit, value, onPick }) {
|
|
1058
886
|
const labels = useLabels();
|
|
1059
887
|
const textTitle = useId();
|
|
1060
888
|
const backgroundTitle = useId();
|
|
1061
|
-
const group = (key, title, titleId) => /* @__PURE__ */
|
|
1062
|
-
/* @__PURE__ */
|
|
1063
|
-
/* @__PURE__ */
|
|
889
|
+
const group = (key, title, titleId) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
890
|
+
/* @__PURE__ */ jsx(kit.Label, { id: titleId, children: title }),
|
|
891
|
+
/* @__PURE__ */ jsx(kit.RadioGroup, { "aria-labelledby": titleId, value: value[key], onValueChange: (name) => onPick(key, name), children: PALETTE.map((name) => /* @__PURE__ */ jsxs(kit.RadioItem, { value: name, indicator: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }), children: [
|
|
1064
892
|
swatches[key](name),
|
|
1065
893
|
labels.colors[name]
|
|
1066
894
|
] }, name)) })
|
|
1067
895
|
] });
|
|
1068
|
-
return /* @__PURE__ */
|
|
896
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1069
897
|
group("color", labels.textColor, textTitle),
|
|
1070
|
-
/* @__PURE__ */
|
|
898
|
+
/* @__PURE__ */ jsx(kit.Separator, {}),
|
|
1071
899
|
group("background", labels.backgroundColor, backgroundTitle)
|
|
1072
900
|
] });
|
|
1073
901
|
}
|
|
@@ -1076,12 +904,12 @@ function ColorMenu({ kit, controller, blocks }) {
|
|
|
1076
904
|
const blockIds = blocks.map((block) => block.id);
|
|
1077
905
|
const value = { color: sharedColor(blocks, "color"), background: sharedColor(blocks, "background") };
|
|
1078
906
|
const pick = (key, name) => runOnBlocks(controller, blockIds, setBlockColor({ [key]: name === "default" ? null : name }));
|
|
1079
|
-
return /* @__PURE__ */
|
|
1080
|
-
/* @__PURE__ */
|
|
1081
|
-
/* @__PURE__ */
|
|
907
|
+
return /* @__PURE__ */ jsxs(kit.Sub, { children: [
|
|
908
|
+
/* @__PURE__ */ jsxs(kit.SubTrigger, { children: [
|
|
909
|
+
/* @__PURE__ */ jsx(MenuIcon, { icon: Palette }),
|
|
1082
910
|
labels.color
|
|
1083
911
|
] }),
|
|
1084
|
-
/* @__PURE__ */
|
|
912
|
+
/* @__PURE__ */ jsx(kit.SubContent, { children: /* @__PURE__ */ jsx(ColorGroups, { kit, value, onPick: pick }) })
|
|
1085
913
|
] });
|
|
1086
914
|
}
|
|
1087
915
|
|
|
@@ -1126,12 +954,6 @@ function shortcutHint(key, isMac, labels) {
|
|
|
1126
954
|
return { text: formatShortcut(key, { isMac, labels }), aria };
|
|
1127
955
|
}
|
|
1128
956
|
|
|
1129
|
-
// src/gutter/TurnIntoMenu.tsx
|
|
1130
|
-
import { Repeat2 } from "lucide-react";
|
|
1131
|
-
|
|
1132
|
-
// src/blocks/code/CodeBlock.tsx
|
|
1133
|
-
import { useRef as useRef3 } from "react";
|
|
1134
|
-
|
|
1135
957
|
// src/blocks/code/code-languages.ts
|
|
1136
958
|
var language = (name, id = name.toLowerCase(), ...aliases) => ({ id, name, aliases });
|
|
1137
959
|
var CODE_LANGUAGES = [
|
|
@@ -1191,9 +1013,6 @@ function languageOptions(query, plainText) {
|
|
|
1191
1013
|
return [{ id: "", name: plainText }, ...CODE_LANGUAGES].filter(matches);
|
|
1192
1014
|
}
|
|
1193
1015
|
|
|
1194
|
-
// src/blocks/code/CodeEditor.tsx
|
|
1195
|
-
import { useCallback as useCallback2, useEffect as useEffect3, useRef } from "react";
|
|
1196
|
-
|
|
1197
1016
|
// src/blocks/insert-blocks.ts
|
|
1198
1017
|
var isEmptyParagraph = (schema, block) => isParagraph(block) && regionLength(block, primaryRegion(schema, block) ?? "") === 0;
|
|
1199
1018
|
function fresh(schema, { id, type, attrs, regions }, indent3) {
|
|
@@ -1424,9 +1243,6 @@ function runCodeAction(action, context) {
|
|
|
1424
1243
|
}
|
|
1425
1244
|
}
|
|
1426
1245
|
|
|
1427
|
-
// src/blocks/code/use-type-into-code.ts
|
|
1428
|
-
import { useEffect as useEffect2 } from "react";
|
|
1429
|
-
|
|
1430
1246
|
// src/view/input/intercept-keys.ts
|
|
1431
1247
|
function interceptKeys(controller, intercept) {
|
|
1432
1248
|
controller.keyInterceptors.add(intercept);
|
|
@@ -1435,7 +1251,7 @@ function interceptKeys(controller, intercept) {
|
|
|
1435
1251
|
|
|
1436
1252
|
// src/blocks/code/use-type-into-code.ts
|
|
1437
1253
|
function useTypeIntoCode(controller, blockId, field, edit2) {
|
|
1438
|
-
|
|
1254
|
+
useEffect(() => {
|
|
1439
1255
|
const typeInto = (event) => {
|
|
1440
1256
|
const area = field.current;
|
|
1441
1257
|
const { selection } = controller.editor.state;
|
|
@@ -1450,9 +1266,6 @@ function useTypeIntoCode(controller, blockId, field, edit2) {
|
|
|
1450
1266
|
return interceptKeys(controller, typeInto);
|
|
1451
1267
|
}, [controller, blockId, field, edit2]);
|
|
1452
1268
|
}
|
|
1453
|
-
|
|
1454
|
-
// src/blocks/code/CodeEditor.tsx
|
|
1455
|
-
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1456
1269
|
var sessions = 0;
|
|
1457
1270
|
function CodeEditor({ block, controller, field, focusControls }) {
|
|
1458
1271
|
const labels = useLabels();
|
|
@@ -1461,12 +1274,12 @@ function CodeEditor({ block, controller, field, focusControls }) {
|
|
|
1461
1274
|
const mark = useRef(null);
|
|
1462
1275
|
const { editing, stop } = useVoidEditing(controller, block.id);
|
|
1463
1276
|
const blockId = block.id;
|
|
1464
|
-
const reveal =
|
|
1277
|
+
const reveal = useCallback(() => {
|
|
1465
1278
|
if (field.current !== null && drawn.current !== null && mark.current !== null) {
|
|
1466
1279
|
revealCaret(field.current, drawn.current, mark.current);
|
|
1467
1280
|
}
|
|
1468
1281
|
}, [field]);
|
|
1469
|
-
|
|
1282
|
+
useEffect(() => {
|
|
1470
1283
|
const area = field.current;
|
|
1471
1284
|
if (!editing || area === null) return;
|
|
1472
1285
|
area.focus();
|
|
@@ -1474,7 +1287,7 @@ function CodeEditor({ block, controller, field, focusControls }) {
|
|
|
1474
1287
|
reveal();
|
|
1475
1288
|
stop();
|
|
1476
1289
|
}, [editing, stop, field, reveal]);
|
|
1477
|
-
const edit2 =
|
|
1290
|
+
const edit2 = useCallback(
|
|
1478
1291
|
(next) => {
|
|
1479
1292
|
const area = field.current;
|
|
1480
1293
|
if (area === null) return;
|
|
@@ -1490,8 +1303,8 @@ function CodeEditor({ block, controller, field, focusControls }) {
|
|
|
1490
1303
|
const action = codeKeyAction(event, fieldOf(area), controller.isMac);
|
|
1491
1304
|
if (action !== null && runCodeAction(action, { controller, blockId, area, edit: edit2, focusControls })) event.preventDefault();
|
|
1492
1305
|
};
|
|
1493
|
-
return /* @__PURE__ */
|
|
1494
|
-
/* @__PURE__ */
|
|
1306
|
+
return /* @__PURE__ */ jsx("div", { ...{ [NATIVE_INTERACTION]: "" }, dir: "ltr", className: "quoin-code-scroll", children: /* @__PURE__ */ jsxs("div", { className: "quoin-code-lines", children: [
|
|
1307
|
+
/* @__PURE__ */ jsx(
|
|
1495
1308
|
HighlightOverlay,
|
|
1496
1309
|
{
|
|
1497
1310
|
"aria-hidden": "true",
|
|
@@ -1500,8 +1313,8 @@ function CodeEditor({ block, controller, field, focusControls }) {
|
|
|
1500
1313
|
language: str(block.attrs.language)
|
|
1501
1314
|
}
|
|
1502
1315
|
),
|
|
1503
|
-
/* @__PURE__ */
|
|
1504
|
-
/* @__PURE__ */
|
|
1316
|
+
/* @__PURE__ */ jsx("span", { ref: mark, "aria-hidden": "true", className: "quoin-code-caret" }),
|
|
1317
|
+
/* @__PURE__ */ jsx(
|
|
1505
1318
|
"textarea",
|
|
1506
1319
|
{
|
|
1507
1320
|
ref: field,
|
|
@@ -1526,15 +1339,6 @@ function CodeEditor({ block, controller, field, focusControls }) {
|
|
|
1526
1339
|
)
|
|
1527
1340
|
] }) });
|
|
1528
1341
|
}
|
|
1529
|
-
|
|
1530
|
-
// src/blocks/code/CopyCodeButton.tsx
|
|
1531
|
-
import { useEffect as useEffect4, useState as useState2 } from "react";
|
|
1532
|
-
import { Check, Copy as Copy2 } from "lucide-react";
|
|
1533
|
-
|
|
1534
|
-
// src/ui/button.tsx
|
|
1535
|
-
import * as React3 from "react";
|
|
1536
|
-
import { Slot } from "@radix-ui/react-slot";
|
|
1537
|
-
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1538
1342
|
var BASE = [
|
|
1539
1343
|
"inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,background-color,border-color,box-shadow,opacity] disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 shrink-0",
|
|
1540
1344
|
FOCUS_RING
|
|
@@ -1552,9 +1356,9 @@ var SIZES = {
|
|
|
1552
1356
|
"icon-sm": `size-8 ${SQUARE_TAP_TARGET_FLOOR}`
|
|
1553
1357
|
};
|
|
1554
1358
|
var buttonVariants = ({ variant = "default", size = "default", className }) => cn(BASE, variant && VARIANTS[variant], size && SIZES[size], className);
|
|
1555
|
-
var Button =
|
|
1359
|
+
var Button = React7.forwardRef(function Button2({ className, variant = "default", size = "default", asChild = false, ...props }, ref) {
|
|
1556
1360
|
const Comp = asChild ? Slot : "button";
|
|
1557
|
-
return /* @__PURE__ */
|
|
1361
|
+
return /* @__PURE__ */ jsx(
|
|
1558
1362
|
Comp,
|
|
1559
1363
|
{
|
|
1560
1364
|
ref,
|
|
@@ -1566,15 +1370,12 @@ var Button = React3.forwardRef(function Button2({ className, variant = "default"
|
|
|
1566
1370
|
}
|
|
1567
1371
|
);
|
|
1568
1372
|
});
|
|
1569
|
-
|
|
1570
|
-
// src/blocks/code/CopyCodeButton.tsx
|
|
1571
|
-
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
1572
1373
|
var COPIED_FOR_MS = 1500;
|
|
1573
1374
|
function CopyCodeButton({ code, controller }) {
|
|
1574
1375
|
const labels = useLabels();
|
|
1575
1376
|
const readOnly = useReadOnly(controller);
|
|
1576
|
-
const [copied, setCopied] =
|
|
1577
|
-
|
|
1377
|
+
const [copied, setCopied] = useState(false);
|
|
1378
|
+
useEffect(() => {
|
|
1578
1379
|
if (!copied) return;
|
|
1579
1380
|
const timer = setTimeout(() => setCopied(false), COPIED_FOR_MS);
|
|
1580
1381
|
return () => clearTimeout(timer);
|
|
@@ -1584,8 +1385,8 @@ function CopyCodeButton({ code, controller }) {
|
|
|
1584
1385
|
setCopied(true);
|
|
1585
1386
|
controller.announce(labels.copied);
|
|
1586
1387
|
};
|
|
1587
|
-
const Icon = copied ? Check :
|
|
1588
|
-
return /* @__PURE__ */
|
|
1388
|
+
const Icon = copied ? Check : Copy;
|
|
1389
|
+
return /* @__PURE__ */ jsx(
|
|
1589
1390
|
Button,
|
|
1590
1391
|
{
|
|
1591
1392
|
type: "button",
|
|
@@ -1595,21 +1396,15 @@ function CopyCodeButton({ code, controller }) {
|
|
|
1595
1396
|
"aria-label": labels.copyCode,
|
|
1596
1397
|
className: "quoin-code-control",
|
|
1597
1398
|
onClick: () => void copy(),
|
|
1598
|
-
children: /* @__PURE__ */
|
|
1399
|
+
children: /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" })
|
|
1599
1400
|
}
|
|
1600
1401
|
);
|
|
1601
1402
|
}
|
|
1602
1403
|
|
|
1603
|
-
// src/blocks/code/LanguageCombobox.tsx
|
|
1604
|
-
import { useId as useId2, useRef as useRef2, useState as useState3 } from "react";
|
|
1605
|
-
|
|
1606
1404
|
// src/menus/floating/keep-focus.ts
|
|
1607
1405
|
function keepFocus(event) {
|
|
1608
1406
|
if (!("pointerType" in event) || event.pointerType !== "touch") event.preventDefault();
|
|
1609
1407
|
}
|
|
1610
|
-
|
|
1611
|
-
// src/menus/suggestion/SuggestionOption.tsx
|
|
1612
|
-
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
1613
1408
|
var OPTION = cn(
|
|
1614
1409
|
"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm",
|
|
1615
1410
|
"data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground",
|
|
@@ -1617,7 +1412,7 @@ var OPTION = cn(
|
|
|
1617
1412
|
TAP_TARGET_FLOOR
|
|
1618
1413
|
);
|
|
1619
1414
|
function SuggestionOption({ id, active, onHighlight, onChoose, children }) {
|
|
1620
|
-
return /* @__PURE__ */
|
|
1415
|
+
return /* @__PURE__ */ jsx(
|
|
1621
1416
|
"div",
|
|
1622
1417
|
{
|
|
1623
1418
|
role: "option",
|
|
@@ -1633,19 +1428,14 @@ function SuggestionOption({ id, active, onHighlight, onChoose, children }) {
|
|
|
1633
1428
|
}
|
|
1634
1429
|
);
|
|
1635
1430
|
}
|
|
1636
|
-
|
|
1637
|
-
// src/ui/popover.tsx
|
|
1638
|
-
import * as React4 from "react";
|
|
1639
|
-
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
1640
|
-
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
1641
1431
|
function Popover(props) {
|
|
1642
|
-
return /* @__PURE__ */
|
|
1432
|
+
return /* @__PURE__ */ jsx(PopoverPrimitive.Root, { ...props });
|
|
1643
1433
|
}
|
|
1644
|
-
var PopoverAnchor = /* @__PURE__ */
|
|
1645
|
-
return /* @__PURE__ */
|
|
1434
|
+
var PopoverAnchor = /* @__PURE__ */ React7.forwardRef(function PopoverAnchor2(props, ref) {
|
|
1435
|
+
return /* @__PURE__ */ jsx(PopoverPrimitive.Anchor, { ref, "data-slot": "popover-anchor", ...props });
|
|
1646
1436
|
});
|
|
1647
|
-
var PopoverContent = /* @__PURE__ */
|
|
1648
|
-
return /* @__PURE__ */
|
|
1437
|
+
var PopoverContent = /* @__PURE__ */ React7.forwardRef(function PopoverContent2({ className, align = "center", sideOffset = 4, ...props }, ref) {
|
|
1438
|
+
return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
1649
1439
|
PopoverPrimitive.Content,
|
|
1650
1440
|
{
|
|
1651
1441
|
ref,
|
|
@@ -1668,20 +1458,17 @@ var preventDefault = (event) => event.preventDefault();
|
|
|
1668
1458
|
function setBlockAttrs(controller, blockId, patch) {
|
|
1669
1459
|
if (!controller.readOnly) controller.run(onBlock(blockId, setAttrs(patch)));
|
|
1670
1460
|
}
|
|
1671
|
-
|
|
1672
|
-
// src/blocks/code/LanguageCombobox.tsx
|
|
1673
|
-
import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1674
1461
|
var FIELD = `quoin-code-language quoin-code-control ${FOCUS_RING}`;
|
|
1675
1462
|
var CONTENT = `${MENU_CONTENT} flex max-h-64 w-48 flex-col overflow-y-hidden`;
|
|
1676
1463
|
function LanguageCombobox({ blockId, controller, language: language2, field, onDone }) {
|
|
1677
1464
|
const labels = useLabels();
|
|
1678
|
-
const listboxId =
|
|
1679
|
-
const list =
|
|
1680
|
-
const settled =
|
|
1681
|
-
const focusedByPress =
|
|
1465
|
+
const listboxId = useId();
|
|
1466
|
+
const list = useRef(null);
|
|
1467
|
+
const settled = useRef(false);
|
|
1468
|
+
const focusedByPress = useRef(false);
|
|
1682
1469
|
const shown = languageName(language2) ?? language2;
|
|
1683
|
-
const [draft, setDraft] =
|
|
1684
|
-
const [active, setActive] =
|
|
1470
|
+
const [draft, setDraft] = useState(null);
|
|
1471
|
+
const [active, setActive] = useState(-1);
|
|
1685
1472
|
const options = draft === null ? [] : languageOptions(draft === shown ? "" : draft, labels.plainText);
|
|
1686
1473
|
const open = options.length > 0;
|
|
1687
1474
|
const optionId = (index) => `${listboxId}-${index}`;
|
|
@@ -1721,8 +1508,8 @@ function LanguageCombobox({ blockId, controller, language: language2, field, onD
|
|
|
1721
1508
|
finish(event.key === "Enter" ? commit : close);
|
|
1722
1509
|
}
|
|
1723
1510
|
};
|
|
1724
|
-
return /* @__PURE__ */
|
|
1725
|
-
/* @__PURE__ */
|
|
1511
|
+
return /* @__PURE__ */ jsxs(Popover, { open, children: [
|
|
1512
|
+
/* @__PURE__ */ jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
1726
1513
|
"input",
|
|
1727
1514
|
{
|
|
1728
1515
|
ref: field,
|
|
@@ -1760,7 +1547,7 @@ function LanguageCombobox({ blockId, controller, language: language2, field, onD
|
|
|
1760
1547
|
onKeyDown
|
|
1761
1548
|
}
|
|
1762
1549
|
) }),
|
|
1763
|
-
/* @__PURE__ */
|
|
1550
|
+
/* @__PURE__ */ jsx(
|
|
1764
1551
|
PopoverContent,
|
|
1765
1552
|
{
|
|
1766
1553
|
role: void 0,
|
|
@@ -1768,7 +1555,7 @@ function LanguageCombobox({ blockId, controller, language: language2, field, onD
|
|
|
1768
1555
|
className: CONTENT,
|
|
1769
1556
|
onOpenAutoFocus: preventDefault,
|
|
1770
1557
|
onCloseAutoFocus: preventDefault,
|
|
1771
|
-
children: /* @__PURE__ */
|
|
1558
|
+
children: /* @__PURE__ */ jsx("div", { ref: list, role: "listbox", id: listboxId, "aria-label": labels.codeLanguage, className: "min-h-0 overflow-y-auto", children: options.map((option, index) => /* @__PURE__ */ jsx(
|
|
1772
1559
|
SuggestionOption,
|
|
1773
1560
|
{
|
|
1774
1561
|
id: optionId(index),
|
|
@@ -1783,20 +1570,17 @@ function LanguageCombobox({ blockId, controller, language: language2, field, onD
|
|
|
1783
1570
|
)
|
|
1784
1571
|
] });
|
|
1785
1572
|
}
|
|
1786
|
-
|
|
1787
|
-
// src/blocks/code/CodeBlock.tsx
|
|
1788
|
-
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1789
1573
|
var CodeBlock = ({ block, controller }) => {
|
|
1790
1574
|
const labels = useLabels();
|
|
1791
1575
|
const readOnly = useReadOnly(controller);
|
|
1792
|
-
const languageField =
|
|
1793
|
-
const codeField =
|
|
1576
|
+
const languageField = useRef(null);
|
|
1577
|
+
const codeField = useRef(null);
|
|
1794
1578
|
const code = str(block.attrs.code);
|
|
1795
1579
|
const language2 = str(block.attrs.language);
|
|
1796
1580
|
const name = languageName(language2) ?? language2;
|
|
1797
|
-
return /* @__PURE__ */
|
|
1798
|
-
/* @__PURE__ */
|
|
1799
|
-
readOnly ? /* @__PURE__ */
|
|
1581
|
+
return /* @__PURE__ */ jsxs("div", { role: "group", "aria-label": labels.blockNames.code, contentEditable: false, className: "quoin-code", children: [
|
|
1582
|
+
/* @__PURE__ */ jsxs("div", { className: "quoin-code-header", children: [
|
|
1583
|
+
readOnly ? /* @__PURE__ */ jsx("span", { className: "quoin-code-language quoin-code-control", children: name || labels.plainText }) : /* @__PURE__ */ jsx(
|
|
1800
1584
|
LanguageCombobox,
|
|
1801
1585
|
{
|
|
1802
1586
|
blockId: block.id,
|
|
@@ -1806,9 +1590,9 @@ var CodeBlock = ({ block, controller }) => {
|
|
|
1806
1590
|
onDone: () => codeField.current?.focus()
|
|
1807
1591
|
}
|
|
1808
1592
|
),
|
|
1809
|
-
/* @__PURE__ */
|
|
1593
|
+
/* @__PURE__ */ jsx(CopyCodeButton, { code, controller })
|
|
1810
1594
|
] }),
|
|
1811
|
-
readOnly ? /* @__PURE__ */
|
|
1595
|
+
readOnly ? /* @__PURE__ */ jsx("div", { dir: "ltr", role: "region", "aria-label": name || labels.codeText, tabIndex: 0, className: `quoin-code-scroll ${FOCUS_RING}`, children: /* @__PURE__ */ jsx(HighlightOverlay, { code, language: language2 }) }) : /* @__PURE__ */ jsx(
|
|
1812
1596
|
CodeEditor,
|
|
1813
1597
|
{
|
|
1814
1598
|
block,
|
|
@@ -1819,32 +1603,21 @@ var CodeBlock = ({ block, controller }) => {
|
|
|
1819
1603
|
)
|
|
1820
1604
|
] });
|
|
1821
1605
|
};
|
|
1822
|
-
|
|
1823
|
-
// src/blocks/file/FileBlock.tsx
|
|
1824
|
-
import { useRef as useRef8 } from "react";
|
|
1825
|
-
|
|
1826
|
-
// src/blocks/upload/UploadArea.tsx
|
|
1827
|
-
import { useEffect as useEffect6, useRef as useRef6 } from "react";
|
|
1828
|
-
|
|
1829
|
-
// src/upload/FilePickerButton.tsx
|
|
1830
|
-
import * as React5 from "react";
|
|
1831
|
-
import { Upload } from "lucide-react";
|
|
1832
|
-
import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1833
1606
|
function FilePickerButton({ label, accept, disabled, busy = false, onPick }) {
|
|
1834
|
-
const inputRef =
|
|
1835
|
-
const restoreFocus =
|
|
1836
|
-
|
|
1607
|
+
const inputRef = React7.useRef(null);
|
|
1608
|
+
const restoreFocus = React7.useRef(false);
|
|
1609
|
+
React7.useEffect(() => {
|
|
1837
1610
|
if (disabled || !restoreFocus.current) return;
|
|
1838
1611
|
restoreFocus.current = false;
|
|
1839
1612
|
const { activeElement } = document;
|
|
1840
1613
|
if (activeElement === null || activeElement === document.body) inputRef.current?.focus();
|
|
1841
1614
|
}, [disabled]);
|
|
1842
|
-
return /* @__PURE__ */
|
|
1843
|
-
/* @__PURE__ */
|
|
1844
|
-
/* @__PURE__ */
|
|
1615
|
+
return /* @__PURE__ */ jsxs("span", { className: "relative inline-flex rounded-md has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-[var(--quoin-ring)]", children: [
|
|
1616
|
+
/* @__PURE__ */ jsx(Button, { asChild: true, variant: "outline", size: "sm", children: /* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: disabled || busy ? "pointer-events-none opacity-50" : void 0, children: [
|
|
1617
|
+
/* @__PURE__ */ jsx(Upload, { "aria-hidden": "true" }),
|
|
1845
1618
|
label
|
|
1846
1619
|
] }) }),
|
|
1847
|
-
/* @__PURE__ */
|
|
1620
|
+
/* @__PURE__ */ jsx(
|
|
1848
1621
|
"input",
|
|
1849
1622
|
{
|
|
1850
1623
|
ref: inputRef,
|
|
@@ -1913,15 +1686,12 @@ function selectHandlers(controller, blockId, root, onSelect) {
|
|
|
1913
1686
|
}
|
|
1914
1687
|
};
|
|
1915
1688
|
}
|
|
1916
|
-
|
|
1917
|
-
// src/blocks/upload/use-block-upload.ts
|
|
1918
|
-
import { useCallback as useCallback3, useRef as useRef5, useState as useState4 } from "react";
|
|
1919
1689
|
var IDLE = { busy: false, error: "" };
|
|
1920
1690
|
function useBlockUpload(controller, blockId, area, uploader) {
|
|
1921
1691
|
const { upload, resolveAssetUrl, onError, labels } = useQuoin();
|
|
1922
|
-
const [state, setState] =
|
|
1923
|
-
const started =
|
|
1924
|
-
const start =
|
|
1692
|
+
const [state, setState] = useState(IDLE);
|
|
1693
|
+
const started = useRef(0);
|
|
1694
|
+
const start = useCallback(
|
|
1925
1695
|
(file) => {
|
|
1926
1696
|
if (!upload) return onError(new Error(labels.uploadsUnavailable));
|
|
1927
1697
|
const run = ++started.current;
|
|
@@ -1941,16 +1711,13 @@ function useBlockUpload(controller, blockId, area, uploader) {
|
|
|
1941
1711
|
);
|
|
1942
1712
|
return { ...state, start };
|
|
1943
1713
|
}
|
|
1944
|
-
|
|
1945
|
-
// src/blocks/upload/UploadArea.tsx
|
|
1946
|
-
import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1947
1714
|
var fileIn = (transfer, takes) => Array.from(transfer?.files ?? []).find(takes);
|
|
1948
1715
|
function UploadArea(props) {
|
|
1949
1716
|
const { blockId, controller, uploader, takes, accept, label, hint, className, onSelect, actions, children } = props;
|
|
1950
1717
|
const { upload, labels } = useQuoin();
|
|
1951
|
-
const area =
|
|
1718
|
+
const area = useRef(null);
|
|
1952
1719
|
const { busy, error, start } = useBlockUpload(controller, blockId, area, uploader);
|
|
1953
|
-
|
|
1720
|
+
useEffect(() => {
|
|
1954
1721
|
const element = area.current;
|
|
1955
1722
|
const onDrop = (event) => {
|
|
1956
1723
|
const file = fileIn(event.dataTransfer, takes);
|
|
@@ -1968,7 +1735,7 @@ function UploadArea(props) {
|
|
|
1968
1735
|
event.preventDefault();
|
|
1969
1736
|
start(file);
|
|
1970
1737
|
};
|
|
1971
|
-
return /* @__PURE__ */
|
|
1738
|
+
return /* @__PURE__ */ jsxs(
|
|
1972
1739
|
"div",
|
|
1973
1740
|
{
|
|
1974
1741
|
ref: area,
|
|
@@ -1976,32 +1743,29 @@ function UploadArea(props) {
|
|
|
1976
1743
|
onPaste,
|
|
1977
1744
|
...selectHandlers(controller, blockId, area, onSelect),
|
|
1978
1745
|
children: [
|
|
1979
|
-
/* @__PURE__ */
|
|
1980
|
-
/* @__PURE__ */
|
|
1746
|
+
/* @__PURE__ */ jsxs("div", { className: "quoin-upload-actions", children: [
|
|
1747
|
+
/* @__PURE__ */ jsx(FilePickerButton, { label, accept, disabled: !upload, busy, onPick: start }),
|
|
1981
1748
|
actions
|
|
1982
1749
|
] }),
|
|
1983
1750
|
children,
|
|
1984
|
-
/* @__PURE__ */
|
|
1985
|
-
/* @__PURE__ */
|
|
1986
|
-
error !== "" && /* @__PURE__ */
|
|
1751
|
+
/* @__PURE__ */ jsx("p", { className: "quoin-block-message", children: upload ? hint : labels.uploadsUnavailable }),
|
|
1752
|
+
/* @__PURE__ */ jsx("p", { role: "status", className: busy ? "quoin-block-message" : "sr-only", children: busy ? labels.uploading : "" }),
|
|
1753
|
+
error !== "" && /* @__PURE__ */ jsx("p", { role: "alert", className: "quoin-block-message text-destructive", children: error })
|
|
1987
1754
|
]
|
|
1988
1755
|
}
|
|
1989
1756
|
);
|
|
1990
1757
|
}
|
|
1991
|
-
|
|
1992
|
-
// src/blocks/void/use-node-keys.ts
|
|
1993
|
-
import { useEffect as useEffect7 } from "react";
|
|
1994
1758
|
var CONTROL = "input:not([disabled]), button:not([disabled])";
|
|
1995
1759
|
var typed = (event) => !event.ctrlKey && !event.metaKey && [...event.key].length === 1;
|
|
1996
1760
|
function useNodeKeys(controller, blockId, editable, opens, root, { enter, type } = {}) {
|
|
1997
1761
|
const { editing, stop } = useVoidEditing(controller, blockId, editable && opens);
|
|
1998
|
-
|
|
1762
|
+
useEffect(() => {
|
|
1999
1763
|
if (!editing) return;
|
|
2000
1764
|
stop();
|
|
2001
1765
|
if (enter) enter();
|
|
2002
1766
|
else root.current?.querySelector(CONTROL)?.focus();
|
|
2003
1767
|
}, [editing, stop, enter, root]);
|
|
2004
|
-
|
|
1768
|
+
useEffect(() => {
|
|
2005
1769
|
if (!editable) return;
|
|
2006
1770
|
const intercept = (event) => {
|
|
2007
1771
|
const { selection } = controller.editor.state;
|
|
@@ -2014,10 +1778,6 @@ function useNodeKeys(controller, blockId, editable, opens, root, { enter, type }
|
|
|
2014
1778
|
}, [controller, blockId, editable, type]);
|
|
2015
1779
|
}
|
|
2016
1780
|
|
|
2017
|
-
// src/blocks/file/FileCard.tsx
|
|
2018
|
-
import { useRef as useRef7 } from "react";
|
|
2019
|
-
import { Download } from "lucide-react";
|
|
2020
|
-
|
|
2021
1781
|
// src/menus/bubble/bubble-part.ts
|
|
2022
1782
|
var BUBBLE_PART = "data-quoin-bubble";
|
|
2023
1783
|
var partIds = /* @__PURE__ */ new WeakMap();
|
|
@@ -2041,15 +1801,12 @@ function focusInEditor(controller) {
|
|
|
2041
1801
|
const active = document.activeElement;
|
|
2042
1802
|
return active !== null && (controller.isEditorElement(active) || isBubblePart(active, controller));
|
|
2043
1803
|
}
|
|
2044
|
-
|
|
2045
|
-
// src/blocks/file/file-icon.ts
|
|
2046
|
-
import { FileArchive, FileIcon, FileImage, FileMusic, FilePlay, FileText as FileText2 } from "lucide-react";
|
|
2047
1804
|
var KINDS = [
|
|
2048
1805
|
[FileImage, /^(image\/|(png|jpe?g|gif|webp|svg|heic|bmp)$)/],
|
|
2049
1806
|
[FileMusic, /^(audio\/|(mp3|wav|ogg|flac|m4a|aac)$)/],
|
|
2050
1807
|
[FilePlay, /^(video\/|(mp4|mov|webm|mkv|avi|mpe?g)$)/],
|
|
2051
1808
|
[FileArchive, /^(zip|rar|7z|tar|gz|xz)$/],
|
|
2052
|
-
[
|
|
1809
|
+
[FileText, /^(text\/|(txt|md|csv|pdf|rtf|docx?)$)/]
|
|
2053
1810
|
];
|
|
2054
1811
|
var kindOf = (value) => KINDS.find(([, pattern]) => pattern.test(value))?.[0];
|
|
2055
1812
|
var fileIcon = (mime, filename) => kindOf(mime) ?? kindOf(/\.([^.]+)$/.exec(filename)?.[1].toLowerCase() ?? "") ?? FileIcon;
|
|
@@ -2057,22 +1814,19 @@ var fileIcon = (mime, filename) => kindOf(mime) ?? kindOf(/\.([^.]+)$/.exec(file
|
|
|
2057
1814
|
// src/blocks/file/file-source.ts
|
|
2058
1815
|
var fileName = (attrs) => str(attrs.filename) || str(attrs.storageKey);
|
|
2059
1816
|
var hasFile = (attrs) => fileName(attrs) !== "";
|
|
2060
|
-
|
|
2061
|
-
// src/blocks/file/FileCard.tsx
|
|
2062
|
-
import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2063
1817
|
function FileCard({ block, controller, readOnly }) {
|
|
2064
1818
|
const { labels, resolveAssetUrl } = useQuoin();
|
|
2065
|
-
const card =
|
|
1819
|
+
const card = useRef(null);
|
|
2066
1820
|
const { id, attrs } = block;
|
|
2067
1821
|
const name = fileName(attrs);
|
|
2068
1822
|
const size = optionalNumber(attrs.size);
|
|
2069
1823
|
const href = assetHref(resolveAssetUrl, str(attrs.storageKey));
|
|
2070
1824
|
const Icon = fileIcon(str(attrs.mime), name);
|
|
2071
|
-
return /* @__PURE__ */
|
|
2072
|
-
/* @__PURE__ */
|
|
2073
|
-
/* @__PURE__ */
|
|
2074
|
-
size !== void 0 && /* @__PURE__ */
|
|
2075
|
-
href !== null && /* @__PURE__ */
|
|
1825
|
+
return /* @__PURE__ */ jsxs("div", { ref: card, className: "quoin-file-card", ...selectHandlers(controller, id, card), children: [
|
|
1826
|
+
/* @__PURE__ */ jsx(Icon, { "aria-hidden": "true", className: "quoin-file-icon" }),
|
|
1827
|
+
/* @__PURE__ */ jsx("span", { className: "quoin-file-name", children: name }),
|
|
1828
|
+
size !== void 0 && /* @__PURE__ */ jsx("span", { className: "quoin-file-size", children: labels.fileSize(size) }),
|
|
1829
|
+
href !== null && /* @__PURE__ */ jsxs(
|
|
2076
1830
|
"a",
|
|
2077
1831
|
{
|
|
2078
1832
|
href,
|
|
@@ -2084,7 +1838,7 @@ function FileCard({ block, controller, readOnly }) {
|
|
|
2084
1838
|
tabIndex: readOnly ? void 0 : -1,
|
|
2085
1839
|
...readOnly ? void 0 : bubblePart(controller),
|
|
2086
1840
|
children: [
|
|
2087
|
-
/* @__PURE__ */
|
|
1841
|
+
/* @__PURE__ */ jsx(Download, { "aria-hidden": "true" }),
|
|
2088
1842
|
labels.download
|
|
2089
1843
|
]
|
|
2090
1844
|
}
|
|
@@ -2137,17 +1891,14 @@ var uploadFile = (controller, blockId, file, host) => uploadInto(
|
|
|
2137
1891
|
host,
|
|
2138
1892
|
(stored) => writeAttrs(controller, blockId, fileAttrs(file, stored), true)
|
|
2139
1893
|
);
|
|
2140
|
-
|
|
2141
|
-
// src/blocks/file/FileBlock.tsx
|
|
2142
|
-
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
2143
1894
|
var anyFile = () => true;
|
|
2144
1895
|
var FileBlock = ({ block, controller }) => {
|
|
2145
1896
|
const labels = useLabels();
|
|
2146
1897
|
const readOnly = useReadOnly(controller);
|
|
2147
|
-
const root =
|
|
1898
|
+
const root = useRef(null);
|
|
2148
1899
|
const filled = hasFile(block.attrs);
|
|
2149
1900
|
useNodeKeys(controller, block.id, !readOnly, !filled, root);
|
|
2150
|
-
const empty = readOnly ? /* @__PURE__ */
|
|
1901
|
+
const empty = readOnly ? /* @__PURE__ */ jsx("p", { className: "quoin-block-message", children: labels.emptyFile }) : /* @__PURE__ */ jsx(
|
|
2151
1902
|
UploadArea,
|
|
2152
1903
|
{
|
|
2153
1904
|
blockId: block.id,
|
|
@@ -2158,15 +1909,11 @@ var FileBlock = ({ block, controller }) => {
|
|
|
2158
1909
|
hint: labels.dropFile
|
|
2159
1910
|
}
|
|
2160
1911
|
);
|
|
2161
|
-
return /* @__PURE__ */
|
|
1912
|
+
return /* @__PURE__ */ jsx("div", { ref: root, role: "group", "aria-label": labels.blockNames.file, contentEditable: false, className: "quoin-file", children: filled ? /* @__PURE__ */ jsx(FileCard, { block, controller, readOnly }) : empty });
|
|
2162
1913
|
};
|
|
2163
|
-
|
|
2164
|
-
// src/blocks/upload/use-replace-picker.tsx
|
|
2165
|
-
import { useRef as useRef9 } from "react";
|
|
2166
|
-
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
2167
1914
|
function useReplacePicker(controller, blockId, uploader, accept) {
|
|
2168
1915
|
const { labels, upload, resolveAssetUrl, onError } = useQuoin();
|
|
2169
|
-
const picker =
|
|
1916
|
+
const picker = useRef(null);
|
|
2170
1917
|
const replace = (event) => {
|
|
2171
1918
|
const file = event.target.files?.[0];
|
|
2172
1919
|
event.target.value = "";
|
|
@@ -2178,24 +1925,21 @@ function useReplacePicker(controller, blockId, uploader, accept) {
|
|
|
2178
1925
|
};
|
|
2179
1926
|
return {
|
|
2180
1927
|
open: upload && (() => picker.current?.click()),
|
|
2181
|
-
input: /* @__PURE__ */
|
|
1928
|
+
input: /* @__PURE__ */ jsx("input", { ref: picker, type: "file", accept, hidden: true, tabIndex: -1, onChange: replace })
|
|
2182
1929
|
};
|
|
2183
1930
|
}
|
|
2184
1931
|
|
|
2185
|
-
// src/blocks/void/block-part.ts
|
|
2186
|
-
import { useMemo as useMemo3 } from "react";
|
|
2187
|
-
|
|
2188
1932
|
// src/menus/floating/virtual-anchor.ts
|
|
2189
1933
|
var ROOM_BELOW = 240;
|
|
2190
1934
|
function virtualAnchor(measure2, context) {
|
|
2191
|
-
let last2
|
|
1935
|
+
let last2;
|
|
2192
1936
|
return {
|
|
2193
1937
|
// Read when Floating UI starts watching, after the commit that drew the anchor's host has registered it.
|
|
2194
1938
|
get contextElement() {
|
|
2195
1939
|
return context();
|
|
2196
1940
|
},
|
|
2197
1941
|
getBoundingClientRect() {
|
|
2198
|
-
last2 = measure2() ?? last2;
|
|
1942
|
+
last2 = measure2() ?? last2 ?? new DOMRect();
|
|
2199
1943
|
return last2;
|
|
2200
1944
|
}
|
|
2201
1945
|
};
|
|
@@ -2207,28 +1951,22 @@ function sideFor(anchor, viewportHeight) {
|
|
|
2207
1951
|
// src/blocks/void/block-part.ts
|
|
2208
1952
|
var blockPart = (controller, blockId, selector) => controller.blockElement(blockId)?.querySelector(selector) ?? void 0;
|
|
2209
1953
|
function usePartAnchor(controller, blockId, selector) {
|
|
2210
|
-
return
|
|
1954
|
+
return useMemo(() => {
|
|
2211
1955
|
const part = () => blockPart(controller, blockId, selector);
|
|
2212
1956
|
return { current: virtualAnchor(() => part()?.getBoundingClientRect() ?? null, part) };
|
|
2213
1957
|
}, [controller, blockId, selector]);
|
|
2214
1958
|
}
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
1959
|
+
var replaceItem = (title, run) => run ? [{ id: "replace", title, icon: Upload, run }] : [];
|
|
1960
|
+
function deleteBlock(controller, blockId) {
|
|
1961
|
+
runOnBlocks(controller, [blockId], deleteBlocks);
|
|
1962
|
+
controller.focus();
|
|
1963
|
+
}
|
|
2219
1964
|
var deleteItem = (blockId, title) => ({
|
|
2220
1965
|
id: "delete",
|
|
2221
1966
|
title,
|
|
2222
|
-
icon:
|
|
2223
|
-
run: (controller) =>
|
|
2224
|
-
runOnBlocks(controller, [blockId], deleteBlocks);
|
|
2225
|
-
controller.focus();
|
|
2226
|
-
}
|
|
1967
|
+
icon: Trash,
|
|
1968
|
+
run: (controller) => deleteBlock(controller, blockId)
|
|
2227
1969
|
});
|
|
2228
|
-
|
|
2229
|
-
// src/menus/bubble/bubble-items.tsx
|
|
2230
|
-
import { Bold, Code as Code2, Italic, Link as Link2, Strikethrough, Subscript, Superscript, Underline } from "lucide-react";
|
|
2231
|
-
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
2232
1970
|
var PRESSED = "aria-pressed:bg-accent aria-pressed:text-accent-foreground";
|
|
2233
1971
|
function markItem(mark, title, icon) {
|
|
2234
1972
|
return {
|
|
@@ -2242,7 +1980,7 @@ function markItem(mark, title, icon) {
|
|
|
2242
1980
|
var linkItem = (labels, openLink) => ({
|
|
2243
1981
|
id: "link",
|
|
2244
1982
|
title: labels.link,
|
|
2245
|
-
icon:
|
|
1983
|
+
icon: Link,
|
|
2246
1984
|
run: openLink
|
|
2247
1985
|
});
|
|
2248
1986
|
function bubbleItems(labels, openLink) {
|
|
@@ -2252,7 +1990,7 @@ function bubbleItems(labels, openLink) {
|
|
|
2252
1990
|
markItem("italic", labels.italic, Italic),
|
|
2253
1991
|
markItem("underline", labels.underline, Underline),
|
|
2254
1992
|
markItem("strike", labels.strike, Strikethrough),
|
|
2255
|
-
markItem("code", labels.code,
|
|
1993
|
+
markItem("code", labels.code, Code),
|
|
2256
1994
|
linkItem(labels, openLink)
|
|
2257
1995
|
],
|
|
2258
1996
|
scripts: [markItem("sub", labels.subscript, Subscript), markItem("sup", labels.superscript, Superscript)]
|
|
@@ -2261,7 +1999,7 @@ function bubbleItems(labels, openLink) {
|
|
|
2261
1999
|
function ToolbarButton({ item, state, controller, buttonRef }) {
|
|
2262
2000
|
if (item.available?.(state) === false) return null;
|
|
2263
2001
|
const Icon = item.icon;
|
|
2264
|
-
return /* @__PURE__ */
|
|
2002
|
+
return /* @__PURE__ */ jsx(
|
|
2265
2003
|
Button,
|
|
2266
2004
|
{
|
|
2267
2005
|
ref: buttonRef,
|
|
@@ -2272,13 +2010,10 @@ function ToolbarButton({ item, state, controller, buttonRef }) {
|
|
|
2272
2010
|
"aria-pressed": item.isActive?.(state),
|
|
2273
2011
|
className: PRESSED,
|
|
2274
2012
|
onClick: () => item.run(controller),
|
|
2275
|
-
children: /* @__PURE__ */
|
|
2013
|
+
children: /* @__PURE__ */ jsx(Icon, {})
|
|
2276
2014
|
}
|
|
2277
2015
|
);
|
|
2278
2016
|
}
|
|
2279
|
-
|
|
2280
|
-
// src/menus/bubble/use-roving-focus.ts
|
|
2281
|
-
import { useCallback as useCallback4, useRef as useRef10 } from "react";
|
|
2282
2017
|
var MOVES = {
|
|
2283
2018
|
ArrowRight: (index, count) => (index + 1) % count,
|
|
2284
2019
|
ArrowLeft: (index, count) => (index - 1 + count) % count,
|
|
@@ -2286,23 +2021,23 @@ var MOVES = {
|
|
|
2286
2021
|
End: (_, count) => count - 1
|
|
2287
2022
|
};
|
|
2288
2023
|
function useRovingFocus() {
|
|
2289
|
-
const row =
|
|
2290
|
-
const current =
|
|
2291
|
-
const items =
|
|
2292
|
-
const tabStop =
|
|
2024
|
+
const row = useRef(null);
|
|
2025
|
+
const current = useRef(null);
|
|
2026
|
+
const items = useCallback(() => [...row.current?.querySelectorAll(":scope > button") ?? []], []);
|
|
2027
|
+
const tabStop = useCallback(() => {
|
|
2293
2028
|
const all = items();
|
|
2294
2029
|
return all.find((item) => item === current.current) ?? all[0];
|
|
2295
2030
|
}, [items]);
|
|
2296
|
-
const syncTabStop =
|
|
2031
|
+
const syncTabStop = useCallback(() => {
|
|
2297
2032
|
const stop = tabStop();
|
|
2298
2033
|
for (const item of items()) item.tabIndex = item === stop ? 0 : -1;
|
|
2299
2034
|
}, [items, tabStop]);
|
|
2300
|
-
const owns =
|
|
2035
|
+
const owns = useCallback(
|
|
2301
2036
|
(target) => target instanceof HTMLElement && items().includes(target),
|
|
2302
2037
|
[items]
|
|
2303
2038
|
);
|
|
2304
|
-
const focusCurrent =
|
|
2305
|
-
const ref =
|
|
2039
|
+
const focusCurrent = useCallback(() => tabStop()?.focus(), [tabStop]);
|
|
2040
|
+
const ref = useCallback(
|
|
2306
2041
|
(element) => {
|
|
2307
2042
|
row.current = element;
|
|
2308
2043
|
syncTabStop();
|
|
@@ -2338,9 +2073,6 @@ function useFocusKey(controller, focus) {
|
|
|
2338
2073
|
return interceptKeys(controller, intercept);
|
|
2339
2074
|
}, [controller, focus]);
|
|
2340
2075
|
}
|
|
2341
|
-
|
|
2342
|
-
// src/blocks/void/NodeToolbar.tsx
|
|
2343
|
-
import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2344
2076
|
function NodeToolbar(props) {
|
|
2345
2077
|
const { blockId, controller, label, anchor, items, next, buttonRefs, children, popover } = props;
|
|
2346
2078
|
const state = useEditorState(controller, wholeState);
|
|
@@ -2355,9 +2087,9 @@ function NodeToolbar(props) {
|
|
|
2355
2087
|
else return roving.onKeyDown(event);
|
|
2356
2088
|
event.preventDefault();
|
|
2357
2089
|
};
|
|
2358
|
-
return /* @__PURE__ */
|
|
2359
|
-
/* @__PURE__ */
|
|
2360
|
-
/* @__PURE__ */
|
|
2090
|
+
return /* @__PURE__ */ jsxs(Popover, { open: true, modal: false, children: [
|
|
2091
|
+
/* @__PURE__ */ jsx(PopoverAnchor, { virtualRef: anchor }),
|
|
2092
|
+
/* @__PURE__ */ jsxs(
|
|
2361
2093
|
PopoverContent,
|
|
2362
2094
|
{
|
|
2363
2095
|
ref: roving.ref,
|
|
@@ -2373,7 +2105,7 @@ function NodeToolbar(props) {
|
|
|
2373
2105
|
onKeyDown,
|
|
2374
2106
|
...bubblePart(controller),
|
|
2375
2107
|
children: [
|
|
2376
|
-
items.map((item) => /* @__PURE__ */
|
|
2108
|
+
items.map((item) => /* @__PURE__ */ jsx(ToolbarButton, { item, state, controller, buttonRef: buttonRefs?.[item.id] }, item.id)),
|
|
2377
2109
|
children
|
|
2378
2110
|
]
|
|
2379
2111
|
}
|
|
@@ -2381,9 +2113,6 @@ function NodeToolbar(props) {
|
|
|
2381
2113
|
popover
|
|
2382
2114
|
] });
|
|
2383
2115
|
}
|
|
2384
|
-
|
|
2385
|
-
// src/menus/bubble/use-selection-settled.ts
|
|
2386
|
-
import { useMemo as useMemo4, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
2387
2116
|
function createSettled(controller) {
|
|
2388
2117
|
let pressed = false;
|
|
2389
2118
|
let composing = false;
|
|
@@ -2403,7 +2132,7 @@ function createSettled(controller) {
|
|
|
2403
2132
|
return {
|
|
2404
2133
|
read: () => focusInEditor(controller) && !pressed && !composing && !viewComposing(),
|
|
2405
2134
|
subscribe(notify) {
|
|
2406
|
-
const
|
|
2135
|
+
const listeners2 = Object.entries(handlers).map(([type, handle2]) => {
|
|
2407
2136
|
const listener = (event) => {
|
|
2408
2137
|
handle2(event);
|
|
2409
2138
|
notify();
|
|
@@ -2413,7 +2142,7 @@ function createSettled(controller) {
|
|
|
2413
2142
|
});
|
|
2414
2143
|
const stopState = controller.editor.subscribe(() => notify());
|
|
2415
2144
|
return () => {
|
|
2416
|
-
|
|
2145
|
+
listeners2.forEach((remove) => remove());
|
|
2417
2146
|
stopState();
|
|
2418
2147
|
};
|
|
2419
2148
|
}
|
|
@@ -2421,8 +2150,8 @@ function createSettled(controller) {
|
|
|
2421
2150
|
}
|
|
2422
2151
|
var NOT_SETTLED = () => false;
|
|
2423
2152
|
function useSelectionSettled(controller) {
|
|
2424
|
-
const settled =
|
|
2425
|
-
return
|
|
2153
|
+
const settled = useMemo(() => createSettled(controller), [controller]);
|
|
2154
|
+
return useSyncExternalStore(settled.subscribe, settled.read, NOT_SETTLED);
|
|
2426
2155
|
}
|
|
2427
2156
|
|
|
2428
2157
|
// src/blocks/void/use-toolbar-block.ts
|
|
@@ -2436,20 +2165,17 @@ function useToolbarBlock(controller, selected, keptFor = null) {
|
|
|
2436
2165
|
const settled = useSelectionSettled(controller);
|
|
2437
2166
|
return blockId !== null && !readOnly && (settled || keptFor === blockId) ? blockId : null;
|
|
2438
2167
|
}
|
|
2439
|
-
|
|
2440
|
-
// src/blocks/file/FileToolbar.tsx
|
|
2441
|
-
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
2442
2168
|
var selectedFile = selectedBlock("FILE", hasFile);
|
|
2443
2169
|
function FileToolbarOverlay({ controller }) {
|
|
2444
2170
|
const blockId = useToolbarBlock(controller, selectedFile);
|
|
2445
|
-
return blockId === null ? null : /* @__PURE__ */
|
|
2171
|
+
return blockId === null ? null : /* @__PURE__ */ jsx(FileToolbar, { blockId, controller }, blockId);
|
|
2446
2172
|
}
|
|
2447
2173
|
function FileToolbar({ blockId, controller }) {
|
|
2448
2174
|
const { labels } = useQuoin();
|
|
2449
2175
|
const picker = useReplacePicker(controller, blockId, uploadFile);
|
|
2450
2176
|
const anchor = usePartAnchor(controller, blockId, ".quoin-file-card");
|
|
2451
2177
|
const items = [...replaceItem(labels.replaceFile, picker.open), deleteItem(blockId, labels.delete)];
|
|
2452
|
-
return /* @__PURE__ */
|
|
2178
|
+
return /* @__PURE__ */ jsx(
|
|
2453
2179
|
NodeToolbar,
|
|
2454
2180
|
{
|
|
2455
2181
|
blockId,
|
|
@@ -2463,15 +2189,17 @@ function FileToolbar({ blockId, controller }) {
|
|
|
2463
2189
|
);
|
|
2464
2190
|
}
|
|
2465
2191
|
|
|
2466
|
-
// src/blocks/image/
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2192
|
+
// src/blocks/image/alt-request.ts
|
|
2193
|
+
var listeners = /* @__PURE__ */ new WeakMap();
|
|
2194
|
+
function listenForAltRequests(controller, listener) {
|
|
2195
|
+
listeners.set(controller, listener);
|
|
2196
|
+
return () => {
|
|
2197
|
+
if (listeners.get(controller) === listener) listeners.delete(controller);
|
|
2198
|
+
};
|
|
2199
|
+
}
|
|
2200
|
+
function requestAlt(controller, blockId) {
|
|
2201
|
+
listeners.get(controller)?.(blockId);
|
|
2202
|
+
}
|
|
2475
2203
|
|
|
2476
2204
|
// src/blocks/image/resize-width.ts
|
|
2477
2205
|
var MIN_WIDTH = 10;
|
|
@@ -2491,12 +2219,9 @@ function drawnWidth(frame) {
|
|
|
2491
2219
|
const block = frame?.parentElement?.clientWidth ?? 0;
|
|
2492
2220
|
return frame && block > 0 ? snapWidth(frame.offsetWidth / block * 100) : MAX_WIDTH;
|
|
2493
2221
|
}
|
|
2494
|
-
|
|
2495
|
-
// src/blocks/image/use-drawn-width.ts
|
|
2496
|
-
import { useEffect as useEffect8, useState as useState5 } from "react";
|
|
2497
2222
|
function useDrawnWidth(frame, watching) {
|
|
2498
|
-
const [drawn, setDrawn] =
|
|
2499
|
-
|
|
2223
|
+
const [drawn, setDrawn] = useState(MAX_WIDTH);
|
|
2224
|
+
useEffect(() => {
|
|
2500
2225
|
const element = frame.current;
|
|
2501
2226
|
if (!watching || element === null) return;
|
|
2502
2227
|
const measure2 = () => setDrawn(drawnWidth(element));
|
|
@@ -2508,12 +2233,9 @@ function useDrawnWidth(frame, watching) {
|
|
|
2508
2233
|
}, [frame, watching]);
|
|
2509
2234
|
return drawn;
|
|
2510
2235
|
}
|
|
2511
|
-
|
|
2512
|
-
// src/blocks/image/ResizeHandles.tsx
|
|
2513
|
-
import { Fragment as Fragment4, jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2514
2236
|
function ResizeHandles({ blockId, controller, frame, percent, centred, onPreview }) {
|
|
2515
2237
|
const labels = useLabels();
|
|
2516
|
-
const drag =
|
|
2238
|
+
const drag = useRef(null);
|
|
2517
2239
|
const drawn = useDrawnWidth(frame, percent === void 0);
|
|
2518
2240
|
const value = percent ?? drawn;
|
|
2519
2241
|
const write = (widthPercent) => setBlockAttrs(controller, blockId, { widthPercent });
|
|
@@ -2548,7 +2270,7 @@ function ResizeHandles({ blockId, controller, frame, percent, centred, onPreview
|
|
|
2548
2270
|
const to = stop();
|
|
2549
2271
|
if (to !== null && to !== percent) write(to);
|
|
2550
2272
|
};
|
|
2551
|
-
const handle2 = (side) => /* @__PURE__ */
|
|
2273
|
+
const handle2 = (side) => /* @__PURE__ */ jsx(
|
|
2552
2274
|
"div",
|
|
2553
2275
|
{
|
|
2554
2276
|
role: "slider",
|
|
@@ -2569,29 +2291,27 @@ function ResizeHandles({ blockId, controller, frame, percent, centred, onPreview
|
|
|
2569
2291
|
onPointerCancel: stop
|
|
2570
2292
|
}
|
|
2571
2293
|
);
|
|
2572
|
-
return /* @__PURE__ */
|
|
2294
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2573
2295
|
handle2(-1),
|
|
2574
2296
|
handle2(1)
|
|
2575
2297
|
] });
|
|
2576
2298
|
}
|
|
2577
|
-
|
|
2578
|
-
// src/blocks/image/ImageFigure.tsx
|
|
2579
|
-
import { Fragment as Fragment5, jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2580
2299
|
function ImageFigure({ block, controller, readOnly }) {
|
|
2581
2300
|
const { labels, resolveAssetUrl } = useQuoin();
|
|
2582
|
-
const frame =
|
|
2583
|
-
const [preview, setPreview] =
|
|
2584
|
-
const [failed, setFailed] =
|
|
2301
|
+
const frame = useRef(null);
|
|
2302
|
+
const [preview, setPreview] = useState(null);
|
|
2303
|
+
const [failed, setFailed] = useState(null);
|
|
2585
2304
|
const { id, attrs, regions } = block;
|
|
2586
2305
|
const src = imageSource(attrs, resolveAssetUrl);
|
|
2587
2306
|
const alt = str(attrs.alt);
|
|
2588
2307
|
const name = alt || labels.imageNoAlt;
|
|
2589
2308
|
const percent = optionalNumber(attrs.widthPercent);
|
|
2590
2309
|
const width = preview ?? percent;
|
|
2310
|
+
const flagged = !readOnly && alt === "" && attrs.decorative !== true;
|
|
2591
2311
|
const select = () => focusNode(controller, id);
|
|
2592
|
-
return /* @__PURE__ */
|
|
2593
|
-
/* @__PURE__ */
|
|
2594
|
-
src !== null && src !== failed ? /* @__PURE__ */
|
|
2312
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2313
|
+
/* @__PURE__ */ jsxs("div", { ref: frame, className: "quoin-image-frame", style: width === void 0 ? void 0 : { width: `${width}%` }, children: [
|
|
2314
|
+
src !== null && src !== failed ? /* @__PURE__ */ jsx(
|
|
2595
2315
|
"img",
|
|
2596
2316
|
{
|
|
2597
2317
|
src,
|
|
@@ -2602,11 +2322,23 @@ function ImageFigure({ block, controller, readOnly }) {
|
|
|
2602
2322
|
onError: () => setFailed(src),
|
|
2603
2323
|
onClick: select
|
|
2604
2324
|
}
|
|
2605
|
-
) : /* @__PURE__ */
|
|
2606
|
-
/* @__PURE__ */
|
|
2325
|
+
) : /* @__PURE__ */ jsxs("div", { role: "img", "aria-label": name, className: "quoin-image-missing", onClick: select, children: [
|
|
2326
|
+
/* @__PURE__ */ jsx(Image, { "aria-hidden": "true" }),
|
|
2607
2327
|
alt
|
|
2608
2328
|
] }),
|
|
2609
|
-
|
|
2329
|
+
flagged && /* @__PURE__ */ jsx(
|
|
2330
|
+
"button",
|
|
2331
|
+
{
|
|
2332
|
+
type: "button",
|
|
2333
|
+
className: "quoin-image-no-alt",
|
|
2334
|
+
onClick: () => {
|
|
2335
|
+
select();
|
|
2336
|
+
requestAlt(controller, id);
|
|
2337
|
+
},
|
|
2338
|
+
children: labels.noAltBadge ?? englishLabels.noAltBadge
|
|
2339
|
+
}
|
|
2340
|
+
),
|
|
2341
|
+
!readOnly && /* @__PURE__ */ jsx(
|
|
2610
2342
|
ResizeHandles,
|
|
2611
2343
|
{
|
|
2612
2344
|
blockId: id,
|
|
@@ -2618,7 +2350,7 @@ function ImageFigure({ block, controller, readOnly }) {
|
|
|
2618
2350
|
}
|
|
2619
2351
|
)
|
|
2620
2352
|
] }),
|
|
2621
|
-
(!readOnly || (regions.caption?.length ?? 0) > 0) && /* @__PURE__ */
|
|
2353
|
+
(!readOnly || (regions.caption?.length ?? 0) > 0) && /* @__PURE__ */ jsx(
|
|
2622
2354
|
EditableRegion,
|
|
2623
2355
|
{
|
|
2624
2356
|
block: id,
|
|
@@ -2631,14 +2363,6 @@ function ImageFigure({ block, controller, readOnly }) {
|
|
|
2631
2363
|
] });
|
|
2632
2364
|
}
|
|
2633
2365
|
|
|
2634
|
-
// src/blocks/image/ImageUploadArea.tsx
|
|
2635
|
-
import { useState as useState8 } from "react";
|
|
2636
|
-
import { Link as Link3 } from "lucide-react";
|
|
2637
|
-
|
|
2638
|
-
// src/blocks/image/EmbedLinkForm.tsx
|
|
2639
|
-
import { useId as useId3, useState as useState7 } from "react";
|
|
2640
|
-
import { Check as Check2 } from "lucide-react";
|
|
2641
|
-
|
|
2642
2366
|
// src/menus/link/link-address.ts
|
|
2643
2367
|
var BARE_DOMAIN = /^[^\s/#?.]\S*\.\S*$/;
|
|
2644
2368
|
var WHITESPACE = /\s/;
|
|
@@ -2649,12 +2373,8 @@ function linkAddress(typed2) {
|
|
|
2649
2373
|
const href = sanitizeHref(completed);
|
|
2650
2374
|
return href || null;
|
|
2651
2375
|
}
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
import * as React6 from "react";
|
|
2655
|
-
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
2656
|
-
var Input = React6.forwardRef(function Input2({ className, type, ...props }, ref) {
|
|
2657
|
-
return /* @__PURE__ */ jsx25(
|
|
2376
|
+
var Input = React7.forwardRef(function Input2({ className, type, ...props }, ref) {
|
|
2377
|
+
return /* @__PURE__ */ jsx(
|
|
2658
2378
|
"input",
|
|
2659
2379
|
{
|
|
2660
2380
|
ref,
|
|
@@ -2672,14 +2392,11 @@ var Input = React6.forwardRef(function Input2({ className, type, ...props }, ref
|
|
|
2672
2392
|
}
|
|
2673
2393
|
);
|
|
2674
2394
|
});
|
|
2675
|
-
|
|
2676
|
-
// src/blocks/image/EmbedLinkForm.tsx
|
|
2677
|
-
import { jsx as jsx26, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2678
2395
|
function EmbedLinkForm({ blockId, controller }) {
|
|
2679
2396
|
const labels = useLabels();
|
|
2680
|
-
const [address, setAddress] =
|
|
2681
|
-
const [invalid, setInvalid] =
|
|
2682
|
-
const messageId =
|
|
2397
|
+
const [address, setAddress] = useState("");
|
|
2398
|
+
const [invalid, setInvalid] = useState(false);
|
|
2399
|
+
const messageId = useId();
|
|
2683
2400
|
const embed = (event) => {
|
|
2684
2401
|
event.preventDefault();
|
|
2685
2402
|
const url = linkAddress(address);
|
|
@@ -2690,8 +2407,8 @@ function EmbedLinkForm({ blockId, controller }) {
|
|
|
2690
2407
|
setBlockAttrs(controller, blockId, { url });
|
|
2691
2408
|
focusNode(controller, blockId);
|
|
2692
2409
|
};
|
|
2693
|
-
return /* @__PURE__ */
|
|
2694
|
-
/* @__PURE__ */
|
|
2410
|
+
return /* @__PURE__ */ jsxs("form", { noValidate: true, className: "quoin-image-link", onSubmit: embed, children: [
|
|
2411
|
+
/* @__PURE__ */ jsx(
|
|
2695
2412
|
Input,
|
|
2696
2413
|
{
|
|
2697
2414
|
type: "url",
|
|
@@ -2707,8 +2424,8 @@ function EmbedLinkForm({ blockId, controller }) {
|
|
|
2707
2424
|
}
|
|
2708
2425
|
}
|
|
2709
2426
|
),
|
|
2710
|
-
/* @__PURE__ */
|
|
2711
|
-
invalid && /* @__PURE__ */
|
|
2427
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", variant: "ghost", size: "icon-sm", "aria-label": labels.linkApply, children: /* @__PURE__ */ jsx(Check, {}) }),
|
|
2428
|
+
invalid && /* @__PURE__ */ jsx("p", { id: messageId, role: "alert", className: "quoin-block-message", children: labels.invalidLink })
|
|
2712
2429
|
] });
|
|
2713
2430
|
}
|
|
2714
2431
|
|
|
@@ -2736,13 +2453,10 @@ var uploadImage = (controller, blockId, file, host) => uploadInto(controller, bl
|
|
|
2736
2453
|
writeAttrs(controller, blockId, { storageKey, url: void 0, width: void 0, height: void 0 }, true);
|
|
2737
2454
|
await measureImage(controller, blockId, storageKey, host.resolveAssetUrl, token);
|
|
2738
2455
|
});
|
|
2739
|
-
|
|
2740
|
-
// src/blocks/image/ImageUploadArea.tsx
|
|
2741
|
-
import { jsx as jsx27, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2742
2456
|
function ImageUploadArea({ blockId, controller }) {
|
|
2743
2457
|
const labels = useLabels();
|
|
2744
|
-
const [linking, setLinking] =
|
|
2745
|
-
return /* @__PURE__ */
|
|
2458
|
+
const [linking, setLinking] = useState(false);
|
|
2459
|
+
return /* @__PURE__ */ jsx(
|
|
2746
2460
|
UploadArea,
|
|
2747
2461
|
{
|
|
2748
2462
|
blockId,
|
|
@@ -2754,17 +2468,14 @@ function ImageUploadArea({ blockId, controller }) {
|
|
|
2754
2468
|
hint: labels.dropImage,
|
|
2755
2469
|
className: "quoin-image-upload",
|
|
2756
2470
|
onSelect: () => setLinking(false),
|
|
2757
|
-
actions: /* @__PURE__ */
|
|
2758
|
-
/* @__PURE__ */
|
|
2471
|
+
actions: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", size: "sm", "aria-expanded": linking, onClick: () => setLinking(true), children: [
|
|
2472
|
+
/* @__PURE__ */ jsx(Link, {}),
|
|
2759
2473
|
labels.embedLink
|
|
2760
2474
|
] }),
|
|
2761
|
-
children: linking && /* @__PURE__ */
|
|
2475
|
+
children: linking && /* @__PURE__ */ jsx(EmbedLinkForm, { blockId, controller })
|
|
2762
2476
|
}
|
|
2763
2477
|
);
|
|
2764
2478
|
}
|
|
2765
|
-
|
|
2766
|
-
// src/blocks/image/use-image-keys.ts
|
|
2767
|
-
import { useEffect as useEffect9, useMemo as useMemo5 } from "react";
|
|
2768
2479
|
function captionEnd(controller, blockId) {
|
|
2769
2480
|
const caption = blockById(controller.editor.state.doc, blockId)?.regions.caption ?? [];
|
|
2770
2481
|
return { block: blockId, region: "caption", offset: inlineLength(caption) };
|
|
@@ -2772,7 +2483,7 @@ function captionEnd(controller, blockId) {
|
|
|
2772
2483
|
var plainEnter = (event) => event.key === "Enter" && !event.shiftKey && !event.altKey && !event.ctrlKey && !event.metaKey;
|
|
2773
2484
|
var menuOpenOn = (host) => host?.getAttribute("aria-expanded") === "true";
|
|
2774
2485
|
function useImageKeys(controller, blockId, picture, editable, root) {
|
|
2775
|
-
const caption =
|
|
2486
|
+
const caption = useMemo(() => {
|
|
2776
2487
|
if (!picture) return {};
|
|
2777
2488
|
return {
|
|
2778
2489
|
// Called from an effect, where the canvas's own flush is refused, so the caret goes to the editor, which the view
|
|
@@ -2789,7 +2500,7 @@ function useImageKeys(controller, blockId, picture, editable, root) {
|
|
|
2789
2500
|
};
|
|
2790
2501
|
}, [controller, blockId, picture]);
|
|
2791
2502
|
useNodeKeys(controller, blockId, editable, true, root, caption);
|
|
2792
|
-
|
|
2503
|
+
useEffect(() => {
|
|
2793
2504
|
if (!editable) return;
|
|
2794
2505
|
const intercept = (event) => {
|
|
2795
2506
|
const { selection } = controller.editor.state;
|
|
@@ -2802,17 +2513,14 @@ function useImageKeys(controller, blockId, picture, editable, root) {
|
|
|
2802
2513
|
return interceptKeys(controller, intercept);
|
|
2803
2514
|
}, [controller, blockId, editable]);
|
|
2804
2515
|
}
|
|
2805
|
-
|
|
2806
|
-
// src/blocks/image/ImageBlock.tsx
|
|
2807
|
-
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
2808
2516
|
var ImageBlock = ({ block, controller }) => {
|
|
2809
2517
|
const labels = useLabels();
|
|
2810
2518
|
const readOnly = useReadOnly(controller);
|
|
2811
|
-
const root =
|
|
2519
|
+
const root = useRef(null);
|
|
2812
2520
|
const picture = hasPicture(block.attrs);
|
|
2813
2521
|
useImageKeys(controller, block.id, picture, !readOnly, root);
|
|
2814
|
-
const empty = readOnly ? /* @__PURE__ */
|
|
2815
|
-
return /* @__PURE__ */
|
|
2522
|
+
const empty = readOnly ? /* @__PURE__ */ jsx("p", { className: "quoin-block-message", children: labels.emptyImage }) : /* @__PURE__ */ jsx(ImageUploadArea, { blockId: block.id, controller });
|
|
2523
|
+
return /* @__PURE__ */ jsx(
|
|
2816
2524
|
"div",
|
|
2817
2525
|
{
|
|
2818
2526
|
ref: root,
|
|
@@ -2821,21 +2529,12 @@ var ImageBlock = ({ block, controller }) => {
|
|
|
2821
2529
|
contentEditable: false,
|
|
2822
2530
|
className: "quoin-image",
|
|
2823
2531
|
...picture ? { [NODE_ENTRY]: "" } : void 0,
|
|
2824
|
-
children: picture ? /* @__PURE__ */
|
|
2532
|
+
children: picture ? /* @__PURE__ */ jsx(ImageFigure, { block, controller, readOnly }) : empty
|
|
2825
2533
|
}
|
|
2826
2534
|
);
|
|
2827
2535
|
};
|
|
2828
|
-
|
|
2829
|
-
// src/blocks/image/ImageToolbar.tsx
|
|
2830
|
-
import { useRef as useRef16, useState as useState10 } from "react";
|
|
2831
|
-
|
|
2832
|
-
// src/blocks/image/AltTextPopover.tsx
|
|
2833
|
-
import { useCallback as useCallback5, useEffect as useEffect10, useId as useId4, useRef as useRef15, useState as useState9 } from "react";
|
|
2834
|
-
|
|
2835
|
-
// src/blocks/image/use-outside-press.ts
|
|
2836
|
-
import { useRef as useRef14 } from "react";
|
|
2837
2536
|
function useOutsidePress(element, ownerDocument, onPress) {
|
|
2838
|
-
const latest =
|
|
2537
|
+
const latest = useRef(onPress);
|
|
2839
2538
|
useIsomorphicLayoutEffect(() => {
|
|
2840
2539
|
latest.current = onPress;
|
|
2841
2540
|
});
|
|
@@ -2857,36 +2556,36 @@ function useOutsidePress(element, ownerDocument, onPress) {
|
|
|
2857
2556
|
return listen(doc, { pointerdown: down, click }, true);
|
|
2858
2557
|
}, [element, ownerDocument]);
|
|
2859
2558
|
}
|
|
2860
|
-
|
|
2861
|
-
// src/blocks/image/AltTextPopover.tsx
|
|
2862
|
-
import { jsx as jsx29, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2863
|
-
function storeAlt(controller, blockId, opened, alt) {
|
|
2559
|
+
function storeAlt(controller, blockId, opened, patch) {
|
|
2864
2560
|
const { editor } = controller;
|
|
2865
|
-
const
|
|
2866
|
-
|
|
2867
|
-
|
|
2561
|
+
const attrs = blockById(editor.state.doc, blockId)?.attrs ?? {};
|
|
2562
|
+
const changed = str(attrs.alt) !== opened.alt || attrs.decorative === true !== opened.decorative;
|
|
2563
|
+
if (controller.readOnly || controller.root === null || changed) return;
|
|
2564
|
+
onBlock(blockId, setAttrs(patch))(editor.state, (tr) => editor.dispatch(tr));
|
|
2868
2565
|
}
|
|
2869
|
-
function AltTextPopover({ blockId, controller, anchor, opener, alt, onClose }) {
|
|
2566
|
+
function AltTextPopover({ blockId, controller, anchor, opener, alt, decorative, onClose }) {
|
|
2870
2567
|
const labels = useLabels();
|
|
2871
|
-
const [opened] =
|
|
2872
|
-
const [draft, setDraft] =
|
|
2873
|
-
const
|
|
2568
|
+
const [opened] = useState({ alt, decorative });
|
|
2569
|
+
const [draft, setDraft] = useState(alt);
|
|
2570
|
+
const [marked, setMarked] = useState(decorative);
|
|
2571
|
+
const fieldId = useId();
|
|
2874
2572
|
const hintId = `${fieldId}-hint`;
|
|
2875
|
-
const closed =
|
|
2573
|
+
const closed = useRef(false);
|
|
2876
2574
|
const finish = (store) => {
|
|
2877
2575
|
if (closed.current) return false;
|
|
2878
2576
|
closed.current = true;
|
|
2879
|
-
if (store && draft !== alt
|
|
2577
|
+
if (store && (draft !== alt || marked !== decorative))
|
|
2578
|
+
storeAlt(controller, blockId, opened, { alt: draft, decorative: marked || void 0 });
|
|
2880
2579
|
return true;
|
|
2881
2580
|
};
|
|
2882
|
-
const latestFinish =
|
|
2581
|
+
const latestFinish = useRef(finish);
|
|
2883
2582
|
latestFinish.current = finish;
|
|
2884
|
-
|
|
2583
|
+
useEffect(() => {
|
|
2885
2584
|
closed.current = false;
|
|
2886
2585
|
return () => void latestFinish.current(true);
|
|
2887
2586
|
}, []);
|
|
2888
|
-
|
|
2889
|
-
if (alt !== opened && finish(false)) onClose();
|
|
2587
|
+
useEffect(() => {
|
|
2588
|
+
if ((alt !== opened.alt || decorative !== opened.decorative) && finish(false)) onClose();
|
|
2890
2589
|
});
|
|
2891
2590
|
const close = (store, refocus = true) => {
|
|
2892
2591
|
if (!refocus) controller.readSelectionFromDom();
|
|
@@ -2894,8 +2593,8 @@ function AltTextPopover({ blockId, controller, anchor, opener, alt, onClose }) {
|
|
|
2894
2593
|
onClose();
|
|
2895
2594
|
if (refocus) controller.focus();
|
|
2896
2595
|
};
|
|
2897
|
-
const content =
|
|
2898
|
-
const ownerDocument =
|
|
2596
|
+
const content = useRef(null);
|
|
2597
|
+
const ownerDocument = useCallback(() => controller.root?.ownerDocument ?? document, [controller]);
|
|
2899
2598
|
useOutsidePress(content, ownerDocument, (target) => {
|
|
2900
2599
|
if (!opener.current?.contains(target)) close(true, isBubblePart(target, controller));
|
|
2901
2600
|
});
|
|
@@ -2905,14 +2604,14 @@ function AltTextPopover({ blockId, controller, anchor, opener, alt, onClose }) {
|
|
|
2905
2604
|
};
|
|
2906
2605
|
const onKeyDown = (event) => {
|
|
2907
2606
|
if (event.key !== "Tab" || isComposingKey(controller, event.nativeEvent)) return;
|
|
2908
|
-
const
|
|
2909
|
-
const
|
|
2607
|
+
const controls = [...event.currentTarget.elements];
|
|
2608
|
+
const next = controls[controls.indexOf(event.target) + (event.shiftKey ? -1 : 1)];
|
|
2910
2609
|
event.preventDefault();
|
|
2911
2610
|
event.stopPropagation();
|
|
2912
|
-
if (
|
|
2913
|
-
else
|
|
2611
|
+
if (next === void 0) close(true);
|
|
2612
|
+
else next.focus();
|
|
2914
2613
|
};
|
|
2915
|
-
return /* @__PURE__ */
|
|
2614
|
+
return /* @__PURE__ */ jsxs(
|
|
2916
2615
|
Popover,
|
|
2917
2616
|
{
|
|
2918
2617
|
open: true,
|
|
@@ -2921,8 +2620,8 @@ function AltTextPopover({ blockId, controller, anchor, opener, alt, onClose }) {
|
|
|
2921
2620
|
if (!open) close(true, false);
|
|
2922
2621
|
},
|
|
2923
2622
|
children: [
|
|
2924
|
-
/* @__PURE__ */
|
|
2925
|
-
/* @__PURE__ */
|
|
2623
|
+
/* @__PURE__ */ jsx(PopoverAnchor, { virtualRef: anchor }),
|
|
2624
|
+
/* @__PURE__ */ jsx(
|
|
2926
2625
|
PopoverContent,
|
|
2927
2626
|
{
|
|
2928
2627
|
ref: content,
|
|
@@ -2935,20 +2634,37 @@ function AltTextPopover({ blockId, controller, anchor, opener, alt, onClose }) {
|
|
|
2935
2634
|
if (!isComposingKey(controller, event)) close(false);
|
|
2936
2635
|
},
|
|
2937
2636
|
...bubblePart(controller),
|
|
2938
|
-
children: /* @__PURE__ */
|
|
2939
|
-
/* @__PURE__ */
|
|
2940
|
-
/* @__PURE__ */
|
|
2637
|
+
children: /* @__PURE__ */ jsxs("form", { noValidate: true, className: "quoin-image-alt", onSubmit: save, onKeyDown, children: [
|
|
2638
|
+
/* @__PURE__ */ jsx("label", { htmlFor: fieldId, className: "text-sm font-medium", children: labels.altText }),
|
|
2639
|
+
/* @__PURE__ */ jsx(
|
|
2941
2640
|
Input,
|
|
2942
2641
|
{
|
|
2943
2642
|
id: fieldId,
|
|
2944
|
-
required:
|
|
2945
|
-
"aria-describedby": hintId,
|
|
2643
|
+
required: !marked,
|
|
2644
|
+
"aria-describedby": marked ? void 0 : hintId,
|
|
2946
2645
|
value: draft,
|
|
2947
|
-
onChange: (event) =>
|
|
2646
|
+
onChange: (event) => {
|
|
2647
|
+
setDraft(event.target.value);
|
|
2648
|
+
setMarked(false);
|
|
2649
|
+
}
|
|
2948
2650
|
}
|
|
2949
2651
|
),
|
|
2950
|
-
/* @__PURE__ */
|
|
2951
|
-
/* @__PURE__ */
|
|
2652
|
+
/* @__PURE__ */ jsx("p", { id: hintId, className: marked ? "quoin-block-message invisible" : "quoin-block-message", children: labels.altTextHint }),
|
|
2653
|
+
/* @__PURE__ */ jsxs("label", { className: "quoin-image-decorative text-sm", children: [
|
|
2654
|
+
/* @__PURE__ */ jsx(
|
|
2655
|
+
"input",
|
|
2656
|
+
{
|
|
2657
|
+
type: "checkbox",
|
|
2658
|
+
checked: marked,
|
|
2659
|
+
onChange: (event) => {
|
|
2660
|
+
setMarked(event.target.checked);
|
|
2661
|
+
if (event.target.checked) setDraft("");
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
),
|
|
2665
|
+
labels.decorativeImage ?? englishLabels.decorativeImage
|
|
2666
|
+
] }),
|
|
2667
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", size: "sm", children: labels.save })
|
|
2952
2668
|
] })
|
|
2953
2669
|
}
|
|
2954
2670
|
)
|
|
@@ -2956,9 +2672,6 @@ function AltTextPopover({ blockId, controller, anchor, opener, alt, onClose }) {
|
|
|
2956
2672
|
}
|
|
2957
2673
|
);
|
|
2958
2674
|
}
|
|
2959
|
-
|
|
2960
|
-
// src/blocks/image/image-toolbar-items.ts
|
|
2961
|
-
import { AlignCenter, AlignLeft, AlignRight, Download as Download2, Pencil } from "lucide-react";
|
|
2962
2675
|
var ALIGNS = [
|
|
2963
2676
|
["left", AlignLeft, "alignLeft"],
|
|
2964
2677
|
["center", AlignCenter, "alignCenter"],
|
|
@@ -2979,13 +2692,10 @@ function imageToolbarItems(blockId, labels, actions) {
|
|
|
2979
2692
|
...aligns,
|
|
2980
2693
|
...replaceItem(labels.replaceImage, replace),
|
|
2981
2694
|
{ id: "alt", title: labels.altText, icon: Pencil, run: editAlt },
|
|
2982
|
-
{ id: "download", title: labels.download, icon:
|
|
2695
|
+
{ id: "download", title: labels.download, icon: Download, run: download2 },
|
|
2983
2696
|
deleteItem(blockId, labels.delete)
|
|
2984
2697
|
];
|
|
2985
2698
|
}
|
|
2986
|
-
|
|
2987
|
-
// src/blocks/image/ImageToolbar.tsx
|
|
2988
|
-
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
2989
2699
|
var selectedImage = selectedBlock("IMAGE", hasPicture);
|
|
2990
2700
|
function download(src, doc) {
|
|
2991
2701
|
if (src === null) return;
|
|
@@ -2997,11 +2707,12 @@ function download(src, doc) {
|
|
|
2997
2707
|
link.click();
|
|
2998
2708
|
}
|
|
2999
2709
|
function ImageToolbarOverlay({ controller }) {
|
|
3000
|
-
const [altFor, setAltFor] =
|
|
2710
|
+
const [altFor, setAltFor] = useState(null);
|
|
3001
2711
|
const blockId = useToolbarBlock(controller, selectedImage, altFor);
|
|
2712
|
+
useEffect(() => listenForAltRequests(controller, setAltFor), [controller]);
|
|
3002
2713
|
if (altFor !== null && altFor !== blockId) setAltFor(null);
|
|
3003
2714
|
if (blockId === null) return null;
|
|
3004
|
-
return /* @__PURE__ */
|
|
2715
|
+
return /* @__PURE__ */ jsx(
|
|
3005
2716
|
ImageToolbar,
|
|
3006
2717
|
{
|
|
3007
2718
|
blockId,
|
|
@@ -3016,7 +2727,7 @@ function ImageToolbar({ blockId, controller, editingAlt, onEditAlt }) {
|
|
|
3016
2727
|
const { labels, resolveAssetUrl } = useQuoin();
|
|
3017
2728
|
const state = useEditorState(controller, wholeState);
|
|
3018
2729
|
const picker = useReplacePicker(controller, blockId, uploadImage, "image/*");
|
|
3019
|
-
const altButton =
|
|
2730
|
+
const altButton = useRef(null);
|
|
3020
2731
|
const anchor = usePartAnchor(controller, blockId, ".quoin-image-frame");
|
|
3021
2732
|
const attrs = blockById(state.doc, blockId)?.attrs ?? {};
|
|
3022
2733
|
const items = imageToolbarItems(blockId, labels, {
|
|
@@ -3027,7 +2738,7 @@ function ImageToolbar({ blockId, controller, editingAlt, onEditAlt }) {
|
|
|
3027
2738
|
},
|
|
3028
2739
|
download: () => download(imageSource(attrs, resolveAssetUrl), controller.root?.ownerDocument ?? document)
|
|
3029
2740
|
});
|
|
3030
|
-
return /* @__PURE__ */
|
|
2741
|
+
return /* @__PURE__ */ jsx(
|
|
3031
2742
|
NodeToolbar,
|
|
3032
2743
|
{
|
|
3033
2744
|
blockId,
|
|
@@ -3037,7 +2748,7 @@ function ImageToolbar({ blockId, controller, editingAlt, onEditAlt }) {
|
|
|
3037
2748
|
items,
|
|
3038
2749
|
next: '[role="slider"][data-side="1"]',
|
|
3039
2750
|
buttonRefs: { alt: altButton },
|
|
3040
|
-
popover: editingAlt && /* @__PURE__ */
|
|
2751
|
+
popover: editingAlt && /* @__PURE__ */ jsx(
|
|
3041
2752
|
AltTextPopover,
|
|
3042
2753
|
{
|
|
3043
2754
|
blockId,
|
|
@@ -3045,6 +2756,7 @@ function ImageToolbar({ blockId, controller, editingAlt, onEditAlt }) {
|
|
|
3045
2756
|
anchor,
|
|
3046
2757
|
opener: altButton,
|
|
3047
2758
|
alt: str(attrs.alt),
|
|
2759
|
+
decorative: attrs.decorative === true,
|
|
3048
2760
|
onClose: () => onEditAlt(null)
|
|
3049
2761
|
}
|
|
3050
2762
|
),
|
|
@@ -3063,23 +2775,17 @@ var inPlaceOverlays = {
|
|
|
3063
2775
|
IMAGE: ImageToolbarOverlay,
|
|
3064
2776
|
FILE: FileToolbarOverlay
|
|
3065
2777
|
};
|
|
3066
|
-
|
|
3067
|
-
// src/ui/dropdown-menu.tsx
|
|
3068
|
-
import * as React7 from "react";
|
|
3069
|
-
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
3070
|
-
import { CheckIcon as CheckIcon4, ChevronRightIcon as ChevronRightIcon2, CircleIcon as CircleIcon2 } from "lucide-react";
|
|
3071
|
-
import { jsx as jsx31, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
3072
2778
|
function DropdownMenu({ modal = false, ...props }) {
|
|
3073
|
-
return /* @__PURE__ */
|
|
2779
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Root, { modal, ...props });
|
|
3074
2780
|
}
|
|
3075
2781
|
function DropdownMenuSub(props) {
|
|
3076
|
-
return /* @__PURE__ */
|
|
2782
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Sub, { ...props });
|
|
3077
2783
|
}
|
|
3078
2784
|
var DropdownMenuTrigger = /* @__PURE__ */ React7.forwardRef(function DropdownMenuTrigger2(props, ref) {
|
|
3079
|
-
return /* @__PURE__ */
|
|
2785
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Trigger, { ref, "data-slot": "dropdown-menu-trigger", ...props });
|
|
3080
2786
|
});
|
|
3081
2787
|
var DropdownMenuContent = /* @__PURE__ */ React7.forwardRef(function DropdownMenuContent2({ className, sideOffset = 4, ...props }, ref) {
|
|
3082
|
-
return /* @__PURE__ */
|
|
2788
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
3083
2789
|
DropdownMenuPrimitive.Content,
|
|
3084
2790
|
{
|
|
3085
2791
|
ref,
|
|
@@ -3091,10 +2797,10 @@ var DropdownMenuContent = /* @__PURE__ */ React7.forwardRef(function DropdownMen
|
|
|
3091
2797
|
) });
|
|
3092
2798
|
});
|
|
3093
2799
|
var DropdownMenuGroup = /* @__PURE__ */ React7.forwardRef(function DropdownMenuGroup2(props, ref) {
|
|
3094
|
-
return /* @__PURE__ */
|
|
2800
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Group, { ref, "data-slot": "dropdown-menu-group", ...props });
|
|
3095
2801
|
});
|
|
3096
2802
|
var DropdownMenuItem = /* @__PURE__ */ React7.forwardRef(function DropdownMenuItem2({ className, inset, ...props }, ref) {
|
|
3097
|
-
return /* @__PURE__ */
|
|
2803
|
+
return /* @__PURE__ */ jsx(
|
|
3098
2804
|
DropdownMenuPrimitive.Item,
|
|
3099
2805
|
{
|
|
3100
2806
|
ref,
|
|
@@ -3106,7 +2812,7 @@ var DropdownMenuItem = /* @__PURE__ */ React7.forwardRef(function DropdownMenuIt
|
|
|
3106
2812
|
);
|
|
3107
2813
|
});
|
|
3108
2814
|
var DropdownMenuCheckboxItem = /* @__PURE__ */ React7.forwardRef(function DropdownMenuCheckboxItem2({ className, children, ...props }, ref) {
|
|
3109
|
-
return /* @__PURE__ */
|
|
2815
|
+
return /* @__PURE__ */ jsxs(
|
|
3110
2816
|
DropdownMenuPrimitive.CheckboxItem,
|
|
3111
2817
|
{
|
|
3112
2818
|
ref,
|
|
@@ -3114,17 +2820,17 @@ var DropdownMenuCheckboxItem = /* @__PURE__ */ React7.forwardRef(function Dropdo
|
|
|
3114
2820
|
className: cn(MENU_CHECKABLE_ITEM, className),
|
|
3115
2821
|
...props,
|
|
3116
2822
|
children: [
|
|
3117
|
-
/* @__PURE__ */
|
|
2823
|
+
/* @__PURE__ */ jsx("span", { className: MENU_ITEM_INDICATOR, children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }) }) }),
|
|
3118
2824
|
children
|
|
3119
2825
|
]
|
|
3120
2826
|
}
|
|
3121
2827
|
);
|
|
3122
2828
|
});
|
|
3123
2829
|
var DropdownMenuRadioGroup = /* @__PURE__ */ React7.forwardRef(function DropdownMenuRadioGroup2(props, ref) {
|
|
3124
|
-
return /* @__PURE__ */
|
|
2830
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.RadioGroup, { ref, "data-slot": "dropdown-menu-radio-group", ...props });
|
|
3125
2831
|
});
|
|
3126
|
-
var DropdownMenuRadioItem = /* @__PURE__ */ React7.forwardRef(function DropdownMenuRadioItem2({ className, children, indicator = /* @__PURE__ */
|
|
3127
|
-
return /* @__PURE__ */
|
|
2832
|
+
var DropdownMenuRadioItem = /* @__PURE__ */ React7.forwardRef(function DropdownMenuRadioItem2({ className, children, indicator = /* @__PURE__ */ jsx(CircleIcon, { className: "size-2 fill-current" }), ...props }, ref) {
|
|
2833
|
+
return /* @__PURE__ */ jsxs(
|
|
3128
2834
|
DropdownMenuPrimitive.RadioItem,
|
|
3129
2835
|
{
|
|
3130
2836
|
ref,
|
|
@@ -3132,14 +2838,14 @@ var DropdownMenuRadioItem = /* @__PURE__ */ React7.forwardRef(function DropdownM
|
|
|
3132
2838
|
className: cn(MENU_CHECKABLE_ITEM, className),
|
|
3133
2839
|
...props,
|
|
3134
2840
|
children: [
|
|
3135
|
-
/* @__PURE__ */
|
|
2841
|
+
/* @__PURE__ */ jsx("span", { className: MENU_ITEM_INDICATOR, children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: indicator }) }),
|
|
3136
2842
|
children
|
|
3137
2843
|
]
|
|
3138
2844
|
}
|
|
3139
2845
|
);
|
|
3140
2846
|
});
|
|
3141
2847
|
var DropdownMenuLabel = /* @__PURE__ */ React7.forwardRef(function DropdownMenuLabel2({ className, inset, ...props }, ref) {
|
|
3142
|
-
return /* @__PURE__ */
|
|
2848
|
+
return /* @__PURE__ */ jsx(
|
|
3143
2849
|
DropdownMenuPrimitive.Label,
|
|
3144
2850
|
{
|
|
3145
2851
|
ref,
|
|
@@ -3151,7 +2857,7 @@ var DropdownMenuLabel = /* @__PURE__ */ React7.forwardRef(function DropdownMenuL
|
|
|
3151
2857
|
);
|
|
3152
2858
|
});
|
|
3153
2859
|
var DropdownMenuSeparator = /* @__PURE__ */ React7.forwardRef(function DropdownMenuSeparator2({ className, ...props }, ref) {
|
|
3154
|
-
return /* @__PURE__ */
|
|
2860
|
+
return /* @__PURE__ */ jsx(
|
|
3155
2861
|
DropdownMenuPrimitive.Separator,
|
|
3156
2862
|
{
|
|
3157
2863
|
ref,
|
|
@@ -3163,11 +2869,11 @@ var DropdownMenuSeparator = /* @__PURE__ */ React7.forwardRef(function DropdownM
|
|
|
3163
2869
|
});
|
|
3164
2870
|
var DropdownMenuShortcut = /* @__PURE__ */ React7.forwardRef(
|
|
3165
2871
|
function DropdownMenuShortcut2({ className, ...props }, ref) {
|
|
3166
|
-
return /* @__PURE__ */
|
|
2872
|
+
return /* @__PURE__ */ jsx("span", { ref, "data-slot": "dropdown-menu-shortcut", className: cn(MENU_SHORTCUT, className), ...props });
|
|
3167
2873
|
}
|
|
3168
2874
|
);
|
|
3169
2875
|
var DropdownMenuSubTrigger = /* @__PURE__ */ React7.forwardRef(function DropdownMenuSubTrigger2({ className, inset, children, ...props }, ref) {
|
|
3170
|
-
return /* @__PURE__ */
|
|
2876
|
+
return /* @__PURE__ */ jsxs(
|
|
3171
2877
|
DropdownMenuPrimitive.SubTrigger,
|
|
3172
2878
|
{
|
|
3173
2879
|
ref,
|
|
@@ -3177,13 +2883,13 @@ var DropdownMenuSubTrigger = /* @__PURE__ */ React7.forwardRef(function Dropdown
|
|
|
3177
2883
|
...props,
|
|
3178
2884
|
children: [
|
|
3179
2885
|
children,
|
|
3180
|
-
/* @__PURE__ */
|
|
2886
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, { className: "ml-auto size-4" })
|
|
3181
2887
|
]
|
|
3182
2888
|
}
|
|
3183
2889
|
);
|
|
3184
2890
|
});
|
|
3185
2891
|
var DropdownMenuSubContent = /* @__PURE__ */ React7.forwardRef(function DropdownMenuSubContent2({ className, ...props }, ref) {
|
|
3186
|
-
return /* @__PURE__ */
|
|
2892
|
+
return /* @__PURE__ */ jsx(
|
|
3187
2893
|
DropdownMenuPrimitive.SubContent,
|
|
3188
2894
|
{
|
|
3189
2895
|
ref,
|
|
@@ -3193,13 +2899,10 @@ var DropdownMenuSubContent = /* @__PURE__ */ React7.forwardRef(function Dropdown
|
|
|
3193
2899
|
}
|
|
3194
2900
|
);
|
|
3195
2901
|
});
|
|
3196
|
-
|
|
3197
|
-
// src/blocks/text/CalloutIconMenu.tsx
|
|
3198
|
-
import { jsx as jsx32, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3199
2902
|
function CalloutIconMenu({ blockId, controller, icon }) {
|
|
3200
2903
|
const labels = useLabels();
|
|
3201
|
-
return /* @__PURE__ */
|
|
3202
|
-
/* @__PURE__ */
|
|
2904
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
2905
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
3203
2906
|
Button,
|
|
3204
2907
|
{
|
|
3205
2908
|
type: "button",
|
|
@@ -3208,10 +2911,10 @@ function CalloutIconMenu({ blockId, controller, icon }) {
|
|
|
3208
2911
|
tabIndex: -1,
|
|
3209
2912
|
"aria-label": labels.calloutIcon,
|
|
3210
2913
|
className: "text-base",
|
|
3211
|
-
children: /* @__PURE__ */
|
|
2914
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: icon })
|
|
3212
2915
|
}
|
|
3213
2916
|
) }),
|
|
3214
|
-
/* @__PURE__ */
|
|
2917
|
+
/* @__PURE__ */ jsx(DropdownMenuContent, { align: "start", className: "min-w-0", onCloseAutoFocus: returnFocusToText(controller), children: CALLOUT_ICONS.map((choice) => /* @__PURE__ */ jsx(
|
|
3215
2918
|
DropdownMenuItem,
|
|
3216
2919
|
{
|
|
3217
2920
|
className: "justify-center text-base",
|
|
@@ -3222,9 +2925,6 @@ function CalloutIconMenu({ blockId, controller, icon }) {
|
|
|
3222
2925
|
)) })
|
|
3223
2926
|
] });
|
|
3224
2927
|
}
|
|
3225
|
-
|
|
3226
|
-
// src/blocks/text/CalloutToneMenu.tsx
|
|
3227
|
-
import { jsx as jsx33, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
3228
2928
|
var SHOWN_WITH_THE_BLOCK = [
|
|
3229
2929
|
"opacity-0 group-hover/callout:opacity-100 group-focus-within/callout:opacity-100",
|
|
3230
2930
|
"in-data-[selected=true]:opacity-100 pointer-coarse:opacity-100 focus-visible:opacity-100 data-[state=open]:opacity-100"
|
|
@@ -3232,8 +2932,8 @@ var SHOWN_WITH_THE_BLOCK = [
|
|
|
3232
2932
|
function CalloutToneMenu({ blockId, controller, tone }) {
|
|
3233
2933
|
const labels = useLabels();
|
|
3234
2934
|
const name = labels.calloutTones[tone];
|
|
3235
|
-
return /* @__PURE__ */
|
|
3236
|
-
/* @__PURE__ */
|
|
2935
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
2936
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
3237
2937
|
Button,
|
|
3238
2938
|
{
|
|
3239
2939
|
type: "button",
|
|
@@ -3245,27 +2945,24 @@ function CalloutToneMenu({ blockId, controller, tone }) {
|
|
|
3245
2945
|
children: name
|
|
3246
2946
|
}
|
|
3247
2947
|
) }),
|
|
3248
|
-
/* @__PURE__ */
|
|
2948
|
+
/* @__PURE__ */ jsx(DropdownMenuContent, { align: "end", onCloseAutoFocus: returnFocusToText(controller), children: /* @__PURE__ */ jsx(
|
|
3249
2949
|
DropdownMenuRadioGroup,
|
|
3250
2950
|
{
|
|
3251
2951
|
value: tone,
|
|
3252
2952
|
onValueChange: (value) => setBlockAttrs(controller, blockId, { tone: value }),
|
|
3253
|
-
children: CALLOUT_TONES.map((option) => /* @__PURE__ */
|
|
2953
|
+
children: CALLOUT_TONES.map((option) => /* @__PURE__ */ jsx(DropdownMenuRadioItem, { value: option, children: labels.calloutTones[option] }, option))
|
|
3254
2954
|
}
|
|
3255
2955
|
) })
|
|
3256
2956
|
] });
|
|
3257
2957
|
}
|
|
3258
|
-
|
|
3259
|
-
// src/blocks/text/CalloutBlock.tsx
|
|
3260
|
-
import { jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
3261
2958
|
var CalloutBlock = ({ block, controller }) => {
|
|
3262
2959
|
const labels = useLabels();
|
|
3263
2960
|
const readOnly = useReadOnly(controller);
|
|
3264
2961
|
const tone = calloutTone(block.attrs.tone);
|
|
3265
2962
|
const icon = calloutIcon(block.attrs, tone);
|
|
3266
|
-
return /* @__PURE__ */
|
|
3267
|
-
readOnly ? /* @__PURE__ */
|
|
3268
|
-
/* @__PURE__ */
|
|
2963
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("quoin-callout group/callout flex items-start gap-2", TONE[tone]), "data-tone": tone, children: [
|
|
2964
|
+
readOnly ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "flex size-6 items-center justify-center text-base", children: icon }) : /* @__PURE__ */ jsx(CalloutIconMenu, { blockId: block.id, controller, icon }),
|
|
2965
|
+
/* @__PURE__ */ jsx(
|
|
3269
2966
|
EditableRegion,
|
|
3270
2967
|
{
|
|
3271
2968
|
block: block.id,
|
|
@@ -3274,13 +2971,10 @@ var CalloutBlock = ({ block, controller }) => {
|
|
|
3274
2971
|
className: "min-w-0 flex-1"
|
|
3275
2972
|
}
|
|
3276
2973
|
),
|
|
3277
|
-
!readOnly && /* @__PURE__ */
|
|
2974
|
+
!readOnly && /* @__PURE__ */ jsx(CalloutToneMenu, { blockId: block.id, controller, tone })
|
|
3278
2975
|
] });
|
|
3279
2976
|
};
|
|
3280
|
-
|
|
3281
|
-
// src/blocks/text/DividerBlock.tsx
|
|
3282
|
-
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
3283
|
-
var DividerBlock = ({ block, controller }) => /* @__PURE__ */ jsx35("div", { className: "py-2", contentEditable: false, onClick: () => focusNode(controller, block.id), children: /* @__PURE__ */ jsx35("hr", { className: "border-t border-border" }) });
|
|
2977
|
+
var DividerBlock = ({ block, controller }) => /* @__PURE__ */ jsx("div", { className: "py-2", contentEditable: false, onClick: () => focusNode(controller, block.id), children: /* @__PURE__ */ jsx("hr", { className: "border-t border-border" }) });
|
|
3284
2978
|
|
|
3285
2979
|
// src/blocks/text/marker-styles.ts
|
|
3286
2980
|
var BULLETS = ["\u2022", "\u25E6", "\u25AA"];
|
|
@@ -3328,38 +3022,32 @@ function bulletGlyph(depth) {
|
|
|
3328
3022
|
function orderedLabel(n, depth) {
|
|
3329
3023
|
return `${COUNTERS[cycleOf(depth)](n)}.`;
|
|
3330
3024
|
}
|
|
3331
|
-
|
|
3332
|
-
// src/blocks/text/ListMarker.tsx
|
|
3333
|
-
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
3334
3025
|
function ListMarker(props) {
|
|
3335
3026
|
const text2 = props.list === "bullet" ? bulletGlyph(props.depth) : orderedLabel(props.number, props.depth);
|
|
3336
|
-
return /* @__PURE__ */
|
|
3027
|
+
return /* @__PURE__ */ jsx("span", { className: "quoin-marker", "aria-hidden": "true", children: text2 });
|
|
3337
3028
|
}
|
|
3338
|
-
|
|
3339
|
-
// src/blocks/text/MarkdownBlock.tsx
|
|
3340
|
-
import { jsx as jsx37, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
3341
3029
|
var REGION = "text";
|
|
3342
3030
|
var HEADING_LEVELS = ["mt-6 text-3xl", "mt-5 text-2xl", "mt-4 text-xl", "mt-3 text-lg", "mt-3 text-base", "mt-3 text-sm"];
|
|
3343
3031
|
var headingStyles = (level) => `quoin-heading mb-1 font-semibold leading-tight in-[[data-quoin-block]:first-child]:mt-0 ${HEADING_LEVELS[level - 1]}`;
|
|
3344
3032
|
function Heading({ block }) {
|
|
3345
3033
|
const labels = useLabels();
|
|
3346
3034
|
const level = headingLevel(block.attrs.level);
|
|
3347
|
-
return /* @__PURE__ */
|
|
3035
|
+
return /* @__PURE__ */ jsx("div", { role: "heading", "aria-level": level, className: headingStyles(level), children: /* @__PURE__ */ jsx(EditableRegion, { block: block.id, region: REGION, label: labels.heading(level) }) });
|
|
3348
3036
|
}
|
|
3349
3037
|
function NumberedItem({ block, controller }) {
|
|
3350
3038
|
const labels = useLabels();
|
|
3351
3039
|
const number = useOrderedNumber(controller, block.id);
|
|
3352
|
-
return /* @__PURE__ */
|
|
3353
|
-
/* @__PURE__ */
|
|
3354
|
-
/* @__PURE__ */
|
|
3040
|
+
return /* @__PURE__ */ jsxs("div", { className: "quoin-list-item", "data-list": "ordered", children: [
|
|
3041
|
+
/* @__PURE__ */ jsx(ListMarker, { list: "ordered", number, depth: block.indent }),
|
|
3042
|
+
/* @__PURE__ */ jsx(EditableRegion, { block: block.id, region: REGION, label: labels.numberedItem(number) })
|
|
3355
3043
|
] });
|
|
3356
3044
|
}
|
|
3357
3045
|
function TaskItem({ block, controller }) {
|
|
3358
3046
|
const labels = useLabels();
|
|
3359
3047
|
const hostId = useRegionDomId(block.id, REGION);
|
|
3360
|
-
return /* @__PURE__ */
|
|
3361
|
-
/* @__PURE__ */
|
|
3362
|
-
/* @__PURE__ */
|
|
3048
|
+
return /* @__PURE__ */ jsxs("div", { className: "quoin-task", "data-checked": block.attrs.checked === true, children: [
|
|
3049
|
+
/* @__PURE__ */ jsx(TaskCheckbox, { block, controller, label: labels.task, labelledBy: hostId }),
|
|
3050
|
+
/* @__PURE__ */ jsx(EditableRegion, { id: hostId, block: block.id, region: REGION, label: labels.task })
|
|
3363
3051
|
] });
|
|
3364
3052
|
}
|
|
3365
3053
|
var MarkdownBlock = (props) => {
|
|
@@ -3367,20 +3055,20 @@ var MarkdownBlock = (props) => {
|
|
|
3367
3055
|
const labels = useLabels();
|
|
3368
3056
|
switch (block.attrs.kind) {
|
|
3369
3057
|
case "heading":
|
|
3370
|
-
return /* @__PURE__ */
|
|
3058
|
+
return /* @__PURE__ */ jsx(Heading, { block });
|
|
3371
3059
|
case "bullet":
|
|
3372
|
-
return /* @__PURE__ */
|
|
3373
|
-
/* @__PURE__ */
|
|
3374
|
-
/* @__PURE__ */
|
|
3060
|
+
return /* @__PURE__ */ jsxs("div", { className: "quoin-list-item", "data-list": "bullet", children: [
|
|
3061
|
+
/* @__PURE__ */ jsx(ListMarker, { list: "bullet", depth: block.indent }),
|
|
3062
|
+
/* @__PURE__ */ jsx(EditableRegion, { block: block.id, region: REGION, label: labels.bulletItem })
|
|
3375
3063
|
] });
|
|
3376
3064
|
case "ordered":
|
|
3377
|
-
return /* @__PURE__ */
|
|
3065
|
+
return /* @__PURE__ */ jsx(NumberedItem, { ...props });
|
|
3378
3066
|
case "task":
|
|
3379
|
-
return /* @__PURE__ */
|
|
3067
|
+
return /* @__PURE__ */ jsx(TaskItem, { ...props });
|
|
3380
3068
|
case "quote":
|
|
3381
|
-
return /* @__PURE__ */
|
|
3069
|
+
return /* @__PURE__ */ jsx("div", { className: "quoin-quote", children: /* @__PURE__ */ jsx(EditableRegion, { block: block.id, region: REGION, label: labels.quote }) });
|
|
3382
3070
|
default:
|
|
3383
|
-
return /* @__PURE__ */
|
|
3071
|
+
return /* @__PURE__ */ jsx(EditableRegion, { block: block.id, region: REGION, label: labels.paragraph });
|
|
3384
3072
|
}
|
|
3385
3073
|
};
|
|
3386
3074
|
|
|
@@ -3393,16 +3081,13 @@ function nestedBlockIds({ doc }, blockId) {
|
|
|
3393
3081
|
function useNestedBlocks(controller, blockId) {
|
|
3394
3082
|
return useEditorState(controller, (state) => nestedBlockIds(state, blockId), sameItems);
|
|
3395
3083
|
}
|
|
3396
|
-
|
|
3397
|
-
// src/blocks/text/ToggleBlock.tsx
|
|
3398
|
-
import { jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
3399
3084
|
var ToggleBlock = ({ block, controller }) => {
|
|
3400
3085
|
const labels = useLabels();
|
|
3401
3086
|
const domId = useBlockDomId();
|
|
3402
3087
|
const nested = useNestedBlocks(controller, block.id);
|
|
3403
3088
|
const open = useToggleOpen(controller, block);
|
|
3404
|
-
return /* @__PURE__ */
|
|
3405
|
-
/* @__PURE__ */
|
|
3089
|
+
return /* @__PURE__ */ jsxs("div", { className: "quoin-toggle", "data-open": open, children: [
|
|
3090
|
+
/* @__PURE__ */ jsx(
|
|
3406
3091
|
ToggleChevron,
|
|
3407
3092
|
{
|
|
3408
3093
|
block,
|
|
@@ -3411,7 +3096,7 @@ var ToggleBlock = ({ block, controller }) => {
|
|
|
3411
3096
|
controls: nested.length === 0 ? void 0 : nested.map(domId).join(" ")
|
|
3412
3097
|
}
|
|
3413
3098
|
),
|
|
3414
|
-
/* @__PURE__ */
|
|
3099
|
+
/* @__PURE__ */ jsx(EditableRegion, { block: block.id, region: "text", label: labels.toggle })
|
|
3415
3100
|
] });
|
|
3416
3101
|
};
|
|
3417
3102
|
|
|
@@ -3442,21 +3127,6 @@ function drawnInPlace(definitions, type) {
|
|
|
3442
3127
|
}
|
|
3443
3128
|
var drawsType = (definitions, type) => !Object.hasOwn(inPlaceRenderers, type) || blockByType(definitions, type) !== void 0;
|
|
3444
3129
|
var opensEditor = (definitions, type) => drawnInPlace(definitions, type) || !drawnAsText(definitions, type, false) && blockByType(definitions, type)?.editor !== void 0;
|
|
3445
|
-
|
|
3446
|
-
// src/gutter/turn-into-targets.ts
|
|
3447
|
-
import {
|
|
3448
|
-
Code as Code3,
|
|
3449
|
-
Heading1,
|
|
3450
|
-
Heading2,
|
|
3451
|
-
Heading3,
|
|
3452
|
-
List,
|
|
3453
|
-
ListCollapse,
|
|
3454
|
-
ListOrdered,
|
|
3455
|
-
ListTodo,
|
|
3456
|
-
MessageSquare as MessageSquare2,
|
|
3457
|
-
TextQuote,
|
|
3458
|
-
Type
|
|
3459
|
-
} from "lucide-react";
|
|
3460
3130
|
var HEADING_ICONS = [Heading1, Heading2, Heading3];
|
|
3461
3131
|
function turnIntoTargets(labels) {
|
|
3462
3132
|
const { blockNames } = labels;
|
|
@@ -3477,50 +3147,44 @@ function turnIntoTargets(labels) {
|
|
|
3477
3147
|
line("numberedList", blockNames.numberedList, ListOrdered, { kind: "ordered" }),
|
|
3478
3148
|
line("todoList", blockNames.todoList, ListTodo, { kind: "task" }),
|
|
3479
3149
|
line("quote", blockNames.quote, TextQuote, { kind: "quote" }),
|
|
3480
|
-
{ id: "callout", label: blockNames.callout, icon:
|
|
3150
|
+
{ id: "callout", label: blockNames.callout, icon: MessageSquare, type: "CALLOUT", attrs: {} },
|
|
3481
3151
|
{ id: "toggle", label: blockNames.toggle, icon: ListCollapse, type: "TOGGLE", attrs: {} },
|
|
3482
|
-
{ id: "code", label: blockNames.code, icon:
|
|
3152
|
+
{ id: "code", label: blockNames.code, icon: Code, type: "CODE", attrs: {} }
|
|
3483
3153
|
];
|
|
3484
3154
|
}
|
|
3485
|
-
|
|
3486
|
-
// src/gutter/TurnIntoMenu.tsx
|
|
3487
|
-
import { jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
3488
3155
|
function TurnIntoItems({ kit, controller, blockIds }) {
|
|
3489
3156
|
const { blockTypes, labels } = useQuoin();
|
|
3490
3157
|
const targets = turnIntoTargets(labels).filter((target) => drawsType(blockTypes, target.type));
|
|
3491
|
-
return targets.map((target) => /* @__PURE__ */
|
|
3492
|
-
/* @__PURE__ */
|
|
3158
|
+
return targets.map((target) => /* @__PURE__ */ jsxs(kit.Item, { onSelect: () => runOnBlocks(controller, blockIds, setBlockType(target.type, target.attrs)), children: [
|
|
3159
|
+
/* @__PURE__ */ jsx(MenuIcon, { icon: target.icon }),
|
|
3493
3160
|
target.label
|
|
3494
3161
|
] }, target.id));
|
|
3495
3162
|
}
|
|
3496
3163
|
function TurnIntoMenu(props) {
|
|
3497
3164
|
const { kit } = props;
|
|
3498
3165
|
const labels = useLabels();
|
|
3499
|
-
return /* @__PURE__ */
|
|
3500
|
-
/* @__PURE__ */
|
|
3501
|
-
/* @__PURE__ */
|
|
3166
|
+
return /* @__PURE__ */ jsxs(kit.Sub, { children: [
|
|
3167
|
+
/* @__PURE__ */ jsxs(kit.SubTrigger, { children: [
|
|
3168
|
+
/* @__PURE__ */ jsx(MenuIcon, { icon: Repeat2 }),
|
|
3502
3169
|
labels.turnInto
|
|
3503
3170
|
] }),
|
|
3504
|
-
/* @__PURE__ */
|
|
3171
|
+
/* @__PURE__ */ jsx(kit.SubContent, { children: /* @__PURE__ */ jsx(TurnIntoItems, { ...props }) })
|
|
3505
3172
|
] });
|
|
3506
3173
|
}
|
|
3507
|
-
|
|
3508
|
-
// src/gutter/BlockMenuItems.tsx
|
|
3509
|
-
import { Fragment as Fragment7, jsx as jsx40, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
3510
3174
|
var DESTRUCTIVE = "text-destructive focus:text-destructive";
|
|
3511
3175
|
function ActionItem({ kit, controller, action, blockIds }) {
|
|
3512
3176
|
const labels = useLabels();
|
|
3513
3177
|
const hint = action.shortcut === void 0 ? null : shortcutHint(action.shortcut, controller.isMac, labels);
|
|
3514
|
-
return /* @__PURE__ */
|
|
3178
|
+
return /* @__PURE__ */ jsxs(
|
|
3515
3179
|
kit.Item,
|
|
3516
3180
|
{
|
|
3517
3181
|
className: action.destructive ? DESTRUCTIVE : void 0,
|
|
3518
3182
|
"aria-keyshortcuts": hint?.aria,
|
|
3519
3183
|
onSelect: () => action.run(controller, blockIds),
|
|
3520
3184
|
children: [
|
|
3521
|
-
/* @__PURE__ */
|
|
3185
|
+
/* @__PURE__ */ jsx(MenuIcon, { icon: action.icon }),
|
|
3522
3186
|
action.label,
|
|
3523
|
-
hint !== null && /* @__PURE__ */
|
|
3187
|
+
hint !== null && /* @__PURE__ */ jsx(kit.Shortcut, { "aria-hidden": "true", children: hint.text })
|
|
3524
3188
|
]
|
|
3525
3189
|
}
|
|
3526
3190
|
);
|
|
@@ -3532,15 +3196,15 @@ function BlockMenuItems({ kit, controller, blocks, styled, title, actions }) {
|
|
|
3532
3196
|
const anyText = styled.some((block) => isTextFlow(state.schema, block));
|
|
3533
3197
|
const anyMarkdown = styled.some((block) => block.type === "MARKDOWN");
|
|
3534
3198
|
const allCallouts = styled.length > 0 && styled.every((block) => block.type === "CALLOUT");
|
|
3535
|
-
return /* @__PURE__ */
|
|
3536
|
-
/* @__PURE__ */
|
|
3537
|
-
anyText && /* @__PURE__ */
|
|
3538
|
-
anyMarkdown && /* @__PURE__ */
|
|
3539
|
-
allCallouts && /* @__PURE__ */
|
|
3540
|
-
(anyText || anyMarkdown || allCallouts) && /* @__PURE__ */
|
|
3541
|
-
shown.map((action) => /* @__PURE__ */
|
|
3542
|
-
action.destructive && /* @__PURE__ */
|
|
3543
|
-
/* @__PURE__ */
|
|
3199
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3200
|
+
/* @__PURE__ */ jsx(kit.Label, { className: "text-muted-foreground text-xs", children: title }),
|
|
3201
|
+
anyText && /* @__PURE__ */ jsx(TurnIntoMenu, { kit, controller, blockIds: styled.map((block) => block.id) }),
|
|
3202
|
+
anyMarkdown && /* @__PURE__ */ jsx(ColorMenu, { kit, controller, blocks: styled }),
|
|
3203
|
+
allCallouts && /* @__PURE__ */ jsx(CalloutMenus, { kit, controller, blocks: styled }),
|
|
3204
|
+
(anyText || anyMarkdown || allCallouts) && /* @__PURE__ */ jsx(kit.Separator, {}),
|
|
3205
|
+
shown.map((action) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
3206
|
+
action.destructive && /* @__PURE__ */ jsx(kit.Separator, {}),
|
|
3207
|
+
/* @__PURE__ */ jsx(ActionItem, { kit, controller, action, blockIds })
|
|
3544
3208
|
] }, action.id))
|
|
3545
3209
|
] });
|
|
3546
3210
|
}
|
|
@@ -3570,9 +3234,6 @@ var CONTEXT_KIT = {
|
|
|
3570
3234
|
SubContent: ContextMenuSubContent,
|
|
3571
3235
|
SubTrigger: ContextMenuSubTrigger
|
|
3572
3236
|
};
|
|
3573
|
-
|
|
3574
|
-
// src/gutter/use-context-menu-opener.ts
|
|
3575
|
-
import { useEffect as useEffect11 } from "react";
|
|
3576
3237
|
var GUTTER_BLOCK = "data-quoin-gutter-block";
|
|
3577
3238
|
var OWN_MENU = `[${NATIVE_INTERACTION}], input, textarea, select`;
|
|
3578
3239
|
function contextBlock(controller, target) {
|
|
@@ -3587,7 +3248,7 @@ function contextBlock(controller, target) {
|
|
|
3587
3248
|
return block === void 0 || isTextFlow(state.schema, block) ? null : block.id;
|
|
3588
3249
|
}
|
|
3589
3250
|
function useContextMenuOpener(controller, store, trigger) {
|
|
3590
|
-
|
|
3251
|
+
useEffect(() => {
|
|
3591
3252
|
const root = controller.root;
|
|
3592
3253
|
if (root === null) return;
|
|
3593
3254
|
const blockOf = (event) => event.target === trigger.current || controller.readOnly ? null : contextBlock(controller, event.target);
|
|
@@ -3607,9 +3268,6 @@ function useContextMenuOpener(controller, store, trigger) {
|
|
|
3607
3268
|
}, [controller, store, trigger]);
|
|
3608
3269
|
}
|
|
3609
3270
|
|
|
3610
|
-
// src/gutter/use-menu-blocks.ts
|
|
3611
|
-
import { useCallback as useCallback6, useContext as useContext4, useEffect as useEffect12 } from "react";
|
|
3612
|
-
|
|
3613
3271
|
// src/gutter/block-type-label.ts
|
|
3614
3272
|
var KIND_NAMES = {
|
|
3615
3273
|
paragraph: "text",
|
|
@@ -3634,14 +3292,11 @@ function blockTypeLabel(labels, block, definitions, extensionNames = {}) {
|
|
|
3634
3292
|
if (name !== void 0) return labels.blockNames[name];
|
|
3635
3293
|
return nameIn(extensionNames, block.type) ?? blockByType(definitions, block.type)?.label ?? labels.unsupportedBlock;
|
|
3636
3294
|
}
|
|
3637
|
-
|
|
3638
|
-
// src/gutter/extension-block-names.ts
|
|
3639
|
-
import { createContext as createContext4 } from "react";
|
|
3640
|
-
var ExtensionBlockNames = createContext4({});
|
|
3295
|
+
var ExtensionBlockNames = createContext({});
|
|
3641
3296
|
|
|
3642
3297
|
// src/gutter/use-menu-blocks.ts
|
|
3643
3298
|
function useLiveBlocks(controller, blockIds) {
|
|
3644
|
-
const select =
|
|
3299
|
+
const select = useCallback(
|
|
3645
3300
|
(state) => blockIds.flatMap((id) => blockById(state.doc, id) ?? []),
|
|
3646
3301
|
[blockIds]
|
|
3647
3302
|
);
|
|
@@ -3650,23 +3305,20 @@ function useLiveBlocks(controller, blockIds) {
|
|
|
3650
3305
|
function useMenuBlocks(controller, store, menu) {
|
|
3651
3306
|
const labels = useLabels();
|
|
3652
3307
|
const { blockTypes } = useQuoin();
|
|
3653
|
-
const extensionNames =
|
|
3308
|
+
const extensionNames = useContext(ExtensionBlockNames);
|
|
3654
3309
|
const blocks = useLiveBlocks(controller, menu.blockIds);
|
|
3655
3310
|
const styled = useLiveBlocks(controller, menu.styleIds);
|
|
3656
3311
|
const gone = blocks.length === 0;
|
|
3657
|
-
|
|
3312
|
+
useEffect(() => {
|
|
3658
3313
|
if (gone) closeBlockMenu(store);
|
|
3659
3314
|
}, [gone, store]);
|
|
3660
3315
|
return { blocks, styled, title: gone ? "" : blockTypeLabel(labels, blocks[0], blockTypes, extensionNames) };
|
|
3661
3316
|
}
|
|
3662
|
-
|
|
3663
|
-
// src/gutter/BlockContextMenu.tsx
|
|
3664
|
-
import { jsx as jsx41, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
3665
3317
|
function BlockContextMenuContent({ controller, store, actions, menu }) {
|
|
3666
3318
|
const labels = useLabels();
|
|
3667
3319
|
const { blocks, styled, title } = useMenuBlocks(controller, store, menu);
|
|
3668
3320
|
if (blocks.length === 0) return null;
|
|
3669
|
-
return /* @__PURE__ */
|
|
3321
|
+
return /* @__PURE__ */ jsx(ContextMenuContent, { "aria-label": labels.blockMenu(title), onCloseAutoFocus: returnFocusToText(controller), children: /* @__PURE__ */ jsx(
|
|
3670
3322
|
BlockMenuItems,
|
|
3671
3323
|
{
|
|
3672
3324
|
kit: CONTEXT_KIT,
|
|
@@ -3679,11 +3331,11 @@ function BlockContextMenuContent({ controller, store, actions, menu }) {
|
|
|
3679
3331
|
) });
|
|
3680
3332
|
}
|
|
3681
3333
|
function BlockContextMenu({ controller, store, actions }) {
|
|
3682
|
-
const trigger =
|
|
3334
|
+
const trigger = useRef(null);
|
|
3683
3335
|
const menu = useCanvasUi(store, (state) => state.blockMenu);
|
|
3684
3336
|
const open = menu?.anchor === "pointer";
|
|
3685
3337
|
useContextMenuOpener(controller, store, trigger);
|
|
3686
|
-
return /* @__PURE__ */
|
|
3338
|
+
return /* @__PURE__ */ jsxs(
|
|
3687
3339
|
ContextMenu,
|
|
3688
3340
|
{
|
|
3689
3341
|
open,
|
|
@@ -3691,8 +3343,8 @@ function BlockContextMenu({ controller, store, actions }) {
|
|
|
3691
3343
|
if (!next) closeBlockMenu(store);
|
|
3692
3344
|
},
|
|
3693
3345
|
children: [
|
|
3694
|
-
/* @__PURE__ */
|
|
3695
|
-
open && /* @__PURE__ */
|
|
3346
|
+
/* @__PURE__ */ jsx(ContextMenuTrigger, { ref: trigger, hidden: true }),
|
|
3347
|
+
open && /* @__PURE__ */ jsx(BlockContextMenuContent, { controller, store, actions, menu })
|
|
3696
3348
|
]
|
|
3697
3349
|
}
|
|
3698
3350
|
);
|
|
@@ -3708,14 +3360,6 @@ function blockMenuKeymap(store) {
|
|
|
3708
3360
|
};
|
|
3709
3361
|
return defineExtension({ name: "block-menu", keymap: { "Mod-/": openForHead } });
|
|
3710
3362
|
}
|
|
3711
|
-
|
|
3712
|
-
// src/gutter/Gutter.tsx
|
|
3713
|
-
import { useEffect as useEffect15, useRef as useRef20 } from "react";
|
|
3714
|
-
import { GripVertical, Plus } from "lucide-react";
|
|
3715
|
-
|
|
3716
|
-
// src/drag/DragOverlay.tsx
|
|
3717
|
-
import { forwardRef as forwardRef6, useImperativeHandle, useRef as useRef18 } from "react";
|
|
3718
|
-
import { Fragment as Fragment8, jsx as jsx42, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
3719
3363
|
var UNIQUE_OR_FOCUSABLE = ["id", "data-block-id", "contenteditable", "tabindex"];
|
|
3720
3364
|
function copyOf(shell) {
|
|
3721
3365
|
const copy = shell.cloneNode(true);
|
|
@@ -3726,9 +3370,9 @@ function copyOf(shell) {
|
|
|
3726
3370
|
return copy;
|
|
3727
3371
|
}
|
|
3728
3372
|
var place = (element, { top, left, width }) => Object.assign(element.style, { top: `${top}px`, left: `${left}px`, width: `${width}px` });
|
|
3729
|
-
var DragOverlay =
|
|
3730
|
-
const ghost =
|
|
3731
|
-
const line =
|
|
3373
|
+
var DragOverlay = forwardRef(function DragOverlay2(_props, ref) {
|
|
3374
|
+
const ghost = useRef(null);
|
|
3375
|
+
const line = useRef(null);
|
|
3732
3376
|
useImperativeHandle(ref, () => ({
|
|
3733
3377
|
show(shells, box) {
|
|
3734
3378
|
const element = ghost.current;
|
|
@@ -3755,8 +3399,8 @@ var DragOverlay = forwardRef6(function DragOverlay2(_props, ref) {
|
|
|
3755
3399
|
if (line.current) line.current.hidden = true;
|
|
3756
3400
|
}
|
|
3757
3401
|
}));
|
|
3758
|
-
return /* @__PURE__ */
|
|
3759
|
-
/* @__PURE__ */
|
|
3402
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3403
|
+
/* @__PURE__ */ jsx(
|
|
3760
3404
|
"div",
|
|
3761
3405
|
{
|
|
3762
3406
|
ref: ghost,
|
|
@@ -3766,7 +3410,7 @@ var DragOverlay = forwardRef6(function DragOverlay2(_props, ref) {
|
|
|
3766
3410
|
className: "pointer-events-none fixed z-20 opacity-50"
|
|
3767
3411
|
}
|
|
3768
3412
|
),
|
|
3769
|
-
/* @__PURE__ */
|
|
3413
|
+
/* @__PURE__ */ jsx(
|
|
3770
3414
|
"div",
|
|
3771
3415
|
{
|
|
3772
3416
|
ref: line,
|
|
@@ -3779,9 +3423,6 @@ var DragOverlay = forwardRef6(function DragOverlay2(_props, ref) {
|
|
|
3779
3423
|
] });
|
|
3780
3424
|
});
|
|
3781
3425
|
|
|
3782
|
-
// src/drag/use-block-drag.ts
|
|
3783
|
-
import { useEffect as useEffect13, useRef as useRef19 } from "react";
|
|
3784
|
-
|
|
3785
3426
|
// src/canvas/structure-announcement.ts
|
|
3786
3427
|
var DELETION_STEPS = /* @__PURE__ */ new Set(["removeBlocks", "setIndent"]);
|
|
3787
3428
|
function drawnPosition(doc, blockId) {
|
|
@@ -4009,9 +3650,9 @@ function pressDragHandle(press) {
|
|
|
4009
3650
|
// src/drag/use-block-drag.ts
|
|
4010
3651
|
function useBlockDrag(controller, store, blockId, overlay) {
|
|
4011
3652
|
const labels = useLabels();
|
|
4012
|
-
const cancel =
|
|
4013
|
-
const dragged =
|
|
4014
|
-
|
|
3653
|
+
const cancel = useRef(null);
|
|
3654
|
+
const dragged = useRef(false);
|
|
3655
|
+
useEffect(() => () => cancel.current?.(), []);
|
|
4015
3656
|
return {
|
|
4016
3657
|
onPointerDown(event) {
|
|
4017
3658
|
cancel.current?.();
|
|
@@ -4058,21 +3699,18 @@ function addBlockBelow(controller, blockId) {
|
|
|
4058
3699
|
controller.focus();
|
|
4059
3700
|
return ok;
|
|
4060
3701
|
}
|
|
4061
|
-
|
|
4062
|
-
// src/gutter/BlockMenu.tsx
|
|
4063
|
-
import { jsx as jsx43, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
4064
3702
|
function BlockMenuContent({ controller, store, actions, menu }) {
|
|
4065
3703
|
const labels = useLabels();
|
|
4066
3704
|
const { blocks, styled, title } = useMenuBlocks(controller, store, menu);
|
|
4067
3705
|
if (blocks.length === 0) return null;
|
|
4068
|
-
return /* @__PURE__ */
|
|
3706
|
+
return /* @__PURE__ */ jsx(
|
|
4069
3707
|
DropdownMenuContent,
|
|
4070
3708
|
{
|
|
4071
3709
|
align: "start",
|
|
4072
3710
|
"aria-label": labels.blockMenu(title),
|
|
4073
3711
|
"aria-labelledby": void 0,
|
|
4074
3712
|
onCloseAutoFocus: returnFocusToText(controller),
|
|
4075
|
-
children: /* @__PURE__ */
|
|
3713
|
+
children: /* @__PURE__ */ jsx(
|
|
4076
3714
|
BlockMenuItems,
|
|
4077
3715
|
{
|
|
4078
3716
|
kit: DROPDOWN_KIT,
|
|
@@ -4089,7 +3727,7 @@ function BlockMenuContent({ controller, store, actions, menu }) {
|
|
|
4089
3727
|
function BlockMenu({ controller, store, actions, onOpen, children }) {
|
|
4090
3728
|
const menu = useCanvasUi(store, (state) => state.blockMenu);
|
|
4091
3729
|
const open = menu?.anchor === "handle";
|
|
4092
|
-
return /* @__PURE__ */
|
|
3730
|
+
return /* @__PURE__ */ jsxs(
|
|
4093
3731
|
DropdownMenu,
|
|
4094
3732
|
{
|
|
4095
3733
|
open,
|
|
@@ -4098,8 +3736,8 @@ function BlockMenu({ controller, store, actions, onOpen, children }) {
|
|
|
4098
3736
|
else closeBlockMenu(store);
|
|
4099
3737
|
},
|
|
4100
3738
|
children: [
|
|
4101
|
-
/* @__PURE__ */
|
|
4102
|
-
open && /* @__PURE__ */
|
|
3739
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children }),
|
|
3740
|
+
open && /* @__PURE__ */ jsx(BlockMenuContent, { controller, store, actions, menu })
|
|
4103
3741
|
]
|
|
4104
3742
|
}
|
|
4105
3743
|
);
|
|
@@ -4158,9 +3796,6 @@ function useGutterPosition(controller, gutter, block) {
|
|
|
4158
3796
|
};
|
|
4159
3797
|
}, [controller, gutter, block]);
|
|
4160
3798
|
}
|
|
4161
|
-
|
|
4162
|
-
// src/gutter/use-gutter-target.ts
|
|
4163
|
-
import { useEffect as useEffect14, useState as useState11 } from "react";
|
|
4164
3799
|
var headOf = (state) => headBlockId(state.selection);
|
|
4165
3800
|
function blockAcross(controller, root, y) {
|
|
4166
3801
|
const box = root.getBoundingClientRect();
|
|
@@ -4170,8 +3805,8 @@ function blockAcross(controller, root, y) {
|
|
|
4170
3805
|
function useGutterTarget(controller, store, gutter) {
|
|
4171
3806
|
const hovered = useCanvasUi(store, (state) => state.hoveredBlock);
|
|
4172
3807
|
const head = useEditorState(controller, headOf);
|
|
4173
|
-
const [focusWithin, setFocusWithin] =
|
|
4174
|
-
|
|
3808
|
+
const [focusWithin, setFocusWithin] = useState(false);
|
|
3809
|
+
useEffect(() => {
|
|
4175
3810
|
const root = controller.root;
|
|
4176
3811
|
if (root === null) return;
|
|
4177
3812
|
const pinned = () => store.get().blockMenu !== null || store.get().drag !== null;
|
|
@@ -4193,21 +3828,18 @@ function useGutterTarget(controller, store, gutter) {
|
|
|
4193
3828
|
const target = hovered ?? fallback;
|
|
4194
3829
|
return { target, focused: target !== null && target === fallback };
|
|
4195
3830
|
}
|
|
4196
|
-
|
|
4197
|
-
// src/gutter/Gutter.tsx
|
|
4198
|
-
import { Fragment as Fragment9, jsx as jsx44, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
4199
3831
|
var GUTTER = "absolute top-0 left-0 z-10 flex items-center gap-0.5 pointer-coarse:not-data-current:hidden";
|
|
4200
3832
|
var ADD_BELOW = "text-muted-foreground pointer-coarse:hidden";
|
|
4201
3833
|
function Gutter({ controller, store, actions }) {
|
|
4202
3834
|
const labels = useLabels();
|
|
4203
|
-
const element =
|
|
4204
|
-
const overlay =
|
|
4205
|
-
const menuOpenAtPress =
|
|
3835
|
+
const element = useRef(null);
|
|
3836
|
+
const overlay = useRef(null);
|
|
3837
|
+
const menuOpenAtPress = useRef(false);
|
|
4206
3838
|
const { target, focused } = useGutterTarget(controller, store, element);
|
|
4207
3839
|
const menuOpen = useCanvasUi(store, (state) => state.blockMenu !== null);
|
|
4208
3840
|
const drag = useBlockDrag(controller, store, target, overlay);
|
|
4209
3841
|
useGutterPosition(controller, element, target);
|
|
4210
|
-
|
|
3842
|
+
useEffect(() => () => closeBlockMenu(store), [store]);
|
|
4211
3843
|
const openMenu = () => {
|
|
4212
3844
|
const { state } = controller.editor;
|
|
4213
3845
|
if (target !== null && state.doc.index.has(target)) openBlockMenu(store, state, target);
|
|
@@ -4215,8 +3847,8 @@ function Gutter({ controller, store, actions }) {
|
|
|
4215
3847
|
const addBelow = () => {
|
|
4216
3848
|
if (target !== null) addBlockBelow(controller, target);
|
|
4217
3849
|
};
|
|
4218
|
-
return /* @__PURE__ */
|
|
4219
|
-
/* @__PURE__ */
|
|
3850
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3851
|
+
/* @__PURE__ */ jsxs(
|
|
4220
3852
|
"div",
|
|
4221
3853
|
{
|
|
4222
3854
|
ref: element,
|
|
@@ -4224,7 +3856,7 @@ function Gutter({ controller, store, actions }) {
|
|
|
4224
3856
|
"data-current": focused || menuOpen ? "" : void 0,
|
|
4225
3857
|
...{ [GUTTER_BLOCK]: target ?? void 0 },
|
|
4226
3858
|
children: [
|
|
4227
|
-
/* @__PURE__ */
|
|
3859
|
+
/* @__PURE__ */ jsx(
|
|
4228
3860
|
Button,
|
|
4229
3861
|
{
|
|
4230
3862
|
type: "button",
|
|
@@ -4235,10 +3867,10 @@ function Gutter({ controller, store, actions }) {
|
|
|
4235
3867
|
className: ADD_BELOW,
|
|
4236
3868
|
onPointerDown: keepFocus,
|
|
4237
3869
|
onClick: addBelow,
|
|
4238
|
-
children: /* @__PURE__ */
|
|
3870
|
+
children: /* @__PURE__ */ jsx(Plus, {})
|
|
4239
3871
|
}
|
|
4240
3872
|
),
|
|
4241
|
-
/* @__PURE__ */
|
|
3873
|
+
/* @__PURE__ */ jsx(BlockMenu, { controller, store, actions, onOpen: openMenu, children: /* @__PURE__ */ jsx(
|
|
4242
3874
|
Button,
|
|
4243
3875
|
{
|
|
4244
3876
|
type: "button",
|
|
@@ -4257,13 +3889,13 @@ function Gutter({ controller, store, actions }) {
|
|
|
4257
3889
|
menuOpenAtPress.current = false;
|
|
4258
3890
|
if (!drag.takeClick(event) && !closing) openMenu();
|
|
4259
3891
|
},
|
|
4260
|
-
children: /* @__PURE__ */
|
|
3892
|
+
children: /* @__PURE__ */ jsx(GripVertical, {})
|
|
4261
3893
|
}
|
|
4262
3894
|
) })
|
|
4263
3895
|
]
|
|
4264
3896
|
}
|
|
4265
3897
|
),
|
|
4266
|
-
/* @__PURE__ */
|
|
3898
|
+
/* @__PURE__ */ jsx(DragOverlay, { ref: overlay })
|
|
4267
3899
|
] });
|
|
4268
3900
|
}
|
|
4269
3901
|
|
|
@@ -4274,15 +3906,6 @@ function resolveLabels(overrides) {
|
|
|
4274
3906
|
return given.length === 0 ? englishLabels : { ...englishLabels, ...Object.fromEntries(given) };
|
|
4275
3907
|
}
|
|
4276
3908
|
|
|
4277
|
-
// src/menus/bubble/bubble-extension.tsx
|
|
4278
|
-
import { createContext as createContext5, useContext as useContext5 } from "react";
|
|
4279
|
-
|
|
4280
|
-
// src/menus/bubble/BubbleToolbar.tsx
|
|
4281
|
-
import { useMemo as useMemo7 } from "react";
|
|
4282
|
-
|
|
4283
|
-
// src/menus/floating/use-selection-anchor.ts
|
|
4284
|
-
import { useMemo as useMemo6, useState as useState12 } from "react";
|
|
4285
|
-
|
|
4286
3909
|
// src/menus/floating/range-rect.ts
|
|
4287
3910
|
var TEXT_NODE = 3;
|
|
4288
3911
|
function lineBox(rect, host) {
|
|
@@ -4340,7 +3963,7 @@ function selectionHost(controller) {
|
|
|
4340
3963
|
return (first && controller.registry.get(first.block, first.region)) ?? controller.root ?? void 0;
|
|
4341
3964
|
}
|
|
4342
3965
|
function useSelectionAnchor(controller, state) {
|
|
4343
|
-
const anchor =
|
|
3966
|
+
const anchor = useMemo(
|
|
4344
3967
|
() => ({
|
|
4345
3968
|
current: state.selection === null ? null : virtualAnchor(
|
|
4346
3969
|
() => selectionRect(controller),
|
|
@@ -4349,31 +3972,24 @@ function useSelectionAnchor(controller, state) {
|
|
|
4349
3972
|
}),
|
|
4350
3973
|
[controller, state]
|
|
4351
3974
|
);
|
|
4352
|
-
const [side, setSide] =
|
|
3975
|
+
const [side, setSide] = useState("top");
|
|
4353
3976
|
useIsomorphicLayoutEffect(() => {
|
|
4354
3977
|
const rect = selectionRect(controller);
|
|
4355
3978
|
if (rect) setSide(rect.top < ROOM_ABOVE ? "bottom" : "top");
|
|
4356
3979
|
}, [controller, state]);
|
|
4357
3980
|
return { anchor, side };
|
|
4358
3981
|
}
|
|
4359
|
-
|
|
4360
|
-
// src/menus/bubble/AlignDropdown.tsx
|
|
4361
|
-
import { AlignCenter as AlignCenter2, AlignJustify, AlignLeft as AlignLeft2, AlignRight as AlignRight2, CheckIcon as CheckIcon5 } from "lucide-react";
|
|
4362
|
-
|
|
4363
|
-
// src/menus/bubble/ToolbarMenu.tsx
|
|
4364
|
-
import { useRef as useRef21 } from "react";
|
|
4365
|
-
import { jsx as jsx45, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
4366
3982
|
function ToolbarMenu({ controller, trigger, children }) {
|
|
4367
|
-
const fromToolbar =
|
|
4368
|
-
return /* @__PURE__ */
|
|
3983
|
+
const fromToolbar = useRef(false);
|
|
3984
|
+
return /* @__PURE__ */ jsxs(
|
|
4369
3985
|
DropdownMenu,
|
|
4370
3986
|
{
|
|
4371
3987
|
onOpenChange: (open) => {
|
|
4372
3988
|
if (open) fromToolbar.current = isBubblePart(document.activeElement, controller);
|
|
4373
3989
|
},
|
|
4374
3990
|
children: [
|
|
4375
|
-
/* @__PURE__ */
|
|
4376
|
-
/* @__PURE__ */
|
|
3991
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: trigger }),
|
|
3992
|
+
/* @__PURE__ */ jsx(
|
|
4377
3993
|
DropdownMenuContent,
|
|
4378
3994
|
{
|
|
4379
3995
|
align: "start",
|
|
@@ -4388,10 +4004,7 @@ function ToolbarMenu({ controller, trigger, children }) {
|
|
|
4388
4004
|
}
|
|
4389
4005
|
);
|
|
4390
4006
|
}
|
|
4391
|
-
|
|
4392
|
-
// src/menus/bubble/AlignDropdown.tsx
|
|
4393
|
-
import { jsx as jsx46, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
4394
|
-
var ICONS = { left: AlignLeft2, center: AlignCenter2, right: AlignRight2, justify: AlignJustify };
|
|
4007
|
+
var ICONS = { left: AlignLeft, center: AlignCenter, right: AlignRight, justify: AlignJustify };
|
|
4395
4008
|
var ALIGNS2 = Object.keys(ICONS);
|
|
4396
4009
|
var LABEL_KEYS = { left: "alignLeft", center: "alignCenter", right: "alignRight", justify: "alignJustify" };
|
|
4397
4010
|
function sharedAlign(state) {
|
|
@@ -4404,17 +4017,13 @@ function AlignDropdown({ controller, state }) {
|
|
|
4404
4017
|
const labels = useLabels();
|
|
4405
4018
|
const value = sharedAlign(state);
|
|
4406
4019
|
if (value === null) return null;
|
|
4407
|
-
const Icon = value === "" ?
|
|
4408
|
-
const trigger = /* @__PURE__ */
|
|
4409
|
-
return /* @__PURE__ */
|
|
4410
|
-
/* @__PURE__ */
|
|
4020
|
+
const Icon = value === "" ? AlignLeft : ICONS[value];
|
|
4021
|
+
const trigger = /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.align, children: /* @__PURE__ */ jsx(Icon, {}) });
|
|
4022
|
+
return /* @__PURE__ */ jsx(ToolbarMenu, { controller, trigger, children: /* @__PURE__ */ jsx(DropdownMenuRadioGroup, { value, onValueChange: (align) => controller.run(setTextAlign(align)), children: ALIGNS2.map((align) => /* @__PURE__ */ jsxs(DropdownMenuRadioItem, { value: align, indicator: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }), children: [
|
|
4023
|
+
/* @__PURE__ */ jsx(MenuIcon, { icon: ICONS[align] }),
|
|
4411
4024
|
labels[LABEL_KEYS[align]]
|
|
4412
4025
|
] }, align)) }) });
|
|
4413
4026
|
}
|
|
4414
|
-
|
|
4415
|
-
// src/menus/bubble/ColorPopover.tsx
|
|
4416
|
-
import { Baseline } from "lucide-react";
|
|
4417
|
-
import { jsx as jsx47 } from "react/jsx-runtime";
|
|
4418
4027
|
var MARKS = { color: "color", background: "highlight" };
|
|
4419
4028
|
function selectionColor(state, mark) {
|
|
4420
4029
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -4433,30 +4042,23 @@ function colorCommand(key, name) {
|
|
|
4433
4042
|
function ColorPopover({ controller, state }) {
|
|
4434
4043
|
const labels = useLabels();
|
|
4435
4044
|
const value = { color: selectionColor(state, MARKS.color), background: selectionColor(state, MARKS.background) };
|
|
4436
|
-
const trigger = /* @__PURE__ */
|
|
4437
|
-
return /* @__PURE__ */
|
|
4045
|
+
const trigger = /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.color, children: /* @__PURE__ */ jsx(Baseline, {}) });
|
|
4046
|
+
return /* @__PURE__ */ jsx(ToolbarMenu, { controller, trigger, children: /* @__PURE__ */ jsx(ColorGroups, { kit: DROPDOWN_KIT, value, onPick: (key, name) => controller.run(colorCommand(key, name)) }) });
|
|
4438
4047
|
}
|
|
4439
|
-
|
|
4440
|
-
// src/menus/bubble/TurnIntoDropdown.tsx
|
|
4441
|
-
import { ChevronDown } from "lucide-react";
|
|
4442
|
-
import { jsx as jsx48, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
4443
4048
|
function TurnIntoDropdown({ controller, state }) {
|
|
4444
4049
|
const labels = useLabels();
|
|
4445
|
-
const trigger = /* @__PURE__ */
|
|
4050
|
+
const trigger = /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", size: "sm", className: "gap-1 px-2 has-[>svg]:px-2", children: [
|
|
4446
4051
|
labels.turnInto,
|
|
4447
|
-
/* @__PURE__ */
|
|
4052
|
+
/* @__PURE__ */ jsx(ChevronDown, {})
|
|
4448
4053
|
] });
|
|
4449
|
-
return /* @__PURE__ */
|
|
4054
|
+
return /* @__PURE__ */ jsx(ToolbarMenu, { controller, trigger, children: /* @__PURE__ */ jsx(TurnIntoItems, { kit: DROPDOWN_KIT, controller, blockIds: selectedBlockIds(state.doc, state.selection) }) });
|
|
4450
4055
|
}
|
|
4451
|
-
|
|
4452
|
-
// src/menus/bubble/BubbleToolbar.tsx
|
|
4453
|
-
import { jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
4454
4056
|
var DIVIDER = "mx-0.5 h-5 w-px shrink-0 bg-border";
|
|
4455
4057
|
function BubbleToolbar({ controller, labels, store, extraItems }) {
|
|
4456
4058
|
const state = useEditorState(controller, wholeState);
|
|
4457
4059
|
const { anchor, side } = useSelectionAnchor(controller, state);
|
|
4458
4060
|
const roving = useRovingFocus();
|
|
4459
|
-
const items =
|
|
4061
|
+
const items = useMemo(() => bubbleItems(labels, () => store.set({ linkPopover: { open: true } })), [labels, store]);
|
|
4460
4062
|
useFocusKey(controller, roving.focusCurrent);
|
|
4461
4063
|
const onKeyDown = (event) => {
|
|
4462
4064
|
if (!roving.owns(event.target)) return;
|
|
@@ -4465,10 +4067,10 @@ function BubbleToolbar({ controller, labels, store, extraItems }) {
|
|
|
4465
4067
|
controller.focus();
|
|
4466
4068
|
} else roving.onKeyDown(event);
|
|
4467
4069
|
};
|
|
4468
|
-
const button = (item) => /* @__PURE__ */
|
|
4469
|
-
return /* @__PURE__ */
|
|
4470
|
-
/* @__PURE__ */
|
|
4471
|
-
/* @__PURE__ */
|
|
4070
|
+
const button = (item) => /* @__PURE__ */ jsx(ToolbarButton, { item, state, controller }, item.id);
|
|
4071
|
+
return /* @__PURE__ */ jsxs(Popover, { open: true, modal: false, children: [
|
|
4072
|
+
/* @__PURE__ */ jsx(PopoverAnchor, { virtualRef: anchor }),
|
|
4073
|
+
/* @__PURE__ */ jsxs(
|
|
4472
4074
|
PopoverContent,
|
|
4473
4075
|
{
|
|
4474
4076
|
ref: roving.ref,
|
|
@@ -4484,11 +4086,11 @@ function BubbleToolbar({ controller, labels, store, extraItems }) {
|
|
|
4484
4086
|
onKeyDown,
|
|
4485
4087
|
...bubblePart(controller),
|
|
4486
4088
|
children: [
|
|
4487
|
-
/* @__PURE__ */
|
|
4488
|
-
/* @__PURE__ */
|
|
4089
|
+
/* @__PURE__ */ jsx(TurnIntoDropdown, { controller, state }),
|
|
4090
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: DIVIDER }),
|
|
4489
4091
|
items.inline.map(button),
|
|
4490
|
-
/* @__PURE__ */
|
|
4491
|
-
/* @__PURE__ */
|
|
4092
|
+
/* @__PURE__ */ jsx(ColorPopover, { controller, state }),
|
|
4093
|
+
/* @__PURE__ */ jsx(AlignDropdown, { controller, state }),
|
|
4492
4094
|
items.scripts.map(button),
|
|
4493
4095
|
extraItems.map(button)
|
|
4494
4096
|
]
|
|
@@ -4496,13 +4098,10 @@ function BubbleToolbar({ controller, labels, store, extraItems }) {
|
|
|
4496
4098
|
)
|
|
4497
4099
|
] });
|
|
4498
4100
|
}
|
|
4499
|
-
|
|
4500
|
-
// src/ui/use-media-query.ts
|
|
4501
|
-
import { useCallback as useCallback7, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
4502
4101
|
var listOf = (query) => typeof window.matchMedia === "function" ? window.matchMedia(query) : null;
|
|
4503
4102
|
var readOnServer = () => false;
|
|
4504
4103
|
function useMediaQuery(query, unsupported) {
|
|
4505
|
-
const subscribe3 =
|
|
4104
|
+
const subscribe3 = useCallback(
|
|
4506
4105
|
(notify) => {
|
|
4507
4106
|
const list = listOf(query);
|
|
4508
4107
|
list?.addEventListener("change", notify);
|
|
@@ -4511,7 +4110,7 @@ function useMediaQuery(query, unsupported) {
|
|
|
4511
4110
|
[query]
|
|
4512
4111
|
);
|
|
4513
4112
|
const read2 = () => listOf(query)?.matches ?? unsupported;
|
|
4514
|
-
return
|
|
4113
|
+
return useSyncExternalStore(subscribe3, read2, readOnServer);
|
|
4515
4114
|
}
|
|
4516
4115
|
|
|
4517
4116
|
// src/menus/bubble/use-fine-pointer.ts
|
|
@@ -4526,31 +4125,21 @@ function useBubbleVisibility(controller) {
|
|
|
4526
4125
|
const settled = useSelectionSettled(controller);
|
|
4527
4126
|
return range && !readOnly && fine && settled;
|
|
4528
4127
|
}
|
|
4529
|
-
|
|
4530
|
-
// src/menus/bubble/bubble-extension.tsx
|
|
4531
|
-
import { jsx as jsx50 } from "react/jsx-runtime";
|
|
4532
4128
|
var NO_ITEMS = [];
|
|
4533
|
-
var BubbleItemsContext =
|
|
4129
|
+
var BubbleItemsContext = createContext(NO_ITEMS);
|
|
4534
4130
|
var BubbleItemsProvider = BubbleItemsContext.Provider;
|
|
4535
4131
|
function BubbleOverlay({ controller }) {
|
|
4536
4132
|
const visible = useBubbleVisibility(controller);
|
|
4537
4133
|
const labels = useLabels();
|
|
4538
4134
|
const store = useCanvasUiStore();
|
|
4539
|
-
const extraItems =
|
|
4135
|
+
const extraItems = useContext(BubbleItemsContext);
|
|
4540
4136
|
if (!visible) return null;
|
|
4541
|
-
return /* @__PURE__ */
|
|
4137
|
+
return /* @__PURE__ */ jsx(BubbleToolbar, { controller, labels, store, extraItems });
|
|
4542
4138
|
}
|
|
4543
4139
|
function bubbleExtension() {
|
|
4544
4140
|
return defineExtension({ name: "bubble", ui: { overlays: [BubbleOverlay] } });
|
|
4545
4141
|
}
|
|
4546
4142
|
|
|
4547
|
-
// src/menus/link/link-extension.tsx
|
|
4548
|
-
import { useEffect as useEffect19 } from "react";
|
|
4549
|
-
|
|
4550
|
-
// src/menus/link/LinkHoverCard.tsx
|
|
4551
|
-
import { ExternalLink, Pencil as Pencil2, Unlink } from "lucide-react";
|
|
4552
|
-
import { useMemo as useMemo8, useRef as useRef23 } from "react";
|
|
4553
|
-
|
|
4554
4143
|
// src/menus/link/link-at-selection.ts
|
|
4555
4144
|
function linkAround(state, from, to = from) {
|
|
4556
4145
|
if (from.block !== to.block || from.region !== to.region) return null;
|
|
@@ -4609,12 +4198,9 @@ function unlinkRange({ block, region, from, to }) {
|
|
|
4609
4198
|
return true;
|
|
4610
4199
|
};
|
|
4611
4200
|
}
|
|
4612
|
-
|
|
4613
|
-
// src/menus/link/use-rested-value.ts
|
|
4614
|
-
import { useEffect as useEffect16, useState as useState13 } from "react";
|
|
4615
4201
|
function useRestedValue(value, delay) {
|
|
4616
|
-
const [rested, setRested] =
|
|
4617
|
-
|
|
4202
|
+
const [rested, setRested] = useState(null);
|
|
4203
|
+
useEffect(() => {
|
|
4618
4204
|
if (value === null) return;
|
|
4619
4205
|
const timer = setTimeout(() => setRested(value), delay);
|
|
4620
4206
|
return () => {
|
|
@@ -4637,19 +4223,16 @@ function useCaretInLink(controller, delay) {
|
|
|
4637
4223
|
const settled = useSelectionSettled(controller);
|
|
4638
4224
|
return useRestedValue(settled ? key : null, delay) !== null;
|
|
4639
4225
|
}
|
|
4640
|
-
|
|
4641
|
-
// src/menus/link/use-pointer-link.ts
|
|
4642
|
-
import { useCallback as useCallback8, useEffect as useEffect17, useRef as useRef22, useState as useState14 } from "react";
|
|
4643
4226
|
function usePointerLink(controller, card, delay) {
|
|
4644
|
-
const [element, setElement] =
|
|
4645
|
-
const shown =
|
|
4646
|
-
const timer =
|
|
4647
|
-
const show =
|
|
4227
|
+
const [element, setElement] = useState(null);
|
|
4228
|
+
const shown = useRef(null);
|
|
4229
|
+
const timer = useRef(void 0);
|
|
4230
|
+
const show = useCallback((next) => {
|
|
4648
4231
|
clearTimeout(timer.current);
|
|
4649
4232
|
shown.current = next;
|
|
4650
4233
|
setElement(next);
|
|
4651
4234
|
}, []);
|
|
4652
|
-
|
|
4235
|
+
useEffect(() => {
|
|
4653
4236
|
const onOver = (event) => {
|
|
4654
4237
|
if (event.pointerType === "touch" || event.buttons > 0) return;
|
|
4655
4238
|
const onCard = !!card.current?.contains(event.target);
|
|
@@ -4663,22 +4246,19 @@ function usePointerLink(controller, card, delay) {
|
|
|
4663
4246
|
clearTimeout(timer.current);
|
|
4664
4247
|
};
|
|
4665
4248
|
}, [controller, card, delay, show]);
|
|
4666
|
-
return { element, dismiss:
|
|
4249
|
+
return { element, dismiss: useCallback(() => show(null), [show]) };
|
|
4667
4250
|
}
|
|
4668
|
-
|
|
4669
|
-
// src/menus/link/LinkHoverCard.tsx
|
|
4670
|
-
import { jsx as jsx51, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
4671
4251
|
var REST_MS = 300;
|
|
4672
4252
|
var URL_LENGTH = 48;
|
|
4673
4253
|
var CARD = "flex w-auto items-center gap-0.5 py-1 ps-3 pe-1 shadow-md";
|
|
4674
4254
|
var ADDRESS = "me-1 whitespace-nowrap text-sm text-muted-foreground";
|
|
4675
4255
|
function LinkCard({ controller, labels, store, cardRef, element, onUnlinked }) {
|
|
4676
4256
|
const state = useEditorState(controller, wholeState);
|
|
4677
|
-
const link =
|
|
4257
|
+
const link = useMemo(
|
|
4678
4258
|
() => element === null ? linkAtSelection(state) : linkAtElement(controller, state, element),
|
|
4679
4259
|
[controller, state, element]
|
|
4680
4260
|
);
|
|
4681
|
-
const anchor =
|
|
4261
|
+
const anchor = useMemo(() => {
|
|
4682
4262
|
if (link === null) return { current: null };
|
|
4683
4263
|
const { range } = link;
|
|
4684
4264
|
const host = () => controller.registry.get(range.block, range.region);
|
|
@@ -4699,9 +4279,9 @@ function LinkCard({ controller, labels, store, cardRef, element, onUnlinked }) {
|
|
|
4699
4279
|
controller.run(unlinkRange(link.range));
|
|
4700
4280
|
onUnlinked();
|
|
4701
4281
|
};
|
|
4702
|
-
return /* @__PURE__ */
|
|
4703
|
-
/* @__PURE__ */
|
|
4704
|
-
/* @__PURE__ */
|
|
4282
|
+
return /* @__PURE__ */ jsxs(Popover, { open: true, modal: false, children: [
|
|
4283
|
+
/* @__PURE__ */ jsx(PopoverAnchor, { virtualRef: anchor }),
|
|
4284
|
+
/* @__PURE__ */ jsxs(
|
|
4705
4285
|
PopoverContent,
|
|
4706
4286
|
{
|
|
4707
4287
|
ref: cardRef,
|
|
@@ -4714,27 +4294,23 @@ function LinkCard({ controller, labels, store, cardRef, element, onUnlinked }) {
|
|
|
4714
4294
|
onPointerDown: keepFocus,
|
|
4715
4295
|
onMouseDown: keepFocus,
|
|
4716
4296
|
children: [
|
|
4717
|
-
/* @__PURE__ */
|
|
4718
|
-
href !== null && /* @__PURE__ */
|
|
4719
|
-
/* @__PURE__ */
|
|
4720
|
-
/* @__PURE__ */
|
|
4297
|
+
/* @__PURE__ */ jsx("span", { className: ADDRESS, title: address === link.href ? void 0 : link.href, children: address }),
|
|
4298
|
+
href !== null && /* @__PURE__ */ jsx(Button, { asChild: true, variant: "ghost", size: "icon-sm", children: /* @__PURE__ */ jsx("a", { href, target: "_blank", rel: "noopener noreferrer", "aria-label": labels.linkOpen, children: /* @__PURE__ */ jsx(ExternalLink, {}) }) }),
|
|
4299
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.linkEdit, onClick: edit2, children: /* @__PURE__ */ jsx(Pencil, {}) }),
|
|
4300
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.linkRemove, onClick: unlink, children: /* @__PURE__ */ jsx(Unlink, {}) })
|
|
4721
4301
|
]
|
|
4722
4302
|
}
|
|
4723
4303
|
)
|
|
4724
4304
|
] });
|
|
4725
4305
|
}
|
|
4726
4306
|
function LinkHoverCard(props) {
|
|
4727
|
-
const cardRef =
|
|
4307
|
+
const cardRef = useRef(null);
|
|
4728
4308
|
const pointer = usePointerLink(props.controller, cardRef, REST_MS);
|
|
4729
4309
|
const caretInLink = useCaretInLink(props.controller, REST_MS);
|
|
4730
4310
|
if (pointer.element === null && !caretInLink) return null;
|
|
4731
|
-
return /* @__PURE__ */
|
|
4311
|
+
return /* @__PURE__ */ jsx(LinkCard, { ...props, cardRef, element: pointer.element, onUnlinked: pointer.dismiss });
|
|
4732
4312
|
}
|
|
4733
4313
|
|
|
4734
|
-
// src/menus/link/LinkPopover.tsx
|
|
4735
|
-
import { Check as Check3, ExternalLink as ExternalLink2, Unlink as Unlink2 } from "lucide-react";
|
|
4736
|
-
import { useId as useId5, useMemo as useMemo9, useState as useState15 } from "react";
|
|
4737
|
-
|
|
4738
4314
|
// src/menus/link/apply-link.ts
|
|
4739
4315
|
function insertLinkedText(value, href, caret) {
|
|
4740
4316
|
const safe = sanitizeHref(href);
|
|
@@ -4757,9 +4333,6 @@ function applyLink(href, value) {
|
|
|
4757
4333
|
return setLink(href, link?.title)(state, dispatch);
|
|
4758
4334
|
};
|
|
4759
4335
|
}
|
|
4760
|
-
|
|
4761
|
-
// src/menus/link/LinkPopover.tsx
|
|
4762
|
-
import { jsx as jsx52, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
4763
4336
|
var CONTENT2 = "w-80 p-2 shadow-md";
|
|
4764
4337
|
var FIELD2 = "h-8";
|
|
4765
4338
|
var MESSAGE = "mt-1.5 px-1 text-sm text-destructive";
|
|
@@ -4775,11 +4348,11 @@ function popoverAnchor(controller, link) {
|
|
|
4775
4348
|
);
|
|
4776
4349
|
}
|
|
4777
4350
|
function LinkPopover({ controller, labels, onClose }) {
|
|
4778
|
-
const [link] =
|
|
4779
|
-
const [address, setAddress] =
|
|
4780
|
-
const [invalid, setInvalid] =
|
|
4781
|
-
const messageId =
|
|
4782
|
-
const anchor =
|
|
4351
|
+
const [link] = useState(() => linkAtSelection(controller.editor.state));
|
|
4352
|
+
const [address, setAddress] = useState(link?.href ?? "");
|
|
4353
|
+
const [invalid, setInvalid] = useState(false);
|
|
4354
|
+
const messageId = useId();
|
|
4355
|
+
const anchor = useMemo(() => ({ current: popoverAnchor(controller, link) }), [controller, link]);
|
|
4783
4356
|
const openHref = link && sanitizeHref(link.href);
|
|
4784
4357
|
const backToText = () => {
|
|
4785
4358
|
onClose();
|
|
@@ -4800,7 +4373,7 @@ function LinkPopover({ controller, labels, onClose }) {
|
|
|
4800
4373
|
controller.run(unsetLink);
|
|
4801
4374
|
backToText();
|
|
4802
4375
|
};
|
|
4803
|
-
return /* @__PURE__ */
|
|
4376
|
+
return /* @__PURE__ */ jsxs(
|
|
4804
4377
|
Popover,
|
|
4805
4378
|
{
|
|
4806
4379
|
open: true,
|
|
@@ -4809,8 +4382,8 @@ function LinkPopover({ controller, labels, onClose }) {
|
|
|
4809
4382
|
if (!open) onClose();
|
|
4810
4383
|
},
|
|
4811
4384
|
children: [
|
|
4812
|
-
/* @__PURE__ */
|
|
4813
|
-
/* @__PURE__ */
|
|
4385
|
+
/* @__PURE__ */ jsx(PopoverAnchor, { virtualRef: anchor }),
|
|
4386
|
+
/* @__PURE__ */ jsxs(
|
|
4814
4387
|
PopoverContent,
|
|
4815
4388
|
{
|
|
4816
4389
|
"aria-label": labels.link,
|
|
@@ -4823,8 +4396,8 @@ function LinkPopover({ controller, labels, onClose }) {
|
|
|
4823
4396
|
backToText();
|
|
4824
4397
|
},
|
|
4825
4398
|
children: [
|
|
4826
|
-
/* @__PURE__ */
|
|
4827
|
-
/* @__PURE__ */
|
|
4399
|
+
/* @__PURE__ */ jsxs("form", { noValidate: true, className: "flex items-center gap-0.5", onSubmit: apply, children: [
|
|
4400
|
+
/* @__PURE__ */ jsx(
|
|
4828
4401
|
Input,
|
|
4829
4402
|
{
|
|
4830
4403
|
type: "url",
|
|
@@ -4836,11 +4409,11 @@ function LinkPopover({ controller, labels, onClose }) {
|
|
|
4836
4409
|
onChange
|
|
4837
4410
|
}
|
|
4838
4411
|
),
|
|
4839
|
-
/* @__PURE__ */
|
|
4840
|
-
openHref && /* @__PURE__ */
|
|
4841
|
-
link !== null && /* @__PURE__ */
|
|
4412
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", variant: "ghost", size: "icon-sm", "aria-label": labels.linkApply, children: /* @__PURE__ */ jsx(Check, {}) }),
|
|
4413
|
+
openHref && /* @__PURE__ */ jsx(Button, { asChild: true, variant: "ghost", size: "icon-sm", children: /* @__PURE__ */ jsx("a", { href: openHref, target: "_blank", rel: "noopener noreferrer", "aria-label": labels.linkOpen, children: /* @__PURE__ */ jsx(ExternalLink, {}) }) }),
|
|
4414
|
+
link !== null && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.linkRemove, onClick: remove, children: /* @__PURE__ */ jsx(Unlink, {}) })
|
|
4842
4415
|
] }),
|
|
4843
|
-
invalid && /* @__PURE__ */
|
|
4416
|
+
invalid && /* @__PURE__ */ jsx("p", { id: messageId, role: "alert", className: MESSAGE, children: labels.invalidLink })
|
|
4844
4417
|
]
|
|
4845
4418
|
}
|
|
4846
4419
|
)
|
|
@@ -4848,11 +4421,8 @@ function LinkPopover({ controller, labels, onClose }) {
|
|
|
4848
4421
|
}
|
|
4849
4422
|
);
|
|
4850
4423
|
}
|
|
4851
|
-
|
|
4852
|
-
// src/menus/link/use-link-clicks.ts
|
|
4853
|
-
import { useEffect as useEffect18 } from "react";
|
|
4854
4424
|
function useLinkClicks(controller) {
|
|
4855
|
-
|
|
4425
|
+
useEffect(() => {
|
|
4856
4426
|
const onClick = (event) => {
|
|
4857
4427
|
const link = linkElementAt(controller, event.target);
|
|
4858
4428
|
if (link === null || controller.readOnly) return;
|
|
@@ -4863,9 +4433,6 @@ function useLinkClicks(controller) {
|
|
|
4863
4433
|
return () => document.removeEventListener("click", onClick, true);
|
|
4864
4434
|
}, [controller]);
|
|
4865
4435
|
}
|
|
4866
|
-
|
|
4867
|
-
// src/menus/link/link-extension.tsx
|
|
4868
|
-
import { jsx as jsx53 } from "react/jsx-runtime";
|
|
4869
4436
|
var isPopoverOpen = (state) => state.linkPopover.open;
|
|
4870
4437
|
function LinkOverlay({ controller }) {
|
|
4871
4438
|
const labels = useLabels();
|
|
@@ -4873,12 +4440,12 @@ function LinkOverlay({ controller }) {
|
|
|
4873
4440
|
const popoverOpen = useCanvasUi(store, isPopoverOpen);
|
|
4874
4441
|
const readOnly = useReadOnly(controller);
|
|
4875
4442
|
useLinkClicks(controller);
|
|
4876
|
-
|
|
4443
|
+
useEffect(() => {
|
|
4877
4444
|
if (readOnly && store.get().linkPopover.open) store.set({ linkPopover: { open: false } });
|
|
4878
4445
|
}, [readOnly, store]);
|
|
4879
4446
|
if (readOnly) return null;
|
|
4880
|
-
if (!popoverOpen) return /* @__PURE__ */
|
|
4881
|
-
return /* @__PURE__ */
|
|
4447
|
+
if (!popoverOpen) return /* @__PURE__ */ jsx(LinkHoverCard, { controller, labels, store });
|
|
4448
|
+
return /* @__PURE__ */ jsx(LinkPopover, { controller, labels, onClose: () => store.set({ linkPopover: { open: false } }) });
|
|
4882
4449
|
}
|
|
4883
4450
|
function linkExtension(store) {
|
|
4884
4451
|
const openPopover = (state, dispatch) => {
|
|
@@ -4889,9 +4456,6 @@ function linkExtension(store) {
|
|
|
4889
4456
|
return defineExtension({ name: "link", keymap: { "Mod-k": openPopover }, ui: { overlays: [LinkOverlay] } });
|
|
4890
4457
|
}
|
|
4891
4458
|
|
|
4892
|
-
// src/menus/slash/slash-extension.tsx
|
|
4893
|
-
import { createContext as createContext6, useContext as useContext6, useMemo as useMemo13 } from "react";
|
|
4894
|
-
|
|
4895
4459
|
// src/menus/suggestion/find-trigger.ts
|
|
4896
4460
|
var DEFAULT_MAX_LENGTH = 40;
|
|
4897
4461
|
var NO_TRIGGER_TYPES = /* @__PURE__ */ new Set(["CODE", "TABLE"]);
|
|
@@ -4977,9 +4541,6 @@ function dismissSuggestion(key) {
|
|
|
4977
4541
|
|
|
4978
4542
|
// src/menus/slash/slash-key.ts
|
|
4979
4543
|
var slashKey = createPluginKey("slash");
|
|
4980
|
-
|
|
4981
|
-
// src/menus/slash/slash-items.ts
|
|
4982
|
-
import { Image as Image3, Minus, Paperclip as Paperclip2 } from "lucide-react";
|
|
4983
4544
|
var DETAILS = {
|
|
4984
4545
|
text: { group: "basic", keywords: ["paragraph", "plain"], shortcut: "Mod-Alt-0" },
|
|
4985
4546
|
heading1: { group: "basic", keywords: ["h1", "title", "#"], shortcut: "Mod-Alt-1" },
|
|
@@ -5012,8 +4573,8 @@ function builtInSlashItems(labels, definitions) {
|
|
|
5012
4573
|
const { blockNames } = labels;
|
|
5013
4574
|
const insertions = {
|
|
5014
4575
|
divider: { label: blockNames.divider, icon: Minus, type: "DIVIDER", attrs: {} },
|
|
5015
|
-
image: { label: blockNames.image, icon:
|
|
5016
|
-
file: { label: blockNames.file, icon:
|
|
4576
|
+
image: { label: blockNames.image, icon: Image, type: "IMAGE", attrs: {} },
|
|
4577
|
+
file: { label: blockNames.file, icon: Paperclip, type: "FILE", attrs: {} }
|
|
5017
4578
|
};
|
|
5018
4579
|
for (const target of turnIntoTargets(labels)) insertions[target.id] = target;
|
|
5019
4580
|
return Object.keys(DETAILS).flatMap((id) => {
|
|
@@ -5022,31 +4583,28 @@ function builtInSlashItems(labels, definitions) {
|
|
|
5022
4583
|
return [insertionItem(id, insertion, labels, definitions)];
|
|
5023
4584
|
});
|
|
5024
4585
|
}
|
|
5025
|
-
function initialBlock({ schema },
|
|
5026
|
-
const
|
|
4586
|
+
function initialBlock({ schema }, definition, onError) {
|
|
4587
|
+
const { type } = definition;
|
|
4588
|
+
const data = seedData(definition, onError());
|
|
4589
|
+
if (data === null) return null;
|
|
5027
4590
|
if (data === void 0) return { type };
|
|
5028
4591
|
return { type, ...specFor(schema, type).fromData(data, createBlockCodec(schema).context) };
|
|
5029
4592
|
}
|
|
5030
|
-
|
|
4593
|
+
var refuse = () => false;
|
|
4594
|
+
function blockTypeSlashItems(definitions, onError = () => void 0) {
|
|
5031
4595
|
return paletteBlocks(definitions).filter((definition) => !BUILT_IN_TYPES.has(definition.type)).map((definition) => ({
|
|
5032
4596
|
id: `block:${definition.type}`,
|
|
5033
4597
|
title: definition.label,
|
|
5034
4598
|
group: "custom",
|
|
5035
4599
|
icon: definition.icon,
|
|
5036
|
-
command: ({ state }) =>
|
|
4600
|
+
command: ({ state }) => {
|
|
4601
|
+
const block = initialBlock(state, definition, onError);
|
|
4602
|
+
return block === null ? refuse : insertBlockToWrite(block, opensEditor(definitions, definition.type));
|
|
4603
|
+
}
|
|
5037
4604
|
}));
|
|
5038
4605
|
}
|
|
5039
|
-
|
|
5040
|
-
// src/menus/slash/SlashMenu.tsx
|
|
5041
|
-
import { useCallback as useCallback10 } from "react";
|
|
5042
|
-
|
|
5043
|
-
// src/menus/suggestion/SuggestionMenu.tsx
|
|
5044
|
-
import { useRef as useRef28 } from "react";
|
|
5045
|
-
|
|
5046
|
-
// src/menus/floating/use-range-anchor.ts
|
|
5047
|
-
import { useMemo as useMemo10, useRef as useRef24, useState as useState16 } from "react";
|
|
5048
4606
|
function useRangeAnchor(controller, range) {
|
|
5049
|
-
const anchor =
|
|
4607
|
+
const anchor = useMemo(
|
|
5050
4608
|
() => ({
|
|
5051
4609
|
current: range && virtualAnchor(
|
|
5052
4610
|
() => rangeRect(controller, range),
|
|
@@ -5055,8 +4613,8 @@ function useRangeAnchor(controller, range) {
|
|
|
5055
4613
|
}),
|
|
5056
4614
|
[controller, range]
|
|
5057
4615
|
);
|
|
5058
|
-
const [side, setSide] =
|
|
5059
|
-
const latest =
|
|
4616
|
+
const [side, setSide] = useState("bottom");
|
|
4617
|
+
const latest = useRef(range);
|
|
5060
4618
|
const start = range === null ? null : `${range.block} ${range.region} ${range.from}`;
|
|
5061
4619
|
useIsomorphicLayoutEffect(() => {
|
|
5062
4620
|
latest.current = range;
|
|
@@ -5067,12 +4625,6 @@ function useRangeAnchor(controller, range) {
|
|
|
5067
4625
|
}, [controller, start]);
|
|
5068
4626
|
return { anchor, side };
|
|
5069
4627
|
}
|
|
5070
|
-
|
|
5071
|
-
// src/menus/suggestion/use-suggestion.ts
|
|
5072
|
-
import { useCallback as useCallback9, useEffect as useEffect20, useId as useId6, useMemo as useMemo12, useState as useState18 } from "react";
|
|
5073
|
-
|
|
5074
|
-
// src/menus/suggestion/combobox-attributes.ts
|
|
5075
|
-
import { useRef as useRef25 } from "react";
|
|
5076
4628
|
var ADDED = ["aria-expanded", "aria-controls", "aria-autocomplete", "aria-activedescendant"];
|
|
5077
4629
|
var SWAPPED = ["role", "aria-multiline"];
|
|
5078
4630
|
function restore(host, name, value) {
|
|
@@ -5092,7 +4644,7 @@ function openCombobox(host, listboxId) {
|
|
|
5092
4644
|
};
|
|
5093
4645
|
}
|
|
5094
4646
|
function useComboboxHost(controller, block, region, listboxId, activeOptionId) {
|
|
5095
|
-
const host =
|
|
4647
|
+
const host = useRef(null);
|
|
5096
4648
|
useIsomorphicLayoutEffect(() => {
|
|
5097
4649
|
host.current = block === null || region === null ? null : controller.registry.get(block, region) ?? null;
|
|
5098
4650
|
return host.current === null ? void 0 : openCombobox(host.current, listboxId);
|
|
@@ -5120,9 +4672,6 @@ function groupItems(items, groupOf2) {
|
|
|
5120
4672
|
for (const entry of sections.flatMap((section) => section.entries)) entry.index = index++;
|
|
5121
4673
|
return sections;
|
|
5122
4674
|
}
|
|
5123
|
-
|
|
5124
|
-
// src/menus/suggestion/use-suggestion-keys.ts
|
|
5125
|
-
import { useRef as useRef26 } from "react";
|
|
5126
4675
|
var MOVES2 = {
|
|
5127
4676
|
ArrowDown: (index, count) => (index + 1) % count,
|
|
5128
4677
|
ArrowUp: (index, count) => (index - 1 + count) % count,
|
|
@@ -5145,7 +4694,7 @@ function handle(event, menu) {
|
|
|
5145
4694
|
return true;
|
|
5146
4695
|
}
|
|
5147
4696
|
function useSuggestionKeys(controller, open, menu) {
|
|
5148
|
-
const latest =
|
|
4697
|
+
const latest = useRef(menu);
|
|
5149
4698
|
useIsomorphicLayoutEffect(() => {
|
|
5150
4699
|
latest.current = menu;
|
|
5151
4700
|
});
|
|
@@ -5160,9 +4709,6 @@ function useSuggestionKeys(controller, open, menu) {
|
|
|
5160
4709
|
}, [controller, open]);
|
|
5161
4710
|
}
|
|
5162
4711
|
|
|
5163
|
-
// src/menus/suggestion/use-suggestion-results.ts
|
|
5164
|
-
import { useMemo as useMemo11, useRef as useRef27, useState as useState17 } from "react";
|
|
5165
|
-
|
|
5166
4712
|
// src/to-error.ts
|
|
5167
4713
|
var toError = (cause) => cause instanceof Error ? cause : new Error(String(cause));
|
|
5168
4714
|
|
|
@@ -5171,8 +4717,8 @@ var FORGOTTEN = { source: null, query: null, items: [] };
|
|
|
5171
4717
|
var CLOSED = { items: [], pending: false };
|
|
5172
4718
|
var isPromise = (value) => typeof value?.then === "function";
|
|
5173
4719
|
function useSuggestionResults(source, query, onError) {
|
|
5174
|
-
const [answer, setAnswer] =
|
|
5175
|
-
const report =
|
|
4720
|
+
const [answer, setAnswer] = useState(FORGOTTEN);
|
|
4721
|
+
const report = useRef(onError);
|
|
5176
4722
|
useIsomorphicLayoutEffect(() => {
|
|
5177
4723
|
report.current = onError;
|
|
5178
4724
|
});
|
|
@@ -5201,7 +4747,7 @@ function useSuggestionResults(source, query, onError) {
|
|
|
5201
4747
|
current = false;
|
|
5202
4748
|
};
|
|
5203
4749
|
}, [source, query]);
|
|
5204
|
-
return
|
|
4750
|
+
return useMemo(
|
|
5205
4751
|
() => query === null ? CLOSED : { items: answer.items, pending: answer.source !== source || answer.query !== query },
|
|
5206
4752
|
[source, query, answer]
|
|
5207
4753
|
);
|
|
@@ -5221,20 +4767,20 @@ function useSuggestion({
|
|
|
5221
4767
|
}) {
|
|
5222
4768
|
const { labels, onError } = useQuoin();
|
|
5223
4769
|
const readOnly = useReadOnly(controller);
|
|
5224
|
-
const selectTrigger =
|
|
4770
|
+
const selectTrigger = useCallback((state) => getPluginState(state, pluginKey).active, [pluginKey]);
|
|
5225
4771
|
const active = useEditorState(controller, selectTrigger);
|
|
5226
4772
|
const trigger = readOnly ? null : active;
|
|
5227
4773
|
const results = useSuggestionResults(source, trigger?.query ?? null, onError);
|
|
5228
|
-
const sections =
|
|
5229
|
-
const ordered =
|
|
5230
|
-
const [highlighted, setHighlighted] =
|
|
4774
|
+
const sections = useMemo(() => groupItems(results.items, groupOf2), [results.items, groupOf2]);
|
|
4775
|
+
const ordered = useMemo(() => sections.flatMap((section) => section.entries.map(({ item }) => item)), [sections]);
|
|
4776
|
+
const [highlighted, setHighlighted] = useState(null);
|
|
5231
4777
|
const kept = highlighted?.trigger === trigger ? ordered.findIndex((item) => itemKey2(item) === highlighted.key) : -1;
|
|
5232
4778
|
const activeIndex = Math.max(0, kept);
|
|
5233
|
-
const baseId =
|
|
4779
|
+
const baseId = useId();
|
|
5234
4780
|
const listboxId = `${baseId}-listbox`;
|
|
5235
|
-
const optionId =
|
|
4781
|
+
const optionId = useCallback((item) => `${baseId}-option-${idPart(itemKey2(item))}`, [baseId, itemKey2]);
|
|
5236
4782
|
const activeId = activeIndex < ordered.length ? optionId(ordered[activeIndex]) : null;
|
|
5237
|
-
const highlight =
|
|
4783
|
+
const highlight = useCallback(
|
|
5238
4784
|
(index) => {
|
|
5239
4785
|
if (trigger === null || index >= ordered.length) return;
|
|
5240
4786
|
const key = itemKey2(ordered[index]);
|
|
@@ -5242,29 +4788,26 @@ function useSuggestion({
|
|
|
5242
4788
|
},
|
|
5243
4789
|
[trigger, ordered, itemKey2]
|
|
5244
4790
|
);
|
|
5245
|
-
const select =
|
|
4791
|
+
const select = useCallback(
|
|
5246
4792
|
(index) => {
|
|
5247
4793
|
const current = getPluginState(controller.editor.state, pluginKey).active;
|
|
5248
4794
|
if (current !== null && index < ordered.length) onSelect(ordered[index], rangeOf2(current));
|
|
5249
4795
|
},
|
|
5250
4796
|
[controller, pluginKey, ordered, onSelect]
|
|
5251
4797
|
);
|
|
5252
|
-
const dismiss =
|
|
4798
|
+
const dismiss = useCallback(() => void controller.run(dismissSuggestion(pluginKey)), [controller, pluginKey]);
|
|
5253
4799
|
useSuggestionKeys(controller, trigger !== null, { count: ordered.length, activeIndex, highlight, select, dismiss });
|
|
5254
4800
|
useComboboxHost(controller, trigger?.block ?? null, trigger?.region ?? null, listboxId, activeId);
|
|
5255
4801
|
const query = trigger?.query ?? null;
|
|
5256
4802
|
const count = ordered.length;
|
|
5257
4803
|
const resultMessage = count === 0 ? emptyLabel : labels.resultCount(count);
|
|
5258
|
-
|
|
4804
|
+
useEffect(() => {
|
|
5259
4805
|
if (query === null || results.pending) return;
|
|
5260
4806
|
const timer = setTimeout(() => controller.announce(resultMessage), SETTLE_MS);
|
|
5261
4807
|
return () => clearTimeout(timer);
|
|
5262
4808
|
}, [controller, query, resultMessage, results.pending]);
|
|
5263
4809
|
return { trigger, sections, pending: results.pending, activeIndex, listboxId, optionId, highlight, select, dismiss };
|
|
5264
4810
|
}
|
|
5265
|
-
|
|
5266
|
-
// src/menus/suggestion/SuggestionMenu.tsx
|
|
5267
|
-
import { Fragment as Fragment10, jsx as jsx54, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
5268
4811
|
var CONTENT3 = cn(
|
|
5269
4812
|
MENU_CONTENT,
|
|
5270
4813
|
"flex w-72 max-h-[min(22rem,var(--radix-popper-available-height))] flex-col overflow-y-hidden"
|
|
@@ -5272,7 +4815,7 @@ var CONTENT3 = cn(
|
|
|
5272
4815
|
var LISTBOX = "min-h-0 overflow-y-auto";
|
|
5273
4816
|
var GROUP_LABEL = "px-2 pt-2 pb-1 text-xs font-medium text-muted-foreground";
|
|
5274
4817
|
function SuggestionGroup({ section, labelId, activeIndex, optionId, renderItem, highlight, select }) {
|
|
5275
|
-
const options = section.entries.map(({ item, index }) => /* @__PURE__ */
|
|
4818
|
+
const options = section.entries.map(({ item, index }) => /* @__PURE__ */ jsx(
|
|
5276
4819
|
SuggestionOption,
|
|
5277
4820
|
{
|
|
5278
4821
|
id: optionId(item),
|
|
@@ -5283,9 +4826,9 @@ function SuggestionGroup({ section, labelId, activeIndex, optionId, renderItem,
|
|
|
5283
4826
|
},
|
|
5284
4827
|
optionId(item)
|
|
5285
4828
|
));
|
|
5286
|
-
if (section.label === null) return /* @__PURE__ */
|
|
5287
|
-
return /* @__PURE__ */
|
|
5288
|
-
/* @__PURE__ */
|
|
4829
|
+
if (section.label === null) return /* @__PURE__ */ jsx(Fragment, { children: options });
|
|
4830
|
+
return /* @__PURE__ */ jsxs("div", { role: "group", "aria-labelledby": labelId, children: [
|
|
4831
|
+
/* @__PURE__ */ jsx("div", { role: "presentation", id: labelId, className: GROUP_LABEL, children: section.label }),
|
|
5289
4832
|
options
|
|
5290
4833
|
] });
|
|
5291
4834
|
}
|
|
@@ -5294,7 +4837,7 @@ function SuggestionMenu(props) {
|
|
|
5294
4837
|
const suggestion = useSuggestion(props);
|
|
5295
4838
|
const { trigger, sections, activeIndex, listboxId } = suggestion;
|
|
5296
4839
|
const { anchor, side } = useRangeAnchor(controller, trigger);
|
|
5297
|
-
const listbox =
|
|
4840
|
+
const listbox = useRef(null);
|
|
5298
4841
|
useIsomorphicLayoutEffect(() => {
|
|
5299
4842
|
listbox.current?.querySelector('[aria-selected="true"]')?.scrollIntoView({ block: "nearest" });
|
|
5300
4843
|
}, [activeIndex, sections]);
|
|
@@ -5306,7 +4849,7 @@ function SuggestionMenu(props) {
|
|
|
5306
4849
|
if (inEditor(event.target) && focusStays) event.preventDefault();
|
|
5307
4850
|
};
|
|
5308
4851
|
const status = suggestion.pending ? pendingLabel : sections.length === 0 ? emptyLabel : void 0;
|
|
5309
|
-
return /* @__PURE__ */
|
|
4852
|
+
return /* @__PURE__ */ jsxs(
|
|
5310
4853
|
Popover,
|
|
5311
4854
|
{
|
|
5312
4855
|
open: true,
|
|
@@ -5315,8 +4858,8 @@ function SuggestionMenu(props) {
|
|
|
5315
4858
|
if (!open) queueMicrotask(suggestion.dismiss);
|
|
5316
4859
|
},
|
|
5317
4860
|
children: [
|
|
5318
|
-
/* @__PURE__ */
|
|
5319
|
-
/* @__PURE__ */
|
|
4861
|
+
/* @__PURE__ */ jsx(PopoverAnchor, { virtualRef: anchor }),
|
|
4862
|
+
/* @__PURE__ */ jsxs(
|
|
5320
4863
|
PopoverContent,
|
|
5321
4864
|
{
|
|
5322
4865
|
role: void 0,
|
|
@@ -5329,7 +4872,7 @@ function SuggestionMenu(props) {
|
|
|
5329
4872
|
onPointerDownOutside: insideEditor,
|
|
5330
4873
|
onFocusOutside: insideEditor,
|
|
5331
4874
|
children: [
|
|
5332
|
-
/* @__PURE__ */
|
|
4875
|
+
/* @__PURE__ */ jsx("div", { ref: listbox, role: "listbox", id: listboxId, "aria-label": label, className: LISTBOX, children: sections.map((section, index) => /* @__PURE__ */ jsx(
|
|
5333
4876
|
SuggestionGroup,
|
|
5334
4877
|
{
|
|
5335
4878
|
section,
|
|
@@ -5342,7 +4885,7 @@ function SuggestionMenu(props) {
|
|
|
5342
4885
|
},
|
|
5343
4886
|
section.label ?? ""
|
|
5344
4887
|
)) }),
|
|
5345
|
-
status && /* @__PURE__ */
|
|
4888
|
+
status && /* @__PURE__ */ jsx("p", { className: "px-2 py-1.5 text-sm text-muted-foreground", children: status })
|
|
5346
4889
|
]
|
|
5347
4890
|
}
|
|
5348
4891
|
)
|
|
@@ -5420,23 +4963,20 @@ function fuzzyFilter(items, query) {
|
|
|
5420
4963
|
if (wanted === "") return [...items];
|
|
5421
4964
|
return items.map((item, index) => ({ item, index, score: score(item, wanted) })).filter((entry) => entry.score > 0).sort((a, b) => b.score - a.score || a.index - b.index).map((entry) => entry.item);
|
|
5422
4965
|
}
|
|
5423
|
-
|
|
5424
|
-
// src/menus/slash/SlashMenu.tsx
|
|
5425
|
-
import { Fragment as Fragment11, jsx as jsx55, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
5426
4966
|
var itemKey = (item) => item.id;
|
|
5427
4967
|
function SlashRow({ item, isMac, labels }) {
|
|
5428
4968
|
const hint = item.shortcut === void 0 ? null : shortcutHint(item.shortcut, isMac, labels);
|
|
5429
|
-
return /* @__PURE__ */
|
|
5430
|
-
item.icon !== void 0 && /* @__PURE__ */
|
|
5431
|
-
/* @__PURE__ */
|
|
5432
|
-
/* @__PURE__ */
|
|
5433
|
-
item.description !== void 0 && /* @__PURE__ */
|
|
4969
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4970
|
+
item.icon !== void 0 && /* @__PURE__ */ jsx(MenuIcon, { icon: item.icon }),
|
|
4971
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col", children: [
|
|
4972
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: item.title }),
|
|
4973
|
+
item.description !== void 0 && /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-muted-foreground", children: item.description })
|
|
5434
4974
|
] }),
|
|
5435
|
-
hint !== null && /* @__PURE__ */
|
|
4975
|
+
hint !== null && /* @__PURE__ */ jsx("kbd", { "aria-hidden": "true", className: "ml-auto font-sans text-xs tracking-widest text-muted-foreground pointer-coarse:hidden", children: hint.text })
|
|
5436
4976
|
] });
|
|
5437
4977
|
}
|
|
5438
4978
|
function SlashMenu({ controller, labels, items }) {
|
|
5439
|
-
const search =
|
|
4979
|
+
const search = useCallback(
|
|
5440
4980
|
(query) => {
|
|
5441
4981
|
const { state } = controller.editor;
|
|
5442
4982
|
return fuzzyFilter(
|
|
@@ -5446,16 +4986,16 @@ function SlashMenu({ controller, labels, items }) {
|
|
|
5446
4986
|
},
|
|
5447
4987
|
[controller, items]
|
|
5448
4988
|
);
|
|
5449
|
-
const groupOf2 =
|
|
5450
|
-
const renderItem =
|
|
5451
|
-
(item) => /* @__PURE__ */
|
|
4989
|
+
const groupOf2 = useCallback((item) => labels.groups[item.group], [labels]);
|
|
4990
|
+
const renderItem = useCallback(
|
|
4991
|
+
(item) => /* @__PURE__ */ jsx(SlashRow, { item, isMac: controller.isMac, labels }),
|
|
5452
4992
|
[controller, labels]
|
|
5453
4993
|
);
|
|
5454
|
-
const choose =
|
|
4994
|
+
const choose = useCallback(
|
|
5455
4995
|
(item, range) => chooseSlashItem(controller, item, range),
|
|
5456
4996
|
[controller]
|
|
5457
4997
|
);
|
|
5458
|
-
return /* @__PURE__ */
|
|
4998
|
+
return /* @__PURE__ */ jsx(
|
|
5459
4999
|
SuggestionMenu,
|
|
5460
5000
|
{
|
|
5461
5001
|
controller,
|
|
@@ -5470,21 +5010,18 @@ function SlashMenu({ controller, labels, items }) {
|
|
|
5470
5010
|
}
|
|
5471
5011
|
);
|
|
5472
5012
|
}
|
|
5473
|
-
|
|
5474
|
-
// src/menus/slash/slash-extension.tsx
|
|
5475
|
-
import { jsx as jsx56 } from "react/jsx-runtime";
|
|
5476
5013
|
var NO_ITEMS2 = [];
|
|
5477
|
-
var SlashItemsContext =
|
|
5014
|
+
var SlashItemsContext = createContext(NO_ITEMS2);
|
|
5478
5015
|
var SlashItemsProvider = SlashItemsContext.Provider;
|
|
5479
5016
|
function SlashOverlay({ controller }) {
|
|
5480
5017
|
const labels = useLabels();
|
|
5481
5018
|
const { blockTypes } = useQuoin();
|
|
5482
|
-
const extraItems =
|
|
5483
|
-
const items =
|
|
5019
|
+
const extraItems = useContext(SlashItemsContext);
|
|
5020
|
+
const items = useMemo(
|
|
5484
5021
|
() => [...builtInSlashItems(labels, blockTypes), ...extraItems],
|
|
5485
5022
|
[labels, blockTypes, extraItems]
|
|
5486
5023
|
);
|
|
5487
|
-
return /* @__PURE__ */
|
|
5024
|
+
return /* @__PURE__ */ jsx(SlashMenu, { controller, labels, items });
|
|
5488
5025
|
}
|
|
5489
5026
|
function slashExtension() {
|
|
5490
5027
|
return defineExtension({
|
|
@@ -5493,23 +5030,6 @@ function slashExtension() {
|
|
|
5493
5030
|
ui: { overlays: [SlashOverlay] }
|
|
5494
5031
|
});
|
|
5495
5032
|
}
|
|
5496
|
-
|
|
5497
|
-
// src/mobile/MobileToolbar.tsx
|
|
5498
|
-
import { useMemo as useMemo14 } from "react";
|
|
5499
|
-
import { createPortal } from "react-dom";
|
|
5500
|
-
|
|
5501
|
-
// src/mobile/mobile-items.tsx
|
|
5502
|
-
import {
|
|
5503
|
-
Bold as Bold2,
|
|
5504
|
-
Code as Code4,
|
|
5505
|
-
Italic as Italic2,
|
|
5506
|
-
ListIndentDecrease,
|
|
5507
|
-
ListIndentIncrease,
|
|
5508
|
-
Plus as Plus2,
|
|
5509
|
-
Redo2,
|
|
5510
|
-
Strikethrough as Strikethrough2,
|
|
5511
|
-
Undo2
|
|
5512
|
-
} from "lucide-react";
|
|
5513
5033
|
function commandItem(id, title, icon, command) {
|
|
5514
5034
|
return { id, title, icon, run: (controller) => void controller.run(command) };
|
|
5515
5035
|
}
|
|
@@ -5519,12 +5039,12 @@ function addBlockAtCaret(controller) {
|
|
|
5519
5039
|
}
|
|
5520
5040
|
function mobileItems(labels, openLink) {
|
|
5521
5041
|
return {
|
|
5522
|
-
addBlock: { id: "add-block", title: labels.addBelow, icon:
|
|
5042
|
+
addBlock: { id: "add-block", title: labels.addBelow, icon: Plus, run: addBlockAtCaret },
|
|
5523
5043
|
editing: [
|
|
5524
|
-
markItem("bold", labels.bold,
|
|
5525
|
-
markItem("italic", labels.italic,
|
|
5526
|
-
markItem("strike", labels.strike,
|
|
5527
|
-
markItem("code", labels.code,
|
|
5044
|
+
markItem("bold", labels.bold, Bold),
|
|
5045
|
+
markItem("italic", labels.italic, Italic),
|
|
5046
|
+
markItem("strike", labels.strike, Strikethrough),
|
|
5047
|
+
markItem("code", labels.code, Code),
|
|
5528
5048
|
linkItem(labels, openLink),
|
|
5529
5049
|
commandItem("indent", labels.indent, ListIndentIncrease, indent),
|
|
5530
5050
|
commandItem("outdent", labels.outdent, ListIndentDecrease, outdent),
|
|
@@ -5536,9 +5056,6 @@ function mobileItems(labels, openLink) {
|
|
|
5536
5056
|
|
|
5537
5057
|
// src/mobile/use-coarse-pointer.ts
|
|
5538
5058
|
var useCoarsePointer = () => useMediaQuery("(pointer: coarse)", false);
|
|
5539
|
-
|
|
5540
|
-
// src/mobile/use-editor-focus.ts
|
|
5541
|
-
import { useCallback as useCallback11, useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
5542
5059
|
var FOCUS_EVENTS = ["focusin", "focusout"];
|
|
5543
5060
|
function subscribe(notify) {
|
|
5544
5061
|
for (const type of FOCUS_EVENTS) document.addEventListener(type, notify);
|
|
@@ -5548,12 +5065,9 @@ function subscribe(notify) {
|
|
|
5548
5065
|
}
|
|
5549
5066
|
var NOT_FOCUSED = () => false;
|
|
5550
5067
|
function useEditorFocus(controller) {
|
|
5551
|
-
const read2 =
|
|
5552
|
-
return
|
|
5068
|
+
const read2 = useCallback(() => focusInEditor(controller), [controller]);
|
|
5069
|
+
return useSyncExternalStore(subscribe, read2, NOT_FOCUSED);
|
|
5553
5070
|
}
|
|
5554
|
-
|
|
5555
|
-
// src/mobile/use-visual-viewport.ts
|
|
5556
|
-
import { useSyncExternalStore as useSyncExternalStore5 } from "react";
|
|
5557
5071
|
var EVENTS = ["resize", "scroll"];
|
|
5558
5072
|
function subscribe2(notify) {
|
|
5559
5073
|
const viewport = window.visualViewport;
|
|
@@ -5576,11 +5090,8 @@ function read() {
|
|
|
5576
5090
|
}
|
|
5577
5091
|
var readOnServer2 = () => null;
|
|
5578
5092
|
function useVisualViewport() {
|
|
5579
|
-
return
|
|
5093
|
+
return useSyncExternalStore(subscribe2, read, readOnServer2);
|
|
5580
5094
|
}
|
|
5581
|
-
|
|
5582
|
-
// src/mobile/MobileToolbar.tsx
|
|
5583
|
-
import { jsx as jsx57, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
5584
5095
|
var TOOLBAR = [
|
|
5585
5096
|
"quoin bg-popover text-popover-foreground fixed inset-x-0 z-40 flex items-center gap-0.5 overflow-x-auto",
|
|
5586
5097
|
"border-t p-1 shadow-md"
|
|
@@ -5595,16 +5106,16 @@ function EditingTools({ controller }) {
|
|
|
5595
5106
|
const state = useEditorState(controller, wholeState);
|
|
5596
5107
|
const viewport = useVisualViewport();
|
|
5597
5108
|
const roving = useRovingFocus();
|
|
5598
|
-
const items =
|
|
5109
|
+
const items = useMemo(() => mobileItems(labels, () => store.set({ linkPopover: { open: true } })), [labels, store]);
|
|
5599
5110
|
const onKeyDown = (event) => {
|
|
5600
5111
|
if (event.key === "Escape" && roving.owns(event.target)) {
|
|
5601
5112
|
event.preventDefault();
|
|
5602
5113
|
controller.focus();
|
|
5603
5114
|
} else roving.onKeyDown(event);
|
|
5604
5115
|
};
|
|
5605
|
-
const button = (item) => /* @__PURE__ */
|
|
5116
|
+
const button = (item) => /* @__PURE__ */ jsx(ToolbarButton, { item, state, controller }, item.id);
|
|
5606
5117
|
return createPortal(
|
|
5607
|
-
/* @__PURE__ */
|
|
5118
|
+
/* @__PURE__ */ jsxs(
|
|
5608
5119
|
"div",
|
|
5609
5120
|
{
|
|
5610
5121
|
ref: roving.ref,
|
|
@@ -5619,7 +5130,7 @@ function EditingTools({ controller }) {
|
|
|
5619
5130
|
...bubblePart(controller),
|
|
5620
5131
|
children: [
|
|
5621
5132
|
button(items.addBlock),
|
|
5622
|
-
/* @__PURE__ */
|
|
5133
|
+
/* @__PURE__ */ jsx(TurnIntoDropdown, { controller, state }),
|
|
5623
5134
|
items.editing.map(button)
|
|
5624
5135
|
]
|
|
5625
5136
|
}
|
|
@@ -5631,28 +5142,16 @@ function MobileToolbar({ controller }) {
|
|
|
5631
5142
|
const coarse = useCoarsePointer();
|
|
5632
5143
|
const focused = useEditorFocus(controller);
|
|
5633
5144
|
if (!coarse || !focused) return null;
|
|
5634
|
-
return /* @__PURE__ */
|
|
5145
|
+
return /* @__PURE__ */ jsx(EditingTools, { controller });
|
|
5635
5146
|
}
|
|
5636
|
-
|
|
5637
|
-
// src/shortcuts/shortcuts-extension.tsx
|
|
5638
|
-
import { Keyboard } from "lucide-react";
|
|
5639
|
-
|
|
5640
|
-
// src/shortcuts/ShortcutsDialog.tsx
|
|
5641
|
-
import { useId as useId7, useMemo as useMemo15 } from "react";
|
|
5642
|
-
|
|
5643
|
-
// src/ui/dialog.tsx
|
|
5644
|
-
import * as React8 from "react";
|
|
5645
|
-
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
5646
|
-
import { XIcon } from "lucide-react";
|
|
5647
|
-
import { jsx as jsx58, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
5648
5147
|
function Dialog(props) {
|
|
5649
|
-
return /* @__PURE__ */
|
|
5148
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Root, { ...props });
|
|
5650
5149
|
}
|
|
5651
5150
|
function DialogPortal(props) {
|
|
5652
|
-
return /* @__PURE__ */
|
|
5151
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Portal, { ...props });
|
|
5653
5152
|
}
|
|
5654
|
-
var DialogOverlay = /* @__PURE__ */
|
|
5655
|
-
return /* @__PURE__ */
|
|
5153
|
+
var DialogOverlay = /* @__PURE__ */ React7.forwardRef(function DialogOverlay2({ className, ...props }, ref) {
|
|
5154
|
+
return /* @__PURE__ */ jsx(
|
|
5656
5155
|
DialogPrimitive.Overlay,
|
|
5657
5156
|
{
|
|
5658
5157
|
ref,
|
|
@@ -5665,10 +5164,10 @@ var DialogOverlay = /* @__PURE__ */ React8.forwardRef(function DialogOverlay2({
|
|
|
5665
5164
|
}
|
|
5666
5165
|
);
|
|
5667
5166
|
});
|
|
5668
|
-
var DialogContent = /* @__PURE__ */
|
|
5669
|
-
return /* @__PURE__ */
|
|
5670
|
-
/* @__PURE__ */
|
|
5671
|
-
/* @__PURE__ */
|
|
5167
|
+
var DialogContent = /* @__PURE__ */ React7.forwardRef(function DialogContent2({ className, children, closeLabel = "Close", ...props }, ref) {
|
|
5168
|
+
return /* @__PURE__ */ jsxs(DialogPortal, { children: [
|
|
5169
|
+
/* @__PURE__ */ jsx(DialogOverlay, {}),
|
|
5170
|
+
/* @__PURE__ */ jsxs(
|
|
5672
5171
|
DialogPrimitive.Content,
|
|
5673
5172
|
{
|
|
5674
5173
|
ref,
|
|
@@ -5680,7 +5179,7 @@ var DialogContent = /* @__PURE__ */ React8.forwardRef(function DialogContent2({
|
|
|
5680
5179
|
...props,
|
|
5681
5180
|
children: [
|
|
5682
5181
|
children,
|
|
5683
|
-
/* @__PURE__ */
|
|
5182
|
+
/* @__PURE__ */ jsxs(
|
|
5684
5183
|
DialogPrimitive.Close,
|
|
5685
5184
|
{
|
|
5686
5185
|
className: cn(
|
|
@@ -5689,8 +5188,8 @@ var DialogContent = /* @__PURE__ */ React8.forwardRef(function DialogContent2({
|
|
|
5689
5188
|
ICON_TAP_TARGET_FLOOR
|
|
5690
5189
|
),
|
|
5691
5190
|
children: [
|
|
5692
|
-
/* @__PURE__ */
|
|
5693
|
-
/* @__PURE__ */
|
|
5191
|
+
/* @__PURE__ */ jsx(XIcon, {}),
|
|
5192
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: closeLabel })
|
|
5694
5193
|
]
|
|
5695
5194
|
}
|
|
5696
5195
|
)
|
|
@@ -5699,8 +5198,8 @@ var DialogContent = /* @__PURE__ */ React8.forwardRef(function DialogContent2({
|
|
|
5699
5198
|
)
|
|
5700
5199
|
] });
|
|
5701
5200
|
});
|
|
5702
|
-
var DialogHeader = /* @__PURE__ */
|
|
5703
|
-
return /* @__PURE__ */
|
|
5201
|
+
var DialogHeader = /* @__PURE__ */ React7.forwardRef(function DialogHeader2({ className, ...props }, ref) {
|
|
5202
|
+
return /* @__PURE__ */ jsx(
|
|
5704
5203
|
"div",
|
|
5705
5204
|
{
|
|
5706
5205
|
ref,
|
|
@@ -5710,8 +5209,8 @@ var DialogHeader = /* @__PURE__ */ React8.forwardRef(function DialogHeader2({ cl
|
|
|
5710
5209
|
}
|
|
5711
5210
|
);
|
|
5712
5211
|
});
|
|
5713
|
-
var DialogTitle = /* @__PURE__ */
|
|
5714
|
-
return /* @__PURE__ */
|
|
5212
|
+
var DialogTitle = /* @__PURE__ */ React7.forwardRef(function DialogTitle2({ className, ...props }, ref) {
|
|
5213
|
+
return /* @__PURE__ */ jsx(
|
|
5715
5214
|
DialogPrimitive.Title,
|
|
5716
5215
|
{
|
|
5717
5216
|
ref,
|
|
@@ -5801,23 +5300,20 @@ function shortcutGroups(labels, isMac) {
|
|
|
5801
5300
|
}
|
|
5802
5301
|
];
|
|
5803
5302
|
}
|
|
5804
|
-
|
|
5805
|
-
// src/shortcuts/ShortcutsDialog.tsx
|
|
5806
|
-
import { jsx as jsx59, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
5807
5303
|
var KEYS3 = "rounded border bg-muted px-1.5 py-0.5 font-sans text-xs whitespace-nowrap";
|
|
5808
5304
|
function ShortcutSection({ group }) {
|
|
5809
|
-
const titleId =
|
|
5810
|
-
return /* @__PURE__ */
|
|
5811
|
-
/* @__PURE__ */
|
|
5812
|
-
/* @__PURE__ */
|
|
5813
|
-
/* @__PURE__ */
|
|
5814
|
-
/* @__PURE__ */
|
|
5305
|
+
const titleId = useId();
|
|
5306
|
+
return /* @__PURE__ */ jsxs("section", { "aria-labelledby": titleId, children: [
|
|
5307
|
+
/* @__PURE__ */ jsx("h3", { id: titleId, className: "mb-2 text-sm font-semibold", children: group.title }),
|
|
5308
|
+
/* @__PURE__ */ jsx("dl", { className: "grid gap-1.5 text-sm", children: group.items.map(({ label, keys }) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
|
|
5309
|
+
/* @__PURE__ */ jsx("dt", { children: label }),
|
|
5310
|
+
/* @__PURE__ */ jsx("dd", { children: /* @__PURE__ */ jsx("kbd", { className: KEYS3, children: keys }) })
|
|
5815
5311
|
] }, `${label} ${keys}`)) })
|
|
5816
5312
|
] });
|
|
5817
5313
|
}
|
|
5818
5314
|
function ShortcutsDialog({ open, onOpenChange, labels, isMac, onCloseAutoFocus }) {
|
|
5819
|
-
const groups =
|
|
5820
|
-
return /* @__PURE__ */
|
|
5315
|
+
const groups = useMemo(() => shortcutGroups(labels, isMac), [labels, isMac]);
|
|
5316
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
|
|
5821
5317
|
DialogContent,
|
|
5822
5318
|
{
|
|
5823
5319
|
closeLabel: labels.close,
|
|
@@ -5825,22 +5321,19 @@ function ShortcutsDialog({ open, onOpenChange, labels, isMac, onCloseAutoFocus }
|
|
|
5825
5321
|
onCloseAutoFocus,
|
|
5826
5322
|
className: "max-h-[85vh] overflow-y-auto sm:max-w-2xl",
|
|
5827
5323
|
children: [
|
|
5828
|
-
/* @__PURE__ */
|
|
5829
|
-
/* @__PURE__ */
|
|
5324
|
+
/* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: labels.shortcuts }) }),
|
|
5325
|
+
/* @__PURE__ */ jsx("div", { className: "grid gap-6 sm:grid-cols-2", children: groups.map((group) => /* @__PURE__ */ jsx(ShortcutSection, { group }, group.name)) })
|
|
5830
5326
|
]
|
|
5831
5327
|
}
|
|
5832
5328
|
) });
|
|
5833
5329
|
}
|
|
5834
|
-
|
|
5835
|
-
// src/shortcuts/shortcuts-extension.tsx
|
|
5836
|
-
import { jsx as jsx60 } from "react/jsx-runtime";
|
|
5837
5330
|
var SHORTCUT = "Mod-Shift-/";
|
|
5838
5331
|
var isOpen = (state) => state.shortcutsOpen;
|
|
5839
5332
|
function ShortcutsOverlay({ controller }) {
|
|
5840
5333
|
const labels = useLabels();
|
|
5841
5334
|
const store = useCanvasUiStore();
|
|
5842
5335
|
const open = useCanvasUi(store, isOpen);
|
|
5843
|
-
return /* @__PURE__ */
|
|
5336
|
+
return /* @__PURE__ */ jsx(
|
|
5844
5337
|
ShortcutsDialog,
|
|
5845
5338
|
{
|
|
5846
5339
|
open,
|
|
@@ -5890,13 +5383,6 @@ function linkedBlockId(hash) {
|
|
|
5890
5383
|
}
|
|
5891
5384
|
}
|
|
5892
5385
|
|
|
5893
|
-
// src/blocks/void/void-renderers.ts
|
|
5894
|
-
import { createElement } from "react";
|
|
5895
|
-
|
|
5896
|
-
// src/blocks/void/VoidBlock.tsx
|
|
5897
|
-
import { useCallback as useCallback12, useEffect as useEffect22, useRef as useRef30 } from "react";
|
|
5898
|
-
import { Pencil as Pencil3 } from "lucide-react";
|
|
5899
|
-
|
|
5900
5386
|
// src/blocks/void/block-data.ts
|
|
5901
5387
|
var internal = (controller) => controller.editor;
|
|
5902
5388
|
function readBlockData(controller, block) {
|
|
@@ -5913,15 +5399,18 @@ function writeBlockData(controller, blockId, data) {
|
|
|
5913
5399
|
const tr = editor.createTransaction().step(replaceBlockStep({ ...block, attrs, regions }));
|
|
5914
5400
|
editor.dispatch(tr.setMeta(HISTORY_GROUP, `block-data:${blockId}`));
|
|
5915
5401
|
}
|
|
5916
|
-
function insertAfterBlock(controller, blockId, type, definitions) {
|
|
5402
|
+
function insertAfterBlock(controller, blockId, type, definitions, onError) {
|
|
5917
5403
|
const editor = internal(controller);
|
|
5918
|
-
const data = blockByType(definitions, type)
|
|
5404
|
+
const data = seedData(blockByType(definitions, type), onError);
|
|
5405
|
+
if (data === null) return false;
|
|
5919
5406
|
const content = data && specFor(editor.state.schema, type).fromData(data, editor.codec.context);
|
|
5920
5407
|
controller.run(insertBlockToWrite({ type, ...content }, opensEditor(definitions, type), blockId));
|
|
5408
|
+
return true;
|
|
5409
|
+
}
|
|
5410
|
+
function useBlockIndex(controller, blockId) {
|
|
5411
|
+
const select = useCallback((state) => state.doc.index.get(blockId) ?? -1, [blockId]);
|
|
5412
|
+
return useEditorState(controller, select);
|
|
5921
5413
|
}
|
|
5922
|
-
|
|
5923
|
-
// src/blocks/void/use-editing-focus.ts
|
|
5924
|
-
import { useEffect as useEffect21, useMemo as useMemo16, useRef as useRef29 } from "react";
|
|
5925
5414
|
var FOCUSABLE = [
|
|
5926
5415
|
"input:not([disabled])",
|
|
5927
5416
|
"textarea:not([disabled])",
|
|
@@ -5933,8 +5422,8 @@ var FOCUSABLE = [
|
|
|
5933
5422
|
].join(", ");
|
|
5934
5423
|
var CANVAS = ".quoin-editor";
|
|
5935
5424
|
function useEditingFocus(root, editing, stop) {
|
|
5936
|
-
const inside =
|
|
5937
|
-
|
|
5425
|
+
const inside = useRef(/* @__PURE__ */ new WeakSet());
|
|
5426
|
+
useEffect(() => {
|
|
5938
5427
|
const element = root.current;
|
|
5939
5428
|
if (!editing || element === null) return;
|
|
5940
5429
|
(element.querySelector(FOCUSABLE) ?? element).focus();
|
|
@@ -5954,16 +5443,13 @@ function useEditingFocus(root, editing, stop) {
|
|
|
5954
5443
|
unlisten();
|
|
5955
5444
|
};
|
|
5956
5445
|
}, [root, editing, stop]);
|
|
5957
|
-
return
|
|
5446
|
+
return useMemo(() => {
|
|
5958
5447
|
const mark = (event) => void inside.current.add(event.nativeEvent);
|
|
5959
5448
|
return { onPointerDownCapture: mark, onFocusCapture: mark };
|
|
5960
5449
|
}, []);
|
|
5961
5450
|
}
|
|
5962
|
-
|
|
5963
|
-
// src/blocks/void/VoidBlock.tsx
|
|
5964
|
-
import { jsx as jsx61, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
5965
5451
|
function useMissingPreviewWarning(readOnly, { type, preview }) {
|
|
5966
|
-
|
|
5452
|
+
useEffect(() => {
|
|
5967
5453
|
if (!readOnly || preview !== void 0) return;
|
|
5968
5454
|
devWarn(
|
|
5969
5455
|
`the block type "${type}" has no \`preview\`, so a read-only canvas can draw only its label. Give its definition a \`preview\` to render the block itself.`
|
|
@@ -5971,39 +5457,53 @@ function useMissingPreviewWarning(readOnly, { type, preview }) {
|
|
|
5971
5457
|
}, [readOnly, type, preview]);
|
|
5972
5458
|
}
|
|
5973
5459
|
function VoidPreview({ definition: { preview: Preview }, name, ...props }) {
|
|
5974
|
-
if (Preview === void 0) return /* @__PURE__ */
|
|
5975
|
-
return /* @__PURE__ */
|
|
5460
|
+
if (Preview === void 0) return /* @__PURE__ */ jsx("p", { className: "py-1 text-sm text-muted-foreground", children: name });
|
|
5461
|
+
return /* @__PURE__ */ jsx(Preview, { ...props });
|
|
5976
5462
|
}
|
|
5977
5463
|
function VoidBlock({ block, controller, definition }) {
|
|
5978
5464
|
const { blockTypes, labels } = useQuoin();
|
|
5465
|
+
const { report } = useContext(BlockErrorContext);
|
|
5979
5466
|
const readOnly = useReadOnly(controller);
|
|
5980
5467
|
const { editor: Editor, alwaysEditing = false } = definition;
|
|
5981
5468
|
const name = blockTypeLabel(labels, block, blockTypes);
|
|
5982
5469
|
const blockId = block.id;
|
|
5983
5470
|
const editable = Editor !== void 0 && !readOnly;
|
|
5984
5471
|
const { editing, start, stop } = useVoidEditing(controller, blockId, editable);
|
|
5985
|
-
const
|
|
5472
|
+
const index = useBlockIndex(controller, blockId);
|
|
5473
|
+
const root = useRef(null);
|
|
5986
5474
|
const focusHandlers = useEditingFocus(root, editing, stop);
|
|
5987
5475
|
useMissingPreviewWarning(readOnly, definition);
|
|
5988
|
-
const select =
|
|
5989
|
-
const leave =
|
|
5476
|
+
const select = useCallback(() => focusNode(controller, blockId), [controller, blockId]);
|
|
5477
|
+
const leave = useCallback(() => {
|
|
5990
5478
|
stop();
|
|
5991
5479
|
select();
|
|
5992
5480
|
}, [stop, select]);
|
|
5993
|
-
const onChange =
|
|
5481
|
+
const onChange = useCallback(
|
|
5994
5482
|
(data2) => writeBlockData(controller, blockId, data2),
|
|
5995
5483
|
[controller, blockId]
|
|
5996
5484
|
);
|
|
5997
|
-
const
|
|
5485
|
+
const onPreviewChange = useCallback(
|
|
5486
|
+
(data2) => {
|
|
5487
|
+
writeBlockData(controller, blockId, data2);
|
|
5488
|
+
const shell = root.current?.closest("[data-block-id]");
|
|
5489
|
+
const focused = root.current?.ownerDocument.activeElement ?? null;
|
|
5490
|
+
if (!shell?.contains(focused)) return;
|
|
5491
|
+
if (root.current?.contains(focused)) selectNode(controller, blockId);
|
|
5492
|
+
else select();
|
|
5493
|
+
},
|
|
5494
|
+
[controller, blockId, select]
|
|
5495
|
+
);
|
|
5496
|
+
const onRemove = useCallback(() => deleteBlock(controller, blockId), [controller, blockId]);
|
|
5497
|
+
const onInsertBlock = useCallback(
|
|
5998
5498
|
(type) => {
|
|
5999
|
-
insertAfterBlock(controller, blockId, type, blockTypes);
|
|
5499
|
+
if (!insertAfterBlock(controller, blockId, type, blockTypes, report)) return;
|
|
6000
5500
|
stop();
|
|
6001
5501
|
if (controller.editor.state.selection?.kind !== "node") controller.focus();
|
|
6002
5502
|
},
|
|
6003
|
-
[controller, blockId, blockTypes, stop]
|
|
5503
|
+
[controller, blockId, blockTypes, report, stop]
|
|
6004
5504
|
);
|
|
6005
5505
|
const editorShown = editable && (alwaysEditing || editing);
|
|
6006
|
-
const data = readBlockData(controller, block);
|
|
5506
|
+
const data = useMemo(() => parsedData(definition, readBlockData(controller, block)), [definition, controller, block]);
|
|
6007
5507
|
const onKeyDown = (event) => {
|
|
6008
5508
|
if (event.key !== "Escape" || !editorShown || !root.current?.contains(event.target)) return;
|
|
6009
5509
|
event.preventDefault();
|
|
@@ -6015,7 +5515,7 @@ function VoidBlock({ block, controller, definition }) {
|
|
|
6015
5515
|
const onDoubleClick = (event) => {
|
|
6016
5516
|
if (editable && !editorShown && !isInteractive(root.current, event)) start();
|
|
6017
5517
|
};
|
|
6018
|
-
return /* @__PURE__ */
|
|
5518
|
+
return /* @__PURE__ */ jsxs(
|
|
6019
5519
|
"div",
|
|
6020
5520
|
{
|
|
6021
5521
|
ref: root,
|
|
@@ -6030,8 +5530,28 @@ function VoidBlock({ block, controller, definition }) {
|
|
|
6030
5530
|
onClick,
|
|
6031
5531
|
onDoubleClick,
|
|
6032
5532
|
children: [
|
|
6033
|
-
editorShown && Editor ? /* @__PURE__ */
|
|
6034
|
-
|
|
5533
|
+
editorShown && Editor ? /* @__PURE__ */ jsx(
|
|
5534
|
+
Editor,
|
|
5535
|
+
{
|
|
5536
|
+
data,
|
|
5537
|
+
onChange,
|
|
5538
|
+
blockId,
|
|
5539
|
+
index,
|
|
5540
|
+
onRemove,
|
|
5541
|
+
onInsertBlock,
|
|
5542
|
+
onDone: leave
|
|
5543
|
+
}
|
|
5544
|
+
) : /* @__PURE__ */ jsx(
|
|
5545
|
+
VoidPreview,
|
|
5546
|
+
{
|
|
5547
|
+
definition,
|
|
5548
|
+
name,
|
|
5549
|
+
data,
|
|
5550
|
+
blockId,
|
|
5551
|
+
...readOnly ? {} : { onChange: onPreviewChange }
|
|
5552
|
+
}
|
|
5553
|
+
),
|
|
5554
|
+
editable && !editorShown && /* @__PURE__ */ jsx(
|
|
6035
5555
|
Button,
|
|
6036
5556
|
{
|
|
6037
5557
|
type: "button",
|
|
@@ -6041,7 +5561,7 @@ function VoidBlock({ block, controller, definition }) {
|
|
|
6041
5561
|
"aria-label": labels.editBlock(name),
|
|
6042
5562
|
onClick: () => start(),
|
|
6043
5563
|
className: "absolute right-0 top-0 bg-background/90 opacity-0 group-hover/void:opacity-100 in-data-[selected=true]:opacity-100 pointer-coarse:opacity-100 focus-visible:opacity-100",
|
|
6044
|
-
children: /* @__PURE__ */
|
|
5564
|
+
children: /* @__PURE__ */ jsx(Pencil, { "aria-hidden": "true" })
|
|
6045
5565
|
}
|
|
6046
5566
|
)
|
|
6047
5567
|
]
|
|
@@ -6081,10 +5601,10 @@ function mergeRender(uis) {
|
|
|
6081
5601
|
atomText: render.atomText ?? merged.atomText
|
|
6082
5602
|
}));
|
|
6083
5603
|
}
|
|
6084
|
-
function collectUi(extensions, definitions, readOnly = false) {
|
|
5604
|
+
function collectUi(extensions, definitions, readOnly = false, onError) {
|
|
6085
5605
|
const uis = extensions.map(extensionUi);
|
|
6086
5606
|
return {
|
|
6087
|
-
slashItems: [...uis.flatMap((ui) => ui.slashItems ?? []), ...blockTypeSlashItems(definitions)],
|
|
5607
|
+
slashItems: [...uis.flatMap((ui) => ui.slashItems ?? []), ...blockTypeSlashItems(definitions, onError)],
|
|
6088
5608
|
bubbleItems: uis.flatMap((ui) => ui.bubbleItems ?? []),
|
|
6089
5609
|
blockMenuItems: uis.flatMap((ui) => ui.blockMenuItems ?? []),
|
|
6090
5610
|
renderers: Object.assign({}, canvasRenderers(definitions, readOnly), ...uis.map((ui) => ui.renderers)),
|
|
@@ -6178,9 +5698,6 @@ var selectedBlockLabel = (labels, definitions, extensionNames) => (block, schema
|
|
|
6178
5698
|
if (block.type === "FILE" && hasFile(attrs)) return labels.fileBlockName(firstLine2(fileName(attrs)));
|
|
6179
5699
|
return firstLine2(blockPlainText(block, schema)) || blockTypeLabel(labels, block, definitions, extensionNames);
|
|
6180
5700
|
};
|
|
6181
|
-
|
|
6182
|
-
// src/canvas/use-block-link-target.ts
|
|
6183
|
-
import { useEffect as useEffect23 } from "react";
|
|
6184
5701
|
function revealLinkedBlock(controller, hash) {
|
|
6185
5702
|
const id = linkedBlockId(hash);
|
|
6186
5703
|
const shell = id === null ? void 0 : controller.blockElement(id);
|
|
@@ -6192,7 +5709,7 @@ function revealLinkedBlock(controller, hash) {
|
|
|
6192
5709
|
return true;
|
|
6193
5710
|
}
|
|
6194
5711
|
function useBlockLinkTarget(controller, focusOnMount) {
|
|
6195
|
-
|
|
5712
|
+
useEffect(() => {
|
|
6196
5713
|
const view = controller.root?.ownerDocument.defaultView ?? window;
|
|
6197
5714
|
const linked = revealLinkedBlock(controller, view.location.hash);
|
|
6198
5715
|
if (focusOnMount) controller.focus(linked ? void 0 : "start");
|
|
@@ -6203,9 +5720,6 @@ function useBlockLinkTarget(controller, focusOnMount) {
|
|
|
6203
5720
|
return () => view.removeEventListener("hashchange", onHashChange);
|
|
6204
5721
|
}, [controller, focusOnMount]);
|
|
6205
5722
|
}
|
|
6206
|
-
|
|
6207
|
-
// src/canvas/use-delete-reporter.ts
|
|
6208
|
-
import { useEffect as useEffect24, useRef as useRef31 } from "react";
|
|
6209
5723
|
var WRITER_ORIGINS = /* @__PURE__ */ new Set(["command", "input", "paste"]);
|
|
6210
5724
|
var isBlockDeletion = (tr) => WRITER_ORIGINS.has(tr.origin) && tr.getMeta(LINE_JOIN) !== true;
|
|
6211
5725
|
var isEmptyText = (schema, block) => isTextFlow(schema, block) && regionLength(block, primaryRegion(schema, block) ?? "") === 0;
|
|
@@ -6227,11 +5741,11 @@ function deletions(codec, tr) {
|
|
|
6227
5741
|
});
|
|
6228
5742
|
}
|
|
6229
5743
|
function useDeleteReporter(controller, onDelete) {
|
|
6230
|
-
const latest =
|
|
5744
|
+
const latest = useRef(onDelete);
|
|
6231
5745
|
useIsomorphicLayoutEffect(() => {
|
|
6232
5746
|
latest.current = onDelete;
|
|
6233
5747
|
});
|
|
6234
|
-
|
|
5748
|
+
useEffect(() => {
|
|
6235
5749
|
const { codec } = controller.editor;
|
|
6236
5750
|
return controller.editor.subscribe((_state, tr) => {
|
|
6237
5751
|
if (tr === null || latest.current === void 0 || !isBlockDeletion(tr)) return;
|
|
@@ -6240,11 +5754,8 @@ function useDeleteReporter(controller, onDelete) {
|
|
|
6240
5754
|
});
|
|
6241
5755
|
}, [controller]);
|
|
6242
5756
|
}
|
|
6243
|
-
|
|
6244
|
-
// src/canvas/use-structure-announcements.ts
|
|
6245
|
-
import { useEffect as useEffect25 } from "react";
|
|
6246
5757
|
function useStructureAnnouncements(controller, labels) {
|
|
6247
|
-
|
|
5758
|
+
useEffect(() => {
|
|
6248
5759
|
const undoKeys = formatShortcut("Mod-z", { isMac: controller.isMac, labels });
|
|
6249
5760
|
return controller.editor.subscribe((_state, tr) => {
|
|
6250
5761
|
const message = tr === null ? null : structureAnnouncement(tr, labels, undoKeys);
|
|
@@ -6252,11 +5763,8 @@ function useStructureAnnouncements(controller, labels) {
|
|
|
6252
5763
|
});
|
|
6253
5764
|
}, [controller, labels]);
|
|
6254
5765
|
}
|
|
6255
|
-
|
|
6256
|
-
// src/canvas/use-typed-in-place-warning.ts
|
|
6257
|
-
import { useEffect as useEffect26 } from "react";
|
|
6258
5766
|
function useTypedInPlaceWarning(definitions, readOnly) {
|
|
6259
|
-
|
|
5767
|
+
useEffect(() => {
|
|
6260
5768
|
if (readOnly) return;
|
|
6261
5769
|
for (const type of definedTypedInPlace(definitions)) {
|
|
6262
5770
|
devWarn(
|
|
@@ -6265,11 +5773,8 @@ function useTypedInPlaceWarning(definitions, readOnly) {
|
|
|
6265
5773
|
}
|
|
6266
5774
|
}, [definitions, readOnly]);
|
|
6267
5775
|
}
|
|
6268
|
-
|
|
6269
|
-
// src/canvas/BlockCanvas.tsx
|
|
6270
|
-
import { jsx as jsx62, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
6271
5776
|
var GUTTER_ROOM = "ps-12";
|
|
6272
|
-
var BlockCanvas =
|
|
5777
|
+
var BlockCanvas = forwardRef(function BlockCanvas2({
|
|
6273
5778
|
blocks,
|
|
6274
5779
|
onChange,
|
|
6275
5780
|
onDelete,
|
|
@@ -6288,9 +5793,9 @@ var BlockCanvas = forwardRef8(function BlockCanvas2({
|
|
|
6288
5793
|
id,
|
|
6289
5794
|
"aria-label": ariaLabel
|
|
6290
5795
|
}, ref) {
|
|
6291
|
-
const [voidEditing] =
|
|
6292
|
-
const [uiStore] =
|
|
6293
|
-
const [allExtensions] =
|
|
5796
|
+
const [voidEditing] = useState(createVoidEditing);
|
|
5797
|
+
const [uiStore] = useState(createCanvasUiStore);
|
|
5798
|
+
const [allExtensions] = useState(() => [
|
|
6294
5799
|
...coreExtensions(),
|
|
6295
5800
|
voidEditing.extension,
|
|
6296
5801
|
blockMenuKeymap(uiStore),
|
|
@@ -6300,10 +5805,15 @@ var BlockCanvas = forwardRef8(function BlockCanvas2({
|
|
|
6300
5805
|
shortcutsExtension(uiStore),
|
|
6301
5806
|
...extensions ?? []
|
|
6302
5807
|
]);
|
|
6303
|
-
const labels =
|
|
6304
|
-
const
|
|
5808
|
+
const labels = useMemo(() => resolveLabels(labelOverrides), [labelOverrides]);
|
|
5809
|
+
const latestOnError = useRef(onError);
|
|
5810
|
+
latestOnError.current = onError;
|
|
5811
|
+
const ui = useMemo(
|
|
5812
|
+
() => collectUi(allExtensions, blockTypes, readOnly, () => latestOnError.current),
|
|
5813
|
+
[allExtensions, blockTypes, readOnly]
|
|
5814
|
+
);
|
|
6305
5815
|
useTypedInPlaceWarning(blockTypes, readOnly);
|
|
6306
|
-
const [focusOnMount] =
|
|
5816
|
+
const [focusOnMount] = useState(autoFocus);
|
|
6307
5817
|
const controller = useQuoinEditor({
|
|
6308
5818
|
blocks,
|
|
6309
5819
|
onChange,
|
|
@@ -6321,23 +5831,23 @@ var BlockCanvas = forwardRef8(function BlockCanvas2({
|
|
|
6321
5831
|
useDeleteReporter(controller, onDelete);
|
|
6322
5832
|
useBlockLinkTarget(controller, focusOnMount);
|
|
6323
5833
|
useStructureAnnouncements(controller, labels);
|
|
6324
|
-
const actions =
|
|
5834
|
+
const actions = useMemo(() => {
|
|
6325
5835
|
const onCopied = () => controller.announce(labels.copied);
|
|
6326
5836
|
return menuActions(coreBlockMenuActions(labels, { blockLink, onCopied, resolveAssetUrl }), ui.blockMenuItems);
|
|
6327
5837
|
}, [controller, labels, blockLink, resolveAssetUrl, ui.blockMenuItems]);
|
|
6328
|
-
const slashItems =
|
|
5838
|
+
const slashItems = useMemo(
|
|
6329
5839
|
() => [shortcutsSlashItem(labels, uiStore), ...ui.slashItems],
|
|
6330
5840
|
[labels, uiStore, ui.slashItems]
|
|
6331
5841
|
);
|
|
6332
|
-
const blockLabel =
|
|
5842
|
+
const blockLabel = useMemo(
|
|
6333
5843
|
() => selectedBlockLabel(labels, blockTypes, ui.blockNames),
|
|
6334
5844
|
[labels, blockTypes, ui.blockNames]
|
|
6335
5845
|
);
|
|
6336
|
-
const blockPlaceholder =
|
|
5846
|
+
const blockPlaceholder = useMemo(() => {
|
|
6337
5847
|
const placeholderLabels = placeholder === void 0 ? labels : { ...labels, placeholderEmpty: placeholder };
|
|
6338
5848
|
return (state, block) => placeholderFor(state, block, placeholderLabels);
|
|
6339
5849
|
}, [labels, placeholder]);
|
|
6340
|
-
|
|
5850
|
+
useImperativeHandle(
|
|
6341
5851
|
ref,
|
|
6342
5852
|
() => ({
|
|
6343
5853
|
editor: controller.editor,
|
|
@@ -6347,7 +5857,7 @@ var BlockCanvas = forwardRef8(function BlockCanvas2({
|
|
|
6347
5857
|
}),
|
|
6348
5858
|
[controller, resolveAssetUrl]
|
|
6349
5859
|
);
|
|
6350
|
-
return /* @__PURE__ */
|
|
5860
|
+
return /* @__PURE__ */ jsx(QuoinProvider, { value: { blockTypes, upload, resolveAssetUrl, onError, highlight, controller, labels }, children: /* @__PURE__ */ jsx(VoidEditingContext.Provider, { value: voidEditing, children: /* @__PURE__ */ jsx(SlashItemsProvider, { value: slashItems, children: /* @__PURE__ */ jsx(BubbleItemsProvider, { value: ui.bubbleItems, children: /* @__PURE__ */ jsx(CanvasUiProvider, { value: uiStore, children: /* @__PURE__ */ jsxs(
|
|
6351
5861
|
EditorView,
|
|
6352
5862
|
{
|
|
6353
5863
|
controller,
|
|
@@ -6360,24 +5870,22 @@ var BlockCanvas = forwardRef8(function BlockCanvas2({
|
|
|
6360
5870
|
selectedContentLabel: labels.selectedContent,
|
|
6361
5871
|
blockLabel,
|
|
6362
5872
|
unsupportedBlockLabel: labels.unsupportedBlock,
|
|
5873
|
+
blockErrorLabel: labels.blockError,
|
|
5874
|
+
onBlockError: onError,
|
|
6363
5875
|
placeholder: placeholder ?? labels.placeholderEmpty,
|
|
6364
5876
|
blockPlaceholder,
|
|
6365
5877
|
blocksSelectedLabel: labels.blocksSelected,
|
|
6366
5878
|
children: [
|
|
6367
|
-
!readOnly && /* @__PURE__ */
|
|
6368
|
-
/* @__PURE__ */
|
|
6369
|
-
/* @__PURE__ */
|
|
6370
|
-
/* @__PURE__ */
|
|
5879
|
+
!readOnly && /* @__PURE__ */ jsxs(ExtensionBlockNames.Provider, { value: ui.blockNames, children: [
|
|
5880
|
+
/* @__PURE__ */ jsx(Gutter, { controller, store: uiStore, actions }),
|
|
5881
|
+
/* @__PURE__ */ jsx(BlockContextMenu, { controller, store: uiStore, actions }),
|
|
5882
|
+
/* @__PURE__ */ jsx(MobileToolbar, { controller })
|
|
6371
5883
|
] }),
|
|
6372
|
-
ui.overlays.map((Overlay2, index) => /* @__PURE__ */
|
|
5884
|
+
ui.overlays.map((Overlay2, index) => /* @__PURE__ */ jsx(Overlay2, { controller }, index))
|
|
6373
5885
|
]
|
|
6374
5886
|
}
|
|
6375
5887
|
) }) }) }) }) });
|
|
6376
5888
|
});
|
|
6377
|
-
|
|
6378
|
-
// src/upload/UploadField.tsx
|
|
6379
|
-
import * as React9 from "react";
|
|
6380
|
-
import { jsx as jsx63, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
6381
5889
|
function progressText(state, labels) {
|
|
6382
5890
|
if (state.phase === "busy") return labels.uploading;
|
|
6383
5891
|
if (state.phase === "uploaded") return labels.uploaded(state.name);
|
|
@@ -6386,7 +5894,7 @@ function progressText(state, labels) {
|
|
|
6386
5894
|
function UploadField({ category, label, accept, onUploaded }) {
|
|
6387
5895
|
const { upload, onError } = useQuoin();
|
|
6388
5896
|
const labels = useLabels();
|
|
6389
|
-
const [state, setState] =
|
|
5897
|
+
const [state, setState] = React7.useState({ phase: "idle" });
|
|
6390
5898
|
async function run(file) {
|
|
6391
5899
|
if (!upload) return;
|
|
6392
5900
|
setState({ phase: "busy" });
|
|
@@ -6406,8 +5914,8 @@ function UploadField({ category, label, accept, onUploaded }) {
|
|
|
6406
5914
|
}
|
|
6407
5915
|
}
|
|
6408
5916
|
const progress = progressText(state, labels);
|
|
6409
|
-
return /* @__PURE__ */
|
|
6410
|
-
/* @__PURE__ */
|
|
5917
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start gap-1.5", children: [
|
|
5918
|
+
/* @__PURE__ */ jsx(
|
|
6411
5919
|
FilePickerButton,
|
|
6412
5920
|
{
|
|
6413
5921
|
label,
|
|
@@ -6417,15 +5925,12 @@ function UploadField({ category, label, accept, onUploaded }) {
|
|
|
6417
5925
|
onPick: (file) => void run(file)
|
|
6418
5926
|
}
|
|
6419
5927
|
),
|
|
6420
|
-
!upload && /* @__PURE__ */
|
|
6421
|
-
/* @__PURE__ */
|
|
6422
|
-
state.phase === "failed" && /* @__PURE__ */
|
|
5928
|
+
!upload && /* @__PURE__ */ jsx("span", { role: "note", className: "text-xs text-muted-foreground", children: labels.uploadsUnavailable }),
|
|
5929
|
+
/* @__PURE__ */ jsx("span", { role: "status", className: progress === "" ? "sr-only" : "text-xs text-muted-foreground", children: progress }),
|
|
5930
|
+
state.phase === "failed" && /* @__PURE__ */ jsx("span", { role: "alert", className: "text-xs text-destructive", children: state.message })
|
|
6423
5931
|
] });
|
|
6424
5932
|
}
|
|
6425
5933
|
|
|
6426
|
-
// src/hooks/useAutosave.ts
|
|
6427
|
-
import * as React10 from "react";
|
|
6428
|
-
|
|
6429
5934
|
// src/hooks/autosave-backoff.ts
|
|
6430
5935
|
function clearTimer(ref) {
|
|
6431
5936
|
if (ref.current !== null) clearTimeout(ref.current);
|
|
@@ -6535,29 +6040,29 @@ function useAutosave({
|
|
|
6535
6040
|
isRetryable = alwaysRetry,
|
|
6536
6041
|
flushOnHide = true
|
|
6537
6042
|
}) {
|
|
6538
|
-
const [status, setStatus] =
|
|
6539
|
-
const [error, setError] =
|
|
6043
|
+
const [status, setStatus] = React7.useState("idle");
|
|
6044
|
+
const [error, setError] = React7.useState(null);
|
|
6540
6045
|
const latest = { build, save, policy: { debounceMs, maxBackoffMs, maxRetries, isRetryable } };
|
|
6541
|
-
const [runner] =
|
|
6542
|
-
|
|
6046
|
+
const [runner] = React7.useState(() => createSaveRunner({ setStatus, setError }, latest));
|
|
6047
|
+
React7.useEffect(() => {
|
|
6543
6048
|
runner.configure(latest);
|
|
6544
6049
|
});
|
|
6545
|
-
const seenRef =
|
|
6546
|
-
|
|
6050
|
+
const seenRef = React7.useRef(null);
|
|
6051
|
+
React7.useEffect(() => {
|
|
6547
6052
|
const seen = seenRef.current;
|
|
6548
6053
|
seenRef.current = deps;
|
|
6549
6054
|
if (seen === null) return;
|
|
6550
6055
|
const unchanged = sameItems(seen, deps);
|
|
6551
6056
|
if (!unchanged) runner.markDirty();
|
|
6552
6057
|
}, deps);
|
|
6553
|
-
|
|
6058
|
+
React7.useEffect(() => {
|
|
6554
6059
|
return runner.schedule(debounceMs);
|
|
6555
6060
|
}, deps);
|
|
6556
|
-
|
|
6061
|
+
React7.useEffect(() => {
|
|
6557
6062
|
runner.mount();
|
|
6558
6063
|
return runner.dispose;
|
|
6559
6064
|
}, [runner]);
|
|
6560
|
-
|
|
6065
|
+
React7.useEffect(() => {
|
|
6561
6066
|
if (!flushOnHide) return;
|
|
6562
6067
|
const onVisibility = () => {
|
|
6563
6068
|
if (document.visibilityState === "hidden") runner.flush();
|
|
@@ -6572,65 +6077,6 @@ function useAutosave({
|
|
|
6572
6077
|
return { status, error, retry: runner.retry, flush: runner.flush };
|
|
6573
6078
|
}
|
|
6574
6079
|
|
|
6575
|
-
export {
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
useQuoin,
|
|
6579
|
-
useLabels,
|
|
6580
|
-
coreBlocks,
|
|
6581
|
-
selectNode,
|
|
6582
|
-
focusNode,
|
|
6583
|
-
returnFocusToText,
|
|
6584
|
-
cn,
|
|
6585
|
-
FOCUS_RING,
|
|
6586
|
-
FLOATING_TOOLBAR,
|
|
6587
|
-
MENU_ITEM,
|
|
6588
|
-
runOnBlocks,
|
|
6589
|
-
noChange,
|
|
6590
|
-
styleTargets,
|
|
6591
|
-
MenuIcon,
|
|
6592
|
-
formatShortcut,
|
|
6593
|
-
insertBlocks,
|
|
6594
|
-
insertBlockToWrite,
|
|
6595
|
-
interceptKeys,
|
|
6596
|
-
Button,
|
|
6597
|
-
keepFocus,
|
|
6598
|
-
Popover,
|
|
6599
|
-
PopoverAnchor,
|
|
6600
|
-
PopoverContent,
|
|
6601
|
-
preventDefault,
|
|
6602
|
-
FilePickerButton,
|
|
6603
|
-
selectHandlers,
|
|
6604
|
-
useNodeKeys,
|
|
6605
|
-
bubblePart,
|
|
6606
|
-
virtualAnchor,
|
|
6607
|
-
usePartAnchor,
|
|
6608
|
-
useRovingFocus,
|
|
6609
|
-
useFocusKey,
|
|
6610
|
-
linkAddress,
|
|
6611
|
-
Input,
|
|
6612
|
-
useOutsidePress,
|
|
6613
|
-
DropdownMenu,
|
|
6614
|
-
DropdownMenuTrigger,
|
|
6615
|
-
DropdownMenuContent,
|
|
6616
|
-
DropdownMenuItem,
|
|
6617
|
-
DropdownMenuCheckboxItem,
|
|
6618
|
-
DropdownMenuRadioGroup,
|
|
6619
|
-
DropdownMenuRadioItem,
|
|
6620
|
-
DropdownMenuSeparator,
|
|
6621
|
-
inlineDirection,
|
|
6622
|
-
resolveLabels,
|
|
6623
|
-
rangeRect,
|
|
6624
|
-
suggestionPlugin,
|
|
6625
|
-
dismissSuggestion,
|
|
6626
|
-
useRangeAnchor,
|
|
6627
|
-
toError,
|
|
6628
|
-
SuggestionMenu,
|
|
6629
|
-
replaceTrigger,
|
|
6630
|
-
blockFragment,
|
|
6631
|
-
linkedBlockId,
|
|
6632
|
-
BlockCanvas,
|
|
6633
|
-
UploadField,
|
|
6634
|
-
useAutosave
|
|
6635
|
-
};
|
|
6636
|
-
//# sourceMappingURL=chunk-T43RZTUT.js.map
|
|
6080
|
+
export { BlockCanvas, Button, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger, FLOATING_TOOLBAR, FOCUS_RING, FilePickerButton, Input, MENU_ITEM, MenuIcon, Popover, PopoverAnchor, PopoverContent, QuoinProvider, SuggestionMenu, UploadField, blockFragment, bubblePart, cn, coreBlocks, dismissSuggestion, englishLabels, focusNode, formatShortcut, inlineDirection, insertBlockToWrite, insertBlocks, interceptKeys, keepFocus, linkAddress, linkedBlockId, noChange, preventDefault, rangeRect, replaceTrigger, resolveLabels, returnFocusToText, runOnBlocks, selectHandlers, selectNode, styleTargets, suggestionPlugin, toError, useAutosave, useFocusKey, useLabels, useNodeKeys, useOutsidePress, usePartAnchor, useQuoin, useRangeAnchor, useRovingFocus, virtualAnchor };
|
|
6081
|
+
//# sourceMappingURL=chunk-XJDPQFPU.js.map
|
|
6082
|
+
//# sourceMappingURL=chunk-XJDPQFPU.js.map
|