slidev-workspace 0.3.0 → 0.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slidev-workspace",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "A workspace tool for managing multiple Slidev presentations with API-based content management",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -4,113 +4,113 @@
4
4
  @custom-variant dark (&:is(.dark *));
5
5
 
6
6
  @theme inline {
7
- --color-background: var(--background);
8
- --color-foreground: var(--foreground);
9
- --color-card: var(--card);
10
- --color-card-foreground: var(--card-foreground);
11
- --color-popover: var(--popover);
12
- --color-popover-foreground: var(--popover-foreground);
13
- --color-primary: var(--primary);
14
- --color-primary-foreground: var(--primary-foreground);
15
- --color-secondary: var(--secondary);
16
- --color-secondary-foreground: var(--secondary-foreground);
17
- --color-muted: var(--muted);
18
- --color-muted-foreground: var(--muted-foreground);
19
- --color-accent: var(--accent);
20
- --color-accent-foreground: var(--accent-foreground);
21
- --color-destructive: var(--destructive);
22
- --color-destructive-foreground: var(--destructive-foreground);
23
- --color-border: var(--border);
24
- --color-input: var(--input);
25
- --color-ring: var(--ring);
26
- --color-chart-1: var(--chart-1);
27
- --color-chart-2: var(--chart-2);
28
- --color-chart-3: var(--chart-3);
29
- --color-chart-4: var(--chart-4);
30
- --color-chart-5: var(--chart-5);
7
+ --color-background: hsl(var(--background));
8
+ --color-foreground: hsl(var(--foreground));
9
+ --color-card: hsl(var(--card));
10
+ --color-card-foreground: hsl(var(--card-foreground));
11
+ --color-popover: hsl(var(--popover));
12
+ --color-popover-foreground: hsl(var(--popover-foreground));
13
+ --color-primary: hsl(var(--primary));
14
+ --color-primary-foreground: hsl(var(--primary-foreground));
15
+ --color-secondary: hsl(var(--secondary));
16
+ --color-secondary-foreground: hsl(var(--secondary-foreground));
17
+ --color-muted: hsl(var(--muted));
18
+ --color-muted-foreground: hsl(var(--muted-foreground));
19
+ --color-accent: hsl(var(--accent));
20
+ --color-accent-foreground: hsl(var(--accent-foreground));
21
+ --color-destructive: hsl(var(--destructive));
22
+ --color-destructive-foreground: hsl(var(--destructive-foreground));
23
+ --color-border: hsl(var(--border));
24
+ --color-input: hsl(var(--input));
25
+ --color-ring: hsl(var(--ring));
26
+ --color-chart-1: hsl(var(--chart-1));
27
+ --color-chart-2: hsl(var(--chart-2));
28
+ --color-chart-3: hsl(var(--chart-3));
29
+ --color-chart-4: hsl(var(--chart-4));
30
+ --color-chart-5: hsl(var(--chart-5));
31
31
  --radius-sm: calc(var(--radius) - 4px);
32
32
  --radius-md: calc(var(--radius) - 2px);
33
33
  --radius-lg: var(--radius);
34
34
  --radius-xl: calc(var(--radius) + 4px);
35
- --color-sidebar: var(--sidebar);
36
- --color-sidebar-foreground: var(--sidebar-foreground);
37
- --color-sidebar-primary: var(--sidebar-primary);
38
- --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
39
- --color-sidebar-accent: var(--sidebar-accent);
40
- --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
41
- --color-sidebar-border: var(--sidebar-border);
42
- --color-sidebar-ring: var(--sidebar-ring);
35
+ --color-sidebar: hsl(var(--sidebar));
36
+ --color-sidebar-foreground: hsl(var(--sidebar-foreground));
37
+ --color-sidebar-primary: hsl(var(--sidebar-primary));
38
+ --color-sidebar-primary-foreground: hsl(var(--sidebar-primary-foreground));
39
+ --color-sidebar-accent: hsl(var(--sidebar-accent));
40
+ --color-sidebar-accent-foreground: hsl(var(--sidebar-accent-foreground));
41
+ --color-sidebar-border: hsl(var(--sidebar-border));
42
+ --color-sidebar-ring: hsl(var(--sidebar-ring));
43
43
  }
44
44
 
