@pos-360/horizon 0.1.0 → 0.2.1
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/dist/chunk-BWR6DSQJ.js +995 -0
- package/dist/chunk-BWR6DSQJ.js.map +1 -0
- package/dist/{chunk-7LVVOCBV.mjs → chunk-BYICEALC.mjs} +267 -33
- package/dist/chunk-BYICEALC.mjs.map +1 -0
- package/dist/{chunk-J6RXKZE5.js → chunk-FOXFMLET.js} +333 -89
- package/dist/chunk-FOXFMLET.js.map +1 -0
- package/dist/chunk-TDRL2RCT.mjs +10 -0
- package/dist/chunk-TDRL2RCT.mjs.map +1 -0
- package/dist/chunk-TMZLQK74.js +12 -0
- package/dist/chunk-TMZLQK74.js.map +1 -0
- package/dist/{chunk-6YAK6HNR.mjs → chunk-TQPMV72P.mjs} +481 -5
- package/dist/chunk-TQPMV72P.mjs.map +1 -0
- package/dist/enhanced.d.mts +29 -1
- package/dist/enhanced.d.ts +29 -1
- package/dist/enhanced.js +34 -5
- package/dist/enhanced.mjs +2 -1
- package/dist/index.d.mts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +152 -83
- package/dist/index.mjs +3 -2
- package/dist/primitives.d.mts +62 -10
- package/dist/primitives.d.ts +62 -10
- package/dist/primitives.js +117 -76
- package/dist/primitives.mjs +2 -1
- package/package.json +17 -11
- package/tailwind.config.js +1 -0
- package/dist/chunk-6YAK6HNR.mjs.map +0 -1
- package/dist/chunk-7LVVOCBV.mjs.map +0 -1
- package/dist/chunk-J6RXKZE5.js.map +0 -1
- package/dist/chunk-ZD6CMWPW.js +0 -476
- package/dist/chunk-ZD6CMWPW.js.map +0 -1
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { cn } from './chunk-TDRL2RCT.mjs';
|
|
2
|
+
import { motion, AnimatePresence } from 'framer-motion';
|
|
2
3
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
import * as React from 'react';
|
|
3
5
|
import { forwardRef, useState, useEffect } from 'react';
|
|
4
|
-
import { Info, ChevronDown, ChevronUp, Check, AlertTriangle, X } from 'lucide-react';
|
|
6
|
+
import { Info, ChevronDown, ChevronUp, LayoutGrid, List, Check, ExternalLink, AlertTriangle, X, Moon, Rocket, Star, Globe, Orbit, Sparkles } from 'lucide-react';
|
|
7
|
+
export { Globe, Moon, Orbit, Rocket, Sparkles, Star } from 'lucide-react';
|
|
5
8
|
|
|
6
9
|
var AnimatedButton = ({
|
|
7
10
|
label,
|
|
@@ -340,6 +343,479 @@ var Input = forwardRef(
|
|
|
340
343
|
}
|
|
341
344
|
);
|
|
342
345
|
Input.displayName = "Input";
|
|
346
|
+
var accentColors = {
|
|
347
|
+
blue: {
|
|
348
|
+
selected: "bg-blue-100/80 dark:bg-blue-900/30",
|
|
349
|
+
selectedBorder: "border-blue-500 dark:border-blue-400",
|
|
350
|
+
selectedGlow: "shadow-lg shadow-blue-500/20 dark:shadow-blue-400/20",
|
|
351
|
+
hoverBg: "group-hover:bg-blue-50/60 dark:group-hover:bg-blue-900/20",
|
|
352
|
+
hoverBgDark: "hover:bg-blue-50 dark:hover:bg-blue-900/30",
|
|
353
|
+
iconSelected: "text-blue-600 dark:text-blue-400",
|
|
354
|
+
iconHover: "group-hover:text-blue-500 dark:group-hover:text-blue-400",
|
|
355
|
+
checkBg: "bg-blue-500 border-blue-500 dark:bg-blue-400 dark:border-blue-400",
|
|
356
|
+
inputBorder: "border-blue-500 dark:border-blue-400",
|
|
357
|
+
inputRing: "focus:ring-blue-500/20",
|
|
358
|
+
textHover: "hover:text-blue-600 dark:hover:text-blue-400",
|
|
359
|
+
toggleActive: "text-blue-600 dark:text-blue-400"
|
|
360
|
+
},
|
|
361
|
+
violet: {
|
|
362
|
+
selected: "bg-violet-100/80 dark:bg-violet-900/30",
|
|
363
|
+
selectedBorder: "border-violet-500 dark:border-violet-400",
|
|
364
|
+
selectedGlow: "shadow-lg shadow-violet-500/20 dark:shadow-violet-400/20",
|
|
365
|
+
hoverBg: "group-hover:bg-violet-50/60 dark:group-hover:bg-violet-900/20",
|
|
366
|
+
hoverBgDark: "hover:bg-violet-50 dark:hover:bg-violet-900/30",
|
|
367
|
+
iconSelected: "text-violet-600 dark:text-violet-400",
|
|
368
|
+
iconHover: "group-hover:text-violet-500 dark:group-hover:text-violet-400",
|
|
369
|
+
checkBg: "bg-violet-500 border-violet-500 dark:bg-violet-400 dark:border-violet-400",
|
|
370
|
+
inputBorder: "border-violet-500 dark:border-violet-400",
|
|
371
|
+
inputRing: "focus:ring-violet-500/20",
|
|
372
|
+
textHover: "hover:text-violet-600 dark:hover:text-violet-400",
|
|
373
|
+
toggleActive: "text-violet-600 dark:text-violet-400"
|
|
374
|
+
},
|
|
375
|
+
emerald: {
|
|
376
|
+
selected: "bg-emerald-100/80 dark:bg-emerald-900/30",
|
|
377
|
+
selectedBorder: "border-emerald-500 dark:border-emerald-400",
|
|
378
|
+
selectedGlow: "shadow-lg shadow-emerald-500/20 dark:shadow-emerald-400/20",
|
|
379
|
+
hoverBg: "group-hover:bg-emerald-50/60 dark:group-hover:bg-emerald-900/20",
|
|
380
|
+
hoverBgDark: "hover:bg-emerald-50 dark:hover:bg-emerald-900/30",
|
|
381
|
+
iconSelected: "text-emerald-600 dark:text-emerald-400",
|
|
382
|
+
iconHover: "group-hover:text-emerald-500 dark:group-hover:text-emerald-400",
|
|
383
|
+
checkBg: "bg-emerald-500 border-emerald-500 dark:bg-emerald-400 dark:border-emerald-400",
|
|
384
|
+
inputBorder: "border-emerald-500 dark:border-emerald-400",
|
|
385
|
+
inputRing: "focus:ring-emerald-500/20",
|
|
386
|
+
textHover: "hover:text-emerald-600 dark:hover:text-emerald-400",
|
|
387
|
+
toggleActive: "text-emerald-600 dark:text-emerald-400"
|
|
388
|
+
},
|
|
389
|
+
rose: {
|
|
390
|
+
selected: "bg-rose-100/80 dark:bg-rose-900/30",
|
|
391
|
+
selectedBorder: "border-rose-500 dark:border-rose-400",
|
|
392
|
+
selectedGlow: "shadow-lg shadow-rose-500/20 dark:shadow-rose-400/20",
|
|
393
|
+
hoverBg: "group-hover:bg-rose-50/60 dark:group-hover:bg-rose-900/20",
|
|
394
|
+
hoverBgDark: "hover:bg-rose-50 dark:hover:bg-rose-900/30",
|
|
395
|
+
iconSelected: "text-rose-600 dark:text-rose-400",
|
|
396
|
+
iconHover: "group-hover:text-rose-500 dark:group-hover:text-rose-400",
|
|
397
|
+
checkBg: "bg-rose-500 border-rose-500 dark:bg-rose-400 dark:border-rose-400",
|
|
398
|
+
inputBorder: "border-rose-500 dark:border-rose-400",
|
|
399
|
+
inputRing: "focus:ring-rose-500/20",
|
|
400
|
+
textHover: "hover:text-rose-600 dark:hover:text-rose-400",
|
|
401
|
+
toggleActive: "text-rose-600 dark:text-rose-400"
|
|
402
|
+
},
|
|
403
|
+
amber: {
|
|
404
|
+
selected: "bg-amber-100/80 dark:bg-amber-900/30",
|
|
405
|
+
selectedBorder: "border-amber-500 dark:border-amber-400",
|
|
406
|
+
selectedGlow: "shadow-lg shadow-amber-500/20 dark:shadow-amber-400/20",
|
|
407
|
+
hoverBg: "group-hover:bg-amber-50/60 dark:group-hover:bg-amber-900/20",
|
|
408
|
+
hoverBgDark: "hover:bg-amber-50 dark:hover:bg-amber-900/30",
|
|
409
|
+
iconSelected: "text-amber-600 dark:text-amber-400",
|
|
410
|
+
iconHover: "group-hover:text-amber-500 dark:group-hover:text-amber-400",
|
|
411
|
+
checkBg: "bg-amber-500 border-amber-500 dark:bg-amber-400 dark:border-amber-400",
|
|
412
|
+
inputBorder: "border-amber-500 dark:border-amber-400",
|
|
413
|
+
inputRing: "focus:ring-amber-500/20",
|
|
414
|
+
textHover: "hover:text-amber-600 dark:hover:text-amber-400",
|
|
415
|
+
toggleActive: "text-amber-600 dark:text-amber-400"
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
var defaultIconMap = {
|
|
419
|
+
nebula: Sparkles,
|
|
420
|
+
andromeda: Orbit,
|
|
421
|
+
cosmos: Globe,
|
|
422
|
+
stellar: Star,
|
|
423
|
+
voyager: Rocket,
|
|
424
|
+
eclipse: Moon
|
|
425
|
+
};
|
|
426
|
+
var getTemplateIcon = (template) => {
|
|
427
|
+
if (template.icon) return template.icon;
|
|
428
|
+
const key = template.title.toLowerCase();
|
|
429
|
+
return defaultIconMap[key] || Star;
|
|
430
|
+
};
|
|
431
|
+
var TemplateSelector = ({
|
|
432
|
+
templates,
|
|
433
|
+
value,
|
|
434
|
+
onChange,
|
|
435
|
+
onNameChange,
|
|
436
|
+
defaultView = "card",
|
|
437
|
+
showViewToggle = true,
|
|
438
|
+
editable = false,
|
|
439
|
+
className,
|
|
440
|
+
cardClassName,
|
|
441
|
+
columns = 3,
|
|
442
|
+
accentColor = "blue"
|
|
443
|
+
}) => {
|
|
444
|
+
const colors = accentColors[accentColor];
|
|
445
|
+
const [view, setView] = useState(defaultView);
|
|
446
|
+
const [selectedId, setSelectedId] = useState(value);
|
|
447
|
+
React.useEffect(() => {
|
|
448
|
+
setSelectedId(value);
|
|
449
|
+
}, [value]);
|
|
450
|
+
const handleSelect = (templateId) => {
|
|
451
|
+
setSelectedId(templateId);
|
|
452
|
+
onChange?.(templateId);
|
|
453
|
+
};
|
|
454
|
+
const handlePreviewClick = (e, previewUrl) => {
|
|
455
|
+
e.stopPropagation();
|
|
456
|
+
window.open(previewUrl, "_blank", "noopener,noreferrer");
|
|
457
|
+
};
|
|
458
|
+
const handleNameChange = (templateId, newName) => {
|
|
459
|
+
onNameChange?.(templateId, newName);
|
|
460
|
+
};
|
|
461
|
+
const columnClasses = {
|
|
462
|
+
2: "grid-cols-1 sm:grid-cols-2",
|
|
463
|
+
3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
|
|
464
|
+
4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
|
|
465
|
+
};
|
|
466
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("w-full", className), children: [
|
|
467
|
+
showViewToggle && /* @__PURE__ */ jsx("div", { className: "flex justify-end mb-4", children: /* @__PURE__ */ jsxs("div", { className: "inline-flex rounded-lg border border-neutral-200 dark:border-neutral-700 p-1 bg-neutral-100 dark:bg-neutral-800", children: [
|
|
468
|
+
/* @__PURE__ */ jsx(
|
|
469
|
+
"button",
|
|
470
|
+
{
|
|
471
|
+
type: "button",
|
|
472
|
+
onClick: () => setView("card"),
|
|
473
|
+
className: cn(
|
|
474
|
+
"p-2 rounded-md text-sm font-medium transition-all duration-200",
|
|
475
|
+
view === "card" ? `bg-white dark:bg-neutral-700 shadow-sm ${colors.toggleActive}` : "text-neutral-500 dark:text-neutral-400 hover:text-neutral-700 dark:hover:text-neutral-300"
|
|
476
|
+
),
|
|
477
|
+
"aria-label": "Card view",
|
|
478
|
+
children: /* @__PURE__ */ jsx(LayoutGrid, { size: 16 })
|
|
479
|
+
}
|
|
480
|
+
),
|
|
481
|
+
/* @__PURE__ */ jsx(
|
|
482
|
+
"button",
|
|
483
|
+
{
|
|
484
|
+
type: "button",
|
|
485
|
+
onClick: () => setView("list"),
|
|
486
|
+
className: cn(
|
|
487
|
+
"p-2 rounded-md text-sm font-medium transition-all duration-200",
|
|
488
|
+
view === "list" ? `bg-white dark:bg-neutral-700 shadow-sm ${colors.toggleActive}` : "text-neutral-500 dark:text-neutral-400 hover:text-neutral-700 dark:hover:text-neutral-300"
|
|
489
|
+
),
|
|
490
|
+
"aria-label": "List view",
|
|
491
|
+
children: /* @__PURE__ */ jsx(List, { size: 16 })
|
|
492
|
+
}
|
|
493
|
+
)
|
|
494
|
+
] }) }),
|
|
495
|
+
/* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: view === "card" ? /* @__PURE__ */ jsx(
|
|
496
|
+
motion.div,
|
|
497
|
+
{
|
|
498
|
+
initial: { opacity: 0, y: 10 },
|
|
499
|
+
animate: { opacity: 1, y: 0 },
|
|
500
|
+
exit: { opacity: 0, y: -10 },
|
|
501
|
+
transition: { duration: 0.2 },
|
|
502
|
+
className: cn("grid gap-4", columnClasses[columns]),
|
|
503
|
+
children: templates.map((template) => /* @__PURE__ */ jsx(
|
|
504
|
+
TemplateCard,
|
|
505
|
+
{
|
|
506
|
+
template,
|
|
507
|
+
isSelected: selectedId === template.id,
|
|
508
|
+
onSelect: handleSelect,
|
|
509
|
+
onPreviewClick: handlePreviewClick,
|
|
510
|
+
onNameChange: handleNameChange,
|
|
511
|
+
editable,
|
|
512
|
+
className: cardClassName,
|
|
513
|
+
colors
|
|
514
|
+
},
|
|
515
|
+
template.id
|
|
516
|
+
))
|
|
517
|
+
},
|
|
518
|
+
"card-view"
|
|
519
|
+
) : /* @__PURE__ */ jsx(
|
|
520
|
+
motion.div,
|
|
521
|
+
{
|
|
522
|
+
initial: { opacity: 0, y: 10 },
|
|
523
|
+
animate: { opacity: 1, y: 0 },
|
|
524
|
+
exit: { opacity: 0, y: -10 },
|
|
525
|
+
transition: { duration: 0.2 },
|
|
526
|
+
className: "flex flex-col gap-2",
|
|
527
|
+
children: templates.map((template) => /* @__PURE__ */ jsx(
|
|
528
|
+
TemplateListItem,
|
|
529
|
+
{
|
|
530
|
+
template,
|
|
531
|
+
isSelected: selectedId === template.id,
|
|
532
|
+
onSelect: handleSelect,
|
|
533
|
+
onPreviewClick: handlePreviewClick,
|
|
534
|
+
onNameChange: handleNameChange,
|
|
535
|
+
editable,
|
|
536
|
+
colors
|
|
537
|
+
},
|
|
538
|
+
template.id
|
|
539
|
+
))
|
|
540
|
+
},
|
|
541
|
+
"list-view"
|
|
542
|
+
) })
|
|
543
|
+
] });
|
|
544
|
+
};
|
|
545
|
+
var TemplateCard = ({
|
|
546
|
+
template,
|
|
547
|
+
isSelected,
|
|
548
|
+
onSelect,
|
|
549
|
+
onPreviewClick,
|
|
550
|
+
onNameChange,
|
|
551
|
+
editable,
|
|
552
|
+
className,
|
|
553
|
+
colors
|
|
554
|
+
}) => {
|
|
555
|
+
const [isEditing, setIsEditing] = useState(false);
|
|
556
|
+
const [editValue, setEditValue] = useState(template.name || template.title);
|
|
557
|
+
const inputRef = React.useRef(null);
|
|
558
|
+
const displayName = template.name || template.title;
|
|
559
|
+
const IconComponent = getTemplateIcon(template);
|
|
560
|
+
const handleDoubleClick = (e) => {
|
|
561
|
+
if (editable) {
|
|
562
|
+
e.stopPropagation();
|
|
563
|
+
setIsEditing(true);
|
|
564
|
+
setEditValue(displayName);
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
const handleBlur = () => {
|
|
568
|
+
setIsEditing(false);
|
|
569
|
+
if (editValue.trim() && editValue !== displayName) {
|
|
570
|
+
onNameChange(template.id, editValue.trim());
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
const handleKeyDown = (e) => {
|
|
574
|
+
if (e.key === "Enter") {
|
|
575
|
+
handleBlur();
|
|
576
|
+
} else if (e.key === "Escape") {
|
|
577
|
+
setIsEditing(false);
|
|
578
|
+
setEditValue(displayName);
|
|
579
|
+
}
|
|
580
|
+
};
|
|
581
|
+
React.useEffect(() => {
|
|
582
|
+
if (isEditing && inputRef.current) {
|
|
583
|
+
inputRef.current.focus();
|
|
584
|
+
inputRef.current.select();
|
|
585
|
+
}
|
|
586
|
+
}, [isEditing]);
|
|
587
|
+
return /* @__PURE__ */ jsxs(
|
|
588
|
+
motion.div,
|
|
589
|
+
{
|
|
590
|
+
whileHover: { y: -4, scale: 1.02 },
|
|
591
|
+
whileTap: { scale: 0.98 },
|
|
592
|
+
transition: { type: "spring", stiffness: 400, damping: 25 },
|
|
593
|
+
onClick: () => onSelect(template.id),
|
|
594
|
+
className: cn(
|
|
595
|
+
"group relative cursor-pointer rounded-xl overflow-hidden border-2 transition-all duration-300",
|
|
596
|
+
"bg-white dark:bg-neutral-800",
|
|
597
|
+
isSelected ? `${colors.selectedBorder} ${colors.selectedGlow}` : "border-neutral-200 dark:border-neutral-700 hover:border-neutral-300 dark:hover:border-neutral-600 hover:shadow-md",
|
|
598
|
+
className
|
|
599
|
+
),
|
|
600
|
+
children: [
|
|
601
|
+
/* @__PURE__ */ jsx(
|
|
602
|
+
"div",
|
|
603
|
+
{
|
|
604
|
+
className: cn(
|
|
605
|
+
"absolute top-3 left-3 z-10 w-5 h-5 rounded-full border-2 flex items-center justify-center transition-all duration-200",
|
|
606
|
+
isSelected ? colors.checkBg : "bg-white dark:bg-neutral-800 border-neutral-300 dark:border-neutral-600"
|
|
607
|
+
),
|
|
608
|
+
children: isSelected && /* @__PURE__ */ jsx(Check, { size: 12, className: "text-white", strokeWidth: 3 })
|
|
609
|
+
}
|
|
610
|
+
),
|
|
611
|
+
/* @__PURE__ */ jsx(
|
|
612
|
+
"button",
|
|
613
|
+
{
|
|
614
|
+
type: "button",
|
|
615
|
+
onClick: (e) => onPreviewClick(e, template.previewUrl),
|
|
616
|
+
className: cn(
|
|
617
|
+
"absolute top-3 right-3 z-10 p-1.5 rounded-lg transition-all duration-200",
|
|
618
|
+
"bg-white dark:bg-neutral-700",
|
|
619
|
+
"border border-neutral-200 dark:border-neutral-600",
|
|
620
|
+
"text-neutral-500 dark:text-neutral-400",
|
|
621
|
+
"opacity-0 group-hover:opacity-100",
|
|
622
|
+
"hover:bg-blue-50 dark:hover:bg-blue-900/30 hover:text-blue-600 dark:hover:text-blue-400 hover:border-blue-300 dark:hover:border-blue-600"
|
|
623
|
+
),
|
|
624
|
+
"aria-label": `Preview ${displayName}`,
|
|
625
|
+
children: /* @__PURE__ */ jsx(ExternalLink, { size: 14 })
|
|
626
|
+
}
|
|
627
|
+
),
|
|
628
|
+
/* @__PURE__ */ jsx("div", { className: "aspect-[4/3] overflow-hidden bg-neutral-50 dark:bg-neutral-800/80 flex items-center justify-center", children: /* @__PURE__ */ jsx(
|
|
629
|
+
motion.div,
|
|
630
|
+
{
|
|
631
|
+
initial: { scale: 0.9, opacity: 0.5 },
|
|
632
|
+
animate: { scale: 1, opacity: 1 },
|
|
633
|
+
className: cn(
|
|
634
|
+
"p-6 rounded-full transition-all duration-300",
|
|
635
|
+
isSelected ? colors.selected : `bg-neutral-100 dark:bg-neutral-700/50 ${colors.hoverBg}`
|
|
636
|
+
),
|
|
637
|
+
children: /* @__PURE__ */ jsx(
|
|
638
|
+
IconComponent,
|
|
639
|
+
{
|
|
640
|
+
size: 48,
|
|
641
|
+
strokeWidth: 1.5,
|
|
642
|
+
className: cn(
|
|
643
|
+
"transition-colors duration-300",
|
|
644
|
+
isSelected ? colors.iconSelected : `text-neutral-400 dark:text-neutral-500 ${colors.iconHover}`
|
|
645
|
+
)
|
|
646
|
+
}
|
|
647
|
+
)
|
|
648
|
+
}
|
|
649
|
+
) }),
|
|
650
|
+
/* @__PURE__ */ jsx("div", { className: "p-3 border-t border-neutral-100 dark:border-neutral-700", children: isEditing ? /* @__PURE__ */ jsx(
|
|
651
|
+
"input",
|
|
652
|
+
{
|
|
653
|
+
ref: inputRef,
|
|
654
|
+
type: "text",
|
|
655
|
+
value: editValue,
|
|
656
|
+
onChange: (e) => setEditValue(e.target.value),
|
|
657
|
+
onBlur: handleBlur,
|
|
658
|
+
onKeyDown: handleKeyDown,
|
|
659
|
+
onClick: (e) => e.stopPropagation(),
|
|
660
|
+
className: cn(
|
|
661
|
+
"w-full px-2 py-1 text-sm font-medium rounded",
|
|
662
|
+
"bg-neutral-100 dark:bg-neutral-700",
|
|
663
|
+
`border ${colors.inputBorder}`,
|
|
664
|
+
"text-neutral-900 dark:text-neutral-100",
|
|
665
|
+
`focus:outline-none focus:ring-2 ${colors.inputRing}`
|
|
666
|
+
)
|
|
667
|
+
}
|
|
668
|
+
) : /* @__PURE__ */ jsx(
|
|
669
|
+
"h3",
|
|
670
|
+
{
|
|
671
|
+
onDoubleClick: handleDoubleClick,
|
|
672
|
+
className: cn(
|
|
673
|
+
"text-sm font-medium text-neutral-900 dark:text-neutral-100 truncate",
|
|
674
|
+
editable && `cursor-text ${colors.textHover}`
|
|
675
|
+
),
|
|
676
|
+
title: editable ? "Double-click to rename" : displayName,
|
|
677
|
+
children: displayName
|
|
678
|
+
}
|
|
679
|
+
) })
|
|
680
|
+
]
|
|
681
|
+
}
|
|
682
|
+
);
|
|
683
|
+
};
|
|
684
|
+
var TemplateListItem = ({
|
|
685
|
+
template,
|
|
686
|
+
isSelected,
|
|
687
|
+
onSelect,
|
|
688
|
+
onPreviewClick,
|
|
689
|
+
onNameChange,
|
|
690
|
+
editable,
|
|
691
|
+
colors
|
|
692
|
+
}) => {
|
|
693
|
+
const [isEditing, setIsEditing] = useState(false);
|
|
694
|
+
const [editValue, setEditValue] = useState(template.name || template.title);
|
|
695
|
+
const inputRef = React.useRef(null);
|
|
696
|
+
const displayName = template.name || template.title;
|
|
697
|
+
const IconComponent = getTemplateIcon(template);
|
|
698
|
+
const handleDoubleClick = (e) => {
|
|
699
|
+
if (editable) {
|
|
700
|
+
e.stopPropagation();
|
|
701
|
+
setIsEditing(true);
|
|
702
|
+
setEditValue(displayName);
|
|
703
|
+
}
|
|
704
|
+
};
|
|
705
|
+
const handleBlur = () => {
|
|
706
|
+
setIsEditing(false);
|
|
707
|
+
if (editValue.trim() && editValue !== displayName) {
|
|
708
|
+
onNameChange(template.id, editValue.trim());
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
const handleKeyDown = (e) => {
|
|
712
|
+
if (e.key === "Enter") {
|
|
713
|
+
handleBlur();
|
|
714
|
+
} else if (e.key === "Escape") {
|
|
715
|
+
setIsEditing(false);
|
|
716
|
+
setEditValue(displayName);
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
React.useEffect(() => {
|
|
720
|
+
if (isEditing && inputRef.current) {
|
|
721
|
+
inputRef.current.focus();
|
|
722
|
+
inputRef.current.select();
|
|
723
|
+
}
|
|
724
|
+
}, [isEditing]);
|
|
725
|
+
return /* @__PURE__ */ jsxs(
|
|
726
|
+
motion.div,
|
|
727
|
+
{
|
|
728
|
+
whileHover: { x: 4, scale: 1.01 },
|
|
729
|
+
whileTap: { scale: 0.995 },
|
|
730
|
+
transition: { type: "spring", stiffness: 400, damping: 25 },
|
|
731
|
+
onClick: () => onSelect(template.id),
|
|
732
|
+
className: cn(
|
|
733
|
+
"group flex items-center gap-4 p-3 cursor-pointer rounded-xl border-2 transition-all duration-300",
|
|
734
|
+
"bg-white dark:bg-neutral-800",
|
|
735
|
+
isSelected ? `${colors.selectedBorder} shadow-md ${colors.selectedGlow}` : "border-neutral-200 dark:border-neutral-700 hover:border-neutral-300 dark:hover:border-neutral-600"
|
|
736
|
+
),
|
|
737
|
+
children: [
|
|
738
|
+
/* @__PURE__ */ jsx(
|
|
739
|
+
"div",
|
|
740
|
+
{
|
|
741
|
+
className: cn(
|
|
742
|
+
"w-5 h-5 rounded-full border-2 flex items-center justify-center flex-shrink-0 transition-all duration-200",
|
|
743
|
+
isSelected ? colors.checkBg : "bg-white dark:bg-neutral-800 border-neutral-300 dark:border-neutral-600"
|
|
744
|
+
),
|
|
745
|
+
children: isSelected && /* @__PURE__ */ jsx(Check, { size: 12, className: "text-white", strokeWidth: 3 })
|
|
746
|
+
}
|
|
747
|
+
),
|
|
748
|
+
/* @__PURE__ */ jsx(
|
|
749
|
+
"div",
|
|
750
|
+
{
|
|
751
|
+
className: cn(
|
|
752
|
+
"w-12 h-12 rounded-lg flex items-center justify-center flex-shrink-0 transition-colors duration-300",
|
|
753
|
+
isSelected ? colors.selected : `bg-neutral-100 dark:bg-neutral-700/50 ${colors.hoverBg}`
|
|
754
|
+
),
|
|
755
|
+
children: /* @__PURE__ */ jsx(
|
|
756
|
+
IconComponent,
|
|
757
|
+
{
|
|
758
|
+
size: 24,
|
|
759
|
+
strokeWidth: 1.5,
|
|
760
|
+
className: cn(
|
|
761
|
+
"transition-colors duration-300",
|
|
762
|
+
isSelected ? colors.iconSelected : `text-neutral-400 dark:text-neutral-500 ${colors.iconHover}`
|
|
763
|
+
)
|
|
764
|
+
}
|
|
765
|
+
)
|
|
766
|
+
}
|
|
767
|
+
),
|
|
768
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: isEditing ? /* @__PURE__ */ jsx(
|
|
769
|
+
"input",
|
|
770
|
+
{
|
|
771
|
+
ref: inputRef,
|
|
772
|
+
type: "text",
|
|
773
|
+
value: editValue,
|
|
774
|
+
onChange: (e) => setEditValue(e.target.value),
|
|
775
|
+
onBlur: handleBlur,
|
|
776
|
+
onKeyDown: handleKeyDown,
|
|
777
|
+
onClick: (e) => e.stopPropagation(),
|
|
778
|
+
className: cn(
|
|
779
|
+
"w-full px-2 py-1 text-sm font-medium rounded",
|
|
780
|
+
"bg-neutral-100 dark:bg-neutral-700",
|
|
781
|
+
`border ${colors.inputBorder}`,
|
|
782
|
+
"text-neutral-900 dark:text-neutral-100",
|
|
783
|
+
`focus:outline-none focus:ring-2 ${colors.inputRing}`
|
|
784
|
+
)
|
|
785
|
+
}
|
|
786
|
+
) : /* @__PURE__ */ jsx(
|
|
787
|
+
"h3",
|
|
788
|
+
{
|
|
789
|
+
onDoubleClick: handleDoubleClick,
|
|
790
|
+
className: cn(
|
|
791
|
+
"text-sm font-medium text-neutral-900 dark:text-neutral-100 truncate",
|
|
792
|
+
editable && `cursor-text ${colors.textHover}`
|
|
793
|
+
),
|
|
794
|
+
title: editable ? "Double-click to rename" : displayName,
|
|
795
|
+
children: displayName
|
|
796
|
+
}
|
|
797
|
+
) }),
|
|
798
|
+
/* @__PURE__ */ jsx(
|
|
799
|
+
"button",
|
|
800
|
+
{
|
|
801
|
+
type: "button",
|
|
802
|
+
onClick: (e) => onPreviewClick(e, template.previewUrl),
|
|
803
|
+
className: cn(
|
|
804
|
+
"p-2 rounded-lg transition-all duration-200 flex-shrink-0",
|
|
805
|
+
"text-neutral-400 dark:text-neutral-500",
|
|
806
|
+
"opacity-0 group-hover:opacity-100",
|
|
807
|
+
colors.hoverBgDark,
|
|
808
|
+
colors.textHover
|
|
809
|
+
),
|
|
810
|
+
"aria-label": `Preview ${displayName}`,
|
|
811
|
+
children: /* @__PURE__ */ jsx(ExternalLink, { size: 16 })
|
|
812
|
+
}
|
|
813
|
+
)
|
|
814
|
+
]
|
|
815
|
+
}
|
|
816
|
+
);
|
|
817
|
+
};
|
|
818
|
+
TemplateSelector.displayName = "TemplateSelector";
|
|
343
819
|
var TextButton = ({
|
|
344
820
|
children,
|
|
345
821
|
onClick,
|
|
@@ -466,6 +942,6 @@ var Toast = ({
|
|
|
466
942
|
);
|
|
467
943
|
};
|
|
468
944
|
|
|
469
|
-
export { AnimatedButton, Input, TextButton, Toast };
|
|
470
|
-
//# sourceMappingURL=chunk-
|
|
471
|
-
//# sourceMappingURL=chunk-
|
|
945
|
+
export { AnimatedButton, Input, TemplateSelector, TextButton, Toast };
|
|
946
|
+
//# sourceMappingURL=chunk-TQPMV72P.mjs.map
|
|
947
|
+
//# sourceMappingURL=chunk-TQPMV72P.mjs.map
|