@pitcher/js-api 1.29.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 (158) hide show
  1. package/js-api.esm.js +488 -56
  2. package/js-api.esm.js.map +1 -1
  3. package/js-api.umd.min.js +32 -11
  4. package/js-api.umd.min.js.map +1 -1
  5. package/lib/ai-tasks/__tests__/weekly-focus.spec.d.ts +1 -0
  6. package/lib/ai-tasks/weekly-focus.d.ts +241 -0
  7. package/lib/apps/browser/appTypes.d.ts +28 -0
  8. package/lib/apps/browser/components/ContextMenu/TranslateFileButton.test.d.ts +1 -0
  9. package/lib/apps/browser/stores/api.d.ts +6 -1
  10. package/lib/apps/browser/stores/api.filesFoldersDeleter.test.d.ts +1 -0
  11. package/lib/apps/browser/stores/app.d.ts +5 -0
  12. package/lib/apps/browser/stores/app.selectionPruneScope.test.d.ts +1 -0
  13. package/lib/apps/browser/stores/upload.d.ts +26 -1
  14. package/lib/apps/browser/stores/upload.types.d.ts +9 -0
  15. package/lib/apps/browser/util/lifecycle.d.ts +57 -0
  16. package/lib/apps/browser/util/lifecycle.test.d.ts +1 -0
  17. package/lib/apps/canvas-builder/components/container/PopupApps/PopupAppModal.spec.d.ts +1 -0
  18. package/lib/apps/canvas-builder/components/container/PresentationTools/PresentationToolsButtons.spec.d.ts +1 -0
  19. package/lib/apps/canvas-builder/components/ui/BottomSheetModal/BottomSheetModal.integration.spec.d.ts +1 -0
  20. package/lib/apps/canvas-builder/components/ui/BottomSheetModal/BottomSheetModal.spec.d.ts +1 -0
  21. package/lib/apps/canvas-builder/components/ui/DynamicContent/section-component-bindings.util.d.ts +32 -0
  22. package/lib/apps/canvas-builder/components/ui/DynamicContent/useDynamicContent.d.ts +6 -0
  23. package/lib/apps/canvas-builder/components/ui/Link/Link.util.d.ts +8 -1
  24. package/lib/apps/canvas-builder/components/ui/Link/Link.util.test.d.ts +1 -0
  25. package/lib/apps/canvas-builder/components/ui/Multimedia/Multimedia.ldAsset.spec.d.ts +1 -0
  26. package/lib/apps/canvas-builder/components/ui/SectionList/SectionItemModal.spec.d.ts +1 -0
  27. package/lib/apps/canvas-builder/composables/useCanvas.d.ts +286 -10
  28. package/lib/apps/canvas-builder/composables/useCanvas.saveEcho.spec.d.ts +1 -0
  29. package/lib/apps/canvas-builder/composables/useCanvasBlocks.d.ts +40 -2
  30. package/lib/apps/canvas-builder/composables/useCanvasExit.d.ts +1 -0
  31. package/lib/apps/canvas-builder/composables/useCanvasHistory.d.ts +38 -2
  32. package/lib/apps/canvas-builder/composables/useCanvasTheme.d.ts +4 -2
  33. package/lib/apps/canvas-builder/composables/useContentSelector.d.ts +8 -1
  34. package/lib/apps/canvas-builder/composables/useInstalledEmbeddables.d.ts +1 -1
  35. package/lib/apps/canvas-builder/composables/useNavigatorDrawer.d.ts +27 -0
  36. package/lib/apps/canvas-builder/composables/useNavigatorDrawer.spec.d.ts +1 -0
  37. package/lib/apps/canvas-builder/composables/usePopupApps.d.ts +43 -4
  38. package/lib/apps/canvas-builder/composables/usePopupApps.spec.d.ts +1 -0
  39. package/lib/apps/canvas-builder/composables/usePresentationTools.d.ts +112 -0
  40. package/lib/apps/canvas-builder/composables/usePresentationTools.spec.d.ts +1 -0
  41. package/lib/apps/canvas-builder/types/canvas.d.ts +66 -3
  42. package/lib/apps/canvas-builder/util/canvas.util.d.ts +12 -0
  43. package/lib/apps/canvas-builder/util/completionWizard.util.d.ts +347 -0
  44. package/lib/apps/canvas-builder/util/completionWizard.util.test.d.ts +1 -0
  45. package/lib/apps/canvas-builder/util/fullscreenMode.util.d.ts +7 -0
  46. package/lib/apps/canvas-builder/util/fullscreenMode.util.test.d.ts +1 -0
  47. package/lib/apps/canvas-builder/util/iframe.util.d.ts +24 -2
  48. package/lib/apps/canvas-builder/util/iframe.util.test.d.ts +1 -0
  49. package/lib/apps/canvas-builder/util/lazySections.util.d.ts +35 -0
  50. package/lib/apps/canvas-builder/util/lazySections.util.test.d.ts +1 -0
  51. package/lib/apps/canvas-selector/stores/app.d.ts +14 -0
  52. package/lib/apps/collection-player/components/AppHeader.spec.d.ts +1 -0
  53. package/lib/apps/collection-player/composables/collection-navigation.util.d.ts +27 -0
  54. package/lib/apps/collection-player/composables/collection-navigation.util.spec.d.ts +1 -0
  55. package/lib/apps/collection-player/composables/speaker-notes.use.d.ts +14 -0
  56. package/lib/apps/collection-player/composables/speaker-notes.use.spec.d.ts +1 -0
  57. package/lib/apps/collection-player/stores/app.store.d.ts +8 -1
  58. package/lib/apps/collection-player/stores/showNotesToggle.spec.d.ts +1 -0
  59. package/lib/apps/content-selector/appTypes.d.ts +16 -0
  60. package/lib/apps/content-selector/components/Assets.uploaderRefresh.spec.d.ts +1 -0
  61. package/lib/apps/content-selector/components/Content/AllContent/List/expandFileGuard.spec.d.ts +1 -0
  62. package/lib/apps/content-selector/stores/app.d.ts +1 -1
  63. package/lib/apps/notes/NotesApp.accountNotes.spec.d.ts +1 -0
  64. package/lib/apps/notes/NotesApp.speakerNotes.spec.d.ts +1 -0
  65. package/lib/apps/notes/composables/useAccountNotes.d.ts +14 -0
  66. package/lib/apps/notes/composables/useAccountNotes.spec.d.ts +1 -0
  67. package/lib/apps/notes/composables/useAccountOnlyNotesGate.d.ts +21 -0
  68. package/lib/apps/notes/composables/useAccountOnlyNotesGate.spec.d.ts +1 -0
  69. package/lib/apps/notes/composables/useActiveSlideNotes.d.ts +42 -0
  70. package/lib/apps/notes/composables/useActiveSlideNotes.spec.d.ts +1 -0
  71. package/lib/components/CFileAccessManagement/collaborationApi.d.ts +2 -0
  72. package/lib/components/CFilePanel/Details.spec.d.ts +1 -0
  73. package/lib/components/CFilePanel/KeyMessages.spec.d.ts +1 -0
  74. package/lib/components/CFilePanel/Summary.spec.d.ts +1 -0
  75. package/lib/components/CFileViewer/pdf/CFileViewer.pdf.annotations.use.d.ts +5 -1
  76. package/lib/components/CFileViewer/pdf/CFileViewer.pdf.formFields.use.d.ts +8 -0
  77. package/lib/components/CFileViewer/pdf/CFileViewer.pdf.link.use.d.ts +1 -1
  78. package/lib/components/CFileViewer/pdf/CFileViewer.pdf.overlayItems.use.d.ts +1 -1
  79. package/lib/components/CFileViewer/pdf/CFileViewer.pdf.use.d.ts +4 -9
  80. package/lib/components/CFileViewer/pdf/CFileViewer.pdf.util.d.ts +53 -1
  81. package/lib/components/CFileViewer/pdf/CFileViewerFullscreen.pdf.use.d.ts +1 -1
  82. package/lib/components/CFileViewer/pdf/__tests__/CFileViewer.pdf.annotations.text.test.d.ts +1 -0
  83. package/lib/components/CGlobalLoader/CGlobalLoaderMark.spec.d.ts +1 -0
  84. package/lib/components/CGlobalLoader/globalLoader.paths.d.ts +2 -0
  85. package/lib/components/CGlobalSearch/globalSearchTarget.util.d.ts +31 -0
  86. package/lib/components/CGlobalSearch/globalSearchTarget.util.test.d.ts +1 -0
  87. package/lib/components/CRichTextEditor/extensions/paragraphExtended.d.ts +7 -1
  88. package/lib/components/CRichTextEditor/extensions/paragraphExtended.test.d.ts +1 -0
  89. package/lib/components/canvases/CanvasesManagementBulk.use.d.ts +12 -2
  90. package/lib/components/masterCanvases/CMasterCanvasesManagement.use.d.ts +86 -0
  91. package/lib/components/masterCanvases/CMasterCanvasesManagement.use.spec.d.ts +1 -0
  92. package/lib/components/masterCanvases/CMasterCanvasesPendingShareCell.spec.d.ts +1 -0
  93. package/lib/components/masterCanvases/CMasterCanvasesSharedWithCell.use.d.ts +39 -0
  94. package/lib/components/masterCanvases/CMasterCanvasesSharedWithCell.use.spec.d.ts +1 -0
  95. package/lib/components/masterCanvases/createFromMaster.use.d.ts +255 -0
  96. package/lib/components/masterCanvases/createFromMaster.use.spec.d.ts +1 -0
  97. package/lib/components/masterCanvases/masterCanvasDocuments.use.d.ts +56 -0
  98. package/lib/components/masterCanvases/masterCanvasDocuments.use.spec.d.ts +1 -0
  99. package/lib/components/masterCanvases/masterCanvasShares.use.d.ts +103 -0
  100. package/lib/components/masterCanvases/masterCanvasShares.use.spec.d.ts +1 -0
  101. package/lib/components/masterCanvases/masterFromCanvas.use.d.ts +122 -0
  102. package/lib/components/masterCanvases/masterFromCanvas.use.spec.d.ts +1 -0
  103. package/lib/components/masterCanvases/masterFromTemplate.use.d.ts +50 -0
  104. package/lib/components/masterCanvases/masterFromTemplate.use.spec.d.ts +1 -0
  105. package/lib/components/savedCanvases/CSavedCanvasesManagement.use.d.ts +204 -0
  106. package/lib/components/savedCanvases/savedCanvasDocuments.use.d.ts +111 -0
  107. package/lib/components/savedCanvases/savedCanvasDocuments.use.spec.d.ts +1 -0
  108. package/lib/components/savedCanvases/smartFolders/SmartFolders.use.d.ts +4 -0
  109. package/lib/composables/useCourseOnlyApps.d.ts +1 -1
  110. package/lib/composables/usePdfInterpolation.d.ts +2 -2
  111. package/lib/composables/useWindowEvents.d.ts +1 -1
  112. package/lib/constants/cdp.const.d.ts +2 -0
  113. package/lib/constants/translationLanguages.const.d.ts +150 -0
  114. package/lib/constants/translationLanguages.const.spec.d.ts +1 -0
  115. package/lib/main.lib.d.ts +7 -0
  116. package/lib/sdk/api/HighLevelApi.d.ts +19 -6
  117. package/lib/sdk/api/modules/ai.d.ts +43 -1
  118. package/lib/sdk/api/modules/ai.spec.d.ts +1 -0
  119. package/lib/sdk/api/modules/appsDb.d.ts +4 -4
  120. package/lib/sdk/api/modules/canvas.d.ts +20 -0
  121. package/lib/sdk/api/modules/ui/types.ui.d.ts +25 -0
  122. package/lib/sdk/interfaces.d.ts +31 -1
  123. package/lib/sdk/main.d.ts +46 -0
  124. package/lib/sdk/payload.types.d.ts +149 -0
  125. package/lib/sdk/platform.d.ts +27 -0
  126. package/lib/sdk/platform.spec.d.ts +1 -0
  127. package/lib/sdk/singleton-scope.spec.d.ts +1 -0
  128. package/lib/sdk/utils/httpFetch.spec.d.ts +1 -0
  129. package/lib/theme/canvasUiUnoPreset.test.d.ts +1 -0
  130. package/lib/types/ai-tasks.const.d.ts +39 -1
  131. package/lib/types/app.d.ts +55 -1
  132. package/lib/types/call.d.ts +14 -0
  133. package/lib/types/canvases.d.ts +15 -0
  134. package/lib/types/launchDarkly.types.d.ts +8 -3
  135. package/lib/types/organizationSettings.types.d.ts +39 -0
  136. package/lib/util/aiSummary.d.ts +30 -0
  137. package/lib/util/aiSummary.spec.d.ts +1 -0
  138. package/lib/util/network.d.ts +35 -0
  139. package/lib/util/user.d.ts +18 -0
  140. package/lib/util/user.test.d.ts +1 -0
  141. package/package.json +1 -1
  142. package/types/openapi/models/Canvas.d.ts +1 -0
  143. package/types/openapi/models/CanvasCreate.d.ts +1 -0
  144. package/types/openapi/models/CanvasCreateRequest.d.ts +1 -0
  145. package/types/openapi/models/CanvasRecommendedFile.d.ts +1 -1
  146. package/types/openapi/models/CanvasRetrieve.d.ts +1 -0
  147. package/types/openapi/models/CanvasUpdate.d.ts +1 -0
  148. package/types/openapi/models/CanvasUpdateRequest.d.ts +1 -0
  149. package/types/openapi/models/DeletedCanvas.d.ts +1 -0
  150. package/types/openapi/models/DeletedEnvironment.d.ts +0 -1
  151. package/types/openapi/models/Environment.d.ts +0 -1
  152. package/types/openapi/models/EnvironmentRequest.d.ts +0 -1
  153. package/types/openapi/models/File.d.ts +3 -1
  154. package/types/openapi/models/FileRetrieve.d.ts +2 -0
  155. package/types/openapi/models/PatchedCanvasUpdateRequest.d.ts +1 -0
  156. package/types/openapi/models/PatchedEnvironmentRequest.d.ts +0 -1
  157. package/types/openapi/models/SharedLink.d.ts +6 -0
  158. package/types/openapi/models/SharedLinkCreateRequest.d.ts +5 -0
