Skip to content

Commit

Permalink
Implementing Rails Draggable kit
Browse files Browse the repository at this point in the history
  • Loading branch information
carloslimasd committed Jul 24, 2024
1 parent e54614e commit 8bf388a
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 4 deletions.
2 changes: 1 addition & 1 deletion playbook-website/config/menu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ kits:
platforms: *1
status: stable
- name: draggable
platforms: *2
platforms: *1
description:
status: stable
- category: message_text_patterns
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<%
items = [
{
id: "21",
url: "https://unsplash.it/500/400/?image=633",
},
{
id: "22",
url: "https://unsplash.it/500/400/?image=634",
},
{
id: "23",
url: "https://unsplash.it/500/400/?image=637",
},
]
%>

<%= pb_rails("draggable", props: { initial_items: items }) do %>
<%= pb_rails("draggable/draggable_container") do %>
<%= pb_rails("flex") do %>
<% items.each do |item| %>
<%= pb_rails("draggable/draggable_item", props: { drag_id: item[:id], container: "carlos" }) do %>
<%= pb_rails("image", props: { alt: item[:id], margin: "xs", size: "md", url: item[:url] }) %>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
5 changes: 2 additions & 3 deletions playbook/app/pb_kits/playbook/pb_draggable/docs/example.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
examples:

rails:
- draggable_default: Default

react:
- draggable_default: Default
- draggable_with_list: Draggable with List Kit
- draggable_with_selectable_list: Draggable with SelectableList Kit
- draggable_with_cards: Draggable with Cards
- draggable_multiple_containers: Dragging Across Multiple Containers


8 changes: 8 additions & 0 deletions playbook/app/pb_kits/playbook/pb_draggable/draggable.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<%= content_tag(:div,
aria: object.aria,
class: object.classname,
data: object.data,
id: object.id,
**combined_html_options) do %>
<%= content %>
<% end %>
18 changes: 18 additions & 0 deletions playbook/app/pb_kits/playbook/pb_draggable/draggable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

module Playbook
module PbDraggable
class Draggable < Playbook::KitBase
prop :initial_items, type: Playbook::Props::Array,
default: []

def data
Hash(prop(:data)).merge(pb_draggable: initial_items)
end

def classname
generate_classname("pb_draggable")
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<%= content_tag(:div,
aria: object.aria,
class: object.classname,
data: object.data,
id: object.id,
**combined_html_options) do %>
<%= content %>
<% end %>
19 changes: 19 additions & 0 deletions playbook/app/pb_kits/playbook/pb_draggable/draggable_container.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

module Playbook
module PbDraggable
class DraggableContainer < Playbook::KitBase
prop :container

def data
Hash(prop(:data)).merge(
pb_draggable_container: container.presence || ""
)
end

def classname
generate_classname("pb_draggable_container")
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<%= content_tag(:div,
aria: object.aria,
class: object.classname,
data: object.data,
id: object.id,
**combined_html_options) do %>
<%= content %>
<% end %>
23 changes: 23 additions & 0 deletions playbook/app/pb_kits/playbook/pb_draggable/draggable_item.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

module Playbook
module PbDraggable
class DraggableItem < Playbook::KitBase
prop :container
prop :drag_id, type: Playbook::Props::String,
default: ""

def data
Hash(prop(:data)).merge(
pb_draggable_item: true,
pb_draggable_item_container: container.presence || "",
pb_draggable_item_drag_id: drag_id
)
end

def classname
generate_classname("pb_draggable_item")
end
end
end
end
116 changes: 116 additions & 0 deletions playbook/app/pb_kits/playbook/pb_draggable/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import PbEnhancedElement from "../pb_enhanced_element";

const DRAGGABLE_SELECTOR = "[data-pb-draggable]";
const DRAGGABLE_CONTAINER_SELECTOR = "[data-pb-draggable-container]";
const DRAGGABLE_ITEM_SELECTOR = "[data-pb-draggable-item]";

const initialState = {
items: [],
dragData: { id: "", initialGroup: "" },
isDragging: "",
activeContainer: ""
};

export default class PbDraggable extends PbEnhancedElement {
static get selector() {
return DRAGGABLE_SELECTOR;
}

connect() {
document.pbDraggableState = document.pbDraggableState || initialState;
this.setItems(this.getInitialItems());
this.bindEventListeners();
}

getInitialItems() {
return JSON.parse(this.element.dataset.pbDraggable);
}

bindEventListeners() {
this.bindContainerEventListener();
this.bindItemEventListener();
}

bindContainerEventListener() {
const containerElement = this.element.querySelector(DRAGGABLE_CONTAINER_SELECTOR);
const container = containerElement.dataset.pbDraggableContainer;
containerElement.addEventListener("dragover", (e) => this.handleDragOver(e, container));
containerElement.addEventListener("drop", () => this.handleDrop(container));
}

bindItemEventListener() {
const itemElements = this.element.querySelectorAll(DRAGGABLE_ITEM_SELECTOR);
itemElements.forEach((itemElement) => {
const container = itemElement.dataset.pbDraggableItemContainer;
const dragId = itemElement.dataset.pbDraggableItemDragId;
itemElement.addEventListener("dragstart", () => this.handleDragStart(dragId, container));
itemElement.addEventListener("dragenter", () => this.handleDragEnter(dragId, container));
itemElement.addEventListener("dragend", () => this.handleDragEnd());
});
}

setItems(items) {
document.pbDraggableState = { ...document.pbDraggableState, items: items };
}

setDragData(dragData) {
document.pbDraggableState = { ...document.pbDraggableState, dragData: dragData };
}

setIsDragging(isDragging) {
document.pbDraggableState = { ...document.pbDraggableState, isDragging: isDragging };
}

setActiveContainer(activeContainer) {
document.pbDraggableState = { ...document.pbDraggableState, activeContainer: activeContainer };
}

changeCategory(itemId, container) {
document.pbDraggableState = {
...document.pbDraggableState,
items: document.pbDraggableState.items.map(item =>
item.id === itemId ? { ...item, container: container } : item
)
};
}

reorderItems(dragId, targetId) {
const newItems = [...document.pbDraggableState.items];
const draggedItem = newItems.find(item => item.id === dragId);
const draggedIndex = newItems.indexOf(draggedItem);
const targetIndex = newItems.findIndex(item => item.id === targetId);

newItems.splice(draggedIndex, 1);
newItems.splice(targetIndex, 0, draggedItem);

document.pbDraggableState = { ...document.pbDraggableState, items: newItems };
}

handleDragStart(id, container) {
this.setDragData({ id: id, initialGroup: container });
this.setIsDragging(id);
}

handleDragEnter(id, container) {
if (document.pbDraggableState.dragData.id !== id) {
this.reorderItems(document.pbDraggableState.dragData.id, id);
this.setDragData({ id: document.pbDraggableState.dragData.id, initialGroup: container });
}
}

handleDragEnd() {
this.setIsDragging("");
this.setActiveContainer("");
}

handleDrop(container) {
this.setIsDragging("");
this.setActiveContainer("");
this.changeCategory(document.pbDraggableState.dragData.id, container);
}

handleDragOver(e, container) {
e.preventDefault();
this.setActiveContainer(container);
}
}
3 changes: 3 additions & 0 deletions playbook/app/pb_kits/playbook/playbook-rails.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ PbNav.start()
import PbStarRating from './pb_star_rating'
PbStarRating.start()

import PbDraggable from './pb_draggable'
PbDraggable.start()

import 'flatpickr'

// React-Rendered Rails Kits =====
Expand Down

0 comments on commit 8bf388a

Please sign in to comment.