playbook_ui 12.18.0 → 12.19.0.pre.alpha.PLAY603datepickerquickpickinputpresetdropdown638
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_date_picker/_date_picker.scss +26 -0
- data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +99 -95
- data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +3 -2
- data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +1 -1
- data/app/pb_kits/playbook/pb_date_picker/date_picker.test.js +44 -1
- data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +34 -2
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick.html.erb +8 -0
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick.jsx +18 -0
- data/app/pb_kits/playbook/pb_date_picker/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_date_picker/docs/index.js +2 -1
- data/app/pb_kits/playbook/pb_date_picker/plugins/quickPick.tsx +161 -0
- data/app/pb_kits/playbook/pb_date_picker/sass_partials/_calendar_input_icon.scss +3 -2
- data/app/pb_kits/playbook/pb_date_picker/sass_partials/_quick_pick_styles.scss +75 -0
- data/app/pb_kits/playbook/pb_nav/_item.tsx +1 -1
- data/app/pb_kits/playbook/pb_nav/_subtle_mixin.scss +1 -1
- data/app/pb_kits/playbook/pb_table/index.ts +6 -2
- data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +11 -10
- data/app/pb_kits/playbook/pb_tooltip/tooltip.test.jsx +29 -0
- data/app/pb_kits/playbook/tokens/_colors.scss +5 -3
- data/lib/playbook/version.rb +2 -2
- metadata +11 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 453164dea66b229cdd84038a46f6178bf1008bbf17b5838d2f319e94f1f8fd55
|
4
|
+
data.tar.gz: 8cec3bedef3f08dda63bae0c5faa319542743c9c0e9ebaeef085d868510925e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3982d4582e7c91ec22107b1bd2288f943dd22fe8d054060d56d4193e067a5041a0947e02a940f9873457c7566db4a1ec020858d2bee8aa78985e2430e7c7a6b
|
7
|
+
data.tar.gz: 4af1dfb8a83b8e74411aac7bf618f0f5f946facb7636e560eb87918aec8210ebb91a644d8ede92fbab461d61ba20d125f660a8f5497cd9fd8622af8e39dc2b72
|
@@ -6,6 +6,7 @@
|
|
6
6
|
@import "./sass_partials/month_and_year_styles";
|
7
7
|
@import "./sass_partials/time_selection_styles";
|
8
8
|
@import "./sass_partials/input_styles";
|
9
|
+
@import "./sass_partials/quick_pick_styles";
|
9
10
|
|
10
11
|
[class^=pb_date_picker_kit] {
|
11
12
|
.input_wrapper {
|
@@ -26,7 +27,32 @@
|
|
26
27
|
@include transition_default;
|
27
28
|
border-color: $primary;
|
28
29
|
}
|
30
|
+
.add-on-card {
|
31
|
+
border-color: $primary;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
@media (hover: hover) {
|
36
|
+
&:hover {
|
37
|
+
.add-on-card {
|
38
|
+
cursor: pointer;
|
39
|
+
background-color: rgba($focus_input_light,$opacity_5);
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
43
|
+
.text_input_wrapper_add_on .add-on-icon {
|
44
|
+
color: $text_lt_light
|
29
45
|
}
|
46
|
+
|
47
|
+
.text_input_wrapper_add_on .add-on-right .text_input{
|
48
|
+
cursor: pointer;
|
49
|
+
}
|
50
|
+
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
.pb_popover_reference_wrapper {
|
55
|
+
display: unset !important
|
30
56
|
}
|
31
57
|
|
32
58
|
.flatpickr-calendar {
|
@@ -30,7 +30,7 @@ type DatePickerProps = {
|
|
30
30
|
inputAria?: { [key: string]: string },
|
31
31
|
inputData?: { [key: string]: string },
|
32
32
|
inputOnChange?: (e: React.FormEvent<HTMLInputElement>) => void,
|
33
|
-
inputValue?:
|
33
|
+
inputValue?: string,
|
34
34
|
label?: string,
|
35
35
|
maxDate: string,
|
36
36
|
minDate: string,
|
@@ -39,7 +39,7 @@ type DatePickerProps = {
|
|
39
39
|
placeholder?: string,
|
40
40
|
positionElement?: HTMLElement | null,
|
41
41
|
scrollContainer?: string,
|
42
|
-
selectionType?: "month" | "week",
|
42
|
+
selectionType?: "month" | "week"| "quickpick",
|
43
43
|
showTimezone?: boolean,
|
44
44
|
staticPosition: boolean,
|
45
45
|
timeFormat?: string,
|
@@ -96,46 +96,46 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
|
|
96
96
|
const inputAriaProps = buildAriaProps(inputAria)
|
97
97
|
const inputDataProps = buildDataProps(inputData)
|
98
98
|
|
99
|
+
useEffect(() => {
|
100
|
+
datePickerHelper({
|
101
|
+
allowInput,
|
102
|
+
defaultDate,
|
103
|
+
disableDate,
|
104
|
+
disableRange,
|
105
|
+
disableWeekdays,
|
106
|
+
enableTime,
|
107
|
+
format,
|
108
|
+
hideIcon,
|
109
|
+
inLine,
|
110
|
+
maxDate,
|
111
|
+
minDate,
|
112
|
+
mode,
|
113
|
+
onChange,
|
114
|
+
onClose,
|
115
|
+
pickerId,
|
116
|
+
plugins,
|
117
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
118
|
+
// @ts-ignore
|
119
|
+
position,
|
120
|
+
positionElement,
|
121
|
+
selectionType,
|
122
|
+
showTimezone,
|
123
|
+
staticPosition,
|
124
|
+
yearRange,
|
125
|
+
required: false,
|
126
|
+
}, scrollContainer)
|
127
|
+
})
|
99
128
|
const filteredProps = {...props}
|
100
129
|
delete filteredProps?.position
|
101
130
|
|
102
131
|
const classes = classnames(
|
103
132
|
buildCss('pb_date_picker_kit'),
|
133
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
104
134
|
//@ts-ignore
|
105
135
|
globalProps(filteredProps),
|
106
136
|
error ? 'error' : null,
|
107
137
|
className
|
108
138
|
)
|
109
|
-
|
110
|
-
useEffect(() => {
|
111
|
-
datePickerHelper({
|
112
|
-
allowInput,
|
113
|
-
defaultDate,
|
114
|
-
disableDate,
|
115
|
-
disableRange,
|
116
|
-
disableWeekdays,
|
117
|
-
enableTime,
|
118
|
-
format,
|
119
|
-
hideIcon,
|
120
|
-
inLine,
|
121
|
-
maxDate,
|
122
|
-
minDate,
|
123
|
-
mode,
|
124
|
-
onChange,
|
125
|
-
onClose,
|
126
|
-
pickerId,
|
127
|
-
plugins,
|
128
|
-
// @ts-ignore
|
129
|
-
position,
|
130
|
-
positionElement,
|
131
|
-
selectionType,
|
132
|
-
showTimezone,
|
133
|
-
staticPosition,
|
134
|
-
yearRange,
|
135
|
-
required: false,
|
136
|
-
}, scrollContainer)
|
137
|
-
})
|
138
|
-
|
139
139
|
const iconWrapperClass = () => {
|
140
140
|
let base = 'cal_icon_wrapper'
|
141
141
|
if (dark) {
|
@@ -150,80 +150,84 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
|
|
150
150
|
return base
|
151
151
|
}
|
152
152
|
|
153
|
+
|
153
154
|
return (
|
154
155
|
<div
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
156
|
+
{...ariaProps}
|
157
|
+
{...dataProps}
|
158
|
+
className={classes}
|
159
|
+
id={id}
|
159
160
|
>
|
160
161
|
<div
|
161
|
-
|
162
|
-
|
163
|
-
|
162
|
+
{...inputAriaProps}
|
163
|
+
{...inputDataProps}
|
164
|
+
className="input_wrapper"
|
165
|
+
>
|
164
166
|
|
165
167
|
<Caption
|
166
|
-
|
167
|
-
|
168
|
+
className="pb_date_picker_kit_label"
|
169
|
+
text={hideLabel ? null : label}
|
168
170
|
/>
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
/>
|
181
|
-
|
182
|
-
{error && <Body
|
183
|
-
status="negative"
|
184
|
-
text={error}
|
185
|
-
variant={null}
|
186
|
-
/>
|
187
|
-
}
|
188
|
-
</div>
|
189
|
-
|
190
|
-
{!hideIcon &&
|
191
|
-
<div
|
192
|
-
className={iconWrapperClass()}
|
193
|
-
id={`cal-icon-${pickerId}`}
|
194
|
-
>
|
195
|
-
<Icon
|
196
|
-
className="cal_icon"
|
197
|
-
icon="calendar-alt"
|
198
|
-
/>
|
199
|
-
</div>
|
200
|
-
}
|
201
|
-
|
202
|
-
{hideIcon && inLine ?
|
203
|
-
<div>
|
204
|
-
<div
|
205
|
-
className={iconWrapperClass()}
|
206
|
-
id={`${pickerId}-icon-plus`}
|
207
|
-
>
|
208
|
-
<Icon
|
209
|
-
className="date-picker-plus-icon"
|
210
|
-
icon="plus"
|
211
|
-
/>
|
212
|
-
</div>
|
213
|
-
<div
|
214
|
-
className={iconWrapperClass()}
|
215
|
-
id={`${pickerId}-angle-down`}
|
216
|
-
>
|
217
|
-
<Icon
|
218
|
-
className="angle_down_icon"
|
219
|
-
icon="angle-down"
|
171
|
+
<>
|
172
|
+
<div className="date_picker_input_wrapper">
|
173
|
+
<input
|
174
|
+
autoComplete="off"
|
175
|
+
className="date_picker_input"
|
176
|
+
disabled={disableInput}
|
177
|
+
id={pickerId}
|
178
|
+
name={name}
|
179
|
+
onChange={inputOnChange}
|
180
|
+
placeholder={placeholder}
|
181
|
+
value={inputValue}
|
220
182
|
/>
|
183
|
+
|
184
|
+
{error &&
|
185
|
+
<Body
|
186
|
+
status="negative"
|
187
|
+
text={error}
|
188
|
+
variant={null}
|
189
|
+
/>
|
190
|
+
}
|
221
191
|
</div>
|
222
|
-
|
223
|
-
|
192
|
+
|
193
|
+
{!hideIcon &&
|
194
|
+
<div
|
195
|
+
className={iconWrapperClass()}
|
196
|
+
id={`cal-icon-${pickerId}`}
|
197
|
+
>
|
198
|
+
<Icon
|
199
|
+
className="cal_icon"
|
200
|
+
icon="calendar-alt"
|
201
|
+
/>
|
202
|
+
</div>
|
203
|
+
}
|
204
|
+
|
205
|
+
{hideIcon && inLine ?
|
206
|
+
<div>
|
207
|
+
<div
|
208
|
+
className={iconWrapperClass()}
|
209
|
+
id={`${pickerId}-icon-plus`}
|
210
|
+
>
|
211
|
+
<Icon
|
212
|
+
className="date-picker-plus-icon"
|
213
|
+
icon="plus"
|
214
|
+
/>
|
215
|
+
</div>
|
216
|
+
<div
|
217
|
+
className={iconWrapperClass()}
|
218
|
+
id={`${pickerId}-angle-down`}
|
219
|
+
>
|
220
|
+
<Icon
|
221
|
+
className="angle_down_icon"
|
222
|
+
icon="angle-down"
|
223
|
+
/>
|
224
|
+
</div>
|
225
|
+
</div>
|
226
|
+
: null
|
227
|
+
}
|
228
|
+
</>
|
224
229
|
</div>
|
225
230
|
</div>
|
226
231
|
)
|
227
232
|
}
|
228
|
-
|
229
233
|
export default DatePicker
|
@@ -61,7 +61,8 @@
|
|
61
61
|
|
62
62
|
<%= javascript_tag do %>
|
63
63
|
window.addEventListener("DOMContentLoaded", () => {
|
64
|
-
|
64
|
+
datePickerHelper(<%= object.date_picker_config %>, "<%= object.scroll_container %>")
|
65
65
|
})
|
66
|
+
|
66
67
|
<% end %>
|
67
|
-
<% end %>
|
68
|
+
<% end %>
|
@@ -51,7 +51,7 @@ module Playbook
|
|
51
51
|
prop :position_element, type: Playbook::Props::String
|
52
52
|
prop :scroll_container, type: Playbook::Props::String
|
53
53
|
prop :selection_type, type: Playbook::Props::Enum,
|
54
|
-
values: %w[week month none],
|
54
|
+
values: %w[week month quickpick none],
|
55
55
|
default: "none"
|
56
56
|
prop :show_timezone, type: Playbook::Props::Boolean,
|
57
57
|
default: false
|
@@ -1,5 +1,6 @@
|
|
1
1
|
/* eslint-disable no-console */
|
2
2
|
import React from 'react'
|
3
|
+
import moment from 'moment'
|
3
4
|
import { fireEvent, render, screen, waitFor, within } from '../utilities/test-utils'
|
4
5
|
|
5
6
|
import DatePicker from './_date_picker'
|
@@ -10,7 +11,6 @@ import { getTimezoneText } from './plugins/timeSelect'
|
|
10
11
|
jest.setSystemTime(new Date('01/01/2020'));
|
11
12
|
const DEFAULT_DATE = new Date()
|
12
13
|
|
13
|
-
|
14
14
|
describe('DatePicker Kit', () => {
|
15
15
|
beforeEach(() => {
|
16
16
|
jest.spyOn(console, 'error').mockImplementation(() => { });
|
@@ -158,4 +158,47 @@ describe('DatePicker Kit', () => {
|
|
158
158
|
expect(input).toHaveValue('01/01/2020 at 12:00 PM')
|
159
159
|
})
|
160
160
|
})
|
161
|
+
test('shows DatePicker QuickPick dropdown and adds correct date to input', async () => {
|
162
|
+
const testId = 'datepicker-quick-pick'
|
163
|
+
render(
|
164
|
+
<DatePicker
|
165
|
+
allowInput
|
166
|
+
data={{ testid: testId }}
|
167
|
+
mode="range"
|
168
|
+
pickerId="date-picker-quick-pick"
|
169
|
+
placeholder="mm/dd/yyyy → mm/dd/yyyy"
|
170
|
+
selectionType="quickpick"
|
171
|
+
/>
|
172
|
+
)
|
173
|
+
|
174
|
+
const kit = screen.getByTestId(testId)
|
175
|
+
const input = within(kit).getByPlaceholderText('mm/dd/yyyy → mm/dd/yyyy')
|
176
|
+
|
177
|
+
fireEvent(
|
178
|
+
input,
|
179
|
+
new MouseEvent('click', {
|
180
|
+
bubbles: true,
|
181
|
+
cancelable: true,
|
182
|
+
}),
|
183
|
+
)
|
184
|
+
const today = within(kit).getByText('Today')
|
185
|
+
const thisYear = within(kit).getByText('This year')
|
186
|
+
await waitFor(() => {
|
187
|
+
expect(today).toBeInTheDocument()
|
188
|
+
expect(thisYear).toBeInTheDocument()
|
189
|
+
})
|
190
|
+
|
191
|
+
fireEvent(
|
192
|
+
thisYear,
|
193
|
+
new MouseEvent('click', {
|
194
|
+
bubbles: true,
|
195
|
+
cancelable: true,
|
196
|
+
}),
|
197
|
+
)
|
198
|
+
|
199
|
+
await waitFor(() => {
|
200
|
+
expect(input).toHaveValue(moment().startOf('year').format('MM/DD/YYYY') + " → " + moment().format('MM/DD/YYYY'))
|
201
|
+
})
|
202
|
+
|
203
|
+
})
|
161
204
|
})
|
@@ -3,6 +3,7 @@ import { BaseOptions } from 'flatpickr/dist/types/options'
|
|
3
3
|
import monthSelectPlugin from 'flatpickr/dist/plugins/monthSelect'
|
4
4
|
import weekSelect from "flatpickr/dist/plugins/weekSelect/weekSelect"
|
5
5
|
import timeSelectPlugin from './plugins/timeSelect'
|
6
|
+
import quickPickPlugin from './plugins/quickPick'
|
6
7
|
|
7
8
|
const getPositionElement = (element: string | Element) => {
|
8
9
|
return (typeof element === 'string') ? document.querySelectorAll(element)[0] : element
|
@@ -19,8 +20,8 @@ type DatePickerConfig = {
|
|
19
20
|
hideIcon?: boolean;
|
20
21
|
inLine?: boolean,
|
21
22
|
onChange: (dateStr: string, selectedDates: Date[]) => void,
|
23
|
+
selectionType?: "month" | "week" | "quickpick" | "",
|
22
24
|
onClose: (dateStr: Date[] | string, selectedDates: Date[] | string) => void,
|
23
|
-
selectionType?: "month" | "week" | "",
|
24
25
|
showTimezone?: boolean,
|
25
26
|
staticPosition: boolean,
|
26
27
|
timeCaption?: string,
|
@@ -90,18 +91,23 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
|
|
90
91
|
}
|
91
92
|
|
92
93
|
const setPlugins = () => {
|
93
|
-
|
94
|
+
const pluginList = []
|
94
95
|
|
95
96
|
// month and week selection
|
96
97
|
if (selectionType === "month" || plugins.length > 0) {
|
97
98
|
pluginList.push(monthSelectPlugin({ shorthand: true, dateFormat: 'F Y', altFormat: 'F Y' }))
|
98
99
|
} else if ( selectionType === "week") {
|
99
100
|
pluginList.push(weekSelect())
|
101
|
+
|
102
|
+
} else if (selectionType === "quickpick") {
|
103
|
+
//------- QUICKPICK VARIANT PLUGIN -------------//
|
104
|
+
pluginList.push(quickPickPlugin())
|
100
105
|
}
|
101
106
|
|
102
107
|
// time selection
|
103
108
|
if (enableTime) pluginList.push(timeSelectPlugin({ caption: timeCaption, showTimezone: showTimezone}))
|
104
109
|
|
110
|
+
|
105
111
|
return pluginList
|
106
112
|
}
|
107
113
|
|
@@ -144,6 +150,9 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
|
|
144
150
|
},
|
145
151
|
] : disabledParser(),
|
146
152
|
enableTime,
|
153
|
+
locale: {
|
154
|
+
rangeSeparator: ' → '
|
155
|
+
},
|
147
156
|
maxDate,
|
148
157
|
minDate,
|
149
158
|
mode,
|
@@ -171,10 +180,33 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
|
|
171
180
|
static: staticPosition,
|
172
181
|
})
|
173
182
|
|
183
|
+
|
174
184
|
// ===========================================================
|
175
185
|
// Additional JS Functionality |
|
176
186
|
// ===========================================================
|
177
187
|
|
188
|
+
// opens flatpickr instance when calander icon is clicked so we can have a hover state on icon
|
189
|
+
// window.addEventListener("DOMContentLoaded", (event) => {
|
190
|
+
// event.preventDefault();
|
191
|
+
// function attachIconClickHandler() {
|
192
|
+
// const variantArr = document.querySelectorAll(`#cal-icon-${pickerId}`)
|
193
|
+
// if (!variantArr) {
|
194
|
+
// setTimeout(attachIconClickHandler, 100);
|
195
|
+
// return;
|
196
|
+
// }
|
197
|
+
|
198
|
+
// const instance = document.querySelector<HTMLElement & { [x: string]: any }>(`#${pickerId}`)._flatpickr
|
199
|
+
// variantArr.forEach((icon) => {
|
200
|
+
// icon.addEventListener("click", function(event) {
|
201
|
+
// event.preventDefault();
|
202
|
+
// instance.open()
|
203
|
+
// });
|
204
|
+
// })
|
205
|
+
// }
|
206
|
+
|
207
|
+
// attachIconClickHandler();
|
208
|
+
// });
|
209
|
+
|
178
210
|
// Assign dynamically sourced flatpickr instance to variable
|
179
211
|
const picker = document.querySelector<HTMLElement & { [x: string]: any }>(`#${pickerId}`)._flatpickr
|
180
212
|
picker.innerContainer.parentElement.id = `cal-${pickerId}`
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
|
3
|
+
import DatePicker from '../_date_picker'
|
4
|
+
|
5
|
+
const DatePickerQuickPick = (props) => (
|
6
|
+
<div>
|
7
|
+
<DatePicker
|
8
|
+
allowInput
|
9
|
+
mode="range"
|
10
|
+
pickerId="date-picker-quick-pick"
|
11
|
+
placeholder="mm/dd/yyyy → mm/dd/yyyy"
|
12
|
+
selectionType="quickpick"
|
13
|
+
{...props}
|
14
|
+
/>
|
15
|
+
</div>
|
16
|
+
)
|
17
|
+
|
18
|
+
export default DatePickerQuickPick
|
@@ -8,6 +8,7 @@ examples:
|
|
8
8
|
- date_picker_input: Input Field
|
9
9
|
- date_picker_label: Label
|
10
10
|
- date_picker_range: Range
|
11
|
+
- date_picker_quick_pick: Range (Quick Pick)
|
11
12
|
- date_picker_format: Format
|
12
13
|
- date_picker_disabled: Disabled Dates
|
13
14
|
- date_picker_min_max: Min Max
|
@@ -33,6 +34,7 @@ examples:
|
|
33
34
|
- date_picker_on_change: onChange
|
34
35
|
- date_picker_on_close: onClose
|
35
36
|
- date_picker_range: Range
|
37
|
+
- date_picker_quick_pick: Range (Quick Pick)
|
36
38
|
- date_picker_format: Format
|
37
39
|
- date_picker_disabled: Disabled Dates
|
38
40
|
- date_picker_min_max: Min Max
|
@@ -19,4 +19,5 @@ export { default as DatePickerWeek } from './_date_picker_week.jsx'
|
|
19
19
|
export { default as DatePickerPositions } from './_date_picker_positions.jsx'
|
20
20
|
export { default as DatePickerPositionsElement } from './_date_picker_positions_element.jsx'
|
21
21
|
export { default as DatePickerAllowInput } from './_date_picker_allow_input'
|
22
|
-
export { default as
|
22
|
+
export { default as DatePickerQuickPick } from './_date_picker_quick_pick'
|
23
|
+
export { default as DatePickerOnClose } from './_date_picker_on_close.jsx'
|
@@ -0,0 +1,161 @@
|
|
1
|
+
import moment from 'moment'
|
2
|
+
|
3
|
+
type FpTypes = {
|
4
|
+
setDate: (arg0: any, arg1: boolean) => void,
|
5
|
+
config: { [key: string]: string },
|
6
|
+
clear: (arg0: boolean, arg1: boolean) => void,
|
7
|
+
close: () => void,
|
8
|
+
calendarContainer?: {
|
9
|
+
classList: { add: (arg0: string) => void };
|
10
|
+
prepend: (arg0: HTMLDivElement) => void;
|
11
|
+
append: (arg0: HTMLDivElement) => void;
|
12
|
+
},
|
13
|
+
loadedPlugins: string[],
|
14
|
+
};
|
15
|
+
|
16
|
+
type pluginDataType = {
|
17
|
+
ranges: { [key: string]: Date[] },
|
18
|
+
rangesNav: HTMLUListElement,
|
19
|
+
rangesButtons: [] | any,
|
20
|
+
}
|
21
|
+
|
22
|
+
const quickPickPlugin = () => {
|
23
|
+
return function (fp: FpTypes & any): any {
|
24
|
+
|
25
|
+
let activeLabel = ""
|
26
|
+
|
27
|
+
// variable that holds the ranges available
|
28
|
+
const ranges = {
|
29
|
+
'Today': [new Date(), new Date()],
|
30
|
+
'Yesterday': [moment().subtract(1, 'days').toDate(), moment().subtract(1, 'days').toDate()],
|
31
|
+
'This week': [moment().startOf('week').toDate(), moment().endOf('week').toDate()],
|
32
|
+
'This month': [moment().startOf('month').toDate(), new Date()],
|
33
|
+
'This quarter': [moment().startOf('quarter').toDate(), new Date()],
|
34
|
+
'This year': [moment().startOf('year').toDate(), new Date()],
|
35
|
+
'Last week': [
|
36
|
+
moment().subtract(1, 'week').startOf('week').toDate(),
|
37
|
+
moment().subtract(1, 'week').endOf('week').toDate()
|
38
|
+
],
|
39
|
+
'Last month': [
|
40
|
+
moment().subtract(1, 'month').startOf('month').toDate(),
|
41
|
+
moment().subtract(1, 'month').endOf('month').toDate()
|
42
|
+
],
|
43
|
+
'Last quarter': [
|
44
|
+
moment().subtract(1, 'quarter').startOf('quarter').toDate(),
|
45
|
+
moment().subtract(1, 'quarter').endOf('quarter').toDate()
|
46
|
+
],
|
47
|
+
'Last year': [
|
48
|
+
moment().subtract(1, 'year').startOf('year').toDate(),
|
49
|
+
moment().subtract(1, 'year').endOf('year').toDate()
|
50
|
+
]
|
51
|
+
}
|
52
|
+
//creating the ul element for the nav dropdown and giving it classnames
|
53
|
+
const rangesNav = document.createElement('ul');
|
54
|
+
|
55
|
+
// creating the pluginData object that will hold the properties of this plugin
|
56
|
+
const pluginData: pluginDataType = {
|
57
|
+
ranges: ranges,
|
58
|
+
rangesNav: rangesNav,
|
59
|
+
rangesButtons: [],
|
60
|
+
};
|
61
|
+
|
62
|
+
/**
|
63
|
+
* @param {string} label
|
64
|
+
* @returns HTML Element
|
65
|
+
*/
|
66
|
+
|
67
|
+
//funciton for creating the range buttons in the nav
|
68
|
+
const addRangeButton = (label: string) => {
|
69
|
+
|
70
|
+
// creating new elements to mimick selectable card component
|
71
|
+
const div2 = document.createElement('div');
|
72
|
+
div2.className = "nav-item-link"
|
73
|
+
div2.innerHTML = label;
|
74
|
+
|
75
|
+
pluginData.rangesButtons[label] = div2;
|
76
|
+
|
77
|
+
// create li elements inside the dropdown
|
78
|
+
const item = document.createElement('li');
|
79
|
+
item.className = "nav-item";
|
80
|
+
|
81
|
+
// append those nav items to the li items
|
82
|
+
item.appendChild(pluginData.rangesButtons[label]);
|
83
|
+
|
84
|
+
// append the li item to the ul rangeNav prop
|
85
|
+
pluginData.rangesNav.appendChild(item);
|
86
|
+
|
87
|
+
// return the ranges buton prop
|
88
|
+
return pluginData.rangesButtons[label];
|
89
|
+
};
|
90
|
+
|
91
|
+
const selectActiveRangeButton = (selectedDates: Array<string>) => {
|
92
|
+
const current = pluginData.rangesNav.querySelector('.active');
|
93
|
+
|
94
|
+
if (current) {
|
95
|
+
current.classList.remove('active');
|
96
|
+
}
|
97
|
+
/** conditional statment to extract start and end dates from selectedDates,
|
98
|
+
* then loop through ranges prop in pluginData
|
99
|
+
* and check if chosen dates equal to a date in the ranges prop
|
100
|
+
* if they are equal, add the active class
|
101
|
+
*/
|
102
|
+
if (selectedDates.length > 0) {
|
103
|
+
pluginData.rangesButtons[activeLabel].classList.add('active');
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
|
108
|
+
return {
|
109
|
+
// onReady is a hook from flatpickr that runs when calender is in a ready state
|
110
|
+
onReady(selectedDates: Array<string>) {
|
111
|
+
// loop through the ranges and create an anchor tag for each range and add an event listiner to set the date when user clicks on a date range
|
112
|
+
for (const [label, range] of Object.entries(pluginData.ranges)) {
|
113
|
+
addRangeButton(label).addEventListener('click', function () {
|
114
|
+
|
115
|
+
const start = moment(range[0]).toDate();
|
116
|
+
const end = moment(range[1]).toDate();
|
117
|
+
|
118
|
+
if (!start) {
|
119
|
+
fp.clear();
|
120
|
+
}
|
121
|
+
else {
|
122
|
+
activeLabel = label
|
123
|
+
fp.setDate([start, end], true);
|
124
|
+
fp.close();
|
125
|
+
}
|
126
|
+
|
127
|
+
});
|
128
|
+
}
|
129
|
+
|
130
|
+
// conditional to check if there is a dropdown to add it to the calendar container and git it the classes it needs
|
131
|
+
if (pluginData.rangesNav.children.length > 0) {
|
132
|
+
|
133
|
+
fp.calendarContainer.prepend(pluginData.rangesNav);
|
134
|
+
pluginData.rangesNav.classList.add('quick-pick-ul')
|
135
|
+
fp.calendarContainer.classList.add('quick-pick-drop-down');
|
136
|
+
|
137
|
+
/**
|
138
|
+
*
|
139
|
+
* @param {Array} selectedDates
|
140
|
+
*/
|
141
|
+
|
142
|
+
// function to give the active butto the active class
|
143
|
+
selectActiveRangeButton(selectedDates);
|
144
|
+
}
|
145
|
+
|
146
|
+
},
|
147
|
+
onValueUpdate(selectedDates: Array<string>) {
|
148
|
+
selectActiveRangeButton(selectedDates);
|
149
|
+
},
|
150
|
+
|
151
|
+
// onClose(selectedDates: Array<string>) {
|
152
|
+
// // set the input value to the selected dates when the dropdown is closed
|
153
|
+
// // if (!selectedDates[1]) {
|
154
|
+
// // fp.input.value = fp.formatDate(this.selectedDates[0], fp.config.dateFormat) + ' → ' + fp.formatDate(this.selectedDates[1], fp.config.dateFormat);
|
155
|
+
// // }
|
156
|
+
// }
|
157
|
+
};
|
158
|
+
};
|
159
|
+
}
|
160
|
+
|
161
|
+
export default quickPickPlugin;
|
@@ -1,3 +1,4 @@
|
|
1
|
+
@import "../../tokens/colors";
|
1
2
|
// Calendar Icon Styles
|
2
3
|
.cal_icon_wrapper {
|
3
4
|
pointer-events: none;
|
@@ -13,8 +14,8 @@
|
|
13
14
|
padding-left: $space_sm - 1;
|
14
15
|
color: $text_lt_light;
|
15
16
|
@media (hover: hover) {
|
16
|
-
&:hover
|
17
|
-
|
17
|
+
&:hover{
|
18
|
+
background-color: rgba($focus_input_light,$opacity_5);
|
18
19
|
}
|
19
20
|
}
|
20
21
|
&.dark {
|
@@ -0,0 +1,75 @@
|
|
1
|
+
@import "../../tokens/animation-curves";
|
2
|
+
@import "../../tokens/colors";
|
3
|
+
@import "../../tokens/typography";
|
4
|
+
@import "../../tokens/titles";
|
5
|
+
@import "../../tokens/spacing";
|
6
|
+
|
7
|
+
$pb_card_border_width: 1px;
|
8
|
+
$pb_card_border_radius: $border_rad_heavier;
|
9
|
+
|
10
|
+
// used to display dropdown on the left of the calender
|
11
|
+
.quick-pick-drop-down {
|
12
|
+
width: auto;
|
13
|
+
display: grid;
|
14
|
+
}
|
15
|
+
|
16
|
+
.quick-pick-ul {
|
17
|
+
padding: $space_xs 0px;
|
18
|
+
margin: 0;
|
19
|
+
list-style: none;
|
20
|
+
}
|
21
|
+
|
22
|
+
.nav-item {
|
23
|
+
list-style: none;
|
24
|
+
border-radius: 6px;
|
25
|
+
border-bottom: 0;
|
26
|
+
margin: $space_xs $space_sm;
|
27
|
+
}
|
28
|
+
|
29
|
+
.nav-item-link {
|
30
|
+
text-decoration: none;
|
31
|
+
border-width: $pb_card_border_width;
|
32
|
+
border-style: solid;
|
33
|
+
border-color: $border_light;
|
34
|
+
border-radius: $pb_card_border_radius;
|
35
|
+
padding: $space_xs 14px;
|
36
|
+
transition-property: color, background-color;
|
37
|
+
transition-duration: 0.15s;
|
38
|
+
transition-timing-function: $bezier;
|
39
|
+
line-height: 1.4;
|
40
|
+
color: $charcoal;
|
41
|
+
font-size: $font_default;
|
42
|
+
font-weight: $regular;
|
43
|
+
&.active {
|
44
|
+
border-width: 2px;
|
45
|
+
border-color: $primary;
|
46
|
+
}
|
47
|
+
@media (hover:hover) {
|
48
|
+
&:hover {
|
49
|
+
cursor: pointer;
|
50
|
+
box-shadow: $shadow-deep;
|
51
|
+
border-color: $slate;
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
// Hide the calendar
|
57
|
+
.quick-pick-drop-down > .flatpickr-months, .quick-pick-drop-down > .flatpickr-innerContainer {
|
58
|
+
display: none;
|
59
|
+
}
|
60
|
+
|
61
|
+
@media only screen and (max-width: 767px) {
|
62
|
+
.quick-pick-ul {
|
63
|
+
padding: $space_xs $space_xs;
|
64
|
+
display: grid;
|
65
|
+
grid-template-columns: 1fr 1fr;
|
66
|
+
}
|
67
|
+
|
68
|
+
.nav-item {
|
69
|
+
margin: $space_xxs $space_xs;
|
70
|
+
}
|
71
|
+
|
72
|
+
.nav-item-link {
|
73
|
+
padding: $space_xs $space_xxs;
|
74
|
+
}
|
75
|
+
}
|
@@ -11,8 +11,12 @@ export default class PbTable extends PbEnhancedElement {
|
|
11
11
|
// Each Table
|
12
12
|
[].forEach.call(tables, (table: HTMLTableElement) => {
|
13
13
|
// Header Titles
|
14
|
-
|
15
|
-
|
14
|
+
let headers: string[] = [];
|
15
|
+
[].forEach.call(table.querySelectorAll('th'), (header: HTMLTableCellElement) => {
|
16
|
+
let colSpan = header.colSpan
|
17
|
+
for (let i = 0; i < colSpan; i++) {
|
18
|
+
headers.push(header.textContent.replace(/\r?\n|\r/, ''));
|
19
|
+
}
|
16
20
|
});
|
17
21
|
|
18
22
|
// for each row in tbody
|
@@ -6,7 +6,7 @@ import {
|
|
6
6
|
offset,
|
7
7
|
Placement,
|
8
8
|
safePolygon,
|
9
|
-
shift,
|
9
|
+
shift,
|
10
10
|
useFloating,
|
11
11
|
useHover,
|
12
12
|
useInteractions,
|
@@ -17,9 +17,6 @@ import { GlobalProps, globalProps } from "../utilities/globalProps"
|
|
17
17
|
import { buildAriaProps, buildDataProps } from "../utilities/props"
|
18
18
|
import Flex from "../pb_flex/_flex"
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
20
|
type TooltipProps = {
|
24
21
|
aria?: { [key: string]: string },
|
25
22
|
className?: string | string[],
|
@@ -29,8 +26,8 @@ type TooltipProps = {
|
|
29
26
|
icon?: string,
|
30
27
|
interaction?: boolean,
|
31
28
|
placement?: Placement,
|
29
|
+
position?: "absolute" | "fixed";
|
32
30
|
text: string,
|
33
|
-
zIndex?: Pick<GlobalProps, "ZIndex">,
|
34
31
|
} & GlobalProps
|
35
32
|
|
36
33
|
const Tooltip = (props: TooltipProps): React.ReactElement => {
|
@@ -43,6 +40,7 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
|
|
43
40
|
icon = null,
|
44
41
|
interaction = false,
|
45
42
|
placement: preferredPlacement = "top",
|
43
|
+
position = "absolute",
|
46
44
|
text,
|
47
45
|
zIndex,
|
48
46
|
...rest
|
@@ -50,24 +48,26 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
|
|
50
48
|
|
51
49
|
const dataProps: { [key: string]: any } = buildDataProps(data)
|
52
50
|
const ariaProps: { [key: string]: any } = buildAriaProps(aria)
|
53
|
-
|
51
|
+
|
54
52
|
const css = classnames(
|
55
53
|
globalProps({...rest}),
|
56
54
|
className,
|
57
55
|
)
|
58
56
|
const [open, setOpen] = useState(false)
|
59
57
|
const arrowRef = useRef(null)
|
60
|
-
const {
|
61
58
|
|
59
|
+
|
60
|
+
const {
|
62
61
|
context,
|
63
62
|
floating,
|
64
|
-
middlewareData: { arrow: { x: arrowX, y: arrowY } = {}
|
63
|
+
middlewareData: { arrow: { x: arrowX, y: arrowY } = {}, },
|
65
64
|
placement,
|
66
65
|
reference,
|
67
66
|
strategy,
|
68
67
|
x,
|
69
68
|
y,
|
70
69
|
} = useFloating({
|
70
|
+
strategy: position,
|
71
71
|
middleware: [
|
72
72
|
arrow({
|
73
73
|
element: arrowRef,
|
@@ -87,6 +87,7 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
|
|
87
87
|
placement: preferredPlacement
|
88
88
|
})
|
89
89
|
|
90
|
+
|
90
91
|
const { getFloatingProps } = useInteractions([
|
91
92
|
useHover(context, {
|
92
93
|
delay,
|
@@ -142,7 +143,7 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
|
|
142
143
|
className="arrow_bg"
|
143
144
|
ref={arrowRef}
|
144
145
|
style={{
|
145
|
-
position:
|
146
|
+
position: "absolute",
|
146
147
|
left: arrowX != null ? `${arrowX}px` : "",
|
147
148
|
top: arrowY != null ? `${arrowY}px` : "",
|
148
149
|
[staticSide]: "-5px",
|
@@ -154,4 +155,4 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
|
|
154
155
|
)
|
155
156
|
}
|
156
157
|
|
157
|
-
export default Tooltip
|
158
|
+
export default Tooltip
|
@@ -65,3 +65,32 @@ test("closes on mouseleave", async () => {
|
|
65
65
|
|
66
66
|
cleanup();
|
67
67
|
});
|
68
|
+
|
69
|
+
test("has default position absolute", async () => {
|
70
|
+
render(<TooltipTest />);
|
71
|
+
|
72
|
+
fireEvent.mouseEnter(screen.getByRole("tooltip_trigger"));
|
73
|
+
await waitFor(() => {
|
74
|
+
expect(screen.queryByRole("tooltip")).toHaveStyle({"position": "absolute"});
|
75
|
+
cleanup();
|
76
|
+
})
|
77
|
+
|
78
|
+
cleanup();
|
79
|
+
});
|
80
|
+
|
81
|
+
test("has position fixed", async () => {
|
82
|
+
render(
|
83
|
+
<Tooltip
|
84
|
+
data={{ testid: "fixed-position-test" }}
|
85
|
+
position="fixed"
|
86
|
+
/>
|
87
|
+
);
|
88
|
+
|
89
|
+
fireEvent.mouseEnter(screen.getByRole("tooltip_trigger"));
|
90
|
+
await waitFor(() => {
|
91
|
+
expect(screen.queryByRole("tooltip")).toHaveStyle({"position": "fixed"});
|
92
|
+
cleanup();
|
93
|
+
})
|
94
|
+
|
95
|
+
cleanup();
|
96
|
+
});
|
@@ -68,7 +68,7 @@ $background_colors: (
|
|
68
68
|
|
69
69
|
/* Card colors ------------------*/
|
70
70
|
$card_light: $white !default;
|
71
|
-
$card_dark:
|
71
|
+
$card_dark: mix(white, $bg_dark, 10%) !default;
|
72
72
|
$card_colors: (
|
73
73
|
card_light: $card_light,
|
74
74
|
card_dark: $card_dark
|
@@ -109,16 +109,18 @@ $focus_input_colors: (
|
|
109
109
|
|
110
110
|
/* Border colors ----------------------*/
|
111
111
|
$border_light: #E4E8F0 !default;
|
112
|
-
$border_dark:
|
112
|
+
$border_dark: mix(white, $bg_dark, 20%) !default;
|
113
113
|
$border_colors: (
|
114
114
|
border_light: $border_light,
|
115
115
|
border_dark: $border_dark
|
116
116
|
);
|
117
117
|
|
118
118
|
/* Shadow colors ----------------------*/
|
119
|
-
$shadow:
|
119
|
+
$shadow: rgba(#3C6AAC, $opacity_2) !default;
|
120
|
+
$shadow_dark: $bg_dark !default;
|
120
121
|
$shadow_colors: (
|
121
122
|
shadow: $shadow,
|
123
|
+
shadow_dark: $shadow_dark,
|
122
124
|
);
|
123
125
|
|
124
126
|
/* Text colors ------------------------*/
|
data/lib/playbook/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: playbook_ui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 12.
|
4
|
+
version: 12.19.0.pre.alpha.PLAY603datepickerquickpickinputpresetdropdown638
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Power UX
|
8
8
|
- Power Devs
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-05-
|
12
|
+
date: 2023-05-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: actionpack
|
@@ -745,6 +745,8 @@ files:
|
|
745
745
|
- app/pb_kits/playbook/pb_date_picker/docs/_date_picker_positions.md
|
746
746
|
- app/pb_kits/playbook/pb_date_picker/docs/_date_picker_positions_element.html.erb
|
747
747
|
- app/pb_kits/playbook/pb_date_picker/docs/_date_picker_positions_element.jsx
|
748
|
+
- app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick.html.erb
|
749
|
+
- app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick.jsx
|
748
750
|
- app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range.html.erb
|
749
751
|
- app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range.jsx
|
750
752
|
- app/pb_kits/playbook/pb_date_picker/docs/_date_picker_time.html.erb
|
@@ -759,6 +761,7 @@ files:
|
|
759
761
|
- app/pb_kits/playbook/pb_date_picker/docs/_description.md
|
760
762
|
- app/pb_kits/playbook/pb_date_picker/docs/example.yml
|
761
763
|
- app/pb_kits/playbook/pb_date_picker/docs/index.js
|
764
|
+
- app/pb_kits/playbook/pb_date_picker/plugins/quickPick.tsx
|
762
765
|
- app/pb_kits/playbook/pb_date_picker/plugins/timeSelect.ts
|
763
766
|
- app/pb_kits/playbook/pb_date_picker/sass_partials/_calendar_input_icon.scss
|
764
767
|
- app/pb_kits/playbook/pb_date_picker/sass_partials/_day_styles.scss
|
@@ -768,6 +771,7 @@ files:
|
|
768
771
|
- app/pb_kits/playbook/pb_date_picker/sass_partials/_input_styles.scss
|
769
772
|
- app/pb_kits/playbook/pb_date_picker/sass_partials/_month_and_year_styles.scss
|
770
773
|
- app/pb_kits/playbook/pb_date_picker/sass_partials/_overrides.scss
|
774
|
+
- app/pb_kits/playbook/pb_date_picker/sass_partials/_quick_pick_styles.scss
|
771
775
|
- app/pb_kits/playbook/pb_date_picker/sass_partials/_time_selection_styles.scss
|
772
776
|
- app/pb_kits/playbook/pb_date_picker/sass_partials/_week_styles.scss
|
773
777
|
- app/pb_kits/playbook/pb_date_range_inline/_date_range_inline.scss
|
@@ -2485,7 +2489,7 @@ homepage: http://playbook.powerapp.cloud
|
|
2485
2489
|
licenses:
|
2486
2490
|
- ISC
|
2487
2491
|
metadata: {}
|
2488
|
-
post_install_message:
|
2492
|
+
post_install_message:
|
2489
2493
|
rdoc_options: []
|
2490
2494
|
require_paths:
|
2491
2495
|
- lib
|
@@ -2496,12 +2500,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
2496
2500
|
version: '0'
|
2497
2501
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
2498
2502
|
requirements:
|
2499
|
-
- - "
|
2503
|
+
- - ">"
|
2500
2504
|
- !ruby/object:Gem::Version
|
2501
|
-
version:
|
2505
|
+
version: 1.3.1
|
2502
2506
|
requirements: []
|
2503
2507
|
rubygems_version: 3.3.7
|
2504
|
-
signing_key:
|
2508
|
+
signing_key:
|
2505
2509
|
specification_version: 4
|
2506
2510
|
summary: Playbook Design System
|
2507
2511
|
test_files: []
|