import { Editor, Text } from "slate";
import {
  findBreakpointOverride,
  Slate
} from "@makeswift/controls";
import unhangRange from "./utils/unhangRange";
import shallowEqual from "../utils/shallowEqual";
import { isNonNullable } from "../utils/isNonNullable";
import deepEqual from "../utils/deepEqual";
import keys from "../utils/keys";
function getSelection(editor) {
  if (editor.selection)
    return unhangRange(editor, editor.selection);
  return {
    anchor: Editor.start(editor, []),
    focus: Editor.end(editor, [])
  };
}
function getBlocksInSelection(editor) {
  return Array.from(
    Editor.nodes(editor, {
      at: getSelection(editor),
      match: (node) => Slate.isRootBlock(node)
    })
  ).filter((entry) => Slate.isRootBlock(entry[0]));
}
function getInlinesInSelection(editor) {
  return Array.from(
    Editor.nodes(editor, {
      at: getSelection(editor),
      match: (node) => Slate.isInline(node)
    })
  ).filter((entry) => Slate.isInline(entry[0]));
}
function getActiveBlockType(editor) {
  const rootBlocks = getBlocksInSelection(editor).map(([node]) => node.type);
  return rootBlocks.reduce(
    (a, b) => a === b ? b : null,
    rootBlocks.at(0) ?? null
  );
}
function getActiveBlockValue(editor, key) {
  const blocks = getBlocksInSelection(editor);
  const active = blocks.map(
    ([block]) => block[key] ?? null
  );
  return active.length === 0 ? null : active.reduce((a, b) => shallowEqual(a, b) ? b : null);
}
function getActiveBlockDeviceOverrideValue(editor, key, breakpoints, deviceId) {
  const active = [];
  const blocks = getBlocksInSelection(editor);
  blocks.forEach(([block]) => {
    const deviceOverride = findBreakpointOverride(breakpoints, block[key], deviceId) || null;
    active.push(deviceOverride?.value ?? null);
  });
  return active.length === 0 ? null : active.reduce((a, b) => shallowEqual(a, b) ? b : null);
}
const concat = (a, b) => a.concat(b);
function intersection(a, b, isEqual = deepEqual) {
  const allKeys = [.../* @__PURE__ */ new Set([...keys(a), ...keys(b)])];
  return allKeys.reduce(
    (acc, k) => {
      if (isEqual(a[k], b[k]))
        acc[k] = a[k];
      else
        acc[k] = void 0;
      return acc;
    },
    {}
  );
}
const fuseTypographyMarks = (values, breakpoints) => {
  const devices = [
    ...new Set(
      values.filter(isNonNullable).map(({ style }) => style.map(({ deviceId }) => deviceId)).reduce(concat, [])
    )
  ];
  return {
    id: values.map((v) => v && v.id).reduce((a, b) => a === b ? a : void 0) ?? void 0,
    style: devices.map(
      (deviceId) => values.map(
        (v) => v && findBreakpointOverride(breakpoints, v.style, deviceId) || {
          deviceId,
          value: {}
        }
      ).reduce((acc, { value }) => {
        const a = intersection(acc.value, value);
        return {
          deviceId,
          value: a
        };
      })
    )
  };
};
function getActiveTypographyMark(editor, breakpoints) {
  const active = [];
  const textNodes = Editor.nodes(editor, {
    at: getSelection(editor),
    match: (node) => Text.isText(node)
  });
  for (const [node] of textNodes) {
    if (Text.isText(node) && "typography" in node && node.typography != void 0) {
      active.push(node.typography);
    }
  }
  return active.length === 0 ? { style: [] } : fuseTypographyMarks(active, breakpoints);
}
export {
  intersection as default,
  getActiveBlockDeviceOverrideValue,
  getActiveBlockType,
  getActiveBlockValue,
  getActiveTypographyMark,
  getBlocksInSelection,
  getInlinesInSelection,
  getSelection
};
//# sourceMappingURL=selectors.js.map