@strapi/i18n 0.0.0-experimental.9df68962083938acba06546a7901c68a63266aec → 0.0.0-experimental.a13c58eec89ab119f0e381fb79c0252979e9c125

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.
Files changed (54) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{SettingsPage-DT1sxWa2.js → SettingsPage-D0hqaut-.js} +8 -8
  3. package/dist/_chunks/SettingsPage-D0hqaut-.js.map +1 -0
  4. package/dist/_chunks/{SettingsPage-B5sTcP82.mjs → SettingsPage-D67CaQAB.mjs} +8 -8
  5. package/dist/_chunks/SettingsPage-D67CaQAB.mjs.map +1 -0
  6. package/dist/_chunks/{en-BsOU9o5z.js → en-BKBz3tro.js} +10 -3
  7. package/dist/_chunks/en-BKBz3tro.js.map +1 -0
  8. package/dist/_chunks/{en-CM6Pjfyv.mjs → en-DlXfy6Gy.mjs} +10 -3
  9. package/dist/_chunks/en-DlXfy6Gy.mjs.map +1 -0
  10. package/dist/_chunks/{index-jMrzaEb9.js → index-46DNtLCn.js} +415 -171
  11. package/dist/_chunks/index-46DNtLCn.js.map +1 -0
  12. package/dist/_chunks/{index-DsNqyQKx.mjs → index-CNR8i3KM.mjs} +411 -167
  13. package/dist/_chunks/index-CNR8i3KM.mjs.map +1 -0
  14. package/dist/admin/index.js +1 -1
  15. package/dist/admin/index.mjs +1 -1
  16. package/dist/admin/src/components/BulkLocaleActionModal.d.ts +2 -1
  17. package/dist/admin/src/components/CMHeaderActions.d.ts +29 -3
  18. package/dist/admin/src/components/CreateLocale.d.ts +6 -6
  19. package/dist/admin/src/utils/clean.d.ts +4 -0
  20. package/dist/admin/src/utils/schemas.d.ts +1 -0
  21. package/dist/server/index.js +413 -480
  22. package/dist/server/index.js.map +1 -1
  23. package/dist/server/index.mjs +415 -482
  24. package/dist/server/index.mjs.map +1 -1
  25. package/dist/server/src/bootstrap.d.ts +1 -4
  26. package/dist/server/src/bootstrap.d.ts.map +1 -1
  27. package/dist/server/src/index.d.ts +21 -13
  28. package/dist/server/src/index.d.ts.map +1 -1
  29. package/dist/server/src/register.d.ts.map +1 -1
  30. package/dist/server/src/services/index.d.ts +20 -10
  31. package/dist/server/src/services/index.d.ts.map +1 -1
  32. package/dist/server/src/services/permissions/actions.d.ts +14 -2
  33. package/dist/server/src/services/permissions/actions.d.ts.map +1 -1
  34. package/dist/server/src/services/permissions.d.ts +14 -2
  35. package/dist/server/src/services/permissions.d.ts.map +1 -1
  36. package/dist/server/src/services/sanitize/index.d.ts +11 -0
  37. package/dist/server/src/services/sanitize/index.d.ts.map +1 -0
  38. package/dist/server/src/utils/index.d.ts +2 -2
  39. package/dist/server/src/utils/index.d.ts.map +1 -1
  40. package/package.json +10 -10
  41. package/dist/_chunks/SettingsPage-B5sTcP82.mjs.map +0 -1
  42. package/dist/_chunks/SettingsPage-DT1sxWa2.js.map +0 -1
  43. package/dist/_chunks/en-BsOU9o5z.js.map +0 -1
  44. package/dist/_chunks/en-CM6Pjfyv.mjs.map +0 -1
  45. package/dist/_chunks/index-DsNqyQKx.mjs.map +0 -1
  46. package/dist/_chunks/index-jMrzaEb9.js.map +0 -1
  47. package/dist/admin/src/components/Initializer.d.ts +0 -5
  48. package/dist/server/src/migrations/content-type/disable/index.d.ts +0 -3
  49. package/dist/server/src/migrations/content-type/disable/index.d.ts.map +0 -1
  50. package/dist/server/src/migrations/content-type/enable/index.d.ts +0 -3
  51. package/dist/server/src/migrations/content-type/enable/index.d.ts.map +0 -1
  52. package/dist/server/src/services/entity-service-decorator.d.ts +0 -29
  53. package/dist/server/src/services/entity-service-decorator.d.ts.map +0 -1
  54. package/strapi-server.js +0 -3
@@ -1,12 +1,13 @@
1
1
  import get from "lodash/get";
2
2
  import * as yup from "yup";
3
- import { jsxs, jsx } from "react/jsx-runtime";
3
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
4
4
  import * as React from "react";
5
- import { Typography, Dialog, Field, Checkbox, Flex, Button as Button$1, Box, Status, IconButton, Tooltip, SingleSelect, SingleSelectOption, VisuallyHidden, useCollator, Popover } from "@strapi/design-system";
6
- import { WarningCircle, Pencil, CrossCircle, CheckCircle, ArrowsCounterClockwise, Trash, ListPlus, Earth, EarthStriked, CaretDown } from "@strapi/icons";
5
+ import { Typography, Dialog, Field, Checkbox, Flex, Button, Modal, Box, Status, IconButton, Tooltip, SingleSelect, SingleSelectOption, VisuallyHidden, useCollator, Popover } from "@strapi/design-system";
6
+ import { WarningCircle, Pencil, CrossCircle, CheckCircle, ArrowsCounterClockwise, Trash, Plus, Download, ListPlus, Cross, Earth, EarthStriked, CaretDown } from "@strapi/icons";
7
7
  import { useIntl } from "react-intl";
