refactor: merge playground into webui
This commit is contained in:
@@ -1,24 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "recorder",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "rsbuild dev",
|
|
||||||
"build": "rsbuild build",
|
|
||||||
"preview": "rsbuild preview"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@graphiql/react": "^0.28.2",
|
|
||||||
"@graphiql/toolkit": "^0.11.1",
|
|
||||||
"graphiql": "^3.8.3",
|
|
||||||
"graphql-ws": "^6.0.4",
|
|
||||||
"observable-hooks": "^4.2.4",
|
|
||||||
"react": "^19.0.0",
|
|
||||||
"react-dom": "^19.0.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@rsbuild/plugin-react": "^1.1.1",
|
|
||||||
"@types/react": "^19.0.7",
|
|
||||||
"@types/react-dom": "^19.0.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
export default {
|
|
||||||
plugins: {
|
|
||||||
'@tailwindcss/postcss': {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../../../assets/favicon.ico
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
import { defineConfig } from '@rsbuild/core';
|
|
||||||
import { pluginReact } from '@rsbuild/plugin-react';
|
|
||||||
import { TanStackRouterRspack } from '@tanstack/router-plugin/rspack';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [pluginReact()],
|
|
||||||
html: {
|
|
||||||
favicon: './public/assets/favicon.ico',
|
|
||||||
// tags: [
|
|
||||||
// {
|
|
||||||
// tag: 'script',
|
|
||||||
// attrs: { src: 'https://cdn.tailwindcss.com' },
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
},
|
|
||||||
tools: {
|
|
||||||
rspack: {
|
|
||||||
plugins: [TanStackRouterRspack()],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
source: {
|
|
||||||
entry: {
|
|
||||||
index: './src/main.tsx',
|
|
||||||
},
|
|
||||||
define: {
|
|
||||||
'process.env.AUTH_TYPE': JSON.stringify(process.env.AUTH_TYPE),
|
|
||||||
'process.env.OIDC_CLIENT_ID': JSON.stringify(process.env.OIDC_CLIENT_ID),
|
|
||||||
'process.env.OIDC_CLIENT_SECRET': JSON.stringify(
|
|
||||||
process.env.OIDC_CLIENT_SECRET
|
|
||||||
),
|
|
||||||
'process.env.OIDC_ISSUER': JSON.stringify(process.env.OIDC_ISSUER),
|
|
||||||
'process.env.OIDC_AUDIENCE': JSON.stringify(process.env.OIDC_AUDIENCE),
|
|
||||||
'process.env.OIDC_EXTRA_SCOPES': JSON.stringify(
|
|
||||||
process.env.OIDC_EXTRA_SCOPES
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
dev: {
|
|
||||||
client: {
|
|
||||||
path: '/api/playground/rsbuild-hmr',
|
|
||||||
},
|
|
||||||
setupMiddlewares: [
|
|
||||||
(middlewares) => {
|
|
||||||
middlewares.unshift((req, res, next) => {
|
|
||||||
if (process.env.AUTH_TYPE === 'basic') {
|
|
||||||
res.setHeader('WWW-Authenticate', 'Basic realm="konobangu"');
|
|
||||||
|
|
||||||
const authorization =
|
|
||||||
(req.headers.authorization || '').split(' ')[1] || '';
|
|
||||||
const [user, password] = Buffer.from(authorization, 'base64')
|
|
||||||
.toString()
|
|
||||||
.split(':');
|
|
||||||
|
|
||||||
if (
|
|
||||||
user !== process.env.BASIC_USER ||
|
|
||||||
password !== process.env.BASIC_PASSWORD
|
|
||||||
) {
|
|
||||||
res.statusCode = 401;
|
|
||||||
res.write('Unauthorized');
|
|
||||||
res.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
return middlewares;
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
server: {
|
|
||||||
base: '/api/playground/',
|
|
||||||
host: '0.0.0.0',
|
|
||||||
port: 5002,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
1
apps/recorder/src/env.d.ts
vendored
1
apps/recorder/src/env.d.ts
vendored
@@ -1 +0,0 @@
|
|||||||
/// <reference types="@rsbuild/core/types" />
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
@import "tailwindcss";
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
import '@abraham/reflection';
|
|
||||||
import { type Injector, ReflectiveInjector } from '@outposts/injection-js';
|
|
||||||
import { RouterProvider, createRouter } from '@tanstack/react-router';
|
|
||||||
import {
|
|
||||||
OidcSecurityService,
|
|
||||||
provideAuth,
|
|
||||||
withCheckAuthResultEvent,
|
|
||||||
withDefaultFeatures,
|
|
||||||
} from 'oidc-client-rx';
|
|
||||||
import { withTanstackRouter } from 'oidc-client-rx/adapters/@tanstack/react-router';
|
|
||||||
import {
|
|
||||||
InjectorContextVoidInjector,
|
|
||||||
InjectorProvider,
|
|
||||||
} from 'oidc-client-rx/adapters/react';
|
|
||||||
import React from 'react';
|
|
||||||
import ReactDOM from 'react-dom/client';
|
|
||||||
import { buildOidcConfig, isBasicAuth } from './auth/config';
|
|
||||||
import { useAuth } from './auth/hooks';
|
|
||||||
import { routeTree } from './routeTree.gen';
|
|
||||||
import './main.css';
|
|
||||||
|
|
||||||
const router = createRouter({
|
|
||||||
routeTree,
|
|
||||||
basepath: '/api/playground',
|
|
||||||
defaultPreload: 'intent',
|
|
||||||
context: {
|
|
||||||
isAuthenticated: isBasicAuth,
|
|
||||||
injector: InjectorContextVoidInjector,
|
|
||||||
oidcSecurityService: {} as OidcSecurityService,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Register things for typesafety
|
|
||||||
declare module '@tanstack/react-router' {
|
|
||||||
interface Register {
|
|
||||||
router: typeof router;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const injector: Injector = isBasicAuth
|
|
||||||
? ReflectiveInjector.resolveAndCreate([])
|
|
||||||
: ReflectiveInjector.resolveAndCreate(
|
|
||||||
provideAuth(
|
|
||||||
{
|
|
||||||
config: buildOidcConfig(),
|
|
||||||
},
|
|
||||||
withDefaultFeatures({
|
|
||||||
router: { enabled: false },
|
|
||||||
securityStorage: { type: 'local-storage' },
|
|
||||||
}),
|
|
||||||
withTanstackRouter(router),
|
|
||||||
withCheckAuthResultEvent()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// if needed, check when init
|
|
||||||
let oidcSecurityService: OidcSecurityService | undefined;
|
|
||||||
if (!isBasicAuth) {
|
|
||||||
oidcSecurityService = injector.get(OidcSecurityService);
|
|
||||||
oidcSecurityService.checkAuth().subscribe();
|
|
||||||
}
|
|
||||||
|
|
||||||
const AppWithBasicAuth = () => {
|
|
||||||
return <RouterProvider router={router} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
const AppWithOidcAuth = () => {
|
|
||||||
const { isAuthenticated, oidcSecurityService, injector } = useAuth();
|
|
||||||
return (
|
|
||||||
<RouterProvider
|
|
||||||
router={router}
|
|
||||||
context={{
|
|
||||||
isAuthenticated,
|
|
||||||
oidcSecurityService,
|
|
||||||
injector,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const App = isBasicAuth ? AppWithBasicAuth : AppWithOidcAuth;
|
|
||||||
|
|
||||||
const rootEl = document.getElementById('root');
|
|
||||||
|
|
||||||
if (rootEl) {
|
|
||||||
rootEl.classList.add('min-h-svh');
|
|
||||||
const root = ReactDOM.createRoot(rootEl);
|
|
||||||
|
|
||||||
root.render(
|
|
||||||
<React.StrictMode>
|
|
||||||
<InjectorProvider injector={injector}>
|
|
||||||
<App />
|
|
||||||
</InjectorProvider>
|
|
||||||
</React.StrictMode>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
/* eslint-disable */
|
|
||||||
|
|
||||||
// @ts-nocheck
|
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
|
||||||
|
|
||||||
// This file was automatically generated by TanStack Router.
|
|
||||||
// You should NOT make any changes in this file as it will be overwritten.
|
|
||||||
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
|
|
||||||
|
|
||||||
// Import Routes
|
|
||||||
|
|
||||||
import { Route as rootRoute } from './web/controller/__root'
|
|
||||||
import { Route as IndexImport } from './web/controller/index'
|
|
||||||
import { Route as GraphqlIndexImport } from './web/controller/graphql/index'
|
|
||||||
import { Route as OidcCallbackImport } from './web/controller/oidc/callback'
|
|
||||||
|
|
||||||
// Create/Update Routes
|
|
||||||
|
|
||||||
const IndexRoute = IndexImport.update({
|
|
||||||
id: '/',
|
|
||||||
path: '/',
|
|
||||||
getParentRoute: () => rootRoute,
|
|
||||||
} as any)
|
|
||||||
|
|
||||||
const GraphqlIndexRoute = GraphqlIndexImport.update({
|
|
||||||
id: '/graphql/',
|
|
||||||
path: '/graphql/',
|
|
||||||
getParentRoute: () => rootRoute,
|
|
||||||
} as any)
|
|
||||||
|
|
||||||
const OidcCallbackRoute = OidcCallbackImport.update({
|
|
||||||
id: '/oidc/callback',
|
|
||||||
path: '/oidc/callback',
|
|
||||||
getParentRoute: () => rootRoute,
|
|
||||||
} as any)
|
|
||||||
|
|
||||||
// Populate the FileRoutesByPath interface
|
|
||||||
|
|
||||||
declare module '@tanstack/react-router' {
|
|
||||||
interface FileRoutesByPath {
|
|
||||||
'/': {
|
|
||||||
id: '/'
|
|
||||||
path: '/'
|
|
||||||
fullPath: '/'
|
|
||||||
preLoaderRoute: typeof IndexImport
|
|
||||||
parentRoute: typeof rootRoute
|
|
||||||
}
|
|
||||||
'/oidc/callback': {
|
|
||||||
id: '/oidc/callback'
|
|
||||||
path: '/oidc/callback'
|
|
||||||
fullPath: '/oidc/callback'
|
|
||||||
preLoaderRoute: typeof OidcCallbackImport
|
|
||||||
parentRoute: typeof rootRoute
|
|
||||||
}
|
|
||||||
'/graphql/': {
|
|
||||||
id: '/graphql/'
|
|
||||||
path: '/graphql'
|
|
||||||
fullPath: '/graphql'
|
|
||||||
preLoaderRoute: typeof GraphqlIndexImport
|
|
||||||
parentRoute: typeof rootRoute
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create and export the route tree
|
|
||||||
|
|
||||||
export interface FileRoutesByFullPath {
|
|
||||||
'/': typeof IndexRoute
|
|
||||||
'/oidc/callback': typeof OidcCallbackRoute
|
|
||||||
'/graphql': typeof GraphqlIndexRoute
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FileRoutesByTo {
|
|
||||||
'/': typeof IndexRoute
|
|
||||||
'/oidc/callback': typeof OidcCallbackRoute
|
|
||||||
'/graphql': typeof GraphqlIndexRoute
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FileRoutesById {
|
|
||||||
__root__: typeof rootRoute
|
|
||||||
'/': typeof IndexRoute
|
|
||||||
'/oidc/callback': typeof OidcCallbackRoute
|
|
||||||
'/graphql/': typeof GraphqlIndexRoute
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FileRouteTypes {
|
|
||||||
fileRoutesByFullPath: FileRoutesByFullPath
|
|
||||||
fullPaths: '/' | '/oidc/callback' | '/graphql'
|
|
||||||
fileRoutesByTo: FileRoutesByTo
|
|
||||||
to: '/' | '/oidc/callback' | '/graphql'
|
|
||||||
id: '__root__' | '/' | '/oidc/callback' | '/graphql/'
|
|
||||||
fileRoutesById: FileRoutesById
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RootRouteChildren {
|
|
||||||
IndexRoute: typeof IndexRoute
|
|
||||||
OidcCallbackRoute: typeof OidcCallbackRoute
|
|
||||||
GraphqlIndexRoute: typeof GraphqlIndexRoute
|
|
||||||
}
|
|
||||||
|
|
||||||
const rootRouteChildren: RootRouteChildren = {
|
|
||||||
IndexRoute: IndexRoute,
|
|
||||||
OidcCallbackRoute: OidcCallbackRoute,
|
|
||||||
GraphqlIndexRoute: GraphqlIndexRoute,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const routeTree = rootRoute
|
|
||||||
._addFileChildren(rootRouteChildren)
|
|
||||||
._addFileTypes<FileRouteTypes>()
|
|
||||||
|
|
||||||
/* ROUTE_MANIFEST_START
|
|
||||||
{
|
|
||||||
"routes": {
|
|
||||||
"__root__": {
|
|
||||||
"filePath": "__root.tsx",
|
|
||||||
"children": [
|
|
||||||
"/",
|
|
||||||
"/oidc/callback",
|
|
||||||
"/graphql/"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"/": {
|
|
||||||
"filePath": "index.tsx"
|
|
||||||
},
|
|
||||||
"/oidc/callback": {
|
|
||||||
"filePath": "oidc/callback.tsx"
|
|
||||||
},
|
|
||||||
"/graphql/": {
|
|
||||||
"filePath": "graphql/index.tsx"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ROUTE_MANIFEST_END */
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
import type { Injector } from '@outposts/injection-js';
|
|
||||||
import {
|
|
||||||
Outlet,
|
|
||||||
createRootRouteWithContext,
|
|
||||||
} from '@tanstack/react-router';
|
|
||||||
import { TanStackRouterDevtools } from '@tanstack/router-devtools';
|
|
||||||
import type { OidcSecurityService } from 'oidc-client-rx';
|
|
||||||
|
|
||||||
export type RouterContext =
|
|
||||||
| {
|
|
||||||
isAuthenticated: false;
|
|
||||||
injector: Injector;
|
|
||||||
oidcSecurityService: OidcSecurityService;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
isAuthenticated: true;
|
|
||||||
injector?: Injector;
|
|
||||||
oidcSecurityService?: OidcSecurityService;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Route = createRootRouteWithContext<RouterContext>()({
|
|
||||||
component: RootComponent,
|
|
||||||
});
|
|
||||||
|
|
||||||
function RootComponent() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Outlet />
|
|
||||||
<TanStackRouterDevtools position="bottom-right" />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
import { type Fetcher, createGraphiQLFetcher } from '@graphiql/toolkit';
|
|
||||||
import { createFileRoute } from '@tanstack/react-router';
|
|
||||||
import GraphiQL from 'graphiql';
|
|
||||||
import { useMemo } from 'react';
|
|
||||||
import { firstValueFrom } from 'rxjs';
|
|
||||||
import { beforeLoadGuard } from '../../../auth/guard';
|
|
||||||
import { useAuth } from '../../../auth/hooks';
|
|
||||||
import 'graphiql/graphiql.css';
|
|
||||||
|
|
||||||
export const Route = createFileRoute('/graphql/')({
|
|
||||||
component: RouteComponent,
|
|
||||||
beforeLoad: beforeLoadGuard,
|
|
||||||
});
|
|
||||||
|
|
||||||
function RouteComponent() {
|
|
||||||
const { oidcSecurityService } = useAuth();
|
|
||||||
|
|
||||||
const fetcher = useMemo(
|
|
||||||
(): Fetcher => async (props) => {
|
|
||||||
const accessToken = oidcSecurityService
|
|
||||||
? await firstValueFrom(oidcSecurityService.getAccessToken())
|
|
||||||
: undefined;
|
|
||||||
return createGraphiQLFetcher({
|
|
||||||
url: '/api/graphql',
|
|
||||||
headers: accessToken
|
|
||||||
? {
|
|
||||||
Authorization: `Bearer ${accessToken}`,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
})(props);
|
|
||||||
},
|
|
||||||
[oidcSecurityService]
|
|
||||||
);
|
|
||||||
|
|
||||||
return <GraphiQL fetcher={fetcher} className="!h-svh" />;
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { createFileRoute } from '@tanstack/react-router'
|
|
||||||
|
|
||||||
export const Route = createFileRoute('/')({
|
|
||||||
component: RouteComponent,
|
|
||||||
})
|
|
||||||
|
|
||||||
function RouteComponent() {
|
|
||||||
return <div>Hello to playground!</div>
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
import { createFileRoute, redirect } from '@tanstack/react-router';
|
|
||||||
import { EventTypes } from 'oidc-client-rx';
|
|
||||||
import { useAuth } from '../../../auth/hooks';
|
|
||||||
|
|
||||||
export const Route = createFileRoute('/oidc/callback')({
|
|
||||||
component: RouteComponent,
|
|
||||||
beforeLoad: ({ context }) => {
|
|
||||||
if (!context.oidcSecurityService) {
|
|
||||||
throw redirect({
|
|
||||||
to: '/',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
function RouteComponent() {
|
|
||||||
const auth = useAuth();
|
|
||||||
|
|
||||||
if (!auth.checkAuthResultEvent) {
|
|
||||||
return <div>Loading...</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
OpenID Connect Auth Callback:{' '}
|
|
||||||
{auth.checkAuthResultEvent?.type ===
|
|
||||||
EventTypes.CheckingAuthFinishedWithError
|
|
||||||
? auth.checkAuthResultEvent.value
|
|
||||||
: 'success'}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../tsconfig.base.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"rootDir": ".",
|
|
||||||
"composite": true,
|
|
||||||
"jsx": "react-jsx",
|
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "Bundler",
|
|
||||||
"experimentalDecorators": true,
|
|
||||||
"emitDecoratorMetadata": true,
|
|
||||||
"strict": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": true
|
|
||||||
},
|
|
||||||
"include": ["src"]
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"routesDirectory": "./src/web/controller",
|
|
||||||
"generatedRouteTree": "./src/routeTree.gen.ts"
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ark-ui/solid": "^4.10.2",
|
"@ark-ui/solid": "^4.10.2",
|
||||||
"@codemirror/language": "^6.10.8",
|
"@codemirror/language": "6.0.0",
|
||||||
"@corvu/drawer": "^0.2.3",
|
"@corvu/drawer": "^0.2.3",
|
||||||
"@corvu/otp-field": "^0.1.4",
|
"@corvu/otp-field": "^0.1.4",
|
||||||
"@corvu/resizable": "^0.2.4",
|
"@corvu/resizable": "^0.2.4",
|
||||||
@@ -26,14 +26,35 @@
|
|||||||
"embla-carousel-solid": "^8.5.2",
|
"embla-carousel-solid": "^8.5.2",
|
||||||
"graphiql": "^3.8.3",
|
"graphiql": "^3.8.3",
|
||||||
"lucide-solid": "^0.477.0",
|
"lucide-solid": "^0.477.0",
|
||||||
"react": "^18",
|
"react": "^18.0.0",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18.0.0",
|
||||||
"solid-js": "^1.9.5",
|
"solid-js": "^1.9.5",
|
||||||
"solid-sonner": "^0.2.8",
|
"solid-sonner": "^0.2.8",
|
||||||
"tailwindcss": "^3"
|
"tailwindcss": "^3.4.17",
|
||||||
|
"tailwind-merge": "^3.0.2",
|
||||||
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
"@tanstack/react-router": "^1.112.0",
|
||||||
|
"@tanstack/router-devtools": "^1.112.6",
|
||||||
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"@abraham/reflection": "^0.12.0",
|
||||||
|
"@outposts/injection-js": "^2.5.1",
|
||||||
|
"arktype": "^2.1.2",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"oidc-client-rx": "0.1.0-alpha.8",
|
||||||
|
"rxjs": "^7.8.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@rsbuild/core": "^1.2.14",
|
||||||
|
"@rsbuild/plugin-babel": "^1.0.4",
|
||||||
|
"chalk": "^5.4.1",
|
||||||
|
"commander": "^13.1.0",
|
||||||
|
"postcss": "^8.5.3",
|
||||||
"@rsbuild/plugin-solid": "^1.0.5",
|
"@rsbuild/plugin-solid": "^1.0.5",
|
||||||
"@tanstack/react-router": "^1.112.0"
|
"@tanstack/react-router": "^1.112.0",
|
||||||
|
"@types/react": "^18.0.0",
|
||||||
|
"@types/react-dom": "^18.0.0",
|
||||||
|
"@tailwindcss/postcss": "^4.0.9",
|
||||||
|
"@tanstack/router-devtools": "^1.112.6",
|
||||||
|
"@tanstack/router-plugin": "^1.112.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { TanStackRouterRspack } from '@tanstack/router-plugin/rspack';
|
|||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
html: {
|
html: {
|
||||||
|
title: 'Konobangu',
|
||||||
favicon: './public/assets/favicon.ico',
|
favicon: './public/assets/favicon.ico',
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { LogLevel, type OpenIdConfiguration } from 'oidc-client-rx';
|
import { LogLevel, type OpenIdConfiguration } from 'oidc-client-rx';
|
||||||
|
|
||||||
export const isBasicAuth = process.env.AUTH_TYPE === 'basic';
|
export const isBasicAuth = process.env.AUTH_TYPE === 'basic';
|
||||||
|
export const isOidcAuth = process.env.AUTH_TYPE === 'oidc';
|
||||||
|
|
||||||
export function buildOidcConfig(): OpenIdConfiguration {
|
export function buildOidcConfig(): OpenIdConfiguration {
|
||||||
const origin = window.location.origin;
|
const origin = window.location.origin;
|
||||||
|
|||||||
@@ -1,12 +1,4 @@
|
|||||||
import type { Injector } from '@outposts/injection-js';
|
import { createSignal } from 'solid-js';
|
||||||
import type { OidcSecurityService } from 'oidc-client-rx';
|
|
||||||
import { type Accessor, createSignal } from 'solid-js';
|
|
||||||
import { isBasicAuth } from './config';
|
import { isBasicAuth } from './config';
|
||||||
|
|
||||||
export const [isAuthenticated, setIsAuthenticated] = createSignal(isBasicAuth);
|
export const [isAuthenticated, setIsAuthenticated] = createSignal(isBasicAuth);
|
||||||
|
|
||||||
export type RouterContext = {
|
|
||||||
isAuthenticated: Accessor<boolean>;
|
|
||||||
injector: Injector;
|
|
||||||
oidcSecurityService: OidcSecurityService;
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { runInInjectionContext } from '@outposts/injection-js';
|
import { runInInjectionContext } from '@outposts/injection-js';
|
||||||
import { autoLoginPartialRoutesGuard } from 'oidc-client-rx';
|
import { autoLoginPartialRoutesGuard } from 'oidc-client-rx';
|
||||||
import { firstValueFrom } from 'rxjs';
|
import { firstValueFrom } from 'rxjs';
|
||||||
import type { RouterContext } from './context';
|
import type { RouterContext } from '~/traits/router';
|
||||||
|
|
||||||
export const beforeLoadGuard = async ({
|
export const beforeLoadGuard = async ({
|
||||||
context,
|
context,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
} from 'oidc-client-rx/adapters/solid-js';
|
} from 'oidc-client-rx/adapters/solid-js';
|
||||||
import { NEVER, of } from 'rxjs';
|
import { NEVER, of } from 'rxjs';
|
||||||
import { createMemo, from } from 'solid-js';
|
import { createMemo, from } from 'solid-js';
|
||||||
import { isBasicAuth } from './config';
|
import { isBasicAuth, isOidcAuth } from './config';
|
||||||
|
|
||||||
const BASIC_AUTH_IS_AUTHENTICATED$ = of({
|
const BASIC_AUTH_IS_AUTHENTICATED$ = of({
|
||||||
isAuthenticated: true,
|
isAuthenticated: true,
|
||||||
@@ -17,11 +17,10 @@ const BASIC_AUTH_USER_DATA$ = of({
|
|||||||
allUserData: [],
|
allUserData: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const useOidcClientExt = isOidcAuth ? useOidcClient : () => ({ oidcSecurityService: undefined, injector: InjectorContextVoidInjector })
|
||||||
|
|
||||||
export function useAuth() {
|
export function useAuth() {
|
||||||
const { oidcSecurityService, injector } = isBasicAuth
|
const { oidcSecurityService, injector } = useOidcClientExt();
|
||||||
? { oidcSecurityService: undefined, injector: InjectorContextVoidInjector }
|
|
||||||
: // biome-ignore lint/correctness/useHookAtTopLevel: <explanation>
|
|
||||||
useOidcClient();
|
|
||||||
|
|
||||||
const isAuthenticatedObj = from(
|
const isAuthenticatedObj = from(
|
||||||
oidcSecurityService?.isAuthenticated$ ?? BASIC_AUTH_IS_AUTHENTICATED$
|
oidcSecurityService?.isAuthenticated$ ?? BASIC_AUTH_IS_AUTHENTICATED$
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
import { Outlet } from '@tanstack/solid-router';
|
import { useMatches } from '@tanstack/solid-router';
|
||||||
|
import {
|
||||||
|
type ComponentProps,
|
||||||
|
type FlowProps,
|
||||||
|
For,
|
||||||
|
Show,
|
||||||
|
createMemo,
|
||||||
|
splitProps,
|
||||||
|
} from 'solid-js';
|
||||||
|
import { Dynamic } from 'solid-js/web';
|
||||||
import { AppSidebar } from '~/components/layout/app-sidebar';
|
import { AppSidebar } from '~/components/layout/app-sidebar';
|
||||||
import {
|
import {
|
||||||
Breadcrumb,
|
Breadcrumb,
|
||||||
@@ -13,8 +22,55 @@ import {
|
|||||||
SidebarProvider,
|
SidebarProvider,
|
||||||
SidebarTrigger,
|
SidebarTrigger,
|
||||||
} from '~/components/ui/sidebar';
|
} from '~/components/ui/sidebar';
|
||||||
|
import type { RouteStateDataOption } from '~/traits/router';
|
||||||
|
import type { RouteBreadcrumbItem } from '~/traits/router';
|
||||||
|
import { cn } from '~/utils/styles';
|
||||||
|
import { ProLink } from '../ui/pro-link';
|
||||||
|
|
||||||
|
export type AppAsideBreadcrumbItem = RouteBreadcrumbItem;
|
||||||
|
export interface AppAsideProps extends FlowProps<ComponentProps<'div'>> {
|
||||||
|
breadcrumb?: AppAsideBreadcrumbItem[];
|
||||||
|
extractBreadcrumbFromRoutes?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AppAside(props: AppAsideProps) {
|
||||||
|
const [local, other] = splitProps(props, [
|
||||||
|
'children',
|
||||||
|
'class',
|
||||||
|
'breadcrumb',
|
||||||
|
'extractBreadcrumbFromRoutes',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const matches = useMatches();
|
||||||
|
|
||||||
|
const breadcrumb = createMemo(() => {
|
||||||
|
if (local.breadcrumb) {
|
||||||
|
return local.breadcrumb;
|
||||||
|
}
|
||||||
|
if (local.extractBreadcrumbFromRoutes) {
|
||||||
|
return matches()
|
||||||
|
.map((m, i, arr) => {
|
||||||
|
const staticData = m.staticData as RouteStateDataOption;
|
||||||
|
if (staticData.breadcrumb) {
|
||||||
|
return {
|
||||||
|
link:
|
||||||
|
i + 1 >= arr.length
|
||||||
|
? undefined
|
||||||
|
: {
|
||||||
|
to: m.pathname,
|
||||||
|
},
|
||||||
|
...staticData.breadcrumb,
|
||||||
|
} as AppAsideBreadcrumbItem;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
})
|
||||||
|
.filter((b): b is AppAsideBreadcrumbItem => !!b);
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
|
||||||
|
const breadcrumbLength = breadcrumb().length;
|
||||||
|
|
||||||
export function AppLayout() {
|
|
||||||
return (
|
return (
|
||||||
<SidebarProvider>
|
<SidebarProvider>
|
||||||
<AppSidebar />
|
<AppSidebar />
|
||||||
@@ -22,24 +78,47 @@ export function AppLayout() {
|
|||||||
<header class="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12">
|
<header class="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12">
|
||||||
<div class="flex items-center gap-2 px-4">
|
<div class="flex items-center gap-2 px-4">
|
||||||
<SidebarTrigger class="-ml-1" />
|
<SidebarTrigger class="-ml-1" />
|
||||||
|
<Show when={breadcrumbLength}>
|
||||||
<Separator orientation="vertical" class="mr-2 h-4" />
|
<Separator orientation="vertical" class="mr-2 h-4" />
|
||||||
<Breadcrumb>
|
<Breadcrumb>
|
||||||
<BreadcrumbList>
|
<BreadcrumbList>
|
||||||
|
<For each={breadcrumb()}>
|
||||||
|
{(item, index) => {
|
||||||
|
const iconEl = (
|
||||||
|
<Show when={!!item.icon}>
|
||||||
|
<Dynamic component={item.icon} class=" size-4" />
|
||||||
|
</Show>
|
||||||
|
);
|
||||||
|
|
||||||
|
const isCurrent = index() + 1 === breadcrumbLength;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{index() > 0 && (
|
||||||
|
<BreadcrumbSeparator class="hidden md:block" />
|
||||||
|
)}
|
||||||
<BreadcrumbItem class="hidden md:block">
|
<BreadcrumbItem class="hidden md:block">
|
||||||
<BreadcrumbLink href="#">
|
<BreadcrumbLink
|
||||||
Building Your Application
|
class="text-[var(--foreground)] hover:text-inherit"
|
||||||
|
as={item.link ? ProLink : undefined}
|
||||||
|
current={isCurrent}
|
||||||
|
{...item?.link}
|
||||||
|
>
|
||||||
|
{iconEl}
|
||||||
|
{item.label}
|
||||||
</BreadcrumbLink>
|
</BreadcrumbLink>
|
||||||
</BreadcrumbItem>
|
</BreadcrumbItem>
|
||||||
<BreadcrumbSeparator class="hidden md:block" />
|
</>
|
||||||
<BreadcrumbItem>
|
);
|
||||||
<BreadcrumbLink current>Data Fetching</BreadcrumbLink>
|
}}
|
||||||
</BreadcrumbItem>
|
</For>
|
||||||
</BreadcrumbList>
|
</BreadcrumbList>
|
||||||
</Breadcrumb>
|
</Breadcrumb>
|
||||||
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div class="p-4 pt-0">
|
<div {...other} class={cn('min-h-0 flex-1 p-4 pt-0', local.class)}>
|
||||||
<Outlet />
|
{local.children}
|
||||||
</div>
|
</div>
|
||||||
</SidebarInset>
|
</SidebarInset>
|
||||||
</SidebarProvider>
|
</SidebarProvider>
|
||||||
|
|||||||
43
apps/webui/src/components/layout/app-not-found.tsx
Normal file
43
apps/webui/src/components/layout/app-not-found.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import {
|
||||||
|
type AnyRoute,
|
||||||
|
type ParsedLocation,
|
||||||
|
redirect,
|
||||||
|
} from '@tanstack/solid-router';
|
||||||
|
import { ProLink } from '../ui/pro-link';
|
||||||
|
|
||||||
|
export function guardRouteIndexAsNotFound(
|
||||||
|
this: AnyRoute,
|
||||||
|
{ location }: { location: ParsedLocation<any> }
|
||||||
|
) {
|
||||||
|
// biome-ignore lint/performance/useTopLevelRegex: <explanation>
|
||||||
|
if (location.pathname.replace(/\/+$/, '') === this.id) {
|
||||||
|
throw redirect({
|
||||||
|
href: '/404',
|
||||||
|
replace: true,
|
||||||
|
reloadDocument: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AppNotFoundComponent() {
|
||||||
|
return (
|
||||||
|
<div class="flex min-h-screen items-center px-4 py-12 sm:px-6 md:px-8 lg:px-12 xl:px-16">
|
||||||
|
<div class="w-full space-y-6 text-center">
|
||||||
|
<div class="space-y-3">
|
||||||
|
<h1 class="font-bold text-4xl tracking-tighter sm:text-5xl">
|
||||||
|
404 Page Not Found
|
||||||
|
</h1>
|
||||||
|
<p class="text-gray-500">
|
||||||
|
Sorry, we couldn't find the page you're looking for.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<ProLink
|
||||||
|
to="/"
|
||||||
|
class="inline-flex h-10 items-center rounded-md border border-gray-200 border-gray-200 bg-white px-8 font-medium text-sm shadow-sm transition-colors hover:bg-gray-100 hover:text-gray-900 dark:border-gray-800 dark:border-gray-800 dark:bg-gray-950 dark:focus-visible:ring-gray-300 dark:hover:bg-gray-800 dark:hover:text-gray-50"
|
||||||
|
>
|
||||||
|
Return to website
|
||||||
|
</ProLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
BookOpen,
|
BookOpen,
|
||||||
Bot,
|
|
||||||
Folders,
|
Folders,
|
||||||
Settings2,
|
Settings2,
|
||||||
SquareTerminal,
|
SquareTerminal,
|
||||||
@@ -52,40 +51,16 @@ const navMain = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Playground',
|
title: 'Playground',
|
||||||
href: '#',
|
|
||||||
icon: SquareTerminal,
|
icon: SquareTerminal,
|
||||||
isActive: true,
|
link: {
|
||||||
items: [
|
to: '/playground',
|
||||||
{
|
|
||||||
title: 'History',
|
|
||||||
href: '#',
|
|
||||||
},
|
},
|
||||||
|
children: [
|
||||||
{
|
{
|
||||||
title: 'Starred',
|
title: 'GraphQL Api',
|
||||||
href: '#',
|
link: {
|
||||||
|
to: '/playground/graphql-api',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: 'Settings',
|
|
||||||
href: '#',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Models',
|
|
||||||
href: '#',
|
|
||||||
icon: Bot,
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
title: 'Genesis',
|
|
||||||
href: '#',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Explorer',
|
|
||||||
href: '#',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Quantum',
|
|
||||||
href: '#',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -99,24 +74,16 @@ const navMain = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Settings',
|
title: 'Settings',
|
||||||
href: '#',
|
link: {
|
||||||
|
to: '/settings',
|
||||||
|
},
|
||||||
icon: Settings2,
|
icon: Settings2,
|
||||||
items: [
|
children: [
|
||||||
{
|
{
|
||||||
title: 'General',
|
title: 'Downloader',
|
||||||
href: '#',
|
link: {
|
||||||
|
to: '/settings/downloader',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: 'Team',
|
|
||||||
href: '#',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Billing',
|
|
||||||
href: '#',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Limits',
|
|
||||||
href: '#',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
12
apps/webui/src/components/layout/app-skeleton.tsx
Normal file
12
apps/webui/src/components/layout/app-skeleton.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
export function AppSkeleton() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div class="grid auto-rows-min gap-4 md:grid-cols-3">
|
||||||
|
<div class="aspect-video rounded-xl bg-muted/50" />
|
||||||
|
<div class="aspect-video rounded-xl bg-muted/50" />
|
||||||
|
<div class="aspect-video rounded-xl bg-muted/50" />
|
||||||
|
</div>
|
||||||
|
<div class="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,40 +1,45 @@
|
|||||||
import type { JSX, ValidComponent } from "solid-js"
|
import type { JSX, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import * as AccordionPrimitive from "@kobalte/core/accordion"
|
import * as AccordionPrimitive from '@kobalte/core/accordion';
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const Accordion = AccordionPrimitive.Root
|
const Accordion = AccordionPrimitive.Root;
|
||||||
|
|
||||||
type AccordionItemProps<T extends ValidComponent = "div"> =
|
type AccordionItemProps<T extends ValidComponent = 'div'> =
|
||||||
AccordionPrimitive.AccordionItemProps<T> & {
|
AccordionPrimitive.AccordionItemProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const AccordionItem = <T extends ValidComponent = "div">(
|
const AccordionItem = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, AccordionItemProps<T>>
|
props: PolymorphicProps<T, AccordionItemProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as AccordionItemProps, ["class"])
|
const [local, others] = splitProps(props as AccordionItemProps, ['class']);
|
||||||
return <AccordionPrimitive.Item class={cn("border-b", local.class)} {...others} />
|
return (
|
||||||
}
|
<AccordionPrimitive.Item class={cn('border-b', local.class)} {...others} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
type AccordionTriggerProps<T extends ValidComponent = "button"> =
|
type AccordionTriggerProps<T extends ValidComponent = 'button'> =
|
||||||
AccordionPrimitive.AccordionTriggerProps<T> & {
|
AccordionPrimitive.AccordionTriggerProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const AccordionTrigger = <T extends ValidComponent = "button">(
|
const AccordionTrigger = <T extends ValidComponent = 'button'>(
|
||||||
props: PolymorphicProps<T, AccordionTriggerProps<T>>
|
props: PolymorphicProps<T, AccordionTriggerProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as AccordionTriggerProps, ["class", "children"])
|
const [local, others] = splitProps(props as AccordionTriggerProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<AccordionPrimitive.Header class="flex">
|
<AccordionPrimitive.Header class="flex">
|
||||||
<AccordionPrimitive.Trigger
|
<AccordionPrimitive.Trigger
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-expanded]>svg]:rotate-180",
|
'flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-expanded]>svg]:rotate-180',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -54,30 +59,33 @@ const AccordionTrigger = <T extends ValidComponent = "button">(
|
|||||||
</svg>
|
</svg>
|
||||||
</AccordionPrimitive.Trigger>
|
</AccordionPrimitive.Trigger>
|
||||||
</AccordionPrimitive.Header>
|
</AccordionPrimitive.Header>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type AccordionContentProps<T extends ValidComponent = "div"> =
|
type AccordionContentProps<T extends ValidComponent = 'div'> =
|
||||||
AccordionPrimitive.AccordionContentProps<T> & {
|
AccordionPrimitive.AccordionContentProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const AccordionContent = <T extends ValidComponent = "div">(
|
const AccordionContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, AccordionContentProps<T>>
|
props: PolymorphicProps<T, AccordionContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as AccordionContentProps, ["class", "children"])
|
const [local, others] = splitProps(props as AccordionContentProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<AccordionPrimitive.Content
|
<AccordionPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
"animate-accordion-up overflow-hidden text-sm transition-all data-[expanded]:animate-accordion-down",
|
'animate-accordion-up overflow-hidden text-sm transition-all data-[expanded]:animate-accordion-down',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
>
|
>
|
||||||
<div class="pb-4 pt-0">{local.children}</div>
|
<div class="pt-0 pb-4">{local.children}</div>
|
||||||
</AccordionPrimitive.Content>
|
</AccordionPrimitive.Content>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
|
||||||
|
|||||||
@@ -1,57 +1,62 @@
|
|||||||
import type { JSX, ValidComponent } from "solid-js"
|
import type { JSX, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import * as AlertDialogPrimitive from "@kobalte/core/alert-dialog"
|
import * as AlertDialogPrimitive from '@kobalte/core/alert-dialog';
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const AlertDialog = AlertDialogPrimitive.Root
|
const AlertDialog = AlertDialogPrimitive.Root;
|
||||||
const AlertDialogTrigger = AlertDialogPrimitive.Trigger
|
const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
|
||||||
const AlertDialogPortal = AlertDialogPrimitive.Portal
|
const AlertDialogPortal = AlertDialogPrimitive.Portal;
|
||||||
|
|
||||||
type AlertDialogOverlayProps<T extends ValidComponent = "div"> =
|
type AlertDialogOverlayProps<T extends ValidComponent = 'div'> =
|
||||||
AlertDialogPrimitive.AlertDialogOverlayProps<T> & {
|
AlertDialogPrimitive.AlertDialogOverlayProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const AlertDialogOverlay = <T extends ValidComponent = "div">(
|
const AlertDialogOverlay = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, AlertDialogOverlayProps<T>>
|
props: PolymorphicProps<T, AlertDialogOverlayProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as AlertDialogOverlayProps, ["class"])
|
const [local, others] = splitProps(props as AlertDialogOverlayProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<AlertDialogPrimitive.Overlay
|
<AlertDialogPrimitive.Overlay
|
||||||
class={cn(
|
class={cn(
|
||||||
"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[expanded]:animate-in data-[closed]:animate-out data-[closed]:fade-out-0 data-[expanded]:fade-in-0",
|
'data-[closed]:fade-out-0 data-[expanded]:fade-in-0 fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[closed]:animate-out data-[expanded]:animate-in',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type AlertDialogContentProps<T extends ValidComponent = "div"> =
|
type AlertDialogContentProps<T extends ValidComponent = 'div'> =
|
||||||
AlertDialogPrimitive.AlertDialogContentProps<T> & {
|
AlertDialogPrimitive.AlertDialogContentProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const AlertDialogContent = <T extends ValidComponent = "div">(
|
const AlertDialogContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, AlertDialogContentProps<T>>
|
props: PolymorphicProps<T, AlertDialogContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as AlertDialogContentProps, ["class", "children"])
|
const [local, others] = splitProps(props as AlertDialogContentProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<AlertDialogPortal>
|
<AlertDialogPortal>
|
||||||
<AlertDialogOverlay />
|
<AlertDialogOverlay />
|
||||||
<AlertDialogPrimitive.Content
|
<AlertDialogPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
"fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-background p-6 shadow-lg duration-200 data-[expanded]:animate-in data-[closed]:animate-out data-[closed]:fade-out-0 data-[expanded]:fade-in-0 data-[closed]:zoom-out-95 data-[expanded]:zoom-in-95 data-[closed]:slide-out-to-left-1/2 data-[closed]:slide-out-to-top-[48%] data-[expanded]:slide-in-from-left-1/2 data-[expanded]:slide-in-from-top-[48%] sm:rounded-lg md:w-full",
|
'-translate-x-1/2 -translate-y-1/2 data-[closed]:fade-out-0 data-[expanded]:fade-in-0 data-[closed]:zoom-out-95 data-[expanded]:zoom-in-95 data-[closed]:slide-out-to-left-1/2 data-[closed]:slide-out-to-top-[48%] data-[expanded]:slide-in-from-left-1/2 data-[expanded]:slide-in-from-top-[48%] fixed top-1/2 left-1/2 z-50 grid w-full max-w-lg gap-4 border bg-background p-6 shadow-lg duration-200 data-[closed]:animate-out data-[expanded]:animate-in sm:rounded-lg md:w-full',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
>
|
>
|
||||||
{local.children}
|
{local.children}
|
||||||
<AlertDialogPrimitive.CloseButton class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[expanded]:bg-accent data-[expanded]:text-muted-foreground">
|
<AlertDialogPrimitive.CloseButton class="absolute top-4 right-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[expanded]:bg-accent data-[expanded]:text-muted-foreground">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
@@ -69,37 +74,44 @@ const AlertDialogContent = <T extends ValidComponent = "div">(
|
|||||||
</AlertDialogPrimitive.CloseButton>
|
</AlertDialogPrimitive.CloseButton>
|
||||||
</AlertDialogPrimitive.Content>
|
</AlertDialogPrimitive.Content>
|
||||||
</AlertDialogPortal>
|
</AlertDialogPortal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type AlertDialogTitleProps<T extends ValidComponent = "h2"> =
|
type AlertDialogTitleProps<T extends ValidComponent = 'h2'> =
|
||||||
AlertDialogPrimitive.AlertDialogTitleProps<T> & {
|
AlertDialogPrimitive.AlertDialogTitleProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const AlertDialogTitle = <T extends ValidComponent = "h2">(
|
const AlertDialogTitle = <T extends ValidComponent = 'h2'>(
|
||||||
props: PolymorphicProps<T, AlertDialogTitleProps<T>>
|
props: PolymorphicProps<T, AlertDialogTitleProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as AlertDialogTitleProps, ["class"])
|
const [local, others] = splitProps(props as AlertDialogTitleProps, ['class']);
|
||||||
return <AlertDialogPrimitive.Title class={cn("text-lg font-semibold", local.class)} {...others} />
|
|
||||||
}
|
|
||||||
|
|
||||||
type AlertDialogDescriptionProps<T extends ValidComponent = "p"> =
|
|
||||||
AlertDialogPrimitive.AlertDialogDescriptionProps<T> & {
|
|
||||||
class?: string | undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
const AlertDialogDescription = <T extends ValidComponent = "p">(
|
|
||||||
props: PolymorphicProps<T, AlertDialogDescriptionProps<T>>
|
|
||||||
) => {
|
|
||||||
const [local, others] = splitProps(props as AlertDialogDescriptionProps, ["class"])
|
|
||||||
return (
|
return (
|
||||||
<AlertDialogPrimitive.Description
|
<AlertDialogPrimitive.Title
|
||||||
class={cn("text-sm text-muted-foreground", local.class)}
|
class={cn('font-semibold text-lg', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
type AlertDialogDescriptionProps<T extends ValidComponent = 'p'> =
|
||||||
|
AlertDialogPrimitive.AlertDialogDescriptionProps<T> & {
|
||||||
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const AlertDialogDescription = <T extends ValidComponent = 'p'>(
|
||||||
|
props: PolymorphicProps<T, AlertDialogDescriptionProps<T>>
|
||||||
|
) => {
|
||||||
|
const [local, others] = splitProps(props as AlertDialogDescriptionProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
|
return (
|
||||||
|
<AlertDialogPrimitive.Description
|
||||||
|
class={cn('text-muted-foreground text-sm', local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
@@ -108,5 +120,5 @@ export {
|
|||||||
AlertDialogTrigger,
|
AlertDialogTrigger,
|
||||||
AlertDialogContent,
|
AlertDialogContent,
|
||||||
AlertDialogTitle,
|
AlertDialogTitle,
|
||||||
AlertDialogDescription
|
AlertDialogDescription,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,50 +1,63 @@
|
|||||||
import type { Component, ComponentProps, ValidComponent } from "solid-js"
|
import type { Component, ComponentProps, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import * as AlertPrimitive from "@kobalte/core/alert"
|
import * as AlertPrimitive from '@kobalte/core/alert';
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
import type { VariantProps } from "class-variance-authority"
|
import type { VariantProps } from 'class-variance-authority';
|
||||||
import { cva } from "class-variance-authority"
|
import { cva } from 'class-variance-authority';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const alertVariants = cva(
|
const alertVariants = cva(
|
||||||
"relative w-full rounded-lg border p-4 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
|
'relative w-full rounded-lg border p-4 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:top-4 [&>svg]:left-4 [&>svg]:text-foreground [&>svg~*]:pl-7',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: "bg-background text-foreground",
|
default: 'bg-background text-foreground',
|
||||||
destructive:
|
destructive:
|
||||||
"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive"
|
'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: "default"
|
variant: 'default',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
)
|
|
||||||
|
|
||||||
type AlertRootProps<T extends ValidComponent = "div"> = AlertPrimitive.AlertRootProps<T> &
|
type AlertRootProps<T extends ValidComponent = 'div'> =
|
||||||
VariantProps<typeof alertVariants> & { class?: string | undefined }
|
AlertPrimitive.AlertRootProps<T> &
|
||||||
|
VariantProps<typeof alertVariants> & { class?: string | undefined };
|
||||||
|
|
||||||
const Alert = <T extends ValidComponent = "div">(props: PolymorphicProps<T, AlertRootProps<T>>) => {
|
const Alert = <T extends ValidComponent = 'div'>(
|
||||||
const [local, others] = splitProps(props as AlertRootProps, ["class", "variant"])
|
props: PolymorphicProps<T, AlertRootProps<T>>
|
||||||
|
) => {
|
||||||
|
const [local, others] = splitProps(props as AlertRootProps, [
|
||||||
|
'class',
|
||||||
|
'variant',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<AlertPrimitive.Root
|
<AlertPrimitive.Root
|
||||||
class={cn(alertVariants({ variant: props.variant }), local.class)}
|
class={cn(alertVariants({ variant: props.variant }), local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const AlertTitle: Component<ComponentProps<"h5">> = (props) => {
|
const AlertTitle: Component<ComponentProps<'h5'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <h5 class={cn("mb-1 font-medium leading-none tracking-tight", local.class)} {...others} />
|
return (
|
||||||
}
|
<h5
|
||||||
|
class={cn('mb-1 font-medium leading-none tracking-tight', local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const AlertDescription: Component<ComponentProps<"div">> = (props) => {
|
const AlertDescription: Component<ComponentProps<'div'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <div class={cn("text-sm [&_p]:leading-relaxed", local.class)} {...others} />
|
return (
|
||||||
}
|
<div class={cn('text-sm [&_p]:leading-relaxed', local.class)} {...others} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export { Alert, AlertTitle, AlertDescription }
|
export { Alert, AlertTitle, AlertDescription };
|
||||||
|
|||||||
@@ -1,51 +1,64 @@
|
|||||||
import type { ValidComponent } from "solid-js"
|
import type { ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import * as ImagePrimitive from "@kobalte/core/image"
|
import * as ImagePrimitive from '@kobalte/core/image';
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
type AvatarRootProps<T extends ValidComponent = "span"> = ImagePrimitive.ImageRootProps<T> & {
|
type AvatarRootProps<T extends ValidComponent = 'span'> =
|
||||||
class?: string | undefined
|
ImagePrimitive.ImageRootProps<T> & {
|
||||||
}
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const Avatar = <T extends ValidComponent = "span">(
|
const Avatar = <T extends ValidComponent = 'span'>(
|
||||||
props: PolymorphicProps<T, AvatarRootProps<T>>
|
props: PolymorphicProps<T, AvatarRootProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as AvatarRootProps, ["class"])
|
const [local, others] = splitProps(props as AvatarRootProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<ImagePrimitive.Root
|
<ImagePrimitive.Root
|
||||||
class={cn("relative flex size-10 shrink-0 overflow-hidden rounded-full", local.class)}
|
class={cn(
|
||||||
|
'relative flex size-10 shrink-0 overflow-hidden rounded-full',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type AvatarImageProps<T extends ValidComponent = "img"> = ImagePrimitive.ImageImgProps<T> & {
|
type AvatarImageProps<T extends ValidComponent = 'img'> =
|
||||||
class?: string | undefined
|
ImagePrimitive.ImageImgProps<T> & {
|
||||||
}
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const AvatarImage = <T extends ValidComponent = "img">(
|
const AvatarImage = <T extends ValidComponent = 'img'>(
|
||||||
props: PolymorphicProps<T, AvatarImageProps<T>>
|
props: PolymorphicProps<T, AvatarImageProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as AvatarImageProps, ["class"])
|
const [local, others] = splitProps(props as AvatarImageProps, ['class']);
|
||||||
return <ImagePrimitive.Img class={cn("aspect-square size-full", local.class)} {...others} />
|
|
||||||
}
|
|
||||||
|
|
||||||
type AvatarFallbackProps<T extends ValidComponent = "span"> =
|
|
||||||
ImagePrimitive.ImageFallbackProps<T> & { class?: string | undefined }
|
|
||||||
|
|
||||||
const AvatarFallback = <T extends ValidComponent = "span">(
|
|
||||||
props: PolymorphicProps<T, AvatarFallbackProps<T>>
|
|
||||||
) => {
|
|
||||||
const [local, others] = splitProps(props as AvatarFallbackProps, ["class"])
|
|
||||||
return (
|
return (
|
||||||
<ImagePrimitive.Fallback
|
<ImagePrimitive.Img
|
||||||
class={cn("flex size-full items-center justify-center bg-muted", local.class)}
|
class={cn('aspect-square size-full', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Avatar, AvatarImage, AvatarFallback }
|
type AvatarFallbackProps<T extends ValidComponent = 'span'> =
|
||||||
|
ImagePrimitive.ImageFallbackProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
|
const AvatarFallback = <T extends ValidComponent = 'span'>(
|
||||||
|
props: PolymorphicProps<T, AvatarFallbackProps<T>>
|
||||||
|
) => {
|
||||||
|
const [local, others] = splitProps(props as AvatarFallbackProps, ['class']);
|
||||||
|
return (
|
||||||
|
<ImagePrimitive.Fallback
|
||||||
|
class={cn(
|
||||||
|
'flex size-full items-center justify-center bg-muted',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { Avatar, AvatarImage, AvatarFallback };
|
||||||
|
|||||||
@@ -1,27 +1,36 @@
|
|||||||
import type { Component, JSXElement } from "solid-js"
|
import type { Component, JSXElement } from 'solid-js';
|
||||||
import { createEffect, on, splitProps } from "solid-js"
|
import { createEffect, on, splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { VariantProps } from "class-variance-authority"
|
import type { VariantProps } from 'class-variance-authority';
|
||||||
import { cva } from "class-variance-authority"
|
import { cva } from 'class-variance-authority';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import type { BadgeProps } from '~/components/ui/badge';
|
||||||
import type { BadgeProps } from "~/components/ui/badge"
|
import { Badge } from '~/components/ui/badge';
|
||||||
import { Badge } from "~/components/ui/badge"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
type DeltaType = "increase" | "moderateIncrease" | "unchanged" | "moderateDecrease" | "decrease"
|
type DeltaType =
|
||||||
|
| 'increase'
|
||||||
|
| 'moderateIncrease'
|
||||||
|
| 'unchanged'
|
||||||
|
| 'moderateDecrease'
|
||||||
|
| 'decrease';
|
||||||
|
|
||||||
const badgeDeltaVariants = cva("", {
|
const badgeDeltaVariants = cva('', {
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
success: "bg-success text-success-foreground hover:bg-success",
|
success: 'bg-success text-success-foreground hover:bg-success',
|
||||||
warning: "bg-warning text-warning-foreground hover:bg-warning",
|
warning: 'bg-warning text-warning-foreground hover:bg-warning',
|
||||||
error: "bg-error text-error-foreground hover:bg-error"
|
error: 'bg-error text-error-foreground hover:bg-error',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
type DeltaVariant = NonNullable<VariantProps<typeof badgeDeltaVariants>["variant"]>
|
type DeltaVariant = NonNullable<
|
||||||
|
VariantProps<typeof badgeDeltaVariants>['variant']
|
||||||
|
>;
|
||||||
|
|
||||||
const iconMap: { [key in DeltaType]: (props: { class?: string }) => JSXElement } = {
|
const iconMap: {
|
||||||
|
[key in DeltaType]: (props: { class?: string }) => JSXElement;
|
||||||
|
} = {
|
||||||
increase: (props) => (
|
increase: (props) => (
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -99,38 +108,41 @@ const iconMap: { [key in DeltaType]: (props: { class?: string }) => JSXElement }
|
|||||||
<path d="M18 13l-6 6" />
|
<path d="M18 13l-6 6" />
|
||||||
<path d="M6 13l6 6" />
|
<path d="M6 13l6 6" />
|
||||||
</svg>
|
</svg>
|
||||||
)
|
),
|
||||||
}
|
};
|
||||||
|
|
||||||
const variantMap: { [key in DeltaType]: DeltaVariant } = {
|
const variantMap: { [key in DeltaType]: DeltaVariant } = {
|
||||||
increase: "success",
|
increase: 'success',
|
||||||
moderateIncrease: "success",
|
moderateIncrease: 'success',
|
||||||
unchanged: "warning",
|
unchanged: 'warning',
|
||||||
moderateDecrease: "error",
|
moderateDecrease: 'error',
|
||||||
decrease: "error"
|
decrease: 'error',
|
||||||
}
|
};
|
||||||
|
|
||||||
type BadgeDeltaProps = Omit<BadgeProps, "variant"> & {
|
type BadgeDeltaProps = Omit<BadgeProps, 'variant'> & {
|
||||||
deltaType: DeltaType
|
deltaType: DeltaType;
|
||||||
}
|
};
|
||||||
|
|
||||||
const BadgeDelta: Component<BadgeDeltaProps> = (props) => {
|
const BadgeDelta: Component<BadgeDeltaProps> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class", "children", "deltaType"])
|
const [local, others] = splitProps(props, ['class', 'children', 'deltaType']);
|
||||||
|
|
||||||
// eslint-disable-next-line solid/reactivity
|
// eslint-disable-next-line solid/reactivity
|
||||||
let Icon = iconMap[local.deltaType]
|
let Icon = iconMap[local.deltaType];
|
||||||
createEffect(
|
createEffect(
|
||||||
on(
|
on(
|
||||||
() => local.deltaType,
|
() => local.deltaType,
|
||||||
() => {
|
() => {
|
||||||
Icon = iconMap[local.deltaType]
|
Icon = iconMap[local.deltaType];
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Badge
|
<Badge
|
||||||
class={cn(badgeDeltaVariants({ variant: variantMap[local.deltaType] }), local.class)}
|
class={cn(
|
||||||
|
badgeDeltaVariants({ variant: variantMap[local.deltaType] }),
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
>
|
>
|
||||||
<span class="flex gap-1">
|
<span class="flex gap-1">
|
||||||
@@ -138,7 +150,7 @@ const BadgeDelta: Component<BadgeDeltaProps> = (props) => {
|
|||||||
{local.children}
|
{local.children}
|
||||||
</span>
|
</span>
|
||||||
</Badge>
|
</Badge>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { BadgeDelta }
|
export { BadgeDelta };
|
||||||
|
|||||||
@@ -1,48 +1,48 @@
|
|||||||
import type { Component, ComponentProps } from "solid-js"
|
import type { Component, ComponentProps } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { VariantProps } from "class-variance-authority"
|
import type { VariantProps } from 'class-variance-authority';
|
||||||
import { cva } from "class-variance-authority"
|
import { cva } from 'class-variance-authority';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const badgeVariants = cva(
|
const badgeVariants = cva(
|
||||||
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
'inline-flex items-center rounded-md border px-2.5 py-0.5 font-semibold text-xs transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: "border-transparent bg-primary text-primary-foreground",
|
default: 'border-transparent bg-primary text-primary-foreground',
|
||||||
secondary: "border-transparent bg-secondary text-secondary-foreground",
|
secondary: 'border-transparent bg-secondary text-secondary-foreground',
|
||||||
outline: "text-foreground",
|
outline: 'text-foreground',
|
||||||
success: "border-success-foreground bg-success text-success-foreground",
|
success: 'border-success-foreground bg-success text-success-foreground',
|
||||||
warning: "border-warning-foreground bg-warning text-warning-foreground",
|
warning: 'border-warning-foreground bg-warning text-warning-foreground',
|
||||||
error: "border-error-foreground bg-error text-error-foreground"
|
error: 'border-error-foreground bg-error text-error-foreground',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: "default"
|
variant: 'default',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
)
|
|
||||||
|
|
||||||
type BadgeProps = ComponentProps<"div"> &
|
type BadgeProps = ComponentProps<'div'> &
|
||||||
VariantProps<typeof badgeVariants> & {
|
VariantProps<typeof badgeVariants> & {
|
||||||
round?: boolean
|
round?: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
const Badge: Component<BadgeProps> = (props) => {
|
const Badge: Component<BadgeProps> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class", "variant", "round"])
|
const [local, others] = splitProps(props, ['class', 'variant', 'round']);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cn(
|
class={cn(
|
||||||
badgeVariants({ variant: local.variant }),
|
badgeVariants({ variant: local.variant }),
|
||||||
local.round && "rounded-full",
|
local.round && 'rounded-full',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export type { BadgeProps }
|
export type { BadgeProps };
|
||||||
export { Badge, badgeVariants }
|
export { Badge, badgeVariants };
|
||||||
|
|||||||
@@ -1,58 +1,64 @@
|
|||||||
import type { ComponentProps, JSX } from "solid-js"
|
import type { ComponentProps, JSX } from 'solid-js';
|
||||||
import { For, mergeProps, Show, splitProps } from "solid-js"
|
import { For, Show, mergeProps, splitProps } from 'solid-js';
|
||||||
import { Dynamic } from "solid-js/web"
|
import { Dynamic } from 'solid-js/web';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
type Bar<T> = T & {
|
type Bar<T> = T & {
|
||||||
value: number
|
value: number;
|
||||||
name: JSX.Element
|
name: JSX.Element;
|
||||||
icon?: (props: ComponentProps<"svg">) => JSX.Element
|
icon?: (props: ComponentProps<'svg'>) => JSX.Element;
|
||||||
href?: string
|
href?: string;
|
||||||
target?: string
|
target?: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
type SortOrder = "ascending" | "descending" | "none"
|
type SortOrder = 'ascending' | 'descending' | 'none';
|
||||||
|
|
||||||
type ValueFormatter = (value: number) => string
|
type ValueFormatter = (value: number) => string;
|
||||||
|
|
||||||
const defaultValueFormatter: ValueFormatter = (value: number) => value.toString()
|
const defaultValueFormatter: ValueFormatter = (value: number) =>
|
||||||
|
value.toString();
|
||||||
|
|
||||||
type BarListProps<T> = ComponentProps<"div"> & {
|
type BarListProps<T> = ComponentProps<'div'> & {
|
||||||
data: Bar<T>[]
|
data: Bar<T>[];
|
||||||
valueFormatter?: ValueFormatter
|
valueFormatter?: ValueFormatter;
|
||||||
sortOrder?: SortOrder
|
sortOrder?: SortOrder;
|
||||||
}
|
};
|
||||||
|
|
||||||
const BarList = <T,>(rawProps: BarListProps<T>) => {
|
const BarList = <T,>(rawProps: BarListProps<T>) => {
|
||||||
const props = mergeProps(
|
const props = mergeProps(
|
||||||
{
|
{
|
||||||
valueFormatter: defaultValueFormatter,
|
valueFormatter: defaultValueFormatter,
|
||||||
sortOrder: "descending" as SortOrder
|
sortOrder: 'descending' as SortOrder,
|
||||||
},
|
},
|
||||||
rawProps
|
rawProps
|
||||||
)
|
);
|
||||||
const [local, others] = splitProps(props, ["class", "data", "valueFormatter", "sortOrder"])
|
const [local, others] = splitProps(props, [
|
||||||
|
'class',
|
||||||
|
'data',
|
||||||
|
'valueFormatter',
|
||||||
|
'sortOrder',
|
||||||
|
]);
|
||||||
|
|
||||||
const sortedData = () => {
|
const sortedData = () => {
|
||||||
if (local.sortOrder === "none") {
|
if (local.sortOrder === 'none') {
|
||||||
return local.data
|
return local.data;
|
||||||
}
|
}
|
||||||
return local.data.sort((a, b) =>
|
return local.data.sort((a, b) =>
|
||||||
local.sortOrder === "ascending" ? a.value - b.value : b.value - a.value
|
local.sortOrder === 'ascending' ? a.value - b.value : b.value - a.value
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const widths = () => {
|
const widths = () => {
|
||||||
const maxValue = Math.max(...sortedData().map((item) => item.value), 0)
|
const maxValue = Math.max(...sortedData().map((item) => item.value), 0);
|
||||||
return sortedData().map((item) =>
|
return sortedData().map((item) =>
|
||||||
item.value === 0 ? 0 : Math.max((item.value / maxValue) * 100, 2)
|
item.value === 0 ? 0 : Math.max((item.value / maxValue) * 100, 2)
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cn("flex flex-col space-y-1.5", local.class)}
|
class={cn('flex flex-col space-y-1.5', local.class)}
|
||||||
aria-sort={local.sortOrder}
|
aria-sort={local.sortOrder}
|
||||||
{...others}
|
{...others}
|
||||||
>
|
>
|
||||||
@@ -62,19 +68,26 @@ const BarList = <T,>(rawProps: BarListProps<T>) => {
|
|||||||
<div class="row flex w-full justify-between space-x-6">
|
<div class="row flex w-full justify-between space-x-6">
|
||||||
<div class="grow">
|
<div class="grow">
|
||||||
<div
|
<div
|
||||||
class={cn("flex h-8 items-center rounded-md bg-secondary px-2")}
|
class={cn(
|
||||||
|
'flex h-8 items-center rounded-md bg-secondary px-2'
|
||||||
|
)}
|
||||||
style={{
|
style={{
|
||||||
width: `${widths()[idx()]}%`
|
width: `${widths()[idx()]}%`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Show when={bar.icon}>
|
<Show when={bar.icon}>
|
||||||
{(icon) => <Dynamic component={icon()} class="mr-2 size-5 flex-none" />}
|
{(icon) => (
|
||||||
|
<Dynamic
|
||||||
|
component={icon()}
|
||||||
|
class="mr-2 size-5 flex-none"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Show>
|
</Show>
|
||||||
<Show when={bar.href} fallback={<p>{bar.name}</p>}>
|
<Show when={bar.href} fallback={<p>{bar.name}</p>}>
|
||||||
{(href) => (
|
{(href) => (
|
||||||
<a
|
<a
|
||||||
href={href()}
|
href={href()}
|
||||||
target={bar.target ?? "_blank"}
|
target={bar.target ?? '_blank'}
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
class="hover:underline"
|
class="hover:underline"
|
||||||
>
|
>
|
||||||
@@ -84,13 +97,15 @@ const BarList = <T,>(rawProps: BarListProps<T>) => {
|
|||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center">{local.valueFormatter(bar.value)}</div>
|
<div class="flex items-center">
|
||||||
|
{local.valueFormatter(bar.value)}
|
||||||
</div>
|
</div>
|
||||||
)
|
</div>
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
</For>
|
</For>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { BarList }
|
export { BarList };
|
||||||
|
|||||||
@@ -1,61 +1,72 @@
|
|||||||
import type { Component, ComponentProps, JSX, ValidComponent } from "solid-js"
|
import type { Component, ComponentProps, JSX, ValidComponent } from 'solid-js';
|
||||||
import { Show, splitProps } from "solid-js"
|
import { Show, splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { PolymorphicProps } from "@kobalte/core"
|
import type { PolymorphicProps } from '@kobalte/core';
|
||||||
import * as BreadcrumbPrimitive from "@kobalte/core/breadcrumbs"
|
import * as BreadcrumbPrimitive from '@kobalte/core/breadcrumbs';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const Breadcrumb = BreadcrumbPrimitive.Root
|
const Breadcrumb = BreadcrumbPrimitive.Root;
|
||||||
|
|
||||||
const BreadcrumbList: Component<ComponentProps<"ol">> = (props) => {
|
const BreadcrumbList: Component<ComponentProps<'ol'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<ol
|
<ol
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5",
|
'flex flex-wrap items-center gap-1.5 break-words text-muted-foreground text-sm sm:gap-2.5',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const BreadcrumbItem: Component<ComponentProps<"li">> = (props) => {
|
const BreadcrumbItem: Component<ComponentProps<'li'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <li class={cn("inline-flex items-center gap-1.5", local.class)} {...others} />
|
return (
|
||||||
}
|
<li
|
||||||
|
class={cn('inline-flex items-center gap-1.5', local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
type BreadcrumbLinkProps<T extends ValidComponent = "a"> =
|
type BreadcrumbLinkProps<T extends ValidComponent = 'a'> =
|
||||||
BreadcrumbPrimitive.BreadcrumbsLinkProps<T> & { class?: string | undefined }
|
BreadcrumbPrimitive.BreadcrumbsLinkProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const BreadcrumbLink = <T extends ValidComponent = "a">(
|
const BreadcrumbLink = <T extends ValidComponent = 'a'>(
|
||||||
props: PolymorphicProps<T, BreadcrumbLinkProps<T>>
|
props: PolymorphicProps<T, BreadcrumbLinkProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as BreadcrumbLinkProps, ["class"])
|
const [local, others] = splitProps(props as BreadcrumbLinkProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<BreadcrumbPrimitive.Link
|
<BreadcrumbPrimitive.Link
|
||||||
class={cn(
|
class={cn(
|
||||||
"transition-colors hover:text-foreground data-[current]:font-normal data-[current]:text-foreground",
|
'transition-colors hover:text-foreground data-[current]:font-normal data-[current]:text-foreground',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type BreadcrumbSeparatorProps<T extends ValidComponent = "span"> =
|
type BreadcrumbSeparatorProps<T extends ValidComponent = 'span'> =
|
||||||
BreadcrumbPrimitive.BreadcrumbsSeparatorProps<T> & {
|
BreadcrumbPrimitive.BreadcrumbsSeparatorProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const BreadcrumbSeparator = <T extends ValidComponent = "span">(
|
const BreadcrumbSeparator = <T extends ValidComponent = 'span'>(
|
||||||
props: PolymorphicProps<T, BreadcrumbSeparatorProps<T>>
|
props: PolymorphicProps<T, BreadcrumbSeparatorProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as BreadcrumbSeparatorProps, ["class", "children"])
|
const [local, others] = splitProps(props as BreadcrumbSeparatorProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<BreadcrumbPrimitive.Separator class={cn("[&>svg]:size-3.5", local.class)} {...others}>
|
<BreadcrumbPrimitive.Separator
|
||||||
|
class={cn('[&>svg]:size-3.5', local.class)}
|
||||||
|
{...others}
|
||||||
|
>
|
||||||
<Show
|
<Show
|
||||||
when={local.children}
|
when={local.children}
|
||||||
fallback={
|
fallback={
|
||||||
@@ -75,13 +86,16 @@ const BreadcrumbSeparator = <T extends ValidComponent = "span">(
|
|||||||
{local.children}
|
{local.children}
|
||||||
</Show>
|
</Show>
|
||||||
</BreadcrumbPrimitive.Separator>
|
</BreadcrumbPrimitive.Separator>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const BreadcrumbEllipsis: Component<ComponentProps<"span">> = (props) => {
|
const BreadcrumbEllipsis: Component<ComponentProps<'span'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<span class={cn("flex size-9 items-center justify-center", local.class)} {...others}>
|
<span
|
||||||
|
class={cn('flex size-9 items-center justify-center', local.class)}
|
||||||
|
{...others}
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
@@ -98,8 +112,8 @@ const BreadcrumbEllipsis: Component<ComponentProps<"span">> = (props) => {
|
|||||||
</svg>
|
</svg>
|
||||||
<span class="sr-only">More</span>
|
<span class="sr-only">More</span>
|
||||||
</span>
|
</span>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Breadcrumb,
|
Breadcrumb,
|
||||||
@@ -107,5 +121,5 @@ export {
|
|||||||
BreadcrumbItem,
|
BreadcrumbItem,
|
||||||
BreadcrumbLink,
|
BreadcrumbLink,
|
||||||
BreadcrumbSeparator,
|
BreadcrumbSeparator,
|
||||||
BreadcrumbEllipsis
|
BreadcrumbEllipsis,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,53 +1,67 @@
|
|||||||
import type { JSX, ValidComponent } from "solid-js"
|
import type { JSX, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import * as ButtonPrimitive from "@kobalte/core/button"
|
import * as ButtonPrimitive from '@kobalte/core/button';
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
import type { VariantProps } from "class-variance-authority"
|
import type { VariantProps } from 'class-variance-authority';
|
||||||
import { cva } from "class-variance-authority"
|
import { cva } from 'class-variance-authority';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const buttonVariants = cva(
|
const buttonVariants = cva(
|
||||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium text-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
||||||
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
destructive:
|
||||||
outline: "border border-input hover:bg-accent hover:text-accent-foreground",
|
'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
||||||
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
outline:
|
||||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
'border border-input hover:bg-accent hover:text-accent-foreground',
|
||||||
link: "text-primary underline-offset-4 hover:underline"
|
secondary:
|
||||||
|
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
||||||
|
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
||||||
|
link: 'text-primary underline-offset-4 hover:underline',
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
default: "h-10 px-4 py-2",
|
default: 'h-10 px-4 py-2',
|
||||||
sm: "h-9 px-3 text-xs",
|
sm: 'h-9 px-3 text-xs',
|
||||||
lg: "h-11 px-8",
|
lg: 'h-11 px-8',
|
||||||
icon: "size-10"
|
icon: 'size-10',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: "default",
|
variant: 'default',
|
||||||
size: "default"
|
size: 'default',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
)
|
|
||||||
|
|
||||||
type ButtonProps<T extends ValidComponent = "button"> = ButtonPrimitive.ButtonRootProps<T> &
|
type ButtonProps<T extends ValidComponent = 'button'> =
|
||||||
VariantProps<typeof buttonVariants> & { class?: string | undefined; children?: JSX.Element }
|
ButtonPrimitive.ButtonRootProps<T> &
|
||||||
|
VariantProps<typeof buttonVariants> & {
|
||||||
|
class?: string | undefined;
|
||||||
|
children?: JSX.Element;
|
||||||
|
};
|
||||||
|
|
||||||
const Button = <T extends ValidComponent = "button">(
|
const Button = <T extends ValidComponent = 'button'>(
|
||||||
props: PolymorphicProps<T, ButtonProps<T>>
|
props: PolymorphicProps<T, ButtonProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ButtonProps, ["variant", "size", "class"])
|
const [local, others] = splitProps(props as ButtonProps, [
|
||||||
|
'variant',
|
||||||
|
'size',
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<ButtonPrimitive.Root
|
<ButtonPrimitive.Root
|
||||||
class={cn(buttonVariants({ variant: local.variant, size: local.size }), local.class)}
|
class={cn(
|
||||||
|
buttonVariants({ variant: local.variant, size: local.size }),
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export type { ButtonProps }
|
export type { ButtonProps };
|
||||||
export { Button, buttonVariants }
|
export { Button, buttonVariants };
|
||||||
|
|||||||
@@ -1,40 +1,46 @@
|
|||||||
import type { Component, ComponentProps } from "solid-js"
|
import type { Component, ComponentProps } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { VariantProps } from "class-variance-authority"
|
import type { VariantProps } from 'class-variance-authority';
|
||||||
import { cva } from "class-variance-authority"
|
import { cva } from 'class-variance-authority';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const calloutVariants = cva("rounded-md border-l-4 p-2 pl-4", {
|
const calloutVariants = cva('rounded-md border-l-4 p-2 pl-4', {
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: "border-info-foreground bg-info text-info-foreground",
|
default: 'border-info-foreground bg-info text-info-foreground',
|
||||||
success: "border-success-foreground bg-success text-success-foreground",
|
success: 'border-success-foreground bg-success text-success-foreground',
|
||||||
warning: "border-warning-foreground bg-warning text-warning-foreground",
|
warning: 'border-warning-foreground bg-warning text-warning-foreground',
|
||||||
error: "border-error-foreground bg-error text-error-foreground"
|
error: 'border-error-foreground bg-error text-error-foreground',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: "default"
|
variant: 'default',
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
type CalloutProps = ComponentProps<"div"> & VariantProps<typeof calloutVariants>
|
type CalloutProps = ComponentProps<'div'> &
|
||||||
|
VariantProps<typeof calloutVariants>;
|
||||||
|
|
||||||
const Callout: Component<CalloutProps> = (props) => {
|
const Callout: Component<CalloutProps> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class", "variant"])
|
const [local, others] = splitProps(props, ['class', 'variant']);
|
||||||
return <div class={cn(calloutVariants({ variant: local.variant }), local.class)} {...others} />
|
return (
|
||||||
}
|
<div
|
||||||
|
class={cn(calloutVariants({ variant: local.variant }), local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const CalloutTitle: Component<ComponentProps<"h3">> = (props) => {
|
const CalloutTitle: Component<ComponentProps<'h3'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <h3 class={cn("font-semibold", local.class)} {...others} />
|
return <h3 class={cn('font-semibold', local.class)} {...others} />;
|
||||||
}
|
};
|
||||||
|
|
||||||
const CalloutContent: Component<ComponentProps<"div">> = (props) => {
|
const CalloutContent: Component<ComponentProps<'div'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <div class={cn("mt-2", local.class)} {...others} />
|
return <div class={cn('mt-2', local.class)} {...others} />;
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Callout, CalloutTitle, CalloutContent }
|
export { Callout, CalloutTitle, CalloutContent };
|
||||||
|
|||||||
@@ -1,43 +1,65 @@
|
|||||||
import type { Component, ComponentProps } from "solid-js"
|
import type { Component, ComponentProps } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const Card: Component<ComponentProps<"div">> = (props) => {
|
const Card: Component<ComponentProps<'div'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cn("rounded-lg border bg-card text-card-foreground shadow-sm", local.class)}
|
class={cn(
|
||||||
|
'rounded-lg border bg-card text-card-foreground shadow-sm',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const CardHeader: Component<ComponentProps<"div">> = (props) => {
|
const CardHeader: Component<ComponentProps<'div'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <div class={cn("flex flex-col space-y-1.5 p-6", local.class)} {...others} />
|
|
||||||
}
|
|
||||||
|
|
||||||
const CardTitle: Component<ComponentProps<"h3">> = (props) => {
|
|
||||||
const [local, others] = splitProps(props, ["class"])
|
|
||||||
return (
|
return (
|
||||||
<h3 class={cn("text-lg font-semibold leading-none tracking-tight", local.class)} {...others} />
|
<div class={cn('flex flex-col space-y-1.5 p-6', local.class)} {...others} />
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const CardDescription: Component<ComponentProps<"p">> = (props) => {
|
const CardTitle: Component<ComponentProps<'h3'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <p class={cn("text-sm text-muted-foreground", local.class)} {...others} />
|
return (
|
||||||
}
|
<h3
|
||||||
|
class={cn(
|
||||||
|
'font-semibold text-lg leading-none tracking-tight',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const CardContent: Component<ComponentProps<"div">> = (props) => {
|
const CardDescription: Component<ComponentProps<'p'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <div class={cn("p-6 pt-0", local.class)} {...others} />
|
return (
|
||||||
}
|
<p class={cn('text-muted-foreground text-sm', local.class)} {...others} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const CardFooter: Component<ComponentProps<"div">> = (props) => {
|
const CardContent: Component<ComponentProps<'div'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <div class={cn("flex items-center p-6 pt-0", local.class)} {...others} />
|
return <div class={cn('p-6 pt-0', local.class)} {...others} />;
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
|
const CardFooter: Component<ComponentProps<'div'>> = (props) => {
|
||||||
|
const [local, others] = splitProps(props, ['class']);
|
||||||
|
return (
|
||||||
|
<div class={cn('flex items-center p-6 pt-0', local.class)} {...others} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
Card,
|
||||||
|
CardHeader,
|
||||||
|
CardFooter,
|
||||||
|
CardTitle,
|
||||||
|
CardDescription,
|
||||||
|
CardContent,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Accessor, Component, ComponentProps, VoidProps } from "solid-js"
|
import type { Accessor, Component, ComponentProps, VoidProps } from 'solid-js';
|
||||||
import {
|
import {
|
||||||
createContext,
|
createContext,
|
||||||
createEffect,
|
createEffect,
|
||||||
@@ -6,118 +6,122 @@ import {
|
|||||||
createSignal,
|
createSignal,
|
||||||
mergeProps,
|
mergeProps,
|
||||||
splitProps,
|
splitProps,
|
||||||
useContext
|
useContext,
|
||||||
} from "solid-js"
|
} from 'solid-js';
|
||||||
|
|
||||||
import type { CreateEmblaCarouselType } from "embla-carousel-solid"
|
import type { CreateEmblaCarouselType } from 'embla-carousel-solid';
|
||||||
import createEmblaCarousel from "embla-carousel-solid"
|
import createEmblaCarousel from 'embla-carousel-solid';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import type { ButtonProps } from '~/components/ui/button';
|
||||||
import type { ButtonProps } from "~/components/ui/button"
|
import { Button } from '~/components/ui/button';
|
||||||
import { Button } from "~/components/ui/button"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
export type CarouselApi = CreateEmblaCarouselType[1]
|
export type CarouselApi = CreateEmblaCarouselType[1];
|
||||||
|
|
||||||
type UseCarouselParameters = Parameters<typeof createEmblaCarousel>
|
type UseCarouselParameters = Parameters<typeof createEmblaCarousel>;
|
||||||
type CarouselOptions = NonNullable<UseCarouselParameters[0]>
|
type CarouselOptions = NonNullable<UseCarouselParameters[0]>;
|
||||||
type CarouselPlugin = NonNullable<UseCarouselParameters[1]>
|
type CarouselPlugin = NonNullable<UseCarouselParameters[1]>;
|
||||||
|
|
||||||
type CarouselProps = {
|
type CarouselProps = {
|
||||||
opts?: ReturnType<CarouselOptions>
|
opts?: ReturnType<CarouselOptions>;
|
||||||
plugins?: ReturnType<CarouselPlugin>
|
plugins?: ReturnType<CarouselPlugin>;
|
||||||
orientation?: "horizontal" | "vertical"
|
orientation?: 'horizontal' | 'vertical';
|
||||||
setApi?: (api: CarouselApi) => void
|
setApi?: (api: CarouselApi) => void;
|
||||||
}
|
};
|
||||||
|
|
||||||
type CarouselContextProps = {
|
type CarouselContextProps = {
|
||||||
carouselRef: ReturnType<typeof createEmblaCarousel>[0]
|
carouselRef: ReturnType<typeof createEmblaCarousel>[0];
|
||||||
api: ReturnType<typeof createEmblaCarousel>[1]
|
api: ReturnType<typeof createEmblaCarousel>[1];
|
||||||
scrollPrev: () => void
|
scrollPrev: () => void;
|
||||||
scrollNext: () => void
|
scrollNext: () => void;
|
||||||
canScrollPrev: Accessor<boolean>
|
canScrollPrev: Accessor<boolean>;
|
||||||
canScrollNext: Accessor<boolean>
|
canScrollNext: Accessor<boolean>;
|
||||||
} & CarouselProps
|
} & CarouselProps;
|
||||||
|
|
||||||
const CarouselContext = createContext<Accessor<CarouselContextProps> | null>(null)
|
const CarouselContext = createContext<Accessor<CarouselContextProps> | null>(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
const useCarousel = () => {
|
const useCarousel = () => {
|
||||||
const context = useContext(CarouselContext)
|
const context = 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();
|
||||||
}
|
};
|
||||||
|
|
||||||
const Carousel: Component<CarouselProps & ComponentProps<"div">> = (rawProps) => {
|
const Carousel: Component<CarouselProps & ComponentProps<'div'>> = (
|
||||||
const props = mergeProps<(CarouselProps & ComponentProps<"div">)[]>(
|
|
||||||
{ orientation: "horizontal" },
|
|
||||||
rawProps
|
rawProps
|
||||||
)
|
) => {
|
||||||
|
const props = mergeProps<(CarouselProps & ComponentProps<'div'>)[]>(
|
||||||
|
{ orientation: 'horizontal' },
|
||||||
|
rawProps
|
||||||
|
);
|
||||||
|
|
||||||
const [local, others] = splitProps(props, [
|
const [local, others] = splitProps(props, [
|
||||||
"orientation",
|
'orientation',
|
||||||
"opts",
|
'opts',
|
||||||
"setApi",
|
'setApi',
|
||||||
"plugins",
|
'plugins',
|
||||||
"class",
|
'class',
|
||||||
"children"
|
'children',
|
||||||
])
|
]);
|
||||||
|
|
||||||
const [carouselRef, api] = createEmblaCarousel(
|
const [carouselRef, api] = createEmblaCarousel(
|
||||||
() => ({
|
() => ({
|
||||||
...local.opts,
|
...local.opts,
|
||||||
axis: local.orientation === "horizontal" ? "x" : "y"
|
axis: local.orientation === 'horizontal' ? 'x' : 'y',
|
||||||
}),
|
}),
|
||||||
() => (local.plugins === undefined ? [] : local.plugins)
|
() => (local.plugins === undefined ? [] : local.plugins)
|
||||||
)
|
);
|
||||||
const [canScrollPrev, setCanScrollPrev] = createSignal(false)
|
const [canScrollPrev, setCanScrollPrev] = createSignal(false);
|
||||||
const [canScrollNext, setCanScrollNext] = createSignal(false)
|
const [canScrollNext, setCanScrollNext] = createSignal(false);
|
||||||
|
|
||||||
const onSelect = (api: NonNullable<ReturnType<CarouselApi>>) => {
|
const onSelect = (api: NonNullable<ReturnType<CarouselApi>>) => {
|
||||||
setCanScrollPrev(api.canScrollPrev())
|
setCanScrollPrev(api.canScrollPrev());
|
||||||
setCanScrollNext(api.canScrollNext())
|
setCanScrollNext(api.canScrollNext());
|
||||||
}
|
};
|
||||||
|
|
||||||
const scrollPrev = () => {
|
const scrollPrev = () => {
|
||||||
api()?.scrollPrev()
|
api()?.scrollPrev();
|
||||||
}
|
};
|
||||||
|
|
||||||
const scrollNext = () => {
|
const scrollNext = () => {
|
||||||
api()?.scrollNext()
|
api()?.scrollNext();
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleKeyDown = (event: KeyboardEvent) => {
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
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();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
if (!api() || !local.setApi) {
|
if (!api() || !local.setApi) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
local.setApi(api)
|
local.setApi(api);
|
||||||
})
|
});
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
if (!api()) {
|
if (!api()) {
|
||||||
return
|
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);
|
||||||
}
|
};
|
||||||
})
|
});
|
||||||
|
|
||||||
const value = createMemo(
|
const value = createMemo(
|
||||||
() =>
|
() =>
|
||||||
@@ -125,19 +129,21 @@ const Carousel: Component<CarouselProps & ComponentProps<"div">> = (rawProps) =>
|
|||||||
carouselRef,
|
carouselRef,
|
||||||
api,
|
api,
|
||||||
opts: local.opts,
|
opts: local.opts,
|
||||||
orientation: local.orientation || (local.opts?.axis === "y" ? "vertical" : "horizontal"),
|
orientation:
|
||||||
|
local.orientation ||
|
||||||
|
(local.opts?.axis === 'y' ? 'vertical' : 'horizontal'),
|
||||||
scrollPrev,
|
scrollPrev,
|
||||||
scrollNext,
|
scrollNext,
|
||||||
canScrollPrev,
|
canScrollPrev,
|
||||||
canScrollNext
|
canScrollNext,
|
||||||
}) satisfies CarouselContextProps
|
}) satisfies CarouselContextProps
|
||||||
)
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CarouselContext.Provider value={value}>
|
<CarouselContext.Provider value={value}>
|
||||||
<div
|
<div
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
class={cn("relative", local.class)}
|
class={cn('relative', local.class)}
|
||||||
role="region"
|
role="region"
|
||||||
aria-roledescription="carousel"
|
aria-roledescription="carousel"
|
||||||
{...others}
|
{...others}
|
||||||
@@ -145,57 +151,64 @@ const Carousel: Component<CarouselProps & ComponentProps<"div">> = (rawProps) =>
|
|||||||
{local.children}
|
{local.children}
|
||||||
</div>
|
</div>
|
||||||
</CarouselContext.Provider>
|
</CarouselContext.Provider>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const CarouselContent: Component<ComponentProps<"div">> = (props) => {
|
const CarouselContent: Component<ComponentProps<'div'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
const { carouselRef, orientation } = useCarousel()
|
const { carouselRef, orientation } = useCarousel();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={carouselRef} class="overflow-hidden">
|
<div ref={carouselRef} class="overflow-hidden">
|
||||||
<div
|
<div
|
||||||
class={cn("flex", orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col", local.class)}
|
class={cn(
|
||||||
|
'flex',
|
||||||
|
orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const CarouselItem: Component<ComponentProps<"div">> = (props) => {
|
const CarouselItem: Component<ComponentProps<'div'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
const { orientation } = useCarousel()
|
const { orientation } = useCarousel();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
role="group"
|
role="group"
|
||||||
aria-roledescription="slide"
|
aria-roledescription="slide"
|
||||||
class={cn(
|
class={cn(
|
||||||
"min-w-0 shrink-0 grow-0 basis-full",
|
'min-w-0 shrink-0 grow-0 basis-full',
|
||||||
orientation === "horizontal" ? "pl-4" : "pt-4",
|
orientation === 'horizontal' ? 'pl-4' : 'pt-4',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type CarouselButtonProps = VoidProps<ButtonProps>
|
type CarouselButtonProps = VoidProps<ButtonProps>;
|
||||||
|
|
||||||
const CarouselPrevious: Component<CarouselButtonProps> = (rawProps) => {
|
const CarouselPrevious: Component<CarouselButtonProps> = (rawProps) => {
|
||||||
const props = mergeProps<CarouselButtonProps[]>({ variant: "outline", size: "icon" }, rawProps)
|
const props = mergeProps<CarouselButtonProps[]>(
|
||||||
const [local, others] = splitProps(props, ["class", "variant", "size"])
|
{ variant: 'outline', size: 'icon' },
|
||||||
const { orientation, scrollPrev, canScrollPrev } = useCarousel()
|
rawProps
|
||||||
|
);
|
||||||
|
const [local, others] = splitProps(props, ['class', 'variant', 'size']);
|
||||||
|
const { orientation, scrollPrev, canScrollPrev } = useCarousel();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
variant={local.variant}
|
variant={local.variant}
|
||||||
size={local.size}
|
size={local.size}
|
||||||
class={cn(
|
class={cn(
|
||||||
"absolute size-8 touch-manipulation rounded-full",
|
'absolute size-8 touch-manipulation rounded-full',
|
||||||
orientation === "horizontal"
|
orientation === 'horizontal'
|
||||||
? "-left-12 top-1/2 -translate-y-1/2"
|
? '-left-12 -translate-y-1/2 top-1/2'
|
||||||
: "-top-12 left-1/2 -translate-x-1/2 rotate-90",
|
: '-top-12 -translate-x-1/2 left-1/2 rotate-90',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
disabled={!canScrollPrev()}
|
disabled={!canScrollPrev()}
|
||||||
@@ -218,23 +231,26 @@ const CarouselPrevious: Component<CarouselButtonProps> = (rawProps) => {
|
|||||||
</svg>
|
</svg>
|
||||||
<span class="sr-only">Previous slide</span>
|
<span class="sr-only">Previous slide</span>
|
||||||
</Button>
|
</Button>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const CarouselNext: Component<CarouselButtonProps> = (rawProps) => {
|
const CarouselNext: Component<CarouselButtonProps> = (rawProps) => {
|
||||||
const props = mergeProps<CarouselButtonProps[]>({ variant: "outline", size: "icon" }, rawProps)
|
const props = mergeProps<CarouselButtonProps[]>(
|
||||||
const [local, others] = splitProps(props, ["class", "variant", "size"])
|
{ variant: 'outline', size: 'icon' },
|
||||||
const { orientation, scrollNext, canScrollNext } = useCarousel()
|
rawProps
|
||||||
|
);
|
||||||
|
const [local, others] = splitProps(props, ['class', 'variant', 'size']);
|
||||||
|
const { orientation, scrollNext, canScrollNext } = useCarousel();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
variant={local.variant}
|
variant={local.variant}
|
||||||
size={local.size}
|
size={local.size}
|
||||||
class={cn(
|
class={cn(
|
||||||
"absolute size-8 touch-manipulation rounded-full",
|
'absolute size-8 touch-manipulation rounded-full',
|
||||||
orientation === "horizontal"
|
orientation === 'horizontal'
|
||||||
? "-right-12 top-1/2 -translate-y-1/2"
|
? '-right-12 -translate-y-1/2 top-1/2'
|
||||||
: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
|
: '-bottom-12 -translate-x-1/2 left-1/2 rotate-90',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
disabled={!canScrollNext()}
|
disabled={!canScrollNext()}
|
||||||
@@ -257,7 +273,13 @@ const CarouselNext: Component<CarouselButtonProps> = (rawProps) => {
|
|||||||
</svg>
|
</svg>
|
||||||
<span class="sr-only">Next slide</span>
|
<span class="sr-only">Next slide</span>
|
||||||
</Button>
|
</Button>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext }
|
export {
|
||||||
|
Carousel,
|
||||||
|
CarouselContent,
|
||||||
|
CarouselItem,
|
||||||
|
CarouselPrevious,
|
||||||
|
CarouselNext,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import type { ValidComponent } from "solid-js"
|
import type { ValidComponent } from 'solid-js';
|
||||||
import { Match, splitProps, Switch } from "solid-js"
|
import { Match, Switch, splitProps } from 'solid-js';
|
||||||
|
|
||||||
import * as CheckboxPrimitive from "@kobalte/core/checkbox"
|
import * as CheckboxPrimitive from '@kobalte/core/checkbox';
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
type CheckboxRootProps<T extends ValidComponent = "div"> =
|
type CheckboxRootProps<T extends ValidComponent = 'div'> =
|
||||||
CheckboxPrimitive.CheckboxRootProps<T> & { class?: string | undefined }
|
CheckboxPrimitive.CheckboxRootProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const Checkbox = <T extends ValidComponent = "div">(
|
const Checkbox = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, CheckboxRootProps<T>>
|
props: PolymorphicProps<T, CheckboxRootProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as CheckboxRootProps, ["class"])
|
const [local, others] = splitProps(props as CheckboxRootProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<CheckboxPrimitive.Root
|
<CheckboxPrimitive.Root
|
||||||
class={cn("items-top group relative flex space-x-2", local.class)}
|
class={cn('items-top group relative flex space-x-2', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
>
|
>
|
||||||
<CheckboxPrimitive.Input class="peer" />
|
<CheckboxPrimitive.Input class="peer" />
|
||||||
@@ -54,7 +54,7 @@ const Checkbox = <T extends ValidComponent = "div">(
|
|||||||
</CheckboxPrimitive.Indicator>
|
</CheckboxPrimitive.Indicator>
|
||||||
</CheckboxPrimitive.Control>
|
</CheckboxPrimitive.Control>
|
||||||
</CheckboxPrimitive.Root>
|
</CheckboxPrimitive.Root>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Checkbox }
|
export { Checkbox };
|
||||||
|
|||||||
@@ -1,43 +1,46 @@
|
|||||||
import type { JSX, ValidComponent } from "solid-js"
|
import type { JSX, ValidComponent } from 'solid-js';
|
||||||
import { Show, splitProps } from "solid-js"
|
import { Show, splitProps } from 'solid-js';
|
||||||
|
|
||||||
import * as ComboboxPrimitive from "@kobalte/core/combobox"
|
import * as ComboboxPrimitive from '@kobalte/core/combobox';
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const Combobox = ComboboxPrimitive.Root
|
const Combobox = ComboboxPrimitive.Root;
|
||||||
const ComboboxItemLabel = ComboboxPrimitive.ItemLabel
|
const ComboboxItemLabel = ComboboxPrimitive.ItemLabel;
|
||||||
const ComboboxHiddenSelect = ComboboxPrimitive.HiddenSelect
|
const ComboboxHiddenSelect = ComboboxPrimitive.HiddenSelect;
|
||||||
|
|
||||||
type ComboboxItemProps<T extends ValidComponent = "li"> = ComboboxPrimitive.ComboboxItemProps<T> & {
|
type ComboboxItemProps<T extends ValidComponent = 'li'> =
|
||||||
class?: string | undefined
|
ComboboxPrimitive.ComboboxItemProps<T> & {
|
||||||
}
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const ComboboxItem = <T extends ValidComponent = "li">(
|
const ComboboxItem = <T extends ValidComponent = 'li'>(
|
||||||
props: PolymorphicProps<T, ComboboxItemProps<T>>
|
props: PolymorphicProps<T, ComboboxItemProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ComboboxItemProps, ["class"])
|
const [local, others] = splitProps(props as ComboboxItemProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<ComboboxPrimitive.Item
|
<ComboboxPrimitive.Item
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative flex cursor-default select-none items-center justify-between rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50",
|
'relative flex cursor-default select-none items-center justify-between rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ComboboxItemIndicatorProps<T extends ValidComponent = "div"> =
|
type ComboboxItemIndicatorProps<T extends ValidComponent = 'div'> =
|
||||||
ComboboxPrimitive.ComboboxItemIndicatorProps<T> & {
|
ComboboxPrimitive.ComboboxItemIndicatorProps<T> & {
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const ComboboxItemIndicator = <T extends ValidComponent = "div">(
|
const ComboboxItemIndicator = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, ComboboxItemIndicatorProps<T>>
|
props: PolymorphicProps<T, ComboboxItemIndicatorProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ComboboxItemIndicatorProps, ["children"])
|
const [local, others] = splitProps(props as ComboboxItemIndicatorProps, [
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<ComboboxPrimitive.ItemIndicator {...others}>
|
<ComboboxPrimitive.ItemIndicator {...others}>
|
||||||
<Show
|
<Show
|
||||||
@@ -60,76 +63,84 @@ const ComboboxItemIndicator = <T extends ValidComponent = "div">(
|
|||||||
{(children) => children()}
|
{(children) => children()}
|
||||||
</Show>
|
</Show>
|
||||||
</ComboboxPrimitive.ItemIndicator>
|
</ComboboxPrimitive.ItemIndicator>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ComboboxSectionProps<T extends ValidComponent = "li"> =
|
type ComboboxSectionProps<T extends ValidComponent = 'li'> =
|
||||||
ComboboxPrimitive.ComboboxSectionProps<T> & { class?: string | undefined }
|
ComboboxPrimitive.ComboboxSectionProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const ComboboxSection = <T extends ValidComponent = "li">(
|
const ComboboxSection = <T extends ValidComponent = 'li'>(
|
||||||
props: PolymorphicProps<T, ComboboxSectionProps<T>>
|
props: PolymorphicProps<T, ComboboxSectionProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ComboboxSectionProps, ["class"])
|
const [local, others] = splitProps(props as ComboboxSectionProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<ComboboxPrimitive.Section
|
<ComboboxPrimitive.Section
|
||||||
class={cn(
|
class={cn(
|
||||||
"overflow-hidden p-1 px-2 py-1.5 text-xs font-medium text-muted-foreground ",
|
'overflow-hidden p-1 px-2 py-1.5 font-medium text-muted-foreground text-xs ',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ComboboxControlProps<
|
type ComboboxControlProps<
|
||||||
U,
|
U,
|
||||||
T extends ValidComponent = "div"
|
T extends ValidComponent = 'div',
|
||||||
> = ComboboxPrimitive.ComboboxControlProps<U, T> & {
|
> = ComboboxPrimitive.ComboboxControlProps<U, T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const ComboboxControl = <T, U extends ValidComponent = "div">(
|
const ComboboxControl = <T, U extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<U, ComboboxControlProps<T>>
|
props: PolymorphicProps<U, ComboboxControlProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ComboboxControlProps<T>, ["class"])
|
const [local, others] = splitProps(props as ComboboxControlProps<T>, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<ComboboxPrimitive.Control
|
<ComboboxPrimitive.Control
|
||||||
class={cn("flex h-10 items-center rounded-md border px-3", local.class)}
|
class={cn('flex h-10 items-center rounded-md border px-3', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ComboboxInputProps<T extends ValidComponent = "input"> =
|
type ComboboxInputProps<T extends ValidComponent = 'input'> =
|
||||||
ComboboxPrimitive.ComboboxInputProps<T> & { class?: string | undefined }
|
ComboboxPrimitive.ComboboxInputProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const ComboboxInput = <T extends ValidComponent = "input">(
|
const ComboboxInput = <T extends ValidComponent = 'input'>(
|
||||||
props: PolymorphicProps<T, ComboboxInputProps<T>>
|
props: PolymorphicProps<T, ComboboxInputProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ComboboxInputProps, ["class"])
|
const [local, others] = splitProps(props as ComboboxInputProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<ComboboxPrimitive.Input
|
<ComboboxPrimitive.Input
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex size-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
'flex size-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ComboboxTriggerProps<T extends ValidComponent = "button"> =
|
type ComboboxTriggerProps<T extends ValidComponent = 'button'> =
|
||||||
ComboboxPrimitive.ComboboxTriggerProps<T> & {
|
ComboboxPrimitive.ComboboxTriggerProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const ComboboxTrigger = <T extends ValidComponent = "button">(
|
const ComboboxTrigger = <T extends ValidComponent = 'button'>(
|
||||||
props: PolymorphicProps<T, ComboboxTriggerProps<T>>
|
props: PolymorphicProps<T, ComboboxTriggerProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ComboboxTriggerProps, ["class", "children"])
|
const [local, others] = splitProps(props as ComboboxTriggerProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<ComboboxPrimitive.Trigger class={cn("size-4 opacity-50", local.class)} {...others}>
|
<ComboboxPrimitive.Trigger
|
||||||
|
class={cn('size-4 opacity-50', local.class)}
|
||||||
|
{...others}
|
||||||
|
>
|
||||||
<ComboboxPrimitive.Icon>
|
<ComboboxPrimitive.Icon>
|
||||||
<Show
|
<Show
|
||||||
when={local.children}
|
when={local.children}
|
||||||
@@ -153,21 +164,21 @@ const ComboboxTrigger = <T extends ValidComponent = "button">(
|
|||||||
</Show>
|
</Show>
|
||||||
</ComboboxPrimitive.Icon>
|
</ComboboxPrimitive.Icon>
|
||||||
</ComboboxPrimitive.Trigger>
|
</ComboboxPrimitive.Trigger>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ComboboxContentProps<T extends ValidComponent = "div"> =
|
type ComboboxContentProps<T extends ValidComponent = 'div'> =
|
||||||
ComboboxPrimitive.ComboboxContentProps<T> & { class?: string | undefined }
|
ComboboxPrimitive.ComboboxContentProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const ComboboxContent = <T extends ValidComponent = "div">(
|
const ComboboxContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, ComboboxContentProps<T>>
|
props: PolymorphicProps<T, ComboboxContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ComboboxContentProps, ["class"])
|
const [local, others] = splitProps(props as ComboboxContentProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<ComboboxPrimitive.Portal>
|
<ComboboxPrimitive.Portal>
|
||||||
<ComboboxPrimitive.Content
|
<ComboboxPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative z-50 min-w-32 overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md animate-in fade-in-80",
|
'fade-in-80 relative z-50 min-w-32 animate-in overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -175,8 +186,8 @@ const ComboboxContent = <T extends ValidComponent = "div">(
|
|||||||
<ComboboxPrimitive.Listbox class="m-0 p-1" />
|
<ComboboxPrimitive.Listbox class="m-0 p-1" />
|
||||||
</ComboboxPrimitive.Content>
|
</ComboboxPrimitive.Content>
|
||||||
</ComboboxPrimitive.Portal>
|
</ComboboxPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Combobox,
|
Combobox,
|
||||||
@@ -188,5 +199,5 @@ export {
|
|||||||
ComboboxTrigger,
|
ComboboxTrigger,
|
||||||
ComboboxInput,
|
ComboboxInput,
|
||||||
ComboboxHiddenSelect,
|
ComboboxHiddenSelect,
|
||||||
ComboboxContent
|
ComboboxContent,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,28 +1,35 @@
|
|||||||
import type { Component, ComponentProps, ParentProps, VoidProps } from "solid-js"
|
import type {
|
||||||
import { splitProps } from "solid-js"
|
Component,
|
||||||
|
ComponentProps,
|
||||||
|
ParentProps,
|
||||||
|
VoidProps,
|
||||||
|
} from 'solid-js';
|
||||||
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { DialogRootProps } from "@kobalte/core/dialog"
|
import type { DialogRootProps } from '@kobalte/core/dialog';
|
||||||
import * as CommandPrimitive from "cmdk-solid"
|
import * as CommandPrimitive from 'cmdk-solid';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { Dialog, DialogContent } from '~/components/ui/dialog';
|
||||||
import { Dialog, DialogContent } from "~/components/ui/dialog"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const Command: Component<ParentProps<CommandPrimitive.CommandRootProps>> = (props) => {
|
const Command: Component<ParentProps<CommandPrimitive.CommandRootProps>> = (
|
||||||
const [local, others] = splitProps(props, ["class"])
|
props
|
||||||
|
) => {
|
||||||
|
const [local, others] = splitProps(props, ['class']);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommandPrimitive.CommandRoot
|
<CommandPrimitive.CommandRoot
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex size-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground blur-none",
|
'flex size-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground blur-none',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const CommandDialog: Component<ParentProps<DialogRootProps>> = (props) => {
|
const CommandDialog: Component<ParentProps<DialogRootProps>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["children"])
|
const [local, others] = splitProps(props, ['children']);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog {...others}>
|
<Dialog {...others}>
|
||||||
@@ -32,11 +39,13 @@ const CommandDialog: Component<ParentProps<DialogRootProps>> = (props) => {
|
|||||||
</Command>
|
</Command>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const CommandInput: Component<VoidProps<CommandPrimitive.CommandInputProps>> = (props) => {
|
const CommandInput: Component<VoidProps<CommandPrimitive.CommandInputProps>> = (
|
||||||
const [local, others] = splitProps(props, ["class"])
|
props
|
||||||
|
) => {
|
||||||
|
const [local, others] = splitProps(props, ['class']);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="flex items-center border-b px-3" cmdk-input-wrapper="">
|
<div class="flex items-center border-b px-3" cmdk-input-wrapper="">
|
||||||
@@ -55,82 +64,100 @@ const CommandInput: Component<VoidProps<CommandPrimitive.CommandInputProps>> = (
|
|||||||
</svg>
|
</svg>
|
||||||
<CommandPrimitive.CommandInput
|
<CommandPrimitive.CommandInput
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
'flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const CommandList: Component<ParentProps<CommandPrimitive.CommandListProps>> = (props) => {
|
const CommandList: Component<ParentProps<CommandPrimitive.CommandListProps>> = (
|
||||||
const [local, others] = splitProps(props, ["class"])
|
props
|
||||||
|
) => {
|
||||||
|
const [local, others] = splitProps(props, ['class']);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommandPrimitive.CommandList
|
<CommandPrimitive.CommandList
|
||||||
class={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", local.class)}
|
class={cn('max-h-[300px] overflow-y-auto overflow-x-hidden', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const CommandEmpty: Component<ParentProps<CommandPrimitive.CommandEmptyProps>> = (props) => {
|
const CommandEmpty: Component<
|
||||||
const [local, others] = splitProps(props, ["class"])
|
ParentProps<CommandPrimitive.CommandEmptyProps>
|
||||||
|
> = (props) => {
|
||||||
|
const [local, others] = splitProps(props, ['class']);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommandPrimitive.CommandEmpty
|
<CommandPrimitive.CommandEmpty
|
||||||
class={cn("py-6 text-center text-sm", local.class)}
|
class={cn('py-6 text-center text-sm', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const CommandGroup: Component<ParentProps<CommandPrimitive.CommandGroupProps>> = (props) => {
|
const CommandGroup: Component<
|
||||||
const [local, others] = splitProps(props, ["class"])
|
ParentProps<CommandPrimitive.CommandGroupProps>
|
||||||
|
> = (props) => {
|
||||||
|
const [local, others] = splitProps(props, ['class']);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommandPrimitive.CommandGroup
|
<CommandPrimitive.CommandGroup
|
||||||
class={cn(
|
class={cn(
|
||||||
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
'overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:text-xs',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const CommandSeparator: Component<VoidProps<CommandPrimitive.CommandSeparatorProps>> = (props) => {
|
const CommandSeparator: Component<
|
||||||
const [local, others] = splitProps(props, ["class"])
|
VoidProps<CommandPrimitive.CommandSeparatorProps>
|
||||||
|
> = (props) => {
|
||||||
|
const [local, others] = splitProps(props, ['class']);
|
||||||
|
|
||||||
return <CommandPrimitive.CommandSeparator class={cn("h-px bg-border", local.class)} {...others} />
|
return (
|
||||||
}
|
<CommandPrimitive.CommandSeparator
|
||||||
|
class={cn('h-px bg-border', local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const CommandItem: Component<ParentProps<CommandPrimitive.CommandItemProps>> = (props) => {
|
const CommandItem: Component<ParentProps<CommandPrimitive.CommandItemProps>> = (
|
||||||
const [local, others] = splitProps(props, ["class"])
|
props
|
||||||
|
) => {
|
||||||
|
const [local, others] = splitProps(props, ['class']);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommandPrimitive.CommandItem
|
<CommandPrimitive.CommandItem
|
||||||
cmdk-item=""
|
cmdk-item=""
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50",
|
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const CommandShortcut: Component<ComponentProps<"span">> = (props) => {
|
const CommandShortcut: Component<ComponentProps<'span'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
class={cn("ml-auto text-xs tracking-widest text-muted-foreground", local.class)}
|
class={cn(
|
||||||
|
'ml-auto text-muted-foreground text-xs tracking-widest',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Command,
|
Command,
|
||||||
@@ -141,5 +168,5 @@ export {
|
|||||||
CommandGroup,
|
CommandGroup,
|
||||||
CommandItem,
|
CommandItem,
|
||||||
CommandShortcut,
|
CommandShortcut,
|
||||||
CommandSeparator
|
CommandSeparator,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,99 +1,113 @@
|
|||||||
import type { Component, ComponentProps, JSX, ValidComponent } from "solid-js"
|
import type { Component, ComponentProps, JSX, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import * as ContextMenuPrimitive from "@kobalte/core/context-menu"
|
import * as ContextMenuPrimitive from '@kobalte/core/context-menu';
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const ContextMenuTrigger = ContextMenuPrimitive.Trigger
|
const ContextMenuTrigger = ContextMenuPrimitive.Trigger;
|
||||||
const ContextMenuPortal = ContextMenuPrimitive.Portal
|
const ContextMenuPortal = ContextMenuPrimitive.Portal;
|
||||||
const ContextMenuSub = ContextMenuPrimitive.Sub
|
const ContextMenuSub = ContextMenuPrimitive.Sub;
|
||||||
const ContextMenuGroup = ContextMenuPrimitive.Group
|
const ContextMenuGroup = ContextMenuPrimitive.Group;
|
||||||
const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup
|
const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;
|
||||||
|
|
||||||
const ContextMenu: Component<ContextMenuPrimitive.ContextMenuRootProps> = (props) => {
|
const ContextMenu: Component<ContextMenuPrimitive.ContextMenuRootProps> = (
|
||||||
return <ContextMenuPrimitive.Root gutter={4} {...props} />
|
props
|
||||||
}
|
) => {
|
||||||
|
return <ContextMenuPrimitive.Root gutter={4} {...props} />;
|
||||||
|
};
|
||||||
|
|
||||||
type ContextMenuContentProps<T extends ValidComponent = "div"> =
|
type ContextMenuContentProps<T extends ValidComponent = 'div'> =
|
||||||
ContextMenuPrimitive.ContextMenuContentProps<T> & {
|
ContextMenuPrimitive.ContextMenuContentProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const ContextMenuContent = <T extends ValidComponent = "div">(
|
const ContextMenuContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, ContextMenuContentProps<T>>
|
props: PolymorphicProps<T, ContextMenuContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ContextMenuContentProps, ["class"])
|
const [local, others] = splitProps(props as ContextMenuContentProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<ContextMenuPrimitive.Portal>
|
<ContextMenuPrimitive.Portal>
|
||||||
<ContextMenuPrimitive.Content
|
<ContextMenuPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
"z-50 min-w-32 origin-[var(--kb-menu-content-transform-origin)] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in",
|
'z-50 min-w-32 origin-[var(--kb-menu-content-transform-origin)] animate-in overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
</ContextMenuPrimitive.Portal>
|
</ContextMenuPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ContextMenuItemProps<T extends ValidComponent = "div"> =
|
type ContextMenuItemProps<T extends ValidComponent = 'div'> =
|
||||||
ContextMenuPrimitive.ContextMenuItemProps<T> & {
|
ContextMenuPrimitive.ContextMenuItemProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const ContextMenuItem = <T extends ValidComponent = "div">(
|
const ContextMenuItem = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, ContextMenuItemProps<T>>
|
props: PolymorphicProps<T, ContextMenuItemProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ContextMenuItemProps, ["class"])
|
const [local, others] = splitProps(props as ContextMenuItemProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<ContextMenuPrimitive.Item
|
<ContextMenuPrimitive.Item
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const ContextMenuShortcut: Component<ComponentProps<"span">> = (props) => {
|
const ContextMenuShortcut: Component<ComponentProps<'span'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <span class={cn("ml-auto text-xs tracking-widest opacity-60", local.class)} {...others} />
|
|
||||||
}
|
|
||||||
|
|
||||||
type ContextMenuSeparatorProps<T extends ValidComponent = "hr"> =
|
|
||||||
ContextMenuPrimitive.ContextMenuSeparatorProps<T> & {
|
|
||||||
class?: string | undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
const ContextMenuSeparator = <T extends ValidComponent = "hr">(
|
|
||||||
props: PolymorphicProps<T, ContextMenuSeparatorProps<T>>
|
|
||||||
) => {
|
|
||||||
const [local, others] = splitProps(props as ContextMenuSeparatorProps, ["class"])
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuPrimitive.Separator
|
<span
|
||||||
class={cn("-mx-1 my-1 h-px bg-muted", local.class)}
|
class={cn('ml-auto text-xs tracking-widest opacity-60', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ContextMenuSubTriggerProps<T extends ValidComponent = "div"> =
|
type ContextMenuSeparatorProps<T extends ValidComponent = 'hr'> =
|
||||||
|
ContextMenuPrimitive.ContextMenuSeparatorProps<T> & {
|
||||||
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ContextMenuSeparator = <T extends ValidComponent = 'hr'>(
|
||||||
|
props: PolymorphicProps<T, ContextMenuSeparatorProps<T>>
|
||||||
|
) => {
|
||||||
|
const [local, others] = splitProps(props as ContextMenuSeparatorProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
|
return (
|
||||||
|
<ContextMenuPrimitive.Separator
|
||||||
|
class={cn('-mx-1 my-1 h-px bg-muted', local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type ContextMenuSubTriggerProps<T extends ValidComponent = 'div'> =
|
||||||
ContextMenuPrimitive.ContextMenuSubTriggerProps<T> & {
|
ContextMenuPrimitive.ContextMenuSubTriggerProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const ContextMenuSubTrigger = <T extends ValidComponent = "div">(
|
const ContextMenuSubTrigger = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, ContextMenuSubTriggerProps<T>>
|
props: PolymorphicProps<T, ContextMenuSubTriggerProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ContextMenuSubTriggerProps, ["class", "children"])
|
const [local, others] = splitProps(props as ContextMenuSubTriggerProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<ContextMenuPrimitive.SubTrigger
|
<ContextMenuPrimitive.SubTrigger
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
|
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -112,43 +126,48 @@ const ContextMenuSubTrigger = <T extends ValidComponent = "div">(
|
|||||||
<path d="M9 6l6 6l-6 6" />
|
<path d="M9 6l6 6l-6 6" />
|
||||||
</svg>
|
</svg>
|
||||||
</ContextMenuPrimitive.SubTrigger>
|
</ContextMenuPrimitive.SubTrigger>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ContextMenuSubContentProps<T extends ValidComponent = "div"> =
|
type ContextMenuSubContentProps<T extends ValidComponent = 'div'> =
|
||||||
ContextMenuPrimitive.ContextMenuSubContentProps<T> & {
|
ContextMenuPrimitive.ContextMenuSubContentProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const ContextMenuSubContent = <T extends ValidComponent = "div">(
|
const ContextMenuSubContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, ContextMenuSubContentProps<T>>
|
props: PolymorphicProps<T, ContextMenuSubContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ContextMenuSubContentProps, ["class"])
|
const [local, others] = splitProps(props as ContextMenuSubContentProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<ContextMenuPrimitive.SubContent
|
<ContextMenuPrimitive.SubContent
|
||||||
class={cn(
|
class={cn(
|
||||||
"z-50 min-w-32 origin-[var(--kb-menu-content-transform-origin)] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in",
|
'z-50 min-w-32 origin-[var(--kb-menu-content-transform-origin)] animate-in overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ContextMenuCheckboxItemProps<T extends ValidComponent = "div"> =
|
type ContextMenuCheckboxItemProps<T extends ValidComponent = 'div'> =
|
||||||
ContextMenuPrimitive.ContextMenuCheckboxItemProps<T> & {
|
ContextMenuPrimitive.ContextMenuCheckboxItemProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const ContextMenuCheckboxItem = <T extends ValidComponent = "div">(
|
const ContextMenuCheckboxItem = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, ContextMenuCheckboxItemProps<T>>
|
props: PolymorphicProps<T, ContextMenuCheckboxItemProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ContextMenuCheckboxItemProps, ["class", "children"])
|
const [local, others] = splitProps(props as ContextMenuCheckboxItemProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<ContextMenuPrimitive.CheckboxItem
|
<ContextMenuPrimitive.CheckboxItem
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -171,40 +190,45 @@ const ContextMenuCheckboxItem = <T extends ValidComponent = "div">(
|
|||||||
</span>
|
</span>
|
||||||
{local.children}
|
{local.children}
|
||||||
</ContextMenuPrimitive.CheckboxItem>
|
</ContextMenuPrimitive.CheckboxItem>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ContextMenuGroupLabelProps<T extends ValidComponent = "span"> =
|
type ContextMenuGroupLabelProps<T extends ValidComponent = 'span'> =
|
||||||
ContextMenuPrimitive.ContextMenuGroupLabelProps<T> & {
|
ContextMenuPrimitive.ContextMenuGroupLabelProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const ContextMenuGroupLabel = <T extends ValidComponent = "span">(
|
const ContextMenuGroupLabel = <T extends ValidComponent = 'span'>(
|
||||||
props: PolymorphicProps<T, ContextMenuGroupLabelProps<T>>
|
props: PolymorphicProps<T, ContextMenuGroupLabelProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ContextMenuGroupLabelProps, ["class"])
|
const [local, others] = splitProps(props as ContextMenuGroupLabelProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<ContextMenuPrimitive.GroupLabel
|
<ContextMenuPrimitive.GroupLabel
|
||||||
class={cn("px-2 py-1.5 text-sm font-semibold", local.class)}
|
class={cn('px-2 py-1.5 font-semibold text-sm', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ContextMenuRadioItemProps<T extends ValidComponent = "div"> =
|
type ContextMenuRadioItemProps<T extends ValidComponent = 'div'> =
|
||||||
ContextMenuPrimitive.ContextMenuRadioItemProps<T> & {
|
ContextMenuPrimitive.ContextMenuRadioItemProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const ContextMenuRadioItem = <T extends ValidComponent = "div">(
|
const ContextMenuRadioItem = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, ContextMenuRadioItemProps<T>>
|
props: PolymorphicProps<T, ContextMenuRadioItemProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ContextMenuRadioItemProps, ["class", "children"])
|
const [local, others] = splitProps(props as ContextMenuRadioItemProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<ContextMenuPrimitive.RadioItem
|
<ContextMenuPrimitive.RadioItem
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -227,8 +251,8 @@ const ContextMenuRadioItem = <T extends ValidComponent = "div">(
|
|||||||
</span>
|
</span>
|
||||||
{local.children}
|
{local.children}
|
||||||
</ContextMenuPrimitive.RadioItem>
|
</ContextMenuPrimitive.RadioItem>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
@@ -245,5 +269,5 @@ export {
|
|||||||
ContextMenuGroup,
|
ContextMenuGroup,
|
||||||
ContextMenuGroupLabel,
|
ContextMenuGroupLabel,
|
||||||
ContextMenuRadioGroup,
|
ContextMenuRadioGroup,
|
||||||
ContextMenuRadioItem
|
ContextMenuRadioItem,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,53 +1,53 @@
|
|||||||
import { children, Show, splitProps } from "solid-js"
|
import { Show, children, splitProps } from 'solid-js';
|
||||||
|
|
||||||
import { DatePicker as DatePickerPrimitive } from "@ark-ui/solid"
|
import { DatePicker as DatePickerPrimitive } from '@ark-ui/solid';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { buttonVariants } from '~/components/ui/button';
|
||||||
import { buttonVariants } from "~/components/ui/button"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const DatePicker = DatePickerPrimitive.Root
|
const DatePicker = DatePickerPrimitive.Root;
|
||||||
const DatePickerLabel = DatePickerPrimitive.Label
|
const DatePickerLabel = DatePickerPrimitive.Label;
|
||||||
const DatePickerContext = DatePickerPrimitive.Context
|
const DatePickerContext = DatePickerPrimitive.Context;
|
||||||
const DatePickerTableHead = DatePickerPrimitive.TableHead
|
const DatePickerTableHead = DatePickerPrimitive.TableHead;
|
||||||
const DatePickerTableBody = DatePickerPrimitive.TableBody
|
const DatePickerTableBody = DatePickerPrimitive.TableBody;
|
||||||
const DatePickerYearSelect = DatePickerPrimitive.YearSelect
|
const DatePickerYearSelect = DatePickerPrimitive.YearSelect;
|
||||||
const DatePickerMonthSelect = DatePickerPrimitive.MonthSelect
|
const DatePickerMonthSelect = DatePickerPrimitive.MonthSelect;
|
||||||
const DatePickerPositioner = DatePickerPrimitive.Positioner
|
const DatePickerPositioner = DatePickerPrimitive.Positioner;
|
||||||
|
|
||||||
const DatePickerControl = (props: DatePickerPrimitive.ControlProps) => {
|
const DatePickerControl = (props: DatePickerPrimitive.ControlProps) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<DatePickerPrimitive.Control
|
<DatePickerPrimitive.Control
|
||||||
class={cn("inline-flex items-center gap-1", local.class)}
|
class={cn('inline-flex items-center gap-1', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const DatePickerInput = (props: DatePickerPrimitive.InputProps) => {
|
const DatePickerInput = (props: DatePickerPrimitive.InputProps) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<DatePickerPrimitive.Input
|
<DatePickerPrimitive.Input
|
||||||
class={cn(
|
class={cn(
|
||||||
"h-9 w-full rounded-md border border-border bg-background px-3 py-1 text-sm shadow-sm transition-shadow placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-[1.5px] focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
|
'h-9 w-full rounded-md border border-border bg-background px-3 py-1 text-sm shadow-sm transition-shadow placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-[1.5px] focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const DatePickerTrigger = (props: DatePickerPrimitive.TriggerProps) => {
|
const DatePickerTrigger = (props: DatePickerPrimitive.TriggerProps) => {
|
||||||
const [local, others] = splitProps(props, ["class", "children"])
|
const [local, others] = splitProps(props, ['class', 'children']);
|
||||||
|
|
||||||
// prevents rendering children twice
|
// prevents rendering children twice
|
||||||
const resolvedChildren = children(() => local.children)
|
const resolvedChildren = children(() => local.children);
|
||||||
const hasChildren = () => resolvedChildren.toArray().length !== 0
|
const hasChildren = () => resolvedChildren.toArray().length !== 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DatePickerPrimitive.Trigger
|
<DatePickerPrimitive.Trigger
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex min-h-9 min-w-9 items-center justify-center rounded-md border border-border bg-background transition-[box-shadow,background-color] hover:bg-accent/50 focus-visible:outline-none focus-visible:ring-[1.5px] focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>svg]:size-4",
|
'flex min-h-9 min-w-9 items-center justify-center rounded-md border border-border bg-background transition-[box-shadow,background-color] hover:bg-accent/50 focus-visible:outline-none focus-visible:ring-[1.5px] focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>svg]:size-4',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -73,54 +73,59 @@ const DatePickerTrigger = (props: DatePickerPrimitive.TriggerProps) => {
|
|||||||
</svg>
|
</svg>
|
||||||
</Show>
|
</Show>
|
||||||
</DatePickerPrimitive.Trigger>
|
</DatePickerPrimitive.Trigger>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const DatePickerContent = (props: DatePickerPrimitive.ContentProps) => {
|
const DatePickerContent = (props: DatePickerPrimitive.ContentProps) => {
|
||||||
const [local, others] = splitProps(props, ["class", "children"])
|
const [local, others] = splitProps(props, ['class', 'children']);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DatePickerPrimitive.Content
|
<DatePickerPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
"z-50 rounded-md border bg-popover p-3 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 z-50 rounded-md border bg-popover p-3 text-popover-foreground shadow-md outline-none data-[state=closed]:animate-out data-[state=open]:animate-in',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
>
|
>
|
||||||
{local.children}
|
{local.children}
|
||||||
</DatePickerPrimitive.Content>
|
</DatePickerPrimitive.Content>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const DatePickerView = (props: DatePickerPrimitive.ViewProps) => {
|
const DatePickerView = (props: DatePickerPrimitive.ViewProps) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <DatePickerPrimitive.View class={cn("space-y-4", local.class)} {...others} />
|
|
||||||
}
|
|
||||||
|
|
||||||
const DatePickerViewControl = (props: DatePickerPrimitive.ViewControlProps) => {
|
|
||||||
const [local, others] = splitProps(props, ["class"])
|
|
||||||
return (
|
return (
|
||||||
<DatePickerPrimitive.ViewControl
|
<DatePickerPrimitive.View
|
||||||
class={cn("flex items-center justify-between gap-4", local.class)}
|
class={cn('space-y-4', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
const DatePickerViewControl = (props: DatePickerPrimitive.ViewControlProps) => {
|
||||||
|
const [local, others] = splitProps(props, ['class']);
|
||||||
|
return (
|
||||||
|
<DatePickerPrimitive.ViewControl
|
||||||
|
class={cn('flex items-center justify-between gap-4', local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const DatePickerPrevTrigger = (props: DatePickerPrimitive.PrevTriggerProps) => {
|
const DatePickerPrevTrigger = (props: DatePickerPrimitive.PrevTriggerProps) => {
|
||||||
const [local, others] = splitProps(props, ["class", "children"])
|
const [local, others] = splitProps(props, ['class', 'children']);
|
||||||
|
|
||||||
// prevents rendering children twice
|
// prevents rendering children twice
|
||||||
const resolvedChildren = children(() => local.children)
|
const resolvedChildren = children(() => local.children);
|
||||||
const hasChildren = () => resolvedChildren.toArray().length !== 0
|
const hasChildren = () => resolvedChildren.toArray().length !== 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DatePickerPrimitive.PrevTrigger
|
<DatePickerPrimitive.PrevTrigger
|
||||||
class={cn(
|
class={cn(
|
||||||
buttonVariants({
|
buttonVariants({
|
||||||
variant: "outline"
|
variant: 'outline',
|
||||||
}),
|
}),
|
||||||
"size-7 bg-transparent p-0 opacity-50 hover:opacity-100",
|
'size-7 bg-transparent p-0 opacity-50 hover:opacity-100',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -141,23 +146,23 @@ const DatePickerPrevTrigger = (props: DatePickerPrimitive.PrevTriggerProps) => {
|
|||||||
</svg>
|
</svg>
|
||||||
</Show>
|
</Show>
|
||||||
</DatePickerPrimitive.PrevTrigger>
|
</DatePickerPrimitive.PrevTrigger>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const DatePickerNextTrigger = (props: DatePickerPrimitive.NextTriggerProps) => {
|
const DatePickerNextTrigger = (props: DatePickerPrimitive.NextTriggerProps) => {
|
||||||
const [local, others] = splitProps(props, ["class", "children"])
|
const [local, others] = splitProps(props, ['class', 'children']);
|
||||||
|
|
||||||
// prevents rendering children twice
|
// prevents rendering children twice
|
||||||
const resolvedChildren = children(() => local.children)
|
const resolvedChildren = children(() => local.children);
|
||||||
const hasChildren = () => resolvedChildren.toArray().length !== 0
|
const hasChildren = () => resolvedChildren.toArray().length !== 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DatePickerPrimitive.NextTrigger
|
<DatePickerPrimitive.NextTrigger
|
||||||
class={cn(
|
class={cn(
|
||||||
buttonVariants({
|
buttonVariants({
|
||||||
variant: "outline"
|
variant: 'outline',
|
||||||
}),
|
}),
|
||||||
"size-7 bg-transparent p-0 opacity-50 hover:opacity-100",
|
'size-7 bg-transparent p-0 opacity-50 hover:opacity-100',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -178,83 +183,96 @@ const DatePickerNextTrigger = (props: DatePickerPrimitive.NextTriggerProps) => {
|
|||||||
</svg>
|
</svg>
|
||||||
</Show>
|
</Show>
|
||||||
</DatePickerPrimitive.NextTrigger>
|
</DatePickerPrimitive.NextTrigger>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const DatePickerViewTrigger = (props: DatePickerPrimitive.ViewTriggerProps) => {
|
const DatePickerViewTrigger = (props: DatePickerPrimitive.ViewTriggerProps) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<DatePickerPrimitive.ViewTrigger
|
<DatePickerPrimitive.ViewTrigger
|
||||||
class={cn(buttonVariants({ variant: "ghost" }), "h-7", local.class)}
|
class={cn(buttonVariants({ variant: 'ghost' }), 'h-7', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const DatePickerRangeText = (props: DatePickerPrimitive.RangeTextProps) => {
|
const DatePickerRangeText = (props: DatePickerPrimitive.RangeTextProps) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<DatePickerPrimitive.RangeText class={cn("text-sm font-medium", local.class)} {...others} />
|
<DatePickerPrimitive.RangeText
|
||||||
)
|
class={cn('font-medium text-sm', local.class)}
|
||||||
}
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const DatePickerTable = (props: DatePickerPrimitive.TableProps) => {
|
const DatePickerTable = (props: DatePickerPrimitive.TableProps) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<DatePickerPrimitive.Table
|
<DatePickerPrimitive.Table
|
||||||
class={cn("w-full border-collapse space-y-1", local.class)}
|
class={cn('w-full border-collapse space-y-1', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const DatePickerTableRow = (props: DatePickerPrimitive.TableRowProps) => {
|
const DatePickerTableRow = (props: DatePickerPrimitive.TableRowProps) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <DatePickerPrimitive.TableRow class={cn("mt-2 flex w-full", local.class)} {...others} />
|
|
||||||
}
|
|
||||||
|
|
||||||
const DatePickerTableHeader = (props: DatePickerPrimitive.TableHeaderProps) => {
|
|
||||||
const [local, others] = splitProps(props, ["class"])
|
|
||||||
return (
|
return (
|
||||||
<DatePickerPrimitive.TableHeader
|
<DatePickerPrimitive.TableRow
|
||||||
class={cn("w-8 flex-1 text-[0.8rem] font-normal text-muted-foreground", local.class)}
|
class={cn('mt-2 flex w-full', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
const DatePickerTableHeader = (props: DatePickerPrimitive.TableHeaderProps) => {
|
||||||
|
const [local, others] = splitProps(props, ['class']);
|
||||||
|
return (
|
||||||
|
<DatePickerPrimitive.TableHeader
|
||||||
|
class={cn(
|
||||||
|
'w-8 flex-1 font-normal text-[0.8rem] text-muted-foreground',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const DatePickerTableCell = (props: DatePickerPrimitive.TableCellProps) => {
|
const DatePickerTableCell = (props: DatePickerPrimitive.TableCellProps) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<DatePickerPrimitive.TableCell
|
<DatePickerPrimitive.TableCell
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex-1 p-0 text-center text-sm has-[[data-range-end]]:rounded-r-md has-[[data-range-start]]:rounded-l-md has-[[data-in-range]]:bg-accent has-[[data-outside-range][data-in-range]]:bg-accent/50 has-[[data-in-range]]:first-of-type:rounded-l-md has-[[data-in-range]]:last-of-type:rounded-r-md",
|
'flex-1 p-0 text-center text-sm has-[[data-range-end]]:rounded-r-md has-[[data-range-start]]:rounded-l-md has-[[data-in-range]]:bg-accent has-[[data-outside-range][data-in-range]]:bg-accent/50 has-[[data-in-range]]:last-of-type:rounded-r-md has-[[data-in-range]]:first-of-type:rounded-l-md',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const DatePickerTableCellTrigger = (props: DatePickerPrimitive.TableCellTriggerProps) => {
|
const DatePickerTableCellTrigger = (
|
||||||
const [local, others] = splitProps(props, ["class"])
|
props: DatePickerPrimitive.TableCellTriggerProps
|
||||||
|
) => {
|
||||||
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<DatePickerPrimitive.TableCellTrigger
|
<DatePickerPrimitive.TableCellTrigger
|
||||||
class={cn(
|
class={cn(
|
||||||
buttonVariants({ variant: "ghost" }),
|
buttonVariants({ variant: 'ghost' }),
|
||||||
"size-8 w-full p-0 font-normal data-[selected]:opacity-100",
|
'size-8 w-full p-0 font-normal data-[selected]:opacity-100',
|
||||||
"data-[today]:bg-accent data-[today]:text-accent-foreground",
|
'data-[today]:bg-accent data-[today]:text-accent-foreground',
|
||||||
"[&:is([data-today][data-selected])]:bg-primary [&:is([data-today][data-selected])]:text-primary-foreground",
|
'[&:is([data-today][data-selected])]:bg-primary [&:is([data-today][data-selected])]:text-primary-foreground',
|
||||||
"data-[selected]:bg-primary data-[selected]:text-primary-foreground data-[selected]:hover:bg-primary data-[selected]:hover:text-primary-foreground",
|
'data-[selected]:bg-primary data-[selected]:text-primary-foreground data-[selected]:hover:bg-primary data-[selected]:hover:text-primary-foreground',
|
||||||
"data-[disabled]:text-muted-foreground data-[disabled]:opacity-50",
|
'data-[disabled]:text-muted-foreground data-[disabled]:opacity-50',
|
||||||
"data-[outside-range]:text-muted-foreground data-[outside-range]:opacity-50",
|
'data-[outside-range]:text-muted-foreground data-[outside-range]:opacity-50',
|
||||||
"[&:is([data-outside-range][data-in-range])]:bg-accent/50 [&:is([data-outside-range][data-in-range])]:text-muted-foreground [&:is([data-outside-range][data-in-range])]:opacity-30",
|
'[&:is([data-outside-range][data-in-range])]:bg-accent/50 [&:is([data-outside-range][data-in-range])]:text-muted-foreground [&:is([data-outside-range][data-in-range])]:opacity-30',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
DatePicker,
|
DatePicker,
|
||||||
@@ -279,5 +297,5 @@ export {
|
|||||||
DatePickerTableCellTrigger,
|
DatePickerTableCellTrigger,
|
||||||
DatePickerYearSelect,
|
DatePickerYearSelect,
|
||||||
DatePickerMonthSelect,
|
DatePickerMonthSelect,
|
||||||
DatePickerPositioner
|
DatePickerPositioner,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,58 +1,75 @@
|
|||||||
import { mergeProps, Show, splitProps, type Component, type ComponentProps } from "solid-js"
|
import {
|
||||||
|
type Component,
|
||||||
|
type ComponentProps,
|
||||||
|
Show,
|
||||||
|
mergeProps,
|
||||||
|
splitProps,
|
||||||
|
} from 'solid-js';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
type DeltaBarProps = ComponentProps<"div"> & {
|
type DeltaBarProps = ComponentProps<'div'> & {
|
||||||
value: number
|
value: number;
|
||||||
isIncreasePositive?: boolean
|
isIncreasePositive?: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
const DeltaBar: Component<DeltaBarProps> = (rawProps) => {
|
const DeltaBar: Component<DeltaBarProps> = (rawProps) => {
|
||||||
const props = mergeProps(
|
const props = mergeProps(
|
||||||
{
|
{
|
||||||
isIncreasePositive: true
|
isIncreasePositive: true,
|
||||||
},
|
},
|
||||||
rawProps
|
rawProps
|
||||||
)
|
);
|
||||||
const [local, others] = splitProps(props, ["value", "isIncreasePositive", "class"])
|
const [local, others] = splitProps(props, [
|
||||||
|
'value',
|
||||||
|
'isIncreasePositive',
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cn("relative flex h-2 w-full items-center rounded-full bg-secondary", local.class)}
|
class={cn(
|
||||||
|
'relative flex h-2 w-full items-center rounded-full bg-secondary',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
>
|
>
|
||||||
<div class="flex h-full w-1/2 justify-end">
|
<div class="flex h-full w-1/2 justify-end">
|
||||||
<Show when={local.value < 0}>
|
<Show when={local.value < 0}>
|
||||||
<div
|
<div
|
||||||
class={cn(
|
class={cn(
|
||||||
"rounded-l-full",
|
'rounded-l-full',
|
||||||
(local.value > 0 && local.isIncreasePositive) ||
|
(local.value > 0 && local.isIncreasePositive) ||
|
||||||
(local.value < 0 && !local.isIncreasePositive)
|
(local.value < 0 && !local.isIncreasePositive)
|
||||||
? "bg-success-foreground"
|
? 'bg-success-foreground'
|
||||||
: "bg-error-foreground"
|
: 'bg-error-foreground'
|
||||||
)}
|
)}
|
||||||
style={{ width: `${Math.abs(local.value)}%` }}
|
style={{ width: `${Math.abs(local.value)}%` }}
|
||||||
/>
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
<div class={cn("z-10 h-4 w-1 rounded-full bg-primary ring-2 ring-background")} />
|
<div
|
||||||
|
class={cn(
|
||||||
|
'z-10 h-4 w-1 rounded-full bg-primary ring-2 ring-background'
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<div class="flex h-full w-1/2 justify-start">
|
<div class="flex h-full w-1/2 justify-start">
|
||||||
<Show when={local.value > 0}>
|
<Show when={local.value > 0}>
|
||||||
<div
|
<div
|
||||||
class={cn(
|
class={cn(
|
||||||
"rounded-r-full",
|
'rounded-r-full',
|
||||||
(local.value > 0 && local.isIncreasePositive) ||
|
(local.value > 0 && local.isIncreasePositive) ||
|
||||||
(local.value < 0 && !local.isIncreasePositive)
|
(local.value < 0 && !local.isIncreasePositive)
|
||||||
? "bg-success-foreground"
|
? 'bg-success-foreground'
|
||||||
: "bg-error-foreground"
|
: 'bg-error-foreground'
|
||||||
)}
|
)}
|
||||||
style={{ width: `${Math.abs(local.value)}%` }}
|
style={{ width: `${Math.abs(local.value)}%` }}
|
||||||
/>
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export type { DeltaBarProps }
|
export type { DeltaBarProps };
|
||||||
export { DeltaBar }
|
export { DeltaBar };
|
||||||
|
|||||||
@@ -1,65 +1,68 @@
|
|||||||
import type { Component, ComponentProps, JSX, ValidComponent } from "solid-js"
|
import type { Component, ComponentProps, JSX, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import * as DialogPrimitive from "@kobalte/core/dialog"
|
import * as DialogPrimitive from '@kobalte/core/dialog';
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const Dialog = DialogPrimitive.Root
|
const Dialog = DialogPrimitive.Root;
|
||||||
const DialogTrigger = DialogPrimitive.Trigger
|
const DialogTrigger = DialogPrimitive.Trigger;
|
||||||
|
|
||||||
const DialogPortal: Component<DialogPrimitive.DialogPortalProps> = (props) => {
|
const DialogPortal: Component<DialogPrimitive.DialogPortalProps> = (props) => {
|
||||||
const [, rest] = splitProps(props, ["children"])
|
const [, rest] = splitProps(props, ['children']);
|
||||||
return (
|
return (
|
||||||
<DialogPrimitive.Portal {...rest}>
|
<DialogPrimitive.Portal {...rest}>
|
||||||
<div class="fixed inset-0 z-50 flex items-start justify-center sm:items-center">
|
<div class="fixed inset-0 z-50 flex items-start justify-center sm:items-center">
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
</DialogPrimitive.Portal>
|
</DialogPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DialogOverlayProps<T extends ValidComponent = "div"> =
|
type DialogOverlayProps<T extends ValidComponent = 'div'> =
|
||||||
DialogPrimitive.DialogOverlayProps<T> & { class?: string | undefined }
|
DialogPrimitive.DialogOverlayProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const DialogOverlay = <T extends ValidComponent = "div">(
|
const DialogOverlay = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, DialogOverlayProps<T>>
|
props: PolymorphicProps<T, DialogOverlayProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DialogOverlayProps, ["class"])
|
const [, rest] = splitProps(props as DialogOverlayProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<DialogPrimitive.Overlay
|
<DialogPrimitive.Overlay
|
||||||
class={cn(
|
class={cn(
|
||||||
"fixed inset-0 z-50 bg-background/80 data-[expanded]:animate-in data-[closed]:animate-out data-[closed]:fade-out-0 data-[expanded]:fade-in-0",
|
'data-[closed]:fade-out-0 data-[expanded]:fade-in-0 fixed inset-0 z-50 bg-background/80 data-[closed]:animate-out data-[expanded]:animate-in',
|
||||||
props.class
|
props.class
|
||||||
)}
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DialogContentProps<T extends ValidComponent = "div"> =
|
type DialogContentProps<T extends ValidComponent = 'div'> =
|
||||||
DialogPrimitive.DialogContentProps<T> & {
|
DialogPrimitive.DialogContentProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const DialogContent = <T extends ValidComponent = "div">(
|
const DialogContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, DialogContentProps<T>>
|
props: PolymorphicProps<T, DialogContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DialogContentProps, ["class", "children"])
|
const [, rest] = splitProps(props as DialogContentProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<DialogPortal>
|
<DialogPortal>
|
||||||
<DialogOverlay />
|
<DialogOverlay />
|
||||||
<DialogPrimitive.Content
|
<DialogPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
"fixed left-1/2 top-1/2 z-50 grid max-h-screen w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 overflow-y-auto border bg-background p-6 shadow-lg duration-200 data-[expanded]:animate-in data-[closed]:animate-out data-[closed]:fade-out-0 data-[expanded]:fade-in-0 data-[closed]:zoom-out-95 data-[expanded]:zoom-in-95 data-[closed]:slide-out-to-left-1/2 data-[closed]:slide-out-to-top-[48%] data-[expanded]:slide-in-from-left-1/2 data-[expanded]:slide-in-from-top-[48%] sm:rounded-lg",
|
'-translate-x-1/2 -translate-y-1/2 data-[closed]:fade-out-0 data-[expanded]:fade-in-0 data-[closed]:zoom-out-95 data-[expanded]:zoom-in-95 data-[closed]:slide-out-to-left-1/2 data-[closed]:slide-out-to-top-[48%] data-[expanded]:slide-in-from-left-1/2 data-[expanded]:slide-in-from-top-[48%] fixed top-1/2 left-1/2 z-50 grid max-h-screen w-full max-w-lg gap-4 overflow-y-auto border bg-background p-6 shadow-lg duration-200 data-[closed]:animate-out data-[expanded]:animate-in sm:rounded-lg',
|
||||||
props.class
|
props.class
|
||||||
)}
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
<DialogPrimitive.CloseButton class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[expanded]:bg-accent data-[expanded]:text-muted-foreground">
|
<DialogPrimitive.CloseButton class="absolute top-4 right-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[expanded]:bg-accent data-[expanded]:text-muted-foreground">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
@@ -77,58 +80,71 @@ const DialogContent = <T extends ValidComponent = "div">(
|
|||||||
</DialogPrimitive.CloseButton>
|
</DialogPrimitive.CloseButton>
|
||||||
</DialogPrimitive.Content>
|
</DialogPrimitive.Content>
|
||||||
</DialogPortal>
|
</DialogPortal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const DialogHeader: Component<ComponentProps<"div">> = (props) => {
|
const DialogHeader: Component<ComponentProps<'div'>> = (props) => {
|
||||||
const [, rest] = splitProps(props, ["class"])
|
const [, rest] = splitProps(props, ['class']);
|
||||||
return (
|
|
||||||
<div class={cn("flex flex-col space-y-1.5 text-center sm:text-left", props.class)} {...rest} />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const DialogFooter: Component<ComponentProps<"div">> = (props) => {
|
|
||||||
const [, rest] = splitProps(props, ["class"])
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", props.class)}
|
class={cn(
|
||||||
|
'flex flex-col space-y-1.5 text-center sm:text-left',
|
||||||
|
props.class
|
||||||
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DialogTitleProps<T extends ValidComponent = "h2"> = DialogPrimitive.DialogTitleProps<T> & {
|
const DialogFooter: Component<ComponentProps<'div'>> = (props) => {
|
||||||
class?: string | undefined
|
const [, rest] = splitProps(props, ['class']);
|
||||||
}
|
return (
|
||||||
|
<div
|
||||||
|
class={cn(
|
||||||
|
'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
|
||||||
|
props.class
|
||||||
|
)}
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const DialogTitle = <T extends ValidComponent = "h2">(
|
type DialogTitleProps<T extends ValidComponent = 'h2'> =
|
||||||
|
DialogPrimitive.DialogTitleProps<T> & {
|
||||||
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DialogTitle = <T extends ValidComponent = 'h2'>(
|
||||||
props: PolymorphicProps<T, DialogTitleProps<T>>
|
props: PolymorphicProps<T, DialogTitleProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DialogTitleProps, ["class"])
|
const [, rest] = splitProps(props as DialogTitleProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<DialogPrimitive.Title
|
<DialogPrimitive.Title
|
||||||
class={cn("text-lg font-semibold leading-none tracking-tight", props.class)}
|
class={cn(
|
||||||
|
'font-semibold text-lg leading-none tracking-tight',
|
||||||
|
props.class
|
||||||
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DialogDescriptionProps<T extends ValidComponent = "p"> =
|
type DialogDescriptionProps<T extends ValidComponent = 'p'> =
|
||||||
DialogPrimitive.DialogDescriptionProps<T> & {
|
DialogPrimitive.DialogDescriptionProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const DialogDescription = <T extends ValidComponent = "p">(
|
const DialogDescription = <T extends ValidComponent = 'p'>(
|
||||||
props: PolymorphicProps<T, DialogDescriptionProps<T>>
|
props: PolymorphicProps<T, DialogDescriptionProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DialogDescriptionProps, ["class"])
|
const [, rest] = splitProps(props as DialogDescriptionProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<DialogPrimitive.Description
|
<DialogPrimitive.Description
|
||||||
class={cn("text-sm text-muted-foreground", props.class)}
|
class={cn('text-muted-foreground text-sm', props.class)}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Dialog,
|
Dialog,
|
||||||
@@ -137,5 +153,5 @@ export {
|
|||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogFooter,
|
DialogFooter,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogDescription
|
DialogDescription,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,61 +1,66 @@
|
|||||||
import type { Component, ComponentProps, JSX, ValidComponent } from "solid-js"
|
import type { Component, ComponentProps, JSX, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ContentProps,
|
ContentProps,
|
||||||
DescriptionProps,
|
DescriptionProps,
|
||||||
DynamicProps,
|
DynamicProps,
|
||||||
LabelProps,
|
LabelProps,
|
||||||
OverlayProps
|
OverlayProps,
|
||||||
} from "@corvu/drawer"
|
} from '@corvu/drawer';
|
||||||
import DrawerPrimitive from "@corvu/drawer"
|
import DrawerPrimitive from '@corvu/drawer';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const Drawer = DrawerPrimitive
|
const Drawer = DrawerPrimitive;
|
||||||
|
|
||||||
const DrawerTrigger = DrawerPrimitive.Trigger
|
const DrawerTrigger = DrawerPrimitive.Trigger;
|
||||||
|
|
||||||
const DrawerPortal = DrawerPrimitive.Portal
|
const DrawerPortal = DrawerPrimitive.Portal;
|
||||||
|
|
||||||
const DrawerClose = DrawerPrimitive.Close
|
const DrawerClose = DrawerPrimitive.Close;
|
||||||
|
|
||||||
type DrawerOverlayProps<T extends ValidComponent = "div"> = OverlayProps<T> & { class?: string }
|
type DrawerOverlayProps<T extends ValidComponent = 'div'> = OverlayProps<T> & {
|
||||||
|
class?: string;
|
||||||
|
};
|
||||||
|
|
||||||
const DrawerOverlay = <T extends ValidComponent = "div">(
|
const DrawerOverlay = <T extends ValidComponent = 'div'>(
|
||||||
props: DynamicProps<T, DrawerOverlayProps<T>>
|
props: DynamicProps<T, DrawerOverlayProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DrawerOverlayProps, ["class"])
|
const [, rest] = splitProps(props as DrawerOverlayProps, ['class']);
|
||||||
const drawerContext = DrawerPrimitive.useContext()
|
const drawerContext = DrawerPrimitive.useContext();
|
||||||
return (
|
return (
|
||||||
<DrawerPrimitive.Overlay
|
<DrawerPrimitive.Overlay
|
||||||
class={cn(
|
class={cn(
|
||||||
"fixed inset-0 z-50 data-[transitioning]:transition-colors data-[transitioning]:duration-300",
|
'fixed inset-0 z-50 data-[transitioning]:transition-colors data-[transitioning]:duration-300',
|
||||||
props.class
|
props.class
|
||||||
)}
|
)}
|
||||||
style={{
|
style={{
|
||||||
"background-color": `rgb(0 0 0 / ${0.8 * drawerContext.openPercentage()})`
|
'background-color': `rgb(0 0 0 / ${0.8 * drawerContext.openPercentage()})`,
|
||||||
}}
|
}}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DrawerContentProps<T extends ValidComponent = "div"> = ContentProps<T> & {
|
type DrawerContentProps<T extends ValidComponent = 'div'> = ContentProps<T> & {
|
||||||
class?: string
|
class?: string;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const DrawerContent = <T extends ValidComponent = "div">(
|
const DrawerContent = <T extends ValidComponent = 'div'>(
|
||||||
props: DynamicProps<T, DrawerContentProps<T>>
|
props: DynamicProps<T, DrawerContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DrawerContentProps, ["class", "children"])
|
const [, rest] = splitProps(props as DrawerContentProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<DrawerPortal>
|
<DrawerPortal>
|
||||||
<DrawerOverlay />
|
<DrawerOverlay />
|
||||||
<DrawerPrimitive.Content
|
<DrawerPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background after:absolute after:inset-x-0 after:top-full after:h-1/2 after:bg-inherit data-[transitioning]:transition-transform data-[transitioning]:duration-300 md:select-none",
|
'fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background after:absolute after:inset-x-0 after:top-full after:h-1/2 after:bg-inherit data-[transitioning]:transition-transform data-[transitioning]:duration-300 md:select-none',
|
||||||
props.class
|
props.class
|
||||||
)}
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
@@ -64,48 +69,61 @@ const DrawerContent = <T extends ValidComponent = "div">(
|
|||||||
{props.children}
|
{props.children}
|
||||||
</DrawerPrimitive.Content>
|
</DrawerPrimitive.Content>
|
||||||
</DrawerPortal>
|
</DrawerPortal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const DrawerHeader: Component<ComponentProps<"div">> = (props) => {
|
const DrawerHeader: Component<ComponentProps<'div'>> = (props) => {
|
||||||
const [, rest] = splitProps(props, ["class"])
|
const [, rest] = splitProps(props, ['class']);
|
||||||
return <div class={cn("grid gap-1.5 p-4 text-center sm:text-left", props.class)} {...rest} />
|
return (
|
||||||
}
|
<div
|
||||||
|
class={cn('grid gap-1.5 p-4 text-center sm:text-left', props.class)}
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const DrawerFooter: Component<ComponentProps<"div">> = (props) => {
|
const DrawerFooter: Component<ComponentProps<'div'>> = (props) => {
|
||||||
const [, rest] = splitProps(props, ["class"])
|
const [, rest] = splitProps(props, ['class']);
|
||||||
return <div class={cn("t-auto flex flex-col gap-2 p-4", props.class)} {...rest} />
|
return (
|
||||||
}
|
<div class={cn('t-auto flex flex-col gap-2 p-4', props.class)} {...rest} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
type DrawerTitleProps<T extends ValidComponent = "div"> = LabelProps<T> & { class?: string }
|
type DrawerTitleProps<T extends ValidComponent = 'div'> = LabelProps<T> & {
|
||||||
|
class?: string;
|
||||||
|
};
|
||||||
|
|
||||||
const DrawerTitle = <T extends ValidComponent = "div">(
|
const DrawerTitle = <T extends ValidComponent = 'div'>(
|
||||||
props: DynamicProps<T, DrawerTitleProps<T>>
|
props: DynamicProps<T, DrawerTitleProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DrawerTitleProps, ["class"])
|
const [, rest] = splitProps(props as DrawerTitleProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<DrawerPrimitive.Label
|
<DrawerPrimitive.Label
|
||||||
class={cn("text-lg font-semibold leading-none tracking-tight", props.class)}
|
class={cn(
|
||||||
|
'font-semibold text-lg leading-none tracking-tight',
|
||||||
|
props.class
|
||||||
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DrawerDescriptionProps<T extends ValidComponent = "div"> = DescriptionProps<T> & {
|
type DrawerDescriptionProps<T extends ValidComponent = 'div'> =
|
||||||
class?: string
|
DescriptionProps<T> & {
|
||||||
}
|
class?: string;
|
||||||
|
};
|
||||||
|
|
||||||
const DrawerDescription = <T extends ValidComponent = "div">(
|
const DrawerDescription = <T extends ValidComponent = 'div'>(
|
||||||
props: DynamicProps<T, DrawerDescriptionProps<T>>
|
props: DynamicProps<T, DrawerDescriptionProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DrawerDescriptionProps, ["class"])
|
const [, rest] = splitProps(props as DrawerDescriptionProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<DrawerPrimitive.Description
|
<DrawerPrimitive.Description
|
||||||
class={cn("text-sm text-muted-foreground", props.class)}
|
class={cn('text-muted-foreground text-sm', props.class)}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Drawer,
|
Drawer,
|
||||||
@@ -117,5 +135,5 @@ export {
|
|||||||
DrawerHeader,
|
DrawerHeader,
|
||||||
DrawerFooter,
|
DrawerFooter,
|
||||||
DrawerTitle,
|
DrawerTitle,
|
||||||
DrawerDescription
|
DrawerDescription,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,109 +1,125 @@
|
|||||||
import type { Component, ComponentProps, JSX, ValidComponent } from "solid-js"
|
import type { Component, ComponentProps, JSX, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import * as DropdownMenuPrimitive from "@kobalte/core/dropdown-menu"
|
import * as DropdownMenuPrimitive from '@kobalte/core/dropdown-menu';
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
|
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
||||||
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
|
const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
|
||||||
const DropdownMenuSub = DropdownMenuPrimitive.Sub
|
const DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
||||||
const DropdownMenuGroup = DropdownMenuPrimitive.Group
|
const DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
||||||
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
|
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
||||||
|
|
||||||
const DropdownMenu: Component<DropdownMenuPrimitive.DropdownMenuRootProps> = (props) => {
|
const DropdownMenu: Component<DropdownMenuPrimitive.DropdownMenuRootProps> = (
|
||||||
return <DropdownMenuPrimitive.Root gutter={4} {...props} />
|
props
|
||||||
}
|
) => {
|
||||||
|
return <DropdownMenuPrimitive.Root gutter={4} {...props} />;
|
||||||
|
};
|
||||||
|
|
||||||
type DropdownMenuContentProps<T extends ValidComponent = "div"> =
|
type DropdownMenuContentProps<T extends ValidComponent = 'div'> =
|
||||||
DropdownMenuPrimitive.DropdownMenuContentProps<T> & {
|
DropdownMenuPrimitive.DropdownMenuContentProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const DropdownMenuContent = <T extends ValidComponent = "div">(
|
const DropdownMenuContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, DropdownMenuContentProps<T>>
|
props: PolymorphicProps<T, DropdownMenuContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DropdownMenuContentProps, ["class"])
|
const [, rest] = splitProps(props as DropdownMenuContentProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<DropdownMenuPrimitive.Portal>
|
<DropdownMenuPrimitive.Portal>
|
||||||
<DropdownMenuPrimitive.Content
|
<DropdownMenuPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
"z-50 min-w-32 origin-[var(--kb-menu-content-transform-origin)] animate-content-hide overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[expanded]:animate-content-show",
|
'z-50 min-w-32 origin-[var(--kb-menu-content-transform-origin)] animate-content-hide overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[expanded]:animate-content-show',
|
||||||
props.class
|
props.class
|
||||||
)}
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
</DropdownMenuPrimitive.Portal>
|
</DropdownMenuPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DropdownMenuItemProps<T extends ValidComponent = "div"> =
|
type DropdownMenuItemProps<T extends ValidComponent = 'div'> =
|
||||||
DropdownMenuPrimitive.DropdownMenuItemProps<T> & {
|
DropdownMenuPrimitive.DropdownMenuItemProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const DropdownMenuItem = <T extends ValidComponent = "div">(
|
const DropdownMenuItem = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, DropdownMenuItemProps<T>>
|
props: PolymorphicProps<T, DropdownMenuItemProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DropdownMenuItemProps, ["class"])
|
const [, rest] = splitProps(props as DropdownMenuItemProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<DropdownMenuPrimitive.Item
|
<DropdownMenuPrimitive.Item
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
'relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
props.class
|
props.class
|
||||||
)}
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const DropdownMenuShortcut: Component<ComponentProps<"span">> = (props) => {
|
const DropdownMenuShortcut: Component<ComponentProps<'span'>> = (props) => {
|
||||||
const [, rest] = splitProps(props, ["class"])
|
const [, rest] = splitProps(props, ['class']);
|
||||||
return <span class={cn("ml-auto text-xs tracking-widest opacity-60", props.class)} {...rest} />
|
return (
|
||||||
}
|
<span
|
||||||
|
class={cn('ml-auto text-xs tracking-widest opacity-60', props.class)}
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const DropdownMenuLabel: Component<ComponentProps<"div"> & { inset?: boolean }> = (props) => {
|
const DropdownMenuLabel: Component<
|
||||||
const [, rest] = splitProps(props, ["class", "inset"])
|
ComponentProps<'div'> & { inset?: boolean }
|
||||||
|
> = (props) => {
|
||||||
|
const [, rest] = splitProps(props, ['class', 'inset']);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cn("px-2 py-1.5 text-sm font-semibold", props.inset && "pl-8", props.class)}
|
class={cn(
|
||||||
|
'px-2 py-1.5 font-semibold text-sm',
|
||||||
|
props.inset && 'pl-8',
|
||||||
|
props.class
|
||||||
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DropdownMenuSeparatorProps<T extends ValidComponent = "hr"> =
|
type DropdownMenuSeparatorProps<T extends ValidComponent = 'hr'> =
|
||||||
DropdownMenuPrimitive.DropdownMenuSeparatorProps<T> & {
|
DropdownMenuPrimitive.DropdownMenuSeparatorProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const DropdownMenuSeparator = <T extends ValidComponent = "hr">(
|
const DropdownMenuSeparator = <T extends ValidComponent = 'hr'>(
|
||||||
props: PolymorphicProps<T, DropdownMenuSeparatorProps<T>>
|
props: PolymorphicProps<T, DropdownMenuSeparatorProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DropdownMenuSeparatorProps, ["class"])
|
const [, rest] = splitProps(props as DropdownMenuSeparatorProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<DropdownMenuPrimitive.Separator
|
<DropdownMenuPrimitive.Separator
|
||||||
class={cn("-mx-1 my-1 h-px bg-muted", props.class)}
|
class={cn('-mx-1 my-1 h-px bg-muted', props.class)}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DropdownMenuSubTriggerProps<T extends ValidComponent = "div"> =
|
type DropdownMenuSubTriggerProps<T extends ValidComponent = 'div'> =
|
||||||
DropdownMenuPrimitive.DropdownMenuSubTriggerProps<T> & {
|
DropdownMenuPrimitive.DropdownMenuSubTriggerProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const DropdownMenuSubTrigger = <T extends ValidComponent = "div">(
|
const DropdownMenuSubTrigger = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, DropdownMenuSubTriggerProps<T>>
|
props: PolymorphicProps<T, DropdownMenuSubTriggerProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DropdownMenuSubTriggerProps, ["class", "children"])
|
const [, rest] = splitProps(props as DropdownMenuSubTriggerProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<DropdownMenuPrimitive.SubTrigger
|
<DropdownMenuPrimitive.SubTrigger
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
|
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent',
|
||||||
props.class
|
props.class
|
||||||
)}
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
@@ -122,43 +138,46 @@ const DropdownMenuSubTrigger = <T extends ValidComponent = "div">(
|
|||||||
<path d="M9 6l6 6l-6 6" />
|
<path d="M9 6l6 6l-6 6" />
|
||||||
</svg>
|
</svg>
|
||||||
</DropdownMenuPrimitive.SubTrigger>
|
</DropdownMenuPrimitive.SubTrigger>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DropdownMenuSubContentProps<T extends ValidComponent = "div"> =
|
type DropdownMenuSubContentProps<T extends ValidComponent = 'div'> =
|
||||||
DropdownMenuPrimitive.DropdownMenuSubContentProps<T> & {
|
DropdownMenuPrimitive.DropdownMenuSubContentProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const DropdownMenuSubContent = <T extends ValidComponent = "div">(
|
const DropdownMenuSubContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, DropdownMenuSubContentProps<T>>
|
props: PolymorphicProps<T, DropdownMenuSubContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DropdownMenuSubContentProps, ["class"])
|
const [, rest] = splitProps(props as DropdownMenuSubContentProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<DropdownMenuPrimitive.SubContent
|
<DropdownMenuPrimitive.SubContent
|
||||||
class={cn(
|
class={cn(
|
||||||
"z-50 min-w-32 origin-[var(--kb-menu-content-transform-origin)] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in",
|
'z-50 min-w-32 origin-[var(--kb-menu-content-transform-origin)] animate-in overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md',
|
||||||
props.class
|
props.class
|
||||||
)}
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DropdownMenuCheckboxItemProps<T extends ValidComponent = "div"> =
|
type DropdownMenuCheckboxItemProps<T extends ValidComponent = 'div'> =
|
||||||
DropdownMenuPrimitive.DropdownMenuCheckboxItemProps<T> & {
|
DropdownMenuPrimitive.DropdownMenuCheckboxItemProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const DropdownMenuCheckboxItem = <T extends ValidComponent = "div">(
|
const DropdownMenuCheckboxItem = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, DropdownMenuCheckboxItemProps<T>>
|
props: PolymorphicProps<T, DropdownMenuCheckboxItemProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DropdownMenuCheckboxItemProps, ["class", "children"])
|
const [, rest] = splitProps(props as DropdownMenuCheckboxItemProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<DropdownMenuPrimitive.CheckboxItem
|
<DropdownMenuPrimitive.CheckboxItem
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
props.class
|
props.class
|
||||||
)}
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
@@ -181,40 +200,43 @@ const DropdownMenuCheckboxItem = <T extends ValidComponent = "div">(
|
|||||||
</span>
|
</span>
|
||||||
{props.children}
|
{props.children}
|
||||||
</DropdownMenuPrimitive.CheckboxItem>
|
</DropdownMenuPrimitive.CheckboxItem>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DropdownMenuGroupLabelProps<T extends ValidComponent = "span"> =
|
type DropdownMenuGroupLabelProps<T extends ValidComponent = 'span'> =
|
||||||
DropdownMenuPrimitive.DropdownMenuGroupLabelProps<T> & {
|
DropdownMenuPrimitive.DropdownMenuGroupLabelProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const DropdownMenuGroupLabel = <T extends ValidComponent = "span">(
|
const DropdownMenuGroupLabel = <T extends ValidComponent = 'span'>(
|
||||||
props: PolymorphicProps<T, DropdownMenuGroupLabelProps<T>>
|
props: PolymorphicProps<T, DropdownMenuGroupLabelProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DropdownMenuGroupLabelProps, ["class"])
|
const [, rest] = splitProps(props as DropdownMenuGroupLabelProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<DropdownMenuPrimitive.GroupLabel
|
<DropdownMenuPrimitive.GroupLabel
|
||||||
class={cn("px-2 py-1.5 text-sm font-semibold", props.class)}
|
class={cn('px-2 py-1.5 font-semibold text-sm', props.class)}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DropdownMenuRadioItemProps<T extends ValidComponent = "div"> =
|
type DropdownMenuRadioItemProps<T extends ValidComponent = 'div'> =
|
||||||
DropdownMenuPrimitive.DropdownMenuRadioItemProps<T> & {
|
DropdownMenuPrimitive.DropdownMenuRadioItemProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const DropdownMenuRadioItem = <T extends ValidComponent = "div">(
|
const DropdownMenuRadioItem = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, DropdownMenuRadioItemProps<T>>
|
props: PolymorphicProps<T, DropdownMenuRadioItemProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as DropdownMenuRadioItemProps, ["class", "children"])
|
const [, rest] = splitProps(props as DropdownMenuRadioItemProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<DropdownMenuPrimitive.RadioItem
|
<DropdownMenuPrimitive.RadioItem
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
props.class
|
props.class
|
||||||
)}
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
@@ -237,8 +259,8 @@ const DropdownMenuRadioItem = <T extends ValidComponent = "div">(
|
|||||||
</span>
|
</span>
|
||||||
{props.children}
|
{props.children}
|
||||||
</DropdownMenuPrimitive.RadioItem>
|
</DropdownMenuPrimitive.RadioItem>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
@@ -256,5 +278,5 @@ export {
|
|||||||
DropdownMenuGroup,
|
DropdownMenuGroup,
|
||||||
DropdownMenuGroupLabel,
|
DropdownMenuGroupLabel,
|
||||||
DropdownMenuRadioGroup,
|
DropdownMenuRadioGroup,
|
||||||
DropdownMenuRadioItem
|
DropdownMenuRadioItem,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,38 +1,44 @@
|
|||||||
import type { Component, ComponentProps } from "solid-js"
|
import type { Component, ComponentProps } from 'solid-js';
|
||||||
import { mergeProps, splitProps } from "solid-js"
|
import { mergeProps, splitProps } from 'solid-js';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
type JustifyContent = "start" | "end" | "center" | "between" | "around" | "evenly"
|
type JustifyContent =
|
||||||
type AlignItems = "start" | "end" | "center" | "baseline" | "stretch"
|
| 'start'
|
||||||
type FlexDirection = "row" | "col" | "row-reverse" | "col-reverse"
|
| 'end'
|
||||||
|
| 'center'
|
||||||
|
| 'between'
|
||||||
|
| 'around'
|
||||||
|
| 'evenly';
|
||||||
|
type AlignItems = 'start' | 'end' | 'center' | 'baseline' | 'stretch';
|
||||||
|
type FlexDirection = 'row' | 'col' | 'row-reverse' | 'col-reverse';
|
||||||
|
|
||||||
type FlexProps = ComponentProps<"div"> & {
|
type FlexProps = ComponentProps<'div'> & {
|
||||||
flexDirection?: FlexDirection
|
flexDirection?: FlexDirection;
|
||||||
justifyContent?: JustifyContent
|
justifyContent?: JustifyContent;
|
||||||
alignItems?: AlignItems
|
alignItems?: AlignItems;
|
||||||
}
|
};
|
||||||
|
|
||||||
const Flex: Component<FlexProps> = (rawProps) => {
|
const Flex: Component<FlexProps> = (rawProps) => {
|
||||||
const props = mergeProps(
|
const props = mergeProps(
|
||||||
{
|
{
|
||||||
flexDirection: "row",
|
flexDirection: 'row',
|
||||||
justifyContent: "between",
|
justifyContent: 'between',
|
||||||
alignItems: "center"
|
alignItems: 'center',
|
||||||
} satisfies FlexProps,
|
} satisfies FlexProps,
|
||||||
rawProps
|
rawProps
|
||||||
)
|
);
|
||||||
const [local, others] = splitProps(props, [
|
const [local, others] = splitProps(props, [
|
||||||
"flexDirection",
|
'flexDirection',
|
||||||
"justifyContent",
|
'justifyContent',
|
||||||
"alignItems",
|
'alignItems',
|
||||||
"class"
|
'class',
|
||||||
])
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex w-full",
|
'flex w-full',
|
||||||
flexDirectionClassNames[local.flexDirection],
|
flexDirectionClassNames[local.flexDirection],
|
||||||
justifyContentClassNames[local.justifyContent],
|
justifyContentClassNames[local.justifyContent],
|
||||||
alignItemsClassNames[local.alignItems],
|
alignItemsClassNames[local.alignItems],
|
||||||
@@ -40,31 +46,31 @@ const Flex: Component<FlexProps> = (rawProps) => {
|
|||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Flex }
|
export { Flex };
|
||||||
|
|
||||||
const justifyContentClassNames: { [key in JustifyContent]: string } = {
|
const justifyContentClassNames: { [key in JustifyContent]: string } = {
|
||||||
start: "justify-start",
|
start: 'justify-start',
|
||||||
end: "justify-end",
|
end: 'justify-end',
|
||||||
center: "justify-center",
|
center: 'justify-center',
|
||||||
between: "justify-between",
|
between: 'justify-between',
|
||||||
around: "justify-around",
|
around: 'justify-around',
|
||||||
evenly: "justify-evenly"
|
evenly: 'justify-evenly',
|
||||||
}
|
};
|
||||||
|
|
||||||
const alignItemsClassNames: { [key in AlignItems]: string } = {
|
const alignItemsClassNames: { [key in AlignItems]: string } = {
|
||||||
start: "items-start",
|
start: 'items-start',
|
||||||
end: "items-end",
|
end: 'items-end',
|
||||||
center: "items-center",
|
center: 'items-center',
|
||||||
baseline: "items-baseline",
|
baseline: 'items-baseline',
|
||||||
stretch: "items-stretch"
|
stretch: 'items-stretch',
|
||||||
}
|
};
|
||||||
|
|
||||||
const flexDirectionClassNames: { [key in FlexDirection]: string } = {
|
const flexDirectionClassNames: { [key in FlexDirection]: string } = {
|
||||||
row: "flex-row",
|
row: 'flex-row',
|
||||||
col: "flex-col",
|
col: 'flex-col',
|
||||||
"row-reverse": "flex-row-reverse",
|
'row-reverse': 'flex-row-reverse',
|
||||||
"col-reverse": "flex-col-reverse"
|
'col-reverse': 'flex-col-reverse',
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,26 +1,32 @@
|
|||||||
import type { Component, ComponentProps } from "solid-js"
|
import type { Component, ComponentProps } from 'solid-js';
|
||||||
import { mergeProps, splitProps } from "solid-js"
|
import { mergeProps, splitProps } from 'solid-js';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
type Cols = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
|
type Cols = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
||||||
type Span = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13
|
type Span = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13;
|
||||||
|
|
||||||
type GridProps = ComponentProps<"div"> & {
|
type GridProps = ComponentProps<'div'> & {
|
||||||
cols?: Cols
|
cols?: Cols;
|
||||||
colsSm?: Cols
|
colsSm?: Cols;
|
||||||
colsMd?: Cols
|
colsMd?: Cols;
|
||||||
colsLg?: Cols
|
colsLg?: Cols;
|
||||||
}
|
};
|
||||||
|
|
||||||
const Grid: Component<GridProps> = (rawProps) => {
|
const Grid: Component<GridProps> = (rawProps) => {
|
||||||
const props = mergeProps({ cols: 1 } satisfies GridProps, rawProps)
|
const props = mergeProps({ cols: 1 } satisfies GridProps, rawProps);
|
||||||
const [local, others] = splitProps(props, ["cols", "colsSm", "colsMd", "colsLg", "class"])
|
const [local, others] = splitProps(props, [
|
||||||
|
'cols',
|
||||||
|
'colsSm',
|
||||||
|
'colsMd',
|
||||||
|
'colsLg',
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cn(
|
class={cn(
|
||||||
"grid",
|
'grid',
|
||||||
gridCols[local.cols],
|
gridCols[local.cols],
|
||||||
local.colsSm && gridColsSm[local.colsSm],
|
local.colsSm && gridColsSm[local.colsSm],
|
||||||
local.colsMd && gridColsMd[local.colsMd],
|
local.colsMd && gridColsMd[local.colsMd],
|
||||||
@@ -29,19 +35,25 @@ const Grid: Component<GridProps> = (rawProps) => {
|
|||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ColProps = ComponentProps<"div"> & {
|
type ColProps = ComponentProps<'div'> & {
|
||||||
span?: Span
|
span?: Span;
|
||||||
spanSm?: Span
|
spanSm?: Span;
|
||||||
spanMd?: Span
|
spanMd?: Span;
|
||||||
spanLg?: Span
|
spanLg?: Span;
|
||||||
}
|
};
|
||||||
|
|
||||||
const Col: Component<ColProps> = (rawProps) => {
|
const Col: Component<ColProps> = (rawProps) => {
|
||||||
const props = mergeProps({ span: 1 as Span }, rawProps)
|
const props = mergeProps({ span: 1 as Span }, rawProps);
|
||||||
const [local, others] = splitProps(props, ["span", "spanSm", "spanMd", "spanLg", "class"])
|
const [local, others] = splitProps(props, [
|
||||||
|
'span',
|
||||||
|
'spanSm',
|
||||||
|
'spanMd',
|
||||||
|
'spanLg',
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -54,135 +66,135 @@ const Col: Component<ColProps> = (rawProps) => {
|
|||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Grid, Col }
|
export { Grid, Col };
|
||||||
|
|
||||||
const gridCols: { [key in Cols]: string } = {
|
const gridCols: { [key in Cols]: string } = {
|
||||||
0: "grid-cols-none",
|
0: 'grid-cols-none',
|
||||||
1: "grid-cols-1",
|
1: 'grid-cols-1',
|
||||||
2: "grid-cols-2",
|
2: 'grid-cols-2',
|
||||||
3: "grid-cols-3",
|
3: 'grid-cols-3',
|
||||||
4: "grid-cols-4",
|
4: 'grid-cols-4',
|
||||||
5: "grid-cols-5",
|
5: 'grid-cols-5',
|
||||||
6: "grid-cols-6",
|
6: 'grid-cols-6',
|
||||||
7: "grid-cols-7",
|
7: 'grid-cols-7',
|
||||||
8: "grid-cols-8",
|
8: 'grid-cols-8',
|
||||||
9: "grid-cols-9",
|
9: 'grid-cols-9',
|
||||||
10: "grid-cols-10",
|
10: 'grid-cols-10',
|
||||||
11: "grid-cols-11",
|
11: 'grid-cols-11',
|
||||||
12: "grid-cols-12"
|
12: 'grid-cols-12',
|
||||||
}
|
};
|
||||||
|
|
||||||
const gridColsSm: { [key in Cols]: string } = {
|
const gridColsSm: { [key in Cols]: string } = {
|
||||||
0: "sm:grid-cols-none",
|
0: 'sm:grid-cols-none',
|
||||||
1: "sm:grid-cols-1",
|
1: 'sm:grid-cols-1',
|
||||||
2: "sm:grid-cols-2",
|
2: 'sm:grid-cols-2',
|
||||||
3: "sm:grid-cols-3",
|
3: 'sm:grid-cols-3',
|
||||||
4: "sm:grid-cols-4",
|
4: 'sm:grid-cols-4',
|
||||||
5: "sm:grid-cols-5",
|
5: 'sm:grid-cols-5',
|
||||||
6: "sm:grid-cols-6",
|
6: 'sm:grid-cols-6',
|
||||||
7: "sm:grid-cols-7",
|
7: 'sm:grid-cols-7',
|
||||||
8: "sm:grid-cols-8",
|
8: 'sm:grid-cols-8',
|
||||||
9: "sm:grid-cols-9",
|
9: 'sm:grid-cols-9',
|
||||||
10: "sm:grid-cols-10",
|
10: 'sm:grid-cols-10',
|
||||||
11: "sm:grid-cols-11",
|
11: 'sm:grid-cols-11',
|
||||||
12: "sm:grid-cols-12"
|
12: 'sm:grid-cols-12',
|
||||||
}
|
};
|
||||||
|
|
||||||
const gridColsMd: { [key in Cols]: string } = {
|
const gridColsMd: { [key in Cols]: string } = {
|
||||||
0: "md:grid-cols-none",
|
0: 'md:grid-cols-none',
|
||||||
1: "md:grid-cols-1",
|
1: 'md:grid-cols-1',
|
||||||
2: "md:grid-cols-2",
|
2: 'md:grid-cols-2',
|
||||||
3: "md:grid-cols-3",
|
3: 'md:grid-cols-3',
|
||||||
4: "md:grid-cols-4",
|
4: 'md:grid-cols-4',
|
||||||
5: "md:grid-cols-5",
|
5: 'md:grid-cols-5',
|
||||||
6: "md:grid-cols-6",
|
6: 'md:grid-cols-6',
|
||||||
7: "md:grid-cols-7",
|
7: 'md:grid-cols-7',
|
||||||
8: "md:grid-cols-8",
|
8: 'md:grid-cols-8',
|
||||||
9: "md:grid-cols-9",
|
9: 'md:grid-cols-9',
|
||||||
10: "md:grid-cols-10",
|
10: 'md:grid-cols-10',
|
||||||
11: "md:grid-cols-11",
|
11: 'md:grid-cols-11',
|
||||||
12: "md:grid-cols-12"
|
12: 'md:grid-cols-12',
|
||||||
}
|
};
|
||||||
|
|
||||||
const gridColsLg: { [key in Cols]: string } = {
|
const gridColsLg: { [key in Cols]: string } = {
|
||||||
0: "lg:grid-cols-none",
|
0: 'lg:grid-cols-none',
|
||||||
1: "lg:grid-cols-1",
|
1: 'lg:grid-cols-1',
|
||||||
2: "lg:grid-cols-2",
|
2: 'lg:grid-cols-2',
|
||||||
3: "lg:grid-cols-3",
|
3: 'lg:grid-cols-3',
|
||||||
4: "lg:grid-cols-4",
|
4: 'lg:grid-cols-4',
|
||||||
5: "lg:grid-cols-5",
|
5: 'lg:grid-cols-5',
|
||||||
6: "lg:grid-cols-6",
|
6: 'lg:grid-cols-6',
|
||||||
7: "lg:grid-cols-7",
|
7: 'lg:grid-cols-7',
|
||||||
8: "lg:grid-cols-8",
|
8: 'lg:grid-cols-8',
|
||||||
9: "lg:grid-cols-9",
|
9: 'lg:grid-cols-9',
|
||||||
10: "lg:grid-cols-10",
|
10: 'lg:grid-cols-10',
|
||||||
11: "lg:grid-cols-11",
|
11: 'lg:grid-cols-11',
|
||||||
12: "lg:grid-cols-12"
|
12: 'lg:grid-cols-12',
|
||||||
}
|
};
|
||||||
|
|
||||||
const colSpan: { [key in Span]: string } = {
|
const colSpan: { [key in Span]: string } = {
|
||||||
1: "col-span-1",
|
1: 'col-span-1',
|
||||||
2: "col-span-2",
|
2: 'col-span-2',
|
||||||
3: "col-span-3",
|
3: 'col-span-3',
|
||||||
4: "col-span-4",
|
4: 'col-span-4',
|
||||||
5: "col-span-5",
|
5: 'col-span-5',
|
||||||
6: "col-span-6",
|
6: 'col-span-6',
|
||||||
7: "col-span-7",
|
7: 'col-span-7',
|
||||||
8: "col-span-8",
|
8: 'col-span-8',
|
||||||
9: "col-span-9",
|
9: 'col-span-9',
|
||||||
10: "col-span-10",
|
10: 'col-span-10',
|
||||||
11: "col-span-11",
|
11: 'col-span-11',
|
||||||
12: "col-span-12",
|
12: 'col-span-12',
|
||||||
13: "col-span-13"
|
13: 'col-span-13',
|
||||||
}
|
};
|
||||||
|
|
||||||
const colSpanSm: { [key in Span]: string } = {
|
const colSpanSm: { [key in Span]: string } = {
|
||||||
1: "sm:col-span-1",
|
1: 'sm:col-span-1',
|
||||||
2: "sm:col-span-2",
|
2: 'sm:col-span-2',
|
||||||
3: "sm:col-span-3",
|
3: 'sm:col-span-3',
|
||||||
4: "sm:col-span-4",
|
4: 'sm:col-span-4',
|
||||||
5: "sm:col-span-5",
|
5: 'sm:col-span-5',
|
||||||
6: "sm:col-span-6",
|
6: 'sm:col-span-6',
|
||||||
7: "sm:col-span-7",
|
7: 'sm:col-span-7',
|
||||||
8: "sm:col-span-8",
|
8: 'sm:col-span-8',
|
||||||
9: "sm:col-span-9",
|
9: 'sm:col-span-9',
|
||||||
10: "sm:col-span-10",
|
10: 'sm:col-span-10',
|
||||||
11: "sm:col-span-11",
|
11: 'sm:col-span-11',
|
||||||
12: "sm:col-span-12",
|
12: 'sm:col-span-12',
|
||||||
13: "sm:col-span-13"
|
13: 'sm:col-span-13',
|
||||||
}
|
};
|
||||||
|
|
||||||
const colSpanMd: { [key in Span]: string } = {
|
const colSpanMd: { [key in Span]: string } = {
|
||||||
1: "md:col-span-1",
|
1: 'md:col-span-1',
|
||||||
2: "md:col-span-2",
|
2: 'md:col-span-2',
|
||||||
3: "md:col-span-3",
|
3: 'md:col-span-3',
|
||||||
4: "md:col-span-4",
|
4: 'md:col-span-4',
|
||||||
5: "md:col-span-5",
|
5: 'md:col-span-5',
|
||||||
6: "md:col-span-6",
|
6: 'md:col-span-6',
|
||||||
7: "md:col-span-7",
|
7: 'md:col-span-7',
|
||||||
8: "md:col-span-8",
|
8: 'md:col-span-8',
|
||||||
9: "md:col-span-9",
|
9: 'md:col-span-9',
|
||||||
10: "md:col-span-10",
|
10: 'md:col-span-10',
|
||||||
11: "md:col-span-11",
|
11: 'md:col-span-11',
|
||||||
12: "md:col-span-12",
|
12: 'md:col-span-12',
|
||||||
13: "md:col-span-13"
|
13: 'md:col-span-13',
|
||||||
}
|
};
|
||||||
|
|
||||||
const colSpanLg: { [key in Span]: string } = {
|
const colSpanLg: { [key in Span]: string } = {
|
||||||
1: "lg:col-span-1",
|
1: 'lg:col-span-1',
|
||||||
2: "lg:col-span-2",
|
2: 'lg:col-span-2',
|
||||||
3: "lg:col-span-3",
|
3: 'lg:col-span-3',
|
||||||
4: "lg:col-span-4",
|
4: 'lg:col-span-4',
|
||||||
5: "lg:col-span-5",
|
5: 'lg:col-span-5',
|
||||||
6: "lg:col-span-6",
|
6: 'lg:col-span-6',
|
||||||
7: "lg:col-span-7",
|
7: 'lg:col-span-7',
|
||||||
8: "lg:col-span-8",
|
8: 'lg:col-span-8',
|
||||||
9: "lg:col-span-9",
|
9: 'lg:col-span-9',
|
||||||
10: "lg:col-span-10",
|
10: 'lg:col-span-10',
|
||||||
11: "lg:col-span-11",
|
11: 'lg:col-span-11',
|
||||||
12: "lg:col-span-12",
|
12: 'lg:col-span-12',
|
||||||
13: "lg:col-span-13"
|
13: 'lg:col-span-13',
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,37 +1,37 @@
|
|||||||
import type { Component, ValidComponent } from "solid-js"
|
import type { Component, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import * as HoverCardPrimitive from "@kobalte/core/hover-card"
|
import * as HoverCardPrimitive from '@kobalte/core/hover-card';
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const HoverCardTrigger = HoverCardPrimitive.Trigger
|
const HoverCardTrigger = HoverCardPrimitive.Trigger;
|
||||||
|
|
||||||
const HoverCard: Component<HoverCardPrimitive.HoverCardRootProps> = (props) => {
|
const HoverCard: Component<HoverCardPrimitive.HoverCardRootProps> = (props) => {
|
||||||
return <HoverCardPrimitive.Root gutter={4} {...props} />
|
return <HoverCardPrimitive.Root gutter={4} {...props} />;
|
||||||
}
|
};
|
||||||
|
|
||||||
type HoverCardContentProps<T extends ValidComponent = "div"> =
|
type HoverCardContentProps<T extends ValidComponent = 'div'> =
|
||||||
HoverCardPrimitive.HoverCardContentProps<T> & {
|
HoverCardPrimitive.HoverCardContentProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const HoverCardContent = <T extends ValidComponent = "div">(
|
const HoverCardContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, HoverCardContentProps<T>>
|
props: PolymorphicProps<T, HoverCardContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as HoverCardContentProps, ["class"])
|
const [local, others] = splitProps(props as HoverCardContentProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<HoverCardPrimitive.Portal>
|
<HoverCardPrimitive.Portal>
|
||||||
<HoverCardPrimitive.Content
|
<HoverCardPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
"z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=closed]:animate-out data-[state=open]:animate-in',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
</HoverCardPrimitive.Portal>
|
</HoverCardPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { HoverCard, HoverCardTrigger, HoverCardContent }
|
export { HoverCard, HoverCardTrigger, HoverCardContent };
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
import type { Component, ComponentProps } from "solid-js"
|
import type { Component, ComponentProps } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const Label: Component<ComponentProps<"label">> = (props) => {
|
const Label: Component<ComponentProps<'label'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
class={cn(
|
class={cn(
|
||||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
'font-medium text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Label }
|
export { Label };
|
||||||
|
|||||||
@@ -1,97 +1,98 @@
|
|||||||
import type { Component, ComponentProps, JSX, ValidComponent } from "solid-js"
|
import type { Component, ComponentProps, JSX, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import * as MenubarPrimitive from "@kobalte/core/menubar"
|
import * as MenubarPrimitive from '@kobalte/core/menubar';
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const MenubarGroup = MenubarPrimitive.Group
|
const MenubarGroup = MenubarPrimitive.Group;
|
||||||
const MenubarPortal = MenubarPrimitive.Portal
|
const MenubarPortal = MenubarPrimitive.Portal;
|
||||||
const MenubarSub = MenubarPrimitive.Sub
|
const MenubarSub = MenubarPrimitive.Sub;
|
||||||
const MenubarRadioGroup = MenubarPrimitive.RadioGroup
|
const MenubarRadioGroup = MenubarPrimitive.RadioGroup;
|
||||||
|
|
||||||
type MenubarRootProps<T extends ValidComponent = "div"> = MenubarPrimitive.MenubarRootProps<T> & {
|
type MenubarRootProps<T extends ValidComponent = 'div'> =
|
||||||
class?: string | undefined
|
MenubarPrimitive.MenubarRootProps<T> & {
|
||||||
}
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const Menubar = <T extends ValidComponent = "div">(
|
const Menubar = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, MenubarRootProps<T>>
|
props: PolymorphicProps<T, MenubarRootProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as MenubarRootProps, ["class"])
|
const [local, others] = splitProps(props as MenubarRootProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<MenubarPrimitive.Root
|
<MenubarPrimitive.Root
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex h-10 items-center space-x-1 rounded-md border bg-background p-1",
|
'flex h-10 items-center space-x-1 rounded-md border bg-background p-1',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const MenubarMenu: Component<MenubarPrimitive.MenubarMenuProps> = (props) => {
|
const MenubarMenu: Component<MenubarPrimitive.MenubarMenuProps> = (props) => {
|
||||||
return <MenubarPrimitive.Menu gutter={8} {...props} />
|
return <MenubarPrimitive.Menu gutter={8} {...props} />;
|
||||||
}
|
};
|
||||||
|
|
||||||
type MenubarTriggerProps<T extends ValidComponent = "button"> =
|
type MenubarTriggerProps<T extends ValidComponent = 'button'> =
|
||||||
MenubarPrimitive.MenubarTriggerProps<T> & { class?: string | undefined }
|
MenubarPrimitive.MenubarTriggerProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const MenubarTrigger = <T extends ValidComponent = "button">(
|
const MenubarTrigger = <T extends ValidComponent = 'button'>(
|
||||||
props: PolymorphicProps<T, MenubarTriggerProps<T>>
|
props: PolymorphicProps<T, MenubarTriggerProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as MenubarTriggerProps, ["class"])
|
const [local, others] = splitProps(props as MenubarTriggerProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<MenubarPrimitive.Trigger
|
<MenubarPrimitive.Trigger
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
|
'flex cursor-default select-none items-center rounded-sm px-3 py-1.5 font-medium text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type MenubarContentProps<T extends ValidComponent = "div"> =
|
type MenubarContentProps<T extends ValidComponent = 'div'> =
|
||||||
MenubarPrimitive.MenubarContentProps<T> & { class?: string | undefined }
|
MenubarPrimitive.MenubarContentProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const MenubarContent = <T extends ValidComponent = "div">(
|
const MenubarContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, MenubarContentProps<T>>
|
props: PolymorphicProps<T, MenubarContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as MenubarContentProps, ["class"])
|
const [local, others] = splitProps(props as MenubarContentProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<MenubarPrimitive.Portal>
|
<MenubarPrimitive.Portal>
|
||||||
<MenubarPrimitive.Content
|
<MenubarPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
"z-50 min-w-48 origin-[var(--kb-menu-content-transform-origin)] animate-content-hide overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[expanded]:animate-content-show",
|
'z-50 min-w-48 origin-[var(--kb-menu-content-transform-origin)] animate-content-hide overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[expanded]:animate-content-show',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
</MenubarPrimitive.Portal>
|
</MenubarPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type MenubarSubTriggerProps<T extends ValidComponent = "div"> =
|
type MenubarSubTriggerProps<T extends ValidComponent = 'div'> =
|
||||||
MenubarPrimitive.MenubarSubTriggerProps<T> & {
|
MenubarPrimitive.MenubarSubTriggerProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
inset?: boolean
|
inset?: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
const MenubarSubTrigger = <T extends ValidComponent = "div">(
|
const MenubarSubTrigger = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, MenubarSubTriggerProps<T>>
|
props: PolymorphicProps<T, MenubarSubTriggerProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as MenubarSubTriggerProps, [
|
const [local, others] = splitProps(props as MenubarSubTriggerProps, [
|
||||||
"class",
|
'class',
|
||||||
"children",
|
'children',
|
||||||
"inset"
|
'inset',
|
||||||
])
|
]);
|
||||||
return (
|
return (
|
||||||
<MenubarPrimitive.SubTrigger
|
<MenubarPrimitive.SubTrigger
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
|
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
|
||||||
local.inset && "pl-8",
|
local.inset && 'pl-8',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -110,66 +111,75 @@ const MenubarSubTrigger = <T extends ValidComponent = "div">(
|
|||||||
<path d="M9 6l6 6l-6 6" />
|
<path d="M9 6l6 6l-6 6" />
|
||||||
</svg>
|
</svg>
|
||||||
</MenubarPrimitive.SubTrigger>
|
</MenubarPrimitive.SubTrigger>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type MenubarSubContentProps<T extends ValidComponent = "div"> =
|
type MenubarSubContentProps<T extends ValidComponent = 'div'> =
|
||||||
MenubarPrimitive.MenubarSubContentProps<T> & {
|
MenubarPrimitive.MenubarSubContentProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const MenubarSubContent = <T extends ValidComponent = "div">(
|
const MenubarSubContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, MenubarSubContentProps<T>>
|
props: PolymorphicProps<T, MenubarSubContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as MenubarSubContentProps, ["class"])
|
const [local, others] = splitProps(props as MenubarSubContentProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<MenubarPrimitive.Portal>
|
<MenubarPrimitive.Portal>
|
||||||
<MenubarPrimitive.SubContent
|
<MenubarPrimitive.SubContent
|
||||||
class={cn(
|
class={cn(
|
||||||
"z-50 min-w-32 origin-[var(--kb-menu-content-transform-origin)] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in",
|
'z-50 min-w-32 origin-[var(--kb-menu-content-transform-origin)] animate-in overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
</MenubarPrimitive.Portal>
|
</MenubarPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type MenubarItemProps<T extends ValidComponent = "div"> = MenubarPrimitive.MenubarItemProps<T> & {
|
type MenubarItemProps<T extends ValidComponent = 'div'> =
|
||||||
class?: string | undefined
|
MenubarPrimitive.MenubarItemProps<T> & {
|
||||||
inset?: boolean
|
class?: string | undefined;
|
||||||
}
|
inset?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
const MenubarItem = <T extends ValidComponent = "div">(
|
const MenubarItem = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, MenubarItemProps<T>>
|
props: PolymorphicProps<T, MenubarItemProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as MenubarItemProps, ["class", "inset"])
|
const [local, others] = splitProps(props as MenubarItemProps, [
|
||||||
|
'class',
|
||||||
|
'inset',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<MenubarPrimitive.Item
|
<MenubarPrimitive.Item
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
local.inset && "pl-8",
|
local.inset && 'pl-8',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type MenubarCheckboxItemProps<T extends ValidComponent = "div"> =
|
type MenubarCheckboxItemProps<T extends ValidComponent = 'div'> =
|
||||||
MenubarPrimitive.MenubarCheckboxItemProps<T> & {
|
MenubarPrimitive.MenubarCheckboxItemProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const MenubarCheckboxItem = <T extends ValidComponent = "div">(
|
const MenubarCheckboxItem = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, MenubarCheckboxItemProps<T>>
|
props: PolymorphicProps<T, MenubarCheckboxItemProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as MenubarCheckboxItemProps, ["class", "children"])
|
const [local, others] = splitProps(props as MenubarCheckboxItemProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<MenubarPrimitive.CheckboxItem
|
<MenubarPrimitive.CheckboxItem
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -192,23 +202,26 @@ const MenubarCheckboxItem = <T extends ValidComponent = "div">(
|
|||||||
</span>
|
</span>
|
||||||
{local.children}
|
{local.children}
|
||||||
</MenubarPrimitive.CheckboxItem>
|
</MenubarPrimitive.CheckboxItem>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type MenubarRadioItemProps<T extends ValidComponent = "div"> =
|
type MenubarRadioItemProps<T extends ValidComponent = 'div'> =
|
||||||
MenubarPrimitive.MenubarRadioItemProps<T> & {
|
MenubarPrimitive.MenubarRadioItemProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const MenubarRadioItem = <T extends ValidComponent = "div">(
|
const MenubarRadioItem = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, MenubarRadioItemProps<T>>
|
props: PolymorphicProps<T, MenubarRadioItemProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as MenubarRadioItemProps, ["class", "children"])
|
const [local, others] = splitProps(props as MenubarRadioItemProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<MenubarPrimitive.RadioItem
|
<MenubarPrimitive.RadioItem
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -231,66 +244,86 @@ const MenubarRadioItem = <T extends ValidComponent = "div">(
|
|||||||
</span>
|
</span>
|
||||||
{local.children}
|
{local.children}
|
||||||
</MenubarPrimitive.RadioItem>
|
</MenubarPrimitive.RadioItem>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type MenubarItemLabelProps<T extends ValidComponent = "div"> =
|
type MenubarItemLabelProps<T extends ValidComponent = 'div'> =
|
||||||
MenubarPrimitive.MenubarItemLabelProps<T> & {
|
MenubarPrimitive.MenubarItemLabelProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
inset?: boolean
|
inset?: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
const MenubarItemLabel = <T extends ValidComponent = "div">(
|
const MenubarItemLabel = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, MenubarItemLabelProps<T>>
|
props: PolymorphicProps<T, MenubarItemLabelProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as MenubarItemLabelProps, ["class", "inset"])
|
const [local, others] = splitProps(props as MenubarItemLabelProps, [
|
||||||
|
'class',
|
||||||
|
'inset',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<MenubarPrimitive.ItemLabel
|
<MenubarPrimitive.ItemLabel
|
||||||
class={cn("px-2 py-1.5 text-sm font-semibold", local.inset && "pl-8", local.class)}
|
class={cn(
|
||||||
|
'px-2 py-1.5 font-semibold text-sm',
|
||||||
|
local.inset && 'pl-8',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type MenubarGroupLabelProps<T extends ValidComponent = "span"> =
|
type MenubarGroupLabelProps<T extends ValidComponent = 'span'> =
|
||||||
MenubarPrimitive.MenubarGroupLabelProps<T> & {
|
MenubarPrimitive.MenubarGroupLabelProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
inset?: boolean
|
inset?: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
const MenubarGroupLabel = <T extends ValidComponent = "span">(
|
const MenubarGroupLabel = <T extends ValidComponent = 'span'>(
|
||||||
props: PolymorphicProps<T, MenubarGroupLabelProps<T>>
|
props: PolymorphicProps<T, MenubarGroupLabelProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as MenubarGroupLabelProps, ["class", "inset"])
|
const [local, others] = splitProps(props as MenubarGroupLabelProps, [
|
||||||
|
'class',
|
||||||
|
'inset',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<MenubarPrimitive.GroupLabel
|
<MenubarPrimitive.GroupLabel
|
||||||
class={cn("px-2 py-1.5 text-sm font-semibold", local.inset && "pl-8", local.class)}
|
class={cn(
|
||||||
|
'px-2 py-1.5 font-semibold text-sm',
|
||||||
|
local.inset && 'pl-8',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type MenubarSeparatorProps<T extends ValidComponent = "hr"> =
|
type MenubarSeparatorProps<T extends ValidComponent = 'hr'> =
|
||||||
MenubarPrimitive.MenubarSeparatorProps<T> & { class?: string | undefined }
|
MenubarPrimitive.MenubarSeparatorProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const MenubarSeparator = <T extends ValidComponent = "hr">(
|
const MenubarSeparator = <T extends ValidComponent = 'hr'>(
|
||||||
props: PolymorphicProps<T, MenubarSeparatorProps<T>>
|
props: PolymorphicProps<T, MenubarSeparatorProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as MenubarSeparatorProps, ["class"])
|
const [local, others] = splitProps(props as MenubarSeparatorProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<MenubarPrimitive.Separator class={cn("-mx-1 my-1 h-px bg-muted", local.class)} {...others} />
|
<MenubarPrimitive.Separator
|
||||||
)
|
class={cn('-mx-1 my-1 h-px bg-muted', local.class)}
|
||||||
}
|
|
||||||
|
|
||||||
const MenubarShortcut: Component<ComponentProps<"span">> = (props) => {
|
|
||||||
const [local, others] = splitProps(props, ["class"])
|
|
||||||
return (
|
|
||||||
<span
|
|
||||||
class={cn("ml-auto text-xs tracking-widest text-muted-foreground", local.class)}
|
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
const MenubarShortcut: Component<ComponentProps<'span'>> = (props) => {
|
||||||
|
const [local, others] = splitProps(props, ['class']);
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
class={cn(
|
||||||
|
'ml-auto text-muted-foreground text-xs tracking-widest',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Menubar,
|
Menubar,
|
||||||
@@ -309,5 +342,5 @@ export {
|
|||||||
MenubarSubTrigger,
|
MenubarSubTrigger,
|
||||||
MenubarGroup,
|
MenubarGroup,
|
||||||
MenubarSub,
|
MenubarSub,
|
||||||
MenubarShortcut
|
MenubarShortcut,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,28 +1,31 @@
|
|||||||
import type { JSX, ValidComponent } from "solid-js"
|
import type { JSX, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { PolymorphicProps } from "@kobalte/core"
|
import type { PolymorphicProps } from '@kobalte/core';
|
||||||
import * as NavigationMenuPrimitive from "@kobalte/core/navigation-menu"
|
import * as NavigationMenuPrimitive from '@kobalte/core/navigation-menu';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const NavigationMenuItem = NavigationMenuPrimitive.Menu
|
const NavigationMenuItem = NavigationMenuPrimitive.Menu;
|
||||||
|
|
||||||
type NavigationMenuProps<T extends ValidComponent = "ul"> =
|
type NavigationMenuProps<T extends ValidComponent = 'ul'> =
|
||||||
NavigationMenuPrimitive.NavigationMenuRootProps<T> & {
|
NavigationMenuPrimitive.NavigationMenuRootProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const NavigationMenu = <T extends ValidComponent = "ul">(
|
const NavigationMenu = <T extends ValidComponent = 'ul'>(
|
||||||
props: PolymorphicProps<T, NavigationMenuProps<T>>
|
props: PolymorphicProps<T, NavigationMenuProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as NavigationMenuProps, ["class", "children"])
|
const [local, others] = splitProps(props as NavigationMenuProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<NavigationMenuPrimitive.Root
|
<NavigationMenuPrimitive.Root
|
||||||
gutter={6}
|
gutter={6}
|
||||||
class={cn(
|
class={cn(
|
||||||
"group/menu flex w-max flex-1 list-none items-center justify-center data-[orientation=vertical]:flex-col [&>li]:w-full",
|
'group/menu flex w-max flex-1 list-none items-center justify-center data-[orientation=vertical]:flex-col [&>li]:w-full',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -30,28 +33,30 @@ const NavigationMenu = <T extends ValidComponent = "ul">(
|
|||||||
{local.children}
|
{local.children}
|
||||||
<NavigationMenuViewport />
|
<NavigationMenuViewport />
|
||||||
</NavigationMenuPrimitive.Root>
|
</NavigationMenuPrimitive.Root>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type NavigationMenuTriggerProps<T extends ValidComponent = "button"> =
|
type NavigationMenuTriggerProps<T extends ValidComponent = 'button'> =
|
||||||
NavigationMenuPrimitive.NavigationMenuTriggerProps<T> & {
|
NavigationMenuPrimitive.NavigationMenuTriggerProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const NavigationMenuTrigger = <T extends ValidComponent = "button">(
|
const NavigationMenuTrigger = <T extends ValidComponent = 'button'>(
|
||||||
props: PolymorphicProps<T, NavigationMenuTriggerProps<T>>
|
props: PolymorphicProps<T, NavigationMenuTriggerProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as NavigationMenuTriggerProps, ["class"])
|
const [local, others] = splitProps(props as NavigationMenuTriggerProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<NavigationMenuPrimitive.Trigger
|
<NavigationMenuPrimitive.Trigger
|
||||||
class={cn(
|
class={cn(
|
||||||
"group/trigger inline-flex h-10 w-full items-center justify-center whitespace-nowrap rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[expanded]:bg-accent/50",
|
'group/trigger inline-flex h-10 w-full items-center justify-center whitespace-nowrap rounded-md bg-background px-4 py-2 font-medium text-sm transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[expanded]:bg-accent/50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
const NavigationMenuIcon = () => {
|
const NavigationMenuIcon = () => {
|
||||||
return (
|
return (
|
||||||
<NavigationMenuPrimitive.Icon aria-hidden="true">
|
<NavigationMenuPrimitive.Icon aria-hidden="true">
|
||||||
@@ -63,115 +68,133 @@ const NavigationMenuIcon = () => {
|
|||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
class="relative top-px ml-1 size-3 transition duration-200 group-data-[expanded]/trigger:rotate-180 group-data-[orientation=vertical]/menu:-rotate-90 group-data-[orientation=vertical]/menu:group-data-[expanded]/trigger:rotate-90"
|
class="group-data-[orientation=vertical]/menu:-rotate-90 relative top-px ml-1 size-3 transition duration-200 group-data-[orientation=vertical]/menu:group-data-[expanded]/trigger:rotate-90 group-data-[expanded]/trigger:rotate-180"
|
||||||
>
|
>
|
||||||
<path d="M6 9l6 6l6 -6" />
|
<path d="M6 9l6 6l6 -6" />
|
||||||
</svg>
|
</svg>
|
||||||
</NavigationMenuPrimitive.Icon>
|
</NavigationMenuPrimitive.Icon>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type NavigationMenuViewportProps<T extends ValidComponent = "li"> =
|
type NavigationMenuViewportProps<T extends ValidComponent = 'li'> =
|
||||||
NavigationMenuPrimitive.NavigationMenuViewportProps<T> & { class?: string | undefined }
|
NavigationMenuPrimitive.NavigationMenuViewportProps<T> & {
|
||||||
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const NavigationMenuViewport = <T extends ValidComponent = "li">(
|
const NavigationMenuViewport = <T extends ValidComponent = 'li'>(
|
||||||
props: PolymorphicProps<T, NavigationMenuViewportProps<T>>
|
props: PolymorphicProps<T, NavigationMenuViewportProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as NavigationMenuViewportProps, ["class"])
|
const [local, others] = splitProps(props as NavigationMenuViewportProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<NavigationMenuPrimitive.Viewport
|
<NavigationMenuPrimitive.Viewport
|
||||||
class={cn(
|
class={cn(
|
||||||
// base settings
|
// base settings
|
||||||
"pointer-events-none z-[1000] flex h-[var(--kb-navigation-menu-viewport-height)] w-[var(--kb-navigation-menu-viewport-width)] origin-[var(--kb-menu-content-transform-origin)] items-center justify-center overflow-x-clip overflow-y-visible rounded-md border bg-popover opacity-0 shadow-lg data-[expanded]:pointer-events-auto data-[orientation=vertical]:overflow-y-clip data-[orientation=vertical]:overflow-x-visible data-[expanded]:rounded-md",
|
'pointer-events-none z-[1000] flex h-[var(--kb-navigation-menu-viewport-height)] w-[var(--kb-navigation-menu-viewport-width)] origin-[var(--kb-menu-content-transform-origin)] items-center justify-center overflow-x-clip overflow-y-visible rounded-md border bg-popover opacity-0 shadow-lg data-[expanded]:pointer-events-auto data-[orientation=vertical]:overflow-y-clip data-[orientation=vertical]:overflow-x-visible data-[expanded]:rounded-md',
|
||||||
// animate
|
// animate
|
||||||
"animate-content-hide transition-[width,height] duration-200 ease-in data-[expanded]:animate-content-show data-[expanded]:opacity-100 data-[expanded]:ease-out",
|
'animate-content-hide transition-[width,height] duration-200 ease-in data-[expanded]:animate-content-show data-[expanded]:opacity-100 data-[expanded]:ease-out',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type NavigationMenuContentProps<T extends ValidComponent = "ul"> =
|
type NavigationMenuContentProps<T extends ValidComponent = 'ul'> =
|
||||||
NavigationMenuPrimitive.NavigationMenuContentProps<T> & {
|
NavigationMenuPrimitive.NavigationMenuContentProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const NavigationMenuContent = <T extends ValidComponent = "ul">(
|
const NavigationMenuContent = <T extends ValidComponent = 'ul'>(
|
||||||
props: PolymorphicProps<T, NavigationMenuContentProps<T>>
|
props: PolymorphicProps<T, NavigationMenuContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as NavigationMenuContentProps, ["class"])
|
const [local, others] = splitProps(props as NavigationMenuContentProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<NavigationMenuPrimitive.Portal>
|
<NavigationMenuPrimitive.Portal>
|
||||||
<NavigationMenuPrimitive.Content
|
<NavigationMenuPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
// base settings
|
// base settings
|
||||||
"pointer-events-none absolute left-0 top-0 box-border p-4 focus:outline-none data-[expanded]:pointer-events-auto",
|
'pointer-events-none absolute top-0 left-0 box-border p-4 focus:outline-none data-[expanded]:pointer-events-auto',
|
||||||
// base animation settings
|
// base animation settings
|
||||||
"data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out",
|
'data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out',
|
||||||
// left to right
|
// left to right
|
||||||
"data-[orientation=horizontal]:data-[motion=from-start]:slide-in-from-left-52 data-[orientation=horizontal]:data-[motion=to-end]:slide-out-to-right-52",
|
'data-[orientation=horizontal]:data-[motion=from-start]:slide-in-from-left-52 data-[orientation=horizontal]:data-[motion=to-end]:slide-out-to-right-52',
|
||||||
// right to left
|
// right to left
|
||||||
"data-[orientation=horizontal]:data-[motion=from-end]:slide-in-from-right-52 data-[orientation=horizontal]:data-[motion=to-start]:slide-out-to-left-52",
|
'data-[orientation=horizontal]:data-[motion=from-end]:slide-in-from-right-52 data-[orientation=horizontal]:data-[motion=to-start]:slide-out-to-left-52',
|
||||||
// top to bottom
|
// top to bottom
|
||||||
"data-[orientation=vertical]:data-[motion=from-start]:slide-in-from-top-52 data-[orientation=vertical]:data-[motion=to-end]:slide-out-to-bottom-52",
|
'data-[orientation=vertical]:data-[motion=from-start]:slide-in-from-top-52 data-[orientation=vertical]:data-[motion=to-end]:slide-out-to-bottom-52',
|
||||||
//bottom to top
|
//bottom to top
|
||||||
"data-[orientation=vertical]:data-[motion=from-end]:slide-in-from-bottom-52 data-[orientation=vertical]:data-[motion=to-start]:slide-out-to-bottom-52",
|
'data-[orientation=vertical]:data-[motion=from-end]:slide-in-from-bottom-52 data-[orientation=vertical]:data-[motion=to-start]:slide-out-to-bottom-52',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
</NavigationMenuPrimitive.Portal>
|
</NavigationMenuPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type NavigationMenuLinkProps<T extends ValidComponent = "a"> =
|
type NavigationMenuLinkProps<T extends ValidComponent = 'a'> =
|
||||||
NavigationMenuPrimitive.NavigationMenuItemProps<T> & { class?: string | undefined }
|
NavigationMenuPrimitive.NavigationMenuItemProps<T> & {
|
||||||
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const NavigationMenuLink = <T extends ValidComponent = "a">(
|
const NavigationMenuLink = <T extends ValidComponent = 'a'>(
|
||||||
props: PolymorphicProps<T, NavigationMenuLinkProps<T>>
|
props: PolymorphicProps<T, NavigationMenuLinkProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as NavigationMenuLinkProps, ["class"])
|
const [local, others] = splitProps(props as NavigationMenuLinkProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<NavigationMenuPrimitive.Item
|
<NavigationMenuPrimitive.Item
|
||||||
class={cn(
|
class={cn(
|
||||||
"block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
|
'block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type NavigationMenuLabelProps<T extends ValidComponent = "div"> =
|
type NavigationMenuLabelProps<T extends ValidComponent = 'div'> =
|
||||||
NavigationMenuPrimitive.NavigationMenuItemLabelProps<T> & { class?: string | undefined }
|
NavigationMenuPrimitive.NavigationMenuItemLabelProps<T> & {
|
||||||
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const NavigationMenuLabel = <T extends ValidComponent = "div">(
|
const NavigationMenuLabel = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, NavigationMenuLabelProps<T>>
|
props: PolymorphicProps<T, NavigationMenuLabelProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as NavigationMenuLabelProps, ["class"])
|
const [local, others] = splitProps(props as NavigationMenuLabelProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<NavigationMenuPrimitive.ItemLabel
|
<NavigationMenuPrimitive.ItemLabel
|
||||||
class={cn("text-sm font-medium leading-none", local.class)}
|
class={cn('font-medium text-sm leading-none', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type NavigationMenuDescriptionProps<T extends ValidComponent = "div"> =
|
type NavigationMenuDescriptionProps<T extends ValidComponent = 'div'> =
|
||||||
NavigationMenuPrimitive.NavigationMenuItemDescriptionProps<T> & { class?: string | undefined }
|
NavigationMenuPrimitive.NavigationMenuItemDescriptionProps<T> & {
|
||||||
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const NavigationMenuDescription = <T extends ValidComponent = "div">(
|
const NavigationMenuDescription = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, NavigationMenuDescriptionProps<T>>
|
props: PolymorphicProps<T, NavigationMenuDescriptionProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as NavigationMenuDescriptionProps, ["class"])
|
const [local, others] = splitProps(props as NavigationMenuDescriptionProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<NavigationMenuPrimitive.ItemDescription
|
<NavigationMenuPrimitive.ItemDescription
|
||||||
class={cn("text-sm leading-snug text-muted-foreground", local.class)}
|
class={cn('text-muted-foreground text-sm leading-snug', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
NavigationMenu,
|
NavigationMenu,
|
||||||
@@ -182,5 +205,5 @@ export {
|
|||||||
NavigationMenuContent,
|
NavigationMenuContent,
|
||||||
NavigationMenuLink,
|
NavigationMenuLink,
|
||||||
NavigationMenuLabel,
|
NavigationMenuLabel,
|
||||||
NavigationMenuDescription
|
NavigationMenuDescription,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,83 +1,83 @@
|
|||||||
import type { Component, ComponentProps, JSX, ValidComponent } from "solid-js"
|
import type { Component, ComponentProps, JSX, ValidComponent } from 'solid-js';
|
||||||
import { Show, splitProps } from "solid-js"
|
import { Show, splitProps } from 'solid-js';
|
||||||
|
|
||||||
import * as NumberFieldPrimitive from "@kobalte/core/number-field"
|
import * as NumberFieldPrimitive from '@kobalte/core/number-field';
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const NumberField = NumberFieldPrimitive.Root
|
const NumberField = NumberFieldPrimitive.Root;
|
||||||
|
|
||||||
const NumberFieldGroup: Component<ComponentProps<"div">> = (props) => {
|
const NumberFieldGroup: Component<ComponentProps<'div'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative rounded-md focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
|
'relative rounded-md focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type NumberFieldLabelProps<T extends ValidComponent = "label"> =
|
type NumberFieldLabelProps<T extends ValidComponent = 'label'> =
|
||||||
NumberFieldPrimitive.NumberFieldLabelProps<T> & {
|
NumberFieldPrimitive.NumberFieldLabelProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const NumberFieldLabel = <T extends ValidComponent = "label">(
|
const NumberFieldLabel = <T extends ValidComponent = 'label'>(
|
||||||
props: PolymorphicProps<T, NumberFieldLabelProps<T>>
|
props: PolymorphicProps<T, NumberFieldLabelProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as NumberFieldLabelProps, ["class"])
|
const [local, others] = splitProps(props as NumberFieldLabelProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<NumberFieldPrimitive.Label
|
<NumberFieldPrimitive.Label
|
||||||
class={cn(
|
class={cn(
|
||||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
'font-medium text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type NumberFieldInputProps<T extends ValidComponent = "input"> =
|
type NumberFieldInputProps<T extends ValidComponent = 'input'> =
|
||||||
NumberFieldPrimitive.NumberFieldInputProps<T> & {
|
NumberFieldPrimitive.NumberFieldInputProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const NumberFieldInput = <T extends ValidComponent = "input">(
|
const NumberFieldInput = <T extends ValidComponent = 'input'>(
|
||||||
props: PolymorphicProps<T, NumberFieldInputProps<T>>
|
props: PolymorphicProps<T, NumberFieldInputProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as NumberFieldInputProps, ["class"])
|
const [local, others] = splitProps(props as NumberFieldInputProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<NumberFieldPrimitive.Input
|
<NumberFieldPrimitive.Input
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 data-[invalid]:border-error-foreground data-[invalid]:text-error-foreground",
|
'flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:font-medium file:text-sm placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 data-[invalid]:border-error-foreground data-[invalid]:text-error-foreground',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type NumberFieldIncrementTriggerProps<T extends ValidComponent = "button"> =
|
type NumberFieldIncrementTriggerProps<T extends ValidComponent = 'button'> =
|
||||||
NumberFieldPrimitive.NumberFieldIncrementTriggerProps<T> & {
|
NumberFieldPrimitive.NumberFieldIncrementTriggerProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const NumberFieldIncrementTrigger = <T extends ValidComponent = "button">(
|
const NumberFieldIncrementTrigger = <T extends ValidComponent = 'button'>(
|
||||||
props: PolymorphicProps<T, NumberFieldIncrementTriggerProps<T>>
|
props: PolymorphicProps<T, NumberFieldIncrementTriggerProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as NumberFieldIncrementTriggerProps, [
|
const [local, others] = splitProps(
|
||||||
"class",
|
props as NumberFieldIncrementTriggerProps,
|
||||||
"children"
|
['class', 'children']
|
||||||
])
|
);
|
||||||
return (
|
return (
|
||||||
<NumberFieldPrimitive.IncrementTrigger
|
<NumberFieldPrimitive.IncrementTrigger
|
||||||
class={cn(
|
class={cn(
|
||||||
"absolute right-1 top-1 inline-flex size-4 items-center justify-center",
|
'absolute top-1 right-1 inline-flex size-4 items-center justify-center',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -102,26 +102,26 @@ const NumberFieldIncrementTrigger = <T extends ValidComponent = "button">(
|
|||||||
{(children) => children()}
|
{(children) => children()}
|
||||||
</Show>
|
</Show>
|
||||||
</NumberFieldPrimitive.IncrementTrigger>
|
</NumberFieldPrimitive.IncrementTrigger>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type NumberFieldDecrementTriggerProps<T extends ValidComponent = "button"> =
|
type NumberFieldDecrementTriggerProps<T extends ValidComponent = 'button'> =
|
||||||
NumberFieldPrimitive.NumberFieldDecrementTriggerProps<T> & {
|
NumberFieldPrimitive.NumberFieldDecrementTriggerProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const NumberFieldDecrementTrigger = <T extends ValidComponent = "button">(
|
const NumberFieldDecrementTrigger = <T extends ValidComponent = 'button'>(
|
||||||
props: PolymorphicProps<T, NumberFieldDecrementTriggerProps<T>>
|
props: PolymorphicProps<T, NumberFieldDecrementTriggerProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as NumberFieldDecrementTriggerProps, [
|
const [local, others] = splitProps(
|
||||||
"class",
|
props as NumberFieldDecrementTriggerProps,
|
||||||
"children"
|
['class', 'children']
|
||||||
])
|
);
|
||||||
return (
|
return (
|
||||||
<NumberFieldPrimitive.DecrementTrigger
|
<NumberFieldPrimitive.DecrementTrigger
|
||||||
class={cn(
|
class={cn(
|
||||||
"absolute bottom-1 right-1 inline-flex size-4 items-center justify-center",
|
'absolute right-1 bottom-1 inline-flex size-4 items-center justify-center',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -146,42 +146,46 @@ const NumberFieldDecrementTrigger = <T extends ValidComponent = "button">(
|
|||||||
{(children) => children()}
|
{(children) => children()}
|
||||||
</Show>
|
</Show>
|
||||||
</NumberFieldPrimitive.DecrementTrigger>
|
</NumberFieldPrimitive.DecrementTrigger>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type NumberFieldDescriptionProps<T extends ValidComponent = "div"> =
|
type NumberFieldDescriptionProps<T extends ValidComponent = 'div'> =
|
||||||
NumberFieldPrimitive.NumberFieldDescriptionProps<T> & {
|
NumberFieldPrimitive.NumberFieldDescriptionProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const NumberFieldDescription = <T extends ValidComponent = "div">(
|
const NumberFieldDescription = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, NumberFieldDescriptionProps<T>>
|
props: PolymorphicProps<T, NumberFieldDescriptionProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as NumberFieldDescriptionProps, ["class"])
|
const [local, others] = splitProps(props as NumberFieldDescriptionProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<NumberFieldPrimitive.Description
|
<NumberFieldPrimitive.Description
|
||||||
class={cn("text-sm text-muted-foreground", local.class)}
|
class={cn('text-muted-foreground text-sm', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type NumberFieldErrorMessageProps<T extends ValidComponent = "div"> =
|
type NumberFieldErrorMessageProps<T extends ValidComponent = 'div'> =
|
||||||
NumberFieldPrimitive.NumberFieldErrorMessageProps<T> & {
|
NumberFieldPrimitive.NumberFieldErrorMessageProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const NumberFieldErrorMessage = <T extends ValidComponent = "div">(
|
const NumberFieldErrorMessage = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, NumberFieldErrorMessageProps<T>>
|
props: PolymorphicProps<T, NumberFieldErrorMessageProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as NumberFieldErrorMessageProps, ["class"])
|
const [local, others] = splitProps(props as NumberFieldErrorMessageProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<NumberFieldPrimitive.ErrorMessage
|
<NumberFieldPrimitive.ErrorMessage
|
||||||
class={cn("text-sm text-error-foreground", local.class)}
|
class={cn('text-error-foreground text-sm', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
NumberField,
|
NumberField,
|
||||||
@@ -191,5 +195,5 @@ export {
|
|||||||
NumberFieldIncrementTrigger,
|
NumberFieldIncrementTrigger,
|
||||||
NumberFieldDecrementTrigger,
|
NumberFieldDecrementTrigger,
|
||||||
NumberFieldDescription,
|
NumberFieldDescription,
|
||||||
NumberFieldErrorMessage
|
NumberFieldErrorMessage,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,55 +1,63 @@
|
|||||||
import type { Component, ComponentProps, ValidComponent } from "solid-js"
|
import type { Component, ComponentProps, ValidComponent } from 'solid-js';
|
||||||
import { Show, splitProps } from "solid-js"
|
import { Show, splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { DynamicProps, RootProps } from "@corvu/otp-field"
|
import type { DynamicProps, RootProps } from '@corvu/otp-field';
|
||||||
import OtpField from "@corvu/otp-field"
|
import OtpField from '@corvu/otp-field';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
export const REGEXP_ONLY_DIGITS = "^\\d*$"
|
export const REGEXP_ONLY_DIGITS = '^\\d*$';
|
||||||
export const REGEXP_ONLY_CHARS = "^[a-zA-Z]*$"
|
export const REGEXP_ONLY_CHARS = '^[a-zA-Z]*$';
|
||||||
export const REGEXP_ONLY_DIGITS_AND_CHARS = "^[a-zA-Z0-9]*$"
|
export const REGEXP_ONLY_DIGITS_AND_CHARS = '^[a-zA-Z0-9]*$';
|
||||||
|
|
||||||
type OTPFieldProps<T extends ValidComponent = "div"> = RootProps<T> & { class?: string }
|
type OTPFieldProps<T extends ValidComponent = 'div'> = RootProps<T> & {
|
||||||
|
class?: string;
|
||||||
|
};
|
||||||
|
|
||||||
const OTPField = <T extends ValidComponent = "div">(props: DynamicProps<T, OTPFieldProps<T>>) => {
|
const OTPField = <T extends ValidComponent = 'div'>(
|
||||||
const [local, others] = splitProps(props as OTPFieldProps, ["class"])
|
props: DynamicProps<T, OTPFieldProps<T>>
|
||||||
|
) => {
|
||||||
|
const [local, others] = splitProps(props as OTPFieldProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<OtpField
|
<OtpField
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex items-center gap-2 disabled:cursor-not-allowed has-[:disabled]:opacity-50",
|
'flex items-center gap-2 disabled:cursor-not-allowed has-[:disabled]:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const OTPFieldInput = OtpField.Input
|
const OTPFieldInput = OtpField.Input;
|
||||||
|
|
||||||
const OTPFieldGroup: Component<ComponentProps<"div">> = (props) => {
|
const OTPFieldGroup: Component<ComponentProps<'div'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <div class={cn("flex items-center", local.class)} {...others} />
|
return <div class={cn('flex items-center', local.class)} {...others} />;
|
||||||
}
|
};
|
||||||
|
|
||||||
const OTPFieldSlot: Component<ComponentProps<"div"> & { index: number }> = (props) => {
|
const OTPFieldSlot: Component<ComponentProps<'div'> & { index: number }> = (
|
||||||
const [local, others] = splitProps(props, ["class", "index"])
|
props
|
||||||
const context = OtpField.useContext()
|
) => {
|
||||||
const char = () => context.value()[local.index]
|
const [local, others] = splitProps(props, ['class', 'index']);
|
||||||
const showFakeCaret = () => context.value().length === local.index && context.isInserting()
|
const context = OtpField.useContext();
|
||||||
|
const char = () => context.value()[local.index];
|
||||||
|
const showFakeCaret = () =>
|
||||||
|
context.value().length === local.index && context.isInserting();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cn(
|
class={cn(
|
||||||
"group relative flex size-10 items-center justify-center border-y border-r border-input text-sm first:rounded-l-md first:border-l last:rounded-r-md",
|
'group relative flex size-10 items-center justify-center border-input border-y border-r text-sm first:rounded-l-md first:border-l last:rounded-r-md',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class={cn(
|
class={cn(
|
||||||
"absolute inset-0 z-10 transition-all group-first:rounded-l-md group-last:rounded-r-md",
|
'absolute inset-0 z-10 transition-all group-first:rounded-l-md group-last:rounded-r-md',
|
||||||
context.activeSlots().includes(local.index) && "ring-2 ring-ring ring-offset-background"
|
context.activeSlots().includes(local.index) &&
|
||||||
|
'ring-2 ring-ring ring-offset-background'
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
{char()}
|
{char()}
|
||||||
@@ -59,10 +67,10 @@ const OTPFieldSlot: Component<ComponentProps<"div"> & { index: number }> = (prop
|
|||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const OTPFieldSeparator: Component<ComponentProps<"div">> = (props) => {
|
const OTPFieldSeparator: Component<ComponentProps<'div'>> = (props) => {
|
||||||
return (
|
return (
|
||||||
<div {...props}>
|
<div {...props}>
|
||||||
<svg
|
<svg
|
||||||
@@ -78,7 +86,13 @@ const OTPFieldSeparator: Component<ComponentProps<"div">> = (props) => {
|
|||||||
<circle cx="12.1" cy="12.1" r="1" />
|
<circle cx="12.1" cy="12.1" r="1" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { OTPField, OTPFieldInput, OTPFieldGroup, OTPFieldSlot, OTPFieldSeparator }
|
export {
|
||||||
|
OTPField,
|
||||||
|
OTPFieldInput,
|
||||||
|
OTPFieldGroup,
|
||||||
|
OTPFieldSlot,
|
||||||
|
OTPFieldSeparator,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,62 +1,67 @@
|
|||||||
import type { JSX, ValidComponent } from "solid-js"
|
import type { JSX, ValidComponent } from 'solid-js';
|
||||||
import { Show, splitProps } from "solid-js"
|
import { Show, splitProps } from 'solid-js';
|
||||||
|
|
||||||
import * as PaginationPrimitive from "@kobalte/core/pagination"
|
import * as PaginationPrimitive from '@kobalte/core/pagination';
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { buttonVariants } from '~/components/ui/button';
|
||||||
import { buttonVariants } from "~/components/ui/button"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const PaginationItems = PaginationPrimitive.Items
|
const PaginationItems = PaginationPrimitive.Items;
|
||||||
|
|
||||||
type PaginationRootProps<T extends ValidComponent = "nav"> =
|
type PaginationRootProps<T extends ValidComponent = 'nav'> =
|
||||||
PaginationPrimitive.PaginationRootProps<T> & { class?: string | undefined }
|
PaginationPrimitive.PaginationRootProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const Pagination = <T extends ValidComponent = "nav">(
|
const Pagination = <T extends ValidComponent = 'nav'>(
|
||||||
props: PolymorphicProps<T, PaginationRootProps<T>>
|
props: PolymorphicProps<T, PaginationRootProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as PaginationRootProps, ["class"])
|
const [local, others] = splitProps(props as PaginationRootProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<PaginationPrimitive.Root
|
<PaginationPrimitive.Root
|
||||||
class={cn("[&>*]:flex [&>*]:flex-row [&>*]:items-center [&>*]:gap-1", local.class)}
|
|
||||||
{...others}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type PaginationItemProps<T extends ValidComponent = "button"> =
|
|
||||||
PaginationPrimitive.PaginationItemProps<T> & { class?: string | undefined }
|
|
||||||
|
|
||||||
const PaginationItem = <T extends ValidComponent = "button">(
|
|
||||||
props: PolymorphicProps<T, PaginationItemProps<T>>
|
|
||||||
) => {
|
|
||||||
const [local, others] = splitProps(props as PaginationItemProps, ["class"])
|
|
||||||
return (
|
|
||||||
<PaginationPrimitive.Item
|
|
||||||
class={cn(
|
class={cn(
|
||||||
buttonVariants({
|
'[&>*]:flex [&>*]:flex-row [&>*]:items-center [&>*]:gap-1',
|
||||||
variant: "ghost"
|
|
||||||
}),
|
|
||||||
"size-10 data-[current]:border",
|
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type PaginationEllipsisProps<T extends ValidComponent = "div"> =
|
type PaginationItemProps<T extends ValidComponent = 'button'> =
|
||||||
|
PaginationPrimitive.PaginationItemProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
|
const PaginationItem = <T extends ValidComponent = 'button'>(
|
||||||
|
props: PolymorphicProps<T, PaginationItemProps<T>>
|
||||||
|
) => {
|
||||||
|
const [local, others] = splitProps(props as PaginationItemProps, ['class']);
|
||||||
|
return (
|
||||||
|
<PaginationPrimitive.Item
|
||||||
|
class={cn(
|
||||||
|
buttonVariants({
|
||||||
|
variant: 'ghost',
|
||||||
|
}),
|
||||||
|
'size-10 data-[current]:border',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type PaginationEllipsisProps<T extends ValidComponent = 'div'> =
|
||||||
PaginationPrimitive.PaginationEllipsisProps<T> & {
|
PaginationPrimitive.PaginationEllipsisProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const PaginationEllipsis = <T extends ValidComponent = "div">(
|
const PaginationEllipsis = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, PaginationEllipsisProps<T>>
|
props: PolymorphicProps<T, PaginationEllipsisProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as PaginationEllipsisProps, ["class"])
|
const [local, others] = splitProps(props as PaginationEllipsisProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<PaginationPrimitive.Ellipsis
|
<PaginationPrimitive.Ellipsis
|
||||||
class={cn("flex size-10 items-center justify-center", local.class)}
|
class={cn('flex size-10 items-center justify-center', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
@@ -75,26 +80,29 @@ const PaginationEllipsis = <T extends ValidComponent = "div">(
|
|||||||
</svg>
|
</svg>
|
||||||
<span class="sr-only">More pages</span>
|
<span class="sr-only">More pages</span>
|
||||||
</PaginationPrimitive.Ellipsis>
|
</PaginationPrimitive.Ellipsis>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type PaginationPreviousProps<T extends ValidComponent = "button"> =
|
type PaginationPreviousProps<T extends ValidComponent = 'button'> =
|
||||||
PaginationPrimitive.PaginationPreviousProps<T> & {
|
PaginationPrimitive.PaginationPreviousProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const PaginationPrevious = <T extends ValidComponent = "button">(
|
const PaginationPrevious = <T extends ValidComponent = 'button'>(
|
||||||
props: PolymorphicProps<T, PaginationPreviousProps<T>>
|
props: PolymorphicProps<T, PaginationPreviousProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as PaginationPreviousProps, ["class", "children"])
|
const [local, others] = splitProps(props as PaginationPreviousProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<PaginationPrimitive.Previous
|
<PaginationPrimitive.Previous
|
||||||
class={cn(
|
class={cn(
|
||||||
buttonVariants({
|
buttonVariants({
|
||||||
variant: "ghost"
|
variant: 'ghost',
|
||||||
}),
|
}),
|
||||||
"gap-1 pl-2.5",
|
'gap-1 pl-2.5',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -122,26 +130,29 @@ const PaginationPrevious = <T extends ValidComponent = "button">(
|
|||||||
{(children) => children()}
|
{(children) => children()}
|
||||||
</Show>
|
</Show>
|
||||||
</PaginationPrimitive.Previous>
|
</PaginationPrimitive.Previous>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type PaginationNextProps<T extends ValidComponent = "button"> =
|
type PaginationNextProps<T extends ValidComponent = 'button'> =
|
||||||
PaginationPrimitive.PaginationNextProps<T> & {
|
PaginationPrimitive.PaginationNextProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const PaginationNext = <T extends ValidComponent = "button">(
|
const PaginationNext = <T extends ValidComponent = 'button'>(
|
||||||
props: PolymorphicProps<T, PaginationNextProps<T>>
|
props: PolymorphicProps<T, PaginationNextProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as PaginationNextProps, ["class", "children"])
|
const [local, others] = splitProps(props as PaginationNextProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<PaginationPrimitive.Next
|
<PaginationPrimitive.Next
|
||||||
class={cn(
|
class={cn(
|
||||||
buttonVariants({
|
buttonVariants({
|
||||||
variant: "ghost"
|
variant: 'ghost',
|
||||||
}),
|
}),
|
||||||
"gap-1 pl-2.5",
|
'gap-1 pl-2.5',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -169,8 +180,8 @@ const PaginationNext = <T extends ValidComponent = "button">(
|
|||||||
{(children) => children()}
|
{(children) => children()}
|
||||||
</Show>
|
</Show>
|
||||||
</PaginationPrimitive.Next>
|
</PaginationPrimitive.Next>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Pagination,
|
Pagination,
|
||||||
@@ -178,5 +189,5 @@ export {
|
|||||||
PaginationItem,
|
PaginationItem,
|
||||||
PaginationEllipsis,
|
PaginationEllipsis,
|
||||||
PaginationPrevious,
|
PaginationPrevious,
|
||||||
PaginationNext
|
PaginationNext,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
import type { Component, ValidComponent } from "solid-js"
|
import type { Component, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
import * as PopoverPrimitive from "@kobalte/core/popover"
|
import * as PopoverPrimitive from '@kobalte/core/popover';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const PopoverTrigger = PopoverPrimitive.Trigger
|
const PopoverTrigger = PopoverPrimitive.Trigger;
|
||||||
|
|
||||||
const Popover: Component<PopoverPrimitive.PopoverRootProps> = (props) => {
|
const Popover: Component<PopoverPrimitive.PopoverRootProps> = (props) => {
|
||||||
return <PopoverPrimitive.Root gutter={4} {...props} />
|
return <PopoverPrimitive.Root gutter={4} {...props} />;
|
||||||
}
|
};
|
||||||
|
|
||||||
type PopoverContentProps<T extends ValidComponent = "div"> =
|
type PopoverContentProps<T extends ValidComponent = 'div'> =
|
||||||
PopoverPrimitive.PopoverContentProps<T> & { class?: string | undefined }
|
PopoverPrimitive.PopoverContentProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const PopoverContent = <T extends ValidComponent = "div">(
|
const PopoverContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, PopoverContentProps<T>>
|
props: PolymorphicProps<T, PopoverContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as PopoverContentProps, ["class"])
|
const [local, others] = splitProps(props as PopoverContentProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<PopoverPrimitive.Portal>
|
<PopoverPrimitive.Portal>
|
||||||
<PopoverPrimitive.Content
|
<PopoverPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
"z-50 w-72 origin-[var(--kb-popover-content-transform-origin)] rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[expanded]:animate-in data-[closed]:animate-out data-[closed]:fade-out-0 data-[expanded]:fade-in-0 data-[closed]:zoom-out-95 data-[expanded]:zoom-in-95",
|
'data-[closed]:fade-out-0 data-[expanded]:fade-in-0 data-[closed]:zoom-out-95 data-[expanded]:zoom-in-95 z-50 w-72 origin-[var(--kb-popover-content-transform-origin)] rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[closed]:animate-out data-[expanded]:animate-in',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
</PopoverPrimitive.Portal>
|
</PopoverPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Popover, PopoverTrigger, PopoverContent }
|
export { Popover, PopoverTrigger, PopoverContent };
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import { type LinkComponent, createLink } from '@tanstack/solid-router';
|
import { type LinkComponent, createLink } from '@tanstack/solid-router';
|
||||||
import { type Component, type ComponentProps, type JSX, Show } from 'solid-js';
|
import {
|
||||||
|
type Component,
|
||||||
|
type ComponentProps,
|
||||||
|
type JSX,
|
||||||
|
Show,
|
||||||
|
splitProps,
|
||||||
|
} from 'solid-js';
|
||||||
|
|
||||||
type BasicLinkProps = JSX.IntrinsicElements['a'];
|
type BasicLinkProps = JSX.IntrinsicElements['a'];
|
||||||
|
|
||||||
@@ -10,12 +16,13 @@ const BasicLinkComponent: Component<BasicLinkProps> = (props) => (
|
|||||||
const CreatedLinkComponent = createLink(BasicLinkComponent);
|
const CreatedLinkComponent = createLink(BasicLinkComponent);
|
||||||
|
|
||||||
export const ProLink: LinkComponent<typeof BasicLinkComponent> = (props) => {
|
export const ProLink: LinkComponent<typeof BasicLinkComponent> = (props) => {
|
||||||
|
const [local, other] = splitProps(props, ['href']);
|
||||||
return (
|
return (
|
||||||
<Show
|
<Show
|
||||||
when={props.href}
|
when={!props.href}
|
||||||
fallback={<CreatedLinkComponent preload={'intent'} {...props} />}
|
fallback={<BasicLinkComponent {...(other as any)} href={local.href} />}
|
||||||
>
|
>
|
||||||
<BasicLinkComponent {...(props as any)} />
|
<CreatedLinkComponent preload={'intent'} {...(other as typeof props)} />
|
||||||
</Show>
|
</Show>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,48 +1,54 @@
|
|||||||
import type { Component, ComponentProps } from "solid-js"
|
import type { Component, ComponentProps } from 'solid-js';
|
||||||
import { mergeProps, splitProps } from "solid-js"
|
import { mergeProps, splitProps } from 'solid-js';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
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 },
|
||||||
sm: { radius: 19, strokeWidth: 4 },
|
sm: { radius: 19, strokeWidth: 4 },
|
||||||
md: { radius: 32, strokeWidth: 6 },
|
md: { radius: 32, strokeWidth: 6 },
|
||||||
lg: { radius: 52, strokeWidth: 8 },
|
lg: { radius: 52, strokeWidth: 8 },
|
||||||
xl: { radius: 80, strokeWidth: 10 }
|
xl: { radius: 80, strokeWidth: 10 },
|
||||||
}
|
};
|
||||||
|
|
||||||
type ProgressCircleProps = ComponentProps<"div"> & {
|
type ProgressCircleProps = ComponentProps<'div'> & {
|
||||||
value?: number
|
value?: number;
|
||||||
size?: Size
|
size?: Size;
|
||||||
radius?: number
|
radius?: number;
|
||||||
strokeWidth?: number
|
strokeWidth?: number;
|
||||||
showAnimation?: boolean
|
showAnimation?: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
const ProgressCircle: Component<ProgressCircleProps> = (rawProps) => {
|
const ProgressCircle: Component<ProgressCircleProps> = (rawProps) => {
|
||||||
const props = mergeProps({ size: "md" as Size, showAnimation: true }, rawProps)
|
const props = mergeProps(
|
||||||
|
{ size: 'md' as Size, showAnimation: true },
|
||||||
|
rawProps
|
||||||
|
);
|
||||||
const [local, others] = splitProps(props, [
|
const [local, others] = splitProps(props, [
|
||||||
"class",
|
'class',
|
||||||
"children",
|
'children',
|
||||||
"value",
|
'value',
|
||||||
"size",
|
'size',
|
||||||
"radius",
|
'radius',
|
||||||
"strokeWidth",
|
'strokeWidth',
|
||||||
"showAnimation"
|
'showAnimation',
|
||||||
])
|
]);
|
||||||
|
|
||||||
const value = () => getLimitedValue(local.value)
|
const value = () => getLimitedValue(local.value);
|
||||||
const radius = () => local.radius ?? sizes[local.size].radius
|
const radius = () => local.radius ?? sizes[local.size].radius;
|
||||||
const strokeWidth = () => local.strokeWidth ?? sizes[local.size].strokeWidth
|
const strokeWidth = () => local.strokeWidth ?? sizes[local.size].strokeWidth;
|
||||||
const normalizedRadius = () => radius() - strokeWidth() / 2
|
const normalizedRadius = () => radius() - strokeWidth() / 2;
|
||||||
const circumference = () => normalizedRadius() * 2 * Math.PI
|
const circumference = () => normalizedRadius() * 2 * Math.PI;
|
||||||
const strokeDashoffset = () => (value() / 100) * circumference()
|
const strokeDashoffset = () => (value() / 100) * circumference();
|
||||||
const offset = () => circumference() - strokeDashoffset()
|
const offset = () => circumference() - strokeDashoffset();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={cn("flex flex-col items-center justify-center", local.class)} {...others}>
|
<div
|
||||||
|
class={cn('flex flex-col items-center justify-center', local.class)}
|
||||||
|
{...others}
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
width={radius() * 2}
|
width={radius() * 2}
|
||||||
height={radius() * 2}
|
height={radius() * 2}
|
||||||
@@ -57,7 +63,7 @@ const ProgressCircle: Component<ProgressCircleProps> = (rawProps) => {
|
|||||||
fill="transparent"
|
fill="transparent"
|
||||||
stroke=""
|
stroke=""
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
class={cn("stroke-secondary transition-colors ease-linear")}
|
class={cn('stroke-secondary transition-colors ease-linear')}
|
||||||
/>
|
/>
|
||||||
{value() >= 0 ? (
|
{value() >= 0 ? (
|
||||||
<circle
|
<circle
|
||||||
@@ -65,30 +71,32 @@ const ProgressCircle: Component<ProgressCircleProps> = (rawProps) => {
|
|||||||
cx={radius()}
|
cx={radius()}
|
||||||
cy={radius()}
|
cy={radius()}
|
||||||
stroke-width={strokeWidth()}
|
stroke-width={strokeWidth()}
|
||||||
stroke-dasharray={circumference() + " " + circumference()}
|
stroke-dasharray={circumference() + ' ' + circumference()}
|
||||||
stroke-dashoffset={offset()}
|
stroke-dashoffset={offset()}
|
||||||
fill="transparent"
|
fill="transparent"
|
||||||
stroke=""
|
stroke=""
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
class={cn(
|
class={cn(
|
||||||
"stroke-primary transition-colors ease-linear",
|
'stroke-primary transition-colors ease-linear',
|
||||||
local.showAnimation ? "transition-all duration-300 ease-in-out" : ""
|
local.showAnimation
|
||||||
|
? 'transition-all duration-300 ease-in-out'
|
||||||
|
: ''
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</svg>
|
</svg>
|
||||||
<div class={cn("absolute flex")}>{local.children}</div>
|
<div class={cn('absolute flex')}>{local.children}</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
function getLimitedValue(input: number | undefined) {
|
function getLimitedValue(input: number | undefined) {
|
||||||
if (input === undefined) {
|
if (input === undefined) {
|
||||||
return 0
|
return 0;
|
||||||
} else if (input > 100) {
|
} else if (input > 100) {
|
||||||
return 100
|
return 100;
|
||||||
}
|
}
|
||||||
return input
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { ProgressCircle }
|
export { ProgressCircle };
|
||||||
|
|||||||
@@ -1,33 +1,44 @@
|
|||||||
import type { JSX, ValidComponent } from "solid-js"
|
import type { JSX, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
import * as RadioGroupPrimitive from "@kobalte/core/radio-group"
|
import * as RadioGroupPrimitive from '@kobalte/core/radio-group';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
type RadioGroupRootProps<T extends ValidComponent = "div"> =
|
type RadioGroupRootProps<T extends ValidComponent = 'div'> =
|
||||||
RadioGroupPrimitive.RadioGroupRootProps<T> & { class?: string | undefined }
|
RadioGroupPrimitive.RadioGroupRootProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const RadioGroup = <T extends ValidComponent = "div">(
|
const RadioGroup = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, RadioGroupRootProps<T>>
|
props: PolymorphicProps<T, RadioGroupRootProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as RadioGroupRootProps, ["class"])
|
const [local, others] = splitProps(props as RadioGroupRootProps, ['class']);
|
||||||
return <RadioGroupPrimitive.Root class={cn("grid gap-2", local.class)} {...others} />
|
return (
|
||||||
}
|
<RadioGroupPrimitive.Root
|
||||||
|
class={cn('grid gap-2', local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
type RadioGroupItemProps<T extends ValidComponent = "div"> =
|
type RadioGroupItemProps<T extends ValidComponent = 'div'> =
|
||||||
RadioGroupPrimitive.RadioGroupItemProps<T> & {
|
RadioGroupPrimitive.RadioGroupItemProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const RadioGroupItem = <T extends ValidComponent = "div">(
|
const RadioGroupItem = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, RadioGroupItemProps<T>>
|
props: PolymorphicProps<T, RadioGroupItemProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as RadioGroupItemProps, ["class", "children"])
|
const [local, others] = splitProps(props as RadioGroupItemProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<RadioGroupPrimitive.Item class={cn("flex items-center space-x-2", local.class)} {...others}>
|
<RadioGroupPrimitive.Item
|
||||||
|
class={cn('flex items-center space-x-2', local.class)}
|
||||||
|
{...others}
|
||||||
|
>
|
||||||
<RadioGroupPrimitive.ItemInput />
|
<RadioGroupPrimitive.ItemInput />
|
||||||
<RadioGroupPrimitive.ItemControl class="aspect-square size-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50">
|
<RadioGroupPrimitive.ItemControl class="aspect-square size-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50">
|
||||||
<RadioGroupPrimitive.ItemIndicator class="flex h-full items-center justify-center ">
|
<RadioGroupPrimitive.ItemIndicator class="flex h-full items-center justify-center ">
|
||||||
@@ -47,27 +58,27 @@ const RadioGroupItem = <T extends ValidComponent = "div">(
|
|||||||
</RadioGroupPrimitive.ItemControl>
|
</RadioGroupPrimitive.ItemControl>
|
||||||
{local.children}
|
{local.children}
|
||||||
</RadioGroupPrimitive.Item>
|
</RadioGroupPrimitive.Item>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type RadioGroupLabelProps<T extends ValidComponent = "label"> =
|
type RadioGroupLabelProps<T extends ValidComponent = 'label'> =
|
||||||
RadioGroupPrimitive.RadioGroupLabelProps<T> & {
|
RadioGroupPrimitive.RadioGroupLabelProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const RadioGroupItemLabel = <T extends ValidComponent = "label">(
|
const RadioGroupItemLabel = <T extends ValidComponent = 'label'>(
|
||||||
props: PolymorphicProps<T, RadioGroupLabelProps<T>>
|
props: PolymorphicProps<T, RadioGroupLabelProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as RadioGroupLabelProps, ["class"])
|
const [local, others] = splitProps(props as RadioGroupLabelProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<RadioGroupPrimitive.ItemLabel
|
<RadioGroupPrimitive.ItemLabel
|
||||||
class={cn(
|
class={cn(
|
||||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
'font-medium text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { RadioGroup, RadioGroupItem, RadioGroupItemLabel }
|
export { RadioGroup, RadioGroupItem, RadioGroupItemLabel };
|
||||||
|
|||||||
@@ -1,38 +1,49 @@
|
|||||||
import type { ValidComponent } from "solid-js"
|
import type { ValidComponent } from 'solid-js';
|
||||||
import { Show, splitProps } from "solid-js"
|
import { Show, splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { DynamicProps, HandleProps, RootProps } from "@corvu/resizable"
|
import type { DynamicProps, HandleProps, RootProps } from '@corvu/resizable';
|
||||||
import ResizablePrimitive from "@corvu/resizable"
|
import ResizablePrimitive from '@corvu/resizable';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
type ResizableProps<T extends ValidComponent = "div"> = RootProps<T> & { class?: string }
|
type ResizableProps<T extends ValidComponent = 'div'> = RootProps<T> & {
|
||||||
|
class?: string;
|
||||||
|
};
|
||||||
|
|
||||||
const Resizable = <T extends ValidComponent = "div">(props: DynamicProps<T, ResizableProps<T>>) => {
|
const Resizable = <T extends ValidComponent = 'div'>(
|
||||||
const [, rest] = splitProps(props as ResizableProps, ["class"])
|
props: DynamicProps<T, ResizableProps<T>>
|
||||||
|
) => {
|
||||||
|
const [, rest] = splitProps(props as ResizableProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<ResizablePrimitive
|
<ResizablePrimitive
|
||||||
class={cn("flex size-full data-[orientation=vertical]:flex-col", props.class)}
|
class={cn(
|
||||||
|
'flex size-full data-[orientation=vertical]:flex-col',
|
||||||
|
props.class
|
||||||
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const ResizablePanel = ResizablePrimitive.Panel
|
const ResizablePanel = ResizablePrimitive.Panel;
|
||||||
|
|
||||||
type ResizableHandleProps<T extends ValidComponent = "button"> = HandleProps<T> & {
|
type ResizableHandleProps<T extends ValidComponent = 'button'> =
|
||||||
class?: string
|
HandleProps<T> & {
|
||||||
withHandle?: boolean
|
class?: string;
|
||||||
}
|
withHandle?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
const ResizableHandle = <T extends ValidComponent = "button">(
|
const ResizableHandle = <T extends ValidComponent = 'button'>(
|
||||||
props: DynamicProps<T, ResizableHandleProps<T>>
|
props: DynamicProps<T, ResizableHandleProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [, rest] = splitProps(props as ResizableHandleProps, ["class", "withHandle"])
|
const [, rest] = splitProps(props as ResizableHandleProps, [
|
||||||
|
'class',
|
||||||
|
'withHandle',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<ResizablePrimitive.Handle
|
<ResizablePrimitive.Handle
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative flex w-px shrink-0 items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[orientation=vertical]:h-px data-[orientation=vertical]:w-full data-[orientation=vertical]:after:left-0 data-[orientation=vertical]:after:h-1 data-[orientation=vertical]:after:w-full data-[orientation=vertical]:after:-translate-y-1/2 data-[orientation=vertical]:after:translate-x-0 [&[data-orientation=vertical]>div]:rotate-90",
|
'after:-translate-x-1/2 data-[orientation=vertical]:after:-translate-y-1/2 relative flex w-px shrink-0 items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[orientation=vertical]:h-px data-[orientation=vertical]:w-full data-[orientation=vertical]:after:left-0 data-[orientation=vertical]:after:h-1 data-[orientation=vertical]:after:w-full data-[orientation=vertical]:after:translate-x-0 [&[data-orientation=vertical]>div]:rotate-90',
|
||||||
props.class
|
props.class
|
||||||
)}
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
@@ -59,7 +70,7 @@ const ResizableHandle = <T extends ValidComponent = "button">(
|
|||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
</ResizablePrimitive.Handle>
|
</ResizablePrimitive.Handle>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Resizable, ResizablePanel, ResizableHandle }
|
export { Resizable, ResizablePanel, ResizableHandle };
|
||||||
|
|||||||
@@ -1,30 +1,33 @@
|
|||||||
import type { JSX, ValidComponent } from "solid-js"
|
import type { JSX, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
import * as SelectPrimitive from "@kobalte/core/select"
|
import * as SelectPrimitive from '@kobalte/core/select';
|
||||||
import { cva } from "class-variance-authority"
|
import { cva } from 'class-variance-authority';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const Select = SelectPrimitive.Root
|
const Select = SelectPrimitive.Root;
|
||||||
const SelectValue = SelectPrimitive.Value
|
const SelectValue = SelectPrimitive.Value;
|
||||||
const SelectHiddenSelect = SelectPrimitive.HiddenSelect
|
const SelectHiddenSelect = SelectPrimitive.HiddenSelect;
|
||||||
|
|
||||||
type SelectTriggerProps<T extends ValidComponent = "button"> =
|
type SelectTriggerProps<T extends ValidComponent = 'button'> =
|
||||||
SelectPrimitive.SelectTriggerProps<T> & {
|
SelectPrimitive.SelectTriggerProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const SelectTrigger = <T extends ValidComponent = "button">(
|
const SelectTrigger = <T extends ValidComponent = 'button'>(
|
||||||
props: PolymorphicProps<T, SelectTriggerProps<T>>
|
props: PolymorphicProps<T, SelectTriggerProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as SelectTriggerProps, ["class", "children"])
|
const [local, others] = splitProps(props as SelectTriggerProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<SelectPrimitive.Trigger
|
<SelectPrimitive.Trigger
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
'flex h-10 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -45,21 +48,21 @@ const SelectTrigger = <T extends ValidComponent = "button">(
|
|||||||
<path d="M16 15l-4 4l-4 -4" />
|
<path d="M16 15l-4 4l-4 -4" />
|
||||||
</SelectPrimitive.Icon>
|
</SelectPrimitive.Icon>
|
||||||
</SelectPrimitive.Trigger>
|
</SelectPrimitive.Trigger>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type SelectContentProps<T extends ValidComponent = "div"> =
|
type SelectContentProps<T extends ValidComponent = 'div'> =
|
||||||
SelectPrimitive.SelectContentProps<T> & { class?: string | undefined }
|
SelectPrimitive.SelectContentProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const SelectContent = <T extends ValidComponent = "div">(
|
const SelectContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, SelectContentProps<T>>
|
props: PolymorphicProps<T, SelectContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as SelectContentProps, ["class"])
|
const [local, others] = splitProps(props as SelectContentProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<SelectPrimitive.Portal>
|
<SelectPrimitive.Portal>
|
||||||
<SelectPrimitive.Content
|
<SelectPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative z-50 min-w-32 overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md animate-in fade-in-80",
|
'fade-in-80 relative z-50 min-w-32 animate-in overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -67,22 +70,26 @@ const SelectContent = <T extends ValidComponent = "div">(
|
|||||||
<SelectPrimitive.Listbox class="m-0 p-1" />
|
<SelectPrimitive.Listbox class="m-0 p-1" />
|
||||||
</SelectPrimitive.Content>
|
</SelectPrimitive.Content>
|
||||||
</SelectPrimitive.Portal>
|
</SelectPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type SelectItemProps<T extends ValidComponent = "li"> = SelectPrimitive.SelectItemProps<T> & {
|
type SelectItemProps<T extends ValidComponent = 'li'> =
|
||||||
class?: string | undefined
|
SelectPrimitive.SelectItemProps<T> & {
|
||||||
children?: JSX.Element
|
class?: string | undefined;
|
||||||
}
|
children?: JSX.Element;
|
||||||
|
};
|
||||||
|
|
||||||
const SelectItem = <T extends ValidComponent = "li">(
|
const SelectItem = <T extends ValidComponent = 'li'>(
|
||||||
props: PolymorphicProps<T, SelectItemProps<T>>
|
props: PolymorphicProps<T, SelectItemProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as SelectItemProps, ["class", "children"])
|
const [local, others] = splitProps(props as SelectItemProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<SelectPrimitive.Item
|
<SelectPrimitive.Item
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative mt-0 flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
'relative mt-0 flex w-full cursor-default select-none items-center rounded-sm py-1.5 pr-8 pl-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -104,69 +111,79 @@ const SelectItem = <T extends ValidComponent = "li">(
|
|||||||
</SelectPrimitive.ItemIndicator>
|
</SelectPrimitive.ItemIndicator>
|
||||||
<SelectPrimitive.ItemLabel>{local.children}</SelectPrimitive.ItemLabel>
|
<SelectPrimitive.ItemLabel>{local.children}</SelectPrimitive.ItemLabel>
|
||||||
</SelectPrimitive.Item>
|
</SelectPrimitive.Item>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const labelVariants = cva(
|
const labelVariants = cva(
|
||||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
'font-medium text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
label: "data-[invalid]:text-destructive",
|
label: 'data-[invalid]:text-destructive',
|
||||||
description: "font-normal text-muted-foreground",
|
description: 'font-normal text-muted-foreground',
|
||||||
error: "text-xs text-destructive"
|
error: 'text-destructive text-xs',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: "label"
|
variant: 'label',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
)
|
|
||||||
|
|
||||||
type SelectLabelProps<T extends ValidComponent = "label"> = SelectPrimitive.SelectLabelProps<T> & {
|
type SelectLabelProps<T extends ValidComponent = 'label'> =
|
||||||
class?: string | undefined
|
SelectPrimitive.SelectLabelProps<T> & {
|
||||||
}
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const SelectLabel = <T extends ValidComponent = "label">(
|
const SelectLabel = <T extends ValidComponent = 'label'>(
|
||||||
props: PolymorphicProps<T, SelectLabelProps<T>>
|
props: PolymorphicProps<T, SelectLabelProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as SelectLabelProps, ["class"])
|
const [local, others] = splitProps(props as SelectLabelProps, ['class']);
|
||||||
return <SelectPrimitive.Label class={cn(labelVariants(), local.class)} {...others} />
|
return (
|
||||||
}
|
<SelectPrimitive.Label
|
||||||
|
class={cn(labelVariants(), local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
type SelectDescriptionProps<T extends ValidComponent = "div"> =
|
type SelectDescriptionProps<T extends ValidComponent = 'div'> =
|
||||||
SelectPrimitive.SelectDescriptionProps<T> & {
|
SelectPrimitive.SelectDescriptionProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const SelectDescription = <T extends ValidComponent = "div">(
|
const SelectDescription = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, SelectDescriptionProps<T>>
|
props: PolymorphicProps<T, SelectDescriptionProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as SelectDescriptionProps, ["class"])
|
const [local, others] = splitProps(props as SelectDescriptionProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<SelectPrimitive.Description
|
<SelectPrimitive.Description
|
||||||
class={cn(labelVariants({ variant: "description" }), local.class)}
|
class={cn(labelVariants({ variant: 'description' }), local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type SelectErrorMessageProps<T extends ValidComponent = "div"> =
|
type SelectErrorMessageProps<T extends ValidComponent = 'div'> =
|
||||||
SelectPrimitive.SelectErrorMessageProps<T> & {
|
SelectPrimitive.SelectErrorMessageProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const SelectErrorMessage = <T extends ValidComponent = "div">(
|
const SelectErrorMessage = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, SelectErrorMessageProps<T>>
|
props: PolymorphicProps<T, SelectErrorMessageProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as SelectErrorMessageProps, ["class"])
|
const [local, others] = splitProps(props as SelectErrorMessageProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<SelectPrimitive.ErrorMessage
|
<SelectPrimitive.ErrorMessage
|
||||||
class={cn(labelVariants({ variant: "error" }), local.class)}
|
class={cn(labelVariants({ variant: 'error' }), local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Select,
|
Select,
|
||||||
@@ -177,5 +194,5 @@ export {
|
|||||||
SelectItem,
|
SelectItem,
|
||||||
SelectLabel,
|
SelectLabel,
|
||||||
SelectDescription,
|
SelectDescription,
|
||||||
SelectErrorMessage
|
SelectErrorMessage,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,29 +1,32 @@
|
|||||||
import type { ValidComponent } from "solid-js"
|
import type { ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
import * as SeparatorPrimitive from "@kobalte/core/separator"
|
import * as SeparatorPrimitive from '@kobalte/core/separator';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
type SeparatorRootProps<T extends ValidComponent = "hr"> =
|
type SeparatorRootProps<T extends ValidComponent = 'hr'> =
|
||||||
SeparatorPrimitive.SeparatorRootProps<T> & { class?: string | undefined }
|
SeparatorPrimitive.SeparatorRootProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const Separator = <T extends ValidComponent = "hr">(
|
const Separator = <T extends ValidComponent = 'hr'>(
|
||||||
props: PolymorphicProps<T, SeparatorRootProps<T>>
|
props: PolymorphicProps<T, SeparatorRootProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as SeparatorRootProps, ["class", "orientation"])
|
const [local, others] = splitProps(props as SeparatorRootProps, [
|
||||||
|
'class',
|
||||||
|
'orientation',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<SeparatorPrimitive.Root
|
<SeparatorPrimitive.Root
|
||||||
orientation={local.orientation ?? "horizontal"}
|
orientation={local.orientation ?? 'horizontal'}
|
||||||
class={cn(
|
class={cn(
|
||||||
"shrink-0 bg-border",
|
'shrink-0 bg-border',
|
||||||
local.orientation === "vertical" ? "h-full w-px" : "h-px w-full",
|
local.orientation === 'vertical' ? 'h-full w-px' : 'h-px w-full',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Separator }
|
export { Separator };
|
||||||
|
|||||||
@@ -1,84 +1,96 @@
|
|||||||
import type { Component, ComponentProps, JSX, ValidComponent } from "solid-js"
|
import type { Component, ComponentProps, JSX, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import * as SheetPrimitive from "@kobalte/core/dialog"
|
import * as SheetPrimitive from '@kobalte/core/dialog';
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
import { cva, type VariantProps } from "class-variance-authority"
|
import { type VariantProps, cva } from 'class-variance-authority';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const Sheet = SheetPrimitive.Root
|
const Sheet = SheetPrimitive.Root;
|
||||||
const SheetTrigger = SheetPrimitive.Trigger
|
const SheetTrigger = SheetPrimitive.Trigger;
|
||||||
const SheetClose = SheetPrimitive.CloseButton
|
const SheetClose = SheetPrimitive.CloseButton;
|
||||||
|
|
||||||
const portalVariants = cva("fixed inset-0 z-50 flex", {
|
const portalVariants = cva('fixed inset-0 z-50 flex', {
|
||||||
variants: {
|
variants: {
|
||||||
position: {
|
position: {
|
||||||
top: "items-start",
|
top: 'items-start',
|
||||||
bottom: "items-end",
|
bottom: 'items-end',
|
||||||
left: "justify-start",
|
left: 'justify-start',
|
||||||
right: "justify-end"
|
right: 'justify-end',
|
||||||
}
|
|
||||||
},
|
},
|
||||||
defaultVariants: { position: "right" }
|
},
|
||||||
})
|
defaultVariants: { position: 'right' },
|
||||||
|
});
|
||||||
|
|
||||||
type PortalProps = SheetPrimitive.DialogPortalProps & VariantProps<typeof portalVariants>
|
type PortalProps = SheetPrimitive.DialogPortalProps &
|
||||||
|
VariantProps<typeof portalVariants>;
|
||||||
|
|
||||||
const SheetPortal: Component<PortalProps> = (props) => {
|
const SheetPortal: Component<PortalProps> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["position", "children"])
|
const [local, others] = splitProps(props, ['position', 'children']);
|
||||||
return (
|
return (
|
||||||
<SheetPrimitive.Portal {...others}>
|
<SheetPrimitive.Portal {...others}>
|
||||||
<div class={portalVariants({ position: local.position })}>{local.children}</div>
|
<div class={portalVariants({ position: local.position })}>
|
||||||
|
{local.children}
|
||||||
|
</div>
|
||||||
</SheetPrimitive.Portal>
|
</SheetPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DialogOverlayProps<T extends ValidComponent = "div"> = SheetPrimitive.DialogOverlayProps<T> & {
|
type DialogOverlayProps<T extends ValidComponent = 'div'> =
|
||||||
class?: string | undefined
|
SheetPrimitive.DialogOverlayProps<T> & {
|
||||||
}
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const SheetOverlay = <T extends ValidComponent = "div">(
|
const SheetOverlay = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, DialogOverlayProps<T>>
|
props: PolymorphicProps<T, DialogOverlayProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as DialogOverlayProps, ["class"])
|
const [local, others] = splitProps(props as DialogOverlayProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<SheetPrimitive.Overlay
|
<SheetPrimitive.Overlay
|
||||||
class={cn(
|
class={cn(
|
||||||
"fixed inset-0 z-50 bg-black/80 data-[expanded=]:animate-in data-[closed=]:animate-out data-[closed=]:fade-out-0 data-[expanded=]:fade-in-0",
|
'data-[closed=]:fade-out-0 data-[expanded=]:fade-in-0 fixed inset-0 z-50 bg-black/80 data-[closed=]:animate-out data-[expanded=]:animate-in',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const sheetVariants = cva(
|
const sheetVariants = cva(
|
||||||
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[closed=]:duration-300 data-[expanded=]:duration-500 data-[expanded=]:animate-in data-[closed=]:animate-out",
|
'fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[closed=]:animate-out data-[expanded=]:animate-in data-[closed=]:duration-300 data-[expanded=]:duration-500',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
position: {
|
position: {
|
||||||
top: "inset-x-0 top-0 border-b data-[closed=]:slide-out-to-top data-[expanded=]:slide-in-from-top",
|
top: 'data-[closed=]:slide-out-to-top data-[expanded=]:slide-in-from-top inset-x-0 top-0 border-b',
|
||||||
bottom:
|
bottom:
|
||||||
"inset-x-0 bottom-0 border-t data-[closed=]:slide-out-to-bottom data-[expanded=]:slide-in-from-bottom",
|
'data-[closed=]:slide-out-to-bottom data-[expanded=]:slide-in-from-bottom inset-x-0 bottom-0 border-t',
|
||||||
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[closed=]:slide-out-to-left data-[expanded=]:slide-in-from-left sm:max-w-sm",
|
left: 'data-[closed=]:slide-out-to-left data-[expanded=]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm',
|
||||||
right:
|
right:
|
||||||
"inset-y-0 right-0 h-full w-3/4 border-l data-[closed=]:slide-out-to-right data-[expanded=]:slide-in-from-right sm:max-w-sm"
|
'data-[closed=]:slide-out-to-right data-[expanded=]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
position: "right"
|
position: 'right',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
)
|
|
||||||
|
|
||||||
type DialogContentProps<T extends ValidComponent = "div"> = SheetPrimitive.DialogContentProps<T> &
|
type DialogContentProps<T extends ValidComponent = 'div'> =
|
||||||
VariantProps<typeof sheetVariants> & { class?: string | undefined; children?: JSX.Element }
|
SheetPrimitive.DialogContentProps<T> &
|
||||||
|
VariantProps<typeof sheetVariants> & {
|
||||||
|
class?: string | undefined;
|
||||||
|
children?: JSX.Element;
|
||||||
|
};
|
||||||
|
|
||||||
const SheetContent = <T extends ValidComponent = "div">(
|
const SheetContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, DialogContentProps<T>>
|
props: PolymorphicProps<T, DialogContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as DialogContentProps, ["position", "class", "children"])
|
const [local, others] = splitProps(props as DialogContentProps, [
|
||||||
|
'position',
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<SheetPortal position={local.position}>
|
<SheetPortal position={local.position}>
|
||||||
<SheetOverlay />
|
<SheetOverlay />
|
||||||
@@ -86,12 +98,12 @@ const SheetContent = <T extends ValidComponent = "div">(
|
|||||||
class={cn(
|
class={cn(
|
||||||
sheetVariants({ position: local.position }),
|
sheetVariants({ position: local.position }),
|
||||||
local.class,
|
local.class,
|
||||||
"max-h-screen overflow-y-auto"
|
'max-h-screen overflow-y-auto'
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
>
|
>
|
||||||
{local.children}
|
{local.children}
|
||||||
<SheetPrimitive.CloseButton class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
|
<SheetPrimitive.CloseButton class="absolute top-4 right-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
@@ -109,56 +121,68 @@ const SheetContent = <T extends ValidComponent = "div">(
|
|||||||
</SheetPrimitive.CloseButton>
|
</SheetPrimitive.CloseButton>
|
||||||
</SheetPrimitive.Content>
|
</SheetPrimitive.Content>
|
||||||
</SheetPortal>
|
</SheetPortal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const SheetHeader: Component<ComponentProps<"div">> = (props) => {
|
const SheetHeader: Component<ComponentProps<'div'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
|
||||||
<div class={cn("flex flex-col space-y-2 text-center sm:text-left", local.class)} {...others} />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const SheetFooter: Component<ComponentProps<"div">> = (props) => {
|
|
||||||
const [local, others] = splitProps(props, ["class"])
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", local.class)}
|
class={cn(
|
||||||
|
'flex flex-col space-y-2 text-center sm:text-left',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DialogTitleProps<T extends ValidComponent = "h2"> = SheetPrimitive.DialogTitleProps<T> & {
|
const SheetFooter: Component<ComponentProps<'div'>> = (props) => {
|
||||||
class?: string | undefined
|
const [local, others] = splitProps(props, ['class']);
|
||||||
}
|
return (
|
||||||
|
<div
|
||||||
|
class={cn(
|
||||||
|
'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const SheetTitle = <T extends ValidComponent = "h2">(
|
type DialogTitleProps<T extends ValidComponent = 'h2'> =
|
||||||
|
SheetPrimitive.DialogTitleProps<T> & {
|
||||||
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const SheetTitle = <T extends ValidComponent = 'h2'>(
|
||||||
props: PolymorphicProps<T, DialogTitleProps<T>>
|
props: PolymorphicProps<T, DialogTitleProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as DialogTitleProps, ["class"])
|
const [local, others] = splitProps(props as DialogTitleProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<SheetPrimitive.Title
|
<SheetPrimitive.Title
|
||||||
class={cn("text-lg font-semibold text-foreground", local.class)}
|
class={cn('font-semibold text-foreground text-lg', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type DialogDescriptionProps<T extends ValidComponent = "p"> =
|
type DialogDescriptionProps<T extends ValidComponent = 'p'> =
|
||||||
SheetPrimitive.DialogDescriptionProps<T> & { class?: string | undefined }
|
SheetPrimitive.DialogDescriptionProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const SheetDescription = <T extends ValidComponent = "p">(
|
const SheetDescription = <T extends ValidComponent = 'p'>(
|
||||||
props: PolymorphicProps<T, DialogDescriptionProps<T>>
|
props: PolymorphicProps<T, DialogDescriptionProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as DialogDescriptionProps, ["class"])
|
const [local, others] = splitProps(props as DialogDescriptionProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<SheetPrimitive.Description
|
<SheetPrimitive.Description
|
||||||
class={cn("text-sm text-muted-foreground", local.class)}
|
class={cn('text-muted-foreground text-sm', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Sheet,
|
Sheet,
|
||||||
@@ -168,5 +192,5 @@ export {
|
|||||||
SheetHeader,
|
SheetHeader,
|
||||||
SheetFooter,
|
SheetFooter,
|
||||||
SheetTitle,
|
SheetTitle,
|
||||||
SheetDescription
|
SheetDescription,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import {
|
|||||||
TooltipContent,
|
TooltipContent,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from '~/components/ui/tooltip';
|
} from '~/components/ui/tooltip';
|
||||||
import { cn } from '~/styles/utils';
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const MOBILE_BREAKPOINT = 768;
|
const MOBILE_BREAKPOINT = 768;
|
||||||
const SIDEBAR_COOKIE_NAME = 'sidebar:state';
|
const SIDEBAR_COOKIE_NAME = 'sidebar:state';
|
||||||
|
|||||||
@@ -1,24 +1,27 @@
|
|||||||
import type { ValidComponent } from "solid-js"
|
import type { ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
import * as SkeletonPrimitive from "@kobalte/core/skeleton"
|
import * as SkeletonPrimitive from '@kobalte/core/skeleton';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
type SkeletonRootProps<T extends ValidComponent = "div"> =
|
type SkeletonRootProps<T extends ValidComponent = 'div'> =
|
||||||
SkeletonPrimitive.SkeletonRootProps<T> & { class?: string | undefined }
|
SkeletonPrimitive.SkeletonRootProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const Skeleton = <T extends ValidComponent = "div">(
|
const Skeleton = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, SkeletonRootProps<T>>
|
props: PolymorphicProps<T, SkeletonRootProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as SkeletonRootProps, ["class"])
|
const [local, others] = splitProps(props as SkeletonRootProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<SkeletonPrimitive.Root
|
<SkeletonPrimitive.Root
|
||||||
class={cn("bg-primary/10 data-[animate='true']:animate-pulse", local.class)}
|
class={cn(
|
||||||
|
"bg-primary/10 data-[animate='true']:animate-pulse",
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Skeleton }
|
export { Skeleton };
|
||||||
|
|||||||
@@ -1,92 +1,112 @@
|
|||||||
import type { JSX, ValidComponent } from "solid-js"
|
import type { JSX, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
import * as SliderPrimitive from "@kobalte/core/slider"
|
import * as SliderPrimitive from '@kobalte/core/slider';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { Label } from '~/components/ui/label';
|
||||||
import { Label } from "~/components/ui/label"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
type SliderRootProps<T extends ValidComponent = "div"> = SliderPrimitive.SliderRootProps<T> & {
|
type SliderRootProps<T extends ValidComponent = 'div'> =
|
||||||
class?: string | undefined
|
SliderPrimitive.SliderRootProps<T> & {
|
||||||
}
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const Slider = <T extends ValidComponent = "div">(
|
const Slider = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, SliderRootProps<T>>
|
props: PolymorphicProps<T, SliderRootProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as SliderRootProps, ["class"])
|
const [local, others] = splitProps(props as SliderRootProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<SliderPrimitive.Root
|
<SliderPrimitive.Root
|
||||||
class={cn("relative flex w-full touch-none select-none flex-col items-center", local.class)}
|
class={cn(
|
||||||
|
'relative flex w-full touch-none select-none flex-col items-center',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type SliderTrackProps<T extends ValidComponent = "div"> = SliderPrimitive.SliderTrackProps<T> & {
|
type SliderTrackProps<T extends ValidComponent = 'div'> =
|
||||||
class?: string | undefined
|
SliderPrimitive.SliderTrackProps<T> & {
|
||||||
}
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const SliderTrack = <T extends ValidComponent = "div">(
|
const SliderTrack = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, SliderTrackProps<T>>
|
props: PolymorphicProps<T, SliderTrackProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as SliderTrackProps, ["class"])
|
const [local, others] = splitProps(props as SliderTrackProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<SliderPrimitive.Track
|
<SliderPrimitive.Track
|
||||||
class={cn("relative h-2 w-full grow rounded-full bg-secondary", local.class)}
|
class={cn(
|
||||||
|
'relative h-2 w-full grow rounded-full bg-secondary',
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type SliderFillProps<T extends ValidComponent = "div"> = SliderPrimitive.SliderFillProps<T> & {
|
type SliderFillProps<T extends ValidComponent = 'div'> =
|
||||||
class?: string | undefined
|
SliderPrimitive.SliderFillProps<T> & {
|
||||||
}
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const SliderFill = <T extends ValidComponent = "div">(
|
const SliderFill = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, SliderFillProps<T>>
|
props: PolymorphicProps<T, SliderFillProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as SliderFillProps, ["class"])
|
const [local, others] = splitProps(props as SliderFillProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<SliderPrimitive.Fill
|
<SliderPrimitive.Fill
|
||||||
class={cn("absolute h-full rounded-full bg-primary", local.class)}
|
class={cn('absolute h-full rounded-full bg-primary', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type SliderThumbProps<T extends ValidComponent = "span"> = SliderPrimitive.SliderThumbProps<T> & {
|
type SliderThumbProps<T extends ValidComponent = 'span'> =
|
||||||
class?: string | undefined
|
SliderPrimitive.SliderThumbProps<T> & {
|
||||||
children?: JSX.Element
|
class?: string | undefined;
|
||||||
}
|
children?: JSX.Element;
|
||||||
|
};
|
||||||
|
|
||||||
const SliderThumb = <T extends ValidComponent = "span">(
|
const SliderThumb = <T extends ValidComponent = 'span'>(
|
||||||
props: PolymorphicProps<T, SliderThumbProps<T>>
|
props: PolymorphicProps<T, SliderThumbProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as SliderThumbProps, ["class", "children"])
|
const [local, others] = splitProps(props as SliderThumbProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<SliderPrimitive.Thumb
|
<SliderPrimitive.Thumb
|
||||||
class={cn(
|
class={cn(
|
||||||
"top-[-6px] block size-5 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
'top-[-6px] block size-5 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
>
|
>
|
||||||
<SliderPrimitive.Input />
|
<SliderPrimitive.Input />
|
||||||
</SliderPrimitive.Thumb>
|
</SliderPrimitive.Thumb>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const SliderLabel = <T extends ValidComponent = "label">(
|
const SliderLabel = <T extends ValidComponent = 'label'>(
|
||||||
props: PolymorphicProps<T, SliderPrimitive.SliderLabelProps<T>>
|
props: PolymorphicProps<T, SliderPrimitive.SliderLabelProps<T>>
|
||||||
) => {
|
) => {
|
||||||
return <SliderPrimitive.Label as={Label} {...props} />
|
return <SliderPrimitive.Label as={Label} {...props} />;
|
||||||
}
|
};
|
||||||
|
|
||||||
const SliderValueLabel = <T extends ValidComponent = "label">(
|
const SliderValueLabel = <T extends ValidComponent = 'label'>(
|
||||||
props: PolymorphicProps<T, SliderPrimitive.SliderValueLabelProps<T>>
|
props: PolymorphicProps<T, SliderPrimitive.SliderValueLabelProps<T>>
|
||||||
) => {
|
) => {
|
||||||
return <SliderPrimitive.ValueLabel as={Label} {...props} />
|
return <SliderPrimitive.ValueLabel as={Label} {...props} />;
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Slider, SliderTrack, SliderFill, SliderThumb, SliderLabel, SliderValueLabel }
|
export {
|
||||||
|
Slider,
|
||||||
|
SliderTrack,
|
||||||
|
SliderFill,
|
||||||
|
SliderThumb,
|
||||||
|
SliderLabel,
|
||||||
|
SliderValueLabel,
|
||||||
|
};
|
||||||
|
|||||||
287
apps/webui/src/components/ui/spinner.tsx
Normal file
287
apps/webui/src/components/ui/spinner.tsx
Normal file
@@ -0,0 +1,287 @@
|
|||||||
|
import {
|
||||||
|
LoaderCircleIcon,
|
||||||
|
LoaderIcon,
|
||||||
|
LoaderPinwheelIcon,
|
||||||
|
type LucideProps,
|
||||||
|
} from 'lucide-solid';
|
||||||
|
import { mergeProps, splitProps } from 'solid-js';
|
||||||
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
|
type SpinnerVariantProps = Omit<SpinnerProps, 'variant'>;
|
||||||
|
|
||||||
|
const Default = (props: SpinnerVariantProps) => {
|
||||||
|
const [local, other] = splitProps(props, ['class']);
|
||||||
|
return <LoaderIcon class={cn('animate-spin', local.class)} {...other} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Circle = (props: SpinnerVariantProps) => {
|
||||||
|
const [local, other] = splitProps(props, ['class']);
|
||||||
|
return (
|
||||||
|
<LoaderCircleIcon class={cn('animate-spin', local.class)} {...other} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Pinwheel = (props: SpinnerVariantProps) => {
|
||||||
|
const [local, other] = splitProps(props, ['class']);
|
||||||
|
return (
|
||||||
|
<LoaderPinwheelIcon class={cn('animate-spin', local.class)} {...other} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const CircleFilled = (props: SpinnerVariantProps) => {
|
||||||
|
const [local, _] = splitProps(mergeProps({ size: 24 }, props), [
|
||||||
|
'class',
|
||||||
|
'size',
|
||||||
|
]);
|
||||||
|
const size = `${local.size}`;
|
||||||
|
return (
|
||||||
|
<div class="relative" style={{ width: size, height: size }}>
|
||||||
|
<div class="absolute inset-0 rotate-180">
|
||||||
|
<LoaderCircleIcon
|
||||||
|
class={cn('animate-spin', local.class, 'text-foreground opacity-20')}
|
||||||
|
size={size}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<LoaderCircleIcon
|
||||||
|
class={cn('relative animate-spin', local.class)}
|
||||||
|
size={size}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Ellipsis = (props: SpinnerVariantProps) => {
|
||||||
|
const [{ size = 24 }, other] = splitProps(props, ['size']);
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width={size}
|
||||||
|
height={size}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
{...other}
|
||||||
|
>
|
||||||
|
<title>Loading...</title>
|
||||||
|
<circle cx="4" cy="12" r="2" fill="currentColor">
|
||||||
|
<animate
|
||||||
|
id="ellipsis1"
|
||||||
|
begin="0;ellipsis3.end+0.25s"
|
||||||
|
attributeName="cy"
|
||||||
|
calcMode="spline"
|
||||||
|
dur="0.6s"
|
||||||
|
values="12;6;12"
|
||||||
|
keySplines=".33,.66,.66,1;.33,0,.66,.33"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
<circle cx="12" cy="12" r="2" fill="currentColor">
|
||||||
|
<animate
|
||||||
|
begin="ellipsis1.begin+0.1s"
|
||||||
|
attributeName="cy"
|
||||||
|
calcMode="spline"
|
||||||
|
dur="0.6s"
|
||||||
|
values="12;6;12"
|
||||||
|
keySplines=".33,.66,.66,1;.33,0,.66,.33"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
<circle cx="20" cy="12" r="2" fill="currentColor">
|
||||||
|
<animate
|
||||||
|
id="ellipsis3"
|
||||||
|
begin="ellipsis1.begin+0.2s"
|
||||||
|
attributeName="cy"
|
||||||
|
calcMode="spline"
|
||||||
|
dur="0.6s"
|
||||||
|
values="12;6;12"
|
||||||
|
keySplines=".33,.66,.66,1;.33,0,.66,.33"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Ring = (props: SpinnerVariantProps) => {
|
||||||
|
const [{ size = 24 }, other] = splitProps(props, ['size']);
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width={size}
|
||||||
|
height={size}
|
||||||
|
viewBox="0 0 44 44"
|
||||||
|
stroke="currentColor"
|
||||||
|
{...other}
|
||||||
|
>
|
||||||
|
<title>Loading...</title>
|
||||||
|
<g fill="none" fill-rule="evenodd" stroke-width="2">
|
||||||
|
<circle cx="22" cy="22" r="1">
|
||||||
|
<animate
|
||||||
|
attributeName="r"
|
||||||
|
begin="0s"
|
||||||
|
dur="1.8s"
|
||||||
|
values="1; 20"
|
||||||
|
calcMode="spline"
|
||||||
|
keyTimes="0; 1"
|
||||||
|
keySplines="0.165, 0.84, 0.44, 1"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="stroke-opacity"
|
||||||
|
begin="0s"
|
||||||
|
dur="1.8s"
|
||||||
|
values="1; 0"
|
||||||
|
calcMode="spline"
|
||||||
|
keyTimes="0; 1"
|
||||||
|
keySplines="0.3, 0.61, 0.355, 1"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
<circle cx="22" cy="22" r="1">
|
||||||
|
<animate
|
||||||
|
attributeName="r"
|
||||||
|
begin="-0.9s"
|
||||||
|
dur="1.8s"
|
||||||
|
values="1; 20"
|
||||||
|
calcMode="spline"
|
||||||
|
keyTimes="0; 1"
|
||||||
|
keySplines="0.165, 0.84, 0.44, 1"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
<animate
|
||||||
|
attributeName="stroke-opacity"
|
||||||
|
begin="-0.9s"
|
||||||
|
dur="1.8s"
|
||||||
|
values="1; 0"
|
||||||
|
calcMode="spline"
|
||||||
|
keyTimes="0; 1"
|
||||||
|
keySplines="0.3, 0.61, 0.355, 1"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Bars = ({ size = 24, ...props }: SpinnerVariantProps) => (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width={size}
|
||||||
|
height={size}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<title>Loading...</title>
|
||||||
|
<style>{`
|
||||||
|
.spinner-bar {
|
||||||
|
animation: spinner-bars-animation .8s linear infinite;
|
||||||
|
animation-delay: -.8s;
|
||||||
|
}
|
||||||
|
.spinner-bars-2 {
|
||||||
|
animation-delay: -.65s;
|
||||||
|
}
|
||||||
|
.spinner-bars-3 {
|
||||||
|
animation-delay: -0.5s;
|
||||||
|
}
|
||||||
|
@keyframes spinner-bars-animation {
|
||||||
|
0% {
|
||||||
|
y: 1px;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
93.75% {
|
||||||
|
y: 5px;
|
||||||
|
height: 14px;
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
<rect
|
||||||
|
class="spinner-bar"
|
||||||
|
x="1"
|
||||||
|
y="1"
|
||||||
|
width="6"
|
||||||
|
height="22"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
class="spinner-bar spinner-bars-2"
|
||||||
|
x="9"
|
||||||
|
y="1"
|
||||||
|
width="6"
|
||||||
|
height="22"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
class="spinner-bar spinner-bars-3"
|
||||||
|
x="17"
|
||||||
|
y="1"
|
||||||
|
width="6"
|
||||||
|
height="22"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
const Infinite = ({ size = 24, ...props }: SpinnerVariantProps) => (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width={size}
|
||||||
|
height={size}
|
||||||
|
viewBox="0 0 100 100"
|
||||||
|
preserveAspectRatio="xMidYMid"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<title>Loading...</title>
|
||||||
|
<path
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="10"
|
||||||
|
stroke-dasharray="205.271142578125 51.317785644531256"
|
||||||
|
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"
|
||||||
|
stroke-linecap="round"
|
||||||
|
style={{
|
||||||
|
transform: 'scale(0.8)',
|
||||||
|
'transform-origin': '50px 50px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="stroke-dashoffset"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
dur="2s"
|
||||||
|
keyTimes="0;1"
|
||||||
|
values="0;256.58892822265625"
|
||||||
|
/>
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
export type SpinnerProps = LucideProps & {
|
||||||
|
variant?:
|
||||||
|
| 'default'
|
||||||
|
| 'circle'
|
||||||
|
| 'pinwheel'
|
||||||
|
| 'circle-filled'
|
||||||
|
| 'ellipsis'
|
||||||
|
| 'ring'
|
||||||
|
| 'bars'
|
||||||
|
| 'infinite';
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Spinner = ({ variant, ...props }: SpinnerProps) => {
|
||||||
|
switch (variant) {
|
||||||
|
case 'circle':
|
||||||
|
return <Circle {...props} />;
|
||||||
|
case 'pinwheel':
|
||||||
|
return <Pinwheel {...props} />;
|
||||||
|
case 'circle-filled':
|
||||||
|
return <CircleFilled {...props} />;
|
||||||
|
case 'ellipsis':
|
||||||
|
return <Ellipsis {...props} />;
|
||||||
|
case 'ring':
|
||||||
|
return <Ring {...props} />;
|
||||||
|
case 'bars':
|
||||||
|
return <Bars {...props} />;
|
||||||
|
case 'infinite':
|
||||||
|
return <Infinite {...props} />;
|
||||||
|
default:
|
||||||
|
return <Default {...props} />;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,35 +1,38 @@
|
|||||||
import type { JSX, ValidComponent } from "solid-js"
|
import type { JSX, ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { PolymorphicProps } from "@kobalte/core"
|
import type { PolymorphicProps } from '@kobalte/core';
|
||||||
import * as SwitchPrimitive from "@kobalte/core/switch"
|
import * as SwitchPrimitive from '@kobalte/core/switch';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const Switch = SwitchPrimitive.Root
|
const Switch = SwitchPrimitive.Root;
|
||||||
const SwitchDescription = SwitchPrimitive.Description
|
const SwitchDescription = SwitchPrimitive.Description;
|
||||||
const SwitchErrorMessage = SwitchPrimitive.ErrorMessage
|
const SwitchErrorMessage = SwitchPrimitive.ErrorMessage;
|
||||||
|
|
||||||
type SwitchControlProps = SwitchPrimitive.SwitchControlProps & {
|
type SwitchControlProps = SwitchPrimitive.SwitchControlProps & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
children?: JSX.Element
|
children?: JSX.Element;
|
||||||
}
|
};
|
||||||
|
|
||||||
const SwitchControl = <T extends ValidComponent = "input">(
|
const SwitchControl = <T extends ValidComponent = 'input'>(
|
||||||
props: PolymorphicProps<T, SwitchControlProps>
|
props: PolymorphicProps<T, SwitchControlProps>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as SwitchControlProps, ["class", "children"])
|
const [local, others] = splitProps(props as SwitchControlProps, [
|
||||||
|
'class',
|
||||||
|
'children',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SwitchPrimitive.Input
|
<SwitchPrimitive.Input
|
||||||
class={cn(
|
class={cn(
|
||||||
"[&:focus-visible+div]:outline-none [&:focus-visible+div]:ring-2 [&:focus-visible+div]:ring-ring [&:focus-visible+div]:ring-offset-2 [&:focus-visible+div]:ring-offset-background",
|
'[&:focus-visible+div]:outline-none [&:focus-visible+div]:ring-2 [&:focus-visible+div]:ring-ring [&:focus-visible+div]:ring-offset-2 [&:focus-visible+div]:ring-offset-background',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<SwitchPrimitive.Control
|
<SwitchPrimitive.Control
|
||||||
class={cn(
|
class={cn(
|
||||||
"inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent bg-input transition-[color,background-color,box-shadow] data-[disabled]:cursor-not-allowed data-[checked]:bg-primary data-[disabled]:opacity-50",
|
'inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent bg-input transition-[color,background-color,box-shadow] data-[disabled]:cursor-not-allowed data-[checked]:bg-primary data-[disabled]:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -37,41 +40,52 @@ const SwitchControl = <T extends ValidComponent = "input">(
|
|||||||
{local.children}
|
{local.children}
|
||||||
</SwitchPrimitive.Control>
|
</SwitchPrimitive.Control>
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type SwitchThumbProps = SwitchPrimitive.SwitchThumbProps & { class?: string | undefined }
|
type SwitchThumbProps = SwitchPrimitive.SwitchThumbProps & {
|
||||||
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const SwitchThumb = <T extends ValidComponent = "div">(
|
const SwitchThumb = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, SwitchThumbProps>
|
props: PolymorphicProps<T, SwitchThumbProps>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as SwitchThumbProps, ["class"])
|
const [local, others] = splitProps(props as SwitchThumbProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<SwitchPrimitive.Thumb
|
<SwitchPrimitive.Thumb
|
||||||
class={cn(
|
class={cn(
|
||||||
"pointer-events-none block size-5 translate-x-0 rounded-full bg-background shadow-lg ring-0 transition-transform data-[checked]:translate-x-5",
|
'pointer-events-none block size-5 translate-x-0 rounded-full bg-background shadow-lg ring-0 transition-transform data-[checked]:translate-x-5',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type SwitchLabelProps = SwitchPrimitive.SwitchLabelProps & { class?: string | undefined }
|
type SwitchLabelProps = SwitchPrimitive.SwitchLabelProps & {
|
||||||
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const SwitchLabel = <T extends ValidComponent = "label">(
|
const SwitchLabel = <T extends ValidComponent = 'label'>(
|
||||||
props: PolymorphicProps<T, SwitchLabelProps>
|
props: PolymorphicProps<T, SwitchLabelProps>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as SwitchLabelProps, ["class"])
|
const [local, others] = splitProps(props as SwitchLabelProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<SwitchPrimitive.Label
|
<SwitchPrimitive.Label
|
||||||
class={cn(
|
class={cn(
|
||||||
"text-sm font-medium leading-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-70",
|
'font-medium text-sm leading-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-70',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Switch, SwitchControl, SwitchThumb, SwitchLabel, SwitchDescription, SwitchErrorMessage }
|
export {
|
||||||
|
Switch,
|
||||||
|
SwitchControl,
|
||||||
|
SwitchThumb,
|
||||||
|
SwitchLabel,
|
||||||
|
SwitchDescription,
|
||||||
|
SwitchErrorMessage,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,70 +1,95 @@
|
|||||||
import type { Component, ComponentProps } from "solid-js"
|
import type { Component, ComponentProps } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const Table: Component<ComponentProps<"table">> = (props) => {
|
const Table: Component<ComponentProps<'table'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<div class="relative w-full overflow-auto">
|
<div class="relative w-full overflow-auto">
|
||||||
<table class={cn("w-full caption-bottom text-sm", local.class)} {...others} />
|
<table
|
||||||
|
class={cn('w-full caption-bottom text-sm', local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const TableHeader: Component<ComponentProps<"thead">> = (props) => {
|
const TableHeader: Component<ComponentProps<'thead'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <thead class={cn("[&_tr]:border-b", local.class)} {...others} />
|
return <thead class={cn('[&_tr]:border-b', local.class)} {...others} />;
|
||||||
}
|
};
|
||||||
|
|
||||||
const TableBody: Component<ComponentProps<"tbody">> = (props) => {
|
const TableBody: Component<ComponentProps<'tbody'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <tbody class={cn("[&_tr:last-child]:border-0", local.class)} {...others} />
|
|
||||||
}
|
|
||||||
|
|
||||||
const TableFooter: Component<ComponentProps<"tfoot">> = (props) => {
|
|
||||||
const [local, others] = splitProps(props, ["class"])
|
|
||||||
return (
|
return (
|
||||||
<tfoot class={cn("bg-primary font-medium text-primary-foreground", local.class)} {...others} />
|
<tbody class={cn('[&_tr:last-child]:border-0', local.class)} {...others} />
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const TableRow: Component<ComponentProps<"tr">> = (props) => {
|
const TableFooter: Component<ComponentProps<'tfoot'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
|
return (
|
||||||
|
<tfoot
|
||||||
|
class={cn('bg-primary font-medium text-primary-foreground', local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const TableRow: Component<ComponentProps<'tr'>> = (props) => {
|
||||||
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<tr
|
<tr
|
||||||
class={cn(
|
class={cn(
|
||||||
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
|
'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const TableHead: Component<ComponentProps<"th">> = (props) => {
|
const TableHead: Component<ComponentProps<'th'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<th
|
<th
|
||||||
class={cn(
|
class={cn(
|
||||||
"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
|
'h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const TableCell: Component<ComponentProps<"td">> = (props) => {
|
const TableCell: Component<ComponentProps<'td'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return (
|
return (
|
||||||
<td class={cn("p-2 align-middle [&:has([role=checkbox])]:pr-0", local.class)} {...others} />
|
<td
|
||||||
)
|
class={cn('p-2 align-middle [&:has([role=checkbox])]:pr-0', local.class)}
|
||||||
}
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const TableCaption: Component<ComponentProps<"caption">> = (props) => {
|
const TableCaption: Component<ComponentProps<'caption'>> = (props) => {
|
||||||
const [local, others] = splitProps(props, ["class"])
|
const [local, others] = splitProps(props, ['class']);
|
||||||
return <caption class={cn("mt-4 text-sm text-muted-foreground", local.class)} {...others} />
|
return (
|
||||||
}
|
<caption
|
||||||
|
class={cn('mt-4 text-muted-foreground text-sm', local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption }
|
export {
|
||||||
|
Table,
|
||||||
|
TableHeader,
|
||||||
|
TableBody,
|
||||||
|
TableFooter,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
TableCell,
|
||||||
|
TableCaption,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,87 +1,91 @@
|
|||||||
import type { ValidComponent } from "solid-js"
|
import type { ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
import * as TabsPrimitive from "@kobalte/core/tabs"
|
import * as TabsPrimitive from '@kobalte/core/tabs';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const Tabs = TabsPrimitive.Root
|
const Tabs = TabsPrimitive.Root;
|
||||||
|
|
||||||
type TabsListProps<T extends ValidComponent = "div"> = TabsPrimitive.TabsListProps<T> & {
|
type TabsListProps<T extends ValidComponent = 'div'> =
|
||||||
class?: string | undefined
|
TabsPrimitive.TabsListProps<T> & {
|
||||||
}
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const TabsList = <T extends ValidComponent = "div">(
|
const TabsList = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, TabsListProps<T>>
|
props: PolymorphicProps<T, TabsListProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as TabsListProps, ["class"])
|
const [local, others] = splitProps(props as TabsListProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<TabsPrimitive.List
|
<TabsPrimitive.List
|
||||||
class={cn(
|
class={cn(
|
||||||
"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
|
'inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type TabsTriggerProps<T extends ValidComponent = "button"> = TabsPrimitive.TabsTriggerProps<T> & {
|
type TabsTriggerProps<T extends ValidComponent = 'button'> =
|
||||||
class?: string | undefined
|
TabsPrimitive.TabsTriggerProps<T> & {
|
||||||
}
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const TabsTrigger = <T extends ValidComponent = "button">(
|
const TabsTrigger = <T extends ValidComponent = 'button'>(
|
||||||
props: PolymorphicProps<T, TabsTriggerProps<T>>
|
props: PolymorphicProps<T, TabsTriggerProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as TabsTriggerProps, ["class"])
|
const [local, others] = splitProps(props as TabsTriggerProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<TabsPrimitive.Trigger
|
<TabsPrimitive.Trigger
|
||||||
class={cn(
|
class={cn(
|
||||||
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[selected]:bg-background data-[selected]:text-foreground data-[selected]:shadow-sm",
|
'inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 font-medium text-sm ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[selected]:bg-background data-[selected]:text-foreground data-[selected]:shadow-sm',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type TabsContentProps<T extends ValidComponent = "div"> = TabsPrimitive.TabsContentProps<T> & {
|
type TabsContentProps<T extends ValidComponent = 'div'> =
|
||||||
class?: string | undefined
|
TabsPrimitive.TabsContentProps<T> & {
|
||||||
}
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const TabsContent = <T extends ValidComponent = "div">(
|
const TabsContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, TabsContentProps<T>>
|
props: PolymorphicProps<T, TabsContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as TabsContentProps, ["class"])
|
const [local, others] = splitProps(props as TabsContentProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<TabsPrimitive.Content
|
<TabsPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
'mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type TabsIndicatorProps<T extends ValidComponent = "div"> = TabsPrimitive.TabsIndicatorProps<T> & {
|
type TabsIndicatorProps<T extends ValidComponent = 'div'> =
|
||||||
class?: string | undefined
|
TabsPrimitive.TabsIndicatorProps<T> & {
|
||||||
}
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const TabsIndicator = <T extends ValidComponent = "div">(
|
const TabsIndicator = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, TabsIndicatorProps<T>>
|
props: PolymorphicProps<T, TabsIndicatorProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as TabsIndicatorProps, ["class"])
|
const [local, others] = splitProps(props as TabsIndicatorProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<TabsPrimitive.Indicator
|
<TabsPrimitive.Indicator
|
||||||
class={cn(
|
class={cn(
|
||||||
"duration-250ms absolute transition-all data-[orientation=horizontal]:-bottom-px data-[orientation=vertical]:-right-px data-[orientation=horizontal]:h-[2px] data-[orientation=vertical]:w-[2px]",
|
'data-[orientation=horizontal]:-bottom-px data-[orientation=vertical]:-right-px absolute transition-all duration-250ms data-[orientation=horizontal]:h-[2px] data-[orientation=vertical]:w-[2px]',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Tabs, TabsList, TabsTrigger, TabsContent, TabsIndicator }
|
export { Tabs, TabsList, TabsTrigger, TabsContent, TabsIndicator };
|
||||||
|
|||||||
@@ -1,146 +1,168 @@
|
|||||||
import type { ValidComponent } from "solid-js"
|
import type { ValidComponent } from 'solid-js';
|
||||||
import { mergeProps, splitProps } from "solid-js"
|
import { mergeProps, splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { PolymorphicProps } from "@kobalte/core"
|
import type { PolymorphicProps } from '@kobalte/core';
|
||||||
import * as TextFieldPrimitive from "@kobalte/core/text-field"
|
import * as TextFieldPrimitive from '@kobalte/core/text-field';
|
||||||
import { cva } from "class-variance-authority"
|
import { cva } from 'class-variance-authority';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
type TextFieldRootProps<T extends ValidComponent = "div"> =
|
type TextFieldRootProps<T extends ValidComponent = 'div'> =
|
||||||
TextFieldPrimitive.TextFieldRootProps<T> & {
|
TextFieldPrimitive.TextFieldRootProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const TextField = <T extends ValidComponent = "div">(
|
const TextField = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, TextFieldRootProps<T>>
|
props: PolymorphicProps<T, TextFieldRootProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as TextFieldRootProps, ["class"])
|
const [local, others] = splitProps(props as TextFieldRootProps, ['class']);
|
||||||
return <TextFieldPrimitive.Root class={cn("flex flex-col gap-1", local.class)} {...others} />
|
return (
|
||||||
}
|
<TextFieldPrimitive.Root
|
||||||
|
class={cn('flex flex-col gap-1', local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
type TextFieldInputProps<T extends ValidComponent = "input"> =
|
type TextFieldInputProps<T extends ValidComponent = 'input'> =
|
||||||
TextFieldPrimitive.TextFieldInputProps<T> & {
|
TextFieldPrimitive.TextFieldInputProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
type?:
|
type?:
|
||||||
| "button"
|
| 'button'
|
||||||
| "checkbox"
|
| 'checkbox'
|
||||||
| "color"
|
| 'color'
|
||||||
| "date"
|
| 'date'
|
||||||
| "datetime-local"
|
| 'datetime-local'
|
||||||
| "email"
|
| 'email'
|
||||||
| "file"
|
| 'file'
|
||||||
| "hidden"
|
| 'hidden'
|
||||||
| "image"
|
| 'image'
|
||||||
| "month"
|
| 'month'
|
||||||
| "number"
|
| 'number'
|
||||||
| "password"
|
| 'password'
|
||||||
| "radio"
|
| 'radio'
|
||||||
| "range"
|
| 'range'
|
||||||
| "reset"
|
| 'reset'
|
||||||
| "search"
|
| 'search'
|
||||||
| "submit"
|
| 'submit'
|
||||||
| "tel"
|
| 'tel'
|
||||||
| "text"
|
| 'text'
|
||||||
| "time"
|
| 'time'
|
||||||
| "url"
|
| 'url'
|
||||||
| "week"
|
| 'week';
|
||||||
}
|
};
|
||||||
|
|
||||||
const TextFieldInput = <T extends ValidComponent = "input">(
|
const TextFieldInput = <T extends ValidComponent = 'input'>(
|
||||||
rawProps: PolymorphicProps<T, TextFieldInputProps<T>>
|
rawProps: PolymorphicProps<T, TextFieldInputProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const props = mergeProps<TextFieldInputProps<T>[]>({ type: "text" }, rawProps)
|
const props = mergeProps<TextFieldInputProps<T>[]>(
|
||||||
const [local, others] = splitProps(props as TextFieldInputProps, ["type", "class"])
|
{ type: 'text' },
|
||||||
|
rawProps
|
||||||
|
);
|
||||||
|
const [local, others] = splitProps(props as TextFieldInputProps, [
|
||||||
|
'type',
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<TextFieldPrimitive.Input
|
<TextFieldPrimitive.Input
|
||||||
type={local.type}
|
type={local.type}
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[invalid]:border-error-foreground data-[invalid]:text-error-foreground",
|
'flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:font-medium file:text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[invalid]:border-error-foreground data-[invalid]:text-error-foreground',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type TextFieldTextAreaProps<T extends ValidComponent = "textarea"> =
|
type TextFieldTextAreaProps<T extends ValidComponent = 'textarea'> =
|
||||||
TextFieldPrimitive.TextFieldTextAreaProps<T> & { class?: string | undefined }
|
TextFieldPrimitive.TextFieldTextAreaProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const TextFieldTextArea = <T extends ValidComponent = "textarea">(
|
const TextFieldTextArea = <T extends ValidComponent = 'textarea'>(
|
||||||
props: PolymorphicProps<T, TextFieldTextAreaProps<T>>
|
props: PolymorphicProps<T, TextFieldTextAreaProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as TextFieldTextAreaProps, ["class"])
|
const [local, others] = splitProps(props as TextFieldTextAreaProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<TextFieldPrimitive.TextArea
|
<TextFieldPrimitive.TextArea
|
||||||
class={cn(
|
class={cn(
|
||||||
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
'flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const labelVariants = cva(
|
const labelVariants = cva(
|
||||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
'font-medium text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
label: "data-[invalid]:text-destructive",
|
label: 'data-[invalid]:text-destructive',
|
||||||
description: "font-normal text-muted-foreground",
|
description: 'font-normal text-muted-foreground',
|
||||||
error: "text-xs text-destructive"
|
error: 'text-destructive text-xs',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: "label"
|
variant: 'label',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
)
|
|
||||||
|
|
||||||
type TextFieldLabelProps<T extends ValidComponent = "label"> =
|
type TextFieldLabelProps<T extends ValidComponent = 'label'> =
|
||||||
TextFieldPrimitive.TextFieldLabelProps<T> & { class?: string | undefined }
|
TextFieldPrimitive.TextFieldLabelProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const TextFieldLabel = <T extends ValidComponent = "label">(
|
const TextFieldLabel = <T extends ValidComponent = 'label'>(
|
||||||
props: PolymorphicProps<T, TextFieldLabelProps<T>>
|
props: PolymorphicProps<T, TextFieldLabelProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as TextFieldLabelProps, ["class"])
|
const [local, others] = splitProps(props as TextFieldLabelProps, ['class']);
|
||||||
return <TextFieldPrimitive.Label class={cn(labelVariants(), local.class)} {...others} />
|
return (
|
||||||
}
|
<TextFieldPrimitive.Label
|
||||||
|
class={cn(labelVariants(), local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
type TextFieldDescriptionProps<T extends ValidComponent = "div"> =
|
type TextFieldDescriptionProps<T extends ValidComponent = 'div'> =
|
||||||
TextFieldPrimitive.TextFieldDescriptionProps<T> & {
|
TextFieldPrimitive.TextFieldDescriptionProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const TextFieldDescription = <T extends ValidComponent = "div">(
|
const TextFieldDescription = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, TextFieldDescriptionProps<T>>
|
props: PolymorphicProps<T, TextFieldDescriptionProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as TextFieldDescriptionProps, ["class"])
|
const [local, others] = splitProps(props as TextFieldDescriptionProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<TextFieldPrimitive.Description
|
<TextFieldPrimitive.Description
|
||||||
class={cn(labelVariants({ variant: "description" }), local.class)}
|
class={cn(labelVariants({ variant: 'description' }), local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type TextFieldErrorMessageProps<T extends ValidComponent = "div"> =
|
type TextFieldErrorMessageProps<T extends ValidComponent = 'div'> =
|
||||||
TextFieldPrimitive.TextFieldErrorMessageProps<T> & {
|
TextFieldPrimitive.TextFieldErrorMessageProps<T> & {
|
||||||
class?: string | undefined
|
class?: string | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const TextFieldErrorMessage = <T extends ValidComponent = "div">(
|
const TextFieldErrorMessage = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, TextFieldErrorMessageProps<T>>
|
props: PolymorphicProps<T, TextFieldErrorMessageProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as TextFieldErrorMessageProps, ["class"])
|
const [local, others] = splitProps(props as TextFieldErrorMessageProps, [
|
||||||
|
'class',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<TextFieldPrimitive.ErrorMessage
|
<TextFieldPrimitive.ErrorMessage
|
||||||
class={cn(labelVariants({ variant: "error" }), local.class)}
|
class={cn(labelVariants({ variant: 'error' }), local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
TextField,
|
TextField,
|
||||||
@@ -148,5 +170,5 @@ export {
|
|||||||
TextFieldTextArea,
|
TextFieldTextArea,
|
||||||
TextFieldLabel,
|
TextFieldLabel,
|
||||||
TextFieldDescription,
|
TextFieldDescription,
|
||||||
TextFieldErrorMessage
|
TextFieldErrorMessage,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,21 +1,28 @@
|
|||||||
import type { ComponentProps, ParentComponent } from "solid-js"
|
import type { ComponentProps, ParentComponent } from 'solid-js';
|
||||||
import { For, mergeProps, Show, splitProps, type Component, type JSXElement } from "solid-js"
|
import {
|
||||||
|
type Component,
|
||||||
|
For,
|
||||||
|
type JSXElement,
|
||||||
|
Show,
|
||||||
|
mergeProps,
|
||||||
|
splitProps,
|
||||||
|
} from 'solid-js';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
export type TimelinePropsItem = Omit<
|
export type TimelinePropsItem = Omit<
|
||||||
TimelineItemProps,
|
TimelineItemProps,
|
||||||
"isActive" | "isActiveBullet" | "bulletSize" | "lineSize"
|
'isActive' | 'isActiveBullet' | 'bulletSize' | 'lineSize'
|
||||||
> & {
|
> & {
|
||||||
bulletSize?: number
|
bulletSize?: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type TimelineProps = {
|
export type TimelineProps = {
|
||||||
items: TimelinePropsItem[]
|
items: TimelinePropsItem[];
|
||||||
activeItem: number
|
activeItem: number;
|
||||||
bulletSize?: number
|
bulletSize?: number;
|
||||||
lineSize?: number
|
lineSize?: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
No bullet or line is active when activeItem is -1
|
No bullet or line is active when activeItem is -1
|
||||||
@@ -24,12 +31,12 @@ export type TimelineProps = {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const Timeline: Component<TimelineProps> = (rawProps) => {
|
const Timeline: Component<TimelineProps> = (rawProps) => {
|
||||||
const props = mergeProps({ bulletSize: 16, lineSize: 2 }, rawProps)
|
const props = mergeProps({ bulletSize: 16, lineSize: 2 }, rawProps);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul
|
<ul
|
||||||
style={{
|
style={{
|
||||||
"padding-left": `${props.bulletSize / 2}px`
|
'padding-left': `${props.bulletSize / 2}px`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<For each={props.items}>
|
<For each={props.items}>
|
||||||
@@ -39,51 +46,55 @@ const Timeline: Component<TimelineProps> = (rawProps) => {
|
|||||||
description={item.description}
|
description={item.description}
|
||||||
bullet={item.bullet}
|
bullet={item.bullet}
|
||||||
isLast={index() === props.items.length - 1}
|
isLast={index() === props.items.length - 1}
|
||||||
isActive={props.activeItem === -1 ? false : props.activeItem >= index() + 1}
|
isActive={
|
||||||
isActiveBullet={props.activeItem === -1 ? false : props.activeItem >= index()}
|
props.activeItem === -1 ? false : props.activeItem >= index() + 1
|
||||||
|
}
|
||||||
|
isActiveBullet={
|
||||||
|
props.activeItem === -1 ? false : props.activeItem >= index()
|
||||||
|
}
|
||||||
bulletSize={props.bulletSize}
|
bulletSize={props.bulletSize}
|
||||||
lineSize={props.lineSize}
|
lineSize={props.lineSize}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
</ul>
|
</ul>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export type TimelineItemProps = {
|
export type TimelineItemProps = {
|
||||||
title: JSXElement
|
title: JSXElement;
|
||||||
description?: JSXElement
|
description?: JSXElement;
|
||||||
bullet?: JSXElement
|
bullet?: JSXElement;
|
||||||
isLast?: boolean
|
isLast?: boolean;
|
||||||
isActive: boolean
|
isActive: boolean;
|
||||||
isActiveBullet: boolean
|
isActiveBullet: boolean;
|
||||||
class?: string
|
class?: string;
|
||||||
bulletSize: number
|
bulletSize: number;
|
||||||
lineSize: number
|
lineSize: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
const TimelineItem: Component<TimelineItemProps> = (props) => {
|
const TimelineItem: Component<TimelineItemProps> = (props) => {
|
||||||
const [local, others] = splitProps(props, [
|
const [local, others] = splitProps(props, [
|
||||||
"class",
|
'class',
|
||||||
"bullet",
|
'bullet',
|
||||||
"description",
|
'description',
|
||||||
"title",
|
'title',
|
||||||
"isLast",
|
'isLast',
|
||||||
"isActive",
|
'isActive',
|
||||||
"isActiveBullet",
|
'isActiveBullet',
|
||||||
"bulletSize",
|
'bulletSize',
|
||||||
"lineSize"
|
'lineSize',
|
||||||
])
|
]);
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
class={cn(
|
class={cn(
|
||||||
"relative border-l pb-8 pl-8",
|
'relative border-l pb-8 pl-8',
|
||||||
local.isLast && "border-l-transparent pb-0",
|
local.isLast && 'border-l-transparent pb-0',
|
||||||
local.isActive && !local.isLast && "border-l-primary",
|
local.isActive && !local.isLast && 'border-l-primary',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
style={{
|
style={{
|
||||||
"border-left-width": `${local.lineSize}px`
|
'border-left-width': `${local.lineSize}px`,
|
||||||
}}
|
}}
|
||||||
{...others}
|
{...others}
|
||||||
>
|
>
|
||||||
@@ -99,47 +110,51 @@ const TimelineItem: Component<TimelineItemProps> = (props) => {
|
|||||||
<TimelineItemDescription>{local.description}</TimelineItemDescription>
|
<TimelineItemDescription>{local.description}</TimelineItemDescription>
|
||||||
</Show>
|
</Show>
|
||||||
</li>
|
</li>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export type TimelineItemBulletProps = {
|
export type TimelineItemBulletProps = {
|
||||||
children?: JSXElement
|
children?: JSXElement;
|
||||||
isActive?: boolean
|
isActive?: boolean;
|
||||||
bulletSize: number
|
bulletSize: number;
|
||||||
lineSize: number
|
lineSize: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
const TimelineItemBullet: Component<TimelineItemBulletProps> = (props) => {
|
const TimelineItemBullet: Component<TimelineItemBulletProps> = (props) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cn(
|
class={cn(
|
||||||
`absolute top-0 flex items-center justify-center rounded-full border bg-background`,
|
`absolute top-0 flex items-center justify-center rounded-full border bg-background`,
|
||||||
props.isActive && "border-primary"
|
props.isActive && 'border-primary'
|
||||||
)}
|
)}
|
||||||
style={{
|
style={{
|
||||||
width: `${props.bulletSize}px`,
|
width: `${props.bulletSize}px`,
|
||||||
height: `${props.bulletSize}px`,
|
height: `${props.bulletSize}px`,
|
||||||
left: `${-props.bulletSize / 2 - props.lineSize / 2}px`,
|
left: `${-props.bulletSize / 2 - props.lineSize / 2}px`,
|
||||||
"border-width": `${props.lineSize}px`
|
'border-width': `${props.lineSize}px`,
|
||||||
}}
|
}}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const TimelineItemTitle: ParentComponent = (props) => {
|
const TimelineItemTitle: ParentComponent = (props) => {
|
||||||
return <div class="mb-1 text-base font-semibold leading-none">{props.children}</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
const TimelineItemDescription: Component<ComponentProps<"p">> = (props) => {
|
|
||||||
const [local, others] = splitProps(props, ["class", "children"])
|
|
||||||
return (
|
return (
|
||||||
<p class={cn("text-sm text-muted-foreground", local.class)} {...others}>
|
<div class="mb-1 font-semibold text-base leading-none">
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const TimelineItemDescription: Component<ComponentProps<'p'>> = (props) => {
|
||||||
|
const [local, others] = splitProps(props, ['class', 'children']);
|
||||||
|
return (
|
||||||
|
<p class={cn('text-muted-foreground text-sm', local.class)} {...others}>
|
||||||
{local.children}
|
{local.children}
|
||||||
</p>
|
</p>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Timeline }
|
export { Timeline };
|
||||||
|
|||||||
@@ -1,81 +1,90 @@
|
|||||||
import type { JSX, ValidComponent } from "solid-js"
|
import type { JSX, ValidComponent } from 'solid-js';
|
||||||
import { Match, splitProps, Switch } from "solid-js"
|
import { Match, Switch, splitProps } from 'solid-js';
|
||||||
import { Portal } from "solid-js/web"
|
import { Portal } from 'solid-js/web';
|
||||||
|
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
import * as ToastPrimitive from "@kobalte/core/toast"
|
import * as ToastPrimitive from '@kobalte/core/toast';
|
||||||
import type { VariantProps } from "class-variance-authority"
|
import type { VariantProps } from 'class-variance-authority';
|
||||||
import { cva } from "class-variance-authority"
|
import { cva } from 'class-variance-authority';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const toastVariants = cva(
|
const toastVariants = cva(
|
||||||
"group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--kb-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--kb-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[opened]:animate-in data-[closed]:animate-out data-[swipe=end]:animate-out data-[closed]:fade-out-80 data-[closed]:slide-out-to-right-full data-[opened]:slide-in-from-top-full data-[opened]:sm:slide-in-from-bottom-full",
|
'group data-[closed]:fade-out-80 data-[closed]:slide-out-to-right-full data-[opened]:slide-in-from-top-full data-[opened]:sm:slide-in-from-bottom-full pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--kb-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--kb-toast-swipe-move-x)] data-[closed]:animate-out data-[opened]:animate-in data-[swipe=end]:animate-out data-[swipe=move]:transition-none',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: "border bg-background text-foreground",
|
default: 'border bg-background text-foreground',
|
||||||
destructive:
|
destructive:
|
||||||
"destructive group border-destructive bg-destructive text-destructive-foreground",
|
'destructive group border-destructive bg-destructive text-destructive-foreground',
|
||||||
success: "success border-success-foreground bg-success text-success-foreground",
|
success:
|
||||||
warning: "warning border-warning-foreground bg-warning text-warning-foreground",
|
'success border-success-foreground bg-success text-success-foreground',
|
||||||
error: "error border-error-foreground bg-error text-error-foreground"
|
warning:
|
||||||
}
|
'warning border-warning-foreground bg-warning text-warning-foreground',
|
||||||
|
error: 'error border-error-foreground bg-error text-error-foreground',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: "default"
|
variant: 'default',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
)
|
type ToastVariant = NonNullable<VariantProps<typeof toastVariants>['variant']>;
|
||||||
type ToastVariant = NonNullable<VariantProps<typeof toastVariants>["variant"]>
|
|
||||||
|
|
||||||
type ToastListProps<T extends ValidComponent = "ol"> = ToastPrimitive.ToastListProps<T> & {
|
type ToastListProps<T extends ValidComponent = 'ol'> =
|
||||||
class?: string | undefined
|
ToastPrimitive.ToastListProps<T> & {
|
||||||
}
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const Toaster = <T extends ValidComponent = "ol">(
|
const Toaster = <T extends ValidComponent = 'ol'>(
|
||||||
props: PolymorphicProps<T, ToastListProps<T>>
|
props: PolymorphicProps<T, ToastListProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ToastListProps, ["class"])
|
const [local, others] = splitProps(props as ToastListProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<Portal>
|
<Portal>
|
||||||
<ToastPrimitive.Region>
|
<ToastPrimitive.Region>
|
||||||
<ToastPrimitive.List
|
<ToastPrimitive.List
|
||||||
class={cn(
|
class={cn(
|
||||||
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse gap-2 p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
|
'fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse gap-2 p-4 sm:top-auto sm:right-0 sm:bottom-0 sm:flex-col md:max-w-[420px]',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
</ToastPrimitive.Region>
|
</ToastPrimitive.Region>
|
||||||
</Portal>
|
</Portal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ToastRootProps<T extends ValidComponent = "li"> = ToastPrimitive.ToastRootProps<T> &
|
type ToastRootProps<T extends ValidComponent = 'li'> =
|
||||||
VariantProps<typeof toastVariants> & { class?: string | undefined }
|
ToastPrimitive.ToastRootProps<T> &
|
||||||
|
VariantProps<typeof toastVariants> & { class?: string | undefined };
|
||||||
|
|
||||||
const Toast = <T extends ValidComponent = "li">(props: PolymorphicProps<T, ToastRootProps<T>>) => {
|
const Toast = <T extends ValidComponent = 'li'>(
|
||||||
const [local, others] = splitProps(props as ToastRootProps, ["class", "variant"])
|
props: PolymorphicProps<T, ToastRootProps<T>>
|
||||||
|
) => {
|
||||||
|
const [local, others] = splitProps(props as ToastRootProps, [
|
||||||
|
'class',
|
||||||
|
'variant',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<ToastPrimitive.Root
|
<ToastPrimitive.Root
|
||||||
class={cn(toastVariants({ variant: local.variant }), local.class)}
|
class={cn(toastVariants({ variant: local.variant }), local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ToastCloseButtonProps<T extends ValidComponent = "button"> =
|
type ToastCloseButtonProps<T extends ValidComponent = 'button'> =
|
||||||
ToastPrimitive.ToastCloseButtonProps<T> & { class?: string | undefined }
|
ToastPrimitive.ToastCloseButtonProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const ToastClose = <T extends ValidComponent = "button">(
|
const ToastClose = <T extends ValidComponent = 'button'>(
|
||||||
props: PolymorphicProps<T, ToastCloseButtonProps<T>>
|
props: PolymorphicProps<T, ToastCloseButtonProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ToastCloseButtonProps, ["class"])
|
const [local, others] = splitProps(props as ToastCloseButtonProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<ToastPrimitive.CloseButton
|
<ToastPrimitive.CloseButton
|
||||||
class={cn(
|
class={cn(
|
||||||
"absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-destructive-foreground group-[.error]:text-error-foreground group-[.success]:text-success-foreground group-[.warning]:text-warning-foreground",
|
'absolute top-2 right-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-destructive-foreground group-[.error]:text-error-foreground group-[.success]:text-success-foreground group-[.warning]:text-warning-foreground',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
@@ -94,70 +103,103 @@ const ToastClose = <T extends ValidComponent = "button">(
|
|||||||
<path d="M6 6l12 12" />
|
<path d="M6 6l12 12" />
|
||||||
</svg>
|
</svg>
|
||||||
</ToastPrimitive.CloseButton>
|
</ToastPrimitive.CloseButton>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ToastTitleProps<T extends ValidComponent = "div"> = ToastPrimitive.ToastTitleProps<T> & {
|
type ToastTitleProps<T extends ValidComponent = 'div'> =
|
||||||
class?: string | undefined
|
ToastPrimitive.ToastTitleProps<T> & {
|
||||||
}
|
class?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const ToastTitle = <T extends ValidComponent = "div">(
|
const ToastTitle = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, ToastTitleProps<T>>
|
props: PolymorphicProps<T, ToastTitleProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ToastTitleProps, ["class"])
|
const [local, others] = splitProps(props as ToastTitleProps, ['class']);
|
||||||
return <ToastPrimitive.Title class={cn("text-sm font-semibold", local.class)} {...others} />
|
return (
|
||||||
}
|
<ToastPrimitive.Title
|
||||||
|
class={cn('font-semibold text-sm', local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
type ToastDescriptionProps<T extends ValidComponent = "div"> =
|
type ToastDescriptionProps<T extends ValidComponent = 'div'> =
|
||||||
ToastPrimitive.ToastDescriptionProps<T> & { class?: string | undefined }
|
ToastPrimitive.ToastDescriptionProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const ToastDescription = <T extends ValidComponent = "div">(
|
const ToastDescription = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, ToastDescriptionProps<T>>
|
props: PolymorphicProps<T, ToastDescriptionProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ToastDescriptionProps, ["class"])
|
const [local, others] = splitProps(props as ToastDescriptionProps, ['class']);
|
||||||
return <ToastPrimitive.Description class={cn("text-sm opacity-90", local.class)} {...others} />
|
return (
|
||||||
}
|
<ToastPrimitive.Description
|
||||||
|
class={cn('text-sm opacity-90', local.class)}
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
function showToast(props: {
|
function showToast(props: {
|
||||||
title?: JSX.Element
|
title?: JSX.Element;
|
||||||
description?: JSX.Element
|
description?: JSX.Element;
|
||||||
variant?: ToastVariant
|
variant?: ToastVariant;
|
||||||
duration?: number
|
duration?: number;
|
||||||
}) {
|
}) {
|
||||||
ToastPrimitive.toaster.show((data) => (
|
ToastPrimitive.toaster.show((data) => (
|
||||||
<Toast toastId={data.toastId} variant={props.variant} duration={props.duration}>
|
<Toast
|
||||||
|
toastId={data.toastId}
|
||||||
|
variant={props.variant}
|
||||||
|
duration={props.duration}
|
||||||
|
>
|
||||||
<div class="grid gap-1">
|
<div class="grid gap-1">
|
||||||
{props.title && <ToastTitle>{props.title}</ToastTitle>}
|
{props.title && <ToastTitle>{props.title}</ToastTitle>}
|
||||||
{props.description && <ToastDescription>{props.description}</ToastDescription>}
|
{props.description && (
|
||||||
|
<ToastDescription>{props.description}</ToastDescription>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<ToastClose />
|
<ToastClose />
|
||||||
</Toast>
|
</Toast>
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
function showToastPromise<T, U>(
|
function showToastPromise<T, U>(
|
||||||
promise: Promise<T> | (() => Promise<T>),
|
promise: Promise<T> | (() => Promise<T>),
|
||||||
options: {
|
options: {
|
||||||
loading?: JSX.Element
|
loading?: JSX.Element;
|
||||||
success?: (data: T) => JSX.Element
|
success?: (data: T) => JSX.Element;
|
||||||
error?: (error: U) => JSX.Element
|
error?: (error: U) => JSX.Element;
|
||||||
duration?: number
|
duration?: number;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
const variant: { [key in ToastPrimitive.ToastPromiseState]: ToastVariant } = {
|
const variant: { [key in ToastPrimitive.ToastPromiseState]: ToastVariant } = {
|
||||||
pending: "default",
|
pending: 'default',
|
||||||
fulfilled: "success",
|
fulfilled: 'success',
|
||||||
rejected: "error"
|
rejected: 'error',
|
||||||
}
|
};
|
||||||
return ToastPrimitive.toaster.promise<T, U>(promise, (props) => (
|
return ToastPrimitive.toaster.promise<T, U>(promise, (props) => (
|
||||||
<Toast toastId={props.toastId} variant={variant[props.state]} duration={options.duration}>
|
<Toast
|
||||||
|
toastId={props.toastId}
|
||||||
|
variant={variant[props.state]}
|
||||||
|
duration={options.duration}
|
||||||
|
>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Match when={props.state === "pending"}>{options.loading}</Match>
|
<Match when={props.state === 'pending'}>{options.loading}</Match>
|
||||||
<Match when={props.state === "fulfilled"}>{options.success?.(props.data!)}</Match>
|
<Match when={props.state === 'fulfilled'}>
|
||||||
<Match when={props.state === "rejected"}>{options.error?.(props.error!)}</Match>
|
{options.success?.(props.data!)}
|
||||||
|
</Match>
|
||||||
|
<Match when={props.state === 'rejected'}>
|
||||||
|
{options.error?.(props.error!)}
|
||||||
|
</Match>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Toast>
|
</Toast>
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Toaster, Toast, ToastClose, ToastTitle, ToastDescription, showToast, showToastPromise }
|
export {
|
||||||
|
Toaster,
|
||||||
|
Toast,
|
||||||
|
ToastClose,
|
||||||
|
ToastTitle,
|
||||||
|
ToastDescription,
|
||||||
|
showToast,
|
||||||
|
showToastPromise,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,75 +1,82 @@
|
|||||||
import type { JSX, ValidComponent } from "solid-js"
|
import type { JSX, ValidComponent } from 'solid-js';
|
||||||
import { createContext, splitProps, useContext } from "solid-js"
|
import { createContext, splitProps, useContext } from 'solid-js';
|
||||||
|
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
import * as ToggleGroupPrimitive from "@kobalte/core/toggle-group"
|
import * as ToggleGroupPrimitive from '@kobalte/core/toggle-group';
|
||||||
import type { VariantProps } from "class-variance-authority"
|
import type { VariantProps } from 'class-variance-authority';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { toggleVariants } from '~/components/ui/toggle';
|
||||||
import { toggleVariants } from "~/components/ui/toggle"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const ToggleGroupContext = createContext<VariantProps<typeof toggleVariants>>({
|
const ToggleGroupContext = createContext<VariantProps<typeof toggleVariants>>({
|
||||||
size: "default",
|
size: 'default',
|
||||||
variant: "default"
|
variant: 'default',
|
||||||
})
|
});
|
||||||
|
|
||||||
type ToggleGroupRootProps<T extends ValidComponent = "div"> =
|
type ToggleGroupRootProps<T extends ValidComponent = 'div'> =
|
||||||
ToggleGroupPrimitive.ToggleGroupRootProps<T> &
|
ToggleGroupPrimitive.ToggleGroupRootProps<T> &
|
||||||
VariantProps<typeof toggleVariants> & { class?: string | undefined; children?: JSX.Element }
|
VariantProps<typeof toggleVariants> & {
|
||||||
|
class?: string | undefined;
|
||||||
|
children?: JSX.Element;
|
||||||
|
};
|
||||||
|
|
||||||
const ToggleGroup = <T extends ValidComponent = "div">(
|
const ToggleGroup = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, ToggleGroupRootProps<T>>
|
props: PolymorphicProps<T, ToggleGroupRootProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ToggleGroupRootProps, [
|
const [local, others] = splitProps(props as ToggleGroupRootProps, [
|
||||||
"class",
|
'class',
|
||||||
"children",
|
'children',
|
||||||
"size",
|
'size',
|
||||||
"variant"
|
'variant',
|
||||||
])
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ToggleGroupPrimitive.Root
|
<ToggleGroupPrimitive.Root
|
||||||
class={cn("flex items-center justify-center gap-1", local.class)}
|
class={cn('flex items-center justify-center gap-1', local.class)}
|
||||||
{...others}
|
{...others}
|
||||||
>
|
>
|
||||||
<ToggleGroupContext.Provider
|
<ToggleGroupContext.Provider
|
||||||
value={{
|
value={{
|
||||||
get size() {
|
get size() {
|
||||||
return local.size
|
return local.size;
|
||||||
},
|
},
|
||||||
get variant() {
|
get variant() {
|
||||||
return local.variant
|
return local.variant;
|
||||||
}
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{local.children}
|
{local.children}
|
||||||
</ToggleGroupContext.Provider>
|
</ToggleGroupContext.Provider>
|
||||||
</ToggleGroupPrimitive.Root>
|
</ToggleGroupPrimitive.Root>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ToggleGroupItemProps<T extends ValidComponent = "button"> =
|
type ToggleGroupItemProps<T extends ValidComponent = 'button'> =
|
||||||
ToggleGroupPrimitive.ToggleGroupItemProps<T> &
|
ToggleGroupPrimitive.ToggleGroupItemProps<T> &
|
||||||
VariantProps<typeof toggleVariants> & { class?: string | undefined }
|
VariantProps<typeof toggleVariants> & { class?: string | undefined };
|
||||||
|
|
||||||
const ToggleGroupItem = <T extends ValidComponent = "button">(
|
const ToggleGroupItem = <T extends ValidComponent = 'button'>(
|
||||||
props: PolymorphicProps<T, ToggleGroupItemProps<T>>
|
props: PolymorphicProps<T, ToggleGroupItemProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ToggleGroupItemProps, ["class", "size", "variant"])
|
const [local, others] = splitProps(props as ToggleGroupItemProps, [
|
||||||
const context = useContext(ToggleGroupContext)
|
'class',
|
||||||
|
'size',
|
||||||
|
'variant',
|
||||||
|
]);
|
||||||
|
const context = useContext(ToggleGroupContext);
|
||||||
return (
|
return (
|
||||||
<ToggleGroupPrimitive.Item
|
<ToggleGroupPrimitive.Item
|
||||||
class={cn(
|
class={cn(
|
||||||
toggleVariants({
|
toggleVariants({
|
||||||
size: context.size || local.size,
|
size: context.size || local.size,
|
||||||
variant: context.variant || local.variant
|
variant: context.variant || local.variant,
|
||||||
}),
|
}),
|
||||||
"hover:bg-muted hover:text-muted-foreground data-[pressed]:bg-accent data-[pressed]:text-accent-foreground",
|
'hover:bg-muted hover:text-muted-foreground data-[pressed]:bg-accent data-[pressed]:text-accent-foreground',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { ToggleGroup, ToggleGroupItem }
|
export { ToggleGroup, ToggleGroupItem };
|
||||||
|
|||||||
@@ -1,49 +1,56 @@
|
|||||||
import type { ValidComponent } from "solid-js"
|
import type { ValidComponent } from 'solid-js';
|
||||||
import { splitProps } from "solid-js"
|
import { splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
import * as ToggleButtonPrimitive from "@kobalte/core/toggle-button"
|
import * as ToggleButtonPrimitive from '@kobalte/core/toggle-button';
|
||||||
import { cva } from "class-variance-authority"
|
import { cva } from 'class-variance-authority';
|
||||||
import type { VariantProps } from "class-variance-authority"
|
import type { VariantProps } from 'class-variance-authority';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const toggleVariants = cva(
|
const toggleVariants = cva(
|
||||||
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
'inline-flex items-center justify-center rounded-md font-medium text-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: "bg-transparent",
|
default: 'bg-transparent',
|
||||||
outline: "border border-input bg-transparent shadow-sm"
|
outline: 'border border-input bg-transparent shadow-sm',
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
default: "h-9 px-3",
|
default: 'h-9 px-3',
|
||||||
sm: "h-8 px-2",
|
sm: 'h-8 px-2',
|
||||||
lg: "h-10 px-3"
|
lg: 'h-10 px-3',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: "default",
|
variant: 'default',
|
||||||
size: "default"
|
size: 'default',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
)
|
|
||||||
|
|
||||||
type ToggleButtonRootProps<T extends ValidComponent = "button"> =
|
type ToggleButtonRootProps<T extends ValidComponent = 'button'> =
|
||||||
ToggleButtonPrimitive.ToggleButtonRootProps<T> &
|
ToggleButtonPrimitive.ToggleButtonRootProps<T> &
|
||||||
VariantProps<typeof toggleVariants> & { class?: string | undefined }
|
VariantProps<typeof toggleVariants> & { class?: string | undefined };
|
||||||
|
|
||||||
const Toggle = <T extends ValidComponent = "button">(
|
const Toggle = <T extends ValidComponent = 'button'>(
|
||||||
props: PolymorphicProps<T, ToggleButtonRootProps<T>>
|
props: PolymorphicProps<T, ToggleButtonRootProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as ToggleButtonRootProps, ["class", "variant", "size"])
|
const [local, others] = splitProps(props as ToggleButtonRootProps, [
|
||||||
|
'class',
|
||||||
|
'variant',
|
||||||
|
'size',
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<ToggleButtonPrimitive.Root
|
<ToggleButtonPrimitive.Root
|
||||||
class={cn(toggleVariants({ variant: local.variant, size: local.size }), local.class)}
|
class={cn(
|
||||||
|
toggleVariants({ variant: local.variant, size: local.size }),
|
||||||
|
local.class
|
||||||
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export type { ToggleButtonRootProps as ToggleProps }
|
export type { ToggleButtonRootProps as ToggleProps };
|
||||||
export { toggleVariants, Toggle }
|
export { toggleVariants, Toggle };
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
import type { ValidComponent } from "solid-js"
|
import type { ValidComponent } from 'solid-js';
|
||||||
import { splitProps, type Component } from "solid-js"
|
import { type Component, splitProps } from 'solid-js';
|
||||||
|
|
||||||
import type { PolymorphicProps } from "@kobalte/core/polymorphic"
|
import type { PolymorphicProps } from '@kobalte/core/polymorphic';
|
||||||
import * as TooltipPrimitive from "@kobalte/core/tooltip"
|
import * as TooltipPrimitive from '@kobalte/core/tooltip';
|
||||||
|
|
||||||
import { cn } from "~/styles/utils"
|
import { cn } from '~/utils/styles';
|
||||||
|
|
||||||
const TooltipTrigger = TooltipPrimitive.Trigger
|
const TooltipTrigger = TooltipPrimitive.Trigger;
|
||||||
|
|
||||||
const Tooltip: Component<TooltipPrimitive.TooltipRootProps> = (props) => {
|
const Tooltip: Component<TooltipPrimitive.TooltipRootProps> = (props) => {
|
||||||
return <TooltipPrimitive.Root gutter={4} {...props} />
|
return <TooltipPrimitive.Root gutter={4} {...props} />;
|
||||||
}
|
};
|
||||||
|
|
||||||
type TooltipContentProps<T extends ValidComponent = "div"> =
|
type TooltipContentProps<T extends ValidComponent = 'div'> =
|
||||||
TooltipPrimitive.TooltipContentProps<T> & { class?: string | undefined }
|
TooltipPrimitive.TooltipContentProps<T> & { class?: string | undefined };
|
||||||
|
|
||||||
const TooltipContent = <T extends ValidComponent = "div">(
|
const TooltipContent = <T extends ValidComponent = 'div'>(
|
||||||
props: PolymorphicProps<T, TooltipContentProps<T>>
|
props: PolymorphicProps<T, TooltipContentProps<T>>
|
||||||
) => {
|
) => {
|
||||||
const [local, others] = splitProps(props as TooltipContentProps, ["class"])
|
const [local, others] = splitProps(props as TooltipContentProps, ['class']);
|
||||||
return (
|
return (
|
||||||
<TooltipPrimitive.Portal>
|
<TooltipPrimitive.Portal>
|
||||||
<TooltipPrimitive.Content
|
<TooltipPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
"z-50 origin-[var(--kb-popover-content-transform-origin)] overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95",
|
'fade-in-0 zoom-in-95 z-50 origin-[var(--kb-popover-content-transform-origin)] animate-in overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-popover-foreground text-sm shadow-md',
|
||||||
local.class
|
local.class
|
||||||
)}
|
)}
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
</TooltipPrimitive.Portal>
|
</TooltipPrimitive.Portal>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export { Tooltip, TooltipTrigger, TooltipContent }
|
export { Tooltip, TooltipTrigger, TooltipContent };
|
||||||
|
|||||||
@@ -18,11 +18,12 @@ import {
|
|||||||
InjectorProvider,
|
InjectorProvider,
|
||||||
} from 'oidc-client-rx/adapters/solid-js';
|
} from 'oidc-client-rx/adapters/solid-js';
|
||||||
import { Dynamic, render } from 'solid-js/web';
|
import { Dynamic, render } from 'solid-js/web';
|
||||||
import { buildOidcConfig, isBasicAuth } from './auth/config';
|
import { buildOidcConfig, isBasicAuth, isOidcAuth } from './auth/config';
|
||||||
import { isAuthenticated } from './auth/context';
|
import { isAuthenticated } from './auth/context';
|
||||||
import { useAuth } from './auth/hooks';
|
import { useAuth } from './auth/hooks';
|
||||||
import { routeTree } from './routeTree.gen';
|
import { routeTree } from './routeTree.gen';
|
||||||
import './app.css';
|
import './app.css';
|
||||||
|
import { AppNotFoundComponent } from './components/layout/app-not-found';
|
||||||
|
|
||||||
// Create a new router instance
|
// Create a new router instance
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
@@ -30,6 +31,8 @@ const router = createRouter({
|
|||||||
defaultPreload: 'intent',
|
defaultPreload: 'intent',
|
||||||
defaultStaleTime: 5000,
|
defaultStaleTime: 5000,
|
||||||
scrollRestoration: true,
|
scrollRestoration: true,
|
||||||
|
defaultNotFoundComponent: AppNotFoundComponent,
|
||||||
|
notFoundMode: 'root',
|
||||||
context: {
|
context: {
|
||||||
isAuthenticated: isAuthenticated,
|
isAuthenticated: isAuthenticated,
|
||||||
injector: InjectorContextVoidInjector,
|
injector: InjectorContextVoidInjector,
|
||||||
@@ -62,7 +65,7 @@ const injector: Injector = isBasicAuth
|
|||||||
|
|
||||||
// if needed, check when init
|
// if needed, check when init
|
||||||
let oidcSecurityService: OidcSecurityService | undefined;
|
let oidcSecurityService: OidcSecurityService | undefined;
|
||||||
if (!isBasicAuth) {
|
if (isOidcAuth) {
|
||||||
oidcSecurityService = injector.get(OidcSecurityService);
|
oidcSecurityService = injector.get(OidcSecurityService);
|
||||||
oidcSecurityService.checkAuth().subscribe();
|
oidcSecurityService.checkAuth().subscribe();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,15 +13,19 @@
|
|||||||
import { Route as rootRoute } from './routes/__root'
|
import { Route as rootRoute } from './routes/__root'
|
||||||
import { Route as AboutImport } from './routes/about'
|
import { Route as AboutImport } from './routes/about'
|
||||||
import { Route as AppImport } from './routes/_app'
|
import { Route as AppImport } from './routes/_app'
|
||||||
|
import { Route as R404Import } from './routes/404'
|
||||||
import { Route as IndexImport } from './routes/index'
|
import { Route as IndexImport } from './routes/index'
|
||||||
import { Route as AuthSignUpImport } from './routes/auth/sign-up'
|
import { Route as AuthSignUpImport } from './routes/auth/sign-up'
|
||||||
import { Route as AuthSignInImport } from './routes/auth/sign-in'
|
import { Route as AuthSignInImport } from './routes/auth/sign-in'
|
||||||
import { Route as AppExploreImport } from './routes/_app/explore'
|
import { Route as AppExploreImport } from './routes/_app/explore'
|
||||||
|
import { Route as AppSubscriptionsRouteImport } from './routes/_app/subscriptions/route'
|
||||||
|
import { Route as AppSettingsRouteImport } from './routes/_app/settings/route'
|
||||||
|
import { Route as AppPlaygroundRouteImport } from './routes/_app/playground/route'
|
||||||
import { Route as AuthOidcCallbackImport } from './routes/auth/oidc/callback'
|
import { Route as AuthOidcCallbackImport } from './routes/auth/oidc/callback'
|
||||||
import { Route as AppSubscriptionsManageImport } from './routes/_app/subscriptions/manage'
|
import { Route as AppSubscriptionsManageImport } from './routes/_app/subscriptions/manage'
|
||||||
import { Route as AppSubscriptionsCreateImport } from './routes/_app/subscriptions/create'
|
import { Route as AppSubscriptionsCreateImport } from './routes/_app/subscriptions/create'
|
||||||
import { Route as AppPlaygroundGraphqlApiImport } from './routes/_app/playground/graphql-api'
|
import { Route as AppPlaygroundGraphqlApiImport } from './routes/_app/playground/graphql-api'
|
||||||
import { Route as AppSubscriptionsEditSubscriptionIdImport } from './routes/_app/subscriptions/edit/$subscription-id'
|
import { Route as AppSubscriptionsEditSubscriptionIdImport } from './routes/_app/subscriptions/edit.$subscription-id'
|
||||||
|
|
||||||
// Create/Update Routes
|
// Create/Update Routes
|
||||||
|
|
||||||
@@ -36,6 +40,12 @@ const AppRoute = AppImport.update({
|
|||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
|
const R404Route = R404Import.update({
|
||||||
|
id: '/404',
|
||||||
|
path: '/404',
|
||||||
|
getParentRoute: () => rootRoute,
|
||||||
|
} as any)
|
||||||
|
|
||||||
const IndexRoute = IndexImport.update({
|
const IndexRoute = IndexImport.update({
|
||||||
id: '/',
|
id: '/',
|
||||||
path: '/',
|
path: '/',
|
||||||
@@ -60,6 +70,24 @@ const AppExploreRoute = AppExploreImport.update({
|
|||||||
getParentRoute: () => AppRoute,
|
getParentRoute: () => AppRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
|
const AppSubscriptionsRouteRoute = AppSubscriptionsRouteImport.update({
|
||||||
|
id: '/subscriptions',
|
||||||
|
path: '/subscriptions',
|
||||||
|
getParentRoute: () => AppRoute,
|
||||||
|
} as any)
|
||||||
|
|
||||||
|
const AppSettingsRouteRoute = AppSettingsRouteImport.update({
|
||||||
|
id: '/settings',
|
||||||
|
path: '/settings',
|
||||||
|
getParentRoute: () => AppRoute,
|
||||||
|
} as any)
|
||||||
|
|
||||||
|
const AppPlaygroundRouteRoute = AppPlaygroundRouteImport.update({
|
||||||
|
id: '/playground',
|
||||||
|
path: '/playground',
|
||||||
|
getParentRoute: () => AppRoute,
|
||||||
|
} as any)
|
||||||
|
|
||||||
const AuthOidcCallbackRoute = AuthOidcCallbackImport.update({
|
const AuthOidcCallbackRoute = AuthOidcCallbackImport.update({
|
||||||
id: '/auth/oidc/callback',
|
id: '/auth/oidc/callback',
|
||||||
path: '/auth/oidc/callback',
|
path: '/auth/oidc/callback',
|
||||||
@@ -67,28 +95,30 @@ const AuthOidcCallbackRoute = AuthOidcCallbackImport.update({
|
|||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
const AppSubscriptionsManageRoute = AppSubscriptionsManageImport.update({
|
const AppSubscriptionsManageRoute = AppSubscriptionsManageImport.update({
|
||||||
id: '/subscriptions/manage',
|
id: '/manage',
|
||||||
path: '/subscriptions/manage',
|
path: '/manage',
|
||||||
getParentRoute: () => AppRoute,
|
getParentRoute: () => AppSubscriptionsRouteRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
const AppSubscriptionsCreateRoute = AppSubscriptionsCreateImport.update({
|
const AppSubscriptionsCreateRoute = AppSubscriptionsCreateImport.update({
|
||||||
id: '/subscriptions/create',
|
id: '/create',
|
||||||
path: '/subscriptions/create',
|
path: '/create',
|
||||||
getParentRoute: () => AppRoute,
|
getParentRoute: () => AppSubscriptionsRouteRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
const AppPlaygroundGraphqlApiRoute = AppPlaygroundGraphqlApiImport.update({
|
const AppPlaygroundGraphqlApiRoute = AppPlaygroundGraphqlApiImport.update({
|
||||||
id: '/playground/graphql-api',
|
id: '/graphql-api',
|
||||||
path: '/playground/graphql-api',
|
path: '/graphql-api',
|
||||||
getParentRoute: () => AppRoute,
|
getParentRoute: () => AppPlaygroundRouteRoute,
|
||||||
} as any)
|
} as any).lazy(() =>
|
||||||
|
import('./routes/_app/playground/graphql-api.lazy').then((d) => d.Route),
|
||||||
|
)
|
||||||
|
|
||||||
const AppSubscriptionsEditSubscriptionIdRoute =
|
const AppSubscriptionsEditSubscriptionIdRoute =
|
||||||
AppSubscriptionsEditSubscriptionIdImport.update({
|
AppSubscriptionsEditSubscriptionIdImport.update({
|
||||||
id: '/subscriptions/edit/$subscription-id',
|
id: '/edit/$subscription-id',
|
||||||
path: '/subscriptions/edit/$subscription-id',
|
path: '/edit/$subscription-id',
|
||||||
getParentRoute: () => AppRoute,
|
getParentRoute: () => AppSubscriptionsRouteRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
// Populate the FileRoutesByPath interface
|
// Populate the FileRoutesByPath interface
|
||||||
@@ -102,6 +132,13 @@ declare module '@tanstack/solid-router' {
|
|||||||
preLoaderRoute: typeof IndexImport
|
preLoaderRoute: typeof IndexImport
|
||||||
parentRoute: typeof rootRoute
|
parentRoute: typeof rootRoute
|
||||||
}
|
}
|
||||||
|
'/404': {
|
||||||
|
id: '/404'
|
||||||
|
path: '/404'
|
||||||
|
fullPath: '/404'
|
||||||
|
preLoaderRoute: typeof R404Import
|
||||||
|
parentRoute: typeof rootRoute
|
||||||
|
}
|
||||||
'/_app': {
|
'/_app': {
|
||||||
id: '/_app'
|
id: '/_app'
|
||||||
path: ''
|
path: ''
|
||||||
@@ -116,6 +153,27 @@ declare module '@tanstack/solid-router' {
|
|||||||
preLoaderRoute: typeof AboutImport
|
preLoaderRoute: typeof AboutImport
|
||||||
parentRoute: typeof rootRoute
|
parentRoute: typeof rootRoute
|
||||||
}
|
}
|
||||||
|
'/_app/playground': {
|
||||||
|
id: '/_app/playground'
|
||||||
|
path: '/playground'
|
||||||
|
fullPath: '/playground'
|
||||||
|
preLoaderRoute: typeof AppPlaygroundRouteImport
|
||||||
|
parentRoute: typeof AppImport
|
||||||
|
}
|
||||||
|
'/_app/settings': {
|
||||||
|
id: '/_app/settings'
|
||||||
|
path: '/settings'
|
||||||
|
fullPath: '/settings'
|
||||||
|
preLoaderRoute: typeof AppSettingsRouteImport
|
||||||
|
parentRoute: typeof AppImport
|
||||||
|
}
|
||||||
|
'/_app/subscriptions': {
|
||||||
|
id: '/_app/subscriptions'
|
||||||
|
path: '/subscriptions'
|
||||||
|
fullPath: '/subscriptions'
|
||||||
|
preLoaderRoute: typeof AppSubscriptionsRouteImport
|
||||||
|
parentRoute: typeof AppImport
|
||||||
|
}
|
||||||
'/_app/explore': {
|
'/_app/explore': {
|
||||||
id: '/_app/explore'
|
id: '/_app/explore'
|
||||||
path: '/explore'
|
path: '/explore'
|
||||||
@@ -139,24 +197,24 @@ declare module '@tanstack/solid-router' {
|
|||||||
}
|
}
|
||||||
'/_app/playground/graphql-api': {
|
'/_app/playground/graphql-api': {
|
||||||
id: '/_app/playground/graphql-api'
|
id: '/_app/playground/graphql-api'
|
||||||
path: '/playground/graphql-api'
|
path: '/graphql-api'
|
||||||
fullPath: '/playground/graphql-api'
|
fullPath: '/playground/graphql-api'
|
||||||
preLoaderRoute: typeof AppPlaygroundGraphqlApiImport
|
preLoaderRoute: typeof AppPlaygroundGraphqlApiImport
|
||||||
parentRoute: typeof AppImport
|
parentRoute: typeof AppPlaygroundRouteImport
|
||||||
}
|
}
|
||||||
'/_app/subscriptions/create': {
|
'/_app/subscriptions/create': {
|
||||||
id: '/_app/subscriptions/create'
|
id: '/_app/subscriptions/create'
|
||||||
path: '/subscriptions/create'
|
path: '/create'
|
||||||
fullPath: '/subscriptions/create'
|
fullPath: '/subscriptions/create'
|
||||||
preLoaderRoute: typeof AppSubscriptionsCreateImport
|
preLoaderRoute: typeof AppSubscriptionsCreateImport
|
||||||
parentRoute: typeof AppImport
|
parentRoute: typeof AppSubscriptionsRouteImport
|
||||||
}
|
}
|
||||||
'/_app/subscriptions/manage': {
|
'/_app/subscriptions/manage': {
|
||||||
id: '/_app/subscriptions/manage'
|
id: '/_app/subscriptions/manage'
|
||||||
path: '/subscriptions/manage'
|
path: '/manage'
|
||||||
fullPath: '/subscriptions/manage'
|
fullPath: '/subscriptions/manage'
|
||||||
preLoaderRoute: typeof AppSubscriptionsManageImport
|
preLoaderRoute: typeof AppSubscriptionsManageImport
|
||||||
parentRoute: typeof AppImport
|
parentRoute: typeof AppSubscriptionsRouteImport
|
||||||
}
|
}
|
||||||
'/auth/oidc/callback': {
|
'/auth/oidc/callback': {
|
||||||
id: '/auth/oidc/callback'
|
id: '/auth/oidc/callback'
|
||||||
@@ -167,39 +225,69 @@ declare module '@tanstack/solid-router' {
|
|||||||
}
|
}
|
||||||
'/_app/subscriptions/edit/$subscription-id': {
|
'/_app/subscriptions/edit/$subscription-id': {
|
||||||
id: '/_app/subscriptions/edit/$subscription-id'
|
id: '/_app/subscriptions/edit/$subscription-id'
|
||||||
path: '/subscriptions/edit/$subscription-id'
|
path: '/edit/$subscription-id'
|
||||||
fullPath: '/subscriptions/edit/$subscription-id'
|
fullPath: '/subscriptions/edit/$subscription-id'
|
||||||
preLoaderRoute: typeof AppSubscriptionsEditSubscriptionIdImport
|
preLoaderRoute: typeof AppSubscriptionsEditSubscriptionIdImport
|
||||||
parentRoute: typeof AppImport
|
parentRoute: typeof AppSubscriptionsRouteImport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create and export the route tree
|
// Create and export the route tree
|
||||||
|
|
||||||
interface AppRouteChildren {
|
interface AppPlaygroundRouteRouteChildren {
|
||||||
AppExploreRoute: typeof AppExploreRoute
|
|
||||||
AppPlaygroundGraphqlApiRoute: typeof AppPlaygroundGraphqlApiRoute
|
AppPlaygroundGraphqlApiRoute: typeof AppPlaygroundGraphqlApiRoute
|
||||||
|
}
|
||||||
|
|
||||||
|
const AppPlaygroundRouteRouteChildren: AppPlaygroundRouteRouteChildren = {
|
||||||
|
AppPlaygroundGraphqlApiRoute: AppPlaygroundGraphqlApiRoute,
|
||||||
|
}
|
||||||
|
|
||||||
|
const AppPlaygroundRouteRouteWithChildren =
|
||||||
|
AppPlaygroundRouteRoute._addFileChildren(AppPlaygroundRouteRouteChildren)
|
||||||
|
|
||||||
|
interface AppSubscriptionsRouteRouteChildren {
|
||||||
AppSubscriptionsCreateRoute: typeof AppSubscriptionsCreateRoute
|
AppSubscriptionsCreateRoute: typeof AppSubscriptionsCreateRoute
|
||||||
AppSubscriptionsManageRoute: typeof AppSubscriptionsManageRoute
|
AppSubscriptionsManageRoute: typeof AppSubscriptionsManageRoute
|
||||||
AppSubscriptionsEditSubscriptionIdRoute: typeof AppSubscriptionsEditSubscriptionIdRoute
|
AppSubscriptionsEditSubscriptionIdRoute: typeof AppSubscriptionsEditSubscriptionIdRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
const AppRouteChildren: AppRouteChildren = {
|
const AppSubscriptionsRouteRouteChildren: AppSubscriptionsRouteRouteChildren = {
|
||||||
AppExploreRoute: AppExploreRoute,
|
|
||||||
AppPlaygroundGraphqlApiRoute: AppPlaygroundGraphqlApiRoute,
|
|
||||||
AppSubscriptionsCreateRoute: AppSubscriptionsCreateRoute,
|
AppSubscriptionsCreateRoute: AppSubscriptionsCreateRoute,
|
||||||
AppSubscriptionsManageRoute: AppSubscriptionsManageRoute,
|
AppSubscriptionsManageRoute: AppSubscriptionsManageRoute,
|
||||||
AppSubscriptionsEditSubscriptionIdRoute:
|
AppSubscriptionsEditSubscriptionIdRoute:
|
||||||
AppSubscriptionsEditSubscriptionIdRoute,
|
AppSubscriptionsEditSubscriptionIdRoute,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AppSubscriptionsRouteRouteWithChildren =
|
||||||
|
AppSubscriptionsRouteRoute._addFileChildren(
|
||||||
|
AppSubscriptionsRouteRouteChildren,
|
||||||
|
)
|
||||||
|
|
||||||
|
interface AppRouteChildren {
|
||||||
|
AppPlaygroundRouteRoute: typeof AppPlaygroundRouteRouteWithChildren
|
||||||
|
AppSettingsRouteRoute: typeof AppSettingsRouteRoute
|
||||||
|
AppSubscriptionsRouteRoute: typeof AppSubscriptionsRouteRouteWithChildren
|
||||||
|
AppExploreRoute: typeof AppExploreRoute
|
||||||
|
}
|
||||||
|
|
||||||
|
const AppRouteChildren: AppRouteChildren = {
|
||||||
|
AppPlaygroundRouteRoute: AppPlaygroundRouteRouteWithChildren,
|
||||||
|
AppSettingsRouteRoute: AppSettingsRouteRoute,
|
||||||
|
AppSubscriptionsRouteRoute: AppSubscriptionsRouteRouteWithChildren,
|
||||||
|
AppExploreRoute: AppExploreRoute,
|
||||||
|
}
|
||||||
|
|
||||||
const AppRouteWithChildren = AppRoute._addFileChildren(AppRouteChildren)
|
const AppRouteWithChildren = AppRoute._addFileChildren(AppRouteChildren)
|
||||||
|
|
||||||
export interface FileRoutesByFullPath {
|
export interface FileRoutesByFullPath {
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
|
'/404': typeof R404Route
|
||||||
'': typeof AppRouteWithChildren
|
'': typeof AppRouteWithChildren
|
||||||
'/about': typeof AboutRoute
|
'/about': typeof AboutRoute
|
||||||
|
'/playground': typeof AppPlaygroundRouteRouteWithChildren
|
||||||
|
'/settings': typeof AppSettingsRouteRoute
|
||||||
|
'/subscriptions': typeof AppSubscriptionsRouteRouteWithChildren
|
||||||
'/explore': typeof AppExploreRoute
|
'/explore': typeof AppExploreRoute
|
||||||
'/auth/sign-in': typeof AuthSignInRoute
|
'/auth/sign-in': typeof AuthSignInRoute
|
||||||
'/auth/sign-up': typeof AuthSignUpRoute
|
'/auth/sign-up': typeof AuthSignUpRoute
|
||||||
@@ -212,8 +300,12 @@ export interface FileRoutesByFullPath {
|
|||||||
|
|
||||||
export interface FileRoutesByTo {
|
export interface FileRoutesByTo {
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
|
'/404': typeof R404Route
|
||||||
'': typeof AppRouteWithChildren
|
'': typeof AppRouteWithChildren
|
||||||
'/about': typeof AboutRoute
|
'/about': typeof AboutRoute
|
||||||
|
'/playground': typeof AppPlaygroundRouteRouteWithChildren
|
||||||
|
'/settings': typeof AppSettingsRouteRoute
|
||||||
|
'/subscriptions': typeof AppSubscriptionsRouteRouteWithChildren
|
||||||
'/explore': typeof AppExploreRoute
|
'/explore': typeof AppExploreRoute
|
||||||
'/auth/sign-in': typeof AuthSignInRoute
|
'/auth/sign-in': typeof AuthSignInRoute
|
||||||
'/auth/sign-up': typeof AuthSignUpRoute
|
'/auth/sign-up': typeof AuthSignUpRoute
|
||||||
@@ -227,8 +319,12 @@ export interface FileRoutesByTo {
|
|||||||
export interface FileRoutesById {
|
export interface FileRoutesById {
|
||||||
__root__: typeof rootRoute
|
__root__: typeof rootRoute
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
|
'/404': typeof R404Route
|
||||||
'/_app': typeof AppRouteWithChildren
|
'/_app': typeof AppRouteWithChildren
|
||||||
'/about': typeof AboutRoute
|
'/about': typeof AboutRoute
|
||||||
|
'/_app/playground': typeof AppPlaygroundRouteRouteWithChildren
|
||||||
|
'/_app/settings': typeof AppSettingsRouteRoute
|
||||||
|
'/_app/subscriptions': typeof AppSubscriptionsRouteRouteWithChildren
|
||||||
'/_app/explore': typeof AppExploreRoute
|
'/_app/explore': typeof AppExploreRoute
|
||||||
'/auth/sign-in': typeof AuthSignInRoute
|
'/auth/sign-in': typeof AuthSignInRoute
|
||||||
'/auth/sign-up': typeof AuthSignUpRoute
|
'/auth/sign-up': typeof AuthSignUpRoute
|
||||||
@@ -243,8 +339,12 @@ export interface FileRouteTypes {
|
|||||||
fileRoutesByFullPath: FileRoutesByFullPath
|
fileRoutesByFullPath: FileRoutesByFullPath
|
||||||
fullPaths:
|
fullPaths:
|
||||||
| '/'
|
| '/'
|
||||||
|
| '/404'
|
||||||
| ''
|
| ''
|
||||||
| '/about'
|
| '/about'
|
||||||
|
| '/playground'
|
||||||
|
| '/settings'
|
||||||
|
| '/subscriptions'
|
||||||
| '/explore'
|
| '/explore'
|
||||||
| '/auth/sign-in'
|
| '/auth/sign-in'
|
||||||
| '/auth/sign-up'
|
| '/auth/sign-up'
|
||||||
@@ -256,8 +356,12 @@ export interface FileRouteTypes {
|
|||||||
fileRoutesByTo: FileRoutesByTo
|
fileRoutesByTo: FileRoutesByTo
|
||||||
to:
|
to:
|
||||||
| '/'
|
| '/'
|
||||||
|
| '/404'
|
||||||
| ''
|
| ''
|
||||||
| '/about'
|
| '/about'
|
||||||
|
| '/playground'
|
||||||
|
| '/settings'
|
||||||
|
| '/subscriptions'
|
||||||
| '/explore'
|
| '/explore'
|
||||||
| '/auth/sign-in'
|
| '/auth/sign-in'
|
||||||
| '/auth/sign-up'
|
| '/auth/sign-up'
|
||||||
@@ -269,8 +373,12 @@ export interface FileRouteTypes {
|
|||||||
id:
|
id:
|
||||||
| '__root__'
|
| '__root__'
|
||||||
| '/'
|
| '/'
|
||||||
|
| '/404'
|
||||||
| '/_app'
|
| '/_app'
|
||||||
| '/about'
|
| '/about'
|
||||||
|
| '/_app/playground'
|
||||||
|
| '/_app/settings'
|
||||||
|
| '/_app/subscriptions'
|
||||||
| '/_app/explore'
|
| '/_app/explore'
|
||||||
| '/auth/sign-in'
|
| '/auth/sign-in'
|
||||||
| '/auth/sign-up'
|
| '/auth/sign-up'
|
||||||
@@ -284,6 +392,7 @@ export interface FileRouteTypes {
|
|||||||
|
|
||||||
export interface RootRouteChildren {
|
export interface RootRouteChildren {
|
||||||
IndexRoute: typeof IndexRoute
|
IndexRoute: typeof IndexRoute
|
||||||
|
R404Route: typeof R404Route
|
||||||
AppRoute: typeof AppRouteWithChildren
|
AppRoute: typeof AppRouteWithChildren
|
||||||
AboutRoute: typeof AboutRoute
|
AboutRoute: typeof AboutRoute
|
||||||
AuthSignInRoute: typeof AuthSignInRoute
|
AuthSignInRoute: typeof AuthSignInRoute
|
||||||
@@ -293,6 +402,7 @@ export interface RootRouteChildren {
|
|||||||
|
|
||||||
const rootRouteChildren: RootRouteChildren = {
|
const rootRouteChildren: RootRouteChildren = {
|
||||||
IndexRoute: IndexRoute,
|
IndexRoute: IndexRoute,
|
||||||
|
R404Route: R404Route,
|
||||||
AppRoute: AppRouteWithChildren,
|
AppRoute: AppRouteWithChildren,
|
||||||
AboutRoute: AboutRoute,
|
AboutRoute: AboutRoute,
|
||||||
AuthSignInRoute: AuthSignInRoute,
|
AuthSignInRoute: AuthSignInRoute,
|
||||||
@@ -311,6 +421,7 @@ export const routeTree = rootRoute
|
|||||||
"filePath": "__root.tsx",
|
"filePath": "__root.tsx",
|
||||||
"children": [
|
"children": [
|
||||||
"/",
|
"/",
|
||||||
|
"/404",
|
||||||
"/_app",
|
"/_app",
|
||||||
"/about",
|
"/about",
|
||||||
"/auth/sign-in",
|
"/auth/sign-in",
|
||||||
@@ -321,19 +432,41 @@ export const routeTree = rootRoute
|
|||||||
"/": {
|
"/": {
|
||||||
"filePath": "index.tsx"
|
"filePath": "index.tsx"
|
||||||
},
|
},
|
||||||
|
"/404": {
|
||||||
|
"filePath": "404.tsx"
|
||||||
|
},
|
||||||
"/_app": {
|
"/_app": {
|
||||||
"filePath": "_app.tsx",
|
"filePath": "_app.tsx",
|
||||||
"children": [
|
"children": [
|
||||||
"/_app/explore",
|
"/_app/playground",
|
||||||
"/_app/playground/graphql-api",
|
"/_app/settings",
|
||||||
"/_app/subscriptions/create",
|
"/_app/subscriptions",
|
||||||
"/_app/subscriptions/manage",
|
"/_app/explore"
|
||||||
"/_app/subscriptions/edit/$subscription-id"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"/about": {
|
"/about": {
|
||||||
"filePath": "about.tsx"
|
"filePath": "about.tsx"
|
||||||
},
|
},
|
||||||
|
"/_app/playground": {
|
||||||
|
"filePath": "_app/playground/route.tsx",
|
||||||
|
"parent": "/_app",
|
||||||
|
"children": [
|
||||||
|
"/_app/playground/graphql-api"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"/_app/settings": {
|
||||||
|
"filePath": "_app/settings/route.tsx",
|
||||||
|
"parent": "/_app"
|
||||||
|
},
|
||||||
|
"/_app/subscriptions": {
|
||||||
|
"filePath": "_app/subscriptions/route.tsx",
|
||||||
|
"parent": "/_app",
|
||||||
|
"children": [
|
||||||
|
"/_app/subscriptions/create",
|
||||||
|
"/_app/subscriptions/manage",
|
||||||
|
"/_app/subscriptions/edit/$subscription-id"
|
||||||
|
]
|
||||||
|
},
|
||||||
"/_app/explore": {
|
"/_app/explore": {
|
||||||
"filePath": "_app/explore.tsx",
|
"filePath": "_app/explore.tsx",
|
||||||
"parent": "/_app"
|
"parent": "/_app"
|
||||||
@@ -346,22 +479,22 @@ export const routeTree = rootRoute
|
|||||||
},
|
},
|
||||||
"/_app/playground/graphql-api": {
|
"/_app/playground/graphql-api": {
|
||||||
"filePath": "_app/playground/graphql-api.tsx",
|
"filePath": "_app/playground/graphql-api.tsx",
|
||||||
"parent": "/_app"
|
"parent": "/_app/playground"
|
||||||
},
|
},
|
||||||
"/_app/subscriptions/create": {
|
"/_app/subscriptions/create": {
|
||||||
"filePath": "_app/subscriptions/create.tsx",
|
"filePath": "_app/subscriptions/create.tsx",
|
||||||
"parent": "/_app"
|
"parent": "/_app/subscriptions"
|
||||||
},
|
},
|
||||||
"/_app/subscriptions/manage": {
|
"/_app/subscriptions/manage": {
|
||||||
"filePath": "_app/subscriptions/manage.tsx",
|
"filePath": "_app/subscriptions/manage.tsx",
|
||||||
"parent": "/_app"
|
"parent": "/_app/subscriptions"
|
||||||
},
|
},
|
||||||
"/auth/oidc/callback": {
|
"/auth/oidc/callback": {
|
||||||
"filePath": "auth/oidc/callback.tsx"
|
"filePath": "auth/oidc/callback.tsx"
|
||||||
},
|
},
|
||||||
"/_app/subscriptions/edit/$subscription-id": {
|
"/_app/subscriptions/edit/$subscription-id": {
|
||||||
"filePath": "_app/subscriptions/edit/$subscription-id.tsx",
|
"filePath": "_app/subscriptions/edit.$subscription-id.tsx",
|
||||||
"parent": "/_app"
|
"parent": "/_app/subscriptions"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
apps/webui/src/routes/404.tsx
Normal file
6
apps/webui/src/routes/404.tsx
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/solid-router';
|
||||||
|
import { AppNotFoundComponent } from '~/components/layout/app-not-found';
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/404')({
|
||||||
|
component: AppNotFoundComponent,
|
||||||
|
});
|
||||||
@@ -1,8 +1,12 @@
|
|||||||
import { Outlet, createRootRouteWithContext } from '@tanstack/solid-router';
|
import { Outlet, createRootRouteWithContext } from '@tanstack/solid-router';
|
||||||
import type { RouterContext } from '../auth/context';
|
import { Home } from 'lucide-solid';
|
||||||
|
import type { RouteStateDataOption, RouterContext } from '~/traits/router';
|
||||||
|
|
||||||
export const Route = createRootRouteWithContext<RouterContext>()({
|
export const Route = createRootRouteWithContext<RouterContext>()({
|
||||||
component: () => {
|
component: Outlet,
|
||||||
return <Outlet />;
|
staticData: {
|
||||||
|
breadcrumb: {
|
||||||
|
icon: Home,
|
||||||
},
|
},
|
||||||
|
} satisfies RouteStateDataOption,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
import { createFileRoute } from '@tanstack/solid-router';
|
import { Outlet, createFileRoute } from '@tanstack/solid-router';
|
||||||
import { beforeLoadGuard } from '~/auth/guard';
|
import { beforeLoadGuard } from '~/auth/guard';
|
||||||
import { AppLayout } from '~/components/layout/app-layout';
|
import { AppAside } from '~/components/layout/app-layout';
|
||||||
|
|
||||||
export const Route = createFileRoute('/_app')({
|
export const Route = createFileRoute('/_app')({
|
||||||
component: AppLayout,
|
component: AppLayoutRoute,
|
||||||
beforeLoad: beforeLoadGuard,
|
beforeLoad: beforeLoadGuard,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function AppLayoutRoute() {
|
||||||
|
return (
|
||||||
|
<AppAside extractBreadcrumbFromRoutes>
|
||||||
|
<Outlet />
|
||||||
|
</AppAside>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
import { createFileRoute } from '@tanstack/solid-router';
|
import { createFileRoute } from '@tanstack/solid-router';
|
||||||
|
import type { RouteStateDataOption } from '~/traits/router';
|
||||||
|
|
||||||
export const Route = createFileRoute('/_app/explore')({
|
export const Route = createFileRoute('/_app/explore')({
|
||||||
component: RouteComponent,
|
component: ExploreRouteComponent,
|
||||||
|
staticData: {
|
||||||
|
breadcrumb: {
|
||||||
|
label: 'Explore',
|
||||||
|
},
|
||||||
|
} satisfies RouteStateDataOption,
|
||||||
});
|
});
|
||||||
|
|
||||||
function RouteComponent() {
|
function ExploreRouteComponent() {
|
||||||
return <div>Hello "/_app/explore"!</div>;
|
return <div>Hello "/_app/explore"!</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
54
apps/webui/src/routes/_app/playground/graphql-api.lazy.tsx
Normal file
54
apps/webui/src/routes/_app/playground/graphql-api.lazy.tsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { type Fetcher, createGraphiQLFetcher } from '@graphiql/toolkit';
|
||||||
|
import { createLazyFileRoute } from '@tanstack/solid-router';
|
||||||
|
import GraphiQL from 'graphiql';
|
||||||
|
import React from 'react';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
import { onCleanup, onMount } from 'solid-js';
|
||||||
|
import { isOidcAuth } from '~/auth/config';
|
||||||
|
import { useAuth } from '~/auth/hooks';
|
||||||
|
import 'graphiql/graphiql.css';
|
||||||
|
import { firstValueFrom } from 'rxjs';
|
||||||
|
|
||||||
|
export const Route = createLazyFileRoute('/_app/playground/graphql-api')({
|
||||||
|
component: PlaygroundGraphQLApiRouteComponent,
|
||||||
|
});
|
||||||
|
|
||||||
|
function PlaygroundGraphQLApiRouteComponent() {
|
||||||
|
const auth = useAuth();
|
||||||
|
let containerRef: HTMLDivElement | undefined;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (containerRef) {
|
||||||
|
const reactRoot = createRoot(containerRef);
|
||||||
|
if (reactRoot) {
|
||||||
|
const fetcher: Fetcher = async (props) => {
|
||||||
|
const accessToken = isOidcAuth
|
||||||
|
? await firstValueFrom(auth.oidcSecurityService!.getAccessToken())
|
||||||
|
: undefined;
|
||||||
|
return createGraphiQLFetcher({
|
||||||
|
url: '/api/graphql',
|
||||||
|
headers: accessToken
|
||||||
|
? {
|
||||||
|
Authorization: `Bearer ${accessToken}`,
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
})(props);
|
||||||
|
};
|
||||||
|
const g = React.createElement(GraphiQL, {
|
||||||
|
fetcher,
|
||||||
|
});
|
||||||
|
reactRoot.render(g);
|
||||||
|
|
||||||
|
onCleanup(() => reactRoot.unmount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-id="graphiql-playground-container"
|
||||||
|
class="h-full"
|
||||||
|
ref={containerRef}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
import { createFileRoute } from '@tanstack/solid-router'
|
import { createFileRoute } from '@tanstack/solid-router';
|
||||||
|
import { buildLeafRouteStaticData } from '~/utils/route';
|
||||||
|
|
||||||
export const Route = createFileRoute('/_app/playground/graphql-api')({
|
export const Route = createFileRoute('/_app/playground/graphql-api')({
|
||||||
component: RouteComponent,
|
staticData: buildLeafRouteStaticData({ title: 'GraphQL Api' }),
|
||||||
})
|
});
|
||||||
|
|
||||||
function RouteComponent() {
|
|
||||||
return <div>Hello "/_app/playground/group-api"!</div>
|
|
||||||
}
|
|
||||||
|
|||||||
8
apps/webui/src/routes/_app/playground/route.tsx
Normal file
8
apps/webui/src/routes/_app/playground/route.tsx
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/solid-router';
|
||||||
|
import { buildVirtualBranchRouteOptions } from '~/utils/route';
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/_app/playground')(
|
||||||
|
buildVirtualBranchRouteOptions({
|
||||||
|
title: 'Playground',
|
||||||
|
})
|
||||||
|
);
|
||||||
8
apps/webui/src/routes/_app/settings/route.tsx
Normal file
8
apps/webui/src/routes/_app/settings/route.tsx
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/solid-router';
|
||||||
|
import { buildVirtualBranchRouteOptions } from '~/utils/route';
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/_app/settings')(
|
||||||
|
buildVirtualBranchRouteOptions({
|
||||||
|
title: 'Settings',
|
||||||
|
})
|
||||||
|
);
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
import { createFileRoute } from '@tanstack/solid-router';
|
import { createFileRoute } from '@tanstack/solid-router';
|
||||||
|
import type { RouteStateDataOption } from '~/traits/router';
|
||||||
|
|
||||||
export const Route = createFileRoute('/_app/subscriptions/create')({
|
export const Route = createFileRoute('/_app/subscriptions/create')({
|
||||||
component: RouteComponent,
|
component: SubscriptionCreateRouteComponent,
|
||||||
|
staticData: {
|
||||||
|
breadcrumb: { label: 'Create' },
|
||||||
|
} satisfies RouteStateDataOption,
|
||||||
});
|
});
|
||||||
|
|
||||||
function RouteComponent() {
|
function SubscriptionCreateRouteComponent() {
|
||||||
return <div>Hello "/subscriptions/create"!</div>;
|
return <div>Hello "/subscriptions/create"!</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/solid-router';
|
||||||
|
import type { RouteStateDataOption } from '~/traits/router';
|
||||||
|
|
||||||
|
export const Route = createFileRoute(
|
||||||
|
'/_app/subscriptions/edit/$subscription-id'
|
||||||
|
)({
|
||||||
|
component: RouteComponent,
|
||||||
|
staticData: {
|
||||||
|
breadcrumb: { label: 'Edit' },
|
||||||
|
} satisfies RouteStateDataOption,
|
||||||
|
});
|
||||||
|
|
||||||
|
function RouteComponent() {
|
||||||
|
return <div>Hello "/subscriptions/edit/$subscription-id"!</div>;
|
||||||
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { createFileRoute } from '@tanstack/solid-router'
|
|
||||||
|
|
||||||
export const Route = createFileRoute('/_app/subscriptions/edit/$subscription-id')({
|
|
||||||
component: RouteComponent,
|
|
||||||
})
|
|
||||||
|
|
||||||
function RouteComponent() {
|
|
||||||
return <div>Hello "/subscriptions/edit/$subscription-id"!</div>
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
import { createFileRoute } from '@tanstack/solid-router';
|
import { createFileRoute } from '@tanstack/solid-router';
|
||||||
|
import type { RouteStateDataOption } from '~/traits/router';
|
||||||
|
|
||||||
export const Route = createFileRoute('/_app/subscriptions/manage')({
|
export const Route = createFileRoute('/_app/subscriptions/manage')({
|
||||||
component: SubscriptionDashboard,
|
component: SubscriptionManage,
|
||||||
|
staticData: {
|
||||||
|
breadcrumb: { label: 'Manage' },
|
||||||
|
} satisfies RouteStateDataOption,
|
||||||
});
|
});
|
||||||
|
|
||||||
function SubscriptionDashboard() {
|
function SubscriptionManage() {
|
||||||
return <div>Hello "/subscriptions/manage"!</div>;
|
return <div>Hello "/subscriptions/manage"!</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
8
apps/webui/src/routes/_app/subscriptions/route.tsx
Normal file
8
apps/webui/src/routes/_app/subscriptions/route.tsx
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/solid-router';
|
||||||
|
import { buildVirtualBranchRouteOptions } from '~/utils/route';
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/_app/subscriptions')(
|
||||||
|
buildVirtualBranchRouteOptions({
|
||||||
|
title: 'Subscriptions',
|
||||||
|
})
|
||||||
|
);
|
||||||
@@ -1,57 +1,15 @@
|
|||||||
import { createFileRoute } from '@tanstack/solid-router';
|
import { createFileRoute } from '@tanstack/solid-router';
|
||||||
import { AppSidebar } from '~/components/layout/app-sidebar';
|
import { AppAside } from '~/components/layout/app-layout';
|
||||||
import {
|
import { AppSkeleton } from '~/components/layout/app-skeleton';
|
||||||
Breadcrumb,
|
|
||||||
BreadcrumbItem,
|
|
||||||
BreadcrumbLink,
|
|
||||||
BreadcrumbList,
|
|
||||||
BreadcrumbSeparator,
|
|
||||||
} from '~/components/ui/breadcrumb';
|
|
||||||
import { Separator } from '~/components/ui/separator';
|
|
||||||
import {
|
|
||||||
SidebarInset,
|
|
||||||
SidebarProvider,
|
|
||||||
SidebarTrigger,
|
|
||||||
} from '~/components/ui/sidebar';
|
|
||||||
|
|
||||||
export const Route = createFileRoute('/')({
|
export const Route = createFileRoute('/')({
|
||||||
component: Home,
|
component: HomeRouteComponent,
|
||||||
beforeLoad: async () => {},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function Home() {
|
function HomeRouteComponent() {
|
||||||
return (
|
return (
|
||||||
<SidebarProvider>
|
<AppAside class="flex flex-1 flex-col gap-4" extractBreadcrumbFromRoutes>
|
||||||
<AppSidebar />
|
<AppSkeleton />
|
||||||
<SidebarInset>
|
</AppAside>
|
||||||
<header class="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12">
|
|
||||||
<div class="flex items-center gap-2 px-4">
|
|
||||||
<SidebarTrigger class="-ml-1" />
|
|
||||||
<Separator orientation="vertical" class="mr-2 h-4" />
|
|
||||||
<Breadcrumb>
|
|
||||||
<BreadcrumbList>
|
|
||||||
<BreadcrumbItem class="hidden md:block">
|
|
||||||
<BreadcrumbLink href="#">
|
|
||||||
Building Your Application
|
|
||||||
</BreadcrumbLink>
|
|
||||||
</BreadcrumbItem>
|
|
||||||
<BreadcrumbSeparator class="hidden md:block" />
|
|
||||||
<BreadcrumbItem>
|
|
||||||
<BreadcrumbLink current>Data Fetching</BreadcrumbLink>
|
|
||||||
</BreadcrumbItem>
|
|
||||||
</BreadcrumbList>
|
|
||||||
</Breadcrumb>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<div class="flex flex-1 flex-col gap-4 p-4 pt-0">
|
|
||||||
<div class="grid auto-rows-min gap-4 md:grid-cols-3">
|
|
||||||
<div class="aspect-video rounded-xl bg-muted/50" />
|
|
||||||
<div class="aspect-video rounded-xl bg-muted/50" />
|
|
||||||
<div class="aspect-video rounded-xl bg-muted/50" />
|
|
||||||
</div>
|
|
||||||
<div class="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
|
|
||||||
</div>
|
|
||||||
</SidebarInset>
|
|
||||||
</SidebarProvider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
21
apps/webui/src/traits/router.ts
Normal file
21
apps/webui/src/traits/router.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import type { Injector } from '@outposts/injection-js';
|
||||||
|
import type { LucideIcon } from 'lucide-solid';
|
||||||
|
import type { OidcSecurityService } from 'oidc-client-rx';
|
||||||
|
import type { Accessor } from 'solid-js';
|
||||||
|
import type { ProLinkProps } from '~/components/ui/pro-link';
|
||||||
|
|
||||||
|
export type RouterContext = {
|
||||||
|
isAuthenticated: Accessor<boolean>;
|
||||||
|
injector: Injector;
|
||||||
|
oidcSecurityService: OidcSecurityService;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RouteBreadcrumbItem = {
|
||||||
|
label?: string;
|
||||||
|
icon?: LucideIcon;
|
||||||
|
link?: Omit<ProLinkProps, 'aria-current' | 'current'>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface RouteStateDataOption {
|
||||||
|
breadcrumb?: RouteBreadcrumbItem;
|
||||||
|
}
|
||||||
36
apps/webui/src/utils/route/index.ts
Normal file
36
apps/webui/src/utils/route/index.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { FileRoutesByPath, Outlet } from '@tanstack/solid-router';
|
||||||
|
import { guardRouteIndexAsNotFound } from '~/components/layout/app-not-found';
|
||||||
|
import type { RouteStateDataOption } from '~/traits/router';
|
||||||
|
|
||||||
|
export interface BuildVirtualBranchRouteOptions {
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildVirtualBranchRouteOptions(
|
||||||
|
options: BuildVirtualBranchRouteOptions
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
beforeLoad: guardRouteIndexAsNotFound,
|
||||||
|
staticData: {
|
||||||
|
breadcrumb: {
|
||||||
|
label: options.title,
|
||||||
|
link: undefined,
|
||||||
|
},
|
||||||
|
} satisfies RouteStateDataOption,
|
||||||
|
component: Outlet,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BuildLeafRouteStaticDataOptions {
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildLeafRouteStaticData(
|
||||||
|
options: BuildLeafRouteStaticDataOptions
|
||||||
|
): RouteStateDataOption {
|
||||||
|
return {
|
||||||
|
breadcrumb: {
|
||||||
|
label: options.title,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -60,7 +60,17 @@ module.exports = {
|
|||||||
card: {
|
card: {
|
||||||
DEFAULT: "hsl(var(--card))",
|
DEFAULT: "hsl(var(--card))",
|
||||||
foreground: "hsl(var(--card-foreground))"
|
foreground: "hsl(var(--card-foreground))"
|
||||||
}
|
},
|
||||||
|
sidebar: {
|
||||||
|
DEFAULT: 'hsl(var(--sidebar-background))',
|
||||||
|
foreground: 'hsl(var(--sidebar-foreground))',
|
||||||
|
primary: 'hsl(var(--sidebar-primary))',
|
||||||
|
'primary-foreground': 'hsl(var(--sidebar-primary-foreground))',
|
||||||
|
accent: 'hsl(var(--sidebar-accent))',
|
||||||
|
'accent-foreground': 'hsl(var(--sidebar-accent-foreground))',
|
||||||
|
border: 'hsl(var(--sidebar-border))',
|
||||||
|
ring: 'hsl(var(--sidebar-ring))',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
borderRadius: {
|
borderRadius: {
|
||||||
xl: "calc(var(--radius) + 4px)",
|
xl: "calc(var(--radius) + 4px)",
|
||||||
|
|||||||
@@ -8,6 +8,6 @@
|
|||||||
},
|
},
|
||||||
"aliases": {
|
"aliases": {
|
||||||
"components": "~/components/ui",
|
"components": "~/components/ui",
|
||||||
"utils": "~/styles/utils"
|
"utils": "~/utils/styles"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
justfile
5
justfile
@@ -14,8 +14,3 @@ dev-proxy:
|
|||||||
dev-recorder:
|
dev-recorder:
|
||||||
bacon recorder
|
bacon recorder
|
||||||
|
|
||||||
dev-playground:
|
|
||||||
pnpm run --filter=recorder dev
|
|
||||||
|
|
||||||
# play-recorder:
|
|
||||||
# cargo recorder-playground
|
|
||||||
|
|||||||
32
package.json
32
package.json
@@ -3,21 +3,14 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"description": "Kono bangumi?",
|
"description": "Kono bangumi?",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"workspaces": [
|
"workspaces": ["packages/*", "apps/*"],
|
||||||
"packages/*",
|
|
||||||
"apps/*"
|
|
||||||
],
|
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/dumtruck/konobangu.git"
|
"url": "https://github.com/dumtruck/konobangu.git"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "turbo build",
|
|
||||||
"dev": "turbo dev",
|
|
||||||
"lint": "ultracite lint",
|
"lint": "ultracite lint",
|
||||||
"format": "ultracite format",
|
"format": "ultracite format",
|
||||||
"test": "turbo test",
|
|
||||||
"analyze": "turbo analyze",
|
|
||||||
"bump-deps": "npx --yes npm-check-updates --deep -u -x react-day-picker && pnpm install",
|
"bump-deps": "npx --yes npm-check-updates --deep -u -x react-day-picker && pnpm install",
|
||||||
"clean": "git clean -xdf node_modules"
|
"clean": "git clean -xdf node_modules"
|
||||||
},
|
},
|
||||||
@@ -25,34 +18,11 @@
|
|||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22"
|
"node": ">=22"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
|
||||||
"@abraham/reflection": "^0.12.0",
|
|
||||||
"@outposts/injection-js": "^2.5.1",
|
|
||||||
"@tanstack/react-router": "^1.112.0",
|
|
||||||
"@tanstack/router-devtools": "^1.112.6",
|
|
||||||
"arktype": "^2.1.2",
|
|
||||||
"class-variance-authority": "^0.7.1",
|
|
||||||
"clsx": "^2.1.1",
|
|
||||||
"oidc-client-rx": "0.1.0-alpha.8",
|
|
||||||
"rxjs": "^7.8.2",
|
|
||||||
"tailwind-merge": "^3.0.2",
|
|
||||||
"tailwindcss": "^4.0.9",
|
|
||||||
"tailwindcss-animate": "^1.0.7"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@auto-it/all-contributors": "^11.3.0",
|
"@auto-it/all-contributors": "^11.3.0",
|
||||||
"@auto-it/first-time-contributor": "^11.3.0",
|
"@auto-it/first-time-contributor": "^11.3.0",
|
||||||
"@biomejs/biome": "1.9.4",
|
"@biomejs/biome": "1.9.4",
|
||||||
"@rsbuild/core": "^1.2.14",
|
|
||||||
"@rsbuild/plugin-babel": "^1.0.4",
|
|
||||||
"@tailwindcss/postcss": "^4.0.9",
|
|
||||||
"@tanstack/router-devtools": "^1.112.6",
|
|
||||||
"@tanstack/router-plugin": "^1.112.3",
|
|
||||||
"@types/jsdom": "^21.1.7",
|
|
||||||
"@types/node": "^22.13.8",
|
"@types/node": "^22.13.8",
|
||||||
"chalk": "^5.4.1",
|
|
||||||
"commander": "^13.1.0",
|
|
||||||
"postcss": "^8.5.3",
|
|
||||||
"shx": "^0.3.4",
|
"shx": "^0.3.4",
|
||||||
"tsx": "^4.19.2",
|
"tsx": "^4.19.2",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.8.2",
|
||||||
|
|||||||
1023
pnpm-lock.yaml
generated
1023
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -4,9 +4,6 @@
|
|||||||
{
|
{
|
||||||
"path": "./apps/email-playground"
|
"path": "./apps/email-playground"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "./apps/recorder"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "./apps/webui"
|
"path": "./apps/webui"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user