frappe-ui 0.1.76 → 0.1.78
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.
- package/package.json +1 -1
- package/src/components/Badge.vue +20 -22
- package/src/components/Dialog.story.vue +15 -1
- package/src/components/Dialog.vue +39 -32
- package/src/components/Dropdown.vue +4 -4
- package/src/components/Rating/Rating.vue +2 -2
- package/src/components/Tabs.story.md +0 -6
- package/src/components/Tabs.vue +11 -16
- package/src/components/TextInput.vue +4 -0
- package/src/style.css +0 -32
- package/src/tailwind/colors.js +642 -0
- package/src/tailwind/plugin.js +301 -0
- package/src/tailwind/preset.js +10 -0
- package/src/utils/tailwind.config.js +6 -439
- package/src/espressoColors.css +0 -152
- package/src/utils/espressoVariables.js +0 -83
package/package.json
CHANGED
package/src/components/Badge.vue
CHANGED
|
@@ -41,37 +41,35 @@ const props = withDefaults(defineProps<BadgeProps>(), {
|
|
|
41
41
|
|
|
42
42
|
const classes = computed(() => {
|
|
43
43
|
let solidClasses = {
|
|
44
|
-
gray: 'text-
|
|
45
|
-
blue: 'text-
|
|
46
|
-
green: 'text-
|
|
47
|
-
orange: 'text-
|
|
48
|
-
red: 'text-
|
|
44
|
+
gray: 'text-ink-white bg-surface-gray-7',
|
|
45
|
+
blue: 'text-ink-blue-1 bg-surface-blue-2',
|
|
46
|
+
green: 'text-ink-green-1 bg-surface-green-3',
|
|
47
|
+
orange: 'text-ink-amber-1 bg-surface-amber-2',
|
|
48
|
+
red: 'text-ink-red-1 bg-surface-red-4',
|
|
49
49
|
}[props.theme]
|
|
50
50
|
|
|
51
51
|
let subtleClasses = {
|
|
52
|
-
gray: 'text-
|
|
53
|
-
blue: 'text-
|
|
54
|
-
green: 'text-
|
|
55
|
-
orange: 'text-
|
|
56
|
-
red: 'text-
|
|
52
|
+
gray: 'text-ink-gray-6 bg-surface-gray-2',
|
|
53
|
+
blue: 'text-ink-blue-2 bg-surface-blue-1',
|
|
54
|
+
green: 'text-ink-green-3 bg-surface-green-2',
|
|
55
|
+
orange: 'text-ink-amber-3 bg-surface-amber-1',
|
|
56
|
+
red: 'text-ink-red-4 bg-surface-red-1',
|
|
57
57
|
}[props.theme]
|
|
58
58
|
|
|
59
59
|
let outlineClasses = {
|
|
60
|
-
gray: 'text-
|
|
61
|
-
blue: 'text-
|
|
62
|
-
green:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
'text-text-icons-amber-3 bg-transparent border border-outline-amber-2',
|
|
66
|
-
red: 'text-text-icons-red-4 bg-transparent border border-outline-red-2',
|
|
60
|
+
gray: 'text-ink-gray-6 bg-transparent border border-outline-gray-1',
|
|
61
|
+
blue: 'text-ink-blue-2 bg-transparent border border-outline-blue-1',
|
|
62
|
+
green: 'text-ink-green-3 bg-transparent border border-outline-green-2',
|
|
63
|
+
orange: 'text-ink-amber-3 bg-transparent border border-outline-amber-2',
|
|
64
|
+
red: 'text-ink-red-4 bg-transparent border border-outline-red-2',
|
|
67
65
|
}[props.theme]
|
|
68
66
|
|
|
69
67
|
let ghostClasses = {
|
|
70
|
-
gray: 'text-
|
|
71
|
-
blue: 'text-
|
|
72
|
-
green: 'text-
|
|
73
|
-
orange: 'text-
|
|
74
|
-
red: 'text-
|
|
68
|
+
gray: 'text-ink-gray-6 bg-transparent',
|
|
69
|
+
blue: 'text-ink-blue-2 bg-transparent',
|
|
70
|
+
green: 'text-ink-green-3 bg-transparent',
|
|
71
|
+
orange: 'text-ink-amber-3 bg-transparent',
|
|
72
|
+
red: 'text-ink-red-4 bg-transparent',
|
|
75
73
|
}[props.theme]
|
|
76
74
|
|
|
77
75
|
let variantClasses = {
|
|
@@ -5,6 +5,12 @@ import { Button } from './Button'
|
|
|
5
5
|
|
|
6
6
|
const dialog1 = ref(false)
|
|
7
7
|
const dialog2 = ref(false)
|
|
8
|
+
|
|
9
|
+
const createPromise = () => {
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
setTimeout(resolve, 2000)
|
|
12
|
+
})
|
|
13
|
+
}
|
|
8
14
|
</script>
|
|
9
15
|
<template>
|
|
10
16
|
<Story :layout="{ width: 500, type: 'grid' }">
|
|
@@ -15,7 +21,15 @@ const dialog2 = ref(false)
|
|
|
15
21
|
title: 'Confirm',
|
|
16
22
|
message: 'Are you sure you want to confirm this action?',
|
|
17
23
|
size: 'xl',
|
|
18
|
-
actions: [
|
|
24
|
+
actions: [
|
|
25
|
+
{
|
|
26
|
+
label: 'Confirm',
|
|
27
|
+
variant: 'solid',
|
|
28
|
+
onClick: () => {
|
|
29
|
+
return createPromise()
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
],
|
|
19
33
|
}"
|
|
20
34
|
v-model="dialog1"
|
|
21
35
|
/>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<TransitionRoot
|
|
3
3
|
as="template"
|
|
4
|
-
:show="
|
|
4
|
+
:show="isOpen"
|
|
5
5
|
@after-leave="$emit('after-leave')"
|
|
6
6
|
>
|
|
7
7
|
<HDialog
|
|
@@ -116,13 +116,13 @@
|
|
|
116
116
|
</slot>
|
|
117
117
|
<div
|
|
118
118
|
class="px-4 pb-7 pt-4 sm:px-6"
|
|
119
|
-
v-if="
|
|
119
|
+
v-if="actions.length || $slots.actions"
|
|
120
120
|
>
|
|
121
121
|
<slot name="actions" v-bind="{ close }">
|
|
122
122
|
<div class="space-y-2">
|
|
123
123
|
<Button
|
|
124
124
|
class="w-full"
|
|
125
|
-
v-for="action in
|
|
125
|
+
v-for="action in actions"
|
|
126
126
|
:key="action.label"
|
|
127
127
|
v-bind="action"
|
|
128
128
|
>
|
|
@@ -147,7 +147,7 @@ import {
|
|
|
147
147
|
TransitionChild,
|
|
148
148
|
TransitionRoot,
|
|
149
149
|
} from '@headlessui/vue'
|
|
150
|
-
import { computed,
|
|
150
|
+
import { computed, reactive } from 'vue'
|
|
151
151
|
import { Button, ButtonProps } from './Button'
|
|
152
152
|
import FeatherIcon from './FeatherIcon.vue'
|
|
153
153
|
|
|
@@ -178,8 +178,11 @@ type DialogOptions = {
|
|
|
178
178
|
position?: 'top' | 'center'
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
+
type DialogActionContext = {
|
|
182
|
+
close: () => void
|
|
183
|
+
}
|
|
181
184
|
type DialogAction = ButtonProps & {
|
|
182
|
-
onClick?: (
|
|
185
|
+
onClick?: (context: DialogActionContext) => void | Promise<void>
|
|
183
186
|
}
|
|
184
187
|
|
|
185
188
|
interface DialogProps {
|
|
@@ -199,37 +202,41 @@ const emit = defineEmits<{
|
|
|
199
202
|
(event: 'after-leave'): void
|
|
200
203
|
}>()
|
|
201
204
|
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
()
|
|
205
|
-
(actions) => {
|
|
206
|
-
if (!actions?.length) return
|
|
205
|
+
const actions = computed(() => {
|
|
206
|
+
let actions = props.options.actions
|
|
207
|
+
if (!actions?.length) return []
|
|
207
208
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
209
|
+
return actions.map((action) => {
|
|
210
|
+
let _action = reactive({
|
|
211
|
+
...action,
|
|
212
|
+
loading: false,
|
|
213
|
+
onClick: !action.onClick
|
|
214
|
+
? close
|
|
215
|
+
: async () => {
|
|
216
|
+
_action.loading = true
|
|
217
|
+
try {
|
|
218
|
+
if (action.onClick) {
|
|
219
|
+
// deprecated: uncomment this when we remove the backwards compatibility
|
|
220
|
+
// let context: DialogActionContext = { close }
|
|
221
|
+
let backwardsCompatibleContext = function () {
|
|
222
|
+
console.warn(
|
|
223
|
+
'Value passed to onClick is a context object. Please use context.close() instead of context() to close the dialog.',
|
|
224
|
+
)
|
|
225
|
+
close()
|
|
221
226
|
}
|
|
222
|
-
|
|
223
|
-
|
|
227
|
+
backwardsCompatibleContext.close = close
|
|
228
|
+
await action.onClick(backwardsCompatibleContext)
|
|
224
229
|
}
|
|
225
|
-
}
|
|
226
|
-
|
|
230
|
+
} finally {
|
|
231
|
+
_action.loading = false
|
|
232
|
+
}
|
|
233
|
+
},
|
|
227
234
|
})
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
)
|
|
235
|
+
return _action
|
|
236
|
+
})
|
|
237
|
+
})
|
|
231
238
|
|
|
232
|
-
const
|
|
239
|
+
const isOpen = computed({
|
|
233
240
|
get() {
|
|
234
241
|
return props.modelValue
|
|
235
242
|
},
|
|
@@ -242,7 +249,7 @@ const open = computed({
|
|
|
242
249
|
})
|
|
243
250
|
|
|
244
251
|
function close() {
|
|
245
|
-
|
|
252
|
+
isOpen.value = false
|
|
246
253
|
}
|
|
247
254
|
|
|
248
255
|
const icon = computed(() => {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
<div v-for="group in groups" :key="group.key" class="p-1.5">
|
|
27
27
|
<div
|
|
28
28
|
v-if="group.group && !group.hideLabel"
|
|
29
|
-
class="flex h-7 items-center px-2 text-sm font-medium text-
|
|
29
|
+
class="flex h-7 items-center px-2 text-sm font-medium text-ink-gray-6"
|
|
30
30
|
>
|
|
31
31
|
{{ group.group }}
|
|
32
32
|
</div>
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
<button
|
|
44
44
|
v-else
|
|
45
45
|
:class="[
|
|
46
|
-
active ? 'bg-gray-100' : 'text-
|
|
46
|
+
active ? 'bg-gray-100' : 'text-ink-gray-6',
|
|
47
47
|
'group flex h-7 w-full items-center rounded px-2 text-base',
|
|
48
48
|
]"
|
|
49
49
|
@click="item.onClick"
|
|
@@ -51,11 +51,11 @@
|
|
|
51
51
|
<FeatherIcon
|
|
52
52
|
v-if="item.icon && typeof item.icon === 'string'"
|
|
53
53
|
:name="item.icon"
|
|
54
|
-
class="mr-2 h-4 w-4 flex-shrink-0 text-
|
|
54
|
+
class="mr-2 h-4 w-4 flex-shrink-0 text-ink-gray-6"
|
|
55
55
|
aria-hidden="true"
|
|
56
56
|
/>
|
|
57
57
|
<component
|
|
58
|
-
class="mr-2 h-4 w-4 flex-shrink-0 text-
|
|
58
|
+
class="mr-2 h-4 w-4 flex-shrink-0 text-ink-gray-6"
|
|
59
59
|
v-else-if="item.icon"
|
|
60
60
|
:is="item.icon"
|
|
61
61
|
/>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="space-y-1">
|
|
3
|
-
<label class="block text-xs text-
|
|
3
|
+
<label class="block text-xs text-ink-gray-5" v-if="label">
|
|
4
4
|
{{ label }}
|
|
5
5
|
</label>
|
|
6
6
|
<div class="flex text-center">
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
>
|
|
13
13
|
<FeatherIcon
|
|
14
14
|
name="star"
|
|
15
|
-
class="fill-gray-400 text-
|
|
15
|
+
class="fill-gray-400 text-ink-gray-1 stroke-1 mr-1"
|
|
16
16
|
:class="iconClasses(index)"
|
|
17
17
|
@click="markRating(index)"
|
|
18
18
|
/>
|
|
@@ -10,12 +10,6 @@ It is an array of objects which contains the following attributes:
|
|
|
10
10
|
3. You can add more attributes which can be used for custom rendering in the tab
|
|
11
11
|
header or content.
|
|
12
12
|
|
|
13
|
-
### Options
|
|
14
|
-
|
|
15
|
-
Currently, it has only one option `indicatorLeft` which is used to set the left
|
|
16
|
-
position of the indicator in case of custom rendering. It is optional and
|
|
17
|
-
default value is `20`.
|
|
18
|
-
|
|
19
13
|
## v-model
|
|
20
14
|
|
|
21
15
|
It is used to set the active tab or change the active tab. It is required.
|
package/src/components/Tabs.vue
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<TabGroup
|
|
3
3
|
as="div"
|
|
4
|
-
class="flex flex-1 flex-col"
|
|
4
|
+
class="flex flex-1 flex-col overflow-y-hidden"
|
|
5
|
+
:style="`height: calc(100vh - ${tabListRef?.$el.offsetTop}px)`"
|
|
5
6
|
:defaultIndex="changedIndex"
|
|
6
7
|
:selectedIndex="changedIndex"
|
|
7
8
|
@change="(idx) => (changedIndex = idx)"
|
|
8
9
|
>
|
|
9
10
|
<TabList
|
|
10
|
-
|
|
11
|
+
ref="tabListRef"
|
|
12
|
+
class="relative flex items-center gap-7.5 overflow-x-auto border-b px-5"
|
|
11
13
|
:class="tablistClass"
|
|
12
14
|
>
|
|
13
15
|
<Tab
|
|
@@ -30,9 +32,8 @@
|
|
|
30
32
|
</Tab>
|
|
31
33
|
<div
|
|
32
34
|
ref="indicator"
|
|
33
|
-
class="absolute bottom-0 h-px bg-gray-900"
|
|
35
|
+
class="tab-indicator absolute bottom-0 h-px bg-gray-900"
|
|
34
36
|
:class="transitionClass"
|
|
35
|
-
:style="{ left: `${indicatorLeft}px` }"
|
|
36
37
|
/>
|
|
37
38
|
</TabList>
|
|
38
39
|
<TabPanels class="flex flex-1 overflow-hidden" :class="tabPanelClass">
|
|
@@ -68,12 +69,6 @@ const props = defineProps({
|
|
|
68
69
|
type: String,
|
|
69
70
|
default: '',
|
|
70
71
|
},
|
|
71
|
-
options: {
|
|
72
|
-
type: Object,
|
|
73
|
-
default: () => ({
|
|
74
|
-
indicatorLeft: 20,
|
|
75
|
-
}),
|
|
76
|
-
},
|
|
77
72
|
})
|
|
78
73
|
|
|
79
74
|
const emit = defineEmits(['update:modelValue'])
|
|
@@ -83,11 +78,11 @@ const changedIndex = computed({
|
|
|
83
78
|
set: (index) => emit('update:modelValue', index),
|
|
84
79
|
})
|
|
85
80
|
|
|
81
|
+
const tabListRef = ref(null)
|
|
86
82
|
const tabRef = ref([])
|
|
87
83
|
const indicator = ref(null)
|
|
88
84
|
const tabsLength = computed(() => props.tabs?.length)
|
|
89
85
|
|
|
90
|
-
const indicatorLeft = ref(props.options?.indicatorLeft)
|
|
91
86
|
const transitionClass = ref('')
|
|
92
87
|
|
|
93
88
|
function moveIndicator(index) {
|
|
@@ -96,20 +91,20 @@ function moveIndicator(index) {
|
|
|
96
91
|
}
|
|
97
92
|
const selectedTab = tabRef.value[index].el
|
|
98
93
|
indicator.value.style.width = `${selectedTab.offsetWidth}px`
|
|
99
|
-
|
|
94
|
+
indicator.value.style.left = `${selectedTab.offsetLeft}px`
|
|
100
95
|
}
|
|
101
96
|
|
|
102
97
|
watch(changedIndex, (index) => {
|
|
103
98
|
if (index >= tabsLength.value) {
|
|
104
99
|
changedIndex.value = tabsLength.value - 1
|
|
105
100
|
}
|
|
101
|
+
transitionClass.value = 'transition-all duration-300 ease-in-out'
|
|
106
102
|
nextTick(() => moveIndicator(index))
|
|
107
103
|
})
|
|
108
104
|
|
|
109
105
|
onMounted(() => {
|
|
110
|
-
moveIndicator(changedIndex.value)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
})
|
|
106
|
+
nextTick(() => moveIndicator(changedIndex.value))
|
|
107
|
+
// Fix for indicator not moving on initial load
|
|
108
|
+
setTimeout(() => moveIndicator(changedIndex.value), 100)
|
|
114
109
|
})
|
|
115
110
|
</script>
|
package/src/style.css
CHANGED
|
@@ -1,37 +1,5 @@
|
|
|
1
1
|
@import './fonts/Inter/inter.css';
|
|
2
|
-
@import './espressoColors.css';
|
|
3
2
|
|
|
4
3
|
@tailwind base;
|
|
5
4
|
@tailwind components;
|
|
6
5
|
@tailwind utilities;
|
|
7
|
-
|
|
8
|
-
@layer base {
|
|
9
|
-
html,
|
|
10
|
-
body,
|
|
11
|
-
button,
|
|
12
|
-
p,
|
|
13
|
-
span,
|
|
14
|
-
div {
|
|
15
|
-
font-variation-settings: 'opsz' 24;
|
|
16
|
-
-webkit-font-smoothing: antialiased;
|
|
17
|
-
-moz-osx-font-smoothing: grayscale;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
select {
|
|
21
|
-
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="%237C7C7C" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" aria-hidden="true" viewBox="0 0 24 24" ><path d="m6 9 6 6 6-6" /></svg>');
|
|
22
|
-
background-size: 1.13em;
|
|
23
|
-
background-position: right 0.44rem center;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
@layer components {
|
|
28
|
-
.form-input,
|
|
29
|
-
.form-textarea,
|
|
30
|
-
.form-select {
|
|
31
|
-
@apply h-7 rounded border border-gray-100 bg-gray-100 py-1.5 pl-2 pr-2 text-base text-gray-800 placeholder-gray-500 transition-colors hover:border-gray-200 hover:bg-gray-200 focus:border-gray-500 focus:bg-white focus:shadow-sm focus:ring-0 focus-visible:ring-2 focus-visible:ring-gray-400;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.form-checkbox {
|
|
35
|
-
@apply rounded-md bg-gray-100 text-blue-500 focus:ring-0 focus-visible:ring-1;
|
|
36
|
-
}
|
|
37
|
-
}
|