@prosekit/core 0.2.3 → 0.2.5

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.
@@ -3,6 +3,7 @@ import { Attrs } from '@prosekit/pm/model';
3
3
  import { Attrs as Attrs_2 } from 'prosemirror-model';
4
4
  import { Command } from '@prosekit/pm/state';
5
5
  import type { ConditionalExcept } from 'type-fest';
6
+ import type { ContentMatch } from '@prosekit/pm/model';
6
7
  import type { DirectEditorProps } from '@prosekit/pm/view';
7
8
  import { EditorState } from '@prosekit/pm/state';
8
9
  import type { EditorStateConfig } from '@prosekit/pm/state';
@@ -164,7 +165,7 @@ declare type ConverterTuple = Tuple5<FacetConverter | undefined>;
164
165
  /**
165
166
  * @public
166
167
  */
167
- declare function createEditor<E extends Extension>({ extension, defaultDoc, defaultHTML, defaultSelection, }: EditorOptions<E>): Editor<E>;
168
+ declare function createEditor<E extends Extension>(options: EditorOptions<E>): Editor<E>;
168
169
  export { createEditor }
169
170
  export { createEditor as createEditor_alias_1 }
170
171
 
@@ -180,6 +181,13 @@ export declare const default_alias_1: {
180
181
  };
181
182
  };
182
183
 
