import { r as registerInstance, c as createEvent, h, H as Host, g as getElement } from './index-BIwHMk6j.js';
import { b as n } from './index.esm-CMeGYws2.js';
import { H as HighlightFeedItemHandler } from './highlight-item.handler-BWMpG2bS.js';

var differenceInMinutes = {};

var getRoundingMethod = {};

var hasRequiredGetRoundingMethod;

function requireGetRoundingMethod () {
	if (hasRequiredGetRoundingMethod) return getRoundingMethod;
	hasRequiredGetRoundingMethod = 1;
	getRoundingMethod.getRoundingMethod = getRoundingMethod$1;

	function getRoundingMethod$1(method) {
	  return (number) => {
	    const round = method ? Math[method] : Math.trunc;
	    const result = round(number);
	    // Prevent negative zero
	    return result === 0 ? 0 : result;
	  };
	}
	return getRoundingMethod;
}

var constants = {};

var hasRequiredConstants;

function requireConstants () {
	if (hasRequiredConstants) return constants;
	hasRequiredConstants = 1;
	constants.secondsInYear =
	  constants.secondsInWeek =
	  constants.secondsInQuarter =
	  constants.secondsInMonth =
	  constants.secondsInMinute =
	  constants.secondsInHour =
	  constants.secondsInDay =
	  constants.quartersInYear =
	  constants.monthsInYear =
	  constants.monthsInQuarter =
	  constants.minutesInYear =
	  constants.minutesInMonth =
	  constants.minutesInHour =
	  constants.minutesInDay =
	  constants.minTime =
	  constants.millisecondsInWeek =
	  constants.millisecondsInSecond =
	  constants.millisecondsInMinute =
	  constants.millisecondsInHour =
	  constants.millisecondsInDay =
	  constants.maxTime =
	  constants.daysInYear =
	  constants.daysInWeek =
	    void 0; /**
	 * @module constants
	 * @summary Useful constants
	 * @description
	 * Collection of useful date constants.
	 *
	 * The constants could be imported from `date-fns/constants`:
	 *
	 * ```ts
	 * import { maxTime, minTime } from "date-fns/constants";
	 *
	 * function isAllowedTime(time) {
	 *   return time <= maxTime && time >= minTime;
	 * }
	 * ```
	 */

	/**
	 * @constant
	 * @name daysInWeek
	 * @summary Days in 1 week.
	 */
	(constants.daysInWeek = 7);

	/**
	 * @constant
	 * @name daysInYear
	 * @summary Days in 1 year.
	 *
	 * @description
	 * How many days in a year.
	 *
	 * One years equals 365.2425 days according to the formula:
	 *
	 * > Leap year occures every 4 years, except for years that are divisable by 100 and not divisable by 400.
	 * > 1 mean year = (365+1/4-1/100+1/400) days = 365.2425 days
	 */
	const daysInYear = (constants.daysInYear = 365.2425);

	/**
	 * @constant
	 * @name maxTime
	 * @summary Maximum allowed time.
	 *
	 * @example
	 * import { maxTime } from "date-fns/constants";
	 *
	 * const isValid = 8640000000000001 <= maxTime;
	 * //=> false
	 *
	 * new Date(8640000000000001);
	 * //=> Invalid Date
	 */
	const maxTime = (constants.maxTime = Math.pow(10, 8) * 24 * 60 * 60 * 1000);

	/**
	 * @constant
	 * @name minTime
	 * @summary Minimum allowed time.
	 *
	 * @example
	 * import { minTime } from "date-fns/constants";
	 *
	 * const isValid = -8640000000000001 >= minTime;
	 * //=> false
	 *
	 * new Date(-8640000000000001)
	 * //=> Invalid Date
	 */
	(constants.minTime = -maxTime);

	/**
	 * @constant
	 * @name millisecondsInWeek
	 * @summary Milliseconds in 1 week.
	 */
	(constants.millisecondsInWeek = 604800000);

	/**
	 * @constant
	 * @name millisecondsInDay
	 * @summary Milliseconds in 1 day.
	 */
	(constants.millisecondsInDay = 86400000);

	/**
	 * @constant
	 * @name millisecondsInMinute
	 * @summary Milliseconds in 1 minute
	 */
	(constants.millisecondsInMinute = 60000);

	/**
	 * @constant
	 * @name millisecondsInHour
	 * @summary Milliseconds in 1 hour
	 */
	(constants.millisecondsInHour = 3600000);

	/**
	 * @constant
	 * @name millisecondsInSecond
	 * @summary Milliseconds in 1 second
	 */
	(constants.millisecondsInSecond = 1000);

	/**
	 * @constant
	 * @name minutesInYear
	 * @summary Minutes in 1 year.
	 */
	(constants.minutesInYear = 525600);

	/**
	 * @constant
	 * @name minutesInMonth
	 * @summary Minutes in 1 month.
	 */
	(constants.minutesInMonth = 43200);

	/**
	 * @constant
	 * @name minutesInDay
	 * @summary Minutes in 1 day.
	 */
	(constants.minutesInDay = 1440);

	/**
	 * @constant
	 * @name minutesInHour
	 * @summary Minutes in 1 hour.
	 */
	(constants.minutesInHour = 60);

	/**
	 * @constant
	 * @name monthsInQuarter
	 * @summary Months in 1 quarter.
	 */
	(constants.monthsInQuarter = 3);

	/**
	 * @constant
	 * @name monthsInYear
	 * @summary Months in 1 year.
	 */
	(constants.monthsInYear = 12);

	/**
	 * @constant
	 * @name quartersInYear
	 * @summary Quarters in 1 year
	 */
	(constants.quartersInYear = 4);

	/**
	 * @constant
	 * @name secondsInHour
	 * @summary Seconds in 1 hour.
	 */
	const secondsInHour = (constants.secondsInHour = 3600);

	/**
	 * @constant
	 * @name secondsInMinute
	 * @summary Seconds in 1 minute.
	 */
	(constants.secondsInMinute = 60);

	/**
	 * @constant
	 * @name secondsInDay
	 * @summary Seconds in 1 day.
	 */
	const secondsInDay = (constants.secondsInDay = secondsInHour * 24);

	/**
	 * @constant
	 * @name secondsInWeek
	 * @summary Seconds in 1 week.
	 */
	(constants.secondsInWeek = secondsInDay * 7);

	/**
	 * @constant
	 * @name secondsInYear
	 * @summary Seconds in 1 year.
	 */
	const secondsInYear = (constants.secondsInYear = secondsInDay * daysInYear);

	/**
	 * @constant
	 * @name secondsInMonth
	 * @summary Seconds in 1 month
	 */
	const secondsInMonth = (constants.secondsInMonth = secondsInYear / 12);

	/**
	 * @constant
	 * @name secondsInQuarter
	 * @summary Seconds in 1 quarter.
	 */
	(constants.secondsInQuarter = secondsInMonth * 3);
	return constants;
}

