dishui 0.0.97 → 0.0.101
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/dist/.release-verified.json +2 -2
- package/dist/ai.js +17 -15
- package/dist/components/Card/Ticket.d.ts +52 -0
- package/dist/components/Card/Ticket2.js +218 -0
- package/dist/components/Card/Ticket2.js.map +1 -0
- package/dist/components/Card/index.d.ts +12 -0
- package/dist/components/Card/index.js +142 -139
- package/dist/components/Card/index.js.map +1 -1
- package/dist/components/ai/AgentRunCard/index.d.ts +38 -0
- package/dist/components/ai/AgentRunCard/index.js +100 -0
- package/dist/components/ai/AgentRunCard/index.js.map +1 -0
- package/dist/components/ai/IssueCard/index.d.ts +39 -0
- package/dist/components/ai/IssueCard/index.js +78 -0
- package/dist/components/ai/IssueCard/index.js.map +1 -0
- package/dist/components/ai/index.d.ts +4 -0
- package/dist/components/pro/Flow/constants.js +3 -3
- package/dist/components/pro/Flow/constants.js.map +1 -1
- package/dist/components/pro/Flow/nodes/shapes.js +3 -3
- package/dist/components/pro/Flow/nodes/shapes.js.map +1 -1
- package/dist/components/pro/Flow/utils/themeColor.d.ts +2 -2
- package/dist/components/pro/Flow/utils/themeColor.js +2 -2
- package/dist/components/pro/Flow/utils/themeColor.js.map +1 -1
- package/dist/components/pro/Kanban/Kanban.d.ts +3 -0
- package/dist/components/pro/Kanban/Kanban.js +339 -0
- package/dist/components/pro/Kanban/Kanban.js.map +1 -0
- package/dist/components/pro/Kanban/Swimlanes.d.ts +3 -0
- package/dist/components/pro/Kanban/Swimlanes.js +60 -0
- package/dist/components/pro/Kanban/Swimlanes.js.map +1 -0
- package/dist/components/pro/Kanban/index.d.ts +5 -0
- package/dist/components/pro/Kanban/types.d.ts +103 -0
- package/dist/components/pro/Kanban/useKanbanDrag.d.ts +17 -0
- package/dist/components/pro/Kanban/useKanbanDrag.js +69 -0
- package/dist/components/pro/Kanban/useKanbanDrag.js.map +1 -0
- package/dist/components/pro/Kanban/utils.d.ts +13 -0
- package/dist/components/pro/Kanban/utils.js +48 -0
- package/dist/components/pro/Kanban/utils.js.map +1 -0
- package/dist/components/pro/RichTextEditor/AIRewrite.js +158 -127
- package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BlockHandle.d.ts +2 -0
- package/dist/components/pro/RichTextEditor/BlockHandle.js +156 -115
- package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
- package/dist/components/pro/RichTextEditor/RichTextEditor.js +136 -159
- package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js +44 -41
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js +59 -53
- package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js +48 -44
- package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js +67 -63
- package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.d.ts +1 -0
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js +182 -129
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/ToolbarButton.d.ts +1 -0
- package/dist/components/pro/RichTextEditor/Toolbar/ToolbarButton.js +3 -3
- package/dist/components/pro/RichTextEditor/Toolbar/ToolbarButton.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/useAnchoredDropdown.d.ts +3 -0
- package/dist/components/pro/RichTextEditor/Toolbar/useAnchoredDropdown.js +31 -0
- package/dist/components/pro/RichTextEditor/Toolbar/useAnchoredDropdown.js.map +1 -0
- package/dist/components/pro/RichTextEditor/index.d.ts +1 -1
- package/dist/components/pro/RichTextEditor/types.d.ts +78 -11
- package/dist/components/pro/RichTextEditor/types.js +11 -0
- package/dist/components/pro/RichTextEditor/types.js.map +1 -1
- package/dist/dishui.css +1 -1
- package/dist/index-nostyled.d.ts +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +128 -122
- package/dist/kanban.js +5 -0
- package/dist/utils/i18n.js +20 -0
- package/dist/utils/i18n.js.map +1 -1
- package/dist/utils/menu.js +1 -1
- package/dist/utils/menu.js.map +1 -1
- package/package.json +5 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { useAnchoredDropdown as e } from "./useAnchoredDropdown.js";
|
|
2
|
+
import { useEffect as t, useRef as n, useState as r } from "react";
|
|
3
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
4
|
+
import { flushSync as o } from "react-dom";
|
|
4
5
|
//#region src/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.tsx
|
|
5
|
-
var
|
|
6
|
+
var s = [
|
|
6
7
|
{
|
|
7
8
|
key: "flowchart",
|
|
8
9
|
labelKey: "mdTplFlowchart",
|
|
@@ -63,28 +64,29 @@ var o = [
|
|
|
63
64
|
icon: "🎨",
|
|
64
65
|
content: "## Mixed Content Example\n\n### Architecture Overview\n\n```mermaid\ngraph LR\n Client[Client App] --> Gateway[API Gateway]\n Gateway --> Auth[Auth Service]\n Gateway --> Core[Core Service]\n Core --> DB[(PostgreSQL)]\n Core --> Cache[(Redis)]\n Auth --> DB\n```\n\n### Performance Formula\n\nThe response time $T$ is calculated as:\n\n$$\nT = T_{network} + T_{processing} + T_{db}\n$$\n\nwhere $T_{db} = O(\\log n)$ with proper indexing.\n\n### Implementation\n\n```python\nfrom fastapi import FastAPI, Depends\nfrom functools import lru_cache\n\napp = FastAPI()\n\n@lru_cache(maxsize=256)\ndef compute_heavy(n: int) -> float:\n \"\"\"Cached computation: O(log n) amortized.\"\"\"\n return sum(1.0 / i for i in range(1, n + 1))\n\n@app.get(\"/api/harmonic/{n}\")\nasync def harmonic(n: int):\n result = compute_heavy(n)\n return {\"n\": n, \"H_n\": round(result, 6)}\n```\n\n### Project Status\n\n```mermaid\npie title Sprint Progress\n \"Completed\" : 65\n \"In Progress\" : 20\n \"Blocked\" : 10\n \"Not Started\" : 5\n```\n"
|
|
65
66
|
}
|
|
66
|
-
],
|
|
67
|
-
let [
|
|
68
|
-
let n = e.detail === 0 ||
|
|
69
|
-
|
|
67
|
+
], c = ({ labels: c, onSelect: l }) => {
|
|
68
|
+
let [u, d] = r(!1), f = n(null), p = n(null), m = n(null), h = e(u, p, m), g = n(""), _ = (e, t) => {
|
|
69
|
+
let n = e.detail === 0 || g.current !== "touch";
|
|
70
|
+
o(() => d(!1)), l(t, n);
|
|
70
71
|
};
|
|
71
|
-
return
|
|
72
|
+
return t(() => {
|
|
72
73
|
let e = (e) => {
|
|
73
|
-
|
|
74
|
+
f.current && !f.current.contains(e.target) && d(!1);
|
|
74
75
|
};
|
|
75
76
|
return document.addEventListener("pointerdown", e), () => document.removeEventListener("pointerdown", e);
|
|
76
|
-
}, []), /* @__PURE__ */
|
|
77
|
-
ref:
|
|
77
|
+
}, []), /* @__PURE__ */ a("div", {
|
|
78
|
+
ref: f,
|
|
78
79
|
className: "rte-toolbar__template-menu",
|
|
79
80
|
onPointerDown: (e) => {
|
|
80
|
-
|
|
81
|
+
g.current = e.pointerType;
|
|
81
82
|
},
|
|
82
|
-
children: [/* @__PURE__ */
|
|
83
|
+
children: [/* @__PURE__ */ a("button", {
|
|
83
84
|
type: "button",
|
|
84
|
-
|
|
85
|
-
"
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
ref: p,
|
|
86
|
+
className: `rte-toolbar__btn ${u ? "rte-toolbar__btn--active" : ""}`,
|
|
87
|
+
"aria-expanded": u,
|
|
88
|
+
onClick: () => d(!u),
|
|
89
|
+
title: c.mdTemplates || "Markdown Templates",
|
|
88
90
|
style: {
|
|
89
91
|
width: "auto",
|
|
90
92
|
padding: "0 6px",
|
|
@@ -92,7 +94,7 @@ var o = [
|
|
|
92
94
|
display: "inline-flex",
|
|
93
95
|
alignItems: "center"
|
|
94
96
|
},
|
|
95
|
-
children: [/* @__PURE__ */
|
|
97
|
+
children: [/* @__PURE__ */ a("svg", {
|
|
96
98
|
width: "16",
|
|
97
99
|
height: "16",
|
|
98
100
|
viewBox: "0 0 24 24",
|
|
@@ -102,95 +104,97 @@ var o = [
|
|
|
102
104
|
strokeLinecap: "round",
|
|
103
105
|
strokeLinejoin: "round",
|
|
104
106
|
children: [
|
|
105
|
-
/* @__PURE__ */
|
|
107
|
+
/* @__PURE__ */ i("rect", {
|
|
106
108
|
x: "3",
|
|
107
109
|
y: "3",
|
|
108
110
|
width: "8",
|
|
109
111
|
height: "8",
|
|
110
112
|
rx: "1.5"
|
|
111
113
|
}),
|
|
112
|
-
/* @__PURE__ */
|
|
114
|
+
/* @__PURE__ */ i("rect", {
|
|
113
115
|
x: "13",
|
|
114
116
|
y: "3",
|
|
115
117
|
width: "8",
|
|
116
118
|
height: "8",
|
|
117
119
|
rx: "1.5"
|
|
118
120
|
}),
|
|
119
|
-
/* @__PURE__ */
|
|
121
|
+
/* @__PURE__ */ i("rect", {
|
|
120
122
|
x: "3",
|
|
121
123
|
y: "13",
|
|
122
124
|
width: "8",
|
|
123
125
|
height: "8",
|
|
124
126
|
rx: "1.5"
|
|
125
127
|
}),
|
|
126
|
-
/* @__PURE__ */
|
|
128
|
+
/* @__PURE__ */ i("path", { d: "M17 14v6M14 17h6" })
|
|
127
129
|
]
|
|
128
|
-
}), /* @__PURE__ */
|
|
130
|
+
}), /* @__PURE__ */ i("svg", {
|
|
129
131
|
width: "10",
|
|
130
132
|
height: "10",
|
|
131
133
|
viewBox: "0 0 24 24",
|
|
132
134
|
fill: "none",
|
|
133
135
|
stroke: "currentColor",
|
|
134
136
|
strokeWidth: "2.5",
|
|
135
|
-
children: /* @__PURE__ */
|
|
137
|
+
children: /* @__PURE__ */ i("polyline", { points: "6 9 12 15 18 9" })
|
|
136
138
|
})]
|
|
137
|
-
}),
|
|
139
|
+
}), u && /* @__PURE__ */ a("div", {
|
|
140
|
+
ref: m,
|
|
138
141
|
className: "rte-toolbar__template-dropdown",
|
|
142
|
+
style: h,
|
|
139
143
|
children: [
|
|
140
|
-
/* @__PURE__ */
|
|
144
|
+
/* @__PURE__ */ i("div", {
|
|
141
145
|
className: "rte-toolbar__template-group-label",
|
|
142
146
|
children: "Mermaid"
|
|
143
147
|
}),
|
|
144
|
-
|
|
148
|
+
s.filter((e) => [
|
|
145
149
|
"flowchart",
|
|
146
150
|
"sequence",
|
|
147
151
|
"pie",
|
|
148
152
|
"gantt",
|
|
149
153
|
"xychart"
|
|
150
|
-
].includes(e.key)).map((e) => /* @__PURE__ */
|
|
154
|
+
].includes(e.key)).map((e) => /* @__PURE__ */ a("button", {
|
|
151
155
|
type: "button",
|
|
152
156
|
className: "rte-toolbar__template-item",
|
|
153
|
-
onClick: (t) =>
|
|
154
|
-
children: [/* @__PURE__ */
|
|
157
|
+
onClick: (t) => _(t, e.content),
|
|
158
|
+
children: [/* @__PURE__ */ i("span", {
|
|
155
159
|
className: "rte-toolbar__template-icon",
|
|
156
160
|
children: e.icon
|
|
157
|
-
}), /* @__PURE__ */
|
|
161
|
+
}), /* @__PURE__ */ i("span", { children: c[e.labelKey] || e.labelKey })]
|
|
158
162
|
}, e.key)),
|
|
159
|
-
/* @__PURE__ */
|
|
163
|
+
/* @__PURE__ */ i("div", {
|
|
160
164
|
className: "rte-toolbar__template-group-label",
|
|
161
165
|
children: "Code"
|
|
162
166
|
}),
|
|
163
|
-
|
|
167
|
+
s.filter((e) => [
|
|
164
168
|
"python",
|
|
165
169
|
"typescript",
|
|
166
170
|
"rust"
|
|
167
|
-
].includes(e.key)).map((e) => /* @__PURE__ */
|
|
171
|
+
].includes(e.key)).map((e) => /* @__PURE__ */ a("button", {
|
|
168
172
|
type: "button",
|
|
169
173
|
className: "rte-toolbar__template-item",
|
|
170
|
-
onClick: (t) =>
|
|
171
|
-
children: [/* @__PURE__ */
|
|
174
|
+
onClick: (t) => _(t, e.content),
|
|
175
|
+
children: [/* @__PURE__ */ i("span", {
|
|
172
176
|
className: "rte-toolbar__template-icon",
|
|
173
177
|
children: e.icon
|
|
174
|
-
}), /* @__PURE__ */
|
|
178
|
+
}), /* @__PURE__ */ i("span", { children: c[e.labelKey] || e.labelKey })]
|
|
175
179
|
}, e.key)),
|
|
176
|
-
/* @__PURE__ */
|
|
180
|
+
/* @__PURE__ */ i("div", {
|
|
177
181
|
className: "rte-toolbar__template-group-label",
|
|
178
182
|
children: "Math / Mixed"
|
|
179
183
|
}),
|
|
180
|
-
|
|
184
|
+
s.filter((e) => ["math", "mixed"].includes(e.key)).map((e) => /* @__PURE__ */ a("button", {
|
|
181
185
|
type: "button",
|
|
182
186
|
className: "rte-toolbar__template-item",
|
|
183
|
-
onClick: (t) =>
|
|
184
|
-
children: [/* @__PURE__ */
|
|
187
|
+
onClick: (t) => _(t, e.content),
|
|
188
|
+
children: [/* @__PURE__ */ i("span", {
|
|
185
189
|
className: "rte-toolbar__template-icon",
|
|
186
190
|
children: e.icon
|
|
187
|
-
}), /* @__PURE__ */
|
|
191
|
+
}), /* @__PURE__ */ i("span", { children: c[e.labelKey] || e.labelKey })]
|
|
188
192
|
}, e.key))
|
|
189
193
|
]
|
|
190
194
|
})]
|
|
191
195
|
});
|
|
192
196
|
};
|
|
193
197
|
//#endregion
|
|
194
|
-
export {
|
|
198
|
+
export { s as MD_TEMPLATES, c as MarkdownTemplateMenu };
|
|
195
199
|
|
|
196
200
|
//# sourceMappingURL=MarkdownTemplates.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkdownTemplates.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport { flushSync } from 'react-dom';\nimport type { RichTextEditorLabels } from '../types';\n\nexport const MD_TEMPLATES: { key: string; labelKey: keyof RichTextEditorLabels; icon: string; content: string }[] = [\n {\n key: 'flowchart', labelKey: 'mdTplFlowchart', icon: '🔀',\n content: `## Flowchart\n\n\\`\\`\\`mermaid\ngraph TD\n A[Start] --> B{Is it valid?}\n B -->|Yes| C[Process Data]\n B -->|No| D[Show Error]\n C --> E[Save to DB]\n E --> F[Send Response]\n D --> G[Log Warning]\n G --> A\n F --> H[End]\n\\`\\`\\`\n`,\n },\n {\n key: 'sequence', labelKey: 'mdTplSequence', icon: '🔄',\n content: `## Sequence Diagram\n\n\\`\\`\\`mermaid\nsequenceDiagram\n participant Browser\n participant Server\n participant Database\n participant Cache\n\n Browser->>Server: POST /api/login\n Server->>Database: Query user\n Database-->>Server: User record\n Server->>Cache: Store session\n Cache-->>Server: OK\n Server-->>Browser: 200 JWT Token\n Browser->>Server: GET /api/data (Bearer token)\n Server->>Cache: Validate session\n Cache-->>Server: Valid\n Server->>Database: Fetch data\n Database-->>Server: Result set\n Server-->>Browser: 200 JSON data\n\\`\\`\\`\n`,\n },\n {\n key: 'pie', labelKey: 'mdTplPieChart', icon: '🥧',\n content: `## Pie Chart\n\n\\`\\`\\`mermaid\npie title Tech Stack Usage 2025\n \"TypeScript\" : 35\n \"Python\" : 25\n \"Rust\" : 15\n \"Go\" : 12\n \"Java\" : 8\n \"Others\" : 5\n\\`\\`\\`\n`,\n },\n {\n key: 'gantt', labelKey: 'mdTplGantt', icon: '📊',\n content: `## Gantt Chart\n\n\\`\\`\\`mermaid\ngantt\n title Project Development Timeline\n dateFormat YYYY-MM-DD\n section Design\n UI/UX Design :a1, 2025-01-01, 20d\n API Design :a2, after a1, 10d\n section Frontend\n Component Library :b1, after a2, 25d\n Page Integration :b2, after b1, 15d\n Testing & Bug Fix :b3, after b2, 10d\n section Backend\n Core API Development :c1, after a2, 30d\n Database Optimization :c2, after c1, 10d\n section Deployment\n Staging Deploy :d1, after b3, 5d\n Production Release :milestone, after d1, 0d\n\\`\\`\\`\n`,\n },\n {\n key: 'xychart', labelKey: 'mdTplBarChart', icon: '📈',\n content: `## Bar Chart (xychart)\n\n\\`\\`\\`mermaid\nxychart-beta\n title \"Monthly Revenue (in thousands)\"\n x-axis [Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]\n y-axis \"Revenue (USD)\" 0 --> 120\n bar [52, 48, 61, 55, 72, 68, 85, 90, 78, 95, 102, 110]\n line [52, 48, 61, 55, 72, 68, 85, 90, 78, 95, 102, 110]\n\\`\\`\\`\n`,\n },\n {\n key: 'python', labelKey: 'mdTplPython', icon: '🐍',\n content: `## Python Example\n\n\\`\\`\\`python\nimport asyncio\nfrom dataclasses import dataclass, field\nfrom typing import AsyncIterator\n\n\n@dataclass\nclass DataPipeline:\n \"\"\"Async data processing pipeline.\"\"\"\n name: str\n buffer_size: int = 100\n _queue: asyncio.Queue = field(init=False)\n\n def __post_init__(self):\n self._queue = asyncio.Queue(maxsize=self.buffer_size)\n\n async def produce(self, items: list[int]) -> None:\n for item in items:\n transformed = item ** 2 + 2 * item + 1\n await self._queue.put(transformed)\n await self._queue.put(None) # sentinel\n\n async def consume(self) -> AsyncIterator[int]:\n while True:\n item = await self._queue.get()\n if item is None:\n break\n yield item\n\n async def run(self, data: list[int]) -> list[int]:\n results: list[int] = []\n producer = asyncio.create_task(self.produce(data))\n async for value in self.consume():\n results.append(value)\n await producer\n return results\n\n\nasync def main():\n pipeline = DataPipeline(name=\"squares\", buffer_size=50)\n data = list(range(1, 21))\n results = await pipeline.run(data)\n print(f\"Processed {len(results)} items: {results[:5]}...\")\n\n\nif __name__ == \"__main__\":\n asyncio.run(main())\n\\`\\`\\`\n`,\n },\n {\n key: 'typescript', labelKey: 'mdTplTypeScript', icon: '🟦',\n content: `## TypeScript Example\n\n\\`\\`\\`typescript\ninterface APIResponse<T> {\n data: T;\n status: number;\n message: string;\n timestamp: Date;\n}\n\ntype HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';\n\nclass TypedFetcher {\n private baseUrl: string;\n private headers: Record<string, string>;\n\n constructor(baseUrl: string, token?: string) {\n this.baseUrl = baseUrl;\n this.headers = {\n 'Content-Type': 'application/json',\n ...(token ? { Authorization: \\\\\\`Bearer \\\\\\${token}\\\\\\` } : {}),\n };\n }\n\n async request<T>(\n method: HttpMethod,\n path: string,\n body?: unknown,\n ): Promise<APIResponse<T>> {\n const response = await fetch(\\\\\\`\\\\\\${this.baseUrl}\\\\\\${path}\\\\\\`, {\n method,\n headers: this.headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n throw new Error(\\\\\\`HTTP \\\\\\${response.status}: \\\\\\${response.statusText}\\\\\\`);\n }\n\n return response.json() as Promise<APIResponse<T>>;\n }\n\n get<T>(path: string) { return this.request<T>('GET', path); }\n post<T>(path: string, body: unknown) { return this.request<T>('POST', path, body); }\n put<T>(path: string, body: unknown) { return this.request<T>('PUT', path, body); }\n delete<T>(path: string) { return this.request<T>('DELETE', path); }\n}\n\n// Usage\ninterface User {\n id: number;\n name: string;\n email: string;\n}\n\nconst api = new TypedFetcher('https://api.example.com', 'my-token');\nconst users = await api.get<User[]>('/users');\nconsole.log(users.data);\n\\`\\`\\`\n`,\n },\n {\n key: 'rust', labelKey: 'mdTplRust', icon: '🦀',\n content: `## Rust Example\n\n\\`\\`\\`rust\nuse std::collections::HashMap;\nuse std::sync::Arc;\nuse tokio::sync::RwLock;\n\n#[derive(Debug, Clone)]\nstruct CacheEntry<V: Clone> {\n value: V,\n expires_at: std::time::Instant,\n}\n\n#[derive(Clone)]\nstruct AsyncCache<V: Clone + Send + Sync + 'static> {\n store: Arc<RwLock<HashMap<String, CacheEntry<V>>>>,\n ttl: std::time::Duration,\n}\n\nimpl<V: Clone + Send + Sync + 'static> AsyncCache<V> {\n fn new(ttl_secs: u64) -> Self {\n Self {\n store: Arc::new(RwLock::new(HashMap::new())),\n ttl: std::time::Duration::from_secs(ttl_secs),\n }\n }\n\n async fn get(&self, key: &str) -> Option<V> {\n let store = self.store.read().await;\n store.get(key).and_then(|entry| {\n if entry.expires_at > std::time::Instant::now() {\n Some(entry.value.clone())\n } else {\n None\n }\n })\n }\n\n async fn set(&self, key: String, value: V) {\n let mut store = self.store.write().await;\n store.insert(key, CacheEntry {\n value,\n expires_at: std::time::Instant::now() + self.ttl,\n });\n }\n\n async fn cleanup(&self) -> usize {\n let mut store = self.store.write().await;\n let now = std::time::Instant::now();\n let before = store.len();\n store.retain(|_, entry| entry.expires_at > now);\n before - store.len()\n }\n}\n\n#[tokio::main]\nasync fn main() {\n let cache = AsyncCache::<String>::new(60);\n cache.set(\"hello\".into(), \"world\".into()).await;\n\n if let Some(val) = cache.get(\"hello\").await {\n println!(\"Got: {val}\");\n }\n}\n\\`\\`\\`\n`,\n },\n {\n key: 'math', labelKey: 'mdTplMath', icon: '🔢',\n content: `## Math Formulas (TeX)\n\n### Euler's Identity\n\n$$\ne^{i\\\\pi} + 1 = 0\n$$\n\n### Quadratic Formula\n\n$$\nx = \\\\frac{-b \\\\pm \\\\sqrt{b^2 - 4ac}}{2a}\n$$\n\n### Gaussian Integral\n\n$$\n\\\\int_{-\\\\infty}^{\\\\infty} e^{-x^2} \\\\, dx = \\\\sqrt{\\\\pi}\n$$\n\n### Maxwell's Equations\n\n$$\n\\\\nabla \\\\cdot \\\\mathbf{E} = \\\\frac{\\\\rho}{\\\\epsilon_0}\n$$\n\n$$\n\\\\nabla \\\\cdot \\\\mathbf{B} = 0\n$$\n\n$$\n\\\\nabla \\\\times \\\\mathbf{E} = -\\\\frac{\\\\partial \\\\mathbf{B}}{\\\\partial t}\n$$\n\n$$\n\\\\nabla \\\\times \\\\mathbf{B} = \\\\mu_0 \\\\mathbf{J} + \\\\mu_0 \\\\epsilon_0 \\\\frac{\\\\partial \\\\mathbf{E}}{\\\\partial t}\n$$\n\n### Taylor Series Expansion\n\n$$\nf(x) = \\\\sum_{n=0}^{\\\\infty} \\\\frac{f^{(n)}(a)}{n!}(x-a)^n\n$$\n\n### Matrix Notation\n\n$$\n\\\\mathbf{A} = \\\\begin{pmatrix} a_{11} & a_{12} & \\\\cdots & a_{1n} \\\\\\\\ a_{21} & a_{22} & \\\\cdots & a_{2n} \\\\\\\\ \\\\vdots & \\\\vdots & \\\\ddots & \\\\vdots \\\\\\\\ a_{m1} & a_{m2} & \\\\cdots & a_{mn} \\\\end{pmatrix}\n$$\n\n### Inline math: The identity $e^{i\\\\theta} = \\\\cos\\\\theta + i\\\\sin\\\\theta$ is known as Euler's formula.\n`,\n },\n {\n key: 'mixed', labelKey: 'mdTplMixed', icon: '🎨',\n content: `## Mixed Content Example\n\n### Architecture Overview\n\n\\`\\`\\`mermaid\ngraph LR\n Client[Client App] --> Gateway[API Gateway]\n Gateway --> Auth[Auth Service]\n Gateway --> Core[Core Service]\n Core --> DB[(PostgreSQL)]\n Core --> Cache[(Redis)]\n Auth --> DB\n\\`\\`\\`\n\n### Performance Formula\n\nThe response time $T$ is calculated as:\n\n$$\nT = T_{network} + T_{processing} + T_{db}\n$$\n\nwhere $T_{db} = O(\\\\log n)$ with proper indexing.\n\n### Implementation\n\n\\`\\`\\`python\nfrom fastapi import FastAPI, Depends\nfrom functools import lru_cache\n\napp = FastAPI()\n\n@lru_cache(maxsize=256)\ndef compute_heavy(n: int) -> float:\n \"\"\"Cached computation: O(log n) amortized.\"\"\"\n return sum(1.0 / i for i in range(1, n + 1))\n\n@app.get(\"/api/harmonic/{n}\")\nasync def harmonic(n: int):\n result = compute_heavy(n)\n return {\"n\": n, \"H_n\": round(result, 6)}\n\\`\\`\\`\n\n### Project Status\n\n\\`\\`\\`mermaid\npie title Sprint Progress\n \"Completed\" : 65\n \"In Progress\" : 20\n \"Blocked\" : 10\n \"Not Started\" : 5\n\\`\\`\\`\n`,\n },\n];\n\ninterface MarkdownTemplateMenuProps {\n labels: RichTextEditorLabels;\n onSelect: (content: string, focusEditor?: boolean) => void;\n}\n\nexport const MarkdownTemplateMenu: React.FC<MarkdownTemplateMenuProps> = ({ labels, onSelect }) => {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n const pointerType = useRef('');\n const select = (event: React.MouseEvent, content: string) => {\n // Touch insertion must not enter Android's native editing/IME focus path.\n const focusEditor = event.detail === 0 || pointerType.current !== 'touch';\n flushSync(() => setIsOpen(false));\n onSelect(content, focusEditor);\n };\n\n useEffect(() => {\n const handler = (e: PointerEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('pointerdown', handler);\n return () => document.removeEventListener('pointerdown', handler);\n }, []);\n\n return (\n <div ref={ref} className=\"rte-toolbar__template-menu\" onPointerDown={(event) => { pointerType.current = event.pointerType; }}>\n <button\n type=\"button\"\n className={`rte-toolbar__btn ${isOpen ? 'rte-toolbar__btn--active' : ''}`}\n aria-expanded={isOpen}\n onClick={() => setIsOpen(!isOpen)}\n title={labels.mdTemplates || 'Markdown Templates'}\n style={{ width: 'auto', padding: '0 6px', gap: '2px', display: 'inline-flex', alignItems: 'center' }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"8\" height=\"8\" rx=\"1.5\" />\n <rect x=\"13\" y=\"3\" width=\"8\" height=\"8\" rx=\"1.5\" />\n <rect x=\"3\" y=\"13\" width=\"8\" height=\"8\" rx=\"1.5\" />\n <path d=\"M17 14v6M14 17h6\" />\n </svg>\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n {isOpen && (\n <div className=\"rte-toolbar__template-dropdown\">\n <div className=\"rte-toolbar__template-group-label\">Mermaid</div>\n {MD_TEMPLATES.filter(t => ['flowchart', 'sequence', 'pie', 'gantt', 'xychart'].includes(t.key)).map(t => (\n <button\n key={t.key}\n type=\"button\"\n className=\"rte-toolbar__template-item\"\n onClick={(event) => select(event, t.content)}\n >\n <span className=\"rte-toolbar__template-icon\">{t.icon}</span>\n <span>{labels[t.labelKey] || t.labelKey}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Code</div>\n {MD_TEMPLATES.filter(t => ['python', 'typescript', 'rust'].includes(t.key)).map(t => (\n <button\n key={t.key}\n type=\"button\"\n className=\"rte-toolbar__template-item\"\n onClick={(event) => select(event, t.content)}\n >\n <span className=\"rte-toolbar__template-icon\">{t.icon}</span>\n <span>{labels[t.labelKey] || t.labelKey}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Math / Mixed</div>\n {MD_TEMPLATES.filter(t => ['math', 'mixed'].includes(t.key)).map(t => (\n <button\n key={t.key}\n type=\"button\"\n className=\"rte-toolbar__template-item\"\n onClick={(event) => select(event, t.content)}\n >\n <span className=\"rte-toolbar__template-icon\">{t.icon}</span>\n <span>{labels[t.labelKey] || t.labelKey}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MarkdownTemplates.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport { flushSync } from 'react-dom';\nimport type { RichTextEditorLabels } from '../types';\nimport { useAnchoredDropdown } from './useAnchoredDropdown';\n\nexport const MD_TEMPLATES: { key: string; labelKey: keyof RichTextEditorLabels; icon: string; content: string }[] = [\n {\n key: 'flowchart', labelKey: 'mdTplFlowchart', icon: '🔀',\n content: `## Flowchart\n\n\\`\\`\\`mermaid\ngraph TD\n A[Start] --> B{Is it valid?}\n B -->|Yes| C[Process Data]\n B -->|No| D[Show Error]\n C --> E[Save to DB]\n E --> F[Send Response]\n D --> G[Log Warning]\n G --> A\n F --> H[End]\n\\`\\`\\`\n`,\n },\n {\n key: 'sequence', labelKey: 'mdTplSequence', icon: '🔄',\n content: `## Sequence Diagram\n\n\\`\\`\\`mermaid\nsequenceDiagram\n participant Browser\n participant Server\n participant Database\n participant Cache\n\n Browser->>Server: POST /api/login\n Server->>Database: Query user\n Database-->>Server: User record\n Server->>Cache: Store session\n Cache-->>Server: OK\n Server-->>Browser: 200 JWT Token\n Browser->>Server: GET /api/data (Bearer token)\n Server->>Cache: Validate session\n Cache-->>Server: Valid\n Server->>Database: Fetch data\n Database-->>Server: Result set\n Server-->>Browser: 200 JSON data\n\\`\\`\\`\n`,\n },\n {\n key: 'pie', labelKey: 'mdTplPieChart', icon: '🥧',\n content: `## Pie Chart\n\n\\`\\`\\`mermaid\npie title Tech Stack Usage 2025\n \"TypeScript\" : 35\n \"Python\" : 25\n \"Rust\" : 15\n \"Go\" : 12\n \"Java\" : 8\n \"Others\" : 5\n\\`\\`\\`\n`,\n },\n {\n key: 'gantt', labelKey: 'mdTplGantt', icon: '📊',\n content: `## Gantt Chart\n\n\\`\\`\\`mermaid\ngantt\n title Project Development Timeline\n dateFormat YYYY-MM-DD\n section Design\n UI/UX Design :a1, 2025-01-01, 20d\n API Design :a2, after a1, 10d\n section Frontend\n Component Library :b1, after a2, 25d\n Page Integration :b2, after b1, 15d\n Testing & Bug Fix :b3, after b2, 10d\n section Backend\n Core API Development :c1, after a2, 30d\n Database Optimization :c2, after c1, 10d\n section Deployment\n Staging Deploy :d1, after b3, 5d\n Production Release :milestone, after d1, 0d\n\\`\\`\\`\n`,\n },\n {\n key: 'xychart', labelKey: 'mdTplBarChart', icon: '📈',\n content: `## Bar Chart (xychart)\n\n\\`\\`\\`mermaid\nxychart-beta\n title \"Monthly Revenue (in thousands)\"\n x-axis [Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]\n y-axis \"Revenue (USD)\" 0 --> 120\n bar [52, 48, 61, 55, 72, 68, 85, 90, 78, 95, 102, 110]\n line [52, 48, 61, 55, 72, 68, 85, 90, 78, 95, 102, 110]\n\\`\\`\\`\n`,\n },\n {\n key: 'python', labelKey: 'mdTplPython', icon: '🐍',\n content: `## Python Example\n\n\\`\\`\\`python\nimport asyncio\nfrom dataclasses import dataclass, field\nfrom typing import AsyncIterator\n\n\n@dataclass\nclass DataPipeline:\n \"\"\"Async data processing pipeline.\"\"\"\n name: str\n buffer_size: int = 100\n _queue: asyncio.Queue = field(init=False)\n\n def __post_init__(self):\n self._queue = asyncio.Queue(maxsize=self.buffer_size)\n\n async def produce(self, items: list[int]) -> None:\n for item in items:\n transformed = item ** 2 + 2 * item + 1\n await self._queue.put(transformed)\n await self._queue.put(None) # sentinel\n\n async def consume(self) -> AsyncIterator[int]:\n while True:\n item = await self._queue.get()\n if item is None:\n break\n yield item\n\n async def run(self, data: list[int]) -> list[int]:\n results: list[int] = []\n producer = asyncio.create_task(self.produce(data))\n async for value in self.consume():\n results.append(value)\n await producer\n return results\n\n\nasync def main():\n pipeline = DataPipeline(name=\"squares\", buffer_size=50)\n data = list(range(1, 21))\n results = await pipeline.run(data)\n print(f\"Processed {len(results)} items: {results[:5]}...\")\n\n\nif __name__ == \"__main__\":\n asyncio.run(main())\n\\`\\`\\`\n`,\n },\n {\n key: 'typescript', labelKey: 'mdTplTypeScript', icon: '🟦',\n content: `## TypeScript Example\n\n\\`\\`\\`typescript\ninterface APIResponse<T> {\n data: T;\n status: number;\n message: string;\n timestamp: Date;\n}\n\ntype HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';\n\nclass TypedFetcher {\n private baseUrl: string;\n private headers: Record<string, string>;\n\n constructor(baseUrl: string, token?: string) {\n this.baseUrl = baseUrl;\n this.headers = {\n 'Content-Type': 'application/json',\n ...(token ? { Authorization: \\\\\\`Bearer \\\\\\${token}\\\\\\` } : {}),\n };\n }\n\n async request<T>(\n method: HttpMethod,\n path: string,\n body?: unknown,\n ): Promise<APIResponse<T>> {\n const response = await fetch(\\\\\\`\\\\\\${this.baseUrl}\\\\\\${path}\\\\\\`, {\n method,\n headers: this.headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n throw new Error(\\\\\\`HTTP \\\\\\${response.status}: \\\\\\${response.statusText}\\\\\\`);\n }\n\n return response.json() as Promise<APIResponse<T>>;\n }\n\n get<T>(path: string) { return this.request<T>('GET', path); }\n post<T>(path: string, body: unknown) { return this.request<T>('POST', path, body); }\n put<T>(path: string, body: unknown) { return this.request<T>('PUT', path, body); }\n delete<T>(path: string) { return this.request<T>('DELETE', path); }\n}\n\n// Usage\ninterface User {\n id: number;\n name: string;\n email: string;\n}\n\nconst api = new TypedFetcher('https://api.example.com', 'my-token');\nconst users = await api.get<User[]>('/users');\nconsole.log(users.data);\n\\`\\`\\`\n`,\n },\n {\n key: 'rust', labelKey: 'mdTplRust', icon: '🦀',\n content: `## Rust Example\n\n\\`\\`\\`rust\nuse std::collections::HashMap;\nuse std::sync::Arc;\nuse tokio::sync::RwLock;\n\n#[derive(Debug, Clone)]\nstruct CacheEntry<V: Clone> {\n value: V,\n expires_at: std::time::Instant,\n}\n\n#[derive(Clone)]\nstruct AsyncCache<V: Clone + Send + Sync + 'static> {\n store: Arc<RwLock<HashMap<String, CacheEntry<V>>>>,\n ttl: std::time::Duration,\n}\n\nimpl<V: Clone + Send + Sync + 'static> AsyncCache<V> {\n fn new(ttl_secs: u64) -> Self {\n Self {\n store: Arc::new(RwLock::new(HashMap::new())),\n ttl: std::time::Duration::from_secs(ttl_secs),\n }\n }\n\n async fn get(&self, key: &str) -> Option<V> {\n let store = self.store.read().await;\n store.get(key).and_then(|entry| {\n if entry.expires_at > std::time::Instant::now() {\n Some(entry.value.clone())\n } else {\n None\n }\n })\n }\n\n async fn set(&self, key: String, value: V) {\n let mut store = self.store.write().await;\n store.insert(key, CacheEntry {\n value,\n expires_at: std::time::Instant::now() + self.ttl,\n });\n }\n\n async fn cleanup(&self) -> usize {\n let mut store = self.store.write().await;\n let now = std::time::Instant::now();\n let before = store.len();\n store.retain(|_, entry| entry.expires_at > now);\n before - store.len()\n }\n}\n\n#[tokio::main]\nasync fn main() {\n let cache = AsyncCache::<String>::new(60);\n cache.set(\"hello\".into(), \"world\".into()).await;\n\n if let Some(val) = cache.get(\"hello\").await {\n println!(\"Got: {val}\");\n }\n}\n\\`\\`\\`\n`,\n },\n {\n key: 'math', labelKey: 'mdTplMath', icon: '🔢',\n content: `## Math Formulas (TeX)\n\n### Euler's Identity\n\n$$\ne^{i\\\\pi} + 1 = 0\n$$\n\n### Quadratic Formula\n\n$$\nx = \\\\frac{-b \\\\pm \\\\sqrt{b^2 - 4ac}}{2a}\n$$\n\n### Gaussian Integral\n\n$$\n\\\\int_{-\\\\infty}^{\\\\infty} e^{-x^2} \\\\, dx = \\\\sqrt{\\\\pi}\n$$\n\n### Maxwell's Equations\n\n$$\n\\\\nabla \\\\cdot \\\\mathbf{E} = \\\\frac{\\\\rho}{\\\\epsilon_0}\n$$\n\n$$\n\\\\nabla \\\\cdot \\\\mathbf{B} = 0\n$$\n\n$$\n\\\\nabla \\\\times \\\\mathbf{E} = -\\\\frac{\\\\partial \\\\mathbf{B}}{\\\\partial t}\n$$\n\n$$\n\\\\nabla \\\\times \\\\mathbf{B} = \\\\mu_0 \\\\mathbf{J} + \\\\mu_0 \\\\epsilon_0 \\\\frac{\\\\partial \\\\mathbf{E}}{\\\\partial t}\n$$\n\n### Taylor Series Expansion\n\n$$\nf(x) = \\\\sum_{n=0}^{\\\\infty} \\\\frac{f^{(n)}(a)}{n!}(x-a)^n\n$$\n\n### Matrix Notation\n\n$$\n\\\\mathbf{A} = \\\\begin{pmatrix} a_{11} & a_{12} & \\\\cdots & a_{1n} \\\\\\\\ a_{21} & a_{22} & \\\\cdots & a_{2n} \\\\\\\\ \\\\vdots & \\\\vdots & \\\\ddots & \\\\vdots \\\\\\\\ a_{m1} & a_{m2} & \\\\cdots & a_{mn} \\\\end{pmatrix}\n$$\n\n### Inline math: The identity $e^{i\\\\theta} = \\\\cos\\\\theta + i\\\\sin\\\\theta$ is known as Euler's formula.\n`,\n },\n {\n key: 'mixed', labelKey: 'mdTplMixed', icon: '🎨',\n content: `## Mixed Content Example\n\n### Architecture Overview\n\n\\`\\`\\`mermaid\ngraph LR\n Client[Client App] --> Gateway[API Gateway]\n Gateway --> Auth[Auth Service]\n Gateway --> Core[Core Service]\n Core --> DB[(PostgreSQL)]\n Core --> Cache[(Redis)]\n Auth --> DB\n\\`\\`\\`\n\n### Performance Formula\n\nThe response time $T$ is calculated as:\n\n$$\nT = T_{network} + T_{processing} + T_{db}\n$$\n\nwhere $T_{db} = O(\\\\log n)$ with proper indexing.\n\n### Implementation\n\n\\`\\`\\`python\nfrom fastapi import FastAPI, Depends\nfrom functools import lru_cache\n\napp = FastAPI()\n\n@lru_cache(maxsize=256)\ndef compute_heavy(n: int) -> float:\n \"\"\"Cached computation: O(log n) amortized.\"\"\"\n return sum(1.0 / i for i in range(1, n + 1))\n\n@app.get(\"/api/harmonic/{n}\")\nasync def harmonic(n: int):\n result = compute_heavy(n)\n return {\"n\": n, \"H_n\": round(result, 6)}\n\\`\\`\\`\n\n### Project Status\n\n\\`\\`\\`mermaid\npie title Sprint Progress\n \"Completed\" : 65\n \"In Progress\" : 20\n \"Blocked\" : 10\n \"Not Started\" : 5\n\\`\\`\\`\n`,\n },\n];\n\ninterface MarkdownTemplateMenuProps {\n labels: RichTextEditorLabels;\n onSelect: (content: string, focusEditor?: boolean) => void;\n}\n\nexport const MarkdownTemplateMenu: React.FC<MarkdownTemplateMenuProps> = ({ labels, onSelect }) => {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const dropdownStyle = useAnchoredDropdown(isOpen, triggerRef, dropdownRef);\n const pointerType = useRef('');\n const select = (event: React.MouseEvent, content: string) => {\n // Touch insertion must not enter Android's native editing/IME focus path.\n const focusEditor = event.detail === 0 || pointerType.current !== 'touch';\n flushSync(() => setIsOpen(false));\n onSelect(content, focusEditor);\n };\n\n useEffect(() => {\n const handler = (e: PointerEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('pointerdown', handler);\n return () => document.removeEventListener('pointerdown', handler);\n }, []);\n\n return (\n <div ref={ref} className=\"rte-toolbar__template-menu\" onPointerDown={(event) => { pointerType.current = event.pointerType; }}>\n <button\n type=\"button\"\n ref={triggerRef}\n className={`rte-toolbar__btn ${isOpen ? 'rte-toolbar__btn--active' : ''}`}\n aria-expanded={isOpen}\n onClick={() => setIsOpen(!isOpen)}\n title={labels.mdTemplates || 'Markdown Templates'}\n style={{ width: 'auto', padding: '0 6px', gap: '2px', display: 'inline-flex', alignItems: 'center' }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"8\" height=\"8\" rx=\"1.5\" />\n <rect x=\"13\" y=\"3\" width=\"8\" height=\"8\" rx=\"1.5\" />\n <rect x=\"3\" y=\"13\" width=\"8\" height=\"8\" rx=\"1.5\" />\n <path d=\"M17 14v6M14 17h6\" />\n </svg>\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n {isOpen && (\n <div ref={dropdownRef} className=\"rte-toolbar__template-dropdown\" style={dropdownStyle}>\n <div className=\"rte-toolbar__template-group-label\">Mermaid</div>\n {MD_TEMPLATES.filter(t => ['flowchart', 'sequence', 'pie', 'gantt', 'xychart'].includes(t.key)).map(t => (\n <button\n key={t.key}\n type=\"button\"\n className=\"rte-toolbar__template-item\"\n onClick={(event) => select(event, t.content)}\n >\n <span className=\"rte-toolbar__template-icon\">{t.icon}</span>\n <span>{labels[t.labelKey] || t.labelKey}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Code</div>\n {MD_TEMPLATES.filter(t => ['python', 'typescript', 'rust'].includes(t.key)).map(t => (\n <button\n key={t.key}\n type=\"button\"\n className=\"rte-toolbar__template-item\"\n onClick={(event) => select(event, t.content)}\n >\n <span className=\"rte-toolbar__template-icon\">{t.icon}</span>\n <span>{labels[t.labelKey] || t.labelKey}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Math / Mixed</div>\n {MD_TEMPLATES.filter(t => ['math', 'mixed'].includes(t.key)).map(t => (\n <button\n key={t.key}\n type=\"button\"\n className=\"rte-toolbar__template-item\"\n onClick={(event) => select(event, t.content)}\n >\n <span className=\"rte-toolbar__template-icon\">{t.icon}</span>\n <span>{labels[t.labelKey] || t.labelKey}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,79 +1,81 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useAnchoredDropdown as e } from "./useAnchoredDropdown.js";
|
|
2
|
+
import { useEffect as t, useRef as n, useState as r } from "react";
|
|
3
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
3
4
|
//#region src/components/pro/RichTextEditor/Toolbar/TableOpsMenu.tsx
|
|
4
|
-
var
|
|
5
|
-
let [
|
|
6
|
-
|
|
5
|
+
var o = ({ editor: o, labels: s }) => {
|
|
6
|
+
let [c, l] = r(!1), u = n(null), d = n(null), f = n(null), p = e(c, d, f);
|
|
7
|
+
t(() => {
|
|
7
8
|
let e = (e) => {
|
|
8
|
-
|
|
9
|
+
u.current && !u.current.contains(e.target) && l(!1);
|
|
9
10
|
};
|
|
10
11
|
return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
|
|
11
12
|
}, []);
|
|
12
|
-
let
|
|
13
|
+
let m = o.isActive("table"), h = [
|
|
13
14
|
{
|
|
14
|
-
label:
|
|
15
|
-
action: () =>
|
|
15
|
+
label: s.tableAddColumnBefore || "Add Column Before",
|
|
16
|
+
action: () => o.chain().focus().addColumnBefore().run(),
|
|
16
17
|
icon: "⇤+"
|
|
17
18
|
},
|
|
18
19
|
{
|
|
19
|
-
label:
|
|
20
|
-
action: () =>
|
|
20
|
+
label: s.tableAddColumnAfter || "Add Column After",
|
|
21
|
+
action: () => o.chain().focus().addColumnAfter().run(),
|
|
21
22
|
icon: "+⇥"
|
|
22
23
|
},
|
|
23
24
|
{
|
|
24
|
-
label:
|
|
25
|
-
action: () =>
|
|
25
|
+
label: s.tableDeleteColumn || "Delete Column",
|
|
26
|
+
action: () => o.chain().focus().deleteColumn().run(),
|
|
26
27
|
icon: "−⫼"
|
|
27
28
|
},
|
|
28
29
|
{
|
|
29
|
-
label:
|
|
30
|
-
action: () =>
|
|
30
|
+
label: s.tableAddRowBefore || "Add Row Before",
|
|
31
|
+
action: () => o.chain().focus().addRowBefore().run(),
|
|
31
32
|
icon: "↑+"
|
|
32
33
|
},
|
|
33
34
|
{
|
|
34
|
-
label:
|
|
35
|
-
action: () =>
|
|
35
|
+
label: s.tableAddRowAfter || "Add Row After",
|
|
36
|
+
action: () => o.chain().focus().addRowAfter().run(),
|
|
36
37
|
icon: "+↓"
|
|
37
38
|
},
|
|
38
39
|
{
|
|
39
|
-
label:
|
|
40
|
-
action: () =>
|
|
40
|
+
label: s.tableDeleteRow || "Delete Row",
|
|
41
|
+
action: () => o.chain().focus().deleteRow().run(),
|
|
41
42
|
icon: "−═"
|
|
42
43
|
},
|
|
43
44
|
{
|
|
44
|
-
label:
|
|
45
|
-
action: () =>
|
|
45
|
+
label: s.tableMergeCells || "Merge Cells",
|
|
46
|
+
action: () => o.chain().focus().mergeCells().run(),
|
|
46
47
|
icon: "⊞"
|
|
47
48
|
},
|
|
48
49
|
{
|
|
49
|
-
label:
|
|
50
|
-
action: () =>
|
|
50
|
+
label: s.tableSplitCell || "Split Cell",
|
|
51
|
+
action: () => o.chain().focus().splitCell().run(),
|
|
51
52
|
icon: "⊟"
|
|
52
53
|
},
|
|
53
54
|
{
|
|
54
|
-
label:
|
|
55
|
-
action: () =>
|
|
55
|
+
label: s.tableDelete || "Delete Table",
|
|
56
|
+
action: () => o.chain().focus().deleteTable().run(),
|
|
56
57
|
icon: "🗑"
|
|
57
58
|
}
|
|
58
59
|
];
|
|
59
|
-
return /* @__PURE__ */
|
|
60
|
-
ref:
|
|
60
|
+
return /* @__PURE__ */ a("div", {
|
|
61
|
+
ref: u,
|
|
61
62
|
className: "rte-toolbar__template-menu",
|
|
62
|
-
children: [/* @__PURE__ */
|
|
63
|
+
children: [/* @__PURE__ */ a("button", {
|
|
63
64
|
type: "button",
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
ref: d,
|
|
66
|
+
className: `rte-toolbar__btn ${c ? "rte-toolbar__btn--active" : ""}`,
|
|
67
|
+
onClick: () => l(!c),
|
|
68
|
+
disabled: !m,
|
|
69
|
+
title: s.tableOps || "Table Operations",
|
|
68
70
|
style: {
|
|
69
71
|
width: "auto",
|
|
70
72
|
padding: "0 6px",
|
|
71
73
|
gap: "2px",
|
|
72
74
|
display: "inline-flex",
|
|
73
75
|
alignItems: "center",
|
|
74
|
-
opacity:
|
|
76
|
+
opacity: m ? 1 : .4
|
|
75
77
|
},
|
|
76
|
-
children: [/* @__PURE__ */
|
|
78
|
+
children: [/* @__PURE__ */ a("svg", {
|
|
77
79
|
width: "16",
|
|
78
80
|
height: "16",
|
|
79
81
|
viewBox: "0 0 24 24",
|
|
@@ -83,115 +85,117 @@ var a = ({ editor: a, labels: o }) => {
|
|
|
83
85
|
strokeLinecap: "round",
|
|
84
86
|
strokeLinejoin: "round",
|
|
85
87
|
children: [
|
|
86
|
-
/* @__PURE__ */
|
|
88
|
+
/* @__PURE__ */ i("rect", {
|
|
87
89
|
x: "3",
|
|
88
90
|
y: "3",
|
|
89
91
|
width: "18",
|
|
90
92
|
height: "18",
|
|
91
93
|
rx: "2"
|
|
92
94
|
}),
|
|
93
|
-
/* @__PURE__ */
|
|
95
|
+
/* @__PURE__ */ i("line", {
|
|
94
96
|
x1: "3",
|
|
95
97
|
y1: "9",
|
|
96
98
|
x2: "21",
|
|
97
99
|
y2: "9"
|
|
98
100
|
}),
|
|
99
|
-
/* @__PURE__ */
|
|
101
|
+
/* @__PURE__ */ i("line", {
|
|
100
102
|
x1: "3",
|
|
101
103
|
y1: "15",
|
|
102
104
|
x2: "21",
|
|
103
105
|
y2: "15"
|
|
104
106
|
}),
|
|
105
|
-
/* @__PURE__ */
|
|
107
|
+
/* @__PURE__ */ i("line", {
|
|
106
108
|
x1: "9",
|
|
107
109
|
y1: "3",
|
|
108
110
|
x2: "9",
|
|
109
111
|
y2: "21"
|
|
110
112
|
}),
|
|
111
|
-
/* @__PURE__ */
|
|
113
|
+
/* @__PURE__ */ i("line", {
|
|
112
114
|
x1: "15",
|
|
113
115
|
y1: "3",
|
|
114
116
|
x2: "15",
|
|
115
117
|
y2: "21"
|
|
116
118
|
})
|
|
117
119
|
]
|
|
118
|
-
}), /* @__PURE__ */
|
|
120
|
+
}), /* @__PURE__ */ i("svg", {
|
|
119
121
|
width: "10",
|
|
120
122
|
height: "10",
|
|
121
123
|
viewBox: "0 0 24 24",
|
|
122
124
|
fill: "none",
|
|
123
125
|
stroke: "currentColor",
|
|
124
126
|
strokeWidth: "2.5",
|
|
125
|
-
children: /* @__PURE__ */
|
|
127
|
+
children: /* @__PURE__ */ i("polyline", { points: "6 9 12 15 18 9" })
|
|
126
128
|
})]
|
|
127
|
-
}),
|
|
129
|
+
}), c && m && /* @__PURE__ */ a("div", {
|
|
130
|
+
ref: f,
|
|
128
131
|
className: "rte-toolbar__template-dropdown",
|
|
132
|
+
style: p,
|
|
129
133
|
children: [
|
|
130
|
-
/* @__PURE__ */
|
|
134
|
+
/* @__PURE__ */ i("div", {
|
|
131
135
|
className: "rte-toolbar__template-group-label",
|
|
132
136
|
children: "Columns"
|
|
133
137
|
}),
|
|
134
|
-
|
|
138
|
+
h.slice(0, 3).map((e, t) => /* @__PURE__ */ a("button", {
|
|
135
139
|
type: "button",
|
|
136
140
|
className: "rte-toolbar__template-item",
|
|
137
141
|
onClick: () => {
|
|
138
|
-
e.action(),
|
|
142
|
+
e.action(), l(!1);
|
|
139
143
|
},
|
|
140
|
-
children: [/* @__PURE__ */
|
|
144
|
+
children: [/* @__PURE__ */ i("span", {
|
|
141
145
|
className: "rte-toolbar__template-icon",
|
|
142
146
|
children: e.icon
|
|
143
|
-
}), /* @__PURE__ */
|
|
147
|
+
}), /* @__PURE__ */ i("span", { children: e.label })]
|
|
144
148
|
}, t)),
|
|
145
|
-
/* @__PURE__ */
|
|
149
|
+
/* @__PURE__ */ i("div", {
|
|
146
150
|
className: "rte-toolbar__template-group-label",
|
|
147
151
|
children: "Rows"
|
|
148
152
|
}),
|
|
149
|
-
|
|
153
|
+
h.slice(3, 6).map((e, t) => /* @__PURE__ */ a("button", {
|
|
150
154
|
type: "button",
|
|
151
155
|
className: "rte-toolbar__template-item",
|
|
152
156
|
onClick: () => {
|
|
153
|
-
e.action(),
|
|
157
|
+
e.action(), l(!1);
|
|
154
158
|
},
|
|
155
|
-
children: [/* @__PURE__ */
|
|
159
|
+
children: [/* @__PURE__ */ i("span", {
|
|
156
160
|
className: "rte-toolbar__template-icon",
|
|
157
161
|
children: e.icon
|
|
158
|
-
}), /* @__PURE__ */
|
|
162
|
+
}), /* @__PURE__ */ i("span", { children: e.label })]
|
|
159
163
|
}, t)),
|
|
160
|
-
/* @__PURE__ */
|
|
164
|
+
/* @__PURE__ */ i("div", {
|
|
161
165
|
className: "rte-toolbar__template-group-label",
|
|
162
166
|
children: "Merge / Split"
|
|
163
167
|
}),
|
|
164
|
-
|
|
168
|
+
h.slice(6, 8).map((e, t) => /* @__PURE__ */ a("button", {
|
|
165
169
|
type: "button",
|
|
166
170
|
className: "rte-toolbar__template-item",
|
|
167
171
|
onClick: () => {
|
|
168
|
-
e.action(),
|
|
172
|
+
e.action(), l(!1);
|
|
169
173
|
},
|
|
170
|
-
children: [/* @__PURE__ */
|
|
174
|
+
children: [/* @__PURE__ */ i("span", {
|
|
171
175
|
className: "rte-toolbar__template-icon",
|
|
172
176
|
children: e.icon
|
|
173
|
-
}), /* @__PURE__ */
|
|
177
|
+
}), /* @__PURE__ */ i("span", { children: e.label })]
|
|
174
178
|
}, t)),
|
|
175
|
-
/* @__PURE__ */
|
|
179
|
+
/* @__PURE__ */ i("div", {
|
|
176
180
|
className: "rte-toolbar__template-group-label",
|
|
177
181
|
children: "Table"
|
|
178
182
|
}),
|
|
179
|
-
|
|
183
|
+
h.slice(8).map((e, t) => /* @__PURE__ */ a("button", {
|
|
180
184
|
type: "button",
|
|
181
185
|
className: "rte-toolbar__template-item rte-toolbar__template-item--danger",
|
|
182
186
|
onClick: () => {
|
|
183
|
-
e.action(),
|
|
187
|
+
e.action(), l(!1);
|
|
184
188
|
},
|
|
185
|
-
children: [/* @__PURE__ */
|
|
189
|
+
children: [/* @__PURE__ */ i("span", {
|
|
186
190
|
className: "rte-toolbar__template-icon",
|
|
187
191
|
children: e.icon
|
|
188
|
-
}), /* @__PURE__ */
|
|
192
|
+
}), /* @__PURE__ */ i("span", { children: e.label })]
|
|
189
193
|
}, t))
|
|
190
194
|
]
|
|
191
195
|
})]
|
|
192
196
|
});
|
|
193
197
|
};
|
|
194
198
|
//#endregion
|
|
195
|
-
export {
|
|
199
|
+
export { o as TableOpsMenu };
|
|
196
200
|
|
|
197
201
|
//# sourceMappingURL=TableOpsMenu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableOpsMenu.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/TableOpsMenu.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport type { RichTextEditorLabels } from '../types';\n\ninterface TableOpsMenuProps {\n editor: Editor;\n labels: RichTextEditorLabels;\n}\n\nexport const TableOpsMenu: React.FC<TableOpsMenuProps> = ({ editor, labels }) => {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, []);\n\n const isInTable = editor.isActive('table');\n\n const actions: { label: string; action: () => void; icon: string }[] = [\n { label: labels.tableAddColumnBefore || 'Add Column Before', action: () => editor.chain().focus().addColumnBefore().run(), icon: '⇤+' },\n { label: labels.tableAddColumnAfter || 'Add Column After', action: () => editor.chain().focus().addColumnAfter().run(), icon: '+⇥' },\n { label: labels.tableDeleteColumn || 'Delete Column', action: () => editor.chain().focus().deleteColumn().run(), icon: '−⫼' },\n { label: labels.tableAddRowBefore || 'Add Row Before', action: () => editor.chain().focus().addRowBefore().run(), icon: '↑+' },\n { label: labels.tableAddRowAfter || 'Add Row After', action: () => editor.chain().focus().addRowAfter().run(), icon: '+↓' },\n { label: labels.tableDeleteRow || 'Delete Row', action: () => editor.chain().focus().deleteRow().run(), icon: '−═' },\n { label: labels.tableMergeCells || 'Merge Cells', action: () => editor.chain().focus().mergeCells().run(), icon: '⊞' },\n { label: labels.tableSplitCell || 'Split Cell', action: () => editor.chain().focus().splitCell().run(), icon: '⊟' },\n { label: labels.tableDelete || 'Delete Table', action: () => editor.chain().focus().deleteTable().run(), icon: '🗑' },\n ];\n\n return (\n <div ref={ref} className=\"rte-toolbar__template-menu\">\n <button\n type=\"button\"\n className={`rte-toolbar__btn ${isOpen ? 'rte-toolbar__btn--active' : ''}`}\n onClick={() => setIsOpen(!isOpen)}\n disabled={!isInTable}\n title={labels.tableOps || 'Table Operations'}\n style={{ width: 'auto', padding: '0 6px', gap: '2px', display: 'inline-flex', alignItems: 'center', opacity: isInTable ? 1 : 0.4 }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" />\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\" /><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\" />\n <line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\" /><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\" />\n </svg>\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n {isOpen && isInTable && (\n <div className=\"rte-toolbar__template-dropdown\">\n <div className=\"rte-toolbar__template-group-label\">Columns</div>\n {actions.slice(0, 3).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Rows</div>\n {actions.slice(3, 6).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Merge / Split</div>\n {actions.slice(6, 8).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Table</div>\n {actions.slice(8).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item rte-toolbar__template-item--danger\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"TableOpsMenu.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/TableOpsMenu.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport type { RichTextEditorLabels } from '../types';\nimport { useAnchoredDropdown } from './useAnchoredDropdown';\n\ninterface TableOpsMenuProps {\n editor: Editor;\n labels: RichTextEditorLabels;\n}\n\nexport const TableOpsMenu: React.FC<TableOpsMenuProps> = ({ editor, labels }) => {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const dropdownStyle = useAnchoredDropdown(isOpen, triggerRef, dropdownRef);\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, []);\n\n const isInTable = editor.isActive('table');\n\n const actions: { label: string; action: () => void; icon: string }[] = [\n { label: labels.tableAddColumnBefore || 'Add Column Before', action: () => editor.chain().focus().addColumnBefore().run(), icon: '⇤+' },\n { label: labels.tableAddColumnAfter || 'Add Column After', action: () => editor.chain().focus().addColumnAfter().run(), icon: '+⇥' },\n { label: labels.tableDeleteColumn || 'Delete Column', action: () => editor.chain().focus().deleteColumn().run(), icon: '−⫼' },\n { label: labels.tableAddRowBefore || 'Add Row Before', action: () => editor.chain().focus().addRowBefore().run(), icon: '↑+' },\n { label: labels.tableAddRowAfter || 'Add Row After', action: () => editor.chain().focus().addRowAfter().run(), icon: '+↓' },\n { label: labels.tableDeleteRow || 'Delete Row', action: () => editor.chain().focus().deleteRow().run(), icon: '−═' },\n { label: labels.tableMergeCells || 'Merge Cells', action: () => editor.chain().focus().mergeCells().run(), icon: '⊞' },\n { label: labels.tableSplitCell || 'Split Cell', action: () => editor.chain().focus().splitCell().run(), icon: '⊟' },\n { label: labels.tableDelete || 'Delete Table', action: () => editor.chain().focus().deleteTable().run(), icon: '🗑' },\n ];\n\n return (\n <div ref={ref} className=\"rte-toolbar__template-menu\">\n <button\n type=\"button\"\n ref={triggerRef}\n className={`rte-toolbar__btn ${isOpen ? 'rte-toolbar__btn--active' : ''}`}\n onClick={() => setIsOpen(!isOpen)}\n disabled={!isInTable}\n title={labels.tableOps || 'Table Operations'}\n style={{ width: 'auto', padding: '0 6px', gap: '2px', display: 'inline-flex', alignItems: 'center', opacity: isInTable ? 1 : 0.4 }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" />\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\" /><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\" />\n <line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\" /><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\" />\n </svg>\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n {isOpen && isInTable && (\n <div ref={dropdownRef} className=\"rte-toolbar__template-dropdown\" style={dropdownStyle}>\n <div className=\"rte-toolbar__template-group-label\">Columns</div>\n {actions.slice(0, 3).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Rows</div>\n {actions.slice(3, 6).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Merge / Split</div>\n {actions.slice(6, 8).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Table</div>\n {actions.slice(8).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item rte-toolbar__template-item--danger\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n};\n"],"mappings":"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"}
|