holie-vkit 1.1.6 β 1.1.7
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/dist/components/Button.d.ts +2 -0
- package/dist/components/Button.js +2 -0
- package/dist/components/FormComponents.d.ts +1 -0
- package/dist/components/FormComponents.js +4 -0
- package/dist/components/Input.d.ts +2 -0
- package/dist/components/Input.js +2 -0
- package/dist/components/Label.d.ts +2 -0
- package/dist/components/Label.js +2 -0
- package/dist/components/Select.d.ts +10 -0
- package/dist/components/Select.js +6 -0
- package/dist/components/Switch.d.ts +5 -0
- package/dist/components/Switch.js +2 -0
- package/dist/components/Tabs.d.ts +11 -0
- package/dist/components/Tabs.js +5 -0
- package/dist/components/Textarea.d.ts +2 -0
- package/dist/components/Textarea.js +2 -0
- package/dist/constants/categories.d.ts +5 -0
- package/dist/constants/categories.js +27 -0
- package/dist/constants/designTokens.d.ts +22 -0
- package/dist/constants/designTokens.js +23 -0
- package/dist/hooks/useAI.d.ts +12 -0
- package/dist/hooks/useAI.js +27 -0
- package/dist/hooks/useAnalyticsEvents.d.ts +7 -0
- package/dist/hooks/useAnalyticsEvents.js +11 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.js +8 -1
- package/dist/utils/formUtils.d.ts +11 -0
- package/dist/utils/formUtils.js +28 -0
- package/dist/utils/translations.d.ts +4 -0
- package/dist/utils/translations.js +19 -0
- package/dist/utils/validationUtils.d.ts +16 -0
- package/dist/utils/validationUtils.js +57 -0
- package/package.json +4 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export {};
|
|
2
|
+
// ...existing code from eendje FormComponents.tsx, adapted for holie-vkit
|
|
3
|
+
// (CategorySelector, StatusSwitches, SocialMediaInputs, LanguageIndicator, MultiLanguageTabs, TranslateButtons)
|
|
4
|
+
// For brevity, see source for full implementation. All props/types are preserved.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export declare const Select: ({ children, ...props }: any) => import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export declare const SelectContent: ({ children }: {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export declare const SelectItem: ({ children, ...props }: any) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export declare const SelectTrigger: ({ children, ...props }: any) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare const SelectValue: ({ children }: {
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
export const Select = ({ children, ...props }) => _jsx("select", { ...props, children: children });
|
|
3
|
+
export const SelectContent = ({ children }) => _jsx("div", { children: children });
|
|
4
|
+
export const SelectItem = ({ children, ...props }) => _jsx("option", { ...props, children: children });
|
|
5
|
+
export const SelectTrigger = ({ children, ...props }) => _jsx("div", { ...props, children: children });
|
|
6
|
+
export const SelectValue = ({ children }) => _jsx("span", { children: children });
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export declare const Tabs: ({ children }: {
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export declare const TabsContent: ({ children }: {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare const TabsList: ({ children }: {
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export declare const TabsTrigger: ({ children, ...props }: React.ButtonHTMLAttributes<HTMLButtonElement>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
export const Tabs = ({ children }) => _jsx("div", { children: children });
|
|
3
|
+
export const TabsContent = ({ children }) => _jsx("div", { children: children });
|
|
4
|
+
export const TabsList = ({ children }) => _jsx("div", { children: children });
|
|
5
|
+
export const TabsTrigger = ({ children, ...props }) => _jsx("button", { ...props, children: children });
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const CATEGORIES: readonly ["reizen", "festivals", "voetbal", "vrijetijd", "eten", "tech"];
|
|
2
|
+
export type Category = typeof CATEGORIES[number];
|
|
3
|
+
export declare const CATEGORY_ICONS: Record<Category, any>;
|
|
4
|
+
export declare const CATEGORY_COLORS: Record<Category, string>;
|
|
5
|
+
export declare const CATEGORY_GRADIENTS: Record<Category, string>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Shared category definitions and icons for holie websites
|
|
2
|
+
import { Plane, Music, Trophy, UtensilsCrossed, Cpu, Gamepad2 } from 'lucide-react';
|
|
3
|
+
export const CATEGORIES = ['reizen', 'festivals', 'voetbal', 'vrijetijd', 'eten', 'tech'];
|
|
4
|
+
export const CATEGORY_ICONS = {
|
|
5
|
+
reizen: Plane,
|
|
6
|
+
festivals: Music,
|
|
7
|
+
voetbal: Trophy,
|
|
8
|
+
vrijetijd: Gamepad2,
|
|
9
|
+
eten: UtensilsCrossed,
|
|
10
|
+
tech: Cpu,
|
|
11
|
+
};
|
|
12
|
+
export const CATEGORY_COLORS = {
|
|
13
|
+
reizen: 'bg-sky-blue/10 text-sky-blue border-sky-blue/20',
|
|
14
|
+
festivals: 'bg-duck-orange/10 text-duck-orange border-duck-orange/20',
|
|
15
|
+
voetbal: 'bg-destructive/10 text-destructive border-destructive/20',
|
|
16
|
+
vrijetijd: 'bg-green-500/10 text-green-600 border-green-500/20',
|
|
17
|
+
eten: 'bg-water-teal/10 text-water-teal border-water-teal/20',
|
|
18
|
+
tech: 'bg-primary/10 text-primary border-primary/20',
|
|
19
|
+
};
|
|
20
|
+
export const CATEGORY_GRADIENTS = {
|
|
21
|
+
reizen: 'from-blue-400 to-cyan-400',
|
|
22
|
+
festivals: 'from-orange-400 to-amber-400',
|
|
23
|
+
voetbal: 'from-red-500 to-orange-500',
|
|
24
|
+
vrijetijd: 'from-green-400 to-emerald-400',
|
|
25
|
+
eten: 'from-emerald-400 to-cyan-400',
|
|
26
|
+
tech: 'from-purple-500 to-indigo-500',
|
|
27
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const COLORS: {
|
|
2
|
+
primary: string;
|
|
3
|
+
secondary: string;
|
|
4
|
+
accent: string;
|
|
5
|
+
destructive: string;
|
|
6
|
+
background: string;
|
|
7
|
+
text: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const GRADIENTS: {
|
|
10
|
+
blueToCyan: string;
|
|
11
|
+
orangeToAmber: string;
|
|
12
|
+
redToOrange: string;
|
|
13
|
+
greenToEmerald: string;
|
|
14
|
+
emeraldToCyan: string;
|
|
15
|
+
purpleToIndigo: string;
|
|
16
|
+
};
|
|
17
|
+
export declare const TYPOGRAPHY: {
|
|
18
|
+
heading: string;
|
|
19
|
+
subheading: string;
|
|
20
|
+
body: string;
|
|
21
|
+
caption: string;
|
|
22
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Shared design tokens for holie websites
|
|
2
|
+
export const COLORS = {
|
|
3
|
+
primary: '#6C63FF',
|
|
4
|
+
secondary: '#FF6584',
|
|
5
|
+
accent: '#43E97B',
|
|
6
|
+
destructive: '#FF3B3F',
|
|
7
|
+
background: '#F7F7FB',
|
|
8
|
+
text: '#22223B',
|
|
9
|
+
};
|
|
10
|
+
export const GRADIENTS = {
|
|
11
|
+
blueToCyan: 'from-blue-400 to-cyan-400',
|
|
12
|
+
orangeToAmber: 'from-orange-400 to-amber-400',
|
|
13
|
+
redToOrange: 'from-red-500 to-orange-500',
|
|
14
|
+
greenToEmerald: 'from-green-400 to-emerald-400',
|
|
15
|
+
emeraldToCyan: 'from-emerald-400 to-cyan-400',
|
|
16
|
+
purpleToIndigo: 'from-purple-500 to-indigo-500',
|
|
17
|
+
};
|
|
18
|
+
export const TYPOGRAPHY = {
|
|
19
|
+
heading: 'font-bold text-2xl md:text-3xl',
|
|
20
|
+
subheading: 'font-semibold text-lg md:text-xl',
|
|
21
|
+
body: 'font-normal text-base',
|
|
22
|
+
caption: 'font-light text-sm',
|
|
23
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface AICompletionOptions {
|
|
2
|
+
prompt: string;
|
|
3
|
+
model?: string;
|
|
4
|
+
temperature?: number;
|
|
5
|
+
maxTokens?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function useAICompletion(): {
|
|
8
|
+
loading: boolean;
|
|
9
|
+
result: string | null;
|
|
10
|
+
error: string | null;
|
|
11
|
+
complete: (options: AICompletionOptions) => Promise<void>;
|
|
12
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Shared AI integration hook for holie websites
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
export function useAICompletion() {
|
|
4
|
+
const [loading, setLoading] = useState(false);
|
|
5
|
+
const [result, setResult] = useState(null);
|
|
6
|
+
const [error, setError] = useState(null);
|
|
7
|
+
async function complete(options) {
|
|
8
|
+
setLoading(true);
|
|
9
|
+
setError(null);
|
|
10
|
+
setResult(null);
|
|
11
|
+
try {
|
|
12
|
+
// Placeholder: Replace with actual API call to your AI backend
|
|
13
|
+
// Example: const response = await fetch('/api/ai', { method: 'POST', body: JSON.stringify(options) });
|
|
14
|
+
// const data = await response.json();
|
|
15
|
+
// setResult(data.result);
|
|
16
|
+
setTimeout(() => {
|
|
17
|
+
setResult('Dit is een voorbeeld AI response.');
|
|
18
|
+
setLoading(false);
|
|
19
|
+
}, 1000);
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
setError(e.message || 'AI completion failed');
|
|
23
|
+
setLoading(false);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return { loading, result, error, complete };
|
|
27
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Shared analytics events hook for holie websites
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
|
+
export function useAnalyticsEvents() {
|
|
4
|
+
// Replace with actual event tracking logic (e.g. send to backend, Google Analytics, etc.)
|
|
5
|
+
const trackEvent = useCallback((event) => {
|
|
6
|
+
// Example: window.gtag('event', event.type, event.payload);
|
|
7
|
+
// For now, just log to console
|
|
8
|
+
console.log('[Analytics]', event.type, event.payload || {});
|
|
9
|
+
}, []);
|
|
10
|
+
return { trackEvent };
|
|
11
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,14 @@ export * from './components/Navbar';
|
|
|
7
7
|
export * from './components/Footer';
|
|
8
8
|
export * from './hooks/useI18n';
|
|
9
9
|
export * from './hooks/useAnalytics';
|
|
10
|
-
export * from './hooks/useAICompletion';
|
|
11
10
|
export * from './utils/i18n';
|
|
12
11
|
export * from './utils/analytics';
|
|
13
12
|
export * from './utils/shared';
|
|
13
|
+
export * from './constants/categories';
|
|
14
|
+
export * from './constants/designTokens';
|
|
15
|
+
export * from './hooks/useAI';
|
|
16
|
+
export * from './hooks/useAnalyticsEvents';
|
|
17
|
+
export * from './utils/translations';
|
|
18
|
+
export * from './components/FormComponents';
|
|
19
|
+
export * from './utils/formUtils';
|
|
20
|
+
export * from './utils/validationUtils';
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,14 @@ export * from './components/Navbar';
|
|
|
7
7
|
export * from './components/Footer';
|
|
8
8
|
export * from './hooks/useI18n';
|
|
9
9
|
export * from './hooks/useAnalytics';
|
|
10
|
-
export * from './hooks/useAICompletion';
|
|
11
10
|
export * from './utils/i18n';
|
|
12
11
|
export * from './utils/analytics';
|
|
13
12
|
export * from './utils/shared';
|
|
13
|
+
export * from './constants/categories';
|
|
14
|
+
export * from './constants/designTokens';
|
|
15
|
+
export * from './hooks/useAI';
|
|
16
|
+
export * from './hooks/useAnalyticsEvents';
|
|
17
|
+
export * from './utils/translations';
|
|
18
|
+
export * from './components/FormComponents';
|
|
19
|
+
export * from './utils/formUtils';
|
|
20
|
+
export * from './utils/validationUtils';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type ArticleCategory = string;
|
|
2
|
+
export type LangCode = string;
|
|
3
|
+
export interface MultiLanguageFormData {
|
|
4
|
+
[key: string]: string | boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare const langFlags: Record<string, string>;
|
|
7
|
+
export declare const allLanguages: string[];
|
|
8
|
+
export declare const createEmptyFormData: () => MultiLanguageFormData;
|
|
9
|
+
export declare const isLanguageMissing: (lang: LangCode, formData: MultiLanguageFormData) => boolean;
|
|
10
|
+
export declare const getMissingLanguages: (formData: MultiLanguageFormData) => LangCode[];
|
|
11
|
+
export declare const generateSlug: (title: string) => string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const langFlags = {
|
|
2
|
+
nl: 'π³π±', en: 'π¬π§', fr: 'π«π·', de: 'π©πͺ', es: 'πͺπΈ', pt: 'π΅πΉ', ar: 'πΈπ¦', pl: 'π΅π±', ja: 'π―π΅'
|
|
3
|
+
};
|
|
4
|
+
export const allLanguages = Object.keys(langFlags);
|
|
5
|
+
export const createEmptyFormData = () => {
|
|
6
|
+
const data = {};
|
|
7
|
+
allLanguages.forEach(lang => {
|
|
8
|
+
data[`title_${lang}`] = '';
|
|
9
|
+
data[`excerpt_${lang}`] = '';
|
|
10
|
+
data[`content_${lang}`] = '';
|
|
11
|
+
});
|
|
12
|
+
data.category = '';
|
|
13
|
+
data.featured = false;
|
|
14
|
+
data.published = false;
|
|
15
|
+
data.image_url = '';
|
|
16
|
+
data.instagram_url = '';
|
|
17
|
+
data.tiktok_url = '';
|
|
18
|
+
return data;
|
|
19
|
+
};
|
|
20
|
+
export const isLanguageMissing = (lang, formData) => {
|
|
21
|
+
return !formData[`title_${lang}`] && !formData[`excerpt_${lang}`] && !formData[`content_${lang}`];
|
|
22
|
+
};
|
|
23
|
+
export const getMissingLanguages = (formData) => {
|
|
24
|
+
return allLanguages.filter(lang => isLanguageMissing(lang, formData));
|
|
25
|
+
};
|
|
26
|
+
export const generateSlug = (title) => {
|
|
27
|
+
return title.toLowerCase().replace(/[^a-z0-9\s-]/g, '').replace(/\s+/g, '-').replace(/-+/g, '-').trim();
|
|
28
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type Translations = Record<string, Record<string, string>>;
|
|
2
|
+
export declare function getTranslation(translations: Translations, key: string, lang: string, fallback?: string): string;
|
|
3
|
+
export declare function getAvailableLanguages(translations: Translations): string[];
|
|
4
|
+
export declare function translateAll(translations: Translations, lang: string): Record<string, string>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function getTranslation(translations, key, lang, fallback) {
|
|
2
|
+
if (!translations[key])
|
|
3
|
+
return fallback || key;
|
|
4
|
+
return translations[key][lang] || translations[key].en || fallback || key;
|
|
5
|
+
}
|
|
6
|
+
export function getAvailableLanguages(translations) {
|
|
7
|
+
const langs = new Set();
|
|
8
|
+
Object.values(translations).forEach(obj => {
|
|
9
|
+
Object.keys(obj).forEach(lang => langs.add(lang));
|
|
10
|
+
});
|
|
11
|
+
return Array.from(langs);
|
|
12
|
+
}
|
|
13
|
+
export function translateAll(translations, lang) {
|
|
14
|
+
const result = {};
|
|
15
|
+
Object.keys(translations).forEach(key => {
|
|
16
|
+
result[key] = getTranslation(translations, key, lang);
|
|
17
|
+
});
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const emailSchema: z.ZodString;
|
|
3
|
+
export declare const passwordSchema: z.ZodString;
|
|
4
|
+
export declare const authSchema: z.ZodObject<{
|
|
5
|
+
email: z.ZodString;
|
|
6
|
+
password: z.ZodString;
|
|
7
|
+
displayName: z.ZodOptional<z.ZodString>;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
export declare const calculatePasswordStrength: (pwd: string) => {
|
|
10
|
+
score: number;
|
|
11
|
+
label: string;
|
|
12
|
+
color: string;
|
|
13
|
+
};
|
|
14
|
+
export declare const authErrorMessages: Record<string, string>;
|
|
15
|
+
export declare const validateEmail: (email: string) => string;
|
|
16
|
+
export declare const validatePassword: (password: string) => string;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const emailSchema = z.string().email('Invalid email address');
|
|
3
|
+
export const passwordSchema = z.string().min(6, 'Password must be at least 6 characters');
|
|
4
|
+
export const authSchema = z.object({
|
|
5
|
+
email: emailSchema,
|
|
6
|
+
password: passwordSchema,
|
|
7
|
+
displayName: z.string()
|
|
8
|
+
.refine((val) => !val || !val.includes('@'), {
|
|
9
|
+
message: 'Display name cannot contain email address',
|
|
10
|
+
})
|
|
11
|
+
.optional(),
|
|
12
|
+
});
|
|
13
|
+
export const calculatePasswordStrength = (pwd) => {
|
|
14
|
+
if (!pwd)
|
|
15
|
+
return { score: 0, label: '', color: '' };
|
|
16
|
+
let score = 0;
|
|
17
|
+
if (pwd.length >= 6)
|
|
18
|
+
score++;
|
|
19
|
+
if (pwd.length >= 8)
|
|
20
|
+
score++;
|
|
21
|
+
if (pwd.length >= 12)
|
|
22
|
+
score++;
|
|
23
|
+
if (/[A-Z]/.test(pwd))
|
|
24
|
+
score++;
|
|
25
|
+
if (/[0-9]/.test(pwd))
|
|
26
|
+
score++;
|
|
27
|
+
if (/[^A-Za-z0-9]/.test(pwd))
|
|
28
|
+
score++;
|
|
29
|
+
if (score <= 2)
|
|
30
|
+
return { score, label: 'Weak', color: 'text-destructive' };
|
|
31
|
+
if (score <= 4)
|
|
32
|
+
return { score, label: 'Medium', color: 'text-yellow-600' };
|
|
33
|
+
return { score, label: 'Strong', color: 'text-green-600' };
|
|
34
|
+
};
|
|
35
|
+
export const authErrorMessages = {
|
|
36
|
+
'auth/invalid-credentials': 'Invalid login credentials',
|
|
37
|
+
'auth/user-already-exists': 'This email address is already registered',
|
|
38
|
+
'auth/email-not-confirmed': 'Email address not yet confirmed',
|
|
39
|
+
};
|
|
40
|
+
export const validateEmail = (email) => {
|
|
41
|
+
if (!email)
|
|
42
|
+
return '';
|
|
43
|
+
try {
|
|
44
|
+
emailSchema.parse(email);
|
|
45
|
+
return '';
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return 'Invalid email address';
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
export const validatePassword = (password) => {
|
|
52
|
+
if (!password)
|
|
53
|
+
return '';
|
|
54
|
+
if (password.length < 6)
|
|
55
|
+
return 'Password too short';
|
|
56
|
+
return '';
|
|
57
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "holie-vkit",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.7",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
"build": "tsc"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"
|
|
15
|
-
"react": "^18.0.0"
|
|
14
|
+
"lucide-react": "^0.563.0",
|
|
15
|
+
"react": "^18.0.0",
|
|
16
|
+
"zod": "^4.3.6"
|
|
16
17
|
},
|
|
17
18
|
"devDependencies": {
|
|
18
19
|
"@types/react": "^19.2.10",
|