blacklight-spotlight 5.3.1 → 5.3.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.
@@ -1,8 +1,4 @@
1
1
  .spotlight-flexbox {
2
- display: -webkit-box;
3
- display: -moz-box;
4
- display: -ms-flexbox;
5
- display: -webkit-flex;
6
2
  display: flex;
7
3
  flex-flow: row wrap;
8
4
 
@@ -13,7 +9,7 @@
13
9
 
14
10
  @media (max-width: breakpoint-max("sm")) {
15
11
  min-width: 200px;
16
- -webkit-flex: 1 1 200px;
12
+ flex: 1 1 200px;
17
13
  }
18
14
 
19
15
  .caption {
@@ -23,11 +19,6 @@
23
19
  img {
24
20
  max-width: 100%;
25
21
  }
26
- -webkit-box-flex: 1;
27
- -moz-box-flex: 1;
28
- -webkit-flex: 1;
29
- -ms-flex: 1;
30
22
  flex: 1;
31
- -webkit-flex: 1 1 125px;
32
23
  }
33
24
  }
@@ -26,10 +26,27 @@ tr.dd-item {
26
26
  position: relative;
27
27
  }
28
28
 
29
+ // SortableJS moves an item to the start of a list when the pointer is over the list more than
30
+ // 10px left of its items.
31
+ $dd-nested-list-padding-left: 5px;
32
+
29
33
  .dd-list { display: block; position: relative; margin: 0; padding: 0 0 5px 0; list-style: none; }
30
- .dd-list .dd-list { margin-left: 15px; padding-left: 15px; padding-bottom: 0; } // Having this mix of padding and margin improves the experience of dragging left to remove an item from a nested list.
34
+ .dd-list .dd-list { margin-left: 25px; padding-left: $dd-nested-list-padding-left; padding-bottom: 0; }
31
35
  .dd-collapsed .dd-list { display: none; }
32
36
 
37
+ // While a drag is in progress, extend each child list with a drop zone that covers the
38
+ // indented part of the next item. Dragging an item to the right then nests it.
39
+ .dd-nesting .dd-item > .dd-list::after {
40
+ content: "";
41
+ position: absolute;
42
+ top: 100%;
43
+ left: $dd-nested-list-padding-left; // Offset from the child list's padding box, so the zone starts where its items start
44
+ right: 0;
45
+ height: var(--dd-nesting-zone-height);
46
+ z-index: 1;
47
+ }
48
+ .dd-nesting .sortable-chosen > .dd-list::after { display: none; }
49
+
33
50
  .dd-item,
34
51
  .dd-empty,
35
52
  .dd-placeholder { display: block; position: relative; margin: 0; padding: 0; min-height: 20px; font-size: 13px; line-height: 20px; }
@@ -237,14 +237,14 @@
237
237
 
238
238
  .box {
239
239
  min-width: 150px;
240
- -webkit-flex: 1 1 150px;
240
+ flex: 1 1 150px;
241
241
  }
242
242
 
243
243
  /* two items */
244
244
  .box:first-child:nth-last-child(2),
245
245
  .box:first-child:nth-last-child(2) ~ .box {
246
246
  min-width: 250px;
247
- -webkit-flex: 1 1 250px;
247
+ flex: 1 1 250px;
248
248
  }
249
249
 
250
250
  /* only images, no text */
@@ -260,7 +260,7 @@
260
260
  }
261
261
 
262
262
  @media (max-width: breakpoint-max("md")) {
263
- -webkit-flex: 1 1 175px;
263
+ flex: 1 1 175px;
264
264
  }
265
265
  }
266
266
  }
