@korioinc/next-core 2.0.3 → 2.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,32 +1,3 @@
1
- type RequestMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
2
- type NextFetchOptions = {
3
- revalidate?: number | false;
4
- tags?: string[];
5
- };
6
- interface RequestOptions extends Omit<RequestInit, 'method' | 'headers' | 'body' | 'cache' | 'credentials'> {
7
- method?: RequestMethod;
8
- headers?: Record<string, string>;
9
- body?: unknown;
10
- params?: Record<string, string>;
11
- cache?: RequestCache;
12
- credentials?: RequestCredentials;
13
- next?: NextFetchOptions;
14
- }
15
- /**
16
- * Generic API response type
17
- */
18
- export interface ApiResponse<T> {
19
- data: T;
20
- success: boolean;
21
- message?: string;
22
- error?: unknown;
23
- }
24
- /**
25
- * Reusable API request function
26
- * @param endpoint - API endpoint path (without base URL)
27
- * @param options - Request options
28
- * @returns Promise with the response data
29
- */
30
- export declare function requestApi<T = unknown>(endpoint: string, options?: RequestOptions): Promise<T>;
31
- export {};
1
+ export { requestApi } from './server';
2
+ export type { ApiResponse } from './server';
32
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api-client/index.ts"],"names":[],"mappings":"AAMA,KAAK,aAAa,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEjE,KAAK,gBAAgB,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEzE,UAAU,cAAe,SAAQ,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,CAAC;IACzG,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC;IACR,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,CAAC,CAAC,CAsGxG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api-client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC"}
@@ -1,95 +1 @@
1
- import { cookies } from 'next/headers';
2
- import { getConfig } from '@korioinc/next-conf';
3
- import { deleteCookie, getCookie, setCookie } from 'cookies-next/server';
4
- /**
5
- * Reusable API request function
6
- * @param endpoint - API endpoint path (without base URL)
7
- * @param options - Request options
8
- * @returns Promise with the response data
9
- */
10
- export async function requestApi(endpoint, options = {}) {
11
- const { method = 'GET', headers = {}, body, params, cache, credentials, next } = options;
12
- // Get configuration
13
- const cfg = getConfig();
14
- const apiConfig = cfg.api;
15
- // Prepare URL
16
- const url = new URL(`${apiConfig.baseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`);
17
- if (params) {
18
- Object.entries(params).forEach(([key, value]) => {
19
- url.searchParams.append(key, value.toString());
20
- });
21
- }
22
- // Get access token from cookie
23
- const cookieCfg = cfg.cookie;
24
- const accessTokenName = cookieCfg.accessTokenName;
25
- const accessToken = await getCookie(accessTokenName, { cookies });
26
- // Prepare headers with defaults
27
- const requestHeaders = {
28
- Accept: 'application/json',
29
- ...headers,
30
- };
31
- // Add Authorization header if token exists
32
- if (accessToken) {
33
- requestHeaders['Authorization'] = `Bearer ${accessToken}`;
34
- }
35
- // Add Content-Type for requests with body
36
- if (body && !requestHeaders['Content-Type'] && !(body instanceof FormData)) {
37
- requestHeaders['Content-Type'] = 'application/json';
38
- }
39
- // Prepare request options
40
- const requestOptions = {
41
- method,
42
- headers: requestHeaders,
43
- credentials: credentials || 'same-origin',
44
- };
45
- // Add cache and revalidation options
46
- if (cache) {
47
- requestOptions.cache = cache;
48
- }
49
- if (next) {
50
- requestOptions.next = next;
51
- }
52
- // Add body for non-GET requests if provided
53
- if (method !== 'GET' && body) {
54
- requestOptions.body = body instanceof FormData ? body : JSON.stringify(body);
55
- }
56
- try {
57
- const response = await fetch(url.toString(), requestOptions);
58
- const refreshedToken = response.headers.get('x-refreshed-token');
59
- if (refreshedToken) {
60
- // Update the access token cookie
61
- await setCookie(accessTokenName, refreshedToken, {
62
- cookies,
63
- path: '/',
64
- domain: cookieCfg.domain,
65
- maxAge: cookieCfg.maxAge,
66
- sameSite: 'lax',
67
- });
68
- }
69
- // Handle non-OK responses
70
- if (!response.ok) {
71
- const errorData = await response.json().catch(() => ({
72
- message: `API error: ${response.status} ${response.statusText}`,
73
- }));
74
- // Delete cookie on 401 Unauthorized
75
- if (response.status === 401) {
76
- deleteCookie(accessTokenName, {
77
- cookies,
78
- path: '/',
79
- domain: cookieCfg.domain,
80
- });
81
- }
82
- throw new Error(errorData.message || `API error: ${response.status}`);
83
- }
84
- if (response.status === 204) {
85
- return undefined;
86
- }
87
- // Parse JSON response
88
- const jsonResponse = await response.json();
89
- return jsonResponse;
90
- }
91
- catch (error) {
92
- console.error(`Failed API request to ${endpoint}:`, error);
93
- throw error;
94
- }
95
- }
1
+ export { requestApi } from './server';
@@ -0,0 +1,32 @@
1
+ type RequestMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
2
+ type NextFetchOptions = {
3
+ revalidate?: number | false;
4
+ tags?: string[];
5
+ };
6
+ interface RequestOptions extends Omit<RequestInit, 'method' | 'headers' | 'body' | 'cache' | 'credentials'> {
7
+ method?: RequestMethod;
8
+ headers?: Record<string, string>;
9
+ body?: unknown;
10
+ params?: Record<string, string>;
11
+ cache?: RequestCache;
12
+ credentials?: RequestCredentials;
13
+ next?: NextFetchOptions;
14
+ }
15
+ /**
16
+ * Generic API response type
17
+ */
18
+ export interface ApiResponse<T> {
19
+ data: T;
20
+ success: boolean;
21
+ message?: string;
22
+ error?: unknown;
23
+ }
24
+ /**
25
+ * Reusable API request function (server-only)
26
+ * @param endpoint - API endpoint path (without base URL)
27
+ * @param options - Request options
28
+ * @returns Promise with the response data
29
+ */
30
+ export declare function requestApi<T = unknown>(endpoint: string, options?: RequestOptions): Promise<T>;
31
+ export {};
32
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/api-client/server.ts"],"names":[],"mappings":"AAMA,KAAK,aAAa,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEjE,KAAK,gBAAgB,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEzE,UAAU,cAAe,SAAQ,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,CAAC;IACzG,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC;IACR,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,CAAC,CAAC,CAsGxG"}
@@ -0,0 +1,95 @@
1
+ import { cookies } from 'next/headers';
2
+ import { getConfig } from '@korioinc/next-conf';
3
+ import { deleteCookie, getCookie, setCookie } from 'cookies-next/server';
4
+ /**
5
+ * Reusable API request function (server-only)
6
+ * @param endpoint - API endpoint path (without base URL)
7
+ * @param options - Request options
8
+ * @returns Promise with the response data
9
+ */
10
+ export async function requestApi(endpoint, options = {}) {
11
+ const { method = 'GET', headers = {}, body, params, cache, credentials, next } = options;
12
+ // Get configuration
13
+ const cfg = getConfig();
14
+ const apiConfig = cfg.api;
15
+ // Prepare URL
16
+ const url = new URL(`${apiConfig.baseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`);
17
+ if (params) {
18
+ Object.entries(params).forEach(([key, value]) => {
19
+ url.searchParams.append(key, value.toString());
20
+ });
21
+ }
22
+ // Get access token from cookie
23
+ const cookieCfg = cfg.cookie;
24
+ const accessTokenName = cookieCfg.accessTokenName;
25
+ const accessToken = await getCookie(accessTokenName, { cookies });
26
+ // Prepare headers with defaults
27
+ const requestHeaders = {
28
+ Accept: 'application/json',
29
+ ...headers,
30
+ };
31
+ // Add Authorization header if token exists
32
+ if (accessToken) {
33
+ requestHeaders['Authorization'] = `Bearer ${accessToken}`;
34
+ }
35
+ // Add Content-Type for requests with body
36
+ if (body && !requestHeaders['Content-Type'] && !(body instanceof FormData)) {
37
+ requestHeaders['Content-Type'] = 'application/json';
38
+ }
39
+ // Prepare request options
40
+ const requestOptions = {
41
+ method,
42
+ headers: requestHeaders,
43
+ credentials: credentials || 'same-origin',
44
+ };
45
+ // Add cache and revalidation options
46
+ if (cache) {
47
+ requestOptions.cache = cache;
48
+ }
49
+ if (next) {
50
+ requestOptions.next = next;
51
+ }
52
+ // Add body for non-GET requests if provided
53
+ if (method !== 'GET' && body) {
54
+ requestOptions.body = body instanceof FormData ? body : JSON.stringify(body);
55
+ }
56
+ try {
57
+ const response = await fetch(url.toString(), requestOptions);
58
+ const refreshedToken = response.headers.get('x-refreshed-token');
59
+ if (refreshedToken) {
60
+ // Update the access token cookie
61
+ await setCookie(accessTokenName, refreshedToken, {
62
+ cookies,
63
+ path: '/',
64
+ domain: cookieCfg.domain,
65
+ maxAge: cookieCfg.maxAge,
66
+ sameSite: 'lax',
67
+ });
68
+ }
69
+ // Handle non-OK responses
70
+ if (!response.ok) {
71
+ const errorData = await response.json().catch(() => ({
72
+ message: `API error: ${response.status} ${response.statusText}`,
73
+ }));
74
+ // Delete cookie on 401 Unauthorized
75
+ if (response.status === 401) {
76
+ deleteCookie(accessTokenName, {
77
+ cookies,
78
+ path: '/',
79
+ domain: cookieCfg.domain,
80
+ });
81
+ }
82
+ throw new Error(errorData.message || `API error: ${response.status}`);
83
+ }
84
+ if (response.status === 204) {
85
+ return undefined;
86
+ }
87
+ // Parse JSON response
88
+ const jsonResponse = await response.json();
89
+ return jsonResponse;
90
+ }
91
+ catch (error) {
92
+ console.error(`Failed API request to ${endpoint}:`, error);
93
+ throw error;
94
+ }
95
+ }
@@ -65,5 +65,5 @@ export default function LocaleSwitcher({ languages } = {}) {
65
65
  if (!currentLanguage) {
66
66
  return null;
67
67
  }
68
- return (_jsxs(Menu, { as: 'div', className: 'relative', children: [_jsx(MenuButton, { className: 'border-input bg-card hover:bg-accent hover:text-accent-foreground relative inline-flex h-9 w-9 items-center justify-center rounded-md border transition-colors', children: currentLanguage.flag }), _jsx(Transition, { as: Fragment, enter: 'transition ease-out duration-100', enterFrom: 'transform opacity-0 scale-95', enterTo: 'transform opacity-100 scale-100', leave: 'transition ease-in duration-75', leaveFrom: 'transform opacity-100 scale-100', leaveTo: 'transform opacity-0 scale-95', children: _jsx(MenuItems, { anchor: 'bottom end', className: 'bg-popover border-border z-50 w-36 rounded-md border shadow-lg ring-1 ring-black/5 [--anchor-gap:4px] focus:outline-none', children: _jsx("div", { className: 'py-1', children: availableLanguages.map((language) => (_jsx(MenuItem, { children: _jsxs("button", { onClick: () => changeLanguage(language.code), className: 'data-[focus]:bg-accent data-[focus]:text-accent-foreground text-foreground group flex w-full items-center gap-2 px-3 py-2 text-sm transition-colors', children: [language.flag, _jsx("span", { children: language.name }), currentLocale === language.code && (_jsx("svg", { className: 'ml-auto h-4 w-4', fill: 'none', stroke: 'currentColor', viewBox: '0 0 24 24', children: _jsx("path", { strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: 2, d: 'M5 13l4 4L19 7' }) }))] }) }, language.code))) }) }) })] }));
68
+ return (_jsxs(Menu, { as: 'div', className: 'relative', children: [_jsx(MenuButton, { className: 'border-glass bg-glass hover:bg-glass-backdrop relative inline-flex h-9 w-9 items-center justify-center rounded-md border transition-colors', children: currentLanguage.flag }), _jsx(Transition, { as: Fragment, enter: 'transition ease-out duration-100', enterFrom: 'transform opacity-0 scale-95', enterTo: 'transform opacity-100 scale-100', leave: 'transition ease-in duration-75', leaveFrom: 'transform opacity-100 scale-100', leaveTo: 'transform opacity-0 scale-95', children: _jsx(MenuItems, { anchor: 'bottom end', className: 'glass-backdrop border-glass z-50 w-36 rounded-md border ring-1 ring-black/5 [--anchor-gap:4px] focus:outline-none', children: _jsx("div", { className: 'py-1', children: availableLanguages.map((language) => (_jsx(MenuItem, { children: _jsxs("button", { onClick: () => changeLanguage(language.code), className: 'data-[focus]:bg-glass-backdrop text-foreground group flex w-full items-center gap-2 px-3 py-2 text-sm transition-colors', children: [language.flag, _jsx("span", { children: language.name }), currentLocale === language.code && (_jsx("svg", { className: 'ml-auto h-4 w-4', fill: 'none', stroke: 'currentColor', viewBox: '0 0 24 24', children: _jsx("path", { strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: 2, d: 'M5 13l4 4L19 7' }) }))] }) }, language.code))) }) }) })] }));
69
69
  }
