UNPKG

sanity-plugin-media

Version:

This version of `sanity-plugin-media` is for Sanity Studio V3.

5,585 lines 218 kB
"use strict";
Object.defineProperty(exports, "__esModule", { value: !0 });
var jsxRuntime = require("react/jsx-runtime"), sanity = require("sanity"), icons = require("@sanity/icons"), ui = require("@sanity/ui"), react = require("react"), groq = require("groq"), reactRedux = require("react-redux"), toolkit = require("@reduxjs/toolkit"), nanoid = require("nanoid"), reduxObservable = require("redux-observable"), rxjs = require("rxjs"), operators$1 = require("rxjs/operators"), uuid = require("@sanity/uuid"), styledComponents = require("styled-components"), pluralize = require("pluralize"), reactNprogress = require("@tanem/react-nprogress"), color = require("@sanity/color"), Select = require("react-select"), reactVirtuoso = require("react-virtuoso"), zod = require("@hookform/resolvers/zod"), reactHookForm = require("react-hook-form"), z = require("zod"), dateFns = require("date-fns"), filesize = require("filesize"), copy = require("copy-to-clipboard"), router = require("sanity/router"), reactFileIcon = require("react-file-icon"), CreatableSelect = require("react-select/creatable"), reactDropzone = require("react-dropzone");
function _interopDefaultCompat(e) {
  return e && typeof e == "object" && "default" in e ? e : { default: e };
}
function _interopNamespaceCompat(e) {
  if (e && typeof e == "object" && "default" in e) return e;
  var n = /* @__PURE__ */ Object.create(null);
  return e && Object.keys(e).forEach(function(k) {
    if (k !== "default") {
      var d = Object.getOwnPropertyDescriptor(e, k);
      Object.defineProperty(n, k, d.get ? d : {
        enumerable: !0,
        get: function() {
          return e[k];
        }
      });
    }
  }), n.default = e, Object.freeze(n);
}
var groq__default = /* @__PURE__ */ _interopDefaultCompat(groq), pluralize__default = /* @__PURE__ */ _interopDefaultCompat(pluralize), Select__default = /* @__PURE__ */ _interopDefaultCompat(Select), z__namespace = /* @__PURE__ */ _interopNamespaceCompat(z), filesize__default = /* @__PURE__ */ _interopDefaultCompat(filesize), copy__default = /* @__PURE__ */ _interopDefaultCompat(copy), CreatableSelect__default = /* @__PURE__ */ _interopDefaultCompat(CreatableSelect);
function getDefaultExportFromCjs(x) {
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x.default : x;
}
var lib = {}, hasRequiredLib;
function requireLib() {
  if (hasRequiredLib) return lib;
  hasRequiredLib = 1, Object.defineProperty(lib, "__esModule", {
    value: !0
  });
  for (var IS_MAC = typeof window < "u" && /Mac|iPod|iPhone|iPad/.test(window.navigator.platform), MODIFIERS = {
    alt: "altKey",
    control: "ctrlKey",
    meta: "metaKey",
    shift: "shiftKey"
  }, ALIASES = {
    add: "+",
    break: "pause",
    cmd: "meta",
    command: "meta",
    ctl: "control",
    ctrl: "control",
    del: "delete",
    down: "arrowdown",
    esc: "escape",
    ins: "insert",
    left: "arrowleft",
    mod: IS_MAC ? "meta" : "control",
    opt: "alt",
    option: "alt",
    return: "enter",
    right: "arrowright",
    space: " ",
    spacebar: " ",
    up: "arrowup",
    win: "meta",
    windows: "meta"
  }, CODES = {
    backspace: 8,
    tab: 9,
    enter: 13,
    shift: 16,
    control: 17,
    alt: 18,
    pause: 19,
    capslock: 20,
    escape: 27,
    " ": 32,
    pageup: 33,
    pagedown: 34,
    end: 35,
    home: 36,
    arrowleft: 37,
    arrowup: 38,
    arrowright: 39,
    arrowdown: 40,
    insert: 45,
    delete: 46,
    meta: 91,
    numlock: 144,
    scrolllock: 145,
    ";": 186,
    "=": 187,
    ",": 188,
    "-": 189,
    ".": 190,
    "/": 191,
    "`": 192,
    "[": 219,
    "\\": 220,
    "]": 221,
    "'": 222
  }, f = 1; f < 20; f++)
    CODES["f" + f] = 111 + f;
  function isHotkey2(hotkey, options, event) {
    options && !("byKey" in options) && (event = options, options = null), Array.isArray(hotkey) || (hotkey = [hotkey]);
    var array = hotkey.map(function(string) {
      return parseHotkey(string, options);
    }), check = function(e) {
      return array.some(function(object) {
        return compareHotkey(object, e);
      });
    }, ret = event == null ? check : check(event);
    return ret;
  }
  function isCodeHotkey(hotkey, event) {
    return isHotkey2(hotkey, event);
  }
  function isKeyHotkey(hotkey, event) {
    return isHotkey2(hotkey, { byKey: !0 }, event);
  }
  function parseHotkey(hotkey, options) {
    var byKey = options && options.byKey, ret = {};
    hotkey = hotkey.replace("++", "+add");
    var values = hotkey.split("+"), length = values.length;
    for (var k in MODIFIERS)
      ret[MODIFIERS[k]] = !1;
    var _iteratorNormalCompletion = !0, _didIteratorError = !1, _iteratorError = void 0;
    try {
      for (var _iterator = values[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = !0) {
        var value = _step.value, optional = value.endsWith("?") && value.length > 1;
        optional && (value = value.slice(0, -1));
        var name = toKeyName(value), modifier = MODIFIERS[name];
        if (value.length > 1 && !modifier && !ALIASES[value] && !CODES[name])
          throw new TypeError('Unknown modifier: "' + value + '"');
        (length === 1 || !modifier) && (byKey ? ret.key = name : ret.which = toKeyCode(value)), modifier && (ret[modifier] = optional ? null : !0);
      }
    } catch (err) {
      _didIteratorError = !0, _iteratorError = err;
    } finally {
      try {
        !_iteratorNormalCompletion && _iterator.return && _iterator.return();
      } finally {
        if (_didIteratorError)
          throw _iteratorError;
      }
    }
    return ret;
  }
  function compareHotkey(object, event) {
    for (var key in object) {
      var expected = object[key], actual = void 0;
      if (expected != null && (key === "key" && event.key != null ? actual = event.key.toLowerCase() : key === "which" ? actual = expected === 91 && event.which === 93 ? 91 : event.which : actual = event[key], !(actual == null && expected === !1) && actual !== expected))
        return !1;
    }
    return !0;
  }
  function toKeyCode(name) {
    name = toKeyName(name);
    var code = CODES[name] || name.toUpperCase().charCodeAt(0);
    return code;
  }
  function toKeyName(name) {
    return name = name.toLowerCase(), name = ALIASES[name] || name, name;
  }
  return lib.default = isHotkey2, lib.isHotkey = isHotkey2, lib.isCodeHotkey = isCodeHotkey, lib.isKeyHotkey = isKeyHotkey, lib.parseHotkey = parseHotkey, lib.compareHotkey = compareHotkey, lib.toKeyCode = toKeyCode, lib.toKeyName = toKeyName, lib;
}
var libExports = requireLib(), isHotkey = /* @__PURE__ */ getDefaultExportFromCjs(libExports);
const useKeyPress = (hotkey, onPress) => {
  const keyPressed = react.useRef(!1), downHandler = react.useCallback(
    (e) => {
      isHotkey(hotkey, e) && (keyPressed.current = !0, onPress && onPress());
    },
    [hotkey, onPress]
  ), upHandler = react.useCallback(() => {
    keyPressed.current = !1;
  }, []);
  return react.useEffect(() => (window.addEventListener("keydown", downHandler), window.addEventListener("keyup", upHandler), () => {
    window.removeEventListener("keydown", downHandler), window.removeEventListener("keyup", upHandler);
  }), [downHandler, upHandler]), keyPressed;
}, divider = { type: "divider" }, inputs = {
  altText: {
    assetTypes: ["file", "image"],
    field: "altText",
    name: "altText",
    operatorType: "empty",
    operatorTypes: ["empty", "notEmpty", null, "includes", "doesNotInclude"],
    title: "Alt text",
    type: "string",
    value: ""
  },
  creditLine: {
    assetTypes: ["file", "image"],
    field: "creditLine",
    name: "creditLine",
    operatorType: "empty",
    operatorTypes: ["empty", "notEmpty", null, "includes", "doesNotInclude"],
    title: "Credit",
    type: "string",
    value: ""
  },
  description: {
    assetTypes: ["file", "image"],
    field: "description",
    name: "description",
    operatorType: "empty",
    operatorTypes: ["empty", "notEmpty", null, "includes", "doesNotInclude"],
    title: "Description",
    type: "string",
    value: ""
  },
  fileName: {
    assetTypes: ["file", "image"],
    field: "originalFilename",
    name: "filename",
    operatorType: "includes",
    operatorTypes: ["includes", "doesNotInclude"],
    title: "File name",
    type: "string",
    value: ""
  },
  height: {
    assetTypes: ["image"],
    field: "metadata.dimensions.height",
    name: "height",
    operatorType: "greaterThan",
    operatorTypes: [
      "greaterThan",
      "greaterThanOrEqualTo",
      "lessThan",
      "lessThanOrEqualTo",
      null,
      "equalTo"
    ],
    title: "Height",
    type: "number",
    value: 400
  },
  inCurrentDocument: {
    assetTypes: ["file", "image"],
    name: "inCurrentDocument",
    operatorType: "is",
    options: [
      {
        name: "true",
        title: "True",
        value: groq__default.default`_id in $documentAssetIds`
      },
      {
        name: "false",
        title: "False",
        value: groq__default.default`!(_id in $documentAssetIds)`
      }
    ],
    selectOnly: !0,
    title: "In use in current document",
    type: "select",
    value: "true"
  },
  inUse: {
    assetTypes: ["file", "image"],
    name: "inUse",
    operatorType: "is",
    options: [
      {
        name: "true",
        title: "True",
        value: groq__default.default`count(*[references(^._id)]) > 0`
      },
      {
        name: "false",
        title: "False",
        value: groq__default.default`count(*[references(^._id)]) == 0`
      }
    ],
    title: "In use",
    type: "select",
    value: "true"
  },
  isOpaque: {
    assetTypes: ["image"],
    field: "metadata.isOpaque",
    name: "isOpaque",
    operatorType: "equalTo",
    options: [
      {
        name: "true",
        title: "True",
        value: "false"
      },
      {
        name: "false",
        title: "False",
        value: "true"
      }
    ],
    title: "Has transparency",
    type: "select",
    value: "true"
  },
  orientation: {
    assetTypes: ["image"],
    name: "orientation",
    operatorType: "is",
    operatorTypes: ["is", "isNot"],
    options: [
      {
        name: "portrait",
        title: "Portrait",
        value: "metadata.dimensions.aspectRatio < 1"
      },
      {
        name: "landscape",
        title: "Landscape",
        value: "metadata.dimensions.aspectRatio > 1"
      },
      {
        name: "square",
        title: "Square",
        value: "metadata.dimensions.aspectRatio == 1"
      }
    ],
    title: "Orientation",
    type: "select",
    value: "portrait"
  },
  size: {
    assetTypes: ["file", "image"],
    field: "size",
    modifier: "kb",
    modifiers: [
      {
        name: "kb",
        title: "KB",
        fieldModifier: (fieldName) => `round(${fieldName} / 1000)`
      },
      {
        name: "mb",
        title: "MB",
        fieldModifier: (fieldName) => `round(${fieldName} / 1000000)`
      }
    ],
    name: "size",
    operatorType: "greaterThan",
    operatorTypes: [
      "greaterThan",
      "greaterThanOrEqualTo",
      "lessThan",
      "lessThanOrEqualTo",
      null,
      "equalTo"
    ],
    title: "File size",
    type: "number",
    value: 0
  },
  tag: {
    assetTypes: ["file", "image"],
    field: "opt.media.tags",
    name: "tag",
    operatorType: "references",
    operatorTypes: ["references", "doesNotReference", null, "empty", "notEmpty"],
    title: "Tags",
    type: "searchable"
  },
  title: {
    assetTypes: ["file", "image"],
    field: "title",
    name: "title",
    operatorType: "empty",
    operatorTypes: ["empty", "notEmpty", null, "includes", "doesNotInclude"],
    title: "Title",
    type: "string",
    value: ""
  },
  type: {
    assetTypes: ["file", "image"],
    name: "type",
    operatorType: "is",
    operatorTypes: ["is", "isNot"],
    options: [
      {
        name: "image",
        title: "Image",
        value: 'mimeType match "image*"'
      },
      {
        name: "video",
        title: "Video",
        value: 'mimeType match "video*"'
      },
      {
        name: "audio",
        title: "Audio",
        value: 'mimeType match "audio*"'
      },
      {
        name: "pdf",
        title: "PDF",
        value: 'mimeType == "application/pdf"'
      }
    ],
    title: "File type",
    type: "select",
    value: "image"
  },
  width: {
    assetTypes: ["image"],
    field: "metadata.dimensions.width",
    name: "width",
    operatorType: "greaterThan",
    operatorTypes: [
      "greaterThan",
      "greaterThanOrEqualTo",
      "lessThan",
      "lessThanOrEqualTo",
      null,
      "equalTo"
    ],
    title: "Width",
    type: "number",
    value: 400
  }
}, operators = {
  doesNotInclude: {
    fn: (value, field) => value ? `!(${field} match '*${value}*')` : void 0,
    label: "does not include"
  },
  doesNotReference: {
    fn: (value, _field) => value ? `!references('${value}')` : void 0,
    label: "does not include"
  },
  empty: {
    fn: (_value, field) => `!defined(${field})`,
    hideInput: !0,
    label: "is empty"
  },
  equalTo: {
    fn: (value, field) => value ? `${field} == ${value}` : void 0,
    label: "is equal to"
  },
  greaterThan: {
    fn: (value, field) => value ? `${field} > ${value}` : void 0,
    label: "is greater than"
  },
  greaterThanOrEqualTo: {
    fn: (value, field) => value ? `${field} >= ${value}` : void 0,
    label: "is greater than or equal to"
  },
  includes: {
    fn: (value, field) => value ? `${field} match '*${value}*'` : void 0,
    label: "includes"
  },
  is: {
    fn: (value, _field) => `${value}`,
    label: "is"
  },
  isNot: {
    fn: (value, _field) => `!(${value})`,
    label: "is not"
  },
  lessThan: {
    fn: (value, field) => value ? `${field} < ${value}` : void 0,
    label: "is less than"
  },
  lessThanOrEqualTo: {
    fn: (value, field) => value ? `${field} <= ${value}` : void 0,
    label: "is less than or equal to"
  },
  notEmpty: {
    fn: (_value, field) => `defined(${field})`,
    hideInput: !0,
    label: "is not empty"
  },
  references: {
    fn: (value, _field) => value ? `references('${value}')` : void 0,
    label: "includes"
  }
}, SUPPORTED_ASSET_TYPES = [
  "file",
  "image"
], ORDER_OPTIONS = [
  {
    direction: "desc",
    field: "_createdAt"
  },
  {
    direction: "asc",
    field: "_createdAt"
  },
  // Divider
  null,
  {
    direction: "desc",
    field: "_updatedAt"
  },
  {
    direction: "asc",
    field: "_updatedAt"
  },
  // Divider
  null,
  {
    direction: "asc",
    field: "originalFilename"
  },
  {
    direction: "desc",
    field: "originalFilename"
  },
  // Divider
  null,
  {
    direction: "desc",
    field: "size"
  },
  {
    direction: "asc",
    field: "size"
  }
], FACETS = [
  inputs.tag,
  divider,
  inputs.inUse,
  inputs.inCurrentDocument,
  divider,
  inputs.title,
  inputs.altText,
  inputs.creditLine,
  inputs.description,
  divider,
  inputs.isOpaque,
  divider,
  inputs.fileName,
  inputs.size,
  inputs.type,
  divider,
  inputs.orientation,
  inputs.width,
  inputs.height
], GRID_TEMPLATE_COLUMNS = {
  SMALL: "3rem 100px auto 1.5rem",
  LARGE: "3rem 100px auto 5.5rem 5.5rem 3.5rem 8.5rem 4.75rem 2rem"
}, PANEL_HEIGHT = 32, TAG_DOCUMENT_NAME = "media.tag", TAGS_PANEL_WIDTH = 250, AssetSourceDispatchContext = react.createContext(void 0), AssetBrowserDispatchProvider = (props) => {
  const { children, onSelect } = props, contextValue = {
    onSelect
  };
  return /* @__PURE__ */ jsxRuntime.jsx(AssetSourceDispatchContext.Provider, { value: contextValue, children });
}, useAssetSourceActions = () => {
  const context = react.useContext(AssetSourceDispatchContext);
  if (context === void 0)
    throw new Error("useAssetSourceActions must be used within an AssetSourceDispatchProvider");
  return context;
}, useVersionedClient = () => sanity.useClient({ apiVersion: "2022-10-01" }), ORDER_DICTIONARY = {
  _createdAt: {
    asc: "Last created: Oldest first",
    desc: "Last created: Newest first"
  },
  _updatedAt: {
    asc: "Last updated: Oldest first",
    desc: "Last updated: Newest first"
  },
  mimeType: {
    asc: "MIME type: A to Z",
    desc: "MIME type: Z to A"
  },
  originalFilename: {
    asc: "File name: A to Z",
    desc: "File name: Z to A"
  },
  size: {
    asc: "File size: Smallest first",
    desc: "File size: Largest first"
  }
}, getOrderTitle = (field, direction) => ORDER_DICTIONARY[field][direction], debugThrottle = (throttled) => function(source) {
  return rxjs.iif(
    () => !!throttled,
    source.pipe(
      operators$1.delay(3e3),
      operators$1.mergeMap((v) => Math.random() > 0.5 ? rxjs.throwError({
        message: "Test error",
        statusCode: 500
      }) : rxjs.of(v))
    ),
    source
  );
}, constructFilter = ({
  assetTypes,
  searchFacets,
  searchQuery
}) => {
  const documentAssetTypes = assetTypes.map((type) => `sanity.${type}Asset`), baseFilter = groq__default.default`
    _type in ${JSON.stringify(documentAssetTypes)} && !(_id in path("drafts.**"))
  `, searchFacetFragments = searchFacets.reduce((acc, facet) => {
    if (facet.type === "number") {
      const { field, modifier, modifiers, operatorType, value } = facet, operator = operators[operatorType], currentModifier = modifiers?.find((m) => m.name === modifier), facetField = currentModifier?.fieldModifier ? currentModifier.fieldModifier(field) : field, fragment = operator.fn(value, facetField);
      fragment && acc.push(fragment);
    }
    if (facet.type === "searchable") {
      const { field, operatorType, value } = facet, fragment = operators[operatorType].fn(value?.value, field);
      fragment && acc.push(fragment);
    }
    if (facet.type === "select") {
      const { field, operatorType, options, value } = facet, operator = operators[operatorType], currentOptionValue = options?.find((l) => l.name === value)?.value, fragment = operator.fn(currentOptionValue, field);
      fragment && acc.push(fragment);
    }
    if (facet.type === "string") {
      const { field, operatorType, value } = facet, fragment = operators[operatorType].fn(value, field);
      fragment && acc.push(fragment);
    }
    return acc;
  }, []);
  return [
    // Base filter
    baseFilter,
    // Search query (if present)
    // NOTE: Currently this only searches direct fields on sanity.fileAsset/sanity.imageAsset and NOT referenced tags
    // It's possible to add this by adding the following line to the searchQuery, but it's quite slow
    // references(*[_type == "media.tag" && name.current == "${searchQuery.trim()}"]._id)
    ...searchQuery ? [
      groq__default.default`[_id, altText, assetId, creditLine, description, originalFilename, title, url] match '*${searchQuery.trim()}*'`
    ] : [],
    // Search facets
    ...searchFacetFragments
  ].join(" && ");
}, checkTagName = (client, name) => function(source) {
  return source.pipe(
    operators$1.mergeMap(() => rxjs.from(
      client.fetch(groq__default.default`count(*[_type == "${TAG_DOCUMENT_NAME}" && name.current == $name])`, {
        name
      })
    )),
    operators$1.mergeMap((existingTagCount) => existingTagCount > 0 ? rxjs.throwError({
      message: "Tag already exists",
      statusCode: 409
    }) : rxjs.of(!0))
  );
}, getTagSelectOptions = (tags) => tags.reduce((acc, val) => {
  const tag = val?.tag;
  return tag && acc.push({
    label: tag?.name?.current,
    value: tag?._id
  }), acc;
}, []), ASSETS_ACTIONS = {
  tagsAddComplete: toolkit.createAction(
    "actions/tagsAddComplete",
    function({ assets, tag }) {
      return { payload: { assets, tag } };
    }
  ),
  tagsAddError: toolkit.createAction(
    "actions/tagsAddError",
    function({ assets, error, tag }) {
      return { payload: { assets, error, tag } };
    }
  ),
  tagsAddRequest: toolkit.createAction(
    "actions/tagsAddRequest",
    function({ assets, tag }) {
      return { payload: { assets, tag } };
    }
  ),
  tagsRemoveComplete: toolkit.createAction(
    "actions/tagsRemoveComplete",
    function({ assets, tag }) {
      return { payload: { assets, tag } };
    }
  ),
  tagsRemoveError: toolkit.createAction(
    "actions/tagsRemoveError",
    function({ assets, error, tag }) {
      return { payload: { assets, error, tag } };
    }
  ),
  tagsRemoveRequest: toolkit.createAction(
    "actions/tagsRemoveRequest",
    function({ assets, tag }) {
      return { payload: { assets, tag } };
    }
  )
}, DIALOG_ACTIONS = {
  showTagCreate: toolkit.createAction("dialog/showTagCreate"),
  showTagEdit: toolkit.createAction("dialog/showTagEdit", function({ tagId }) {
    return {
      payload: { tagId }
    };
  })
}, initialState$7 = {
  allIds: [],
  byIds: {},
  creating: !1,
  creatingError: void 0,
  fetchCount: -1,
  fetching: !1,
  fetchingError: void 0,
  panelVisible: !0
}, tagsSlice = toolkit.createSlice({
  name: "tags",
  initialState: initialState$7,
  extraReducers: (builder) => {
    builder.addCase(DIALOG_ACTIONS.showTagCreate, (state) => {
      delete state.creatingError;
    }).addCase(DIALOG_ACTIONS.showTagEdit, (state, action) => {
      const { tagId } = action.payload;
      delete state.byIds[tagId].error;
    }).addMatcher(
      toolkit.isAnyOf(
        ASSETS_ACTIONS.tagsAddComplete,
        ASSETS_ACTIONS.tagsAddError,
        ASSETS_ACTIONS.tagsRemoveComplete,
        ASSETS_ACTIONS.tagsRemoveError
      ),
      (state, action) => {
        const { tag } = action.payload;
        state.byIds[tag._id].updating = !1;
      }
    ).addMatcher(
      toolkit.isAnyOf(ASSETS_ACTIONS.tagsAddRequest, ASSETS_ACTIONS.tagsRemoveRequest),
      (state, action) => {
        const { tag } = action.payload;
        state.byIds[tag._id].updating = !0;
      }
    );
  },
  reducers: {
    createComplete(state, action) {
      const { tag } = action.payload;
      state.creating = !1, state.allIds.includes(tag._id) || state.allIds.push(tag._id), state.byIds[tag._id] = {
        _type: "tag",
        picked: !1,
        tag,
        updating: !1
      };
    },
    createError(state, action) {
      state.creating = !1, state.creatingError = action.payload.error;
    },
    createRequest(state, _action) {
      state.creating = !0, delete state.creatingError;
    },
    deleteComplete(state, action) {
      const { tagId } = action.payload, deleteIndex = state.allIds.indexOf(tagId);
      deleteIndex >= 0 && state.allIds.splice(deleteIndex, 1), delete state.byIds[tagId];
    },
    deleteError(state, action) {
      const { error, tag } = action.payload, tagId = tag?._id;
      state.byIds[tagId].error = error, state.byIds[tagId].updating = !1;
    },
    deleteRequest(state, action) {
      const tagId = action.payload?.tag?._id;
      state.byIds[tagId].picked = !1, state.byIds[tagId].updating = !0, Object.keys(state.byIds).forEach((key) => {
        delete state.byIds[key].error;
      });
    },
    fetchComplete(state, action) {
      const { tags } = action.payload;
      tags?.forEach((tag) => {
        state.allIds.push(tag._id), state.byIds[tag._id] = {
          _type: "tag",
          picked: !1,
          tag,
          updating: !1
        };
      }), state.fetching = !1, state.fetchCount = tags.length || 0, delete state.fetchingError;
    },
    fetchError(state, action) {
      const { error } = action.payload;
      state.fetching = !1, state.fetchingError = error;
    },
    fetchRequest: {
      reducer: (state, _action) => {
        state.fetching = !0, delete state.fetchingError;
      },
      prepare: () => ({ payload: { query: groq__default.default`
          {
            "items": *[
              _type == "${TAG_DOCUMENT_NAME}"
              && !(_id in path("drafts.**"))
            ] {
              _createdAt,
              _updatedAt,
              _id,
              _rev,
              _type,
              name
            } | order(name.current asc),
          }
        ` } })
    },
    // Queue batch tag creation
    listenerCreateQueue(_state, _action) {
    },
    // Apply created tags (via sanity real-time events)
    listenerCreateQueueComplete(state, action) {
      const { tags } = action.payload;
      tags?.forEach((tag) => {
        state.byIds[tag._id] = {
          _type: "tag",
          picked: !1,
          tag,
          updating: !1
        }, state.allIds.includes(tag._id) || state.allIds.push(tag._id);
      });
    },
    // Queue batch tag deletion
    listenerDeleteQueue(_state, _action) {
    },
    // Apply deleted tags (via sanity real-time events)
    listenerDeleteQueueComplete(state, action) {
      const { tagIds } = action.payload;
      tagIds?.forEach((tagId) => {
        const deleteIndex = state.allIds.indexOf(tagId);
        deleteIndex >= 0 && state.allIds.splice(deleteIndex, 1), delete state.byIds[tagId];
      });
    },
    // Queue batch tag updates
    listenerUpdateQueue(_state, _action) {
    },
    // Apply updated tags (via sanity real-time events)
    listenerUpdateQueueComplete(state, action) {
      const { tags } = action.payload;
      tags?.forEach((tag) => {
        state.byIds[tag._id] && (state.byIds[tag._id].tag = tag);
      });
    },
    // Set tag panel visibility
    panelVisibleSet(state, action) {
      const { panelVisible } = action.payload;
      state.panelVisible = panelVisible;
    },
    // Sort all tags by name
    sort(state) {
      state.allIds.sort((a, b) => {
        const tagA = state.byIds[a].tag.name.current, tagB = state.byIds[b].tag.name.current;
        return tagA < tagB ? -1 : tagA > tagB ? 1 : 0;
      });
    },
    updateComplete(state, action) {
      const { tag } = action.payload;
      state.byIds[tag._id].tag = tag, state.byIds[tag._id].updating = !1;
    },
    updateError(state, action) {
      const { error, tag } = action.payload, tagId = tag?._id;
      state.byIds[tagId].error = error, state.byIds[tagId].updating = !1;
    },
    updateRequest(state, action) {
      const { tag } = action.payload;
      state.byIds[tag?._id].updating = !0;
    }
  }
}), tagsCreateEpic = (action$, state$, { client }) => action$.pipe(
  operators$1.filter(tagsSlice.actions.createRequest.match),
  operators$1.withLatestFrom(state$),
  operators$1.mergeMap(([action, state]) => {
    const { assetId, name } = action.payload;
    return rxjs.of(action).pipe(
      debugThrottle(state.debug.badConnection),
      checkTagName(client, name),
      operators$1.mergeMap(
        () => client.observable.create({
          _type: TAG_DOCUMENT_NAME,
          name: {
            _type: "slug",
            current: name
          }
        })
      ),
      operators$1.mergeMap((result) => rxjs.of(tagsSlice.actions.createComplete({ assetId, tag: result }))),
      operators$1.catchError(
        (error) => rxjs.of(
          tagsSlice.actions.createError({
            error: {
              message: error?.message || "Internal error",
              statusCode: error?.statusCode || 500
            },
            name
          })
        )
      )
    );
  })
), tagsDeleteEpic = (action$, state$, { client }) => action$.pipe(
  operators$1.filter(tagsSlice.actions.deleteRequest.match),
  operators$1.withLatestFrom(state$),
  operators$1.mergeMap(([action, state]) => {
    const { tag } = action.payload;
    return rxjs.of(action).pipe(
      // Optionally throttle
      debugThrottle(state.debug.badConnection),
      // Fetch assets which reference this tag
      operators$1.mergeMap(
        () => client.observable.fetch(
          groq__default.default`*[
              _type in ["sanity.fileAsset", "sanity.imageAsset"]
              && references(*[_type == "media.tag" && name.current == $tagName]._id)
            ] {
              _id,
              _rev,
              opt
            }`,
          { tagName: tag.name.current }
        )
      ),
      // Create transaction which remove tag references from all matched assets and delete tag
      operators$1.mergeMap((assets) => {
        const transaction = assets.map((asset) => ({
          id: asset._id,
          patch: {
            // this will cause the transaction to fail if the document has been modified since it was fetched.
            ifRevisionID: asset._rev,
            unset: [`opt.media.tags[_ref == "${tag._id}"]`]
          }
        })).reduce(
          (tx, patch) => tx.patch(patch.id, patch.patch),
          client.transaction()
        );
        return transaction.delete(tag._id), rxjs.from(transaction.commit());
      }),
      // Dispatch complete action
      operators$1.mergeMap(() => rxjs.of(tagsSlice.actions.deleteComplete({ tagId: tag._id }))),
      operators$1.catchError(
        (error) => rxjs.of(
          tagsSlice.actions.deleteError({
            error: {
              message: error?.message || "Internal error",
              statusCode: error?.statusCode || 500
            },
            tag
          })
        )
      )
    );
  })
), tagsFetchEpic = (action$, state$, { client }) => action$.pipe(
  operators$1.filter(tagsSlice.actions.fetchRequest.match),
  operators$1.withLatestFrom(state$),
  operators$1.switchMap(([action, state]) => {
    const { query } = action.payload;
    return rxjs.of(action).pipe(
      // Optionally throttle
      debugThrottle(state.debug.badConnection),
      // Fetch tags
      operators$1.mergeMap(
        () => client.observable.fetch(query)
      ),
      // Dispatch complete action
      operators$1.mergeMap((result) => {
        const { items } = result;
        return rxjs.of(tagsSlice.actions.fetchComplete({ tags: items }));
      }),
      operators$1.catchError(
        (error) => rxjs.of(
          tagsSlice.actions.fetchError({
            error: {
              message: error?.message || "Internal error",
              statusCode: error?.statusCode || 500
            }
          })
        )
      )
    );
  })
), tagsListenerCreateQueueEpic = (action$) => action$.pipe(
  operators$1.filter(tagsSlice.actions.listenerCreateQueue.match),
  operators$1.bufferTime(2e3),
  operators$1.filter((actions) => actions.length > 0),
  operators$1.mergeMap((actions) => {
    const tags = actions?.map((action) => action.payload.tag);
    return rxjs.of(tagsSlice.actions.listenerCreateQueueComplete({ tags }));
  })
), tagsListenerDeleteQueueEpic = (action$) => action$.pipe(
  operators$1.filter(tagsSlice.actions.listenerDeleteQueue.match),
  operators$1.bufferTime(2e3),
  operators$1.filter((actions) => actions.length > 0),
  operators$1.mergeMap((actions) => {
    const tagIds = actions?.map((action) => action.payload.tagId);
    return rxjs.of(tagsSlice.actions.listenerDeleteQueueComplete({ tagIds }));
  })
), tagsListenerUpdateQueueEpic = (action$) => action$.pipe(
  operators$1.filter(tagsSlice.actions.listenerUpdateQueue.match),
  operators$1.bufferTime(2e3),
  operators$1.filter((actions) => actions.length > 0),
  operators$1.mergeMap((actions) => {
    const tags = actions?.map((action) => action.payload.tag);
    return rxjs.of(tagsSlice.actions.listenerUpdateQueueComplete({ tags }));
  })
), tagsSortEpic = (action$) => action$.pipe(
  reduxObservable.ofType(
    tagsSlice.actions.listenerCreateQueueComplete.type,
    tagsSlice.actions.listenerUpdateQueueComplete.type
  ),
  operators$1.bufferTime(1e3),
  operators$1.filter((actions) => actions.length > 0),
  operators$1.mergeMap(() => rxjs.of(tagsSlice.actions.sort()))
), tagsUpdateEpic = (action$, state$, { client }) => action$.pipe(
  operators$1.filter(tagsSlice.actions.updateRequest.match),
  operators$1.withLatestFrom(state$),
  operators$1.mergeMap(([action, state]) => {
    const { closeDialogId, formData, tag } = action.payload;
    return rxjs.of(action).pipe(
      // Optionally throttle
      debugThrottle(state.debug.badConnection),
      // Check if tag name is available, throw early if not
      checkTagName(client, formData?.name?.current),
      // Patch document (Update tag)
      operators$1.mergeMap(
        () => rxjs.from(
          client.patch(tag._id).set({ name: { _type: "slug", current: formData?.name.current } }).commit()
        )
      ),
      // Dispatch complete action
      operators$1.mergeMap((updatedTag) => rxjs.of(
        tagsSlice.actions.updateComplete({
          closeDialogId,
          tag: updatedTag
        })
      )),
      operators$1.catchError(
        (error) => rxjs.of(
          tagsSlice.actions.updateError({
            error: {
              message: error?.message || "Internal error",
              statusCode: error?.statusCode || 500
            },
            tag
          })
        )
      )
    );
  })
), selectTagsByIds = (state) => state.tags.byIds, selectTagsAllIds = (state) => state.tags.allIds, selectTags = toolkit.createSelector(
  [selectTagsByIds, selectTagsAllIds],
  (byIds, allIds) => allIds.map((id) => byIds[id])
), selectTagById = toolkit.createSelector(
  [selectTagsByIds, (_state, tagId) => tagId],
  (byIds, tagId) => byIds[tagId]
), selectTagSelectOptions = (asset) => (state) => {
  const tags = asset?.opt?.media?.tags?.reduce((acc, v) => {
    const tagItem = state.tags.byIds[v._ref];
    return tagItem?.tag && acc.push(tagItem), acc;
  }, []);
  return tags && tags?.length > 0 ? getTagSelectOptions(tags) : null;
}, tagsActions = { ...tagsSlice.actions };
var tagsReducer = tagsSlice.reducer;
const initialState$6 = {
  facets: [],
  query: ""
}, searchSlice = toolkit.createSlice({
  name: "search",
  initialState: initialState$6,
  reducers: {
    // Add search facet
    facetsAdd(state, action) {
      state.facets.push({ ...action.payload.facet, id: uuid.uuid() });
    },
    // Clear all search facets
    facetsClear(state) {
      state.facets = [];
    },
    // Remove search facet by name
    facetsRemoveByName(state, action) {
      state.facets = state.facets.filter((facet) => facet.name !== action.payload.facetName);
    },
    // Remove search facet by name
    facetsRemoveByTag(state, action) {
      state.facets = state.facets.filter(
        (facet) => !(facet.name === "tag" && facet.type === "searchable" && (facet.operatorType === "references" || facet.operatorType === "doesNotReference") && facet.value?.value === action.payload.tagId)
      );
    },
    // Remove search facet by name
    facetsRemoveById(state, action) {
      state.facets = state.facets.filter((facet) => facet.id !== action.payload.facetId);
    },
    // Update an existing search facet
    facetsUpdate(state, action) {
      const { modifier, name, operatorType, value } = action.payload, facet = state.facets.find((f) => f.name === name);
      facet && (facet.type === "number" && modifier && (facet.modifier = modifier), operatorType && (facet.operatorType = operatorType), typeof value < "u" && (facet.value = value), state.facets = state.facets.filter((f) => f.name !== facet.name || f.id === facet.id));
    },
    // Update an existing search facet
    facetsUpdateById(state, action) {
      const { modifier, id, operatorType, value } = action.payload;
      state.facets.forEach((facet, index) => {
        facet.id === id && (facet.type === "number" && modifier && (facet.modifier = modifier), operatorType && (facet.operatorType = operatorType), typeof value < "u" && (state.facets[index].value = value));
      });
    },
    // Update existing search query
    querySet(state, action) {
      state.query = action.payload?.searchQuery;
    }
  }
}), searchFacetTagUpdateEpic = (action$, state$) => action$.pipe(
  operators$1.filter(tagsActions.updateComplete.match),
  operators$1.withLatestFrom(state$),
  operators$1.mergeMap(([action, state]) => {
    const { tag } = action.payload, currentSearchFacetTag = state.search.facets?.find((facet) => facet.name === "tag"), tagItem = state.tags.byIds[tag._id];
    return currentSearchFacetTag?.type === "searchable" && currentSearchFacetTag.value?.value === tag._id ? rxjs.of(
      searchSlice.actions.facetsUpdate({
        name: "tag",
        value: {
          label: tagItem?.tag?.name?.current,
          value: tagItem?.tag?._id
        }
      })
    ) : rxjs.EMPTY;
  })
), selectIsSearchFacetTag = toolkit.createSelector(
  [
    (state) => state.search.facets,
    (_state, tagId) => tagId
  ],
  (searchFacets, tagId) => searchFacets.some(
    (facet) => facet.name === "tag" && facet.type === "searchable" && (facet.operatorType === "references" || facet.operatorType === "doesNotReference") && facet.value?.value === tagId
  )
), searchActions = { ...searchSlice.actions };
var searchReducer = searchSlice.reducer;
const UPLOADS_ACTIONS = {
  uploadComplete: toolkit.createAction(
    "uploads/uploadComplete",
    function({ asset }) {
      return {
        payload: { asset }
      };
    }
  )
}, defaultOrder = ORDER_OPTIONS[0], initialState$5 = {
  allIds: [],
  assetTypes: [],
  byIds: {},
  fetchCount: -1,
  fetching: !1,
  fetchingError: void 0,
  lastPicked: void 0,
  order: {
    direction: defaultOrder.direction,
    field: defaultOrder.field,
    title: getOrderTitle(defaultOrder.field, defaultOrder.direction)
  },
  pageIndex: 0,
  pageSize: 100,
  // totalCount: -1,
  view: "grid"
}, assetsSlice = toolkit.createSlice({
  name: "assets",
  initialState: initialState$5,
  extraReducers: (builder) => {
    builder.addCase(UPLOADS_ACTIONS.uploadComplete, (state, action) => {
      const { asset } = action.payload;
      state.byIds[asset._id] = {
        _type: "asset",
        asset,
        picked: !1,
        updating: !1
      };
    }).addCase(ASSETS_ACTIONS.tagsAddComplete, (state, action) => {
      const { assets } = action.payload;
      assets.forEach((asset) => {
        state.byIds[asset.asset._id].updating = !1;
      });
    }).addCase(ASSETS_ACTIONS.tagsAddError, (state, action) => {
      const { assets } = action.payload;
      assets.forEach((asset) => {
        state.byIds[asset.asset._id].updating = !1;
      });
    }).addCase(ASSETS_ACTIONS.tagsAddRequest, (state, action) => {
      const { assets } = action.payload;
      assets.forEach((asset) => {
        state.byIds[asset.asset._id].updating = !0;
      });
    }).addCase(ASSETS_ACTIONS.tagsRemoveComplete, (state, action) => {
      const { assets } = action.payload;
      assets.forEach((asset) => {
        state.byIds[asset.asset._id].updating = !1;
      });
    }).addCase(ASSETS_ACTIONS.tagsRemoveError, (state, action) => {
      const { assets } = action.payload;
      assets.forEach((asset) => {
        state.byIds[asset.asset._id].updating = !1;
      });
    }).addCase(ASSETS_ACTIONS.tagsRemoveRequest, (state, action) => {
      const { assets } = action.payload;
      assets.forEach((asset) => {
        state.byIds[asset.asset._id].updating = !0;
      });
    });
  },
  reducers: {
    // Clear asset order
    clear(state) {
      state.allIds = [];
    },
    // Remove assets and update page index
    deleteComplete(state, action) {
      const { assetIds } = action.payload;
      assetIds?.forEach((id) => {
        const deleteIndex = state.allIds.indexOf(id);
        deleteIndex >= 0 && state.allIds.splice(deleteIndex, 1), delete state.byIds[id];
      }), state.pageIndex = Math.floor(state.allIds.length / state.pageSize) - 1;
    },
    deleteError(state, action) {
      const { assetIds, error } = action.payload, itemErrors = error?.response?.body?.error?.items?.map(
        (item) => item.error
      );
      assetIds?.forEach((id) => {
        state.byIds[id].updating = !1;
      }), itemErrors?.forEach((item) => {
        state.byIds[item.id].error = item.description;
      });
    },
    deleteRequest(state, action) {
      const { assets } = action.payload;
      assets.forEach((asset) => {
        state.byIds[asset?._id].updating = !0;
      }), Object.keys(state.byIds).forEach((key) => {
        delete state.byIds[key].error;
      });
    },
    fetchComplete(state, action) {
      const assets = action.payload?.assets || [];
      assets && assets.forEach((asset) => {
        state.allIds.includes(asset._id) || state.allIds.push(asset._id), state.byIds[asset._id] = {
          _type: "asset",
          asset,
          picked: !1,
          updating: !1
        };
      }), state.fetching = !1, state.fetchCount = assets.length || 0, delete state.fetchingError;
    },
    fetchError(state, action) {
      const error = action.payload;
      state.fetching = !1, state.fetchingError = error;
    },
    fetchRequest: {
      reducer: (state, _action) => {
        state.fetching = !0, delete state.fetchingError;
      },
      prepare: ({
        params = {},
        queryFilter,
        selector = "",
        sort = groq__default.default`order(_updatedAt desc)`
      }) => {
        const query = groq__default.default`
          {
            "items": *[${queryFilter}] {
              _id,
              _type,
              _createdAt,
              _updatedAt,
              altText,
              creditLine,
              description,
              extension,
              metadata {
                dimensions,
                exif,
                isOpaque,
              },
              mimeType,
              opt {
                media
              },
              originalFilename,
              size,
              source {
                name,
                id,
                url,
              },
              title,
              url
            } ${sort || selector ? "|" : ""} ${sort} ${selector},
          }
        `;
        return { payload: { params, query } };
      }
    },
    insertUploads(state, action) {
      const { results } = action.payload;
      Object.entries(results).forEach(([hash, assetId]) => {
        assetId && !state.allIds.includes(hash) && state.allIds.push(assetId);
      });
    },
    listenerCreateQueue(_state, _action) {
    },
    listenerCreateQueueComplete(state, action) {
      const { assets } = action.payload;
      assets?.forEach((asset) => {
        state.byIds[asset?._id]?.asset && (state.byIds[asset._id].asset = asset);
      });
    },
    listenerDeleteQueue(_state, _action) {
    },
    listenerDeleteQueueComplete(state, action) {
      const { assetIds } = action.payload;
      assetIds?.forEach((assetId) => {
        const deleteIndex = state.allIds.indexOf(assetId);
        deleteIndex >= 0 && state.allIds.splice(deleteIndex, 1), delete state.byIds[assetId];
      });
    },
    listenerUpdateQueue(_state, _action) {
    },
    listenerUpdateQueueComplete(state, action) {
      const { assets } = action.payload;
      assets?.forEach((asset) => {
        state.byIds[asset?._id]?.asset && (state.byIds[asset._id].asset = asset);
      });
    },
    loadNextPage() {
    },
    loadPageIndex(state, action) {
      state.pageIndex = action.payload.pageIndex;
    },
    orderSet(state, action) {
      state.order = action.payload?.order, state.pageIndex = 0;
    },
    pick(state, action) {
      const { assetId, picked } = action.payload;
      state.byIds[assetId].picked = picked, state.lastPicked = picked ? assetId : void 0;
    },
    pickAll(state) {
      state.allIds.forEach((id) => {
        state.byIds[id].picked = !0;
      });
    },
    pickClear(state) {
      state.lastPicked = void 0, Object.values(state.byIds).forEach((asset) => {
        state.byIds[asset.asset._id].picked = !1;
      });
    },
    pickRange(state, action) {
      const startIndex = state.allIds.findIndex((id) => id === action.payload.startId), endIndex = state.allIds.findIndex((id) => id === action.payload.endId), indices = [startIndex, endIndex].sort((a, b) => a - b);
      state.allIds.slice(indices[0], indices[1] + 1).forEach((key) => {
        state.byIds[key].picked = !0;
      }), state.lastPicked = state.allIds[endIndex];
    },
    sort(state) {
      state.allIds.sort((a, b) => {
        const tagA = state.byIds[a].asset[state.order.field], tagB = state.byIds[b].asset[state.order.field];
        return tagA < tagB ? state.order.direction === "asc" ? -1 : 1 : tagA > tagB ? state.order.direction === "asc" ? 1 : -1 : 0;
      });
    },
    updateComplete(state, action) {
      const { asset } = action.payload;
      state.byIds[asset._id].updating = !1, state.byIds[asset._id].asset = asset;
    },
    updateError(state, action) {
      const { asset, error } = action.payload, assetId = asset?._id;
      state.byIds[assetId].error = error.message, state.byIds[assetId].updating = !1;
    },
    updateRequest(state, action) {
      const assetId = action.payload?.asset?._id;
      state.byIds[assetId].updating = !0;
    },
    viewSet(state, action) {
      state.view = action.payload?.view;
    }
  }
}), assetsDeleteEpic = (action$, _state$, { client }) => action$.pipe(
  operators$1.filter(assetsActions.deleteRequest.match),
  operators$1.mergeMap((action) => {
    const { assets } = action.payload, assetIds = assets.map((asset) => asset._id);
    return rxjs.of(assets).pipe(
      operators$1.mergeMap(
        () => client.observable.delete({
          query: groq__default.default`*[_id in ${JSON.stringify(assetIds)}]`
        })
      ),
      operators$1.mergeMap(() => rxjs.of(assetsActions.deleteComplete({ assetIds }))),
      operators$1.catchError((error) => rxjs.of(assetsActions.deleteError({ assetIds, error })))
    );
  })
), assetsFetchEpic = (action$, state$, { client }) => action$.pipe(
  operators$1.filter(assetsActions.fetchRequest.match),
  operators$1.withLatestFrom(state$),
  operators$1.switchMap(([action, state]) => {
    const params = action.payload?.params, query = action.payload?.query;
    return rxjs.of(action).pipe(
      debugThrottle(state.debug.badConnection),
      operators$1.mergeMap(
        () => client.observable.fetch(query, params)
      ),
      operators$1.mergeMap((result) => {
        const {
          items
          // totalCount
        } = result;
        return rxjs.of(assetsActions.fetchComplete({ assets: items }));
      }),
      operators$1.catchError(
        (error) => rxjs.of(
          assetsActions.fetchError({
            message: error?.message || "Internal error",
            statusCode: error?.statusCode || 500
          })
        )
      )
    );
  })
), assetsFetchPageIndexEpic = (action$, state$) => action$.pipe(
  operators$1.filter(assetsActions.loadPageIndex.match),
  operators$1.withLatestFrom(state$),
  operators$1.switchMap(([action, state]) => {
    const pageSize = state.assets.pageSize, start = action.payload.pageIndex * pageSize, end = start + pageSize, documentId = state?.selected.document?._id, documentAssetIds = state?.selected?.documentAssetIds, constructedFilter = constructFilter({
      assetTypes: state.assets.assetTypes,
      searchFacets: state.search.facets,
      searchQuery: state.search.query
    }), params = {
      ...documentId ? { documentId } : {},
      documentAssetIds
    };
    return rxjs.of(
      assetsActions.fetchRequest({
        params,
        queryFilter: constructedFilter,
        selector: groq__default.default`[${start}...${end}]`,
        sort: groq__default.default`order(${state.assets?.order?.field} ${state.assets?.order?.direction})`
      })
    );
  })
), assetsFetchNextPageEpic = (action$, state$) => action$.pipe(
  operators$1.filter(assetsActions.loadNextPage.match),
  operators$1.withLatestFrom(state$),
  operators$1.switchMap(
    ([_action, state]) => rxjs.of(assetsActions.loadPageIndex({ pageIndex: state.assets.pageIndex + 1 }))
  )
), assetsFetchAfterDeleteAllEpic = (action$, state$) => action$.pipe(
  operators$1.filter(assetsActions.deleteComplete.match),
  operators$1.withLatestFrom(state$),
  operators$1.switchMap(([_action, state]) => {
    if (state.assets.allIds.length === 0) {
      const nextPageIndex = Math.floor(state.assets.allIds.length / state.assets.pageSize);
      return rxjs.of(assetsActions.loadPageIndex({ pageIndex: nextPageIndex }));
    }
    return rxjs.EMPTY;
  })
), filterAssetWithoutTag = (tag) => (asset) => (asset?.asset?.opt?.media?.tags?.findIndex((t) => t._ref === tag?._id) ?? -1) < 0, patchOperationTagAppend = ({ tag }) => (patch) => patch.setIfMissing({ opt: {} }).setIfMissing({ "opt.media": {} }).setIfMissing({ "opt.media.tags": [] }).append("opt.media.tags", [{ _key: nanoid.nanoid(), _ref: tag?._id, _type: "reference", _weak: !0 }]), patchOperationTagUnset = ({ asset, tag }) => (patch) => patch.ifRevisionId(asset?.asset?._rev).unset([`opt.media.tags[_ref == "${tag._id}"]`]), assetsOrderSetEpic = (action$) => action$.pipe(
  operators$1.filter(assetsActions.orderSet.match),
  operators$1.mergeMap(() => rxjs.of(
    assetsActions.clear(),
    //
    assetsActions.loadPageIndex({ pageIndex: 0 })
  ))
), assetsSearchEpic = (action$) => action$.pipe(
  reduxObservable.ofType(
    searchActions.facetsAdd.type,
    searchActions.facetsClear.type,
    searchActions.facetsRemoveById.type,
    searchActions.facetsRemoveByName.type,
    searchActions.facetsRemoveByTag.type,
    searchActions.facetsUpdate.type,
    searchActions.facetsUpdateById.type,
    searchActions.querySet.type
  ),
  operators$1.debounceTime(400),
  operators$1.mergeMap(() => rxjs.of(
    assetsActions.clear(),
    //
    assetsActions.loadPageIndex({ pageIndex: 0 })
  ))
), assetsListenerCreateQueueEpic = (action$) => action$.pipe(
  operators$1.filter(assetsActions.listenerCreateQueue.match),
  operators$1.bufferTime(2e3),
  operators$1.filter((actions) => actions.length > 0),
  operators$1.mergeMap((actions) => {
    const assets = actions?.map((action) => action.payload.asset);
    return rxjs.of(assetsActions.listenerCreateQueueComplete({ assets }));
  })
), assetsListenerDeleteQueueEpic = (action$) => action$.pipe(
  operators$1.filter(assetsActions.listenerDeleteQueue.match),
  operators$1.bufferTime(2e3),
  operators$1.filter((actions) => actions.length > 0),
  operators$1.mergeMap((actions) => {
    const assetIds = actions?.map((action) => action.payload.assetId);
    return rxjs.of(assetsActions.listenerDeleteQueueComplete({ assetIds }));
  })
), assetsListenerUpdateQueueEpic = (action$) => action$.pipe(
  operators$1.filter(assetsActions.listenerUpdateQueue.match),
  operators$1.bufferTime(2e3),
  operators$1.filter((actions) => actions.length > 0),
  operators$1.mergeMap((actions) => {
    const assets = actions?.map((action) => action.payload.asset);
    return rxjs.of(assetsActions.listenerUpdateQueueComplete({ assets }));
  })
), assetsSortEpic = (action$) => action$.pipe(
  reduxObservable.ofType(
    assetsActions.insertUploads.type,
    assetsActions.listenerUpdateQueueComplete.type,
    assetsActions.updateComplete.type
  ),
  operators$1.mergeMap(() => rxjs.of(assetsActions.sort()))
), assetsTagsAddEpic = (action$, state$, { client }) => action$.pipe(
  operators$1.filter(ASSETS_ACTIONS.tagsAddRequest.match),
  operators$1.withLatestFrom(state$),
  operators$1.mergeMap(([action, state]) => {
    const { assets, tag } = action.payload;
    return rxjs.of(action).pipe(
      // Optionally throttle
      debugThrottle(state.debug.badConnection),
      // Add tag references to all picked assets
      operators$1.mergeMap(() => {
        const transaction = (selectAssetsPicked(state)?.filter(filterAssetWithoutTag(tag))).reduce(
          (tx, pickedAsset) => tx.patch(pickedAsset?.asset?._id, patchOperationTagAppend({ tag })),
          client.transaction()
        );
        return rxjs.from(transaction.commit());
      }),
      // Dispatch complete action
      operators$1.mergeMap(() => rxjs.of(ASSETS_ACTIONS.tagsAddComplete({ assets, tag }))),
      operators$1.catchError(
        (error) => rxjs.of(
          ASSETS_ACTIONS.tagsAddError({
            assets,
            error: {
              message: error?.message || "Internal error",
              statusCode: error?.statusCode || 500
            },
            tag
          })
        )
      )
    );
  })
), assetsTagsRemoveEpic = (action$, state$, { client }) => action$.pipe(
  operators$1.filter(ASSETS_ACTIONS.tagsRemoveRequest.match),
  operators$1.withLatestFrom(state$),
  operators$1.mergeMap(([action, state]) => {
    const { assets, tag } = action.payload;
    return rxjs.of(action).pipe(
      // Optionally throttle
      debugThrottle(state.debug.badConnection),
      // Remove tag references from all picked assets
      operators$1.mergeMap(() => {
        const transaction = selectAssetsPicked(state).reduce(
          (tx, pickedAsset) => tx.patch(pickedAsset?.asset?._id, patchOperationTagUnset({ asset: pickedAsset, tag })),
          client.transaction()
        );
        return rxjs.from(transaction.commit());
      }),
      // Dispatch complete action
      operators$1.mergeMap(() => rxjs.of(ASSETS_ACTIONS.tagsRemoveComplete({ assets, tag }))),
      operators$1.catchError(
        (error) => rxjs.of(
          ASSETS_ACTIONS.tagsRemoveError({
            assets,
            error: {
              message: error?.message || "Internal error",
              statusCode: error?.statusCode || 500
            },
            tag
          })
        )
      )
    );
  })
), assetsUnpickEpic = (action$) => action$.pipe(
  reduxObservable.ofType(
    assetsActions.orderSet.type,
    assetsActions.viewSet.type,
    searchActions.facetsAdd.type,
    searchActions.facetsClear.type,
    searchActions.facetsRemoveById.type,
    searchActions.facetsRemoveByName.type,
    searchActions.facetsRemoveByTag.type,
    searchActions.facetsUpdate.type,
    searchActions.facetsUpdateById.type,
    searchActions.querySet.type
  ),
  operators$1.mergeMap(() => rxjs.of(assetsActions.pickClear()))
), assetsUpdateEpic = (action$, state$, { client }) => action$.pipe(
  operators$1.filter(assetsActions.updateRequest.match),
  operators$1.withLatestFrom(state$),
  operators$1.mergeMap(([action, state]) => {
    const { asset, closeDialogId, formData } = action.payload;
    return rxjs.of(action).pipe(
      debugThrottle(state.debug.badConnection),
      operators$1.mergeMap(
        () => rxjs.from(
          client.patch(asset._id).setIfMissing({ opt: {} }).setIfMissing({ "opt.media": {} }).set(formData).commit()
        )
      ),
      operators$1.mergeMap(
        (updatedAsset) => rxjs.of(
          assetsActions.updateComplete({
            asset: updatedAsset,
            closeDialogId
          })
        )
      ),
      operators$1.catchError(
        (error) => rxjs.of(
          assetsActions.updateError({
            asset,
            error: {
              message: error?.message || "Internal error",
              statusCode: error?.statusCode || 500
            }
          })
        )
      )
    );
  })
), selectAssetsByIds = (state) => state.assets.byIds, selectAssetsAllIds = (state) => state.assets.allIds, selectAssetById = toolkit.createSelector(
  [
    (state) => state.assets.byIds,
    (_state, assetId) => assetId
  ],
  (byIds, assetId) => byIds[assetId] || void 0
), selectAssets = toolkit.createSelector(
  [selectAssetsByIds, selectAssetsAllIds],
  (byIds, allIds) => allIds.map((id) => byIds[id])
), selectAssetsLength = toolkit.createSelector([selectAssets], (assets) => assets.length), selectAssetsPicked = toolkit.createSelector(
  [selectAssets],
  (assets) => assets.filter((item) => item?.picked)
), selectAssetsPickedLength = toolkit.createSelector(
  [selectAssetsPicked],
  (assetsPicked) => assetsPicked.length
), assetsActions = { ...assetsSlice.actions };
var assetsReducer = assetsSlice.reducer;
const customScrollbar = styledComponents.css`
  ::-webkit-scrollbar {
    width: 14px;
  }

  ::-webkit-scrollbar-thumb {
    border-radius: 10px;
    border: 4px solid rgba(0, 0, 0, 0);
    background: var(--card-border-color);
    background-clip: padding-box;

    &:hover {
      background: var(--card-muted-fg-color);
      background-clip: padding-box;
    }
  }
`, GlobalStyle = styledComponents.createGlobalStyle`
  .media__custom-scrollbar {
    ${customScrollbar}
  }

  // @sanity/ui overrides

  // Custom scrollbar on Box (used in Dialogs)
  div[data-ui="Box"] {
    ${customScrollbar}
  }

  // Dialog background color
  div[data-ui="Dialog"] {
    background-color: rgba(15, 17, 18, 0.9);
  }

`, useTypedSelector = reactRedux.useSelector, initialState$4 = {
  items: []
}, dialogSlice = toolkit.createSlice({
  name: "dialog",
  initialState: initialState$4,
  extraReducers: (builder) => {
    builder.addCase(DIALOG_ACTIONS.showTagCreate, (state) => {
      state.items.push({
        id: "tagCreate",
        type: "tagCreate"
      });
    }), builder.addCase(DIALOG_ACTIONS.showTagEdit, (state, action) => {
      const { tagId } = action.payload;
      state.items.push({
        id: tagId,
        tagId,
        type: "tagEdit"
      });
    });
  },
  reducers: {
    // Clear all dialogs
    clear(state) {
      state.items = [];
    },
    // Add newly created inline tag to assetEdit dialog
    inlineTagCreate(state, action) {
      const { assetId, tag } = action.payload;
      state.items.forEach((item) => {
        item.type === "assetEdit" && item.assetId === assetId && (item.lastCreatedTag = {
          label: tag.name.current,
          value: tag._id
        });
      });
    },
    // Remove inline tags from assetEdit dialog
    inlineTagRemove(state, action) {
      const { tagIds } = action.payload;
      state.items.forEach((item) => {
        item.type === "assetEdit" && (item.lastRemovedTagIds = tagIds);
      });
    },
    // Remove dialog by id
    remove(state, action) {
      const id = action.payload?.id;
      state.items = state.items.filter((item) => item.id !== id);
    },
    showConfirmAssetsTagAdd(state, action) {
      const { assetsPicked, closeDialogId, tag } = action.payload, suffix = `${assetsPicked.length} ${pluralize__default.default("asset", assetsPicked.length)}`;
      state.items.push({
        closeDialogId,
        confirmCallbackAction: ASSETS_ACTIONS.tagsAddRequest({
          assets: assetsPicked,
          tag
        }),
        confirmText: `Yes, add tag to ${suffix}`,
        title: `Add tag ${tag.name.current} to ${suffix}?`,
        id: "confirm",
        headerTitle: "Confirm tag addition",
        tone: "primary",
        type: "confirm"
      });
    },
    showConfirmAssetsTagRemove(state, action) {
      const { assetsPicked, closeDialogId, tag } = action.payload, suffix = `${assetsPicked.length} ${pluralize__default.default("asset", assetsPicked.length)}`;
      state.items.push({
        closeDialogId,
        confirmCallbackAction: ASSETS_ACTIONS.tagsRemoveRequest({ assets: assetsPicked, tag }),
        confirmText: `Yes, remove tag from ${suffix}`,
        headerTitle: "Confirm tag removal",
        id: "confirm",
        title: `Remove tag ${tag.name.current} from ${suffix}?`,
        tone: "critical",
        type: "confirm"
      });
    },
    showConfirmDeleteAssets(state, action) {
      const { assets, closeDialogId } = action.payload, suffix = `${assets.length} ${pluralize__default.default("asset", assets.length)}`;
      state.items.push({
        closeDialogId,
        confirmCallbackAction: assetsActions.deleteRequest({
          assets: assets.map((assetItem) => assetItem.asset)
        }),
        confirmText: `Yes, delete ${suffix}`,
        description: "This operation cannot be reversed. Are you sure you want to continue?",
        title: `Permanently delete ${suffix}?`,
        id: "confirm",
        headerTitle: "Confirm deletion",
        tone: "critical",
        type: "confirm"
      });
    },
    showConfirmDeleteTag(state, action) {
      const { closeDialogId, tag } = action.payload, suffix = "tag";
      state.items.push({
        closeDialogId,
        confirmCallbackAction: tagsActions.deleteRequest({ tag }),
        confirmText: `Yes, delete ${suffix}`,
        description: "This operation cannot be reversed. Are you sure you want to continue?",
        title: `Permanently delete ${suffix}?`,
        id: "confirm",
        headerTitle: "Confirm deletion",
        tone: "critical",
        type: "confirm"
      });
    },
    showAssetEdit(state, action) {
      const { assetId } = action.payload;
      state.items.push({
        assetId,
        id: assetId,
        type: "assetEdit"
      });
    },
    showSearchFacets(state) {
      state.items.push({
        id: "searchFacets",
        type: "searchFacets"
      });
    },
    showTags(state) {
      state.items.push({
        id: "tags",
        type: "tags"
      });
    }
  }
}), dialogClearOnAssetUpdateEpic = (action$) => action$.pipe(
  reduxObservable.ofType(
    assetsActions.deleteComplete.type,
    assetsActions.updateComplete.type,
    tagsActions.deleteComplete.type,
    tagsActions.updateComplete.type
  ),
  operators$1.filter(
    (action) => !!action?.payload?.closeDialogId
  ),
  operators$1.mergeMap((action) => {
    const dialogId = action?.payload?.closeDialogId;
    return dialogId ? rxjs.of(dialogSlice.actions.remove({ id: dialogId })) : rxjs.EMPTY;
  })
), dialogTagCreateEpic = (action$) => action$.pipe(
  operators$1.filter(tagsActions.createComplete.match),
  operators$1.mergeMap((action) => {
    const { assetId, tag } = action?.payload;
    return assetId ? rxjs.of(dialogSlice.actions.inlineTagCreate({ tag, assetId })) : tag._id ? rxjs.of(dialogSlice.actions.remove({ id: "tagCreate" })) : rxjs.EMPTY;
  })
), dialogTagDeleteEpic = (action$) => action$.pipe(
  operators$1.filter(tagsActions.listenerDeleteQueueComplete.match),
  operators$1.mergeMap((action) => {
    const { tagIds } = action?.payload;
    return rxjs.of(dialogSlice.actions.inlineTagRemove({ tagIds }));
  })
), dialogActions = { ...dialogSlice.actions };
var dialogReducer = dialogSlice.reducer;
const ButtonViewGroup = () => {
  const dispatch = reactRedux.useDispatch(), view = useTypedSelector((state) => state.assets.view);
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Inline, { space: 0, style: { whiteSpace: "nowrap" }, children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.Button,
      {
        fontSize: 1,
        icon: icons.ThLargeIcon,
        mode: view === "grid" ? "default" : "ghost",
        onClick: () => dispatch(assetsActions.viewSet({ view: "grid" })),
        style: {
          borderBottomRightRadius: 0,
          borderTopRightRadius: 0
        }
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.Button,
      {
        fontSize: 1,
        icon: icons.ThListIcon,
        mode: view === "table" ? "default" : "ghost",
        onClick: () => dispatch(assetsActions.viewSet({ view: "table" })),
        style: {
          borderBottomLeftRadius: 0,
          borderTopLeftRadius: 0
        }
      }
    )
  ] });
};
function usePortalPopoverProps() {
  const portal = ui.usePortal();
  return {
    animate: !0,
    constrainSize: !0,
    floatingBoundary: portal.element,
    portal: !0,
    referenceBoundary: portal.element
  };
}
const OrderSelect = () => {
  const dispatch = reactRedux.useDispatch(), order = useTypedSelector((state) => state.assets.order), popoverProps = usePortalPopoverProps();
  return /* @__PURE__ */ jsxRuntime.jsx(
    ui.MenuButton,
    {
      button: /* @__PURE__ */ jsxRuntime.jsx(
        ui.Button,
        {
          fontSize: 1,
          icon: icons.SortIcon,
          mode: "bleed",
          padding: 3,
          text: getOrderTitle(order.field, order.direction)
        }
      ),
      id: "order",
      menu: /* @__PURE__ */ jsxRuntime.jsx(ui.Menu, { children: ORDER_OPTIONS?.map((item, index) => {
        if (item) {
          const selected = order.field === item.field && order.direction === item.direction;
          return /* @__PURE__ */ jsxRuntime.jsx(
            ui.MenuItem,
            {
              disabled: selected,
              fontSize: 1,
              iconRight: selected,
              onClick: () => dispatch(
                assetsActions.orderSet({
                  order: { direction: item.direction, field: item.field }
                })
              ),
              padding: 2,
              selected,
              space: 4,
              style: { minWidth: "200px" },
              text: getOrderTitle(item.field, item.direction)
            },
            index
          );
        }
        return /* @__PURE__ */ jsxRuntime.jsx(ui.MenuDivider, {}, index);
      }) }),
      popover: popoverProps
    }
  );
}, Progress = (props) => {
  const { loading } = props, { animationDuration, isFinished, progress } = reactNprogress.useNProgress({
    animationDuration: 300,
    isAnimating: loading
  });
  return /* @__PURE__ */ jsxRuntime.jsx(
    ui.Box,
    {
      style: {
        opacity: isFinished ? 0 : 1,
        transition: `opacity ${animationDuration}ms linear`
      },
      children: /* @__PURE__ */ jsxRuntime.jsx(
        ui.Box,
        {
          style: {
            height: "1px",
            background: "rgba(255, 255, 255, 0.5)",
            position: "absolute",
            left: 0,
            top: 0,
            transition: `width ${animationDuration}ms linear`,
            width: `${progress * 100}%`
          }
        }
      )
    }
  );
}, SCHEME_COLORS = {
  bg: {
    dark: color.hues.gray[950].hex,
    light: color.hues.gray[50].hex
  },
  bg2: {
    dark: color.hues.gray[900].hex,
    light: color.hues.gray[100].hex
  },
  inputEnabledBorder: {
    dark: ui.studioTheme.color.dark.default.input.default.enabled.border,
    light: ui.studioTheme.color.light.default.input.default.enabled.border
  },
  inputHoveredBorder: {
    dark: ui.studioTheme.color.dark.default.input.default.hovered.border,
    light: ui.studioTheme.color.light.default.input.default.hovered.border
  },
  mutedHoveredBg: {
    dark: ui.studioTheme.color.dark.primary.muted.primary.hovered.bg,
    light: ui.studioTheme.color.light.primary.muted.primary.hovered.bg
  },
  mutedHoveredFg: {
    dark: ui.studioTheme.color.dark.primary.muted.primary.hovered.fg,
    light: ui.studioTheme.color.light.primary.muted.primary.hovered.fg
  },
  mutedSelectedBg: {
    dark: ui.studioTheme.color.dark.primary.muted.primary.selected.bg,
    light: ui.studioTheme.color.light.primary.muted.primary.selected.bg
  },
  spotBlue: {
    dark: ui.studioTheme.color.dark.primary.spot.blue,
    light: ui.studioTheme.color.light.primary.spot.blue
  }
};
function getSchemeColor(scheme, colorKey) {
  return SCHEME_COLORS[colorKey]?.[scheme];
}
const Container$1 = styledComponents.styled(ui.Box)(({ $scheme, theme }) => styledComponents.css`
    background: ${getSchemeColor($scheme, "bg")};
    border-radius: ${ui.rem(theme.sanity.radius[2])};
  `), SearchFacet = (props) => {
  const { children, facet } = props, scheme = sanity.useColorSchemeValue(), dispatch = reactRedux.useDispatch(), handleClose = () => {
    dispatch(searchActions.facetsRemoveById({ facetId: facet.id }));
  };
  return /* @__PURE__ */ jsxRuntime.jsx(Container$1, { padding: [2, 2, 1], $scheme: scheme, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: ["flex-start", "flex-start", "center"], direction: ["column", "column", "row"], children: [
    /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { paddingBottom: [3, 3, 0], paddingLeft: 1, paddingRight: 2, paddingTop: [1, 1, 0], children: /* @__PURE__ */ jsxRuntime.jsx(
      ui.Label,
      {
        size: 0,
        style: {
          whiteSpace: "nowrap"
        },
        children: facet.title
      }
    ) }),
    /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", children: [
      children,
      /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginLeft: 1, paddingX: 2, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 0, children: /* @__PURE__ */ jsxRuntime.jsx(icons.CloseIcon, { onClick: handleClose }) }) })
    ] })
  ] }) });
}, TextInputNumber = (props) => {
  const { onValueChange, value, ...remainingProps } = props;
  return /* @__PURE__ */ jsxRuntime.jsx(
    ui.TextInput,
    {
      ...remainingProps,
      onChange: (e) => {
        const val = e.target.value;
        (val === "" || /^[0-9\b]+$/.test(val)) && onValueChange(parseInt(val, 10) || "");
      },
      value: value ?? ""
    }
  );
}, SearchFacetNumber = ({ facet }) => {
  const dispatch = reactRedux.useDispatch(), popoverProps = usePortalPopoverProps(), modifiers = facet?.modifiers, selectedModifier = facet?.modifier ? modifiers?.find((modifier) => modifier.name === facet?.modifier) : modifiers?.[0], handleOperatorItemClick = (operatorType) => {
    dispatch(searchActions.facetsUpdateById({ id: facet.id, operatorType }));
  }, handleModifierClick = (modifier) => {
    dispatch(searchActions.facetsUpdateById({ id: facet.id, modifier: modifier.name }));
  }, handleValueChange = (value) => {
    dispatch(searchActions.facetsUpdateById({ id: facet.id, value }));
  }, selectedOperatorType = facet.operatorType ?? "greaterThan";
  return /* @__PURE__ */ jsxRuntime.jsxs(SearchFacet, { facet, children: [
    facet?.operatorTypes && /* @__PURE__ */ jsxRuntime.jsx(
      ui.MenuButton,
      {
        button: /* @__PURE__ */ jsxRuntime.jsx(
          ui.Button,
          {
            fontSize: 1,
            iconRight: icons.SelectIcon,
            padding: 2,
            text: operators[selectedOperatorType].label
          }
        ),
        id: "operators",
        menu: /* @__PURE__ */ jsxRuntime.jsx(ui.Menu, { children: facet.operatorTypes.map((operatorType, index) => operatorType ? /* @__PURE__ */ jsxRuntime.jsx(
          ui.MenuItem,
          {
            disabled: operatorType === selectedOperatorType,
            fontSize: 1,
            onClick: () => handleOperatorItemClick(operatorType),
            padding: 2,
            text: operators[operatorType].label
          },
          operatorType
        ) : /* @__PURE__ */ jsxRuntime.jsx(ui.MenuDivider, {}, index)) }),
        popover: popoverProps
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginX: 1, style: { maxWidth: "50px" }, children: /* @__PURE__ */ jsxRuntime.jsx(
      TextInputNumber,
      {
        fontSize: 1,
        onValueChange: handleValueChange,
        padding: 2,
        radius: 2,
        width: 2,
        value: facet?.value
      }
    ) }),
    modifiers && /* @__PURE__ */ jsxRuntime.jsx(
      ui.MenuButton,
      {
        button: /* @__PURE__ */ jsxRuntime.jsx(
          ui.Button,
          {
            fontSize: 1,
            iconRight: icons.SelectIcon,
            padding: 2,
            text: selectedModifier?.title
          }
        ),
        id: "modifier",
        menu: /* @__PURE__ */ jsxRuntime.jsx(ui.Menu, { children: modifiers.map((modifier) => {
          const selected = modifier.name === facet.modifier;
          return /* @__PURE__ */ jsxRuntime.jsx(
            ui.MenuItem,
            {
              disabled: selected,
              fontSize: 1,
              onClick: () => handleModifierClick(modifier),
              padding: 2,
              text: modifier.title
            },
            modifier.name
          );
        }) }),
        popover: popoverProps
      }
    )
  ] });
}, SearchFacetSelect = ({ facet }) => {
  const dispatch = reactRedux.useDispatch(), popoverProps = usePortalPopoverProps(), options = facet?.options, selectedItem = options?.find((v) => v.name === facet?.value), handleListItemClick = (option) => {
    dispatch(searchActions.facetsUpdate({ name: facet.name, value: option.name }));
  }, handleOperatorItemClick = (operatorType) => {
    dispatch(searchActions.facetsUpdate({ name: facet.name, operatorType }));
  }, selectedOperatorType = facet?.operatorType ?? "is";
  return /* @__PURE__ */ jsxRuntime.jsxs(SearchFacet, { facet, children: [
    facet?.operatorTypes && /* @__PURE__ */ jsxRuntime.jsx(
      ui.MenuButton,
      {
        button: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginRight: 1, children: /* @__PURE__ */ jsxRuntime.jsx(
          ui.Button,
          {
            fontSize: 1,
            iconRight: icons.SelectIcon,
            padding: 2,
            text: operators[selectedOperatorType].label
          }
        ) }),
        id: "operators",
        menu: /* @__PURE__ */ jsxRuntime.jsx(ui.Menu, { children: facet.operatorTypes.map((operatorType, index) => operatorType ? /* @__PURE__ */ jsxRuntime.jsx(
          ui.MenuItem,
          {
            disabled: operatorType === selectedOperatorType,
            fontSize: 1,
            onClick: () => handleOperatorItemClick(operatorType),
            padding: 2,
            text: operators[operatorType].label
          },
          operatorType
        ) : /* @__PURE__ */ jsxRuntime.jsx(ui.MenuDivider, {}, index)) }),
        popover: popoverProps
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.MenuButton,
      {
        button: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { fontSize: 1, iconRight: icons.SelectIcon, padding: 2, text: selectedItem?.title }),
        id: "list",
        menu: /* @__PURE__ */ jsxRuntime.jsx(ui.Menu, { children: options?.map((item, index) => {
          const selected = item.name === selectedItem?.name;
          return /* @__PURE__ */ jsxRuntime.jsx(
            ui.MenuItem,
            {
              disabled: selected,
              fontSize: 1,
              onClick: () => handleListItemClick(options[index]),
              padding: 2,
              text: item.title
            },
            item.name
          );
        }) }),
        popover: popoverProps
      }
    )
  ] });
}, SearchFacetString = ({ facet }) => {
  const dispatch = reactRedux.useDispatch(), popoverProps = usePortalPopoverProps(), handleOperatorItemClick = (operatorType) => {
    dispatch(searchActions.facetsUpdateById({ id: facet.id, operatorType }));
  }, handleChange = (e) => {
    dispatch(searchActions.facetsUpdateById({ id: facet.id, value: e.target.value }));
  }, selectedOperatorType = facet.operatorType;
  return /* @__PURE__ */ jsxRuntime.jsxs(SearchFacet, { facet, children: [
    facet?.operatorTypes && /* @__PURE__ */ jsxRuntime.jsx(
      ui.MenuButton,
      {
        button: /* @__PURE__ */ jsxRuntime.jsx(
          ui.Button,
          {
            fontSize: 1,
            iconRight: icons.SelectIcon,
            padding: 2,
            text: operators[selectedOperatorType].label
          }
        ),
        id: "operators",
        menu: /* @__PURE__ */ jsxRuntime.jsx(ui.Menu, { children: facet.operatorTypes.map((operatorType, index) => operatorType ? /* @__PURE__ */ jsxRuntime.jsx(
          ui.MenuItem,
          {
            disabled: operatorType === selectedOperatorType,
            fontSize: 1,
            onClick: () => handleOperatorItemClick(operatorType),
            padding: 2,
            text: operators[operatorType].label
          },
          operatorType
        ) : /* @__PURE__ */ jsxRuntime.jsx(ui.MenuDivider, {}, index)) }),
        popover: popoverProps
      }
    ),
    !operators[selectedOperatorType].hideInput && /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginLeft: 1, style: { maxWidth: "125px" }, children: /* @__PURE__ */ jsxRuntime.jsx(
      ui.TextInput,
      {
        fontSize: 1,
        onChange: handleChange,
        padding: 2,
        radius: 2,
        width: 2,
        value: facet?.value
      }
    ) })
  ] });
}, {
  fonts: {
    text: { sizes: themeTextSizes }
  },
  radius: themeRadius$1,
  space: themeSpace$1
} = ui.studioTheme, reactSelectStyles$1 = (scheme) => ({
  control: (styles, { isDisabled, isFocused }) => {
    let boxShadow = "inset 0 0 0 1px var(--card-border-color)";
    return isFocused && (boxShadow = `inset 0 0 0 1px ${getSchemeColor(scheme, "inputEnabledBorder")},
        0 0 0 1px ${getSchemeColor(scheme, "bg2")},
        0 0 0 3px var(--card-focus-ring-color) !important`), {
      ...styles,
      backgroundColor: "var(--card-bg-color)",
      color: "inherit",
      border: "none",
      borderRadius: themeRadius$1[2],
      boxShadow,
      fontSize: themeTextSizes[1].fontSize,
      minHeight: "25px",
      opacity: isDisabled ? 0.5 : "inherit",
      outline: "none",
      transition: "none",
      "&:hover": {
        boxShadow: `inset 0 0 0 1px ${getSchemeColor(scheme, "inputHoveredBorder")}`
      }
    };
  },
  input: (styles) => ({
    ...styles,
    color: "var(--card-fg-color)",
    fontFamily: ui.studioTheme.fonts.text.family,
    fontSize: themeTextSizes[1].fontSize,
    marginLeft: ui.rem(themeSpace$1[2])
  }),
  menuList: (styles) => ({
    ...styles,
    padding: 0
  }),
  noOptionsMessage: (styles) => ({
    ...styles,
    fontFamily: ui.studioTheme.fonts.text.family,
    fontSize: themeTextSizes[1].fontSize,
    lineHeight: "1em"
  }),
  option: (styles, { isFocused }) => ({
    ...styles,
    backgroundColor: isFocused ? getSchemeColor(scheme, "spotBlue") : "transparent",
    borderRadius: themeRadius$1[2],
    color: isFocused ? getSchemeColor(scheme, "bg") : "inherit",
    fontSize: themeTextSizes[1].fontSize,
    lineHeight: "1em",
    margin: 0,
    padding: ui.rem(themeSpace$1[1]),
    "&:hover": {
      backgroundColor: getSchemeColor(scheme, "spotBlue"),
      color: getSchemeColor(scheme, "bg")
    }
  }),
  placeholder: (styles) => ({
    ...styles,
    fontSize: themeTextSizes[1].fontSize,
    marginLeft: ui.rem(themeSpace$1[2]),
    paddingLeft: 0
  }),
  singleValue: (styles) => ({
    ...styles,
    alignItems: "center",
    display: "inline-flex",
    height: "100%",
    marginLeft: ui.rem(themeSpace$1[2])
  }),
  valueContainer: (styles) => ({
    ...styles,
    margin: 0,
    padding: 0
  })
}), ClearIndicator = (props) => /* @__PURE__ */ jsxRuntime.jsx(Select.components.ClearIndicator, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx(
  ui.Box,
  {
    paddingRight: 1,
    style: {
      transform: "scale(0.85)"
    },
    children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 0, children: /* @__PURE__ */ jsxRuntime.jsx(icons.CloseIcon, {}) })
  }
) }), Menu$1 = (props) => /* @__PURE__ */ jsxRuntime.jsx(Select.components.Menu, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { radius: 1, shadow: 2, children: props.children }) }), MenuList$1 = (props) => {
  const { children } = props, MAX_ROWS = 5, OPTION_HEIGHT = 33;
  if (Array.isArray(children)) {
    const height = children.length > MAX_ROWS ? OPTION_HEIGHT * MAX_ROWS : children.length * OPTION_HEIGHT;
    return /* @__PURE__ */ jsxRuntime.jsx(
      reactVirtuoso.Virtuoso,
      {
        className: "media__custom-scrollbar",
        itemContent: (index) => {
          const item = children[index];
          return /* @__PURE__ */ jsxRuntime.jsx(Option$1, { ...item.props });
        },
        style: { height },
        totalCount: children.length
      }
    );
  }
  return /* @__PURE__ */ jsxRuntime.jsx(Select.components.MenuList, { ...props, children });
}, NoOptionsMessage = (props) => /* @__PURE__ */ jsxRuntime.jsx(Select.components.NoOptionsMessage, { ...props, children: props.children }), Option$1 = (props) => /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 1, children: /* @__PURE__ */ jsxRuntime.jsx(Select.components.Option, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { paddingY: 1, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, style: { color: "inherit" }, textOverflow: "ellipsis", children: props.children }) }) }) }), SingleValue = (props) => /* @__PURE__ */ jsxRuntime.jsx(Select.components.SingleValue, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, textOverflow: "ellipsis", children: props.children }) }), reactSelectComponents$1 = {
  ClearIndicator,
  DropdownIndicator: null,
  IndicatorSeparator: null,
  Menu: Menu$1,
  MenuList: MenuList$1,
  NoOptionsMessage,
  Option: Option$1,
  SingleValue
}, SearchFacetTags = ({ facet }) => {
  const scheme = sanity.useColorSchemeValue(), dispatch = reactRedux.useDispatch(), tags = useTypedSelector((state) => selectTags(state)), tagsFetching = useTypedSelector((state) => state.tags.fetching), allTagOptions = getTagSelectOptions(tags), popoverProps = usePortalPopoverProps(), handleChange = (option) => {
    dispatch(
      searchActions.facetsUpdateById({
        id: facet.id,
        value: option
      })
    );
  }, handleOperatorItemClick = (operatorType) => {
    dispatch(
      searchActions.facetsUpdateById({
        id: facet.id,
        operatorType
      })
    );
  }, selectedOperatorType = facet.operatorType;
  return /* @__PURE__ */ jsxRuntime.jsxs(SearchFacet, { facet, children: [
    facet?.operatorTypes && /* @__PURE__ */ jsxRuntime.jsx(
      ui.MenuButton,
      {
        button: /* @__PURE__ */ jsxRuntime.jsx(
          ui.Button,
          {
            fontSize: 1,
            iconRight: icons.SelectIcon,
            padding: 2,
            text: operators[selectedOperatorType].label
          }
        ),
        id: "operators",
        menu: /* @__PURE__ */ jsxRuntime.jsx(ui.Menu, { children: facet.operatorTypes.map((operatorType, index) => operatorType ? /* @__PURE__ */ jsxRuntime.jsx(
          ui.MenuItem,
          {
            disabled: operatorType === selectedOperatorType,
            fontSize: 1,
            onClick: () => handleOperatorItemClick(operatorType),
            padding: 2,
            space: 4,
            style: { minWidth: "150px" },
            text: operators[operatorType].label
          },
          operatorType
        ) : /* @__PURE__ */ jsxRuntime.jsx(ui.MenuDivider, {}, index)) }),
        popover: popoverProps
      }
    ),
    !operators[selectedOperatorType].hideInput && /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginX: 1, style: { width: "160px" }, children: /* @__PURE__ */ jsxRuntime.jsx(
      Select__default.default,
      {
        components: reactSelectComponents$1,
        instanceId: "facet-searchable",
        isClearable: !0,
        isDisabled: tagsFetching,
        isSearchable: !0,
        name: "tags",
        noOptionsMessage: () => "No tags",
        onChange: (value) => handleChange(value),
        options: allTagOptions,
        placeholder: tagsFetching ? "Loading..." : "Select...",
        styles: reactSelectStyles$1(scheme),
        value: facet?.value
      }
    ) })
  ] });
}, StackContainer = styledComponents.styled(ui.Flex)(({ theme }) => styledComponents.css`
    > * {
      margin-bottom: ${ui.rem(theme.sanity.space[2])};
    }
  `), SearchFacets = (props) => {
  const { layout = "inline" } = props, searchFacets = useTypedSelector((state) => state.search.facets), Items2 = searchFacets.map((facet) => {
    const key = facet.id;
    return facet.type === "number" ? /* @__PURE__ */ jsxRuntime.jsx(SearchFacetNumber, { facet }, key) : facet.type === "searchable" ? /* @__PURE__ */ jsxRuntime.jsx(SearchFacetTags, { facet }, key) : facet.type === "select" ? /* @__PURE__ */ jsxRuntime.jsx(SearchFacetSelect, { facet }, key) : facet.type === "string" ? /* @__PURE__ */ jsxRuntime.jsx(SearchFacetString, { facet }, key) : null;
  });
  if (layout === "inline")
    return searchFacets.length === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginBottom: 2, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Inline, { space: 2, children: Items2 }) });
  if (layout === "stack")
    return /* @__PURE__ */ jsxRuntime.jsx(StackContainer, { align: "flex-start", direction: "column", children: Items2 });
  throw Error("Invalid layout");
}, ToolOptionsContext = react.createContext(null), ToolOptionsProvider = ({ options, children }) => {
  const value = react.useMemo(() => {
    let creditLineExcludeSources;
    return options?.creditLine?.excludeSources && (creditLineExcludeSources = Array.isArray(options?.creditLine?.excludeSources) ? options.creditLine.excludeSources : [options?.creditLine?.excludeSources]), {
      dropzone: { maxSize: options?.maximumUploadSize },
      components: {
        details: options?.components?.details
      },
      creditLine: {
        enabled: options?.creditLine?.enabled || !1,
        excludeSources: creditLineExcludeSources
      },
      directUploads: options?.directUploads ?? !0
    };
  }, [
    options?.creditLine?.enabled,
    options?.components,
    options?.creditLine?.excludeSources,
    options?.maximumUploadSize,
    options?.directUploads
  ]);
  return /* @__PURE__ */ jsxRuntime.jsx(ToolOptionsContext.Provider, { value, children });
}, useToolOptions = () => {
  const context = react.useContext(ToolOptionsContext);
  if (!context)
    throw new Error("useToolOptions must be used within an ToolOptionsProvider");
  return context;
}, SearchFacetsControl = () => {
  const dispatch = reactRedux.useDispatch(), assetTypes = useTypedSelector((state) => state.assets.assetTypes), searchFacets = useTypedSelector((state) => state.search.facets), selectedDocument = useTypedSelector((state) => state.selected.document), popoverProps = usePortalPopoverProps(), { creditLine } = useToolOptions(), isTool = !selectedDocument, filteredFacets = FACETS.filter((facet) => !creditLine?.enabled && facet?.type === "string" && facet?.name === "creditLine" ? !1 : facet.type === "group" || facet.type === "divider" ? !0 : isTool ? !facet?.selectOnly : facet.assetTypes.filter(
    (assetType) => assetTypes.includes(assetType)
  ).length > 0).filter((facet, index, facets) => {
    const previousFacet = facets[index - 1];
    return !(facet.type === "divider" && (index === 0 || index === facets.length - 1) || facet.type === "divider" && previousFacet?.type === "divider");
  }), hasSearchFacets = filteredFacets.length > 0, renderMenuFacets = (facets, level = 0) => /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: facets?.map((facet, index) => {
    if (facet.type === "divider")
      return /* @__PURE__ */ jsxRuntime.jsx(ui.MenuDivider, {}, index);
    if (facet.type === "group")
      return /* @__PURE__ */ jsxRuntime.jsx(ui.MenuGroup, { text: facet.title, title: facet.title, children: renderMenuFacets(facet.facets, level + 1) }, `group-${level}-${index}`);
    if (facet) {
      const disabled = !facet.operatorTypes && !!searchFacets.find((v) => v.name === facet.name);
      return /* @__PURE__ */ jsxRuntime.jsx(
        ui.MenuItem,
        {
          disabled,
          fontSize: 1,
          onClick: () => dispatch(searchActions.facetsAdd({ facet })),
          padding: 2,
          text: facet.title
        },
        facet.name
      );
    }
    return null;
  }) });
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.MenuButton,
      {
        button: /* @__PURE__ */ jsxRuntime.jsx(
          ui.Button,
          {
            disabled: !hasSearchFacets,
            fontSize: 1,
            icon: icons.AddIcon,
            mode: "bleed",
            space: 2,
            text: "Add filter",
            tone: "primary"
          }
        ),
        id: "facets",
        menu: /* @__PURE__ */ jsxRuntime.jsx(ui.Menu, { children: renderMenuFacets(filteredFacets) }),
        popover: {
          ...popoverProps,
          placement: "right-start"
        }
      }
    ),
    searchFacets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
      ui.Button,
      {
        fontSize: 1,
        mode: "bleed",
        onClick: () => dispatch(searchActions.facetsClear()),
        text: "Clear"
      }
    )
  ] });
}, TagIcon = () => /* @__PURE__ */ jsxRuntime.jsxs(
  "svg",
  {
    "data-sanity-icon": "media__tag",
    fill: "currentColor",
    height: "1em",
    stroke: "currentColor",
    strokeWidth: "0",
    viewBox: "0 0 512 512",
    width: "1em",
    children: [
      /* @__PURE__ */ jsxRuntime.jsx(
        "path",
        {
          d: "M435.25 48h-122.9a14.46 14.46 0 00-10.2 4.2L56.45 297.9a28.85 28.85 0 000 40.7l117 117a28.85 28.85 0 0040.7 0L459.75 210a14.46 14.46 0 004.2-10.2v-123a28.66 28.66 0 00-28.7-28.8z",
          fill: "none",
          strokeLinecap: "round",
          strokeLinejoin: "round",
          strokeWidth: "32"
        }
      ),
      /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M384 160a32 32 0 1132-32 32 32 0 01-32 32z" })
    ]
  }
), TextInputSearch = () => {
  const searchQuery = useTypedSelector((state) => state.search.query), dispatch = reactRedux.useDispatch(), handleChange = (e) => {
    dispatch(searchActions.querySet({ searchQuery: e.currentTarget.value }));
  }, handleClear = () => {
    dispatch(searchActions.querySet({ searchQuery: "" }));
  };
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { style: { position: "relative" }, children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.TextInput,
      {
        fontSize: 1,
        icon: icons.SearchIcon,
        onChange: handleChange,
        placeholder: "Search",
        radius: 2,
        value: searchQuery
      }
    ),
    searchQuery.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
      ui.Flex,
      {
        align: "center",
        justify: "center",
        onClick: handleClear,
        style: {
          cursor: "pointer",
          height: "100%",
          opacity: 0.75,
          position: "absolute",
          right: 0,
          top: 0,
          width: "2em",
          zIndex: 1
          // force stacking context
        },
        children: /* @__PURE__ */ jsxRuntime.jsx(icons.CloseIcon, {})
      }
    )
  ] });
}, Controls = () => {
  const dispatch = reactRedux.useDispatch(), fetching = useTypedSelector((state) => state.assets.fetching), pageIndex = useTypedSelector((state) => state.assets.pageIndex), searchFacets = useTypedSelector((state) => state.search.facets), tagsPanelVisible = useTypedSelector((state) => state.tags.panelVisible), mediaIndex = ui.useMediaIndex(), handleShowSearchFacetDialog = () => {
    dispatch(dialogActions.showSearchFacets());
  }, handleShowTagsDialog = () => {
    dispatch(dialogActions.showTags());
  }, toggleTagsPanelToggle = () => {
    dispatch(tagsActions.panelVisibleSet({ panelVisible: !tagsPanelVisible }));
  };
  return /* @__PURE__ */ jsxRuntime.jsxs(
    ui.Box,
    {
      paddingY: 2,
      style: {
        borderBottom: "1px solid var(--card-border-color)",
        zIndex: 2
      },
      children: [
        /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginBottom: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
          ui.Flex,
          {
            align: "flex-start",
            direction: ["column", "column", "column", "column", "row"],
            justify: "space-between",
            children: /* @__PURE__ */ jsxRuntime.jsxs(
              ui.Flex,
              {
                flex: 1,
                style: {
                  alignItems: "flex-start",
                  flex: 1,
                  height: "100%",
                  justifyContent: mediaIndex < 2 ? "space-between" : "flex-start",
                  position: "relative",
                  width: "100%"
                },
                children: [
                  /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginX: 2, style: { minWidth: "200px" }, children: /* @__PURE__ */ jsxRuntime.jsx(TextInputSearch, {}) }),
                  /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { display: ["none", "none", "block"], children: [
                    /* @__PURE__ */ jsxRuntime.jsx(SearchFacets, {}),
                    /* @__PURE__ */ jsxRuntime.jsx(SearchFacetsControl, {})
                  ] }),
                  /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { display: ["block", "block", "none"], marginX: 2, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Inline, { space: 2, style: { whiteSpace: "nowrap" }, children: [
                    /* @__PURE__ */ jsxRuntime.jsx(
                      ui.Button,
                      {
                        fontSize: 1,
                        mode: "ghost",
                        onClick: handleShowSearchFacetDialog,
                        text: `Filters${searchFacets.length > 0 ? ` (${searchFacets.length})` : ""}`,
                        tone: "primary"
                      }
                    ),
                    /* @__PURE__ */ jsxRuntime.jsx(
                      ui.Button,
                      {
                        fontSize: 1,
                        mode: "ghost",
                        onClick: handleShowTagsDialog,
                        text: "Tags",
                        tone: "primary"
                      }
                    )
                  ] }) })
                ]
              }
            )
          }
        ) }),
        /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", justify: ["space-between"], children: [
          /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginX: 2, children: /* @__PURE__ */ jsxRuntime.jsx(ButtonViewGroup, {}) }),
          /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { marginX: 2, children: [
            /* @__PURE__ */ jsxRuntime.jsx(OrderSelect, {}),
            /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { display: ["none", "none", "block"], marginLeft: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
              ui.Button,
              {
                fontSize: 1,
                icon: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { style: { transform: "scale(0.75)" }, children: /* @__PURE__ */ jsxRuntime.jsx(TagIcon, {}) }),
                onClick: toggleTagsPanelToggle,
                mode: tagsPanelVisible ? "default" : "ghost",
                text: tagsPanelVisible ? "Tags" : ""
              }
            ) })
          ] })
        ] }) }),
        /* @__PURE__ */ jsxRuntime.jsx(Progress, { loading: fetching }, pageIndex)
      ]
    }
  );
}, initialState$3 = {
  badConnection: !1,
  enabled: !1
}, debugSlice = toolkit.createSlice({
  name: "debug",
  initialState: initialState$3,
  reducers: {
    setBadConnection(state, action) {
      state.badConnection = action.payload;
    },
    toggleEnabled(state) {
      state.enabled = !state.enabled;
    }
  }
}), debugActions = { ...debugSlice.actions };
var debugReducer = debugSlice.reducer;
const DebugControls = () => {
  const dispatch = reactRedux.useDispatch(), badConnection = useTypedSelector((state) => state.debug.badConnection), debugEnabled = useTypedSelector((state) => state.debug.enabled), handleChange = (e) => {
    const checked = e.target.checked;
    dispatch(debugActions.setBadConnection(checked));
  };
  return useKeyPress("alt+ctrl+shift+/", () => {
    dispatch(debugActions.toggleEnabled());
  }), debugEnabled ? /* @__PURE__ */ jsxRuntime.jsx(
    ui.Box,
    {
      padding: 4,
      style: {
        bottom: 0,
        left: 0,
        pointerEvents: "none",
        position: "fixed",
        width: "100%"
      },
      children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", children: [
        /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginRight: 3, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 1, children: /* @__PURE__ */ jsxRuntime.jsx(icons.PlugIcon, {}) }) }),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.Tooltip,
          {
            animate: !0,
            content: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 2, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 1, children: badConnection ? "Bad connection: +3000ms & 50% chance to fail" : "No connection throttling" }) }),
            fallbackPlacements: ["right", "left"],
            placement: "bottom",
            portal: !0,
            children: /* @__PURE__ */ jsxRuntime.jsx(
              ui.Switch,
              {
                checked: badConnection,
                onChange: handleChange,
                style: {
                  pointerEvents: "auto"
                }
              }
            )
          }
        )
      ] })
    }
  ) : null;
}, tagOptionSchema = z__namespace.object({
  label: z__namespace.string().trim().min(1, { message: "Label cannot be empty" }),
  value: z__namespace.string().trim().min(1, { message: "Value cannot be empty" })
}), assetFormSchema = z__namespace.object({
  altText: z__namespace.string().trim().optional(),
  creditLine: z__namespace.string().trim().optional(),
  description: z__namespace.string().trim().optional(),
  opt: z__namespace.object({
    media: z__namespace.object({
      tags: z__namespace.array(tagOptionSchema).nullable()
    })
  }),
  originalFilename: z__namespace.string().trim().min(1, { message: "Filename cannot be empty" }),
  title: z__namespace.string().trim().optional()
}), tagFormSchema = z__namespace.object({
  name: z__namespace.string().min(1, { message: "Name cannot be empty" })
});
function getUniqueDocuments(documents) {
  const draftIds = documents.reduce(
    (acc, doc) => doc._id.startsWith("drafts.") ? acc.concat(doc._id.slice(7)) : acc,
    []
  );
  return documents.filter(
    (doc) => !draftIds.includes(doc._id)
  );
}
const imageDprUrl = (asset, options) => {
  const dpi = typeof window > "u" || !window.devicePixelRatio ? 1 : Math.round(window.devicePixelRatio), imgH = options?.height ? options?.height * Math.max(1, dpi) : void 0, imgW = options.width * Math.max(1, dpi), urlParams = new URLSearchParams();
  return urlParams.append("fit", "max"), urlParams.append("w", imgW.toString()), imgH && urlParams.append("h", imgH.toString()), `${asset.url}?${urlParams.toString()}`;
}, sanitizeFormData = (formData) => Object.keys(formData).reduce((acc, key) => {
  const val = formData[key];
  return typeof val == "object" && val !== null && val.constructor !== Array ? acc[key] = sanitizeFormData(val) : val === "" || typeof val > "u" || val?.length === 0 ? acc[key] = null : typeof val == "string" && val ? acc[key] = formData[key].trim() : acc[key] = formData[key], acc;
}, {}), isFileAsset = (asset) => asset._type === "sanity.fileAsset", isImageAsset = (asset) => asset._type === "sanity.imageAsset", getAssetResolution = (asset) => `${asset.metadata.dimensions.width}x${asset.metadata.dimensions.height}px`, ButtonAssetCopy = ({ disabled, url }) => {
  const popoverProps = usePortalPopoverProps(), refPopoverTimeout = react.useRef(null), [popoverVisible, setPopoverVisible] = react.useState(!1), handleClick = () => {
    refPopoverTimeout.current && clearTimeout(refPopoverTimeout.current), setPopoverVisible(!0), copy__default.default(url), refPopoverTimeout.current = setTimeout(() => {
      setPopoverVisible(!1);
    }, 1250);
  };
  return react.useEffect(() => () => {
    refPopoverTimeout.current && clearTimeout(refPopoverTimeout.current);
  }, []), /* @__PURE__ */ jsxRuntime.jsx(
    ui.Popover,
    {
      content: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 1, children: "Copied!" }),
      open: popoverVisible,
      padding: 2,
      placement: "top",
      radius: 1,
      ...popoverProps,
      children: /* @__PURE__ */ jsxRuntime.jsx(
        ui.Button,
        {
          disabled,
          fontSize: 1,
          icon: icons.ClipboardIcon,
          mode: "ghost",
          onClick: handleClick,
          text: "Copy URL"
        }
      )
    }
  );
}, Row = ({ label, value }) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { justify: "space-between", children: [
  /* @__PURE__ */ jsxRuntime.jsx(
    ui.Text,
    {
      size: 1,
      style: {
        opacity: 0.8,
        width: "40%"
      },
      textOverflow: "ellipsis",
      children: label
    }
  ),
  /* @__PURE__ */ jsxRuntime.jsx(
    ui.Text,
    {
      size: 1,
      style: {
        opacity: 0.4,
        textAlign: "right",
        width: "60%"
      },
      textOverflow: "ellipsis",
      children: value
    }
  )
] }), AssetMetadata = (props) => {
  const { asset, item } = props, exif = asset?.metadata?.exif, handleDownload = () => {
    window.location.href = `${asset.url}?dl=${asset.originalFilename}`;
  };
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { marginTop: 3, children: [
    /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
      /* @__PURE__ */ jsxRuntime.jsx(Row, { label: "Size", value: filesize__default.default(asset?.size, { base: 10, round: 0 }) }),
      /* @__PURE__ */ jsxRuntime.jsx(Row, { label: "MIME type", value: asset?.mimeType }),
      /* @__PURE__ */ jsxRuntime.jsx(Row, { label: "Extension", value: (asset?.extension).toUpperCase() }),
      isImageAsset(asset) && /* @__PURE__ */ jsxRuntime.jsx(Row, { label: "Dimensions", value: getAssetResolution(asset) })
    ] }) }),
    exif && (exif.DateTimeOriginal || exif.FNumber || exif.FocalLength || exif.ExposureTime || exif.ISO) && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
      /* @__PURE__ */ jsxRuntime.jsx(
        ui.Box,
        {
          marginY: 4,
          style: {
            background: "var(--card-border-color)",
            height: "1px",
            width: "100%"
          }
        }
      ),
      /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
        exif.ISO && /* @__PURE__ */ jsxRuntime.jsx(Row, { label: "ISO", value: exif.ISO }),
        exif.FNumber && /* @__PURE__ */ jsxRuntime.jsx(Row, { label: "Aperture", value: `\u0192/${exif.FNumber}` }),
        exif.FocalLength && /* @__PURE__ */ jsxRuntime.jsx(Row, { label: "Focal length", value: `${exif.FocalLength}mm` }),
        exif.ExposureTime && /* @__PURE__ */ jsxRuntime.jsx(Row, { label: "Exposure time", value: `1/${1 / exif.ExposureTime}` }),
        exif.DateTimeOriginal && /* @__PURE__ */ jsxRuntime.jsx(
          Row,
          {
            label: "Original date",
            value: dateFns.format(new Date(exif.DateTimeOriginal), "PPp")
          }
        )
      ] }) })
    ] }),
    /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginTop: 5, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Inline, { space: 2, children: [
      /* @__PURE__ */ jsxRuntime.jsx(
        ui.Button,
        {
          disabled: !item || item?.updating,
          fontSize: 1,
          icon: icons.DownloadIcon,
          mode: "ghost",
          onClick: handleDownload,
          text: "Download"
        }
      ),
      /* @__PURE__ */ jsxRuntime.jsx(ButtonAssetCopy, { disabled: !item || item?.updating, url: asset.url })
    ] }) })
  ] });
}, Dialog = (props) => /* @__PURE__ */ jsxRuntime.jsx(ui.Dialog, { ...props, style: { position: "fixed" } }), DocumentList = ({ documents, isLoading }) => {
  const schema = sanity.useSchema();
  return isLoading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 1, children: "Loading..." }) : documents.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 1, children: "No documents are referencing this asset" }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { flex: 1, marginBottom: 2, padding: 2, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: documents?.map((doc) => /* @__PURE__ */ jsxRuntime.jsx(ReferringDocument, { doc, schemaType: schema.get(doc._type) }, doc._id)) }) });
}, ReferringDocument = (props) => {
  const { doc, schemaType } = props, { onClick } = router.useIntentLink({
    intent: "edit",
    params: { id: doc._id }
  });
  return schemaType ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { mode: "bleed", onClick, padding: 2, style: { width: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsx(sanity.Preview, { layout: "default", schemaType, value: doc }) }, doc._id) : /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 2, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: 1, children: [
    "A document of the unknown type ",
    /* @__PURE__ */ jsxRuntime.jsx("em", { children: doc._type })
  ] }) });
}, Container = styledComponents.styled(ui.Box)(({ theme }) => styledComponents.css`
    text {
      font-family: ${theme.sanity.fonts.text.family} !important;
      font-size: 8px !important;
      font-weight: 500 !important;
    }
  `), FileIcon = (props) => {
  const { extension, onClick, width } = props;
  return /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { align: "center", justify: "center", onClick, style: { height: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsx(Container, { style: { width }, children: extension ? /* @__PURE__ */ jsxRuntime.jsx(
    reactFileIcon.FileIcon,
    {
      extension,
      ...reactFileIcon.defaultStyles[extension]
    }
  ) : /* @__PURE__ */ jsxRuntime.jsx(reactFileIcon.FileIcon, {}) }) });
}, FileAssetPreview = (props) => {
  const { asset } = props;
  return asset.mimeType.search("audio") === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { align: "center", justify: "center", style: { height: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsx("audio", { controls: !0, src: asset.url, style: { width: "100%" } }) }) : asset.mimeType.search("video") === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
    "video",
    {
      controls: !0,
      src: asset.url,
      style: {
        height: "100%",
        width: "100%"
      }
    }
  ) : /* @__PURE__ */ jsxRuntime.jsx(FileIcon, { extension: asset.extension, width: "50%" });
}, FormSubmitButton = (props) => {
  const { disabled, isValid, lastUpdated, onClick } = props;
  let content;
  return isValid ? lastUpdated ? content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    "Last updated",
    /* @__PURE__ */ jsxRuntime.jsx("br", {}),
    " ",
    dateFns.format(new Date(lastUpdated), "PPp")
  ] }) : content = "No unpublished changes" : content = "There are validation errors that need to be fixed before this document can be published", /* @__PURE__ */ jsxRuntime.jsx(
    ui.Tooltip,
    {
      animate: !0,
      content: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 3, style: { maxWidth: "185px" }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 1, children: content }) }),
      disabled: "ontouchstart" in window,
      placement: "top",
      portal: !0,
      children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { children: /* @__PURE__ */ jsxRuntime.jsx(
        ui.Button,
        {
          disabled,
          fontSize: 1,
          onClick,
          text: "Save and close",
          tone: "primary"
        }
      ) })
    }
  );
}, Image$1 = styledComponents.styled.img`
  --checkerboard-color: ${(props) => props.$scheme ? getSchemeColor(props.$scheme, "bg2") : "inherit"};

  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;

  ${(props) => props.$showCheckerboard && styledComponents.css`
      background-image: linear-gradient(45deg, var(--checkerboard-color) 25%, transparent 25%),
        linear-gradient(-45deg, var(--checkerboard-color) 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, var(--checkerboard-color) 75%),
        linear-gradient(-45deg, transparent 75%, var(--checkerboard-color) 75%);
      background-size: 20px 20px;
      background-position: 0 0, 0 10px, 10px -10px, -10px 0;
    `}
`, { radius: themeRadius, space: themeSpace } = ui.studioTheme, reactSelectStyles = (scheme) => ({
  control: (styles, { isFocused }) => {
    let boxShadow = "inset 0 0 0 1px var(--card-border-color)";
    return isFocused && (boxShadow = `inset 0 0 0 1px ${getSchemeColor(scheme, "inputEnabledBorder")},
        0 0 0 1px var(--card-bg-color),
        0 0 0 3px var(--card-focus-ring-color) !important`), {
      ...styles,
      backgroundColor: "var(--card-bg-color)",
      color: "inherit",
      border: "none",
      borderRadius: themeRadius[1],
      boxShadow,
      margin: 0,
      minHeight: "35px",
      outline: "none",
      padding: ui.rem(themeSpace[1]),
      transition: "none",
      "&:hover": {
        boxShadow: `inset 0 0 0 1px ${getSchemeColor(scheme, "inputHoveredBorder")}`
      }
    };
  },
  indicatorsContainer: (styles, { isDisabled }) => ({
    ...styles,
    opacity: isDisabled ? 0.25 : 1
  }),
  input: (styles) => ({
    ...styles,
    color: "var(--card-fg-color)",
    fontFamily: ui.studioTheme.fonts.text.family,
    marginLeft: ui.rem(themeSpace[2])
  }),
  menuList: (styles) => ({
    ...styles
  }),
  multiValue: (styles, { isDisabled }) => ({
    ...styles,
    backgroundColor: getSchemeColor(scheme, "mutedHoveredBg"),
    borderRadius: themeRadius[2],
    opacity: isDisabled ? 0.5 : 1
  }),
  multiValueLabel: () => ({
    color: getSchemeColor(scheme, "mutedHoveredFg"),
    fontSize: "inherit",
    padding: 0
  }),
  multiValueRemove: (styles) => ({
    ...styles,
    borderTopLeftRadius: 0,
    borderBottomLeftRadius: 0,
    svg: { color: getSchemeColor(scheme, "mutedHoveredFg") },
    "&:hover": {
      backgroundColor: getSchemeColor(scheme, "mutedSelectedBg")
    }
  }),
  noOptionsMessage: (styles) => ({
    ...styles,
    fontFamily: ui.studioTheme.fonts.text.family,
    lineHeight: "1em"
  }),
  option: (styles, { isFocused }) => ({
    ...styles,
    backgroundColor: isFocused ? getSchemeColor(scheme, "spotBlue") : "transparent",
    borderRadius: themeRadius[2],
    color: isFocused ? getSchemeColor(scheme, "bg") : "inherit",
    padding: `${ui.rem(themeSpace[1])} ${ui.rem(themeSpace[2])}`,
    "&:hover": {
      backgroundColor: getSchemeColor(scheme, "spotBlue"),
      color: getSchemeColor(scheme, "bg")
    }
  }),
  placeholder: (styles) => ({
    ...styles,
    marginLeft: ui.rem(themeSpace[2])
  }),
  valueContainer: (styles) => ({
    ...styles,
    margin: 0,
    padding: 0
  })
}), DropdownIndicator = (props) => /* @__PURE__ */ jsxRuntime.jsx(Select.components.DropdownIndicator, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { paddingX: 2, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDownIcon, {}) }) }) }), Menu = (props) => /* @__PURE__ */ jsxRuntime.jsx(Select.components.Menu, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { radius: 1, shadow: 2, children: props.children }) }), MenuList = (props) => {
  const { children } = props, MAX_ROWS = 5, OPTION_HEIGHT = 37;
  if (Array.isArray(children)) {
    const height = children.length > MAX_ROWS ? OPTION_HEIGHT * MAX_ROWS : children.length * OPTION_HEIGHT;
    return /* @__PURE__ */ jsxRuntime.jsx(
      reactVirtuoso.Virtuoso,
      {
        className: "media__custom-scrollbar",
        itemContent: (index) => {
          const item = children[index];
          return /* @__PURE__ */ jsxRuntime.jsx(Option, { ...item.props });
        },
        style: { height },
        totalCount: children.length
      }
    );
  }
  return /* @__PURE__ */ jsxRuntime.jsx(Select.components.MenuList, { ...props, children });
}, MultiValueLabel = (props) => /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 2, paddingRight: 1, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, weight: "medium", children: /* @__PURE__ */ jsxRuntime.jsx(Select.components.MultiValueLabel, { ...props }) }) }), MultiValueRemove = (props) => /* @__PURE__ */ jsxRuntime.jsx(Select.components.MultiValueRemove, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx(icons.CloseIcon, { color: "#1f2123" }) }), Option = (props) => /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { paddingX: 1, paddingY: 1, children: /* @__PURE__ */ jsxRuntime.jsx(Select.components.Option, { ...props, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", children: [
  props.data.__isNew__ && /* @__PURE__ */ jsxRuntime.jsx(icons.AddIcon, { style: { marginRight: "3px" } }),
  props.children
] }) }) }), reactSelectComponents = {
  DropdownIndicator,
  IndicatorSeparator: null,
  Menu,
  MenuList,
  MultiValueLabel,
  MultiValueRemove,
  Option
}, StyledErrorOutlineIcon = styledComponents.styled(icons.ErrorOutlineIcon)(({ theme }) => ({
  color: theme.sanity.color.spot.red
})), FormFieldInputLabel = (props) => {
  const { description, error, label, name } = props;
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginY: 3, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Inline, { space: 2, children: [
      /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { as: "label", htmlFor: name, size: 1, weight: "semibold", children: label }),
      error && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: /* @__PURE__ */ jsxRuntime.jsx(
        ui.Tooltip,
        {
          animate: !0,
          content: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 2, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { muted: !0, size: 1, children: [
            /* @__PURE__ */ jsxRuntime.jsx(StyledErrorOutlineIcon, { style: { marginRight: "0.1em" } }),
            error
          ] }) }),
          fallbackPlacements: ["top", "left"],
          placement: "right",
          portal: !0,
          children: /* @__PURE__ */ jsxRuntime.jsx(StyledErrorOutlineIcon, {})
        }
      ) })
    ] }) }),
    description && /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginY: 3, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { htmlFor: name, muted: !0, size: 1, children: description }) })
  ] });
}, FormFieldInputTags = (props) => {
  const {
    control,
    description,
    disabled,
    error,
    label,
    name,
    onCreateTag,
    options,
    placeholder,
    value
  } = props, scheme = sanity.useColorSchemeValue(), creating = useTypedSelector((state) => state.tags.creating), tagsFetching = useTypedSelector((state) => state.tags.fetching);
  return /* @__PURE__ */ jsxRuntime.jsxs(
    ui.Box,
    {
      style: { zIndex: 2 },
      children: [
        /* @__PURE__ */ jsxRuntime.jsx(FormFieldInputLabel, { description, error, label, name }),
        /* @__PURE__ */ jsxRuntime.jsx(
          reactHookForm.Controller,
          {
            control,
            defaultValue: value,
            name,
            render: ({ field }) => {
              const { onBlur, onChange, value: controllerValue } = field;
              return /* @__PURE__ */ jsxRuntime.jsx(
                CreatableSelect__default.default,
                {
                  components: reactSelectComponents,
                  instanceId: "tags",
                  isClearable: !1,
                  isDisabled: creating || disabled || tagsFetching,
                  isLoading: creating,
                  isMulti: !0,
                  name,
                  noOptionsMessage: () => "No tags",
                  onBlur,
                  onChange,
                  onCreateOption: onCreateTag,
                  options,
                  placeholder: tagsFetching ? "Loading..." : placeholder,
                  styles: reactSelectStyles(scheme),
                  value: controllerValue
                }
              );
            }
          }
        )
      ]
    }
  );
}, FormFieldInputText = react.forwardRef((props, ref) => {
  const { description, disabled, error, label, name, placeholder, value, ...rest } = props;
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { children: [
    /* @__PURE__ */ jsxRuntime.jsx(FormFieldInputLabel, { description, error, label, name }),
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.TextInput,
      {
        ...rest,
        autoComplete: "off",
        autoFocus: !0,
        defaultValue: value,
        disabled,
        id: name,
        name,
        placeholder,
        ref
      }
    )
  ] });
}), FormFieldInputTextarea = react.forwardRef((props, ref) => {
  const { description, disabled, error, label, name, placeholder, rows, value, ...rest } = props;
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { children: [
    /* @__PURE__ */ jsxRuntime.jsx(FormFieldInputLabel, { description, error, label, name }),
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.TextArea,
      {
        ...rest,
        autoComplete: "off",
        defaultValue: value,
        disabled,
        id: name,
        name,
        placeholder,
        ref,
        rows
      }
    )
  ] });
});
function Details({
  formUpdating,
  handleCreateTag,
  control,
  errors,
  register,
  allTagOptions,
  assetTagOptions,
  currentAsset,
  creditLine
}) {
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      FormFieldInputTags,
      {
        control,
        disabled: formUpdating,
        error: errors?.opt?.media?.tags?.message,
        label: "Tags",
        name: "opt.media.tags",
        onCreateTag: handleCreateTag,
        options: allTagOptions,
        placeholder: "Select or create...",
        value: assetTagOptions
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      FormFieldInputText,
      {
        ...register("originalFilename"),
        disabled: formUpdating,
        error: errors?.originalFilename?.message,
        label: "Filename",
        name: "originalFilename",
        value: currentAsset?.originalFilename
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      FormFieldInputText,
      {
        ...register("title"),
        disabled: formUpdating,
        error: errors?.title?.message,
        label: "Title",
        name: "title",
        value: currentAsset?.title
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      FormFieldInputText,
      {
        ...register("altText"),
        disabled: formUpdating,
        error: errors?.altText?.message,
        label: "Alt Text",
        name: "altText",
        value: currentAsset?.altText
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      FormFieldInputTextarea,
      {
        ...register("description"),
        disabled: formUpdating,
        error: errors?.description?.message,
        label: "Description",
        name: "description",
        rows: 5,
        value: currentAsset?.description
      }
    ),
    creditLine?.enabled && /* @__PURE__ */ jsxRuntime.jsx(
      FormFieldInputText,
      {
        ...register("creditLine"),
        error: errors?.creditLine?.message,
        label: "Credit",
        name: "creditLine",
        value: currentAsset?.creditLine,
        disabled: formUpdating || creditLine?.excludeSources?.includes(currentAsset?.source?.name)
      }
    )
  ] });
}
function renderDefaultDetails(props) {
  return /* @__PURE__ */ jsxRuntime.jsx(Details, { ...props });
}
const DialogAssetEdit = (props) => {
  const {
    children,
    dialog: { assetId, id, lastCreatedTag, lastRemovedTagIds }
  } = props, client = useVersionedClient(), scheme = sanity.useColorSchemeValue(), documentStore = sanity.useDocumentStore(), dispatch = reactRedux.useDispatch(), assetItem = useTypedSelector((state) => selectAssetById(state, String(assetId))), tags = useTypedSelector(selectTags), assetUpdatedPrev = react.useRef(void 0), [assetSnapshot, setAssetSnapshot] = react.useState(assetItem?.asset), [tabSection, setTabSection] = react.useState("details"), currentAsset = assetItem ? assetItem?.asset : assetSnapshot, allTagOptions = getTagSelectOptions(tags), assetTagOptions = useTypedSelector(selectTagSelectOptions(currentAsset)), { creditLine, components: { details: CustomDetails } = {} } = useToolOptions(), generateDefaultValues = react.useCallback(
    (asset) => ({
      altText: asset?.altText || "",
      creditLine: asset?.creditLine || "",
      description: asset?.description || "",
      originalFilename: asset?.originalFilename || "",
      opt: { media: { tags: assetTagOptions } },
      title: asset?.title || ""
    }),
    [assetTagOptions]
  ), {
    control,
    // Read the formState before render to subscribe the form state through Proxy
    formState: { errors, isDirty, isValid },
    getValues,
    handleSubmit,
    register,
    reset,
    setValue
  } = reactHookForm.useForm({
    defaultValues: generateDefaultValues(assetItem?.asset),
    mode: "onChange",
    resolver: zod.zodResolver(assetFormSchema)
  }), formUpdating = !assetItem || assetItem?.updating, handleClose = react.useCallback(() => {
    dispatch(dialogActions.remove({ id }));
  }, [dispatch, id]), handleDelete = react.useCallback(() => {
    assetItem?.asset && dispatch(
      dialogActions.showConfirmDeleteAssets({
        assets: [assetItem],
        closeDialogId: assetItem?.asset._id
      })
    );
  }, [assetItem, dispatch]), handleAssetUpdate = react.useCallback((update) => {
    const { result, transition } = update;
    result && transition === "update" && setAssetSnapshot(result);
  }, []), handleCreateTag = react.useCallback(
    (tagName) => {
      dispatch(
        tagsActions.createRequest({
          assetId: currentAsset?._id,
          name: tagName
        })
      );
    },
    [currentAsset?._id, dispatch]
  ), onSubmit = react.useCallback(
    (formData) => {
      if (!assetItem?.asset)
        return;
      const sanitizedFormData = sanitizeFormData(formData);
      dispatch(
        assetsActions.updateRequest({
          asset: assetItem?.asset,
          closeDialogId: assetItem?.asset._id,
          formData: {
            ...sanitizedFormData,
            // Map tags to sanity references
            opt: {
              media: {
                ...sanitizedFormData.opt.media,
                tags: sanitizedFormData.opt.media.tags?.map((tag) => ({
                  _ref: tag.value,
                  _type: "reference",
                  _weak: !0
                })) || null
              }
            }
          }
        })
      );
    },
    [assetItem?.asset, dispatch]
  );
  react.useEffect(() => {
    if (!assetItem?.asset)
      return;
    const subscriptionAsset = client.listen(groq__default.default`*[_id == $id]`, { id: assetItem?.asset._id }).subscribe(handleAssetUpdate);
    return () => {
      subscriptionAsset?.unsubscribe();
    };
  }, [assetItem?.asset, client, handleAssetUpdate]), react.useEffect(() => {
    if (lastCreatedTag) {
      const updatedTags = (getValues("opt.media.tags") || []).concat([lastCreatedTag]);
      setValue("opt.media.tags", updatedTags, { shouldDirty: !0 });
    }
  }, [getValues, lastCreatedTag, setValue]), react.useEffect(() => {
    if (lastRemovedTagIds) {
      const updatedTags = (getValues("opt.media.tags") || []).filter((tag) => !lastRemovedTagIds.includes(tag.value));
      setValue("opt.media.tags", updatedTags, { shouldDirty: !0 });
    }
  }, [getValues, lastRemovedTagIds, setValue]), react.useEffect(() => {
    assetUpdatedPrev.current !== assetItem?.asset._updatedAt && reset(generateDefaultValues(assetItem?.asset)), assetUpdatedPrev.current = assetItem?.asset._updatedAt;
  }, [assetItem?.asset, generateDefaultValues, reset]);
  const Footer = () => /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 3, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { justify: "space-between", children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.Button,
      {
        disabled: formUpdating,
        fontSize: 1,
        mode: "bleed",
        onClick: handleDelete,
        text: "Delete",
        tone: "critical"
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      FormSubmitButton,
      {
        disabled: formUpdating || !isDirty || !isValid,
        isValid,
        lastUpdated: currentAsset?._updatedAt,
        onClick: handleSubmit(onSubmit)
      }
    )
  ] }) });
  if (!currentAsset)
    return null;
  const detailsProps = {
    control,
    errors,
    formUpdating,
    register,
    setValue,
    assetTagOptions,
    allTagOptions,
    handleCreateTag,
    currentAsset,
    creditLine
  };
  return /* @__PURE__ */ jsxRuntime.jsxs(
    Dialog,
    {
      animate: !0,
      footer: /* @__PURE__ */ jsxRuntime.jsx(Footer, {}),
      header: "Asset details",
      id,
      onClose: handleClose,
      width: 3,
      children: [
        /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { direction: ["column-reverse", "column-reverse", "row-reverse"], children: [
          /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { flex: 1, marginTop: [5, 5, 0], padding: 4, children: /* @__PURE__ */ jsxRuntime.jsx(sanity.WithReferringDocuments, { documentStore, id: currentAsset._id, children: ({ isLoading, referringDocuments }) => {
            const uniqueReferringDocuments = getUniqueDocuments(referringDocuments);
            return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
              /* @__PURE__ */ jsxRuntime.jsxs(ui.TabList, { space: 2, children: [
                /* @__PURE__ */ jsxRuntime.jsx(
                  ui.Tab,
                  {
                    "aria-controls": "details-panel",
                    disabled: formUpdating,
                    id: "details-tab",
                    label: "Details",
                    onClick: () => setTabSection("details"),
                    selected: tabSection === "details",
                    size: 2
                  }
                ),
                /* @__PURE__ */ jsxRuntime.jsx(
                  ui.Tab,
                  {
                    "aria-controls": "references-panel",
                    disabled: formUpdating,
                    id: "references-tab",
                    label: `References${!isLoading && Array.isArray(uniqueReferringDocuments) ? ` (${uniqueReferringDocuments.length})` : ""}`,
                    onClick: () => setTabSection("references"),
                    selected: tabSection === "references",
                    size: 2
                  }
                )
              ] }),
              /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { as: "form", marginTop: 4, onSubmit: handleSubmit(onSubmit), children: [
                !assetItem && /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { marginBottom: 3, padding: 3, radius: 2, shadow: 1, tone: "critical", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: "This file cannot be found \u2013 it may have been deleted." }) }),
                /* @__PURE__ */ jsxRuntime.jsx("button", { style: { display: "none" }, tabIndex: -1, type: "submit" }),
                /* @__PURE__ */ jsxRuntime.jsx(
                  ui.TabPanel,
                  {
                    "aria-labelledby": "details",
                    hidden: tabSection !== "details",
                    id: "details-panel",
                    children: CustomDetails ? /* @__PURE__ */ jsxRuntime.jsx(
                      CustomDetails,
                      {
                        ...detailsProps,
                        renderDefaultDetails
                      }
                    ) : /* @__PURE__ */ jsxRuntime.jsx(Details, { ...detailsProps })
                  }
                ),
                /* @__PURE__ */ jsxRuntime.jsx(
                  ui.TabPanel,
                  {
                    "aria-labelledby": "references",
                    hidden: tabSection !== "references",
                    id: "references-panel",
                    children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginTop: 5, children: assetItem?.asset && /* @__PURE__ */ jsxRuntime.jsx(
                      DocumentList,
                      {
                        documents: uniqueReferringDocuments,
                        isLoading
                      }
                    ) })
                  }
                )
              ] })
            ] });
          } }) }),
          /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { flex: 1, padding: 4, children: [
            /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { style: { aspectRatio: "1" }, children: [
              isFileAsset(currentAsset) && /* @__PURE__ */ jsxRuntime.jsx(FileAssetPreview, { asset: currentAsset }),
              isImageAsset(currentAsset) && /* @__PURE__ */ jsxRuntime.jsx(
                Image$1,
                {
                  draggable: !1,
                  $scheme: scheme,
                  $showCheckerboard: !currentAsset?.metadata?.isOpaque,
                  src: imageDprUrl(currentAsset, { height: 600, width: 600 })
                }
              )
            ] }),
            currentAsset && /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginTop: 4, children: /* @__PURE__ */ jsxRuntime.jsx(AssetMetadata, { asset: currentAsset, item: assetItem }) })
          ] })
        ] }),
        children
      ]
    }
  );
}, DialogConfirm = (props) => {
  const { children, dialog } = props, dispatch = reactRedux.useDispatch(), handleClose = () => {
    dispatch(dialogActions.remove({ id: dialog?.id }));
  }, handleConfirm = () => {
    dialog?.closeDialogId && dispatch(dialogActions.remove({ id: dialog?.closeDialogId })), dialog?.confirmCallbackAction && dispatch(dialog.confirmCallbackAction), handleClose();
  };
  return /* @__PURE__ */ jsxRuntime.jsxs(
    Dialog,
    {
      animate: !0,
      footer: /* @__PURE__ */ jsxRuntime.jsx(() => /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 3, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { justify: "space-between", children: [
        /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { fontSize: 1, mode: "bleed", onClick: handleClose, text: "Cancel" }),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.Button,
          {
            fontSize: 1,
            onClick: handleConfirm,
            text: dialog?.confirmText,
            tone: dialog?.tone
          }
        )
      ] }) }), {}),
      header: /* @__PURE__ */ jsxRuntime.jsx(() => /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", children: [
        /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { paddingX: 1, children: /* @__PURE__ */ jsxRuntime.jsx(icons.WarningOutlineIcon, {}) }),
        /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginLeft: 2, children: dialog?.headerTitle })
      ] }), {}),
      id: "confirm",
      onClose: handleClose,
      width: 1,
      children: [
        /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { paddingX: 4, paddingY: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
          dialog?.title && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: dialog.title }),
          dialog?.description && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 1, children: /* @__PURE__ */ jsxRuntime.jsx("em", { children: dialog.description }) })
        ] }) }),
        children
      ]
    }
  );
}, DialogSearchFacets = (props) => {
  const {
    children,
    dialog: { id }
  } = props, dispatch = reactRedux.useDispatch(), handleClose = react.useCallback(() => {
    dispatch(dialogActions.clear());
  }, []);
  return /* @__PURE__ */ jsxRuntime.jsxs(Dialog, { animate: !0, header: "Filters", id, onClose: handleClose, width: 1, children: [
    /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { padding: 3, children: [
      /* @__PURE__ */ jsxRuntime.jsx(SearchFacets, { layout: "stack" }),
      /* @__PURE__ */ jsxRuntime.jsx(SearchFacetsControl, {})
    ] }),
    children
  ] });
}, DialogTagCreate = (props) => {
  const {
    children,
    dialog: { id }
  } = props, dispatch = reactRedux.useDispatch(), creating = useTypedSelector((state) => state.tags.creating), creatingError = useTypedSelector((state) => state.tags.creatingError), {
    // Read the formState before render to subscribe the form state through Proxy
    formState: { errors, isDirty, isValid },
    handleSubmit,
    register,
    setError
  } = reactHookForm.useForm({
    defaultValues: {
      name: ""
    },
    mode: "onChange",
    resolver: zod.zodResolver(tagFormSchema)
  }), formUpdating = creating, handleClose = () => {
    dispatch(dialogActions.clear());
  }, onSubmit = (formData) => {
    const sanitizedFormData = sanitizeFormData(formData);
    dispatch(tagsActions.createRequest({ name: sanitizedFormData.name }));
  };
  return react.useEffect(() => {
    creatingError && setError("name", {
      message: creatingError?.message
    });
  }, [creatingError, setError]), /* @__PURE__ */ jsxRuntime.jsxs(Dialog, { animate: !0, footer: /* @__PURE__ */ jsxRuntime.jsx(() => /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { justify: "flex-end", children: /* @__PURE__ */ jsxRuntime.jsx(
    FormSubmitButton,
    {
      disabled: formUpdating || !isDirty || !isValid,
      isValid,
      onClick: handleSubmit(onSubmit)
    }
  ) }) }), {}), header: "Create Tag", id, onClose: handleClose, width: 1, children: [
    /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { as: "form", padding: 4, onSubmit: handleSubmit(onSubmit), children: [
      /* @__PURE__ */ jsxRuntime.jsx("button", { style: { display: "none" }, tabIndex: -1, type: "submit" }),
      /* @__PURE__ */ jsxRuntime.jsx(
        FormFieldInputText,
        {
          ...register("name"),
          disabled: formUpdating,
          error: errors?.name?.message,
          label: "Name",
          name: "name"
        }
      )
    ] }),
    children
  ] });
}, DialogTagEdit = (props) => {
  const {
    children,
    dialog: { id, tagId }
  } = props, client = useVersionedClient(), dispatch = reactRedux.useDispatch(), tagItem = useTypedSelector((state) => selectTagById(state, String(tagId))), [tagSnapshot, setTagSnapshot] = react.useState(tagItem?.tag), currentTag = tagItem ? tagItem?.tag : tagSnapshot, generateDefaultValues = (tag) => ({
    name: tag?.name?.current || ""
  }), {
    // Read the formState before render to subscribe the form state through Proxy
    formState: { errors, isDirty, isValid },
    handleSubmit,
    register,
    reset,
    setError
  } = reactHookForm.useForm({
    defaultValues: generateDefaultValues(tagItem?.tag),
    mode: "onChange",
    resolver: zod.zodResolver(tagFormSchema)
  }), formUpdating = !tagItem || tagItem?.updating, handleClose = () => {
    dispatch(dialogActions.remove({ id }));
  }, onSubmit = (formData) => {
    if (!tagItem?.tag)
      return;
    const sanitizedFormData = sanitizeFormData(formData);
    dispatch(
      tagsActions.updateRequest({
        closeDialogId: tagItem?.tag?._id,
        formData: {
          name: {
            _type: "slug",
            current: sanitizedFormData.name
          }
        },
        tag: tagItem?.tag
      })
    );
  }, handleDelete = () => {
    tagItem?.tag && dispatch(
      dialogActions.showConfirmDeleteTag({
        closeDialogId: tagItem?.tag?._id,
        tag: tagItem?.tag
      })
    );
  }, handleTagUpdate = react.useCallback(
    (update) => {
      const { result, transition } = update;
      result && transition === "update" && (setTagSnapshot(result), reset(generateDefaultValues(result)));
    },
    [reset]
  );
  react.useEffect(() => {
    tagItem?.error && setError("name", {
      message: tagItem.error?.message
    });
  }, [setError, tagItem.error]), react.useEffect(() => {
    if (!tagItem?.tag)
      return;
    const subscriptionAsset = client.listen(groq__default.default`*[_id == $id]`, { id: tagItem?.tag._id }).subscribe(handleTagUpdate);
    return () => {
      subscriptionAsset?.unsubscribe();
    };
  }, [client, handleTagUpdate, tagItem?.tag]);
  const Footer = () => /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 3, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { justify: "space-between", children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.Button,
      {
        disabled: formUpdating,
        fontSize: 1,
        mode: "bleed",
        onClick: handleDelete,
        text: "Delete",
        tone: "critical"
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      FormSubmitButton,
      {
        disabled: formUpdating || !isDirty || !isValid,
        isValid,
        lastUpdated: tagItem?.tag?._updatedAt,
        onClick: handleSubmit(onSubmit)
      }
    )
  ] }) });
  return currentTag ? /* @__PURE__ */ jsxRuntime.jsxs(Dialog, { animate: !0, footer: /* @__PURE__ */ jsxRuntime.jsx(Footer, {}), header: "Edit Tag", id, onClose: handleClose, width: 1, children: [
    /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { as: "form", padding: 4, onSubmit: handleSubmit(onSubmit), children: [
      !tagItem && /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { marginBottom: 3, padding: 3, radius: 2, shadow: 1, tone: "critical", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: "This tag cannot be found \u2013 it may have been deleted." }) }),
      /* @__PURE__ */ jsxRuntime.jsx("button", { style: { display: "none" }, tabIndex: -1, type: "submit" }),
      /* @__PURE__ */ jsxRuntime.jsx(
        FormFieldInputText,
        {
          ...register("name"),
          disabled: formUpdating,
          error: errors?.name?.message,
          label: "Name",
          name: "name"
        }
      )
    ] }),
    children
  ] }) : null;
}, TagContainer = styledComponents.styled(ui.Flex)`
  height: ${PANEL_HEIGHT}px;
`, ButtonContainer = styledComponents.styled(ui.Flex)`
  @media (pointer: fine) {
    visibility: hidden;
  }

  @media (hover: hover) and (pointer: fine) {
    ${TagContainer}:hover & {
      visibility: visible;
    }
  }
`, TagButton = (props) => {
  const { disabled, icon, onClick, tone, tooltip } = props;
  return /* @__PURE__ */ jsxRuntime.jsx(
    ui.Tooltip,
    {
      animate: !0,
      content: /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { padding: 2, width: 0, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 1, children: tooltip }) }),
      disabled: "ontouchstart" in window,
      placement: "top",
      portal: !0,
      children: /* @__PURE__ */ jsxRuntime.jsx(
        ui.Button,
        {
          disabled,
          fontSize: 1,
          icon,
          mode: "bleed",
          onClick,
          padding: 2,
          tone
        }
      )
    }
  );
}, Tag = (props) => {
  const { actions, tag } = props, dispatch = reactRedux.useDispatch(), assetsPicked = useTypedSelector(selectAssetsPicked), isSearchFacetTag = useTypedSelector((state) => selectIsSearchFacetTag(state, tag?.tag?._id)), handleSearchFacetTagRemove = () => {
    dispatch(searchActions.facetsRemoveByTag({ tagId: tag.tag._id }));
  }, handleShowAddTagToAssetsDialog = () => {
    dispatch(dialogActions.showConfirmAssetsTagAdd({ assetsPicked, tag: tag.tag }));
  }, handleShowRemoveTagFromAssetsDialog = () => {
    dispatch(dialogActions.showConfirmAssetsTagRemove({ assetsPicked, tag: tag.tag }));
  }, handleShowTagDeleteDialog = () => {
    dispatch(dialogActions.showConfirmDeleteTag({ tag: tag.tag }));
  }, handleShowTagEditDialog = () => {
    dispatch(DIALOG_ACTIONS.showTagEdit({ tagId: tag?.tag?._id }));
  }, handleSearchFacetTagAddOrUpdate = () => {
    const searchFacet = {
      ...inputs.tag,
      value: {
        label: tag?.tag?.name?.current,
        value: tag?.tag?._id
      }
    };
    dispatch(
      isSearchFacetTag ? searchActions.facetsUpdate({
        name: "tag",
        operatorType: "references",
        value: searchFacet.value
      }) : searchActions.facetsAdd({ facet: searchFacet })
    );
  };
  return /* @__PURE__ */ jsxRuntime.jsxs(TagContainer, { align: "center", flex: 1, justify: "space-between", paddingLeft: 3, children: [
    /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { flex: 1, children: /* @__PURE__ */ jsxRuntime.jsx(
      ui.Text,
      {
        muted: !0,
        size: 1,
        style: {
          opacity: tag?.updating ? 0.5 : 1,
          userSelect: "none"
        },
        textOverflow: "ellipsis",
        children: tag?.tag?.name?.current
      }
    ) }),
    /* @__PURE__ */ jsxRuntime.jsxs(ButtonContainer, { align: "center", style: { flexShrink: 0 }, children: [
      actions?.includes("search") && /* @__PURE__ */ jsxRuntime.jsx(
        TagButton,
        {
          disabled: tag?.updating,
          icon: isSearchFacetTag ? /* @__PURE__ */ jsxRuntime.jsx(icons.CloseIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.SearchIcon, {}),
          onClick: isSearchFacetTag ? handleSearchFacetTagRemove : handleSearchFacetTagAddOrUpdate,
          tooltip: isSearchFacetTag ? "Remove filter" : "Filter by tag"
        }
      ),
      actions?.includes("edit") && /* @__PURE__ */ jsxRuntime.jsx(
        TagButton,
        {
          disabled: tag?.updating,
          icon: /* @__PURE__ */ jsxRuntime.jsx(icons.EditIcon, {}),
          onClick: handleShowTagEditDialog,
          tone: "primary",
          tooltip: "Edit tag"
        }
      ),
      actions?.includes("applyAll") && /* @__PURE__ */ jsxRuntime.jsx(
        TagButton,
        {
          disabled: tag?.updating,
          icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpIcon, {}),
          onClick: handleShowAddTagToAssetsDialog,
          tone: "primary",
          tooltip: "Add tag to selected assets"
        }
      ),
      actions?.includes("removeAll") && /* @__PURE__ */ jsxRuntime.jsx(
        TagButton,
        {
          disabled: tag?.updating,
          icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownIcon, {}),
          onClick: handleShowRemoveTagFromAssetsDialog,
          tone: "critical",
          tooltip: "Remove tag from selected assets"
        }
      ),
      actions?.includes("delete") && /* @__PURE__ */ jsxRuntime.jsx(
        TagButton,
        {
          disabled: tag?.updating,
          icon: /* @__PURE__ */ jsxRuntime.jsx(icons.TrashIcon, {}),
          onClick: handleShowTagDeleteDialog,
          tone: "critical",
          tooltip: "Delete tag"
        }
      )
    ] })
  ] });
}, VirtualRow$1 = react.memo(
  ({
    isScrolling,
    item
  }) => typeof item == "string" ? /* @__PURE__ */ jsxRuntime.jsx(
    ui.Flex,
    {
      align: "center",
      justify: "space-between",
      paddingX: 3,
      style: { height: `${PANEL_HEIGHT}px` },
      children: /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: 0, children: item })
    },
    item
  ) : /* @__PURE__ */ jsxRuntime.jsx(Tag, { actions: isScrolling ? void 0 : item.actions, tag: item }, item.tag?._id)
), TagsVirtualized = () => {
  const assetsPicked = useTypedSelector(selectAssetsPicked), tags = useTypedSelector(selectTags), [isScrolling, setIsScrolling] = react.useState(!1), pickedTagIds = assetsPicked?.reduce((acc, val) => {
    const assetTagIds = val?.asset?.opt?.media?.tags?.map((tag) => tag._ref) || [];
    return acc = acc.concat(assetTagIds), acc;
  }, []), pickedTagIdsUnique = [...new Set(pickedTagIds)], tagIdsSegmented = pickedTagIdsUnique.reduce(
    (acc, tagId) => (assetsPicked.every((assetItem) => (assetItem.asset.opt?.media?.tags?.findIndex((tag) => tag._ref === tagId) ?? -1) >= 0) ? acc.appliedToAll.push(tagId) : acc.appliedToSome.push(tagId), acc),
    {
      appliedToAll: [],
      appliedToSome: []
    }
  ), tagsAppliedToAll = tags.filter((tag) => tagIdsSegmented.appliedToAll.includes(tag.tag._id)).map((tagItem) => ({
    ...tagItem,
    actions: ["delete", "edit", "removeAll", "search"]
  })), tagsAppliedToSome = tags.filter((tag) => tagIdsSegmented.appliedToSome.includes(tag.tag._id)).map((tagItem) => ({
    ...tagItem,
    actions: ["applyAll", "delete", "edit", "removeAll", "search"]
  })), tagsUnused = tags.filter((tag) => !pickedTagIdsUnique.includes(tag.tag._id)).map((tagItem) => ({
    ...tagItem,
    actions: ["applyAll", "delete", "edit", "search"]
  }));
  let items = [];
  return assetsPicked.length === 0 ? items = tags.map((tagItem) => ({
    ...tagItem,
    actions: ["delete", "edit", "search"]
  })) : (tagsAppliedToAll?.length > 0 && (items = [
    ...items,
    //
    assetsPicked.length === 1 ? "Used" : "Used by all",
    ...tagsAppliedToAll
  ]), tagsAppliedToSome?.length > 0 && (items = [
    ...items,
    //
    "Used by some",
    ...tagsAppliedToSome
  ]), tagsUnused?.length > 0 && (items = [
    ...items,
    //
    "Unused",
    ...tagsUnused
  ])), /* @__PURE__ */ jsxRuntime.jsx(
    reactVirtuoso.Virtuoso,
    {
      className: "media__custom-scrollbar",
      computeItemKey: (index) => {
        const item = items[index];
        return typeof item == "string" ? item : item.tag._id;
      },
      isScrolling: setIsScrolling,
      itemContent: (index) => /* @__PURE__ */ jsxRuntime.jsx(VirtualRow$1, { isScrolling, item: items[index] }),
      style: { flex: 1, overflowX: "hidden" },
      totalCount: items.length
    }
  );
}, TagViewHeader = ({ allowCreate, light, title }) => {
  const scheme = sanity.useColorSchemeValue(), dispatch = reactRedux.useDispatch(), tagsCreating = useTypedSelector((state) => state.tags.creating), tagsFetching = useTypedSelector((state) => state.tags.fetching), handleTagCreate = () => {
    dispatch(DIALOG_ACTIONS.showTagCreate());
  };
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs(
    ui.Flex,
    {
      align: "center",
      justify: "space-between",
      paddingLeft: 3,
      style: {
        background: light ? getSchemeColor(scheme, "bg") : "inherit",
        borderBottom: "1px solid var(--card-border-color)",
        flexShrink: 0,
        height: `${PANEL_HEIGHT}px`
      },
      children: [
        /* @__PURE__ */ jsxRuntime.jsxs(ui.Inline, { space: 2, children: [
          /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: 0, children: title }),
          tagsFetching && /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: 0, style: { opacity: 0.3 }, children: "Loading..." })
        ] }),
        allowCreate && /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginRight: 1, children: /* @__PURE__ */ jsxRuntime.jsx(
          ui.Button,
          {
            disabled: tagsCreating,
            fontSize: 1,
            icon: icons.ComposeIcon,
            mode: "bleed",
            onClick: handleTagCreate,
            style: {
              background: "transparent",
              boxShadow: "none"
            }
          }
        ) })
      ]
    }
  ) });
}, TagView = () => {
  const numPickedAssets = useTypedSelector(selectAssetsPickedLength), tags = useTypedSelector(selectTags), fetching = useTypedSelector((state) => state.tags.fetching), fetchComplete = useTypedSelector((state) => state.tags.fetchCount) !== -1, hasTags = !fetching && tags?.length > 0, hasPicked = numPickedAssets > 0;
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { direction: "column", flex: 1, height: "fill", children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      TagViewHeader,
      {
        allowCreate: !0,
        light: hasPicked,
        title: hasPicked ? "Tags (in selection)" : "Tags"
      }
    ),
    fetchComplete && !hasTags && /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 1, children: /* @__PURE__ */ jsxRuntime.jsx("em", { children: "No tags" }) }) }),
    hasTags && /* @__PURE__ */ jsxRuntime.jsx(TagsVirtualized, {})
  ] });
}, DialogTags = (props) => {
  const {
    children,
    dialog: { id }
  } = props, dispatch = reactRedux.useDispatch(), handleClose = react.useCallback(() => {
    dispatch(dialogActions.clear());
  }, []);
  return /* @__PURE__ */ jsxRuntime.jsxs(Dialog, { animate: !0, header: "All Tags", id, onClose: handleClose, width: 1, children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.Box,
      {
        style: {
          height: "100%",
          minHeight: "420px"
          // explicit height required as <TagView> is virtualized
        },
        children: /* @__PURE__ */ jsxRuntime.jsx(TagView, {})
      }
    ),
    children
  ] });
}, Dialogs = () => {
  const currentDialogs = useTypedSelector((state) => state.dialog.items), renderDialogs = (dialogs, index) => {
    if (dialogs.length === 0 || index >= dialogs.length)
      return null;
    const dialog = dialogs[index], childDialogs = renderDialogs(dialogs, index + 1);
    return dialog.type === "assetEdit" ? /* @__PURE__ */ jsxRuntime.jsx(DialogAssetEdit, { dialog, children: childDialogs }, index) : dialog.type === "confirm" ? /* @__PURE__ */ jsxRuntime.jsx(DialogConfirm, { dialog, children: childDialogs }, index) : dialog.type === "searchFacets" ? /* @__PURE__ */ jsxRuntime.jsx(DialogSearchFacets, { dialog, children: childDialogs }, index) : dialog.type === "tagCreate" ? /* @__PURE__ */ jsxRuntime.jsx(DialogTagCreate, { dialog, children: childDialogs }, index) : dialog.type === "tagEdit" ? /* @__PURE__ */ jsxRuntime.jsx(DialogTagEdit, { dialog, children: childDialogs }, index) : dialog.type === "tags" ? /* @__PURE__ */ jsxRuntime.jsx(DialogTags, { dialog, children: childDialogs }, index) : null;
  };
  return renderDialogs(currentDialogs, 0);
}, DropzoneDispatchContext = react.createContext(void 0), DropzoneDispatchProvider = (props) => {
  const { children, open } = props, contextValue = { open };
  return /* @__PURE__ */ jsxRuntime.jsx(DropzoneDispatchContext.Provider, { value: contextValue, children });
}, useDropzoneActions = () => {
  const context = react.useContext(DropzoneDispatchContext);
  if (context === void 0)
    throw new Error("useDropzoneActions must be used within an DropzoneDispatchProvider");
  return context;
}, Header = (props) => {
  const { onClose } = props, { open } = useDropzoneActions(), { onSelect } = useAssetSourceActions(), assetTypes = useTypedSelector((state) => state.assets.assetTypes), selectedDocument = useTypedSelector((state) => state.selected.document), { directUploads } = useToolOptions();
  return /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { paddingY: 2, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", justify: "space-between", children: [
    /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { flex: 1, marginX: 3, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Inline, { style: { whiteSpace: "nowrap" }, children: [
      /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { textOverflow: "ellipsis", weight: "semibold", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: onSelect ? `Insert ${assetTypes.join(" or ")}` : "Browse Assets" }) }),
      selectedDocument && /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { display: ["none", "none", "block"], children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { children: [
        /* @__PURE__ */ jsxRuntime.jsx("span", { style: { margin: "0 0.5em" }, children: /* @__PURE__ */ jsxRuntime.jsx(icons.Icon, { symbol: "arrow-right" }) }),
        /* @__PURE__ */ jsxRuntime.jsx("span", { style: { textTransform: "capitalize" }, children: selectedDocument._type })
      ] }) })
    ] }) }),
    /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { marginX: 2, children: [
      directUploads && /* @__PURE__ */ jsxRuntime.jsx(
        ui.Button,
        {
          fontSize: 1,
          icon: icons.UploadIcon,
          mode: "bleed",
          onClick: open,
          text: `Upload ${assetTypes.length === 1 ? pluralize__default.default(assetTypes[0]) : "assets"}`
        }
      ),
      onClose && /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { style: { flexShrink: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(
        ui.Button,
        {
          disabled: !onClose,
          icon: icons.CloseIcon,
          mode: "bleed",
          onClick: onClose,
          radius: 2
        }
      ) })
    ] })
  ] }) });
}, useBreakpointIndex = () => {
  const mediaQueryLists = ui.studioTheme?.container?.map(
    (width) => window.matchMedia(`(max-width: ${width}px)`)
  ), getBreakpointIndex = () => mediaQueryLists.findIndex((mql) => mql.matches), [value, setValue] = react.useState(getBreakpointIndex());
  return react.useEffect(() => {
    const handleBreakpoint = () => {
      setValue(getBreakpointIndex);
    };
    return mediaQueryLists.forEach((mql) => {
      try {
        mql.addEventListener("change", handleBreakpoint);
      } catch {
        try {
          mql.addListener(handleBreakpoint);
        } catch {
        }
      }
    }), () => {
      try {
        mediaQueryLists.forEach((mql) => mql.removeEventListener("change", handleBreakpoint));
      } catch {
        try {
          mediaQueryLists.forEach((mql) => mql.removeListener(handleBreakpoint));
        } catch {
        }
      }
    };
  }, []), value;
}, selectCombinedItems = toolkit.createSelector(
  [
    (state) => state.assets.allIds,
    (state) => state.uploads.allIds
  ],
  (assetIds, uploadIds) => {
    const assetItems = assetIds.map((id) => ({ id, type: "asset" }));
    return [...uploadIds.map((id) => ({ id, type: "upload" })), ...assetItems];
  }
), CardWrapper$1 = styledComponents.styled(ui.Flex)`
  box-sizing: border-box;
  height: 100%;
  overflow: hidden;
  position: relative;
  width: 100%;
`, CardContainer = styledComponents.styled(ui.Flex)(
  ({ $picked, theme, $updating }) => styledComponents.css`
      border: 1px solid transparent;
      height: 100%;
      pointer-events: ${$updating ? "none" : "auto"};
      position: relative;
      transition: all 300ms;
      user-select: none;
      width: 100%;

      border: ${$picked ? `1px solid ${theme.sanity.color.spot.orange} !important` : "1px solid inherit"};

      ${!$updating && styledComponents.css`
        @media (hover: hover) and (pointer: fine) {
          &:hover {
            border: 1px solid var(--card-border-color);
          }
        }
      `}
    `
), ContextActionContainer$2 = styledComponents.styled(ui.Flex)(
  ({ $scheme }) => styledComponents.css`
      cursor: pointer;
      height: ${PANEL_HEIGHT}px;
      transition: all 300ms;
      @media (hover: hover) and (pointer: fine) {
        &:hover {
          background: ${getSchemeColor($scheme, "bg")};
        }
      }
    `
), StyledWarningOutlineIcon = styledComponents.styled(icons.WarningFilledIcon)(({ theme }) => ({
  color: theme.sanity.color.spot.red
})), CardAsset$1 = (props) => {
  const { id, selected } = props, scheme = sanity.useColorSchemeValue(), shiftPressed = useKeyPress("shift"), dispatch = reactRedux.useDispatch(), lastPicked = useTypedSelector((state) => state.assets.lastPicked), item = useTypedSelector((state) => selectAssetById(state, id)), asset = item?.asset, error = item?.error, isOpaque = item?.asset?.metadata?.isOpaque, picked = item?.picked, updating = item?.updating, { onSelect } = useAssetSourceActions();
  if (!asset)
    return null;
  const handleAssetClick = (e) => {
    e.stopPropagation(), onSelect ? onSelect([
      {
        kind: "assetDocumentId",
        value: asset._id
      }
    ]) : shiftPressed.current ? dispatch(picked ? assetsActions.pick({ assetId: asset._id, picked: !picked }) : assetsActions.pickRange({ startId: lastPicked || asset._id, endId: asset._id })) : dispatch(dialogActions.showAssetEdit({ assetId: asset._id }));
  }, handleContextActionClick = (e) => {
    e.stopPropagation(), onSelect ? dispatch(dialogActions.showAssetEdit({ assetId: asset._id })) : shiftPressed.current && !picked ? dispatch(assetsActions.pickRange({ startId: lastPicked || asset._id, endId: asset._id })) : dispatch(assetsActions.pick({ assetId: asset._id, picked: !picked }));
  }, opacityContainer = updating ? 0.5 : 1, opacityPreview = selected || updating ? 0.25 : 1;
  return /* @__PURE__ */ jsxRuntime.jsx(CardWrapper$1, { padding: 1, children: /* @__PURE__ */ jsxRuntime.jsxs(CardContainer, { direction: "column", $picked: picked, $updating: item.updating, children: [
    /* @__PURE__ */ jsxRuntime.jsxs(
      ui.Box,
      {
        flex: 1,
        style: {
          cursor: selected ? "default" : "pointer",
          position: "relative"
        },
        children: [
          /* @__PURE__ */ jsxRuntime.jsxs("div", { onClick: handleAssetClick, style: { height: "100%", opacity: opacityPreview }, children: [
            isFileAsset(asset) && /* @__PURE__ */ jsxRuntime.jsx(FileIcon, { extension: asset.extension, width: "80px" }),
            isImageAsset(asset) && /* @__PURE__ */ jsxRuntime.jsx(
              Image$1,
              {
                draggable: !1,
                $scheme: scheme,
                $showCheckerboard: !isOpaque,
                src: imageDprUrl(asset, { height: 250, width: 250 }),
                style: {
                  draggable: !1,
                  transition: "opacity 1000ms"
                }
              }
            )
          ] }),
          selected && !updating && /* @__PURE__ */ jsxRuntime.jsx(
            ui.Flex,
            {
              align: "center",
              justify: "center",
              style: {
                height: "100%",
                left: 0,
                opacity: opacityContainer,
                position: "absolute",
                top: 0,
                width: "100%"
              },
              children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 2, children: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckmarkCircleIcon, {}) })
            }
          ),
          updating && /* @__PURE__ */ jsxRuntime.jsx(
            ui.Flex,
            {
              align: "center",
              justify: "center",
              style: {
                height: "100%",
                left: 0,
                position: "absolute",
                top: 0,
                width: "100%"
              },
              children: /* @__PURE__ */ jsxRuntime.jsx(ui.Spinner, {})
            }
          )
        ]
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsxs(
      ContextActionContainer$2,
      {
        align: "center",
        onClick: handleContextActionClick,
        paddingX: 1,
        $scheme: scheme,
        style: { opacity: opacityContainer },
        children: [
          onSelect ? /* @__PURE__ */ jsxRuntime.jsx(
            icons.EditIcon,
            {
              style: {
                flexShrink: 0,
                opacity: 0.5
              }
            }
          ) : /* @__PURE__ */ jsxRuntime.jsx(
            ui.Checkbox,
            {
              checked: picked,
              readOnly: !0,
              style: {
                flexShrink: 0,
                pointerEvents: "none",
                transform: "scale(0.8)"
              }
            }
          ),
          /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginLeft: 2, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 0, textOverflow: "ellipsis", children: asset.originalFilename }) })
        ]
      }
    ),
    error && /* @__PURE__ */ jsxRuntime.jsx(
      ui.Box,
      {
        padding: 3,
        style: {
          position: "absolute",
          right: 0,
          top: 0
        },
        children: /* @__PURE__ */ jsxRuntime.jsx(
          ui.Tooltip,
          {
            animate: !0,
            content: /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { padding: 2, width: 0, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: error }) }),
            placement: "left",
            portal: !0,
            children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: /* @__PURE__ */ jsxRuntime.jsx(StyledWarningOutlineIcon, { color: "critical" }) })
          }
        )
      }
    )
  ] }) });
};
var CardAsset = react.memo(CardAsset$1);
const PREVIEW_WIDTH = 180, createBlob = (img) => new Promise((resolve) => {
  const imageAspect = img.width / img.height, canvas = document.createElement("canvas");
  canvas.width = PREVIEW_WIDTH, canvas.height = Math.max(PREVIEW_WIDTH / imageAspect, 1);
  try {
    canvas.getContext("2d")?.drawImage(img, 0, 0, PREVIEW_WIDTH, PREVIEW_WIDTH / imageAspect), canvas.toBlob(resolve, "image/jpeg");
  } catch (err) {
    console.warn("Unable to generate preview image:", err);
  }
}), createImageEl = (file) => new Promise((resolve) => {
  const blobUrlLarge = window.URL.createObjectURL(file), img = new Image();
  img.onload = () => {
    window.URL.revokeObjectURL(blobUrlLarge), resolve(img);
  }, img.src = blobUrlLarge;
}), generatePreviewBlobUrl = async (file) => {
  const imageEl = await createImageEl(file), blob = await createBlob(imageEl);
  if (!blob)
    throw Error("Unable to generate file Blob");
  return window.URL.createObjectURL(blob);
}, generatePreviewBlobUrl$ = (file) => rxjs.of(null).pipe(operators$1.mergeMap(() => rxjs.from(generatePreviewBlobUrl(file)))), DEFAULT_CONCURRENCY = 4;
function remove(array, item) {
  const index = array.indexOf(item);
  return index > -1 && array.splice(index, 1), array;
}
const createThrottler = (concurrency = DEFAULT_CONCURRENCY) => {
  const currentSubscriptions = [], pendingObservables = [], ready$ = new rxjs.Subject();
  function request(observable) {
    return new rxjs.Observable((observer) => {
      if (currentSubscriptions.length >= concurrency)
        return scheduleAndWait$(observable).pipe(operators$1.mergeMap(request)).subscribe(observer);
      const subscription = observable.subscribe(observer);
      return currentSubscriptions.push(subscription), () => {
        for (remove(currentSubscriptions, subscription), remove(pendingObservables, observable), subscription.unsubscribe(); pendingObservables.length > 0 && currentSubscriptions.length < concurrency; )
          ready$.next(pendingObservables.shift());
      };
    });
  }
  function scheduleAndWait$(observable) {
    return pendingObservables.push(observable), ready$.asObservable().pipe(operators$1.first((obs) => obs === observable));
  }
  return request;
}, withMaxConcurrency = (func, concurrency = DEFAULT_CONCURRENCY) => {
  const throttler = createThrottler(concurrency);
  return (...args) => rxjs.from(throttler(func(...args)));
}, fetchExisting$ = (client, type, hash) => client.observable.fetch("*[_type == $documentType && sha1hash == $hash][0]", {
  documentType: type,
  hash
}), readFile$ = (file) => new rxjs.Observable((subscriber) => {
  const reader = new FileReader();
  return reader.onload = () => {
    subscriber.next(reader.result), subscriber.complete();
  }, reader.onerror = (err) => {
    subscriber.error(err);
  }, reader.readAsArrayBuffer(file), () => {
    reader.abort();
  };
}), hexFromBuffer = (buffer) => Array.prototype.map.call(new Uint8Array(buffer), (x) => `00${x.toString(16)}`.slice(-2)).join(""), hashFile$ = (file) => !window.crypto || !window.crypto.subtle || !window.FileReader ? rxjs.throwError({
  message: "Unable to generate hash: uploads are only allowed in secure contexts",
  statusCode: 500
}) : readFile$(file).pipe(
  operators$1.mergeMap((arrayBuffer) => window.crypto.subtle.digest("SHA-1", arrayBuffer)),
  operators$1.map(hexFromBuffer)
), uploadSanityAsset$ = (client, assetType, file, hash) => rxjs.of(null).pipe(
  // NOTE: the sanity api will still dedupe unique files, but this saves us from uploading the asset file entirely
  operators$1.mergeMap(() => fetchExisting$(client, `sanity.${assetType}Asset`, hash)),
  // Cancel if the asset already exists
  operators$1.mergeMap((existingAsset) => existingAsset ? rxjs.throwError({
    message: "Asset already exists",
    statusCode: 409
  }) : rxjs.of(null)),
  operators$1.mergeMap(() => client.observable.assets.upload(assetType, file, {
    extract: ["blurhash", "exif", "location", "lqip", "palette"],
    preserveFilename: !0
  }).pipe(
    operators$1.map(
      (event) => event.type === "response" ? {
        // rewrite to a 'complete' event
        asset: event.body.document,
        id: event.body.document._id,
        type: "complete"
      } : event
    )
  ))
), uploadAsset$ = withMaxConcurrency(uploadSanityAsset$), initialState$2 = {
  allIds: [],
  byIds: {}
}, uploadsSlice = toolkit.createSlice({
  name: "uploads",
  initialState: initialState$2,
  extraReducers: (builder) => {
    builder.addCase(UPLOADS_ACTIONS.uploadComplete, (state, action) => {
      const { asset } = action.payload;
      state.byIds[asset.sha1hash] && (state.byIds[asset.sha1hash].status = "complete");
    });
  },
  reducers: {
    checkRequest(_state, _action) {
    },
    checkComplete(state, action) {
      const { results } = action.payload;
      Object.keys(results).forEach((hash) => {
        const deleteIndex = state.allIds.indexOf(hash);
        if (deleteIndex >= 0 && state.allIds.splice(deleteIndex, 1), state.byIds[hash]) {
          const blobUrl = state.byIds[hash].objectUrl;
          blobUrl && window.URL.revokeObjectURL(blobUrl), delete state.byIds[hash];
        }
      });
    },
    previewReady(state, action) {
      const { blobUrl, hash } = action.payload;
      state.byIds[hash] && (state.byIds[hash].objectUrl = blobUrl);
    },
    uploadCancel(state, action) {
      const { hash } = action.payload, deleteIndex = state.allIds.indexOf(hash);
      deleteIndex >= 0 && state.allIds.splice(deleteIndex, 1), state.byIds[hash] && delete state.byIds[hash];
    },
    uploadError(state, action) {
      const { hash } = action.payload, deleteIndex = state.allIds.indexOf(hash);
      deleteIndex >= 0 && state.allIds.splice(deleteIndex, 1), delete state.byIds[hash];
    },
    uploadRequest(_state, _action) {
    },
    uploadProgress(state, action) {
      const { event, uploadHash } = action.payload;
      state.byIds[uploadHash].percent = event.percent, state.byIds[uploadHash].status = "uploading";
    },
    uploadStart(state, action) {
      const { uploadItem } = action.payload;
      state.allIds.includes(uploadItem.hash) || state.allIds.push(uploadItem.hash), state.byIds[uploadItem.hash] = uploadItem;
    }
  }
}), uploadsAssetStartEpic = (action$, _state$, { client }) => action$.pipe(
  operators$1.filter(uploadsActions.uploadStart.match),
  operators$1.mergeMap((action) => {
    const { file, uploadItem } = action.payload;
    return rxjs.merge(
      // Generate low res preview
      rxjs.of(null).pipe(
        operators$1.mergeMap(() => generatePreviewBlobUrl$(file)),
        operators$1.mergeMap((url) => rxjs.of(
          uploadsActions.previewReady({
            blobUrl: url,
            hash: uploadItem.hash
          })
        ))
      ),
      // Upload asset and receive progress / complete events
      rxjs.of(null).pipe(
        // delay(500000), // debug uploads
        operators$1.mergeMap(() => uploadAsset$(client, uploadItem.assetType, file, uploadItem.hash)),
        operators$1.takeUntil(
          action$.pipe(
            operators$1.filter(uploadsActions.uploadCancel.match),
            operators$1.filter((v) => v.payload.hash === uploadItem.hash)
          )
        ),
        operators$1.mergeMap((event) => event?.type === "complete" ? rxjs.of(
          UPLOADS_ACTIONS.uploadComplete({
            asset: event.asset
          })
        ) : event?.type === "progress" && event?.stage === "upload" ? rxjs.of(
          uploadsActions.uploadProgress({
            event,
            uploadHash: uploadItem.hash
          })
        ) : rxjs.empty()),
        operators$1.catchError(
          (error) => rxjs.of(
            uploadsActions.uploadError({
              error: {
                message: error?.message || "Internal error",
                statusCode: error?.statusCode || 500
              },
              hash: uploadItem.hash
            })
          )
        )
      )
    );
  })
), uploadsAssetUploadEpic = (action$, state$) => action$.pipe(
  operators$1.filter(uploadsActions.uploadRequest.match),
  operators$1.withLatestFrom(state$),
  operators$1.mergeMap(([action, state]) => {
    const { file, forceAsAssetType } = action.payload;
    return rxjs.of(action).pipe(
      // Generate SHA1 hash from local file
      // This will throw in insecure contexts (non-localhost / https)
      operators$1.mergeMap(() => hashFile$(file)),
      // Ignore if the file exists and is currently being uploaded
      operators$1.filter((hash) => !state.uploads.byIds[hash]),
      // Dispatch start action and begin upload process
      operators$1.mergeMap((hash) => {
        const uploadItem = {
          _type: "upload",
          assetType: forceAsAssetType || (file.type.indexOf("image") >= 0 ? "image" : "file"),
          hash,
          name: file.name,
          size: file.size,
          status: "queued"
        };
        return rxjs.of(uploadsActions.uploadStart({ file, uploadItem }));
      })
    );
  })
), uploadsCompleteQueueEpic = (action$) => action$.pipe(
  operators$1.filter(UPLOADS_ACTIONS.uploadComplete.match),
  operators$1.mergeMap((action) => rxjs.of(
    uploadsActions.checkRequest({
      assets: [action.payload.asset]
    })
  ))
), uploadsCheckRequestEpic = (action$, state$, { client }) => action$.pipe(
  operators$1.filter(uploadsActions.checkRequest.match),
  operators$1.withLatestFrom(state$),
  operators$1.mergeMap(([action, state]) => {
    const { assets } = action.payload, documentIds = assets.map((asset) => asset._id), constructedFilter = constructFilter({
      assetTypes: state.assets.assetTypes,
      searchFacets: state.search.facets,
      searchQuery: state.search.query
    }), query = groq__default.default`
        *[${constructedFilter} && _id in $documentIds].sha1hash
      `;
    return rxjs.of(action).pipe(
      operators$1.delay(1e3),
      // give Sanity some time to register the recently uploaded asset
      operators$1.mergeMap(() => client.observable.fetch(query, { documentIds })),
      operators$1.mergeMap((resultHashes) => {
        const checkedResults = assets.reduce((acc, asset) => (acc[asset.sha1hash] = resultHashes.includes(asset.sha1hash) ? asset._id : null, acc), {});
        return rxjs.of(
          uploadsActions.checkComplete({ results: checkedResults }),
          //
          assetsActions.insertUploads({ results: checkedResults })
        );
      })
    );
  })
), selectUploadsByIds = (state) => state.uploads.byIds, selectUploadsAllIds = (state) => state.uploads.allIds, selectUploadById = toolkit.createSelector(
  [
    (state) => state.uploads.byIds,
    (_state, uploadId) => uploadId
  ],
  (byIds, uploadId) => byIds[uploadId]
);
toolkit.createSelector(
  [selectUploadsByIds, selectUploadsAllIds],
  (byIds, allIds) => allIds.map((id) => byIds[id])
);
const uploadsActions = { ...uploadsSlice.actions };
var uploadsReducer = uploadsSlice.reducer;
const CardWrapper = styledComponents.styled(ui.Flex)`
  box-sizing: border-box;
  height: 100%;
  overflow: hidden;
  position: relative;
  width: 100%;
`, CardUpload = (props) => {
  const { id } = props, scheme = sanity.useColorSchemeValue(), dispatch = reactRedux.useDispatch(), item = useTypedSelector((state) => selectUploadById(state, id));
  if (!item)
    return null;
  const fileSize = filesize__default.default(item.size, { base: 10, round: 0 }), percentLoaded = Math.round(item.percent || 0), isComplete = item.status === "complete", isUploading = item.status === "uploading", isQueued = item.status === "queued";
  let status;
  isComplete && (status = "Verifying"), isUploading && (status = `${percentLoaded}%`), isQueued && (status = "Queued");
  const handleCancelUpload = () => {
    dispatch(uploadsActions.uploadCancel({ hash: item.hash }));
  };
  return /* @__PURE__ */ jsxRuntime.jsx(CardWrapper, { padding: 1, children: /* @__PURE__ */ jsxRuntime.jsxs(
    ui.Flex,
    {
      direction: "column",
      flex: 1,
      style: {
        background: getSchemeColor(scheme, "bg"),
        border: "1px solid transparent",
        height: "100%",
        position: "relative"
      },
      children: [
        /* @__PURE__ */ jsxRuntime.jsx(
          "div",
          {
            style: {
              background: "var(--card-fg-color)",
              bottom: 0,
              height: "1px",
              left: 0,
              position: "absolute",
              width: "100%",
              transform: `scaleX(${percentLoaded * 0.01})`,
              transformOrigin: "bottom left",
              transition: "all 1000ms ease-out"
            }
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { flex: 1, style: { position: "relative" }, children: [
          item.assetType === "image" && item?.objectUrl && /* @__PURE__ */ jsxRuntime.jsx(
            Image$1,
            {
              draggable: !1,
              $scheme: scheme,
              src: item.objectUrl,
              style: {
                opacity: 0.4
              }
            }
          ),
          item.assetType === "file" && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: "100%", opacity: 0.1 }, children: /* @__PURE__ */ jsxRuntime.jsx(FileIcon, { width: "80px" }) }),
          !isComplete && percentLoaded !== 100 && /* @__PURE__ */ jsxRuntime.jsx(
            ui.Flex,
            {
              align: "center",
              direction: "column",
              justify: "center",
              style: {
                height: "100%",
                left: 0,
                position: "absolute",
                top: 0,
                width: "100%"
              },
              children: /* @__PURE__ */ jsxRuntime.jsx(
                ui.Button,
                {
                  fontSize: 4,
                  icon: icons.CloseIcon,
                  mode: "bleed",
                  onClick: handleCancelUpload,
                  padding: 2,
                  style: { background: "none", boxShadow: "none" },
                  tone: "critical"
                }
              )
            }
          )
        ] }),
        /* @__PURE__ */ jsxRuntime.jsxs(
          ui.Flex,
          {
            align: "center",
            justify: "space-between",
            paddingX: 2,
            style: { height: `${PANEL_HEIGHT}px` },
            children: [
              /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { flex: 1, marginRight: 1, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: 0, textOverflow: "ellipsis", children: [
                item.name,
                " (",
                fileSize,
                ")"
              ] }) }),
              /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 0, style: { flexShrink: 0 }, weight: "semibold", children: status })
            ]
          }
        )
      ]
    }
  ) });
}, CARD_HEIGHT = 220, CARD_WIDTH = 240, VirtualCell = react.memo(
  ({ item, selected }) => item?.type === "asset" ? /* @__PURE__ */ jsxRuntime.jsx(CardAsset, { id: item.id, selected }) : item?.type === "upload" ? /* @__PURE__ */ jsxRuntime.jsx(CardUpload, { id: item.id }) : null
), StyledItemContainer = styledComponents.styled.div`
  height: ${CARD_HEIGHT}px;
  width: ${CARD_WIDTH}px;
`, ItemContainer = react.forwardRef((props, ref) => {
  const { context, ...rest } = props;
  return /* @__PURE__ */ jsxRuntime.jsx(StyledItemContainer, { ref, ...rest });
}), StyledListContainer = styledComponents.styled.div`
  display: grid;
  grid-template-columns: repeat(auto-fill, ${CARD_WIDTH}px);
  grid-template-rows: repeat(auto-fill, ${CARD_HEIGHT}px);
  justify-content: center;
  margin: 0 auto;
`, ListContainer = react.forwardRef((props, ref) => {
  const { context, ...rest } = props;
  return /* @__PURE__ */ jsxRuntime.jsx(StyledListContainer, { ref, ...rest });
}), AssetGridVirtualized = (props) => {
  const { items, onLoadMore } = props, selectedAssets = useTypedSelector((state) => state.selected.assets), selectedIds = selectedAssets && selectedAssets.map((asset) => asset._id) || [], totalCount = items?.length;
  return totalCount === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(
    reactVirtuoso.VirtuosoGrid,
    {
      className: "media__custom-scrollbar",
      computeItemKey: (index) => items[index]?.id,
      components: {
        Item: ItemContainer,
        List: ListContainer
      },
      endReached: onLoadMore,
      itemContent: (index) => {
        const item = items[index], selected = selectedIds.includes(item?.id);
        return /* @__PURE__ */ jsxRuntime.jsx(VirtualCell, { item, selected });
      },
      overscan: 48,
      style: { overflowX: "hidden", overflowY: "scroll" },
      totalCount
    }
  );
}, TableHeaderItem = (props) => {
  const { field, title } = props, dispatch = reactRedux.useDispatch(), order = useTypedSelector((state) => state.assets.order), isActive = order.field === field;
  return /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { muted: !field, size: 0, children: /* @__PURE__ */ jsxRuntime.jsxs(
    ui.Box,
    {
      onClick: field ? () => {
        if (!(!field || !title))
          if (isActive) {
            const direction = order.direction === "asc" ? "desc" : "asc";
            dispatch(assetsActions.orderSet({ order: { field, direction } }));
          } else
            dispatch(assetsActions.orderSet({ order: { field, direction: "asc" } }));
      } : void 0,
      style: {
        cursor: field ? "pointer" : "default",
        display: "inline",
        whiteSpace: "nowrap"
      },
      children: [
        /* @__PURE__ */ jsxRuntime.jsx(
          "span",
          {
            style: {
              marginRight: "0.4em"
            },
            children: title
          }
        ),
        isActive && order?.direction === "asc" && /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronUpIcon, {}),
        isActive && order?.direction === "desc" && /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDownIcon, {})
      ]
    }
  ) });
}, ContextActionContainer$1 = styledComponents.styled(ui.Flex)(
  ({ $scheme }) => styledComponents.css`
      cursor: pointer;
      @media (hover: hover) and (pointer: fine) {
        &:hover {
          background: ${getSchemeColor($scheme, "bg")};
        }
      }
    `
), TableHeader = () => {
  const scheme = sanity.useColorSchemeValue(), dispatch = reactRedux.useDispatch(), fetching = useTypedSelector((state) => state.assets.fetching), itemsLength = useTypedSelector(selectAssetsLength), numPickedAssets = useTypedSelector(selectAssetsPickedLength), mediaIndex = ui.useMediaIndex(), { onSelect } = useAssetSourceActions(), allSelected = numPickedAssets === itemsLength, handleContextActionClick = (e) => {
    e.stopPropagation(), dispatch(allSelected ? assetsActions.pickClear() : assetsActions.pickAll());
  };
  return /* @__PURE__ */ jsxRuntime.jsxs(
    ui.Grid,
    {
      style: {
        alignItems: "center",
        background: "var(--card-bg-color)",
        borderBottom: "1px solid var(--card-border-color)",
        gridColumnGap: mediaIndex < 3 ? 0 : "16px",
        gridTemplateColumns: GRID_TEMPLATE_COLUMNS.LARGE,
        height: mediaIndex < 3 ? 0 : `${PANEL_HEIGHT}px`,
        letterSpacing: "0.025em",
        position: "sticky",
        textTransform: "uppercase",
        top: 0,
        visibility: mediaIndex < 3 ? "hidden" : "visible",
        width: "100%",
        zIndex: 1
        // force stacking context
      },
      children: [
        onSelect ? /* @__PURE__ */ jsxRuntime.jsx(TableHeaderItem, {}) : /* @__PURE__ */ jsxRuntime.jsx(
          ContextActionContainer$1,
          {
            align: "center",
            justify: "center",
            onClick: handleContextActionClick,
            $scheme: scheme,
            style: {
              height: "100%",
              position: "relative"
            },
            children: /* @__PURE__ */ jsxRuntime.jsx(
              ui.Checkbox,
              {
                checked: !fetching && allSelected,
                readOnly: !0,
                style: {
                  pointerEvents: "none",
                  // TODO: consider alternative for usability
                  transform: "scale(0.8)"
                }
              }
            )
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(TableHeaderItem, {}),
        /* @__PURE__ */ jsxRuntime.jsx(TableHeaderItem, { field: "originalFilename", title: "Filename" }),
        /* @__PURE__ */ jsxRuntime.jsx(TableHeaderItem, { title: "Resolution" }),
        /* @__PURE__ */ jsxRuntime.jsx(TableHeaderItem, { field: "mimeType", title: "MIME type" }),
        /* @__PURE__ */ jsxRuntime.jsx(TableHeaderItem, { field: "size", title: "Size" }),
        /* @__PURE__ */ jsxRuntime.jsx(TableHeaderItem, { field: "_updatedAt", title: "Last updated" }),
        /* @__PURE__ */ jsxRuntime.jsx(TableHeaderItem, { title: "References" }),
        /* @__PURE__ */ jsxRuntime.jsx(TableHeaderItem, {})
      ]
    }
  );
}, REFERENCE_COUNT_VISIBILITY_DELAY = 750, ContainerGrid = styledComponents.styled(ui.Grid)(({ $scheme, $selected, $updating }) => styledComponents.css`
    align-items: center;
    cursor: ${$selected ? "default" : "pointer"};
    height: 100%;
    pointer-events: ${$updating ? "none" : "auto"};
    user-select: none;
    white-space: nowrap;

    ${!$updating && styledComponents.css`
      @media (hover: hover) and (pointer: fine) {
        &:hover {
          background: ${getSchemeColor($scheme, "bg")};
        }
      }
    `}
  `), ContextActionContainer = styledComponents.styled(ui.Flex)(
  ({ $scheme }) => styledComponents.css`
      cursor: pointer;
      @media (hover: hover) and (pointer: fine) {
        &:hover {
          background: ${getSchemeColor($scheme, "bg2")};
        }
      }
    `
), StyledWarningIcon = styledComponents.styled(icons.WarningFilledIcon)(({ theme }) => ({
  color: theme.sanity.color.spot.red
})), TableRowAsset$1 = (props) => {
  const { id, selected } = props, scheme = sanity.useColorSchemeValue(), shiftPressed = useKeyPress("shift"), [referenceCountVisible, setReferenceCountVisible] = react.useState(!1), refCountVisibleTimeout = react.useRef(null), dispatch = reactRedux.useDispatch(), lastPicked = useTypedSelector((state) => state.assets.lastPicked), item = useTypedSelector((state) => selectAssetById(state, id)), mediaIndex = ui.useMediaIndex(), asset = item?.asset, error = item?.error, isOpaque = item?.asset?.metadata?.isOpaque, picked = item?.picked, updating = item?.updating, { onSelect } = useAssetSourceActions(), handleContextActionClick = react.useCallback(
    (e) => {
      e.stopPropagation(), asset && (onSelect ? dispatch(dialogActions.showAssetEdit({ assetId: asset._id })) : shiftPressed.current && !picked ? dispatch(assetsActions.pickRange({ startId: lastPicked || asset._id, endId: asset._id })) : dispatch(assetsActions.pick({ assetId: asset._id, picked: !picked })));
    },
    [asset, dispatch, lastPicked, onSelect, picked, shiftPressed]
  ), handleClick = react.useCallback(
    (e) => {
      e.stopPropagation(), asset && (onSelect ? onSelect([{ kind: "assetDocumentId", value: asset._id }]) : shiftPressed.current ? dispatch(picked ? assetsActions.pick({ assetId: asset._id, picked: !picked }) : assetsActions.pickRange({ startId: lastPicked || asset._id, endId: asset._id })) : dispatch(dialogActions.showAssetEdit({ assetId: asset._id })));
    },
    [asset, dispatch, lastPicked, onSelect, picked, shiftPressed]
  ), opacityCell = updating ? 0.5 : 1, opacityPreview = selected || updating ? 0.1 : 1;
  return react.useEffect(() => (refCountVisibleTimeout.current = setTimeout(
    () => setReferenceCountVisible(!0),
    REFERENCE_COUNT_VISIBILITY_DELAY
  ), () => {
    refCountVisibleTimeout.current && clearTimeout(refCountVisibleTimeout.current);
  }), []), asset ? /* @__PURE__ */ jsxRuntime.jsxs(
    ContainerGrid,
    {
      onClick: selected ? void 0 : handleClick,
      $scheme: scheme,
      $selected: selected,
      style: {
        gridColumnGap: mediaIndex < 3 ? 0 : "16px",
        gridRowGap: 0,
        gridTemplateColumns: mediaIndex < 3 ? GRID_TEMPLATE_COLUMNS.SMALL : GRID_TEMPLATE_COLUMNS.LARGE,
        gridTemplateRows: mediaIndex < 3 ? "auto" : "1fr"
      },
      $updating: item.updating,
      children: [
        /* @__PURE__ */ jsxRuntime.jsx(
          ContextActionContainer,
          {
            onClick: handleContextActionClick,
            $scheme: scheme,
            style: {
              alignItems: "center",
              gridColumn: 1,
              gridRowStart: 1,
              gridRowEnd: "span 5",
              height: "100%",
              justifyContent: "center",
              opacity: opacityCell,
              position: "relative"
            },
            children: onSelect ? /* @__PURE__ */ jsxRuntime.jsx(
              icons.EditIcon,
              {
                style: {
                  flexShrink: 0,
                  opacity: 0.5
                }
              }
            ) : /* @__PURE__ */ jsxRuntime.jsx(
              ui.Checkbox,
              {
                checked: picked,
                readOnly: !0,
                style: {
                  pointerEvents: "none",
                  // TODO: consider alternative for usability
                  transform: "scale(0.8)"
                }
              }
            )
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.Box,
          {
            style: {
              gridColumn: 2,
              gridRowStart: 1,
              gridRowEnd: "span 5",
              height: "90px",
              width: "100px"
            },
            children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", justify: "center", style: { height: "100%", position: "relative" }, children: [
              /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { style: { height: "100%", opacity: opacityPreview, position: "relative" }, children: [
                isFileAsset(asset) && /* @__PURE__ */ jsxRuntime.jsx(FileIcon, { extension: asset.extension, width: "40px" }),
                isImageAsset(asset) && /* @__PURE__ */ jsxRuntime.jsx(
                  Image$1,
                  {
                    draggable: !1,
                    $scheme: scheme,
                    $showCheckerboard: !isOpaque,
                    src: imageDprUrl(asset, { height: 100, width: 100 })
                  }
                )
              ] }),
              updating && /* @__PURE__ */ jsxRuntime.jsx(
                ui.Flex,
                {
                  align: "center",
                  justify: "center",
                  style: {
                    height: "100%",
                    left: 0,
                    position: "absolute",
                    top: 0,
                    width: "100%"
                  },
                  children: /* @__PURE__ */ jsxRuntime.jsx(ui.Spinner, {})
                }
              ),
              selected && !updating && /* @__PURE__ */ jsxRuntime.jsx(
                ui.Flex,
                {
                  align: "center",
                  justify: "center",
                  style: {
                    height: "100%",
                    left: 0,
                    position: "absolute",
                    top: 0,
                    width: "100%"
                  },
                  children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 2, children: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckmarkCircleIcon, {}) })
                }
              )
            ] })
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.Box,
          {
            marginLeft: mediaIndex < 3 ? 3 : 0,
            style: {
              gridColumn: 3,
              gridRow: mediaIndex < 3 ? 2 : "auto",
              opacity: opacityCell
            },
            children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 1, style: { lineHeight: "2em" }, textOverflow: "ellipsis", children: asset.originalFilename })
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.Box,
          {
            marginLeft: mediaIndex < 3 ? 3 : 0,
            style: {
              gridColumn: mediaIndex < 3 ? 3 : 4,
              gridRow: mediaIndex < 3 ? 3 : "auto",
              opacity: opacityCell
            },
            children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 1, style: { lineHeight: "2em" }, textOverflow: "ellipsis", children: isImageAsset(asset) && getAssetResolution(asset) })
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.Box,
          {
            style: {
              display: mediaIndex < 3 ? "none" : "block",
              gridColumn: 5,
              gridRow: "auto",
              opacity: opacityCell
            },
            children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 1, style: { lineHeight: "2em" }, textOverflow: "ellipsis", children: asset.mimeType })
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.Box,
          {
            style: {
              display: mediaIndex < 3 ? "none" : "block",
              gridColumn: 6,
              gridRow: "auto",
              opacity: opacityCell
            },
            children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 1, style: { lineHeight: "2em" }, textOverflow: "ellipsis", children: filesize__default.default(asset.size, { base: 10, round: 0 }) })
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.Box,
          {
            marginLeft: mediaIndex < 3 ? 3 : 0,
            style: {
              gridColumn: mediaIndex < 3 ? 3 : 7,
              gridRow: mediaIndex < 3 ? 4 : "auto",
              opacity: opacityCell
            },
            children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 1, style: { lineHeight: "2em" }, textOverflow: "ellipsis", children: dateFns.formatRelative(new Date(asset._updatedAt), /* @__PURE__ */ new Date()) })
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.Box,
          {
            style: {
              display: mediaIndex < 3 ? "none" : "block",
              gridColumn: 8,
              gridRow: "auto",
              opacity: opacityCell
            },
            children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, size: 1, style: { lineHeight: "2em" }, textOverflow: "ellipsis", children: referenceCountVisible ? /* @__PURE__ */ jsxRuntime.jsx(sanity.WithReferringDocuments, { id, children: ({ isLoading, referringDocuments }) => {
              const uniqueDocuments = getUniqueDocuments(referringDocuments);
              return isLoading ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: "-" }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.isArray(uniqueDocuments) ? uniqueDocuments.length : 0 });
            } }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: "-" }) })
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.Flex,
          {
            align: "center",
            justify: "center",
            style: {
              gridColumn: mediaIndex < 3 ? 4 : 9,
              gridRowStart: "1",
              gridRowEnd: mediaIndex < 3 ? "span 5" : "auto",
              opacity: opacityCell
            },
            children: error && /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
              ui.Tooltip,
              {
                animate: !0,
                content: /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { padding: 2, width: 0, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: error }) }),
                placement: "left",
                portal: !0,
                children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: /* @__PURE__ */ jsxRuntime.jsx(StyledWarningIcon, { color: "critical" }) })
              }
            ) })
          }
        )
      ]
    }
  ) : null;
};
var TableRowAsset = react.memo(TableRowAsset$1);
const TableRowUpload = (props) => {
  const { id } = props, scheme = sanity.useColorSchemeValue(), dispatch = reactRedux.useDispatch(), item = useTypedSelector((state) => selectUploadById(state, id)), mediaIndex = ui.useMediaIndex();
  if (!item)
    return null;
  const fileSize = filesize__default.default(item.size, { base: 10, round: 0 }), percentLoaded = Math.round(item.percent || 0), isComplete = item.status === "complete", isUploading = item.status === "uploading", isQueued = item.status === "queued";
  let status;
  isComplete && (status = "Verifying"), isUploading && (status = `${percentLoaded}%`), isQueued && (status = "Queued");
  const handleCancelUpload = () => {
    dispatch(uploadsActions.uploadCancel({ hash: item.hash }));
  };
  return /* @__PURE__ */ jsxRuntime.jsxs(
    ui.Grid,
    {
      style: {
        alignItems: "center",
        background: getSchemeColor(scheme, "bg"),
        gridColumnGap: mediaIndex < 3 ? 0 : "16px",
        gridRowGap: 0,
        gridTemplateColumns: mediaIndex < 3 ? GRID_TEMPLATE_COLUMNS.SMALL : GRID_TEMPLATE_COLUMNS.LARGE,
        gridTemplateRows: mediaIndex < 3 ? "auto" : "1fr",
        height: "100%",
        position: "relative"
      },
      children: [
        /* @__PURE__ */ jsxRuntime.jsx(
          "div",
          {
            style: {
              background: "var(--card-fg-color)",
              bottom: 0,
              height: "1px",
              left: 0,
              position: "absolute",
              width: "100%",
              transform: `scaleX(${percentLoaded * 0.01})`,
              transformOrigin: "bottom left",
              transition: "all 1000ms ease-out"
            }
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.Box,
          {
            style: {
              gridColumn: 2,
              gridRowStart: mediaIndex < 3 ? 1 : "auto",
              gridRowEnd: mediaIndex < 3 ? "span 4" : "auto",
              height: "90px",
              width: "100px"
            },
            children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { style: { height: "100%", position: "relative" }, children: [
              item.assetType === "image" && item?.objectUrl && /* @__PURE__ */ jsxRuntime.jsx(
                Image$1,
                {
                  draggable: !1,
                  $scheme: scheme,
                  src: item.objectUrl,
                  style: { opacity: 0.25 }
                }
              ),
              item.assetType === "file" && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: "100%", opacity: 0.1 }, children: /* @__PURE__ */ jsxRuntime.jsx(FileIcon, { width: "40px" }) }),
              !isComplete && percentLoaded !== 100 && /* @__PURE__ */ jsxRuntime.jsx(
                ui.Flex,
                {
                  align: "center",
                  justify: "center",
                  style: {
                    position: "absolute",
                    height: "100%",
                    left: 0,
                    top: 0,
                    width: "100%"
                  },
                  children: /* @__PURE__ */ jsxRuntime.jsx(
                    ui.Button,
                    {
                      fontSize: 3,
                      icon: icons.CloseIcon,
                      mode: "bleed",
                      onClick: handleCancelUpload,
                      padding: 2,
                      style: { background: "none", boxShadow: "none" },
                      tone: "critical"
                    }
                  )
                }
              )
            ] })
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.Box,
          {
            style: {
              gridColumn: mediaIndex < 3 ? 3 : "3/8",
              gridRow: mediaIndex < 3 ? "2/4" : "auto",
              marginLeft: mediaIndex < 3 ? 3 : 0
            },
            children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
              /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { muted: !0, size: 1, textOverflow: "ellipsis", children: [
                item.name,
                " (",
                fileSize,
                ")"
              ] }),
              /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, textOverflow: "ellipsis", weight: "semibold", children: status })
            ] })
          }
        )
      ]
    }
  );
}, VirtualRow = react.memo(
  ({ item, selected }) => item?.type === "asset" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { style: { height: "100px" }, children: /* @__PURE__ */ jsxRuntime.jsx(TableRowAsset, { id: item.id, selected }) }) : item?.type === "upload" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { style: { height: "100px" }, children: /* @__PURE__ */ jsxRuntime.jsx(TableRowUpload, { id: item.id }) }) : null
), AssetTableVirtualized = (props) => {
  const { items, onLoadMore } = props, selectedAssets = useTypedSelector((state) => state.selected.assets), selectedIds = selectedAssets && selectedAssets.map((asset) => asset._id) || [], totalCount = items?.length;
  return totalCount === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(
    reactVirtuoso.GroupedVirtuoso,
    {
      className: "media__custom-scrollbar",
      computeItemKey: (index) => items[index]?.id || index,
      endReached: onLoadMore,
      groupCounts: Array(1).fill(totalCount),
      groupContent: () => /* @__PURE__ */ jsxRuntime.jsx(TableHeader, {}),
      itemContent: (index) => {
        const item = items[index], selected = selectedIds.includes(item?.id);
        return /* @__PURE__ */ jsxRuntime.jsx(VirtualRow, { item, selected });
      },
      style: { overflowX: "hidden" }
    }
  );
}, Items = () => {
  const dispatch = reactRedux.useDispatch(), fetchCount = useTypedSelector((state) => state.assets.fetchCount), fetching = useTypedSelector((state) => state.assets.fetching), tagsPanelVisible = useTypedSelector((state) => state.tags.panelVisible), view = useTypedSelector((state) => state.assets.view), combinedItems = useTypedSelector(selectCombinedItems), breakpointIndex = useBreakpointIndex(), hasFetchedOnce = fetchCount >= 0, hasItems = combinedItems.length > 0, handleLoadMoreItems = () => {
    fetching || dispatch(assetsActions.loadNextPage());
  };
  return react.useEffect(() => {
    breakpointIndex <= 1 && tagsPanelVisible && dispatch(tagsActions.panelVisibleSet({ panelVisible: !1 }));
  }, [breakpointIndex]), /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { flex: 1, style: { width: "100%" }, children: !hasItems && hasFetchedOnce && !fetching ? /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 4, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, weight: "semibold", children: "No results for the current query" }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    view === "grid" && /* @__PURE__ */ jsxRuntime.jsx(AssetGridVirtualized, { items: combinedItems, onLoadMore: handleLoadMoreItems }),
    view === "table" && /* @__PURE__ */ jsxRuntime.jsx(AssetTableVirtualized, { items: combinedItems, onLoadMore: handleLoadMoreItems })
  ] }) });
}, Notifications = () => {
  const items = useTypedSelector((state) => state.notifications.items), toast = ui.useToast();
  return react.useEffect(() => {
    if (items.length > 0) {
      const lastItem = items[items.length - 1];
      toast.push({
        closable: !0,
        status: lastItem.status,
        title: lastItem.title
      });
    }
  }, [items.length]), null;
}, PickedBar = () => {
  const scheme = sanity.useColorSchemeValue(), dispatch = reactRedux.useDispatch(), assetsPicked = useTypedSelector(selectAssetsPicked), handlePickClear = () => {
    dispatch(assetsActions.pickClear());
  }, handleDeletePicked = () => {
    dispatch(dialogActions.showConfirmDeleteAssets({ assets: assetsPicked }));
  };
  return assetsPicked.length === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(
    ui.Flex,
    {
      align: "center",
      justify: "flex-start",
      style: {
        background: getSchemeColor(scheme, "bg"),
        borderBottom: "1px solid var(--card-border-color)",
        height: `${PANEL_HEIGHT}px`,
        position: "relative",
        width: "100%"
      },
      children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", paddingX: 3, children: [
        /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { paddingRight: 2, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Label, { size: 0, style: { color: "inherit" }, children: [
          assetsPicked.length,
          " ",
          pluralize__default.default("asset", assetsPicked.length),
          " selected"
        ] }) }),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.Button,
          {
            mode: "bleed",
            onClick: handlePickClear,
            padding: 2,
            style: { background: "none", boxShadow: "none" },
            tone: "default",
            children: /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: 0, children: "Deselect" })
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.Button,
          {
            mode: "bleed",
            onClick: handleDeletePicked,
            padding: 2,
            style: { background: "none", boxShadow: "none" },
            tone: "critical",
            children: /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: 0, children: "Delete" })
          }
        )
      ] })
    }
  );
}, initialState$1 = {
  assets: [],
  document: void 0,
  documentAssetIds: []
}, selectedSlice = toolkit.createSlice({
  name: "selected",
  initialState: initialState$1,
  reducers: {}
});
var selectedReducer = selectedSlice.reducer;
const initialState = {
  items: []
}, notificationsSlice = toolkit.createSlice({
  name: "notifications",
  initialState,
  reducers: {
    add(state, action) {
      const { asset, status, title } = action.payload;
      state.items.push({
        asset,
        status,
        title
      });
    }
  }
}), notificationsAssetsDeleteCompleteEpic = (action$) => action$.pipe(
  operators$1.filter(assetsActions.deleteComplete.match),
  operators$1.mergeMap((action) => {
    const { assetIds } = action.payload, deletedCount = assetIds.length;
    return rxjs.of(
      notificationsSlice.actions.add({
        status: "info",
        title: `${deletedCount} ${pluralize__default.default("asset", deletedCount)} deleted`
      })
    );
  })
), notificationsAssetsDeleteErrorEpic = (action$) => action$.pipe(
  operators$1.filter(assetsActions.deleteError.match),
  operators$1.mergeMap((action) => {
    const { assetIds } = action.payload, count = assetIds.length;
    return rxjs.of(
      notificationsSlice.actions.add({
        status: "error",
        title: `Unable to delete ${count} ${pluralize__default.default(
          "asset",
          count
        )}. Please review any asset errors and try again.`
      })
    );
  })
), notificationsAssetsTagsAddCompleteEpic = (action$) => action$.pipe(
  operators$1.filter(ASSETS_ACTIONS.tagsAddComplete.match),
  operators$1.mergeMap((action) => {
    const count = action?.payload?.assets?.length;
    return rxjs.of(
      notificationsSlice.actions.add({
        status: "info",
        title: `Tag added to ${count} ${pluralize__default.default("asset", count)}`
      })
    );
  })
), notificationsAssetsTagsRemoveCompleteEpic = (action$) => action$.pipe(
  operators$1.filter(ASSETS_ACTIONS.tagsRemoveComplete.match),
  operators$1.mergeMap((action) => {
    const count = action?.payload?.assets?.length;
    return rxjs.of(
      notificationsSlice.actions.add({
        status: "info",
        title: `Tag removed from ${count} ${pluralize__default.default("asset", count)}`
      })
    );
  })
), notificationsAssetsUpdateCompleteEpic = (action$) => action$.pipe(
  operators$1.filter(assetsActions.updateComplete.match),
  operators$1.bufferTime(2e3),
  operators$1.filter((actions) => actions.length > 0),
  operators$1.mergeMap((actions) => {
    const updatedCount = actions.length;
    return rxjs.of(
      notificationsSlice.actions.add({
        status: "info",
        title: `${updatedCount} ${pluralize__default.default("asset", updatedCount)} updated`
      })
    );
  })
), notificationsGenericErrorEpic = (action$) => action$.pipe(
  reduxObservable.ofType(
    assetsActions.fetchError.type,
    assetsActions.updateError.type,
    tagsActions.createError.type,
    tagsActions.deleteError.type,
    tagsActions.fetchError.type,
    tagsActions.updateError.type,
    uploadsActions.uploadError.type
  ),
  operators$1.mergeMap((action) => {
    const error = action.payload?.error;
    return rxjs.of(
      notificationsSlice.actions.add({
        status: "error",
        title: `An error occured: ${error.message}`
      })
    );
  })
), notificationsTagCreateCompleteEpic = (action$) => action$.pipe(
  operators$1.filter(tagsActions.createComplete.match),
  operators$1.mergeMap(() => rxjs.of(notificationsSlice.actions.add({ status: "info", title: "Tag created" })))
), notificationsTagDeleteCompleteEpic = (action$) => action$.pipe(
  operators$1.filter(tagsActions.deleteComplete.match),
  operators$1.mergeMap(() => rxjs.of(notificationsSlice.actions.add({ status: "info", title: "Tag deleted" })))
), notificationsTagUpdateCompleteEpic = (action$) => action$.pipe(
  operators$1.filter(tagsActions.updateComplete.match),
  operators$1.mergeMap(() => rxjs.of(notificationsSlice.actions.add({ status: "info", title: "Tag updated" })))
), notificationsActions = { ...notificationsSlice.actions };
var notificationsReducer = notificationsSlice.reducer;
const rootEpic = reduxObservable.combineEpics(
  assetsDeleteEpic,
  assetsFetchEpic,
  assetsFetchAfterDeleteAllEpic,
  assetsFetchNextPageEpic,
  assetsFetchPageIndexEpic,
  assetsListenerCreateQueueEpic,
  assetsListenerDeleteQueueEpic,
  assetsListenerUpdateQueueEpic,
  assetsOrderSetEpic,
  assetsSearchEpic,
  assetsSortEpic,
  assetsTagsAddEpic,
  assetsTagsRemoveEpic,
  assetsUnpickEpic,
  assetsUpdateEpic,
  dialogClearOnAssetUpdateEpic,
  dialogTagCreateEpic,
  dialogTagDeleteEpic,
  notificationsAssetsDeleteErrorEpic,
  notificationsAssetsDeleteCompleteEpic,
  notificationsAssetsTagsAddCompleteEpic,
  notificationsAssetsTagsRemoveCompleteEpic,
  notificationsAssetsUpdateCompleteEpic,
  notificationsGenericErrorEpic,
  notificationsTagCreateCompleteEpic,
  notificationsTagDeleteCompleteEpic,
  notificationsTagUpdateCompleteEpic,
  searchFacetTagUpdateEpic,
  tagsCreateEpic,
  tagsDeleteEpic,
  tagsFetchEpic,
  tagsListenerCreateQueueEpic,
  tagsListenerDeleteQueueEpic,
  tagsListenerUpdateQueueEpic,
  tagsSortEpic,
  tagsUpdateEpic,
  uploadsAssetStartEpic,
  uploadsAssetUploadEpic,
  uploadsCheckRequestEpic,
  uploadsCompleteQueueEpic
), reducers = {
  assets: assetsReducer,
  debug: debugReducer,
  dialog: dialogReducer,
  notifications: notificationsReducer,
  search: searchReducer,
  selected: selectedReducer,
  tags: tagsReducer,
  uploads: uploadsReducer
}, rootReducer = toolkit.combineReducers(reducers), isPlainObject = (value) => value !== null && typeof value == "object" && !Array.isArray(value), getAssetIds = (node, acc = []) => (Array.isArray(node) && node.forEach((v) => {
  getAssetIds(v, acc);
}), isPlainObject(node) && (node?.asset?._type === "reference" && node?.asset?._ref && acc.push(node.asset._ref), Object.values(node).forEach((val) => {
  getAssetIds(val, acc);
})), acc), getDocumentAssetIds = (document2) => {
  const assetIds = getAssetIds(document2);
  return [...new Set(assetIds.sort())];
};
function isSupportedAssetType(assetType) {
  return assetType ? SUPPORTED_ASSET_TYPES.includes(assetType) : !1;
}
class ReduxProvider extends react.Component {
  store;
  constructor(props) {
    super(props);
    const epicMiddleware = reduxObservable.createEpicMiddleware({
      dependencies: {
        client: props.client
        // inject sanity client as a dependency to all epics
      }
    });
    this.store = toolkit.configureStore({
      reducer: rootReducer,
      middleware: (getDefaultMiddleware) => getDefaultMiddleware({
        /*
        serializableCheck: {
          ignoredActions: [
            assetsActions.deleteError.type,
            uploadsActions.uploadRequest.type,
            uploadsActions.uploadStart.type,
          ]
        },
        */
        // TODO: remove once we're no longer storing non-serializable data in the store
        serializableCheck: !1,
        thunk: !1
      }).prepend(epicMiddleware),
      devTools: !0,
      preloadedState: {
        assets: {
          ...initialState$5,
          assetTypes: isSupportedAssetType(props?.assetType) ? [props.assetType] : ["file", "image"]
        },
        debug: {
          badConnection: !1,
          enabled: !1
        },
        dialog: { items: [] },
        notifications: { items: [] },
        search: { facets: [], query: "" },
        selected: {
          assets: props.selectedAssets || [],
          document: props.document,
          documentAssetIds: props.document ? getDocumentAssetIds(props.document) : []
        },
        tags: {
          allIds: [],
          byIds: {},
          creating: !1,
          fetchCount: -1,
          fetching: !1,
          panelVisible: !0
        },
        uploads: {
          allIds: [],
          byIds: {}
        }
      }
    }), epicMiddleware.run(rootEpic);
  }
  render() {
    return /* @__PURE__ */ jsxRuntime.jsx(reactRedux.Provider, { store: this.store, children: this.props.children });
  }
}
const TagsPanel = () => useTypedSelector((state) => state.tags.panelVisible) ? /* @__PURE__ */ jsxRuntime.jsx(
  ui.Box,
  {
    style: {
      position: "relative",
      width: TAGS_PANEL_WIDTH
    },
    children: /* @__PURE__ */ jsxRuntime.jsx(
      ui.Box,
      {
        className: "media__custom-scrollbar",
        style: {
          borderLeft: "1px solid var(--card-border-color)",
          height: "100%",
          overflowX: "hidden",
          overflowY: "auto",
          position: "absolute",
          right: 0,
          top: 0,
          width: "100%"
        },
        children: /* @__PURE__ */ jsxRuntime.jsx(TagView, {})
      }
    )
  }
) : null, UploadContainer = styledComponents.styled.div`
  color: white;
  height: 100%;
  min-height: 100%;
  right: 0;
  top: 0;
  width: 100%;

  &:focus {
    outline: none;
  }
`, DragActiveContainer = styledComponents.styled.div`
  align-items: center;
  background: rgba(0, 0, 0, 0.75);
  display: flex;
  height: 100%;
  justify-content: center;
  position: absolute;
  right: 0;
  top: 0;
  width: 100%;
  z-index: 3;
`;
async function filterFiles(fileList) {
  const files = Array.from(fileList), filteredFiles = [];
  for (const file of files)
    try {
      await file.slice(0, 1).arrayBuffer(), filteredFiles.push(file);
    } catch {
    }
  return filteredFiles;
}
const UploadDropzone = (props) => {
  const { children } = props, {
    dropzone: { maxSize },
    directUploads
  } = useToolOptions(), { onSelect } = useAssetSourceActions(), dispatch = reactRedux.useDispatch(), assetTypes = useTypedSelector((state) => state.assets.assetTypes), isImageAssetType = assetTypes.length === 1 && assetTypes[0] === "image", handleDrop = async (acceptedFiles) => {
    acceptedFiles.forEach(
      (file) => dispatch(
        uploadsActions.uploadRequest({
          file,
          forceAsAssetType: assetTypes.length === 1 ? assetTypes[0] : void 0
        })
      )
    );
  }, handleDropRejected = (rejections) => {
    rejections.flatMap(({ errors }) => errors.map(({ code }) => code)).includes("file-too-large") && dispatch(
      notificationsActions.add({
        status: "error",
        title: "One or more files exceed the maximum upload size."
      })
    );
  }, handleFileGetter = async (event) => {
    let fileList;
    if (event.type === "drop" && "dataTransfer" in event && (fileList = event?.dataTransfer?.files), event.type === "change") {
      const target = event?.target;
      target?.files && (fileList = target.files);
    }
    if (!fileList)
      return [];
    const files = await filterFiles(fileList);
    return fileList?.length !== files.length && dispatch(
      notificationsActions.add({
        status: "error",
        title: "Unable to upload some items (folders and packages aren't supported)"
      })
    ), files;
  }, { getRootProps, getInputProps, isDragActive, open } = reactDropzone.useDropzone({
    accept: isImageAssetType ? "image/*" : "",
    getFilesFromEvent: handleFileGetter,
    noClick: !0,
    // HACK: Disable drag and drop functionality when in a selecting context
    // (This is currently due to Sanity's native image input taking precedence with drag and drop)
    noDrag: !!onSelect,
    onDrop: handleDrop,
    maxSize,
    onDropRejected: handleDropRejected,
    disabled: !directUploads
  });
  return /* @__PURE__ */ jsxRuntime.jsx(DropzoneDispatchProvider, { open, children: /* @__PURE__ */ jsxRuntime.jsxs(UploadContainer, { ...getRootProps(), children: [
    /* @__PURE__ */ jsxRuntime.jsx("input", { ...getInputProps() }),
    isDragActive && /* @__PURE__ */ jsxRuntime.jsx(DragActiveContainer, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { direction: "column", justify: "center", style: { color: color.white.hex }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 3, style: { color: "inherit" }, children: "Drop files to upload" }) }) }),
    children
  ] }) });
}, BrowserContent = ({ onClose }) => {
  const client = useVersionedClient(), [portalElement, setPortalElement] = react.useState(null), dispatch = reactRedux.useDispatch();
  return react.useEffect(() => {
    const handleAssetUpdate = (update) => {
      const { documentId, result, transition } = update;
      transition === "appear" && dispatch(assetsActions.listenerCreateQueue({ asset: result })), transition === "disappear" && dispatch(assetsActions.listenerDeleteQueue({ assetId: documentId })), transition === "update" && dispatch(assetsActions.listenerUpdateQueue({ asset: result }));
    }, handleTagUpdate = (update) => {
      const { documentId, result, transition } = update;
      transition === "appear" && dispatch(tagsActions.listenerCreateQueue({ tag: result })), transition === "disappear" && dispatch(tagsActions.listenerDeleteQueue({ tagId: documentId })), transition === "update" && dispatch(tagsActions.listenerUpdateQueue({ tag: result }));
    };
    dispatch(assetsActions.loadPageIndex({ pageIndex: 0 })), dispatch(tagsActions.fetchRequest());
    const subscriptionAsset = client.listen(
      groq__default.default`*[_type in ["sanity.fileAsset", "sanity.imageAsset"] && !(_id in path("drafts.**"))]`
    ).subscribe(handleAssetUpdate), subscriptionTag = client.listen(groq__default.default`*[_type == "${TAG_DOCUMENT_NAME}" && !(_id in path("drafts.**"))]`).subscribe(handleTagUpdate);
    return () => {
      subscriptionAsset?.unsubscribe(), subscriptionTag?.unsubscribe();
    };
  }, [client, dispatch]), /* @__PURE__ */ jsxRuntime.jsx(ui.PortalProvider, { element: portalElement, children: /* @__PURE__ */ jsxRuntime.jsxs(UploadDropzone, { children: [
    /* @__PURE__ */ jsxRuntime.jsx(Dialogs, {}),
    /* @__PURE__ */ jsxRuntime.jsx(Notifications, {}),
    /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { display: "flex", height: "fill", ref: setPortalElement, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { direction: "column", flex: 1, children: [
      /* @__PURE__ */ jsxRuntime.jsx(Header, { onClose }),
      /* @__PURE__ */ jsxRuntime.jsx(Controls, {}),
      /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { flex: 1, children: [
        /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "flex-end", direction: "column", flex: 1, style: { position: "relative" }, children: [
          /* @__PURE__ */ jsxRuntime.jsx(PickedBar, {}),
          /* @__PURE__ */ jsxRuntime.jsx(Items, {})
        ] }),
        /* @__PURE__ */ jsxRuntime.jsx(TagsPanel, {})
      ] }),
      /* @__PURE__ */ jsxRuntime.jsx(DebugControls, {})
    ] }) })
  ] }) });
}, Browser = (props) => {
  const client = useVersionedClient();
  return /* @__PURE__ */ jsxRuntime.jsx(
    ReduxProvider,
    {
      assetType: props?.assetType,
      client,
      document: props?.document,
      selectedAssets: props?.selectedAssets,
      children: /* @__PURE__ */ jsxRuntime.jsxs(AssetBrowserDispatchProvider, { onSelect: props?.onSelect, children: [
        /* @__PURE__ */ jsxRuntime.jsx(GlobalStyle, {}),
        /* @__PURE__ */ jsxRuntime.jsx(BrowserContent, { onClose: props?.onClose })
      ] })
    }
  );
}, FormBuilderTool = (props) => {
  const { onClose } = props, portalElement = useRootPortalElement(), currentDocument = sanity.useFormValue([]);
  useKeyPress("escape", onClose);
  const handleStopPropagation = (event) => {
    event.nativeEvent.stopImmediatePropagation(), event.stopPropagation();
  }, { zIndex } = ui.useLayer();
  return /* @__PURE__ */ jsxRuntime.jsx(ui.PortalProvider, { element: portalElement, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
    ui.Box,
    {
      onDragEnter: handleStopPropagation,
      onDragLeave: handleStopPropagation,
      onDragOver: handleStopPropagation,
      onDrop: handleStopPropagation,
      onMouseUp: handleStopPropagation,
      style: {
        bottom: 0,
        height: "auto",
        left: 0,
        position: "fixed",
        top: 0,
        width: "100%",
        zIndex
      },
      children: /* @__PURE__ */ jsxRuntime.jsx(Browser, { document: currentDocument, ...props })
    }
  ) }) });
}, useRootPortalElement = () => {
  const [container] = react.useState(() => document.createElement("div"));
  return react.useEffect(() => (container.classList.add("media-portal"), document.body.appendChild(container), () => {
    document.body.removeChild(container);
  }), [container]), container;
}, Tool = () => /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { direction: "column", height: "fill", flex: 1, children: /* @__PURE__ */ jsxRuntime.jsx(Browser, {}) });
var mediaTag = {
  title: "Media Tag",
  icon: TagIcon,
  name: TAG_DOCUMENT_NAME,
  type: "document",
  fields: [
    {
      title: "Name",
      name: "name",
      type: "slug"
    }
  ],
  preview: {
    select: {
      name: "name"
    },
    prepare(selection) {
      const { name } = selection;
      return {
        media: TagIcon,
        title: name?.current
      };
    }
  }
};
const plugin = {
  icon: icons.ImageIcon,
  name: "media",
  title: "Media"
}, mediaAssetSource = {
  ...plugin,
  component: FormBuilderTool
}, tool = {
  ...plugin,
  component: Tool,
  // @ts-expect-error TS doesn't know about this internal field see https://github.com/sanity-io/sanity/pull/7980
  __internalApplicationType: "sanity/media"
}, media = sanity.definePlugin((options) => ({
  name: "media",
  studio: {
    components: {
      layout: (props) => /* @__PURE__ */ jsxRuntime.jsx(ToolOptionsProvider, { options, children: props.renderDefault(props) })
    }
  },
  form: {
    file: {
      assetSources: (prev) => [...prev, mediaAssetSource]
    },
    image: {
      assetSources: (prev) => [...prev, mediaAssetSource]
    }
  },
  schema: {
    types: [mediaTag]
  },
  tools: (prev) => [...prev, tool]
}));
exports.media = media;
exports.mediaAssetSource = mediaAssetSource;
//# sourceMappingURL=index.js.map