var differenceInMilliseconds = {};

var toDate = {};

var hasRequiredToDate;

function requireToDate () {
	if (hasRequiredToDate) return toDate;
	hasRequiredToDate = 1;
	toDate.toDate = toDate$1;

	/**
	 * @name toDate
	 * @category Common Helpers
	 * @summary Convert the given argument to an instance of Date.
	 *
	 * @description
	 * Convert the given argument to an instance of Date.
	 *
	 * If the argument is an instance of Date, the function returns its clone.
	 *
	 * If the argument is a number, it is treated as a timestamp.
	 *
	 * If the argument is none of the above, the function returns Invalid Date.
	 *
	 * **Note**: *all* Date arguments passed to any *date-fns* function is processed by `toDate`.
	 *
	 * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
	 *
	 * @param argument - The value to convert
	 *
	 * @returns The parsed date in the local time zone
	 *
	 * @example
	 * // Clone the date:
	 * const result = toDate(new Date(2014, 1, 11, 11, 30, 30))
	 * //=> Tue Feb 11 2014 11:30:30
	 *
	 * @example
	 * // Convert the timestamp to date:
	 * const result = toDate(1392098430000)
	 * //=> Tue Feb 11 2014 11:30:30
	 */
	function toDate$1(argument) {
	  const argStr = Object.prototype.toString.call(argument);

	  // Clone the date
	  if (
	    argument instanceof Date ||
	    (typeof argument === "object" && argStr === "[object Date]")
	  ) {
	    // Prevent the date to lose the milliseconds when passed to new Date() in IE10
	    return new argument.constructor(+argument);
	  } else if (
	    typeof argument === "number" ||
	    argStr === "[object Number]" ||
	    typeof argument === "string" ||
	    argStr === "[object String]"
	  ) {
	    // TODO: Can we get rid of as?
	    return new Date(argument);
	  } else {
	    // TODO: Can we get rid of as?
	    return new Date(NaN);
	  }
	}
	return toDate;
}