@@ -15,6 +15,6 @@ const ThemeSwitcher = () => {
15
15
  if (!mounted) {
16
16
  return (_jsx("button", { className: 'border-input bg-card relative inline-flex h-9 w-9 items-center justify-center rounded-md border opacity-0', "aria-hidden": 'true', children: _jsx("div", { className: 'h-5 w-5' }) }));
17
17
  }
18
- return (_jsxs("button", { onClick: toggleTheme, className: 'border-input bg-card hover:bg-accent hover:text-accent-foreground relative inline-flex h-9 w-9 items-center justify-center rounded-md border transition-colors', "aria-label": `Switch theme (current: ${theme})`, title: `Theme: ${theme === 'light' ? 'Light' : 'Dark'} (click to change)`, children: [_jsxs("svg", { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: `absolute h-5 w-5 transition-all ${theme !== 'dark' ? 'scale-100 rotate-0 opacity-100' : 'scale-0 rotate-90 opacity-0'}`, children: [_jsx("circle", { cx: '12', cy: '12', r: '5' }), _jsx("line", { x1: '12', y1: '1', x2: '12', y2: '3' }), _jsx("line", { x1: '12', y1: '21', x2: '12', y2: '23' }), _jsx("line", { x1: '4.22', y1: '4.22', x2: '5.64', y2: '5.64' }), _jsx("line", { x1: '18.36', y1: '18.36', x2: '19.78', y2: '19.78' }), _jsx("line", { x1: '1', y1: '12', x2: '3', y2: '12' }), _jsx("line", { x1: '21', y1: '12', x2: '23', y2: '12' }), _jsx("line", { x1: '4.22', y1: '19.78', x2: '5.64', y2: '18.36' }), _jsx("line", { x1: '18.36', y1: '5.64', x2: '19.78', y2: '4.22' })] }), _jsx("svg", { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: `absolute h-5 w-5 transition-all ${theme === 'dark' ? 'scale-100 rotate-0 opacity-100' : 'scale-0 -rotate-90 opacity-0'}`, children: _jsx("path", { d: 'M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z' }) })] }));
18
+ return (_jsxs("button", { onClick: toggleTheme, className: 'border-glass bg-glass hover:bg-glass-backdrop relative inline-flex h-9 w-9 items-center justify-center rounded-md border transition-colors', "aria-label": `Switch theme (current: ${theme})`, title: `Theme: ${theme === 'light' ? 'Light' : 'Dark'} (click to change)`, children: [_jsxs("svg", { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: `absolute h-5 w-5 transition-all ${theme !== 'dark' ? 'scale-100 rotate-0 opacity-100' : 'scale-0 rotate-90 opacity-0'}`, children: [_jsx("circle", { cx: '12', cy: '12', r: '5' }), _jsx("line", { x1: '12', y1: '1', x2: '12', y2: '3' }), _jsx("line", { x1: '12', y1: '21', x2: '12', y2: '23' }), _jsx("line", { x1: '4.22', y1: '4.22', x2: '5.64', y2: '5.64' }), _jsx("line", { x1: '18.36', y1: '18.36', x2: '19.78', y2: '19.78' }), _jsx("line", { x1: '1', y1: '12', x2: '3', y2: '12' }), _jsx("line", { x1: '21', y1: '12', x2: '23', y2: '12' }), _jsx("line", { x1: '4.22', y1: '19.78', x2: '5.64', y2: '18.36' }), _jsx("line", { x1: '18.36', y1: '5.64', x2: '19.78', y2: '4.22' })] }), _jsx("svg", { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: `absolute h-5 w-5 transition-all ${theme === 'dark' ? 'scale-100 rotate-0 opacity-100' : 'scale-0 -rotate-90 opacity-0'}`, children: _jsx("path", { d: 'M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z' }) })] }));
19
19
  };
