@copilotz/chat-ui 0.9.3 → 0.9.4

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/index.cjs CHANGED
@@ -2466,14 +2466,6 @@ var ThreadInitialsIcon = ({ title }) => {
2466
2466
  const initials = title?.split(" ").map((n) => n[0]).slice(0, 2).join("").toUpperCase() || "?";
2467
2467
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex h-5 w-5 shrink-0 items-center justify-center rounded bg-muted text-[10px] font-medium text-muted-foreground", children: initials });
2468
2468
  };
2469
- var TAG_COLOR_CLASSES = [
2470
- "bg-sky-500",
2471
- "bg-emerald-500",
2472
- "bg-violet-500",
2473
- "bg-amber-500",
2474
- "bg-rose-500",
2475
- "bg-cyan-500"
2476
- ];
2477
2469
  function slugTagName(name) {
2478
2470
  const slug = name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
2479
2471
  return slug || "tag";
@@ -2505,31 +2497,125 @@ function collectThreadTags(threads) {
2505
2497
  }
2506
2498
  return tags.sort((a, b) => a.name.localeCompare(b.name));
2507
2499
  }
2508
- function tagColorIndex(tag) {
2500
+ function normalizeTagColorKey(tag) {
2501
+ return (tag.name || tag.id || "tag").trim().toLowerCase().normalize("NFKD").replace(/[\u0300-\u036f]/g, "");
2502
+ }
2503
+ function hashTagColorKey(value) {
2509
2504
  let hash = 0;
2510
- for (const char of tag.id || tag.name) {
2505
+ for (const char of value) {
2511
2506
  hash = hash * 31 + char.charCodeAt(0) >>> 0;
2512
2507
  }
2513
- return hash % TAG_COLOR_CLASSES.length;
2508
+ return hash;
2514
2509
  }
2515
- var TagDot = ({ tag }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2516
- "span",
2517
- {
2518
- "aria-hidden": "true",
2519
- className: `h-2 w-2 shrink-0 rounded-full ${TAG_COLOR_CLASSES[tagColorIndex(tag)]}`
2510
+ function hslToRgb(hue, saturation, lightness) {
2511
+ const chroma = (1 - Math.abs(2 * lightness - 1)) * saturation;
2512
+ const x = chroma * (1 - Math.abs(hue / 60 % 2 - 1));
2513
+ const match = lightness - chroma / 2;
2514
+ let red = 0;
2515
+ let green = 0;
2516
+ let blue = 0;
2517
+ if (hue < 60) {
2518
+ red = chroma;
2519
+ green = x;
2520
+ } else if (hue < 120) {
2521
+ red = x;
2522
+ green = chroma;
2523
+ } else if (hue < 180) {
2524
+ green = chroma;
2525
+ blue = x;
2526
+ } else if (hue < 240) {
2527
+ green = x;
2528
+ blue = chroma;
2529
+ } else if (hue < 300) {
2530
+ red = x;
2531
+ blue = chroma;
2532
+ } else {
2533
+ red = chroma;
2534
+ blue = x;
2520
2535
  }
2521
- );
2522
- var ThreadTagBadge = ({ tag }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
2523
- Badge,
2524
- {
2525
- variant: "secondary",
2526
- className: "h-4 max-w-24 gap-1 rounded px-1.5 py-0 text-[10px] font-normal text-muted-foreground",
2527
- children: [
2528
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TagDot, { tag }),
2529
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "truncate", children: tag.name })
2530
- ]
2536
+ return {
2537
+ red: Math.round((red + match) * 255),
2538
+ green: Math.round((green + match) * 255),
2539
+ blue: Math.round((blue + match) * 255)
2540
+ };
2541
+ }
2542
+ function tagColor(tag) {
2543
+ if (tag.color) {
2544
+ return {
2545
+ accent: tag.color,
2546
+ background: `color-mix(in srgb, ${tag.color} 12%, transparent)`,
2547
+ border: `color-mix(in srgb, ${tag.color} 24%, transparent)`
2548
+ };
2531
2549
  }
2532
- );
2550
+ const hue = hashTagColorKey(normalizeTagColorKey(tag)) % 360;
2551
+ const { red, green, blue } = hslToRgb(hue, 0.68, 0.48);
2552
+ return {
2553
+ accent: `rgb(${red} ${green} ${blue})`,
2554
+ background: `rgb(${red} ${green} ${blue} / 0.12)`,
2555
+ border: `rgb(${red} ${green} ${blue} / 0.24)`
2556
+ };
2557
+ }
2558
+ var TagDot = ({ tag }) => {
2559
+ const color = tagColor(tag);
2560
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2561
+ "span",
2562
+ {
2563
+ "aria-hidden": "true",
2564
+ className: "h-2 w-2 shrink-0 rounded-full",
2565
+ style: { backgroundColor: color.accent }
2566
+ }
2567
+ );
2568
+ };
2569
+ var ThreadTagBadge = ({ tag }) => {
2570
+ const color = tagColor(tag);
2571
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
2572
+ Badge,
2573
+ {
2574
+ variant: "secondary",
2575
+ className: "h-4 max-w-24 gap-1 rounded border px-1.5 py-0 text-[10px] font-normal text-muted-foreground",
2576
+ style: {
2577
+ backgroundColor: color.background,
2578
+ borderColor: color.border
2579
+ },
2580
+ children: [
2581
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TagDot, { tag }),
2582
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "truncate", children: tag.name })
2583
+ ]
2584
+ }
2585
+ );
2586
+ };
2587
+ var ThreadTagEditorBadge = ({
2588
+ tag,
2589
+ removeLabel,
2590
+ onRemove
2591
+ }) => {
2592
+ const color = tagColor(tag);
2593
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
2594
+ Badge,
2595
+ {
2596
+ variant: "secondary",
2597
+ className: "gap-1 rounded-md border py-1 text-sm font-normal",
2598
+ style: {
2599
+ backgroundColor: color.background,
2600
+ borderColor: color.border
2601
+ },
2602
+ children: [
2603
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TagDot, { tag }),
2604
+ tag.name,
2605
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2606
+ "button",
2607
+ {
2608
+ type: "button",
2609
+ className: "rounded-sm hover:bg-background/80",
2610
+ onClick: onRemove,
2611
+ "aria-label": removeLabel,
2612
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.X, { className: "h-3 w-3" })
2613
+ }
2614
+ )
2615
+ ]
2616
+ }
2617
+ );
2618
+ };
2533
2619
  var Sidebar2 = ({
2534
2620
  threads,
2535
2621
  currentThreadId,
@@ -2996,25 +3082,12 @@ var Sidebar2 = ({
2996
3082
  /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-4", children: [
2997
3083
  /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-2", children: [
2998
3084
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "text-sm font-medium", children: config.labels?.tags || "Tags" }),
2999
- (tagDialogThread.tags ?? []).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm text-muted-foreground", children: config.labels?.untagged || "Untagged" }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex flex-wrap gap-2", children: (tagDialogThread.tags ?? []).map((tag) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
3000
- Badge,
3085
+ (tagDialogThread.tags ?? []).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm text-muted-foreground", children: config.labels?.untagged || "Untagged" }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex flex-wrap gap-2", children: (tagDialogThread.tags ?? []).map((tag) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3086
+ ThreadTagEditorBadge,
3001
3087
  {
3002
- variant: "secondary",
3003
- className: "gap-1 rounded-md py-1 text-sm font-normal",
3004
- children: [
3005
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TagDot, { tag }),
3006
- tag.name,
3007
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3008
- "button",
3009
- {
3010
- type: "button",
3011
- className: "rounded-sm hover:bg-background/80",
3012
- onClick: () => removeTagFromThread(tagDialogThread, tag.id),
3013
- "aria-label": config.labels?.removeTag || "Remove tag",
3014
- children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.X, { className: "h-3 w-3" })
3015
- }
3016
- )
3017
- ]
3088
+ tag,
3089
+ removeLabel: config.labels?.removeTag || "Remove tag",
3090
+ onRemove: () => removeTagFromThread(tagDialogThread, tag.id)
3018
3091
  },
3019
3092
  tag.id
3020
3093
  )) })