184
+ /**
185
+ * @internal
186
+ */
187
+ declare function defaultBlockAt(match: ContentMatch): NodeType_2 | null;
188
+ export { defaultBlockAt }
189
+ export { defaultBlockAt as defaultBlockAt_alias_1 }
190
+
183
191
  declare interface DefaultStateOptions {
184
192
  /**
185
193
  * A JSON object representing the starting document to use when creating the
@@ -297,6 +305,15 @@ declare function defineDocChangeHandler(handler: DocChangeHandler): Extension<Ex
297
305
  export { defineDocChangeHandler }
298
306
  export { defineDocChangeHandler as defineDocChangeHandler_alias_1 }
299
307
 
308
+ /**
309
+ * Registers a event handler that is called when the editor gains or loses focus.
310
+ *
311
+ * @public
312
+ */
313
+ declare function defineFocusChangeHandler(handler: FocusChangeHandler): Extension<ExtensionTyping<string, string, CommandArgs>>;
314
+ export { defineFocusChangeHandler }
315
+ export { defineFocusChangeHandler as defineFocusChangeHandler_alias_1 }
316
+
300
317
  /**
301
318
  * Add undo/redo history to the editor.
302
319
  */
@@ -472,13 +489,35 @@ declare class Editor<E extends Extension = any> {
472
489
  * @internal
473
490
  */
474
491
  static create(instance: any): Editor<any>;
492
+ /**
493
+ * Whether the editor is mounted.
494
+ */
475
495
  get mounted(): boolean;
496
+ /**
497
+ * The editor view.
498
+ */
476
499
  get view(): EditorView;
500
+ /**
501
+ * The editor schema.
502
+ */
477
503
  get schema(): Schema<ExtractNodes<E>, ExtractMarks<E>>;
478
504
  get commands(): ExtractCommandAppliers<E>;
505
+ /**
506
+ * Whether the editor is focused.
507
+ */
508
+ get focused(): boolean;
479
509
  mount(place: HTMLElement | null | undefined | void): void;
480
510
  unmount(): void;
511
+ /**
512
+ * Focus the editor.
513
+ */
514
+ focus(): void;
515
+ /**
516
+ * Blur the editor.
517
+ */
518
+ blur(): void;
481
519
  use(extension: Extension): VoidFunction;
520
+ get state(): EditorState;
482
521
  get nodes(): Record<ExtractNodes<E>, NodeBuilder>;
483
522
  get marks(): Record<ExtractMarks<E>, MarkBuilder>;
484
523
  }
@@ -667,6 +706,17 @@ declare interface FacetOptions<Input, Output> {
667
706
  export { FacetOptions }
668
707
  export { FacetOptions as FacetOptions_alias_1 }
669
708
 
709
+ /**
710
+ * A function that is called when the editor gains or loses focus.
711
+ *
712
+ * @param hasFocus - Whether the editor has focus.
713
+ *
714
+ * @public
715
+ */
716
+ declare type FocusChangeHandler = (hasFocus: boolean) => void;
717
+ export { FocusChangeHandler }
718
+ export { FocusChangeHandler as FocusChangeHandler_alias_1 }
719
+
670
720
  export declare function getBrowserDocument(): Document | undefined;
671
721
 
672
722
  export declare function getBrowserWindow(): (Window & typeof globalThis) | null | undefined;
@@ -732,6 +782,15 @@ export { isAllSelection as isAllSelection_alias_1 }
732
782
 
733
783
  export declare function isElement(value: unknown): value is Element;
734
784
 
785
+ /**
786
+ * Check if the selection is in a code block.
787
+ *
788
+ * @internal
789
+ */
790
+ declare function isInCodeBlock(selection: Selection_2): boolean | undefined;
791
+ export { isInCodeBlock }
792
+ export { isInCodeBlock as isInCodeBlock_alias_1 }
793
+
735
794
  export declare const isMac: boolean;
736
795
 
737
796
  /**
@@ -997,6 +1056,13 @@ declare interface NodeViewOptions {
997
1056
  export { NodeViewOptions }
998
1057
  export { NodeViewOptions as NodeViewOptions_alias_1 }
999
1058
 
1059
+ /**
1060
+ * @internal
1061
+ */
1062
+ declare const OBJECT_REPLACEMENT_CHARACTER = "\uFFFC";
1063
+ export { OBJECT_REPLACEMENT_CHARACTER }
1064
+ export { OBJECT_REPLACEMENT_CHARACTER as OBJECT_REPLACEMENT_CHARACTER_alias_1 }
1065
+
1000
1066
  export declare function objectEqual<T>(a: T, b: T): boolean;
1001
1067
 
1002
1068
  declare type Payload = unknown;
@@ -1181,6 +1247,11 @@ export { toggleNode as toggleNode_alias_1 }
1181
1247
 
1182
1248
  declare type Tuple5<T> = [T, T, T, T, T];
1183
1249
 
1250
+ /**
1251
+ * Merge multiple extensions into one.
1252
+ *
1253
+ * @public
1254
+ */
1184
1255
  declare function union<E extends Extension | Extension[]>(extension: E): SimplifyExtension<E>;
1185
1256
  export { union }
1186
1257
  export { union as union_alias_1 }
@@ -1239,6 +1310,13 @@ declare function withPriority<T extends Extension>(extension: T, priority: Prior
1239
1310
  export { withPriority }
1240
1311
  export { withPriority as withPriority_alias_1 }
1241
1312
 
1313
+ /**
1314
+ * @internal
1315
+ */
1316
+ declare function withSkipCodeBlock(command: Command): Command;
1317
+ export { withSkipCodeBlock }
1318
+ export { withSkipCodeBlock as withSkipCodeBlock_alias_1 }
1319
+
1242
1320
  export declare function wrap({ nodeType, attrs, }: {
1243
1321
  nodeType: NodeType;
1244
1322
  attrs?: Attrs | null;
@@ -17,6 +17,8 @@ export { DefaultStateOptions } from './_tsup-dts-rollup';
17
17
  export { defineDoc } from './_tsup-dts-rollup';
18
18
  export { defineDocChangeHandler } from './_tsup-dts-rollup';
19
19
  export { DocChangeHandler } from './_tsup-dts-rollup';
20
+ export { defineFocusChangeHandler } from './_tsup-dts-rollup';
21
+ export { FocusChangeHandler } from './_tsup-dts-rollup';
20
22
  export { defineMountHandler } from './_tsup-dts-rollup';
21
23
  export { defineUnmountHandler } from './_tsup-dts-rollup';
22
24
  export { defineUpdateHandler } from './_tsup-dts-rollup';
@@ -64,9 +66,11 @@ export { StateJSON } from './_tsup-dts-rollup';
64
66
  export { Priority } from './_tsup-dts-rollup';
65
67
  export { SimplifyUnion } from './_tsup-dts-rollup';
66
68
  export { clsx } from './_tsup-dts-rollup';
69
+ export { defaultBlockAt } from './_tsup-dts-rollup';
67
70
  export { _getId } from './_tsup-dts-rollup';
68
71
  export { getMarkType } from './_tsup-dts-rollup';
69
72
  export { getNodeType } from './_tsup-dts-rollup';
73
+ export { isInCodeBlock } from './_tsup-dts-rollup';
70
74
  export { jsonFromElement } from './_tsup-dts-rollup';
71
75
  export { jsonFromHTML } from './_tsup-dts-rollup';
72
76
  export { jsonFromNode } from './_tsup-dts-rollup';
@@ -80,3 +84,5 @@ export { isMark } from './_tsup-dts-rollup';
80
84
  export { isNodeSelection } from './_tsup-dts-rollup';
81
85
  export { isProseMirrorNode } from './_tsup-dts-rollup';
82
86
  export { isTextSelection } from './_tsup-dts-rollup';
87
+ export { withSkipCodeBlock } from './_tsup-dts-rollup';
88
+ export { OBJECT_REPLACEMENT_CHARACTER } from './_tsup-dts-rollup';
@@ -825,12 +825,9 @@ function union(extension) {
825
825
  }
826
826
 
827
827
  // src/editor/editor.ts
828
- function createEditor({
829
- extension,
830
- defaultDoc,
831
- defaultHTML,
832
- defaultSelection
833
- }) {
828
+ function createEditor(options) {
829
+ const { defaultDoc, defaultHTML, defaultSelection } = options;
830
+ let extension = options.extension;
834
831
  if (defaultDoc || defaultHTML) {
835
832
  extension = union([
836
833
  extension,
@@ -858,6 +855,7 @@ var EditorInstance = class {
858
855
  const schema = new Schema6(schemaInput);
859
856
  const stateConfig = stateInput ? stateInput({ schema }) : { schema };
860
857
  const state = EditorState2.create(stateConfig);
858
+ this.cachedState = state;
861
859
  if (commandInput) {
862
860
  for (const [name, commandCreator] of Object.entries(commandInput)) {
863
861
  this.defineCommand(name, commandCreator);
@@ -865,10 +863,7 @@ var EditorInstance = class {
865
863
  }
866
864
  this.directEditorProps = { state, ...viewInput };
867
865
  this.schema = this.directEditorProps.state.schema;
868
- const getState = () => {
869
- var _a;
870
- return (_a = this.view) == null ? void 0 : _a.state;
871
- };
866
+ const getState = () => this.getState();
872
867
  this.nodeBuilders = Object.fromEntries(
873
868
  Object.values(this.schema.nodes).map((type) => [
874
869
  type.name,
@@ -882,6 +877,12 @@ var EditorInstance = class {
882
877
  ])
883
878
  );
884
879
  }
880
+ getState() {
881
+ if (this.view) {
882
+ this.cachedState = this.view.state;
883
+ }
884
+ return this.cachedState;
885
+ }
885
886
  updateExtension(extension, mode) {
886
887
  var _a;
887
888
  const { schemaInput, stateInput, viewInput, commandInput } = updateExtension(this.payloads, this.converters, extension, mode);
@@ -986,18 +987,34 @@ var Editor = class _Editor {
986
987
  }
987
988
  return new _Editor(instance);
988
989
  }
990
+ /**
991
+ * Whether the editor is mounted.
992
+ */
989
993
  get mounted() {
990
994
  return !!this.instance.view;
991
995
  }
996
+ /**
997
+ * The editor view.
998
+ */
992
999
  get view() {
993
1000
  return this.instance.assertView;
994
1001
  }
1002
+ /**
1003
+ * The editor schema.
1004
+ */
995
1005
  get schema() {
996
1006
  return this.instance.schema;
997
1007
  }
998
1008
  get commands() {
999
1009
  return this.instance.commandAppliers;
1000
1010
  }
1011
+ /**
1012
+ * Whether the editor is focused.
1013
+ */
1014
+ get focused() {
1015
+ var _a, _b;
1016
+ return (_b = (_a = this.instance.view) == null ? void 0 : _a.hasFocus()) != null ? _b : false;
1017
+ }
1001
1018
  mount(place) {
1002
1019
  if (!place) {
1003
1020
  return this.unmount();
@@ -1010,6 +1027,20 @@ var Editor = class _Editor {
1010
1027
  this.instance.unmount();
1011
1028
  }
1012
1029
  }
1030
+ /**
1031
+ * Focus the editor.
1032
+ */
1033
+ focus() {
1034
+ var _a;
1035
+ (_a = this.instance.view) == null ? void 0 : _a.focus();
1036
+ }
1037
+ /**
1038
+ * Blur the editor.
1039
+ */
1040
+ blur() {
1041
+ var _a;
1042
+ (_a = this.instance.view) == null ? void 0 : _a.dom.blur();
1043
+ }
1013
1044
  use(extension) {
1014
1045
  if (!this.mounted) {
1015
1046
  let lazyRemove = null;
@@ -1024,6 +1055,9 @@ var Editor = class _Editor {
1024
1055
  this.instance.updateExtension(extension, "add");
1025
1056
  return () => this.instance.updateExtension(extension, "remove");
1026
1057
  }
1058
+ get state() {
1059
+ return this.instance.getState();
1060
+ }
1027
1061
  get nodes() {
1028
1062
  return this.instance.nodeBuilders;
1029
1063
  }
@@ -1326,6 +1360,28 @@ function defineDocChangeHandler(handler) {
1326
1360
  });
1327
1361
  }
1328
1362
 
1363
+ // src/extensions/events/focus.ts
1364
+ import { PluginKey as PluginKey2, ProseMirrorPlugin as ProseMirrorPlugin2 } from "@prosekit/pm/state";
1365
+ function defineFocusChangeHandler(handler) {
1366
+ const handleFocus = () => handler(true);
1367
+ const handleBlur = () => handler(false);
1368
+ const plugin = new ProseMirrorPlugin2({
1369
+ key: new PluginKey2("prosekit-focus-handler"),
1370
+ view: (view) => {
1371
+ const dom = view.dom;
1372
+ dom.addEventListener("focus", handleFocus);
1373
+ dom.addEventListener("blur", handleBlur);
1374
+ return {
1375
+ destroy: () => {
1376
+ dom.removeEventListener("focus", handleFocus);
1377
+ dom.removeEventListener("blur", handleBlur);
1378
+ }
1379
+ };
1380
+ }
1381
+ });
1382
+ return definePlugin(plugin);
1383
+ }
1384
+
1329
1385
  // src/extensions/history.ts
1330
1386
  import { history, redo, undo } from "@prosekit/pm/history";
1331
1387
 
@@ -1335,7 +1391,7 @@ var isMac = typeof navigator !== "undefined" ? /Mac|iP(hone|[ao]d)/.test(navigat
1335
1391
  // src/extensions/keymap.ts
1336
1392
  import { baseKeymap, chainCommands } from "@prosekit/pm/commands";
1337
1393
  import { keydownHandler } from "@prosekit/pm/keymap";
1338
- import { Plugin as Plugin3, PluginKey as PluginKey2 } from "@prosekit/pm/state";
1394
+ import { Plugin as Plugin3, PluginKey as PluginKey3 } from "@prosekit/pm/state";
1339
1395
  function defineKeymap(keymap) {
1340
1396
  return keymapFacet.extension([keymap]);
1341
1397
  }
@@ -1386,7 +1442,7 @@ function mergeKeymaps(keymaps) {
1386
1442
  ])
1387
1443
  );
1388
1444
  }
1389
- var keymapPluginKey = new PluginKey2("prosekit-keymap");
1445
+ var keymapPluginKey = new PluginKey3("prosekit-keymap");
1390
1446
 
1391
1447
  // src/extensions/history.ts
1392
1448
  function defineHistory() {
@@ -1525,7 +1581,7 @@ var markSpecFacet = Facet.define({
1525
1581
  });
1526
1582
 
1527
1583
  // src/extensions/node-view.ts
1528
- import { ProseMirrorPlugin as ProseMirrorPlugin2 } from "@prosekit/pm/state";
1584
+ import { ProseMirrorPlugin as ProseMirrorPlugin3 } from "@prosekit/pm/state";
1529
1585
  import "@prosekit/pm/view";
1530
1586
  function defineNodeView(options) {
1531
1587
  return nodeViewFacet.extension([options]);
@@ -1538,13 +1594,13 @@ var nodeViewFacet = Facet.define({
1538
1594
  nodeViews[input.name] = input.constructor;
1539
1595
  }
1540
1596
  }
1541
- return () => [new ProseMirrorPlugin2({ props: { nodeViews } })];
1597
+ return () => [new ProseMirrorPlugin3({ props: { nodeViews } })];
1542
1598
  },
1543
1599
  next: pluginFacet
1544
1600
  });
1545
1601
 
1546
1602
  // src/extensions/node-view-effect.ts
1547
- import { ProseMirrorPlugin as ProseMirrorPlugin3 } from "@prosekit/pm/state";
1603
+ import { ProseMirrorPlugin as ProseMirrorPlugin4 } from "@prosekit/pm/state";
1548
1604
  import "@prosekit/pm/view";
1549
1605
  function defineNodeViewFactory(options) {
1550
1606
  return nodeViewFactoryFacet.extension([options]);
@@ -1572,7 +1628,7 @@ var nodeViewFactoryFacet = Facet.define({
1572
1628
  nodeViews[name] = factory(args);
1573
1629
  }
1574
1630
  }
1575
- return () => [new ProseMirrorPlugin3({ props: { nodeViews } })];
1631
+ return () => [new ProseMirrorPlugin4({ props: { nodeViews } })];
1576
1632
  },
1577
1633
  next: pluginFacet
1578
1634
  });
@@ -1605,27 +1661,61 @@ function defineText() {
1605
1661
  import clsxLite from "clsx/lite";
1606
1662
  var clsx = clsxLite;
1607
1663
 
1664
+ // src/utils/default-block-at.ts
1665
+ function defaultBlockAt(match) {
1666
+ for (let i = 0; i < match.edgeCount; i++) {
1667
+ const { type } = match.edge(i);
1668
+ if (type.isTextblock && !type.hasRequiredAttrs())
1669
+ return type;
1670
+ }
1671
+ return null;
1672
+ }
1673
+
1608
1674
  // src/utils/get-id.ts
1609
1675
  var id = 0;
1610
1676
  function getId() {
1611
1677
  id = (id + 1) % Number.MAX_SAFE_INTEGER;
1612
1678
  return `id:${id}`;
1613
1679
  }
1680
+
1681
+ // src/utils/is-in-code-block.ts
1682
+ function isCodeBlockType(type) {
1683
+ return type.spec.code && type.isBlock;
1684
+ }
1685
+ function isInCodeBlock(selection) {
1686
+ return isCodeBlockType(selection.$from.parent.type) || isCodeBlockType(selection.$to.parent.type);
1687
+ }
1688
+
1689
+ // src/utils/unicode.ts
1690
+ var OBJECT_REPLACEMENT_CHARACTER = "\uFFFC";
1691
+
1692
+ // src/utils/with-skip-code-block.ts
1693
+ function withSkipCodeBlock(command) {
1694
+ return (state, dispatch, view) => {
1695
+ if (isInCodeBlock(state.selection)) {
1696
+ return false;
1697
+ }
1698
+ return command(state, dispatch, view);
1699
+ };
1700
+ }
1614
1701
  export {
1615
1702
  Editor,
1616
1703
  Facet,
1704
+ OBJECT_REPLACEMENT_CHARACTER,
1617
1705
  Priority,
1618
1706
  ProseKitError,
1619
1707
  getId as _getId,
1620
1708
  addMark,
1621
1709
  clsx,
1622
1710
  createEditor,
1711
+ defaultBlockAt,
1623
1712
  defineBaseCommands,
1624
1713
  defineBaseKeymap,
1625
1714
  defineCommands,
1626
1715
  defineDefaultState,
1627
1716
  defineDoc,
1628
1717
  defineDocChangeHandler,
1718
+ defineFocusChangeHandler,
1629
1719
  defineHistory,
1630
1720
  defineInputRule,
1631
1721
  defineKeymap,
@@ -1645,6 +1735,7 @@ export {
1645
1735
  getNodeType,
1646
1736
  insertNode,
1647
1737
  isAllSelection,
1738
+ isInCodeBlock,
1648
1739
  isMark,
1649
1740
  isNodeSelection,
1650
1741
  isProseMirrorNode,
@@ -1664,5 +1755,6 @@ export {
1664
1755
  toggleMark,
1665
1756
  toggleNode,
1666
1757
  union,
1667
- withPriority
1758
+ withPriority,
1759
+ withSkipCodeBlock
1668
1760
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@prosekit/core",
3
3
  "type": "module",
4
- "version": "0.2.3",
4
+ "version": "0.2.5",
5
5
  "private": false,
6
6
  "author": {
7
7
  "name": "ocavue",
@@ -44,7 +44,7 @@
44
44
  "@prosekit/dev": "*",
45
45
  "tsup": "^8.0.1",
46
46
  "typescript": "^5.3.3",
47
- "vitest": "^1.1.3"
47
+ "vitest": "^1.2.0"
48
48
  },
49
49
  "scripts": {
50
50
  "build:tsup": "tsup",
package/src/index.ts CHANGED
@@ -18,6 +18,10 @@ export {
18
18
  defineDocChangeHandler,
19
19
  type DocChangeHandler,
20
20
  } from './extensions/events/doc-change'
21
+ export {
22
+ defineFocusChangeHandler,
23
+ type FocusChangeHandler,
24
+ } from './extensions/events/focus'
21
25
  export {
22
26
  defineMountHandler,
23
27
  defineUnmountHandler,
@@ -75,9 +79,11 @@ export type { NodeJSON, SelectionJSON, StateJSON } from './types/model'
75
79
  export { Priority } from './types/priority'
76
80
  export { type SimplifyUnion } from './types/simplify-union'
77
81
  export { clsx } from './utils/clsx'
82
+ export { defaultBlockAt } from './utils/default-block-at'
78
83
  export { getId as _getId } from './utils/get-id'
79
84
  export { getMarkType } from './utils/get-mark-type'
80
85
  export { getNodeType } from './utils/get-node-type'
86
+ export { isInCodeBlock } from './utils/is-in-code-block'
81
87
  export {
82
88
  jsonFromElement,
83
89
  jsonFromHTML,
@@ -95,3 +101,5 @@ export {
95
101
  isProseMirrorNode,
96
102
  isTextSelection,
97
103
  } from './utils/type-assertion'
104
+ export * from './utils/unicode'
105
+ export { withSkipCodeBlock } from './utils/with-skip-code-block'