playbook_ui 16.8.0.pre.alpha.PLAY2945selectformblankselection16424 → 16.8.0.pre.alpha.PLAY2965datepickerconsoleerrors16591
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.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +2 -0
- data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +2 -0
- data/app/pb_kits/playbook/pb_advanced_table/Components/VirtualizedTableView.tsx +5 -1
- data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +24 -0
- data/app/pb_kits/playbook/pb_advanced_table/Utilities/ColumnLayoutHelper.ts +138 -0
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +144 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling.jsx +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling.md +6 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_width.jsx +57 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_width.md +66 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_playground.json +5 -2
- data/app/pb_kits/playbook/pb_advanced_table/docs/_playground.overrides.json +1 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_column_definitions_styling.json +4 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_card/_card.tsx +1 -1
- data/app/pb_kits/playbook/pb_card/card.html.erb +1 -1
- data/app/pb_kits/playbook/pb_currency/_currency.tsx +9 -6
- data/app/pb_kits/playbook/pb_currency/currency.rb +5 -10
- data/app/pb_kits/playbook/pb_currency/currency.test.js +44 -1
- data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +36 -21
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_dialog_submission.jsx +2 -2
- data/app/pb_kits/playbook/pb_draggable/_draggable.scss +19 -0
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_cards_rails.md +2 -0
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_cards_react.md +1 -0
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list_rails.md +2 -0
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list_react.md +3 -1
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list_rails.md +3 -1
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list_react.md +3 -1
- data/app/pb_kits/playbook/pb_draggable/draggable.test.jsx +16 -0
- data/app/pb_kits/playbook/pb_draggable/draggable_container.html.erb +3 -1
- data/app/pb_kits/playbook/pb_draggable/draggable_item.html.erb +1 -0
- data/app/pb_kits/playbook/pb_draggable/index.js +149 -7
- data/app/pb_kits/playbook/pb_draggable/subcomponents/DraggableContainer.tsx +1 -0
- data/app/pb_kits/playbook/pb_draggable/subcomponents/DraggableItem.tsx +67 -1
- data/app/pb_kits/playbook/pb_draggable/touchDrag.test.js +38 -0
- data/app/pb_kits/playbook/pb_draggable/utilities/touchDrag.ts +173 -0
- data/app/pb_kits/playbook/pb_form/docs/example.yml +0 -1
- data/app/pb_kits/playbook/pb_icon/docs/example.yml +0 -2
- data/app/pb_kits/playbook/pb_icon/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_list/_list_item.tsx +4 -1
- data/app/pb_kits/playbook/pb_list/item.html.erb +1 -1
- data/dist/chunks/{_typeahead-D2TWdJTn.js → _typeahead-DA__Kgp5.js} +1 -1
- data/dist/chunks/vendor.js +2 -2
- data/dist/menu.yml +67 -127
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/forms/builder/collection_select_field.rb +1 -1
- data/lib/playbook/forms/builder/select_field.rb +1 -1
- data/lib/playbook/forms/builder/time_zone_select_field.rb +1 -1
- data/lib/playbook/version.rb +1 -1
- metadata +9 -8
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_select_examples.html.erb +0 -31
- data/app/pb_kits/playbook/pb_icon/docs/_icon_fa_kit.html.erb +0 -1
- data/app/pb_kits/playbook/pb_icon/docs/_icon_fa_kit.jsx +0 -21
- data/app/pb_kits/playbook/pb_icon/docs/_icon_fa_kit.md +0 -7
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DRAG_HANDLE_SELECTOR,
|
|
3
|
+
getContainerFromElement,
|
|
4
|
+
getDragIdFromElement,
|
|
5
|
+
} from "./utilities/touchDrag";
|
|
6
|
+
|
|
7
|
+
describe("touchDrag utilities", () => {
|
|
8
|
+
test("DRAG_HANDLE_SELECTOR matches standard and card handles", () => {
|
|
9
|
+
document.body.innerHTML = `
|
|
10
|
+
<div class="pb_draggable_item" data-pb-drag-id="1">
|
|
11
|
+
<span class="pb_draggable_handle"></span>
|
|
12
|
+
<span class="card_draggable_handle"></span>
|
|
13
|
+
</div>
|
|
14
|
+
`;
|
|
15
|
+
|
|
16
|
+
const item = document.querySelector(".pb_draggable_item");
|
|
17
|
+
expect(item.querySelector(DRAG_HANDLE_SELECTOR)).toBeTruthy();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("getDragIdFromElement reads data-pb-drag-id", () => {
|
|
21
|
+
document.body.innerHTML = `
|
|
22
|
+
<div class="pb_draggable_item" data-pb-drag-id="task-1"></div>
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
expect(getDragIdFromElement(document.querySelector(".pb_draggable_item"))).toBe("task-1");
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("getContainerFromElement reads data-pb-drag-container", () => {
|
|
29
|
+
document.body.innerHTML = `
|
|
30
|
+
<div class="pb_draggable_container" data-pb-drag-container="To Do">
|
|
31
|
+
<div class="pb_draggable_item" data-pb-drag-id="1"></div>
|
|
32
|
+
</div>
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
const item = document.querySelector(".pb_draggable_item");
|
|
36
|
+
expect(getContainerFromElement(item)).toBe("To Do");
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
export const DRAG_HANDLE_SELECTOR = '.pb_draggable_handle, .card_draggable_handle';
|
|
2
|
+
|
|
3
|
+
const DRAG_THRESHOLD_PX = 5;
|
|
4
|
+
|
|
5
|
+
export const isTouchDragDevice = (): boolean => {
|
|
6
|
+
if (typeof window === 'undefined') return false;
|
|
7
|
+
|
|
8
|
+
const hasTouch = 'ontouchstart' in window;
|
|
9
|
+
const hasCoarsePointer =
|
|
10
|
+
typeof window.matchMedia === 'function' &&
|
|
11
|
+
window.matchMedia('(hover: none) and (pointer: coarse)').matches;
|
|
12
|
+
|
|
13
|
+
return hasTouch || hasCoarsePointer;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const getDragIdFromElement = (element: Element | null): string | null => {
|
|
17
|
+
const item = element?.closest('.pb_draggable_item');
|
|
18
|
+
if (!item) return null;
|
|
19
|
+
|
|
20
|
+
return item.getAttribute('data-pb-drag-id');
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const getContainerFromElement = (element: Element | null): string | undefined => {
|
|
24
|
+
const container = element?.closest('.pb_draggable_container');
|
|
25
|
+
if (!container) return undefined;
|
|
26
|
+
|
|
27
|
+
return container.getAttribute('data-pb-drag-container') || undefined;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
type TouchDragHandlers = {
|
|
31
|
+
onDragStart: (dragId: string, container?: string) => void;
|
|
32
|
+
onDragEnter: (targetDragId: string, container?: string) => void;
|
|
33
|
+
onDragOver: (event: Event, container?: string) => void;
|
|
34
|
+
onDrop: (container?: string) => void;
|
|
35
|
+
onDragEnd: () => void;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
type TouchDragOptions = {
|
|
39
|
+
dragId: string;
|
|
40
|
+
container?: string;
|
|
41
|
+
itemElement: HTMLElement;
|
|
42
|
+
handlers: TouchDragHandlers;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
type TouchDragState = {
|
|
46
|
+
active: boolean;
|
|
47
|
+
dragging: boolean;
|
|
48
|
+
startX: number;
|
|
49
|
+
startY: number;
|
|
50
|
+
lastTargetDragId: string | null;
|
|
51
|
+
lastContainer: string | undefined;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const createPreventableEvent = (): Event => ({
|
|
55
|
+
preventDefault: () => undefined,
|
|
56
|
+
} as Event);
|
|
57
|
+
|
|
58
|
+
export const bindTouchDrag = ({
|
|
59
|
+
dragId,
|
|
60
|
+
container,
|
|
61
|
+
itemElement,
|
|
62
|
+
handlers,
|
|
63
|
+
}: TouchDragOptions): (() => void) => {
|
|
64
|
+
if (!isTouchDragDevice()) return () => undefined;
|
|
65
|
+
|
|
66
|
+
const handle = itemElement.querySelector(DRAG_HANDLE_SELECTOR) as HTMLElement | null;
|
|
67
|
+
const dragTarget = handle || itemElement;
|
|
68
|
+
|
|
69
|
+
const state: TouchDragState = {
|
|
70
|
+
active: false,
|
|
71
|
+
dragging: false,
|
|
72
|
+
startX: 0,
|
|
73
|
+
startY: 0,
|
|
74
|
+
lastTargetDragId: null,
|
|
75
|
+
lastContainer: undefined,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const resetState = () => {
|
|
79
|
+
state.active = false;
|
|
80
|
+
state.dragging = false;
|
|
81
|
+
state.lastTargetDragId = null;
|
|
82
|
+
state.lastContainer = undefined;
|
|
83
|
+
itemElement.classList.remove('is_touch_active');
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const handleTouchStart = (event: TouchEvent) => {
|
|
87
|
+
if (handle && !handle.contains(event.target as Node)) return;
|
|
88
|
+
|
|
89
|
+
const touch = event.touches[0];
|
|
90
|
+
if (!touch) return;
|
|
91
|
+
|
|
92
|
+
state.active = true;
|
|
93
|
+
state.startX = touch.clientX;
|
|
94
|
+
state.startY = touch.clientY;
|
|
95
|
+
itemElement.classList.add('is_touch_active');
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const handleTouchMove = (event: TouchEvent) => {
|
|
99
|
+
if (!state.active) return;
|
|
100
|
+
|
|
101
|
+
const touch = event.touches[0];
|
|
102
|
+
if (!touch) return;
|
|
103
|
+
|
|
104
|
+
if (!state.dragging) {
|
|
105
|
+
const deltaX = touch.clientX - state.startX;
|
|
106
|
+
const deltaY = touch.clientY - state.startY;
|
|
107
|
+
|
|
108
|
+
if (Math.hypot(deltaX, deltaY) < DRAG_THRESHOLD_PX) return;
|
|
109
|
+
|
|
110
|
+
state.dragging = true;
|
|
111
|
+
handlers.onDragStart(dragId, container);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
event.preventDefault();
|
|
115
|
+
|
|
116
|
+
const elementBelow = document.elementFromPoint(touch.clientX, touch.clientY);
|
|
117
|
+
const targetDragId = getDragIdFromElement(elementBelow);
|
|
118
|
+
const targetContainer = getContainerFromElement(elementBelow);
|
|
119
|
+
|
|
120
|
+
if (targetDragId && targetDragId !== dragId && targetDragId !== state.lastTargetDragId) {
|
|
121
|
+
state.lastTargetDragId = targetDragId;
|
|
122
|
+
handlers.onDragEnter(targetDragId, targetContainer ?? container);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (targetContainer && targetContainer !== state.lastContainer) {
|
|
126
|
+
state.lastContainer = targetContainer;
|
|
127
|
+
handlers.onDragOver(createPreventableEvent(), targetContainer);
|
|
128
|
+
} else if (targetContainer) {
|
|
129
|
+
handlers.onDragOver(createPreventableEvent(), targetContainer);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const finishDrag = (touch: Touch | null) => {
|
|
134
|
+
if (!state.active) return;
|
|
135
|
+
|
|
136
|
+
if (state.dragging && touch) {
|
|
137
|
+
const elementBelow = document.elementFromPoint(touch.clientX, touch.clientY);
|
|
138
|
+
const dropContainer = getContainerFromElement(elementBelow) ?? container;
|
|
139
|
+
|
|
140
|
+
if (dropContainer) {
|
|
141
|
+
handlers.onDrop(dropContainer);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
handlers.onDragEnd();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
resetState();
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const handleTouchEnd = (event: TouchEvent) => {
|
|
151
|
+
finishDrag(event.changedTouches[0] ?? null);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const handleTouchCancel = (event: TouchEvent) => {
|
|
155
|
+
if (state.dragging) {
|
|
156
|
+
handlers.onDragEnd();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
finishDrag(event.changedTouches[0] ?? null);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
dragTarget.addEventListener('touchstart', handleTouchStart, { passive: true });
|
|
163
|
+
dragTarget.addEventListener('touchmove', handleTouchMove, { passive: false });
|
|
164
|
+
dragTarget.addEventListener('touchend', handleTouchEnd, { passive: true });
|
|
165
|
+
dragTarget.addEventListener('touchcancel', handleTouchCancel, { passive: true });
|
|
166
|
+
|
|
167
|
+
return () => {
|
|
168
|
+
dragTarget.removeEventListener('touchstart', handleTouchStart);
|
|
169
|
+
dragTarget.removeEventListener('touchmove', handleTouchMove);
|
|
170
|
+
dragTarget.removeEventListener('touchend', handleTouchEnd);
|
|
171
|
+
dragTarget.removeEventListener('touchcancel', handleTouchCancel);
|
|
172
|
+
};
|
|
173
|
+
};
|
|
@@ -8,7 +8,6 @@ examples:
|
|
|
8
8
|
- icon_border: Icon Border
|
|
9
9
|
- icon_sizes: Icon Sizes
|
|
10
10
|
- icon_custom: Icon Custom
|
|
11
|
-
- icon_fa_kit: Icon with FontAwesome Kit
|
|
12
11
|
- icon_color: Icon Color
|
|
13
12
|
|
|
14
13
|
react:
|
|
@@ -20,7 +19,6 @@ examples:
|
|
|
20
19
|
- icon_border: Icon Border
|
|
21
20
|
- icon_sizes: Icon Sizes
|
|
22
21
|
- icon_custom: Icon Custom
|
|
23
|
-
- icon_fa_kit: Icon with FontAwesome Kit
|
|
24
22
|
- icon_color: Icon Color
|
|
25
23
|
|
|
26
24
|
swift:
|
|
@@ -6,5 +6,4 @@ export { default as IconPull } from './_icon_pull.jsx'
|
|
|
6
6
|
export { default as IconBorder } from './_icon_border.jsx'
|
|
7
7
|
export { default as IconSizes } from './_icon_sizes.jsx'
|
|
8
8
|
export { default as IconCustom } from './_icon_custom.jsx'
|
|
9
|
-
export { default as IconFaKit} from './_icon_fa_kit.jsx'
|
|
10
9
|
export { default as IconColor } from './_icon_color.jsx'
|
|
@@ -58,7 +58,10 @@ const ListItem = (props: ListItemProps) => {
|
|
|
58
58
|
>
|
|
59
59
|
{
|
|
60
60
|
dragHandle && (
|
|
61
|
-
<span
|
|
61
|
+
<span
|
|
62
|
+
className="pb_draggable_handle"
|
|
63
|
+
style={{verticalAlign: 'middle'}}
|
|
64
|
+
>
|
|
62
65
|
<Body color="light">
|
|
63
66
|
<Icon
|
|
64
67
|
icon="grip-dots-vertical"
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
**combined_html_options
|
|
10
10
|
) do %>
|
|
11
11
|
<% if object.drag_handle %>
|
|
12
|
-
<span style="vertical-align: middle;">
|
|
12
|
+
<span class="pb_draggable_handle" style="vertical-align: middle;">
|
|
13
13
|
<%= pb_rails("body") do %>
|
|
14
14
|
<svg width="auto" height="auto" viewBox="0 0 31 25" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="pb_custom_icon svg-inline--fa vertical_align_middle svg_fw"><path d="M12.904 6.355a1.48 1.48 0 01-1.5-1.5c0-.796.656-1.5 1.5-1.5.797 0 1.5.704 1.5 1.5 0 .844-.703 1.5-1.5 1.5zm0 7.5a1.48 1.48 0 01-1.5-1.5c0-.796.656-1.5 1.5-1.5.797 0 1.5.704 1.5 1.5 0 .844-.703 1.5-1.5 1.5zm1.5 6c0 .844-.703 1.5-1.5 1.5a1.48 1.48 0 01-1.5-1.5c0-.796.656-1.5 1.5-1.5.797 0 1.5.704 1.5 1.5zm4.5-13.5a1.48 1.48 0 01-1.5-1.5c0-.796.657-1.5 1.5-1.5.797 0 1.5.704 1.5 1.5 0 .844-.703 1.5-1.5 1.5zm1.5 6c0 .844-.703 1.5-1.5 1.5a1.48 1.48 0 01-1.5-1.5c0-.796.657-1.5 1.5-1.5.797 0 1.5.704 1.5 1.5zm-1.5 9a1.48 1.48 0 01-1.5-1.5c0-.796.657-1.5 1.5-1.5.797 0 1.5.704 1.5 1.5 0 .844-.703 1.5-1.5 1.5z" fill="#242B42"></path></svg>
|
|
15
15
|
<% end %>
|