@hectasquare/medusa-plugin-category-tree 1.0.10 → 1.0.12

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.
@@ -126,12 +126,15 @@ const CategoryProductsManager = ({ categoryId, categoryName, initialMetadata, on
126
126
  }
127
127
  };
128
128
  // Sibling product ranking handlers (Move Up / Move Down)
129
- const handleMoveProduct = async (index, direction) => {
130
- const targetIndex = direction === "up" ? index - 1 : index + 1;
129
+ const handleMoveProduct = async (productId, direction) => {
130
+ const currentIndex = products.findIndex((p) => p.id === productId);
131
+ if (currentIndex === -1)
132
+ return;
133
+ const targetIndex = direction === "up" ? currentIndex - 1 : currentIndex + 1;
131
134
  if (targetIndex < 0 || targetIndex >= products.length)
132
135
  return;
133
136
  const reordered = [...products];
134
- const [moved] = reordered.splice(index, 1);
137
+ const [moved] = reordered.splice(currentIndex, 1);
135
138
  reordered.splice(targetIndex, 0, moved);
136
139
  setProducts(reordered);
137
140
  const newOrder = reordered.map((p) => p.id);
@@ -155,7 +158,7 @@ const CategoryProductsManager = ({ categoryId, categoryName, initialMetadata, on
155
158
  const currentOrder = products.map((p) => p.id);
156
159
  await persistProductConfig(currentOrder, next);
157
160
  };
158
- // Remove products from category
161
+ // Remove products from category using official Medusa v2 JS SDK method
159
162
  const handleRemoveProducts = async (idsToRemove) => {
160
163
  if (idsToRemove.length === 0)
161
164
  return;
@@ -166,9 +169,8 @@ const CategoryProductsManager = ({ categoryId, categoryName, initialMetadata, on
166
169
  return;
167
170
  setIsRemoving(true);
168
171
  try {
169
- await sdk_1.sdk.client.fetch(`/admin/product-categories/${categoryId}/products`, {
170
- method: "POST",
171
- body: { remove: idsToRemove },
172
+ await sdk_1.sdk.admin.productCategory.updateProducts(categoryId, {
173
+ remove: idsToRemove,
172
174
  });
173
175
  ui_1.toast.success(`Removed ${idsToRemove.length} product(s) from category`);
174
176
  setSelectedIds(new Set());
@@ -210,15 +212,15 @@ const CategoryProductsManager = ({ categoryId, categoryName, initialMetadata, on
210
212
  searchCatalog(searchQuery, catalogPage);
211
213
  }
212
214
  }, [focusModalOpen, searchQuery, catalogPage, searchCatalog]);
215
+ // Save added products using official Medusa v2 JS SDK method
213
216
  const handleSaveAddedProducts = async () => {
214
217
  const idsToAdd = Array.from(catalogSelectedIds);
215
218
  if (idsToAdd.length === 0)
216
219
  return;
217
220
  setIsAdding(true);
218
221
  try {
219
- await sdk_1.sdk.client.fetch(`/admin/product-categories/${categoryId}/products`, {
220
- method: "POST",
221
- body: { add: idsToAdd },
222
+ await sdk_1.sdk.admin.productCategory.updateProducts(categoryId, {
223
+ add: idsToAdd,
222
224
  });
223
225
  ui_1.toast.success(`Added ${idsToAdd.length} product(s) to ${categoryName}`);
224
226
  setFocusModalOpen(false);
@@ -243,18 +245,39 @@ const CategoryProductsManager = ({ categoryId, categoryName, initialMetadata, on
243
245
  }
244
246
  return products;
245
247
  }, [products, activeView, topSellerIds]);
246
- return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between flex-wrap gap-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1.5 p-1 rounded-lg bg-ui-bg-subtle border border-ui-border-base", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => setActiveView("all"), className: `px-2.5 py-1 text-xs font-medium rounded-md transition-colors ${activeView === "all"
248
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between flex-wrap gap-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1.5 p-1 rounded-lg bg-ui-bg-subtle border border-ui-border-base", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: (e) => {
249
+ e.preventDefault();
250
+ e.stopPropagation();
251
+ setActiveView("all");
252
+ }, className: `px-2.5 py-1 text-xs font-medium rounded-md transition-colors ${activeView === "all"
247
253
  ? "bg-ui-bg-base text-ui-fg-base shadow-2xs font-semibold"
248
- : "text-ui-fg-muted hover:text-ui-fg-base"}`, children: ["All Products (", products.length, ")"] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => setActiveView("top_sellers"), className: `flex items-center gap-1 px-2.5 py-1 text-xs font-medium rounded-md transition-colors ${activeView === "top_sellers"
254
+ : "text-ui-fg-muted hover:text-ui-fg-base"}`, children: ["All Products (", products.length, ")"] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: (e) => {
255
+ e.preventDefault();
256
+ e.stopPropagation();
257
+ setActiveView("top_sellers");
258
+ }, className: `flex items-center gap-1 px-2.5 py-1 text-xs font-medium rounded-md transition-colors ${activeView === "top_sellers"
249
259
  ? "bg-amber-500/10 text-amber-700 dark:text-amber-400 font-semibold"
250
- : "text-ui-fg-muted hover:text-amber-600"}`, children: [(0, jsx_runtime_1.jsx)(icons_1.Sparkles, { className: "w-3.5 h-3.5 text-amber-500" }), (0, jsx_runtime_1.jsxs)("span", { children: ["Top Commercial Sellers (", topSellerIds.size, ")"] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [selectedIds.size > 0 && ((0, jsx_runtime_1.jsxs)(ui_1.Button, { size: "small", variant: "danger", disabled: isRemoving, onClick: () => handleRemoveProducts(Array.from(selectedIds)), className: "flex items-center gap-1 text-xs", children: [(0, jsx_runtime_1.jsx)(icons_1.Trash, { className: "w-3.5 h-3.5" }), (0, jsx_runtime_1.jsxs)("span", { children: ["Remove Selected (", selectedIds.size, ")"] })] })), (0, jsx_runtime_1.jsxs)(ui_1.Button, { size: "small", variant: "secondary", onClick: () => {
260
+ : "text-ui-fg-muted hover:text-amber-600"}`, children: [(0, jsx_runtime_1.jsx)(icons_1.Sparkles, { className: "w-3.5 h-3.5 text-amber-500" }), (0, jsx_runtime_1.jsxs)("span", { children: ["Top Commercial Sellers (", topSellerIds.size, ")"] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [selectedIds.size > 0 && ((0, jsx_runtime_1.jsxs)(ui_1.Button, { type: "button", size: "small", variant: "danger", disabled: isRemoving, onClick: (e) => {
261
+ e.preventDefault();
262
+ e.stopPropagation();
263
+ handleRemoveProducts(Array.from(selectedIds));
264
+ }, className: "flex items-center gap-1 text-xs", children: [(0, jsx_runtime_1.jsx)(icons_1.Trash, { className: "w-3.5 h-3.5" }), (0, jsx_runtime_1.jsxs)("span", { children: ["Remove Selected (", selectedIds.size, ")"] })] })), (0, jsx_runtime_1.jsxs)(ui_1.Button, { type: "button", size: "small", variant: "secondary", onClick: (e) => {
265
+ e.preventDefault();
266
+ e.stopPropagation();
251
267
  setCatalogSelectedIds(new Set());
252
268
  setSearchQuery("");
253
269
  setCatalogPage(0);
254
270
  setFocusModalOpen(true);
255
271
  }, className: "flex items-center gap-1 text-xs", children: [(0, jsx_runtime_1.jsx)(icons_1.Plus, { className: "w-3.5 h-3.5" }), (0, jsx_runtime_1.jsx)("span", { children: "Add Products" })] })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "border border-ui-border-base rounded-xl overflow-hidden bg-ui-bg-base shadow-2xs", children: isLoading ? ((0, jsx_runtime_1.jsx)("div", { className: "p-8 text-center text-xs text-ui-fg-muted", children: "Loading products\u2026" })) : displayedProducts.length === 0 ? ((0, jsx_runtime_1.jsxs)("div", { className: "p-8 text-center flex flex-col items-center justify-center gap-2", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-xs text-ui-fg-muted", children: activeView === "top_sellers"
256
272
  ? "No products marked as Top Commercial Sellers yet. Star a product below to highlight it."
257
- : "No products assigned to this category." }), activeView === "all" && ((0, jsx_runtime_1.jsxs)(ui_1.Button, { size: "small", variant: "secondary", onClick: () => setFocusModalOpen(true), className: "flex items-center gap-1 text-xs", children: [(0, jsx_runtime_1.jsx)(icons_1.Plus, { className: "w-3.5 h-3.5" }), (0, jsx_runtime_1.jsx)("span", { children: "Add Products" })] }))] })) : ((0, jsx_runtime_1.jsxs)("table", { className: "w-full text-left text-xs border-collapse", children: [(0, jsx_runtime_1.jsx)("thead", { children: (0, jsx_runtime_1.jsxs)("tr", { className: "border-b border-ui-border-base bg-ui-bg-subtle/60 text-ui-fg-muted font-medium", children: [(0, jsx_runtime_1.jsx)("th", { className: "py-2.5 px-3 w-8", children: (0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: displayedProducts.length > 0 && selectedIds.size === displayedProducts.length, onChange: () => {
273
+ : "No products assigned to this category." }), activeView === "all" && ((0, jsx_runtime_1.jsxs)(ui_1.Button, { type: "button", size: "small", variant: "secondary", onClick: (e) => {
274
+ e.preventDefault();
275
+ e.stopPropagation();
276
+ setCatalogSelectedIds(new Set());
277
+ setSearchQuery("");
278
+ setCatalogPage(0);
279
+ setFocusModalOpen(true);
280
+ }, className: "flex items-center gap-1 text-xs", children: [(0, jsx_runtime_1.jsx)(icons_1.Plus, { className: "w-3.5 h-3.5" }), (0, jsx_runtime_1.jsx)("span", { children: "Add Products" })] }))] })) : ((0, jsx_runtime_1.jsxs)("table", { className: "w-full text-left text-xs border-collapse", children: [(0, jsx_runtime_1.jsx)("thead", { children: (0, jsx_runtime_1.jsxs)("tr", { className: "border-b border-ui-border-base bg-ui-bg-subtle/60 text-ui-fg-muted font-medium", children: [(0, jsx_runtime_1.jsx)("th", { className: "py-2.5 px-3 w-8", children: (0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: displayedProducts.length > 0 && selectedIds.size === displayedProducts.length, onChange: () => {
258
281
  if (selectedIds.size === displayedProducts.length)
259
282
  setSelectedIds(new Set());
260
283
  else
@@ -274,27 +297,31 @@ const CategoryProductsManager = ({ categoryId, categoryName, initialMetadata, on
274
297
  }, className: "rounded border-ui-border-base cursor-pointer" }) }), (0, jsx_runtime_1.jsx)("td", { className: "py-2.5 px-3", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1 font-mono", children: [(0, jsx_runtime_1.jsxs)("span", { className: "text-xs font-bold text-ui-fg-subtle px-1.5 py-0.5 rounded bg-ui-bg-subtle border border-ui-border-base", children: ["#", index + 1] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", title: "Move Up", disabled: index === 0, onClick: (e) => {
275
298
  e.preventDefault();
276
299
  e.stopPropagation();
277
- handleMoveProduct(index, "up");
300
+ handleMoveProduct(p.id, "up");
278
301
  }, className: "text-[9px] text-ui-fg-muted hover:text-ui-fg-base disabled:opacity-20 px-0.5 leading-none cursor-pointer", children: "\u25B2" }), (0, jsx_runtime_1.jsx)("button", { type: "button", title: "Move Down", disabled: index === displayedProducts.length - 1, onClick: (e) => {
279
302
  e.preventDefault();
280
303
  e.stopPropagation();
281
- handleMoveProduct(index, "down");
282
- }, className: "text-[9px] text-ui-fg-muted hover:text-ui-fg-base disabled:opacity-20 px-0.5 leading-none cursor-pointer", children: "\u25BC" })] })] }) }), (0, jsx_runtime_1.jsx)("td", { className: "py-2.5 px-3", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2.5 min-w-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-9 h-9 rounded-md border border-ui-border-base overflow-hidden bg-ui-bg-subtle flex-shrink-0 flex items-center justify-center", children: p.thumbnail ? ((0, jsx_runtime_1.jsx)("img", { src: p.thumbnail, alt: p.title, className: "w-full h-full object-cover" })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-[9px] text-ui-fg-muted", children: "IMG" })) }), (0, jsx_runtime_1.jsx)("div", { className: "flex flex-col min-w-0", children: (0, jsx_runtime_1.jsx)("span", { className: "font-semibold text-ui-fg-base truncate leading-snug", title: p.title, children: p.title }) })] }) }), (0, jsx_runtime_1.jsx)("td", { className: "py-2.5 px-3", children: (0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: (e) => {
304
+ handleMoveProduct(p.id, "down");
305
+ }, className: "text-[9px] text-ui-fg-muted hover:text-ui-fg-base disabled:opacity-20 px-0.5 leading-none cursor-pointer", children: "\u25BC" })] })] }) }), (0, jsx_runtime_1.jsx)("td", { className: "py-2.5 px-3", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2.5 min-w-0", children: [(0, jsx_runtime_1.jsx)("a", { href: `/app/products/${p.id}`, target: "_blank", rel: "noopener noreferrer", className: "w-9 h-9 rounded-md border border-ui-border-base overflow-hidden bg-ui-bg-subtle flex-shrink-0 flex items-center justify-center hover:opacity-80 transition-opacity", title: `Open ${p.title} in new tab`, children: p.thumbnail ? ((0, jsx_runtime_1.jsx)("img", { src: p.thumbnail, alt: p.title, className: "w-full h-full object-cover" })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-[9px] text-ui-fg-muted", children: "IMG" })) }), (0, jsx_runtime_1.jsx)("div", { className: "flex flex-col min-w-0", children: (0, jsx_runtime_1.jsxs)("a", { href: `/app/products/${p.id}`, target: "_blank", rel: "noopener noreferrer", className: "font-semibold text-ui-fg-base hover:text-ui-fg-interactive truncate leading-snug hover:underline flex items-center gap-1 group/pname", title: `Open ${p.title} in new tab`, children: [(0, jsx_runtime_1.jsx)("span", { className: "truncate", children: p.title }), (0, jsx_runtime_1.jsx)(icons_1.ArrowUpRightMicro, { className: "w-3.5 h-3.5 text-ui-fg-muted group-hover/pname:text-ui-fg-interactive transition-colors shrink-0" })] }) })] }) }), (0, jsx_runtime_1.jsx)("td", { className: "py-2.5 px-3", children: (0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: (e) => {
283
306
  e.preventDefault();
284
307
  e.stopPropagation();
285
308
  handleToggleTopSeller(p.id, p.title);
286
- }, className: `inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[11px] font-semibold border transition-all ${isTopSeller
309
+ }, className: `inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[11px] font-semibold border transition-all cursor-pointer ${isTopSeller
287
310
  ? "bg-amber-500/15 text-amber-700 dark:text-amber-400 border-amber-300 dark:border-amber-700 shadow-2xs"
288
311
  : "bg-ui-bg-subtle text-ui-fg-muted border-ui-border-base hover:text-amber-600 hover:border-amber-300"}`, title: isTopSeller
289
312
  ? "Click to remove from Top Commercial Sellers"
290
- : "Click to mark as Top Commercial Seller (Reflected in Storefront 2)", children: [(0, jsx_runtime_1.jsx)("span", { children: isTopSeller ? "★" : "☆" }), (0, jsx_runtime_1.jsx)("span", { children: isTopSeller ? "Top Seller" : "Normal" })] }) }), (0, jsx_runtime_1.jsx)("td", { className: "py-2.5 px-3 text-ui-fg-muted", children: p.collection?.title || "-" }), (0, jsx_runtime_1.jsxs)("td", { className: "py-2.5 px-3 text-ui-fg-subtle", children: [p.variants?.length || 0, " variant(s)"] }), (0, jsx_runtime_1.jsx)("td", { className: "py-2.5 px-3", children: (0, jsx_runtime_1.jsx)("span", { className: `inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium ${p.status === "published"
313
+ : "Click to mark as Top Commercial Seller (Reflected on Storefront 2)", children: [(0, jsx_runtime_1.jsx)("span", { children: isTopSeller ? "★" : "☆" }), (0, jsx_runtime_1.jsx)("span", { children: isTopSeller ? "Top Seller" : "Normal" })] }) }), (0, jsx_runtime_1.jsx)("td", { className: "py-2.5 px-3 text-ui-fg-muted", children: p.collection?.title || "-" }), (0, jsx_runtime_1.jsxs)("td", { className: "py-2.5 px-3 text-ui-fg-subtle", children: [p.variants?.length || 0, " variant(s)"] }), (0, jsx_runtime_1.jsx)("td", { className: "py-2.5 px-3", children: (0, jsx_runtime_1.jsx)("span", { className: `inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium ${p.status === "published"
291
314
  ? "bg-emerald-50 text-emerald-700 border border-emerald-200 dark:bg-emerald-950/50 dark:text-emerald-300"
292
315
  : "bg-neutral-100 text-neutral-600 dark:bg-neutral-800 dark:text-neutral-400"}`, children: p.status }) }), (0, jsx_runtime_1.jsx)("td", { className: "py-2.5 px-3 text-right", children: (0, jsx_runtime_1.jsx)("button", { type: "button", title: "Remove from category", onClick: (e) => {
293
316
  e.preventDefault();
294
317
  e.stopPropagation();
295
318
  handleRemoveProducts([p.id]);
296
- }, className: "p-1 text-ui-fg-muted hover:text-rose-600 hover:bg-rose-50 dark:hover:bg-rose-950/50 rounded transition-colors", children: (0, jsx_runtime_1.jsx)(icons_1.Trash, { className: "w-3.5 h-3.5" }) }) })] }, p.id));
297
- }) })] })) }), focusModalOpen && ((0, jsx_runtime_1.jsxs)("div", { className: "fixed inset-0 z-50 flex flex-col bg-white dark:bg-neutral-950 animate-in fade-in-50", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between px-6 py-3 border-b border-ui-border-base bg-ui-bg-base flex-shrink-0", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setFocusModalOpen(false), className: "p-1.5 rounded-lg text-ui-fg-muted hover:text-ui-fg-base hover:bg-ui-bg-subtle transition-colors", title: "Close (ESC)", children: (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-bold", children: "\u2715" }) }), (0, jsx_runtime_1.jsx)("span", { className: "text-[11px] font-mono font-medium text-ui-fg-muted px-1.5 py-0.5 rounded bg-ui-bg-subtle border border-ui-border-base", children: "ESC" }), (0, jsx_runtime_1.jsxs)("h2", { className: "text-sm font-semibold text-ui-fg-base", children: ["Add Products to Category: ", categoryName] })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-3", children: (0, jsx_runtime_1.jsxs)("div", { className: "relative w-64", children: [(0, jsx_runtime_1.jsx)("input", { type: "text", placeholder: "Search products\u2026", value: searchQuery, onChange: (e) => {
319
+ }, className: "p-1 text-ui-fg-muted hover:text-rose-600 hover:bg-rose-50 dark:hover:bg-rose-950/50 rounded transition-colors cursor-pointer", children: (0, jsx_runtime_1.jsx)(icons_1.Trash, { className: "w-3.5 h-3.5" }) }) })] }, p.id));
320
+ }) })] })) }), focusModalOpen && ((0, jsx_runtime_1.jsxs)("div", { className: "fixed inset-0 z-50 flex flex-col bg-white dark:bg-neutral-950 animate-in fade-in-50", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between px-6 py-3 border-b border-ui-border-base bg-ui-bg-base flex-shrink-0", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: (e) => {
321
+ e.preventDefault();
322
+ e.stopPropagation();
323
+ setFocusModalOpen(false);
324
+ }, className: "p-1.5 rounded-lg text-ui-fg-muted hover:text-ui-fg-base hover:bg-ui-bg-subtle transition-colors cursor-pointer", title: "Close (ESC)", children: (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-bold", children: "\u2715" }) }), (0, jsx_runtime_1.jsx)("span", { className: "text-[11px] font-mono font-medium text-ui-fg-muted px-1.5 py-0.5 rounded bg-ui-bg-subtle border border-ui-border-base", children: "ESC" }), (0, jsx_runtime_1.jsxs)("h2", { className: "text-sm font-semibold text-ui-fg-base", children: ["Add Products to Category: ", categoryName] })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-3", children: (0, jsx_runtime_1.jsxs)("div", { className: "relative w-64", children: [(0, jsx_runtime_1.jsx)("input", { type: "text", placeholder: "Search products\u2026", value: searchQuery, onChange: (e) => {
298
325
  setSearchQuery(e.target.value);
299
326
  setCatalogPage(0);
300
327
  }, className: "w-full text-xs pl-8 pr-3 py-1.5 rounded-lg bg-ui-bg-subtle border border-ui-border-base text-ui-fg-base focus:bg-ui-bg-base focus:border-ui-border-interactive focus:outline-none placeholder:text-ui-fg-muted", autoFocus: true }), (0, jsx_runtime_1.jsx)(icons_1.MagnifyingGlass, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-ui-fg-muted pointer-events-none" })] }) })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 overflow-y-auto px-6 py-4", children: (0, jsx_runtime_1.jsx)("div", { className: "border border-ui-border-base rounded-xl overflow-hidden bg-ui-bg-base shadow-sm", children: (0, jsx_runtime_1.jsxs)("table", { className: "w-full text-left text-xs border-collapse", children: [(0, jsx_runtime_1.jsx)("thead", { children: (0, jsx_runtime_1.jsxs)("tr", { className: "border-b border-ui-border-base bg-ui-bg-subtle/80 text-ui-fg-muted font-medium", children: [(0, jsx_runtime_1.jsx)("th", { className: "py-2.5 px-3 w-8", children: (0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: catalogProducts.length > 0 &&
@@ -338,6 +365,22 @@ const CategoryProductsManager = ({ categoryId, categoryName, initialMetadata, on
338
365
  }, className: "rounded border-ui-border-base cursor-pointer" }) }), (0, jsx_runtime_1.jsx)("td", { className: "py-2.5 px-3", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2.5 min-w-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-8 h-8 rounded border border-ui-border-base overflow-hidden bg-ui-bg-subtle flex-shrink-0 flex items-center justify-center", children: p.thumbnail ? ((0, jsx_runtime_1.jsx)("img", { src: p.thumbnail, alt: p.title, className: "w-full h-full object-cover" })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-[8px] text-ui-fg-muted", children: "IMG" })) }), (0, jsx_runtime_1.jsx)("span", { className: "font-semibold text-ui-fg-base truncate leading-snug", children: p.title }), isAlreadyAssigned && ((0, jsx_runtime_1.jsx)(ui_1.Badge, { size: "small", color: "grey", className: "ml-1 text-[9px]", children: "Already in Category" }))] }) }), (0, jsx_runtime_1.jsx)("td", { className: "py-2.5 px-3 text-ui-fg-muted", children: p.collection?.title || "-" }), (0, jsx_runtime_1.jsx)("td", { className: "py-2.5 px-3", children: (0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-1 flex-wrap", children: (p.sales_channels || []).map((sc) => ((0, jsx_runtime_1.jsx)("span", { className: "px-1.5 py-0.5 rounded text-[10px] bg-ui-bg-subtle border border-ui-border-base text-ui-fg-subtle", children: sc.name }, sc.id))) }) }), (0, jsx_runtime_1.jsxs)("td", { className: "py-2.5 px-3 text-ui-fg-subtle", children: [p.variants?.length || 0, " variant(s)"] }), (0, jsx_runtime_1.jsx)("td", { className: "py-2.5 px-3", children: (0, jsx_runtime_1.jsx)("span", { className: `inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium ${p.status === "published"
339
366
  ? "bg-emerald-50 text-emerald-700 border border-emerald-200 dark:bg-emerald-950/50 dark:text-emerald-300"
340
367
  : "bg-neutral-100 text-neutral-600 dark:bg-neutral-800 dark:text-neutral-400"}`, children: p.status }) })] }, p.id));
341
- })) })] }) }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between px-6 py-3 border-t border-ui-border-base bg-ui-bg-base flex-shrink-0", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsxs)("span", { className: "text-xs text-ui-fg-muted", children: ["Showing ", Math.min(catalogProducts.length, PAGE_SIZE), " of ", catalogTotalCount, " results"] }), (0, jsx_runtime_1.jsx)("span", { className: "text-xs text-ui-fg-muted", children: "\u2022" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-xs font-semibold text-ui-fg-base", children: [catalogSelectedIds.size, " product(s) selected"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", disabled: catalogPage === 0, onClick: () => setCatalogPage((p) => Math.max(0, p - 1)), className: "px-2.5 py-1 text-xs rounded border border-ui-border-base bg-ui-bg-subtle hover:bg-ui-bg-base disabled:opacity-40", children: "Prev" }), (0, jsx_runtime_1.jsx)("button", { type: "button", disabled: (catalogPage + 1) * PAGE_SIZE >= catalogTotalCount, onClick: () => setCatalogPage((p) => p + 1), className: "px-2.5 py-1 text-xs rounded border border-ui-border-base bg-ui-bg-subtle hover:bg-ui-bg-base disabled:opacity-40", children: "Next" }), (0, jsx_runtime_1.jsx)("div", { className: "h-4 w-[1px] bg-ui-border-base mx-1" }), (0, jsx_runtime_1.jsx)(ui_1.Button, { size: "small", variant: "secondary", onClick: () => setFocusModalOpen(false), children: "Cancel" }), (0, jsx_runtime_1.jsxs)(ui_1.Button, { size: "small", variant: "primary", disabled: catalogSelectedIds.size === 0 || isAdding, onClick: handleSaveAddedProducts, className: "flex items-center gap-1 text-xs min-w-[70px] justify-center", children: [(0, jsx_runtime_1.jsx)(icons_1.CheckMini, { className: "w-3.5 h-3.5" }), (0, jsx_runtime_1.jsx)("span", { children: isAdding ? "Saving…" : "Save" })] })] })] })] }))] }));
368
+ })) })] }) }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between px-6 py-3 border-t border-ui-border-base bg-ui-bg-base flex-shrink-0", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsxs)("span", { className: "text-xs text-ui-fg-muted", children: ["Showing ", Math.min(catalogProducts.length, PAGE_SIZE), " of ", catalogTotalCount, " results"] }), (0, jsx_runtime_1.jsx)("span", { className: "text-xs text-ui-fg-muted", children: "\u2022" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-xs font-semibold text-ui-fg-base", children: [catalogSelectedIds.size, " product(s) selected"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", disabled: catalogPage === 0, onClick: (e) => {
369
+ e.preventDefault();
370
+ e.stopPropagation();
371
+ setCatalogPage((p) => Math.max(0, p - 1));
372
+ }, className: "px-2.5 py-1 text-xs rounded border border-ui-border-base bg-ui-bg-subtle hover:bg-ui-bg-base disabled:opacity-40 cursor-pointer", children: "Prev" }), (0, jsx_runtime_1.jsx)("button", { type: "button", disabled: (catalogPage + 1) * PAGE_SIZE >= catalogTotalCount, onClick: (e) => {
373
+ e.preventDefault();
374
+ e.stopPropagation();
375
+ setCatalogPage((p) => p + 1);
376
+ }, className: "px-2.5 py-1 text-xs rounded border border-ui-border-base bg-ui-bg-subtle hover:bg-ui-bg-base disabled:opacity-40 cursor-pointer", children: "Next" }), (0, jsx_runtime_1.jsx)("div", { className: "h-4 w-[1px] bg-ui-border-base mx-1" }), (0, jsx_runtime_1.jsx)(ui_1.Button, { type: "button", size: "small", variant: "secondary", onClick: (e) => {
377
+ e.preventDefault();
378
+ e.stopPropagation();
379
+ setFocusModalOpen(false);
380
+ }, children: "Cancel" }), (0, jsx_runtime_1.jsxs)(ui_1.Button, { type: "button", size: "small", variant: "primary", disabled: catalogSelectedIds.size === 0 || isAdding, onClick: (e) => {
381
+ e.preventDefault();
382
+ e.stopPropagation();
383
+ handleSaveAddedProducts();
384
+ }, className: "flex items-center gap-1 text-xs min-w-[70px] justify-center", children: [(0, jsx_runtime_1.jsx)(icons_1.CheckMini, { className: "w-3.5 h-3.5" }), (0, jsx_runtime_1.jsx)("span", { children: isAdding ? "Saving…" : "Save" })] })] })] })] }))] }));
342
385
  };
343
386
  exports.CategoryProductsManager = CategoryProductsManager;
@@ -12,17 +12,17 @@ function extractYouTubeVideoId(url) {
12
12
  return null;
13
13
  const trimmed = url.trim();
14
14
  const patterns = [
15
- /(?:youtube\.com\/shorts\/)([^?&\s]+)/i,
16
- /(?:youtube\.com\/watch\?.*v=)([^?&\s]+)/i,
17
- /(?:youtu\.be\/)([^?&\s]+)/i,
18
- /(?:youtube\.com\/embed\/)([^?&\s]+)/i,
15
+ /(?:youtube\.com\/shorts\/)([a-zA-Z0-9_-]{11})/i,
16
+ /(?:youtube\.com\/watch\?.*v=)([a-zA-Z0-9_-]{11})/i,
17
+ /(?:youtu\.be\/)([a-zA-Z0-9_-]{11})/i,
18
+ /(?:youtube\.com\/embed\/)([a-zA-Z0-9_-]{11})/i,
19
19
  ];
20
20
  for (const pattern of patterns) {
21
21
  const match = trimmed.match(pattern);
22
22
  if (match && match[1])
23
23
  return match[1];
24
24
  }
25
- if (/^[a-zA-Z0-9_-]{11}$/.test(trimmed))
25
+ if (/^[a-zA-Z0-9_-]{11}$/.test(trimmed) && !/^[A-Za-z]{11}$/.test(trimmed))
26
26
  return trimmed;
27
27
  return null;
28
28
  }
@@ -58,15 +58,21 @@ const EditCategoryDrawer = ({ open, onOpenChange, category, salesChannels, onSuc
58
58
  setIsInternal(Boolean(category.is_internal));
59
59
  setSelectedChannels(category.sales_channels || salesChannels.map((s) => s.id));
60
60
  setCurrentMetadata(category.metadata || {});
61
- // Parse YouTube URLs from metadata
61
+ // Parse YouTube URLs from metadata (including legacy fields)
62
62
  const meta = category.metadata;
63
63
  const urls = [];
64
64
  if (meta?.youtube_urls && Array.isArray(meta.youtube_urls)) {
65
65
  meta.youtube_urls.forEach((u) => typeof u === "string" && u.trim() && urls.push(u.trim()));
66
66
  }
67
- else if (meta?.youtube_url && typeof meta.youtube_url === "string") {
67
+ else if (meta?.youtube_url && typeof meta.youtube_url === "string" && meta.youtube_url.trim()) {
68
68
  urls.push(meta.youtube_url.trim());
69
69
  }
70
+ else if (meta?.youtube_link && typeof meta.youtube_link === "string" && meta.youtube_link.trim()) {
71
+ urls.push(meta.youtube_link.trim());
72
+ }
73
+ else if (meta?.video_url && typeof meta.video_url === "string" && meta.video_url.trim()) {
74
+ urls.push(meta.video_url.trim());
75
+ }
70
76
  setYoutubeUrls(urls);
71
77
  setActiveTab("general");
72
78
  // Load category media from backend
@@ -93,8 +99,13 @@ const EditCategoryDrawer = ({ open, onOpenChange, category, salesChannels, onSuc
93
99
  catch {
94
100
  // Endpoint fallback
95
101
  }
96
- // Metadata fallback: if metadata.images array exists
97
- if (metadata?.images && Array.isArray(metadata.images) && metadata.images.length > 0) {
102
+ // Explicit metadata.images check: if metadata.images array exists (even if empty)
103
+ if (metadata && Array.isArray(metadata.images)) {
104
+ if (metadata.images.length === 0) {
105
+ setCategoryImages([]);
106
+ setImageUrl("");
107
+ return;
108
+ }
98
109
  setCategoryImages(metadata.images);
99
110
  const thumb = metadata.images.find((img) => img.type === "thumbnail") || metadata.images[0];
100
111
  if (thumb?.url)
@@ -103,7 +114,7 @@ const EditCategoryDrawer = ({ open, onOpenChange, category, salesChannels, onSuc
103
114
  }
104
115
  // Legacy fallback
105
116
  const list = [];
106
- const thumb = currentImageUrl || metadata?.thumbnail || metadata?.image_url;
117
+ const thumb = metadata?.thumbnail || metadata?.image_url || currentImageUrl;
107
118
  if (thumb) {
108
119
  list.push({ url: thumb, type: "thumbnail" });
109
120
  }
@@ -228,8 +239,26 @@ const EditCategoryDrawer = ({ open, onOpenChange, category, salesChannels, onSuc
228
239
  setManualImageUrl("");
229
240
  ui_1.toast.success(`Added to gallery as ${newType === "thumbnail" ? "Thumbnail" : newType === "banner" ? "Hero Banner" : "Image"}`);
230
241
  };
231
- // Delete category image
242
+ // Delete category image with immediate persistence & explicit nulls
232
243
  const handleDeleteImage = async (img) => {
244
+ const remaining = categoryImages.filter((i) => i.url !== img.url && (img.id ? i.id !== img.id : true));
245
+ const nextThumb = remaining.find((i) => i.type === "thumbnail") || remaining[0] || null;
246
+ const nextBanner = remaining.find((i) => i.type === "banner") ||
247
+ (remaining.length > 1 ? remaining.find((i) => i.url !== nextThumb?.url) : null) ||
248
+ null;
249
+ // Update local state immediately
250
+ setCategoryImages(remaining);
251
+ setImageUrl(nextThumb ? nextThumb.url : "");
252
+ const updatedMeta = {
253
+ ...(currentMetadata || {}),
254
+ images: remaining,
255
+ thumbnail: nextThumb ? nextThumb.url : null,
256
+ image_url: nextThumb ? nextThumb.url : null,
257
+ banner: nextBanner ? nextBanner.url : null,
258
+ image: (nextBanner?.url || nextThumb?.url) || null,
259
+ };
260
+ setCurrentMetadata(updatedMeta);
261
+ // Call backend endpoint if DB relation exists
233
262
  if (img.id) {
234
263
  try {
235
264
  await sdk_1.sdk.client.fetch(`/admin/categories/${category.id}/images/batch`, {
@@ -240,16 +269,27 @@ const EditCategoryDrawer = ({ open, onOpenChange, category, salesChannels, onSuc
240
269
  },
241
270
  });
242
271
  }
243
- catch {
244
- // Fallback
272
+ catch (err) {
273
+ console.warn("Could not delete from backend images endpoint:", err);
245
274
  }
246
275
  }
247
- setCategoryImages((prev) => prev.filter((i) => i.url !== img.url && (img.id ? i.id !== img.id : true)));
248
- if (imageUrl === img.url) {
249
- const remaining = categoryImages.filter((i) => i.url !== img.url && (img.id ? i.id !== img.id : true));
250
- setImageUrl(remaining[0]?.url || "");
276
+ // Immediately persist metadata changes to Medusa
277
+ try {
278
+ await sdk_1.sdk.admin.productCategory.update(category.id, {
279
+ metadata: updatedMeta,
280
+ });
281
+ const updatedCat = {
282
+ ...category,
283
+ image_url: nextThumb ? nextThumb.url : "",
284
+ metadata: updatedMeta,
285
+ };
286
+ onSuccess(updatedCat);
287
+ ui_1.toast.success("Image removed and changes saved");
288
+ }
289
+ catch (err) {
290
+ console.warn("Could not immediately update category metadata on delete:", err);
291
+ ui_1.toast.info("Image removed from gallery (remember to save)");
251
292
  }
252
- ui_1.toast.info("Image removed");
253
293
  };
254
294
  if (!category)
255
295
  return null;
@@ -258,7 +298,7 @@ const EditCategoryDrawer = ({ open, onOpenChange, category, salesChannels, onSuc
258
298
  ? prev.filter((id) => id !== channelId)
259
299
  : [...prev, channelId]);
260
300
  };
261
- const handleAddYoutube = () => {
301
+ const handleAddYoutube = async () => {
262
302
  const raw = newYoutubeInput.trim();
263
303
  if (!raw)
264
304
  return;
@@ -272,15 +312,59 @@ const EditCategoryDrawer = ({ open, onOpenChange, category, salesChannels, onSuc
272
312
  ui_1.toast.error("Video already added");
273
313
  return;
274
314
  }
275
- setYoutubeUrls((prev) => [...prev, cleanUrl]);
315
+ const nextUrls = [...youtubeUrls, cleanUrl];
316
+ setYoutubeUrls(nextUrls);
276
317
  setNewYoutubeInput("");
277
- ui_1.toast.success("YouTube video added");
318
+ const updatedMeta = {
319
+ ...(currentMetadata || {}),
320
+ youtube_urls: nextUrls,
321
+ youtube_url: nextUrls[0] || null,
322
+ youtube_link: nextUrls[0] || null,
323
+ video_url: nextUrls[0] || null,
324
+ };
325
+ setCurrentMetadata(updatedMeta);
326
+ try {
327
+ await sdk_1.sdk.admin.productCategory.update(category.id, {
328
+ metadata: updatedMeta,
329
+ });
330
+ onSuccess({
331
+ ...category,
332
+ metadata: updatedMeta,
333
+ });
334
+ ui_1.toast.success("YouTube video added and saved");
335
+ }
336
+ catch {
337
+ ui_1.toast.success("YouTube video added");
338
+ }
278
339
  };
279
- const handleRemoveYoutube = (urlToRemove) => {
280
- setYoutubeUrls((prev) => prev.filter((u) => u !== urlToRemove));
340
+ const handleRemoveYoutube = async (urlToRemove) => {
341
+ const nextUrls = youtubeUrls.filter((u) => u !== urlToRemove);
342
+ setYoutubeUrls(nextUrls);
343
+ const updatedMeta = {
344
+ ...(currentMetadata || {}),
345
+ youtube_urls: nextUrls,
346
+ youtube_url: nextUrls[0] || null,
347
+ youtube_link: nextUrls[0] || null,
348
+ video_url: nextUrls[0] || null,
349
+ };
350
+ setCurrentMetadata(updatedMeta);
351
+ try {
352
+ await sdk_1.sdk.admin.productCategory.update(category.id, {
353
+ metadata: updatedMeta,
354
+ });
355
+ onSuccess({
356
+ ...category,
357
+ metadata: updatedMeta,
358
+ });
359
+ ui_1.toast.success("Video removed and changes saved");
360
+ }
361
+ catch {
362
+ ui_1.toast.info("Video removed (remember to save)");
363
+ }
281
364
  };
282
365
  const handleSubmit = async (e) => {
283
- e.preventDefault();
366
+ if (e && e.preventDefault)
367
+ e.preventDefault();
284
368
  if (!name.trim()) {
285
369
  ui_1.toast.error("Category name is required");
286
370
  return;
@@ -288,26 +372,24 @@ const EditCategoryDrawer = ({ open, onOpenChange, category, salesChannels, onSuc
288
372
  setIsSubmitting(true);
289
373
  try {
290
374
  const thumbImg = categoryImages.find((img) => img.type === "thumbnail") ||
291
- categoryImages[0];
375
+ categoryImages[0] ||
376
+ null;
292
377
  const bannerImg = categoryImages.find((img) => img.type === "banner") ||
293
- categoryImages.find((img) => img.url !== thumbImg?.url);
378
+ (categoryImages.length > 1 ? categoryImages.find((img) => img.url !== thumbImg?.url) : null) ||
379
+ null;
294
380
  const updatedMetadata = {
295
381
  ...(currentMetadata || {}),
296
382
  sales_channels: selectedChannels,
297
383
  youtube_urls: youtubeUrls,
384
+ youtube_url: youtubeUrls[0] || null,
385
+ youtube_link: youtubeUrls[0] || null,
386
+ video_url: youtubeUrls[0] || null,
298
387
  images: categoryImages,
388
+ thumbnail: thumbImg ? thumbImg.url : null,
389
+ image_url: thumbImg ? thumbImg.url : null,
390
+ banner: bannerImg ? bannerImg.url : null,
391
+ image: (bannerImg?.url || thumbImg?.url) || null,
299
392
  };
300
- if (thumbImg?.url) {
301
- updatedMetadata.thumbnail = thumbImg.url;
302
- updatedMetadata.image_url = thumbImg.url;
303
- }
304
- if (bannerImg?.url && bannerImg.url !== thumbImg?.url) {
305
- updatedMetadata.banner = bannerImg.url;
306
- updatedMetadata.image = bannerImg.url;
307
- }
308
- else if (thumbImg?.url) {
309
- updatedMetadata.image = thumbImg.url;
310
- }
311
393
  await sdk_1.sdk.admin.productCategory.update(category.id, {
312
394
  name: name.trim(),
313
395
  handle: handle.trim() || undefined,
@@ -322,7 +404,7 @@ const EditCategoryDrawer = ({ open, onOpenChange, category, salesChannels, onSuc
322
404
  name: name.trim(),
323
405
  handle: handle.trim(),
324
406
  description: description.trim() || null,
325
- image_url: imageUrl.trim() || category.image_url,
407
+ image_url: thumbImg ? thumbImg.url : "",
326
408
  rank: Number(rank) || 0,
327
409
  sales_channels: selectedChannels,
328
410
  is_active: isActive,
@@ -360,15 +442,15 @@ const EditCategoryDrawer = ({ open, onOpenChange, category, salesChannels, onSuc
360
442
  };
361
443
  return ((0, jsx_runtime_1.jsx)(ui_1.Drawer, { open: open, onOpenChange: onOpenChange, children: (0, jsx_runtime_1.jsx)(ui_1.Drawer.Content, { className: `transition-all duration-300 w-full z-50 ${isFullScreen
362
444
  ? "!max-w-full !w-screen !h-screen !inset-0 !rounded-none"
363
- : "max-w-5xl xl:max-w-6xl w-[92vw]"}`, children: (0, jsx_runtime_1.jsxs)("form", { onSubmit: handleSubmit, className: "flex flex-col h-full", children: [(0, jsx_runtime_1.jsxs)(ui_1.Drawer.Header, { className: "border-b border-ui-border-base pb-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between w-full", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(ui_1.Drawer.Title, { className: "text-base font-semibold text-ui-fg-base", children: category.name }), (0, jsx_runtime_1.jsxs)(ui_1.Drawer.Description, { className: "text-xs text-ui-fg-muted mt-0.5", children: ["Tier ", category.tier, " \u2022 ID: ", category.id] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => setIsFullScreen((prev) => !prev), className: "flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-ui-fg-subtle hover:text-ui-fg-base rounded-lg border border-ui-border-base bg-ui-bg-subtle hover:bg-ui-bg-base shadow-2xs transition-colors", title: isFullScreen ? "Exit Fullscreen" : "Expand to Full Page Modal", children: [(0, jsx_runtime_1.jsx)(icons_1.ArrowsPointingOut, { className: "w-3.5 h-3.5" }), (0, jsx_runtime_1.jsx)("span", { children: isFullScreen ? "Exit Fullscreen" : "Full Page" })] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => window.open(`/app/categories/${category.id}`, "_blank"), className: "flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-ui-fg-subtle hover:text-ui-fg-base rounded-lg border border-ui-border-base bg-ui-bg-subtle hover:bg-ui-bg-base shadow-2xs transition-colors", title: "Open full category details page in a new tab", children: [(0, jsx_runtime_1.jsx)("span", { children: "Open Full Page" }), (0, jsx_runtime_1.jsx)(icons_1.ArrowUpRightMicro, { className: "w-3.5 h-3.5" })] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1 mt-3 border-b border-ui-border-base/50 -mb-3 pb-1", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab("general"), className: `px-3 py-1.5 text-xs font-medium rounded-t-lg transition-colors border-b-2 -mb-[5px] ${activeTab === "general"
364
- ? "border-ui-border-interactive text-ui-fg-base bg-ui-bg-subtle/50"
365
- : "border-transparent text-ui-fg-muted hover:text-ui-fg-base"}`, children: "General & Ranking" }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab("products"), className: `px-3 py-1.5 text-xs font-medium rounded-t-lg transition-colors border-b-2 -mb-[5px] ${activeTab === "products"
366
- ? "border-ui-border-interactive text-ui-fg-base bg-ui-bg-subtle/50"
367
- : "border-transparent text-ui-fg-muted hover:text-ui-fg-base"}`, children: "Products Management" }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab("channels"), className: `px-3 py-1.5 text-xs font-medium rounded-t-lg transition-colors border-b-2 -mb-[5px] ${activeTab === "channels"
368
- ? "border-ui-border-interactive text-ui-fg-base bg-ui-bg-subtle/50"
369
- : "border-transparent text-ui-fg-muted hover:text-ui-fg-base"}`, children: "Storefronts & Media" }), (0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => setActiveTab("youtube"), className: `px-3 py-1.5 text-xs font-medium rounded-t-lg transition-colors border-b-2 -mb-[5px] ${activeTab === "youtube"
370
- ? "border-ui-border-interactive text-ui-fg-base bg-ui-bg-subtle/50"
371
- : "border-transparent text-ui-fg-muted hover:text-ui-fg-base"}`, children: ["YouTube Videos (", youtubeUrls.length, ")"] })] })] }), (0, jsx_runtime_1.jsxs)(ui_1.Drawer.Body, { className: "flex flex-col gap-4 overflow-y-auto px-6 py-4 flex-1", children: [activeTab === "general" && ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1.5", children: [(0, jsx_runtime_1.jsx)(ui_1.Label, { htmlFor: "edit-name", className: "text-xs font-semibold", children: "Category Name *" }), (0, jsx_runtime_1.jsx)(ui_1.Input, { id: "edit-name", size: "small", value: name, onChange: (e) => setName(e.target.value) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1.5", children: [(0, jsx_runtime_1.jsx)(ui_1.Label, { htmlFor: "edit-handle", className: "text-xs font-semibold", children: "Handle (URL slug)" }), (0, jsx_runtime_1.jsx)(ui_1.Input, { id: "edit-handle", size: "small", value: handle, onChange: (e) => setHandle(e.target.value) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1.5 p-3 rounded-lg bg-ui-bg-subtle border border-ui-border-base", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)(ui_1.Label, { htmlFor: "edit-rank", className: "text-xs font-semibold", children: "Storefront Ranking (Sort Order)" }), (0, jsx_runtime_1.jsx)("span", { className: "text-[10px] font-mono text-ui-fg-muted", children: "Controls Storefront 2 & Monfil" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(ui_1.Input, { id: "edit-rank", type: "number", size: "small", value: rank, onChange: (e) => setRank(Number(e.target.value)), className: "w-24" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setRank((r) => Math.max(0, r - 1)), className: "px-2 py-1 text-xs font-medium rounded border border-ui-border-base bg-ui-bg-base hover:bg-ui-bg-subtle transition-colors", title: "Move Earlier in Storefront", children: "\u2191 Earlier" }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setRank((r) => r + 1), className: "px-2 py-1 text-xs font-medium rounded border border-ui-border-base bg-ui-bg-base hover:bg-ui-bg-subtle transition-colors", title: "Move Later in Storefront", children: "\u2193 Later" }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setRank(0), className: "px-2 py-1 text-xs font-medium rounded border border-ui-border-base bg-ui-bg-base hover:bg-ui-bg-subtle transition-colors", title: "Set as First Category", children: "Top (#0)" })] })] }), (0, jsx_runtime_1.jsx)("p", { className: "text-[11px] text-ui-fg-muted leading-relaxed", children: "Categories are sorted by rank ASC (0, 1, 2...). Lower numbers appear first on your storefront navigation menu." })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1.5", children: [(0, jsx_runtime_1.jsx)(ui_1.Label, { htmlFor: "edit-desc", className: "text-xs font-semibold", children: "Description" }), (0, jsx_runtime_1.jsx)(ui_1.Textarea, { id: "edit-desc", value: description, onChange: (e) => setDescription(e.target.value), rows: 3 })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between pt-2 border-t border-ui-border-base", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(ui_1.Label, { className: "text-xs font-semibold", children: "Active Status" }), (0, jsx_runtime_1.jsx)(ui_1.Text, { size: "xsmall", className: "text-ui-fg-muted", children: "Visible to shoppers on enabled storefronts" })] }), (0, jsx_runtime_1.jsx)(ui_1.Switch, { checked: isActive, onCheckedChange: setIsActive })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(ui_1.Label, { className: "text-xs font-semibold", children: "Internal Only" }), (0, jsx_runtime_1.jsx)(ui_1.Text, { size: "xsmall", className: "text-ui-fg-muted", children: "Hidden from public storefront navigation" })] }), (0, jsx_runtime_1.jsx)(ui_1.Switch, { checked: isInternal, onCheckedChange: setIsInternal })] }), (0, jsx_runtime_1.jsx)("div", { className: "pt-3 border-t border-ui-border-base", children: (0, jsx_runtime_1.jsxs)(ui_1.Button, { type: "button", variant: "danger", size: "small", onClick: handleDelete, isLoading: isDeleting, className: "w-full flex items-center justify-center gap-1.5", children: [(0, jsx_runtime_1.jsx)(icons_1.Trash, { className: "w-3.5 h-3.5" }), (0, jsx_runtime_1.jsx)("span", { children: "Delete Category" })] }) })] })), activeTab === "products" && ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-col gap-3", children: (0, jsx_runtime_1.jsx)(category_products_manager_1.CategoryProductsManager, { categoryId: category.id, categoryName: category.name, initialMetadata: currentMetadata, onMetadataUpdate: (meta) => {
445
+ : "max-w-5xl xl:max-w-6xl w-[92vw]"}`, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col h-full", children: [(0, jsx_runtime_1.jsxs)(ui_1.Drawer.Header, { className: "border-b border-ui-border-base pb-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between w-full", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(ui_1.Drawer.Title, { className: "text-base font-semibold text-ui-fg-base", children: category.name }), (0, jsx_runtime_1.jsxs)(ui_1.Drawer.Description, { className: "text-xs text-ui-fg-muted mt-0.5", children: ["Tier ", category.tier, " \u2022 ID: ", category.id] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => setIsFullScreen((prev) => !prev), className: "flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-ui-fg-subtle hover:text-ui-fg-base rounded-lg border border-ui-border-base bg-ui-bg-subtle hover:bg-ui-bg-base shadow-2xs transition-colors cursor-pointer", title: isFullScreen ? "Exit Fullscreen" : "Expand to Full Page Modal", children: [(0, jsx_runtime_1.jsx)(icons_1.ArrowsPointingOut, { className: "w-3.5 h-3.5" }), (0, jsx_runtime_1.jsx)("span", { children: isFullScreen ? "Exit Fullscreen" : "Full Page" })] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => window.open(`/app/categories/${category.id}`, "_blank"), className: "flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-ui-fg-subtle hover:text-ui-fg-base rounded-lg border border-ui-border-base bg-ui-bg-subtle hover:bg-ui-bg-base shadow-2xs transition-colors cursor-pointer", title: "Open full category details page in a new tab", children: [(0, jsx_runtime_1.jsx)("span", { children: "Open Full Page" }), (0, jsx_runtime_1.jsx)(icons_1.ArrowUpRightMicro, { className: "w-3.5 h-3.5" })] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1 mt-3 border-b border-ui-border-base -mb-3", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab("general"), className: `px-3 py-1.5 text-xs font-medium border-b-2 transition-colors cursor-pointer ${activeTab === "general"
446
+ ? "border-blue-600 text-blue-600 font-semibold"
447
+ : "border-transparent text-ui-fg-muted hover:text-ui-fg-base"}`, children: "General & Ranking" }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab("products"), className: `px-3 py-1.5 text-xs font-medium border-b-2 transition-colors cursor-pointer ${activeTab === "products"
448
+ ? "border-blue-600 text-blue-600 font-semibold"
449
+ : "border-transparent text-ui-fg-muted hover:text-ui-fg-base"}`, children: "Products Management" }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab("channels"), className: `px-3 py-1.5 text-xs font-medium border-b-2 transition-colors cursor-pointer ${activeTab === "channels"
450
+ ? "border-blue-600 text-blue-600 font-semibold"
451
+ : "border-transparent text-ui-fg-muted hover:text-ui-fg-base"}`, children: "Storefronts & Media" }), (0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => setActiveTab("youtube"), className: `flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium border-b-2 transition-colors cursor-pointer ${activeTab === "youtube"
452
+ ? "border-blue-600 text-blue-600 font-semibold"
453
+ : "border-transparent text-ui-fg-muted hover:text-ui-fg-base"}`, children: [(0, jsx_runtime_1.jsx)("span", { children: "YouTube Videos" }), youtubeUrls.length > 0 && ((0, jsx_runtime_1.jsx)("span", { className: "px-1.5 py-0.2 rounded-full text-[10px] font-bold bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200", children: youtubeUrls.length }))] })] })] }), (0, jsx_runtime_1.jsxs)(ui_1.Drawer.Body, { className: "overflow-y-auto flex-1 p-6", children: [activeTab === "general" && ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1.5", children: [(0, jsx_runtime_1.jsx)(ui_1.Label, { htmlFor: "edit-name", className: "text-xs font-semibold", children: "Category Name *" }), (0, jsx_runtime_1.jsx)(ui_1.Input, { id: "edit-name", value: name, onChange: (e) => setName(e.target.value), required: true })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1.5", children: [(0, jsx_runtime_1.jsx)(ui_1.Label, { htmlFor: "edit-handle", className: "text-xs font-semibold", children: "Handle (URL Slug)" }), (0, jsx_runtime_1.jsx)(ui_1.Input, { id: "edit-handle", value: handle, onChange: (e) => setHandle(e.target.value), placeholder: "e.g. rayon-embroidery-thread" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1.5 p-3 rounded-xl border border-ui-border-base bg-ui-bg-subtle/50", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)(ui_1.Label, { htmlFor: "edit-rank", className: "text-xs font-semibold", children: "Storefront Ranking (Sort Order)" }), (0, jsx_runtime_1.jsx)("span", { className: "text-[10px] font-mono text-ui-fg-muted", children: "Controls Storefront 2 & Monfil" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(ui_1.Input, { id: "edit-rank", type: "number", size: "small", value: rank, onChange: (e) => setRank(Number(e.target.value)), className: "w-24" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setRank((r) => Math.max(0, r - 1)), className: "px-2 py-1 text-xs font-medium rounded border border-ui-border-base bg-ui-bg-base hover:bg-ui-bg-subtle transition-colors cursor-pointer", title: "Move Earlier in Storefront", children: "\u2191 Earlier" }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setRank((r) => r + 1), className: "px-2 py-1 text-xs font-medium rounded border border-ui-border-base bg-ui-bg-base hover:bg-ui-bg-subtle transition-colors cursor-pointer", title: "Move Later in Storefront", children: "\u2193 Later" }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setRank(0), className: "px-2 py-1 text-xs font-medium rounded border border-ui-border-base bg-ui-bg-base hover:bg-ui-bg-subtle transition-colors cursor-pointer", title: "Set as First Category", children: "Top (#0)" })] })] }), (0, jsx_runtime_1.jsx)("p", { className: "text-[11px] text-ui-fg-muted leading-relaxed", children: "Categories are sorted by rank ASC (0, 1, 2...). Lower numbers appear first on your storefront navigation menu." })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1.5", children: [(0, jsx_runtime_1.jsx)(ui_1.Label, { htmlFor: "edit-desc", className: "text-xs font-semibold", children: "Description" }), (0, jsx_runtime_1.jsx)(ui_1.Textarea, { id: "edit-desc", value: description, onChange: (e) => setDescription(e.target.value), rows: 3 })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between pt-2 border-t border-ui-border-base", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(ui_1.Label, { className: "text-xs font-semibold", children: "Active Status" }), (0, jsx_runtime_1.jsx)(ui_1.Text, { size: "xsmall", className: "text-ui-fg-muted", children: "Visible to shoppers on enabled storefronts" })] }), (0, jsx_runtime_1.jsx)(ui_1.Switch, { checked: isActive, onCheckedChange: setIsActive })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(ui_1.Label, { className: "text-xs font-semibold", children: "Internal Only" }), (0, jsx_runtime_1.jsx)(ui_1.Text, { size: "xsmall", className: "text-ui-fg-muted", children: "Hidden from public storefront navigation" })] }), (0, jsx_runtime_1.jsx)(ui_1.Switch, { checked: isInternal, onCheckedChange: setIsInternal })] }), (0, jsx_runtime_1.jsx)("div", { className: "pt-3 border-t border-ui-border-base", children: (0, jsx_runtime_1.jsxs)(ui_1.Button, { type: "button", variant: "danger", size: "small", onClick: handleDelete, isLoading: isDeleting, className: "w-full flex items-center justify-center gap-1.5", children: [(0, jsx_runtime_1.jsx)(icons_1.Trash, { className: "w-3.5 h-3.5" }), (0, jsx_runtime_1.jsx)("span", { children: "Delete Category" })] }) })] })), activeTab === "products" && ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-col gap-3", children: (0, jsx_runtime_1.jsx)(category_products_manager_1.CategoryProductsManager, { categoryId: category.id, categoryName: category.name, initialMetadata: currentMetadata, onMetadataUpdate: (meta) => {
372
454
  setCurrentMetadata(meta);
373
455
  } }) })), activeTab === "channels" && ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-2", children: [(0, jsx_runtime_1.jsx)(ui_1.Label, { className: "text-xs font-semibold", children: "Storefront Visibility" }), (0, jsx_runtime_1.jsx)(ui_1.Text, { size: "xsmall", className: "text-ui-fg-muted", children: "Designate which storefront sales channels display this category." }), (0, jsx_runtime_1.jsx)("div", { className: "flex flex-col gap-2 mt-1", children: salesChannels.map((channel) => {
374
456
  const isChecked = selectedChannels.includes(channel.id);
@@ -395,16 +477,16 @@ const EditCategoryDrawer = ({ open, onOpenChange, category, salesChannels, onSuc
395
477
  e.preventDefault();
396
478
  e.stopPropagation();
397
479
  handleSetThumbnail(img);
398
- }, className: "w-full py-0.5 bg-white text-neutral-900 rounded text-[9px] font-semibold hover:bg-neutral-100 transition-colors shadow-xs text-center", children: "Set Thumbnail" })), !isBanner && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: (e) => {
480
+ }, className: "w-full py-0.5 bg-white text-neutral-900 rounded text-[9px] font-semibold hover:bg-neutral-100 transition-colors shadow-xs text-center cursor-pointer", children: "Set Thumbnail" })), !isBanner && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: (e) => {
399
481
  e.preventDefault();
400
482
  e.stopPropagation();
401
483
  handleSetBanner(img);
402
- }, className: "w-full py-0.5 bg-emerald-500 text-white rounded text-[9px] font-semibold hover:bg-emerald-600 transition-colors shadow-xs text-center", children: "Set as Banner" })), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: (e) => {
484
+ }, className: "w-full py-0.5 bg-emerald-600 text-white rounded text-[9px] font-semibold hover:bg-emerald-700 transition-colors shadow-xs text-center cursor-pointer", children: "Set as Banner" })), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: (e) => {
403
485
  e.preventDefault();
404
486
  e.stopPropagation();
405
487
  handleDeleteImage(img);
406
- }, className: "p-1 bg-rose-600 text-white rounded hover:bg-rose-700 transition-colors", title: "Remove image", children: (0, jsx_runtime_1.jsx)(icons_1.Trash, { className: "w-3.5 h-3.5" }) })] })] }, img.id || img.url || idx));
407
- }) })] })), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1.5 mt-1 pt-2 border-t border-ui-border-base/50", children: [(0, jsx_runtime_1.jsx)(ui_1.Label, { htmlFor: "manual-image-url", className: "text-[11px] text-ui-fg-muted font-medium", children: "Or paste an external image URL to add to gallery" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(ui_1.Input, { id: "manual-image-url", size: "small", value: manualImageUrl, onChange: (e) => setManualImageUrl(e.target.value), placeholder: "https://example.com/banner-or-thumbnail.jpg", className: "flex-1 text-xs", onKeyDown: (e) => {
488
+ }, className: "w-full py-0.5 bg-rose-600 text-white rounded text-[9px] font-semibold hover:bg-rose-700 transition-colors shadow-xs text-center cursor-pointer", children: "Delete" })] })] }, img.id || img.url || idx));
489
+ }) })] })), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1.5 mt-2 p-3 rounded-xl border border-ui-border-base bg-ui-bg-subtle/30", children: [(0, jsx_runtime_1.jsx)(ui_1.Label, { className: "text-xs font-semibold text-ui-fg-base", children: "External Image URL (CDN / Manual)" }), (0, jsx_runtime_1.jsx)("p", { className: "text-[11px] text-ui-fg-muted", children: "Or paste a direct image URL (S3, Cloudinary, Imgur, Supabase) to link without uploading." }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 mt-1", children: [(0, jsx_runtime_1.jsx)(ui_1.Input, { size: "small", type: "url", placeholder: "https://example.com/category-image.jpg", value: manualImageUrl, onChange: (e) => setManualImageUrl(e.target.value), className: "text-xs flex-1", onKeyDown: (e) => {
408
490
  if (e.key === "Enter") {
409
491
  e.preventDefault();
410
492
  handleAddManualImage();
@@ -417,7 +499,7 @@ const EditCategoryDrawer = ({ open, onOpenChange, category, salesChannels, onSuc
417
499
  } }), (0, jsx_runtime_1.jsxs)(ui_1.Button, { size: "small", type: "button", variant: "secondary", onClick: handleAddYoutube, className: "flex items-center gap-1 text-xs flex-shrink-0", children: [(0, jsx_runtime_1.jsx)(icons_1.Plus, { className: "w-3.5 h-3.5" }), (0, jsx_runtime_1.jsx)("span", { children: "Add Video" })] })] }), youtubeUrls.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "p-8 text-center text-xs text-ui-fg-muted border border-dashed border-ui-border-base rounded-xl", children: "No demonstration videos attached yet." })) : ((0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-2 gap-3", children: youtubeUrls.map((url) => {
418
500
  const id = extractYouTubeVideoId(url);
419
501
  const thumb = id ? `https://img.youtube.com/vi/${id}/hqdefault.jpg` : null;
420
- return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col border border-ui-border-base rounded-xl overflow-hidden bg-ui-bg-subtle/40 shadow-xs", children: [(0, jsx_runtime_1.jsxs)("div", { className: "relative aspect-video bg-black/80 overflow-hidden flex items-center justify-center", children: [thumb ? ((0, jsx_runtime_1.jsx)("img", { src: thumb, alt: "YouTube Preview", className: "w-full h-full object-cover" })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-xs text-white", children: "Video" })), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => handleRemoveYoutube(url), className: "absolute top-1.5 right-1.5 p-1 bg-black/70 hover:bg-rose-600 text-white rounded-full transition-colors", title: "Remove video", children: (0, jsx_runtime_1.jsx)(icons_1.Trash, { className: "w-3 h-3" }) })] }), (0, jsx_runtime_1.jsx)("div", { className: "p-2", children: (0, jsx_runtime_1.jsx)("span", { className: "text-[10px] text-ui-fg-muted truncate block font-mono", title: url, children: url }) })] }, url));
421
- }) }))] }))] }), (0, jsx_runtime_1.jsxs)(ui_1.Drawer.Footer, { className: "flex justify-end gap-2 px-6 py-4 border-t border-ui-border-base", children: [(0, jsx_runtime_1.jsx)(ui_1.Button, { type: "button", variant: "secondary", size: "small", onClick: () => onOpenChange(false), disabled: isSubmitting || isDeleting, children: "Close" }), (0, jsx_runtime_1.jsx)(ui_1.Button, { type: "submit", size: "small", isLoading: isSubmitting, disabled: isSubmitting || !name.trim() || isDeleting, children: "Save Category" })] })] }) }) }));
502
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col border border-ui-border-base rounded-xl overflow-hidden bg-ui-bg-subtle/40 shadow-xs", children: [(0, jsx_runtime_1.jsxs)("div", { className: "relative aspect-video bg-black/80 overflow-hidden flex items-center justify-center", children: [thumb ? ((0, jsx_runtime_1.jsx)("img", { src: thumb, alt: "YouTube Preview", className: "w-full h-full object-cover" })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-xs text-white", children: "Video" })), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => handleRemoveYoutube(url), className: "absolute top-1.5 right-1.5 p-1 bg-black/70 hover:bg-rose-600 text-white rounded-full transition-colors cursor-pointer", title: "Remove video", children: (0, jsx_runtime_1.jsx)(icons_1.Trash, { className: "w-3 h-3" }) })] }), (0, jsx_runtime_1.jsx)("div", { className: "p-2", children: (0, jsx_runtime_1.jsx)("span", { className: "text-[10px] text-ui-fg-muted truncate block font-mono", title: url, children: url }) })] }, url));
503
+ }) }))] }))] }), (0, jsx_runtime_1.jsxs)(ui_1.Drawer.Footer, { className: "flex justify-end gap-2 px-6 py-4 border-t border-ui-border-base", children: [(0, jsx_runtime_1.jsx)(ui_1.Button, { type: "button", variant: "secondary", size: "small", onClick: () => onOpenChange(false), disabled: isSubmitting || isDeleting, children: "Close" }), (0, jsx_runtime_1.jsx)(ui_1.Button, { type: "button", size: "small", onClick: () => handleSubmit(), isLoading: isSubmitting, disabled: isSubmitting || !name.trim() || isDeleting, children: "Save Category" })] })] }) }) }));
422
504
  };
423
505
  exports.EditCategoryDrawer = EditCategoryDrawer;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hectasquare/medusa-plugin-category-tree",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "AAA Interactive Category Tree & Mind Map for Medusa v2 Admin with drag-and-drop reparenting, tier indicators, superscript ranks, multi-storefront filtering, and NotebookLM-style subtree collapse.",
5
5
  "author": "HectaSquare Team",
6
6
  "license": "Apache-2.0",