@particle-academy/react-fancy 5.67.0 → 5.69.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 (77) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/dist/ContentRenderer.types-RO_l7_6N.d.cts +137 -0
  3. package/dist/ContentRenderer.types-RO_l7_6N.d.ts +137 -0
  4. package/dist/{PastedFilesInput-Bt3KSTVN.d.ts → PastedFilesInput-BT5y95sb.d.ts} +2 -1
  5. package/dist/{PastedFilesInput-CUQeOeOA.d.cts → PastedFilesInput-Cd4k6a38.d.cts} +2 -1
  6. package/dist/{chunk-U5LKNGHU.cjs → chunk-2PSHIUM7.cjs} +8 -8
  7. package/dist/{chunk-U5LKNGHU.cjs.map → chunk-2PSHIUM7.cjs.map} +1 -1
  8. package/dist/{chunk-QSGAFKK2.js → chunk-4UEIMGHZ.js} +3 -3
  9. package/dist/{chunk-QSGAFKK2.js.map → chunk-4UEIMGHZ.js.map} +1 -1
  10. package/dist/{chunk-YIKXJWO4.js → chunk-4WIPWJYD.js} +5 -4
  11. package/dist/chunk-4WIPWJYD.js.map +1 -0
  12. package/dist/{chunk-7FYRFNPX.cjs → chunk-FPFQBYKJ.cjs} +9 -9
  13. package/dist/{chunk-7FYRFNPX.cjs.map → chunk-FPFQBYKJ.cjs.map} +1 -1
  14. package/dist/{chunk-23AVEYUP.js → chunk-HRZDEZSE.js} +24 -19
  15. package/dist/chunk-HRZDEZSE.js.map +1 -0
  16. package/dist/{chunk-SAG6DHQK.cjs → chunk-ISNS4GAW.cjs} +29 -24
  17. package/dist/chunk-ISNS4GAW.cjs.map +1 -0
  18. package/dist/{chunk-6CAXLP7D.cjs → chunk-J5TFVYYM.cjs} +6 -6
  19. package/dist/{chunk-6CAXLP7D.cjs.map → chunk-J5TFVYYM.cjs.map} +1 -1
  20. package/dist/{chunk-E5UU666U.cjs → chunk-KGJ2ORY6.cjs} +148 -56
  21. package/dist/chunk-KGJ2ORY6.cjs.map +1 -0
  22. package/dist/{chunk-HEY4SMS2.js → chunk-LLVYCACC.js} +10 -4
  23. package/dist/chunk-LLVYCACC.js.map +1 -0
  24. package/dist/{chunk-4S5DFN5N.cjs → chunk-O4KZYGGC.cjs} +17 -11
  25. package/dist/chunk-O4KZYGGC.cjs.map +1 -0
  26. package/dist/{chunk-DCAD2JPP.js → chunk-U4PWNLOH.js} +3 -3
  27. package/dist/{chunk-DCAD2JPP.js.map → chunk-U4PWNLOH.js.map} +1 -1
  28. package/dist/{chunk-B4LVQ4QI.js → chunk-YEGFOMJB.js} +3 -3
  29. package/dist/{chunk-B4LVQ4QI.js.map → chunk-YEGFOMJB.js.map} +1 -1
  30. package/dist/{chunk-HFK5SBNM.cjs → chunk-YJETQ76J.cjs} +5 -4
  31. package/dist/chunk-YJETQ76J.cjs.map +1 -0
  32. package/dist/{chunk-FXOT4P4P.js → chunk-Z6RA37IC.js} +148 -56
  33. package/dist/chunk-Z6RA37IC.js.map +1 -0
  34. package/dist/composer.cjs +4 -4
  35. package/dist/composer.js +2 -2
  36. package/dist/content-renderer.cjs +4 -4
  37. package/dist/content-renderer.d.cts +3 -72
  38. package/dist/content-renderer.d.ts +3 -72
  39. package/dist/content-renderer.js +1 -1
  40. package/dist/editor.cjs +4 -4
  41. package/dist/editor.d.cts +19 -2
  42. package/dist/editor.d.ts +19 -2
  43. package/dist/editor.js +2 -2
  44. package/dist/{index-XR5t8bTq.d.ts → index-BQi_n6eS.d.ts} +21 -3
  45. package/dist/{index-DWtSViJ3.d.cts → index-n_4_OZK_.d.cts} +21 -3
  46. package/dist/index.cjs +38 -38
  47. package/dist/index.d.cts +4 -4
  48. package/dist/index.d.ts +4 -4
  49. package/dist/index.js +7 -7
  50. package/dist/input.cjs +3 -3
  51. package/dist/input.js +2 -2
  52. package/dist/inputs.cjs +3 -3
  53. package/dist/inputs.js +2 -2
  54. package/dist/json-editor.cjs +14 -14
  55. package/dist/json-editor.js +3 -3
  56. package/dist/paste-pills.cjs +14 -14
  57. package/dist/paste-pills.d.cts +1 -1
  58. package/dist/paste-pills.d.ts +1 -1
  59. package/dist/paste-pills.js +1 -1
  60. package/dist/prompt-input.cjs +5 -5
  61. package/dist/prompt-input.d.cts +1 -1
  62. package/dist/prompt-input.d.ts +1 -1
  63. package/dist/prompt-input.js +2 -2
  64. package/docs/ContentRenderer.md +63 -6
  65. package/docs/Editor.md +38 -0
  66. package/docs/PromptInput.md +3 -2
  67. package/package.json +1 -1
  68. package/dist/chunk-23AVEYUP.js.map +0 -1
  69. package/dist/chunk-4S5DFN5N.cjs.map +0 -1
  70. package/dist/chunk-E5UU666U.cjs.map +0 -1
  71. package/dist/chunk-FXOT4P4P.js.map +0 -1
  72. package/dist/chunk-HEY4SMS2.js.map +0 -1
  73. package/dist/chunk-HFK5SBNM.cjs.map +0 -1
  74. package/dist/chunk-SAG6DHQK.cjs.map +0 -1
  75. package/dist/chunk-YIKXJWO4.js.map +0 -1
  76. package/dist/extensions-DiByZIpD.d.cts +0 -61
  77. package/dist/extensions-DiByZIpD.d.ts +0 -61
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var chunkU5LKNGHU_cjs = require('./chunk-U5LKNGHU.cjs');
3
+ var chunk2PSHIUM7_cjs = require('./chunk-2PSHIUM7.cjs');
4
4
  require('./chunk-2O5UXH5R.cjs');
