@rozenite/storage-plugin 1.13.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/README.md +6 -1
- package/dist/devtools/assets/panel-BlDRXgVW.js +32 -0
- package/dist/devtools/assets/panel-DBweZnW5.css +1 -0
- package/dist/devtools/panel.html +2 -2
- package/dist/react-native/chunks/async-storage.require.cjs +1 -1
- package/dist/react-native/chunks/async-storage.require.js +8 -7
- package/dist/react-native/chunks/index.require.cjs +1 -1
- package/dist/react-native/chunks/index.require.js +70 -66
- package/dist/react-native/chunks/secure-storage.require.cjs +1 -1
- package/dist/react-native/chunks/secure-storage.require.js +17 -13
- package/dist/react-native/chunks/useRozeniteStoragePlugin.require.cjs +1 -1
- package/dist/react-native/chunks/useRozeniteStoragePlugin.require.js +863 -344
- package/dist/react-native/index.d.ts +166 -18
- package/dist/rozenite.json +1 -1
- package/dist/sdk/index.cjs +1 -1
- package/dist/sdk/index.d.ts +13 -5
- package/dist/sdk/index.js +21 -12
- package/package.json +35 -37
- package/react-native.ts +12 -22
- package/rozenite.config.ts +74 -0
- package/sdk.ts +1 -5
- package/src/react-native/__tests__/entry-preview-pagination.test.ts +234 -0
- package/src/react-native/__tests__/export-snapshot.test.ts +138 -0
- package/src/react-native/__tests__/full-entry-request.test.ts +143 -0
- package/src/react-native/__tests__/import.test.ts +174 -11
- package/src/react-native/__tests__/storage-discovery.test.ts +144 -0
- package/src/react-native/__tests__/storage-view.test.ts +172 -0
- package/src/react-native/__tests__/stress-verification.test.ts +140 -0
- package/src/react-native/__tests__/use-storage-agent-tools.test.ts +221 -0
- package/src/react-native/adapters/__tests__/mmkv.test.ts +20 -30
- package/src/react-native/adapters/async-storage.ts +8 -9
- package/src/react-native/adapters/index.ts +2 -8
- package/src/react-native/adapters/mmkv.ts +12 -24
- package/src/react-native/adapters/secure-storage.ts +4 -0
- package/src/react-native/entry-preview-pagination.ts +261 -0
- package/src/react-native/export-snapshot.ts +88 -0
- package/src/react-native/full-entry-request.ts +91 -0
- package/src/react-native/import.ts +179 -16
- package/src/react-native/storage-discovery.ts +92 -0
- package/src/react-native/storage-view.ts +47 -109
- package/src/react-native/useRozeniteStoragePlugin.ts +153 -129
- package/src/react-native/useStorageAgentTools.ts +196 -91
- package/src/shared/__tests__/entry-preview.test.ts +99 -0
- package/src/shared/__tests__/snapshot.test.ts +31 -32
- package/src/shared/agent-tools.ts +33 -38
- package/src/shared/entry-preview.ts +54 -0
- package/src/shared/messaging.ts +140 -21
- package/src/shared/snapshot.ts +12 -18
- package/src/shared/types.ts +21 -4
- package/src/ui/__tests__/binary-value-editor-state.test.ts +16 -13
- package/src/ui/__tests__/binary.test.ts +31 -33
- package/src/ui/__tests__/large-value-viewer-state.test.ts +21 -0
- package/src/ui/__tests__/large-value-viewer.test.tsx +54 -0
- package/src/ui/__tests__/panel.test.tsx +382 -0
- package/src/ui/__tests__/storage-groups.test.ts +88 -0
- package/src/ui/__tests__/type-conversion.test.ts +8 -24
- package/src/ui/__tests__/use-storage-entries.test.tsx +337 -0
- package/src/ui/add-entry-dialog.tsx +66 -117
- package/src/ui/binary-value-editor-state.ts +16 -25
- package/src/ui/binary-value-editor.tsx +59 -47
- package/src/ui/binary.ts +54 -15
- package/src/ui/edit-entry-dialog.tsx +68 -104
- package/src/ui/editor-switcher.tsx +9 -16
- package/src/ui/entry-detail-dialog.tsx +62 -181
- package/src/ui/format-value.tsx +25 -0
- package/src/ui/globals.css +1 -123
- package/src/ui/import-dialog.tsx +72 -109
- package/src/ui/large-value-viewer-state.ts +25 -0
- package/src/ui/large-value-viewer.tsx +65 -0
- package/src/ui/panel.tsx +649 -509
- package/src/ui/query-client.tsx +23 -0
- package/src/ui/storage-groups.ts +66 -0
- package/src/ui/type-conversion.ts +2 -5
- package/src/ui/typed-value-editor.tsx +15 -20
- package/src/ui/use-storage-entries.ts +192 -0
- package/src/ui/utils.ts +1 -4
- package/tsconfig.json +5 -1
- package/dist/devtools/assets/panel-Bm-SWF7d.js +0 -33
- package/dist/devtools/assets/panel-DIqI4WSp.css +0 -1
- package/postcss.config.js +0 -6
- package/src/ui/confirm-dialog.tsx +0 -100
- package/src/ui/editable-table.tsx +0 -300
- package/tailwind.config.ts +0 -94
|
@@ -1,38 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { JSONTree } from 'react-json-tree';
|
|
3
|
-
import { StorageEntry } from '../shared/types';
|
|
1
|
+
import { Badge, Button, Dialog, JsonInspector } from '@rozenite/ui';
|
|
4
2
|
import { useMemo } from 'react';
|
|
5
|
-
import {
|
|
3
|
+
import { Edit3, Info } from 'lucide-react';
|
|
4
|
+
import type { StorageEntry } from '../shared/types';
|
|
5
|
+
import { formatValue } from './format-value';
|
|
6
|
+
import { HexdumpValueViewer, TextValueViewer } from './large-value-viewer';
|
|
6
7
|
|
|
7
8
|
export type EntryDetailDialogProps = {
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
open: boolean;
|
|
10
|
+
onOpenChange: (open: boolean) => void;
|
|
10
11
|
onEdit?: (entry: StorageEntry) => void;
|
|
11
12
|
entry: StorageEntry | null;
|
|
12
13
|
};
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
-
base00: 'transparent',
|
|
16
|
-
base01: '#374151', // bg-gray-700
|
|
17
|
-
base02: '#4b5563', // bg-gray-600
|
|
18
|
-
base03: '#6b7280', // text-gray-500
|
|
19
|
-
base04: '#9ca3af', // text-gray-400
|
|
20
|
-
base05: '#d1d5db', // text-gray-300
|
|
21
|
-
base06: '#e5e7eb', // text-gray-200
|
|
22
|
-
base07: '#f9fafb', // text-gray-100
|
|
23
|
-
base08: '#ef4444', // text-red-500
|
|
24
|
-
base09: '#f59e0b', // text-yellow-500
|
|
25
|
-
base0A: '#10b981', // text-green-500
|
|
26
|
-
base0B: '#3b82f6', // text-blue-500
|
|
27
|
-
base0C: '#06b6d4', // text-cyan-500
|
|
28
|
-
base0D: '#8b5cf6', // text-purple-500
|
|
29
|
-
base0E: '#ec4899', // text-pink-500
|
|
30
|
-
base0F: '#f97316', // text-orange-500
|
|
31
|
-
};
|
|
15
|
+
const MAX_AUTO_JSON_INSPECTION_LENGTH = 50_000;
|
|
32
16
|
|
|
33
|
-
const jsonSafeParse = (
|
|
34
|
-
value: string,
|
|
35
|
-
): Record<string, unknown> | unknown[] | null => {
|
|
17
|
+
export const jsonSafeParse = (value: string): Record<string, unknown> | unknown[] | null => {
|
|
36
18
|
try {
|
|
37
19
|
const parsed = JSON.parse(value) as unknown;
|
|
38
20
|
|
|
@@ -50,179 +32,78 @@ const jsonSafeParse = (
|
|
|
50
32
|
}
|
|
51
33
|
};
|
|
52
34
|
|
|
53
|
-
const getTypeColorClass = (type: string) => {
|
|
54
|
-
switch (type) {
|
|
55
|
-
case 'string':
|
|
56
|
-
return 'bg-green-600';
|
|
57
|
-
case 'number':
|
|
58
|
-
return 'bg-blue-600';
|
|
59
|
-
case 'boolean':
|
|
60
|
-
return 'bg-yellow-600';
|
|
61
|
-
case 'buffer':
|
|
62
|
-
return 'bg-purple-600';
|
|
63
|
-
default:
|
|
64
|
-
return 'bg-gray-600';
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const formatValue = (entry: StorageEntry) => {
|
|
69
|
-
switch (entry.type) {
|
|
70
|
-
case 'string':
|
|
71
|
-
return (
|
|
72
|
-
<span className="text-green-300 font-mono break-all">
|
|
73
|
-
"{entry.value as string}"
|
|
74
|
-
</span>
|
|
75
|
-
);
|
|
76
|
-
case 'number':
|
|
77
|
-
return (
|
|
78
|
-
<span className="text-blue-300 font-mono">{entry.value as number}</span>
|
|
79
|
-
);
|
|
80
|
-
case 'boolean':
|
|
81
|
-
return (
|
|
82
|
-
<span
|
|
83
|
-
className={`font-mono ${
|
|
84
|
-
entry.value ? 'text-green-400' : 'text-red-400'
|
|
85
|
-
}`}
|
|
86
|
-
>
|
|
87
|
-
{entry.value ? 'true' : 'false'}
|
|
88
|
-
</span>
|
|
89
|
-
);
|
|
90
|
-
case 'buffer': {
|
|
91
|
-
const bufferArray = entry.value as number[];
|
|
92
|
-
return (
|
|
93
|
-
<div className="space-y-2">
|
|
94
|
-
<div className="text-xs text-gray-400">
|
|
95
|
-
{bufferArray.length} {bufferArray.length === 1 ? 'byte' : 'bytes'}
|
|
96
|
-
</div>
|
|
97
|
-
<pre className="text-purple-200 font-mono text-xs whitespace-pre overflow-auto leading-snug">
|
|
98
|
-
{bytesToHexdump(bufferArray)}
|
|
99
|
-
</pre>
|
|
100
|
-
</div>
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
default:
|
|
104
|
-
return <span className="text-gray-400">Unknown</span>;
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
|
|
108
35
|
export const EntryDetailDialog = ({
|
|
109
|
-
|
|
110
|
-
|
|
36
|
+
open,
|
|
37
|
+
onOpenChange,
|
|
111
38
|
onEdit,
|
|
112
39
|
entry,
|
|
113
40
|
}: EntryDetailDialogProps) => {
|
|
114
41
|
const isStringValue = entry?.type === 'string';
|
|
115
|
-
const stringValue = isStringValue ?
|
|
116
|
-
const jsonValue = useMemo(
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
122
|
-
if (e.key === 'Escape') {
|
|
123
|
-
onClose();
|
|
42
|
+
const stringValue = isStringValue ? entry.value : '';
|
|
43
|
+
const jsonValue = useMemo(() => {
|
|
44
|
+
if (!isStringValue || stringValue.length > MAX_AUTO_JSON_INSPECTION_LENGTH) {
|
|
45
|
+
return null;
|
|
124
46
|
}
|
|
125
|
-
};
|
|
126
47
|
|
|
127
|
-
|
|
48
|
+
return jsonSafeParse(stringValue);
|
|
49
|
+
}, [isStringValue, stringValue]);
|
|
128
50
|
|
|
129
51
|
return (
|
|
130
|
-
<
|
|
131
|
-
className="
|
|
132
|
-
|
|
133
|
-
>
|
|
134
|
-
<div
|
|
135
|
-
className="bg-gray-800 rounded-lg p-6 w-[90vw] max-w-2xl max-h-[90vh] flex flex-col"
|
|
136
|
-
onClick={(e) => e.stopPropagation()}
|
|
137
|
-
onKeyDown={handleKeyDown}
|
|
138
|
-
>
|
|
139
|
-
<div className="flex items-center justify-between mb-4">
|
|
52
|
+
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
53
|
+
<Dialog.Content className="max-w-2xl">
|
|
54
|
+
<Dialog.Header>
|
|
140
55
|
<div className="flex items-center gap-2">
|
|
141
|
-
<Info className="h-
|
|
142
|
-
<
|
|
143
|
-
Entry Details
|
|
144
|
-
</h2>
|
|
56
|
+
<Info className="h-4 w-4 text-muted-foreground" />
|
|
57
|
+
<Dialog.Title>Entry Details</Dialog.Title>
|
|
145
58
|
</div>
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
<div className="space-y-4 flex-1 overflow-auto">
|
|
156
|
-
{/* Key Display */}
|
|
157
|
-
<div>
|
|
158
|
-
<label className="block text-sm font-medium text-gray-200 mb-1">
|
|
159
|
-
Key
|
|
160
|
-
</label>
|
|
161
|
-
<div className="w-full px-3 py-2 text-sm bg-gray-700 border border-gray-600 rounded text-gray-100 font-mono break-all">
|
|
162
|
-
{entry.key}
|
|
59
|
+
</Dialog.Header>
|
|
60
|
+
|
|
61
|
+
{entry && (
|
|
62
|
+
<div className="flex max-h-[70vh] flex-col gap-4 overflow-auto">
|
|
63
|
+
<div>
|
|
64
|
+
<div className="mb-1 text-sm font-medium text-foreground">Key</div>
|
|
65
|
+
<div className="w-full break-all rounded-md border border-input bg-muted px-3 py-2 font-mono text-sm text-foreground">
|
|
66
|
+
{entry.key}
|
|
67
|
+
</div>
|
|
163
68
|
</div>
|
|
164
|
-
</div>
|
|
165
69
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
Type
|
|
170
|
-
</label>
|
|
171
|
-
<div className="flex items-center">
|
|
172
|
-
<span
|
|
173
|
-
className={`px-2 py-1 text-xs font-medium rounded text-white ${getTypeColorClass(
|
|
174
|
-
entry.type,
|
|
175
|
-
)}`}
|
|
176
|
-
>
|
|
177
|
-
{entry.type}
|
|
178
|
-
</span>
|
|
70
|
+
<div>
|
|
71
|
+
<div className="mb-1 text-sm font-medium text-foreground">Type</div>
|
|
72
|
+
<Badge variant="outline">{entry.type}</Badge>
|
|
179
73
|
</div>
|
|
180
|
-
</div>
|
|
181
74
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
75
|
+
<div className="flex min-h-0 flex-1 flex-col">
|
|
76
|
+
<div className="mb-1 text-sm font-medium text-foreground">Value</div>
|
|
77
|
+
<div className="max-h-96 overflow-auto rounded-md border border-input bg-muted p-3">
|
|
78
|
+
{jsonValue ? (
|
|
79
|
+
<JsonInspector data={jsonValue} />
|
|
80
|
+
) : entry.type === 'buffer' ? (
|
|
81
|
+
<div className="flex flex-col gap-2">
|
|
82
|
+
<div className="text-xs text-muted-foreground">
|
|
83
|
+
{entry.value.length} {entry.value.length === 1 ? 'byte' : 'bytes'}
|
|
84
|
+
</div>
|
|
85
|
+
<HexdumpValueViewer bytes={entry.value} />
|
|
86
|
+
</div>
|
|
87
|
+
) : entry.type === 'string' ? (
|
|
88
|
+
<TextValueViewer value={entry.value} />
|
|
89
|
+
) : (
|
|
90
|
+
<div className="text-sm">{formatValue(entry)}</div>
|
|
91
|
+
)}
|
|
92
|
+
</div>
|
|
198
93
|
</div>
|
|
199
94
|
</div>
|
|
200
|
-
|
|
95
|
+
)}
|
|
201
96
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
onClick={() => {
|
|
207
|
-
if (entry && onEdit) {
|
|
208
|
-
onEdit(entry);
|
|
209
|
-
}
|
|
210
|
-
}}
|
|
211
|
-
className="flex items-center gap-2 px-4 py-2 text-sm bg-gray-700 hover:bg-gray-600 text-white rounded transition-colors"
|
|
212
|
-
>
|
|
213
|
-
<Edit3 className="h-4 w-4" />
|
|
97
|
+
<Dialog.Footer>
|
|
98
|
+
{entry && onEdit && (
|
|
99
|
+
<Button variant="outline" onClick={() => onEdit(entry)}>
|
|
100
|
+
<Edit3 className="h-3.5 w-3.5" />
|
|
214
101
|
Edit
|
|
215
|
-
</
|
|
102
|
+
</Button>
|
|
216
103
|
)}
|
|
217
|
-
<
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
>
|
|
222
|
-
Close
|
|
223
|
-
</button>
|
|
224
|
-
</div>
|
|
225
|
-
</div>
|
|
226
|
-
</div>
|
|
104
|
+
<Dialog.Close render={<Button />}>Close</Dialog.Close>
|
|
105
|
+
</Dialog.Footer>
|
|
106
|
+
</Dialog.Content>
|
|
107
|
+
</Dialog>
|
|
227
108
|
);
|
|
228
109
|
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { cn } from '@rozenite/ui';
|
|
2
|
+
import type { StorageEntry } from '../shared/types';
|
|
3
|
+
import { compactBufferPreview } from './binary';
|
|
4
|
+
|
|
5
|
+
export const formatValue = (entry: StorageEntry) => {
|
|
6
|
+
if (entry.type === 'string') {
|
|
7
|
+
return <span className="font-mono text-foreground">"{entry.value}"</span>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (entry.type === 'number') {
|
|
11
|
+
return <span className="font-mono text-foreground">{entry.value}</span>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (entry.type === 'boolean') {
|
|
15
|
+
return (
|
|
16
|
+
<span className={cn('font-mono', entry.value ? 'text-primary' : 'text-destructive')}>
|
|
17
|
+
{entry.value ? 'true' : 'false'}
|
|
18
|
+
</span>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<span className="font-mono text-muted-foreground">{compactBufferPreview(entry.value)}</span>
|
|
24
|
+
);
|
|
25
|
+
};
|
package/src/ui/globals.css
CHANGED
|
@@ -1,123 +1 @@
|
|
|
1
|
-
@
|
|
2
|
-
@tailwind components;
|
|
3
|
-
@tailwind utilities;
|
|
4
|
-
|
|
5
|
-
@layer utilities {
|
|
6
|
-
.text-balance {
|
|
7
|
-
text-wrap: balance;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
.wrap-anywhere {
|
|
11
|
-
overflow-wrap: anywhere;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
@layer base {
|
|
16
|
-
:root {
|
|
17
|
-
--background: 0 0% 100%;
|
|
18
|
-
--foreground: 0 0% 3.9%;
|
|
19
|
-
--card: 0 0% 100%;
|
|
20
|
-
--card-foreground: 0 0% 3.9%;
|
|
21
|
-
--popover: 0 0% 100%;
|
|
22
|
-
--popover-foreground: 0 0% 3.9%;
|
|
23
|
-
--primary: 0 0% 9%;
|
|
24
|
-
--primary-foreground: 0 0% 98%;
|
|
25
|
-
--secondary: 0 0% 96.1%;
|
|
26
|
-
--secondary-foreground: 0 0% 9%;
|
|
27
|
-
--muted: 0 0% 96.1%;
|
|
28
|
-
--muted-foreground: 0 0% 45.1%;
|
|
29
|
-
--accent: 0 0% 96.1%;
|
|
30
|
-
--accent-foreground: 0 0% 9%;
|
|
31
|
-
--destructive: 0 84.2% 60.2%;
|
|
32
|
-
--destructive-foreground: 0 0% 98%;
|
|
33
|
-
--border: 0 0% 89.8%;
|
|
34
|
-
--input: 0 0% 89.8%;
|
|
35
|
-
--ring: 0 0% 3.9%;
|
|
36
|
-
--chart-1: 12 76% 61%;
|
|
37
|
-
--chart-2: 173 58% 39%;
|
|
38
|
-
--chart-3: 197 37% 24%;
|
|
39
|
-
--chart-4: 43 74% 66%;
|
|
40
|
-
--chart-5: 27 87% 67%;
|
|
41
|
-
--radius: 0.5rem;
|
|
42
|
-
--sidebar-background: 0 0% 98%;
|
|
43
|
-
--sidebar-foreground: 240 5.3% 26.1%;
|
|
44
|
-
--sidebar-primary: 240 5.9% 10%;
|
|
45
|
-
--sidebar-primary-foreground: 0 0% 98%;
|
|
46
|
-
--sidebar-accent: 240 4.8% 95.9%;
|
|
47
|
-
--sidebar-accent-foreground: 240 5.9% 10%;
|
|
48
|
-
--sidebar-border: 220 13% 91%;
|
|
49
|
-
--sidebar-ring: 217.2 91.2% 59.8%;
|
|
50
|
-
}
|
|
51
|
-
.dark {
|
|
52
|
-
--background: 0 0% 3.9%;
|
|
53
|
-
--foreground: 0 0% 98%;
|
|
54
|
-
--card: 0 0% 3.9%;
|
|
55
|
-
--card-foreground: 0 0% 98%;
|
|
56
|
-
--popover: 0 0% 3.9%;
|
|
57
|
-
--popover-foreground: 0 0% 98%;
|
|
58
|
-
--primary: 0 0% 98%;
|
|
59
|
-
--primary-foreground: 0 0% 9%;
|
|
60
|
-
--secondary: 0 0% 14.9%;
|
|
61
|
-
--secondary-foreground: 0 0% 98%;
|
|
62
|
-
--muted: 0 0% 14.9%;
|
|
63
|
-
--muted-foreground: 0 0% 63.9%;
|
|
64
|
-
--accent: 0 0% 14.9%;
|
|
65
|
-
--accent-foreground: 0 0% 98%;
|
|
66
|
-
--destructive: 0 62.8% 30.6%;
|
|
67
|
-
--destructive-foreground: 0 0% 98%;
|
|
68
|
-
--border: 0 0% 14.9%;
|
|
69
|
-
--input: 0 0% 14.9%;
|
|
70
|
-
--ring: 0 0% 83.1%;
|
|
71
|
-
--chart-1: 220 70% 50%;
|
|
72
|
-
--chart-2: 160 60% 45%;
|
|
73
|
-
--chart-3: 30 80% 55%;
|
|
74
|
-
--chart-4: 280 65% 60%;
|
|
75
|
-
--chart-5: 340 75% 55%;
|
|
76
|
-
--sidebar-background: 240 5.9% 10%;
|
|
77
|
-
--sidebar-foreground: 240 4.8% 95.9%;
|
|
78
|
-
--sidebar-primary: 224.3 76.3% 48%;
|
|
79
|
-
--sidebar-primary-foreground: 0 0% 100%;
|
|
80
|
-
--sidebar-accent: 240 3.7% 15.9%;
|
|
81
|
-
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
|
82
|
-
--sidebar-border: 240 3.7% 15.9%;
|
|
83
|
-
--sidebar-ring: 217.2 91.2% 59.8%;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
@layer base {
|
|
88
|
-
* {
|
|
89
|
-
@apply border-border;
|
|
90
|
-
}
|
|
91
|
-
body {
|
|
92
|
-
@apply bg-background text-foreground;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/* Custom scrollbar styles to match plugin theme */
|
|
97
|
-
::-webkit-scrollbar {
|
|
98
|
-
width: 8px;
|
|
99
|
-
height: 8px;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
::-webkit-scrollbar-track {
|
|
103
|
-
background: #1f2937; /* gray-800 */
|
|
104
|
-
border-radius: 4px;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
::-webkit-scrollbar-thumb {
|
|
108
|
-
background: #374151; /* gray-700 */
|
|
109
|
-
border-radius: 4px;
|
|
110
|
-
border: 1px solid #1f2937; /* gray-800 */
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
::-webkit-scrollbar-thumb:hover {
|
|
114
|
-
background: #4b5563; /* gray-600 */
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
::-webkit-scrollbar-thumb:active {
|
|
118
|
-
background: #6b7280; /* gray-500 */
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
::-webkit-scrollbar-corner {
|
|
122
|
-
background: #1f2937; /* gray-800 */
|
|
123
|
-
}
|
|
1
|
+
@import '@rozenite/ui/styles.css';
|