@mrakomor/core 0.0.11 → 0.0.13
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/blockChrome.mjs +2 -2
- package/dist/blockInsertMenu.mjs +1 -1
- package/dist/chunk-2C6UDFD4.mjs +1 -0
- package/dist/chunk-4WTPDNPA.mjs +1 -0
- package/dist/chunk-5AD5MQXI.mjs +1 -0
- package/dist/{chunk-K2DMHAUD.mjs → chunk-7CJLTNHZ.mjs} +1 -1
- package/dist/{chunk-VYTSZ4S6.mjs → chunk-B2UFH244.mjs} +1 -1
- package/dist/chunk-BWK2S4UI.mjs +2 -0
- package/dist/chunk-D6K2L5O3.mjs +4 -0
- package/dist/{chunk-NR2BAMSW.mjs → chunk-DHFIX7FW.mjs} +2 -2
- package/dist/chunk-ERNLRJPB.mjs +1 -0
- package/dist/chunk-EXDY5TZH.mjs +1 -0
- package/dist/chunk-J4TTWQ6J.mjs +2 -0
- package/dist/{chunk-2VURZA2E.mjs → chunk-SG5PCGIV.mjs} +1 -1
- package/dist/chunk-ZHOZPQZH.mjs +1 -0
- package/dist/clipboard.cjs +3 -3
- package/dist/clipboard.mjs +3 -3
- package/dist/footer.cjs +3 -3
- package/dist/footer.mjs +2 -2
- package/dist/headline.cjs +2 -2
- package/dist/headline.mjs +1 -1
- package/dist/help.cjs +1 -1
- package/dist/help.mjs +2 -2
- package/dist/index.cjs +6 -6
- package/dist/index.mjs +4 -4
- package/dist/link.mjs +2 -2
- package/dist/list.cjs +3 -3
- package/dist/list.mjs +1 -1
- package/dist/paragraph.cjs +2 -2
- package/dist/paragraph.mjs +1 -1
- package/dist/slashCommand.cjs +2 -2
- package/dist/slashCommand.mjs +1 -1
- package/dist/tooltip.cjs +1 -1
- package/dist/tooltip.mjs +2 -2
- package/dist/tts.cjs +8 -8
- package/dist/tts.mjs +3 -3
- package/dist/types/Mrakomor.d.mts +230 -0
- package/dist/types/component/AbstractComponent.d.mts +69 -0
- package/dist/types/component/Editor.d.mts +8 -0
- package/dist/types/component/block/BlockComponent.d.mts +105 -0
- package/dist/types/component/block/BlockRegister.d.mts +29 -0
- package/dist/types/component/block/ExternalComponent.d.mts +42 -0
- package/dist/types/component/block/UnknownComponent.d.mts +3 -0
- package/dist/types/component/block/blockItemEquals.d.mts +6 -0
- package/dist/types/component/block/helpers.d.mts +319 -0
- package/dist/types/component/editorContext.d.mts +4 -0
- package/dist/types/component/entityRange/EntityRangeElement.d.mts +15 -0
- package/dist/types/component/inlineStyle/Bold.d.mts +4 -0
- package/dist/types/component/inlineStyle/InlineElement.d.mts +10 -0
- package/dist/types/component/inlineStyle/Italic.d.mts +4 -0
- package/dist/types/component/inlineStyle/Subscript.d.mts +4 -0
- package/dist/types/component/inlineStyle/Superscript.d.mts +4 -0
- package/dist/types/component/inlineStyle/Underline.d.mts +4 -0
- package/dist/types/component/inlineStyle/index.d.mts +5 -0
- package/dist/types/component/overlayMount.d.mts +46 -0
- package/dist/types/dom.d.mts +169 -0
- package/dist/types/emitter.d.mts +38 -0
- package/dist/types/index.d.mts +7 -0
- package/dist/types/namespaces.d.mts +17 -0
- package/dist/types/plugin/blockChrome/BlockChrome.d.mts +11 -0
- package/dist/types/plugin/blockChrome/index.d.mts +1 -0
- package/dist/types/plugin/blockInsertMenu/BlockInsertMenu.d.mts +6 -0
- package/dist/types/plugin/blockInsertMenu/index.d.mts +1 -0
- package/dist/types/plugin/clipboard/clipboardHelpers.d.mts +151 -0
- package/dist/types/plugin/clipboard/clipboardPlugin.d.mts +6 -0
- package/dist/types/plugin/clipboard/index.d.mts +1 -0
- package/dist/types/plugin/default/defaultMrakomorPlugin.d.mts +21 -0
- package/dist/types/plugin/dialog/Dialog.d.mts +23 -0
- package/dist/types/plugin/footer/footerPlugin.d.mts +7 -0
- package/dist/types/plugin/footer/index.d.mts +1 -0
- package/dist/types/plugin/headline/Headline.d.mts +29 -0
- package/dist/types/plugin/headline/index.d.mts +1 -0
- package/dist/types/plugin/help/HelpRegister.d.mts +15 -0
- package/dist/types/plugin/help/helpPlugin.d.mts +26 -0
- package/dist/types/plugin/help/helpSchema.d.mts +11 -0
- package/dist/types/plugin/help/index.d.mts +1 -0
- package/dist/types/plugin/linkEntity/LinkEntity.d.mts +37 -0
- package/dist/types/plugin/linkEntity/index.d.mts +1 -0
- package/dist/types/plugin/list/List.d.mts +61 -0
- package/dist/types/plugin/list/index.d.mts +1 -0
- package/dist/types/plugin/list/listHelpers.d.mts +166 -0
- package/dist/types/plugin/menu/Menu.d.mts +22 -0
- package/dist/types/plugin/menu/menuPlugin.d.mts +6 -0
- package/dist/types/plugin/paragraph/Paragraph.d.mts +16 -0
- package/dist/types/plugin/paragraph/index.d.mts +1 -0
- package/dist/types/plugin/slashCommand/SlashActionRegister.d.mts +12 -0
- package/dist/types/plugin/slashCommand/index.d.mts +1 -0
- package/dist/types/plugin/slashCommand/slashActionSchema.d.mts +29 -0
- package/dist/types/plugin/slashCommand/slashCommandHelpers.d.mts +77 -0
- package/dist/types/plugin/slashCommand/slashCommandPlugin.d.mts +11 -0
- package/dist/types/plugin/slashCommand/slashHelp.d.mts +12 -0
- package/dist/types/plugin/tooltip/Tooltip.d.mts +16 -0
- package/dist/types/plugin/tooltip/index.d.mts +1 -0
- package/dist/types/plugin/tts/TtsHeadline.d.mts +27 -0
- package/dist/types/plugin/tts/TtsList.d.mts +19 -0
- package/dist/types/plugin/tts/TtsParagraph.d.mts +9 -0
- package/dist/types/plugin/tts/TtsVoice.d.mts +52 -0
- package/dist/types/plugin/tts/index.d.mts +4 -0
- package/dist/types/register/Register.d.mts +50 -0
- package/dist/types/register/sortRegisterEntries.d.mts +7 -0
- package/dist/types/schema/blockContent.d.mts +34 -0
- package/dist/types/schema/blockRegister.d.mts +14 -0
- package/dist/types/schema/config.d.mts +6 -0
- package/dist/types/types.d.mts +636 -0
- package/package.json +36 -22
- package/dist/chunk-5VPYPKGA.mjs +0 -1
- package/dist/chunk-BCE45I7Q.mjs +0 -2
- package/dist/chunk-N4I2WZWF.mjs +0 -1
- package/dist/chunk-SCFD3XBH.mjs +0 -1
- package/dist/chunk-T7OO472O.mjs +0 -1
- package/dist/chunk-WQWE5UCN.mjs +0 -1
- package/dist/chunk-YO4ZA6PJ.mjs +0 -2
- package/dist/chunk-ZDMD7SRT.mjs +0 -4
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema for one inline style range: `{ length, offset, style }`.
|
|
3
|
+
* @returns {*} `@esmj/schema` object schema
|
|
4
|
+
*/
|
|
5
|
+
export function inlineStyleRangeSchema(): any;
|
|
6
|
+
/**
|
|
7
|
+
* One entity range: `{ entity: { type, data }, length, offset }`.
|
|
8
|
+
*
|
|
9
|
+
* @param {import('#src/types.mjs').EntityRangeSchemaOptions} [options]
|
|
10
|
+
*/
|
|
11
|
+
export function entityRangeSchema({ type, data, length, offset, }?: import("#src/types.mjs").EntityRangeSchemaOptions): import("@esmj/schema").ObjectSchemaInterface<{
|
|
12
|
+
entity: import("@esmj/schema").SchemaInterface<{
|
|
13
|
+
type: string;
|
|
14
|
+
data: unknown;
|
|
15
|
+
}, {
|
|
16
|
+
type: string;
|
|
17
|
+
data: unknown;
|
|
18
|
+
}>;
|
|
19
|
+
length: import("@esmj/schema").NumberSchemaInterface;
|
|
20
|
+
offset: import("@esmj/schema").NumberSchemaInterface;
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* `entityRanges` array that keeps only `atom.tts.Voice` entries.
|
|
24
|
+
* @returns {*} `@esmj/schema` array schema
|
|
25
|
+
*/
|
|
26
|
+
export function ttsVoiceEntityRangesSchema(): any;
|
|
27
|
+
/**
|
|
28
|
+
* Shared `{ component, componentId, properties, settings }` block envelope.
|
|
29
|
+
*
|
|
30
|
+
* @param {Element | null | undefined} node HTML used to seed `componentId` / text defaults
|
|
31
|
+
* @param {import('#src/types.mjs').BlockStateSchemaSpec} spec
|
|
32
|
+
* @returns {*} `@esmj/schema` object schema
|
|
33
|
+
*/
|
|
34
|
+
export function blockStateSchema(node: Element | null | undefined, { component, properties, settings }: import("#src/types.mjs").BlockStateSchemaSpec): any;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable register id for a block entry (`block:{NAMESPACE}` or list variants).
|
|
3
|
+
* @param {string} namespace
|
|
4
|
+
* @param {object | undefined} settings
|
|
5
|
+
* @returns {string}
|
|
6
|
+
*/
|
|
7
|
+
export function blockRegistrationId(namespace: string, settings: object | undefined): string;
|
|
8
|
+
/**
|
|
9
|
+
* Parse one block register entry (constructor or registration object).
|
|
10
|
+
* @param {import('#src/types.mjs').BlockConstructor | import('#src/types.mjs').BlockComponentRegistration} entry
|
|
11
|
+
* @param {number} [index]
|
|
12
|
+
* @returns {import('#src/types.mjs').BlockComponentRegistration}
|
|
13
|
+
*/
|
|
14
|
+
export function blockComponentRegistrationSchema(entry: import("#src/types.mjs").BlockConstructor | import("#src/types.mjs").BlockComponentRegistration, index?: number): import("#src/types.mjs").BlockComponentRegistration;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public `createMrakomor(config)` input. Call `.parse(config)` to throw on invalid values.
|
|
3
|
+
* Parse for validation only — merge the original `config` afterward so unknown keys are kept.
|
|
4
|
+
* @returns {*} `@esmj/schema` object schema
|
|
5
|
+
*/
|
|
6
|
+
export function createMrakomorConfigSchema(): any;
|
|
@@ -0,0 +1,636 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@esmj/signals` state cell.
|
|
3
|
+
*/
|
|
4
|
+
export type Signal<T> = import("@esmj/signals").Signal<T>;
|
|
5
|
+
/**
|
|
6
|
+
* Signal-shaped DOM ref returned by `@esmj/dom` `useRef()`.
|
|
7
|
+
*/
|
|
8
|
+
export type ElementRef<ElementType extends HTMLElement = HTMLElement> = {
|
|
9
|
+
get: () => ElementType | null;
|
|
10
|
+
set: (arg0: ElementType | null) => ElementType | null;
|
|
11
|
+
current: ElementType | null;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* One inline style span on block (or list-item) text.
|
|
15
|
+
*/
|
|
16
|
+
export type InlineStyleRange = {
|
|
17
|
+
offset: number;
|
|
18
|
+
length: number;
|
|
19
|
+
style: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* One entity span (`atom.link.Link`, `atom.tts.Voice`, …).
|
|
23
|
+
*/
|
|
24
|
+
export type EntityRange = {
|
|
25
|
+
entity: {
|
|
26
|
+
type: string;
|
|
27
|
+
data: any;
|
|
28
|
+
};
|
|
29
|
+
offset: number;
|
|
30
|
+
length: number;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Entity range accepted before its schema fills defaults.
|
|
34
|
+
*/
|
|
35
|
+
export type EntityRangeInput = {
|
|
36
|
+
entity: {
|
|
37
|
+
type: string;
|
|
38
|
+
data?: any;
|
|
39
|
+
};
|
|
40
|
+
offset?: number | undefined;
|
|
41
|
+
length?: number | undefined;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Character range relative to a selectable root.
|
|
45
|
+
*/
|
|
46
|
+
export type RangeMeta = {
|
|
47
|
+
offset: number;
|
|
48
|
+
length: number;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* A `[SELECTABLE_ELEMENT]`-marked DOM element resolved from a `Range`, plus
|
|
52
|
+
* its index among its root's selectable items. See `dom.mjs`'s
|
|
53
|
+
* `getSelectableElementsInBlock` / `getSelectableItemForRange`.
|
|
54
|
+
*/
|
|
55
|
+
export type SelectableItem = {
|
|
56
|
+
element: Element;
|
|
57
|
+
index: number;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* CMS block envelope. `properties` / `settings` depend on `component`.
|
|
61
|
+
*/
|
|
62
|
+
export type BlockState<Properties = Record<string, any>, Settings = Record<string, any>> = {
|
|
63
|
+
/**
|
|
64
|
+
* dotted NAMESPACE
|
|
65
|
+
*/
|
|
66
|
+
component: string;
|
|
67
|
+
componentId: string;
|
|
68
|
+
properties: Properties;
|
|
69
|
+
settings: Settings;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Block accepted before `normalizeComponentState()` fills schema defaults.
|
|
73
|
+
*/
|
|
74
|
+
export type BlockStateInput = {
|
|
75
|
+
/**
|
|
76
|
+
* dotted NAMESPACE
|
|
77
|
+
*/
|
|
78
|
+
component: string;
|
|
79
|
+
componentId?: string | undefined;
|
|
80
|
+
properties?: Record<string, any> | undefined;
|
|
81
|
+
settings?: Record<string, any> | undefined;
|
|
82
|
+
};
|
|
83
|
+
export type ComponentStateInput = BlockStateInput | EntityRangeInput;
|
|
84
|
+
export type ComponentState = BlockState | EntityRange;
|
|
85
|
+
/**
|
|
86
|
+
* Generic cross-component conversion shape used by
|
|
87
|
+
* `BlockConstructor.toExchangeState` / `fromExchangeState`. `properties.items`
|
|
88
|
+
* ({@link ExchangeItem}[]) is the ONLY text-shaped field — every block type
|
|
89
|
+
* (flat text blocks like Paragraph/Headline, or multi-row blocks like List)
|
|
90
|
+
* produces/consumes the same `items[]` array, one entry per selectable item
|
|
91
|
+
* (a flat block always has exactly one). This lets transform/merge/footer
|
|
92
|
+
* text-count/formatting-resolution share one generic implementation instead
|
|
93
|
+
* of each block having its own flat-vs-list special case.
|
|
94
|
+
* Contract: each item's `text` (when present) is always DOM-sentinel-free —
|
|
95
|
+
* every `toExchangeState` implementation normalizes it via
|
|
96
|
+
* `normalizeBlockText` before returning, so callers never need to
|
|
97
|
+
* re-normalize a `toExchangeState()` result.
|
|
98
|
+
*/
|
|
99
|
+
export type ExchangeBlockState = {
|
|
100
|
+
properties: {
|
|
101
|
+
items: ExchangeItem[];
|
|
102
|
+
} & Record<string, any>;
|
|
103
|
+
settings?: Record<string, any> | undefined;
|
|
104
|
+
/**
|
|
105
|
+
* current/target component namespace for this exchange state (e.g. clipboard wraps a list item's shape as PARAGRAPH_NAMESPACE)
|
|
106
|
+
*/
|
|
107
|
+
component?: string | undefined;
|
|
108
|
+
/**
|
|
109
|
+
* component namespace this exchange state was produced FROM (set by toExchangeState producers); lets fromExchangeState implementations make origin-aware decisions
|
|
110
|
+
*/
|
|
111
|
+
originComponent?: string | undefined;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* One row of `ExchangeBlockState.properties.items` — a flat text block has
|
|
115
|
+
* exactly one, a List has one per `<li>`. This is an OPEN bag (like
|
|
116
|
+
* `ExchangeBlockState.properties`): the well-known keys below cover every
|
|
117
|
+
* block today, but a block's own `toExchangeState` override may add whatever
|
|
118
|
+
* extra keys it needs (e.g. a future richer block type) — do not treat this
|
|
119
|
+
* as a sealed shape.
|
|
120
|
+
*/
|
|
121
|
+
export type ExchangeItem = {
|
|
122
|
+
text?: string | undefined;
|
|
123
|
+
inlineStyleRanges?: InlineStyleRange[] | undefined;
|
|
124
|
+
entityRanges?: EntityRange[] | undefined;
|
|
125
|
+
/**
|
|
126
|
+
* nesting level (List only; default 0, ignored by flat blocks)
|
|
127
|
+
*/
|
|
128
|
+
depth?: number | undefined;
|
|
129
|
+
/**
|
|
130
|
+
* stable per-item DOM identity (List only); lets `patchBlockExchangeItem`'s `fromExchangeState` round-trip avoid minting new ids on every keystroke
|
|
131
|
+
*/
|
|
132
|
+
componentId?: string | undefined;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Paragraph / headline `properties`.
|
|
136
|
+
*/
|
|
137
|
+
export type TextBlockProperties = {
|
|
138
|
+
text: string;
|
|
139
|
+
inlineStyleRanges: InlineStyleRange[];
|
|
140
|
+
entityRanges: EntityRange[];
|
|
141
|
+
};
|
|
142
|
+
export type TextBlockState = BlockState<TextBlockProperties>;
|
|
143
|
+
/**
|
|
144
|
+
* Minimal text/range state accepted by rich-text helpers.
|
|
145
|
+
*/
|
|
146
|
+
export type RichTextState = {
|
|
147
|
+
component?: string | undefined;
|
|
148
|
+
componentId?: string | undefined;
|
|
149
|
+
properties: TextBlockProperties;
|
|
150
|
+
settings?: Record<string, any> | undefined;
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* One list row.
|
|
154
|
+
*/
|
|
155
|
+
export type ListItem = {
|
|
156
|
+
componentId: string;
|
|
157
|
+
depth: number;
|
|
158
|
+
text: string;
|
|
159
|
+
inlineStyleRanges: InlineStyleRange[];
|
|
160
|
+
entityRanges: EntityRange[];
|
|
161
|
+
};
|
|
162
|
+
export type ListBlockProperties = {
|
|
163
|
+
items: ListItem[];
|
|
164
|
+
};
|
|
165
|
+
export type ListBlockState = BlockState<ListBlockProperties, {
|
|
166
|
+
style: "ORDERED" | "UNORDERED";
|
|
167
|
+
}>;
|
|
168
|
+
/**
|
|
169
|
+
* Minimal schema contract used by component constructors.
|
|
170
|
+
*/
|
|
171
|
+
export type Schema<Output> = {
|
|
172
|
+
parse: (...args: any[]) => Output;
|
|
173
|
+
};
|
|
174
|
+
/**
|
|
175
|
+
* Inline-style class used to build and parse rich text.
|
|
176
|
+
*/
|
|
177
|
+
export type InlineStyleConstructor = Function & {
|
|
178
|
+
style: string;
|
|
179
|
+
match: (arg0: any) => boolean;
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Entity-range class used to build and parse rich text.
|
|
183
|
+
*/
|
|
184
|
+
export type EntityRangeConstructor = Function & {
|
|
185
|
+
NAMESPACE: string;
|
|
186
|
+
match: (arg0: any) => boolean;
|
|
187
|
+
getStateSchema: (...args: any[]) => Schema<EntityRange>;
|
|
188
|
+
};
|
|
189
|
+
/**
|
|
190
|
+
* Inline-style and entity-range constructors used to build/parse rich text.
|
|
191
|
+
*/
|
|
192
|
+
export type RichTextComponents = {
|
|
193
|
+
inlineStyleComponents: InlineStyleConstructor[];
|
|
194
|
+
entityRangeComponents: EntityRangeConstructor[];
|
|
195
|
+
};
|
|
196
|
+
/**
|
|
197
|
+
* Tooltip actions declared on a block type.
|
|
198
|
+
*/
|
|
199
|
+
export type TooltipConfig = {
|
|
200
|
+
inlineStyles: string[];
|
|
201
|
+
entityRanges: string[];
|
|
202
|
+
blockTransforms: string[];
|
|
203
|
+
};
|
|
204
|
+
/**
|
|
205
|
+
* Any class/function component resolvable by a plugin.
|
|
206
|
+
*/
|
|
207
|
+
export type ComponentConstructor = Function & {
|
|
208
|
+
NAMESPACE: string;
|
|
209
|
+
LABEL?: string | Function;
|
|
210
|
+
getStateSchema?: (...args: any[]) => Schema<any>;
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* Content block class (`Paragraph`, `List`, …).
|
|
214
|
+
*/
|
|
215
|
+
export type BlockConstructor = Function & {
|
|
216
|
+
NAMESPACE: string;
|
|
217
|
+
LABEL?: string | Function;
|
|
218
|
+
getStateSchema: (...args: any[]) => Schema<BlockState>;
|
|
219
|
+
toExchangeState: (arg0: BlockState) => ExchangeBlockState;
|
|
220
|
+
fromExchangeState: (arg0: ExchangeBlockState) => BlockStateInput;
|
|
221
|
+
appendExchangeState: (arg0: BlockState, arg1: ExchangeBlockState) => ({
|
|
222
|
+
state: BlockState;
|
|
223
|
+
cursor: number;
|
|
224
|
+
} | null);
|
|
225
|
+
};
|
|
226
|
+
/**
|
|
227
|
+
* Content-editable block instance (`this` in Paragraph / List / Headline).
|
|
228
|
+
*/
|
|
229
|
+
export type BlockInstance = {
|
|
230
|
+
element: Element | null;
|
|
231
|
+
mrakomor: Mrakomor;
|
|
232
|
+
state: Signal<BlockState>;
|
|
233
|
+
constructor: Function;
|
|
234
|
+
getState: () => BlockState;
|
|
235
|
+
isStale: () => boolean;
|
|
236
|
+
isAtomic?: (() => boolean) | undefined;
|
|
237
|
+
setCursor?: ((arg0?: {
|
|
238
|
+
cursor?: number;
|
|
239
|
+
itemIndex?: number;
|
|
240
|
+
} | undefined) => void) | undefined;
|
|
241
|
+
onKeydown?: ((arg0: KeydownEvent) => void) | undefined;
|
|
242
|
+
getInlineStyleComponents?: (() => InlineStyleConstructor[]) | undefined;
|
|
243
|
+
getEntityRangeComponents?: (() => EntityRangeConstructor[]) | undefined;
|
|
244
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* Rich-text block instance accepted by DOM parse helpers.
|
|
247
|
+
*/
|
|
248
|
+
export type RichTextBlockInstance = BlockInstance & {
|
|
249
|
+
getInlineStyleComponents: () => InlineStyleConstructor[];
|
|
250
|
+
getEntityRangeComponents: () => EntityRangeConstructor[];
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* Display-only help dialog row (not executable; not in `register.slashActions`).
|
|
254
|
+
*/
|
|
255
|
+
export type HelpEntry = {
|
|
256
|
+
id: string;
|
|
257
|
+
group: string;
|
|
258
|
+
description: string;
|
|
259
|
+
commands?: string[] | undefined;
|
|
260
|
+
shortcuts?: string[] | undefined;
|
|
261
|
+
};
|
|
262
|
+
/**
|
|
263
|
+
* Core + plugin command methods on `mrakomor.command`.
|
|
264
|
+
*/
|
|
265
|
+
export type MrakomorCommand = {
|
|
266
|
+
insertBlockElement: (arg0: object | undefined, arg1: object | undefined) => void;
|
|
267
|
+
replaceBlockElement: (arg0: object | undefined, arg1: object | undefined) => void;
|
|
268
|
+
removeBlockElement: (arg0: object | undefined, arg1: object | undefined) => void;
|
|
269
|
+
mergeBlockElement: (arg0: object | undefined, arg1: object | undefined) => void;
|
|
270
|
+
transformBlockElement: (arg0: object | undefined, arg1: object | undefined) => void;
|
|
271
|
+
moveBlockElement: (arg0: object | undefined, arg1: object | undefined) => void;
|
|
272
|
+
insertEntityRange: (arg0: object | undefined, arg1: object | undefined) => void;
|
|
273
|
+
removeEntityRange: (arg0: object | undefined, arg1: object | undefined) => void;
|
|
274
|
+
insertInlineStyleRange: (arg0: object | undefined, arg1: object | undefined) => void;
|
|
275
|
+
copy?: ((arg0?: object | undefined) => void) | undefined;
|
|
276
|
+
cut?: ((arg0?: object | undefined) => void) | undefined;
|
|
277
|
+
paste?: ((arg0?: object | undefined) => void) | undefined;
|
|
278
|
+
openDialog?: ((arg0?: object | undefined, arg1?: object | undefined) => void) | undefined;
|
|
279
|
+
closeDialog?: (() => void) | undefined;
|
|
280
|
+
openTooltip?: ((arg0?: object | undefined, arg1?: object | undefined) => void) | undefined;
|
|
281
|
+
closeTooltip?: ((arg0?: object | undefined) => void) | undefined;
|
|
282
|
+
openMenu?: ((arg0?: object | undefined, arg1?: object | undefined) => void) | undefined;
|
|
283
|
+
updateMenu?: ((arg0?: object | undefined, arg1?: object | undefined) => void) | undefined;
|
|
284
|
+
closeMenu?: (() => void) | undefined;
|
|
285
|
+
openBlockInsertMenu?: ((arg0: {
|
|
286
|
+
blockElement: Element;
|
|
287
|
+
anchorRect: DOMRect;
|
|
288
|
+
}) => void) | undefined;
|
|
289
|
+
closeBlockInsertMenu?: (() => void) | undefined;
|
|
290
|
+
openHelp?: ((arg0?: object | undefined) => void) | undefined;
|
|
291
|
+
};
|
|
292
|
+
export type RegisterSubscription = {
|
|
293
|
+
unsubscribe: () => void;
|
|
294
|
+
};
|
|
295
|
+
/**
|
|
296
|
+
* Map-backed register base API (`Register` extends `@esmj/observable` `Observable`).
|
|
297
|
+
*/
|
|
298
|
+
export type RegisterApi = {
|
|
299
|
+
add: (arg0: any) => any | null | any[];
|
|
300
|
+
get: (arg0: string) => any | undefined;
|
|
301
|
+
has: (arg0: string) => boolean;
|
|
302
|
+
remove: (arg0: string) => boolean;
|
|
303
|
+
list: () => any[];
|
|
304
|
+
subscribe: (arg0: (arg0: any[]) => void) => RegisterSubscription;
|
|
305
|
+
};
|
|
306
|
+
/**
|
|
307
|
+
* Block register (`component/block/BlockRegister.mjs`).
|
|
308
|
+
*/
|
|
309
|
+
export type BlockRegister = RegisterApi & {
|
|
310
|
+
getByNamespace: (arg0: string) => BlockConstructor | undefined;
|
|
311
|
+
};
|
|
312
|
+
/**
|
|
313
|
+
* Slash action register (`plugin/slashCommand/SlashActionRegister.mjs`).
|
|
314
|
+
* Stored ids are bare slugs (e.g. `help`).
|
|
315
|
+
*/
|
|
316
|
+
export type SlashActionRegister = RegisterApi;
|
|
317
|
+
/**
|
|
318
|
+
* Editor registries — constructed in `Mrakomor`; normalize on `add`.
|
|
319
|
+
*/
|
|
320
|
+
export type MrakomorRegister = {
|
|
321
|
+
blocks: BlockRegister;
|
|
322
|
+
/**
|
|
323
|
+
* Set by `slashCommandPlugin`
|
|
324
|
+
*/
|
|
325
|
+
slashActions?: RegisterApi | undefined;
|
|
326
|
+
help: RegisterApi;
|
|
327
|
+
};
|
|
328
|
+
/**
|
|
329
|
+
* Editor instance plugins and blocks talk to.
|
|
330
|
+
*/
|
|
331
|
+
export type Mrakomor = {
|
|
332
|
+
command: MrakomorCommand;
|
|
333
|
+
register: MrakomorRegister;
|
|
334
|
+
emitter: import("@esmj/emitter").Emitter;
|
|
335
|
+
listenerAbortController: AbortController;
|
|
336
|
+
_id: string;
|
|
337
|
+
getConfig: () => MrakomorConfig;
|
|
338
|
+
getRoot: () => Element | null;
|
|
339
|
+
_getContentRoot: () => Element | null;
|
|
340
|
+
_setContentRoot: (arg0: Element | null) => void;
|
|
341
|
+
getContent: () => BlockState[];
|
|
342
|
+
setContent: (arg0: BlockStateInput[] | undefined) => void;
|
|
343
|
+
emit: (arg0: string, arg1: object | undefined) => EmitterEvent;
|
|
344
|
+
on: (arg0: string, arg1: (arg0: EmitterEvent) => void) => () => void;
|
|
345
|
+
onChangeContent: (arg0: (arg0: EmitterEvent) => void) => () => void;
|
|
346
|
+
emitDomEvent: (arg0: string, arg1: Event) => boolean;
|
|
347
|
+
wrapBlockElement: (arg0: any) => any;
|
|
348
|
+
mount: () => any;
|
|
349
|
+
unmount: () => void;
|
|
350
|
+
resolveComponent: (arg0: string, arg1: Signal<BlockState>) => any;
|
|
351
|
+
resolveComponentConstructor: (arg0: string) => ComponentConstructor | undefined;
|
|
352
|
+
normalizeComponentState: (arg0: ComponentStateInput) => ComponentState | undefined;
|
|
353
|
+
_getContentState: () => BlockState[];
|
|
354
|
+
_setContentState: (arg0: BlockState[] | undefined) => void;
|
|
355
|
+
_getBlockElements: () => Element[];
|
|
356
|
+
_syncBlockElementsFromDom: () => void;
|
|
357
|
+
_setBlockElement: (arg0: Element, arg1: number | undefined) => void;
|
|
358
|
+
_removeBlockElement: (arg0: Element) => void;
|
|
359
|
+
_getBlockElementIndex: (arg0: Element | null | undefined) => number;
|
|
360
|
+
_getBlockElementByComponentId: (arg0: string | null | undefined) => Element | null;
|
|
361
|
+
_getBlockElementState: (arg0: Element | null | undefined) => BlockState | undefined;
|
|
362
|
+
_onMount: () => void;
|
|
363
|
+
_onUnmount: () => void;
|
|
364
|
+
_init?: (() => void) | undefined;
|
|
365
|
+
};
|
|
366
|
+
/**
|
|
367
|
+
* Fully resolved editor config passed to plugins.
|
|
368
|
+
*/
|
|
369
|
+
export type MrakomorConfig = {
|
|
370
|
+
debug: boolean;
|
|
371
|
+
content: BlockStateInput[];
|
|
372
|
+
/**
|
|
373
|
+
* Always includes `dialogPlugin`, `menuPlugin`, and ends with `defaultMrakomorPlugin` (appended if missing). Add `footerPlugin` / `helpPlugin` from `@mrakomor/core/footer` and `@mrakomor/core/help` when needed.
|
|
374
|
+
*/
|
|
375
|
+
plugins: PluginFactory[];
|
|
376
|
+
/**
|
|
377
|
+
* Normalized via `register.blocks` (`getConfig()` read-through).
|
|
378
|
+
*/
|
|
379
|
+
blockComponents: BlockComponentRegistration[];
|
|
380
|
+
/**
|
|
381
|
+
* Normalized via `register.slashActions`; auto-synced to help.
|
|
382
|
+
*/
|
|
383
|
+
slashActions?: SlashActionRegistration[] | undefined;
|
|
384
|
+
inlineStyles: InlineStyleConstructor[];
|
|
385
|
+
entityRanges: EntityRangeConstructor[];
|
|
386
|
+
tooltip: {
|
|
387
|
+
[x: string]: Partial<TooltipConfig>;
|
|
388
|
+
};
|
|
389
|
+
root: Element;
|
|
390
|
+
id?: string | undefined;
|
|
391
|
+
};
|
|
392
|
+
/**
|
|
393
|
+
* Public `createMrakomor()` configuration before defaults are applied.
|
|
394
|
+
* Validated by `createMrakomorConfigSchema()` in [`schema/config.mjs`](schema/config.mjs).
|
|
395
|
+
*/
|
|
396
|
+
export type CreateMrakomorConfig = {
|
|
397
|
+
root: Element;
|
|
398
|
+
id?: string | undefined;
|
|
399
|
+
debug?: boolean | undefined;
|
|
400
|
+
content?: BlockStateInput[] | undefined;
|
|
401
|
+
/**
|
|
402
|
+
* Always includes `dialogPlugin`, `menuPlugin`, and ends with `defaultMrakomorPlugin` (appended if missing). Add `footerPlugin` / `helpPlugin` from `@mrakomor/core/footer` and `@mrakomor/core/help` when needed.
|
|
403
|
+
*/
|
|
404
|
+
plugins?: PluginFactory[] | undefined;
|
|
405
|
+
blockComponents?: (BlockConstructor | BlockComponentRegistration)[] | undefined;
|
|
406
|
+
slashActions?: SlashActionRegistration[] | undefined;
|
|
407
|
+
inlineStyles?: InlineStyleConstructor[] | undefined;
|
|
408
|
+
entityRanges?: EntityRangeConstructor[] | undefined;
|
|
409
|
+
tooltip?: {
|
|
410
|
+
[x: string]: Partial<TooltipConfig>;
|
|
411
|
+
} | undefined;
|
|
412
|
+
};
|
|
413
|
+
/**
|
|
414
|
+
* Registered block in `config.blockComponents` (register + resolve). Normalized id: `block:{NAMESPACE}` or `block:{NAMESPACE}:ul|ol`.
|
|
415
|
+
*/
|
|
416
|
+
export type BlockComponentRegistration = {
|
|
417
|
+
component: BlockConstructor;
|
|
418
|
+
id: string;
|
|
419
|
+
label: string;
|
|
420
|
+
keywords: string[];
|
|
421
|
+
group: string;
|
|
422
|
+
order?: number | undefined;
|
|
423
|
+
settings?: object | undefined;
|
|
424
|
+
};
|
|
425
|
+
/**
|
|
426
|
+
* Non-block slash menu entry (`config.slashActions`). Invoked via `handler(ctx)`.
|
|
427
|
+
*/
|
|
428
|
+
export type SlashActionRegistration = {
|
|
429
|
+
/**
|
|
430
|
+
* Stable id (bare slug after normalize, e.g. `help`)
|
|
431
|
+
*/
|
|
432
|
+
id: string;
|
|
433
|
+
label: string;
|
|
434
|
+
keywords: string[];
|
|
435
|
+
/**
|
|
436
|
+
* Help dialog section (auto-synced from slashActions)
|
|
437
|
+
*/
|
|
438
|
+
group: string;
|
|
439
|
+
order?: number | undefined;
|
|
440
|
+
/**
|
|
441
|
+
* Optional; shown in help dialog
|
|
442
|
+
*/
|
|
443
|
+
description?: string | undefined;
|
|
444
|
+
handler: (arg0: SlashCommandContext) => void;
|
|
445
|
+
};
|
|
446
|
+
/**
|
|
447
|
+
* Slash menu row: block insert/replace or non-block action.
|
|
448
|
+
*/
|
|
449
|
+
export type SlashMenuEntry = BlockComponentRegistration | SlashActionRegistration;
|
|
450
|
+
/**
|
|
451
|
+
* Context for slash apply helpers.
|
|
452
|
+
*/
|
|
453
|
+
export type SlashCommandContext = {
|
|
454
|
+
mrakomor: Mrakomor;
|
|
455
|
+
blockElement: Element;
|
|
456
|
+
query: string;
|
|
457
|
+
slashStart: number;
|
|
458
|
+
slashEnd: number;
|
|
459
|
+
/**
|
|
460
|
+
* Block snapshot at `/` (through `/`; query is DOM-only until apply)
|
|
461
|
+
*/
|
|
462
|
+
baselineState: BlockState | null | undefined;
|
|
463
|
+
range: Range | null;
|
|
464
|
+
};
|
|
465
|
+
/**
|
|
466
|
+
* Active slash session offsets (plugin-private).
|
|
467
|
+
*/
|
|
468
|
+
export type SlashSession = {
|
|
469
|
+
blockElement: Element;
|
|
470
|
+
slashStart: number;
|
|
471
|
+
slashEnd: number;
|
|
472
|
+
query: string;
|
|
473
|
+
baselineState?: BlockState | null | undefined;
|
|
474
|
+
};
|
|
475
|
+
/**
|
|
476
|
+
* Factory argument: `plugin({ config, root, mrakomor })`.
|
|
477
|
+
*/
|
|
478
|
+
export type PluginContext = {
|
|
479
|
+
config: MrakomorConfig;
|
|
480
|
+
root: Element;
|
|
481
|
+
mrakomor: Mrakomor;
|
|
482
|
+
};
|
|
483
|
+
/**
|
|
484
|
+
* Plugin instance. Every hook is optional.
|
|
485
|
+
*/
|
|
486
|
+
export type Plugin = {
|
|
487
|
+
resolveConfig?: ((arg0: MrakomorConfig) => MrakomorConfig) | undefined;
|
|
488
|
+
resolveComponent?: ((arg0: string) => ComponentConstructor | undefined) | undefined;
|
|
489
|
+
wrapBlockElement?: ((arg0: any) => any | undefined) | undefined;
|
|
490
|
+
registerEvents?: ((arg0: Mrakomor) => void) | undefined;
|
|
491
|
+
registerHandlers?: ((arg0: Mrakomor) => void) | undefined;
|
|
492
|
+
registerCommands?: ((arg0: Mrakomor) => void) | undefined;
|
|
493
|
+
registerListeners?: ((arg0: Mrakomor) => void) | undefined;
|
|
494
|
+
onKeyDown?: ((arg0: KeydownEvent) => void) | undefined;
|
|
495
|
+
onMount?: ((arg0: Mrakomor) => void) | undefined;
|
|
496
|
+
onUnmount?: ((arg0: Mrakomor) => void) | undefined;
|
|
497
|
+
};
|
|
498
|
+
export type PluginFactory = (context: PluginContext) => Plugin;
|
|
499
|
+
/**
|
|
500
|
+
* Caret/selection snapshot that survives remount.
|
|
501
|
+
*/
|
|
502
|
+
export type SelectionState = {
|
|
503
|
+
start: number;
|
|
504
|
+
end: number;
|
|
505
|
+
element: Element | null;
|
|
506
|
+
selectableElement?: Node | null | undefined;
|
|
507
|
+
};
|
|
508
|
+
/**
|
|
509
|
+
* Non-collapsed selection that may span blocks.
|
|
510
|
+
*/
|
|
511
|
+
export type CrossBlockSelectionState = {
|
|
512
|
+
startBlock: Element;
|
|
513
|
+
endBlock: Element;
|
|
514
|
+
startOffset: number;
|
|
515
|
+
endOffset: number;
|
|
516
|
+
};
|
|
517
|
+
/**
|
|
518
|
+
* Copy/cut/paste selection in content-array indexes.
|
|
519
|
+
*/
|
|
520
|
+
export type ClipboardSelection = {
|
|
521
|
+
collapsed?: boolean | undefined;
|
|
522
|
+
startIndex: number;
|
|
523
|
+
endIndex: number;
|
|
524
|
+
startOffset: number;
|
|
525
|
+
endOffset: number;
|
|
526
|
+
/**
|
|
527
|
+
* start list item, or the only item
|
|
528
|
+
*/
|
|
529
|
+
listItemIndex?: number | undefined;
|
|
530
|
+
/**
|
|
531
|
+
* end list item when the selection spans items
|
|
532
|
+
*/
|
|
533
|
+
endListItemIndex?: number | undefined;
|
|
534
|
+
};
|
|
535
|
+
/**
|
|
536
|
+
* Result of delete/paste/merge on the content array.
|
|
537
|
+
*/
|
|
538
|
+
export type ContentMutation = {
|
|
539
|
+
content: BlockState[];
|
|
540
|
+
resultIndex: number;
|
|
541
|
+
cursor: number;
|
|
542
|
+
listItemIndex?: number | undefined;
|
|
543
|
+
};
|
|
544
|
+
/**
|
|
545
|
+
* Split of a text block at the caret.
|
|
546
|
+
*/
|
|
547
|
+
export type SplitBlockResult = {
|
|
548
|
+
originalLineState: RichTextState;
|
|
549
|
+
newLineState: RichTextState;
|
|
550
|
+
};
|
|
551
|
+
/**
|
|
552
|
+
* Lift one list item to a text block, splitting the list around it.
|
|
553
|
+
*/
|
|
554
|
+
export type UnwrapListResult = {
|
|
555
|
+
blocks: BlockState[];
|
|
556
|
+
paragraphIndex: number;
|
|
557
|
+
};
|
|
558
|
+
/**
|
|
559
|
+
* Tooltip button descriptor.
|
|
560
|
+
*/
|
|
561
|
+
export type TooltipAction = {
|
|
562
|
+
label: string | Function | object;
|
|
563
|
+
title?: string | object | Function | undefined;
|
|
564
|
+
group?: string | undefined;
|
|
565
|
+
active?: (() => boolean) | undefined;
|
|
566
|
+
onAction: (arg0: Mrakomor) => void;
|
|
567
|
+
};
|
|
568
|
+
/**
|
|
569
|
+
* Emitter event from `mrakomor.emit` (`@esmj/emitter`).
|
|
570
|
+
*/
|
|
571
|
+
export type EmitterEvent = {
|
|
572
|
+
name: string;
|
|
573
|
+
context: any;
|
|
574
|
+
defaultPrevented: boolean;
|
|
575
|
+
preventDefault: () => void;
|
|
576
|
+
stopPropagation: () => void;
|
|
577
|
+
mrakomor?: Mrakomor | undefined;
|
|
578
|
+
/**
|
|
579
|
+
* payload of `CONTENT_CHANGE`
|
|
580
|
+
*/
|
|
581
|
+
content?: BlockState<Record<string, any>, Record<string, any>>[] | undefined;
|
|
582
|
+
/**
|
|
583
|
+
* payload of `FOCUSOUT` / `FOCUSIN`
|
|
584
|
+
*/
|
|
585
|
+
relatedTarget?: EventTarget | null | undefined;
|
|
586
|
+
/**
|
|
587
|
+
* payload of `CLICK` (viewport X, native `MouseEvent.clientX`)
|
|
588
|
+
*/
|
|
589
|
+
clientX?: number | undefined;
|
|
590
|
+
/**
|
|
591
|
+
* payload of `CLICK` (viewport Y, native `MouseEvent.clientY`)
|
|
592
|
+
*/
|
|
593
|
+
clientY?: number | undefined;
|
|
594
|
+
};
|
|
595
|
+
/**
|
|
596
|
+
* KEYDOWN payload bridged onto the editor emitter.
|
|
597
|
+
*/
|
|
598
|
+
export type KeydownEvent = EmitterEvent;
|
|
599
|
+
/**
|
|
600
|
+
* INPUT / BEFORE_INPUT payload bridged onto the editor emitter.
|
|
601
|
+
*/
|
|
602
|
+
export type InputDomEvent = EmitterEvent;
|
|
603
|
+
/**
|
|
604
|
+
* `entityRangeSchema()` options.
|
|
605
|
+
*/
|
|
606
|
+
export type EntityRangeSchemaOptions = {
|
|
607
|
+
/**
|
|
608
|
+
* default `entity.type` (entity classes)
|
|
609
|
+
*/
|
|
610
|
+
type?: string | undefined;
|
|
611
|
+
/**
|
|
612
|
+
* schema for `entity.data` (default `s.any()`)
|
|
613
|
+
*/
|
|
614
|
+
data?: import("@esmj/schema").SchemaType | undefined;
|
|
615
|
+
length?: number | undefined;
|
|
616
|
+
offset?: number | undefined;
|
|
617
|
+
};
|
|
618
|
+
/**
|
|
619
|
+
* `blockStateSchema()` field spec.
|
|
620
|
+
*/
|
|
621
|
+
export type BlockStateSchemaSpec = {
|
|
622
|
+
/**
|
|
623
|
+
* dotted NAMESPACE
|
|
624
|
+
*/
|
|
625
|
+
component: string;
|
|
626
|
+
/**
|
|
627
|
+
* field schemas for `properties`
|
|
628
|
+
*/
|
|
629
|
+
properties: {
|
|
630
|
+
[x: string]: import("@esmj/schema").SchemaType;
|
|
631
|
+
};
|
|
632
|
+
/**
|
|
633
|
+
* settings schema (default empty object)
|
|
634
|
+
*/
|
|
635
|
+
settings?: import("@esmj/schema").SchemaType | undefined;
|
|
636
|
+
};
|