playbook_ui 14.0.0 → 14.1.0.pre.alpha.PA1477timestampkit3601

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.
Files changed (163) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +2 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +5 -2
  4. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableBody.tsx +24 -20
  5. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +17 -12
  6. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +89 -4
  7. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +5 -1
  8. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +1 -1
  9. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +30 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_responsive.jsx +67 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_responsive.md +1 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +1 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +2 -1
  14. data/app/pb_kits/playbook/pb_avatar/_avatar.scss +0 -30
  15. data/app/pb_kits/playbook/pb_avatar/_avatar.tsx +19 -1
  16. data/app/pb_kits/playbook/pb_avatar/avatar.rb +44 -1
  17. data/app/pb_kits/playbook/pb_avatar/avatar.test.js +17 -0
  18. data/app/pb_kits/playbook/pb_badge/_badge.scss +9 -0
  19. data/app/pb_kits/playbook/pb_badge/_badge.tsx +8 -3
  20. data/app/pb_kits/playbook/pb_badge/badge.rb +1 -1
  21. data/app/pb_kits/playbook/pb_badge/badge.test.js +17 -11
  22. data/app/pb_kits/playbook/pb_badge/docs/_badge_notification.html.erb +13 -0
  23. data/app/pb_kits/playbook/pb_badge/docs/_badge_notification.jsx +31 -12
  24. data/app/pb_kits/playbook/pb_button/_button.tsx +4 -1
  25. data/app/pb_kits/playbook/pb_button/button.html.erb +1 -1
  26. data/app/pb_kits/playbook/pb_button/button.rb +4 -0
  27. data/app/pb_kits/playbook/pb_date_picker/docs/_description.md +3 -1
  28. data/app/pb_kits/playbook/pb_date_time/dateTime.test.js +2 -2
  29. data/app/pb_kits/playbook/pb_dialog/_close_icon.tsx +5 -1
  30. data/app/pb_kits/playbook/pb_dialog/_dialog.tsx +3 -1
  31. data/app/pb_kits/playbook/pb_dialog/dialog.test.jsx +20 -1
  32. data/app/pb_kits/playbook/pb_dialog/dialog_header.html.erb +1 -1
  33. data/app/pb_kits/playbook/pb_dialog/dialog_header.rb +4 -0
  34. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_default.jsx +1 -5
  35. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_loading.jsx +46 -0
  36. data/app/pb_kits/playbook/pb_dialog/docs/example.yml +1 -0
  37. data/app/pb_kits/playbook/pb_dialog/docs/index.js +1 -0
  38. data/app/pb_kits/playbook/pb_filter/filter.rb +1 -1
  39. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/_fixed_confirmation_toast.scss +1 -1
  40. data/app/pb_kits/playbook/pb_form/docs/_form_form_with.html.erb +1 -0
  41. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +1 -0
  42. data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +43 -25
  43. data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +6 -2
  44. data/app/pb_kits/playbook/pb_form_pill/docs/example.yml +2 -2
  45. data/app/pb_kits/playbook/pb_form_pill/form_pill.html.erb +4 -4
  46. data/app/pb_kits/playbook/pb_form_pill/form_pill.rb +4 -0
  47. data/app/pb_kits/playbook/pb_gantt_chart/_gantt_chart.scss +3 -0
  48. data/app/pb_kits/playbook/pb_gantt_chart/_gantt_chart.tsx +72 -0
  49. data/app/pb_kits/playbook/pb_gantt_chart/docs/_gantt_chart_default.jsx +53 -0
  50. data/app/pb_kits/playbook/pb_gantt_chart/docs/example.yml +7 -0
  51. data/app/pb_kits/playbook/pb_gantt_chart/docs/index.js +1 -0
  52. data/app/pb_kits/playbook/pb_gantt_chart/gantt_chart.test.jsx +19 -0
  53. data/app/pb_kits/playbook/pb_icon/_icon.tsx +4 -1
  54. data/app/pb_kits/playbook/pb_icon/icon.rb +2 -0
  55. data/app/pb_kits/playbook/pb_icon_circle/_icon_circle.tsx +2 -1
  56. data/app/pb_kits/playbook/pb_icon_circle/icon_circle.rb +2 -2
  57. data/app/pb_kits/playbook/pb_icon_stat_value/_icon_stat_value.scss +0 -11
  58. data/app/pb_kits/playbook/pb_icon_stat_value/_icon_stat_value.tsx +3 -2
  59. data/app/pb_kits/playbook/pb_icon_stat_value/docs/_icon_stat_value_color.html.erb +1 -0
  60. data/app/pb_kits/playbook/pb_icon_stat_value/icon_stat_value.rb +2 -2
  61. data/app/pb_kits/playbook/pb_icon_stat_value/icon_stat_value.test.js +5 -4
  62. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +0 -2
  63. data/app/pb_kits/playbook/pb_nav/_horizontal_nav.scss +1 -1
  64. data/app/pb_kits/playbook/pb_online_status/_online_status.scss +52 -5
  65. data/app/pb_kits/playbook/pb_online_status/_online_status.tsx +6 -1
  66. data/app/pb_kits/playbook/pb_online_status/docs/_online_status_no_border.html.erb +1 -0
  67. data/app/pb_kits/playbook/pb_online_status/docs/_online_status_no_border.jsx +14 -0
  68. data/app/pb_kits/playbook/pb_online_status/docs/_online_status_size.html.erb +3 -0
  69. data/app/pb_kits/playbook/pb_online_status/docs/_online_status_size.jsx +25 -0
  70. data/app/pb_kits/playbook/pb_online_status/docs/example.yml +6 -2
  71. data/app/pb_kits/playbook/pb_online_status/docs/index.js +2 -0
  72. data/app/pb_kits/playbook/pb_online_status/online_status.rb +11 -1
  73. data/app/pb_kits/playbook/pb_online_status/online_status.test.js +31 -0
  74. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_toggle.html.erb +61 -0
  75. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_toggle.jsx +70 -0
  76. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_toggle.md +1 -0
  77. data/app/pb_kits/playbook/pb_overlay/docs/example.yml +4 -2
  78. data/app/pb_kits/playbook/pb_overlay/docs/index.js +1 -0
  79. data/app/pb_kits/playbook/pb_pagination/_pagination.scss +49 -13
  80. data/app/pb_kits/playbook/pb_pagination/_pagination.tsx +164 -0
  81. data/app/pb_kits/playbook/pb_pagination/docs/_pagination_default.jsx +19 -0
  82. data/app/pb_kits/playbook/pb_pagination/docs/_pagination_default_react.md +1 -0
  83. data/app/pb_kits/playbook/pb_pagination/docs/_pagination_page_change.jsx +62 -0
  84. data/app/pb_kits/playbook/pb_pagination/docs/_pagination_page_change_react.md +1 -0
  85. data/app/pb_kits/playbook/pb_pagination/docs/data.js +23 -0
  86. data/app/pb_kits/playbook/pb_pagination/docs/example.yml +3 -1
  87. data/app/pb_kits/playbook/pb_pagination/docs/index.js +2 -0
  88. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss +0 -7
  89. data/app/pb_kits/playbook/pb_popover/_popover.tsx +10 -5
  90. data/app/pb_kits/playbook/pb_rich_text_editor/_previewer_mixin.scss +132 -0
  91. data/app/pb_kits/playbook/pb_rich_text_editor/_tiptap_styles.scss +50 -76
  92. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_preview.jsx +73 -0
  93. data/app/pb_kits/playbook/pb_rich_text_editor/docs/example.yml +1 -0
  94. data/app/pb_kits/playbook/pb_rich_text_editor/docs/index.js +2 -1
  95. data/app/pb_kits/playbook/pb_star_rating/_star_rating.scss +83 -6
  96. data/app/pb_kits/playbook/pb_star_rating/docs/example.yml +3 -1
  97. data/app/pb_kits/playbook/pb_star_rating/index.js +128 -22
  98. data/app/pb_kits/playbook/pb_star_rating/star_rating.html.erb +5 -3
  99. data/app/pb_kits/playbook/pb_star_rating/star_rating.rb +19 -2
  100. data/app/pb_kits/playbook/pb_star_rating/stars/utils.tsx +5 -1
  101. data/app/pb_kits/playbook/pb_star_rating/subcomponents/_star_rating_display.tsx +0 -2
  102. data/app/pb_kits/playbook/pb_star_rating/subcomponents/_star_rating_interactive.tsx +50 -22
  103. data/app/pb_kits/playbook/pb_table/_table.tsx +1 -1
  104. data/app/pb_kits/playbook/pb_table/index.ts +4 -4
  105. data/app/pb_kits/playbook/pb_table/subcomponents/_table_body.tsx +1 -1
  106. data/app/pb_kits/playbook/pb_table/subcomponents/_table_cell.tsx +1 -1
  107. data/app/pb_kits/playbook/pb_table/subcomponents/_table_head.tsx +1 -1
  108. data/app/pb_kits/playbook/pb_table/subcomponents/_table_header.tsx +1 -1
  109. data/app/pb_kits/playbook/pb_table/subcomponents/_table_row.tsx +1 -1
  110. data/app/pb_kits/playbook/pb_table/table.test.js +2 -0
  111. data/app/pb_kits/playbook/pb_text_input/_text_input.tsx +1 -1
  112. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_default.jsx +1 -1
  113. data/app/pb_kits/playbook/pb_textarea/_textarea.tsx +45 -27
  114. data/app/pb_kits/playbook/pb_textarea/index.ts +3 -3
  115. data/app/pb_kits/playbook/pb_time/_time.tsx +15 -11
  116. data/app/pb_kits/playbook/pb_time/time.html.erb +3 -3
  117. data/app/pb_kits/playbook/pb_time/time.rb +4 -0
  118. data/app/pb_kits/playbook/pb_time_range_inline/_time_range_inline.tsx +1 -1
  119. data/app/pb_kits/playbook/pb_timeline/_item.tsx +1 -1
  120. data/app/pb_kits/playbook/pb_timeline/_timeline.tsx +1 -1
  121. data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_elapsed.html.erb +2 -2
  122. data/app/pb_kits/playbook/pb_timestamp/timestamp.rb +46 -2
  123. data/app/pb_kits/playbook/pb_title_detail/_title_detail.tsx +10 -10
  124. data/app/pb_kits/playbook/pb_toggle/_toggle.tsx +1 -1
  125. data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +2 -2
  126. data/app/pb_kits/playbook/pb_treemap_chart/_treemap_chart.tsx +1 -2
  127. data/app/pb_kits/playbook/pb_treemap_chart/treemapChart.test.js +2 -0
  128. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +2 -2
  129. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_multi_kit.html.erb +1 -1
  130. data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +1 -0
  131. data/app/pb_kits/playbook/pb_user/_user.tsx +1 -1
  132. data/app/pb_kits/playbook/pb_user_badge/_user_badge.tsx +6 -6
  133. data/app/pb_kits/playbook/pb_user_badge/badges/million-dollar.tsx +236 -235
  134. data/app/pb_kits/playbook/pb_user_badge/badges/veteran.tsx +1 -1
  135. data/app/pb_kits/playbook/pb_walkthrough/_walkthrough.tsx +68 -63
  136. data/app/pb_kits/playbook/pb_weekday_stacked/_weekday_stacked.tsx +1 -1
  137. data/app/pb_kits/playbook/tokens/_container.scss +21 -0
  138. data/app/pb_kits/playbook/utilities/_min_width.scss +45 -0
  139. data/app/pb_kits/playbook/utilities/_positioning.scss +26 -15
  140. data/app/pb_kits/playbook/utilities/globalPropNames.mjs +1 -0
  141. data/app/pb_kits/playbook/utilities/globalProps.ts +20 -3
  142. data/app/pb_kits/playbook/utilities/icons/allicons.tsx +59 -0
  143. data/app/pb_kits/playbook/utilities/icons/clock.svg +9 -0
  144. data/app/pb_kits/playbook/utilities/icons/spinner.svg +3 -0
  145. data/app/pb_kits/playbook/utilities/icons/times.svg +3 -0
  146. data/dist/chunks/_typeahead-Cq7RLPBA.js +22 -0
  147. data/dist/chunks/_weekday_stacked-Cykj5kLZ.js +45 -0
  148. data/dist/chunks/{lib-Bf_E03gc.js → lib-DErGXNy3.js} +2 -2
  149. data/dist/chunks/{pb_form_validation-D0dhqeN2.js → pb_form_validation-BC6kh7Hu.js} +1 -1
  150. data/dist/chunks/vendor.js +1 -1
  151. data/dist/menu.yml +4 -0
  152. data/dist/playbook-doc.js +1 -1
  153. data/dist/playbook-rails-react-bindings.js +1 -1
  154. data/dist/playbook-rails.js +1 -1
  155. data/dist/playbook.css +1 -1
  156. data/lib/playbook/classnames.rb +1 -0
  157. data/lib/playbook/spacing.rb +31 -2
  158. data/lib/playbook/version.rb +2 -2
  159. metadata +44 -13
  160. data/app/pb_kits/playbook/pb_online_status/_online_status_mixins.scss +0 -32
  161. data/dist/chunks/_typeahead-COUJ88EA.js +0 -22
  162. data/dist/chunks/_weekday_stacked-BAkwel5p.js +0 -45
  163. /data/app/pb_kits/playbook/pb_pagination/docs/{_pagination_default.md → _pagination_default_rails.md} +0 -0
