@pitcher/js-api 1.30.0 → 1.31.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 (113) hide show
  1. package/js-api.esm.js +80 -17
  2. package/js-api.esm.js.map +1 -1
  3. package/js-api.umd.min.js +15 -15
  4. package/js-api.umd.min.js.map +1 -1
  5. package/lib/apps/browser/components/ContextMenu/TranslateFileButton.test.d.ts +1 -0
  6. package/lib/apps/browser/stores/api.filesFoldersDeleter.test.d.ts +1 -0
  7. package/lib/apps/canvas-builder/components/container/PopupApps/PopupAppModal.spec.d.ts +1 -0
  8. package/lib/apps/canvas-builder/components/container/PresentationTools/PresentationToolsButtons.spec.d.ts +1 -0
  9. package/lib/apps/canvas-builder/components/ui/BottomSheetModal/BottomSheetModal.integration.spec.d.ts +1 -0
  10. package/lib/apps/canvas-builder/components/ui/BottomSheetModal/BottomSheetModal.spec.d.ts +1 -0
  11. package/lib/apps/canvas-builder/components/ui/DynamicContent/section-component-bindings.util.d.ts +32 -0
  12. package/lib/apps/canvas-builder/components/ui/DynamicContent/useDynamicContent.d.ts +4 -0
  13. package/lib/apps/canvas-builder/components/ui/Link/Link.util.d.ts +8 -1
  14. package/lib/apps/canvas-builder/components/ui/Link/Link.util.test.d.ts +1 -0
  15. package/lib/apps/canvas-builder/components/ui/SectionList/SectionItemModal.spec.d.ts +1 -0
  16. package/lib/apps/canvas-builder/composables/useCanvas.d.ts +83 -9
  17. package/lib/apps/canvas-builder/composables/useCanvasBlocks.d.ts +4 -2
  18. package/lib/apps/canvas-builder/composables/useCanvasHistory.d.ts +2 -2
  19. package/lib/apps/canvas-builder/composables/useCanvasTheme.d.ts +2 -2
  20. package/lib/apps/canvas-builder/composables/useNavigatorDrawer.d.ts +25 -0
  21. package/lib/apps/canvas-builder/composables/useNavigatorDrawer.spec.d.ts +1 -0
  22. package/lib/apps/canvas-builder/composables/usePopupApps.d.ts +41 -4
  23. package/lib/apps/canvas-builder/composables/usePopupApps.spec.d.ts +1 -0
  24. package/lib/apps/canvas-builder/composables/usePresentationTools.d.ts +112 -0
  25. package/lib/apps/canvas-builder/composables/usePresentationTools.spec.d.ts +1 -0
  26. package/lib/apps/canvas-builder/types/canvas.d.ts +13 -0
  27. package/lib/apps/canvas-builder/util/canvas.util.d.ts +12 -0
  28. package/lib/apps/canvas-builder/util/completionWizard.util.d.ts +251 -11
  29. package/lib/apps/canvas-builder/util/iframe.util.d.ts +24 -2
  30. package/lib/apps/canvas-builder/util/iframe.util.test.d.ts +1 -0
  31. package/lib/apps/canvas-selector/stores/app.d.ts +14 -0
  32. package/lib/apps/collection-player/components/AppHeader.spec.d.ts +1 -0
  33. package/lib/apps/collection-player/composables/speaker-notes.use.d.ts +14 -0
  34. package/lib/apps/collection-player/composables/speaker-notes.use.spec.d.ts +1 -0
  35. package/lib/apps/collection-player/stores/app.store.d.ts +5 -1
  36. package/lib/apps/collection-player/stores/showNotesToggle.spec.d.ts +1 -0
  37. package/lib/apps/content-selector/appTypes.d.ts +16 -0
  38. package/lib/apps/content-selector/components/Content/AllContent/List/expandFileGuard.spec.d.ts +1 -0
  39. package/lib/apps/notes/NotesApp.accountNotes.spec.d.ts +1 -0
  40. package/lib/apps/notes/NotesApp.speakerNotes.spec.d.ts +1 -0
  41. package/lib/apps/notes/composables/useAccountNotes.d.ts +14 -0
  42. package/lib/apps/notes/composables/useAccountNotes.spec.d.ts +1 -0
  43. package/lib/apps/notes/composables/useAccountOnlyNotesGate.d.ts +21 -0
  44. package/lib/apps/notes/composables/useAccountOnlyNotesGate.spec.d.ts +1 -0
  45. package/lib/apps/notes/composables/useActiveSlideNotes.d.ts +42 -0
  46. package/lib/apps/notes/composables/useActiveSlideNotes.spec.d.ts +1 -0
  47. package/lib/components/CFileAccessManagement/collaborationApi.d.ts +2 -0
  48. package/lib/components/CFilePanel/Details.spec.d.ts +1 -0
  49. package/lib/components/CFilePanel/KeyMessages.spec.d.ts +1 -0
  50. package/lib/components/CFilePanel/Summary.spec.d.ts +1 -0
  51. package/lib/components/CFileViewer/pdf/CFileViewer.pdf.util.d.ts +52 -0
  52. package/lib/components/CGlobalLoader/CGlobalLoaderMark.spec.d.ts +1 -0
  53. package/lib/components/CGlobalLoader/globalLoader.paths.d.ts +2 -0
  54. package/lib/components/CGlobalSearch/globalSearchTarget.util.d.ts +31 -0
  55. package/lib/components/CGlobalSearch/globalSearchTarget.util.test.d.ts +1 -0
  56. package/lib/components/CRichTextEditor/extensions/paragraphExtended.d.ts +7 -1
  57. package/lib/components/CRichTextEditor/extensions/paragraphExtended.test.d.ts +1 -0
  58. package/lib/components/canvases/CanvasesManagementBulk.use.d.ts +12 -2
  59. package/lib/components/masterCanvases/CMasterCanvasesManagement.use.d.ts +86 -0
  60. package/lib/components/masterCanvases/CMasterCanvasesManagement.use.spec.d.ts +1 -0
  61. package/lib/components/masterCanvases/CMasterCanvasesPendingShareCell.spec.d.ts +1 -0
  62. package/lib/components/masterCanvases/CMasterCanvasesSharedWithCell.use.d.ts +39 -0
  63. package/lib/components/masterCanvases/CMasterCanvasesSharedWithCell.use.spec.d.ts +1 -0
  64. package/lib/components/masterCanvases/createFromMaster.use.d.ts +255 -0
  65. package/lib/components/masterCanvases/createFromMaster.use.spec.d.ts +1 -0
  66. package/lib/components/masterCanvases/masterCanvasDocuments.use.d.ts +56 -0
  67. package/lib/components/masterCanvases/masterCanvasDocuments.use.spec.d.ts +1 -0
  68. package/lib/components/masterCanvases/masterCanvasShares.use.d.ts +103 -0
  69. package/lib/components/masterCanvases/masterCanvasShares.use.spec.d.ts +1 -0
  70. package/lib/components/masterCanvases/masterFromCanvas.use.d.ts +122 -0
  71. package/lib/components/masterCanvases/masterFromCanvas.use.spec.d.ts +1 -0
  72. package/lib/components/masterCanvases/masterFromTemplate.use.d.ts +50 -0
  73. package/lib/components/masterCanvases/masterFromTemplate.use.spec.d.ts +1 -0
  74. package/lib/components/savedCanvases/CSavedCanvasesManagement.use.d.ts +203 -0
  75. package/lib/components/savedCanvases/savedCanvasDocuments.use.d.ts +111 -0
  76. package/lib/components/savedCanvases/savedCanvasDocuments.use.spec.d.ts +1 -0
  77. package/lib/components/savedCanvases/smartFolders/SmartFolders.use.d.ts +4 -0
  78. package/lib/constants/cdp.const.d.ts +1 -0
  79. package/lib/constants/translationLanguages.const.d.ts +86 -8
  80. package/lib/constants/translationLanguages.const.spec.d.ts +1 -0
  81. package/lib/main.lib.d.ts +5 -0
  82. package/lib/sdk/api/HighLevelApi.d.ts +2 -0
  83. package/lib/sdk/api/modules/appsDb.d.ts +4 -4
  84. package/lib/sdk/api/modules/canvas.d.ts +12 -0
  85. package/lib/sdk/api/modules/ui/types.ui.d.ts +18 -0
  86. package/lib/sdk/interfaces.d.ts +31 -1
  87. package/lib/sdk/main.d.ts +38 -0
  88. package/lib/sdk/payload.types.d.ts +45 -0
  89. package/lib/sdk/platform.d.ts +27 -0
  90. package/lib/sdk/platform.spec.d.ts +1 -0
  91. package/lib/sdk/singleton-scope.spec.d.ts +1 -0
  92. package/lib/sdk/utils/httpFetch.spec.d.ts +1 -0
  93. package/lib/theme/canvasUiUnoPreset.test.d.ts +1 -0
  94. package/lib/types/app.d.ts +55 -1
  95. package/lib/types/canvases.d.ts +15 -0
  96. package/lib/types/launchDarkly.types.d.ts +8 -1
  97. package/lib/types/organizationSettings.types.d.ts +29 -0
  98. package/lib/util/aiSummary.d.ts +30 -0
  99. package/lib/util/aiSummary.spec.d.ts +1 -0
  100. package/lib/util/network.d.ts +35 -0
  101. package/package.json +1 -1
  102. package/types/openapi/models/Canvas.d.ts +1 -0
  103. package/types/openapi/models/CanvasCreate.d.ts +1 -0
  104. package/types/openapi/models/CanvasCreateRequest.d.ts +1 -0
  105. package/types/openapi/models/CanvasRecommendedFile.d.ts +1 -1
  106. package/types/openapi/models/CanvasRetrieve.d.ts +1 -0
  107. package/types/openapi/models/CanvasUpdate.d.ts +1 -0
  108. package/types/openapi/models/CanvasUpdateRequest.d.ts +1 -0
  109. package/types/openapi/models/DeletedCanvas.d.ts +1 -0
  110. package/types/openapi/models/File.d.ts +1 -1
  111. package/types/openapi/models/PatchedCanvasUpdateRequest.d.ts +1 -0
  112. package/types/openapi/models/SharedLink.d.ts +6 -0
  113. package/types/openapi/models/SharedLinkCreateRequest.d.ts +5 -0
