rimelight-components 1.1.2 → 1.1.4

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.
@@ -0,0 +1,149 @@
1
+ <script setup>
2
+ import { getLocalTimeZone, CalendarDate, today } from "@internationalized/date";
3
+ import { formatDateRange } from "little-date";
4
+ const { dateRange, setDateRange, setPresetRange } = useDateRange();
5
+ const formattedDateRange = computed(() => {
6
+ if (dateRange.value.start && dateRange.value.end) {
7
+ return formatDateRange(dateRange.value.start, dateRange.value.end, {
8
+ includeTime: false
9
+ });
10
+ }
11
+ return null;
12
+ });
13
+ const ranges = [
14
+ {
15
+ label: `Last 7 days`,
16
+ preset: `week`
17
+ },
18
+ {
19
+ label: `Last 30 days`,
20
+ preset: `month`
21
+ },
22
+ {
23
+ label: `Last 3 months`,
24
+ preset: `3months`
25
+ },
26
+ {
27
+ label: `Last 6 months`,
28
+ preset: `6months`
29
+ },
30
+ {
31
+ label: `Last year`,
32
+ preset: `year`
33
+ }
34
+ ];
35
+ const toCalendarDate = (date) => {
36
+ return new CalendarDate(
37
+ date.getFullYear(),
38
+ date.getMonth() + 1,
39
+ date.getDate()
40
+ );
41
+ };
42
+ const calendarRange = computed({
43
+ get: () => ({
44
+ start: dateRange.value.start ? toCalendarDate(dateRange.value.start) : void 0,
45
+ end: dateRange.value.end ? toCalendarDate(dateRange.value.end) : void 0
46
+ }),
47
+ set: (newValue) => {
48
+ if (newValue.start && newValue.end) {
49
+ setDateRange({
50
+ start: newValue.start.toDate(getLocalTimeZone()),
51
+ end: newValue.end.toDate(getLocalTimeZone())
52
+ });
53
+ }
54
+ }
55
+ });
56
+ const isRangeSelected = (preset) => {
57
+ if (!dateRange.value.start || !dateRange.value.end) return false;
58
+ const currentDate = today(getLocalTimeZone());
59
+ let startDate = currentDate.copy();
60
+ switch (preset) {
61
+ case `week`:
62
+ startDate = startDate.subtract({
63
+ days: 7
64
+ });
65
+ break;
66
+ case `month`:
67
+ startDate = startDate.subtract({
68
+ days: 30
69
+ });
70
+ break;
71
+ case `3months`:
72
+ startDate = startDate.subtract({
73
+ months: 3
74
+ });
75
+ break;
76
+ case `6months`:
77
+ startDate = startDate.subtract({
78
+ months: 6
79
+ });
80
+ break;
81
+ case `year`:
82
+ startDate = startDate.subtract({
83
+ years: 1
84
+ });
85
+ break;
86
+ }
87
+ const selectedStart = toCalendarDate(dateRange.value.start);
88
+ const selectedEnd = toCalendarDate(dateRange.value.end);
89
+ return Math.abs(
90
+ selectedStart.toDate(getLocalTimeZone()).getTime() - startDate.toDate(getLocalTimeZone()).getTime()
91
+ ) < 24 * 60 * 60 * 1e3 && Math.abs(
92
+ selectedEnd.toDate(getLocalTimeZone()).getTime() - currentDate.toDate(getLocalTimeZone()).getTime()
93
+ ) < 24 * 60 * 60 * 1e3;
94
+ };
95
+ </script>
96
+
97
+ <template>
98
+ <div class="mb-4 flex w-full items-center justify-center">
99
+ <UPopover :content="{ align: 'center' }" :modal="true">
100
+ <UButton
101
+ color="neutral"
102
+ variant="outline"
103
+ icon="i-lucide-calendar"
104
+ class="group min-w-fit data-[state=open]:bg-elevated"
105
+ >
106
+ <span class="truncate">
107
+ <template v-if="formattedDateRange">
108
+ {{ formattedDateRange }}
109
+ </template>
110
+ <template v-else> Pick a date range </template>
111
+ </span>
112
+
113
+ <template #trailing>
114
+ <UIcon
115
+ name="i-lucide-chevron-down"
116
+ class="size-5 shrink-0 text-dimmed transition-transform duration-200 group-data-[state=open]:rotate-180"
117
+ />
118
+ </template>
119
+ </UButton>
120
+
121
+ <template #content>
122
+ <div class="flex items-stretch divide-default sm:divide-x">
123
+ <div class="hidden min-w-[140px] flex-col justify-center sm:flex">
124
+ <UButton
125
+ v-for="(range, index) in ranges"
126
+ :key="index"
127
+ :label="range.label"
128
+ color="neutral"
129
+ variant="ghost"
130
+ class="justify-start rounded-none px-4"
131
+ :class="[
132
+ isRangeSelected(range.preset) ? 'bg-elevated' : 'hover:bg-elevated/50'
133
+ ]"
134
+ truncate
135
+ @click="setPresetRange(range.preset)"
136
+ />
137
+ </div>
138
+
139
+ <UCalendar
140
+ v-model="calendarRange"
141
+ class="p-2"
142
+ :number-of-months="2"
143
+ range
144
+ />
145
+ </div>
146
+ </template>
147
+ </UPopover>
148
+ </div>
149
+ </template>
@@ -0,0 +1,3 @@
1
+ declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;
@@ -0,0 +1,10 @@
1
+ type __VLS_Props = {
2
+ feedback: FeedbackItem;
3
+ };
4
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
5
+ delete: (id: number) => any;
6
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
7
+ onDelete?: ((id: number) => any) | undefined;
8
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
+ declare const _default: typeof __VLS_export;
10
+ export default _default;
@@ -0,0 +1,77 @@
1
+ <script setup>
2
+ const {} = defineProps({
3
+ feedback: { type: null, required: true }
4
+ });
5
+ const emit = defineEmits([]);
6
+ const { getRatingFromFeedback, getScoreColor } = useFeedbackRatings();
7
+ const rating = computed(() => getRatingFromFeedback(props.feedback));
8
+ const isDeleting = ref(false);
9
+ async function handleDelete() {
10
+ if (!confirm(`Are you sure you want to delete this feedback?`)) {
11
+ return;
12
+ }
13
+ isDeleting.value = true;
14
+ try {
15
+ emit(`delete`, props.feedback.id);
16
+ } finally {
17
+ isDeleting.value = false;
18
+ }
19
+ }
20
+ </script>
21
+
22
+ <template>
23
+ <div class="rounded-lg border border-default p-4">
24
+ <div class="mb-3 flex items-start justify-between">
25
+ <div class="flex items-center gap-3">
26
+ <div class="flex flex-col items-center">
27
+ <span class="text-2xl">{{ rating.emoji }}</span>
28
+ <span class="text-xs font-bold" :class="getScoreColor(rating.score)">
29
+ {{ rating.score }}/4
30
+ </span>
31
+ </div>
32
+ <div>
33
+ <div class="mb-1 flex items-center gap-2">
34
+ <span class="text-sm font-medium">{{ rating.label }}</span>
35
+ </div>
36
+ <div class="flex items-center gap-3 text-xs text-muted">
37
+ <span class="flex items-center gap-1">
38
+ <UIcon name="i-lucide-calendar" class="size-3" />
39
+ {{
40
+ new Date(feedback.updatedAt).toLocaleDateString("en-US", {
41
+ month: "short",
42
+ day: "numeric",
43
+ year: "numeric",
44
+ hour: "2-digit",
45
+ minute: "2-digit"
46
+ })
47
+ }}
48
+ </span>
49
+ <span v-if="feedback.country" class="flex items-center gap-1">
50
+ <UIcon name="i-lucide-map-pin" class="size-3" />
51
+ {{ feedback.country }}
52
+ </span>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ <UButton
57
+ color="error"
58
+ variant="ghost"
59
+ size="sm"
60
+ icon="i-lucide-trash-2"
61
+ :loading="isDeleting"
62
+ :disabled="isDeleting"
63
+ @click="handleDelete"
64
+ />
65
+ </div>
66
+
67
+ <div
68
+ v-if="feedback.feedback"
69
+ class="rounded bg-muted/30 p-3 text-sm leading-relaxed"
70
+ >
71
+ "{{ feedback.feedback }}"
72
+ </div>
73
+ <div v-else class="text-sm text-muted italic">
74
+ No additional comment provided
75
+ </div>
76
+ </div>
77
+ </template>
@@ -0,0 +1,10 @@
1
+ type __VLS_Props = {
2
+ feedback: FeedbackItem;
3
+ };
4
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
5
+ delete: (id: number) => any;
6
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
7
+ onDelete?: ((id: number) => any) | undefined;
8
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
+ declare const _default: typeof __VLS_export;
10
+ export default _default;
@@ -0,0 +1,17 @@
1
+ type __VLS_Props = {
2
+ icon: string;
3
+ iconColor?: string;
4
+ value: number | string;
5
+ label: string;
6
+ description?: string;
7
+ descriptionColor?: string;
8
+ popoverStats?: {
9
+ percentage?: string;
10
+ trend?: string;
11
+ lastPeriod?: string;
12
+ details?: string;
13
+ };
14
+ };
15
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
+ declare const _default: typeof __VLS_export;
17
+ export default _default;
@@ -0,0 +1,66 @@
1
+ <script setup>
2
+ const { iconColor = `text-primary`, descriptionColor = `text-muted` } = defineProps({
3
+ icon: { type: String, required: true },
4
+ iconColor: { type: String, required: false },
5
+ value: { type: [Number, String], required: true },
6
+ label: { type: String, required: true },
7
+ description: { type: String, required: false },
8
+ descriptionColor: { type: String, required: false },
9
+ popoverStats: { type: Object, required: false }
10
+ });
11
+ </script>
12
+
13
+ <template>
14
+ <UPopover mode="hover" arrow :open-delay="300" :close-delay="200">
15
+ <div
16
+ class="flex cursor-pointer items-center gap-3 rounded-lg border border-default bg-muted/20 px-4 py-3 transition-colors hover:bg-muted/30"
17
+ >
18
+ <UIcon :name="icon" :class="`size-6 ${iconColor} shrink-0`" />
19
+ <div>
20
+ <div class="text-xl font-bold">
21
+ {{ value }}
22
+ </div>
23
+ <div class="text-sm text-muted">
24
+ {{ label }}
25
+ </div>
26
+ </div>
27
+ </div>
28
+
29
+ <template #content>
30
+ <div class="min-w-64 p-4">
31
+ <div class="mb-3 flex items-center gap-2">
32
+ <UIcon :name="icon" :class="`size-5 ${iconColor}`" />
33
+ <h3 class="font-semibold">{{ label }} Details</h3>
34
+ </div>
35
+
36
+ <div class="space-y-2 text-sm">
37
+ <div v-if="popoverStats?.percentage" class="flex justify-between">
38
+ <span class="text-muted">Percentage:</span>
39
+ <span class="font-medium">{{ popoverStats.percentage }}</span>
40
+ </div>
41
+
42
+ <div v-if="popoverStats?.trend" class="flex justify-between">
43
+ <span class="text-muted">Status:</span>
44
+ <span class="font-medium">
45
+ {{ popoverStats.trend }}
46
+ </span>
47
+ </div>
48
+
49
+ <div v-if="popoverStats?.lastPeriod" class="flex justify-between">
50
+ <span class="text-muted">Last 7 days:</span>
51
+ <span class="font-medium">{{ popoverStats.lastPeriod }}</span>
52
+ </div>
53
+
54
+ <div
55
+ v-if="popoverStats?.details"
56
+ class="border-t border-default pt-2"
57
+ >
58
+ <p class="text-xs text-muted">
59
+ {{ popoverStats.details }}
60
+ </p>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ </template>
65
+ </UPopover>
66
+ </template>
@@ -0,0 +1,17 @@
1
+ type __VLS_Props = {
2
+ icon: string;
3
+ iconColor?: string;
4
+ value: number | string;
5
+ label: string;
6
+ description?: string;
7
+ descriptionColor?: string;
8
+ popoverStats?: {
9
+ percentage?: string;
10
+ trend?: string;
11
+ lastPeriod?: string;
12
+ details?: string;
13
+ };
14
+ };
15
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
+ declare const _default: typeof __VLS_export;
17
+ export default _default;
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "rimelight-components",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "My new Nuxt module",
5
- "repository": "RimelightEntertainment/rimelight-components",
5
+ "repository": "Rimelight Entertainment/rimelight-components",
6
6
  "license": "MIT",
