@soubiran/ui 0.9.2 → 0.10.1
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/README.md +9 -0
- package/dist/imports.mjs +5 -1
- package/dist/index.d.ts +716 -3
- package/dist/index.js +2717 -4
- package/dist/resolver.mjs +7 -6
- package/dist/style.css +6 -141
- package/dist/styles/animations.css +80 -0
- package/dist/styles/keyframes.css +23 -0
- package/dist/styles/shiki.css +17 -0
- package/package.json +16 -16
- package/dist/components/Container.vue +0 -36
- package/dist/components/Feedback.vue +0 -65
- package/dist/components/FeedbackCard.vue +0 -168
- package/dist/components/Header.vue +0 -138
- package/dist/components/Page.vue +0 -63
- package/dist/components/PageHeader.vue +0 -36
- package/dist/components/PageTitle.vue +0 -32
- package/dist/components/Socials.vue +0 -82
- package/dist/components/Sponsors.vue +0 -34
- package/dist/components/TableOfContents.vue +0 -74
- package/dist/components/ViewersCounter.vue +0 -75
- package/dist/composables/useTableOfContents.d.ts +0 -11
- package/dist/composables/useTableOfContents.js +0 -20
- package/dist/composables/useUmami.d.ts +0 -6
- package/dist/composables/useUmami.js +0 -14
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { FunctionalComponent, SVGAttributes } from 'vue'
|
|
3
|
-
import { tv } from 'tailwind-variants'
|
|
4
|
-
import { computed } from 'vue'
|
|
5
|
-
import discord from '~icons/simple-icons/discord'
|
|
6
|
-
import github from '~icons/simple-icons/github'
|
|
7
|
-
import linkedin from '~icons/simple-icons/linkedin'
|
|
8
|
-
import twitch from '~icons/simple-icons/twitch'
|
|
9
|
-
import x from '~icons/simple-icons/x'
|
|
10
|
-
import useUmami from '../composables/useUmami'
|
|
11
|
-
import Container from './Container.vue'
|
|
12
|
-
|
|
13
|
-
const header = tv({
|
|
14
|
-
slots: {
|
|
15
|
-
base: 'h-(--ui-header-height) flex flex-row gap-4 items-center justify-end',
|
|
16
|
-
link: 'p-0 text-dimmed',
|
|
17
|
-
},
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
export interface HeaderProps {
|
|
21
|
-
links: {
|
|
22
|
-
icon: FunctionalComponent<SVGAttributes>
|
|
23
|
-
label: string
|
|
24
|
-
to?: string
|
|
25
|
-
href?: string
|
|
26
|
-
target?: string
|
|
27
|
-
rel?: string
|
|
28
|
-
}[]
|
|
29
|
-
class?: any
|
|
30
|
-
ui?: Partial<typeof header.slots>
|
|
31
|
-
}
|
|
32
|
-
export interface HeaderEmits {}
|
|
33
|
-
export interface HeaderSlots {}
|
|
34
|
-
</script>
|
|
35
|
-
|
|
36
|
-
<script lang="ts" setup>
|
|
37
|
-
const props = defineProps<HeaderProps>()
|
|
38
|
-
defineEmits<HeaderEmits>()
|
|
39
|
-
defineSlots<HeaderSlots>()
|
|
40
|
-
|
|
41
|
-
const { track } = useUmami()
|
|
42
|
-
function trackClick(label: string) {
|
|
43
|
-
track('header_click', { label })
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const ui = computed(() => header())
|
|
47
|
-
</script>
|
|
48
|
-
|
|
49
|
-
<template>
|
|
50
|
-
<Container :ui="{ inner: 'max-w-5xl' }">
|
|
51
|
-
<header :class="ui.base({ class: [props.ui?.base, props.class] })">
|
|
52
|
-
<UTooltip
|
|
53
|
-
v-for="link of props.links"
|
|
54
|
-
:key="link.label"
|
|
55
|
-
:text="link.label"
|
|
56
|
-
>
|
|
57
|
-
<UButton
|
|
58
|
-
variant="link"
|
|
59
|
-
color="neutral"
|
|
60
|
-
:to="link.to"
|
|
61
|
-
:href="link.href"
|
|
62
|
-
:aria-label="link.label"
|
|
63
|
-
:icon="link.icon"
|
|
64
|
-
:target="link.target"
|
|
65
|
-
:rel="link.rel"
|
|
66
|
-
:class="ui.link({ class: props.ui?.link })"
|
|
67
|
-
@click="trackClick(link.label)"
|
|
68
|
-
/>
|
|
69
|
-
</UTooltip>
|
|
70
|
-
<USeparator orientation="vertical" class="h-5" />
|
|
71
|
-
<UTooltip text="LinkedIn">
|
|
72
|
-
<UButton
|
|
73
|
-
href="https://www.linkedin.com/in/esteban25/"
|
|
74
|
-
target="_blank"
|
|
75
|
-
variant="link"
|
|
76
|
-
color="neutral"
|
|
77
|
-
aria-label="LinkedIn"
|
|
78
|
-
:icon="linkedin"
|
|
79
|
-
:class="ui.link({ class: props.ui?.link })"
|
|
80
|
-
:ui="{ leadingIcon: 'size-4' }"
|
|
81
|
-
@click="trackClick('LinkedIn')"
|
|
82
|
-
/>
|
|
83
|
-
</UTooltip>
|
|
84
|
-
<UTooltip text="X">
|
|
85
|
-
<UButton
|
|
86
|
-
href="https://x.com/soubiran_"
|
|
87
|
-
target="_blank"
|
|
88
|
-
variant="link"
|
|
89
|
-
color="neutral"
|
|
90
|
-
aria-label="X"
|
|
91
|
-
:icon="x"
|
|
92
|
-
:class="ui.link({ class: props.ui?.link })"
|
|
93
|
-
:ui="{ leadingIcon: 'size-4' }"
|
|
94
|
-
@click="trackClick('X')"
|
|
95
|
-
/>
|
|
96
|
-
</UTooltip>
|
|
97
|
-
<UTooltip text="Twitch">
|
|
98
|
-
<UButton
|
|
99
|
-
href="https://www.twitch.tv/barbapapazes"
|
|
100
|
-
target="_blank"
|
|
101
|
-
variant="link"
|
|
102
|
-
color="neutral"
|
|
103
|
-
aria-label="Twitch"
|
|
104
|
-
:icon="twitch"
|
|
105
|
-
:class="ui.link({ class: props.ui?.link })"
|
|
106
|
-
:ui="{ leadingIcon: 'size-4' }"
|
|
107
|
-
@click="trackClick('Twitch')"
|
|
108
|
-
/>
|
|
109
|
-
</UTooltip>
|
|
110
|
-
<UTooltip text="GitHub">
|
|
111
|
-
<UButton
|
|
112
|
-
href="https://github.com/barbapapazes"
|
|
113
|
-
target="_blank"
|
|
114
|
-
variant="link"
|
|
115
|
-
color="neutral"
|
|
116
|
-
aria-label="GitHub"
|
|
117
|
-
:icon="github"
|
|
118
|
-
:class="ui.link({ class: props.ui?.link })"
|
|
119
|
-
:ui="{ leadingIcon: 'size-4' }"
|
|
120
|
-
@click="trackClick('GitHub')"
|
|
121
|
-
/>
|
|
122
|
-
</UTooltip>
|
|
123
|
-
<UTooltip text="Discord">
|
|
124
|
-
<UButton
|
|
125
|
-
href="https://discord.gg/q2ghCGUuFR"
|
|
126
|
-
target="_blank"
|
|
127
|
-
variant="link"
|
|
128
|
-
color="neutral"
|
|
129
|
-
aria-label="Discord"
|
|
130
|
-
:icon="discord"
|
|
131
|
-
:class="ui.link({ class: props.ui?.link })"
|
|
132
|
-
:ui="{ leadingIcon: 'size-4' }"
|
|
133
|
-
@click="trackClick('Discord')"
|
|
134
|
-
/>
|
|
135
|
-
</UTooltip>
|
|
136
|
-
</header>
|
|
137
|
-
</Container>
|
|
138
|
-
</template>
|
package/dist/components/Page.vue
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { tv } from 'tailwind-variants'
|
|
3
|
-
import { computed } from 'vue'
|
|
4
|
-
import Container from './Container.vue'
|
|
5
|
-
|
|
6
|
-
const page = tv({
|
|
7
|
-
slots: {
|
|
8
|
-
base: 'py-12',
|
|
9
|
-
header: 'max-w-3xl mx-auto xl:max-w-none xl:grid xl:grid-cols-[256px_768px_256px]',
|
|
10
|
-
headerInner: 'xl:col-start-2',
|
|
11
|
-
content: 'mt-6 max-w-3xl mx-auto xl:max-w-none xl:grid xl:grid-cols-[256px_768px_256px] xl:mx-auto',
|
|
12
|
-
contentInner: 'xl:col-start-2',
|
|
13
|
-
right: 'hidden xl:block xl:col-start-3 xl:pl-8 xl:h-full',
|
|
14
|
-
rightInner: 'sticky top-4',
|
|
15
|
-
},
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
export interface PageProps {
|
|
19
|
-
class?: any
|
|
20
|
-
ui?: Partial<typeof page.slots>
|
|
21
|
-
}
|
|
22
|
-
export interface PageEmits {}
|
|
23
|
-
export interface PageSlots {
|
|
24
|
-
default: (props: any) => any
|
|
25
|
-
header: (props: any) => any
|
|
26
|
-
right: (props: any) => any
|
|
27
|
-
bottom: (props: any) => any
|
|
28
|
-
}
|
|
29
|
-
</script>
|
|
30
|
-
|
|
31
|
-
<script lang="ts" setup>
|
|
32
|
-
const props = defineProps<PageProps>()
|
|
33
|
-
defineEmits<PageEmits>()
|
|
34
|
-
defineSlots<PageSlots>()
|
|
35
|
-
|
|
36
|
-
const ui = computed(() => page())
|
|
37
|
-
</script>
|
|
38
|
-
|
|
39
|
-
<template>
|
|
40
|
-
<div :class="ui.base({ class: [props.ui?.base, props.class] })">
|
|
41
|
-
<Container>
|
|
42
|
-
<div :class="ui.header({ class: props.ui?.header })">
|
|
43
|
-
<div :class="ui.headerInner({ class: props.ui?.headerInner })">
|
|
44
|
-
<slot name="header" />
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
47
|
-
|
|
48
|
-
<div :class="ui.content({ class: props.ui?.content })">
|
|
49
|
-
<div :class="ui.contentInner({ class: props.ui?.contentInner })">
|
|
50
|
-
<slot />
|
|
51
|
-
</div>
|
|
52
|
-
|
|
53
|
-
<div :class="ui.right({ class: props.ui?.right })">
|
|
54
|
-
<div :class="ui.rightInner({ class: props.ui?.rightInner })">
|
|
55
|
-
<slot name="right" />
|
|
56
|
-
</div>
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
59
|
-
</Container>
|
|
60
|
-
|
|
61
|
-
<slot name="bottom" />
|
|
62
|
-
</div>
|
|
63
|
-
</template>
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { tv } from 'tailwind-variants'
|
|
3
|
-
import { computed } from 'vue'
|
|
4
|
-
import PageTitle from './PageTitle.vue'
|
|
5
|
-
|
|
6
|
-
const pageHeader = tv({
|
|
7
|
-
slots: {
|
|
8
|
-
base: '',
|
|
9
|
-
},
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
export interface PageHeaderProps {
|
|
13
|
-
title: string
|
|
14
|
-
class?: any
|
|
15
|
-
ui?: Partial<typeof pageHeader.slots>
|
|
16
|
-
}
|
|
17
|
-
export interface PageHeaderEmits {}
|
|
18
|
-
export interface PageHeaderSlots {
|
|
19
|
-
after: (props: any) => any
|
|
20
|
-
}
|
|
21
|
-
</script>
|
|
22
|
-
|
|
23
|
-
<script lang="ts" setup>
|
|
24
|
-
const props = defineProps<PageHeaderProps>()
|
|
25
|
-
defineEmits<PageHeaderEmits>()
|
|
26
|
-
defineSlots<PageHeaderSlots>()
|
|
27
|
-
|
|
28
|
-
const ui = computed(() => pageHeader())
|
|
29
|
-
</script>
|
|
30
|
-
|
|
31
|
-
<template>
|
|
32
|
-
<div :class="ui.base({ class: [props.ui?.base, props.class] })">
|
|
33
|
-
<PageTitle :title="props.title" />
|
|
34
|
-
<slot name="after" />
|
|
35
|
-
</div>
|
|
36
|
-
</template>
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { tv } from 'tailwind-variants'
|
|
3
|
-
import { computed } from 'vue'
|
|
4
|
-
|
|
5
|
-
const pageTitle = tv({
|
|
6
|
-
slots: {
|
|
7
|
-
base: 'text-xl font-bold text-highlighted',
|
|
8
|
-
},
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
export interface PageTitleProps {
|
|
12
|
-
title: string
|
|
13
|
-
class?: any
|
|
14
|
-
ui?: Partial<typeof pageTitle.slots>
|
|
15
|
-
}
|
|
16
|
-
export interface PageTitleEmits {}
|
|
17
|
-
export interface PageTitleSlots {}
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
<script lang="ts" setup>
|
|
21
|
-
const props = defineProps<PageTitleProps>()
|
|
22
|
-
defineEmits<PageTitleEmits>()
|
|
23
|
-
defineSlots<PageTitleSlots>()
|
|
24
|
-
|
|
25
|
-
const ui = computed(() => pageTitle())
|
|
26
|
-
</script>
|
|
27
|
-
|
|
28
|
-
<template>
|
|
29
|
-
<h1 :class="ui.base({ class: [props.ui?.base, props.class] })">
|
|
30
|
-
{{ title }}
|
|
31
|
-
</h1>
|
|
32
|
-
</template>
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { tv } from 'tailwind-variants'
|
|
3
|
-
import { computed } from 'vue'
|
|
4
|
-
import github from '~icons/simple-icons/github'
|
|
5
|
-
import linkedin from '~icons/simple-icons/linkedin'
|
|
6
|
-
import twitch from '~icons/simple-icons/twitch'
|
|
7
|
-
import x from '~icons/simple-icons/x'
|
|
8
|
-
import youtube from '~icons/simple-icons/youtube'
|
|
9
|
-
|
|
10
|
-
const socials = tv({
|
|
11
|
-
slots: {
|
|
12
|
-
base: 'flex flex-wrap gap-2',
|
|
13
|
-
link: 'flex items-center gap-1',
|
|
14
|
-
icon: 'size-4',
|
|
15
|
-
},
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
export interface SocialsProps {
|
|
19
|
-
class?: any
|
|
20
|
-
ui?: Partial<typeof socials.slots>
|
|
21
|
-
}
|
|
22
|
-
export interface SocialsEmits {}
|
|
23
|
-
export interface SocialsSlots {}
|
|
24
|
-
</script>
|
|
25
|
-
|
|
26
|
-
<script lang="ts" setup>
|
|
27
|
-
const props = defineProps<SocialsProps>()
|
|
28
|
-
defineEmits<SocialsEmits>()
|
|
29
|
-
defineSlots<SocialsSlots>()
|
|
30
|
-
|
|
31
|
-
const ui = computed(() => socials())
|
|
32
|
-
</script>
|
|
33
|
-
|
|
34
|
-
<template>
|
|
35
|
-
<p :class="ui.base({ class: [props.ui?.base, props.class] })">
|
|
36
|
-
<a
|
|
37
|
-
href="https://www.linkedin.com/in/esteban25/"
|
|
38
|
-
rel="noopener noreferrer"
|
|
39
|
-
target="_blank"
|
|
40
|
-
:class="ui.link({ class: props.ui?.link })"
|
|
41
|
-
>
|
|
42
|
-
<UIcon :name="linkedin" :class="ui.icon({ class: props.ui?.icon })" />
|
|
43
|
-
<span>LinkedIn</span>
|
|
44
|
-
</a>
|
|
45
|
-
<a
|
|
46
|
-
href="https://x.com/soubiran_"
|
|
47
|
-
rel="noopener noreferrer"
|
|
48
|
-
target="_blank"
|
|
49
|
-
:class="ui.link({ class: props.ui?.link })"
|
|
50
|
-
>
|
|
51
|
-
<UIcon :name="x" :class="ui.icon({ class: props.ui?.icon })" />
|
|
52
|
-
<span>X (Twitter)</span>
|
|
53
|
-
</a>
|
|
54
|
-
<a
|
|
55
|
-
href="https://github.com/barbapapazes"
|
|
56
|
-
rel="noopener noreferrer"
|
|
57
|
-
target="_blank"
|
|
58
|
-
:class="ui.link({ class: props.ui?.link })"
|
|
59
|
-
>
|
|
60
|
-
<UIcon :name="github" :class="ui.icon({ class: props.ui?.icon })" />
|
|
61
|
-
<span>GitHub</span>
|
|
62
|
-
</a>
|
|
63
|
-
<a
|
|
64
|
-
href="https://www.twitch.tv/barbapapazes"
|
|
65
|
-
rel="noopener noreferrer"
|
|
66
|
-
target="_blank"
|
|
67
|
-
:class="ui.link({ class: props.ui?.link })"
|
|
68
|
-
>
|
|
69
|
-
<UIcon :name="twitch" :class="ui.icon({ class: props.ui?.icon })" />
|
|
70
|
-
<span>Twitch</span>
|
|
71
|
-
</a>
|
|
72
|
-
<a
|
|
73
|
-
href="https://www.youtube.com/@barbapapazes"
|
|
74
|
-
target="_blank"
|
|
75
|
-
rel="noopener noreferrer"
|
|
76
|
-
:class="ui.link({ class: props.ui?.link })"
|
|
77
|
-
>
|
|
78
|
-
<UIcon :name="youtube" :class="ui.icon({ class: props.ui?.icon })" />
|
|
79
|
-
<span>YouTube</span>
|
|
80
|
-
</a>
|
|
81
|
-
</p>
|
|
82
|
-
</template>
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { tv } from 'tailwind-variants'
|
|
3
|
-
import { computed } from 'vue'
|
|
4
|
-
|
|
5
|
-
const sponsors = tv({
|
|
6
|
-
slots: {
|
|
7
|
-
base: 'not-prose',
|
|
8
|
-
img: 'border-0',
|
|
9
|
-
},
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
export interface SponsorsProps {
|
|
13
|
-
class?: any
|
|
14
|
-
ui?: Partial<typeof sponsors.slots>
|
|
15
|
-
}
|
|
16
|
-
export interface SponsorsEmits {}
|
|
17
|
-
export interface SponsorsSlots {}
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
<script lang="ts" setup>
|
|
21
|
-
const props = defineProps<SponsorsProps>()
|
|
22
|
-
defineEmits<SponsorsEmits>()
|
|
23
|
-
defineSlots<SponsorsSlots>()
|
|
24
|
-
|
|
25
|
-
const ui = computed(() => sponsors())
|
|
26
|
-
</script>
|
|
27
|
-
|
|
28
|
-
<template>
|
|
29
|
-
<p :class="ui.base({ class: [props.ui?.base, props.class] })">
|
|
30
|
-
<a href="https://soubiran.dev/sponsorship?utm_source=infra.soubiran.dev&utm_medium=link" target="_blank">
|
|
31
|
-
<img src="https://raw.githubusercontent.com/Barbapapazes/static/refs/heads/main/sponsors.svg" alt="Sponsors" :class="ui.img({ class: props.ui?.img })">
|
|
32
|
-
</a>
|
|
33
|
-
</p>
|
|
34
|
-
</template>
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { tv } from 'tailwind-variants'
|
|
3
|
-
import { computed } from 'vue'
|
|
4
|
-
import useTableOfContents from '../composables/useTableOfContents'
|
|
5
|
-
import useUmami from '../composables/useUmami'
|
|
6
|
-
|
|
7
|
-
const tableOfContents = tv({
|
|
8
|
-
slots: {
|
|
9
|
-
base: 'space-y-1 text-sm text-dimmed font-medium',
|
|
10
|
-
title: '',
|
|
11
|
-
list: 'font-sofia',
|
|
12
|
-
link: 'flex gap-1 px-0 py-1 text-dimmed hover:text-default active:text-default transition-colors focus:outline-none focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-inverted data-active:text-default rounded-md',
|
|
13
|
-
},
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
export interface TableOfContentsItem {
|
|
17
|
-
level: number
|
|
18
|
-
anchor: string | null
|
|
19
|
-
text: string
|
|
20
|
-
children?: TableOfContentsItem[]
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface TableOfContentsProps {
|
|
24
|
-
toc: TableOfContentsItem[]
|
|
25
|
-
class?: any
|
|
26
|
-
ui?: Partial<typeof tableOfContents.slots>
|
|
27
|
-
}
|
|
28
|
-
export interface TableOfContentsEmits {}
|
|
29
|
-
export interface TableOfContentsSlots {}
|
|
30
|
-
</script>
|
|
31
|
-
|
|
32
|
-
<script lang="ts" setup>
|
|
33
|
-
const props = defineProps<TableOfContentsProps>()
|
|
34
|
-
defineEmits<TableOfContentsEmits>()
|
|
35
|
-
defineSlots<TableOfContentsSlots>()
|
|
36
|
-
|
|
37
|
-
const { track } = useUmami()
|
|
38
|
-
function trackClick(text: string, hash: string) {
|
|
39
|
-
track('table_of_contents_click', {
|
|
40
|
-
toc_text: text,
|
|
41
|
-
toc_hash: hash,
|
|
42
|
-
})
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const { activeHeadings } = useTableOfContents()
|
|
46
|
-
|
|
47
|
-
const ui = computed(() => tableOfContents())
|
|
48
|
-
</script>
|
|
49
|
-
|
|
50
|
-
<template>
|
|
51
|
-
<div :class="ui.base({ class: [props.ui?.base, props.class] })">
|
|
52
|
-
<div :class="ui.title({ class: props.ui?.title })">
|
|
53
|
-
Table of Contents
|
|
54
|
-
</div>
|
|
55
|
-
<ul :class="ui.list({ class: props.ui?.list })">
|
|
56
|
-
<li v-for="(item, index) in props.toc" :key="item.anchor || index">
|
|
57
|
-
<!-- Cannot use RouterLink as the anchor will be prefixed with the route path. -->
|
|
58
|
-
<a
|
|
59
|
-
v-if="item.anchor"
|
|
60
|
-
custom
|
|
61
|
-
variant="link"
|
|
62
|
-
color="neutral"
|
|
63
|
-
:href="`#${item.anchor}`"
|
|
64
|
-
:data-active="activeHeadings.includes(item.anchor || '') ? true : undefined"
|
|
65
|
-
:class="ui.link({ class: props.ui?.link })"
|
|
66
|
-
@click="trackClick(item.text, item.anchor)"
|
|
67
|
-
>
|
|
68
|
-
<span>{{ index + 1 }}.</span>
|
|
69
|
-
{{ item.text }}
|
|
70
|
-
</a>
|
|
71
|
-
</li>
|
|
72
|
-
</ul>
|
|
73
|
-
</div>
|
|
74
|
-
</template>
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import PartySocket from 'partysocket'
|
|
3
|
-
import { tv } from 'tailwind-variants'
|
|
4
|
-
import { computed, onMounted, ref } from 'vue'
|
|
5
|
-
|
|
6
|
-
const viewersCounter = tv({
|
|
7
|
-
slots: {
|
|
8
|
-
base: 'flex items-center justify-center gap-[0.375rem] border border-green-400 rounded-full px-[0.375rem] py-[0.125rem] text-xs text-muted font-light leading-3 dark:border-green-700',
|
|
9
|
-
dot: 'inline-block h-[0.375rem] w-[0.375rem] animate-[pulse_4s_cubic-bezier(0.4,_0,_0.6,_1)_infinite] rounded-full bg-green-400 ring ring-2 ring-green-200 dark:bg-green-700 dark:ring-green-500',
|
|
10
|
-
},
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
interface Data {
|
|
14
|
-
count: number
|
|
15
|
-
connections: { [key: string]: number }
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface ViewersCounterProps {
|
|
19
|
-
class?: any
|
|
20
|
-
ui?: Partial<typeof viewersCounter.slots>
|
|
21
|
-
}
|
|
22
|
-
export interface ViewersCounterEmits {}
|
|
23
|
-
export interface ViewersCounterSlots {}
|
|
24
|
-
</script>
|
|
25
|
-
|
|
26
|
-
<script lang="ts" setup>
|
|
27
|
-
const props = defineProps<ViewersCounterProps>()
|
|
28
|
-
defineEmits<ViewersCounterEmits>()
|
|
29
|
-
defineSlots<ViewersCounterSlots>()
|
|
30
|
-
|
|
31
|
-
const count = ref<number>(0)
|
|
32
|
-
const connections = ref<{ [key: string]: number }>({})
|
|
33
|
-
|
|
34
|
-
function connect() {
|
|
35
|
-
return new PartySocket({
|
|
36
|
-
host: import.meta.env.VITE_PARTYKIT_URL,
|
|
37
|
-
room: 'soubiran-dev',
|
|
38
|
-
})
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
onMounted(() => {
|
|
42
|
-
const ws = connect()
|
|
43
|
-
|
|
44
|
-
ws.addEventListener('message', (event) => {
|
|
45
|
-
const data = JSON.parse(event.data) as Data
|
|
46
|
-
|
|
47
|
-
count.value = data.count
|
|
48
|
-
connections.value = data.connections
|
|
49
|
-
})
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
const title = computed(() => {
|
|
53
|
-
return `${count.value} viewer${count.value > 1 ? 's' : ''} currently online (${Object.keys(connections.value)
|
|
54
|
-
.map(host => `${connections.value[host]} from ${host}`)
|
|
55
|
-
.join(', ')})`
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
const ui = computed(() => viewersCounter())
|
|
59
|
-
</script>
|
|
60
|
-
|
|
61
|
-
<template>
|
|
62
|
-
<Transition name="fade">
|
|
63
|
-
<div
|
|
64
|
-
v-if="count"
|
|
65
|
-
:title
|
|
66
|
-
:class="ui.base({ class: [props.class, props.ui?.base] })"
|
|
67
|
-
>
|
|
68
|
-
<span>{{ count }}</span>
|
|
69
|
-
<span
|
|
70
|
-
:class="ui.dot({ class: props.ui?.dot })"
|
|
71
|
-
aria-hidden="true"
|
|
72
|
-
/>
|
|
73
|
-
</div>
|
|
74
|
-
</Transition>
|
|
75
|
-
</template>
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import * as _$vue from "vue";
|
|
2
|
-
|
|
3
|
-
//#region src/composables/useTableOfContents.d.ts
|
|
4
|
-
declare function _useTableOfContents(): {
|
|
5
|
-
setActive: (id: string) => void;
|
|
6
|
-
unsetActive: (id: string) => void;
|
|
7
|
-
activeHeadings: Readonly<_$vue.Ref<readonly string[], readonly string[]>>;
|
|
8
|
-
};
|
|
9
|
-
declare const _default: typeof _useTableOfContents;
|
|
10
|
-
//#endregion
|
|
11
|
-
export { _default };
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { createSharedComposable } from "@vueuse/core";
|
|
2
|
-
import { readonly, ref } from "vue";
|
|
3
|
-
//#region src/composables/useTableOfContents.ts
|
|
4
|
-
function _useTableOfContents() {
|
|
5
|
-
const activeHeadings = ref([]);
|
|
6
|
-
function setActive(id) {
|
|
7
|
-
activeHeadings.value.push(id);
|
|
8
|
-
}
|
|
9
|
-
function unsetActive(id) {
|
|
10
|
-
activeHeadings.value = activeHeadings.value.filter((h) => h !== id);
|
|
11
|
-
}
|
|
12
|
-
return {
|
|
13
|
-
setActive,
|
|
14
|
-
unsetActive,
|
|
15
|
-
activeHeadings: readonly(activeHeadings)
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
var useTableOfContents_default = createSharedComposable(_useTableOfContents);
|
|
19
|
-
//#endregion
|
|
20
|
-
export { useTableOfContents_default as default };
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { useRoute } from "vue-router";
|
|
2
|
-
//#region src/composables/useUmami.ts
|
|
3
|
-
function useUmami() {
|
|
4
|
-
const route = useRoute();
|
|
5
|
-
function track(event, data) {
|
|
6
|
-
window.umami?.track(event, {
|
|
7
|
-
...data,
|
|
8
|
-
page_path: route.path
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
return { track };
|
|
12
|
-
}
|
|
13
|
-
//#endregion
|
|
14
|
-
export { useUmami as default };
|