@docmentis/udoc-editor 0.0.1 → 0.8.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/LICENSE-APACHE +202 -0
- package/LICENSE-MIT +21 -0
- package/README.md +48 -0
- package/dist/arrange.d.ts +37 -0
- package/dist/arrange.d.ts.map +1 -0
- package/dist/arrange.js +431 -0
- package/dist/arrange.js.map +1 -0
- package/dist/clipboard.d.ts +12 -0
- package/dist/clipboard.d.ts.map +1 -0
- package/dist/clipboard.js +101 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/commands.d.ts +12 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +225 -0
- package/dist/commands.js.map +1 -0
- package/dist/components/ComboBox.d.ts +38 -0
- package/dist/components/ComboBox.d.ts.map +1 -0
- package/dist/components/ComboBox.js +57 -0
- package/dist/components/ComboBox.js.map +1 -0
- package/dist/components/ModeSwitch.d.ts +15 -0
- package/dist/components/ModeSwitch.d.ts.map +1 -0
- package/dist/components/ModeSwitch.js +94 -0
- package/dist/components/ModeSwitch.js.map +1 -0
- package/dist/components/NewSlideModal.d.ts +41 -0
- package/dist/components/NewSlideModal.d.ts.map +1 -0
- package/dist/components/NewSlideModal.js +136 -0
- package/dist/components/NewSlideModal.js.map +1 -0
- package/dist/components/PageControls.d.ts +78 -0
- package/dist/components/PageControls.d.ts.map +1 -0
- package/dist/components/PageControls.js +201 -0
- package/dist/components/PageControls.js.map +1 -0
- package/dist/components/PageSettingsModal.d.ts +27 -0
- package/dist/components/PageSettingsModal.d.ts.map +1 -0
- package/dist/components/PageSettingsModal.js +273 -0
- package/dist/components/PageSettingsModal.js.map +1 -0
- package/dist/components/PaintOptionsModal.d.ts +19 -0
- package/dist/components/PaintOptionsModal.d.ts.map +1 -0
- package/dist/components/PaintOptionsModal.js +103 -0
- package/dist/components/PaintOptionsModal.js.map +1 -0
- package/dist/components/TextControls.d.ts +49 -0
- package/dist/components/TextControls.d.ts.map +1 -0
- package/dist/components/TextControls.js +452 -0
- package/dist/components/TextControls.js.map +1 -0
- package/dist/context-menu.d.ts +46 -0
- package/dist/context-menu.d.ts.map +1 -0
- package/dist/context-menu.js +144 -0
- package/dist/context-menu.js.map +1 -0
- package/dist/edit-client.d.ts +121 -0
- package/dist/edit-client.d.ts.map +1 -0
- package/dist/edit-client.js +154 -0
- package/dist/edit-client.js.map +1 -0
- package/dist/edit-command.d.ts +7 -0
- package/dist/edit-command.d.ts.map +1 -0
- package/dist/edit-command.js +18 -0
- package/dist/edit-command.js.map +1 -0
- package/dist/edit-mode.d.ts +19 -0
- package/dist/edit-mode.d.ts.map +1 -0
- package/dist/edit-mode.js +214 -0
- package/dist/edit-mode.js.map +1 -0
- package/dist/editor.d.ts +101 -0
- package/dist/editor.d.ts.map +1 -0
- package/dist/editor.js +101 -0
- package/dist/editor.js.map +1 -0
- package/dist/fonts/faces.d.ts +28 -0
- package/dist/fonts/faces.d.ts.map +1 -0
- package/dist/fonts/faces.js +38 -0
- package/dist/fonts/faces.js.map +1 -0
- package/dist/fonts/preview.d.ts +98 -0
- package/dist/fonts/preview.d.ts.map +1 -0
- package/dist/fonts/preview.js +149 -0
- package/dist/fonts/preview.js.map +1 -0
- package/dist/formatting-marks.d.ts +23 -0
- package/dist/formatting-marks.d.ts.map +1 -0
- package/dist/formatting-marks.js +55 -0
- package/dist/formatting-marks.js.map +1 -0
- package/dist/grips.d.ts +14 -0
- package/dist/grips.d.ts.map +1 -0
- package/dist/grips.js +459 -0
- package/dist/grips.js.map +1 -0
- package/dist/i18n/ar.d.ts +4 -0
- package/dist/i18n/ar.d.ts.map +1 -0
- package/dist/i18n/ar.js +175 -0
- package/dist/i18n/ar.js.map +1 -0
- package/dist/i18n/de.d.ts +4 -0
- package/dist/i18n/de.d.ts.map +1 -0
- package/dist/i18n/de.js +175 -0
- package/dist/i18n/de.js.map +1 -0
- package/dist/i18n/en.d.ts +5 -0
- package/dist/i18n/en.d.ts.map +1 -0
- package/dist/i18n/en.js +176 -0
- package/dist/i18n/en.js.map +1 -0
- package/dist/i18n/es.d.ts +4 -0
- package/dist/i18n/es.d.ts.map +1 -0
- package/dist/i18n/es.js +175 -0
- package/dist/i18n/es.js.map +1 -0
- package/dist/i18n/fr.d.ts +4 -0
- package/dist/i18n/fr.d.ts.map +1 -0
- package/dist/i18n/fr.js +175 -0
- package/dist/i18n/fr.js.map +1 -0
- package/dist/i18n/index.d.ts +21 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +42 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/ja.d.ts +4 -0
- package/dist/i18n/ja.d.ts.map +1 -0
- package/dist/i18n/ja.js +175 -0
- package/dist/i18n/ja.js.map +1 -0
- package/dist/i18n/ko.d.ts +4 -0
- package/dist/i18n/ko.d.ts.map +1 -0
- package/dist/i18n/ko.js +175 -0
- package/dist/i18n/ko.js.map +1 -0
- package/dist/i18n/messages.d.ts +316 -0
- package/dist/i18n/messages.d.ts.map +1 -0
- package/dist/i18n/messages.js +2 -0
- package/dist/i18n/messages.js.map +1 -0
- package/dist/i18n/pt-BR.d.ts +4 -0
- package/dist/i18n/pt-BR.d.ts.map +1 -0
- package/dist/i18n/pt-BR.js +175 -0
- package/dist/i18n/pt-BR.js.map +1 -0
- package/dist/i18n/ru.d.ts +4 -0
- package/dist/i18n/ru.d.ts.map +1 -0
- package/dist/i18n/ru.js +175 -0
- package/dist/i18n/ru.js.map +1 -0
- package/dist/i18n/zh-CN.d.ts +4 -0
- package/dist/i18n/zh-CN.d.ts.map +1 -0
- package/dist/i18n/zh-CN.js +175 -0
- package/dist/i18n/zh-CN.js.map +1 -0
- package/dist/i18n/zh-TW.d.ts +4 -0
- package/dist/i18n/zh-TW.d.ts.map +1 -0
- package/dist/i18n/zh-TW.js +175 -0
- package/dist/i18n/zh-TW.js.map +1 -0
- package/dist/icons.d.ts +97 -0
- package/dist/icons.d.ts.map +1 -0
- package/dist/icons.js +103 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/insert.d.ts +21 -0
- package/dist/insert.d.ts.map +1 -0
- package/dist/insert.js +129 -0
- package/dist/insert.js.map +1 -0
- package/dist/menu-action.d.ts +73 -0
- package/dist/menu-action.d.ts.map +1 -0
- package/dist/menu-action.js +89 -0
- package/dist/menu-action.js.map +1 -0
- package/dist/mode.d.ts +21 -0
- package/dist/mode.d.ts.map +1 -0
- package/dist/mode.js +17 -0
- package/dist/mode.js.map +1 -0
- package/dist/new-slide.d.ts +21 -0
- package/dist/new-slide.d.ts.map +1 -0
- package/dist/new-slide.js +63 -0
- package/dist/new-slide.js.map +1 -0
- package/dist/page-controls.d.ts +20 -0
- package/dist/page-controls.d.ts.map +1 -0
- package/dist/page-controls.js +99 -0
- package/dist/page-controls.js.map +1 -0
- package/dist/paint.d.ts +52 -0
- package/dist/paint.d.ts.map +1 -0
- package/dist/paint.js +262 -0
- package/dist/paint.js.map +1 -0
- package/dist/ruler.d.ts +10 -0
- package/dist/ruler.d.ts.map +1 -0
- package/dist/ruler.js +97 -0
- package/dist/ruler.js.map +1 -0
- package/dist/state.d.ts +85 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +28 -0
- package/dist/state.js.map +1 -0
- package/dist/styles.d.ts +2 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +758 -0
- package/dist/styles.js.map +1 -0
- package/dist/tabs.d.ts +11 -0
- package/dist/tabs.d.ts.map +1 -0
- package/dist/tabs.js +153 -0
- package/dist/tabs.js.map +1 -0
- package/dist/text-format.d.ts +114 -0
- package/dist/text-format.d.ts.map +1 -0
- package/dist/text-format.js +315 -0
- package/dist/text-format.js.map +1 -0
- package/dist/tools.d.ts +35 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +41 -0
- package/dist/tools.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +7 -0
- package/dist/version.js.map +1 -0
- package/dist/worker/handlers.d.ts +11 -0
- package/dist/worker/handlers.d.ts.map +1 -0
- package/dist/worker/handlers.js +127 -0
- package/dist/worker/handlers.js.map +1 -0
- package/dist/worker/protocol.d.ts +190 -0
- package/dist/worker/protocol.d.ts.map +1 -0
- package/dist/worker/protocol.js +2 -0
- package/dist/worker/protocol.js.map +1 -0
- package/dist/worker/worker-source.d.ts +3 -0
- package/dist/worker/worker-source.d.ts.map +1 -0
- package/dist/worker/worker-source.js +11 -0
- package/dist/worker/worker.d.ts +2 -0
- package/dist/worker/worker.d.ts.map +1 -0
- package/dist/worker/worker.js +6 -0
- package/dist/worker/worker.js.map +1 -0
- package/package.json +68 -5
package/dist/arrange.js
ADDED
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
// Arrange: the Shape and Object tabs' Arrange menus — z-order, align and
|
|
2
|
+
// distribute, rotate and flip, group — and the edits they make of the
|
|
3
|
+
// selection.
|
|
4
|
+
import { allowsEdit } from "@docmentis/udoc-ui/internal";
|
|
5
|
+
import { ICON_ALIGN_BOTTOM, ICON_ALIGN_CENTER_H, ICON_ALIGN_LEFT, ICON_ALIGN_MIDDLE_V, ICON_ALIGN_RIGHT, ICON_ALIGN_TOP, ICON_BRING_FORWARD, ICON_BRING_TO_FRONT, ICON_DISTRIBUTE_H, ICON_DISTRIBUTE_V, ICON_FLIP, ICON_GROUP, ICON_ORDER, ICON_ROTATE_LEFT, ICON_ROTATE_RIGHT, ICON_SEND_BACKWARD, ICON_SEND_TO_BACK, ICON_UNGROUP, } from "./icons.js";
|
|
6
|
+
import { editAction } from "./menu-action.js";
|
|
7
|
+
import { editState, editStateOf } from "./state.js";
|
|
8
|
+
/** A quarter turn in radians — the Rotate dropdown's 90° steps. Document space is
|
|
9
|
+
* y-down, so a positive angle reads as clockwise on screen. */
|
|
10
|
+
const QUARTER_TURN = Math.PI / 2;
|
|
11
|
+
/** `icon` given a quarter turn — Flip Vertical's glyph: Material Symbols draws
|
|
12
|
+
* the mirror about an upright axis only, so the horizontal one lies it down. */
|
|
13
|
+
function quarterTurned(icon) {
|
|
14
|
+
return icon.replace("<svg ", '<svg style="transform: rotate(90deg)" ');
|
|
15
|
+
}
|
|
16
|
+
/** True when any item in `items` is enabled — the enablement of a submenu row
|
|
17
|
+
* (and of an Arrange trigger), which lights up exactly when it has a live
|
|
18
|
+
* child to offer. */
|
|
19
|
+
const anyEnabled = (items) => (c) => items.some((i) => i.enabledWhen(c));
|
|
20
|
+
/**
|
|
21
|
+
* The Order submenu: z-order moves ordered front→back (top of menu = top of the
|
|
22
|
+
* stack). Lives under the Shape tab's Arrange ▸ Order.
|
|
23
|
+
*/
|
|
24
|
+
const SHAPE_ORDER_MENU = [
|
|
25
|
+
// All four moves share one precondition (`reorderShapes`): the engine reports it
|
|
26
|
+
// live when the selection isn't already the contiguous front-and-back block,
|
|
27
|
+
// so if no move would change anything the whole submenu greys out together.
|
|
28
|
+
{
|
|
29
|
+
action: editAction({ kind: "reorder", order: "front" }),
|
|
30
|
+
label: "arrange.bringToFront",
|
|
31
|
+
icon: ICON_BRING_TO_FRONT,
|
|
32
|
+
enabledWhen: (c) => allowsEdit(c.selection, "reorderShapes"),
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
action: editAction({ kind: "reorder", order: "forward" }),
|
|
36
|
+
label: "arrange.bringForward",
|
|
37
|
+
icon: ICON_BRING_FORWARD,
|
|
38
|
+
enabledWhen: (c) => allowsEdit(c.selection, "reorderShapes"),
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
action: editAction({ kind: "reorder", order: "backward" }),
|
|
42
|
+
label: "arrange.sendBackward",
|
|
43
|
+
icon: ICON_SEND_BACKWARD,
|
|
44
|
+
enabledWhen: (c) => allowsEdit(c.selection, "reorderShapes"),
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
action: editAction({ kind: "reorder", order: "back" }),
|
|
48
|
+
label: "arrange.sendToBack",
|
|
49
|
+
icon: ICON_SEND_TO_BACK,
|
|
50
|
+
enabledWhen: (c) => allowsEdit(c.selection, "reorderShapes"),
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
/** Whether the selected shapes can be aligned to `edge`: aligning to the slide
|
|
54
|
+
* needs one shape, aligning to the selection's own bounds needs two (a lone box
|
|
55
|
+
* is already its own union). Both need the shapes to be movable. */
|
|
56
|
+
const canAlignShapes = (c) => allowsEdit(c.selection, "translateShapes") && c.selection.count >= (editStateOf(c).alignToPage ? 1 : 2);
|
|
57
|
+
/**
|
|
58
|
+
* The Align dropdown: the six edge/center alignments, the two distributions
|
|
59
|
+
* below a divider, then the page/slide reference toggle. The toggle flips
|
|
60
|
+
* whether the edges align to the page or to the selection's own bounds.
|
|
61
|
+
*/
|
|
62
|
+
const SHAPE_ALIGN_MENU = [
|
|
63
|
+
{
|
|
64
|
+
action: editAction({ kind: "align", edge: "left" }),
|
|
65
|
+
label: "arrange.alignLeft",
|
|
66
|
+
icon: ICON_ALIGN_LEFT,
|
|
67
|
+
enabledWhen: canAlignShapes,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
action: editAction({ kind: "align", edge: "centerX" }),
|
|
71
|
+
label: "arrange.alignCenter",
|
|
72
|
+
icon: ICON_ALIGN_CENTER_H,
|
|
73
|
+
enabledWhen: canAlignShapes,
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
action: editAction({ kind: "align", edge: "right" }),
|
|
77
|
+
label: "arrange.alignRight",
|
|
78
|
+
icon: ICON_ALIGN_RIGHT,
|
|
79
|
+
enabledWhen: canAlignShapes,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
action: editAction({ kind: "align", edge: "top" }),
|
|
83
|
+
label: "arrange.alignTop",
|
|
84
|
+
icon: ICON_ALIGN_TOP,
|
|
85
|
+
enabledWhen: canAlignShapes,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
action: editAction({ kind: "align", edge: "centerY" }),
|
|
89
|
+
label: "arrange.alignMiddle",
|
|
90
|
+
icon: ICON_ALIGN_MIDDLE_V,
|
|
91
|
+
enabledWhen: canAlignShapes,
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
action: editAction({ kind: "align", edge: "bottom" }),
|
|
95
|
+
label: "arrange.alignBottom",
|
|
96
|
+
icon: ICON_ALIGN_BOTTOM,
|
|
97
|
+
enabledWhen: canAlignShapes,
|
|
98
|
+
},
|
|
99
|
+
// Distribute equalizes gaps, so it needs three boxes to have an inner one to move.
|
|
100
|
+
{
|
|
101
|
+
action: editAction({ kind: "distribute", axis: "horizontal" }),
|
|
102
|
+
label: "arrange.distributeHorizontally",
|
|
103
|
+
icon: ICON_DISTRIBUTE_H,
|
|
104
|
+
enabledWhen: (c) => allowsEdit(c.selection, "translateShapes") && c.selection.count >= 3,
|
|
105
|
+
separatorBefore: true,
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
action: editAction({ kind: "distribute", axis: "vertical" }),
|
|
109
|
+
label: "arrange.distributeVertically",
|
|
110
|
+
icon: ICON_DISTRIBUTE_V,
|
|
111
|
+
enabledWhen: (c) => allowsEdit(c.selection, "translateShapes") && c.selection.count >= 3,
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
action: editAction({ kind: "alignToPage" }),
|
|
115
|
+
label: "arrange.alignToPage",
|
|
116
|
+
enabledWhen: (c) => c.ready,
|
|
117
|
+
separatorBefore: true,
|
|
118
|
+
checked: (c) => editStateOf(c).alignToPage,
|
|
119
|
+
keepsOpen: true,
|
|
120
|
+
},
|
|
121
|
+
];
|
|
122
|
+
/**
|
|
123
|
+
* The Rotate dropdown: quarter-turn rotations, then the two mirror flips below a
|
|
124
|
+
* divider. Each acts on every selected object in place (about its own center).
|
|
125
|
+
*/
|
|
126
|
+
const SHAPE_ROTATE_MENU = [
|
|
127
|
+
{
|
|
128
|
+
action: editAction({ kind: "rotate", angle: QUARTER_TURN }),
|
|
129
|
+
label: "arrange.rotateRight",
|
|
130
|
+
icon: ICON_ROTATE_RIGHT,
|
|
131
|
+
enabledWhen: (c) => allowsEdit(c.selection, "rotateEachShape"),
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
action: editAction({ kind: "rotate", angle: -QUARTER_TURN }),
|
|
135
|
+
label: "arrange.rotateLeft",
|
|
136
|
+
icon: ICON_ROTATE_LEFT,
|
|
137
|
+
enabledWhen: (c) => allowsEdit(c.selection, "rotateEachShape"),
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
action: editAction({ kind: "flip", axis: "horizontal" }),
|
|
141
|
+
label: "arrange.flipHorizontal",
|
|
142
|
+
icon: ICON_FLIP,
|
|
143
|
+
enabledWhen: (c) => allowsEdit(c.selection, "scaleEachShape"),
|
|
144
|
+
separatorBefore: true,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
action: editAction({ kind: "flip", axis: "vertical" }),
|
|
148
|
+
label: "arrange.flipVertical",
|
|
149
|
+
icon: quarterTurned(ICON_FLIP),
|
|
150
|
+
enabledWhen: (c) => allowsEdit(c.selection, "scaleEachShape"),
|
|
151
|
+
},
|
|
152
|
+
];
|
|
153
|
+
/**
|
|
154
|
+
* The Shape tab's Arrange dropdown: the arrangement submenus — Order (z-order),
|
|
155
|
+
* Align (align / distribute), and Rotate (rotate / flip) as fly-outs — then the
|
|
156
|
+
* grouping pair below a divider. Consolidates what used to be three sibling
|
|
157
|
+
* toolbar buttons into one, matching the Office/Slides "Arrange" menu.
|
|
158
|
+
*
|
|
159
|
+
* Align's row uses {@link canAlignShapes} rather than `anyEnabled(SHAPE_ALIGN_MENU)` because
|
|
160
|
+
* the submenu's always-on "Align to page" toggle would otherwise light the row
|
|
161
|
+
* up with nothing aligned — the same guard the old Align button carried.
|
|
162
|
+
*/
|
|
163
|
+
export const SHAPE_ARRANGE_MENU = [
|
|
164
|
+
{ submenu: SHAPE_ORDER_MENU, label: "arrange.order", icon: ICON_ORDER, enabledWhen: anyEnabled(SHAPE_ORDER_MENU) },
|
|
165
|
+
{ submenu: SHAPE_ALIGN_MENU, label: "arrange.align", icon: ICON_ALIGN_LEFT, enabledWhen: canAlignShapes },
|
|
166
|
+
{
|
|
167
|
+
submenu: SHAPE_ROTATE_MENU,
|
|
168
|
+
label: "arrange.rotate",
|
|
169
|
+
icon: ICON_ROTATE_RIGHT,
|
|
170
|
+
enabledWhen: anyEnabled(SHAPE_ROTATE_MENU),
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
action: editAction({ kind: "group" }),
|
|
174
|
+
label: "arrange.group",
|
|
175
|
+
icon: ICON_GROUP,
|
|
176
|
+
enabledWhen: (c) => allowsEdit(c.selection, "groupShapes"),
|
|
177
|
+
separatorBefore: true,
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
action: editAction({ kind: "ungroup" }),
|
|
181
|
+
label: "arrange.ungroup",
|
|
182
|
+
icon: ICON_UNGROUP,
|
|
183
|
+
enabledWhen: (c) => allowsEdit(c.selection, "ungroupShapes"),
|
|
184
|
+
},
|
|
185
|
+
];
|
|
186
|
+
/**
|
|
187
|
+
* The Order submenu: z-order moves ordered front→back (top of menu = top of the
|
|
188
|
+
* stack). Lives under the Object tab's Arrange ▸ Order.
|
|
189
|
+
*/
|
|
190
|
+
const OBJECT_ORDER_MENU = [
|
|
191
|
+
// All four moves share one precondition (`reorderObjects`, or
|
|
192
|
+
// `reorderAnnotations` for selected annotations): the engine reports it live
|
|
193
|
+
// when the selection isn't already the contiguous front-and-back block, so if
|
|
194
|
+
// no move would change anything the whole submenu greys out together.
|
|
195
|
+
{
|
|
196
|
+
action: editAction({ kind: "reorder", order: "front" }),
|
|
197
|
+
label: "arrange.bringToFront",
|
|
198
|
+
icon: ICON_BRING_TO_FRONT,
|
|
199
|
+
enabledWhen: (c) => allowsEdit(c.selection, "reorderObjects", "reorderAnnotations"),
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
action: editAction({ kind: "reorder", order: "forward" }),
|
|
203
|
+
label: "arrange.bringForward",
|
|
204
|
+
icon: ICON_BRING_FORWARD,
|
|
205
|
+
enabledWhen: (c) => allowsEdit(c.selection, "reorderObjects", "reorderAnnotations"),
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
action: editAction({ kind: "reorder", order: "backward" }),
|
|
209
|
+
label: "arrange.sendBackward",
|
|
210
|
+
icon: ICON_SEND_BACKWARD,
|
|
211
|
+
enabledWhen: (c) => allowsEdit(c.selection, "reorderObjects", "reorderAnnotations"),
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
action: editAction({ kind: "reorder", order: "back" }),
|
|
215
|
+
label: "arrange.sendToBack",
|
|
216
|
+
icon: ICON_SEND_TO_BACK,
|
|
217
|
+
enabledWhen: (c) => allowsEdit(c.selection, "reorderObjects", "reorderAnnotations"),
|
|
218
|
+
},
|
|
219
|
+
];
|
|
220
|
+
/** Whether the selected objects can be aligned to `edge`: aligning to the page
|
|
221
|
+
* needs one object, aligning to the selection's own bounds needs two (a lone
|
|
222
|
+
* box is already its own union). Both need the objects to be movable. */
|
|
223
|
+
const canAlignObjects = (c) => allowsEdit(c.selection, "translateObjects") && c.selection.count >= (editStateOf(c).alignToPage ? 1 : 2);
|
|
224
|
+
/**
|
|
225
|
+
* The Align dropdown: the six edge/center alignments, the two distributions
|
|
226
|
+
* below a divider, then the page/slide reference toggle. The toggle flips
|
|
227
|
+
* whether the edges align to the page or to the selection's own bounds.
|
|
228
|
+
*/
|
|
229
|
+
const OBJECT_ALIGN_MENU = [
|
|
230
|
+
{
|
|
231
|
+
action: editAction({ kind: "align", edge: "left" }),
|
|
232
|
+
label: "arrange.alignLeft",
|
|
233
|
+
icon: ICON_ALIGN_LEFT,
|
|
234
|
+
enabledWhen: canAlignObjects,
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
action: editAction({ kind: "align", edge: "centerX" }),
|
|
238
|
+
label: "arrange.alignCenter",
|
|
239
|
+
icon: ICON_ALIGN_CENTER_H,
|
|
240
|
+
enabledWhen: canAlignObjects,
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
action: editAction({ kind: "align", edge: "right" }),
|
|
244
|
+
label: "arrange.alignRight",
|
|
245
|
+
icon: ICON_ALIGN_RIGHT,
|
|
246
|
+
enabledWhen: canAlignObjects,
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
action: editAction({ kind: "align", edge: "top" }),
|
|
250
|
+
label: "arrange.alignTop",
|
|
251
|
+
icon: ICON_ALIGN_TOP,
|
|
252
|
+
enabledWhen: canAlignObjects,
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
action: editAction({ kind: "align", edge: "centerY" }),
|
|
256
|
+
label: "arrange.alignMiddle",
|
|
257
|
+
icon: ICON_ALIGN_MIDDLE_V,
|
|
258
|
+
enabledWhen: canAlignObjects,
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
action: editAction({ kind: "align", edge: "bottom" }),
|
|
262
|
+
label: "arrange.alignBottom",
|
|
263
|
+
icon: ICON_ALIGN_BOTTOM,
|
|
264
|
+
enabledWhen: canAlignObjects,
|
|
265
|
+
},
|
|
266
|
+
// Distribute equalizes gaps, so it needs three boxes to have an inner one to move.
|
|
267
|
+
{
|
|
268
|
+
action: editAction({ kind: "distribute", axis: "horizontal" }),
|
|
269
|
+
label: "arrange.distributeHorizontally",
|
|
270
|
+
icon: ICON_DISTRIBUTE_H,
|
|
271
|
+
enabledWhen: (c) => allowsEdit(c.selection, "translateObjects") && c.selection.count >= 3,
|
|
272
|
+
separatorBefore: true,
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
action: editAction({ kind: "distribute", axis: "vertical" }),
|
|
276
|
+
label: "arrange.distributeVertically",
|
|
277
|
+
icon: ICON_DISTRIBUTE_V,
|
|
278
|
+
enabledWhen: (c) => allowsEdit(c.selection, "translateObjects") && c.selection.count >= 3,
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
action: editAction({ kind: "alignToPage" }),
|
|
282
|
+
label: "arrange.alignToPage",
|
|
283
|
+
enabledWhen: (c) => c.ready,
|
|
284
|
+
separatorBefore: true,
|
|
285
|
+
checked: (c) => editStateOf(c).alignToPage,
|
|
286
|
+
keepsOpen: true,
|
|
287
|
+
},
|
|
288
|
+
];
|
|
289
|
+
/**
|
|
290
|
+
* The Rotate dropdown: quarter-turn rotations, then the two mirror flips below a
|
|
291
|
+
* divider. Each acts on every selected object in place (about its own center).
|
|
292
|
+
*/
|
|
293
|
+
const OBJECT_ROTATE_MENU = [
|
|
294
|
+
{
|
|
295
|
+
action: editAction({ kind: "rotate", angle: QUARTER_TURN }),
|
|
296
|
+
label: "arrange.rotateRight",
|
|
297
|
+
icon: ICON_ROTATE_RIGHT,
|
|
298
|
+
enabledWhen: (c) => allowsEdit(c.selection, "rotateEachObject"),
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
action: editAction({ kind: "rotate", angle: -QUARTER_TURN }),
|
|
302
|
+
label: "arrange.rotateLeft",
|
|
303
|
+
icon: ICON_ROTATE_LEFT,
|
|
304
|
+
enabledWhen: (c) => allowsEdit(c.selection, "rotateEachObject"),
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
action: editAction({ kind: "flip", axis: "horizontal" }),
|
|
308
|
+
label: "arrange.flipHorizontal",
|
|
309
|
+
icon: ICON_FLIP,
|
|
310
|
+
enabledWhen: (c) => allowsEdit(c.selection, "scaleEachObject"),
|
|
311
|
+
separatorBefore: true,
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
action: editAction({ kind: "flip", axis: "vertical" }),
|
|
315
|
+
label: "arrange.flipVertical",
|
|
316
|
+
icon: quarterTurned(ICON_FLIP),
|
|
317
|
+
enabledWhen: (c) => allowsEdit(c.selection, "scaleEachObject"),
|
|
318
|
+
},
|
|
319
|
+
];
|
|
320
|
+
/**
|
|
321
|
+
* The Object tab's Arrange dropdown: the arrangement submenus — Order (z-order),
|
|
322
|
+
* Align (align / distribute), and Rotate (rotate / flip) as fly-outs — then the
|
|
323
|
+
* grouping pair below a divider. Consolidates what used to be three sibling
|
|
324
|
+
* toolbar buttons into one, matching the Office/Slides "Arrange" menu.
|
|
325
|
+
*
|
|
326
|
+
* Align's row uses {@link canAlignObjects} rather than `anyEnabled(OBJECT_ALIGN_MENU)` because
|
|
327
|
+
* the submenu's always-on "Align to page" toggle would otherwise light the row
|
|
328
|
+
* up with nothing aligned — the same guard the old Align button carried.
|
|
329
|
+
*/
|
|
330
|
+
export const OBJECT_ARRANGE_MENU = [
|
|
331
|
+
{
|
|
332
|
+
submenu: OBJECT_ORDER_MENU,
|
|
333
|
+
label: "arrange.order",
|
|
334
|
+
icon: ICON_ORDER,
|
|
335
|
+
enabledWhen: anyEnabled(OBJECT_ORDER_MENU),
|
|
336
|
+
},
|
|
337
|
+
{ submenu: OBJECT_ALIGN_MENU, label: "arrange.align", icon: ICON_ALIGN_LEFT, enabledWhen: canAlignObjects },
|
|
338
|
+
{
|
|
339
|
+
submenu: OBJECT_ROTATE_MENU,
|
|
340
|
+
label: "arrange.rotate",
|
|
341
|
+
icon: ICON_ROTATE_RIGHT,
|
|
342
|
+
enabledWhen: anyEnabled(OBJECT_ROTATE_MENU),
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
action: editAction({ kind: "group" }),
|
|
346
|
+
label: "arrange.group",
|
|
347
|
+
icon: ICON_GROUP,
|
|
348
|
+
enabledWhen: (c) => allowsEdit(c.selection, "groupObjects"),
|
|
349
|
+
separatorBefore: true,
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
action: editAction({ kind: "ungroup" }),
|
|
353
|
+
label: "arrange.ungroup",
|
|
354
|
+
icon: ICON_UNGROUP,
|
|
355
|
+
enabledWhen: (c) => allowsEdit(c.selection, "ungroupObjects"),
|
|
356
|
+
},
|
|
357
|
+
];
|
|
358
|
+
/** The arrangement edits of the selection, on the shell `host` lends. */
|
|
359
|
+
export function createArrangeEdits(host) {
|
|
360
|
+
const { store, client, commit } = host;
|
|
361
|
+
const annotationsSelected = () => host.annotationsSelected();
|
|
362
|
+
// Each edit names what it acts on, as its command does: a drawing's shapes
|
|
363
|
+
// — in the doc types embedding the drawing families, a slide's shapes or a
|
|
364
|
+
// docx drawing's — or a PDF's page objects or annotations.
|
|
365
|
+
function shapeDocType() {
|
|
366
|
+
const docType = store.getState().docType;
|
|
367
|
+
return docType === "presentation" || docType === "wordprocessing";
|
|
368
|
+
}
|
|
369
|
+
function reorderSelection(order) {
|
|
370
|
+
let edit;
|
|
371
|
+
if (shapeDocType())
|
|
372
|
+
edit = { kind: "reorderShapes", order };
|
|
373
|
+
else if (annotationsSelected())
|
|
374
|
+
edit = { kind: "annotation", edit: { kind: "reorderAnnotations", order } };
|
|
375
|
+
else
|
|
376
|
+
edit = { kind: "object", edit: { kind: "reorderObjects", order } };
|
|
377
|
+
return commit(() => client.executeOnSelection(edit));
|
|
378
|
+
}
|
|
379
|
+
// Align reads the live `alignToPage` flag to pick its reference (the
|
|
380
|
+
// selection's own bounds vs. the page/slide); distribute and flip carry only
|
|
381
|
+
// their axis. All ride the agnostic `executeOnSelection` seam.
|
|
382
|
+
function alignSelection(edge) {
|
|
383
|
+
const toPage = editState(store.getState()).alignToPage;
|
|
384
|
+
const edit = shapeDocType()
|
|
385
|
+
? { kind: "alignShapes", edge, toPage }
|
|
386
|
+
: { kind: "object", edit: { kind: "alignObjects", edge, toPage } };
|
|
387
|
+
return commit(() => client.executeOnSelection(edit));
|
|
388
|
+
}
|
|
389
|
+
function distributeSelection(axis) {
|
|
390
|
+
const edit = shapeDocType()
|
|
391
|
+
? { kind: "distributeShapes", axis }
|
|
392
|
+
: { kind: "object", edit: { kind: "distributeObjects", axis } };
|
|
393
|
+
return commit(() => client.executeOnSelection(edit));
|
|
394
|
+
}
|
|
395
|
+
function flipSelection(axis) {
|
|
396
|
+
const edit = shapeDocType()
|
|
397
|
+
? { kind: "flipShapes", axis }
|
|
398
|
+
: { kind: "object", edit: { kind: "flipObjects", axis } };
|
|
399
|
+
return commit(() => client.executeOnSelection(edit));
|
|
400
|
+
}
|
|
401
|
+
function groupSelection() {
|
|
402
|
+
const edit = shapeDocType()
|
|
403
|
+
? { kind: "groupShapes" }
|
|
404
|
+
: { kind: "object", edit: { kind: "groupObjects" } };
|
|
405
|
+
return commit(() => client.executeOnSelection(edit));
|
|
406
|
+
}
|
|
407
|
+
function ungroupSelection() {
|
|
408
|
+
const edit = shapeDocType()
|
|
409
|
+
? { kind: "ungroupShapes" }
|
|
410
|
+
: { kind: "object", edit: { kind: "ungroupObjects" } };
|
|
411
|
+
return commit(() => client.executeOnSelection(edit));
|
|
412
|
+
}
|
|
413
|
+
// Turn each selected object by `angle` about its own center — the Rotate
|
|
414
|
+
// dropdown's quarter turns, and the rotation grip's drag.
|
|
415
|
+
function rotateSelectionEach(angle) {
|
|
416
|
+
const edit = shapeDocType()
|
|
417
|
+
? { kind: "rotateEachShape", angle }
|
|
418
|
+
: { kind: "object", edit: { kind: "rotateEachObject", angle } };
|
|
419
|
+
return commit(() => client.executeOnSelection(edit));
|
|
420
|
+
}
|
|
421
|
+
return {
|
|
422
|
+
reorderSelection,
|
|
423
|
+
alignSelection,
|
|
424
|
+
distributeSelection,
|
|
425
|
+
flipSelection,
|
|
426
|
+
groupSelection,
|
|
427
|
+
ungroupSelection,
|
|
428
|
+
rotateSelectionEach,
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
//# sourceMappingURL=arrange.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arrange.js","sourceRoot":"","sources":["../src/arrange.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { EditHost } from "./edit-client.js";
|
|
2
|
+
/** Edit mode's clipboard verbs, for a menu row — a keyboard cut or paste rides
|
|
3
|
+
* the native event on the sink instead, and a copy is the shell's. */
|
|
4
|
+
export interface Clipboard {
|
|
5
|
+
cut(): void;
|
|
6
|
+
paste(): Promise<void>;
|
|
7
|
+
/** Stop listening on the sink. */
|
|
8
|
+
destroy(): void;
|
|
9
|
+
}
|
|
10
|
+
/** The clipboard over `host`'s sink. */
|
|
11
|
+
export declare function createClipboard(host: EditHost): Clipboard;
|
|
12
|
+
//# sourceMappingURL=clipboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../src/clipboard.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD;uEACuE;AACvE,MAAM,WAAW,SAAS;IACtB,GAAG,IAAI,IAAI,CAAC;IACZ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,kCAAkC;IAClC,OAAO,IAAI,IAAI,CAAC;CACnB;AAED,wCAAwC;AACxC,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,CAgGzD"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { allowsEdit, fragmentFromHtml, parseFragment, UDOC_FRAGMENT_FORMAT } from "@docmentis/udoc-ui/internal";
|
|
2
|
+
/** The clipboard over `host`'s sink. */
|
|
3
|
+
export function createClipboard(host) {
|
|
4
|
+
const { edit } = host;
|
|
5
|
+
function isEditReady() {
|
|
6
|
+
const st = host.store.getState();
|
|
7
|
+
return st.status === "ready" && st.mode === "edit";
|
|
8
|
+
}
|
|
9
|
+
// The native `cut`: copy, then delete — but only when the selection is
|
|
10
|
+
// deletable (cut = copy + delete), and only once something was copied. A
|
|
11
|
+
// copyable-but-locked object is copied without being removed.
|
|
12
|
+
function onCutEvent(event) {
|
|
13
|
+
if (!isEditReady())
|
|
14
|
+
return;
|
|
15
|
+
const deletable = allowsEdit(host.store.getState().selectionCaps, "deleteObjects", "deleteAnnotations", "deleteShapes");
|
|
16
|
+
void host.clipboard.write(event).then((copied) => {
|
|
17
|
+
if (copied && deletable)
|
|
18
|
+
void host.deleteSelection();
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
// The native `paste`: read the clipboard (the source of truth). Prefer our own
|
|
22
|
+
// flavor, then the fragment in the HTML envelope (what a clipboard written by
|
|
23
|
+
// the copy's async fallback carries — it has no custom format); else fall
|
|
24
|
+
// through to `text/plain`, which routes to the text caret when one is live and
|
|
25
|
+
// is otherwise a no-op (a text box from a string is a later increment).
|
|
26
|
+
function onPasteEvent(event) {
|
|
27
|
+
if (!isEditReady())
|
|
28
|
+
return;
|
|
29
|
+
event.preventDefault();
|
|
30
|
+
const data = event.clipboardData;
|
|
31
|
+
if (!data)
|
|
32
|
+
return;
|
|
33
|
+
const own = parseFragment(data.getData(UDOC_FRAGMENT_FORMAT)) ?? fragmentFromHtml(data.getData("text/html"));
|
|
34
|
+
if (own) {
|
|
35
|
+
void host.commit(() => edit.paste(own));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const text = data.getData("text/plain");
|
|
39
|
+
if (text)
|
|
40
|
+
void host.insertSelectionText(text);
|
|
41
|
+
}
|
|
42
|
+
// The context menu's Cut row: a click fires no native clipboard event, so
|
|
43
|
+
// re-enter the native path — focus the sink and let `execCommand` dispatch a
|
|
44
|
+
// synthetic cut the handler catches (custom format and all, on every
|
|
45
|
+
// browser).
|
|
46
|
+
function menuCut() {
|
|
47
|
+
if (!isEditReady())
|
|
48
|
+
return;
|
|
49
|
+
host.focusClipboardSink();
|
|
50
|
+
document.execCommand("cut");
|
|
51
|
+
}
|
|
52
|
+
// The menu's Paste row can't trigger a native paste (`execCommand("paste")` is
|
|
53
|
+
// blocked), so it reads the clipboard asynchronously. That read can't see our
|
|
54
|
+
// custom format (see the flavor note in udoc-ui's clipboard) — it recovers
|
|
55
|
+
// the fragment from the HTML envelope, which is exactly why the envelope
|
|
56
|
+
// exists. Prefers our fragment, else routes text to the caret.
|
|
57
|
+
//
|
|
58
|
+
// Still not the equal of Ctrl/Cmd+V: the read is permission-gated, and Safari
|
|
59
|
+
// fronts it with its own paste-confirmation UI. It pastes the same object,
|
|
60
|
+
// just not as quietly.
|
|
61
|
+
async function menuPaste() {
|
|
62
|
+
if (!isEditReady())
|
|
63
|
+
return;
|
|
64
|
+
let fragment = null;
|
|
65
|
+
let text = "";
|
|
66
|
+
try {
|
|
67
|
+
for (const item of await navigator.clipboard.read()) {
|
|
68
|
+
if (!fragment && item.types.includes("text/html")) {
|
|
69
|
+
fragment = fragmentFromHtml(await (await item.getType("text/html")).text());
|
|
70
|
+
}
|
|
71
|
+
if (!text && item.types.includes("text/plain")) {
|
|
72
|
+
text = await (await item.getType("text/plain")).text();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return; // read unsupported / denied
|
|
78
|
+
}
|
|
79
|
+
const frag = fragment;
|
|
80
|
+
if (frag)
|
|
81
|
+
void host.commit(() => edit.paste(frag));
|
|
82
|
+
else if (text)
|
|
83
|
+
void host.insertSelectionText(text);
|
|
84
|
+
}
|
|
85
|
+
const sink = host.clipboardSink;
|
|
86
|
+
const listeners = [
|
|
87
|
+
["cut", onCutEvent],
|
|
88
|
+
["paste", onPasteEvent],
|
|
89
|
+
];
|
|
90
|
+
for (const [type, listener] of listeners)
|
|
91
|
+
sink.addEventListener(type, listener);
|
|
92
|
+
return {
|
|
93
|
+
cut: menuCut,
|
|
94
|
+
paste: menuPaste,
|
|
95
|
+
destroy() {
|
|
96
|
+
for (const [type, listener] of listeners)
|
|
97
|
+
sink.removeEventListener(type, listener);
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=clipboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../src/clipboard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CommandDef } from "@docmentis/udoc-ui/internal";
|
|
2
|
+
import type { MessageKey } from "./i18n/index.js";
|
|
3
|
+
import type { EditTools } from "./tools.js";
|
|
4
|
+
type Def = CommandDef<MessageKey>;
|
|
5
|
+
/**
|
|
6
|
+
* The format commands, their controls built over `tools` — read when the ribbon
|
|
7
|
+
* builds a control, which it does only on an open document's strip, so after
|
|
8
|
+
* edit mode is mounted.
|
|
9
|
+
*/
|
|
10
|
+
export declare function formatCommands(tools: () => EditTools): Readonly<Record<string, Def>>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAG9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AA4BlD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,KAAK,GAAG,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;AAElC;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CA+NpF"}
|