@wakastellar/ui 3.3.3 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/dist/badge-BbwO7QeZ.js +1 -0
  2. package/dist/badge-BfiocODp.mjs +23 -0
  3. package/dist/charts.cjs.js +1 -1
  4. package/dist/charts.es.js +1 -1
  5. package/dist/chunk-14q5BKub.js +1 -0
  6. package/dist/{chunk-BH6uBOac.mjs → chunk-Cr9pTUWm.mjs} +5 -5
  7. package/dist/cn-DEtaFQsA.js +1 -0
  8. package/dist/cn-DUn6aSIQ.mjs +24 -0
  9. package/dist/doc.cjs.js +2 -2
  10. package/dist/doc.es.js +19 -19
  11. package/dist/editor.cjs.js +48 -0
  12. package/dist/editor.d.ts +1 -0
  13. package/dist/editor.es.js +6551 -0
  14. package/dist/{exceljs.min-DG9M8IZ1.mjs → exceljs.min-DL1XYDll.mjs} +1 -1
  15. package/dist/{exceljs.min-BuefmDRS.js → exceljs.min-qeIfSCbF.js} +1 -1
  16. package/dist/export.cjs.js +1 -1
  17. package/dist/export.es.js +1 -1
  18. package/dist/index.cjs.js +150 -150
  19. package/dist/index.es.js +26782 -27591
  20. package/dist/input-BfaSAGVw.js +1 -0
  21. package/dist/input-DVr_Qkl8.mjs +14 -0
  22. package/dist/rich-text.cjs.js +1 -1
  23. package/dist/rich-text.es.js +1 -1
  24. package/dist/security-CyBpuklN.mjs +122 -0
  25. package/dist/security-bFWwDrlg.js +1 -0
  26. package/dist/separator-NrkltulH.js +1 -0
  27. package/dist/separator-ibN2mycs.mjs +51 -0
  28. package/dist/src/components/editor/blocks/index.d.ts +51 -0
  29. package/dist/src/components/editor/blocks/waka-acceptance-criteria-block.d.ts +60 -0
  30. package/dist/src/components/editor/blocks/waka-ai-assist-block.d.ts +58 -0
  31. package/dist/src/components/editor/blocks/waka-api-endpoint-block.d.ts +63 -0
  32. package/dist/src/components/editor/blocks/waka-code-playground-block.d.ts +61 -0
  33. package/dist/src/components/editor/blocks/waka-comment-thread-block.d.ts +85 -0
  34. package/dist/src/components/editor/blocks/waka-diagram-block.d.ts +52 -0
  35. package/dist/src/components/editor/blocks/waka-embed-block.d.ts +58 -0
  36. package/dist/src/components/editor/blocks/waka-slash-menu-block.d.ts +67 -0
  37. package/dist/src/components/editor/blocks/waka-user-story-block.d.ts +79 -0
  38. package/dist/src/components/editor/blocks/waka-version-diff-block.d.ts +73 -0
  39. package/dist/src/components/editor/index.d.ts +66 -0
  40. package/dist/src/components/editor/waka-ai-writer.d.ts +80 -0
  41. package/dist/src/components/editor/waka-collaborative-editor.d.ts +93 -0
  42. package/dist/src/components/editor/waka-diff-viewer.d.ts +71 -0
  43. package/dist/src/components/editor/waka-dnd-editor.d.ts +64 -0
  44. package/dist/src/components/editor/waka-document-editor.d.ts +92 -0
  45. package/dist/src/components/editor/waka-editor-elements.d.ts +79 -0
  46. package/dist/src/components/editor/waka-editor-leaves.d.ts +39 -0
  47. package/dist/src/components/editor/waka-editor-plugins.d.ts +41 -0
  48. package/dist/src/components/editor/waka-editor-toolbar.d.ts +20 -0
  49. package/dist/src/components/editor/waka-editor.d.ts +59 -0
  50. package/dist/src/components/editor/waka-floating-toolbar.d.ts +47 -0
  51. package/dist/src/components/editor/waka-markdown-editor.d.ts +60 -0
  52. package/dist/src/components/editor/waka-mention-editor.d.ts +125 -0
  53. package/dist/src/components/editor/waka-slash-menu.d.ts +70 -0
  54. package/dist/src/components/editor/waka-spec-editor.d.ts +88 -0
  55. package/dist/src/components/index.d.ts +1 -15
  56. package/dist/src/editor.d.ts +26 -0
  57. package/dist/textarea-CdQWggYG.js +1 -0
  58. package/dist/textarea-DJDXJ3nd.mjs +23 -0
  59. package/dist/types-C2St0wOW.js +1 -0
  60. package/dist/{types-B6GVaSIP.mjs → types-JnqoLyuv.mjs} +214 -211
  61. package/dist/{useDataTableImport-BPvfo--2.mjs → useDataTableImport-BWUFesPi.mjs} +3 -3
  62. package/dist/{useDataTableImport-Cm_pCKnO.js → useDataTableImport-T7ddpN5k.js} +3 -3
  63. package/dist/waka-doc-renderer-CTxC7Trf.js +3 -0
  64. package/dist/{waka-doc-renderer-BkIvas3z.mjs → waka-doc-renderer-Cw-Xnyen.mjs} +264 -281
  65. package/dist/waka-editor-plugins-DR6tpsUC.mjs +135 -0
  66. package/dist/waka-editor-plugins-sGSh9hn2.js +1 -0
  67. package/dist/waka-rich-text-editor-BlIdtknG.js +1 -0
  68. package/dist/waka-rich-text-editor-D1uA3zbB.js +1 -0
  69. package/dist/waka-rich-text-editor-DgSWiXMW.mjs +342 -0
  70. package/dist/waka-rich-text-editor-DndVJuDw.mjs +2 -0
  71. package/package.json +87 -2
  72. package/src/blocks/footer/index.tsx +1 -6
  73. package/src/blocks/login/index.tsx +1 -7
  74. package/src/blocks/profile/index.tsx +3 -5
  75. package/src/components/editor/blocks/index.ts +182 -0
  76. package/src/components/editor/blocks/waka-acceptance-criteria-block.tsx +326 -0
  77. package/src/components/editor/blocks/waka-ai-assist-block.tsx +284 -0
  78. package/src/components/editor/blocks/waka-api-endpoint-block.tsx +382 -0
  79. package/src/components/editor/blocks/waka-code-playground-block.tsx +331 -0
  80. package/src/components/editor/blocks/waka-comment-thread-block.tsx +448 -0
  81. package/src/components/editor/blocks/waka-diagram-block.tsx +293 -0
  82. package/src/components/editor/blocks/waka-embed-block.tsx +416 -0
  83. package/src/components/editor/blocks/waka-slash-menu-block.tsx +432 -0
  84. package/src/components/editor/blocks/waka-user-story-block.tsx +295 -0
  85. package/src/components/editor/blocks/waka-version-diff-block.tsx +426 -0
  86. package/src/components/editor/index.ts +279 -0
  87. package/src/components/editor/waka-ai-writer.tsx +434 -0
  88. package/src/components/editor/waka-collaborative-editor.tsx +426 -0
  89. package/src/components/editor/waka-diff-viewer.tsx +352 -0
  90. package/src/components/editor/waka-dnd-editor.tsx +284 -0
  91. package/src/components/editor/waka-document-editor.tsx +502 -0
  92. package/src/components/editor/waka-editor-elements.tsx +312 -0
  93. package/src/components/editor/waka-editor-leaves.tsx +101 -0
  94. package/src/components/editor/waka-editor-plugins.ts +207 -0
  95. package/src/components/editor/waka-editor-toolbar.tsx +358 -0
  96. package/src/components/editor/waka-editor.tsx +431 -0
  97. package/src/components/editor/waka-floating-toolbar.tsx +268 -0
  98. package/src/components/editor/waka-markdown-editor.tsx +395 -0
  99. package/src/components/editor/waka-mention-editor.tsx +459 -0
  100. package/src/components/editor/waka-slash-menu.tsx +392 -0
  101. package/src/components/editor/waka-spec-editor.tsx +657 -0
  102. package/src/components/index.ts +1 -18
  103. package/dist/chunk-BDDJmn7V.js +0 -1
  104. package/dist/cn-DnPbmOCy.js +0 -1
  105. package/dist/cn-DpLcAzrf.mjs +0 -22
  106. package/dist/separator-BDReXBvI.mjs +0 -59
  107. package/dist/separator-BKjNl9sI.js +0 -1
  108. package/dist/src/components/waka-actor-badge/index.d.ts +0 -8
  109. package/dist/src/components/waka-actors-list/index.d.ts +0 -18
  110. package/dist/src/components/waka-ai-assistant-button/index.d.ts +0 -8
  111. package/dist/src/components/waka-document-flyover/index.d.ts +0 -10
  112. package/dist/src/components/waka-document-preview-popup/index.d.ts +0 -26
  113. package/dist/src/components/waka-hour-balance-badge/index.d.ts +0 -8
  114. package/dist/src/components/waka-hour-consumption-table/index.d.ts +0 -15
  115. package/dist/src/components/waka-hour-pack-dialog/index.d.ts +0 -8
  116. package/dist/src/components/waka-project-stats-header/index.d.ts +0 -15
  117. package/dist/src/components/waka-step-comment-bubble/index.d.ts +0 -13
  118. package/dist/src/components/waka-step-comment-panel/index.d.ts +0 -20
  119. package/dist/src/components/waka-step-permission-matrix/index.d.ts +0 -12
  120. package/dist/src/components/waka-time-entry-dialog/index.d.ts +0 -16
  121. package/dist/src/components/waka-time-tracking-flyover/index.d.ts +0 -11
  122. package/dist/types-BH9cQRqZ.js +0 -1
  123. package/dist/waka-doc-renderer-BZ2-SqyT.js +0 -3
  124. package/dist/waka-rich-text-editor-BJGlQgpq.js +0 -1
  125. package/dist/waka-rich-text-editor-BJzzxeP1.mjs +0 -361
  126. package/dist/waka-rich-text-editor-wnXLwvUo.js +0 -1
  127. package/src/components/waka-actor-badge/index.tsx +0 -34
  128. package/src/components/waka-actors-list/index.tsx +0 -125
  129. package/src/components/waka-ai-assistant-button/index.tsx +0 -31
  130. package/src/components/waka-document-flyover/index.tsx +0 -36
  131. package/src/components/waka-document-preview-popup/index.tsx +0 -103
  132. package/src/components/waka-hour-balance-badge/index.tsx +0 -43
  133. package/src/components/waka-hour-consumption-table/index.tsx +0 -72
  134. package/src/components/waka-hour-pack-dialog/index.tsx +0 -72
  135. package/src/components/waka-project-stats-header/index.tsx +0 -69
  136. package/src/components/waka-step-comment-bubble/index.tsx +0 -71
  137. package/src/components/waka-step-comment-panel/index.tsx +0 -106
  138. package/src/components/waka-step-permission-matrix/index.tsx +0 -65
  139. package/src/components/waka-time-entry-dialog/index.tsx +0 -131
  140. package/src/components/waka-time-tracking-flyover/index.tsx +0 -41
