@rotki/ui-library 3.0.0-beta.1 → 3.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js +3 -3
  2. package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
  3. package/dist/components/accordions/accordions/RuiAccordions.vue_vue_type_script_setup_true_lang.js +1 -1
  4. package/dist/components/avatars/RuiAvatar.vue_vue_type_script_setup_true_lang.js +1 -1
  5. package/dist/components/avatars/RuiAvatarGroup.vue_vue_type_script_setup_true_lang.js +1 -1
  6. package/dist/components/buttons/button/RuiButton.js.map +1 -1
  7. package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js +10 -10
  8. package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  9. package/dist/components/buttons/button/button-styles.js +10 -2
  10. package/dist/components/buttons/button/button-styles.js.map +1 -1
  11. package/dist/components/buttons/button-group/RuiButtonGroup.vue_vue_type_script_setup_true_lang.js +1 -1
  12. package/dist/components/calendar/RuiCalendar.vue_vue_type_script_setup_true_lang.js +1 -1
  13. package/dist/components/calendar/RuiCalendarGrid.vue_vue_type_script_setup_true_lang.js +1 -1
  14. package/dist/components/calendar/RuiCalendarHeader.vue_vue_type_script_setup_true_lang.js +1 -1
  15. package/dist/components/calendar/RuiCalendarMenu.vue_vue_type_script_setup_true_lang.js +1 -1
  16. package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js +1 -1
  17. package/dist/components/color-picker/RuiColorBoard.vue_vue_type_script_setup_true_lang.js +1 -1
  18. package/dist/components/color-picker/RuiColorDisplay.vue_vue_type_script_setup_true_lang.js +1 -1
  19. package/dist/components/color-picker/RuiColorHue.vue_vue_type_script_setup_true_lang.js +1 -1
  20. package/dist/components/color-picker/RuiColorInput.vue_vue_type_script_setup_true_lang.js +9 -10
  21. package/dist/components/color-picker/RuiColorInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  22. package/dist/components/color-picker/RuiColorPicker.vue_vue_type_script_setup_true_lang.js +3 -4
  23. package/dist/components/color-picker/RuiColorPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  24. package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js +33 -33
  25. package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  26. package/dist/components/date-time-picker/use-date-bounds.js +1 -1
  27. package/dist/components/date-time-picker/use-date-time-selection.js +65 -66
  28. package/dist/components/date-time-picker/use-date-time-selection.js.map +1 -1
  29. package/dist/components/date-time-picker/use-input-handler.js +1 -1
  30. package/dist/components/date-time-picker/use-keyboard-handler.js +29 -30
  31. package/dist/components/date-time-picker/use-keyboard-handler.js.map +1 -1
  32. package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js +24 -24
  33. package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  34. package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js +49 -49
  35. package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  36. package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js +1 -1
  37. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js +1 -1
  38. package/dist/components/forms/file-upload/RuiFileUpload.js.map +1 -1
  39. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js +19 -17
  40. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js.map +1 -1
  41. package/dist/components/forms/radio-button/radio/RuiRadio.vue_vue_type_script_setup_true_lang.js +1 -1
  42. package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js +11 -11
  43. package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  44. package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js +17 -17
  45. package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  46. package/dist/components/forms/switch/RuiSwitch.vue_vue_type_script_setup_true_lang.js +1 -1
  47. package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js +21 -21
  48. package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  49. package/dist/components/forms/text-field/RuiTextField.js.map +1 -1
  50. package/dist/components/forms/text-field/RuiTextField.vue.d.ts +2 -0
  51. package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js +24 -20
  52. package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  53. package/dist/components/helpers/RuiFormTextDetail.js.map +1 -1
  54. package/dist/components/helpers/RuiFormTextDetail.vue.d.ts +11 -1
  55. package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js +3 -3
  56. package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js.map +1 -1
  57. package/dist/components/icons/RuiIcon.vue_vue_type_script_setup_true_lang.js +1 -1
  58. package/dist/components/logos/RuiLogo.vue_vue_type_script_setup_true_lang.js +1 -1
  59. package/dist/components/overlays/badge/RuiBadge.vue_vue_type_script_setup_true_lang.js +1 -1
  60. package/dist/components/overlays/dialog/RuiDialog.vue_vue_type_script_setup_true_lang.js +1 -1
  61. package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js +17 -17
  62. package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  63. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.js.map +1 -1
  64. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js +9 -9
  65. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js.map +1 -1
  66. package/dist/components/overlays/notification/RuiNotification.vue_vue_type_script_setup_true_lang.js +3 -4
  67. package/dist/components/overlays/notification/RuiNotification.vue_vue_type_script_setup_true_lang.js.map +1 -1
  68. package/dist/components/overlays/tooltip/RuiTooltip.vue_vue_type_script_setup_true_lang.js +1 -1
  69. package/dist/components/progress/RuiProgress.vue_vue_type_script_setup_true_lang.js +1 -1
  70. package/dist/components/steppers/RuiFooterStepper.vue_vue_type_script_setup_true_lang.js +1 -1
  71. package/dist/components/steppers/RuiStepper.js.map +1 -1
  72. package/dist/components/steppers/RuiStepper.vue_vue_type_script_setup_true_lang.js +13 -8
  73. package/dist/components/steppers/RuiStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  74. package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js +27 -27
  75. package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  76. package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js +1 -1
  77. package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js +1 -1
  78. package/dist/components/tables/data-table/RuiDataTableCell.vue_vue_type_script_setup_true_lang.js +1 -1
  79. package/dist/components/tables/data-table/RuiDataTableGroupRow.vue_vue_type_script_setup_true_lang.js +1 -1
  80. package/dist/components/tables/data-table/RuiDataTableMobileSort.vue_vue_type_script_setup_true_lang.js +1 -1
  81. package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js +23 -23
  82. package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  83. package/dist/components/tables/use-pagination-navigation.js +1 -1
  84. package/dist/components/tabs/tab/RuiTab.vue_vue_type_script_setup_true_lang.js +1 -1
  85. package/dist/components/tabs/tab/use-tab-link.js +1 -1
  86. package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js +6 -6
  87. package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js.map +1 -1
  88. package/dist/components/tabs/tabs/RuiTabs.vue_vue_type_script_setup_true_lang.js +11 -12
  89. package/dist/components/tabs/tabs/RuiTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  90. package/dist/components/tabs/tabs/use-tab-indicator.js +7 -7
  91. package/dist/components/tabs/tabs/use-tab-indicator.js.map +1 -1
  92. package/dist/components/tabs/tabs/use-tab-keyboard.js +1 -1
  93. package/dist/components/tabs/tabs/use-tab-scroll.js +15 -15
  94. package/dist/components/tabs/tabs/use-tab-scroll.js.map +1 -1
  95. package/dist/components/time-picker/RuiTimePicker.vue_vue_type_script_setup_true_lang.js +60 -61
  96. package/dist/components/time-picker/RuiTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  97. package/dist/composables/breakpoint.js +3 -3
  98. package/dist/composables/breakpoint.js.map +1 -1
  99. package/dist/composables/dropdown-menu.d.ts +9 -9
  100. package/dist/composables/dropdown-menu.js +32 -32
  101. package/dist/composables/dropdown-menu.js.map +1 -1
  102. package/dist/composables/floating.d.ts +1 -1
  103. package/dist/composables/floating.js +11 -11
  104. package/dist/composables/floating.js.map +1 -1
  105. package/dist/composables/forms/auto-complete/focus.js +16 -17
  106. package/dist/composables/forms/auto-complete/focus.js.map +1 -1
  107. package/dist/composables/forms/auto-complete/keyboard-navigation.js +1 -1
  108. package/dist/composables/forms/auto-complete/search.js +6 -7
  109. package/dist/composables/forms/auto-complete/search.js.map +1 -1
  110. package/dist/composables/forms/auto-complete/selection.js +1 -1
  111. package/dist/composables/forms/auto-complete/value.js +1 -1
  112. package/dist/composables/forms/category-picker/use-category-picker.js +1 -1
  113. package/dist/composables/forms/use-prepend-append-width.js +6 -6
  114. package/dist/composables/forms/use-prepend-append-width.js.map +1 -1
  115. package/dist/composables/keyboard-scroll.js +5 -5
  116. package/dist/composables/keyboard-scroll.js.map +1 -1
  117. package/dist/composables/overlay-stack.js +1 -1
  118. package/dist/composables/sticky-header.js +8 -8
  119. package/dist/composables/sticky-header.js.map +1 -1
  120. package/dist/composables/tables/data-table/columns.js +1 -1
  121. package/dist/composables/tables/data-table/expansion.js +1 -1
  122. package/dist/composables/tables/data-table/grouping.js +27 -28
  123. package/dist/composables/tables/data-table/grouping.js.map +1 -1
  124. package/dist/composables/tables/data-table/page-scroll.d.ts +7 -5
  125. package/dist/composables/tables/data-table/page-scroll.js +48 -17
  126. package/dist/composables/tables/data-table/page-scroll.js.map +1 -1
  127. package/dist/composables/tables/data-table/pagination.js +1 -1
  128. package/dist/composables/tables/data-table/selection.js +37 -38
  129. package/dist/composables/tables/data-table/selection.js.map +1 -1
  130. package/dist/composables/tables/data-table/sort.js +1 -1
  131. package/dist/composables/theme.js +12 -12
  132. package/dist/composables/theme.js.map +1 -1
  133. package/dist/composables/timeout-manager.js +1 -1
  134. package/dist/index.d.ts +2 -2
  135. package/dist/index.js +2 -2
  136. package/dist/index.js.map +1 -1
  137. package/dist/style.css +2 -18
  138. package/dist/types/dom.d.ts +9 -0
  139. package/dist/types/theme.d.ts +2 -3
  140. package/dist/types/theme.js.map +1 -1
  141. package/dist/utils/form-text-detail.js +1 -1
  142. package/dist/utils/helpers.js +1 -1
  143. package/dist/vendor/@vueuse/core/dist/index.js +1577 -0
  144. package/dist/vendor/@vueuse/core/dist/index.js.map +1 -0
  145. package/dist/vendor/@vueuse/shared/dist/index.js +563 -0
  146. package/dist/vendor/@vueuse/shared/dist/index.js.map +1 -0
  147. package/dist/vite-plugin/index.js +5 -6
  148. package/dist/vite-plugin/index.js.map +1 -1
  149. package/dist/web-types.json +9 -2
  150. package/package.json +5 -4
