playbook_ui 16.6.0.pre.alpha.emptystatepresets15848 → 16.6.0.pre.alpha.play294216115

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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_grouped_headers_composition.jsx +15 -1
  3. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_infinite_scroll.jsx +2 -2
  4. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_inline_row_loading.jsx +2 -2
  5. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows.jsx +2 -2
  6. data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_mock_data_inline_loading_empty_children.json +41 -0
  7. data/app/pb_kits/playbook/pb_bread_crumbs/docs/_bread_crumbs_default.jsx +5 -5
  8. data/app/pb_kits/playbook/pb_button/_button.scss +24 -23
  9. data/app/pb_kits/playbook/pb_button/button.rb +3 -1
  10. data/app/pb_kits/playbook/pb_date_picker/date_picker.test.js +30 -0
  11. data/app/pb_kits/playbook/pb_dialog/index.js +6 -1
  12. data/app/pb_kits/playbook/pb_draggable/index.js +6 -1
  13. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +51 -2
  14. data/app/pb_kits/playbook/pb_empty_state/_empty_state.tsx +9 -22
  15. data/app/pb_kits/playbook/pb_empty_state/docs/example.yml +0 -2
  16. data/app/pb_kits/playbook/pb_empty_state/docs/index.js +0 -1
  17. data/app/pb_kits/playbook/pb_empty_state/empty_state.html.erb +1 -3
  18. data/app/pb_kits/playbook/pb_empty_state/empty_state.rb +0 -43
  19. data/app/pb_kits/playbook/pb_icon/_icon.scss +130 -0
  20. data/app/pb_kits/playbook/pb_icon/_icon.tsx +29 -13
  21. data/app/pb_kits/playbook/pb_icon/icon.test.js +70 -1
  22. data/app/pb_kits/playbook/pb_kit/dateTime.ts +4 -22
  23. data/app/pb_kits/playbook/pb_pagination/_pagination.scss +274 -23
  24. data/app/pb_kits/playbook/pb_pagination/docs/_pagination_default.html.erb +1 -1
  25. data/app/pb_kits/playbook/pb_pagination/docs/_pagination_external_control.jsx +22 -1
  26. data/app/pb_kits/playbook/pb_pagination/docs/_pagination_page_change.jsx +22 -2
  27. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +68 -0
  28. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_show_placeholder.html.erb +5 -0
  29. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_show_placeholder.jsx +14 -0
  30. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_show_placeholder.md +3 -0
  31. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +2 -0
  32. data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
  33. data/app/pb_kits/playbook/pb_phone_number_input/kit.schema.json +8 -0
  34. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +3 -0
  35. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.test.js +79 -2
  36. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_templates.jsx +76 -1
  37. data/app/pb_kits/playbook/pb_select/docs/_select_error.jsx +1 -1
  38. data/app/pb_kits/playbook/pb_select/docs/_select_inline.jsx +1 -1
  39. data/app/pb_kits/playbook/pb_select/docs/_select_inline_compact.jsx +1 -1
  40. data/app/pb_kits/playbook/pb_select/docs/_select_inline_show_arrow.jsx +1 -1
  41. data/app/pb_kits/playbook/pb_select/docs/_select_multiple.html.erb +3 -3
  42. data/app/pb_kits/playbook/pb_select/docs/_select_multiple.jsx +5 -5
  43. data/app/pb_kits/playbook/pb_select/docs/_select_react_hook.jsx +5 -5
  44. data/app/pb_kits/playbook/pb_select/docs/_select_required_indicator.jsx +1 -1
  45. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_react_hook.jsx +2 -2
  46. data/app/pb_kits/playbook/tokens/exports/exports.d.ts +1 -5
  47. data/app/pb_kits/playbook/utilities/icons/playbookIconResolver.ts +69 -0
  48. data/dist/chunks/{_pb_line_graph-EzcacMw_.js → _pb_line_graph-D7f-RfJJ.js} +1 -1
  49. data/dist/chunks/_typeahead-BO3J1J3f.js +1 -0
  50. data/dist/chunks/{globalProps-6Hsm3bJX.js → globalProps-BwwZkfTI.js} +1 -1
  51. data/dist/chunks/{lib-o4u12zAw.js → lib-Ch18RlJa.js} +1 -1
  52. data/dist/chunks/vendor.js +2 -2
  53. data/dist/playbook-rails-react-bindings.js +1 -1
  54. data/dist/playbook-rails.js +1 -1
  55. data/dist/playbook.css +1 -1
  56. data/lib/playbook/pagination_renderer.rb +119 -8
  57. data/lib/playbook/version.rb +1 -1
  58. metadata +11 -16
  59. data/app/pb_kits/playbook/pb_advanced_table/docs/_mock_data_inline_loading.js +0 -200
  60. data/app/pb_kits/playbook/pb_advanced_table/docs/_mock_data_inline_loading_empty_children.js +0 -42
  61. data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_grouped_headers_composition_mock_data.json +0 -98
  62. data/app/pb_kits/playbook/pb_empty_state/__mocks__/assetUrl.ts +0 -1
  63. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_presets.html.erb +0 -14
  64. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_presets.jsx +0 -27
  65. data/app/pb_kits/playbook/pb_empty_state/docs/default_image/this_is_fine.svg +0 -21
  66. data/app/pb_kits/playbook/pb_empty_state/docs/default_image/travolta_lost.gif +0 -0
  67. data/app/pb_kits/playbook/pb_pagination/docs/data.js +0 -23
  68. data/app/pb_kits/playbook/pb_rich_text_editor/docs/templates.js +0 -75
  69. data/dist/chunks/_typeahead-BYUXg9ZT.js +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f403796e53bc3b998e1c127a73fec5be5d4ecdff23f011d4bdf66777e5d8549f