@@ -8,7 +8,10 @@ const Module = (function () {
8
8
  handle: ".dd-handle",
9
9
  fallbackOnBody: true,
10
10
  swapThreshold: 0.65,
11
- emptyInsertThreshold: 15,
11
+ // 0 turns off SortableJS's "drop near an empty list" check. The .dd-nesting drop
12
+ // zones in _nestable.scss decide nesting, so a vertical drag past an item's edge
13
+ // does not nest it by accident.
14
+ emptyInsertThreshold: 0,
12
15
  onStart: onStartHandler,
13
16
  onEnd: onEndHandler,
14
17
  onMove: onMoveHandler,
@@ -17,6 +20,7 @@ const Module = (function () {
17
20
  const nestedSortableClass = "dd-list"
18
21
  const nestedSortableSelector = ".dd-list"
19
22
  const nestedSortableNodeName = "ol"
23
+ const nestingClass = "dd-nesting"
20
24
  const findNode = (id, container) =>
21
25
  container.querySelector(`[data-id="${id}"]`)
22
26
  const setWeight = (node, weight) => (weightField(node).value = weight)
@@ -58,14 +62,23 @@ const Module = (function () {
58
62
  }
59
63
 
60
64
  function onStartHandler(evt) {
65
+ const nestableContainer = getNestableContainer(evt.item)
61
66
  makeEmptyChildSortablesForEligibleParents(
62
- getNestableContainer(evt.item),
67
+ nestableContainer,
63
68
  getMaxNestingLevelSetting(evt.item),
64
69
  )
70
+ // Size the drop zone below each child list to match the dragged item, so that
71
+ // a drag straight to the right lands in the list of the item above.
72
+ nestableContainer.style.setProperty(
73
+ "--dd-nesting-zone-height",
74
+ `${evt.item.querySelector(sortableOptions.handle).offsetHeight}px`,
75
+ )
76
+ nestableContainer.classList.add(nestingClass)
65
77
  }
66
78
 
67
79
  function onEndHandler(evt) {
68
80
  const nestableContainer = getNestableContainer(evt.item)
81
+ nestableContainer.classList.remove(nestingClass)
69
82
  removeEmptySortables(nestableContainer)
70
83
  updateWeightsAndRelationships(nestableContainer)
71
84
  }
@@ -1,4 +1,7 @@
1
- import bootstrap from "bootstrap"
1
+ import * as bootstrap from "bootstrap"
2
+
3
+ // Bootstrap's ESM build exports Tab by name; CDN-converted UMD builds (e.g. ga.jspm.io) only have a default export
4
+ const Tab = bootstrap.Tab ?? bootstrap.default?.Tab
2
5
 
3
6
  export default class {
4
7
  connect() {
@@ -15,7 +18,7 @@ export default class {
15
18
  )
16
19
  if (!tabElement) return
17
20
 
18
- bootstrap.Tab.getOrCreateInstance(tabElement).show()
21
+ Tab.getOrCreateInstance(tabElement).show()
19
22
  }
20
23
  }
21
24
  }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Spotlight
4
- VERSION = '5.3.1'
4
+ VERSION = '5.3.2'
5
5
  end
@@ -58,6 +58,37 @@ module Spotlight
58
58
  expect(page).to have_no_selector('.alert-danger')
59
59
  end
60
60
 
61
+ # Capybara's HTML5 drag emulation sends the drag events to a given element. This drags
62
+ # to a point instead, so the test covers what is under the pointer.
63
+ def drag_horizontally(handle, by:)
64
+ # elementFromPoint returns null for a point outside the viewport
65
+ page.scroll_to(handle, align: :center)
66
+ page.driver.browser.action.click_and_hold(handle.native).perform
67
+ error = page.evaluate_async_script(DRAG_HORIZONTALLY_SCRIPT, handle, by)
68
+ page.driver.browser.action.release.perform
69
+ raise error if error
70
+ end
71
+
72
+ DRAG_HORIZONTALLY_SCRIPT = <<~JS
73
+ const [handle, offset, done] = arguments
74
+ const item = handle.closest('.dd-item')
75
+ const tick = () => new Promise((resolve) => setTimeout(resolve, 50))
76
+ const opts = { bubbles: true, cancelable: true, dataTransfer: new DataTransfer() }
77
+
78
+ item.dispatchEvent(new DragEvent('dragstart', opts))
79
+ tick().then(() => {
80
+ const rect = handle.getBoundingClientRect()
81
+ const point = { clientX: rect.left + rect.width / 2 + offset, clientY: rect.top + rect.height / 2 }
82
+ const target = document.elementFromPoint(point.clientX, point.clientY)
83
+ target.dispatchEvent(new DragEvent('dragover', { ...opts, ...point }))
84
+ return tick().then(() => {
85
+ target.dispatchEvent(new DragEvent('drop', { ...opts, ...point }))
86
+ item.dispatchEvent(new DragEvent('dragend', { ...opts, ...point }))
87
+ done()
88
+ })
89
+ }).catch((error) => done(String(error)))
90
+ JS
91
+
61
92
  RSpec::Matchers.define :have_breadcrumbs do |*expected|
62
93
  match do |actual|
63
94
  errors = []
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blacklight-spotlight
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.3.1
4
+ version: 5.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Beer
@@ -10,7 +10,7 @@ authors:
10
10
  - Justin Coyne
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2026-09-29 00:00:00.000000000 Z
13
+ date: 2026-09-30 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activejob-status