@qkix/strapi-plugin-better-blocks 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +795 -0
  3. package/dist/_chunks/en-BcPniuRQ.js +1 -0
  4. package/dist/_chunks/en-DYxpcVy9.mjs +4 -0
  5. package/dist/admin/index.js +1933 -0
  6. package/dist/admin/index.mjs +17091 -0
  7. package/dist/admin/src/components/BlocksInput/Blocks/Audio.d.ts +6 -0
  8. package/dist/admin/src/components/BlocksInput/Blocks/AudioEditorModal.d.ts +21 -0
  9. package/dist/admin/src/components/BlocksInput/Blocks/Button.d.ts +11 -0
  10. package/dist/admin/src/components/BlocksInput/Blocks/ButtonEditorModal.d.ts +17 -0
  11. package/dist/admin/src/components/BlocksInput/Blocks/Callout.d.ts +21 -0
  12. package/dist/admin/src/components/BlocksInput/Blocks/Code.d.ts +18 -0
  13. package/dist/admin/src/components/BlocksInput/Blocks/Details.d.ts +12 -0
  14. package/dist/admin/src/components/BlocksInput/Blocks/Diagram.d.ts +15 -0
  15. package/dist/admin/src/components/BlocksInput/Blocks/Embed.d.ts +22 -0
  16. package/dist/admin/src/components/BlocksInput/Blocks/EmbedEditorModal.d.ts +27 -0
  17. package/dist/admin/src/components/BlocksInput/Blocks/Heading.d.ts +14 -0
  18. package/dist/admin/src/components/BlocksInput/Blocks/HorizontalLine.d.ts +10 -0
  19. package/dist/admin/src/components/BlocksInput/Blocks/Image.d.ts +5 -0
  20. package/dist/admin/src/components/BlocksInput/Blocks/Link.d.ts +3 -0
  21. package/dist/admin/src/components/BlocksInput/Blocks/List.d.ts +3 -0
  22. package/dist/admin/src/components/BlocksInput/Blocks/Math.d.ts +17 -0
  23. package/dist/admin/src/components/BlocksInput/Blocks/MediaEmbed.d.ts +7 -0
  24. package/dist/admin/src/components/BlocksInput/Blocks/Paragraph.d.ts +3 -0
  25. package/dist/admin/src/components/BlocksInput/Blocks/Quote.d.ts +3 -0
  26. package/dist/admin/src/components/BlocksInput/Blocks/SocialEmbed.d.ts +8 -0
  27. package/dist/admin/src/components/BlocksInput/Blocks/SocialEmbedEditorModal.d.ts +41 -0
  28. package/dist/admin/src/components/BlocksInput/Blocks/SourceEditorModal.d.ts +19 -0
  29. package/dist/admin/src/components/BlocksInput/Blocks/Table.d.ts +14 -0
  30. package/dist/admin/src/components/BlocksInput/Blocks/TableGridPicker.d.ts +20 -0
  31. package/dist/admin/src/components/BlocksInput/Blocks/TableIcons.d.ts +31 -0
  32. package/dist/admin/src/components/BlocksInput/Blocks/TableToolbar.d.ts +14 -0
  33. package/dist/admin/src/components/BlocksInput/Blocks/Video.d.ts +6 -0
  34. package/dist/admin/src/components/BlocksInput/Blocks/VideoEditorModal.d.ts +29 -0
  35. package/dist/admin/src/components/BlocksInput/Blocks/embedProviders.d.ts +43 -0
  36. package/dist/admin/src/components/BlocksInput/Blocks/muxClient.d.ts +40 -0
  37. package/dist/admin/src/components/BlocksInput/Blocks/socialFrame.d.ts +13 -0
  38. package/dist/admin/src/components/BlocksInput/Blocks/tableGrid.d.ts +90 -0
  39. package/dist/admin/src/components/BlocksInput/Blocks/tableOperations.d.ts +124 -0
  40. package/dist/admin/src/components/BlocksInput/Blocks/videoProviders.d.ts +37 -0
  41. package/dist/admin/src/components/BlocksInput/BlocksContent.d.ts +7 -0
  42. package/dist/admin/src/components/BlocksInput/BlocksEditor.d.ts +71 -0
  43. package/dist/admin/src/components/BlocksInput/BlocksToolbar.d.ts +27 -0
  44. package/dist/admin/src/components/BlocksInput/EditorLayout.d.ts +10 -0
  45. package/dist/admin/src/components/BlocksInput/EmojiPicker.d.ts +5 -0
  46. package/dist/admin/src/components/BlocksInput/FindReplace.d.ts +11 -0
  47. package/dist/admin/src/components/BlocksInput/FloatingSelectionToolbar.d.ts +11 -0
  48. package/dist/admin/src/components/BlocksInput/FontModifiersIcons.d.ts +32 -0
  49. package/dist/admin/src/components/BlocksInput/InlineColorPicker.d.ts +3 -0
  50. package/dist/admin/src/components/BlocksInput/MenuScrollbar.d.ts +30 -0
  51. package/dist/admin/src/components/BlocksInput/Modifiers.d.ts +16 -0
  52. package/dist/admin/src/components/BlocksInput/SlashCommands.d.ts +3 -0
  53. package/dist/admin/src/components/BlocksInput/SpecialCharPicker.d.ts +5 -0
  54. package/dist/admin/src/components/BlocksInput/WordCount.d.ts +3 -0
  55. package/dist/admin/src/components/BlocksInput/plugins/withAutoTransform.d.ts +3 -0
  56. package/dist/admin/src/components/BlocksInput/plugins/withLinks.d.ts +8 -0
  57. package/dist/admin/src/components/BlocksInput/plugins/withMarkdownPaste.d.ts +3 -0
  58. package/dist/admin/src/components/BlocksInput/plugins/withStrapiSchema.d.ts +6 -0
  59. package/dist/admin/src/components/BlocksInput/utils/constants.d.ts +13 -0
  60. package/dist/admin/src/components/BlocksInput/utils/conversions.d.ts +14 -0
  61. package/dist/admin/src/components/BlocksInput/utils/enterKey.d.ts +6 -0
  62. package/dist/admin/src/components/BlocksInput/utils/links.d.ts +12 -0
  63. package/dist/admin/src/components/BlocksInput/utils/optionsDefaults.d.ts +28 -0
  64. package/dist/admin/src/components/BlocksInput/utils/optionsParser.d.ts +34 -0
  65. package/dist/admin/src/components/BlocksInput/utils/parseMarkdownToSlate.d.ts +2 -0
  66. package/dist/admin/src/components/BlocksInput/utils/prefixFileUrlWithBackendUrl.d.ts +8 -0
  67. package/dist/admin/src/components/BlocksInput/utils/shiki.d.ts +29 -0
  68. package/dist/admin/src/components/BlocksInput/utils/shortcuts.d.ts +25 -0
  69. package/dist/admin/src/components/BlocksInput/utils/types.d.ts +404 -0
  70. package/dist/admin/src/components/Initializer.d.ts +5 -0
  71. package/dist/admin/src/components/Input.d.ts +45 -0
  72. package/dist/admin/src/components/PluginIcon.d.ts +3 -0
  73. package/dist/admin/src/hooks/useDragAndDrop.d.ts +51 -0
  74. package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +14 -0
  75. package/dist/admin/src/index.d.ts +10 -0
  76. package/dist/admin/src/pages/App.d.ts +3 -0
  77. package/dist/admin/src/pages/HomePage.d.ts +3 -0
  78. package/dist/admin/src/pluginId.d.ts +1 -0
  79. package/dist/admin/src/utils/getTranslation.d.ts +2 -0
  80. package/dist/server/index.js +1 -0
  81. package/dist/server/index.mjs +393 -0
  82. package/dist/server/src/bootstrap.d.ts +5 -0
  83. package/dist/server/src/config/index.d.ts +94 -0
  84. package/dist/server/src/content-types/index.d.ts +2 -0
  85. package/dist/server/src/controllers/controller.d.ts +12 -0
  86. package/dist/server/src/controllers/index.d.ts +14 -0
  87. package/dist/server/src/controllers/oembed.d.ts +12 -0
  88. package/dist/server/src/destroy.d.ts +5 -0
  89. package/dist/server/src/index.d.ts +125 -0
  90. package/dist/server/src/middlewares/index.d.ts +2 -0
  91. package/dist/server/src/policies/index.d.ts +2 -0
  92. package/dist/server/src/register.d.ts +5 -0
  93. package/dist/server/src/routes/admin.d.ts +9 -0
  94. package/dist/server/src/routes/content-api.d.ts +9 -0
  95. package/dist/server/src/routes/index.d.ts +25 -0
  96. package/dist/server/src/services/index.d.ts +14 -0
  97. package/dist/server/src/services/oembed.d.ts +27 -0
  98. package/dist/server/src/services/service.d.ts +7 -0
  99. package/package.json +131 -0
