@embedpdf/viewer-chrome 3.0.0-next.15 → 3.0.0-next.16

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 (200) hide show
  1. package/dist/{annotation-fonts-BqoLZ4Mp.js → annotation-fonts-DWjVOTP0.js} +2 -2
  2. package/dist/{annotation-fonts-BqoLZ4Mp.js.map → annotation-fonts-DWjVOTP0.js.map} +1 -1
  3. package/dist/{annotation-fonts-Dt0IQXhz.cjs → annotation-fonts-dpfVkhnq.cjs} +2 -2
  4. package/dist/{annotation-fonts-Dt0IQXhz.cjs.map → annotation-fonts-dpfVkhnq.cjs.map} +1 -1
  5. package/dist/{annotation-style-Bzvvp8-N.cjs → annotation-style-B3XKAyZ-.cjs} +3 -3
  6. package/dist/{annotation-style-Bzvvp8-N.cjs.map → annotation-style-B3XKAyZ-.cjs.map} +1 -1
  7. package/dist/{annotation-style--rPIZsuP.js → annotation-style-CXF3X47Z.js} +3 -3
  8. package/dist/{annotation-style--rPIZsuP.js.map → annotation-style-CXF3X47Z.js.map} +1 -1
  9. package/dist/{ar-DnEj5vbP.cjs → ar-B132r9bo.cjs} +93 -1
  10. package/dist/ar-B132r9bo.cjs.map +1 -0
  11. package/dist/{ar-D9XKAmDx.js → ar-BLWFJoA_.js} +93 -1
  12. package/dist/ar-BLWFJoA_.js.map +1 -0
  13. package/dist/attachments-panel-Cxln8xos.cjs +217 -0
  14. package/dist/attachments-panel-Cxln8xos.cjs.map +1 -0
  15. package/dist/attachments-panel-H1ucRbwo.js +217 -0
  16. package/dist/attachments-panel-H1ucRbwo.js.map +1 -0
  17. package/dist/chrome.cjs +21 -0
  18. package/dist/chrome.cjs.map +1 -1
  19. package/dist/chrome.js +21 -0
  20. package/dist/chrome.js.map +1 -1
  21. package/dist/{commands-BmgxhJ8B.js → commands-BkgLP3Om.js} +418 -23
  22. package/dist/commands-BkgLP3Om.js.map +1 -0
  23. package/dist/{commands-CYt4SFUX.cjs → commands-DL1gjZt7.cjs} +433 -20
  24. package/dist/commands-DL1gjZt7.cjs.map +1 -0
  25. package/dist/commands.cjs +2 -1
  26. package/dist/commands.d.cts +3 -1
  27. package/dist/commands.d.ts +3 -1
  28. package/dist/commands.js +2 -2
  29. package/dist/{comments-panel-pEcQg4Vs.cjs → comments-panel-BsnWedTh.cjs} +2 -2
  30. package/dist/{comments-panel-pEcQg4Vs.cjs.map → comments-panel-BsnWedTh.cjs.map} +1 -1
  31. package/dist/{comments-panel-MUVgLCBI.js → comments-panel-D7Eadws9.js} +2 -2
  32. package/dist/{comments-panel-MUVgLCBI.js.map → comments-panel-D7Eadws9.js.map} +1 -1
  33. package/dist/{de-Dv6zvbnd.cjs → de-7_MvFWzN.cjs} +93 -1
  34. package/dist/de-7_MvFWzN.cjs.map +1 -0
  35. package/dist/{de-Bdr4aWzm.js → de-BUhwc9-x.js} +93 -1
  36. package/dist/de-BUhwc9-x.js.map +1 -0
  37. package/dist/{dialog-B5GBisKv.js → dialog-BIb373cg.js} +3 -3
  38. package/dist/dialog-BIb373cg.js.map +1 -0
  39. package/dist/{dialog-t8F13BL_.cjs → dialog-CngKTnAM.cjs} +3 -3
  40. package/dist/dialog-CngKTnAM.cjs.map +1 -0
  41. package/dist/{es-BP09DR9w.cjs → es-DgYj-1L3.cjs} +93 -1
  42. package/dist/es-DgYj-1L3.cjs.map +1 -0
  43. package/dist/{es-BSXz5tBv.js → es-DoXTqFoO.js} +93 -1
  44. package/dist/es-DoXTqFoO.js.map +1 -0
  45. package/dist/{form-design-panel-vWWU9uB-.js → form-design-panel-CgV_5YWC.js} +3 -3
  46. package/dist/{form-design-panel-vWWU9uB-.js.map → form-design-panel-CgV_5YWC.js.map} +1 -1
  47. package/dist/{form-design-panel-B5MXTZ96.cjs → form-design-panel-D0FdmWXW.cjs} +3 -3
  48. package/dist/{form-design-panel-B5MXTZ96.cjs.map → form-design-panel-D0FdmWXW.cjs.map} +1 -1
  49. package/dist/{fr-Ckn3K9v1.js → fr-B-8NDhBA.js} +93 -1
  50. package/dist/fr-B-8NDhBA.js.map +1 -0
  51. package/dist/{fr-BBQQn7tJ.cjs → fr-C856dmQJ.cjs} +93 -1
  52. package/dist/fr-C856dmQJ.cjs.map +1 -0
  53. package/dist/{he-DRsG7bH7.cjs → he-BFTeNc4t.cjs} +93 -1
  54. package/dist/he-BFTeNc4t.cjs.map +1 -0
  55. package/dist/{he-wdGU5PkU.js → he-Dlh0fNXM.js} +93 -1
  56. package/dist/he-Dlh0fNXM.js.map +1 -0
  57. package/dist/{icons-x0Tc05bs.cjs → icons-1UfLUZ_y.cjs} +20 -1
  58. package/dist/icons-1UfLUZ_y.cjs.map +1 -0
  59. package/dist/{icons-BrK5iVL8.js → icons-7dB0Y1ct.js} +20 -1
  60. package/dist/icons-7dB0Y1ct.js.map +1 -0
  61. package/dist/index.cjs +740 -171
  62. package/dist/index.cjs.map +1 -1
  63. package/dist/index.d.cts +16 -2
  64. package/dist/index.d.ts +16 -2
  65. package/dist/index.js +727 -170
  66. package/dist/index.js.map +1 -1
  67. package/dist/{it-BuP4o0xQ.cjs → it-Bef-2Yxq.cjs} +93 -1
  68. package/dist/it-Bef-2Yxq.cjs.map +1 -0
  69. package/dist/{it-Us-VmvIu.js → it-BkirG7ol.js} +93 -1
  70. package/dist/it-BkirG7ol.js.map +1 -0
  71. package/dist/{ja-Cizj0-5O.js → ja-CGEjCE-s.js} +93 -1
  72. package/dist/ja-CGEjCE-s.js.map +1 -0
  73. package/dist/{ja-DovEd6ts.cjs → ja-DNw2zqSD.cjs} +93 -1
  74. package/dist/ja-DNw2zqSD.cjs.map +1 -0
  75. package/dist/{ko-DlrXliE1.js → ko-CTkl5vMh.js} +93 -1
  76. package/dist/ko-CTkl5vMh.js.map +1 -0
  77. package/dist/{ko-B-qJEol2.cjs → ko-YHzeBqP6.cjs} +93 -1
  78. package/dist/ko-YHzeBqP6.cjs.map +1 -0
  79. package/dist/{link-editor-CSjqPnj1.cjs → link-editor-CAS7MZM2.cjs} +2 -2
  80. package/dist/{link-editor-CSjqPnj1.cjs.map → link-editor-CAS7MZM2.cjs.map} +1 -1
  81. package/dist/{link-editor-SxM1nnJU.js → link-editor-CkwtqRvb.js} +2 -2
  82. package/dist/{link-editor-SxM1nnJU.js.map → link-editor-CkwtqRvb.js.map} +1 -1
  83. package/dist/{measurement-Bs61XWbJ.js → measurement-CQdbnIrn.js} +2 -2
  84. package/dist/{measurement-Bs61XWbJ.js.map → measurement-CQdbnIrn.js.map} +1 -1
  85. package/dist/{measurement-CcCsHPOX.cjs → measurement-Cxv1Ahxx.cjs} +2 -2
  86. package/dist/{measurement-CcCsHPOX.cjs.map → measurement-Cxv1Ahxx.cjs.map} +1 -1
  87. package/dist/{nl-D3KZDDiJ.cjs → nl-BjkbaLq3.cjs} +93 -1
  88. package/dist/nl-BjkbaLq3.cjs.map +1 -0
  89. package/dist/{nl-0aF7M_0h.js → nl-Dya4sR8_.js} +93 -1
  90. package/dist/nl-Dya4sR8_.js.map +1 -0
  91. package/dist/outline-panel-BpGtBdj0.cjs +707 -0
  92. package/dist/outline-panel-BpGtBdj0.cjs.map +1 -0
  93. package/dist/outline-panel-DO5_REYw.js +707 -0
  94. package/dist/outline-panel-DO5_REYw.js.map +1 -0
  95. package/dist/outline-properties-BCa2cc0t.js +330 -0
  96. package/dist/outline-properties-BCa2cc0t.js.map +1 -0
  97. package/dist/outline-properties-DT3FIxCw.cjs +330 -0
  98. package/dist/outline-properties-DT3FIxCw.cjs.map +1 -0
  99. package/dist/{pl-DSFhAUqx.cjs → pl-CKKdVnpZ.cjs} +93 -1
  100. package/dist/pl-CKKdVnpZ.cjs.map +1 -0
  101. package/dist/{pl-BW--AaCI.js → pl-DA9b5NVg.js} +93 -1
  102. package/dist/pl-DA9b5NVg.js.map +1 -0
  103. package/dist/print-dialog-BqIrHCBh.cjs +276 -0
  104. package/dist/print-dialog-BqIrHCBh.cjs.map +1 -0
  105. package/dist/print-dialog-DvcI2m2_.js +276 -0
  106. package/dist/print-dialog-DvcI2m2_.js.map +1 -0
  107. package/dist/{pt-C5S-8MC5.cjs → pt-DLcszlzi.cjs} +93 -1
  108. package/dist/pt-DLcszlzi.cjs.map +1 -0
  109. package/dist/{pt-DIhpU5pT.js → pt-Nm8yyjbX.js} +93 -1
  110. package/dist/pt-Nm8yyjbX.js.map +1 -0
  111. package/dist/{redact-confirm-CX_SY2ZN.cjs → redact-confirm-C6EiK8yN.cjs} +2 -2
  112. package/dist/{redact-confirm-CX_SY2ZN.cjs.map → redact-confirm-C6EiK8yN.cjs.map} +1 -1
  113. package/dist/{redact-confirm-B6j36TPw.js → redact-confirm-CKuv9iN_.js} +2 -2
  114. package/dist/{redact-confirm-B6j36TPw.js.map → redact-confirm-CKuv9iN_.js.map} +1 -1
  115. package/dist/{redaction-panel-IJDshSJI.js → redaction-panel-CgNZ-pQk.js} +2 -2
  116. package/dist/{redaction-panel-IJDshSJI.js.map → redaction-panel-CgNZ-pQk.js.map} +1 -1
  117. package/dist/{redaction-panel-BmoIl-Ll.cjs → redaction-panel-ZhX0dlMi.cjs} +2 -2
  118. package/dist/{redaction-panel-BmoIl-Ll.cjs.map → redaction-panel-ZhX0dlMi.cjs.map} +1 -1
  119. package/dist/{search-panel-HfIhJm1M.js → search-panel-BE4xzWlm.js} +4 -4
  120. package/dist/{search-panel-HfIhJm1M.js.map → search-panel-BE4xzWlm.js.map} +1 -1
  121. package/dist/{search-panel-s9IoiOtv.cjs → search-panel-wcbTNG1z.cjs} +4 -4
  122. package/dist/{search-panel-s9IoiOtv.cjs.map → search-panel-wcbTNG1z.cjs.map} +1 -1
  123. package/dist/{sheet-BDsa_Sup.cjs → sheet-DTBFiwde.cjs} +30 -11
  124. package/dist/sheet-DTBFiwde.cjs.map +1 -0
  125. package/dist/{sheet-R6XDgyEf.js → sheet-DyjKfAq0.js} +25 -12
  126. package/dist/sheet-DyjKfAq0.js.map +1 -0
  127. package/dist/{sign-dialog-CgnR7akj.cjs → sign-dialog-D5WGx-Yn.cjs} +2 -2
  128. package/dist/{sign-dialog-CgnR7akj.cjs.map → sign-dialog-D5WGx-Yn.cjs.map} +1 -1
  129. package/dist/{sign-dialog-GDqCoQhA.js → sign-dialog-DerNe8qT.js} +2 -2
  130. package/dist/{sign-dialog-GDqCoQhA.js.map → sign-dialog-DerNe8qT.js.map} +1 -1
  131. package/dist/{signature-inspector-DyO313Qf.cjs → signature-inspector-Bz6TAfZM.cjs} +4 -10
  132. package/dist/signature-inspector-Bz6TAfZM.cjs.map +1 -0
  133. package/dist/{signature-inspector-okFz8do6.js → signature-inspector-CsGr9EBk.js} +4 -10
  134. package/dist/signature-inspector-CsGr9EBk.js.map +1 -0
  135. package/dist/{signature-maker-BoYa8vgA.cjs → signature-maker-D_YfBXLn.cjs} +3 -3
  136. package/dist/{signature-maker-BoYa8vgA.cjs.map → signature-maker-D_YfBXLn.cjs.map} +1 -1
  137. package/dist/{signature-maker-BhCmYyHD.js → signature-maker-Dnth4rV4.js} +3 -3
  138. package/dist/{signature-maker-BhCmYyHD.js.map → signature-maker-Dnth4rV4.js.map} +1 -1
  139. package/dist/{signatures-panel-B56PC6d9.cjs → signatures-panel-Ci_LaI1C.cjs} +4 -10
  140. package/dist/signatures-panel-Ci_LaI1C.cjs.map +1 -0
  141. package/dist/{signatures-panel-CgnFfhFm.js → signatures-panel-DZ9ywrjz.js} +4 -10
  142. package/dist/signatures-panel-DZ9ywrjz.js.map +1 -0
  143. package/dist/{stamps-panel-CDO0FPyK.js → stamps-panel-BrczStaz.js} +4 -10
  144. package/dist/stamps-panel-BrczStaz.js.map +1 -0
  145. package/dist/{stamps-panel-B9NYGayn.cjs → stamps-panel-Cv9nJBwx.cjs} +4 -10
  146. package/dist/stamps-panel-Cv9nJBwx.cjs.map +1 -0
  147. package/dist/theme-Be0OZokZ.js +97 -0
  148. package/dist/theme-Be0OZokZ.js.map +1 -0
  149. package/dist/theme-FR26JI3r.cjs +126 -0
  150. package/dist/theme-FR26JI3r.cjs.map +1 -0
  151. package/dist/{toolbar-z9od3tKl.js → toolbar-DF361xWY.js} +7 -6
  152. package/dist/toolbar-DF361xWY.js.map +1 -0
  153. package/dist/{toolbar-CJu2wKTU.cjs → toolbar-ddvpsvTb.cjs} +7 -6
  154. package/dist/toolbar-ddvpsvTb.cjs.map +1 -0
  155. package/dist/{zh-cn-CxkUUBct.js → zh-cn-BMPPkLpL.js} +93 -1
  156. package/dist/zh-cn-BMPPkLpL.js.map +1 -0
  157. package/dist/{zh-cn-3tmMeHqv.cjs → zh-cn-CZOO3p4H.cjs} +93 -1
  158. package/dist/zh-cn-CZOO3p4H.cjs.map +1 -0
  159. package/package.json +4 -4
  160. package/src/styles.css +8 -0
  161. package/dist/ar-D9XKAmDx.js.map +0 -1
  162. package/dist/ar-DnEj5vbP.cjs.map +0 -1
  163. package/dist/commands-BmgxhJ8B.js.map +0 -1
  164. package/dist/commands-CYt4SFUX.cjs.map +0 -1
  165. package/dist/de-Bdr4aWzm.js.map +0 -1
  166. package/dist/de-Dv6zvbnd.cjs.map +0 -1
  167. package/dist/dialog-B5GBisKv.js.map +0 -1
  168. package/dist/dialog-t8F13BL_.cjs.map +0 -1
  169. package/dist/es-BP09DR9w.cjs.map +0 -1
  170. package/dist/es-BSXz5tBv.js.map +0 -1
  171. package/dist/fr-BBQQn7tJ.cjs.map +0 -1
  172. package/dist/fr-Ckn3K9v1.js.map +0 -1
  173. package/dist/he-DRsG7bH7.cjs.map +0 -1
  174. package/dist/he-wdGU5PkU.js.map +0 -1
  175. package/dist/icons-BrK5iVL8.js.map +0 -1
  176. package/dist/icons-x0Tc05bs.cjs.map +0 -1
  177. package/dist/it-BuP4o0xQ.cjs.map +0 -1
  178. package/dist/it-Us-VmvIu.js.map +0 -1
  179. package/dist/ja-Cizj0-5O.js.map +0 -1
  180. package/dist/ja-DovEd6ts.cjs.map +0 -1
  181. package/dist/ko-B-qJEol2.cjs.map +0 -1
  182. package/dist/ko-DlrXliE1.js.map +0 -1
  183. package/dist/nl-0aF7M_0h.js.map +0 -1
  184. package/dist/nl-D3KZDDiJ.cjs.map +0 -1
  185. package/dist/pl-BW--AaCI.js.map +0 -1
  186. package/dist/pl-DSFhAUqx.cjs.map +0 -1
  187. package/dist/pt-C5S-8MC5.cjs.map +0 -1
  188. package/dist/pt-DIhpU5pT.js.map +0 -1
  189. package/dist/sheet-BDsa_Sup.cjs.map +0 -1
  190. package/dist/sheet-R6XDgyEf.js.map +0 -1
  191. package/dist/signature-inspector-DyO313Qf.cjs.map +0 -1
  192. package/dist/signature-inspector-okFz8do6.js.map +0 -1
  193. package/dist/signatures-panel-B56PC6d9.cjs.map +0 -1
  194. package/dist/signatures-panel-CgnFfhFm.js.map +0 -1
  195. package/dist/stamps-panel-B9NYGayn.cjs.map +0 -1
  196. package/dist/stamps-panel-CDO0FPyK.js.map +0 -1
  197. package/dist/toolbar-CJu2wKTU.cjs.map +0 -1
  198. package/dist/toolbar-z9od3tKl.js.map +0 -1
  199. package/dist/zh-cn-3tmMeHqv.cjs.map +0 -1
  200. package/dist/zh-cn-CxkUUBct.js.map +0 -1