45
45
  :root {
46
- --background: oklch(1 0 0);
47
- --foreground: oklch(0.145 0 0);
48
- --card: oklch(1 0 0);
49
- --card-foreground: oklch(0.145 0 0);
50
- --popover: oklch(1 0 0);
51
- --popover-foreground: oklch(0.145 0 0);
52
- --primary: oklch(0.205 0 0);
53
- --primary-foreground: oklch(0.985 0 0);
54
- --secondary: oklch(0.97 0 0);
55
- --secondary-foreground: oklch(0.205 0 0);
56
- --muted: oklch(0.97 0 0);
57
- --muted-foreground: oklch(0.556 0 0);
58
- --accent: oklch(0.97 0 0);
59
- --accent-foreground: oklch(0.205 0 0);
60
- --destructive: oklch(0.577 0.245 27.325);
61
- --destructive-foreground: oklch(0.577 0.245 27.325);
62
- --border: oklch(0.922 0 0);
63
- --input: oklch(0.922 0 0);
64
- --ring: oklch(0.708 0 0);
65
- --chart-1: oklch(0.646 0.222 41.116);
66
- --chart-2: oklch(0.6 0.118 184.704);
67
- --chart-3: oklch(0.398 0.07 227.392);
68
- --chart-4: oklch(0.828 0.189 84.429);
69
- --chart-5: oklch(0.769 0.188 70.08);
70
- --radius: 0.625rem;
71
- --sidebar: oklch(0.985 0 0);
72
- --sidebar-foreground: oklch(0.145 0 0);
73
- --sidebar-primary: oklch(0.205 0 0);
74
- --sidebar-primary-foreground: oklch(0.985 0 0);
75
- --sidebar-accent: oklch(0.97 0 0);
76
- --sidebar-accent-foreground: oklch(0.205 0 0);
77
- --sidebar-border: oklch(0.922 0 0);
78
- --sidebar-ring: oklch(0.708 0 0);
46
+ --background: 0 0% 100%;
47
+ --foreground: 0 0% 3.9%;
48
+ --card: 0 0% 100%;
49
+ --card-foreground: 0 0% 3.9%;
50
+ --popover: 0 0% 100%;
51
+ --popover-foreground: 0 0% 3.9%;
52
+ --primary: 0 0% 9%;
53
+ --primary-foreground: 0 0% 98%;
54
+ --secondary: 0 0% 96.1%;
55
+ --secondary-foreground: 0 0% 9%;
56
+ --muted: 0 0% 96.1%;
57
+ --muted-foreground: 0 0% 45.1%;
58
+ --accent: 0 0% 96.1%;
59
+ --accent-foreground: 0 0% 9%;
60
+ --destructive: 0 84.2% 60.2%;
61
+ --destructive-foreground: 0 0% 98%;
62
+ --border: 0 0% 89.8%;
63
+ --input: 0 0% 89.8%;
64
+ --ring: 0 0% 3.9%;
65
+ --chart-1: 12 76% 61%;
66
+ --chart-2: 173 58% 39%;
67
+ --chart-3: 197 37% 24%;
68
+ --chart-4: 43 74% 66%;
69
+ --chart-5: 27 87% 67%;
70
+ --radius: 0.5rem;
71
+ --sidebar: 0 0% 98%;
72
+ --sidebar-foreground: 0 0% 3.9%;
73
+ --sidebar-primary: 0 0% 9%;
74
+ --sidebar-primary-foreground: 0 0% 98%;
75
+ --sidebar-accent: 0 0% 96.1%;
76
+ --sidebar-accent-foreground: 0 0% 9%;
77
+ --sidebar-border: 0 0% 89.8%;
78
+ --sidebar-ring: 0 0% 3.9%;
79
79
  }
80
80
 
