@jhits/plugin-content 0.0.18 → 0.0.19

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.
@@ -23,6 +23,6 @@ interface DynamicLinkProps {
23
23
  type: 'url' | 'file';
24
24
  }) => React.ReactNode;
25
25
  }
26
- export declare function DynamicLink({ linkKey, siteId, locale, defaultLabel, defaultTarget, defaultType, className, isAdmin, apiBaseUrl, isButton, onClick, children }: DynamicLinkProps): import("react/jsx-runtime").JSX.Element;
26
+ export default function DynamicLink({ linkKey, siteId, locale, defaultLabel, defaultTarget, defaultType, className, isAdmin, apiBaseUrl, isButton, onClick, children }: DynamicLinkProps): import("react/jsx-runtime").JSX.Element;
27
27
  export {};
28
28
  //# sourceMappingURL=DynamicLink.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DynamicLink.d.ts","sourceRoot":"","sources":["../../src/components/DynamicLink.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAKnD,UAAU,gBAAgB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oCAAoC;IACpC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,KAAK,GAAG,MAAM,CAAA;KAAE,KAAK,KAAK,CAAC,SAAS,CAAC;CACjG;AAED,wBAAgB,WAAW,CAAC,EACxB,OAAO,EACP,MAAkB,EAClB,MAAM,EACN,YAAY,EACZ,aAAa,EACb,WAAmB,EACnB,SAAc,EACd,OAAe,EACf,UAAU,EACV,QAAgB,EAChB,OAAO,EACP,QAAQ,EACX,EAAE,gBAAgB,2CA6GlB"}
