playbook_ui 12.20.0.pre.alpha.title2667 → 12.21.0.pre.alpha.PLAY807RTEcustomtoolbar680

Sign up to get free protection for your applications and to get access to all the features.
Files changed (24) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_docs/kit_example.html.erb +40 -11
  3. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +57 -15
  4. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/MoreExtensionsDropdown.tsx +69 -0
  5. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/Toolbar.tsx +10 -2
  6. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/ToolbarDropdown.tsx +10 -0
  7. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +4 -2
  8. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_more_extensions.jsx +55 -0
  9. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_more_extensions.md +12 -0
  10. data/app/pb_kits/playbook/pb_rich_text_editor/docs/example.yml +1 -0
  11. data/app/pb_kits/playbook/pb_rich_text_editor/docs/index.js +2 -1
  12. data/app/pb_kits/playbook/pb_title/_title.scss +0 -1
  13. data/app/pb_kits/playbook/pb_title/docs/_title_light_weight.md +2 -2
  14. data/app/pb_kits/playbook/pb_user_badge/{_user_badge.jsx → _user_badge.tsx} +9 -10
  15. data/app/pb_kits/playbook/pb_user_badge/badges/million-dollar.tsx +358 -0
  16. data/app/pb_kits/playbook/pb_user_badge/badges/veteran.tsx +27 -0
  17. data/app/pb_kits/playbook/pb_user_badge/user_badge.test.js +67 -0
  18. data/app/pb_kits/playbook/pb_walkthrough/_walkthrough.tsx +193 -0
  19. data/dist/menu.yml +1 -1
  20. data/lib/playbook/version.rb +2 -2
  21. metadata +10 -6
  22. data/app/pb_kits/playbook/pb_user_badge/badges/million-dollar.jsx +0 -363
  23. data/app/pb_kits/playbook/pb_user_badge/badges/veteran.jsx +0 -28
  24. data/app/pb_kits/playbook/pb_walkthrough/_walkthrough.jsx +0 -197
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d39aced18b9b6f732ee243b0c03200f52c99e9041a70977b126396b767b91be
4
- data.tar.gz: d0eaea4b72d3e116515cdfbd90f7aec99c6ece119400865c6d9d5230efa548ab
3
+ metadata.gz: 9561ff1283a2c2a61fd7562e899a6c2391f1cbf95010e4365229d432904b878a
4
+ data.tar.gz: 8e70472802e711a1d8d304e973f1bca85a9b496c1d7af38af367e931dcf320f6
5
5
  SHA512:
6
- metadata.gz: d37c49956c03f81876aa62224de4ac4f57438b494628242fdf61db405effef4fe0d2c244086c9b4c75e056b2f72a86181212bf42df09cfd46deefc281870ba21
7
- data.tar.gz: 65d1fdc3ce3c4fb3535dad0b91c04215688af1650124315c5b9f1f599d32fd4eb94c01442118e117a99d20590a3e31421a45cb5c4c7ae8ce2edd3a66deb05069
6
+ metadata.gz: 3bead3870a688c20c322c9bf534ddef966ed46e361eeded0d79b351e99640693bd9bb3f6ab5a2b2e62129145c189b5d2becc7c6fd34647f6b2485c1cc42ed077
7
+ data.tar.gz: f572b39bd3f17ea6619df329cd1e5986f8374b7b713e74ffab52094b45180c9f8a5a168651e909ad3d4b1af7d5097503d4dc156ab0f49c334e67b2b1c9c1c94a
@@ -15,31 +15,60 @@
15
15
  <div id="code-wrapper">
16
16
  <div class="pb--codeControls">
17
17
  <ul>
18
- <% if type == "rails" %>
18
+ <% hide_button = type == "rails" ? 'flex' : 'none' %>
19
19
  <li>
20
- <a href="#" id="copy-<%= example_key %>-trigger" onclick="copyOnClick(`<%= example_html %>`, `copy-<%= example_key %>`)">
21
- Copy HTML
22
- </a>
20
+ <%= pb_rails("button", props: { id:"copy-html-#{example_key}", icon: "copy", text: "Copy HTML", variant: "link", size: "sm", display: hide_button }) %>
23
21
  </li>
24
- <% end %>
25
22
  <li>
26
- <a href="#" id="toggle-open" data-toggle="code_example">Code Example</a>
23
+ <%= pb_rails("button", props: { icon: "code", id:"toggle-open-opened", text: "Close Code", variant: "link", size: "sm", display: "none" }) %>
24
+ <%= pb_rails("button", props: { icon: "code", id:"toggle-open-closed", text: "Show Code", variant: "link", size: "sm" }) %>
27
25
  </li>
