@abyss-project/commons-front-core 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/dist/{CookieConsentSettings.component-CgiQCgFX.js → CookieConsentSettings.component-CSf_M5Gx.js} +505 -443
  2. package/dist/components/Avatars/ProjectAvatar/ProjectAvatar.component.d.ts +3 -0
  3. package/dist/components/Avatars/UserAvatar/UserAvatar.component.d.ts +3 -0
  4. package/dist/components/Cards/ProjectCard/ProjectCard.component.d.ts +1 -0
  5. package/dist/components/CommandPalette/AbyssCommandPalette.d.ts +9 -0
  6. package/dist/components/CommandPalette/types.d.ts +63 -0
  7. package/dist/components/CommandPalette/useCommandPaletteHotkey.d.ts +9 -0
  8. package/dist/components/CompanySearchAutocomplete/CompanySearchAutocomplete.d.ts +25 -0
  9. package/dist/components/CompanySearchAutocomplete/CompanySearchAutocomplete.error.spec.d.ts +1 -0
  10. package/dist/components/CompanySearchAutocomplete/index.d.ts +2 -0
  11. package/dist/components/CookieConsent/AbyssCookieConsentProvider.d.ts +9 -0
  12. package/dist/components/CookieConsent/privacy-link.constant.d.ts +25 -0
  13. package/dist/components/Data/AbyssTable/AbyssTable.component.d.ts +16 -2
  14. package/dist/components/Data/AbyssTable/abyss-table.logic.d.ts +72 -0
  15. package/dist/components/Inputs/AbyssNumberField/AbyssNumberField.component.d.ts +18 -0
  16. package/dist/components/Inputs/AbyssNumberField/format.d.ts +28 -0
  17. package/dist/components/Inputs/CloudImport/CloudImport.component.d.ts +1 -0
  18. package/dist/components/Inputs/ColorPalette/ColorPalette.component.d.ts +2 -0
  19. package/dist/components/Inputs/ContextSelector/ContextSelector.component.d.ts +25 -0
  20. package/dist/components/Inputs/DatePeriodPicker/DatePeriodPicker.component.d.ts +32 -0
  21. package/dist/components/Inputs/DatePeriodPicker/date-period-picker.logic.d.ts +54 -0
  22. package/dist/components/Inputs/DatePeriodPicker/date-period-presets.util.d.ts +8 -0
  23. package/dist/components/Inputs/LanguageFlagLabel/LanguageFlagLabel.component.d.ts +13 -0
  24. package/dist/components/Inputs/LanguageFlagLabel/language-flags.d.ts +10 -0
  25. package/dist/components/Inputs/PasswordInput/PasswordInput.component.d.ts +16 -0
  26. package/dist/components/Inputs/ProjectLinkSelector/index.d.ts +1 -1
  27. package/dist/components/Layouts/AbyssBillingPlan/AbyssBillingPlan.component.d.ts +2 -0
  28. package/dist/components/Layouts/AbyssFamilyBanner/AbyssFamilyBanner.component.d.ts +12 -0
  29. package/dist/components/Layouts/AbyssLayoutProvider/index.d.ts +1 -1
  30. package/dist/components/Layouts/AbyssSidebar/index.d.ts +2 -2
  31. package/dist/components/Modals/AbyssModal/AbyssModal.component.d.ts +6 -0
  32. package/dist/components/Modals/QRCodeModal/QRCodeModal.component.d.ts +1 -0
  33. package/dist/components/Modals/UserSettingsModal/UserSettingsModal.component.d.ts +5 -0
  34. package/dist/components/Modals/UserSettingsModal/index.d.ts +1 -1
  35. package/dist/components/PdfEditor/hooks/use-pdf-document.d.ts +12 -0
  36. package/dist/components/PdfEditor/hooks/use-uploaded-docs.d.ts +9 -0
  37. package/dist/components/PdfEditor/operations/actions.d.ts +14 -0
  38. package/dist/components/PdfEditor/operations/compute-page-order.d.ts +11 -0
  39. package/dist/components/PdfEditor/operations/extract.d.ts +5 -0
  40. package/dist/components/PdfEditor/operations/pdf-data-url.d.ts +4 -0
  41. package/dist/components/PdfEditor/operations/rasterize.d.ts +17 -0
  42. package/dist/components/PdfEditor/operations/redact.d.ts +8 -0
  43. package/dist/components/PdfEditor/operations/rotate-coords.d.ts +25 -0
  44. package/dist/components/PdfEditor/signature/SignaturePicker.d.ts +3 -0
  45. package/dist/components/PdfEditor/signature/SignatureSaveButton.d.ts +3 -0
  46. package/dist/components/PdfEditor/signature/resolve-asset.d.ts +17 -0
  47. package/dist/components/PdfEditor/tools/RedactTool.d.ts +6 -0
  48. package/dist/components/PdfEditor/tools/Toolbar.d.ts +9 -0
  49. package/dist/components/PdfEditor/tools/tool-options-ui.d.ts +1 -0
  50. package/dist/components/PdfEditor/types.d.ts +85 -0
  51. package/dist/components/PdfEditor/viewer/PageOverlay.d.ts +10 -0
  52. package/dist/components/PdfEditor/viewer/PdfCanvas.d.ts +1 -0
  53. package/dist/components/PdfEditor/viewer/ViewerControls.d.ts +4 -0
  54. package/dist/components/QuotaGauge/AbyssQuotaGauge.component.d.ts +39 -0
  55. package/dist/components/QuotaGauge/bubble-placement.d.ts +40 -0
  56. package/dist/components/QuotaGauge/gauge-segments.d.ts +56 -0
  57. package/dist/components/QuotaOffer/AbyssQuotaOffer.component.d.ts +60 -0
  58. package/dist/components/QuotaOffer/quota-offer-state.d.ts +64 -0
  59. package/dist/components/QuotaReached/QuotaReachedDialog.component.d.ts +10 -0
  60. package/dist/components/QuotaReached/billing-quota-error.d.ts +7 -0
  61. package/dist/components/QuotaReached/quota-dialog.store.d.ts +10 -0
  62. package/dist/components/QuotaReached/quota-service-meta.d.ts +4 -0
  63. package/dist/components/Support/SupportCategorySelect.component.d.ts +3 -0
  64. package/dist/components/Support/SupportStatusTimeline.component.d.ts +2 -0
  65. package/dist/components/Support/index.d.ts +2 -2
  66. package/dist/components/Support/support-attachment.logic.d.ts +10 -0
  67. package/dist/components/Support/support-author.logic.d.ts +9 -0
  68. package/dist/components/Support/support-create-stepper.logic.d.ts +13 -0
  69. package/dist/components/Support/support-message-input.logic.d.ts +8 -0
  70. package/dist/components/Support/support-status-timeline.logic.d.ts +16 -0
  71. package/dist/components/Support/types.d.ts +55 -0
  72. package/dist/components/Utils/AbyssBackground/AbyssBackground.component.d.ts +3 -0
  73. package/dist/components/Utils/AbyssFamilyMenuSection/AbyssFamilyMenuSection.d.ts +9 -0
  74. package/dist/components/Utils/AbyssLayoutMenu/index.d.ts +1 -1
  75. package/dist/components/Utils/AbyssLayoutNotifications/AbyssLayoutNotifications.component.d.ts +4 -0
  76. package/dist/components/Utils/AbyssLayoutNotifications/index.d.ts +1 -1
  77. package/dist/components/Utils/ImportButton/ImportButton.component.d.ts +4 -0
  78. package/dist/components/Utils/Toast/AbyssToast.component.d.ts +6 -0
  79. package/dist/components/Utils/WaterParticles/WaterParticles.component.d.ts +8 -0
  80. package/dist/components/index.d.ts +1 -0
  81. package/dist/cookie-consent.js +1 -1
  82. package/dist/hooks/use-public-users.hook.d.ts +39 -0
  83. package/dist/hooks/use-rich-intl.hook.d.ts +27 -5
  84. package/dist/hooks/use-theme-transition.hook.d.ts +13 -0
  85. package/dist/{index-D2ot8DZ4.js → index-6vOdokCY.js} +2 -2
  86. package/dist/{index-cYFrJDdQ.js → index-AUELqW5Y.js} +4 -4
  87. package/dist/{index-DXDfaFmT.js → index-AwC_8lIT.js} +4 -4
  88. package/dist/{index-BN-71mBQ.js → index-B7EugME7.js} +2 -2
  89. package/dist/{index-0WPkkm3C.js → index-BOqcEEHH.js} +3 -3
  90. package/dist/{index-Ctm2mN4b.js → index-BSRrH_Gr.js} +2 -2
  91. package/dist/{index-DpeaEf87.js → index-BToZYvup.js} +2 -2
  92. package/dist/{index-CgqzFzYH.js → index-BlCa_Vlr.js} +2 -2
  93. package/dist/{index-FF8J68dM.js → index-BoYupKIh.js} +23908 -20833
  94. package/dist/{index-2gSMCEyX.js → index-BtiGEZHC.js} +3 -3
  95. package/dist/{index-d9VwJ6nR.js → index-C2a_Y6jF.js} +2 -2
  96. package/dist/{index-C7bGgD6e.js → index-CCphPqf4.js} +2 -2
  97. package/dist/{index-CdpydxgB.js → index-CD9GifGt.js} +2 -2
  98. package/dist/{index-BSa7pbNq.js → index-CDWityvJ.js} +3 -3
  99. package/dist/{index-CAqpnDEx.js → index-CFVsaKv5.js} +4 -4
  100. package/dist/{index-C1NWZqnA.js → index-CtSA_KxY.js} +2 -2
  101. package/dist/{index-C02uLNDS.js → index-D7WU-N9n.js} +2 -2
  102. package/dist/{index-D5IIOkfu.js → index-DUGpZohv.js} +2 -2
  103. package/dist/{index-BqjTmumL.js → index-DrHXb1cg.js} +2 -2
  104. package/dist/{index-B9n8aGer.js → index-GhkzA3Z-.js} +2 -2
  105. package/dist/{index-CXNLGqpN.js → index-RBcLmJfD.js} +1 -1
  106. package/dist/{index-DQgswKg1.js → index-iw6ikhdy.js} +3 -3
  107. package/dist/index.js +185 -184
  108. package/dist/theme/augmentation.d.ts +6 -0
  109. package/dist/theme/index.d.ts +11 -4
  110. package/dist/theme/palettes/common.d.ts +13 -0
  111. package/dist/theme/palettes/dark.d.ts +1 -0
  112. package/dist/theme/palettes/light.d.ts +1 -0
  113. package/dist/theme/tokens/animations.d.ts +3 -0
  114. package/dist/theme/tokens/borders.d.ts +3 -0
  115. package/dist/theme/tokens/colors.d.ts +27 -0
  116. package/dist/theme/tokens/shadows.d.ts +8 -0
  117. package/dist/theme/tokens/transitions.d.ts +4 -0
  118. package/dist/theme/tokens/typography.d.ts +6 -0
  119. package/dist/translations/en.d.ts +3 -0
  120. package/dist/translations/fr.d.ts +3 -0
  121. package/dist/utils/share-notification.utils.d.ts +9 -0
  122. package/dist/utils/space-display-name.utils.d.ts +8 -0
  123. package/package.json +14 -13
  124. package/tsconfig.json +26 -25
  125. package/vite.config.ts +1 -17
