@ablogcms/media 3.2.28-beta.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 (69) hide show
  1. package/README.md +28 -0
  2. package/dist/acms.d.ts +10 -0
  3. package/dist/acms.mjs +1 -0
  4. package/dist/acms.mjs.map +1 -0
  5. package/dist/chunk-32U7ADG2.mjs +456 -0
  6. package/dist/chunk-32U7ADG2.mjs.map +1 -0
  7. package/dist/chunk-3SYVRD3N.mjs +37 -0
  8. package/dist/chunk-3SYVRD3N.mjs.map +1 -0
  9. package/dist/chunk-5P6HFS6L.mjs +90 -0
  10. package/dist/chunk-5P6HFS6L.mjs.map +1 -0
  11. package/dist/chunk-J5LGTIGS.mjs +10 -0
  12. package/dist/chunk-J5LGTIGS.mjs.map +1 -0
  13. package/dist/chunk-JJTHI4QP.mjs +1783 -0
  14. package/dist/chunk-JJTHI4QP.mjs.map +1 -0
  15. package/dist/chunk-KQNVYJOK.mjs +1814 -0
  16. package/dist/chunk-KQNVYJOK.mjs.map +1 -0
  17. package/dist/chunk-LAZAMWG6.mjs +231 -0
  18. package/dist/chunk-LAZAMWG6.mjs.map +1 -0
  19. package/dist/components/media-admin/media-admin-view.d.ts +22 -0
  20. package/dist/components/media-admin/media-admin.d.ts +6 -0
  21. package/dist/components/media-admin/media-admin.mjs +148 -0
  22. package/dist/components/media-admin/media-admin.mjs.map +1 -0
  23. package/dist/components/media-droparea/media-droparea.d.ts +63 -0
  24. package/dist/components/media-droparea/media-droparea.mjs +152 -0
  25. package/dist/components/media-droparea/media-droparea.mjs.map +1 -0
  26. package/dist/components/media-edit-modal/media-edit-modal.d.ts +58 -0
  27. package/dist/components/media-insert/media-insert-modal.d.ts +30 -0
  28. package/dist/components/media-insert/media-insert.d.ts +5 -0
  29. package/dist/components/media-insert/media-insert.mjs +11 -0
  30. package/dist/components/media-insert/media-insert.mjs.map +1 -0
  31. package/dist/components/media-list/media-list.d.ts +125 -0
  32. package/dist/components/media-modal/media-modal.d.ts +94 -0
  33. package/dist/components/media-modal/pdf-previewer.d.ts +8 -0
  34. package/dist/components/media-unit/media-unit.d.ts +65 -0
  35. package/dist/components/media-unit/media-unit.mjs +13 -0
  36. package/dist/components/media-unit/media-unit.mjs.map +1 -0
  37. package/dist/components/media-update/media-update-modal.d.ts +12 -0
  38. package/dist/components/media-update/media-update.d.ts +5 -0
  39. package/dist/components/media-update/media-update.mjs +10 -0
  40. package/dist/components/media-update/media-update.mjs.map +1 -0
  41. package/dist/components/media-uploader/media-uploader.d.ts +69 -0
  42. package/dist/constants/index.d.ts +19 -0
  43. package/dist/containers/media-admin.d.ts +10 -0
  44. package/dist/containers/media-insert.d.ts +17 -0
  45. package/dist/containers/media-update.d.ts +13 -0
  46. package/dist/dataview/column-type.d.ts +10 -0
  47. package/dist/dataview/column-type.mjs +75 -0
  48. package/dist/dataview/column-type.mjs.map +1 -0
  49. package/dist/events.d.ts +70 -0
  50. package/dist/media-crop-focal-OQHAYXEP.svg +1 -0
  51. package/dist/media-crop-icon-LD2QEJHL.svg +12 -0
  52. package/dist/media-focal-point-OQQ3MQM2.svg +3 -0
  53. package/dist/media-rotate-icon-HBMXAPD4.svg +7 -0
  54. package/dist/runtime.d.ts +20 -0
  55. package/dist/runtime.mjs +16 -0
  56. package/dist/runtime.mjs.map +1 -0
  57. package/dist/setup-media-unit.d.ts +2 -0
  58. package/dist/setup-media-unit.mjs +118 -0
  59. package/dist/setup-media-unit.mjs.map +1 -0
  60. package/dist/stores/actions.d.ts +64 -0
  61. package/dist/stores/reducer.d.ts +5 -0
  62. package/dist/stores/saga.d.ts +35 -0
  63. package/dist/types/config.d.ts +29 -0
  64. package/dist/types/index.d.ts +83 -0
  65. package/dist/types/index.mjs +1 -0
  66. package/dist/types/index.mjs.map +1 -0
  67. package/dist/types/transport.d.ts +76 -0
  68. package/dist/utils/index.d.ts +5 -0
  69. package/package.json +112 -0
