'use strict';

var uiReact = require('../ui-react/index.cjs');
var React = require('react');

const getTypeOf = (thing) => typeof thing;
const EMPTY_STRING = '';
const STRING = getTypeOf(EMPTY_STRING);
const BOOLEAN = getTypeOf(true);
const NUMBER = getTypeOf(0);
const CELL = 'Cell';
const VALUE = 'Value';
const CURRENT_TARGET = 'currentTarget';
const _VALUE = 'value';

const math = Math;
const mathMin = math.min;
const isFiniteNumber = isFinite;
const isUndefined = (thing) => thing == void 0;
const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
const isString = (thing) => getTypeOf(thing) == STRING;
const isArray = (thing) => Array.isArray(thing);

const getCellOrValueType = (cellOrValue) => {
  const type = getTypeOf(cellOrValue);
  return isTypeStringOrBoolean(type) ||
    (type == NUMBER && isFiniteNumber(cellOrValue))
    ? type
    : void 0;
};
const getTypeCase = (type, stringCase, numberCase, booleanCase) =>
  type == STRING ? stringCase : type == NUMBER ? numberCase : booleanCase;

const {
  PureComponent,
  Fragment,
  createElement,
  useCallback: useCallback$1,
  useLayoutEffect,
  useRef,
  useState: useState$1,
} = React;
const getProps = (getProps2, ...ids) =>
  isUndefined(getProps2) ? {} : getProps2(...ids);
const getRelationshipsStoreTableIds = (relationships, relationshipId) => [
  relationships,
  relationships == null ? void 0 : relationships.getStore(),
  relationships == null
    ? void 0
    : relationships.getLocalTableId(relationshipId),
  relationships == null
    ? void 0
    : relationships.getRemoteTableId(relationshipId),
];
const getIndexStoreTableId = (indexes, indexId) => [
  indexes,
  indexes == null ? void 0 : indexes.getStore(),
  indexes == null ? void 0 : indexes.getTableId(indexId),
];

const arrayMap = (array, cb) => array.map(cb);

const object = Object;
const objEntries = object.entries;
const objNew = (entries = []) => object.fromEntries(entries);
const objToArray = (obj, cb) =>
  arrayMap(objEntries(obj), ([id, value]) => cb(value, id));
const objMap = (obj, cb) =>
  objNew(objToArray(obj, (value, id) => [id, cb(value, id)]));

var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) =>
  key in obj
    ? __defProp(obj, key, {
        enumerable: true,
        configurable: true,
        writable: true,
        value,
      })
    : (obj[key] = value);
var __spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]);
  if (__getOwnPropSymbols)
    for (var prop of __getOwnPropSymbols(b)) {
      if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]);
    }
  return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __objRest = (source, exclude) => {
  var target = {};
  for (var prop in source)
    if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
      target[prop] = source[prop];
  if (source != null && __getOwnPropSymbols)
    for (var prop of __getOwnPropSymbols(source)) {
      if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
        target[prop] = source[prop];
    }
  return target;
};
const {useCallback, useMemo, useState} = React;
const DOT = '.';
const EDITABLE = 'editable';
const LEFT_ARROW = '\u2190';
const UP_ARROW = '\u2191';
const RIGHT_ARROW = '\u2192';
const DOWN_ARROW = '\u2193';
const useDottedCellIds = (tableId, store) =>
  arrayMap(
    uiReact.useTableCellIds(tableId, store),
    (cellId) => tableId + DOT + cellId,
  );
const useCallbackOrUndefined = (callback, deps, test) => {
  const returnCallback = useCallback(callback, deps);
  return test ? returnCallback : void 0;
};
const useParams = (...args) =>
  useMemo(
    () => args,
    // eslint-disable-next-line react-hooks/exhaustive-deps
    args,
  );
const useStoreCellComponentProps = (store, tableId) =>
  useMemo(() => ({store, tableId}), [store, tableId]);
const useQueriesCellComponentProps = (queries, queryId) =>
  useMemo(() => ({queries, queryId}), [queries, queryId]);
