playbook_ui 15.5.0.pre.alpha.PLAY2581aggressivevalidation12698 → 15.5.0.pre.alpha.draggableask12812
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_background/_background.tsx +6 -6
- data/app/pb_kits/playbook/pb_background/background.test.js +5 -1
- data/app/pb_kits/playbook/pb_background/docs/_background_light.html.erb +1 -1
- data/app/pb_kits/playbook/pb_background/docs/_background_light.jsx +0 -1
- data/app/pb_kits/playbook/pb_background/docs/_background_light.md +1 -0
- data/app/pb_kits/playbook/pb_background/docs/example.yml +2 -2
- data/app/pb_kits/playbook/pb_dialog/index.js +10 -15
- data/app/pb_kits/playbook/pb_draggable/context/index.tsx +131 -1
- data/app/pb_kits/playbook/pb_home_address_street/_home_address_street.tsx +34 -22
- data/app/pb_kits/playbook/pb_home_address_street/city_emphasis.html.erb +16 -12
- data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_default.html.erb +1 -1
- data/app/pb_kits/playbook/pb_home_address_street/none_emphasis.html.erb +16 -12
- data/app/pb_kits/playbook/pb_home_address_street/street_emphasis.html.erb +16 -12
- data/app/pb_kits/playbook/pb_multiple_users/_multiple_users.scss +10 -0
- data/app/pb_kits/playbook/pb_multiple_users/_multiple_users.tsx +66 -15
- data/app/pb_kits/playbook/pb_multiple_users/docs/_multiple_users_with_tooltip.jsx +42 -0
- data/app/pb_kits/playbook/pb_multiple_users/docs/_multiple_users_with_tooltip.md +1 -0
- data/app/pb_kits/playbook/pb_multiple_users/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_multiple_users/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_multiple_users/multiple_users.test.js +25 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_validation.html.erb +34 -4
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_validation.jsx +16 -7
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.test.jsx +15 -0
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +3 -0
- data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.tsx +6 -1
- data/app/pb_kits/playbook/pb_typeahead/components/ValueContainer.tsx +34 -7
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_input_display.html.erb +30 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_input_display.jsx +37 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_input_display.md +3 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/index.js +2 -1
- data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +6 -1
- data/dist/chunks/_typeahead-C0TXfY_W.js +6 -0
- data/dist/chunks/vendor.js +2 -2
- 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/version.rb +1 -1
- metadata +9 -3
- data/dist/chunks/_typeahead-C8dnmJBs.js +0 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 56097fbb1da0d4528e1d4beb87d0737331ed094cc2e29e3ebdee8384c8a2ba98
|
|
4
|
+
data.tar.gz: dd17076481fb9ad736c29ca19272f2c8c598fb996e858216971756d8405dd9e6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8ed5946c8074670af44c1ebf4bfdff28144418e7eb199ea8bc755c3750f4d4ecd7ea9050c773e4adff13c55daed0ca16376e0f088ba2664795a8a58340bbaf27
|
|
7
|
+
data.tar.gz: c712a117f381ee38fbdcbb850003540978418541b04ef575e16c65964d2224b40a2399c9d61ff14613bdaa064e8241657dc48588a5babbc54df6c99d27ffeef3
|
|
@@ -102,16 +102,16 @@ const Background = (props: BackgroundProps): React.ReactElement => {
|
|
|
102
102
|
useEffect(() => {
|
|
103
103
|
const updateResponsiveProps = () => {
|
|
104
104
|
setResponsiveProps({
|
|
105
|
-
backgroundSize: getResponsiveValue(
|
|
106
|
-
backgroundPosition: getResponsiveValue(
|
|
107
|
-
backgroundRepeat: getResponsiveValue(
|
|
108
|
-
backgroundColor: getResponsiveValue(
|
|
109
|
-
imageUrl: getResponsiveValue(
|
|
105
|
+
backgroundSize: getResponsiveValue(backgroundSize),
|
|
106
|
+
backgroundPosition: getResponsiveValue(backgroundPosition),
|
|
107
|
+
backgroundRepeat: getResponsiveValue(backgroundRepeat),
|
|
108
|
+
backgroundColor: getResponsiveValue(backgroundColor),
|
|
109
|
+
imageUrl: getResponsiveValue(imageUrl),
|
|
110
110
|
});
|
|
111
111
|
};
|
|
112
112
|
window.addEventListener('resize', updateResponsiveProps);
|
|
113
113
|
return () => window.removeEventListener('resize', updateResponsiveProps);
|
|
114
|
-
}, [
|
|
114
|
+
}, [backgroundSize, backgroundPosition, backgroundRepeat, backgroundColor, imageUrl]);
|
|
115
115
|
|
|
116
116
|
|
|
117
117
|
// Extract currently applicable responsive values.
|
|
@@ -4,7 +4,6 @@ import Background from './_background'
|
|
|
4
4
|
|
|
5
5
|
const props = {
|
|
6
6
|
data: { testid: 'background' },
|
|
7
|
-
backgroundColor: null,
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
it('Should be accessible', async () => {
|
|
@@ -42,3 +41,8 @@ test('applies correct overlay class when imageOverlay prop is provided', () => {
|
|
|
42
41
|
const kit = renderKit(Background, props, { imageOverlay: 'opacity_6' });
|
|
43
42
|
expect(kit).toHaveClass('imageoverlay_opacity_6');
|
|
44
43
|
});
|
|
44
|
+
|
|
45
|
+
test('Sets backgroundColor to light as default when no backgroundColor prop is provided', () => {
|
|
46
|
+
const kit = renderKit(Background, props);
|
|
47
|
+
expect(kit).toHaveClass('pb_background_color_light');
|
|
48
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
By default, the Background kit sets background color to 'light' as seen here.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
examples:
|
|
2
2
|
|
|
3
3
|
rails:
|
|
4
|
-
- background_light:
|
|
4
|
+
- background_light: Default
|
|
5
5
|
- background_white: White
|
|
6
6
|
- background_gradient: Gradient
|
|
7
7
|
- background_image: Image
|
|
@@ -11,7 +11,7 @@ examples:
|
|
|
11
11
|
- background_size: Size
|
|
12
12
|
|
|
13
13
|
react:
|
|
14
|
-
- background_light:
|
|
14
|
+
- background_light: Default
|
|
15
15
|
- background_white: White
|
|
16
16
|
- background_gradient: Gradient
|
|
17
17
|
- background_image: Image
|
|
@@ -143,30 +143,25 @@ export default class PbDialog extends PbEnhancedElement {
|
|
|
143
143
|
|
|
144
144
|
// Close dialog box on outside click
|
|
145
145
|
dialogs.forEach((dialogElement) => {
|
|
146
|
-
const
|
|
147
|
-
if (
|
|
148
|
-
|
|
146
|
+
const originalMousedownHandler = dialogElement._outsideClickHandler
|
|
147
|
+
if (originalMousedownHandler) dialogElement.removeEventListener("mousedown", originalMousedownHandler)
|
|
149
148
|
dialogElement._outsideClickHandler = (event) => {
|
|
150
149
|
const dialogParentDataset = dialogElement.parentElement.dataset
|
|
151
150
|
if (dialogParentDataset.overlayClick === "overlay_close") return
|
|
152
151
|
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
event.
|
|
157
|
-
event.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
// Only close if clicked outside the dialog content (on the backdrop)
|
|
163
|
-
if (!clickedInDialog) {
|
|
152
|
+
const dialogModal = event.target.getBoundingClientRect()
|
|
153
|
+
const clickedOutsideDialogModal = event.clientX < dialogModal.left ||
|
|
154
|
+
event.clientX > dialogModal.right ||
|
|
155
|
+
event.clientY < dialogModal.top ||
|
|
156
|
+
event.clientY > dialogModal.bottom
|
|
157
|
+
|
|
158
|
+
if (clickedOutsideDialogModal) {
|
|
164
159
|
dialogElement.close()
|
|
165
160
|
event.stopPropagation()
|
|
166
161
|
}
|
|
167
162
|
}
|
|
168
163
|
|
|
169
|
-
dialogElement.addEventListener("
|
|
164
|
+
dialogElement.addEventListener("mousedown", dialogElement._outsideClickHandler);
|
|
170
165
|
})
|
|
171
166
|
}
|
|
172
167
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext, useReducer, useContext, useEffect, useMemo } from "react";
|
|
1
|
+
import React, { createContext, useReducer, useContext, useEffect, useMemo, useRef } from "react";
|
|
2
2
|
import { InitialStateType, ActionType, DraggableProviderType } from "./types";
|
|
3
3
|
|
|
4
4
|
const initialState: InitialStateType = {
|
|
@@ -8,6 +8,9 @@ const initialState: InitialStateType = {
|
|
|
8
8
|
activeContainer: ""
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
+
// Track if a successful drop occurred to distinguish from dragEnd without drop
|
|
12
|
+
let dropOccurred = false;
|
|
13
|
+
|
|
11
14
|
const reducer = (state: InitialStateType, action: ActionType) => {
|
|
12
15
|
switch (action.type) {
|
|
13
16
|
case 'SET_ITEMS':
|
|
@@ -92,6 +95,19 @@ const reducer = (state: InitialStateType, action: ActionType) => {
|
|
|
92
95
|
return { ...state, items: newItems };
|
|
93
96
|
}
|
|
94
97
|
|
|
98
|
+
// Reset item back to its original container (e.g., when drag ends without valid drop)
|
|
99
|
+
case "RESET_DRAG_CONTAINER": {
|
|
100
|
+
const { itemId, originalContainer } = action.payload;
|
|
101
|
+
return {
|
|
102
|
+
...state,
|
|
103
|
+
items: state.items.map(item =>
|
|
104
|
+
item.id === itemId
|
|
105
|
+
? { ...item, container: originalContainer }
|
|
106
|
+
: item
|
|
107
|
+
)
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
95
111
|
default:
|
|
96
112
|
return state;
|
|
97
113
|
}
|
|
@@ -119,6 +135,19 @@ export const DraggableProvider = ({
|
|
|
119
135
|
enableCrossContainerPreview = false,
|
|
120
136
|
}: DraggableProviderType) => {
|
|
121
137
|
const [state, dispatch] = useReducer(reducer, initialState);
|
|
138
|
+
|
|
139
|
+
// Track drag state for global listener
|
|
140
|
+
const dragStateRef = useRef<{
|
|
141
|
+
isDragging: boolean;
|
|
142
|
+
draggedItemId: string;
|
|
143
|
+
originalContainer: string;
|
|
144
|
+
dropOccurred: boolean;
|
|
145
|
+
}>({
|
|
146
|
+
isDragging: false,
|
|
147
|
+
draggedItemId: '',
|
|
148
|
+
originalContainer: '',
|
|
149
|
+
dropOccurred: false,
|
|
150
|
+
});
|
|
122
151
|
|
|
123
152
|
// Parse dropZone prop - handle both string format (backward compatibility) and object format
|
|
124
153
|
let dropZoneType = 'ghost';
|
|
@@ -148,7 +177,94 @@ export const DraggableProvider = ({
|
|
|
148
177
|
onReorder(state.items);
|
|
149
178
|
}, [state.items]);
|
|
150
179
|
|
|
180
|
+
// Monitor for failed drops by detecting mouse/pointer release during drag (this is needed for cross container preview)
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
if (!enableCrossContainerPreview) return;
|
|
183
|
+
|
|
184
|
+
const handleGlobalMouseUp = () => {
|
|
185
|
+
// If we're dragging and mouse is released, wait a bit to see if drop occurs
|
|
186
|
+
if (dragStateRef.current.isDragging) {
|
|
187
|
+
setTimeout(() => {
|
|
188
|
+
// If drop still hasn't occurred, reset
|
|
189
|
+
if (dragStateRef.current.isDragging && !dragStateRef.current.dropOccurred) {
|
|
190
|
+
dispatch({
|
|
191
|
+
type: 'RESET_DRAG_CONTAINER',
|
|
192
|
+
payload: {
|
|
193
|
+
itemId: dragStateRef.current.draggedItemId,
|
|
194
|
+
originalContainer: dragStateRef.current.originalContainer,
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
|
|
198
|
+
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
|
|
199
|
+
dispatch({ type: 'SET_DRAG_DATA', payload: { id: "", initialGroup: "", originId: "" } });
|
|
200
|
+
|
|
201
|
+
// Clear drag state
|
|
202
|
+
dragStateRef.current = {
|
|
203
|
+
isDragging: false,
|
|
204
|
+
draggedItemId: '',
|
|
205
|
+
originalContainer: '',
|
|
206
|
+
dropOccurred: false,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
}, 50); // Small delay to let drop event fire if it's going to
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
document.addEventListener('mouseup', handleGlobalMouseUp);
|
|
214
|
+
document.addEventListener('pointerup', handleGlobalMouseUp);
|
|
215
|
+
|
|
216
|
+
return () => {
|
|
217
|
+
document.removeEventListener('mouseup', handleGlobalMouseUp);
|
|
218
|
+
document.removeEventListener('pointerup', handleGlobalMouseUp);
|
|
219
|
+
};
|
|
220
|
+
}, [enableCrossContainerPreview]);
|
|
221
|
+
|
|
222
|
+
// Detect when dragging stops (isDragging goes from truthy to empty)
|
|
223
|
+
const prevIsDraggingRef = useRef(state.isDragging);
|
|
224
|
+
|
|
225
|
+
useEffect(() => {
|
|
226
|
+
if (!enableCrossContainerPreview) return;
|
|
227
|
+
|
|
228
|
+
const wasDragging = prevIsDraggingRef.current;
|
|
229
|
+
const isNowDragging = state.isDragging;
|
|
230
|
+
|
|
231
|
+
// Drag just ended (was dragging, now not)
|
|
232
|
+
if (wasDragging && !isNowDragging) {
|
|
233
|
+
|
|
234
|
+
// If drop didn't occur, reset to original container
|
|
235
|
+
if (!dragStateRef.current.dropOccurred && dragStateRef.current.draggedItemId) {
|
|
236
|
+
dispatch({
|
|
237
|
+
type: 'RESET_DRAG_CONTAINER',
|
|
238
|
+
payload: {
|
|
239
|
+
itemId: dragStateRef.current.draggedItemId,
|
|
240
|
+
originalContainer: dragStateRef.current.originalContainer,
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Clear drag state
|
|
246
|
+
dragStateRef.current = {
|
|
247
|
+
isDragging: false,
|
|
248
|
+
draggedItemId: '',
|
|
249
|
+
originalContainer: '',
|
|
250
|
+
dropOccurred: false,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
prevIsDraggingRef.current = isNowDragging;
|
|
255
|
+
}, [state.isDragging, enableCrossContainerPreview]);
|
|
256
|
+
|
|
151
257
|
const handleDragStart = (id: string, container: string) => {
|
|
258
|
+
// Track drag in ref for global listener
|
|
259
|
+
if (enableCrossContainerPreview) {
|
|
260
|
+
dragStateRef.current = {
|
|
261
|
+
isDragging: true,
|
|
262
|
+
draggedItemId: id,
|
|
263
|
+
originalContainer: container,
|
|
264
|
+
dropOccurred: false,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
152
268
|
dispatch({ type: 'SET_DRAG_DATA', payload: { id: id, initialGroup: container, originId: providerId } });
|
|
153
269
|
dispatch({ type: 'SET_IS_DRAGGING', payload: id });
|
|
154
270
|
if (onDragStart) onDragStart(id, container);
|
|
@@ -202,9 +318,18 @@ export const DraggableProvider = ({
|
|
|
202
318
|
const draggedItemId = state.dragData.id;
|
|
203
319
|
const originalContainer = state.dragData.initialGroup;
|
|
204
320
|
|
|
321
|
+
// If enableCrossContainerPreview is true and no drop occurred, reset item to original container
|
|
322
|
+
if (enableCrossContainerPreview && !dropOccurred && draggedItemId && originalContainer) {
|
|
323
|
+
dispatch({ type: 'RESET_DRAG_CONTAINER', payload: { itemId: draggedItemId, originalContainer } });
|
|
324
|
+
}
|
|
325
|
+
|
|
205
326
|
dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
|
|
206
327
|
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
|
|
207
328
|
dispatch({ type: 'SET_DRAG_DATA', payload: { id: "", initialGroup: "", originId: "" } });
|
|
329
|
+
|
|
330
|
+
// Reset the drop flag
|
|
331
|
+
dropOccurred = false;
|
|
332
|
+
|
|
208
333
|
if (onDragEnd) {
|
|
209
334
|
if (!enableCrossContainerPreview) {
|
|
210
335
|
onDragEnd();
|
|
@@ -237,6 +362,11 @@ export const DraggableProvider = ({
|
|
|
237
362
|
|
|
238
363
|
const draggedItemId = state.dragData.id;
|
|
239
364
|
const originalContainer = state.dragData.initialGroup;
|
|
365
|
+
|
|
366
|
+
// Mark drop as successful in ref for global listener
|
|
367
|
+
if (enableCrossContainerPreview) {
|
|
368
|
+
dragStateRef.current.dropOccurred = true;
|
|
369
|
+
}
|
|
240
370
|
|
|
241
371
|
dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
|
|
242
372
|
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
|
|
@@ -96,20 +96,24 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
|
|
|
96
96
|
{hasAllEmptyProps && '—'}
|
|
97
97
|
{emphasis == 'street' && !hasAllEmptyProps &&
|
|
98
98
|
<div>
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
99
|
+
{(address || houseStyle) && (
|
|
100
|
+
<Title
|
|
101
|
+
className="pb_home_address_street_address"
|
|
102
|
+
dark={dark}
|
|
103
|
+
size={4}
|
|
104
|
+
>
|
|
105
|
+
{joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
|
|
106
|
+
</Title>
|
|
107
|
+
)}
|
|
108
|
+
{addressCont && (
|
|
109
|
+
<Title
|
|
110
|
+
className="pb_home_address_street_address"
|
|
111
|
+
dark={dark}
|
|
112
|
+
size={4}
|
|
113
|
+
>
|
|
114
|
+
{titleize(addressCont)}
|
|
115
|
+
</Title>
|
|
116
|
+
)}
|
|
113
117
|
<Body color="light">
|
|
114
118
|
{`${city ? `${titleize(city)}, ` : ''}${uppercaseState}${zipcode ? ` ${zipcode}` : ''}`}
|
|
115
119
|
</Body>
|
|
@@ -117,10 +121,14 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
|
|
|
117
121
|
}
|
|
118
122
|
{emphasis == 'city' && !hasAllEmptyProps &&
|
|
119
123
|
<div>
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
+
{(address || houseStyle) && (
|
|
125
|
+
<Body color="light">
|
|
126
|
+
{joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
|
|
127
|
+
</Body>
|
|
128
|
+
)}
|
|
129
|
+
{addressCont && (
|
|
130
|
+
<Body color="light">{titleize(addressCont)}</Body>
|
|
131
|
+
)}
|
|
124
132
|
<div>
|
|
125
133
|
<Title
|
|
126
134
|
className="pb_home_address_street_address"
|
|
@@ -141,10 +149,14 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
|
|
|
141
149
|
}
|
|
142
150
|
{emphasis == 'none' && !hasAllEmptyProps &&
|
|
143
151
|
<div>
|
|
144
|
-
|
|
145
|
-
{
|
|
146
|
-
|
|
147
|
-
|
|
152
|
+
{(address || houseStyle) && (
|
|
153
|
+
<Body dark={dark}>
|
|
154
|
+
{joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
|
|
155
|
+
</Body>
|
|
156
|
+
)}
|
|
157
|
+
{addressCont && (
|
|
158
|
+
<Body dark={dark}>{formatStreetAdr(addressCont)}</Body>
|
|
159
|
+
)}
|
|
148
160
|
<div>
|
|
149
161
|
<Body
|
|
150
162
|
color="light"
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
<% if object.address_house_style.present? %>
|
|
2
|
+
<%= pb_rails "body", props: {
|
|
3
|
+
classname: "pb_home_address_street_address",
|
|
4
|
+
color: "light",
|
|
5
|
+
text: object.address_house_style,
|
|
6
|
+
dark: object.dark
|
|
7
|
+
} %>
|
|
8
|
+
<% end %>
|
|
9
|
+
<% if object.address_house_style2.present? %>
|
|
10
|
+
<%= pb_rails "body", props: {
|
|
11
|
+
classname: "pb_home_address_street_address",
|
|
12
|
+
color: "light",
|
|
13
|
+
text: object.address_house_style2,
|
|
14
|
+
dark: object.dark
|
|
15
|
+
} %>
|
|
16
|
+
<% end %>
|
|
13
17
|
<div>
|
|
14
18
|
<%= pb_rails "title", props: {
|
|
15
19
|
tag: "span",
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
<% if object.address_house_style.present? %>
|
|
2
|
+
<%= pb_rails "body", props: {
|
|
3
|
+
classname: "pb_home_address_street_address",
|
|
4
|
+
size: 4,
|
|
5
|
+
text: object.address_house_style,
|
|
6
|
+
dark: object.dark
|
|
7
|
+
} %>
|
|
8
|
+
<% end %>
|
|
9
|
+
<% if object.address_house_style2.present? %>
|
|
10
|
+
<%= pb_rails "body", props: {
|
|
11
|
+
classname: "pb_home_address_street_address",
|
|
12
|
+
size: 4,
|
|
13
|
+
text: object.address_house_style2,
|
|
14
|
+
dark: object.dark
|
|
15
|
+
} %>
|
|
16
|
+
<% end %>
|
|
13
17
|
<%= pb_rails "body", props: {
|
|
14
18
|
color: "light",
|
|
15
19
|
text: object.city_state_zip,
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
<% if object.address_house_style.present? %>
|
|
2
|
+
<%= pb_rails "title", props: {
|
|
3
|
+
classname: "pb_home_address_street_address",
|
|
4
|
+
size: 4,
|
|
5
|
+
text: object.address_house_style,
|
|
6
|
+
dark: object.dark
|
|
7
|
+
} %>
|
|
8
|
+
<% end %>
|
|
9
|
+
<% if object.address_house_style2.present? %>
|
|
10
|
+
<%= pb_rails "title", props: {
|
|
11
|
+
classname: "pb_home_address_street_address",
|
|
12
|
+
size: 4,
|
|
13
|
+
text: object.address_house_style2,
|
|
14
|
+
dark: object.dark
|
|
15
|
+
} %>
|
|
16
|
+
<% end %>
|
|
13
17
|
<%= pb_rails "body", props: {
|
|
14
18
|
color: "light",
|
|
15
19
|
text: object.city_state_zip,
|
|
@@ -36,6 +36,16 @@ $pb_multiple_users_size_xxs: map-get($avatar-sizes, "xxs");
|
|
|
36
36
|
height: $pb_multiple_users_size_xxs;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
|
|
40
|
+
.user_tooltip {
|
|
41
|
+
margin-left: $pb_multiple_users_overlap !important;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.user_count_tooltip {
|
|
45
|
+
margin-left: $pb_multiple_users_overlap !important;
|
|
46
|
+
position: relative;
|
|
47
|
+
}
|
|
48
|
+
|
|
39
49
|
.pb_multiple_users_item {
|
|
40
50
|
margin-left: $pb_multiple_users_overlap;
|
|
41
51
|
margin-right: 0;
|
|
@@ -5,17 +5,19 @@ import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../uti
|
|
|
5
5
|
import { globalProps } from '../utilities/globalProps'
|
|
6
6
|
|
|
7
7
|
import Avatar from '../pb_avatar/_avatar'
|
|
8
|
+
import Tooltip from '../pb_tooltip/_tooltip'
|
|
8
9
|
|
|
9
10
|
type MultipleUsersProps = {
|
|
10
11
|
aria?: { [key: string]: string },
|
|
11
12
|
className?: string,
|
|
12
13
|
dark?: boolean,
|
|
13
14
|
data?: { [key: string]: string },
|
|
14
|
-
htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
|
|
15
|
+
htmlOptions?: { [key: string]: string | number | boolean | (() => void) },
|
|
15
16
|
id?: string,
|
|
16
17
|
maxDisplayedUsers?: number,
|
|
17
18
|
reverse?: boolean,
|
|
18
19
|
size?: "md" | "lg" | "sm" | "xl" | "xs" | "xxs",
|
|
20
|
+
withTooltip?: boolean,
|
|
19
21
|
users: Array<{ [key: string]: string }>,
|
|
20
22
|
}
|
|
21
23
|
|
|
@@ -30,6 +32,7 @@ const MultipleUsers = (props: MultipleUsersProps): React.ReactElement => {
|
|
|
30
32
|
maxDisplayedUsers = 4,
|
|
31
33
|
reverse = false,
|
|
32
34
|
size = 'xs',
|
|
35
|
+
withTooltip = false,
|
|
33
36
|
users,
|
|
34
37
|
} = props
|
|
35
38
|
|
|
@@ -62,22 +65,70 @@ const MultipleUsers = (props: MultipleUsersProps): React.ReactElement => {
|
|
|
62
65
|
className={classes}
|
|
63
66
|
id={id}
|
|
64
67
|
>
|
|
65
|
-
{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
68
|
+
{withTooltip ?
|
|
69
|
+
<>
|
|
70
|
+
{usersToDisplay.map((avatarData, index) => (
|
|
71
|
+
<Tooltip
|
|
72
|
+
key={"user_tooltip_" + index}
|
|
73
|
+
placement='top'
|
|
74
|
+
text={avatarData.tooltip ? avatarData.tooltip : ''}
|
|
75
|
+
zIndex={10}
|
|
76
|
+
>
|
|
77
|
+
<Avatar
|
|
78
|
+
{...avatarData}
|
|
79
|
+
className={"pb_multiple_users_item" + (withTooltip ? " user_tooltip" : "")}
|
|
80
|
+
dark={dark}
|
|
81
|
+
imageAlt={avatarData.name}
|
|
82
|
+
key={index}
|
|
83
|
+
size={size}
|
|
84
|
+
/>
|
|
85
|
+
</Tooltip>
|
|
86
|
+
))}
|
|
75
87
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
88
|
+
{users.length > maxDisplayedUsers &&
|
|
89
|
+
<Tooltip
|
|
90
|
+
placement='top'
|
|
91
|
+
text={
|
|
92
|
+
<div>
|
|
93
|
+
{
|
|
94
|
+
usersToDisplay.length < users.length ?
|
|
95
|
+
users.slice(displayCount).map((u, i) => (
|
|
96
|
+
<div key={i}>{u.tooltip}</div>
|
|
97
|
+
))
|
|
98
|
+
:
|
|
99
|
+
''
|
|
100
|
+
}
|
|
101
|
+
</div>
|
|
102
|
+
}
|
|
103
|
+
zIndex={10}
|
|
104
|
+
>
|
|
105
|
+
<div className={itemClasses + (withTooltip ? " user_count_tooltip" : "")}>
|
|
106
|
+
{`+${users.length - displayCount}`}
|
|
107
|
+
</div>
|
|
108
|
+
</Tooltip>
|
|
109
|
+
}
|
|
110
|
+
</>
|
|
111
|
+
:
|
|
112
|
+
<>
|
|
113
|
+
{usersToDisplay.map((avatarData, index) => (
|
|
114
|
+
<Avatar
|
|
115
|
+
{...avatarData}
|
|
116
|
+
className="pb_multiple_users_item"
|
|
117
|
+
dark={dark}
|
|
118
|
+
imageAlt={avatarData.name}
|
|
119
|
+
key={index}
|
|
120
|
+
size={size}
|
|
121
|
+
/>
|
|
122
|
+
))}
|
|
123
|
+
|
|
124
|
+
{users.length > maxDisplayedUsers &&
|
|
125
|
+
<div className={itemClasses}>
|
|
126
|
+
{`+${users.length - 3}`}
|
|
127
|
+
</div>
|
|
128
|
+
}
|
|
129
|
+
</>
|
|
80
130
|
}
|
|
131
|
+
|
|
81
132
|
</div>
|
|
82
133
|
)
|
|
83
134
|
}
|