7
7
  "type": "module",
8
8
  "exports": {
@@ -38,25 +38,36 @@
38
38
  "playground"
39
39
  ],
40
40
  "dependencies": {
41
- "nuxt": "^4.1.3",
41
+ "@nuxt/image": "^1.11.0",
42
42
  "@nuxt/kit": "^4.1.3",
43
+ "@nuxt/ui": "^4.0.1",
43
44
  "date-fns": "^4.1.0",
45
+ "nuxt": "^4.1.3",
46
+ "tailwind-variants": "^3.1.1",
44
47
  "vue": "^3.5.22"
45
48
  },
46
49
  "devDependencies": {
47
- "@nuxt/image": "1.11.0",
48
50
  "@nuxt/devtools": "^2.6.5",
49
51
  "@nuxt/module-builder": "^1.0.2",
50
52
  "@nuxt/schema": "^4.1.3",
51
53
  "@nuxt/test-utils": "^3.19.2",
54
+ "@prettier/plugin-oxc": "^0.0.4",
52
55
  "@types/node": "latest",
53
56
  "changelogen": "^0.6.2",
54
- "typescript": "~5.9.3",
55
- "vitest": "^3.2.4",
56
- "vue-tsc": "^3.1.0",
57
- "@prettier/plugin-oxc": "^0.0.4",
57
+ "class-variance-authority": "^0.7.1",
58
+ "clsx": "^2.1.1",
59
+ "motion-v": "^1.7.2",
58
60
  "oxlint": "^1.21.0",
59
61
  "prettier": "^3.6.2",
60
- "prettier-plugin-tailwindcss": "^0.6.14"
61
- }
62
+ "prettier-plugin-tailwindcss": "^0.6.14",
63
+ "tailwind-merge": "^3.3.1",
64
+ "tw-animate-css": "^1.4.0",
65
+ "typescript": "~5.9.3",
66
+ "vitest": "^3.2.4",
67
+ "vue-tsc": "^3.1.0"
68
+ },
69
+ "trustedDependencies": [
70
+ "@parcel/watcher",
71
+ "@tailwindcss/oxide"
72
+ ]
62
73
  }
@@ -1,23 +0,0 @@
1
- <script setup>
2
- import { ref } from "vue";
3
- const { to } = defineProps({
4
- to: { type: String, required: true }
5
- });
6
- const actions = ref([
7
- {
8
- label: "View on GitHub",
9
- trailingIcon: "mdi:github",
10
- to
11
- }
12
- ]);
13
- </script>
14
-
15
- <template>
16
- <UBanner
17
- color="primary"
18
- icon="lucide:construction"
19
- title="This website is currently under construction. Feel free to report any issues!"
20
- :actions="actions"
21
- close
22
- />
23
- </template>