katalyst-tables 3.11.3 → 3.12.0

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.
@@ -15,7 +15,7 @@ export default class OrderableListController extends Controller {
15
15
  this.element.style.position = "relative";
16
16
  }
17
17
 
18
- stopDragging() {
18
+ stopDragging({ reset = true } = {}) {
19
19
  const dragState = this.dragState;
20
20
  delete this.dragState;
21
21
 
@@ -24,7 +24,7 @@ export default class OrderableListController extends Controller {
24
24
  window.removeEventListener("scroll", this.scroll, true);
25
25
 
26
26
  this.element.removeAttribute("style");
27
- this.tablesOrderableItemOutlets.forEach((item) => item.reset());
27
+ if (reset) this.items.forEach((item) => item.reset());
28
28
 
29
29
  return dragState;
30
30
  }
@@ -38,25 +38,30 @@ export default class OrderableListController extends Controller {
38
38
 
39
39
  if (!dragItem) return;
40
40
 
41
- const newIndex = dragItem.dragIndex;
42
- const targetItem = this.tablesOrderableItemOutlets[newIndex];
41
+ const items = this.items;
42
+ items.forEach((item) => item.captureDropPosition());
43
43
 
44
- if (!targetItem) return;
44
+ this.#insertDragItem(this.orderedItems, dragItem);
45
45
 
46
- // swap the dragged item into the correct position for its current offset
47
- if (newIndex < dragItem.index) {
48
- targetItem.row.insertAdjacentElement("beforebegin", dragItem.row);
49
- } else if (newIndex > dragItem.index) {
50
- targetItem.row.insertAdjacentElement("afterend", dragItem.row);
51
- }
46
+ items.forEach((item) => item.invertDropPosition());
47
+
48
+ // Commit the inverted transforms before enabling transitions to play out.
49
+ this.element.offsetHeight;
52
50
 
53
51
  // reindex all items based on their new positions
54
- this.tablesOrderableItemOutlets.forEach((item, index) =>
55
- item.updateIndex(index),
56
- );
52
+ this.items.forEach((item, index) => item.updateIndex(index));
57
53
 
58
54
  // save the changes
59
55
  this.commitChanges();
56
+
57
+ window.requestAnimationFrame(() => {
58
+ items.forEach((item) => item.playDrop());
59
+ window.setTimeout(() => {
60
+ items.forEach((item) => item.reset());
61
+ }, this.#animationDuration);
62
+ });
63
+
64
+ return true;
60
65
  }
61
66
 
62
67
  commitChanges() {
@@ -64,7 +69,7 @@ export default class OrderableListController extends Controller {
64
69
  this.tablesOrderableFormOutlet.clear();
65
70
 
66
71
  // insert any items that have changed position
67
- this.tablesOrderableItemOutlets.forEach((item) => {
72
+ this.items.forEach((item) => {
68
73
  if (item.hasChanges) this.tablesOrderableFormOutlet.add(item);
69
74
  });
70
75
 
@@ -127,9 +132,9 @@ export default class OrderableListController extends Controller {
127
132
  mouseup = (event) => {
128
133
  if (!this.isDragging) return;
129
134
 
130
- this.drop();
131
- this.stopDragging();
132
- this.tablesOrderableFormOutlets.forEach((form) => delete form.dragState);
135
+ const dropped = this.drop();
136
+ this.stopDragging({ reset: !dropped });
137
+ this.items.forEach((form) => delete form.dragState);
133
138
  };
134
139
 
135
140
  tablesOrderableFormOutletConnected(form, element) {
@@ -172,9 +177,11 @@ export default class OrderableListController extends Controller {
172
177
 
173
178
  // Visually updates the position of all items in the list relative to the
174
179
  // dragged item. No actual changes to orderings at this stage.
175
- this.#currentItems.forEach((item, index) => {
176
- if (item === dragItem) return;
177
- item.updateVisually(index);
180
+ let nextOffset = 0;
181
+
182
+ this.orderedItems.forEach((item) => {
183
+ if (item !== dragItem) item.updateVisually(nextOffset);
184
+ nextOffset += item.height;
178
185
  });
179
186
  };
180
187
 
@@ -185,23 +192,30 @@ export default class OrderableListController extends Controller {
185
192
  get dragItem() {
186
193
  if (!this.isDragging) return null;
187
194
 
188
- return this.tablesOrderableItemOutlets.find(
189
- (item) => item.id === this.dragState.targetId,
190
- );
195
+ return this.items.find((item) => item.id === this.dragState.targetId);
191
196
  }
192
197
 
193
198
  /**
194
- * Returns the current items in the list, sorted by their current index.
195
- * Current uses the drag index if the item is being dragged, if set.
199
+ * Returns the current items in the list in DOM order.
196
200
  *
197
201
  * @returns {Array[OrderableRowController]}
198
202
  */
199
- get #currentItems() {
200
- return this.tablesOrderableItemOutlets.toSorted(
201
- (a, b) => a.comparisonIndex - b.comparisonIndex,
203
+ get items() {
204
+ // Note, item outlets may include other items as the outlets do not have a
205
+ // mechanism to specify an element scope.
206
+ return this.tablesOrderableItemOutlets.filter((item) =>
207
+ this.element.contains(item.element),
202
208
  );
203
209
  }
204
210
 
211
+ get orderedItems() {
212
+ const dragItem = this.dragItem;
213
+
214
+ if (!dragItem) return this.items;
215
+
216
+ return this.items.toSorted((a, b) => a.dragPosition - b.dragPosition);
217
+ }
218
+
205
219
  /**
206
220
  * Returns the item outlet that was clicked on, if any.
207
221
  *
@@ -209,14 +223,42 @@ export default class OrderableListController extends Controller {
209
223
  * @returns {OrderableRowController}
210
224
  */
211
225
  #targetItem(element) {
212
- return this.tablesOrderableItemOutlets.find(
213
- (item) => item.element === element,
214
- );
226
+ return this.items.find((item) => item.element === element);
227
+ }
228
+
229
+ #insertDragItem(orderedItems, dragItem) {
230
+ const index = orderedItems.indexOf(dragItem);
231
+ const previousItem = orderedItems[index - 1];
232
+ const nextItem = orderedItems[index + 1];
233
+
234
+ if (previousItem) {
235
+ previousItem.row.insertAdjacentElement("afterend", dragItem.row);
236
+ } else if (nextItem) {
237
+ nextItem.row.insertAdjacentElement("beforebegin", dragItem.row);
238
+ }
239
+ }
240
+
241
+ get #animationDuration() {
242
+ const duration =
243
+ window
244
+ .getComputedStyle(this.element)
245
+ .getPropertyValue("--animation-duration") || "150ms";
246
+
247
+ return parseTime(duration);
215
248
  }
216
249
 
217
250
  //endregion
218
251
  }
219
252
 
253
+ function parseTime(value) {
254
+ value = value.trim();
255
+
256
+ if (value.endsWith("ms")) return parseFloat(value);
257
+ if (value.endsWith("s")) return parseFloat(value) * 1000;
258
+
259
+ return parseFloat(value) || 0;
260
+ }
261
+
220
262
  /**
221
263
  * During drag we want to be able to translate a document-relative coordinate
222
264
  * into a coordinate relative to the list element. This state object calculates
@@ -64,7 +64,7 @@ module Katalyst
64
64
  def value_for_multiple(value)
65
65
  case value
66
66
  when ::Array
67
- value.reject { |v| v.is_a?(::Range) }
67
+ value.grep_v(::Range)
68
68
  when ::Range
69
69
  value
70
70
  else
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: katalyst-tables
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.11.3
4
+ version: 3.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katalyst Interactive
@@ -182,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
182
182
  - !ruby/object:Gem::Version
183
183
  version: '0'
184
184
  requirements: []
185
- rubygems_version: 4.0.3
185
+ rubygems_version: 4.0.6
186
186
  specification_version: 4
187
187
  summary: HTML table generator for Rails views
188
188
  test_files: []