playbook_ui 13.16.0.pre.alpha.play1141iconkitusinglibrary2060 → 13.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +14 -12
  3. data/app/pb_kits/playbook/index.js +2 -1
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/CollapsibleTrail.tsx +30 -0
  5. data/app/pb_kits/playbook/pb_advanced_table/Components/CustomCell.tsx +62 -0
  6. data/app/pb_kits/playbook/pb_advanced_table/Components/LoadingCell.tsx +5 -0
  7. data/app/pb_kits/playbook/pb_advanced_table/Components/SortIconButton.tsx +30 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/Components/SubRowHeaderRow.tsx +61 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +128 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/Components/ToggleIconButton.tsx +28 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +5 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/README.md +288 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableBody.tsx +95 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +51 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/Utilities/BrowserCheck.tsx +5 -0
  16. data/app/pb_kits/playbook/pb_advanced_table/Utilities/ExpansionControlHelpers.tsx +63 -0
  17. data/app/pb_kits/playbook/pb_advanced_table/Utilities/IconHelpers.tsx +8 -0
  18. data/app/pb_kits/playbook/pb_advanced_table/Utilities/types.ts +8 -0
  19. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +98 -0
  20. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +245 -0
  21. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +56 -0
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_default.jsx +49 -0
  23. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_default.md +13 -0
  24. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort.jsx +57 -0
  25. data/app/pb_kits/playbook/pb_advanced_table/docs/_description.md +1 -0
  26. data/app/pb_kits/playbook/pb_advanced_table/docs/_mock_data.js +278 -0
  27. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +6 -0
  28. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +2 -0
  29. data/app/pb_kits/playbook/pb_advanced_table/scss_partials/_loading.scss +71 -0
  30. data/app/pb_kits/playbook/pb_advanced_table/scss_partials/_pseudo_states.scss +12 -0
  31. data/app/pb_kits/playbook/pb_flex/_flex.tsx +1 -1
  32. data/app/pb_kits/playbook/pb_icon/_icon.scss +6 -48
  33. data/app/pb_kits/playbook/pb_icon/_icon.tsx +36 -107
  34. data/app/pb_kits/playbook/pb_icon/docs/_icon_custom.html.erb +11 -5
  35. data/app/pb_kits/playbook/pb_icon/docs/_icon_custom.jsx +18 -44
  36. data/app/pb_kits/playbook/pb_icon/docs/_icon_custom.md +5 -10
  37. data/app/pb_kits/playbook/pb_icon/icon.html.erb +4 -6
  38. data/app/pb_kits/playbook/pb_icon/icon.rb +10 -33
  39. data/app/pb_kits/playbook/pb_nav/_nav_item.test.js +2 -2
  40. data/app/pb_kits/playbook/pb_table/_table.tsx +29 -29
  41. data/app/pb_kits/playbook/playbook-doc.js +2 -0
  42. data/app/pb_kits/playbook/utilities/globalProps.ts +1 -1
  43. data/dist/menu.yml +4 -1
  44. data/dist/playbook-rails.js +6 -6
  45. data/lib/playbook/version.rb +1 -1
  46. metadata +34 -7