5
5
  require('./chunk-TLRFXSPA.cjs');
6
- require('./chunk-6CAXLP7D.cjs');
6
+ require('./chunk-J5TFVYYM.cjs');
7
7
  require('./chunk-WKPBCB67.cjs');
8
8
  require('./chunk-MAZEX4EZ.cjs');
9
9
  require('./chunk-MRZXTL46.cjs');
@@ -12,7 +12,7 @@ require('./chunk-QF7CD4JH.cjs');
12
12
  require('./chunk-O3F6DYWR.cjs');
13
13
  require('./chunk-4XMBXG4K.cjs');
14
14
  require('./chunk-GKLETY7D.cjs');
15
- require('./chunk-HFK5SBNM.cjs');
15
+ require('./chunk-YJETQ76J.cjs');
16
16
  require('./chunk-MKGWHSNV.cjs');
17
17
  require('./chunk-KJ22KE56.cjs');
18
18
  require('./chunk-L3V3BYVS.cjs');
@@ -33,47 +33,47 @@ require('./chunk-ZU5Q77OT.cjs');
33
33
 
34
34
  Object.defineProperty(exports, "JsonEditor", {
35
35
  enumerable: true,
36
- get: function () { return chunkU5LKNGHU_cjs.JsonEditor; }
36
+ get: function () { return chunk2PSHIUM7_cjs.JsonEditor; }
37
37
  });
38
38
  Object.defineProperty(exports, "applyJsonEdit", {
39
39
  enumerable: true,
40
- get: function () { return chunkU5LKNGHU_cjs.applyJsonEdit; }
40
+ get: function () { return chunk2PSHIUM7_cjs.applyJsonEdit; }
41
41
  });
42
42
  Object.defineProperty(exports, "describeEdit", {
43
43
  enumerable: true,
44
- get: function () { return chunkU5LKNGHU_cjs.describeEdit; }
44
+ get: function () { return chunk2PSHIUM7_cjs.describeEdit; }
45
45
  });
46
46
  Object.defineProperty(exports, "findJsonConflicts", {
47
47
  enumerable: true,
48
- get: function () { return chunkU5LKNGHU_cjs.findJsonConflicts; }
48
+ get: function () { return chunk2PSHIUM7_cjs.findJsonConflicts; }
49
49
  });
50
50
  Object.defineProperty(exports, "getAtPath", {
51
51
  enumerable: true,
52
- get: function () { return chunkU5LKNGHU_cjs.getAtPath; }
52
+ get: function () { return chunk2PSHIUM7_cjs.getAtPath; }
53
53
  });
54
54
  Object.defineProperty(exports, "inferType", {
55
55
  enumerable: true,
56
- get: function () { return chunkU5LKNGHU_cjs.inferType; }
56
+ get: function () { return chunk2PSHIUM7_cjs.inferType; }
57
57
  });
