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

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 (157) hide show
  1. package/README.md +175 -132
  2. package/dist/annotation-fonts-BqoLZ4Mp.js +80 -0
  3. package/dist/annotation-fonts-BqoLZ4Mp.js.map +1 -0
  4. package/dist/annotation-fonts-Dt0IQXhz.cjs +91 -0
  5. package/dist/annotation-fonts-Dt0IQXhz.cjs.map +1 -0
  6. package/dist/annotation-style--rPIZsuP.js +879 -0
  7. package/dist/annotation-style--rPIZsuP.js.map +1 -0
  8. package/dist/annotation-style-Bzvvp8-N.cjs +879 -0
  9. package/dist/annotation-style-Bzvvp8-N.cjs.map +1 -0
  10. package/dist/ar-D9XKAmDx.js +567 -0
  11. package/dist/ar-D9XKAmDx.js.map +1 -0
  12. package/dist/ar-DnEj5vbP.cjs +567 -0
  13. package/dist/ar-DnEj5vbP.cjs.map +1 -0
  14. package/dist/chrome.cjs +378 -221
  15. package/dist/chrome.cjs.map +1 -1
  16. package/dist/chrome.d.cts +5 -34
  17. package/dist/chrome.d.ts +5 -34
  18. package/dist/chrome.js +377 -218
  19. package/dist/chrome.js.map +1 -1
  20. package/dist/commands-BmgxhJ8B.js +953 -0
  21. package/dist/commands-BmgxhJ8B.js.map +1 -0
  22. package/dist/commands-CYt4SFUX.cjs +1060 -0
  23. package/dist/commands-CYt4SFUX.cjs.map +1 -0
  24. package/dist/commands.cjs +12 -595
  25. package/dist/commands.d.cts +29 -4
  26. package/dist/commands.d.ts +29 -4
  27. package/dist/commands.js +2 -593
  28. package/dist/comments-panel-MUVgLCBI.js +514 -0
  29. package/dist/comments-panel-MUVgLCBI.js.map +1 -0
  30. package/dist/comments-panel-pEcQg4Vs.cjs +514 -0
  31. package/dist/comments-panel-pEcQg4Vs.cjs.map +1 -0
  32. package/dist/de-Bdr4aWzm.js +566 -0
  33. package/dist/de-Bdr4aWzm.js.map +1 -0
  34. package/dist/de-Dv6zvbnd.cjs +566 -0
  35. package/dist/de-Dv6zvbnd.cjs.map +1 -0
  36. package/dist/dialog-B5GBisKv.js +55 -0
  37. package/dist/dialog-B5GBisKv.js.map +1 -0
  38. package/dist/dialog-t8F13BL_.cjs +60 -0
  39. package/dist/dialog-t8F13BL_.cjs.map +1 -0
  40. package/dist/es-BP09DR9w.cjs +566 -0
  41. package/dist/es-BP09DR9w.cjs.map +1 -0
  42. package/dist/es-BSXz5tBv.js +566 -0
  43. package/dist/es-BSXz5tBv.js.map +1 -0
  44. package/dist/form-design-panel-B5MXTZ96.cjs +418 -0
  45. package/dist/form-design-panel-B5MXTZ96.cjs.map +1 -0
  46. package/dist/form-design-panel-vWWU9uB-.js +418 -0
  47. package/dist/form-design-panel-vWWU9uB-.js.map +1 -0
  48. package/dist/fr-BBQQn7tJ.cjs +566 -0
  49. package/dist/fr-BBQQn7tJ.cjs.map +1 -0
  50. package/dist/fr-Ckn3K9v1.js +566 -0
  51. package/dist/fr-Ckn3K9v1.js.map +1 -0
  52. package/dist/he-DRsG7bH7.cjs +567 -0
  53. package/dist/he-DRsG7bH7.cjs.map +1 -0
  54. package/dist/he-wdGU5PkU.js +567 -0
  55. package/dist/he-wdGU5PkU.js.map +1 -0
  56. package/dist/icons-BrK5iVL8.js +856 -0
  57. package/dist/icons-BrK5iVL8.js.map +1 -0
  58. package/dist/icons-x0Tc05bs.cjs +1010 -0
  59. package/dist/icons-x0Tc05bs.cjs.map +1 -0
  60. package/dist/index.cjs +3162 -5106
  61. package/dist/index.cjs.map +1 -1
  62. package/dist/index.d.cts +636 -143
  63. package/dist/index.d.ts +636 -143
  64. package/dist/index.js +3083 -4975
  65. package/dist/index.js.map +1 -1
  66. package/dist/it-BuP4o0xQ.cjs +566 -0
  67. package/dist/it-BuP4o0xQ.cjs.map +1 -0
  68. package/dist/it-Us-VmvIu.js +566 -0
  69. package/dist/it-Us-VmvIu.js.map +1 -0
  70. package/dist/ja-Cizj0-5O.js +566 -0
  71. package/dist/ja-Cizj0-5O.js.map +1 -0
  72. package/dist/ja-DovEd6ts.cjs +566 -0
  73. package/dist/ja-DovEd6ts.cjs.map +1 -0
  74. package/dist/ko-B-qJEol2.cjs +566 -0
  75. package/dist/ko-B-qJEol2.cjs.map +1 -0
  76. package/dist/ko-DlrXliE1.js +566 -0
  77. package/dist/ko-DlrXliE1.js.map +1 -0
  78. package/dist/labels-BiM9wp9K.cjs +21 -0
  79. package/dist/labels-BiM9wp9K.cjs.map +1 -0
  80. package/dist/labels-C6_i87Oj.js +16 -0
  81. package/dist/labels-C6_i87Oj.js.map +1 -0
  82. package/dist/link-editor-CSjqPnj1.cjs +125 -0
  83. package/dist/link-editor-CSjqPnj1.cjs.map +1 -0
  84. package/dist/link-editor-SxM1nnJU.js +125 -0
  85. package/dist/link-editor-SxM1nnJU.js.map +1 -0
  86. package/dist/measurement-Bs61XWbJ.js +325 -0
  87. package/dist/measurement-Bs61XWbJ.js.map +1 -0
  88. package/dist/measurement-CcCsHPOX.cjs +326 -0
  89. package/dist/measurement-CcCsHPOX.cjs.map +1 -0
  90. package/dist/nl-0aF7M_0h.js +566 -0
  91. package/dist/nl-0aF7M_0h.js.map +1 -0
  92. package/dist/nl-D3KZDDiJ.cjs +566 -0
  93. package/dist/nl-D3KZDDiJ.cjs.map +1 -0
  94. package/dist/pl-BW--AaCI.js +566 -0
  95. package/dist/pl-BW--AaCI.js.map +1 -0
  96. package/dist/pl-DSFhAUqx.cjs +566 -0
  97. package/dist/pl-DSFhAUqx.cjs.map +1 -0
  98. package/dist/pt-C5S-8MC5.cjs +566 -0
  99. package/dist/pt-C5S-8MC5.cjs.map +1 -0
  100. package/dist/pt-DIhpU5pT.js +566 -0
  101. package/dist/pt-DIhpU5pT.js.map +1 -0
  102. package/dist/redact-confirm-B6j36TPw.js +83 -0
  103. package/dist/redact-confirm-B6j36TPw.js.map +1 -0
  104. package/dist/redact-confirm-CX_SY2ZN.cjs +83 -0
  105. package/dist/redact-confirm-CX_SY2ZN.cjs.map +1 -0
  106. package/dist/redaction-panel-BmoIl-Ll.cjs +96 -0
  107. package/dist/redaction-panel-BmoIl-Ll.cjs.map +1 -0
  108. package/dist/redaction-panel-IJDshSJI.js +96 -0
  109. package/dist/redaction-panel-IJDshSJI.js.map +1 -0
  110. package/dist/search-panel-HfIhJm1M.js +249 -0
  111. package/dist/search-panel-HfIhJm1M.js.map +1 -0
  112. package/dist/search-panel-s9IoiOtv.cjs +249 -0
  113. package/dist/search-panel-s9IoiOtv.cjs.map +1 -0
  114. package/dist/sheet-BDsa_Sup.cjs +442 -0
  115. package/dist/sheet-BDsa_Sup.cjs.map +1 -0
  116. package/dist/sheet-R6XDgyEf.js +365 -0
  117. package/dist/sheet-R6XDgyEf.js.map +1 -0
  118. package/dist/sign-dialog-CgnR7akj.cjs +155 -0
  119. package/dist/sign-dialog-CgnR7akj.cjs.map +1 -0
  120. package/dist/sign-dialog-GDqCoQhA.js +155 -0
  121. package/dist/sign-dialog-GDqCoQhA.js.map +1 -0
  122. package/dist/signature-inspector-DyO313Qf.cjs +166 -0
  123. package/dist/signature-inspector-DyO313Qf.cjs.map +1 -0
  124. package/dist/signature-inspector-okFz8do6.js +166 -0
  125. package/dist/signature-inspector-okFz8do6.js.map +1 -0
  126. package/dist/signature-maker-BhCmYyHD.js +393 -0
  127. package/dist/signature-maker-BhCmYyHD.js.map +1 -0
  128. package/dist/signature-maker-BoYa8vgA.cjs +393 -0
  129. package/dist/signature-maker-BoYa8vgA.cjs.map +1 -0
  130. package/dist/signatures-panel-B56PC6d9.cjs +300 -0
  131. package/dist/signatures-panel-B56PC6d9.cjs.map +1 -0
  132. package/dist/signatures-panel-CgnFfhFm.js +300 -0
  133. package/dist/signatures-panel-CgnFfhFm.js.map +1 -0
  134. package/dist/stamp-store-BHvRs-Do.cjs +147 -0
  135. package/dist/stamp-store-BHvRs-Do.cjs.map +1 -0
  136. package/dist/stamp-store-WuF-L3Jj.js +112 -0
  137. package/dist/stamp-store-WuF-L3Jj.js.map +1 -0
  138. package/dist/stamps-panel-B9NYGayn.cjs +231 -0
  139. package/dist/stamps-panel-B9NYGayn.cjs.map +1 -0
  140. package/dist/stamps-panel-CDO0FPyK.js +231 -0
  141. package/dist/stamps-panel-CDO0FPyK.js.map +1 -0
  142. package/dist/toolbar-CJu2wKTU.cjs +1659 -0
  143. package/dist/toolbar-CJu2wKTU.cjs.map +1 -0
  144. package/dist/toolbar-z9od3tKl.js +1564 -0
  145. package/dist/toolbar-z9od3tKl.js.map +1 -0
  146. package/dist/zh-cn-3tmMeHqv.cjs +566 -0
  147. package/dist/zh-cn-3tmMeHqv.cjs.map +1 -0
  148. package/dist/zh-cn-CxkUUBct.js +566 -0
  149. package/dist/zh-cn-CxkUUBct.js.map +1 -0
  150. package/package.json +6 -4
  151. package/src/styles.css +153 -89
  152. package/dist/commands.cjs.map +0 -1
  153. package/dist/commands.js.map +0 -1
  154. package/dist/es-DYwzfxyt.cjs +0 -293
  155. package/dist/es-DYwzfxyt.cjs.map +0 -1
  156. package/dist/es-sN6uqBgD.js +0 -293
  157. package/dist/es-sN6uqBgD.js.map +0 -1