@@ -0,0 +1,358 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import {
5
+ Bold,
6
+ Italic,
7
+ Underline,
8
+ Strikethrough,
9
+ Code,
10
+ Highlighter,
11
+ Heading1,
12
+ Heading2,
13
+ Heading3,
14
+ Quote,
15
+ Table,
16
+ Columns2,
17
+ Link,
18
+ Image,
19
+ Minus,
20
+ Sparkles,
21
+ MessageSquarePlus,
22
+ AlignLeft,
23
+ type LucideIcon,
24
+ } from "lucide-react"
25
+ import { Button } from "../button"
26
+ import { Separator } from "../separator"
27
+ import {
28
+ Tooltip,
29
+ TooltipContent,
30
+ TooltipTrigger,
31
+ TooltipProvider,
32
+ } from "../tooltip"
33
+ import { cn } from "../../utils/cn"
34
+
35
+ // ─── Types ───────────────────────────────────────────────────────────────────
36
+
37
+ export type ToolbarAction =
38
+ | "bold"
39
+ | "italic"
40
+ | "underline"
41
+ | "strikethrough"
42
+ | "code"
43
+ | "highlight"
44
+ | "h1"
45
+ | "h2"
46
+ | "h3"
47
+ | "blockquote"
48
+ | "callout"
49
+ | "table"
50
+ | "columns"
51
+ | "link"
52
+ | "image"
53
+ | "separator"
54
+ | "ai"
55
+
56
+ /** A group of toolbar buttons rendered together with separators between groups */
57
+ export type ToolbarGroup = ToolbarAction[]
58
+
59
+ export interface WakaEditorToolbarProps {
60
+ /** Button groups to render */
61
+ groups?: ToolbarGroup[]
62
+ /** The Plate editor instance (typed as unknown to avoid tight coupling) */
63
+ editor: unknown
64
+ /** Extra CSS class names */
65
+ className?: string
66
+ /** Whether to show AI button */
67
+ enableAI?: boolean
68
+ /** Callback when AI button is clicked */
69
+ onAIClick?: () => void
70
+ }
71
+
72
+ // ─── Button registry ─────────────────────────────────────────────────────────
73
+
74
+ interface ToolbarButtonConfig {
75
+ icon: LucideIcon
76
+ label: string
77
+ shortcut?: string
78
+ action: (editor: Record<string, unknown>) => void
79
+ isActive?: (editor: Record<string, unknown>) => boolean
80
+ }
81
+
82
+ function safeChain(editor: Record<string, unknown>, fn: (chain: Record<string, unknown>) => void) {
83
+ try {
84
+ const chain = (editor as { chain: () => { focus: () => Record<string, unknown> } }).chain().focus()
85
+ fn(chain)
86
+ } catch {
87
+ // Plugin not loaded, silently ignore
88
+ }
89
+ }
90
+
91
+ function safeIsActive(editor: Record<string, unknown>, type: string, attrs?: object): boolean {
92
+ try {
93
+ return (editor as { isActive: (t: string, a?: object) => boolean }).isActive(type, attrs)
94
+ } catch {
95
+ return false
96
+ }
97
+ }
98
+
99
+ const BUTTON_REGISTRY: Record<ToolbarAction, ToolbarButtonConfig> = {
100
+ bold: {
101
+ icon: Bold,
102
+ label: "Gras",
103
+ shortcut: "Ctrl+B",
104
+ action: (e) => safeChain(e, (c) => (c as { toggleBold: () => { run: () => void } }).toggleBold().run()),
105
+ isActive: (e) => safeIsActive(e, "bold"),
106
+ },
107
+ italic: {
108
+ icon: Italic,
109
+ label: "Italique",
110
+ shortcut: "Ctrl+I",
111
+ action: (e) => safeChain(e, (c) => (c as { toggleItalic: () => { run: () => void } }).toggleItalic().run()),
112
+ isActive: (e) => safeIsActive(e, "italic"),
113
+ },
114
+ underline: {
115
+ icon: Underline,
116
+ label: "Souligné",
117
+ shortcut: "Ctrl+U",
118
+ action: (e) => safeChain(e, (c) => (c as { toggleUnderline: () => { run: () => void } }).toggleUnderline().run()),
119
+ isActive: (e) => safeIsActive(e, "underline"),
120
+ },
121
+ strikethrough: {
122
+ icon: Strikethrough,
123
+ label: "Barré",
124
+ shortcut: "Ctrl+Shift+S",
125
+ action: (e) => safeChain(e, (c) => (c as { toggleStrike: () => { run: () => void } }).toggleStrike().run()),
126
+ isActive: (e) => safeIsActive(e, "strikethrough"),
127
+ },
128
+ code: {
129
+ icon: Code,
130
+ label: "Code",
131
+ shortcut: "Ctrl+E",
132
+ action: (e) => safeChain(e, (c) => (c as { toggleCode: () => { run: () => void } }).toggleCode().run()),
133
+ isActive: (e) => safeIsActive(e, "code"),
134
+ },
135
+ highlight: {
136
+ icon: Highlighter,
137
+ label: "Surligné",
138
+ action: (e) => safeChain(e, (c) => (c as { toggleHighlight: () => { run: () => void } }).toggleHighlight().run()),
139
+ isActive: (e) => safeIsActive(e, "highlight"),
140
+ },
141
+ h1: {
142
+ icon: Heading1,
143
+ label: "Titre 1",
144
+ action: (e) => {
145
+ try {
146
+ (e as { tf: { h1: { toggle: () => void } } }).tf.h1.toggle()
147
+ } catch {
148
+ safeChain(e, (c) => (c as { toggleHeading: (o: { level: number }) => { run: () => void } }).toggleHeading({ level: 1 }).run())
149
+ }
150
+ },
151
+ isActive: (e) => safeIsActive(e, "heading", { level: 1 }),
152
+ },
153
+ h2: {
154
+ icon: Heading2,
155
+ label: "Titre 2",
156
+ action: (e) => {
157
+ try {
158
+ (e as { tf: { h2: { toggle: () => void } } }).tf.h2.toggle()
159
+ } catch {
160
+ safeChain(e, (c) => (c as { toggleHeading: (o: { level: number }) => { run: () => void } }).toggleHeading({ level: 2 }).run())
161
+ }
162
+ },
163
+ isActive: (e) => safeIsActive(e, "heading", { level: 2 }),
164
+ },
165
+ h3: {
166
+ icon: Heading3,
167
+ label: "Titre 3",
168
+ action: (e) => {
169
+ try {
170
+ (e as { tf: { h3: { toggle: () => void } } }).tf.h3.toggle()
171
+ } catch {
172
+ safeChain(e, (c) => (c as { toggleHeading: (o: { level: number }) => { run: () => void } }).toggleHeading({ level: 3 }).run())
173
+ }
174
+ },
175
+ isActive: (e) => safeIsActive(e, "heading", { level: 3 }),
176
+ },
177
+ blockquote: {
178
+ icon: Quote,
179
+ label: "Citation",
180
+ action: (e) => {
181
+ try {
182
+ (e as { tf: { blockquote: { toggle: () => void } } }).tf.blockquote.toggle()
183
+ } catch {
184
+ safeChain(e, (c) => (c as { toggleBlockquote: () => { run: () => void } }).toggleBlockquote().run())
185
+ }
186
+ },
187
+ isActive: (e) => safeIsActive(e, "blockquote"),
188
+ },
189
+ callout: {
190
+ icon: MessageSquarePlus,
191
+ label: "Callout",
192
+ action: (e) => {
193
+ try {
194
+ (e as { tf: { callout: { insert: () => void } } }).tf.callout.insert()
195
+ } catch {
196
+ // Callout plugin not loaded
197
+ }
198
+ },
199
+ isActive: (e) => safeIsActive(e, "callout"),
200
+ },
201
+ table: {
202
+ icon: Table,
203
+ label: "Tableau",
204
+ action: (e) => {
205
+ try {
206
+ (e as { tf: { table: { insert: (o: { rows: number; cols: number }) => void } } }).tf.table.insert({ rows: 3, cols: 3 })
207
+ } catch {
208
+ // Table plugin not loaded
209
+ }
210
+ },
211
+ isActive: (e) => safeIsActive(e, "table"),
212
+ },
213
+ columns: {
214
+ icon: Columns2,
215
+ label: "Colonnes",
216
+ action: (e) => {
217
+ try {
218
+ (e as { tf: { column: { insert: () => void } } }).tf.column.insert()
219
+ } catch {
220
+ // Column plugin not loaded
221
+ }
222
+ },
223
+ isActive: (e) => safeIsActive(e, "column_group"),
224
+ },
225
+ link: {
226
+ icon: Link,
227
+ label: "Lien",
228
+ shortcut: "Ctrl+K",
229
+ action: (e) => {
230
+ try {
231
+ (e as { tf: { link: { toggle: () => void } } }).tf.link.toggle()
232
+ } catch {
233
+ // Link plugin not loaded
234
+ }
235
+ },
236
+ isActive: (e) => safeIsActive(e, "a"),
237
+ },
238
+ image: {
239
+ icon: Image,
240
+ label: "Image",
241
+ action: (e) => {
242
+ try {
243
+ (e as { tf: { image: { insert: (o: { url: string }) => void } } }).tf.image.insert({ url: "" })
244
+ } catch {
245
+ // Image plugin not loaded
246
+ }
247
+ },
248
+ isActive: () => false,
249
+ },
250
+ separator: {
251
+ icon: Minus,
252
+ label: "Séparateur",
253
+ action: (e) => {
254
+ try {
255
+ safeChain(e, (c) => (c as { insertBreak: () => { run: () => void } }).insertBreak().run())
256
+ } catch {
257
+ // silent
258
+ }
259
+ },
260
+ isActive: () => false,
261
+ },
262
+ ai: {
263
+ icon: Sparkles,
264
+ label: "Assistant IA",
265
+ action: () => {
266
+ // Handled externally via onAIClick
267
+ },
268
+ isActive: () => false,
269
+ },
270
+ }
271
+
272
+ // ─── Default groups ──────────────────────────────────────────────────────────
273
+
274
+ export const DEFAULT_TOOLBAR_GROUPS: ToolbarGroup[] = [
275
+ ["bold", "italic", "underline", "strikethrough", "code", "highlight"],
276
+ ["h1", "h2", "h3"],
277
+ ["blockquote", "callout", "table", "columns"],
278
+ ["link", "image", "separator"],
279
+ ]
280
+
281
+ // ─── Component ───────────────────────────────────────────────────────────────
282
+
283
+ export function WakaEditorToolbar({
284
+ groups = DEFAULT_TOOLBAR_GROUPS,
285
+ editor,
286
+ className,
287
+ enableAI = false,
288
+ onAIClick,
289
+ }: WakaEditorToolbarProps) {
290
+ const allGroups = React.useMemo(() => {
291
+ if (enableAI) {
292
+ return [...groups, ["ai"] as ToolbarGroup]
293
+ }
294
+ return groups
295
+ }, [groups, enableAI])
296
+
297
+ return (
298
+ <TooltipProvider delayDuration={300}>
299
+ <div
300
+ role="toolbar"
301
+ aria-label="Barre d'outils de formatage"
302
+ className={cn(
303
+ "flex flex-wrap items-center gap-0.5 p-1",
304
+ "border-b bg-muted/30",
305
+ className
306
+ )}
307
+ >
308
+ {allGroups.map((group, groupIndex) => (
309
+ <React.Fragment key={groupIndex}>
310
+ {groupIndex > 0 && (
311
+ <Separator orientation="vertical" className="mx-1 h-6" />
312
+ )}
313
+ {group.map((action) => {
314
+ const config = BUTTON_REGISTRY[action]
315
+ if (!config) return null
316
+
317
+ const isActive = config.isActive?.(editor as Record<string, unknown>) ?? false
318
+ const tooltipText = config.shortcut
319
+ ? `${config.label} (${config.shortcut})`
320
+ : config.label
321
+
322
+ const Icon = config.icon
323
+
324
+ return (
325
+ <Tooltip key={action}>
326
+ <TooltipTrigger asChild>
327
+ <Button
328
+ type="button"
329
+ variant={isActive ? "secondary" : "ghost"}
330
+ size="icon"
331
+ className="h-7 w-7"
332
+ onClick={() => {
333
+ if (action === "ai" && onAIClick) {
334
+ onAIClick()
335
+ return
336
+ }
337
+ config.action(editor as Record<string, unknown>)
338
+ }}
339
+ aria-label={config.label}
340
+ aria-pressed={isActive}
341
+ >
342
+ <Icon className="h-4 w-4" />
343
+ </Button>
344
+ </TooltipTrigger>
345
+ <TooltipContent side="bottom" className="text-xs">
346
+ {tooltipText}
347
+ </TooltipContent>
348
+ </Tooltip>
349
+ )
350
+ })}
351
+ </React.Fragment>
352
+ ))}
353
+ </div>
354
+ </TooltipProvider>
355
+ )
356
+ }
357
+
358
+ WakaEditorToolbar.displayName = "WakaEditorToolbar"