@@ -1,25 +1,79 @@
1
1
  import { Locale } from 'date-fns';
2
2
  export type EditingBound = 'start' | 'end';
3
+ /**
4
+ * Time granularity of the resolved range.
5
+ *
6
+ * - `day` (default): bounds snap to start-of-day (start) / end-of-day (end). The
7
+ * picker behaves as a day-only range picker — fully backward-compatible.
8
+ * - `minute`: bounds keep an explicit hour/minute and resolve to the exact
9
+ * selected instant (no start/end-of-day snapping).
10
+ */
3
11
  export type DatePeriodGranularity = 'day' | 'minute';
4
12
  export type RangeUpdateInput = {
13
+ /** Which bound the user is currently editing. */
5
14
  editing: EditingBound;
15
+ /** The day the user just picked in the calendar. */
6
16
  picked: Date;
17
+ /** Current start bound (may be null/invalid). */
7
18
  startDate: Date | null;
19
+ /** Current end bound (may be null/invalid). */
8
20
  endDate: Date | null;
21
+ /**
22
+ * Time granularity. Defaults to `day` (snap to start/end of day). In `minute`
23
+ * mode the previously entered time is preserved when only the calendar day
24
+ * changes.
25
+ */
9
26
  granularity?: DatePeriodGranularity;
10
27
  };