@@ -0,0 +1,83 @@
1
+ import { t as Dialog } from "./dialog-B5GBisKv.js";
2
+ import { useId, useState } from "react";
3
+ import { useRedaction } from "@embedpdf/react/redaction";
4
+ import { useT } from "@embedpdf/react/i18n";
5
+ import { useSurface } from "@embedpdf/react/shell";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/ui/redact-confirm.tsx
8
+ /**
9
+ * The apply-all confirm modal (`redact-confirm` shell surface, `exclusive:
10
+ * 'modal'` via the command router). Shows the pending count and the
11
+ * client-side collateral estimate — other annotations the apply will destroy —
12
+ * before anything irreversible happens. The authoritative collateral count
13
+ * comes back on the result. Escape cancels, unless the apply is running.
14
+ */
15
+ function RedactConfirmModal() {
16
+ const t = useT();
17
+ const surface = useSurface("redact-confirm");
18
+ const redaction = useRedaction();
19
+ const [busy, setBusy] = useState(false);
20
+ const [error, setError] = useState(null);
21
+ const titleId = useId();
22
+ if (!surface.isOpen) return null;
23
+ const count = redaction.getPendingCount();
24
+ const collateral = redaction.estimateCollateral().count;
25
+ const apply = async () => {
26
+ setBusy(true);
27
+ setError(null);
28
+ try {
29
+ await redaction.applyAll();
30
+ surface.close();
31
+ } catch (error) {
32
+ setError(error instanceof Error ? error.message : String(error));
33
+ } finally {
34
+ setBusy(false);
35
+ }
36
+ };
37
+ return /* @__PURE__ */ jsxs(Dialog, {
38
+ labelledBy: titleId,
39
+ onClose: () => {
40
+ if (!busy) surface.close();
41
+ },
42
+ className: "border-border bg-surface w-96 rounded-lg border p-4 shadow-xl",
43
+ children: [
44
+ /* @__PURE__ */ jsx("h2", {
45
+ id: titleId,
46
+ className: "text-fg text-base font-semibold",
47
+ children: t("demo.redactConfirmTitle")
48
+ }),
49
+ /* @__PURE__ */ jsx("p", {
50
+ className: "text-fg-muted mt-2 text-sm",
51
+ children: t("demo.redactConfirmBody", { params: { count } })
52
+ }),
53
+ collateral > 0 ? /* @__PURE__ */ jsx("p", {
54
+ className: "mt-2 text-sm font-medium text-red-600",
55
+ children: t("demo.redactConfirmCollateral", { params: { count: collateral } })
56
+ }) : null,
57
+ error ? /* @__PURE__ */ jsx("p", {
58
+ className: "mt-2 text-sm text-red-600",
59
+ children: error
60
+ }) : null,
61
+ /* @__PURE__ */ jsxs("div", {
62
+ className: "mt-4 flex justify-end gap-2",
63
+ children: [/* @__PURE__ */ jsx("button", {
64
+ type: "button",
65
+ disabled: busy,
66
+ onClick: surface.close,
67
+ className: "border-border text-fg hover:bg-hover rounded-md border px-3 py-1.5 text-sm",
68
+ children: t("demo.cancel")
69
+ }), /* @__PURE__ */ jsx("button", {
70
+ type: "button",
71
+ disabled: busy,
72
+ onClick: () => void apply(),
73
+ className: "rounded-md bg-red-600 px-3 py-1.5 text-sm text-white hover:bg-red-700 disabled:opacity-60",
74
+ children: busy ? t("demo.redactApplying") : t("demo.redactApply")
75
+ })]
76
+ })
77
+ ]
78
+ });
79
+ }
80
+ //#endregion
81
+ export { RedactConfirmModal };
82
+
83
+ //# sourceMappingURL=redact-confirm-B6j36TPw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact-confirm-B6j36TPw.js","names":[],"sources":["../src/ui/redact-confirm.tsx"],"sourcesContent":["import { useId, useState } from 'react';\nimport { useRedaction } from '@embedpdf/react/redaction';\nimport { useSurface } from '@embedpdf/react/shell';\nimport { useT } from '@embedpdf/react/i18n';\nimport { Dialog } from './dialog';\n\n/**\n * The apply-all confirm modal (`redact-confirm` shell surface, `exclusive:\n * 'modal'` via the command router). Shows the pending count and the\n * client-side collateral estimate — other annotations the apply will destroy —\n * before anything irreversible happens. The authoritative collateral count\n * comes back on the result. Escape cancels, unless the apply is running.\n */\nexport function RedactConfirmModal() {\n const t = useT();\n const surface = useSurface('redact-confirm');\n const redaction = useRedaction();\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const titleId = useId();\n\n if (!surface.isOpen) return null;\n\n const count = redaction.getPendingCount();\n const collateral = redaction.estimateCollateral().count;\n\n const apply = async () => {\n setBusy(true);\n setError(null);\n try {\n await redaction.applyAll();\n surface.close();\n } catch (error) {\n setError(error instanceof Error ? error.message : String(error));\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Dialog\n labelledBy={titleId}\n onClose={() => {\n if (!busy) surface.close();\n }}\n className=\"border-border bg-surface w-96 rounded-lg border p-4 shadow-xl\"\n >\n <h2 id={titleId} className=\"text-fg text-base font-semibold\">\n {t('demo.redactConfirmTitle')}\n </h2>\n <p className=\"text-fg-muted mt-2 text-sm\">\n {t('demo.redactConfirmBody', { params: { count } })}\n </p>\n {collateral > 0 ? (\n <p className=\"mt-2 text-sm font-medium text-red-600\">\n {t('demo.redactConfirmCollateral', { params: { count: collateral } })}\n </p>\n ) : null}\n {error ? <p className=\"mt-2 text-sm text-red-600\">{error}</p> : null}\n <div className=\"mt-4 flex justify-end gap-2\">\n <button\n type=\"button\"\n disabled={busy}\n onClick={surface.close}\n className=\"border-border text-fg hover:bg-hover rounded-md border px-3 py-1.5 text-sm\"\n >\n {t('demo.cancel')}\n </button>\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => void apply()}\n className=\"rounded-md bg-red-600 px-3 py-1.5 text-sm text-white hover:bg-red-700 disabled:opacity-60\"\n >\n {busy ? t('demo.redactApplying') : t('demo.redactApply')}\n </button>\n </div>\n </Dialog>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AAaA,SAAgB,qBAAqB;CACnC,MAAM,IAAI,KAAK;CACf,MAAM,UAAU,WAAW,gBAAgB;CAC3C,MAAM,YAAY,aAAa;CAC/B,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,MAAM,CAAC,OAAO,YAAY,SAAwB,IAAI;CACtD,MAAM,UAAU,MAAM;CAEtB,IAAI,CAAC,QAAQ,QAAQ,OAAO;CAE5B,MAAM,QAAQ,UAAU,gBAAgB;CACxC,MAAM,aAAa,UAAU,mBAAmB,CAAC,CAAC;CAElD,MAAM,QAAQ,YAAY;EACxB,QAAQ,IAAI;EACZ,SAAS,IAAI;EACb,IAAI;GACF,MAAM,UAAU,SAAS;GACzB,QAAQ,MAAM;EAChB,SAAS,OAAO;GACd,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;EACjE,UAAU;GACR,QAAQ,KAAK;EACf;CACF;CAEA,OACE,qBAAC,QAAD;EACE,YAAY;EACZ,eAAe;GACb,IAAI,CAAC,MAAM,QAAQ,MAAM;EAC3B;EACA,WAAU;EALZ,UAAA;GAOE,oBAAC,MAAD;IAAI,IAAI;IAAS,WAAU;IACxB,UAAA,EAAE,yBAAyB;GAC1B,CAAA;GACJ,oBAAC,KAAD;IAAG,WAAU;IACV,UAAA,EAAE,0BAA0B,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;GACjD,CAAA;GACF,aAAa,IACZ,oBAAC,KAAD;IAAG,WAAU;IACV,UAAA,EAAE,gCAAgC,EAAE,QAAQ,EAAE,OAAO,WAAW,EAAE,CAAC;GACnE,CAAA,IACD;GACH,QAAQ,oBAAC,KAAD;IAAG,WAAU;IAA6B,UAAA;GAAS,CAAA,IAAI;GAChE,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,oBAAC,UAAD;KACE,MAAK;KACL,UAAU;KACV,SAAS,QAAQ;KACjB,WAAU;KAET,UAAA,EAAE,aAAa;IACV,CAAA,GACR,oBAAC,UAAD;KACE,MAAK;KACL,UAAU;KACV,eAAe,KAAK,MAAM;KAC1B,WAAU;KAET,UAAA,OAAO,EAAE,qBAAqB,IAAI,EAAE,kBAAkB;IACjD,CAAA,CACL;;EACC;;AAEZ"}
@@ -0,0 +1,83 @@
1
+ const require_dialog = require("./dialog-t8F13BL_.cjs");
2
+ let react = require("react");
3
+ let _embedpdf_react_redaction = require("@embedpdf/react/redaction");
4
+ let _embedpdf_react_i18n = require("@embedpdf/react/i18n");
5
+ let _embedpdf_react_shell = require("@embedpdf/react/shell");
6
+ let react_jsx_runtime = require("react/jsx-runtime");
7
+ //#region src/ui/redact-confirm.tsx
8
+ /**
9
+ * The apply-all confirm modal (`redact-confirm` shell surface, `exclusive:
10
+ * 'modal'` via the command router). Shows the pending count and the
11
+ * client-side collateral estimate — other annotations the apply will destroy —
12
+ * before anything irreversible happens. The authoritative collateral count
13
+ * comes back on the result. Escape cancels, unless the apply is running.
14
+ */
15
+ function RedactConfirmModal() {
16
+ const t = (0, _embedpdf_react_i18n.useT)();
17
+ const surface = (0, _embedpdf_react_shell.useSurface)("redact-confirm");
18
+ const redaction = (0, _embedpdf_react_redaction.useRedaction)();
19
+ const [busy, setBusy] = (0, react.useState)(false);
20
+ const [error, setError] = (0, react.useState)(null);
21
+ const titleId = (0, react.useId)();
22
+ if (!surface.isOpen) return null;
23
+ const count = redaction.getPendingCount();
24
+ const collateral = redaction.estimateCollateral().count;
25
+ const apply = async () => {
26
+ setBusy(true);
27
+ setError(null);
28
+ try {
29
+ await redaction.applyAll();
30
+ surface.close();
31
+ } catch (error) {
32
+ setError(error instanceof Error ? error.message : String(error));
33
+ } finally {
34
+ setBusy(false);
35
+ }
36
+ };
37
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_dialog.Dialog, {
38
+ labelledBy: titleId,
39
+ onClose: () => {
40
+ if (!busy) surface.close();
41
+ },
42
+ className: "border-border bg-surface w-96 rounded-lg border p-4 shadow-xl",
43
+ children: [
44
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
45
+ id: titleId,
46
+ className: "text-fg text-base font-semibold",
47
+ children: t("demo.redactConfirmTitle")
48
+ }),
49
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
50
+ className: "text-fg-muted mt-2 text-sm",
51
+ children: t("demo.redactConfirmBody", { params: { count } })
52
+ }),
53
+ collateral > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
54
+ className: "mt-2 text-sm font-medium text-red-600",
55
+ children: t("demo.redactConfirmCollateral", { params: { count: collateral } })
56
+ }) : null,
57
+ error ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
58
+ className: "mt-2 text-sm text-red-600",
59
+ children: error
60
+ }) : null,
61
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
62
+ className: "mt-4 flex justify-end gap-2",
63
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
64
+ type: "button",
65
+ disabled: busy,
66
+ onClick: surface.close,
67
+ className: "border-border text-fg hover:bg-hover rounded-md border px-3 py-1.5 text-sm",
68
+ children: t("demo.cancel")
69
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
70
+ type: "button",
71
+ disabled: busy,
72
+ onClick: () => void apply(),
73
+ className: "rounded-md bg-red-600 px-3 py-1.5 text-sm text-white hover:bg-red-700 disabled:opacity-60",
74
+ children: busy ? t("demo.redactApplying") : t("demo.redactApply")
75
+ })]
76
+ })
77
+ ]
78
+ });
79
+ }
80
+ //#endregion
81
+ exports.RedactConfirmModal = RedactConfirmModal;
82
+
83
+ //# sourceMappingURL=redact-confirm-CX_SY2ZN.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact-confirm-CX_SY2ZN.cjs","names":["Dialog"],"sources":["../src/ui/redact-confirm.tsx"],"sourcesContent":["import { useId, useState } from 'react';\nimport { useRedaction } from '@embedpdf/react/redaction';\nimport { useSurface } from '@embedpdf/react/shell';\nimport { useT } from '@embedpdf/react/i18n';\nimport { Dialog } from './dialog';\n\n/**\n * The apply-all confirm modal (`redact-confirm` shell surface, `exclusive:\n * 'modal'` via the command router). Shows the pending count and the\n * client-side collateral estimate — other annotations the apply will destroy —\n * before anything irreversible happens. The authoritative collateral count\n * comes back on the result. Escape cancels, unless the apply is running.\n */\nexport function RedactConfirmModal() {\n const t = useT();\n const surface = useSurface('redact-confirm');\n const redaction = useRedaction();\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const titleId = useId();\n\n if (!surface.isOpen) return null;\n\n const count = redaction.getPendingCount();\n const collateral = redaction.estimateCollateral().count;\n\n const apply = async () => {\n setBusy(true);\n setError(null);\n try {\n await redaction.applyAll();\n surface.close();\n } catch (error) {\n setError(error instanceof Error ? error.message : String(error));\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Dialog\n labelledBy={titleId}\n onClose={() => {\n if (!busy) surface.close();\n }}\n className=\"border-border bg-surface w-96 rounded-lg border p-4 shadow-xl\"\n >\n <h2 id={titleId} className=\"text-fg text-base font-semibold\">\n {t('demo.redactConfirmTitle')}\n </h2>\n <p className=\"text-fg-muted mt-2 text-sm\">\n {t('demo.redactConfirmBody', { params: { count } })}\n </p>\n {collateral > 0 ? (\n <p className=\"mt-2 text-sm font-medium text-red-600\">\n {t('demo.redactConfirmCollateral', { params: { count: collateral } })}\n </p>\n ) : null}\n {error ? <p className=\"mt-2 text-sm text-red-600\">{error}</p> : null}\n <div className=\"mt-4 flex justify-end gap-2\">\n <button\n type=\"button\"\n disabled={busy}\n onClick={surface.close}\n className=\"border-border text-fg hover:bg-hover rounded-md border px-3 py-1.5 text-sm\"\n >\n {t('demo.cancel')}\n </button>\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => void apply()}\n className=\"rounded-md bg-red-600 px-3 py-1.5 text-sm text-white hover:bg-red-700 disabled:opacity-60\"\n >\n {busy ? t('demo.redactApplying') : t('demo.redactApply')}\n </button>\n </div>\n </Dialog>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AAaA,SAAgB,qBAAqB;CACnC,MAAM,KAAA,GAAA,qBAAA,KAAA,CAAS;CACf,MAAM,WAAA,GAAA,sBAAA,WAAA,CAAqB,gBAAgB;CAC3C,MAAM,aAAA,GAAA,0BAAA,aAAA,CAAyB;CAC/B,MAAM,CAAC,MAAM,YAAA,GAAA,MAAA,SAAA,CAAoB,KAAK;CACtC,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,SAAA,CAAoC,IAAI;CACtD,MAAM,WAAA,GAAA,MAAA,MAAA,CAAgB;CAEtB,IAAI,CAAC,QAAQ,QAAQ,OAAO;CAE5B,MAAM,QAAQ,UAAU,gBAAgB;CACxC,MAAM,aAAa,UAAU,mBAAmB,CAAC,CAAC;CAElD,MAAM,QAAQ,YAAY;EACxB,QAAQ,IAAI;EACZ,SAAS,IAAI;EACb,IAAI;GACF,MAAM,UAAU,SAAS;GACzB,QAAQ,MAAM;EAChB,SAAS,OAAO;GACd,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;EACjE,UAAU;GACR,QAAQ,KAAK;EACf;CACF;CAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAACA,eAAAA,QAAD;EACE,YAAY;EACZ,eAAe;GACb,IAAI,CAAC,MAAM,QAAQ,MAAM;EAC3B;EACA,WAAU;EALZ,UAAA;GAOE,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;IAAI,IAAI;IAAS,WAAU;IACxB,UAAA,EAAE,yBAAyB;GAC1B,CAAA;GACJ,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;IAAG,WAAU;IACV,UAAA,EAAE,0BAA0B,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;GACjD,CAAA;GACF,aAAa,IACZ,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;IAAG,WAAU;IACV,UAAA,EAAE,gCAAgC,EAAE,QAAQ,EAAE,OAAO,WAAW,EAAE,CAAC;GACnE,CAAA,IACD;GACH,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;IAAG,WAAU;IAA6B,UAAA;GAAS,CAAA,IAAI;GAChE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;KACE,MAAK;KACL,UAAU;KACV,SAAS,QAAQ;KACjB,WAAU;KAET,UAAA,EAAE,aAAa;IACV,CAAA,GACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;KACE,MAAK;KACL,UAAU;KACV,eAAe,KAAK,MAAM;KAC1B,WAAU;KAET,UAAA,OAAO,EAAE,qBAAqB,IAAI,EAAE,kBAAkB;IACjD,CAAA,CACL;;EACC;;AAEZ"}
@@ -0,0 +1,96 @@
1
+ const require_icons = require("./icons-x0Tc05bs.cjs");
2
+ let _embedpdf_react_runtime = require("@embedpdf/react/runtime");
3
+ let _embedpdf_react_annotation = require("@embedpdf/react/annotation");
4
+ let _embedpdf_react_redaction = require("@embedpdf/react/redaction");
5
+ let _embedpdf_react_i18n = require("@embedpdf/react/i18n");
6
+ let _embedpdf_react_shell = require("@embedpdf/react/shell");
7
+ let react_jsx_runtime = require("react/jsx-runtime");
8
+ //#region src/ui/redaction-panel.tsx
9
+ /**
10
+ * The pending-redactions review panel (right sidebar). The list is a live view
11
+ * over the annotation plane — deleting a mark here is deleting the annotation.
12
+ * "Apply all" routes through the confirm modal: the apply is irreversible.
13
+ */
14
+ function RedactionPanel() {
15
+ const t = (0, _embedpdf_react_i18n.useT)();
16
+ const redaction = (0, _embedpdf_react_redaction.useRedaction)();
17
+ const applying = (0, _embedpdf_react_redaction.useRedactionState)((state) => state.applying);
18
+ const pending = (0, _embedpdf_react_redaction.usePendingRedactions)();
19
+ const anno = (0, _embedpdf_react_runtime.useCapability)(_embedpdf_react_annotation.AnnotationToken);
20
+ const confirm = (0, _embedpdf_react_shell.useSurface)("redact-confirm");
21
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
22
+ className: "flex min-h-0 flex-1 flex-col",
23
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
24
+ className: "min-h-0 flex-1 overflow-y-auto p-2",
25
+ children: pending.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
26
+ className: "flex flex-col items-center gap-3 px-4 py-10 text-center",
27
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons.Icon, {
28
+ name: "redactionSidebar",
29
+ size: 32,
30
+ className: "text-fg-muted"
31
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
32
+ className: "text-fg-muted text-sm",
33
+ children: t("demo.redactionEmpty")
34
+ })]
35
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
36
+ className: "flex flex-col gap-1",
37
+ children: pending.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38
+ role: "button",
39
+ tabIndex: 0,
40
+ onClick: () => anno.selection.set([item.ref]),
41
+ onKeyDown: (event) => event.key === "Enter" && anno.selection.set([item.ref]),
42
+ className: "hover:bg-hover group flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-start",
43
+ children: [
44
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons.Icon, {
45
+ name: item.kind === "area" ? "redactArea" : "redact",
46
+ size: 16,
47
+ className: "text-fg-muted shrink-0"
48
+ }),
49
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
50
+ className: "text-fg min-w-0 flex-1 truncate text-sm",
51
+ children: item.overlayText ?? t(item.kind === "area" ? "demo.redactionArea" : "demo.redactionText")
52
+ }),
53
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
54
+ className: "text-fg-muted shrink-0 text-xs",
55
+ children: t("demo.pageBadge", { params: { page: item.pageIndex >= 0 ? String(item.pageIndex + 1) : "?" } })
56
+ }),
57
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
58
+ type: "button",
59
+ onClick: (event) => {
60
+ event.stopPropagation();
61
+ anno.delete(item.ref);
62
+ },
63
+ className: "text-fg-muted hover:text-fg grid h-6 w-6 shrink-0 place-items-center rounded opacity-0 group-hover:opacity-100",
64
+ title: t("demo.redactionRemove"),
65
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons.Icon, {
66
+ name: "trash",
67
+ size: 14
68
+ })
69
+ })
70
+ ]
71
+ }) }, (0, _embedpdf_react_annotation.annotationKey)(item.ref)))
72
+ })
73
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
74
+ className: "border-border-subtle flex shrink-0 gap-2 border-t p-3",
75
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
76
+ type: "button",
77
+ disabled: pending.length === 0,
78
+ onClick: () => {
79
+ for (const item of pending) anno.delete(item.ref);
80
+ },
81
+ className: "border-border text-fg hover:bg-hover flex-1 rounded-md border px-3 py-1.5 text-sm disabled:opacity-40",
82
+ children: t("commands.redact.clearAll")
83
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
84
+ type: "button",
85
+ disabled: pending.length === 0 || !redaction.canApply() || applying,
86
+ onClick: () => confirm.open(),
87
+ className: "flex-1 rounded-md bg-red-600 px-3 py-1.5 text-sm text-white hover:bg-red-700 disabled:opacity-40",
88
+ children: t("commands.redact.applyAll")
89
+ })]
90
+ })]
91
+ });
92
+ }
93
+ //#endregion
94
+ exports.RedactionPanel = RedactionPanel;
95
+
96
+ //# sourceMappingURL=redaction-panel-BmoIl-Ll.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redaction-panel-BmoIl-Ll.cjs","names":["AnnotationToken","Icon"],"sources":["../src/ui/redaction-panel.tsx"],"sourcesContent":["import { useCapability } from '@embedpdf/react/runtime';\nimport { AnnotationToken } from '@embedpdf/react/annotation';\nimport { annotationKey } from '@embedpdf/react/annotation';\nimport { usePendingRedactions, useRedaction, useRedactionState } from '@embedpdf/react/redaction';\nimport { useSurface } from '@embedpdf/react/shell';\nimport { useT } from '@embedpdf/react/i18n';\nimport { Icon } from './icons';\n\n/**\n * The pending-redactions review panel (right sidebar). The list is a live view\n * over the annotation plane — deleting a mark here is deleting the annotation.\n * \"Apply all\" routes through the confirm modal: the apply is irreversible.\n */\nexport function RedactionPanel() {\n const t = useT();\n const redaction = useRedaction();\n const applying = useRedactionState((state) => state.applying);\n const pending = usePendingRedactions();\n const anno = useCapability(AnnotationToken);\n const confirm = useSurface('redact-confirm');\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col\">\n <div className=\"min-h-0 flex-1 overflow-y-auto p-2\">\n {pending.length === 0 ? (\n <div className=\"flex flex-col items-center gap-3 px-4 py-10 text-center\">\n <Icon name=\"redactionSidebar\" size={32} className=\"text-fg-muted\" />\n <p className=\"text-fg-muted text-sm\">{t('demo.redactionEmpty')}</p>\n </div>\n ) : (\n <ul className=\"flex flex-col gap-1\">\n {pending.map((item) => (\n <li key={annotationKey(item.ref)}>\n <div\n role=\"button\"\n tabIndex={0}\n onClick={() => anno.selection.set([item.ref])}\n onKeyDown={(event) => event.key === 'Enter' && anno.selection.set([item.ref])}\n className=\"hover:bg-hover group flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-start\"\n >\n <Icon\n name={item.kind === 'area' ? 'redactArea' : 'redact'}\n size={16}\n className=\"text-fg-muted shrink-0\"\n />\n <span className=\"text-fg min-w-0 flex-1 truncate text-sm\">\n {item.overlayText ??\n t(item.kind === 'area' ? 'demo.redactionArea' : 'demo.redactionText')}\n </span>\n <span className=\"text-fg-muted shrink-0 text-xs\">\n {t('demo.pageBadge', {\n params: { page: item.pageIndex >= 0 ? String(item.pageIndex + 1) : '?' },\n })}\n </span>\n <button\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n void anno.delete(item.ref);\n }}\n className=\"text-fg-muted hover:text-fg grid h-6 w-6 shrink-0 place-items-center rounded opacity-0 group-hover:opacity-100\"\n title={t('demo.redactionRemove')}\n >\n <Icon name=\"trash\" size={14} />\n </button>\n </div>\n </li>\n ))}\n </ul>\n )}\n </div>\n <div className=\"border-border-subtle flex shrink-0 gap-2 border-t p-3\">\n <button\n type=\"button\"\n disabled={pending.length === 0}\n onClick={() => {\n for (const item of pending) void anno.delete(item.ref);\n }}\n className=\"border-border text-fg hover:bg-hover flex-1 rounded-md border px-3 py-1.5 text-sm disabled:opacity-40\"\n >\n {t('commands.redact.clearAll')}\n </button>\n <button\n type=\"button\"\n disabled={pending.length === 0 || !redaction.canApply() || applying}\n onClick={() => confirm.open()}\n className=\"flex-1 rounded-md bg-red-600 px-3 py-1.5 text-sm text-white hover:bg-red-700 disabled:opacity-40\"\n >\n {t('commands.redact.applyAll')}\n </button>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAaA,SAAgB,iBAAiB;CAC/B,MAAM,KAAA,GAAA,qBAAA,KAAA,CAAS;CACf,MAAM,aAAA,GAAA,0BAAA,aAAA,CAAyB;CAC/B,MAAM,YAAA,GAAA,0BAAA,kBAAA,EAA8B,UAAU,MAAM,QAAQ;CAC5D,MAAM,WAAA,GAAA,0BAAA,qBAAA,CAA+B;CACrC,MAAM,QAAA,GAAA,wBAAA,cAAA,CAAqBA,2BAAAA,eAAe;CAC1C,MAAM,WAAA,GAAA,sBAAA,WAAA,CAAqB,gBAAgB;CAE3C,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;GAAK,WAAU;GACZ,UAAA,QAAQ,WAAW,IAClB,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,cAAAA,MAAD;KAAM,MAAK;KAAmB,MAAM;KAAI,WAAU;IAAiB,CAAA,GACnE,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;KAAG,WAAU;KAAyB,UAAA,EAAE,qBAAqB;IAAK,CAAA,CAC/D;GAEL,CAAA,IAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;IAAI,WAAU;IACX,UAAA,QAAQ,KAAK,SACZ,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KACE,MAAK;KACL,UAAU;KACV,eAAe,KAAK,UAAU,IAAI,CAAC,KAAK,GAAG,CAAC;KAC5C,YAAY,UAAU,MAAM,QAAQ,WAAW,KAAK,UAAU,IAAI,CAAC,KAAK,GAAG,CAAC;KAC5E,WAAU;KALZ,UAAA;MAOE,iBAAA,GAAA,kBAAA,IAAA,CAACA,cAAAA,MAAD;OACE,MAAM,KAAK,SAAS,SAAS,eAAe;OAC5C,MAAM;OACN,WAAU;MACX,CAAA;MACD,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAM,WAAU;OACb,UAAA,KAAK,eACJ,EAAE,KAAK,SAAS,SAAS,uBAAuB,oBAAoB;MAClE,CAAA;MACN,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAM,WAAU;OACb,UAAA,EAAE,kBAAkB,EACnB,QAAQ,EAAE,MAAM,KAAK,aAAa,IAAI,OAAO,KAAK,YAAY,CAAC,IAAI,IAAI,EACzE,CAAC;MACG,CAAA;MACN,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;OACE,MAAK;OACL,UAAU,UAAU;QAClB,MAAM,gBAAgB;QACtB,KAAU,OAAO,KAAK,GAAG;OAC3B;OACA,WAAU;OACV,OAAO,EAAE,sBAAsB;OAE/B,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACA,cAAAA,MAAD;QAAM,MAAK;QAAQ,MAAM;OAAK,CAAA;MACxB,CAAA;KACL;IACH,CAAA,EAAA,IAAA,GAAA,2BAAA,cAAA,CAlCmB,KAAK,GAAG,CAkC3B,CACL;GACC,CAAA;EAEH,CAAA,GACL,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;IACE,MAAK;IACL,UAAU,QAAQ,WAAW;IAC7B,eAAe;KACb,KAAK,MAAM,QAAQ,SAAS,KAAU,OAAO,KAAK,GAAG;IACvD;IACA,WAAU;IAET,UAAA,EAAE,0BAA0B;GACvB,CAAA,GACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;IACE,MAAK;IACL,UAAU,QAAQ,WAAW,KAAK,CAAC,UAAU,SAAS,KAAK;IAC3D,eAAe,QAAQ,KAAK;IAC5B,WAAU;IAET,UAAA,EAAE,0BAA0B;GACvB,CAAA,CACL;EACF,CAAA,CAAA;;AAET"}
@@ -0,0 +1,96 @@
1
+ import { n as Icon } from "./icons-BrK5iVL8.js";
2
+ import { useCapability } from "@embedpdf/react/runtime";
3
+ import { AnnotationToken, annotationKey } from "@embedpdf/react/annotation";
4
+ import { usePendingRedactions, useRedaction, useRedactionState } from "@embedpdf/react/redaction";
5
+ import { useT } from "@embedpdf/react/i18n";
6
+ import { useSurface } from "@embedpdf/react/shell";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ //#region src/ui/redaction-panel.tsx
9
+ /**
10
+ * The pending-redactions review panel (right sidebar). The list is a live view
11
+ * over the annotation plane — deleting a mark here is deleting the annotation.
12
+ * "Apply all" routes through the confirm modal: the apply is irreversible.
13
+ */
14
+ function RedactionPanel() {
15
+ const t = useT();
16
+ const redaction = useRedaction();
17
+ const applying = useRedactionState((state) => state.applying);
18
+ const pending = usePendingRedactions();
19
+ const anno = useCapability(AnnotationToken);
20
+ const confirm = useSurface("redact-confirm");
21
+ return /* @__PURE__ */ jsxs("div", {
22
+ className: "flex min-h-0 flex-1 flex-col",
23
+ children: [/* @__PURE__ */ jsx("div", {
24
+ className: "min-h-0 flex-1 overflow-y-auto p-2",
25
+ children: pending.length === 0 ? /* @__PURE__ */ jsxs("div", {
26
+ className: "flex flex-col items-center gap-3 px-4 py-10 text-center",
27
+ children: [/* @__PURE__ */ jsx(Icon, {
28
+ name: "redactionSidebar",
29
+ size: 32,
30
+ className: "text-fg-muted"
31
+ }), /* @__PURE__ */ jsx("p", {
32
+ className: "text-fg-muted text-sm",
33
+ children: t("demo.redactionEmpty")
34
+ })]
35
+ }) : /* @__PURE__ */ jsx("ul", {
36
+ className: "flex flex-col gap-1",
37
+ children: pending.map((item) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("div", {
38
+ role: "button",
39
+ tabIndex: 0,
40
+ onClick: () => anno.selection.set([item.ref]),
41
+ onKeyDown: (event) => event.key === "Enter" && anno.selection.set([item.ref]),
42
+ className: "hover:bg-hover group flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-start",
43
+ children: [
44
+ /* @__PURE__ */ jsx(Icon, {
45
+ name: item.kind === "area" ? "redactArea" : "redact",
46
+ size: 16,
47
+ className: "text-fg-muted shrink-0"
48
+ }),
49
+ /* @__PURE__ */ jsx("span", {
50
+ className: "text-fg min-w-0 flex-1 truncate text-sm",
51
+ children: item.overlayText ?? t(item.kind === "area" ? "demo.redactionArea" : "demo.redactionText")
52
+ }),
53
+ /* @__PURE__ */ jsx("span", {
54
+ className: "text-fg-muted shrink-0 text-xs",
55
+ children: t("demo.pageBadge", { params: { page: item.pageIndex >= 0 ? String(item.pageIndex + 1) : "?" } })
56
+ }),
57
+ /* @__PURE__ */ jsx("button", {
58
+ type: "button",
59
+ onClick: (event) => {
60
+ event.stopPropagation();
61
+ anno.delete(item.ref);
62
+ },
63
+ className: "text-fg-muted hover:text-fg grid h-6 w-6 shrink-0 place-items-center rounded opacity-0 group-hover:opacity-100",
64
+ title: t("demo.redactionRemove"),
65
+ children: /* @__PURE__ */ jsx(Icon, {
66
+ name: "trash",
67
+ size: 14
68
+ })
69
+ })
70
+ ]
71
+ }) }, annotationKey(item.ref)))
72
+ })
73
+ }), /* @__PURE__ */ jsxs("div", {
74
+ className: "border-border-subtle flex shrink-0 gap-2 border-t p-3",
75
+ children: [/* @__PURE__ */ jsx("button", {
76
+ type: "button",
77
+ disabled: pending.length === 0,
78
+ onClick: () => {
79
+ for (const item of pending) anno.delete(item.ref);
80
+ },
81
+ className: "border-border text-fg hover:bg-hover flex-1 rounded-md border px-3 py-1.5 text-sm disabled:opacity-40",
82
+ children: t("commands.redact.clearAll")
83
+ }), /* @__PURE__ */ jsx("button", {
84
+ type: "button",
85
+ disabled: pending.length === 0 || !redaction.canApply() || applying,
86
+ onClick: () => confirm.open(),
87
+ className: "flex-1 rounded-md bg-red-600 px-3 py-1.5 text-sm text-white hover:bg-red-700 disabled:opacity-40",
88
+ children: t("commands.redact.applyAll")
89
+ })]
90
+ })]
91
+ });
92
+ }
93
+ //#endregion
94
+ export { RedactionPanel };
95
+
96
+ //# sourceMappingURL=redaction-panel-IJDshSJI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redaction-panel-IJDshSJI.js","names":[],"sources":["../src/ui/redaction-panel.tsx"],"sourcesContent":["import { useCapability } from '@embedpdf/react/runtime';\nimport { AnnotationToken } from '@embedpdf/react/annotation';\nimport { annotationKey } from '@embedpdf/react/annotation';\nimport { usePendingRedactions, useRedaction, useRedactionState } from '@embedpdf/react/redaction';\nimport { useSurface } from '@embedpdf/react/shell';\nimport { useT } from '@embedpdf/react/i18n';\nimport { Icon } from './icons';\n\n/**\n * The pending-redactions review panel (right sidebar). The list is a live view\n * over the annotation plane — deleting a mark here is deleting the annotation.\n * \"Apply all\" routes through the confirm modal: the apply is irreversible.\n */\nexport function RedactionPanel() {\n const t = useT();\n const redaction = useRedaction();\n const applying = useRedactionState((state) => state.applying);\n const pending = usePendingRedactions();\n const anno = useCapability(AnnotationToken);\n const confirm = useSurface('redact-confirm');\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col\">\n <div className=\"min-h-0 flex-1 overflow-y-auto p-2\">\n {pending.length === 0 ? (\n <div className=\"flex flex-col items-center gap-3 px-4 py-10 text-center\">\n <Icon name=\"redactionSidebar\" size={32} className=\"text-fg-muted\" />\n <p className=\"text-fg-muted text-sm\">{t('demo.redactionEmpty')}</p>\n </div>\n ) : (\n <ul className=\"flex flex-col gap-1\">\n {pending.map((item) => (\n <li key={annotationKey(item.ref)}>\n <div\n role=\"button\"\n tabIndex={0}\n onClick={() => anno.selection.set([item.ref])}\n onKeyDown={(event) => event.key === 'Enter' && anno.selection.set([item.ref])}\n className=\"hover:bg-hover group flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-start\"\n >\n <Icon\n name={item.kind === 'area' ? 'redactArea' : 'redact'}\n size={16}\n className=\"text-fg-muted shrink-0\"\n />\n <span className=\"text-fg min-w-0 flex-1 truncate text-sm\">\n {item.overlayText ??\n t(item.kind === 'area' ? 'demo.redactionArea' : 'demo.redactionText')}\n </span>\n <span className=\"text-fg-muted shrink-0 text-xs\">\n {t('demo.pageBadge', {\n params: { page: item.pageIndex >= 0 ? String(item.pageIndex + 1) : '?' },\n })}\n </span>\n <button\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n void anno.delete(item.ref);\n }}\n className=\"text-fg-muted hover:text-fg grid h-6 w-6 shrink-0 place-items-center rounded opacity-0 group-hover:opacity-100\"\n title={t('demo.redactionRemove')}\n >\n <Icon name=\"trash\" size={14} />\n </button>\n </div>\n </li>\n ))}\n </ul>\n )}\n </div>\n <div className=\"border-border-subtle flex shrink-0 gap-2 border-t p-3\">\n <button\n type=\"button\"\n disabled={pending.length === 0}\n onClick={() => {\n for (const item of pending) void anno.delete(item.ref);\n }}\n className=\"border-border text-fg hover:bg-hover flex-1 rounded-md border px-3 py-1.5 text-sm disabled:opacity-40\"\n >\n {t('commands.redact.clearAll')}\n </button>\n <button\n type=\"button\"\n disabled={pending.length === 0 || !redaction.canApply() || applying}\n onClick={() => confirm.open()}\n className=\"flex-1 rounded-md bg-red-600 px-3 py-1.5 text-sm text-white hover:bg-red-700 disabled:opacity-40\"\n >\n {t('commands.redact.applyAll')}\n </button>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAaA,SAAgB,iBAAiB;CAC/B,MAAM,IAAI,KAAK;CACf,MAAM,YAAY,aAAa;CAC/B,MAAM,WAAW,mBAAmB,UAAU,MAAM,QAAQ;CAC5D,MAAM,UAAU,qBAAqB;CACrC,MAAM,OAAO,cAAc,eAAe;CAC1C,MAAM,UAAU,WAAW,gBAAgB;CAE3C,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACE,oBAAC,OAAD;GAAK,WAAU;GACZ,UAAA,QAAQ,WAAW,IAClB,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,oBAAC,MAAD;KAAM,MAAK;KAAmB,MAAM;KAAI,WAAU;IAAiB,CAAA,GACnE,oBAAC,KAAD;KAAG,WAAU;KAAyB,UAAA,EAAE,qBAAqB;IAAK,CAAA,CAC/D;GAEL,CAAA,IAAA,oBAAC,MAAD;IAAI,WAAU;IACX,UAAA,QAAQ,KAAK,SACZ,oBAAC,MAAD,EAAA,UACE,qBAAC,OAAD;KACE,MAAK;KACL,UAAU;KACV,eAAe,KAAK,UAAU,IAAI,CAAC,KAAK,GAAG,CAAC;KAC5C,YAAY,UAAU,MAAM,QAAQ,WAAW,KAAK,UAAU,IAAI,CAAC,KAAK,GAAG,CAAC;KAC5E,WAAU;KALZ,UAAA;MAOE,oBAAC,MAAD;OACE,MAAM,KAAK,SAAS,SAAS,eAAe;OAC5C,MAAM;OACN,WAAU;MACX,CAAA;MACD,oBAAC,QAAD;OAAM,WAAU;OACb,UAAA,KAAK,eACJ,EAAE,KAAK,SAAS,SAAS,uBAAuB,oBAAoB;MAClE,CAAA;MACN,oBAAC,QAAD;OAAM,WAAU;OACb,UAAA,EAAE,kBAAkB,EACnB,QAAQ,EAAE,MAAM,KAAK,aAAa,IAAI,OAAO,KAAK,YAAY,CAAC,IAAI,IAAI,EACzE,CAAC;MACG,CAAA;MACN,oBAAC,UAAD;OACE,MAAK;OACL,UAAU,UAAU;QAClB,MAAM,gBAAgB;QACtB,KAAU,OAAO,KAAK,GAAG;OAC3B;OACA,WAAU;OACV,OAAO,EAAE,sBAAsB;OAE/B,UAAA,oBAAC,MAAD;QAAM,MAAK;QAAQ,MAAM;OAAK,CAAA;MACxB,CAAA;KACL;IACH,CAAA,EAAA,GAlCK,cAAc,KAAK,GAAG,CAkC3B,CACL;GACC,CAAA;EAEH,CAAA,GACL,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,oBAAC,UAAD;IACE,MAAK;IACL,UAAU,QAAQ,WAAW;IAC7B,eAAe;KACb,KAAK,MAAM,QAAQ,SAAS,KAAU,OAAO,KAAK,GAAG;IACvD;IACA,WAAU;IAET,UAAA,EAAE,0BAA0B;GACvB,CAAA,GACR,oBAAC,UAAD;IACE,MAAK;IACL,UAAU,QAAQ,WAAW,KAAK,CAAC,UAAU,SAAS,KAAK;IAC3D,eAAe,QAAQ,KAAK;IAC5B,WAAU;IAET,UAAA,EAAE,0BAA0B;GACvB,CAAA,CACL;EACF,CAAA,CAAA;;AAET"}
@@ -0,0 +1,249 @@
1
+ import { n as Icon } from "./icons-BrK5iVL8.js";
2
+ import { r as buttonClass } from "./toolbar-z9od3tKl.js";
3
+ import { i as useCloseOnPick } from "./sheet-R6XDgyEf.js";
4
+ import { useEffect, useMemo, useRef, useState } from "react";
5
+ import { useSearch, useSearchHits, useSearchState, validateSearchQuery } from "@embedpdf/react/search";
6
+ import { useT } from "@embedpdf/react/i18n";
7
+ import { useSurfaceFocus } from "@embedpdf/react/shell";
8
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
+ //#region src/ui/search-panel.tsx
10
+ /**
11
+ * The search panel — the search sidebar on the plugin-search capability. One
12
+ * shape end to end: the flat `SearchQuery` {text, regex, matchCase, wholeWord}
13
+ * is what the engine matches, what the plugin stores (document-scoped,
14
+ * survives the sidebar closing), and what this box renders.
15
+ * The panel keeps only a draft of it for keystroke/debounce echo.
16
+ *
17
+ * Data flow:
18
+ * type / toggle → validateSearchQuery → (debounced) search(draftQuery)
19
+ * useSearchState() → query / status / hitCount / activeHitIndex (reactive)
20
+ * useSearchHits() → the streamed hit list
21
+ * click a hit / prev / next → goTo/prev/next (capability reveals it on-page)
22
+ *
23
+ * The look: a magnifier input with a clear button, option checkboxes, a
24
+ * results-found counter with prev/next, and a per-page grouped snippet list
25
+ * with the match bolded and the active hit accented, in this app's semantic
26
+ * tokens. matchDiacritics exists in the engine but is deliberately not
27
+ * exposed here.
28
+ */
29
+ const DEBOUNCE_MS = 300;
30
+ /** Field-wise equality on the flat query — the mount/echo no-op guard. */
31
+ const sameQuery = (left, right) => left != null && left.text === right.text && !!left.regex === !!right.regex && !!left.matchCase === !!right.matchCase && !!left.wholeWord === !!right.wholeWord;
32
+ function Checkbox({ label, checked, onChange }) {
33
+ return /* @__PURE__ */ jsxs("label", {
34
+ className: "text-fg-secondary flex cursor-pointer select-none items-center gap-2 text-xs font-medium",
35
+ children: [/* @__PURE__ */ jsxs("span", {
36
+ className: "relative flex h-4 w-4 items-center justify-center",
37
+ children: [/* @__PURE__ */ jsx("input", {
38
+ type: "checkbox",
39
+ checked,
40
+ onChange: (event) => onChange(event.target.checked),
41
+ className: "border-border bg-surface checked:border-accent checked:bg-accent rounded-xs peer h-4 w-4 shrink-0 appearance-none border transition-colors"
42
+ }), /* @__PURE__ */ jsx("svg", {
43
+ viewBox: "0 0 24 24",
44
+ className: "text-on-accent pointer-events-none absolute h-3 w-3 opacity-0 peer-checked:opacity-100",
45
+ fill: "none",
46
+ stroke: "currentColor",
47
+ strokeWidth: 3,
48
+ strokeLinecap: "round",
49
+ strokeLinejoin: "round",
50
+ children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" })
51
+ })]
52
+ }), label]
53
+ });
54
+ }
55
+ function renderSnippet(snippet) {
56
+ if (!snippet) return null;
57
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
58
+ snippet.before,
59
+ /* @__PURE__ */ jsx("span", {
60
+ className: "text-accent font-semibold",
61
+ children: snippet.match
62
+ }),
63
+ snippet.after
64
+ ] });
65
+ }
66
+ function HitLine({ hit, active, onClick }) {
67
+ const ref = useRef(null);
68
+ useEffect(() => {
69
+ if (active) ref.current?.scrollIntoView({
70
+ behavior: "smooth",
71
+ block: "nearest"
72
+ });
73
+ }, [active]);
74
+ return /* @__PURE__ */ jsx("button", {
75
+ ref,
76
+ type: "button",
77
+ onClick,
78
+ className: `w-full rounded border p-2 text-left text-sm transition-colors ${active ? "border-accent bg-accent-light text-fg" : "border-border-subtle bg-surface text-fg-secondary hover:bg-hover"}`,
79
+ children: /* @__PURE__ */ jsx("span", { children: renderSnippet(hit.snippet) })
80
+ });
81
+ }
82
+ function SearchPanel() {
83
+ const t = useT();
84
+ const search = useSearch();
85
+ const { query, status, hitCount, activeHitIndex } = useSearchState();
86
+ const hits = useSearchHits();
87
+ const closeOnPick = useCloseOnPick();
88
+ const [draft, setDraft] = useState(() => query?.text ?? "");
89
+ const [matchCase, setMatchCase] = useState(() => query?.matchCase ?? false);
90
+ const [wholeWord, setWholeWord] = useState(() => query?.wholeWord ?? false);
91
+ const [regex, setRegex] = useState(() => query?.regex ?? false);
92
+ const inputRef = useRef(null);
93
+ useSurfaceFocus("search", inputRef, { select: true });
94
+ const draftQuery = {
95
+ text: draft,
96
+ regex,
97
+ matchCase,
98
+ wholeWord
99
+ };
100
+ const validation = draft && regex ? validateSearchQuery(draftQuery) : { ok: true };
101
+ useEffect(() => {
102
+ if (!validation.ok || sameQuery(query, draftQuery)) return;
103
+ if (draft === "" && query === null) return;
104
+ const id = setTimeout(() => search.search(draftQuery), DEBOUNCE_MS);
105
+ return () => clearTimeout(id);
106
+ }, [
107
+ draft,
108
+ matchCase,
109
+ wholeWord,
110
+ regex,
111
+ query,
112
+ validation.ok,
113
+ search
114
+ ]);
115
+ const grouped = useMemo(() => {
116
+ const map = /* @__PURE__ */ new Map();
117
+ hits.forEach((hit, index) => {
118
+ const arr = map.get(hit.pageIndex);
119
+ if (arr) arr.push({
120
+ hit,
121
+ index
122
+ });
123
+ else map.set(hit.pageIndex, [{
124
+ hit,
125
+ index
126
+ }]);
127
+ });
128
+ return [...map.entries()].sort((left, right) => left[0] - right[0]);
129
+ }, [hits]);
130
+ const searching = status === "searching";
131
+ return /* @__PURE__ */ jsxs("div", {
132
+ className: "flex min-h-0 flex-1 flex-col",
133
+ children: [/* @__PURE__ */ jsxs("div", {
134
+ className: "p-3",
135
+ children: [
136
+ /* @__PURE__ */ jsxs("div", {
137
+ className: "relative",
138
+ children: [
139
+ /* @__PURE__ */ jsx("div", {
140
+ className: "text-fg-muted pointer-events-none absolute inset-y-0 start-0 flex items-center ps-2.5",
141
+ children: /* @__PURE__ */ jsx(Icon, {
142
+ name: "search",
143
+ size: 16
144
+ })
145
+ }),
146
+ /* @__PURE__ */ jsx("input", {
147
+ ref: inputRef,
148
+ type: "text",
149
+ value: draft,
150
+ placeholder: t("demo.searchPlaceholder"),
151
+ onChange: (event) => setDraft(event.target.value),
152
+ className: `bg-surface text-fg w-full rounded-md border py-1.5 pe-9 ps-8 text-sm outline-none focus:ring-1 ${validation.ok ? "border-border focus:border-accent focus:ring-accent" : "border-red-400 focus:border-red-400 focus:ring-red-400"}`
153
+ }),
154
+ draft && /* @__PURE__ */ jsx("button", {
155
+ type: "button",
156
+ onClick: () => {
157
+ setDraft("");
158
+ inputRef.current?.focus();
159
+ },
160
+ className: "text-fg-muted hover:text-fg-secondary absolute inset-y-0 end-0 flex items-center pe-2.5",
161
+ children: /* @__PURE__ */ jsx(Icon, {
162
+ name: "x",
163
+ size: 16
164
+ })
165
+ })
166
+ ]
167
+ }),
168
+ !validation.ok && /* @__PURE__ */ jsx("p", {
169
+ className: "mt-1.5 text-xs text-red-500",
170
+ children: validation.message
171
+ }),
172
+ /* @__PURE__ */ jsxs("div", {
173
+ className: "mt-3 flex flex-col gap-2",
174
+ children: [
175
+ /* @__PURE__ */ jsx(Checkbox, {
176
+ label: t("demo.searchCaseSensitive"),
177
+ checked: matchCase,
178
+ onChange: setMatchCase
179
+ }),
180
+ /* @__PURE__ */ jsx(Checkbox, {
181
+ label: t("demo.searchWholeWord"),
182
+ checked: wholeWord,
183
+ onChange: setWholeWord
184
+ }),
185
+ /* @__PURE__ */ jsx(Checkbox, {
186
+ label: t("demo.searchRegex"),
187
+ checked: regex,
188
+ onChange: setRegex
189
+ })
190
+ ]
191
+ }),
192
+ /* @__PURE__ */ jsx("hr", { className: "border-border-subtle mb-2 mt-4" }),
193
+ status !== "idle" && /* @__PURE__ */ jsxs("div", {
194
+ className: "flex h-8 items-center justify-between",
195
+ children: [/* @__PURE__ */ jsx("div", {
196
+ className: "text-fg-muted text-xs",
197
+ children: hitCount === 0 ? t(searching ? "demo.searchSearching" : "demo.searchNoResults") : t("demo.searchResults", { params: { count: hitCount } })
198
+ }), hitCount > 1 && /* @__PURE__ */ jsxs("div", {
199
+ className: "flex items-center",
200
+ children: [/* @__PURE__ */ jsx("button", {
201
+ type: "button",
202
+ title: t("demo.searchPrevious"),
203
+ className: buttonClass(false),
204
+ onClick: () => search.previousHit(),
205
+ children: /* @__PURE__ */ jsx(Icon, {
206
+ name: "chevronLeft",
207
+ size: 20,
208
+ className: "rtl:-scale-x-100"
209
+ })
210
+ }), /* @__PURE__ */ jsx("button", {
211
+ type: "button",
212
+ title: t("demo.searchNext"),
213
+ className: buttonClass(false),
214
+ onClick: () => search.nextHit(),
215
+ children: /* @__PURE__ */ jsx(Icon, {
216
+ name: "chevronRight",
217
+ size: 20,
218
+ className: "rtl:-scale-x-100"
219
+ })
220
+ })]
221
+ })]
222
+ })
223
+ ]
224
+ }), /* @__PURE__ */ jsx("div", {
225
+ className: "flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto px-3 pb-3",
226
+ children: grouped.map(([pageIndex, items]) => /* @__PURE__ */ jsxs("div", {
227
+ className: "mt-2 first:mt-0",
228
+ children: [/* @__PURE__ */ jsx("div", {
229
+ className: "bg-surface/80 text-fg-muted py-2 text-xs backdrop-blur",
230
+ children: t("demo.searchPage", { params: { page: pageIndex + 1 } })
231
+ }), /* @__PURE__ */ jsx("div", {
232
+ className: "flex flex-col gap-2",
233
+ children: items.map(({ hit, index }) => /* @__PURE__ */ jsx(HitLine, {
234
+ hit,
235
+ active: index === activeHitIndex,
236
+ onClick: () => {
237
+ search.goToHit(index);
238
+ closeOnPick();
239
+ }
240
+ }, index))
241
+ })]
242
+ }, pageIndex))
243
+ })]
244
+ });
245
+ }
246
+ //#endregion
247
+ export { SearchPanel };
248
+
249
+ //# sourceMappingURL=search-panel-HfIhJm1M.js.map