@prosekit/preact 0.6.8 → 0.7.0-beta.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.
Files changed (117) hide show
  1. package/dist/prosekit-preact-autocomplete.d.ts +226 -18
  2. package/dist/prosekit-preact-autocomplete.d.ts.map +1 -1
  3. package/dist/prosekit-preact-autocomplete.js +218 -9
  4. package/dist/prosekit-preact-autocomplete.js.map +1 -1
  5. package/dist/prosekit-preact-block-handle.d.ts +210 -14
  6. package/dist/prosekit-preact-block-handle.d.ts.map +1 -1
  7. package/dist/prosekit-preact-block-handle.js +184 -7
  8. package/dist/prosekit-preact-block-handle.js.map +1 -1
  9. package/dist/prosekit-preact-drop-indicator.d.ts +27 -6
  10. package/dist/prosekit-preact-drop-indicator.d.ts.map +1 -1
  11. package/dist/prosekit-preact-drop-indicator.js +38 -3
  12. package/dist/prosekit-preact-drop-indicator.js.map +1 -1
  13. package/dist/prosekit-preact-inline-popover.d.ts +204 -8
  14. package/dist/prosekit-preact-inline-popover.d.ts.map +1 -1
  15. package/dist/prosekit-preact-inline-popover.js +130 -5
  16. package/dist/prosekit-preact-inline-popover.js.map +1 -1
  17. package/dist/prosekit-preact-menu.d.ts +288 -0
  18. package/dist/prosekit-preact-menu.d.ts.map +1 -0
  19. package/dist/prosekit-preact-menu.js +274 -0
  20. package/dist/prosekit-preact-menu.js.map +1 -0
  21. package/dist/prosekit-preact-popover.d.ts +227 -14
  22. package/dist/prosekit-preact-popover.d.ts.map +1 -1
  23. package/dist/prosekit-preact-popover.js +170 -7
  24. package/dist/prosekit-preact-popover.js.map +1 -1
  25. package/dist/prosekit-preact-resizable.d.ts +56 -12
  26. package/dist/prosekit-preact-resizable.d.ts.map +1 -1
  27. package/dist/prosekit-preact-resizable.js +80 -7
  28. package/dist/prosekit-preact-resizable.js.map +1 -1
  29. package/dist/prosekit-preact-table-handle.d.ts +447 -38
  30. package/dist/prosekit-preact-table-handle.d.ts.map +1 -1
  31. package/dist/prosekit-preact-table-handle.js +381 -19
  32. package/dist/prosekit-preact-table-handle.js.map +1 -1
  33. package/dist/prosekit-preact-tooltip.d.ts +211 -14
  34. package/dist/prosekit-preact-tooltip.d.ts.map +1 -1
  35. package/dist/prosekit-preact-tooltip.js +157 -7
  36. package/dist/prosekit-preact-tooltip.js.map +1 -1
  37. package/package.json +27 -16
  38. package/src/components/autocomplete/autocomplete-empty.gen.ts +41 -31
  39. package/src/components/autocomplete/autocomplete-item.gen.ts +84 -31
  40. package/src/components/autocomplete/autocomplete-popup.gen.ts +80 -0
  41. package/src/components/autocomplete/autocomplete-positioner.gen.ts +153 -0
  42. package/src/components/autocomplete/autocomplete-root.gen.ts +109 -0
  43. package/src/components/autocomplete/index.gen.ts +12 -4
  44. package/src/components/autocomplete/index.ts +27 -0
  45. package/src/components/block-handle/block-handle-add.gen.ts +59 -31
  46. package/src/components/block-handle/block-handle-draggable.gen.ts +59 -31
  47. package/src/components/block-handle/block-handle-popup.gen.ts +44 -0
  48. package/src/components/block-handle/block-handle-positioner.gen.ts +171 -0
  49. package/src/components/block-handle/block-handle-root.gen.ts +84 -0
  50. package/src/components/block-handle/index.gen.ts +13 -3
  51. package/src/components/block-handle/index.ts +27 -0
  52. package/src/components/drop-indicator/drop-indicator.gen.ts +65 -31
  53. package/src/components/drop-indicator/index.gen.ts +5 -1
  54. package/src/components/drop-indicator/index.ts +14 -0
  55. package/src/components/inline-popover/index.gen.ts +11 -1
  56. package/src/components/inline-popover/index.ts +22 -0
  57. package/src/components/inline-popover/inline-popover-popup.gen.ts +44 -0
  58. package/src/components/inline-popover/inline-popover-positioner.gen.ts +177 -0
  59. package/src/components/inline-popover/inline-popover-root.gen.ts +108 -0
  60. package/src/components/menu/index.gen.ts +19 -0
  61. package/src/components/menu/index.ts +37 -0
  62. package/src/components/menu/menu-item.gen.ts +91 -0
  63. package/src/components/menu/menu-popup.gen.ts +58 -0
  64. package/src/components/menu/menu-positioner.gen.ts +178 -0
  65. package/src/components/menu/menu-root.gen.ts +88 -0
  66. package/src/components/menu/menu-submenu-root.gen.ts +44 -0
  67. package/src/components/menu/menu-submenu-trigger.gen.ts +44 -0
  68. package/src/components/menu/menu-trigger.gen.ts +79 -0
  69. package/src/components/popover/index.gen.ts +11 -3
  70. package/src/components/popover/index.ts +24 -0
  71. package/src/components/popover/popover-popup.gen.ts +44 -0
  72. package/src/components/popover/popover-positioner.gen.ts +178 -0
  73. package/src/components/popover/popover-root.gen.ts +92 -31
  74. package/src/components/popover/popover-trigger.gen.ts +92 -31
  75. package/src/components/resizable/index.gen.ts +8 -2
  76. package/src/components/resizable/index.ts +20 -0
  77. package/src/components/resizable/resizable-handle.gen.ts +54 -31
  78. package/src/components/resizable/resizable-root.gen.ts +90 -31
  79. package/src/components/table-handle/index.gen.ts +17 -9
  80. package/src/components/table-handle/index.ts +58 -0
  81. package/src/components/table-handle/table-handle-column-menu-root.gen.ts +66 -0
  82. package/src/components/table-handle/table-handle-column-menu-trigger.gen.ts +60 -0
  83. package/src/components/table-handle/table-handle-column-popup.gen.ts +44 -0
  84. package/src/components/table-handle/table-handle-column-positioner.gen.ts +201 -0
  85. package/src/components/table-handle/table-handle-drag-preview.gen.ts +57 -31
  86. package/src/components/table-handle/table-handle-drop-indicator.gen.ts +57 -31
  87. package/src/components/table-handle/table-handle-root.gen.ts +59 -31
  88. package/src/components/table-handle/table-handle-row-menu-root.gen.ts +66 -0
  89. package/src/components/table-handle/table-handle-row-menu-trigger.gen.ts +60 -0
  90. package/src/components/table-handle/table-handle-row-popup.gen.ts +44 -0
  91. package/src/components/table-handle/table-handle-row-positioner.gen.ts +201 -0
  92. package/src/components/tooltip/index.gen.ts +11 -3
  93. package/src/components/tooltip/index.ts +24 -0
  94. package/src/components/tooltip/tooltip-popup.gen.ts +44 -0
  95. package/src/components/tooltip/tooltip-positioner.gen.ts +178 -0
  96. package/src/components/tooltip/tooltip-root.gen.ts +85 -31
  97. package/src/components/tooltip/tooltip-trigger.gen.ts +63 -31
  98. package/src/extensions/preact-node-view.spec.ts +151 -0
  99. package/dist/create-component.js +0 -95
  100. package/dist/create-component.js.map +0 -1
  101. package/dist/create-props.d.ts +0 -6
  102. package/dist/create-props.d.ts.map +0 -1
  103. package/src/components/autocomplete/autocomplete-list.gen.ts +0 -34
  104. package/src/components/autocomplete/autocomplete-popover.gen.ts +0 -34
  105. package/src/components/block-handle/block-handle-popover.gen.ts +0 -34
  106. package/src/components/create-component.ts +0 -123
  107. package/src/components/create-props.ts +0 -13
  108. package/src/components/inline-popover/inline-popover.gen.ts +0 -34
  109. package/src/components/merge-refs.ts +0 -35
  110. package/src/components/popover/popover-content.gen.ts +0 -34
  111. package/src/components/table-handle/table-handle-column-root.gen.ts +0 -34
  112. package/src/components/table-handle/table-handle-column-trigger.gen.ts +0 -34
  113. package/src/components/table-handle/table-handle-popover-content.gen.ts +0 -34
  114. package/src/components/table-handle/table-handle-popover-item.gen.ts +0 -34
  115. package/src/components/table-handle/table-handle-row-root.gen.ts +0 -34
  116. package/src/components/table-handle/table-handle-row-trigger.gen.ts +0 -34
  117. package/src/components/tooltip/tooltip-content.gen.ts +0 -34