8
8
  import { styled } from "styled-components";
9
- import { useAuth, adminApi, useTable, Table, useQueryParams, useNotification, useAPIErrorHandler } from "@strapi/admin/strapi-admin";
9
+ import { skipToken } from "@reduxjs/toolkit/query";
10
+ import { useAuth, adminApi, useTable, Table, useQueryParams, useForm, useNotification, useAPIErrorHandler } from "@strapi/admin/strapi-admin";
10
11
  import { unstable_useDocument, unstable_useDocumentActions, buildValidParams } from "@strapi/content-manager/strapi-admin";
11
12
  import { useParams, Link, useNavigate, matchPath } from "react-router-dom";
12
13
  import * as qs from "qs";
@@ -77,11 +78,11 @@ const CheckboxConfirmation = ({
77
78
  }) }) })
78
79
  ] }) }),
79
80
  /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
80
- /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button$1, { variant: "tertiary", children: formatMessage({
81
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
81
82
  id: "components.popUpWarning.button.cancel",
82
83
  defaultMessage: "No, cancel"
83
84
  }) }) }),
84
- /* @__PURE__ */ jsx(Dialog.Action, { children: /* @__PURE__ */ jsx(Button$1, { variant: "danger-light", onClick: handleConfirm, children: formatMessage({
85
+ /* @__PURE__ */ jsx(Dialog.Action, { children: /* @__PURE__ */ jsx(Button, { variant: "danger-light", onClick: handleConfirm, children: formatMessage({
85
86
  id: getTranslation("CheckboxConfirmation.Modal.button-confirm"),
86
87
  defaultMessage: "Yes, disable"
87
88
  }) }) })
@@ -136,7 +137,7 @@ const useI18n = () => {
136
137
  model: params.slug
137
138
  },
138
139
  {
139
- skip: !params.slug || !params.collectionType
140
+ skip: true
140
141
  }
141
142
  );
142
143
  if (doesPluginOptionsHaveI18nLocalized(schema?.pluginOptions)) {
@@ -216,10 +217,94 @@ const relationsApi = i18nApi.injectEndpoints({
216
217
  })
217
218
  });
218
219
  const { useGetManyDraftRelationCountQuery } = relationsApi;
220
+ const cleanData = (data, schema, components) => {
221
+ const cleanedData = removeFields(data, [
222
+ "createdAt",
223
+ "createdBy",
224
+ "updatedAt",
225
+ "updatedBy",
226
+ "id",
227
+ "documentId",
228
+ "publishedAt",
229
+ "strapi_stage",
230
+ "strapi_assignee",
231
+ "locale",
232
+ "status"
233
+ ]);
234
+ const cleanedDataWithoutPasswordAndRelation = recursiveRemoveFieldTypes(
235
+ cleanedData,
236
+ schema,
237
+ components,
238
+ ["relation", "password"]
239
+ );
240
+ return cleanedDataWithoutPasswordAndRelation;
241
+ };
242
+ const removeFields = (data, fields) => {
243
+ return Object.keys(data).reduce((acc, current) => {
244
+ if (fields.includes(current)) {
245
+ return acc;
246
+ }
247
+ acc[current] = data[current];
248
+ return acc;
249
+ }, {});
250
+ };
251
+ const recursiveRemoveFieldTypes = (data, schema, components, fields) => {
252
+ return Object.keys(data).reduce((acc, current) => {
253
+ const attribute = schema.attributes[current] ?? { type: void 0 };
254
+ if (fields.includes(attribute.type)) {
255
+ return acc;
256
+ }
257
+ if (attribute.type === "dynamiczone") {
258
+ acc[current] = data[current].map((componentValue, index2) => {
259
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
260
+ componentValue,
261
+ components[componentValue.__component],
262
+ components,
263
+ fields
264
+ );
265
+ return {
266
+ ...rest,
267
+ __temp_key__: index2 + 1
268
+ };
269
+ });
270
+ } else if (attribute.type === "component") {
271
+ const { repeatable, component } = attribute;
272
+ if (repeatable) {
273
+ acc[current] = (data[current] ?? []).map((compoData, index2) => {
274
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
275
+ compoData,
276
+ components[component],
277
+ components,
278
+ fields
279
+ );
280
+ return {
281
+ ...rest,
282
+ __temp_key__: index2 + 1
283
+ };
284
+ });
285
+ } else {
286
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
287
+ data[current] ?? {},
288
+ components[component],
289
+ components,
290
+ fields
291
+ );
292
+ acc[current] = rest;
293
+ }
294
+ } else {
295
+ acc[current] = data[current];
296
+ }
297
+ return acc;
298
+ }, {});
299
+ };
219
300
  const isErrorMessageDescriptor = (object) => {
220
301
  return typeof object === "object" && object !== null && "id" in object && "defaultMessage" in object;
221
302
  };
222
- const EntryValidationText = ({ status = "draft", validationErrors }) => {
303
+ const EntryValidationText = ({
304
+ status = "draft",
305
+ validationErrors,
306
+ action
307
+ }) => {
223
308
  const { formatMessage } = useIntl();
224
309
  const getErrorStr = (key, value) => {
225
310
  if (typeof value === "string") {
@@ -253,30 +338,63 @@ const EntryValidationText = ({ status = "draft", validationErrors }) => {
253
338
  ) })
254
339
  ] });
255
340
  }