const useSortingAndPagination = (
  cellId,
  descending = false,
  sortOnClick,
  offset = 0,
  limit,
  total,
  paginator,
  onChange,
) => {
  const [[currentCellId, currentDescending, currentOffset], setState] =
    useState([cellId, descending, offset]);
  const setStateAndChange = useCallback(
    (sortAndOffset) => {
      setState(sortAndOffset);
      onChange == null ? void 0 : onChange(sortAndOffset);
    },
    [onChange],
  );
  const handleSort = useCallbackOrUndefined(
    (cellId2) =>
      setStateAndChange([
        cellId2,
        cellId2 == currentCellId ? !currentDescending : false,
        currentOffset,
      ]),
    [setStateAndChange, currentCellId, currentDescending, currentOffset],
    sortOnClick,
  );
  const handleChangeOffset = useCallback(
    (offset2) => setStateAndChange([currentCellId, currentDescending, offset2]),
    [setStateAndChange, currentCellId, currentDescending],
  );
  const PaginatorComponent =
    paginator === true ? SortedTablePaginator : paginator;
  return [
    [currentCellId, currentDescending, currentOffset],
    handleSort,
    useMemo(
      () =>
        paginator === false
          ? null
          : /* @__PURE__ */ createElement(PaginatorComponent, {
              offset: currentOffset,
              limit,
              total,
              onChange: handleChangeOffset,
            }),
      [
        paginator,
        PaginatorComponent,
        currentOffset,
        limit,
        total,
        handleChangeOffset,
      ],
    ),
  ];
};
const useCells = (defaultCellIds, customCells, defaultCellComponent) =>
  useMemo(() => {
    const cellIds = customCells != null ? customCells : defaultCellIds;
    return objMap(
      isArray(cellIds)
        ? objNew(arrayMap(cellIds, (cellId) => [cellId, cellId]))
        : cellIds,
      (labelOrCustomCell, cellId) =>
        __spreadValues(
          __spreadValues({}, {label: cellId, component: defaultCellComponent}),
          isString(labelOrCustomCell)
            ? {label: labelOrCustomCell}
            : labelOrCustomCell,
        ),
    );
  }, [customCells, defaultCellComponent, defaultCellIds]);
const HtmlTable = ({
  className,
  headerRow,
  idColumn,
  params: [
    cells,
    cellComponentProps,
    rowIds,
    sortAndOffset,
    handleSort,
    paginatorComponent,
  ],
}) =>
  /* @__PURE__ */ createElement(
    'table',
    {className},
    paginatorComponent
      ? /* @__PURE__ */ createElement('caption', null, paginatorComponent)
      : null,
    headerRow === false
      ? null
      : /* @__PURE__ */ createElement(
          'thead',
          null,
          /* @__PURE__ */ createElement(
            'tr',
            null,
            idColumn === false
              ? null
              : /* @__PURE__ */ createElement(HtmlHeaderCell, {
                  sort: sortAndOffset != null ? sortAndOffset : [],
                  label: 'Id',
                  onClick: handleSort,
                }),
            objToArray(cells, ({label}, cellId) =>
              /* @__PURE__ */ createElement(HtmlHeaderCell, {
                key: cellId,
                cellId,
                label,
                sort: sortAndOffset != null ? sortAndOffset : [],
                onClick: handleSort,
              }),
            ),
          ),
        ),
    /* @__PURE__ */ createElement(
      'tbody',
      null,
      arrayMap(rowIds, (rowId) =>
        /* @__PURE__ */ createElement(
          'tr',
          {key: rowId},
          idColumn === false
            ? null
            : /* @__PURE__ */ createElement('th', null, rowId),
          objToArray(
            cells,
            ({component: CellView2, getComponentProps}, cellId) =>
              /* @__PURE__ */ createElement(
                'td',
                {key: cellId},
                /* @__PURE__ */ createElement(
                  CellView2,
                  __spreadProps(
                    __spreadValues(
                      __spreadValues(
                        {},
                        getProps(getComponentProps, rowId, cellId),
                      ),
                      cellComponentProps,
                    ),
                    {
                      rowId,
                      cellId,
                    },
                  ),
                ),
              ),
          ),
        ),
      ),
    ),
  );
