@tulip-systems/create-app 0.12.2 → 0.12.3

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 (41) hide show
  1. package/dist/templates/basic/package.json +5 -5
  2. package/dist/templates/code/package.json +31 -14
  3. package/dist/templates/code/src/app/admin/customers/[id]/(default)/@dashboard/page.tsx +2 -0
  4. package/dist/templates/code/src/app/admin/projects/[id]/(default)/page.tsx +2 -0
  5. package/dist/templates/code/src/app/admin/prospects/[id]/(default)/@dashboard/page.tsx +2 -0
  6. package/dist/templates/code/src/app/admin/tasks/[id]/(default)/@dashboard/page.tsx +6 -4
  7. package/dist/templates/code/src/lib/config/editor.ts +54 -0
  8. package/dist/templates/spark/package.json +30 -13
  9. package/dist/templates/spark/src/app/admin/assignments/[id]/(default)/@dashboard/page.tsx +2 -0
  10. package/dist/templates/spark/src/app/admin/companies/[id]/(default)/@dashboard/page.tsx +2 -0
  11. package/dist/templates/spark/src/app/admin/customers/[id]/(default)/@dashboard/page.tsx +2 -0
  12. package/dist/templates/spark/src/app/admin/emails/_components/send-email.tsx +5 -6
  13. package/dist/templates/spark/src/app/admin/executions/[id]/@dashboard/page.tsx +2 -0
  14. package/dist/templates/spark/src/app/admin/products/[id]/(preview)/page.tsx +2 -2
  15. package/dist/templates/spark/src/app/admin/products/[id]/dashboard/@dashboard/page.tsx +2 -0
  16. package/dist/templates/spark/src/app/admin/products/[id]/dashboard/editor/page.tsx +6 -8
  17. package/dist/templates/spark/src/app/admin/projects/[id]/(dashboard)/page.tsx +2 -0
  18. package/dist/templates/spark/src/app/admin/projects/[id]/messages/page.tsx +7 -1
  19. package/dist/templates/spark/src/app/admin/purchase-orders/[id]/(default)/@dashboard/page.tsx +2 -0
  20. package/dist/templates/spark/src/app/admin/purchase-orders/_config/columns-data.tsx +7 -1
  21. package/dist/templates/spark/src/app/admin/quotation-items/_config/columns-data.tsx +7 -1
  22. package/dist/templates/spark/src/app/admin/quotation-items/_config/columns-inline.tsx +2 -0
  23. package/dist/templates/spark/src/app/admin/quotations/[id]/(default)/@dashboard/page.tsx +2 -0
  24. package/dist/templates/spark/src/app/admin/run-tasks/_config/columns-data.tsx +7 -1
  25. package/dist/templates/spark/src/app/admin/runs/[id]/@dashboard/page.tsx +2 -0
  26. package/dist/templates/spark/src/app/admin/runs/[id]/reports/page.tsx +2 -0
  27. package/dist/templates/spark/src/app/admin/sales-invoice-items/_config/columns-data.tsx +7 -1
  28. package/dist/templates/spark/src/app/admin/sales-invoice-items/_config/columns-inline.tsx +2 -0
  29. package/dist/templates/spark/src/app/admin/sales-order-items/_config/columns-data.tsx +7 -1
  30. package/dist/templates/spark/src/app/admin/sales-order-items/_config/columns-inline.tsx +2 -0
  31. package/dist/templates/spark/src/app/admin/sales-orders/[id]/(default)/@dashboard/page.tsx +2 -0
  32. package/dist/templates/spark/src/app/admin/suppliers/[id]/@dashboard/page.tsx +2 -0
  33. package/dist/templates/spark/src/app/admin/tasks/_config/columns-data.tsx +7 -1
  34. package/dist/templates/spark/src/app/admin/tasks/_config/columns-inline.tsx +2 -0
  35. package/dist/templates/spark/src/app/admin/technical-sheets/[id]/page.tsx +2 -0
  36. package/dist/templates/spark/src/app/admin/technical-sheets/_config/columns-data.tsx +13 -2
  37. package/dist/templates/spark/src/app/admin/template-tasks/_config/columns-data.tsx +7 -1
  38. package/dist/templates/spark/src/app/admin/template-tasks/_config/columns-inline.tsx +2 -0
  39. package/dist/templates/spark/src/app/admin/templates/[id]/@dashboard/page.tsx +2 -0
  40. package/dist/templates/spark/src/lib/config/editor.ts +54 -0
  41. package/package.json +1 -1
@@ -25,11 +25,11 @@
25
25
  "@orpc/tanstack-query": "^1.14.15",
26
26
  "@tailwindcss/typography": "^0.5.20",
27
27
  "@tanstack/react-query": "^5.101.4",
28
- "@tulip-systems/app": "0.12.2",
29
- "@tulip-systems/auth": "0.12.2",
30
- "@tulip-systems/commands": "0.12.2",
31
- "@tulip-systems/core": "0.12.2",
32
- "@tulip-systems/ui": "0.12.2",
28
+ "@tulip-systems/app": "0.12.3",
29
+ "@tulip-systems/auth": "0.12.3",
30
+ "@tulip-systems/commands": "0.12.3",
31
+ "@tulip-systems/core": "0.12.3",
32
+ "@tulip-systems/ui": "0.12.3",
33
33
  "@vercel/functions": "^3.9.0",
34
34
  "better-auth": "^1.6.26",
35
35
  "class-variance-authority": "^0.7.1",
@@ -49,20 +49,37 @@
49
49
  "@tanstack/react-query": "^5.101.4",
50
50
  "@tanstack/react-table": "^8.21.3",
51
51
  "@tanstack/react-virtual": "^3.14.9",