4
- data.tar.gz: 27bc94414daabd7e53b42d503e86aaedfbc3edff2332d8a17506d3c8823bd0bd
3
+ metadata.gz: f4decbfeb1e045070d591f56daf85d3ef2794bf2855d33e889f00fb2dc694be7
4
+ data.tar.gz: 04b363904b41e8d0b30e2752af2c1e07d6cf6ca38ca5ae0f3576b515fcaa8c23
5
5
  SHA512:
6
- metadata.gz: 1e215435bd8d6420d587f0db1043b603f272ef79020bee8e3f0abf597daac8473b6d0a9481dfb901a7bb364a56109f975b40f557436d6decba7652db5006b8e4
7
- data.tar.gz: 50a69d0bc34bf5fbb44ee650b4158fe1e4dd8b51b84a51243ef7b3a2c428e82ccf0943a399dc2a6b5c50c20480260b4c4b5b79c1bf18a9624fc47e1809eaec64
6
+ metadata.gz: 42918e61a6d599a6b5033053eaad2a5d09139d2d977d85f766f0fbd5c65f0e05608bef3c57fa787ce7efd3e847d785ba198472bd532e436ffbc2d7c161ad3314
7
+ data.tar.gz: 13bc1c4045f5d400052204a4a495d345aeb2b814de5ba3d8c87e510327e18ecaa80d18d99b307d75a9d3e8a7c2cf9c2e0b2466ea7a30c41f9d282aad0766275f
@@ -9,7 +9,21 @@ import ListItem from "../../pb_list/_list_item"
9
9
  import PbReactPopover from "../../pb_popover/_popover"
10
10
  import SectionSeparator from "../../pb_section_separator/_section_separator"
11
11
  import StarRating from "../../pb_star_rating/_star_rating"