@@ -0,0 +1,151 @@
1
+ /* eslint-disable @eslint-react/component-hook-factories */
2
+
3
+ import { createEditor, union, type NodeJSON } from '@prosekit/core'
4
+ import { defineTestExtension, type ImageAttrs } from '@prosekit/testing'
5
+ import { createElement } from 'preact'
6
+ import { useEffect, useState } from 'preact/hooks'
7
+ import { beforeEach, describe, expect, it } from 'vitest'
8
+ import { render } from 'vitest-browser-preact'
9
+ import { page } from 'vitest/browser'
10
+
11
+ import { ProseKit } from '../components/prosekit.ts'
12
+
13
+ import { definePreactNodeView, type PreactNodeViewComponent, type PreactNodeViewProps } from './preact-node-view.ts'
14
+
15
+ describe('PreactNodeView', () => {
16
+ const initialState = {
17
+ imageRefresh: {
18
+ mounted: 0,
19
+ unmounted: 0,
20
+ setAttrs: 0,
21
+ },
22
+ }
23
+
24
+ let state = structuredClone(initialState)
25
+
26
+ beforeEach(() => {
27
+ state = structuredClone(initialState)
28
+ })
29
+
30
+ function defineExtension() {
31
+ return union(
32
+ defineTestExtension(),
33
+ definePreactNodeView({
34
+ name: 'image',
35
+ component: ImageRefreshView satisfies PreactNodeViewComponent,
36
+ }),
37
+ )
38
+ }
39
+
40
+ function ImageRefreshView(props: PreactNodeViewProps) {
41
+ const url = (props.node.attrs as ImageAttrs).src
42
+ const setAttrs = props.setAttrs
43
+
44
+ useEffect(() => {
45
+ state.imageRefresh.mounted++
46
+ const id = setInterval(() => {
47
+ state.imageRefresh.setAttrs++
48
+ setAttrs({ src: String(Math.random()) })
49
+ }, 50)
50
+ return () => {
51
+ state.imageRefresh.unmounted++
52
+ clearInterval(id)
53
+ }
54
+ }, [setAttrs])
55
+
56
+ return createElement('div', {
57
+ 'data-testid': 'image-refresh-view',
58
+ 'data-url': url,
59
+ })
60
+ }
61
+
62
+ function TestEditor(props: { initialContent?: NodeJSON }) {
63
+ const [editor] = useState(() => {
64
+ return createEditor({
65
+ extension: defineExtension(),
66
+ defaultContent: props.initialContent,
67
+ })
68
+ })
69
+
70
+ return createElement(
71
+ ProseKit,
72
+ { editor },
73
+ createElement('div', {
74
+ 'data-testid': 'editor',
75
+ 'ref': editor.mount,
76
+ }),
77
+ )
78
+ }
79
+
80
+ const paragraphJSON: NodeJSON = {
81
+ type: 'paragraph',
82
+ content: [{ type: 'text', text: 'Hello' }],
83
+ }
84
+ const imageRefreshJSON: NodeJSON = {
85
+ type: 'image',
86
+ }
87
+
88
+ const editor = page.getByTestId('editor')
89
+ const imageRefresh = page.getByTestId('image-refresh-view')
90
+
91
+ it('can render a single self-update image node', async () => {
92
+ const initialContent: NodeJSON = {
93
+ type: 'doc',
94
+ content: [imageRefreshJSON, paragraphJSON],
95
+ }
96
+ const screen = render(createElement(TestEditor, { initialContent }))
97
+ await expect.element(editor).toBeVisible()
98
+ await expect.element(imageRefresh).toBeInTheDocument()
99
+
100
+ const urls = new Set<string>()
101
+ const check = () => {
102
+ imageRefresh.elements().forEach((element) => {
103
+ const url = element.getAttribute('data-url')
104
+ if (url) {
105
+ urls.add(url)
106
+ }
107
+ })
108
+ return urls.size >= 5
109
+ }
110
+
111
+ await expect.poll(check, { interval: 50, timeout: 30_000 }).toBe(true)
112
+
113
+ screen.unmount()
114
+
115
+ expect(state.imageRefresh.setAttrs).toBeGreaterThanOrEqual(5)
116
+ expect(state.imageRefresh.mounted).toBe(1)
117
+ expect(state.imageRefresh.unmounted).toBe(1)
118
+ })
119
+
120
+ it('can render multiple self-update image nodes', async () => {
121
+ const initialContent: NodeJSON = {
122
+ type: 'doc',
123
+ content: [imageRefreshJSON, paragraphJSON, imageRefreshJSON, imageRefreshJSON],
124
+ }
125
+ const screen = render(createElement(TestEditor, { initialContent }))
126
+ await expect.element(editor).toBeVisible()
127
+ await expect.element(imageRefresh.nth(0)).toBeInTheDocument()
128
+ await expect.element(imageRefresh.nth(1)).toBeInTheDocument()
129
+ await expect.element(imageRefresh.nth(2)).toBeInTheDocument()
130
+ await expect.element(imageRefresh.nth(3)).not.toBeInTheDocument()
131
+
132
+ const urls = new Set<string>()
133
+ const check = () => {
134
+ imageRefresh.elements().forEach((element) => {
135
+ const url = element.getAttribute('data-url')
136
+ if (url) {
137
+ urls.add(url)
138
+ }
139
+ })
140
+ return urls.size >= 15
141
+ }
142
+
143
+ await expect.poll(check, { interval: 50, timeout: 30_000 }).toBe(true)
144
+
145
+ screen.unmount()
146
+
147
+ expect(state.imageRefresh.setAttrs).toBeGreaterThanOrEqual(15)
148
+ expect(state.imageRefresh.mounted).toBe(3)
149
+ expect(state.imageRefresh.unmounted).toBe(3)
150
+ })
151
+ })
@@ -1,95 +0,0 @@
1
- import { n as useEditorContext } from "./editor-context.js";
2
- import { createElement } from "preact";
3
- import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "preact/hooks";
4
- import { forwardRef } from "preact/compat";
5
- //#region src/components/merge-refs.ts
6
- /**
7
- * Assigns a value to a ref.
8
- * @returns The ref cleanup callback, if any.
9
- */
10
- function assignRef(ref, value) {
11
- if (typeof ref === "function") return ref(value);
12
- else if (ref) ref.current = value;
13
- }
14
- /**
15
- * Merges multiple refs into a single one.
16
- */
17
- function mergeRefs(refs) {
18
- return (value) => {
19
- const cleanups = [];
20
- for (const ref of refs) {
21
- const cleanup = assignRef(ref, value);
22
- const isCleanup = typeof cleanup === "function";
23
- cleanups.push(isCleanup ? cleanup : () => assignRef(ref, null));
24
- }
25
- return () => {
26
- for (const cleanup of cleanups) cleanup();
27
- };
28
- };
29
- }
30
- //#endregion
31
- //#region src/components/create-component.ts
32
- const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
33
- function createComponent(tagName, displayName, propNames, eventNames) {
34
- const hasEditor = propNames.includes("editor");
35
- const lowerCaseEventNameMap = new Map(eventNames.map((name) => [name.toLowerCase(), name]));
36
- const Component = forwardRef((props, ref) => {
37
- const [el, setEl] = useState(null);
38
- const properties = {};
39
- const attributes = {};
40
- const eventHandlersRef = useRef({});
41
- const eventHandlers = {};
42
- for (const [name, value] of Object.entries(props)) {
43
- if (value === void 0) continue;
44
- if (propNames.includes(name)) {
45
- properties[name] = value;
46
- continue;
47
- }
48
- if (name.startsWith("on")) {
49
- const lowerCaseEventName = name.slice(2).toLowerCase();
50
- const eventName = lowerCaseEventNameMap.get(lowerCaseEventName);
51
- if (eventName) {
52
- const extractDetail = eventName.endsWith("Change");
53
- eventHandlers[eventName] = (event) => {
54
- const handler = value;
55
- if (typeof handler === "function") handler(extractDetail ? event.detail : event);
56
- };
57
- continue;
58
- }
59
- }
60
- if (name === "className") attributes["class"] = value;
61
- else attributes[name] = value;
62
- }
63
- const editor = useEditorContext();
64
- if (hasEditor && editor && !properties["editor"]) properties["editor"] = editor;
65
- useIsomorphicLayoutEffect(() => {
66
- if (!el) return;
67
- for (const [name, value] of Object.entries(properties)) if (value !== void 0) el[name] = value;
68
- }, [el, ...propNames.map((name) => properties[name])]);
69
- useIsomorphicLayoutEffect(() => {
70
- eventHandlersRef.current = eventHandlers;
71
- });
72
- useIsomorphicLayoutEffect(() => {
73
- if (!el) return;
74
- const fixedEventHandlers = {};
75
- for (const eventName of eventNames) fixedEventHandlers[eventName] = (event) => {
76
- eventHandlersRef.current[eventName]?.(event);
77
- };
78
- for (const [name, handler] of Object.entries(fixedEventHandlers)) el.addEventListener(name, handler);
79
- return () => {
80
- for (const [name, handler] of Object.entries(fixedEventHandlers)) el.removeEventListener(name, handler);
81
- };
82
- }, [el]);
83
- const mergedRef = useMemo(() => mergeRefs([ref, setEl]), [ref]);
84
- return createElement(tagName, {
85
- ...attributes,
86
- ref: mergedRef
87
- });
88
- });
89
- Component.displayName = displayName;
90
- return Component;
91
- }
92
- //#endregion
93
- export { createComponent as t };
94
-
95
- //# sourceMappingURL=create-component.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-component.js","names":[],"sources":["../src/components/merge-refs.ts","../src/components/create-component.ts"],"sourcesContent":["import type { Ref } from 'preact'\n\n/**\n * Assigns a value to a ref.\n * @returns The ref cleanup callback, if any.\n */\nfunction assignRef<T>(\n ref: Ref<T> | undefined,\n value: T | null,\n): VoidFunction | void {\n if (typeof ref === 'function') {\n return ref(value)\n } else if (ref) {\n ref.current = value\n }\n}\n\n/**\n * Merges multiple refs into a single one.\n */\nexport function mergeRefs<T>(refs: (Ref<T> | undefined)[]): Ref<T> {\n return (value: T | null) => {\n const cleanups: VoidFunction[] = []\n\n for (const ref of refs) {\n const cleanup = assignRef(ref, value)\n const isCleanup = typeof cleanup === 'function'\n cleanups.push(isCleanup ? cleanup : () => assignRef(ref, null))\n }\n\n return () => {\n for (const cleanup of cleanups) cleanup()\n }\n }\n}\n","import type { AnyFunction } from '@prosekit/core'\nimport { createElement } from 'preact'\nimport { forwardRef, type ForwardRefExoticComponent, type HTMLAttributes, type RefAttributes } from 'preact/compat'\nimport { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'preact/hooks'\n\nimport { useEditorContext } from '../contexts/editor-context.ts'\n\nimport { mergeRefs } from './merge-refs.ts'\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect\n\nexport function createComponent<\n Props extends object,\n CustomElement extends HTMLElement,\n>(\n tagName: string,\n displayName: string,\n propNames: string[],\n eventNames: string[],\n): ForwardRefExoticComponent<\n Partial<Props> & RefAttributes<CustomElement> & HTMLAttributes<CustomElement>\n> {\n const hasEditor = propNames.includes('editor')\n const lowerCaseEventNameMap = new Map(\n eventNames.map((name) => [name.toLowerCase(), name]),\n )\n\n const Component = forwardRef<any, any>((props: Props, ref) => {\n const [el, setEl] = useState<HTMLElement | null>(null)\n\n const properties: Record<string, unknown> = {}\n const attributes: Record<string, unknown> = {}\n const eventHandlersRef = useRef<Record<string, AnyFunction>>({})\n const eventHandlers: Record<string, AnyFunction> = {}\n\n for (const [name, value] of Object.entries(props)) {\n if (value === undefined) {\n continue\n }\n\n if (propNames.includes(name)) {\n properties[name] = value\n continue\n }\n\n if (name.startsWith('on')) {\n const lowerCaseEventName = name.slice(2).toLowerCase()\n const eventName = lowerCaseEventNameMap.get(lowerCaseEventName)\n if (eventName) {\n const extractDetail = eventName.endsWith('Change')\n eventHandlers[eventName] = (event: Event) => {\n const handler = value as AnyFunction | null\n if (typeof handler === 'function') {\n handler(extractDetail ? (event as CustomEvent).detail : event)\n }\n }\n continue\n }\n }\n\n if (name === 'className') {\n attributes['class'] = value\n } else {\n attributes[name] = value\n }\n }\n\n const editor = useEditorContext()\n\n if (hasEditor && editor && !properties['editor']) {\n properties['editor'] = editor\n }\n\n // Set all properties.\n useIsomorphicLayoutEffect(() => {\n if (!el) return\n for (const [name, value] of Object.entries(properties)) {\n if (value !== undefined) {\n // @ts-expect-error: we know that name is a valid property name\n el[name] = value\n }\n }\n }, [el, ...propNames.map((name) => properties[name])])\n\n // Put all event listeners extracted from `props` into `eventHandlersRef`.\n useIsomorphicLayoutEffect(() => {\n eventHandlersRef.current = eventHandlers\n })\n\n // Register the event listeners to the element.\n useIsomorphicLayoutEffect(() => {\n if (!el) {\n return\n }\n\n const fixedEventHandlers: Record<string, AnyFunction> = {}\n\n for (const eventName of eventNames) {\n fixedEventHandlers[eventName] = (event: Event) => {\n eventHandlersRef.current[eventName]?.(event)\n }\n }\n\n for (const [name, handler] of Object.entries(fixedEventHandlers)) {\n el.addEventListener(name, handler)\n }\n\n return () => {\n for (const [name, handler] of Object.entries(fixedEventHandlers)) {\n el.removeEventListener(name, handler)\n }\n }\n }, [el])\n\n const mergedRef = useMemo(() => mergeRefs([ref, setEl]), [ref])\n\n return createElement(tagName, { ...attributes, ref: mergedRef })\n })\n\n Component.displayName = displayName\n\n return Component\n}\n"],"mappings":";;;;;;;;;AAMA,SAAS,UACP,KACA,OACqB;AACrB,KAAI,OAAO,QAAQ,WACjB,QAAO,IAAI,MAAM;UACR,IACT,KAAI,UAAU;;;;;AAOlB,SAAgB,UAAa,MAAsC;AACjE,SAAQ,UAAoB;EAC1B,MAAM,WAA2B,EAAE;AAEnC,OAAK,MAAM,OAAO,MAAM;GACtB,MAAM,UAAU,UAAU,KAAK,MAAM;GACrC,MAAM,YAAY,OAAO,YAAY;AACrC,YAAS,KAAK,YAAY,gBAAgB,UAAU,KAAK,KAAK,CAAC;;AAGjE,eAAa;AACX,QAAK,MAAM,WAAW,SAAU,UAAS;;;;;;ACtB/C,MAAM,4BAA4B,OAAO,WAAW,cAAc,kBAAkB;AAEpF,SAAgB,gBAId,SACA,aACA,WACA,YAGA;CACA,MAAM,YAAY,UAAU,SAAS,SAAS;CAC9C,MAAM,wBAAwB,IAAI,IAChC,WAAW,KAAK,SAAS,CAAC,KAAK,aAAa,EAAE,KAAK,CAAC,CACrD;CAED,MAAM,YAAY,YAAsB,OAAc,QAAQ;EAC5D,MAAM,CAAC,IAAI,SAAS,SAA6B,KAAK;EAEtD,MAAM,aAAsC,EAAE;EAC9C,MAAM,aAAsC,EAAE;EAC9C,MAAM,mBAAmB,OAAoC,EAAE,CAAC;EAChE,MAAM,gBAA6C,EAAE;AAErD,OAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,MAAM,EAAE;AACjD,OAAI,UAAU,KAAA,EACZ;AAGF,OAAI,UAAU,SAAS,KAAK,EAAE;AAC5B,eAAW,QAAQ;AACnB;;AAGF,OAAI,KAAK,WAAW,KAAK,EAAE;IACzB,MAAM,qBAAqB,KAAK,MAAM,EAAE,CAAC,aAAa;IACtD,MAAM,YAAY,sBAAsB,IAAI,mBAAmB;AAC/D,QAAI,WAAW;KACb,MAAM,gBAAgB,UAAU,SAAS,SAAS;AAClD,mBAAc,cAAc,UAAiB;MAC3C,MAAM,UAAU;AAChB,UAAI,OAAO,YAAY,WACrB,SAAQ,gBAAiB,MAAsB,SAAS,MAAM;;AAGlE;;;AAIJ,OAAI,SAAS,YACX,YAAW,WAAW;OAEtB,YAAW,QAAQ;;EAIvB,MAAM,SAAS,kBAAkB;AAEjC,MAAI,aAAa,UAAU,CAAC,WAAW,UACrC,YAAW,YAAY;AAIzB,kCAAgC;AAC9B,OAAI,CAAC,GAAI;AACT,QAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,WAAW,CACpD,KAAI,UAAU,KAAA,EAEZ,IAAG,QAAQ;KAGd,CAAC,IAAI,GAAG,UAAU,KAAK,SAAS,WAAW,MAAM,CAAC,CAAC;AAGtD,kCAAgC;AAC9B,oBAAiB,UAAU;IAC3B;AAGF,kCAAgC;AAC9B,OAAI,CAAC,GACH;GAGF,MAAM,qBAAkD,EAAE;AAE1D,QAAK,MAAM,aAAa,WACtB,oBAAmB,cAAc,UAAiB;AAChD,qBAAiB,QAAQ,aAAa,MAAM;;AAIhD,QAAK,MAAM,CAAC,MAAM,YAAY,OAAO,QAAQ,mBAAmB,CAC9D,IAAG,iBAAiB,MAAM,QAAQ;AAGpC,gBAAa;AACX,SAAK,MAAM,CAAC,MAAM,YAAY,OAAO,QAAQ,mBAAmB,CAC9D,IAAG,oBAAoB,MAAM,QAAQ;;KAGxC,CAAC,GAAG,CAAC;EAER,MAAM,YAAY,cAAc,UAAU,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC;AAE/D,SAAO,cAAc,SAAS;GAAE,GAAG;GAAY,KAAK;GAAW,CAAC;GAChE;AAEF,WAAU,cAAc;AAExB,QAAO"}
@@ -1,6 +0,0 @@
1
- //#region src/components/create-props.d.ts
2
- type CreateProps<Props extends { [PropName in keyof Props]: unknown }, Events extends { [EventName in keyof Events]: CustomEvent }> = Props & CreateEventProps<Events>;
3
- type CreateEventProps<Events extends { [EventName in keyof Events]: CustomEvent }> = { [EventName in keyof Events as `on${Capitalize<string & EventName>}`]: (event: EventName extends `${string}Change` ? Events[EventName]['detail'] : Events[EventName]) => void };
4
- //#endregion
5
- export { CreateProps as t };
6
- //# sourceMappingURL=create-props.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-props.d.ts","names":[],"sources":["../src/components/create-props.ts"],"mappings":";KAAY,WAAA,oCACyB,KAAA,mDACE,MAAA,GAAS,WAAA,MAC5C,KAAA,GAAQ,gBAAA,CAAiB,MAAA;AAAA,KAExB,gBAAA,sCACkC,MAAA,GAAS,WAAA,4BAE1B,MAAA,SAAe,UAAA,UAAoB,SAAA,OACrD,KAAA,EAAO,SAAA,6BAAsC,MAAA,CAAO,SAAA,cAChD,MAAA,CAAO,SAAA"}
@@ -1,34 +0,0 @@
1
- import {
2
- type AutocompleteListElement,
3
- type AutocompleteListProps as Props,
4
- type AutocompleteListEvents as Events,
5
- autocompleteListProps,
6
- autocompleteListEvents,
7
- } from '@prosekit/web/autocomplete'
8
- import type {
9
- ForwardRefExoticComponent,
10
- HTMLAttributes,
11
- RefAttributes,
12
- } from 'preact/compat'
13
-
14
- import { createComponent } from '../create-component.ts'
15
- import type { CreateProps } from '../create-props.ts'
16
-
17
- /**
18
- * Props for the {@link AutocompleteList} component.
19
- */
20
- export interface AutocompleteListProps extends Partial<CreateProps<Props, Events>> {}
21
-
22
- export const AutocompleteList: ForwardRefExoticComponent<
23
- Partial<AutocompleteListProps> &
24
- RefAttributes<AutocompleteListElement> &
25
- HTMLAttributes<AutocompleteListElement>
26
- > = createComponent<
27
- AutocompleteListProps,
28
- AutocompleteListElement
29
- >(
30
- 'prosekit-autocomplete-list',
31
- 'AutocompleteList',
32
- Object.keys(autocompleteListProps),
33
- Object.keys(autocompleteListEvents),
34
- )
@@ -1,34 +0,0 @@
1
- import {
2
- type AutocompletePopoverElement,
3
- type AutocompletePopoverProps as Props,
4
- type AutocompletePopoverEvents as Events,
5
- autocompletePopoverProps,
6
- autocompletePopoverEvents,
7
- } from '@prosekit/web/autocomplete'
8
- import type {
9
- ForwardRefExoticComponent,
10
- HTMLAttributes,
11
- RefAttributes,
12
- } from 'preact/compat'
13
-
14
- import { createComponent } from '../create-component.ts'
15
- import type { CreateProps } from '../create-props.ts'
16
-
17
- /**
18
- * Props for the {@link AutocompletePopover} component.
19
- */
20
- export interface AutocompletePopoverProps extends Partial<CreateProps<Props, Events>> {}
21
-
22
- export const AutocompletePopover: ForwardRefExoticComponent<
23
- Partial<AutocompletePopoverProps> &
24
- RefAttributes<AutocompletePopoverElement> &
25
- HTMLAttributes<AutocompletePopoverElement>
26
- > = createComponent<
27
- AutocompletePopoverProps,
28
- AutocompletePopoverElement
29
- >(
30
- 'prosekit-autocomplete-popover',
31
- 'AutocompletePopover',
32
- Object.keys(autocompletePopoverProps),
33
- Object.keys(autocompletePopoverEvents),
34
- )
@@ -1,34 +0,0 @@
1
- import {
2
- type BlockHandlePopoverElement,
3
- type BlockHandlePopoverProps as Props,
4
- type BlockHandlePopoverEvents as Events,
5
- blockHandlePopoverProps,
6
- blockHandlePopoverEvents,
7
- } from '@prosekit/web/block-handle'
8
- import type {
9
- ForwardRefExoticComponent,
10
- HTMLAttributes,
11
- RefAttributes,
12
- } from 'preact/compat'
13
-
14
- import { createComponent } from '../create-component.ts'
15
- import type { CreateProps } from '../create-props.ts'
16
-
17
- /**
18
- * Props for the {@link BlockHandlePopover} component.
19
- */
20
- export interface BlockHandlePopoverProps extends Partial<CreateProps<Props, Events>> {}
21
-
22
- export const BlockHandlePopover: ForwardRefExoticComponent<
23
- Partial<BlockHandlePopoverProps> &
24
- RefAttributes<BlockHandlePopoverElement> &
25
- HTMLAttributes<BlockHandlePopoverElement>
26
- > = createComponent<
27
- BlockHandlePopoverProps,
28
- BlockHandlePopoverElement
29
- >(
30
- 'prosekit-block-handle-popover',
31
- 'BlockHandlePopover',
32
- Object.keys(blockHandlePopoverProps),
33
- Object.keys(blockHandlePopoverEvents),
34
- )
@@ -1,123 +0,0 @@
1
- import type { AnyFunction } from '@prosekit/core'
2
- import { createElement } from 'preact'
3
- import { forwardRef, type ForwardRefExoticComponent, type HTMLAttributes, type RefAttributes } from 'preact/compat'
4
- import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'preact/hooks'
5
-
6
- import { useEditorContext } from '../contexts/editor-context.ts'
7
-
8
- import { mergeRefs } from './merge-refs.ts'
9
-
10
- const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect
11
-
12
- export function createComponent<
13
- Props extends object,
14
- CustomElement extends HTMLElement,
15
- >(
16
- tagName: string,
17
- displayName: string,
18
- propNames: string[],
19
- eventNames: string[],
20
- ): ForwardRefExoticComponent<
21
- Partial<Props> & RefAttributes<CustomElement> & HTMLAttributes<CustomElement>
22
- > {
23
- const hasEditor = propNames.includes('editor')
24
- const lowerCaseEventNameMap = new Map(
25
- eventNames.map((name) => [name.toLowerCase(), name]),
26
- )
27
-
28
- const Component = forwardRef<any, any>((props: Props, ref) => {
29
- const [el, setEl] = useState<HTMLElement | null>(null)
30
-
31
- const properties: Record<string, unknown> = {}
32
- const attributes: Record<string, unknown> = {}
33
- const eventHandlersRef = useRef<Record<string, AnyFunction>>({})
34
- const eventHandlers: Record<string, AnyFunction> = {}
35
-
36
- for (const [name, value] of Object.entries(props)) {
37
- if (value === undefined) {
38
- continue
39
- }
40
-
41
- if (propNames.includes(name)) {
42
- properties[name] = value
43
- continue
44
- }
45
-
46
- if (name.startsWith('on')) {
47
- const lowerCaseEventName = name.slice(2).toLowerCase()
48
- const eventName = lowerCaseEventNameMap.get(lowerCaseEventName)
49
- if (eventName) {
50
- const extractDetail = eventName.endsWith('Change')
51
- eventHandlers[eventName] = (event: Event) => {
52
- const handler = value as AnyFunction | null
53
- if (typeof handler === 'function') {
54
- handler(extractDetail ? (event as CustomEvent).detail : event)
55
- }
56
- }
57
- continue
58
- }
59
- }
60
-
61
- if (name === 'className') {
62
- attributes['class'] = value
63
- } else {
64
- attributes[name] = value
65
- }
66
- }
67
-
68
- const editor = useEditorContext()
69
-
70
- if (hasEditor && editor && !properties['editor']) {
71
- properties['editor'] = editor
72
- }
73
-
74
- // Set all properties.
75
- useIsomorphicLayoutEffect(() => {
76
- if (!el) return
77
- for (const [name, value] of Object.entries(properties)) {
78
- if (value !== undefined) {
79
- // @ts-expect-error: we know that name is a valid property name
80
- el[name] = value
81
- }
82
- }
83
- }, [el, ...propNames.map((name) => properties[name])])
84
-
85
- // Put all event listeners extracted from `props` into `eventHandlersRef`.
86
- useIsomorphicLayoutEffect(() => {
87
- eventHandlersRef.current = eventHandlers
88
- })
89
-
90
- // Register the event listeners to the element.
91
- useIsomorphicLayoutEffect(() => {
92
- if (!el) {
93
- return
94
- }
95
-
96
- const fixedEventHandlers: Record<string, AnyFunction> = {}
97
-
98
- for (const eventName of eventNames) {
99
- fixedEventHandlers[eventName] = (event: Event) => {
100
- eventHandlersRef.current[eventName]?.(event)
101
- }
102
- }
103
-
104
- for (const [name, handler] of Object.entries(fixedEventHandlers)) {
105
- el.addEventListener(name, handler)
106
- }
107
-
108
- return () => {
109
- for (const [name, handler] of Object.entries(fixedEventHandlers)) {
110
- el.removeEventListener(name, handler)
111
- }
112
- }
113
- }, [el])
114
-
115
- const mergedRef = useMemo(() => mergeRefs([ref, setEl]), [ref])
116
-
117
- return createElement(tagName, { ...attributes, ref: mergedRef })
118
- })
119
-
120
- Component.displayName = displayName
121
-
122
- return Component
123
- }
@@ -1,13 +0,0 @@
1
- export type CreateProps<
2
- Props extends { [PropName in keyof Props]: unknown },
3
- Events extends { [EventName in keyof Events]: CustomEvent },
4
- > = Props & CreateEventProps<Events>
5
-
6
- type CreateEventProps<
7
- Events extends { [EventName in keyof Events]: CustomEvent },
8
- > = {
9
- [EventName in keyof Events as `on${Capitalize<string & EventName>}`]: (
10
- event: EventName extends `${string}Change` ? Events[EventName]['detail']
11
- : Events[EventName],
12
- ) => void
13
- }
@@ -1,34 +0,0 @@
1
- import {
2
- type InlinePopoverElement,
3
- type InlinePopoverProps as Props,
4
- type InlinePopoverEvents as Events,
5
- inlinePopoverProps,
6
- inlinePopoverEvents,
7
- } from '@prosekit/web/inline-popover'
8
- import type {
9
- ForwardRefExoticComponent,
10
- HTMLAttributes,
11
- RefAttributes,
12
- } from 'preact/compat'
13
-
14
- import { createComponent } from '../create-component.ts'
15
- import type { CreateProps } from '../create-props.ts'
16
-
17
- /**
18
- * Props for the {@link InlinePopover} component.
19
- */
20
- export interface InlinePopoverProps extends Partial<CreateProps<Props, Events>> {}
21
-
22
- export const InlinePopover: ForwardRefExoticComponent<
23
- Partial<InlinePopoverProps> &
24
- RefAttributes<InlinePopoverElement> &
25
- HTMLAttributes<InlinePopoverElement>
26
- > = createComponent<
27
- InlinePopoverProps,
28
- InlinePopoverElement
29
- >(
30
- 'prosekit-inline-popover',
31
- 'InlinePopover',
32
- Object.keys(inlinePopoverProps),
33
- Object.keys(inlinePopoverEvents),
34
- )
@@ -1,35 +0,0 @@
1
- import type { Ref } from 'preact'
2
-
3
- /**
4
- * Assigns a value to a ref.
5
- * @returns The ref cleanup callback, if any.
6
- */
7
- function assignRef<T>(
8
- ref: Ref<T> | undefined,
9
- value: T | null,
10
- ): VoidFunction | void {
11
- if (typeof ref === 'function') {
12
- return ref(value)
13
- } else if (ref) {
14
- ref.current = value
15
- }
16
- }
17
-
18
- /**
19
- * Merges multiple refs into a single one.
20
- */
21
- export function mergeRefs<T>(refs: (Ref<T> | undefined)[]): Ref<T> {
22
- return (value: T | null) => {
23
- const cleanups: VoidFunction[] = []
24
-
25
- for (const ref of refs) {
26
- const cleanup = assignRef(ref, value)
27
- const isCleanup = typeof cleanup === 'function'
28
- cleanups.push(isCleanup ? cleanup : () => assignRef(ref, null))
29
- }
30
-
31
- return () => {
32
- for (const cleanup of cleanups) cleanup()
33
- }
34
- }
35
- }
@@ -1,34 +0,0 @@
1
- import {
2
- type PopoverContentElement,
3
- type PopoverContentProps as Props,
4
- type PopoverContentEvents as Events,
5
- popoverContentProps,
6
- popoverContentEvents,
7
- } from '@prosekit/web/popover'
8
- import type {
9
- ForwardRefExoticComponent,
10
- HTMLAttributes,
11
- RefAttributes,
12
- } from 'preact/compat'
13
-
14
- import { createComponent } from '../create-component.ts'
15
- import type { CreateProps } from '../create-props.ts'
16
-
17
- /**
18
- * Props for the {@link PopoverContent} component.
19
- */
20
- export interface PopoverContentProps extends Partial<CreateProps<Props, Events>> {}
21
-
22
- export const PopoverContent: ForwardRefExoticComponent<
23
- Partial<PopoverContentProps> &
24
- RefAttributes<PopoverContentElement> &
25
- HTMLAttributes<PopoverContentElement>
26
- > = createComponent<
27
- PopoverContentProps,
28
- PopoverContentElement
29
- >(
30
- 'prosekit-popover-content',
31
- 'PopoverContent',
32
- Object.keys(popoverContentProps),
33
- Object.keys(popoverContentEvents),
34
- )
@@ -1,34 +0,0 @@
1
- import {
2
- type TableHandleColumnRootElement,
3
- type TableHandleColumnRootProps as Props,
4
- type TableHandleColumnRootEvents as Events,
5
- tableHandleColumnRootProps,
6
- tableHandleColumnRootEvents,
7
- } from '@prosekit/web/table-handle'
8
- import type {
9
- ForwardRefExoticComponent,
10
- HTMLAttributes,
11
- RefAttributes,
12
- } from 'preact/compat'
13
-
14
- import { createComponent } from '../create-component.ts'
15
- import type { CreateProps } from '../create-props.ts'
16
-
17
- /**
18
- * Props for the {@link TableHandleColumnRoot} component.
19
- */
20
- export interface TableHandleColumnRootProps extends Partial<CreateProps<Props, Events>> {}
21
-
22
- export const TableHandleColumnRoot: ForwardRefExoticComponent<
23
- Partial<TableHandleColumnRootProps> &
24
- RefAttributes<TableHandleColumnRootElement> &
25
- HTMLAttributes<TableHandleColumnRootElement>
26
- > = createComponent<
27
- TableHandleColumnRootProps,
28
- TableHandleColumnRootElement
29
- >(
30
- 'prosekit-table-handle-column-root',
31
- 'TableHandleColumnRoot',
32
- Object.keys(tableHandleColumnRootProps),
33
- Object.keys(tableHandleColumnRootEvents),
34
- )