@inkbrick/react 0.0.0-stage → 0.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FormulaPalette-WFRPRHS5.js +320 -0
- package/dist/FormulaPalette-WFRPRHS5.js.map +1 -0
- package/dist/chunk-TPUX4C45.js +2309 -0
- package/dist/chunk-TPUX4C45.js.map +1 -0
- package/dist/index.d.ts +1431 -0
- package/dist/index.js +4880 -0
- package/dist/index.js.map +1 -0
- package/dist/mathCss-FLPE6QBM.js +361 -0
- package/dist/mathCss-FLPE6QBM.js.map +1 -0
- package/package.json +46 -3
- package/src/block-handle/BlockHandleController.ts +93 -0
- package/src/block-handle/BlockHandleHost.tsx +108 -0
- package/src/block-handle/DefaultBlockHandle.tsx +71 -0
- package/src/block-handle/DefaultBlockMenu.tsx +114 -0
- package/src/block-handle/DropIndicatorHost.tsx +58 -0
- package/src/block-handle/actions.tsx +146 -0
- package/src/block-handle/blockDrag.ts +215 -0
- package/src/block-handle/geometry.ts +64 -0
- package/src/block-handle/gripGesture.ts +108 -0
- package/src/block-handle/types.ts +65 -0
- package/src/block-handle/useBlockDrag.ts +21 -0
- package/src/block-handle/useBlockHandles.ts +125 -0
- package/src/blocks/BlockChildren.tsx +17 -0
- package/src/blocks/BlockProps.ts +5 -0
- package/src/blocks/CalloutBlock.tsx +61 -0
- package/src/blocks/CodeBlock.tsx +96 -0
- package/src/blocks/DividerBlock.tsx +15 -0
- package/src/blocks/Editable.tsx +84 -0
- package/src/blocks/FormulaBlock.tsx +173 -0
- package/src/blocks/HeadingBlock.tsx +22 -0
- package/src/blocks/ImageBlock.tsx +362 -0
- package/src/blocks/ListBlock.tsx +86 -0
- package/src/blocks/NoteBlock.tsx +10 -0
- package/src/blocks/PageBlock.tsx +10 -0
- package/src/blocks/ParagraphBlock.tsx +20 -0
- package/src/blocks/QuoteBlock.tsx +18 -0
- package/src/blocks/UnknownBlockView.tsx +27 -0
- package/src/blocks/defineBlock.ts +49 -0
- package/src/clipboard/html/blocks.ts +379 -0
- package/src/clipboard/html/inline.ts +92 -0
- package/src/clipboard/html/style.ts +92 -0
- package/src/clipboard/html/tags.ts +77 -0
- package/src/clipboard/htmlToFragment.ts +41 -0
- package/src/clipboard/useClipboard.ts +296 -0
- package/src/code/highlight.ts +56 -0
- package/src/code/languages.ts +236 -0
- package/src/code/scan/css.ts +164 -0
- package/src/code/scan/generic.ts +328 -0
- package/src/code/scan/html.ts +129 -0
- package/src/code/scan/markdown.ts +58 -0
- package/src/code/scan/shared.ts +81 -0
- package/src/code/scan/yaml.ts +34 -0
- package/src/code/types.ts +34 -0
- package/src/context/EditorContext.ts +9 -0
- package/src/context/EditorProvider.tsx +172 -0
- package/src/controllers/adapters.tsx +63 -0
- package/src/editing/BlockSelectionController.ts +27 -0
- package/src/editing/CaretController.ts +27 -0
- package/src/editing/EditorView.ts +108 -0
- package/src/editing/ViewportController.ts +63 -0
- package/src/editing/beforeInput.ts +276 -0
- package/src/editing/deleteAtBoundary.ts +16 -0
- package/src/editing/inputActions.ts +109 -0
- package/src/editing/renderCode.ts +69 -0
- package/src/editing/renderInline.ts +144 -0
- package/src/editing/selection.ts +262 -0
- package/src/editing/useEditorInput.ts +223 -0
- package/src/editing/useSelectionState.ts +46 -0
- package/src/formula/FormulaController.ts +51 -0
- package/src/formula/FormulaPalette.tsx +79 -0
- package/src/formula/FormulaPopover.tsx +181 -0
- package/src/formula/LazyFormulaPalette.tsx +42 -0
- package/src/formula/actions.ts +138 -0
- package/src/formula/snippet.ts +70 -0
- package/src/formula/symbols.ts +264 -0
- package/src/hooks/useBlock.ts +21 -0
- package/src/hooks/useBlockController.ts +30 -0
- package/src/hooks/useChildren.ts +16 -0
- package/src/hooks/useDocument.ts +16 -0
- package/src/hooks/useEditor.ts +13 -0
- package/src/hooks/useEditorView.ts +13 -0
- package/src/hooks/useHistory.ts +46 -0
- package/src/hooks/useReadOnly.ts +21 -0
- package/src/hooks/useT.ts +10 -0
- package/src/i18n/en.ts +182 -0
- package/src/i18n/ru.ts +174 -0
- package/src/i18n/translate.ts +77 -0
- package/src/icons/ICONS_LICENSE.md +50 -0
- package/src/icons/Icon.tsx +41 -0
- package/src/icons/lucide.ts +234 -0
- package/src/images/ImageError.ts +39 -0
- package/src/images/UploadTracker.ts +49 -0
- package/src/images/insertImages.ts +142 -0
- package/src/images/types.ts +22 -0
- package/src/images/upload.ts +62 -0
- package/src/index.ts +102 -0
- package/src/keymap/defaultKeymap.ts +189 -0
- package/src/keymap/keymap.ts +42 -0
- package/src/keymap/shortcut.ts +105 -0
- package/src/keymap/types.ts +40 -0
- package/src/math/FormulaView.tsx +62 -0
- package/src/math/mathCss.ts +4 -0
- package/src/math/renderer.ts +198 -0
- package/src/registry/defaultBlockComponents.ts +26 -0
- package/src/registry/resolveBlockComponent.ts +14 -0
- package/src/renderer/BlockRenderer.tsx +63 -0
- package/src/renderer/DocumentRenderer.tsx +33 -0
- package/src/renderer/DocumentView.tsx +94 -0
- package/src/renderer/virtual/VirtualChildList.tsx +355 -0
- package/src/renderer/virtual/estimate.ts +62 -0
- package/src/renderer/virtual/virtualRenderer.tsx +35 -0
- package/src/slash/DefaultSlashMenu.tsx +119 -0
- package/src/slash/SlashMenuController.ts +66 -0
- package/src/slash/SlashMenuHost.tsx +48 -0
- package/src/slash/applySlashItem.ts +57 -0
- package/src/slash/defaultSlashItems.tsx +186 -0
- package/src/slash/filter.ts +29 -0
- package/src/slash/items.ts +30 -0
- package/src/slash/syncSlashMenu.ts +67 -0
- package/src/slash/types.ts +21 -0
- package/src/toolbar/DefaultToolbar.tsx +281 -0
- package/src/toolbar/ToolbarController.ts +100 -0
- package/src/toolbar/ToolbarHost.tsx +81 -0
- package/src/toolbar/formatting.ts +75 -0
- package/src/toolbar/rich.ts +58 -0
- package/src/toolbar/syncToolbar.ts +39 -0
- package/src/toolbar/types.ts +21 -0
- package/src/ui/EditorUIContext.ts +26 -0
- package/src/ui/presentation.ts +24 -0
- package/src/ui/types.ts +70 -0
- package/README.md +0 -3
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
// src/math/mathCss.ts
|
|
2
|
+
var MATH_CSS = `math {
|
|
3
|
+
font-family: "Cambria Math", 'STIXTwoMath-Regular', 'NotoSansMath-Regular', math;
|
|
4
|
+
font-style: normal;
|
|
5
|
+
font-weight: normal;
|
|
6
|
+
line-height: normal;
|
|
7
|
+
font-size-adjust: none;
|
|
8
|
+
text-indent: 0;
|
|
9
|
+
text-transform: none;
|
|
10
|
+
letter-spacing: normal;
|
|
11
|
+
word-wrap: normal;
|
|
12
|
+
direction: ltr;
|
|
13
|
+
/* Prevent Firefox from omitting the dot on i or j. */
|
|
14
|
+
font-feature-settings: "dtls" off;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
math * {
|
|
18
|
+
border-color: currentColor;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* display: block is necessary in Firefox and Safari.
|
|
22
|
+
* Not in Chromium, which recognizes display: "block math" written inline. */
|
|
23
|
+
math.tml-display {
|
|
24
|
+
display: block;
|
|
25
|
+
width: 100%;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
*.mathcal {
|
|
29
|
+
/* NotoSans */
|
|
30
|
+
font-feature-settings: 'ss01';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
math .mathscr {
|
|
34
|
+
font-family: "Temml";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
mo.tml-prime {
|
|
38
|
+
font-family: Temml;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Cramped superscripts in WebKit */
|
|
42
|
+
mfrac > :nth-child(2),
|
|
43
|
+
msqrt,
|
|
44
|
+
mover > :first-child {
|
|
45
|
+
math-shift: compact
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.menclose {
|
|
49
|
+
display: inline-block;
|
|
50
|
+
position: relative;
|
|
51
|
+
padding: 0.5ex 0ex;
|
|
52
|
+
}
|
|
53
|
+
.tml-cancelto {
|
|
54
|
+
display: inline-block;
|
|
55
|
+
position: absolute;
|
|
56
|
+
top: 0;
|
|
57
|
+
left: 0;
|
|
58
|
+
padding: 0.5ex 0ex;
|
|
59
|
+
background-color: currentColor;
|
|
60
|
+
/* Use the SVG as an alpha mask (painted by background-color) */
|
|
61
|
+
-webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><defs><marker id='a' markerHeight='5' markerUnits='strokeWidth' markerWidth='7' orient='auto' refX='7' refY='2.5'><path fill='black' d='m0 0 7 2.5L0 5z'/></marker></defs><line x2='100%25' y1='100%25' stroke='black' stroke-width='.06em' marker-end='url(%23a)' vector-effect='non-scaling-stroke'/></svg>");
|
|
62
|
+
mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><defs><marker id='a' markerHeight='5' markerUnits='strokeWidth' markerWidth='7' orient='auto' refX='7' refY='2.5'><path fill='black' d='m0 0 7 2.5L0 5z'/></marker></defs><line x2='100%25' y1='100%25' stroke='black' stroke-width='.06em' marker-end='url(%23a)' vector-effect='non-scaling-stroke'/></svg>");
|
|
63
|
+
-webkit-mask-repeat: no-repeat;
|
|
64
|
+
mask-repeat: no-repeat;
|
|
65
|
+
-webkit-mask-size: 100% 100%;
|
|
66
|
+
mask-size: 100% 100%;
|
|
67
|
+
-webkit-mask-position: 0 0;
|
|
68
|
+
mask-position: 0 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@supports (-moz-appearance: none) {
|
|
72
|
+
/* \\vec w/o italic correction for Firefox */
|
|
73
|
+
.tml-vec {
|
|
74
|
+
transform: scale(0.75)
|
|
75
|
+
}
|
|
76
|
+
/* Fix \\cancelto in Firefox */
|
|
77
|
+
.ff-narrow {
|
|
78
|
+
width: 0em;
|
|
79
|
+
}
|
|
80
|
+
.ff-nudge-left {
|
|
81
|
+
margin-left: -0.2em;
|
|
82
|
+
}
|
|
83
|
+
/* Squash hidden mrows in \\bordermatrix. Messes with centering, but necessary to squash. */
|
|
84
|
+
.ff-squash mtd {
|
|
85
|
+
display: block;
|
|
86
|
+
height: 0;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@supports (not (-moz-appearance: none)) {
|
|
91
|
+
/* Chromium and WebKit */
|
|
92
|
+
/* prime vertical alignment */
|
|
93
|
+
mo.tml-prime {
|
|
94
|
+
font-family: Temml;
|
|
95
|
+
}
|
|
96
|
+
/* Italic correction on superscripts */
|
|
97
|
+
.tml-sml-pad {
|
|
98
|
+
padding-left: 0.05em;
|
|
99
|
+
}
|
|
100
|
+
.tml-med-pad {
|
|
101
|
+
padding-left: 0.10em;
|
|
102
|
+
}
|
|
103
|
+
.tml-lrg-pad {
|
|
104
|
+
padding-left: 0.15em;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@supports (-webkit-backdrop-filter: blur(1px)) {
|
|
109
|
+
/* WebKit vertical & italic correction on accents */
|
|
110
|
+
.wbk-acc {
|
|
111
|
+
/* lower by x-height distance */
|
|
112
|
+
transform: translate(0em, 0.431em);
|
|
113
|
+
}
|
|
114
|
+
.wbk-sml {
|
|
115
|
+
transform: translate(0.07em, 0);
|
|
116
|
+
}
|
|
117
|
+
.wbk-sml-acc {
|
|
118
|
+
transform: translate(0.07em, 0.431em);
|
|
119
|
+
}
|
|
120
|
+
.wbk-sml-vec {
|
|
121
|
+
transform: scale(0.75) translate(0.07em, 0);
|
|
122
|
+
}
|
|
123
|
+
.wbk-med {
|
|
124
|
+
transform: translate(0.14em, 0);
|
|
125
|
+
}
|
|
126
|
+
.wbk-med-acc {
|
|
127
|
+
transform: translate(0.14em, 0.431em);
|
|
128
|
+
}
|
|
129
|
+
.wbk-med-vec {
|
|
130
|
+
transform: scale(0.75) translate(0.14em, 0);
|
|
131
|
+
}
|
|
132
|
+
.wbk-lrg {
|
|
133
|
+
transform: translate(0.21em, 0);
|
|
134
|
+
}
|
|
135
|
+
.wbk-lrg-acc {
|
|
136
|
+
transform: translate(0.21em, 0.431em);
|
|
137
|
+
}
|
|
138
|
+
.wbk-lrg-vec {
|
|
139
|
+
transform: scale(0.75) translate(0.21em, 0);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/* \\cancel & \\phase use background images. Get them to print. */
|
|
144
|
+
menclose {
|
|
145
|
+
-webkit-print-color-adjust: exact; /* Chrome & Edge */
|
|
146
|
+
print-color-adjust: exact;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* Array cell justification in Firefox & WebKit */
|
|
150
|
+
.tml-right {
|
|
151
|
+
text-align: right;
|
|
152
|
+
}
|
|
153
|
+
.tml-left {
|
|
154
|
+
text-align: left;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/* For CD labels that grow to the left in Firefox and WebKit */
|
|
158
|
+
.tml-shift-left { margin-left:-200% }
|
|
159
|
+
|
|
160
|
+
/* Styles for Chromium only */
|
|
161
|
+
@supports (not (-webkit-backdrop-filter: blur(1px))) and (not (-moz-appearance: none)) {
|
|
162
|
+
/* Italic correction on accents */
|
|
163
|
+
.chr-sml {
|
|
164
|
+
transform: translate(0.07em, 0)
|
|
165
|
+
}
|
|
166
|
+
.chr-sml-vec {
|
|
167
|
+
transform: scale(0.75) translate(0.07em, 0)
|
|
168
|
+
}
|
|
169
|
+
.chr-med {
|
|
170
|
+
transform: translate(0.14em, 0)
|
|
171
|
+
}
|
|
172
|
+
.chr-med-vec {
|
|
173
|
+
transform: scale(0.75) translate(0.14em, 0)
|
|
174
|
+
}
|
|
175
|
+
.chr-lrg {
|
|
176
|
+
transform: translate(0.21em, 0)
|
|
177
|
+
}
|
|
178
|
+
.chr-lrg-vec {
|
|
179
|
+
transform: scale(0.75) translate(0.21em, 0)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* For CD labels that grow to the left */
|
|
183
|
+
.tml-shift-left { margin-left:-100% }
|
|
184
|
+
|
|
185
|
+
/* MathML Core & Chromium do not support the MathML 3.0 element <menclose> attributes. */
|
|
186
|
+
/* So use styles. */
|
|
187
|
+
menclose {
|
|
188
|
+
position: relative;
|
|
189
|
+
padding: 0.5ex 0ex;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.tml-overline {
|
|
193
|
+
padding: 0.1em 0 0 0;
|
|
194
|
+
border-top: 0.065em solid;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.tml-underline {
|
|
198
|
+
padding: 0 0 0.1em 0;
|
|
199
|
+
border-bottom: 0.065em solid;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.tml-cancel {
|
|
203
|
+
display: inline-block;
|
|
204
|
+
position: absolute;
|
|
205
|
+
left: 0.5px;
|
|
206
|
+
bottom: 0;
|
|
207
|
+
width: 100%;
|
|
208
|
+
height: 100%;
|
|
209
|
+
background-color: currentColor;
|
|
210
|
+
}
|
|
211
|
+
.upstrike {
|
|
212
|
+
clip-path: polygon(0.05em 100%, 0em calc(100% - 0.05em), calc(100% - 0.05em) 0em, 100% 0.05em);
|
|
213
|
+
}
|
|
214
|
+
.downstrike {
|
|
215
|
+
clip-path: polygon(0em 0.05em, 0.05em 0em, 100% calc(100% - 0.05em), calc(100% - 0.05em) 100%);
|
|
216
|
+
}
|
|
217
|
+
.sout {
|
|
218
|
+
clip-path: polygon(0em calc(55% + 0.0333em), 0em calc(55% - 0.0333em), 100% calc(55% - 0.0333em), 100% calc(55% + 0.0333em));
|
|
219
|
+
}
|
|
220
|
+
.tml-xcancel {
|
|
221
|
+
clip-path: polygon(0.05em 0em, 0em 0.05em, calc(50% - 0.05em) 50%, 0em calc(100% - 0.05em), 0.05em 100%, 50% calc(50% + 0.05em), calc(100% - 0.05em) 100%, 100% calc(100% - 0.05em), calc(50% + 0.05em) 50%, 100% 0.05em, calc(100% - 0.05em) 0%, 50% calc(50% - 0.05em));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.longdiv-top {
|
|
225
|
+
border-top: 0.067em solid;
|
|
226
|
+
padding: 0.1em 0.2em 0.2em 0.433em;
|
|
227
|
+
}
|
|
228
|
+
.longdiv-arc {
|
|
229
|
+
position: absolute;
|
|
230
|
+
top: 0;
|
|
231
|
+
bottom: 0.1em;
|
|
232
|
+
left: -0.4em;
|
|
233
|
+
width: 0.7em;
|
|
234
|
+
border: 0.067em solid;
|
|
235
|
+
transform: translateY(-0.067em);
|
|
236
|
+
border-radius: 70%;
|
|
237
|
+
clip-path: inset(0 0 0 0.4em);
|
|
238
|
+
box-sizing: border-box;}
|
|
239
|
+
.menclose {display: inline-block;
|
|
240
|
+
text-align: left;
|
|
241
|
+
position: relative;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.phasor-bottom {
|
|
245
|
+
border-bottom: 0.067em solid;
|
|
246
|
+
padding: 0.2em 0.2em 0.1em 0.6em;
|
|
247
|
+
}
|
|
248
|
+
.phasor-angle {
|
|
249
|
+
display: inline-block;
|
|
250
|
+
position: absolute;
|
|
251
|
+
left: 0.5px;
|
|
252
|
+
bottom: -0.04em;
|
|
253
|
+
height: 100%;
|
|
254
|
+
aspect-ratio: 0.5;
|
|
255
|
+
background-color: currentColor;
|
|
256
|
+
clip-path: polygon(0.05em 100%, 0em calc(100% - 0.05em), calc(100% - 0.05em) 0em, 100% 0.05em);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.tml-fbox {
|
|
260
|
+
padding: 3pt;
|
|
261
|
+
border: 1px solid;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.circle-pad {
|
|
265
|
+
padding: 0.267em;
|
|
266
|
+
}
|
|
267
|
+
.textcircle {
|
|
268
|
+
position: absolute;
|
|
269
|
+
top: 0;
|
|
270
|
+
bottom: 0;
|
|
271
|
+
right: 0;
|
|
272
|
+
left: 0;
|
|
273
|
+
border: 0.067em solid;
|
|
274
|
+
border-radius: 50%;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.actuarial {
|
|
278
|
+
padding: 0.03889em 0.03889em 0 0.03889em;
|
|
279
|
+
border-width: 0.08em 0.08em 0em 0em;
|
|
280
|
+
border-style: solid;
|
|
281
|
+
margin-right: 0.03889em;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/* Stretch \\widetilde */
|
|
285
|
+
.tml-tilde-2 {
|
|
286
|
+
transform: scale(2.0, 1.1)
|
|
287
|
+
}
|
|
288
|
+
.tml-tilde-3 {
|
|
289
|
+
transform: scale(3.0, 1.1)
|
|
290
|
+
}
|
|
291
|
+
.tml-tilde-4 {
|
|
292
|
+
transform: scale(4.0, 1.1)
|
|
293
|
+
}
|
|
294
|
+
/* Stretch \\widehat */
|
|
295
|
+
.tml-hat-1 {
|
|
296
|
+
transform: scale(1.9, 1.0)
|
|
297
|
+
}
|
|
298
|
+
.tml-hat-2 {
|
|
299
|
+
transform: scale(3.9, 1.0)
|
|
300
|
+
}
|
|
301
|
+
.tml-hat-3 {
|
|
302
|
+
transform: scale(5.8, 1.0)
|
|
303
|
+
}
|
|
304
|
+
.tml-hat-4 {
|
|
305
|
+
transform: scale(7.8, 1.0)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/* set array cell justification */
|
|
309
|
+
.tml-right {
|
|
310
|
+
text-align: -webkit-right;
|
|
311
|
+
}
|
|
312
|
+
.tml-left {
|
|
313
|
+
text-align: -webkit-left;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.special-fraction {
|
|
318
|
+
font-family: 'STIX TWO', 'Times New Roman', Times, Tinos, serif;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/* flex-wrap for line-breaking in Chromium */
|
|
322
|
+
math {
|
|
323
|
+
display: inline-flex;
|
|
324
|
+
flex-wrap: wrap;
|
|
325
|
+
align-items: baseline;
|
|
326
|
+
}
|
|
327
|
+
math > mrow {
|
|
328
|
+
padding: 0.5ex 0ex;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/* Default mtd top padding is 0.5ex per MathML-Core and user-agent CSS */
|
|
332
|
+
/* We adjust for jot and small */
|
|
333
|
+
mtable.tml-jot > mtr > mtd {
|
|
334
|
+
padding-top: 0.7ex;
|
|
335
|
+
padding-bottom: 0.7ex;
|
|
336
|
+
}
|
|
337
|
+
mtable.tml-small mtd {
|
|
338
|
+
padding-top: 0.35ex;
|
|
339
|
+
padding-bottom: 0.35ex;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/* Firefox */
|
|
343
|
+
@-moz-document url-prefix() {
|
|
344
|
+
/* Avoid flex-wrap */
|
|
345
|
+
math { display: inline; }
|
|
346
|
+
math > mrow { padding: 0 }
|
|
347
|
+
/* Adjust Firefox spacing between array rows */
|
|
348
|
+
mtd, mtable.tml-small mtd { padding-top: 0; padding-bottom: 0; }
|
|
349
|
+
mtable.tml-jot > mtr > mtd { padding-top: 0.2ex; padding-bottom: 0.2ex; }
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/* AMS environment auto-numbering via CSS counter. */
|
|
353
|
+
.tml-eqn::before {
|
|
354
|
+
counter-increment: tmlEqnNo;
|
|
355
|
+
content: "(" counter(tmlEqnNo) ")";
|
|
356
|
+
}
|
|
357
|
+
`;
|
|
358
|
+
export {
|
|
359
|
+
MATH_CSS
|
|
360
|
+
};
|
|
361
|
+
//# sourceMappingURL=mathCss-FLPE6QBM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/math/mathCss.ts"],"sourcesContent":["// Стили MathML-вывода Temml (https://temml.org, лицензия MIT, © Ron Kok) — файл dist/Temml-Local.css без @font-face.\n// Файл сгенерирован из пакета temml; не правьте вручную. Лицензия — в `LICENSE` пакета temml.\nexport const MATH_CSS: string =\n \"math {\\n font-family: \\\"Cambria Math\\\", 'STIXTwoMath-Regular', 'NotoSansMath-Regular', math;\\n font-style: normal;\\n font-weight: normal;\\n line-height: normal;\\n font-size-adjust: none;\\n text-indent: 0;\\n text-transform: none;\\n letter-spacing: normal;\\n word-wrap: normal;\\n direction: ltr;\\n /* Prevent Firefox from omitting the dot on i or j. */\\n font-feature-settings: \\\"dtls\\\" off;\\n}\\n\\nmath * {\\n border-color: currentColor;\\n}\\n\\n/* display: block is necessary in Firefox and Safari.\\n * Not in Chromium, which recognizes display: \\\"block math\\\" written inline. */\\n math.tml-display {\\n display: block;\\n width: 100%;\\n}\\n\\n*.mathcal {\\n /* NotoSans */\\n font-feature-settings: 'ss01';\\n}\\n\\nmath .mathscr {\\n font-family: \\\"Temml\\\";\\n}\\n\\nmo.tml-prime {\\n font-family: Temml;\\n}\\n\\n/* Cramped superscripts in WebKit */\\nmfrac > :nth-child(2),\\nmsqrt,\\nmover > :first-child {\\n math-shift: compact\\n}\\n\\n.menclose {\\n display: inline-block;\\n position: relative;\\n padding: 0.5ex 0ex;\\n}\\n.tml-cancelto {\\n display: inline-block;\\n position: absolute;\\n top: 0;\\n left: 0;\\n padding: 0.5ex 0ex;\\n background-color: currentColor;\\n /* Use the SVG as an alpha mask (painted by background-color) */\\n -webkit-mask-image: url(\\\"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><defs><marker id='a' markerHeight='5' markerUnits='strokeWidth' markerWidth='7' orient='auto' refX='7' refY='2.5'><path fill='black' d='m0 0 7 2.5L0 5z'/></marker></defs><line x2='100%25' y1='100%25' stroke='black' stroke-width='.06em' marker-end='url(%23a)' vector-effect='non-scaling-stroke'/></svg>\\\");\\n mask-image: url(\\\"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><defs><marker id='a' markerHeight='5' markerUnits='strokeWidth' markerWidth='7' orient='auto' refX='7' refY='2.5'><path fill='black' d='m0 0 7 2.5L0 5z'/></marker></defs><line x2='100%25' y1='100%25' stroke='black' stroke-width='.06em' marker-end='url(%23a)' vector-effect='non-scaling-stroke'/></svg>\\\");\\n -webkit-mask-repeat: no-repeat;\\n mask-repeat: no-repeat;\\n -webkit-mask-size: 100% 100%;\\n mask-size: 100% 100%;\\n -webkit-mask-position: 0 0;\\n mask-position: 0 0;\\n}\\n\\n@supports (-moz-appearance: none) {\\n /* \\\\vec w/o italic correction for Firefox */\\n .tml-vec {\\n transform: scale(0.75)\\n }\\n /* Fix \\\\cancelto in Firefox */\\n .ff-narrow {\\n width: 0em;\\n }\\n .ff-nudge-left {\\n margin-left: -0.2em;\\n }\\n /* Squash hidden mrows in \\\\bordermatrix. Messes with centering, but necessary to squash. */\\n .ff-squash mtd {\\n display: block;\\n height: 0;\\n }\\n}\\n\\n@supports (not (-moz-appearance: none)) {\\n /* Chromium and WebKit */\\n /* prime vertical alignment */\\n mo.tml-prime {\\n font-family: Temml;\\n }\\n /* Italic correction on superscripts */\\n .tml-sml-pad {\\n padding-left: 0.05em;\\n }\\n .tml-med-pad {\\n padding-left: 0.10em;\\n }\\n .tml-lrg-pad {\\n padding-left: 0.15em;\\n }\\n}\\n\\n@supports (-webkit-backdrop-filter: blur(1px)) {\\n /* WebKit vertical & italic correction on accents */\\n .wbk-acc {\\n /* lower by x-height distance */\\n transform: translate(0em, 0.431em);\\n }\\n .wbk-sml {\\n transform: translate(0.07em, 0);\\n }\\n .wbk-sml-acc {\\n transform: translate(0.07em, 0.431em);\\n }\\n .wbk-sml-vec {\\n transform: scale(0.75) translate(0.07em, 0);\\n }\\n .wbk-med {\\n transform: translate(0.14em, 0);\\n }\\n .wbk-med-acc {\\n transform: translate(0.14em, 0.431em);\\n }\\n .wbk-med-vec {\\n transform: scale(0.75) translate(0.14em, 0);\\n }\\n .wbk-lrg {\\n transform: translate(0.21em, 0);\\n }\\n .wbk-lrg-acc {\\n transform: translate(0.21em, 0.431em);\\n }\\n .wbk-lrg-vec {\\n transform: scale(0.75) translate(0.21em, 0);\\n }\\n}\\n\\n/* \\\\cancel & \\\\phase use background images. Get them to print. */\\nmenclose {\\n -webkit-print-color-adjust: exact; /* Chrome & Edge */\\n print-color-adjust: exact;\\n}\\n\\n/* Array cell justification in Firefox & WebKit */\\n.tml-right {\\n text-align: right;\\n}\\n.tml-left {\\n text-align: left;\\n}\\n\\n/* For CD labels that grow to the left in Firefox and WebKit */\\n.tml-shift-left { margin-left:-200% }\\n\\n/* Styles for Chromium only */\\n@supports (not (-webkit-backdrop-filter: blur(1px))) and (not (-moz-appearance: none)) {\\n /* Italic correction on accents */\\n .chr-sml {\\n transform: translate(0.07em, 0)\\n }\\n .chr-sml-vec {\\n transform: scale(0.75) translate(0.07em, 0)\\n }\\n .chr-med {\\n transform: translate(0.14em, 0)\\n }\\n .chr-med-vec {\\n transform: scale(0.75) translate(0.14em, 0)\\n }\\n .chr-lrg {\\n transform: translate(0.21em, 0)\\n }\\n .chr-lrg-vec {\\n transform: scale(0.75) translate(0.21em, 0)\\n }\\n\\n /* For CD labels that grow to the left */\\n .tml-shift-left { margin-left:-100% }\\n\\n /* MathML Core & Chromium do not support the MathML 3.0 element <menclose> attributes. */\\n /* So use styles. */\\n menclose {\\n position: relative;\\n padding: 0.5ex 0ex;\\n }\\n \\n .tml-overline {\\n padding: 0.1em 0 0 0;\\n border-top: 0.065em solid;\\n }\\n\\n .tml-underline {\\n padding: 0 0 0.1em 0;\\n border-bottom: 0.065em solid;\\n }\\n\\n .tml-cancel {\\n display: inline-block;\\n position: absolute;\\n left: 0.5px;\\n bottom: 0;\\n width: 100%;\\n height: 100%;\\n background-color: currentColor;\\n }\\n .upstrike {\\n clip-path: polygon(0.05em 100%, 0em calc(100% - 0.05em), calc(100% - 0.05em) 0em, 100% 0.05em);\\n }\\n .downstrike {\\n clip-path: polygon(0em 0.05em, 0.05em 0em, 100% calc(100% - 0.05em), calc(100% - 0.05em) 100%);\\n }\\n .sout {\\n clip-path: polygon(0em calc(55% + 0.0333em), 0em calc(55% - 0.0333em), 100% calc(55% - 0.0333em), 100% calc(55% + 0.0333em));\\n }\\n .tml-xcancel {\\n clip-path: polygon(0.05em 0em, 0em 0.05em, calc(50% - 0.05em) 50%, 0em calc(100% - 0.05em), 0.05em 100%, 50% calc(50% + 0.05em), calc(100% - 0.05em) 100%, 100% calc(100% - 0.05em), calc(50% + 0.05em) 50%, 100% 0.05em, calc(100% - 0.05em) 0%, 50% calc(50% - 0.05em));\\n }\\n\\n .longdiv-top {\\n border-top: 0.067em solid;\\n padding: 0.1em 0.2em 0.2em 0.433em;\\n }\\n .longdiv-arc {\\n position: absolute;\\n top: 0;\\n bottom: 0.1em;\\n left: -0.4em;\\n width: 0.7em;\\n border: 0.067em solid;\\n transform: translateY(-0.067em);\\n border-radius: 70%;\\n clip-path: inset(0 0 0 0.4em);\\n box-sizing: border-box;}\\n .menclose {display: inline-block;\\n text-align: left;\\n position: relative;\\n }\\n \\n .phasor-bottom {\\n border-bottom: 0.067em solid;\\n padding: 0.2em 0.2em 0.1em 0.6em;\\n }\\n .phasor-angle {\\n display: inline-block;\\n position: absolute;\\n left: 0.5px;\\n bottom: -0.04em;\\n height: 100%;\\n aspect-ratio: 0.5;\\n background-color: currentColor;\\n clip-path: polygon(0.05em 100%, 0em calc(100% - 0.05em), calc(100% - 0.05em) 0em, 100% 0.05em);\\n }\\n\\n .tml-fbox {\\n padding: 3pt;\\n border: 1px solid;\\n }\\n\\n .circle-pad {\\n padding: 0.267em;\\n }\\n .textcircle {\\n position: absolute;\\n top: 0;\\n bottom: 0;\\n right: 0;\\n left: 0;\\n border: 0.067em solid;\\n border-radius: 50%;\\n }\\n\\n .actuarial {\\n padding: 0.03889em 0.03889em 0 0.03889em;\\n border-width: 0.08em 0.08em 0em 0em;\\n border-style: solid;\\n margin-right: 0.03889em;\\n }\\n\\n /* Stretch \\\\widetilde */\\n .tml-tilde-2 {\\n transform: scale(2.0, 1.1)\\n }\\n .tml-tilde-3 {\\n transform: scale(3.0, 1.1)\\n }\\n .tml-tilde-4 {\\n transform: scale(4.0, 1.1)\\n }\\n /* Stretch \\\\widehat */\\n .tml-hat-1 {\\n transform: scale(1.9, 1.0)\\n }\\n .tml-hat-2 {\\n transform: scale(3.9, 1.0)\\n }\\n .tml-hat-3 {\\n transform: scale(5.8, 1.0)\\n }\\n .tml-hat-4 {\\n transform: scale(7.8, 1.0)\\n }\\n \\n /* set array cell justification */\\n .tml-right {\\n text-align: -webkit-right;\\n }\\n .tml-left {\\n text-align: -webkit-left;\\n }\\n}\\n\\n.special-fraction {\\n font-family: 'STIX TWO', 'Times New Roman', Times, Tinos, serif;\\n}\\n\\n/* flex-wrap for line-breaking in Chromium */\\nmath {\\n display: inline-flex;\\n flex-wrap: wrap;\\n align-items: baseline;\\n}\\nmath > mrow {\\n padding: 0.5ex 0ex;\\n}\\n\\n/* Default mtd top padding is 0.5ex per MathML-Core and user-agent CSS */\\n/* We adjust for jot and small */\\nmtable.tml-jot > mtr > mtd {\\n padding-top: 0.7ex;\\n padding-bottom: 0.7ex;\\n}\\nmtable.tml-small mtd {\\n padding-top: 0.35ex;\\n padding-bottom: 0.35ex;\\n}\\n\\n/* Firefox */\\n@-moz-document url-prefix() {\\n /* Avoid flex-wrap */\\n math { display: inline; }\\n math > mrow { padding: 0 }\\n /* Adjust Firefox spacing between array rows */\\n mtd, mtable.tml-small mtd { padding-top: 0; padding-bottom: 0; }\\n mtable.tml-jot > mtr > mtd { padding-top: 0.2ex; padding-bottom: 0.2ex; }\\n}\\n\\n/* AMS environment auto-numbering via CSS counter. */\\n.tml-eqn::before {\\n counter-increment: tmlEqnNo;\\n content: \\\"(\\\" counter(tmlEqnNo) \\\")\\\";\\n}\\n\";\n"],"mappings":";AAEO,IAAM,WACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inkbrick/react",
|
|
3
|
-
"version": "0.0.0
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "React bindings and the default UI for the Inkbrick block editor.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"src"
|
|
11
|
+
],
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"peerDependencies": {
|
|
14
|
+
"react": ">=18",
|
|
15
|
+
"react-dom": ">=18"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"temml": "^0.14.0",
|
|
19
|
+
"@inkbrick/document": "0.1.0-alpha.0",
|
|
20
|
+
"@inkbrick/engine": "0.1.0-alpha.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@testing-library/dom": "^10.4.1",
|
|
24
|
+
"@testing-library/react": "^16.3.2",
|
|
25
|
+
"jsdom": "^29.1.1",
|
|
26
|
+
"react": "^19.2.0",
|
|
27
|
+
"react-dom": "^19.2.0"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/CyberWizard6090/Inkbrick.git",
|
|
36
|
+
"directory": "packages/react"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsup"
|
|
40
|
+
},
|
|
41
|
+
"module": "./dist/index.js",
|
|
42
|
+
"exports": {
|
|
43
|
+
".": {
|
|
44
|
+
"types": "./dist/index.d.ts",
|
|
45
|
+
"import": "./dist/index.js"
|
|
46
|
+
},
|
|
47
|
+
"./package.json": "./package.json"
|
|
48
|
+
}
|
|
6
49
|
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export type DropPosition = 'before' | 'after';
|
|
2
|
+
|
|
3
|
+
export interface BlockAnchor {
|
|
4
|
+
readonly blockId: string;
|
|
5
|
+
readonly x: number;
|
|
6
|
+
readonly y: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface DropIndicatorRect {
|
|
10
|
+
readonly left: number;
|
|
11
|
+
readonly top: number;
|
|
12
|
+
readonly width: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface DragState {
|
|
16
|
+
readonly blockId: string;
|
|
17
|
+
readonly targetId: string | null;
|
|
18
|
+
readonly position: DropPosition | null;
|
|
19
|
+
readonly indicator: DropIndicatorRect | null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface BlockHandleState {
|
|
23
|
+
readonly hover: BlockAnchor | null;
|
|
24
|
+
readonly menu: BlockAnchor | null;
|
|
25
|
+
readonly drag: DragState | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const IDLE: BlockHandleState = Object.freeze({ hover: null, menu: null, drag: null });
|
|
29
|
+
|
|
30
|
+
const sameAnchor = (a: BlockAnchor | null, b: BlockAnchor | null) =>
|
|
31
|
+
a === b || (!!a && !!b && a.blockId === b.blockId && a.x === b.x && a.y === b.y);
|
|
32
|
+
|
|
33
|
+
export class BlockHandleController {
|
|
34
|
+
private state: BlockHandleState = IDLE;
|
|
35
|
+
|
|
36
|
+
private readonly listeners = new Set<() => void>();
|
|
37
|
+
|
|
38
|
+
getState = (): BlockHandleState => this.state;
|
|
39
|
+
|
|
40
|
+
subscribe = (listener: () => void): (() => void) => {
|
|
41
|
+
this.listeners.add(listener);
|
|
42
|
+
|
|
43
|
+
return () => {
|
|
44
|
+
this.listeners.delete(listener);
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
setHover(hover: BlockAnchor | null): void {
|
|
49
|
+
if (!sameAnchor(this.state.hover, hover)) this.set({ ...this.state, hover });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
openMenu(menu: BlockAnchor): void {
|
|
53
|
+
this.set({ ...this.state, menu });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
closeMenu(): void {
|
|
57
|
+
if (this.state.menu) this.set({ ...this.state, menu: null });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
startDrag(blockId: string): void {
|
|
61
|
+
this.set({
|
|
62
|
+
...this.state,
|
|
63
|
+
menu: null,
|
|
64
|
+
drag: { blockId, targetId: null, position: null, indicator: null },
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
updateDrag(patch: Partial<Omit<DragState, 'blockId'>>): void {
|
|
69
|
+
const drag = this.state.drag;
|
|
70
|
+
|
|
71
|
+
if (!drag) return;
|
|
72
|
+
|
|
73
|
+
const next = { ...drag, ...patch };
|
|
74
|
+
const same =
|
|
75
|
+
next.targetId === drag.targetId &&
|
|
76
|
+
next.position === drag.position &&
|
|
77
|
+
next.indicator?.left === drag.indicator?.left &&
|
|
78
|
+
next.indicator?.top === drag.indicator?.top &&
|
|
79
|
+
next.indicator?.width === drag.indicator?.width;
|
|
80
|
+
|
|
81
|
+
if (!same) this.set({ ...this.state, drag: next });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
endDrag(): void {
|
|
85
|
+
if (this.state.drag) this.set({ ...this.state, drag: null });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private set(state: BlockHandleState): void {
|
|
89
|
+
this.state = state;
|
|
90
|
+
|
|
91
|
+
for (const listener of [...this.listeners]) listener();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { useEffect, useRef, useSyncExternalStore } from 'react';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
3
|
+
|
|
4
|
+
import { useEditor } from '../hooks/useEditor';
|
|
5
|
+
import { useEditorView } from '../hooks/useEditorView';
|
|
6
|
+
import { useReadOnly } from '../hooks/useReadOnly';
|
|
7
|
+
import { useEditorUI } from '../ui/EditorUIContext';
|
|
8
|
+
import { addBlockBelow, buildBlockActions } from './actions';
|
|
9
|
+
import { DefaultBlockHandle } from './DefaultBlockHandle';
|
|
10
|
+
import { DefaultBlockMenu } from './DefaultBlockMenu';
|
|
11
|
+
import { startGripGesture } from './gripGesture';
|
|
12
|
+
import type { GripProps } from './types';
|
|
13
|
+
import { useBlockDrag } from './useBlockDrag';
|
|
14
|
+
|
|
15
|
+
const GRIP_STYLE = Object.freeze({ touchAction: 'none' as const });
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Ручка блока и меню действий. `slots.BlockHandle = null` отключает их вместе со встроенным перетаскиванием;
|
|
19
|
+
* линию вставки рисует DropIndicatorHost, поэтому свой DnD через `useBlockDrag` работает и без ручек.
|
|
20
|
+
*/
|
|
21
|
+
export function BlockHandleHost() {
|
|
22
|
+
const editor = useEditor();
|
|
23
|
+
const view = useEditorView();
|
|
24
|
+
const drag = useBlockDrag();
|
|
25
|
+
const { slots, slashItems, t } = useEditorUI();
|
|
26
|
+
const readOnly = useReadOnly();
|
|
27
|
+
const state = useSyncExternalStore(
|
|
28
|
+
view.blocks.subscribe,
|
|
29
|
+
view.blocks.getState,
|
|
30
|
+
view.blocks.getState,
|
|
31
|
+
);
|
|
32
|
+
const cleanup = useRef<(() => void) | null>(null);
|
|
33
|
+
|
|
34
|
+
// Не оставляем слушателей, если компонент исчез посреди перетаскивания.
|
|
35
|
+
useEffect(() => () => cleanup.current?.(), []);
|
|
36
|
+
|
|
37
|
+
if (slots.BlockHandle === null || readOnly || typeof document === 'undefined') return null;
|
|
38
|
+
|
|
39
|
+
const { hover, menu } = state;
|
|
40
|
+
const dragging = state.drag;
|
|
41
|
+
|
|
42
|
+
const openMenuFor = (blockId: string) => {
|
|
43
|
+
const anchor = view.blocks.getState().hover ?? hover;
|
|
44
|
+
|
|
45
|
+
if (anchor) view.blocks.openMenu({ blockId, x: anchor.x, y: anchor.y + 30 });
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const gripPropsFor = (blockId: string): GripProps => ({
|
|
49
|
+
onPointerDown: (event) => {
|
|
50
|
+
if (event.button !== 0) return;
|
|
51
|
+
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
cleanup.current?.();
|
|
54
|
+
|
|
55
|
+
const anchor = hover;
|
|
56
|
+
const cancel = startGripGesture(drag, blockId, event.nativeEvent, {
|
|
57
|
+
onTap: () => {
|
|
58
|
+
cleanup.current = null;
|
|
59
|
+
if (anchor) view.blocks.openMenu({ blockId, x: anchor.x, y: anchor.y + 30 });
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
cleanup.current = cancel;
|
|
64
|
+
},
|
|
65
|
+
onContextMenu: (event) => event.preventDefault(),
|
|
66
|
+
style: GRIP_STYLE,
|
|
67
|
+
'data-inkbrick-grip': '',
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const Handle = slots.BlockHandle ?? DefaultBlockHandle;
|
|
71
|
+
const Menu = slots.BlockMenu ?? DefaultBlockMenu;
|
|
72
|
+
const activeId = dragging?.blockId ?? hover?.blockId;
|
|
73
|
+
|
|
74
|
+
const menuBlock = menu ? editor.store.getBlock(menu.blockId) : undefined;
|
|
75
|
+
const menuContent =
|
|
76
|
+
menu && menuBlock ? buildBlockActions(editor, view, menu.blockId, slashItems, t) : null;
|
|
77
|
+
|
|
78
|
+
return createPortal(
|
|
79
|
+
<>
|
|
80
|
+
{hover && activeId && (
|
|
81
|
+
<Handle
|
|
82
|
+
blockId={activeId}
|
|
83
|
+
position={{ x: hover.x, y: hover.y }}
|
|
84
|
+
canAdd={editor.can('insertBlock', { flavour: 'block:paragraph', afterId: activeId })}
|
|
85
|
+
dragging={!!dragging}
|
|
86
|
+
menuOpen={!!menu}
|
|
87
|
+
onAdd={() => addBlockBelow(editor, view, activeId, slashItems)}
|
|
88
|
+
onOpenMenu={() => openMenuFor(activeId)}
|
|
89
|
+
gripProps={gripPropsFor(activeId)}
|
|
90
|
+
/>
|
|
91
|
+
)}
|
|
92
|
+
|
|
93
|
+
{menu && menuBlock && menuContent && (
|
|
94
|
+
<Menu
|
|
95
|
+
block={menuBlock}
|
|
96
|
+
position={{ x: menu.x, y: menu.y }}
|
|
97
|
+
actions={menuContent.actions}
|
|
98
|
+
turnInto={menuContent.turnInto}
|
|
99
|
+
onClose={() => {
|
|
100
|
+
view.blocks.closeMenu();
|
|
101
|
+
view.getRoot()?.focus({ preventScroll: true });
|
|
102
|
+
}}
|
|
103
|
+
/>
|
|
104
|
+
)}
|
|
105
|
+
</>,
|
|
106
|
+
document.body,
|
|
107
|
+
);
|
|
108
|
+
}
|