@@ -39,15 +39,17 @@
39
39
  <% end %>
40
40
 
41
41
  <% else %>
42
- <%= pb_rails("flex", props: { orientation: "column" }) do %>
42
+ <%= pb_rails("flex", props: { data: {"pb-star-rating-wrapper": "true" }, orientation: "column" }) do %>
43
43
  <% if object.label.present? %>
44
44
  <%= pb_rails("caption", props: {text: object.label, margin_bottom:"xs"}) %>
45
45
  <% end %>
46
- <input type="hidden" id="star-rating-input" value="" name="<%= object.name %>"/>
46
+
47
+ <%= hidden_input_tag %>
48
+
47
49
  <%= pb_rails("flex", props: { orientation: "row" }) do %>
48
50
  <% object.denominator.times do |index| %>
49
51
  <div data-pb-star-rating id="<%= index + 1 %>" class="<%= star_color %>">
50
- <%= pb_rails("icon", props: { classname: "#{background_star_color} pb_star_#{size} interactive-star-icon", custom_icon: Playbook::Engine.root.join(background_star_path)} ) %>
52
+ <%= pb_rails("icon", props: { classname: "#{background_star_color} pb_star_#{size} interactive-star-icon", custom_icon: Playbook::Engine.root.join(background_star_path), tabindex: 0 } ) %>
51
53
  </div>
