@withwiz/block-editor 0.1.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 (40) hide show
  1. package/README.md +219 -0
  2. package/dist/blocks/built-in.d.ts +6 -0
  3. package/dist/blocks/built-in.js +11 -0
  4. package/dist/chunk-3R3HAGQL.js +102 -0
  5. package/dist/chunk-62BAOSP6.js +100 -0
  6. package/dist/chunk-CJGZUEQO.js +270 -0
  7. package/dist/chunk-CLC3FEL2.js +313 -0
  8. package/dist/chunk-CYMYM7LP.js +25 -0
  9. package/dist/chunk-EERQYNER.js +123 -0
  10. package/dist/chunk-G6J2DCC5.js +77 -0
  11. package/dist/chunk-N3ETBM74.js +24 -0
  12. package/dist/chunk-PPVXNJWI.js +28 -0
  13. package/dist/chunk-QR225IXX.js +148 -0
  14. package/dist/chunk-VIJV6FLT.js +250 -0
  15. package/dist/components/ArtistEditor.d.ts +12 -0
  16. package/dist/components/ArtistEditor.js +11 -0
  17. package/dist/components/BlockEditor.d.ts +24 -0
  18. package/dist/components/BlockEditor.js +16 -0
  19. package/dist/components/BlockRenderer.d.ts +10 -0
  20. package/dist/components/BlockRenderer.js +12 -0
  21. package/dist/components/ImageUploadField.d.ts +11 -0
  22. package/dist/components/ImageUploadField.js +11 -0
  23. package/dist/context/BlockEditorProvider.d.ts +21 -0
  24. package/dist/context/BlockEditorProvider.js +10 -0
  25. package/dist/core/html-renderer.d.ts +13 -0
  26. package/dist/core/html-renderer.js +11 -0
  27. package/dist/core/image-resize.d.ts +17 -0
  28. package/dist/core/image-resize.js +11 -0
  29. package/dist/core/serializer.d.ts +9 -0
  30. package/dist/core/serializer.js +7 -0
  31. package/dist/hooks/useImageDropZone.d.ts +23 -0
  32. package/dist/hooks/useImageDropZone.js +10 -0
  33. package/dist/index.d.ts +11 -0
  34. package/dist/index.js +57 -0
  35. package/dist/types.d.ts +67 -0
  36. package/dist/types.js +0 -0
  37. package/package.json +43 -0
  38. package/styles/artist.css +332 -0
  39. package/styles/editor.css +394 -0
  40. package/styles/preview.css +203 -0