20
20
  export default ThemeSwitcher;
@@ -71,10 +71,11 @@
71
71
  --color-code-number: var(--code-number);
72
72
  --color-selection: var(--selection);
73
73
  --color-selection-foreground: var(--selection-foreground);
74
+ --color-glass: var(--glass);
75
+ --color-glass-backdrop: var(--glass-backdrop);
74
76
  }
75
77
 
76
78
  :root {
77
- --radius: 0.625rem;
78
79
  --background: oklch(1 0 0);
79
80
  --foreground: oklch(0.145 0 0);
80
81
  --card: oklch(1 0 0);
@@ -114,6 +115,35 @@
114
115
  --code-number: oklch(0.56 0 0);
115
116
  --selection: oklch(0.145 0 0);
116
117
  --selection-foreground: oklch(1 0 0);
118
+ --radius: 0.625rem;
119
+
120
+ /************************************************************/
121
+ /* liquid glass (light) */
122
+ /************************************************************/
123
+ --glass: oklch(0.8985 0.0271 250 / 0.22);
124
+ --glass-backdrop: oklch(0.8764 0.0271 255 / 0.32);
125
+ --glass-surface: oklch(0.962 0.014 250 / 0.42);
126
+ --glass-surface-backdrop: oklch(0.975 0.018 255 / 0.52);
127
+ --glass-border: oklch(0.92 0.02 250 / 0.78);
128
+ --glass-border-subtle: oklch(0.88 0.015 250 / 0.5);
129
+ --glass-shine: oklch(1 0 0 / 1);
130
+ --glass-shine-subtle: oklch(1 0 0 / 0.88);
131
+ --glass-shadow-color: oklch(0.25 0.02 250 / 0.08);
132
+ --glass-shadow-ambient: oklch(0.35 0.015 250 / 0.055);
133
+ --glass-glow: oklch(0.65 0.18 250 / 0.32);
134
+ --glass-blur: 14px;
135
+ --glass-blur-backdrop: 8px;
136
+
137
+ --mesh-1: oklch(0.6008 0.1493 249.6 / 0.251);
138
+ --mesh-2: oklch(0.6498 0.1201 300.4 / 0.2);
139
+ --mesh-3: oklch(0.7 0.1201 220.3 / 0.18);
140
+ --mesh-4: oklch(0.5994 0.1998 320.1 / 0.302);
141
+
142
+ --aurora-1: oklch(0.6496 0.1802 250.1 / 0.451);
143
+ --aurora-2: oklch(0.7006 0.1494 279.7 / 0.4);
144
+ --aurora-3: oklch(0.7492 0.1199 200.4 / 0.349);
145
+
146
+ --noise-opacity: 0.025;
117
147
  }