@@ -0,0 +1,707 @@
1
+ const require_icons = require("./icons-1UfLUZ_y.cjs");
2
+ const require_commands = require("./commands-DL1gjZt7.cjs");
3
+ const require_toolbar = require("./toolbar-ddvpsvTb.cjs");
4
+ const require_theme = require("./theme-FR26JI3r.cjs");
5
+ const require_sheet = require("./sheet-DTBFiwde.cjs");
6
+ let react = require("react");
7
+ let _embedpdf_react_outline = require("@embedpdf/react/outline");
8
+ let _embedpdf_react_i18n = require("@embedpdf/react/i18n");
9
+ let _embedpdf_react_commands = require("@embedpdf/react/commands");
10
+ let _embedpdf_react_shell = require("@embedpdf/react/shell");
11
+ let _embedpdf_core_ui = require("@embedpdf/core-ui");
12
+ let react_jsx_runtime = require("react/jsx-runtime");
13
+ //#region src/ui/outline-tree.ts
14
+ const outlineKeyOf = (ref) => ref ? String(ref.objectNumber) : "top";
15
+ /**
16
+ * The rows a filter shows: every item whose title holds the text, whatever its case, with the
17
+ * items it sits under so it is found in its place. Every shown parent shows its children.
18
+ */
19
+ function filteredRows(items, query) {
20
+ const needle = query.trim().toLocaleLowerCase();
21
+ if (!needle) return [];
22
+ const byKey = new Map(items.map((item) => [outlineKeyOf(item.ref), item]));
23
+ const shown = /* @__PURE__ */ new Set();
24
+ for (const item of items) {
25
+ if (!item.title.toLocaleLowerCase().includes(needle)) continue;
26
+ for (let at = item; at;) {
27
+ const key = outlineKeyOf(at.ref);
28
+ if (shown.has(key)) break;
29
+ shown.add(key);
30
+ at = at.parent ? byKey.get(outlineKeyOf(at.parent)) : void 0;
31
+ }
32
+ }
33
+ const depthOf = /* @__PURE__ */ new Map();
34
+ const parents = new Set(items.flatMap((item) => item.parent ? [outlineKeyOf(item.parent)] : []));
35
+ const rows = [];
36
+ for (const item of items) {
37
+ const key = outlineKeyOf(item.ref);
38
+ const depth = item.parent ? (depthOf.get(outlineKeyOf(item.parent)) ?? -1) + 1 : 0;
39
+ depthOf.set(key, depth);
40
+ if (!shown.has(key)) continue;
41
+ const hasChildren = parents.has(key);
42
+ rows.push({
43
+ item,
44
+ depth,
45
+ hasChildren,
46
+ expanded: hasChildren
47
+ });
48
+ }
49
+ return rows;
50
+ }
51
+ /** The panel's background in each mode, as the viewer's theme draws it. */
52
+ const SURFACE = {
53
+ light: "#ffffff",
54
+ dark: "#1f2937"
55
+ };
56
+ /** WCAG's least contrast for large or bold text, and for parts of a picture. */
57
+ const LEAST_CONTRAST = 3;
58
+ /** A `#rrggbb` colour's relative luminance (WCAG 2.2, "relative luminance"). */
59
+ function luminanceOf(color) {
60
+ const value = Number.parseInt(color.slice(1), 16);
61
+ const channel = (shift) => {
62
+ const level = (value >> shift & 255) / 255;
63
+ return level <= .04045 ? level / 12.92 : ((level + .055) / 1.055) ** 2.4;
64
+ };
65
+ return .2126 * channel(16) + .7152 * channel(8) + .0722 * channel(0);
66
+ }
67
+ /**
68
+ * The colour to draw an item's title in: its own (`/C`), unless it would read badly on the
69
+ * panel (a dark red in the dark theme, yellow in the light one); then the panel's own text
70
+ * colour, as for an item without one.
71
+ */
72
+ function readableColor(color, mode) {
73
+ if (!color || !/^#[0-9a-fA-F]{6}$/.test(color)) return null;
74
+ const [lighter, darker] = [luminanceOf(color), luminanceOf(SURFACE[mode])].sort((left, right) => right - left);
75
+ return (lighter + .05) / (darker + .05) >= LEAST_CONTRAST ? color : null;
76
+ }
77
+ /**
78
+ * The keys of the rows that move with `dragged`: each dragged row and the rows under it that
79
+ * show. A drop among them would put an item under itself.
80
+ */
81
+ function movingKeysOf(rows, dragged) {
82
+ const moving = /* @__PURE__ */ new Set();
83
+ let under = -1;
84
+ for (const row of rows) {
85
+ const key = outlineKeyOf(row.item.ref);
86
+ if (under >= 0 && row.depth > under) {
87
+ moving.add(key);
88
+ continue;
89
+ }
90
+ under = -1;
91
+ if (dragged.has(key)) {
92
+ moving.add(key);
93
+ under = row.depth;
94
+ }
95
+ }
96
+ return moving;
97
+ }
98
+ /**
99
+ * Where rows dropped in the gap before `rows[gap]` land, at the level the pointer asks for
100
+ * (`depth`), as a tree view lets them: no deeper than one level under the row above, and no
101
+ * shallower than the row below, so the tree stays a tree. `moving` are the rows that move: the
102
+ * gaps among them are left out. `null` when no row stays to place them by.
103
+ */
104
+ function dropOf(rows, moving, gap, depth) {
105
+ const kept = rows.filter((row) => !moving.has(outlineKeyOf(row.item.ref)));
106
+ if (kept.length === 0) return null;
107
+ const at = rows.slice(0, gap).filter((row) => !moving.has(outlineKeyOf(row.item.ref))).length;
108
+ const above = kept[at - 1];
109
+ const below = kept[at];
110
+ const deepest = above ? above.depth + 1 : 0;
111
+ const shallowest = below ? Math.min(below.depth, deepest) : 0;
112
+ const level = Math.max(shallowest, Math.min(deepest, Math.round(depth)));
113
+ let parent = null;
114
+ let previous = null;
115
+ for (let i = at - 1; i >= 0; i -= 1) {
116
+ const row = kept[i];
117
+ if (row.depth < level) {
118
+ parent = row.item.ref;
119
+ break;
120
+ }
121
+ if (row.depth === level && previous === null) previous = row.item.ref;
122
+ }
123
+ return {
124
+ parent,
125
+ position: previous ? { after: previous } : "start",
126
+ depth: level
127
+ };
128
+ }
129
+ //#endregion
130
+ //#region src/ui/outline-rows.tsx
131
+ /**
132
+ * The outline's rows: a tree that draws only the rows in view (every row is one height), with
133
+ * the keyboard of the ARIA tree pattern (`treeKeyAction`), renaming in the row, and dragging rows
134
+ * to another place, the pointer's distance from the edge choosing how deep. A pen or a finger
135
+ * holds a row first, so a swipe still scrolls the list.
136
+ */
137
+ /** Rows drawn past each edge of the view, so a scroll shows no gap before the next frame. */
138
+ const OVERSCAN = 8;
139
+ /** How far the pointer moves before a press on a row becomes a drag, in px. */
140
+ const DRAG_SLOP_PX = 4;
141
+ /** How long a pen or a finger holds a row before it drags it, in ms. */
142
+ const HOLD_MS = 450;
143
+ /** Within this many px of the list's top or bottom, a drag scrolls the list. */
144
+ const EDGE_PX = 28;
145
+ /** The text of a row is drawn at this size, in px. */
146
+ const TEXT_PX = 13;
147
+ /** A text field below this size makes iOS zoom the page as it takes focus. */
148
+ const FIELD_PX = 16;
149
+ function OutlineRows(props) {
150
+ const { outline, rows, currentKey, selected, editable, filtering, renamingKey, onRename } = props;
151
+ const t = (0, _embedpdf_react_i18n.useT)();
152
+ const idPrefix = (0, react.useId)();
153
+ const list = (0, react.useRef)(null);
154
+ const [scrollTop, setScrollTop] = (0, react.useState)(0);
155
+ const [height, setHeight] = (0, react.useState)(0);
156
+ const [focusedKey, setFocusedKey] = (0, react.useState)(null);
157
+ const [anchorKey, setAnchorKey] = (0, react.useState)(null);
158
+ const [drag, setDrag] = (0, react.useState)(null);
159
+ const [treeFocused, setTreeFocused] = (0, react.useState)(false);
160
+ const dragRef = (0, react.useRef)(null);
161
+ dragRef.current = drag;
162
+ const holdTimer = (0, react.useRef)(null);
163
+ const suppressClick = (0, react.useRef)(false);
164
+ const selectedKeys = new Set(selected.map(outlineKeyOf));
165
+ const indexOfKey = (key) => key === null ? -1 : rows.findIndex((row) => outlineKeyOf(row.item.ref) === key);
166
+ const focused = indexOfKey(focusedKey) >= 0 ? focusedKey : currentKey ?? (selected[0] ? outlineKeyOf(selected[0]) : null);
167
+ const focusedIndex = indexOfKey(focused);
168
+ (0, react.useLayoutEffect)(() => {
169
+ const element = list.current;
170
+ if (!element) return;
171
+ const observer = new ResizeObserver(() => setHeight(element.clientHeight));
172
+ observer.observe(element);
173
+ setHeight(element.clientHeight);
174
+ return () => observer.disconnect();
175
+ }, []);
176
+ /** Scroll so a row shows, moving no more than it takes. */
177
+ const reveal = (index) => {
178
+ const element = list.current;
179
+ if (!element || index < 0) return;
180
+ const top = index * 30;
181
+ if (top < element.scrollTop) element.scrollTop = top;
182
+ else if (top + 30 > element.scrollTop + element.clientHeight) element.scrollTop = top + 30 - element.clientHeight;
183
+ };
184
+ const currentIndex = indexOfKey(currentKey);
185
+ (0, react.useEffect)(() => reveal(currentIndex), [currentIndex]);
186
+ const renamingIndex = indexOfKey(renamingKey);
187
+ (0, react.useEffect)(() => reveal(renamingIndex), [renamingIndex]);
188
+ const first = Math.max(0, Math.floor(scrollTop / 30) - OVERSCAN);
189
+ const last = Math.min(rows.length, Math.ceil((scrollTop + height) / 30) + OVERSCAN);
190
+ const follow = (row) => {
191
+ const { item } = row;
192
+ if (!item.target && !item.action) return;
193
+ outline.activate(item.ref);
194
+ props.onPicked();
195
+ };
196
+ const focusRow = (index, select) => {
197
+ const row = rows[index];
198
+ if (!row) return;
199
+ const key = outlineKeyOf(row.item.ref);
200
+ setFocusedKey(key);
201
+ if (select) {
202
+ setAnchorKey(key);
203
+ outline.select([row.item.ref]);
204
+ }
205
+ reveal(index);
206
+ };
207
+ const run = (action) => {
208
+ switch (action.type) {
209
+ case "focus":
210
+ focusRow(action.row, true);
211
+ return;
212
+ case "expand":
213
+ for (const index of action.rows) {
214
+ const row = rows[index];
215
+ if (row) outline.expand(row.item.ref);
216
+ }
217
+ return;
218
+ case "collapse": {
219
+ const row = rows[action.row];
220
+ if (row) outline.collapse(row.item.ref);
221
+ return;
222
+ }
223
+ case "activate": {
224
+ const row = rows[action.row];
225
+ if (row) follow(row);
226
+ return;
227
+ }
228
+ case "rename": {
229
+ const row = rows[action.row];
230
+ if (row) onRename(outlineKeyOf(row.item.ref));
231
+ return;
232
+ }
233
+ case "delete":
234
+ if (selected.length > 0) outline.delete(selected).catch(() => {});
235
+ return;
236
+ }
237
+ };
238
+ const onKeyDown = (event) => {
239
+ if (event.target !== event.currentTarget) return;
240
+ setTreeFocused(true);
241
+ const key = event.key === "Backspace" ? "Delete" : event.key;
242
+ const action = (0, _embedpdf_core_ui.treeKeyAction)(rows, focusedIndex, key, { editable });
243
+ if (!action || filtering && (action.type === "expand" || action.type === "collapse")) return;
244
+ event.preventDefault();
245
+ run(action);
246
+ };
247
+ const onRowClick = (row, index, event) => {
248
+ if (suppressClick.current) {
249
+ suppressClick.current = false;
250
+ return;
251
+ }
252
+ const key = outlineKeyOf(row.item.ref);
253
+ setFocusedKey(key);
254
+ if (event.metaKey || event.ctrlKey) {
255
+ outline.select(selectedKeys.has(key) ? selected.filter((ref) => outlineKeyOf(ref) !== key) : [...selected, row.item.ref]);
256
+ setAnchorKey(key);
257
+ return;
258
+ }
259
+ if (event.shiftKey && anchorKey !== null && indexOfKey(anchorKey) >= 0) {
260
+ const from = indexOfKey(anchorKey);
261
+ const [low, high] = from < index ? [from, index] : [index, from];
262
+ outline.select(rows.slice(low, high + 1).map((each) => each.item.ref));
263
+ return;
264
+ }
265
+ setAnchorKey(key);
266
+ outline.select([row.item.ref]);
267
+ follow(row);
268
+ };
269
+ const stopHold = () => {
270
+ if (holdTimer.current !== null) clearTimeout(holdTimer.current);
271
+ holdTimer.current = null;
272
+ };
273
+ /** Where the pointer drops what's dragged, from where it is over the list. */
274
+ const dropAt = (current, clientX, clientY) => {
275
+ const element = list.current;
276
+ if (!element) return null;
277
+ const y = clientY - element.getBoundingClientRect().top + element.scrollTop;
278
+ const gap = Math.max(0, Math.min(rows.length, Math.round(y / 30)));
279
+ const rtl = getComputedStyle(element).direction === "rtl";
280
+ const across = (clientX - current.startX) * (rtl ? -1 : 1);
281
+ const drop = dropOf(rows, current.moving, gap, current.startDepth + across / 16);
282
+ return drop ? {
283
+ ...drop,
284
+ gap
285
+ } : null;
286
+ };
287
+ const startDrag = (current, clientX, clientY) => {
288
+ const next = {
289
+ ...current,
290
+ active: true,
291
+ drop: dropAt(current, clientX, clientY)
292
+ };
293
+ setDrag(next);
294
+ list.current?.setPointerCapture(current.pointerId);
295
+ };
296
+ const onPointerDown = (row, event) => {
297
+ if (!editable || filtering || event.button !== 0 || renamingKey !== null) return;
298
+ if (event.target.closest("button, input")) return;
299
+ const key = outlineKeyOf(row.item.ref);
300
+ const dragged = selectedKeys.has(key) ? selectedKeys : /* @__PURE__ */ new Set([key]);
301
+ const moving = movingKeysOf(rows, dragged);
302
+ const refs = rows.filter((each) => dragged.has(outlineKeyOf(each.item.ref))).filter((each) => {
303
+ const keyOf = outlineKeyOf(each.item.ref);
304
+ const parent = each.item.parent ? outlineKeyOf(each.item.parent) : null;
305
+ return !(parent !== null && moving.has(parent) && moving.has(keyOf));
306
+ }).map((each) => each.item.ref);
307
+ const pending = {
308
+ pointerId: event.pointerId,
309
+ startX: event.clientX,
310
+ startY: event.clientY,
311
+ startDepth: row.depth,
312
+ moving,
313
+ refs,
314
+ active: false,
315
+ drop: null
316
+ };
317
+ setDrag(pending);
318
+ if (event.pointerType !== "mouse") {
319
+ const { clientX, clientY } = event;
320
+ holdTimer.current = setTimeout(() => {
321
+ const current = dragRef.current;
322
+ if (current && !current.active) startDrag(current, clientX, clientY);
323
+ }, HOLD_MS);
324
+ }
325
+ };
326
+ const dragging = drag?.active === true;
327
+ (0, react.useEffect)(() => {
328
+ if (!dragging) return;
329
+ const prevent = (event) => event.preventDefault();
330
+ document.addEventListener("touchmove", prevent, { passive: false });
331
+ return () => document.removeEventListener("touchmove", prevent);
332
+ }, [dragging]);
333
+ const onPointerMove = (event) => {
334
+ const current = dragRef.current;
335
+ if (!current || event.pointerId !== current.pointerId) return;
336
+ const moved = Math.hypot(event.clientX - current.startX, event.clientY - current.startY);
337
+ if (!current.active) {
338
+ if (moved <= DRAG_SLOP_PX) return;
339
+ if (event.pointerType === "mouse") startDrag(current, event.clientX, event.clientY);
340
+ else {
341
+ stopHold();
342
+ setDrag(null);
343
+ }
344
+ return;
345
+ }
346
+ const element = list.current;
347
+ if (element) {
348
+ const box = element.getBoundingClientRect();
349
+ if (event.clientY < box.top + EDGE_PX) element.scrollTop -= 8;
350
+ else if (event.clientY > box.bottom - EDGE_PX) element.scrollTop += 8;
351
+ }
352
+ setDrag({
353
+ ...current,
354
+ drop: dropAt(current, event.clientX, event.clientY)
355
+ });
356
+ };
357
+ const endDrag = (event, commit) => {
358
+ stopHold();
359
+ const current = dragRef.current;
360
+ if (!current || event.pointerId !== current.pointerId) return;
361
+ setDrag(null);
362
+ if (!current.active) return;
363
+ suppressClick.current = true;
364
+ setTimeout(() => {
365
+ suppressClick.current = false;
366
+ }, 0);
367
+ if (commit && current.drop && current.refs.length > 0) outline.move(current.refs, current.drop.parent, current.drop.position).catch(() => {});
368
+ };
369
+ (0, react.useEffect)(() => stopHold, []);
370
+ const shown = rows.slice(first, last);
371
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
372
+ ref: list,
373
+ role: "tree",
374
+ "aria-label": props.label,
375
+ "aria-multiselectable": true,
376
+ tabIndex: 0,
377
+ "aria-activedescendant": focusedIndex >= 0 ? `${idPrefix}-${focused}` : void 0,
378
+ onKeyDown,
379
+ onFocus: (event) => event.target === event.currentTarget && setTreeFocused(event.currentTarget.matches(":focus-visible")),
380
+ onBlur: (event) => event.target === event.currentTarget && setTreeFocused(false),
381
+ onScroll: (event) => setScrollTop(event.currentTarget.scrollTop),
382
+ onPointerMove,
383
+ onPointerUp: (event) => endDrag(event, true),
384
+ onPointerCancel: (event) => endDrag(event, false),
385
+ className: "focus-visible:ring-accent relative min-h-0 flex-1 overflow-y-auto outline-none focus-visible:ring-2 focus-visible:ring-inset",
386
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
387
+ style: {
388
+ height: rows.length * 30,
389
+ position: "relative"
390
+ },
391
+ children: [shown.map((row, offset) => {
392
+ const index = first + offset;
393
+ const key = outlineKeyOf(row.item.ref);
394
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
395
+ id: `${idPrefix}-${key}`,
396
+ outline,
397
+ row,
398
+ index,
399
+ current: key === currentKey,
400
+ selected: selectedKeys.has(key),
401
+ focused: treeFocused && key === focused,
402
+ moving: dragging && drag.moving.has(key),
403
+ editable,
404
+ foldable: !filtering,
405
+ renaming: key === renamingKey,
406
+ mode: props.mode,
407
+ untitled: t("outline.untitled"),
408
+ onClick: (event) => onRowClick(row, index, event),
409
+ onPointerDown: (event) => onPointerDown(row, event),
410
+ onRenameStart: () => onRename(key),
411
+ onRenameEnd: () => {
412
+ onRename(null);
413
+ setFocusedKey(key);
414
+ list.current?.focus({ preventScroll: true });
415
+ },
416
+ onMenu: () => {
417
+ setFocusedKey(key);
418
+ if (!selectedKeys.has(key)) outline.select([row.item.ref]);
419
+ }
420
+ }, key);
421
+ }), dragging && drag.drop && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
422
+ "aria-hidden": true,
423
+ className: "bg-accent pointer-events-none absolute h-0.5 rounded-full",
424
+ style: {
425
+ top: drag.drop.gap * 30 - 1,
426
+ insetInlineStart: 24 + drag.drop.depth * 16,
427
+ insetInlineEnd: 4
428
+ }
429
+ })]
430
+ })
431
+ });
432
+ }
433
+ function Row(props) {
434
+ const { row, outline } = props;
435
+ const { item, depth, hasChildren, expanded } = row;
436
+ const menuButton = (0, react.useRef)(null);
437
+ const inert = !item.target && !item.action;
438
+ const color = readableColor(item.color, props.mode);
439
+ const tone = props.selected ? "bg-accent-light text-fg" : props.current ? "bg-hover text-fg" : "text-fg-secondary hover:bg-hover";
440
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
441
+ id: props.id,
442
+ role: "treeitem",
443
+ "aria-level": depth + 1,
444
+ "aria-expanded": hasChildren ? expanded : void 0,
445
+ "aria-selected": props.selected,
446
+ "aria-current": props.current ? "location" : void 0,
447
+ onClick: props.onClick,
448
+ onDoubleClick: () => props.editable && props.onRenameStart(),
449
+ onContextMenu: (event) => {
450
+ if (!props.editable) return;
451
+ event.preventDefault();
452
+ props.onMenu();
453
+ menuButton.current?.querySelector("button")?.click();
454
+ },
455
+ onPointerDown: props.onPointerDown,
456
+ className: `group absolute inset-x-0 flex cursor-default select-none items-center gap-0.5 rounded pe-1 ${tone} ${props.focused ? "ring-accent/60 ring-1 ring-inset" : ""} ${props.moving ? "opacity-40" : ""}`,
457
+ style: {
458
+ top: props.index * 30,
459
+ height: 30,
460
+ paddingInlineStart: 4 + depth * 16
461
+ },
462
+ children: [
463
+ props.current && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
464
+ "aria-hidden": true,
465
+ className: "bg-accent absolute inset-y-1 start-0 w-0.5 rounded-full"
466
+ }),
467
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
468
+ type: "button",
469
+ tabIndex: -1,
470
+ "aria-hidden": true,
471
+ disabled: !hasChildren || !props.foldable,
472
+ onClick: (event) => {
473
+ event.stopPropagation();
474
+ if (expanded) outline.collapse(item.ref);
475
+ else outline.expand(item.ref);
476
+ },
477
+ className: "text-fg-muted flex h-5 w-5 shrink-0 items-center justify-center rounded disabled:cursor-default",
478
+ children: hasChildren && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons.Icon, {
479
+ name: "chevronRight",
480
+ size: 14,
481
+ className: `transition-transform rtl:-scale-x-100 ${expanded ? "rotate-90 rtl:-rotate-90" : ""}`
482
+ })
483
+ }),
484
+ props.renaming ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenameField, {
485
+ title: item.title,
486
+ onDone: (title) => {
487
+ props.onRenameEnd();
488
+ if (title !== null && title !== item.title) outline.update(item.ref, { title }).catch(() => {});
489
+ }
490
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
491
+ className: `min-w-0 flex-1 truncate ${inert ? "opacity-60" : ""}`,
492
+ style: {
493
+ fontSize: TEXT_PX,
494
+ color: color ?? void 0,
495
+ fontWeight: item.bold ? 600 : void 0,
496
+ fontStyle: item.italic ? "italic" : void 0
497
+ },
498
+ title: item.title || props.untitled,
499
+ children: item.title || props.untitled
500
+ }),
501
+ props.editable && !props.renaming && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
502
+ ref: menuButton,
503
+ onClick: (event) => event.stopPropagation(),
504
+ onPointerDownCapture: props.onMenu,
505
+ className: `shrink-0 ${props.selected || props.focused ? "" : "opacity-0 focus-within:opacity-100 group-hover:opacity-100"}`,
506
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowMenuButton, {})
507
+ })
508
+ ]
509
+ });
510
+ }
511
+ /** The row's menu button: the outline's commands for the selected row. */
512
+ function RowMenuButton() {
513
+ const more = (0, _embedpdf_react_commands.useCommand)("menu:outline-item");
514
+ if (!more.visible) return null;
515
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_toolbar.CommandButton, {
516
+ cmd: more,
517
+ variant: "icon",
518
+ run: () => void more.run()
519
+ });
520
+ }
521
+ /**
522
+ * The title being typed in its row: Enter or leaving the field keeps it, Escape keeps the one it
523
+ * had. The field is laid out at 16px and drawn at the row's size, so iOS doesn't zoom in on it.
524
+ */
525
+ function RenameField({ title, onDone }) {
526
+ const t = (0, _embedpdf_react_i18n.useT)();
527
+ const field = (0, react.useRef)(null);
528
+ const done = (0, react.useRef)(false);
529
+ const [draft, setDraft] = (0, react.useState)(title);
530
+ (0, react.useLayoutEffect)(() => {
531
+ field.current?.focus();
532
+ field.current?.select();
533
+ }, []);
534
+ const finish = (value) => {
535
+ if (done.current) return;
536
+ done.current = true;
537
+ onDone(value);
538
+ };
539
+ const scale = TEXT_PX / FIELD_PX;
540
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
541
+ className: "relative min-w-0 flex-1",
542
+ style: { height: 24 },
543
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
544
+ ref: field,
545
+ type: "text",
546
+ value: draft,
547
+ "aria-label": t("commands.outline.rename"),
548
+ maxLength: 32767,
549
+ onChange: (event) => setDraft(event.target.value),
550
+ onKeyDown: (event) => {
551
+ event.stopPropagation();
552
+ if (event.key === "Enter") finish(draft);
553
+ else if (event.key === "Escape") finish(null);
554
+ },
555
+ onBlur: () => finish(draft),
556
+ onClick: (event) => event.stopPropagation(),
557
+ className: "border-accent bg-surface text-fg absolute start-0 top-0 origin-top-left rounded border px-1 outline-none rtl:origin-top-right",
558
+ style: {
559
+ fontSize: FIELD_PX,
560
+ width: `${100 / scale}%`,
561
+ height: `${100 / scale}%`,
562
+ transform: `scale(${scale})`
563
+ }
564
+ })
565
+ });
566
+ }
567
+ //#endregion
568
+ //#region src/ui/outline-panel.tsx
569
+ /**
570
+ * The outline panel: the document's outline (its bookmarks) as a tree. A row goes where its item
571
+ * goes; the row of the item the main view is reading is marked, and comes into view as the
572
+ * reader moves on. A filter finds items by their title, in their place. A session that may change
573
+ * the outline adds items (after the selected one, at the place in view, renaming them at once),
574
+ * renames, drags and deletes them, and opens a row's menu for the rest.
575
+ */
576
+ /**
577
+ * The row to mark for where the reader is: the current item's own when it shows, else that of
578
+ * the nearest item it sits under that does.
579
+ */
580
+ function shownKeyOf(current, shown, items) {
581
+ if (!current) return null;
582
+ const byKey = new Map(items.map((item) => [outlineKeyOf(item.ref), item]));
583
+ for (let key = outlineKeyOf(current); key !== null;) {
584
+ if (shown.has(key)) return key;
585
+ const parent = byKey.get(key)?.parent ?? null;
586
+ key = parent ? outlineKeyOf(parent) : null;
587
+ }
588
+ return null;
589
+ }
590
+ function OutlinePanel() {
591
+ const t = (0, _embedpdf_react_i18n.useT)();
592
+ const outline = (0, _embedpdf_react_outline.useOutline)();
593
+ const { items, rows, current, selected, status, incomplete } = (0, _embedpdf_react_outline.useOutlineState)();
594
+ const { mode } = require_theme.useTheme();
595
+ const closeOnPick = require_sheet.useCloseOnPick();
596
+ const add = (0, _embedpdf_react_commands.useCommand)("outline:add");
597
+ const expandAll = (0, _embedpdf_react_commands.useCommand)("outline:expand-all");
598
+ const collapseAll = (0, _embedpdf_react_commands.useCommand)("outline:collapse-all");
599
+ const editable = add.visible && add.enabled;
600
+ const [filter, setFilter] = (0, react.useState)("");
601
+ const [renamingKey, setRenamingKey] = (0, react.useState)(null);
602
+ const filtering = filter.trim() !== "";
603
+ const shownRows = (0, react.useMemo)(() => filtering ? filteredRows(items, filter) : rows, [
604
+ filtering,
605
+ items,
606
+ filter,
607
+ rows
608
+ ]);
609
+ const currentKey = shownKeyOf(current, (0, react.useMemo)(() => new Set(shownRows.map((row) => outlineKeyOf(row.item.ref))), [shownRows]), items);
610
+ const renameRequest = (0, _embedpdf_react_shell.useSurface)(require_commands.OUTLINE_RENAME);
611
+ (0, react.useEffect)(() => {
612
+ if (!renameRequest.isOpen) return;
613
+ const request = renameRequest.props;
614
+ if (request.item !== void 0) {
615
+ setRenamingKey(String(request.item));
616
+ renameRequest.close();
617
+ return;
618
+ }
619
+ const [first] = selected;
620
+ if (!first || first.objectNumber === request.after) return;
621
+ setFilter("");
622
+ setRenamingKey(outlineKeyOf(first));
623
+ renameRequest.close();
624
+ }, [renameRequest, selected]);
625
+ const toolbar = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
626
+ className: "border-border-subtle flex items-center gap-1 border-b p-2",
627
+ children: [
628
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
629
+ className: "relative min-w-0 flex-1",
630
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
631
+ className: "text-fg-muted pointer-events-none absolute inset-y-0 start-0 flex items-center ps-2",
632
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons.Icon, {
633
+ name: "search",
634
+ size: 14
635
+ })
636
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
637
+ type: "search",
638
+ value: filter,
639
+ placeholder: t("outline.filter"),
640
+ "aria-label": t("outline.filter"),
641
+ onChange: (event) => setFilter(event.target.value),
642
+ className: "border-border bg-surface text-fg focus:border-accent focus:ring-accent w-full rounded-md border py-1 pe-2 ps-7 text-sm outline-none focus:ring-1"
643
+ })]
644
+ }),
645
+ add.visible && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_toolbar.CommandButton, {
646
+ cmd: add,
647
+ variant: "icon",
648
+ run: () => void add.run()
649
+ }),
650
+ expandAll.visible && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_toolbar.CommandButton, {
651
+ cmd: expandAll,
652
+ variant: "icon",
653
+ run: () => void expandAll.run()
654
+ }),
655
+ collapseAll.visible && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_toolbar.CommandButton, {
656
+ cmd: collapseAll,
657
+ variant: "icon",
658
+ run: () => void collapseAll.run()
659
+ })
660
+ ]
661
+ });
662
+ const message = (text, withAdd = false) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
663
+ className: "text-fg-muted flex flex-col items-center gap-3 p-6 text-center text-sm",
664
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: text }), withAdd && editable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
665
+ type: "button",
666
+ onClick: () => void add.run(),
667
+ className: "border-border text-fg hover:bg-hover rounded-md border px-3 py-1.5 text-sm",
668
+ children: add.label
669
+ })]
670
+ });
671
+ const body = (() => {
672
+ if (items.length === 0) {
673
+ if (status === "idle" || status === "loading") return message(t("outline.loading"));
674
+ if (status === "forbidden" || status === "error") return message(t("outline.failed"));
675
+ return message(t("outline.empty"), true);
676
+ }
677
+ if (filtering && shownRows.length === 0) return message(t("outline.noMatches"));
678
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OutlineRows, {
679
+ outline,
680
+ rows: shownRows,
681
+ currentKey,
682
+ selected,
683
+ editable,
684
+ filtering,
685
+ renamingKey,
686
+ onRename: setRenamingKey,
687
+ mode,
688
+ onPicked: closeOnPick,
689
+ label: t("panels.outline")
690
+ });
691
+ })();
692
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
693
+ className: "flex min-h-0 flex-1 flex-col",
694
+ children: [
695
+ toolbar,
696
+ incomplete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
697
+ className: "text-fg-muted border-border-subtle border-b px-3 py-2 text-xs",
698
+ children: t("outline.incomplete")
699
+ }),
700
+ body
701
+ ]
702
+ });
703
+ }
704
+ //#endregion
705
+ exports.OutlinePanel = OutlinePanel;
706
+
707
+ //# sourceMappingURL=outline-panel-BpGtBdj0.cjs.map