const HtmlHeaderCell = ({
  cellId,
  sort: [sortCellId, sortDescending],
  label = cellId != null ? cellId : EMPTY_STRING,
  onClick,
}) =>
  /* @__PURE__ */ createElement(
    'th',
    {
      onClick: useCallbackOrUndefined(
        () => (onClick == null ? void 0 : onClick(cellId)),
        [onClick, cellId],
        onClick,
      ),
      className:
        isUndefined(sortDescending) || sortCellId != cellId
          ? void 0
          : `sorted ${sortDescending ? 'de' : 'a'}scending`,
    },
    isUndefined(sortDescending) || sortCellId != cellId
      ? null
      : (sortDescending ? DOWN_ARROW : UP_ARROW) + ' ',
    label,
  );
const RelationshipInHtmlRow = ({
  localRowId,
  params: [
    idColumn,
    cells,
    localTableId,
    remoteTableId,
    relationshipId,
    relationships,
    store,
  ],
}) => {
  const remoteRowId = uiReact.useRemoteRowId(
    relationshipId,
    localRowId,
    relationships,
  );
  return /* @__PURE__ */ createElement(
    'tr',
    null,
    idColumn === false
      ? null
      : /* @__PURE__ */ createElement(
          React.Fragment,
          null,
          /* @__PURE__ */ createElement('th', null, localRowId),
          /* @__PURE__ */ createElement('th', null, remoteRowId),
        ),
    objToArray(
      cells,
      ({component: CellView2, getComponentProps}, compoundCellId) => {
        const [tableId, cellId] = compoundCellId.split(DOT, 2);
        const rowId =
          tableId === localTableId
            ? localRowId
            : tableId === remoteTableId
              ? remoteRowId
              : null;
        return isUndefined(rowId)
          ? null
          : /* @__PURE__ */ createElement(
              'td',
              {key: compoundCellId},
              /* @__PURE__ */ createElement(
                CellView2,
                __spreadProps(
                  __spreadValues(
                    {},
                    getProps(getComponentProps, rowId, cellId),
                  ),
                  {
                    store,
                    tableId,
                    rowId,
                    cellId,
                  },
                ),
              ),
            );
      },
    ),
  );
};
const EditableThing = ({
  thing,
  onThingChange,
  className,
  hasSchema,
  showType = true,
}) => {
  const [thingType, setThingType] = useState();
  const [currentThing, setCurrentThing] = useState();
  const [stringThing, setStringThing] = useState();
  const [numberThing, setNumberThing] = useState();
  const [booleanThing, setBooleanThing] = useState();
  if (currentThing !== thing) {
    setThingType(getCellOrValueType(thing));
    setCurrentThing(thing);
    setStringThing(String(thing));
    setNumberThing(Number(thing) || 0);
    setBooleanThing(Boolean(thing));
  }
  const handleThingChange = useCallback(
    (thing2, setTypedThing) => {
      setTypedThing(thing2);
      setCurrentThing(thing2);
      onThingChange(thing2);
    },
    [onThingChange],
  );
  const handleTypeChange = useCallback(() => {
    if (!(hasSchema == null ? void 0 : hasSchema())) {
      const nextType = getTypeCase(thingType, NUMBER, BOOLEAN, STRING);
      const thing2 = getTypeCase(
        nextType,
        stringThing,
        numberThing,
        booleanThing,
      );
      setThingType(nextType);
      setCurrentThing(thing2);
      onThingChange(thing2);
    }
  }, [
    hasSchema,
    onThingChange,
    stringThing,
    numberThing,
    booleanThing,
    thingType,
  ]);
  return /* @__PURE__ */ createElement(
    'div',
    {className},
    showType
      ? /* @__PURE__ */ createElement(
          'button',
          {className: thingType, onClick: handleTypeChange},
          thingType,
        )
      : null,
    getTypeCase(
      thingType,
      /* @__PURE__ */ createElement('input', {
        key: thingType,
        value: stringThing,
        onChange: useCallback(
          (event) =>
            handleThingChange(
              String(event[CURRENT_TARGET][_VALUE]),
              setStringThing,
            ),
          [handleThingChange],
        ),
      }),
      /* @__PURE__ */ createElement('input', {
        key: thingType,
        type: 'number',
        value: numberThing,
        onChange: useCallback(
          (event) =>
            handleThingChange(
              Number(event[CURRENT_TARGET][_VALUE] || 0),
              setNumberThing,
            ),
          [handleThingChange],
        ),
      }),
      /* @__PURE__ */ createElement('input', {
        key: thingType,
        type: 'checkbox',
        checked: booleanThing,
        onChange: useCallback(
          (event) =>
            handleThingChange(
              Boolean(event[CURRENT_TARGET].checked),
              setBooleanThing,
            ),
          [handleThingChange],
        ),
      }),
    ),
  );
};
const TableInHtmlTable = (_a) => {
  var _b = _a,
    {tableId, store, editable, customCells} = _b,
    props = __objRest(_b, ['tableId', 'store', 'editable', 'customCells']);
  return /* @__PURE__ */ createElement(
    HtmlTable,
    __spreadProps(__spreadValues({}, props), {
      params: useParams(
        useCells(
          uiReact.useTableCellIds(tableId, store),
          customCells,
          editable ? EditableCellView : uiReact.CellView,
        ),
        useStoreCellComponentProps(store, tableId),
        uiReact.useRowIds(tableId, store),
      ),
    }),
  );
};
const SortedTableInHtmlTable = (_c) => {
  var _d = _c,
    {
      tableId,
      cellId,
      descending,
      offset,
      limit,
      store,
      editable,
      sortOnClick,
      paginator = false,
      onChange,
      customCells,
    } = _d,
    props = __objRest(_d, [
      'tableId',
      'cellId',
      'descending',
      'offset',
      'limit',
      'store',
      'editable',
      'sortOnClick',
      'paginator',
      'onChange',
      'customCells',
    ]);
  const [sortAndOffset, handleSort, paginatorComponent] =
    useSortingAndPagination(
      cellId,
      descending,
      sortOnClick,
      offset,
      limit,
      uiReact.useRowCount(tableId, store),
      paginator,
      onChange,
    );
  return /* @__PURE__ */ createElement(
    HtmlTable,
    __spreadProps(__spreadValues({}, props), {
      params: useParams(
        useCells(
          uiReact.useTableCellIds(tableId, store),
          customCells,
          editable ? EditableCellView : uiReact.CellView,
        ),
        useStoreCellComponentProps(store, tableId),
        uiReact.useSortedRowIds(tableId, ...sortAndOffset, limit, store),
        sortAndOffset,
        handleSort,
        paginatorComponent,
      ),
    }),
  );
};
const ValuesInHtmlTable = ({
  store,
  editable = false,
  valueComponent: Value = editable ? EditableValueView : uiReact.ValueView,
  getValueComponentProps,
  className,
  headerRow,
  idColumn,
}) =>
  /* @__PURE__ */ createElement(
    'table',
    {className},
    headerRow === false
      ? null
      : /* @__PURE__ */ createElement(
          'thead',
          null,
          /* @__PURE__ */ createElement(
            'tr',
            null,
            idColumn === false
              ? null
              : /* @__PURE__ */ createElement('th', null, 'Id'),
            /* @__PURE__ */ createElement('th', null, VALUE),
          ),
        ),
    /* @__PURE__ */ createElement(
      'tbody',
      null,
      arrayMap(uiReact.useValueIds(store), (valueId) =>
        /* @__PURE__ */ createElement(
          'tr',
          {key: valueId},
          idColumn === false
            ? null
            : /* @__PURE__ */ createElement('th', null, valueId),
          /* @__PURE__ */ createElement(
            'td',
            null,
            /* @__PURE__ */ createElement(
              Value,
              __spreadProps(
                __spreadValues({}, getProps(getValueComponentProps, valueId)),
                {
                  valueId,
                  store,
                },
              ),
            ),
          ),
        ),
      ),
    ),
  );
