jamdesk 1.1.174 → 1.1.175
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jamdesk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.175",
|
|
4
4
|
"description": "CLI for Jamdesk — build, preview, and deploy documentation sites from MDX. Dev server with hot reload, 50+ components, OpenAPI support, AI search, and Mintlify migration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jamdesk",
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
type ReactNode,
|
|
13
13
|
} from 'react';
|
|
14
14
|
|
|
15
|
+
import { useBodyScrollLock } from '@/hooks/useBodyScrollLock';
|
|
15
16
|
import { useOnClickOutside } from '@/hooks/useOnClickOutside';
|
|
16
17
|
import { renderInlineMarkdown } from '@/lib/inline-markdown';
|
|
17
18
|
import { decodePromptSource } from '@/lib/prompt-source-codec';
|
|
@@ -70,6 +71,188 @@ function ActionIcon({ action }: { action: ResolvedPromptAction['action'] }): Rea
|
|
|
70
71
|
return null;
|
|
71
72
|
}
|
|
72
73
|
|
|
74
|
+
interface PromptCopyButtonProps {
|
|
75
|
+
copyState: CopyState;
|
|
76
|
+
className: string;
|
|
77
|
+
onCopy: () => void;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function PromptCopyButton({
|
|
81
|
+
copyState,
|
|
82
|
+
className,
|
|
83
|
+
onCopy,
|
|
84
|
+
}: PromptCopyButtonProps): ReactElement {
|
|
85
|
+
const label = copyState === 'copied'
|
|
86
|
+
? 'Copied'
|
|
87
|
+
: copyState === 'error'
|
|
88
|
+
? 'Copy failed'
|
|
89
|
+
: 'Copy prompt';
|
|
90
|
+
return (
|
|
91
|
+
<button
|
|
92
|
+
type="button"
|
|
93
|
+
aria-label="Copy prompt"
|
|
94
|
+
title={label}
|
|
95
|
+
className={className}
|
|
96
|
+
data-copy-state={copyState}
|
|
97
|
+
onClick={onCopy}
|
|
98
|
+
>
|
|
99
|
+
<i
|
|
100
|
+
className={copyState === 'copied'
|
|
101
|
+
? 'fa-solid fa-check text-[var(--color-success-text)]'
|
|
102
|
+
: copyState === 'error'
|
|
103
|
+
? 'fa-solid fa-triangle-exclamation text-[var(--color-error-text)]'
|
|
104
|
+
: 'fa-regular fa-copy'}
|
|
105
|
+
aria-hidden="true"
|
|
106
|
+
/>
|
|
107
|
+
</button>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
interface PromptDialogProps {
|
|
112
|
+
isOpen: boolean;
|
|
113
|
+
prompt: string;
|
|
114
|
+
title?: string;
|
|
115
|
+
copyState: CopyState;
|
|
116
|
+
onCopy: () => void;
|
|
117
|
+
onClose: () => void;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const contrastSafeFocusClassName = [
|
|
121
|
+
'focus-visible:outline-none focus-visible:ring-2',
|
|
122
|
+
'focus-visible:ring-[var(--color-text-primary)] focus-visible:ring-offset-2',
|
|
123
|
+
'focus-visible:ring-offset-[var(--color-bg-primary)]',
|
|
124
|
+
].join(' ');
|
|
125
|
+
|
|
126
|
+
const promptUtilityClassName = [
|
|
127
|
+
'inline-flex size-10 shrink-0 cursor-pointer items-center justify-center rounded-[var(--radius-lg)]',
|
|
128
|
+
'text-[var(--color-text-tertiary)] transition-colors',
|
|
129
|
+
'hover:bg-[var(--color-bg-hover)]',
|
|
130
|
+
'hover:text-[var(--color-primary)]',
|
|
131
|
+
contrastSafeFocusClassName,
|
|
132
|
+
].join(' ');
|
|
133
|
+
|
|
134
|
+
const primaryActionClassName = [
|
|
135
|
+
'inline-flex min-h-10 min-w-0 items-center gap-2 px-4 py-2 text-sm font-semibold',
|
|
136
|
+
'prompt-primary-action bg-[var(--color-text-primary)] text-[var(--color-bg-primary)] transition-opacity cursor-pointer',
|
|
137
|
+
'hover:opacity-90',
|
|
138
|
+
contrastSafeFocusClassName,
|
|
139
|
+
].join(' ');
|
|
140
|
+
|
|
141
|
+
function PromptDialog({
|
|
142
|
+
isOpen,
|
|
143
|
+
prompt,
|
|
144
|
+
title,
|
|
145
|
+
copyState,
|
|
146
|
+
onCopy,
|
|
147
|
+
onClose,
|
|
148
|
+
}: PromptDialogProps): ReactElement {
|
|
149
|
+
const dialogRef = useRef<HTMLDialogElement>(null);
|
|
150
|
+
const focusFrameRef = useRef<number | null>(null);
|
|
151
|
+
useBodyScrollLock(isOpen);
|
|
152
|
+
|
|
153
|
+
useEffect(() => {
|
|
154
|
+
const dialog = dialogRef.current;
|
|
155
|
+
if (!dialog) return;
|
|
156
|
+
if (isOpen && !dialog.open) {
|
|
157
|
+
dialog.showModal();
|
|
158
|
+
focusFrameRef.current = requestAnimationFrame(() => {
|
|
159
|
+
dialog.querySelector<HTMLButtonElement>('[aria-label="Close prompt"]')?.focus();
|
|
160
|
+
});
|
|
161
|
+
} else if (!isOpen && dialog.open) {
|
|
162
|
+
dialog.close();
|
|
163
|
+
}
|
|
164
|
+
return () => {
|
|
165
|
+
if (focusFrameRef.current !== null) cancelAnimationFrame(focusFrameRef.current);
|
|
166
|
+
};
|
|
167
|
+
}, [isOpen]);
|
|
168
|
+
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
if (!isOpen) return;
|
|
171
|
+
const handleKeyDown = (event: KeyboardEvent): void => {
|
|
172
|
+
if (event.key === 'Escape') {
|
|
173
|
+
event.preventDefault();
|
|
174
|
+
event.stopPropagation();
|
|
175
|
+
onClose();
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (event.key !== 'Tab' || !dialogRef.current) return;
|
|
179
|
+
const focusable = Array.from(dialogRef.current.querySelectorAll<HTMLElement>(
|
|
180
|
+
'button, [href], [tabindex]:not([tabindex="-1"])',
|
|
181
|
+
)).filter((element) => !element.hasAttribute('disabled'));
|
|
182
|
+
if (focusable.length === 0) return;
|
|
183
|
+
const first = focusable[0];
|
|
184
|
+
const last = focusable[focusable.length - 1];
|
|
185
|
+
if (event.shiftKey && document.activeElement === first) {
|
|
186
|
+
event.preventDefault();
|
|
187
|
+
last.focus();
|
|
188
|
+
} else if (!event.shiftKey && document.activeElement === last) {
|
|
189
|
+
event.preventDefault();
|
|
190
|
+
first.focus();
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
window.addEventListener('keydown', handleKeyDown, true);
|
|
194
|
+
return () => window.removeEventListener('keydown', handleKeyDown, true);
|
|
195
|
+
}, [isOpen, onClose]);
|
|
196
|
+
|
|
197
|
+
return (
|
|
198
|
+
<dialog
|
|
199
|
+
ref={dialogRef}
|
|
200
|
+
aria-modal="true"
|
|
201
|
+
aria-label={title ?? 'Prompt'}
|
|
202
|
+
className="prompt-dialog m-auto max-h-[calc(100dvh-2rem)] w-[calc(100%-2rem)] max-w-4xl overflow-hidden rounded-[var(--radius-lg)] border border-[var(--color-border)] bg-[var(--color-bg-primary)] p-0 text-[var(--color-text-primary)] shadow-[var(--shadow-lg)]"
|
|
203
|
+
onCancel={(event) => {
|
|
204
|
+
event.preventDefault();
|
|
205
|
+
onClose();
|
|
206
|
+
}}
|
|
207
|
+
onMouseDown={(event) => {
|
|
208
|
+
if (event.target === event.currentTarget) onClose();
|
|
209
|
+
}}
|
|
210
|
+
>
|
|
211
|
+
<div className="flex max-h-[calc(100dvh-2rem)] min-h-0 flex-col">
|
|
212
|
+
<div className="flex shrink-0 items-center justify-between gap-3 border-b border-[var(--color-border)] px-4 py-3">
|
|
213
|
+
<h2 className="m-0 min-w-0 truncate text-sm font-semibold text-[var(--color-text-primary)]">
|
|
214
|
+
{title ?? 'Prompt'}
|
|
215
|
+
</h2>
|
|
216
|
+
<button
|
|
217
|
+
type="button"
|
|
218
|
+
aria-label="Close prompt"
|
|
219
|
+
className={promptUtilityClassName}
|
|
220
|
+
onClick={onClose}
|
|
221
|
+
>
|
|
222
|
+
<i className="fa-solid fa-xmark" aria-hidden="true" />
|
|
223
|
+
</button>
|
|
224
|
+
</div>
|
|
225
|
+
<div className="flex min-h-0 flex-1 gap-3 overflow-hidden p-4">
|
|
226
|
+
<pre
|
|
227
|
+
data-testid="prompt-dialog-source"
|
|
228
|
+
role="region"
|
|
229
|
+
aria-label="Prompt source"
|
|
230
|
+
tabIndex={0}
|
|
231
|
+
className={`m-0 min-h-0 min-w-0 flex-1 overflow-auto overscroll-contain whitespace-pre-wrap break-words font-mono text-sm leading-6 text-[var(--color-text-primary)] ${contrastSafeFocusClassName}`}
|
|
232
|
+
>
|
|
233
|
+
{prompt}
|
|
234
|
+
</pre>
|
|
235
|
+
<PromptCopyButton
|
|
236
|
+
copyState={copyState}
|
|
237
|
+
className={promptUtilityClassName}
|
|
238
|
+
onCopy={onCopy}
|
|
239
|
+
/>
|
|
240
|
+
</div>
|
|
241
|
+
<span role="status" aria-live="polite" className="sr-only">
|
|
242
|
+
{copyState === 'copied' ? 'Copied' : copyState === 'error' ? 'Copy failed' : ''}
|
|
243
|
+
</span>
|
|
244
|
+
</div>
|
|
245
|
+
<style jsx>{`
|
|
246
|
+
.prompt-dialog::backdrop {
|
|
247
|
+
background: var(--color-text-primary);
|
|
248
|
+
opacity: 0.6;
|
|
249
|
+
backdrop-filter: blur(4px);
|
|
250
|
+
}
|
|
251
|
+
`}</style>
|
|
252
|
+
</dialog>
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
73
256
|
export function Prompt({
|
|
74
257
|
children,
|
|
75
258
|
title,
|
|
@@ -84,9 +267,12 @@ export function Prompt({
|
|
|
84
267
|
}: PromptProps): ReactElement {
|
|
85
268
|
const [copyState, setCopyState] = useState<CopyState>('idle');
|
|
86
269
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
270
|
+
const [dialogOpen, setDialogOpen] = useState(false);
|
|
87
271
|
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
88
272
|
const copyAttemptRef = useRef(0);
|
|
89
273
|
const mountedRef = useRef(false);
|
|
274
|
+
const expandTriggerRef = useRef<HTMLButtonElement>(null);
|
|
275
|
+
const returnFocusFrameRef = useRef<number | null>(null);
|
|
90
276
|
const menuBoundaryRef = useRef<HTMLDivElement>(null);
|
|
91
277
|
const triggerRef = useRef<HTMLButtonElement>(null);
|
|
92
278
|
const itemRefs = useRef<Array<HTMLAnchorElement | null>>([]);
|
|
@@ -105,6 +291,8 @@ export function Prompt({
|
|
|
105
291
|
const hasTitle = Boolean(title?.trim());
|
|
106
292
|
const shouldHidePrompt = hasTitle && (hidePrompt === true || hidePrompt === 'true');
|
|
107
293
|
const authorIcon = resolveAuthorIcon(icon, iconType);
|
|
294
|
+
const hasDescription = description !== undefined;
|
|
295
|
+
const hasHeader = hasTitle || resolvedActions.length > 0;
|
|
108
296
|
|
|
109
297
|
const closeMenu = useCallback(() => {
|
|
110
298
|
setMenuOpen(false);
|
|
@@ -115,6 +303,13 @@ export function Prompt({
|
|
|
115
303
|
triggerRef.current?.focus();
|
|
116
304
|
}, []);
|
|
117
305
|
|
|
306
|
+
const closeDialog = useCallback(() => {
|
|
307
|
+
setDialogOpen(false);
|
|
308
|
+
returnFocusFrameRef.current = requestAnimationFrame(() => {
|
|
309
|
+
expandTriggerRef.current?.focus();
|
|
310
|
+
});
|
|
311
|
+
}, []);
|
|
312
|
+
|
|
118
313
|
useOnClickOutside(menuBoundaryRef, closeMenu, menuOpen);
|
|
119
314
|
|
|
120
315
|
useEffect(() => {
|
|
@@ -126,6 +321,12 @@ export function Prompt({
|
|
|
126
321
|
};
|
|
127
322
|
}, []);
|
|
128
323
|
|
|
324
|
+
useEffect(() => () => {
|
|
325
|
+
if (returnFocusFrameRef.current !== null) {
|
|
326
|
+
cancelAnimationFrame(returnFocusFrameRef.current);
|
|
327
|
+
}
|
|
328
|
+
}, []);
|
|
329
|
+
|
|
129
330
|
useEffect(() => {
|
|
130
331
|
if (menuOpen) itemRefs.current[0]?.focus();
|
|
131
332
|
}, [menuOpen]);
|
|
@@ -193,157 +394,183 @@ export function Prompt({
|
|
|
193
394
|
}, [closeMenuAndFocusTrigger, secondary.length]);
|
|
194
395
|
|
|
195
396
|
const rootClassName = [
|
|
196
|
-
'not-prose my-4 min-w-0 max-w-full overflow-visible',
|
|
197
|
-
'rounded-[var(--radius-lg)] border
|
|
198
|
-
'bg-[var(--color-bg-secondary)] text-[var(--color-text-primary)]',
|
|
199
|
-
'shadow-[var(--shadow-sm)]',
|
|
397
|
+
'prompt-card-fern not-prose my-4 min-w-0 max-w-full overflow-visible',
|
|
398
|
+
'rounded-[calc(var(--radius-lg)+0.25rem)] border text-[var(--color-text-primary)]',
|
|
200
399
|
className,
|
|
201
400
|
].filter(Boolean).join(' ');
|
|
202
401
|
|
|
203
|
-
const actionClassName = [
|
|
204
|
-
'inline-flex min-w-0 max-w-full items-center gap-2 rounded-[var(--radius-lg)]',
|
|
205
|
-
'border border-[var(--color-border)] px-3 py-2 text-sm font-medium',
|
|
206
|
-
'text-[var(--color-text-primary)] transition-colors cursor-pointer',
|
|
207
|
-
'hover:border-[var(--color-primary)] hover:text-[var(--color-primary)]',
|
|
208
|
-
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)]',
|
|
209
|
-
'disabled:cursor-not-allowed disabled:opacity-50',
|
|
210
|
-
].join(' ');
|
|
211
|
-
|
|
212
402
|
return (
|
|
213
403
|
<section data-testid="prompt-card" className={rootClassName}>
|
|
214
|
-
|
|
215
|
-
data-testid={!hasTitle ? 'prompt-body-row' : undefined}
|
|
216
|
-
className={hasTitle
|
|
217
|
-
? 'contents'
|
|
218
|
-
: 'flex min-w-0 max-w-full flex-wrap items-start gap-3 px-4 py-4'}
|
|
219
|
-
>
|
|
404
|
+
{hasHeader ? (
|
|
220
405
|
<div
|
|
221
|
-
data-testid=
|
|
222
|
-
className=
|
|
223
|
-
? 'flex min-w-0 max-w-full items-center gap-3 px-4 pt-4'
|
|
224
|
-
: 'contents'}
|
|
406
|
+
data-testid="prompt-header"
|
|
407
|
+
className="flex min-w-0 flex-col items-stretch gap-3 px-4 py-3 sm:flex-row sm:items-center sm:justify-between sm:px-5"
|
|
225
408
|
>
|
|
226
|
-
<span
|
|
227
|
-
data-testid="prompt-icon"
|
|
228
|
-
className="shrink-0 text-[var(--color-primary)]"
|
|
229
|
-
aria-hidden="true"
|
|
230
|
-
>
|
|
231
|
-
<Icon icon={authorIcon} size={18} />
|
|
232
|
-
</span>
|
|
233
409
|
{hasTitle ? (
|
|
234
|
-
<h3 className="m-0
|
|
410
|
+
<h3 className="prompt-title m-0 w-full min-w-0 break-words [overflow-wrap:anywhere] text-base font-semibold text-[var(--color-text-primary)] sm:w-auto sm:flex-1">
|
|
235
411
|
{title}
|
|
236
412
|
</h3>
|
|
237
413
|
) : null}
|
|
238
|
-
</div>
|
|
239
|
-
|
|
240
|
-
{!shouldHidePrompt ? (
|
|
241
414
|
<div
|
|
242
|
-
data-testid="prompt-
|
|
243
|
-
className=
|
|
415
|
+
data-testid="prompt-actions"
|
|
416
|
+
className="flex min-w-0 max-w-full items-stretch justify-end self-end sm:ml-auto sm:self-auto"
|
|
244
417
|
>
|
|
245
|
-
{
|
|
418
|
+
{primary ? (
|
|
419
|
+
<a
|
|
420
|
+
href={primary.href}
|
|
421
|
+
target="_blank"
|
|
422
|
+
rel="noopener noreferrer"
|
|
423
|
+
aria-label={primary.label}
|
|
424
|
+
className={`${primaryActionClassName} ${secondary.length > 0 ? 'rounded-l-[var(--radius-lg)]' : 'rounded-[var(--radius-lg)]'}`}
|
|
425
|
+
>
|
|
426
|
+
<span aria-hidden="true"><ActionIcon action={primary.action} /></span>
|
|
427
|
+
<span className="min-w-0 truncate">{primary.label}</span>
|
|
428
|
+
</a>
|
|
429
|
+
) : null}
|
|
430
|
+
{secondary.length > 0 ? (
|
|
431
|
+
<div ref={menuBoundaryRef} className="relative flex shrink-0">
|
|
432
|
+
<button
|
|
433
|
+
ref={triggerRef}
|
|
434
|
+
type="button"
|
|
435
|
+
aria-label="More prompt actions"
|
|
436
|
+
aria-haspopup="menu"
|
|
437
|
+
aria-expanded={menuOpen}
|
|
438
|
+
aria-controls={menuId}
|
|
439
|
+
className={`${primaryActionClassName} min-w-10 rounded-r-[var(--radius-lg)] border-l border-[var(--color-bg-primary)] px-3`}
|
|
440
|
+
onMouseDown={(event) => {
|
|
441
|
+
if (menuOpen) event.preventDefault();
|
|
442
|
+
}}
|
|
443
|
+
onClick={() => {
|
|
444
|
+
setMenuOpen((open) => !open);
|
|
445
|
+
if (menuOpen) triggerRef.current?.focus();
|
|
446
|
+
}}
|
|
447
|
+
>
|
|
448
|
+
<i className="fa-solid fa-chevron-down text-xs" aria-hidden="true" />
|
|
449
|
+
</button>
|
|
450
|
+
{menuOpen ? (
|
|
451
|
+
<div
|
|
452
|
+
id={menuId}
|
|
453
|
+
role="menu"
|
|
454
|
+
aria-label="More prompt actions"
|
|
455
|
+
className="absolute right-0 top-full z-20 mt-2 w-max max-w-[min(20rem,calc(100vw-2rem))] rounded-[var(--radius-lg)] border border-[var(--color-border)] bg-[var(--color-bg-primary)] p-1 shadow-[var(--shadow-sm)]"
|
|
456
|
+
onKeyDown={handleMenuKeyDown}
|
|
457
|
+
onBlur={(event) => {
|
|
458
|
+
if (!event.currentTarget.contains(event.relatedTarget)) closeMenu();
|
|
459
|
+
}}
|
|
460
|
+
>
|
|
461
|
+
{secondary.map((action, index) => (
|
|
462
|
+
<a
|
|
463
|
+
key={`${action.label}-${action.href}-${index}`}
|
|
464
|
+
ref={(node) => { itemRefs.current[index] = node; }}
|
|
465
|
+
role="menuitem"
|
|
466
|
+
tabIndex={-1}
|
|
467
|
+
href={action.href}
|
|
468
|
+
target="_blank"
|
|
469
|
+
rel="noopener noreferrer"
|
|
470
|
+
aria-label={action.label}
|
|
471
|
+
className={`flex min-h-10 min-w-0 max-w-full cursor-pointer items-center gap-2 rounded-[var(--radius-lg)] px-3 py-2 text-sm text-[var(--color-text-primary)] hover:bg-[var(--color-border)] ${contrastSafeFocusClassName}`}
|
|
472
|
+
onClick={closeMenuAndFocusTrigger}
|
|
473
|
+
>
|
|
474
|
+
<span aria-hidden="true"><ActionIcon action={action.action} /></span>
|
|
475
|
+
<span className="min-w-0 truncate">{action.label}</span>
|
|
476
|
+
</a>
|
|
477
|
+
))}
|
|
478
|
+
</div>
|
|
479
|
+
) : null}
|
|
480
|
+
</div>
|
|
481
|
+
) : null}
|
|
482
|
+
{shouldHidePrompt && hasPrompt ? (
|
|
483
|
+
<PromptCopyButton
|
|
484
|
+
copyState={copyState}
|
|
485
|
+
className={`${promptUtilityClassName} ml-2`}
|
|
486
|
+
onCopy={copyPrompt}
|
|
487
|
+
/>
|
|
488
|
+
) : null}
|
|
246
489
|
</div>
|
|
247
|
-
|
|
490
|
+
</div>
|
|
491
|
+
) : null}
|
|
248
492
|
|
|
493
|
+
{!shouldHidePrompt ? (
|
|
249
494
|
<div
|
|
250
|
-
data-testid="prompt-
|
|
251
|
-
className={`flex min-w-0
|
|
495
|
+
data-testid="prompt-well"
|
|
496
|
+
className={`prompt-well mx-3 mb-3 flex min-w-0 items-start gap-3 rounded-[var(--radius-lg)] border bg-[var(--color-bg-primary)] px-3 py-3 sm:mx-4 sm:mb-4 sm:px-4 ${hasHeader ? '' : 'mt-3 sm:mt-4'}`}
|
|
252
497
|
>
|
|
253
|
-
<
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
data-copy-state={copyState}
|
|
258
|
-
disabled={!hasPrompt}
|
|
259
|
-
onClick={copyPrompt}
|
|
498
|
+
<span
|
|
499
|
+
data-testid="prompt-icon"
|
|
500
|
+
className="mt-1 shrink-0 text-[var(--color-primary)]"
|
|
501
|
+
aria-hidden="true"
|
|
260
502
|
>
|
|
261
|
-
<
|
|
262
|
-
<span>{copyState === 'copied' ? 'Copied' : copyState === 'error' ? 'Copy failed' : 'Copy'}</span>
|
|
263
|
-
</button>
|
|
264
|
-
|
|
265
|
-
<span role="status" aria-live="polite" className="sr-only">
|
|
266
|
-
{copyState === 'copied' ? 'Copied' : copyState === 'error' ? 'Copy failed' : ''}
|
|
503
|
+
<Icon icon={authorIcon} size={18} />
|
|
267
504
|
</span>
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
>
|
|
277
|
-
<span aria-hidden="true"><ActionIcon action={primary.action} /></span>
|
|
278
|
-
<span className="min-w-0 truncate">{primary.label}</span>
|
|
279
|
-
</a>
|
|
280
|
-
) : null}
|
|
281
|
-
|
|
282
|
-
{secondary.length > 0 ? (
|
|
283
|
-
<div
|
|
284
|
-
ref={menuBoundaryRef}
|
|
285
|
-
className="relative flex min-w-0 max-w-full basis-full w-full shrink-0 justify-end sm:ml-auto sm:basis-auto sm:w-auto sm:shrink"
|
|
286
|
-
>
|
|
505
|
+
<div
|
|
506
|
+
data-testid="prompt-preview"
|
|
507
|
+
className={`prompt-preview min-w-0 flex-1 text-sm leading-6 text-[var(--color-text-primary)]${hasPrompt && !hasDescription ? ' font-mono whitespace-pre-wrap' : ''}${isSingleLine ? ' prompt-preview-single-line' : ''}`}
|
|
508
|
+
>
|
|
509
|
+
{hasDescription ? renderInlineMarkdown(description) : prompt || children}
|
|
510
|
+
</div>
|
|
511
|
+
{hasPrompt ? (
|
|
512
|
+
<div data-testid="prompt-utilities" className="flex shrink-0 items-center gap-1">
|
|
287
513
|
<button
|
|
288
|
-
ref={
|
|
514
|
+
ref={expandTriggerRef}
|
|
289
515
|
type="button"
|
|
290
|
-
aria-label="
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
className={actionClassName}
|
|
295
|
-
onMouseDown={(event) => {
|
|
296
|
-
if (menuOpen) event.preventDefault();
|
|
297
|
-
}}
|
|
298
|
-
onClick={() => {
|
|
299
|
-
setMenuOpen((open) => !open);
|
|
300
|
-
if (menuOpen) triggerRef.current?.focus();
|
|
301
|
-
}}
|
|
516
|
+
aria-label="Expand prompt"
|
|
517
|
+
title="Expand prompt"
|
|
518
|
+
className={promptUtilityClassName}
|
|
519
|
+
onClick={() => setDialogOpen(true)}
|
|
302
520
|
>
|
|
303
|
-
<
|
|
304
|
-
<i className="fa-solid fa-chevron-down text-xs" aria-hidden="true" />
|
|
521
|
+
<i className="fa-solid fa-expand" aria-hidden="true" />
|
|
305
522
|
</button>
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
aria-label="More prompt actions"
|
|
312
|
-
className="absolute top-full right-0 z-20 mt-2 w-max max-w-[min(20rem,calc(100vw-2rem))] rounded-[var(--radius-lg)] border border-[var(--color-border)] bg-[var(--color-bg-secondary)] p-1 shadow-[var(--shadow-sm)]"
|
|
313
|
-
onKeyDown={handleMenuKeyDown}
|
|
314
|
-
onBlur={(event) => {
|
|
315
|
-
if (!event.currentTarget.contains(event.relatedTarget)) {
|
|
316
|
-
closeMenu();
|
|
317
|
-
}
|
|
318
|
-
}}
|
|
319
|
-
>
|
|
320
|
-
{secondary.map((action, index) => (
|
|
321
|
-
<a
|
|
322
|
-
key={`${action.label}-${action.href}-${index}`}
|
|
323
|
-
ref={(node) => { itemRefs.current[index] = node; }}
|
|
324
|
-
role="menuitem"
|
|
325
|
-
tabIndex={-1}
|
|
326
|
-
href={action.href}
|
|
327
|
-
target="_blank"
|
|
328
|
-
rel="noopener noreferrer"
|
|
329
|
-
aria-label={action.label}
|
|
330
|
-
className="flex min-w-0 max-w-full cursor-pointer items-center gap-2 rounded-[var(--radius-lg)] px-3 py-2 text-sm text-[var(--color-text-primary)] hover:bg-[var(--color-border)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)]"
|
|
331
|
-
onClick={closeMenuAndFocusTrigger}
|
|
332
|
-
>
|
|
333
|
-
<span aria-hidden="true"><ActionIcon action={action.action} /></span>
|
|
334
|
-
<span className="min-w-0 truncate">{action.label}</span>
|
|
335
|
-
</a>
|
|
336
|
-
))}
|
|
337
|
-
</div>
|
|
338
|
-
) : null}
|
|
523
|
+
<PromptCopyButton
|
|
524
|
+
copyState={copyState}
|
|
525
|
+
className={promptUtilityClassName}
|
|
526
|
+
onCopy={copyPrompt}
|
|
527
|
+
/>
|
|
339
528
|
</div>
|
|
340
529
|
) : null}
|
|
341
530
|
</div>
|
|
342
|
-
|
|
531
|
+
) : null}
|
|
532
|
+
{!dialogOpen ? (
|
|
533
|
+
<span role="status" aria-live="polite" className="sr-only">
|
|
534
|
+
{copyState === 'copied' ? 'Copied' : copyState === 'error' ? 'Copy failed' : ''}
|
|
535
|
+
</span>
|
|
536
|
+
) : null}
|
|
537
|
+
|
|
538
|
+
<PromptDialog
|
|
539
|
+
isOpen={dialogOpen}
|
|
540
|
+
prompt={prompt}
|
|
541
|
+
title={hasTitle ? title!.trim() : undefined}
|
|
542
|
+
copyState={copyState}
|
|
543
|
+
onCopy={copyPrompt}
|
|
544
|
+
onClose={closeDialog}
|
|
545
|
+
/>
|
|
343
546
|
|
|
344
547
|
<style jsx>{`
|
|
548
|
+
.prompt-card-fern {
|
|
549
|
+
border-color: var(--color-primary);
|
|
550
|
+
background: var(--color-bg-secondary);
|
|
551
|
+
}
|
|
552
|
+
.prompt-well {
|
|
553
|
+
border-color: var(--color-border);
|
|
554
|
+
}
|
|
555
|
+
.prompt-primary-action {
|
|
556
|
+
background: var(--color-text-primary);
|
|
557
|
+
color: var(--color-bg-primary);
|
|
558
|
+
}
|
|
559
|
+
.prompt-title {
|
|
560
|
+
color: var(--color-text-primary);
|
|
561
|
+
}
|
|
562
|
+
@supports (color: color-mix(in srgb, black, white)) {
|
|
563
|
+
.prompt-card-fern {
|
|
564
|
+
border-color: color-mix(in srgb, var(--color-primary) 48%, var(--color-border));
|
|
565
|
+
background: color-mix(in srgb, var(--color-primary) 7%, var(--color-bg-primary));
|
|
566
|
+
}
|
|
567
|
+
.prompt-well {
|
|
568
|
+
border-color: color-mix(in srgb, var(--color-border) 88%, var(--color-primary));
|
|
569
|
+
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-primary) 3%, transparent);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
345
572
|
.prompt-preview {
|
|
346
|
-
max-height:
|
|
573
|
+
max-height: 10rem;
|
|
347
574
|
overflow-y: auto;
|
|
348
575
|
overflow-wrap: anywhere;
|
|
349
576
|
}
|
|
@@ -30,9 +30,10 @@ interface CaptureResult {
|
|
|
30
30
|
error?: string;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
// Headroom for the retry path: two 15s page.goto budgets + 3s
|
|
34
|
-
//
|
|
35
|
-
// (closed-target only) fail fast
|
|
33
|
+
// Headroom for the retry path: two 15s page.goto('load') budgets + 3s retry
|
|
34
|
+
// wait + 2s best-effort networkidle + 1s settle total ~36s worst case before
|
|
35
|
+
// the screenshot is taken. Launch retries (closed-target only) fail fast
|
|
36
|
+
// (<~2s) so they stay inside this 45s race.
|
|
36
37
|
const SCREENSHOT_TIMEOUT_MS = 45000;
|
|
37
38
|
|
|
38
39
|
// Playwright launch flakes intermittently in the container — the Chromium
|
|
@@ -201,22 +202,31 @@ export async function captureHomepageScreenshot(options: CaptureOptions): Promis
|
|
|
201
202
|
// Cold render after a project-wide revalidation can transiently 404 —
|
|
202
203
|
// retry once on 4xx/5xx, then capture whatever the page shows so the
|
|
203
204
|
// dashboard preview reflects the real state of the site.
|
|
205
|
+
//
|
|
206
|
+
// Wait for 'load' (document + images/CSS/fonts), NOT 'networkidle'. A
|
|
207
|
+
// custom-domain-only subdomain 404s the client's RSC nav prefetches
|
|
208
|
+
// (`/docs/<page>?_rsc=…`) — they're built from the route and carry no
|
|
209
|
+
// ?jd_proxy=1 marker — so Next keeps retrying them and a large docs site
|
|
210
|
+
// (jamdesk-docs) NEVER goes network-idle. 'networkidle' timed out at 15s
|
|
211
|
+
// and every capture/Retry failed. 'load' fires before the prefetch storm.
|
|
212
|
+
const gotoOpts = { waitUntil: 'load', timeout: 15000 } as const;
|
|
204
213
|
console.log(`Capturing screenshot from: ${homepageUrl}`);
|
|
205
|
-
const firstResponse = await page.goto(homepageUrl,
|
|
206
|
-
waitUntil: 'networkidle',
|
|
207
|
-
timeout: 15000,
|
|
208
|
-
});
|
|
214
|
+
const firstResponse = await page.goto(homepageUrl, gotoOpts);
|
|
209
215
|
const firstStatus = firstResponse?.status();
|
|
210
216
|
|
|
211
217
|
if (firstStatus !== undefined && firstStatus >= 400) {
|
|
212
218
|
console.log(`Screenshot got ${firstStatus} on first attempt, retrying once after 3s`);
|
|
213
219
|
await page.waitForTimeout(3000);
|
|
214
|
-
await page.goto(homepageUrl,
|
|
215
|
-
waitUntil: 'networkidle',
|
|
216
|
-
timeout: 15000,
|
|
217
|
-
});
|
|
220
|
+
await page.goto(homepageUrl, gotoOpts);
|
|
218
221
|
}
|
|
219
222
|
|
|
223
|
+
// Short best-effort settle for late images/fonts — the page above already
|
|
224
|
+
// reached 'load', and a never-idle page (see the prefetch note above)
|
|
225
|
+
// would otherwise burn the full timeout for nothing. Never fail the
|
|
226
|
+
// capture on it. Mirrors the pdf-service networkidle fallback
|
|
227
|
+
// (worker-pool.ts).
|
|
228
|
+
await page.waitForLoadState('networkidle', { timeout: 2000 }).catch(() => {});
|
|
229
|
+
|
|
220
230
|
// Additional wait for any late-loading content
|
|
221
231
|
await page.waitForTimeout(1000);
|
|
222
232
|
|
|
@@ -53,6 +53,25 @@
|
|
|
53
53
|
--color-accent-light: #FBF0DE;
|
|
54
54
|
--color-accent-text: #8A5E23;
|
|
55
55
|
|
|
56
|
+
/* Primary — the platform's "brand" token, read by the TOC scroll thumb,
|
|
57
|
+
active TOC links, active step chips, Card/Tile icons and hover borders,
|
|
58
|
+
li::marker, code-line highlights, the update badge, and more. It is ONLY
|
|
59
|
+
ever emitted by generatePrimaryColorVariables (layout-helpers.tsx) when a
|
|
60
|
+
project sets colors.primary — there is NO global default — so without
|
|
61
|
+
this line every one of those consumers computes to transparent/inherit
|
|
62
|
+
and silently vanishes (the invisible TOC thumb bug). Halo's primary IS
|
|
63
|
+
its accent, the same primary==accent equivalence
|
|
64
|
+
generatePrimaryColorVariables itself enforces. var() is late-resolved,
|
|
65
|
+
so this single :root declaration tracks the .dark accent swap — no .dark
|
|
66
|
+
restatement needed. A project's colors.primary still wins: its style
|
|
67
|
+
block (jd-colors-<slug>) is injected AFTER this file (jd-theme-halo) at
|
|
68
|
+
the same precedence, so its --color-primary out-cascades this on source
|
|
69
|
+
order. --color-primary-dark rides along because PlaygroundModal reads the
|
|
70
|
+
PAIR as a gradient — defining only one would blend caramel into the
|
|
71
|
+
other's indigo fallback. */
|
|
72
|
+
--color-primary: var(--color-accent);
|
|
73
|
+
--color-primary-dark: var(--color-accent-hover);
|
|
74
|
+
|
|
56
75
|
/* Code block colors — light. Tracks --color-bg-secondary by hand (a literal,
|
|
57
76
|
not a var(), to match how every other theme writes this block): a code
|
|
58
77
|
panel sits one step below the card, same as the ground. Left behind when
|
|
@@ -368,11 +387,40 @@ body[data-theme="halo"] .sidebar-scroll ul li a.nav-active {
|
|
|
368
387
|
font-weight: 600;
|
|
369
388
|
}
|
|
370
389
|
|
|
371
|
-
/* Tab + TOC links match the sidebar pill
|
|
390
|
+
/* Tab + TOC links match the sidebar pill (var(--radius-lg), same as the
|
|
391
|
+
.sidebar-scroll ::before highlight) — --radius-md left them a step tighter. */
|
|
372
392
|
body[data-theme="halo"] .nav-tab-link,
|
|
373
393
|
body[data-theme="halo"] .toc-link,
|
|
374
394
|
body[data-theme="halo"] .toc-link-bg {
|
|
375
|
-
border-radius: var(--radius-
|
|
395
|
+
border-radius: var(--radius-lg) !important;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/* TOC step-number circles ("On this page" → <Steps> headings). TableOfContents
|
|
399
|
+
sets the INACTIVE number inline to var(--color-text-muted). LIGHT mode is the
|
|
400
|
+
broken case: on halo's sand card that muted token is #A99D89 on ~#FFFDF9 =
|
|
401
|
+
2.6:1, so the numbers read as invisible until a step goes active. Secondary
|
|
402
|
+
(#5C5346 = ~7.4:1) clears the 4.5:1 floor with margin; tertiary (4.26:1)
|
|
403
|
+
would sit just under it. (Earlier "still faint" field reports were a stale
|
|
404
|
+
open tab, not a cascade loss — this CSS is a runtime fs read inlined as a
|
|
405
|
+
React-hoisted <style>, so Turbopack never hot-reloads it; verify edits with
|
|
406
|
+
a full page reload.) Scoped to LIGHT only (html:not(.dark)): in dark, muted on
|
|
407
|
+
the near-black ground already reads fine, so dark keeps the shipped default.
|
|
408
|
+
Inline colour ⇒ !important; inactive-only via data-active so the active
|
|
409
|
+
white-on-caramel chip is untouched. */
|
|
410
|
+
html:not(.dark) body[data-theme="halo"] a[data-step][data-active="false"] > span[aria-hidden="true"] {
|
|
411
|
+
color: var(--color-text-secondary) !important;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/* ACTIVE step number, dark only. The component fills the circle inline with
|
|
415
|
+
var(--color-primary) and a #fff digit. In light that now resolves (via the
|
|
416
|
+
:root default above) to caramel #C0873F — white-on-caramel at ~3.1:1, the
|
|
417
|
+
intended active look, so light needs no rule here. In dark the same fill
|
|
418
|
+
would be #E0A867, putting the white digit at ~2.1:1 — LESS legible than the
|
|
419
|
+
shipped-and-approved dark rendering, which is the bare white digit on the
|
|
420
|
+
near-black card (~17:1). Pin the dark chip transparent so defining
|
|
421
|
+
--color-primary cannot regress the approved dark look. */
|
|
422
|
+
html.dark body[data-theme="halo"] a[data-step][data-active="true"] > span[aria-hidden="true"] {
|
|
423
|
+
background-color: transparent !important;
|
|
376
424
|
}
|
|
377
425
|
|
|
378
426
|
/* ===== HALO SIGNATURE: THE CONTENT CARD ===== */
|
|
@@ -467,6 +515,27 @@ body[data-theme="halo"] {
|
|
|
467
515
|
}
|
|
468
516
|
}
|
|
469
517
|
|
|
518
|
+
/* Sidebar scroll container height cap — REQUIRED for a tall nav to scroll.
|
|
519
|
+
The shared markup gives .sidebar-scroll `overflow-y-auto` but no bounded
|
|
520
|
+
height, and its <aside> is `lg:self-start` (height = content), so without a
|
|
521
|
+
cap the nav grows unbounded and never scrolls once it's taller than the
|
|
522
|
+
viewport. jam and nebula both carry this exact rule; halo's full-bleed rewrite
|
|
523
|
+
dropped it. Header is 57px tall; a top tab strip adds another 57px (114px). */
|
|
524
|
+
@media (min-width: 1024px) {
|
|
525
|
+
body[data-theme="halo"] .sidebar-scroll {
|
|
526
|
+
position: sticky !important;
|
|
527
|
+
flex: 0 0 auto !important;
|
|
528
|
+
}
|
|
529
|
+
body[data-theme="halo"] .sidebar-scroll[data-has-tabs="true"] {
|
|
530
|
+
top: 114px !important;
|
|
531
|
+
max-height: calc(100vh - 114px) !important;
|
|
532
|
+
}
|
|
533
|
+
body[data-theme="halo"] .sidebar-scroll[data-has-tabs="false"] {
|
|
534
|
+
top: 57px !important;
|
|
535
|
+
max-height: calc(100vh - 57px) !important;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
470
539
|
/* 6. Vertical alignment of the three columns.
|
|
471
540
|
The article and the TOC wrapper both use `py-6 sm:py-10`, so breadcrumb
|
|
472
541
|
and "On this page" already share a baseline at 2.5rem. The sidebar's first
|
|
@@ -512,3 +581,4 @@ body[data-theme="halo"] .sidebar-scroll .sidebar-nav-groups > div.ml-6 {
|
|
|
512
581
|
min-height: 36px;
|
|
513
582
|
}
|
|
514
583
|
}
|
|
584
|
+
|
|
@@ -1275,47 +1275,47 @@
|
|
|
1275
1275
|
}
|
|
1276
1276
|
},
|
|
1277
1277
|
"node_modules/@tailwindcss/node": {
|
|
1278
|
-
"version": "4.3.
|
|
1279
|
-
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.
|
|
1280
|
-
"integrity": "sha512
|
|
1278
|
+
"version": "4.3.3",
|
|
1279
|
+
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz",
|
|
1280
|
+
"integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==",
|
|
1281
1281
|
"license": "MIT",
|
|
1282
1282
|
"dependencies": {
|
|
1283
1283
|
"@jridgewell/remapping": "^2.3.5",
|
|
1284
|
-
"enhanced-resolve": "5.
|
|
1284
|
+
"enhanced-resolve": "^5.24.1",
|
|
1285
1285
|
"jiti": "^2.7.0",
|
|
1286
1286
|
"lightningcss": "1.32.0",
|
|
1287
1287
|
"magic-string": "^0.30.21",
|
|
1288
1288
|
"source-map-js": "^1.2.1",
|
|
1289
|
-
"tailwindcss": "4.3.
|
|
1289
|
+
"tailwindcss": "4.3.3"
|
|
1290
1290
|
}
|
|
1291
1291
|
},
|
|
1292
1292
|
"node_modules/@tailwindcss/oxide": {
|
|
1293
|
-
"version": "4.3.
|
|
1294
|
-
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.
|
|
1295
|
-
"integrity": "sha512-
|
|
1293
|
+
"version": "4.3.3",
|
|
1294
|
+
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz",
|
|
1295
|
+
"integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==",
|
|
1296
1296
|
"license": "MIT",
|
|
1297
1297
|
"engines": {
|
|
1298
1298
|
"node": ">= 20"
|
|
1299
1299
|
},
|
|
1300
1300
|
"optionalDependencies": {
|
|
1301
|
-
"@tailwindcss/oxide-android-arm64": "4.3.
|
|
1302
|
-
"@tailwindcss/oxide-darwin-arm64": "4.3.
|
|
1303
|
-
"@tailwindcss/oxide-darwin-x64": "4.3.
|
|
1304
|
-
"@tailwindcss/oxide-freebsd-x64": "4.3.
|
|
1305
|
-
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.
|
|
1306
|
-
"@tailwindcss/oxide-linux-arm64-gnu": "4.3.
|
|
1307
|
-
"@tailwindcss/oxide-linux-arm64-musl": "4.3.
|
|
1308
|
-
"@tailwindcss/oxide-linux-x64-gnu": "4.3.
|
|
1309
|
-
"@tailwindcss/oxide-linux-x64-musl": "4.3.
|
|
1310
|
-
"@tailwindcss/oxide-wasm32-wasi": "4.3.
|
|
1311
|
-
"@tailwindcss/oxide-win32-arm64-msvc": "4.3.
|
|
1312
|
-
"@tailwindcss/oxide-win32-x64-msvc": "4.3.
|
|
1301
|
+
"@tailwindcss/oxide-android-arm64": "4.3.3",
|
|
1302
|
+
"@tailwindcss/oxide-darwin-arm64": "4.3.3",
|
|
1303
|
+
"@tailwindcss/oxide-darwin-x64": "4.3.3",
|
|
1304
|
+
"@tailwindcss/oxide-freebsd-x64": "4.3.3",
|
|
1305
|
+
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3",
|
|
1306
|
+
"@tailwindcss/oxide-linux-arm64-gnu": "4.3.3",
|
|
1307
|
+
"@tailwindcss/oxide-linux-arm64-musl": "4.3.3",
|
|
1308
|
+
"@tailwindcss/oxide-linux-x64-gnu": "4.3.3",
|
|
1309
|
+
"@tailwindcss/oxide-linux-x64-musl": "4.3.3",
|
|
1310
|
+
"@tailwindcss/oxide-wasm32-wasi": "4.3.3",
|
|
1311
|
+
"@tailwindcss/oxide-win32-arm64-msvc": "4.3.3",
|
|
1312
|
+
"@tailwindcss/oxide-win32-x64-msvc": "4.3.3"
|
|
1313
1313
|
}
|
|
1314
1314
|
},
|
|
1315
1315
|
"node_modules/@tailwindcss/oxide-android-arm64": {
|
|
1316
|
-
"version": "4.3.
|
|
1317
|
-
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.
|
|
1318
|
-
"integrity": "sha512-
|
|
1316
|
+
"version": "4.3.3",
|
|
1317
|
+
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz",
|
|
1318
|
+
"integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==",
|
|
1319
1319
|
"cpu": [
|
|
1320
1320
|
"arm64"
|
|
1321
1321
|
],
|
|
@@ -1329,9 +1329,9 @@
|
|
|
1329
1329
|
}
|
|
1330
1330
|
},
|
|
1331
1331
|
"node_modules/@tailwindcss/oxide-darwin-arm64": {
|
|
1332
|
-
"version": "4.3.
|
|
1333
|
-
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.
|
|
1334
|
-
"integrity": "sha512-
|
|
1332
|
+
"version": "4.3.3",
|
|
1333
|
+
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz",
|
|
1334
|
+
"integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==",
|
|
1335
1335
|
"cpu": [
|
|
1336
1336
|
"arm64"
|
|
1337
1337
|
],
|
|
@@ -1345,9 +1345,9 @@
|
|
|
1345
1345
|
}
|
|
1346
1346
|
},
|
|
1347
1347
|
"node_modules/@tailwindcss/oxide-darwin-x64": {
|
|
1348
|
-
"version": "4.3.
|
|
1349
|
-
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.
|
|
1350
|
-
"integrity": "sha512-
|
|
1348
|
+
"version": "4.3.3",
|
|
1349
|
+
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz",
|
|
1350
|
+
"integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==",
|
|
1351
1351
|
"cpu": [
|
|
1352
1352
|
"x64"
|
|
1353
1353
|
],
|
|
@@ -1361,9 +1361,9 @@
|
|
|
1361
1361
|
}
|
|
1362
1362
|
},
|
|
1363
1363
|
"node_modules/@tailwindcss/oxide-freebsd-x64": {
|
|
1364
|
-
"version": "4.3.
|
|
1365
|
-
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.
|
|
1366
|
-
"integrity": "sha512-
|
|
1364
|
+
"version": "4.3.3",
|
|
1365
|
+
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz",
|
|
1366
|
+
"integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==",
|
|
1367
1367
|
"cpu": [
|
|
1368
1368
|
"x64"
|
|
1369
1369
|
],
|
|
@@ -1377,9 +1377,9 @@
|
|
|
1377
1377
|
}
|
|
1378
1378
|
},
|
|
1379
1379
|
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
|
|
1380
|
-
"version": "4.3.
|
|
1381
|
-
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.
|
|
1382
|
-
"integrity": "sha512-
|
|
1380
|
+
"version": "4.3.3",
|
|
1381
|
+
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz",
|
|
1382
|
+
"integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==",
|
|
1383
1383
|
"cpu": [
|
|
1384
1384
|
"arm"
|
|
1385
1385
|
],
|
|
@@ -1393,9 +1393,9 @@
|
|
|
1393
1393
|
}
|
|
1394
1394
|
},
|
|
1395
1395
|
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
|
|
1396
|
-
"version": "4.3.
|
|
1397
|
-
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.
|
|
1398
|
-
"integrity": "sha512-
|
|
1396
|
+
"version": "4.3.3",
|
|
1397
|
+
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz",
|
|
1398
|
+
"integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==",
|
|
1399
1399
|
"cpu": [
|
|
1400
1400
|
"arm64"
|
|
1401
1401
|
],
|
|
@@ -1412,9 +1412,9 @@
|
|
|
1412
1412
|
}
|
|
1413
1413
|
},
|
|
1414
1414
|
"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
|
|
1415
|
-
"version": "4.3.
|
|
1416
|
-
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.
|
|
1417
|
-
"integrity": "sha512-
|
|
1415
|
+
"version": "4.3.3",
|
|
1416
|
+
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz",
|
|
1417
|
+
"integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==",
|
|
1418
1418
|
"cpu": [
|
|
1419
1419
|
"arm64"
|
|
1420
1420
|
],
|
|
@@ -1431,9 +1431,9 @@
|
|
|
1431
1431
|
}
|
|
1432
1432
|
},
|
|
1433
1433
|
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
|
|
1434
|
-
"version": "4.3.
|
|
1435
|
-
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.
|
|
1436
|
-
"integrity": "sha512-
|
|
1434
|
+
"version": "4.3.3",
|
|
1435
|
+
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz",
|
|
1436
|
+
"integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==",
|
|
1437
1437
|
"cpu": [
|
|
1438
1438
|
"x64"
|
|
1439
1439
|
],
|
|
@@ -1450,9 +1450,9 @@
|
|
|
1450
1450
|
}
|
|
1451
1451
|
},
|
|
1452
1452
|
"node_modules/@tailwindcss/oxide-linux-x64-musl": {
|
|
1453
|
-
"version": "4.3.
|
|
1454
|
-
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.
|
|
1455
|
-
"integrity": "sha512-
|
|
1453
|
+
"version": "4.3.3",
|
|
1454
|
+
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz",
|
|
1455
|
+
"integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==",
|
|
1456
1456
|
"cpu": [
|
|
1457
1457
|
"x64"
|
|
1458
1458
|
],
|
|
@@ -1469,9 +1469,9 @@
|
|
|
1469
1469
|
}
|
|
1470
1470
|
},
|
|
1471
1471
|
"node_modules/@tailwindcss/oxide-wasm32-wasi": {
|
|
1472
|
-
"version": "4.3.
|
|
1473
|
-
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.
|
|
1474
|
-
"integrity": "sha512-
|
|
1472
|
+
"version": "4.3.3",
|
|
1473
|
+
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz",
|
|
1474
|
+
"integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==",
|
|
1475
1475
|
"bundleDependencies": [
|
|
1476
1476
|
"@napi-rs/wasm-runtime",
|
|
1477
1477
|
"@emnapi/core",
|
|
@@ -1558,9 +1558,9 @@
|
|
|
1558
1558
|
"optional": true
|
|
1559
1559
|
},
|
|
1560
1560
|
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
|
1561
|
-
"version": "4.3.
|
|
1562
|
-
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.
|
|
1563
|
-
"integrity": "sha512-
|
|
1561
|
+
"version": "4.3.3",
|
|
1562
|
+
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz",
|
|
1563
|
+
"integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==",
|
|
1564
1564
|
"cpu": [
|
|
1565
1565
|
"arm64"
|
|
1566
1566
|
],
|
|
@@ -1574,9 +1574,9 @@
|
|
|
1574
1574
|
}
|
|
1575
1575
|
},
|
|
1576
1576
|
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
|
|
1577
|
-
"version": "4.3.
|
|
1578
|
-
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.
|
|
1579
|
-
"integrity": "sha512-
|
|
1577
|
+
"version": "4.3.3",
|
|
1578
|
+
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz",
|
|
1579
|
+
"integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==",
|
|
1580
1580
|
"cpu": [
|
|
1581
1581
|
"x64"
|
|
1582
1582
|
],
|
|
@@ -1590,16 +1590,16 @@
|
|
|
1590
1590
|
}
|
|
1591
1591
|
},
|
|
1592
1592
|
"node_modules/@tailwindcss/postcss": {
|
|
1593
|
-
"version": "4.3.
|
|
1594
|
-
"resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.
|
|
1595
|
-
"integrity": "sha512-
|
|
1593
|
+
"version": "4.3.3",
|
|
1594
|
+
"resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.3.tgz",
|
|
1595
|
+
"integrity": "sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==",
|
|
1596
1596
|
"license": "MIT",
|
|
1597
1597
|
"dependencies": {
|
|
1598
1598
|
"@alloc/quick-lru": "^5.2.0",
|
|
1599
|
-
"@tailwindcss/node": "4.3.
|
|
1600
|
-
"@tailwindcss/oxide": "4.3.
|
|
1601
|
-
"postcss": "^8.5.
|
|
1602
|
-
"tailwindcss": "4.3.
|
|
1599
|
+
"@tailwindcss/node": "4.3.3",
|
|
1600
|
+
"@tailwindcss/oxide": "4.3.3",
|
|
1601
|
+
"postcss": "^8.5.16",
|
|
1602
|
+
"tailwindcss": "4.3.3"
|
|
1603
1603
|
}
|
|
1604
1604
|
},
|
|
1605
1605
|
"node_modules/@tailwindcss/typography": {
|
|
@@ -2113,9 +2113,9 @@
|
|
|
2113
2113
|
}
|
|
2114
2114
|
},
|
|
2115
2115
|
"node_modules/autoprefixer": {
|
|
2116
|
-
"version": "10.5.
|
|
2117
|
-
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.
|
|
2118
|
-
"integrity": "sha512-
|
|
2116
|
+
"version": "10.5.4",
|
|
2117
|
+
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.4.tgz",
|
|
2118
|
+
"integrity": "sha512-MaU0U/za7N3r6brxD4YB/l4NSrFzLPlANv6wEuQVaIPlD3L4W9rFcQPbL/EilY9BHhHvhfcz3gInDLrEtWT4EA==",
|
|
2119
2119
|
"funding": [
|
|
2120
2120
|
{
|
|
2121
2121
|
"type": "opencollective",
|
|
@@ -2133,7 +2133,7 @@
|
|
|
2133
2133
|
"license": "MIT",
|
|
2134
2134
|
"dependencies": {
|
|
2135
2135
|
"browserslist": "^4.28.6",
|
|
2136
|
-
"caniuse-lite": "^1.0.
|
|
2136
|
+
"caniuse-lite": "^1.0.30001806",
|
|
2137
2137
|
"fraction.js": "^5.3.4",
|
|
2138
2138
|
"picocolors": "^1.1.1",
|
|
2139
2139
|
"postcss-value-parser": "^4.2.0"
|
|
@@ -2231,9 +2231,9 @@
|
|
|
2231
2231
|
"license": "MIT"
|
|
2232
2232
|
},
|
|
2233
2233
|
"node_modules/caniuse-lite": {
|
|
2234
|
-
"version": "1.0.
|
|
2235
|
-
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.
|
|
2236
|
-
"integrity": "sha512-
|
|
2234
|
+
"version": "1.0.30001806",
|
|
2235
|
+
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz",
|
|
2236
|
+
"integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==",
|
|
2237
2237
|
"funding": [
|
|
2238
2238
|
{
|
|
2239
2239
|
"type": "opencollective",
|
|
@@ -2968,9 +2968,9 @@
|
|
|
2968
2968
|
"license": "ISC"
|
|
2969
2969
|
},
|
|
2970
2970
|
"node_modules/enhanced-resolve": {
|
|
2971
|
-
"version": "5.
|
|
2972
|
-
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.
|
|
2973
|
-
"integrity": "sha512-
|
|
2971
|
+
"version": "5.24.2",
|
|
2972
|
+
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.2.tgz",
|
|
2973
|
+
"integrity": "sha512-rpsZEGT1jFuve6QlpyRp9ckQ+kN61hvF9BzCPyMdaKTm8UJce96KBn3sorXOFXlzjPrs3Vc4T1NsSroZ3PxlFw==",
|
|
2974
2974
|
"license": "MIT",
|
|
2975
2975
|
"dependencies": {
|
|
2976
2976
|
"graceful-fs": "^4.2.4",
|
|
@@ -6292,9 +6292,9 @@
|
|
|
6292
6292
|
"license": "MIT"
|
|
6293
6293
|
},
|
|
6294
6294
|
"node_modules/tailwindcss": {
|
|
6295
|
-
"version": "4.3.
|
|
6296
|
-
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.
|
|
6297
|
-
"integrity": "sha512-
|
|
6295
|
+
"version": "4.3.3",
|
|
6296
|
+
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz",
|
|
6297
|
+
"integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==",
|
|
6298
6298
|
"license": "MIT"
|
|
6299
6299
|
},
|
|
6300
6300
|
"node_modules/tapable": {
|