{"version":3,"file":"index.mjs","sources":[""],"sourcesContent":["import {\r\n  layout,\r\n  measureLineStats,\r\n  measureNaturalWidth,\r\n  prepareWithSegments,\r\n} from \"@chenglou/pretext\";\r\nimport { getElWrapper } from \"@web3r/flowerkit/dom\";\r\nimport { getDocument } from \"ssr-window\";\r\nimport type { TStaticElementCfg } from \"../../utils/getCfg\";\r\nimport { getCfg } from \"../../utils/getCfg\";\r\nimport { Dispatcher } from \"../dispatcher\";\r\n\r\nexport interface IAdaptiveTableCfg {\r\n  isFormatText: boolean;\r\n  minWidth: number;\r\n  maxWidth: number;\r\n  thresholdColsNumber: number;\r\n  horizontalPadding: number;\r\n  heightWeight: number;\r\n  lineWeight: number;\r\n}\r\n\r\ntype TAdaptiveTableWidthCandidate = {\r\n  width: number;\r\n  lineCount: number;\r\n  score: number;\r\n};\r\n\r\n/**\r\n * Singleton. Плагин для создания адаптивных таблиц.\r\n * Обеспечивает таблицы горизонтальной прокруткой, делая их адаптивными на мобильных устройствах путём оборачивания исходного элемента в новые блоки с возможностью скроллинга. Имеет несколько статических методов.\r\n * В зависимости от крайнего положения скролла у элемента `div.adaptiveTable` динамически изменяются классы `isEdgeLeft` и `isEdgeRight`, служащие для появления и скрытия декоративных теней.\r\n * @module AdaptiveTable\r\n * @example\r\n * <!-- До применения плагина -->\r\n * <table></table>\r\n * <table data-js-adaptiveTableExclude=\"\"></table>\r\n *\r\n * <!-- После применения плагина -->\r\n * <div data-js-adaptive-table class=\"adaptiveTable isEdgeLeft\"><div class=\"adaptiveTable__wrapper\"><table></table></div></div>\r\n * <table data-js-adaptiveTableExclude=\"\"></table>\r\n */\r\nexport class AdaptiveTable {\r\n\r\n  static #instance: AdaptiveTable | null = null;\r\n\r\n  /**\r\n   * Селекторы, используемые для поиска обёртки адаптивной таблицы и исключений.\r\n   * @type {{instance: string, customAdaptiveTable: string}}\r\n   */\r\n  static selectors = {\r\n    instance: \"[data-js-adaptiveTable]\",\r\n    customAdaptiveTable: \"[data-js-adaptiveTableExclude]\",\r\n  };\r\n\r\n  /**\r\n   * Конфигурация по умолчанию для адаптивных таблиц.\r\n   */\r\n  static defaultCfg: IAdaptiveTableCfg = {\r\n    /** Включает автоматический подбор минимальной ширины ячеек по тексту. */\r\n    isFormatText: true,\r\n    /** Минимально допустимая ширина ячейки. */\r\n    minWidth: 120,\r\n    /** Верхняя граница ширины ячейки, чтобы таблица не расползалась. */\r\n    maxWidth: 400,\r\n    /** Минимальное количество колонок, начиная с которого включается оптимизация. */\r\n    thresholdColsNumber: 7,\r\n    /** Базовый запас по горизонтали под внутренние отступы ячейки. */\r\n    horizontalPadding: 16,\r\n    /** Вес штрафа за избыточную высоту текста в ячейке. */\r\n    heightWeight: 2,\r\n    /** Вес штрафа за дополнительные переносы строк. */\r\n    lineWeight: 4,\r\n  };\r\n\r\n  static #classStates = {\r\n    leftEdge: \"isEdgeLeft\",\r\n    rightEdge: \"isEdgeRight\",\r\n    formatText: \"adaptiveTable--isFormatted\",\r\n  };\r\n\r\n  static #layouts = {\r\n    wrap: `<div data-js-adaptiveTable class=\"adaptiveTable\"><div class=\"adaptiveTable__wrapper\"></div></div>`,\r\n  };\r\n\r\n  static #measurementCache = new Map<string, number>();\r\n\r\n  static #scrollEdgeThreshold = 1;\r\n\r\n  constructor() {\r\n    if (AdaptiveTable.#instance) {\r\n      return AdaptiveTable.#instance;\r\n    }\r\n    AdaptiveTable.init();\r\n    AdaptiveTable.#bindEvents();\r\n    AdaptiveTable.#instance = this;\r\n  }\r\n\r\n  static #bindEvents() {\r\n    Dispatcher.initiator = {\r\n      selector: AdaptiveTable.selectors.instance,\r\n      initiator: (context: Document | HTMLElement) => AdaptiveTable.init(context),\r\n      getCollection: () => [],\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Проверяет, является ли таблица адаптивной\r\n   * @param table{HTMLTableElement} таблица\r\n   * @returns {boolean}\r\n   */\r\n  static isAdaptive(table: HTMLTableElement): boolean {\r\n    return !table.closest(AdaptiveTable.selectors.instance)\r\n      && !table.matches(AdaptiveTable.selectors.customAdaptiveTable)\r\n      && !table.closest(AdaptiveTable.selectors.customAdaptiveTable);\r\n  }\r\n\r\n  /**\r\n   * Инициализатор плагина\r\n   * @param context{Document|HTMLElement} контекст поиска элементов\r\n   */\r\n  static init(context: Document | HTMLElement = getDocument()) {\r\n    context.querySelectorAll<HTMLTableElement>(\"table\").forEach((table: HTMLTableElement) => {\r\n      if (AdaptiveTable.isAdaptive(table)) {\r\n        const wrapped = getElWrapper(table, AdaptiveTable.#layouts.wrap) as HTMLElement;\r\n        wrapped.scrollLeft = 0;\r\n        AdaptiveTable.#bindScrollEvent(wrapped);\r\n        const container = AdaptiveTable.#getContainer(wrapped);\r\n        if (container instanceof HTMLElement) {\r\n          AdaptiveTable.formatText(container);\r\n          AdaptiveTable.setEdges(container);\r\n        }\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Запускает дополнительное форматирование текста таблицы, если оно включено в конфиге.\r\n   * @param container{HTMLElement} адаптивный контейнер таблицы\r\n   */\r\n  static formatText(container: HTMLElement) {\r\n    const cfg = AdaptiveTable.#getCfg(container);\r\n    if (!cfg.isFormatText) {\r\n      return;\r\n    }\r\n\r\n    const table = container.querySelector<HTMLTableElement>(\"table\");\r\n\r\n    if (!table) {\r\n      return;\r\n    }\r\n\r\n    AdaptiveTable.#optimiseTable(container, table, cfg);\r\n  }\r\n\r\n  /**\r\n   * Добавляет класс для оптимизированной таблицы\r\n   * @param container\r\n   * @private\r\n   */\r\n  static #addFormatClass(container: HTMLElement) {\r\n    container.classList.add(AdaptiveTable.#classStates.formatText);\r\n  }\r\n\r\n  /**\r\n   * Получает конфигурацию адаптивного контейнера.\r\n   * @param container{HTMLElement} адаптивный контейнер таблицы\r\n   * @returns {TStaticElementCfg<IAdaptiveTableCfg>}\r\n   */\r\n  static #getCfg(container: HTMLElement): TStaticElementCfg<IAdaptiveTableCfg> {\r\n    return getCfg(container, AdaptiveTable.selectors.instance, AdaptiveTable.defaultCfg);\r\n  }\r\n\r\n  /**\r\n   * Проходит по всем ячейкам таблицы и выставляет для каждой рассчитанный `min-width`.\r\n   * Оптимизация запускается только для таблиц, у которых количество колонок превышает заданный порог.\r\n   * После оптимизации добавляется класс для плавных переходов\r\n   * @param container{HTMLElement} адаптивный контейнер таблицы\r\n   * @param table{HTMLTableElement} таблица\r\n   * @param cfg{TStaticElementCfg<IAdaptiveTableCfg>} конфигурация\r\n   */\r\n  static #optimiseTable(container: HTMLElement, table: HTMLTableElement, cfg: TStaticElementCfg<IAdaptiveTableCfg>) {\r\n    const rows = [ ...table.rows ];\r\n\r\n    if (!rows.length) {\r\n      return;\r\n    }\r\n\r\n    const colsCount = rows[0].cells.length;\r\n\r\n    if (colsCount < cfg.thresholdColsNumber || !AdaptiveTable.#isMeasurementSupported()) {\r\n      return;\r\n    }\r\n\r\n    rows.forEach((row) => {\r\n      [ ...row.cells ].forEach((cell) => {\r\n        cell.style.minWidth = `${AdaptiveTable.#measureCell(cell, cfg)}px`;\r\n      });\r\n    });\r\n\r\n    AdaptiveTable.#addFormatClass(container);\r\n  }\r\n\r\n  /**\r\n   * Проверяет доступность canvas-измерений, необходимых для pretext.\r\n   * @returns {boolean}\r\n   */\r\n  static #isMeasurementSupported() {\r\n    try {\r\n      if (typeof OffscreenCanvas !== \"undefined\") {\r\n        return !!new OffscreenCanvas(1, 1).getContext(\"2d\");\r\n      }\r\n\r\n      if (typeof document === \"undefined\") {\r\n        return false;\r\n      }\r\n\r\n      return !!document.createElement(\"canvas\").getContext(\"2d\");\r\n    } catch {\r\n      return false;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Вычисляет оптимальную минимальную ширину ячейки на основе её текста и CSS-стилей.\r\n   * @param cell{HTMLTableCellElement} ячейка, для которой нужно подобрать ширину.\r\n   * @param cfg{TStaticElementCfg<IAdaptiveTableCfg>} конфигурация\r\n   * @returns итоговая минимальная ширина ячейки в пикселях.\r\n   */\r\n  static #measureCell(cell: HTMLTableCellElement, cfg: TStaticElementCfg<IAdaptiveTableCfg>): number {\r\n    const text = cell.textContent\r\n      ?.replace(/\\s+/g, \" \")\r\n      .trim();\r\n\r\n    if (!text) {\r\n      return cfg.minWidth;\r\n    }\r\n\r\n    const styles = window.getComputedStyle(cell);\r\n    const font = AdaptiveTable.#getCanvasFont(styles);\r\n    const lineHeight = AdaptiveTable.#getLineHeight(styles);\r\n    const letterSpacing = AdaptiveTable.#getLetterSpacing(styles);\r\n    const horizontalPadding = AdaptiveTable.#resolveHorizontalPadding(styles, cfg);\r\n    const whiteSpace = styles.whiteSpace.includes(\"pre\") ? \"pre-wrap\" : \"normal\";\r\n    const wordBreak = styles.wordBreak === \"keep-all\" ? \"keep-all\" : \"normal\";\r\n    const cacheKey = [\r\n      text,\r\n      font,\r\n      lineHeight,\r\n      letterSpacing,\r\n      horizontalPadding,\r\n      whiteSpace,\r\n      wordBreak,\r\n    ].join(\"|\");\r\n    const cachedWidth = AdaptiveTable.#measurementCache.get(cacheKey);\r\n\r\n    if (cachedWidth !== undefined) {\r\n      return cachedWidth;\r\n    }\r\n\r\n    const prepared = prepareWithSegments(text, font, {\r\n      whiteSpace,\r\n      wordBreak,\r\n      ...(letterSpacing !== 0 ? { letterSpacing } : {}),\r\n    });\r\n    const minContentWidth = Math.max(1, cfg.minWidth - horizontalPadding);\r\n    const maxContentWidth = Math.max(minContentWidth, cfg.maxWidth - horizontalPadding);\r\n    const naturalWidth = Math.ceil(measureNaturalWidth(prepared));\r\n\r\n    if (naturalWidth <= minContentWidth) {\r\n      AdaptiveTable.#measurementCache.set(cacheKey, cfg.minWidth);\r\n      return cfg.minWidth;\r\n    }\r\n\r\n    const optimalContentWidth = AdaptiveTable.#findOptimalWidth(prepared, minContentWidth, Math.min(maxContentWidth, naturalWidth), lineHeight, cfg);\r\n    const measuredWidth = Math.min(cfg.maxWidth, Math.max(cfg.minWidth, Math.ceil(optimalContentWidth + horizontalPadding)));\r\n\r\n    AdaptiveTable.#measurementCache.set(cacheKey, measuredWidth);\r\n\r\n    return measuredWidth;\r\n  }\r\n\r\n  /**\r\n   * Перебирает допустимый диапазон ширин и выбирает вариант с наилучшим интегральным score.\r\n   * @param prepared{ReturnType<typeof prepareWithSegments>} подготовленный pretext-объект для текста ячейки\r\n   * @param minWidth{number} нижняя граница перебора для контентной ширины\r\n   * @param maxWidth{number} верхняя граница перебора для контентной ширины\r\n   * @param lineHeight{number} текущая высота строки текста в ячейке\r\n   * @param cfg{TStaticElementCfg<IAdaptiveTableCfg>} конфигурация\r\n   * @returns {number} лучшая найденная контентная ширина в пикселях\r\n   */\r\n  static #findOptimalWidth(\r\n    prepared: ReturnType<typeof prepareWithSegments>,\r\n    minWidth: number,\r\n    maxWidth: number,\r\n    lineHeight: number,\r\n    cfg: TStaticElementCfg<IAdaptiveTableCfg>\r\n  ): number {\r\n    if (maxWidth <= minWidth) {\r\n      return minWidth;\r\n    }\r\n\r\n    const step = Math.max(4, Math.round((maxWidth - minWidth) / 24));\r\n    let bestWidth = maxWidth;\r\n    let bestScore = Number.POSITIVE_INFINITY;\r\n    let bestLineCount = Number.POSITIVE_INFINITY;\r\n\r\n    for (let width = minWidth; width <= maxWidth; width += step) {\r\n      const candidate = AdaptiveTable.#evaluateWidth(prepared, width, lineHeight, cfg);\r\n\r\n      if (AdaptiveTable.#shouldUseCandidate(candidate, bestScore, bestLineCount, bestWidth)) {\r\n        bestScore = candidate.score;\r\n        bestLineCount = candidate.lineCount;\r\n        bestWidth = candidate.width;\r\n      }\r\n    }\r\n\r\n    if ((maxWidth - minWidth) % step !== 0) {\r\n      const candidate = AdaptiveTable.#evaluateWidth(prepared, maxWidth, lineHeight, cfg);\r\n\r\n      if (AdaptiveTable.#shouldUseCandidate(candidate, bestScore, bestLineCount, bestWidth)) {\r\n        return candidate.width;\r\n      }\r\n    }\r\n\r\n    return bestWidth;\r\n  }\r\n\r\n  /**\r\n   * Считает метрики текста для конкретной ширины и формирует score кандидата.\r\n   * @param prepared{ReturnType<typeof prepareWithSegments>} подготовленный pretext-объект для текста ячейки\r\n   * @param width{number} проверяемая контентная ширина\r\n   * @param lineHeight{number} текущая высота строки текста в ячейке\r\n   * @param cfg{TStaticElementCfg<IAdaptiveTableCfg>} конфигурация\r\n   * @returns {TAdaptiveTableWidthCandidate} метрики кандидата для сравнения\r\n   */\r\n  static #evaluateWidth(\r\n    prepared: ReturnType<typeof prepareWithSegments>,\r\n    width: number,\r\n    lineHeight: number,\r\n    cfg: TStaticElementCfg<IAdaptiveTableCfg>\r\n  ): TAdaptiveTableWidthCandidate {\r\n    const { maxLineWidth, lineCount } = measureLineStats(prepared, width);\r\n    const { height } = layout(prepared, width, lineHeight);\r\n\r\n    return {\r\n      width: Math.ceil(maxLineWidth),\r\n      lineCount,\r\n      score: maxLineWidth + (height * cfg.heightWeight) + (lineCount * cfg.lineWeight),\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Определяет, лучше ли новый кандидат текущего лучшего варианта.\r\n   * @param candidate{TAdaptiveTableWidthCandidate} новый кандидат на оптимальную ширину\r\n   * @param bestScore{number} лучший найденный score\r\n   * @param bestLineCount{number} число строк у лучшего найденного кандидата\r\n   * @param bestWidth{number} ширина у лучшего найденного кандидата\r\n   * @returns {boolean} `true`, если нового кандидата нужно принять как лучшего\r\n   */\r\n  static #shouldUseCandidate(\r\n    candidate: TAdaptiveTableWidthCandidate,\r\n    bestScore: number,\r\n    bestLineCount: number,\r\n    bestWidth: number\r\n  ) {\r\n    return (\r\n      candidate.score < bestScore\r\n      || (candidate.score === bestScore && candidate.lineCount < bestLineCount)\r\n      || (\r\n        candidate.score === bestScore\r\n        && candidate.lineCount === bestLineCount\r\n        && candidate.width < bestWidth\r\n      )\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Возвращает CSS font shorthand в формате, пригодном для canvas/pretext измерений.\r\n   * @param styles{CSSStyleDeclaration} вычисленные CSS-стили ячейки\r\n   * @returns {string} строка шрифта для передачи в pretext\r\n   */\r\n  static #getCanvasFont(styles: CSSStyleDeclaration): string {\r\n    const font = styles.font.trim();\r\n\r\n    if (font) {\r\n      return font.replace(/\\/[^\\s]+/, \"\");\r\n    }\r\n\r\n    return [\r\n      styles.fontStyle,\r\n      styles.fontVariant,\r\n      styles.fontWeight,\r\n      styles.fontSize,\r\n      styles.fontFamily,\r\n    ]\r\n      .filter(Boolean)\r\n      .join(\" \");\r\n  }\r\n\r\n  /**\r\n   * Возвращает числовое значение `line-height` для расчёта высоты текста.\r\n   * @param styles{CSSStyleDeclaration} вычисленные CSS-стили ячейки\r\n   * @returns {number} высота строки в пикселях\r\n   */\r\n  static #getLineHeight(styles: CSSStyleDeclaration): number {\r\n    const lineHeight = Number.parseFloat(styles.lineHeight);\r\n\r\n    if (Number.isFinite(lineHeight)) {\r\n      return lineHeight;\r\n    }\r\n\r\n    return Math.ceil(Number.parseFloat(styles.fontSize) * 1.2);\r\n  }\r\n\r\n  /**\r\n   * Нормализует `letter-spacing` в числовое значение для pretext.\r\n   * @param styles{CSSStyleDeclaration} вычисленные CSS-стили ячейки\r\n   * @returns {number} межбуквенный интервал в пикселях\r\n   */\r\n  static #getLetterSpacing(styles: CSSStyleDeclaration): number {\r\n    const letterSpacing = Number.parseFloat(styles.letterSpacing);\r\n\r\n    return Number.isFinite(letterSpacing) ? letterSpacing : 0;\r\n  }\r\n\r\n  /**\r\n   * Определяет горизонтальные внутренние отступы ячейки.\r\n   * @param styles{CSSStyleDeclaration} вычисленные CSS-стили ячейки\r\n   * @param cfg{TStaticElementCfg<IAdaptiveTableCfg>} конфигурация\r\n   * @returns {number} суммарный горизонтальный отступ в пикселях\r\n   */\r\n  static #resolveHorizontalPadding(styles: CSSStyleDeclaration, cfg: TStaticElementCfg<IAdaptiveTableCfg>): number {\r\n    const paddingLeft = Number.parseFloat(styles.paddingLeft) || 0;\r\n    const paddingRight = Number.parseFloat(styles.paddingRight) || 0;\r\n\r\n    return Math.max(cfg.horizontalPadding, Math.ceil(paddingLeft + paddingRight));\r\n  }\r\n\r\n  /**\r\n   * Получает родительский адаптивный контейнер таблицы\r\n   * @param el{HTMLElement|ChildNode} элемент\r\n   * @returns {*}\r\n   */\r\n  static #getContainer(el: Element | null) {\r\n    return el?.closest(AdaptiveTable.selectors.instance) ?? null;\r\n  }\r\n\r\n  /**\r\n   * Устанавливает дополнительные классы, если скроллинг внутри таблицы достиг конца\r\n   * @param el{HTMLElement} элемент\r\n   */\r\n  static setEdges(el: HTMLElement) {\r\n    const container = AdaptiveTable.#getContainer(el);\r\n    if (!container) {\r\n      return;\r\n    }\r\n    const { scrollLeft, scrollWidth, offsetWidth } = el;\r\n    const maxScrollLeft = Math.max(0, scrollWidth - offsetWidth);\r\n    container.classList.toggle(AdaptiveTable.#classStates.leftEdge, scrollLeft <= AdaptiveTable.#scrollEdgeThreshold);\r\n    container.classList.toggle(\r\n      AdaptiveTable.#classStates.rightEdge, scrollLeft >= maxScrollLeft - AdaptiveTable.#scrollEdgeThreshold\r\n    );\r\n  }\r\n\r\n  static #onTableScroll(e: Event) {\r\n    const target = e.target;\r\n    if (target instanceof HTMLElement) {\r\n      AdaptiveTable.setEdges(target);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Устанавливает на элемент слушатель скроллинга\r\n   * @param el{HTMLElement|ChildNode} элемент\r\n   */\r\n  static #bindScrollEvent(el: HTMLElement) {\r\n    el.addEventListener(\"scroll\", AdaptiveTable.#onTableScroll);\r\n  }\r\n\r\n}\r\n"],"names":["AdaptiveTable","static","instance","customAdaptiveTable","isFormatText","minWidth","maxWidth","thresholdColsNumber","horizontalPadding","heightWeight","lineWeight","leftEdge","rightEdge","formatText","wrap","Map","constructor","init","bindEvents","this","Dispatcher","initiator","selector","selectors","context","getCollection","isAdaptive","table","closest","matches","getDocument","querySelectorAll","forEach","wrapped","getElWrapper","layouts","scrollLeft","bindScrollEvent","container","getContainer","HTMLElement","setEdges","cfg","getCfg","querySelector","optimiseTable","addFormatClass","classList","add","classStates","defaultCfg","rows","length","colsCount","cells","isMeasurementSupported","row","cell","style","measureCell","OffscreenCanvas","getContext","document","createElement","text","textContent","replace","trim","styles","window","getComputedStyle","font","getCanvasFont","lineHeight","getLineHeight","letterSpacing","getLetterSpacing","resolveHorizontalPadding","whiteSpace","includes","wordBreak","cacheKey","join","cachedWidth","measurementCache","get","undefined","prepared","prepareWithSegments","minContentWidth","Math","max","maxContentWidth","naturalWidth","ceil","measureNaturalWidth","set","optimalContentWidth","findOptimalWidth","min","measuredWidth","step","round","bestWidth","bestScore","Number","POSITIVE_INFINITY","bestLineCount","width","candidate","evaluateWidth","shouldUseCandidate","score","lineCount","maxLineWidth","measureLineStats","height","layout","fontStyle","fontVariant","fontWeight","fontSize","fontFamily","filter","Boolean","parseFloat","isFinite","paddingLeft","paddingRight","el","scrollWidth","offsetWidth","maxScrollLeft","toggle","scrollEdgeThreshold","onTableScroll","e","target","addEventListener"],"mappings":";;;;;;;;;;;;;;GA0CO,MAAMA,cAEXC,gBAAyC;;;;;AAMzCA,iBAAmB,CACjBC,SAAU,0BACVC,oBAAqB;;;;AAMvBF,kBAAuC;;AAErCG,aAAc;;AAEdC,SAAU;;AAEVC,SAAU;;AAEVC,oBAAqB;;AAErBC,kBAAmB;;AAEnBC,aAAc;;AAEdC,WAAY,GAGdT,mBAAsB,CACpBU,SAAU,aACVC,UAAW,cACXC,WAAY,8BAGdZ,eAAkB,CAChBa,KAAM,qGAGRb,wBAA2B,IAAIc,IAE/Bd,2BAA8B,EAE9B,WAAAe,GACE,GAAIhB,eAAcE,SAChB,OAAOF,eAAcE,SAEvBF,cAAciB,OACdjB,eAAckB,aACdlB,eAAcE,SAAYiB,IAC5B,CAEA,iBAAOD,GACLE,WAAWC,UAAY,CACrBC,SAAUtB,cAAcuB,UAAUrB,SAClCmB,UAAYG,SAAoCxB,cAAciB,KAAKO,SACnEC,cAAe,IAAM,GAEzB;;;;;KAOA,iBAAOC,CAAWC,OAChB,OAAQA,MAAMC,QAAQ5B,cAAcuB,UAAUrB,YACxCyB,MAAME,QAAQ7B,cAAcuB,UAAUpB,uBACtCwB,MAAMC,QAAQ5B,cAAcuB,UAAUpB,oBAC9C;;;;KAMA,WAAOc,CAAKO,QAAkCM,eAC5CN,QAAQO,iBAAmC,SAASC,QAASL,QAC3D,GAAI3B,cAAc0B,WAAWC,OAAQ,CACnC,MAAMM,QAAUC,aAAaP,MAAO3B,eAAcmC,QAASrB,MAC3DmB,QAAQG,WAAa,EACrBpC,eAAcqC,gBAAiBJ,SAC/B,MAAMK,UAAYtC,eAAcuC,aAAcN,SAC9C,GAAIK,qBAAqBE,YAAa,CACpCxC,cAAca,WAAWyB,WACzBtC,cAAcyC,SAASH,UACzB,CACF,GAEJ;;;;KAMA,iBAAOzB,CAAWyB,WAChB,MAAMI,IAAM1C,eAAc2C,OAAQL,WAClC,IAAKI,IAAItC,aACP,OAGF,MAAMuB,MAAQW,UAAUM,cAAgC,SAExD,IAAKjB,MACH,OAGF3B,eAAc6C,cAAeP,UAAWX,MAAOe,IACjD;;;;;KAOA,qBAAOI,CAAgBR,WACrBA,UAAUS,UAAUC,IAAIhD,eAAciD,YAAapC,WACrD;;;;;KAOA,aAAO8B,CAAQL,WACb,OAAOK,OAAOL,UAAWtC,cAAcuB,UAAUrB,SAAUF,cAAckD,WAC3E;;;;;;;;KAUA,oBAAOL,CAAeP,UAAwBX,MAAyBe,KACrE,MAAMS,KAAO,IAAKxB,MAAMwB,MAExB,IAAKA,KAAKC,OACR,OAGF,MAAMC,UAAYF,KAAK,GAAGG,MAAMF,OAEhC,GAAIC,UAAYX,IAAInC,sBAAwBP,eAAcuD,yBACxD,OAGFJ,KAAKnB,QAASwB,MACZ,IAAKA,IAAIF,OAAQtB,QAASyB,OACxBA,KAAKC,MAAMrD,SAAW,GAAGL,eAAc2D,YAAaF,KAAMf,aAI9D1C,eAAc8C,eAAgBR,UAChC;;;;KAMA,6BAAOiB,GACL,IACE,UAAWK,kBAAoB,YAC7B,QAAS,IAAIA,gBAAgB,EAAG,GAAGC,WAAW,MAGhD,UAAWC,WAAa,YACtB,OAAO,MAGT,QAASA,SAASC,cAAc,UAAUF,WAAW,KACvD,CAAE,MACA,OAAO,KACT,CACF;;;;;;KAQA,kBAAOF,CAAaF,KAA4Bf,KAC9C,MAAMsB,KAAOP,KAAKQ,aACdC,QAAQ,OAAQ,KACjBC,OAEH,IAAKH,KACH,OAAOtB,IAAIrC,SAGb,MAAM+D,OAASC,OAAOC,iBAAiBb,MACvC,MAAMc,KAAOvE,eAAcwE,cAAeJ,QAC1C,MAAMK,WAAazE,eAAc0E,cAAeN,QAChD,MAAMO,cAAgB3E,eAAc4E,iBAAkBR,QACtD,MAAM5D,kBAAoBR,eAAc6E,yBAA0BT,OAAQ1B,KAC1E,MAAMoC,WAAaV,OAAOU,WAAWC,SAAS,OAAS,WAAa,SACpE,MAAMC,UAAYZ,OAAOY,YAAc,WAAa,WAAa,SACjE,MAAMC,SAAW,CACfjB,KACAO,KACAE,WACAE,cACAnE,kBACAsE,WACAE,WACAE,KAAK,KACP,MAAMC,YAAcnF,eAAcoF,iBAAkBC,IAAIJ,UAExD,GAAIE,mBAAgBG,EAClB,OAAOH,YAGT,MAAMI,SAAWC,oBAAoBxB,KAAMO,KAAM,CAC/CO,sBACAE,uBACIL,gBAAkB,EAAI,CAAEA,6BAAkB,CAAA,IAEhD,MAAMc,gBAAkBC,KAAKC,IAAI,EAAGjD,IAAIrC,SAAWG,mBACnD,MAAMoF,gBAAkBF,KAAKC,IAAIF,gBAAiB/C,IAAIpC,SAAWE,mBACjE,MAAMqF,aAAeH,KAAKI,KAAKC,oBAAoBR,WAEnD,GAAIM,cAAgBJ,gBAAiB,CACnCzF,eAAcoF,iBAAkBY,IAAIf,SAAUvC,IAAIrC,UAClD,OAAOqC,IAAIrC,QACb,CAEA,MAAM4F,oBAAsBjG,eAAckG,iBAAkBX,SAAUE,gBAAiBC,KAAKS,IAAIP,gBAAiBC,cAAepB,WAAY/B,KAC5I,MAAM0D,cAAgBV,KAAKS,IAAIzD,IAAIpC,SAAUoF,KAAKC,IAAIjD,IAAIrC,SAAUqF,KAAKI,KAAKG,oBAAsBzF,qBAEpGR,eAAcoF,iBAAkBY,IAAIf,SAAUmB,eAE9C,OAAOA,aACT;;;;;;;;;KAWA,uBAAOF,CACLX,SACAlF,SACAC,SACAmE,WACA/B,KAEA,GAAIpC,UAAYD,SACd,OAAOA,SAGT,MAAMgG,KAAOX,KAAKC,IAAI,EAAGD,KAAKY,OAAOhG,SAAWD,UAAY,KAC5D,IAAIkG,UAAYjG,SAChB,IAAIkG,UAAYC,OAAOC,kBACvB,IAAIC,cAAgBF,OAAOC,kBAE3B,IAAK,IAAIE,MAAQvG,SAAUuG,OAAStG,SAAUsG,OAASP,KAAM,CAC3D,MAAMQ,UAAY7G,eAAc8G,cAAevB,SAAUqB,MAAOnC,WAAY/B,KAE5E,GAAI1C,eAAc+G,mBAAoBF,UAAWL,UAAWG,cAAeJ,WAAY,CACrFC,UAAYK,UAAUG,MACtBL,cAAgBE,UAAUI,UAC1BV,UAAYM,UAAUD,KACxB,CACF,CAEA,IAAKtG,SAAWD,UAAYgG,OAAS,EAAG,CACtC,MAAMQ,UAAY7G,eAAc8G,cAAevB,SAAUjF,SAAUmE,WAAY/B,KAE/E,GAAI1C,eAAc+G,mBAAoBF,UAAWL,UAAWG,cAAeJ,WACzE,OAAOM,UAAUD,KAErB,CAEA,OAAOL,SACT;;;;;;;;KAUA,oBAAOO,CACLvB,SACAqB,MACAnC,WACA/B,KAEA,MAAMwE,aAAEA,aAAYD,UAAEA,WAAcE,iBAAiB5B,SAAUqB,OAC/D,MAAMQ,OAAEA,QAAWC,OAAO9B,SAAUqB,MAAOnC,YAE3C,MAAO,CACLmC,MAAOlB,KAAKI,KAAKoB,cACjBD,oBACAD,MAAOE,aAAgBE,OAAS1E,IAAIjC,aAAiBwG,UAAYvE,IAAIhC,WAEzE;;;;;;;;KAUA,yBAAOqG,CACLF,UACAL,UACAG,cACAJ,WAEA,OACEM,UAAUG,MAAQR,WACdK,UAAUG,QAAUR,WAAaK,UAAUI,UAAYN,eAEzDE,UAAUG,QAAUR,WACjBK,UAAUI,YAAcN,eACxBE,UAAUD,MAAQL,SAG3B;;;;;KAOA,oBAAO/B,CAAeJ,QACpB,MAAMG,KAAOH,OAAOG,KAAKJ,OAEzB,GAAII,KACF,OAAOA,KAAKL,QAAQ,WAAY,IAGlC,MAAO,CACLE,OAAOkD,UACPlD,OAAOmD,YACPnD,OAAOoD,WACPpD,OAAOqD,SACPrD,OAAOsD,YAENC,OAAOC,SACP1C,KAAK,IACV;;;;;KAOA,oBAAOR,CAAeN,QACpB,MAAMK,WAAagC,OAAOoB,WAAWzD,OAAOK,YAE5C,GAAIgC,OAAOqB,SAASrD,YAClB,OAAOA,WAGT,OAAOiB,KAAKI,KAAKW,OAAOoB,WAAWzD,OAAOqD,UAAY,IACxD;;;;;KAOA,uBAAO7C,CAAkBR,QACvB,MAAMO,cAAgB8B,OAAOoB,WAAWzD,OAAOO,eAE/C,OAAO8B,OAAOqB,SAASnD,eAAiBA,cAAgB,CAC1D;;;;;;KAQA,+BAAOE,CAA0BT,OAA6B1B,KAC5D,MAAMqF,YAActB,OAAOoB,WAAWzD,OAAO2D,cAAgB,EAC7D,MAAMC,aAAevB,OAAOoB,WAAWzD,OAAO4D,eAAiB,EAE/D,OAAOtC,KAAKC,IAAIjD,IAAIlC,kBAAmBkF,KAAKI,KAAKiC,YAAcC,cACjE;;;;;KAOA,mBAAOzF,CAAc0F,IACnB,OAAOA,IAAIrG,QAAQ5B,cAAcuB,UAAUrB,WAAa,IAC1D;;;;KAMA,eAAOuC,CAASwF,IACd,MAAM3F,UAAYtC,eAAcuC,aAAc0F,IAC9C,IAAK3F,UACH,OAEF,MAAMF,WAAEA,WAAU8F,YAAEA,YAAWC,YAAEA,aAAgBF,GACjD,MAAMG,cAAgB1C,KAAKC,IAAI,EAAGuC,YAAcC,aAChD7F,UAAUS,UAAUsF,OAAOrI,eAAciD,YAAatC,SAAUyB,YAAcpC,eAAcsI,qBAC5FhG,UAAUS,UAAUsF,OAClBrI,eAAciD,YAAarC,UAAWwB,YAAcgG,cAAgBpI,eAAcsI,oBAEtF,CAEA,oBAAOC,CAAeC,GACpB,MAAMC,OAASD,EAAEC,OACjB,GAAIA,kBAAkBjG,YACpBxC,cAAcyC,SAASgG,OAE3B;;;;KAMA,sBAAOpG,CAAiB4F,IACtBA,GAAGS,iBAAiB,SAAU1I,eAAcuI,cAC9C"}