52
54
  <% end %>
53
55
  <% end %>
@@ -30,6 +30,10 @@ module Playbook
30
30
  default: "display"
31
31
  prop :label, type: Playbook::Props::String
32
32
  prop :name, type: Playbook::Props::String
33
+ prop :required, type: Playbook::Props::Boolean,
34
+ default: false
35
+ prop :input_options, type: Playbook::Props::HashProp,
36
+ default: {}
33
37
 
34
38
  def one_decimal_rating
35
39
  rating.to_f.round(1)
@@ -52,9 +56,9 @@ module Playbook
52
56
  when "yellow"
53
57
  "yellow_star"
54
58
  when "primary"
55
- "primary_star"
59
+ dark ? "primary_star_dark" : "primary_star_light"
56
60
  when "subtle"
57
- dark ? "suble_star_dark" : "suble_star_light"
61
+ dark ? "subtle_star_dark" : "subtle_star_light"
58
62
  end
59
63
  end
60
64
 
@@ -106,6 +110,19 @@ module Playbook
106
110
  def classname
107
111
  generate_classname("pb_star_rating_kit")
108
112
  end
113
+
114
+ def hidden_input_tag
115
+ tag(:input, all_input_options)
116
+ end
117
+
118
+ def all_input_options
119
+ input_options.merge(
120
+ data: { "pb-star-rating-input": true },
121
+ name: name,
122
+ required: required,
123
+ style: "display: none"
124
+ )
125
+ end
109
126
  end