256
- if (status === "published") {
257
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
258
- /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
259
- /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
260
- id: "content-manager.bulk-publish.already-published",
261
- defaultMessage: "Already Published"
262
- }) })
263
- ] });
264
- }
265
- if (status === "modified") {
266
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
267
- /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
268
- /* @__PURE__ */ jsx(Typography, { children: formatMessage({
269
- id: "app.utils.ready-to-publish-changes",
270
- defaultMessage: "Ready to publish changes"
271
- }) })
272
- ] });
273
- }
341
+ const getStatusMessage = () => {
342
+ if (action === "bulk-publish") {
343
+ if (status === "published") {
344
+ return {
345
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
346
+ text: formatMessage({
347
+ id: "content-manager.bulk-publish.already-published",
348
+ defaultMessage: "Already Published"
349
+ }),
350
+ textColor: "success600",
351
+ fontWeight: "bold"
352
+ };
353
+ } else if (status === "modified") {
354
+ return {
355
+ icon: /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
356
+ text: formatMessage({
357
+ id: "app.utils.ready-to-publish-changes",
358
+ defaultMessage: "Ready to publish changes"
359
+ })
360
+ };
361
+ } else {
362
+ return {
363
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
364
+ text: formatMessage({
365
+ id: "app.utils.ready-to-publish",
366
+ defaultMessage: "Ready to publish"
367
+ })
368
+ };
369
+ }
370
+ } else {
371
+ if (status === "draft") {
372
+ return {
373
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
374
+ text: formatMessage({
375
+ id: "content-manager.bulk-unpublish.already-unpublished",
376
+ defaultMessage: "Already Unpublished"
377
+ }),
378
+ textColor: "success600",
379
+ fontWeight: "bold"
380
+ };
381
+ } else {
382
+ return {
383
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
384
+ text: formatMessage({
385
+ id: "app.utils.ready-to-unpublish-changes",
386
+ defaultMessage: "Ready to unpublish"
387
+ }),
388
+ textColor: "success600",
389
+ fontWeight: "bold"
390
+ };
391
+ }
392
+ }
393
+ };
394
+ const { icon, text, textColor = "success600", fontWeight = "normal" } = getStatusMessage();
274
395
  return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
275
- /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
276
- /* @__PURE__ */ jsx(Typography, { children: formatMessage({
277
- id: "app.utils.ready-to-publish",
278
- defaultMessage: "Ready to publish"
279
- }) })
396
+ icon,
397
+ /* @__PURE__ */ jsx(Typography, { textColor, fontWeight, children: text })
280
398
  ] });
281
399
  };
282
400
  const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
@@ -284,7 +402,8 @@ const BulkLocaleActionModal = ({
284
402
  headers,
285
403
  rows,
286
404
  localesMetadata,
287
- validationErrors = {}
405
+ validationErrors = {},
406
+ action
288
407
  }) => {
289
408
  const { formatMessage } = useIntl();
290
409
  const selectedRows = useTable(
@@ -297,27 +416,29 @@ const BulkLocaleActionModal = ({
297
416
  return acc;
298
417
  }, {});
299
418
  const localesWithErrors = Object.keys(validationErrors);
300
- const alreadyPublishedCount = selectedRows.filter(
419
+ const publishedCount = selectedRows.filter(
301
420
  ({ locale }) => currentStatusByLocale[locale] === "published"
302
421
  ).length;
303
- const readyToPublishCount = selectedRows.filter(
422
+ const draftCount = selectedRows.filter(
304
423
  ({ locale }) => (currentStatusByLocale[locale] === "draft" || currentStatusByLocale[locale] === "modified") && !localesWithErrors.includes(locale)
305
424
  ).length;
306
425
  const withErrorsCount = localesWithErrors.length;
426
+ const messageId = action === "bulk-publish" ? "content-manager.containers.list.selectedEntriesModal.selectedCount.publish" : "content-manager.containers.list.selectedEntriesModal.selectedCount.unpublish";
427
+ const defaultMessage = action === "bulk-publish" ? "<b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{draftCount}</b> {draftCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action." : "<b>{draftCount}</b> {draftCount, plural, =0 {entries} one {entry} other {entries}} already unpublished. <b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} ready to unpublish.";
307
428
  return formatMessage(
308
429
  {
309
- id: "content-manager.containers.list.selectedEntriesModal.selectedCount",
310
- defaultMessage: "<b>{alreadyPublishedCount}</b> {alreadyPublishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{readyToPublishCount}</b> {readyToPublishCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
430
+ id: messageId,
431
+ defaultMessage
311
432
  },
312
433
  {
313
434
  withErrorsCount,
314
- readyToPublishCount,
315
- alreadyPublishedCount,
435
+ draftCount,
436
+ publishedCount,
316
437
  b: BoldChunk
317
438
  }
318
439
  );
319
440
  };
320
- return /* @__PURE__ */ jsxs(React.Fragment, { children: [
441
+ return /* @__PURE__ */ jsxs(Modal.Body, { children: [
321
442
  /* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
322
443
  /* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsxs(Table.Content, { children: [
323
444
  /* @__PURE__ */ jsxs(Table.Head, { children: [
@@ -338,13 +459,12 @@ const BulkLocaleActionModal = ({
338
459
  paddingRight: "6px",
339
460
  paddingTop: "2px",
340
461
  paddingBottom: "2px",
341
- showBullet: false,
342
462
  size: "S",
343
463
  variant: statusVariant,
344
464
  children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
345
465
  }
346
466
  ) }) }),
347
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status }) }),
467
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status, action }) }),
348
468
  /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
349
469
  IconButton,
