slidev-workspace 0.1.6 → 0.1.8

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.
Files changed (31) hide show
  1. package/dist/cli.js +1 -2
  2. package/dist/index.d.ts +7 -38
  3. package/dist/index.js +2 -157
  4. package/dist/plugin-slides.d.ts +6 -0
  5. package/dist/plugin-slides.js +153 -0
  6. package/package.json +11 -15
  7. package/src/preview/assets/main.css +1 -1
  8. package/src/preview/components/SlideCard.vue +41 -20
  9. package/src/preview/components/SlideDeck.vue +11 -20
  10. package/src/preview/components/ui/button/Button.vue +2 -2
  11. package/src/preview/components/ui/button/index.ts +1 -1
  12. package/src/preview/components/ui/card/Card.vue +4 -4
  13. package/src/preview/components/ui/card/CardAction.vue +10 -5
  14. package/src/preview/components/ui/card/CardContent.vue +5 -8
  15. package/src/preview/components/ui/card/CardDescription.vue +4 -4
  16. package/src/preview/components/ui/card/CardFooter.vue +4 -4
  17. package/src/preview/components/ui/card/CardHeader.vue +8 -5
  18. package/src/preview/components/ui/card/CardTitle.vue +4 -4
  19. package/src/preview/components/ui/card/index.ts +7 -7
  20. package/src/preview/components/ui/input/Input.vue +20 -18
  21. package/src/preview/components/ui/input/index.ts +1 -1
  22. package/src/preview/composables/useSlides.ts +5 -17
  23. package/src/preview/index.html +11 -11
  24. package/src/preview/lib/utils.ts +3 -3
  25. package/src/preview/main.ts +4 -4
  26. package/vite.config.ts +1 -1
  27. package/src/preview/components/SlideDetail.vue +0 -160
  28. package/src/preview/dist/assets/index-Cbywrv7-.css +0 -2
  29. package/src/preview/dist/assets/index-LGnZwLzS.js +0 -24
  30. package/src/preview/dist/index.html +0 -13
  31. package/src/preview/utils/getSlides.ts +0 -65
package/dist/cli.js CHANGED
@@ -7,7 +7,6 @@ import tailwindcss from "@tailwindcss/vite";
7
7
  import { existsSync, readFileSync, readdirSync, watch } from "fs";
8
8
  import { basename, join as join$1, resolve as resolve$1 } from "path";
9
9
  import { parse } from "yaml";
10
- import "vue";
11
10
 
12
11
  //#region src/scripts/config.ts