var hasRequiredDifferenceInMilliseconds;

function requireDifferenceInMilliseconds () {
	if (hasRequiredDifferenceInMilliseconds) return differenceInMilliseconds;
	hasRequiredDifferenceInMilliseconds = 1;
	differenceInMilliseconds.differenceInMilliseconds = differenceInMilliseconds$1;
	var _index = /*@__PURE__*/ requireToDate();

	/**
	 * @name differenceInMilliseconds
	 * @category Millisecond Helpers
	 * @summary Get the number of milliseconds between the given dates.
	 *
	 * @description
	 * Get the number of milliseconds between the given dates.
	 *
	 * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
	 *
	 * @param dateLeft - The later date
	 * @param dateRight - The earlier date
	 *
	 * @returns The number of milliseconds
	 *
	 * @example
	 * // How many milliseconds are between
	 * // 2 July 2014 12:30:20.600 and 2 July 2014 12:30:21.700?
	 * const result = differenceInMilliseconds(
	 *   new Date(2014, 6, 2, 12, 30, 21, 700),
	 *   new Date(2014, 6, 2, 12, 30, 20, 600)
	 * )
	 * //=> 1100
	 */
	function differenceInMilliseconds$1(dateLeft, dateRight) {
	  return +(0, _index.toDate)(dateLeft) - +(0, _index.toDate)(dateRight);
	}
	return differenceInMilliseconds;
}

var hasRequiredDifferenceInMinutes;

function requireDifferenceInMinutes () {
	if (hasRequiredDifferenceInMinutes) return differenceInMinutes;
	hasRequiredDifferenceInMinutes = 1;
	differenceInMinutes.differenceInMinutes = differenceInMinutes$1;
	var _index = /*@__PURE__*/ requireGetRoundingMethod();
	var _index2 = /*@__PURE__*/ requireConstants();
	var _index3 = /*@__PURE__*/ requireDifferenceInMilliseconds();

	/**
	 * The {@link differenceInMinutes} function options.
	 */

	/**
	 * @name differenceInMinutes
	 * @category Minute Helpers
	 * @summary Get the number of minutes between the given dates.
	 *
	 * @description
	 * Get the signed number of full (rounded towards 0) minutes between the given dates.
	 *
	 * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
	 *
	 * @param dateLeft - The later date
	 * @param dateRight - The earlier date
	 * @param options - An object with options.
	 *
	 * @returns The number of minutes
	 *
	 * @example
	 * // How many minutes are between 2 July 2014 12:07:59 and 2 July 2014 12:20:00?
	 * const result = differenceInMinutes(
	 *   new Date(2014, 6, 2, 12, 20, 0),
	 *   new Date(2014, 6, 2, 12, 7, 59)
	 * )
	 * //=> 12
	 *
	 * @example
	 * // How many minutes are between 10:01:59 and 10:00:00
	 * const result = differenceInMinutes(
	 *   new Date(2000, 0, 1, 10, 0, 0),
	 *   new Date(2000, 0, 1, 10, 1, 59)
	 * )
	 * //=> -1
	 */
	function differenceInMinutes$1(dateLeft, dateRight, options) {
	  const diff =
	    (0, _index3.differenceInMilliseconds)(dateLeft, dateRight) /
	    _index2.millisecondsInMinute;
	  return (0, _index.getRoundingMethod)(options?.roundingMethod)(diff);
	}
	return differenceInMinutes;
}

var differenceInMinutesExports = /*@__PURE__*/ requireDifferenceInMinutes();

