@fnd-platform/cms 1.0.0-alpha.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/LICENSE +21 -0
- package/README.md +283 -0
- package/lib/cms-project.d.ts +127 -0
- package/lib/cms-project.d.ts.map +1 -0
- package/lib/cms-project.js +343 -0
- package/lib/cms-project.js.map +1 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +20 -0
- package/lib/index.js.map +1 -0
- package/lib/options.d.ts +59 -0
- package/lib/options.d.ts.map +1 -0
- package/lib/options.js +3 -0
- package/lib/options.js.map +1 -0
- package/lib/templates/admin-breadcrumbs.d.ts +13 -0
- package/lib/templates/admin-breadcrumbs.d.ts.map +1 -0
- package/lib/templates/admin-breadcrumbs.js +80 -0
- package/lib/templates/admin-breadcrumbs.js.map +1 -0
- package/lib/templates/admin-content-route.d.ts +18 -0
- package/lib/templates/admin-content-route.d.ts.map +1 -0
- package/lib/templates/admin-content-route.js +100 -0
- package/lib/templates/admin-content-route.js.map +1 -0
- package/lib/templates/admin-content-type-route.d.ts +9 -0
- package/lib/templates/admin-content-type-route.d.ts.map +1 -0
- package/lib/templates/admin-content-type-route.js +96 -0
- package/lib/templates/admin-content-type-route.js.map +1 -0
- package/lib/templates/admin-header.d.ts +13 -0
- package/lib/templates/admin-header.d.ts.map +1 -0
- package/lib/templates/admin-header.js +123 -0
- package/lib/templates/admin-header.js.map +1 -0
- package/lib/templates/admin-index.d.ts +9 -0
- package/lib/templates/admin-index.d.ts.map +1 -0
- package/lib/templates/admin-index.js +60 -0
- package/lib/templates/admin-index.js.map +1 -0
- package/lib/templates/admin-layout.d.ts +10 -0
- package/lib/templates/admin-layout.d.ts.map +1 -0
- package/lib/templates/admin-layout.js +46 -0
- package/lib/templates/admin-layout.js.map +1 -0
- package/lib/templates/admin-sidebar.d.ts +13 -0
- package/lib/templates/admin-sidebar.d.ts.map +1 -0
- package/lib/templates/admin-sidebar.js +149 -0
- package/lib/templates/admin-sidebar.js.map +1 -0
- package/lib/templates/content-editor.d.ts +10 -0
- package/lib/templates/content-editor.d.ts.map +1 -0
- package/lib/templates/content-editor.js +354 -0
- package/lib/templates/content-editor.js.map +1 -0
- package/lib/templates/content-schema.d.ts +10 -0
- package/lib/templates/content-schema.d.ts.map +1 -0
- package/lib/templates/content-schema.js +274 -0
- package/lib/templates/content-schema.js.map +1 -0
- package/lib/templates/content-table.d.ts +13 -0
- package/lib/templates/content-table.d.ts.map +1 -0
- package/lib/templates/content-table.js +177 -0
- package/lib/templates/content-table.js.map +1 -0
- package/lib/templates/content-types-examples.d.ts +19 -0
- package/lib/templates/content-types-examples.d.ts.map +1 -0
- package/lib/templates/content-types-examples.js +275 -0
- package/lib/templates/content-types-examples.js.map +1 -0
- package/lib/templates/content-types-registry.d.ts +10 -0
- package/lib/templates/content-types-registry.d.ts.map +1 -0
- package/lib/templates/content-types-registry.js +87 -0
- package/lib/templates/content-types-registry.js.map +1 -0
- package/lib/templates/content-types.d.ts +10 -0
- package/lib/templates/content-types.d.ts.map +1 -0
- package/lib/templates/content-types.js +384 -0
- package/lib/templates/content-types.js.map +1 -0
- package/lib/templates/dashboard-stats.d.ts +13 -0
- package/lib/templates/dashboard-stats.d.ts.map +1 -0
- package/lib/templates/dashboard-stats.js +117 -0
- package/lib/templates/dashboard-stats.js.map +1 -0
- package/lib/templates/editor/index.d.ts +6 -0
- package/lib/templates/editor/index.d.ts.map +1 -0
- package/lib/templates/editor/index.js +21 -0
- package/lib/templates/editor/index.js.map +1 -0
- package/lib/templates/editor/rich-text-editor.d.ts +7 -0
- package/lib/templates/editor/rich-text-editor.d.ts.map +1 -0
- package/lib/templates/editor/rich-text-editor.js +115 -0
- package/lib/templates/editor/rich-text-editor.js.map +1 -0
- package/lib/templates/editor/toolbar.d.ts +7 -0
- package/lib/templates/editor/toolbar.d.ts.map +1 -0
- package/lib/templates/editor/toolbar.js +272 -0
- package/lib/templates/editor/toolbar.js.map +1 -0
- package/lib/templates/form-fields/boolean-field.d.ts +7 -0
- package/lib/templates/form-fields/boolean-field.d.ts.map +1 -0
- package/lib/templates/form-fields/boolean-field.js +76 -0
- package/lib/templates/form-fields/boolean-field.js.map +1 -0
- package/lib/templates/form-fields/date-field.d.ts +7 -0
- package/lib/templates/form-fields/date-field.d.ts.map +1 -0
- package/lib/templates/form-fields/date-field.js +61 -0
- package/lib/templates/form-fields/date-field.js.map +1 -0
- package/lib/templates/form-fields/datetime-field.d.ts +7 -0
- package/lib/templates/form-fields/datetime-field.d.ts.map +1 -0
- package/lib/templates/form-fields/datetime-field.js +87 -0
- package/lib/templates/form-fields/datetime-field.js.map +1 -0
- package/lib/templates/form-fields/index.d.ts +23 -0
- package/lib/templates/form-fields/index.d.ts.map +1 -0
- package/lib/templates/form-fields/index.js +275 -0
- package/lib/templates/form-fields/index.js.map +1 -0
- package/lib/templates/form-fields/media-field.d.ts +10 -0
- package/lib/templates/form-fields/media-field.d.ts.map +1 -0
- package/lib/templates/form-fields/media-field.js +225 -0
- package/lib/templates/form-fields/media-field.js.map +1 -0
- package/lib/templates/form-fields/multiselect-field.d.ts +7 -0
- package/lib/templates/form-fields/multiselect-field.d.ts.map +1 -0
- package/lib/templates/form-fields/multiselect-field.js +121 -0
- package/lib/templates/form-fields/multiselect-field.js.map +1 -0
- package/lib/templates/form-fields/number-field.d.ts +7 -0
- package/lib/templates/form-fields/number-field.d.ts.map +1 -0
- package/lib/templates/form-fields/number-field.js +87 -0
- package/lib/templates/form-fields/number-field.js.map +1 -0
- package/lib/templates/form-fields/reference-field.d.ts +9 -0
- package/lib/templates/form-fields/reference-field.d.ts.map +1 -0
- package/lib/templates/form-fields/reference-field.js +145 -0
- package/lib/templates/form-fields/reference-field.js.map +1 -0
- package/lib/templates/form-fields/richtext-field.d.ts +9 -0
- package/lib/templates/form-fields/richtext-field.d.ts.map +1 -0
- package/lib/templates/form-fields/richtext-field.js +60 -0
- package/lib/templates/form-fields/richtext-field.js.map +1 -0
- package/lib/templates/form-fields/select-field.d.ts +7 -0
- package/lib/templates/form-fields/select-field.d.ts.map +1 -0
- package/lib/templates/form-fields/select-field.js +70 -0
- package/lib/templates/form-fields/select-field.js.map +1 -0
- package/lib/templates/form-fields/slug-field.d.ts +7 -0
- package/lib/templates/form-fields/slug-field.d.ts.map +1 -0
- package/lib/templates/form-fields/slug-field.js +143 -0
- package/lib/templates/form-fields/slug-field.js.map +1 -0
- package/lib/templates/form-fields/tags-field.d.ts +7 -0
- package/lib/templates/form-fields/tags-field.d.ts.map +1 -0
- package/lib/templates/form-fields/tags-field.js +172 -0
- package/lib/templates/form-fields/tags-field.js.map +1 -0
- package/lib/templates/form-fields/text-field.d.ts +7 -0
- package/lib/templates/form-fields/text-field.d.ts.map +1 -0
- package/lib/templates/form-fields/text-field.js +63 -0
- package/lib/templates/form-fields/text-field.js.map +1 -0
- package/lib/templates/form-fields/textarea-field.d.ts +7 -0
- package/lib/templates/form-fields/textarea-field.d.ts.map +1 -0
- package/lib/templates/form-fields/textarea-field.js +64 -0
- package/lib/templates/form-fields/textarea-field.js.map +1 -0
- package/lib/templates/index.d.ts +34 -0
- package/lib/templates/index.d.ts.map +1 -0
- package/lib/templates/index.js +92 -0
- package/lib/templates/index.js.map +1 -0
- package/lib/templates/media/index.d.ts +12 -0
- package/lib/templates/media/index.d.ts.map +1 -0
- package/lib/templates/media/index.js +50 -0
- package/lib/templates/media/index.js.map +1 -0
- package/lib/templates/media/media-api.d.ts +13 -0
- package/lib/templates/media/media-api.d.ts.map +1 -0
- package/lib/templates/media/media-api.js +274 -0
- package/lib/templates/media/media-api.js.map +1 -0
- package/lib/templates/media/media-grid.d.ts +14 -0
- package/lib/templates/media/media-grid.d.ts.map +1 -0
- package/lib/templates/media/media-grid.js +314 -0
- package/lib/templates/media/media-grid.js.map +1 -0
- package/lib/templates/media/media-library-route.d.ts +13 -0
- package/lib/templates/media/media-library-route.d.ts.map +1 -0
- package/lib/templates/media/media-library-route.js +105 -0
- package/lib/templates/media/media-library-route.js.map +1 -0
- package/lib/templates/media/media-picker.d.ts +13 -0
- package/lib/templates/media/media-picker.d.ts.map +1 -0
- package/lib/templates/media/media-picker.js +152 -0
- package/lib/templates/media/media-picker.js.map +1 -0
- package/lib/templates/media/media-uploader.d.ts +14 -0
- package/lib/templates/media/media-uploader.d.ts.map +1 -0
- package/lib/templates/media/media-uploader.js +318 -0
- package/lib/templates/media/media-uploader.js.map +1 -0
- package/lib/templates/recent-content.d.ts +13 -0
- package/lib/templates/recent-content.d.ts.map +1 -0
- package/lib/templates/recent-content.js +138 -0
- package/lib/templates/recent-content.js.map +1 -0
- package/lib/templates/slug-utils.d.ts +10 -0
- package/lib/templates/slug-utils.d.ts.map +1 -0
- package/lib/templates/slug-utils.js +194 -0
- package/lib/templates/slug-utils.js.map +1 -0
- package/lib/templates/ui-avatar.d.ts +8 -0
- package/lib/templates/ui-avatar.d.ts.map +1 -0
- package/lib/templates/ui-avatar.js +60 -0
- package/lib/templates/ui-avatar.js.map +1 -0
- package/lib/templates/ui-badge.d.ts +8 -0
- package/lib/templates/ui-badge.d.ts.map +1 -0
- package/lib/templates/ui-badge.js +52 -0
- package/lib/templates/ui-badge.js.map +1 -0
- package/lib/templates/ui-dialog.d.ts +10 -0
- package/lib/templates/ui-dialog.d.ts.map +1 -0
- package/lib/templates/ui-dialog.js +134 -0
- package/lib/templates/ui-dialog.js.map +1 -0
- package/lib/templates/ui-dropdown-menu.d.ts +8 -0
- package/lib/templates/ui-dropdown-menu.d.ts.map +1 -0
- package/lib/templates/ui-dropdown-menu.js +210 -0
- package/lib/templates/ui-dropdown-menu.js.map +1 -0
- package/lib/templates/ui-popover.d.ts +8 -0
- package/lib/templates/ui-popover.d.ts.map +1 -0
- package/lib/templates/ui-popover.js +43 -0
- package/lib/templates/ui-popover.js.map +1 -0
- package/lib/templates/ui-progress.d.ts +10 -0
- package/lib/templates/ui-progress.d.ts.map +1 -0
- package/lib/templates/ui-progress.js +40 -0
- package/lib/templates/ui-progress.js.map +1 -0
- package/lib/templates/ui-table.d.ts +8 -0
- package/lib/templates/ui-table.d.ts.map +1 -0
- package/lib/templates/ui-table.js +129 -0
- package/lib/templates/ui-table.js.map +1 -0
- package/lib/templates/ui-tabs.d.ts +10 -0
- package/lib/templates/ui-tabs.d.ts.map +1 -0
- package/lib/templates/ui-tabs.js +67 -0
- package/lib/templates/ui-tabs.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.getRecentContentTemplate = getRecentContentTemplate;
|
|
4
|
+
/**
|
|
5
|
+
* Generates the recent content component template.
|
|
6
|
+
*
|
|
7
|
+
* This component displays:
|
|
8
|
+
* - List of recently updated content items
|
|
9
|
+
* - Status badges
|
|
10
|
+
* - Content type labels
|
|
11
|
+
* - Time since last update
|
|
12
|
+
*
|
|
13
|
+
* @returns Template string for app/components/admin/recent-content.tsx
|
|
14
|
+
*/
|
|
15
|
+
function getRecentContentTemplate() {
|
|
16
|
+
return `import { Link } from '@remix-run/react';
|
|
17
|
+
import { FileText } from 'lucide-react';
|
|
18
|
+
import { Card, CardContent, CardHeader, CardTitle } from '~/components/ui/card';
|
|
19
|
+
import { Badge } from '~/components/ui/badge';
|
|
20
|
+
|
|
21
|
+
export interface ContentItem {
|
|
22
|
+
id: string;
|
|
23
|
+
title: string;
|
|
24
|
+
type: string;
|
|
25
|
+
typeLabel: string;
|
|
26
|
+
status: 'draft' | 'published' | 'scheduled' | 'archived';
|
|
27
|
+
updatedAt: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface RecentContentProps {
|
|
31
|
+
items: ContentItem[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function getStatusBadgeVariant(
|
|
35
|
+
status: string
|
|
36
|
+
): 'default' | 'secondary' | 'success' | 'warning' | 'outline' {
|
|
37
|
+
switch (status) {
|
|
38
|
+
case 'published':
|
|
39
|
+
return 'success';
|
|
40
|
+
case 'draft':
|
|
41
|
+
return 'secondary';
|
|
42
|
+
case 'scheduled':
|
|
43
|
+
return 'warning';
|
|
44
|
+
case 'archived':
|
|
45
|
+
return 'outline';
|
|
46
|
+
default:
|
|
47
|
+
return 'default';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function formatRelativeTime(dateString: string): string {
|
|
52
|
+
const date = new Date(dateString);
|
|
53
|
+
const now = new Date();
|
|
54
|
+
const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);
|
|
55
|
+
|
|
56
|
+
if (diffInSeconds < 60) {
|
|
57
|
+
return 'Just now';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const diffInMinutes = Math.floor(diffInSeconds / 60);
|
|
61
|
+
if (diffInMinutes < 60) {
|
|
62
|
+
return \`\${diffInMinutes} minute\${diffInMinutes !== 1 ? 's' : ''} ago\`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const diffInHours = Math.floor(diffInMinutes / 60);
|
|
66
|
+
if (diffInHours < 24) {
|
|
67
|
+
return \`\${diffInHours} hour\${diffInHours !== 1 ? 's' : ''} ago\`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const diffInDays = Math.floor(diffInHours / 24);
|
|
71
|
+
if (diffInDays < 7) {
|
|
72
|
+
return \`\${diffInDays} day\${diffInDays !== 1 ? 's' : ''} ago\`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return date.toLocaleDateString();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function RecentContent({ items }: RecentContentProps) {
|
|
79
|
+
if (items.length === 0) {
|
|
80
|
+
return (
|
|
81
|
+
<Card>
|
|
82
|
+
<CardHeader>
|
|
83
|
+
<CardTitle className="text-lg">Recent Content</CardTitle>
|
|
84
|
+
</CardHeader>
|
|
85
|
+
<CardContent>
|
|
86
|
+
<div className="flex flex-col items-center justify-center py-8 text-center">
|
|
87
|
+
<FileText className="h-12 w-12 text-muted-foreground/50" />
|
|
88
|
+
<p className="mt-4 text-sm text-muted-foreground">
|
|
89
|
+
No content yet. Create your first content item to get started.
|
|
90
|
+
</p>
|
|
91
|
+
</div>
|
|
92
|
+
</CardContent>
|
|
93
|
+
</Card>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<Card>
|
|
99
|
+
<CardHeader>
|
|
100
|
+
<CardTitle className="text-lg">Recent Content</CardTitle>
|
|
101
|
+
</CardHeader>
|
|
102
|
+
<CardContent>
|
|
103
|
+
<div className="space-y-4">
|
|
104
|
+
{items.map((item) => (
|
|
105
|
+
<div
|
|
106
|
+
key={item.id}
|
|
107
|
+
className="flex items-center justify-between rounded-lg border p-3 transition-colors hover:bg-muted/50"
|
|
108
|
+
>
|
|
109
|
+
<div className="flex items-center gap-3 min-w-0">
|
|
110
|
+
<FileText className="h-5 w-5 shrink-0 text-muted-foreground" />
|
|
111
|
+
<div className="min-w-0">
|
|
112
|
+
<Link
|
|
113
|
+
to={\`/admin/content/\${item.type}/\${item.id}\`}
|
|
114
|
+
className="block truncate font-medium hover:underline"
|
|
115
|
+
>
|
|
116
|
+
{item.title}
|
|
117
|
+
</Link>
|
|
118
|
+
<p className="text-xs text-muted-foreground">
|
|
119
|
+
{item.typeLabel} · {formatRelativeTime(item.updatedAt)}
|
|
120
|
+
</p>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
<Badge
|
|
124
|
+
variant={getStatusBadgeVariant(item.status)}
|
|
125
|
+
className="shrink-0 capitalize"
|
|
126
|
+
>
|
|
127
|
+
{item.status}
|
|
128
|
+
</Badge>
|
|
129
|
+
</div>
|
|
130
|
+
))}
|
|
131
|
+
</div>
|
|
132
|
+
</CardContent>
|
|
133
|
+
</Card>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
`;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=recent-content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recent-content.js","sourceRoot":"","sources":["../../src/templates/recent-content.ts"],"names":[],"mappings":";;AAWA,4DA0HC;AArID;;;;;;;;;;GAUG;AACH,SAAgB,wBAAwB;IACtC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwHR,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates the slug utilities template.
|
|
3
|
+
*
|
|
4
|
+
* This template provides utilities for generating URL-friendly slugs
|
|
5
|
+
* from text content.
|
|
6
|
+
*
|
|
7
|
+
* @returns Template string for app/lib/slug-utils.ts
|
|
8
|
+
*/
|
|
9
|
+
export declare function getSlugUtilsTemplate(): string;
|
|
10
|
+
//# sourceMappingURL=slug-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug-utils.d.ts","sourceRoot":"","sources":["../../src/templates/slug-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAqL7C"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.getSlugUtilsTemplate = getSlugUtilsTemplate;
|
|
4
|
+
/**
|
|
5
|
+
* Generates the slug utilities template.
|
|
6
|
+
*
|
|
7
|
+
* This template provides utilities for generating URL-friendly slugs
|
|
8
|
+
* from text content.
|
|
9
|
+
*
|
|
10
|
+
* @returns Template string for app/lib/slug-utils.ts
|
|
11
|
+
*/
|
|
12
|
+
function getSlugUtilsTemplate() {
|
|
13
|
+
return `/**
|
|
14
|
+
* Slug Utilities
|
|
15
|
+
*
|
|
16
|
+
* Utilities for generating URL-friendly slugs from text content.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Options for slug generation.
|
|
21
|
+
*/
|
|
22
|
+
export interface SlugOptions {
|
|
23
|
+
/** Maximum length for the slug */
|
|
24
|
+
maxLength?: number;
|
|
25
|
+
/** Replace spaces with this character (default: '-') */
|
|
26
|
+
separator?: string;
|
|
27
|
+
/** Convert to lowercase (default: true) */
|
|
28
|
+
lowercase?: boolean;
|
|
29
|
+
/** Remove stop words like 'a', 'the', 'is' (default: false) */
|
|
30
|
+
removeStopWords?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Common stop words to optionally remove from slugs.
|
|
35
|
+
*/
|
|
36
|
+
const STOP_WORDS = new Set([
|
|
37
|
+
'a', 'an', 'and', 'are', 'as', 'at', 'be', 'by', 'for',
|
|
38
|
+
'from', 'has', 'he', 'in', 'is', 'it', 'its', 'of', 'on',
|
|
39
|
+
'that', 'the', 'to', 'was', 'were', 'will', 'with',
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Character replacements for common diacritics and special characters.
|
|
44
|
+
*/
|
|
45
|
+
const CHAR_REPLACEMENTS: Record<string, string> = {
|
|
46
|
+
// Latin Extended
|
|
47
|
+
'à': 'a', 'á': 'a', 'â': 'a', 'ã': 'a', 'ä': 'a', 'å': 'a', 'æ': 'ae',
|
|
48
|
+
'ç': 'c', 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e',
|
|
49
|
+
'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i',
|
|
50
|
+
'ð': 'd', 'ñ': 'n',
|
|
51
|
+
'ò': 'o', 'ó': 'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', 'ø': 'o',
|
|
52
|
+
'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u',
|
|
53
|
+
'ý': 'y', 'þ': 'th', 'ÿ': 'y',
|
|
54
|
+
// Special characters
|
|
55
|
+
'&': 'and',
|
|
56
|
+
'@': 'at',
|
|
57
|
+
// Currencies
|
|
58
|
+
'$': 'dollar',
|
|
59
|
+
'€': 'euro',
|
|
60
|
+
'£': 'pound',
|
|
61
|
+
'¥': 'yen',
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Generate a URL-friendly slug from text.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* \`\`\`typescript
|
|
69
|
+
* generateSlug('Hello World!'); // 'hello-world'
|
|
70
|
+
* generateSlug('My Blog Post Title', { maxLength: 20 }); // 'my-blog-post-title'
|
|
71
|
+
* generateSlug('Café & Restaurant'); // 'cafe-and-restaurant'
|
|
72
|
+
* \`\`\`
|
|
73
|
+
*/
|
|
74
|
+
export function generateSlug(text: string, options: SlugOptions = {}): string {
|
|
75
|
+
const {
|
|
76
|
+
maxLength = 100,
|
|
77
|
+
separator = '-',
|
|
78
|
+
lowercase = true,
|
|
79
|
+
removeStopWords = false,
|
|
80
|
+
} = options;
|
|
81
|
+
|
|
82
|
+
if (!text || typeof text !== 'string') {
|
|
83
|
+
return '';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
let slug = text;
|
|
87
|
+
|
|
88
|
+
// Convert to lowercase if requested
|
|
89
|
+
if (lowercase) {
|
|
90
|
+
slug = slug.toLowerCase();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Replace special characters
|
|
94
|
+
slug = slug
|
|
95
|
+
.split('')
|
|
96
|
+
.map((char) => CHAR_REPLACEMENTS[char] ?? char)
|
|
97
|
+
.join('');
|
|
98
|
+
|
|
99
|
+
// Remove HTML tags
|
|
100
|
+
slug = slug.replace(/<[^>]*>/g, '');
|
|
101
|
+
|
|
102
|
+
// Replace non-alphanumeric characters with separator
|
|
103
|
+
slug = slug.replace(/[^a-z0-9]+/gi, separator);
|
|
104
|
+
|
|
105
|
+
// Optionally remove stop words
|
|
106
|
+
if (removeStopWords) {
|
|
107
|
+
const words = slug.split(separator).filter((word) => !STOP_WORDS.has(word));
|
|
108
|
+
slug = words.join(separator);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Remove leading/trailing separators
|
|
112
|
+
slug = slug.replace(new RegExp(\`^\${separator}+|\${separator}+$\`, 'g'), '');
|
|
113
|
+
|
|
114
|
+
// Collapse multiple separators
|
|
115
|
+
slug = slug.replace(new RegExp(\`\${separator}+\`, 'g'), separator);
|
|
116
|
+
|
|
117
|
+
// Enforce max length (trim at word boundary if possible)
|
|
118
|
+
if (maxLength && slug.length > maxLength) {
|
|
119
|
+
slug = slug.substring(0, maxLength);
|
|
120
|
+
const lastSeparator = slug.lastIndexOf(separator);
|
|
121
|
+
if (lastSeparator > maxLength / 2) {
|
|
122
|
+
slug = slug.substring(0, lastSeparator);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Final cleanup
|
|
127
|
+
slug = slug.replace(new RegExp(\`\${separator}+$\`, 'g'), '');
|
|
128
|
+
|
|
129
|
+
return slug;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Validate a slug format.
|
|
134
|
+
*
|
|
135
|
+
* Valid slugs:
|
|
136
|
+
* - Contain only lowercase letters, numbers, and hyphens
|
|
137
|
+
* - Don't start or end with hyphens
|
|
138
|
+
* - Don't contain consecutive hyphens
|
|
139
|
+
*/
|
|
140
|
+
export function isValidSlug(slug: string): boolean {
|
|
141
|
+
if (!slug || typeof slug !== 'string') {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Check pattern
|
|
146
|
+
const validPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
147
|
+
return validPattern.test(slug);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Normalize a slug to ensure it's valid.
|
|
152
|
+
* If the input is already a valid slug, it's returned unchanged.
|
|
153
|
+
* Otherwise, it's transformed using generateSlug.
|
|
154
|
+
*/
|
|
155
|
+
export function normalizeSlug(input: string): string {
|
|
156
|
+
if (isValidSlug(input)) {
|
|
157
|
+
return input;
|
|
158
|
+
}
|
|
159
|
+
return generateSlug(input);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Generate a unique slug by appending a number if needed.
|
|
164
|
+
*
|
|
165
|
+
* @param baseSlug - The desired slug
|
|
166
|
+
* @param existingSlugs - Array of slugs that already exist
|
|
167
|
+
* @returns A unique slug
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* \`\`\`typescript
|
|
171
|
+
* ensureUniqueSlug('my-post', ['my-post', 'my-post-2']);
|
|
172
|
+
* // Returns 'my-post-3'
|
|
173
|
+
* \`\`\`
|
|
174
|
+
*/
|
|
175
|
+
export function ensureUniqueSlug(baseSlug: string, existingSlugs: string[]): string {
|
|
176
|
+
const slugSet = new Set(existingSlugs);
|
|
177
|
+
|
|
178
|
+
if (!slugSet.has(baseSlug)) {
|
|
179
|
+
return baseSlug;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
let counter = 2;
|
|
183
|
+
let candidateSlug = \`\${baseSlug}-\${counter}\`;
|
|
184
|
+
|
|
185
|
+
while (slugSet.has(candidateSlug)) {
|
|
186
|
+
counter++;
|
|
187
|
+
candidateSlug = \`\${baseSlug}-\${counter}\`;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return candidateSlug;
|
|
191
|
+
}
|
|
192
|
+
`;
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=slug-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug-utils.js","sourceRoot":"","sources":["../../src/templates/slug-utils.ts"],"names":[],"mappings":";;AAQA,oDAqLC;AA7LD;;;;;;;GAOG;AACH,SAAgB,oBAAoB;IAClC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmLR,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates the Avatar component file content.
|
|
3
|
+
* Standard shadcn/ui avatar with Radix UI primitives.
|
|
4
|
+
*
|
|
5
|
+
* @returns app/components/ui/avatar.tsx file content
|
|
6
|
+
*/
|
|
7
|
+
export declare function getAvatarTemplate(): string;
|
|
8
|
+
//# sourceMappingURL=ui-avatar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-avatar.d.ts","sourceRoot":"","sources":["../../src/templates/ui-avatar.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAiD1C"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.getAvatarTemplate = getAvatarTemplate;
|
|
4
|
+
/**
|
|
5
|
+
* Generates the Avatar component file content.
|
|
6
|
+
* Standard shadcn/ui avatar with Radix UI primitives.
|
|
7
|
+
*
|
|
8
|
+
* @returns app/components/ui/avatar.tsx file content
|
|
9
|
+
*/
|
|
10
|
+
function getAvatarTemplate() {
|
|
11
|
+
return `import * as React from 'react';
|
|
12
|
+
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
|
13
|
+
import { cn } from '~/lib/utils';
|
|
14
|
+
|
|
15
|
+
const Avatar = React.forwardRef<
|
|
16
|
+
React.ElementRef<typeof AvatarPrimitive.Root>,
|
|
17
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
|
|
18
|
+
>(({ className, ...props }, ref) => (
|
|
19
|
+
<AvatarPrimitive.Root
|
|
20
|
+
ref={ref}
|
|
21
|
+
className={cn(
|
|
22
|
+
'relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full',
|
|
23
|
+
className
|
|
24
|
+
)}
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
));
|
|
28
|
+
Avatar.displayName = AvatarPrimitive.Root.displayName;
|
|
29
|
+
|
|
30
|
+
const AvatarImage = React.forwardRef<
|
|
31
|
+
React.ElementRef<typeof AvatarPrimitive.Image>,
|
|
32
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
|
|
33
|
+
>(({ className, ...props }, ref) => (
|
|
34
|
+
<AvatarPrimitive.Image
|
|
35
|
+
ref={ref}
|
|
36
|
+
className={cn('aspect-square h-full w-full', className)}
|
|
37
|
+
{...props}
|
|
38
|
+
/>
|
|
39
|
+
));
|
|
40
|
+
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
|
|
41
|
+
|
|
42
|
+
const AvatarFallback = React.forwardRef<
|
|
43
|
+
React.ElementRef<typeof AvatarPrimitive.Fallback>,
|
|
44
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
|
|
45
|
+
>(({ className, ...props }, ref) => (
|
|
46
|
+
<AvatarPrimitive.Fallback
|
|
47
|
+
ref={ref}
|
|
48
|
+
className={cn(
|
|
49
|
+
'flex h-full w-full items-center justify-center rounded-full bg-muted',
|
|
50
|
+
className
|
|
51
|
+
)}
|
|
52
|
+
{...props}
|
|
53
|
+
/>
|
|
54
|
+
));
|
|
55
|
+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
|
|
56
|
+
|
|
57
|
+
export { Avatar, AvatarImage, AvatarFallback };
|
|
58
|
+
`;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=ui-avatar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-avatar.js","sourceRoot":"","sources":["../../src/templates/ui-avatar.ts"],"names":[],"mappings":";;AAMA,8CAiDC;AAvDD;;;;;GAKG;AACH,SAAgB,iBAAiB;IAC/B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+CR,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates the Badge component file content.
|
|
3
|
+
* Standard shadcn/ui badge with variants for status display.
|
|
4
|
+
*
|
|
5
|
+
* @returns app/components/ui/badge.tsx file content
|
|
6
|
+
*/
|
|
7
|
+
export declare function getBadgeTemplate(): string;
|
|
8
|
+
//# sourceMappingURL=ui-badge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-badge.d.ts","sourceRoot":"","sources":["../../src/templates/ui-badge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAyCzC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.getBadgeTemplate = getBadgeTemplate;
|
|
4
|
+
/**
|
|
5
|
+
* Generates the Badge component file content.
|
|
6
|
+
* Standard shadcn/ui badge with variants for status display.
|
|
7
|
+
*
|
|
8
|
+
* @returns app/components/ui/badge.tsx file content
|
|
9
|
+
*/
|
|
10
|
+
function getBadgeTemplate() {
|
|
11
|
+
return `import * as React from 'react';
|
|
12
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
13
|
+
import { cn } from '~/lib/utils';
|
|
14
|
+
|
|
15
|
+
const badgeVariants = cva(
|
|
16
|
+
'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
|
|
17
|
+
{
|
|
18
|
+
variants: {
|
|
19
|
+
variant: {
|
|
20
|
+
default:
|
|
21
|
+
'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
|
|
22
|
+
secondary:
|
|
23
|
+
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
|
24
|
+
destructive:
|
|
25
|
+
'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
|
|
26
|
+
outline: 'text-foreground',
|
|
27
|
+
success:
|
|
28
|
+
'border-transparent bg-green-500 text-white hover:bg-green-500/80',
|
|
29
|
+
warning:
|
|
30
|
+
'border-transparent bg-yellow-500 text-white hover:bg-yellow-500/80',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
defaultVariants: {
|
|
34
|
+
variant: 'default',
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
export interface BadgeProps
|
|
40
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
41
|
+
VariantProps<typeof badgeVariants> {}
|
|
42
|
+
|
|
43
|
+
function Badge({ className, variant, ...props }: BadgeProps) {
|
|
44
|
+
return (
|
|
45
|
+
<div className={cn(badgeVariants({ variant }), className)} {...props} />
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { Badge, badgeVariants };
|
|
50
|
+
`;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=ui-badge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-badge.js","sourceRoot":"","sources":["../../src/templates/ui-badge.ts"],"names":[],"mappings":";;AAMA,4CAyCC;AA/CD;;;;;GAKG;AACH,SAAgB,gBAAgB;IAC9B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuCR,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates the Dialog component template.
|
|
3
|
+
*
|
|
4
|
+
* This is a shadcn/ui-style dialog component based on Radix Dialog
|
|
5
|
+
* primitives, used for the media picker and other modal interactions.
|
|
6
|
+
*
|
|
7
|
+
* @returns Template string for app/components/ui/dialog.tsx
|
|
8
|
+
*/
|
|
9
|
+
export declare function getDialogTemplate(): string;
|
|
10
|
+
//# sourceMappingURL=ui-dialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-dialog.d.ts","sourceRoot":"","sources":["../../src/templates/ui-dialog.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAyH1C"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.getDialogTemplate = getDialogTemplate;
|
|
4
|
+
/**
|
|
5
|
+
* Generates the Dialog component template.
|
|
6
|
+
*
|
|
7
|
+
* This is a shadcn/ui-style dialog component based on Radix Dialog
|
|
8
|
+
* primitives, used for the media picker and other modal interactions.
|
|
9
|
+
*
|
|
10
|
+
* @returns Template string for app/components/ui/dialog.tsx
|
|
11
|
+
*/
|
|
12
|
+
function getDialogTemplate() {
|
|
13
|
+
return `import * as React from 'react';
|
|
14
|
+
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
15
|
+
import { X } from 'lucide-react';
|
|
16
|
+
import { cn } from '~/lib/utils';
|
|
17
|
+
|
|
18
|
+
const Dialog = DialogPrimitive.Root;
|
|
19
|
+
|
|
20
|
+
const DialogTrigger = DialogPrimitive.Trigger;
|
|
21
|
+
|
|
22
|
+
const DialogPortal = DialogPrimitive.Portal;
|
|
23
|
+
|
|
24
|
+
const DialogClose = DialogPrimitive.Close;
|
|
25
|
+
|
|
26
|
+
const DialogOverlay = React.forwardRef<
|
|
27
|
+
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
|
28
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
|
29
|
+
>(({ className, ...props }, ref) => (
|
|
30
|
+
<DialogPrimitive.Overlay
|
|
31
|
+
ref={ref}
|
|
32
|
+
className={cn(
|
|
33
|
+
'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
|
|
34
|
+
className
|
|
35
|
+
)}
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
));
|
|
39
|
+
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
40
|
+
|
|
41
|
+
const DialogContent = React.forwardRef<
|
|
42
|
+
React.ElementRef<typeof DialogPrimitive.Content>,
|
|
43
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
|
44
|
+
>(({ className, children, ...props }, ref) => (
|
|
45
|
+
<DialogPortal>
|
|
46
|
+
<DialogOverlay />
|
|
47
|
+
<DialogPrimitive.Content
|
|
48
|
+
ref={ref}
|
|
49
|
+
className={cn(
|
|
50
|
+
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
|
|
51
|
+
className
|
|
52
|
+
)}
|
|
53
|
+
{...props}
|
|
54
|
+
>
|
|
55
|
+
{children}
|
|
56
|
+
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
|
57
|
+
<X className="h-4 w-4" />
|
|
58
|
+
<span className="sr-only">Close</span>
|
|
59
|
+
</DialogPrimitive.Close>
|
|
60
|
+
</DialogPrimitive.Content>
|
|
61
|
+
</DialogPortal>
|
|
62
|
+
));
|
|
63
|
+
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
64
|
+
|
|
65
|
+
const DialogHeader = ({
|
|
66
|
+
className,
|
|
67
|
+
...props
|
|
68
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
69
|
+
<div
|
|
70
|
+
className={cn(
|
|
71
|
+
'flex flex-col space-y-1.5 text-center sm:text-left',
|
|
72
|
+
className
|
|
73
|
+
)}
|
|
74
|
+
{...props}
|
|
75
|
+
/>
|
|
76
|
+
);
|
|
77
|
+
DialogHeader.displayName = 'DialogHeader';
|
|
78
|
+
|
|
79
|
+
const DialogFooter = ({
|
|
80
|
+
className,
|
|
81
|
+
...props
|
|
82
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
83
|
+
<div
|
|
84
|
+
className={cn(
|
|
85
|
+
'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
|
|
86
|
+
className
|
|
87
|
+
)}
|
|
88
|
+
{...props}
|
|
89
|
+
/>
|
|
90
|
+
);
|
|
91
|
+
DialogFooter.displayName = 'DialogFooter';
|
|
92
|
+
|
|
93
|
+
const DialogTitle = React.forwardRef<
|
|
94
|
+
React.ElementRef<typeof DialogPrimitive.Title>,
|
|
95
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
|
96
|
+
>(({ className, ...props }, ref) => (
|
|
97
|
+
<DialogPrimitive.Title
|
|
98
|
+
ref={ref}
|
|
99
|
+
className={cn(
|
|
100
|
+
'text-lg font-semibold leading-none tracking-tight',
|
|
101
|
+
className
|
|
102
|
+
)}
|
|
103
|
+
{...props}
|
|
104
|
+
/>
|
|
105
|
+
));
|
|
106
|
+
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
107
|
+
|
|
108
|
+
const DialogDescription = React.forwardRef<
|
|
109
|
+
React.ElementRef<typeof DialogPrimitive.Description>,
|
|
110
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
|
111
|
+
>(({ className, ...props }, ref) => (
|
|
112
|
+
<DialogPrimitive.Description
|
|
113
|
+
ref={ref}
|
|
114
|
+
className={cn('text-sm text-muted-foreground', className)}
|
|
115
|
+
{...props}
|
|
116
|
+
/>
|
|
117
|
+
));
|
|
118
|
+
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
119
|
+
|
|
120
|
+
export {
|
|
121
|
+
Dialog,
|
|
122
|
+
DialogPortal,
|
|
123
|
+
DialogOverlay,
|
|
124
|
+
DialogClose,
|
|
125
|
+
DialogTrigger,
|
|
126
|
+
DialogContent,
|
|
127
|
+
DialogHeader,
|
|
128
|
+
DialogFooter,
|
|
129
|
+
DialogTitle,
|
|
130
|
+
DialogDescription,
|
|
131
|
+
};
|
|
132
|
+
`;
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=ui-dialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-dialog.js","sourceRoot":"","sources":["../../src/templates/ui-dialog.ts"],"names":[],"mappings":";;AAQA,8CAyHC;AAjID;;;;;;;GAOG;AACH,SAAgB,iBAAiB;IAC/B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuHR,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates the DropdownMenu component file content.
|
|
3
|
+
* Standard shadcn/ui dropdown menu with Radix UI primitives.
|
|
4
|
+
*
|
|
5
|
+
* @returns app/components/ui/dropdown-menu.tsx file content
|
|
6
|
+
*/
|
|
7
|
+
export declare function getDropdownMenuTemplate(): string;
|
|
8
|
+
//# sourceMappingURL=ui-dropdown-menu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-dropdown-menu.d.ts","sourceRoot":"","sources":["../../src/templates/ui-dropdown-menu.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAuMhD"}
|