12
- import COMPOSITION_MOCK_DATA from "./advanced_table_grouped_headers_composition_mock_data.json"
12
+
13
+ const COMPOSITION_MOCK_DATA = [
14
+ { id: "1", year: "2015", newEnrollments: "12", scheduledMeetings: "40", attendanceRate: "62%", classCompletionRate: "28%" },
15
+ { id: "2", year: "2016", newEnrollments: "88", scheduledMeetings: "12", attendanceRate: "71%", classCompletionRate: "55%" },
16
+ { id: "3", year: "2017", newEnrollments: "34", scheduledMeetings: "67", attendanceRate: "58%", classCompletionRate: "41%" },
17
+ { id: "4", year: "2018", newEnrollments: "05", scheduledMeetings: "91", attendanceRate: "44%", classCompletionRate: "73%" },
18
+ { id: "5", year: "2019", newEnrollments: "61", scheduledMeetings: "19", attendanceRate: "83%", classCompletionRate: "36%" },
19
+ { id: "6", year: "2020", newEnrollments: "19", scheduledMeetings: "54", attendanceRate: "67%", classCompletionRate: "62%" },
20
+ { id: "7", year: "2021", newEnrollments: "73", scheduledMeetings: "08", attendanceRate: "52%", classCompletionRate: "49%" },
21
+ { id: "8", year: "2022", newEnrollments: "50", scheduledMeetings: "50", attendanceRate: "75%", classCompletionRate: "45%" },
22
+ { id: "9", year: "2023", newEnrollments: "95", scheduledMeetings: "03", attendanceRate: "69%", classCompletionRate: "81%" },
23
+ { id: "10", year: "2024", newEnrollments: "27", scheduledMeetings: "76", attendanceRate: "91%", classCompletionRate: "22%" },
24
+ { id: "11", year: "2025", newEnrollments: "41", scheduledMeetings: "33", attendanceRate: "48%", classCompletionRate: "94%" },
25
+ { id: "12", year: "2026", newEnrollments: "66", scheduledMeetings: "66", attendanceRate: "55%", classCompletionRate: "58%" },
26
+ ]
13
27
 
14
28
  const LEAF_COUNT = "newEnrollments"
15
29
  const LEAF_SCHEDULED = "scheduledMeetings"
@@ -1,6 +1,6 @@
1
1
  import React from "react"
2
2
  import AdvancedTable from '../_advanced_table'
3
- import MOCK_DATA from "./advanced_table_mock_data_infinite_scroll.json"
3
+ import INFINITE_SCROLL_MOCK_DATA from "./advanced_table_mock_data_infinite_scroll.json"
4
4
 
