refactor: refactor webui
This commit is contained in:
parent
b20f7cd1ad
commit
ee1b1ae5e6
@ -10,11 +10,11 @@
|
|||||||
"cssVariables": true
|
"cssVariables": true
|
||||||
},
|
},
|
||||||
"aliases": {
|
"aliases": {
|
||||||
"components": "@/components",
|
"components": "@/views/components",
|
||||||
"utils": "@/infra/styles/utils",
|
"utils": "@/views/utils",
|
||||||
"ui": "@/components/ui",
|
"ui": "@/views/components/ui",
|
||||||
"lib": "@/lib",
|
"lib": "@/views/lib",
|
||||||
"hooks": "@/infra/hooks"
|
"hooks": "@/views/hooks"
|
||||||
},
|
},
|
||||||
"iconLibrary": "lucide"
|
"iconLibrary": "lucide"
|
||||||
}
|
}
|
||||||
|
@ -18,32 +18,32 @@
|
|||||||
"@graphiql/toolkit": "^0.11.1",
|
"@graphiql/toolkit": "^0.11.1",
|
||||||
"@hookform/resolvers": "^5.0.1",
|
"@hookform/resolvers": "^5.0.1",
|
||||||
"@outposts/injection-js": "^2.5.1",
|
"@outposts/injection-js": "^2.5.1",
|
||||||
"@radix-ui/react-accordion": "^1.2.7",
|
"@radix-ui/react-accordion": "^1.2.10",
|
||||||
"@radix-ui/react-alert-dialog": "^1.1.10",
|
"@radix-ui/react-alert-dialog": "^1.1.13",
|
||||||
"@radix-ui/react-aspect-ratio": "^1.1.4",
|
"@radix-ui/react-aspect-ratio": "^1.1.6",
|
||||||
"@radix-ui/react-avatar": "^1.1.6",
|
"@radix-ui/react-avatar": "^1.1.9",
|
||||||
"@radix-ui/react-checkbox": "^1.2.2",
|
"@radix-ui/react-checkbox": "^1.3.1",
|
||||||
"@radix-ui/react-collapsible": "^1.1.7",
|
"@radix-ui/react-collapsible": "^1.1.10",
|
||||||
"@radix-ui/react-context-menu": "^2.2.11",
|
"@radix-ui/react-context-menu": "^2.2.14",
|
||||||
"@radix-ui/react-dialog": "^1.1.10",
|
"@radix-ui/react-dialog": "^1.1.13",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.11",
|
"@radix-ui/react-dropdown-menu": "^2.1.14",
|
||||||
"@radix-ui/react-hover-card": "^1.1.10",
|
"@radix-ui/react-hover-card": "^1.1.13",
|
||||||
"@radix-ui/react-label": "^2.1.4",
|
"@radix-ui/react-label": "^2.1.6",
|
||||||
"@radix-ui/react-menubar": "^1.1.11",
|
"@radix-ui/react-menubar": "^1.1.14",
|
||||||
"@radix-ui/react-navigation-menu": "^1.2.9",
|
"@radix-ui/react-navigation-menu": "^1.2.12",
|
||||||
"@radix-ui/react-popover": "^1.1.10",
|
"@radix-ui/react-popover": "^1.1.13",
|
||||||
"@radix-ui/react-progress": "^1.1.4",
|
"@radix-ui/react-progress": "^1.1.6",
|
||||||
"@radix-ui/react-radio-group": "^1.3.3",
|
"@radix-ui/react-radio-group": "^1.3.6",
|
||||||
"@radix-ui/react-scroll-area": "^1.2.5",
|
"@radix-ui/react-scroll-area": "^1.2.8",
|
||||||
"@radix-ui/react-select": "^2.2.2",
|
"@radix-ui/react-select": "^2.2.4",
|
||||||
"@radix-ui/react-separator": "^1.1.4",
|
"@radix-ui/react-separator": "^1.1.6",
|
||||||
"@radix-ui/react-slider": "^1.3.2",
|
"@radix-ui/react-slider": "^1.3.4",
|
||||||
"@radix-ui/react-slot": "^1.2.0",
|
"@radix-ui/react-slot": "^1.2.2",
|
||||||
"@radix-ui/react-switch": "^1.2.2",
|
"@radix-ui/react-switch": "^1.2.4",
|
||||||
"@radix-ui/react-tabs": "^1.1.8",
|
"@radix-ui/react-tabs": "^1.1.11",
|
||||||
"@radix-ui/react-toggle": "^1.1.6",
|
"@radix-ui/react-toggle": "^1.1.8",
|
||||||
"@radix-ui/react-toggle-group": "^1.1.7",
|
"@radix-ui/react-toggle-group": "^1.1.9",
|
||||||
"@radix-ui/react-tooltip": "^1.2.3",
|
"@radix-ui/react-tooltip": "^1.2.6",
|
||||||
"@rsbuild/plugin-react": "^1.2.0",
|
"@rsbuild/plugin-react": "^1.2.0",
|
||||||
"@tanstack/react-router": "^1.112.13",
|
"@tanstack/react-router": "^1.112.13",
|
||||||
"@tanstack/router-devtools": "^1.112.13",
|
"@tanstack/router-devtools": "^1.112.13",
|
||||||
@ -63,10 +63,10 @@
|
|||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"oidc-client-rx": "0.1.0-alpha.9",
|
"oidc-client-rx": "0.1.0-alpha.9",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-day-picker": "9.6.7",
|
"react-day-picker": "8.10.1",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
"react-hook-form": "^7.56.0",
|
"react-hook-form": "^7.56.3",
|
||||||
"react-resizable-panels": "^3.0.0",
|
"react-resizable-panels": "^3.0.1",
|
||||||
"recharts": "^2.15.3",
|
"recharts": "^2.15.3",
|
||||||
"rxjs": "^7.8.2",
|
"rxjs": "^7.8.2",
|
||||||
"sonner": "^2.0.3",
|
"sonner": "^2.0.3",
|
||||||
@ -74,7 +74,8 @@
|
|||||||
"tailwindcss": "^4.0.6",
|
"tailwindcss": "^4.0.6",
|
||||||
"tw-animate-css": "^1.2.7",
|
"tw-animate-css": "^1.2.7",
|
||||||
"type-fest": "^4.40.0",
|
"type-fest": "^4.40.0",
|
||||||
"vaul": "^1.1.2"
|
"vaul": "^1.1.2",
|
||||||
|
"zod": "^3.24.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rsbuild/core": "^1.2.15",
|
"@rsbuild/core": "^1.2.15",
|
||||||
|
@ -1,4 +1,13 @@
|
|||||||
import { AuthService } from '@/domains/auth/auth.service';
|
import { AuthService } from '@/domains/auth/auth.service';
|
||||||
|
import { AUTH_PROVIDER, type AuthProvider } from '@/infra/auth/auth.provider';
|
||||||
|
import { BasicAuthProvider } from '@/infra/auth/basic';
|
||||||
|
import {
|
||||||
|
AUTH_METHOD,
|
||||||
|
type AuthMethodType,
|
||||||
|
getAppAuthMethod,
|
||||||
|
} from '@/infra/auth/defs';
|
||||||
|
import { OidcAuthProvider, buildOidcConfig } from '@/infra/auth/oidc';
|
||||||
|
import { UnreachableError } from '@/infra/errors/common';
|
||||||
import type { Injector, Provider } from '@outposts/injection-js';
|
import type { Injector, Provider } from '@outposts/injection-js';
|
||||||
import type { AnyRouter } from '@tanstack/react-router';
|
import type { AnyRouter } from '@tanstack/react-router';
|
||||||
import {
|
import {
|
||||||
@ -9,16 +18,11 @@ import {
|
|||||||
} from 'oidc-client-rx';
|
} from 'oidc-client-rx';
|
||||||
import { withTanstackRouter } from 'oidc-client-rx/adapters/@tanstack/react-router';
|
import { withTanstackRouter } from 'oidc-client-rx/adapters/@tanstack/react-router';
|
||||||
import type { Observable } from 'rxjs';
|
import type { Observable } from 'rxjs';
|
||||||
import {
|
|
||||||
AppAuthMethod,
|
|
||||||
AuthMethodEnum,
|
|
||||||
type AuthMethodType,
|
|
||||||
buildOidcConfig,
|
|
||||||
} from './config';
|
|
||||||
|
|
||||||
export function provideAuth(router: AnyRouter): Provider[] {
|
export function provideAuth(router: AnyRouter): Provider[] {
|
||||||
const providers: Provider[] = [AuthService];
|
const providers: Provider[] = [AuthService];
|
||||||
if (AppAuthMethod === AuthMethodEnum.OIDC) {
|
const appAuthMethod = getAppAuthMethod();
|
||||||
|
if (appAuthMethod === AUTH_METHOD.OIDC) {
|
||||||
providers.push(
|
providers.push(
|
||||||
...provideOidcAuth(
|
...provideOidcAuth(
|
||||||
{
|
{
|
||||||
@ -32,18 +36,25 @@ export function provideAuth(router: AnyRouter): Provider[] {
|
|||||||
withCheckAuthResultEvent()
|
withCheckAuthResultEvent()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
providers.push({
|
||||||
|
provide: AUTH_PROVIDER,
|
||||||
|
useClass: OidcAuthProvider,
|
||||||
|
});
|
||||||
|
} else if (appAuthMethod === AUTH_METHOD.BASIC) {
|
||||||
|
providers.push({
|
||||||
|
provide: AUTH_PROVIDER,
|
||||||
|
useClass: BasicAuthProvider,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new UnreachableError(`Unsupported auth method: ${appAuthMethod}`);
|
||||||
}
|
}
|
||||||
return providers;
|
return providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setupAuthContext(injector: Injector) {
|
|
||||||
const { authService } = authContextFromInjector(injector);
|
|
||||||
authService.setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AuthContext {
|
export interface AuthContext {
|
||||||
type: AuthMethodType;
|
type: AuthMethodType;
|
||||||
authService: AuthService;
|
authService: AuthService;
|
||||||
|
authProvider: AuthProvider;
|
||||||
isAuthenticated$: Observable<boolean>;
|
isAuthenticated$: Observable<boolean>;
|
||||||
userData$: Observable<{}>;
|
userData$: Observable<{}>;
|
||||||
checkAuthResultEvent$: Observable<CheckAuthResultEventType>;
|
checkAuthResultEvent$: Observable<CheckAuthResultEventType>;
|
||||||
@ -51,11 +62,18 @@ export interface AuthContext {
|
|||||||
|
|
||||||
export function authContextFromInjector(injector: Injector): AuthContext {
|
export function authContextFromInjector(injector: Injector): AuthContext {
|
||||||
const authService = injector.get(AuthService);
|
const authService = injector.get(AuthService);
|
||||||
|
const authProvider = injector.get(AUTH_PROVIDER);
|
||||||
return {
|
return {
|
||||||
type: AppAuthMethod,
|
type: authProvider.authMethod,
|
||||||
authService,
|
|
||||||
isAuthenticated$: authService.isAuthenticated$,
|
isAuthenticated$: authService.isAuthenticated$,
|
||||||
userData$: authService.userData$,
|
userData$: authService.userData$,
|
||||||
checkAuthResultEvent$: authService.checkAuthResultEvent$,
|
checkAuthResultEvent$: authService.checkAuthResultEvent$,
|
||||||
|
authService,
|
||||||
|
authProvider,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setupAuthContext(injector: Injector) {
|
||||||
|
const { authService } = authContextFromInjector(injector);
|
||||||
|
authService.setup();
|
||||||
|
}
|
||||||
|
@ -1,19 +1,17 @@
|
|||||||
import type { RouterContext } from '@/infra/routes/traits';
|
import type { RouterContext } from '@/infra/routes/traits';
|
||||||
import { runInInjectionContext } from '@outposts/injection-js';
|
|
||||||
import { autoLoginPartialRoutesGuard } from 'oidc-client-rx';
|
|
||||||
import { firstValueFrom } from 'rxjs';
|
import { firstValueFrom } from 'rxjs';
|
||||||
import { authContextFromInjector } from './context';
|
import { authContextFromInjector } from './context';
|
||||||
|
|
||||||
export const beforeLoadGuard = async ({
|
export const beforeLoadGuard = async ({
|
||||||
context,
|
context,
|
||||||
}: { context: RouterContext }) => {
|
}: { context: RouterContext }) => {
|
||||||
const { isAuthenticated$ } = authContextFromInjector(context.injector);
|
const { isAuthenticated$, authProvider } = authContextFromInjector(
|
||||||
|
context.injector
|
||||||
|
);
|
||||||
if (!(await firstValueFrom(isAuthenticated$))) {
|
if (!(await firstValueFrom(isAuthenticated$))) {
|
||||||
const guard$ = runInInjectionContext(context.injector, () =>
|
const isAuthenticated = await firstValueFrom(
|
||||||
autoLoginPartialRoutesGuard()
|
authProvider.autoLoginPartialRoutesGuard()
|
||||||
);
|
);
|
||||||
|
|
||||||
const isAuthenticated = await firstValueFrom(guard$);
|
|
||||||
if (!isAuthenticated) {
|
if (!isAuthenticated) {
|
||||||
throw !isAuthenticated;
|
throw !isAuthenticated;
|
||||||
}
|
}
|
||||||
|
@ -26,9 +26,9 @@ export function useAuth() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
...authContext,
|
||||||
userData,
|
userData,
|
||||||
injector,
|
injector,
|
||||||
isAuthenticated,
|
isAuthenticated,
|
||||||
authContext,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,53 +1,15 @@
|
|||||||
import { AppAuthMethod, AuthMethodEnum } from '@/app/auth/config';
|
import { AUTH_PROVIDER } from '@/infra/auth/auth.provider';
|
||||||
import { injectInjector } from '@/infra/di/inject';
|
import { Injectable, inject } from '@outposts/injection-js';
|
||||||
import { Injectable, type Injector } from '@outposts/injection-js';
|
|
||||||
import {
|
|
||||||
CHECK_AUTH_RESULT_EVENT,
|
|
||||||
type CheckAuthResultEventType,
|
|
||||||
OidcSecurityService,
|
|
||||||
} from 'oidc-client-rx';
|
|
||||||
import { NEVER, type Observable, map, of } from 'rxjs';
|
|
||||||
|
|
||||||
const BASIC_AUTH_IS_AUTHENTICATED$ = of(true) as Observable<true>;
|
|
||||||
|
|
||||||
const BASIC_AUTH_USER_DATA$ = of({});
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
private injector: Injector = injectInjector();
|
private authProvider = inject(AUTH_PROVIDER);
|
||||||
oidcSecurityService: OidcSecurityService | undefined;
|
|
||||||
checkAuthResultEvent$: Observable<CheckAuthResultEventType>;
|
isAuthenticated$ = this.authProvider.isAuthenticated$;
|
||||||
constructor() {
|
userData$ = this.authProvider.userData$;
|
||||||
if (AppAuthMethod === 'oidc') {
|
checkAuthResultEvent$ = this.authProvider.checkAuthResultEvent$;
|
||||||
this.oidcSecurityService = this.injector.get(OidcSecurityService);
|
|
||||||
this.checkAuthResultEvent$ = this.injector.get(CHECK_AUTH_RESULT_EVENT);
|
|
||||||
} else {
|
|
||||||
this.checkAuthResultEvent$ = NEVER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
if (AppAuthMethod === AuthMethodEnum.OIDC) {
|
this.authProvider.setup();
|
||||||
this.oidcSecurityService!.checkAuth().subscribe();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get isAuthenticated$() {
|
|
||||||
return (
|
|
||||||
this.oidcSecurityService?.isAuthenticated$.pipe(
|
|
||||||
map((s) => s.isAuthenticated)
|
|
||||||
) ?? BASIC_AUTH_IS_AUTHENTICATED$
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
get userData$() {
|
|
||||||
return (
|
|
||||||
this.oidcSecurityService?.userData$?.pipe(map((s) => s.userData)) ??
|
|
||||||
BASIC_AUTH_USER_DATA$
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getAccessToken(): Observable<string | undefined> {
|
|
||||||
return this.oidcSecurityService?.getAccessToken() ?? of(undefined);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
apps/webui/src/infra/auth/auth.provider.ts
Normal file
27
apps/webui/src/infra/auth/auth.provider.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { InjectionToken } from '@outposts/injection-js';
|
||||||
|
import type { CheckAuthResultEventType } from 'oidc-client-rx';
|
||||||
|
import { type Observable, map } from 'rxjs';
|
||||||
|
import type { AuthMethodType } from './defs';
|
||||||
|
|
||||||
|
export abstract class AuthProvider {
|
||||||
|
abstract authMethod: AuthMethodType;
|
||||||
|
abstract checkAuthResultEvent$: Observable<CheckAuthResultEventType>;
|
||||||
|
abstract isAuthenticated$: Observable<boolean>;
|
||||||
|
abstract userData$: Observable<any>;
|
||||||
|
abstract getAccessToken(): Observable<string | undefined>;
|
||||||
|
abstract setup(): void;
|
||||||
|
abstract autoLoginPartialRoutesGuard(): Observable<boolean>;
|
||||||
|
getAuthHeaders(): Observable<Record<string, string>> {
|
||||||
|
return this.getAccessToken().pipe(
|
||||||
|
map((accessToken) =>
|
||||||
|
accessToken
|
||||||
|
? {
|
||||||
|
Authorization: `Bearer ${accessToken}`,
|
||||||
|
}
|
||||||
|
: ({} as Record<string, string>)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AUTH_PROVIDER = new InjectionToken<AuthProvider>('AUTH_PROVIDER');
|
22
apps/webui/src/infra/auth/basic/basic-auth.provider.ts
Normal file
22
apps/webui/src/infra/auth/basic/basic-auth.provider.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { UnreachableError } from '@/infra/errors/common';
|
||||||
|
import type { CheckAuthResultEventType } from 'oidc-client-rx';
|
||||||
|
import { NEVER, type Observable, of } from 'rxjs';
|
||||||
|
import { AuthProvider } from '../auth.provider';
|
||||||
|
import { AUTH_METHOD } from '../defs';
|
||||||
|
|
||||||
|
export class BasicAuthProvider extends AuthProvider {
|
||||||
|
authMethod = AUTH_METHOD.BASIC;
|
||||||
|
isAuthenticated$ = of(true);
|
||||||
|
userData$ = of({});
|
||||||
|
checkAuthResultEvent$: Observable<CheckAuthResultEventType> = NEVER;
|
||||||
|
|
||||||
|
getAccessToken(): Observable<string | undefined> {
|
||||||
|
return of(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
setup(): void {}
|
||||||
|
|
||||||
|
autoLoginPartialRoutesGuard(): Observable<boolean> {
|
||||||
|
throw new UnreachableError('Basic auth should always be authenticated');
|
||||||
|
}
|
||||||
|
}
|
1
apps/webui/src/infra/auth/basic/index.ts
Normal file
1
apps/webui/src/infra/auth/basic/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { BasicAuthProvider } from './basic-auth.provider';
|
12
apps/webui/src/infra/auth/defs.ts
Normal file
12
apps/webui/src/infra/auth/defs.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import type { ValueOf } from 'type-fest';
|
||||||
|
|
||||||
|
export const AUTH_METHOD = {
|
||||||
|
BASIC: 'basic',
|
||||||
|
OIDC: 'oidc',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type AuthMethodType = ValueOf<typeof AUTH_METHOD>;
|
||||||
|
|
||||||
|
export function getAppAuthMethod(): AuthMethodType {
|
||||||
|
return process.env.AUTH_TYPE as AuthMethodType;
|
||||||
|
}
|
@ -1,14 +1,4 @@
|
|||||||
import { LogLevel, type OpenIdConfiguration } from 'oidc-client-rx';
|
import { LogLevel, type OpenIdConfiguration } from 'oidc-client-rx';
|
||||||
import type { ValueOf } from 'type-fest';
|
|
||||||
|
|
||||||
export const AuthMethodEnum = {
|
|
||||||
BASIC: 'basic',
|
|
||||||
OIDC: 'oidc',
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export type AuthMethodType = ValueOf<typeof AuthMethodEnum>;
|
|
||||||
|
|
||||||
export const AppAuthMethod = process.env.AUTH_TYPE as AuthMethodType;
|
|
||||||
|
|
||||||
export function buildOidcConfig(): OpenIdConfiguration {
|
export function buildOidcConfig(): OpenIdConfiguration {
|
||||||
const origin = window.location.origin;
|
const origin = window.location.origin;
|
2
apps/webui/src/infra/auth/oidc/index.ts
Normal file
2
apps/webui/src/infra/auth/oidc/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { buildOidcConfig } from './config';
|
||||||
|
export { OidcAuthProvider } from './oidc-auth.provider';
|
41
apps/webui/src/infra/auth/oidc/oidc-auth.provider.ts
Normal file
41
apps/webui/src/infra/auth/oidc/oidc-auth.provider.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { injectInjector } from '@/infra/di/inject';
|
||||||
|
import { inject, runInInjectionContext } from '@outposts/injection-js';
|
||||||
|
import {
|
||||||
|
CHECK_AUTH_RESULT_EVENT,
|
||||||
|
OidcSecurityService,
|
||||||
|
autoLoginPartialRoutesGuard,
|
||||||
|
} from 'oidc-client-rx';
|
||||||
|
import { type Observable, map } from 'rxjs';
|
||||||
|
import { AuthProvider } from '../auth.provider';
|
||||||
|
import { AUTH_METHOD } from '../defs';
|
||||||
|
|
||||||
|
export class OidcAuthProvider extends AuthProvider {
|
||||||
|
authMethod = AUTH_METHOD.OIDC;
|
||||||
|
oidcSecurityService = inject(OidcSecurityService);
|
||||||
|
checkAuthResultEvent$ = inject(CHECK_AUTH_RESULT_EVENT);
|
||||||
|
injector = injectInjector();
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
this.oidcSecurityService.checkAuth().subscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
get isAuthenticated$() {
|
||||||
|
return this.oidcSecurityService.isAuthenticated$.pipe(
|
||||||
|
map((s) => s.isAuthenticated)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get userData$() {
|
||||||
|
return this.oidcSecurityService.userData$.pipe(map((s) => s.userData));
|
||||||
|
}
|
||||||
|
|
||||||
|
getAccessToken(): Observable<string | undefined> {
|
||||||
|
return this.oidcSecurityService.getAccessToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
autoLoginPartialRoutesGuard() {
|
||||||
|
return runInInjectionContext(this.injector, () =>
|
||||||
|
autoLoginPartialRoutesGuard()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
16
apps/webui/src/infra/graphql/context.ts
Normal file
16
apps/webui/src/infra/graphql/context.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import type { Injector, Provider } from '@outposts/injection-js';
|
||||||
|
import { GraphQLService } from './graphql.service';
|
||||||
|
|
||||||
|
export function provideGraphql(): Provider[] {
|
||||||
|
return [GraphQLService];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GraphQLContext {
|
||||||
|
graphqlService: GraphQLService;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function graphqlContextFromInjector(injector: Injector): GraphQLContext {
|
||||||
|
return {
|
||||||
|
graphqlService: injector.get(GraphQLService),
|
||||||
|
};
|
||||||
|
}
|
30
apps/webui/src/infra/graphql/graphql.service.ts
Normal file
30
apps/webui/src/infra/graphql/graphql.service.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client';
|
||||||
|
import { setContext } from '@apollo/client/link/context';
|
||||||
|
import { Injectable, inject } from '@outposts/injection-js';
|
||||||
|
import { firstValueFrom } from 'rxjs';
|
||||||
|
import { AUTH_PROVIDER } from '../auth/auth.provider.ts';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class GraphQLService {
|
||||||
|
private authProvider = inject(AUTH_PROVIDER);
|
||||||
|
|
||||||
|
private apiLink = createHttpLink({
|
||||||
|
uri: '/api/graphql',
|
||||||
|
});
|
||||||
|
|
||||||
|
private authLink = setContext(async (_, { headers }) => {
|
||||||
|
const authHeaders = await firstValueFrom(
|
||||||
|
this.authProvider.getAuthHeaders()
|
||||||
|
);
|
||||||
|
return { headers: { ...headers, ...authHeaders } };
|
||||||
|
});
|
||||||
|
|
||||||
|
_apollo = new ApolloClient({
|
||||||
|
link: this.authLink.concat(this.apiLink),
|
||||||
|
cache: new InMemoryCache(),
|
||||||
|
});
|
||||||
|
|
||||||
|
query = this._apollo.query;
|
||||||
|
mutate = this._apollo.mutate;
|
||||||
|
watchQuery = this._apollo.watchQuery;
|
||||||
|
}
|
2
apps/webui/src/infra/graphql/index.ts
Normal file
2
apps/webui/src/infra/graphql/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { GraphQLService } from './graphql.service';
|
||||||
|
export { provideGraphql } from './context';
|
@ -1,21 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
const MOBILE_BREAKPOINT = 768;
|
|
||||||
|
|
||||||
export function useIsMobile() {
|
|
||||||
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(
|
|
||||||
undefined
|
|
||||||
);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
||||||
const onChange = () => {
|
|
||||||
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
||||||
};
|
|
||||||
mql.addEventListener('change', onChange);
|
|
||||||
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
||||||
return () => mql.removeEventListener('change', onChange);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return !!isMobile;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
import { Injectable, inject } from '@outposts/injection-js';
|
|
||||||
import { OidcSecurityService } from 'oidc-client-rx';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class HttpService {
|
|
||||||
authService = inject(OidcSecurityService);
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
import type { ProLinkProps } from '@/components/ui/pro-link';
|
import type { ProLinkProps } from '@/views/components/ui/pro-link';
|
||||||
import type { Injector } from '@outposts/injection-js';
|
import type { Injector } from '@outposts/injection-js';
|
||||||
import type { LucideIcon } from 'lucide-react';
|
import type { LucideIcon } from 'lucide-react';
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { guardRouteIndexAsNotFound } from '@/components/layout/app-not-found';
|
|
||||||
import type { RouteStateDataOption } from '@/infra/routes/traits';
|
import type { RouteStateDataOption } from '@/infra/routes/traits';
|
||||||
|
import { guardRouteIndexAsNotFound } from '@/views/components/layout/app-not-found';
|
||||||
import { Outlet } from '@tanstack/react-router';
|
import { Outlet } from '@tanstack/react-router';
|
||||||
|
|
||||||
export interface BuildVirtualBranchRouteOptions {
|
export interface BuildVirtualBranchRouteOptions {
|
||||||
|
@ -3,6 +3,8 @@ import { provideAuth, setupAuthContext } from '@/app/auth/context';
|
|||||||
import { providePlatform } from '@/infra/platform/context';
|
import { providePlatform } from '@/infra/platform/context';
|
||||||
import { provideStorages } from '@/infra/storage/context';
|
import { provideStorages } from '@/infra/storage/context';
|
||||||
import { provideStyles } from '@/infra/styles/context';
|
import { provideStyles } from '@/infra/styles/context';
|
||||||
|
import { AppNotFoundComponent } from '@/views/components/layout/app-not-found';
|
||||||
|
import { routeTree } from '@/views/routeTree.gen';
|
||||||
import { type Injector, ReflectiveInjector } from '@outposts/injection-js';
|
import { type Injector, ReflectiveInjector } from '@outposts/injection-js';
|
||||||
import { RouterProvider, createRouter } from '@tanstack/react-router';
|
import { RouterProvider, createRouter } from '@tanstack/react-router';
|
||||||
import {
|
import {
|
||||||
@ -11,9 +13,10 @@ import {
|
|||||||
} from 'oidc-client-rx/adapters/react';
|
} from 'oidc-client-rx/adapters/react';
|
||||||
import { Suspense } from 'react';
|
import { Suspense } from 'react';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
import { AppNotFoundComponent } from './components/layout/app-not-found';
|
|
||||||
import { routeTree } from './routeTree.gen';
|
|
||||||
import './app.css';
|
import './app.css';
|
||||||
|
import { ApolloProvider } from '@apollo/client';
|
||||||
|
import { provideGraphql } from './infra/graphql';
|
||||||
|
import { graphqlContextFromInjector } from './infra/graphql/context';
|
||||||
|
|
||||||
// Create a new router instance
|
// Create a new router instance
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
@ -40,22 +43,27 @@ const injector: Injector = ReflectiveInjector.resolveAndCreate([
|
|||||||
...provideStorages(),
|
...provideStorages(),
|
||||||
...provideAuth(router),
|
...provideAuth(router),
|
||||||
...provideStyles(),
|
...provideStyles(),
|
||||||
|
...provideGraphql(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
setupAuthContext(injector);
|
setupAuthContext(injector);
|
||||||
|
|
||||||
const rootElement = document.getElementById('root');
|
const rootElement = document.getElementById('root');
|
||||||
|
|
||||||
|
const { graphqlService } = graphqlContextFromInjector(injector);
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
||||||
<InjectorProvider injector={injector}>
|
<InjectorProvider injector={injector}>
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<RouterProvider
|
<ApolloProvider client={graphqlService._apollo}>
|
||||||
router={router}
|
<RouterProvider
|
||||||
context={{
|
router={router}
|
||||||
injector,
|
context={{
|
||||||
}}
|
injector,
|
||||||
/>
|
}}
|
||||||
|
/>
|
||||||
|
</ApolloProvider>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</InjectorProvider>
|
</InjectorProvider>
|
||||||
);
|
);
|
||||||
|
@ -2,9 +2,9 @@ import {
|
|||||||
SidebarMenu,
|
SidebarMenu,
|
||||||
SidebarMenuButton,
|
SidebarMenuButton,
|
||||||
SidebarMenuItem,
|
SidebarMenuItem,
|
||||||
} from '@/components/ui/sidebar';
|
} from '@/views/components/ui/sidebar';
|
||||||
|
|
||||||
import { Image } from '@/components/ui/image';
|
import { Image } from '@/views/components/ui/image';
|
||||||
|
|
||||||
export function AppIcon() {
|
export function AppIcon() {
|
||||||
return (
|
return (
|
@ -1,4 +1,6 @@
|
|||||||
import { AppSidebar } from '@/components/layout/app-sidebar';
|
import type { RouteStateDataOption } from '@/infra/routes/traits';
|
||||||
|
import type { RouteBreadcrumbItem } from '@/infra/routes/traits';
|
||||||
|
import { AppSidebar } from '@/views/components/layout/app-sidebar';
|
||||||
import {
|
import {
|
||||||
Breadcrumb,
|
Breadcrumb,
|
||||||
BreadcrumbItem,
|
BreadcrumbItem,
|
||||||
@ -6,16 +8,14 @@ import {
|
|||||||
BreadcrumbList,
|
BreadcrumbList,
|
||||||
BreadcrumbPage,
|
BreadcrumbPage,
|
||||||
BreadcrumbSeparator,
|
BreadcrumbSeparator,
|
||||||
} from '@/components/ui/breadcrumb';
|
} from '@/views/components/ui/breadcrumb';
|
||||||
import { Separator } from '@/components/ui/separator';
|
import { Separator } from '@/views/components/ui/separator';
|
||||||
import {
|
import {
|
||||||
SidebarInset,
|
SidebarInset,
|
||||||
SidebarProvider,
|
SidebarProvider,
|
||||||
SidebarTrigger,
|
SidebarTrigger,
|
||||||
} from '@/components/ui/sidebar';
|
} from '@/views/components/ui/sidebar';
|
||||||
import type { RouteStateDataOption } from '@/infra/routes/traits';
|
import { cn } from '@/views/utils';
|
||||||
import type { RouteBreadcrumbItem } from '@/infra/routes/traits';
|
|
||||||
import { cn } from '@/infra/styles/utils';
|
|
||||||
import { useMatches } from '@tanstack/react-router';
|
import { useMatches } from '@tanstack/react-router';
|
||||||
import {
|
import {
|
||||||
type DetailedHTMLProps,
|
type DetailedHTMLProps,
|
@ -1,11 +1,11 @@
|
|||||||
|
import { AppNavMainData } from '@/infra/routes/nav';
|
||||||
import {
|
import {
|
||||||
Sidebar,
|
Sidebar,
|
||||||
SidebarContent,
|
SidebarContent,
|
||||||
SidebarFooter,
|
SidebarFooter,
|
||||||
SidebarHeader,
|
SidebarHeader,
|
||||||
SidebarRail,
|
SidebarRail,
|
||||||
} from '@/components/ui/sidebar';
|
} from '@/views/components/ui/sidebar';
|
||||||
import { AppNavMainData } from '@/infra/routes/nav';
|
|
||||||
import type { ComponentPropsWithoutRef } from 'react';
|
import type { ComponentPropsWithoutRef } from 'react';
|
||||||
import { AppIcon } from './app-icon';
|
import { AppIcon } from './app-icon';
|
||||||
import { NavMain } from './nav-main';
|
import { NavMain } from './nav-main';
|
@ -6,7 +6,7 @@ import {
|
|||||||
Collapsible,
|
Collapsible,
|
||||||
CollapsibleContent,
|
CollapsibleContent,
|
||||||
CollapsibleTrigger,
|
CollapsibleTrigger,
|
||||||
} from '@/components/ui/collapsible';
|
} from '@/views/components/ui/collapsible';
|
||||||
import {
|
import {
|
||||||
SidebarGroup,
|
SidebarGroup,
|
||||||
SidebarGroupLabel,
|
SidebarGroupLabel,
|
||||||
@ -16,7 +16,7 @@ import {
|
|||||||
SidebarMenuSub,
|
SidebarMenuSub,
|
||||||
SidebarMenuSubButton,
|
SidebarMenuSubButton,
|
||||||
SidebarMenuSubItem,
|
SidebarMenuSubItem,
|
||||||
} from '@/components/ui/sidebar';
|
} from '@/views/components/ui/sidebar';
|
||||||
import { useMatches } from '@tanstack/react-router';
|
import { useMatches } from '@tanstack/react-router';
|
||||||
import { ProLink, type ProLinkProps } from '../ui/pro-link';
|
import { ProLink, type ProLinkProps } from '../ui/pro-link';
|
||||||
|
|
@ -16,7 +16,7 @@ import {
|
|||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuSeparator,
|
DropdownMenuSeparator,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from '@/components/ui/dropdown-menu';
|
} from '@/views/components/ui/dropdown-menu';
|
||||||
import {
|
import {
|
||||||
SidebarGroup,
|
SidebarGroup,
|
||||||
SidebarGroupLabel,
|
SidebarGroupLabel,
|
||||||
@ -25,7 +25,7 @@ import {
|
|||||||
SidebarMenuButton,
|
SidebarMenuButton,
|
||||||
SidebarMenuItem,
|
SidebarMenuItem,
|
||||||
useSidebar,
|
useSidebar,
|
||||||
} from '@/components/ui/sidebar';
|
} from '@/views/components/ui/sidebar';
|
||||||
import type { ComponentProps } from 'react';
|
import type { ComponentProps } from 'react';
|
||||||
|
|
||||||
export function NavProjects({
|
export function NavProjects({
|
@ -9,7 +9,11 @@ import {
|
|||||||
Sparkles,
|
Sparkles,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
|
|
||||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
import {
|
||||||
|
Avatar,
|
||||||
|
AvatarFallback,
|
||||||
|
AvatarImage,
|
||||||
|
} from '@/views/components/ui/avatar';
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
@ -18,13 +22,13 @@ import {
|
|||||||
DropdownMenuLabel,
|
DropdownMenuLabel,
|
||||||
DropdownMenuSeparator,
|
DropdownMenuSeparator,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from '@/components/ui/dropdown-menu';
|
} from '@/views/components/ui/dropdown-menu';
|
||||||
import {
|
import {
|
||||||
SidebarMenu,
|
SidebarMenu,
|
||||||
SidebarMenuButton,
|
SidebarMenuButton,
|
||||||
SidebarMenuItem,
|
SidebarMenuItem,
|
||||||
useSidebar,
|
useSidebar,
|
||||||
} from '@/components/ui/sidebar';
|
} from '@/views/components/ui/sidebar';
|
||||||
|
|
||||||
export function NavUser({
|
export function NavUser({
|
||||||
user,
|
user,
|
@ -1,13 +1,13 @@
|
|||||||
import * as React from "react"
|
import * as AccordionPrimitive from "@radix-ui/react-accordion";
|
||||||
import * as AccordionPrimitive from "@radix-ui/react-accordion"
|
import { ChevronDownIcon } from "lucide-react";
|
||||||
import { ChevronDownIcon } from "lucide-react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Accordion({
|
function Accordion({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof AccordionPrimitive.Root>) {
|
}: React.ComponentProps<typeof AccordionPrimitive.Root>) {
|
||||||
return <AccordionPrimitive.Root data-slot="accordion" {...props} />
|
return <AccordionPrimitive.Root data-slot="accordion" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function AccordionItem({
|
function AccordionItem({
|
||||||
@ -20,7 +20,7 @@ function AccordionItem({
|
|||||||
className={cn("border-b last:border-b-0", className)}
|
className={cn("border-b last:border-b-0", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AccordionTrigger({
|
function AccordionTrigger({
|
||||||
@ -42,7 +42,7 @@ function AccordionTrigger({
|
|||||||
<ChevronDownIcon className="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" />
|
<ChevronDownIcon className="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" />
|
||||||
</AccordionPrimitive.Trigger>
|
</AccordionPrimitive.Trigger>
|
||||||
</AccordionPrimitive.Header>
|
</AccordionPrimitive.Header>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AccordionContent({
|
function AccordionContent({
|
||||||
@ -58,7 +58,7 @@ function AccordionContent({
|
|||||||
>
|
>
|
||||||
<div className={cn("pt-0 pb-4", className)}>{children}</div>
|
<div className={cn("pt-0 pb-4", className)}>{children}</div>
|
||||||
</AccordionPrimitive.Content>
|
</AccordionPrimitive.Content>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
|
@ -1,15 +1,15 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
|
||||||
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { buttonVariants } from "@/views/components/ui/button";
|
||||||
import { buttonVariants } from "@/components/ui/button"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function AlertDialog({
|
function AlertDialog({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
|
}: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
|
||||||
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />
|
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function AlertDialogTrigger({
|
function AlertDialogTrigger({
|
||||||
@ -17,7 +17,7 @@ function AlertDialogTrigger({
|
|||||||
}: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
|
}: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
|
||||||
return (
|
return (
|
||||||
<AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
|
<AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AlertDialogPortal({
|
function AlertDialogPortal({
|
||||||
@ -25,7 +25,7 @@ function AlertDialogPortal({
|
|||||||
}: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
|
}: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
|
||||||
return (
|
return (
|
||||||
<AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
|
<AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AlertDialogOverlay({
|
function AlertDialogOverlay({
|
||||||
@ -41,7 +41,7 @@ function AlertDialogOverlay({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AlertDialogContent({
|
function AlertDialogContent({
|
||||||
@ -60,7 +60,7 @@ function AlertDialogContent({
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</AlertDialogPortal>
|
</AlertDialogPortal>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AlertDialogHeader({
|
function AlertDialogHeader({
|
||||||
@ -73,7 +73,7 @@ function AlertDialogHeader({
|
|||||||
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AlertDialogFooter({
|
function AlertDialogFooter({
|
||||||
@ -89,7 +89,7 @@ function AlertDialogFooter({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AlertDialogTitle({
|
function AlertDialogTitle({
|
||||||
@ -102,7 +102,7 @@ function AlertDialogTitle({
|
|||||||
className={cn("text-lg font-semibold", className)}
|
className={cn("text-lg font-semibold", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AlertDialogDescription({
|
function AlertDialogDescription({
|
||||||
@ -115,7 +115,7 @@ function AlertDialogDescription({
|
|||||||
className={cn("text-muted-foreground text-sm", className)}
|
className={cn("text-muted-foreground text-sm", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AlertDialogAction({
|
function AlertDialogAction({
|
||||||
@ -127,7 +127,7 @@ function AlertDialogAction({
|
|||||||
className={cn(buttonVariants(), className)}
|
className={cn(buttonVariants(), className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AlertDialogCancel({
|
function AlertDialogCancel({
|
||||||
@ -139,7 +139,7 @@ function AlertDialogCancel({
|
|||||||
className={cn(buttonVariants({ variant: "outline" }), className)}
|
className={cn(buttonVariants({ variant: "outline" }), className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -154,4 +154,4 @@ export {
|
|||||||
AlertDialogDescription,
|
AlertDialogDescription,
|
||||||
AlertDialogAction,
|
AlertDialogAction,
|
||||||
AlertDialogCancel,
|
AlertDialogCancel,
|
||||||
}
|
};
|
@ -1,7 +1,7 @@
|
|||||||
import * as React from "react"
|
import { type VariantProps, cva } from "class-variance-authority";
|
||||||
import { cva, type VariantProps } from "class-variance-authority"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
const alertVariants = cva(
|
const alertVariants = cva(
|
||||||
"relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
|
"relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
|
||||||
@ -17,7 +17,7 @@ const alertVariants = cva(
|
|||||||
variant: "default",
|
variant: "default",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
|
|
||||||
function Alert({
|
function Alert({
|
||||||
className,
|
className,
|
||||||
@ -31,7 +31,7 @@ function Alert({
|
|||||||
className={cn(alertVariants({ variant }), className)}
|
className={cn(alertVariants({ variant }), className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
|
function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@ -44,7 +44,7 @@ function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AlertDescription({
|
function AlertDescription({
|
||||||
@ -60,7 +60,7 @@ function AlertDescription({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Alert, AlertTitle, AlertDescription }
|
export { Alert, AlertTitle, AlertDescription };
|
@ -1,9 +1,9 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
||||||
import * as AvatarPrimitive from "@radix-ui/react-avatar"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Avatar({
|
function Avatar({
|
||||||
className,
|
className,
|
||||||
@ -18,7 +18,7 @@ function Avatar({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AvatarImage({
|
function AvatarImage({
|
||||||
@ -31,7 +31,7 @@ function AvatarImage({
|
|||||||
className={cn("aspect-square size-full", className)}
|
className={cn("aspect-square size-full", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AvatarFallback({
|
function AvatarFallback({
|
||||||
@ -47,7 +47,7 @@ function AvatarFallback({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Avatar, AvatarImage, AvatarFallback }
|
export { Avatar, AvatarImage, AvatarFallback };
|
@ -1,8 +1,8 @@
|
|||||||
import * as React from "react"
|
import { Slot } from "@radix-ui/react-slot";
|
||||||
import { Slot } from "@radix-ui/react-slot"
|
import { type VariantProps, cva } from "class-variance-authority";
|
||||||
import { cva, type VariantProps } from "class-variance-authority"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
const badgeVariants = cva(
|
const badgeVariants = cva(
|
||||||
"inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
|
"inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
|
||||||
@ -23,7 +23,7 @@ const badgeVariants = cva(
|
|||||||
variant: "default",
|
variant: "default",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
|
|
||||||
function Badge({
|
function Badge({
|
||||||
className,
|
className,
|
||||||
@ -32,7 +32,7 @@ function Badge({
|
|||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"span"> &
|
}: React.ComponentProps<"span"> &
|
||||||
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
|
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
|
||||||
const Comp = asChild ? Slot : "span"
|
const Comp = asChild ? Slot : "span";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Comp
|
<Comp
|
||||||
@ -40,7 +40,7 @@ function Badge({
|
|||||||
className={cn(badgeVariants({ variant }), className)}
|
className={cn(badgeVariants({ variant }), className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Badge, badgeVariants }
|
export { Badge, badgeVariants };
|
@ -1,11 +1,11 @@
|
|||||||
import * as React from "react"
|
import { Slot } from "@radix-ui/react-slot";
|
||||||
import { Slot } from "@radix-ui/react-slot"
|
import { ChevronRight, MoreHorizontal } from "lucide-react";
|
||||||
import { ChevronRight, MoreHorizontal } from "lucide-react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
|
function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
|
||||||
return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />
|
return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
|
function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
|
||||||
@ -18,7 +18,7 @@ function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
|
function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
|
||||||
@ -28,7 +28,7 @@ function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
|
|||||||
className={cn("inline-flex items-center gap-1.5", className)}
|
className={cn("inline-flex items-center gap-1.5", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function BreadcrumbLink({
|
function BreadcrumbLink({
|
||||||
@ -36,9 +36,9 @@ function BreadcrumbLink({
|
|||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"a"> & {
|
}: React.ComponentProps<"a"> & {
|
||||||
asChild?: boolean
|
asChild?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const Comp = asChild ? Slot : "a"
|
const Comp = asChild ? Slot : "a";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Comp
|
<Comp
|
||||||
@ -46,7 +46,7 @@ function BreadcrumbLink({
|
|||||||
className={cn("hover:text-foreground transition-colors", className)}
|
className={cn("hover:text-foreground transition-colors", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
|
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
|
||||||
@ -59,7 +59,7 @@ function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
|
|||||||
className={cn("text-foreground font-normal", className)}
|
className={cn("text-foreground font-normal", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function BreadcrumbSeparator({
|
function BreadcrumbSeparator({
|
||||||
@ -77,7 +77,7 @@ function BreadcrumbSeparator({
|
|||||||
>
|
>
|
||||||
{children ?? <ChevronRight />}
|
{children ?? <ChevronRight />}
|
||||||
</li>
|
</li>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function BreadcrumbEllipsis({
|
function BreadcrumbEllipsis({
|
||||||
@ -95,7 +95,7 @@ function BreadcrumbEllipsis({
|
|||||||
<MoreHorizontal className="size-4" />
|
<MoreHorizontal className="size-4" />
|
||||||
<span className="sr-only">More</span>
|
<span className="sr-only">More</span>
|
||||||
</span>
|
</span>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -106,4 +106,4 @@ export {
|
|||||||
BreadcrumbPage,
|
BreadcrumbPage,
|
||||||
BreadcrumbSeparator,
|
BreadcrumbSeparator,
|
||||||
BreadcrumbEllipsis,
|
BreadcrumbEllipsis,
|
||||||
}
|
};
|
@ -1,8 +1,8 @@
|
|||||||
import * as React from "react"
|
import { Slot } from "@radix-ui/react-slot";
|
||||||
import { Slot } from "@radix-ui/react-slot"
|
import { type VariantProps, cva } from "class-variance-authority";
|
||||||
import { cva, type VariantProps } from "class-variance-authority"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
const buttonVariants = cva(
|
const buttonVariants = cva(
|
||||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||||
@ -33,7 +33,7 @@ const buttonVariants = cva(
|
|||||||
size: "default",
|
size: "default",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
|
|
||||||
function Button({
|
function Button({
|
||||||
className,
|
className,
|
||||||
@ -43,9 +43,9 @@ function Button({
|
|||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"button"> &
|
}: React.ComponentProps<"button"> &
|
||||||
VariantProps<typeof buttonVariants> & {
|
VariantProps<typeof buttonVariants> & {
|
||||||
asChild?: boolean
|
asChild?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const Comp = asChild ? Slot : "button"
|
const Comp = asChild ? Slot : "button";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Comp
|
<Comp
|
||||||
@ -53,7 +53,7 @@ function Button({
|
|||||||
className={cn(buttonVariants({ variant, size, className }))}
|
className={cn(buttonVariants({ variant, size, className }))}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Button, buttonVariants }
|
export { Button, buttonVariants };
|
@ -1,9 +1,9 @@
|
|||||||
import * as React from "react"
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react"
|
import * as React from "react";
|
||||||
import { DayPicker } from "react-day-picker"
|
import { DayPicker } from "react-day-picker";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { buttonVariants } from "@/views/components/ui/button";
|
||||||
import { buttonVariants } from "@/components/ui/button"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Calendar({
|
function Calendar({
|
||||||
className,
|
className,
|
||||||
@ -67,7 +67,7 @@ function Calendar({
|
|||||||
}}
|
}}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Calendar }
|
export { Calendar };
|
@ -1,6 +1,6 @@
|
|||||||
import * as React from "react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Card({ className, ...props }: React.ComponentProps<"div">) {
|
function Card({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
return (
|
return (
|
||||||
@ -12,7 +12,7 @@ function Card({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@ -25,7 +25,7 @@ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@ -35,7 +35,7 @@ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
className={cn("leading-none font-semibold", className)}
|
className={cn("leading-none font-semibold", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@ -45,7 +45,7 @@ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
className={cn("text-muted-foreground text-sm", className)}
|
className={cn("text-muted-foreground text-sm", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@ -58,7 +58,7 @@ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@ -68,7 +68,7 @@ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
className={cn("px-6", className)}
|
className={cn("px-6", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@ -78,7 +78,7 @@ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
|
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -89,4 +89,4 @@ export {
|
|||||||
CardAction,
|
CardAction,
|
||||||
CardDescription,
|
CardDescription,
|
||||||
CardContent,
|
CardContent,
|
||||||
}
|
};
|
@ -1,45 +1,45 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
|
||||||
import useEmblaCarousel, {
|
import useEmblaCarousel, {
|
||||||
type UseEmblaCarouselType,
|
type UseEmblaCarouselType,
|
||||||
} from "embla-carousel-react"
|
} from "embla-carousel-react";
|
||||||
import { ArrowLeft, ArrowRight } from "lucide-react"
|
import { ArrowLeft, ArrowRight } from "lucide-react";
|
||||||
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { Button } from "@/views/components/ui/button";
|
||||||
import { Button } from "@/components/ui/button"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
type CarouselApi = UseEmblaCarouselType[1]
|
type CarouselApi = UseEmblaCarouselType[1];
|
||||||
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
|
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>;
|
||||||
type CarouselOptions = UseCarouselParameters[0]
|
type CarouselOptions = UseCarouselParameters[0];
|
||||||
type CarouselPlugin = UseCarouselParameters[1]
|
type CarouselPlugin = UseCarouselParameters[1];
|
||||||
|
|
||||||
type CarouselProps = {
|
type CarouselProps = {
|
||||||
opts?: CarouselOptions
|
opts?: CarouselOptions;
|
||||||
plugins?: CarouselPlugin
|
plugins?: CarouselPlugin;
|
||||||
orientation?: "horizontal" | "vertical"
|
orientation?: "horizontal" | "vertical";
|
||||||
setApi?: (api: CarouselApi) => void
|
setApi?: (api: CarouselApi) => void;
|
||||||
}
|
};
|
||||||
|
|
||||||
type CarouselContextProps = {
|
type CarouselContextProps = {
|
||||||
carouselRef: ReturnType<typeof useEmblaCarousel>[0]
|
carouselRef: ReturnType<typeof useEmblaCarousel>[0];
|
||||||
api: ReturnType<typeof useEmblaCarousel>[1]
|
api: ReturnType<typeof useEmblaCarousel>[1];
|
||||||
scrollPrev: () => void
|
scrollPrev: () => void;
|
||||||
scrollNext: () => void
|
scrollNext: () => void;
|
||||||
canScrollPrev: boolean
|
canScrollPrev: boolean;
|
||||||
canScrollNext: boolean
|
canScrollNext: boolean;
|
||||||
} & CarouselProps
|
} & CarouselProps;
|
||||||
|
|
||||||
const CarouselContext = React.createContext<CarouselContextProps | null>(null)
|
const CarouselContext = React.createContext<CarouselContextProps | null>(null);
|
||||||
|
|
||||||
function useCarousel() {
|
function useCarousel() {
|
||||||
const context = React.useContext(CarouselContext)
|
const context = React.useContext(CarouselContext);
|
||||||
|
|
||||||
if (!context) {
|
if (!context) {
|
||||||
throw new Error("useCarousel must be used within a <Carousel />")
|
throw new Error("useCarousel must be used within a <Carousel />");
|
||||||
}
|
}
|
||||||
|
|
||||||
return context
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Carousel({
|
function Carousel({
|
||||||
@ -57,52 +57,52 @@ function Carousel({
|
|||||||
axis: orientation === "horizontal" ? "x" : "y",
|
axis: orientation === "horizontal" ? "x" : "y",
|
||||||
},
|
},
|
||||||
plugins
|
plugins
|
||||||
)
|
);
|
||||||
const [canScrollPrev, setCanScrollPrev] = React.useState(false)
|
const [canScrollPrev, setCanScrollPrev] = React.useState(false);
|
||||||
const [canScrollNext, setCanScrollNext] = React.useState(false)
|
const [canScrollNext, setCanScrollNext] = React.useState(false);
|
||||||
|
|
||||||
const onSelect = React.useCallback((api: CarouselApi) => {
|
const onSelect = React.useCallback((api: CarouselApi) => {
|
||||||
if (!api) return
|
if (!api) return;
|
||||||
setCanScrollPrev(api.canScrollPrev())
|
setCanScrollPrev(api.canScrollPrev());
|
||||||
setCanScrollNext(api.canScrollNext())
|
setCanScrollNext(api.canScrollNext());
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
const scrollPrev = React.useCallback(() => {
|
const scrollPrev = React.useCallback(() => {
|
||||||
api?.scrollPrev()
|
api?.scrollPrev();
|
||||||
}, [api])
|
}, [api]);
|
||||||
|
|
||||||
const scrollNext = React.useCallback(() => {
|
const scrollNext = React.useCallback(() => {
|
||||||
api?.scrollNext()
|
api?.scrollNext();
|
||||||
}, [api])
|
}, [api]);
|
||||||
|
|
||||||
const handleKeyDown = React.useCallback(
|
const handleKeyDown = React.useCallback(
|
||||||
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
if (event.key === "ArrowLeft") {
|
if (event.key === "ArrowLeft") {
|
||||||
event.preventDefault()
|
event.preventDefault();
|
||||||
scrollPrev()
|
scrollPrev();
|
||||||
} else if (event.key === "ArrowRight") {
|
} else if (event.key === "ArrowRight") {
|
||||||
event.preventDefault()
|
event.preventDefault();
|
||||||
scrollNext()
|
scrollNext();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[scrollPrev, scrollNext]
|
[scrollPrev, scrollNext]
|
||||||
)
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!api || !setApi) return
|
if (!api || !setApi) return;
|
||||||
setApi(api)
|
setApi(api);
|
||||||
}, [api, setApi])
|
}, [api, setApi]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!api) return
|
if (!api) return;
|
||||||
onSelect(api)
|
onSelect(api);
|
||||||
api.on("reInit", onSelect)
|
api.on("reInit", onSelect);
|
||||||
api.on("select", onSelect)
|
api.on("select", onSelect);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
api?.off("select", onSelect)
|
api?.off("select", onSelect);
|
||||||
}
|
};
|
||||||
}, [api, onSelect])
|
}, [api, onSelect]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CarouselContext.Provider
|
<CarouselContext.Provider
|
||||||
@ -129,11 +129,11 @@ function Carousel({
|
|||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</CarouselContext.Provider>
|
</CarouselContext.Provider>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CarouselContent({ className, ...props }: React.ComponentProps<"div">) {
|
function CarouselContent({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
const { carouselRef, orientation } = useCarousel()
|
const { carouselRef, orientation } = useCarousel();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -150,11 +150,11 @@ function CarouselContent({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CarouselItem({ className, ...props }: React.ComponentProps<"div">) {
|
function CarouselItem({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
const { orientation } = useCarousel()
|
const { orientation } = useCarousel();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -168,7 +168,7 @@ function CarouselItem({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CarouselPrevious({
|
function CarouselPrevious({
|
||||||
@ -177,7 +177,7 @@ function CarouselPrevious({
|
|||||||
size = "icon",
|
size = "icon",
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof Button>) {
|
}: React.ComponentProps<typeof Button>) {
|
||||||
const { orientation, scrollPrev, canScrollPrev } = useCarousel()
|
const { orientation, scrollPrev, canScrollPrev } = useCarousel();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
@ -198,7 +198,7 @@ function CarouselPrevious({
|
|||||||
<ArrowLeft />
|
<ArrowLeft />
|
||||||
<span className="sr-only">Previous slide</span>
|
<span className="sr-only">Previous slide</span>
|
||||||
</Button>
|
</Button>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CarouselNext({
|
function CarouselNext({
|
||||||
@ -207,7 +207,7 @@ function CarouselNext({
|
|||||||
size = "icon",
|
size = "icon",
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof Button>) {
|
}: React.ComponentProps<typeof Button>) {
|
||||||
const { orientation, scrollNext, canScrollNext } = useCarousel()
|
const { orientation, scrollNext, canScrollNext } = useCarousel();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
@ -228,7 +228,7 @@ function CarouselNext({
|
|||||||
<ArrowRight />
|
<ArrowRight />
|
||||||
<span className="sr-only">Next slide</span>
|
<span className="sr-only">Next slide</span>
|
||||||
</Button>
|
</Button>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -238,4 +238,4 @@ export {
|
|||||||
CarouselItem,
|
CarouselItem,
|
||||||
CarouselPrevious,
|
CarouselPrevious,
|
||||||
CarouselNext,
|
CarouselNext,
|
||||||
}
|
};
|
@ -1,7 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as RechartsPrimitive from "recharts";
|
import * as RechartsPrimitive from "recharts";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils";
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
// Format: { THEME_NAME: CSS_SELECTOR }
|
// Format: { THEME_NAME: CSS_SELECTOR }
|
||||||
const THEMES = { light: "", dark: ".dark" } as const;
|
const THEMES = { light: "", dark: ".dark" } as const;
|
@ -1,10 +1,10 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
||||||
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
|
import { CheckIcon } from "lucide-react";
|
||||||
import { CheckIcon } from "lucide-react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Checkbox({
|
function Checkbox({
|
||||||
className,
|
className,
|
||||||
@ -26,7 +26,7 @@ function Checkbox({
|
|||||||
<CheckIcon className="size-3.5" />
|
<CheckIcon className="size-3.5" />
|
||||||
</CheckboxPrimitive.Indicator>
|
</CheckboxPrimitive.Indicator>
|
||||||
</CheckboxPrimitive.Root>
|
</CheckboxPrimitive.Root>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Checkbox }
|
export { Checkbox };
|
@ -1,17 +1,17 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import { Command as CommandPrimitive } from "cmdk";
|
||||||
import { Command as CommandPrimitive } from "cmdk"
|
import { SearchIcon } from "lucide-react";
|
||||||
import { SearchIcon } from "lucide-react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogDescription,
|
DialogDescription,
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from "@/components/ui/dialog"
|
} from "@/views/components/ui/dialog";
|
||||||
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Command({
|
function Command({
|
||||||
className,
|
className,
|
||||||
@ -26,7 +26,7 @@ function Command({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CommandDialog({
|
function CommandDialog({
|
||||||
@ -35,8 +35,8 @@ function CommandDialog({
|
|||||||
children,
|
children,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof Dialog> & {
|
}: React.ComponentProps<typeof Dialog> & {
|
||||||
title?: string
|
title?: string;
|
||||||
description?: string
|
description?: string;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Dialog {...props}>
|
<Dialog {...props}>
|
||||||
@ -50,7 +50,7 @@ function CommandDialog({
|
|||||||
</Command>
|
</Command>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CommandInput({
|
function CommandInput({
|
||||||
@ -72,7 +72,7 @@ function CommandInput({
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CommandList({
|
function CommandList({
|
||||||
@ -88,7 +88,7 @@ function CommandList({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CommandEmpty({
|
function CommandEmpty({
|
||||||
@ -100,7 +100,7 @@ function CommandEmpty({
|
|||||||
className="py-6 text-center text-sm"
|
className="py-6 text-center text-sm"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CommandGroup({
|
function CommandGroup({
|
||||||
@ -116,7 +116,7 @@ function CommandGroup({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CommandSeparator({
|
function CommandSeparator({
|
||||||
@ -129,7 +129,7 @@ function CommandSeparator({
|
|||||||
className={cn("bg-border -mx-1 h-px", className)}
|
className={cn("bg-border -mx-1 h-px", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CommandItem({
|
function CommandItem({
|
||||||
@ -145,7 +145,7 @@ function CommandItem({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CommandShortcut({
|
function CommandShortcut({
|
||||||
@ -161,7 +161,7 @@ function CommandShortcut({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -174,4 +174,4 @@ export {
|
|||||||
CommandItem,
|
CommandItem,
|
||||||
CommandShortcut,
|
CommandShortcut,
|
||||||
CommandSeparator,
|
CommandSeparator,
|
||||||
}
|
};
|
@ -1,15 +1,15 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
|
||||||
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"
|
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
|
||||||
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function ContextMenu({
|
function ContextMenu({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {
|
}: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {
|
||||||
return <ContextMenuPrimitive.Root data-slot="context-menu" {...props} />
|
return <ContextMenuPrimitive.Root data-slot="context-menu" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContextMenuTrigger({
|
function ContextMenuTrigger({
|
||||||
@ -17,7 +17,7 @@ function ContextMenuTrigger({
|
|||||||
}: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>) {
|
}: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>) {
|
||||||
return (
|
return (
|
||||||
<ContextMenuPrimitive.Trigger data-slot="context-menu-trigger" {...props} />
|
<ContextMenuPrimitive.Trigger data-slot="context-menu-trigger" {...props} />
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContextMenuGroup({
|
function ContextMenuGroup({
|
||||||
@ -25,7 +25,7 @@ function ContextMenuGroup({
|
|||||||
}: React.ComponentProps<typeof ContextMenuPrimitive.Group>) {
|
}: React.ComponentProps<typeof ContextMenuPrimitive.Group>) {
|
||||||
return (
|
return (
|
||||||
<ContextMenuPrimitive.Group data-slot="context-menu-group" {...props} />
|
<ContextMenuPrimitive.Group data-slot="context-menu-group" {...props} />
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContextMenuPortal({
|
function ContextMenuPortal({
|
||||||
@ -33,13 +33,13 @@ function ContextMenuPortal({
|
|||||||
}: React.ComponentProps<typeof ContextMenuPrimitive.Portal>) {
|
}: React.ComponentProps<typeof ContextMenuPrimitive.Portal>) {
|
||||||
return (
|
return (
|
||||||
<ContextMenuPrimitive.Portal data-slot="context-menu-portal" {...props} />
|
<ContextMenuPrimitive.Portal data-slot="context-menu-portal" {...props} />
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContextMenuSub({
|
function ContextMenuSub({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) {
|
}: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) {
|
||||||
return <ContextMenuPrimitive.Sub data-slot="context-menu-sub" {...props} />
|
return <ContextMenuPrimitive.Sub data-slot="context-menu-sub" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContextMenuRadioGroup({
|
function ContextMenuRadioGroup({
|
||||||
@ -50,7 +50,7 @@ function ContextMenuRadioGroup({
|
|||||||
data-slot="context-menu-radio-group"
|
data-slot="context-menu-radio-group"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContextMenuSubTrigger({
|
function ContextMenuSubTrigger({
|
||||||
@ -59,7 +59,7 @@ function ContextMenuSubTrigger({
|
|||||||
children,
|
children,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & {
|
}: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & {
|
||||||
inset?: boolean
|
inset?: boolean;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<ContextMenuPrimitive.SubTrigger
|
<ContextMenuPrimitive.SubTrigger
|
||||||
@ -74,7 +74,7 @@ function ContextMenuSubTrigger({
|
|||||||
{children}
|
{children}
|
||||||
<ChevronRightIcon className="ml-auto" />
|
<ChevronRightIcon className="ml-auto" />
|
||||||
</ContextMenuPrimitive.SubTrigger>
|
</ContextMenuPrimitive.SubTrigger>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContextMenuSubContent({
|
function ContextMenuSubContent({
|
||||||
@ -90,7 +90,7 @@ function ContextMenuSubContent({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContextMenuContent({
|
function ContextMenuContent({
|
||||||
@ -108,7 +108,7 @@ function ContextMenuContent({
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</ContextMenuPrimitive.Portal>
|
</ContextMenuPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContextMenuItem({
|
function ContextMenuItem({
|
||||||
@ -117,8 +117,8 @@ function ContextMenuItem({
|
|||||||
variant = "default",
|
variant = "default",
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
|
}: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
|
||||||
inset?: boolean
|
inset?: boolean;
|
||||||
variant?: "default" | "destructive"
|
variant?: "default" | "destructive";
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<ContextMenuPrimitive.Item
|
<ContextMenuPrimitive.Item
|
||||||
@ -131,7 +131,7 @@ function ContextMenuItem({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContextMenuCheckboxItem({
|
function ContextMenuCheckboxItem({
|
||||||
@ -157,7 +157,7 @@ function ContextMenuCheckboxItem({
|
|||||||
</span>
|
</span>
|
||||||
{children}
|
{children}
|
||||||
</ContextMenuPrimitive.CheckboxItem>
|
</ContextMenuPrimitive.CheckboxItem>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContextMenuRadioItem({
|
function ContextMenuRadioItem({
|
||||||
@ -181,7 +181,7 @@ function ContextMenuRadioItem({
|
|||||||
</span>
|
</span>
|
||||||
{children}
|
{children}
|
||||||
</ContextMenuPrimitive.RadioItem>
|
</ContextMenuPrimitive.RadioItem>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContextMenuLabel({
|
function ContextMenuLabel({
|
||||||
@ -189,7 +189,7 @@ function ContextMenuLabel({
|
|||||||
inset,
|
inset,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof ContextMenuPrimitive.Label> & {
|
}: React.ComponentProps<typeof ContextMenuPrimitive.Label> & {
|
||||||
inset?: boolean
|
inset?: boolean;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<ContextMenuPrimitive.Label
|
<ContextMenuPrimitive.Label
|
||||||
@ -201,7 +201,7 @@ function ContextMenuLabel({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContextMenuSeparator({
|
function ContextMenuSeparator({
|
||||||
@ -214,7 +214,7 @@ function ContextMenuSeparator({
|
|||||||
className={cn("bg-border -mx-1 my-1 h-px", className)}
|
className={cn("bg-border -mx-1 my-1 h-px", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContextMenuShortcut({
|
function ContextMenuShortcut({
|
||||||
@ -230,7 +230,7 @@ function ContextMenuShortcut({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -249,4 +249,4 @@ export {
|
|||||||
ContextMenuSubContent,
|
ContextMenuSubContent,
|
||||||
ContextMenuSubTrigger,
|
ContextMenuSubTrigger,
|
||||||
ContextMenuRadioGroup,
|
ContextMenuRadioGroup,
|
||||||
}
|
};
|
@ -1,31 +1,31 @@
|
|||||||
import * as React from "react"
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||||
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
import { XIcon } from "lucide-react";
|
||||||
import { XIcon } from "lucide-react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Dialog({
|
function Dialog({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
||||||
return <DialogPrimitive.Root data-slot="dialog" {...props} />
|
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogTrigger({
|
function DialogTrigger({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
||||||
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
|
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogPortal({
|
function DialogPortal({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
||||||
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
|
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogClose({
|
function DialogClose({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
||||||
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
|
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogOverlay({
|
function DialogOverlay({
|
||||||
@ -41,7 +41,7 @@ function DialogOverlay({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogContent({
|
function DialogContent({
|
||||||
@ -67,7 +67,7 @@ function DialogContent({
|
|||||||
</DialogPrimitive.Close>
|
</DialogPrimitive.Close>
|
||||||
</DialogPrimitive.Content>
|
</DialogPrimitive.Content>
|
||||||
</DialogPortal>
|
</DialogPortal>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@ -77,7 +77,7 @@ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@ -90,7 +90,7 @@ function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogTitle({
|
function DialogTitle({
|
||||||
@ -103,7 +103,7 @@ function DialogTitle({
|
|||||||
className={cn("text-lg leading-none font-semibold", className)}
|
className={cn("text-lg leading-none font-semibold", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogDescription({
|
function DialogDescription({
|
||||||
@ -116,7 +116,7 @@ function DialogDescription({
|
|||||||
className={cn("text-muted-foreground text-sm", className)}
|
className={cn("text-muted-foreground text-sm", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -130,4 +130,4 @@ export {
|
|||||||
DialogPortal,
|
DialogPortal,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogTrigger,
|
DialogTrigger,
|
||||||
}
|
};
|
@ -1,30 +1,30 @@
|
|||||||
import * as React from "react"
|
import * as React from "react";
|
||||||
import { Drawer as DrawerPrimitive } from "vaul"
|
import { Drawer as DrawerPrimitive } from "vaul";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Drawer({
|
function Drawer({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DrawerPrimitive.Root>) {
|
}: React.ComponentProps<typeof DrawerPrimitive.Root>) {
|
||||||
return <DrawerPrimitive.Root data-slot="drawer" {...props} />
|
return <DrawerPrimitive.Root data-slot="drawer" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DrawerTrigger({
|
function DrawerTrigger({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {
|
}: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {
|
||||||
return <DrawerPrimitive.Trigger data-slot="drawer-trigger" {...props} />
|
return <DrawerPrimitive.Trigger data-slot="drawer-trigger" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DrawerPortal({
|
function DrawerPortal({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DrawerPrimitive.Portal>) {
|
}: React.ComponentProps<typeof DrawerPrimitive.Portal>) {
|
||||||
return <DrawerPrimitive.Portal data-slot="drawer-portal" {...props} />
|
return <DrawerPrimitive.Portal data-slot="drawer-portal" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DrawerClose({
|
function DrawerClose({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DrawerPrimitive.Close>) {
|
}: React.ComponentProps<typeof DrawerPrimitive.Close>) {
|
||||||
return <DrawerPrimitive.Close data-slot="drawer-close" {...props} />
|
return <DrawerPrimitive.Close data-slot="drawer-close" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DrawerOverlay({
|
function DrawerOverlay({
|
||||||
@ -40,7 +40,7 @@ function DrawerOverlay({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DrawerContent({
|
function DrawerContent({
|
||||||
@ -67,7 +67,7 @@ function DrawerContent({
|
|||||||
{children}
|
{children}
|
||||||
</DrawerPrimitive.Content>
|
</DrawerPrimitive.Content>
|
||||||
</DrawerPortal>
|
</DrawerPortal>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) {
|
function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@ -77,7 +77,7 @@ function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
className={cn("flex flex-col gap-1.5 p-4", className)}
|
className={cn("flex flex-col gap-1.5 p-4", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) {
|
function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@ -87,7 +87,7 @@ function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
|
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DrawerTitle({
|
function DrawerTitle({
|
||||||
@ -100,7 +100,7 @@ function DrawerTitle({
|
|||||||
className={cn("text-foreground font-semibold", className)}
|
className={cn("text-foreground font-semibold", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DrawerDescription({
|
function DrawerDescription({
|
||||||
@ -113,7 +113,7 @@ function DrawerDescription({
|
|||||||
className={cn("text-muted-foreground text-sm", className)}
|
className={cn("text-muted-foreground text-sm", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -127,4 +127,4 @@ export {
|
|||||||
DrawerFooter,
|
DrawerFooter,
|
||||||
DrawerTitle,
|
DrawerTitle,
|
||||||
DrawerDescription,
|
DrawerDescription,
|
||||||
}
|
};
|
@ -1,15 +1,15 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
||||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
|
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
|
||||||
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function DropdownMenu({
|
function DropdownMenu({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
|
||||||
return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />
|
return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenuPortal({
|
function DropdownMenuPortal({
|
||||||
@ -17,7 +17,7 @@ function DropdownMenuPortal({
|
|||||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
|
||||||
return (
|
return (
|
||||||
<DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
|
<DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenuTrigger({
|
function DropdownMenuTrigger({
|
||||||
@ -28,7 +28,7 @@ function DropdownMenuTrigger({
|
|||||||
data-slot="dropdown-menu-trigger"
|
data-slot="dropdown-menu-trigger"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenuContent({
|
function DropdownMenuContent({
|
||||||
@ -48,7 +48,7 @@ function DropdownMenuContent({
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</DropdownMenuPrimitive.Portal>
|
</DropdownMenuPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenuGroup({
|
function DropdownMenuGroup({
|
||||||
@ -56,7 +56,7 @@ function DropdownMenuGroup({
|
|||||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
|
||||||
return (
|
return (
|
||||||
<DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
|
<DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenuItem({
|
function DropdownMenuItem({
|
||||||
@ -65,8 +65,8 @@ function DropdownMenuItem({
|
|||||||
variant = "default",
|
variant = "default",
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
|
||||||
inset?: boolean
|
inset?: boolean;
|
||||||
variant?: "default" | "destructive"
|
variant?: "default" | "destructive";
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<DropdownMenuPrimitive.Item
|
<DropdownMenuPrimitive.Item
|
||||||
@ -79,7 +79,7 @@ function DropdownMenuItem({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenuCheckboxItem({
|
function DropdownMenuCheckboxItem({
|
||||||
@ -105,7 +105,7 @@ function DropdownMenuCheckboxItem({
|
|||||||
</span>
|
</span>
|
||||||
{children}
|
{children}
|
||||||
</DropdownMenuPrimitive.CheckboxItem>
|
</DropdownMenuPrimitive.CheckboxItem>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenuRadioGroup({
|
function DropdownMenuRadioGroup({
|
||||||
@ -116,7 +116,7 @@ function DropdownMenuRadioGroup({
|
|||||||
data-slot="dropdown-menu-radio-group"
|
data-slot="dropdown-menu-radio-group"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenuRadioItem({
|
function DropdownMenuRadioItem({
|
||||||
@ -140,7 +140,7 @@ function DropdownMenuRadioItem({
|
|||||||
</span>
|
</span>
|
||||||
{children}
|
{children}
|
||||||
</DropdownMenuPrimitive.RadioItem>
|
</DropdownMenuPrimitive.RadioItem>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenuLabel({
|
function DropdownMenuLabel({
|
||||||
@ -148,7 +148,7 @@ function DropdownMenuLabel({
|
|||||||
inset,
|
inset,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
|
||||||
inset?: boolean
|
inset?: boolean;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<DropdownMenuPrimitive.Label
|
<DropdownMenuPrimitive.Label
|
||||||
@ -160,7 +160,7 @@ function DropdownMenuLabel({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenuSeparator({
|
function DropdownMenuSeparator({
|
||||||
@ -173,7 +173,7 @@ function DropdownMenuSeparator({
|
|||||||
className={cn("bg-border -mx-1 my-1 h-px", className)}
|
className={cn("bg-border -mx-1 my-1 h-px", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenuShortcut({
|
function DropdownMenuShortcut({
|
||||||
@ -189,13 +189,13 @@ function DropdownMenuShortcut({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenuSub({
|
function DropdownMenuSub({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
|
||||||
return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />
|
return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenuSubTrigger({
|
function DropdownMenuSubTrigger({
|
||||||
@ -204,7 +204,7 @@ function DropdownMenuSubTrigger({
|
|||||||
children,
|
children,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
|
||||||
inset?: boolean
|
inset?: boolean;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<DropdownMenuPrimitive.SubTrigger
|
<DropdownMenuPrimitive.SubTrigger
|
||||||
@ -219,7 +219,7 @@ function DropdownMenuSubTrigger({
|
|||||||
{children}
|
{children}
|
||||||
<ChevronRightIcon className="ml-auto size-4" />
|
<ChevronRightIcon className="ml-auto size-4" />
|
||||||
</DropdownMenuPrimitive.SubTrigger>
|
</DropdownMenuPrimitive.SubTrigger>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenuSubContent({
|
function DropdownMenuSubContent({
|
||||||
@ -235,7 +235,7 @@ function DropdownMenuSubContent({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -254,4 +254,4 @@ export {
|
|||||||
DropdownMenuSub,
|
DropdownMenuSub,
|
||||||
DropdownMenuSubTrigger,
|
DropdownMenuSubTrigger,
|
||||||
DropdownMenuSubContent,
|
DropdownMenuSubContent,
|
||||||
}
|
};
|
@ -11,8 +11,8 @@ import {
|
|||||||
useFormState,
|
useFormState,
|
||||||
} from "react-hook-form";
|
} from "react-hook-form";
|
||||||
|
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/views/components/ui/label";
|
||||||
import { cn } from "@/infra/styles/utils";
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
const Form = FormProvider;
|
const Form = FormProvider;
|
||||||
|
|
@ -1,12 +1,12 @@
|
|||||||
import * as React from "react"
|
import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
|
||||||
import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function HoverCard({
|
function HoverCard({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof HoverCardPrimitive.Root>) {
|
}: React.ComponentProps<typeof HoverCardPrimitive.Root>) {
|
||||||
return <HoverCardPrimitive.Root data-slot="hover-card" {...props} />
|
return <HoverCardPrimitive.Root data-slot="hover-card" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function HoverCardTrigger({
|
function HoverCardTrigger({
|
||||||
@ -14,7 +14,7 @@ function HoverCardTrigger({
|
|||||||
}: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {
|
}: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {
|
||||||
return (
|
return (
|
||||||
<HoverCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />
|
<HoverCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function HoverCardContent({
|
function HoverCardContent({
|
||||||
@ -36,7 +36,7 @@ function HoverCardContent({
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</HoverCardPrimitive.Portal>
|
</HoverCardPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { HoverCard, HoverCardTrigger, HoverCardContent }
|
export { HoverCard, HoverCardTrigger, HoverCardContent };
|
@ -1,17 +1,17 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import { OTPInput, OTPInputContext } from "input-otp";
|
||||||
import { OTPInput, OTPInputContext } from "input-otp"
|
import { MinusIcon } from "lucide-react";
|
||||||
import { MinusIcon } from "lucide-react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function InputOTP({
|
function InputOTP({
|
||||||
className,
|
className,
|
||||||
containerClassName,
|
containerClassName,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof OTPInput> & {
|
}: React.ComponentProps<typeof OTPInput> & {
|
||||||
containerClassName?: string
|
containerClassName?: string;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<OTPInput
|
<OTPInput
|
||||||
@ -23,7 +23,7 @@ function InputOTP({
|
|||||||
className={cn("disabled:cursor-not-allowed", className)}
|
className={cn("disabled:cursor-not-allowed", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function InputOTPGroup({ className, ...props }: React.ComponentProps<"div">) {
|
function InputOTPGroup({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@ -33,7 +33,7 @@ function InputOTPGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
className={cn("flex items-center", className)}
|
className={cn("flex items-center", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function InputOTPSlot({
|
function InputOTPSlot({
|
||||||
@ -41,10 +41,10 @@ function InputOTPSlot({
|
|||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"div"> & {
|
}: React.ComponentProps<"div"> & {
|
||||||
index: number
|
index: number;
|
||||||
}) {
|
}) {
|
||||||
const inputOTPContext = React.useContext(OTPInputContext)
|
const inputOTPContext = React.useContext(OTPInputContext);
|
||||||
const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {}
|
const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -63,7 +63,7 @@ function InputOTPSlot({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) {
|
function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) {
|
||||||
@ -71,7 +71,7 @@ function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) {
|
|||||||
<div data-slot="input-otp-separator" role="separator" {...props}>
|
<div data-slot="input-otp-separator" role="separator" {...props}>
|
||||||
<MinusIcon />
|
<MinusIcon />
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }
|
export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator };
|
@ -1,6 +1,6 @@
|
|||||||
import * as React from "react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
||||||
return (
|
return (
|
||||||
@ -15,7 +15,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Input }
|
export { Input };
|
@ -1,9 +1,9 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as LabelPrimitive from "@radix-ui/react-label";
|
||||||
import * as LabelPrimitive from "@radix-ui/react-label"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Label({
|
function Label({
|
||||||
className,
|
className,
|
||||||
@ -18,7 +18,7 @@ function Label({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Label }
|
export { Label };
|
@ -1,8 +1,8 @@
|
|||||||
import * as React from "react"
|
import * as MenubarPrimitive from "@radix-ui/react-menubar";
|
||||||
import * as MenubarPrimitive from "@radix-ui/react-menubar"
|
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
|
||||||
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Menubar({
|
function Menubar({
|
||||||
className,
|
className,
|
||||||
@ -17,25 +17,25 @@ function Menubar({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MenubarMenu({
|
function MenubarMenu({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof MenubarPrimitive.Menu>) {
|
}: React.ComponentProps<typeof MenubarPrimitive.Menu>) {
|
||||||
return <MenubarPrimitive.Menu data-slot="menubar-menu" {...props} />
|
return <MenubarPrimitive.Menu data-slot="menubar-menu" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function MenubarGroup({
|
function MenubarGroup({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof MenubarPrimitive.Group>) {
|
}: React.ComponentProps<typeof MenubarPrimitive.Group>) {
|
||||||
return <MenubarPrimitive.Group data-slot="menubar-group" {...props} />
|
return <MenubarPrimitive.Group data-slot="menubar-group" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function MenubarPortal({
|
function MenubarPortal({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof MenubarPrimitive.Portal>) {
|
}: React.ComponentProps<typeof MenubarPrimitive.Portal>) {
|
||||||
return <MenubarPrimitive.Portal data-slot="menubar-portal" {...props} />
|
return <MenubarPrimitive.Portal data-slot="menubar-portal" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function MenubarRadioGroup({
|
function MenubarRadioGroup({
|
||||||
@ -43,7 +43,7 @@ function MenubarRadioGroup({
|
|||||||
}: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {
|
}: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {
|
||||||
return (
|
return (
|
||||||
<MenubarPrimitive.RadioGroup data-slot="menubar-radio-group" {...props} />
|
<MenubarPrimitive.RadioGroup data-slot="menubar-radio-group" {...props} />
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MenubarTrigger({
|
function MenubarTrigger({
|
||||||
@ -59,7 +59,7 @@ function MenubarTrigger({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MenubarContent({
|
function MenubarContent({
|
||||||
@ -83,7 +83,7 @@ function MenubarContent({
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</MenubarPortal>
|
</MenubarPortal>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MenubarItem({
|
function MenubarItem({
|
||||||
@ -92,8 +92,8 @@ function MenubarItem({
|
|||||||
variant = "default",
|
variant = "default",
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof MenubarPrimitive.Item> & {
|
}: React.ComponentProps<typeof MenubarPrimitive.Item> & {
|
||||||
inset?: boolean
|
inset?: boolean;
|
||||||
variant?: "default" | "destructive"
|
variant?: "default" | "destructive";
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<MenubarPrimitive.Item
|
<MenubarPrimitive.Item
|
||||||
@ -106,7 +106,7 @@ function MenubarItem({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MenubarCheckboxItem({
|
function MenubarCheckboxItem({
|
||||||
@ -132,7 +132,7 @@ function MenubarCheckboxItem({
|
|||||||
</span>
|
</span>
|
||||||
{children}
|
{children}
|
||||||
</MenubarPrimitive.CheckboxItem>
|
</MenubarPrimitive.CheckboxItem>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MenubarRadioItem({
|
function MenubarRadioItem({
|
||||||
@ -156,7 +156,7 @@ function MenubarRadioItem({
|
|||||||
</span>
|
</span>
|
||||||
{children}
|
{children}
|
||||||
</MenubarPrimitive.RadioItem>
|
</MenubarPrimitive.RadioItem>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MenubarLabel({
|
function MenubarLabel({
|
||||||
@ -164,7 +164,7 @@ function MenubarLabel({
|
|||||||
inset,
|
inset,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof MenubarPrimitive.Label> & {
|
}: React.ComponentProps<typeof MenubarPrimitive.Label> & {
|
||||||
inset?: boolean
|
inset?: boolean;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<MenubarPrimitive.Label
|
<MenubarPrimitive.Label
|
||||||
@ -176,7 +176,7 @@ function MenubarLabel({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MenubarSeparator({
|
function MenubarSeparator({
|
||||||
@ -189,7 +189,7 @@ function MenubarSeparator({
|
|||||||
className={cn("bg-border -mx-1 my-1 h-px", className)}
|
className={cn("bg-border -mx-1 my-1 h-px", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MenubarShortcut({
|
function MenubarShortcut({
|
||||||
@ -205,13 +205,13 @@ function MenubarShortcut({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MenubarSub({
|
function MenubarSub({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof MenubarPrimitive.Sub>) {
|
}: React.ComponentProps<typeof MenubarPrimitive.Sub>) {
|
||||||
return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />
|
return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function MenubarSubTrigger({
|
function MenubarSubTrigger({
|
||||||
@ -220,7 +220,7 @@ function MenubarSubTrigger({
|
|||||||
children,
|
children,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & {
|
}: React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & {
|
||||||
inset?: boolean
|
inset?: boolean;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<MenubarPrimitive.SubTrigger
|
<MenubarPrimitive.SubTrigger
|
||||||
@ -235,7 +235,7 @@ function MenubarSubTrigger({
|
|||||||
{children}
|
{children}
|
||||||
<ChevronRightIcon className="ml-auto h-4 w-4" />
|
<ChevronRightIcon className="ml-auto h-4 w-4" />
|
||||||
</MenubarPrimitive.SubTrigger>
|
</MenubarPrimitive.SubTrigger>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MenubarSubContent({
|
function MenubarSubContent({
|
||||||
@ -251,7 +251,7 @@ function MenubarSubContent({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -271,4 +271,4 @@ export {
|
|||||||
MenubarSub,
|
MenubarSub,
|
||||||
MenubarSubTrigger,
|
MenubarSubTrigger,
|
||||||
MenubarSubContent,
|
MenubarSubContent,
|
||||||
}
|
};
|
@ -1,9 +1,9 @@
|
|||||||
import * as React from "react"
|
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu";
|
||||||
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
|
import { cva } from "class-variance-authority";
|
||||||
import { cva } from "class-variance-authority"
|
import { ChevronDownIcon } from "lucide-react";
|
||||||
import { ChevronDownIcon } from "lucide-react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function NavigationMenu({
|
function NavigationMenu({
|
||||||
className,
|
className,
|
||||||
@ -11,7 +11,7 @@ function NavigationMenu({
|
|||||||
viewport = true,
|
viewport = true,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof NavigationMenuPrimitive.Root> & {
|
}: React.ComponentProps<typeof NavigationMenuPrimitive.Root> & {
|
||||||
viewport?: boolean
|
viewport?: boolean;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<NavigationMenuPrimitive.Root
|
<NavigationMenuPrimitive.Root
|
||||||
@ -26,7 +26,7 @@ function NavigationMenu({
|
|||||||
{children}
|
{children}
|
||||||
{viewport && <NavigationMenuViewport />}
|
{viewport && <NavigationMenuViewport />}
|
||||||
</NavigationMenuPrimitive.Root>
|
</NavigationMenuPrimitive.Root>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function NavigationMenuList({
|
function NavigationMenuList({
|
||||||
@ -42,7 +42,7 @@ function NavigationMenuList({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function NavigationMenuItem({
|
function NavigationMenuItem({
|
||||||
@ -55,12 +55,12 @@ function NavigationMenuItem({
|
|||||||
className={cn("relative", className)}
|
className={cn("relative", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const navigationMenuTriggerStyle = cva(
|
const navigationMenuTriggerStyle = cva(
|
||||||
"group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=open]:hover:bg-accent data-[state=open]:text-accent-foreground data-[state=open]:focus:bg-accent data-[state=open]:bg-accent/50 focus-visible:ring-ring/50 outline-none transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1"
|
"group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=open]:hover:bg-accent data-[state=open]:text-accent-foreground data-[state=open]:focus:bg-accent data-[state=open]:bg-accent/50 focus-visible:ring-ring/50 outline-none transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1"
|
||||||
)
|
);
|
||||||
|
|
||||||
function NavigationMenuTrigger({
|
function NavigationMenuTrigger({
|
||||||
className,
|
className,
|
||||||
@ -79,7 +79,7 @@ function NavigationMenuTrigger({
|
|||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
</NavigationMenuPrimitive.Trigger>
|
</NavigationMenuPrimitive.Trigger>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function NavigationMenuContent({
|
function NavigationMenuContent({
|
||||||
@ -96,7 +96,7 @@ function NavigationMenuContent({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function NavigationMenuViewport({
|
function NavigationMenuViewport({
|
||||||
@ -118,7 +118,7 @@ function NavigationMenuViewport({
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function NavigationMenuLink({
|
function NavigationMenuLink({
|
||||||
@ -134,7 +134,7 @@ function NavigationMenuLink({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function NavigationMenuIndicator({
|
function NavigationMenuIndicator({
|
||||||
@ -152,7 +152,7 @@ function NavigationMenuIndicator({
|
|||||||
>
|
>
|
||||||
<div className="bg-border relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm shadow-md" />
|
<div className="bg-border relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm shadow-md" />
|
||||||
</NavigationMenuPrimitive.Indicator>
|
</NavigationMenuPrimitive.Indicator>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -165,4 +165,4 @@ export {
|
|||||||
NavigationMenuIndicator,
|
NavigationMenuIndicator,
|
||||||
NavigationMenuViewport,
|
NavigationMenuViewport,
|
||||||
navigationMenuTriggerStyle,
|
navigationMenuTriggerStyle,
|
||||||
}
|
};
|
@ -1,12 +1,12 @@
|
|||||||
import * as React from "react"
|
|
||||||
import {
|
import {
|
||||||
ChevronLeftIcon,
|
ChevronLeftIcon,
|
||||||
ChevronRightIcon,
|
ChevronRightIcon,
|
||||||
MoreHorizontalIcon,
|
MoreHorizontalIcon,
|
||||||
} from "lucide-react"
|
} from "lucide-react";
|
||||||
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { Button, buttonVariants } from "@/views/components/ui/button";
|
||||||
import { Button, buttonVariants } from "@/components/ui/button"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
|
function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
|
||||||
return (
|
return (
|
||||||
@ -17,7 +17,7 @@ function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
|
|||||||
className={cn("mx-auto flex w-full justify-center", className)}
|
className={cn("mx-auto flex w-full justify-center", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function PaginationContent({
|
function PaginationContent({
|
||||||
@ -30,17 +30,17 @@ function PaginationContent({
|
|||||||
className={cn("flex flex-row items-center gap-1", className)}
|
className={cn("flex flex-row items-center gap-1", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function PaginationItem({ ...props }: React.ComponentProps<"li">) {
|
function PaginationItem({ ...props }: React.ComponentProps<"li">) {
|
||||||
return <li data-slot="pagination-item" {...props} />
|
return <li data-slot="pagination-item" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
type PaginationLinkProps = {
|
type PaginationLinkProps = {
|
||||||
isActive?: boolean
|
isActive?: boolean;
|
||||||
} & Pick<React.ComponentProps<typeof Button>, "size"> &
|
} & Pick<React.ComponentProps<typeof Button>, "size"> &
|
||||||
React.ComponentProps<"a">
|
React.ComponentProps<"a">;
|
||||||
|
|
||||||
function PaginationLink({
|
function PaginationLink({
|
||||||
className,
|
className,
|
||||||
@ -62,7 +62,7 @@ function PaginationLink({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function PaginationPrevious({
|
function PaginationPrevious({
|
||||||
@ -79,7 +79,7 @@ function PaginationPrevious({
|
|||||||
<ChevronLeftIcon />
|
<ChevronLeftIcon />
|
||||||
<span className="hidden sm:block">Previous</span>
|
<span className="hidden sm:block">Previous</span>
|
||||||
</PaginationLink>
|
</PaginationLink>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function PaginationNext({
|
function PaginationNext({
|
||||||
@ -96,7 +96,7 @@ function PaginationNext({
|
|||||||
<span className="hidden sm:block">Next</span>
|
<span className="hidden sm:block">Next</span>
|
||||||
<ChevronRightIcon />
|
<ChevronRightIcon />
|
||||||
</PaginationLink>
|
</PaginationLink>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function PaginationEllipsis({
|
function PaginationEllipsis({
|
||||||
@ -113,7 +113,7 @@ function PaginationEllipsis({
|
|||||||
<MoreHorizontalIcon className="size-4" />
|
<MoreHorizontalIcon className="size-4" />
|
||||||
<span className="sr-only">More pages</span>
|
<span className="sr-only">More pages</span>
|
||||||
</span>
|
</span>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -124,4 +124,4 @@ export {
|
|||||||
PaginationPrevious,
|
PaginationPrevious,
|
||||||
PaginationNext,
|
PaginationNext,
|
||||||
PaginationEllipsis,
|
PaginationEllipsis,
|
||||||
}
|
};
|
@ -1,20 +1,20 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
||||||
import * as PopoverPrimitive from "@radix-ui/react-popover"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Popover({
|
function Popover({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof PopoverPrimitive.Root>) {
|
}: React.ComponentProps<typeof PopoverPrimitive.Root>) {
|
||||||
return <PopoverPrimitive.Root data-slot="popover" {...props} />
|
return <PopoverPrimitive.Root data-slot="popover" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function PopoverTrigger({
|
function PopoverTrigger({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
|
}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
|
||||||
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
|
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function PopoverContent({
|
function PopoverContent({
|
||||||
@ -36,13 +36,13 @@ function PopoverContent({
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</PopoverPrimitive.Portal>
|
</PopoverPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function PopoverAnchor({
|
function PopoverAnchor({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
|
}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
|
||||||
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />
|
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }
|
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor };
|
@ -1,7 +1,7 @@
|
|||||||
import { cn } from '@/infra/styles/utils';
|
import { cn } from "@/views/utils";
|
||||||
import type { FC, HTMLAttributes } from 'react';
|
import type { FC, HTMLAttributes } from "react";
|
||||||
|
|
||||||
type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
type Size = "xs" | "sm" | "md" | "lg" | "xl";
|
||||||
|
|
||||||
const sizes: Record<Size, { radius: number; strokeWidth: number }> = {
|
const sizes: Record<Size, { radius: number; strokeWidth: number }> = {
|
||||||
xs: { radius: 15, strokeWidth: 3 },
|
xs: { radius: 15, strokeWidth: 3 },
|
||||||
@ -23,7 +23,7 @@ const ProgressCircle: FC<ProgressCircleProps> = ({
|
|||||||
className,
|
className,
|
||||||
children,
|
children,
|
||||||
value = 0,
|
value = 0,
|
||||||
size = 'md',
|
size = "md",
|
||||||
radius,
|
radius,
|
||||||
strokeWidth,
|
strokeWidth,
|
||||||
showAnimation = true,
|
showAnimation = true,
|
||||||
@ -39,7 +39,7 @@ const ProgressCircle: FC<ProgressCircleProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn('flex flex-col items-center justify-center', className)}
|
className={cn("flex flex-col items-center justify-center", className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
@ -56,7 +56,7 @@ const ProgressCircle: FC<ProgressCircleProps> = ({
|
|||||||
fill="transparent"
|
fill="transparent"
|
||||||
stroke=""
|
stroke=""
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
className={cn('stroke-secondary transition-colors ease-linear')}
|
className={cn("stroke-secondary transition-colors ease-linear")}
|
||||||
/>
|
/>
|
||||||
{currentValue >= 0 && (
|
{currentValue >= 0 && (
|
||||||
<circle
|
<circle
|
||||||
@ -70,13 +70,13 @@ const ProgressCircle: FC<ProgressCircleProps> = ({
|
|||||||
stroke=""
|
stroke=""
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
className={cn(
|
className={cn(
|
||||||
'stroke-primary transition-colors ease-linear',
|
"stroke-primary transition-colors ease-linear",
|
||||||
showAnimation ? 'transition-all duration-300 ease-in-out' : ''
|
showAnimation ? "transition-all duration-300 ease-in-out" : ""
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</svg>
|
</svg>
|
||||||
<div className={cn('absolute flex')}>{children}</div>
|
<div className={cn("absolute flex")}>{children}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
@ -1,7 +1,7 @@
|
|||||||
import * as React from "react"
|
import * as ProgressPrimitive from "@radix-ui/react-progress";
|
||||||
import * as ProgressPrimitive from "@radix-ui/react-progress"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Progress({
|
function Progress({
|
||||||
className,
|
className,
|
||||||
@ -23,7 +23,7 @@ function Progress({
|
|||||||
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
|
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
|
||||||
/>
|
/>
|
||||||
</ProgressPrimitive.Root>
|
</ProgressPrimitive.Root>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Progress }
|
export { Progress };
|
@ -1,10 +1,10 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
|
||||||
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
|
import { CircleIcon } from "lucide-react";
|
||||||
import { CircleIcon } from "lucide-react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function RadioGroup({
|
function RadioGroup({
|
||||||
className,
|
className,
|
||||||
@ -16,7 +16,7 @@ function RadioGroup({
|
|||||||
className={cn("grid gap-3", className)}
|
className={cn("grid gap-3", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function RadioGroupItem({
|
function RadioGroupItem({
|
||||||
@ -39,7 +39,7 @@ function RadioGroupItem({
|
|||||||
<CircleIcon className="fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2" />
|
<CircleIcon className="fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2" />
|
||||||
</RadioGroupPrimitive.Indicator>
|
</RadioGroupPrimitive.Indicator>
|
||||||
</RadioGroupPrimitive.Item>
|
</RadioGroupPrimitive.Item>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { RadioGroup, RadioGroupItem }
|
export { RadioGroup, RadioGroupItem };
|
@ -1,8 +1,8 @@
|
|||||||
import * as React from "react"
|
import { GripVerticalIcon } from "lucide-react";
|
||||||
import { GripVerticalIcon } from "lucide-react"
|
import * as React from "react";
|
||||||
import * as ResizablePrimitive from "react-resizable-panels"
|
import * as ResizablePrimitive from "react-resizable-panels";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function ResizablePanelGroup({
|
function ResizablePanelGroup({
|
||||||
className,
|
className,
|
||||||
@ -17,13 +17,13 @@ function ResizablePanelGroup({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ResizablePanel({
|
function ResizablePanel({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof ResizablePrimitive.Panel>) {
|
}: React.ComponentProps<typeof ResizablePrimitive.Panel>) {
|
||||||
return <ResizablePrimitive.Panel data-slot="resizable-panel" {...props} />
|
return <ResizablePrimitive.Panel data-slot="resizable-panel" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ResizableHandle({
|
function ResizableHandle({
|
||||||
@ -31,7 +31,7 @@ function ResizableHandle({
|
|||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
|
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
|
||||||
withHandle?: boolean
|
withHandle?: boolean;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<ResizablePrimitive.PanelResizeHandle
|
<ResizablePrimitive.PanelResizeHandle
|
||||||
@ -48,7 +48,7 @@ function ResizableHandle({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</ResizablePrimitive.PanelResizeHandle>
|
</ResizablePrimitive.PanelResizeHandle>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { ResizablePanelGroup, ResizablePanel, ResizableHandle }
|
export { ResizablePanelGroup, ResizablePanel, ResizableHandle };
|
@ -1,9 +1,9 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
||||||
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function ScrollArea({
|
function ScrollArea({
|
||||||
className,
|
className,
|
||||||
@ -25,7 +25,7 @@ function ScrollArea({
|
|||||||
<ScrollBar />
|
<ScrollBar />
|
||||||
<ScrollAreaPrimitive.Corner />
|
<ScrollAreaPrimitive.Corner />
|
||||||
</ScrollAreaPrimitive.Root>
|
</ScrollAreaPrimitive.Root>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ScrollBar({
|
function ScrollBar({
|
||||||
@ -52,7 +52,7 @@ function ScrollBar({
|
|||||||
className="bg-border relative flex-1 rounded-full"
|
className="bg-border relative flex-1 rounded-full"
|
||||||
/>
|
/>
|
||||||
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { ScrollArea, ScrollBar }
|
export { ScrollArea, ScrollBar };
|
@ -1,25 +1,25 @@
|
|||||||
import * as React from "react"
|
import * as SelectPrimitive from "@radix-ui/react-select";
|
||||||
import * as SelectPrimitive from "@radix-ui/react-select"
|
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
||||||
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Select({
|
function Select({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
}: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
||||||
return <SelectPrimitive.Root data-slot="select" {...props} />
|
return <SelectPrimitive.Root data-slot="select" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function SelectGroup({
|
function SelectGroup({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof SelectPrimitive.Group>) {
|
}: React.ComponentProps<typeof SelectPrimitive.Group>) {
|
||||||
return <SelectPrimitive.Group data-slot="select-group" {...props} />
|
return <SelectPrimitive.Group data-slot="select-group" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function SelectValue({
|
function SelectValue({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof SelectPrimitive.Value>) {
|
}: React.ComponentProps<typeof SelectPrimitive.Value>) {
|
||||||
return <SelectPrimitive.Value data-slot="select-value" {...props} />
|
return <SelectPrimitive.Value data-slot="select-value" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function SelectTrigger({
|
function SelectTrigger({
|
||||||
@ -28,7 +28,7 @@ function SelectTrigger({
|
|||||||
children,
|
children,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
|
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
|
||||||
size?: "sm" | "default"
|
size?: "sm" | "default";
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<SelectPrimitive.Trigger
|
<SelectPrimitive.Trigger
|
||||||
@ -45,7 +45,7 @@ function SelectTrigger({
|
|||||||
<ChevronDownIcon className="size-4 opacity-50" />
|
<ChevronDownIcon className="size-4 opacity-50" />
|
||||||
</SelectPrimitive.Icon>
|
</SelectPrimitive.Icon>
|
||||||
</SelectPrimitive.Trigger>
|
</SelectPrimitive.Trigger>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SelectContent({
|
function SelectContent({
|
||||||
@ -80,7 +80,7 @@ function SelectContent({
|
|||||||
<SelectScrollDownButton />
|
<SelectScrollDownButton />
|
||||||
</SelectPrimitive.Content>
|
</SelectPrimitive.Content>
|
||||||
</SelectPrimitive.Portal>
|
</SelectPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SelectLabel({
|
function SelectLabel({
|
||||||
@ -93,7 +93,7 @@ function SelectLabel({
|
|||||||
className={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
|
className={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SelectItem({
|
function SelectItem({
|
||||||
@ -117,7 +117,7 @@ function SelectItem({
|
|||||||
</span>
|
</span>
|
||||||
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
||||||
</SelectPrimitive.Item>
|
</SelectPrimitive.Item>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SelectSeparator({
|
function SelectSeparator({
|
||||||
@ -130,7 +130,7 @@ function SelectSeparator({
|
|||||||
className={cn("bg-border pointer-events-none -mx-1 my-1 h-px", className)}
|
className={cn("bg-border pointer-events-none -mx-1 my-1 h-px", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SelectScrollUpButton({
|
function SelectScrollUpButton({
|
||||||
@ -148,7 +148,7 @@ function SelectScrollUpButton({
|
|||||||
>
|
>
|
||||||
<ChevronUpIcon className="size-4" />
|
<ChevronUpIcon className="size-4" />
|
||||||
</SelectPrimitive.ScrollUpButton>
|
</SelectPrimitive.ScrollUpButton>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SelectScrollDownButton({
|
function SelectScrollDownButton({
|
||||||
@ -166,7 +166,7 @@ function SelectScrollDownButton({
|
|||||||
>
|
>
|
||||||
<ChevronDownIcon className="size-4" />
|
<ChevronDownIcon className="size-4" />
|
||||||
</SelectPrimitive.ScrollDownButton>
|
</SelectPrimitive.ScrollDownButton>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -180,4 +180,4 @@ export {
|
|||||||
SelectSeparator,
|
SelectSeparator,
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
}
|
};
|
@ -1,9 +1,9 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
||||||
import * as SeparatorPrimitive from "@radix-ui/react-separator"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Separator({
|
function Separator({
|
||||||
className,
|
className,
|
||||||
@ -22,7 +22,7 @@ function Separator({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Separator }
|
export { Separator };
|
@ -1,29 +1,29 @@
|
|||||||
import * as React from "react"
|
import * as SheetPrimitive from "@radix-ui/react-dialog";
|
||||||
import * as SheetPrimitive from "@radix-ui/react-dialog"
|
import { XIcon } from "lucide-react";
|
||||||
import { XIcon } from "lucide-react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
|
function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
|
||||||
return <SheetPrimitive.Root data-slot="sheet" {...props} />
|
return <SheetPrimitive.Root data-slot="sheet" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function SheetTrigger({
|
function SheetTrigger({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
|
}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
|
||||||
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
|
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function SheetClose({
|
function SheetClose({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof SheetPrimitive.Close>) {
|
}: React.ComponentProps<typeof SheetPrimitive.Close>) {
|
||||||
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
|
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function SheetPortal({
|
function SheetPortal({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof SheetPrimitive.Portal>) {
|
}: React.ComponentProps<typeof SheetPrimitive.Portal>) {
|
||||||
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
|
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function SheetOverlay({
|
function SheetOverlay({
|
||||||
@ -39,7 +39,7 @@ function SheetOverlay({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SheetContent({
|
function SheetContent({
|
||||||
@ -48,7 +48,7 @@ function SheetContent({
|
|||||||
side = "right",
|
side = "right",
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof SheetPrimitive.Content> & {
|
}: React.ComponentProps<typeof SheetPrimitive.Content> & {
|
||||||
side?: "top" | "right" | "bottom" | "left"
|
side?: "top" | "right" | "bottom" | "left";
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<SheetPortal>
|
<SheetPortal>
|
||||||
@ -76,7 +76,7 @@ function SheetContent({
|
|||||||
</SheetPrimitive.Close>
|
</SheetPrimitive.Close>
|
||||||
</SheetPrimitive.Content>
|
</SheetPrimitive.Content>
|
||||||
</SheetPortal>
|
</SheetPortal>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
|
function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@ -86,7 +86,7 @@ function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
className={cn("flex flex-col gap-1.5 p-4", className)}
|
className={cn("flex flex-col gap-1.5 p-4", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
|
function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@ -96,7 +96,7 @@ function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
|
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SheetTitle({
|
function SheetTitle({
|
||||||
@ -109,7 +109,7 @@ function SheetTitle({
|
|||||||
className={cn("text-foreground font-semibold", className)}
|
className={cn("text-foreground font-semibold", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SheetDescription({
|
function SheetDescription({
|
||||||
@ -122,7 +122,7 @@ function SheetDescription({
|
|||||||
className={cn("text-muted-foreground text-sm", className)}
|
className={cn("text-muted-foreground text-sm", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -134,4 +134,4 @@ export {
|
|||||||
SheetFooter,
|
SheetFooter,
|
||||||
SheetTitle,
|
SheetTitle,
|
||||||
SheetDescription,
|
SheetDescription,
|
||||||
}
|
};
|
@ -5,25 +5,25 @@ import { VariantProps, cva } from "class-variance-authority";
|
|||||||
import { PanelLeftIcon } from "lucide-react";
|
import { PanelLeftIcon } from "lucide-react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/views/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/views/components/ui/input";
|
||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/views/components/ui/separator";
|
||||||
import {
|
import {
|
||||||
Sheet,
|
Sheet,
|
||||||
SheetContent,
|
SheetContent,
|
||||||
SheetDescription,
|
SheetDescription,
|
||||||
SheetHeader,
|
SheetHeader,
|
||||||
SheetTitle,
|
SheetTitle,
|
||||||
} from "@/components/ui/sheet";
|
} from "@/views/components/ui/sheet";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/views/components/ui/skeleton";
|
||||||
import {
|
import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
TooltipContent,
|
TooltipContent,
|
||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/views/components/ui/tooltip";
|
||||||
import { useIsMobile } from "@/infra/hooks/use-mobile";
|
import { useIsMobile } from "@/views/hooks/use-mobile";
|
||||||
import { cn } from "@/infra/styles/utils";
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
const SIDEBAR_COOKIE_NAME = "sidebar_state";
|
const SIDEBAR_COOKIE_NAME = "sidebar_state";
|
||||||
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
||||||
@ -83,7 +83,7 @@ function SidebarProvider({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This sets the cookie to keep the sidebar state.
|
// This sets the cookie to keep the sidebar state.
|
||||||
// TODO: FIXME
|
// TODO: FIX THIS
|
||||||
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
|
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
|
||||||
},
|
},
|
||||||
[setOpenProp, open]
|
[setOpenProp, open]
|
@ -1,7 +1,7 @@
|
|||||||
import { cn } from "@/infra/styles/utils";
|
import { cn } from "@/views/utils";
|
||||||
import type React from "react";
|
import { ComponentProps } from "react";
|
||||||
|
|
||||||
function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
|
function Skeleton({ className, ...props }: ComponentProps<"div">) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="skeleton"
|
data-slot="skeleton"
|
@ -1,9 +1,9 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as SliderPrimitive from "@radix-ui/react-slider";
|
||||||
import * as SliderPrimitive from "@radix-ui/react-slider"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Slider({
|
function Slider({
|
||||||
className,
|
className,
|
||||||
@ -21,7 +21,7 @@ function Slider({
|
|||||||
? defaultValue
|
? defaultValue
|
||||||
: [min, max],
|
: [min, max],
|
||||||
[value, defaultValue, min, max]
|
[value, defaultValue, min, max]
|
||||||
)
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SliderPrimitive.Root
|
<SliderPrimitive.Root
|
||||||
@ -57,7 +57,7 @@ function Slider({
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</SliderPrimitive.Root>
|
</SliderPrimitive.Root>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Slider }
|
export { Slider };
|
@ -1,24 +1,24 @@
|
|||||||
import { cn } from '@/infra/styles/utils';
|
import { cn } from "@/views/utils";
|
||||||
import {
|
import {
|
||||||
Loader,
|
Loader,
|
||||||
LoaderCircle,
|
LoaderCircle,
|
||||||
LoaderPinwheel,
|
LoaderPinwheel,
|
||||||
type LucideProps,
|
type LucideProps,
|
||||||
} from 'lucide-react';
|
} from "lucide-react";
|
||||||
|
|
||||||
export type SpinnerVariantProps = Omit<SpinnerProps, 'variant'>;
|
export type SpinnerVariantProps = Omit<SpinnerProps, "variant">;
|
||||||
|
|
||||||
const Default = ({ className, ...props }: SpinnerVariantProps) => {
|
const Default = ({ className, ...props }: SpinnerVariantProps) => {
|
||||||
return <Loader className={cn('animate-spin', className)} {...props} />;
|
return <Loader className={cn("animate-spin", className)} {...props} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Circle = ({ className, ...props }: SpinnerVariantProps) => {
|
const Circle = ({ className, ...props }: SpinnerVariantProps) => {
|
||||||
return <LoaderCircle className={cn('animate-spin', className)} {...props} />;
|
return <LoaderCircle className={cn("animate-spin", className)} {...props} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Pinwheel = ({ className, ...props }: SpinnerVariantProps) => {
|
const Pinwheel = ({ className, ...props }: SpinnerVariantProps) => {
|
||||||
return (
|
return (
|
||||||
<LoaderPinwheel className={cn('animate-spin', className)} {...props} />
|
<LoaderPinwheel className={cn("animate-spin", className)} {...props} />
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -32,16 +32,16 @@ const CircleFilled = ({
|
|||||||
<div className="absolute inset-0 rotate-180">
|
<div className="absolute inset-0 rotate-180">
|
||||||
<LoaderCircle
|
<LoaderCircle
|
||||||
className={cn(
|
className={cn(
|
||||||
'animate-spin',
|
"animate-spin",
|
||||||
className,
|
className,
|
||||||
'text-foreground opacity-20'
|
"text-foreground opacity-20"
|
||||||
)}
|
)}
|
||||||
size={size}
|
size={size}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<LoaderCircle
|
<LoaderCircle
|
||||||
className={cn('relative animate-spin', className)}
|
className={cn("relative animate-spin", className)}
|
||||||
size={size}
|
size={size}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
@ -233,8 +233,8 @@ const Infinite = ({ size = 24, ...props }: SpinnerVariantProps) => (
|
|||||||
d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40 C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z"
|
d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40 C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z"
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
style={{
|
style={{
|
||||||
transform: 'scale(0.8)',
|
transform: "scale(0.8)",
|
||||||
transformOrigin: '50px 50px',
|
transformOrigin: "50px 50px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
@ -250,31 +250,31 @@ const Infinite = ({ size = 24, ...props }: SpinnerVariantProps) => (
|
|||||||
|
|
||||||
export type SpinnerProps = LucideProps & {
|
export type SpinnerProps = LucideProps & {
|
||||||
variant?:
|
variant?:
|
||||||
| 'default'
|
| "default"
|
||||||
| 'circle'
|
| "circle"
|
||||||
| 'pinwheel'
|
| "pinwheel"
|
||||||
| 'circle-filled'
|
| "circle-filled"
|
||||||
| 'ellipsis'
|
| "ellipsis"
|
||||||
| 'ring'
|
| "ring"
|
||||||
| 'bars'
|
| "bars"
|
||||||
| 'infinite';
|
| "infinite";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Spinner = ({ variant, ...props }: SpinnerProps) => {
|
export const Spinner = ({ variant, ...props }: SpinnerProps) => {
|
||||||
switch (variant) {
|
switch (variant) {
|
||||||
case 'circle':
|
case "circle":
|
||||||
return <Circle {...props} />;
|
return <Circle {...props} />;
|
||||||
case 'pinwheel':
|
case "pinwheel":
|
||||||
return <Pinwheel {...props} />;
|
return <Pinwheel {...props} />;
|
||||||
case 'circle-filled':
|
case "circle-filled":
|
||||||
return <CircleFilled {...props} />;
|
return <CircleFilled {...props} />;
|
||||||
case 'ellipsis':
|
case "ellipsis":
|
||||||
return <Ellipsis {...props} />;
|
return <Ellipsis {...props} />;
|
||||||
case 'ring':
|
case "ring":
|
||||||
return <Ring {...props} />;
|
return <Ring {...props} />;
|
||||||
case 'bars':
|
case "bars":
|
||||||
return <Bars {...props} />;
|
return <Bars {...props} />;
|
||||||
case 'infinite':
|
case "infinite":
|
||||||
return <Infinite {...props} />;
|
return <Infinite {...props} />;
|
||||||
default:
|
default:
|
||||||
return <Default {...props} />;
|
return <Default {...props} />;
|
@ -1,9 +1,9 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as SwitchPrimitive from "@radix-ui/react-switch";
|
||||||
import * as SwitchPrimitive from "@radix-ui/react-switch"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Switch({
|
function Switch({
|
||||||
className,
|
className,
|
||||||
@ -25,7 +25,7 @@ function Switch({
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</SwitchPrimitive.Root>
|
</SwitchPrimitive.Root>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Switch }
|
export { Switch };
|
@ -1,6 +1,6 @@
|
|||||||
import * as React from "react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Table({ className, ...props }: React.ComponentProps<"table">) {
|
function Table({ className, ...props }: React.ComponentProps<"table">) {
|
||||||
return (
|
return (
|
||||||
@ -14,7 +14,7 @@ function Table({ className, ...props }: React.ComponentProps<"table">) {
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
|
function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
|
||||||
@ -24,7 +24,7 @@ function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
|
|||||||
className={cn("[&_tr]:border-b", className)}
|
className={cn("[&_tr]:border-b", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
|
function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
|
||||||
@ -34,7 +34,7 @@ function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
|
|||||||
className={cn("[&_tr:last-child]:border-0", className)}
|
className={cn("[&_tr:last-child]:border-0", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
||||||
@ -47,7 +47,7 @@ function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
||||||
@ -60,7 +60,7 @@ function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
||||||
@ -73,7 +73,7 @@ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
||||||
@ -86,7 +86,7 @@ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableCaption({
|
function TableCaption({
|
||||||
@ -99,7 +99,7 @@ function TableCaption({
|
|||||||
className={cn("text-muted-foreground mt-4 text-sm", className)}
|
className={cn("text-muted-foreground mt-4 text-sm", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -111,4 +111,4 @@ export {
|
|||||||
TableRow,
|
TableRow,
|
||||||
TableCell,
|
TableCell,
|
||||||
TableCaption,
|
TableCaption,
|
||||||
}
|
};
|
@ -1,9 +1,9 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
||||||
import * as TabsPrimitive from "@radix-ui/react-tabs"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Tabs({
|
function Tabs({
|
||||||
className,
|
className,
|
||||||
@ -15,7 +15,7 @@ function Tabs({
|
|||||||
className={cn("flex flex-col gap-2", className)}
|
className={cn("flex flex-col gap-2", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TabsList({
|
function TabsList({
|
||||||
@ -31,7 +31,7 @@ function TabsList({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TabsTrigger({
|
function TabsTrigger({
|
||||||
@ -47,7 +47,7 @@ function TabsTrigger({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TabsContent({
|
function TabsContent({
|
||||||
@ -60,7 +60,7 @@ function TabsContent({
|
|||||||
className={cn("flex-1 outline-none", className)}
|
className={cn("flex-1 outline-none", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Tabs, TabsList, TabsTrigger, TabsContent }
|
export { Tabs, TabsList, TabsTrigger, TabsContent };
|
@ -1,6 +1,6 @@
|
|||||||
import * as React from "react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
||||||
return (
|
return (
|
||||||
@ -12,7 +12,7 @@ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Textarea }
|
export { Textarea };
|
@ -1,18 +1,18 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
|
||||||
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group"
|
import { type VariantProps } from "class-variance-authority";
|
||||||
import { type VariantProps } from "class-variance-authority"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { toggleVariants } from "@/views/components/ui/toggle";
|
||||||
import { toggleVariants } from "@/components/ui/toggle"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
const ToggleGroupContext = React.createContext<
|
const ToggleGroupContext = React.createContext<
|
||||||
VariantProps<typeof toggleVariants>
|
VariantProps<typeof toggleVariants>
|
||||||
>({
|
>({
|
||||||
size: "default",
|
size: "default",
|
||||||
variant: "default",
|
variant: "default",
|
||||||
})
|
});
|
||||||
|
|
||||||
function ToggleGroup({
|
function ToggleGroup({
|
||||||
className,
|
className,
|
||||||
@ -37,7 +37,7 @@ function ToggleGroup({
|
|||||||
{children}
|
{children}
|
||||||
</ToggleGroupContext.Provider>
|
</ToggleGroupContext.Provider>
|
||||||
</ToggleGroupPrimitive.Root>
|
</ToggleGroupPrimitive.Root>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ToggleGroupItem({
|
function ToggleGroupItem({
|
||||||
@ -48,7 +48,7 @@ function ToggleGroupItem({
|
|||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &
|
}: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &
|
||||||
VariantProps<typeof toggleVariants>) {
|
VariantProps<typeof toggleVariants>) {
|
||||||
const context = React.useContext(ToggleGroupContext)
|
const context = React.useContext(ToggleGroupContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ToggleGroupPrimitive.Item
|
<ToggleGroupPrimitive.Item
|
||||||
@ -67,7 +67,7 @@ function ToggleGroupItem({
|
|||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</ToggleGroupPrimitive.Item>
|
</ToggleGroupPrimitive.Item>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { ToggleGroup, ToggleGroupItem }
|
export { ToggleGroup, ToggleGroupItem };
|
@ -1,8 +1,8 @@
|
|||||||
import * as React from "react"
|
import * as TogglePrimitive from "@radix-ui/react-toggle";
|
||||||
import * as TogglePrimitive from "@radix-ui/react-toggle"
|
import { type VariantProps, cva } from "class-variance-authority";
|
||||||
import { cva, type VariantProps } from "class-variance-authority"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
const toggleVariants = cva(
|
const toggleVariants = cva(
|
||||||
"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap",
|
"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap",
|
||||||
@ -24,7 +24,7 @@ const toggleVariants = cva(
|
|||||||
size: "default",
|
size: "default",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
|
|
||||||
function Toggle({
|
function Toggle({
|
||||||
className,
|
className,
|
||||||
@ -39,7 +39,7 @@ function Toggle({
|
|||||||
className={cn(toggleVariants({ variant, size, className }))}
|
className={cn(toggleVariants({ variant, size, className }))}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Toggle, toggleVariants }
|
export { Toggle, toggleVariants };
|
@ -1,7 +1,7 @@
|
|||||||
import * as React from "react"
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/infra/styles/utils"
|
import { cn } from "@/views/utils";
|
||||||
|
|
||||||
function TooltipProvider({
|
function TooltipProvider({
|
||||||
delayDuration = 0,
|
delayDuration = 0,
|
||||||
@ -13,7 +13,7 @@ function TooltipProvider({
|
|||||||
delayDuration={delayDuration}
|
delayDuration={delayDuration}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Tooltip({
|
function Tooltip({
|
||||||
@ -23,13 +23,13 @@ function Tooltip({
|
|||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TooltipTrigger({
|
function TooltipTrigger({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
|
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
|
||||||
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
|
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function TooltipContent({
|
function TooltipContent({
|
||||||
@ -53,7 +53,7 @@ function TooltipContent({
|
|||||||
<TooltipPrimitive.Arrow className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
|
<TooltipPrimitive.Arrow className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
|
||||||
</TooltipPrimitive.Content>
|
</TooltipPrimitive.Content>
|
||||||
</TooltipPrimitive.Portal>
|
</TooltipPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
|
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|
19
apps/webui/src/views/hooks/use-mobile.ts
Normal file
19
apps/webui/src/views/hooks/use-mobile.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
const MOBILE_BREAKPOINT = 768
|
||||||
|
|
||||||
|
export function useIsMobile() {
|
||||||
|
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
|
||||||
|
const onChange = () => {
|
||||||
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
||||||
|
}
|
||||||
|
mql.addEventListener("change", onChange)
|
||||||
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
||||||
|
return () => mql.removeEventListener("change", onChange)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return !!isMobile
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { AppNotFoundComponent } from '@/components/layout/app-not-found';
|
import { AppNotFoundComponent } from '@/views/components/layout/app-not-found';
|
||||||
import { createFileRoute } from '@tanstack/react-router';
|
import { createFileRoute } from '@tanstack/react-router';
|
||||||
|
|
||||||
export const Route = createFileRoute('/404')({
|
export const Route = createFileRoute('/404')({
|
@ -11,23 +11,17 @@ export const Route = createLazyFileRoute('/_app/playground/graphql-api')({
|
|||||||
});
|
});
|
||||||
|
|
||||||
function PlaygroundGraphQLApiRouteComponent() {
|
function PlaygroundGraphQLApiRouteComponent() {
|
||||||
const { authContext } = useAuth();
|
const { authProvider } = useAuth();
|
||||||
|
|
||||||
const fetcher: Fetcher = useCallback(
|
const fetcher: Fetcher = useCallback(
|
||||||
async (props) => {
|
async (props) => {
|
||||||
const accessToken = await firstValueFrom(
|
const authHeaders = await firstValueFrom(authProvider.getAuthHeaders());
|
||||||
authContext.authService.getAccessToken()
|
|
||||||
);
|
|
||||||
return createGraphiQLFetcher({
|
return createGraphiQLFetcher({
|
||||||
url: '/api/graphql',
|
url: '/api/graphql',
|
||||||
headers: accessToken
|
headers: authHeaders,
|
||||||
? {
|
|
||||||
Authorization: `Bearer ${accessToken}`,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
})(props);
|
})(props);
|
||||||
},
|
},
|
||||||
[authContext.authService.getAccessToken]
|
[authProvider]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
@ -1,5 +1,5 @@
|
|||||||
import { AppSkeleton } from '@/components/layout/app-skeleton';
|
|
||||||
import { buildLeafRouteStaticData } from '@/infra/routes/utils';
|
import { buildLeafRouteStaticData } from '@/infra/routes/utils';
|
||||||
|
import { AppSkeleton } from '@/views/components/layout/app-skeleton';
|
||||||
import { createFileRoute } from '@tanstack/react-router';
|
import { createFileRoute } from '@tanstack/react-router';
|
||||||
|
|
||||||
export const Route = createFileRoute('/_app/playground/graphql-api')({
|
export const Route = createFileRoute('/_app/playground/graphql-api')({
|
@ -1,5 +1,5 @@
|
|||||||
import { beforeLoadGuard } from '@/app/auth/guard';
|
import { beforeLoadGuard } from '@/app/auth/guard';
|
||||||
import { AppAside } from '@/components/layout/app-layout';
|
import { AppAside } from '@/views/components/layout/app-layout';
|
||||||
import { Outlet, createFileRoute } from '@tanstack/react-router';
|
import { Outlet, createFileRoute } from '@tanstack/react-router';
|
||||||
|
|
||||||
export const Route = createFileRoute('/_app')({
|
export const Route = createFileRoute('/_app')({
|
@ -1,5 +1,6 @@
|
|||||||
import { useAuth } from '@/app/auth/hooks';
|
import { useAuth } from '@/app/auth/hooks';
|
||||||
import { Button } from '@/components/ui/button';
|
import type { RouteStateDataOption } from '@/infra/routes/traits';
|
||||||
|
import { Button } from '@/views/components/ui/button';
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
@ -7,7 +8,7 @@ import {
|
|||||||
CardFooter,
|
CardFooter,
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from '@/components/ui/card';
|
} from '@/views/components/ui/card';
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
@ -16,17 +17,17 @@ import {
|
|||||||
FormItem,
|
FormItem,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from '@/components/ui/form';
|
} from '@/views/components/ui/form';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/views/components/ui/input';
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
SelectItem,
|
SelectItem,
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from '@/components/ui/select';
|
} from '@/views/components/ui/select';
|
||||||
import { Switch } from '@/components/ui/switch';
|
import { Switch } from '@/views/components/ui/switch';
|
||||||
import type { RouteStateDataOption } from '@/infra/routes/traits';
|
import { gql, useMutation } from '@apollo/client';
|
||||||
import { createFileRoute } from '@tanstack/react-router';
|
import { createFileRoute } from '@tanstack/react-router';
|
||||||
import { useNavigate } from '@tanstack/react-router';
|
import { useNavigate } from '@tanstack/react-router';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
@ -47,6 +48,18 @@ type SubscriptionFormValues = {
|
|||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CREATE_SUBSCRIPTION_MUTATION = gql`
|
||||||
|
mutation CreateSubscription($input: SubscriptionsInsertInput!) {
|
||||||
|
subscriptionsCreateOne(data: $input) {
|
||||||
|
id
|
||||||
|
displayName
|
||||||
|
sourceUrl
|
||||||
|
enabled
|
||||||
|
category
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
function SubscriptionCreateRouteComponent() {
|
function SubscriptionCreateRouteComponent() {
|
||||||
const { userData } = useAuth();
|
const { userData } = useAuth();
|
||||||
console.log(JSON.stringify(userData, null, 2));
|
console.log(JSON.stringify(userData, null, 2));
|
||||||
@ -61,21 +74,12 @@ function SubscriptionCreateRouteComponent() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [createSubscription] = useMutation(CREATE_SUBSCRIPTION_MUTATION);
|
||||||
|
|
||||||
const onSubmit = async (data: SubscriptionFormValues) => {
|
const onSubmit = async (data: SubscriptionFormValues) => {
|
||||||
try {
|
try {
|
||||||
setIsSubmitting(true);
|
setIsSubmitting(true);
|
||||||
const requestData = {
|
const response = await createSubscription({
|
||||||
query: `
|
|
||||||
mutation CreateSubscription($input: SubscriptionsInsertInput!) {
|
|
||||||
subscriptionsCreateOne(data: $input) {
|
|
||||||
id
|
|
||||||
displayName
|
|
||||||
sourceUrl
|
|
||||||
enabled
|
|
||||||
category
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
variables: {
|
variables: {
|
||||||
input: {
|
input: {
|
||||||
category: data.category,
|
category: data.category,
|
||||||
@ -84,18 +88,11 @@ function SubscriptionCreateRouteComponent() {
|
|||||||
enabled: data.enabled,
|
enabled: data.enabled,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
|
||||||
|
|
||||||
const response = await fetch('/api/graphql', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify(requestData),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const responseData = await response.json();
|
if (response.errors) {
|
||||||
if (responseData.errors) {
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
responseData.errors[0]?.message || 'Failed to create subscription'
|
response.errors[0]?.message || 'Failed to create subscription'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,9 @@
|
|||||||
import { AppAuthMethod, AuthMethodEnum } from '@/app/auth/config';
|
import { authContextFromInjector } from '@/app/auth/context';
|
||||||
import { useAuth } from '@/app/auth/hooks';
|
import { useAuth } from '@/app/auth/hooks';
|
||||||
import { ProLink } from '@/components/ui/pro-link';
|
import { AUTH_METHOD } from '@/infra/auth/defs';
|
||||||
import { Spinner } from '@/components/ui/spinner';
|
import { ProLink } from '@/views/components/ui/pro-link';
|
||||||
import { createFileRoute } from '@tanstack/react-router';
|
import { Spinner } from '@/views/components/ui/spinner';
|
||||||
|
import { createFileRoute, redirect } from '@tanstack/react-router';
|
||||||
import { useAtom } from 'jotai/react';
|
import { useAtom } from 'jotai/react';
|
||||||
import { atomWithObservable } from 'jotai/utils';
|
import { atomWithObservable } from 'jotai/utils';
|
||||||
import { EventTypes } from 'oidc-client-rx';
|
import { EventTypes } from 'oidc-client-rx';
|
||||||
@ -11,18 +12,24 @@ import { filter, map } from 'rxjs';
|
|||||||
|
|
||||||
export const Route = createFileRoute('/auth/oidc/callback')({
|
export const Route = createFileRoute('/auth/oidc/callback')({
|
||||||
component: OidcCallbackRouteComponent,
|
component: OidcCallbackRouteComponent,
|
||||||
|
beforeLoad: ({ context }) => {
|
||||||
|
const { authProvider } = authContextFromInjector(context.injector);
|
||||||
|
if (authProvider.authMethod !== AUTH_METHOD.OIDC) {
|
||||||
|
throw redirect({ to: '/' });
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
function OidcCallbackRouteComponent() {
|
function OidcCallbackRouteComponent() {
|
||||||
const { authContext } = useAuth();
|
const { authService } = useAuth();
|
||||||
|
|
||||||
const isLoading = useAtom(
|
const isLoading = useAtom(
|
||||||
useMemo(
|
useMemo(
|
||||||
() =>
|
() =>
|
||||||
atomWithObservable(() =>
|
atomWithObservable(() =>
|
||||||
authContext.checkAuthResultEvent$.pipe(map(Boolean))
|
authService.checkAuthResultEvent$.pipe(map(Boolean))
|
||||||
),
|
),
|
||||||
[authContext.checkAuthResultEvent$]
|
[authService.checkAuthResultEvent$]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -30,7 +37,7 @@ function OidcCallbackRouteComponent() {
|
|||||||
useMemo(
|
useMemo(
|
||||||
() =>
|
() =>
|
||||||
atomWithObservable(() =>
|
atomWithObservable(() =>
|
||||||
authContext.checkAuthResultEvent$.pipe(
|
authService.checkAuthResultEvent$.pipe(
|
||||||
filter(
|
filter(
|
||||||
(
|
(
|
||||||
e
|
e
|
||||||
@ -42,7 +49,7 @@ function OidcCallbackRouteComponent() {
|
|||||||
map((e) => e.value)
|
map((e) => e.value)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
[authContext.checkAuthResultEvent$]
|
[authService.checkAuthResultEvent$]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -64,27 +71,19 @@ function OidcCallbackRouteComponent() {
|
|||||||
<div className="flex justify-center font-bold text-4xl tracking-tighter sm:text-5xl">
|
<div className="flex justify-center font-bold text-4xl tracking-tighter sm:text-5xl">
|
||||||
<Spinner variant="circle-filled" size="48" />
|
<Spinner variant="circle-filled" size="48" />
|
||||||
</div>
|
</div>
|
||||||
{AppAuthMethod === AuthMethodEnum.OIDC ? (
|
{isLoading && (
|
||||||
<>
|
|
||||||
{isLoading && (
|
|
||||||
<p className="text-gray-500">
|
|
||||||
Processing OIDC authentication callback...
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
{checkAuthResultError && (
|
|
||||||
<p className="text-gray-500">
|
|
||||||
Failed to handle OIDC callback: {checkAuthResultError}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
{!isLoading && !checkAuthResultError && (
|
|
||||||
<p className="text-gray-500">
|
|
||||||
Succeed to handle OIDC authentication callback.
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<p className="text-gray-500">
|
<p className="text-gray-500">
|
||||||
Error: Current authentication method is not OIDC!
|
Processing OIDC authentication callback...
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
{checkAuthResultError && (
|
||||||
|
<p className="text-gray-500">
|
||||||
|
Failed to handle OIDC callback: {checkAuthResultError}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
{!isLoading && !checkAuthResultError && (
|
||||||
|
<p className="text-gray-500">
|
||||||
|
Succeed to handle OIDC authentication callback.
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{renderBackToHome()}
|
{renderBackToHome()}
|
@ -1,5 +1,5 @@
|
|||||||
import { AppAside } from '@/components/layout/app-layout';
|
import { AppAside } from '@/views/components/layout/app-layout';
|
||||||
import { AppSkeleton } from '@/components/layout/app-skeleton';
|
import { AppSkeleton } from '@/views/components/layout/app-skeleton';
|
||||||
import { createFileRoute } from '@tanstack/react-router';
|
import { createFileRoute } from '@tanstack/react-router';
|
||||||
|
|
||||||
export const Route = createFileRoute('/')({
|
export const Route = createFileRoute('/')({
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user