medusa-dynamic-metadata 0.0.1

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.
@@ -0,0 +1,1729 @@
1
+ "use strict";
2
+ const jsxRuntime = require("react/jsx-runtime");
3
+ const adminSdk = require("@medusajs/admin-sdk");
4
+ const react = require("react");
5
+ const ui = require("@medusajs/ui");
6
+ const reactQuery = require("@tanstack/react-query");
7
+ const METADATA_FIELD_TYPES = ["number", "text", "file", "bool"];
8
+ const VALID_FIELD_TYPES = new Set(METADATA_FIELD_TYPES);
9
+ const BOOLEAN_TRUES = /* @__PURE__ */ new Set(["true", "1", "yes", "y", "on"]);
10
+ const BOOLEAN_FALSES = /* @__PURE__ */ new Set(["false", "0", "no", "n", "off"]);
11
+ function normalizeMetadataDescriptors(input) {
12
+ if (!Array.isArray(input)) return [];
13
+ const seenKeys = /* @__PURE__ */ new Set();
14
+ return input.filter(
15
+ (item) => item && typeof item === "object"
16
+ ).map((item) => {
17
+ const key = normalizeKey(item.key);
18
+ const type = normalizeType(item.type);
19
+ const label = normalizeLabel(item.label);
20
+ const filterable = !!item.filterable;
21
+ return { key, type, label, filterable };
22
+ }).filter(({ key, type }) => key && type && !seenKeys.has(key)).map(({ key, type, label, filterable }) => {
23
+ seenKeys.add(key);
24
+ return {
25
+ key,
26
+ type,
27
+ ...label && { label },
28
+ ...filterable && { filterable: true }
29
+ };
30
+ });
31
+ }
32
+ function buildInitialFormState(descriptors, metadata) {
33
+ const base = metadata && typeof metadata === "object" ? metadata : {};
34
+ return descriptors.reduce((acc, descriptor) => {
35
+ acc[descriptor.key] = normalizeFormValue(descriptor, base[descriptor.key]);
36
+ return acc;
37
+ }, {});
38
+ }
39
+ function buildMetadataPayload({
40
+ descriptors,
41
+ values,
42
+ originalMetadata
43
+ }) {
44
+ const base = originalMetadata && typeof originalMetadata === "object" ? { ...originalMetadata } : {};
45
+ descriptors.forEach((descriptor) => {
46
+ const coerced = coerceMetadataValue(descriptor, values[descriptor.key]);
47
+ if (coerced === void 0) {
48
+ delete base[descriptor.key];
49
+ } else {
50
+ base[descriptor.key] = coerced;
51
+ }
52
+ });
53
+ return base;
54
+ }
55
+ function hasMetadataChanges({
56
+ descriptors,
57
+ values,
58
+ originalMetadata
59
+ }) {
60
+ const next = buildMetadataPayload({ descriptors, values, originalMetadata });
61
+ const prev = originalMetadata && typeof originalMetadata === "object" ? originalMetadata : {};
62
+ return descriptors.some(({ key }) => !isDeepEqual(prev[key], next[key]));
63
+ }
64
+ function validateValueForDescriptor(descriptor, value) {
65
+ if (descriptor.type === "number") {
66
+ if (value == null || value === "") return void 0;
67
+ const num = typeof value === "number" ? value : Number(String(value).trim());
68
+ return isNaN(num) ? "Enter a valid number" : void 0;
69
+ }
70
+ if (descriptor.type === "file") {
71
+ if (!value) return void 0;
72
+ try {
73
+ new URL(String(value).trim());
74
+ return void 0;
75
+ } catch {
76
+ return "Enter a valid URL";
77
+ }
78
+ }
79
+ return void 0;
80
+ }
81
+ function normalizeFormValue(descriptor, currentValue) {
82
+ if (descriptor.type === "bool") return Boolean(currentValue);
83
+ if ((descriptor.type === "number" || descriptor.type === "text") && typeof currentValue === "number") {
84
+ return currentValue.toString();
85
+ }
86
+ if (typeof currentValue === "string" || typeof currentValue === "number") {
87
+ return String(currentValue);
88
+ }
89
+ return "";
90
+ }
91
+ function coerceMetadataValue(descriptor, value) {
92
+ if (value == null || value === "") return void 0;
93
+ if (descriptor.type === "bool") {
94
+ if (typeof value === "boolean") return value;
95
+ if (typeof value === "number") return value !== 0;
96
+ const normalized = String(value).trim().toLowerCase();
97
+ if (!normalized) return void 0;
98
+ if (BOOLEAN_TRUES.has(normalized)) return true;
99
+ if (BOOLEAN_FALSES.has(normalized)) return false;
100
+ return Boolean(value);
101
+ }
102
+ if (descriptor.type === "number") {
103
+ const num = typeof value === "number" ? value : Number(String(value).trim());
104
+ return isNaN(num) ? void 0 : num;
105
+ }
106
+ const trimmed = String(value).trim();
107
+ if (!trimmed) return void 0;
108
+ return trimmed;
109
+ }
110
+ function normalizeKey(value) {
111
+ return typeof value === "string" ? value.trim() || void 0 : void 0;
112
+ }
113
+ function normalizeType(value) {
114
+ if (typeof value !== "string") return void 0;
115
+ const type = value.trim().toLowerCase();
116
+ return VALID_FIELD_TYPES.has(type) ? type : void 0;
117
+ }
118
+ function normalizeLabel(value) {
119
+ return typeof value === "string" ? value.trim() || void 0 : void 0;
120
+ }
121
+ function isDeepEqual(a, b) {
122
+ if (a === b) return true;
123
+ if (!a || !b || typeof a !== "object" || typeof b !== "object") return false;
124
+ const aKeys = Object.keys(a);
125
+ const bKeys = Object.keys(b);
126
+ if (aKeys.length !== bKeys.length) return false;
127
+ return aKeys.every(
128
+ (key) => isDeepEqual(a[key], b[key])
129
+ );
130
+ }
131
+ const CONFIG_ENDPOINT = "/admin/metadata-config";
132
+ const QUERY_KEY = ["medusa-dynamic-metadata", "metadata-config"];
133
+ function useMetadataConfig({ entity }) {
134
+ return reactQuery.useQuery({
135
+ queryKey: [...QUERY_KEY, entity],
136
+ queryFn: async () => {
137
+ const response = await fetch(`${CONFIG_ENDPOINT}?entity=${entity}`, {
138
+ credentials: "include"
139
+ });
140
+ if (!response.ok) {
141
+ throw new Error("Unable to load metadata configuration");
142
+ }
143
+ const payload = await response.json();
144
+ return normalizeMetadataDescriptors(payload.metadataDescriptors);
145
+ },
146
+ staleTime: 5 * 60 * 1e3
147
+ });
148
+ }
149
+ const DEFAULT_ENTITY_MAPPINGS = {
150
+ products: {
151
+ widgetZone: "product.details.after",
152
+ apiEndpoint: "/admin/products/{id}",
153
+ responseKey: "product"
154
+ },
155
+ orders: {
156
+ widgetZone: "order.details.after",
157
+ apiEndpoint: "/admin/orders/{id}",
158
+ responseKey: "order"
159
+ },
160
+ categories: {
161
+ widgetZone: "product_category.details.after",
162
+ apiEndpoint: "/admin/product-categories/{id}",
163
+ responseKey: "product_category"
164
+ },
165
+ collections: {
166
+ widgetZone: "product_collection.details.after",
167
+ apiEndpoint: "/admin/collections/{id}",
168
+ responseKey: "collection"
169
+ },
170
+ customers: {
171
+ widgetZone: "customer.details.after",
172
+ apiEndpoint: "/admin/customers/{id}",
173
+ responseKey: "customer"
174
+ },
175
+ regions: {
176
+ widgetZone: "region.details.after",
177
+ apiEndpoint: "/admin/regions/{id}",
178
+ responseKey: "region"
179
+ },
180
+ sales_channels: {
181
+ widgetZone: "sales_channel.details.after",
182
+ apiEndpoint: "/admin/sales-channels/{id}",
183
+ responseKey: "sales_channel"
184
+ },
185
+ stores: {
186
+ widgetZone: "store.details.after",
187
+ apiEndpoint: "/admin/stores/{id}",
188
+ responseKey: "store"
189
+ },
190
+ promotions: {
191
+ widgetZone: "promotion.details.after",
192
+ apiEndpoint: "/admin/promotions/{id}",
193
+ responseKey: "promotion"
194
+ },
195
+ campaigns: {
196
+ widgetZone: "campaign.details.after",
197
+ apiEndpoint: "/admin/campaigns/{id}",
198
+ responseKey: "campaign"
199
+ },
200
+ price_lists: {
201
+ widgetZone: "price_list.details.after",
202
+ apiEndpoint: "/admin/price-lists/{id}",
203
+ responseKey: "price_list"
204
+ },
205
+ shipping_profiles: {
206
+ widgetZone: "shipping_profile.details.after",
207
+ apiEndpoint: "/admin/shipping-profiles/{id}",
208
+ responseKey: "shipping_profile"
209
+ },
210
+ return_reasons: {
211
+ widgetZone: "return_reason.details.after",
212
+ apiEndpoint: "/admin/return-reasons/{id}",
213
+ responseKey: "return_reason"
214
+ },
215
+ inventory_items: {
216
+ widgetZone: "inventory_item.details.after",
217
+ apiEndpoint: "/admin/inventory-items/{id}",
218
+ responseKey: "inventory_item"
219
+ },
220
+ product_variants: {
221
+ widgetZone: "product_variant.details.after",
222
+ apiEndpoint: "/admin/product-variants/{id}",
223
+ responseKey: "product_variant"
224
+ },
225
+ account_holders: {
226
+ widgetZone: "account_holder.details.after",
227
+ apiEndpoint: "/admin/account-holders/{id}",
228
+ responseKey: "account_holder"
229
+ },
230
+ captures: {
231
+ widgetZone: "capture.details.after",
232
+ apiEndpoint: "/admin/captures/{id}",
233
+ responseKey: "capture"
234
+ },
235
+ carts: {
236
+ widgetZone: "cart.details.after",
237
+ apiEndpoint: "/admin/carts/{id}",
238
+ responseKey: "cart"
239
+ },
240
+ cart_addresses: {
241
+ widgetZone: "cart_address.details.after",
242
+ apiEndpoint: "/admin/cart-addresses/{id}",
243
+ responseKey: "cart_address"
244
+ },
245
+ cart_line_items: {
246
+ widgetZone: "cart_line_item.details.after",
247
+ apiEndpoint: "/admin/cart-line-items/{id}",
248
+ responseKey: "cart_line_item"
249
+ },
250
+ cart_line_item_adjustments: {
251
+ widgetZone: "cart_line_item_adjustment.details.after",
252
+ apiEndpoint: "/admin/cart-line-item-adjustments/{id}",
253
+ responseKey: "cart_line_item_adjustment"
254
+ },
255
+ cart_line_item_tax_lines: {
256
+ widgetZone: "cart_line_item_tax_line.details.after",
257
+ apiEndpoint: "/admin/cart-line-item-tax-lines/{id}",
258
+ responseKey: "cart_line_item_tax_line"
259
+ },
260
+ cart_shipping_methods: {
261
+ widgetZone: "cart_shipping_method.details.after",
262
+ apiEndpoint: "/admin/cart-shipping-methods/{id}",
263
+ responseKey: "cart_shipping_method"
264
+ },
265
+ cart_shipping_method_adjustments: {
266
+ widgetZone: "cart_shipping_method_adjustment.details.after",
267
+ apiEndpoint: "/admin/cart-shipping-method-adjustments/{id}",
268
+ responseKey: "cart_shipping_method_adjustment"
269
+ },
270
+ cart_shipping_method_tax_lines: {
271
+ widgetZone: "cart_shipping_method_tax_line.details.after",
272
+ apiEndpoint: "/admin/cart-shipping-method-tax-lines/{id}",
273
+ responseKey: "cart_shipping_method_tax_line"
274
+ },
275
+ contact_email_subscriptions: {
276
+ widgetZone: "contact_email_subscription.details.after",
277
+ apiEndpoint: "/admin/contact-email-subscriptions/{id}",
278
+ responseKey: "contact_email_subscription"
279
+ },
280
+ contact_requests: {
281
+ widgetZone: "contact_request.details.after",
282
+ apiEndpoint: "/admin/contact-requests/{id}",
283
+ responseKey: "contact_request"
284
+ },
285
+ credit_lines: {
286
+ widgetZone: "credit_line.details.after",
287
+ apiEndpoint: "/admin/credit-lines/{id}",
288
+ responseKey: "credit_line"
289
+ },
290
+ customer_addresses: {
291
+ widgetZone: "customer_address.details.after",
292
+ apiEndpoint: "/admin/customer-addresses/{id}",
293
+ responseKey: "customer_address"
294
+ },
295
+ customer_groups: {
296
+ widgetZone: "customer_group.details.after",
297
+ apiEndpoint: "/admin/customer-groups/{id}",
298
+ responseKey: "customer_group"
299
+ },
300
+ customer_group_customers: {
301
+ widgetZone: "customer_group_customer.details.after",
302
+ apiEndpoint: "/admin/customer-group-customers/{id}",
303
+ responseKey: "customer_group_customer"
304
+ },
305
+ fulfillments: {
306
+ widgetZone: "fulfillment.details.after",
307
+ apiEndpoint: "/admin/fulfillments/{id}",
308
+ responseKey: "fulfillment"
309
+ },
310
+ fulfillment_addresses: {
311
+ widgetZone: "fulfillment_address.details.after",
312
+ apiEndpoint: "/admin/fulfillment-addresses/{id}",
313
+ responseKey: "fulfillment_address"
314
+ },
315
+ fulfillment_sets: {
316
+ widgetZone: "fulfillment_set.details.after",
317
+ apiEndpoint: "/admin/fulfillment-sets/{id}",
318
+ responseKey: "fulfillment_set"
319
+ },
320
+ geo_zones: {
321
+ widgetZone: "geo_zone.details.after",
322
+ apiEndpoint: "/admin/geo-zones/{id}",
323
+ responseKey: "geo_zone"
324
+ },
325
+ images: {
326
+ widgetZone: "image.details.after",
327
+ apiEndpoint: "/admin/images/{id}",
328
+ responseKey: "image"
329
+ },
330
+ inventory_levels: {
331
+ widgetZone: "inventory_level.details.after",
332
+ apiEndpoint: "/admin/inventory-levels/{id}",
333
+ responseKey: "inventory_level"
334
+ },
335
+ invites: {
336
+ widgetZone: "invite.details.after",
337
+ apiEndpoint: "/admin/invites/{id}",
338
+ responseKey: "invite"
339
+ },
340
+ order_addresses: {
341
+ widgetZone: "order_address.details.after",
342
+ apiEndpoint: "/admin/order-addresses/{id}",
343
+ responseKey: "order_address"
344
+ },
345
+ order_changes: {
346
+ widgetZone: "order_change.details.after",
347
+ apiEndpoint: "/admin/order-changes/{id}",
348
+ responseKey: "order_change"
349
+ },
350
+ order_claims: {
351
+ widgetZone: "order_claim.details.after",
352
+ apiEndpoint: "/admin/order-claims/{id}",
353
+ responseKey: "order_claim"
354
+ },
355
+ order_claim_items: {
356
+ widgetZone: "order_claim_item.details.after",
357
+ apiEndpoint: "/admin/order-claim-items/{id}",
358
+ responseKey: "order_claim_item"
359
+ },
360
+ order_claim_item_images: {
361
+ widgetZone: "order_claim_item_image.details.after",
362
+ apiEndpoint: "/admin/order-claim-item-images/{id}",
363
+ responseKey: "order_claim_item_image"
364
+ },
365
+ order_credit_lines: {
366
+ widgetZone: "order_credit_line.details.after",
367
+ apiEndpoint: "/admin/order-credit-lines/{id}",
368
+ responseKey: "order_credit_line"
369
+ },
370
+ order_exchanges: {
371
+ widgetZone: "order_exchange.details.after",
372
+ apiEndpoint: "/admin/order-exchanges/{id}",
373
+ responseKey: "order_exchange"
374
+ },
375
+ order_exchange_items: {
376
+ widgetZone: "order_exchange_item.details.after",
377
+ apiEndpoint: "/admin/order-exchange-items/{id}",
378
+ responseKey: "order_exchange_item"
379
+ },
380
+ order_items: {
381
+ widgetZone: "order_item.details.after",
382
+ apiEndpoint: "/admin/order-items/{id}",
383
+ responseKey: "order_item"
384
+ },
385
+ order_line_items: {
386
+ widgetZone: "order_line_item.details.after",
387
+ apiEndpoint: "/admin/order-line-items/{id}",
388
+ responseKey: "order_line_item"
389
+ },
390
+ order_shipping_methods: {
391
+ widgetZone: "order_shipping_method.details.after",
392
+ apiEndpoint: "/admin/order-shipping-methods/{id}",
393
+ responseKey: "order_shipping_method"
394
+ },
395
+ payments: {
396
+ widgetZone: "payment.details.after",
397
+ apiEndpoint: "/admin/payments/{id}",
398
+ responseKey: "payment"
399
+ },
400
+ payment_collections: {
401
+ widgetZone: "payment_collection.details.after",
402
+ apiEndpoint: "/admin/payment-collections/{id}",
403
+ responseKey: "payment_collection"
404
+ },
405
+ payment_sessions: {
406
+ widgetZone: "payment_session.details.after",
407
+ apiEndpoint: "/admin/payment-sessions/{id}",
408
+ responseKey: "payment_session"
409
+ },
410
+ product_options: {
411
+ widgetZone: "product_option.details.after",
412
+ apiEndpoint: "/admin/product-options/{id}",
413
+ responseKey: "product_option"
414
+ },
415
+ product_option_values: {
416
+ widgetZone: "product_option_value.details.after",
417
+ apiEndpoint: "/admin/product-option-values/{id}",
418
+ responseKey: "product_option_value"
419
+ },
420
+ product_tags: {
421
+ widgetZone: "product_tag.details.after",
422
+ apiEndpoint: "/admin/product-tags/{id}",
423
+ responseKey: "product_tag"
424
+ },
425
+ product_types: {
426
+ widgetZone: "product_type.details.after",
427
+ apiEndpoint: "/admin/product-types/{id}",
428
+ responseKey: "product_type"
429
+ },
430
+ refunds: {
431
+ widgetZone: "refund.details.after",
432
+ apiEndpoint: "/admin/refunds/{id}",
433
+ responseKey: "refund"
434
+ },
435
+ refund_reasons: {
436
+ widgetZone: "refund_reason.details.after",
437
+ apiEndpoint: "/admin/refund-reasons/{id}",
438
+ responseKey: "refund_reason"
439
+ },
440
+ region_countries: {
441
+ widgetZone: "region_country.details.after",
442
+ apiEndpoint: "/admin/region-countries/{id}",
443
+ responseKey: "region_country"
444
+ },
445
+ reservation_items: {
446
+ widgetZone: "reservation_item.details.after",
447
+ apiEndpoint: "/admin/reservation-items/{id}",
448
+ responseKey: "reservation_item"
449
+ },
450
+ returns: {
451
+ widgetZone: "return.details.after",
452
+ apiEndpoint: "/admin/returns/{id}",
453
+ responseKey: "return"
454
+ },
455
+ return_items: {
456
+ widgetZone: "return_item.details.after",
457
+ apiEndpoint: "/admin/return-items/{id}",
458
+ responseKey: "return_item"
459
+ },
460
+ service_zones: {
461
+ widgetZone: "service_zone.details.after",
462
+ apiEndpoint: "/admin/service-zones/{id}",
463
+ responseKey: "service_zone"
464
+ },
465
+ shipping_options: {
466
+ widgetZone: "shipping_option.details.after",
467
+ apiEndpoint: "/admin/shipping-options/{id}",
468
+ responseKey: "shipping_option"
469
+ },
470
+ stock_locations: {
471
+ widgetZone: "stock_location.details.after",
472
+ apiEndpoint: "/admin/stock-locations/{id}",
473
+ responseKey: "stock_location"
474
+ },
475
+ stock_location_addresses: {
476
+ widgetZone: "stock_location_address.details.after",
477
+ apiEndpoint: "/admin/stock-location-addresses/{id}",
478
+ responseKey: "stock_location_address"
479
+ },
480
+ tax_rates: {
481
+ widgetZone: "tax_rate.details.after",
482
+ apiEndpoint: "/admin/tax-rates/{id}",
483
+ responseKey: "tax_rate"
484
+ },
485
+ tax_rate_rules: {
486
+ widgetZone: "tax_rate_rule.details.after",
487
+ apiEndpoint: "/admin/tax-rate-rules/{id}",
488
+ responseKey: "tax_rate_rule"
489
+ },
490
+ tax_regions: {
491
+ widgetZone: "tax_region.details.after",
492
+ apiEndpoint: "/admin/tax-regions/{id}",
493
+ responseKey: "tax_region"
494
+ },
495
+ users: {
496
+ widgetZone: "user.details.after",
497
+ apiEndpoint: "/admin/users/{id}",
498
+ responseKey: "user"
499
+ }
500
+ };
501
+ let customMappings = {};
502
+ function getEntityMapping(entityType) {
503
+ return customMappings[entityType] || DEFAULT_ENTITY_MAPPINGS[entityType];
504
+ }
505
+ function getApiEndpoint(entityType) {
506
+ const mapping = getEntityMapping(entityType);
507
+ return mapping == null ? void 0 : mapping.apiEndpoint;
508
+ }
509
+ function getResponseKey(entityType) {
510
+ const mapping = getEntityMapping(entityType);
511
+ return mapping == null ? void 0 : mapping.responseKey;
512
+ }
513
+ function resolveApiEndpoint(entityType, entityId) {
514
+ const endpoint = getApiEndpoint(entityType);
515
+ if (!endpoint) return void 0;
516
+ return endpoint.replace("{id}", entityId);
517
+ }
518
+ const CONFIG_DOCS_URL = "https://docs.medusajs.com/admin/extension-points/widgets";
519
+ const MetadataTableWidget = ({
520
+ data,
521
+ entityType,
522
+ queryKey = []
523
+ }) => {
524
+ const { data: descriptors = [], isPending, isError } = useMetadataConfig({
525
+ entity: entityType
526
+ });
527
+ const entityId = (data == null ? void 0 : data.id) ?? void 0;
528
+ const [baselineMetadata, setBaselineMetadata] = react.useState(
529
+ (data == null ? void 0 : data.metadata) ?? {}
530
+ );
531
+ const queryClient = reactQuery.useQueryClient();
532
+ const previousEntityIdRef = react.useRef(entityId);
533
+ const isInitializedRef = react.useRef(false);
534
+ const dataRef = react.useRef(data);
535
+ const descriptorsRef = react.useRef(descriptors);
536
+ react.useEffect(() => {
537
+ dataRef.current = data;
538
+ descriptorsRef.current = descriptors;
539
+ }, [data, descriptors]);
540
+ react.useEffect(() => {
541
+ var _a;
542
+ if (previousEntityIdRef.current === entityId && isInitializedRef.current) {
543
+ return;
544
+ }
545
+ const entityIdChanged = previousEntityIdRef.current !== entityId;
546
+ if (entityIdChanged || !isInitializedRef.current) {
547
+ const currentMetadata = (data == null ? void 0 : data.metadata) ?? ((_a = dataRef.current) == null ? void 0 : _a.metadata) ?? {};
548
+ const currentDescriptors = descriptorsRef.current.length > 0 ? descriptorsRef.current : descriptors;
549
+ if (currentDescriptors.length === 0) {
550
+ return;
551
+ }
552
+ previousEntityIdRef.current = entityId;
553
+ setBaselineMetadata(currentMetadata);
554
+ const newInitialState = buildInitialFormState(
555
+ currentDescriptors,
556
+ currentMetadata
557
+ );
558
+ setValues(newInitialState);
559
+ isInitializedRef.current = true;
560
+ }
561
+ }, [entityId]);
562
+ const metadataStringRef = react.useRef("");
563
+ react.useEffect(() => {
564
+ const hasEntityData = !!data;
565
+ const descriptorsLoaded = descriptors.length > 0;
566
+ const sameEntity = previousEntityIdRef.current === entityId;
567
+ const notInitialized = !isInitializedRef.current;
568
+ const currentMetadata = (data == null ? void 0 : data.metadata) ?? {};
569
+ const currentMetadataString = JSON.stringify(currentMetadata);
570
+ const metadataChanged = currentMetadataString !== metadataStringRef.current;
571
+ if (hasEntityData && descriptorsLoaded && sameEntity && (notInitialized || metadataChanged)) {
572
+ const newInitialState = buildInitialFormState(descriptors, currentMetadata);
573
+ setBaselineMetadata(currentMetadata);
574
+ setValues(newInitialState);
575
+ metadataStringRef.current = currentMetadataString;
576
+ isInitializedRef.current = true;
577
+ }
578
+ }, [data, descriptors.length, entityId]);
579
+ const initialState = react.useMemo(
580
+ () => buildInitialFormState(descriptors, baselineMetadata),
581
+ [descriptors, baselineMetadata]
582
+ );
583
+ const [values, setValues] = react.useState({});
584
+ const [isSaving, setIsSaving] = react.useState(false);
585
+ const errors = react.useMemo(() => {
586
+ return descriptors.reduce((acc, descriptor) => {
587
+ const error = validateValueForDescriptor(descriptor, values[descriptor.key]);
588
+ if (error) {
589
+ acc[descriptor.key] = error;
590
+ }
591
+ return acc;
592
+ }, {});
593
+ }, [descriptors, values]);
594
+ const hasErrors = Object.keys(errors).length > 0;
595
+ const isDirty = react.useMemo(() => {
596
+ return hasMetadataChanges({
597
+ descriptors,
598
+ values,
599
+ originalMetadata: baselineMetadata
600
+ });
601
+ }, [descriptors, values, baselineMetadata]);
602
+ const handleStringChange = (key, nextValue) => {
603
+ setValues((prev) => ({
604
+ ...prev,
605
+ [key]: nextValue
606
+ }));
607
+ };
608
+ const handleBooleanChange = (key, nextValue) => {
609
+ setValues((prev) => ({
610
+ ...prev,
611
+ [key]: nextValue
612
+ }));
613
+ };
614
+ const handleReset = () => {
615
+ setValues(initialState);
616
+ };
617
+ const handleSubmit = async () => {
618
+ if (!(data == null ? void 0 : data.id) || !descriptors.length) {
619
+ return;
620
+ }
621
+ setIsSaving(true);
622
+ try {
623
+ const metadataPayload = buildMetadataPayload({
624
+ descriptors,
625
+ values,
626
+ originalMetadata: baselineMetadata
627
+ });
628
+ const apiEndpoint = resolveApiEndpoint(entityType, data.id);
629
+ if (!apiEndpoint) {
630
+ throw new Error(`No API endpoint configured for entity type: ${entityType}`);
631
+ }
632
+ const response = await fetch(apiEndpoint, {
633
+ method: "POST",
634
+ credentials: "include",
635
+ headers: {
636
+ "Content-Type": "application/json"
637
+ },
638
+ body: JSON.stringify({
639
+ metadata: metadataPayload
640
+ })
641
+ });
642
+ if (!response.ok) {
643
+ const payload = await response.json().catch(() => null);
644
+ throw new Error((payload == null ? void 0 : payload.message) ?? "Unable to save metadata");
645
+ }
646
+ const responseKey = getResponseKey(entityType) || entityType;
647
+ const updated = await response.json();
648
+ const entity = updated[responseKey] || updated;
649
+ const nextMetadata = entity == null ? void 0 : entity.metadata;
650
+ setBaselineMetadata(nextMetadata);
651
+ setValues(buildInitialFormState(descriptors, nextMetadata));
652
+ ui.toast.success("Metadata saved");
653
+ if (queryKey.length > 0) {
654
+ await queryClient.invalidateQueries({
655
+ queryKey
656
+ });
657
+ if (data.id) {
658
+ queryClient.refetchQueries({
659
+ queryKey: [...queryKey, data.id]
660
+ }).catch(() => {
661
+ });
662
+ }
663
+ }
664
+ } catch (error) {
665
+ ui.toast.error(error instanceof Error ? error.message : "Save failed");
666
+ } finally {
667
+ setIsSaving(false);
668
+ }
669
+ };
670
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "flex flex-col gap-y-4", children: [
671
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-y-1", children: [
672
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-3", children: [
673
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Metadata" }),
674
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", rounded: "full", children: descriptors.length })
675
+ ] }),
676
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Structured metadata mapped to the keys you configured in the plugin options." })
677
+ ] }),
678
+ isPending || !isInitializedRef.current || Object.keys(values).length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-[160px] w-full" }) : isError ? /* @__PURE__ */ jsxRuntime.jsxs(ui.InlineTip, { variant: "error", label: "Configuration unavailable", children: [
679
+ "Unable to load metadata configuration for this plugin. Confirm that the plugin is registered with options in ",
680
+ /* @__PURE__ */ jsxRuntime.jsx("code", { children: "medusa-config.ts" }),
681
+ "."
682
+ ] }) : !descriptors.length ? /* @__PURE__ */ jsxRuntime.jsxs(ui.InlineTip, { variant: "info", label: "No configured metadata keys", children: [
683
+ "Provide metadata descriptors for ",
684
+ /* @__PURE__ */ jsxRuntime.jsx("code", { children: entityType }),
685
+ " in the plugin options to control which keys show up here.",
686
+ " ",
687
+ /* @__PURE__ */ jsxRuntime.jsx(
688
+ "a",
689
+ {
690
+ className: "text-ui-fg-interactive underline",
691
+ href: CONFIG_DOCS_URL,
692
+ target: "_blank",
693
+ rel: "noreferrer",
694
+ children: "Learn how to configure it."
695
+ }
696
+ )
697
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
698
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-lg border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
699
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
700
+ /* @__PURE__ */ jsxRuntime.jsx(
701
+ "th",
702
+ {
703
+ scope: "col",
704
+ className: "txt-compact-xsmall-plus text-left uppercase tracking-wide text-ui-fg-muted px-4 py-3",
705
+ children: "Label"
706
+ }
707
+ ),
708
+ /* @__PURE__ */ jsxRuntime.jsx(
709
+ "th",
710
+ {
711
+ scope: "col",
712
+ className: "txt-compact-xsmall-plus text-left uppercase tracking-wide text-ui-fg-muted px-4 py-3",
713
+ children: "Value"
714
+ }
715
+ )
716
+ ] }) }),
717
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle bg-ui-bg-base", children: descriptors.map((descriptor) => {
718
+ const value = values[descriptor.key];
719
+ const error = errors[descriptor.key];
720
+ return /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
721
+ /* @__PURE__ */ jsxRuntime.jsx(
722
+ "th",
723
+ {
724
+ scope: "row",
725
+ className: "txt-compact-medium text-ui-fg-base align-top px-4 py-4",
726
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [
727
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: descriptor.label ?? descriptor.key }),
728
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "txt-compact-xsmall-plus text-ui-fg-muted uppercase tracking-wide", children: descriptor.type })
729
+ ] })
730
+ }
731
+ ),
732
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "align-top px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [
733
+ /* @__PURE__ */ jsxRuntime.jsx(
734
+ ValueField,
735
+ {
736
+ descriptor,
737
+ value,
738
+ onStringChange: handleStringChange,
739
+ onBooleanChange: handleBooleanChange
740
+ }
741
+ ),
742
+ error && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "txt-compact-small text-ui-fg-error", children: error })
743
+ ] }) })
744
+ ] }, descriptor.key);
745
+ }) })
746
+ ] }) }),
747
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3 border-t border-ui-border-subtle pt-3 md:flex-row md:items-center md:justify-between", children: [
748
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Changes are stored on the entity metadata object. Clearing a field removes the corresponding key on save." }),
749
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
750
+ /* @__PURE__ */ jsxRuntime.jsx(
751
+ ui.Button,
752
+ {
753
+ variant: "secondary",
754
+ size: "small",
755
+ disabled: !isDirty || isSaving,
756
+ onClick: handleReset,
757
+ children: "Reset"
758
+ }
759
+ ),
760
+ /* @__PURE__ */ jsxRuntime.jsx(
761
+ ui.Button,
762
+ {
763
+ size: "small",
764
+ onClick: handleSubmit,
765
+ disabled: !isDirty || hasErrors || isSaving,
766
+ isLoading: isSaving,
767
+ children: "Save metadata"
768
+ }
769
+ )
770
+ ] })
771
+ ] })
772
+ ] })
773
+ ] });
774
+ };
775
+ const ValueField = ({
776
+ descriptor,
777
+ value,
778
+ onStringChange,
779
+ onBooleanChange
780
+ }) => {
781
+ const fileInputRef = react.useRef(null);
782
+ const [isUploading, setIsUploading] = react.useState(false);
783
+ const handleFileUpload = async (event) => {
784
+ var _a;
785
+ const file = (_a = event.target.files) == null ? void 0 : _a[0];
786
+ if (!file) {
787
+ return;
788
+ }
789
+ setIsUploading(true);
790
+ try {
791
+ const formData = new FormData();
792
+ formData.append("files", file);
793
+ const response = await fetch("/admin/uploads", {
794
+ method: "POST",
795
+ credentials: "include",
796
+ body: formData
797
+ });
798
+ if (!response.ok) {
799
+ const payload = await response.json().catch(() => null);
800
+ throw new Error((payload == null ? void 0 : payload.message) ?? "File upload failed");
801
+ }
802
+ const result = await response.json();
803
+ if (result.files && result.files.length > 0) {
804
+ const uploadedFile = result.files[0];
805
+ const fileUrl = uploadedFile.url || uploadedFile.key;
806
+ if (fileUrl) {
807
+ onStringChange(descriptor.key, fileUrl);
808
+ ui.toast.success("File uploaded successfully");
809
+ } else {
810
+ throw new Error("File upload succeeded but no URL returned");
811
+ }
812
+ } else {
813
+ throw new Error("File upload failed - no files returned");
814
+ }
815
+ } catch (error) {
816
+ ui.toast.error(
817
+ error instanceof Error ? error.message : "Failed to upload file"
818
+ );
819
+ } finally {
820
+ setIsUploading(false);
821
+ if (fileInputRef.current) {
822
+ fileInputRef.current.value = "";
823
+ }
824
+ }
825
+ };
826
+ if (descriptor.type === "bool") {
827
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
828
+ /* @__PURE__ */ jsxRuntime.jsx(
829
+ ui.Switch,
830
+ {
831
+ checked: Boolean(value),
832
+ onCheckedChange: (checked) => onBooleanChange(descriptor.key, Boolean(checked)),
833
+ "aria-label": `Toggle ${descriptor.label ?? descriptor.key}`
834
+ }
835
+ ),
836
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "txt-compact-small text-ui-fg-muted", children: Boolean(value) ? "True" : "False" })
837
+ ] });
838
+ }
839
+ if (descriptor.type === "text") {
840
+ return /* @__PURE__ */ jsxRuntime.jsx(
841
+ ui.Textarea,
842
+ {
843
+ value: value ?? "",
844
+ placeholder: "Enter text",
845
+ rows: 3,
846
+ onChange: (event) => onStringChange(descriptor.key, event.target.value)
847
+ }
848
+ );
849
+ }
850
+ if (descriptor.type === "number") {
851
+ return /* @__PURE__ */ jsxRuntime.jsx(
852
+ ui.Input,
853
+ {
854
+ type: "text",
855
+ inputMode: "decimal",
856
+ placeholder: "0.00",
857
+ value: value ?? "",
858
+ onChange: (event) => onStringChange(descriptor.key, event.target.value)
859
+ }
860
+ );
861
+ }
862
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [
863
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
864
+ /* @__PURE__ */ jsxRuntime.jsx(
865
+ ui.Input,
866
+ {
867
+ type: "url",
868
+ placeholder: "https://example.com/file",
869
+ value: value ?? "",
870
+ onChange: (event) => onStringChange(descriptor.key, event.target.value),
871
+ className: "flex-1"
872
+ }
873
+ ),
874
+ /* @__PURE__ */ jsxRuntime.jsx(
875
+ "input",
876
+ {
877
+ ref: fileInputRef,
878
+ type: "file",
879
+ className: "hidden",
880
+ onChange: handleFileUpload,
881
+ disabled: isUploading,
882
+ "aria-label": `Upload file for ${descriptor.label ?? descriptor.key}`
883
+ }
884
+ ),
885
+ /* @__PURE__ */ jsxRuntime.jsx(
886
+ ui.Button,
887
+ {
888
+ type: "button",
889
+ variant: "secondary",
890
+ size: "small",
891
+ onClick: () => {
892
+ var _a;
893
+ return (_a = fileInputRef.current) == null ? void 0 : _a.click();
894
+ },
895
+ disabled: isUploading,
896
+ isLoading: isUploading,
897
+ children: isUploading ? "Uploading..." : "Upload"
898
+ }
899
+ )
900
+ ] }),
901
+ typeof value === "string" && value && /* @__PURE__ */ jsxRuntime.jsx(
902
+ "a",
903
+ {
904
+ className: "txt-compact-small-plus text-ui-fg-interactive underline",
905
+ href: value,
906
+ target: "_blank",
907
+ rel: "noreferrer",
908
+ children: "View file"
909
+ }
910
+ )
911
+ ] });
912
+ };
913
+ const ZONE_PATTERNS = [
914
+ // Product zones
915
+ { pattern: /^product\.details\./, entityType: "products" },
916
+ { pattern: /^product\./, entityType: "products" },
917
+ // Order zones
918
+ { pattern: /^order\.details\./, entityType: "orders" },
919
+ { pattern: /^order\./, entityType: "orders" },
920
+ // Category zones
921
+ { pattern: /^product_category\.details\./, entityType: "categories" },
922
+ { pattern: /^product_category\./, entityType: "categories" },
923
+ { pattern: /^category\.details\./, entityType: "categories" },
924
+ { pattern: /^category\./, entityType: "categories" },
925
+ // Collection zones
926
+ { pattern: /^product_collection\.details\./, entityType: "collections" },
927
+ { pattern: /^product_collection\./, entityType: "collections" },
928
+ { pattern: /^collection\.details\./, entityType: "collections" },
929
+ { pattern: /^collection\./, entityType: "collections" },
930
+ // Customer zones
931
+ { pattern: /^customer\.details\./, entityType: "customers" },
932
+ { pattern: /^customer\./, entityType: "customers" },
933
+ // Region zones
934
+ { pattern: /^region\.details\./, entityType: "regions" },
935
+ { pattern: /^region\./, entityType: "regions" },
936
+ // Sales Channel zones
937
+ { pattern: /^sales_channel\.details\./, entityType: "sales_channels" },
938
+ { pattern: /^sales_channel\./, entityType: "sales_channels" },
939
+ // Store zones
940
+ { pattern: /^store\.details\./, entityType: "stores" },
941
+ { pattern: /^store\./, entityType: "stores" },
942
+ // Promotion zones
943
+ { pattern: /^promotion\.details\./, entityType: "promotions" },
944
+ { pattern: /^promotion\./, entityType: "promotions" },
945
+ // Campaign zones
946
+ { pattern: /^campaign\.details\./, entityType: "campaigns" },
947
+ { pattern: /^campaign\./, entityType: "campaigns" },
948
+ // Price List zones
949
+ { pattern: /^price_list\.details\./, entityType: "price_lists" },
950
+ { pattern: /^price_list\./, entityType: "price_lists" },
951
+ // Shipping Profile zones
952
+ { pattern: /^shipping_profile\.details\./, entityType: "shipping_profiles" },
953
+ { pattern: /^shipping_profile\./, entityType: "shipping_profiles" },
954
+ // Return Reason zones
955
+ { pattern: /^return_reason\.details\./, entityType: "return_reasons" },
956
+ { pattern: /^return_reason\./, entityType: "return_reasons" },
957
+ // Inventory Item zones
958
+ { pattern: /^inventory_item\.details\./, entityType: "inventory_items" },
959
+ { pattern: /^inventory_item\./, entityType: "inventory_items" },
960
+ // Product Variant zones
961
+ { pattern: /^product_variant\.details\./, entityType: "product_variants" },
962
+ { pattern: /^product_variant\./, entityType: "product_variants" },
963
+ // Account Holder zones
964
+ { pattern: /^account_holder\.details\./, entityType: "account_holders" },
965
+ { pattern: /^account_holder\./, entityType: "account_holders" },
966
+ // Capture zones
967
+ { pattern: /^capture\.details\./, entityType: "captures" },
968
+ { pattern: /^capture\./, entityType: "captures" },
969
+ // Cart zones
970
+ { pattern: /^cart\.details\./, entityType: "carts" },
971
+ { pattern: /^cart\./, entityType: "carts" },
972
+ // Cart Address zones
973
+ { pattern: /^cart_address\.details\./, entityType: "cart_addresses" },
974
+ { pattern: /^cart_address\./, entityType: "cart_addresses" },
975
+ // Cart Line Item zones
976
+ { pattern: /^cart_line_item\.details\./, entityType: "cart_line_items" },
977
+ { pattern: /^cart_line_item\./, entityType: "cart_line_items" },
978
+ // Cart Line Item Adjustment zones
979
+ { pattern: /^cart_line_item_adjustment\.details\./, entityType: "cart_line_item_adjustments" },
980
+ { pattern: /^cart_line_item_adjustment\./, entityType: "cart_line_item_adjustments" },
981
+ // Cart Line Item Tax Line zones
982
+ { pattern: /^cart_line_item_tax_line\.details\./, entityType: "cart_line_item_tax_lines" },
983
+ { pattern: /^cart_line_item_tax_line\./, entityType: "cart_line_item_tax_lines" },
984
+ // Cart Shipping Method zones
985
+ { pattern: /^cart_shipping_method\.details\./, entityType: "cart_shipping_methods" },
986
+ { pattern: /^cart_shipping_method\./, entityType: "cart_shipping_methods" },
987
+ // Cart Shipping Method Adjustment zones
988
+ { pattern: /^cart_shipping_method_adjustment\.details\./, entityType: "cart_shipping_method_adjustments" },
989
+ { pattern: /^cart_shipping_method_adjustment\./, entityType: "cart_shipping_method_adjustments" },
990
+ // Cart Shipping Method Tax Line zones
991
+ { pattern: /^cart_shipping_method_tax_line\.details\./, entityType: "cart_shipping_method_tax_lines" },
992
+ { pattern: /^cart_shipping_method_tax_line\./, entityType: "cart_shipping_method_tax_lines" },
993
+ // Contact Email Subscription zones
994
+ { pattern: /^contact_email_subscription\.details\./, entityType: "contact_email_subscriptions" },
995
+ { pattern: /^contact_email_subscription\./, entityType: "contact_email_subscriptions" },
996
+ // Contact Request zones
997
+ { pattern: /^contact_request\.details\./, entityType: "contact_requests" },
998
+ { pattern: /^contact_request\./, entityType: "contact_requests" },
999
+ // Credit Line zones
1000
+ { pattern: /^credit_line\.details\./, entityType: "credit_lines" },
1001
+ { pattern: /^credit_line\./, entityType: "credit_lines" },
1002
+ // Customer Address zones
1003
+ { pattern: /^customer_address\.details\./, entityType: "customer_addresses" },
1004
+ { pattern: /^customer_address\./, entityType: "customer_addresses" },
1005
+ // Customer Group zones
1006
+ { pattern: /^customer_group\.details\./, entityType: "customer_groups" },
1007
+ { pattern: /^customer_group\./, entityType: "customer_groups" },
1008
+ // Customer Group Customer zones
1009
+ { pattern: /^customer_group_customer\.details\./, entityType: "customer_group_customers" },
1010
+ { pattern: /^customer_group_customer\./, entityType: "customer_group_customers" },
1011
+ // Fulfillment zones
1012
+ { pattern: /^fulfillment\.details\./, entityType: "fulfillments" },
1013
+ { pattern: /^fulfillment\./, entityType: "fulfillments" },
1014
+ // Fulfillment Address zones
1015
+ { pattern: /^fulfillment_address\.details\./, entityType: "fulfillment_addresses" },
1016
+ { pattern: /^fulfillment_address\./, entityType: "fulfillment_addresses" },
1017
+ // Fulfillment Set zones
1018
+ { pattern: /^fulfillment_set\.details\./, entityType: "fulfillment_sets" },
1019
+ { pattern: /^fulfillment_set\./, entityType: "fulfillment_sets" },
1020
+ // Geo Zone zones
1021
+ { pattern: /^geo_zone\.details\./, entityType: "geo_zones" },
1022
+ { pattern: /^geo_zone\./, entityType: "geo_zones" },
1023
+ // Image zones
1024
+ { pattern: /^image\.details\./, entityType: "images" },
1025
+ { pattern: /^image\./, entityType: "images" },
1026
+ // Inventory Level zones
1027
+ { pattern: /^inventory_level\.details\./, entityType: "inventory_levels" },
1028
+ { pattern: /^inventory_level\./, entityType: "inventory_levels" },
1029
+ // Invite zones
1030
+ { pattern: /^invite\.details\./, entityType: "invites" },
1031
+ { pattern: /^invite\./, entityType: "invites" },
1032
+ // Order Address zones
1033
+ { pattern: /^order_address\.details\./, entityType: "order_addresses" },
1034
+ { pattern: /^order_address\./, entityType: "order_addresses" },
1035
+ // Order Change zones
1036
+ { pattern: /^order_change\.details\./, entityType: "order_changes" },
1037
+ { pattern: /^order_change\./, entityType: "order_changes" },
1038
+ // Order Claim zones
1039
+ { pattern: /^order_claim\.details\./, entityType: "order_claims" },
1040
+ { pattern: /^order_claim\./, entityType: "order_claims" },
1041
+ // Order Claim Item zones
1042
+ { pattern: /^order_claim_item\.details\./, entityType: "order_claim_items" },
1043
+ { pattern: /^order_claim_item\./, entityType: "order_claim_items" },
1044
+ // Order Claim Item Image zones
1045
+ { pattern: /^order_claim_item_image\.details\./, entityType: "order_claim_item_images" },
1046
+ { pattern: /^order_claim_item_image\./, entityType: "order_claim_item_images" },
1047
+ // Order Credit Line zones
1048
+ { pattern: /^order_credit_line\.details\./, entityType: "order_credit_lines" },
1049
+ { pattern: /^order_credit_line\./, entityType: "order_credit_lines" },
1050
+ // Order Exchange zones
1051
+ { pattern: /^order_exchange\.details\./, entityType: "order_exchanges" },
1052
+ { pattern: /^order_exchange\./, entityType: "order_exchanges" },
1053
+ // Order Exchange Item zones
1054
+ { pattern: /^order_exchange_item\.details\./, entityType: "order_exchange_items" },
1055
+ { pattern: /^order_exchange_item\./, entityType: "order_exchange_items" },
1056
+ // Order Item zones
1057
+ { pattern: /^order_item\.details\./, entityType: "order_items" },
1058
+ { pattern: /^order_item\./, entityType: "order_items" },
1059
+ // Order Line Item zones
1060
+ { pattern: /^order_line_item\.details\./, entityType: "order_line_items" },
1061
+ { pattern: /^order_line_item\./, entityType: "order_line_items" },
1062
+ // Order Shipping Method zones
1063
+ { pattern: /^order_shipping_method\.details\./, entityType: "order_shipping_methods" },
1064
+ { pattern: /^order_shipping_method\./, entityType: "order_shipping_methods" },
1065
+ // Payment zones
1066
+ { pattern: /^payment\.details\./, entityType: "payments" },
1067
+ { pattern: /^payment\./, entityType: "payments" },
1068
+ // Payment Collection zones
1069
+ { pattern: /^payment_collection\.details\./, entityType: "payment_collections" },
1070
+ { pattern: /^payment_collection\./, entityType: "payment_collections" },
1071
+ // Payment Session zones
1072
+ { pattern: /^payment_session\.details\./, entityType: "payment_sessions" },
1073
+ { pattern: /^payment_session\./, entityType: "payment_sessions" },
1074
+ // Product Option zones
1075
+ { pattern: /^product_option\.details\./, entityType: "product_options" },
1076
+ { pattern: /^product_option\./, entityType: "product_options" },
1077
+ // Product Option Value zones
1078
+ { pattern: /^product_option_value\.details\./, entityType: "product_option_values" },
1079
+ { pattern: /^product_option_value\./, entityType: "product_option_values" },
1080
+ // Product Tag zones
1081
+ { pattern: /^product_tag\.details\./, entityType: "product_tags" },
1082
+ { pattern: /^product_tag\./, entityType: "product_tags" },
1083
+ // Product Type zones
1084
+ { pattern: /^product_type\.details\./, entityType: "product_types" },
1085
+ { pattern: /^product_type\./, entityType: "product_types" },
1086
+ // Refund zones
1087
+ { pattern: /^refund\.details\./, entityType: "refunds" },
1088
+ { pattern: /^refund\./, entityType: "refunds" },
1089
+ // Refund Reason zones
1090
+ { pattern: /^refund_reason\.details\./, entityType: "refund_reasons" },
1091
+ { pattern: /^refund_reason\./, entityType: "refund_reasons" },
1092
+ // Region Country zones
1093
+ { pattern: /^region_country\.details\./, entityType: "region_countries" },
1094
+ { pattern: /^region_country\./, entityType: "region_countries" },
1095
+ // Reservation Item zones
1096
+ { pattern: /^reservation_item\.details\./, entityType: "reservation_items" },
1097
+ { pattern: /^reservation_item\./, entityType: "reservation_items" },
1098
+ // Return zones
1099
+ { pattern: /^return\.details\./, entityType: "returns" },
1100
+ { pattern: /^return\./, entityType: "returns" },
1101
+ // Return Item zones
1102
+ { pattern: /^return_item\.details\./, entityType: "return_items" },
1103
+ { pattern: /^return_item\./, entityType: "return_items" },
1104
+ // Service Zone zones
1105
+ { pattern: /^service_zone\.details\./, entityType: "service_zones" },
1106
+ { pattern: /^service_zone\./, entityType: "service_zones" },
1107
+ // Shipping Option zones
1108
+ { pattern: /^shipping_option\.details\./, entityType: "shipping_options" },
1109
+ { pattern: /^shipping_option\./, entityType: "shipping_options" },
1110
+ // Stock Location zones
1111
+ { pattern: /^stock_location\.details\./, entityType: "stock_locations" },
1112
+ { pattern: /^stock_location\./, entityType: "stock_locations" },
1113
+ // Stock Location Address zones
1114
+ { pattern: /^stock_location_address\.details\./, entityType: "stock_location_addresses" },
1115
+ { pattern: /^stock_location_address\./, entityType: "stock_location_addresses" },
1116
+ // Tax Rate zones
1117
+ { pattern: /^tax_rate\.details\./, entityType: "tax_rates" },
1118
+ { pattern: /^tax_rate\./, entityType: "tax_rates" },
1119
+ // Tax Rate Rule zones
1120
+ { pattern: /^tax_rate_rule\.details\./, entityType: "tax_rate_rules" },
1121
+ { pattern: /^tax_rate_rule\./, entityType: "tax_rate_rules" },
1122
+ // Tax Region zones
1123
+ { pattern: /^tax_region\.details\./, entityType: "tax_regions" },
1124
+ { pattern: /^tax_region\./, entityType: "tax_regions" },
1125
+ // User zones
1126
+ { pattern: /^user\.details\./, entityType: "users" },
1127
+ { pattern: /^user\./, entityType: "users" },
1128
+ // Generic pattern: {entity}.details.{position}
1129
+ { pattern: /^(\w+)\.details\./, entityType: "" }
1130
+ // Will extract from match
1131
+ ];
1132
+ let customZoneMappings = {};
1133
+ function resolveEntityTypeFromZone(zone) {
1134
+ if (customZoneMappings[zone]) {
1135
+ return customZoneMappings[zone];
1136
+ }
1137
+ const entityTypes = [
1138
+ "products",
1139
+ "orders",
1140
+ "categories",
1141
+ "collections",
1142
+ "customers",
1143
+ "regions",
1144
+ "sales_channels",
1145
+ "stores",
1146
+ "promotions",
1147
+ "campaigns",
1148
+ "price_lists",
1149
+ "shipping_profiles",
1150
+ "return_reasons",
1151
+ "inventory_items",
1152
+ "product_variants",
1153
+ "account_holders",
1154
+ "captures",
1155
+ "carts",
1156
+ "cart_addresses",
1157
+ "cart_line_items",
1158
+ "cart_line_item_adjustments",
1159
+ "cart_line_item_tax_lines",
1160
+ "cart_shipping_methods",
1161
+ "cart_shipping_method_adjustments",
1162
+ "cart_shipping_method_tax_lines",
1163
+ "contact_email_subscriptions",
1164
+ "contact_requests",
1165
+ "credit_lines",
1166
+ "customer_addresses",
1167
+ "customer_groups",
1168
+ "customer_group_customers",
1169
+ "fulfillments",
1170
+ "fulfillment_addresses",
1171
+ "fulfillment_sets",
1172
+ "geo_zones",
1173
+ "images",
1174
+ "inventory_levels",
1175
+ "invites",
1176
+ "order_addresses",
1177
+ "order_changes",
1178
+ "order_claims",
1179
+ "order_claim_items",
1180
+ "order_claim_item_images",
1181
+ "order_credit_lines",
1182
+ "order_exchanges",
1183
+ "order_exchange_items",
1184
+ "order_items",
1185
+ "order_line_items",
1186
+ "order_shipping_methods",
1187
+ "payments",
1188
+ "payment_collections",
1189
+ "payment_sessions",
1190
+ "product_options",
1191
+ "product_option_values",
1192
+ "product_tags",
1193
+ "product_types",
1194
+ "refunds",
1195
+ "refund_reasons",
1196
+ "region_countries",
1197
+ "reservation_items",
1198
+ "returns",
1199
+ "return_items",
1200
+ "service_zones",
1201
+ "shipping_options",
1202
+ "stock_locations",
1203
+ "stock_location_addresses",
1204
+ "tax_rates",
1205
+ "tax_rate_rules",
1206
+ "tax_regions",
1207
+ "users"
1208
+ ];
1209
+ for (const entityType of entityTypes) {
1210
+ const mapping = getEntityMapping(entityType);
1211
+ if ((mapping == null ? void 0 : mapping.widgetZone) === zone) {
1212
+ return entityType;
1213
+ }
1214
+ }
1215
+ for (const { pattern, entityType } of ZONE_PATTERNS) {
1216
+ const match = zone.match(pattern);
1217
+ if (match) {
1218
+ if (entityType === "" && match[1]) {
1219
+ const singular = match[1];
1220
+ return `${singular}s`;
1221
+ }
1222
+ return entityType;
1223
+ }
1224
+ }
1225
+ const parts = zone.split(".");
1226
+ if (parts.length > 0) {
1227
+ const firstPart = parts[0];
1228
+ if (firstPart && !firstPart.endsWith("s")) {
1229
+ return `${firstPart}s`;
1230
+ }
1231
+ return firstPart;
1232
+ }
1233
+ return void 0;
1234
+ }
1235
+ const ENTITY_DETECTION_PATTERNS = [
1236
+ // Products: typically have handle, title, description
1237
+ {
1238
+ patterns: ["handle", "title", "description", "subtitle"],
1239
+ entityType: "products"
1240
+ },
1241
+ // Orders: typically have display_id, status, email
1242
+ {
1243
+ patterns: ["display_id", "status", "email", "currency_code"],
1244
+ entityType: "orders"
1245
+ },
1246
+ // Categories: typically have name, handle, parent_category_id
1247
+ {
1248
+ patterns: ["name", "handle", "parent_category_id", "category_children"],
1249
+ entityType: "categories"
1250
+ },
1251
+ // Collections: typically have title, handle
1252
+ {
1253
+ patterns: ["title", "handle", "products"],
1254
+ entityType: "collections"
1255
+ },
1256
+ // Customers: typically have email, first_name, last_name
1257
+ {
1258
+ patterns: ["email", "first_name", "last_name", "phone"],
1259
+ entityType: "customers"
1260
+ },
1261
+ // Regions: typically have name, currency_code
1262
+ {
1263
+ patterns: ["name", "currency_code", "countries"],
1264
+ entityType: "regions"
1265
+ },
1266
+ // Sales Channels: typically have name, description
1267
+ {
1268
+ patterns: ["name", "description", "is_default"],
1269
+ entityType: "sales_channels"
1270
+ },
1271
+ // Stores: typically have name, default_currency_code
1272
+ {
1273
+ patterns: ["name", "default_currency_code", "default_region_id"],
1274
+ entityType: "stores"
1275
+ },
1276
+ // Promotions: typically have code, type, is_automatic
1277
+ {
1278
+ patterns: ["code", "type", "is_automatic", "status"],
1279
+ entityType: "promotions"
1280
+ },
1281
+ // Campaigns: typically have name, campaign_identifier
1282
+ {
1283
+ patterns: ["name", "campaign_identifier", "budget"],
1284
+ entityType: "campaigns"
1285
+ },
1286
+ // Price Lists: typically have name, type, status
1287
+ {
1288
+ patterns: ["name", "type", "status", "prices"],
1289
+ entityType: "price_lists"
1290
+ },
1291
+ // Shipping Profiles: typically have name, type
1292
+ {
1293
+ patterns: ["name", "type", "shipping_options"],
1294
+ entityType: "shipping_profiles"
1295
+ },
1296
+ // Return Reasons: typically have label, value
1297
+ {
1298
+ patterns: ["label", "value", "description"],
1299
+ entityType: "return_reasons"
1300
+ },
1301
+ // Inventory Items: typically have sku, requires_shipping
1302
+ {
1303
+ patterns: ["sku", "requires_shipping", "hs_code"],
1304
+ entityType: "inventory_items"
1305
+ },
1306
+ // Product Variants: typically have sku, title, inventory_quantity
1307
+ {
1308
+ patterns: ["sku", "title", "inventory_quantity", "manage_inventory"],
1309
+ entityType: "product_variants"
1310
+ },
1311
+ // Carts: typically have email, region_id, currency_code
1312
+ {
1313
+ patterns: ["email", "region_id", "currency_code", "items"],
1314
+ entityType: "carts"
1315
+ },
1316
+ // Payments: typically have amount, currency_code, provider_id
1317
+ {
1318
+ patterns: ["amount", "currency_code", "provider_id", "status"],
1319
+ entityType: "payments"
1320
+ },
1321
+ // Fulfillments: typically have location_id, provider_id, shipped_at
1322
+ {
1323
+ patterns: ["location_id", "provider_id", "shipped_at", "delivered_at"],
1324
+ entityType: "fulfillments"
1325
+ },
1326
+ // Returns: typically have order_id, status, items
1327
+ {
1328
+ patterns: ["order_id", "status", "items", "return_reason"],
1329
+ entityType: "returns"
1330
+ },
1331
+ // Refunds: typically have amount, currency_code, reason
1332
+ {
1333
+ patterns: ["amount", "currency_code", "reason", "payment_id"],
1334
+ entityType: "refunds"
1335
+ },
1336
+ // Customer Groups: typically have name, customers
1337
+ {
1338
+ patterns: ["name", "customers", "created_at"],
1339
+ entityType: "customer_groups"
1340
+ },
1341
+ // Shipping Options: typically have name, price_type, service_zone_id
1342
+ {
1343
+ patterns: ["name", "price_type", "service_zone_id", "shipping_profile_id"],
1344
+ entityType: "shipping_options"
1345
+ },
1346
+ // Tax Rates: typically have rate, code, name
1347
+ {
1348
+ patterns: ["rate", "code", "name", "region_id"],
1349
+ entityType: "tax_rates"
1350
+ },
1351
+ // Users: typically have email, first_name, last_name
1352
+ {
1353
+ patterns: ["email", "first_name", "last_name", "role"],
1354
+ entityType: "users"
1355
+ }
1356
+ ];
1357
+ function detectEntityTypeFromData(data) {
1358
+ if (!data || typeof data !== "object") {
1359
+ return void 0;
1360
+ }
1361
+ const dataKeys = Object.keys(data);
1362
+ const scores = {};
1363
+ for (const { patterns, entityType } of ENTITY_DETECTION_PATTERNS) {
1364
+ const matchCount = patterns.filter((pattern) => dataKeys.includes(pattern)).length;
1365
+ if (matchCount > 0) {
1366
+ scores[entityType] = matchCount;
1367
+ }
1368
+ }
1369
+ const sortedScores = Object.entries(scores).sort((a, b) => b[1] - a[1]);
1370
+ if (sortedScores.length > 0 && sortedScores[0][1] > 0) {
1371
+ return sortedScores[0][0];
1372
+ }
1373
+ return void 0;
1374
+ }
1375
+ function resolveQueryKey(entityType) {
1376
+ const queryKeyMap = {
1377
+ products: ["products"],
1378
+ orders: ["orders"],
1379
+ categories: ["product-categories"],
1380
+ collections: ["collections"],
1381
+ customers: ["customers"],
1382
+ regions: ["regions"],
1383
+ sales_channels: ["sales-channels"],
1384
+ stores: ["stores"],
1385
+ promotions: ["promotions"],
1386
+ campaigns: ["campaigns"],
1387
+ price_lists: ["price-lists"],
1388
+ shipping_profiles: ["shipping-profiles"],
1389
+ return_reasons: ["return-reasons"],
1390
+ inventory_items: ["inventory-items"],
1391
+ product_variants: ["product-variants"],
1392
+ account_holders: ["account-holders"],
1393
+ captures: ["captures"],
1394
+ carts: ["carts"],
1395
+ cart_addresses: ["cart-addresses"],
1396
+ cart_line_items: ["cart-line-items"],
1397
+ cart_line_item_adjustments: ["cart-line-item-adjustments"],
1398
+ cart_line_item_tax_lines: ["cart-line-item-tax-lines"],
1399
+ cart_shipping_methods: ["cart-shipping-methods"],
1400
+ cart_shipping_method_adjustments: ["cart-shipping-method-adjustments"],
1401
+ cart_shipping_method_tax_lines: ["cart-shipping-method-tax-lines"],
1402
+ contact_email_subscriptions: ["contact-email-subscriptions"],
1403
+ contact_requests: ["contact-requests"],
1404
+ credit_lines: ["credit-lines"],
1405
+ customer_addresses: ["customer-addresses"],
1406
+ customer_groups: ["customer-groups"],
1407
+ customer_group_customers: ["customer-group-customers"],
1408
+ fulfillments: ["fulfillments"],
1409
+ fulfillment_addresses: ["fulfillment-addresses"],
1410
+ fulfillment_sets: ["fulfillment-sets"],
1411
+ geo_zones: ["geo-zones"],
1412
+ images: ["images"],
1413
+ inventory_levels: ["inventory-levels"],
1414
+ invites: ["invites"],
1415
+ order_addresses: ["order-addresses"],
1416
+ order_changes: ["order-changes"],
1417
+ order_claims: ["order-claims"],
1418
+ order_claim_items: ["order-claim-items"],
1419
+ order_claim_item_images: ["order-claim-item-images"],
1420
+ order_credit_lines: ["order-credit-lines"],
1421
+ order_exchanges: ["order-exchanges"],
1422
+ order_exchange_items: ["order-exchange-items"],
1423
+ order_items: ["order-items"],
1424
+ order_line_items: ["order-line-items"],
1425
+ order_shipping_methods: ["order-shipping-methods"],
1426
+ payments: ["payments"],
1427
+ payment_collections: ["payment-collections"],
1428
+ payment_sessions: ["payment-sessions"],
1429
+ product_options: ["product-options"],
1430
+ product_option_values: ["product-option-values"],
1431
+ product_tags: ["product-tags"],
1432
+ product_types: ["product-types"],
1433
+ refunds: ["refunds"],
1434
+ refund_reasons: ["refund-reasons"],
1435
+ region_countries: ["region-countries"],
1436
+ reservation_items: ["reservation-items"],
1437
+ returns: ["returns"],
1438
+ return_items: ["return-items"],
1439
+ service_zones: ["service-zones"],
1440
+ shipping_options: ["shipping-options"],
1441
+ stock_locations: ["stock-locations"],
1442
+ stock_location_addresses: ["stock-location-addresses"],
1443
+ tax_rates: ["tax-rates"],
1444
+ tax_rate_rules: ["tax-rate-rules"],
1445
+ tax_regions: ["tax-regions"],
1446
+ users: ["users"]
1447
+ };
1448
+ return queryKeyMap[entityType] || [entityType];
1449
+ }
1450
+ const UniversalMetadataWidget = ({
1451
+ data,
1452
+ zone
1453
+ }) => {
1454
+ const entityType = react.useMemo(() => {
1455
+ if (zone) {
1456
+ const zoneResolved = resolveEntityTypeFromZone(zone);
1457
+ if (zoneResolved) {
1458
+ return zoneResolved;
1459
+ }
1460
+ }
1461
+ if (data) {
1462
+ const dataDetected = detectEntityTypeFromData(data);
1463
+ if (dataDetected) {
1464
+ return dataDetected;
1465
+ }
1466
+ }
1467
+ console.warn(
1468
+ "[UniversalMetadataWidget] Could not detect entity type. Using default: products",
1469
+ { zone, dataKeys: data ? Object.keys(data) : [] }
1470
+ );
1471
+ return "products";
1472
+ }, [zone, data]);
1473
+ const { data: descriptors = [], isPending } = useMetadataConfig({
1474
+ entity: entityType
1475
+ });
1476
+ if (!isPending && descriptors.length === 0) {
1477
+ return null;
1478
+ }
1479
+ const queryKey = react.useMemo(() => {
1480
+ return resolveQueryKey(entityType);
1481
+ }, [entityType]);
1482
+ return /* @__PURE__ */ jsxRuntime.jsx(
1483
+ MetadataTableWidget,
1484
+ {
1485
+ data,
1486
+ entityType,
1487
+ queryKey
1488
+ }
1489
+ );
1490
+ };
1491
+ const Widget$d = ({ data }) => {
1492
+ return /* @__PURE__ */ jsxRuntime.jsx(UniversalMetadataWidget, { data, zone: "campaign.details.after" });
1493
+ };
1494
+ adminSdk.defineWidgetConfig({
1495
+ zone: "campaign.details.after"
1496
+ });
1497
+ const Widget$c = ({ data }) => {
1498
+ return /* @__PURE__ */ jsxRuntime.jsx(UniversalMetadataWidget, { data, zone: "product_category.details.after" });
1499
+ };
1500
+ adminSdk.defineWidgetConfig({
1501
+ zone: "product_category.details.after"
1502
+ });
1503
+ const Widget$b = ({ data }) => {
1504
+ return /* @__PURE__ */ jsxRuntime.jsx(UniversalMetadataWidget, { data, zone: "product_collection.details.after" });
1505
+ };
1506
+ adminSdk.defineWidgetConfig({
1507
+ zone: "product_collection.details.after"
1508
+ });
1509
+ const Widget$a = ({ data }) => {
1510
+ return /* @__PURE__ */ jsxRuntime.jsx(UniversalMetadataWidget, { data, zone: "customer.details.after" });
1511
+ };
1512
+ adminSdk.defineWidgetConfig({
1513
+ zone: "customer.details.after"
1514
+ });
1515
+ const GenericMetadataTableWidget = ({ data }) => {
1516
+ return /* @__PURE__ */ jsxRuntime.jsx(
1517
+ UniversalMetadataWidget,
1518
+ {
1519
+ data,
1520
+ zone: "product.details.after"
1521
+ }
1522
+ );
1523
+ };
1524
+ adminSdk.defineWidgetConfig({
1525
+ zone: "product.details.after"
1526
+ // TODO: Replace with your entity's zone (e.g., "customer.details.after")
1527
+ });
1528
+ const HideDefaultMetadataWidget = () => {
1529
+ react.useEffect(() => {
1530
+ const hideMetadataSection = () => {
1531
+ const headings = document.querySelectorAll("h2");
1532
+ headings.forEach((heading) => {
1533
+ var _a;
1534
+ if (((_a = heading.textContent) == null ? void 0 : _a.trim()) === "Metadata") {
1535
+ let container = heading.parentElement;
1536
+ while (container && container !== document.body) {
1537
+ const hasContainerClass = container.classList.toString().includes("Container");
1538
+ const isInSidebar = container.closest('[class*="Sidebar"]') || container.closest('[class*="sidebar"]');
1539
+ if (hasContainerClass || isInSidebar) {
1540
+ const editLink = container.querySelector('a[href*="metadata/edit"]');
1541
+ const badge = container.querySelector('div[class*="Badge"]');
1542
+ if (editLink && badge) {
1543
+ container.style.display = "none";
1544
+ container.setAttribute("data-metadata-hidden", "true");
1545
+ return;
1546
+ }
1547
+ }
1548
+ container = container.parentElement;
1549
+ }
1550
+ }
1551
+ });
1552
+ };
1553
+ const runHide = () => {
1554
+ setTimeout(hideMetadataSection, 100);
1555
+ };
1556
+ runHide();
1557
+ const observer = new MutationObserver(() => {
1558
+ const alreadyHidden = document.querySelector('[data-metadata-hidden="true"]');
1559
+ if (!alreadyHidden) {
1560
+ runHide();
1561
+ }
1562
+ });
1563
+ observer.observe(document.body, {
1564
+ childList: true,
1565
+ subtree: true
1566
+ });
1567
+ return () => {
1568
+ observer.disconnect();
1569
+ const hidden = document.querySelector('[data-metadata-hidden="true"]');
1570
+ if (hidden) {
1571
+ hidden.style.display = "";
1572
+ hidden.removeAttribute("data-metadata-hidden");
1573
+ }
1574
+ };
1575
+ }, []);
1576
+ return null;
1577
+ };
1578
+ const ProductHideDefaultMetadata = () => {
1579
+ return /* @__PURE__ */ jsxRuntime.jsx(HideDefaultMetadataWidget, {});
1580
+ };
1581
+ adminSdk.defineWidgetConfig({
1582
+ zone: "product.details.side.before"
1583
+ });
1584
+ const Widget$9 = ({ data }) => {
1585
+ return /* @__PURE__ */ jsxRuntime.jsx(UniversalMetadataWidget, { data, zone: "inventory_item.details.after" });
1586
+ };
1587
+ adminSdk.defineWidgetConfig({
1588
+ zone: "inventory_item.details.after"
1589
+ });
1590
+ const Widget$8 = ({ data }) => {
1591
+ return /* @__PURE__ */ jsxRuntime.jsx(UniversalMetadataWidget, { data, zone: "order.details.after" });
1592
+ };
1593
+ adminSdk.defineWidgetConfig({
1594
+ zone: "order.details.after"
1595
+ });
1596
+ const Widget$7 = ({ data }) => {
1597
+ return /* @__PURE__ */ jsxRuntime.jsx(UniversalMetadataWidget, { data, zone: "price_list.details.after" });
1598
+ };
1599
+ adminSdk.defineWidgetConfig({
1600
+ zone: "price_list.details.after"
1601
+ });
1602
+ const Widget$6 = ({ data }) => {
1603
+ return /* @__PURE__ */ jsxRuntime.jsx(UniversalMetadataWidget, { data, zone: "product_variant.details.after" });
1604
+ };
1605
+ adminSdk.defineWidgetConfig({
1606
+ zone: "product_variant.details.after"
1607
+ });
1608
+ const Widget$5 = ({ data }) => {
1609
+ return /* @__PURE__ */ jsxRuntime.jsx(UniversalMetadataWidget, { data, zone: "product.details.after" });
1610
+ };
1611
+ adminSdk.defineWidgetConfig({
1612
+ zone: "product.details.after"
1613
+ });
1614
+ const Widget$4 = ({ data }) => {
1615
+ return /* @__PURE__ */ jsxRuntime.jsx(UniversalMetadataWidget, { data, zone: "promotion.details.after" });
1616
+ };
1617
+ adminSdk.defineWidgetConfig({
1618
+ zone: "promotion.details.after"
1619
+ });
1620
+ const Widget$3 = ({ data }) => {
1621
+ return /* @__PURE__ */ jsxRuntime.jsx(UniversalMetadataWidget, { data, zone: "region.details.after" });
1622
+ };
1623
+ adminSdk.defineWidgetConfig({
1624
+ zone: "region.details.after"
1625
+ });
1626
+ const Widget$2 = ({ data }) => {
1627
+ return /* @__PURE__ */ jsxRuntime.jsx(UniversalMetadataWidget, { data, zone: "sales_channel.details.after" });
1628
+ };
1629
+ adminSdk.defineWidgetConfig({
1630
+ zone: "sales_channel.details.after"
1631
+ });
1632
+ const Widget$1 = ({ data }) => {
1633
+ return /* @__PURE__ */ jsxRuntime.jsx(UniversalMetadataWidget, { data, zone: "shipping_profile.details.after" });
1634
+ };
1635
+ adminSdk.defineWidgetConfig({
1636
+ zone: "shipping_profile.details.after"
1637
+ });
1638
+ const Widget = ({ data }) => {
1639
+ return /* @__PURE__ */ jsxRuntime.jsx(UniversalMetadataWidget, { data, zone: "store.details.after" });
1640
+ };
1641
+ adminSdk.defineWidgetConfig({
1642
+ zone: "store.details.after"
1643
+ });
1644
+ const widgetModule = { widgets: [
1645
+ {
1646
+ Component: Widget$d,
1647
+ zone: ["campaign.details.after"]
1648
+ },
1649
+ {
1650
+ Component: Widget$c,
1651
+ zone: ["product_category.details.after"]
1652
+ },
1653
+ {
1654
+ Component: Widget$b,
1655
+ zone: ["product_collection.details.after"]
1656
+ },
1657
+ {
1658
+ Component: Widget$a,
1659
+ zone: ["customer.details.after"]
1660
+ },
1661
+ {
1662
+ Component: GenericMetadataTableWidget,
1663
+ zone: ["product.details.after"]
1664
+ },
1665
+ {
1666
+ Component: ProductHideDefaultMetadata,
1667
+ zone: ["product.details.side.before"]
1668
+ },
1669
+ {
1670
+ Component: Widget$9,
1671
+ zone: ["inventory_item.details.after"]
1672
+ },
1673
+ {
1674
+ Component: Widget$8,
1675
+ zone: ["order.details.after"]
1676
+ },
1677
+ {
1678
+ Component: Widget$7,
1679
+ zone: ["price_list.details.after"]
1680
+ },
1681
+ {
1682
+ Component: Widget$6,
1683
+ zone: ["product_variant.details.after"]
1684
+ },
1685
+ {
1686
+ Component: Widget$5,
1687
+ zone: ["product.details.after"]
1688
+ },
1689
+ {
1690
+ Component: Widget$4,
1691
+ zone: ["promotion.details.after"]
1692
+ },
1693
+ {
1694
+ Component: Widget$3,
1695
+ zone: ["region.details.after"]
1696
+ },
1697
+ {
1698
+ Component: Widget$2,
1699
+ zone: ["sales_channel.details.after"]
1700
+ },
1701
+ {
1702
+ Component: Widget$1,
1703
+ zone: ["shipping_profile.details.after"]
1704
+ },
1705
+ {
1706
+ Component: Widget,
1707
+ zone: ["store.details.after"]
1708
+ }
1709
+ ] };
1710
+ const routeModule = {
1711
+ routes: []
1712
+ };
1713
+ const menuItemModule = {
1714
+ menuItems: []
1715
+ };
1716
+ const formModule = { customFields: {} };
1717
+ const displayModule = {
1718
+ displays: {}
1719
+ };
1720
+ const i18nModule = { resources: {} };
1721
+ const plugin = {
1722
+ widgetModule,
1723
+ routeModule,
1724
+ menuItemModule,
1725
+ formModule,
1726
+ displayModule,
1727
+ i18nModule
1728
+ };
1729
+ module.exports = plugin;