@@ -0,0 +1,94 @@
1
+ import { Component } from 'react';
2
+ import Modal from '@ablogcms/components/modal';
3
+ import { type AutoResizeTextareaRef } from '@ablogcms/components/textarea';
4
+ import type { FocalPoint, MediaItem, MediaTag } from '../../types/index.js';
5
+ /**
6
+ * Slot `media.edit-modal.field.alt`(HOOKS.md 参照)の fillProps。
7
+ * `ACMS.Config.mediaShowAltAndCaptionOnModal` が off のとき alt 行ごと非表示になり、この Slot も
8
+ * 一緒に消える仕様(alt 生成という文脈から離れる置き場所を避けるため、行外には置かない)。
9
+ */
10
+ export interface MediaEditModalAltFillProps {
11
+ item: MediaItem;
12
+ /** 差し替え中の画像も反映済みのプレビュー URL */
13
+ previewSrc: string;
14
+ /** textarea の現在値 */
15
+ getAlt: () => string;
16
+ /** `AutoResizeTextarea` の `setValue`(内部 state・DOM 値の両方を更新する imperative handle)経由で書き戻す。高さの自動リサイズも追随する */
17
+ setAlt: (value: string) => void;
18
+ }
19
+ /** Slot `media.edit-modal.fields` の fillProps。独自メタパネルの受け皿(config 非依存で常時表示) */
20
+ export interface MediaEditModalFieldsFillProps {
21
+ item: MediaItem;
22
+ }
23
+ /** Slot `media.edit-modal.footer` の fillProps */
24
+ export interface MediaEditModalFooterFillProps {
25
+ item: MediaItem;
26
+ /** 保存直前の FormData(`buildFormData('ACMS_POST_Media_Update')` と同じ内容)を組み立てて返す */
27
+ getFormData: () => FormData;
28
+ }
29
+ type MediaModalState = {
30
+ isEditDialogOpen: boolean;
31
+ blob: Blob | null;
32
+ file: File | null;
33
+ preview: string;
34
+ pdfPreviewSrc: string;
35
+ pdfHasPrevPage: boolean;
36
+ pdfHasNextPage: boolean;
37
+ pdfPage: number;
38
+ focalPoint: FocalPoint;
39
+ replaced: boolean;
40
+ activeTab: string;
41
+ };
42
+ interface MediaModalProps extends Pick<React.ComponentPropsWithoutRef<typeof Modal>, 'isOpen' | 'onClose' | 'onAfterClose' | 'onAfterOpen' | 'container'> {
43
+ formToken: string;
44
+ item: MediaItem | null;
45
+ tags?: string[];
46
+ onUpdate?: (media: MediaItem) => void;
47
+ actions: typeof import('../../stores/actions.js');
48
+ }
49
+ export default class MediaModal extends Component<MediaModalProps, MediaModalState> {
50
+ form: HTMLFormElement | null;
51
+ filenameInputRef: React.RefObject<HTMLInputElement | null>;
52
+ tagsInputRef: React.RefObject<HTMLInputElement | null>;
53
+ altTextareaRef: React.RefObject<AutoResizeTextareaRef | null>;
54
+ modalRef: React.RefObject<HTMLDivElement | null>;
55
+ root: HTMLElement;
56
+ static defaultProps: {
57
+ tags: never[];
58
+ };
59
+ constructor(props: MediaModalProps | Readonly<MediaModalProps>);
60
+ componentDidMount(): void;
61
+ getDefaultPreview(item: MediaItem): string;
62
+ handleAfterClose(): void;
63
+ handleAfterOpen(): void;
64
+ componentDidUpdate(prevProps: Readonly<MediaModalProps>): void;
65
+ setFormRef(node: HTMLFormElement): void;
66
+ componentWillUnmount(): void;
67
+ pdfPreview(url: string, page: number): Promise<void>;
68
+ pdfPrevPage(e: React.MouseEvent<HTMLButtonElement>): Promise<void>;
69
+ pdfNextPage(e: React.MouseEvent<HTMLButtonElement>): Promise<void>;
70
+ hideModal(): void;
71
+ handleClose(): void;
72
+ isImageMedia(state: MediaModalState, props: MediaModalProps): boolean;
73
+ isSvgMedia(state: MediaModalState, props: MediaModalProps): boolean;
74
+ isFileMedia(state: MediaModalState, props: MediaModalProps): boolean;
75
+ isPdfFile(state: MediaModalState, props: MediaModalProps): boolean;
76
+ buildFormData(postName: string): FormData;
77
+ updateStateOnAfterSave(mediaItem: MediaItem): void;
78
+ update(item: MediaItem): Promise<void>;
79
+ uploadAsNew(item: MediaItem): Promise<void>;
80
+ makeTags(label: string): {
81
+ value: string;
82
+ label: string;
83
+ }[] | null;
84
+ handleTagsChange(tags: readonly MediaTag[]): void;
85
+ openEditDialog(): void;
86
+ blobToDataURL(blob: Blob): Promise<string>;
87
+ handleEditDialogClose(): void;
88
+ handleCrop(blob: Blob | null, focalPoint: FocalPoint): void;
89
+ changeImage(e: React.ChangeEvent<HTMLInputElement>): Promise<false | undefined>;
90
+ imageWidth(size: string): number;
91
+ imageHeight(size: string): number;
92
+ render(): import("react").JSX.Element;
93
+ }
94
+ export {};
@@ -0,0 +1,8 @@
1
+ export type PdfPageResult = {
2
+ image: string | false;
3
+ hasPrev: boolean;
4
+ hasNext: boolean;
5
+ currentPage: number;
6
+ };
7
+ /** 同じ url|page は1本に合流し、完了後はキャッシュから返す */
8
+ export declare function fetchPdfPage(url: string, page: number): Promise<PdfPageResult>;
@@ -0,0 +1,65 @@
1
+ import { Component } from 'react';
2
+ import { ExtendedFile } from '@ablogcms/lib/read-files';
3
+ import { MediaItem } from '../../types/index.js';
4
+ type MediaUnitProps = {
5
+ items: MediaItem[];
6
+ mediaSizes?: {
7
+ value: string;
8
+ label: string;
9
+ selected: boolean;
10
+ }[];
11
+ primaryImageId: string;
12
+ id: string;
13
+ active: 'on' | 'off';
14
+ lang?: string;
15
+ usePdfIcon: 'yes' | 'no';
16
+ primary: 'true' | 'false';
17
+ hasLink: 'true' | 'false';
18
+ multiUpload: 'true' | 'false';
19
+ enlarged: 'true' | 'false';
20
+ overrideLink: string;
21
+ overrideAlt: string;
22
+ overrideCaption: string;
23
+ onMount?: () => void;
24
+ onChange?: (mediaItems: MediaItem[]) => void;
25
+ };
26
+ type MediaUnitState = {
27
+ insertModalOpened: boolean;
28
+ updateModalOpened: boolean;
29
+ newMedia: boolean;
30
+ noLink: 'yes' | 'no';
31
+ noLarge: 'yes' | 'no';
32
+ useIcon: 'yes' | 'no';
33
+ modalType: 'upload' | 'select';
34
+ link: string;
35
+ targetId: number | null;
36
+ items: MediaItem[];
37
+ files: File[];
38
+ landscape: boolean;
39
+ alt: string;
40
+ caption: string;
41
+ };
42
+ export default class MediaUnit extends Component<MediaUnitProps, MediaUnitState> {
43
+ static defaultProps: {
44
+ items: never[];
45
+ mediaSizes: never[];
46
+ lang: string;
47
+ };
48
+ rootRef: import("react").RefObject<HTMLDivElement | null>;
49
+ handleMediaUpdated?: (event: Event) => void;
50
+ constructor(props: MediaUnitProps);
51
+ componentDidMount(): void;
52
+ componentWillUnmount(): void;
53
+ componentDidUpdate(_: MediaUnitProps, prevState: MediaUnitState): void;
54
+ openInsertModal: () => void;
55
+ onInsert: (items: MediaItem[]) => void;
56
+ onClose: () => void;
57
+ onUpdateModalClose: () => void;
58
+ onUpdateModalUpdate: (item: MediaItem) => void;
59
+ removeMediaAt: (index: number) => void;
60
+ openEditModal: (targetId: number) => void;
61
+ onComplete: (files: ExtendedFile[]) => void;
62
+ uploadFile: (e: React.ChangeEvent<HTMLInputElement>) => void;
63
+ render(): import("react").JSX.Element;
64
+ }
65
+ export {};
@@ -0,0 +1,13 @@
1
+ import {
2
+ MediaUnit
3
+ } from "../../chunk-32U7ADG2.mjs";
4
+ import "../../chunk-5P6HFS6L.mjs";
5
+ import "../../chunk-LAZAMWG6.mjs";
6
+ import "../../chunk-KQNVYJOK.mjs";
7
+ import "../../chunk-JJTHI4QP.mjs";
8
+ import "../../chunk-3SYVRD3N.mjs";
9
+ import "../../chunk-J5LGTIGS.mjs";
10
+ export {
11
+ MediaUnit as default
12
+ };
13
+ //# sourceMappingURL=media-unit.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,12 @@
1
+ import { Component } from 'react';
2
+ import MediaModal from '../media-modal/media-modal.js';
3
+ import type { MediaStateProps } from '../../types/index.js';
4
+ interface MediaUpdateModalProps extends MediaStateProps, Pick<React.ComponentProps<typeof MediaModal>, 'onClose' | 'isOpen' | 'onUpdate' | 'container'> {
5
+ mid: number;
6
+ }
7
+ export default class MediaUpdateModal extends Component<MediaUpdateModalProps> {
8
+ handleAfterMediaModalOpen(): void;
9
+ handleAfterMediaModalClose(): void;
10
+ render(): import("react").JSX.Element;
11
+ }
12
+ export {};
@@ -0,0 +1,5 @@
1
+ import MediaUpdateContainer from '../../containers/media-update.js';
2
+ interface MediaUpdateProps extends React.ComponentProps<typeof MediaUpdateContainer> {
3
+ }
4
+ declare function MediaUpdate(props: MediaUpdateProps): import("react").JSX.Element;
5
+ export default MediaUpdate;
@@ -0,0 +1,10 @@
1
+ import {
2
+ media_update_default
3
+ } from "../../chunk-5P6HFS6L.mjs";
4
+ import "../../chunk-JJTHI4QP.mjs";
5
+ import "../../chunk-3SYVRD3N.mjs";
6
+ import "../../chunk-J5LGTIGS.mjs";
7
+ export {
8
+ media_update_default as default
9
+ };
10
+ //# sourceMappingURL=media-update.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,69 @@
1
+ import { Component } from 'react';
2
+ import { type ExtendedFile } from '@ablogcms/lib/read-files';
3
+ import { MediaAjaxConfig, MediaItem, MediaTag } from '../../types/index.js';
4
+ import * as actions from '../../stores/actions.js';
5
+ interface MediaUploadItem {
6
+ file: File;
7
+ filetype: string;
8
+ preview: string;
9
+ blob?: Blob | null;
10
+ id: string;
11
+ idx: number;
12
+ progress: number;
13
+ progressError: boolean;
14
+ name: string;
15
+ size: number;
16
+ uploadedItem?: MediaItem;
17
+ }
18
+ interface MediaUploaderProps {
19
+ showUploadButton?: boolean;
20
+ largeSize: number;
21
+ config: MediaAjaxConfig;
22
+ actions: typeof actions;
23
+ files?: File[];
24
+ tags?: string[];
25
+ label?: string;
26
+ }
27
+ interface MediaUploaderState {
28
+ items: MediaUploadItem[];
29
+ label: string;
30
+ loading: boolean;
31
+ imgsOnStage: boolean;
32
+ hasUploadedItems: boolean;
33
+ }
34
+ export default class MediaUploader extends Component<MediaUploaderProps, MediaUploaderState> {
35
+ static defaultProps: {
36
+ showUploadButton: boolean;
37
+ tags: never[];
38
+ files: never[];
39
+ };
40
+ constructor(props: MediaUploaderProps);
41
+ get uploadLimit(): number;
42
+ get uploadConcurrency(): number;
43
+ get uploadProgress(): {
44
+ done: number;
45
+ total: number;
46
+ percent: number;
47
+ errorCount: number;
48
+ };
49
+ handleBeforeUnload: (event: BeforeUnloadEvent) => void;
50
+ componentDidMount(): void;
51
+ componentWillUnmount(): void;
52
+ createPdfThumbnail(file: Blob | File): Promise<string>;
53
+ upload(blob: Blob | File, label: string, name: string, item: MediaUploadItem): Promise<MediaItem>;
54
+ setProgressBar(item: MediaUploadItem, progress: number, progressError?: boolean): void;
55
+ removeFile(file: MediaUploadItem): void;
56
+ setUploadedItem(file: MediaUploadItem, uploadedItem: MediaItem): void;
57
+ editItem(item: MediaUploadItem): void;
58
+ uploadItems(): Promise<MediaItem[]>;
59
+ onComplete(files: ExtendedFile[]): void;
60
+ makeTags(label: string): {
61
+ value: string;
62
+ label: string;
63
+ }[] | null;
64
+ addTags(tags: readonly MediaTag[]): void;
65
+ removeUploadedItems(): void;
66
+ renderOverallText(): string | import("react").JSX.Element;
67
+ render(): import("react").JSX.Element;
68
+ }
69
+ export {};
@@ -0,0 +1,19 @@
1
+ export declare const FETCHMEDIALIST: "FETCHMEDIALIST";
2
+ export declare const FETCHTAGLIST: "FETCHTAGLIST";
3
+ export declare const SETMEDIALIST: "SETMEDIALIST";
4
+ export declare const SETMEDIALASTPAGE: "SETMEDIALASTPAGE";
5
+ export declare const SETMEDIACONFIG: "SETMEDIACONFIG";
6
+ export declare const SETMEDIAPAGE: "SETMEDIAPAGE";
7
+ export declare const SETMEDIALIMIT: "SETMEDIALIMIT";
8
+ export declare const SETITEM: "SETITEM";
9
+ export declare const UPDATEMEDIALIST: "UPDATEMEDIALIST";
10
+ export declare const SETMEDIALARGESIZE: "SETMEDIALARGESIZE";
11
+ export declare const SETFORMTOKEN: "SETFORMTOKEN";
12
+ export declare const SETLABEL: "SETLABEL";
13
+ export declare const SETMEDIAKEYWORD: "SETMEDIAKEYWORD";
14
+ export declare const SETMEDIAARCHIVES: "SETMEDIAARCHIVES";
15
+ export declare const SETMEDIATAGS: "SETMEDIATAGS";
16
+ export declare const SETMEDIATOTAL: "SETMEDIATOTAL";
17
+ export declare const SETLOADING: "SETLOADING";
18
+ export declare const SETSELECTEDTAGS: "SETSELECTEDTAGS";
19
+ export declare const SETMEDIAEXTENSIONS: "SETMEDIAEXTENSIONS";
@@ -0,0 +1,10 @@
1
+ import MediaAdminView from '../components/media-admin/media-admin-view.js';
2
+ declare const _default: import("react-redux").ConnectedComponent<typeof MediaAdminView, {
3
+ tab?: "upload" | "select" | undefined;
4
+ key?: import("react").Key | null | undefined;
5
+ ref?: import("react").Ref<MediaAdminView> | undefined;
6
+ mode: "edit" | "insert";
7
+ context?: import("react").Context<import("react-redux").ReactReduxContextValue<any, import("redux").UnknownAction> | null> | undefined;
8
+ store?: import("redux").Store | undefined;
9
+ }>;
10
+ export default _default;
@@ -0,0 +1,17 @@
1
+ import MediaInsertModal from '../components/media-insert/media-insert-modal.js';
2
+ declare const _default: import("react-redux").ConnectedComponent<typeof MediaInsertModal, {
3
+ tab?: "upload" | "select" | undefined;
4
+ files?: File[] | undefined;
5
+ key?: import("react").Key | null | undefined;
6
+ ref?: import("react").Ref<MediaInsertModal> | undefined;
7
+ filetype?: import("../types/index.js").MediaViewFileType | undefined;
8
+ isOpen: boolean;
9
+ onClose: () => void;
10
+ container?: HTMLElement | undefined;
11
+ mode?: "edit" | "insert" | undefined;
12
+ radioMode?: boolean | undefined;
13
+ onInsert: (items: import("../types/index.js").MediaItem[]) => void;
14
+ context?: import("react").Context<import("react-redux").ReactReduxContextValue<any, import("redux").UnknownAction> | null> | undefined;
15
+ store?: import("redux").Store | undefined;
16
+ }>;
17
+ export default _default;
@@ -0,0 +1,13 @@
1
+ import MediaUpdateModal from '../components/media-update/media-update-modal.js';
2
+ declare const _default: import("react-redux").ConnectedComponent<typeof MediaUpdateModal, {
3
+ key?: import("react").Key | null | undefined;
4
+ ref?: import("react").Ref<MediaUpdateModal> | undefined;
5
+ readonly isOpen: boolean;
6
+ readonly onClose: () => void;
7
+ readonly container?: HTMLElement | undefined;
8
+ mid: number;
9
+ readonly onUpdate?: ((media: import("../types/index.js").MediaItem) => void) | undefined;
10
+ context?: import("react").Context<import("react-redux").ReactReduxContextValue<any, import("redux").UnknownAction> | null> | undefined;
11
+ store?: import("redux").Store | undefined;
12
+ }>;
13
+ export default _default;
@@ -0,0 +1,10 @@
1
+ import type { ColumnTypeDef } from '@ablogcms/components/dataview/types';
2
+ /**
3
+ * dataview の `columnTypes` prop に登録する media カラム型定義。
4
+ * 元は components/dataview/dataview.tsx にハードコードされていたが、
5
+ * dataview から media への逆流参照を断つため(フェーズ3-1b)ここへ移設した。
6
+ *
7
+ * `ColumnTypeDef<any>` にしているのは、entry / module 等どの行の型(T)にも登録できる
8
+ * ようにするため(登録先ごとに具体的な行の型でラップし直す必要をなくす)。
9
+ */
10
+ export declare const mediaColumnType: ColumnTypeDef<any>;
@@ -0,0 +1,75 @@
1
+ import "../chunk-J5LGTIGS.mjs";
2
+
3
+ // src/dataview/column-type.tsx
4
+ import { isAccessorColumn } from "@ablogcms/components/dataview/types";
5
+ import { Tooltip } from "@ablogcms/components/tooltip";
6
+ import { truncate } from "@ablogcms/utils/string";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ var formatFileName = (value) => truncate(value, 30, "...");
9
+ function getValue(info) {
10
+ const column = info.column.columnDef.meta?.column;
11
+ if (!column) {
12
+ throw new Error("column is not found");
13
+ }
14
+ if (!isAccessorColumn(column)) {
15
+ throw new Error("column is not accessor column");
16
+ }
17
+ if (!column.accessorKey) {
18
+ throw new Error("column accessor key is not found");
19
+ }
20
+ const name = column.accessorKey;
21
+ const data = info.row.original;
22
+ const base = {
23
+ id: parseInt(data[name], 10),
24
+ type: data[`${name}@type`],
25
+ path: data[`${name}@path`],
26
+ thumbnail: data[`${name}@thumbnail`],
27
+ filename: data[`${name}@name`],
28
+ extension: data[`${name}@extension`],
29
+ filesize: parseInt(data[`${name}@filesize`], 10) || 0,
30
+ caption: data[`${name}@caption`] || "",
31
+ link: data[`${name}@link`] || "",
32
+ alt: data[`${name}@alt`] || "",
33
+ text: data[`${name}@text`] || ""
34
+ };
35
+ const media = {
36
+ ...base,
37
+ ...base.type === "image" ? {
38
+ focalX: Object.hasOwn(data, `${name}@focalX`) ? parseFloat(data[`${name}@focalX`]) : void 0,
39
+ focalY: Object.hasOwn(data, `${name}@focalY`) ? parseFloat(data[`${name}@focalY`]) : void 0,
40
+ width: parseInt(data[`${name}@width`], 10) || 0,
41
+ height: parseInt(data[`${name}@height`], 10) || 0,
42
+ ratio: parseFloat(data[`${name}@ratio`]) || 0
43
+ } : {},
44
+ ...base.type === "file" ? {
45
+ page: parseInt(data[`${name}@page`], 10) || 1
46
+ } : {}
47
+ };
48
+ return {
49
+ image: /* @__PURE__ */ jsx("div", { className: "acms-admin-cell-image", children: /* @__PURE__ */ jsx("img", { src: media.thumbnail, alt: media.alt }) }),
50
+ svg: /* @__PURE__ */ jsx("div", { className: "acms-admin-cell-image", children: /* @__PURE__ */ jsx("img", { src: media.thumbnail, alt: media.alt }) }),
51
+ file: /* @__PURE__ */ jsxs(Fragment, { children: [
52
+ /* @__PURE__ */ jsxs("a", { href: media.path, className: "acms-admin-cell-file", target: "_blank", rel: "noreferrer", children: [
53
+ /* @__PURE__ */ jsx("img", { src: media.thumbnail, alt: "" }),
54
+ /* @__PURE__ */ jsx(
55
+ "span",
56
+ {
57
+ "data-tooltip-id": `${info.cell.id}-${media.id}-media-filename-tooptip`,
58
+ "data-tooltip-content": media.filename,
59
+ "data-tooltip-place": "top-end",
60
+ children: formatFileName(media.filename)
61
+ }
62
+ )
63
+ ] }),
64
+ /* @__PURE__ */ jsx(Tooltip, { id: `${info.cell.id}-${media.id}-media-filename-tooptip` })
65
+ ] })
66
+ }[media.type];
67
+ }
68
+ var mediaColumnType = {
69
+ getValue,
70
+ label: ACMS.i18n("dataview.custom_column.type.media")
71
+ };
72
+ export {
73
+ mediaColumnType
74
+ };
75
+ //# sourceMappingURL=column-type.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/dataview/column-type.tsx"],"sourcesContent":["/* eslint @typescript-eslint/no-explicit-any: 0 */\n\nimport type { CellContext } from '@tanstack/react-table';\nimport type { ColumnTypeDef, RowData } from '@ablogcms/components/dataview/types';\nimport { isAccessorColumn } from '@ablogcms/components/dataview/types';\nimport { Tooltip } from '@ablogcms/components/tooltip';\nimport { truncate } from '@ablogcms/utils/string';\nimport type { MediaType } from '../types';\n\ninterface MediaBase {\n id: number;\n type: MediaType;\n path: string;\n thumbnail: string;\n filename: string;\n extension: string;\n filesize: number;\n caption: string;\n link: string;\n alt: string;\n text: string;\n}\n\ninterface ImageMedia extends MediaBase {\n type: 'image';\n focalX?: number;\n focalY?: number;\n width?: number;\n height?: number;\n ratio?: number;\n}\n\ninterface SvgMedia extends MediaBase {\n type: 'svg';\n}\n\ninterface FileMedia extends MediaBase {\n type: 'file';\n page: number;\n}\n\ntype Media = ImageMedia | SvgMedia | FileMedia;\n\nconst formatFileName = (value: string): string => truncate(value, 30, '...');\n\nfunction getValue(info: CellContext<RowData, Record<string, unknown>>): React.ReactNode {\n const column = info.column.columnDef.meta?.column;\n if (!column) {\n throw new Error('column is not found');\n }\n if (!isAccessorColumn(column)) {\n throw new Error('column is not accessor column');\n }\n if (!column.accessorKey) {\n throw new Error('column accessor key is not found');\n }\n const name = column.accessorKey;\n const data = info.row.original as Record<string, unknown>;\n const base: MediaBase = {\n id: parseInt(data[name] as string, 10),\n type: data[`${name}@type`] as Media['type'],\n path: data[`${name}@path`] as string,\n thumbnail: data[`${name}@thumbnail`] as string,\n filename: data[`${name}@name`] as string,\n extension: data[`${name}@extension`] as string,\n filesize: parseInt(data[`${name}@filesize`] as string, 10) || 0,\n caption: (data[`${name}@caption`] as string) || '',\n link: (data[`${name}@link`] as string) || '',\n alt: (data[`${name}@alt`] as string) || '',\n text: (data[`${name}@text`] as string) || '',\n };\n const media: Media = {\n ...base,\n ...(base.type === 'image'\n ? {\n focalX: Object.hasOwn(data, `${name}@focalX`) ? parseFloat(data[`${name}@focalX`] as string) : undefined,\n focalY: Object.hasOwn(data, `${name}@focalY`) ? parseFloat(data[`${name}@focalY`] as string) : undefined,\n width: parseInt(data[`${name}@width`] as string, 10) || 0,\n height: parseInt(data[`${name}@height`] as string, 10) || 0,\n ratio: parseFloat(data[`${name}@ratio`] as string) || 0,\n }\n : {}),\n ...(base.type === 'file'\n ? {\n page: parseInt(data[`${name}@page`] as string, 10) || 1,\n }\n : {}),\n } as Media;\n\n return {\n image: (\n <div className=\"acms-admin-cell-image\">\n <img src={media.thumbnail} alt={media.alt} />\n </div>\n ),\n svg: (\n <div className=\"acms-admin-cell-image\">\n <img src={media.thumbnail} alt={media.alt} />\n </div>\n ),\n file: (\n <>\n <a href={media.path} className=\"acms-admin-cell-file\" target=\"_blank\" rel=\"noreferrer\">\n <img src={media.thumbnail} alt=\"\" />\n <span\n data-tooltip-id={`${info.cell.id}-${media.id}-media-filename-tooptip`}\n data-tooltip-content={media.filename}\n data-tooltip-place=\"top-end\"\n >\n {formatFileName(media.filename)}\n </span>\n </a>\n <Tooltip id={`${info.cell.id}-${media.id}-media-filename-tooptip`} />\n </>\n ),\n }[media.type];\n}\n\n/**\n * dataview の `columnTypes` prop に登録する media カラム型定義。\n * 元は components/dataview/dataview.tsx にハードコードされていたが、\n * dataview から media への逆流参照を断つため(フェーズ3-1b)ここへ移設した。\n *\n * `ColumnTypeDef<any>` にしているのは、entry / module 等どの行の型(T)にも登録できる\n * ようにするため(登録先ごとに具体的な行の型でラップし直す必要をなくす)。\n */\nexport const mediaColumnType: ColumnTypeDef<any> = {\n getValue,\n label: ACMS.i18n('dataview.custom_column.type.media'),\n};\n"],"mappings":"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","names":[]}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * media ドメインのイベントを `AcmsEventMap`(`@ablogcms/events`)へ登録する module augmentation。
3
+ *
4
+ * 実際の発火・購読は `ACMS.events`(グローバル)経由で行う。このファイルは型のみを供給し、
5
+ * ランタイムの副作用は持たない(拡張基盤 design.md「拡張ポイントの提案」節)。
6
+ */
7
+ import type { AcmsGateEvent, AcmsNotifyEvent } from '@ablogcms/events';
8
+ import type { MediaItem } from './types/index.js';
9
+ declare module '@ablogcms/events' {
10
+ interface AcmsEventMap {
11
+ /**
12
+ * アップロード開始前のゲート。案件固有の追加確認(コンプラ同意等)を挟める。
13
+ * 既存の必須バリデーション(mime/サイズ等)を置き換えるものではなく、その上乗せの関門。
14
+ */
15
+ 'media.upload.before': AcmsGateEvent<{
16
+ files: File[];
17
+ }>;
18
+ /** アップロード完了後の通知。既存の DOM CustomEvent `acms.media-updated`(編集保存時)とは別イベント */
19
+ 'media.upload.success': AcmsNotifyEvent<{
20
+ items: MediaItem[];
21
+ }>;
22
+ /**
23
+ * メディア詳細モーダルの保存前ゲート。alt 必須化・NG ワード検査等を挟める。
24
+ * `formData` の値変更(waterfall)・キャンセルの両方に対応する。
25
+ */
26
+ 'media.update.before': AcmsGateEvent<{
27
+ item: MediaItem;
28
+ formData: FormData;
29
+ }>;
30
+ /**
31
+ * メディア詳細モーダルの保存完了後の通知。既存の DOM CustomEvent `acms.media-updated` と
32
+ * 二重発火される(新バス→レガシーの順)型付き版
33
+ */
34
+ 'media.update.success': AcmsNotifyEvent<{
35
+ item: MediaItem;
36
+ }>;
37
+ /**
38
+ * メディア詳細モーダルの「別名保存」前ゲート。`media.update.before` と同じ検査を挟める。
39
+ * 別名保存はレガシー DOM イベント(`acms.media-updated`)すら飛ばない非対称があるため、
40
+ * `.success` 通知の価値が高い。
41
+ */
42
+ 'media.update-as-new.before': AcmsGateEvent<{
43
+ item: MediaItem;
44
+ formData: FormData;
45
+ }>;
46
+ /** メディア詳細モーダルの「別名保存」完了後の通知。二重発火するレガシー DOM イベントは無い */
47
+ 'media.update-as-new.success': AcmsNotifyEvent<{
48
+ item: MediaItem;
49
+ }>;
50
+ /**
51
+ * メディア一覧の一括削除前ゲート。参照チェック・外部ストレージ連動削除等に使える。
52
+ */
53
+ 'media.delete.before': AcmsGateEvent<{
54
+ mediaIds: string[];
55
+ }>;
56
+ /** メディア一覧の一括削除完了後の通知 */
57
+ 'media.delete.success': AcmsNotifyEvent<{
58
+ mediaIds: string[];
59
+ }>;
60
+ /** DOM CustomEvent `acms.media-field.change` の型付き版。メディアフィールド変更の連携(自社購読なし) */
61
+ 'media-field.change': AcmsNotifyEvent<{
62
+ target: HTMLElement;
63
+ }>;
64
+ /** DOM CustomEvent `acms.media-unit.change` の型付き版。メディアユニット変更の連携(自社購読なし) */
65
+ 'media-unit.change': AcmsNotifyEvent<{
66
+ target: HTMLElement;
67
+ mediaItems: MediaItem[];
68
+ }>;
69
+ }
70
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="19.13mm" height="19.13mm" viewBox="0 0 54.24 54.24"><title>アセット 2</title><g style="isolation:isolate"><g id="f6125acf-7c67-43a7-b4c1-afdc030c1b9e" data-name="レイヤー 2"><g id="e22857cd-f676-4916-bb4a-9f9ccc35786d" data-name="レイヤー 1"><image width="226" height="226" transform="scale(0.24)" opacity="0.45" xlink:href="data:image/png;base64,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" style="mix-blend-mode:multiply"/><g opacity="0"><path d="M27.22,15.21a12,12,0,1,0,12,12,12,12,0,0,0-12-12Z" fill="#fff"/></g><circle cx="27.22" cy="27.21" r="12" fill="#231815" opacity="0.4"/><path d="M27.22,17.21a10,10,0,1,1-10,10,10,10,0,0,1,10-10m0-2a12,12,0,1,0,12,12,12,12,0,0,0-12-12Z" fill="#fff"/><path d="M27.22,45.71a.5.5,0,0,1-.5-.5v-36a.5.5,0,0,1,.5-.5.5.5,0,0,1,.5.5v36A.5.5,0,0,1,27.22,45.71Z" fill="#fff"/><circle cx="27.22" cy="27.21" r="3" fill="#fff"/><path d="M45.22,27.71h-36a.5.5,0,1,1,0-1h36a.5.5,0,0,1,0,1Z" fill="#fff"/></g></g></g></svg>
@@ -0,0 +1,12 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
2
+ <g id="グループ化_1178" data-name="グループ化 1178" transform="translate(-46.471 -347)">
3
+ <g id="グループ化_1177" data-name="グループ化 1177" transform="translate(53.938 354.467)">
4
+ <rect id="長方形_1640" data-name="長方形 1640" width="24.533" height="2.453" fill="#fff"/>
5
+ <rect id="長方形_1641" data-name="長方形 1641" width="24.533" height="2.453" transform="translate(2.453) rotate(90)" fill="#fff"/>
6
+ </g>
7
+ <g id="グループ化_1176" data-name="グループ化 1176" transform="translate(71.005 371.533) rotate(180)">
8
+ <rect id="長方形_1642" data-name="長方形 1642" width="24.533" height="2.453" transform="translate(0 0)" fill="#fff"/>
9
+ <rect id="長方形_1643" data-name="長方形 1643" width="24.533" height="2.453" transform="translate(2.453 0) rotate(90)" fill="#fff"/>
10
+ </g>
11
+ </g>
12
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="30.114" height="30.113" viewBox="0 0 30.114 30.113">
2
+ <path id="パス_96" data-name="パス 96" d="M221.87,39.009h-4.9a9.752,9.752,0,0,0-9.339-9.338v-4.9a.407.407,0,1,0-.814,0v4.9a9.751,9.751,0,0,0-9.339,9.338h-4.9a.407.407,0,0,0,0,.814h4.9a9.751,9.751,0,0,0,9.339,9.339v4.9a.407.407,0,0,0,.814,0v-4.9a9.752,9.752,0,0,0,9.339-9.339h4.9a.407.407,0,1,0,0-.814Zm-6.532,0H209.62a2.432,2.432,0,0,0-1.993-1.993V31.3A8.135,8.135,0,0,1,215.337,39.009ZM206.813,31.3v5.718a2.433,2.433,0,0,0-1.994,1.993H199.1A8.137,8.137,0,0,1,206.813,31.3ZM199.1,39.823h5.718a2.433,2.433,0,0,0,1.994,1.994v5.718A8.135,8.135,0,0,1,199.1,39.823Zm8.525,7.712V41.817a2.431,2.431,0,0,0,1.993-1.994h5.717A8.135,8.135,0,0,1,207.627,47.534Z" transform="translate(-192.163 -24.359)" fill="#fff"/>
3
+ </svg>
@@ -0,0 +1,7 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="20.66" height="26.747" viewBox="0 0 20.66 26.747">
2
+ <g id="グループ化_1180" data-name="グループ化 1180" transform="translate(1.438 1.022)">
3
+ <path id="パス_97" data-name="パス 97" d="M0,0,12.372.2l.2,12.372L.2,12.372Z" transform="translate(0 15.396) rotate(-45)" fill="none" stroke="#fff" stroke-linecap="round" stroke-width="2"/>
4
+ <path id="パス_75" data-name="パス 75" d="M22.8,7l2.4.206.206-2.4" transform="translate(-9.436 -2.195)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
5
+ <path id="パス_76" data-name="パス 76" d="M16.711,5.124a7.259,7.259,0,0,0-7.42-4.053A7.488,7.488,0,0,0,4,4.987" transform="translate(-1.905 -1.009)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
6
+ </g>
7
+ </svg>
@@ -0,0 +1,20 @@
1
+ import type { SlotFillStore } from '@ablogcms/components/slot-fill';
2
+ import type { MediaTransport } from './types/transport.js';
3
+ import type { MediaConfig } from './types/config.js';
4
+ /**
5
+ * `fillStore` は MediaModal を開く 8 経路(メディア管理 / カスタムフィールド / ブロックエディター
6
+ * 画像・ファイル / リッチエディター / バナー / ナビゲーション / ユニット)を横断する `Slot` 差し込み口を
7
+ * 提供するための注入。`@ablogcms/media` は `@ablogcms/plugins/core`(`getGlobalFillBridge()`)に
8
+ * 直接依存しない設計のため、コア(`ablogcms/js/src/features/media/bootstrap.ts`)がここへ注入する。
9
+ * 省略時は `SlotFillProvider` がローカルストアにフォールバックし、`Slot` が throw しない状態を保つ
10
+ * (その場合 Fill はページ横断で共有されない)。
11
+ */
12
+ export declare function configureMediaRuntime(transport: MediaTransport, config?: MediaConfig, fillStore?: SlotFillStore): void;
13
+ export declare function getMediaTransport(): MediaTransport;
14
+ export declare function getMediaConfig(): MediaConfig;
15
+ /** 未注入時は `undefined` を返す。`SlotFillProvider` の `store` prop はこれをそのまま受け取れる(省略時ローカルストアへフォールバック) */
16
+ export declare function getMediaFillStore(): SlotFillStore | undefined;
17
+ /**
18
+ * テスト専用のリセットヘルパー。`configureMediaRuntime` した内容を次のテストへ持ち越さないために使う。
19
+ */
20
+ export declare function resetMediaRuntimeForTesting(): void;
@@ -0,0 +1,16 @@
1
+ import {
2
+ configureMediaRuntime,
3
+ getMediaConfig,
4
+ getMediaFillStore,
5
+ getMediaTransport,
6
+ resetMediaRuntimeForTesting
7
+ } from "./chunk-3SYVRD3N.mjs";
8
+ import "./chunk-J5LGTIGS.mjs";
9
+ export {
10
+ configureMediaRuntime,
11
+ getMediaConfig,
12
+ getMediaFillStore,
13
+ getMediaTransport,
14
+ resetMediaRuntimeForTesting
15
+ };
16
+ //# sourceMappingURL=runtime.mjs.map