const feedCss = () => `:host(limebb-feed){--limebb-feed-background-color:var(       --feed-background-color,       rgb(var(--contrast-100))   );--limebb-feed-item-background-color:var(--contrast-300);display:flex;flex-direction:column;gap:0.25rem;max-width:45rem;background-color:var(--limebb-feed-background-color)}limel-spinner{align-self:center;justify-self:center;margin:auto}.date-group{isolation:isolate;display:flex;flex-direction:column;gap:0.375rem}.date-heading{position:sticky;z-index:1;top:0.25rem;display:flex;border-radius:9rem;padding:0.25rem 0.5rem;margin:0 auto 0 -0.5rem;width:fit-content;font-size:0.75rem;line-height:1;color:rgb(var(--contrast-900));backdrop-filter:blur(0.5rem);-webkit-backdrop-filter:blur(0.5rem);transition:color 0.2s ease, border-color 0.4s ease}.date-heading:hover{color:rgb(var(--contrast-1000));border-color:rgb(var(--contrast-500))}.date-heading:hover:before{opacity:1}.date-heading:before{transition:opacity 0.2s ease;content:"";position:absolute;z-index:-1;inset:0;opacity:0.6;border-radius:inherit;background-color:rgb(var(--contrast-100))}limebb-feed-timeline-item:has(+limebb-feed-timeline-item[is-bundled]){--limebb-promoted-action-bar-grid-template-rows:0fr}.load-more-button{margin-top:0.5rem}limebb-feed-timeline-item:focus{outline:none}limebb-feed-timeline-item[aria-current=true]:focus{animation:highlight-animation ease-in-out;animation-duration:var(--limebb-feed-highlight-duration)}@keyframes highlight-animation{0%,20%,100%{box-shadow:none}10%,50%,60%{box-shadow:var(--shadow-focused-state)}}`;

