@soubiran/ui 0.3.1 → 0.5.0
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/dist/components/Container.vue +36 -0
- package/dist/components/Feedback.vue +67 -0
- package/dist/components/FeedbackCard.vue +174 -0
- package/dist/components/Header.vue +135 -0
- package/dist/components/Page.vue +63 -0
- package/dist/components/PageHeader.vue +36 -0
- package/dist/components/PageTitle.vue +32 -0
- package/dist/components/Socials.vue +83 -0
- package/dist/components/Sponsors.vue +34 -0
- package/dist/components/TableOfContents.vue +74 -0
- package/dist/components/ViewersCounter.vue +75 -0
- package/dist/composables/useTableOfContents.d.ts +11 -0
- package/dist/composables/useTableOfContents.js +20 -0
- package/dist/composables/useUmami.d.ts +6 -0
- package/dist/composables/useUmami.js +14 -0
- package/dist/imports.mjs +1 -2
- package/dist/index.d.ts +3 -618
- package/dist/index.js +4 -876
- package/dist/resolver.mjs +3 -4
- package/dist/{styles.css → style.css} +51 -37
- package/dist/wrapper-classes.d.ts +4 -0
- package/dist/wrapper-classes.js +19 -0
- package/package.json +33 -23
- package/dist/styles.js +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
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>
|
|
@@ -0,0 +1,75 @@
|
|
|
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>
|
|
@@ -0,0 +1,11 @@
|
|
|
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 };
|
|
@@ -0,0 +1,20 @@
|
|
|
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 };
|
|
@@ -0,0 +1,14 @@
|
|
|
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 };
|
package/dist/imports.mjs
CHANGED