pimelon-ui 0.1.74 → 0.1.75

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.
Files changed (30) hide show
  1. package/package.json +1 -1
  2. package/src/components/Autocomplete.vue +1 -1
  3. package/src/components/Billing/TrialBanner.vue +1 -1
  4. package/src/components/Breadcrumbs.vue +8 -2
  5. package/src/components/{Button.story.vue → Button/Button.story.vue} +1 -1
  6. package/src/components/{Button.vue → Button/Button.vue} +39 -16
  7. package/src/components/Button/index.ts +1 -0
  8. package/src/components/Calendar/Calendar.vue +1 -1
  9. package/src/components/Calendar/CalendarWeekly.vue +1 -1
  10. package/src/components/Calendar/NewEventModal.vue +1 -1
  11. package/src/components/ConfirmDialog.vue +1 -1
  12. package/src/components/DatePicker.vue +1 -1
  13. package/src/components/DateRangePicker.vue +1 -1
  14. package/src/components/DateTimePicker.vue +1 -1
  15. package/src/components/Dialog.story.vue +1 -1
  16. package/src/components/Dialog.vue +1 -2
  17. package/src/components/Dropdown.story.vue +1 -1
  18. package/src/components/Dropdown.vue +45 -31
  19. package/src/components/FileUploader.story.vue +1 -1
  20. package/src/components/ListView/ListEmptyState.vue +1 -1
  21. package/src/components/ListView/ListSelectBanner.vue +1 -1
  22. package/src/components/ListView.story.vue +1 -1
  23. package/src/components/LoadingIndicator.vue +1 -5
  24. package/src/components/Popover.story.vue +1 -1
  25. package/src/components/TextEditor/InsertImage.vue +1 -1
  26. package/src/components/TextEditor/InsertLink.vue +1 -1
  27. package/src/components/TextEditor/InsertVideo.vue +1 -1
  28. package/src/components/Tooltip/Tooltip.story.vue +1 -1
  29. package/src/index.js +1 -1
  30. package/src/components/types/Button.ts +0 -14
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pimelon-ui",
3
- "version": "0.1.74",
3
+ "version": "0.1.75",
4
4
  "description": "A set of components and utilities for rapid UI development",
5
5
  "main": "./src/index.js",
