frappe-ui 0.1.143 → 0.1.145

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.
@@ -7,7 +7,13 @@
7
7
  <slot>
8
8
  <div class="flex flex-col gap-2 text-ink-gray-9 text-base">
9
9
  <div v-if="currentStep.message">{{ currentStep.message }}</div>
10
- <video v-if="currentStep.videoURL" class="w-full rounded" controls>
10
+ <video
11
+ v-if="currentStep.videoURL"
12
+ class="w-full rounded"
13
+ controls
14
+ autoplay
15
+ muted
16
+ >
11
17
  <source :src="currentStep.videoURL" type="video/mp4" />
12
18
  Your browser does not support the video tag.
13
19
  </video>
@@ -35,25 +35,38 @@
35
35
  v-for="step in steps"
36
36
  :key="step.title"
37
37
  class="group w-full flex gap-2 justify-between items-center hover:bg-surface-gray-1 rounded px-2 py-1.5 cursor-pointer"
38
- @click.stop="() => !step.completed && step.onClick()"
38
+ @click.stop="
39
+ () => !step.completed && !isDependent(step) && step.onClick()
40
+ "
39
41
  >
40
- <div
41
- class="flex gap-2 items-center"
42
- :class="[step.completed ? 'text-ink-gray-5' : 'text-ink-gray-8']"
42
+ <component
43
+ :is="isDependent(step) ? Tooltip : 'div'"
44
+ :text="dependsOnTooltip(step)"
43
45
  >
44
- <component :is="step.icon" class="h-4" />
45
- <div class="text-base" :class="{ 'line-through': step.completed }">
46
- {{ step.title }}
46
+ <div
47
+ class="flex gap-2 items-center"
48
+ :class="[
49
+ step.completed
50
+ ? 'text-ink-gray-5'
51
+ : isDependent(step)
52
+ ? 'text-ink-gray-4'
53
+ : 'text-ink-gray-8',
54
+ ]"
55
+ >
56
+ <component :is="step.icon" class="h-4" />
57
+ <div class="text-base" :class="{ 'line-through': step.completed }">
58
+ {{ step.title }}
59
+ </div>
47
60
  </div>
48
- </div>
61
+ </component>
49
62
  <Button
50
- v-if="!step.completed"
63
+ v-if="!step.completed && !isDependent(step)"
51
64
  :label="'Skip'"
52
65
  class="!h-4 text-xs !text-ink-gray-6 hidden group-hover:flex"
53
66
  @click="() => skip(step.name, afterSkip)"
54
67
  />
55
68
  <Button
56
- v-else
69
+ v-else-if="!isDependent(step)"
57
70
  :label="'Reset'"
58
71
  class="!h-4 text-xs !text-ink-gray-6 hidden group-hover:flex"
59
72
  @click.stop="() => reset(step.name, afterReset)"
@@ -64,6 +77,7 @@
64
77
  </template>
65
78
  <script setup>
66
79
  import { useOnboarding } from './onboarding'
80
+ import Tooltip from '../../src/components/Tooltip/Tooltip.vue'
67
81
  import Button from '../../src/components/Button/Button.vue'
68
82
  import Badge from '../../src/components/Badge.vue'
69
83
 
@@ -98,6 +112,26 @@ const props = defineProps({
98
112
  },
99
113
  })
100
114
 
