@plasmicpkgs/plasmic-content-stack 0.0.130 → 0.0.131

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/index.mjs ADDED
@@ -0,0 +1,479 @@
1
+ // src/index.tsx
2
+ import registerComponent from "@plasmicapp/host/registerComponent";
3
+ import registerGlobalContext from "@plasmicapp/host/registerGlobalContext";
4
+
5
+ // src/contentstack.tsx
6
+ import {
7
+ DataProvider,
8
+ repeatedElement,
9
+ useSelector
10
+ } from "@plasmicapp/host";
11
+ import { usePlasmicQueryData } from "@plasmicapp/query";
12
+ import { pascalCase } from "change-case";
13
+ import get from "dlv";
14
+ import React, { useContext } from "react";
15
+
16
+ // src/utils.ts
17
+ var queryOperators = [
18
+ {
19
+ value: "",
20
+ label: "Is"
21
+ },
22
+ {
23
+ value: "$ne",
24
+ label: "Is not"
25
+ },
26
+ {
27
+ value: "$lt",
28
+ label: "Less than"
29
+ },
30
+ {
31
+ value: "$lte",
32
+ label: "Less than or equal"
33
+ },
34
+ {
35
+ value: "$gt",
36
+ label: "Greater than"
37
+ },
38
+ {
39
+ value: "$gte",
40
+ label: "Greater than or equal "
41
+ }
42
+ ];
43
+
44
+ // src/contentstack.tsx
45
+ function ensure(x) {
46
+ if (x === null || x === void 0) {
47
+ debugger;
48
+ throw new Error(`Value must not be undefined or null`);
49
+ } else {
50
+ return x;
51
+ }
52
+ }
53
+ var modulePath = "@plasmicpkgs/plasmic-content-stack";
54
+ var makeDataProviderName = (contentType) => `currentContentstack${pascalCase(contentType)}Item`;
55
+ var CredentialsContext = React.createContext(void 0);
56
+ var ContentStackCredentialsProviderMeta = {
57
+ name: "ContentStackCredentialsProvider",
58
+ displayName: "ContentStack Credentials Provider",
59
+ description: "The API key is a unique key assigned to each stack. Learn how to [get your API key](https://www.contentstack.com/docs/developers/apis/content-management-api/#how-to-get-stack-api-key).",
60
+ importName: "ContentStackCredentialsProvider",
61
+ importPath: modulePath,
62
+ props: {
63
+ apiKey: {
64
+ type: "string",
65
+ displayName: "API Key",
66
+ description: "API Key of your Stack ",
67
+ defaultValue: "blt02f7b45378b008ee"
68
+ },
69
+ accessToken: {
70
+ type: "string",
71
+ displayName: "Access Token ",
72
+ description: "Access Token",
73
+ defaultValue: "cs5b69faf35efdebd91d08bcf4"
74
+ },
75
+ environment: {
76
+ type: "string",
77
+ displayName: "Environment",
78
+ defaultValue: "production"
79
+ }
80
+ }
81
+ };
82
+ function ContentStackCredentialsProvider({
83
+ apiKey,
84
+ accessToken,
85
+ environment,
86
+ children
87
+ }) {
88
+ return /* @__PURE__ */ React.createElement(CredentialsContext.Provider, { value: { apiKey, accessToken, environment } }, children);
89
+ }
90
+ var ContentStackFetcherMeta = {
91
+ name: "ContentStackFetcher",
92
+ displayName: "ContentStack Fetcher",
93
+ importName: "ContentStackFetcher",
94
+ importPath: modulePath,
95
+ providesData: true,
96
+ description: "Fetches ContentStack data and repeats content of children once for every row fetched. ",
97
+ defaultStyles: {
98
+ display: "grid",
99
+ gridTemplateColumns: "1fr 1fr 1fr 1fr",
100
+ gridRowGap: "8px",
101
+ gridColumnGap: "8px",
102
+ padding: "8px",
103
+ maxWidth: "100%"
104
+ },
105
+ props: {
106
+ children: {
107
+ type: "slot",
108
+ defaultValue: {
109
+ type: "vbox",
110
+ styles: {
111
+ padding: "8px"
112
+ },
113
+ children: {
114
+ type: "component",
115
+ name: "ContentStackField"
116
+ }
117
+ }
118
+ },
119
+ contentType: {
120
+ type: "choice",
121
+ options: (props, ctx) => {
122
+ var _a, _b;
123
+ return (_b = (_a = ctx == null ? void 0 : ctx.types) == null ? void 0 : _a.map((type) => ({
124
+ label: type == null ? void 0 : type.title,
125
+ value: type == null ? void 0 : type.uid
126
+ }))) != null ? _b : [];
127
+ },
128
+ displayName: "Content type",
129
+ description: "Content type to be queried."
130
+ },
131
+ filterField: {
132
+ type: "choice",
133
+ displayName: "Filter field",
134
+ description: "Field (from Collection) to filter by",
135
+ options: (props, ctx) => {
136
+ var _a;
137
+ return (_a = ctx == null ? void 0 : ctx.filterFields) != null ? _a : [];
138
+ },
139
+ hidden: (props, ctx) => !props.contentType
140
+ },
141
+ queryOperator: {
142
+ type: "choice",
143
+ displayName: "Query Operator",
144
+ description: "Query Operator filter by",
145
+ options: (props, ctx) => {
146
+ var _a;
147
+ return (_a = ctx == null ? void 0 : ctx.queryOptions) != null ? _a : [];
148
+ },
149
+ hidden: (props, ctx) => !props.filterField
150
+ },
151
+ filterValue: {
152
+ type: "string",
153
+ displayName: "Filter value",
154
+ description: "Value to filter by, should be of filter field type"
155
+ },
156
+ limit: {
157
+ type: "number",
158
+ displayName: "Limit",
159
+ description: "Limit"
160
+ },
161
+ noAutoRepeat: {
162
+ type: "boolean",
163
+ displayName: "No auto-repeat",
164
+ description: "Do not automatically repeat children for every entries.",
165
+ defaultValue: false
166
+ },
167
+ noLayout: {
168
+ type: "boolean",
169
+ displayName: "No layout",
170
+ description: "When set, ContentStack Fetcher will not layout its children; instead, the layout set on its parent element will be used. Useful if you want to set flex gap or control container tag type.",
171
+ defaultValue: false
172
+ }
173
+ }
174
+ };
175
+ function ContentStackFetcher({
176
+ contentType,
177
+ filterField,
178
+ filterValue,
179
+ queryOperator,
180
+ limit,
181
+ noAutoRepeat,
182
+ children,
183
+ className,
184
+ noLayout,
185
+ setControlContextData
186
+ }) {
187
+ var _a, _b;
188
+ const creds = ensure(useContext(CredentialsContext));
189
+ const cacheKey = JSON.stringify({
190
+ limit,
191
+ contentType,
192
+ filterField,
193
+ filterValue,
194
+ queryOperator,
195
+ creds
196
+ });
197
+ const allContentTypes = usePlasmicQueryData(
198
+ `${cacheKey}/contentTypes`,
199
+ async () => {
200
+ const resp = await fetch(
201
+ "https://cdn.contentstack.io/v3/content_types?include_count=true&include_global_field_schema=true",
202
+ {
203
+ headers: {
204
+ api_key: creds.apiKey,
205
+ access_token: creds.accessToken
206
+ }
207
+ }
208
+ );
209
+ return resp.json();
210
+ }
211
+ );
212
+ const contentTypes = (_a = allContentTypes.data) != null ? _a : [];
213
+ const { data: entriesData } = usePlasmicQueryData(
214
+ contentType ? `${cacheKey}/${contentType}/entries` : null,
215
+ async () => {
216
+ const url = `https://cdn.contentstack.io/v3/content_types/${contentType}/entries?environment=${creds.environment}`;
217
+ let query;
218
+ if (limit) {
219
+ query = `${url}&limit=${limit}`;
220
+ } else {
221
+ query = url;
222
+ }
223
+ const resp = await fetch(query, {
224
+ headers: {
225
+ api_key: creds.apiKey,
226
+ access_token: creds.accessToken
227
+ }
228
+ });
229
+ return await resp.json();
230
+ }
231
+ );
232
+ const { data: filteredData } = usePlasmicQueryData(
233
+ contentType && filterField && filterValue && entriesData ? `${cacheKey}/${contentType}/filtered` : null,
234
+ async () => {
235
+ if (!contentType && !filterField && !filterValue && !entriesData && !contentTypes) {
236
+ return null;
237
+ }
238
+ const matched = Object.values(entriesData).flatMap((model) => Array.isArray(model) ? model : [model]).map((item) => {
239
+ const fields = Object.entries(item).find(
240
+ (el) => el[0] === filterField
241
+ );
242
+ return fields;
243
+ });
244
+ let url;
245
+ if (!queryOperator) {
246
+ Object.values(matched).map((model) => Array.isArray(model) ? model : [model]).map((item) => {
247
+ if (typeof item[1] === "number" && typeof item[1] !== "object") {
248
+ url = `https://cdn.contentstack.io/v3/content_types/${contentType}/entries?environment=${creds.environment}&query={"${filterField}" : ${filterValue}}`;
249
+ } else if (typeof item[1] !== "number" && typeof item[1] !== "object" && typeof item[1] === "string") {
250
+ url = `https://cdn.contentstack.io/v3/content_types/${contentType}/entries?environment=${creds.environment}&query=${JSON.stringify({
251
+ [filterField]: filterValue
252
+ })}`;
253
+ } else {
254
+ url = "";
255
+ }
256
+ });
257
+ } else if (queryOperator === "$ne" || queryOperator === "$regex") {
258
+ Object.values(matched).map((model) => Array.isArray(model) ? model : [model]).map((item) => {
259
+ if (typeof item[1] === "number" && typeof item[1] !== "object") {
260
+ url = `https://cdn.contentstack.io/v3/content_types/${contentType}/entries?environment=${creds.environment}&query={"${filterField}":{"${queryOperator}":${filterValue}}}`;
261
+ } else if (typeof item[1] !== "number" && typeof item[1] !== "object" && typeof item[1] === "string") {
262
+ url = `https://cdn.contentstack.io/v3/content_types/${contentType}/entries?environment=${creds.environment}&query=${JSON.stringify({
263
+ [filterField]: { [queryOperator]: filterValue }
264
+ })}`;
265
+ } else {
266
+ url = "";
267
+ }
268
+ });
269
+ } else {
270
+ url = `https://cdn.contentstack.io/v3/content_types/${contentType}/entries?environment=${creds.environment}&query={"${filterField}":{"${queryOperator}" :${filterValue}}}`;
271
+ }
272
+ const resp = await fetch(url, {
273
+ headers: {
274
+ api_key: creds.apiKey,
275
+ access_token: creds.accessToken
276
+ }
277
+ });
278
+ return await resp.json();
279
+ }
280
+ );
281
+ if (!contentTypes) {
282
+ return /* @__PURE__ */ React.createElement("div", null, "Please configure the ContentStack credentials");
283
+ }
284
+ const types = Object.values(contentTypes).flatMap((model) => {
285
+ return model;
286
+ });
287
+ setControlContextData == null ? void 0 : setControlContextData({
288
+ types
289
+ });
290
+ if (!creds.apiKey || !creds.accessToken || !creds.environment) {
291
+ return /* @__PURE__ */ React.createElement("div", null, "Please specify a valid API Credentials: API Key, Access Token and Environment");
292
+ }
293
+ if (!entriesData) {
294
+ return /* @__PURE__ */ React.createElement("div", null, "Please specify content type ");
295
+ }
296
+ const fieldsForFilter = Object.values(entriesData).flatMap((model) => Array.isArray(model) ? model : [model]).map((item) => {
297
+ const fields = Object.keys(item).filter((field) => {
298
+ const value = get(item, field);
299
+ return typeof value !== "object" && field !== "images" && typeof value === "number" || typeof value === "string" && !value.match(
300
+ /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?Z?/gm
301
+ ) && !value.match(/^blt.*/);
302
+ });
303
+ return fields;
304
+ });
305
+ let operators;
306
+ const matchedFields = Object.values(entriesData).flatMap((model) => Array.isArray(model) ? model : [model]).map((item) => {
307
+ const fields = Object.entries(item).find((el) => el[0] === filterField);
308
+ return fields;
309
+ });
310
+ Object.values(matchedFields).map((model) => Array.isArray(model) ? model : [model]).map((item) => {
311
+ if (typeof item[1] === "number" && typeof item[1] !== "object") {
312
+ operators = queryOperators;
313
+ } else if (typeof item[1] !== "number" && typeof item[1] !== "object" && typeof item[1] === "string") {
314
+ operators = [
315
+ {
316
+ value: "",
317
+ label: "Is"
318
+ },
319
+ {
320
+ value: "$ne",
321
+ label: "Is not"
322
+ },
323
+ {
324
+ value: "$regex",
325
+ label: "Matches regex"
326
+ }
327
+ ];
328
+ }
329
+ });
330
+ setControlContextData == null ? void 0 : setControlContextData({
331
+ queryOptions: operators,
332
+ types,
333
+ filterFields: fieldsForFilter[0]
334
+ });
335
+ if (queryOperator && !filterValue && !filterField) {
336
+ return /* @__PURE__ */ React.createElement("div", null, "Please specify a Filter Field and a Filter Value");
337
+ }
338
+ if (!queryOperator && filterValue && !filterField) {
339
+ return /* @__PURE__ */ React.createElement("div", null, "Please specify a Query Operator and a Filter Field");
340
+ }
341
+ if (!queryOperator && !filterValue && filterField) {
342
+ return /* @__PURE__ */ React.createElement("div", null, "Please specify a Query Operator and a Filter Value");
343
+ }
344
+ if (queryOperator && filterValue && !filterField) {
345
+ return /* @__PURE__ */ React.createElement("div", null, "Please specify a Filter Field");
346
+ }
347
+ if (queryOperator && !filterValue && filterField) {
348
+ return /* @__PURE__ */ React.createElement("div", null, "Please specify a Filter Value");
349
+ }
350
+ const entries = Object.values(entriesData).flatMap(
351
+ (item) => Array.isArray(item) ? item : [item]
352
+ );
353
+ let renderedData;
354
+ if (filteredData) {
355
+ const filtered = Object.values(filteredData).flatMap((model) => model).length;
356
+ if (filtered === 0) {
357
+ return /* @__PURE__ */ React.createElement("div", null, "No published entry found ");
358
+ }
359
+ const entries2 = Object.values(filteredData).flatMap(
360
+ (model) => Array.isArray(model) ? model : [model]
361
+ );
362
+ renderedData = entries2 == null ? void 0 : entries2.map((item, index) => /* @__PURE__ */ React.createElement(
363
+ DataProvider,
364
+ {
365
+ key: item._id,
366
+ name: "contentstackItem",
367
+ data: item,
368
+ hidden: true
369
+ },
370
+ /* @__PURE__ */ React.createElement(DataProvider, { name: makeDataProviderName(contentType), data: item }, repeatedElement(index, children))
371
+ ));
372
+ } else {
373
+ const entries2 = Object.values(entriesData).flatMap(
374
+ (model) => Array.isArray(model) ? model : [model]
375
+ );
376
+ renderedData = entries2 == null ? void 0 : entries2.map((item, index) => /* @__PURE__ */ React.createElement(
377
+ DataProvider,
378
+ {
379
+ key: item._id,
380
+ name: "contentstackItem",
381
+ data: item,
382
+ hidden: true
383
+ },
384
+ /* @__PURE__ */ React.createElement(DataProvider, { name: makeDataProviderName(contentType), data: item }, repeatedElement(index, children))
385
+ ));
386
+ }
387
+ return /* @__PURE__ */ React.createElement(DataProvider, { data: entries, name: "contentStackItems" }, noAutoRepeat ? children : /* @__PURE__ */ React.createElement(
388
+ DataProvider,
389
+ {
390
+ name: "contentstackSchema",
391
+ data: (_b = types == null ? void 0 : types.find((type) => type.uid === contentType)) == null ? void 0 : _b.schema,
392
+ hidden: true
393
+ },
394
+ noLayout ? /* @__PURE__ */ React.createElement(React.Fragment, null, " ", renderedData, " ") : /* @__PURE__ */ React.createElement("div", { className }, " ", renderedData, " ")
395
+ ));
396
+ }
397
+ var ContentStackFieldMeta = {
398
+ name: "ContentStackField",
399
+ displayName: "ContentStack Field",
400
+ importName: "ContentStackField",
401
+ importPath: modulePath,
402
+ props: {
403
+ objectPath: {
404
+ type: "dataSelector",
405
+ data: (props, ctx) => {
406
+ var _a;
407
+ return (_a = ctx == null ? void 0 : ctx.data) != null ? _a : {};
408
+ },
409
+ displayName: "Field",
410
+ description: "Field to be displayed."
411
+ }
412
+ }
413
+ };
414
+ function ContentStackField({
415
+ objectPath,
416
+ setControlContextData,
417
+ ...rest
418
+ }) {
419
+ var _a;
420
+ const item = useSelector("contentstackItem");
421
+ if (!item) {
422
+ return /* @__PURE__ */ React.createElement("div", null, "ContentStackField must be used within a ContentStackFetcher ");
423
+ }
424
+ const schema = useSelector("contentstackSchema");
425
+ setControlContextData == null ? void 0 : setControlContextData({
426
+ data: item
427
+ });
428
+ if (!objectPath) {
429
+ return /* @__PURE__ */ React.createElement("div", null, "Please specify a valid path or select a field.");
430
+ }
431
+ const isRichText = () => {
432
+ var _a2, _b;
433
+ return (_b = (_a2 = schema == null ? void 0 : schema.find((field) => field.uid === get(objectPath, [0]))) == null ? void 0 : _a2.field_metadata) == null ? void 0 : _b.allow_rich_text;
434
+ };
435
+ const data = get(item, objectPath);
436
+ if (typeof data === "object" && ((_a = data == null ? void 0 : data.content_type) == null ? void 0 : _a.startsWith("image"))) {
437
+ return /* @__PURE__ */ React.createElement("img", { ...rest, src: data.url });
438
+ } else if (!data || typeof data === "object") {
439
+ return /* @__PURE__ */ React.createElement("div", { ...rest }, " Please specify a valid field.");
440
+ } else if (isRichText()) {
441
+ return /* @__PURE__ */ React.createElement("div", { ...rest, dangerouslySetInnerHTML: { __html: data } });
442
+ } else {
443
+ return /* @__PURE__ */ React.createElement("div", { ...rest }, " ", data, " ");
444
+ }
445
+ }
446
+
447
+ // src/index.tsx
448
+ function registerAll(loader) {
449
+ const _registerComponent = (Component, defaultMeta) => {
450
+ if (loader) {
451
+ loader.registerComponent(Component, defaultMeta);
452
+ } else {
453
+ registerComponent(Component, defaultMeta);
454
+ }
455
+ };
456
+ if (loader) {
457
+ loader.registerGlobalContext(
458
+ ContentStackCredentialsProvider,
459
+ ContentStackCredentialsProviderMeta
460
+ );
461
+ } else {
462
+ registerGlobalContext(
463
+ ContentStackCredentialsProvider,
464
+ ContentStackCredentialsProviderMeta
465
+ );
466
+ }
467
+ _registerComponent(ContentStackFetcher, ContentStackFetcherMeta);
468
+ _registerComponent(ContentStackField, ContentStackFieldMeta);
469
+ }
470
+ export {
471
+ ContentStackCredentialsProvider,
472
+ ContentStackCredentialsProviderMeta,
473
+ ContentStackFetcher,
474
+ ContentStackFetcherMeta,
475
+ ContentStackField,
476
+ ContentStackFieldMeta,
477
+ ensure,
478
+ registerAll
479
+ };
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@plasmicpkgs/plasmic-content-stack",
3
- "version": "0.0.130",
3
+ "version": "0.0.131",
4
4
  "description": "Plasmic ContentStack components.",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