58
58
  Object.defineProperty(exports, "parseKeyMap", {
59
59
  enumerable: true,
60
- get: function () { return chunkU5LKNGHU_cjs.parseKeyMap; }
60
+ get: function () { return chunk2PSHIUM7_cjs.parseKeyMap; }
61
61
  });
62
62
  Object.defineProperty(exports, "parsePath", {
63
63
  enumerable: true,
64
- get: function () { return chunkU5LKNGHU_cjs.parsePath; }
64
+ get: function () { return chunk2PSHIUM7_cjs.parsePath; }
65
65
  });
66
66
  Object.defineProperty(exports, "pathToString", {
67
67
  enumerable: true,
68
- get: function () { return chunkU5LKNGHU_cjs.pathToString; }
68
+ get: function () { return chunk2PSHIUM7_cjs.pathToString; }
69
69
  });
70
70
  Object.defineProperty(exports, "resolveKeyRule", {
71
71
  enumerable: true,
72
- get: function () { return chunkU5LKNGHU_cjs.resolveKeyRule; }
72
+ get: function () { return chunk2PSHIUM7_cjs.resolveKeyRule; }
73
73
  });
74
74
  Object.defineProperty(exports, "typeMatches", {
75
75
  enumerable: true,
76
- get: function () { return chunkU5LKNGHU_cjs.typeMatches; }
76
+ get: function () { return chunk2PSHIUM7_cjs.typeMatches; }
77
77
  });
78
78
  //# sourceMappingURL=json-editor.cjs.map
79
79
  //# sourceMappingURL=json-editor.cjs.map
@@ -1,7 +1,7 @@
1
- export { JsonEditor, applyJsonEdit, describeEdit, findJsonConflicts, getAtPath, inferType, parseKeyMap, parsePath, pathToString, resolveKeyRule, typeMatches } from './chunk-DCAD2JPP.js';
1
+ export { JsonEditor, applyJsonEdit, describeEdit, findJsonConflicts, getAtPath, inferType, parseKeyMap, parsePath, pathToString, resolveKeyRule, typeMatches } from './chunk-U4PWNLOH.js';
2
2
  import './chunk-DXZCKDYS.js';
3
3
  import './chunk-2UTN3EFK.js';
4
- import './chunk-B4LVQ4QI.js';
4
+ import './chunk-YEGFOMJB.js';
5
5
  import './chunk-FVI4JDLA.js';
6
6
  import './chunk-UVUBV4VZ.js';
7
7
  import './chunk-KXYMMNNV.js';
@@ -10,7 +10,7 @@ import './chunk-5WQ6FPSP.js';
10
10
  import './chunk-USWQAMI3.js';
11
11
  import './chunk-XM3V3RSU.js';
12
12
  import './chunk-SVSQXKFL.js';
13
- import './chunk-YIKXJWO4.js';
13
+ import './chunk-4WIPWJYD.js';
14
14
  import './chunk-QTS4Q2NK.js';
15
15
  import './chunk-OL53XYHF.js';
16
16
  import './chunk-NRXK42LO.js';
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkHFK5SBNM_cjs = require('./chunk-HFK5SBNM.cjs');
3
+ var chunkYJETQ76J_cjs = require('./chunk-YJETQ76J.cjs');
4
4
  require('./chunk-MKGWHSNV.cjs');
5
5
  require('./chunk-J2DI6RMR.cjs');
6
6
  require('./chunk-MKHYENKR.cjs');
@@ -14,55 +14,55 @@ require('./chunk-ZU5Q77OT.cjs');
14
14
 
15
15
  Object.defineProperty(exports, "HOST_ATTR", {
16
16
  enumerable: true,
17
- get: function () { return chunkHFK5SBNM_cjs.HOST_ATTR; }
17
+ get: function () { return chunkYJETQ76J_cjs.HOST_ATTR; }
18
18
  });
19
19
  Object.defineProperty(exports, "InlinePasteEditor", {
20
20
  enumerable: true,
21
- get: function () { return chunkHFK5SBNM_cjs.InlinePasteEditor; }
21
+ get: function () { return chunkYJETQ76J_cjs.InlinePasteEditor; }
22
22
  });
23
23
  Object.defineProperty(exports, "InlinePill", {
24
24
  enumerable: true,
25
- get: function () { return chunkHFK5SBNM_cjs.InlinePill; }
25
+ get: function () { return chunkYJETQ76J_cjs.InlinePill; }
26
26
  });