11
28
  export type RangeUpdateResult = {
29
+ /** New start bound, or the previous reference when unchanged. */
12
30
  start: Date | null;
31
+ /** New end bound, or the previous reference when unchanged. */
13
32
  end: Date | null;
33
+ /** Whether the start reference changed. */
14
34
  startChanged: boolean;
35
+ /** Whether the end reference changed. */
15
36
  endChanged: boolean;
16
37
  };
17
38
  export type TimeChangeInput = {
39
+ /** Which bound the user is currently editing. */
18
40
  editing: EditingBound;
41
+ /** The value emitted by the time field (carries the new hour/minute). */
19
42
  time: Date;
43
+ /** Current start bound (may be null/invalid). */
20
44
  startDate: Date | null;
45
+ /** Current end bound (may be null/invalid). */
21
46
  endDate: Date | null;
22
47
  };
48
+ /**
49
+ * Pure, independent range-bound update for a calendar day pick.
50
+ *
51
+ * Each bound is edited independently: editing the END never moves the START and
52
+ * vice-versa (fixes the "changing end also moves start" regression). The only
53
+ * coupling is a validation clamp guaranteeing `end >= start`:
54
+ * - editing `start` past `end` clamps the start down to `end` (end untouched);
55
+ * - editing `end` before `start` clamps the end up to `start` (start untouched).
56
+ *
57
+ * In `day` granularity (default) bounds are normalized to start-of-day (start) /
58
+ * end-of-day (end). In `minute` granularity the previously entered time is kept
59
+ * and only the calendar day changes; the range resolves to the exact instant.
60
+ */
23
61
  export declare const computeRangeUpdate: (input: RangeUpdateInput) => RangeUpdateResult;
62
+ /**
63
+ * Pure time-of-day update (minute granularity only).
64
+ *
65
+ * Applies the hour/minute emitted by a time field to the edited bound while
66
+ * keeping that bound's calendar day. When the edited bound has no value yet, the
67
+ * time field's own day is used as the base. The same `end >= start` clamp as
68
+ * {@link computeRangeUpdate} keeps the range valid without moving the other bound.
69
+ */
24
70
  export declare const applyTimeChange: (input: TimeChangeInput) => RangeUpdateResult;
71
+ /**
72
+ * Resolve a date-fns `Locale` from an app language code (e.g. the react-intl
73
+ * `intl.locale`). Defaults to English for unknown / missing codes.
74
+ *
75
+ * The specific locales are imported directly so they survive tree-shaking inside
76
+ * the commons bundle — the host's global `setDefaultOptions` never reaches the
77
+ * bundle's own date-fns copy, so locale must always be passed explicitly.
78
+ */
25
79
  export declare const resolveDateFnsLocale: (language?: string | null) => Locale;