81
81
  .dark {
82
- --background: oklch(0.145 0 0);
83
- --foreground: oklch(0.985 0 0);
84
- --card: oklch(0.145 0 0);
85
- --card-foreground: oklch(0.985 0 0);
86
- --popover: oklch(0.145 0 0);
87
- --popover-foreground: oklch(0.985 0 0);
88
- --primary: oklch(0.985 0 0);
89
- --primary-foreground: oklch(0.205 0 0);
90
- --secondary: oklch(0.269 0 0);
91
- --secondary-foreground: oklch(0.985 0 0);
92
- --muted: oklch(0.269 0 0);
93
- --muted-foreground: oklch(0.708 0 0);
94
- --accent: oklch(0.269 0 0);
95
- --accent-foreground: oklch(0.985 0 0);
96
- --destructive: oklch(0.396 0.141 25.723);
97
- --destructive-foreground: oklch(0.637 0.237 25.331);
98
- --border: oklch(0.269 0 0);
99
- --input: oklch(0.269 0 0);
100
- --ring: oklch(0.439 0 0);
101
- --chart-1: oklch(0.488 0.243 264.376);
102
- --chart-2: oklch(0.696 0.17 162.48);
103
- --chart-3: oklch(0.769 0.188 70.08);
104
- --chart-4: oklch(0.627 0.265 303.9);
105
- --chart-5: oklch(0.645 0.246 16.439);
106
- --sidebar: oklch(0.205 0 0);
107
- --sidebar-foreground: oklch(0.985 0 0);
108
- --sidebar-primary: oklch(0.488 0.243 264.376);
109
- --sidebar-primary-foreground: oklch(0.985 0 0);
110
- --sidebar-accent: oklch(0.269 0 0);
111
- --sidebar-accent-foreground: oklch(0.985 0 0);
112
- --sidebar-border: oklch(0.269 0 0);
113
- --sidebar-ring: oklch(0.439 0 0);
82
+ --background: 224 71.4% 4.1%;
83
+ --foreground: 210 20% 98%;
84
+ --muted: 215 27.9% 16.9%;
85
+ --muted-foreground: 217.9 10.6% 64.9%;
86
+ --popover: 224 71.4% 4.1%;
87
+ --popover-foreground: 210 20% 98%;
88
+ --card: 224 71.4% 4.1%;
89
+ --card-foreground: 210 20% 98%;
90
+ --border: 215 27.9% 16.9%;
91
+ --input: 215 27.9% 16.9%;
92
+ --primary: 210 20% 98%;
93
+ --primary-foreground: 220.9 39.3% 11%;
94
+ --secondary: 215 27.9% 16.9%;
95
+ --secondary-foreground: 210 20% 98%;
96
+ --accent: 215 27.9% 16.9%;
97
+ --accent-foreground: 210 20% 98%;
98
+ --destructive: 0 62.8% 30.6%;
99
+ --destructive-foreground: 210 20% 98%;
100
+ --ring: 216 12.2% 83.9%;
101
+ --chart-1: 220 70% 50%;
102
+ --chart-2: 160 60% 45%;
103
+ --chart-3: 30 80% 55%;
104
+ --chart-4: 280 65% 60%;
105
+ --chart-5: 340 75% 55%;
106
+ --sidebar: 0 0% 9%;
107
+ --sidebar-foreground: 0 0% 98%;
108
+ --sidebar-primary: 220 70% 50%;
109
+ --sidebar-primary-foreground: 0 0% 98%;
110
+ --sidebar-accent: 0 0% 14.9%;
111
+ --sidebar-accent-foreground: 0 0% 98%;
112
+ --sidebar-border: 0 0% 14.9%;
113
+ --sidebar-ring: 0 0% 83.1%;
114
114
  }
115
115
 
