Live-ghost column drag; "only" app filter; disk size / free space filters

Custom View column drag rewritten with pointer events (replacing native
drag-and-drop): grab a column by its grip or anywhere on its header (a
click still sorts); the real column slides into the slot it would land
in as a translucent striped ghost while a label follows the pointer.
Only the horizontal position decides the slot. Esc cancels; data
refreshes wait until the drop; wide tables scroll near the edges.

Filters:
- List columns (software, tags): "Has any ticked" / "Has only ticked"
  toggle - e.g. devices missing only Adobe Acrobat Pro
- Space columns: filter by disk size (221 GB, 442 GB, no reading) plus a
  free-space rule (any / at least N GB / less than N GB, default 20); sort
  by disk size or by free space (numeric, no reading last); header clicks
  cancel these sorts
- Menu controls no longer shrink when the menu is height-limited
This commit is contained in:
Johan Sandoval committed 2026-10-06 18:20:00 +00:00
1 parent 973ff592a4
commit 50c2a18a68
3 files changed
+277 -92

No files matched your search

+33 -15
View File
@@ -361,21 +361,39 @@ table.xf-table thead th:has(> .xf-btn):not(.sortable-th) { position: relative; p
}
.xf-opt.xf-none { font-style: italic; border-bottom: 1px dashed var(--border-light); }
/* Custom View column drag preview (layout.js) */
.col-drag-ghost {
position: fixed; top: -1000px; left: -1000px; z-index: 9999; pointer-events: none;
background: var(--bg-card); color: var(--text-main); border: 2px solid #3498db; border-radius: 6px;
box-shadow: 0 10px 24px rgba(0,0,0,0.45); overflow: hidden; font-size: 12px;
/* Custom View column drag (layout.js): the column moves live as a ghost, a label follows */
#table-custom thead th.custom-th .col-label-row { cursor: grab; }
body.col-dragging, body.col-dragging * { cursor: grabbing !important; user-select: none !important; }
#table-custom .col-ghost {
opacity: 0.55;
background-image: repeating-linear-gradient(45deg, rgba(52,152,219,0.16) 0 6px, transparent 6px 12px) !important;
box-shadow: inset 2px 0 0 #3498db, inset -2px 0 0 #3498db;
}
.col-drag-ghost-head { padding: 7px 10px; font-weight: 700; color: #fff; background: var(--table-header-bg); }
.col-drag-ghost-cell {
padding: 5px 10px; border-top: 1px solid var(--border-light);
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
#table-custom thead th.col-ghost { opacity: 0.8; box-shadow: inset 2px 0 0 #3498db, inset -2px 0 0 #3498db, inset 0 2px 0 #3498db; }
.col-drag-float {
position: fixed; z-index: 9999; pointer-events: none; white-space: nowrap;
transform: translate(12px, -50%) rotate(-2deg);
padding: 7px 12px; font-weight: 700; font-size: 13px; color: #fff;
background: var(--table-header-bg); border: 1px solid #3498db; border-radius: 6px;
box-shadow: 0 10px 24px rgba(0,0,0,0.45);
}
#table-custom .col-moving { opacity: 0.35; }
.col-drop-marker {
position: absolute; top: 0; width: 4px; z-index: 30; pointer-events: none;
background: #3498db; border-radius: 2px; box-shadow: 0 0 8px rgba(52,152,219,0.8);
/* Filter menu: sections, free-space rule, any/only toggle */
.xf-section { padding: 2px 12px 6px; }
.xf-section-title { font-size: 0.75em; font-weight: 700; letter-spacing: 0.5px; text-transform: uppercase; color: var(--text-muted); padding: 4px 0; }
.xf-list-title { padding: 4px 12px; }
.xf-radio { display: flex; align-items: center; gap: 8px; padding: 3px 0; cursor: pointer; }
.xf-thr { display: flex; align-items: center; gap: 8px; padding: 4px 0 0 24px; color: var(--text-muted); font-size: 0.9em; }
.xf-num {
width: 64px; padding: 4px 6px; font: inherit; color: var(--text-main);
background: var(--input-bg); border: 1px solid var(--border-color); border-radius: 4px;
}
/* the single insertion line replaces the per-header highlight */
#table-custom .custom-th.drag-over { box-shadow: none !important; }
.xf-seg { display: flex; margin: 0 12px 6px; border: 1px solid var(--border-color); border-radius: 6px; overflow: hidden; }
.xf-seg-btn {
flex: 1; padding: 5px 6px; cursor: pointer; font: inherit; font-size: 0.85em; white-space: nowrap;
background: transparent; color: var(--text-muted); border: 0;
}
.xf-seg-btn + .xf-seg-btn { border-left: 1px solid var(--border-color); }
.xf-seg-btn.on { background: #3498db; color: #fff; font-weight: 600; }
/* Only the value list shrinks when the menu is height-limited; controls keep their size */
.xf-menu > :not(.xf-list):not(.xf-add):not(.xf-fields) { flex-shrink: 0; }