prosekit-registry 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +241 -0
- package/dist/r/lit-example-minimal.json +36 -0
- package/dist/r/lit-example-slash-menu.json +55 -0
- package/dist/r/lit-example-table.json +56 -0
- package/dist/r/lit-example-toolbar.json +60 -0
- package/dist/r/lit-sample-sample-doc-table.json +29 -0
- package/dist/r/lit-sample-sample-uploader.json +29 -0
- package/dist/r/lit-ui-button.json +36 -0
- package/dist/r/lit-ui-editor-context.json +30 -0
- package/dist/r/lit-ui-image-upload-popover.json +42 -0
- package/dist/r/lit-ui-slash-menu.json +56 -0
- package/dist/r/lit-ui-table-handle.json +47 -0
- package/dist/r/lit-ui-toolbar.json +55 -0
- package/dist/r/preact-example-block-handle.json +60 -0
- package/dist/r/preact-example-blockquote.json +53 -0
- package/dist/r/preact-example-bold.json +56 -0
- package/dist/r/preact-example-change-tracking.json +50 -0
- package/dist/r/preact-example-code-block-themes.json +66 -0
- package/dist/r/preact-example-code-block.json +60 -0
- package/dist/r/preact-example-code.json +56 -0
- package/dist/r/preact-example-drop-cursor.json +48 -0
- package/dist/r/preact-example-emoji-rules.json +50 -0
- package/dist/r/preact-example-full.json +106 -0
- package/dist/r/preact-example-gap-cursor.json +48 -0
- package/dist/r/preact-example-hard-break.json +59 -0
- package/dist/r/preact-example-heading.json +56 -0
- package/dist/r/preact-example-horizontal-rule.json +53 -0
- package/dist/r/preact-example-image-view.json +55 -0
- package/dist/r/preact-example-inline-menu.json +54 -0
- package/dist/r/preact-example-italic.json +56 -0
- package/dist/r/preact-example-keymap.json +63 -0
- package/dist/r/preact-example-link-mark-view.json +55 -0
- package/dist/r/preact-example-link.json +54 -0
- package/dist/r/preact-example-list-custom-checkbox.json +63 -0
- package/dist/r/preact-example-list.json +56 -0
- package/dist/r/preact-example-loro.json +62 -0
- package/dist/r/preact-example-mark-rule.json +50 -0
- package/dist/r/preact-example-minimal.json +36 -0
- package/dist/r/preact-example-page.json +49 -0
- package/dist/r/preact-example-placeholder.json +43 -0
- package/dist/r/preact-example-readonly.json +66 -0
- package/dist/r/preact-example-rtl.json +74 -0
- package/dist/r/preact-example-save-html.json +36 -0
- package/dist/r/preact-example-save-json.json +36 -0
- package/dist/r/preact-example-save-markdown.json +50 -0
- package/dist/r/preact-example-search.json +54 -0
- package/dist/r/preact-example-slash-menu.json +51 -0
- package/dist/r/preact-example-strike.json +59 -0
- package/dist/r/preact-example-table.json +52 -0
- package/dist/r/preact-example-temml.json +51 -0
- package/dist/r/preact-example-text-align.json +59 -0
- package/dist/r/preact-example-text-color.json +59 -0
- package/dist/r/preact-example-toolbar.json +56 -0
- package/dist/r/preact-example-typography.json +59 -0
- package/dist/r/preact-example-underline.json +56 -0
- package/dist/r/preact-example-unmount.json +58 -0
- package/dist/r/preact-example-user-menu-dynamic.json +67 -0
- package/dist/r/preact-example-user-menu.json +59 -0
- package/dist/r/preact-example-view-adapter.json +58 -0
- package/dist/r/preact-example-word-counter.json +52 -0
- package/dist/r/preact-example-yjs.json +62 -0
- package/dist/r/preact-sample-define-atom-block.json +29 -0
- package/dist/r/preact-sample-katex.json +29 -0
- package/dist/r/preact-sample-sample-doc-block-handle.json +29 -0
- package/dist/r/preact-sample-sample-doc-bold.json +29 -0
- package/dist/r/preact-sample-sample-doc-code-block.json +29 -0
- package/dist/r/preact-sample-sample-doc-code.json +29 -0
- package/dist/r/preact-sample-sample-doc-drop-cursor.json +29 -0
- package/dist/r/preact-sample-sample-doc-full.json +29 -0
- package/dist/r/preact-sample-sample-doc-gap-cursor.json +29 -0
- package/dist/r/preact-sample-sample-doc-hard-break.json +29 -0
- package/dist/r/preact-sample-sample-doc-heading.json +29 -0
- package/dist/r/preact-sample-sample-doc-image.json +29 -0
- package/dist/r/preact-sample-sample-doc-inline-menu.json +29 -0
- package/dist/r/preact-sample-sample-doc-italic.json +29 -0
- package/dist/r/preact-sample-sample-doc-link-mark-view.json +29 -0
- package/dist/r/preact-sample-sample-doc-link.json +29 -0
- package/dist/r/preact-sample-sample-doc-list-custom-checkbox.json +29 -0
- package/dist/r/preact-sample-sample-doc-list.json +29 -0
- package/dist/r/preact-sample-sample-doc-page.json +29 -0
- package/dist/r/preact-sample-sample-doc-readonly.json +29 -0
- package/dist/r/preact-sample-sample-doc-rtl.json +29 -0
- package/dist/r/preact-sample-sample-doc-search.json +29 -0
- package/dist/r/preact-sample-sample-doc-strike.json +29 -0
- package/dist/r/preact-sample-sample-doc-table.json +29 -0
- package/dist/r/preact-sample-sample-doc-tex.json +29 -0
- package/dist/r/preact-sample-sample-doc-text-align.json +29 -0
- package/dist/r/preact-sample-sample-doc-text-color.json +29 -0
- package/dist/r/preact-sample-sample-doc-typography.json +29 -0
- package/dist/r/preact-sample-sample-doc-underline.json +29 -0
- package/dist/r/preact-sample-sample-doc-view-adapter.json +29 -0
- package/dist/r/preact-sample-sample-doc-word-counter.json +29 -0
- package/dist/r/preact-sample-sample-query-users.json +32 -0
- package/dist/r/preact-sample-sample-tag-data.json +27 -0
- package/dist/r/preact-sample-sample-uploader.json +29 -0
- package/dist/r/preact-sample-sample-user-data.json +27 -0
- package/dist/r/preact-sample-temml.json +29 -0
- package/dist/r/preact-ui-block-handle.json +41 -0
- package/dist/r/preact-ui-button.json +36 -0
- package/dist/r/preact-ui-code-block-view.json +36 -0
- package/dist/r/preact-ui-drop-indicator.json +36 -0
- package/dist/r/preact-ui-image-upload-popover.json +42 -0
- package/dist/r/preact-ui-image-view.json +41 -0
- package/dist/r/preact-ui-inline-menu.json +47 -0
- package/dist/r/preact-ui-search.json +47 -0
- package/dist/r/preact-ui-slash-menu.json +50 -0
- package/dist/r/preact-ui-table-handle.json +41 -0
- package/dist/r/preact-ui-tag-menu.json +36 -0
- package/dist/r/preact-ui-toolbar.json +51 -0
- package/dist/r/preact-ui-user-menu.json +36 -0
- package/dist/r/preact-ui-word-counter.json +36 -0
- package/dist/r/react-example-block-handle.json +60 -0
- package/dist/r/react-example-blockquote.json +53 -0
- package/dist/r/react-example-bold.json +56 -0
- package/dist/r/react-example-change-tracking.json +50 -0
- package/dist/r/react-example-code-block-themes.json +66 -0
- package/dist/r/react-example-code-block.json +60 -0
- package/dist/r/react-example-code.json +56 -0
- package/dist/r/react-example-drop-cursor.json +48 -0
- package/dist/r/react-example-emoji-rules.json +50 -0
- package/dist/r/react-example-full.json +113 -0
- package/dist/r/react-example-gap-cursor.json +48 -0
- package/dist/r/react-example-hard-break.json +59 -0
- package/dist/r/react-example-heading.json +56 -0
- package/dist/r/react-example-horizontal-rule.json +53 -0
- package/dist/r/react-example-image-view.json +55 -0
- package/dist/r/react-example-inline-menu.json +54 -0
- package/dist/r/react-example-italic.json +56 -0
- package/dist/r/react-example-keymap.json +63 -0
- package/dist/r/react-example-link-mark-view.json +55 -0
- package/dist/r/react-example-link.json +54 -0
- package/dist/r/react-example-list-custom-checkbox.json +63 -0
- package/dist/r/react-example-list.json +56 -0
- package/dist/r/react-example-loro.json +62 -0
- package/dist/r/react-example-mark-rule.json +50 -0
- package/dist/r/react-example-minimal.json +36 -0
- package/dist/r/react-example-notion.json +166 -0
- package/dist/r/react-example-page.json +62 -0
- package/dist/r/react-example-placeholder.json +43 -0
- package/dist/r/react-example-readonly.json +66 -0
- package/dist/r/react-example-rtl.json +74 -0
- package/dist/r/react-example-save-html.json +36 -0
- package/dist/r/react-example-save-json.json +36 -0
- package/dist/r/react-example-save-markdown.json +50 -0
- package/dist/r/react-example-search.json +54 -0
- package/dist/r/react-example-slash-menu.json +51 -0
- package/dist/r/react-example-strike.json +59 -0
- package/dist/r/react-example-table.json +52 -0
- package/dist/r/react-example-temml.json +51 -0
- package/dist/r/react-example-text-align.json +59 -0
- package/dist/r/react-example-text-color.json +59 -0
- package/dist/r/react-example-toolbar.json +56 -0
- package/dist/r/react-example-tweet.json +63 -0
- package/dist/r/react-example-typography.json +59 -0
- package/dist/r/react-example-underline.json +56 -0
- package/dist/r/react-example-unmount.json +58 -0
- package/dist/r/react-example-user-menu-dynamic.json +67 -0
- package/dist/r/react-example-user-menu.json +59 -0
- package/dist/r/react-example-view-adapter.json +58 -0
- package/dist/r/react-example-word-counter.json +52 -0
- package/dist/r/react-example-yjs.json +62 -0
- package/dist/r/react-sample-define-atom-block.json +29 -0
- package/dist/r/react-sample-katex.json +29 -0
- package/dist/r/react-sample-sample-doc-block-handle.json +29 -0
- package/dist/r/react-sample-sample-doc-bold.json +29 -0
- package/dist/r/react-sample-sample-doc-code-block.json +29 -0
- package/dist/r/react-sample-sample-doc-code.json +29 -0
- package/dist/r/react-sample-sample-doc-drop-cursor.json +29 -0
- package/dist/r/react-sample-sample-doc-full.json +29 -0
- package/dist/r/react-sample-sample-doc-gap-cursor.json +29 -0
- package/dist/r/react-sample-sample-doc-hard-break.json +29 -0
- package/dist/r/react-sample-sample-doc-heading.json +29 -0
- package/dist/r/react-sample-sample-doc-image.json +29 -0
- package/dist/r/react-sample-sample-doc-inline-menu.json +29 -0
- package/dist/r/react-sample-sample-doc-italic.json +29 -0
- package/dist/r/react-sample-sample-doc-link-mark-view.json +29 -0
- package/dist/r/react-sample-sample-doc-link.json +29 -0
- package/dist/r/react-sample-sample-doc-list-custom-checkbox.json +29 -0
- package/dist/r/react-sample-sample-doc-list.json +29 -0
- package/dist/r/react-sample-sample-doc-notion.json +29 -0
- package/dist/r/react-sample-sample-doc-page.json +29 -0
- package/dist/r/react-sample-sample-doc-readonly.json +29 -0
- package/dist/r/react-sample-sample-doc-rtl.json +29 -0
- package/dist/r/react-sample-sample-doc-search.json +29 -0
- package/dist/r/react-sample-sample-doc-strike.json +29 -0
- package/dist/r/react-sample-sample-doc-table.json +29 -0
- package/dist/r/react-sample-sample-doc-tex.json +29 -0
- package/dist/r/react-sample-sample-doc-text-align.json +29 -0
- package/dist/r/react-sample-sample-doc-text-color.json +29 -0
- package/dist/r/react-sample-sample-doc-tweet.json +29 -0
- package/dist/r/react-sample-sample-doc-typography.json +29 -0
- package/dist/r/react-sample-sample-doc-underline.json +29 -0
- package/dist/r/react-sample-sample-doc-view-adapter.json +29 -0
- package/dist/r/react-sample-sample-doc-word-counter.json +29 -0
- package/dist/r/react-sample-sample-query-users.json +32 -0
- package/dist/r/react-sample-sample-tag-data.json +27 -0
- package/dist/r/react-sample-sample-uploader.json +29 -0
- package/dist/r/react-sample-sample-user-data.json +27 -0
- package/dist/r/react-sample-temml.json +29 -0
- package/dist/r/react-ui-block-handle.json +41 -0
- package/dist/r/react-ui-button.json +36 -0
- package/dist/r/react-ui-code-block-view.json +36 -0
- package/dist/r/react-ui-drop-indicator.json +36 -0
- package/dist/r/react-ui-image-upload-popover.json +42 -0
- package/dist/r/react-ui-image-view.json +41 -0
- package/dist/r/react-ui-inline-menu.json +47 -0
- package/dist/r/react-ui-search.json +47 -0
- package/dist/r/react-ui-slash-menu.json +50 -0
- package/dist/r/react-ui-table-handle.json +41 -0
- package/dist/r/react-ui-tag-menu.json +36 -0
- package/dist/r/react-ui-toolbar.json +51 -0
- package/dist/r/react-ui-user-menu.json +36 -0
- package/dist/r/react-ui-word-counter.json +36 -0
- package/dist/r/registry.json +20642 -0
- package/dist/r/solid-example-block-handle.json +60 -0
- package/dist/r/solid-example-blockquote.json +53 -0
- package/dist/r/solid-example-bold.json +56 -0
- package/dist/r/solid-example-change-tracking.json +50 -0
- package/dist/r/solid-example-code-block-themes.json +66 -0
- package/dist/r/solid-example-code-block.json +60 -0
- package/dist/r/solid-example-code.json +56 -0
- package/dist/r/solid-example-drop-cursor.json +48 -0
- package/dist/r/solid-example-emoji-rules.json +50 -0
- package/dist/r/solid-example-full.json +106 -0
- package/dist/r/solid-example-gap-cursor.json +48 -0
- package/dist/r/solid-example-hard-break.json +59 -0
- package/dist/r/solid-example-heading.json +56 -0
- package/dist/r/solid-example-horizontal-rule.json +53 -0
- package/dist/r/solid-example-image-view.json +55 -0
- package/dist/r/solid-example-inline-menu.json +54 -0
- package/dist/r/solid-example-italic.json +56 -0
- package/dist/r/solid-example-keymap.json +63 -0
- package/dist/r/solid-example-link-mark-view.json +55 -0
- package/dist/r/solid-example-link.json +54 -0
- package/dist/r/solid-example-list-custom-checkbox.json +63 -0
- package/dist/r/solid-example-list.json +56 -0
- package/dist/r/solid-example-loro.json +62 -0
- package/dist/r/solid-example-mark-rule.json +50 -0
- package/dist/r/solid-example-minimal.json +36 -0
- package/dist/r/solid-example-placeholder.json +43 -0
- package/dist/r/solid-example-readonly.json +66 -0
- package/dist/r/solid-example-rtl.json +74 -0
- package/dist/r/solid-example-save-html.json +36 -0
- package/dist/r/solid-example-save-json.json +36 -0
- package/dist/r/solid-example-save-markdown.json +50 -0
- package/dist/r/solid-example-search.json +54 -0
- package/dist/r/solid-example-slash-menu.json +51 -0
- package/dist/r/solid-example-strike.json +59 -0
- package/dist/r/solid-example-table.json +52 -0
- package/dist/r/solid-example-temml.json +51 -0
- package/dist/r/solid-example-text-align.json +59 -0
- package/dist/r/solid-example-text-color.json +59 -0
- package/dist/r/solid-example-toolbar.json +56 -0
- package/dist/r/solid-example-typography.json +59 -0
- package/dist/r/solid-example-underline.json +56 -0
- package/dist/r/solid-example-unmount.json +58 -0
- package/dist/r/solid-example-user-menu-dynamic.json +67 -0
- package/dist/r/solid-example-user-menu.json +59 -0
- package/dist/r/solid-example-view-adapter.json +58 -0
- package/dist/r/solid-example-word-counter.json +52 -0
- package/dist/r/solid-example-yjs.json +62 -0
- package/dist/r/solid-sample-define-atom-block.json +29 -0
- package/dist/r/solid-sample-katex.json +29 -0
- package/dist/r/solid-sample-sample-doc-block-handle.json +29 -0
- package/dist/r/solid-sample-sample-doc-bold.json +29 -0
- package/dist/r/solid-sample-sample-doc-code-block.json +29 -0
- package/dist/r/solid-sample-sample-doc-code.json +29 -0
- package/dist/r/solid-sample-sample-doc-drop-cursor.json +29 -0
- package/dist/r/solid-sample-sample-doc-full.json +29 -0
- package/dist/r/solid-sample-sample-doc-gap-cursor.json +29 -0
- package/dist/r/solid-sample-sample-doc-hard-break.json +29 -0
- package/dist/r/solid-sample-sample-doc-heading.json +29 -0
- package/dist/r/solid-sample-sample-doc-image.json +29 -0
- package/dist/r/solid-sample-sample-doc-inline-menu.json +29 -0
- package/dist/r/solid-sample-sample-doc-italic.json +29 -0
- package/dist/r/solid-sample-sample-doc-link-mark-view.json +29 -0
- package/dist/r/solid-sample-sample-doc-link.json +29 -0
- package/dist/r/solid-sample-sample-doc-list-custom-checkbox.json +29 -0
- package/dist/r/solid-sample-sample-doc-list.json +29 -0
- package/dist/r/solid-sample-sample-doc-readonly.json +29 -0
- package/dist/r/solid-sample-sample-doc-rtl.json +29 -0
- package/dist/r/solid-sample-sample-doc-search.json +29 -0
- package/dist/r/solid-sample-sample-doc-strike.json +29 -0
- package/dist/r/solid-sample-sample-doc-table.json +29 -0
- package/dist/r/solid-sample-sample-doc-tex.json +29 -0
- package/dist/r/solid-sample-sample-doc-text-align.json +29 -0
- package/dist/r/solid-sample-sample-doc-text-color.json +29 -0
- package/dist/r/solid-sample-sample-doc-typography.json +29 -0
- package/dist/r/solid-sample-sample-doc-underline.json +29 -0
- package/dist/r/solid-sample-sample-doc-view-adapter.json +29 -0
- package/dist/r/solid-sample-sample-doc-word-counter.json +29 -0
- package/dist/r/solid-sample-sample-query-users.json +32 -0
- package/dist/r/solid-sample-sample-tag-data.json +27 -0
- package/dist/r/solid-sample-sample-uploader.json +29 -0
- package/dist/r/solid-sample-sample-user-data.json +27 -0
- package/dist/r/solid-sample-temml.json +29 -0
- package/dist/r/solid-ui-block-handle.json +41 -0
- package/dist/r/solid-ui-button.json +36 -0
- package/dist/r/solid-ui-code-block-view.json +36 -0
- package/dist/r/solid-ui-drop-indicator.json +36 -0
- package/dist/r/solid-ui-image-upload-popover.json +42 -0
- package/dist/r/solid-ui-image-view.json +41 -0
- package/dist/r/solid-ui-inline-menu.json +47 -0
- package/dist/r/solid-ui-search.json +47 -0
- package/dist/r/solid-ui-slash-menu.json +50 -0
- package/dist/r/solid-ui-table-handle.json +41 -0
- package/dist/r/solid-ui-tag-menu.json +36 -0
- package/dist/r/solid-ui-toolbar.json +51 -0
- package/dist/r/solid-ui-user-menu.json +36 -0
- package/dist/r/solid-ui-word-counter.json +36 -0
- package/dist/r/svelte-example-block-handle.json +60 -0
- package/dist/r/svelte-example-blockquote.json +53 -0
- package/dist/r/svelte-example-bold.json +56 -0
- package/dist/r/svelte-example-change-tracking.json +50 -0
- package/dist/r/svelte-example-code-block-themes.json +66 -0
- package/dist/r/svelte-example-code-block.json +60 -0
- package/dist/r/svelte-example-code.json +56 -0
- package/dist/r/svelte-example-drop-cursor.json +48 -0
- package/dist/r/svelte-example-emoji-rules.json +50 -0
- package/dist/r/svelte-example-full.json +106 -0
- package/dist/r/svelte-example-gap-cursor.json +48 -0
- package/dist/r/svelte-example-hard-break.json +59 -0
- package/dist/r/svelte-example-heading.json +56 -0
- package/dist/r/svelte-example-horizontal-rule.json +53 -0
- package/dist/r/svelte-example-image-view.json +55 -0
- package/dist/r/svelte-example-inline-menu.json +54 -0
- package/dist/r/svelte-example-italic.json +56 -0
- package/dist/r/svelte-example-katex.json +51 -0
- package/dist/r/svelte-example-keymap.json +56 -0
- package/dist/r/svelte-example-link-mark-view.json +55 -0
- package/dist/r/svelte-example-link.json +54 -0
- package/dist/r/svelte-example-list-custom-checkbox.json +63 -0
- package/dist/r/svelte-example-list.json +56 -0
- package/dist/r/svelte-example-loro.json +62 -0
- package/dist/r/svelte-example-mark-rule.json +50 -0
- package/dist/r/svelte-example-minimal.json +36 -0
- package/dist/r/svelte-example-page.json +62 -0
- package/dist/r/svelte-example-placeholder.json +43 -0
- package/dist/r/svelte-example-readonly.json +59 -0
- package/dist/r/svelte-example-rtl.json +74 -0
- package/dist/r/svelte-example-save-html.json +36 -0
- package/dist/r/svelte-example-save-json.json +36 -0
- package/dist/r/svelte-example-save-markdown.json +50 -0
- package/dist/r/svelte-example-search.json +54 -0
- package/dist/r/svelte-example-slash-menu.json +51 -0
- package/dist/r/svelte-example-strike.json +59 -0
- package/dist/r/svelte-example-table.json +52 -0
- package/dist/r/svelte-example-text-align.json +59 -0
- package/dist/r/svelte-example-text-color.json +59 -0
- package/dist/r/svelte-example-toolbar.json +56 -0
- package/dist/r/svelte-example-typography.json +59 -0
- package/dist/r/svelte-example-underline.json +56 -0
- package/dist/r/svelte-example-unmount.json +58 -0
- package/dist/r/svelte-example-user-menu-dynamic.json +67 -0
- package/dist/r/svelte-example-user-menu.json +59 -0
- package/dist/r/svelte-example-view-adapter.json +58 -0
- package/dist/r/svelte-example-word-counter.json +52 -0
- package/dist/r/svelte-example-yjs.json +62 -0
- package/dist/r/svelte-sample-define-atom-block.json +29 -0
- package/dist/r/svelte-sample-katex.json +29 -0
- package/dist/r/svelte-sample-sample-doc-block-handle.json +29 -0
- package/dist/r/svelte-sample-sample-doc-bold.json +29 -0
- package/dist/r/svelte-sample-sample-doc-code-block.json +29 -0
- package/dist/r/svelte-sample-sample-doc-code.json +29 -0
- package/dist/r/svelte-sample-sample-doc-drop-cursor.json +29 -0
- package/dist/r/svelte-sample-sample-doc-full.json +29 -0
- package/dist/r/svelte-sample-sample-doc-gap-cursor.json +29 -0
- package/dist/r/svelte-sample-sample-doc-hard-break.json +29 -0
- package/dist/r/svelte-sample-sample-doc-heading.json +29 -0
- package/dist/r/svelte-sample-sample-doc-image.json +29 -0
- package/dist/r/svelte-sample-sample-doc-inline-menu.json +29 -0
- package/dist/r/svelte-sample-sample-doc-italic.json +29 -0
- package/dist/r/svelte-sample-sample-doc-link-mark-view.json +29 -0
- package/dist/r/svelte-sample-sample-doc-link.json +29 -0
- package/dist/r/svelte-sample-sample-doc-list-custom-checkbox.json +29 -0
- package/dist/r/svelte-sample-sample-doc-list.json +29 -0
- package/dist/r/svelte-sample-sample-doc-page.json +29 -0
- package/dist/r/svelte-sample-sample-doc-readonly.json +29 -0
- package/dist/r/svelte-sample-sample-doc-rtl.json +29 -0
- package/dist/r/svelte-sample-sample-doc-search.json +29 -0
- package/dist/r/svelte-sample-sample-doc-strike.json +29 -0
- package/dist/r/svelte-sample-sample-doc-table.json +29 -0
- package/dist/r/svelte-sample-sample-doc-tex.json +29 -0
- package/dist/r/svelte-sample-sample-doc-text-align.json +29 -0
- package/dist/r/svelte-sample-sample-doc-text-color.json +29 -0
- package/dist/r/svelte-sample-sample-doc-typography.json +29 -0
- package/dist/r/svelte-sample-sample-doc-underline.json +29 -0
- package/dist/r/svelte-sample-sample-doc-view-adapter.json +29 -0
- package/dist/r/svelte-sample-sample-doc-word-counter.json +29 -0
- package/dist/r/svelte-sample-sample-query-users.json +32 -0
- package/dist/r/svelte-sample-sample-tag-data.json +27 -0
- package/dist/r/svelte-sample-sample-uploader.json +29 -0
- package/dist/r/svelte-sample-sample-user-data.json +27 -0
- package/dist/r/svelte-ui-block-handle.json +41 -0
- package/dist/r/svelte-ui-button.json +36 -0
- package/dist/r/svelte-ui-code-block-view.json +36 -0
- package/dist/r/svelte-ui-drop-indicator.json +36 -0
- package/dist/r/svelte-ui-image-upload-popover.json +42 -0
- package/dist/r/svelte-ui-image-view.json +41 -0
- package/dist/r/svelte-ui-inline-menu.json +47 -0
- package/dist/r/svelte-ui-search.json +47 -0
- package/dist/r/svelte-ui-slash-menu.json +50 -0
- package/dist/r/svelte-ui-table-handle.json +41 -0
- package/dist/r/svelte-ui-tag-menu.json +36 -0
- package/dist/r/svelte-ui-toolbar.json +51 -0
- package/dist/r/svelte-ui-user-menu.json +36 -0
- package/dist/r/svelte-ui-word-counter.json +36 -0
- package/dist/r/vanilla-example-minimal.json +36 -0
- package/dist/r/vanilla-example-slash-menu.json +51 -0
- package/dist/r/vanilla-ui-slash-menu.json +50 -0
- package/dist/r/vue-example-block-handle.json +60 -0
- package/dist/r/vue-example-blockquote.json +53 -0
- package/dist/r/vue-example-bold.json +56 -0
- package/dist/r/vue-example-change-tracking.json +50 -0
- package/dist/r/vue-example-code-block-themes.json +66 -0
- package/dist/r/vue-example-code-block.json +60 -0
- package/dist/r/vue-example-code.json +56 -0
- package/dist/r/vue-example-drop-cursor.json +48 -0
- package/dist/r/vue-example-emoji-rules.json +50 -0
- package/dist/r/vue-example-full.json +106 -0
- package/dist/r/vue-example-gap-cursor.json +48 -0
- package/dist/r/vue-example-hard-break.json +59 -0
- package/dist/r/vue-example-heading.json +56 -0
- package/dist/r/vue-example-horizontal-rule.json +53 -0
- package/dist/r/vue-example-image-view.json +55 -0
- package/dist/r/vue-example-inline-menu.json +54 -0
- package/dist/r/vue-example-italic.json +56 -0
- package/dist/r/vue-example-katex.json +51 -0
- package/dist/r/vue-example-keymap.json +63 -0
- package/dist/r/vue-example-link-mark-view.json +55 -0
- package/dist/r/vue-example-link.json +54 -0
- package/dist/r/vue-example-list-custom-checkbox.json +63 -0
- package/dist/r/vue-example-list.json +56 -0
- package/dist/r/vue-example-loro.json +62 -0
- package/dist/r/vue-example-mark-rule.json +50 -0
- package/dist/r/vue-example-minimal.json +36 -0
- package/dist/r/vue-example-placeholder.json +43 -0
- package/dist/r/vue-example-readonly.json +66 -0
- package/dist/r/vue-example-rtl.json +74 -0
- package/dist/r/vue-example-save-html.json +36 -0
- package/dist/r/vue-example-save-json.json +36 -0
- package/dist/r/vue-example-save-markdown.json +50 -0
- package/dist/r/vue-example-search.json +54 -0
- package/dist/r/vue-example-slash-menu.json +51 -0
- package/dist/r/vue-example-strike.json +59 -0
- package/dist/r/vue-example-table.json +52 -0
- package/dist/r/vue-example-text-align.json +59 -0
- package/dist/r/vue-example-text-color.json +59 -0
- package/dist/r/vue-example-toolbar.json +56 -0
- package/dist/r/vue-example-tweet.json +63 -0
- package/dist/r/vue-example-typography.json +59 -0
- package/dist/r/vue-example-underline.json +56 -0
- package/dist/r/vue-example-unmount.json +58 -0
- package/dist/r/vue-example-user-menu-dynamic.json +67 -0
- package/dist/r/vue-example-user-menu.json +59 -0
- package/dist/r/vue-example-view-adapter.json +58 -0
- package/dist/r/vue-example-word-counter.json +52 -0
- package/dist/r/vue-example-yjs.json +62 -0
- package/dist/r/vue-sample-define-atom-block.json +29 -0
- package/dist/r/vue-sample-katex.json +29 -0
- package/dist/r/vue-sample-sample-doc-block-handle.json +29 -0
- package/dist/r/vue-sample-sample-doc-bold.json +29 -0
- package/dist/r/vue-sample-sample-doc-code-block.json +29 -0
- package/dist/r/vue-sample-sample-doc-code.json +29 -0
- package/dist/r/vue-sample-sample-doc-drop-cursor.json +29 -0
- package/dist/r/vue-sample-sample-doc-full.json +29 -0
- package/dist/r/vue-sample-sample-doc-gap-cursor.json +29 -0
- package/dist/r/vue-sample-sample-doc-hard-break.json +29 -0
- package/dist/r/vue-sample-sample-doc-heading.json +29 -0
- package/dist/r/vue-sample-sample-doc-image.json +29 -0
- package/dist/r/vue-sample-sample-doc-inline-menu.json +29 -0
- package/dist/r/vue-sample-sample-doc-italic.json +29 -0
- package/dist/r/vue-sample-sample-doc-link-mark-view.json +29 -0
- package/dist/r/vue-sample-sample-doc-link.json +29 -0
- package/dist/r/vue-sample-sample-doc-list-custom-checkbox.json +29 -0
- package/dist/r/vue-sample-sample-doc-list.json +29 -0
- package/dist/r/vue-sample-sample-doc-readonly.json +29 -0
- package/dist/r/vue-sample-sample-doc-rtl.json +29 -0
- package/dist/r/vue-sample-sample-doc-search.json +29 -0
- package/dist/r/vue-sample-sample-doc-strike.json +29 -0
- package/dist/r/vue-sample-sample-doc-table.json +29 -0
- package/dist/r/vue-sample-sample-doc-tex.json +29 -0
- package/dist/r/vue-sample-sample-doc-text-align.json +29 -0
- package/dist/r/vue-sample-sample-doc-text-color.json +29 -0
- package/dist/r/vue-sample-sample-doc-tweet.json +29 -0
- package/dist/r/vue-sample-sample-doc-typography.json +29 -0
- package/dist/r/vue-sample-sample-doc-underline.json +29 -0
- package/dist/r/vue-sample-sample-doc-view-adapter.json +29 -0
- package/dist/r/vue-sample-sample-doc-word-counter.json +29 -0
- package/dist/r/vue-sample-sample-query-users.json +32 -0
- package/dist/r/vue-sample-sample-tag-data.json +27 -0
- package/dist/r/vue-sample-sample-uploader.json +29 -0
- package/dist/r/vue-sample-sample-user-data.json +27 -0
- package/dist/r/vue-ui-block-handle.json +41 -0
- package/dist/r/vue-ui-button.json +36 -0
- package/dist/r/vue-ui-code-block-view.json +36 -0
- package/dist/r/vue-ui-drop-indicator.json +36 -0
- package/dist/r/vue-ui-image-upload-popover.json +42 -0
- package/dist/r/vue-ui-image-view.json +41 -0
- package/dist/r/vue-ui-inline-menu.json +47 -0
- package/dist/r/vue-ui-search.json +47 -0
- package/dist/r/vue-ui-slash-menu.json +50 -0
- package/dist/r/vue-ui-table-handle.json +41 -0
- package/dist/r/vue-ui-tag-menu.json +36 -0
- package/dist/r/vue-ui-toolbar.json +51 -0
- package/dist/r/vue-ui-user-menu.json +36 -0
- package/dist/r/vue-ui-word-counter.json +36 -0
- package/package.json +353 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "solid-ui-image-upload-popover",
|
|
3
|
+
"title": "solid-ui-image-upload-popover",
|
|
4
|
+
"type": "registry:component",
|
|
5
|
+
"description": "",
|
|
6
|
+
"registryDependencies": [
|
|
7
|
+
"https://prosekit.dev/r/solid-ui-button.json"
|
|
8
|
+
],
|
|
9
|
+
"dependencies": [
|
|
10
|
+
"prosekit"
|
|
11
|
+
],
|
|
12
|
+
"files": [
|
|
13
|
+
{
|
|
14
|
+
"path": "registry/src/solid/ui/image-upload-popover/image-upload-popover.tsx",
|
|
15
|
+
"type": "registry:component",
|
|
16
|
+
"target": "components/editor/ui/image-upload-popover/image-upload-popover.tsx",
|
|
17
|
+
"content": "import type { Uploader } from 'prosekit/extensions/file'\nimport type { ImageExtension } from 'prosekit/extensions/image'\nimport { useEditor } from 'prosekit/solid'\nimport type { OpenChangeEvent } from 'prosekit/solid/popover'\nimport { PopoverPopup, PopoverPositioner, PopoverRoot, PopoverTrigger } from 'prosekit/solid/popover'\nimport { createSignal, createUniqueId, Show, type JSX } from 'solid-js'\n\nimport { Button } from '../button'\n\nexport default function ImageUploadPopover(props: {\n uploader: Uploader<string>\n tooltip: string\n disabled: boolean\n children: JSX.Element\n}): JSX.Element {\n const [open, setOpen] = createSignal(false)\n const [url, setUrl] = createSignal('')\n const [file, setFile] = createSignal<File | null>(null)\n const ariaId = createUniqueId()\n\n const editor = useEditor<ImageExtension>()\n\n const handleFileChange = (event: Event) => {\n const target = event.target as HTMLInputElement\n const selectedFile = target.files?.[0]\n\n if (selectedFile) {\n setFile(selectedFile)\n setUrl('')\n } else {\n setFile(null)\n }\n }\n\n const handleUrlChange = (event: Event) => {\n const target = event.target as HTMLInputElement\n const inputUrl = target.value\n\n if (inputUrl) {\n setUrl(inputUrl)\n setFile(null)\n } else {\n setUrl('')\n }\n }\n\n const deferResetState = () => {\n setTimeout(() => {\n setUrl('')\n setFile(null)\n }, 300)\n }\n\n const handleSubmit = () => {\n if (url()) {\n editor().commands.insertImage({ src: url() })\n } else if (file()) {\n editor().commands.uploadImage({ file: file()!, uploader: props.uploader })\n }\n setOpen(false)\n deferResetState()\n }\n\n const handleOpenChange = (event: OpenChangeEvent) => {\n if (!event.detail) {\n deferResetState()\n }\n setOpen(event.detail)\n }\n\n return (\n <PopoverRoot open={open()} onOpenChange={handleOpenChange}>\n <PopoverTrigger>\n <Button pressed={open()} disabled={props.disabled} tooltip={props.tooltip}>\n {props.children}\n </Button>\n </PopoverTrigger>\n\n <PopoverPositioner placement=\"bottom\" class=\"block overflow-visible bg-transparent w-min h-min z-50 motion-safe:ease-out motion-safe:transition-transform motion-safe:duration-100\">\n <PopoverPopup class=\"box-border data-[state=closed]:motion-safe:duration-150 motion-safe:transition-discrete motion-safe:transition-all data-[state=closed]:opacity-0 starting:opacity-0 opacity-100 data-[state=closed]:scale-95 starting:scale-95 scale-100 motion-safe:duration-40 rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950 shadow-lg flex flex-col gap-y-4 p-6 text-sm w-sm\">\n <Show when={!file()}>\n <label for={`id-link-${ariaId}`}>Embed Link</label>\n <input\n id={`id-link-${ariaId}`}\n class=\"flex h-9 rounded-md w-full bg-white dark:bg-gray-950 px-3 py-2 text-sm placeholder:text-gray-500 dark:placeholder:text-gray-500 transition border box-border border-gray-200 dark:border-gray-800 border-solid ring-0 ring-transparent focus-visible:ring-2 focus-visible:ring-gray-900 dark:focus-visible:ring-gray-300 focus-visible:ring-offset-0 outline-hidden focus-visible:outline-hidden file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:cursor-not-allowed disabled:opacity-50\"\n placeholder=\"Paste the image link...\"\n type=\"url\"\n value={url()}\n onInput={handleUrlChange}\n />\n </Show>\n\n <Show when={!url()}>\n <label for={`id-upload-${ariaId}`}>Upload</label>\n <input\n id={`id-upload-${ariaId}`}\n class=\"flex h-9 rounded-md w-full bg-white dark:bg-gray-950 px-3 py-2 text-sm placeholder:text-gray-500 dark:placeholder:text-gray-500 transition border box-border border-gray-200 dark:border-gray-800 border-solid ring-0 ring-transparent focus-visible:ring-2 focus-visible:ring-gray-900 dark:focus-visible:ring-gray-300 focus-visible:ring-offset-0 outline-hidden focus-visible:outline-hidden file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:cursor-not-allowed disabled:opacity-50\"\n accept=\"image/*\"\n type=\"file\"\n onChange={handleFileChange}\n />\n </Show>\n\n <Show when={url()}>\n <button class=\"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-white dark:ring-offset-gray-950 transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-gray-900 dark:focus-visible:ring-gray-300 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border-0 bg-gray-900 dark:bg-gray-50 text-gray-50 dark:text-gray-900 hover:bg-gray-900/90 dark:hover:bg-gray-50/90 h-10 px-4 py-2 w-full\" onClick={handleSubmit}>\n Insert Image\n </button>\n </Show>\n\n <Show when={file()}>\n <button class=\"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-white dark:ring-offset-gray-950 transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-gray-900 dark:focus-visible:ring-gray-300 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border-0 bg-gray-900 dark:bg-gray-50 text-gray-50 dark:text-gray-900 hover:bg-gray-900/90 dark:hover:bg-gray-50/90 h-10 px-4 py-2 w-full\" onClick={handleSubmit}>\n Upload Image\n </button>\n </Show>\n </PopoverPopup>\n </PopoverPositioner>\n </PopoverRoot>\n )\n}\n"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"path": "registry/src/solid/ui/image-upload-popover/index.ts",
|
|
21
|
+
"type": "registry:component",
|
|
22
|
+
"target": "components/editor/ui/image-upload-popover/index.ts",
|
|
23
|
+
"content": "export { default as ImageUploadPopover } from './image-upload-popover'\n"
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"meta": {
|
|
27
|
+
"hasIcons": false,
|
|
28
|
+
"hidden": false,
|
|
29
|
+
"story": "",
|
|
30
|
+
"framework": "solid",
|
|
31
|
+
"accumulatedFiles": [
|
|
32
|
+
"registry/src/solid/ui/button/button.tsx",
|
|
33
|
+
"registry/src/solid/ui/button/index.ts",
|
|
34
|
+
"registry/src/solid/ui/image-upload-popover/image-upload-popover.tsx",
|
|
35
|
+
"registry/src/solid/ui/image-upload-popover/index.ts"
|
|
36
|
+
],
|
|
37
|
+
"internalDependencies": [
|
|
38
|
+
"solid-ui-button"
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json"
|
|
42
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "solid-ui-image-view",
|
|
3
|
+
"title": "solid-ui-image-view",
|
|
4
|
+
"type": "registry:component",
|
|
5
|
+
"description": "",
|
|
6
|
+
"registryDependencies": [],
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"@egoist/tailwindcss-icons",
|
|
9
|
+
"@iconify-json/lucide",
|
|
10
|
+
"prosekit"
|
|
11
|
+
],
|
|
12
|
+
"files": [
|
|
13
|
+
{
|
|
14
|
+
"path": "registry/src/solid/ui/image-view/image-view.tsx",
|
|
15
|
+
"type": "registry:component",
|
|
16
|
+
"target": "components/editor/ui/image-view/image-view.tsx",
|
|
17
|
+
"content": "import { UploadTask } from 'prosekit/extensions/file'\nimport type { ImageAttrs } from 'prosekit/extensions/image'\nimport type { SolidNodeViewProps } from 'prosekit/solid'\nimport { ResizableHandle, ResizableRoot } from 'prosekit/solid/resizable'\nimport { createEffect, createSignal, onCleanup, Show, type JSX } from 'solid-js'\n\nexport default function ImageView(props: SolidNodeViewProps): JSX.Element {\n const attrs = () => props.node.attrs as ImageAttrs\n const url = () => attrs().src || ''\n const uploading = () => url().startsWith('blob:')\n\n const [aspectRatio, setAspectRatio] = createSignal<number | undefined>()\n const [error, setError] = createSignal<string | undefined>()\n const [progress, setProgress] = createSignal(0)\n\n createEffect(() => {\n if (!uploading()) return\n\n const uploadTask = UploadTask.get<string>(url())\n if (!uploadTask) return\n\n let canceled = false\n\n uploadTask.finished.catch((err) => {\n if (canceled) return\n setError(String(err))\n })\n const unsubscribeProgress = uploadTask.subscribeProgress(({ loaded, total }) => {\n if (canceled) return\n setProgress(total ? loaded / total : 0)\n })\n\n onCleanup(() => {\n canceled = true\n unsubscribeProgress()\n })\n })\n\n const handleImageLoad = (event: Event) => {\n const img = event.target as HTMLImageElement\n const { naturalWidth, naturalHeight } = img\n const ratio = naturalWidth / naturalHeight\n if (ratio && Number.isFinite(ratio)) {\n setAspectRatio(ratio)\n }\n if (naturalWidth && naturalHeight && (!attrs().width || !attrs().height)) {\n props.setAttrs({ width: naturalWidth, height: naturalHeight })\n }\n }\n\n return (\n <ResizableRoot\n width={attrs().width ?? undefined}\n height={attrs().height ?? undefined}\n aspectRatio={aspectRatio()}\n onResizeEnd={(event) => props.setAttrs(event.detail)}\n attr:data-selected={props.selected ? '' : undefined}\n class=\"relative flex items-center justify-center box-border overflow-hidden my-2 group max-h-150 max-w-full min-h-16 min-w-16 outline-2 outline-transparent data-selected:outline-blue-500 outline-solid\"\n >\n <Show when={url() && !error()}>\n <img\n src={url()}\n onLoad={handleImageLoad}\n alt=\"upload preview\"\n class=\"h-full w-full max-w-full max-h-full object-contain\"\n />\n </Show>\n <Show when={uploading() && !error()}>\n <div class=\"absolute bottom-0 left-0 m-1 flex content-center items-center gap-2 rounded-sm bg-gray-800/60 p-1.5 text-xs text-white/80 transition\">\n <div class=\"i-lucide-loader-circle size-4 animate-spin block\"></div>\n <div>{Math.round(progress() * 100)}%</div>\n </div>\n </Show>\n <Show when={error()}>\n <div class=\"absolute bottom-0 left-0 right-0 top-0 flex flex-col items-center justify-center gap-4 bg-gray-200 p-2 text-sm dark:bg-gray-800 @container\">\n <div class=\"i-lucide-image-off size-8 block\"></div>\n <div class=\"hidden opacity-80 @xs:block\">\n Failed to upload image\n </div>\n </div>\n </Show>\n <ResizableHandle\n class=\"absolute bottom-0 right-0 rounded-sm m-1.5 p-1 transition bg-gray-900/30 active:bg-gray-800/60 hover:bg-gray-800/60 text-white/50 active:text-white/80 active:translate-x-0.5 active:translate-y-0.5 opacity-0 hover:opacity-100 group-hover:opacity-100 group-data-resizing:opacity-100\"\n position=\"bottom-right\"\n >\n <div class=\"i-lucide-arrow-down-right size-4 block\"></div>\n </ResizableHandle>\n </ResizableRoot>\n )\n}\n"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"path": "registry/src/solid/ui/image-view/index.ts",
|
|
21
|
+
"type": "registry:component",
|
|
22
|
+
"target": "components/editor/ui/image-view/index.ts",
|
|
23
|
+
"content": "import type { Extension } from 'prosekit/core'\nimport { defineSolidNodeView, type SolidNodeViewComponent } from 'prosekit/solid'\n\nimport ImageView from './image-view'\n\nexport function defineImageView(): Extension {\n return defineSolidNodeView({\n name: 'image',\n component: ImageView satisfies SolidNodeViewComponent,\n })\n}\n"
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"meta": {
|
|
27
|
+
"hasIcons": true,
|
|
28
|
+
"hidden": false,
|
|
29
|
+
"story": "",
|
|
30
|
+
"framework": "solid",
|
|
31
|
+
"accumulatedFiles": [
|
|
32
|
+
"registry/src/solid/ui/image-view/image-view.tsx",
|
|
33
|
+
"registry/src/solid/ui/image-view/index.ts"
|
|
34
|
+
],
|
|
35
|
+
"internalDependencies": []
|
|
36
|
+
},
|
|
37
|
+
"css": {
|
|
38
|
+
"@plugin @egoist/tailwindcss-icons": {}
|
|
39
|
+
},
|
|
40
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json"
|
|
41
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "solid-ui-inline-menu",
|
|
3
|
+
"title": "solid-ui-inline-menu",
|
|
4
|
+
"type": "registry:component",
|
|
5
|
+
"description": "",
|
|
6
|
+
"registryDependencies": [
|
|
7
|
+
"https://prosekit.dev/r/solid-ui-button.json"
|
|
8
|
+
],
|
|
9
|
+
"dependencies": [
|
|
10
|
+
"@egoist/tailwindcss-icons",
|
|
11
|
+
"@iconify-json/lucide",
|
|
12
|
+
"prosekit"
|
|
13
|
+
],
|
|
14
|
+
"files": [
|
|
15
|
+
{
|
|
16
|
+
"path": "registry/src/solid/ui/inline-menu/index.ts",
|
|
17
|
+
"type": "registry:component",
|
|
18
|
+
"target": "components/editor/ui/inline-menu/index.ts",
|
|
19
|
+
"content": "export { default as InlineMenu } from './inline-menu'\n"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"path": "registry/src/solid/ui/inline-menu/inline-menu.tsx",
|
|
23
|
+
"type": "registry:component",
|
|
24
|
+
"target": "components/editor/ui/inline-menu/inline-menu.tsx",
|
|
25
|
+
"content": "import type { BasicExtension } from 'prosekit/basic'\nimport type { Editor } from 'prosekit/core'\nimport type { LinkAttrs } from 'prosekit/extensions/link'\nimport type { EditorState } from 'prosekit/pm/state'\nimport { useEditor, useEditorDerivedValue } from 'prosekit/solid'\nimport { InlinePopoverPopup, InlinePopoverPositioner, InlinePopoverRoot } from 'prosekit/solid/inline-popover'\nimport { createSignal, Show, type JSX } from 'solid-js'\n\nimport { Button } from '../button'\n\nfunction getInlineMenuItems(editor: Editor<BasicExtension>) {\n return {\n bold: editor.commands.toggleBold\n ? {\n isActive: editor.marks.bold.isActive(),\n canExec: editor.commands.toggleBold.canExec(),\n command: () => editor.commands.toggleBold(),\n }\n : undefined,\n italic: editor.commands.toggleItalic\n ? {\n isActive: editor.marks.italic.isActive(),\n canExec: editor.commands.toggleItalic.canExec(),\n command: () => editor.commands.toggleItalic(),\n }\n : undefined,\n underline: editor.commands.toggleUnderline\n ? {\n isActive: editor.marks.underline.isActive(),\n canExec: editor.commands.toggleUnderline.canExec(),\n command: () => editor.commands.toggleUnderline(),\n }\n : undefined,\n strike: editor.commands.toggleStrike\n ? {\n isActive: editor.marks.strike.isActive(),\n canExec: editor.commands.toggleStrike.canExec(),\n command: () => editor.commands.toggleStrike(),\n }\n : undefined,\n code: editor.commands.toggleCode\n ? {\n isActive: editor.marks.code.isActive(),\n canExec: editor.commands.toggleCode.canExec(),\n command: () => editor.commands.toggleCode(),\n }\n : undefined,\n link: editor.commands.addLink\n ? {\n isActive: editor.marks.link.isActive(),\n canExec: editor.commands.addLink.canExec({ href: '' }),\n command: () => editor.commands.expandLink(),\n currentLink: getCurrentLink(editor.state) || '',\n }\n : undefined,\n }\n}\n\nfunction getCurrentLink(state: EditorState): string | undefined {\n const { $from } = state.selection\n const marks = $from.marksAcross($from)\n if (!marks) {\n return\n }\n for (const mark of marks) {\n if (mark.type.name === 'link') {\n return (mark.attrs as LinkAttrs).href\n }\n }\n}\n\nexport default function InlineMenu(): JSX.Element {\n const editor = useEditor<BasicExtension>()\n const items = useEditorDerivedValue(getInlineMenuItems)\n\n const [linkMenuOpen, setLinkMenuOpen] = createSignal(false)\n const toggleLinkMenuOpen = () => setLinkMenuOpen((open) => !open)\n\n const handleLinkUpdate = (href?: string) => {\n if (href) {\n editor().commands.addLink({ href })\n } else {\n editor().commands.removeLink()\n }\n\n setLinkMenuOpen(false)\n editor().focus()\n }\n\n return (\n <>\n <InlinePopoverRoot\n onOpenChange={(event) => {\n if (!event.detail) {\n setLinkMenuOpen(false)\n }\n }}\n >\n <InlinePopoverPositioner class=\"block overflow-visible bg-transparent w-min h-min z-50 motion-safe:ease-out motion-safe:transition-transform motion-safe:duration-100\">\n <InlinePopoverPopup\n attr:data-testid=\"inline-menu-main\"\n class=\"box-border data-[state=closed]:motion-safe:duration-150 motion-safe:transition-discrete motion-safe:transition-all data-[state=closed]:opacity-0 starting:opacity-0 opacity-100 data-[state=closed]:scale-95 starting:scale-95 scale-100 motion-safe:duration-40 border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950 shadow-lg relative flex min-w-32 space-x-1 overflow-auto whitespace-nowrap rounded-md p-1\"\n >\n <Show when={items().bold}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Bold\"\n >\n <div class=\"i-lucide-bold size-5 block\"></div>\n </Button>\n )}\n </Show>\n <Show when={items().italic}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Italic\"\n >\n <div class=\"i-lucide-italic size-5 block\"></div>\n </Button>\n )}\n </Show>\n <Show when={items().underline}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Underline\"\n >\n <div class=\"i-lucide-underline size-5 block\"></div>\n </Button>\n )}\n </Show>\n <Show when={items().strike}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Strikethrough\"\n >\n <div class=\"i-lucide-strikethrough size-5 block\"></div>\n </Button>\n )}\n </Show>\n <Show when={items().code}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Code\"\n >\n <div class=\"i-lucide-code size-5 block\"></div>\n </Button>\n )}\n </Show>\n <Show when={items().link?.canExec && items().link}>\n {(item) => (\n <Button\n pressed={item().isActive}\n onClick={() => {\n item().command()\n toggleLinkMenuOpen()\n }}\n tooltip=\"Link\"\n >\n <div class=\"i-lucide-link size-5 block\"></div>\n </Button>\n )}\n </Show>\n </InlinePopoverPopup>\n </InlinePopoverPositioner>\n </InlinePopoverRoot>\n\n <Show when={items().link}>\n {(item) => (\n <InlinePopoverRoot\n defaultOpen={false}\n open={linkMenuOpen()}\n onOpenChange={(event) => setLinkMenuOpen(event.detail)}\n >\n <InlinePopoverPositioner placement=\"bottom\" class=\"block overflow-visible bg-transparent w-min h-min z-50 motion-safe:ease-out motion-safe:transition-transform motion-safe:duration-100\">\n <InlinePopoverPopup\n attr:data-testid=\"inline-menu-link\"\n class=\"box-border data-[state=closed]:motion-safe:duration-150 motion-safe:transition-discrete motion-safe:transition-all data-[state=closed]:opacity-0 starting:opacity-0 opacity-100 data-[state=closed]:scale-95 starting:scale-95 scale-100 motion-safe:duration-40 border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950 shadow-lg relative flex flex-col w-xs rounded-lg p-4 gap-y-2 items-stretch\"\n >\n <Show when={linkMenuOpen()}>\n <form\n onSubmit={(event) => {\n event.preventDefault()\n const target = event.target as HTMLFormElement | null\n const href = target?.querySelector('input')?.value?.trim()\n handleLinkUpdate(href)\n }}\n >\n <input\n placeholder=\"Paste the link...\"\n value={item().currentLink || ''}\n class=\"flex h-9 rounded-md w-full bg-white dark:bg-gray-950 px-3 py-2 text-sm placeholder:text-gray-500 dark:placeholder:text-gray-500 transition border box-border border-gray-200 dark:border-gray-800 border-solid ring-0 ring-transparent focus-visible:ring-2 focus-visible:ring-gray-900 dark:focus-visible:ring-gray-300 focus-visible:ring-offset-0 outline-hidden focus-visible:outline-hidden file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:cursor-not-allowed disabled:opacity-50\"\n />\n </form>\n </Show>\n <Show when={item().isActive}>\n <button\n onClick={() => handleLinkUpdate()}\n onMouseDown={(event) => event.preventDefault()}\n class=\"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-white dark:ring-offset-gray-950 transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-gray-900 dark:focus-visible:ring-gray-300 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border-0 bg-gray-900 dark:bg-gray-50 text-gray-50 dark:text-gray-900 hover:bg-gray-900/90 dark:hover:bg-gray-50/90 h-9 px-3\"\n >\n Remove link\n </button>\n </Show>\n </InlinePopoverPopup>\n </InlinePopoverPositioner>\n </InlinePopoverRoot>\n )}\n </Show>\n </>\n )\n}\n"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"meta": {
|
|
29
|
+
"hasIcons": true,
|
|
30
|
+
"hidden": false,
|
|
31
|
+
"story": "",
|
|
32
|
+
"framework": "solid",
|
|
33
|
+
"accumulatedFiles": [
|
|
34
|
+
"registry/src/solid/ui/button/button.tsx",
|
|
35
|
+
"registry/src/solid/ui/button/index.ts",
|
|
36
|
+
"registry/src/solid/ui/inline-menu/index.ts",
|
|
37
|
+
"registry/src/solid/ui/inline-menu/inline-menu.tsx"
|
|
38
|
+
],
|
|
39
|
+
"internalDependencies": [
|
|
40
|
+
"solid-ui-button"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"css": {
|
|
44
|
+
"@plugin @egoist/tailwindcss-icons": {}
|
|
45
|
+
},
|
|
46
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json"
|
|
47
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "solid-ui-search",
|
|
3
|
+
"title": "solid-ui-search",
|
|
4
|
+
"type": "registry:component",
|
|
5
|
+
"description": "",
|
|
6
|
+
"registryDependencies": [
|
|
7
|
+
"https://prosekit.dev/r/solid-ui-button.json"
|
|
8
|
+
],
|
|
9
|
+
"dependencies": [
|
|
10
|
+
"@egoist/tailwindcss-icons",
|
|
11
|
+
"@iconify-json/lucide",
|
|
12
|
+
"prosekit"
|
|
13
|
+
],
|
|
14
|
+
"files": [
|
|
15
|
+
{
|
|
16
|
+
"path": "registry/src/solid/ui/search/index.ts",
|
|
17
|
+
"type": "registry:component",
|
|
18
|
+
"target": "components/editor/ui/search/index.ts",
|
|
19
|
+
"content": "export { default as Search } from './search'\n"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"path": "registry/src/solid/ui/search/search.tsx",
|
|
23
|
+
"type": "registry:component",
|
|
24
|
+
"target": "components/editor/ui/search/search.tsx",
|
|
25
|
+
"content": "import { defineSearchQuery, type SearchCommandsExtension } from 'prosekit/extensions/search'\nimport { useEditor, useExtension } from 'prosekit/solid'\nimport { createMemo, createSignal, type JSX } from 'solid-js'\n\nimport { Button } from '../button'\n\nexport default function Search(props: { onClose?: VoidFunction }): JSX.Element {\n const [showReplace, setShowReplace] = createSignal(false)\n const toggleReplace = () => setShowReplace((value) => !value)\n\n const [searchText, setSearchText] = createSignal('')\n const [replaceText, setReplaceText] = createSignal('')\n\n const extension = createMemo(() => {\n if (!searchText()) {\n return null\n }\n return defineSearchQuery({ search: searchText(), replace: replaceText() })\n })\n\n useExtension(extension)\n\n const editor = useEditor<SearchCommandsExtension>({ update: true })\n\n const handleSearchKeyDown = (event: KeyboardEvent) => {\n if (isEnter(event)) {\n event.preventDefault()\n editor().commands.findNext()\n } else if (isShiftEnter(event)) {\n event.preventDefault()\n editor().commands.findPrev()\n }\n }\n\n const handleReplaceKeyDown = (event: KeyboardEvent) => {\n if (isEnter(event)) {\n event.preventDefault()\n editor().commands.replaceNext()\n } else if (isShiftEnter(event)) {\n event.preventDefault()\n editor().commands.replaceAll()\n }\n }\n\n return (\n <div class=\"z-2 box-border border-gray-200 dark:border-gray-800 border-solid border-l-0 border-r-0 border-t-0 border-b grid grid-cols-[min-content_1fr_min-content] gap-2 p-2\">\n <Button tooltip=\"Toggle Replace\" onClick={toggleReplace}>\n <span\n attr:data-rotate={showReplace() ? '' : undefined}\n class=\"i-lucide-chevron-right size-5 block transition-transform data-rotate:rotate-90\"\n />\n </Button>\n <input\n placeholder=\"Search\"\n type=\"text\"\n value={searchText()}\n onInput={(event) => setSearchText(event.currentTarget.value)}\n onKeyDown={handleSearchKeyDown}\n class=\"flex h-9 rounded-md w-full bg-white dark:bg-gray-950 px-3 py-2 text-sm placeholder:text-gray-500 dark:placeholder:text-gray-500 transition border box-border border-gray-200 dark:border-gray-800 border-solid ring-0 ring-transparent focus-visible:ring-2 focus-visible:ring-gray-900 dark:focus-visible:ring-gray-300 focus-visible:ring-offset-0 outline-hidden focus-visible:outline-hidden file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:cursor-not-allowed disabled:opacity-50 col-start-2\"\n />\n <div class=\"flex items-center justify-between gap-1\">\n <Button\n tooltip=\"Previous (Shift Enter)\"\n onClick={() => editor().commands.findPrev()}\n >\n <span class=\"i-lucide-arrow-left size-5 block\" />\n </Button>\n <Button tooltip=\"Next (Enter)\" onClick={() => editor().commands.findNext()}>\n <span class=\"i-lucide-arrow-right size-5 block\" />\n </Button>\n <Button tooltip=\"Close\" onClick={() => props.onClose?.()}>\n <span class=\"i-lucide-x size-5 block\" />\n </Button>\n </div>\n {showReplace() && (\n <input\n placeholder=\"Replace\"\n type=\"text\"\n value={replaceText()}\n onInput={(event) => setReplaceText(event.currentTarget.value)}\n onKeyDown={handleReplaceKeyDown}\n class=\"flex h-9 rounded-md w-full bg-white dark:bg-gray-950 px-3 py-2 text-sm placeholder:text-gray-500 dark:placeholder:text-gray-500 transition border box-border border-gray-200 dark:border-gray-800 border-solid ring-0 ring-transparent focus-visible:ring-2 focus-visible:ring-gray-900 dark:focus-visible:ring-gray-300 focus-visible:ring-offset-0 outline-hidden focus-visible:outline-hidden file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:cursor-not-allowed disabled:opacity-50 col-start-2\"\n />\n )}\n {showReplace() && (\n <div class=\"flex items-center justify-between gap-1\">\n <Button tooltip=\"Replace (Enter)\" onClick={() => editor().commands.replaceNext()}>\n Replace\n </Button>\n <Button\n tooltip=\"Replace All (Shift Enter)\"\n onClick={() => editor().commands.replaceAll()}\n >\n All\n </Button>\n </div>\n )}\n </div>\n )\n}\n\nfunction isEnter(event: KeyboardEvent) {\n return (\n event.key === 'Enter'\n && !event.shiftKey\n && !event.metaKey\n && !event.altKey\n && !event.ctrlKey\n && !event.isComposing\n )\n}\n\nfunction isShiftEnter(event: KeyboardEvent) {\n return (\n event.key === 'Enter'\n && event.shiftKey\n && !event.metaKey\n && !event.altKey\n && !event.ctrlKey\n && !event.isComposing\n )\n}\n"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"meta": {
|
|
29
|
+
"hasIcons": true,
|
|
30
|
+
"hidden": false,
|
|
31
|
+
"story": "",
|
|
32
|
+
"framework": "solid",
|
|
33
|
+
"accumulatedFiles": [
|
|
34
|
+
"registry/src/solid/ui/button/button.tsx",
|
|
35
|
+
"registry/src/solid/ui/button/index.ts",
|
|
36
|
+
"registry/src/solid/ui/search/index.ts",
|
|
37
|
+
"registry/src/solid/ui/search/search.tsx"
|
|
38
|
+
],
|
|
39
|
+
"internalDependencies": [
|
|
40
|
+
"solid-ui-button"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"css": {
|
|
44
|
+
"@plugin @egoist/tailwindcss-icons": {}
|
|
45
|
+
},
|
|
46
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json"
|
|
47
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "solid-ui-slash-menu",
|
|
3
|
+
"title": "solid-ui-slash-menu",
|
|
4
|
+
"type": "registry:component",
|
|
5
|
+
"description": "",
|
|
6
|
+
"registryDependencies": [],
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"prosekit"
|
|
9
|
+
],
|
|
10
|
+
"files": [
|
|
11
|
+
{
|
|
12
|
+
"path": "registry/src/solid/ui/slash-menu/index.ts",
|
|
13
|
+
"type": "registry:component",
|
|
14
|
+
"target": "components/editor/ui/slash-menu/index.ts",
|
|
15
|
+
"content": "export { default as SlashMenu } from './slash-menu'\n"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"path": "registry/src/solid/ui/slash-menu/slash-menu-empty.tsx",
|
|
19
|
+
"type": "registry:component",
|
|
20
|
+
"target": "components/editor/ui/slash-menu/slash-menu-empty.tsx",
|
|
21
|
+
"content": "import { AutocompleteEmpty } from 'prosekit/solid/autocomplete'\nimport type { JSX } from 'solid-js'\n\nexport default function SlashMenuEmpty(): JSX.Element {\n return (\n <AutocompleteEmpty class=\"relative flex items-center justify-between min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\">\n <span>No results</span>\n </AutocompleteEmpty>\n )\n}\n"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"path": "registry/src/solid/ui/slash-menu/slash-menu-item.tsx",
|
|
25
|
+
"type": "registry:component",
|
|
26
|
+
"target": "components/editor/ui/slash-menu/slash-menu-item.tsx",
|
|
27
|
+
"content": "import { AutocompleteItem } from 'prosekit/solid/autocomplete'\nimport { Show, type JSX } from 'solid-js'\n\nexport default function SlashMenuItem(props: {\n label: string\n kbd?: string\n onSelect: () => void\n}): JSX.Element {\n return (\n <AutocompleteItem onSelect={props.onSelect} class=\"relative flex items-center justify-between min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\">\n <span>{props.label}</span>\n <Show when={props.kbd}>\n <kbd class=\"text-xs font-mono text-gray-400 dark:text-gray-500\">{props.kbd}</kbd>\n </Show>\n </AutocompleteItem>\n )\n}\n"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"path": "registry/src/solid/ui/slash-menu/slash-menu.tsx",
|
|
31
|
+
"type": "registry:component",
|
|
32
|
+
"target": "components/editor/ui/slash-menu/slash-menu.tsx",
|
|
33
|
+
"content": "import type { BasicExtension } from 'prosekit/basic'\nimport { canUseRegexLookbehind } from 'prosekit/core'\nimport { useEditor } from 'prosekit/solid'\nimport { AutocompletePopup, AutocompletePositioner, AutocompleteRoot } from 'prosekit/solid/autocomplete'\nimport type { JSX } from 'solid-js'\n\nimport SlashMenuEmpty from './slash-menu-empty'\nimport SlashMenuItem from './slash-menu-item'\n\n// Match inputs like \"/\", \"/table\", \"/heading 1\" etc. Do not match \"/ heading\".\nconst regex = canUseRegexLookbehind() ? /(?<!\\S)\\/(\\S.*)?$/u : /\\/(\\S.*)?$/u\n\nexport default function SlashMenu(): JSX.Element {\n const editor = useEditor<BasicExtension>()\n\n return (\n <AutocompleteRoot regex={regex}>\n <AutocompletePositioner class=\"block overflow-visible bg-transparent w-min h-min z-50 motion-safe:ease-out motion-safe:transition-transform motion-safe:duration-100\">\n <AutocompletePopup class=\"box-border data-[state=closed]:motion-safe:duration-150 motion-safe:transition-discrete motion-safe:transition-all data-[state=closed]:opacity-0 starting:opacity-0 opacity-100 data-[state=closed]:scale-95 starting:scale-95 scale-100 motion-safe:duration-40 rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950 shadow-lg flex flex-col relative max-h-100 min-w-60 select-none overflow-auto whitespace-nowrap p-1\">\n <SlashMenuItem\n label=\"Text\"\n onSelect={() => editor().commands.setParagraph()}\n />\n\n <SlashMenuItem\n label=\"Heading 1\"\n kbd=\"#\"\n onSelect={() => editor().commands.setHeading({ level: 1 })}\n />\n\n <SlashMenuItem\n label=\"Heading 2\"\n kbd=\"##\"\n onSelect={() => editor().commands.setHeading({ level: 2 })}\n />\n\n <SlashMenuItem\n label=\"Heading 3\"\n kbd=\"###\"\n onSelect={() => editor().commands.setHeading({ level: 3 })}\n />\n\n <SlashMenuItem\n label=\"Bullet list\"\n kbd=\"-\"\n onSelect={() => editor().commands.wrapInList({ kind: 'bullet' })}\n />\n\n <SlashMenuItem\n label=\"Ordered list\"\n kbd=\"1.\"\n onSelect={() => editor().commands.wrapInList({ kind: 'ordered' })}\n />\n\n <SlashMenuItem\n label=\"Task list\"\n kbd=\"[]\"\n onSelect={() => editor().commands.wrapInList({ kind: 'task' })}\n />\n\n <SlashMenuItem\n label=\"Toggle list\"\n kbd=\">>\"\n onSelect={() => editor().commands.wrapInList({ kind: 'toggle' })}\n />\n\n <SlashMenuItem\n label=\"Quote\"\n kbd=\">\"\n onSelect={() => editor().commands.setBlockquote()}\n />\n\n <SlashMenuItem\n label=\"Table\"\n onSelect={() => editor().commands.insertTable({ row: 3, col: 3 })}\n />\n\n <SlashMenuItem\n label=\"Divider\"\n kbd=\"---\"\n onSelect={() => editor().commands.insertHorizontalRule()}\n />\n\n <SlashMenuItem\n label=\"Code\"\n kbd=\"```\"\n onSelect={() => editor().commands.setCodeBlock()}\n />\n\n <SlashMenuEmpty />\n </AutocompletePopup>\n </AutocompletePositioner>\n </AutocompleteRoot>\n )\n}\n"
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"meta": {
|
|
37
|
+
"hasIcons": false,
|
|
38
|
+
"hidden": false,
|
|
39
|
+
"story": "",
|
|
40
|
+
"framework": "solid",
|
|
41
|
+
"accumulatedFiles": [
|
|
42
|
+
"registry/src/solid/ui/slash-menu/index.ts",
|
|
43
|
+
"registry/src/solid/ui/slash-menu/slash-menu-empty.tsx",
|
|
44
|
+
"registry/src/solid/ui/slash-menu/slash-menu-item.tsx",
|
|
45
|
+
"registry/src/solid/ui/slash-menu/slash-menu.tsx"
|
|
46
|
+
],
|
|
47
|
+
"internalDependencies": []
|
|
48
|
+
},
|
|
49
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json"
|
|
50
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "solid-ui-table-handle",
|
|
3
|
+
"title": "solid-ui-table-handle",
|
|
4
|
+
"type": "registry:component",
|
|
5
|
+
"description": "",
|
|
6
|
+
"registryDependencies": [],
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"@egoist/tailwindcss-icons",
|
|
9
|
+
"@iconify-json/lucide",
|
|
10
|
+
"prosekit"
|
|
11
|
+
],
|
|
12
|
+
"files": [
|
|
13
|
+
{
|
|
14
|
+
"path": "registry/src/solid/ui/table-handle/index.ts",
|
|
15
|
+
"type": "registry:component",
|
|
16
|
+
"target": "components/editor/ui/table-handle/index.ts",
|
|
17
|
+
"content": "export { default as TableHandle } from './table-handle'\n"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"path": "registry/src/solid/ui/table-handle/table-handle.tsx",
|
|
21
|
+
"type": "registry:component",
|
|
22
|
+
"target": "components/editor/ui/table-handle/table-handle.tsx",
|
|
23
|
+
"content": "import type { Editor } from 'prosekit/core'\nimport type { TableExtension } from 'prosekit/extensions/table'\nimport { useEditorDerivedValue } from 'prosekit/solid'\nimport { MenuItem, MenuPopup, MenuPositioner } from 'prosekit/solid/menu'\nimport {\n TableHandleColumnMenuRoot,\n TableHandleColumnMenuTrigger,\n TableHandleColumnPopup,\n TableHandleColumnPositioner,\n TableHandleDragPreview,\n TableHandleDropIndicator,\n TableHandleRoot,\n TableHandleRowMenuRoot,\n TableHandleRowMenuTrigger,\n TableHandleRowPopup,\n TableHandleRowPositioner,\n} from 'prosekit/solid/table-handle'\nimport { Show, type JSX } from 'solid-js'\n\nfunction getTableHandleState(editor: Editor<TableExtension>) {\n return {\n addTableColumnBefore: {\n canExec: editor.commands.addTableColumnBefore.canExec(),\n command: () => editor.commands.addTableColumnBefore(),\n },\n addTableColumnAfter: {\n canExec: editor.commands.addTableColumnAfter.canExec(),\n command: () => editor.commands.addTableColumnAfter(),\n },\n deleteCellSelection: {\n canExec: editor.commands.deleteCellSelection.canExec(),\n command: () => editor.commands.deleteCellSelection(),\n },\n deleteTableColumn: {\n canExec: editor.commands.deleteTableColumn.canExec(),\n command: () => editor.commands.deleteTableColumn(),\n },\n addTableRowAbove: {\n canExec: editor.commands.addTableRowAbove.canExec(),\n command: () => editor.commands.addTableRowAbove(),\n },\n addTableRowBelow: {\n canExec: editor.commands.addTableRowBelow.canExec(),\n command: () => editor.commands.addTableRowBelow(),\n },\n deleteTableRow: {\n canExec: editor.commands.deleteTableRow.canExec(),\n command: () => editor.commands.deleteTableRow(),\n },\n deleteTable: {\n canExec: editor.commands.deleteTable.canExec(),\n command: () => editor.commands.deleteTable(),\n },\n }\n}\n\ninterface Props {\n dir?: 'ltr' | 'rtl'\n}\n\nexport default function TableHandle(props: Props): JSX.Element {\n const state = useEditorDerivedValue(getTableHandleState)\n\n return (\n <TableHandleRoot>\n <TableHandleDragPreview />\n <TableHandleDropIndicator />\n <TableHandleColumnPositioner class=\"block overflow-visible bg-transparent w-min h-min z-50 motion-safe:ease-out motion-safe:transition-transform motion-safe:duration-100\">\n <TableHandleColumnPopup class=\"translate-y-[50%] flex box-border motion-safe:duration-100 data-[state=closed]:motion-safe:duration-150 motion-safe:transition-discrete motion-safe:transition-all data-[state=closed]:opacity-0 starting:opacity-0 opacity-100 data-[state=closed]:scale-95 starting:scale-95 scale-100\">\n <TableHandleColumnMenuRoot>\n <TableHandleColumnMenuTrigger class=\"h-4.5 w-6 flex items-center box-border justify-center bg-white dark:bg-gray-950 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-sm text-gray-500/50 dark:text-gray-400/50 border border-gray-200 dark:border-gray-800 border-solid p-0 transition-colors overflow-clip\">\n <div class=\"i-lucide-grip-horizontal size-5 min-h-5 min-w-5 block\"></div>\n </TableHandleColumnMenuTrigger>\n <MenuPositioner class=\"overflow-visible bg-transparent\">\n <MenuPopup class=\"box-border data-[state=closed]:motion-safe:duration-150 motion-safe:transition-discrete motion-safe:transition-all data-[state=closed]:opacity-0 starting:opacity-0 opacity-100 data-[state=closed]:scale-95 starting:scale-95 scale-100 motion-safe:duration-40 rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950 shadow-lg relative flex flex-col max-h-100 min-w-32 select-none overflow-auto whitespace-nowrap p-1 outline-none\">\n <Show when={state().addTableColumnBefore.canExec}>\n <MenuItem\n class=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n onSelect={() => state().addTableColumnBefore.command()}\n >\n <span>Insert Left</span>\n </MenuItem>\n </Show>\n <Show when={state().addTableColumnAfter.canExec}>\n <MenuItem\n class=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n onSelect={() => state().addTableColumnAfter.command()}\n >\n <span>Insert Right</span>\n </MenuItem>\n </Show>\n <Show when={state().deleteCellSelection.canExec}>\n <MenuItem\n class=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n onSelect={() => state().deleteCellSelection.command()}\n >\n <span>Clear Contents</span>\n <span class=\"text-xs tracking-widest text-gray-500 dark:text-gray-500\">Del</span>\n </MenuItem>\n </Show>\n <Show when={state().deleteTableColumn.canExec}>\n <MenuItem\n class=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n onSelect={() => state().deleteTableColumn.command()}\n >\n <span>Delete Column</span>\n </MenuItem>\n </Show>\n <Show when={state().deleteTable.canExec}>\n <MenuItem\n class=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n attr:data-danger=\"\"\n onSelect={() => state().deleteTable.command()}\n >\n <span>Delete Table</span>\n </MenuItem>\n </Show>\n </MenuPopup>\n </MenuPositioner>\n </TableHandleColumnMenuRoot>\n </TableHandleColumnPopup>\n </TableHandleColumnPositioner>\n <TableHandleRowPositioner\n placement={props.dir === 'rtl' ? 'right' : 'left'}\n class=\"block overflow-visible bg-transparent w-min h-min z-50 motion-safe:ease-out motion-safe:transition-transform motion-safe:duration-100\"\n >\n <TableHandleRowPopup class=\"ltr:translate-x-[50%] rtl:translate-x-[-50%] flex box-border motion-safe:duration-100 data-[state=closed]:motion-safe:duration-150 motion-safe:transition-discrete motion-safe:transition-all data-[state=closed]:opacity-0 starting:opacity-0 opacity-100 data-[state=closed]:scale-95 starting:scale-95 scale-100\">\n <TableHandleRowMenuRoot>\n <TableHandleRowMenuTrigger class=\"h-6 w-4.5 flex items-center box-border justify-center bg-white dark:bg-gray-950 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-sm text-gray-500/50 dark:text-gray-400/50 border border-gray-200 dark:border-gray-800 border-solid p-0 transition-colors overflow-clip\">\n <div class=\"i-lucide-grip-vertical size-5 min-h-5 min-w-5 block\"></div>\n </TableHandleRowMenuTrigger>\n <MenuPositioner class=\"overflow-visible bg-transparent\">\n <MenuPopup class=\"box-border data-[state=closed]:motion-safe:duration-150 motion-safe:transition-discrete motion-safe:transition-all data-[state=closed]:opacity-0 starting:opacity-0 opacity-100 data-[state=closed]:scale-95 starting:scale-95 scale-100 motion-safe:duration-40 rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950 shadow-lg relative flex flex-col max-h-100 min-w-32 select-none overflow-auto whitespace-nowrap p-1 outline-none\">\n <Show when={state().addTableRowAbove.canExec}>\n <MenuItem\n class=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n onSelect={() => state().addTableRowAbove.command()}\n >\n <span>Insert Above</span>\n </MenuItem>\n </Show>\n <Show when={state().addTableRowBelow.canExec}>\n <MenuItem\n class=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n onSelect={() => state().addTableRowBelow.command()}\n >\n <span>Insert Below</span>\n </MenuItem>\n </Show>\n <Show when={state().deleteCellSelection.canExec}>\n <MenuItem\n class=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n onSelect={() => state().deleteCellSelection.command()}\n >\n <span>Clear Contents</span>\n <span class=\"text-xs tracking-widest text-gray-500 dark:text-gray-500\">Del</span>\n </MenuItem>\n </Show>\n <Show when={state().deleteTableRow.canExec}>\n <MenuItem\n class=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n onSelect={() => state().deleteTableRow.command()}\n >\n <span>Delete Row</span>\n </MenuItem>\n </Show>\n <Show when={state().deleteTable.canExec}>\n <MenuItem\n class=\"relative min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 flex items-center justify-between gap-8 data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 hover:data-[disabled=true]:opacity-50 data-danger:text-red-500 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n attr:data-danger=\"\"\n onSelect={() => state().deleteTable.command()}\n >\n <span>Delete Table</span>\n </MenuItem>\n </Show>\n </MenuPopup>\n </MenuPositioner>\n </TableHandleRowMenuRoot>\n </TableHandleRowPopup>\n </TableHandleRowPositioner>\n </TableHandleRoot>\n )\n}\n"
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"meta": {
|
|
27
|
+
"hasIcons": true,
|
|
28
|
+
"hidden": false,
|
|
29
|
+
"story": "",
|
|
30
|
+
"framework": "solid",
|
|
31
|
+
"accumulatedFiles": [
|
|
32
|
+
"registry/src/solid/ui/table-handle/index.ts",
|
|
33
|
+
"registry/src/solid/ui/table-handle/table-handle.tsx"
|
|
34
|
+
],
|
|
35
|
+
"internalDependencies": []
|
|
36
|
+
},
|
|
37
|
+
"css": {
|
|
38
|
+
"@plugin @egoist/tailwindcss-icons": {}
|
|
39
|
+
},
|
|
40
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json"
|
|
41
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "solid-ui-tag-menu",
|
|
3
|
+
"title": "solid-ui-tag-menu",
|
|
4
|
+
"type": "registry:component",
|
|
5
|
+
"description": "",
|
|
6
|
+
"registryDependencies": [],
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"prosekit"
|
|
9
|
+
],
|
|
10
|
+
"files": [
|
|
11
|
+
{
|
|
12
|
+
"path": "registry/src/solid/ui/tag-menu/index.ts",
|
|
13
|
+
"type": "registry:component",
|
|
14
|
+
"target": "components/editor/ui/tag-menu/index.ts",
|
|
15
|
+
"content": "export { default as TagMenu } from './tag-menu'\n"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"path": "registry/src/solid/ui/tag-menu/tag-menu.tsx",
|
|
19
|
+
"type": "registry:component",
|
|
20
|
+
"target": "components/editor/ui/tag-menu/tag-menu.tsx",
|
|
21
|
+
"content": "import type { BasicExtension } from 'prosekit/basic'\nimport type { Union } from 'prosekit/core'\nimport type { MentionExtension } from 'prosekit/extensions/mention'\nimport { useEditor } from 'prosekit/solid'\nimport {\n AutocompleteEmpty,\n AutocompleteItem,\n AutocompletePopup,\n AutocompletePositioner,\n AutocompleteRoot,\n} from 'prosekit/solid/autocomplete'\nimport { For, type JSX } from 'solid-js'\n\nconst regex = /#[\\da-z]*$/i\n\nexport default function TagMenu(props: { tags: { id: number; label: string }[] }): JSX.Element {\n const editor = useEditor<Union<[MentionExtension, BasicExtension]>>()\n\n const handleTagInsert = (id: number, label: string) => {\n editor().commands.insertMention({\n id: id.toString(),\n value: '#' + label,\n kind: 'tag',\n })\n editor().commands.insertText({ text: ' ' })\n }\n\n return (\n <AutocompleteRoot regex={regex}>\n <AutocompletePositioner class=\"block overflow-visible bg-transparent w-min h-min z-50 motion-safe:ease-out motion-safe:transition-transform motion-safe:duration-100\">\n <AutocompletePopup class=\"box-border data-[state=closed]:motion-safe:duration-150 motion-safe:transition-discrete motion-safe:transition-all data-[state=closed]:opacity-0 starting:opacity-0 opacity-100 data-[state=closed]:scale-95 starting:scale-95 scale-100 motion-safe:duration-40 rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950 shadow-lg flex flex-col relative max-h-100 min-w-60 select-none overflow-auto whitespace-nowrap p-1\">\n <AutocompleteEmpty class=\"relative flex items-center justify-between min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\">\n No results\n </AutocompleteEmpty>\n\n <For each={props.tags}>\n {(tag) => (\n <AutocompleteItem\n class=\"relative flex items-center justify-between min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n onSelect={() => handleTagInsert(tag.id, tag.label)}\n >\n #{tag.label}\n </AutocompleteItem>\n )}\n </For>\n </AutocompletePopup>\n </AutocompletePositioner>\n </AutocompleteRoot>\n )\n}\n"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"meta": {
|
|
25
|
+
"hasIcons": false,
|
|
26
|
+
"hidden": false,
|
|
27
|
+
"story": "",
|
|
28
|
+
"framework": "solid",
|
|
29
|
+
"accumulatedFiles": [
|
|
30
|
+
"registry/src/solid/ui/tag-menu/index.ts",
|
|
31
|
+
"registry/src/solid/ui/tag-menu/tag-menu.tsx"
|
|
32
|
+
],
|
|
33
|
+
"internalDependencies": []
|
|
34
|
+
},
|
|
35
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json"
|
|
36
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "solid-ui-toolbar",
|
|
3
|
+
"title": "solid-ui-toolbar",
|
|
4
|
+
"type": "registry:component",
|
|
5
|
+
"description": "",
|
|
6
|
+
"registryDependencies": [
|
|
7
|
+
"https://prosekit.dev/r/solid-ui-button.json",
|
|
8
|
+
"https://prosekit.dev/r/solid-ui-image-upload-popover.json"
|
|
9
|
+
],
|
|
10
|
+
"dependencies": [
|
|
11
|
+
"@egoist/tailwindcss-icons",
|
|
12
|
+
"@iconify-json/lucide",
|
|
13
|
+
"prosekit"
|
|
14
|
+
],
|
|
15
|
+
"files": [
|
|
16
|
+
{
|
|
17
|
+
"path": "registry/src/solid/ui/toolbar/index.ts",
|
|
18
|
+
"type": "registry:component",
|
|
19
|
+
"target": "components/editor/ui/toolbar/index.ts",
|
|
20
|
+
"content": "export { default as Toolbar } from './toolbar'\n"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"path": "registry/src/solid/ui/toolbar/toolbar.tsx",
|
|
24
|
+
"type": "registry:component",
|
|
25
|
+
"target": "components/editor/ui/toolbar/toolbar.tsx",
|
|
26
|
+
"content": "import type { BasicExtension } from 'prosekit/basic'\nimport type { Editor } from 'prosekit/core'\nimport type { Uploader } from 'prosekit/extensions/file'\nimport { useEditorDerivedValue } from 'prosekit/solid'\nimport { Show, type JSX } from 'solid-js'\n\nimport { Button } from '../button'\nimport { ImageUploadPopover } from '../image-upload-popover'\n\nfunction getToolbarItems(editor: Editor<BasicExtension>) {\n return {\n undo: editor.commands.undo\n ? {\n isActive: false,\n canExec: editor.commands.undo.canExec(),\n command: () => editor.commands.undo(),\n }\n : undefined,\n redo: editor.commands.redo\n ? {\n isActive: false,\n canExec: editor.commands.redo.canExec(),\n command: () => editor.commands.redo(),\n }\n : undefined,\n bold: editor.commands.toggleBold\n ? {\n isActive: editor.marks.bold.isActive(),\n canExec: editor.commands.toggleBold.canExec(),\n command: () => editor.commands.toggleBold(),\n }\n : undefined,\n italic: editor.commands.toggleItalic\n ? {\n isActive: editor.marks.italic.isActive(),\n canExec: editor.commands.toggleItalic.canExec(),\n command: () => editor.commands.toggleItalic(),\n }\n : undefined,\n underline: editor.commands.toggleUnderline\n ? {\n isActive: editor.marks.underline.isActive(),\n canExec: editor.commands.toggleUnderline.canExec(),\n command: () => editor.commands.toggleUnderline(),\n }\n : undefined,\n strike: editor.commands.toggleStrike\n ? {\n isActive: editor.marks.strike.isActive(),\n canExec: editor.commands.toggleStrike.canExec(),\n command: () => editor.commands.toggleStrike(),\n }\n : undefined,\n code: editor.commands.toggleCode\n ? {\n isActive: editor.marks.code.isActive(),\n canExec: editor.commands.toggleCode.canExec(),\n command: () => editor.commands.toggleCode(),\n }\n : undefined,\n codeBlock: editor.commands.insertCodeBlock\n ? {\n isActive: editor.nodes.codeBlock.isActive(),\n canExec: editor.commands.insertCodeBlock.canExec({ language: 'javascript' }),\n command: () => editor.commands.insertCodeBlock({ language: 'javascript' }),\n }\n : undefined,\n heading1: editor.commands.toggleHeading\n ? {\n isActive: editor.nodes.heading.isActive({ level: 1 }),\n canExec: editor.commands.toggleHeading.canExec({ level: 1 }),\n command: () => editor.commands.toggleHeading({ level: 1 }),\n }\n : undefined,\n heading2: editor.commands.toggleHeading\n ? {\n isActive: editor.nodes.heading.isActive({ level: 2 }),\n canExec: editor.commands.toggleHeading.canExec({ level: 2 }),\n command: () => editor.commands.toggleHeading({ level: 2 }),\n }\n : undefined,\n heading3: editor.commands.toggleHeading\n ? {\n isActive: editor.nodes.heading.isActive({ level: 3 }),\n canExec: editor.commands.toggleHeading.canExec({ level: 3 }),\n command: () => editor.commands.toggleHeading({ level: 3 }),\n }\n : undefined,\n horizontalRule: editor.commands.insertHorizontalRule\n ? {\n isActive: editor.nodes.horizontalRule.isActive(),\n canExec: editor.commands.insertHorizontalRule.canExec(),\n command: () => editor.commands.insertHorizontalRule(),\n }\n : undefined,\n blockquote: editor.commands.toggleBlockquote\n ? {\n isActive: editor.nodes.blockquote.isActive(),\n canExec: editor.commands.toggleBlockquote.canExec(),\n command: () => editor.commands.toggleBlockquote(),\n }\n : undefined,\n bulletList: editor.commands.toggleList\n ? {\n isActive: editor.nodes.list.isActive({ kind: 'bullet' }),\n canExec: editor.commands.toggleList.canExec({ kind: 'bullet' }),\n command: () => editor.commands.toggleList({ kind: 'bullet' }),\n }\n : undefined,\n orderedList: editor.commands.toggleList\n ? {\n isActive: editor.nodes.list.isActive({ kind: 'ordered' }),\n canExec: editor.commands.toggleList.canExec({ kind: 'ordered' }),\n command: () => editor.commands.toggleList({ kind: 'ordered' }),\n }\n : undefined,\n taskList: editor.commands.toggleList\n ? {\n isActive: editor.nodes.list.isActive({ kind: 'task' }),\n canExec: editor.commands.toggleList.canExec({ kind: 'task' }),\n command: () => editor.commands.toggleList({ kind: 'task' }),\n }\n : undefined,\n toggleList: editor.commands.toggleList\n ? {\n isActive: editor.nodes.list.isActive({ kind: 'toggle' }),\n canExec: editor.commands.toggleList.canExec({ kind: 'toggle' }),\n command: () => editor.commands.toggleList({ kind: 'toggle' }),\n }\n : undefined,\n indentList: editor.commands.indentList\n ? {\n isActive: false,\n canExec: editor.commands.indentList.canExec(),\n command: () => editor.commands.indentList(),\n }\n : undefined,\n dedentList: editor.commands.dedentList\n ? {\n isActive: false,\n canExec: editor.commands.dedentList.canExec(),\n command: () => editor.commands.dedentList(),\n }\n : undefined,\n insertImage: editor.commands.insertImage\n ? {\n isActive: false,\n canExec: editor.commands.insertImage.canExec(),\n }\n : undefined,\n }\n}\n\nexport default function Toolbar(props: { uploader?: Uploader<string> }): JSX.Element {\n const items = useEditorDerivedValue(getToolbarItems)\n\n return (\n <div class=\"z-2 box-border border-gray-200 dark:border-gray-800 border-solid border-l-0 border-r-0 border-t-0 border-b flex flex-wrap gap-1 p-2 items-center\">\n <Show when={items().undo}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Undo\"\n >\n <div class=\"i-lucide-undo-2 size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().redo}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Redo\"\n >\n <div class=\"i-lucide-redo-2 size-5 block\" />\n </Button>\n )}\n </Show>\n\n <Show when={items().bold}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Bold\"\n >\n <div class=\"i-lucide-bold size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().italic}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Italic\"\n >\n <div class=\"i-lucide-italic size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().underline}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Underline\"\n >\n <div class=\"i-lucide-underline size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().strike}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Strike\"\n >\n <div class=\"i-lucide-strikethrough size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().code}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Code\"\n >\n <div class=\"i-lucide-code size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().codeBlock}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Code Block\"\n >\n <div class=\"i-lucide-square-code size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().heading1}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Heading 1\"\n >\n <div class=\"i-lucide-heading-1 size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().heading2}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Heading 2\"\n >\n <div class=\"i-lucide-heading-2 size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().heading3}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Heading 3\"\n >\n <div class=\"i-lucide-heading-3 size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().horizontalRule}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Divider\"\n >\n <div class=\"i-lucide-minus size-5 block\"></div>\n </Button>\n )}\n </Show>\n <Show when={items().blockquote}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Blockquote\"\n >\n <div class=\"i-lucide-text-quote size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().bulletList}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Bullet List\"\n >\n <div class=\"i-lucide-list size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().orderedList}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Ordered List\"\n >\n <div class=\"i-lucide-list-ordered size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().taskList}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Task List\"\n >\n <div class=\"i-lucide-list-checks size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().toggleList}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Toggle List\"\n >\n <div class=\"i-lucide-list-collapse size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().indentList}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Increase indentation\"\n >\n <div class=\"i-lucide-indent-increase size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={items().dedentList}>\n {(item) => (\n <Button\n pressed={item().isActive}\n disabled={!item().canExec}\n onClick={item().command}\n tooltip=\"Decrease indentation\"\n >\n <div class=\"i-lucide-indent-decrease size-5 block\" />\n </Button>\n )}\n </Show>\n <Show when={props.uploader && items().insertImage}>\n {(item) => (\n <ImageUploadPopover\n uploader={props.uploader!}\n disabled={!item().canExec}\n tooltip=\"Insert Image\"\n >\n <div class=\"i-lucide-image size-5 block\" />\n </ImageUploadPopover>\n )}\n </Show>\n </div>\n )\n}\n"
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"meta": {
|
|
30
|
+
"hasIcons": true,
|
|
31
|
+
"hidden": false,
|
|
32
|
+
"story": "",
|
|
33
|
+
"framework": "solid",
|
|
34
|
+
"accumulatedFiles": [
|
|
35
|
+
"registry/src/solid/ui/button/button.tsx",
|
|
36
|
+
"registry/src/solid/ui/button/index.ts",
|
|
37
|
+
"registry/src/solid/ui/image-upload-popover/image-upload-popover.tsx",
|
|
38
|
+
"registry/src/solid/ui/image-upload-popover/index.ts",
|
|
39
|
+
"registry/src/solid/ui/toolbar/index.ts",
|
|
40
|
+
"registry/src/solid/ui/toolbar/toolbar.tsx"
|
|
41
|
+
],
|
|
42
|
+
"internalDependencies": [
|
|
43
|
+
"solid-ui-button",
|
|
44
|
+
"solid-ui-image-upload-popover"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
"css": {
|
|
48
|
+
"@plugin @egoist/tailwindcss-icons": {}
|
|
49
|
+
},
|
|
50
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json"
|
|
51
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "solid-ui-user-menu",
|
|
3
|
+
"title": "solid-ui-user-menu",
|
|
4
|
+
"type": "registry:component",
|
|
5
|
+
"description": "",
|
|
6
|
+
"registryDependencies": [],
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"prosekit"
|
|
9
|
+
],
|
|
10
|
+
"files": [
|
|
11
|
+
{
|
|
12
|
+
"path": "registry/src/solid/ui/user-menu/index.ts",
|
|
13
|
+
"type": "registry:component",
|
|
14
|
+
"target": "components/editor/ui/user-menu/index.ts",
|
|
15
|
+
"content": "export { default as UserMenu } from './user-menu'\n"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"path": "registry/src/solid/ui/user-menu/user-menu.tsx",
|
|
19
|
+
"type": "registry:component",
|
|
20
|
+
"target": "components/editor/ui/user-menu/user-menu.tsx",
|
|
21
|
+
"content": "import type { BasicExtension } from 'prosekit/basic'\nimport { canUseRegexLookbehind, type Union } from 'prosekit/core'\nimport type { MentionExtension } from 'prosekit/extensions/mention'\nimport { useEditor } from 'prosekit/solid'\nimport {\n AutocompleteEmpty,\n AutocompleteItem,\n AutocompletePopup,\n AutocompletePositioner,\n AutocompleteRoot,\n} from 'prosekit/solid/autocomplete'\nimport { For, type JSX } from 'solid-js'\n\n// Match inputs like \"@\", \"@foo\", \"@foo bar\" etc. Do not match \"@ foo\".\nconst regex = canUseRegexLookbehind() ? /(?<!\\S)@(\\S.*)?$/u : /@(\\S.*)?$/u\n\nexport default function UserMenu(props: {\n users: { id: number; name: string }[]\n loading?: boolean\n onQueryChange?: (query: string) => void\n onOpenChange?: (open: boolean) => void\n}): JSX.Element {\n const editor = useEditor<Union<[MentionExtension, BasicExtension]>>()\n\n const handleUserInsert = (id: number, username: string) => {\n editor().commands.insertMention({\n id: id.toString(),\n value: '@' + username,\n kind: 'user',\n })\n editor().commands.insertText({ text: ' ' })\n }\n\n return (\n <AutocompleteRoot\n regex={regex}\n onQueryChange={(event) => props.onQueryChange?.(event.detail)}\n onOpenChange={(event) => props.onOpenChange?.(event.detail)}\n >\n <AutocompletePositioner class=\"block overflow-visible bg-transparent w-min h-min z-50 motion-safe:ease-out motion-safe:transition-transform motion-safe:duration-100\">\n <AutocompletePopup class=\"box-border data-[state=closed]:motion-safe:duration-150 motion-safe:transition-discrete motion-safe:transition-all data-[state=closed]:opacity-0 starting:opacity-0 opacity-100 data-[state=closed]:scale-95 starting:scale-95 scale-100 motion-safe:duration-40 rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950 shadow-lg flex flex-col relative max-h-100 min-w-60 select-none overflow-auto whitespace-nowrap p-1\">\n <AutocompleteEmpty class=\"relative flex items-center justify-between min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\">\n {props.loading ? 'Loading...' : 'No results'}\n </AutocompleteEmpty>\n\n <For each={props.users}>\n {(user) => (\n <AutocompleteItem\n class=\"relative flex items-center justify-between min-w-32 scroll-my-1 rounded-sm px-3 py-1.5 box-border cursor-default select-none whitespace-nowrap outline-hidden data-highlighted:bg-gray-100 dark:data-highlighted:bg-gray-800\"\n onSelect={() => handleUserInsert(user.id, user.name)}\n >\n <span class={props.loading ? 'opacity-50' : undefined}>\n {user.name}\n </span>\n </AutocompleteItem>\n )}\n </For>\n </AutocompletePopup>\n </AutocompletePositioner>\n </AutocompleteRoot>\n )\n}\n"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"meta": {
|
|
25
|
+
"hasIcons": false,
|
|
26
|
+
"hidden": false,
|
|
27
|
+
"story": "",
|
|
28
|
+
"framework": "solid",
|
|
29
|
+
"accumulatedFiles": [
|
|
30
|
+
"registry/src/solid/ui/user-menu/index.ts",
|
|
31
|
+
"registry/src/solid/ui/user-menu/user-menu.tsx"
|
|
32
|
+
],
|
|
33
|
+
"internalDependencies": []
|
|
34
|
+
},
|
|
35
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json"
|
|
36
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "solid-ui-word-counter",
|
|
3
|
+
"title": "solid-ui-word-counter",
|
|
4
|
+
"type": "registry:component",
|
|
5
|
+
"description": "",
|
|
6
|
+
"registryDependencies": [],
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"prosekit"
|
|
9
|
+
],
|
|
10
|
+
"files": [
|
|
11
|
+
{
|
|
12
|
+
"path": "registry/src/solid/ui/word-counter/index.ts",
|
|
13
|
+
"type": "registry:component",
|
|
14
|
+
"target": "components/editor/ui/word-counter/index.ts",
|
|
15
|
+
"content": "export { default as WordCounter } from './word-counter'\n"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"path": "registry/src/solid/ui/word-counter/word-counter.tsx",
|
|
19
|
+
"type": "registry:component",
|
|
20
|
+
"target": "components/editor/ui/word-counter/word-counter.tsx",
|
|
21
|
+
"content": "import type { Editor } from 'prosekit/core'\nimport { useEditorDerivedValue } from 'prosekit/solid'\nimport type { JSX } from 'solid-js'\n\nfunction getWordCount(editor: Editor) {\n const doc = editor.state.doc\n const words = doc ? doc.textBetween(0, doc.content.size, ' ') : ''\n const wordCount = words.split(/\\s+/).filter((s) => s).length\n const characterCount = doc ? doc.textContent.length : 0\n return { wordCount, characterCount }\n}\n\nexport default function WordCounter(): JSX.Element {\n const counts = useEditorDerivedValue(getWordCount)\n\n return (\n <div class=\"p-4 text-center italic tabular-nums\">\n Word Count: {counts().wordCount}\n <br />\n Character Count: {counts().characterCount}\n </div>\n )\n}\n"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"meta": {
|
|
25
|
+
"hasIcons": false,
|
|
26
|
+
"hidden": false,
|
|
27
|
+
"story": "",
|
|
28
|
+
"framework": "solid",
|
|
29
|
+
"accumulatedFiles": [
|
|
30
|
+
"registry/src/solid/ui/word-counter/index.ts",
|
|
31
|
+
"registry/src/solid/ui/word-counter/word-counter.tsx"
|
|
32
|
+
],
|
|
33
|
+
"internalDependencies": []
|
|
34
|
+
},
|
|
35
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json"
|
|
36
|
+
}
|