Add Legal Office seal and complete Azure CDN deployment
- Add Legal Office of the Master seal (SVG design with Maltese Cross, scales of justice, legal scroll) - Create legal-office-manifest-template.json for Legal Office credentials - Update SEAL_MAPPING.md and DESIGN_GUIDE.md with Legal Office seal documentation - Complete Azure CDN infrastructure deployment: - Resource group, storage account, and container created - 17 PNG seal files uploaded to Azure Blob Storage - All manifest templates updated with Azure URLs - Configuration files generated (azure-cdn-config.env) - Add comprehensive Azure CDN setup scripts and documentation - Fix manifest URL generation to prevent double slashes - Verify all seals accessible via HTTPS
This commit is contained in:
@@ -25,7 +25,7 @@ export interface BadgeProps
|
||||
extends React.HTMLAttributes<HTMLDivElement>,
|
||||
VariantProps<typeof badgeVariants> {}
|
||||
|
||||
export function Badge({ className, variant, ...props }: BadgeProps) {
|
||||
export function Badge({ className, variant, ...props }: BadgeProps): JSX.Element {
|
||||
return <div className={cn(badgeVariants({ variant }), className)} {...props} />;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import { cn } from '../lib/utils';
|
||||
|
||||
export interface BreadcrumbItem {
|
||||
@@ -10,9 +8,10 @@ export interface BreadcrumbItem {
|
||||
export interface BreadcrumbsProps {
|
||||
items: BreadcrumbItem[];
|
||||
className?: string;
|
||||
LinkComponent?: React.ComponentType<{ href: string; className?: string; children: React.ReactNode }>;
|
||||
}
|
||||
|
||||
export function Breadcrumbs({ items, className }: BreadcrumbsProps) {
|
||||
export function Breadcrumbs({ items, className, LinkComponent }: BreadcrumbsProps): JSX.Element {
|
||||
return (
|
||||
<nav aria-label="Breadcrumb" className={cn('flex', className)}>
|
||||
<ol className="flex items-center space-x-2 text-sm">
|
||||
@@ -26,9 +25,15 @@ export function Breadcrumbs({ items, className }: BreadcrumbsProps) {
|
||||
{item.label}
|
||||
</span>
|
||||
) : item.href ? (
|
||||
<Link href={item.href} className="text-gray-600 hover:text-gray-900">
|
||||
{item.label}
|
||||
</Link>
|
||||
LinkComponent ? (
|
||||
<LinkComponent href={item.href} className="text-gray-600 hover:text-gray-900">
|
||||
{item.label}
|
||||
</LinkComponent>
|
||||
) : (
|
||||
<a href={item.href} className="text-gray-600 hover:text-gray-900">
|
||||
{item.label}
|
||||
</a>
|
||||
)
|
||||
) : (
|
||||
<span className="text-gray-600">{item.label}</span>
|
||||
)}
|
||||
|
||||
@@ -32,7 +32,7 @@ export interface ButtonProps
|
||||
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
({ className, variant, size, ...props }, ref) => {
|
||||
return (
|
||||
<button className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />
|
||||
<button className={cn(buttonVariants({ variant, size }), className)} ref={ref} {...props} />
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -16,27 +16,29 @@ export interface DropdownProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function Dropdown({ trigger, items, align = 'left', className }: DropdownProps) {
|
||||
export function Dropdown({ trigger, items, align = 'left', className }: DropdownProps): JSX.Element {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
||||
const handleClickOutside = (event: MouseEvent): void => {
|
||||
if (dropdownRef.current && event.target instanceof Node && !dropdownRef.current.contains(event.target)) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (isOpen) {
|
||||
if (isOpen && typeof document !== 'undefined') {
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
}
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
if (typeof document !== 'undefined') {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
}
|
||||
};
|
||||
}, [isOpen]);
|
||||
|
||||
const handleItemClick = (item: DropdownItem) => {
|
||||
const handleItemClick = (item: DropdownItem): void => {
|
||||
if (item.disabled) return;
|
||||
item.onClick?.();
|
||||
setIsOpen(false);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { cn } from '../lib/utils';
|
||||
|
||||
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}
|
||||
export type InputProps = React.InputHTMLAttributes<HTMLInputElement>;
|
||||
|
||||
export const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
({ className, type, ...props }, ref) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { cn } from '../lib/utils';
|
||||
|
||||
export interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {}
|
||||
export type LabelProps = React.LabelHTMLAttributes<HTMLLabelElement>;
|
||||
|
||||
export const Label = React.forwardRef<HTMLLabelElement, LabelProps>(
|
||||
({ className, ...props }, ref) => {
|
||||
|
||||
@@ -20,15 +20,17 @@ export function Modal({
|
||||
children,
|
||||
size = 'md',
|
||||
showCloseButton = true,
|
||||
}: ModalProps) {
|
||||
}: ModalProps): JSX.Element | null {
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
if (open && typeof document !== 'undefined') {
|
||||
document.body.style.overflow = 'hidden';
|
||||
} else {
|
||||
} else if (typeof document !== 'undefined') {
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
return () => {
|
||||
document.body.style.overflow = '';
|
||||
if (typeof document !== 'undefined') {
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
};
|
||||
}, [open]);
|
||||
|
||||
@@ -102,8 +104,8 @@ export function ConfirmModal({
|
||||
confirmText = 'Confirm',
|
||||
cancelText = 'Cancel',
|
||||
variant = 'default',
|
||||
}: ConfirmModalProps) {
|
||||
const handleConfirm = () => {
|
||||
}: ConfirmModalProps): JSX.Element {
|
||||
const handleConfirm = (): void => {
|
||||
onConfirm();
|
||||
onClose();
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { cn } from '../lib/utils';
|
||||
|
||||
export interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {}
|
||||
export type SelectProps = React.SelectHTMLAttributes<HTMLSelectElement>;
|
||||
|
||||
export const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
|
||||
({ className, children, ...props }, ref) => {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React from 'react';
|
||||
import { cn } from '../lib/utils';
|
||||
|
||||
export interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement> {}
|
||||
export type SkeletonProps = React.HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
export function Skeleton({ className, ...props }: SkeletonProps) {
|
||||
export function Skeleton({ className, ...props }: SkeletonProps): JSX.Element {
|
||||
return <div className={cn('animate-pulse rounded-md bg-muted', className)} {...props} />;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { createContext, useContext, useState, ReactNode } from 'react';
|
||||
import { createContext, useContext, useState, ReactNode } from 'react';
|
||||
import { cn } from '../lib/utils';
|
||||
|
||||
interface TabsContextType {
|
||||
@@ -16,12 +16,12 @@ export interface TabsProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function Tabs({ defaultValue, value: controlledValue, onValueChange, children, className }: TabsProps) {
|
||||
export function Tabs({ defaultValue, value: controlledValue, onValueChange, children, className }: TabsProps): JSX.Element {
|
||||
const [internalValue, setInternalValue] = useState(defaultValue || '');
|
||||
const isControlled = controlledValue !== undefined;
|
||||
const currentValue = isControlled ? controlledValue : internalValue;
|
||||
|
||||
const handleValueChange = (newValue: string) => {
|
||||
const handleValueChange = (newValue: string): void => {
|
||||
if (!isControlled) {
|
||||
setInternalValue(newValue);
|
||||
}
|
||||
@@ -40,7 +40,7 @@ export interface TabsListProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function TabsList({ children, className }: TabsListProps) {
|
||||
export function TabsList({ children, className }: TabsListProps): JSX.Element {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
@@ -60,7 +60,7 @@ export interface TabsTriggerProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function TabsTrigger({ value, children, className }: TabsTriggerProps) {
|
||||
export function TabsTrigger({ value, children, className }: TabsTriggerProps): JSX.Element {
|
||||
const context = useContext(TabsContext);
|
||||
if (!context) {
|
||||
throw new Error('TabsTrigger must be used within Tabs');
|
||||
@@ -94,7 +94,7 @@ export interface TabsContentProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function TabsContent({ value, children, className }: TabsContentProps) {
|
||||
export function TabsContent({ value, children, className }: TabsContentProps): JSX.Element | null {
|
||||
const context = useContext(TabsContext);
|
||||
if (!context) {
|
||||
throw new Error('TabsContent must be used within Tabs');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { cn } from '../lib/utils';
|
||||
|
||||
export interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
|
||||
export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
|
||||
|
||||
export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
({ className, ...props }, ref) => {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React, { createContext, useContext, useState, useCallback, ReactNode } from 'react';
|
||||
import { cn } from '../lib/utils';
|
||||
import { createContext, useContext, useState, useCallback, ReactNode } from 'react';
|
||||
import { Alert, AlertDescription } from './Alert';
|
||||
|
||||
export type ToastVariant = 'default' | 'success' | 'error' | 'warning' | 'info';
|
||||
@@ -24,7 +23,7 @@ interface ToastContextType {
|
||||
|
||||
const ToastContext = createContext<ToastContextType | undefined>(undefined);
|
||||
|
||||
export function useToast() {
|
||||
export function useToast(): ToastContextType {
|
||||
const context = useContext(ToastContext);
|
||||
if (!context) {
|
||||
throw new Error('useToast must be used within a ToastProvider');
|
||||
@@ -32,15 +31,15 @@ export function useToast() {
|
||||
return context;
|
||||
}
|
||||
|
||||
export function ToastProvider({ children }: { children: ReactNode }) {
|
||||
export function ToastProvider({ children }: { children: ReactNode }): JSX.Element {
|
||||
const [toasts, setToasts] = useState<Toast[]>([]);
|
||||
|
||||
const removeToast = useCallback((id: string) => {
|
||||
const removeToast = useCallback((id: string): void => {
|
||||
setToasts((prev) => prev.filter((toast) => toast.id !== id));
|
||||
}, []);
|
||||
|
||||
const addToast = useCallback(
|
||||
(toast: Omit<Toast, 'id'>) => {
|
||||
(toast: Omit<Toast, 'id'>): void => {
|
||||
const id = Math.random().toString(36).substring(2, 9);
|
||||
const newToast: Toast = {
|
||||
...toast,
|
||||
@@ -51,37 +50,39 @@ export function ToastProvider({ children }: { children: ReactNode }) {
|
||||
setToasts((prev) => [...prev, newToast]);
|
||||
|
||||
if (newToast.duration && newToast.duration > 0) {
|
||||
setTimeout(() => {
|
||||
removeToast(id);
|
||||
}, newToast.duration);
|
||||
if (typeof window !== 'undefined') {
|
||||
setTimeout(() => {
|
||||
removeToast(id);
|
||||
}, newToast.duration);
|
||||
}
|
||||
}
|
||||
},
|
||||
[removeToast]
|
||||
);
|
||||
|
||||
const success = useCallback(
|
||||
(message: string, title?: string) => {
|
||||
(message: string, title?: string): void => {
|
||||
addToast({ message, title, variant: 'success' });
|
||||
},
|
||||
[addToast]
|
||||
);
|
||||
|
||||
const error = useCallback(
|
||||
(message: string, title?: string) => {
|
||||
(message: string, title?: string): void => {
|
||||
addToast({ message, title, variant: 'error' });
|
||||
},
|
||||
[addToast]
|
||||
);
|
||||
|
||||
const warning = useCallback(
|
||||
(message: string, title?: string) => {
|
||||
(message: string, title?: string): void => {
|
||||
addToast({ message, title, variant: 'warning' });
|
||||
},
|
||||
[addToast]
|
||||
);
|
||||
|
||||
const info = useCallback(
|
||||
(message: string, title?: string) => {
|
||||
(message: string, title?: string): void => {
|
||||
addToast({ message, title, variant: 'info' });
|
||||
},
|
||||
[addToast]
|
||||
@@ -95,7 +96,7 @@ export function ToastProvider({ children }: { children: ReactNode }) {
|
||||
);
|
||||
}
|
||||
|
||||
function ToastContainer({ toasts, removeToast }: { toasts: Toast[]; removeToast: (id: string) => void }) {
|
||||
function ToastContainer({ toasts, removeToast }: { toasts: Toast[]; removeToast: (id: string) => void }): JSX.Element | null {
|
||||
if (toasts.length === 0) return null;
|
||||
|
||||
return (
|
||||
@@ -107,7 +108,7 @@ function ToastContainer({ toasts, removeToast }: { toasts: Toast[]; removeToast:
|
||||
);
|
||||
}
|
||||
|
||||
function ToastItem({ toast, onRemove }: { toast: Toast; onRemove: (id: string) => void }) {
|
||||
function ToastItem({ toast, onRemove }: { toast: Toast; onRemove: (id: string) => void }): JSX.Element {
|
||||
const variantMap: Record<ToastVariant, { alert: 'default' | 'destructive' | 'success' | 'warning'; icon: string }> = {
|
||||
default: { alert: 'default', icon: 'ℹ️' },
|
||||
success: { alert: 'success', icon: '✓' },
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { type ClassValue, clsx } from 'clsx';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
export function cn(...inputs: ClassValue[]): string {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"jsx": "react-jsx"
|
||||
"jsx": "react-jsx",
|
||||
"lib": ["dom", "dom.iterable", "esnext"]
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts", "**/*.spec.tsx"]
|
||||
|
||||
Reference in New Issue
Block a user