@@ -5,6 +5,208 @@ export declare function getFreezeStatus(canvas: Pick<CanvasRetrieve, 'metadata'>
5
5
  export declare const SYSTEM_EXCLUDED_TAGS: readonly ["home", "share", "sharebox"];
6
6
  export declare function hasHidingTag(tags?: string[], dynamicTags?: string[]): boolean;
7
7
  export declare function isTemplateHiddenFromReps(canvas: Pick<CanvasRetrieve, 'tags' | 'template'>, rendererExcludedTags?: string[]): boolean;
8
+ /**
9
+ * PIT-7488 — which canvas list `CSavedCanvasesManagement` is rendering.
10
+ *
11
+ * Everything the variant changes lives in the pure resolvers below rather than inline in the
12
+ * SFC, because three of them guard state that is SHARED between simultaneously-reachable
13
+ * instances of the component (localStorage / sessionStorage), where a wrong answer shows up as
14
+ * the other tab misbehaving and is invisible in normal single-tab use.
15
+ */
16
+ export type CanvasesManagementVariant = 'pitchdecks' | 'masters';
17
+ export declare function isMastersVariant(variant?: CanvasesManagementVariant): boolean;
18
+ /**
19
+ * Smart folders are a pitchdeck-only view. `isSmartFoldersView` is a `useLocalStorage`, shared
20
+ * across every instance of the component, so without the variant guard a rep who switched the
21
+ * Pitchdecks tab to smart folders would find the master tab rendering `SmartFolders` — which
22
+ * lists ordinary pitchdecks. Masters aren't foldered, so they have no smart-folder equivalent.
23
+ */
24
+ export declare function resolveCanvasesView(opts: {
25
+ isMasters: boolean;
26
+ smartFoldersEnabled?: boolean;
27
+ isSmartFoldersView?: boolean;
28
+ }): 'smartFolders' | 'normal';
29
+ /**
30
+ * The localStorage key `useTableColumnsSettings` persists show/hide/reorder under. Must differ
31
+ * per variant: a shared key lets the two tabs overwrite each other's layout, and writes the
32
+ * masters-only `shared_with` column into the pitchdeck tab's saved settings.
33
+ *
34
+ * The masters key is `ciq_master_canvases_management_table_columns_settings`. It was renamed off
35
+ * `…master_pitchdecks…` with the rest of the feature, which resets any column layout a tester had
36
+ * already saved on the master tab — once, and only for that tab.
37
+ */
38
+ export declare function resolveColumnSettingsKey(isMasters: boolean): string;
39
+ /**
40
+ * Which `canvas_manager_table_columns` key to read LD column visibility from. Masters get their
41
+ * own so ops can configure the two lists independently — `getVisibleColumns` degrades to "show
42
+ * every column" when the key is absent, whereas reusing `canvases` would mean hiding a column on
43
+ * the Pitchdecks tab silently hid it here too.
44
+ *
45
+ * The masters key is now `master_canvases`: ops must rename it inside the
46
+ * `canvas_manager_table_columns` LD value, and until they do the helper degrades to "show every
47
+ * column" rather than failing closed.
48
+ */
49
+ export declare function resolveColumnVisibilityView(isMasters: boolean): 'canvases' | 'master_canvases';
50
+ /**
51
+ * PIT-8360 QA — the copy that must NAME a master instead of saying "canvas".
52
+ *
53
+ * QA read the delete and unfreeze confirmations on the masters tab as belonging to an ordinary
54
+ * pitchdeck, because every sentence in them says "canvas". Instances rename that word through
55
+ * `translation_overrides` (a whole-word replace, so Vontobel's "canvas" -> "PitchDeck" makes them
56
+ * read "this PitchDeck"), which means the fix is NOT a per-instance label change: the source
57
+ * string has to carry the qualifier so the same override yields "master PitchDeck". This is also
58
+ * why the master strings say "master canvas" rather than "master pitchdeck" — the override only
59
+ * fires on the word it knows.
60
+ *
61
+ * Two shapes were rejected, and both failures are worth keeping written down:
62
+ *
63
+ * 1. An `{entity}` placeholder in the shared sentences. The pitchdeck tab uses the same strings in
64
+ * 14 locales, where a swapped-in noun would have to agree in article and gender.
65
+ * 2. A `resolveKey(copy, isMasters)` table returning the i18n key. **`vue-i18n-extract` runs with
66
+ * `--remove` in CI** (`scripts/lib-extract-translations.js`, and slotty's `extract:translations`)
67
+ * and finds keys by scanning source for literal translation calls — a computed key is
68
+ * invisible to it, so it deleted the master keys AND the pitchdeck keys whose literals the
69
+ * table had replaced. Every i18n key must appear spelled out as the argument of a translation
70
+ * call at its own call site; that is why the master copy is selected with a ternary over two
71
+ * whole calls rather than by picking a key. `resolveBulkEntityType` below is fine because it
72
+ * names an ENTITY, not a key — its `canvasUI.common.masterCanvas` literal lives in
73
+ * `getCanvasTypeTranslation`. Mind this when writing about i18n in a comment, too: a
74
+ * call-shaped example inside the scan glob is harvested as a real key.
75
+ */
76
+ /**
77
+ * The noun the BULK dialogs put in front of the rep ("delete the 2 selected …").
78
+ *
79
+ * Only the two bulk dialogs the masters tab actually offers take this — delete and manage
80
+ * attributes. The tag dialogs are hidden there (`moreActions.addTags: !isMasters`) and keep the
81
+ * plain `CanvasType`, because their value is also sent to the instance-tags endpoint as
82
+ * `canvas_type`, where `'master-canvas'` is not a thing.
83
+ */
84
+ export declare function resolveBulkEntityType(isMasters: boolean): 'canvas' | 'master-canvas';
85
+ /**
86
+ * Account scoping for the fetch. Never applies to masters: they are account-less server-side
87
+ * (`resolve_account` nulls it on write), so an `account__id` filter matches nothing and empties
88
+ * the whole list. The selected account comes from localStorage and therefore survives across
89
+ * tabs — so this fires on the master tab even when no account was ever picked there.
90
+ */
91
+ export declare function resolveAccountFilterId(opts: {
92
+ isMasters: boolean;
93
+ accountVisibilityEnabled?: boolean;
94
+ selectedAccountId?: string | null;
95
+ }): string | undefined;
96
+ /** Masters have no account, so the column would render a dash on every row. */
97
+ export declare function shouldShowAccountColumn(opts: {
98
+ isMasters: boolean;
99
+ isCRM?: boolean;
100
+ }): boolean;
101
+ /**
102
+ * Masters always show Owner: block 5 lets colleagues share a master, so the list stops being
103
+ * "only mine" and the owner becomes what distinguishes rows. On the pitchdeck tab it stays
104
+ * admin-gated exactly as before.
105
+ */
106
+ export declare function shouldShowOwnerColumn(opts: {
107
+ isMasters: boolean;
108
+ isAnyTypeOfAdmin?: boolean;
109
+ accountVisibilityEnabled?: boolean;
110
+ }): boolean;
111
+ /**
112
+ * Whether the Documents column shows (PIT-8360).
113
+ *
114
+ * Pitchdecks only. It shipped on the MASTER tab, where the signed-off prototype never put it — the
115
+ * prototype's "Document download" column belongs to the pitchdecks tab. Nothing is lost by
116
+ * removing it from the masters list: a master's rendered documents are still reachable from its row
117
+ * actions (Download PDF / PPTX / Regenerate), which read the same server-side state the column did.
118
+ *
119
+ * The `enable_scale_content` term is not belt-and-braces. That flag selects which conversion path
120
+ * runs for a DECK, and only the pdftopptx path it enables ever writes the `pdf_url`/`pptx_url`
121
+ * metadata this column reads — so with it off every row would render a dash under a header
122
+ * promising documents. Hidden beats uniformly empty.
123
+ *
124
+ * The downloader term follows how `shared_with` gates on its fetcher: a host that supplies none
125
+ * would otherwise get a column whose PDF/PPTX buttons render and then do nothing — the silent-no-op
126
+ * failure this file's `template`-column comment records as a reported QA bug.
127
+ *
128
+ * Gated here rather than through the LD column config because `getVisibleColumns` degrades to
129
+ * "show every column" when an instance configures no entry for the view, so the config cannot
130
+ * express "never on this tab".
131
+ */
132
+ export declare function shouldShowDocumentsColumn(opts: {
133
+ isMasters: boolean;
134
+ scaleContentEnabled?: boolean;
135
+ /** The host callback behind the column's click; without it the buttons are inert. */
136
+ hasDocumentDownloader?: boolean;
137
+ }): boolean;
138
+ /**
139
+ * Whether duplicating should prompt for an account first.
140
+ *
141
+ * Never for masters. Not merely because the value would be redundant (the server nulls it) — the
142
+ * master tab passes `accounts: []`, so the modal would open with an empty list, the rep could
143
+ * select nothing, and the duplicate would silently abort with no toast and no error.
144
+ */
145
+ export declare function shouldRequireAccountOnDuplicate(opts: {
146
+ isMasters: boolean;
147
+ isCRM?: boolean;
148
+ requireAccountOnCanvasCreation?: boolean;
149
+ }): boolean;
150
+ /**
151
+ * PIT-7488 block 4 — inputs shared by the two places the create-from-master flow can be started.
152
+ *
153
+ * The host capabilities are part of the gate on purpose: the flow needs a way to LIST masters (for
154
+ * the picker, and to resolve a preselected id to a label) and a way to create an ORDINARY deck
155
+ * (the masters tab's own `creator` makes masters). A flag turned on without them renders an entry
156
+ * that cannot work, which reads as a broken feature rather than an unconfigured one.
157
+ *
158
+ * `isCanvasCreationDisabled` matters because this creates a canvas — the same permission bypass
159
+ * CodeRabbit caught on block 3's "Use as master", where a rep without `canvas.create` could make
160
+ * one anyway.
161
+ */
162
+ interface CreateFromMasterCapability {
163
+ masterCanvasesEnabled?: boolean;
164
+ hasMasterFetcher?: boolean;
165
+ hasCanvasFromMasterCreator?: boolean;
166
+ isCanvasCreationDisabled?: boolean;
167
+ }
168
+ /** Enables the master row's "Use to create pitchdeck" button (rendered disabled until block 4). */
169
+ export declare function canUseMasterToCreateCanvas(opts: CreateFromMasterCapability): boolean;
170
+ /**
171
+ * Whether NEW becomes a dropdown offering "From my master pitchdeck".
172
+ *
173
+ * The ONLY difference from `canUseMasterToCreateCanvas` is the variant term, and it is not
174
+ * cosmetic: `CSavedCanvasesManagementToolbar` renders for BOTH variants, so without the guard the
175
+ * master tab's own NEW grows an entry that builds a deck from a master while standing in the master
176
+ * list — the same shared-surface trap as the smart-folders view and the column-settings key.
177
+ */
178
+ export declare function shouldOfferCreateFromMaster(opts: CreateFromMasterCapability & {
179
+ isMasters: boolean;
180
+ }): boolean;
181
+ /**
182
+ * PIT-8398 — apply a known field delta to one loaded row, instead of refetching the page to
183
+ * discover what the caller just wrote.
184
+ *
185
+ * Two properties this relies on, both load-bearing:
186
+ *
187
+ * 1. **Immutable replacement**, because this is a pure function — it must not mutate the array
188
+ * the caller handed it, which is also what makes it testable in isolation. Note this is NOT
189
+ * a reactivity requirement: `CTable` renders each cell from `row.original`, so Vue's deep
190
+ * proxy tracks a nested write and an in-place `rows[i].metadata = …` re-renders too
191
+ * (measured, not assumed). Replacement is preferred anyway — it matches the three existing
192
+ * row-write patterns in the consuming component (`updateProperty`, `refreshCanvasMetadata`,
193
+ * `startAsyncDownload`) and it does not depend on the row being a reactive proxy at all,
194
+ * which a plain snapshot passed through `deepToRaw` would not be.
195
+ * 2. **Spread onto the existing row, never replace it.** A PATCH response carries only the
196
+ * canvas fields; it does not carry the list-only ones the row already holds (`indicators`
197
+ * from the list serializer, the account name injected by `enrichCanvasesWithAccountNames`).
198
+ * Overwriting the row with a response would silently drop them — the trap `updateProperty`
199
+ * works around by re-attaching `indicators` by hand.
200
+ *
201
+ * `patched` is false when the id is not on the current page, so a caller can fall back to a
202
+ * full `refetch()` rather than assume the UI caught up.
203
+ */
204
+ export declare function applyRowPatch<T extends {
205
+ id: string;
206
+ }>(rows: T[], id: T['id'], patch: Partial<T>): {
207
+ rows: T[];
208
+ patched: boolean;
209
+ };
8
210
  export declare function useCSavedCanvasesManagement(): {
9
211
  statusOptions: {
10
212
  label: string;
@@ -14,3 +216,4 @@ export declare function useCSavedCanvasesManagement(): {
14
216
  [key: string]: any;
15
217
  }>[];
16
218
  };
219
+ export {};
@@ -0,0 +1,111 @@
1
+ import { MasterDocumentsState } from '../masterCanvases/masterCanvasDocuments.use';
2
+ /**
3
+ * PIT-8360 — the Documents column on the PITCHDECK tab.
4
+ *
5
+ * The column shipped on the master tab, which the signed-off prototype never had: its
6
+ * "Document download" column sits on the pitchdecks tab. Moving it there means feeding the SAME
7
+ * cell from a different artifact store, because the two tabs' documents come from different
8
+ * pipelines and only one of them is server-orchestrated:
9
+ *
10
+ * - a MASTER's artifacts live in `core_master_canvas_documents`, rendered server-side by
11
+ * next-core, and the bulk read is also the scheduler;
12
+ * - a DECK's artifacts live in its own `metadata` (`pdf_url` / `pptx_url` / `conversion_date` /
13
+ * `job_id`), written by the pdftopptx callback server when a rep asks for a download.
14
+ *
15
+ * So this is an adapter, not a second fetch: everything it needs is already on the row the list
16
+ * fetched. That is the whole reason the column could move without touching the backend — and why
17
+ * relaxing next-core's `c.is_master = true` filters was not necessary. It also means the pitchdeck
18
+ * column adds no requests and schedules no renders, which matters: reps hold far more decks than
19
+ * masters, so scheduling one render per listed row would have multiplied Gotenberg load.
20
+ *
21
+ * Kept free of Vue so the mapping is testable on its own, like its master-side counterpart.
22
+ */
23
+ /**
24
+ * What `getAsyncDownloadState` in `CSavedCanvasesManagement` returns.
25
+ *
26
+ * Declared here rather than exported from the component: it is a local `const` inside a
27
+ * 2000-line SFC, and the call site is what structurally checks the two against each other, so a
28
+ * drift shows up as a type error there. `undefined` is part of the contract — that function
29
+ * returns it outright when `enable_scale_content` is off.
30
+ */
31
+ export interface SavedCanvasDownloadNotStarted {
32
+ status: 'not_started';
33
+ }
34
+ export interface SavedCanvasDownloadInProgress {
35
+ status: 'in_progress';
36
+ jobId?: string;
37
+ /** `metadata.conversion_date` verbatim — when the job was queued. See the staleness rule below. */
38
+ conversionDate?: string | null;
39
+ /**
40
+ * The rep started this download in THIS session, so the component is already polling it and it is
41
+ * live by construction. Exempt from the staleness rule, and legitimately stampless.
42
+ */
43
+ startedThisSession?: boolean;
44
+ }
45
+ export interface SavedCanvasDownloadCompleted {
46
+ status: 'completed';
47
+ pdfUrl?: string;
48
+ pptxUrl?: string;
49
+ jobId?: string;
50
+ /** The presigned artifact is past the instance's `async_download_expiration_hours` window. */
51
+ isExpired?: boolean;
52
+ /**
53
+ * `metadata.conversion_date` verbatim. Needed here because `isExpired` alone cannot be trusted —
54
+ * see the age guards in `toDocumentsState`.
55
+ */
56
+ conversionDate?: string | null;
57
+ }
58
+ /**
59
+ * A `type` because it is a union, which an interface cannot express; the object shapes above are
60
+ * interfaces per the repo convention.
61
+ */
62
+ export type SavedCanvasAsyncDownloadState = SavedCanvasDownloadNotStarted | SavedCanvasDownloadInProgress | SavedCanvasDownloadCompleted;
63
+ /**
64
+ * Maps a deck's async-download state onto the shape `CMasterCanvasesDocumentsCell` renders.
65
+ *
66
+ * `null` means "no documents", which the cell draws as a dash. Three states reach it:
67
+ *
68
+ * - the pipeline is off (`undefined`), so no deck can have artifacts;
69
+ * - nobody has downloaded this deck yet;
70
+ * - the artifacts have EXPIRED. Returning the URLs anyway would hand the rep two buttons
71
+ * pointing at objects that are gone — the actions menu already refuses to offer them
72
+ * (`!props.isExpired` gates its PDF/PPTX entries) and offers Regenerate instead, so a dash here
73
+ * keeps the two surfaces telling the same story.
74
+ *
75
+ * Note what is deliberately NOT mapped:
76
+ *
77
+ * - `is_stale` is always false. Staleness is a master concept — the server re-renders a master
78
+ * whose slides have moved on, and the cell keeps the old links plus a quiet refresh spinner. A
79
+ * deck's artifact is never refreshed behind the rep's back; it expires instead.
80
+ * - there is no `failed`. `getAsyncDownloadState` never reports one, so `canRetryDocuments` stays
81
+ * false and the cell renders no Retry button — which is correct, because re-running a deck
82
+ * conversion is the actions menu's Download entry, not this cell's job.
83
+ * - `rendered_at` and `error` stay null: the deck pipeline records neither, and inventing values
84
+ * would claim knowledge the cell would then display.
85
+ */
86
+ export declare function toDocumentsState(asyncState: SavedCanvasAsyncDownloadState | undefined | null): MasterDocumentsState | null;
87
+ /**
88
+ * The predicate behind `openableUrl`, exported because the row's Download actions need the same
89
+ * answer: they build their own anchor instead of going through the host's opener, so without this
90
+ * they are the only artifact surface with no scheme check on them at all.
91
+ */
92
+ export declare function isOpenableDocumentUrl(url: string | null | undefined): url is string;
93
+ /**
94
+ * Whether the cell should offer a download for a deck that has no artifact yet (PIT-8360 follow-up).
95
+ *
96
+ * The column started as a mirror of existing artifacts, so a deck nobody had downloaded showed a
97
+ * dash — which reads as "no documents available" when the truth is "nobody has asked yet". The
98
+ * developer's call: a READY deck always offers PDF and PPTX, and the click generates them.
99
+ *
100
+ * Gated on Ready (`is_draft === false`) because that is the signal the rep uses to mean "this deck
101
+ * is finished". A draft still keeps its Download action in the row menu, so nothing is lost — the
102
+ * column simply does not invite a render of something still being written.
103
+ *
104
+ * `isDraft` is optional and a missing value is treated as NOT ready: a partially-fetched row must
105
+ * not invite a Gotenberg render on a deck whose state we do not actually know.
106
+ */
107
+ export declare function shouldOfferDocumentDownload(opts: {
108
+ isDraft?: boolean;
109
+ /** Present when the artifacts already exist — then the cell shows real links, not an offer. */
110
+ hasDocuments?: boolean;
111
+ }): boolean;
@@ -65,6 +65,7 @@ export default function useSmartFolders(emit?: (event: 'open', ...args: any[]) =
65
65
  is_template?: boolean | undefined;
66
66
  is_section?: boolean | undefined;
67
67
  is_block?: boolean | undefined;
68
+ is_master?: boolean | undefined;
68
69
  is_editable?: boolean | undefined;
69
70
  is_default?: boolean | undefined;
70
71
  metadata?: any;
@@ -150,6 +151,7 @@ export default function useSmartFolders(emit?: (event: 'open', ...args: any[]) =
150
151
  is_template?: boolean | undefined;
151
152
  is_section?: boolean | undefined;
152
153
  is_block?: boolean | undefined;
154
+ is_master?: boolean | undefined;
153
155
  is_editable?: boolean | undefined;
154
156
  is_default?: boolean | undefined;
155
157
  metadata?: any;
@@ -215,6 +217,7 @@ export default function useSmartFolders(emit?: (event: 'open', ...args: any[]) =
215
217
  is_template?: boolean | undefined;
216
218
  is_section?: boolean | undefined;
217
219
  is_block?: boolean | undefined;
220
+ is_master?: boolean | undefined;
218
221
  is_editable?: boolean | undefined;
219
222
  is_default?: boolean | undefined;
220
223
  metadata?: any;
@@ -281,6 +284,7 @@ export default function useSmartFolders(emit?: (event: 'open', ...args: any[]) =
281
284
  is_template?: boolean | undefined;
282
285
  is_section?: boolean | undefined;
283
286
  is_block?: boolean | undefined;
287
+ is_master?: boolean | undefined;
284
288
  is_editable?: boolean | undefined;
285
289
  is_default?: boolean | undefined;
286
290
  metadata?: any;
@@ -51,6 +51,7 @@ export declare const PLATFORM_TYPE: {
51
51
  readonly ios: "ios";
52
52
  readonly android: "android";
53
53
  readonly windows: "windows";
54
+ readonly macos: "macos";
54
55
  };
55
56
  export declare const EMBED_TYPE: {
56
57
  readonly standalone: "standalone";
@@ -15,12 +15,42 @@
15
15
  * `label` is intentionally NOT an i18n key: language names are shown in their own
16
16
  * language (the endonym), which is what every locale picker in the product does,
17
17
  * and it keeps the list free of the dynamic-key lookups the i18n extractor strips.
18
+ * That is also what lets this list exceed the shipped locales without any i18n work.
19
+ *
20
+ * ⚠️ THE LITERAL ORDER IS THE DISPLAY ORDER. Entries are sorted by `label`, the
21
+ * string the admin actually reads: Latin alphabetically, then Greek, Cyrillic,
22
+ * Devanagari, Thai, Hangul, CJK, which is what `Intl.Collator` yields. Sorting by
23
+ * `locale` reads better in a diff and was the original order, but it only looked
24
+ * alphabetical by accident while the list was 14 Latin-ish languages — at 24 it put
25
+ * Suomi between Español and Français. The pickers do not sort, so this list must.
26
+ *
27
+ * ⚠️ These are NOT all platform UI locales. The original 14 were, which is why an
28
+ * older version of this comment said so; the 10 added on 2026-08-11 (cs, da, fi,
29
+ * hi, id, ko, nb, ru, sv, vi) have no `locale/<code>.json`. Translating CONTENT is
30
+ * not localising the PRODUCT, and nothing here loads a bundle from `locale`.
31
+ *
32
+ * ⚠️ Every entry must stay selectable — the admin client maps this list straight to
33
+ * Vuetify items with no `disabled` prop and no filtering, which is deliberate. Do
34
+ * not add a per-language disabled/beta flag; a language that cannot be served by
35
+ * both translation legs should not be in the list. That is why Arabic and Hebrew
36
+ * are absent despite DeepL supporting them: the product has no RTL rendering, so a
37
+ * translated canvas would lay out left-to-right.
18
38
  */
19
39
  export interface TranslationLanguageOption {
20
- /** Platform locale, matching the locale JSON filenames. Posted to the backend. */
40
+ /** Target-language key posted to the backend. NOT necessarily a shipped UI locale. */
21
41
  locale: string;
22
42
  /** Endonym shown in the picker. */
23
43
  label: string;
44
+ /**
45
+ * English name of the language, used ONLY to make the picker searchable.
46
+ *
47
+ * ⚠️ Load-bearing for `filterable` pickers. Naive UI's default filter matches
48
+ * `option.label`, and `label` is the endonym — so without this an admin typing
49
+ * "swedish" gets "No data" for Svenska, and likewise for 9 other entries. The
50
+ * filter must be given explicitly and must test BOTH fields; see
51
+ * `translationLanguageOptions`.
52
+ */
53
+ englishName: string;
24
54
  /** Uppercase suffix the backend appends to a translated record's name. */
25
55
  suffix: string;
26
56
  }
@@ -53,20 +83,68 @@ export declare function isTranslatableFileExtension(extension?: string | null):
53
83
  * Extension of a file record, resolved the way the route resolves it.
54
84
  *
55
85
  * ⚠️ MIRROR of `resolveExtension` in
56
- * `packages/next-core/src/app/api/protected/files/translate/route.ts`: prefer the
57
- * explicit extension field, fall back to parsing the name. A UI gate that only
58
- * read the explicit field hid the action on records whose extension column is
59
- * empty even though the route would have accepted them. The API field is called
60
- * `extension` on the detail serializer and `original_extension` on the compact
61
- * one the browser list uses, so both are accepted here.
86
+ * `packages/next-core/src/services/translation/translated-file.ts`: prefer
87
+ * `content_extension`, then `extension`, then parse the name. Keep the two in
88
+ * step a gate that disagrees with the route either hides a supported file or
89
+ * offers one the route will reject.
90
+ *
91
+ * `content_extension` comes first because it is the closest thing the list
92
+ * payload has to the rendition, and it is nearer to what the route declares to
93
+ * DeepL. Resolving `original_extension` first offered the action for a
94
+ * PDF-converted deck as `pptx`, so the button appeared and the upload then
95
+ * failed on bytes that are a PDF.
96
+ *
97
+ * ⚠️ `content_extension` does NOT describe the bytes actually stored. It records
98
+ * the UPLOAD. Django derives the served rendition from `content_type` alone
99
+ * (`get_content_url`), which is why the route resolves from `content_url` and
100
+ * this gate can only approximate it. Do not restate the stronger claim: it was
101
+ * wrong, and believing it cost three defects on PIT-7916.
102
+ *
103
+ * ⚠️ The chain is deliberately LONGER than the route's, and `original_extension`
104
+ * must stay in it. The two read different payloads:
105
+ *
106
+ * - This gate runs over the **folder/list** payload, which carries ONLY
107
+ * `original_extension` (verified against `GET /api/v1/folders/{id}/`: no
108
+ * `content_extension`, no `extension`). Drop it here and every file in the
109
+ * content browser resolves `''` and loses the action.
110
+ * - The route re-resolves from the **detail** payload
111
+ * (`GET /api/v1/files/{id}/`), which always carries `content_extension`, so it
112
+ * never needs the pre-conversion value and must not trust it.
113
+ *
114
+ * So a converted deck shows the action as `pptx` and then translates as `pdf`,
115
+ * which is correct in both places. The name parse survives as the last resort
116
+ * for records with no extension column at all.
62
117
  */
63
118
  export declare function resolveFileExtension(file?: {
64
119
  name?: string | null;
120
+ content_extension?: string | null;
65
121
  extension?: string | null;
66
122
  original_extension?: string | null;
67
123
  } | null): string;
68
- /** Naive UI / CSelect option shape for the language pickers. */
124
+ /**
125
+ * Naive UI / CSelect option shape for the language pickers.
126
+ *
127
+ * `englishName` rides along so a `filterable` picker can search it — see
128
+ * `translationLanguageFilter`, which such a picker MUST be given.
129
+ */
69
130
  export declare function translationLanguageOptions(): {
70
131
  label: string;
132
+ englishName: string;
71
133
  value: string;
72
134
  }[];
135
+ /**
136
+ * Filter for a `filterable` language picker, matching the endonym OR the English name.
137
+ *
138
+ * ⚠️ Pass this explicitly. Naive UI's default filter tests `option.label` only, and
139
+ * `label` is the endonym, so the default silently returns "No data" for every
140
+ * language an English-speaking admin would type the name of: Čeština, Dansk, Suomi,
141
+ * हिन्दी, Bahasa Indonesia, 한국어, Norsk bokmål, Русский, Svenska, Tiếng Việt, plus
142
+ * Ελληνικά, 日本語, ไทย and 中文. That is 14 of 24, and it fails silently rather than
143
+ * visibly, which is why it went unnoticed while the list was small.
144
+ *
145
+ * Accent-insensitive on the pattern side too, so "cestina" finds Čeština.
146
+ */
147
+ export declare function translationLanguageFilter(pattern: string, option: {
148
+ label?: string;
149
+ englishName?: string;
150
+ }): boolean;
@@ -0,0 +1 @@
1
+ export {};
package/lib/main.lib.d.ts CHANGED
@@ -86,6 +86,7 @@ export { default as CAssignedCanvasesManagement } from './components/assignedCan
86
86
  export { default as CAssignedCanvasesManagementToolbar } from './components/assignedCanvases/CAssignedCanvasesManagementToolbar.vue';
87
87
  export { default as useShareCanvas } from './components/savedCanvases/CSavedCanvasesManagementShareCanvas.use';
88
88
  export { getFreezeStatus, SYSTEM_EXCLUDED_TAGS, type FreezeStatus } from './components/savedCanvases/CSavedCanvasesManagement.use';
89
+ export { buildMasterFromTemplatePayload, type MasterFromTemplatePayload, type MasterTemplateSource, } from './components/masterCanvases/masterFromTemplate.use';
89
90
  export { default as CConfigEditor } from './components/CConfigEditor/CConfigEditor.vue';
90
91
  export { default as CTableInput } from './components/CTableInput/CTableInput.vue';
91
92
  export { default as CTableTag } from './components/CTableTag/CTableTag.vue';
@@ -106,6 +107,7 @@ export { default as CFileViewer } from './components/CFileViewer/CFileViewer.vue
106
107
  export { default as CDetailPageSectionButtons } from './components/CDetailPageSectionButtons/CDetailPageSectionButtons.vue';
107
108
  export { default as CFullScreenLoader } from './components/CFullScreenLoader/CFullScreenLoader.vue';
108
109
  export { default as CGlobalLoader } from './components/CGlobalLoader/CGlobalLoader.vue';
110
+ export { default as CGlobalLoaderMark } from './components/CGlobalLoader/CGlobalLoaderMark.vue';
109
111
  export { default as CFilesFolderDeleteDialogContent } from './components/CFilesFolderDeleteDialogContent/CFilesFolderDeleteDialogContent.vue';
110
112
  export { default as CCatalogIqSwitcher } from './components/CCatalogIqSwitcher/CCatalogIqSwitcher.vue';
111
113
  export { default as CCarousel } from './components/CCarousel/CCarousel.vue';
@@ -138,6 +140,9 @@ export { default as CanvasSelector } from './apps/canvas-selector/App.vue';
138
140
  export type { CanvasSelection } from './apps/canvas-selector/appTypes';
139
141
  export { default as NotesApp } from './apps/notes/NotesApp.vue';
140
142
  export { default as useNotesApp } from './apps/notes/composables/useNotesApp';
143
+ export { useAccountNotes, accountNotesBucketKey, NOTES_APP_CONTENT_KEY } from './apps/notes/composables/useAccountNotes';
144
+ export { useAccountOnlyNotesGate } from './apps/notes/composables/useAccountOnlyNotesGate';
145
+ export { ACTIVE_SLIDE_NOTES_KEY, clearActiveSlideNotes, setActiveSlideNotes, useActiveSlideNotes, type ActiveSlideNotes, } from './apps/notes/composables/useActiveSlideNotes';
141
146
  export { default as AssetsManagerApp } from './apps/assets-manager/App.vue';
142
147
  export type { AppProps as AssetsManagerProps } from './apps/assets-manager/App.vue';
143
148
  export * as pptConversionSelector from './apps/ppt-conversion-selector/export';
@@ -173,6 +173,7 @@ export declare function createHighLevelApi(options?: ApiOptions): {
173
173
  id: import('../../main.lib').CanvasRetrieve["id"];
174
174
  fields?: string;
175
175
  lazy_sections?: boolean;
176
+ skip_error_toast?: boolean;
176
177
  }): Promise<import('../../main.lib').CanvasRetrieve>;
177
178
  getSectionsByIds(payload: {
178
179
  canvas_id: import('../../main.lib').CanvasRetrieve["id"];
@@ -185,6 +186,7 @@ export declare function createHighLevelApi(options?: ApiOptions): {
185
186
  }>;
186
187
  shareCanvas(payload: {
187
188
  id: import('../../main.lib').CanvasRetrieve["id"];
189
+ brand_id?: string;
188
190
  }): Promise<import('../../main.lib').SharedLink>;
189
191
  getCanvasRecommendedFiles(payload: {
190
192
  canvas_id: import('../../main.lib').CanvasRetrieve["id"];
@@ -2,7 +2,7 @@ import { AppsDbDeleteEntryPayload, AppsDbEntriesResult, AppsDbEntry, AppsDbGetEn
2
2
  /**
3
3
  * Lists AppsDB entries of a type, adapting to the platform:
4
4
  * - Web: GET to the next-core AppsDB REST API.
5
- * - iOS: reads the local offline mirror via the `appsdb_get_entries` bridge
5
+ * - Native (iPad or desktop): reads the local offline mirror via the `appsdb_get_entries` bridge
6
6
  * request. Types not allowlisted in the `offline_appsdb_types` setting fail
7
7
  * with `code = type_not_synced` and automatically fall back to the network.
8
8
  *
@@ -13,7 +13,7 @@ export declare function appsDbGetEntries(payload: AppsDbGetEntriesPayload): Prom
13
13
  /**
14
14
  * Creates or updates (deep-merges) an AppsDB entry, adapting to the platform:
15
15
  * - Web: POST (create) or PUT (update, when `id` is set) to the next-core AppsDB REST API.
16
- * - iOS: the `appsdb_upsert_entry` bridge request writes on the server and
16
+ * - Native (iPad or desktop): the `appsdb_upsert_entry` bridge request writes on the server and
17
17
  * mirrors the authoritative result locally. Offline it rejects with
18
18
  * `code = offline_write_not_supported` — AppsDB writes are online-only.
19
19
  *
@@ -28,7 +28,7 @@ export declare function appsDbUpsertEntry(payload: AppsDbUpsertEntryPayload): Pr
28
28
  /**
29
29
  * Deletes an AppsDB entry (soft delete server-side), adapting to the platform:
30
30
  * - Web: DELETE to the next-core AppsDB REST API.
31
- * - iOS: the `appsdb_delete_entry` bridge request deletes on the server and
31
+ * - Native (iPad or desktop): the `appsdb_delete_entry` bridge request deletes on the server and
32
32
  * removes the entry from the local offline mirror. Offline it rejects with
33
33
  * `code = offline_write_not_supported`.
34
34
  *
@@ -40,7 +40,7 @@ export declare function appsDbDeleteEntry(payload: AppsDbDeleteEntryPayload): Pr
40
40
  * Runs a PSQL (SQL-like) query against AppsDB: POST to the next-core
41
41
  * `/appsdb/psql` endpoint whenever the network is available.
42
42
  *
43
- * On iOS the local offline mirror (`appsdb_get_entries` + client-side
43
+ * On a native host the local offline mirror (`appsdb_get_entries` + client-side
44
44
  * evaluation of simple `field = literal` AND-chains) serves the query ONLY
45
45
  * while the device is offline, or when an online fetch fails at the
46
46
  * connection level. Online queries are always answered by the server: Hub
@@ -91,6 +91,8 @@ export declare function getCanvas(payload: {
91
91
  id: CanvasRetrieve['id'];
92
92
  fields?: string;
93
93
  lazy_sections?: boolean;
94
+ /** Suppress the host's error toast for best-effort reads (e.g. download-completion polling). */
95
+ skip_error_toast?: boolean;
94
96
  }): Promise<CanvasRetrieve>;
95
97
  /**
96
98
  * Batch-hydrate section bodies for a canvas fetched as a lazy shell.
@@ -123,8 +125,18 @@ export declare function getSectionsByIds(payload: {
123
125
  }): Promise<{
124
126
  sections: CanvasSection[];
125
127
  }>;
128
+ /**
129
+ * Get (or create) the shared link for a canvas.
130
+ *
131
+ * `brand_id` (PIT-7682, optional) names an entry in the instance's `shared_link_brands` setting and
132
+ * only takes effect when the link is created. Omit it and the server uses the brand the rep last
133
+ * used on that instance, falling back to the instance default — the behaviour quick-share,
134
+ * bulk-share and API-created links get. A host that does not forward it (the iOS bridge today)
135
+ * therefore still produces a correctly branded link, just without the rep's per-share choice.
136
+ */
126
137
  export declare function shareCanvas(payload: {
127
138
  id: CanvasRetrieve['id'];
139
+ brand_id?: string;
128
140
  }): Promise<SharedLink>;
129
141
  export declare function getCanvasRecommendedFiles(payload: {
130
142
  canvas_id: CanvasRetrieve['id'];
@@ -356,5 +356,23 @@ export interface UiOpenSharingSettingsResponse {
356
356
  allowed_domains?: string[];
357
357
  valid_until_days?: number | null;
358
358
  allow_download?: boolean;
359
+ /**
360
+ * PIT-7682 — id of an entry in the instance's `shared_link_brands` setting, present only when
361
+ * the rep made a deliberate pick in the sharing modal. The host collects it; the app that
362
+ * later creates the link (ng-emails-app's ShareBox POST) forwards it verbatim to
363
+ * `/shared-links`, which is the only place it means anything — the brand is baked into the
364
+ * short URL at creation. Absent means "no choice", and the API applies the brand the rep last
365
+ * used on the instance, then the instance default.
366
+ */
367
+ brand_id?: string;
359
368
  };
369
+ /**
370
+ * PIT-5865 — the name the rep typed for the ShareBox in the sharing modal, already resolved
371
+ * (blank fell back to the default timestamp name, and it is capped at 100 chars). Deliberately a
372
+ * SIBLING of `settings` rather than a field inside it: `settings` is stored verbatim by the
373
+ * calling app as its pending-ShareBox sharing settings and rides into saved drafts, so a canvas
374
+ * name has no business in there. Absent on older hosts — the caller falls back to its own
375
+ * default.
376
+ */
377
+ canvas_name?: string;
360
378
  }