playbook_ui 13.2.0 → 13.4.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.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/_playbook.scss +1 -0
- data/app/pb_kits/playbook/pb_body/_body.scss +5 -0
- data/app/pb_kits/playbook/pb_body/_body.tsx +4 -1
- data/app/pb_kits/playbook/pb_body/_body_mixins.scss +19 -0
- data/app/pb_kits/playbook/pb_body/body.rb +8 -1
- data/app/pb_kits/playbook/pb_button/button.html.erb +2 -2
- data/app/pb_kits/playbook/pb_button/button.rb +3 -0
- data/app/pb_kits/playbook/pb_collapsible/child_kits/CollapsibleMain.tsx +5 -1
- data/app/pb_kits/playbook/pb_kit/dateTime.ts +54 -23
- data/app/pb_kits/playbook/pb_table/docs/_table_header.html.erb +54 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_header.md +1 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_two_actions.jsx +3 -3
- data/app/pb_kits/playbook/pb_table/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_table/styles/_all.scss +1 -0
- data/app/pb_kits/playbook/pb_table/styles/_table_header.scss +31 -0
- data/app/pb_kits/playbook/pb_table/table_header.html.erb +64 -0
- data/app/pb_kits/playbook/pb_table/table_header.rb +53 -0
- data/app/pb_kits/playbook/pb_timestamp/_timestamp.tsx +14 -7
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_unstyled.html.erb +21 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_unstyled.jsx +36 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_unstyled.md +1 -0
- data/app/pb_kits/playbook/pb_timestamp/docs/example.yml +3 -1
- data/app/pb_kits/playbook/pb_timestamp/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_timestamp/timestamp.html.erb +5 -1
- data/app/pb_kits/playbook/pb_timestamp/timestamp.rb +3 -1
- data/app/pb_kits/playbook/pb_title/_title.scss +8 -4
- data/app/pb_kits/playbook/pb_title/_title.tsx +4 -1
- data/app/pb_kits/playbook/pb_title/_title_mixin.scss +19 -0
- data/app/pb_kits/playbook/pb_title/title.rb +9 -2
- data/app/pb_kits/playbook/tokens/_spacing.scss +1 -1
- data/app/pb_kits/playbook/tokens/_text_align.scss +18 -0
- data/app/pb_kits/playbook/utilities/_hover.scss +4 -0
- data/app/pb_kits/playbook/utilities/_max_width.scss +4 -0
- data/app/pb_kits/playbook/utilities/_spacing.scss +92 -49
- data/app/pb_kits/playbook/utilities/_text_align.scss +3 -0
- data/app/pb_kits/playbook/utilities/globalProps.ts +30 -2
- data/dist/playbook-rails.js +5 -5
- data/lib/playbook/classnames.rb +1 -0
- data/lib/playbook/hover.rb +6 -2
- data/lib/playbook/kit_base.rb +2 -0
- data/lib/playbook/spacing.rb +13 -4
- data/lib/playbook/text_align.rb +37 -0
- data/lib/playbook/version.rb +2 -2
- metadata +13 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4de8135dcb47909b6c71e27192382cc5ab8890bc54c6e1d5cb4c624553cc65a2
|
4
|
+
data.tar.gz: c3dd0cd17ad4319288dc8c7b16f2d93147ed8b5a04d33b8ecd8876bebc97f221
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a20fc82e7400098302e5e929cb70ad54a4c2360db26f42f2e38fdacb4bec2625528838b043695a6ba3c133c8f23553ccebeda91ab0f551b5d5032335cac1f682
|
7
|
+
data.tar.gz: 4554d268f82cf779641860ea89b2ceebb194b407dc6a30374e762e207b9e2094c9d63dee0669494be80815d4ec663d0e503ef3b58138c9bf8923090aa6bdfc03
|
@@ -37,10 +37,15 @@
|
|
37
37
|
font-size: $font_smaller;
|
38
38
|
letter-spacing: $lspace_loose;
|
39
39
|
}
|
40
|
+
|
41
|
+
&[class*=_truncate] {
|
42
|
+
@include body_truncate;
|
43
|
+
}
|
40
44
|
|
41
45
|
@each $status_name, $status_value in $pb_body_status {
|
42
46
|
&[class*=#{$status_name}] {
|
43
47
|
@include pb_body($status_value);
|
48
|
+
@include body_truncate;
|
44
49
|
}
|
45
50
|
}
|
46
51
|
|
@@ -19,6 +19,7 @@ type BodyProps = {
|
|
19
19
|
status?: 'neutral' | 'negative' | 'positive',
|
20
20
|
tag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span' | 'div',
|
21
21
|
text?: string,
|
22
|
+
truncate?: null | '1' | '2' | '3' | '4' | '5',
|
22
23
|
variant?: null | 'link',
|
23
24
|
} & GlobalProps
|
24
25
|
|
@@ -36,13 +37,15 @@ const Body = (props: BodyProps): React.ReactElement => {
|
|
36
37
|
status = null,
|
37
38
|
tag = 'div',
|
38
39
|
text = '',
|
40
|
+
truncate = null,
|
39
41
|
variant = null,
|
40
42
|
} = props
|
41
43
|
|
42
44
|
const ariaProps: {[key: string]: any} = buildAriaProps(aria)
|
43
45
|
const dataProps: {[key: string]: any} = buildDataProps(data)
|
46
|
+
const isTruncated = truncate ? `truncate_${truncate}` : ''
|
44
47
|
const classes = classnames(
|
45
|
-
buildCss('pb_body_kit', color, variant, status),
|
48
|
+
buildCss('pb_body_kit', color, variant, status, isTruncated),
|
46
49
|
globalProps(props),
|
47
50
|
className
|
48
51
|
)
|
@@ -36,6 +36,25 @@ $pb_body_status: (
|
|
36
36
|
font-family: $font-family-base;
|
37
37
|
}
|
38
38
|
|
39
|
+
$pb_body_truncate: (
|
40
|
+
truncate_1: 1,
|
41
|
+
truncate_2: 2,
|
42
|
+
truncate_3: 3,
|
43
|
+
truncate_4: 4,
|
44
|
+
truncate_5: 5
|
45
|
+
);
|
46
|
+
|
47
|
+
@mixin body_truncate {
|
48
|
+
@each $name, $number in $pb_body_truncate {
|
49
|
+
&[class*=_#{$name}] {
|
50
|
+
overflow: hidden;
|
51
|
+
display: -webkit-box;
|
52
|
+
-webkit-line-clamp: $number;
|
53
|
+
-webkit-box-orient: vertical;
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
39
58
|
|
40
59
|
// Colors ======================
|
41
60
|
@mixin pb_body_light {
|
@@ -18,9 +18,12 @@ module Playbook
|
|
18
18
|
default: false
|
19
19
|
prop :highlighted_text, type: Playbook::Props::Array,
|
20
20
|
default: []
|
21
|
+
prop :truncate, type: Playbook::Props::Enum,
|
22
|
+
values: [nil, "1", "2", "3", "4", "5"],
|
23
|
+
default: nil
|
21
24
|
|
22
25
|
def classname
|
23
|
-
generate_classname("pb_body_kit", color_class, status_class)
|
26
|
+
generate_classname("pb_body_kit", color_class, status_class, is_truncated)
|
24
27
|
end
|
25
28
|
|
26
29
|
def content
|
@@ -28,6 +31,10 @@ module Playbook
|
|
28
31
|
highlighting ? apply_highlight(body_text) : body_text
|
29
32
|
end
|
30
33
|
|
34
|
+
def is_truncated
|
35
|
+
truncate ? "truncate_#{truncate}" : nil
|
36
|
+
end
|
37
|
+
|
31
38
|
private
|
32
39
|
|
33
40
|
def apply_highlight(text)
|
@@ -18,14 +18,14 @@
|
|
18
18
|
<% else %>
|
19
19
|
<% if object.icon && !object.icon_right %>
|
20
20
|
<span>
|
21
|
-
<%= pb_rails("icon", props: { icon: "#{icon}", fixed_width: true, margin_right: "xs" }) %>
|
21
|
+
<%= pb_rails("icon", props: { icon: "#{icon}", fixed_width: true, margin_right: "xs", font_style: object.icon_font_family }) %>
|
22
22
|
</span>
|
23
23
|
<% end %>
|
24
24
|
<%= pb_rails("icon", props: { icon: "spinner", pulse: true, fixed_width: true, classname: "loading-icon" }) %>
|
25
25
|
<span class="pb_button_content"><%= content.presence || object.text %></span>
|
26
26
|
<% if object.icon && object.icon_right %>
|
27
27
|
<span>
|
28
|
-
<%= pb_rails("icon", props: { icon: "#{icon}", fixed_width: true, margin_left: "xs" }) %>
|
28
|
+
<%= pb_rails("icon", props: { icon: "#{icon}", fixed_width: true, margin_left: "xs", font_style: object.icon_font_family }) %>
|
29
29
|
</span>
|
30
30
|
<% end %>
|
31
31
|
<% end %>
|
@@ -99,8 +99,12 @@ const CollapsibleMain = ({
|
|
99
99
|
const mainSpacing = globalProps(props, { cursor })
|
100
100
|
|
101
101
|
const handleCollapsibleClick = () => {
|
102
|
+
onClick && onClick();
|
103
|
+
//To disable default toggling behavior return "true" in the onClick()
|
104
|
+
const disableToggle = onClick && onClick();
|
105
|
+
if (disableToggle !== true) {
|
102
106
|
toggle();
|
103
|
-
|
107
|
+
}
|
104
108
|
}
|
105
109
|
|
106
110
|
return (
|
@@ -121,30 +121,61 @@ export const toIso = (newDate: Date | string): string => {
|
|
121
121
|
}
|
122
122
|
|
123
123
|
export const fromNow = (newDate: Date | string): string => {
|
124
|
-
const
|
125
|
-
const
|
124
|
+
const today = new Date()
|
125
|
+
const formattedDate = formatDate(newDate)
|
126
|
+
|
127
|
+
const startDate = formattedDate.getTime()
|
128
|
+
const endDate = today.getTime()
|
126
129
|
const elapsedTime = endDate - startDate
|
127
|
-
|
128
|
-
|
129
|
-
const
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
130
|
+
|
131
|
+
// For years/months, don't use elapsedTime due to rounding
|
132
|
+
const differenceInYears = today.getFullYear() - formattedDate.getFullYear()
|
133
|
+
const differenceInMonths = () => {
|
134
|
+
let months = differenceInYears * 12
|
135
|
+
months -= formattedDate.getMonth()
|
136
|
+
months += today.getMonth()
|
137
|
+
return months
|
138
|
+
}
|
139
|
+
|
140
|
+
const FORTY_FIVE_SECONDS = 45000
|
141
|
+
const NINETY_SECONDS = 90000
|
142
|
+
|
143
|
+
const FORTY_FIVE_MINUTES = 2670000
|
144
|
+
const NINETY_MINUTES = 5400000
|
145
|
+
|
146
|
+
const TWENTY_TWO_HOURS = 77400000
|
147
|
+
const THIRTY_SIX_HOURS = 129600000
|
148
|
+
|
149
|
+
const TWENTY_SIX_DAYS = 2203200000
|
150
|
+
const FORTY_FIVE_DAYS = 3888000000
|
151
|
+
|
152
|
+
const TEN_AND_A_HALF_MONTHS = 27560000000
|
153
|
+
|
154
|
+
const MILLISECONDS_IN_A_MINUTE = 60000
|
155
|
+
const MILLISECONDS_IN_A_HOUR = 3600000
|
156
|
+
const MILLISECONDS_IN_A_DAY = 86400000
|
157
|
+
|
158
|
+
let elapsedTimeString = differenceInYears === 1 ? `${differenceInYears} year ago` : `${differenceInYears} years ago` // 320 days to 1+ year: "x year(s) ago"
|
159
|
+
|
160
|
+
// Inspiration: https://momentjs.com/docs/#/displaying/fromnow/
|
161
|
+
const intervals = [
|
162
|
+
{ min: 0, max: FORTY_FIVE_SECONDS, value: "a few seconds ago" }, // 0-44.99 seconds
|
163
|
+
{ min: FORTY_FIVE_SECONDS, max: NINETY_SECONDS, value: "a minute ago" }, // 45-89.99 seconds
|
164
|
+
{ min: NINETY_SECONDS, max: FORTY_FIVE_MINUTES, value: `${Math.round(elapsedTime / MILLISECONDS_IN_A_MINUTE)} minutes ago` }, // 90s-44.49 minutes: "2 minutes ago ... 44 minutes ago"
|
165
|
+
{ min: FORTY_FIVE_MINUTES, max: NINETY_MINUTES, value: "an hour ago" }, // 44.5-89.99 minutes
|
166
|
+
{ min: NINETY_MINUTES, max: TWENTY_TWO_HOURS, value: `${Math.round(elapsedTime / MILLISECONDS_IN_A_HOUR)} hours ago` }, // 90m-21.49 hours: "2 hours ago ... 21 hours ago"
|
167
|
+
{ min: TWENTY_TWO_HOURS, max: THIRTY_SIX_HOURS, value: "a day ago" }, // 21.5-35.99 hours
|
168
|
+
{ min: THIRTY_SIX_HOURS, max: TWENTY_SIX_DAYS, value: `${Math.round(elapsedTime / MILLISECONDS_IN_A_DAY)} days ago` }, // 36h-25.49 days: "2 days ago ... 25 days ago"
|
169
|
+
{ min: TWENTY_SIX_DAYS, max: FORTY_FIVE_DAYS, value: "a month ago" }, // 25.5-44.99 days
|
170
|
+
{ min: FORTY_FIVE_DAYS, max: TEN_AND_A_HALF_MONTHS, value: `${differenceInMonths()} months ago` }, // 45 days to 319 days: "2 months ago ... 10 months ago"
|
171
|
+
]
|
172
|
+
|
173
|
+
for (const interval of intervals) {
|
174
|
+
const { min, max, value } = interval
|
175
|
+
|
176
|
+
if (elapsedTime >= min && elapsedTime < max) {
|
177
|
+
elapsedTimeString = value
|
178
|
+
break
|
148
179
|
}
|
149
180
|
}
|
150
181
|
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<%= pb_rails("table", props: { size: "lg"} ) do %>
|
2
|
+
<thead>
|
3
|
+
<tr>
|
4
|
+
<%= pb_rails("table/table_header", props: {
|
5
|
+
id: "name",
|
6
|
+
colspan: 2,
|
7
|
+
sort_menu: [
|
8
|
+
{ item: "Name", link: "?q[sorts]=name+desc", active: false, direction: "desc" },
|
9
|
+
{ item: "Name", link: "?q[sorts]=name+asc", active: true, direction: "asc" },
|
10
|
+
],
|
11
|
+
}) %>
|
12
|
+
<%= pb_rails("table/table_header", props: {
|
13
|
+
text: "Age",
|
14
|
+
id: "age",
|
15
|
+
sort_menu: [
|
16
|
+
{ item: "Age", link: "?q[sorts]=age+desc", active: false, direction: "desc" },
|
17
|
+
{ item: "Age", link: "?q[sorts]=age+asc", active: false, direction: "asc" },
|
18
|
+
],
|
19
|
+
}) %>
|
20
|
+
<%= pb_rails("table/table_header", props: {
|
21
|
+
text: "Territory",
|
22
|
+
id: "territory",
|
23
|
+
sort_menu: [
|
24
|
+
{ item: "Territory", link: "?q[sorts]=territory+desc", active: false, direction: "desc" },
|
25
|
+
{ item: "Territory", link: "?q[sorts]=territory+asc", active: false, direction: "asc" },
|
26
|
+
],
|
27
|
+
}) %>
|
28
|
+
<%= pb_rails("table/table_header", props: { text: "Job Title" }) %>
|
29
|
+
</tr>
|
30
|
+
</thead>
|
31
|
+
<tbody>
|
32
|
+
<tr>
|
33
|
+
<td>Name 1</td>
|
34
|
+
<td>Name 2</td>
|
35
|
+
<td>Value 3</td>
|
36
|
+
<td>Value 4</td>
|
37
|
+
<td>Value 5</td>
|
38
|
+
</tr>
|
39
|
+
<tr>
|
40
|
+
<td>Name 1</td>
|
41
|
+
<td>Name 2</td>
|
42
|
+
<td>Value 3</td>
|
43
|
+
<td>Value 4</td>
|
44
|
+
<td>Value 5</td>
|
45
|
+
</tr>
|
46
|
+
<tr>
|
47
|
+
<td>Name 1</td>
|
48
|
+
<td>Name 2</td>
|
49
|
+
<td>Value 3</td>
|
50
|
+
<td>Value 4</td>
|
51
|
+
<td>Value 5</td>
|
52
|
+
</tr>
|
53
|
+
</tbody>
|
54
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
A kit that produces a `<th>` tag. You can also use the `sort_menu` prop to make the header a sortable link, just like <a href="https://playbook.powerapp.cloud/kits/filter#sort-only" target="_blank">our filter kit.</a>
|
@@ -28,7 +28,7 @@ const TableOneAction = (props) => {
|
|
28
28
|
<Button
|
29
29
|
onClick={() => alert('button clicked!')}
|
30
30
|
paddingLeft="none"
|
31
|
-
text="
|
31
|
+
text="Tertiary Action"
|
32
32
|
variant="link"
|
33
33
|
{...props}
|
34
34
|
/>
|
@@ -49,7 +49,7 @@ const TableOneAction = (props) => {
|
|
49
49
|
<Button
|
50
50
|
onClick={() => alert('button clicked!')}
|
51
51
|
paddingLeft="none"
|
52
|
-
text="
|
52
|
+
text="Tertiary Action"
|
53
53
|
variant="link"
|
54
54
|
{...props}
|
55
55
|
/>
|
@@ -70,7 +70,7 @@ const TableOneAction = (props) => {
|
|
70
70
|
<Button
|
71
71
|
onClick={() => alert('button clicked!')}
|
72
72
|
paddingLeft="none"
|
73
|
-
text="
|
73
|
+
text="Tertiary Action"
|
74
74
|
variant="link"
|
75
75
|
{...props}
|
76
76
|
/>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
$text_align_values: (
|
3
|
+
start: start,
|
4
|
+
end: end,
|
5
|
+
left: left,
|
6
|
+
right: right,
|
7
|
+
center: center,
|
8
|
+
justify: justify,
|
9
|
+
justify-all: justify-all,
|
10
|
+
match-parent: match-parent,
|
11
|
+
);
|
12
|
+
|
13
|
+
[class^=pb_table] {
|
14
|
+
thead {
|
15
|
+
[class^=pb_table_header_kit] {
|
16
|
+
@each $align_name, $align_value in $text_align_values {
|
17
|
+
&[class*=_align_#{$align_name}] {
|
18
|
+
text-align: $align_value;
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
[class^=pb_table] {
|
26
|
+
thead {
|
27
|
+
[class^=pb_th_active] {
|
28
|
+
color: $primary !important;
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
@@ -0,0 +1,64 @@
|
|
1
|
+
<%= content_tag(:th,
|
2
|
+
colspan: object.colspan,
|
3
|
+
aria: object.aria,
|
4
|
+
class: object.classname,
|
5
|
+
data: object.data,
|
6
|
+
id: "pb-th#{object.id}") do %>
|
7
|
+
<% object.sort_menu.each do |item| %>
|
8
|
+
<% if item[:active] == true %>
|
9
|
+
<%= pb_rails("flex", props:{ align: object.align_content }) do %>
|
10
|
+
<%= content.presence || content_tag(:span, item[:item], class: "pb_th_active") %>
|
11
|
+
<span class="pb_th_active">
|
12
|
+
<%= pb_rails("icon", props: { icon: object.sort_icon(item[:direction]),
|
13
|
+
fixed_width: true,
|
14
|
+
classname: "pb_th_active",
|
15
|
+
padding_left: "xs" }) %>
|
16
|
+
</span>
|
17
|
+
<% end %>
|
18
|
+
<% end %>
|
19
|
+
<% end %>
|
20
|
+
<% if object.sort_menu.all? { |item| item[:active] == false } %>
|
21
|
+
<%= pb_rails("flex", props:{ align: object.align_content }) do %>
|
22
|
+
<%= content.presence || object.text %>
|
23
|
+
<%= pb_rails("icon", props: { icon: "arrow-up-arrow-down",
|
24
|
+
fixed_width: true,
|
25
|
+
padding_left: "xs" }) %>
|
26
|
+
<% end %>
|
27
|
+
<% else %>
|
28
|
+
<%= content.presence || object.text %>
|
29
|
+
<% end %>
|
30
|
+
<% if object.sort_menu != [{}] && object.colspan > 1 %>
|
31
|
+
<%= pb_rails("popover", props: { classname: "pb_filter_sort_menu",
|
32
|
+
close_on_click: "outside",
|
33
|
+
trigger_element_id: "pb-th#{object.id}",
|
34
|
+
tooltip_id: "sort-filter-btn-tooltip#{object.id}",
|
35
|
+
position: object.placement ,
|
36
|
+
padding: 'none'}) do %>
|
37
|
+
<%= pb_rails("list") do %>
|
38
|
+
<% object.sort_menu.each do |item| %>
|
39
|
+
<%= pb_rails("list/item") do %>
|
40
|
+
<%= pb_rails("button", props: { variant: "link" ,
|
41
|
+
classname: "p-0",
|
42
|
+
text: item[:item],
|
43
|
+
link: item[:link],
|
44
|
+
icon: sort_icon(item[:direction]),
|
45
|
+
icon_right: true }) %>
|
46
|
+
<% end %>
|
47
|
+
<% end %>
|
48
|
+
<% end %>
|
49
|
+
<% end %>
|
50
|
+
<% end %>
|
51
|
+
<% end %>
|
52
|
+
<% if object.sort_menu != [{}] && object.colspan == 1 %>
|
53
|
+
<script>
|
54
|
+
document.addEventListener("DOMContentLoaded", function() {
|
55
|
+
var thId = `<%= "#pb-th#{object.id}" %>`
|
56
|
+
var firstLink = `<%= next_link %>`
|
57
|
+
var thElement = document.querySelector(thId);
|
58
|
+
|
59
|
+
thElement.addEventListener("click", function() {
|
60
|
+
window.location.href = firstLink;
|
61
|
+
});
|
62
|
+
});
|
63
|
+
</script>
|
64
|
+
<% end %>
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Playbook
|
4
|
+
module PbTable
|
5
|
+
class TableHeader < Playbook::KitBase
|
6
|
+
prop :align, type: Playbook::Props::Enum,
|
7
|
+
values: %w[start center end stretch baseline none],
|
8
|
+
default: "start"
|
9
|
+
prop :align_content, type: Playbook::Props::Enum,
|
10
|
+
values: %w[start center end stretch baseline none],
|
11
|
+
default: "center"
|
12
|
+
prop :colspan, type: Playbook::Props::Number,
|
13
|
+
default: 1
|
14
|
+
prop :placement, type: Playbook::Props::Enum,
|
15
|
+
values: %w[top bottom left right top-start top-end bottom-start bottom-end right-start right-end left-start left-end],
|
16
|
+
default: "bottom-start"
|
17
|
+
prop :sort_menu, type: Playbook::Props::HashArray,
|
18
|
+
default: [{}]
|
19
|
+
prop :text, type: Playbook::Props::String,
|
20
|
+
default: ""
|
21
|
+
|
22
|
+
def classname
|
23
|
+
generate_classname("pb_table_header_kit", align_class)
|
24
|
+
end
|
25
|
+
|
26
|
+
def align_class
|
27
|
+
align.present? ? "align_#{align}" : nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def next_link
|
31
|
+
return sort_menu[0][:link] if sort_menu.all? { |item| item[:active] == false }
|
32
|
+
|
33
|
+
sort_menu.each_with_index do |item, index|
|
34
|
+
if item[:active] == true
|
35
|
+
next_index = (index + 1) % sort_menu.length
|
36
|
+
sort_menu[next_index][:link]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def sort_icon(direction)
|
42
|
+
case direction
|
43
|
+
when "asc"
|
44
|
+
"sort-amount-up"
|
45
|
+
when "desc"
|
46
|
+
"sort-amount-down"
|
47
|
+
else
|
48
|
+
""
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -5,7 +5,6 @@ import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
|
|
5
5
|
import { globalProps } from '../utilities/globalProps'
|
6
6
|
import DateTime from '../pb_kit/dateTime';
|
7
7
|
|
8
|
-
|
9
8
|
import Caption from '../pb_caption/_caption'
|
10
9
|
|
11
10
|
type TimestampProps = {
|
@@ -22,6 +21,7 @@ type TimestampProps = {
|
|
22
21
|
showUser?: boolean,
|
23
22
|
hideUpdated?: boolean,
|
24
23
|
showTimezone?: boolean,
|
24
|
+
unstyled?: boolean,
|
25
25
|
variant?: "default" | "elapsed" | "updated"
|
26
26
|
}
|
27
27
|
|
@@ -39,6 +39,7 @@ const Timestamp = (props: TimestampProps): React.ReactElement => {
|
|
39
39
|
showUser = false,
|
40
40
|
hideUpdated = false,
|
41
41
|
showTimezone = false,
|
42
|
+
unstyled = false,
|
42
43
|
variant = 'default',
|
43
44
|
} = props
|
44
45
|
|
@@ -85,7 +86,7 @@ const Timestamp = (props: TimestampProps): React.ReactElement => {
|
|
85
86
|
return `${updatedText} ${userDisplay} ${DateTime.fromNow(timestamp)}`
|
86
87
|
}
|
87
88
|
|
88
|
-
const
|
89
|
+
const timestampText = () => {
|
89
90
|
switch (variant) {
|
90
91
|
case 'updated':
|
91
92
|
return formatUpdatedString()
|
@@ -103,11 +104,17 @@ const Timestamp = (props: TimestampProps): React.ReactElement => {
|
|
103
104
|
className={classes}
|
104
105
|
>
|
105
106
|
<div className="pb_timestamp_kit">
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
107
|
+
{unstyled ? (
|
108
|
+
<div>
|
109
|
+
{timestampText()}
|
110
|
+
</div>
|
111
|
+
) : (
|
112
|
+
<Caption
|
113
|
+
dark={dark}
|
114
|
+
size="xs"
|
115
|
+
text={timestampText()}
|
116
|
+
/>
|
117
|
+
)}
|
111
118
|
</div>
|
112
119
|
</div>
|
113
120
|
)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<%= pb_rails("caption", props: { size: "xs", text: "Basic unstyled example" }) %>
|
2
|
+
|
3
|
+
<%= pb_rails("timestamp", props: {
|
4
|
+
timestamp: DateTime.now,
|
5
|
+
show_date: true,
|
6
|
+
align: "left",
|
7
|
+
unstyled: true,
|
8
|
+
}) %>
|
9
|
+
|
10
|
+
<br />
|
11
|
+
|
12
|
+
<%= pb_rails("caption", props: { size: "xs", text: "Example with wrapping typography kit" }) %>
|
13
|
+
|
14
|
+
<%= pb_rails("title", props: { size: 1 }) do %>
|
15
|
+
<%= pb_rails("timestamp", props: {
|
16
|
+
timestamp: DateTime.now,
|
17
|
+
show_date: true,
|
18
|
+
align: "left",
|
19
|
+
unstyled: true,
|
20
|
+
}) %>
|
21
|
+
<% end %>
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import { Caption, Timestamp, Title } from '../../'
|
3
|
+
|
4
|
+
const TimestampUnstyled = (props) => {
|
5
|
+
return (
|
6
|
+
<>
|
7
|
+
<Caption size="xs"
|
8
|
+
text="Basic unstyled example"
|
9
|
+
/>
|
10
|
+
<Timestamp
|
11
|
+
align="left"
|
12
|
+
showDate
|
13
|
+
timestamp={new Date()}
|
14
|
+
unstyled
|
15
|
+
{...props}
|
16
|
+
/>
|
17
|
+
|
18
|
+
<br />
|
19
|
+
|
20
|
+
<Caption size="xs"
|
21
|
+
text="Example with wrapping typography kit"
|
22
|
+
/>
|
23
|
+
<Title size={1}>
|
24
|
+
<Timestamp
|
25
|
+
align="left"
|
26
|
+
showDate
|
27
|
+
timestamp={new Date()}
|
28
|
+
unstyled
|
29
|
+
{...props}
|
30
|
+
/>
|
31
|
+
</Title>
|
32
|
+
</>
|
33
|
+
)
|
34
|
+
}
|
35
|
+
|
36
|
+
export default TimestampUnstyled
|
@@ -0,0 +1 @@
|
|
1
|
+
For alternative typography styles, you can pass a boolean prop called `unstyled` to the `Timestamp` kit and wrap it in any of our typography kits (`Title`, `Body`, etc.). This will allow the `Timestamp` kit to inherit any of our typography styles.
|
@@ -6,6 +6,7 @@ examples:
|
|
6
6
|
- timestamp_timezones: Timezones
|
7
7
|
- timestamp_updated: Last Updated by
|
8
8
|
- timestamp_elapsed: Time Ago
|
9
|
+
- timestamp_unstyled: Unstyled
|
9
10
|
|
10
11
|
react:
|
11
12
|
- timestamp_default: Default
|
@@ -13,7 +14,8 @@ examples:
|
|
13
14
|
- timestamp_timezones: Timezones
|
14
15
|
- timestamp_updated: Last Updated by
|
15
16
|
- timestamp_elapsed: Time Ago
|
16
|
-
|
17
|
+
- timestamp_unstyled: Unstyled
|
18
|
+
|
17
19
|
swift:
|
18
20
|
- timestamp_default_swift: Default
|
19
21
|
- timestamp_align_swift: Alignments
|
@@ -3,3 +3,4 @@ export { default as TimestampAlign } from './_timestamp_align.jsx'
|
|
3
3
|
export { default as TimestampTimezones } from './_timestamp_timezones.jsx'
|
4
4
|
export { default as TimestampUpdated } from './_timestamp_updated.jsx'
|
5
5
|
export { default as TimestampElapsed } from './_timestamp_elapsed.jsx'
|
6
|
+
export { default as TimestampUnstyled } from './_timestamp_unstyled.jsx'
|
@@ -4,5 +4,9 @@
|
|
4
4
|
data: object.data,
|
5
5
|
class: object.classname) do %>
|
6
6
|
|
7
|
-
|
7
|
+
<% if object.unstyled %>
|
8
|
+
<div><%= object.timestamp_text %></div>
|
9
|
+
<% else %>
|
10
|
+
<%= pb_rails("caption", props: { text: object.timestamp_text, size: 'xs', dark: object.dark }) %>
|
11
|
+
<% end %>
|
8
12
|
<% end %>
|