@@ -0,0 +1,6 @@
1
+ examples:
2
+ react:
3
+ - advanced_table_default: Default
4
+ # - advanced_table_sort: enableSorting
5
+
6
+
@@ -0,0 +1,2 @@
1
+ export { default as AdvancedTableDefault } from './_advanced_table_default.jsx'
2
+ export { default as AdvancedTableSort } from './_advanced_table_sort.jsx'
@@ -0,0 +1,71 @@
1
+
2
+ //animation scss
3
+ @keyframes wave {
4
+ 0% {
5
+ background-position: -468px 0;
6
+ }
7
+ 100% {
8
+ background-position: 468px 0;
9
+ }
10
+ }
11
+
12
+ .content-loading {
13
+ pointer-events: none;
14
+ p,
15
+ .pb_body_kit_light,
16
+ .loading-toggle-icon,
17
+ .pb_caption_kit_md,
18
+ h4,
19
+ .loading-cell {
20
+ position: relative;
21
+ color: rgba($white, 0) !important;
22
+ background: rgba($white, 0) !important;
23
+ border: 0 !important;
24
+ &::after {
25
+ content: "";
26
+ position: absolute;
27
+ top: $space-xxs;
28
+ left: 0;
29
+ width: 100%;
30
+ height: calc(100% - #{$space-xxs * 2});
31
+ display: block;
32
+ border-radius: $border-rad-light;
33
+ animation-duration: 1.5s;
34
+ animation-fill-mode: forwards;
35
+ animation-iteration-count: infinite;
36
+ animation-name: wave;
37
+ animation-timing-function: linear;
38
+ background: $silver;
39
+ background-color: $silver;
40
+ background-image: linear-gradient(
41
+ to left,
42
+ $silver 0%,
43
+ lighten($silver, 1%) 50%,
44
+ lighten($silver, 1%) 60%,
45
+ $silver 80%,
46
+ $silver 100%
47
+ );
48
+ background-repeat: no-repeat;
49
+ background-size: 800px 104px;
50
+ }
51
+ }
52
+
53
+ .loading-cell {
54
+ height: $space_sm + 4;
55
+ }
56
+
57
+ .loading-toggle-icon {
58
+ width: $space_sm - 1;
59
+ height: $space_sm - 1;
60
+ margin-bottom: $space_xxs + 2;
61
+ &::after {
62
+ height: $space_sm - 1;
63
+ border-radius: $border_radius_rounded;
64
+ }
65
+ }
66
+
67
+ svg,
68
+ img {
69
+ visibility: hidden;
70
+ }
71
+ }
@@ -0,0 +1,12 @@
1
+ %primary-color-pseudo {
2
+ &:hover,
3
+ &:active {
4
+ color: $primary;
5
+ }
6
+
7
+ &:focus-visible {
8
+ border-color: transparent;
9
+ box-shadow: 0px 0px 0 2px $primary_action;
10
+ outline: none;
11
+ }
12
+ }
@@ -10,7 +10,7 @@ type FlexProps = {
10
10
  data?: GenericObject,
11
11
  horizontal?: "left" | "center" | "right" | "stretch" | "none",
12
12
  justify?: "start" | "center" | "end" | "around" | "between" | "evenly" | "none",
13
- htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
13
+ htmlOptions?: {[key: string]: string | number | boolean | (() => void) | ((arg?: unknown) => void)},
14
14
  id?: string,
15
15
  inline?: boolean,
16
16
  orientation?: "row" | "column",
@@ -1,51 +1,9 @@
1
- $rotate-list: (90, 180, 270);
2
- $flip-list: (
3
- "horizontal": (-1, 1),
4
- "vertical": (1, -1),
5
- "both": (-1, -1)
6
- );
7
-
8
- @keyframes pb_icon_spin {
9
- 0% {
10
- -webkit-transform: rotate(0);
11
- transform: rotate(0);
12
- }
13
- 100% {
14
- -webkit-transform: rotate(360deg);
15
- transform: rotate(360deg);
16
- }
17
- };
18
-
19
- svg {
20
- &.pb_icon_kit {
21
- path {
22
- fill: currentColor !important;
23
- }
24
- @each $r in $rotate-list {
25
- &.rotate_#{$r} {
26
- transform: rotate(#{$r}deg);
27
- }
28
- }
29
- @each $f, $v in $flip-list {
30
- &.flip_#{$f} {
31
- transform: scale($v);
32
- }
33
- }
34
- &.pulse {
35
- animation-name: pb_icon_spin;
36
- animation-direction: normal;
37
- animation-duration: 1s;
38
- animation-iteration-count: infinite;
39
- animation-timing-function: steps(8);
40
- }
41
- &.spin {
42
- animation-name: pb_icon_spin;
43
- animation-delay: 0s;
44
- animation-direction: normal;
45
- animation-duration: 2s;
46
- animation-iteration-count: infinite;
47
- animation-timing-function: linear;
48
- }
1
+ // Rails custom icon styles
2
+ svg.pb_custom_icon {
3
+ width: 1em;
4
+ fill: currentColor;
5
+ path {
6
+ fill: currentColor;
49
7
  }
50
8
  }
51
9
 
@@ -1,14 +1,13 @@
1
- import React, { ReactSVGElement } from 'react'
1
+ import React from 'react'
2
2
  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
6
 
7
- type IconSizeNames = "lg"
7
+ export type IconSizes = "lg"
8
8
  | "xs"
9
9
  | "sm"
10
-
11
- export type IconSizes = IconSizeNames | "1x"
10
+ | "1x"
12
11
  | "2x"
13
12
  | "3x"
14
13
  | "4x"
@@ -22,14 +21,13 @@ export type IconSizes = IconSizeNames | "1x"
22
21
 
23
22
  type IconProps = {
24
23
  aria?: {[key: string]: string},
25
- aspectRatio?: string,
26
24
  border?: string,
27
25
  className?: string,
28
26
  customIcon?: {[key: string] :SVGElement},
29
27
  data?: {[key: string]: string},
30
28
  fixedWidth?: boolean,
31
29
  flip?: "horizontal" | "vertical" | "both" | "none",
32
- icon: string | ReactSVGElement,
30
+ icon: string,
33
31
  htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
34
32
  id?: string,
35
33
  inverse?: boolean,
@@ -42,66 +40,16 @@ type IconProps = {
42
40
  spin?: boolean,
43
41
  } & GlobalProps
44
42
 
45
- const iconSizeMap = {
46
- base: 16,
47
- xs: .75,
48
- sm: .875,
49
- lg: 1.25
50
- }
51
-
52
- const getSvgDimensions = (aspectRatio = '1:1', size: string): {width: number, height: number} | null => {
53
- if (!size) return null
54
- const aspect = aspectRatio.split(':')
55
-
56
- const scale = size.toLowerCase().endsWith('x') ?
57
- parseInt(size.replace(/\x/i, '')) :
58
- iconSizeMap[size as IconSizeNames]
59
-
60
- return {
61
- width: (iconSizeMap.base * scale) * parseInt(aspect[0]),
62
- height: (iconSizeMap.base * scale) * parseInt(aspect[1])
63
- }
64
- }
65
-
66
43
  const flipMap = {
67
- fa: {
68
- horizontal: 'fa-flip-horizontal',
69
- vertical: 'fa-flip-vertical',
70
- both: 'fa-flip-horizontal fa-flip-vertical',
71
- none: ''
72
- },
73
- svg: {
74
- horizontal: 'flip_horizontal',
75
- vertical: 'flip_vertical',
76
- both: 'flip_horizontal flip_vertical',
77
- none: ''
78
- }
79
- }
80
- const pulseMap = {
81
- fa: 'fa-pulse',
82
- svg: 'pulse'
83
- }
84
- const spinMap = {
85
- fa: 'fa-spin',
86
- svg: 'spin'
87
- }
88
- const rotateMap = {
89
- fa: {
90
- 90: 'fa-rotate-90',
91
- 180: 'fa-rotate-180',
92
- 270: 'fa-rotate-270'
93
- },
94
- svg: {
95
- 90: 'rotate_90',
96
- 180: 'rotate_180',
97
- 270: 'rotate_270'
98
- }
44
+ horizontal: 'fa-flip-horizontal',
45
+ vertical: 'fa-flip-vertical',
46
+ both: 'fa-flip-horizontal fa-flip-vertical',
47
+ none: ""
99
48
  }
100
49
 
101
50
  const Icon = (props: IconProps) => {
102
51
  const {
103
52
  aria = {},
104
- aspectRatio,
105
53
  border = false,
106
54
  className,
107
55
  customIcon,
@@ -109,52 +57,46 @@ const Icon = (props: IconProps) => {
109
57
  fixedWidth = true,
110
58
  flip = "none",
111
59
  htmlOptions = {},
112
- icon = "",
60
+ icon,
113
61
  id,
114
62
  inverse = false,
115
63
  listItem = false,
116
64
  pull,
117
65
  pulse = false,
118
66
  rotation,
119
- size = '1x',
67
+ size,
120
68
  fontStyle = 'far',
121
69
  spin = false,
122
70
  } = props
123
71
 
124
- const iconURL = typeof(icon) === 'string' && icon.includes('.svg') ? icon : null
125
- const iconElement: ReactSVGElement | null = typeof(icon) === "object" ? icon : null
72
+ const faClasses = {
73
+ 'fa-border': border,
74
+ 'fa-fw': fixedWidth,
75
+ 'fa-inverse': inverse,
76
+ 'fa-li': listItem,
77
+ 'fa-pulse': pulse,
78
+ 'fa-spin': spin,
79
+ [`fa-${size}`]: size,
80
+ [`fa-pull-${pull}`]: pull,
81
+ [`fa-rotate-${rotation}`]: rotation,
126
82
 
127
- const isFA = !iconElement && !customIcon && !iconURL
128
- const svgProps = isFA ? null : {...{fill: 'currentColor'}, ...getSvgDimensions(aspectRatio, size)}
83
+ }
129
84
 
130
- let classes = classnames(
85
+ // Lets check and see if the icon prop is referring to a custom Power icon...
86
+ // If so, then set fa-icon to "custom"
87
+ // this ensures the JS will not do any further operations
88
+ // faClasses[`fa-${icon}`] = customIcon ? 'custom' : icon
89
+ if (!customIcon) faClasses[`fa-${icon}`] = icon
90
+
91
+ const classes = classnames(
92
+ flipMap[flip],
131
93
  'pb_icon_kit',
132
- isFA ? fontStyle : null,
94
+ customIcon ? '' : fontStyle,
95
+ faClasses,
133
96
  globalProps(props),
134
97
  className
135
98
  )
136
99
 
137
- const transformClasses = classnames(
138
- flip ? flipMap[isFA ? 'fa' : 'svg'][flip] : null,
139
- pulse ? pulseMap[isFA ? 'fa' : 'svg'] : null,
140
- rotation ? rotateMap[isFA ? 'fa' : 'svg'][rotation] : null,
141
- spin ? spinMap[isFA ? 'fa' : 'svg'] : null,
142
- )
143
- if (transformClasses) classes += ` ${transformClasses}`
144
-
145
- if (isFA) {
146
- const faClassList = {
147
- 'fa-border': border,
148
- 'fa-fw': (iconElement) ? false : fixedWidth,
149
- 'fa-inverse': inverse,
150
- 'fa-li': listItem,
151
- [`fa-${size}`]: size,
152
- [`fa-pull-${pull}`]: pull,
153
- }
154
- faClassList[`fa-${icon}`] = icon as string
155
- classes += ` ${classnames(faClassList)}`
156
- }
157
-
158
100
  const classesEmoji = classnames(
159
101
  'pb_icon_kit_emoji',
160
102
  globalProps(props),
@@ -168,21 +110,20 @@ const Icon = (props: IconProps) => {
168
110
 
169
111
  // Add a conditional here to show only the SVG if custom
170
112
  const displaySVG = (customIcon: any) => {
171
- if (iconElement || customIcon)
113
+ if (customIcon)
172
114
  return (
173
115
  <>
174
116
  {
175
- React.cloneElement(iconElement || customIcon, {
117
+ React.cloneElement(customIcon, {
176
118
  ...dataProps,
177
119
  ...htmlProps,
178
- ...svgProps,
179
120
  className: classes,
180
121
  id,
181
122
  })
182
123
  }
183
124
  </>
184
125
  )
185
- else if (isValidEmoji(icon as string))
126
+ else if (isValidEmoji(icon))
186
127
  return (
187
128
  <>
188
129
  <span
@@ -195,19 +136,7 @@ const Icon = (props: IconProps) => {
195
136
  </span>
196
137
  </>
197
138
  )
198
- else if (iconURL)
199
- return (
200
- <>
201
- <img
202
- {...dataProps}
203
- {...htmlProps}
204
- {...svgProps}
205
- className={classes}
206
- id={id}
207
- src={iconURL}
208
- />
209
- </>
210
- )
139
+
211
140
  else
212
141
  return (
213
142
  <>
@@ -232,4 +161,4 @@ const Icon = (props: IconProps) => {
232
161
  )
233
162
  }
234
163
 
235
- export default Icon
164
+ export default Icon
@@ -2,9 +2,15 @@
2
2
  <div class="icon-wrapper">
3
3
 
4
4
  <% svg_url = "https://upload.wikimedia.org/wikipedia/commons/3/3b/Wrench_font_awesome.svg" %>
5
- <p><%= pb_rails("icon", props: { icon: svg_url } ) %></p>
6
- <p><%= pb_rails("icon", props: { rotation: 90, icon: svg_url, size: "2x" } ) %></p>
7
- <p><%= pb_rails("icon", props: { spin: true, icon: svg_url, size: "3x" } ) %></p>
8
- <p><%= pb_rails("icon", props: { size: "5x", icon: svg_url } ) %></p>
9
- <p><%= pb_rails("icon", props: { flip: "horizontal", size: "5x", icon: svg_url } ) %></p>
5
+ <p><%= pb_rails("icon", props: { custom_icon: svg_url } ) %></p>
6
+ <p><%= pb_rails("icon", props: { rotation: 90, custom_icon: svg_url, size: "2x" } ) %></p>
7
+ <p><%= pb_rails("icon", props: { spin: true, custom_icon: svg_url, size: "3x" } ) %></p>
8
+ <p><%= pb_rails("icon", props: { size: "5x", custom_icon: svg_url } ) %></p>
9
+ <p><%= pb_rails("icon", props: { flip: "horizontal", size: "5x", custom_icon: svg_url } ) %></p>
10
+
11
+ <%= pb_rails("body", props: {
12
+ text: "Custom icons are compatible with other icon props (size, rotation,
13
+ spin, flip, etc). Their SVG fill colors will be inherited from
14
+ parent element's css color properties."
15
+ } ) %>
10
16
  </div>
@@ -1,59 +1,33 @@
1
1
  import React from 'react'
2
2
  import { Icon } from '../../'
3
3
 
4
+ // import Icons as config from 'power-icons'
4
5
  const config = {
5
- icon: (
6
- <svg viewBox="0 -256 1792 1792"
6
+ moon: (
7
+ <svg
8
+ ariaHidden="true"
9
+ focusable="false"
10
+ role="img"
11
+ viewBox="0 0 512 512"
7
12
  xmlns="http://www.w3.org/2000/svg"
8
13
  >
9
- <g transform="matrix(1,0,0,-1,53.152542,1217.0847)">
10
- <path d="m 384,64 q 0,26 -19,45 -19,19 -45,19 -26,0 -45,-19 -19,-19 -19,-45 0,-26 19,-45 19,-19 45,-19 26,0 45,19 19,19 19,45 z m 644,420 -682,-682 q -37,-37 -90,-37 -52,0 -91,37 L 59,-90 Q 21,-54 21,0 21,53 59,91 L 740,772 Q 779,674 854.5,598.5 930,523 1028,484 z m 634,435 q 0,-39 -23,-106 Q 1592,679 1474.5,595.5 1357,512 1216,512 1031,512 899.5,643.5 768,775 768,960 q 0,185 131.5,316.5 131.5,131.5 316.5,131.5 58,0 121.5,-16.5 63.5,-16.5 107.5,-46.5 16,-11 16,-28 0,-17 -16,-28 L 1152,1120 V 896 l 193,-107 q 5,3 79,48.5 74,45.5 135.5,81 61.5,35.5 70.5,35.5 15,0 23.5,-10 8.5,-10 8.5,-25 z" />
11
- </g>
14
+ <path
15
+ d="M448 0H64C28.7 0 0 28.7 0 64v288c0 35.3 28.7 64 64 64h96v84c0 7.1 5.8 12 12 12 2.4 0 4.9-.7 7.1-2.4L304 416h144c35.3 0 64-28.7 64-64V64c0-35.3-28.7-64-64-64zm16 352c0 8.8-7.2 16-16 16H288l-12.8 9.6L208 428v-60H64c-8.8 0-16-7.2-16-16V64c0-8.8 7.2-16 16-16h384c8.8 0 16 7.2 16 16v288zM336 184h-56v-56c0-8.8-7.2-16-16-16h-16c-8.8 0-16 7.2-16 16v56h-56c-8.8 0-16 7.2-16 16v16c0 8.8 7.2 16 16 16h56v56c0 8.8 7.2 16 16 16h16c8.8 0 16-7.2 16-16v-56h56c8.8 0 16-7.2 16-16v-16c0-8.8-7.2-16-16-16z"
16
+ fill="currentColor"
17
+ />
12
18
  </svg>
13
19
  ),
14
20
  }
15
21
 
16
22
  const IconCustom = (props) => {
17
23
  return (
18
- <React.Fragment>
19
- <p>
20
- <Icon
21
- icon={config.icon}
22
- {...props}
23
- />
24
- </p>
25
- <p>
26
- <Icon
27
- icon={config.icon}
28
- rotation={90}
29
- size="2x"
30
- {...props}
31
- />
32
- </p>
33
- <p>
34
- <Icon
35
- icon={config.icon}
36
- size="3x"
37
- spin
38
- {...props}
39
- />
40
- </p>
41
- <p>
42
- <Icon
43
- icon={config.icon}
44
- size="5x"
45
- {...props}
46
- />
47
- </p>
48
- <p>
49
- <Icon
50
- flip="horizontal"
51
- icon={config.icon}
52
- size="5x"
53
- {...props}
54
- />
55
- </p>
56
- </React.Fragment>
24
+ <div>
25
+ <Icon
26
+ customIcon={config.moon}
27
+ size="7x"
28
+ {...props}
29
+ />
30
+ </div>
57
31
  )
58
32
  }
59
33
 
@@ -4,21 +4,16 @@ When using custom icons it is important to introduce a "clean" SVG. In order to
4
4
 
5
5
  Attributes must be React compatible e.g. <code>xmlns:xlink</code> should be <code>xmlnsXlink</code> and so on. <strong>There should be no hyphenated attributes and no semi-colons!.</strong>
6
6
 
7
- Fill colors with regards to <code>g</code> or <code>path</code> nodes, e.g. <code>fill="black"</code>, should be replaced with <code>currentColor</code> ala <code>fill="currentColor"</code>. Your mileage may vary depending on the complexity of your SVG.
7
+ Fill colors with regards to <code>g</code> or <code>path</code> nodes, e.g. <code>fill="black"</code>, should be replaced with <code>currentColor</code> ala <code>fill="currentColor"</code>. Your mileage may vary depending on the complexity of your SVG.
8
8
 
9
- Pay attention to your custom icon's dimensions and `viewBox` attribute. It is best to use a `viewBox="0 0 512 512"` starting point **when designing instead of trying to retrofit the viewbox afterwards**!
9
+ Pay attention to your custom icon's dimensions and `viewBox` attribute. It is best to use a `viewBox="0 0 512 512"` starting point __when designing instead of trying to retrofit the viewbox afterwards__!
10
10
 
11
- You must source _your own SVG into component/view_ you are working on. This can easily be done in programmatic and maintainable ways.
11
+ You must source *your own SVG into component/view* you are working on. This can easily be done in programmatic and maintainable ways.
12
12
 
13
13
  ### React
14
14
 
15
- - Providing a valid React `<SVG>` element to the `icon` prop results in an `<SVG>` node within the working view.
16
- - Sending the absolute path to your SVG (e.g. `/my/path/to/icon.svg`) results in an `img` node with the `src` attribute set to the provided path:
17
-
18
- ```html
19
- <img src="host.com/my/path/to/icon.svg" />
20
- ```
15
+ So long as you have a valid React `<SVG>` node, you can send it as the `customIcon` prop and the kit will take care of the rest.
21
16
 
22
17
  ### Rails
23
18
 
24
- Sending the absolute path to the `icon` prop results in an `<SVG>` tag within the working view.
19
+ Some Rails applications use only webpack(er) which means using `image_url` will be successful over `image_path` in most cases especially development where Webpack Dev Server is serving assets over HTTP. Rails applications still using Asset Pipeline may use `image_path` or `image_url`. Of course, YMMV depending on any custom configurations in your Rails application.
@@ -1,9 +1,7 @@
1
- <% if object.is_svg? %>
2
- <%= object.render_svg %>
3
- <% elsif object.valid_emoji? %>
4
- <span class="pb_icon_kit_emoji">
5
- <%= object.icon.html_safe %>
6
- </span>
1
+ <% if object.custom_icon %>
2
+ <%= object.render_svg(object.custom_icon) %>
3
+ <% elsif object.valid_emoji(object.icon) %>
4
+ <span class="pb_icon_kit_emoji"><%= object.icon.html_safe %></span>
7
5
  <% else %>
8
6
  <%= content_tag(:i, nil,
9
7
  id: object.id,
@@ -38,7 +38,7 @@ module Playbook
38
38
  prop :spin, type: Playbook::Props::Boolean,
39
39
  default: false
40
40
 
41
- def valid_emoji?
41
+ def valid_emoji(icon)
42
42
  emoji_regex = /\p{Emoji}/
43
43
  emoji_regex.match?(icon)
44
44
  end
@@ -79,42 +79,19 @@ module Playbook
79
79
  )
80
80
  end
81
81
 
82
- def render_svg
83
- doc = Nokogiri::XML(URI.open(icon || custom_icon)) # rubocop:disable Security/Open
84
- svg = doc.at_css "svg"
85
- svg["class"] = "pb_custom_icon " + object.custom_icon_classname
86
- svg["height"] = svg_dims[svg_size] * 16
87
- svg["width"] = svg_dims[svg_size] * 16
88
- doc.at_css("path")["fill"] = "currentColor"
89
- raw doc
90
- end
91
-
92
- def is_svg?
93
- (icon || custom_icon.to_s).include?(".svg")
82
+ def render_svg(path)
83
+ if File.extname(path) == ".svg"
84
+ doc = Nokogiri::XML(URI.open(path)) # rubocop:disable Security/Open
85
+ svg = doc.at_css "svg"
86
+ svg["class"] = "pb_custom_icon " + object.custom_icon_classname
87
+ raw doc
88
+ else
89
+ raise("Custom icon must be an svg. Please check your path and file type.")
90
+ end
94
91
  end
95
92
 
96
93
  private
97
94
 
98
- def svg_size
99
- size.nil? ? "1x" : size
100
- end
101
-
102
- def svg_dims
103
- { "lg" => 1.25,
104
- "xs" => 0.75,
105
- "sm" => 0.875,
106
- "1x" => 1,
107
- "2x" => 2,
108
- "3x" => 3,
109
- "4x" => 4,
110
- "5x" => 5,
111
- "6x" => 6,
112
- "7x" => 7,
113
- "8x" => 8,
114
- "9x" => 9,
115
- "10x" => 10 }
116
- end
117
-
118
95
  def border_class
119
96
  border ? "fa-border" : nil
120
97
  end
@@ -95,11 +95,11 @@ test('should not have a left border', () => {
95
95
  test('should have a right icon', () => {
96
96
  render(<NavDefault iconRight="angle-down" />)
97
97
  const kit = screen.getByTestId(itemTestId)
98
- expect(kit).toContainHTML('<i class="pb_icon_kit far pb_nav_list_item_icon_right fa-fw fa-1x fa-angle-down" />')
98
+ expect(kit).toContainHTML('<i class="pb_icon_kit far fa-fw fa-angle-down pb_nav_list_item_icon_right" />')
99
99
  })
100
100
 
101
101
  test('should have a left icon', () => {
102
102
  render(<NavDefault iconLeft="users-class" />)
103
103
  const kit = screen.getByTestId(itemTestId)
104
- expect(kit).toContainHTML('<i class="pb_icon_kit far pb_nav_list_item_icon_left fa-fw fa-1x fa-users-class" />')
104
+ expect(kit).toContainHTML('<i class="pb_icon_kit far fa-fw fa-users-class pb_nav_list_item_icon_left" />')
105
105
  })