118
148
 
119
149
  .dark {
@@ -156,6 +186,34 @@
156
186
  --code-number: oklch(0.72 0 0);
157
187
  --selection: oklch(0.922 0 0);
158
188
  --selection-foreground: oklch(0.205 0 0);
189
+
190
+ /************************************************************/
191
+ /* liquid glass (dark) */
192
+ /************************************************************/
193
+ --glass: oklch(0.32 0.0198 252.2 / 0.52);
194
+ --glass-backdrop: oklch(0.36 0.0206 254.9 / 0.62);
195
+ --glass-surface: oklch(0.1792 0.0198 252.2 / 0.42);
196
+ --glass-surface-backdrop: oklch(0.2195 0.0206 254.9 / 0.52);
197
+ --glass-border: oklch(1 0 0 / 0.122);
198
+ --glass-border-subtle: oklch(1 0 0 / 0.078);
199
+ --glass-shine: oklch(1 0 0 / 0.149);
200
+ --glass-shine-subtle: oklch(1 0 0 / 0.078);
201
+ --glass-shadow-color: oklch(0 0 0 / 0.21);
202
+ --glass-shadow-ambient: oklch(0 0 0 / 0.11);
203
+ --glass-glow: oklch(0.6991 0.1648 249.1 / 0.302);
204
+ --glass-blur: 12px;
205
+ --glass-blur-backdrop: 8px;
206
+
207
+ --mesh-1: oklch(0.4035 0.121 252.1 / 0.349);
208
+ --mesh-2: oklch(0.4504 0.1802 299.9 / 0.302);
209
+ --mesh-3: oklch(0.5014 0.0917 220.6 / 0.251);
210
+ --mesh-4: oklch(0.5016 0.2405 320.2 / 0.349);
211
+
212
+ --aurora-1: oklch(0.5057 0.1589 253.6 / 0.502);
213
+ --aurora-2: oklch(0.4499 0.2002 280 / 0.451);
214
+ --aurora-3: oklch(0.5581 0.0949 201.4 / 0.4);
215
+
216
+ --noise-opacity: 0.035;
159
217
  }
