playbook_ui 13.31.0 → 13.32.0.pre.alpha.play1416movealiaslogic3239
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_button/_button.scss +3 -3
- data/app/pb_kits/playbook/pb_button/_button_mixins.scss +3 -2
- data/app/pb_kits/playbook/pb_caption/_caption_mixin.scss +1 -1
- data/app/pb_kits/playbook/pb_dashboard/commonSettings.js +1 -1
- data/app/pb_kits/playbook/pb_dashboard/pbChartsDarkTheme.ts +1 -1
- data/app/pb_kits/playbook/pb_dashboard/pbChartsLightTheme.ts +1 -1
- data/app/pb_kits/playbook/pb_date_year_stacked/docs/_date_year_stacked_default.jsx +4 -1
- data/app/pb_kits/playbook/pb_draggable/context/index.tsx +15 -1
- data/app/pb_kits/playbook/pb_draggable/context/types.ts +5 -0
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_default.jsx +14 -19
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_default.md +5 -3
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_cards.md +7 -3
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list.md +3 -5
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list.md +3 -5
- data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +3 -1
- data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +2 -0
- data/app/pb_kits/playbook/pb_dropdown/index.js +33 -4
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +9 -0
- data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +1 -1
- data/app/pb_kits/playbook/pb_icon/_icon.tsx +6 -37
- data/app/pb_kits/playbook/pb_icon/icon.rb +9 -3
- data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +8 -23
- data/app/pb_kits/playbook/tokens/_titles.scss +4 -4
- data/app/pb_kits/playbook/tokens/_typography.scss +10 -10
- data/dist/menu.yml +566 -472
- data/dist/playbook-rails.js +7 -7
- data/dist/reset.css +1 -1
- data/lib/playbook/version.rb +2 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 38d2ad5fae80d023caae7a74a96bf549e74693d82376000d2d056ecdd94e5948
|
4
|
+
data.tar.gz: c3de45c50a99868c1a157179eb8912acfd173337bd94af3eb166c42d01c051ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e83a30785c99181d6f62a6632ad1d52c6c7970f8a53dd42e01041814fe5c9f09ee969aa0c2a39b180b20f565492c096e94744ce3149cf407c8c2ed09c99636ec
|
7
|
+
data.tar.gz: 37992e6abfc459bdb39b5a62292a43c3d49a79e17261136c955929836de307c9677653338fe9635c619dc0314ca69b498348cbacea044279d1dd924e5edac86f
|
@@ -9,7 +9,7 @@
|
|
9
9
|
|
10
10
|
$pb_button_size: 40px;
|
11
11
|
$pb_button_v_padding: 7px;
|
12
|
-
$pb_button_h_padding:
|
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: $
|
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;
|
@@ -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.
|
56
|
+
axis.labels.style.fontWeight = typography.regular
|
57
57
|
axis.labels.style.fontSize = typography.font_small
|
58
58
|
}
|
59
59
|
|
@@ -4,7 +4,10 @@ import { DateYearStacked } from '../../'
|
|
4
4
|
const DateYearStackedDefault = (props) => {
|
5
5
|
return (
|
6
6
|
<div>
|
7
|
-
<DateYearStacked
|
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 = ({
|
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 {
|
2
|
+
import { Flex, Image, Draggable, DraggableProvider } from "../../";
|
3
3
|
|
4
4
|
// Initial items to be dragged
|
5
5
|
const data = [
|
6
6
|
{
|
7
|
-
id: "
|
8
|
-
|
7
|
+
id: "21",
|
8
|
+
url: "https://unsplash.it/500/400/?image=633",
|
9
9
|
},
|
10
10
|
{
|
11
|
-
id: "
|
12
|
-
|
11
|
+
id: "22",
|
12
|
+
url: "https://unsplash.it/500/400/?image=634",
|
13
13
|
},
|
14
14
|
{
|
15
|
-
id: "
|
16
|
-
|
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
|
-
|
34
|
-
{initialState.map(({ id,
|
29
|
+
<Flex>
|
30
|
+
{initialState.map(({ id, url }) => (
|
35
31
|
<Draggable.Item dragId={id}
|
36
32
|
key={id}
|
37
33
|
>
|
38
|
-
<
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
{...props}
|
34
|
+
<Image alt={id}
|
35
|
+
margin="xs"
|
36
|
+
size="md"
|
37
|
+
url={url}
|
43
38
|
/>
|
44
39
|
</Draggable.Item>
|
45
40
|
))}
|
46
|
-
|
41
|
+
</Flex>
|
47
42
|
</Draggable.Container>
|
48
43
|
</DraggableProvider>
|
49
44
|
</>
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
The Draggable kit gives you a full subcomponent structure that allows it to be used with almost any kits.
|
2
2
|
|
3
|
-
|
4
|
-
|
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,
|
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,
|
1
|
+
For a simplified version of the Draggable API for the List kit, you can do the following:
|
2
2
|
|
3
|
-
|
3
|
+
Use `DraggableProvider` and manage state as shown.
|
4
4
|
|
5
|
-
The
|
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,
|
1
|
+
For a simplified version of the Draggable API for the SelectableList kit, you can do the following:
|
2
2
|
|
3
|
-
|
3
|
+
Use `DraggableProvider` and manage state as shown.
|
4
4
|
|
5
|
-
The
|
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 } %>
|
@@ -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
|
-
|
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[
|
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-${
|
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 = `${
|
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(
|
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
|
-
{
|
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 =
|
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)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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: $
|
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 {
|