@@ -1 +1 @@
1
- {"version":3,"file":"sticky-header.js","names":[],"sources":["../../src/composables/sticky-header.ts"],"sourcesContent":["import type { MaybeRefOrGetter, Ref, ShallowRef } from 'vue';\n\nexport interface UseStickyTableHeaderRefs {\n table: Readonly<ShallowRef<HTMLTableElement | null>>;\n}\n\ninterface StickyElements {\n head: HTMLElement;\n theadClone: HTMLElement;\n root: HTMLTableElement;\n}\n\ninterface UseStickyTableHeaderReturn {\n stick: Readonly<Ref<boolean>>;\n}\n\nconst SELECTORS = {\n head: ':scope > thead[data-id=head-main]',\n headClone: ':scope > thead[data-id=head-clone]',\n row: ':scope > tbody > tr:not([hidden])',\n th: ':scope > th',\n} as const;\n\nconst BORDER_PRECISION = -0.5;\n\nfunction queryHeadRow(root: HTMLTableElement, selector: string): HTMLTableRowElement | null {\n return root.querySelector(`${selector} > tr`);\n}\n\nfunction queryColumns(row: HTMLTableRowElement | null): HTMLElement[] {\n if (!row)\n return [];\n return Array.from(row.querySelectorAll<HTMLElement>(SELECTORS.th));\n}\n\nfunction readColumnWidths(columns: HTMLElement[]): number[] {\n return columns.map(col => col.getBoundingClientRect().width);\n}\n\nfunction applyColumnWidths(columns: HTMLElement[], widths: number[]): void {\n for (const [i, column] of columns.entries()) {\n const width = widths[i];\n if (width !== undefined)\n column.style.width = `${width}px`;\n }\n}\n\nfunction positionHeadAtRest(head: HTMLElement): void {\n head.style.left = `${BORDER_PRECISION}px`;\n head.style.top = '0';\n}\n\ninterface StuckPosition {\n clonedRect: DOMRect;\n tableRect: DOMRect;\n lastRowHeight: number;\n top: number;\n origin: Point;\n}\n\nfunction positionHeadStuck(head: HTMLElement, { clonedRect, lastRowHeight, origin, tableRect, top }: StuckPosition): void {\n head.style.left = `${clonedRect.left - origin.left + BORDER_PRECISION}px`;\n\n const isNearBottom = tableRect.bottom <= lastRowHeight + clonedRect.height + top;\n const viewportTop = isNearBottom ? tableRect.bottom - lastRowHeight - clonedRect.height : top;\n head.style.top = `${viewportTop - origin.top}px`;\n}\n\nfunction isInStickyRange(tableRect: DOMRect, top: number): boolean {\n return tableRect.top <= top && tableRect.bottom > top;\n}\n\ninterface Point {\n left: number;\n top: number;\n}\n\n/**\n * The nearest ancestor that currently scrolls vertically, e.g. a dialog or drawer body, or\n * `undefined` when only the page does. One that could scroll but has nothing to (a card body on a\n * page) is skipped, as is the table's own scroller, which only scrolls sideways.\n */\nfunction findScrollParent(element: HTMLElement): HTMLElement | undefined {\n let parent = element.parentElement;\n while (parent && parent !== document.body && parent !== document.documentElement) {\n const { overflowY } = getComputedStyle(parent);\n if ((overflowY === 'auto' || overflowY === 'scroll') && parent.scrollHeight > parent.clientHeight)\n return parent;\n parent = parent.parentElement;\n }\n return undefined;\n}\n\nfunction isSet(value: string | undefined): boolean {\n return value !== undefined && value !== '' && value !== 'none';\n}\n\n/**\n * Whether an element becomes the containing block of its `position: fixed`\n * descendants. The individual `translate`, `rotate` and `scale` properties\n * count like `transform`: Tailwind 4 writes its translate utilities to\n * `translate`, so a dialog centred with `-translate-x-1/2` leaves `transform`\n * at `none`.\n */\nexport function createsFixedContainingBlock(style: CSSStyleDeclaration): boolean {\n return isSet(style.transform)\n || isSet(style.translate)\n || isSet(style.rotate)\n || isSet(style.scale)\n || isSet(style.perspective)\n || isSet(style.filter)\n || isSet(style.backdropFilter)\n || /transform|translate|rotate|scale|perspective|filter/.test(style.willChange)\n || /paint|layout|strict|content/.test(style.contain);\n}\n\n/**\n * Where a `position: fixed` descendant's `top: 0; left: 0` lands in the viewport. That is the\n * viewport origin, unless an ancestor (a centred dialog is translated) becomes its containing block.\n */\nfunction getFixedOrigin(element: HTMLElement): Point {\n let parent = element.parentElement;\n while (parent) {\n if (createsFixedContainingBlock(getComputedStyle(parent))) {\n const rect = parent.getBoundingClientRect();\n return { left: rect.left + parent.clientLeft, top: rect.top + parent.clientTop };\n }\n parent = parent.parentElement;\n }\n return { left: 0, top: 0 };\n}\n\nfunction getLastRowHeight(root: HTMLTableElement): number | undefined {\n const rows = root.querySelectorAll(SELECTORS.row);\n if (rows.length <= 1)\n return undefined;\n return rows.item(rows.length - 1)?.getBoundingClientRect().height ?? 0;\n}\n\n/**\n * Setup sticky table header\n */\nexport function useStickyTableHeader(\n sticky: MaybeRefOrGetter<boolean> = shallowRef(false),\n offsetTop: MaybeRefOrGetter<number | undefined>,\n tableRefs: UseStickyTableHeaderRefs,\n): UseStickyTableHeaderReturn {\n const { table } = tableRefs;\n const stick = shallowRef<boolean>(false);\n\n let resizeCleanups: (() => void)[] = [];\n let syncRafId: number | null = null;\n let rafId: number | null = null;\n\n function cleanupResizeObservers(): void {\n for (const cleanup of resizeCleanups)\n cleanup();\n resizeCleanups = [];\n }\n\n function cancelPendingSync(): void {\n if (syncRafId !== null)\n cancelAnimationFrame(syncRafId);\n syncRafId = null;\n }\n\n function scheduleSyncWidths(cloneColumns: HTMLElement[], mainColumns: HTMLElement[]): void {\n cancelPendingSync();\n\n // One frame is enough: the main thead is positioned, so its widths never feed back into the clone's\n syncRafId = requestAnimationFrame(() => {\n syncRafId = null;\n applyColumnWidths(mainColumns, readColumnWidths(cloneColumns));\n // the head's own width too: left stale, it squeezes the columns and leaves an untinted strip at the end\n toggleStickyClass();\n });\n }\n\n function observeColumnResizes(cloneColumns: HTMLElement[], mainColumns: HTMLElement[]): void {\n cleanupResizeObservers();\n\n for (const th of cloneColumns) {\n const { stop } = useResizeObserver(th, () => {\n scheduleSyncWidths(cloneColumns, mainColumns);\n });\n resizeCleanups.push(stop);\n }\n }\n\n function watchCellWidth(): void {\n const root = get(table);\n if (!toValue(sticky) || !root)\n return;\n\n const cloneRow = queryHeadRow(root, SELECTORS.headClone);\n const mainRow = queryHeadRow(root, SELECTORS.head);\n const cloneColumns = queryColumns(cloneRow);\n const mainColumns = queryColumns(mainRow);\n\n useMutationObserver(cloneRow, (mutations) => {\n const hasRelevantMutation = mutations.some(\n m => m.type === 'childList' || m.type === 'attributes',\n );\n if (hasRelevantMutation)\n observeColumnResizes(queryColumns(cloneRow), queryColumns(mainRow));\n }, { attributes: true, childList: true, subtree: true });\n\n observeColumnResizes(cloneColumns, mainColumns);\n }\n\n function queryStickyElements(): StickyElements | undefined {\n const root = get(table);\n if (!toValue(sticky) || !root)\n return undefined;\n\n const theadClone = root.querySelector<HTMLElement>(SELECTORS.headClone);\n const head = root.querySelector<HTMLElement>(SELECTORS.head);\n if (!theadClone || !head)\n return undefined;\n\n return { head, root, theadClone };\n }\n\n function toggleStickyClass(): void {\n const elements = queryStickyElements();\n if (!elements)\n return;\n\n const { head, root, theadClone } = elements;\n const clonedRect = theadClone.getBoundingClientRect();\n const tableRect = root.getBoundingClientRect();\n const pageTop = toValue(offsetTop) ?? 0;\n const scrollParent = findScrollParent(root);\n const top = scrollParent\n ? Math.max(scrollParent.getBoundingClientRect().top + scrollParent.clientTop, pageTop)\n : pageTop;\n\n head.style.width = `${clonedRect.width}px`;\n\n const lastRowHeight = getLastRowHeight(root);\n if (lastRowHeight === undefined) {\n set(stick, false);\n positionHeadAtRest(head);\n return;\n }\n\n if (isInStickyRange(tableRect, top)) {\n set(stick, true);\n positionHeadStuck(head, { clonedRect, lastRowHeight, origin: getFixedOrigin(head), tableRect, top });\n }\n else {\n set(stick, false);\n positionHeadAtRest(head);\n }\n }\n\n function throttledToggleStickyClass(): void {\n if (rafId !== null)\n return;\n rafId = requestAnimationFrame(() => {\n toggleStickyClass();\n rafId = null;\n });\n }\n\n function onScroll(event: Event): void {\n const root = get(table);\n const target = event.target;\n // scroll does not bubble, so this runs in capture for every scroll: only an ancestor's matters\n if (!root || !(target instanceof Node) || !target.contains(root))\n return;\n throttledToggleStickyClass();\n }\n\n onMounted(() => {\n toggleStickyClass();\n useEventListener(document, 'scroll', onScroll, { capture: true, passive: true });\n useEventListener(window, 'resize', throttledToggleStickyClass);\n watchCellWidth();\n });\n\n return {\n stick: readonly(stick),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sticky-header.js","names":[],"sources":["../../src/composables/sticky-header.ts"],"sourcesContent":["import type { MaybeRefOrGetter, Ref, ShallowRef } from 'vue';\n\nexport interface UseStickyTableHeaderRefs {\n table: Readonly<ShallowRef<HTMLTableElement | null>>;\n}\n\ninterface StickyElements {\n head: HTMLElement;\n theadClone: HTMLElement;\n root: HTMLTableElement;\n}\n\ninterface UseStickyTableHeaderReturn {\n stick: Readonly<Ref<boolean>>;\n}\n\nconst SELECTORS = {\n head: ':scope > thead[data-id=head-main]',\n headClone: ':scope > thead[data-id=head-clone]',\n row: ':scope > tbody > tr:not([hidden])',\n th: ':scope > th',\n} as const;\n\nconst BORDER_PRECISION = -0.5;\n\nfunction queryHeadRow(root: HTMLTableElement, selector: string): HTMLTableRowElement | null {\n return root.querySelector(`${selector} > tr`);\n}\n\nfunction queryColumns(row: HTMLTableRowElement | null): HTMLElement[] {\n if (!row)\n return [];\n return Array.from(row.querySelectorAll<HTMLElement>(SELECTORS.th));\n}\n\nfunction readColumnWidths(columns: HTMLElement[]): number[] {\n return columns.map(col => col.getBoundingClientRect().width);\n}\n\nfunction applyColumnWidths(columns: HTMLElement[], widths: number[]): void {\n for (const [i, column] of columns.entries()) {\n const width = widths[i];\n if (width !== undefined)\n column.style.width = `${width}px`;\n }\n}\n\nfunction positionHeadAtRest(head: HTMLElement): void {\n head.style.left = `${BORDER_PRECISION}px`;\n head.style.top = '0';\n}\n\ninterface StuckPosition {\n clonedRect: DOMRect;\n tableRect: DOMRect;\n lastRowHeight: number;\n top: number;\n origin: Point;\n}\n\nfunction positionHeadStuck(head: HTMLElement, { clonedRect, lastRowHeight, origin, tableRect, top }: StuckPosition): void {\n head.style.left = `${clonedRect.left - origin.left + BORDER_PRECISION}px`;\n\n const isNearBottom = tableRect.bottom <= lastRowHeight + clonedRect.height + top;\n const viewportTop = isNearBottom ? tableRect.bottom - lastRowHeight - clonedRect.height : top;\n head.style.top = `${viewportTop - origin.top}px`;\n}\n\nfunction isInStickyRange(tableRect: DOMRect, top: number): boolean {\n return tableRect.top <= top && tableRect.bottom > top;\n}\n\ninterface Point {\n left: number;\n top: number;\n}\n\n/**\n * The nearest ancestor that currently scrolls vertically, e.g. a dialog or drawer body, or\n * `undefined` when only the page does. One that could scroll but has nothing to (a card body on a\n * page) is skipped, as is the table's own scroller, which only scrolls sideways.\n */\nfunction findScrollParent(element: HTMLElement): HTMLElement | undefined {\n let parent = element.parentElement;\n while (parent && parent !== document.body && parent !== document.documentElement) {\n const { overflowY } = getComputedStyle(parent);\n if ((overflowY === 'auto' || overflowY === 'scroll') && parent.scrollHeight > parent.clientHeight)\n return parent;\n parent = parent.parentElement;\n }\n return undefined;\n}\n\nfunction isSet(value: string | undefined): boolean {\n return value !== undefined && value !== '' && value !== 'none';\n}\n\n/**\n * Whether an element becomes the containing block of its `position: fixed`\n * descendants. The individual `translate`, `rotate` and `scale` properties\n * count like `transform`: Tailwind 4 writes its translate utilities to\n * `translate`, so a dialog centred with `-translate-x-1/2` leaves `transform`\n * at `none`.\n */\nexport function createsFixedContainingBlock(style: CSSStyleDeclaration): boolean {\n return isSet(style.transform)\n || isSet(style.translate)\n || isSet(style.rotate)\n || isSet(style.scale)\n || isSet(style.perspective)\n || isSet(style.filter)\n || isSet(style.backdropFilter)\n || /transform|translate|rotate|scale|perspective|filter/.test(style.willChange)\n || /paint|layout|strict|content/.test(style.contain);\n}\n\n/**\n * Where a `position: fixed` descendant's `top: 0; left: 0` lands in the viewport. That is the\n * viewport origin, unless an ancestor (a centred dialog is translated) becomes its containing block.\n */\nfunction getFixedOrigin(element: HTMLElement): Point {\n let parent = element.parentElement;\n while (parent) {\n if (createsFixedContainingBlock(getComputedStyle(parent))) {\n const rect = parent.getBoundingClientRect();\n return { left: rect.left + parent.clientLeft, top: rect.top + parent.clientTop };\n }\n parent = parent.parentElement;\n }\n return { left: 0, top: 0 };\n}\n\nfunction getLastRowHeight(root: HTMLTableElement): number | undefined {\n const rows = root.querySelectorAll(SELECTORS.row);\n if (rows.length <= 1)\n return undefined;\n return rows.item(rows.length - 1)?.getBoundingClientRect().height ?? 0;\n}\n\n/**\n * Setup sticky table header\n */\nexport function useStickyTableHeader(\n sticky: MaybeRefOrGetter<boolean> = shallowRef(false),\n offsetTop: MaybeRefOrGetter<number | undefined>,\n tableRefs: UseStickyTableHeaderRefs,\n): UseStickyTableHeaderReturn {\n const { table } = tableRefs;\n const stick = shallowRef<boolean>(false);\n\n let resizeCleanups: (() => void)[] = [];\n let syncRafId: number | null = null;\n let rafId: number | null = null;\n\n function cleanupResizeObservers(): void {\n for (const cleanup of resizeCleanups)\n cleanup();\n resizeCleanups = [];\n }\n\n function cancelPendingSync(): void {\n if (syncRafId !== null)\n cancelAnimationFrame(syncRafId);\n syncRafId = null;\n }\n\n function scheduleSyncWidths(cloneColumns: HTMLElement[], mainColumns: HTMLElement[]): void {\n cancelPendingSync();\n\n // One frame is enough: the main thead is positioned, so its widths never feed back into the clone's\n syncRafId = requestAnimationFrame(() => {\n syncRafId = null;\n applyColumnWidths(mainColumns, readColumnWidths(cloneColumns));\n // the head's own width too: left stale, it squeezes the columns and leaves an untinted strip at the end\n toggleStickyClass();\n });\n }\n\n function observeColumnResizes(cloneColumns: HTMLElement[], mainColumns: HTMLElement[]): void {\n cleanupResizeObservers();\n\n for (const th of cloneColumns) {\n const { stop } = useResizeObserver(th, () => {\n scheduleSyncWidths(cloneColumns, mainColumns);\n });\n resizeCleanups.push(stop);\n }\n }\n\n function watchCellWidth(): void {\n const root = get(table);\n if (!toValue(sticky) || !root)\n return;\n\n const cloneRow = queryHeadRow(root, SELECTORS.headClone);\n const mainRow = queryHeadRow(root, SELECTORS.head);\n const cloneColumns = queryColumns(cloneRow);\n const mainColumns = queryColumns(mainRow);\n\n useMutationObserver(cloneRow, (mutations) => {\n const hasRelevantMutation = mutations.some(\n m => m.type === 'childList' || m.type === 'attributes',\n );\n if (hasRelevantMutation)\n observeColumnResizes(queryColumns(cloneRow), queryColumns(mainRow));\n }, { attributes: true, childList: true, subtree: true });\n\n observeColumnResizes(cloneColumns, mainColumns);\n }\n\n function queryStickyElements(): StickyElements | undefined {\n const root = get(table);\n if (!toValue(sticky) || !root)\n return undefined;\n\n const theadClone = root.querySelector<HTMLElement>(SELECTORS.headClone);\n const head = root.querySelector<HTMLElement>(SELECTORS.head);\n if (!theadClone || !head)\n return undefined;\n\n return { head, root, theadClone };\n }\n\n function toggleStickyClass(): void {\n const elements = queryStickyElements();\n if (!elements)\n return;\n\n const { head, root, theadClone } = elements;\n const clonedRect = theadClone.getBoundingClientRect();\n const tableRect = root.getBoundingClientRect();\n const pageTop = toValue(offsetTop) ?? 0;\n const scrollParent = findScrollParent(root);\n const top = scrollParent\n ? Math.max(scrollParent.getBoundingClientRect().top + scrollParent.clientTop, pageTop)\n : pageTop;\n\n head.style.width = `${clonedRect.width}px`;\n\n const lastRowHeight = getLastRowHeight(root);\n if (lastRowHeight === undefined) {\n set(stick, false);\n positionHeadAtRest(head);\n return;\n }\n\n if (isInStickyRange(tableRect, top)) {\n set(stick, true);\n positionHeadStuck(head, { clonedRect, lastRowHeight, origin: getFixedOrigin(head), tableRect, top });\n }\n else {\n set(stick, false);\n positionHeadAtRest(head);\n }\n }\n\n function throttledToggleStickyClass(): void {\n if (rafId !== null)\n return;\n rafId = requestAnimationFrame(() => {\n toggleStickyClass();\n rafId = null;\n });\n }\n\n function onScroll(event: Event): void {\n const root = get(table);\n const target = event.target;\n // scroll does not bubble, so this runs in capture for every scroll: only an ancestor's matters\n if (!root || !(target instanceof Node) || !target.contains(root))\n return;\n throttledToggleStickyClass();\n }\n\n onMounted(() => {\n toggleStickyClass();\n useEventListener(document, 'scroll', onScroll, { capture: true, passive: true });\n useEventListener(window, 'resize', throttledToggleStickyClass);\n watchCellWidth();\n });\n\n return {\n stick: readonly(stick),\n };\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
+ import { get } from "../../../vendor/@vueuse/shared/dist/index.js";
1
2
  import { TableAlign, getAlignClass } from "../../../components/tables/table-props.js";
2
3
  import { getObjectKeys, isHeaderSlot } from "./types.js";
3
4
  import { computed, toValue } from "vue";
4
- import { get } from "@vueuse/shared";
5
5
  //#region src/composables/tables/data-table/columns.ts
6
6
  function useTableColumns(options) {
7
7
  const { cols, columnAttr, expandable, groupKeys, isMobile, rows, selectedData, slots, tdResolver } = options;
@@ -1,5 +1,5 @@
1
+ import { get, set } from "../../../vendor/@vueuse/shared/dist/index.js";
1
2
  import { computed } from "vue";
2
- import { get, set } from "@vueuse/shared";
3
3
  //#region src/composables/tables/data-table/expansion.ts
4
4
  function useTableExpansion(options, deps) {
5
5
  const { rowAttr, singleExpand } = options;
@@ -1,57 +1,56 @@
1
1
  import { assert } from "../../../utils/assert.js";
2
+ import { get, isDefined, set } from "../../../vendor/@vueuse/shared/dist/index.js";
2
3
  import { GROUP_HEADER_BRAND, isRow } from "./types.js";
3
4
  import { computed, ref, watch } from "vue";
4
- import { isDefined } from "@vueuse/core";
5
- import { get as get$1, set as set$1 } from "@vueuse/shared";
6
5
  //#region src/composables/tables/data-table/grouping.ts
7
6
  var GROUP_KEY_SEPARATOR = "\0";
8
7
  function useTableGrouping(options, deps) {
9
8
  const { rowAttr } = options;
10
9
  const { group, collapsed, sorted } = deps;
11
10
  const collapsedRows = ref([]);
12
- watch(collapsed, (value) => set$1(collapsedRows, value ?? []), { immediate: true });
11
+ watch(collapsed, (value) => set(collapsedRows, value ?? []), { immediate: true });
13
12
  const groupKeys = computed(() => {
14
- const groupBy = get$1(group);
13
+ const groupBy = get(group);
15
14
  if (!groupBy) return [];
16
15
  if (!Array.isArray(groupBy)) return [groupBy];
17
16
  return groupBy;
18
17
  });
19
18
  const groupKey = computed(() => {
20
- return get$1(groupKeys).join(":") || void 0;
19
+ return get(groupKeys).join(":") || void 0;
21
20
  });
22
- const isGrouped = computed(() => get$1(groupKey) !== void 0);
23
- const collapsedIdentifierSet = computed(() => new Set(get$1(collapsedRows).map((row) => row[rowAttr])));
21
+ const isGrouped = computed(() => get(groupKey) !== void 0);
22
+ const collapsedIdentifierSet = computed(() => new Set(get(collapsedRows).map((row) => row[rowAttr])));
24
23
  const collapsedGroupKeySet = computed(() => {
25
- const grouping = get$1(groupKeys);
24
+ const grouping = get(groupKeys);
26
25
  if (grouping.length === 0) return /* @__PURE__ */ new Set();
27
26
  const seen = /* @__PURE__ */ new Set();
28
- for (const row of get$1(collapsedRows)) seen.add(computeGroupKey(row, grouping));
27
+ for (const row of get(collapsedRows)) seen.add(computeGroupKey(row, grouping));
29
28
  return seen;
30
29
  });
31
30
  function getRowGroup(row) {
32
31
  const result = {};
33
- for (const key of get$1(groupKeys)) result[key] = row[key];
32
+ for (const key of get(groupKeys)) result[key] = row[key];
34
33
  return result;
35
34
  }
36
35
  function compareGroupsFn(a, b) {
37
- const grouping = get$1(groupKeys);
36
+ const grouping = get(groupKeys);
38
37
  if (grouping.length === 0) return false;
39
38
  return grouping.every((key) => a[key] === b[key]);
40
39
  }
41
40
  function isExpandedGroup(value) {
42
- const grouping = get$1(groupKeys);
41
+ const grouping = get(groupKeys);
43
42
  let groupVal = "";
44
43
  for (const gk of grouping) {
45
44
  if (groupVal) groupVal += GROUP_KEY_SEPARATOR;
46
45
  const val = value[gk];
47
46
  groupVal += isDefined(val) ? val : "";
48
47
  }
49
- return !get$1(collapsedGroupKeySet).has(groupVal);
48
+ return !get(collapsedGroupKeySet).has(groupVal);
50
49
  }
51
50
  function isHiddenRow(row) {
52
- if (!get$1(isGrouped)) return false;
51
+ if (!get(isGrouped)) return false;
53
52
  if (!isRow(row)) return false;
54
- return get$1(collapsedIdentifierSet).has(row[rowAttr]);
53
+ return get(collapsedIdentifierSet).has(row[rowAttr]);
55
54
  }
56
55
  function computeGroupKey(row, grouping) {
57
56
  let key = "";
@@ -63,9 +62,9 @@ function useTableGrouping(options, deps) {
63
62
  return key;
64
63
  }
65
64
  const mappedGroups = computed(() => {
66
- const grouping = get$1(groupKeys);
65
+ const grouping = get(groupKeys);
67
66
  if (grouping.length === 0) return {};
68
- const result = get$1(sorted);
67
+ const result = get(sorted);
69
68
  const identifier = rowAttr;
70
69
  const acc = {};
71
70
  for (const row of result) {
@@ -81,31 +80,31 @@ function useTableGrouping(options, deps) {
81
80
  return acc;
82
81
  });
83
82
  const grouped = computed(() => {
84
- const result = get$1(sorted);
85
- if (!get$1(groupKey)) return result;
86
- const groups = get$1(mappedGroups);
83
+ const result = get(sorted);
84
+ if (!get(groupKey)) return result;
85
+ const groups = get(mappedGroups);
87
86
  const out = [];
88
87
  for (const items of Object.values(groups)) for (const item of items) out.push(item);
89
88
  return out;
90
89
  });
91
90
  function getGroupRows(groupVal) {
92
- if (!get$1(isGrouped)) return [];
93
- const groupRows = get$1(mappedGroups)[groupVal];
91
+ if (!get(isGrouped)) return [];
92
+ const groupRows = get(mappedGroups)[groupVal];
94
93
  assert(groupRows);
95
94
  return groupRows.filter(isRow);
96
95
  }
97
96
  function onToggleExpandGroup(groupPartial, value) {
98
97
  if (!value) return;
99
- const currentCollapsed = get$1(collapsedRows);
98
+ const currentCollapsed = get(collapsedRows);
100
99
  const groupExpanded = isExpandedGroup(groupPartial);
101
100
  const groupRows = getGroupRows(value);
102
- set$1(collapsedRows, groupExpanded ? [...currentCollapsed, ...groupRows] : currentCollapsed.filter((row) => !compareGroupsFn(row, groupPartial)));
103
- set$1(collapsed, get$1(collapsedRows));
101
+ set(collapsedRows, groupExpanded ? [...currentCollapsed, ...groupRows] : currentCollapsed.filter((row) => !compareGroupsFn(row, groupPartial)));
102
+ set(collapsed, get(collapsedRows));
104
103
  }
105
104
  function onUngroup() {
106
- set$1(collapsedRows, []);
107
- set$1(collapsed, []);
108
- set$1(group, Array.isArray(get$1(group)) ? [] : void 0);
105
+ set(collapsedRows, []);
106
+ set(collapsed, []);
107
+ set(group, Array.isArray(get(group)) ? [] : void 0);
109
108
  }
110
109
  return {
111
110
  groupKeys,
@@ -1 +1 @@
1
- {"version":3,"file":"grouping.js","names":[],"sources":["../../../../src/composables/tables/data-table/grouping.ts"],"sourcesContent":["import type { ComputedRef, Ref } from 'vue';\nimport type { TableRowKey, TableRowKeyData } from '@/components/tables/RuiTableHead.vue';\nimport {\n GROUP_HEADER_BRAND,\n type GroupedTableRow,\n type GroupHeader,\n isRow,\n} from '@/composables/tables/data-table/types';\nimport { assert } from '@/utils/assert';\n\nexport interface UseTableGroupingOptions<T extends object, IdType extends keyof T> {\n /** The property on each row used as the unique row identifier. */\n rowAttr: IdType;\n}\n\nexport interface UseTableGroupingDeps<T extends object> {\n group: Ref<TableRowKeyData<T>>;\n collapsed: Ref<T[] | undefined>;\n sorted: ComputedRef<readonly T[]>;\n}\n\nexport interface UseTableGroupingReturn<T extends object> {\n groupKeys: ComputedRef<TableRowKey<T>[]>;\n groupKey: ComputedRef<string | undefined>;\n isGrouped: ComputedRef<boolean>;\n mappedGroups: ComputedRef<Record<string, GroupedTableRow<T>[]>>;\n grouped: ComputedRef<readonly GroupedTableRow<T>[]>;\n getRowGroup: (row: T) => Partial<T>;\n getGroupRows: (groupVal: string) => T[];\n compareGroupsFn: (a: T, b: Partial<T>) => boolean;\n isExpandedGroup: (value: Partial<T>) => boolean;\n isHiddenRow: (row: GroupedTableRow<T>) => boolean;\n onToggleExpandGroup: (group: Partial<T>, value?: string) => void;\n onUngroup: () => void;\n}\n\n// Null character separator prevents false collisions when group values contain commas\nconst GROUP_KEY_SEPARATOR = '\\0';\n\nexport function useTableGrouping<T extends object, IdType extends keyof T>(\n options: UseTableGroupingOptions<T, IdType>,\n deps: UseTableGroupingDeps<T>,\n): UseTableGroupingReturn<T> {\n const { rowAttr } = options;\n const { group, collapsed, sorted } = deps;\n\n const collapsedRows: Ref<T[]> = ref([]);\n\n watch(collapsed, value => set(collapsedRows, value ?? []), { immediate: true });\n\n const groupKeys: ComputedRef<TableRowKey<T>[]> = computed(() => {\n const groupBy = get(group);\n\n if (!groupBy)\n return [];\n\n if (!Array.isArray(groupBy))\n return [groupBy];\n\n return groupBy;\n });\n\n const groupKey = computed<string | undefined>(() => {\n const key = get(groupKeys).join(':');\n return key || undefined;\n });\n\n const isGrouped = computed<boolean>(() => get(groupKey) !== undefined);\n\n const collapsedIdentifierSet = computed<Set<T[IdType]>>(\n () => new Set(get(collapsedRows).map(row => row[rowAttr])),\n );\n\n const collapsedGroupKeySet = computed<Set<string>>(() => {\n const grouping = get(groupKeys);\n if (grouping.length === 0)\n return new Set<string>();\n\n const seen = new Set<string>();\n for (const row of get(collapsedRows))\n seen.add(computeGroupKey(row, grouping));\n return seen;\n });\n\n function getRowGroup(row: T): Partial<T> {\n const result: Partial<T> = {};\n for (const key of get(groupKeys)) {\n result[key] = row[key];\n }\n return result;\n }\n\n function compareGroupsFn(a: T, b: Partial<T>): boolean {\n const grouping = get(groupKeys);\n if (grouping.length === 0)\n return false;\n\n return grouping.every(key => a[key] === b[key]);\n }\n\n function isExpandedGroup(value: Partial<T>): boolean {\n const grouping = get(groupKeys);\n let groupVal = '';\n for (const gk of grouping) {\n if (groupVal)\n groupVal += GROUP_KEY_SEPARATOR;\n const val = value[gk];\n groupVal += isDefined(val) ? val : '';\n }\n return !get(collapsedGroupKeySet).has(groupVal);\n }\n\n function isHiddenRow(row: GroupedTableRow<T>): boolean {\n if (!get(isGrouped))\n return false;\n if (!isRow(row))\n return false;\n return get(collapsedIdentifierSet).has(row[rowAttr]);\n }\n\n function computeGroupKey(row: T, grouping: TableRowKey<T>[]): string {\n let key = '';\n for (const gk of grouping) {\n if (key)\n key += GROUP_KEY_SEPARATOR;\n const val = row[gk];\n key += isDefined(val) ? val : '';\n }\n return key;\n }\n\n const mappedGroups = computed<Record<string, GroupedTableRow<T>[]>>(() => {\n const grouping = get(groupKeys);\n if (grouping.length === 0)\n return {};\n\n const result = get(sorted);\n const identifier = rowAttr;\n const acc: Record<string, GroupedTableRow<T>[]> = {};\n\n for (const row of result) {\n if (!isDefined(row[identifier]) || row[identifier] === '')\n continue;\n\n const groupVal = computeGroupKey(row, grouping);\n if (!acc[groupVal]) {\n acc[groupVal] = [\n {\n [GROUP_HEADER_BRAND]: true,\n group: getRowGroup(row),\n identifier: groupVal,\n } satisfies GroupHeader<T>,\n ];\n }\n\n acc[groupVal].push(row);\n }\n\n return acc;\n });\n\n const grouped = computed<readonly GroupedTableRow<T>[]>(() => {\n const result = get(sorted);\n const groupByKey = get(groupKey);\n\n if (!groupByKey)\n return result;\n\n const groups = get(mappedGroups);\n const out: GroupedTableRow<T>[] = [];\n for (const items of Object.values(groups)) {\n for (const item of items)\n out.push(item);\n }\n return out;\n });\n\n function getGroupRows(groupVal: string): T[] {\n if (!get(isGrouped))\n return [];\n\n const groupRows = get(mappedGroups)[groupVal];\n assert(groupRows);\n return groupRows.filter(isRow);\n }\n\n function onToggleExpandGroup(groupPartial: Partial<T>, value?: string): void {\n if (!value)\n return;\n\n const currentCollapsed = get(collapsedRows);\n\n const groupExpanded = isExpandedGroup(groupPartial);\n\n const groupRows = getGroupRows(value);\n\n set(\n collapsedRows,\n groupExpanded\n ? [...currentCollapsed, ...groupRows]\n : currentCollapsed.filter(row => !compareGroupsFn(row, groupPartial)),\n );\n\n set(collapsed, get(collapsedRows));\n }\n\n function onUngroup(): void {\n set(collapsedRows, []);\n\n set(collapsed, []);\n set(group, Array.isArray(get(group)) ? [] : undefined);\n }\n\n return {\n groupKeys,\n groupKey,\n isGrouped,\n mappedGroups,\n grouped,\n getRowGroup,\n getGroupRows,\n compareGroupsFn,\n isExpandedGroup,\n isHiddenRow,\n onToggleExpandGroup,\n onUngroup,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"grouping.js","names":[],"sources":["../../../../src/composables/tables/data-table/grouping.ts"],"sourcesContent":["import type { ComputedRef, Ref } from 'vue';\nimport type { TableRowKey, TableRowKeyData } from '@/components/tables/RuiTableHead.vue';\nimport {\n GROUP_HEADER_BRAND,\n type GroupedTableRow,\n type GroupHeader,\n isRow,\n} from '@/composables/tables/data-table/types';\nimport { assert } from '@/utils/assert';\n\nexport interface UseTableGroupingOptions<T extends object, IdType extends keyof T> {\n /** The property on each row used as the unique row identifier. */\n rowAttr: IdType;\n}\n\nexport interface UseTableGroupingDeps<T extends object> {\n group: Ref<TableRowKeyData<T>>;\n collapsed: Ref<T[] | undefined>;\n sorted: ComputedRef<readonly T[]>;\n}\n\nexport interface UseTableGroupingReturn<T extends object> {\n groupKeys: ComputedRef<TableRowKey<T>[]>;\n groupKey: ComputedRef<string | undefined>;\n isGrouped: ComputedRef<boolean>;\n mappedGroups: ComputedRef<Record<string, GroupedTableRow<T>[]>>;\n grouped: ComputedRef<readonly GroupedTableRow<T>[]>;\n getRowGroup: (row: T) => Partial<T>;\n getGroupRows: (groupVal: string) => T[];\n compareGroupsFn: (a: T, b: Partial<T>) => boolean;\n isExpandedGroup: (value: Partial<T>) => boolean;\n isHiddenRow: (row: GroupedTableRow<T>) => boolean;\n onToggleExpandGroup: (group: Partial<T>, value?: string) => void;\n onUngroup: () => void;\n}\n\n// Null character separator prevents false collisions when group values contain commas\nconst GROUP_KEY_SEPARATOR = '\\0';\n\nexport function useTableGrouping<T extends object, IdType extends keyof T>(\n options: UseTableGroupingOptions<T, IdType>,\n deps: UseTableGroupingDeps<T>,\n): UseTableGroupingReturn<T> {\n const { rowAttr } = options;\n const { group, collapsed, sorted } = deps;\n\n const collapsedRows: Ref<T[]> = ref([]);\n\n watch(collapsed, value => set(collapsedRows, value ?? []), { immediate: true });\n\n const groupKeys: ComputedRef<TableRowKey<T>[]> = computed(() => {\n const groupBy = get(group);\n\n if (!groupBy)\n return [];\n\n if (!Array.isArray(groupBy))\n return [groupBy];\n\n return groupBy;\n });\n\n const groupKey = computed<string | undefined>(() => {\n const key = get(groupKeys).join(':');\n return key || undefined;\n });\n\n const isGrouped = computed<boolean>(() => get(groupKey) !== undefined);\n\n const collapsedIdentifierSet = computed<Set<T[IdType]>>(\n () => new Set(get(collapsedRows).map(row => row[rowAttr])),\n );\n\n const collapsedGroupKeySet = computed<Set<string>>(() => {\n const grouping = get(groupKeys);\n if (grouping.length === 0)\n return new Set<string>();\n\n const seen = new Set<string>();\n for (const row of get(collapsedRows))\n seen.add(computeGroupKey(row, grouping));\n return seen;\n });\n\n function getRowGroup(row: T): Partial<T> {\n const result: Partial<T> = {};\n for (const key of get(groupKeys)) {\n result[key] = row[key];\n }\n return result;\n }\n\n function compareGroupsFn(a: T, b: Partial<T>): boolean {\n const grouping = get(groupKeys);\n if (grouping.length === 0)\n return false;\n\n return grouping.every(key => a[key] === b[key]);\n }\n\n function isExpandedGroup(value: Partial<T>): boolean {\n const grouping = get(groupKeys);\n let groupVal = '';\n for (const gk of grouping) {\n if (groupVal)\n groupVal += GROUP_KEY_SEPARATOR;\n const val = value[gk];\n groupVal += isDefined(val) ? val : '';\n }\n return !get(collapsedGroupKeySet).has(groupVal);\n }\n\n function isHiddenRow(row: GroupedTableRow<T>): boolean {\n if (!get(isGrouped))\n return false;\n if (!isRow(row))\n return false;\n return get(collapsedIdentifierSet).has(row[rowAttr]);\n }\n\n function computeGroupKey(row: T, grouping: TableRowKey<T>[]): string {\n let key = '';\n for (const gk of grouping) {\n if (key)\n key += GROUP_KEY_SEPARATOR;\n const val = row[gk];\n key += isDefined(val) ? val : '';\n }\n return key;\n }\n\n const mappedGroups = computed<Record<string, GroupedTableRow<T>[]>>(() => {\n const grouping = get(groupKeys);\n if (grouping.length === 0)\n return {};\n\n const result = get(sorted);\n const identifier = rowAttr;\n const acc: Record<string, GroupedTableRow<T>[]> = {};\n\n for (const row of result) {\n if (!isDefined(row[identifier]) || row[identifier] === '')\n continue;\n\n const groupVal = computeGroupKey(row, grouping);\n if (!acc[groupVal]) {\n acc[groupVal] = [\n {\n [GROUP_HEADER_BRAND]: true,\n group: getRowGroup(row),\n identifier: groupVal,\n } satisfies GroupHeader<T>,\n ];\n }\n\n acc[groupVal].push(row);\n }\n\n return acc;\n });\n\n const grouped = computed<readonly GroupedTableRow<T>[]>(() => {\n const result = get(sorted);\n const groupByKey = get(groupKey);\n\n if (!groupByKey)\n return result;\n\n const groups = get(mappedGroups);\n const out: GroupedTableRow<T>[] = [];\n for (const items of Object.values(groups)) {\n for (const item of items)\n out.push(item);\n }\n return out;\n });\n\n function getGroupRows(groupVal: string): T[] {\n if (!get(isGrouped))\n return [];\n\n const groupRows = get(mappedGroups)[groupVal];\n assert(groupRows);\n return groupRows.filter(isRow);\n }\n\n function onToggleExpandGroup(groupPartial: Partial<T>, value?: string): void {\n if (!value)\n return;\n\n const currentCollapsed = get(collapsedRows);\n\n const groupExpanded = isExpandedGroup(groupPartial);\n\n const groupRows = getGroupRows(value);\n\n set(\n collapsedRows,\n groupExpanded\n ? [...currentCollapsed, ...groupRows]\n : currentCollapsed.filter(row => !compareGroupsFn(row, groupPartial)),\n );\n\n set(collapsed, get(collapsedRows));\n }\n\n function onUngroup(): void {\n set(collapsedRows, []);\n\n set(collapsed, []);\n set(group, Array.isArray(get(group)) ? [] : undefined);\n }\n\n return {\n groupKeys,\n groupKey,\n isGrouped,\n mappedGroups,\n grouped,\n getRowGroup,\n getGroupRows,\n compareGroupsFn,\n isExpandedGroup,\n isHiddenRow,\n onToggleExpandGroup,\n onUngroup,\n };\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import type { MaybeComputedElementRef } from '@vueuse/core';
2
1
  import type { MaybeRefOrGetter, Ref } from 'vue';
2
+ import type { MaybeElementRef } from '../../../types/dom';
3
3
  export interface UsePageScrollReturn {
4
4
  /** Scroll the table's top into view, if it has scrolled above the visible area. */
5
5
  revealTableTop: () => Promise<void>;
@@ -20,11 +20,13 @@ export declare function useStickyPaginationBar(wrapper: Readonly<Ref<HTMLElement
20
20
  /**
21
21
  * Publishes how much of the view's bottom a stuck pagination bar covers, as `--rui-sticky-bottom` on
22
22
  * the document root, so the page's own floating parts (a dock, a FAB) can rise above the bar instead of
23
- * covering its page buttons. Only a bar stuck to the page counts: one stuck inside a scrolling area
24
- * sits under nothing the page floats.
23
+ * covering its page buttons. A bar resting at its own place in the bottom band of the view counts too,
24
+ * since it sits in the same corner; it covers from its top down, which is more than its height when it
25
+ * rests above the view's bottom, so the parts keep the same gap above it as above a stuck bar. Only a
26
+ * bar at page level counts: one inside a scrolling area sits under nothing the page floats.
25
27
  *
26
- * @param sentinel - an empty element at the bar's own place after the rows; while it is below the view, the bar is stuck
28
+ * @param sentinel - an empty element at the bar's own place after the rows; while it is below the view's bottom band, the bar covers that corner
27
29
  * @param bar - the bar, measured for its height
28
30
  * @param canStick - whether the bar may stick at all
29
31
  */
30
- export declare function useStickyBottomInset(sentinel: Readonly<Ref<HTMLElement | null | undefined>>, bar: MaybeComputedElementRef, canStick: MaybeRefOrGetter<boolean>): void;
32
+ export declare function useStickyBottomInset(sentinel: Readonly<Ref<HTMLElement | null | undefined>>, bar: MaybeElementRef, canStick: MaybeRefOrGetter<boolean>): void;
@@ -1,6 +1,6 @@
1
- import { nextTick, onMounted, onScopeDispose, shallowRef, toValue, watchEffect } from "vue";
2
- import { useElementSize, useIntersectionObserver } from "@vueuse/core";
3
- import { get as get$1, set as set$1 } from "@vueuse/shared";
1
+ import { get, set } from "../../../vendor/@vueuse/shared/dist/index.js";
2
+ import { unrefElement, useElementSize, useEventListener, useIntersectionObserver, useWindowSize } from "../../../vendor/@vueuse/core/dist/index.js";
3
+ import { nextTick, onMounted, onScopeDispose, shallowRef, toValue, watch, watchEffect } from "vue";
4
4
  //#region src/composables/tables/data-table/page-scroll.ts
5
5
  /**
6
6
  * How much of a table, from its top, must be on screen before its pagination bar sticks: the
@@ -34,7 +34,7 @@ function scrollPageBy(top) {
34
34
  function usePageScroll(wrapper, stickyOffset) {
35
35
  async function revealTableTop() {
36
36
  await nextTick();
37
- const element = get$1(wrapper);
37
+ const element = get(wrapper);
38
38
  if (!element) return;
39
39
  const scroller = findScroller(element);
40
40
  const viewTop = scroller ? scroller.getBoundingClientRect().top : toValue(stickyOffset) ?? 0;
@@ -54,19 +54,24 @@ function useStickyPaginationBar(wrapper, enabled) {
54
54
  const canStick = shallowRef(true);
55
55
  const root = shallowRef();
56
56
  onMounted(() => {
57
- const element = get$1(wrapper);
58
- if (element) set$1(root, findScroller(element));
57
+ const element = get(wrapper);
58
+ if (element) set(root, findScroller(element));
59
59
  });
60
- useIntersectionObserver(() => toValue(enabled) ? get$1(wrapper) : void 0, ([entry]) => {
60
+ useIntersectionObserver(() => toValue(enabled) ? get(wrapper) : void 0, ([entry]) => {
61
61
  if (!entry) return;
62
- set$1(canStick, entry.isIntersecting || entry.boundingClientRect.bottom <= (entry.rootBounds?.top ?? 0));
62
+ set(canStick, entry.isIntersecting || entry.boundingClientRect.bottom <= (entry.rootBounds?.top ?? 0));
63
63
  }, {
64
64
  root,
65
65
  rootMargin: `0px 0px -${STICK_AFTER}px 0px`
66
66
  });
67
67
  return canStick;
68
68
  }
69
- /** The height of each pagination bar stuck to the page, by table; the page's floating parts clear the tallest. */
69
+ /**
70
+ * How far above the bar a bar resting at its own place still counts as covered: a part docked in the
71
+ * bottom corner (rotki's task dock is 82px with its offset) reaches over the bar's top by about this much.
72
+ */
73
+ var RESTING_CLEARANCE = 48;
74
+ /** How much of the view's bottom each pagination bar covers, by table; the page's floating parts clear the most. */
70
75
  var stuckBarHeights = /* @__PURE__ */ new Map();
71
76
  function publishStickyBottom() {
72
77
  if (typeof document === "undefined") return;
@@ -77,10 +82,12 @@ function publishStickyBottom() {
77
82
  /**
78
83
  * Publishes how much of the view's bottom a stuck pagination bar covers, as `--rui-sticky-bottom` on
79
84
  * the document root, so the page's own floating parts (a dock, a FAB) can rise above the bar instead of
80
- * covering its page buttons. Only a bar stuck to the page counts: one stuck inside a scrolling area
81
- * sits under nothing the page floats.
85
+ * covering its page buttons. A bar resting at its own place in the bottom band of the view counts too,
86
+ * since it sits in the same corner; it covers from its top down, which is more than its height when it
87
+ * rests above the view's bottom, so the parts keep the same gap above it as above a stuck bar. Only a
88
+ * bar at page level counts: one inside a scrolling area sits under nothing the page floats.
82
89
  *
83
- * @param sentinel - an empty element at the bar's own place after the rows; while it is below the view, the bar is stuck
90
+ * @param sentinel - an empty element at the bar's own place after the rows; while it is below the view's bottom band, the bar covers that corner
84
91
  * @param bar - the bar, measured for its height
85
92
  * @param canStick - whether the bar may stick at all
86
93
  */
@@ -88,21 +95,45 @@ function useStickyBottomInset(sentinel, bar, canStick) {
88
95
  const id = Symbol("sticky-pagination-bar");
89
96
  const belowView = shallowRef(false);
90
97
  const pageLevel = shallowRef(false);
98
+ const covered = shallowRef(0);
91
99
  const { height } = useElementSize(bar, void 0, { box: "border-box" });
100
+ const { height: viewHeight } = useWindowSize();
101
+ let frame = 0;
102
+ /** From the bar's top to the view's bottom; a stuck bar sits on that bottom, so this is its height. */
103
+ function measureCovered() {
104
+ frame = 0;
105
+ const element = unrefElement(bar);
106
+ if (!element) return;
107
+ set(covered, Math.max(get(height), Math.ceil(get(viewHeight) - element.getBoundingClientRect().top)));
108
+ }
109
+ /** A resting bar moves with the page, so while it is in the band, follow it once per frame. */
110
+ function scheduleMeasure() {
111
+ if (get(belowView) && !frame) frame = requestAnimationFrame(measureCovered);
112
+ }
113
+ useEventListener("scroll", scheduleMeasure, {
114
+ capture: true,
115
+ passive: true
116
+ });
92
117
  onMounted(() => {
93
- const element = get$1(sentinel);
94
- set$1(pageLevel, !!element && !findScroller(element));
118
+ const element = get(sentinel);
119
+ set(pageLevel, !!element && !findScroller(element));
95
120
  });
96
121
  useIntersectionObserver(sentinel, ([entry]) => {
97
122
  if (!entry) return;
98
- set$1(belowView, !entry.isIntersecting && entry.boundingClientRect.top >= (entry.rootBounds?.bottom ?? Number.POSITIVE_INFINITY));
99
- });
123
+ set(belowView, !entry.isIntersecting && entry.boundingClientRect.top >= (entry.rootBounds?.bottom ?? Number.POSITIVE_INFINITY));
124
+ }, { rootMargin: () => `0px 0px -${Math.ceil(get(height)) + RESTING_CLEARANCE}px 0px` });
125
+ watch([
126
+ belowView,
127
+ height,
128
+ viewHeight
129
+ ], () => measureCovered());
100
130
  watchEffect(() => {
101
- if (get$1(pageLevel) && toValue(canStick) && get$1(belowView) && get$1(height) > 0) stuckBarHeights.set(id, get$1(height));
131
+ if (get(pageLevel) && toValue(canStick) && get(belowView) && get(height) > 0) stuckBarHeights.set(id, Math.max(get(height), get(covered)));
102
132
  else stuckBarHeights.delete(id);
103
133
  publishStickyBottom();
104
134
  });
105
135
  onScopeDispose(() => {
136
+ if (frame) cancelAnimationFrame(frame);
106
137
  stuckBarHeights.delete(id);
107
138
  publishStickyBottom();
108
139
  });
@@ -1 +1 @@
1
- {"version":3,"file":"page-scroll.js","names":[],"sources":["../../../../src/composables/tables/data-table/page-scroll.ts"],"sourcesContent":["import type { MaybeComputedElementRef } from '@vueuse/core';\nimport type { MaybeRefOrGetter, Ref } from 'vue';\n\nexport interface UsePageScrollReturn {\n /** Scroll the table's top into view, if it has scrolled above the visible area. */\n revealTableTop: () => Promise<void>;\n}\n\n/**\n * How much of a table, from its top, must be on screen before its pagination bar sticks: the\n * column header and the first rows. A table just scrolling in from below keeps its bar under the\n * rows, rather than showing the bar on top of the header.\n */\nconst STICK_AFTER = 128;\n\n/**\n * The nearest ancestor that scrolls vertically. `undefined` means the page itself does, through\n * the window or a scrolling `<body>`, which is where a sticky offset such as an app bar applies.\n */\nfunction findScroller(element: HTMLElement): HTMLElement | undefined {\n let node = element.parentElement;\n while (node && node !== document.body && node !== document.documentElement) {\n const { overflowY } = getComputedStyle(node);\n if ((overflowY === 'auto' || overflowY === 'scroll') && node.scrollHeight > node.clientHeight)\n return node;\n node = node.parentElement;\n }\n return undefined;\n}\n\nfunction scrollPageBy(top: number): void {\n const body = document.body;\n if (body.scrollHeight > body.clientHeight && ['auto', 'scroll'].includes(getComputedStyle(body).overflowY))\n body.scrollBy({ top });\n else\n window.scrollBy({ top });\n}\n\n/**\n * After a page change, brings the table's first row back into view so the new page reads from the\n * top. It scrolls only when the table's top sits above the visible area, as it does after paging\n * from the bottom bar of a long page; a table that already shows its top stays put, so paging never\n * makes the view jump.\n */\nexport function usePageScroll(\n wrapper: Readonly<Ref<HTMLElement | null | undefined>>,\n stickyOffset: MaybeRefOrGetter<number | undefined>,\n): UsePageScrollReturn {\n async function revealTableTop(): Promise<void> {\n await nextTick();\n const element = get(wrapper);\n if (!element)\n return;\n\n const scroller = findScroller(element);\n const viewTop = scroller ? scroller.getBoundingClientRect().top : (toValue(stickyOffset) ?? 0);\n const distance = element.getBoundingClientRect().top - viewTop;\n if (distance >= 0)\n return;\n\n if (scroller)\n scroller.scrollBy({ top: distance });\n else\n scrollPageBy(distance);\n }\n\n return { revealTableTop };\n}\n\n/**\n * Whether the pagination bar may stick: true once the top {@link STICK_AFTER}px of the table are\n * inside its scrolling area. It starts true, so a page without IntersectionObserver keeps the bar\n * sticky.\n */\nexport function useStickyPaginationBar(\n wrapper: Readonly<Ref<HTMLElement | null | undefined>>,\n enabled: MaybeRefOrGetter<boolean>,\n): Readonly<Ref<boolean>> {\n const canStick = shallowRef<boolean>(true);\n const root = shallowRef<HTMLElement>();\n\n onMounted(() => {\n const element = get(wrapper);\n if (element)\n set(root, findScroller(element));\n });\n\n useIntersectionObserver(\n () => (toValue(enabled) ? get(wrapper) : undefined),\n ([entry]) => {\n if (!entry)\n return;\n // also true once the table has scrolled past the top, when the bar is out of view anyway\n set(canStick, entry.isIntersecting || entry.boundingClientRect.bottom <= (entry.rootBounds?.top ?? 0));\n },\n { root, rootMargin: `0px 0px -${STICK_AFTER}px 0px` },\n );\n\n return canStick;\n}\n\n/** The height of each pagination bar stuck to the page, by table; the page's floating parts clear the tallest. */\nconst stuckBarHeights = new Map<symbol, number>();\n\nfunction publishStickyBottom(): void {\n if (typeof document === 'undefined')\n return;\n const style = document.documentElement.style;\n if (stuckBarHeights.size === 0)\n style.removeProperty('--rui-sticky-bottom');\n else\n style.setProperty('--rui-sticky-bottom', `${Math.max(...stuckBarHeights.values())}px`);\n}\n\n/**\n * Publishes how much of the view's bottom a stuck pagination bar covers, as `--rui-sticky-bottom` on\n * the document root, so the page's own floating parts (a dock, a FAB) can rise above the bar instead of\n * covering its page buttons. Only a bar stuck to the page counts: one stuck inside a scrolling area\n * sits under nothing the page floats.\n *\n * @param sentinel - an empty element at the bar's own place after the rows; while it is below the view, the bar is stuck\n * @param bar - the bar, measured for its height\n * @param canStick - whether the bar may stick at all\n */\nexport function useStickyBottomInset(\n sentinel: Readonly<Ref<HTMLElement | null | undefined>>,\n bar: MaybeComputedElementRef,\n canStick: MaybeRefOrGetter<boolean>,\n): void {\n const id = Symbol('sticky-pagination-bar');\n const belowView = shallowRef<boolean>(false);\n const pageLevel = shallowRef<boolean>(false);\n const { height } = useElementSize(bar, undefined, { box: 'border-box' });\n\n onMounted(() => {\n const element = get(sentinel);\n set(pageLevel, !!element && !findScroller(element));\n });\n\n useIntersectionObserver(sentinel, ([entry]) => {\n if (!entry)\n return;\n // no root bounds (a cross-origin frame) reads as not stuck, which leaves the floating parts where they are\n set(belowView, !entry.isIntersecting && entry.boundingClientRect.top >= (entry.rootBounds?.bottom ?? Number.POSITIVE_INFINITY));\n });\n\n watchEffect(() => {\n if (get(pageLevel) && toValue(canStick) && get(belowView) && get(height) > 0)\n stuckBarHeights.set(id, get(height));\n else\n stuckBarHeights.delete(id);\n publishStickyBottom();\n });\n\n onScopeDispose(() => {\n stuckBarHeights.delete(id);\n publishStickyBottom();\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"page-scroll.js","names":[],"sources":["../../../../src/composables/tables/data-table/page-scroll.ts"],"sourcesContent":["import type { MaybeRefOrGetter, Ref } from 'vue';\nimport type { MaybeElementRef } from '@/types/dom';\n\nexport interface UsePageScrollReturn {\n /** Scroll the table's top into view, if it has scrolled above the visible area. */\n revealTableTop: () => Promise<void>;\n}\n\n/**\n * How much of a table, from its top, must be on screen before its pagination bar sticks: the\n * column header and the first rows. A table just scrolling in from below keeps its bar under the\n * rows, rather than showing the bar on top of the header.\n */\nconst STICK_AFTER = 128;\n\n/**\n * The nearest ancestor that scrolls vertically. `undefined` means the page itself does, through\n * the window or a scrolling `<body>`, which is where a sticky offset such as an app bar applies.\n */\nfunction findScroller(element: HTMLElement): HTMLElement | undefined {\n let node = element.parentElement;\n while (node && node !== document.body && node !== document.documentElement) {\n const { overflowY } = getComputedStyle(node);\n if ((overflowY === 'auto' || overflowY === 'scroll') && node.scrollHeight > node.clientHeight)\n return node;\n node = node.parentElement;\n }\n return undefined;\n}\n\nfunction scrollPageBy(top: number): void {\n const body = document.body;\n if (body.scrollHeight > body.clientHeight && ['auto', 'scroll'].includes(getComputedStyle(body).overflowY))\n body.scrollBy({ top });\n else\n window.scrollBy({ top });\n}\n\n/**\n * After a page change, brings the table's first row back into view so the new page reads from the\n * top. It scrolls only when the table's top sits above the visible area, as it does after paging\n * from the bottom bar of a long page; a table that already shows its top stays put, so paging never\n * makes the view jump.\n */\nexport function usePageScroll(\n wrapper: Readonly<Ref<HTMLElement | null | undefined>>,\n stickyOffset: MaybeRefOrGetter<number | undefined>,\n): UsePageScrollReturn {\n async function revealTableTop(): Promise<void> {\n await nextTick();\n const element = get(wrapper);\n if (!element)\n return;\n\n const scroller = findScroller(element);\n const viewTop = scroller ? scroller.getBoundingClientRect().top : (toValue(stickyOffset) ?? 0);\n const distance = element.getBoundingClientRect().top - viewTop;\n if (distance >= 0)\n return;\n\n if (scroller)\n scroller.scrollBy({ top: distance });\n else\n scrollPageBy(distance);\n }\n\n return { revealTableTop };\n}\n\n/**\n * Whether the pagination bar may stick: true once the top {@link STICK_AFTER}px of the table are\n * inside its scrolling area. It starts true, so a page without IntersectionObserver keeps the bar\n * sticky.\n */\nexport function useStickyPaginationBar(\n wrapper: Readonly<Ref<HTMLElement | null | undefined>>,\n enabled: MaybeRefOrGetter<boolean>,\n): Readonly<Ref<boolean>> {\n const canStick = shallowRef<boolean>(true);\n const root = shallowRef<HTMLElement>();\n\n onMounted(() => {\n const element = get(wrapper);\n if (element)\n set(root, findScroller(element));\n });\n\n useIntersectionObserver(\n () => (toValue(enabled) ? get(wrapper) : undefined),\n ([entry]) => {\n if (!entry)\n return;\n // also true once the table has scrolled past the top, when the bar is out of view anyway\n set(canStick, entry.isIntersecting || entry.boundingClientRect.bottom <= (entry.rootBounds?.top ?? 0));\n },\n { root, rootMargin: `0px 0px -${STICK_AFTER}px 0px` },\n );\n\n return canStick;\n}\n\n/**\n * How far above the bar a bar resting at its own place still counts as covered: a part docked in the\n * bottom corner (rotki's task dock is 82px with its offset) reaches over the bar's top by about this much.\n */\nconst RESTING_CLEARANCE = 48;\n\n/** How much of the view's bottom each pagination bar covers, by table; the page's floating parts clear the most. */\nconst stuckBarHeights = new Map<symbol, number>();\n\nfunction publishStickyBottom(): void {\n if (typeof document === 'undefined')\n return;\n const style = document.documentElement.style;\n if (stuckBarHeights.size === 0)\n style.removeProperty('--rui-sticky-bottom');\n else\n style.setProperty('--rui-sticky-bottom', `${Math.max(...stuckBarHeights.values())}px`);\n}\n\n/**\n * Publishes how much of the view's bottom a stuck pagination bar covers, as `--rui-sticky-bottom` on\n * the document root, so the page's own floating parts (a dock, a FAB) can rise above the bar instead of\n * covering its page buttons. A bar resting at its own place in the bottom band of the view counts too,\n * since it sits in the same corner; it covers from its top down, which is more than its height when it\n * rests above the view's bottom, so the parts keep the same gap above it as above a stuck bar. Only a\n * bar at page level counts: one inside a scrolling area sits under nothing the page floats.\n *\n * @param sentinel - an empty element at the bar's own place after the rows; while it is below the view's bottom band, the bar covers that corner\n * @param bar - the bar, measured for its height\n * @param canStick - whether the bar may stick at all\n */\nexport function useStickyBottomInset(\n sentinel: Readonly<Ref<HTMLElement | null | undefined>>,\n bar: MaybeElementRef,\n canStick: MaybeRefOrGetter<boolean>,\n): void {\n const id = Symbol('sticky-pagination-bar');\n const belowView = shallowRef<boolean>(false);\n const pageLevel = shallowRef<boolean>(false);\n const covered = shallowRef<number>(0);\n const { height } = useElementSize(bar, undefined, { box: 'border-box' });\n const { height: viewHeight } = useWindowSize();\n let frame = 0;\n\n /** From the bar's top to the view's bottom; a stuck bar sits on that bottom, so this is its height. */\n function measureCovered(): void {\n frame = 0;\n const element = unrefElement(bar);\n if (!element)\n return;\n set(covered, Math.max(get(height), Math.ceil(get(viewHeight) - element.getBoundingClientRect().top)));\n }\n\n /** A resting bar moves with the page, so while it is in the band, follow it once per frame. */\n function scheduleMeasure(): void {\n if (get(belowView) && !frame)\n frame = requestAnimationFrame(measureCovered);\n }\n\n useEventListener('scroll', scheduleMeasure, { capture: true, passive: true });\n\n onMounted(() => {\n const element = get(sentinel);\n set(pageLevel, !!element && !findScroller(element));\n });\n\n useIntersectionObserver(sentinel, ([entry]) => {\n if (!entry)\n return;\n // no root bounds (a cross-origin frame) reads as not stuck, which leaves the floating parts where they are\n set(belowView, !entry.isIntersecting && entry.boundingClientRect.top >= (entry.rootBounds?.bottom ?? Number.POSITIVE_INFINITY));\n }, {\n // the view's bottom edge, raised by the band a resting bar covers\n rootMargin: () => `0px 0px -${Math.ceil(get(height)) + RESTING_CLEARANCE}px 0px`,\n });\n\n watch([belowView, height, viewHeight], () => measureCovered());\n\n watchEffect(() => {\n if (get(pageLevel) && toValue(canStick) && get(belowView) && get(height) > 0)\n stuckBarHeights.set(id, Math.max(get(height), get(covered)));\n else\n stuckBarHeights.delete(id);\n publishStickyBottom();\n });\n\n onScopeDispose(() => {\n if (frame)\n cancelAnimationFrame(frame);\n stuckBarHeights.delete(id);\n publishStickyBottom();\n });\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
+ import { get, set } from "../../../vendor/@vueuse/shared/dist/index.js";
1
2
  import { isRow } from "./types.js";
2
3
  import { computed, readonly, ref, shallowRef, watch } from "vue";
3
- import { get, set } from "@vueuse/shared";
4
4
  //#region src/composables/tables/data-table/pagination.ts
5
5
  /**
6
6
  * Skip data rows until the page start offset, tracking the last group header seen.
@@ -1,9 +1,8 @@
1
1
  import { assert } from "../../../utils/assert.js";
2
+ import { get, isDefined, set } from "../../../vendor/@vueuse/shared/dist/index.js";
2
3
  import { useTimeoutManager } from "../../timeout-manager.js";
3
4
  import { isRow } from "./types.js";
4
5
  import { computed, shallowRef, toValue, watch } from "vue";
5
- import { isDefined } from "@vueuse/core";
6
- import { get as get$1, set as set$1 } from "@vueuse/shared";
7
6
  //#region src/composables/tables/data-table/selection.ts
8
7
  function useTableSelection(options, deps) {
9
8
  const { rowAttr, multiPageSelect, disabledRows } = options;
@@ -12,30 +11,30 @@ function useTableSelection(options, deps) {
12
11
  const lastSelectedIndex = shallowRef(-1);
13
12
  const internalSelectedData = shallowRef([]);
14
13
  const { create: scheduleShiftSelect } = useTimeoutManager();
15
- watch(selectedData, (val) => set$1(internalSelectedData, val ?? []), { immediate: true });
16
- const visibleIdentifiers = computed(() => get$1(filtered).filter(isRow).map((row) => row[rowAttr]));
17
- const selectedSet = computed(() => new Set(get$1(selectedData) ?? []));
14
+ watch(selectedData, (val) => set(internalSelectedData, val ?? []), { immediate: true });
15
+ const visibleIdentifiers = computed(() => get(filtered).filter(isRow).map((row) => row[rowAttr]));
16
+ const selectedSet = computed(() => new Set(get(selectedData) ?? []));
18
17
  const disabledRowKeySet = computed(() => {
19
18
  const currentDisabledRows = toValue(disabledRows);
20
19
  if (!currentDisabledRows || !rowAttr) return /* @__PURE__ */ new Set();
21
20
  return new Set(currentDisabledRows.map((row) => row[rowAttr]));
22
21
  });
23
22
  const isAllSelected = computed(() => {
24
- const selectedRows = get$1(selectedData);
23
+ const selectedRows = get(selectedData);
25
24
  if (!selectedRows || selectedRows.length === 0) return false;
26
- const selected = get$1(selectedSet);
27
- return get$1(visibleIdentifiers).every((id) => selected.has(id));
25
+ const selected = get(selectedSet);
26
+ return get(visibleIdentifiers).every((id) => selected.has(id));
28
27
  });
29
28
  const indeterminate = computed(() => {
30
- const selectedRows = get$1(selectedData);
29
+ const selectedRows = get(selectedData);
31
30
  if (!selectedRows) return false;
32
- return selectedRows.length > 0 && !get$1(isAllSelected);
31
+ return selectedRows.length > 0 && !get(isAllSelected);
33
32
  });
34
33
  function isSelected(identifier) {
35
- return get$1(selectedSet).has(identifier);
34
+ return get(selectedSet).has(identifier);
36
35
  }
37
36
  function isDisabledRow(rowKey) {
38
- return get$1(disabledRowKeySet).has(rowKey);
37
+ return get(disabledRowKeySet).has(rowKey);
39
38
  }
40
39
  function isSelectable(rowKey) {
41
40
  return isSelected(rowKey) || !isDisabledRow(rowKey);
@@ -44,30 +43,30 @@ function useTableSelection(options, deps) {
44
43
  return isSelected(rowKey) && isDisabledRow(rowKey);
45
44
  }
46
45
  function resetCheckboxShiftState() {
47
- set$1(shiftClicked, false);
48
- set$1(lastSelectedIndex, -1);
46
+ set(shiftClicked, false);
47
+ set(lastSelectedIndex, -1);
49
48
  }
50
49
  function onToggleAll(checked) {
51
- const selectedRows = get$1(selectedData);
50
+ const selectedRows = get(selectedData);
52
51
  if (!isDefined(selectedRows)) return;
53
52
  if (!multiPageSelect) {
54
- if (checked) set$1(selectedData, get$1(visibleIdentifiers).filter(isSelectable));
55
- else set$1(selectedData, get$1(visibleIdentifiers).filter(mustSelect));
56
- } else if (checked) set$1(selectedData, Array.from(/* @__PURE__ */ new Set([...selectedRows, ...get$1(visibleIdentifiers).filter(isSelectable)])));
53
+ if (checked) set(selectedData, get(visibleIdentifiers).filter(isSelectable));
54
+ else set(selectedData, get(visibleIdentifiers).filter(mustSelect));
55
+ } else if (checked) set(selectedData, Array.from(/* @__PURE__ */ new Set([...selectedRows, ...get(visibleIdentifiers).filter(isSelectable)])));
57
56
  else {
58
- const visibleSet = new Set(get$1(visibleIdentifiers));
59
- const mustSelectSet = new Set(get$1(visibleIdentifiers).filter(mustSelect));
60
- set$1(selectedData, selectedRows.filter((rowKey) => !visibleSet.has(rowKey) || mustSelectSet.has(rowKey)));
57
+ const visibleSet = new Set(get(visibleIdentifiers));
58
+ const mustSelectSet = new Set(get(visibleIdentifiers).filter(mustSelect));
59
+ set(selectedData, selectedRows.filter((rowKey) => !visibleSet.has(rowKey) || mustSelectSet.has(rowKey)));
61
60
  }
62
61
  }
63
62
  function onSelect(checked, value, userAction = false) {
64
- if (get$1(shiftClicked) && userAction) return;
65
- const selectedRows = get$1(internalSelectedData);
63
+ if (get(shiftClicked) && userAction) return;
64
+ const selectedRows = get(internalSelectedData);
66
65
  if (!selectedRows) return;
67
66
  const selected = isSelected(value);
68
- if (checked && !selected) set$1(internalSelectedData, [...selectedRows, value]);
69
- else if (!checked && selected) set$1(internalSelectedData, selectedRows.filter((r) => r !== value));
70
- if (userAction) set$1(selectedData, get$1(internalSelectedData));
67
+ if (checked && !selected) set(internalSelectedData, [...selectedRows, value]);
68
+ else if (!checked && selected) set(internalSelectedData, selectedRows.filter((r) => r !== value));
69
+ if (userAction) set(selectedData, get(internalSelectedData));
71
70
  }
72
71
  function onCheckboxClick(event, value, index) {
73
72
  const currentTarget = event.currentTarget;
@@ -76,12 +75,12 @@ function useTableSelection(options, deps) {
76
75
  const target = event.target;
77
76
  const nodeName = target instanceof HTMLElement ? target.nodeName : void 0;
78
77
  const shiftKey = event.shiftKey;
79
- set$1(shiftClicked, shiftKey);
78
+ set(shiftClicked, shiftKey);
80
79
  if (input && nodeName !== "INPUT") {
81
80
  if (shiftKey) scheduleShiftSelect(() => {
82
- let lastIndex = get$1(lastSelectedIndex);
81
+ let lastIndex = get(lastSelectedIndex);
83
82
  if (lastIndex === -1) lastIndex = index;
84
- const tableData = get$1(filtered);
83
+ const tableData = get(filtered);
85
84
  const lastSelectedData = tableData[lastIndex];
86
85
  assert(lastSelectedData);
87
86
  if (isRow(lastSelectedData)) {
@@ -90,7 +89,7 @@ function useTableSelection(options, deps) {
90
89
  else {
91
90
  const from = Math.min(lastIndex, index);
92
91
  const to = Math.max(lastIndex, index);
93
- const currentSelected = get$1(internalSelectedData);
92
+ const currentSelected = get(internalSelectedData);
94
93
  const rangeIds = [];
95
94
  for (let i = from; i <= to; i++) {
96
95
  const currSelectedData = tableData[i];
@@ -100,25 +99,25 @@ function useTableSelection(options, deps) {
100
99
  if (valueToApply) {
101
100
  const existing = new Set(currentSelected);
102
101
  const toAdd = rangeIds.filter((id) => !existing.has(id));
103
- set$1(internalSelectedData, [...currentSelected, ...toAdd]);
102
+ set(internalSelectedData, [...currentSelected, ...toAdd]);
104
103
  } else {
105
104
  const toRemove = new Set(rangeIds);
106
- set$1(internalSelectedData, currentSelected.filter((id) => !toRemove.has(id)));
105
+ set(internalSelectedData, currentSelected.filter((id) => !toRemove.has(id)));
107
106
  }
108
107
  }
109
- set$1(lastSelectedIndex, index);
110
- set$1(selectedData, get$1(internalSelectedData));
108
+ set(lastSelectedIndex, index);
109
+ set(selectedData, get(internalSelectedData));
111
110
  }
112
111
  }, 1);
113
- else set$1(lastSelectedIndex, index);
112
+ else set(lastSelectedIndex, index);
114
113
  }
115
114
  }
116
115
  function deselectRemovedRows() {
117
- const currentSelected = get$1(selectedData);
116
+ const currentSelected = get(selectedData);
118
117
  if (!currentSelected) return;
119
- const visibleSet = new Set(get$1(visibleIdentifiers));
118
+ const visibleSet = new Set(get(visibleIdentifiers));
120
119
  const remaining = currentSelected.filter((key) => visibleSet.has(key));
121
- if (remaining.length !== currentSelected.length) set$1(selectedData, remaining);
120
+ if (remaining.length !== currentSelected.length) set(selectedData, remaining);
122
121
  }
123
122
  return {
124
123
  visibleIdentifiers,