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