@@ -0,0 +1,6 @@
1
+ import { Editor } from 'slate';
2
+ import { type BlocksStore } from '../BlocksEditor';
3
+ declare const insertAudio: (editor: Editor) => void;
4
+ declare const withAudio: (editor: Editor) => Editor;
5
+ declare const audioBlocks: Pick<BlocksStore, 'audio'>;
6
+ export { audioBlocks, withAudio, insertAudio };
@@ -0,0 +1,21 @@
1
+ import * as React from 'react';
2
+ import { type AudioAlignment, type AudioElement, type AudioPlayerSettings } from '../utils/types';
3
+ /** Human-readable file size. Strapi stores media size in KB (float). */
4
+ export declare const formatBytes: (bytes?: number) => string;
5
+ export declare const DEFAULT_PLAYER: AudioPlayerSettings;
6
+ export interface AudioDraft {
7
+ file: AudioElement['file'];
8
+ title?: string;
9
+ caption?: string;
10
+ player: AudioPlayerSettings;
11
+ alignment: AudioAlignment;
12
+ }
13
+ interface AudioEditorModalProps {
14
+ open: boolean;
15
+ element: AudioElement;
16
+ onSave: (draft: AudioDraft) => void;
17
+ onRemove: () => void;
18
+ onClose: () => void;
19
+ }
20
+ export declare const AudioEditorModal: ({ open, element, onSave, onRemove, onClose, }: AudioEditorModalProps) => React.JSX.Element;
21
+ export default AudioEditorModal;
@@ -0,0 +1,11 @@
1
+ import * as React from 'react';
2
+ import { Editor } from 'slate';
3
+ import { type BlocksStore } from '../BlocksEditor';
4
+ interface ButtonIconProps extends React.SVGProps<SVGSVGElement> {
5
+ fill?: string;
6
+ }
7
+ declare const ButtonIcon: ({ fill, ...rest }: ButtonIconProps) => React.JSX.Element;
8
+ declare const insertButton: (editor: Editor) => void;
9
+ declare const withButtons: (editor: Editor) => Editor;
10
+ declare const buttonBlocks: Pick<BlocksStore, 'button'>;
11
+ export { buttonBlocks, withButtons, insertButton, ButtonIcon };
@@ -0,0 +1,17 @@
1
+ import * as React from 'react';
2
+ import { type ButtonElement, type ButtonPresets } from '../utils/types';
3
+ /** Bytes → human readable, e.g. 5242880 → "5 MB". */
4
+ export declare const formatFileSize: (bytes?: number) => string;
5
+ /** File extension (with or without dot) → emoji icon. */
6
+ export declare const getFileIcon: (ext?: string) => string;
7
+ interface ButtonEditorModalProps {
8
+ open: boolean;
9
+ element: ButtonElement;
10
+ /** Per-project preset overrides (merged over the built-in presets). */
11
+ presets?: ButtonPresets;
12
+ onSave: (patch: Partial<ButtonElement>) => void;
13
+ onRemove: () => void;
14
+ onClose: () => void;
15
+ }
16
+ declare const ButtonEditorModal: ({ open, element, presets, onSave, onRemove, onClose, }: ButtonEditorModalProps) => React.JSX.Element;
17
+ export { ButtonEditorModal };
@@ -0,0 +1,21 @@
1
+ import * as React from 'react';
2
+ import { type MessageDescriptor } from 'react-intl';
3
+ import { Editor } from 'slate';
4
+ import { type BlocksStore } from '../BlocksEditor';
5
+ import { type CalloutVariant } from '../utils/types';
6
+ interface VariantMeta {
7
+ icon: React.ComponentType<any>;
8
+ /** Strapi color family; we use `${family}600` (accent) and `${family}100` (tint) */
9
+ family: 'secondary' | 'success' | 'alternative' | 'warning' | 'danger';
10
+ label: MessageDescriptor;
11
+ }
12
+ declare const VARIANTS: Record<CalloutVariant, VariantMeta>;
13
+ declare const VARIANT_ORDER: CalloutVariant[];
14
+ /**
15
+ * Wrap the current top-level block in a callout of the given variant.
16
+ * Normalization guarantees the callout ends up with at least one block child.
17
+ */
18
+ declare const insertCallout: (editor: Editor, variant?: CalloutVariant) => void;
19
+ declare const withCallout: (editor: Editor) => Editor;
20
+ declare const calloutBlocks: Pick<BlocksStore, 'callout'>;
21
+ export { calloutBlocks, withCallout, insertCallout, VARIANTS, VARIANT_ORDER };
@@ -0,0 +1,18 @@
1
+ import { BaseRange, Editor, NodeEntry } from 'slate';
2
+ import { type BlocksStore } from '../BlocksEditor';
3
+ type BaseRangeCustom = BaseRange & {
4
+ color: string;
5
+ };
6
+ /**
7
+ * Syntax highlighting via Shiki.
8
+ *
9
+ * Returns a factory so the editor can pass in its current `editor` (to resolve
10
+ * the parent code element + language) and `isDark` (to pick the matching Shiki
11
+ * theme). Decoration runs on the code block's text node, mapping each Shiki
12
+ * token to a Slate range carrying a `color`, which `renderLeaf` turns into an
13
+ * inline style. Shiki loads asynchronously: until it (and the requested
14
+ * grammar) are ready, this returns no ranges and a subscriber re-decorates.
15
+ */
16
+ export declare const decorateCode: (editor: Editor, isDark: boolean) => ([node, path]: NodeEntry) => BaseRangeCustom[];
17
+ declare const codeBlocks: Pick<BlocksStore, 'code'>;
18
+ export { codeBlocks };
@@ -0,0 +1,12 @@
1
+ import { Editor } from 'slate';
2
+ import { type BlocksStore } from '../BlocksEditor';
3
+ declare const DEFAULT_SUMMARY = "Click to expand";
4
+ /**
5
+ * Wrap the current block in a collapsible details section. Nesting is allowed,
6
+ * so we wrap any block that is a direct child of the editor or of another
7
+ * details node. Normalization guarantees at least one block child.
8
+ */
9
+ declare const insertDetails: (editor: Editor, summary?: string) => void;
10
+ declare const withDetails: (editor: Editor) => Editor;
11
+ declare const detailsBlocks: Pick<BlocksStore, 'details'>;
12
+ export { detailsBlocks, withDetails, insertDetails, DEFAULT_SUMMARY };
@@ -0,0 +1,15 @@
1
+ import * as React from 'react';
2
+ import { Editor } from 'slate';
3
+ import { type BlocksStore } from '../BlocksEditor';
4
+ interface DiagramIconProps extends React.SVGProps<SVGSVGElement> {
5
+ fill?: string;
6
+ }
7
+ declare const DiagramIcon: ({ fill, ...rest }: DiagramIconProps) => React.JSX.Element;
8
+ /**
9
+ * Convert the currently selected block into a (block) diagram node.
10
+ * Re-inserts a clean node so no stale text is left in the void's children.
11
+ */
12
+ declare const setBlockDiagram: (editor: Editor) => void;
13
+ declare const withDiagram: (editor: Editor) => Editor;
14
+ declare const diagramBlocks: Pick<BlocksStore, 'diagram'>;
15
+ export { diagramBlocks, withDiagram, setBlockDiagram, DiagramIcon };
@@ -0,0 +1,22 @@
1
+ import { Editor } from 'slate';
2
+ import { type BlocksStore } from '../BlocksEditor';
3
+ import { type EmbedElement } from '../utils/types';
4
+ import { isEmbeddableUrl } from './embedProviders';
5
+ /**
6
+ * Insert a blank embed. With no `embedHtml` the block opens its editor on
7
+ * mount, so the author lands straight in the URL field.
8
+ */
9
+ declare const insertEmbed: (editor: Editor, initial?: Partial<EmbedElement>) => void;
10
+ /**
11
+ * Insert a ready-to-render embed straight from a share URL — used by the
12
+ * toolbar's media button, which takes the URL up front and so can skip the
13
+ * modal entirely. Returns false when the URL isn't one we can embed.
14
+ *
15
+ * Unlike `insertEmbed`, this *appends* a node instead of converting the block
16
+ * at the selection: the toolbar button can be pressed with any block selected,
17
+ * and converting would silently destroy it.
18
+ */
19
+ declare const insertEmbedFromUrl: (editor: Editor, url: string) => boolean;
20
+ declare const withEmbed: (editor: Editor) => Editor;
21
+ declare const embedBlocks: Pick<BlocksStore, 'embed'>;
22
+ export { embedBlocks, withEmbed, insertEmbed, insertEmbedFromUrl, isEmbeddableUrl, };
@@ -0,0 +1,27 @@
1
+ import * as React from 'react';
2
+ import { type AspectRatio, type EmbedElement, type EmbedProvider, type MediaAlignment } from '../utils/types';
3
+ import { isEmbeddableUrl } from './embedProviders';
4
+ export interface EmbedDraft {
5
+ source: 'url' | 'iframe';
6
+ url?: string;
7
+ iframe?: string;
8
+ embedHtml?: string;
9
+ embedSrc?: string;
10
+ provider?: EmbedProvider;
11
+ thumbnail?: string;
12
+ aspectRatio: AspectRatio;
13
+ customAspectRatio?: string;
14
+ alignment: MediaAlignment;
15
+ caption?: string;
16
+ title?: string;
17
+ }
18
+ interface EmbedEditorModalProps {
19
+ open: boolean;
20
+ element: EmbedElement;
21
+ onSave: (draft: EmbedDraft) => void;
22
+ onRemove: () => void;
23
+ onClose: () => void;
24
+ }
25
+ export declare const EmbedEditorModal: ({ open, element, onSave, onRemove, onClose, }: EmbedEditorModalProps) => React.JSX.Element;
26
+ export { isEmbeddableUrl };
27
+ export default EmbedEditorModal;
@@ -0,0 +1,14 @@
1
+ import { type BlocksStore } from '../BlocksEditor';
2
+ /**
3
+ * Type scale used to preview each block type inside the block-type dropdown.
4
+ *
5
+ * Deliberately a compressed version of the editor sizes above (4.2rem down to
6
+ * 1.6rem): the point is to convey the hierarchy at a glance, and a literal 4.2rem
7
+ * H1 would turn the menu into a scroll container.
8
+ */
9
+ declare const BLOCK_PREVIEW_TYPOGRAPHY: Record<string, {
10
+ fontSize: string;
11
+ fontWeight: number;
12
+ }>;
13
+ declare const headingBlocks: Pick<BlocksStore, 'heading-one' | 'heading-two' | 'heading-three' | 'heading-four' | 'heading-five' | 'heading-six'>;
14
+ export { headingBlocks, BLOCK_PREVIEW_TYPOGRAPHY };
@@ -0,0 +1,10 @@
1
+ import { Editor } from 'slate';
2
+ import { type BlocksStore } from '../BlocksEditor';
3
+ declare const withHorizontalLine: (editor: Editor) => Editor;
4
+ /**
5
+ * Insert a horizontal line block after the current selection,
6
+ * followed by an empty paragraph so the user can keep typing.
7
+ */
8
+ declare const insertHorizontalLine: (editor: Editor) => void;
9
+ declare const horizontalLineBlocks: Pick<BlocksStore, 'horizontal-line'>;
10
+ export { horizontalLineBlocks, withHorizontalLine, insertHorizontalLine };
@@ -0,0 +1,5 @@
1
+ import { Editor } from 'slate';
2
+ import { type BlocksStore } from '../BlocksEditor';
3
+ declare const withImages: (editor: Editor) => Editor;
4
+ declare const imageBlocks: Pick<BlocksStore, 'image'>;
5
+ export { imageBlocks, withImages };
@@ -0,0 +1,3 @@
1
+ import { type BlocksStore } from '../BlocksEditor';
2
+ declare const linkBlocks: Pick<BlocksStore, 'link'>;
3
+ export { linkBlocks };
@@ -0,0 +1,3 @@
1
+ import { type BlocksStore } from '../BlocksEditor';
2
+ declare const listBlocks: Pick<BlocksStore, 'list-ordered' | 'list-unordered' | 'list-todo' | 'list-item'>;
3
+ export { listBlocks };
@@ -0,0 +1,17 @@
1
+ import * as React from 'react';
2
+ import { Editor } from 'slate';
3
+ import { type BlocksStore } from '../BlocksEditor';
4
+ import 'katex/dist/katex.min.css';
5
+ interface MathIconProps extends React.SVGProps<SVGSVGElement> {
6
+ fill?: string;
7
+ }
8
+ declare const MathIcon: ({ fill, ...rest }: MathIconProps) => React.JSX.Element;
9
+ declare const insertInlineMath: (editor: Editor, value?: string) => void;
10
+ /**
11
+ * Convert the currently selected block into a (block) math node.
12
+ * Re-inserts a clean node so no stale text is left in the void's children.
13
+ */
14
+ declare const setBlockMath: (editor: Editor) => void;
15
+ declare const withMath: (editor: Editor) => Editor;
16
+ declare const mathBlocks: Pick<BlocksStore, 'math'>;
17
+ export { mathBlocks, withMath, insertInlineMath, setBlockMath, MathIcon };
@@ -0,0 +1,7 @@
1
+ import { Editor } from 'slate';
2
+ import { type BlocksStore } from '../BlocksEditor';
3
+ declare const isMediaUrl: (url: string) => boolean;
4
+ declare const insertMediaEmbed: (editor: Editor, url: string) => void;
5
+ declare const withMediaEmbed: (editor: Editor) => Editor;
6
+ declare const mediaEmbedBlocks: Pick<BlocksStore, 'media-embed'>;
7
+ export { mediaEmbedBlocks, withMediaEmbed, insertMediaEmbed, isMediaUrl };
@@ -0,0 +1,3 @@
1
+ import { type BlocksStore } from '../BlocksEditor';
2
+ declare const paragraphBlocks: Pick<BlocksStore, 'paragraph'>;
3
+ export { paragraphBlocks };
@@ -0,0 +1,3 @@
1
+ import { type BlocksStore } from '../BlocksEditor';
2
+ declare const quoteBlocks: Pick<BlocksStore, 'quote'>;
3
+ export { quoteBlocks };
@@ -0,0 +1,8 @@
1
+ import * as React from 'react';
2
+ import { Editor } from 'slate';
3
+ import { type BlocksStore } from '../BlocksEditor';
4
+ declare const SocialIcon: (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
5
+ declare const insertSocialEmbed: (editor: Editor) => void;
6
+ declare const withSocialEmbed: (editor: Editor) => Editor;
7
+ declare const socialEmbedBlocks: Pick<BlocksStore, 'social-embed'>;
8
+ export { socialEmbedBlocks, withSocialEmbed, insertSocialEmbed, SocialIcon };
@@ -0,0 +1,41 @@
1
+ import * as React from 'react';
2
+ import { type SocialAlignment, type SocialEmbedElement, type SocialOEmbed, type SocialPlatform } from '../utils/types';
3
+ export interface PlatformMeta {
4
+ label: string;
5
+ icon: string;
6
+ color: string;
7
+ }
8
+ export declare const PLATFORM_META: Record<SocialPlatform, PlatformMeta>;
9
+ export declare const ALL_PLATFORMS: SocialPlatform[];
10
+ /** Detect the platform from a pasted URL (mirrors the server-side detection). */
11
+ export declare const detectPlatform: (url: string) => SocialPlatform | null;
12
+ /**
13
+ * Widget scripts pasted along with an embed snippet are inert once injected via
14
+ * `innerHTML`, and their leftover tags make renderers think the widget is
15
+ * already loaded. Renderers load those scripts themselves, so keep markup only.
16
+ */
17
+ export declare const stripScripts: (html: string) => string;
18
+ /**
19
+ * Pull the canonical post URL out of a pasted embed snippet, so an embed-code-only
20
+ * embed still carries a link for fallbacks and analytics. Covers Instagram's
21
+ * `data-instgrm-permalink`, blockquote `cite`, and iframe `src`.
22
+ */
23
+ export declare const extractUrlFromEmbedCode: (code: string) => string | null;
24
+ export interface SocialEmbedDraft {
25
+ platform: SocialPlatform;
26
+ url: string;
27
+ embedCode?: string;
28
+ oembed?: SocialOEmbed;
29
+ alignment: SocialAlignment;
30
+ caption?: string;
31
+ }
32
+ interface SocialEmbedEditorModalProps {
33
+ open: boolean;
34
+ element: SocialEmbedElement;
35
+ enabledPlatforms?: SocialPlatform[];
36
+ onSave: (patch: SocialEmbedDraft) => void;
37
+ onRemove: () => void;
38
+ onClose: () => void;
39
+ }
40
+ export declare const SocialEmbedEditorModal: ({ open, element, enabledPlatforms, onSave, onRemove, onClose, }: SocialEmbedEditorModalProps) => React.JSX.Element;
41
+ export default SocialEmbedEditorModal;
@@ -0,0 +1,19 @@
1
+ import * as React from 'react';
2
+ interface SourceEditorModalProps {
3
+ open: boolean;
4
+ /** Modal heading, e.g. "Edit Mermaid diagram". */
5
+ title: string;
6
+ /** Label shown above the source textarea, e.g. "Mermaid". */
7
+ label: string;
8
+ placeholder?: string;
9
+ /** The committed source value (used to detect the initial empty state). */
10
+ source: string;
11
+ onSourceChange: (value: string) => void;
12
+ /** Renders the live preview for the current (uncommitted) source. */
13
+ renderPreview: (source: string) => React.ReactNode;
14
+ onSave: () => void;
15
+ onRemove: () => void;
16
+ onClose: () => void;
17
+ }
18
+ declare const SourceEditorModal: ({ open, title, label, placeholder, source, onSourceChange, renderPreview, onSave, onRemove, onClose, }: SourceEditorModalProps) => React.JSX.Element;
19
+ export { SourceEditorModal };
@@ -0,0 +1,14 @@
1
+ import { Editor } from 'slate';
2
+ import { type BlocksStore } from '../BlocksEditor';
3
+ import { createTableCell, createTableRow, insertTable } from './tableOperations';
4
+ /**
5
+ * Protects the table's shape from Slate's generic editing behaviours (deleting
6
+ * across cells, normalizing rows away, converting a cell to a paragraph, …).
7
+ *
8
+ * Structural edits are performed by tableOperations, which lifts the guard via
9
+ * `allowTableEdit`. Inline editing inside a cell — marks, links, inline math —
10
+ * is deliberately untouched, so cells keep full rich-text parity.
11
+ */
12
+ declare const withTables: (editor: Editor) => Editor;
13
+ declare const tableBlocks: Pick<BlocksStore, 'table' | 'table-row' | 'table-cell' | 'table-header-cell'>;
14
+ export { tableBlocks, withTables, insertTable, createTableCell, createTableRow, };
@@ -0,0 +1,20 @@
1
+ import * as React from 'react';
2
+ /** Size of the hover grid. Larger tables go through the custom-size inputs. */
3
+ declare const GRID_ROWS = 10;
4
+ declare const GRID_COLS = 10;
5
+ /** Upper bound for the custom-size inputs — a guard against typos, not a limit
6
+ * anyone should hit in practice. */
7
+ declare const MAX_DIMENSION = 50;
8
+ interface TableGridPickerProps {
9
+ /** Called with a 1-based row/column count once the author commits a size. */
10
+ onSelect: (rows: number, cols: number) => void;
11
+ }
12
+ /**
13
+ * Notion/Word-style table size picker: hover (or arrow-key) across a 10x10 grid
14
+ * to pick the dimensions, with a custom-size fallback for anything bigger.
15
+ *
16
+ * The grid is plain divs in a CSS grid rather than SVG or a canvas, so it
17
+ * paints instantly and stays keyboard navigable for free.
18
+ */
19
+ declare const TableGridPicker: ({ onSelect }: TableGridPickerProps) => React.JSX.Element;
20
+ export { TableGridPicker, GRID_ROWS, GRID_COLS, MAX_DIMENSION };
@@ -0,0 +1,31 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Icons for the table contextual toolbar.
4
+ *
5
+ * They all share one visual language: a 3x3 table frame with the row or column
6
+ * the action targets picked out by a tinted band, plus a `+` or `x` marker for
7
+ * insert vs delete. That makes "insert row above" readable at a glance instead
8
+ * of relying on the tooltip.
9
+ *
10
+ * `fill` follows the same convention as FontModifiersIcons: a theme color token
11
+ * (e.g. "neutral600"), falling back to a raw CSS color.
12
+ */
13
+ interface TableIconProps {
14
+ fill?: string;
15
+ }
16
+ export declare const InsertRowAboveIcon: ({ fill }: TableIconProps) => React.JSX.Element;
17
+ export declare const InsertRowBelowIcon: ({ fill }: TableIconProps) => React.JSX.Element;
18
+ export declare const InsertColumnLeftIcon: ({ fill }: TableIconProps) => React.JSX.Element;
19
+ export declare const InsertColumnRightIcon: ({ fill }: TableIconProps) => React.JSX.Element;
20
+ export declare const DeleteRowIcon: ({ fill }: TableIconProps) => React.JSX.Element;
21
+ export declare const DeleteColumnIcon: ({ fill }: TableIconProps) => React.JSX.Element;
22
+ /** Table frame with a solid top row — the "toggle header row" affordance. */
23
+ export declare const HeaderRowIcon: ({ fill }: TableIconProps) => React.JSX.Element;
24
+ /**
25
+ * Merge: the top-left 2x2 block reads as one tinted cell, with arrows pointing
26
+ * inward to say "these become one".
27
+ */
28
+ export declare const MergeCellsIcon: ({ fill }: TableIconProps) => React.JSX.Element;
29
+ /** Split: one cell with a dashed divider appearing down the middle. */
30
+ export declare const SplitCellIcon: ({ fill }: TableIconProps) => React.JSX.Element;
31
+ export {};
@@ -0,0 +1,14 @@
1
+ import * as React from 'react';
2
+ import { type TableLocation } from './tableOperations';
3
+ interface TableToolbarProps {
4
+ location: TableLocation;
5
+ disabled: boolean;
6
+ }
7
+ /**
8
+ * Contextual toolbar that floats above a table while the caret is inside it.
9
+ *
10
+ * Every row/column action is directional and anchored on the focused cell —
11
+ * "insert row above" means above *this* row, not at the end of the table.
12
+ */
13
+ declare const TableToolbar: ({ location, disabled }: TableToolbarProps) => React.JSX.Element;
14
+ export { TableToolbar };
@@ -0,0 +1,6 @@
1
+ import { Editor } from 'slate';
2
+ import { type BlocksStore } from '../BlocksEditor';
3
+ declare const insertVideo: (editor: Editor) => void;
4
+ declare const withVideo: (editor: Editor) => Editor;
5
+ declare const videoBlocks: Pick<BlocksStore, 'video'>;
6
+ export { videoBlocks, withVideo, insertVideo };
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ import { type AspectRatio, type MediaAlignment, type VideoElement, type VideoPlayerSettings, type VideoProvider } from '../utils/types';
3
+ /** Human-readable file size. Strapi stores media size in KB (float). */
4
+ export declare const formatBytes: (bytes?: number) => string;
5
+ export declare const DEFAULT_VIDEO_PLAYER: VideoPlayerSettings;
6
+ export interface VideoDraft {
7
+ provider: VideoProvider;
8
+ assetId?: string;
9
+ playbackId?: string;
10
+ url: string;
11
+ file?: VideoElement['file'];
12
+ poster?: string;
13
+ title?: string;
14
+ caption?: string;
15
+ transcript?: string;
16
+ player: VideoPlayerSettings;
17
+ alignment: MediaAlignment;
18
+ aspectRatio: AspectRatio;
19
+ customAspectRatio?: string;
20
+ }
21
+ interface VideoEditorModalProps {
22
+ open: boolean;
23
+ element: VideoElement;
24
+ onSave: (draft: VideoDraft) => void;
25
+ onRemove: () => void;
26
+ onClose: () => void;
27
+ }
28
+ export declare const VideoEditorModal: ({ open, element, onSave, onRemove, onClose, }: VideoEditorModalProps) => React.JSX.Element;
29
+ export default VideoEditorModal;
@@ -0,0 +1,43 @@
1
+ import { type AspectRatio, type EmbedProvider } from '../utils/types';
2
+ /** Hosts an app must allow in `frame-src` for URL-based embeds to render. */
3
+ export declare const EMBED_FRAME_HOSTS: string[];
4
+ /** Human-readable provider name for a URL, e.g. "YouTube". */
5
+ export declare const getProviderLabel: (provider?: EmbedProvider) => string;
6
+ /** Detected provider for a share URL, or `generic` when unrecognised. */
7
+ export declare const detectProvider: (url: string) => EmbedProvider;
8
+ /** Iframe `src` derived from a share URL, or null when not derivable. */
9
+ export declare const getEmbedSrc: (url: string) => string | null;
10
+ /** Poster image derived from a share URL, when the provider exposes one. */
11
+ export declare const getThumbnail: (url: string) => string | null;
12
+ /** True when the URL is one this block can turn into an embed by itself. */
13
+ export declare const isEmbeddableUrl: (url: string) => boolean;
14
+ export interface SanitizedIframe {
15
+ /** Discriminant against `IframeError`; never set on success. */
16
+ error?: undefined;
17
+ /** Rebuilt, safe-to-store iframe markup. */
18
+ html: string;
19
+ /** The iframe's `src`, hoisted for preview/validation. */
20
+ src: string;
21
+ width?: string;
22
+ height?: string;
23
+ }
24
+ export interface IframeError {
25
+ html?: undefined;
26
+ error: 'no-iframe' | 'no-src' | 'insecure-src';
27
+ }
28
+ /**
29
+ * Parse a pasted embed snippet and rebuild a single safe `<iframe>` from it.
30
+ * Returns an error code instead of throwing so the modal can explain what's
31
+ * wrong with the paste.
32
+ */
33
+ export declare const sanitizeIframe: (input: string) => SanitizedIframe | IframeError;
34
+ /**
35
+ * Build the iframe markup for a recognised share URL. Returns null when the URL
36
+ * isn't one of the known providers — the author then has to use embed-code mode.
37
+ */
38
+ export declare const buildUrlEmbed: (url: string, title?: string) => SanitizedIframe | null;
39
+ export declare const ASPECT_RATIOS: AspectRatio[];
40
+ /** `"16:9"` → `"16 / 9"`, the value the CSS `aspect-ratio` property expects. */
41
+ export declare const toCssAspectRatio: (ratio?: string) => string;
42
+ /** Best-effort ratio from a pasted iframe's width/height attributes. */
43
+ export declare const inferAspectRatio: (width?: string, height?: string) => AspectRatio | null;
@@ -0,0 +1,40 @@
1
+ export declare const MUX_PLUGIN_ID = "mux-video-uploader";
2
+ /** Subset of `plugin::mux-video-uploader.mux-asset` this block consumes. */
3
+ export interface MuxAsset {
4
+ documentId: string;
5
+ title: string;
6
+ asset_id?: string;
7
+ playback_id?: string;
8
+ /** True when the asset uses a signed playback policy. */
9
+ signed: boolean;
10
+ isReady: boolean;
11
+ duration?: number;
12
+ /** Mux reports this as e.g. "16:9". */
13
+ aspect_ratio?: string;
14
+ }
15
+ /**
16
+ * Thumbnails go through the plugin's own proxy rather than image.mux.com
17
+ * directly: the route is unauthenticated and exists precisely because the
18
+ * Strapi admin CSP blocks the Mux image host.
19
+ */
20
+ export declare const muxThumbnailProxyUrl: (playbackId: string) => string;
21
+ export interface UseMuxAssetsResult {
22
+ /** null while still probing for the plugin. */
23
+ available: boolean | null;
24
+ assets: MuxAsset[];
25
+ totalCount: number;
26
+ loading: boolean;
27
+ error: string | null;
28
+ search: (query: string) => void;
29
+ query: string;
30
+ }
31
+ /**
32
+ * List Mux assets, with title search. Returns `available: false` when the Mux
33
+ * plugin isn't installed or can't be queried, so callers can hide their UI.
34
+ *
35
+ * Availability is decided by the asset-list call itself rather than the
36
+ * plugin's `mux-settings` route: that route reports "configured" only when a
37
+ * *webhook signing secret* is also set, which listing assets does not need — so
38
+ * it answers false for perfectly usable installs.
39
+ */
40
+ export declare const useMuxAssets: (enabled: boolean) => UseMuxAssetsResult;
@@ -0,0 +1,13 @@
1
+ import { type SocialEmbedElement, type SocialPlatform } from '../utils/types';
2
+ export interface SocialFrame {
3
+ src: string;
4
+ /** Fixed height in px: these frames don't post their size to the parent. */
5
+ height: number;
6
+ }
7
+ /** Hosts an app must allow in `frame-src` for live previews to render. */
8
+ export declare const SOCIAL_FRAME_HOSTS: Record<SocialPlatform, string>;
9
+ /**
10
+ * Build the URL of a script-free preview frame for a social-embed node, or null
11
+ * when the post can't be identified (then the editor keeps showing the card).
12
+ */
13
+ export declare const getSocialFrame: (element: Pick<SocialEmbedElement, 'platform' | 'url' | 'embedCode' | 'oembed'>) => SocialFrame | null;