@slidev/client 0.50.0 → 0.51.0-beta.2

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.
@@ -3,9 +3,9 @@ import { recomputeAllPoppers } from 'floating-vue'
3
3
  import { defineComponent, h, onMounted, onUnmounted, ref, TransitionGroup, watchEffect } from 'vue'
4
4
  import { CLASS_VCLICK_CURRENT, CLASS_VCLICK_DISPLAY_NONE, CLASS_VCLICK_PRIOR, CLASS_VCLICK_TARGET, CLICKS_MAX } from '../constants'
5
5
  import { useSlideContext } from '../context'
6
- import { skipTransition } from '../logic/hmr'
7
6
  import { resolveTransition } from '../logic/transition'
8
7
  import { makeId } from '../logic/utils'
8
+ import { hmrSkipTransition } from '../state'
9
9
 
10
10
  export default defineComponent({
11
11
  props: {
@@ -77,7 +77,7 @@ export default defineComponent({
77
77
 
78
78
  function onAfterLeave() {
79
79
  // Refer to SlidesShow.vue
80
- skipTransition.value = true
80
+ hmrSkipTransition.value = true
81
81
  recomputeAllPoppers()
82
82
  }
83
83
  const transitionProps = transition && {
@@ -107,7 +107,7 @@ export default defineComponent({
107
107
  }, slot?.()))
108
108
  }
109
109
  return transitionProps
110
- ? h(TransitionGroup, skipTransition.value ? {} : transitionProps, () => children)
110
+ ? h(TransitionGroup, hmrSkipTransition.value ? {} : transitionProps, () => children)
111
111
  : h(tag, children)
112
112
  }
113
113
  },
@@ -165,7 +165,7 @@ export function createFixedClicks(
165
165
  ): ClicksContext {
166
166
  const clicksStart = route?.meta.slide?.frontmatter.clicksStart ?? 0
167
167
  return createClicksContextBase(
168
- computed(() => Math.max(toValue(currentInit), clicksStart)),
168
+ ref(Math.max(toValue(currentInit), clicksStart)),
169
169
  clicksStart,
170
170
  route?.meta?.clicks,
171
171
  )
@@ -0,0 +1,35 @@
1
+ import type { Ref } from 'vue'
2
+ import { useEventListener } from '@vueuse/core'
3
+ import { computed } from 'vue'
4
+ import { hideCursorIdle } from '../state'
5
+
6
+ const TIMEOUT = 2000
7
+
8
+ export function useHideCursorIdle(
9
+ enabled: Ref<boolean>,
10
+ ) {
11
+ const shouldHide = computed(() => enabled.value && hideCursorIdle.value)
12
+
13
+ function hide() {
14
+ document.body.style.cursor = 'none'
15
+ }
16
+ function show() {
17
+ document.body.style.cursor = ''
18
+ }
19
+
20
+ let timer: ReturnType<typeof setTimeout> | null = null
21
+
22
+ useEventListener(
23
+ document.body,
24
+ ['pointermove', 'pointerdown'],
25
+ () => {
26
+ show()
27
+ if (!shouldHide.value)
28
+ return
29
+ if (timer)
30
+ clearTimeout(timer)
31
+ timer = setTimeout(hide, TIMEOUT)
32
+ },
33
+ { passive: true },
34
+ )
35
+ }
@@ -9,10 +9,10 @@ import { computed, ref, watch } from 'vue'
9
9
  import { useRoute, useRouter } from 'vue-router'
10
10
  import { CLICKS_MAX } from '../constants'
11
11
  import { configs } from '../env'
12
- import { skipTransition } from '../logic/hmr'
13
12
  import { useRouteQuery } from '../logic/route'
14
13
  import { getSlide, getSlidePath } from '../logic/slides'
15
14
  import { getCurrentTransition } from '../logic/transition'
15
+ import { hmrSkipTransition } from '../state'
16
16
  import { createClicksContextBase } from './useClicks'
17
17
  import { useTocTree } from './useTocTree'
18
18
 
@@ -184,7 +184,7 @@ export function useNavBase(
184
184
  }
185
185
 
186
186
  async function go(no: number | string, clicks: number = 0, force = false) {
187
- skipTransition.value = false
187
+ hmrSkipTransition.value = false
188
188
  const pageChanged = currentSlideNo.value !== no
189
189
  const clicksChanged = clicks !== queryClicks.value
190
190
  const meta = getSlide(no)?.meta
@@ -304,7 +304,7 @@ const useNavState = createSharedComposable((): SlidevContextNavState => {
304
304
  return v
305
305
  },
306
306
  set(v) {
307
- skipTransition.value = false
307
+ hmrSkipTransition.value = false
308
308
  queryClicksRaw.value = v.toString()
309
309
  },
310
310
  })
@@ -13,7 +13,7 @@ export function useTimer() {
13
13
 
14
14
  return {
15
15
  timer,
16
- isTimerAvctive: isActive,
16
+ isTimerActive: isActive,
17
17
  resetTimer: reset,
18
18
  toggleTimer: () => (isActive.value ? pause() : resume()),
19
19
  }
@@ -5,10 +5,14 @@ import { wakeLockEnabled } from '../state'
5
5
  export function useWakeLock() {
6
6
  const { request, release } = useVueUseWakeLock()
7
7
 
8
- watch(wakeLockEnabled, (enabled) => {
9
- if (enabled)
10
- request('screen')
11
- else
12
- release()
13
- }, { immediate: true })
8
+ watch(
9
+ wakeLockEnabled,
10
+ (enabled) => {
11
+ if (enabled)
12
+ request('screen')
13
+ else
14
+ release()
15
+ },
16
+ { immediate: true },
17
+ )
14
18
  }
package/constants.ts CHANGED
@@ -83,5 +83,4 @@ export const HEADMATTER_FIELDS = [
83
83
  'mdc',
84
84
  'contextMenu',
85
85
  'wakeLock',
86
- 'overviewSnapshots',
87
86
  ]
@@ -0,0 +1,48 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import {
4
+ getHashColorFromString,
5
+ getHsla,
6
+ } from '../logic/color'
7
+
8
+ const props = withDefaults(
9
+ defineProps<{
10
+ text?: string
11
+ color?: boolean | number
12
+ as?: string
13
+ size?: string
14
+ }>(),
15
+ {
16
+ color: true,
17
+ },
18
+ )
19
+
20
+ const style = computed(() => {
21
+ if (!props.text || props.color === false)
22
+ return {}
23
+ return {
24
+ color: typeof props.color === 'number'
25
+ ? getHsla(props.color)
26
+ : getHashColorFromString(props.text),
27
+ background: typeof props.color === 'number'
28
+ ? getHsla(props.color, 0.1)
29
+ : getHashColorFromString(props.text, 0.1),
30
+ }
31
+ })
32
+
33
+ const sizeClasses = computed(() => {
34
+ switch (props.size || 'sm') {
35
+ case 'sm':
36
+ return 'px-1.5 text-11px leading-1.6em'
37
+ }
38
+ return ''
39
+ })
40
+ </script>
41
+
42
+ <template>
43
+ <component :is="as || 'span'" ws-nowrap rounded :class="sizeClasses" :style>
44
+ <slot>
45
+ <span v-text="props.text" />
46
+ </slot>
47
+ </component>
48
+ </template>
@@ -43,13 +43,23 @@ ensureDevicesListPermissions()
43
43
  </script>
44
44
 
45
45
  <template>
46
- <div class="text-sm">
47
- <SelectList v-model="currentCamera" title="Camera" :items="camerasItems" />
48
- <SelectList v-model="currentMic" title="Microphone" :items="microphonesItems" />
46
+ <div text-sm flex="~ col gap-2">
47
+ <SelectList
48
+ v-model="currentCamera"
49
+ title="Camera"
50
+ :items="camerasItems"
51
+ />
52
+ <div class="h-1px opacity-10 bg-current w-full" />
53
+ <SelectList
54
+ v-model="currentMic"
55
+ title="Microphone"
56
+ :items="microphonesItems"
57
+ />
58
+ <div class="h-1px opacity-10 bg-current w-full" />
49
59
  <SelectList
50
60
  v-if="mimeTypeItems.length"
51
61
  v-model="mimeType"
52
- title="mimeType"
62
+ title="Video Format"
53
63
  :items="mimeTypeItems"
54
64
  />
55
65
  </div>
@@ -6,6 +6,7 @@ defineProps<{
6
6
  nested?: boolean | number
7
7
  div?: boolean
8
8
  description?: string
9
+ dot?: boolean
9
10
  }>()
10
11
 
11
12
  const emit = defineEmits<{
@@ -19,17 +20,19 @@ function reset() {
19
20
 
20
21
  <template>
21
22
  <component :is="div ? 'div' : 'label'" flex="~ row gap-2 items-center" select-none>
22
- <div w-30 h-10 flex="~ gap-1 items-center">
23
+ <div w-30 h-8 flex="~ gap-1 items-center">
23
24
  <div
24
25
  v-if="nested" i-ri-corner-down-right-line op40
25
26
  :style="typeof nested === 'number' ? { marginLeft: `${nested * 0.5 + 0.5}rem` } : { marginLeft: '0.25rem' }"
26
27
  />
27
- <div v-if="!description" op75 @dblclick="reset">
28
+ <div v-if="!description" op75 relative @dblclick="reset">
28
29
  {{ title }}
30
+ <div v-if="dot" w-1.5 h-1.5 bg-primary rounded absolute top-0 right--2 />
29
31
  </div>
30
32
  <Tooltip v-else distance="10">
31
- <div op75 text-right @dblclick="reset">
33
+ <div op75 text-right relative @dblclick="reset">
32
34
  {{ title }}
35
+ <div v-if="dot" w-1.5 h-1.5 bg-primary rounded absolute top-0 right--2 />
33
36
  </div>
34
37
  <template #popper>
35
38
  <div text-sm min-w-90 v-html="description" />
@@ -0,0 +1,68 @@
1
+ <script setup lang="ts">
2
+ const props = defineProps<{
3
+ max: number
4
+ min: number
5
+ step: number
6
+ unit?: string
7
+ default?: number
8
+ }>()
9
+
10
+ const value = defineModel<number>('modelValue', {
11
+ type: Number,
12
+ })
13
+ </script>
14
+
15
+ <template>
16
+ <div relative h-22px w-60 flex-auto @dblclick="props.default !== undefined ? value = props.default : null">
17
+ <input
18
+ v-model.number="value" type="range" class="slider"
19
+ v-bind="props"
20
+ absolute bottom-0 left-0 right-0 top-0 z-10 w-full align-top
21
+ >
22
+ <span
23
+ v-if="props.default != null"
24
+ border="r main" absolute bottom-0 top-0 h-full w-1px op75
25
+ :style="{
26
+ left: `${(props.default - min) / (max - min) * 100}%`,
27
+ }"
28
+ />
29
+ </div>
30
+ <div relative h-22px>
31
+ <input v-model.number="value" type="number" v-bind="props" border="~ base rounded" m0 w-20 bg-gray:5 pl2 align-top text-sm>
32
+ <span v-if="props.unit" pointer-events-none absolute right-1 top-0.5 text-xs op25>{{ props.unit }}</span>
33
+ </div>
34
+ </template>
35
+
36
+ <style>
37
+ .slider {
38
+ appearance: none;
39
+ height: 22px;
40
+ outline: none;
41
+ opacity: 0.7;
42
+ -webkit-transition: 0.2s;
43
+ transition: opacity 0.2s;
44
+ --uno: border border-main rounded of-hidden bg-gray/5;
45
+ }
46
+
47
+ .slider:hover {
48
+ opacity: 1;
49
+ }
50
+
51
+ .slider::-webkit-slider-thumb {
52
+ -webkit-appearance: none;
53
+ appearance: none;
54
+ width: 5px;
55
+ height: 22px;
56
+ background: var(--slidev-theme-primary);
57
+ cursor: pointer;
58
+ z-index: 10;
59
+ }
60
+
61
+ .slider::-moz-range-thumb {
62
+ width: 5px;
63
+ height: 22px;
64
+ background: var(--slidev-theme-primary);
65
+ cursor: pointer;
66
+ z-index: 10;
67
+ }
68
+ </style>
@@ -30,8 +30,8 @@ onClickOutside(el, () => {
30
30
  <KeepAlive>
31
31
  <div
32
32
  v-if="value"
33
- class="rounded-md bg-main text-main shadow-xl absolute bottom-10 left-0 z-menu"
34
- dark:border="~ main"
33
+ class="bg-main text-main shadow-xl absolute bottom-10 left-0 z-menu py2"
34
+ border="~ main rounded-md"
35
35
  >
36
36
  <slot name="menu" />
37
37
  </div>
@@ -5,11 +5,12 @@ import { useDrawings } from '../composables/useDrawings'
5
5
  import { useNav } from '../composables/useNav'
6
6
  import { configs } from '../env'
7
7
  import { isColorSchemaConfigured, isDark, toggleDark } from '../logic/dark'
8
- import { activeElement, breakpoints, fullscreen, presenterLayout, showEditor, showInfoDialog, showPresenterCursor, toggleOverview, togglePresenterLayout } from '../state'
8
+ import { activeElement, breakpoints, fullscreen, hasViewerCssFilter, presenterLayout, showEditor, showInfoDialog, showPresenterCursor, toggleOverview, togglePresenterLayout } from '../state'
9
9
  import { downloadPDF } from '../utils'
10
10
  import IconButton from './IconButton.vue'
11
11
  import MenuButton from './MenuButton.vue'
12
12
  import Settings from './Settings.vue'
13
+ import SyncControls from './SyncControls.vue'
13
14
 
14
15
  import VerticalDivider from './VerticalDivider.vue'
15
16
 
@@ -48,7 +49,7 @@ function onMouseLeave() {
48
49
 
49
50
  const barStyle = computed(() => props.persist
50
51
  ? 'text-$slidev-controls-foreground bg-transparent'
51
- : 'rounded-md bg-main shadow-xl dark:border dark:border-main')
52
+ : 'rounded-md bg-main shadow-xl border border-main')
52
53
 
53
54
  const RecordingControls = shallowRef<any>()
54
55
  if (__SLIDEV_FEATURE_RECORD__)
@@ -130,19 +131,15 @@ if (__SLIDEV_FEATURE_RECORD__)
130
131
  >
131
132
  <div class="i-carbon:text-annotation-toggle" />
132
133
  </IconButton>
133
-
134
- <IconButton v-if="isPresenter" title="Toggle Presenter Layout" class="aspect-ratio-initial flex items-center" @click="togglePresenterLayout">
135
- <div class="i-carbon:template" />
136
- {{ presenterLayout }}
137
- </IconButton>
138
134
  </template>
135
+
139
136
  <template v-if="!__DEV__">
140
137
  <IconButton v-if="configs.download" title="Download as PDF" @click="downloadPDF">
141
138
  <div class="i-carbon:download" />
142
139
  </IconButton>
143
140
  </template>
144
141
 
145
- <template v-if="__SLIDEV_FEATURE_BROWSER_EXPORTER__">
142
+ <template v-if="__SLIDEV_FEATURE_BROWSER_EXPORTER__ && !isEmbedded && !isPresenter">
146
143
  <IconButton title="Browser Exporter" to="/export">
147
144
  <div class="i-carbon:document-pdf" />
148
145
  </IconButton>
@@ -156,11 +153,21 @@ if (__SLIDEV_FEATURE_RECORD__)
156
153
  <div class="i-carbon:information" />
157
154
  </IconButton>
158
155
 
159
- <template v-if="!isPresenter && !isEmbedded">
156
+ <template v-if="!isEmbedded">
157
+ <VerticalDivider />
158
+
159
+ <IconButton v-if="isPresenter" title="Toggle Presenter Layout" class="aspect-ratio-initial flex items-center" @click="togglePresenterLayout">
160
+ <div class="i-carbon:template" />
161
+ {{ presenterLayout }}
162
+ </IconButton>
163
+
164
+ <SyncControls v-if="__SLIDEV_FEATURE_PRESENTER__" />
165
+
160
166
  <MenuButton>
161
167
  <template #button>
162
168
  <IconButton title="More Options">
163
169
  <div class="i-carbon:settings-adjust" />
170
+ <div v-if="hasViewerCssFilter" w-2 h-2 bg-primary rounded-full absolute top-0.5 right-0.5 />
164
171
  </IconButton>
165
172
  </template>
166
173
  <template #menu>
@@ -4,15 +4,18 @@ import { computed, ref, watchEffect } from 'vue'
4
4
  import { createFixedClicks } from '../composables/useClicks'
5
5
  import { useNav } from '../composables/useNav'
6
6
  import { CLICKS_MAX } from '../constants'
7
- import { configs, pathPrefix } from '../env'
7
+ import { pathPrefix } from '../env'
8
8
  import { currentOverviewPage, overviewRowCount } from '../logic/overview'
9
+ import { isScreenshotSupported } from '../logic/screenshot'
10
+ import { snapshotManager } from '../logic/snapshot'
9
11
  import { breakpoints, showOverview, windowSize } from '../state'
10
12
  import DrawingPreview from './DrawingPreview.vue'
11
13
  import IconButton from './IconButton.vue'
12
14
  import SlideContainer from './SlideContainer.vue'
13
15
  import SlideWrapper from './SlideWrapper.vue'
14
16
 
15
- const { currentSlideNo, go: goSlide, slides } = useNav()
17
+ const nav = useNav()
18
+ const { currentSlideNo, go: goSlide, slides } = nav
16
19
 
17
20
  function close() {
18
21
  showOverview.value = false
@@ -48,6 +51,12 @@ const rowCount = computed(() => {
48
51
 
49
52
  const keyboardBuffer = ref<string>('')
50
53
 
54
+ async function captureSlidesOverview() {
55
+ showOverview.value = false
56
+ await snapshotManager.startCapturing(nav)
57
+ showOverview.value = true
58
+ }
59
+
51
60
  useEventListener('keypress', (e) => {
52
61
  if (!showOverview.value) {
53
62
  keyboardBuffer.value = ''
@@ -129,7 +138,7 @@ watchEffect(() => {
129
138
  <SlideContainer
130
139
  :key="route.no"
131
140
  :no="route.no"
132
- :use-snapshot="configs.overviewSnapshots"
141
+ :use-snapshot="true"
133
142
  :width="cardWidth"
134
143
  class="pointer-events-none"
135
144
  >
@@ -157,7 +166,10 @@ watchEffect(() => {
157
166
  </div>
158
167
  </div>
159
168
  </Transition>
160
- <div v-if="showOverview" class="fixed top-4 right-4 z-modal text-gray-400 flex flex-col items-center gap-2">
169
+ <div
170
+ v-show="showOverview"
171
+ class="fixed top-4 right-4 z-modal text-gray-400 flex flex-col items-center gap-2"
172
+ >
161
173
  <IconButton title="Close" class="text-2xl" @click="close">
162
174
  <div class="i-carbon:close" />
163
175
  </IconButton>
@@ -172,5 +184,13 @@ watchEffect(() => {
172
184
  >
173
185
  <div class="i-carbon:list-boxes" />
174
186
  </IconButton>
187
+ <IconButton
188
+ v-if="__DEV__ && isScreenshotSupported"
189
+ title="Capture slides as images"
190
+ class="text-2xl"
191
+ @click="captureSlidesOverview"
192
+ >
193
+ <div class="i-carbon:drop-photo" />
194
+ </IconButton>
175
195
  </div>
176
196
  </template>
@@ -3,7 +3,7 @@ import { useLocalStorage } from '@vueuse/core'
3
3
  import { onMounted, watch } from 'vue'
4
4
  import { recorder } from '../logic/recording'
5
5
  import { currentCamera, showRecordingDialog } from '../state'
6
- import DevicesList from './DevicesList.vue'
6
+ import DevicesSelectors from './DevicesSelectors.vue'
7
7
  import IconButton from './IconButton.vue'
8
8
  import MenuButton from './MenuButton.vue'
9
9
 
@@ -59,7 +59,7 @@ onMounted(() => {
59
59
  </IconButton>
60
60
  </template>
61
61
  <template #menu>
62
- <DevicesList />
62
+ <DevicesSelectors />
63
63
  </template>
64
64
  </MenuButton>
65
65
  </template>
@@ -2,7 +2,7 @@
2
2
  import { useVModel } from '@vueuse/core'
3
3
  import { nextTick } from 'vue'
4
4
  import { getFilename, mimeType, recordCamera, recorder, recordingName } from '../logic/recording'
5
- import DevicesList from './DevicesList.vue'
5
+ import DevicesSelectors from './DevicesSelectors.vue'
6
6
  import Modal from './Modal.vue'
7
7
 
8
8
  const props = defineProps({
@@ -72,14 +72,14 @@ async function start() {
72
72
  </div>
73
73
  </div>
74
74
  </div>
75
- <DevicesList />
75
+ <DevicesSelectors />
76
76
  </div>
77
77
  <div class="flex my-1">
78
- <button class="cancel" @click="close">
78
+ <button class="slidev-form-button" @click="close">
79
79
  Cancel
80
80
  </button>
81
81
  <div class="flex-auto" />
82
- <button @click="start">
82
+ <button class="slidev-form-button primary" @click="start">
83
83
  Start
84
84
  </button>
85
85
  </div>
@@ -111,15 +111,5 @@ async function start() {
111
111
  input[type='text'] {
112
112
  @apply border border-main rounded px-2 py-1;
113
113
  }
114
-
115
- button {
116
- @apply bg-orange-400 text-white px-4 py-1 rounded border-b-2 border-orange-600;
117
- @apply hover:(bg-orange-500 border-orange-700);
118
- }
119
-
120
- button.cancel {
121
- @apply bg-gray-400 bg-opacity-50 text-white px-4 py-1 rounded border-b-2 border-main;
122
- @apply hover:(bg-opacity-75 border-opacity-75);
123
- }
124
114
  }
125
115
  </style>
@@ -0,0 +1,45 @@
1
+ <script setup lang="ts">
2
+ import { shallowRef, useTemplateRef } from 'vue'
3
+
4
+ const video = useTemplateRef('video')
5
+ const stream = shallowRef<MediaStream | null>(null)
6
+ const started = shallowRef(false)
7
+
8
+ async function startCapture() {
9
+ stream.value = await navigator.mediaDevices.getDisplayMedia({
10
+ video: {
11
+ // @ts-expect-error missing types
12
+ cursor: 'always',
13
+ },
14
+ audio: false,
15
+ selfBrowserSurface: 'include',
16
+ preferCurrentTab: false,
17
+ })
18
+ video.value!.srcObject = stream.value
19
+ video.value!.play()
20
+ started.value = true
21
+ stream.value.addEventListener('inactive', () => {
22
+ video.value!.srcObject = null
23
+ started.value = false
24
+ })
25
+ stream.value.addEventListener('ended', () => {
26
+ video.value!.srcObject = null
27
+ started.value = false
28
+ })
29
+ }
30
+ </script>
31
+
32
+ <template>
33
+ <div h-full w-full>
34
+ <video v-show="started" ref="video" class="w-full h-full object-contain" />
35
+ <div v-if="!started" w-full h-full flex="~ col gap-4 items-center justify-center">
36
+ <div op50>
37
+ Use screen capturing to mirror your main screen back to presenter view.<br>
38
+ Click the button below and <b>select your other monitor or window</b>.
39
+ </div>
40
+ <button class="slidev-form-button" @click="startCapture">
41
+ Start Screen Mirroring
42
+ </button>
43
+ </div>
44
+ </div>
45
+ </template>
@@ -0,0 +1,29 @@
1
+ <script setup lang="ts">
2
+ import Badge from './Badge.vue'
3
+
4
+ defineProps<{
5
+ options: { label: string, value: any }[]
6
+ modelValue: any
7
+ }>()
8
+
9
+ defineEmits<{
10
+ (event: 'update:modelValue', newValue: any): void
11
+ }>()
12
+ </script>
13
+
14
+ <template>
15
+ <div flex="~ gap-1 items-center" rounded bg-gray:4 p1 m--1>
16
+ <Badge
17
+ v-for="option in options"
18
+ :key="option.value"
19
+ class="px-2 py-1 text-xs font-mono"
20
+ :class="option.value === modelValue ? '' : 'op50'"
21
+ :color="option.value === modelValue"
22
+ :aria-pressed="option.value === modelValue"
23
+ size="none"
24
+ :text="option.label"
25
+ as="button"
26
+ @click="$emit('update:modelValue', option.value)"
27
+ />
28
+ </div>
29
+ </template>
@@ -44,19 +44,11 @@ const value = useVModel(props, 'modelValue', emit, { passive: true })
44
44
  </template>
45
45
 
46
46
  <style lang="postcss" scoped>
47
- .select-list {
48
- @apply my-2;
49
- }
50
-
51
47
  .item {
52
48
  @apply flex rounded whitespace-nowrap py-1 gap-1 px-2 cursor-default hover:bg-gray-400 hover:bg-opacity-10;
53
-
54
- svg {
55
- @apply mr-1 -ml-2 my-auto;
56
- }
57
49
  }
58
50
 
59
51
  .title {
60
- @apply text-xs uppercase opacity-50 tracking-widest px-7 py-1 select-none text-nowrap;
52
+ @apply text-sm op75 px3 py1 select-none text-nowrap font-bold;
61
53
  }
62
54
  </style>