52
- "@tulip-systems/ai": "0.12.2",
53
- "@tulip-systems/app": "0.12.2",
54
- "@tulip-systems/auth": "0.12.2",
55
- "@tulip-systems/commands": "0.12.2",
56
- "@tulip-systems/core": "0.12.2",
57
- "@tulip-systems/data-tables": "0.12.2",
58
- "@tulip-systems/drive": "0.12.2",
59
- "@tulip-systems/drive-google": "0.12.2",
60
- "@tulip-systems/editor": "0.12.2",
61
- "@tulip-systems/editor-storage": "0.12.2",
62
- "@tulip-systems/inline": "0.12.2",
63
- "@tulip-systems/query": "0.12.2",
64
- "@tulip-systems/storage": "0.12.2",
65
- "@tulip-systems/ui": "0.12.2",
52
+ "@tiptap/core": "^3.29.2",
53
+ "@tiptap/extension-blockquote": "^3.29.2",
54
+ "@tiptap/extension-bold": "^3.29.2",
55
+ "@tiptap/extension-document": "^3.29.2",
56
+ "@tiptap/extension-hard-break": "^3.29.2",
57
+ "@tiptap/extension-heading": "^3.29.2",
58
+ "@tiptap/extension-highlight": "^3.29.2",
59
+ "@tiptap/extension-horizontal-rule": "^3.29.2",
60
+ "@tiptap/extension-italic": "^3.29.2",
61
+ "@tiptap/extension-link": "^3.29.2",
62
+ "@tiptap/extension-list": "^3.29.2",
63
+ "@tiptap/extension-paragraph": "^3.29.2",
64
+ "@tiptap/extension-strike": "^3.29.2",
65
+ "@tiptap/extension-text": "^3.29.2",
66
+ "@tiptap/extension-text-style": "^3.29.2",
67
+ "@tiptap/extension-underline": "^3.29.2",
68
+ "@tiptap/extensions": "^3.29.2",
69
+ "@tulip-systems/ai": "0.12.3",
70
+ "@tulip-systems/app": "0.12.3",
71
+ "@tulip-systems/auth": "0.12.3",
72
+ "@tulip-systems/commands": "0.12.3",
73
+ "@tulip-systems/core": "0.12.3",
74
+ "@tulip-systems/data-tables": "0.12.3",
75
+ "@tulip-systems/drive": "0.12.3",
76
+ "@tulip-systems/drive-google": "0.12.3",
77
+ "@tulip-systems/editor": "0.12.3",
78
+ "@tulip-systems/editor-storage": "0.12.3",
79
+ "@tulip-systems/inline": "0.12.3",
80
+ "@tulip-systems/query": "0.12.3",
81
+ "@tulip-systems/storage": "0.12.3",
82
+ "@tulip-systems/ui": "0.12.3",
66
83
  "@uidotdev/usehooks": "^2.4.1",
67
84
  "@vercel/functions": "^3.9.0",
68
85
  "@vercel/otel": "^2.1.3",
