canopycms 0.0.57 → 0.0.59
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/ai/json-to-markdown.js +74 -3
- package/dist/ai/json-to-markdown.js.map +1 -1
- package/dist/api/__test__/mock-client.d.ts +9 -5
- package/dist/api/__test__/mock-client.d.ts.map +1 -1
- package/dist/api/__test__/mock-client.js +15 -7
- package/dist/api/__test__/mock-client.js.map +1 -1
- package/dist/api/assets.d.ts +100 -36
- package/dist/api/assets.d.ts.map +1 -1
- package/dist/api/assets.js +338 -51
- package/dist/api/assets.js.map +1 -1
- package/dist/api/client.d.ts +16 -5
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +24 -6
- package/dist/api/client.js.map +1 -1
- package/dist/api/entries.d.ts +4 -4
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js.map +1 -1
- package/dist/api/route-builder.d.ts +9 -0
- package/dist/api/route-builder.d.ts.map +1 -1
- package/dist/api/route-builder.js +1 -0
- package/dist/api/route-builder.js.map +1 -1
- package/dist/api/schema.d.ts +4 -4
- package/dist/api/types.d.ts +11 -1
- package/dist/api/types.d.ts.map +1 -1
- package/dist/assets/asset-prefixes.d.ts +31 -0
- package/dist/assets/asset-prefixes.d.ts.map +1 -0
- package/dist/assets/asset-prefixes.js +20 -0
- package/dist/assets/asset-prefixes.js.map +1 -0
- package/dist/assets/asset-src.d.ts +23 -0
- package/dist/assets/asset-src.d.ts.map +1 -0
- package/dist/assets/asset-src.js +28 -0
- package/dist/assets/asset-src.js.map +1 -0
- package/dist/assets/asset-url.d.ts +35 -0
- package/dist/assets/asset-url.d.ts.map +1 -0
- package/dist/assets/asset-url.js +77 -0
- package/dist/assets/asset-url.js.map +1 -0
- package/dist/assets/factory.d.ts +18 -0
- package/dist/assets/factory.d.ts.map +1 -0
- package/dist/assets/factory.js +42 -0
- package/dist/assets/factory.js.map +1 -0
- package/dist/assets/finalize.d.ts +36 -0
- package/dist/assets/finalize.d.ts.map +1 -0
- package/dist/assets/finalize.js +72 -0
- package/dist/assets/finalize.js.map +1 -0
- package/dist/assets/index.d.ts +20 -0
- package/dist/assets/index.d.ts.map +1 -0
- package/dist/assets/index.js +19 -0
- package/dist/assets/index.js.map +1 -0
- package/dist/assets/keys.d.ts +56 -0
- package/dist/assets/keys.d.ts.map +1 -0
- package/dist/assets/keys.js +88 -0
- package/dist/assets/keys.js.map +1 -0
- package/dist/assets/pipeline.d.ts +50 -0
- package/dist/assets/pipeline.d.ts.map +1 -0
- package/dist/assets/pipeline.js +202 -0
- package/dist/assets/pipeline.js.map +1 -0
- package/dist/assets/store-local.d.ts +84 -0
- package/dist/assets/store-local.d.ts.map +1 -0
- package/dist/assets/store-local.js +254 -0
- package/dist/assets/store-local.js.map +1 -0
- package/dist/assets/store-s3.d.ts +71 -0
- package/dist/assets/store-s3.d.ts.map +1 -0
- package/dist/assets/store-s3.js +183 -0
- package/dist/assets/store-s3.js.map +1 -0
- package/dist/assets/svg-sanitizer.d.ts +37 -0
- package/dist/assets/svg-sanitizer.d.ts.map +1 -0
- package/dist/assets/svg-sanitizer.js +222 -0
- package/dist/assets/svg-sanitizer.js.map +1 -0
- package/dist/assets/transform-directives.d.ts +97 -0
- package/dist/assets/transform-directives.d.ts.map +1 -0
- package/dist/assets/transform-directives.js +267 -0
- package/dist/assets/transform-directives.js.map +1 -0
- package/dist/assets/transform.d.ts +51 -0
- package/dist/assets/transform.d.ts.map +1 -0
- package/dist/assets/transform.js +190 -0
- package/dist/assets/transform.js.map +1 -0
- package/dist/assets/types.d.ts +82 -0
- package/dist/assets/types.d.ts.map +1 -0
- package/dist/assets/types.js +10 -0
- package/dist/assets/types.js.map +1 -0
- package/dist/authorization/groups/schema.d.ts +2 -2
- package/dist/authorization/permissions/schema.d.ts +2 -2
- package/dist/branch-workspace.d.ts.map +1 -1
- package/dist/branch-workspace.js +1 -0
- package/dist/branch-workspace.js.map +1 -1
- package/dist/cli/cli.d.ts +20 -0
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +9561 -246
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/generate-ai-content.js +175 -16
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +29 -5
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/template-files/Dockerfile.cms.template +33 -1
- package/dist/cli/template-files/deploy-cms.yml.template +9 -1
- package/dist/cli/template-files/dockerignore.template +13 -0
- package/dist/cli/template-files/middleware-clerk.ts.template +12 -5
- package/dist/cli/template-files/middleware.ts.template +10 -5
- package/dist/cli/templates.d.ts +1 -0
- package/dist/cli/templates.d.ts.map +1 -1
- package/dist/cli/templates.js +3 -0
- package/dist/cli/templates.js.map +1 -1
- package/dist/config/helpers.d.ts.map +1 -1
- package/dist/config/helpers.js +2 -1
- package/dist/config/helpers.js.map +1 -1
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/schemas/config.d.ts +23 -1
- package/dist/config/schemas/config.d.ts.map +1 -1
- package/dist/config/schemas/config.js +14 -1
- package/dist/config/schemas/config.js.map +1 -1
- package/dist/config/schemas/field.d.ts +38 -3
- package/dist/config/schemas/field.d.ts.map +1 -1
- package/dist/config/schemas/field.js +18 -0
- package/dist/config/schemas/field.js.map +1 -1
- package/dist/config/schemas/media.d.ts +8 -0
- package/dist/config/schemas/media.d.ts.map +1 -1
- package/dist/config/schemas/media.js +9 -0
- package/dist/config/schemas/media.js.map +1 -1
- package/dist/config/types.d.ts +63 -3
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +4 -1
- package/dist/config/types.js.map +1 -1
- package/dist/editor/CanopyEditor.d.ts.map +1 -1
- package/dist/editor/CanopyEditor.js +1 -1
- package/dist/editor/CanopyEditor.js.map +1 -1
- package/dist/editor/Editor.d.ts +2 -0
- package/dist/editor/Editor.d.ts.map +1 -1
- package/dist/editor/Editor.js +82 -80
- package/dist/editor/Editor.js.map +1 -1
- package/dist/editor/FormRenderer.d.ts.map +1 -1
- package/dist/editor/FormRenderer.js +9 -0
- package/dist/editor/FormRenderer.js.map +1 -1
- package/dist/editor/components/EditorSidebar.d.ts +6 -1
- package/dist/editor/components/EditorSidebar.d.ts.map +1 -1
- package/dist/editor/components/EditorSidebar.js +4 -3
- package/dist/editor/components/EditorSidebar.js.map +1 -1
- package/dist/editor/context/AssetContext.d.ts +25 -0
- package/dist/editor/context/AssetContext.d.ts.map +1 -0
- package/dist/editor/context/AssetContext.js +26 -0
- package/dist/editor/context/AssetContext.js.map +1 -0
- package/dist/editor/context/index.d.ts +1 -0
- package/dist/editor/context/index.d.ts.map +1 -1
- package/dist/editor/context/index.js +1 -0
- package/dist/editor/context/index.js.map +1 -1
- package/dist/editor/fields/ImageField.d.ts +22 -0
- package/dist/editor/fields/ImageField.d.ts.map +1 -0
- package/dist/editor/fields/ImageField.js +100 -0
- package/dist/editor/fields/ImageField.js.map +1 -0
- package/dist/editor/fields/MarkdownField.d.ts.map +1 -1
- package/dist/editor/fields/MarkdownField.js +30 -4
- package/dist/editor/fields/MarkdownField.js.map +1 -1
- package/dist/editor/fields/MdxImageDialog.d.ts +16 -0
- package/dist/editor/fields/MdxImageDialog.d.ts.map +1 -0
- package/dist/editor/fields/MdxImageDialog.js +73 -0
- package/dist/editor/fields/MdxImageDialog.js.map +1 -0
- package/dist/editor/media/AssetCard.d.ts +21 -0
- package/dist/editor/media/AssetCard.d.ts.map +1 -0
- package/dist/editor/media/AssetCard.js +41 -0
- package/dist/editor/media/AssetCard.js.map +1 -0
- package/dist/editor/media/CropStep.d.ts +26 -0
- package/dist/editor/media/CropStep.d.ts.map +1 -0
- package/dist/editor/media/CropStep.js +38 -0
- package/dist/editor/media/CropStep.js.map +1 -0
- package/dist/editor/media/MediaLibrary.d.ts +22 -0
- package/dist/editor/media/MediaLibrary.d.ts.map +1 -0
- package/dist/editor/media/MediaLibrary.js +17 -0
- package/dist/editor/media/MediaLibrary.js.map +1 -0
- package/dist/editor/media/MediaLibraryBody.d.ts +17 -0
- package/dist/editor/media/MediaLibraryBody.d.ts.map +1 -0
- package/dist/editor/media/MediaLibraryBody.js +133 -0
- package/dist/editor/media/MediaLibraryBody.js.map +1 -0
- package/dist/editor/media/crop-math.d.ts +37 -0
- package/dist/editor/media/crop-math.d.ts.map +1 -0
- package/dist/editor/media/crop-math.js +62 -0
- package/dist/editor/media/crop-math.js.map +1 -0
- package/dist/editor/media/upload-asset.d.ts +31 -0
- package/dist/editor/media/upload-asset.d.ts.map +1 -0
- package/dist/editor/media/upload-asset.js +56 -0
- package/dist/editor/media/upload-asset.js.map +1 -0
- package/dist/editor/media/upload-constants.d.ts +27 -0
- package/dist/editor/media/upload-constants.d.ts.map +1 -0
- package/dist/editor/media/upload-constants.js +40 -0
- package/dist/editor/media/upload-constants.js.map +1 -0
- package/dist/editor/media/useAssetUpload.d.ts +19 -0
- package/dist/editor/media/useAssetUpload.d.ts.map +1 -0
- package/dist/editor/media/useAssetUpload.js +53 -0
- package/dist/editor/media/useAssetUpload.js.map +1 -0
- package/dist/editor/media/xhr-upload.d.ts +20 -0
- package/dist/editor/media/xhr-upload.d.ts.map +1 -0
- package/dist/editor/media/xhr-upload.js +42 -0
- package/dist/editor/media/xhr-upload.js.map +1 -0
- package/dist/editor/theme.d.ts +2 -1
- package/dist/editor/theme.d.ts.map +1 -1
- package/dist/editor/theme.js +1 -0
- package/dist/editor/theme.js.map +1 -1
- package/dist/entry-schema.d.ts +19 -0
- package/dist/entry-schema.d.ts.map +1 -1
- package/dist/entry-schema.js.map +1 -1
- package/dist/git-manager.d.ts +39 -0
- package/dist/git-manager.d.ts.map +1 -1
- package/dist/git-manager.js +98 -8
- package/dist/git-manager.js.map +1 -1
- package/dist/http/handler.d.ts +5 -2
- package/dist/http/handler.d.ts.map +1 -1
- package/dist/http/handler.js +13 -4
- package/dist/http/handler.js.map +1 -1
- package/dist/http/index.d.ts +2 -2
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +1 -1
- package/dist/http/index.js.map +1 -1
- package/dist/http/router.d.ts +14 -1
- package/dist/http/router.d.ts.map +1 -1
- package/dist/http/router.js +4 -1
- package/dist/http/router.js.map +1 -1
- package/dist/http/types.d.ts +40 -0
- package/dist/http/types.d.ts.map +1 -1
- package/dist/http/types.js +9 -0
- package/dist/http/types.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/schema/schema-store.d.ts +2 -2
- package/dist/server.d.ts +45 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +41 -0
- package/dist/server.js.map +1 -1
- package/dist/settings-workspace.d.ts.map +1 -1
- package/dist/settings-workspace.js +1 -0
- package/dist/settings-workspace.js.map +1 -1
- package/dist/utils/git.d.ts +19 -0
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +47 -0
- package/dist/utils/git.js.map +1 -1
- package/dist/validation/entry-validator.d.ts.map +1 -1
- package/dist/validation/entry-validator.js +56 -1
- package/dist/validation/entry-validator.js.map +1 -1
- package/dist/worker/cms-worker.d.ts +28 -0
- package/dist/worker/cms-worker.d.ts.map +1 -1
- package/dist/worker/cms-worker.js +100 -20
- package/dist/worker/cms-worker.js.map +1 -1
- package/package.json +13 -1
- package/dist/asset-store.d.ts +0 -32
- package/dist/asset-store.d.ts.map +0 -1
- package/dist/asset-store.js +0 -85
- package/dist/asset-store.js.map +0 -1
|
@@ -3,14 +3,29 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
3
3
|
import React, { Suspense, useId, useRef, useCallback, useEffect } from 'react';
|
|
4
4
|
import { Text, Textarea } from '@mantine/core';
|
|
5
5
|
import { InsertEntryLink } from './entry-link/index.js';
|
|
6
|
+
import { MdxImageDialog } from './MdxImageDialog.js';
|
|
7
|
+
import { useApiClient } from '../context/index.js';
|
|
8
|
+
import { uploadAsset } from '../media/upload-asset.js';
|
|
6
9
|
const MDXEditorLazy = React.lazy(async () => {
|
|
7
|
-
const [{ MDXEditor }, { headingsPlugin, listsPlugin, quotePlugin, thematicBreakPlugin, markdownShortcutPlugin, linkPlugin, linkDialogPlugin, imagePlugin, tablePlugin, toolbarPlugin, codeBlockPlugin, codeMirrorPlugin, BoldItalicUnderlineToggles, BlockTypeSelect, ListsToggle, CreateLink, InsertImage, InsertTable, InsertThematicBreak, CodeToggle, InsertCodeBlock, UndoRedo, Separator, insertMarkdown$, usePublisher, },] = await Promise.all([import('@mdxeditor/editor'), import('@mdxeditor/editor')]);
|
|
10
|
+
const [{ MDXEditor }, { headingsPlugin, listsPlugin, quotePlugin, thematicBreakPlugin, markdownShortcutPlugin, linkPlugin, linkDialogPlugin, imagePlugin, tablePlugin, toolbarPlugin, codeBlockPlugin, codeMirrorPlugin, BoldItalicUnderlineToggles, BlockTypeSelect, ListsToggle, CreateLink, InsertImage, InsertTable, InsertThematicBreak, CodeToggle, InsertCodeBlock, UndoRedo, Separator, insertMarkdown$, usePublisher, useCellValues, saveImage$, closeImageDialog$, imageDialogState$, },] = await Promise.all([import('@mdxeditor/editor'), import('@mdxeditor/editor')]);
|
|
8
11
|
/** Toolbar wrapper that provides insertMarkdown to InsertEntryLink */
|
|
9
12
|
const EntryLinkToolbarButton = () => {
|
|
10
13
|
const insertMarkdown = usePublisher(insertMarkdown$);
|
|
11
14
|
return _jsx(InsertEntryLink, { onInsert: insertMarkdown });
|
|
12
15
|
};
|
|
13
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Bridges mdxeditor's realm cells (only reachable once this lazy chunk has
|
|
18
|
+
* loaded) into MdxImageDialog's plain-props interface, so that component
|
|
19
|
+
* itself never imports `@mdxeditor/editor` at runtime. Same pattern as
|
|
20
|
+
* `EntryLinkToolbarButton` above.
|
|
21
|
+
*/
|
|
22
|
+
const MdxImageDialogBridge = () => {
|
|
23
|
+
const [state] = useCellValues(imageDialogState$);
|
|
24
|
+
const saveImage = usePublisher(saveImage$);
|
|
25
|
+
const closeImageDialog = usePublisher(closeImageDialog$);
|
|
26
|
+
return _jsx(MdxImageDialog, { state: state, onSave: saveImage, onClose: closeImageDialog });
|
|
27
|
+
};
|
|
28
|
+
const WrappedEditor = ({ markdown, onChange, editorRef, imageUploadHandler }) => {
|
|
14
29
|
return (_jsx(MDXEditor, { ref: editorRef, markdown: markdown, onChange: onChange, plugins: [
|
|
15
30
|
headingsPlugin(),
|
|
16
31
|
listsPlugin(),
|
|
@@ -19,7 +34,7 @@ const MDXEditorLazy = React.lazy(async () => {
|
|
|
19
34
|
markdownShortcutPlugin(),
|
|
20
35
|
linkPlugin(),
|
|
21
36
|
linkDialogPlugin(),
|
|
22
|
-
imagePlugin(),
|
|
37
|
+
imagePlugin({ imageUploadHandler, ImageDialog: MdxImageDialogBridge }),
|
|
23
38
|
tablePlugin(),
|
|
24
39
|
codeBlockPlugin({ defaultCodeBlockLanguage: '' }),
|
|
25
40
|
codeMirrorPlugin({
|
|
@@ -86,6 +101,17 @@ export const MarkdownField = ({ id, label, value, onChange, dataCanopyField, })
|
|
|
86
101
|
const inputId = id ?? generatedId;
|
|
87
102
|
const editorRef = useRef(null);
|
|
88
103
|
const lastExternalValue = useRef(value);
|
|
104
|
+
const apiClient = useApiClient();
|
|
105
|
+
// Drives both MDXEditor's own drag/drop/paste upload flow and the Upload
|
|
106
|
+
// tab in our custom image dialog (MdxImageDialog) via the SAME presign/
|
|
107
|
+
// finalize-or-proxied pipeline used everywhere else in the editor (see
|
|
108
|
+
// media/upload-asset.ts). Stable across renders (memoized on the API
|
|
109
|
+
// client, which ApiClientProvider itself memoizes) so MDXEditor's plugin
|
|
110
|
+
// list doesn't churn on every keystroke.
|
|
111
|
+
const imageUploadHandler = useCallback(async (file) => {
|
|
112
|
+
const asset = await uploadAsset(apiClient, file);
|
|
113
|
+
return asset.src;
|
|
114
|
+
}, [apiClient]);
|
|
89
115
|
// Sync external value changes into the editor (e.g., undo, reset, load)
|
|
90
116
|
useEffect(() => {
|
|
91
117
|
if (value !== lastExternalValue.current && editorRef.current) {
|
|
@@ -97,7 +123,7 @@ export const MarkdownField = ({ id, label, value, onChange, dataCanopyField, })
|
|
|
97
123
|
lastExternalValue.current = newValue;
|
|
98
124
|
onChange(newValue);
|
|
99
125
|
}, [onChange]);
|
|
100
|
-
return (_jsxs("div", { id: inputId, "data-canopy-field": dataCanopyField, className: "canopy-markdown-field", children: [label && (_jsx(Text, { size: "sm", fw: 500, mb: 4, children: label })), _jsx(EditorContentStyles, {}), _jsx("div", { style: editorWrapperStyle, children: _jsx(Suspense, { fallback: _jsx(FallbackTextarea, { value: value, onChange: onChange }), children: _jsx(MDXEditorLazy, { markdown: value, onChange: handleChange, editorRef: editorRef }) }) })] }));
|
|
126
|
+
return (_jsxs("div", { id: inputId, "data-canopy-field": dataCanopyField, className: "canopy-markdown-field", children: [label && (_jsx(Text, { size: "sm", fw: 500, mb: 4, children: label })), _jsx(EditorContentStyles, {}), _jsx("div", { style: editorWrapperStyle, children: _jsx(Suspense, { fallback: _jsx(FallbackTextarea, { value: value, onChange: onChange }), children: _jsx(MDXEditorLazy, { markdown: value, onChange: handleChange, editorRef: editorRef, imageUploadHandler: imageUploadHandler }) }) })] }));
|
|
101
127
|
};
|
|
102
128
|
export default MarkdownField;
|
|
103
129
|
//# sourceMappingURL=MarkdownField.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkdownField.js","sourceRoot":"","sources":["../../../src/editor/fields/MarkdownField.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAE9E,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAG9C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"MarkdownField.js","sourceRoot":"","sources":["../../../src/editor/fields/MarkdownField.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { EditingImageDialogState, InactiveImageDialogState, NewImageDialogState, SaveImageParameters } from '@mdxeditor/editor';
|
|
3
|
+
export type MdxImageDialogState = InactiveImageDialogState | NewImageDialogState | EditingImageDialogState;
|
|
4
|
+
export interface MdxImageDialogProps {
|
|
5
|
+
state: MdxImageDialogState;
|
|
6
|
+
onSave: (params: SaveImageParameters) => void;
|
|
7
|
+
onClose: () => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Custom MDXEditor image dialog (Upload / From library / By URL), replacing
|
|
11
|
+
* the stock upload-or-URL dialog. Wired in via `imagePlugin({ ImageDialog })`
|
|
12
|
+
* in MarkdownField.tsx.
|
|
13
|
+
*/
|
|
14
|
+
export declare const MdxImageDialog: React.FC<MdxImageDialogProps>;
|
|
15
|
+
export default MdxImageDialog;
|
|
16
|
+
//# sourceMappingURL=MdxImageDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MdxImageDialog.d.ts","sourceRoot":"","sources":["../../../src/editor/fields/MdxImageDialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAA;AAalD,OAAO,KAAK,EACV,uBAAuB,EACvB,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,mBAAmB,CAAA;AAO1B,MAAM,MAAM,mBAAmB,GAC3B,wBAAwB,GACxB,mBAAmB,GACnB,uBAAuB,CAAA;AAE3B,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,mBAAmB,CAAA;IAC1B,MAAM,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAA;IAC7C,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAMD;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA+JxD,CAAA;AAED,eAAe,cAAc,CAAA"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { Alert, Button, Group, Modal, Progress, Stack, Tabs, Text, TextInput } from '@mantine/core';
|
|
5
|
+
import { Dropzone } from '@mantine/dropzone';
|
|
6
|
+
import { IconAlertCircle, IconUpload } from '@tabler/icons-react';
|
|
7
|
+
import { MediaLibraryBody } from '../media/MediaLibraryBody.js';
|
|
8
|
+
import { useAssetUpload } from '../media/useAssetUpload.js';
|
|
9
|
+
import { ACCEPTED_IMAGE_MIME_TYPES, MAX_UPLOAD_BYTES } from '../media/upload-constants.js';
|
|
10
|
+
const LIBRARY_PANEL_HEIGHT = 360;
|
|
11
|
+
/**
|
|
12
|
+
* Custom MDXEditor image dialog (Upload / From library / By URL), replacing
|
|
13
|
+
* the stock upload-or-URL dialog. Wired in via `imagePlugin({ ImageDialog })`
|
|
14
|
+
* in MarkdownField.tsx.
|
|
15
|
+
*/
|
|
16
|
+
export const MdxImageDialog = ({ state, onSave, onClose }) => {
|
|
17
|
+
const [tab, setTab] = useState('upload');
|
|
18
|
+
const [altText, setAltText] = useState('');
|
|
19
|
+
const [urlValue, setUrlValue] = useState('');
|
|
20
|
+
const [dropError, setDropError] = useState(null);
|
|
21
|
+
const upload = useAssetUpload();
|
|
22
|
+
const opened = state.type !== 'inactive';
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (state.type === 'editing') {
|
|
25
|
+
setAltText(state.initialValues.altText ?? '');
|
|
26
|
+
setUrlValue(state.initialValues.src ?? '');
|
|
27
|
+
// Editing an existing image: show its current src/alt on the URL tab
|
|
28
|
+
// rather than defaulting to Upload, which would suggest replacing it.
|
|
29
|
+
setTab('url');
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
setAltText('');
|
|
33
|
+
setUrlValue('');
|
|
34
|
+
setTab('upload');
|
|
35
|
+
}
|
|
36
|
+
setDropError(null);
|
|
37
|
+
upload.reset();
|
|
38
|
+
// Reset local state whenever the dialog's target state changes identity
|
|
39
|
+
// (opened for a new insert, opened to edit a different node, or closed).
|
|
40
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
41
|
+
}, [state]);
|
|
42
|
+
const handleSave = (src) => {
|
|
43
|
+
onSave({ src, altText });
|
|
44
|
+
onClose();
|
|
45
|
+
};
|
|
46
|
+
const handleDrop = async (files) => {
|
|
47
|
+
const file = files[0];
|
|
48
|
+
if (!file)
|
|
49
|
+
return;
|
|
50
|
+
const asset = await upload.upload(file);
|
|
51
|
+
if (asset)
|
|
52
|
+
handleSave(asset.src);
|
|
53
|
+
};
|
|
54
|
+
const handleReject = (rejections) => {
|
|
55
|
+
setDropError(rejections[0]?.errors[0]?.message ?? 'File rejected');
|
|
56
|
+
};
|
|
57
|
+
const handlePickFromLibrary = (asset) => {
|
|
58
|
+
handleSave(asset.src);
|
|
59
|
+
};
|
|
60
|
+
const handleUrlSubmit = () => {
|
|
61
|
+
const trimmed = urlValue.trim();
|
|
62
|
+
if (!trimmed)
|
|
63
|
+
return;
|
|
64
|
+
handleSave(trimmed);
|
|
65
|
+
};
|
|
66
|
+
return (_jsx(Modal, { opened: opened, onClose: onClose, title: "Insert image", size: "lg", overlayProps: { blur: 2 }, "data-testid": "mdx-image-dialog", children: _jsxs(Stack, { gap: "sm", children: [_jsx(TextInput, { label: "Alt text", value: altText, onChange: (event) => setAltText(event.currentTarget.value), "data-testid": "mdx-image-dialog-alt" }), _jsxs(Tabs, { value: tab, onChange: (next) => {
|
|
67
|
+
if (next)
|
|
68
|
+
setTab(next);
|
|
69
|
+
}, children: [_jsxs(Tabs.List, { children: [_jsx(Tabs.Tab, { value: "upload", "data-testid": "mdx-image-dialog-tab-upload", children: "Upload" }), _jsx(Tabs.Tab, { value: "library", "data-testid": "mdx-image-dialog-tab-library", children: "From library" }), _jsx(Tabs.Tab, { value: "url", "data-testid": "mdx-image-dialog-tab-url", children: "By URL" })] }), _jsx(Tabs.Panel, { value: "upload", pt: "sm", children: _jsxs(Stack, { gap: "xs", children: [_jsx(Dropzone, { onDrop: (files) => void handleDrop(files), onReject: handleReject, maxSize: MAX_UPLOAD_BYTES, accept: ACCEPTED_IMAGE_MIME_TYPES, loading: upload.uploading, multiple: false, "data-testid": "mdx-image-dialog-dropzone", children: _jsxs(Group, { justify: "center", gap: "xs", py: "sm", style: { pointerEvents: 'none' }, children: [_jsx(IconUpload, { size: 20 }), _jsx(Text, { size: "sm", children: "Drop an image here, or click to browse" })] }) }), upload.uploading &&
|
|
70
|
+
(upload.progress !== null ? (_jsx(Progress, { value: upload.progress * 100, size: "sm" })) : (_jsx(Progress, { value: 100, size: "sm", animated: true }))), (upload.error || dropError) && (_jsx(Alert, { icon: _jsx(IconAlertCircle, { size: 16 }), color: "red", children: upload.error || dropError }))] }) }), _jsx(Tabs.Panel, { value: "library", pt: "sm", children: _jsx("div", { style: { height: LIBRARY_PANEL_HEIGHT }, children: _jsx(MediaLibraryBody, { opened: tab === 'library', mode: "picker", onSelect: handlePickFromLibrary }) }) }), _jsx(Tabs.Panel, { value: "url", pt: "sm", children: _jsxs(Stack, { gap: "xs", children: [_jsx(TextInput, { label: "Image URL", placeholder: "https://example.com/image.png", value: urlValue, onChange: (event) => setUrlValue(event.currentTarget.value), "data-testid": "mdx-image-dialog-url" }), _jsx(Group, { justify: "flex-end", children: _jsx(Button, { onClick: handleUrlSubmit, disabled: !urlValue.trim(), "data-testid": "mdx-image-dialog-url-submit", children: "Insert" }) })] }) })] }), _jsx(Group, { justify: "flex-end", children: _jsx(Button, { variant: "default", onClick: onClose, children: "Cancel" }) })] }) }));
|
|
71
|
+
};
|
|
72
|
+
export default MdxImageDialog;
|
|
73
|
+
//# sourceMappingURL=MdxImageDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MdxImageDialog.js","sourceRoot":"","sources":["../../../src/editor/fields/MdxImageDialog.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AssetRecord } from '../../api';
|
|
3
|
+
export interface AssetCardProps {
|
|
4
|
+
asset: AssetRecord;
|
|
5
|
+
/** `media.publicBaseUrl` - see AssetContext. */
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
/** Present in picker mode - clicking the card selects the asset. */
|
|
8
|
+
onSelect?: (asset: AssetRecord) => void;
|
|
9
|
+
/** Present only for admins in manage mode - renders the trash button. */
|
|
10
|
+
onDelete?: (asset: AssetRecord) => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* One thumbnail card in the MediaLibrary grid. Raster and svg assets both go
|
|
14
|
+
* through `assetUrl()` unmodified - for svg (a static, non-transform src)
|
|
15
|
+
* `assetUrl` ignores the `width` option and just applies `baseUrl`, which is
|
|
16
|
+
* exactly the behavior wanted here. PDFs have no image to preview, so they
|
|
17
|
+
* render a file-type icon instead.
|
|
18
|
+
*/
|
|
19
|
+
export declare const AssetCard: React.FC<AssetCardProps>;
|
|
20
|
+
export default AssetCard;
|
|
21
|
+
//# sourceMappingURL=AssetCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AssetCard.d.ts","sourceRoot":"","sources":["../../../src/editor/media/AssetCard.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG5C,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,WAAW,CAAA;IAClB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAA;IACvC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAA;CACxC;AAID;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA2E9C,CAAA;AAED,eAAe,SAAS,CAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { ActionIcon, Card, Text, Tooltip } from '@mantine/core';
|
|
4
|
+
import { IconFileTypePdf, IconTrash } from '@tabler/icons-react';
|
|
5
|
+
import { assetUrl } from '../../assets/asset-url.js';
|
|
6
|
+
const THUMBNAIL_WIDTH = 160;
|
|
7
|
+
/**
|
|
8
|
+
* One thumbnail card in the MediaLibrary grid. Raster and svg assets both go
|
|
9
|
+
* through `assetUrl()` unmodified - for svg (a static, non-transform src)
|
|
10
|
+
* `assetUrl` ignores the `width` option and just applies `baseUrl`, which is
|
|
11
|
+
* exactly the behavior wanted here. PDFs have no image to preview, so they
|
|
12
|
+
* render a file-type icon instead.
|
|
13
|
+
*/
|
|
14
|
+
export const AssetCard = ({ asset, baseUrl, onSelect, onDelete }) => {
|
|
15
|
+
const uploadedDate = new Date(asset.uploadedAt).toLocaleDateString();
|
|
16
|
+
const handleKeyDown = (event) => {
|
|
17
|
+
if (!onSelect)
|
|
18
|
+
return;
|
|
19
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
20
|
+
event.preventDefault();
|
|
21
|
+
onSelect(asset);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
return (_jsxs(Card, { withBorder: true, radius: "md", padding: "xs", "data-testid": `asset-card-${asset.hash32}`, style: { position: 'relative', cursor: onSelect ? 'pointer' : undefined }, onClick: onSelect ? () => onSelect(asset) : undefined,
|
|
25
|
+
// Selection is otherwise a bare click handler on a non-interactive
|
|
26
|
+
// element, unreachable from the keyboard - role="button" + tabIndex
|
|
27
|
+
// makes it focusable and announced correctly, and onKeyDown mirrors
|
|
28
|
+
// native <button> Enter/Space activation.
|
|
29
|
+
role: onSelect ? 'button' : undefined, tabIndex: onSelect ? 0 : undefined, onKeyDown: onSelect ? handleKeyDown : undefined, children: [onDelete && (_jsx(ActionIcon, { variant: "filled", color: "red", size: "sm", radius: "xl", style: { position: 'absolute', top: 4, right: 4, zIndex: 1 }, "aria-label": `Delete ${asset.filename}`, "data-testid": `asset-card-delete-${asset.hash32}`, onClick: (event) => {
|
|
30
|
+
event.stopPropagation();
|
|
31
|
+
onDelete(asset);
|
|
32
|
+
}, children: _jsx(IconTrash, { size: 14 }) })), _jsx(Card.Section, { children: asset.kind === 'pdf' ? (_jsx("div", { style: {
|
|
33
|
+
height: 100,
|
|
34
|
+
display: 'flex',
|
|
35
|
+
alignItems: 'center',
|
|
36
|
+
justifyContent: 'center',
|
|
37
|
+
background: 'var(--mantine-color-gray-1)',
|
|
38
|
+
}, children: _jsx(IconFileTypePdf, { size: 40, stroke: 1.5 }) })) : (_jsx("img", { src: assetUrl(asset, { width: THUMBNAIL_WIDTH, baseUrl }), alt: asset.filename, style: { width: '100%', height: 100, objectFit: 'cover', display: 'block' } })) }), _jsx(Tooltip, { label: asset.filename, openDelay: 400, children: _jsx(Text, { size: "xs", fw: 500, truncate: true, mt: 4, children: asset.slug }) }), _jsx(Text, { size: "xs", c: "dimmed", children: uploadedDate })] }));
|
|
39
|
+
};
|
|
40
|
+
export default AssetCard;
|
|
41
|
+
//# sourceMappingURL=AssetCard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AssetCard.js","sourceRoot":"","sources":["../../../src/editor/media/AssetCard.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { CropRect } from '../../assets/transform-directives';
|
|
3
|
+
export interface CropStepProps {
|
|
4
|
+
opened: boolean;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
/** Full-frame image src to crop - `assetUrl()` with no crop directive, so the user always crops the original frame. */
|
|
7
|
+
imageSrc: string;
|
|
8
|
+
/** Numeric aspect ratio (width/height) parsed from the field config's "W:H" string. */
|
|
9
|
+
aspect: number;
|
|
10
|
+
/** Existing crop rect, if re-cropping - seeds react-easy-crop's initial selection (best effort). */
|
|
11
|
+
initialCrop?: CropRect;
|
|
12
|
+
onConfirm: (rect: CropRect) => void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* react-easy-crop wrapped in a Modal for the ImageField crop step. Percentage
|
|
16
|
+
* -> normalized-rect conversion is delegated to crop-math.ts's pure,
|
|
17
|
+
* independently-unit-tested `cropAreaPercentToRect`.
|
|
18
|
+
*
|
|
19
|
+
* The pan/zoom/pending-selection state lives in `CropStepBody`, mounted only
|
|
20
|
+
* while `opened` and keyed on `imageSrc` - so a fresh crop session always
|
|
21
|
+
* starts from fresh state (React remounts on key change) without an effect
|
|
22
|
+
* that would otherwise need to call `setState` synchronously to reset it.
|
|
23
|
+
*/
|
|
24
|
+
export declare const CropStep: React.FC<CropStepProps>;
|
|
25
|
+
export default CropStep;
|
|
26
|
+
//# sourceMappingURL=CropStep.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CropStep.d.ts","sourceRoot":"","sources":["../../../src/editor/media/CropStep.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAKvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAA;AAGjE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,uHAAuH;IACvH,QAAQ,EAAE,MAAM,CAAA;IAChB,uFAAuF;IACvF,MAAM,EAAE,MAAM,CAAA;IACd,oGAAoG;IACpG,WAAW,CAAC,EAAE,QAAQ,CAAA;IACtB,SAAS,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAA;CACpC;AAMD;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CA6B5C,CAAA;AAqED,eAAe,QAAQ,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { Button, Group, Modal, Slider, Stack, Text } from '@mantine/core';
|
|
5
|
+
import Cropper from 'react-easy-crop';
|
|
6
|
+
import { cropAreaPercentToRect, cropRectToAreaPercent } from './crop-math.js';
|
|
7
|
+
const MIN_ZOOM = 1;
|
|
8
|
+
const MAX_ZOOM = 3;
|
|
9
|
+
const ZOOM_STEP = 0.05;
|
|
10
|
+
/**
|
|
11
|
+
* react-easy-crop wrapped in a Modal for the ImageField crop step. Percentage
|
|
12
|
+
* -> normalized-rect conversion is delegated to crop-math.ts's pure,
|
|
13
|
+
* independently-unit-tested `cropAreaPercentToRect`.
|
|
14
|
+
*
|
|
15
|
+
* The pan/zoom/pending-selection state lives in `CropStepBody`, mounted only
|
|
16
|
+
* while `opened` and keyed on `imageSrc` - so a fresh crop session always
|
|
17
|
+
* starts from fresh state (React remounts on key change) without an effect
|
|
18
|
+
* that would otherwise need to call `setState` synchronously to reset it.
|
|
19
|
+
*/
|
|
20
|
+
export const CropStep = ({ opened, onClose, imageSrc, aspect, initialCrop, onConfirm, }) => {
|
|
21
|
+
return (_jsx(Modal, { opened: opened, onClose: onClose, title: "Crop image", size: "lg", overlayProps: { blur: 2 }, "data-testid": "crop-step-modal", children: opened && (_jsx(CropStepBody, { imageSrc: imageSrc, aspect: aspect, initialCrop: initialCrop, onConfirm: onConfirm, onClose: onClose }, imageSrc)) }));
|
|
22
|
+
};
|
|
23
|
+
const CropStepBody = ({ imageSrc, aspect, initialCrop, onConfirm, onClose, }) => {
|
|
24
|
+
const [crop, setCrop] = useState({ x: 0, y: 0 });
|
|
25
|
+
const [zoom, setZoom] = useState(1);
|
|
26
|
+
const [pendingArea, setPendingArea] = useState(null);
|
|
27
|
+
const handleConfirm = () => {
|
|
28
|
+
if (!pendingArea)
|
|
29
|
+
return;
|
|
30
|
+
const rect = cropAreaPercentToRect(pendingArea);
|
|
31
|
+
if (rect)
|
|
32
|
+
onConfirm(rect);
|
|
33
|
+
};
|
|
34
|
+
const initialCroppedAreaPercentages = initialCrop ? cropRectToAreaPercent(initialCrop) : undefined;
|
|
35
|
+
return (_jsxs(Stack, { gap: "md", children: [_jsx("div", { style: { position: 'relative', width: '100%', height: 360, background: '#000' }, children: _jsx(Cropper, { image: imageSrc, crop: crop, zoom: zoom, aspect: aspect, initialCroppedAreaPercentages: initialCroppedAreaPercentages, onCropChange: setCrop, onZoomChange: setZoom, onCropComplete: (croppedArea) => setPendingArea(croppedArea) }) }), _jsxs(Group, { gap: "sm", align: "center", children: [_jsx(Text, { size: "sm", w: 50, children: "Zoom" }), _jsx(Slider, { style: { flex: 1 }, min: MIN_ZOOM, max: MAX_ZOOM, step: ZOOM_STEP, value: zoom, onChange: setZoom, label: (value) => `${value.toFixed(2)}x` })] }), _jsxs(Group, { justify: "flex-end", children: [_jsx(Button, { variant: "default", onClick: onClose, children: "Cancel" }), _jsx(Button, { onClick: handleConfirm, disabled: !pendingArea, "data-testid": "crop-step-apply", children: "Apply crop" })] })] }));
|
|
36
|
+
};
|
|
37
|
+
export default CropStep;
|
|
38
|
+
//# sourceMappingURL=CropStep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CropStep.js","sourceRoot":"","sources":["../../../src/editor/media/CropStep.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AssetRecord } from '../../api';
|
|
3
|
+
export interface MediaLibraryProps {
|
|
4
|
+
opened: boolean;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
/**
|
|
7
|
+
* 'manage': right-side Drawer opened from the EditorSidebar Settings menu.
|
|
8
|
+
* 'picker': Modal used by ImageField ("Browse library"/"Replace") and the
|
|
9
|
+
* MDX image dialog's "From library" tab.
|
|
10
|
+
*/
|
|
11
|
+
mode: 'manage' | 'picker';
|
|
12
|
+
/** Required in picker mode - called with the chosen asset when a card is clicked. */
|
|
13
|
+
onSelect?: (asset: AssetRecord) => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* One component, two presentations, sharing the same grid/upload/filter/
|
|
17
|
+
* pagination/delete core (MediaLibraryBody) - see
|
|
18
|
+
* .claude/future-tasks/assets-media-system.md "MediaManager design".
|
|
19
|
+
*/
|
|
20
|
+
export declare const MediaLibrary: React.FC<MediaLibraryProps>;
|
|
21
|
+
export default MediaLibrary;
|
|
22
|
+
//# sourceMappingURL=MediaLibrary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaLibrary.d.ts","sourceRoot":"","sources":["../../../src/editor/media/MediaLibrary.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG5C,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB;;;;OAIG;IACH,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAA;IACzB,qFAAqF;IACrF,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAA;CACxC;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAqCpD,CAAA;AAED,eAAe,YAAY,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Drawer, Modal, Text, Title } from '@mantine/core';
|
|
4
|
+
import { MediaLibraryBody } from './MediaLibraryBody.js';
|
|
5
|
+
/**
|
|
6
|
+
* One component, two presentations, sharing the same grid/upload/filter/
|
|
7
|
+
* pagination/delete core (MediaLibraryBody) - see
|
|
8
|
+
* .claude/future-tasks/assets-media-system.md "MediaManager design".
|
|
9
|
+
*/
|
|
10
|
+
export const MediaLibrary = ({ opened, onClose, mode, onSelect }) => {
|
|
11
|
+
if (mode === 'picker') {
|
|
12
|
+
return (_jsx(Modal, { opened: opened, onClose: onClose, title: "Media library", size: "lg", overlayProps: { blur: 2 }, "data-testid": "media-library-picker", children: _jsx(MediaLibraryBody, { opened: opened, mode: "picker", onSelect: onSelect }) }));
|
|
13
|
+
}
|
|
14
|
+
return (_jsx(Drawer, { opened: opened, onClose: onClose, position: "right", title: _jsxs("div", { children: [_jsx(Title, { order: 4, children: "Media library" }), _jsx(Text, { size: "xs", c: "dimmed", children: "Upload and manage images and PDFs" })] }), padding: "md", size: 700, overlayProps: { blur: 2 }, "data-testid": "media-library-manage", children: _jsx(MediaLibraryBody, { opened: opened, mode: "manage" }) }));
|
|
15
|
+
};
|
|
16
|
+
export default MediaLibrary;
|
|
17
|
+
//# sourceMappingURL=MediaLibrary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaLibrary.js","sourceRoot":"","sources":["../../../src/editor/media/MediaLibrary.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAIZ,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAG1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAerD;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAgC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;IAC/F,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,OAAO,CACL,KAAC,KAAK,IACJ,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,KAAK,EAAC,eAAe,EACrB,IAAI,EAAC,IAAI,EACT,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,iBACb,sBAAsB,YAElC,KAAC,gBAAgB,IAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAC,QAAQ,EAAC,QAAQ,EAAE,QAAQ,GAAI,GAChE,CACT,CAAA;IACH,CAAC;IAED,OAAO,CACL,KAAC,MAAM,IACL,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAC,OAAO,EAChB,KAAK,EACH,0BACE,KAAC,KAAK,IAAC,KAAK,EAAE,CAAC,8BAAuB,EACtC,KAAC,IAAI,IAAC,IAAI,EAAC,IAAI,EAAC,CAAC,EAAC,QAAQ,kDAEnB,IACH,EAER,OAAO,EAAC,IAAI,EACZ,IAAI,EAAE,GAAG,EACT,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,iBACb,sBAAsB,YAElC,KAAC,gBAAgB,IAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAC,QAAQ,GAAG,GAC3C,CACV,CAAA;AACH,CAAC,CAAA;AAED,eAAe,YAAY,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AssetRecord } from '../../api';
|
|
3
|
+
export interface MediaLibraryBodyProps {
|
|
4
|
+
/** Whether the enclosing Drawer/Modal is open - gates the (re)fetch of the first page on each open. */
|
|
5
|
+
opened: boolean;
|
|
6
|
+
mode: 'manage' | 'picker';
|
|
7
|
+
/** Present in picker mode - clicking a card (or completing an upload) selects the asset. */
|
|
8
|
+
onSelect?: (asset: AssetRecord) => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Shared grid/upload/filter/pagination/delete core for both MediaLibrary
|
|
12
|
+
* presentations (Drawer "manage" mode, Modal "picker" mode) - see
|
|
13
|
+
* MediaLibrary.tsx for the two wrappers.
|
|
14
|
+
*/
|
|
15
|
+
export declare const MediaLibraryBody: React.FC<MediaLibraryBodyProps>;
|
|
16
|
+
export default MediaLibraryBody;
|
|
17
|
+
//# sourceMappingURL=MediaLibraryBody.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaLibraryBody.d.ts","sourceRoot":"","sources":["../../../src/editor/media/MediaLibraryBody.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA2C,MAAM,OAAO,CAAA;AAkB/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAiB5C,MAAM,WAAW,qBAAqB;IACpC,uGAAuG;IACvG,MAAM,EAAE,OAAO,CAAA;IACf,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAA;IACzB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAA;CACxC;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA2M5D,CAAA;AAED,eAAe,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
4
|
+
import { Alert, Button, Group, Loader, Progress, ScrollArea, SimpleGrid, Stack, Text, TextInput, } from '@mantine/core';
|
|
5
|
+
import { Dropzone } from '@mantine/dropzone';
|
|
6
|
+
import { modals } from '@mantine/modals';
|
|
7
|
+
import { IconAlertCircle, IconUpload } from '@tabler/icons-react';
|
|
8
|
+
import { getErrorMessage } from '../../utils/error.js';
|
|
9
|
+
// Import directly from helpers (not the authorization barrel) to keep server-only
|
|
10
|
+
// authorization code out of this client bundle - matches BranchManager's convention.
|
|
11
|
+
import { isAdmin } from '../../authorization/helpers.js';
|
|
12
|
+
import { useApiClient, useAssetContext } from '../context/index.js';
|
|
13
|
+
import { useUserContext } from '../hooks/index.js';
|
|
14
|
+
import { AssetCard } from './AssetCard.js';
|
|
15
|
+
import { useAssetUpload } from './useAssetUpload.js';
|
|
16
|
+
import { ACCEPTED_ASSET_MIME_TYPES, ACCEPTED_IMAGE_MIME_TYPES, MAX_UPLOAD_BYTES, } from './upload-constants.js';
|
|
17
|
+
const PAGE_SIZE = 40;
|
|
18
|
+
/**
|
|
19
|
+
* Shared grid/upload/filter/pagination/delete core for both MediaLibrary
|
|
20
|
+
* presentations (Drawer "manage" mode, Modal "picker" mode) - see
|
|
21
|
+
* MediaLibrary.tsx for the two wrappers.
|
|
22
|
+
*/
|
|
23
|
+
export const MediaLibraryBody = ({ opened, mode, onSelect }) => {
|
|
24
|
+
const client = useApiClient();
|
|
25
|
+
const { baseUrl } = useAssetContext();
|
|
26
|
+
const { userContext } = useUserContext();
|
|
27
|
+
const canDelete = mode === 'manage' && isAdmin(userContext?.groups);
|
|
28
|
+
const upload = useAssetUpload();
|
|
29
|
+
// `picker` mode is used exclusively by ImageField and the MDX image dialog
|
|
30
|
+
// (see MediaLibraryProps.mode's doc comment) - both image-only contexts.
|
|
31
|
+
// `manage` mode (the Editor's Media Library drawer) keeps accepting PDFs.
|
|
32
|
+
const imageOnly = mode === 'picker';
|
|
33
|
+
const [assets, setAssets] = useState([]);
|
|
34
|
+
const [nextCursor, setNextCursor] = useState(undefined);
|
|
35
|
+
const [loading, setLoading] = useState(false);
|
|
36
|
+
const [loadingMore, setLoadingMore] = useState(false);
|
|
37
|
+
const [listError, setListError] = useState(null);
|
|
38
|
+
const [filterText, setFilterText] = useState('');
|
|
39
|
+
const loadFirstPage = useCallback(async () => {
|
|
40
|
+
setLoading(true);
|
|
41
|
+
setListError(null);
|
|
42
|
+
try {
|
|
43
|
+
const result = await client.assets.list({ limit: String(PAGE_SIZE) });
|
|
44
|
+
if (!result.ok || !result.data) {
|
|
45
|
+
setListError(result.error || 'Failed to load assets');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
setAssets(result.data.assets);
|
|
49
|
+
setNextCursor(result.data.nextCursor);
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
setListError(getErrorMessage(err));
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
setLoading(false);
|
|
56
|
+
}
|
|
57
|
+
}, [client]);
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (!opened)
|
|
60
|
+
return;
|
|
61
|
+
void loadFirstPage();
|
|
62
|
+
// Refetch only when the drawer/modal (re)opens, not on every render where
|
|
63
|
+
// loadFirstPage's identity happens to change.
|
|
64
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
65
|
+
}, [opened]);
|
|
66
|
+
const handleLoadMore = async () => {
|
|
67
|
+
if (!nextCursor)
|
|
68
|
+
return;
|
|
69
|
+
setLoadingMore(true);
|
|
70
|
+
setListError(null);
|
|
71
|
+
try {
|
|
72
|
+
const result = await client.assets.list({ cursor: nextCursor, limit: String(PAGE_SIZE) });
|
|
73
|
+
if (!result.ok || !result.data) {
|
|
74
|
+
setListError(result.error || 'Failed to load more assets');
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const page = result.data;
|
|
78
|
+
setAssets((prev) => [...prev, ...page.assets]);
|
|
79
|
+
setNextCursor(page.nextCursor);
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
setListError(getErrorMessage(err));
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
setLoadingMore(false);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const handleDrop = async (files) => {
|
|
89
|
+
const file = files[0];
|
|
90
|
+
if (!file)
|
|
91
|
+
return;
|
|
92
|
+
const asset = await upload.upload(file);
|
|
93
|
+
if (asset) {
|
|
94
|
+
setAssets((prev) => [asset, ...prev]);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const handleReject = (rejections) => {
|
|
98
|
+
setListError(rejections[0]?.errors[0]?.message ?? 'File rejected');
|
|
99
|
+
};
|
|
100
|
+
const handleDelete = async (asset) => {
|
|
101
|
+
const result = await client.assets.delete({ key: asset.hash32 });
|
|
102
|
+
if (!result.ok) {
|
|
103
|
+
setListError(result.error || 'Failed to delete asset');
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
setAssets((prev) => prev.filter((a) => a.hash32 !== asset.hash32));
|
|
107
|
+
};
|
|
108
|
+
const handleDeleteClick = (asset) => {
|
|
109
|
+
modals.openConfirmModal({
|
|
110
|
+
title: 'Remove from library',
|
|
111
|
+
children: (_jsxs(Text, { size: "sm", children: ["Remove \u201C", asset.filename, "\u201D from the media library? Existing content that already references this file keeps working - removing it here only hides it from the library; the file itself is not deleted."] })),
|
|
112
|
+
labels: { confirm: 'Remove', cancel: 'Cancel' },
|
|
113
|
+
confirmProps: { color: 'red' },
|
|
114
|
+
onConfirm: () => {
|
|
115
|
+
void handleDelete(asset);
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
// Picker mode is image-only (see `imageOnly` above) - pdf assets are
|
|
120
|
+
// filtered out of the pickable grid entirely, not just the upload accept
|
|
121
|
+
// list, since an already-uploaded pdf could otherwise still be selected.
|
|
122
|
+
const kindFiltered = imageOnly ? assets.filter((asset) => asset.kind !== 'pdf') : assets;
|
|
123
|
+
const normalizedFilter = filterText.trim().toLowerCase();
|
|
124
|
+
const filteredAssets = normalizedFilter
|
|
125
|
+
? kindFiltered.filter((asset) => asset.filename.toLowerCase().includes(normalizedFilter))
|
|
126
|
+
: kindFiltered;
|
|
127
|
+
return (_jsxs(Stack, { gap: "sm", h: "100%", style: { display: 'flex', flexDirection: 'column' }, children: [_jsx(Dropzone, { onDrop: (files) => void handleDrop(files), onReject: handleReject, maxSize: MAX_UPLOAD_BYTES, accept: imageOnly ? ACCEPTED_IMAGE_MIME_TYPES : ACCEPTED_ASSET_MIME_TYPES, loading: upload.uploading, multiple: false, "data-testid": "media-library-dropzone", children: _jsxs(Group, { justify: "center", gap: "xs", py: "sm", style: { pointerEvents: 'none' }, children: [_jsx(IconUpload, { size: 20 }), _jsx(Text, { size: "sm", children: imageOnly
|
|
128
|
+
? 'Drop an image here, or click to browse'
|
|
129
|
+
: 'Drop an image or PDF here, or click to browse' })] }) }), upload.uploading &&
|
|
130
|
+
(upload.progress !== null ? (_jsx(Progress, { value: upload.progress * 100, size: "sm", "data-testid": "upload-progress" })) : (_jsx(Progress, { value: 100, size: "sm", animated: true, "data-testid": "upload-progress-indeterminate" }))), upload.error && (_jsx(Alert, { icon: _jsx(IconAlertCircle, { size: 16 }), color: "red", "data-testid": "upload-error", children: upload.error })), _jsx(TextInput, { placeholder: "Filter by filename...", value: filterText, onChange: (event) => setFilterText(event.currentTarget.value), "data-testid": "media-library-filter" }), listError && (_jsx(Alert, { icon: _jsx(IconAlertCircle, { size: 16 }), color: "red", "data-testid": "media-library-error", children: _jsxs(Stack, { gap: 4, children: [_jsx(Text, { size: "sm", children: listError }), _jsx(Button, { size: "xs", variant: "light", onClick: () => void loadFirstPage(), children: "Retry" })] }) })), _jsxs(ScrollArea, { style: { flex: 1 }, children: [loading ? (_jsx(Group, { justify: "center", py: "xl", children: _jsx(Loader, { size: "sm", "data-testid": "media-library-loading" }) })) : filteredAssets.length === 0 ? (_jsx(Text, { size: "sm", c: "dimmed", py: "xl", ta: "center", children: "No assets found." })) : (_jsx(SimpleGrid, { cols: { base: 2, sm: 3, md: 4 }, spacing: "sm", children: filteredAssets.map((asset) => (_jsx(AssetCard, { asset: asset, baseUrl: baseUrl, onSelect: mode === 'picker' ? onSelect : undefined, onDelete: canDelete ? () => handleDeleteClick(asset) : undefined }, asset.hash32))) })), !loading && nextCursor && (_jsx(Group, { justify: "center", py: "sm", children: _jsx(Button, { variant: "light", size: "xs", loading: loadingMore, onClick: () => void handleLoadMore(), "data-testid": "media-library-load-more", children: "Load more" }) }))] })] }));
|
|
131
|
+
};
|
|
132
|
+
export default MediaLibraryBody;
|
|
133
|
+
//# sourceMappingURL=MediaLibraryBody.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaLibraryBody.js","sourceRoot":"","sources":["../../../src/editor/media/MediaLibraryBody.tsx"],"names":[],"mappings":"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"}
|