@abyss-project/commons-front-core 2.6.2 → 3.0.1
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.
- package/dist/{CookieConsentSettings.component-BUxrkECh.js → CookieConsentSettings.component-BLgzLD-Z.js} +687 -591
- package/dist/components/Avatars/ProjectAvatar/ProjectAvatar.component.d.ts +3 -0
- package/dist/components/Avatars/UserAvatar/UserAvatar.component.d.ts +3 -0
- package/dist/components/Cards/ProjectCard/ProjectCard.component.d.ts +1 -0
- package/dist/components/CommandPalette/AbyssCommandPalette.d.ts +9 -0
- package/dist/components/CommandPalette/types.d.ts +63 -0
- package/dist/components/CommandPalette/useCommandPaletteHotkey.d.ts +9 -0
- package/dist/components/CookieConsent/AbyssCookieConsentProvider.d.ts +9 -1
- package/dist/components/CookieConsent/CookieConsentBanner.component.d.ts +0 -1
- package/dist/components/CookieConsent/privacy-link.constant.d.ts +25 -0
- package/dist/components/Data/AbyssTable/AbyssTable.component.d.ts +16 -2
- package/dist/components/Data/AbyssTable/abyss-table.logic.d.ts +72 -0
- package/dist/components/Inputs/AbyssNumberField/AbyssNumberField.component.d.ts +18 -0
- package/dist/components/Inputs/AbyssNumberField/format.d.ts +28 -0
- package/dist/components/Inputs/CloudImport/CloudImport.component.d.ts +1 -0
- package/dist/components/Inputs/ColorPalette/ColorPalette.component.d.ts +2 -0
- package/dist/components/Inputs/ContextSelector/ContextSelector.component.d.ts +25 -0
- package/dist/components/Inputs/DatePeriodPicker/DatePeriodPicker.component.d.ts +32 -0
- package/dist/components/Inputs/DatePeriodPicker/date-period-picker.logic.d.ts +54 -0
- package/dist/components/Inputs/DatePeriodPicker/date-period-presets.util.d.ts +8 -0
- package/dist/components/Inputs/LanguageFlagLabel/LanguageFlagLabel.component.d.ts +13 -0
- package/dist/components/Inputs/LanguageFlagLabel/language-flags.d.ts +10 -0
- package/dist/components/Inputs/PasswordInput/PasswordInput.component.d.ts +16 -0
- package/dist/components/Inputs/ProjectLinkSelector/index.d.ts +1 -1
- package/dist/components/Layouts/AbyssBillingPlan/AbyssBillingPlan.component.d.ts +2 -0
- package/dist/components/Layouts/AbyssFamilyBanner/AbyssFamilyBanner.component.d.ts +12 -0
- package/dist/components/Layouts/AbyssLayoutProvider/index.d.ts +1 -1
- package/dist/components/Layouts/AbyssSidebar/index.d.ts +2 -2
- package/dist/components/Modals/AbyssModal/AbyssModal.component.d.ts +6 -0
- package/dist/components/Modals/QRCodeModal/QRCodeModal.component.d.ts +1 -0
- package/dist/components/Modals/UserSettingsModal/UserSettingsModal.component.d.ts +5 -0
- package/dist/components/Modals/UserSettingsModal/index.d.ts +1 -1
- package/dist/components/PdfEditor/hooks/use-pdf-document.d.ts +12 -0
- package/dist/components/PdfEditor/hooks/use-uploaded-docs.d.ts +9 -0
- package/dist/components/PdfEditor/operations/actions.d.ts +14 -0
- package/dist/components/PdfEditor/operations/compute-page-order.d.ts +11 -0
- package/dist/components/PdfEditor/operations/extract.d.ts +5 -0
- package/dist/components/PdfEditor/operations/pdf-data-url.d.ts +4 -0
- package/dist/components/PdfEditor/operations/rasterize.d.ts +17 -0
- package/dist/components/PdfEditor/operations/redact.d.ts +8 -0
- package/dist/components/PdfEditor/operations/rotate-coords.d.ts +25 -0
- package/dist/components/PdfEditor/signature/SignaturePicker.d.ts +3 -0
- package/dist/components/PdfEditor/signature/SignatureSaveButton.d.ts +3 -0
- package/dist/components/PdfEditor/signature/resolve-asset.d.ts +17 -0
- package/dist/components/PdfEditor/tools/RedactTool.d.ts +6 -0
- package/dist/components/PdfEditor/tools/Toolbar.d.ts +9 -0
- package/dist/components/PdfEditor/tools/tool-options-ui.d.ts +1 -0
- package/dist/components/PdfEditor/types.d.ts +85 -0
- package/dist/components/PdfEditor/viewer/PageOverlay.d.ts +10 -0
- package/dist/components/PdfEditor/viewer/PdfCanvas.d.ts +1 -0
- package/dist/components/PdfEditor/viewer/ViewerControls.d.ts +4 -0
- package/dist/components/QuotaGauge/AbyssQuotaGauge.component.d.ts +39 -0
- package/dist/components/QuotaGauge/bubble-placement.d.ts +40 -0
- package/dist/components/QuotaGauge/gauge-segments.d.ts +56 -0
- package/dist/components/QuotaOffer/AbyssQuotaOffer.component.d.ts +60 -0
- package/dist/components/QuotaOffer/quota-offer-state.d.ts +64 -0
- package/dist/components/QuotaReached/QuotaReachedDialog.component.d.ts +10 -0
- package/dist/components/QuotaReached/billing-quota-error.d.ts +7 -0
- package/dist/components/QuotaReached/quota-dialog.store.d.ts +10 -0
- package/dist/components/QuotaReached/quota-service-meta.d.ts +4 -0
- package/dist/components/Support/SupportCategorySelect.component.d.ts +3 -0
- package/dist/components/Support/SupportStatusTimeline.component.d.ts +2 -0
- package/dist/components/Support/index.d.ts +2 -2
- package/dist/components/Support/support-attachment.logic.d.ts +10 -0
- package/dist/components/Support/support-author.logic.d.ts +9 -0
- package/dist/components/Support/support-create-stepper.logic.d.ts +13 -0
- package/dist/components/Support/support-message-input.logic.d.ts +8 -0
- package/dist/components/Support/support-status-timeline.logic.d.ts +16 -0
- package/dist/components/Support/types.d.ts +55 -0
- package/dist/components/Utils/AbyssBackground/AbyssBackground.component.d.ts +3 -0
- package/dist/components/Utils/AbyssFamilyMenuSection/AbyssFamilyMenuSection.d.ts +9 -0
- package/dist/components/Utils/AbyssLayoutMenu/index.d.ts +1 -1
- package/dist/components/Utils/AbyssLayoutNotifications/AbyssLayoutNotifications.component.d.ts +4 -0
- package/dist/components/Utils/AbyssLayoutNotifications/index.d.ts +1 -1
- package/dist/components/Utils/ImportButton/ImportButton.component.d.ts +4 -0
- package/dist/components/Utils/Toast/AbyssToast.component.d.ts +6 -0
- package/dist/components/Utils/WaterParticles/WaterParticles.component.d.ts +8 -0
- package/dist/cookie-consent.js +1 -1
- package/dist/hooks/use-public-users.hook.d.ts +39 -0
- package/dist/hooks/use-rich-intl.hook.d.ts +13 -5
- package/dist/hooks/use-theme-transition.hook.d.ts +13 -0
- package/dist/{index-D_eg_k-b.js → index-13QCr6ei.js} +1 -1
- package/dist/{index-uIeKLdVL.js → index-B4s0xpO9.js} +3 -3
- package/dist/{index-3FLJ3SfU.js → index-BBH7n9Up.js} +4 -4
- package/dist/{index-C_WLdmTl.js → index-BI7XXRdP.js} +3 -3
- package/dist/{index-7xq1GVwh.js → index-BbuvDSp0.js} +2 -2
- package/dist/{index-XwxG8_UP.js → index-Bhok95RO.js} +2 -2
- package/dist/{index-DtSoIucr.js → index-BjbDo-BN.js} +14320 -11454
- package/dist/{index-BUU_BiL1.js → index-C2iksP8T.js} +2 -2
- package/dist/{index-BLCWSuQw.js → index-CKXa4BvM.js} +2 -2
- package/dist/{index-CIrG9_dY.js → index-Ci9slz4U.js} +2 -2
- package/dist/{index-C5qcmmpX.js → index-CoGr-vvT.js} +3 -3
- package/dist/{index-DcCIQbuV.js → index-Cw4n4Q97.js} +2 -2
- package/dist/{index-CtAqjScO.js → index-DKSA-U8A.js} +2 -2
- package/dist/{index-DHL1-xk6.js → index-DQ6hF6bv.js} +4 -4
- package/dist/{index-Da9DTuJn.js → index-DVDFaXUS.js} +2 -2
- package/dist/{index-DjyLPGQg.js → index-Dfs8HrMj.js} +2 -2
- package/dist/{index-BErplPpW.js → index-Dn5fa9DE.js} +3 -3
- package/dist/{index-Br1U0l5K.js → index-DqW8ipJ0.js} +2 -2
- package/dist/{index-DSaH4UP5.js → index-Dt86SHUY.js} +2 -2
- package/dist/{index-erzdx1Az.js → index-DucVTPTi.js} +2 -2
- package/dist/{index-BcogVLzo.js → index-TJMhsU_S.js} +2 -2
- package/dist/{index-CXjoTXWO.js → index-x_CknZJ4.js} +4 -4
- package/dist/index.js +2 -2
- package/dist/theme/augmentation.d.ts +6 -0
- package/dist/theme/index.d.ts +11 -4
- package/dist/theme/palettes/common.d.ts +13 -0
- package/dist/theme/palettes/dark.d.ts +1 -0
- package/dist/theme/palettes/light.d.ts +1 -0
- package/dist/theme/tokens/animations.d.ts +3 -0
- package/dist/theme/tokens/borders.d.ts +3 -0
- package/dist/theme/tokens/colors.d.ts +27 -0
- package/dist/theme/tokens/shadows.d.ts +8 -0
- package/dist/theme/tokens/transitions.d.ts +4 -0
- package/dist/theme/tokens/typography.d.ts +6 -0
- package/dist/utils/share-notification.utils.d.ts +9 -0
- package/dist/utils/space-display-name.utils.d.ts +8 -0
- package/package.json +14 -13
- package/tsconfig.json +26 -25
- package/vite.config.ts +1 -17
|
@@ -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;
|
|
@@ -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>;
|
|
@@ -2,7 +2,13 @@ import { ReactNode } from 'react';
|
|
|
2
2
|
import { AssetKind } from '@abyss-project/main';
|
|
3
3
|
import { ISpace, IFile } from '@abyss-project/cloud';
|
|
4
4
|
import { SupportCloudImportProps } from '../Support/types';
|
|
5
|
+
/**
|
|
6
|
+
* Wiring for cloud-backed insertions inside the editor (currently only the
|
|
7
|
+
* "Insert pages" button). Includes the standard cloud picker props plus a
|
|
8
|
+
* helper to materialize bytes from the picked file.
|
|
9
|
+
*/
|
|
5
10
|
export interface PdfEditorCloudImportProps extends SupportCloudImportProps {
|
|
11
|
+
/** Resolve the raw bytes for a picked cloud file (e.g. via presigned URL). */
|
|
6
12
|
downloadCloudFile: (cloud: ISpace, file: IFile) => Promise<ArrayBuffer>;
|
|
7
13
|
}
|
|
8
14
|
export declare enum PdfOperationType {
|
|
@@ -38,8 +44,11 @@ export type PdfOperation = {
|
|
|
38
44
|
text: string;
|
|
39
45
|
fontSize: number;
|
|
40
46
|
color: string;
|
|
47
|
+
/** Font family; default 'sans' (Helvetica). */
|
|
41
48
|
fontFamily?: TextFontFamily;
|
|
49
|
+
/** 0..1; default 1. Used by watermarks. */
|
|
42
50
|
opacity?: number;
|
|
51
|
+
/** Counter-clockwise degrees around the text anchor; default 0 (watermark). */
|
|
43
52
|
rotationDeg?: number;
|
|
44
53
|
} | {
|
|
45
54
|
opId: string;
|
|
@@ -68,6 +77,7 @@ export type PdfOperation = {
|
|
|
68
77
|
y2: number;
|
|
69
78
|
color: string;
|
|
70
79
|
strokeWidth: number;
|
|
80
|
+
/** Fill color for rect/ellipse (hex). null = no fill (outline only). */
|
|
71
81
|
fill?: string | null;
|
|
72
82
|
} | {
|
|
73
83
|
opId: string;
|
|
@@ -120,6 +130,21 @@ export type PdfOperation = {
|
|
|
120
130
|
opId: string;
|
|
121
131
|
type: PdfOperationType.FLATTEN;
|
|
122
132
|
};
|
|
133
|
+
/**
|
|
134
|
+
* One variant of the operation union, addressed by its discriminant.
|
|
135
|
+
*
|
|
136
|
+
* `PdfOperation` is an anonymous union, so a value annotated with it is the WHOLE union: a
|
|
137
|
+
* spread like `{ ...op, x }` then fails, because most members carry no `x`. Callers that
|
|
138
|
+
* genuinely hold one variant (a test builder, a tool that only emits text) say so with this
|
|
139
|
+
* helper instead of widening and casting back.
|
|
140
|
+
*/
|
|
141
|
+
export type PdfOperationOf<T extends PdfOperationType> = Extract<PdfOperation, {
|
|
142
|
+
type: T;
|
|
143
|
+
}>;
|
|
144
|
+
/** The subset of operations that carry per-page coordinates. */
|
|
145
|
+
export type PdfPageScopedOperation = Extract<PdfOperation, {
|
|
146
|
+
pageIndex: number;
|
|
147
|
+
}>;
|
|
123
148
|
export type ExportOption = 'DOWNLOAD' | 'CLOUD_NEW_FILE' | 'CLOUD_REPLACE';
|
|
124
149
|
export type ExportRequest = {
|
|
125
150
|
kind: 'DOWNLOAD';
|
|
@@ -219,14 +244,21 @@ export interface AssetPaletteItem {
|
|
|
219
244
|
id: string;
|
|
220
245
|
kind: AssetKind;
|
|
221
246
|
name: string;
|
|
247
|
+
/** Full-resolution download URL for image-mode assets; null for text-mode
|
|
248
|
+
* (TEXT_BLOCK or typed INITIALS). Used when placing the asset on the PDF. */
|
|
222
249
|
downloadUrl: string | null;
|
|
250
|
+
/** Small (256x256) thumbnail URL — preferred for grid previews so the
|
|
251
|
+
* picker stays light. Falls back to downloadUrl when null. */
|
|
223
252
|
thumbnailUrl?: string | null;
|
|
253
|
+
/** Raw text payload — set for TEXT_BLOCK and typed-mode INITIALS. */
|
|
224
254
|
textContent?: string | null;
|
|
225
255
|
}
|
|
226
256
|
export interface AssetPaletteOrgBucket {
|
|
227
257
|
id: string;
|
|
228
258
|
name: string;
|
|
229
259
|
items: AssetPaletteItem[];
|
|
260
|
+
/** Optional pre-rendered avatar node (host-injected, e.g. OrganizationAvatar)
|
|
261
|
+
* used by the scope selector inside the picker. */
|
|
230
262
|
avatar?: ReactNode;
|
|
231
263
|
}
|
|
232
264
|
export interface AssetPaletteProjectBucket {
|
|
@@ -237,11 +269,23 @@ export interface AssetPaletteProjectBucket {
|
|
|
237
269
|
avatar?: ReactNode;
|
|
238
270
|
}
|
|
239
271
|
export interface AssetPalette {
|
|
272
|
+
/** Personal assets (the current user's). */
|
|
240
273
|
personal: AssetPaletteItem[];
|
|
274
|
+
/** Optional pre-rendered avatar for the personal bucket — used by the
|
|
275
|
+
* picker's scope selector to keep visuals consistent with the host app. */
|
|
241
276
|
personalAvatar?: ReactNode;
|
|
277
|
+
/** Optional org-scoped assets, one bucket per organization the user is a
|
|
278
|
+
* member of. */
|
|
242
279
|
organizations?: AssetPaletteOrgBucket[];
|
|
280
|
+
/** Optional project-scoped assets, one bucket per project the user has
|
|
281
|
+
* access to. */
|
|
243
282
|
projects?: AssetPaletteProjectBucket[];
|
|
244
283
|
}
|
|
284
|
+
/** Called when the user clicks "Save signature" in the picker.
|
|
285
|
+
* The implementation uploads the dataUrl as a SIGNATURE/INITIALS/STAMP asset.
|
|
286
|
+
* - `projectId` set → PROJECT scope (organizationId required too).
|
|
287
|
+
* - `organizationId` set (no projectId) → ORG scope.
|
|
288
|
+
* - neither set → personal (USER) scope. */
|
|
245
289
|
export type SaveSignatureFn = (params: {
|
|
246
290
|
dataUrl: string;
|
|
247
291
|
kind: AssetKind;
|
|
@@ -249,29 +293,70 @@ export type SaveSignatureFn = (params: {
|
|
|
249
293
|
organizationId?: string | null;
|
|
250
294
|
projectId?: string | null;
|
|
251
295
|
}) => Promise<void>;
|
|
296
|
+
/**
|
|
297
|
+
* Optional callback invoked debounced (800ms) after operations change,
|
|
298
|
+
* carrying the FULL list of current operations since the last successful flush.
|
|
299
|
+
* Hosts wiring a custom persistence backend should dedupe by op.opId
|
|
300
|
+
* (idempotent). Leave undefined for pure client-side editing.
|
|
301
|
+
*/
|
|
252
302
|
export type OperationsAdapter = (params: {
|
|
253
303
|
operations: PdfOperation[];
|
|
254
304
|
}) => Promise<void>;
|
|
305
|
+
/**
|
|
306
|
+
* Optional host-provided PDF post-processors. pdf-lib cannot write/strip
|
|
307
|
+
* encryption nor truly recompress, so these heavy operations are delegated to
|
|
308
|
+
* the host (which wires a WASM engine like qpdf). Keeping the engine in the host
|
|
309
|
+
* means the multi-MB WASM never bloats the shared bundle: only apps that opt in
|
|
310
|
+
* pay for it, and it loads lazily when the user actually runs the action. The
|
|
311
|
+
* editor surfaces each action only when its callback is provided.
|
|
312
|
+
*/
|
|
255
313
|
export interface PdfSecurity {
|
|
314
|
+
/** Encrypt the baked PDF with a user password; resolves to encrypted bytes. */
|
|
256
315
|
setPassword?: (bytes: Uint8Array, password: string) => Promise<Uint8Array>;
|
|
316
|
+
/** Decrypt a password-protected PDF; resolves to plain bytes. */
|
|
257
317
|
removePassword?: (bytes: Uint8Array, password: string) => Promise<Uint8Array>;
|
|
318
|
+
/** Recompress / optimize the baked PDF; resolves to the smaller bytes. */
|
|
258
319
|
compress?: (bytes: Uint8Array) => Promise<Uint8Array>;
|
|
259
320
|
}
|
|
260
321
|
export interface PdfEditorProps {
|
|
261
322
|
source: PdfSource;
|
|
262
323
|
mode: PdfEditorMode;
|
|
324
|
+
/** Initial server-loaded operations (replayed on mount). */
|
|
263
325
|
initialOperations?: PdfOperation[];
|
|
326
|
+
/** Persist new operations server-side (debounced 800ms). */
|
|
264
327
|
operationsAdapter?: OperationsAdapter;
|
|
328
|
+
/** Authenticated-mode asset palette — enables Saved tab and Save button in SignaturePicker.
|
|
329
|
+
* When omitted, the editor runs in anonymous mode (2-tab picker, no save action). */
|
|
265
330
|
assetPalette?: AssetPalette;
|
|
331
|
+
/** Resolve a saved (server-stored) asset to a data URL ready to embed.
|
|
332
|
+
* Authenticated hosts implement this via a presigned download so it works
|
|
333
|
+
* cross-origin — a bare fetch of the storage public-access URL is CORS-blocked
|
|
334
|
+
* even though an <img> of the same URL renders. When omitted, the editor falls
|
|
335
|
+
* back to fetching `item.downloadUrl` (correct for anonymous local `data:` URLs). */
|
|
266
336
|
resolveAssetBytes?: (item: AssetPaletteItem) => Promise<string>;
|
|
337
|
+
/** Surface a user-facing error (e.g. a toast) — used when an asset fails to
|
|
338
|
+
* resolve so the failure is visible instead of silently doing nothing. */
|
|
267
339
|
onAssetError?: (message: string) => void;
|
|
340
|
+
/** Callback to upload a new signature asset. Wire alongside assetPalette in authenticated mode. */
|
|
268
341
|
onSaveSignature?: SaveSignatureFn;
|
|
269
342
|
onExport: (request: ExportRequest) => Promise<void>;
|
|
270
343
|
exportOptions: ExportOption[];
|
|
271
344
|
readOnly?: boolean;
|
|
345
|
+
/** Optional: full cloud-import wiring. When provided, the page sidebar's
|
|
346
|
+
* "Insert pages" button uses `ImportButton` (file + cloud picker). */
|
|
272
347
|
cloudImport?: PdfEditorCloudImportProps;
|
|
348
|
+
/** Optional: deep-link to the host's asset management page (Account →
|
|
349
|
+
* Assets). When set, the signature picker shows a "Manage" button. */
|
|
273
350
|
manageAssetsUrl?: string;
|
|
351
|
+
/** Optional: when provided, the toolbar shows a "Change file" button that
|
|
352
|
+
* invokes this callback. Hosts typically reset their PdfSource state so
|
|
353
|
+
* the dropzone reappears. */
|
|
274
354
|
onChangeSource?: () => void;
|
|
355
|
+
/** Optional: host-provided encryption/compression engine (e.g. qpdf-WASM).
|
|
356
|
+
* Each provided callback adds its matching action to the document menu. */
|
|
275
357
|
pdfSecurity?: PdfSecurity;
|
|
358
|
+
/** Optional: let the user pick an image from AbyssCloud to insert. Resolves to
|
|
359
|
+
* a `data:` URL ready to place, or null if cancelled. When provided, the
|
|
360
|
+
* Insert panel shows an "AbyssCloud" image source. */
|
|
276
361
|
pickCloudImage?: () => Promise<string | null>;
|
|
277
362
|
}
|