110
127
  end
111
128
  end
@@ -53,7 +53,11 @@ const starOutline = (
53
53
  )
54
54
 
55
55
  export const getStarIconObject = (backgroundType: string, color: string, dark: boolean, size: string) => {
56
- const colorClassName = color === "subtle" ? (dark ? "suble_star_dark" : "suble_star_light") : `${color}_star`
56
+ const colorClassName = color === "subtle"
57
+ ? (dark ? "suble_star_dark" : "suble_star_light")
58
+ : color === "primary"
59
+ ? (dark ? "primary_star_dark" : "primary_star_light")
60
+ : `${color}_star`
57
61
  const backgroundClassName = backgroundType === "outline" ? (dark ? "outline_empty_star_dark" : "outline_empty_star_light") : (dark ? "empty_star_dark" : "empty_star_light")
58
62
 
59
63
  return {
@@ -36,7 +36,6 @@ const StarRatingDisplay = (props: StarRatingDisplayProps) => {
36
36
  <Icon
37
37
  className={starIcon[colorOption].className}
38
38
  customIcon={starIcon[colorOption].icon as unknown as { [key: string]: SVGElement }}
39
- icon=""
40
39
  />
41
40
  </React.Fragment>
42
41
  ))}
@@ -45,7 +44,6 @@ const StarRatingDisplay = (props: StarRatingDisplayProps) => {
45
44
  <Icon
46
45
  className={starIcon[backgroundType].className}
47
46
  customIcon={starIcon[backgroundType].icon as unknown as { [key: string]: SVGElement }}
48
- icon=""
49
47
  />
50
48
  </React.Fragment>
51
49
  ))}
@@ -23,40 +23,68 @@ const StarRatingInteractive = (props: StarRatingInteractiveProps) => {
23
23
  size,
24
24
  } = props
25
25
  const [interactiveStarValue, setInteractiveStarValue] = useState(0)
26
+ const [hoverStarValue, setHoverStarValue] = useState<number | null>(null)
26
27
  const starIcon = getStarIconObject(backgroundType, colorOption, dark, size)
27
28
 
28
29
  const handleOnClick = (interactiveStarValue: number) => {
29
30
  setInteractiveStarValue(interactiveStarValue)
30
31
  onClick && onClick(interactiveStarValue)
31
32
  }
33
+ const handleMouseEnter = (value: number) => {
34
+ setHoverStarValue(value);
35
+ }
36
+ const handleMouseLeave = () => {
37
+ setHoverStarValue(null);
38
+ }
39
+ const handleOnKeyDown = (event: React.KeyboardEvent<HTMLDivElement>, starIndex: number) => {
40
+ if (event.key === 'Enter' || event.key === ' ') {
41
+ event.preventDefault()
42
+ handleOnClick(starIndex)
43
+ }
44
+ }
32
45
 
33
46
  return (
34
47
  <Flex className="star_flex_area">
35
- {[...Array(denominator)].map((_, index) => (
36
- <React.Fragment key={index}>
37
- {index + 1 <= interactiveStarValue && (
48
+ {[...Array(denominator)].map((_, index) => {
49
+ const starIndex = index + 1
50
+ const isFilled = starIndex <= interactiveStarValue
51
+ const isHovered = hoverStarValue !== null && starIndex > interactiveStarValue && starIndex <= hoverStarValue
52
+
53
+ const baseClass = dark
54
+ ? starIcon[backgroundType].className.replace("empty_star_light", "empty_star_dark")
55
+ : starIcon[backgroundType].className
56
+
57
+ let starClass = baseClass
58
+ if (isFilled) {
59
+ starClass = starClass.replace(/(empty_star_light|empty_star_dark)/, '')
60
+ starClass += ` ${starIcon[colorOption].className}`
61
+ }
62
+ if (isHovered) {
63
+ starClass += " star-hovered"
64
+ }
65
+ if (isFilled && starIndex === interactiveStarValue) {
66
+ starClass += " star-selected"
67
+ }
68
+
69
+ return (
70
+ <div
71
+ key={index}
72
+ onKeyDown={(event) => handleOnKeyDown(event, starIndex)}
73
+ >
38
74
  <Icon
39
- className={starIcon[colorOption].className}
75
+ className={starClass.trim()}
40
76
  cursor="pointer"
41
- customIcon={starIcon[colorOption].icon as unknown as { [key: string]: SVGElement }}
42
- htmlOptions={{ onClick: () => handleOnClick(index + 1) }}
43
- icon=""
77
+ customIcon={starIcon[backgroundType].icon as unknown as { [key: string]: SVGElement }}
78
+ htmlOptions={{
79
+ onClick: () => handleOnClick(starIndex),
80
+ onMouseEnter: () => handleMouseEnter(starIndex),
81
+ onMouseLeave: () => handleMouseLeave(),
82
+ }}
83
+ tabIndex={0}
44
84
  />
45
- )}
46
-
47
- {index + 1 > interactiveStarValue && (
48
- <React.Fragment key={index}>
49
- <Icon
50
- className={starIcon[backgroundType].className}
51
- cursor="pointer"
52
- customIcon={starIcon[backgroundType].icon as unknown as { [key: string]: SVGElement }}
53
- htmlOptions={{ onClick: () => handleOnClick(index + 1) }}
54
- icon=""
55
- />
56
- </React.Fragment>
57
- )}
58
- </React.Fragment>
59
- ))}
85
+ </div>
86
+ );
87
+ })}
60
88
  </Flex>
61
89
  )