28
26
  </ul>
29
27
  </div>
30
28
  <div class="pb--codeCopy" data-action="toggle" data-togglable="code_example" style="display: none" >
31
29
  <%= pb_rails("section_separator", props: { dark: dark })%>
32
- <a href="#" id="toggle-close" data-toggle="false" class="pb--close-toggle">Close</a>
30
+ <a href="#" style="padding: 16px 0px 22px 0px;" id="copy-code-<%= example_key %>" class="pb--copy-code" onclick="copyOnClick(`<%= source %>`, `copy-code-<%= example_key %>`)">
31
+ <%= pb_rails("button", props: { id: "copy-button-#{example_key}", text: "Copy Code", size: "sm", icon: "copy" }) %>
32
+ </a>
33
33
  <pre class="highlight"><%= raw rouge(source, highlighter) %></pre>
34
34
  </div>
35
+ <%= pb_rails("popover", props: {
36
+ trigger_element_id: "copy-button-#{example_key}",
37
+ tooltip_id: "tooltip-#{example_key}",
38
+ offset: true,
39
+ position: "bottom"
40
+ }) do %>
41
+ Code Copied
42
+ <% end %>
35
43
  </div>
36
44
  <% end %>
37
45
  <% end %>
38
46
 
39
47
  <script>
40
- function copyOnClick(content, elementID) {
41
- copyContent(content)
48
+ var htmlButton = document.getElementById('<%= "copy-html-#{example_key}" %>')
49
+ if (htmlButton) {
50
+ htmlButton.addEventListener('click', function() {
51
+ var tempElement = document.createElement('div')
52
+ tempElement.innerHTML = `<%= example_html %>`
53
+ var decodedString = tempElement.textContent || tempElement.innerText;
54
+ copyContent(decodedString)
55
+ })
56
+ }
57
+
58
+ var button = document.getElementById('<%= "copy-button-#{example_key}" %>')
59
+ if (button) {
60
+ button.addEventListener('click', function() {
61
+ var tempElement = document.createElement('div')
62
+ tempElement.innerHTML = `<%= source %>`
63
+ var decodedString = tempElement.textContent || tempElement.innerText;
64
+ copyContent(decodedString)
65
+ var fadeAwayDiv = document.getElementById("<%= "tooltip-#{example_key}" %>")
66
+ setTimeout(function() {
67
+ fadeAwayDiv.classList.remove('show')
68
+ }, 3000)
69
+ setTimeout(function() {
70
+ fadeAwayDiv.classList.add('hide')
71
+ }, 3001)
72
+ })
42
73
  }
43
-
44
74
  </script>
45
-
@@ -3,57 +3,99 @@
3
3
  @import "../tokens/border_radius";
4
4
  @import "../tokens/shadows";
5
5
  @import "../tokens/spacing";
6
+ @import "../tokens/typography";
7
+ @import "../tokens/line_height";
6
8
 
7
9
  .pb_multi_level_select {
10
+ font-family: $font-family-base;
11
+
12
+ .search {
13
+ font-family: $font-family-base;
14
+ }
15
+
8
16
  .dropdown {
9
17
  width: 100%;
10
18
  .search {
11
19
  border-bottom: none;
12
20
  }
13
21
 
22
+ .toggle {
23
+ padding: 0px $space_xs + 1;
24
+ }
25
+ .node.tree {
26
+ display: flex;
27
+ align-items: center;
28
+ }
29
+
30
+ .node-label {
31
+ line-height: $lh_tight;
32
+ color: $text_lt_default;
33
+ font-size: $text_default;
34
+ font-weight: $regular;
35
+ font-family: $font-family-base;
36
+ }
37
+
38
+ .checkbox-item {
39
+ height: $space_sm;
40
+ width: $space_sm;
41
+ }
42
+
14
43
  .toggle.expanded:after {
15
44
  border-style: solid;
16
45
  border-width: 0.1em 0.1em 0 0;
17
46
  content: "";
18
47
  display: inline-block;
19
- height: 0.6em;
20
- left: 0.1em;
48
+ height: 0.8em;
21
49
  position: relative;
22
50
  vertical-align: top;
23
- width: 0.6em;
24
- top: 10px;
51
+ width: 0.8em;
52
+ top: 7px;
25
53
  transform: rotate(135deg);
26
54
  font-size: 0.5em;
27
55
  }
56
+ .toggle.expanded:hover {
57
+ background-color: rgba(0, 86, 207, 0.1);
58
+ border-radius: $border_radius_rounded;
59
+ &::after {
60
+ color: $primary;
61
+ }
62
+ }
28
63
  .toggle.collapsed:after {
29
64
  border-style: solid;
30
65
  border-width: 0.1em 0.1em 0 0;
31
66
  content: "";
32
67
  display: inline-block;
33
- height: 0.6em;
34
- left: 0.1em;
68
+ height: 0.8em;
69
+ right: 0.1em;
35
70
  position: relative;
36
71
  vertical-align: top;
37
- width: 0.6em;
38
- top: 10px;
72
+ width: 0.8em;
73
+ top: 7px;
39
74
  font-size: 0.5em;
40
-
41
75
  transform: rotate(45deg);
42
- top: 12px;
76
+ top: 9px;
77
+ }
78
+
79
+ .toggle.collapsed:hover {
80
+ background-color: rgba(0, 86, 207, 0.1);
81
+ border-radius: $border_radius_rounded;
82
+ &::after {
83
+ color: $primary;
84
+ }
43
85
  }
44
86
 
45
87
  .tag {
46
- height: 37px;
88
+ height: fit-content;
47
89
  display: inline-flex;
48
90
  justify-content: center;
49
91
  align-items: center;
50
- padding: 0 $space_xxs 0 $space_xs;
51
- border-radius: 18px;
92
+ padding: $space_xxs $space_xxs $space_xxs $space_xs;
93
+ border-radius: $border_radius_xl + 2;
52
94
  background-color: rgba($primary, 0.1);
53
95
  color: $primary;
54
96
  border: none;
55
- font-size: 16px;
56
- font-weight: 700;
97
+ font-size: $font_smaller;
98
+ font-weight: $bolder;
57
99
 
58
100
  .tag-remove {
59
101
  color: $primary;
@@ -0,0 +1,69 @@
1
+ import React, { useState } from 'react'
2
+
3
+ import Flex from '../../pb_flex/_flex'
4
+ import PbReactPopover from '../../pb_popover/_popover'
5
+ import Icon from '../../pb_icon/_icon'
6
+ import Nav from '../../pb_nav/_nav'
7
+ import NavItem from '../../pb_nav/_item'
8
+
9
+ const MoreExtensionsDropdown = ({extensions}: any) => {
10
+ const [showPopover, setShowPopover] = useState(false)
11
+
12
+ const handleTogglePopover = () => {
13
+ setShowPopover(true)
14
+ }
15
+
16
+ const handlePopoverClose = (shouldClosePopover: boolean) => {
17
+ setShowPopover(!shouldClosePopover)
18
+ }
19
+
20
+
21
+ const popoverReference = (
22
+ <button
23
+ className="toolbar_button"
24
+ onClick={handleTogglePopover}
25
+ >
26
+ <Flex
27
+ align="center"
28
+ className="toolbar_button_icon"
29
+ justify="center"
30
+ >
31
+ <Icon icon="ellipsis" size="lg" />
32
+ </Flex>
33
+ </button>
34
+
35
+ );
36
+
37
+ return (
38
+ <PbReactPopover
39
+ closeOnClick='outside'
40
+ padding='none'
41
+ placement="bottom"
42
+ reference={popoverReference}
43
+ shouldClosePopover={handlePopoverClose}
44
+ show={showPopover}
45
+ >
46
+ <Nav
47
+ paddingTop={extensions.length > 1 ? "xs" : "none"}
48
+ paddingBottom={extensions.length > 1 ? "xs" : "none"}
49
+ variant="subtle"
50
+ >
51
+ {extensions && extensions.map(({ icon, text, onclick, isActive}:any, index:number) => (
52
+ <NavItem
53
+ cursor="pointer"
54
+ className={`pb_tiptap_toolbar_dropdown_list_item ${isActive ? "is-active" : ""}`}
55
+ iconLeft={icon}
56
+ key={`${text}_${index}`}
57
+ margin='none'
58
+ onClick={()=> {onclick(); setShowPopover(false)}}
59
+ text={text}
60
+ paddingTop='xxs'
61
+ paddingBottom='xxs'
62
+ />
63
+ ))}
64
+ </Nav>
65
+ </PbReactPopover>
66
+ )
67
+ }
68
+
69
+ export default MoreExtensionsDropdown
@@ -9,8 +9,9 @@ import ToolbarDropdown from "./ToolbarDropdown";
9
9
  import ToolbarNodes from "./ToolbarNodes";
10
10
  import { ToolbarTypes } from "./EditorTypes";
11
11
  import ToolbarHistoryItems from "./ToolbarHistory";
12
+ import MoreExtensionsDropdown from "./MoreExtensionsDropdown";
12
13
 
13
- const EditorToolbar = ({ editor }:any) => {
14
+ const EditorToolbar = ({ editor, extensions }:any) => {
14
15
  const toolbaritems = [
15
16
  {
16
17
  icon: "bold",
@@ -51,10 +52,17 @@ const EditorToolbar = ({ editor }:any) => {
51
52
  )}
52
53
  <SectionSeparator orientation="vertical" />
53
54
  <ToolbarNodes editor={editor} />
55
+ {
56
+ extensions && (
57
+ <>
58
+ <MoreExtensionsDropdown extensions={extensions}/>
59
+ </>
60
+ )
61
+ }
62
+
54
63
  </FlexItem>
55
64
  <ToolbarHistoryItems editor={editor} />
56
65
  </Flex>
57
- {/* <SectionSeparator /> */}
58
66
  </Background>
59
67
  );
60
68
  };
@@ -98,7 +98,17 @@ const popoverReference = (
98
98
  activeCount === 2 ? (
99
99
  activeItems[1]
100
100
  ) : (
101
+ activeCount === 1 ? (
101
102
  activeItems[0] || null
103
+ ) : (
104
+ <Flex align="center" key="paragraph" gap="xs">
105
+ <Icon icon="paragraph" size="lg" />
106
+ <div>Paragraph</div>
107
+ <Flex className={showPopover ? "fa-flip-vertical" : ""} display="inline_flex">
108
+ <Icon fixedWidth icon="angle-down" margin-left="xs" />
109
+ </Flex>
110
+ </Flex>
111
+ )
102
112
  )
103
113
  }
104
114
  </Button>
@@ -35,7 +35,8 @@ type RichTextEditorProps = {
35
35
  data?: { [key: string]: string },
36
36
  focus?: boolean,
37
37
  id?: string,
38
- inline?: boolean,
38
+ inline?: boolean,
39
+ extensions?: { [key: string]: string }[],
39
40
  name?: string,
40
41
  onChange: (html: string, text: string) => void,
41
42
  placeholder?: string,
@@ -56,6 +57,7 @@ const RichTextEditor = (props: RichTextEditorProps) => {
56
57
  data = {},
57
58
  focus = false,
58
59
  inline = false,
60
+ extensions,
59
61
  name,
60
62
  onChange = noop,
61
63
  placeholder,
@@ -162,7 +164,7 @@ const RichTextEditor = (props: RichTextEditorProps) => {
162
164
  {
163
165
  advancedEditor ? (
164
166
  <div className='pb_rich_text_editor_advanced_container'>
165
- <EditorToolbar editor={advancedEditor}/>
167
+ <EditorToolbar extensions={extensions} editor={advancedEditor}/>
166
168
  { children }
167
169
  </div>
168
170
  ) : (
@@ -0,0 +1,55 @@
1
+ import React from 'react'
2
+ import { RichTextEditor } from '../..'
3
+ import { useEditor, EditorContent } from "@tiptap/react"
4
+ import StarterKit from "@tiptap/starter-kit"
5
+ import Link from '@tiptap/extension-link'
6
+
7
+ import HorizontalRule from "@tiptap/extension-horizontal-rule"
8
+ import Highlight from '@tiptap/extension-highlight'
9
+
10
+
11
+ const RichTextEditorMoreExtensions = (props) => {
12
+
13
+ const editor = useEditor({
14
+ extensions: [
15
+ StarterKit,
16
+ Link,
17
+ HorizontalRule,
18
+ Highlight.configure({ multicolor: true })
19
+ ],
20
+ content:"Add your text here. You can format your text, add links, quotes, and bullets."
21
+ })
22
+ if (!editor) {
23
+ return null
24
+ }
25
+
26
+ const ExtensionsList = [
27
+ {
28
+ icon: "horizontal-rule",
29
+ isActive: editor.isActive("horizontalRule"),
30
+ text: "Horizontal Rule",
31
+ onclick: () => editor.chain().focus().setHorizontalRule().run(),
32
+ },
33
+ {
34
+ icon: "highlighter",
35
+ isActive: editor.isActive("highlight"),
36
+ text: "Highlighter",
37
+ onclick: () => editor.chain().focus().toggleHighlight().run(),
38
+ }
39
+ ]
40
+
41
+
42
+ return (
43
+ <div>
44
+ <RichTextEditor
45
+ advancedEditor={editor}
46
+ extensions={ExtensionsList}
47
+ {...props}
48
+ >
49
+ <EditorContent editor={editor}/>
50
+ </RichTextEditor>
51
+ </div>
52
+ )
53
+ }
54
+
55
+ export default RichTextEditorMoreExtensions
@@ -0,0 +1,12 @@
1
+ This variant allows you to optionally include any of [Tiptap’s 53 extensions](https://tiptap.dev/extensions) within any advanced editor by using the `extensions` prop.
2
+
3
+ __NOTE__: In order to leverage this prop, you __must__ install the extension you need in your project, import it and pass it to the extensions array as shown in this example with the HorizontalRule and the Highlight extensions.
4
+
5
+ In order to add the extension to the editor toolbar, create an array of objects (as shown in the ExtensionsList array in the example below). Each object in this array should include:
6
+
7
+ `icon`: the icon to display within the toolbar dropdown (any Fontawesome icons can be used)
8
+ `isActive`: sets the extension to active within the dropdown, when applicable
9
+ `text`: the label within the toolbar dropdown
10
+ `onclick`: initializes the extension when it’s clicked within the dropdown (snytax varies with extension, see Tiptap's docs for more information)
11
+
12
+ This array can then be passed to the `extensions` prop and all extensions in the array will be rendered in the ellipsis dropdown.
@@ -14,6 +14,7 @@ examples:
14
14
  react:
15
15
  - rich_text_editor_default: Default
16
16
  - rich_text_editor_advanced_default: Advanced Default
17
+ - rich_text_editor_more_extensions: Advanced (Extra Extensions)
17
18
  - rich_text_editor_simple: Simple
18
19
  - rich_text_editor_attributes: Attributes
19
20
  - rich_text_editor_focus: Focus
@@ -7,4 +7,5 @@ export { default as RichTextEditorTemplates } from './_rich_text_editor_template
7
7
  export { default as RichTextEditorToolbarBottom } from './_rich_text_editor_toolbar_bottom.jsx'
8
8
  export { default as RichTextEditorInline } from './_rich_text_editor_inline.jsx'
9
9
  export { default as RichTextEditorPreview } from './_rich_text_editor_preview.jsx'
10
- export { default as RichTextEditorAdvancedDefault } from './_rich_text_editor_advanced_default.jsx'
10
+ export { default as RichTextEditorAdvancedDefault } from './_rich_text_editor_advanced_default.jsx'
11
+ export { default as RichTextEditorMoreExtensions } from './_rich_text_editor_more_extensions.jsx'
@@ -12,7 +12,6 @@
12
12
  &[class*=_2] {
13
13
  @include pb_title_2;
14
14
  @include title_colors;
15
- @include pb_title_bold;
16
15
  }
17
16
 
18
17
  &[class*=_3] {
@@ -1,4 +1,4 @@
1
1
  ##### Prop
2
- Title `size 1` & `size 2` will use `font-weight: 700` by default, if you want a lighter font weight, use the `bold` prop set to `false`.
3
- Title `size 3` uses a light font weight by default and will not accept a bold font weight.
2
+ Title `size 1` will use `font-weight: 700` by default, if you want a lighter font weight, use the `bold` prop set to `false`.
3
+ Title `size 2` & `size 3` uses a light font weight by default and will not accept a bold font weight.
4
4
  Title `size 4` uses a heavy font weight by default and will not accept a lighter font weight.
@@ -1,17 +1,15 @@
1
- /* @flow */
2
1
  import React from 'react'
3
2
  import classnames from 'classnames'
4
3
  import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
5
4
  import { globalProps } from '../utilities/globalProps'
6
- import Veteran from './badges/veteran.jsx';
7
- import MillionDollar from './badges/million-dollar.jsx';
8
-
5
+ import Veteran from './badges/veteran'
6
+ import MillionDollar from './badges/million-dollar';
9
7
 
10
8
  type UserBadgeProps = {
11
- aria?: object,
9
+ aria?: {[key: string]: string},
12
10
  badge?: "million-dollar" | "veteran",
13
11
  className?: string,
14
- data?: object,
12
+ data?: {[key: string]: string},
15
13
  id?: string,
16
14
  size?: "sm" | "md" | "lg",
17
15
  }
@@ -37,10 +35,10 @@ const UserBadge = (props: UserBadgeProps) => {
37
35
 
38
36
  return (
39
37
  <div
40
- {...ariaProps}
41
- {...dataProps}
42
- className={classes}
43
- id={id}
38
+ {...ariaProps}
39
+ {...dataProps}
40
+ className={classes}
41
+ id={id}
44
42
  >
45
43
  <div className="pb_user_badge_wrapper">
46
44
  {image}
@@ -48,4 +46,5 @@ const UserBadge = (props: UserBadgeProps) => {
48
46
  </div>
49
47
  )
50
48
  }
49
+
51
50
  export default UserBadge