@devx-labs/strapi-preview 1.0.5 → 1.0.6

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.
@@ -1,203 +1,3 @@
1
1
  "use strict";
2
- const jsxRuntime = require("react/jsx-runtime");
3
- const react = require("react");
4
- const designSystem = require("@strapi/design-system");
5
- const strapiAdmin = require("@strapi/content-manager/strapi-admin");
6
- const admin = require("@strapi/strapi/admin");
7
- const icons = require("@strapi/icons");
8
- const collectPreviewItems = (value, attributes, componentSchemas, optionsMap) => {
9
- const items = [];
10
- if (!value || !attributes || typeof value !== "object") return items;
11
- const pushItem = (componentUid, tempKey) => {
12
- const opts = optionsMap[componentUid];
13
- if (!opts) return;
14
- const schema = componentSchemas[componentUid];
15
- items.push({
16
- uid: componentUid,
17
- displayName: schema?.info?.displayName ?? componentUid,
18
- previewUrl: opts.url,
19
- previewName: opts.name,
20
- count: 1,
21
- tempKey
22
- });
23
- };
24
- for (const [attributeName, attribute] of Object.entries(attributes)) {
25
- const attributeValue = value[attributeName];
26
- if (!attributeValue) continue;
27
- if (attribute.type === "dynamiczone" && Array.isArray(attributeValue)) {
28
- for (const item of attributeValue) {
29
- if (!item || typeof item !== "object") continue;
30
- const componentUid = item.__component;
31
- const tempKey = item.__temp_key__;
32
- if (componentUid) pushItem(componentUid, tempKey);
33
- }
34
- continue;
35
- }
36
- if (attribute.type === "component" && attribute.component) {
37
- const componentUid = attribute.component;
38
- if (attribute.repeatable && Array.isArray(attributeValue)) {
39
- for (let i = 0; i < attributeValue.length; i++) {
40
- const item = attributeValue[i];
41
- pushItem(componentUid, item?.__temp_key__);
42
- }
43
- } else {
44
- pushItem(componentUid);
45
- }
46
- }
47
- }
48
- return items;
49
- };
50
- const ComponentPreviewPanel = () => {
51
- const { components, contentType, isCreatingEntry } = strapiAdmin.unstable_useContentManagerContext();
52
- const values = admin.useForm("ComponentPreviewPanel", (state) => state.values);
53
- const { get } = admin.useFetchClient();
54
- const [optionsMap, setOptionsMap] = react.useState({});
55
- react.useEffect(() => {
56
- let cancelled = false;
57
- get("/api/component-preview-image/options").then(({ data }) => {
58
- if (!cancelled) setOptionsMap(data ?? {});
59
- }).catch(() => {
60
- if (!cancelled) setOptionsMap({});
61
- });
62
- return () => {
63
- cancelled = true;
64
- };
65
- }, []);
66
- const previewItems = collectPreviewItems(
67
- values,
68
- contentType?.attributes,
69
- components,
70
- optionsMap
71
- );
72
- if (isCreatingEntry) {
73
- return {
74
- title: "Component previews",
75
- content: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", textColor: "neutral600", children: "Save this entry once to load component previews." })
76
- };
77
- }
78
- if (previewItems.length === 0) {
79
- return {
80
- title: "Component previews",
81
- content: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", textColor: "neutral600", children: "No component previews are available for this entry yet." })
82
- };
83
- }
84
- return {
85
- title: "Component previews",
86
- content: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", gap: 4, alignItems: "stretch", children: previewItems.map((item, index2) => /* @__PURE__ */ jsxRuntime.jsx(
87
- designSystem.Box,
88
- {
89
- borderColor: "neutral200",
90
- background: "neutral0",
91
- hasRadius: true,
92
- padding: 3,
93
- shadow: "tableShadow",
94
- width: "100%",
95
- overflow: "hidden",
96
- style: { boxSizing: "border-box" },
97
- children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 3, alignItems: "stretch", children: [
98
- /* @__PURE__ */ jsxRuntime.jsx(
99
- "img",
100
- {
101
- src: item.previewUrl,
102
- alt: item.previewName || item.displayName,
103
- style: {
104
- width: "100%",
105
- maxWidth: "100%",
106
- display: "block",
107
- borderRadius: "8px",
108
- border: "1px solid #dcdce4",
109
- objectFit: "cover",
110
- boxSizing: "border-box"
111
- }
112
- }
113
- ),
114
- /* @__PURE__ */ jsxRuntime.jsxs(
115
- designSystem.Flex,
116
- {
117
- justifyContent: "space-between",
118
- alignItems: "flex-start",
119
- gap: 2,
120
- width: "100%",
121
- children: [
122
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { minWidth: 0, flex: 1 }, children: [
123
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral800", children: item.previewName || item.displayName }),
124
- /* @__PURE__ */ jsxRuntime.jsx(
125
- designSystem.Typography,
126
- {
127
- variant: "pi",
128
- textColor: "neutral600",
129
- style: {
130
- display: "block",
131
- overflowWrap: "anywhere",
132
- wordBreak: "break-word"
133
- },
134
- children: item.uid
135
- }
136
- )
137
- ] }),
138
- /* @__PURE__ */ jsxRuntime.jsx(
139
- designSystem.Button,
140
- {
141
- variant: "tertiary",
142
- size: "S",
143
- tag: "a",
144
- href: item.previewUrl,
145
- target: "_blank",
146
- rel: "noreferrer",
147
- endIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ExternalLink, {}),
148
- style: { flexShrink: 0 },
149
- children: "Open"
150
- }
151
- )
152
- ]
153
- }
154
- )
155
- ] })
156
- },
157
- item.tempKey ?? `${index2}-${item.uid}`
158
- )) })
159
- };
160
- };
161
- const index = {
162
- register(app) {
163
- app.customFields.register({
164
- name: "preview-image",
165
- pluginId: "component-preview-image",
166
- type: "string",
167
- inputSize: { default: 12, isResizable: false },
168
- intlLabel: {
169
- id: "component-preview-image.preview-image.label",
170
- defaultMessage: "Preview Image"
171
- },
172
- intlDescription: {
173
- id: "component-preview-image.preview-image.description",
174
- defaultMessage: "Schema-level preview image — set the image URL once in the Content-Type Builder, shown in the edit-view side panel"
175
- },
176
- components: {
177
- Input: async () => Promise.resolve().then(() => require("../_chunks/PreviewImageInput-Bha74a3E.js")).then((mod) => ({
178
- default: mod.PreviewImageInput
179
- }))
180
- },
181
- options: {
182
- base: [
183
- {
184
- name: "options.url",
185
- type: "text",
186
- intlLabel: {
187
- id: "component-preview-image.options.url.label",
188
- defaultMessage: "Preview Image URL"
189
- },
190
- description: {
191
- id: "component-preview-image.options.url.description",
192
- defaultMessage: "Direct URL of the image to display in the preview panel"
193
- }
194
- }
195
- ]
196
- }
197
- });
198
- },
199
- bootstrap(app) {
200
- app.getPlugin("content-manager").apis.addEditViewSidePanel([ComponentPreviewPanel]);
201
- }
202
- };
203
- module.exports = index;
2
+ const index = require("../_chunks/index-7LCKy9W3.js");
3
+ module.exports = index.index;
@@ -1,204 +1,4 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
2
- import { useState, useEffect } from "react";
3
- import { Typography, Flex, Box, Button } from "@strapi/design-system";
4
- import { unstable_useContentManagerContext } from "@strapi/content-manager/strapi-admin";
5
- import { useForm, useFetchClient } from "@strapi/strapi/admin";
6
- import { ExternalLink } from "@strapi/icons";
7
- const collectPreviewItems = (value, attributes, componentSchemas, optionsMap) => {
8
- const items = [];
9
- if (!value || !attributes || typeof value !== "object") return items;
10
- const pushItem = (componentUid, tempKey) => {
11
- const opts = optionsMap[componentUid];
12
- if (!opts) return;
13
- const schema = componentSchemas[componentUid];
14
- items.push({
15
- uid: componentUid,
16
- displayName: schema?.info?.displayName ?? componentUid,
17
- previewUrl: opts.url,
18
- previewName: opts.name,
19
- count: 1,
20
- tempKey
21
- });
22
- };
23
- for (const [attributeName, attribute] of Object.entries(attributes)) {
24
- const attributeValue = value[attributeName];
25
- if (!attributeValue) continue;
26
- if (attribute.type === "dynamiczone" && Array.isArray(attributeValue)) {
27
- for (const item of attributeValue) {
28
- if (!item || typeof item !== "object") continue;
29
- const componentUid = item.__component;
30
- const tempKey = item.__temp_key__;
31
- if (componentUid) pushItem(componentUid, tempKey);
32
- }
33
- continue;
34
- }
35
- if (attribute.type === "component" && attribute.component) {
36
- const componentUid = attribute.component;
37
- if (attribute.repeatable && Array.isArray(attributeValue)) {
38
- for (let i = 0; i < attributeValue.length; i++) {
39
- const item = attributeValue[i];
40
- pushItem(componentUid, item?.__temp_key__);
41
- }
42
- } else {
43
- pushItem(componentUid);
44
- }
45
- }
46
- }
47
- return items;
48
- };
49
- const ComponentPreviewPanel = () => {
50
- const { components, contentType, isCreatingEntry } = unstable_useContentManagerContext();
51
- const values = useForm("ComponentPreviewPanel", (state) => state.values);
52
- const { get } = useFetchClient();
53
- const [optionsMap, setOptionsMap] = useState({});
54
- useEffect(() => {
55
- let cancelled = false;
56
- get("/api/component-preview-image/options").then(({ data }) => {
57
- if (!cancelled) setOptionsMap(data ?? {});
58
- }).catch(() => {
59
- if (!cancelled) setOptionsMap({});
60
- });
61
- return () => {
62
- cancelled = true;
63
- };
64
- }, []);
65
- const previewItems = collectPreviewItems(
66
- values,
67
- contentType?.attributes,
68
- components,
69
- optionsMap
70
- );
71
- if (isCreatingEntry) {
72
- return {
73
- title: "Component previews",
74
- content: /* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", children: "Save this entry once to load component previews." })
75
- };
76
- }
77
- if (previewItems.length === 0) {
78
- return {
79
- title: "Component previews",
80
- content: /* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", children: "No component previews are available for this entry yet." })
81
- };
82
- }
83
- return {
84
- title: "Component previews",
85
- content: /* @__PURE__ */ jsx(Flex, { direction: "column", gap: 4, alignItems: "stretch", children: previewItems.map((item, index2) => /* @__PURE__ */ jsx(
86
- Box,
87
- {
88
- borderColor: "neutral200",
89
- background: "neutral0",
90
- hasRadius: true,
91
- padding: 3,
92
- shadow: "tableShadow",
93
- width: "100%",
94
- overflow: "hidden",
95
- style: { boxSizing: "border-box" },
96
- children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, alignItems: "stretch", children: [
97
- /* @__PURE__ */ jsx(
98
- "img",
99
- {
100
- src: item.previewUrl,
101
- alt: item.previewName || item.displayName,
102
- style: {
103
- width: "100%",
104
- maxWidth: "100%",
105
- display: "block",
106
- borderRadius: "8px",
107
- border: "1px solid #dcdce4",
108
- objectFit: "cover",
109
- boxSizing: "border-box"
110
- }
111
- }
112
- ),
113
- /* @__PURE__ */ jsxs(
114
- Flex,
115
- {
116
- justifyContent: "space-between",
117
- alignItems: "flex-start",
118
- gap: 2,
119
- width: "100%",
120
- children: [
121
- /* @__PURE__ */ jsxs(Box, { style: { minWidth: 0, flex: 1 }, children: [
122
- /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral800", children: item.previewName || item.displayName }),
123
- /* @__PURE__ */ jsx(
124
- Typography,
125
- {
126
- variant: "pi",
127
- textColor: "neutral600",
128
- style: {
129
- display: "block",
130
- overflowWrap: "anywhere",
131
- wordBreak: "break-word"
132
- },
133
- children: item.uid
134
- }
135
- )
136
- ] }),
137
- /* @__PURE__ */ jsx(
138
- Button,
139
- {
140
- variant: "tertiary",
141
- size: "S",
142
- tag: "a",
143
- href: item.previewUrl,
144
- target: "_blank",
145
- rel: "noreferrer",
146
- endIcon: /* @__PURE__ */ jsx(ExternalLink, {}),
147
- style: { flexShrink: 0 },
148
- children: "Open"
149
- }
150
- )
151
- ]
152
- }
153
- )
154
- ] })
155
- },
156
- item.tempKey ?? `${index2}-${item.uid}`
157
- )) })
158
- };
159
- };
160
- const index = {
161
- register(app) {
162
- app.customFields.register({
163
- name: "preview-image",
164
- pluginId: "component-preview-image",
165
- type: "string",
166
- inputSize: { default: 12, isResizable: false },
167
- intlLabel: {
168
- id: "component-preview-image.preview-image.label",
169
- defaultMessage: "Preview Image"
170
- },
171
- intlDescription: {
172
- id: "component-preview-image.preview-image.description",
173
- defaultMessage: "Schema-level preview image — set the image URL once in the Content-Type Builder, shown in the edit-view side panel"
174
- },
175
- components: {
176
- Input: async () => import("../_chunks/PreviewImageInput-BcPJkyKS.mjs").then((mod) => ({
177
- default: mod.PreviewImageInput
178
- }))
179
- },
180
- options: {
181
- base: [
182
- {
183
- name: "options.url",
184
- type: "text",
185
- intlLabel: {
186
- id: "component-preview-image.options.url.label",
187
- defaultMessage: "Preview Image URL"
188
- },
189
- description: {
190
- id: "component-preview-image.options.url.description",
191
- defaultMessage: "Direct URL of the image to display in the preview panel"
192
- }
193
- }
194
- ]
195
- }
196
- });
197
- },
198
- bootstrap(app) {
199
- app.getPlugin("content-manager").apis.addEditViewSidePanel([ComponentPreviewPanel]);
200
- }
201
- };
1
+ import { i } from "../_chunks/index-BUqIITfj.mjs";
202
2
  export {
203
- index as default
3
+ i as default
204
4
  };