@@ -2,6 +2,14 @@ export type DatePeriodPreset = {
2
2
  label: string;
3
3
  getRange: () => [Date, Date];
4
4
  };
5
+ /** Translation keys backing the default presets. Both locale files define them. */
5
6
  export declare const DEFAULT_PRESET_KEYS: readonly ["inputs.period-picker.labels.presets.7d", "inputs.period-picker.labels.presets.30d", "inputs.period-picker.labels.presets.90d", "inputs.period-picker.labels.presets.month", "inputs.period-picker.labels.presets.year"];
6
7
  export type DefaultPresetKey = (typeof DEFAULT_PRESET_KEYS)[number];
8
+ /**
9
+ * Default presets, labelled from the active translations.
10
+ *
11
+ * These labels used to be hardcoded English literals, so every screen that did
12
+ * not pass its own `presets` rendered "Month" and "Year" next to a French UI.
13
+ * The keys already existed in both locale files; only the wiring was missing.
14
+ */
7
15
  export declare const buildDefaultPresets: (translate: (id: DefaultPresetKey) => string) => DatePeriodPreset[];
@@ -1,9 +1,22 @@
1
1
  import { default as React } from 'react';
2
2
  type Props = {
3
+ /** Language/locale code (e.g. ProjectLanguage.FRENCH) used to resolve the flag. */
3
4
  code: string;
5
+ /** Human-readable, already-translated language name (e.g. "Français"). */
4
6
  label: string;
7
+ /** Font size of the language name. Defaults to MUI body2. */
5
8
  variant?: 'body1' | 'body2' | 'caption';
9
+ /** Gap between the flag and the label (MUI spacing units). */
6
10
  gap?: number;
7
11
  };
12
+ /**
13
+ * Reusable flag + language-name row. The flag is purely decorative
14
+ * (`aria-hidden`) and the readable label carries the accessible text, so screen
15
+ * readers announce the language name without the flag noise.
16
+ *
17
+ * Renders e.g. "🇫🇷 Français" instead of a bare code or "FR - France". Use it in
18
+ * any language picker (`Autocomplete` option, list item, selected value) so every
19
+ * abyss front renders language options the same way. See the README in this folder.
20
+ */
8
21
  export declare const LanguageFlagLabel: React.FC<Props>;
9
22
  export default LanguageFlagLabel;
@@ -1,2 +1,12 @@
1
+ /**
2
+ * Single source of truth that maps a language/locale code to its country flag
3
+ * emoji. Flags are stored as escaped regional-indicator code points so the file
4
+ * stays ASCII-safe and unambiguous in review.
5
+ *
6
+ * Codes match the `ProjectLanguage` enum used across the ecosystem (spotlight,
7
+ * forms, etc.) so any app can render a language option as a flag + readable name
8
+ * instead of a bare code or a "FR - France" style label.
9
+ */
1
10
  export declare const LANGUAGE_FLAGS: Record<string, string>;
11
+ /** Returns the flag emoji for a language/locale code, or '' when unknown. */
2
12
  export declare const getLanguageFlag: (language: string) => string;
@@ -11,15 +11,31 @@ type Props = {
11
11
  size?: 'small' | 'medium';
12
12
  sx?: SxProps;
13
13
  disabled?: boolean;
14
+ /**
15
+ * Password-manager hint. ALWAYS set it on real auth forms — `current-password`
16
+ * on sign-in, `new-password` on sign-up / reset / change. Without it browsers
17
+ * both fail to offer the saved credential and fail to offer to save the new
18
+ * one, which pushes people toward weaker, memorable passwords.
19
+ */
14
20
  autoComplete?: string;
21
+ /** Helper or error text shown under the field. */
15
22
  helperText?: ReactNode;
16
23
  required?: boolean;
17
24
  autoFocus?: boolean;
18
25
  id?: string;
26
+ /**
27
+ * Raw props forwarded to the underlying `input`. Use for a11y wiring
28
+ * (`aria-describedby`, `aria-invalid`) that has no dedicated prop here.
29
+ */
19
30
  inputProps?: Record<string, unknown>;
20
31
  onKeyDown?: (e: KeyboardEvent<HTMLDivElement>) => void;
21
32
  onKeyUp?: (e: KeyboardEvent<HTMLDivElement>) => void;
22
33
  onBlur?: () => void;
23
34
  };
35
+ /**
36
+ * Text field for a password, with a show/hide toggle.
37
+ *
38
+ * See README.md in this folder for the full surface and usage notes.
39
+ */
24
40
  declare const PasswordInput: FC<Props>;
25
41
  export default PasswordInput;
@@ -1,2 +1,2 @@
1
1
  export { default as ProjectLinkSelector } from './ProjectLinkSelector.component';
2
- export type { OrganizationOption, ProjectOption, ApplicationOption, LinkType } from './ProjectLinkSelector.component';
2
+ export type { OrganizationOption, ProjectOption, ApplicationOption, LinkType, } from './ProjectLinkSelector.component';
@@ -1,6 +1,8 @@
1
1
  import { default as React } from 'react';