@@ -0,0 +1,86 @@
1
+ import { CanvasRetrieve } from '../../../types/openapi';
2
+ /**
3
+ * PIT-7488 — row actions on a master pitchdeck, from the signed-off prototype's `…` menu.
4
+ *
5
+ * Same vocabulary as the pitchdeck tab, minus `use-as-master` (a master cannot become one) and
6
+ * plus `share` (sharing a master with colleagues, which ordinary decks do not do).
7
+ */
8
+ export type MasterCanvasAction = 'view' | 'edit' | 'open-new-tab' | 'freeze' | 'share' | 'duplicate' | 'delete';
9
+ /** Dialogs the master tab owns. `create-from-master` belongs to the create flow (block 4). */
10
+ export type MasterCanvasDialog = {
11
+ type: 'share';
12
+ canvasId: CanvasRetrieve['id'];
13
+ } | {
14
+ type: 'duplicate';
15
+ canvasId: CanvasRetrieve['id'];
16
+ } | {
17
+ type: 'confirm-delete';
18
+ canvasId: CanvasRetrieve['id'];
19
+ };
20
+ /** Actions the host performs directly — no confirmation step. */
21
+ export type MasterCanvasPassthroughAction = Exclude<MasterCanvasAction, 'share' | 'duplicate' | 'delete'>;
22
+ /**
23
+ * What a row action resolves to. Splitting these two apart is the point of this module: the
24
+ * prototype's `onRowAction` switch conflates "open a dialog" with "do the thing", and the two
25
+ * have completely different owners in production — dialogs are local state, whereas view / edit /
26
+ * download / freeze are host callbacks that already exist on the pitchdeck tab.
27
+ */
28
+ export type MasterCanvasActionResolution = {
29
+ kind: 'dialog';
30
+ dialog: MasterCanvasDialog;
31
+ } | {
32
+ kind: 'passthrough';
33
+ action: MasterCanvasPassthroughAction;
34
+ };
35
+ export declare function resolveMasterCanvasAction(action: MasterCanvasAction, canvasId: CanvasRetrieve['id']): MasterCanvasActionResolution;
36
+ /**
37
+ * Dialog state for the master tab.
38
+ *
39
+ * This is the ONLY part of the PoC reducer that survives contact with production: its list
40
+ * mutations (create / duplicate / delete / share) all rewrote an in-memory array, whereas here
41
+ * the list comes from the host's `fetcher` and a mutation is a request plus a refetch — machinery
42
+ * `CSavedCanvasesManagement` already owns. So this deliberately holds no rows.
43
+ */
44
+ export declare function useMasterCanvasDialogs(): {
45
+ dialog: import('vue').Ref<{
46
+ type: "share";
47
+ canvasId: CanvasRetrieve["id"];
48
+ } | {
49
+ type: "duplicate";
50
+ canvasId: CanvasRetrieve["id"];
51
+ } | {
52
+ type: "confirm-delete";
53
+ canvasId: CanvasRetrieve["id"];
54
+ } | null, MasterCanvasDialog | {
55
+ type: "share";
56
+ canvasId: CanvasRetrieve["id"];
57
+ } | {
58
+ type: "duplicate";
59
+ canvasId: CanvasRetrieve["id"];
60
+ } | {
61
+ type: "confirm-delete";
62
+ canvasId: CanvasRetrieve["id"];
63
+ } | null>;
64
+ openDialog: (next: MasterCanvasDialog) => void;
65
+ closeDialog: () => void;
66
+ handleAction: (action: MasterCanvasAction, canvasId: CanvasRetrieve["id"]) => MasterCanvasPassthroughAction | null;
67
+ };
68
+ export interface ShouldOfferUseToCreateOptions {
69
+ /** The permission/settings gate the pitchdeck cell also applies. */
70
+ canUseToCreate: boolean;
71
+ }
72
+ /**
73
+ * Whether a master's row may offer "Use to create pitchdeck" (PIT-7488 QA Q12).
74
+ *
75
+ * The `!isDraft` term is GONE as of PIT-8360, along with the Ready column that was the only control
76
+ * able to clear the flag. Keeping it would have stranded two populations for good: every new master
77
+ * (created as a Draft until this change) and every master already created as one — hidden from the
78
+ * row action here and filtered out of the creation picker, with nothing left to flip.
79
+ *
80
+ * So a master is offerable whenever the caller may create from one. Masters no longer carry a
81
+ * meaningful draft state; `is_draft` survives on the model because every canvas has it, not because
82
+ * anything on this tab means anything by it.
83
+ *
84
+ * Hidden rather than disabled, matching how this cell already treats an unavailable lead action.
85
+ */
86
+ export declare function shouldOfferUseToCreate(opts: ShouldOfferUseToCreateOptions): boolean;
@@ -0,0 +1,39 @@
1
+ import { MiniUser } from '../../../types/openapi';
2
+ /**
3
+ * PIT-7488 — display logic for the master pitchdeck "Shared with" cell.
4
+ *
5
+ * Kept out of the SFC so the capping/label rules are unit-testable: the cell itself is then a
6
+ * thin renderer over this result.
7
+ *
8
+ * The list is `Collaboration['user']` (a `MiniUser`) — block 5 is what will actually populate it.
9
+ */
10
+ /** Avatars rendered before collapsing the rest into a "+N" bubble. From the prototype. */
11
+ export declare const MAX_SHARED_WITH_AVATARS = 3;
12
+ export interface SharedWithSummary {
13
+ /** Users to render an avatar for, capped at `max`. */
14
+ shown: MiniUser[];
15
+ /** How many users the cap hid. `0` when everyone fits. */
16
+ overflow: number;
17
+ /** Compact text beside the avatar stack. */
18
+ label: string;
19
+ /** Every name, for the hover tooltip and the aria-label. */
20
+ allNames: string;
21
+ }
22
+ /**
23
+ * Names in list order, blank-name users resolved to their email (SSO users frequently have no
24
+ * populated name — PIT-5973), and users with neither dropped rather than rendered as an
25
+ * empty comma.
26
+ */
27
+ export declare function sharedWithNames(users: MiniUser[]): string[];
28
+ /**
29
+ * The compact label beside the avatar stack: every shown name, then "+N" for the rest.
30
+ *
31
+ * Note the prototype (`next-core/src/app/examples/master-pitchdeck-ng/components/
32
+ * SharedWithCell.tsx`) contradicts itself — its comment promises "first two names + +N" while
33
+ * its code joins all three *shown* names. We follow the code. The label truncates in a narrow
34
+ * column, which is accepted: the tooltip always carries the full list.
35
+ *
36
+ * `names` is already email-resolved and blank-filtered; `overflow` is how many the cap hid.
37
+ */
38
+ export declare function buildSharedWithLabel(names: string[], overflow: number): string;
39
+ export declare function summarizeSharedWith(users: MiniUser[], max?: number): SharedWithSummary;
@@ -0,0 +1,255 @@
1
+ import { CanvasCreateRequest, CanvasRetrieve } from '../../../types/openapi';
2
+ /**
3
+ * Metadata for a MASTER created from an existing canvas ("Use as master").
4
+ *
5
+ * Strips the source deck's own bookkeeping — the async-download record, so the new master does not
6
+ * offer a download of the SOURCE rendered before it became a master, and `frozen_until`, so a
7
+ * brand-new master is not born read-only.
8
+ *
9
+ * Deliberately KEEPS `pitcher.completion_wizard`, which is what separates this from
10
+ * `buildChildMetadata`. A master is a finished source: block 3 lets the wizard state survive into
11
+ * `context` (`buildMasterContext` prunes identity only), so pruning the `metadata` twin here would
12
+ * desynchronise the two and make the list's Progress column disagree with the wizard itself.
13
+ * Reusing `buildChildMetadata` would have been the intuitive fix and the wrong one.
14
+ */
15
+ export declare function buildMasterMetadata(sourceMetadata?: CanvasRetrieve['metadata'] | null): Record<string, unknown> | undefined;
16
+ /**
17
+ * The create payload for "Use as master pitchdeck" (PIT-7488 block 3).
18
+ *
19
+ * Mirror image of `buildCreateFromMasterPayload`, and it lives beside it for the same reason
20
+ * `buildMasterMetadata` does: the two directions must be read together or they drift.
21
+ *
22
+ * **`owned_by_id` is absent, and that absence is the contract (PIT-8362).** Django declares the
23
+ * field `default=CreateOnlyDefault(CurrentUserDefault())`, so omitting it is precisely what makes
24
+ * the master belong to whoever promoted the deck — the only owner "My Master Pitchdecks" can
25
+ * meaningfully show, since it is a personal, RESTRICTED, owner-scoped tab that the promote flow
26
+ * navigates to on success. Sending the SOURCE deck's owner instead (block 3's original rule,
27
+ * reverted here) put a colleague's master in the promoter's tab, and `CanvasOwnedByFieldValidator`
28
+ * 400s that transfer outright for anyone but an org/instance admin. Do not reintroduce the field.
29
+ *
30
+ * The rest mirrors the source deck, minus what a master must not inherit:
31
+ * - `account: null` + `access_type: RESTRICTED` — masters are account-less internal sources rather
32
+ * than shared content (`resolve_account` nulls the account server-side anyway).
33
+ * - `context` — identity is stripped so every deck built from this master renders the PRESENTING
34
+ * rep in `{{user.name}}`, not the promoter. See `buildMasterContext`.
35
+ * - `metadata` — drops the source's async-download record (its Actions cell would otherwise offer a
36
+ * completed download of the deck as it was BEFORE becoming a master) and `pitcher.frozen_until`
37
+ * (a brand-new master born read-only). Deliberately NOT `buildChildMetadata`: that also drops the
38
+ * completion wizard, which a master keeps, and `buildMasterContext` keeps its `context` twin —
39
+ * the two must agree.
40
+ *
41
+ * - `is_draft: false` — forced, NOT inherited (PIT-8360). Masters have no draft state since the
42
+ * Ready column was dropped from the master tab (validation item #44), so nothing can clear the
43
+ * flag afterwards: a deck promoted while still a draft would produce a permanently-draft master.
44
+ * This keeps the promote path agreeing with the other three master-creation paths in
45
+ * `MasterCanvasesView`, which force it too, rather than leaving `is_draft` set on masters with
46
+ * nothing that sets it FOR them, waiting to bite whoever next writes a filter against it.
47
+ */
48
+ export declare function buildMasterFromCanvasPayload(opts: {
49
+ source: CanvasRetrieve;
50
+ name: string;
51
+ }): Omit<CanvasCreateRequest, 'instance_id'>;
52
+ /**
53
+ * Drops the SOURCE's completion-wizard progress from a context that is otherwise copied verbatim.
54
+ *
55
+ * For the plain Duplicate action, which — unlike create-from-master — legitimately keeps the
56
+ * source's identity: the copy belongs to the same person, for the same account, so stripping
57
+ * `user`/`account` there would blank a deck the rep expects to be a faithful duplicate. The wizard
58
+ * state is different: `isCompletionWizardShowing` is `wizardSteps.length > 0 &&
59
+ * !context.pitcher.completion_wizard.completed`, so inheriting `completed: true` makes the copy
60
+ * open straight into the editor with the wizard silently skipped.
61
+ *
62
+ * Returns `undefined` when nothing survives, so the payload omits the field rather than writing an
63
+ * empty object over the server's default.
64
+ */
65
+ export declare function withoutWizardState(context?: CanvasRetrieve['context'] | null): Record<string, unknown> | undefined;
66
+ /**
67
+ * Context for a DUPLICATE (PIT-7488, peer review round 2).
68
+ *
69
+ * A pitchdeck copy strips the wizard state outright — see `withoutWizardState`. A MASTER copy cannot
70
+ * do either extreme:
71
+ *
72
+ * - Stripping it outright makes the copy look un-run, so the wizard reopens as a fresh `create`
73
+ * seeded from the ADMIN GROUP CONFIG and completing it writes that seed over the curated slides
74
+ * the rep just duplicated.
75
+ * - Keeping it verbatim inherits `completed: true`, which is the switch `isCompletionWizardShowing`
76
+ * reads — the copy then opens straight into the editor and never offers the wizard at all, while
77
+ * its Progress chip (from `metadata`) still says In progress. That desync is the whole reason
78
+ * `withoutWizardState` exists.
79
+ *
80
+ * So a master copy is re-marked as what it actually is: a deck that HAS been through the wizard but
81
+ * is not finished. `react_saved` is exactly that state — `resolveWizardFlow` reads it as `edit` (so
82
+ * the copy restores its OWN content), while `completed` stays falsy so the wizard still shows and
83
+ * the chip still reads In progress, agreeing with `buildChildMetadata`.
84
+ *
85
+ * The marker is added only when the source carries a RESTORABLE artifact — see
86
+ * `hasRestorableArtifact`, which is the sole gate on this path because the edit flow has no
87
+ * downstream `fromArtifact` check. A master with nothing to restore must not claim `react_saved`, or
88
+ * the edit flow restores from an artifact that is not there and reopens the empty-`edit` bug (Q9).
89
+ * `initial_section_list_data` is dropped either way, so the copy re-seeds its candidate baseline
90
+ * from its own content rather than re-offering slides the source deliberately dropped.
91
+ */
92
+ export declare function buildDuplicateContext(context?: CanvasRetrieve['context'] | null, opts?: {
93
+ isMaster?: boolean;
94
+ }): Record<string, unknown> | undefined;
95
+ /**
96
+ * Freezing a master says "this source is locked", not "every deck built from it is locked" — and a
97
+ * brand new deck the rep cannot edit is unusable.
98
+ */
99
+ export declare function buildChildMetadata(masterMetadata?: CanvasRetrieve['metadata'] | null): Record<string, unknown> | undefined;
100
+ /**
101
+ * The child's context: the master's configuration plus this session's identity.
102
+ *
103
+ * Identity is **stripped and re-added** rather than merged over, and that is the load-bearing
104
+ * detail. `getDefaultCrmShape` runs its result through `removeEmptyValues`, so on a non-CRM org
105
+ * (or with no live call) it emits no `account` and no `meeting` at all — a plain merge would then
106
+ * leave whatever the master carried, which is the wrong customer's name on the new deck. Stripping
107
+ * first means the child's identity keys can only ever come from the current session.
108
+ *
109
+ * It cannot rely on block 3 having cleaned the master either: `buildMasterContext` runs once, at
110
+ * creation, and opening a master in the builder afterwards deep-merges live `Account` /
111
+ * `salesforce_data` / `pitcher_data` back into its context. Every master is therefore re-poisonable
112
+ * between creation and use, and this is the last gate before a customer sees the result.
113
+ *
114
+ * `accountName` overrides whatever the CRM shape resolved because `getDefaultCrmShape` prefers the
115
+ * LIVE call's selected account (`call.selectedAccount.Name ?? accountName`). The account chosen in
116
+ * the dialog is the deck's account, so a rep prepping a deck for Beta during a call with Acme must
117
+ * not get Acme's name interpolated into it.
118
+ *
119
+ * The wizard artifact's OWN identity goes too (`withoutWizardIdentity`): the top-level key list
120
+ * never reached `wizard.subtitle`, so the promoter's customer rode onto the child's cover slide via
121
+ * `{{wizard.subtitle.label}}` (PIT-8399). Masters are re-poisonable after creation, so this pass
122
+ * has to run here as well as in `buildMasterContext`.
123
+ *
124
+ * The master's wizard PROGRESS is replaced rather than merely dropped (`pitcher.completion_wizard`,
125
+ * see `WIZARD_STATE_PITCHER_KEY`). Dropping it is what lets the completion wizard run on the new
126
+ * deck — on a `enable_react_completion_wizard` instance, the `pitchdeck-wizard-ng` app — but a deck
127
+ * with NO wizard state at all also reads as never-curated, and the wizard's create flow then
128
+ * reseeds its agenda from the ADMIN GROUP CONFIG, silently dropping every custom agenda point the
129
+ * master carried (PIT-8399, the reported defect). So the progress is reset to the one fact that
130
+ * survives: `from_master`, which says "this deck's content was copied from a curated source, so its
131
+ * own artifact is the authoritative agenda". `resolveWizardAgendaSource` reads it.
132
+ *
133
+ * `from_master` deliberately sets NONE of `completed` / `edited` / `react_saved`, so
134
+ * `resolveWizardFlow` still answers `'create'`: the deck really is being created, the editor still
135
+ * says so, and identity stays with the create flow rather than being restored off the master. That
136
+ * is what separates this from `buildDuplicateContext`, which marks a master COPY `react_saved` and
137
+ * accepts the `'edit'` flow because a duplicate legitimately IS the source. Do not unify the two.
138
+ *
139
+ * **Knock-on the marker's PRESENCE has** (review): `App.vue` computes
140
+ * `hasWizardState: isCompletionWizardEnabled || !!context.pitcher.completion_wizard` as a
141
+ * deliberate proxy for the window before the app roster loads, so a from-master deck now satisfies
142
+ * it from creation onward where it previously had no such key. With
143
+ * `enable_edit_opens_completion_wizard` on, `isWizardOwnedEditSurface` therefore holds the surface
144
+ * for such a deck immediately — correct whenever the deck has wizard steps, which is every normal
145
+ * case, and the marker is only written when the master carried an artifact, which means the wizard
146
+ * had already run on it. The sharp edge is a deck with an artifact and ZERO steps (its SectionList
147
+ * node deleted in the raw builder after the wizard ran): it is demoted out of edit mode with no
148
+ * wizard to open. That edge PREDATES this change — every deck that has ever run the wizard carries
149
+ * the same key — and this only adds one more way to reach it, so it is accepted rather than worked
150
+ * around here. Do not "optimise" the marker away on the assumption it is inert.
151
+ *
152
+ * Written only when the copied context actually still CARRIES an artifact (`context.wizard`) — not
153
+ * when the master merely had wizard PROGRESS. Those two come apart in both directions and both are
154
+ * wrong: `ensureWizardInitialized` writes `pitcher.completion_wizard` when the wizard OPENS, so a
155
+ * master whose wizard was opened and cancelled has progress and no artifact (5 such masters live on
156
+ * test-eu), while a master with an artifact and no progress key would be left unfixed. Claiming an
157
+ * artifact that is not there reopens the empty-`edit` bug from the other side (PIT-7488 QA Q9): the
158
+ * restore finds no skeletons and parks every ref on one unnamed point.
159
+ *
160
+ * Returns `undefined` rather than `{}` so the create payload omits the field instead of writing an
161
+ * empty object over the server's default.
162
+ */
163
+ export declare function buildContextFromMaster(opts: {
164
+ masterContext?: CanvasRetrieve['context'] | null;
165
+ /** `getDefaultCrmShape({ accountName, myUser })` — passed in because it needs Vue injection. */
166
+ crmShape?: Record<string, unknown> | null;
167
+ /** The account chosen in the dialog, already privacy-mode-adjusted (blank name = store no name). */
168
+ account?: {
169
+ id: string;
170
+ name?: string;
171
+ } | null;
172
+ }): Record<string, unknown> | undefined;
173
+ /**
174
+ * The create payload for a pitchdeck built from a master.
175
+ *
176
+ * `is_master: false` is spelled out rather than left to the spread: the fetched master carries
177
+ * `is_master: true`, and the flow also runs FROM the master tab, whose own `creator` exists to make
178
+ * masters. The child is an ordinary deck — it appears on the Pitchdecks tab, it has an account, and
179
+ * it is the thing the rep presents.
180
+ *
181
+ * `is_draft: false` matches the platform's other rep-facing creation flows (the create wizard posts
182
+ * `is_draft: false`). Inheriting the master's flag would silently mark customer-facing decks as
183
+ * drafts whenever the master was left in draft — a master's own status is bookkeeping for a source
184
+ * artifact and says nothing about the deck made from it.
185
+ *
186
+ * `access_type` is deliberately absent: it rides along from the master via the spread, and the host
187
+ * `creator` forces the value it wants (RESTRICTED for rep-created decks).
188
+ */
189
+ export declare function buildCreateFromMasterPayload(opts: {
190
+ master: CanvasRetrieve;
191
+ name: string;
192
+ /** Already privacy-mode-adjusted by the caller (`enable_crm_privacy_mode` blanks the name). */
193
+ account?: {
194
+ id: string;
195
+ name?: string;
196
+ } | null;
197
+ crmShape?: Record<string, unknown> | null;
198
+ }): Omit<CanvasCreateRequest, 'instance_id'>;
199
+ /**
200
+ * Whether the dialog must collect an account before it can create.
201
+ *
202
+ * Follows the platform setting rather than the prototype's always-required Account field: on a
203
+ * non-CRM org there are no accounts to offer, so requiring one would make the whole feature
204
+ * unreachable. Same rule the create modal and the duplicate flow already apply.
205
+ */
206
+ export declare function shouldRequireAccountOnCreateFromMaster(opts: {
207
+ isCRM?: boolean;
208
+ requireAccountOnCanvasCreation?: boolean;
209
+ }): boolean;
210
+ type MasterOption = Pick<CanvasRetrieve, 'id' | 'name'>;
211
+ /**
212
+ * Guarantees the master a row action was fired from is in the offered list.
213
+ *
214
+ * Since PIT-8360 dropped the picker's `is_draft: false` fetch filter the two lists agree, so this is
215
+ * now a guard rather than the everyday path: it still covers a master created or renamed after the
216
+ * list was fetched, and the `fetchAll` truncation at `MAX_FETCH_LIMIT`. Without it the rep could
217
+ * click a master's "Use to create pitchdeck" and land in a picker that neither preselects nor offers
218
+ * it. Sibling of `buildMasterPickerOptions`, which applies the same rule to the Vue dialog's option
219
+ * shape.
220
+ */
221
+ export declare function withPreselectedMaster<T extends {
222
+ id: string;
223
+ }>(masters: T[], preselected?: T | null): T[];
224
+ /**
225
+ * Options for the dialog's master picker.
226
+ *
227
+ * The picker lists every master since PIT-8360 dropped the fetch's `is_draft: false` filter — with
228
+ * the master tab's Ready column gone, nothing can clear the flag, so filtering would permanently
229
+ * hide masters already stored as drafts.
230
+ *
231
+ * **No draft marker on the labels** (PR review). It used to suffix "(Draft)", which was already
232
+ * unreachable — the fetch narrows to `id,name,tags,modified_at`, so every option arrived with
233
+ * `is_draft === undefined`. Restoring it via the `fields` list would have been the wrong repair:
234
+ * masters have no draft state to advertise any more, and a badge on a subset of them describes a
235
+ * distinction nothing in the product can act on. Dropping it also removes the hook a future reader
236
+ * would most likely rebuild a filter around.
237
+ *
238
+ * The preselected master is still injected — see `withPreselectedMaster` for the cases that still
239
+ * reaches.
240
+ */
241
+ export declare function buildMasterPickerOptions(opts: {
242
+ masters: MasterOption[];
243
+ preselected?: MasterOption | null;
244
+ }): {
245
+ label: string;
246
+ value: string;
247
+ }[];
248
+ /** Guards the submit button. A blank name would create a nameless row in the rep's own list. */
249
+ export declare function canSubmitCreateFromMaster(opts: {
250
+ name?: string | null;
251
+ masterId?: string | null;
252
+ isAccountRequired?: boolean;
253
+ accountId?: string | null;
254
+ }): boolean;
255
+ export {};
@@ -0,0 +1,56 @@
1
+ /**
2
+ * PIT-7488 block 7 — pure logic behind the Documents column.
3
+ *
4
+ * Display only. The decision of WHICH masters to render lives server-side, in next-core's
5
+ * `selectCanvasIdsNeedingRender`: the bulk read already computes `is_stale` in SQL, so keeping the
6
+ * policy next to it avoids two copies of the same rule drifting apart in two languages.
7
+ *
8
+ * Kept free of Vue so the state machine is testable on its own.
9
+ */
10
+ /**
11
+ * Mirrors next-core's `MasterDocumentsState`. Duplicated deliberately — next-core types are not
12
+ * published to canvas-ui, and canvas-ui must not import from next-core.
13
+ */
14
+ export interface MasterDocumentsState {
15
+ status: 'pending' | 'rendering' | 'ready' | 'failed';
16
+ pdf_url: string | null;
17
+ pptx_url: string | null;
18
+ rendered_at: string | null;
19
+ is_stale: boolean;
20
+ attempts: number;
21
+ error: string | null;
22
+ }
23
+ export type DocumentsCellState =
24
+ /** No documents row at all — this master has never been rendered. */
25
+ 'none'
26
+ /** A render is queued or running. */
27
+ | 'rendering'
28
+ /** Current documents are available. */
29
+ | 'ready'
30
+ /** Documents are available but out of date; a fresh render is coming. */
31
+ | 'ready_refreshing'
32
+ /** The last render failed. */
33
+ | 'failed';
34
+ /**
35
+ * Must match next-core's `MAX_RENDER_ATTEMPTS`. A client offering a fourth retry would render a
36
+ * button the server refuses to act on.
37
+ */
38
+ export declare const MAX_RENDER_ATTEMPTS = 3;
39
+ /**
40
+ * Maps a documents row onto what the cell should show.
41
+ *
42
+ * The `ready` + stale case deliberately keeps the existing links rather than reverting to a spinner:
43
+ * a slightly out-of-date document a rep can open beats a dead control. Only a genuinely absent
44
+ * artifact shows progress.
45
+ */
46
+ export declare function resolveDocumentsCellState(state: MasterDocumentsState | undefined | null): DocumentsCellState;
47
+ /**
48
+ * Whether to offer Retry. Only for a failed row, and only while the server would still act on it.
49
+ */
50
+ export declare function canRetryDocuments(state: MasterDocumentsState | undefined | null): boolean;
51
+ /**
52
+ * Whether the cell has anything openable. Drives the disabled state of each link independently —
53
+ * the two artifacts have different lifetimes (the PPTX object expires days before the PDF's URL
54
+ * mapping does), so one can be present while the other is not.
55
+ */
56
+ export declare function hasOpenableDocument(state: MasterDocumentsState | undefined | null, format: 'pdf' | 'pptx'): boolean;
@@ -0,0 +1,103 @@
1
+ import { MiniUser } from '../../../types/openapi';
2
+ /** Exactly `Collaboration['user']` and the "Sent to" cell's prop element (PIT-8421; was "Shared with"). */
3
+ export type MasterCanvasShareUser = MiniUser;
4
+ /**
5
+ * PIT-7488 block 5 — may the current user CHANGE this master canvas (Edit / Delete / Freeze)?
6
+ *
7
+ * The owner, **or an instance admin/editor**. That second arm mirrors Django's write gate
8
+ * exactly — `CanvasPermission.has_object_permission` returns True for
9
+ * `is_instance_admin or is_instance_editor or obj.is_owner(user)` — and it matters because the
10
+ * master list is not "only mine" for those roles: admins and editors route through
11
+ * `filter_by_admin_access`, so they see every master in the instance. Gating on ownership alone
12
+ * made the UI STRICTER than the API and silently removed Edit/Delete/Freeze from every master an
13
+ * admin did not personally own.
14
+ *
15
+ * A share recipient never reaches this gate on the SENDER's master: accepting an invitation mints
16
+ * a copy they own, so they meet the ownership arm on their own row and the sender's original is
17
+ * not in their list at all. That is why ng-rest-api#1688's read gates were reverted (#1689) —
18
+ * under invitation semantics there is no "viewing someone else's master" state to widen for.
19
+ *
20
+ * Fails closed, and deliberately not a bare `ownerId === myUserId`: that returns true when both
21
+ * are `undefined`, which would hand a recipient full control of any master whose owner failed to
22
+ * serialise.
23
+ */
24
+ export declare function canManageMasterCanvas(opts: {
25
+ ownerId?: number | null;
26
+ myUserId?: number | null;
27
+ isAdminOrEditor?: boolean;
28
+ }): boolean;
29
+ /**
30
+ * PIT-7488 block 5 — may the current user SHARE this master canvas?
31
+ *
32
+ * The owner ONLY — deliberately narrower than `canManageMasterCanvas`. The next-core route is
33
+ * owner-gated (`master.ownedById !== user.id` → 403), so offering "Share with" to an admin on
34
+ * someone else's master would surface an action the API refuses. Sharing is the owner's call
35
+ * about their own material, not a moderation capability.
36
+ */
37
+ export declare function canShareMasterCanvas(opts: {
38
+ ownerId?: number | null;
39
+ myUserId?: number | null;
40
+ }): boolean;
41
+ /**
42
+ * Per-user outcome of a send, mirroring next-core's `InvitationResult`.
43
+ *
44
+ * `already_invited` is benign (the UNIQUE key makes a repeat a no-op); `not_a_member` means the
45
+ * picker offered someone the server then refused, which the sender needs told.
46
+ */
47
+ export type MasterShareInvitationStatus = 'invited' | 'already_invited' | 'not_a_member' | 'self';
48
+ export interface MasterShareInvitationResult {
49
+ user_id: number;
50
+ status: MasterShareInvitationStatus;
51
+ }
52
+ /** One pending invitation, as the recipient's list renders it. */
53
+ export interface PendingMasterShare {
54
+ share_id: number;
55
+ canvas_id: string;
56
+ canvas_name: string;
57
+ instance_id: string;
58
+ shared_by: MiniUser;
59
+ created_at: string;
60
+ }
61
+ export declare function pendingRowId(shareId: number): string;
62
+ export declare function isPendingRowId(id?: string | number | null): boolean;
63
+ /**
64
+ * The share id behind a pending row id, or `null` if it is not one.
65
+ *
66
+ * Digits only, deliberately: `Number('')` is `0` and `Number.isInteger(0)` is true, so a bare
67
+ * `'pending:'` used to parse to share id 0 — and `Number` also accepts whitespace, `0x` and
68
+ * exponent forms. Share ids are a positive `serial`, so anything else is a bug upstream and must
69
+ * read as "not a pending row" rather than as row 0.
70
+ */
71
+ export declare function pendingShareIdFromRowId(id?: string | number | null): number | null;
72
+ /**
73
+ * Shapes a pending invitation as a table row.
74
+ *
75
+ * `owned_by` carries the SHARER, which is what lets the existing Owner column render "who sent
76
+ * this" with no special-casing — for an invitation the only person worth naming is the sender.
77
+ * `is_master` keeps it consistent with the tab it appears on; every other canvas field is left
78
+ * absent so the remaining cells render empty rather than inventing state the invitation has not
79
+ * got (no tags, no progress, no modified date, no ready/draft status).
80
+ */
81
+ export interface PendingMasterShareRow {
82
+ id: string;
83
+ name: string;
84
+ owned_by: MiniUser;
85
+ is_master: true;
86
+ created_at: string;
87
+ modified_at: string;
88
+ __pendingShare: PendingMasterShare;
89
+ }
90
+ export declare function toPendingRow(share: PendingMasterShare): PendingMasterShareRow;
91
+ /**
92
+ * Pending invitations first, then the user's own masters.
93
+ *
94
+ * Prepended rather than sorted in: an invitation is an inbox item needing a decision, and the
95
+ * table's sort applies to the fetched page — a pending row sorted by `modified_at` would sink
96
+ * below the fold on a rep with many masters and never be seen.
97
+ *
98
+ * Returns the list unchanged when there is nothing pending, so the non-master variants and the
99
+ * common case allocate nothing.
100
+ */
101
+ export declare function mergePendingRows<T extends {
102
+ id: string;
103
+ }>(rows: T[], pending: PendingMasterShare[]): (T | PendingMasterShareRow)[];