13
12
  const DEFAULT_CONFIG = {
@@ -112,7 +111,7 @@ if (import.meta.url === `file://${process.argv[1]}`) {
112
111
  }
113
112
 
114
113
  //#endregion
115
- //#region src/scripts/vite-plugin-slides.ts
114
+ //#region src/vite/plugin-slides.ts
116
115
  function slidesPlugin() {
117
116
  return {
118
117
  name: "vite-plugin-slides",
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import * as vue0 from "vue";
2
- import { Plugin } from "vite";
3
2
 
4
3
  //#region src/types/slide.d.ts
5
4
  interface SlideFrontmatter {
@@ -20,7 +19,6 @@ interface SlideFrontmatter {
20
19
  };
21
20
  author?: string;
22
21
  date?: string;
23
- [key: string]: any;
24
22
  }
25
23
  interface SlideInfo {
26
24
  id: string;
@@ -31,7 +29,6 @@ interface SlideInfo {
31
29
  content: string;
32
30
  }
33
31
  interface SlideData {
34
- id: string;
35
32
  title: string;
36
33
  url: string;
37
34
  description: string;
@@ -41,20 +38,14 @@ interface SlideData {
41
38
  theme?: string;
42
39
  transition?: string;
43
40
  class?: string;
44
- sourceDir: string;
45
- path: string;
46
- fullPath: string;
47
- frontmatter: SlideFrontmatter;
48
- content: string;
49
41
  }
50
42
  //#endregion
51
- //#region src/scripts/getSlideFrontmatter.d.ts
52
- declare function getSlideFrontmatter(slideId: string): SlideInfo | null;
53
- declare function getSlideFrontmatterByPath(slideDir: string, slideName: string): SlideInfo | null;
54
- declare function getAllSlidesFrontmatter(): SlideInfo[];
55
- //#endregion
56
- //#region src/scripts/vite-plugin-slides.d.ts
57
- declare function slidesPlugin(): Plugin;
43
+ //#region src/preview/composables/useSlides.d.ts
44
+ declare function useSlides(): {
45
+ slides: vue0.ComputedRef<SlideData[]>;
46
+ slidesCount: vue0.ComputedRef<number>;
47
+ loadSlidesData: () => Promise<void>;
48
+ };
58
49
  //#endregion
59
50
  //#region src/types/config.d.ts
60
51
  interface SlidevWorkspaceConfig {
@@ -64,26 +55,4 @@ interface SlidevWorkspaceConfig {
64
55
  exclude: string[];
65
56
  }
66
57
  //#endregion
67
- //#region src/scripts/config.d.ts
68
- declare function loadConfig(workingDir?: string): SlidevWorkspaceConfig;
69
- declare function resolveSlidesDirs(config: SlidevWorkspaceConfig, workingDir?: string): string[];
70
- //#endregion
71
- //#region src/preview/composables/useSlides.d.ts
72
- interface SlideData$1 {
73
- title: string;
74
- url: string;
75
- description: string;
76
- image: string;
77
- author: string;
78
- date: string;
79
- theme?: string;
80
- transition?: string;
81
- class?: string;
82
- }
83
- declare function useSlides(): {
84
- slides: vue0.ComputedRef<SlideData$1[]>;
85
- slidesCount: vue0.ComputedRef<number>;
86
- loadSlidesData: () => Promise<void>;
87
- };
88
- //#endregion
89
- export { type SlideData, type SlideFrontmatter, type SlideInfo, type SlidevWorkspaceConfig, getAllSlidesFrontmatter, getSlideFrontmatter, getSlideFrontmatterByPath, loadConfig, resolveSlidesDirs, slidesPlugin, useSlides };
58
+ export { type SlideData, type SlideFrontmatter, type SlideInfo, type SlidevWorkspaceConfig, useSlides };
package/dist/index.js CHANGED
@@ -1,167 +1,12 @@
1
- import { existsSync, readFileSync, readdirSync, watch } from "fs";
2
- import { basename, join, resolve } from "path";
3
- import { parse } from "yaml";
4
1
  import { computed, ref } from "vue";
5
2
 
6
- //#region src/scripts/config.ts
7
- const DEFAULT_CONFIG = {
8
- slidesDir: ["./slides"],
9
- outputDir: "./dist",
10
- baseUrl: "/",
11
- exclude: ["node_modules", ".git"]
12
- };
13
- function loadConfig(workingDir) {
14
- const configPaths = [
15
- "slidev-workspace.config.js",
16
- "slidev-workspace.config.ts",
17
- "slidev-workspace.yml",
18
- "slidev-workspace.yaml"
19
- ];
20
- const projectRoot = workingDir || process.env.SLIDEV_WORKSPACE_CWD || process.cwd();
21
- for (const configPath of configPaths) {
22
- const fullPath = join(projectRoot, configPath);
23
- if (existsSync(fullPath)) try {
24
- if (configPath.endsWith(".yml") || configPath.endsWith(".yaml")) {
25
- const content = readFileSync(fullPath, "utf8");
26
- const config = parse(content);
27
- return {
28
- ...DEFAULT_CONFIG,
29
- ...config
30
- };
31
- }
32
- } catch (error) {
33
- console.warn(`Failed to load config from ${fullPath}:`, error);
34
- }
35
- }
36
- return DEFAULT_CONFIG;
37
- }
38
- function resolveSlidesDirs(config, workingDir) {
39
- const projectRoot = workingDir || process.env.SLIDEV_WORKSPACE_CWD || process.cwd();
40
- const resolvedDirs = (config.slidesDir || []).map((dir) => {
41
- if (resolve(dir) === dir) return dir;
42
- else return resolve(projectRoot, dir);
43
- }).filter((dir) => {
44
- const exists = existsSync(dir);
45
- return exists;
46
- });
47
- return resolvedDirs;
48
- }
49
-
50
- //#endregion
51
- //#region src/scripts/getSlideFrontmatter.ts
52
- function getSlideFrontmatter(slideId) {
53
- const allSlides = getAllSlidesFrontmatter();
54
- return allSlides.find((slide) => slide.id === slideId) || null;
55
- }
56
- function getSlideFrontmatterByPath(slideDir, slideName) {
57
- try {
58
- const fullPath = join(slideDir, slideName, "slides.md");
59
- if (!existsSync(fullPath)) {
60
- console.warn(`File not found: ${fullPath}`);
61
- return null;
62
- }
63
- const content = readFileSync(fullPath, "utf8");
64
- const frontmatterMatch = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n/);
65
- if (!frontmatterMatch) {
66
- console.warn(`Frontmatter not found in ${fullPath}`);
67
- return null;
68
- }
69
- const frontmatterYaml = frontmatterMatch[1];
70
- const frontmatter = parse(frontmatterYaml);
71
- const sourceBasename = basename(slideDir);
72
- const slideId = `${sourceBasename}/${slideName}`;
73
- return {
74
- id: slideId,
75
- path: slideName,
76
- fullPath,
77
- sourceDir: slideDir,
78
- frontmatter,
79
- content: content.replace(frontmatterMatch[0], "")
80
- };
81
- } catch (error) {
82
- console.error(`Error parsing frontmatter for ${slideName} in ${slideDir}:`, error);
83
- return null;
84
- }
85
- }
86
- function getAllSlidesFrontmatter() {
87
- const config = loadConfig();
88
- const slidesDirs = resolveSlidesDirs(config);
89
- const slides = [];
90
- for (const slidesDir of slidesDirs) {
91
- if (!existsSync(slidesDir)) {
92
- console.warn(`Slides directory not found: ${slidesDir}`);
93
- continue;
94
- }
95
- try {
96
- const slideDirs = readdirSync(slidesDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).filter((dirent) => !(config.exclude || []).includes(dirent.name)).map((dirent) => dirent.name);
97
- for (const slideDir of slideDirs) {
98
- const slideInfo = getSlideFrontmatterByPath(slidesDir, slideDir);
99
- if (slideInfo) slides.push(slideInfo);
100
- }
101
- } catch (error) {
102
- console.error(`Error reading slides directory ${slidesDir}:`, error);
103
- }
104
- }
105
- return slides;
106
- }
107
- if (import.meta.url === `file://${process.argv[1]}`) {
108
- const slides = getAllSlidesFrontmatter();
109
- console.log(JSON.stringify(slides, null, 2));
110
- }
111
-
112
- //#endregion
113
- //#region src/scripts/vite-plugin-slides.ts
114
- function slidesPlugin() {
115
- return {
116
- name: "vite-plugin-slides",
117
- configureServer(server) {
118
- const watchers = [];
119
- const config = loadConfig();
120
- const slidesDirs = resolveSlidesDirs(config);
121
- slidesDirs.forEach((slidesDir) => {
122
- const watcher = watch(slidesDir, { recursive: true }, (eventType, filename) => {
123
- if (filename && filename.endsWith("slides.md")) try {
124
- const slides = getAllSlidesFrontmatter();
125
- server.ws.send({
126
- type: "custom",
127
- event: "slides-updated",
128
- data: slides
129
- });
130
- } catch (error) {
131
- console.error("❌ Error reading slides frontmatter:", error);
132
- }
133
- });
134
- watchers.push(watcher);
135
- });
136
- server.httpServer?.once("close", () => {
137
- watchers.forEach((watcher) => watcher.close());
138
- });
139
- },
140
- resolveId(id) {
141
- if (id === "slidev:content") return id;
142
- },
143
- load(id) {
144
- if (id === "slidev:content") try {
145
- const slides = getAllSlidesFrontmatter();
146
- return `export const slidesData = ${JSON.stringify(slides, null, 2)};
147
- export default slidesData;`;
148
- } catch (error) {
149
- console.error("Error loading slides data:", error);
150
- return `export const slidesData = [];
151
- export default slidesData;`;
152
- }
153
- }
154
- };
155
- }
156
-
157
- //#endregion
158
3
  //#region src/preview/composables/useSlides.ts
159
4
  function useSlides() {
160
5
  const slidesData = ref([]);
161
6
  const loadSlidesData = async () => {
162
7
  try {
163
8
  const module = await import("slidev:content");
164
- slidesData.value = module.default || module.slidesData || [];
9
+ slidesData.value = module.default || [];
165
10
  } catch (error) {
166
11
  console.warn("Failed to load slides data:", error);
167
12
  slidesData.value = [];
@@ -191,4 +36,4 @@ function useSlides() {
191
36
  }
192
37
 
193
38
  //#endregion
194
- export { getAllSlidesFrontmatter, getSlideFrontmatter, getSlideFrontmatterByPath, loadConfig, resolveSlidesDirs, slidesPlugin, useSlides };
39
+ export { useSlides };
@@ -0,0 +1,6 @@
1
+ import { Plugin } from "vite";
2
+
3
+ //#region src/vite/plugin-slides.d.ts
4
+ declare function slidesPlugin(): Plugin;
5
+ //#endregion
6
+ export { slidesPlugin };
@@ -0,0 +1,153 @@
1
+ import { existsSync, readFileSync, readdirSync, watch } from "fs";
2
+ import { basename, join, resolve } from "path";
3
+ import { parse } from "yaml";
4
+
5
+ //#region src/scripts/config.ts
6
+ const DEFAULT_CONFIG = {
7
+ slidesDir: ["./slides"],
8
+ outputDir: "./dist",
9
+ baseUrl: "/",
10
+ exclude: ["node_modules", ".git"]
11
+ };
12
+ function loadConfig(workingDir) {
13
+ const configPaths = [
14
+ "slidev-workspace.config.js",
15
+ "slidev-workspace.config.ts",
16
+ "slidev-workspace.yml",
17
+ "slidev-workspace.yaml"
18
+ ];
19
+ const projectRoot = workingDir || process.env.SLIDEV_WORKSPACE_CWD || process.cwd();
20
+ for (const configPath of configPaths) {
21
+ const fullPath = join(projectRoot, configPath);
22
+ if (existsSync(fullPath)) try {
23
+ if (configPath.endsWith(".yml") || configPath.endsWith(".yaml")) {
24
+ const content = readFileSync(fullPath, "utf8");
25
+ const config = parse(content);
26
+ return {
27
+ ...DEFAULT_CONFIG,
28
+ ...config
29
+ };
30
+ }
31
+ } catch (error) {
32
+ console.warn(`Failed to load config from ${fullPath}:`, error);
33
+ }
34
+ }
35
+ return DEFAULT_CONFIG;
36
+ }
37
+ function resolveSlidesDirs(config, workingDir) {
38
+ const projectRoot = workingDir || process.env.SLIDEV_WORKSPACE_CWD || process.cwd();
39
+ const resolvedDirs = (config.slidesDir || []).map((dir) => {
40
+ if (resolve(dir) === dir) return dir;
41
+ else return resolve(projectRoot, dir);
42
+ }).filter((dir) => {
43
+ const exists = existsSync(dir);
44
+ return exists;
45
+ });
46
+ return resolvedDirs;
47
+ }
48
+
49
+ //#endregion
50
+ //#region src/scripts/getSlideFrontmatter.ts
51
+ function getSlideFrontmatterByPath(slideDir, slideName) {
52
+ try {
53
+ const fullPath = join(slideDir, slideName, "slides.md");
54
+ if (!existsSync(fullPath)) {
55
+ console.warn(`File not found: ${fullPath}`);
56
+ return null;
57
+ }
58
+ const content = readFileSync(fullPath, "utf8");
59
+ const frontmatterMatch = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n/);
60
+ if (!frontmatterMatch) {
61
+ console.warn(`Frontmatter not found in ${fullPath}`);
62
+ return null;
63
+ }
64
+ const frontmatterYaml = frontmatterMatch[1];
65
+ const frontmatter = parse(frontmatterYaml);
66
+ const sourceBasename = basename(slideDir);
67
+ const slideId = `${sourceBasename}/${slideName}`;
68
+ return {
69
+ id: slideId,
70
+ path: slideName,
71
+ fullPath,
72
+ sourceDir: slideDir,
73
+ frontmatter,
74
+ content: content.replace(frontmatterMatch[0], "")
75
+ };
76
+ } catch (error) {
77
+ console.error(`Error parsing frontmatter for ${slideName} in ${slideDir}:`, error);
78
+ return null;
79
+ }
80
+ }
81
+ function getAllSlidesFrontmatter() {
82
+ const config = loadConfig();
83
+ const slidesDirs = resolveSlidesDirs(config);
84
+ const slides = [];
85
+ for (const slidesDir of slidesDirs) {
86
+ if (!existsSync(slidesDir)) {
87
+ console.warn(`Slides directory not found: ${slidesDir}`);
88
+ continue;
89
+ }
90
+ try {
91
+ const slideDirs = readdirSync(slidesDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).filter((dirent) => !(config.exclude || []).includes(dirent.name)).map((dirent) => dirent.name);
92
+ for (const slideDir of slideDirs) {
93
+ const slideInfo = getSlideFrontmatterByPath(slidesDir, slideDir);
94
+ if (slideInfo) slides.push(slideInfo);
95
+ }
96
+ } catch (error) {
97
+ console.error(`Error reading slides directory ${slidesDir}:`, error);
98
+ }
99
+ }
100
+ return slides;
101
+ }
102
+ if (import.meta.url === `file://${process.argv[1]}`) {
103
+ const slides = getAllSlidesFrontmatter();
104
+ console.log(JSON.stringify(slides, null, 2));
105
+ }
106
+
107
+ //#endregion
108
+ //#region src/vite/plugin-slides.ts
109
+ function slidesPlugin() {
110
+ return {
111
+ name: "vite-plugin-slides",
112
+ configureServer(server) {
113
+ const watchers = [];
114
+ const config = loadConfig();
115
+ const slidesDirs = resolveSlidesDirs(config);
116
+ slidesDirs.forEach((slidesDir) => {
117
+ const watcher = watch(slidesDir, { recursive: true }, (eventType, filename) => {
118
+ if (filename && filename.endsWith("slides.md")) try {
119
+ const slides = getAllSlidesFrontmatter();
120
+ server.ws.send({
121
+ type: "custom",
122
+ event: "slides-updated",
123
+ data: slides
124
+ });
125
+ } catch (error) {
126
+ console.error("❌ Error reading slides frontmatter:", error);
127
+ }
128
+ });
129
+ watchers.push(watcher);
130
+ });
131
+ server.httpServer?.once("close", () => {
132
+ watchers.forEach((watcher) => watcher.close());
133
+ });
134
+ },
135
+ resolveId(id) {
136
+ if (id === "slidev:content") return id;
137
+ },
138
+ load(id) {
139
+ if (id === "slidev:content") try {
140
+ const slides = getAllSlidesFrontmatter();
141
+ return `export const slidesData = ${JSON.stringify(slides, null, 2)};
142
+ export default slidesData;`;
143
+ } catch (error) {
144
+ console.error("Error loading slides data:", error);
145
+ return `export const slidesData = [];
146
+ export default slidesData;`;
147
+ }
148
+ }
149
+ };
150
+ }
151
+
152
+ //#endregion
153
+ export { slidesPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slidev-workspace",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "A workspace tool for managing multiple Slidev presentations with API-based content management",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -27,6 +27,7 @@
27
27
  "types": "./dist/index.d.ts",
28
28
  "exports": {
29
29
  ".": "./dist/index.js",
30
+ "./vite": "./dist/plugin-slides.js",
30
31
  "./package.json": "./package.json",
31
32
  "./scripts": "./scripts"
32
33
  },
@@ -34,7 +35,7 @@
34
35
  "access": "public"
35
36
  },
36
37
  "dependencies": {
37
- "yaml": "^2.8.0",
38
+ "@tailwindcss/vite": "^4.1.11",
38
39
  "@vitejs/plugin-vue": "^6.0.0",
39
40
  "@vueuse/core": "^13.5.0",
40
41
  "class-variance-authority": "^0.7.1",
@@ -44,29 +45,24 @@
44
45
  "tw-animate-css": "^1.3.5",
45
46
  "vite": "npm:rolldown-vite@latest",
46
47
  "vue": "^3.5.17",
47
- "@tailwindcss/vite": "^4.1.11"
48
+ "yaml": "^2.8.0"
48
49
  },
49
50
  "devDependencies": {
50
- "tsdown": "^0.11.9",
51
- "typescript": "^5.8.3",
52
- "vitest": "^3.1.3",
53
- "vue-tsc": "^3.0.3",
51
+ "@prettier/plugin-oxc": "^0.0.4",
54
52
  "@tsconfig/node22": "^22.0.2",
55
53
  "@types/node": "^22.15.32",
56
- "@vue/eslint-config-prettier": "^10.2.0",
57
- "@vue/eslint-config-typescript": "^14.5.1",
58
54
  "@vue/tsconfig": "^0.7.0",
59
- "autoprefixer": "^10.4.21",
60
- "eslint": "^9.29.0",
61
- "eslint-plugin-oxlint": "~1.1.0",
62
- "eslint-plugin-vue": "~10.2.0",
63
55
  "jiti": "^2.4.2",
64
56
  "npm-run-all2": "^8.0.4",
65
57
  "oxlint": "~1.1.0",
66
58
  "postcss": "^8.5.6",
67
59
  "prettier": "3.5.3",
68
60
  "tailwindcss": "^4.1.11",
69
- "vite-plugin-vue-devtools": "^7.7.7"
61
+ "tsdown": "^0.11.9",
62
+ "typescript": "^5.8.3",
63
+ "vite-plugin-vue-devtools": "^7.7.7",
64
+ "vitest": "^3.1.3",
65
+ "vue-tsc": "^3.0.3"
70
66
  },
71
67
  "scripts": {
72
68
  "build": "tsdown",
@@ -74,7 +70,7 @@
74
70
  "dev:watch": "tsdown --watch",
75
71
  "test": "vitest",
76
72
  "typecheck": "vue-tsc --noEmit",
77
- "lint": "eslint . --fix",
73
+ "lint": "oxlint",
78
74
  "format": "prettier --write src/"
79
75
  }
80
76
  }
@@ -1,4 +1,4 @@
1
- @import 'tailwindcss';
1
+ @import "tailwindcss";
2
2
  @import "tw-animate-css";
3
3
 
4
4
  @custom-variant dark (&:is(.dark *));
@@ -1,5 +1,8 @@
1
1
  <template>
2
- <Card class="group hover:shadow-lg transition-all duration-200 cursor-pointer" @click="$emit('click')">
2
+ <Card
3
+ class="group hover:shadow-lg transition-all duration-200 cursor-pointer"
4
+ @click="$emit('click')"
5
+ >
3
6
  <div class="relative overflow-hidden rounded-t-lg">
4
7
  <img
5
8
  :src="image || '/placeholder.svg'"
@@ -9,24 +12,36 @@
9
12
  </div>
10
13
 
11
14
  <CardHeader class="pb-2">
12
- <CardTitle class="text-lg line-clamp-2 group-hover:text-primary transition-colors">
15
+ <CardTitle
16
+ class="text-lg line-clamp-2 group-hover:text-primary transition-colors"
17
+ >
13
18
  {{ title }}
14
19
  </CardTitle>
15
20
  </CardHeader>
16
21
 
17
22
  <CardContent class="space-y-3">
18
- <CardDescription class="line-clamp-3 text-sm h-[40px]">{{ description }}</CardDescription>
23
+ <CardDescription class="line-clamp-3 text-sm h-[40px]">{{
24
+ description
25
+ }}</CardDescription>
19
26
 
20
27
  <div class="flex flex-wrap gap-1 mb-2">
21
- <span v-if="theme" class="inline-flex items-center px-2 py-1 rounded-full text-xs bg-blue-100 text-blue-800">
28
+ <span
29
+ v-if="theme"
30
+ class="inline-flex items-center px-2 py-1 rounded-full text-xs bg-blue-100 text-blue-800"
31
+ >
22
32
  {{ theme }}
23
33
  </span>
24
- <span v-if="sourceDir" class="inline-flex items-center px-2 py-1 rounded-full text-xs bg-green-100 text-green-800">
25
- {{ sourceDir.split('/').pop() }}
34
+ <span
35
+ v-if="sourceDir"
36
+ class="inline-flex items-center px-2 py-1 rounded-full text-xs bg-green-100 text-green-800"
37
+ >
38
+ {{ sourceDir.split("/").pop() }}
26
39
  </span>
27
40
  </div>
28
41
 
29
- <div class="flex items-center justify-between text-xs text-muted-foreground pt-2 border-t">
42
+ <div
43
+ class="flex items-center justify-between text-xs text-muted-foreground pt-2 border-t"
44
+ >
30
45
  <div class="flex items-center gap-1">
31
46
  <User class="h-3 w-3" />
32
47
  <span>{{ author }}</span>
@@ -41,22 +56,28 @@
41
56
  </template>
42
57
 
43
58
  <script setup lang="ts">
44
- import { Calendar, User } from 'lucide-vue-next'
59
+ import { Calendar, User } from "lucide-vue-next";
45
60
 
46
- import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
61
+ import {
62
+ Card,
63
+ CardContent,
64
+ CardDescription,
65
+ CardHeader,
66
+ CardTitle,
67
+ } from "@/components/ui/card";
47
68
 
48
69
  defineProps<{
49
- title: string
50
- image?: string
51
- description?: string
52
- url: string
53
- author: string
54
- date: string
55
- theme?: string
56
- sourceDir?: string
57
- }>()
70
+ title: string;
71
+ image?: string;
72
+ description?: string;
73
+ url: string;
74
+ author: string;
75
+ date: string;
76
+ theme?: string;
77
+ sourceDir?: string;
78
+ }>();
58
79
 
59
80
  defineEmits<{
60
- click: []
61
- }>()
81
+ click: [];
82
+ }>();
62
83
  </script>
@@ -47,13 +47,6 @@
47
47
  />
48
48
  </div>
49
49
  </div>
50
-
51
- <!-- Slide Detail Modal -->
52
- <SlideDetail
53
- v-if="selectedSlide"
54
- :slide="selectedSlide"
55
- @close="closeSlide"
56
- />
57
50
  </div>
58
51
  </template>
59
52
 
@@ -62,27 +55,25 @@ import { ref, computed } from "vue";
62
55
  import { useSlides } from "../composables/useSlides";
63
56
  import { Input } from "../components/ui/input";
64
57
  import SlideCard from "./SlideCard.vue";
65
- import SlideDetail from "./SlideDetail.vue";
58
+ import type { SlideData } from "../../types/slide";
66
59
 
67
60
  const searchTerm = ref("");
68
61
  const { slides, slidesCount } = useSlides();
69
62
 
70
63
  const filteredSlides = computed(() => {
71
64
  if (!searchTerm.value) return slides.value;
72
- return slides.value.filter((slide) =>
73
- slide.title.toLowerCase().includes(searchTerm.value.toLowerCase()) ||
74
- slide.description.toLowerCase().includes(searchTerm.value.toLowerCase()) ||
75
- slide.author.toLowerCase().includes(searchTerm.value.toLowerCase())
65
+ return slides.value.filter(
66
+ (slide) =>
67
+ slide.title.toLowerCase().includes(searchTerm.value.toLowerCase()) ||
68
+ slide.description
69
+ .toLowerCase()
70
+ .includes(searchTerm.value.toLowerCase()) ||
71
+ slide.author.toLowerCase().includes(searchTerm.value.toLowerCase()),
76
72
  );
77
73
  });
78
74
 
79
- const selectedSlide = ref(null);
80
-
81
- const openSlide = (slide: any) => {
82
- selectedSlide.value = slide;
83
- };
84
-
85
- const closeSlide = () => {
86
- selectedSlide.value = null;
75
+ const openSlide = (slide: SlideData) => {
76
+ const url = `${window.location.href}/${slide.url}`;
77
+ window.open(url, "_blank");
87
78
  };
88
79
  </script>
@@ -14,8 +14,8 @@ import type { VariantProps } from "class-variance-authority";
14
14
 
15
15
  interface Props {
16
16
  as?: string;
17
- variant?: VariantProps<typeof buttonVariants>['variant'];
18
- size?: VariantProps<typeof buttonVariants>['size'];
17
+ variant?: VariantProps<typeof buttonVariants>["variant"];
18
+ size?: VariantProps<typeof buttonVariants>["size"];
19
19
  }
20
20
 
21
21
  const props = withDefaults(defineProps<Props>(), {
@@ -26,7 +26,7 @@ export const buttonVariants = cva(
26
26
  variant: "default",
27
27
  size: "default",
28
28
  },
29
- }
29
+ },
30
30
  );
31
31
 
32
32
  export type ButtonVariants = VariantProps<typeof buttonVariants>;