27
27
  Object.defineProperty(exports, "PILL_MARK", {
28
28
  enumerable: true,
29
- get: function () { return chunkHFK5SBNM_cjs.PILL_MARK; }
29
+ get: function () { return chunkYJETQ76J_cjs.PILL_MARK; }
30
30
  });
31
31
  Object.defineProperty(exports, "PastedFilesInput", {
32
32
  enumerable: true,
33
- get: function () { return chunkHFK5SBNM_cjs.PastedFilesInput; }
33
+ get: function () { return chunkYJETQ76J_cjs.PastedFilesInput; }
34
34
  });
35
35
  Object.defineProperty(exports, "endsOf", {
36
36
  enumerable: true,
37
- get: function () { return chunkHFK5SBNM_cjs.endsOf; }
37
+ get: function () { return chunkYJETQ76J_cjs.endsOf; }
38
38
  });
39
39
  Object.defineProperty(exports, "expandMarkers", {
40
40
  enumerable: true,
41
- get: function () { return chunkHFK5SBNM_cjs.expandMarkers; }
41
+ get: function () { return chunkYJETQ76J_cjs.expandMarkers; }
42
42
  });
43
43
  Object.defineProperty(exports, "markedIds", {
44
44
  enumerable: true,
45
- get: function () { return chunkHFK5SBNM_cjs.markedIds; }
45
+ get: function () { return chunkYJETQ76J_cjs.markedIds; }
46
46
  });
47
47
  Object.defineProperty(exports, "pasteMarker", {
48
48
  enumerable: true,
49
- get: function () { return chunkHFK5SBNM_cjs.pasteMarker; }
49
+ get: function () { return chunkYJETQ76J_cjs.pasteMarker; }
50
50
  });
51
51
  Object.defineProperty(exports, "segmentValue", {
52
52
  enumerable: true,
53
- get: function () { return chunkHFK5SBNM_cjs.segmentValue; }
53
+ get: function () { return chunkYJETQ76J_cjs.segmentValue; }
54
54
  });
55
55
  Object.defineProperty(exports, "useInlinePaste", {
56
56
  enumerable: true,
57
- get: function () { return chunkHFK5SBNM_cjs.useInlinePaste; }
57
+ get: function () { return chunkYJETQ76J_cjs.useInlinePaste; }
58
58
  });
59
59
  Object.defineProperty(exports, "usePastePills", {
60
60
  enumerable: true,
61
- get: function () { return chunkHFK5SBNM_cjs.usePastePills; }
61
+ get: function () { return chunkYJETQ76J_cjs.usePastePills; }
62
62
  });
63
63
  Object.defineProperty(exports, "withSeparators", {
64
64
  enumerable: true,
65
- get: function () { return chunkHFK5SBNM_cjs.withSeparators; }
65
+ get: function () { return chunkYJETQ76J_cjs.withSeparators; }
66
66
  });
67
67
  //# sourceMappingURL=paste-pills.cjs.map
68
68
  //# sourceMappingURL=paste-pills.cjs.map
@@ -1,6 +1,6 @@
1
1
  import { C as ComposerPastePreview, a as ComposerPasteClassNames } from './PastePills.types-CpXzsuwJ.cjs';
2
2
  export { H as HeldImage, b as HeldPaste, P as PILL_MARK, c as PasteClassNames, d as PasteEventLike, e as PastePreview, U as UsePastePillsOptions, f as UsePastePillsResult, V as ValueSegment, g as expandMarkers, m as markedIds, p as pasteMarker, s as segmentValue, u as usePastePills } from './PastePills.types-CpXzsuwJ.cjs';
3
- export { H as HOST_ATTR, I as InlinePasteEditor, a as InlinePasteEditorHandle, P as PastedFilesInput, b as PastedFilesInputProps, c as PillToInsert, U as UseInlinePasteOptions, u as useInlinePaste } from './PastedFilesInput-CUQeOeOA.cjs';
3
+ export { H as HOST_ATTR, I as InlinePasteEditor, a as InlinePasteEditorHandle, P as PastedFilesInput, b as PastedFilesInputProps, c as PillToInsert, U as UseInlinePasteOptions, u as useInlinePaste } from './PastedFilesInput-Cd4k6a38.cjs';
4
4
  import * as react from 'react';
5
5
  import { ReactNode } from 'react';
6
6
 
@@ -1,6 +1,6 @@
1
1
  import { C as ComposerPastePreview, a as ComposerPasteClassNames } from './PastePills.types-CpXzsuwJ.js';
2
2
  export { H as HeldImage, b as HeldPaste, P as PILL_MARK, c as PasteClassNames, d as PasteEventLike, e as PastePreview, U as UsePastePillsOptions, f as UsePastePillsResult, V as ValueSegment, g as expandMarkers, m as markedIds, p as pasteMarker, s as segmentValue, u as usePastePills } from './PastePills.types-CpXzsuwJ.js';
