droplinked-editor-configs 1.8.4 → 1.8.5

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "droplinked-editor-configs",
3
3
  "private": false,
4
- "version": "1.8.4",
4
+ "version": "1.8.5",
5
5
  "type": "module",
6
6
  "main": "dist/droplinked-editor.umd.js",
7
7
  "module": "dist/droplinked-editor.es.js",
@@ -34,7 +34,7 @@
34
34
  "classnames": "^2.5.1",
35
35
  "clsx": "^2.1.1",
36
36
  "cmdk": "^1.1.1",
37
- "droplinked-editor-core": "^1.1.7",
37
+ "droplinked-editor-core": "^1.1.8",
38
38
  "framer-motion": "^8.5.0",
39
39
  "keen-slider": "^6.8.6",
40
40
  "lucide-react": "^0.525.0",
@@ -10,45 +10,6 @@ export interface BlogPost {
10
10
  slug: string;
11
11
  }
12
12
 
13
- export interface IBlogContent {
14
- _id: string;
15
- shopID: string;
16
- author: string;
17
- content: string;
18
- title: string;
19
- writer: string;
20
- isVisible: boolean;
21
- category: string[];
22
- tags: string[];
23
- commentsCount: number;
24
- image: string;
25
- likes: number;
26
- readTime: number;
27
- version: number;
28
- isFeatured: boolean;
29
- seoData: {
30
- metaDescription: string;
31
- keywords: string[];
32
- slug: string;
33
- canonicalUrl: string;
34
- ogTitle: string;
35
- ogDescription: string;
36
- ogImage: string;
37
- structuredData: string;
38
- _id: string;
39
- },
40
- mediaData: {
41
- url: string;
42
- title: string;
43
- positionIndex: number;
44
- _id: string;
45
- }[],
46
- publishedDate: string;
47
- createdAt: string;
48
- updatedAt: Date;
49
- __v: number;
50
- }
51
-
52
13
  export interface Blog {
53
14
  featured: BlogPost[];
54
15
  recent: BlogPost[];
@@ -1,8 +1,5 @@
1
1
  import axiosInstance from "apis/axiosConfig"
2
- import { Blog, IBlogContent } from "./interfaces"
2
+ import { Blog } from "./interfaces"
3
3
 
4
4
  export const getShopBlogsService = (shopName: string) =>
5
- axiosInstance.get<{ data: Blog }>(`blogs/public/shops/${shopName}`).then(res => res.data)
6
-
7
- export const getBlogByIdService = ({ slug }: { slug: string }) =>
8
- axiosInstance.get<{ data: IBlogContent }>(`blogs/public/${slug}`).then(res => res.data)
5
+ axiosInstance.get<{ data: Blog }>(`blogs/public/shops/${shopName}`).then(res => res.data)
@@ -1,4 +1,3 @@
1
- import { IRuleSetID, IMedia as Media } from "lib/models/product";
2
1
  import { ProductQuery } from "lib/stores/productQueryStore/productQueryStore";
3
2
 
4
3
  export interface IGetProductsRequest extends ProductQuery {
@@ -8,296 +7,20 @@ export interface IGetProductsRequest extends ProductQuery {
8
7
  }
9
8
 
10
9
  export interface IHomePageProduct {
11
- _id: string;
10
+ id: string;
12
11
  title: string;
13
12
  slug: string;
14
- skuIDs: { options: IOption[] }[];
15
- media: Media[];
16
- lowestSkuPrice: number;
17
- gatedRuleset: boolean;
13
+ type: string;
14
+ status: string;
15
+ images: {
16
+ original: string;
17
+ thumbnail: string;
18
+ alt: string;
19
+ }[];
20
+ isPurchasable: boolean;
21
+ lowestPrice: number;
22
+ collectionName: string;
18
23
  discountRuleset: boolean;
19
- }
20
-
21
- export interface IgetProductPublicService {
22
- shopname: string;
23
- productID: string;
24
- }
25
-
26
- export interface IGetProductBySlugService {
27
- shopname: string;
28
- slug: string;
29
- }
30
-
31
- export interface IGetProductByLinkId {
32
- linkId: string;
33
- }
34
-
35
- // Interface for media objects in the product's media array
36
- interface IMedia {
37
- isMain: boolean; // Indicates whether this media is the main image
38
- thumbnail: string; // URL of the thumbnail image
39
- url: string; // URL of the main image
40
- _id: string; // Unique identifier for the media object
41
- }
42
-
43
- // Interface for the product collection object
44
- interface IProductCollection {
45
- title: string; // Title of the product collection
46
- ruleSetID?: IRuleSetID
47
- }
48
-
49
- // Interface for the optional ruleset object (not required)
50
- interface IRuleSet {
51
- gated?: boolean; // Optional gated flag
52
- redeemedNFTs?: any; // Optional redeemed NFTs field
53
- rules?: any; // Optional rules field
54
- }
55
-
56
- // Interface for option objects inside each SKU
57
- export interface IOption {
58
- variantName: string; // Name of the variant (e.g., color, size)
59
- value: string; // Value of the variant (e.g., red, large)
60
- caption: string; // Caption for the option (additional description)
61
- }
62
-
63
- // Interface for SKU objects in the skuIDs array
64
- export interface ISku {
65
- _id: string; // Unique identifier for the SKU
66
- price: number; // Price of the SKU
67
- quantity: number; // Quantity available for the SKU
68
- image?: string; // Optional image URL for the SKU
69
- weight: number; // Weight of the SKU
70
-
71
- dimensions: { // Dimensions of the SKU
72
- height: number;
73
- length: number;
74
- width: number;
75
- };
76
-
77
- options?: IOption[]; // Optional options array (for NON-DIGITAL products)
78
- }
79
-
80
- // Main interface for the product object
81
- export interface IProduct {
82
- // Ensured this is exported
83
- description: string; // Mandatory description of the product
84
- media: IMedia[]; // Mandatory media array containing images and videos
85
- productCollectionID: IProductCollection; // Object containing the product collection details
86
- ruleSet?: IRuleSet; // Optional ruleSet object (could be undefined)
87
- slug: string | null; // Mandatory slug (URL-friendly identifier for the product)
88
- title: string; // Mandatory title of the product
89
- _id: string | null; // Mandatory unique identifier for the product
90
- ownerID: string | null; // Mandatory unique identifier for the owner of the product
91
- product_type: "NORMAL" | "PRINT_ON_DEMAND" | "DIGITAL"; // Type of the product (one of three types)
92
- skuIDs: ISku[]; // Mandatory SKU array, must contain at least one SKU
93
- launchDate?: string;
94
- purchaseAvailable: boolean;
95
- pod_blank_product_id: string;
96
- // Optional nftData object containing blockchain-related information
97
- nftData?: INftData;
98
- m2m_positions: IM2MPosition[];
99
- m2m_services: IM2MService[];
100
- shippingType: string;
101
- }
102
- export interface IM2MPosition {
103
- placement: string
104
- variantIDs: number[]
105
- url: string
106
- }
107
- export interface IM2MService {
108
- _id: string;
109
- name: string;
110
- chain: string;
111
- }
112
-
113
- export interface INftData {
114
- deployHash: string;
115
- transactionUrl: string;
116
- networkName: string;
117
- }
118
- export interface IShippingAvailbilityData {
119
- statusCode: number;
120
- message: string | null;
121
- data: string[];
122
- }
123
- // Function to convert raw product data into the IProduct model
124
- export const convertProductDataToModel = (data: any): IProduct => {
125
- try {
126
- // Default SKU in case the SKU data is missing or incomplete
127
- const defaultSku: ISku = {
128
- price: 0,
129
- quantity: 0,
130
- _id: "unknown_sku_id",
131
- weight: 0,
132
- dimensions: {
133
- height: 0,
134
- length: 0,
135
- width: 0,
136
- },
137
- };
138
-
139
-
140
- // Default option for SKUs in NON-DIGITAL products
141
- const defaultOption: IOption = {
142
- variantName: "default_variant",
143
- value: "default_value",
144
- caption: " ",
145
- };
146
-
147
- // Default media object in case media array is missing or incomplete
148
- const defaultMedia: IMedia = {
149
- isMain: false,
150
- thumbnail: "default_thumbnail.jpg",
151
- url: "default_url.jpg",
152
- _id: "default_media_id",
153
- };
154
-
155
- // Construct the product object, falling back to default values when necessary
156
- const product: IProduct = {
157
- description: data?.description || "No description available",
158
- media:
159
- Array.isArray(data?.media) && data?.media.length > 0
160
- ? data.media.map((mediaItem: any) => ({
161
- isMain:
162
- mediaItem?.isMain === "true" || mediaItem?.isMain === true,
163
- thumbnail: mediaItem?.thumbnail || "",
164
- url: mediaItem?.url || "",
165
- _id: mediaItem?._id || "",
166
- }))
167
- : [defaultMedia],
168
-
169
- productCollectionID: {
170
- title: data?.productCollectionID?.title || "",
171
- ruleSetID: {
172
- collectionID: data?.productCollectionID?.ruleSetID?.collectionID || "",
173
- createdAt: data?.productCollectionID?.ruleSetID?.createdAt || "",
174
- type: data?.productCollectionID?.ruleSetID?.type || "",
175
- ownerID: data?.productCollectionID?.ruleSetID?.ownerID || "",
176
- _id: data?.productCollectionID?.ruleSetID?._id || "",
177
- blockchainType: data?.productCollectionID?.ruleSetID?.blockchainType || "",
178
- description: data?.productCollectionID?.ruleSetID?.description || "",
179
- discountPercentage: data?.productCollectionID?.ruleSetID?.discountPercentage || "",
180
- minimumNftRequired: data?.productCollectionID?.ruleSetID?.minimumNftRequired || "",
181
- network: data?.productCollectionID?.ruleSetID?.network || "",
182
- nftContractAddresses: data?.productCollectionID?.ruleSetID?.nftContractAddresses || "",
183
- nftPurchaseLink: data?.productCollectionID?.ruleSetID?.nftPurchaseLink || "",
184
- }
185
- },
186
- purchaseAvailable: data.purchaseAvailable,
187
- slug: data?.slug || null,
188
- title: data?.title || "",
189
- _id: data?._id || null,
190
- ownerID: data?.ownerID || null,
191
- product_type: data?.product_type || "NORMAL",
192
- launchDate: data?.launchDate,
193
- pod_blank_product_id: data.pod_blank_product_id,
194
- shippingType: data.shippingType,
195
- skuIDs:
196
- Array.isArray(data?.skuIDs) && data?.skuIDs.length > 0
197
- ? data.skuIDs.map((sku: any) => ({
198
- price: typeof sku?.price === "number" ? sku.price : 0,
199
- quantity: typeof sku?.quantity === "number" ? sku.quantity : 0,
200
- _id: sku?._id || "unknown_sku_id",
201
- options:
202
- data?.product_type !== "DIGITAL" &&
203
- Array.isArray(sku?.options) &&
204
- sku.options.length > 0
205
- ? sku.options.map((option: any) => ({
206
- variantName: option?.variantName || "default_variant",
207
- value: option?.value || "default_value",
208
- caption: option?.caption || " ",
209
- }))
210
- : undefined,
211
- image: sku.image,
212
- weight: sku.weight,
213
- dimensions: {
214
- height: sku.dimensions.height,
215
- length: sku.dimensions.length,
216
- width: sku.dimensions.width,
217
- },
218
- }))
219
- : [defaultSku],
220
-
221
- // Adding nftData
222
- nftData: data?.nftData
223
- ? {
224
- deployHash: data.nftData.deployHash,
225
- transactionUrl: data.nftData.transactionUrl,
226
- networkName: data.nftData.networkName,
227
- }
228
- : undefined,
229
-
230
-
231
- m2m_positions:
232
- Array.isArray(data?.m2m_positions) && data?.m2m_positions.length > 0
233
- ? data.m2m_positions.map((position: any) => ({
234
- placement: position.placement || "",
235
- variantIDs: position.variant_ids || "",
236
- url: position.url || ""
237
- }))
238
- : [],
239
-
240
- m2m_services:
241
- Array.isArray(data?.m2m_services) && data?.m2m_services.length > 0
242
- ? data.m2m_services.map((service: any) => ({
243
- _id: service?._id || "",
244
- name: service?.name || "Unnamed Service",
245
- chain: service?.chain || "Unknown Chain",
246
- }))
247
- : [],
248
- };
249
-
250
- return product;
251
- } catch (error) {
252
- console.error("Error converting product data:", error);
253
-
254
- // If an error occurs, return a product object with default values
255
- return {
256
- description: "No description available",
257
- purchaseAvailable: data?.purchaseAvailable,
258
- media: [
259
- {
260
- isMain: false,
261
- thumbnail: "default_thumbnail.jpg",
262
- url: "default_url.jpg",
263
- _id: "default_media_id",
264
- },
265
- ],
266
- productCollectionID: { title: "Default Collection" },
267
- slug: null,
268
- title: "",
269
- _id: null,
270
- ownerID: null,
271
- product_type: "NORMAL",
272
- pod_blank_product_id: "",
273
- skuIDs: [
274
- {
275
- price: 0,
276
- quantity: 0,
277
- _id: "unknown_sku_id",
278
- weight: 0,
279
- dimensions: {
280
- height: 0,
281
- length: 0,
282
- width: 0,
283
- },
284
- },
285
- ],
286
- nftData: undefined,
287
- m2m_positions: [],
288
- m2m_services: [],
289
- shippingType: ""
290
- };
291
- }
292
- };
293
-
294
- export interface ISemanticSearchParams {
295
- query: string;
296
- limit?: number;
297
- }
298
-
299
- export interface NftImagesData {
300
- nfts: string[];
301
- domains: string[];
302
- }
303
-
24
+ gatedRuleset: boolean;
25
+ nftRecording: any;
26
+ }
@@ -1,14 +1,7 @@
1
1
  import axiosInstance from "apis/axiosConfig";
2
2
  import { createQueryString } from "lib/utils/app/createQueryString";
3
3
  import {
4
- convertProductDataToModel,
5
- IGetProductByLinkId,
6
- IGetProductBySlugService,
7
- IgetProductPublicService,
8
4
  IGetProductsRequest,
9
- IProduct,
10
- ISemanticSearchParams,
11
- IShippingAvailbilityData
12
5
  } from "./interface";
13
6
 
14
7
  export const getProductsService = (params: IGetProductsRequest) => {
@@ -19,30 +12,6 @@ export const getProductsService = (params: IGetProductsRequest) => {
19
12
  }).toString()
20
13
 
21
14
  return axiosInstance
22
- .get(`product/public/shop/${params.shopName}?${queryString}`)
15
+ .get(`/product-v2/public/shop/${params.shopName}?${queryString}`)
23
16
  .then((res) => res.data)
24
- }
25
-
26
- export const getProductPublicService = ({ productID, shopname }: IgetProductPublicService) => {
27
- return axiosInstance.get<{ data: IProduct }>(`product/public/${productID}?shopname=${shopname}`).then((res) => convertProductDataToModel(res.data.data));
28
- };
29
-
30
- export const getProductBySlugService = ({ slug, shopname }: IGetProductBySlugService) => axiosInstance.get(`product/public/${slug}?shopname=${shopname}`);
31
-
32
- export const getProductByLinkId = ({ linkId }: IGetProductByLinkId) => axiosInstance.get(`/product/link/${linkId}`);
33
-
34
- export const getShippingAvailability = async (productId: string): Promise<IShippingAvailbilityData> => {
35
- try {
36
- const response = await axiosInstance.post<IShippingAvailbilityData>("/product/printful-available-shipping", {
37
- product_id: productId,
38
- });
39
- return response.data;
40
- } catch (error) {
41
- console.error("Error fetching shipping availability:", error);
42
- throw new Error("Failed to fetch shipping availability");
43
- }
44
- };
45
-
46
- export const semanticSearchService = ({ query, limit = 10 }: ISemanticSearchParams) => {
47
- return axiosInstance.get(`/product/search/semantic${query && query !== "" ? `?query=${query}` : ""}&limit=${limit}`);
48
- };
17
+ }
@@ -1,7 +1,3 @@
1
- export interface IshopDomainService {
2
- domain: string;
3
- }
4
-
5
1
  export interface IgetShopService {
6
2
  shopName: string;
7
3
  }