62
90
  }
@@ -33,7 +33,7 @@ type TableProps = {
33
33
  verticalBorder?: boolean,
34
34
  } & GlobalProps
35
35
 
36
- const Table = (props: TableProps) => {
36
+ const Table = (props: TableProps): React.ReactElement => {
37
37
  const {
38
38
  aria = {},
39
39
  children,
@@ -1,19 +1,19 @@
1
1
  import PbEnhancedElement from '../pb_enhanced_element'
2
2
 
3
3
  export default class PbTable extends PbEnhancedElement {
4
- static get selector() {
4
+ static get selector(): string {
5
5
  return '.table-responsive-collapse'
6
6
  }
7
7
 
8
- connect() {
8
+ connect(): void {
9
9
  const tables = document.querySelectorAll('.table-responsive-collapse');
10
10
 
11
11
  // Each Table
12
12
  [].forEach.call(tables, (table: HTMLTableElement) => {
13
13
  // Header Titles
14
- let headers: string[] = [];
14
+ const headers: string[] = [];
15
15
  [].forEach.call(table.querySelectorAll('th'), (header: HTMLTableCellElement) => {
16
- let colSpan = header.colSpan
16
+ const colSpan = header.colSpan
17
17
  for (let i = 0; i < colSpan; i++) {
18
18
  headers.push(header.textContent.replace(/\r?\n|\r/, ''));
19
19
  }
@@ -17,7 +17,7 @@ type TableBodyPropTypes = {
17
17
  tag?: "table" | "div";
18
18
  };
19
19
 
20
- const TableBody = (props: TableBodyPropTypes) => {
20
+ const TableBody = (props: TableBodyPropTypes): React.ReactElement => {
21
21
  const {
22
22
  aria = {},
23
23
  children,
@@ -18,7 +18,7 @@ type TableCellPropTypes = {
18
18
  text?: string
19
19
  };
20
20
 
21
- const TableCell = (props: TableCellPropTypes) => {
21
+ const TableCell = (props: TableCellPropTypes): React.ReactElement => {
22
22
  const {
23
23
  aria = {},
24
24
  children,
@@ -17,7 +17,7 @@ type TableHeadPropTypes = {
17
17
  tag?: "table" | "div";
18
18
  };
19
19
 
20
- const TableHead = (props: TableHeadPropTypes) => {
20
+ const TableHead = (props: TableHeadPropTypes): React.ReactElement => {
21
21
  const {
22
22
  aria = {},
23
23
  children,
@@ -18,7 +18,7 @@ type TableHeaderPropTypes = {
18
18
  text?: string;
19
19
  };
20
20
 
21
- const TableHeader = (props: TableHeaderPropTypes) => {
21
+ const TableHeader = (props: TableHeaderPropTypes): React.ReactElement => {
22
22
  const {
23
23
  aria = {},
24
24
  children,
@@ -19,7 +19,7 @@ type TableRowPropTypes = {
19
19
  tag?: "table" | "div";
20
20
  };
21
21
 
22
- const TableRow = (props: TableRowPropTypes) => {
22
+ const TableRow = (props: TableRowPropTypes): React.ReactElement => {
23
23
  const {
24
24
  aria = {},
25
25
  children,
@@ -1,3 +1,5 @@
1
+ /* eslint-disable react/no-multi-comp */
2
+
1
3
  import React from "react";
2
4
  import { ensureAccessible, renderKit, render, screen } from "../utilities/test-utils"
3
5
 
@@ -107,7 +107,7 @@ const TextInput = (props: TextInputProps, ref: React.LegacyRef<HTMLInputElement>
107
107
  required={required}
108
108
  type={type}
109
109
  value={value}
110
- />)
110
+ />)
111
111
  )
112
112
 
113
113
  const addOnInput = (
@@ -5,12 +5,12 @@ import TextInput from '../../pb_text_input/_text_input'
5
5
  import Title from '../../pb_title/_title'
6
6
 
7
7
  const TextInputDefault = (props) => {
8
+ const [firstName, setFirstName] = useState('')
8
9
  const handleOnChangeFirstName = ({ target }) => {
9
10
  setFirstName(target.value)
10
11
  }
11
12
  const ref = React.createRef()
12
13
 
13
- const [firstName, setFirstName] = useState('')
14
14
  const [formFields, setFormFields] = useState({
15
15
  firstName: 'Jane',
16
16
  lastName: 'Doe',
@@ -52,14 +52,15 @@ const Textarea = ({
52
52
  label,
53
53
  maxCharacters,
54
54
  name,
55
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
55
56
  onChange = () => {},
56
57
  placeholder,
57
58
  required,
58
59
  rows = 4,
59
60
  value,
60
61
  ...props
61
- }: TextareaProps, ref: any) => {
62
- ref = useRef<HTMLTextAreaElement>(null)
62
+ }: TextareaProps) => {
63
+ const ref = useRef<HTMLTextAreaElement>(null)
63
64
  useEffect(() => {
64
65
  if (ref.current && resize === 'auto') {
65
66
  PbTextarea.addMatch(ref.current)
@@ -71,58 +72,75 @@ const Textarea = ({
71
72
  const resizeClass = `resize_${resize}`
72
73
  const classes = classnames('pb_textarea_kit', errorClass, inlineClass, resizeClass, globalProps(props), className)
73
74
  const noCount = typeof characterCount !== 'undefined'
74
- const ariaProps: {[key: string]: any} = buildAriaProps(aria)
75
- const dataProps: {[key: string]: any} = buildDataProps(data)
75
+ const ariaProps: {[key: string]: string} = buildAriaProps(aria)
76
+ const dataProps: {[key: string]: string} = buildDataProps(data)
76
77
  const htmlProps = buildHtmlProps(htmlOptions)
77
- const characterCounter = () => {
78
- return maxCharacters && characterCount ? `${checkIfZero(characterCount)} / ${maxCharacters}` : `${checkIfZero(characterCount)}`
79
- }
80
-
81
78
  const checkIfZero = (characterCount: string | number) => {
82
79
  return characterCount == 0 ? characterCount.toString() : characterCount
83
80
  }
81
+ const characterCounter = () => {
82
+ return maxCharacters && characterCount ? `${checkIfZero(characterCount)} / ${maxCharacters}` : `${checkIfZero(characterCount)}`
83
+ }
84
84
 
85
85
  return (
86
86
  <div
87
- {...ariaProps}
88
- {...dataProps}
89
- {...htmlProps}
90
- className={classes}
87
+ {...ariaProps}
88
+ {...dataProps}
89
+ {...htmlProps}
90
+ className={classes}
91
91
  >
92
92
  <Caption text={label} />
93
93
  {children || (
94
94
  <textarea
95
- className="pb_textarea_kit"
96
- disabled={disabled}
97
- name={name}
98
- onChange={onChange}
99
- placeholder={placeholder}
100
- ref={ref}
101
- required={required}
102
- rows={rows}
103
- value={value}
104
- {...props}
95
+ className="pb_textarea_kit"
96
+ disabled={disabled}
97
+ name={name}
98
+ onChange={onChange}
99
+ placeholder={placeholder}
100
+ ref={ref}
101
+ required={required}
102
+ rows={rows}
103
+ value={value}
104
+ {...props}
105
105
  />
106
106
  )}
107
107
 
108
108
  {error ? (
109
109
  <>
110
110
  {characterCount ? (
111
- <Flex spacing="between" vertical="center">
111
+ <Flex
112
+ spacing="between"
113
+ vertical="center"
114
+ >
112
115
  <FlexItem>
113
- <Body margin="none" status="negative" text={error} />
116
+ <Body
117
+ margin="none"
118
+ status="negative"
119
+ text={error}
120
+ />
114
121
  </FlexItem>
115
122
  <FlexItem>
116
- <Caption margin="none" size="xs" text={characterCounter()} />
123
+ <Caption
124
+ margin="none"
125
+ size="xs"
126
+ text={characterCounter()}
127
+ />
117
128
  </FlexItem>
118
129
  </Flex>
119
130
  ) : (
120
- <Body status="negative" text={error} />
131
+ <Body
132
+ status="negative"
133
+ text={error}
134
+ />
121
135
  )}
122
136
  </>
123
137
  ) : (
124
138
  noCount && (
125
- <Caption margin="none" size="xs" text={characterCounter()} />
139
+ <Caption
140
+ margin="none"
141
+ size="xs"
142
+ text={characterCounter()}
143
+ />
126
144
  )
127
145
  )}
128
146
  </div>
@@ -3,16 +3,16 @@ import PbEnhancedElement from '../pb_enhanced_element'
3
3
  export default class PbTextarea extends PbEnhancedElement {
4
4
  style: {[key: string]: string}
5
5
  scrollHeight: string
6
- static get selector() {
6
+ static get selector(): string {
7
7
  return '.resize_auto textarea'
8
8
  }
9
9
 
10
- onInput() {
10
+ onInput(): void {
11
11
  this.style.height = 'auto'
12
12
  this.style.height = (this.scrollHeight) + 'px'
13
13
  }
14
14
 
15
- connect() {
15
+ connect(): void {
16
16
  this.element.setAttribute('style', 'height:' + (this.element.scrollHeight) + 'px;overflow-y:hidden;')
17
17
  this.element.addEventListener('input', this.onInput, false)
18
18
  }
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
  import classnames from "classnames";
3
3
 
4
+ import { getAllIcons } from "../utilities/icons/allicons"
4
5
  import { buildCss, buildHtmlProps } from "../utilities/props";
5
6
  import { globalProps, GlobalProps } from "../utilities/globalProps";
6
7
  import DateTime from '../pb_kit/dateTime';
@@ -24,7 +25,7 @@ type TimeProps = {
24
25
  unstyled?: boolean;
25
26
  } & GlobalProps
26
27
 
27
- const Time = (props: TimeProps) => {
28
+ const Time = (props: TimeProps): React.ReactElement => {
28
29
  const {
29
30
  align,
30
31
  className,
@@ -42,21 +43,22 @@ const Time = (props: TimeProps) => {
42
43
  globalProps(props),
43
44
  className
44
45
  );
45
-
46
+ const clockIcon = getAllIcons()["clock"]
46
47
  const htmlProps = buildHtmlProps(htmlOptions);
47
48
 
48
49
  return (
49
50
  <div
50
- {...htmlProps}
51
- className={classes}
51
+ {...htmlProps}
52
+ className={classes}
52
53
  >
53
54
  {showIcon && (
54
55
  unstyled
55
56
  ? (
56
57
  <span>
57
- <Icon fixedWidth
58
- icon="clock"
59
- />
58
+ <Icon
59
+ className="svg-inline--fa clock"
60
+ customIcon={clockIcon.icon as unknown as { [key: string]: SVGElement }}
61
+ />
60
62
  {" "}
61
63
  </span>
62
64
  )
@@ -65,10 +67,12 @@ const Time = (props: TimeProps) => {
65
67
  <Body color="light"
66
68
  tag="span"
67
69
  >
68
- <Icon fixedWidth
69
- icon="clock"
70
- size={size === "md" ? "" : "sm"}
71
- />
70
+ <Icon
71
+ className="svg-inline--fa clock"
72
+ customIcon={clockIcon.icon as unknown as { [key: string]: SVGElement }}
73
+ fixedWidth
74
+ size={size === "md" ? "" : "sm"}
75
+ />
72
76
  {" "}
73
77
  </Body>
74
78
  </>
@@ -13,7 +13,7 @@
13
13
  <% if object.unstyled %>
14
14
  <% if object.show_icon %>
15
15
  <span>
16
- <%= pb_rails("icon", props: { icon: "clock", fixed_width: true }) %>
16
+ <%= pb_rails("icon", props: { custom_icon: Playbook::Engine.root.join(clock_icon), fixed_width: true }) %>
17
17
  </span>
18
18
  <% end %>
19
19
 
@@ -27,7 +27,7 @@
27
27
  <% elsif size == "md" %>
28
28
  <% if object.show_icon %>
29
29
  <%= pb_rails("body", props: { color: "light", tag: "span"}) do %>
30
- <%= pb_rails("icon", props: { icon: "clock", fixed_width: true }) %>
30
+ <%= pb_rails("icon", props: { custom_icon: Playbook::Engine.root.join(clock_icon), fixed_width: true }) %>
31
31
  <% end %>
32
32
  <% end %>
33
33
 
@@ -41,7 +41,7 @@
41
41
  <% else %>
42
42
  <% if object.show_icon %>
43
43
  <%= pb_rails("body", props: { color: "light", tag: "span"}) do %>
44
- <%= pb_rails("icon", props: { icon: "clock", fixed_width: true, size: "sm" }) %>
44
+ <%= pb_rails("icon", props: { custom_icon: Playbook::Engine.root.join(clock_icon), fixed_width: true, size: "sm" }) %>
45
45
  <% end %>
46
46
  <% end %>
47
47
 
@@ -38,6 +38,10 @@ module Playbook
38
38
  def pb_date_time
39
39
  Playbook::PbKit::PbDateTime.new(time, timezone)
40
40
  end
41
+
42
+ def clock_icon
43
+ "app/pb_kits/playbook/utilities/icons/clock.svg"
44
+ end
41
45
  end
42
46
  end
43
47
  end
@@ -36,7 +36,7 @@ const dateTimeIso = (dateValue: Date) => {
36
36
  return DateTime.toIso(dateValue)
37
37
  }
38
38
 
39
- const TimeRangeInline = (props: TimeRangeInlineProps) => {
39
+ const TimeRangeInline = (props: TimeRangeInlineProps): React.ReactElement => {
40
40
  const {
41
41
  aria = {},
42
42
  className,
@@ -26,7 +26,7 @@ const TimelineItem = ({
26
26
  iconColor = 'default',
27
27
  lineStyle = 'solid',
28
28
  ...props
29
- }: ItemProps) => {
29
+ }: ItemProps): React.ReactElement => {
30
30
  const timelineItemCss = buildCss('pb_timeline_item_kit', lineStyle)
31
31
 
32
32
  const htmlProps = buildHtmlProps(htmlOptions)
@@ -27,7 +27,7 @@ const Timeline = ({
27
27
  orientation = 'horizontal',
28
28
  showDate = false,
29
29
  ...props
30
- }: TimelineProps) => {
30
+ }: TimelineProps): React.ReactElement => {
31
31
  const ariaProps = buildAriaProps(aria)
32
32
  const dataProps = buildDataProps(data)
33
33
  const htmlProps = buildHtmlProps(htmlOptions)
@@ -8,7 +8,7 @@
8
8
  <br>
9
9
 
10
10
  <%= pb_rails("timestamp", props: {
11
- timestamp: DateTime.now,
11
+ timestamp: DateTime.now - 3.months,
12
12
  variant: "elapsed",
13
13
  show_user: false
14
14
  }) %>
@@ -16,7 +16,7 @@
16
16
  <br>
17
17
 
18
18
  <%= pb_rails("timestamp", props: {
19
- timestamp: DateTime.now,
19
+ timestamp: DateTime.now - 320.days,
20
20
  variant: "elapsed",
21
21
  show_user: false,
22
22
  hide_updated: true
@@ -27,6 +27,18 @@ module Playbook
27
27
  values: %w[default elapsed updated],
28
28
  default: "default"
29
29
 
30
+ # Variables to use with pb_time_ago method
31
+ SECS_FORTY_FIVE = 45
32
+ SECS_PER_MIN = 60
33
+ SECS_PER_HOUR = 60 * SECS_PER_MIN # 3,600 seconds
34
+ SECS_PER_DAY = 24 * SECS_PER_HOUR # 86,400 seconds
35
+ SECS_PER_WEEK = 7 * SECS_PER_DAY # 604,800 seconds
36
+ SECS_PER_26 = 26 * SECS_PER_DAY # 26 days = 2,246,400 seconds
37
+ SECS_PER_MONTH = 4 * SECS_PER_WEEK # 2,419,200 seconds
38
+ SECS_PER_YEAR = 12 * SECS_PER_MONTH # 29,030,400 seconds
39
+ SECS_PER_320 = 320 * SECS_PER_DAY # 320 days = 27,648,000 seconds
40
+ SECS_PER_CENT = 100 * SECS_PER_YEAR # 3,153,600,000 seconds
41
+
30
42
  def classname
31
43
  generate_classname("pb_timestamp_kit", variant_class, align)
32
44
  end
@@ -73,12 +85,44 @@ module Playbook
73
85
 
74
86
  def format_elapsed_string
75
87
  user_string = show_user ? " by #{text}" : ""
76
- datetime_string = " #{time_ago_in_words(pb_date_time.convert_to_timestamp)} ago"
88
+ datetime_string = " #{pb_time_ago(pb_date_time.convert_to_timestamp)} ago"
89
+ datetime_string[1] = hide_updated ? datetime_string[1].upcase : datetime_string[1]
77
90
  updated_string = hide_updated ? "" : "Last updated"
78
-
79
91
  "#{updated_string}#{user_string}#{datetime_string}"
80
92
  end
81
93
 
94
+ def pb_time_ago(value)
95
+ time_ago = DateTime.now.to_i - value.to_i
96
+ case time_ago
97
+ when (0...SECS_FORTY_FIVE)
98
+ "a few seconds"
99
+ when (SECS_FORTY_FIVE...SECS_PER_MIN)
100
+ "a minute"
101
+ when (SECS_PER_MIN...SECS_PER_HOUR)
102
+ time = time_ago / SECS_PER_MIN
103
+ time == 1 ? "a minute" : "#{time_ago / SECS_PER_MIN} minutes"
104
+ when (SECS_PER_HOUR...SECS_PER_DAY)
105
+ time = time_ago / SECS_PER_HOUR
106
+ time == 1 ? "an hour" : "#{time_ago / SECS_PER_HOUR} hours"
107
+ when (SECS_PER_DAY...SECS_PER_WEEK)
108
+ time = time_ago / SECS_PER_DAY
109
+ time == 1 ? "a day" : "#{time_ago / SECS_PER_DAY} days"
110
+ when (SECS_PER_WEEK...SECS_PER_26)
111
+ time = time_ago / SECS_PER_WEEK
112
+ time == 1 ? "a week" : "#{time_ago / SECS_PER_WEEK} weeks"
113
+ when (SECS_PER_26...SECS_PER_MONTH)
114
+ "a month"
115
+ when (SECS_PER_MONTH...SECS_PER_320)
116
+ time = time_ago / SECS_PER_MONTH
117
+ time == 1 ? "a month" : "#{time_ago / SECS_PER_MONTH} months"
118
+ when (SECS_PER_320...SECS_PER_YEAR)
119
+ "a year"
120
+ when (SECS_PER_YEAR...SECS_PER_CENT)
121
+ time = time_ago / SECS_PER_YEAR
122
+ time == 1 ? "a year" : "#{time_ago / SECS_PER_YEAR} years"
123
+ end
124
+ end
125
+
82
126
  def datetime_or_text
83
127
  timestamp ? format_datetime_string : text
84
128
  end