3
- export { H as HOST_ATTR, I as InlinePasteEditor, a as InlinePasteEditorHandle, P as PastedFilesInput, b as PastedFilesInputProps, c as PillToInsert, U as UseInlinePasteOptions, u as useInlinePaste } from './PastedFilesInput-Bt3KSTVN.js';
3
+ export { H as HOST_ATTR, I as InlinePasteEditor, a as InlinePasteEditorHandle, P as PastedFilesInput, b as PastedFilesInputProps, c as PillToInsert, U as UseInlinePasteOptions, u as useInlinePaste } from './PastedFilesInput-BT5y95sb.js';
4
4
  import * as react from 'react';
5
5
  import { ReactNode } from 'react';
6
6
 
@@ -1,4 +1,4 @@
1
- export { HOST_ATTR, InlinePasteEditor, InlinePill, PILL_MARK, PastedFilesInput, endsOf, expandMarkers, markedIds, pasteMarker, segmentValue, useInlinePaste, usePastePills, withSeparators } from './chunk-YIKXJWO4.js';
1
+ export { HOST_ATTR, InlinePasteEditor, InlinePill, PILL_MARK, PastedFilesInput, endsOf, expandMarkers, markedIds, pasteMarker, segmentValue, useInlinePaste, usePastePills, withSeparators } from './chunk-4WIPWJYD.js';
2
2
  import './chunk-QTS4Q2NK.js';
3
3
  import './chunk-MQ6VGG62.js';
4
4
  import './chunk-5VMILVWD.js';
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var chunkSAG6DHQK_cjs = require('./chunk-SAG6DHQK.cjs');
3
+ var chunkISNS4GAW_cjs = require('./chunk-ISNS4GAW.cjs');
4
4
  require('./chunk-OASSZI6M.cjs');
5
5
  require('./chunk-I27K6NLX.cjs');
6
6
  require('./chunk-AIA5UNQ5.cjs');
7
- require('./chunk-HFK5SBNM.cjs');
7
+ require('./chunk-YJETQ76J.cjs');
8
8
  require('./chunk-MKGWHSNV.cjs');
9
9
  require('./chunk-J2DI6RMR.cjs');
10
10
  require('./chunk-MKHYENKR.cjs');
@@ -22,15 +22,15 @@ require('./chunk-ZU5Q77OT.cjs');
22
22
 
23
23
  Object.defineProperty(exports, "PromptInput", {
24
24
  enumerable: true,
25
- get: function () { return chunkSAG6DHQK_cjs.PromptInput; }
25
+ get: function () { return chunkISNS4GAW_cjs.PromptInput; }
26
26
  });
27
27
  Object.defineProperty(exports, "promptDataUrlToFile", {
28
28
  enumerable: true,
29
- get: function () { return chunkSAG6DHQK_cjs.promptDataUrlToFile; }
29
+ get: function () { return chunkISNS4GAW_cjs.promptDataUrlToFile; }
30
30
  });
31
31
  Object.defineProperty(exports, "promptFileToDataUrl", {
32
32
  enumerable: true,
33
- get: function () { return chunkSAG6DHQK_cjs.promptFileToDataUrl; }
33
+ get: function () { return chunkISNS4GAW_cjs.promptFileToDataUrl; }
34
34
  });
35
35
  //# sourceMappingURL=prompt-input.cjs.map
36
36
  //# sourceMappingURL=prompt-input.cjs.map
@@ -1,3 +1,3 @@
1
- export { a as PromptAttachment, b as PromptCmd, c as PromptDraft, d as PromptDraftFile, e as PromptDraftPill, f as PromptInput, g as PromptInputHandle, h as PromptInputProps, i as PromptMention, j as PromptSetDraftOptions, p as promptDataUrlToFile, n as promptFileToDataUrl } from './index-DWtSViJ3.cjs';
1
+ export { a as PromptAttachment, b as PromptCmd, c as PromptDraft, d as PromptDraftFile, e as PromptDraftPill, f as PromptFocusOptions, g as PromptInput, h as PromptInputHandle, i as PromptInputProps, j as PromptMention, k as PromptSetDraftOptions, p as promptDataUrlToFile, o as promptFileToDataUrl } from './index-n_4_OZK_.cjs';
2
2
  import 'react';
3
3
  import './PastePills.types-CpXzsuwJ.cjs';