1
+ {"version":3,"file":"DynamicLink.d.ts","sourceRoot":"","sources":["../../src/components/DynamicLink.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAKnD,UAAU,gBAAgB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oCAAoC;IACpC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,KAAK,GAAG,MAAM,CAAA;KAAE,KAAK,KAAK,CAAC,SAAS,CAAC;CACjG;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAChC,OAAO,EACP,MAAkB,EAClB,MAAM,EACN,YAAY,EACZ,aAAa,EACb,WAAmB,EACnB,SAAc,EACd,OAAe,EACf,UAAU,EACV,QAAgB,EAChB,OAAO,EACP,QAAQ,EACX,EAAE,gBAAgB,2CA6GlB"}
@@ -8,7 +8,7 @@ import { useState } from 'react';
8
8
  import { useLinks } from '../hooks/useLinks';
9
9
  import { LinkSettingsModal } from './LinkSettingsModal';
10
10
  import Link from 'next/link';
11
- export function DynamicLink({ linkKey, siteId = 'default', locale, defaultLabel, defaultTarget, defaultType = 'url', className = '', isAdmin = false, apiBaseUrl, isButton = false, onClick, children }) {
11
+ export default function DynamicLink({ linkKey, siteId = 'default', locale, defaultLabel, defaultTarget, defaultType = 'url', className = '', isAdmin = false, apiBaseUrl, isButton = false, onClick, children }) {
12
12
  const { getLink, refetch } = useLinks(siteId, apiBaseUrl);
13
13
  const [isModalOpen, setIsModalOpen] = useState(false);
14
14
  const [isHovered, setIsHovered] = useState(false);
package/dist/index.d.ts CHANGED
@@ -24,7 +24,7 @@ export { default as MultilineText } from './components/MultilineText';
24
24
  export type { MultilineTextProps } from './components/MultilineText';
25
25
  export { default as ParsedText } from './components/ParsedText';
26
26
  export type { ParsedTextProps } from './components/ParsedText';
27
- export { DynamicLink } from './components/DynamicLink';
27
+ export { default as DynamicLink } from './components/DynamicLink';
28
28
  export type { TranslationEditorProps } from './components/TranslationEditor';
29
29
  export { ParserConfigProvider, useParserConfig } from './context/ParserConfigContext';
30
30
  export type { ParserConfigProviderProps } from './context/ParserConfigContext';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,WAAW,kBAAkB;IAC/B,iDAAiD;IACjD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC/B,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAmCD;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,KAAK,EAAE,kBAAkB,kDAyB9D;AAuBD,OAAO,EAAE,aAAa,EAAE,CAAC;AAGzB,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AACtE,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAChE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAG7E,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACtF,YAAY,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAG/E,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAI5C,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,WAAW,kBAAkB;IAC/B,iDAAiD;IACjD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC/B,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAmCD;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,KAAK,EAAE,kBAAkB,kDAyB9D;AAuBD,OAAO,EAAE,aAAa,EAAE,CAAC;AAGzB,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AACtE,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAChE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAClE,YAAY,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAG7E,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACtF,YAAY,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAG/E,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAI5C,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -43,7 +43,7 @@ export { ContentPlugin };
43
43
  // Export components
44
44
  export { default as MultilineText } from './components/MultilineText';
45
45
  export { default as ParsedText } from './components/ParsedText';
46
- export { DynamicLink } from './components/DynamicLink';
46
+ export { default as DynamicLink } from './components/DynamicLink';
47
47
  // Export context
48
48
  export { ParserConfigProvider, useParserConfig } from './context/ParserConfigContext';
49
49
  // Export hooks
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@jhits/plugin-content",
3
- "version": "0.0.18",
3
+ "version": "0.0.19",
4
4
  "description": "Content management and localization plugin for the JHITS ecosystem",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
- "main": "./src/index.ts",
9
- "types": "./src/index.ts",
8
+ "main": "./src/index.tsx",
9
+ "types": "./src/index.tsx",
10
10
  "exports": {
11
11
  ".": {
12
12
  "types": "./src/index.tsx",
@@ -27,7 +27,7 @@ interface DynamicLinkProps {
27
27
  children?: (data: { label: string; target: string; type: 'url' | 'file' }) => React.ReactNode;
28
28
  }
29
29
 
30
- export function DynamicLink({
30
+ export default function DynamicLink({
31
31
  linkKey,
32
32
  siteId = 'default',
33
33
  locale,
package/src/index.tsx CHANGED
@@ -114,7 +114,7 @@ export { default as MultilineText } from './components/MultilineText';
114
114
  export type { MultilineTextProps } from './components/MultilineText';
115
115
  export { default as ParsedText } from './components/ParsedText';
116
116
  export type { ParsedTextProps } from './components/ParsedText';
117
- export { DynamicLink } from './components/DynamicLink';
117
+ export { default as DynamicLink } from './components/DynamicLink';
118
118
  export type { TranslationEditorProps } from './components/TranslationEditor';
119
119
 
120
120
  // Export context
@@ -1,9 +0,0 @@
1
- /**
2
- * Link Manager View
3
- * Allows defining global, localized links and buttons
4
- */
5
- export declare function LinkManagerView({ siteId, locale: defaultLocale }: {
6
- siteId: string;
7
- locale: string;
8
- }): import("react/jsx-runtime").JSX.Element;
9
- //# sourceMappingURL=LinkManager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"LinkManager.d.ts","sourceRoot":"","sources":["../../../src/views/LinkManager/LinkManager.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAsBH,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,2CAuMpG"}
@@ -1,90 +0,0 @@
1
- /**
2
- * Link Manager View
3
- * Allows defining global, localized links and buttons
4
- */
5
- 'use client';
6
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
- import { useState, useEffect } from 'react';
8
- import { Plus, Link2, Trash2, Globe, Save } from 'lucide-react';
9
- export function LinkManagerView({ siteId, locale: defaultLocale }) {
10
- const [links, setLinks] = useState([]);
11
- const [loading, setLoading] = useState(true);
12
- const [activeTab, setActiveTab] = useState('links');
13
- useEffect(() => {
14
- // Fetch links from API
15
- const fetchLinks = async () => {
16
- try {
17
- const res = await fetch(`/api/plugin-content/links?siteId=${siteId}`);
18
- if (res.ok) {
19
- const data = await res.json();
20
- setLinks(data.links || []);
21
- }
22
- }
23
- catch (err) {
24
- console.error('Failed to fetch links:', err);
25
- }
26
- finally {
27
- setLoading(false);
28
- }
29
- };
30
- fetchLinks();
31
- }, [siteId]);
32
- const handleAddLink = () => {
33
- const newLink = {
34
- key: `new-link-${Date.now()}`,
35
- languages: {
36
- [defaultLocale]: { label: 'New Link', target: '', type: 'url' }
37
- }
38
- };
39
- setLinks([...links, newLink]);
40
- };
41
- const handleSaveLink = async (link) => {
42
- try {
43
- const res = await fetch('/api/plugin-content/links', {
44
- method: 'POST',
45
- headers: { 'Content-Type': 'application/json' },
46
- body: JSON.stringify({ siteId, link }),
47
- });
48
- if (res.ok) {
49
- // Refresh list or update local state
50
- const result = await res.json();
51
- setLinks(links.map(l => l.key === link.key ? result.link : l));
52
- }
53
- }
54
- catch (err) {
55
- console.error('Failed to save link:', err);
56
- }
57
- };
58
- const handleDeleteLink = async (key) => {
59
- if (!confirm('Are you sure you want to delete this link?'))
60
- return;
61
- try {
62
- const res = await fetch(`/api/plugin-content/links?siteId=${siteId}&key=${key}`, {
63
- method: 'DELETE',
64
- });
65
- if (res.ok) {
66
- setLinks(links.filter(l => l.key !== key));
67
- }
68
- }
69
- catch (err) {
70
- console.error('Failed to delete link:', err);
71
- }
72
- };
73
- return (_jsxs("div", { className: "p-8 bg-white dark:bg-neutral-900 rounded-[2.5rem] h-full overflow-y-auto", children: [_jsxs("div", { className: "flex items-center justify-between mb-8", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-3xl font-black uppercase tracking-tighter text-neutral-950 dark:text-white", children: "Link & Button Manager" }), _jsx("p", { className: "text-sm text-neutral-500 dark:text-neutral-400", children: "Manage dynamic buttons and links across your application" })] }), _jsxs("button", { onClick: handleAddLink, className: "flex items-center gap-2 px-6 py-3 bg-primary text-white rounded-full text-[10px] font-black uppercase tracking-widest hover:bg-primary/90 transition-all shadow-lg shadow-primary/20", children: [_jsx(Plus, { size: 16 }), "Define New Link"] })] }), _jsx("div", { className: "space-y-6", children: links.length === 0 && !loading ? (_jsxs("div", { className: "text-center py-20 bg-neutral-50 dark:bg-neutral-800/50 rounded-[2rem] border-2 border-dashed border-neutral-200 dark:border-neutral-700", children: [_jsx(Link2, { className: "mx-auto size-12 text-neutral-300 dark:text-neutral-600 mb-4" }), _jsx("p", { className: "text-neutral-500", children: "No dynamic links defined yet." })] })) : (links.map((link) => (_jsxs("div", { className: "bg-neutral-50 dark:bg-neutral-800/50 p-6 rounded-[2rem] border border-neutral-200 dark:border-neutral-700", children: [_jsxs("div", { className: "flex items-start justify-between mb-6", children: [_jsxs("div", { className: "flex-1 max-w-md", children: [_jsx("label", { className: "text-[10px] font-black uppercase tracking-widest text-neutral-400 block mb-2", children: "System Key (Unique ID)" }), _jsx("input", { type: "text", value: link.key, onChange: (e) => setLinks(links.map(l => l.key === link.key ? { ...l, key: e.target.value } : l)), className: "w-full bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-700 p-3 rounded-xl text-sm font-bold outline-none focus:border-primary transition-all", placeholder: "e.g. hero-primary-button" })] }), _jsxs("div", { className: "flex gap-2", children: [_jsx("button", { onClick: () => handleSaveLink(link), className: "p-3 bg-white dark:bg-neutral-900 text-primary border border-neutral-200 dark:border-neutral-700 rounded-xl hover:border-primary transition-all", title: "Save Link", children: _jsx(Save, { size: 18 }) }), _jsx("button", { onClick: () => handleDeleteLink(link.key), className: "p-3 bg-white dark:bg-neutral-900 text-red-500 border border-neutral-200 dark:border-neutral-700 rounded-xl hover:border-red-500 transition-all", title: "Delete Link", children: _jsx(Trash2, { size: 18 }) })] })] }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6", children: [Object.entries(link.languages).map(([locale, data]) => (_jsxs("div", { className: "bg-white dark:bg-neutral-900 p-5 rounded-2xl border border-neutral-100 dark:border-neutral-800", children: [_jsxs("div", { className: "flex items-center gap-2 mb-4", children: [_jsx(Globe, { size: 14, className: "text-primary" }), _jsxs("span", { className: "text-[10px] font-black uppercase tracking-widest text-neutral-500", children: [locale.toUpperCase(), " Translation"] })] }), _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("label", { className: "text-[9px] font-bold uppercase text-neutral-400 block mb-1", children: "Label" }), _jsx("input", { type: "text", value: data.label, onChange: (e) => {
74
- const newLangs = { ...link.languages, [locale]: { ...data, label: e.target.value } };
75
- setLinks(links.map(l => l.key === link.key ? { ...l, languages: newLangs } : l));
76
- }, className: "w-full bg-neutral-50 dark:bg-neutral-800 border border-neutral-200 dark:border-neutral-700 p-2 rounded-lg text-xs outline-none focus:border-primary transition-all" })] }), _jsxs("div", { children: [_jsx("label", { className: "text-[9px] font-bold uppercase text-neutral-400 block mb-1", children: "Target" }), _jsxs("div", { className: "flex gap-2", children: [_jsxs("select", { value: data.type, onChange: (e) => {
77
- const newType = e.target.value;
78
- const newLangs = { ...link.languages, [locale]: { ...data, type: newType } };
79
- setLinks(links.map(l => l.key === link.key ? { ...l, languages: newLangs } : l));
80
- }, className: "bg-neutral-50 dark:bg-neutral-800 border border-neutral-200 dark:border-neutral-700 p-2 rounded-lg text-[10px] outline-none", children: [_jsx("option", { value: "url", children: "URL" }), _jsx("option", { value: "file", children: "File" })] }), _jsx("input", { type: "text", value: data.target, onChange: (e) => {
81
- const newLangs = { ...link.languages, [locale]: { ...data, target: e.target.value } };
82
- setLinks(links.map(l => l.key === link.key ? { ...l, languages: newLangs } : l));
83
- }, className: "flex-1 bg-neutral-50 dark:bg-neutral-800 border border-neutral-200 dark:border-neutral-700 p-2 rounded-lg text-xs outline-none focus:border-primary transition-all", placeholder: data.type === 'url' ? "/about or https://..." : "file-id-..." })] })] })] })] }, locale))), _jsxs("button", { onClick: () => {
84
- const newLocale = prompt('Enter locale (e.g. en, nl, sv):');
85
- if (newLocale) {
86
- const newLangs = { ...link.languages, [newLocale]: { label: '', target: '', type: 'url' } };
87
- setLinks(links.map(l => l.key === link.key ? { ...l, languages: newLangs } : l));
88
- }
89
- }, className: "flex flex-col items-center justify-center p-5 rounded-2xl border-2 border-dashed border-neutral-200 dark:border-neutral-700 hover:border-primary transition-all text-neutral-400 hover:text-primary", children: [_jsx(Plus, { size: 20 }), _jsx("span", { className: "text-[10px] font-black uppercase mt-2", children: "Add translation" })] })] })] }, link.key)))) })] }));
90
- }
@@ -1,8 +0,0 @@
1
- /**
2
- * Media Manager View
3
- * Allows uploading and managing general files (PDFs, docs, etc.)
4
- */
5
- export declare function MediaManagerView({ siteId }: {
6
- siteId: string;
7
- }): import("react/jsx-runtime").JSX.Element;
8
- //# sourceMappingURL=MediaManager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"MediaManager.d.ts","sourceRoot":"","sources":["../../../src/views/MediaManager/MediaManager.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,2CAgL9D"}
@@ -1,93 +0,0 @@
1
- /**
2
- * Media Manager View
3
- * Allows uploading and managing general files (PDFs, docs, etc.)
4
- */
5
- 'use client';
6
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
- import { useState, useEffect, useCallback } from 'react';
8
- import { Upload, File, Trash2, Search, Copy, Check, FileText, ExternalLink } from 'lucide-react';
9
- export function MediaManagerView({ siteId }) {
10
- const [files, setFiles] = useState([]);
11
- const [loading, setLoading] = useState(true);
12
- const [uploading, setUploading] = useState(false);
13
- const [searchQuery, setSearchQuery] = useState('');
14
- const [copiedId, setCopiedId] = useState(null);
15
- const fetchFiles = useCallback(async () => {
16
- try {
17
- setLoading(true);
18
- const res = await fetch(`/api/plugin-content/files?siteId=${siteId}`);
19
- if (res.ok) {
20
- const data = await res.json();
21
- setFiles(data.files || []);
22
- }
23
- }
24
- catch (err) {
25
- console.error('Failed to fetch files:', err);
26
- }
27
- finally {
28
- setLoading(false);
29
- }
30
- }, [siteId]);
31
- useEffect(() => {
32
- fetchFiles();
33
- }, [fetchFiles]);
34
- const handleUpload = async (e) => {
35
- const file = e.target.files?.[0];
36
- if (!file)
37
- return;
38
- try {
39
- setUploading(true);
40
- const formData = new FormData();
41
- formData.append('file', file);
42
- formData.append('siteId', siteId);
43
- const res = await fetch('/api/plugin-content/files/upload', {
44
- method: 'POST',
45
- body: formData,
46
- });
47
- if (res.ok) {
48
- fetchFiles();
49
- }
50
- else {
51
- const error = await res.json();
52
- alert(error.error || 'Upload failed');
53
- }
54
- }
55
- catch (err) {
56
- console.error('Upload error:', err);
57
- alert('An error occurred during upload');
58
- }
59
- finally {
60
- setUploading(false);
61
- }
62
- };
63
- const handleDelete = async (id) => {
64
- if (!confirm('Are you sure you want to delete this file?'))
65
- return;
66
- try {
67
- const res = await fetch(`/api/plugin-content/files?siteId=${siteId}&id=${id}`, {
68
- method: 'DELETE',
69
- });
70
- if (res.ok) {
71
- setFiles(files.filter(f => f.id !== id));
72
- }
73
- }
74
- catch (err) {
75
- console.error('Delete error:', err);
76
- }
77
- };
78
- const copyToClipboard = (text) => {
79
- navigator.clipboard.writeText(text);
80
- setCopiedId(text);
81
- setTimeout(() => setCopiedId(null), 2000);
82
- };
83
- const filteredFiles = files.filter(f => f.filename.toLowerCase().includes(searchQuery.toLowerCase()));
84
- const formatSize = (bytes) => {
85
- if (bytes === 0)
86
- return '0 Bytes';
87
- const k = 1024;
88
- const sizes = ['Bytes', 'KB', 'MB', 'GB'];
89
- const i = Math.floor(Math.log(bytes) / Math.log(k));
90
- return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
91
- };
92
- return (_jsxs("div", { className: "p-8 bg-white dark:bg-neutral-900 rounded-[2.5rem] h-full flex flex-col", children: [_jsxs("div", { className: "flex items-center justify-between mb-8", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-3xl font-black uppercase tracking-tighter text-neutral-950 dark:text-white", children: "File Library" }), _jsx("p", { className: "text-sm text-neutral-500 dark:text-neutral-400", children: "Upload and manage documents, PDFs, and other assets" })] }), _jsxs("label", { className: `flex items-center gap-2 px-6 py-3 bg-primary text-white rounded-full text-[10px] font-black uppercase tracking-widest cursor-pointer hover:bg-primary/90 transition-all shadow-lg shadow-primary/20 ${uploading ? 'opacity-50 pointer-events-none' : ''}`, children: [_jsx(Upload, { size: 16 }), uploading ? 'Uploading...' : 'Upload File', _jsx("input", { type: "file", className: "hidden", onChange: handleUpload, disabled: uploading })] })] }), _jsxs("div", { className: "relative mb-6", children: [_jsx(Search, { className: "absolute left-4 top-1/2 -translate-y-1/2 text-neutral-400 size-4" }), _jsx("input", { type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: "Search files by name...", className: "w-full pl-11 pr-4 py-3 bg-neutral-50 dark:bg-neutral-800 border border-neutral-200 dark:border-neutral-700 rounded-2xl text-sm outline-none focus:border-primary transition-all" })] }), _jsx("div", { className: "flex-1 overflow-y-auto custom-scrollbar", children: loading ? (_jsx("div", { className: "flex items-center justify-center py-20", children: _jsx("div", { className: "w-8 h-8 border-4 border-primary/20 border-t-primary rounded-full animate-spin" }) })) : filteredFiles.length === 0 ? (_jsxs("div", { className: "text-center py-20 bg-neutral-50 dark:bg-neutral-800/50 rounded-[2rem] border-2 border-dashed border-neutral-200 dark:border-neutral-700", children: [_jsx(FileText, { className: "mx-auto size-12 text-neutral-300 dark:text-neutral-600 mb-4" }), _jsx("p", { className: "text-neutral-500", children: searchQuery ? 'No files match your search.' : 'No files uploaded yet.' })] })) : (_jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6", children: filteredFiles.map((file) => (_jsxs("div", { className: "bg-neutral-50 dark:bg-neutral-800/50 p-5 rounded-[2rem] border border-neutral-200 dark:border-neutral-700 group transition-all hover:shadow-xl hover:border-primary/30", children: [_jsxs("div", { className: "flex items-center gap-4 mb-4", children: [_jsx("div", { className: "p-3 bg-white dark:bg-neutral-900 rounded-2xl shadow-sm group-hover:bg-primary/10 transition-colors", children: _jsx(File, { size: 24, className: "text-primary" }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("h3", { className: "font-bold text-sm text-neutral-950 dark:text-white truncate", title: file.filename, children: file.filename }), _jsxs("p", { className: "text-[10px] text-neutral-500 uppercase font-black tracking-tight", children: [formatSize(file.size), " \u2022 ", file.mimeType.split('/')[1].toUpperCase()] })] })] }), _jsxs("div", { className: "flex items-center gap-2 pt-4 border-t border-neutral-200 dark:border-neutral-700", children: [_jsxs("button", { onClick: () => copyToClipboard(file.id), className: "flex-1 flex items-center justify-center gap-2 py-2 bg-white dark:bg-neutral-900 rounded-xl text-[9px] font-black uppercase tracking-widest text-neutral-600 dark:text-neutral-400 hover:text-primary transition-all border border-neutral-200 dark:border-neutral-700", children: [copiedId === file.id ? _jsx(Check, { size: 12 }) : _jsx(Copy, { size: 12 }), copiedId === file.id ? 'Copied' : 'ID'] }), _jsx("a", { href: file.url, target: "_blank", rel: "noopener noreferrer", className: "p-2 bg-white dark:bg-neutral-900 rounded-xl text-neutral-600 dark:text-neutral-400 hover:text-blue-500 transition-all border border-neutral-200 dark:border-neutral-700", title: "View/Download", children: _jsx(ExternalLink, { size: 14 }) }), _jsx("button", { onClick: () => handleDelete(file.id), className: "p-2 bg-white dark:bg-neutral-900 rounded-xl text-neutral-600 dark:text-neutral-400 hover:text-red-500 transition-all border border-neutral-200 dark:border-neutral-700", title: "Delete", children: _jsx(Trash2, { size: 14 }) })] })] }, file.id))) })) })] }));
93
- }
@@ -1,10 +0,0 @@
1
- /**
2
- * Asset Manager View
3
- * Main entry point for managing links and files
4
- */
5
- export declare function AssetManagerView({ siteId, locale, subPath }: {
6
- siteId: string;
7
- locale: string;
8
- subPath: string[];
9
- }): import("react/jsx-runtime").JSX.Element;
10
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/views/index.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AASH,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,2CAkElH"}
@@ -1,22 +0,0 @@
1
- /**
2
- * Asset Manager View
3
- * Main entry point for managing links and files
4
- */
5
- 'use client';
6
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
- import { Link2, FileText, ChevronRight } from 'lucide-react';
8
- import { LinkManagerView } from './LinkManager/LinkManager';
9
- import { MediaManagerView } from './MediaManager/MediaManager';
10
- export function AssetManagerView({ siteId, locale, subPath }) {
11
- const route = subPath[1] || 'links';
12
- const navigate = (path) => {
13
- window.history.pushState(null, '', `/dashboard/content/${path}`);
14
- // Force re-render by triggering popstate or similar if needed,
15
- // but for now we'll just handle it via state if we were in a single view
16
- };
17
- return (_jsxs("div", { className: "flex h-full w-full overflow-hidden", children: [_jsxs("aside", { className: "w-64 border-r border-dashboard-border bg-dashboard-sidebar flex flex-col p-6", children: [_jsx("h2", { className: "text-[10px] font-black uppercase tracking-[0.2em] text-neutral-400 mb-8", children: "Content Assets" }), _jsxs("div", { className: "space-y-2", children: [_jsxs("button", { onClick: () => window.location.href = '/dashboard/content/links', className: `w-full flex items-center justify-between p-4 rounded-2xl transition-all ${route === 'links'
18
- ? 'bg-primary text-white shadow-lg shadow-primary/20'
19
- : 'text-neutral-500 hover:bg-neutral-100 dark:hover:bg-neutral-800'}`, children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Link2, { size: 18 }), _jsx("span", { className: "text-sm font-bold", children: "Links & Buttons" })] }), _jsx(ChevronRight, { size: 14, className: route === 'links' ? 'opacity-100' : 'opacity-0' })] }), _jsxs("button", { onClick: () => window.location.href = '/dashboard/content/media', className: `w-full flex items-center justify-between p-4 rounded-2xl transition-all ${route === 'media'
20
- ? 'bg-primary text-white shadow-lg shadow-primary/20'
21
- : 'text-neutral-500 hover:bg-neutral-100 dark:hover:bg-neutral-800'}`, children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(FileText, { size: 18 }), _jsx("span", { className: "text-sm font-bold", children: "File Library" })] }), _jsx(ChevronRight, { size: 14, className: route === 'media' ? 'opacity-100' : 'opacity-0' })] })] }), _jsx("div", { className: "mt-auto p-4 bg-dashboard-bg rounded-2xl border border-dashboard-border", children: _jsx("p", { className: "text-[10px] text-neutral-500 leading-relaxed font-medium", children: "Use these assets to make your application buttons and downloads dynamic." }) })] }), _jsx("main", { className: "flex-1 min-w-0 overflow-hidden", children: route === 'links' ? (_jsx(LinkManagerView, { siteId: siteId, locale: locale })) : (_jsx(MediaManagerView, { siteId: siteId })) })] }));
22
- }