6
6
  "scripts": {
@@ -174,7 +174,7 @@ import {
174
174
  } from '@headlessui/vue'
175
175
  import { nextTick } from 'vue'
176
176
  import Popover from './Popover.vue'
177
- import Button from './Button.vue'
177
+ import { Button } from './Button'
178
178
  import FeatherIcon from './FeatherIcon.vue'
179
179
 
180
180
  export default {
@@ -22,7 +22,7 @@
22
22
  <script setup>
23
23
  import LightningIcon from './LightningIcon.vue'
24
24
  import FeatherIcon from '../FeatherIcon.vue'
25
- import Button from '../Button.vue'
25
+ import { Button } from '../Button'
26
26
  import { createResource } from '../../resources'
27
27
  import { ref, computed } from 'vue'
28
28
 
@@ -63,7 +63,7 @@ import { useWindowSize } from '@vueuse/core'
63
63
  import { computed } from 'vue'
64
64
  import { RouterLinkProps, useRouter } from 'vue-router'
65
65
  import Dropdown from '../components/Dropdown.vue'
66
- import Button from '../components/Button.vue'
66
+ import { Button } from './Button'
67
67
 
68
68
  interface BreadcrumbItem {
69
69
  label: string
@@ -90,7 +90,13 @@ const dropdownItems = computed(() => {
90
90
 
91
91
  let allExceptLastTwo = items.value.slice(0, -2)
92
92
  return allExceptLastTwo.map((item) => {
93
- let onClick = item.onClick ? item.onClick : () => router.push(item.route)
93
+ let onClick = () => {
94
+ if (item.route) {
95
+ router.push(item.route)
96
+ } else if (item.onClick) {
97
+ item.onClick()
98
+ }
99
+ }
94
100
  return {
95
101
  ...item,
96
102
  icon: null,
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { reactive } from 'vue'
3
- import Button from './Button.vue'
3
+ import { Button } from './index'
4
4
  const state = reactive({
5
5
  theme: 'gray',
6
6
  size: 'sm',
@@ -17,21 +17,23 @@
17
17
  />
18
18
  <slot name="prefix" v-else-if="$slots['prefix'] || iconLeft">
19
19
  <FeatherIcon
20
- v-if="iconLeft"
20
+ v-if="iconLeft && typeof iconLeft === 'string'"
21
21
  :name="iconLeft"
22
22
  :class="slotClasses"
23
23
  aria-hidden="true"
24
24
  />
25
+ <component v-else-if="iconLeft" :is="iconLeft" :class="slotClasses" />
25
26
  </slot>
26
27
 
27
28
  <template v-if="loading && loadingText">{{ loadingText }}</template>
28
29
  <template v-else-if="isIconButton && !loading">
29
30
  <FeatherIcon
30
- v-if="icon"
31
+ v-if="icon && typeof icon === 'string'"
31
32
  :name="icon"
32
33
  :class="slotClasses"
33
34
  :aria-label="label"
34
35
  />
36
+ <component v-else-if="icon" :is="icon" :class="slotClasses" />
35
37
  <slot name="icon" v-else-if="$slots.icon" />
36
38
  </template>
37
39
  <span v-else :class="{ 'sr-only': isIconButton }">
@@ -40,21 +42,39 @@
40
42
 
41
43
  <slot name="suffix">
42
44
  <FeatherIcon
43
- v-if="iconRight"
45
+ v-if="iconRight && typeof iconRight === 'string'"
44
46
  :name="iconRight"
45
47
  :class="slotClasses"
46
48
  aria-hidden="true"
47
49
  />
50
+ <component v-else-if="iconRight" :is="iconRight" :class="slotClasses" />
48
51
  </slot>
49
52
  </button>
50
53
  </template>
51
54
  <script lang="ts" setup>
52
- import { computed, useSlots } from 'vue'
53
- import FeatherIcon from './FeatherIcon.vue'
54
- import LoadingIndicator from './LoadingIndicator.vue'
55
- import { useRouter } from 'vue-router'
56
-
57
- import type { ButtonProps } from './types/Button'
55
+ import { computed, useSlots, type Component } from 'vue'
56
+ import FeatherIcon from '../FeatherIcon.vue'
57
+ import LoadingIndicator from '../LoadingIndicator.vue'
58
+ import { useRouter, type RouteLocation } from 'vue-router'
59
+
60
+ type Theme = 'gray' | 'blue' | 'green' | 'red'
61
+ type Size = 'sm' | 'md' | 'lg' | 'xl' | '2xl'
62
+ type Variant = 'solid' | 'subtle' | 'outline' | 'ghost'
63
+
64
+ export interface ButtonProps {
65
+ theme?: Theme
66
+ size?: Size
67
+ variant?: Variant
68
+ label?: string
69
+ icon?: string | Component
70
+ iconLeft?: string | Component
71
+ iconRight?: string | Component
72
+ loading?: boolean
73
+ loadingText?: string
74
+ disabled?: boolean
75
+ route?: RouteLocation
76
+ link?: string
77
+ }
58
78
 
59
79
  const props = withDefaults(defineProps<ButtonProps>(), {
60
80
  theme: 'gray',
@@ -112,10 +132,12 @@ const buttonClasses = computed(() => {
112
132
  ghost: ghostClasses,
113
133
  }[props.variant]
114
134
 
115
- let themeVariant = `${props.theme}-${props.variant}`
135
+ type ThemeVariant = `${Theme}-${Variant}`
136
+ let themeVariant: ThemeVariant = `${props.theme}-${props.variant}`
116
137
 
117
- let disabledClassesMap = {
118
- gray: 'bg-gray-100 text-gray-500',
138
+ let disabledClassesMap: Record<ThemeVariant, string> = {
139
+ 'gray-solid': 'bg-gray-100 text-gray-500',
140
+ 'gray-subtle': 'bg-gray-100 text-gray-500',
119
141
  'gray-outline': 'bg-gray-100 text-gray-500 border border-gray-300',
120
142
  'gray-ghost': 'text-gray-500',
121
143
 
@@ -124,16 +146,17 @@ const buttonClasses = computed(() => {
124
146
  'blue-outline': 'bg-blue-100 text-blue-400 border border-blue-300',
125
147
  'blue-ghost': 'text-blue-400',
126
148
 
127
- green: 'bg-green-100 text-green-500',
149
+ 'green-solid': 'bg-green-100 text-green-500',
150
+ 'green-subtle': 'bg-green-100 text-green-500',
128
151
  'green-outline': 'bg-green-100 text-green-500 border border-green-400',
129
152
  'green-ghost': 'text-green-500',
130
153
 
131
- red: 'bg-red-100 text-red-400',
154
+ 'red-solid': 'bg-red-100 text-red-400',
155
+ 'red-subtle': 'bg-red-100 text-red-400',
132
156
  'red-outline': 'bg-red-100 text-red-400 border border-red-300',
133
157
  'red-ghost': 'text-red-400',
134
158
  }
135
- let disabledClasses =
136
- disabledClassesMap[themeVariant] || disabledClassesMap[props.theme]
159
+ let disabledClasses = disabledClassesMap[themeVariant]
137
160
 
138
161
  let sizeClasses = {
139
162
  sm: 'h-7 text-base px-2 rounded',
@@ -0,0 +1 @@
1
+ export { default as Button, type ButtonProps } from './Button.vue'
@@ -75,7 +75,7 @@
75
75
  </template>
76
76
  <script setup>
77
77
  import { computed, onMounted, onUnmounted, provide, ref, watch } from 'vue'
78
- import Button from '../Button.vue'
78
+ import { Button } from '../Button'
79
79
  import TabButtons from '../TabButtons.vue'
80
80
  import {
81
81
  getCalendarDates,
@@ -124,7 +124,7 @@ import {
124
124
  parseDate,
125
125
  } from './calendarUtils'
126
126
 
127
- import Button from '../Button.vue'
127
+ import { Button } from '../Button'
128
128
  import ShowMoreCalendarEvent from './ShowMoreCalendarEvent.vue'
129
129
  import useCalendarData from './composables/useCalendarData'
130
130
 
@@ -100,7 +100,7 @@ import { computed, inject, reactive, ref } from 'vue'
100
100
  import Dialog from '../Dialog.vue'
101
101
  import FormControl from '../FormControl.vue'
102
102
  import ErrorMessage from '../ErrorMessage.vue'
103
- import Button from '../Button.vue'
103
+ import { Button } from '../Button'
104
104
 
105
105
  import { calculateDiff, colorMap, handleSeconds } from './calendarUtils'
106
106
  const show = ref(false)
@@ -11,8 +11,8 @@
11
11
  </Dialog>
12
12
  </template>
13
13
  <script>
14
+ import { Button } from './Button'
14
15
  import Dialog from './Dialog.vue'
15
- import Button from './Button.vue'
16
16
 
17
17
  export default {
18
18
  name: 'ConfirmDialog',
@@ -125,7 +125,7 @@
125
125
  import { computed, onMounted } from 'vue'
126
126
 
127
127
  import Input from './Input.vue'
128
- import Button from './Button.vue'
128
+ import { Button } from './Button'
129
129
  import Popover from './Popover.vue'
130
130
  import FeatherIcon from './FeatherIcon.vue'
131
131
  import TextInput from './TextInput.vue'
@@ -121,7 +121,7 @@
121
121
  import { computed, ref, onMounted } from 'vue'
122
122
 
123
123
  import Input from './Input.vue'
124
- import Button from './Button.vue'
124
+ import { Button } from './Button'
125
125
  import Popover from './Popover.vue'
126
126
  import FeatherIcon from './FeatherIcon.vue'
127
127
  import TextInput from './TextInput.vue'
@@ -188,7 +188,7 @@
188
188
  import { ref, computed, onMounted } from 'vue'
189
189
 
190
190
  import Input from './Input.vue'
191
- import Button from './Button.vue'
191
+ import { Button } from './Button'
192
192
  import Popover from './Popover.vue'
193
193
  import FeatherIcon from './FeatherIcon.vue'
194
194
  import TextInput from './TextInput.vue'
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { ref } from 'vue'
3
3
  import Dialog from './Dialog.vue'
4
- import Button from './Button.vue'
4
+ import { Button } from './Button'
5
5
 
6
6
  const dialog1 = ref(false)
7
7
  const dialog2 = ref(false)
@@ -148,9 +148,8 @@ import {
148
148
  TransitionRoot,
149
149
  } from '@headlessui/vue'
150
150
  import { computed, ref, watch } from 'vue'
151
- import Button from './Button.vue'
151
+ import { Button, ButtonProps } from './Button'
152
152
  import FeatherIcon from './FeatherIcon.vue'
153
- import { ButtonProps } from './types/Button'
154
153
 
155
154
  type DialogIcon = {
156
155
  name: string
@@ -2,7 +2,7 @@
2
2
  import { h } from 'vue'
3
3
  import Dropdown from './Dropdown.vue'
4
4
  import FeatherIcon from './FeatherIcon.vue'
5
- import Button from './Button.vue'
5
+ import { Button } from './Button'
6
6
  </script>
7
7
 
8
8
  <template>
@@ -74,33 +74,34 @@
74
74
  <script setup lang="ts">
75
75
  import { Menu, MenuButton, MenuItems, MenuItem } from '@headlessui/vue'
76
76
  import Popover from './Popover.vue'
77
- import Button from './Button.vue'
77
+ import { Button, ButtonProps } from './Button'
78
78
  import FeatherIcon from './FeatherIcon.vue'
79
79
  import { computed } from 'vue'
80
- import { useRouter } from 'vue-router'
80
+ import { RouterLinkProps, useRouter } from 'vue-router'
81
81
 
82
82
  const router = useRouter()
83
83
 
84
84
  type DropdownOption = {
85
85
  label: string
86
- icon?: string
87
- group?: string
86
+ icon?: string | null
88
87
  component?: any
89
88
  onClick?: () => void
90
- route?: string
89
+ route?: RouterLinkProps['to']
91
90
  condition?: () => boolean
92
91
  }
93
92
 
94
- type DropdownOptions = string | DropdownOption
95
-
96
- type ButtonProps = {
97
- label: string
98
- icon?: string
93
+ type DropdownGroupOption = {
94
+ key?: number
95
+ group: string
96
+ items: DropdownOption[]
97
+ hideLabel?: boolean
99
98
  }
100
99
 
100
+ type DropdownOptions = Array<DropdownOption | DropdownGroupOption>
101
+
101
102
  interface DropdownProps {
102
103
  button?: ButtonProps
103
- options?: DropdownOptions[]
104
+ options?: DropdownOptions
104
105
  placement?: string
105
106
  }
106
107
 
@@ -110,42 +111,55 @@ const props = withDefaults(defineProps<DropdownProps>(), {
110
111
  })
111
112
 
112
113
  const normalizeDropdownItem = (option: DropdownOption) => {
113
- let onClick = option.onClick || null
114
- if (!onClick && option.route && router) {
115
- onClick = () => router.push(option.route!)
114
+ let onClick = () => {
115
+ if (option.route) {
116
+ router.push(option.route)
117
+ } else if (option.onClick) {
118
+ option.onClick()
119
+ }
116
120
  }
117
121
 
118
122
  return {
119
123
  label: option.label,
120
124
  icon: option.icon,
121
- group: option.group,
122
125
  component: option.component,
123
126
  onClick,
124
127
  }
125
128
  }
126
129
 
127
- const filterOptions = (options: DropdownOptions) => {
130
+ const filterOptions = (options: DropdownOption[]) => {
128
131
  return (options || [])
129
132
  .filter(Boolean)
130
- .filter((option: DropdownOption) =>
131
- option.condition ? option.condition() : true,
132
- )
133
- .map((option: DropdownOption) => normalizeDropdownItem(option))
133
+ .filter((option) => (option.condition ? option.condition() : true))
134
+ .map((option) => normalizeDropdownItem(option))
134
135
  }
135
136
 
136
137
  const groups = computed(() => {
137
- let groups = props.options[0]?.group
138
- ? props.options
139
- : [{ group: '', items: props.options }]
140
-
141
- return groups.map((group, i) => {
142
- return {
143
- key: i,
144
- group: group.group,
145
- hideLabel: group.hideLabel || false,
146
- items: filterOptions(group.items),
138
+ let groups: DropdownGroupOption[] = []
139
+ let i = 0
140
+ for (let option of props.options) {
141
+ if (option == null) {
142
+ continue
143
+ }
144
+ if ('group' in option) {
145
+ let groupOption = {
146
+ key: i,
147
+ ...option,
148
+ items: filterOptions(option.items),
149
+ } as DropdownGroupOption
150
+ groups.push(groupOption)
151
+ } else {
152
+ let groupOption = {
153
+ key: i,
154
+ group: '',
155
+ hideLabel: true,
156
+ items: filterOptions([option]),
157
+ } as DropdownGroupOption
158
+ groups.push(groupOption)
147
159
  }
148
- })
160
+ i++
161
+ }
162
+ return groups
149
163
  })
150
164
 
151
165
  const dropdownTransition = computed(() => {
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import FileUploader from './FileUploader.vue'
3
- import Button from './Button.vue'
3
+ import { Button } from './Button'
4
4
 
5
5
  const validateFileFunction = (fileObject) => {}
6
6
  const onSuccess = (file) => {}
@@ -18,7 +18,7 @@
18
18
 
19
19
  <script setup>
20
20
  import { inject } from 'vue'
21
- import Button from '../Button.vue'
21
+ import { Button } from '../Button'
22
22
 
23
23
  const list = inject('list')
24
24
  </script>
@@ -70,7 +70,7 @@
70
70
 
71
71
  <script setup>
72
72
  import Checkbox from '../Checkbox.vue'
73
- import Button from '../Button.vue'
73
+ import { Button } from '../Button'
74
74
  import { computed, inject } from 'vue'
75
75
 
76
76
  defineOptions({
@@ -2,7 +2,7 @@
2
2
  import { reactive, h, ref } from 'vue'
3
3
  import Avatar from './Avatar.vue'
4
4
  import Badge from './Badge.vue'
5
- import Button from './Button.vue'
5
+ import { Button } from './Button'
6
6
  import FeatherIcon from './FeatherIcon.vue'
7
7
  import ListHeader from './ListView/ListHeader.vue'
8
8
  import ListHeaderItem from './ListView/ListHeaderItem.vue'
@@ -20,8 +20,4 @@
20
20
  ></path>
21
21
  </svg>
22
22
  </template>
23
- <script>
24
- export default {
25
- name: 'LoadingIndicator',
26
- }
27
- </script>
23
+ <script setup lang="ts"></script>
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import Popover from './Popover.vue'
3
- import Button from './Button.vue'
3
+ import { Button } from './Button'
4
4
  </script>
5
5
  <template>
6
6
  <Story :layout="{ type: 'grid' }">
@@ -36,7 +36,7 @@
36
36
  <script>
37
37
  import fileToBase64 from '../../utils/file-to-base64'
38
38
  import Dialog from '../Dialog.vue'
39
- import Button from '../Button.vue'
39
+ import { Button } from '../Button'
40
40
 
41
41
  export default {
42
42
  name: 'InsertImage',
@@ -26,7 +26,7 @@
26
26
  </template>
27
27
  <script>
28
28
  import Dialog from '../Dialog.vue'
29
- import Button from '../Button.vue'
29
+ import { Button } from '../Button'
30
30
  import FormControl from '../FormControl.vue'
31
31
 
32
32
  export default {
@@ -54,7 +54,7 @@
54
54
  </Dialog>
55
55
  </template>
56
56
  <script>
57
- import Button from '../Button.vue'
57
+ import { Button } from '../Button'
58
58
  import Dialog from '../Dialog.vue'
59
59
  import FileUploader from '../FileUploader.vue'
60
60
 
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { ref } from 'vue'
3
3
  import Tooltip from './Tooltip.vue'
4
- import Button from '../Button.vue'
4
+ import { Button } from '../Button'
5
5
 
6
6
  const placement = ref('top')
7
7
  const disabled = ref(true)
package/src/index.js CHANGED
@@ -4,7 +4,7 @@ export { default as Autocomplete } from './components/Autocomplete.vue'
4
4
  export { default as Avatar } from './components/Avatar.vue'
5
5
  export { default as Badge } from './components/Badge.vue'
6
6
  export { default as Breadcrumbs } from './components/Breadcrumbs.vue'
7
- export { default as Button } from './components/Button.vue'
7
+ export * from './components/Button'
8
8
  export { default as Card } from './components/Card.vue'
9
9
  export { default as Checkbox } from './components/Checkbox.vue'
10
10
  export { default as DatePicker } from './components/DatePicker.vue'
@@ -1,14 +0,0 @@
1
- export interface ButtonProps {
2
- theme?: 'gray' | 'blue' | 'green' | 'red'
3
- size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl'
4
- variant?: 'solid' | 'subtle' | 'outline' | 'ghost'
5
- label?: string
6
- icon?: string
7
- iconLeft?: string
8
- iconRight?: string
9
- loading?: boolean
10
- loadingText?: string
11
- disabled?: boolean
12
- route?: string | object
13
- link?: string
14
- }