@@ -1,3 +1,3 @@
1
- export { a as PromptAttachment, b as PromptCmd, c as PromptDraft, d as PromptDraftFile, e as PromptDraftPill, f as PromptInput, g as PromptInputHandle, h as PromptInputProps, i as PromptMention, j as PromptSetDraftOptions, p as promptDataUrlToFile, n as promptFileToDataUrl } from './index-XR5t8bTq.js';
1
+ export { a as PromptAttachment, b as PromptCmd, c as PromptDraft, d as PromptDraftFile, e as PromptDraftPill, f as PromptFocusOptions, g as PromptInput, h as PromptInputHandle, i as PromptInputProps, j as PromptMention, k as PromptSetDraftOptions, p as promptDataUrlToFile, o as promptFileToDataUrl } from './index-BQi_n6eS.js';
2
2
  import 'react';
3
3
  import './PastePills.types-CpXzsuwJ.js';
@@ -1,8 +1,8 @@
1
- export { PromptInput, promptDataUrlToFile, promptFileToDataUrl } from './chunk-23AVEYUP.js';
1
+ export { PromptInput, promptDataUrlToFile, promptFileToDataUrl } from './chunk-HRZDEZSE.js';
2
2
  import './chunk-GR2WKBER.js';
3
3
  import './chunk-SV5BW3IA.js';
4
4
  import './chunk-TJ66S5K6.js';
5
- import './chunk-YIKXJWO4.js';
5
+ import './chunk-4WIPWJYD.js';
6
6
  import './chunk-QTS4Q2NK.js';
7
7
  import './chunk-MQ6VGG62.js';
8
8
  import './chunk-5VMILVWD.js';
@@ -27,7 +27,7 @@ import { ContentRenderer } from "@particle-academy/react-fancy";
27
27
  | copyButtons | `boolean \| { code?: boolean; table?: boolean }` | `true` | Copy buttons on code blocks and tables. See **Copy buttons**. |
28
28
  | onCopy | `(event: ContentCopyEvent) => void` | - | Called after every copy attempt, successful or not |
29
29
  | clipboardWriter | `ContentClipboardWriter` | - | Host-supplied clipboard writer. See **Clipboard writer**. |
30
- | streaming | `boolean` | `false` | The value is still arriving: hold back an unfinished trailing tag or fence. See **Streaming**. |
30
+ | streaming | `boolean \| "progressive"` | `false` | The value is still arriving. `true` holds back an unfinished trailing tag or fence; `"progressive"` shows it as it fills. See **Streaming**. |
31
31
 
32
32
  ## Copy buttons
33
33
 