7
- "module": "dist/plasmic-content-stack.esm.js",
7
+ "module": "dist/index.mjs",
8
8
  "publishConfig": {
9
9
  "access": "public"
10
10
  },
@@ -12,10 +12,8 @@
12
12
  "dist"
13
13
  ],
14
14
  "scripts": {
15
- "start": "tsdx watch",
16
- "build": "tsdx build",
15
+ "build": "tsup-node src/index.tsx --dts --format esm,cjs --target es2019",
17
16
  "test": "yarn --cwd=../.. test --passWithNoTests",
18
- "lint": "tsdx lint",
19
17
  "prepare": "if-env PREPARE_NO_BUILD=true || yarn build",
20
18
  "size": "size-limit",
21
19
  "analyze": "size-limit --why"
@@ -25,11 +23,11 @@
25
23
  },
26
24
  "size-limit": [
27
25
  {
28
- "path": "dist/plasmic-content-stack.cjs.production.min.js",
26
+ "path": "dist/index.js",
29
27
  "limit": "10 KB"
30
28
  },
31
29
  {
32
- "path": "dist/plasmic-content-stack.esm.js",
30
+ "path": "dist/index.mjs",
33
31
  "limit": "10 KB"
34
32
  }
35
33
  ],
@@ -44,13 +42,14 @@
44
42
  "react": "^18.2.0",