const SliceInHtmlTable = (_e) => {
  var _f = _e,
    {indexId, sliceId, indexes, editable, customCells} = _f,
    props = __objRest(_f, [
      'indexId',
      'sliceId',
      'indexes',
      'editable',
      'customCells',
    ]);
  const [resolvedIndexes, store, tableId] = getIndexStoreTableId(
    uiReact.useIndexesOrIndexesById(indexes),
    indexId,
  );
  return /* @__PURE__ */ createElement(
    HtmlTable,
    __spreadProps(__spreadValues({}, props), {
      params: useParams(
        useCells(
          uiReact.useTableCellIds(tableId, store),
          customCells,
          editable ? EditableCellView : uiReact.CellView,
        ),
        useStoreCellComponentProps(store, tableId),
        uiReact.useSliceRowIds(indexId, sliceId, resolvedIndexes),
      ),
    }),
  );
};
const RelationshipInHtmlTable = ({
  relationshipId,
  relationships,
  editable,
  customCells,
  className,
  headerRow,
  idColumn = true,
}) => {
  const [resolvedRelationships, store, localTableId, remoteTableId] =
    getRelationshipsStoreTableIds(
      uiReact.useRelationshipsOrRelationshipsById(relationships),
      relationshipId,
    );
  const cells = useCells(
    [
      ...useDottedCellIds(localTableId, store),
      ...useDottedCellIds(remoteTableId, store),
    ],
    customCells,
    editable ? EditableCellView : uiReact.CellView,
  );
  const params = useParams(
    idColumn,
    cells,
    localTableId,
    remoteTableId,
    relationshipId,
    resolvedRelationships,
    store,
  );
  return /* @__PURE__ */ createElement(
    'table',
    {className},
    headerRow === false
      ? null
      : /* @__PURE__ */ createElement(
          'thead',
          null,
          /* @__PURE__ */ createElement(
            'tr',
            null,
            idColumn === false
              ? null
              : /* @__PURE__ */ createElement(
                  React.Fragment,
                  null,
                  /* @__PURE__ */ createElement(
                    'th',
                    null,
                    localTableId,
                    '.Id',
                  ),
                  /* @__PURE__ */ createElement(
                    'th',
                    null,
                    remoteTableId,
                    '.Id',
                  ),
                ),
            objToArray(cells, ({label}, cellId) =>
              /* @__PURE__ */ createElement('th', {key: cellId}, label),
            ),
          ),
        ),
    /* @__PURE__ */ createElement(
      'tbody',
      null,
      arrayMap(uiReact.useRowIds(localTableId, store), (localRowId) =>
        /* @__PURE__ */ createElement(RelationshipInHtmlRow, {
          key: localRowId,
          localRowId,
          params,
        }),
      ),
    ),
  );
};
const ResultTableInHtmlTable = (_g) => {
  var _h = _g,
    {queryId, queries, customCells} = _h,
    props = __objRest(_h, ['queryId', 'queries', 'customCells']);
  return /* @__PURE__ */ createElement(
    HtmlTable,
    __spreadProps(__spreadValues({}, props), {
      params: useParams(
        useCells(
          uiReact.useResultTableCellIds(queryId, queries),
          customCells,
          uiReact.ResultCellView,
        ),
        useQueriesCellComponentProps(queries, queryId),
        uiReact.useResultRowIds(queryId, queries),
      ),
    }),
  );
};
const ResultSortedTableInHtmlTable = (_i) => {
  var _j = _i,
    {
      queryId,
      cellId,
      descending,
      offset,
      limit,
      queries,
      sortOnClick,
      paginator = false,
      customCells,
      onChange,
    } = _j,
    props = __objRest(_j, [
      'queryId',
      'cellId',
      'descending',
      'offset',
      'limit',
      'queries',
      'sortOnClick',
      'paginator',
      'customCells',
      'onChange',
    ]);
  const [sortAndOffset, handleSort, paginatorComponent] =
    useSortingAndPagination(
      cellId,
      descending,
      sortOnClick,
      offset,
      limit,
      uiReact.useResultRowCount(queryId, queries),
      paginator,
      onChange,
    );
  return /* @__PURE__ */ createElement(
    HtmlTable,
    __spreadProps(__spreadValues({}, props), {
      params: useParams(
        useCells(
          uiReact.useResultTableCellIds(queryId, queries),
          customCells,
          uiReact.ResultCellView,
        ),
        useQueriesCellComponentProps(queries, queryId),
        uiReact.useResultSortedRowIds(
          queryId,
          ...sortAndOffset,
          limit,
          queries,
        ),
        sortAndOffset,
        handleSort,
        paginatorComponent,
      ),
    }),
  );
};
const EditableCellView = ({
  tableId,
  rowId,
  cellId,
  store,
  className,
  showType,
}) => {
  var _a;
  return /* @__PURE__ */ createElement(EditableThing, {
    thing: uiReact.useCell(tableId, rowId, cellId, store),
    onThingChange: uiReact.useSetCellCallback(
      tableId,
      rowId,
      cellId,
      (cell) => cell,
      [],
      store,
    ),
    className: className != null ? className : EDITABLE + CELL,
    showType,
    hasSchema:
      (_a = uiReact.useStoreOrStoreById(store)) == null
        ? void 0
        : _a.hasTablesSchema,
  });
};
const EditableValueView = ({valueId, store, className, showType}) => {
  var _a;
  return /* @__PURE__ */ createElement(EditableThing, {
    thing: uiReact.useValue(valueId, store),
    onThingChange: uiReact.useSetValueCallback(
      valueId,
      (value) => value,
      [],
      store,
    ),
    className: className != null ? className : EDITABLE + VALUE,
    showType,
    hasSchema:
      (_a = uiReact.useStoreOrStoreById(store)) == null
        ? void 0
        : _a.hasValuesSchema,
  });
};
const SortedTablePaginator = ({
  onChange,
  total,
  offset = 0,
  limit = total,
  singular = 'row',
  plural = singular + 's',
}) => {
  if (offset > total || offset < 0) {
    offset = 0;
    onChange(0);
  }
  const handlePrevClick = useCallbackOrUndefined(
    () => onChange(offset - limit),
    [onChange, offset, limit],
    offset > 0,
  );
  const handleNextClick = useCallbackOrUndefined(
    () => onChange(offset + limit),
    [onChange, offset, limit],
    offset + limit < total,
  );
  return /* @__PURE__ */ createElement(
    React.Fragment,
    null,
    total > limit &&
      /* @__PURE__ */ createElement(
        React.Fragment,
        null,
        /* @__PURE__ */ createElement(
          'button',
          {
            className: 'previous',
            disabled: offset == 0,
            onClick: handlePrevClick,
          },
          LEFT_ARROW,
        ),
        /* @__PURE__ */ createElement(
          'button',
          {
            className: 'next',
            disabled: offset + limit >= total,
            onClick: handleNextClick,
          },
          RIGHT_ARROW,
        ),
        offset + 1,
        ' to ',
        mathMin(total, offset + limit),
        ' of ',
      ),
    total,
    ' ',
    total != 1 ? plural : singular,
  );
};

exports.EditableCellView = EditableCellView;
exports.EditableValueView = EditableValueView;
exports.RelationshipInHtmlTable = RelationshipInHtmlTable;
exports.ResultSortedTableInHtmlTable = ResultSortedTableInHtmlTable;
exports.ResultTableInHtmlTable = ResultTableInHtmlTable;
exports.SliceInHtmlTable = SliceInHtmlTable;
exports.SortedTableInHtmlTable = SortedTableInHtmlTable;
exports.SortedTablePaginator = SortedTablePaginator;
exports.TableInHtmlTable = TableInHtmlTable;
exports.ValuesInHtmlTable = ValuesInHtmlTable;