116
116
  @layer base {
@@ -1,21 +1,38 @@
1
1
  <template>
2
2
  <div
3
- class="min-h-screen bg-gradient-to-br from-gray-100 via-white to-gray-200 py-16 px-4"
3
+ class="min-h-screen bg-gradient-to-br from-gray-100 via-white to-gray-200 dark:from-gray-900 dark:via-gray-950 dark:to-black py-16 px-4 transition-colors"
4
4
  >
5
5
  <div class="max-w-5xl mx-auto">
6
- <div class="mb-8">
7
- <h1 class="text-3xl font-bold mb-2">{{ hero.title }}</h1>
8
- <p class="text-muted-foreground">
9
- {{ hero.description }}
10
- </p>
6
+ <div class="mb-8 flex justify-between items-start">
7
+ <div>
8
+ <h1 class="text-3xl font-bold mb-2">{{ hero.title }}</h1>
9
+ <p class="text-muted-foreground">
10
+ {{ hero.description }}
11
+ </p>
12
+ </div>
13
+ <button
14
+ @click="toggleDarkMode"
15
+ class="p-2 rounded-lg hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring transition-colors cursor-pointer"
16
+ aria-label="Toggle dark mode"
17
+ type="button"
18
+ >
19
+ <Moon v-if="!isDark" class="size-6" />
20
+ <Sun v-else class="size-6" />
21
+ </button>
11
22
  </div>
12
23
 
13
24
  <div class="space-y-4 mb-8">
14
- <div class="relative">
25
+ <div class="relative w-full">
15
26
  <Input
27
+ class="pl-10"
16
28
  placeholder="Search by title, description, or author..."
17
29
  v-model="searchTerm"
18
30
  />
31
+ <span
32
+ class="absolute start-0 inset-y-0 flex items-center justify-center px-2"
33
+ >
34
+ <Search class="size-6 text-muted-foreground/30" />
35
+ </span>
19
36
  </div>
20
37
  </div>
21
38
 
@@ -50,14 +67,18 @@
50
67
 
51
68
  <script setup lang="ts">
52
69
  import { ref, computed } from "vue";
70
+ import { Search, Moon, Sun } from "lucide-vue-next";
71
+
53
72
  import { useSlides } from "../composables/useSlides";
54
73
  import { useConfig } from "../composables/useConfig";
74
+ import { useDarkMode } from "../composables/useDarkMode";
55
75
  import { Input } from "../components/ui/input";
56
76
  import SlideCard from "./SlideCard.vue";
57
77
 
58
78
  const searchTerm = ref("");
59
79
  const { slides, slidesCount } = useSlides();
60
80
  const { hero } = useConfig();
81
+ const { isDark, toggleDarkMode } = useDarkMode();
61
82
 
62
83
  const filteredSlides = computed(() => {
63
84
  if (!searchTerm.value) return slides.value;
@@ -12,7 +12,7 @@ const props = defineProps<{
12
12
  data-slot="card"
13
13
  :class="
14
14
  cn(
15
- 'bg-card text-card-foreground flex flex-col rounded-xl border shadow-sm',
15
+ 'bg-card text-card-foreground flex flex-col rounded-xl border shadow',
16
16
  props.class,
17
17
  )
18
18
  "
@@ -22,12 +22,9 @@ const modelValue = useVModel(props, "modelValue", emits, {
22
22
  <template>
23
23
  <input
24
24
  v-model="modelValue"
25
- data-slot="input"
26
25
  :class="
27
26
  cn(
28
- 'file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
29
- 'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
30
- 'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
27
+ 'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
31
28
  props.class,
32
29
  )
33
30
  "
@@ -0,0 +1,54 @@
1
+ import { useDark } from "@vueuse/core";
2
+
3
+ export function useDarkMode() {
4
+ const isDark = useDark();
5
+
6
+ const toggleDarkMode = (event: MouseEvent) => {
7
+ if (!document.startViewTransition) {
8
+ isDark.value = !isDark.value;
9
+ return;
10
+ }
11
+
12
+ const x = event.clientX;
13
+ const y = event.clientY;
14
+ // Calculate percentage-based position for better accuracy
15
+ const xPercent = (x / window.innerWidth) * 100;
16
+ const yPercent = (y / window.innerHeight) * 100;
17
+
18
+ const endRadius = Math.hypot(
19
+ Math.max(x, window.innerWidth - x),
20
+ Math.max(y, window.innerHeight - y),
21
+ );
22
+
23
+ const wasDark = isDark.value;
24
+
25
+ const transition = document.startViewTransition(() => {
26
+ isDark.value = !wasDark;
27
+ });
28
+
29
+ transition.ready.then(() => {
30
+ const clipPath = [
31
+ `circle(0px at ${xPercent}% ${yPercent}%)`,
32
+ `circle(${endRadius}px at ${xPercent}% ${yPercent}%)`,
33
+ ];
34
+
35
+ document.documentElement.animate(
36
+ {
37
+ clipPath: isDark.value ? clipPath.reverse() : clipPath,
38
+ },
39
+ {
40
+ duration: 200,
41
+ easing: "ease-in",
42
+ pseudoElement: isDark.value
43
+ ? "::view-transition-old(root)"
44
+ : "::view-transition-new(root)",
45
+ },
46
+ );
47
+ });
48
+ };
49
+
50
+ return {
51
+ isDark,
52
+ toggleDarkMode,
53
+ };
54
+ }