@@ -0,0 +1,24 @@
1
+ import type { BlockData, BlockEditorConfig } from "../types";
2
+ interface SerializedMode {
3
+ /** Serialized HTML+marker string from DB */
4
+ content: string;
5
+ /** Called with HTML+marker string */
6
+ onChange: (html: string) => void;
7
+ }
8
+ interface RawMode {
9
+ /** Block array (for parent-managed serialization) */
10
+ blocks: BlockData[];
11
+ /** Called with updated block array */
12
+ onBlocksChange: (blocks: BlockData[]) => void;
13
+ }
14
+ type BlockEditorProps = (SerializedMode | RawMode) & {
15
+ config: BlockEditorConfig;
16
+ /** Current category (when enableCategoryFilter is true) */
17
+ category?: string;
18
+ /** Track uploaded image keys for orphan cleanup */
19
+ onImageUploaded?: (key: string) => void;
20
+ /** Template/sample load notification */
21
+ onModeChange?: (mode: "template" | "sample") => void;
22
+ };
23
+ export declare function BlockEditor(props: BlockEditorProps): import("react/jsx-runtime").JSX.Element;
24
+ export {};
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import {
3
+ BlockEditor
4
+ } from "../chunk-CLC3FEL2.js";
5
+ import "../chunk-EERQYNER.js";
6
+ import "../chunk-62BAOSP6.js";
7
+ import "../chunk-PPVXNJWI.js";
8
+ import "../chunk-CJGZUEQO.js";
9
+ import "../chunk-G6J2DCC5.js";
10
+ import "../chunk-QR225IXX.js";
11
+ import "../chunk-3R3HAGQL.js";
12
+ import "../chunk-CYMYM7LP.js";
13
+ import "../chunk-N3ETBM74.js";
14
+ export {
15
+ BlockEditor
16
+ };
@@ -0,0 +1,10 @@
1
+ import type { BlockData } from "../types";
2
+ interface BlockRendererProps {
3
+ block: BlockData;
4
+ updateBlock: (id: number, field: string, value: string) => void;
5
+ addSubItem: (id: number, type: string) => void;
6
+ removeSubItem: (id: number, idx: number) => void;
7
+ onImageUploaded?: (key: string) => void;
8
+ }
9
+ export declare function BlockRenderer({ block, updateBlock, addSubItem, removeSubItem, onImageUploaded }: BlockRendererProps): import("react/jsx-runtime").JSX.Element | null;
10
+ export {};
@@ -0,0 +1,12 @@
1
+ "use client";
2
+ import {
3
+ BlockRenderer
4
+ } from "../chunk-CJGZUEQO.js";
5
+ import "../chunk-G6J2DCC5.js";
6
+ import "../chunk-QR225IXX.js";
7
+ import "../chunk-3R3HAGQL.js";
8
+ import "../chunk-CYMYM7LP.js";
9
+ import "../chunk-N3ETBM74.js";
10
+ export {
11
+ BlockRenderer
12
+ };
@@ -0,0 +1,11 @@
1
+ interface ImageUploadFieldProps {
2
+ blockId: number;
3
+ field: string;
4
+ src: string;
5
+ className?: string;
6
+ onUploadComplete: (blockId: number, field: string, url: string) => void;
7
+ onKeyTracked?: (key: string) => void;
8
+ onClear: (blockId: number, field: string) => void;
9
+ }
10
+ export declare function ImageUploadField({ blockId, field, src, className, onUploadComplete, onKeyTracked, onClear, }: ImageUploadFieldProps): import("react/jsx-runtime").JSX.Element;
11
+ export {};
@@ -0,0 +1,11 @@
1
+ "use client";
2
+ import {
3
+ ImageUploadField
4
+ } from "../chunk-G6J2DCC5.js";
5
+ import "../chunk-QR225IXX.js";
6
+ import "../chunk-3R3HAGQL.js";
7
+ import "../chunk-CYMYM7LP.js";
8
+ import "../chunk-N3ETBM74.js";
9
+ export {
10
+ ImageUploadField
11
+ };
@@ -0,0 +1,21 @@
1
+ import type { UploadFn, ErrorFn } from "../types";
2
+ interface BlockEditorContextValue {
3
+ uploadImage: UploadFn;
4
+ onError: ErrorFn;
5
+ autoResize: boolean;
6
+ maxSizeMB: number;
7
+ }
8
+ interface BlockEditorProviderProps {
9
+ /** Upload function — project-specific (e.g. adminFetch → /api/upload) */
10
+ uploadImage: UploadFn;
11
+ /** Error handler — project-specific (e.g. toast.error) */
12
+ onError?: ErrorFn;
13
+ /** Auto-resize images over maxSizeMB (default: true) */
14
+ autoResize?: boolean;
15
+ /** Max image size in MB before auto-resize (default: 10) */
16
+ maxSizeMB?: number;
17
+ children: React.ReactNode;
18
+ }
19
+ export declare function BlockEditorProvider({ uploadImage, onError, autoResize, maxSizeMB, children, }: BlockEditorProviderProps): import("react/jsx-runtime").JSX.Element;
20
+ export declare function useBlockEditorContext(): BlockEditorContextValue;
21
+ export {};
@@ -0,0 +1,10 @@
1
+ "use client";
2
+ import {
3
+ BlockEditorProvider,
4
+ useBlockEditorContext
5
+ } from "../chunk-CYMYM7LP.js";
6
+ import "../chunk-N3ETBM74.js";
7
+ export {
8
+ BlockEditorProvider,
9
+ useBlockEditorContext
10
+ };
@@ -0,0 +1,13 @@
1
+ import type { BlockData } from "../types";
2
+ export declare function h(s: string): string;
3
+ export declare function nl2br(s: string): string;
4
+ /**
5
+ * Creates an HTML renderer with the given CSS class prefix.
6
+ * @param prefix - CSS class prefix (e.g. "nbe-pvb", "rm-bk")
7
+ * @param catClass - optional category CSS class for themed blocks (e.g. "onstage")
8
+ */
9
+ export declare function createHtmlRenderer(prefix: string, catClass?: string): {
10
+ renderBlock: (b: BlockData) => string;
11
+ renderBlocks: (blocks: BlockData[]) => string;
12
+ renderBlocksWrapped: (blocks: BlockData[]) => string;
13
+ };
@@ -0,0 +1,11 @@
1
+ import {
2
+ createHtmlRenderer,
3
+ h,
4
+ nl2br
5
+ } from "../chunk-62BAOSP6.js";
6
+ import "../chunk-N3ETBM74.js";
7
+ export {
8
+ createHtmlRenderer,
9
+ h,
10
+ nl2br
11
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Client-side image resizing utility using Canvas API.
3
+ * Automatically resizes images over the threshold while preserving aspect ratio.
4
+ */
5
+ import type { ResizeResult } from "../types";
6
+ export declare const ALLOWED_IMAGE_TYPES: string[];
7
+ /**
8
+ * Resizes images over 10MB using Canvas API.
9
+ * Preserves aspect ratio with a two-stage strategy:
10
+ * - Stage 1: Quality adjustment only
11
+ * - Stage 2: Dimension reduction + quality
12
+ *
13
+ * GIF images are returned as-is (animation loss prevention).
14
+ */
15
+ export declare function resizeImageIfNeeded(file: File): Promise<ResizeResult>;
16
+ /** Validate image file type and size */
17
+ export declare function validateImageFile(file: File): string | null;
@@ -0,0 +1,11 @@
1
+ import {
2
+ ALLOWED_IMAGE_TYPES,
3
+ resizeImageIfNeeded,
4
+ validateImageFile
5
+ } from "../chunk-3R3HAGQL.js";
6
+ import "../chunk-N3ETBM74.js";
7
+ export {
8
+ ALLOWED_IMAGE_TYPES,
9
+ resizeImageIfNeeded,
10
+ validateImageFile
11
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Generic serializer factory.
3
+ * Creates serialize/deserialize functions for a given marker string.
4
+ * Data is stored as base64-encoded JSON inside HTML comments: <!-- {marker}{base64} -->
5
+ */
6
+ export declare function createSerializer<T = unknown>(marker: string): {
7
+ serialize: (data: T) => string;
8
+ deserialize: (html: string) => T | null;
9
+ };
@@ -0,0 +1,7 @@
1
+ import {
2
+ createSerializer
3
+ } from "../chunk-PPVXNJWI.js";
4
+ import "../chunk-N3ETBM74.js";
5
+ export {
6
+ createSerializer
7
+ };
@@ -0,0 +1,23 @@
1
+ import { type DragEvent } from "react";
2
+ import type { UploadResult } from "../types";
3
+ interface UseImageDropZoneOptions {
4
+ multiple?: boolean;
5
+ maxFiles?: number;
6
+ onUpload: (result: UploadResult) => void;
7
+ onKeyTracked?: (key: string) => void;
8
+ disabled?: boolean;
9
+ }
10
+ export declare function useImageDropZone(options: UseImageDropZoneOptions): {
11
+ isDragOver: boolean;
12
+ isUploading: boolean;
13
+ isResizing: boolean;
14
+ error: string | null;
15
+ dragHandlers: {
16
+ onDragEnter: (e: DragEvent) => void;
17
+ onDragOver: (e: DragEvent) => void;
18
+ onDragLeave: (e: DragEvent) => void;
19
+ onDrop: (e: DragEvent) => void;
20
+ };
21
+ handleFileInput: (fileList: FileList | null) => Promise<void>;
22
+ };
23
+ export {};
@@ -0,0 +1,10 @@
1
+ "use client";
2
+ import {
3
+ useImageDropZone
4
+ } from "../chunk-QR225IXX.js";
5
+ import "../chunk-3R3HAGQL.js";
6
+ import "../chunk-CYMYM7LP.js";
7
+ import "../chunk-N3ETBM74.js";
8
+ export {
9
+ useImageDropZone
10
+ };
@@ -0,0 +1,11 @@
1
+ export type { BlockData, BlockDef, BlockEditorConfig, UploadResult, UploadFn, ErrorFn, ResizeResult, ArtistBioData, } from "./types";
2
+ export { createSerializer } from "./core/serializer";
3
+ export { createHtmlRenderer, h, nl2br } from "./core/html-renderer";
4
+ export { resizeImageIfNeeded, validateImageFile, ALLOWED_IMAGE_TYPES } from "./core/image-resize";
5
+ export { BUILT_IN_BLOCKS, createEmptyBlock, getBlockDef } from "./blocks/built-in";
6
+ export { BlockEditorProvider, useBlockEditorContext } from "./context/BlockEditorProvider";
7
+ export { BlockEditor } from "./components/BlockEditor";
8
+ export { BlockRenderer } from "./components/BlockRenderer";
9
+ export { ImageUploadField } from "./components/ImageUploadField";
10
+ export { ArtistEditor } from "./components/ArtistEditor";
11
+ export { useImageDropZone } from "./hooks/useImageDropZone";
package/dist/index.js ADDED
@@ -0,0 +1,57 @@
1
+ import {
2
+ ArtistEditor
3
+ } from "./chunk-VIJV6FLT.js";
4
+ import {
5
+ BlockEditor
6
+ } from "./chunk-CLC3FEL2.js";
7
+ import {
8
+ BUILT_IN_BLOCKS,
9
+ createEmptyBlock,
10
+ getBlockDef
11
+ } from "./chunk-EERQYNER.js";
12
+ import {
13
+ createHtmlRenderer,
14
+ h,
15
+ nl2br
16
+ } from "./chunk-62BAOSP6.js";
17
+ import {
18
+ createSerializer
19
+ } from "./chunk-PPVXNJWI.js";
20
+ import {
21
+ BlockRenderer
22
+ } from "./chunk-CJGZUEQO.js";
23
+ import {
24
+ ImageUploadField
25
+ } from "./chunk-G6J2DCC5.js";
26
+ import {
27
+ useImageDropZone
28
+ } from "./chunk-QR225IXX.js";
29
+ import {
30
+ ALLOWED_IMAGE_TYPES,
31
+ resizeImageIfNeeded,
32
+ validateImageFile
33
+ } from "./chunk-3R3HAGQL.js";
34
+ import {
35
+ BlockEditorProvider,
36
+ useBlockEditorContext
37
+ } from "./chunk-CYMYM7LP.js";
38
+ import "./chunk-N3ETBM74.js";
39
+ export {
40
+ ALLOWED_IMAGE_TYPES,
41
+ ArtistEditor,
42
+ BUILT_IN_BLOCKS,
43
+ BlockEditor,
44
+ BlockEditorProvider,
45
+ BlockRenderer,
46
+ ImageUploadField,
47
+ createEmptyBlock,
48
+ createHtmlRenderer,
49
+ createSerializer,
50
+ getBlockDef,
51
+ h,
52
+ nl2br,
53
+ resizeImageIfNeeded,
54
+ useBlockEditorContext,
55
+ useImageDropZone,
56
+ validateImageFile
57
+ };
@@ -0,0 +1,67 @@
1
+ export interface BlockData {
2
+ id: number;
3
+ type: string;
4
+ text?: string;
5
+ en?: string;
6
+ src?: string;
7
+ src1?: string;
8
+ src2?: string;
9
+ src3?: string;
10
+ cap?: string;
11
+ attr?: string;
12
+ name?: string;
13
+ role?: string;
14
+ bio?: string;
15
+ title?: string;
16
+ url?: string;
17
+ label?: string;
18
+ q?: string;
19
+ a?: string;
20
+ size?: string;
21
+ items?: Record<string, string>[];
22
+ }
23
+ export interface BlockDef {
24
+ type: string;
25
+ label: string;
26
+ icon: string;
27
+ desc?: string;
28
+ cats?: string[];
29
+ createEmpty: (id: number) => BlockData;
30
+ }
31
+ export interface UploadResult {
32
+ url: string;
33
+ key?: string;
34
+ }
35
+ export type UploadFn = (file: File) => Promise<UploadResult>;
36
+ export type ErrorFn = (message: string) => void;
37
+ export interface ResizeResult {
38
+ file: File;
39
+ wasResized: boolean;
40
+ originalSize: number;
41
+ newSize: number;
42
+ }
43
+ export interface BlockEditorConfig {
44
+ /** Available block definitions */
45
+ blocks: BlockDef[];
46
+ /** Serialization marker name (e.g. "nbe-blocks:") */
47
+ marker: string;
48
+ /** CSS class prefix for rendered HTML (e.g. "nbe-pvb") */
49
+ cssPrefix: string;
50
+ /** Enable drag-and-drop reordering (default: true) */
51
+ enableDragDrop?: boolean;
52
+ /** Enable category-based block filtering (default: false) */
53
+ enableCategoryFilter?: boolean;
54
+ /** Category list (required when enableCategoryFilter is true) */
55
+ categories?: string[];
56
+ /** Category → CSS class mapping for themed blocks */
57
+ catClasses?: Record<string, string>;
58
+ /** Category-keyed empty templates */
59
+ templates?: Record<string, Omit<BlockData, "id">[]>;
60
+ /** Category-keyed sample content */
61
+ samples?: Record<string, Omit<BlockData, "id">[]>;
62
+ }
63
+ export interface ArtistBioData {
64
+ text: string;
65
+ mainImage: string;
66
+ gallery: string[];
67
+ }
package/dist/types.js ADDED
File without changes
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@withwiz/block-editor",
3
+ "version": "0.1.0",
4
+ "description": "Block-based content editor for web publishing",
5
+ "private": false,
6
+ "files": ["dist", "styles"],
7
+ "typesVersions": {
8
+ "*": {
9
+ "*": ["./dist/*"]
10
+ }
11
+ },
12
+ "exports": {
13
+ ".": "./dist/index.js",
14
+ "./types": "./dist/types.js",
15
+ "./blocks/built-in": "./dist/blocks/built-in.js",
16
+ "./components/BlockEditor": "./dist/components/BlockEditor.js",
17
+ "./components/BlockRenderer": "./dist/components/BlockRenderer.js",
18
+ "./components/ImageUploadField": "./dist/components/ImageUploadField.js",
19
+ "./components/ArtistEditor": "./dist/components/ArtistEditor.js",
20
+ "./context/BlockEditorProvider": "./dist/context/BlockEditorProvider.js",
21
+ "./core/serializer": "./dist/core/serializer.js",
22
+ "./core/html-renderer": "./dist/core/html-renderer.js",
23
+ "./core/image-resize": "./dist/core/image-resize.js",
24
+ "./hooks/useImageDropZone": "./dist/hooks/useImageDropZone.js",
25
+ "./styles/editor.css": "./styles/editor.css",
26
+ "./styles/preview.css": "./styles/preview.css",
27
+ "./styles/artist.css": "./styles/artist.css"
28
+ },
29
+ "scripts": {
30
+ "build": "tsup && tsc --emitDeclarationOnly --skipLibCheck",
31
+ "build:js": "tsup",
32
+ "build:types": "tsc --emitDeclarationOnly --skipLibCheck"
33
+ },
34
+ "peerDependencies": {
35
+ "react": ">=18.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "@types/react": "19.2.7",
39
+ "@types/react-dom": "19.2.3",
40
+ "tsup": "^8.0.0",
41
+ "typescript": "^5"
42
+ }
43
+ }