160
218
 
161
219
  @layer base {
@@ -218,6 +276,54 @@
218
276
  @apply after:border-border relative after:absolute after:inset-0 after:border after:mix-blend-darken dark:after:mix-blend-lighten;
219
277
  }
220
278
 
279
+ @utility glass {
280
+ background:
281
+ linear-gradient(
282
+ 135deg,
283
+ color-mix(in oklab, var(--glass-shine) 12%, transparent) 0%,
284
+ color-mix(in oklab, var(--glass-shine) 8%, transparent) 30%,
285
+ color-mix(in oklab, var(--glass-shine) 4%, transparent) 70%,
286
+ color-mix(in oklab, var(--glass-shine) 6%, transparent) 100%
287
+ ),
288
+ var(--glass-surface);
289
+ /*backdrop-filter: blur(var(--glass-blur)) saturate(1.2);*/
290
+ box-shadow:
291
+ 0 1px 2px var(--glass-shadow-ambient),
292
+ 0 5px 10px var(--glass-shadow-color),
293
+ inset 0 1px 0 var(--glass-shine-subtle);
294
+ }
295
+
296
+ @utility glass-backdrop {
297
+ background:
298
+ linear-gradient(
299
+ 135deg,
300
+ color-mix(in oklab, var(--glass-shine) 12%, transparent) 0%,
301
+ color-mix(in oklab, var(--glass-shine) 8%, transparent) 30%,
302
+ color-mix(in oklab, var(--glass-shine) 4%, transparent) 70%,
303
+ color-mix(in oklab, var(--glass-shine) 6%, transparent) 100%
304
+ ),
305
+ var(--glass-surface-backdrop);
306
+ backdrop-filter: blur(var(--glass-blur-backdrop)) saturate(1.2);
307
+ box-shadow:
308
+ 0 1px 2px var(--glass-shadow-ambient),
309
+ 0 5px 10px var(--glass-shadow-color),
310
+ inset 0 1px 0 var(--glass-shine-subtle);
311
+ }
312
+
313
+ @utility border-glass {
314
+ border-color: var(--glass-border);
315
+ position: relative;
316
+
317
+ &::after {
318
+ content: '';
319
+ position: absolute;
320
+ inset: 0;
321
+ border-radius: inherit;
322
+ pointer-events: none;
323
+ box-shadow: inset 0 1px 0 var(--glass-shine-subtle);
324
+ }
325
+ }
326
+
221
327
  @utility step {
222
328
  counter-increment: step;
223
329
  @apply relative;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@korioinc/next-core",
3
- "version": "2.0.3",
3
+ "version": "2.0.6",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./ads": {
@@ -79,7 +79,7 @@
79
79
  "tsc-alias": "^1.8.16",
80
80
  "tw-animate-css": "^1.4.0",
81
81
  "typescript": "^5.9.3",
82
- "@korioinc/next-configs": "2.0.3"
82
+ "@korioinc/next-configs": "2.0.6"
83
83
  },
84
84
  "dependencies": {
85
85
  "@floating-ui/react": "^0.27.16",
@@ -94,7 +94,7 @@
94
94
  "schema-dts": "^1.1.5",
95
95
  "tailwind-merge": "^3.4.0",
96
96
  "valtio": "^2.2.0",
97
- "@korioinc/next-conf": "2.0.3"
97
+ "@korioinc/next-conf": "2.0.6"
98
98
  },
99
99
  "publishConfig": {
100
100
  "access": "public",