const MINUTES_OF_PROXIMITY = 5;
const ITEM_HIGHLIGHT_DURATION = 3000;
const Feed = class {
    constructor(hostRef) {
        registerInstance(this, hostRef);
        this.loadMore = createEvent(this, "loadMore");
        this.highlightedItemIdNotFound = createEvent(this, "highlightedItemIdNotFound");
        /**
         * List of items to display in the feed.
         */
        this.items = [];
        /**
         * Number of minutes to take into account, when bundling several
         * feed-items that are created by the same author in a close timespan.
         */
        this.minutesOfProximity = MINUTES_OF_PROXIMITY;
        /**
         * The total number of items available
         */
        this.totalCount = 0;
        /**
         * Defines the chronological sorting of the array of items which are
         * provided to the feed. It is used for visual grouping & bundling logic,
         * as well as rendering the last visited timestamp in the right place.
         * - 'ASC'  : Items are provided oldest -> newest (newest last).
         * Often used when the UI shows newer items near the bottom and older ones above.
         * - 'DESC' : Items are provided newest -> oldest (newest first).
         * Often used when the UI places the latest item at the top.
         *
         * :::important
         * This component does not re-sort the provided `items`.
         * It only renders them in the order received from the consumer.
         * :::
         */
        this.direction = 'ASC';
        this.isBundled = (item, index) => {
            var _a, _b, _c, _d, _e, _f;
            if (index === 0) {
                return false;
            }
            const previousAuthorId = (_b = (_a = this.items[index - 1]) === null || _a === void 0 ? void 0 : _a.author) === null || _b === void 0 ? void 0 : _b.id;
            const currentAuthorId = (_c = item === null || item === void 0 ? void 0 : item.author) === null || _c === void 0 ? void 0 : _c.id;
            if (previousAuthorId !== currentAuthorId) {
                return false;
            }
            const previousItemIcon = (_e = (_d = this.items[index - 1]) === null || _d === void 0 ? void 0 : _d.icon) === null || _e === void 0 ? void 0 : _e.name;
            const currentItemIcon = (_f = item === null || item === void 0 ? void 0 : item.icon) === null || _f === void 0 ? void 0 : _f.name;
            if (previousItemIcon !== currentItemIcon) {
                return false;
            }
            const currentIndexDate = new Date(item.timestamp);
            const previousIndexDate = new Date(this.items[index - 1].timestamp);
            const previousItemDate = new Date(previousIndexDate);
            const currentItemDate = new Date(currentIndexDate);
            if (this.direction === 'DESC') {
                return (differenceInMinutesExports.differenceInMinutes(previousItemDate, currentItemDate) <=
                    this.minutesOfProximity);
            }
            return (differenceInMinutesExports.differenceInMinutes(currentItemDate, previousItemDate) <=
                this.minutesOfProximity);
        };
        this.handleLoadMore = (event) => {
            event.stopPropagation();
            this.loadMore.emit();
        };
    }
    connectedCallback() {
        this.highlighter.registerFeed(this.feedItemElement);
    }
    disconnectedCallback() {
        this.highlighter.unregisterFeed(this.feedItemElement);
    }
    render() {
        return (h(Host, { key: '5d1c5d6ff9949229a0bafbdb060a0bc386a8eb03', role: "log", "aria-busy": this.loading ? 'true' : 'false', style: {
                '--limebb-feed-highlight-duration': `${ITEM_HIGHLIGHT_DURATION}ms`,
            } }, this.renderLoadMore(), this.renderEmptyFeedMessage(), this.renderSpinner(), this.renderFeedItems()));
    }
    renderSpinner() {
        if (this.loading) {
            return h("limel-spinner", { size: "small" });
        }
    }
    renderEmptyFeedMessage() {
        if (this.loading) {
            return;
        }
        if (this.items.length === 0) {
            return (h("limebb-empty-state", { heading: this.heading, value: this.emptyStateMessage, icon: {
                    name: 'typewriter_with_paper',
                    color: 'rgb(var(--contrast-800))',
                } }));
        }
    }
    renderFeedItems() {
        return this.groupedItems.map((group) => (h("section", { class: "date-group", key: `date-group-${group.date}` }, h("a", { class: "date-heading" }, group.date), group.items.map(({ item, index }) => (h("limebb-feed-timeline-item", { platform: this.platform, context: this.context, item: item, key: item.id, ui: item === null || item === void 0 ? void 0 : item.ui, helperText: item === null || item === void 0 ? void 0 : item.helperText, hasError: item === null || item === void 0 ? void 0 : item.hasError, isBundled: this.isBundled(item, index), class: this.isNewItem(item) ? 'is-new' : undefined }))))));
    }
    isNewItem(item) {
        if (!this.lastVisitedTimestamp) {
            return false;
        }
        const lastVisited = new Date(this.lastVisitedTimestamp);
        const itemTime = new Date(item.timestamp);
        return itemTime > lastVisited;
    }
    renderLoadMore() {
        if (this.items.length === 0 || this.totalCount <= this.items.length) {
            return;
        }
        return (h("limel-icon-button", { class: "load-more-button", icon: "more", onClick: this.handleLoadMore, elevated: true, label: this.loadMoreLabel }));
    }
    get dateTimeFormatter() {
        return this.platform.get(n.DateTimeFormatter);
    }
    get loadMoreLabel() {
        return this.translator.get('webclient.load-more');
    }
    get translator() {
        return this.platform.get(n.Translate);
    }
    /**
     * Groups feed items by calendar date (formatted using date formatter 'date').
     * Returns an array of groups each containing the display date string and
     * the original items with their indices.
     */
    get groupedItems() {
        const groups = [];
        for (let index = 0; index < this.items.length; index++) {
            const item = this.items[index];
            const dateKey = this.dateTimeFormatter.format(item.timestamp, 'date');
            const lastGroup = groups.at(-1);
            if (!lastGroup || lastGroup.date !== dateKey) {
                groups.push({ date: dateKey, items: [{ item, index }] });
            }
            else {
                lastGroup.items.push({ item, index });
            }
        }
        return groups;
    }
    highlightedItemIdChanged(newValue) {
        if (newValue !== undefined) {
            this.highlightItem(newValue);
        }
    }
    highlightItem(id) {
        var _a;
        const itemElement = (_a = this.feedItemElement.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector(`limebb-feed-timeline-item[id="${id}"]`);
        if (itemElement) {
            itemElement.setAttribute('aria-current', 'true');
            itemElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
            itemElement.focus();
            setTimeout(() => {
                itemElement.removeAttribute('aria-current');
            }, ITEM_HIGHLIGHT_DURATION);
            return true;
        }
        this.highlightedItemIdNotFound.emit({ id: id });
        return false;
    }
    get highlighter() {
        return this.platform.get(HighlightFeedItemHandler.SERVICE_NAME);
    }
    get feedItemElement() { return getElement(this); }
    static get watchers() { return {
        "highlightedItemId": [{
                "highlightedItemIdChanged": 0
            }]
    }; }
};
Feed.style = feedCss();

export { Feed as limebb_feed };
