@os-team-11/editor 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,721 @@
1
+ import { z } from 'zod';
2
+ import * as react from 'react';
3
+ import { ComponentType, ReactNode, CSSProperties, Ref } from 'react';
4
+
5
+ /** AI 输出 / 编辑器消费的中间格式 */
6
+ interface BidMeta {
7
+ title: string;
8
+ docNo: string;
9
+ tenderer: string;
10
+ version: string;
11
+ generatedAt: string;
12
+ generator?: string;
13
+ }
14
+ interface BidPageMargins {
15
+ top: number;
16
+ right: number;
17
+ bottom: number;
18
+ left: number;
19
+ }
20
+ interface BidPageHeader {
21
+ template: string;
22
+ showOnFirstPage: boolean;
23
+ }
24
+ interface BidPageFooter {
25
+ template: string;
26
+ }
27
+ interface BidPageWatermark {
28
+ text: string;
29
+ opacity: number;
30
+ }
31
+ type BidPageSize = 'A4' | 'Letter' | {
32
+ width: number;
33
+ height: number;
34
+ };
35
+ interface BidPage {
36
+ size: BidPageSize;
37
+ margins: BidPageMargins;
38
+ header?: BidPageHeader;
39
+ footer?: BidPageFooter;
40
+ watermark?: BidPageWatermark;
41
+ }
42
+ /** Milestone 1 支持的 block 类型子集 */
43
+ type BidBlock = {
44
+ type: 'heading';
45
+ level: 2 | 3 | 4;
46
+ text: string;
47
+ } | {
48
+ type: 'paragraph';
49
+ text: string;
50
+ } | {
51
+ type: 'list';
52
+ ordered: boolean;
53
+ items: string[];
54
+ } | {
55
+ type: 'table';
56
+ rows: string[][];
57
+ caption?: string;
58
+ } | {
59
+ type: 'image';
60
+ src: string;
61
+ alt?: string;
62
+ caption?: string;
63
+ };
64
+ interface BidSection {
65
+ id: string;
66
+ title: string;
67
+ level: 1 | 2 | 3;
68
+ blocks: BidBlock[];
69
+ }
70
+ interface BidSchema {
71
+ meta: BidMeta;
72
+ page: BidPage;
73
+ sections: BidSection[];
74
+ }
75
+
76
+ declare const bidSchema: z.ZodObject<{
77
+ meta: z.ZodObject<{
78
+ title: z.ZodString;
79
+ docNo: z.ZodString;
80
+ tenderer: z.ZodString;
81
+ version: z.ZodString;
82
+ generatedAt: z.ZodString;
83
+ generator: z.ZodOptional<z.ZodString>;
84
+ }, "strip", z.ZodTypeAny, {
85
+ title: string;
86
+ docNo: string;
87
+ tenderer: string;
88
+ version: string;
89
+ generatedAt: string;
90
+ generator?: string | undefined;
91
+ }, {
92
+ title: string;
93
+ docNo: string;
94
+ tenderer: string;
95
+ version: string;
96
+ generatedAt: string;
97
+ generator?: string | undefined;
98
+ }>;
99
+ page: z.ZodObject<{
100
+ size: z.ZodUnion<[z.ZodLiteral<"A4">, z.ZodLiteral<"Letter">, z.ZodObject<{
101
+ width: z.ZodNumber;
102
+ height: z.ZodNumber;
103
+ }, "strip", z.ZodTypeAny, {
104
+ width: number;
105
+ height: number;
106
+ }, {
107
+ width: number;
108
+ height: number;
109
+ }>]>;
110
+ margins: z.ZodObject<{
111
+ top: z.ZodNumber;
112
+ right: z.ZodNumber;
113
+ bottom: z.ZodNumber;
114
+ left: z.ZodNumber;
115
+ }, "strip", z.ZodTypeAny, {
116
+ top: number;
117
+ right: number;
118
+ bottom: number;
119
+ left: number;
120
+ }, {
121
+ top: number;
122
+ right: number;
123
+ bottom: number;
124
+ left: number;
125
+ }>;
126
+ header: z.ZodOptional<z.ZodObject<{
127
+ template: z.ZodString;
128
+ showOnFirstPage: z.ZodBoolean;
129
+ }, "strip", z.ZodTypeAny, {
130
+ template: string;
131
+ showOnFirstPage: boolean;
132
+ }, {
133
+ template: string;
134
+ showOnFirstPage: boolean;
135
+ }>>;
136
+ footer: z.ZodOptional<z.ZodObject<{
137
+ template: z.ZodString;
138
+ }, "strip", z.ZodTypeAny, {
139
+ template: string;
140
+ }, {
141
+ template: string;
142
+ }>>;
143
+ watermark: z.ZodOptional<z.ZodObject<{
144
+ text: z.ZodString;
145
+ opacity: z.ZodNumber;
146
+ }, "strip", z.ZodTypeAny, {
147
+ text: string;
148
+ opacity: number;
149
+ }, {
150
+ text: string;
151
+ opacity: number;
152
+ }>>;
153
+ }, "strip", z.ZodTypeAny, {
154
+ size: "A4" | "Letter" | {
155
+ width: number;
156
+ height: number;
157
+ };
158
+ margins: {
159
+ top: number;
160
+ right: number;
161
+ bottom: number;
162
+ left: number;
163
+ };
164
+ header?: {
165
+ template: string;
166
+ showOnFirstPage: boolean;
167
+ } | undefined;
168
+ footer?: {
169
+ template: string;
170
+ } | undefined;
171
+ watermark?: {
172
+ text: string;
173
+ opacity: number;
174
+ } | undefined;
175
+ }, {
176
+ size: "A4" | "Letter" | {
177
+ width: number;
178
+ height: number;
179
+ };
180
+ margins: {
181
+ top: number;
182
+ right: number;
183
+ bottom: number;
184
+ left: number;
185
+ };
186
+ header?: {
187
+ template: string;
188
+ showOnFirstPage: boolean;
189
+ } | undefined;
190
+ footer?: {
191
+ template: string;
192
+ } | undefined;
193
+ watermark?: {
194
+ text: string;
195
+ opacity: number;
196
+ } | undefined;
197
+ }>;
198
+ sections: z.ZodArray<z.ZodObject<{
199
+ id: z.ZodString;
200
+ title: z.ZodString;
201
+ level: z.ZodUnion<[z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>]>;
202
+ blocks: z.ZodArray<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
203
+ type: z.ZodLiteral<"heading">;
204
+ level: z.ZodUnion<[z.ZodLiteral<2>, z.ZodLiteral<3>, z.ZodLiteral<4>]>;
205
+ text: z.ZodString;
206
+ }, "strip", z.ZodTypeAny, {
207
+ type: "heading";
208
+ text: string;
209
+ level: 2 | 3 | 4;
210
+ }, {
211
+ type: "heading";
212
+ text: string;
213
+ level: 2 | 3 | 4;
214
+ }>, z.ZodObject<{
215
+ type: z.ZodLiteral<"paragraph">;
216
+ text: z.ZodString;
217
+ }, "strip", z.ZodTypeAny, {
218
+ type: "paragraph";
219
+ text: string;
220
+ }, {
221
+ type: "paragraph";
222
+ text: string;
223
+ }>, z.ZodObject<{
224
+ type: z.ZodLiteral<"list">;
225
+ ordered: z.ZodBoolean;
226
+ items: z.ZodArray<z.ZodString, "many">;
227
+ }, "strip", z.ZodTypeAny, {
228
+ type: "list";
229
+ ordered: boolean;
230
+ items: string[];
231
+ }, {
232
+ type: "list";
233
+ ordered: boolean;
234
+ items: string[];
235
+ }>, z.ZodObject<{
236
+ type: z.ZodLiteral<"table">;
237
+ rows: z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">;
238
+ caption: z.ZodOptional<z.ZodString>;
239
+ }, "strip", z.ZodTypeAny, {
240
+ type: "table";
241
+ rows: string[][];
242
+ caption?: string | undefined;
243
+ }, {
244
+ type: "table";
245
+ rows: string[][];
246
+ caption?: string | undefined;
247
+ }>, z.ZodObject<{
248
+ type: z.ZodLiteral<"image">;
249
+ src: z.ZodString;
250
+ alt: z.ZodOptional<z.ZodString>;
251
+ caption: z.ZodOptional<z.ZodString>;
252
+ }, "strip", z.ZodTypeAny, {
253
+ type: "image";
254
+ src: string;
255
+ caption?: string | undefined;
256
+ alt?: string | undefined;
257
+ }, {
258
+ type: "image";
259
+ src: string;
260
+ caption?: string | undefined;
261
+ alt?: string | undefined;
262
+ }>]>, "many">;
263
+ }, "strip", z.ZodTypeAny, {
264
+ title: string;
265
+ id: string;
266
+ level: 2 | 3 | 1;
267
+ blocks: ({
268
+ type: "heading";
269
+ text: string;
270
+ level: 2 | 3 | 4;
271
+ } | {
272
+ type: "paragraph";
273
+ text: string;
274
+ } | {
275
+ type: "list";
276
+ ordered: boolean;
277
+ items: string[];
278
+ } | {
279
+ type: "table";
280
+ rows: string[][];
281
+ caption?: string | undefined;
282
+ } | {
283
+ type: "image";
284
+ src: string;
285
+ caption?: string | undefined;
286
+ alt?: string | undefined;
287
+ })[];
288
+ }, {
289
+ title: string;
290
+ id: string;
291
+ level: 2 | 3 | 1;
292
+ blocks: ({
293
+ type: "heading";
294
+ text: string;
295
+ level: 2 | 3 | 4;
296
+ } | {
297
+ type: "paragraph";
298
+ text: string;
299
+ } | {
300
+ type: "list";
301
+ ordered: boolean;
302
+ items: string[];
303
+ } | {
304
+ type: "table";
305
+ rows: string[][];
306
+ caption?: string | undefined;
307
+ } | {
308
+ type: "image";
309
+ src: string;
310
+ caption?: string | undefined;
311
+ alt?: string | undefined;
312
+ })[];
313
+ }>, "many">;
314
+ }, "strip", z.ZodTypeAny, {
315
+ meta: {
316
+ title: string;
317
+ docNo: string;
318
+ tenderer: string;
319
+ version: string;
320
+ generatedAt: string;
321
+ generator?: string | undefined;
322
+ };
323
+ page: {
324
+ size: "A4" | "Letter" | {
325
+ width: number;
326
+ height: number;
327
+ };
328
+ margins: {
329
+ top: number;
330
+ right: number;
331
+ bottom: number;
332
+ left: number;
333
+ };
334
+ header?: {
335
+ template: string;
336
+ showOnFirstPage: boolean;
337
+ } | undefined;
338
+ footer?: {
339
+ template: string;
340
+ } | undefined;
341
+ watermark?: {
342
+ text: string;
343
+ opacity: number;
344
+ } | undefined;
345
+ };
346
+ sections: {
347
+ title: string;
348
+ id: string;
349
+ level: 2 | 3 | 1;
350
+ blocks: ({
351
+ type: "heading";
352
+ text: string;
353
+ level: 2 | 3 | 4;
354
+ } | {
355
+ type: "paragraph";
356
+ text: string;
357
+ } | {
358
+ type: "list";
359
+ ordered: boolean;
360
+ items: string[];
361
+ } | {
362
+ type: "table";
363
+ rows: string[][];
364
+ caption?: string | undefined;
365
+ } | {
366
+ type: "image";
367
+ src: string;
368
+ caption?: string | undefined;
369
+ alt?: string | undefined;
370
+ })[];
371
+ }[];
372
+ }, {
373
+ meta: {
374
+ title: string;
375
+ docNo: string;
376
+ tenderer: string;
377
+ version: string;
378
+ generatedAt: string;
379
+ generator?: string | undefined;
380
+ };
381
+ page: {
382
+ size: "A4" | "Letter" | {
383
+ width: number;
384
+ height: number;
385
+ };
386
+ margins: {
387
+ top: number;
388
+ right: number;
389
+ bottom: number;
390
+ left: number;
391
+ };
392
+ header?: {
393
+ template: string;
394
+ showOnFirstPage: boolean;
395
+ } | undefined;
396
+ footer?: {
397
+ template: string;
398
+ } | undefined;
399
+ watermark?: {
400
+ text: string;
401
+ opacity: number;
402
+ } | undefined;
403
+ };
404
+ sections: {
405
+ title: string;
406
+ id: string;
407
+ level: 2 | 3 | 1;
408
+ blocks: ({
409
+ type: "heading";
410
+ text: string;
411
+ level: 2 | 3 | 4;
412
+ } | {
413
+ type: "paragraph";
414
+ text: string;
415
+ } | {
416
+ type: "list";
417
+ ordered: boolean;
418
+ items: string[];
419
+ } | {
420
+ type: "table";
421
+ rows: string[][];
422
+ caption?: string | undefined;
423
+ } | {
424
+ type: "image";
425
+ src: string;
426
+ caption?: string | undefined;
427
+ alt?: string | undefined;
428
+ })[];
429
+ }[];
430
+ }>;
431
+ declare function validateBid(input: unknown): z.SafeParseReturnType<{
432
+ meta: {
433
+ title: string;
434
+ docNo: string;
435
+ tenderer: string;
436
+ version: string;
437
+ generatedAt: string;
438
+ generator?: string | undefined;
439
+ };
440
+ page: {
441
+ size: "A4" | "Letter" | {
442
+ width: number;
443
+ height: number;
444
+ };
445
+ margins: {
446
+ top: number;
447
+ right: number;
448
+ bottom: number;
449
+ left: number;
450
+ };
451
+ header?: {
452
+ template: string;
453
+ showOnFirstPage: boolean;
454
+ } | undefined;
455
+ footer?: {
456
+ template: string;
457
+ } | undefined;
458
+ watermark?: {
459
+ text: string;
460
+ opacity: number;
461
+ } | undefined;
462
+ };
463
+ sections: {
464
+ title: string;
465
+ id: string;
466
+ level: 2 | 3 | 1;
467
+ blocks: ({
468
+ type: "heading";
469
+ text: string;
470
+ level: 2 | 3 | 4;
471
+ } | {
472
+ type: "paragraph";
473
+ text: string;
474
+ } | {
475
+ type: "list";
476
+ ordered: boolean;
477
+ items: string[];
478
+ } | {
479
+ type: "table";
480
+ rows: string[][];
481
+ caption?: string | undefined;
482
+ } | {
483
+ type: "image";
484
+ src: string;
485
+ caption?: string | undefined;
486
+ alt?: string | undefined;
487
+ })[];
488
+ }[];
489
+ }, {
490
+ meta: {
491
+ title: string;
492
+ docNo: string;
493
+ tenderer: string;
494
+ version: string;
495
+ generatedAt: string;
496
+ generator?: string | undefined;
497
+ };
498
+ page: {
499
+ size: "A4" | "Letter" | {
500
+ width: number;
501
+ height: number;
502
+ };
503
+ margins: {
504
+ top: number;
505
+ right: number;
506
+ bottom: number;
507
+ left: number;
508
+ };
509
+ header?: {
510
+ template: string;
511
+ showOnFirstPage: boolean;
512
+ } | undefined;
513
+ footer?: {
514
+ template: string;
515
+ } | undefined;
516
+ watermark?: {
517
+ text: string;
518
+ opacity: number;
519
+ } | undefined;
520
+ };
521
+ sections: {
522
+ title: string;
523
+ id: string;
524
+ level: 2 | 3 | 1;
525
+ blocks: ({
526
+ type: "heading";
527
+ text: string;
528
+ level: 2 | 3 | 4;
529
+ } | {
530
+ type: "paragraph";
531
+ text: string;
532
+ } | {
533
+ type: "list";
534
+ ordered: boolean;
535
+ items: string[];
536
+ } | {
537
+ type: "table";
538
+ rows: string[][];
539
+ caption?: string | undefined;
540
+ } | {
541
+ type: "image";
542
+ src: string;
543
+ caption?: string | undefined;
544
+ alt?: string | undefined;
545
+ })[];
546
+ }[];
547
+ }>;
548
+
549
+ interface BidEditorElement {
550
+ value: string;
551
+ type?: string;
552
+ level?: number;
553
+ listType?: 'ol' | 'ul';
554
+ listId?: string;
555
+ valueList?: Array<{
556
+ value: string;
557
+ [k: string]: unknown;
558
+ }>;
559
+ alt?: string;
560
+ tableId?: string;
561
+ trList?: unknown;
562
+ colspan?: number;
563
+ rowspan?: number;
564
+ }
565
+ declare function bidToEditorElements(sections: BidSection[]): BidEditorElement[];
566
+
567
+ declare function editorElementsToSections(elements: BidEditorElement[]): BidSection[];
568
+
569
+ declare class BidEditor$1 {
570
+ private readonly editor;
571
+ private readonly container;
572
+ private meta;
573
+ private page;
574
+ constructor(container: HTMLElement, bid: BidSchema);
575
+ load(bid: BidSchema): void;
576
+ getBid(): BidSchema;
577
+ getCommand(): unknown;
578
+ /** 直接暴露 canvas-editor 的 command,便于 hooks 模式访问 */
579
+ get command(): unknown;
580
+ destroy(): void;
581
+ }
582
+
583
+ /**
584
+ * 触发浏览器打印对话框,由用户选择"另存为 PDF"完成导出。
585
+ *
586
+ * canvas-editor 0.9.x 没有公开的 PDF 生成 API;
587
+ * M2 会评估接入 feature/pdf 实验分支或服务端生成方案。
588
+ */
589
+ declare function printBid(): void;
590
+
591
+ type Breakpoint = 'mobile' | 'tablet' | 'desktop';
592
+ /** 36 个工具栏按钮的 ID */
593
+ type ToolbarButtonId = 'font-family' | 'font-size' | 'bold' | 'italic' | 'underline' | 'strikeout' | 'superscript' | 'subscript' | 'color' | 'highlight' | 'align-left' | 'align-center' | 'align-right' | 'align-justify' | 'line-height' | 'h1' | 'h2' | 'h3' | 'h4' | 'list-ol' | 'list-ul' | 'indent' | 'outdent' | 'undo' | 'redo' | 'format-painter' | 'clear-format' | 'table' | 'image' | 'hyperlink' | 'separator' | 'page-break' | 'math' | 'control' | 'date' | 'comment';
594
+ type ToolbarDivider = '|';
595
+ type ToolbarItem = ToolbarButtonId | ToolbarDivider;
596
+ interface ToolbarGroupConfig {
597
+ id: string;
598
+ buttons: ToolbarItem[];
599
+ }
600
+ type ToolbarConfig = true | ToolbarItem[] | {
601
+ hide?: ToolbarButtonId[];
602
+ groups?: ToolbarGroupConfig[];
603
+ };
604
+ interface ThemeColors {
605
+ primary: string;
606
+ text: string;
607
+ border: string;
608
+ background: string;
609
+ hover: string;
610
+ active: string;
611
+ }
612
+ interface Theme {
613
+ colors: ThemeColors;
614
+ radius: {
615
+ button: number;
616
+ container: number;
617
+ };
618
+ spacing: {
619
+ button: number;
620
+ group: number;
621
+ };
622
+ fontSize: number;
623
+ fontFamily: string;
624
+ dark?: boolean;
625
+ }
626
+ interface ButtonRendererProps {
627
+ id: ToolbarButtonId;
628
+ active: boolean;
629
+ disabled: boolean;
630
+ onClick: () => void;
631
+ icon?: ReactNode;
632
+ label?: string;
633
+ shortcut?: string;
634
+ }
635
+ interface DropdownRendererProps {
636
+ children: ReactNode;
637
+ trigger: ReactNode;
638
+ open: boolean;
639
+ onOpenChange: (open: boolean) => void;
640
+ }
641
+ interface Renderers {
642
+ button?: Partial<Record<ToolbarButtonId, ComponentType<ButtonRendererProps>>>;
643
+ divider?: ComponentType;
644
+ dropdown?: ComponentType<DropdownRendererProps>;
645
+ toolbarContainer?: ComponentType<{
646
+ children: ReactNode;
647
+ }>;
648
+ aiDialog?: ComponentType<AIDialogRendererProps>;
649
+ }
650
+ interface BidEditorHandle {
651
+ getBid: () => BidSchema;
652
+ getCommand: () => unknown;
653
+ print: () => void;
654
+ focus: () => void;
655
+ }
656
+ interface BidEditorProps {
657
+ bid: BidSchema;
658
+ onChange?: (bid: BidSchema) => void;
659
+ readOnly?: boolean;
660
+ toolbar?: ToolbarConfig | false;
661
+ theme?: Partial<Theme>;
662
+ renderers?: Renderers;
663
+ fieldPanel?: boolean;
664
+ ai?: AIConfig;
665
+ breakpoint?: Breakpoint;
666
+ className?: string;
667
+ style?: CSSProperties;
668
+ ref?: Ref<BidEditorHandle>;
669
+ }
670
+ type AskFunction = (params: {
671
+ selectedText: string;
672
+ question: string;
673
+ fullDocument?: string;
674
+ }) => Promise<string>;
675
+ interface AIConfig {
676
+ /** 是否启用,默认 true。但 ask 未传时强制视为 false */
677
+ enabled?: boolean;
678
+ /** AI 调用函数。必传,否则菜单项不显示 */
679
+ ask: AskFunction;
680
+ /** 菜单项文字,默认 "AI 问答" */
681
+ label?: string;
682
+ /** 菜单项 icon(HTML 字符串,canvas-editor 菜单需要) */
683
+ iconHtml?: string;
684
+ /** 问题输入框 placeholder,默认 "问 AI 任何问题..." */
685
+ placeholder?: string;
686
+ /** 是否把整个文档纯文本作为上下文,默认 false */
687
+ includeFullDocument?: boolean;
688
+ }
689
+ type AIState = {
690
+ phase: 'closed';
691
+ } | {
692
+ phase: 'open';
693
+ selectedText: string;
694
+ } | {
695
+ phase: 'loading';
696
+ selectedText: string;
697
+ question: string;
698
+ } | {
699
+ phase: 'answered';
700
+ selectedText: string;
701
+ question: string;
702
+ answer: string;
703
+ } | {
704
+ phase: 'error';
705
+ selectedText: string;
706
+ question: string;
707
+ error: string;
708
+ };
709
+ interface AIDialogRendererProps {
710
+ state: AIState;
711
+ placeholder?: string;
712
+ onAsk: (question: string) => void;
713
+ onInsert: () => void;
714
+ onReplace: () => void;
715
+ onCopy: () => void;
716
+ onClose: () => void;
717
+ }
718
+
719
+ declare const BidEditor: react.ForwardRefExoticComponent<Omit<BidEditorProps, "ref"> & react.RefAttributes<BidEditorHandle>>;
720
+
721
+ export { type BidBlock, BidEditor, BidEditor$1 as BidEditorCore, type BidEditorElement, type BidEditorHandle, type BidEditorProps, type BidMeta, type BidPage, type BidPageFooter, type BidPageHeader, type BidPageMargins, type BidPageSize, type BidPageWatermark, type BidSchema, type BidSection, type Renderers, type Theme, type ToolbarButtonId, type ToolbarConfig, bidSchema, bidToEditorElements, editorElementsToSections, printBid, validateBid };