@@ -11,6 +11,7 @@ import {
11
11
  import { DataList, DataListItem, DataListTitle, DataListValue } from "@tulip-systems/ui/data-list";
12
12
  import { use } from "react";
13
13
  import { z } from "zod";
14
+ import { richTextEditorPreset } from "@/lib/config/editor";
14
15
  import { orpc } from "@/server/router/client";
15
16
 
16
17
  const customerMutation = orpc.customers.update.mutationOptions();
@@ -130,6 +131,7 @@ export default function CustomerDetailPage(props: { params: Promise<{ id: string
130
131
  mutation={customerMutation}
131
132
  strategy={{ mutate: { on: "blur" }, validate: { blur: z.any().nullable() } }}
132
133
  className="min-h-40"
134
+ extensions={richTextEditorPreset}
133
135
  >
134
136
  <EditorMenuBubble />
135
137
  <EditorContent />
@@ -26,6 +26,7 @@ import { use } from "react";
26
26
  import { z } from "zod";
27
27
  import { InitiativeStatusField } from "@/app/admin/initiatives/_config/status";
28
28
  import { Icons } from "@/components/icons";
29
+ import { richTextEditorPreset } from "@/lib/config/editor";
29
30
  import { orpc } from "@/server/router/client";
30
31
  import { projectKeySchema } from "../../_lib/validators";
31
32
 
@@ -144,6 +145,7 @@ export default function ProjectDetailPage(props: PageProps<"/admin/projects/[id]
144
145
  mutation={projectMutation}
145
146
  strategy={{ mutate: { on: "change", debounceMs: 700 }, validate: { change: z.any() } }}
146
147
  className="min-h-80"
148
+ extensions={richTextEditorPreset}
147
149
  >
148
150
  <EditorMenuFixed />
149
151
  <EditorContent />
@@ -11,6 +11,7 @@ import {
11
11
  import { DataList, DataListItem, DataListTitle, DataListValue } from "@tulip-systems/ui/data-list";
12
12
  import { notFound } from "next/navigation";
13
13
  import { use } from "react";
14
+ import { richTextEditorPreset } from "@/lib/config/editor";
14
15
  import { orpc } from "@/server/router/client";
15
16
  import { updateProspectSchema } from "../../../_lib/validators";
16
17
 
@@ -164,6 +165,7 @@ export default function ProspectDashboardPage(props: { params: Promise<{ id: str
164
165
  validate: { change: updateProspectSchema.shape.notes },
165
166
  }}
166
167
  className="min-h-40"
168
+ extensions={richTextEditorPreset}
167
169
  >
168
170
  <EditorMenuBubble />
169
171
  <EditorContent />
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { useSuspenseQueries, useSuspenseQuery } from "@tanstack/react-query";
4
4
  import { EditorContent, EditorMenuFixed } from "@tulip-systems/editor/client";
5
- import { createFileHandlerUploadStrategy } from "@tulip-systems/editor-storage";
5
+ import { StorageUploadExtension } from "@tulip-systems/editor-storage";
6
6
  import {
7
7
  InlineComboboxDropdown,
8
8
  InlineEditor,
@@ -22,6 +22,7 @@ import { toast } from "@tulip-systems/ui/sonner";
22
22
  import { notFound } from "next/navigation";
23
23
  import { use } from "react";
24
24
  import { z } from "zod";
25
+ import { richTextEditorPreset } from "@/lib/config/editor";
25
26
  import { orpc } from "@/server/router/client";
26
27
  import { uploadClient } from "@/server/storage/client";
27
28
  import { storyPointsConfig } from "../../../_lib/constants";
@@ -175,8 +176,9 @@ export default function TaskDetailPage(props: PageProps<"/admin/tasks/[id]">) {
175
176
  mutate: { on: "change", debounceMs: 700 },
176
177
  validate: { change: z.any() },
177
178
  }}
178
- extensions={{
179
- fileHandler: createFileHandlerUploadStrategy({
179
+ extensions={[
180
+ ...richTextEditorPreset,
181
+ StorageUploadExtension.configure({
180
182
  allowedMimeTypes: ["image/png", "image/jpeg", "image/gif", "image/webp"],
181
183
  variables: {},
182
184
  uploadClient,
@@ -190,7 +192,7 @@ export default function TaskDetailPage(props: PageProps<"/admin/tasks/[id]">) {
190
192
  });
191
193
  },
192
194
  }),
193
- }}
195
+ ]}
194
196
  className="min-h-40"
195
197
  >
196
198
  <EditorMenuFixed />
@@ -0,0 +1,54 @@
1
+ import type { ResizableNodeViewDirection } from "@tiptap/core";
2
+ import Blockquote from "@tiptap/extension-blockquote";
3
+ import Bold from "@tiptap/extension-bold";
4
+ import Document from "@tiptap/extension-document";
5
+ import HardBreak from "@tiptap/extension-hard-break";
6
+ import Heading from "@tiptap/extension-heading";
7
+ import Highlight from "@tiptap/extension-highlight";
8
+ import HorizontalRule from "@tiptap/extension-horizontal-rule";
9
+ import Italic from "@tiptap/extension-italic";
10
+ import Link from "@tiptap/extension-link";
11
+ import { BulletList, ListItem, ListKeymap, OrderedList } from "@tiptap/extension-list";
12
+ import Paragraph from "@tiptap/extension-paragraph";
13
+ import Strike from "@tiptap/extension-strike";
14
+ import Text from "@tiptap/extension-text";
15
+ import { Color, TextStyle } from "@tiptap/extension-text-style";
16
+ import Underline from "@tiptap/extension-underline";
17
+ import { Dropcursor, Gapcursor, TrailingNode, UndoRedo } from "@tiptap/extensions";
18
+ import { defineEditorPreset } from "@tulip-systems/editor/client";
19
+ import { StorageImage } from "@tulip-systems/editor-storage";
20
+
21
+ const imageResizeOptions = {
22
+ enabled: true,
23
+ directions: ["left", "right"] as ResizableNodeViewDirection[],
24
+ minHeight: 50,
25
+ minWidth: 50,
26
+ alwaysPreserveAspectRatio: true,
27
+ };
28
+
29
+ export const richTextEditorPreset = defineEditorPreset([
30
+ Document,
31
+ Text,
32
+ Paragraph,
33
+ Blockquote,
34
+ HardBreak,
35
+ Heading,
36
+ HorizontalRule,
37
+ ListItem,
38
+ OrderedList,
39
+ BulletList,
40
+ StorageImage.configure({ resize: imageResizeOptions }),
41
+ Bold,
42
+ Italic,
43
+ Link,
44
+ Strike,
45
+ Underline,
46
+ Highlight.configure({ multicolor: true }),
47
+ Dropcursor,
48
+ Gapcursor,
49
+ UndoRedo,
50
+ ListKeymap,
51
+ TrailingNode,
52
+ TextStyle,
53
+ Color,
54
+ ]);
@@ -35,19 +35,36 @@
35
35
  "@tanstack/db": "^0.6.17",
36
36
  "@tanstack/react-query": "^5.101.4",
37
37
  "@tanstack/react-table": "^8.21.3",
38
- "@tulip-systems/app": "0.12.2",
39
- "@tulip-systems/auth": "0.12.2",
40
- "@tulip-systems/commands": "0.12.2",
41
- "@tulip-systems/core": "0.12.2",
42
- "@tulip-systems/data-tables": "0.12.2",
43
- "@tulip-systems/drive": "0.12.2",
44
- "@tulip-systems/drive-local": "0.12.2",
45
- "@tulip-systems/editor": "0.12.2",
46
- "@tulip-systems/editor-storage": "0.12.2",
47
- "@tulip-systems/inline": "0.12.2",
48
- "@tulip-systems/query": "0.12.2",
49
- "@tulip-systems/storage": "0.12.2",
50
- "@tulip-systems/ui": "0.12.2",
38
+ "@tiptap/core": "^3.29.2",
39
+ "@tiptap/extension-blockquote": "^3.29.2",
40
+ "@tiptap/extension-bold": "^3.29.2",
41
+ "@tiptap/extension-document": "^3.29.2",
42
+ "@tiptap/extension-hard-break": "^3.29.2",
43
+ "@tiptap/extension-heading": "^3.29.2",
44
+ "@tiptap/extension-highlight": "^3.29.2",
45
+ "@tiptap/extension-horizontal-rule": "^3.29.2",
46
+ "@tiptap/extension-italic": "^3.29.2",
47
+ "@tiptap/extension-link": "^3.29.2",
48
+ "@tiptap/extension-list": "^3.29.2",
49
+ "@tiptap/extension-paragraph": "^3.29.2",
50
+ "@tiptap/extension-strike": "^3.29.2",
51
+ "@tiptap/extension-text": "^3.29.2",
52
+ "@tiptap/extension-text-style": "^3.29.2",
53
+ "@tiptap/extension-underline": "^3.29.2",
54
+ "@tiptap/extensions": "^3.29.2",
55
+ "@tulip-systems/app": "0.12.3",
56
+ "@tulip-systems/auth": "0.12.3",
57
+ "@tulip-systems/commands": "0.12.3",
58
+ "@tulip-systems/core": "0.12.3",
59
+ "@tulip-systems/data-tables": "0.12.3",
60
+ "@tulip-systems/drive": "0.12.3",
61
+ "@tulip-systems/drive-local": "0.12.3",
62
+ "@tulip-systems/editor": "0.12.3",
63
+ "@tulip-systems/editor-storage": "0.12.3",
64
+ "@tulip-systems/inline": "0.12.3",
65
+ "@tulip-systems/query": "0.12.3",
66
+ "@tulip-systems/storage": "0.12.3",
67
+ "@tulip-systems/ui": "0.12.3",
51
68
  "@vercel/functions": "^3.9.0",
52
69
  "@zip.js/zip.js": "^2.8.34",
53
70
  "better-auth": "^1.6.26",
@@ -24,6 +24,7 @@ import { generateClientHref } from "@/app/admin/clients/_lib/helpers";
24
24
  import { EmployeeAvatars, EmployeeAvatarsLoading } from "@/app/admin/employees/_components/avatars";
25
25
  import { calculateTotalDuration } from "@/app/admin/registrations/_lib/helpers";
26
26
  import { Icons } from "@/components/icons";
27
+ import { richTextEditorPreset } from "@/lib/config/editor";
27
28
  import { orpc } from "@/server/router/client";
28
29
 
29
30
  export default function AssignmentDetailPage(props: PageProps<"/admin/assignments/[id]">) {
@@ -99,6 +100,7 @@ export default function AssignmentDetailPage(props: PageProps<"/admin/assignment
99
100
  validate: { change: z.any() },
100
101
  }}
101
102
  className="min-h-24"
103
+ extensions={richTextEditorPreset}
102
104
  >
103
105
  <EditorMenuBubble />
104
106
  <EditorContent />
@@ -21,6 +21,7 @@ import { DataList, DataListItem, DataListTitle, DataListValue } from "@tulip-sys
21
21
  import { notFound } from "next/navigation";
22
22
  import { use } from "react";
23
23
  import { VAT_RATES } from "@/app/admin/clients/_lib/constants";
24
+ import { richTextEditorPreset } from "@/lib/config/editor";
24
25
  import { orpc } from "@/server/router/client";
25
26
  import { updateCompanySchema } from "../../../_lib/validators";
26
27
 
@@ -227,6 +228,7 @@ export default function CustomerDetailPage(props: { params: Promise<{ id: string
227
228
  validate: { change: updateCompanySchema.shape.notes.unwrap() },
228
229
  }}
229
230
  className="min-h-40"
231
+ extensions={richTextEditorPreset}
230
232
  >
231
233
  <EditorMenuBubble />
232
234
  <EditorContent />
@@ -21,6 +21,7 @@ import { notFound } from "next/navigation";
21
21
  import { use } from "react";
22
22
  import { z } from "zod";
23
23
  import { VAT_RATES } from "@/app/admin/clients/_lib/constants";
24
+ import { richTextEditorPreset } from "@/lib/config/editor";
24
25
  import { orpc } from "@/server/router/client";
25
26
 
26
27
  export default function CustomerDetailPage(props: { params: Promise<{ id: string }> }) {
@@ -151,6 +152,7 @@ export default function CustomerDetailPage(props: { params: Promise<{ id: string
151
152
  validate: { change: z.any() },
152
153
  }}
153
154
  className="min-h-40"
155
+ extensions={richTextEditorPreset}
154
156
  >
155
157
  <EditorMenuBubble />
156
158
  <EditorContent />
@@ -31,6 +31,7 @@ import { notFound, useRouter } from "next/navigation";
31
31
  import { createContext, type PropsWithChildren, Suspense, use, useState } from "react";
32
32
  import { z } from "zod";
33
33
  import { Icons } from "@/components/icons";
34
+ import { richTextEditorPreset } from "@/lib/config/editor";
34
35
  import { orpc } from "@/server/router/client";
35
36
  import type { RouterOutputs } from "@/server/router/router";
36
37
  import { uploadClient } from "@/server/storage/client";
@@ -44,6 +45,9 @@ type SendEmailFormContextType = {
44
45
  };
45
46
 
46
47
  const SendEmailFormContext = createContext({} as SendEmailFormContextType);
48
+ const emailEditorPreset = richTextEditorPreset.filter(
49
+ (extension) => !["highlight", "color", "horizontalRule", "blockquote"].includes(extension.name),
50
+ );
47
51
 
48
52
  /**
49
53
  * Send email form
@@ -197,12 +201,7 @@ export function SendEmailFormBody() {
197
201
  }}
198
202
  className="min-h-120"
199
203
  disabled={data.status !== "draft"}
200
- extensions={{
201
- highlight: false,
202
- color: false,
203
- horizontalRule: false,
204
- blockquote: false,
205
- }}
204
+ extensions={emailEditorPreset}
206
205
  >
207
206
  {data.status === "draft" && <EditorMenuFixed />}
208
207
  <EditorContent />
@@ -22,6 +22,7 @@ import { use } from "react";
22
22
  import { z } from "zod";
23
23
  import { generateClientHref } from "@/app/admin/clients/_lib/helpers";
24
24
  import { calculateTotalDuration } from "@/app/admin/registrations/_lib/helpers";
25
+ import { richTextEditorPreset } from "@/lib/config/editor";
25
26
  import { orpc } from "@/server/router/client";
26
27
  import { ExecutionStatusField } from "../../_config/status";
27
28
 
@@ -98,6 +99,7 @@ export default function Page(props: PageProps<"/admin/executions/[id]">) {
98
99
  validate: { change: z.any() },
99
100
  }}
100
101
  className="min-h-24"
102
+ extensions={richTextEditorPreset}
101
103
  >
102
104
  <EditorMenuBubble />
103
105
  <EditorContent />
@@ -4,7 +4,6 @@ import { useSuspenseQueries } from "@tanstack/react-query";
4
4
  import { Allowed } from "@tulip-systems/auth/permissions/client";
5
5
  import { getLocalDriveFileUrl } from "@tulip-systems/drive-local";
6
6
  import { Editor, EditorContent } from "@tulip-systems/editor/client";
7
- import { createStorageEditorExtensions } from "@tulip-systems/editor-storage/client";
8
7
  import {
9
8
  Accordion,
10
9
  AccordionContent,
@@ -16,6 +15,7 @@ import { Separator } from "@tulip-systems/ui/separator";
16
15
  import Link from "next/link";
17
16
  import { notFound } from "next/navigation";
18
17
  import { use } from "react";
18
+ import { richTextEditorPreset } from "@/lib/config/editor";
19
19
  import { orpc } from "@/server/router/client";
20
20
  import { ImageCarousel } from "../../_components/image-carousel";
21
21
 
@@ -89,7 +89,7 @@ export default function ProductDetailPage(props: PageProps<"/admin/products/[id]
89
89
 
90
90
  <Editor
91
91
  value={productQuery.data.content ?? undefined}
92
- extensions={createStorageEditorExtensions()}
92
+ extensions={richTextEditorPreset}
93
93
  variant="preview"
94
94
  disabled
95
95
  >
@@ -16,6 +16,7 @@ import { DataStackColumn, DataStackLayout, DataStackRow } from "@tulip-systems/u
16
16
  import { notFound } from "next/navigation";
17
17
  import { use } from "react";
18
18
  import { z } from "zod";
19
+ import { richTextEditorPreset } from "@/lib/config/editor";
19
20
  import { orpc } from "@/server/router/client";
20
21
 
21
22
  export default function DetailPage(props: PageProps<"/admin/products/[id]/dashboard">) {
@@ -116,6 +117,7 @@ export default function DetailPage(props: PageProps<"/admin/products/[id]/dashbo
116
117
  validate: { change: z.any() },
117
118
  }}
118
119
  className="min-h-24"
120
+ extensions={richTextEditorPreset}
119
121
  >
120
122
  <EditorMenuBubble />
121
123
  <EditorContent />
@@ -3,15 +3,13 @@
3
3
  import { useSuspenseQuery } from "@tanstack/react-query";
4
4
  import { Allowed } from "@tulip-systems/auth/permissions/client";
5
5
  import { EditorContent, EditorMenuFixed } from "@tulip-systems/editor/client";
6
- import {
7
- createFileHandlerUploadStrategy,
8
- createStorageEditorExtensions,
9
- } from "@tulip-systems/editor-storage/client";
6
+ import { StorageUploadExtension } from "@tulip-systems/editor-storage/client";
10
7
  import { InlineEditor, InlineField, InlineFieldError } from "@tulip-systems/inline/client";
11
8
  import { toast } from "@tulip-systems/ui/sonner";
12
9
  import { notFound } from "next/navigation";
13
10
  import { use } from "react";
14
11
  import { z } from "zod";
12
+ import { richTextEditorPreset } from "@/lib/config/editor";
15
13
  import { orpc } from "@/server/router/client";
16
14
  import { uploadClient } from "@/server/storage/client";
17
15
 
@@ -30,9 +28,9 @@ export default function Page(props: PageProps<"/admin/products/[id]/dashboard/ed
30
28
  variables={(value) => ({ id, data: { content: value } })}
31
29
  mutation={orpc.products.update.mutationOptions()}
32
30
  className="min-h-64"
33
- extensions={{
34
- ...createStorageEditorExtensions(),
35
- fileHandler: createFileHandlerUploadStrategy({
31
+ extensions={[
32
+ ...richTextEditorPreset,
33
+ StorageUploadExtension.configure({
36
34
  allowedMimeTypes: ["image/png", "image/jpeg", "image/gif", "image/webp"],
37
35
  variables: {},
38
36
  uploadClient,
@@ -46,7 +44,7 @@ export default function Page(props: PageProps<"/admin/products/[id]/dashboard/ed
46
44
  });
47
45
  },
48
46
  }),
49
- }}
47
+ ]}
50
48
  strategy={{
51
49
  mutate: { on: "change", debounceMs: 700 },
52
50
  validate: { change: z.any() },
@@ -25,6 +25,7 @@ import { use } from "react";
25
25
  import { z } from "zod";
26
26
  import { generateClientHref } from "@/app/admin/clients/_lib/helpers";
27
27
  import { Icons } from "@/components/icons";
28
+ import { richTextEditorPreset } from "@/lib/config/editor";
28
29
  import { orpc } from "@/server/router/client";
29
30
 
30
31
  const toInlineDateValue = (value: Date | string | null | undefined): string | null => {
@@ -228,6 +229,7 @@ export default function ProjectDetailPage(props: PageProps<"/admin/projects/[id]
228
229
  validate: { change: z.any() },
229
230
  }}
230
231
  className="min-h-40"
232
+ extensions={richTextEditorPreset}
231
233
  >
232
234
  <EditorMenuBubble />
233
235
  <EditorContent />
@@ -19,6 +19,7 @@ import {
19
19
  import Link from "next/link";
20
20
  import { use, useDeferredValue, useMemo } from "react";
21
21
  import { runsFilters } from "@/app/admin/runs/_config/filters";
22
+ import { richTextEditorPreset } from "@/lib/config/editor";
22
23
  import { orpc } from "@/server/router/client";
23
24
 
24
25
  export default function ProjectDetailPage(props: PageProps<"/admin/projects/[id]/messages">) {
@@ -62,7 +63,12 @@ export default function ProjectDetailPage(props: PageProps<"/admin/projects/[id]
62
63
  </CardHeader>
63
64
 
64
65
  <CardContent>
65
- <Editor value={message ?? undefined} variant="preview" disabled>
66
+ <Editor
67
+ value={message ?? undefined}
68
+ variant="preview"
69
+ disabled
70
+ extensions={richTextEditorPreset}
71
+ >
66
72
  <EditorContent />
67
73
  </Editor>
68
74
  </CardContent>
@@ -16,6 +16,7 @@ import { notFound } from "next/navigation";
16
16
  import { use } from "react";
17
17
  import { z } from "zod";
18
18
  import { Icons } from "@/components/icons";
19
+ import { richTextEditorPreset } from "@/lib/config/editor";
19
20
  import { orpc } from "@/server/router/client";
20
21
 
21
22
  export default function DetailPage(props: PageProps<"/admin/purchase-orders/[id]">) {
@@ -97,6 +98,7 @@ export default function DetailPage(props: PageProps<"/admin/purchase-orders/[id]
97
98
  mutation={orpc.purchaseOrders.update.mutationOptions()}
98
99
  strategy={{ mutate: { on: "change", debounceMs: 700 }, validate: { change: z.any() } }}
99
100
  className="min-h-24"
101
+ extensions={richTextEditorPreset}
100
102
  >
101
103
  <EditorMenuBubble />
102
104
  <EditorContent />
@@ -6,6 +6,7 @@ import { createTableSelectCell } from "@tulip-systems/data-tables/client";
6
6
  import { Editor, EditorContent } from "@tulip-systems/editor/client";
7
7
  import Link from "next/link";
8
8
  import { Fragment } from "react";
9
+ import { richTextEditorPreset } from "@/lib/config/editor";
9
10
  import { EmailStatusField } from "../../emails/_config/status";
10
11
  import type { Project } from "../../projects/_lib/validators";
11
12
  import type { PurchaseOrderItem } from "../../purchase-order-items/_lib/validators";
@@ -39,7 +40,12 @@ export const purchaseOrderColumns: TableColumnDef<PurchaseOrderColumn>[] = [
39
40
  header: ({ column }) => <TableColumnHeader column={column} title="Notitie" />,
40
41
  cell: ({ row }) => (
41
42
  <TableCell className="line-clamp-1 max-w-[500px] truncate">
42
- <Editor value={row.original.notes} variant="preview" disabled>
43
+ <Editor
44
+ value={row.original.notes}
45
+ variant="preview"
46
+ disabled
47
+ extensions={richTextEditorPreset}
48
+ >
43
49
  <EditorContent />
44
50
  </Editor>
45
51
  </TableCell>
@@ -4,6 +4,7 @@ import { formatCurrency } from "@tulip-systems/core";
4
4
  import { TableCell, type TableColumnDef, TableColumnHeader } from "@tulip-systems/data-tables";
5
5
  import { createTableSelectCell } from "@tulip-systems/data-tables/client";
6
6
  import { Editor, EditorContent } from "@tulip-systems/editor/client";
7
+ import { richTextEditorPreset } from "@/lib/config/editor";
7
8
  import type { QuotationItemTableData } from "../_components/tables";
8
9
 
9
10
  export const quotationItemColumns: TableColumnDef<QuotationItemTableData>[] = [
@@ -18,7 +19,12 @@ export const quotationItemColumns: TableColumnDef<QuotationItemTableData>[] = [
18
19
  header: ({ column }) => <TableColumnHeader column={column} title="Omschrijving" />,
19
20
  cell: ({ row }) => (
20
21
  <TableCell>
21
- <Editor value={row.getValue("description") ?? undefined} variant="preview" disabled>
22
+ <Editor
23
+ value={row.getValue("description") ?? undefined}
24
+ variant="preview"
25
+ disabled
26
+ extensions={richTextEditorPreset}
27
+ >
22
28
  <EditorContent />
23
29
  </Editor>
24
30
  </TableCell>
@@ -17,6 +17,7 @@ import {
17
17
  InlineTableCellError,
18
18
  } from "@tulip-systems/inline/client";
19
19
  import { z } from "zod";
20
+ import { richTextEditorPreset } from "@/lib/config/editor";
20
21
  import { orpc } from "@/server/router/client";
21
22
  import type { QuotationItemTableData } from "../_components/tables";
22
23
 
@@ -58,6 +59,7 @@ export const quotationItemInlineColumns: TableColumnDef<QuotationItemTableData>[
58
59
  strategy={{ mutate: { on: "change", debounceMs: 700 }, validate: { change: z.any() } }}
59
60
  variant="table"
60
61
  permission={{ quotation: ["update"] }}
62
+ extensions={richTextEditorPreset}
61
63
  >
62
64
  <EditorMenuBubble />
63
65
  <EditorContent />
@@ -24,6 +24,7 @@ import { use } from "react";
24
24
  import { z } from "zod";
25
25
  import { generateClientHref } from "@/app/admin/clients/_lib/helpers";
26
26
  import { Icons } from "@/components/icons";
27
+ import { richTextEditorPreset } from "@/lib/config/editor";
27
28
  import { orpc } from "@/server/router/client";
28
29
 
29
30
  const toInlineDateValue = (value: Date | string | null | undefined): string | null => {
@@ -137,6 +138,7 @@ export default function DetailPage(props: PageProps<"/admin/quotations/[id]">) {
137
138
  validate: { change: z.any() },
138
139
  }}
139
140
  className="min-h-24"
141
+ extensions={richTextEditorPreset}
140
142
  >
141
143
  <EditorMenuBubble />
142
144
  <EditorContent />
@@ -4,6 +4,7 @@ import { TableCell, type TableColumnDef, TableColumnHeader } from "@tulip-system
4
4
  import { createTableSelectCell } from "@tulip-systems/data-tables/client";
5
5
  import { Editor, EditorContent } from "@tulip-systems/editor/client";
6
6
  import Link from "next/link";
7
+ import { richTextEditorPreset } from "@/lib/config/editor";
7
8
  import { TaskStatusField } from "../../tasks/_config/status";
8
9
  import type { RunTaskTableData } from "../_components/tables";
9
10
 
@@ -22,7 +23,12 @@ export const runTaskTableColumns: TableColumnDef<RunTaskTableData>[] = [
22
23
  accessorFn: (row) => row.task.description,
23
24
  cell: ({ row }) => (
24
25
  <TableCell className="w-full min-w-80">
25
- <Editor value={row.getValue("description")} variant="preview" disabled>
26
+ <Editor
27
+ value={row.getValue("description")}
28
+ variant="preview"
29
+ disabled
30
+ extensions={richTextEditorPreset}
31
+ >
26
32
  <EditorContent />
27
33
  </Editor>
28
34
  </TableCell>
@@ -22,6 +22,7 @@ import { z } from "zod";
22
22
  import { EmployeeAvatars, EmployeeAvatarsLoading } from "@/app/admin/employees/_components/avatars";
23
23
  import { calculateTotalDuration } from "@/app/admin/registrations/_lib/helpers";
24
24
  import { Icons } from "@/components/icons";
25
+ import { richTextEditorPreset } from "@/lib/config/editor";
25
26
  import { orpc } from "@/server/router/client";
26
27
 
27
28
  export default function RunDetailPage(props: PageProps<"/admin/runs/[id]">) {
@@ -94,6 +95,7 @@ export default function RunDetailPage(props: PageProps<"/admin/runs/[id]">) {
94
95
  validate: { change: z.any() },
95
96
  }}
96
97
  className="min-h-24"
98
+ extensions={richTextEditorPreset}
97
99
  >
98
100
  <EditorMenuBubble />
99
101
  <EditorContent />
@@ -19,6 +19,7 @@ import { RunTaskInfiniteTableProvider } from "@/app/admin/run-tasks/_components/
19
19
  import { RunTaskTableToolbar } from "@/app/admin/run-tasks/_components/toolbars";
20
20
  import { runTaskTableColumns } from "@/app/admin/run-tasks/_config/columns-data";
21
21
  import { runTaskDeleteCommand, runTaskResetCommand } from "@/app/admin/run-tasks/_config/commands";
22
+ import { richTextEditorPreset } from "@/lib/config/editor";
22
23
  import { orpc } from "@/server/router/client";
23
24
 
24
25
  export default function RunDetailPage(props: PageProps<"/admin/runs/[id]/reports">) {
@@ -39,6 +40,7 @@ export default function RunDetailPage(props: PageProps<"/admin/runs/[id]/reports
39
40
  mutation={orpc.runs.update.mutationOptions()}
40
41
  strategy={{ mutate: { on: "change", debounceMs: 700 }, validate: { change: z.any() } }}
41
42
  className="min-h-24"
43
+ extensions={richTextEditorPreset}
42
44
  >
43
45
  <EditorMenuBubble />
44
46
  <EditorContent />
@@ -4,6 +4,7 @@ import { formatCurrency } from "@tulip-systems/core";
4
4
  import { TableCell, type TableColumnDef, TableColumnHeader } from "@tulip-systems/data-tables";
5
5
  import { createTableSelectCell } from "@tulip-systems/data-tables/client";
6
6
  import { Editor, EditorContent } from "@tulip-systems/editor/client";
7
+ import { richTextEditorPreset } from "@/lib/config/editor";
7
8
  import { VAT_RATES } from "../../clients/_lib/constants";
8
9
  import type { SalesInvoiceItemTableData } from "../_components/tables";
9
10
 
@@ -19,7 +20,12 @@ export const salesInvoiceItemColumns: TableColumnDef<SalesInvoiceItemTableData>[
19
20
  header: ({ column }) => <TableColumnHeader column={column} title="Omschrijving" />,
20
21
  cell: ({ row }) => (
21
22
  <TableCell>
22
- <Editor value={row.getValue("description") ?? undefined} variant="preview" disabled>
23
+ <Editor
24
+ value={row.getValue("description") ?? undefined}
25
+ variant="preview"
26
+ disabled
27
+ extensions={richTextEditorPreset}
28
+ >
23
29
  <EditorContent />
24
30
  </Editor>
25
31
  </TableCell>
@@ -19,6 +19,7 @@ import {
19
19
  InlineTableCellError,
20
20
  } from "@tulip-systems/inline/client";
21
21
  import { z } from "zod";
22
+ import { richTextEditorPreset } from "@/lib/config/editor";
22
23
  import { orpc } from "@/server/router/client";
23
24
  import { vatRateComboboxOptions } from "../../clients/_lib/constants";
24
25
  import type { SalesInvoiceItemTableData } from "../_components/tables";
@@ -58,6 +59,7 @@ export const salesInvoiceItemInlineColumns: TableColumnDef<SalesInvoiceItemTable
58
59
  strategy={{ mutate: { on: "change", debounceMs: 700 }, validate: { change: z.any() } }}
59
60
  variant="table"
60
61
  permission={{ salesOrder: ["update"] }}
62
+ extensions={richTextEditorPreset}
61
63
  >
62
64
  <EditorContent />
63
65
  </InlineEditor>
@@ -4,6 +4,7 @@ import { formatCurrency } from "@tulip-systems/core";
4
4
  import { TableCell, type TableColumnDef, TableColumnHeader } from "@tulip-systems/data-tables";
5
5
  import { createTableSelectCell } from "@tulip-systems/data-tables/client";
6
6
  import { Editor, EditorContent } from "@tulip-systems/editor/client";
7
+ import { richTextEditorPreset } from "@/lib/config/editor";
7
8
  import type { SalesOrderItemTableData } from "../_components/tables";
8
9
 
9
10
  export const salesOrderItemColumns: TableColumnDef<SalesOrderItemTableData>[] = [
@@ -18,7 +19,12 @@ export const salesOrderItemColumns: TableColumnDef<SalesOrderItemTableData>[] =
18
19
  header: ({ column }) => <TableColumnHeader column={column} title="Omschrijving" />,
19
20
  cell: ({ row }) => (
20
21
  <TableCell>
21
- <Editor value={row.getValue("description") ?? undefined} variant="preview" disabled>
22
+ <Editor
23
+ value={row.getValue("description") ?? undefined}
24
+ variant="preview"
25
+ disabled
26
+ extensions={richTextEditorPreset}
27
+ >
22
28
  <EditorContent />
23
29
  </Editor>
24
30
  </TableCell>
@@ -20,6 +20,7 @@ import {
20
20
  InlineTableCellError,
21
21
  } from "@tulip-systems/inline/client";
22
22
  import { z } from "zod";
23
+ import { richTextEditorPreset } from "@/lib/config/editor";
23
24
  import { orpc } from "@/server/router/client";
24
25
  import { vatRateComboboxOptions } from "../../clients/_lib/constants";
25
26
  import type { SalesOrderItemTableData } from "../_components/tables";
@@ -63,6 +64,7 @@ export const salesOrderItemInlineColumns: TableColumnDef<SalesOrderItemTableData
63
64
  variant="table"
64
65
  permission={{ salesOrder: ["update"] }}
65
66
  disabled={row.original.associated.length > 0}
67
+ extensions={richTextEditorPreset}
66
68
  >
67
69
  <EditorMenuBubble />
68
70
  <EditorContent />
@@ -20,6 +20,7 @@ import { use } from "react";
20
20
  import { z } from "zod";
21
21
  import { generateClientHref } from "@/app/admin/clients/_lib/helpers";
22
22
  import { Icons } from "@/components/icons";
23
+ import { richTextEditorPreset } from "@/lib/config/editor";
23
24
  import { orpc } from "@/server/router/client";
24
25
  import { SalesOrderRatioTypeField } from "../../../_config/ratio-type";
25
26
 
@@ -95,6 +96,7 @@ export default function DetailPage(props: PageProps<"/admin/sales-orders/[id]">)
95
96
  mutation={orpc.salesOrders.update.mutationOptions()}
96
97
  strategy={{ mutate: { on: "change", debounceMs: 700 }, validate: { change: z.any() } }}
97
98
  className="min-h-24"
99
+ extensions={richTextEditorPreset}
98
100
  >
99
101
  <EditorMenuBubble />
100
102
  <EditorContent />
@@ -13,6 +13,7 @@ import { DataList, DataListItem, DataListTitle, DataListValue } from "@tulip-sys
13
13
  import { notFound } from "next/navigation";
14
14
  import { use } from "react";
15
15
  import { z } from "zod";
16
+ import { richTextEditorPreset } from "@/lib/config/editor";
16
17
  import { orpc } from "@/server/router/client";
17
18
 
18
19
  export default function DetailPage(props: PageProps<"/admin/suppliers/[id]">) {
@@ -130,6 +131,7 @@ export default function DetailPage(props: PageProps<"/admin/suppliers/[id]">) {
130
131
  validate: { change: z.any() },
131
132
  }}
132
133
  className="min-h-40"
134
+ extensions={richTextEditorPreset}
133
135
  >
134
136
  <EditorMenuBubble />
135
137
  <EditorContent />
@@ -4,6 +4,7 @@ import { TableCell, type TableColumnDef, TableColumnHeader } from "@tulip-system
4
4
  import { createTableIndexCell, createTableSelectCell } from "@tulip-systems/data-tables/client";
5
5
  import { Editor, EditorContent } from "@tulip-systems/editor/client";
6
6
  import Link from "next/link";
7
+ import { richTextEditorPreset } from "@/lib/config/editor";
7
8
  import type { TaskTableData } from "../_components/tables";
8
9
  import { TaskStatusField } from "./status";
9
10
 
@@ -19,7 +20,12 @@ export const taskTableColumns: TableColumnDef<TaskTableData>[] = [
19
20
  header: ({ column }) => <TableColumnHeader column={column} title="Omschrijving" />,
20
21
  cell: ({ row }) => (
21
22
  <TableCell className="w-full min-w-80">
22
- <Editor value={row.getValue("description")} variant="preview" disabled>
23
+ <Editor
24
+ value={row.getValue("description")}
25
+ variant="preview"
26
+ disabled
27
+ extensions={richTextEditorPreset}
28
+ >
23
29
  <EditorContent />
24
30
  </Editor>
25
31
  </TableCell>
@@ -23,6 +23,7 @@ import {
23
23
  } from "@tulip-systems/inline/client";
24
24
  import Link from "next/link";
25
25
  import { z } from "zod";
26
+ import { richTextEditorPreset } from "@/lib/config/editor";
26
27
  import { orpc } from "@/server/router/client";
27
28
  import type { TaskTableData } from "../_components/tables";
28
29
  import type { TaskStatus } from "../_lib/validators";
@@ -62,6 +63,7 @@ export const taskInlineTableColumns: TableColumnDef<TaskTableData>[] = [
62
63
  mutation={orpc.tasks.update.mutationOptions()}
63
64
  strategy={{ mutate: { on: "change", debounceMs: 700 }, validate: { change: z.any() } }}
64
65
  variant="table"
66
+ extensions={richTextEditorPreset}
65
67
  >
66
68
  <EditorMenuBubble />
67
69
  <EditorContent />
@@ -20,6 +20,7 @@ import { notFound } from "next/navigation";
20
20
  import { Suspense, use } from "react";
21
21
  import { z } from "zod";
22
22
  import { Icons } from "@/components/icons";
23
+ import { richTextEditorPreset } from "@/lib/config/editor";
23
24
  import { orpc } from "@/server/router/client";
24
25
  import { DriveFlatView } from "../../drive/_components/flat.client";
25
26
 
@@ -86,6 +87,7 @@ export default function Page(props: PageProps<"/admin/technical-sheets/[id]">) {
86
87
  mutation={orpc.technicalSheets.update.mutationOptions()}
87
88
  strategy={{ mutate: { on: "change", debounceMs: 700 }, validate: { change: z.any() } }}
88
89
  className="min-h-24"
90
+ extensions={richTextEditorPreset}
89
91
  >
90
92
  <EditorMenuBubble />
91
93
  <EditorContent />
@@ -4,6 +4,7 @@ import { TableCell, type TableColumnDef, TableColumnHeader } from "@tulip-system
4
4
  import { createTableIndexCell, createTableSelectCell } from "@tulip-systems/data-tables/client";
5
5
  import { Editor, EditorContent } from "@tulip-systems/editor/client";
6
6
  import Link from "next/link";
7
+ import { richTextEditorPreset } from "@/lib/config/editor";
7
8
  import type { TechnicalSheetTableData } from "../_components/tables";
8
9
  import { TechnicalSheetStatusField } from "./status";
9
10
 
@@ -25,7 +26,12 @@ export const technicalSheetTableColumns: TableColumnDef<TechnicalSheetTableData>
25
26
  header: ({ column }) => <TableColumnHeader column={column} title="Omschrijving" />,
26
27
  cell: ({ row }) => (
27
28
  <TableCell className="w-full min-w-80">
28
- <Editor value={row.getValue("description")} variant="preview" disabled>
29
+ <Editor
30
+ value={row.getValue("description")}
31
+ variant="preview"
32
+ disabled
33
+ extensions={richTextEditorPreset}
34
+ >
29
35
  <EditorContent />
30
36
  </Editor>
31
37
  </TableCell>
@@ -36,7 +42,12 @@ export const technicalSheetTableColumns: TableColumnDef<TechnicalSheetTableData>
36
42
  header: ({ column }) => <TableColumnHeader column={column} title="Notitie" />,
37
43
  cell: ({ row }) => (
38
44
  <TableCell className="w-full min-w-80">
39
- <Editor value={row.getValue("notes")} variant="preview" disabled>
45
+ <Editor
46
+ value={row.getValue("notes")}
47
+ variant="preview"
48
+ disabled
49
+ extensions={richTextEditorPreset}
50
+ >
40
51
  <EditorContent />
41
52
  </Editor>
42
53
  </TableCell>
@@ -4,6 +4,7 @@ import { formatCurrency } from "@tulip-systems/core";
4
4
  import { TableCell, type TableColumnDef, TableColumnHeader } from "@tulip-systems/data-tables";
5
5
  import { createTableSelectCell } from "@tulip-systems/data-tables/client";
6
6
  import { Editor, EditorContent } from "@tulip-systems/editor/client";
7
+ import { richTextEditorPreset } from "@/lib/config/editor";
7
8
  import type { TemplateTaskTableData } from "../_components/tables";
8
9
 
9
10
  export const templateTaskColumns: TableColumnDef<TemplateTaskTableData>[] = [
@@ -18,7 +19,12 @@ export const templateTaskColumns: TableColumnDef<TemplateTaskTableData>[] = [
18
19
  header: ({ column }) => <TableColumnHeader column={column} title="Omschrijving" />,
19
20
  cell: ({ row }) => (
20
21
  <TableCell>
21
- <Editor value={row.getValue("description") ?? undefined} variant="preview" disabled>
22
+ <Editor
23
+ value={row.getValue("description") ?? undefined}
24
+ variant="preview"
25
+ disabled
26
+ extensions={richTextEditorPreset}
27
+ >
22
28
  <EditorContent />
23
29
  </Editor>
24
30
  </TableCell>
@@ -15,6 +15,7 @@ import {
15
15
  InlineTableCellError,
16
16
  } from "@tulip-systems/inline/client";
17
17
  import { z } from "zod";
18
+ import { richTextEditorPreset } from "@/lib/config/editor";
18
19
  import { orpc } from "@/server/router/client";
19
20
  import type { TemplateTaskTableData } from "../_components/tables";
20
21
 
@@ -56,6 +57,7 @@ export const templateTaskInlineColumns: TableColumnDef<TemplateTaskTableData>[]
56
57
  strategy={{ mutate: { on: "change", debounceMs: 700 }, validate: { change: z.any() } }}
57
58
  variant="table"
58
59
  permission={{ template: ["update"] }}
60
+ extensions={richTextEditorPreset}
59
61
  >
60
62
  <EditorMenuBubble />
61
63
  <EditorContent />
@@ -14,6 +14,7 @@ import { DataStackLayout } from "@tulip-systems/ui/data-stack";
14
14
  import { notFound } from "next/navigation";
15
15
  import { use } from "react";
16
16
  import { z } from "zod";
17
+ import { richTextEditorPreset } from "@/lib/config/editor";
17
18
  import { orpc } from "@/server/router/client";
18
19
 
19
20
  export default function DetailPage(props: PageProps<"/admin/templates/[id]">) {
@@ -45,6 +46,7 @@ export default function DetailPage(props: PageProps<"/admin/templates/[id]">) {
45
46
  mutation={orpc.templates.update.mutationOptions()}
46
47
  strategy={{ mutate: { on: "change", debounceMs: 700 }, validate: { change: z.any() } }}
47
48
  className="min-h-24"
49
+ extensions={richTextEditorPreset}
48
50
  >
49
51
  <EditorMenuBubble />
50
52
  <EditorContent />
@@ -0,0 +1,54 @@
1
+ import type { ResizableNodeViewDirection } from "@tiptap/core";
2
+ import Blockquote from "@tiptap/extension-blockquote";
3
+ import Bold from "@tiptap/extension-bold";
4
+ import Document from "@tiptap/extension-document";
5
+ import HardBreak from "@tiptap/extension-hard-break";
6
+ import Heading from "@tiptap/extension-heading";
7
+ import Highlight from "@tiptap/extension-highlight";
8
+ import HorizontalRule from "@tiptap/extension-horizontal-rule";
9
+ import Italic from "@tiptap/extension-italic";
10
+ import Link from "@tiptap/extension-link";
11
+ import { BulletList, ListItem, ListKeymap, OrderedList } from "@tiptap/extension-list";
12
+ import Paragraph from "@tiptap/extension-paragraph";
13
+ import Strike from "@tiptap/extension-strike";
14
+ import Text from "@tiptap/extension-text";
15
+ import { Color, TextStyle } from "@tiptap/extension-text-style";
16
+ import Underline from "@tiptap/extension-underline";
17
+ import { Dropcursor, Gapcursor, TrailingNode, UndoRedo } from "@tiptap/extensions";
18
+ import { defineEditorPreset } from "@tulip-systems/editor/client";
19
+ import { StorageImage } from "@tulip-systems/editor-storage/client";
20
+
21
+ const imageResizeOptions = {
22
+ enabled: true,
23
+ directions: ["left", "right"] as ResizableNodeViewDirection[],
24
+ minHeight: 50,
25
+ minWidth: 50,
26
+ alwaysPreserveAspectRatio: true,
27
+ };
28
+
29
+ export const richTextEditorPreset = defineEditorPreset([
30
+ Document,
31
+ Text,
32
+ Paragraph,
33
+ Blockquote,
34
+ HardBreak,
35
+ Heading,
36
+ HorizontalRule,
37
+ ListItem,
38
+ OrderedList,
39
+ BulletList,
40
+ StorageImage.configure({ resize: imageResizeOptions }),
41
+ Bold,
42
+ Italic,
43
+ Link,
44
+ Strike,
45
+ Underline,
46
+ Highlight.configure({ multicolor: true }),
47
+ Dropcursor,
48
+ Gapcursor,
49
+ UndoRedo,
50
+ ListKeymap,
51
+ TrailingNode,
52
+ TextStyle,
53
+ Color,
54
+ ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tulip-systems/create-app",
3
- "version": "0.12.2",
3
+ "version": "0.12.3",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "AGPL-3.0",