@meowdown/react 0.6.0 → 0.8.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/README.md CHANGED
@@ -5,8 +5,10 @@ React components for Meowdown, a hybrid (live-preview) Markdown editor.
5
5
  ## Usage
6
6
 
7
7
  ```tsx
8
- import { MeowdownEditor, type EditorHandle } from '@meowdown/react'
8
+ import '@meowdown/core/style.css'
9
9
  import '@meowdown/react/style.css'
10
+
11
+ import { MeowdownEditor, type EditorHandle } from '@meowdown/react'
10
12
  import { useRef, useCallback } from 'react'
11
13
 
12
14
  export function App() {
@@ -43,9 +45,9 @@ The Markdown editor component. Renders inside a `div.meowdown` wrapper that fill
43
45
  - `onWikilinkSearch?: (query: string) => WikilinkItem[] | Promise<WikilinkItem[]>`: enables the wikilink menu, which opens as soon as `[[` is typed in a rich mode. Returns ranked rows `{ target, label?, detail?, onSelect? }` (the menu does not re-sort). Selecting a row inserts `[[target]]` then runs its `onSelect`. Omit to disable.
44
46
  - `onWikilinkClick?: (payload: { target: string; event: MouseEvent }) => void`: called when a rendered wiki link is clicked. A plain click inside a link the caret already sits in just places the caret; `Mod`-click always fires. Pass a stable function (e.g. from `useCallback`). Ignored in source mode.
45
47
  - `resolveImageUrl?: (src: string) => string | undefined`: maps an image `src` to a displayable URL (or `undefined` to skip). Enables inline image rendering: `![alt](src)` stays literal text and the image renders beneath its line. Pass a stable function. Ignored in source mode.
46
- - `onImagePaste?: (file: File) => Promise<string | undefined>`: persists a pasted or dropped image file and returns its markdown `src` (or `undefined` to decline). Pass a stable function. Ignored in source mode.
47
- - `onImageSaveError?: (error: Error, file: File) => void`: called when `onImagePaste` throws. Defaults to `console.error`. Ignored in source mode.
48
- - `placeholder?: string | ((state) => string)`: placeholder text shown in an empty block. Pass a stable function. Ignored in source mode.
48
+ - `onImagePaste?: (file: File) => string | undefined | Promise<string | undefined>`: persists a pasted or dropped image file and returns its markdown `src` (or `undefined` to decline), synchronously or as a promise. Pass a stable function. Ignored in source mode.
49
+ - `onImageSaveError?: (error: unknown, file: File) => void`: called when `onImagePaste` throws. Defaults to `console.error`. Ignored in source mode.
50
+ - `placeholder?: string | ((state) => string)`: placeholder text shown when the whole document is empty. Pass a stable function. Ignored in source mode.
49
51
  - `readOnly?: boolean`: makes the editor read-only, in both the rich and source modes.
50
52
  - `spellCheck?: boolean`: toggles the browser's native spell checking in the rich modes. Defaults to the browser's behavior. Ignored in source mode.
51
53
  - `editorClassName?: string`: class on the editable root (the contenteditable). Rich modes only.
@@ -57,14 +59,6 @@ The Markdown editor component. Renders inside a `div.meowdown` wrapper that fill
57
59
 
58
60
  Re-exported from `@prosekit/react`. Call it from a component passed as `children` to read the live editor instance.
59
61
 
60
- ### `checkRoundTrip`
61
-
62
- Re-exported from `@meowdown/core`. `checkRoundTrip(markdown)` returns `'exact' | 'normalizing' | 'lossy'`, for hosts that gate saving markdown files on whether the editor reproduces them faithfully.
63
-
64
- ### `EDITOR_KEY_BINDINGS`
65
-
66
- Re-exported from `@meowdown/core`. A literal (`as const`) object mapping each editor shortcut (e.g. `Mod-b`, `Mod-1`) to its description, for host settings UIs and keybinding-collision checks.
67
-
68
62
  ### `EditorHandle`
69
63
 
70
64
  Imperative handle for the editor, attached via `handleRef`.
@@ -81,20 +75,9 @@ Imperative handle for the editor, attached via `handleRef`.
81
75
 
82
76
  Selection positions are in the mounted editor's coordinate space: ProseMirror document positions in the rich modes, character offsets in source mode. They round-trip within one mode but are not portable across a mode switch.
83
77
 
84
- ## Keyboard shortcuts
85
-
86
- In the rich modes (`focus` / `show` / `hide`), these toggle inline formatting on the selection (`Mod` = Cmd on macOS, Ctrl elsewhere):
87
-
88
- | Key | Action |
89
- | ------------- | -------------------- |
90
- | `Mod-B` | toggle bold |
91
- | `Mod-I` | toggle italic |
92
- | `Mod-E` | toggle inline code |
93
- | `Mod-Shift-X` | toggle strikethrough |
94
-
95
78
  ## Styling
96
79
 
97
- `@meowdown/react/style.css` includes the default theme from [`@meowdown/core`](https://www.npmjs.com/package/@meowdown/core).
80
+ Import both stylesheets: `@meowdown/core/style.css` (the editor theme and variables) and `@meowdown/react/style.css` (the component layout). The core theme is documented in [`@meowdown/core`](https://www.npmjs.com/package/@meowdown/core).
98
81
 
99
82
  ## License
100
83
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ReactNode, Ref } from "react";
2
- import { EDITOR_KEY_BINDINGS, ImageOptions, MarkMode, MarkMode as MarkMode$1, PlaceholderOptions, RoundTripFidelity, TypedEditor, TypedEditor as TypedEditor$1, WikilinkClickHandler, checkRoundTrip } from "@meowdown/core";
2
+ import { ImageOptions, MarkMode, PlaceholderOptions, TypedEditor, WikilinkClickHandler } from "@meowdown/core";
3
3
  import { SelectionJSON, SelectionJSON as SelectionJSON$1 } from "@prosekit/core";
4
4
  import { useEditor } from "@prosekit/react";
5
5
 
@@ -38,7 +38,7 @@ interface EditorHandle {
38
38
  /** Scrolls the selection into view. */
39
39
  scrollIntoView: () => void;
40
40
  /** Escape hatch: the underlying ProseKit editor, or `undefined` in source mode. */
41
- readonly editor: TypedEditor$1 | undefined;
41
+ readonly editor: TypedEditor | undefined;
42
42
  }
43
43
  /**
44
44
  /** One row in the tag menu. The host ranks the rows; the menu does not re-sort. */
@@ -77,7 +77,7 @@ interface WikilinkItem {
77
77
  type WikilinkSearchHandler = (query: string) => WikilinkItem[] | Promise<WikilinkItem[]>;
78
78
  //#endregion
79
79
  //#region src/components/editor.d.ts
80
- type EditorMode = MarkMode$1 | 'source';
80
+ type EditorMode = MarkMode | 'source';
81
81
  interface EditorProps {
82
82
  /**
83
83
  * The editor mode. The three rich modes ('focus', 'show', 'hide') render a ProseKit
@@ -131,8 +131,8 @@ interface EditorProps {
131
131
  /** Called when persisting a pasted/dropped image throws. Ignored in source mode. */
132
132
  onImageSaveError?: ImageOptions['onImageSaveError'];
133
133
  /**
134
- * Placeholder text shown in an empty block. A function receives the editor
135
- * state. Pass a stable function. Ignored in source mode.
134
+ * Placeholder text shown when the whole document is empty. A function
135
+ * receives the editor state. Pass a stable function. Ignored in source mode.
136
136
  */
137
137
  placeholder?: PlaceholderOptions['placeholder'];
138
138
  /** Makes the editor read-only, in both the rich and source modes. */
@@ -170,4 +170,4 @@ declare function MeowdownEditor({
170
170
  children
171
171
  }: EditorProps): import("react").JSX.Element;
172
172
  //#endregion
173
- export { EDITOR_KEY_BINDINGS, type EditorHandle, type EditorMode, type EditorProps, type EditorStateSnapshot, type MarkMode, MeowdownEditor, type RoundTripFidelity, type SelectionHint, type SelectionJSON, type TagItem, type TagSearchHandler, type TypedEditor, type WikilinkItem, type WikilinkSearchHandler, checkRoundTrip, useEditor };
173
+ export { type EditorHandle, type EditorMode, type EditorProps, type EditorStateSnapshot, MeowdownEditor, type SelectionHint, type SelectionJSON, type TagItem, type TagSearchHandler, type WikilinkItem, type WikilinkSearchHandler, useEditor };
package/dist/index.js CHANGED
@@ -7,14 +7,16 @@ import { Compartment, EditorSelection, EditorState } from "@codemirror/state";
7
7
  import { EditorView, keymap } from "@codemirror/view";
8
8
  import { clamp } from "@ocavue/utils";
9
9
  import { jsx, jsxs } from "react/jsx-runtime";
10
- import { EDITOR_KEY_BINDINGS, checkRoundTrip, codeBlockLanguages, defineEditorExtension, defineImages, defineMarkMode, definePlaceholder, defineReadonly, defineWikilinkClickHandler, docToMarkdown, markdownToDoc } from "@meowdown/core";
10
+ import { codeBlockLanguages, defineEditorExtension, defineImages, defineMarkMode, definePlaceholder, defineReadonly, defineWikilinkClickHandler, docToMarkdown, markdownToDoc } from "@meowdown/core";
11
11
  import { canUseRegexLookbehind, createEditor, defineDocChangeHandler, union } from "@prosekit/core";
12
12
  import { Selection, TextSelection } from "@prosekit/pm/state";
13
- import { ProseKit, defineReactNodeView, useEditor, useEditor as useEditor$1, useExtension } from "@prosekit/react";
13
+ import { ProseKit, defineReactNodeView, useEditor, useEditor as useEditor$1, useEditorDerivedValue, useExtension } from "@prosekit/react";
14
14
  import { Combobox } from "@base-ui/react/combobox";
15
15
  import { BlockHandleAdd, BlockHandleDraggable, BlockHandlePopup, BlockHandlePositioner, BlockHandleRoot } from "@prosekit/react/block-handle";
16
16
  import { DropIndicator } from "@prosekit/react/drop-indicator";
17
17
  import { AutocompleteEmpty, AutocompleteItem, AutocompletePopup, AutocompletePositioner, AutocompleteRoot } from "@prosekit/react/autocomplete";
18
+ import { MenuItem, MenuPopup, MenuPositioner } from "@prosekit/react/menu";
19
+ import { TableHandleColumnMenuRoot, TableHandleColumnMenuTrigger, TableHandleColumnPopup, TableHandleColumnPositioner, TableHandleDragPreview, TableHandleDropIndicator, TableHandleRoot, TableHandleRowMenuRoot, TableHandleRowMenuTrigger, TableHandleRowPopup, TableHandleRowPositioner } from "@prosekit/react/table-handle";
18
20
 
19
21
  //#region src/components/codemirror-editor.tsx
20
22
  function resolveSelection$1(selection, docLength) {
@@ -459,7 +461,10 @@ function EditorExtensions({ markMode, onDocChange, onWikilinkClick, resolveImage
459
461
  onImageSaveError
460
462
  ]));
461
463
  useExtension(useMemo(() => {
462
- return placeholder ? definePlaceholder({ placeholder }) : null;
464
+ return placeholder ? definePlaceholder({
465
+ placeholder,
466
+ strategy: "doc"
467
+ }) : null;
463
468
  }, [placeholder]));
464
469
  return null;
465
470
  }
@@ -542,7 +547,8 @@ function SlashMenu() {
542
547
  label: "Table",
543
548
  onSelect: () => editor.commands.insertTable({
544
549
  row: 3,
545
- col: 3
550
+ col: 3,
551
+ header: true
546
552
  })
547
553
  }),
548
554
  /* @__PURE__ */ jsx(AutocompleteEmpty, {
@@ -555,6 +561,212 @@ function SlashMenu() {
555
561
  });
556
562
  }
557
563
 
564
+ //#endregion
565
+ //#region src/components/icons/grip-horizontal-icon.tsx
566
+ function GripHorizontalIcon() {
567
+ return /* @__PURE__ */ jsxs("svg", {
568
+ viewBox: "0 0 24 24",
569
+ fill: "none",
570
+ stroke: "currentColor",
571
+ strokeWidth: 2,
572
+ strokeLinecap: "round",
573
+ strokeLinejoin: "round",
574
+ "aria-hidden": "true",
575
+ children: [
576
+ /* @__PURE__ */ jsx("circle", {
577
+ cx: "12",
578
+ cy: "9",
579
+ r: "1"
580
+ }),
581
+ /* @__PURE__ */ jsx("circle", {
582
+ cx: "19",
583
+ cy: "9",
584
+ r: "1"
585
+ }),
586
+ /* @__PURE__ */ jsx("circle", {
587
+ cx: "5",
588
+ cy: "9",
589
+ r: "1"
590
+ }),
591
+ /* @__PURE__ */ jsx("circle", {
592
+ cx: "12",
593
+ cy: "15",
594
+ r: "1"
595
+ }),
596
+ /* @__PURE__ */ jsx("circle", {
597
+ cx: "19",
598
+ cy: "15",
599
+ r: "1"
600
+ }),
601
+ /* @__PURE__ */ jsx("circle", {
602
+ cx: "5",
603
+ cy: "15",
604
+ r: "1"
605
+ })
606
+ ]
607
+ });
608
+ }
609
+
610
+ //#endregion
611
+ //#region src/components/table-handle.module.css
612
+ var table_handle_module_default = {
613
+ "ColumnPopup": "meow_ColumnPopup_hpZLgq",
614
+ "MenuItem": "meow_MenuItem_hpZLgq",
615
+ "MenuPopup": "meow_MenuPopup_hpZLgq",
616
+ "MenuPositioner": "meow_MenuPositioner_hpZLgq",
617
+ "Positioner": "meow_Positioner_hpZLgq",
618
+ "RowPopup": "meow_RowPopup_hpZLgq",
619
+ "Trigger": "meow_Trigger_hpZLgq"
620
+ };
621
+
622
+ //#endregion
623
+ //#region src/components/table-handle.tsx
624
+ function getTableHandleState(editor) {
625
+ const commands = editor.commands;
626
+ return {
627
+ addTableColumnBefore: {
628
+ canExec: commands.addTableColumnBefore.canExec(),
629
+ command: () => commands.addTableColumnBefore()
630
+ },
631
+ addTableColumnAfter: {
632
+ canExec: commands.addTableColumnAfter.canExec(),
633
+ command: () => commands.addTableColumnAfter()
634
+ },
635
+ addTableRowAbove: {
636
+ canExec: commands.addTableRowAbove.canExec(),
637
+ command: () => commands.addTableRowAbove()
638
+ },
639
+ addTableRowBelow: {
640
+ canExec: commands.addTableRowBelow.canExec(),
641
+ command: () => commands.addTableRowBelow()
642
+ },
643
+ deleteCellSelection: {
644
+ canExec: commands.deleteCellSelection.canExec(),
645
+ command: () => commands.deleteCellSelection()
646
+ },
647
+ deleteTableColumn: {
648
+ canExec: commands.deleteTableColumn.canExec(),
649
+ command: () => commands.deleteTableColumn()
650
+ },
651
+ deleteTableRow: {
652
+ canExec: commands.deleteTableRow.canExec(),
653
+ command: () => commands.deleteTableRow()
654
+ },
655
+ deleteTable: {
656
+ canExec: commands.deleteTable.canExec(),
657
+ command: () => commands.deleteTable()
658
+ }
659
+ };
660
+ }
661
+ function TableHandle() {
662
+ const state = useEditorDerivedValue(getTableHandleState);
663
+ return /* @__PURE__ */ jsxs(TableHandleRoot, { children: [
664
+ /* @__PURE__ */ jsx(TableHandleDragPreview, {}),
665
+ /* @__PURE__ */ jsx(TableHandleDropIndicator, {}),
666
+ /* @__PURE__ */ jsx(TableHandleColumnPositioner, {
667
+ className: table_handle_module_default.Positioner,
668
+ children: /* @__PURE__ */ jsx(TableHandleColumnPopup, {
669
+ className: table_handle_module_default.ColumnPopup,
670
+ children: /* @__PURE__ */ jsxs(TableHandleColumnMenuRoot, { children: [/* @__PURE__ */ jsx(TableHandleColumnMenuTrigger, {
671
+ className: table_handle_module_default.Trigger,
672
+ "data-testid": "table-handle-column",
673
+ children: /* @__PURE__ */ jsx(GripHorizontalIcon, {})
674
+ }), /* @__PURE__ */ jsx(MenuPositioner, {
675
+ className: table_handle_module_default.MenuPositioner,
676
+ children: /* @__PURE__ */ jsxs(MenuPopup, {
677
+ className: table_handle_module_default.MenuPopup,
678
+ "data-testid": "table-handle-column-menu",
679
+ children: [
680
+ state.addTableColumnBefore.canExec && /* @__PURE__ */ jsx(MenuItem, {
681
+ className: table_handle_module_default.MenuItem,
682
+ "data-testid": "table-insert-left",
683
+ onSelect: state.addTableColumnBefore.command,
684
+ children: /* @__PURE__ */ jsx("span", { children: "Insert Left" })
685
+ }),
686
+ state.addTableColumnAfter.canExec && /* @__PURE__ */ jsx(MenuItem, {
687
+ className: table_handle_module_default.MenuItem,
688
+ "data-testid": "table-insert-right",
689
+ onSelect: state.addTableColumnAfter.command,
690
+ children: /* @__PURE__ */ jsx("span", { children: "Insert Right" })
691
+ }),
692
+ state.deleteCellSelection.canExec && /* @__PURE__ */ jsxs(MenuItem, {
693
+ className: table_handle_module_default.MenuItem,
694
+ "data-testid": "table-clear-column",
695
+ onSelect: state.deleteCellSelection.command,
696
+ children: [/* @__PURE__ */ jsx("span", { children: "Clear Contents" }), /* @__PURE__ */ jsx("kbd", { children: "Del" })]
697
+ }),
698
+ state.deleteTableColumn.canExec && /* @__PURE__ */ jsx(MenuItem, {
699
+ className: table_handle_module_default.MenuItem,
700
+ "data-testid": "table-delete-column",
701
+ onSelect: state.deleteTableColumn.command,
702
+ children: /* @__PURE__ */ jsx("span", { children: "Delete Column" })
703
+ }),
704
+ state.deleteTable.canExec && /* @__PURE__ */ jsx(MenuItem, {
705
+ className: table_handle_module_default.MenuItem,
706
+ "data-danger": "",
707
+ "data-testid": "table-delete-table-column",
708
+ onSelect: state.deleteTable.command,
709
+ children: /* @__PURE__ */ jsx("span", { children: "Delete Table" })
710
+ })
711
+ ]
712
+ })
713
+ })] })
714
+ })
715
+ }),
716
+ /* @__PURE__ */ jsx(TableHandleRowPositioner, {
717
+ placement: "left",
718
+ className: table_handle_module_default.Positioner,
719
+ children: /* @__PURE__ */ jsx(TableHandleRowPopup, {
720
+ className: table_handle_module_default.RowPopup,
721
+ children: /* @__PURE__ */ jsxs(TableHandleRowMenuRoot, { children: [/* @__PURE__ */ jsx(TableHandleRowMenuTrigger, {
722
+ className: table_handle_module_default.Trigger,
723
+ "data-testid": "table-handle-row",
724
+ children: /* @__PURE__ */ jsx(GripVerticalIcon, {})
725
+ }), /* @__PURE__ */ jsx(MenuPositioner, {
726
+ className: table_handle_module_default.MenuPositioner,
727
+ children: /* @__PURE__ */ jsxs(MenuPopup, {
728
+ className: table_handle_module_default.MenuPopup,
729
+ "data-testid": "table-handle-row-menu",
730
+ children: [
731
+ state.addTableRowAbove.canExec && /* @__PURE__ */ jsx(MenuItem, {
732
+ className: table_handle_module_default.MenuItem,
733
+ "data-testid": "table-insert-above",
734
+ onSelect: state.addTableRowAbove.command,
735
+ children: /* @__PURE__ */ jsx("span", { children: "Insert Above" })
736
+ }),
737
+ state.addTableRowBelow.canExec && /* @__PURE__ */ jsx(MenuItem, {
738
+ className: table_handle_module_default.MenuItem,
739
+ "data-testid": "table-insert-below",
740
+ onSelect: state.addTableRowBelow.command,
741
+ children: /* @__PURE__ */ jsx("span", { children: "Insert Below" })
742
+ }),
743
+ state.deleteCellSelection.canExec && /* @__PURE__ */ jsxs(MenuItem, {
744
+ className: table_handle_module_default.MenuItem,
745
+ "data-testid": "table-clear-row",
746
+ onSelect: state.deleteCellSelection.command,
747
+ children: [/* @__PURE__ */ jsx("span", { children: "Clear Contents" }), /* @__PURE__ */ jsx("kbd", { children: "Del" })]
748
+ }),
749
+ state.deleteTableRow.canExec && /* @__PURE__ */ jsx(MenuItem, {
750
+ className: table_handle_module_default.MenuItem,
751
+ "data-testid": "table-delete-row",
752
+ onSelect: state.deleteTableRow.command,
753
+ children: /* @__PURE__ */ jsx("span", { children: "Delete Row" })
754
+ }),
755
+ state.deleteTable.canExec && /* @__PURE__ */ jsx(MenuItem, {
756
+ className: table_handle_module_default.MenuItem,
757
+ "data-danger": "",
758
+ "data-testid": "table-delete-table-row",
759
+ onSelect: state.deleteTable.command,
760
+ children: /* @__PURE__ */ jsx("span", { children: "Delete Table" })
761
+ })
762
+ ]
763
+ })
764
+ })] })
765
+ })
766
+ })
767
+ ] });
768
+ }
769
+
558
770
  //#endregion
559
771
  //#region src/utils/returns-true.ts
560
772
  function returnsTrue() {
@@ -777,6 +989,7 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTa
777
989
  readOnly
778
990
  }),
779
991
  /* @__PURE__ */ jsx(BlockHandle, {}),
992
+ !readOnly && /* @__PURE__ */ jsx(TableHandle, {}),
780
993
  /* @__PURE__ */ jsx(DropIndicator$1, {}),
781
994
  /* @__PURE__ */ jsx(SlashMenu, {}),
782
995
  onTagSearch && /* @__PURE__ */ jsx(TagMenu, { onTagSearch }),
@@ -866,4 +1079,4 @@ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onTagSea
866
1079
  }
867
1080
 
868
1081
  //#endregion
869
- export { EDITOR_KEY_BINDINGS, MeowdownEditor, checkRoundTrip, useEditor };
1082
+ export { MeowdownEditor, useEditor };
package/dist/style.css CHANGED
@@ -323,424 +323,146 @@
323
323
  flex-shrink: 0;
324
324
  font-size: .8125rem;
325
325
  }
326
- .ProseMirror {
327
- word-wrap: break-word;
328
- white-space: pre-wrap;
329
- white-space: break-spaces;
330
- -webkit-font-variant-ligatures: none;
331
- font-variant-ligatures: none;
332
- font-feature-settings: "liga" 0;
333
- position: relative;
334
- }
335
-
336
- .ProseMirror pre {
337
- white-space: pre-wrap;
338
- }
339
-
340
- .ProseMirror li {
341
- position: relative;
342
- }
343
-
344
- .ProseMirror-hideselection ::selection {
345
- background: none;
346
- }
347
-
348
- .ProseMirror-hideselection {
349
- caret-color: #0000;
350
- }
351
-
352
- .ProseMirror [draggable][contenteditable="false"] {
353
- user-select: text;
354
- }
355
-
356
- .ProseMirror-selectednode {
357
- outline: 2px solid #8cf;
358
- }
359
-
360
- li.ProseMirror-selectednode {
361
- outline: none;
362
- }
363
-
364
- li.ProseMirror-selectednode:after {
365
- content: "";
366
- pointer-events: none;
367
- border: 2px solid #8cf;
368
- position: absolute;
369
- inset: -2px -2px -2px -32px;
370
- }
371
-
372
- img.ProseMirror-separator {
373
- border: none !important;
374
- margin: 0 !important;
375
- display: inline !important;
376
- }
377
-
378
- :root {
379
- --prosekit-list-bullet-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='2.5' fill='currentColor'/%3E%3C/svg%3E");
380
- --prosekit-list-toggle-open-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpolygon points='8,10 12,14 16,10' fill='currentColor'/%3E%3C/svg%3E");
381
- --prosekit-list-toggle-closed-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpolygon points='10,8 14,12 10,16' fill='currentColor'/%3E%3C/svg%3E");
382
- }
383
-
384
- .prosemirror-flat-list {
385
- margin: 0;
386
- padding: 0;
387
- list-style: none;
388
- position: relative;
389
- }
390
-
391
- .prosemirror-flat-list > .list-marker {
392
- text-align: center;
393
- width: 1lh;
394
- height: 1lh;
395
- position: absolute;
396
- inset-inline-start: 0;
397
- }
398
-
399
- .prosemirror-flat-list > .list-content {
400
- margin-inline-start: 1lh;
401
- }
402
-
403
- .prosemirror-flat-list[data-list-kind="bullet"] > .list-marker, .prosemirror-flat-list[data-list-kind="toggle"] > .list-marker {
404
- background-color: currentColor;
405
- mask-position: center;
406
- mask-size: contain;
407
- mask-repeat: no-repeat;
408
- }
409
-
410
- .prosemirror-flat-list[data-list-kind="bullet"] > .list-marker {
411
- mask-image: var(--prosekit-list-bullet-icon);
412
- }
413
-
414
- .prosemirror-flat-list[data-list-kind="toggle"] > .list-marker {
415
- mask-image: var(--prosekit-list-toggle-open-icon);
416
- }
326
+ .meow_Positioner_hpZLgq, .meow_MenuPositioner_hpZLgq {
327
+ z-index: 50;
328
+ width: min-content;
329
+ height: min-content;
330
+ transition: transform .1s ease-out;
331
+ display: block;
332
+ overflow: visible;
417
333
 
418
- .prosemirror-flat-list[data-list-kind="toggle"][data-list-collapsable][data-list-collapsed] > .list-marker {
419
- mask-image: var(--prosekit-list-toggle-closed-icon);
334
+ @media (prefers-reduced-motion: reduce) {
335
+ transition: none;
336
+ }
420
337
  }
421
338
 
422
- .prosemirror-flat-list[data-list-kind="ordered"] > * {
423
- contain: style;
339
+ .meow_ColumnPopup_hpZLgq {
340
+ transform: translateY(50%);
424
341
  }
425
342
 
426
- .prosemirror-flat-list[data-list-kind="ordered"]:before {
427
- content: counter(prosemirror-flat-list-counter, decimal) ". ";
428
- font-variant-numeric: tabular-nums;
429
- position: absolute;
430
- inset-inline-end: calc(100% - 1lh);
343
+ .meow_RowPopup_hpZLgq {
344
+ transform: translateX(50%);
431
345
  }
432
346
 
433
- .prosemirror-flat-list[data-list-kind="ordered"] {
434
- counter-increment: prosemirror-flat-list-counter;
435
- }
347
+ .meow_ColumnPopup_hpZLgq, .meow_RowPopup_hpZLgq {
348
+ box-sizing: border-box;
349
+ transform-origin: var(--transform-origin);
350
+ transition: opacity .1s, scale .1s;
351
+ display: flex;
436
352
 
437
- .prosemirror-flat-list[data-list-kind="ordered"]:first-child, :not(.prosemirror-flat-list[data-list-kind="ordered"]) + .prosemirror-flat-list[data-list-kind="ordered"] {
438
- counter-reset: prosemirror-flat-list-counter;
439
- }
353
+ &[data-state="closed"] {
354
+ opacity: 0;
355
+ transition-duration: .15s;
356
+ scale: .95;
357
+ }
440
358
 
441
- @supports (counter-set: prosemirror-flat-list-counter 1) {
442
- :is(.prosemirror-flat-list[data-list-kind="ordered"]:first-child, :not(.prosemirror-flat-list[data-list-kind="ordered"]) + .prosemirror-flat-list[data-list-kind="ordered"])[data-list-order] {
443
- counter-set: prosemirror-flat-list-counter var(--prosemirror-flat-list-order);
359
+ @starting-style {
360
+ opacity: 0;
361
+ scale: .95;
444
362
  }
445
- }
446
363
 
447
- @supports not (counter-set: prosemirror-flat-list-counter 1) {
448
- :is(.prosemirror-flat-list[data-list-kind="ordered"]:first-child, :not(.prosemirror-flat-list[data-list-kind="ordered"]) + .prosemirror-flat-list[data-list-kind="ordered"])[data-list-order] {
449
- counter-increment: prosemirror-flat-list-counter var(--prosemirror-flat-list-order);
364
+ @media (prefers-reduced-motion: reduce) {
365
+ transition: none;
450
366
  }
451
367
  }
452
368
 
453
- .prosemirror-flat-list[data-list-kind="task"] > .list-marker, .prosemirror-flat-list[data-list-kind="task"] > .list-marker * {
454
- cursor: pointer;
369
+ .meow_Trigger_hpZLgq {
370
+ box-sizing: border-box;
371
+ border: 1px solid var(--meowdown-border);
372
+ color: color-mix(in oklab, var(--meowdown-muted) 50%, transparent);
373
+ cursor: grab;
374
+ background: light-dark(#fff, #18181b);
375
+ border-radius: .25rem;
376
+ outline: none;
455
377
  justify-content: center;
456
378
  align-items: center;
457
- margin: 0;
458
379
  padding: 0;
380
+ transition: background-color .1s;
459
381
  display: flex;
460
- }
461
-
462
- .prosemirror-flat-list[data-list-kind="toggle"][data-list-collapsable] > .list-marker {
463
- cursor: pointer;
464
- }
382
+ overflow: clip;
465
383
 
466
- .prosemirror-flat-list[data-list-kind="toggle"]:not([data-list-collapsable]) > .list-marker {
467
- opacity: .4;
468
- pointer-events: none;
469
- }
470
-
471
- .prosemirror-flat-list[data-list-kind="toggle"][data-list-collapsable][data-list-collapsed] > .list-content > :nth-child(n+2) {
472
- display: none;
473
- }
384
+ &:hover {
385
+ background: light-dark(#f4f4f5, #27272a);
386
+ }
474
387
 
475
- :root {
476
- --meowdown-text: light-dark(#3f3f46, #d4d4d8);
477
- --meowdown-heading: light-dark(#18181b, #fafafa);
478
- --meowdown-muted: light-dark(#52525b, #a1a1aa);
479
- --meowdown-accent: light-dark(#7c3aed, #c084fc);
480
- --meowdown-mark: light-dark(#a78bfa, #8b5cf6);
481
- --meowdown-border: light-dark(#e4e4e7, #3f3f46);
482
- --meowdown-code-bg: light-dark(#f4f4f5, #18181b);
483
- --meowdown-table-header-bg: light-dark(#fafafa, #27272a);
484
- --meowdown-font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
485
- --meowdown-node-outline: light-dark(#53f, #8870ff);
486
- --meowdown-node-selection: light-dark(#5533ff1a, #8870ff1f);
487
- --meowdown-selection: light-dark(#5533ff38, #8870ff4d);
488
- --meowdown-gutter: 3.5rem;
388
+ & svg {
389
+ width: 1.25rem;
390
+ height: 1.25rem;
391
+ display: block;
392
+ }
489
393
  }
490
394
 
491
- .ProseMirror {
395
+ .meow_MenuPopup_hpZLgq {
492
396
  box-sizing: border-box;
493
- padding: 1.25rem var(--meowdown-gutter) 1.75rem;
494
- color: var(--meowdown-text);
495
- caret-color: var(--meowdown-accent);
496
- -webkit-font-smoothing: antialiased;
397
+ overscroll-behavior: contain;
398
+ white-space: nowrap;
399
+ user-select: none;
400
+ border: 1px solid var(--meowdown-border);
401
+ min-width: 8rem;
402
+ max-height: 25rem;
403
+ transform-origin: var(--transform-origin);
404
+ background: light-dark(#fff, #18181b);
405
+ border-radius: .75rem;
497
406
  outline: none;
498
- font-size: 1.0625rem;
499
- line-height: 1.7;
500
- }
501
-
502
- .ProseMirror > * + * {
503
- margin-top: .85em;
504
- }
505
-
506
- .ProseMirror h1, .ProseMirror h2, .ProseMirror h3, .ProseMirror h4, .ProseMirror h5, .ProseMirror h6 {
507
- letter-spacing: -.01em;
508
- color: var(--meowdown-heading);
509
- font-weight: 600;
510
- line-height: 1.25;
511
- }
512
-
513
- .ProseMirror h1 {
514
- font-size: 1.75rem;
515
- }
516
-
517
- .ProseMirror h2 {
518
- font-size: 1.4rem;
519
- }
520
-
521
- .ProseMirror h3 {
522
- font-size: 1.2rem;
523
- }
524
-
525
- .ProseMirror h4 {
526
- font-size: 1.1rem;
527
- }
528
-
529
- .ProseMirror h5 {
530
- font-size: 1rem;
531
- }
532
-
533
- .ProseMirror h6 {
534
- font-size: .95rem;
535
- }
536
-
537
- .ProseMirror a {
538
- color: var(--meowdown-accent);
539
- text-underline-offset: 2px;
540
- text-decoration: underline 1px;
541
- }
542
-
543
- .ProseMirror code {
544
- font-family: var(--meowdown-font-mono);
545
- background: color-mix(in oklab, var(--meowdown-accent) 10%, transparent);
546
- color: color-mix(in oklab, var(--meowdown-accent) 80%, var(--meowdown-heading));
547
- border-radius: .35rem;
548
- padding: .1em .35em;
549
- font-size: .9em;
550
- }
551
-
552
- .ProseMirror blockquote {
553
- border-left: 3px solid color-mix(in oklab, var(--meowdown-accent) 35%, transparent);
554
- color: var(--meowdown-muted);
555
- margin-left: 0;
556
- padding-left: 1rem;
557
- font-style: italic;
558
- }
559
-
560
- .ProseMirror ul, .ProseMirror ol {
561
- padding-left: 1.5rem;
562
- }
563
-
564
- .ProseMirror ul {
565
- list-style: outside;
566
- }
567
-
568
- .ProseMirror ol {
569
- list-style: decimal;
570
- }
571
-
572
- .ProseMirror li {
573
- margin-top: .25em;
574
- }
575
-
576
- .ProseMirror pre {
577
- background: var(--meowdown-code-bg);
578
- font-family: var(--meowdown-font-mono);
579
- border-radius: .6rem;
580
- padding: .9rem 1rem;
581
- font-size: .9em;
582
- line-height: 1.5;
583
- overflow-x: auto;
584
- }
585
-
586
- .ProseMirror pre code {
587
- color: inherit;
588
- background: none;
589
- padding: 0;
590
- }
591
-
592
- .ProseMirror pre code .tok-keyword {
593
- color: light-dark(#cf222e, #ff7b72);
594
- }
595
-
596
- .ProseMirror pre code .tok-comment {
597
- color: light-dark(#6e7781, #8b949e);
598
- font-style: italic;
599
- }
600
-
601
- .ProseMirror pre code .tok-string, .ProseMirror pre code .tok-url {
602
- color: light-dark(#0a3069, #a5d6ff);
603
- }
604
-
605
- .ProseMirror pre code .tok-number, .ProseMirror pre code .tok-bool, .ProseMirror pre code .tok-atom, .ProseMirror pre code .tok-literal {
606
- color: light-dark(#0550ae, #79c0ff);
607
- }
608
-
609
- .ProseMirror pre code .tok-className, .ProseMirror pre code .tok-typeName, .ProseMirror pre code .tok-namespace {
610
- color: light-dark(#953800, #ffa657);
611
- }
612
-
613
- .ProseMirror pre code .tok-definition {
614
- color: light-dark(#8250df, #d2a8ff);
615
- }
616
-
617
- .ProseMirror pre code .tok-macroName, .ProseMirror pre code .tok-meta, .ProseMirror pre code .tok-inserted {
618
- color: light-dark(#116329, #7ee787);
619
- }
620
-
621
- .ProseMirror pre code .tok-invalid, .ProseMirror pre code .tok-deleted {
622
- color: light-dark(#82071e, #ffa198);
623
- }
624
-
625
- .ProseMirror pre code .tok-heading {
626
- color: light-dark(#0550ae, #79c0ff);
627
- font-weight: 600;
628
- }
629
-
630
- .ProseMirror pre code .tok-strong {
631
- font-weight: 600;
632
- }
633
-
634
- .ProseMirror pre code .tok-emphasis {
635
- font-style: italic;
636
- }
407
+ flex-direction: column;
408
+ padding: .25rem;
409
+ transition: opacity .1s, scale .1s;
410
+ display: flex;
411
+ overflow: auto;
412
+ box-shadow: 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;
637
413
 
638
- .ProseMirror pre code .tok-link {
639
- text-decoration: underline;
640
- }
414
+ &[data-state="closed"] {
415
+ opacity: 0;
416
+ transition-duration: .15s;
417
+ scale: .95;
418
+ }
641
419
 
642
- .ProseMirror hr {
643
- border: none;
644
- border-top: 1px solid var(--meowdown-border);
645
- margin: 1.5em 0;
646
- }
420
+ @starting-style {
421
+ opacity: 0;
422
+ scale: .95;
423
+ }
647
424
 
648
- .ProseMirror table {
649
- border-collapse: collapse;
650
- table-layout: fixed;
651
- width: 100%;
652
- overflow: hidden;
425
+ @media (prefers-reduced-motion: reduce) {
426
+ transition: none;
427
+ }
653
428
  }
654
429
 
655
- .ProseMirror td, .ProseMirror th {
430
+ .meow_MenuItem_hpZLgq {
656
431
  box-sizing: border-box;
657
- border: 1px solid var(--meowdown-border);
658
- vertical-align: top;
659
- text-align: left;
660
- padding: .4rem .75rem;
661
- }
662
-
663
- .ProseMirror th {
664
- color: var(--meowdown-heading);
665
- background: var(--meowdown-table-header-bg);
666
- font-weight: 600;
667
- }
668
-
669
- .ProseMirror table.ProseMirror-selectednode td, .ProseMirror table.ProseMirror-selectednode th {
670
- border-color: var(--meowdown-node-outline);
671
- }
672
-
673
- .ProseMirror .selectedCell {
674
- border: 1px double var(--meowdown-node-outline);
675
- background: var(--meowdown-node-selection);
676
- --meowdown-selection: transparent;
677
- caret-color: #0000;
678
- }
679
-
680
- .ProseMirror ::selection {
681
- background: var(--meowdown-selection);
682
- }
683
-
684
- .ProseMirror .ProseMirror-selectednode {
685
- --meowdown-selection: transparent;
686
- outline: 1px solid var(--meowdown-node-outline);
687
- background: var(--meowdown-node-selection);
688
- border-radius: 2px;
689
- }
690
-
691
- .ProseMirror pre.ProseMirror-selectednode {
692
- border-radius: .6rem;
693
- }
694
-
695
- .ProseMirror.prosekit-dragging {
696
- --meowdown-node-selection: transparent;
697
- }
698
-
699
- .ProseMirror .md-tag {
700
- background: color-mix(in oklab, var(--meowdown-accent) 10%, transparent);
701
- color: color-mix(in oklab, var(--meowdown-accent) 80%, var(--meowdown-heading));
702
- border-radius: .35rem;
703
- padding: .1em .35em;
704
- }
705
-
706
- .ProseMirror .md-wikilink {
707
- color: var(--meowdown-accent);
708
- text-underline-offset: 2px;
709
- cursor: pointer;
710
- text-decoration: underline 1px dashed;
711
- }
712
-
713
- .ProseMirror .md-image {
714
- display: block;
715
- }
716
-
717
- .ProseMirror .md-image img {
718
- max-height: var(--meowdown-image-max-height, 24rem);
719
- border-radius: var(--meowdown-image-radius, .5rem);
720
- max-width: 100%;
721
- }
432
+ color: var(--meowdown-text);
433
+ white-space: nowrap;
434
+ cursor: default;
435
+ user-select: none;
436
+ border-radius: .5rem;
437
+ outline: none;
438
+ justify-content: space-between;
439
+ align-items: center;
440
+ gap: 1.5rem;
441
+ padding: .375rem .75rem;
442
+ scroll-margin: .25rem;
443
+ font-size: .875rem;
444
+ display: flex;
722
445
 
723
- .ProseMirror .prosekit-placeholder:before {
724
- content: attr(data-placeholder);
725
- float: left;
726
- pointer-events: none;
727
- height: 0;
728
- color: var(--meowdown-placeholder, var(--meowdown-muted));
729
- }
446
+ &[data-highlighted] {
447
+ background: light-dark(#f4f4f5, #27272a);
448
+ }
730
449
 
731
- .ProseMirror .md-mark, .ProseMirror .md-link-uri {
732
- color: var(--meowdown-mark);
733
- opacity: .7;
734
- }
450
+ &[data-danger] {
451
+ color: light-dark(#ef4444, #f87171);
452
+ }
735
453
 
736
- .ProseMirror[data-mark-mode="hide"] .md-mark, .ProseMirror[data-mark-mode="hide"] .md-link-uri, .ProseMirror[data-mark-mode="focus"] .md-mark, .ProseMirror[data-mark-mode="focus"] .md-link-uri {
737
- display: none;
738
- }
454
+ &[data-disabled="true"] {
455
+ pointer-events: none;
456
+ opacity: .5;
457
+ }
739
458
 
740
- .ProseMirror[data-mark-mode="focus"] .md-mark:has(.show), .ProseMirror[data-mark-mode="focus"] .md-link-uri:has(.show) {
741
- display: inline;
459
+ & kbd {
460
+ font-family: var(--meowdown-font-mono);
461
+ color: var(--meowdown-muted);
462
+ opacity: .8;
463
+ font-size: .75rem;
464
+ }
742
465
  }
743
-
744
466
  .meowdown {
745
467
  flex-direction: column;
746
468
  flex: 1 0 auto;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meowdown/react",
3
3
  "type": "module",
4
- "version": "0.6.0",
4
+ "version": "0.8.0",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -28,7 +28,7 @@
28
28
  "@prosekit/pm": "^0.1.18",
29
29
  "@prosekit/react": "^0.8.0-beta.0",
30
30
  "clsx": "^2.1.1",
31
- "@meowdown/core": "0.5.0"
31
+ "@meowdown/core": "0.8.0"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "react": "^19.0.0",