@@ -43,7 +43,10 @@ Every code block and table gets a react-fancy `Button` (icon `copy`, then
43
43
  survives a paste into a spreadsheet.
44
44
 
45
45
  Each copy is announced as `Copied` or `Copy failed` through a polite
46
- `aria-live` region (`[data-react-fancy-content-renderer-live]`).
46
+ `aria-live` region (`[data-react-fancy-content-renderer-live]`). The region is
47
+ visually hidden with inline sr-only styles, so it needs nothing from your
48
+ Tailwind build. It is `position: absolute`, so the root is `position: relative`
49
+ unless your `className` already positions it.
47
50
 
48
51
  ```tsx
49
52
  <ContentRenderer value={reply} copyButtons={false} /> // none
@@ -89,7 +92,8 @@ than state. Copy follows that:
89
92
  | `data-copy-state="idle" \| "copied" \| "failed"` | the copy button |
90
93
  | `data-react-fancy-content-copy-block="code" \| "table"` | the wrapper around the block |
91
94
  | `data-react-fancy-content-renderer-live` | the live region |
92
- | `data-streaming="true"` | the root, while `streaming` |
95
+ | `data-streaming="true"` | the root, while `streaming` (either mode) |
96
+ | `data-streaming-mode="progressive"` | the root, while `streaming="progressive"` |
93
97
 
94
98
  `onCopy` receives `{ kind, index, text, html, ok }`, where `index` is the
95
99
  button's position among this renderer's copy buttons in document order. Wire it
@@ -117,6 +121,50 @@ A `<` that cannot become a registered tag is prose and always renders
117
121
  A lone `<` at the very end is held for one chunk, because it may be the start of
118
122
  a tag. When `streaming` goes back to `false`, everything renders.
119
123
 
124
+ ### Progressive streaming
125
+
126
+ `streaming={true}` hides an open block until it closes. Pass
127
+ `streaming="progressive"` to show it as it fills instead:
128
+
129
+ ```tsx
130
+ <ContentRenderer
131
+ value={partial}
132
+ streaming={done ? false : "progressive"}
133
+ extensions={[resultTag]}
134
+ />
135
+ ```
136
+
137
+ - An open tag of a registered extension whose **opening tag is complete**
138
+ renders its component straight away, with the body that has arrived so far.
139
+ A `markdown` extension gets that body as `content` and rendered as
140
+ `children`, through the same pipeline as the final render: converted,
141
+ sanitised, nested extensions, copy buttons on finished blocks.
142
+ - An open code fence renders as a code block of what has arrived, in its
143
+ language. It gets **no copy button until it closes**; copying half a block
144
+ is never what anyone means, and a disabled button would still invite the
145
+ click. Finished code blocks and tables before it keep theirs.
146
+ - Still held back, exactly as in `streaming={true}`: a **partial opening tag**
147
+ (`<`, `<res`, `<result title="Do`), so it never flashes raw; a partial
148
+ closing tag (`</res`), with the body above it still showing; a fence marker
149
+ still arriving (` `` `). Also held: a fence opener line with no newline yet
150
+ (` ```ja `), because its language may be cut off.
151
+ - Inside an open fence, `<` is code and is never held.
152
+
153
+ It works by closing what is open: the open fence gets its own closing marker
154
+ and every open registered tag gets its closing tag, innermost first, and the
155
+ result renders normally. So the rendered body is the same one the final render
156
+ produces once the real closing tags arrive; only what is still to come is
157
+ missing.
158
+
159
+ The lifting rules below do not change in this mode. A `markdown` tag whose
160
+ opening tag is mid-line is not lifted while streaming, any more than it is once
161
+ it closes: it is matched in the HTML, as the final render will match it.
162
+
163
+ **Why a value of `streaming` rather than a second prop:** progressive is a way
164
+ of streaming, not something separate, and a separate boolean would add a
165
+ combination that means nothing (progressive while not streaming). A host that
166
+ already writes `streaming={!done}` changes one expression.
167
+
120
168
  ## Sanitization
121
169
 
122
170
  Since v2.5.0, `ContentRenderer` sanitizes its rendered output by default:
@@ -208,11 +256,20 @@ const resultTag: RenderExtension = {
208
256
  - `content` is the raw markdown body; `children` is that body rendered through
209
257
  the same pipeline as everything else: sanitised, with nested extensions and
210
258
  copy buttons. **Render `children`, not `content`.**
211
- - A tag is lifted when its opening tag starts a line and it has a matching
212
- closing tag. Same-name nesting is balanced, other markdown tags nest inside
213
- it, and a tag inside a code fence or inline code is left alone.
259
+ - A tag is lifted **only** when its opening tag starts a line (after at most
260
+ three spaces) **and** it has a matching closing tag. Same-name nesting is
261
+ balanced, other markdown tags nest inside it, and a tag inside a code fence
262
+ or inline code is left alone.
214
263
  - Anywhere else (mid-line, unclosed, or in HTML content) it is matched in the
215
264
  HTML as before, and `children` renders that HTML body.
265
+ - **Both conditions are deliberate and will stay.** A tag that starts a line
266
+ and closes is an unambiguous block. A mid-line `<result>` is text that
267
+ happens to contain a tag name, and an unclosed one has no end to its body, so
268
+ lifting either would turn prose (or a model quoting the tag) into a
269
+ component. To get a block, put the opening tag on its own line and close it.
270
+ `streaming="progressive"` renders an open block early, but it does so by
271
+ supplying the close the final render will see; it does not relax either
272
+ rule.
216
273
  - Nesting stops at depth 8: deeper bodies render as plain sanitised content.
217
274
 
218
275
  Sanitisation is unchanged by lifting. Every piece of markdown, including each
package/docs/Editor.md CHANGED
@@ -29,6 +29,7 @@ import { Editor } from "@particle-academy/react-fancy";
29
29
  | outputFormat | `"html" \| "markdown"` | `"html"` | Output format for the onChange value |
30
30
  | lineSpacing | `number` | `1.6` | Line height for content area |
31
31
  | placeholder | `string` | - | Placeholder text |
32
+ | mode | `"edit" \| "view"` | `"edit"` | `"view"` renders the value read-only through `ContentRenderer`. Resolution: this prop, then the nearest `<Form>` context, then `"edit"`. See **View mode** |
32
33
  | extensions | `RenderExtension[]` | - | Per-instance render extensions (merged with global) |
33
34
  | showSource | `boolean` | - | Controlled source-view flag. When `true`, the content area shows the raw `value` (in `outputFormat`) in an editable `<textarea>` |
34
35
  | defaultShowSource | `boolean` | `false` | Initial source-view flag when uncontrolled |
@@ -37,6 +38,9 @@ import { Editor } from "@particle-academy/react-fancy";
37
38
  | defaultFullScreen | `boolean` | `false` | Initial full-screen flag when uncontrolled |
38
39
  | onFullScreenChange | `(fullScreen: boolean) => void` | - | Fired by the toggle, Escape, an agent, or the user leaving the browser's full screen |
39
40
  | fullScreenMode | `"overlay" \| "native"` | `"overlay"` | `overlay` covers the viewport in place and always works; `native` uses the browser Fullscreen API and falls back to the overlay. See [FullScreen](./FullScreen.md) |
41
+ | copyButtons | `boolean \| { code?: boolean; table?: boolean }` | `true` | View mode only. Copy buttons on code blocks and tables, forwarded to `ContentRenderer`. `false` turns them off; `{ table: false }` keeps code only. See **View mode** |
42
+ | clipboardWriter | `ContentClipboardWriter` | - | View mode only. Host-supplied clipboard writer, forwarded to `ContentRenderer` (e.g. Electron's `clipboard` in a sandboxed window) |
43
+ | onCopy | `(event: ContentCopyEvent) => void` | - | View mode only. Called after every copy attempt, successful or not, forwarded to `ContentRenderer` |
40
44
  | className | `string` | - | Additional CSS classes |
41
45
 
42
46
  ### Editor.Toolbar
@@ -129,6 +133,40 @@ A host's own actions belong in `toolbarExtra`, not in `children`: children repla
129
133
  </Editor>
130
134
  ```
131
135
 
136
+ ## View mode
137
+
138
+ `mode="view"` (or a `<Form mode="view">` around the editor) renders the value
139
+ read-only through [`ContentRenderer`](./ContentRenderer.md) instead of the
140
+ toolbar and editable surface. `extensions`, `unsafe` and `lineSpacing` reach the
141
+ renderer, and so do the copy props:
142
+
143
+ | Editor prop | ContentRenderer prop | Default |
144
+ |-------------|----------------------|---------|
145
+ | `copyButtons` | `copyButtons` | `true`: a copy button on every code block and table |
146
+ | `clipboardWriter` | `clipboardWriter` | text/html + text/plain via `ClipboardItem`, falling back to `writeText` |
147
+ | `onCopy` | `onCopy` | - |
148
+
149
+ Same types and same defaults as on `ContentRenderer`; leaving them out changes
150
+ nothing. They have no effect in edit mode.
151
+
152
+ ```tsx
153
+ import { clipboard } from "electron";
154
+
155
+ <Editor
156
+ value={doc}
157
+ mode="view"
158
+ outputFormat="markdown"
159
+ clipboardWriter={({ text, html }) => clipboard.write({ text, html })}
160
+ onCopy={(e) => activity.push({ type: "copy", kind: e.kind, ok: e.ok })}
161
+ >
162
+ <Editor.Content />
163
+ </Editor>
164
+
165
+ <Editor value={doc} mode="view" copyButtons={false}> {/* no buttons */}
166
+ <Editor.Content />
167
+ </Editor>
168
+ ```
169
+
132
170
  ## Source View
133
171
 
134
172
  The default toolbar includes a **Source** toggle (`</>`) on the right. Clicking it
@@ -83,6 +83,7 @@ if (saved) composer.current!.setDraft(JSON.parse(saved));
83
83
  ```
84
84
 
85
85
  - `setDraft(draft, { focus?: false })` does **not** focus unless you pass `{ focus: true }`. It never moves the caret of whatever does have focus.
86
+ - Focus from `focus()` or `setDraft(draft, { focus: true })` never scrolls the page or any ancestor (it passes `{ preventScroll: true }`). To let the browser scroll the composer into view, pass `{ preventScroll: false }` to either.
86
87
  - `setDraft` does not call `onChange` / `onDraftChange`. You set the draft yourself, so you already have it.
87
88
  - A draft with an unknown `v` is refused with a console warning.
88
89
 
@@ -151,8 +152,8 @@ interface PromptDraft { v: 1; text: string; pills: PromptDraftPill[]; attachment
151
152
 
152
153
  interface PromptInputHandle {
153
154
  getDraft(): PromptDraft;
154
- setDraft(draft: PromptDraft, options?: { focus?: boolean }): void;
155
- focus(): void;
155
+ setDraft(draft: PromptDraft, options?: { focus?: boolean; preventScroll?: boolean }): void;
156
+ focus(options?: { preventScroll?: boolean }): void; // preventScroll defaults to true
156
157
  }
157
158
  ```
158
159
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@particle-academy/react-fancy",
3
- "version": "5.67.0",
3
+ "version": "5.69.0",
4
4
  "description": "React UI component library for Human+ UX — controlled, agent-bridgeable primitives",
5
5
  "repository": {
6
6
  "type": "git",