5
5
  const AdvancedTableInfiniteScroll = (props) => {
6
6
  const columnDefinitions = [
@@ -39,7 +39,7 @@ const AdvancedTableInfiniteScroll = (props) => {
39
39
  <div>
40
40
  <AdvancedTable
41
41
  columnDefinitions={columnDefinitions}
42
- tableData={MOCK_DATA}
42
+ tableData={INFINITE_SCROLL_MOCK_DATA}
43
43
  virtualizedRows
44
44
  {...props}
45
45
  />
@@ -1,8 +1,8 @@
1
1
  import React from "react"
2
2
  import AdvancedTable from '../../pb_advanced_table/_advanced_table'
3
3
  import Caption from '../../pb_caption/_caption'
4
- import { MOCK_DATA_INLINE_LOADING } from "./_mock_data_inline_loading"
5
- import { MOCK_DATA_INLINE_LOADING_EMPTY_CHILDREN } from "./_mock_data_inline_loading_empty_children"
4
+ import MOCK_DATA_INLINE_LOADING from "./advanced_table_mock_data_inline_loading.json"
5
+ import MOCK_DATA_INLINE_LOADING_EMPTY_CHILDREN from "./advanced_table_mock_data_inline_loading_empty_children.json"
6
6
 
7
7
  const AdvancedTableInlineRowLoading = (props) => {
8
8
  const columnDefinitions = [
@@ -1,6 +1,6 @@
1
1
  import React, { useState } from "react"
2
2
  import AdvancedTable from '../_advanced_table'
3
- import MOCK_DATA from "./advanced_table_mock_data_with_id.json"
3
+ import MOCK_DATA_WITH_ID from "./advanced_table_mock_data_with_id.json"
4
4
 
5
5
  const AdvancedTableRowPinning = (props) => {
6
6
  const columnDefinitions = [
@@ -43,7 +43,7 @@ const AdvancedTableRowPinning = (props) => {
43
43
  columnDefinitions={columnDefinitions}
44
44
  maxHeight="xs"
45
45
  pinnedRows={{value: pinnedRows, onChange: setPinnedRows}}
46
- tableData={MOCK_DATA}
46
+ tableData={MOCK_DATA_WITH_ID}
47
47
  tableProps={{sticky: true}}
48
48
  {...props}
49
49
  >
@@ -0,0 +1,41 @@
1
+ [
2
+ {
3
+ "year": "2021",
4
+ "quarter": null,
5
+ "month": null,
6
+ "day": null,
7
+ "newEnrollments": "20",
8
+ "scheduledMeetings": "10",
9
+ "attendanceRate": "51%",
10
+ "completedClasses": "3",
11
+ "classCompletionRate": "33%",
12
+ "graduatedStudents": "19",
13
+ "children": []
14
+ },
15
+ {
16
+ "year": "2022",
17
+ "quarter": null,
18
+ "month": null,
19
+ "day": null,
20
+ "newEnrollments": "25",
21
+ "scheduledMeetings": "17",
22
+ "attendanceRate": "75%",
23
+ "completedClasses": "5",
24
+ "classCompletionRate": "45%",
25
+ "graduatedStudents": "32",
26
+ "children": []
27
+ },
28
+ {
29
+ "year": "2023",
30
+ "quarter": null,
31
+ "month": null,
32
+ "day": null,
33
+ "newEnrollments": "10",
34
+ "scheduledMeetings": "15",
35
+ "attendanceRate": "65%",
36
+ "completedClasses": "4",
37
+ "classCompletionRate": "49%",
38
+ "graduatedStudents": "29",
39
+ "children": []
40
+ }
41
+ ]
@@ -4,7 +4,7 @@ import Icon from "../../pb_icon/_icon"
4
4
  import Title from "../../pb_title/_title"
5
5
  import BreadCrumbItem from '../_bread_crumb_item'
6
6
 
7
- const Link = (props) => <BreadCrumbItem {...props} />
7
+ const LinkSection = (props) => <BreadCrumbItem {...props} />
8
8
  const BreadCrumbsDefault = (props) => {
9
9
  return (
10
10
  <BreadCrumbs
@@ -35,7 +35,7 @@ const BreadCrumbsDefault = (props) => {
35
35
  size="1x"
36
36
  {...props}
37
37
  />
38
- <Link
38
+ <LinkSection
39
39
  {...props}
40
40
  href="/users"
41
41
  >
@@ -46,20 +46,20 @@ const BreadCrumbsDefault = (props) => {
46
46
  text="Users"
47
47
  {...props}
48
48
  />
49
- </Link>
49
+ </LinkSection>
50
50
  <Icon
51
51
  icon="user"
52
52
  size="1x"
53
53
  {...props}
54
54
  />
55
- <Link {...props}>
55
+ <LinkSection {...props}>
56
56
  <Title
57
57
  size="4"
58
58
  tag="span"
59
59
  text="User"
60
60
  {...props}
61
61
  />
62
- </Link>
62
+ </LinkSection>
63
63
  </BreadCrumbs>
64
64
  )
65
65
  }
@@ -11,6 +11,13 @@ $pb_button_sizes: (
11
11
  "lg": ($font_large - 2px),
12
12
  );
13
13
 
14
+ // Icon-only: fixed square hit targets (not derived from font padding).
15
+ $pb_button_icon_only_dimensions: (
16
+ "sm": 35px,
17
+ "md": 40px,
18
+ "lg": 45px,
19
+ );
20
+
14
21
  // Base button class
15
22
  .pb_button_kit {
16
23
  @include pb_button;
@@ -113,32 +120,26 @@ $pb_button_sizes: (
113
120
  }
114
121
  }
115
122
 
116
- // Icon-only button (icon prop set, no text) - square with equal padding
117
- // Rails: uses .pb_button_icon_only class
118
- // React: when pb_button_content is empty (no text). Do not match when content has
119
- // text + icon (e.g. "Exit Fullscreen" + FA icon) which can include empty spans.
123
+ // Icon-only button (icon prop set, no text) — fixed squares; icon scales via font-size from size prop.
124
+ // Rails: .pb_button_icon_only; React: class or :has(...) when label is empty.
125
+ // Rails uses a truly empty .pb_button_content; React wraps text in a child span (may be empty).
120
126
  &.pb_button_icon_only,
121
127
  &:has(.pb_button_content:empty) {
122
128
  aspect-ratio: 1;
123
- min-width: auto;
124
- width: auto;
125
- height: auto;
126
- padding: $pb_button_v_padding !important;
127
- min-height: ($pb_button_v_padding * 2) + $font_small;
128
-
129
- &.pb_button_size_sm {
130
- padding: $font_smaller !important;
131
- min-height: ($font_smaller * 2) + $font_smaller;
132
- }
133
-
134
- &.pb_button_size_md {
135
- padding: $font_small !important;
136
- min-height: ($font_small * 2) + $font_small;
137
- }
138
-
139
- &.pb_button_size_lg {
140
- padding: ($font_large - 2px) !important;
141
- min-height: (($font_large - 2px) * 2) + ($font_large - 2px);
129
+ box-sizing: border-box;
130
+ $pb_button_icon_only_default: map-get($pb_button_icon_only_dimensions, "md");
131
+ width: $pb_button_icon_only_default;
132
+ min-width: $pb_button_icon_only_default;
133
+ height: $pb_button_icon_only_default;
134
+ min-height: $pb_button_icon_only_default;
135
+ padding: 0 !important;
136
+ @each $name, $dim in $pb_button_icon_only_dimensions {
137
+ &.pb_button_size_#{$name} {
138
+ width: $dim;
139
+ min-width: $dim;
140
+ height: $dim;
141
+ min-height: $dim;
142
+ }
142
143
  }
143
144
 
144
145
  // Remove margins from icons
@@ -73,8 +73,10 @@ module Playbook
73
73
  emoji_regex.match?(icon)
74
74
  end
75
75
 
76
+ # Icon-only = icon with no label. Label may come from `text` or from a block (e.g. CopyButton);
77
+ # block content must not be treated as icon-only when `text` is unset.
76
78
  def icon_only?
77
- icon.present? && text.blank? && variant != "reaction"
79
+ icon.present? && text.blank? && children.blank? && variant != "reaction"
78
80
  end
79
81
 
80
82
  def classname
@@ -310,4 +310,34 @@ describe('DatePicker Kit', () => {
310
310
  expect(label).toBeInTheDocument()
311
311
  expect(kit).not.toHaveTextContent("*")
312
312
  })
313
+
314
+ test('Last month quickpick includes the correct last day of previous month', async () => {
315
+ const testId = 'datepicker-last-month'
316
+ render(
317
+ <DatePicker
318
+ allowInput
319
+ data={{ testid: testId }}
320
+ mode="range"
321
+ pickerId="date-picker-last-month"
322
+ placeholder="mm/dd/yyyy to mm/dd/yyyy"
323
+ selectionType="quickpick"
324
+ />
325
+ )
326
+
327
+ const kit = screen.getByTestId(testId)
328
+ const input = within(kit).getByPlaceholderText('mm/dd/yyyy to mm/dd/yyyy')
329
+
330
+ fireEvent(input, new MouseEvent('click', { bubbles: true, cancelable: true }))
331
+
332
+ const lastMonth = within(kit).getByText('Last month')
333
+ fireEvent(lastMonth, new MouseEvent('click', { bubbles: true, cancelable: true }))
334
+
335
+ await waitFor(() => {
336
+ expect(input).toHaveValue(
337
+ DateTime.getPreviousMonthStartDate(new Date()).formatDate() +
338
+ " to " +
339
+ DateTime.getPreviousMonthEndDate(new Date()).formatDate()
340
+ )
341
+ })
342
+ })
313
343
  })
@@ -16,7 +16,12 @@ export default class PbDialog extends PbEnhancedElement {
16
16
  this.domContentLoadedHandler = () => this.setupDialog()
17
17
  this.turboFrameLoadHandler = () => this.setupDialog()
18
18
 
19
- window.addEventListener("DOMContentLoaded", this.domContentLoadedHandler)
19
+ // If DOM is already loaded, setup immediately; otherwise wait for DOMContentLoaded
20
+ if (document.readyState === "loading") {
21
+ window.addEventListener("DOMContentLoaded", this.domContentLoadedHandler)
22
+ } else {
23
+ this.setupDialog()
24
+ }
20
25
  window.addEventListener("turbo:frame-load", this.turboFrameLoadHandler)
21
26
 
22
27
  // Code for custom_event_type setup (can take multiple events in a string separated by commas)
@@ -22,7 +22,12 @@ export default class PbDraggable extends PbEnhancedElement {
22
22
  this.dragZoneType = "";
23
23
  this.dragZoneColor = "";
24
24
 
25
- document.addEventListener("DOMContentLoaded", () => this.bindEventListeners());
25
+ // If DOM is already loaded, bind immediately; otherwise wait for DOMContentLoaded
26
+ if (document.readyState === "loading") {
27
+ document.addEventListener("DOMContentLoaded", () => this.bindEventListeners());
28
+ } else {
29
+ this.bindEventListeners();
30
+ }
26
31
  }
27
32
 
28
33
  setState(newState) {
@@ -1,8 +1,8 @@
1
1
  import React, { useState } from "react"
2
- import { render, screen, fireEvent } from "../utilities/test-utils"
2
+ import { render, screen, fireEvent, waitFor } from "../utilities/test-utils"
3
3
 
4
4
  import { Dropdown, Icon, IconCircle } from 'playbook-ui'
5
-
5
+ import DateTime from "../pb_kit/dateTime.ts"
6
6
 
7
7
  const testId = 'dropdown'
8
8
 
@@ -778,3 +778,52 @@ test("requiredIndicator prop renders asterisk when true", () => {
778
778
  expect(label).toBeInTheDocument();
779
779
  expect(kit).toHaveTextContent("*");
780
780
  });
781
+
782
+ describe("quickpick Last Month range when current month is shorter than the previous month", () => {
783
+ const quickpickTestId = "dropdown-quickpick-last-month-march"
784
+
785
+ const formatDate = (date) => {
786
+ const month = (date.getMonth() + 1).toString().padStart(2, "0")
787
+ const day = date.getDate().toString().padStart(2, "0")
788
+ const year = date.getFullYear()
789
+ return `${month}/${day}/${year}`
790
+ }
791
+
792
+ beforeEach(() => {
793
+ jest.setSystemTime(new Date(2026, 3, 15, 12, 0, 0))
794
+ })
795
+
796
+ afterEach(() => {
797
+ jest.setSystemTime()
798
+ })
799
+
800
+ test("selecting Last Month matches DateTime previous-month range (full March when today is in April)", async () => {
801
+ const onSelect = jest.fn()
802
+ const now = new Date()
803
+
804
+ render(
805
+ <Dropdown
806
+ data={{ testid: quickpickTestId }}
807
+ onSelect={onSelect}
808
+ variant="quickpick"
809
+ />
810
+ )
811
+
812
+ const kit = screen.getByTestId(quickpickTestId)
813
+ const lastMonthOption = Array.from(kit.querySelectorAll(".pb_dropdown_option_list")).find(
814
+ (el) => el.textContent === "Last Month"
815
+ )
816
+
817
+ expect(lastMonthOption).toBeTruthy()
818
+ fireEvent.click(lastMonthOption)
819
+
820
+ await waitFor(() => {
821
+ expect(onSelect).toHaveBeenCalled()
822
+ })
823
+
824
+ const [startDate, endDate] = onSelect.mock.calls[0][0].value
825
+
826
+ expect(formatDate(startDate)).toBe(formatDate(DateTime.getPreviousMonthStartDate(now)))
827
+ expect(formatDate(endDate)).toBe(formatDate(DateTime.getPreviousMonthEndDate(now)))
828
+ })
829
+ })
@@ -12,8 +12,6 @@ import Flex from "../pb_flex/_flex"
12
12
  import FlexItem from "../pb_flex/_flex_item"
13
13
  import Image from "../pb_image/_image"
14
14
  import computer from "./docs/default_image/utils"
15
- import thisIsFineImageUrl from "./docs/default_image/this_is_fine.svg?url"
16
- import travoltaLostImageUrl from "./docs/default_image/travolta_lost.gif?url"
17
15
 
18
16
  type EventHandler = (React.MouseEventHandler<HTMLElement>)
19
17
 
@@ -25,7 +23,6 @@ type EmptyStateProps = {
25
23
  description?: string,
26
24
  header?: string,
27
25
  id?: string,
28
- /** Built-in illustrations: `default`, `this_is_fine`, `travolta_lost`, or a custom image URL */
29
26
  image?: string,
30
27
  linkButton?: string,
31
28
  onLinkButtonClick?: EventHandler,
@@ -137,22 +134,6 @@ const EmptyState = (props: EmptyStateProps) => {
137
134
  return `data:image/svg+xml,${encodedSvg}`
138
135
  }
139
136
 
140
- const resolvePresetImage = (): { alt: string, url: string } | null => {
141
- if (!image) return null
142
- if (image === "default") {
143
- return { alt: "Empty state illustration", url: getSvgAsDataUrl() }
144
- }
145
- if (image === "this_is_fine") {
146
- return { alt: "This is fine illustration", url: thisIsFineImageUrl }
147
- }
148
- if (image === "travolta_lost") {
149
- return { alt: "Confused reaction illustration", url: travoltaLostImageUrl }
150
- }
151
- return { alt: "Empty state image", url: image }
152
- }
153
-
154
- const presetImage = resolvePresetImage()
155
-
156
137
  const layout = (
157
138
  <div {...ariaProps}
158
139
  {...dataProps}
@@ -167,11 +148,17 @@ const EmptyState = (props: EmptyStateProps) => {
167
148
  vertical="center"
168
149
  >
169
150
 
170
- { presetImage ? (
151
+ { image && image === 'default' ? (
152
+ <Image
153
+ alt="test"
154
+ htmlOptions={{ width: configs.imageWidth, height: "auto", alignment: "start" }}
155
+ url={getSvgAsDataUrl()}
156
+ />
157
+ ) : image && image ? (
171
158
  <Image
172
- alt={presetImage.alt}
159
+ alt="test"
173
160
  htmlOptions={{ width: configs.imageWidth, height: "auto", alignment: "start" }}
174
- url={presetImage.url}
161
+ url={image}
175
162
  />
176
163
  ) : null}
177
164
 
@@ -1,14 +1,12 @@
1
1
  examples:
2
2
  rails:
3
3
  - empty_state_default: Default
4
- - empty_state_presets: Illustration presets
5
4
  - empty_state_size: Size
6
5
  - empty_state_orientation: Orientation
7
6
  - empty_state_alignment: Alignment
8
7
 
9
8
  react:
10
9
  - empty_state_default: Default
11
- - empty_state_presets: Illustration presets
12
10
  - empty_state_size: Size
13
11
  - empty_state_orientation: Orientation
14
12
  - empty_state_alignment: Alignment
@@ -1,5 +1,4 @@
1
1
  export { default as EmptyStateDefault } from './_empty_state_default.jsx'
2
- export { default as EmptyStatePresets } from './_empty_state_presets.jsx'
3
2
  export { default as EmptyStateOrientation } from './_empty_state_orientation.jsx'
4
3
  export { default as EmptyStateSize } from './_empty_state_size.jsx'
5
4
  export { default as EmptyStateAlignment } from './_empty_state_alignment.jsx'
@@ -1,8 +1,6 @@
1
1
  <%= pb_content_tag do %>
2
2
  <%= pb_rails("flex", props: { align: flex_align, orientation: config[:flex_direction], padding_left: padding_size, padding_right: padding_size, vertical: "center", classname: config[:scss_class], max_width: "100%" }) do %>
3
- <% if resolved_image_url.present? %>
4
- <%= pb_rails("image", props: { url: resolved_image_url, alt: image_alt_text, html_options: { width: config[:image_width], height: "auto", alignment: "start" } }) %>
5
- <% end %>
3
+ <%= pb_rails("image", props: { url: image == "default" ? default_image_data_uri : image, alt: "Empty State Image", html_options: { width: config[:image_width], height: "auto", alignment: "start" } }) %>
6
4
  <%= pb_rails("flex/flex_item") do %>
7
5
  <%= pb_rails("title", props: { text: object.header, size: config[:title_size], padding_bottom: config[:title_padding], text_align: alignment }) %>
8
6
  <% if size == "sm" %>
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "base64"
4
-
5
3
  module Playbook
6
4
  module PbEmptyState
7
5
  class EmptyState < Playbook::KitBase
@@ -106,47 +104,6 @@ module Playbook
106
104
  "data:image/svg+xml,#{encoded}"
107
105
  end
108
106
 
109
- def resolved_image_url
110
- case image
111
- when "default"
112
- default_image_data_uri
113
- when "this_is_fine"
114
- svg_preset_data_uri("this_is_fine.svg")
115
- when "travolta_lost"
116
- gif_preset_data_uri("travolta_lost.gif")
117
- when nil, ""
118
- nil
119
- else
120
- image
121
- end
122
- end
123
-
124
- def image_alt_text
125
- case image
126
- when "this_is_fine"
127
- "This is fine illustration"
128
- when "travolta_lost"
129
- "Confused reaction illustration"
130
- when "default"
131
- "Empty state illustration"
132
- else
133
- "Empty state image"
134
- end
135
- end
136
-
137
- def svg_preset_data_uri(filename)
138
- path = File.join(__dir__, "docs", "default_image", filename)
139
- svg = File.read(path)
140
- "data:image/svg+xml,#{ERB::Util.url_encode(svg)}"
141
- end
142
-
143
- def gif_preset_data_uri(filename)
144
- path = File.join(__dir__, "docs", "default_image", filename)
145
- binary = File.binread(path)
146
- b64 = Base64.strict_encode64(binary)
147
- "data:image/gif;base64,#{b64}"
148
- end
149
-
150
107
  def padding_size
151
108
  size == "sm" ? "xs" : "xl"
152
109
  end
@@ -25,6 +25,136 @@ $icon_colors: map-merge($merge_kits8, $accessible_status_icon_background_colors)
25
25
  }
26
26
  }
27
27
 
28
+ .pb_playbook_icon {
29
+ display: inline-block;
30
+ line-height: 1;
31
+
32
+ &::before {
33
+ width: 1em;
34
+ height: 1em;
35
+ }
36
+
37
+ &.svg_inverse::before {
38
+ background: #fff;
39
+ }
40
+
41
+ &.svg_border {
42
+ border-color: #eee;
43
+ border-radius: .1em;
44
+ border-style: solid;
45
+ border-width: .08em;
46
+ padding: .2em .25em .15em;
47
+ }
48
+
49
+ &.svg_fw {
50
+ text-align: center;
51
+ width: 1.25em;
52
+ }
53
+
54
+ &.pull_left {
55
+ float: left;
56
+ margin-right: .3em;
57
+ }
58
+
59
+ &.pull_right {
60
+ float: right;
61
+ margin-left: .3em;
62
+ }
63
+
64
+ &.svg_xs {
65
+ font-size: 0.75em;
66
+ }
67
+
68
+ &.svg_sm {
69
+ font-size: 0.875em;
70
+ }
71
+
72
+ &.svg_lg {
73
+ font-size: 1.25em;
74
+ }
75
+
76
+ &.svg_1x {
77
+ font-size: 1em;
78
+ }
79
+
80
+ &.svg_2x {
81
+ font-size: 2em;
82
+ }
83
+
84
+ &.svg_3x {
85
+ font-size: 3em;
86
+ }
87
+
88
+ &.svg_4x {
89
+ font-size: 4em;
90
+ }
91
+
92
+ &.svg_5x {
93
+ font-size: 5em;
94
+ }
95
+
96
+ &.svg_6x {
97
+ font-size: 6em;
98
+ }
99
+
100
+ &.svg_7x {
101
+ font-size: 7em;
102
+ }
103
+
104
+ &.svg_8x {
105
+ font-size: 8em;
106
+ }
107
+
108
+ &.svg_9x {
109
+ font-size: 9em;
110
+ }
111
+
112
+ &.svg_10x {
113
+ font-size: 10em;
114
+ }
115
+
116
+ &.rotate_90 {
117
+ transform: rotate(90deg);
118
+ }
119
+
120
+ &.rotate_180 {
121
+ transform: rotate(180deg);
122
+ }
123
+
124
+ &.rotate_270 {
125
+ transform: rotate(270deg);
126
+ }
127
+
128
+ &.flip_horizontal {
129
+ transform: scaleX(-1);
130
+ }
131
+
132
+ &.flip_vertical {
133
+ transform: scaleY(-1);
134
+ }
135
+
136
+ &.flip_horizontal.flip_vertical {
137
+ transform: scaleX(-1) scaleY(-1);
138
+ }
139
+
140
+ &.pulse {
141
+ animation-name: pb_icon_spin;
142
+ animation-direction: normal;
143
+ animation-duration: 1s;
144
+ animation-iteration-count: infinite;
145
+ animation-timing-function: steps(8);
146
+ }
147
+
148
+ &.spin {
149
+ animation-name: pb_icon_spin;
150
+ animation-delay: 0s;
151
+ animation-direction: normal;
152
+ animation-duration: 2s;
153
+ animation-iteration-count: infinite;
154
+ animation-timing-function: linear;
155
+ }
156
+ }
157
+
28
158
  // Rails custom icon styles
29
159
  svg.pb_custom_icon {
30
160
  width: 1em;