115
+ function isDependent(step) {
116
+ if (step.dependsOn && !step.completed) {
117
+ const dependsOnStep = steps.find((s) => s.name === step.dependsOn)
118
+ if (dependsOnStep && !dependsOnStep.completed) {
119
+ return true
120
+ }
121
+ }
122
+ return false
123
+ }
124
+
125
+ function dependsOnTooltip(step) {
126
+ if (step.dependsOn && !step.completed) {
127
+ const dependsOnStep = steps.find((s) => s.name === step.dependsOn)
128
+ if (dependsOnStep && !dependsOnStep.completed) {
129
+ return `You need to complete "${dependsOnStep.title}" first.`
130
+ }
131
+ }
132
+ return ''
133
+ }
134
+
101
135
  const {
102
136
  steps,
103
137
  stepsCompleted,
@@ -1,6 +1,7 @@
1
1
  import call from '../../src/utils/call'
2
2
  import { createResource } from '../../src/resources'
3
- import { minimize } from '../Help/help'
3
+ import { minimize, showHelpModal } from '../Help/help'
4
+ import { sessionUser } from '../session'
4
5
  import { useStorage } from '@vueuse/core'
5
6
  import { computed, reactive } from 'vue'
6
7
 
@@ -8,13 +9,18 @@ const onboardings = reactive({})
8
9
  const onboardingStatus = useStorage('onboardingStatus', {})
9
10
 
10
11
  export function useOnboarding(appName) {
12
+ const user = sessionUser()
13
+
14
+ if (!user || user === 'Guest') return
15
+
11
16
  const isOnboardingStepsCompleted = useStorage(
12
- 'isOnboardingStepsCompleted' + appName,
17
+ 'isOnboardingStepsCompleted' + appName + user,
13
18
  false,
14
19
  )
15
20
 
16
21
  const onboardingSteps = computed(
17
- () => onboardingStatus.value?.[appName + '_onboarding_status'] || [],
22
+ () =>
23
+ onboardingStatus.value?.[user]?.[appName + '_onboarding_status'] || [],
18
24
  )
19
25
 
20
26
  if (!onboardingSteps.value.length && !isOnboardingStepsCompleted.value) {
@@ -23,7 +29,7 @@ export function useOnboarding(appName) {
23
29
  cache: 'onboarding_status',
24
30
  auto: true,
25
31
  onSuccess: (data) => {
26
- onboardingStatus.value = data
32
+ onboardingStatus.value[user] = data
27
33
  syncStatus()
28
34
  },
29
35
  })
@@ -63,11 +69,13 @@ export function useOnboarding(appName) {
63
69
  if (isOnboardingStepsCompleted.value) return
64
70
 
65
71
  if (!onboardingSteps.value.length) {
66
- onboardingStatus.value[appName + '_onboarding_status'] = onboardings[
67
- appName
68
- ].map((s) => {
69
- return { name: s.name, completed: false }
70
- })
72
+ if (!onboardingStatus.value[user]) {
73
+ onboardingStatus.value[user] = {}
74
+ }
75
+ onboardingStatus.value[user][appName + '_onboarding_status'] =
76
+ onboardings[appName].map((s) => {
77
+ return { name: s.name, completed: false }
78
+ })
71
79
  }
72
80
 
73
81
  let index = onboardingSteps.value.findIndex((s) => s.name === step)
@@ -87,11 +95,14 @@ export function useOnboarding(appName) {
87
95
  if (isOnboardingStepsCompleted.value && value) return
88
96
 
89
97
  if (!onboardingSteps.value.length) {
90
- onboardingStatus.value[appName + '_onboarding_status'] = onboardings[
91
- appName
92
- ].map((s) => {
93
- return { name: s.name, completed: value }
94
- })
98
+ if (!onboardingStatus.value[user]) {
99
+ onboardingStatus.value[user] = {}
100
+ }
101
+
102
+ onboardingStatus.value[user][appName + '_onboarding_status'] =
103
+ onboardings[appName].map((s) => {
104
+ return { name: s.name, completed: value }
105
+ })
95
106
  } else {
96
107
  onboardingSteps.value.forEach((step) => {
97
108
  step.completed = value
@@ -129,6 +140,8 @@ export function useOnboarding(appName) {
129
140
  }
130
141
 
131
142
  function setUp(steps) {
143
+ showHelpModal.value = !isOnboardingStepsCompleted.value
144
+
132
145
  if (onboardings[appName]) return
133
146
 
134
147
  onboardings[appName] = steps
@@ -0,0 +1,8 @@
1
+ export function sessionUser() {
2
+ let cookies = new URLSearchParams(document.cookie.split('; ').join('&'))
3
+ let _sessionUser = cookies.get('user_id')
4
+ if (_sessionUser === 'Guest') {
5
+ _sessionUser = null
6
+ }
7
+ return _sessionUser
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frappe-ui",
3
- "version": "0.1.143",
3
+ "version": "0.1.145",
4
4
  "description": "A set of components and utilities for rapid UI development",
5
5
  "main": "./src/index.ts",
6
6
  "type": "module",
@@ -12,7 +12,7 @@
12
12
  />
13
13
  <div
14
14
  v-else
15
- class="flex h-full w-full items-center justify-center bg-surface-gray-2 uppercase text-ink-gray-5"
15
+ class="flex h-full w-full items-center justify-center bg-surface-gray-2 uppercase text-ink-gray-5 select-none"
16
16
  :class="[labelClasses, shapeClasses]"
17
17
  >
18
18
  <div :class="iconClasses" v-if="$slots.default">
@@ -284,6 +284,8 @@ function getYAxisOptions(config: AxisChartConfig) {
284
284
  return formatValue(value, 1, true)
285
285
  },
286
286
  },
287
+ min: config.yAxis.yMin,
288
+ max: config.yAxis.yMax,
287
289
  }
288
290
 
289
291
  const secondaryYAxisOptions = {
@@ -324,6 +326,8 @@ function getYAxisOptions(config: AxisChartConfig) {
324
326
  },
325
327
  // color: '#000',
326
328
  },
329
+ min: config.y2Axis?.yMin,
330
+ max: config.y2Axis?.yMax,
327
331
  }
328
332
 
329
333
  return config.swapXY
@@ -8,14 +8,15 @@
8
8
  <TextInput
9
9
  readonly
10
10
  type="text"
11
- icon-left="calendar"
12
11
  :placeholder="placeholder"
13
12
  :value="dateValue && formatter ? formatter(dateValue) : dateValue"
14
13
  @focus="!readonly ? togglePopover() : null"
15
14
  class="w-full"
16
15
  :class="inputClass"
17
16
  v-bind="$attrs"
18
- />
17
+ >
18
+ <template #prefix><LucideCalendar class="size-4" /></template>
19
+ </TextInput>
19
20
  </template>
20
21
 
21
22
  <template #body="{ togglePopover }">
@@ -15,7 +15,9 @@
15
15
  class="w-full"
16
16
  :class="inputClass"
17
17
  v-bind="$attrs"
18
- />
18
+ >
19
+ <template #prefix><LucideCalendar class="size-4" /></template>
20
+ </TextInput>
19
21
  </template>
20
22
 
21
23
  <template #body="{ togglePopover }">
@@ -30,7 +30,7 @@ function getIcons() {
30
30
  let iconSvg = LucideIcons[icon]
31
31
 
32
32
  // set stroke-width to 1.5
33
- if (iconSvg && iconSvg.includes('stroke-width')) {
33
+ if (typeof iconSvg === 'string' && iconSvg.includes('stroke-width')) {
34
34
  iconSvg = iconSvg.replace(/stroke-width="2"/g, 'stroke-width="1.5"')
35
35
  }
36
36
  icons[icon] = iconSvg