@@ -1,13 +1,9 @@
1
1
  import axiosInstance from "apis/axiosConfig"
2
- import { IgetShopService, IshopDomainService, ProductFiltersResponse } from "./interface"
3
-
4
- export const shopDomainService = ({ domain }: IshopDomainService) => {
5
- return axiosInstance.get(`shop/domain/${domain}`)
6
- }
2
+ import { IgetShopService, ProductFiltersResponse } from "./interface"
7
3
 
8
4
  export const getShopService = ({ shopName }: IgetShopService) => {
9
- return axiosInstance.get(`shop/public/${shopName}`)
5
+ return axiosInstance.get(`/shops/v2/public/name/${shopName}`)
10
6
  }
11
7
 
12
8
  export const getAvailableProductFilters = (shopName: string) =>
13
- axiosInstance.get<{ data: ProductFiltersResponse }>(`product/available/filters/${shopName}`).then(res => res.data)
9
+ axiosInstance.get<{ data: ProductFiltersResponse }>(`/product-v2/available/filters/${shopName}`).then(res => res.data)
@@ -12,7 +12,7 @@ interface Props {
12
12
  }
13
13
 
14
14
  export default function GridViewProductCard({ product, isEditing }: Props) {
15
- const { title, lowestSkuPrice, _id, slug } = product
15
+ const { title, lowestPrice, id, slug } = product
16
16
  const [isHovered, setIsHovered] = useState(false)
17
17
 
18
18
  return (
@@ -23,7 +23,7 @@ export default function GridViewProductCard({ product, isEditing }: Props) {
23
23
  >
24
24
  <ProductImageSlider product={product} isHovered={isHovered} isEditing={isEditing} />
25
25
  <ProductTitle title={title} slug={slug} className="mt-3" />
26
- <ProductPrice price={lowestSkuPrice} slug={slug} className="mt-2" />
26
+ <ProductPrice price={lowestPrice} slug={slug} className="mt-2" />
27
27
  </div>
28
28
  )
29
29
  }
@@ -7,18 +7,18 @@ import useThemeInfo from "hooks/useThemeInfo"
7
7
  import { useCustomNavigate } from "hooks/useCustomNavigate"
8
8
 
9
9
  export default function ListViewProductCard({ product }: { product: IHomePageProduct }) {
10
- const { media, title, lowestSkuPrice, discountRuleset, gatedRuleset, slug, _id } = product
10
+ const { images, title, lowestPrice, discountRuleset, gatedRuleset, slug, id } = product
11
11
  const { isDarkTheme } = useThemeInfo()
12
12
  const iconClass = isDarkTheme ? "[&_path]:stroke-white" : ""
13
13
  const { navigate } = useCustomNavigate()
14
- const imageURL = (media.find(m => m.isMain === "true") ?? media[0]).thumbnail
14
+ const imageURL = (images.find(img => img.original) ?? images[0])?.thumbnail || images[0]?.original
15
15
 
16
16
  return (
17
- <div className="cursor-pointer" onClick={() => navigate(`product/${slug ?? _id}`)}>
17
+ <div className="cursor-pointer" onClick={() => navigate(`product/${slug ?? id}`)}>
18
18
  <ProductCardBase
19
19
  image={<img src={imageURL} alt={title} className="w-[70px] h-[70px] object-cover rounded-lg shrink-0" />}
20
20
  title={<ProductTitle title={title} slug={slug} />}
21
- price={<ProductPrice price={lowestSkuPrice} slug={slug} />}
21
+ price={<ProductPrice price={lowestPrice} slug={slug} />}
22
22
  icons={
23
23
  <>
24
24
  {discountRuleset && <PLPIcons.Discount className={iconClass} />}
@@ -39,8 +39,8 @@ function ProductGrid({ limit, isEditing }: { limit?: number; isEditing?: boolean
39
39
  <ProductGridLayout>
40
40
  {products.map(product => (
41
41
  isMobile && viewMode === 'list'
42
- ? <ListViewProductCard key={product._id} product={product} />
43
- : <GridViewProductCard key={product._id} product={product} isEditing={isEditing} />
42
+ ? <ListViewProductCard key={product.id} product={product} />
43
+ : <GridViewProductCard key={product.id} product={product} isEditing={isEditing} />
44
44
  ))}
45
45
 
46
46
  {isFetchingNextPage && renderSkeletons()}
@@ -15,10 +15,10 @@ interface Props {
15
15
  }
16
16
 
17
17
  export default function ProductImageSlider({ product, isHovered, isEditing }: Props) {
18
- const { media, title, slug } = product
18
+ const { images, title, slug } = product
19
19
  const { navigate } = useCustomNavigate()
20
20
  const [currentIndex, setCurrentIndex] = useState(0)
21
- const sliderImages = media.sort((_, b) => (b.isMain === "true" ? 1 : -1)).slice(0, 3)
21
+ const sliderImages = images.slice(0, 3)
22
22
 
23
23
  const [sliderRef, instanceRef] = useKeenSlider<HTMLDivElement>({
24
24
  loop: true,
@@ -53,7 +53,7 @@ export default function ProductImageSlider({ product, isHovered, isEditing }: Pr
53
53
  <div className="relative overflow-hidden rounded-lg aspect-square cursor-pointer">
54
54
  <img
55
55
  src={sliderImages[0]?.thumbnail}
56
- alt={title}
56
+ alt={sliderImages[0]?.alt || title}
57
57
  onClick={handleImageClick}
58
58
  className="w-full h-full object-cover transition-transform duration-500 ease-in-out group-hover:scale-[1.04]"
59
59
  />
@@ -69,7 +69,7 @@ export default function ProductImageSlider({ product, isHovered, isEditing }: Pr
69
69
  <div key={index} className="keen-slider__slide w-full h-full aspect-square flex items-center justify-center">
70
70
  <img
71
71
  src={image.thumbnail}
72
- alt={`${title}-${index}`}
72
+ alt={image.alt || `${title}-${index}`}
73
73
  className="w-full h-full object-cover transition-transform duration-500 ease-in-out group-hover:scale-[1.04]"
74
74
  />
75
75
  </div>