+ this.updateValue(innerHTML)
+ }
+ onPaste={this.handlePasteDrop}
+ onDrop={this.handlePasteDrop}
+ />
+
+ >
+ );
+ }
+}
diff --git a/registry/new-york/blocks/editor/example.tsx b/registry/new-york/blocks/editor/example.tsx
new file mode 100644
index 0000000..e715fa5
--- /dev/null
+++ b/registry/new-york/blocks/editor/example.tsx
@@ -0,0 +1,39 @@
+"use client";
+
+import { configure } from "mobx";
+import { formToJSON } from "web-utility";
+
+import { Button } from "@/components/ui/button";
+import { Editor, OriginalTools, ExtraTools } from "./index";
+
+configure({ enforceActions: "never" });
+
+export const EditorExample = () => (
+
+);
diff --git a/registry/new-york/blocks/editor/index.ts b/registry/new-york/blocks/editor/index.ts
new file mode 100644
index 0000000..8cf5f0a
--- /dev/null
+++ b/registry/new-york/blocks/editor/index.ts
@@ -0,0 +1,3 @@
+export * from "./tool";
+export * from "./tools";
+export * from "./editor";
diff --git a/registry/new-york/blocks/editor/tool.tsx b/registry/new-york/blocks/editor/tool.tsx
new file mode 100644
index 0000000..d942acc
--- /dev/null
+++ b/registry/new-york/blocks/editor/tool.tsx
@@ -0,0 +1,33 @@
+import { ComponentType, RefObject, SVGProps } from "react";
+import { Tool } from "edkit";
+import * as Icons from "lucide-react";
+
+import { Button } from "@/components/ui/button";
+
+export function renderTool(this: Tool, editor: RefObject
) {
+ const { title, active, icon, usable } = this;
+
+ const IconComponent =
+ (Icons[icon as keyof typeof Icons] as ComponentType<
+ SVGProps
+ >) || Icons.Circle;
+
+ return (
+
+ );
+}
diff --git a/registry/new-york/blocks/editor/tools/color.tsx b/registry/new-york/blocks/editor/tools/color.tsx
new file mode 100644
index 0000000..6664c3b
--- /dev/null
+++ b/registry/new-york/blocks/editor/tools/color.tsx
@@ -0,0 +1,100 @@
+import { FC, RefObject } from "react";
+import {
+ ColorName,
+ ColorTool,
+ ForeColorTool as FCT,
+ BackColorTool as BCT,
+} from "edkit";
+import { Type, FileText } from "lucide-react";
+
+import { Button } from "@/components/ui/button";
+
+export interface ColorSelectorProps
+ extends Partial> {
+ icon: "Type" | "FileText";
+ type: ColorName;
+ onChange?: (color: string) => any;
+}
+
+export const ColorSelector: FC = ({
+ className = "",
+ title,
+ type,
+ value,
+ onChange,
+ icon,
+}) => (
+
+ onChange?.(value)}
+ />
+
+
+);
+
+export function renderColorTool(
+ this: ColorTool,
+ editor: RefObject
+) {
+ const { icon, name, colorName } = this;
+
+ return (
+
+ editor.current && this.execute(editor.current, color)
+ }
+ />
+ );
+}
+
+export class ForeColorTool extends FCT {
+ icon = "Type";
+ render = renderColorTool;
+}
+
+export class BackColorTool extends BCT {
+ icon = "FileText";
+ render = renderColorTool;
+}
diff --git a/registry/new-york/blocks/editor/tools/control.ts b/registry/new-york/blocks/editor/tools/control.ts
new file mode 100644
index 0000000..46b2e61
--- /dev/null
+++ b/registry/new-york/blocks/editor/tools/control.ts
@@ -0,0 +1,28 @@
+import {
+ UndoTool as UDT,
+ RedoTool as RDT,
+ ResetTool as RST,
+ ClearTool as CT,
+} from "edkit";
+
+import { renderTool } from "../tool";
+
+export class UndoTool extends UDT {
+ icon = "Undo";
+ render = renderTool;
+}
+
+export class RedoTool extends RDT {
+ icon = "Redo";
+ render = renderTool;
+}
+
+export class ResetTool extends RST {
+ icon = "Eraser";
+ render = renderTool;
+}
+
+export class ClearTool extends CT {
+ icon = "X";
+ render = renderTool;
+}
diff --git a/registry/new-york/blocks/editor/tools/extra.ts b/registry/new-york/blocks/editor/tools/extra.ts
new file mode 100644
index 0000000..c488da7
--- /dev/null
+++ b/registry/new-york/blocks/editor/tools/extra.ts
@@ -0,0 +1,8 @@
+import { CopyMarkdownTool as CMDT } from "edkit";
+
+import { renderTool } from "../tool";
+
+export class CopyMarkdownTool extends CMDT {
+ icon = "FileText";
+ render = renderTool;
+}
diff --git a/registry/new-york/blocks/editor/tools/index.ts b/registry/new-york/blocks/editor/tools/index.ts
new file mode 100644
index 0000000..a20f282
--- /dev/null
+++ b/registry/new-york/blocks/editor/tools/index.ts
@@ -0,0 +1,95 @@
+import {
+ BoldTool,
+ ItalicTool,
+ UnderlineTool,
+ StrikeThroughTool,
+ H1Tool,
+ H2Tool,
+ H3Tool,
+ FontSizeDownTool,
+ FontSizeUpTool,
+ SubscriptTool,
+ SuperscriptTool,
+ LinkTool,
+} from "./text";
+import { ForeColorTool, BackColorTool } from "./color";
+import {
+ AlignLeftTool,
+ AlignCenterTool,
+ AlignRightTool,
+ AlignFullTool,
+ OrderedListTool,
+ UnorderedListTool,
+ HorizontalRuleTool,
+} from "./layout";
+import { IFrameTool, ImageTool, AudioTool, VideoTool } from "./media";
+import { UndoTool, RedoTool, ResetTool, ClearTool } from "./control";
+import { CopyMarkdownTool } from "./extra";
+
+export * from "./text";
+export * from "./color";
+export * from "./layout";
+export * from "./media";
+export * from "./control";
+export * from "./extra";
+
+export const TextTools = [
+ BoldTool,
+ ItalicTool,
+ UnderlineTool,
+ StrikeThroughTool,
+ H1Tool,
+ H2Tool,
+ H3Tool,
+ FontSizeDownTool,
+ FontSizeUpTool,
+ SubscriptTool,
+ SuperscriptTool,
+ LinkTool,
+];
+export const ColorTools = [ForeColorTool, BackColorTool];
+export const LayoutTools = [
+ AlignLeftTool,
+ AlignCenterTool,
+ AlignRightTool,
+ AlignFullTool,
+ OrderedListTool,
+ UnorderedListTool,
+ HorizontalRuleTool,
+];
+export const MediaTools = [IFrameTool, ImageTool, AudioTool, VideoTool];
+export const ControlTools = [UndoTool, RedoTool, ResetTool, ClearTool];
+export const ExtraTools = [CopyMarkdownTool];
+
+export const OriginalTools = [
+ ...TextTools,
+ ...ColorTools,
+ ...LayoutTools,
+ ...MediaTools,
+ ...ControlTools,
+];
+
+export const DefaultTools = [
+ BoldTool,
+ ItalicTool,
+ UnderlineTool,
+ StrikeThroughTool,
+ H1Tool,
+ H2Tool,
+ H3Tool,
+ SubscriptTool,
+ SuperscriptTool,
+ ForeColorTool,
+ BackColorTool,
+ AlignLeftTool,
+ AlignCenterTool,
+ AlignRightTool,
+ AlignFullTool,
+ OrderedListTool,
+ UnorderedListTool,
+ HorizontalRuleTool,
+ ImageTool,
+ UndoTool,
+ RedoTool,
+ ClearTool,
+];
diff --git a/registry/new-york/blocks/editor/tools/layout.ts b/registry/new-york/blocks/editor/tools/layout.ts
new file mode 100644
index 0000000..bab0d11
--- /dev/null
+++ b/registry/new-york/blocks/editor/tools/layout.ts
@@ -0,0 +1,46 @@
+import {
+ AlignLeftTool as ALT,
+ AlignCenterTool as ACT,
+ AlignRightTool as ART,
+ AlignFullTool as AFT,
+ OrderedListTool as OLT,
+ UnorderedListTool as ULT,
+ HorizontalRuleTool as HRT,
+} from "edkit";
+
+import { renderTool } from "../tool";
+
+export class AlignLeftTool extends ALT {
+ icon = "AlignLeft";
+ render = renderTool;
+}
+
+export class AlignCenterTool extends ACT {
+ icon = "AlignCenter";
+ render = renderTool;
+}
+
+export class AlignRightTool extends ART {
+ icon = "AlignRight";
+ render = renderTool;
+}
+
+export class AlignFullTool extends AFT {
+ icon = "AlignJustify";
+ render = renderTool;
+}
+
+export class OrderedListTool extends OLT {
+ icon = "ListOrdered";
+ render = renderTool;
+}
+
+export class UnorderedListTool extends ULT {
+ icon = "List";
+ render = renderTool;
+}
+
+export class HorizontalRuleTool extends HRT {
+ icon = "Minus";
+ render = renderTool;
+}
diff --git a/registry/new-york/blocks/editor/tools/media.ts b/registry/new-york/blocks/editor/tools/media.ts
new file mode 100644
index 0000000..6585aa3
--- /dev/null
+++ b/registry/new-york/blocks/editor/tools/media.ts
@@ -0,0 +1,28 @@
+import {
+ IFrameTool as FT,
+ ImageTool as IT,
+ AudioTool as AT,
+ VideoTool as VT,
+} from "edkit";
+
+import { renderTool } from "../tool";
+
+export class IFrameTool extends FT {
+ icon = "Frame";
+ render = renderTool;
+}
+
+export class ImageTool extends IT {
+ icon = "Image";
+ render = renderTool;
+}
+
+export class AudioTool extends AT {
+ icon = "Mic";
+ render = renderTool;
+}
+
+export class VideoTool extends VT {
+ icon = "Video";
+ render = renderTool;
+}
diff --git a/registry/new-york/blocks/editor/tools/text.ts b/registry/new-york/blocks/editor/tools/text.ts
new file mode 100644
index 0000000..1f3d345
--- /dev/null
+++ b/registry/new-york/blocks/editor/tools/text.ts
@@ -0,0 +1,76 @@
+import {
+ BoldTool as BT,
+ ItalicTool as IT,
+ UnderlineTool as UT,
+ StrikeThroughTool as STT,
+ H1Tool as H1T,
+ H2Tool as H2T,
+ H3Tool as H3T,
+ FontSizeDownTool as FSDT,
+ FontSizeUpTool as FSUT,
+ SubscriptTool as SubST,
+ SuperscriptTool as SupST,
+ LinkTool as LT,
+} from "edkit";
+
+import { renderTool } from "../tool";
+
+export class BoldTool extends BT {
+ icon = "Bold";
+ render = renderTool;
+}
+
+export class ItalicTool extends IT {
+ icon = "Italic";
+ render = renderTool;
+}
+
+export class UnderlineTool extends UT {
+ icon = "Underline";
+ render = renderTool;
+}
+
+export class StrikeThroughTool extends STT {
+ icon = "Strikethrough";
+ render = renderTool;
+}
+
+export class H1Tool extends H1T {
+ icon = "Heading1";
+ render = renderTool;
+}
+
+export class H2Tool extends H2T {
+ icon = "Heading2";
+ render = renderTool;
+}
+
+export class H3Tool extends H3T {
+ icon = "Heading3";
+ render = renderTool;
+}
+
+export class FontSizeDownTool extends FSDT {
+ icon = "ArrowDownAZ";
+ render = renderTool;
+}
+
+export class FontSizeUpTool extends FSUT {
+ icon = "ArrowUpAZ";
+ render = renderTool;
+}
+
+export class SubscriptTool extends SubST {
+ icon = "ArrowDownRight";
+ render = renderTool;
+}
+
+export class SuperscriptTool extends SupST {
+ icon = "ArrowUpRight";
+ render = renderTool;
+}
+
+export class LinkTool extends LT {
+ icon = "Link";
+ render = renderTool;
+}
diff --git a/registry/new-york/blocks/example-form/example-form.tsx b/registry/new-york/blocks/example-form/example-form.tsx
deleted file mode 100644
index 6b6bb9f..0000000
--- a/registry/new-york/blocks/example-form/example-form.tsx
+++ /dev/null
@@ -1,164 +0,0 @@
-"use client"
-
-import * as React from "react"
-import {
- Card,
- CardTitle,
- CardHeader,
- CardDescription,
- CardContent,
- CardFooter,
-} from "@/registry/new-york/ui/card"
-import { Input } from "@/registry/new-york/ui/input"
-import { Label } from "@/registry/new-york/ui/label"
-import { Button } from "@/registry/new-york/ui/button"
-import { Textarea } from "@/registry/new-york/ui/textarea"
-import { z } from "zod"
-
-const exampleFormSchema = z.object({
- name: z.string().min(1),
- email: z.string().email(),
- message: z.string().min(1),
-})
-
-export function ExampleForm() {
- const [pending, setPending] = React.useState(false)
- const [state, setState] = React.useState({
- defaultValues: {
- name: "",
- email: "",
- message: "",
- },
- success: false,
- errors: {
- name: "",
- email: "",
- message: "",
- },
- })
-
- const handleSubmit = React.useCallback(
- (e: React.FormEvent) => {
- e.preventDefault()
- setPending(true)
-
- const formData = new FormData(e.target as HTMLFormElement)
- const data = Object.fromEntries(formData.entries())
- const result = exampleFormSchema.safeParse(data)
-
- if (!result.success) {
- setState({
- ...state,
- errors: Object.fromEntries(
- Object.entries(result.error.flatten().fieldErrors).map(
- ([key, value]) => [key, value?.[0] ?? ""]
- )
- ) as Record,
- })
- setPending(false)
- return
- }
-
- setPending(false)
- },
- [state]
- )
-
- return (
-
- )
-}
diff --git a/registry/new-york/blocks/example-with-css/example-card.css b/registry/new-york/blocks/example-with-css/example-card.css
deleted file mode 100644
index 6b431d2..0000000
--- a/registry/new-york/blocks/example-with-css/example-card.css
+++ /dev/null
@@ -1,134 +0,0 @@
-.login-container {
- --primary-color: #111111;
- --primary-hover: #484747;
- --error-color: #ef4444;
- --text-color: #1f2937;
- --text-light: #6b7280;
- --border-color: #e5e7eb;
- --background-light: #f9fafb;
- --card-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
- 0 2px 4px -1px rgba(0, 0, 0, 0.06);
-
- display: flex;
- justify-content: center;
- align-items: center;
- padding: 1rem;
- background-color: var(--background-light);
- width: 100%;
-}
-
-.login-card {
- width: 100%;
- max-width: 400px;
- padding: 2rem;
- background-color: white;
- border-radius: 8px;
- box-shadow: var(--card-shadow);
-}
-
-.login-title {
- margin: 0 0 0.5rem 0;
- font-size: 1.5rem;
- font-weight: 600;
- color: var(--text-color);
-}
-
-.login-subtitle {
- margin: 0 0 1.5rem 0;
- font-size: 0.875rem;
- color: var(--text-light);
-}
-
-.login-form {
- display: flex;
- flex-direction: column;
- gap: 1.25rem;
-}
-
-.login-error {
- padding: 0.75rem;
- margin-bottom: 0.5rem;
- background-color: rgba(239, 68, 68, 0.1);
- border-left: 3px solid var(--error-color);
- color: var(--error-color);
- font-size: 0.875rem;
- border-radius: 4px;
-}
-
-.form-group {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-}
-
-.form-group label {
- font-size: 0.875rem;
- font-weight: 500;
- color: var(--text-color);
-}
-
-.form-group input {
- padding: 0.75rem;
- border: 1px solid var(--border-color);
- border-radius: 4px;
- font-size: 1rem;
- transition: border-color 0.15s ease;
-}
-
-.form-group input:focus {
- outline: none;
- border-color: var(--primary-color);
- box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
-}
-
-.form-group input::placeholder {
- color: var(--text-light);
-}
-
-.form-actions {
- margin-top: 0.5rem;
-}
-
-.login-button {
- width: 100%;
- padding: 0.75rem;
- background-color: var(--primary-color);
- color: white;
- border: none;
- border-radius: 4px;
- font-size: 1rem;
- font-weight: 500;
- cursor: pointer;
- transition: background-color 0.15s ease;
-}
-
-.login-button:hover {
- background-color: var(--primary-hover);
-}
-
-.login-button:focus {
- outline: none;
- box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.3);
-}
-
-.form-footer {
- display: flex;
- justify-content: center;
- margin-top: 1rem;
-}
-
-.forgot-password {
- font-size: 0.875rem;
- color: var(--primary-color);
- text-decoration: none;
-}
-
-.forgot-password:hover {
- text-decoration: underline;
-}
-
-@media (max-width: 480px) {
- .login-card {
- padding: 1.5rem;
- }
-}
diff --git a/registry/new-york/blocks/example-with-css/example-card.tsx b/registry/new-york/blocks/example-with-css/example-card.tsx
deleted file mode 100644
index e140f74..0000000
--- a/registry/new-york/blocks/example-with-css/example-card.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import "./example-card.css"
-
-export function ExampleCard() {
- return (
-
-
-
Login
-
- Please enter your credentials to continue
-
-
-
-
- )
-}
diff --git a/registry/new-york/blocks/hello-world/hello-world.tsx b/registry/new-york/blocks/hello-world/hello-world.tsx
deleted file mode 100644
index c5f2299..0000000
--- a/registry/new-york/blocks/hello-world/hello-world.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export function HelloWorld() {
- return Hello World
-}
diff --git a/registry/new-york/blocks/rest-table/example.tsx b/registry/new-york/blocks/rest-table/example.tsx
index 1f7eb42..66aa7d4 100644
--- a/registry/new-york/blocks/rest-table/example.tsx
+++ b/registry/new-york/blocks/rest-table/example.tsx
@@ -9,7 +9,7 @@ import { RestTable } from "./rest-table";
configure({ enforceActions: "never" });
export const RestTableExample = () => (
-