45
43
  "react-dom": "^18.2.0",
46
44
  "size-limit": "^7.0.8",
47
- "tsdx": "^0.14.1",
48
- "tslib": "^2.3.1"
45
+ "tslib": "^2.3.1",
46
+ "tsup": "^7.2.0",
47
+ "typescript": "^5.2.2"
49
48
  },
50
49
  "dependencies": {
51
50
  "change-case": "^4.1.2",
52
51
  "contentstack": "^3.15.1",
53
52
  "dlv": "^1.1.3"
54
53
  },
55
- "gitHead": "cb170c2bd81daed2ffb1758c82e49b48086aaef0"
54
+ "gitHead": "d387b9e838764794b8513b5c19288f37c7981dc4"
56
55
  }
@@ -1,41 +0,0 @@
1
- import { ComponentMeta, GlobalContextMeta } from "@plasmicapp/host";
2
- import React, { ReactNode } from "react";
3
- export declare function ensure<T>(x: T | null | undefined): T;
4
- interface ContentStackCredentialsProviderProps {
5
- apiKey: string;
6
- accessToken: string;
7
- environment: string;
8
- }
9
- export declare const ContentStackCredentialsProviderMeta: GlobalContextMeta<ContentStackCredentialsProviderProps>;
10
- export declare function ContentStackCredentialsProvider({ apiKey, accessToken, environment, children, }: React.PropsWithChildren<ContentStackCredentialsProviderProps>): React.JSX.Element;
11
- interface ContentStackFetcherProps {
12
- contentType: string;
13
- children?: ReactNode;
14
- className?: string;
15
- noLayout?: boolean;
16
- filterField?: string;
17
- queryOperator?: string;
18
- filterValue?: string | number;
19
- limit?: number;
20
- noAutoRepeat?: boolean;
21
- setControlContextData?: (data: {
22
- types?: {
23
- title: string;
24
- uid: string;
25
- }[];
26
- filterFields?: string[];
27
- queryOptions?: [];
28
- }) => void;
29
- }
30
- export declare const ContentStackFetcherMeta: ComponentMeta<ContentStackFetcherProps>;
31
- export declare function ContentStackFetcher({ contentType, filterField, filterValue, queryOperator, limit, noAutoRepeat, children, className, noLayout, setControlContextData, }: ContentStackFetcherProps): React.JSX.Element;
32
- interface ContentStackFieldProps {
33
- className?: string;
34
- objectPath?: (string | number)[];
35
- setControlContextData?: (data: {
36
- data: Record<string, any>;
37
- }) => void;
38
- }
39
- export declare const ContentStackFieldMeta: ComponentMeta<ContentStackFieldProps>;
40
- export declare function ContentStackField({ objectPath, setControlContextData, ...rest }: ContentStackFieldProps): React.JSX.Element;
41
- export {};