frappe-ui 0.1.274 → 0.1.276

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.
@@ -163,7 +163,7 @@
163
163
  >
164
164
  {{ '/' }}
165
165
  </span>
166
- <div class="flex w-48 overflow-scroll">
166
+ <div class="flex w-48 overflow-auto">
167
167
  <div
168
168
  v-for="(crumb, index) in slicedBreadcrumbs"
169
169
  :key="index"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frappe-ui",
3
- "version": "0.1.274",
3
+ "version": "0.1.276",
4
4
  "description": "A set of components and utilities for rapid UI development",
5
5
  "type": "module",
6
6
  "sideEffects": false,
package/readme.md CHANGED
@@ -30,7 +30,7 @@ In 2019, I began building [Frappe Books](https://github.com/frappe/books) which
30
30
 
31
31
  ## Links
32
32
 
33
- - [Documentation](https://frappeui.com)
33
+ - [Documentation](https://ui.frappe.io)
34
34
  - [Vite Plugins](vite/README.md)
35
35
  - [Frappe UI Starter Boilerplate](https://github.com/netchampfaris/frappe-ui-starter)
36
36
  - [Community](https://github.com/frappe/frappe-ui/discussions)
@@ -13,7 +13,16 @@ const props = defineProps<{ config: AxisChartConfig }>()
13
13
  const error = ref('')
14
14
  const options = computed(() => {
15
15
  try {
16
- return useAxisChartOptions(props.config)
16
+ const config: AxisChartConfig = {
17
+ ...props.config,
18
+ dir:
19
+ props.config.dir ??
20
+ (typeof document !== 'undefined' &&
21
+ document.documentElement.dir === 'rtl'
22
+ ? 'rtl'
23
+ : 'ltr'),
24
+ }
25
+ return useAxisChartOptions(config)
17
26
  } catch (e: any) {
18
27
  error.value = e.message
19
28
  return {}
@@ -13,7 +13,16 @@ const props = defineProps<{ config: DonutChartConfig }>()
13
13
  const error = ref('')
14
14
  const options = computed(() => {
15
15
  try {
16
- return useDonutChartOptions(props.config)
16
+ const config: DonutChartConfig = {
17
+ ...props.config,
18
+ dir:
19
+ props.config.dir ??
20
+ (typeof document !== 'undefined' &&
21
+ document.documentElement.dir === 'rtl'
22
+ ? 'rtl'
23
+ : 'ltr'),
24
+ }
25
+ return useDonutChartOptions(config)
17
26
  } catch (e: any) {
18
27
  error.value = e.message
19
28
  return {}
@@ -56,7 +56,7 @@ watch(
56
56
  </script>
57
57
 
58
58
  <template>
59
- <div ref="chartDiv" v-show="!error" :class="chartClass"></div>
59
+ <div ref="chartDiv" v-show="!error" dir="ltr" :class="chartClass"></div>
60
60
  <div
61
61
  v-show="error"
62
62
  class="flex h-full w-full items-center justify-center text-center text-ink-red-3"
@@ -13,7 +13,16 @@ const props = defineProps<{ config: FunnelChartConfig }>()
13
13
  const error = ref('')
14
14
  const options = computed(() => {
15
15
  try {
16
- return useFunnelChartOptions(props.config)
16
+ const config: FunnelChartConfig = {
17
+ ...props.config,
18
+ dir:
19
+ props.config.dir ??
20
+ (typeof document !== 'undefined' &&
21
+ document.documentElement.dir === 'rtl'
22
+ ? 'rtl'
23
+ : 'ltr'),
24
+ }
25
+ return useFunnelChartOptions(config)
17
26
  } catch (e: any) {
18
27
  error.value = e.message
19
28
  return {}
@@ -22,6 +22,7 @@ export default function useAxisChartOptions(config: AxisChartConfig) {
22
22
  throw new Error('Swap axes is not supported for non-bar series or y2 axis')
23
23
  }
24
24
 
25
+ const isRTL = config.dir === 'rtl'
25
26
  const swapXY = config.swapXY
26
27
  const lastBarSeriesIdx = config.series
27
28
  .slice()
@@ -39,7 +40,7 @@ export default function useAxisChartOptions(config: AxisChartConfig) {
39
40
  labelPosition = idx == lastBarSeriesIdx ? 'top' : 'inside'
40
41
  }
41
42
  if (s.type == 'bar' && swapXY) {
42
- labelPosition = 'right'
43
+ labelPosition = isRTL ? 'left' : 'right'
43
44
  }
44
45
 
45
46
  const standardSeriesOptions = {
@@ -90,7 +91,11 @@ export default function useAxisChartOptions(config: AxisChartConfig) {
90
91
  }
91
92
 
92
93
  function getBarSeriesOptions(config: AxisChartConfig, series: BarSeriesConfig) {
93
- const roundedCorners = config.swapXY ? [0, 2, 2, 0] : [2, 2, 0, 0]
94
+ const isRTL = config.dir === 'rtl'
95
+ let roundedCorners = config.swapXY ? [0, 2, 2, 0] : [2, 2, 0, 0]
96
+ if (config.swapXY && isRTL) {
97
+ roundedCorners = [2, 0, 0, 2]
98
+ }
94
99
  const idx = config.series.findIndex((s) => s.name === series.name)
95
100
  const lastBarSeriesIdx = config.series
96
101
  .slice()
@@ -3,6 +3,7 @@ import { formatValue } from './helpers'
3
3
  import { DonutChartConfig } from './types'
4
4
 
5
5
  export default function useDonutChartOptions(config: DonutChartConfig) {
6
+ const isRTL = config.dir === 'rtl'
6
7
  let data = config.data || []
7
8
 
8
9
  data = data.sort((a, b) => {
@@ -44,7 +45,7 @@ export default function useDonutChartOptions(config: DonutChartConfig) {
44
45
  animationDuration: 700,
45
46
  color: config.colors,
46
47
  textStyle: { fontFamily: ['InterVar', 'sans-serif'] },
47
- title: getTitleOptions(config.title, config.subtitle),
48
+ title: getTitleOptions(config.title, config.subtitle, isRTL),
48
49
  dataset: {
49
50
  source: [
50
51
  [config.categoryColumn, config.valueColumn],
@@ -117,13 +118,14 @@ export default function useDonutChartOptions(config: DonutChartConfig) {
117
118
  confine: true,
118
119
  appendToBody: false,
119
120
  formatter: function (params: any) {
121
+ const dirAttr = isRTL ? ' dir="rtl"' : ''
120
122
  const p = params as any
121
123
  const value = p.value[1]
122
124
  const percentage = total > 0 ? (value / total) * 100 : 0
123
125
  const formatted = isNaN(value) ? value : formatValue(value, 1, true)
124
126
  const formattedPercentage = percentage.toFixed(0)
125
127
  return `
126
- <div class="flex items-center justify-between gap-5">
128
+ <div${dirAttr} class="flex items-center justify-between gap-5">
127
129
  <div>${p.name}</div>
128
130
  <div class="font-bold">
129
131
  ${formatted} (${formattedPercentage}%)
@@ -11,6 +11,7 @@ export const SUBTITLE_HEIGHT = 18
11
11
  export const TITLE_BOTTOM = 24
12
12
 
13
13
  export default function useEchartsOptions(config: AxisChartConfig) {
14
+ const isRTL = config.dir === 'rtl'
14
15
  const title = config.title
15
16
  const subtitle = config.subtitle
16
17
  const hasTitle = title ? 1 : 0
@@ -27,11 +28,11 @@ export default function useEchartsOptions(config: AxisChartConfig) {
27
28
  animation: true,
28
29
  animationDuration: 700,
29
30
  textStyle: { fontFamily: ['InterVar', 'sans-serif'] },
30
- title: getTitleOptions(title, subtitle),
31
+ title: getTitleOptions(title, subtitle, isRTL),
31
32
  color: config.colors,
32
33
  grid: {
33
- left: '1%',
34
- right: config.swapXY ? '2.5%' : '1.5%',
34
+ left: isRTL ? (config.swapXY ? '2.5%' : '1.5%') : '1%',
35
+ right: isRTL ? '1%' : config.swapXY ? '2.5%' : '1.5%',
35
36
  top:
36
37
  PADDING_TOP +
37
38
  TITLE_HEIGHT * hasTitle +
@@ -47,6 +48,8 @@ export default function useEchartsOptions(config: AxisChartConfig) {
47
48
  show: true,
48
49
  trigger: 'axis',
49
50
  formatter: (params: Object | Array<Object>) => {
51
+ const dirAttr = isRTL ? ' dir="rtl"' : ''
52
+
50
53
  if (Array.isArray(params)) {
51
54
  params = params
52
55
  // remove zero values
@@ -60,7 +63,7 @@ export default function useEchartsOptions(config: AxisChartConfig) {
60
63
  const value = config.swapXY ? p.value[0] : p.value[1]
61
64
  const formatted = isNaN(value) ? value : formatValue(value)
62
65
  return `
63
- <div class="flex items-center justify-between gap-5">
66
+ <div${dirAttr} class="flex items-center justify-between gap-5">
64
67
  <div>${p.name}</div>
65
68
  <div class="font-bold">${formatted}</div>
66
69
  </div>
@@ -77,7 +80,7 @@ export default function useEchartsOptions(config: AxisChartConfig) {
77
80
  : xValue
78
81
  const formattedY = isNaN(yValue) ? yValue : formatValue(yValue)
79
82
  return `
80
- <div class="flex flex-col">
83
+ <div${dirAttr} class="flex flex-col">
81
84
  ${idx == 0 ? `<div>${formattedX}</div>` : ''}
82
85
  <div class="flex items-center justify-between gap-5">
83
86
  <div class="flex gap-1 items-center">
@@ -130,13 +133,13 @@ export default function useEchartsOptions(config: AxisChartConfig) {
130
133
  }
131
134
  }
132
135
 
133
- export function getTitleOptions(title: string, subtitle?: string) {
136
+ export function getTitleOptions(title: string, subtitle?: string, isRTL?: boolean) {
134
137
  return {
135
138
  top: '4px',
136
- left: '0.8%',
139
+ left: isRTL ? 'right' : '0.8%',
140
+ padding: isRTL ? [0, 10, 0, 0] : 0,
137
141
  text: title,
138
142
  subtext: subtitle,
139
- padding: 0,
140
143
  itemGap: -3,
141
144
  textStyle: {
142
145
  fontSize: 14,
@@ -154,6 +157,8 @@ export function getTitleOptions(title: string, subtitle?: string) {
154
157
  }
155
158
 
156
159
  function getXAxisOptions(config: AxisChartConfig) {
160
+ const isRTL = config.dir === 'rtl'
161
+
157
162
  const options = config.swapXY
158
163
  ? {
159
164
  show: true,
@@ -161,12 +166,13 @@ function getXAxisOptions(config: AxisChartConfig) {
161
166
  z: 2,
162
167
  scale: false,
163
168
  boundaryGap: false,
169
+ inverse: isRTL,
164
170
  position: 'top',
165
- name: `${config.yAxis.title} →`,
171
+ name: isRTL ? `← ${config.yAxis.title}` : `${config.yAxis.title} →`,
166
172
  nameGap: 6,
167
173
  nameLocation: 'end',
168
174
  nameTextStyle: {
169
- align: 'right',
175
+ align: isRTL ? 'left' : 'right',
170
176
  verticalAlign: 'bottom',
171
177
  padding: [0, 0, 26, 0],
172
178
  backgroundColor: 'var(--surface-white)',
@@ -205,6 +211,7 @@ function getXAxisOptions(config: AxisChartConfig) {
205
211
  z: 2,
206
212
  type: config.xAxis.type,
207
213
  scale: true,
214
+ inverse: isRTL,
208
215
  splitLine: {
209
216
  show: false,
210
217
  },
@@ -228,6 +235,8 @@ function getXAxisOptions(config: AxisChartConfig) {
228
235
  }
229
236
 
230
237
  function getYAxisOptions(config: AxisChartConfig) {
238
+ const isRTL = config.dir === 'rtl'
239
+
231
240
  let primaryYAxisOptions = config.swapXY
232
241
  ? {
233
242
  show: true,
@@ -235,6 +244,7 @@ function getYAxisOptions(config: AxisChartConfig) {
235
244
  z: 2,
236
245
  scale: true,
237
246
  inverse: 'true',
247
+ position: isRTL ? 'right' : 'left',
238
248
  splitLine: {
239
249
  show: false,
240
250
  },
@@ -256,14 +266,15 @@ function getYAxisOptions(config: AxisChartConfig) {
256
266
  type: 'value',
257
267
  z: 2,
258
268
  scale: false,
269
+ position: isRTL ? 'right' : 'left',
259
270
  boundaryGap: ['0%', '1%'],
260
271
  name: `↑ ${config.yAxis.title}`,
261
272
  nameGap: 6,
262
273
  nameLocation: 'end',
263
274
  nameTextStyle: {
264
- align: 'left',
275
+ align: isRTL ? 'right' : 'left',
265
276
  verticalAlign: 'top',
266
- padding: [0, 0, 0, -2],
277
+ padding: isRTL ? [0, -2, 0, 0] : [0, 0, 0, -2],
267
278
  backgroundColor: 'var(--surface-white)',
268
279
  borderColor: 'var(--surface-white)',
269
280
  color: 'var(--ink-gray-8)',
@@ -307,13 +318,14 @@ function getYAxisOptions(config: AxisChartConfig) {
307
318
  z: 2,
308
319
  alignTicks: true,
309
320
  scale: false,
321
+ position: isRTL ? 'left' : 'right',
310
322
  boundaryGap: ['0%', '1%'],
311
- name: `${config.y2Axis?.title} ↑`,
323
+ name: isRTL ? `↑ ${config.y2Axis?.title}` : `${config.y2Axis?.title} ↑`,
312
324
  nameLocation: 'end',
313
325
  nameTextStyle: {
314
- align: 'right',
326
+ align: isRTL ? 'left' : 'right',
315
327
  verticalAlign: 'top',
316
- padding: [0, 5, 0, 0],
328
+ padding: isRTL ? [0, 0, 0, 5] : [0, 5, 0, 0],
317
329
  backgroundColor: 'var(--surface-white)',
318
330
  borderColor: 'var(--surface-white)',
319
331
  color: 'var(--ink-gray-8)',
@@ -341,7 +353,6 @@ function getYAxisOptions(config: AxisChartConfig) {
341
353
  formatter: function (value: number) {
342
354
  return formatValue(value, 1, true)
343
355
  },
344
- // color: '#000',
345
356
  },
346
357
  min: config.y2Axis?.yMin,
347
358
  max: config.y2Axis?.yMax,
@@ -9,6 +9,7 @@ import { formatValue } from './helpers'
9
9
  import { FunnelChartConfig } from './types'
10
10
 
11
11
  export default function getFunnelChartOptions(config: FunnelChartConfig) {
12
+ const isRTL = config.dir === 'rtl'
12
13
  let data = config.data || []
13
14
 
14
15
  const labelPosition = 'alternate'
@@ -37,7 +38,7 @@ export default function getFunnelChartOptions(config: FunnelChartConfig) {
37
38
  animationDuration: 700,
38
39
  color: colors,
39
40
  textStyle: { fontFamily: ['InterVar', 'sans-serif'] },
40
- title: getTitleOptions(config.title, config.subtitle),
41
+ title: getTitleOptions(config.title, config.subtitle, isRTL),
41
42
  series: [
42
43
  {
43
44
  name: 'Funnel',
@@ -98,13 +99,14 @@ export default function getFunnelChartOptions(config: FunnelChartConfig) {
98
99
  confine: true,
99
100
  appendToBody: false,
100
101
  formatter: function (params: any) {
102
+ const dirAttr = isRTL ? ' dir="rtl"' : ''
101
103
  const p = params as any
102
104
  const value = p.value
103
105
  const percentage = total > 0 ? (value / total) * 100 : 0
104
106
  const formatted = isNaN(value) ? value : formatValue(value, 1, true)
105
107
  const formattedPercentage = percentage.toFixed(0)
106
108
  return `
107
- <div class="flex items-center justify-between gap-5">
109
+ <div${dirAttr} class="flex items-center justify-between gap-5">
108
110
  <div>${p.name}</div>
109
111
  <div class="font-bold">
110
112
  ${formatted} (${formattedPercentage}%)
@@ -5,6 +5,8 @@ export type AxisChartConfig = {
5
5
  title: string
6
6
  subtitle?: string
7
7
  colors?: string[]
8
+ /** Forces layout direction; defaults to document.documentElement.dir */
9
+ dir?: 'rtl' | 'ltr'
8
10
  xAxis: {
9
11
  key: string
10
12
  type: 'category' | 'time' | 'value'
@@ -72,6 +74,8 @@ export type DonutChartConfig = {
72
74
  title: string
73
75
  subtitle?: string
74
76
  colors?: string[]
77
+ /** Forces layout direction; defaults to document.documentElement.dir */
78
+ dir?: 'rtl' | 'ltr'
75
79
  categoryColumn: string
76
80
  valueColumn: string
77
81
  maxSliceCount?: number
@@ -86,6 +90,8 @@ export type FunnelChartConfig = {
86
90
  title: string
87
91
  subtitle?: string
88
92
  colors?: string[]
93
+ /** Forces layout direction; defaults to document.documentElement.dir */
94
+ dir?: 'rtl' | 'ltr'
89
95
  categoryColumn: string
90
96
  valueColumn: string
91
97
  showPercentages?: boolean
@@ -12,7 +12,7 @@
12
12
  :style="dialogPositionStyles"
13
13
  >
14
14
  <DialogContent
15
- class="my-8 inline-block w-full transform overflow-hidden rounded-xl bg-surface-modal text-left align-middle shadow-xl dialog-content focus-visible:outline-none"
15
+ class="my-8 inline-block w-full transform overflow-hidden rounded-xl bg-surface-modal text-start align-middle shadow-xl dialog-content focus-visible:outline-none"
16
16
  :class="{
17
17
  'max-w-7xl': options.size === '7xl',
18
18
  'max-w-6xl': options.size === '6xl',
@@ -86,7 +86,7 @@ const switchCircleClasses = computed(() => {
86
86
  ]
87
87
  })
88
88
 
89
- const iconClasses = 'mr-2 h-4 w-4 flex-shrink-0 text-ink-gray-6'
89
+ const iconClasses = 'me-2 h-4 w-4 flex-shrink-0 text-ink-gray-6'
90
90
  const switchLabelClasses = computed(() => {
91
91
  return [
92
92
  'font-medium leading-normal',
@@ -103,7 +103,7 @@ const switchGroupClasses = computed(() => {
103
103
  const classes = ['flex justify-between']
104
104
  if (!props.description) {
105
105
  classes.push(
106
- 'group items-center space-x-3 py-1.5 cursor-pointer rounded focus-visible:bg-surface-gray-2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-outline-gray-3',
106
+ 'group items-center gap-x-3 py-1.5 cursor-pointer rounded focus-visible:bg-surface-gray-2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-outline-gray-3',
107
107
  )
108
108
 
109
109
  classes.push(
@@ -113,7 +113,7 @@ const switchGroupClasses = computed(() => {
113
113
  )
114
114
  } else {
115
115
  classes.push('items-start')
116
- classes.push(props.size === 'md' ? 'space-x-3.5' : 'space-x-2.5')
116
+ classes.push(props.size === 'md' ? 'gap-x-3.5' : 'gap-x-2.5')
117
117
  }
118
118
 
119
119
  return classes
@@ -8,11 +8,19 @@ import {
8
8
  } from 'reka-ui'
9
9
 
10
10
  import type { TabProps } from './types'
11
- import { h } from 'vue'
11
+ import { computed, h } from 'vue'
12
12
 
13
13
  const props = defineProps<TabProps>()
14
14
  const model = defineModel<string | number>({ default: 0 })
15
15
 
16
+ const dir = computed<'rtl' | 'ltr'>(
17
+ () =>
18
+ props.dir ??
19
+ (typeof document !== 'undefined' && document.documentElement.dir === 'rtl'
20
+ ? 'rtl'
21
+ : 'ltr'),
22
+ )
23
+
16
24
  const indicatorXCss = `left-0 bottom-0 h-[2px] w-[--reka-tabs-indicator-size] transition-[width,transform]
17
25
  translate-x-[--reka-tabs-indicator-position] translate-y-[1px]`
18
26
 
@@ -25,16 +33,21 @@ const Btn = h('button')
25
33
 
26
34
  defineSlots<{
27
35
  /** Custom renderer for a tab trigger (icon + label / router-link). */
28
- 'tab-item'?: (props: { tab: { label: string; icon?: string; route?: string } }) => any
36
+ 'tab-item'?: (props: {
37
+ tab: { label: string; icon?: string; route?: string }
38
+ }) => any
29
39
 
30
40
  /** Content rendered for each tab panel. */
31
- 'tab-panel'?: (props: { tab: { label: string; icon?: string; route?: string } }) => any
41
+ 'tab-panel'?: (props: {
42
+ tab: { label: string; icon?: string; route?: string }
43
+ }) => any
32
44
  }>()
33
45
  </script>
34
46
 
35
47
  <template>
36
48
  <TabsRoot
37
49
  :as="props.as"
50
+ :dir="dir"
38
51
  class="flex flex-1 overflow-hidden flex-col data-[orientation=vertical]:flex-row"
39
52
  :orientation="props.vertical ? 'vertical' : 'horizontal'"
40
53
  :default-value="props.tabs[0].label"
@@ -18,4 +18,7 @@ export interface TabProps {
18
18
 
19
19
  /** Renders tabs vertically instead of horizontally */
20
20
  vertical?: boolean
21
+
22
+ /** Forces layout direction; defaults to document.documentElement.dir */
23
+ dir?: 'rtl' | 'ltr'
21
24
  }
@@ -6,7 +6,7 @@
6
6
  >
7
7
  <div
8
8
  :class="[
9
- 'absolute inset-y-0 left-0 flex items-center',
9
+ 'absolute inset-y-0 start-0 flex items-center',
10
10
  textColor,
11
11
  prefixClasses,
12
12
  ]"
@@ -29,7 +29,7 @@
29
29
  />
30
30
  <div
31
31
  :class="[
32
- 'absolute inset-y-0 right-0 flex items-center',
32
+ 'absolute inset-y-0 end-0 flex items-center',
33
33
  textColor,
34
34
  suffixClasses,
35
35
  ]"
@@ -94,23 +94,23 @@ const inputClasses = computed(() => {
94
94
  let paddingClasses = {
95
95
  sm: [
96
96
  'py-1.5',
97
- slots.prefix ? 'pl-8' : 'pl-2',
98
- slots.suffix ? 'pr-8' : 'pr-2',
97
+ slots.prefix ? 'ps-8' : 'ps-2',
98
+ slots.suffix ? 'pe-8' : 'pe-2',
99
99
  ],
100
100
  md: [
101
101
  'py-1.5',
102
- slots.prefix ? 'pl-9' : 'pl-2.5',
103
- slots.suffix ? 'pr-9' : 'pr-2.5',
102
+ slots.prefix ? 'ps-9' : 'ps-2.5',
103
+ slots.suffix ? 'pe-9' : 'pe-2.5',
104
104
  ],
105
105
  lg: [
106
106
  'py-1.5',
107
- slots.prefix ? 'pl-10' : 'pl-3',
108
- slots.suffix ? 'pr-10' : 'pr-3',
107
+ slots.prefix ? 'ps-10' : 'ps-3',
108
+ slots.suffix ? 'pe-10' : 'pe-3',
109
109
  ],
110
110
  xl: [
111
111
  'py-1.5',
112
- slots.prefix ? 'pl-10' : 'pl-3',
113
- slots.suffix ? 'pr-10' : 'pr-3',
112
+ slots.prefix ? 'ps-10' : 'ps-3',
113
+ slots.suffix ? 'pe-10' : 'pe-3',
114
114
  ],
115
115
  }[props.size]
116
116
 
@@ -140,19 +140,19 @@ const inputClasses = computed(() => {
140
140
 
141
141
  let prefixClasses = computed(() => {
142
142
  return {
143
- sm: 'pl-2',
144
- md: 'pl-2.5',
145
- lg: 'pl-3',
146
- xl: 'pl-3',
143
+ sm: 'ps-2',
144
+ md: 'ps-2.5',
145
+ lg: 'ps-3',
146
+ xl: 'ps-3',
147
147
  }[props.size]
148
148
  })
149
149
 
150
150
  let suffixClasses = computed(() => {
151
151
  return {
152
- sm: 'pr-2',
153
- md: 'pr-2.5',
154
- lg: 'pr-3',
155
- xl: 'pr-3',
152
+ sm: 'pe-2',
153
+ md: 'pe-2.5',
154
+ lg: 'pe-3',
155
+ xl: 'pe-3',
156
156
  }[props.size]
157
157
  })
158
158