playbook_ui 13.31.0 → 13.32.0.pre.alpha.play1416movealiaslogic3239

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_button/_button.scss +3 -3
  3. data/app/pb_kits/playbook/pb_button/_button_mixins.scss +3 -2
  4. data/app/pb_kits/playbook/pb_caption/_caption_mixin.scss +1 -1
  5. data/app/pb_kits/playbook/pb_dashboard/commonSettings.js +1 -1
  6. data/app/pb_kits/playbook/pb_dashboard/pbChartsDarkTheme.ts +1 -1
  7. data/app/pb_kits/playbook/pb_dashboard/pbChartsLightTheme.ts +1 -1
  8. data/app/pb_kits/playbook/pb_date_year_stacked/docs/_date_year_stacked_default.jsx +4 -1
  9. data/app/pb_kits/playbook/pb_draggable/context/index.tsx +15 -1
  10. data/app/pb_kits/playbook/pb_draggable/context/types.ts +5 -0
  11. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_default.jsx +14 -19
  12. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_default.md +5 -3
  13. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_cards.md +7 -3
  14. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list.md +3 -5
  15. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list.md +3 -5
  16. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +3 -1
  17. data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +2 -0
  18. data/app/pb_kits/playbook/pb_dropdown/index.js +33 -4
  19. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +9 -0
  20. data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +1 -1
  21. data/app/pb_kits/playbook/pb_icon/_icon.tsx +6 -37
  22. data/app/pb_kits/playbook/pb_icon/icon.rb +9 -3
  23. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +8 -23
  24. data/app/pb_kits/playbook/tokens/_titles.scss +4 -4
  25. data/app/pb_kits/playbook/tokens/_typography.scss +10 -10
  26. data/dist/menu.yml +566 -472
  27. data/dist/playbook-rails.js +7 -7
  28. data/dist/reset.css +1 -1
  29. data/lib/playbook/version.rb +2 -2
  30. metadata +5 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c02852f26be30f0f9abff5ba3089c03c4d9f6878880b2e3f59827e7b556f8c3d
4
- data.tar.gz: a5c30e259ea3d6a77135c2f6172d607ddb105732e20caf60f68d1d1f014bf468
3
+ metadata.gz: 38d2ad5fae80d023caae7a74a96bf549e74693d82376000d2d056ecdd94e5948
4
+ data.tar.gz: c3de45c50a99868c1a157179eb8912acfd173337bd94af3eb166c42d01c051ac
5
5
  SHA512:
6
- metadata.gz: d14c183e1ef95272881479defd28dec0aa49a6ee8539af55aa630cdd493aa48918830906465d6a46c0caf405a1c2a8b2b7dd5fc894f0031feb62bbd21341ae22
7
- data.tar.gz: 26cd7b2d68304e1c80c4bf3e1bc9ce5cc07cf5c378c82e52bac4541abd61ca0a5a817ded5c6abde4282cb7c785b484778902afa96c3e83e0e7f3fcd84e68872b
6
+ metadata.gz: e83a30785c99181d6f62a6632ad1d52c6c7970f8a53dd42e01041814fe5c9f09ee969aa0c2a39b180b20f565492c096e94744ce3149cf407c8c2ed09c99636ec
7
+ data.tar.gz: 37992e6abfc459bdb39b5a62292a43c3d49a79e17261136c955929836de307c9677653338fe9635c619dc0314ca69b498348cbacea044279d1dd924e5edac86f
@@ -6,9 +6,9 @@
6
6
  @import "../tokens/typography";
7
7
 
8
8
  $pb_button_sizes: (
9
- "sm": 0.75rem,
10
- "md": 0.875rem,
11
- "lg": 1.125rem,
9
+ "sm": $font_smaller,
10
+ "md": $font_small,
11
+ "lg": ($font_large - 2px),
12
12
  );
13
13
 