350
470
  {
@@ -361,7 +481,7 @@ const BulkLocaleActionModal = ({
361
481
  name: locale
362
482
  }
363
483
  ),
364
- borderWidth: 0,
484
+ variant: "ghost",
365
485
  children: /* @__PURE__ */ jsx(Pencil, {})
366
486
  }
367
487
  ) })
@@ -370,6 +490,47 @@ const BulkLocaleActionModal = ({
370
490
  ] }) })
371
491
  ] });
372
492
  };
493
+ const statusVariants = {
494
+ draft: "secondary",
495
+ published: "success",
496
+ modified: "alternative"
497
+ };
498
+ const LocaleOption = ({
499
+ isDraftAndPublishEnabled,
500
+ locale,
501
+ status,
502
+ entryExists
503
+ }) => {
504
+ const { formatMessage } = useIntl();
505
+ if (!entryExists) {
506
+ return formatMessage(
507
+ {
508
+ id: getTranslation("CMEditViewLocalePicker.locale.create"),
509
+ defaultMessage: "Create <bold>{locale}</bold> locale"
510
+ },
511
+ {
512
+ bold: (locale2) => /* @__PURE__ */ jsx("b", { children: locale2 }),
513
+ locale: locale.name
514
+ }
515
+ );
516
+ }
517
+ return /* @__PURE__ */ jsxs(Flex, { width: "100%", gap: 1, justifyContent: "space-between", children: [
518
+ /* @__PURE__ */ jsx(Typography, { children: locale.name }),
519
+ isDraftAndPublishEnabled ? /* @__PURE__ */ jsx(
520
+ Status,
521
+ {
522
+ display: "flex",
523
+ paddingLeft: "6px",
524
+ paddingRight: "6px",
525
+ paddingTop: "2px",
526
+ paddingBottom: "2px",
527
+ size: "S",
528
+ variant: statusVariants[status],
529
+ children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
530
+ }
531
+ ) : null
532
+ ] });
533
+ };
373
534
  const LocalePickerAction = ({
374
535
  document,
375
536
  meta,
@@ -381,7 +542,13 @@ const LocalePickerAction = ({
381
542
  const [{ query }, setQuery] = useQueryParams();
382
543
  const { hasI18n, canCreate, canRead } = useI18n();
383
544
  const { data: locales = [] } = useGetLocalesQuery();
384
- const { schema } = unstable_useDocument({ model, collectionType, documentId });
545
+ const currentDesiredLocale = query.plugins?.i18n?.locale;
546
+ const { schema } = unstable_useDocument({
547
+ model,
548
+ collectionType,
549
+ documentId,
550
+ params: { locale: currentDesiredLocale }
551
+ });
385
552
  const handleSelect = React.useCallback(
386
553
  (value) => {
387
554
  setQuery({
@@ -399,53 +566,47 @@ const LocalePickerAction = ({
399
566
  if (!Array.isArray(locales) || !hasI18n) {
400
567
  return;
401
568
  }
402
- const currentDesiredLocale = query.plugins?.i18n?.locale;
403
569
  const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);
404
570
  const defaultLocale = locales.find((locale) => locale.isDefault);
405
571
  if (!doesLocaleExist && defaultLocale?.code) {
406
572
  handleSelect(defaultLocale.code);
407
573
  }
408
- }, [handleSelect, hasI18n, locales, query.plugins?.i18n?.locale]);
409
- if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
410
- return null;
411
- }
412
- const currentLocale = query.plugins?.i18n?.locale || locales.find((loc) => loc.isDefault)?.code;
574
+ }, [handleSelect, hasI18n, locales, currentDesiredLocale]);
575
+ const currentLocale = Array.isArray(locales) ? locales.find((locale) => locale.code === currentDesiredLocale) : void 0;
413
576
  const allCurrentLocales = [
414
- { status: getDocumentStatus(document, meta), locale: currentLocale },
577
+ { status: getDocumentStatus(document, meta), locale: currentLocale?.code },
415
578
  ...meta?.availableLocales ?? []
416
579
  ];
580
+ if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
581
+ return null;
582
+ }
417
583
  return {
418
584
  label: formatMessage({
419
585
  id: getTranslation("Settings.locales.modal.locales.label"),
420
586
  defaultMessage: "Locales"
421
587
  }),
422
588
  options: locales.map((locale) => {
589
+ const entryWithLocaleExists = allCurrentLocales.some((doc) => doc.locale === locale.code);
423
590
  const currentLocaleDoc = allCurrentLocales.find(
424
591
  (doc) => "locale" in doc ? doc.locale === locale.code : false
425
592
  );
426
- const status = currentLocaleDoc?.status ?? "draft";
427
- const permissionsToCheck = currentLocaleDoc ? canCreate : canRead;
428
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
593
+ const permissionsToCheck = currentLocaleDoc ? canRead : canCreate;
429
594
  return {
430
595
  disabled: !permissionsToCheck.includes(locale.code),
431
596
  value: locale.code,
432
- label: locale.name,
433
- startIcon: schema?.options?.draftAndPublish ? /* @__PURE__ */ jsx(
434
- Status,
597
+ label: /* @__PURE__ */ jsx(
598
+ LocaleOption,
435
599
  {
436
- display: "flex",
437
- paddingLeft: "6px",
438
- paddingRight: "6px",
439
- paddingTop: "2px",
440
- paddingBottom: "2px",
441
- showBullet: false,
442
- size: "S",
443
- variant: statusVariant,
444
- children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
600
+ isDraftAndPublishEnabled: !!schema?.options?.draftAndPublish,
601
+ locale,
602
+ status: currentLocaleDoc?.status,
603
+ entryExists: entryWithLocaleExists
445
604
  }
446
- ) : null
605
+ ),
606
+ startIcon: !entryWithLocaleExists ? /* @__PURE__ */ jsx(Plus, {}) : null
447
607
  };
448
608
  }),
609
+ customizeContent: () => currentLocale?.name,
449
610
  onSelect: handleSelect,
450
611
  value: currentLocale
451
612
  };
@@ -461,6 +622,99 @@ const getDocumentStatus = (document, meta) => {
461
622
  }
462
623
  return docStatus;
463
624
  };
625
+ const FillFromAnotherLocaleAction = ({
626
+ documentId,
627
+ meta,
628
+ model,
629
+ collectionType
630
+ }) => {
631
+ const { formatMessage } = useIntl();
632
+ const [{ query }] = useQueryParams();
633
+ const { hasI18n } = useI18n();
634
+ const currentDesiredLocale = query.plugins?.i18n?.locale;
635
+ const [localeSelected, setLocaleSelected] = React.useState(null);
636
+ const setValues = useForm("FillFromAnotherLocale", (state) => state.setValues);
637
+ const { getDocument } = unstable_useDocumentActions();
638
+ const { schema, components } = unstable_useDocument({
639
+ model,
640
+ documentId,
641
+ collectionType,
642
+ params: { locale: currentDesiredLocale }
643
+ });
644
+ const { data: locales = [] } = useGetLocalesQuery();
645
+ const availableLocales = Array.isArray(locales) ? locales.filter((locale) => meta?.availableLocales.some((l) => l.locale === locale.code)) : [];
646
+ const fillFromLocale = (onClose) => async () => {
647
+ const response = await getDocument({
648
+ collectionType,
649
+ model,
650
+ documentId,
651
+ params: { locale: localeSelected }
652
+ });
653
+ if (!response || !schema) {
654
+ return;
655
+ }
656
+ const { data } = response;
657
+ const cleanedData = cleanData(data, schema, components);
658
+ setValues(cleanedData);
659
+ onClose();
660
+ };
661
+ if (!hasI18n) {
662
+ return null;
663
+ }
664
+ return {
665
+ type: "icon",
666
+ icon: /* @__PURE__ */ jsx(Download, {}),
667
+ disabled: availableLocales.length === 0,
668
+ label: formatMessage({
669
+ id: getTranslation("CMEditViewCopyLocale.copy-text"),
670
+ defaultMessage: "Fill in from another locale"
671
+ }),
672
+ dialog: {
673
+ type: "dialog",
674
+ title: formatMessage({
675
+ id: getTranslation("CMEditViewCopyLocale.dialog.title"),
676
+ defaultMessage: "Confirmation"
677
+ }),
678
+ content: ({ onClose }) => /* @__PURE__ */ jsxs(Fragment, { children: [
679
+ /* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, children: [
680
+ /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
681
+ /* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
682
+ id: getTranslation("CMEditViewCopyLocale.dialog.body"),
683
+ defaultMessage: "Your current content will be erased and filled by the content of the selected locale:"
684
+ }) }),
685
+ /* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
686
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
687
+ id: getTranslation("CMEditViewCopyLocale.dialog.field.label"),
688
+ defaultMessage: "Locale"
689
+ }) }),
690
+ /* @__PURE__ */ jsx(
691
+ SingleSelect,
692
+ {
693
+ value: localeSelected,
694
+ placeholder: formatMessage({
695
+ id: getTranslation("CMEditViewCopyLocale.dialog.field.placeholder"),
696
+ defaultMessage: "Select one locale..."
697
+ }),
698
+ onChange: (value) => setLocaleSelected(value),
699
+ children: availableLocales.map((locale) => /* @__PURE__ */ jsx(SingleSelectOption, { value: locale.code, children: locale.name }, locale.code))
700
+ }
701
+ )
702
+ ] })
703
+ ] }) }),
704
+ /* @__PURE__ */ jsx(Dialog.Footer, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, width: "100%", children: [
705
+ /* @__PURE__ */ jsx(Button, { flex: "auto", variant: "tertiary", onClick: onClose, children: formatMessage({
706
+ id: getTranslation("CMEditViewCopyLocale.cancel-text"),
707
+ defaultMessage: "No, cancel"
708
+ }) }),
709
+ /* @__PURE__ */ jsx(Button, { flex: "auto", variant: "success", onClick: fillFromLocale(onClose), children: formatMessage({
710
+ id: getTranslation("CMEditViewCopyLocale.submit-text"),
711
+ defaultMessage: "Yes, fill in"
712
+ }) })
713
+ ] }) })
714
+ ] })
715
+ }
716
+ };
717
+ };
464
718
  const DeleteLocaleAction = ({
465
719
  document,
466
720
  documentId,
@@ -472,16 +726,23 @@ const DeleteLocaleAction = ({
472
726
  const { toggleNotification } = useNotification();
473
727
  const { delete: deleteAction } = unstable_useDocumentActions();
474
728
  const { hasI18n, canDelete } = useI18n();
729
+ const [{ query }] = useQueryParams();
730
+ const { data: locales = [] } = useGetLocalesQuery();
731
+ const currentDesiredLocale = query.plugins?.i18n?.locale;
732
+ const locale = !("error" in locales) && locales.find((loc) => loc.code === currentDesiredLocale);
475
733
  if (!hasI18n) {
476
734
  return null;
477
735
  }
478
736
  return {
479
737
  disabled: document?.locale && !canDelete.includes(document.locale) || !document || !document.id,
480
738
  position: ["header", "table-row"],
481
- label: formatMessage({
482
- id: getTranslation("actions.delete.label"),
483
- defaultMessage: "Delete locale"
484
- }),
739
+ label: formatMessage(
740
+ {
741
+ id: getTranslation("actions.delete.label"),
742
+ defaultMessage: "Delete entry ({locale})"
743
+ },
744
+ { locale: locale && locale.name }
745
+ ),
485
746
  icon: /* @__PURE__ */ jsx(StyledTrash, {}),
486
747
  variant: "danger",
487
748
  dialog: {
@@ -498,7 +759,12 @@ const DeleteLocaleAction = ({
498
759
  }) })
499
760
  ] }),
500
761
  onConfirm: async () => {
501
- if (!documentId || !document?.locale) {
762
+ const unableToDelete = (
763
+ // We are unable to delete a collection type without a document ID
764
+ // & unable to delete generally if there is no document locale
765
+ collectionType !== "single-types" && !documentId || !document?.locale
766
+ );
767
+ if (unableToDelete) {
502
768
  console.error(
503
769
  "You're trying to delete a document without an id or locale, this is likely a bug with Strapi. Please open an issue."
504
770
  );
@@ -524,37 +790,43 @@ const DeleteLocaleAction = ({
524
790
  }
525
791
  };
526
792
  };
527
- const BulkLocalePublishAction = ({
793
+ const BulkLocaleAction = ({
528
794
  document: baseDocument,
529
795
  documentId,
530
796
  model,
531
- collectionType
797
+ collectionType,
798
+ action
532
799
  }) => {
533
800
  const baseLocale = baseDocument?.locale ?? null;
534
801
  const [{ query }] = useQueryParams();
535
802
  const params = React.useMemo(() => buildValidParams(query), [query]);
536
- const isPublishedTab = query.status === "published";
803
+ const isOnPublishedTab = query.status === "published";
537
804
  const { formatMessage } = useIntl();
538
805
  const { hasI18n, canPublish } = useI18n();
539
806
  const { toggleNotification } = useNotification();
540
807
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
541
808
  const [selectedRows, setSelectedRows] = React.useState([]);
542
809
  const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React.useState(false);
543
- const { publishMany: publishManyAction } = unstable_useDocumentActions();
810
+ const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = unstable_useDocumentActions();
544
811
  const {
545
812
  document,
546
813
  meta: documentMeta,
547
814
  schema,
548
815
  validate
549
- } = unstable_useDocument({
550
- model,
551
- collectionType,
552
- documentId,
553
- params: {
554
- locale: baseLocale
816
+ } = unstable_useDocument(
817
+ {
818
+ model,
819
+ collectionType,
820
+ documentId,
821
+ params: {
822
+ locale: baseLocale
823
+ }
824
+ },
825
+ {
826
+ skip: !hasI18n || !baseLocale
555
827
  }
556
- });
557
- const { data: localesMetadata = [] } = useGetLocalesQuery();
828
+ );
829
+ const { data: localesMetadata = [] } = useGetLocalesQuery(hasI18n ? void 0 : skipToken);
558
830
  const headers = [
559
831
  {
560
832
  label: formatMessage({
@@ -603,12 +875,19 @@ const BulkLocalePublishAction = ({
603
875
  }, {});
604
876
  return [rowsFromMeta, errors];
605
877
  }, [document, documentMeta?.availableLocales, validate]);
606
- const localesToPublish = selectedRows.reduce((acc, selectedRow) => {
607
- if (selectedRow.status !== "published" && !Object.keys(validationErrors).includes(selectedRow.locale)) {
878
+ const isBulkPublish = action === "bulk-publish";
879
+ const localesForAction = selectedRows.reduce((acc, selectedRow) => {
880
+ const isValidLocale = (
881
+ // Validation errors are irrelevant if we are trying to unpublish
882
+ !isBulkPublish || !Object.keys(validationErrors).includes(selectedRow.locale)
883
+ );
884
+ const shouldAddLocale = isBulkPublish ? selectedRow.status !== "published" && isValidLocale : selectedRow.status !== "draft" && isValidLocale;
885
+ if (shouldAddLocale) {
608
886
  acc.push(selectedRow.locale);
609
887
  }
610
888
  return acc;
611
889
  }, []);
890
+ const enableDraftRelationsCount = false;
612
891
  const {
613
892
  data: draftRelationsCount = 0,
614
893
  isLoading: isDraftRelationsLoading,
@@ -617,10 +896,10 @@ const BulkLocalePublishAction = ({
617
896
  {
618
897
  model,
619
898
  documentIds: [documentId],
620
- locale: localesToPublish
899
+ locale: localesForAction
621
900
  },
622
901
  {
623
- skip: !documentId || localesToPublish.length === 0
902
+ skip: !enableDraftRelationsCount
624
903
  }
625
904
  );
626
905
  React.useEffect(() => {
@@ -646,7 +925,18 @@ const BulkLocalePublishAction = ({
646
925
  documentIds: [documentId],
647
926
  params: {
648
927
  ...params,
649
- locale: localesToPublish
928
+ locale: localesForAction
929
+ }
930
+ });
931
+ setSelectedRows([]);
932
+ };
933
+ const unpublish = async () => {
934
+ await unpublishManyAction({
935
+ model,
936
+ documentIds: [documentId],
937
+ params: {
938
+ ...params,
939
+ locale: localesForAction
650
940
  }
651
941
  });
652
942
  setSelectedRows([]);
@@ -654,14 +944,12 @@ const BulkLocalePublishAction = ({
654
944
  const handleAction = async () => {
655
945
  if (draftRelationsCount > 0) {
656
946
  setIsDraftRelationConfirmationOpen(true);
657
- } else {
947
+ } else if (isBulkPublish) {
658
948
  await publish();
949
+ } else {
950
+ await unpublish();
659
951
  }
660
952
  };
661
- const isUnpublish = document?.status === "published";
662
- if (isUnpublish) {
663
- console.warn(["I18N"], "Bulk locale unpublish modal not implemented");
664
- }
665
953
  if (isDraftRelationConfirmationOpen) {
666
954
  return {
667
955
  label: formatMessage({
@@ -696,20 +984,21 @@ const BulkLocalePublishAction = ({
696
984
  }
697
985
  };
698
986
  }
987
+ const hasPermission = selectedRows.map(({ locale }) => locale).every((locale) => canPublish.includes(locale));
699
988
  return {
700
989
  label: formatMessage({
701
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
702
- defaultMessage: "Publish Multiple Locales"
990
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
991
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
703
992
  }),
704
- icon: /* @__PURE__ */ jsx(ListPlus, {}),
705
- disabled: isPublishedTab || !canPublish,
993
+ variant: isBulkPublish ? "secondary" : "danger",
994
+ icon: isBulkPublish ? /* @__PURE__ */ jsx(ListPlus, {}) : /* @__PURE__ */ jsx(Cross, {}),
995
+ disabled: isOnPublishedTab || canPublish.length === 0,
706
996
  position: ["panel"],
707
- variant: "secondary",
708
997
  dialog: {
709
998
  type: "modal",
710
999
  title: formatMessage({
711
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
712
- defaultMessage: "Publish Multiple Locales"
1000
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
1001
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
713
1002
  }),
714
1003
  content: () => {
715
1004
  return /* @__PURE__ */ jsx(
@@ -728,28 +1017,35 @@ const BulkLocalePublishAction = ({
728
1017
  validationErrors,
729
1018
  headers,
730
1019
  rows,
731
- localesMetadata
1020
+ localesMetadata,
1021
+ action: action ?? "bulk-publish"
732
1022
  }
733
1023
  )
734
1024
  }
735
1025
  );
736
1026
  },
737
- footer: () => /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
738
- Button$1,
1027
+ footer: () => /* @__PURE__ */ jsx(Modal.Footer, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
1028
+ Button,
739
1029
  {
740
1030
  loading: isDraftRelationsLoading,
741
- disabled: localesToPublish.length === 0,
1031
+ disabled: !hasPermission || localesForAction.length === 0,
742
1032
  variant: "default",
743
1033
  onClick: handleAction,
744
1034
  children: formatMessage({
745
- id: "app.utils.publish",
746
- defaultMessage: "Publish"
1035
+ id: isBulkPublish ? "app.utils.publish" : "app.utils.unpublish",
1036
+ defaultMessage: isBulkPublish ? "Publish" : "Unpublish"
747
1037
  })
748
1038
  }
749
1039
  ) })
750
1040
  }
751
1041
  };
752
1042
  };
1043
+ const BulkLocalePublishAction = (props) => {
1044
+ return BulkLocaleAction({ action: "bulk-publish", ...props });
1045
+ };
1046
+ const BulkLocaleUnpublishAction = (props) => {
1047
+ return BulkLocaleAction({ action: "bulk-unpublish", ...props });
1048
+ };
753
1049
  const StyledTrash = styled(Trash)`
754
1050
  path {
755
1051
  fill: currentColor;
@@ -806,13 +1102,6 @@ const UnpublishModalAdditionalInfo = () => {
806
1102
  }
807
1103
  ) });
808
1104
  };
809
- const Initializer = ({ setPlugin }) => {
810
- const setPluginRef = React.useRef(setPlugin);
811
- React.useEffect(() => {
812
- setPluginRef.current(pluginId);
813
- }, []);
814
- return null;
815
- };
816
1105
  const LocalePicker = () => {
817
1106
  const { formatMessage } = useIntl();
818
1107
  const [{ query }, setQuery] = useQueryParams();
@@ -976,54 +1265,13 @@ const LocaleListCell = ({
976
1265
  return locale.name;
977
1266
  }).toSorted((a, b) => formatter.compare(a, b));
978
1267
  return /* @__PURE__ */ jsxs(Popover.Root, { children: [
979
- /* @__PURE__ */ jsx(Popover.Trigger, { children: /* @__PURE__ */ jsx(Button, { type: "button", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxs(
980
- ActionWrapper,
981
- {
982
- minWidth: "100%",
983
- alignItems: "center",
984
- justifyContent: "center",
985
- height: "3.2rem",
986
- width: "3.2rem",
987
- children: [
988
- /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, children: localesForDocument.join(", ") }),
989
- /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, {}) })
990
- ]
991
- }
992
- ) }) }),
1268
+ /* @__PURE__ */ jsx(Popover.Trigger, { children: /* @__PURE__ */ jsx(Button, { variant: "ghost", type: "button", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxs(Flex, { minWidth: "100%", alignItems: "center", justifyContent: "center", fontWeight: "regular", children: [
1269
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, marginRight: 2, children: localesForDocument.join(", ") }),
1270
+ /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, { width: "1.2rem", height: "1.2rem" }) })
1271
+ ] }) }) }),
993
1272
  /* @__PURE__ */ jsx(Popover.Content, { sideOffset: 16, children: /* @__PURE__ */ jsx("ul", { children: localesForDocument.map((name) => /* @__PURE__ */ jsx(Box, { padding: 3, tag: "li", children: /* @__PURE__ */ jsx(Typography, { children: name }) }, name)) }) })
994
1273
  ] });
995
1274
  };
996
- const Button = styled.button`
997
- width: 100%;
998
-
999
- svg {
1000
- > g,
1001
- path {
1002
- fill: ${({ theme }) => theme.colors.neutral500};
1003
- }
1004
- }
1005
- &:hover {
1006
- svg {
1007
- > g,
1008
- path {
1009
- fill: ${({ theme }) => theme.colors.neutral600};
1010
- }
1011
- }
1012
- }
1013
- &:active {
1014
- svg {
1015
- > g,
1016
- path {
1017
- fill: ${({ theme }) => theme.colors.neutral400};
1018
- }
1019
- }
1020
- }
1021
- `;
1022
- const ActionWrapper = styled(Flex)`
1023
- svg {
1024
- height: 0.4rem;
1025
- }
1026
- `;
1027
1275
  const addColumnToTableHook = ({ displayedHeaders, layout }) => {
1028
1276
  const { options } = layout;
1029
1277
  const isFieldLocalized = doesPluginOptionsHaveI18nLocalized(options) ? options.i18n.localized : false;
@@ -1149,9 +1397,6 @@ const localeMiddleware = (ctx) => (next) => (permissions) => {
1149
1397
  return next(revisedPermissions);
1150
1398
  };
1151
1399
  const prefixPluginTranslations = (trad, pluginId2) => {
1152
- if (!pluginId2) {
1153
- throw new TypeError("pluginId can't be empty");
1154
- }
1155
1400
  return Object.keys(trad).reduce((acc, current) => {
1156
1401
  acc[`${pluginId2}.${current}`] = trad[current];
1157
1402
  return acc;
@@ -1204,8 +1449,6 @@ const index = {
1204
1449
  app.addRBACMiddleware([localeMiddleware]);
1205
1450
  app.registerPlugin({
1206
1451
  id: pluginId,
1207
- initializer: Initializer,
1208
- isReady: false,
1209
1452
  name: pluginId
1210
1453
  });
1211
1454
  },
@@ -1223,11 +1466,11 @@ const index = {
1223
1466
  },
1224
1467
  id: "internationalization",
1225
1468
  to: "internationalization",
1226
- Component: () => import("./SettingsPage-B5sTcP82.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
1469
+ Component: () => import("./SettingsPage-D67CaQAB.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
1227
1470
  permissions: PERMISSIONS.accessMain
1228
1471
  });
1229
1472
  const contentManager = app.getPlugin("content-manager");
1230
- contentManager.apis.addDocumentHeaderAction([LocalePickerAction]);
1473
+ contentManager.apis.addDocumentHeaderAction([LocalePickerAction, FillFromAnotherLocaleAction]);
1231
1474
  contentManager.apis.addDocumentAction((actions) => {
1232
1475
  const indexOfDeleteAction = actions.findIndex((action) => action.type === "delete");
1233
1476
  actions.splice(indexOfDeleteAction, 0, DeleteLocaleAction);
@@ -1235,6 +1478,7 @@ const index = {
1235
1478
  });
1236
1479
  contentManager.apis.addDocumentAction((actions) => {
1237
1480
  actions.splice(2, 0, BulkLocalePublishAction);
1481
+ actions.splice(5, 0, BulkLocaleUnpublishAction);
1238
1482
  return actions;
1239
1483
  });
1240
1484
  contentManager.injectComponent("listView", "actions", {
@@ -1340,7 +1584,7 @@ const index = {
1340
1584
  async registerTrads({ locales }) {
1341
1585
  const importedTrads = await Promise.all(
1342
1586
  locales.map((locale) => {
1343
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => import("./de-9eCAqqrB.mjs"), "./translations/dk.json": () => import("./dk-2qBjxt-P.mjs"), "./translations/en.json": () => import("./en-CM6Pjfyv.mjs"), "./translations/es.json": () => import("./es-DlmMVaBG.mjs"), "./translations/fr.json": () => import("./fr-3S6ke71d.mjs"), "./translations/ko.json": () => import("./ko-qTjQ8IMw.mjs"), "./translations/pl.json": () => import("./pl-B67TSHqT.mjs"), "./translations/ru.json": () => import("./ru-hagMa57T.mjs"), "./translations/tr.json": () => import("./tr-Dw_jmkG-.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-Dyc-aR-h.mjs"), "./translations/zh.json": () => import("./zh-57YM4amO.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
1587
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => import("./de-9eCAqqrB.mjs"), "./translations/dk.json": () => import("./dk-2qBjxt-P.mjs"), "./translations/en.json": () => import("./en-DlXfy6Gy.mjs"), "./translations/es.json": () => import("./es-DlmMVaBG.mjs"), "./translations/fr.json": () => import("./fr-3S6ke71d.mjs"), "./translations/ko.json": () => import("./ko-qTjQ8IMw.mjs"), "./translations/pl.json": () => import("./pl-B67TSHqT.mjs"), "./translations/ru.json": () => import("./ru-hagMa57T.mjs"), "./translations/tr.json": () => import("./tr-Dw_jmkG-.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-Dyc-aR-h.mjs"), "./translations/zh.json": () => import("./zh-57YM4amO.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
1344
1588
  return {
1345
1589
  data: prefixPluginTranslations(data, pluginId),
1346
1590
  locale
@@ -1366,4 +1610,4 @@ export {
1366
1610
  index as i,
1367
1611
  useCreateLocaleMutation as u
1368
1612
  };
1369
- //# sourceMappingURL=index-DsNqyQKx.mjs.map
1613
+ //# sourceMappingURL=index-CNR8i3KM.mjs.map