2
2
  import { IPlanTemplate } from '@abyss-project/main';
3
3
  type Props = {
4
+ /** Omitted/null when the user has no explicit billing account → shown as the
5
+ * free plan, so the "current plan" badge never silently disappears. */
4
6
  planTemplate?: IPlanTemplate | null;
5
7
  label?: string;
6
8
  abyssUrl?: string;
@@ -12,8 +12,20 @@ type Props = {
12
12
  abyssUrl?: string;
13
13
  variant: FamilyBannerVariant;
14
14
  };
15
+ /** Pure resolver — exported for unit testing (no JSX, no hooks). */
15
16
  export declare function resolveBannerState(currentFamily: CurrentFamilyInfo | null | undefined): FamilyBannerStatus;
17
+ /**
18
+ * Pure CTA href resolver — exported for unit testing.
19
+ *
20
+ * When the user has no family (none state), returns the create-family onboarding
21
+ * URL (with `?intent=family` so the onboarding flow can pre-select the FAMILY
22
+ * user-type). When the user has a family, returns the org management URL.
23
+ */
16
24
  export declare function resolveCTAHref(currentFamily: CurrentFamilyInfo | null | undefined, abyssUrl: string | undefined): string;
25
+ /**
26
+ * Pure layout descriptor — exported for unit testing.
27
+ * Returns structural properties that differ between footer and settings variants.
28
+ */
17
29
  export declare function resolveVariantLayout(variant: FamilyBannerVariant): {
18
30
  isCompact: boolean;
19
31
  showDescription: boolean;
@@ -1,3 +1,3 @@
1
- export { AbyssLayoutProvider, useAbyssLayoutStore } from './AbyssLayoutProvider.component';
1
+ export { AbyssLayoutProvider, useAbyssLayoutStore, } from './AbyssLayoutProvider.component';
2
2
  export { createAbyssLayoutStore } from './abyss-layout.store';
3
3
  export type { AbyssLayoutState, AbyssLayoutStore } from './abyss-layout.store';
@@ -1,3 +1,3 @@
1
1
  export { default as AbyssSidebar } from './AbyssSidebar.component';
2
- export type { AbyssSidebarItem, AbyssSidebarSection } from './AbyssSidebar.component';
3
- export { ABYSS_SIDEBAR_WIDTH, ABYSS_SIDEBAR_WIDTH_COLLAPSED } from './AbyssSidebar.component';
2
+ export type { AbyssSidebarItem, AbyssSidebarSection, } from './AbyssSidebar.component';
3
+ export { ABYSS_SIDEBAR_WIDTH, ABYSS_SIDEBAR_WIDTH_COLLAPSED, } from './AbyssSidebar.component';
@@ -1,7 +1,13 @@
1
1
  import { default as React } from 'react';
2
2
  import { DialogProps, SxProps } from '@mui/material';
3
3
  type Props = {
4
+ /**
5
+ * Opt out of the built-in close button. AbyssModal owns the single close
6
+ * button for every modal — consumers must NOT render their own. Set this only
7
+ * when the modal provides its own custom close affordance.
8
+ */
4
9
  hideCloseButton?: boolean;
10
+ /** @deprecated Use `hideCloseButton` instead. Kept as an alias for back-compat. */
5
11
  disableCloseButton?: boolean;
6
12
  sxCloseButton?: SxProps;
7
13
  onClose?: () => void;
@@ -5,6 +5,7 @@ type Props = {
5
5
  url: string;
6
6
  maskShareButton?: boolean;
7
7
  maskCopyButton?: boolean;
8
+ /** Called when the reset button is clicked */
8
9
  handleResetButton?: () => Promise<void>;
9
10
  };
10
11
  declare const QRCodeModal: React.FC<Props>;
@@ -17,6 +17,11 @@ export type UserSettingsValues = {
17
17
  name: string;
18
18
  familyName: string;
19
19
  };
20
+ /**
21
+ * Exported for unit testing — no React deps.
22
+ * `overrideFamily` is the standalone `currentFamily` prop from the component;
23
+ * when provided it takes precedence, otherwise falls back to `user.currentFamily`.
24
+ */
20
25
  export declare function shouldRenderFamilyBanner(user: UserSettingsUser, overrideFamily?: UserSettingsUser['currentFamily']): boolean;
21
26
  type Props = {
22
27
  isOpen: boolean;
@@ -1,2 +1,2 @@
1
1
  export { default as UserSettingsModal } from './UserSettingsModal.component';
2
- export type { UserSettingsUser, UserSettingsValues } from './UserSettingsModal.component';
2
+ export type { UserSettingsUser, UserSettingsValues, } from './UserSettingsModal.component';
@@ -1,5 +1,6 @@
1
1
  import { PDFDocumentProxy } from 'pdfjs-dist';
2
2
  import { PdfSource } from '../types';
3
+ /** Decrypts password-protected bytes (e.g. via qpdf-WASM). */
3
4
  type Decryptor = (bytes: Uint8Array, password: string) => Promise<Uint8Array>;
4
5
  interface UsePdfDocumentResult {
5
6
  pdfDoc: PDFDocumentProxy | null;
@@ -7,10 +8,21 @@ interface UsePdfDocumentResult {
7
8
  pageCount: number;
8
9
  loading: boolean;
9
10
  error: Error | null;
11
+ /** True when the source is encrypted and a decryptor is available — the host
12
+ * should prompt for a password and call `unlock`. */
10
13
  needsPassword: boolean;
14
+ /** True while a submitted password is being verified/applied. */
11
15
  unlocking: boolean;
16
+ /** True after the last `unlock` attempt failed (wrong password). */
12
17
  unlockFailed: boolean;
18
+ /** Decrypt the source with the given password and load it on success. */
13
19
  unlock: (password: string) => void;
14
20
  }
21
+ /**
22
+ * Loads a PDF from a PdfSource and returns a PDFDocumentProxy and raw bytes.
23
+ *
24
+ * IMPORTANT: `source` must be a stable reference (useState, useMemo, or module-level constant).
25
+ * Passing an inline object literal will cause an infinite reload loop.
26
+ */
15
27
  export declare const usePdfDocument: (source: PdfSource | null, decryptor?: Decryptor) => UsePdfDocumentResult;
16
28
  export {};
@@ -1,3 +1,12 @@
1
1
  import { PDFDocumentProxy } from 'pdfjs-dist';
2
2
  import { PdfOperation } from '../types';
3
+ /**
4
+ * Loads each unique `uploadKey` referenced by PAGE_INSERT_FROM_UPLOAD ops
5
+ * into a PDFDocumentProxy. Returns a map keyed by uploadKey.
6
+ *
7
+ * Re-runs only when the set of uploadKeys changes. Keeps previously-committed
8
+ * docs alive across re-runs so that the renderer never sees a destroyed proxy
9
+ * mid-transition; old docs are released only after the new map is committed
10
+ * (or on unmount).
11
+ */
3
12
  export declare const useUploadedDocs: (operations: PdfOperation[]) => Map<string, PDFDocumentProxy>;
@@ -1,9 +1,23 @@
1
1
  import { AcroFormField, EditorAction, PdfOperation, ToolKind } from '../types';
2
+ /**
3
+ * Typed action creators for the editor reducer.
4
+ *
5
+ * Call sites read as intent (`dispatch(deleteOperation(id))`) instead of raw
6
+ * `dispatch({ type: 'DELETE_OPERATION', payload: { opId: id } })`, and the
7
+ * action shapes live in exactly one place so the reducer, the creators and the
8
+ * `EditorAction` union can never drift apart.
9
+ */
10
+ /** Append a new operation (records an undo step). */
2
11
  export declare const addOperation: (operation: PdfOperation) => EditorAction;
12
+ /** Append several operations as a single undo step. */
3
13
  export declare const addOperations: (operations: PdfOperation[]) => EditorAction;
14
+ /** Fan a text/image op out to the given pages (records a single undo step). */
4
15
  export declare const addOperationAllPages: (operation: PdfOperation, pageIndices: number[]) => EditorAction;
16
+ /** Replace an operation in place (records an undo step). */
5
17
  export declare const updateOperation: (opId: string, operation: PdfOperation) => EditorAction;
18
+ /** Replace an operation in place WITHOUT recording history (drag frames). */
6
19
  export declare const moveOperation: (opId: string, operation: PdfOperation) => EditorAction;
20
+ /** Remove an operation (records an undo step). */
7
21
  export declare const deleteOperation: (opId: string) => EditorAction;
8
22
  export declare const undo: () => EditorAction;
9
23
  export declare const redo: () => EditorAction;
@@ -4,7 +4,18 @@ export interface InsertedPageRef {
4
4
  uploadKey: string;
5
5
  uploadPageIndex: number;
6
6
  }
7
+ /**
8
+ * Maps each synthetic virtual index (>= numPages) to the uploaded page it represents.
9
+ * Allocation order: walk operations in array order; for each PAGE_INSERT_FROM_UPLOAD,
10
+ * allocate uploadPages.length consecutive synthetic indices starting at the next
11
+ * available counter (initial = numPages). The K-th allocated index corresponds to
12
+ * op.uploadPages[K].
13
+ */
7
14
  export declare function computeInsertionTable(numPages: number, operations: PdfOperation[]): Map<number, InsertedPageRef>;
15
+ /**
16
+ * Maps each synthetic virtual index that represents an inserted BLANK page to its
17
+ * size. Allocation order matches computeInsertionTable / computePageOrder.
18
+ */
8
19
  export declare function computeBlankPages(numPages: number, operations: PdfOperation[]): Map<number, {
9
20
  widthPt: number;
10
21
  heightPt: number;
@@ -1,2 +1,7 @@
1
1
  import { PdfOperation } from '../types';
2
+ /**
3
+ * Bake the current edits, then produce a NEW PDF containing only the selected
4
+ * output pages (by display index, 0-based, in the order given). Used by
5
+ * extract / split.
6
+ */
2
7
  export declare const extractPages: (sourceBytes: Uint8Array, operations: PdfOperation[], keepDisplayIndices: number[]) => Promise<Uint8Array>;
@@ -1,2 +1,6 @@
1
+ /**
2
+ * Decode a `data:application/pdf;base64,...` URL into raw bytes.
3
+ * Works in Node (via Buffer) and in the browser (via atob).
4
+ */
1
5
  export declare const dataUrlToBytes: (dataUrl: string) => Uint8Array;
2
6
  export declare const isPdfDataUrl: (key: string) => boolean;
@@ -1,3 +1,20 @@
1
1
  import { PDFDocumentProxy } from 'pdfjs-dist';
2
2
  import { PdfOperation } from '../types';
3
+ /**
4
+ * Browser-only pre-bake step for TRUE redaction.
5
+ *
6
+ * For every page carrying ANNOTATE_REDACT regions, render the original page to a
7
+ * canvas (in unrotated content space), paint opaque black boxes over the redacted
8
+ * rectangles, and replace the page with that flattened image. The page's text and
9
+ * vector content underneath is destroyed — not merely hidden — so the redacted
10
+ * data cannot be recovered with copy/paste or a PDF text extractor.
11
+ *
12
+ * Pages without redaction are copied through untouched (vector, selectable text
13
+ * preserved). The original page count and order are kept, so downstream
14
+ * annotation ops (which key off the source page index) still map correctly.
15
+ *
16
+ * Caller must strip the ANNOTATE_REDACT ops before the main bake — they are
17
+ * already baked into the raster here. Returns the source bytes unchanged when
18
+ * there is nothing to redact.
19
+ */
3
20
  export declare const rasterizeRedactedPages: (sourceBytes: Uint8Array, pdfProxy: PDFDocumentProxy, operations: PdfOperation[]) => Promise<Uint8Array>;
@@ -1,9 +1,17 @@
1
1
  import { PdfOperation } from '../types';
2
+ /** A single rectangle to black out, in PDF points (top-left origin, content space). */
2
3
  export interface RedactRect {
3
4
  x: number;
4
5
  y: number;
5
6
  widthPt: number;
6
7
  heightPt: number;
7
8
  }
9
+ /** True when at least one redaction op is present (cheap export-time check). */
8
10
  export declare const hasRedactions: (operations: PdfOperation[]) => boolean;
11
+ /**
12
+ * Group every redaction region by its (virtual) source page index. Pages absent
13
+ * from the returned map carry no redaction and must NOT be rasterized — keeping
14
+ * them vector preserves quality and selectable text everywhere except the pages
15
+ * the user explicitly redacted.
16
+ */
9
17
  export declare const collectRedactions: (operations: PdfOperation[]) => Map<number, RedactRect[]>;
@@ -1,19 +1,44 @@
1
+ /**
2
+ * Pure geometry helpers for mapping points between a page's UNROTATED content
3
+ * space (top-left origin, y-down, PDF points) and the ROTATED view space the
4
+ * user actually sees and clicks on.
5
+ *
6
+ * The bake (`apply.ts`) always draws annotations in content space and then sets
7
+ * the page rotation, so the page content + annotations rotate together. To keep
8
+ * the on-screen preview identical to the baked output, the editor stores every
9
+ * annotation in content space and uses these helpers to (a) convert pointer
10
+ * input from view space back to content space on creation/drag, and (b) place
11
+ * the (content-space) annotations inside a single inner layer that is rotated as
12
+ * a whole to match the page (`innerLayerTransform`).
13
+ *
14
+ * All rotations are CLOCKWISE and assumed to be multiples of 90.
15
+ */
1
16
  export type Rotation = 0 | 90 | 180 | 270;
17
+ /** Clamp any (possibly negative, possibly >360) multiple of 90 into 0/90/180/270. */
2
18
  export declare const normalizeRotation: (deg: number) => Rotation;
19
+ /** Rendered (view) size of a content box once rotated. 90/270 swap w/h. */
3
20
  export declare const viewSize: (cw: number, ch: number, rotation: Rotation) => {
4
21
  w: number;
5
22
  h: number;
6
23
  };
24
+ /** Content size from a rendered (view) size. Inverse of {@link viewSize}. */
7
25
  export declare const contentSize: (vw: number, vh: number, rotation: Rotation) => {
8
26
  w: number;
9
27
  h: number;
10
28
  };
29
+ /** Map a point from unrotated content space to rotated view space (clockwise). */
11
30
  export declare const contentToView: (x: number, y: number, rotation: Rotation, cw: number, ch: number) => {
12
31
  x: number;
13
32
  y: number;
14
33
  };
34
+ /** Map a point from rotated view space back to content space. Inverse of {@link contentToView}. */
15
35
  export declare const viewToContent: (x: number, y: number, rotation: Rotation, cw: number, ch: number) => {
16
36
  x: number;
17
37
  y: number;
18
38
  };
39
+ /**
40
+ * CSS `transform` for an inner layer sized to the content box (CW x CH pixels,
41
+ * already scaled) so that, after a clockwise rotation about its top-left corner,
42
+ * it lands exactly over the rotated page canvas in the positive quadrant.
43
+ */
19
44
  export declare const innerLayerTransform: (rotation: Rotation, contentWidthPx: number, contentHeightPx: number) => string;
@@ -5,11 +5,14 @@ interface SignaturePickerProps {
5
5
  open: boolean;
6
6
  onClose: () => void;
7
7
  onCapture: (dataUrl: string) => void;
8
+ /** Called when the user picks a TEXT_BLOCK asset — receives raw text so the
9
+ * host can switch to text-placement mode rather than image insertion. */
8
10
  onCaptureText?: (text: string) => void;
9
11
  assetPalette?: AssetPalette;
10
12
  onSaveSignature?: SaveSignatureFn;
11
13
  resolveAssetBytes?: ResolveAssetBytes;
12
14
  onAssetError?: (message: string) => void;
15
+ /** Optional URL to the host's "manage assets" page (Account → Assets). */
13
16
  manageAssetsUrl?: string;
14
17
  }
15
18
  export declare const SignaturePicker: React.FC<SignaturePickerProps>;
@@ -3,6 +3,9 @@ import { AssetPalette, SaveSignatureFn } from '../types';
3
3
  interface SignatureSaveButtonProps {
4
4
  dataUrl: string | null;
5
5
  onSave: SaveSignatureFn;
6
+ /** When provided and it contains at least one org bucket, a scope picker
7
+ * appears in the save dialog so the user can target a personal OR an
8
+ * organization asset. */
6
9
  assetPalette?: AssetPalette;
7
10
  }
8
11
  export declare const SignatureSaveButton: React.FC<SignatureSaveButtonProps>;
@@ -1,3 +1,20 @@
1
1
  import { AssetPaletteItem } from '../types';
2
+ /**
3
+ * Host-provided resolver that returns a usable data URL for a server-stored
4
+ * asset. Authenticated hosts implement this via a presigned download so it works
5
+ * cross-origin (a bare `fetch` of the storage public-access URL is CORS-blocked
6
+ * even though an `<img>` of the same URL renders fine).
7
+ */
2
8
  export type ResolveAssetBytes = (item: AssetPaletteItem) => Promise<string>;
9
+ /**
10
+ * Resolve an asset palette item to a data URL ready to embed.
11
+ *
12
+ * - Prefers the host `resolver` (authenticated, cross-origin safe).
13
+ * - Falls back to a direct `fetch` of `downloadUrl` — correct for same-origin or
14
+ * `data:` URLs (e.g. anonymous local signatures), which is why anonymous mode
15
+ * works without a resolver.
16
+ *
17
+ * Throws on failure so callers can surface a visible error instead of silently
18
+ * doing nothing.
19
+ */
3
20
  export declare const resolveAssetDataUrl: (item: AssetPaletteItem, resolver?: ResolveAssetBytes) => Promise<string>;
@@ -1,2 +1,8 @@
1
1
  import { default as React } from 'react';
2
+ /**
3
+ * Redaction is destructive: on export the affected pages are flattened to an
4
+ * image with opaque black boxes, so the underlying text/content is gone for
5
+ * good. The popover makes that consequence explicit before the user draws —
6
+ * there is no styling to configure, only the warning + how-to.
7
+ */
2
8
  export declare const RedactTool: React.FC;
@@ -16,6 +16,7 @@ interface ToolbarProps {
16
16
  resolveAssetBytes?: ResolveAssetBytes;
17
17
  onAssetError?: (message: string) => void;
18
18
  pendingApplyAllPages?: boolean;
19
+ /** Compact (narrow viewport): drop labels/filename so the bar never overflows. */
19
20
  compact?: boolean;
20
21
  sidebarOpen?: boolean;
21
22
  onToggleSidebar?: () => void;
@@ -23,12 +24,20 @@ interface ToolbarProps {
23
24
  onAddPageNumbers?: () => void;
24
25
  onWatermark?: () => void;
25
26
  onInsertImage?: () => void;
27
+ /** Insert an image picked from AbyssCloud (host-wired). */
26
28
  onInsertCloudImage?: () => void;
27
29
  onExtractPages?: () => void;
30
+ /** Host-provided (qpdf-WASM) actions — shown only when wired. */
28
31
  onProtect?: () => void;
29
32
  onCompress?: () => void;
33
+ /** True while a password/compress operation runs (disables those items). */
30
34
  securing?: boolean;
35
+ /** Options panel for the active tool (null when the tool has none). Rendered
36
+ * in a popover anchored to the active tool button (bottom sheet on mobile). */
31
37
  toolOptions?: React.ReactNode;
38
+ /** True while a signature/image/text is armed for placement. The anchored
39
+ * options popover is suppressed so it never covers the page the user must
40
+ * click to drop it (a non-blocking placement banner takes over instead). */
32
41
  placementActive?: boolean;
33
42
  }
34
43
  export declare const Toolbar: React.FC<ToolbarProps>;
@@ -1,4 +1,5 @@
1
1
  import { default as React } from 'react';
2
+ /** Section label inside a tool-options popover (consistent across every tool). */
2
3
  export declare const OptionLabel: React.FC<{
3
4
  children: React.ReactNode;
4
5
  }>;