@@ -8,7 +8,8 @@ const optionsController = ({ strapi }) => ({
8
8
  if (attr.customField === CUSTOM_FIELD_KEY && attr.options?.url) {
9
9
  result[uid] = {
10
10
  name: schema.info?.displayName || uid,
11
- url: attr.options.url
11
+ url: attr.options.url,
12
+ disableIframe: Boolean(attr.options.disableIframe)
12
13
  };
13
14
  break;
14
15
  }
@@ -7,7 +7,8 @@ const optionsController = ({ strapi }) => ({
7
7
  if (attr.customField === CUSTOM_FIELD_KEY && attr.options?.url) {
8
8
  result[uid] = {
9
9
  name: schema.info?.displayName || uid,
10
- url: attr.options.url
10
+ url: attr.options.url,
11
+ disableIframe: Boolean(attr.options.disableIframe)
11
12
  };
12
13
  break;
13
14
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devx-labs/strapi-preview",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Strapi 5 plugin that adds a preview-image custom field (configured per component in the Content-Type Builder with a direct image URL) and renders a side panel in the edit view showing each component's preview image in dynamic-zone order.",
5
5
  "keywords": [
6
6
  "strapi",
@@ -1,22 +0,0 @@
1
- import { jsx } from "react/jsx-runtime";
2
- import { Flex, LinkButton } from "@strapi/design-system";
3
- import { ExternalLink } from "@strapi/icons";
4
- const PreviewImageInput = ({ attribute }) => {
5
- const url = attribute?.options?.url;
6
- if (!url) return null;
7
- return /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
8
- LinkButton,
9
- {
10
- href: url,
11
- target: "_blank",
12
- rel: "noreferrer",
13
- variant: "tertiary",
14
- size: "S",
15
- endIcon: /* @__PURE__ */ jsx(ExternalLink, {}),
16
- children: "Preview"
17
- }
18
- ) });
19
- };
20
- export {
21
- PreviewImageInput
22
- };
@@ -1,22 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const jsxRuntime = require("react/jsx-runtime");
4
- const designSystem = require("@strapi/design-system");
5
- const icons = require("@strapi/icons");
6
- const PreviewImageInput = ({ attribute }) => {
7
- const url = attribute?.options?.url;
8
- if (!url) return null;
9
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxRuntime.jsx(
10
- designSystem.LinkButton,
11
- {
12
- href: url,
13
- target: "_blank",
14
- rel: "noreferrer",
15
- variant: "tertiary",
16
- size: "S",
17
- endIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ExternalLink, {}),
18
- children: "Preview"
19
- }
20
- ) });
21
- };
22
- exports.PreviewImageInput = PreviewImageInput;