14
14
  [class*=pb_button_kit]{
@@ -9,7 +9,7 @@
9
9
 
10
10
  $pb_button_size: 40px;
11
11
  $pb_button_v_padding: 7px;
12
- $pb_button_h_padding: 34px;
12
+ $pb_button_h_padding: 28px;
13
13
  $pb_button_hover_darken: 4%;
14
14
  $pb_button_border_width: 0px;
15
15
 
@@ -27,13 +27,14 @@ $pb_button_border_width: 0px;
27
27
  text-rendering: optimizeLegibility;
28
28
  font-size: $font_small;
29
29
  font-weight: $bold;
30
+ letter-spacing: $lspace_loose;
30
31
  text-align: center;
31
32
  text-decoration: none;
32
33
  vertical-align: middle;
33
34
  text-transform: none;
34
35
  border-width: $pb_button_border_width;
35
36
  border-style: solid;
36
- border-radius: $border_rad_light;
37
+ border-radius: $border_rad_heavy;
37
38
  min-height: $pb_button_size;
38
39
  line-height: 1.5;
39
40
  padding: $pb_button_v_padding $pb_button_h_padding;
@@ -24,7 +24,7 @@ $pb_dark_caption_colors: (
24
24
  color: $text_lt_light;
25
25
  text-transform: uppercase;
26
26
  font-size: $font_size;
27
- letter-spacing: $lspace_looser;
27
+ letter-spacing: $lspace_loosest;
28
28
  }
29
29
 
30
30
  @mixin caption_color($color: $text_lt_light) {
@@ -53,7 +53,7 @@ const adjustAxisStyle = (axis) => {
53
53
  /* Change axis label styles */
54
54
  axis.labels.style.fontFamily = typography.font_family_base
55
55
  axis.labels.style.color = colors.charcoal
56
- axis.labels.style.fontWeight = typography.light
56
+ axis.labels.style.fontWeight = typography.regular
57
57
  axis.labels.style.fontSize = typography.font_small
58
58
  }
59
59
 
@@ -33,7 +33,7 @@ const highchartsDarkTheme: ThemeProps = {
33
33
  style: {
34
34
  color: colors.text_dk_default,
35
35
  fontFamily: typography.font_family_base,
36
- fontWeight: typography.regular,
36
+ fontWeight: typography.bold,
37
37
  fontSize: typography.heading_3,
38
38
  },
39
39
  },
@@ -34,7 +34,7 @@ const highchartsTheme: ThemeProps = {
34
34
  style: {
35
35
  color: colors.text_lt_default,
36
36
  fontFamily: typography.font_family_base,
37
- fontWeight: typography.regular,
37
+ fontWeight: typography.bold,
38
38
  fontSize: typography.heading_3,
39
39
  },
40
40
  },
@@ -4,7 +4,10 @@ import { DateYearStacked } from '../../'
4
4
  const DateYearStackedDefault = (props) => {
5
5
  return (
6
6
  <div>
7
- <DateYearStacked date={new Date()} />
7
+ <DateYearStacked
8
+ date={new Date()}
9
+ {...props}
10
+ />
8
11
  <DateYearStacked
9
12
  align="center"
10
13
  date={new Date()}
@@ -51,7 +51,16 @@ export const DraggableContext = () => {
51
51
  return useContext(DragContext);
52
52
  };
53
53
 
54
- export const DraggableProvider = ({ children, initialItems, onReorder }: DraggableProviderType) => {
54
+ export const DraggableProvider = ({
55
+ children,
56
+ initialItems,
57
+ onReorder,
58
+ onDragStart,
59
+ onDragEnter,
60
+ onDragEnd,
61
+ onDrop,
62
+ onDragOver
63
+ }: DraggableProviderType) => {
55
64
  const [state, dispatch] = useReducer(reducer, initialState);
56
65
 
57
66
  useEffect(() => {
@@ -65,6 +74,7 @@ export const DraggableProvider = ({ children, initialItems, onReorder }: Draggab
65
74
  const handleDragStart = (id: string, container: string) => {
66
75
  dispatch({ type: 'SET_DRAG_DATA', payload: { id: id, initialGroup: container } });
67
76
  dispatch({ type: 'SET_IS_DRAGGING', payload: id });
77
+ if (onDragStart) onDragStart(id, container);
68
78
  };
69
79
 
70
80
  const handleDragEnter = (id: string, container: string) => {
@@ -72,11 +82,13 @@ export const DraggableProvider = ({ children, initialItems, onReorder }: Draggab
72
82
  dispatch({ type: 'REORDER_ITEMS', payload: { dragId: state.dragData.id, targetId: id } });
73
83
  dispatch({ type: 'SET_DRAG_DATA', payload: { id: state.dragData.id, initialGroup: container } });
74
84
  }
85
+ if (onDragEnter) onDragEnter(id, container);
75
86
  };
76
87
 
77
88
  const handleDragEnd = () => {
78
89
  dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
79
90
  dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
91
+ if (onDragEnd) onDragEnd();
80
92
  };
81
93
 
82
94
  const changeCategory = (itemId: string, container: string) => {
@@ -87,11 +99,13 @@ export const DraggableProvider = ({ children, initialItems, onReorder }: Draggab
87
99
  dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
88
100
  dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
89
101
  changeCategory(state.dragData.id, container);
102
+ if (onDrop) onDrop(container);
90
103
  };
91
104
 
92
105
  const handleDragOver = (e: Event, container: string) => {
93
106
  e.preventDefault();
94
107
  dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: container });
108
+ if (onDragOver) onDragOver(e, container);
95
109
  };
96
110
 
97
111
  const contextValue = useMemo(() => ({
@@ -23,4 +23,9 @@ export interface ItemType {
23
23
  children: React.ReactNode;
24
24
  initialItems: ItemType[];
25
25
  onReorder: (items: ItemType[]) => void;
26
+ onDragStart?: (id: string, container: string) => void;
27
+ onDragEnter?: (id: string, container: string) => void;
28
+ onDragEnd?: () => void;
29
+ onDrop?: (container: string) => void;
30
+ onDragOver?: (e: Event, container: string) => void;
26
31
  }
@@ -1,23 +1,19 @@
1
1
  import React, { useState } from "react";
2
- import { SelectableList, Draggable, DraggableProvider } from "../../";
2
+ import { Flex, Image, Draggable, DraggableProvider } from "../../";
3
3
 
4
4
  // Initial items to be dragged
5
5
  const data = [
6
6
  {
7
- id: "1",
8
- text: "Task 1",
7
+ id: "21",
8
+ url: "https://unsplash.it/500/400/?image=633",
9
9
  },
10
10
  {
11
- id: "2",
12
- text: "Task 2",
11
+ id: "22",
12
+ url: "https://unsplash.it/500/400/?image=634",
13
13
  },
14
14
  {
15
- id: "3",
16
- text: "Task 3",
17
- },
18
- {
19
- id: "4",
20
- text: "Task 4",
15
+ id: "23",
16
+ url: "https://unsplash.it/500/400/?image=637",
21
17
  },
22
18
  ];
23
19
 
@@ -30,20 +26,19 @@ const DraggableDefault = (props) => {
30
26
  onReorder={(items) => setInitialState(items)}
31
27
  >
32
28
  <Draggable.Container {...props}>
33
- <SelectableList variant="checkbox">
34
- {initialState.map(({ id, text }) => (
29
+ <Flex>
30
+ {initialState.map(({ id, url }) => (
35
31
  <Draggable.Item dragId={id}
36
32
  key={id}
37
33
  >
38
- <SelectableList.Item
39
- label={text}
40
- name={id}
41
- value={id}
42
- {...props}
34
+ <Image alt={id}
35
+ margin="xs"
36
+ size="md"
37
+ url={url}
43
38
  />
44
39
  </Draggable.Item>
45
40
  ))}
46
- </SelectableList>
41
+ </Flex>
47
42
  </Draggable.Container>
48
43
  </DraggableProvider>
49
44
  </>
@@ -1,4 +1,6 @@
1
- To use the Draggable kit, you must use the DraggableProvider and pass in `initialItems`. The `onReorder` is a function that returns the data as it changes as items are reordered. Use this to manage state as shown.
1
+ The Draggable kit gives you a full subcomponent structure that allows it to be used with almost any kits.
2
2
 
3
- The `Draggable.Container` specifies the container within which items can be dropped.
4
- The `Draggable.Item` specifies the items that can be dragged and dropped. `dragId` is a REQUIRED prop for Draggable.Item.
3
+ `DraggableProvider` = This provider manages all settings that allows drag and drop to function and must be used as the outermost wrapper. It has 2 REQUIRED props: `initialItems` (initial data) and `onReorder` (function that returns mutated data as items are reordered via drag and drop). Devs must manage state as shown.
4
+
5
+ `Draggable.Container` = This specifies the container within which items can be dropped.
6
+ `Draggable.Item` = This specifies the items that can be dragged and dropped. `dragId` is a REQUIRED prop for Draggable.Item.
@@ -1,5 +1,9 @@
1
- For a simplified version of the Draggable API for the Card kit, You can use the the Card kit as the Draggable Item by using the `draggableItem` prop. The dragHandle is added by default but this can be opted out of by setting `dragHandle` to false on the Card kit.
1
+ For a simplified version of the Draggable API for the Card kit, you can do the following:
2
+
3
+ Use `DraggableProvider` and manage state as shown.
4
+
5
+ `Draggable.Container` creates the container within which the cards can be dragged and dropped.
6
+
7
+ The Card kit is optimized to work with the draggable kit. To enable drag, use the `draggableItem` and `dragId` props on the Card kit as shown. An additional optional boolean prop (set to true by default) of `dragHandle` is also available to show the drag handle icon.
2
8
 
3
- In addition to the above `dragId` is a REQUIRED prop to be passedd to the Card kit when implementing dragging.
4
9
 
5
- The dev must manage state as shown.
@@ -1,7 +1,5 @@
1
- For a simplified version of the Draggable API for the List kit, use the DraggableProvider to wrap the List kit and use the `enableDrag` prop.
1
+ For a simplified version of the Draggable API for the List kit, you can do the following:
2
2
 
3
- In addition to the above `dragId` is a REQUIRED prop to be passed to the List kit when implementing dragging.
3
+ Use `DraggableProvider` and manage state as shown.
4
4
 
5
- The dev must manage state as shown.
6
-
7
- The dragHandle is added by default but this can be opted out of by setting `dragHandle` to false on the List kit.
5
+ The List kit is optimized to work with the draggable kit. To enable drag, use the `enableDrag` prop on List kit AND `dragId` prop on ListItem. An additional optional boolean prop (set to true by default) of `dragHandle` is also available on List kit to show the drag handle icon.
@@ -1,7 +1,5 @@
1
- For a simplified version of the Draggable API for the SelectableList kit, use the DraggableProvider to wrap the SelectableList kit and use the `enableDrag` prop.
1
+ For a simplified version of the Draggable API for the SelectableList kit, you can do the following:
2
2
 
3
- In addition to the above `dragId` is a REQUIRED prop to be passed to the SelectableList kit when implementing dragging.
3
+ Use `DraggableProvider` and manage state as shown.
4
4
 
5
- The dev must manage state as shown.
6
-
7
- The dragHandle is added by default but this can be opted out of by setting `dragHandle` to false on the SelectableList kit.
5
+ The SelectableList kit is optimized to work with the draggable kit. To enable drag, use the `enableDrag` prop on SelectableList kit AND `dragId` prop on SelectableList.Item. An additional optional boolean prop (set to true by default) of `dragHandle` is also available on SelectableList kit to show the drag handle icon.
@@ -8,7 +8,9 @@
8
8
  <%= pb_rails("caption", props: {text: object.label, margin_bottom:"xs"}) %>
9
9
  <% end %>
10
10
  <div class="dropdown_wrapper<%= error_class %>" style="position: relative">
11
- <input type="hidden" name="<%= object.name %>" id="dropdown-selected-option" value=""/>
11
+ <input type="hidden" name="<%= object.name %>" id="dropdown-selected-option" value="" />
12
+ <input id="dropdown-form-validation" name="<%= object.name %>_form_validation" value="" style="display: none" <%= object.required ? "required" : ""%> />
13
+
12
14
  <% if content.present? %>
13
15
  <%= content.presence %>
14
16
  <%= pb_rails("body", props: { status: "negative", text: object.error }) %>
@@ -8,6 +8,8 @@ module Playbook
8
8
  prop :label, type: Playbook::Props::String
9
9
  prop :name, type: Playbook::Props::String
10
10
  prop :error, type: Playbook::Props::String
11
+ prop :required, type: Playbook::Props::Boolean,
12
+ default: false
11
13
 
12
14
  def data
13
15
  Hash(prop(:data)).merge(pb_dropdown: true)
@@ -8,16 +8,22 @@ const DOWN_ARROW_SELECTOR = "#dropdown_open_icon";
8
8
  const UP_ARROW_SELECTOR = "#dropdown_close_icon";
9
9
  const OPTION_SELECTOR = "[data-dropdown-option-label]";
10
10
  const CUSTOM_DISPLAY_SELECTOR = "[data-dropdown-custom-trigger]";
11
+ const INPUT_FORM_VALIDATION = "#dropdown-form-validation";
11
12
 
12
13
  export default class PbDropdown extends PbEnhancedElement {
13
14
  static get selector() {
14
15
  return DROPDOWN_SELECTOR;
15
16
  }
16
17
 
18
+ get target() {
19
+ return this.element.parentNode.querySelector(CONTAINER_SELECTOR);
20
+ }
21
+
17
22
  connect() {
18
23
  this.keyboardHandler = new PbDropdownKeyboard(this);
19
24
  this.bindEventListeners();
20
25
  this.updateArrowDisplay(false);
26
+ this.handleFormValidation();
21
27
  }
22
28
 
23
29
  bindEventListeners() {
@@ -38,9 +44,13 @@ export default class PbDropdown extends PbEnhancedElement {
38
44
  handleOptionClick(event) {
39
45
  const option = event.target.closest(OPTION_SELECTOR);
40
46
  const hiddenInput = this.element.querySelector("#dropdown-selected-option");
47
+ const inputFormValidation = this.element.querySelector(INPUT_FORM_VALIDATION);
48
+
41
49
  if (option) {
42
50
  const value = option.dataset.dropdownOptionLabel;
43
51
  hiddenInput.value = JSON.parse(value).id;
52
+ inputFormValidation.value = JSON.parse(value).id;
53
+ this.clearFormValidation(inputFormValidation);
44
54
  this.onOptionSelected(value, option);
45
55
  }
46
56
  }
@@ -103,10 +113,6 @@ export default class PbDropdown extends PbEnhancedElement {
103
113
  selectedOption.classList.add("pb_dropdown_option_selected");
104
114
  }
105
115
 
106
- get target() {
107
- return this.element.parentNode.querySelector(CONTAINER_SELECTOR);
108
- }
109
-
110
116
  showElement(elem) {
111
117
  elem.classList.remove("close");
112
118
  elem.classList.add("open");
@@ -150,4 +156,27 @@ export default class PbDropdown extends PbEnhancedElement {
150
156
  upArrow.style.display = isOpen ? "inline-block" : "none";
151
157
  }
152
158
  }
159
+
160
+ handleFormValidation() {
161
+ const inputFormValidation = this.element.querySelector(INPUT_FORM_VALIDATION);
162
+
163
+ inputFormValidation.addEventListener("invalid", function (event) {
164
+ if (inputFormValidation.hasAttribute("required") && inputFormValidation.value === "") {
165
+ event.preventDefault();
166
+ inputFormValidation.closest(".dropdown_wrapper").classList.add("error");
167
+ }
168
+ }, true);
169
+ }
170
+
171
+ clearFormValidation(input) {
172
+ if (input.checkValidity()) {
173
+ const dropdownWrapperElement = input.closest(".dropdown_wrapper");
174
+ dropdownWrapperElement.classList.remove("error");
175
+
176
+ const errorLabelElement = dropdownWrapperElement.querySelector(".pb_body_kit_negative");
177
+ if (errorLabelElement) {
178
+ errorLabelElement.remove();
179
+ }
180
+ }
181
+ }
153
182
  }
@@ -13,6 +13,14 @@
13
13
  ]
14
14
  %>
15
15
 
16
+ <%
17
+ example_dropdown_options = [
18
+ { label: 'United States', value: 'United States', id: 'us' },
19
+ { label: 'Canada', value: 'Canada', id: 'ca' },
20
+ { label: 'Pakistan', value: 'Pakistan', id: 'pk' },
21
+ ]
22
+ %>
23
+
16
24
  <%= pb_form_with(scope: :example, method: :get, url: "", validate: true) do |form| %>
17
25
  <%= form.text_field :example_text_field, props: { label: true, required: true } %>
18
26
  <%= form.phone_number_field :example_phone_number_field, props: { label: "Example phone field" } %>
@@ -22,6 +30,7 @@
22
30
  <%= form.password_field :example_password_field, props: { label: true, required: true } %>
23
31
  <%= form.url_field :example_url_field, props: { label: true, required: true } %>
24
32
  <%= form.text_area :example_text_area, props: { label: true, required: true } %>
33
+ <%= form.dropdown_field :example_dropdown, props: { label: true, options: example_dropdown_options, required: true } %>
25
34
  <%= form.select :example_select, [ ["Yes", 1], ["No", 2] ], props: { label: true, blank_selection: "Select One...", required: true } %>
26
35
  <%= form.collection_select :example_collection_select, example_collection, :value, :name, props: { label: true, blank_selection: "Select One...", required: true } %>
27
36
  <%= form.check_box :example_checkbox, props: { text: "Example Checkbox", label: true, required: true } %>
@@ -55,7 +55,7 @@ $form_pill_colors: (
55
55
  height: fit-content;
56
56
  height: -moz-fit-content;
57
57
  .pb_form_pill_text, .pb_form_pill_close, .pb_form_pill_tag {
58
- font-size: 16px;
58
+ font-size: $font_base;
59
59
  font-weight: $regular;
60
60
  }
61
61
  .pb_form_pill_text, .pb_form_pill_tag {
@@ -3,7 +3,6 @@ import classnames from 'classnames'
3
3
  import { buildAriaProps, buildDataProps, buildHtmlProps } from '../utilities/props'
4
4
  import { GlobalProps, globalProps } from '../utilities/globalProps'
5
5
  import { isValidEmoji } from '../utilities/validEmojiChecker'
6
- import aliasesJson from './icon_aliases.json'
7
6
 
8
7
  export type IconSizes = "lg"
9
8
  | "xs"
@@ -41,19 +40,6 @@ type IconProps = {
41
40
  spin?: boolean,
42
41
  } & GlobalProps
43
42
 
44
- type AliasType = string | string[];
45
-
46
- interface Aliases {
47
- [key: string]: AliasType;
48
- }
49
-
50
- interface AliasesJson {
51
- aliases: Aliases;
52
- }
53
-
54
- const aliases: AliasesJson = aliasesJson;
55
-
56
-
57
43
  const flipMap = {
58
44
  horizontal: 'fa-flip-horizontal',
59
45
  vertical: 'fa-flip-vertical',
@@ -66,22 +52,6 @@ declare global {
66
52
  var PB_ICONS: {[key: string]: React.FunctionComponent<any>}
67
53
  }
68
54
 
69
- // Resolve alias function
70
- const resolveAlias = (icon: string): string => {
71
- const alias = aliases.aliases[icon];
72
-
73
- if (alias) {
74
- if (Array.isArray(alias)) {
75
- return alias[0];
76
- } else {
77
- return alias;
78
- }
79
- }
80
-
81
- return icon;
82
- };
83
-
84
-
85
55
  const Icon = (props: IconProps) => {
86
56
  const {
87
57
  aria = {},
@@ -104,8 +74,7 @@ const Icon = (props: IconProps) => {
104
74
  spin = false,
105
75
  } = props
106
76
 
107
- const resolvedIcon = resolveAlias(icon as string)
108
- let iconElement: ReactSVGElement | null = typeof(resolvedIcon) === "object" ? resolvedIcon : null
77
+ let iconElement: ReactSVGElement | null = typeof(icon) === "object" ? icon : null
109
78
 
110
79
  const faClasses = {
111
80
  'fa-border': border,
@@ -121,12 +90,12 @@ const Icon = (props: IconProps) => {
121
90
 
122
91
  if (!customIcon && !iconElement) {
123
92
  const PowerIcon: React.FunctionComponent<any> | undefined =
124
- window.PB_ICONS ? window.PB_ICONS[resolvedIcon as string] : null
93
+ window.PB_ICONS ? window.PB_ICONS[icon as string] : null
125
94
 
126
95
  if (PowerIcon) {
127
96
  iconElement = <PowerIcon /> as ReactSVGElement
128
97
  } else {
129
- faClasses[`fa-${resolvedIcon}`] = resolvedIcon as string
98
+ faClasses[`fa-${icon}`] = icon as string
130
99
  }
131
100
  }
132
101
 
@@ -146,7 +115,7 @@ const Icon = (props: IconProps) => {
146
115
  className
147
116
  )
148
117
 
149
- aria.label ? null : aria.label = `${resolvedIcon} icon`
118
+ aria.label ? null : aria.label = `${icon} icon`
150
119
  const ariaProps: {[key: string]: any} = buildAriaProps(aria)
151
120
  const dataProps: {[key: string]: any} = buildDataProps(data)
152
121
  const htmlProps = buildHtmlProps(htmlOptions)
@@ -168,7 +137,7 @@ const Icon = (props: IconProps) => {
168
137
  }
169
138
  </>
170
139
  )
171
- else if (isValidEmoji(resolvedIcon as string))
140
+ else if (isValidEmoji(icon as string))
172
141
  return (
173
142
  <>
174
143
  <span
@@ -177,7 +146,7 @@ const Icon = (props: IconProps) => {
177
146
  className={classesEmoji}
178
147
  id={id}
179
148
  >
180
- {resolvedIcon}
149
+ {icon}
181
150
  </span>
182
151
  </>
183
152
  )
@@ -39,8 +39,6 @@ module Playbook
39
39
  prop :spin, type: Playbook::Props::Boolean,
40
40
  default: false
41
41
 
42
- ALIASES = JSON.parse(File.read(Playbook::Engine.root.join("app/pb_kits/playbook/pb_icon/icon_aliases.json")))["aliases"].freeze
43
-
44
42
  def valid_emoji?
45
43
  emoji_regex = /\p{Emoji}/
46
44
  emoji_regex.match?(icon)
@@ -82,6 +80,14 @@ module Playbook
82
80
  )
83
81
  end
84
82
 
83
+ def icon_alias_map
84
+ return unless Rails.application.config.respond_to?(:icon_alias_path)
85
+
86
+ base_path = Rails.application.config.icon_alias_path
87
+ json = File.read(Rails.root.join(base_path))
88
+ JSON.parse(json)["aliases"].freeze
89
+ end
90
+
85
91
  def asset_path
86
92
  return unless Rails.application.config.respond_to?(:icon_path)
87
93
 
@@ -111,7 +117,7 @@ module Playbook
111
117
  private
112
118
 
113
119
  def resolve_alias(icon)
114
- aliases = ALIASES[icon]
120
+ aliases = icon_alias_map[icon]
115
121
  return icon unless aliases
116
122
 
117
123
  if aliases.is_a?(Array)
@@ -86,33 +86,18 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
86
86
  const toolbarElement = element.parentElement.querySelector('trix-toolbar') as HTMLElement,
87
87
  blockCodeButton = toolbarElement.querySelector('[data-trix-attribute=code]') as HTMLElement
88
88
 
89
+ // replace default trix "block code" button with "inline code" button
89
90
  let inlineCodeButton = toolbarElement.querySelector('[data-trix-attribute=inlineCode]') as HTMLElement
90
- if (!inlineCodeButton) inlineCodeButton = blockCodeButton.cloneNode(true) as HTMLElement
91
-
92
- // set button attributes
93
- inlineCodeButton.dataset.trixAttribute = 'inlineCode'
94
- blockCodeButton.insertAdjacentElement('afterend', inlineCodeButton)
91
+ if (!inlineCodeButton) {
92
+ inlineCodeButton = blockCodeButton.cloneNode(true) as HTMLElement
93
+ blockCodeButton.hidden = true
94
+ // set button attributes
95
+ inlineCodeButton.dataset.trixAttribute = 'inlineCode'
96
+ blockCodeButton.insertAdjacentElement('afterend', inlineCodeButton)
97
+ }
95
98
 
96
99
  if (toolbarBottom) editor.element.after(toolbarElement)
97
100
 
98
- const getCodeFormattingType = (): string => {
99
- if (editor.attributeIsActive('code')) return 'block'
100
- if (editor.attributeIsActive('inlineCode')) return 'inline'
101
-
102
- const range = editor.getSelectedRange()
103
- if (range[0] == range[1]) return 'block'
104
-
105
- const text = editor.getSelectedDocument().toString().trim()
106
- return /\n/.test(text) ? 'block' : 'inline'
107
- }
108
-
109
- // DOM event listeners
110
- element.addEventListener('trix-selection-change', () => {
111
- const type = getCodeFormattingType()
112
- blockCodeButton.hidden = type == 'inline'
113
- inlineCodeButton.hidden = type == 'block'
114
- })
115
-
116
101
  focus
117
102
  ? (document.addEventListener('trix-focus', useFocus),
118
103
  document.addEventListener('trix-blur', useFocus),
@@ -5,10 +5,11 @@
5
5
  @mixin pb_title(
6
6
  $fontSize: $heading_1,
7
7
  $fontWeight: $lighter,
8
- $lineHeight: $lh_tighter
8
+ $lineHeight: $lh_tighter,
9
+ $letterSpacing: $lspace_tight
9
10
  ){
10
11
  font-size: $fontSize;
11
- letter-spacing: $lspace_tight;
12
+ letter-spacing: $letterSpacing;
12
13
  font-weight: $fontWeight;
13
14
  color: $text_lt_default;
14
15
  margin: 0;
@@ -29,8 +30,7 @@
29
30
  }
30
31
 
31
32
  @mixin pb_title_4 {
32
- @include pb_title($heading_4, $bolder);
33
- letter-spacing: -0.03em;
33
+ @include pb_title($heading_4, $bolder, $letterSpacing: $lspace_normal);
34
34
  }
35
35
 
36
36
  @mixin pb_title_dark {