@almadar/ui 4.56.4 → 4.57.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.
@@ -6432,7 +6432,7 @@ var init_Badge = __esm({
6432
6432
  lg: "px-3 py-1.5 text-base"
6433
6433
  };
6434
6434
  Badge = React96__namespace.default.forwardRef(
6435
- ({ className, variant = "default", size = "sm", amount, label, icon, children, ...props }, ref) => {
6435
+ ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
6436
6436
  const iconSizes3 = { sm: "w-3 h-3", md: "w-3.5 h-3.5", lg: "w-4 h-4" };
6437
6437
  const resolvedIcon = typeof icon === "string" ? (() => {
6438
6438
  const I = resolveIcon(icon);
@@ -6446,12 +6446,31 @@ var init_Badge = __esm({
6446
6446
  "inline-flex items-center gap-1 font-bold rounded-sm",
6447
6447
  variantStyles3[variant],
6448
6448
  sizeStyles3[size],
6449
+ onRemove && "pr-1",
6449
6450
  className
6450
6451
  ),
6451
6452
  ...props,
6452
6453
  children: [
6453
6454
  resolvedIcon,
6454
- children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label)
6455
+ children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label),
6456
+ onRemove ? /* @__PURE__ */ jsxRuntime.jsx(
6457
+ "button",
6458
+ {
6459
+ type: "button",
6460
+ "aria-label": removeLabel ?? "Remove",
6461
+ onClick: (e) => {
6462
+ e.stopPropagation();
6463
+ onRemove();
6464
+ },
6465
+ className: cn(
6466
+ "inline-flex items-center justify-center rounded-sm",
6467
+ "hover:bg-foreground/10 focus:outline-none focus:ring-1 focus:ring-ring",
6468
+ "transition-colors",
6469
+ size === "sm" ? "w-4 h-4 ml-0.5" : size === "md" ? "w-5 h-5 ml-1" : "w-6 h-6 ml-1"
6470
+ ),
6471
+ children: /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.X, { className: iconSizes3[size] })
6472
+ }
6473
+ ) : null
6455
6474
  ]
6456
6475
  }
6457
6476
  );
package/dist/avl/index.js CHANGED
@@ -6,7 +6,7 @@ import { createLogger, isLogLevelEnabled } from '@almadar/logger';
6
6
  import ELK from 'elkjs/lib/elk.bundled.js';
7
7
  import { MarkerType, Handle, Position, getBezierPath, EdgeLabelRenderer, BaseEdge, ReactFlowProvider, useNodesState, useEdgesState, useReactFlow, ReactFlow, Controls, Background, BackgroundVariant } from '@xyflow/react';
8
8
  import * as LucideIcons from 'lucide-react';
9
- import { Loader2, ChevronDown, X, Check, Copy, AlertTriangle, Info, AlertCircle, CheckCircle, List, Printer, ChevronRight, ChevronLeft, GitBranch, Pencil, Eye, Plus, ArrowRight, Trash, Code, FileText, WrapText, Trash2, Menu as Menu$1, Search, Bell, LogOut, ZoomOut, ZoomIn, Download, FileQuestion, Inbox, XCircle, Filter, Pause, Play, RotateCcw, Package, Calendar, MoreHorizontal, Image as Image$1, Upload, Minus, ArrowLeft, Camera, RefreshCw, HelpCircle, ChevronUp, MessageSquare, Flag, Type, Heading1, Heading2, Heading3, ListOrdered, Quote, Eraser, Star, TrendingUp, TrendingDown, ArrowUp, ArrowDown, MoreVertical, Sun, Moon, Circle, Clock, CheckCircle2, FileWarning, GitCommit, AlignLeft, Columns, SkipForward, Bug, Send, Wrench, User, Tag, DollarSign, Coffee, Users, Zap, Sword, Move, Heart, Shield } from 'lucide-react';
9
+ import { Loader2, X, ChevronDown, Check, Copy, AlertTriangle, Info, AlertCircle, CheckCircle, List, Printer, ChevronRight, ChevronLeft, GitBranch, Pencil, Eye, Plus, ArrowRight, Trash, Code, FileText, WrapText, Trash2, Menu as Menu$1, Search, Bell, LogOut, ZoomOut, ZoomIn, Download, FileQuestion, Inbox, XCircle, Filter, Pause, Play, RotateCcw, Package, Calendar, MoreHorizontal, Image as Image$1, Upload, Minus, ArrowLeft, Camera, RefreshCw, HelpCircle, ChevronUp, MessageSquare, Flag, Type, Heading1, Heading2, Heading3, ListOrdered, Quote, Eraser, Star, TrendingUp, TrendingDown, ArrowUp, ArrowDown, MoreVertical, Sun, Moon, Circle, Clock, CheckCircle2, FileWarning, GitCommit, AlignLeft, Columns, SkipForward, Bug, Send, Wrench, User, Tag, DollarSign, Coffee, Users, Zap, Sword, Move, Heart, Shield } from 'lucide-react';
10
10
  import { evaluate, createMinimalContext } from '@almadar/evaluator';
11
11
  import { createPortal } from 'react-dom';
12
12
  import { Link, Outlet, useLocation } from 'react-router-dom';
@@ -6386,7 +6386,7 @@ var init_Badge = __esm({
6386
6386
  lg: "px-3 py-1.5 text-base"
6387
6387
  };
6388
6388
  Badge = React96__default.forwardRef(
6389
- ({ className, variant = "default", size = "sm", amount, label, icon, children, ...props }, ref) => {
6389
+ ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
6390
6390
  const iconSizes3 = { sm: "w-3 h-3", md: "w-3.5 h-3.5", lg: "w-4 h-4" };
6391
6391
  const resolvedIcon = typeof icon === "string" ? (() => {
6392
6392
  const I = resolveIcon(icon);
@@ -6400,12 +6400,31 @@ var init_Badge = __esm({
6400
6400
  "inline-flex items-center gap-1 font-bold rounded-sm",
6401
6401
  variantStyles3[variant],
6402
6402
  sizeStyles3[size],
6403
+ onRemove && "pr-1",
6403
6404
  className
6404
6405
  ),
6405
6406
  ...props,
6406
6407
  children: [
6407
6408
  resolvedIcon,
6408
- children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label)
6409
+ children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label),
6410
+ onRemove ? /* @__PURE__ */ jsx(
6411
+ "button",
6412
+ {
6413
+ type: "button",
6414
+ "aria-label": removeLabel ?? "Remove",
6415
+ onClick: (e) => {
6416
+ e.stopPropagation();
6417
+ onRemove();
6418
+ },
6419
+ className: cn(
6420
+ "inline-flex items-center justify-center rounded-sm",
6421
+ "hover:bg-foreground/10 focus:outline-none focus:ring-1 focus:ring-ring",
6422
+ "transition-colors",
6423
+ size === "sm" ? "w-4 h-4 ml-0.5" : size === "md" ? "w-5 h-5 ml-1" : "w-6 h-6 ml-1"
6424
+ ),
6425
+ children: /* @__PURE__ */ jsx(X, { className: iconSizes3[size] })
6426
+ }
6427
+ ) : null
6409
6428
  ]
6410
6429
  }
6411
6430
  );
@@ -12,5 +12,12 @@ export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
12
12
  label?: string | number;
13
13
  /** Icon name (Lucide icon string) or React node */
14
14
  icon?: React.ReactNode;
15
+ /** When set, renders a small X button on the right of the badge that
16
+ * invokes this handler — turns the badge into a removable chip.
17
+ * Used by the TagInput molecule and other "list of removable values"
18
+ * surfaces. */
19
+ onRemove?: () => void;
20
+ /** Accessible label for the remove button. Defaults to "Remove". */
21
+ removeLabel?: string;
15
22
  }
16
23
  export declare const Badge: React.ForwardRefExoticComponent<BadgeProps & React.RefAttributes<HTMLSpanElement>>;
@@ -1770,7 +1770,7 @@ var init_Badge = __esm({
1770
1770
  lg: "px-3 py-1.5 text-base"
1771
1771
  };
1772
1772
  exports.Badge = React78__namespace.default.forwardRef(
1773
- ({ className, variant = "default", size = "sm", amount, label, icon, children, ...props }, ref) => {
1773
+ ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
1774
1774
  const iconSizes3 = { sm: "w-3 h-3", md: "w-3.5 h-3.5", lg: "w-4 h-4" };
1775
1775
  const resolvedIcon = typeof icon === "string" ? (() => {
1776
1776
  const I = resolveIcon(icon);
@@ -1784,12 +1784,31 @@ var init_Badge = __esm({
1784
1784
  "inline-flex items-center gap-1 font-bold rounded-sm",
1785
1785
  variantStyles3[variant],
1786
1786
  sizeStyles2[size],
1787
+ onRemove && "pr-1",
1787
1788
  className
1788
1789
  ),
1789
1790
  ...props,
1790
1791
  children: [
1791
1792
  resolvedIcon,
1792
- children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label)
1793
+ children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label),
1794
+ onRemove ? /* @__PURE__ */ jsxRuntime.jsx(
1795
+ "button",
1796
+ {
1797
+ type: "button",
1798
+ "aria-label": removeLabel ?? "Remove",
1799
+ onClick: (e) => {
1800
+ e.stopPropagation();
1801
+ onRemove();
1802
+ },
1803
+ className: cn(
1804
+ "inline-flex items-center justify-center rounded-sm",
1805
+ "hover:bg-foreground/10 focus:outline-none focus:ring-1 focus:ring-ring",
1806
+ "transition-colors",
1807
+ size === "sm" ? "w-4 h-4 ml-0.5" : size === "md" ? "w-5 h-5 ml-1" : "w-6 h-6 ml-1"
1808
+ ),
1809
+ children: /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.X, { className: iconSizes3[size] })
1810
+ }
1811
+ ) : null
1793
1812
  ]
1794
1813
  }
1795
1814
  );
@@ -7870,7 +7889,7 @@ var init_MapView = __esm({
7870
7889
  shadowSize: [41, 41]
7871
7890
  });
7872
7891
  L.Marker.prototype.options.icon = defaultIcon;
7873
- const { useEffect: useEffect71, useRef: useRef66, useCallback: useCallback126, useState: useState108 } = React78__namespace.default;
7892
+ const { useEffect: useEffect71, useRef: useRef66, useCallback: useCallback127, useState: useState109 } = React78__namespace.default;
7874
7893
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
7875
7894
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
7876
7895
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -7915,8 +7934,8 @@ var init_MapView = __esm({
7915
7934
  showAttribution = true
7916
7935
  }) {
7917
7936
  const eventBus = useEventBus2();
7918
- const [clickedPosition, setClickedPosition] = useState108(null);
7919
- const handleMapClick = useCallback126((lat, lng) => {
7937
+ const [clickedPosition, setClickedPosition] = useState109(null);
7938
+ const handleMapClick = useCallback127((lat, lng) => {
7920
7939
  if (showClickedPin) {
7921
7940
  setClickedPosition({ lat, lng });
7922
7941
  }
@@ -7925,7 +7944,7 @@ var init_MapView = __esm({
7925
7944
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
7926
7945
  }
7927
7946
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
7928
- const handleMarkerClick = useCallback126((marker) => {
7947
+ const handleMarkerClick = useCallback127((marker) => {
7929
7948
  onMarkerClick?.(marker);
7930
7949
  if (markerClickEvent) {
7931
7950
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -28744,6 +28763,98 @@ var init_TagCloud = __esm({
28744
28763
  exports.TagCloud.displayName = "TagCloud";
28745
28764
  }
28746
28765
  });
28766
+ exports.TagInput = void 0;
28767
+ var init_TagInput = __esm({
28768
+ "components/molecules/TagInput.tsx"() {
28769
+ "use client";
28770
+ init_cn();
28771
+ init_useEventBus();
28772
+ init_Input();
28773
+ init_Badge();
28774
+ init_Stack();
28775
+ init_Typography();
28776
+ exports.TagInput = ({
28777
+ value,
28778
+ onChange,
28779
+ placeholder,
28780
+ disabled = false,
28781
+ variant = "default",
28782
+ unique = true,
28783
+ helperText,
28784
+ className,
28785
+ addEvent,
28786
+ removeEvent
28787
+ }) => {
28788
+ const eventBus = useEventBus();
28789
+ const [draft, setDraft] = React78.useState("");
28790
+ const commit = React78.useCallback(() => {
28791
+ const tag = draft.trim();
28792
+ if (!tag) return;
28793
+ if (unique && value.includes(tag)) {
28794
+ setDraft("");
28795
+ return;
28796
+ }
28797
+ const next = [...value, tag];
28798
+ onChange?.(next);
28799
+ if (addEvent) {
28800
+ eventBus.emit(`UI:${addEvent}`, { tag, value: next });
28801
+ }
28802
+ setDraft("");
28803
+ }, [draft, value, onChange, unique, addEvent, eventBus]);
28804
+ const removeAt = React78.useCallback(
28805
+ (index) => {
28806
+ if (disabled) return;
28807
+ const tag = value[index];
28808
+ const next = value.slice();
28809
+ next.splice(index, 1);
28810
+ onChange?.(next);
28811
+ if (removeEvent) {
28812
+ eventBus.emit(`UI:${removeEvent}`, { tag, index, value: next });
28813
+ }
28814
+ },
28815
+ [value, onChange, disabled, removeEvent, eventBus]
28816
+ );
28817
+ const handleKeyDown = React78.useCallback(
28818
+ (e) => {
28819
+ if (disabled) return;
28820
+ if (e.key === "Enter") {
28821
+ e.preventDefault();
28822
+ commit();
28823
+ } else if (e.key === "Backspace" && draft.length === 0 && value.length > 0) {
28824
+ e.preventDefault();
28825
+ removeAt(value.length - 1);
28826
+ }
28827
+ },
28828
+ [commit, draft.length, value, removeAt, disabled]
28829
+ );
28830
+ return /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", className: cn("w-full", className), children: [
28831
+ value.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "xs", className: "flex-wrap", children: value.map((tag, index) => /* @__PURE__ */ jsxRuntime.jsx(
28832
+ exports.Badge,
28833
+ {
28834
+ variant,
28835
+ size: "sm",
28836
+ onRemove: disabled ? void 0 : () => removeAt(index),
28837
+ removeLabel: `Remove ${tag}`,
28838
+ children: tag
28839
+ },
28840
+ `${tag}-${index}`
28841
+ )) }) : null,
28842
+ /* @__PURE__ */ jsxRuntime.jsx(
28843
+ exports.Input,
28844
+ {
28845
+ value: draft,
28846
+ placeholder: placeholder ?? "Type and press Enter\u2026",
28847
+ disabled,
28848
+ onChange: (e) => setDraft(e.target.value),
28849
+ onKeyDown: handleKeyDown
28850
+ }
28851
+ ),
28852
+ helperText ? /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "muted", children: helperText }) : null
28853
+ ] });
28854
+ };
28855
+ exports.TagInput.displayName = "TagInput";
28856
+ }
28857
+ });
28747
28858
  exports.ShowcaseCard = void 0;
28748
28859
  var init_ShowcaseCard = __esm({
28749
28860
  "components/molecules/ShowcaseCard.tsx"() {
@@ -32879,6 +32990,7 @@ var init_molecules = __esm({
32879
32990
  init_StepFlow();
32880
32991
  init_SplitSection();
32881
32992
  init_TagCloud();
32993
+ init_TagInput();
32882
32994
  init_CommunityLinks();
32883
32995
  init_TeamCard();
32884
32996
  init_ShowcaseCard();
@@ -1724,7 +1724,7 @@ var init_Badge = __esm({
1724
1724
  lg: "px-3 py-1.5 text-base"
1725
1725
  };
1726
1726
  Badge = React78__default.forwardRef(
1727
- ({ className, variant = "default", size = "sm", amount, label, icon, children, ...props }, ref) => {
1727
+ ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
1728
1728
  const iconSizes3 = { sm: "w-3 h-3", md: "w-3.5 h-3.5", lg: "w-4 h-4" };
1729
1729
  const resolvedIcon = typeof icon === "string" ? (() => {
1730
1730
  const I = resolveIcon(icon);
@@ -1738,12 +1738,31 @@ var init_Badge = __esm({
1738
1738
  "inline-flex items-center gap-1 font-bold rounded-sm",
1739
1739
  variantStyles3[variant],
1740
1740
  sizeStyles2[size],
1741
+ onRemove && "pr-1",
1741
1742
  className
1742
1743
  ),
1743
1744
  ...props,
1744
1745
  children: [
1745
1746
  resolvedIcon,
1746
- children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label)
1747
+ children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label),
1748
+ onRemove ? /* @__PURE__ */ jsx(
1749
+ "button",
1750
+ {
1751
+ type: "button",
1752
+ "aria-label": removeLabel ?? "Remove",
1753
+ onClick: (e) => {
1754
+ e.stopPropagation();
1755
+ onRemove();
1756
+ },
1757
+ className: cn(
1758
+ "inline-flex items-center justify-center rounded-sm",
1759
+ "hover:bg-foreground/10 focus:outline-none focus:ring-1 focus:ring-ring",
1760
+ "transition-colors",
1761
+ size === "sm" ? "w-4 h-4 ml-0.5" : size === "md" ? "w-5 h-5 ml-1" : "w-6 h-6 ml-1"
1762
+ ),
1763
+ children: /* @__PURE__ */ jsx(X, { className: iconSizes3[size] })
1764
+ }
1765
+ ) : null
1747
1766
  ]
1748
1767
  }
1749
1768
  );
@@ -7824,7 +7843,7 @@ var init_MapView = __esm({
7824
7843
  shadowSize: [41, 41]
7825
7844
  });
7826
7845
  L.Marker.prototype.options.icon = defaultIcon;
7827
- const { useEffect: useEffect71, useRef: useRef66, useCallback: useCallback126, useState: useState108 } = React78__default;
7846
+ const { useEffect: useEffect71, useRef: useRef66, useCallback: useCallback127, useState: useState109 } = React78__default;
7828
7847
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
7829
7848
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
7830
7849
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -7869,8 +7888,8 @@ var init_MapView = __esm({
7869
7888
  showAttribution = true
7870
7889
  }) {
7871
7890
  const eventBus = useEventBus2();
7872
- const [clickedPosition, setClickedPosition] = useState108(null);
7873
- const handleMapClick = useCallback126((lat, lng) => {
7891
+ const [clickedPosition, setClickedPosition] = useState109(null);
7892
+ const handleMapClick = useCallback127((lat, lng) => {
7874
7893
  if (showClickedPin) {
7875
7894
  setClickedPosition({ lat, lng });
7876
7895
  }
@@ -7879,7 +7898,7 @@ var init_MapView = __esm({
7879
7898
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
7880
7899
  }
7881
7900
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
7882
- const handleMarkerClick = useCallback126((marker) => {
7901
+ const handleMarkerClick = useCallback127((marker) => {
7883
7902
  onMarkerClick?.(marker);
7884
7903
  if (markerClickEvent) {
7885
7904
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -28698,6 +28717,98 @@ var init_TagCloud = __esm({
28698
28717
  TagCloud.displayName = "TagCloud";
28699
28718
  }
28700
28719
  });
28720
+ var TagInput;
28721
+ var init_TagInput = __esm({
28722
+ "components/molecules/TagInput.tsx"() {
28723
+ "use client";
28724
+ init_cn();
28725
+ init_useEventBus();
28726
+ init_Input();
28727
+ init_Badge();
28728
+ init_Stack();
28729
+ init_Typography();
28730
+ TagInput = ({
28731
+ value,
28732
+ onChange,
28733
+ placeholder,
28734
+ disabled = false,
28735
+ variant = "default",
28736
+ unique = true,
28737
+ helperText,
28738
+ className,
28739
+ addEvent,
28740
+ removeEvent
28741
+ }) => {
28742
+ const eventBus = useEventBus();
28743
+ const [draft, setDraft] = useState("");
28744
+ const commit = useCallback(() => {
28745
+ const tag = draft.trim();
28746
+ if (!tag) return;
28747
+ if (unique && value.includes(tag)) {
28748
+ setDraft("");
28749
+ return;
28750
+ }
28751
+ const next = [...value, tag];
28752
+ onChange?.(next);
28753
+ if (addEvent) {
28754
+ eventBus.emit(`UI:${addEvent}`, { tag, value: next });
28755
+ }
28756
+ setDraft("");
28757
+ }, [draft, value, onChange, unique, addEvent, eventBus]);
28758
+ const removeAt = useCallback(
28759
+ (index) => {
28760
+ if (disabled) return;
28761
+ const tag = value[index];
28762
+ const next = value.slice();
28763
+ next.splice(index, 1);
28764
+ onChange?.(next);
28765
+ if (removeEvent) {
28766
+ eventBus.emit(`UI:${removeEvent}`, { tag, index, value: next });
28767
+ }
28768
+ },
28769
+ [value, onChange, disabled, removeEvent, eventBus]
28770
+ );
28771
+ const handleKeyDown = useCallback(
28772
+ (e) => {
28773
+ if (disabled) return;
28774
+ if (e.key === "Enter") {
28775
+ e.preventDefault();
28776
+ commit();
28777
+ } else if (e.key === "Backspace" && draft.length === 0 && value.length > 0) {
28778
+ e.preventDefault();
28779
+ removeAt(value.length - 1);
28780
+ }
28781
+ },
28782
+ [commit, draft.length, value, removeAt, disabled]
28783
+ );
28784
+ return /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: cn("w-full", className), children: [
28785
+ value.length > 0 ? /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: value.map((tag, index) => /* @__PURE__ */ jsx(
28786
+ Badge,
28787
+ {
28788
+ variant,
28789
+ size: "sm",
28790
+ onRemove: disabled ? void 0 : () => removeAt(index),
28791
+ removeLabel: `Remove ${tag}`,
28792
+ children: tag
28793
+ },
28794
+ `${tag}-${index}`
28795
+ )) }) : null,
28796
+ /* @__PURE__ */ jsx(
28797
+ Input,
28798
+ {
28799
+ value: draft,
28800
+ placeholder: placeholder ?? "Type and press Enter\u2026",
28801
+ disabled,
28802
+ onChange: (e) => setDraft(e.target.value),
28803
+ onKeyDown: handleKeyDown
28804
+ }
28805
+ ),
28806
+ helperText ? /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: helperText }) : null
28807
+ ] });
28808
+ };
28809
+ TagInput.displayName = "TagInput";
28810
+ }
28811
+ });
28701
28812
  var ShowcaseCard;
28702
28813
  var init_ShowcaseCard = __esm({
28703
28814
  "components/molecules/ShowcaseCard.tsx"() {
@@ -32833,6 +32944,7 @@ var init_molecules = __esm({
32833
32944
  init_StepFlow();
32834
32945
  init_SplitSection();
32835
32946
  init_TagCloud();
32947
+ init_TagInput();
32836
32948
  init_CommunityLinks();
32837
32949
  init_TeamCard();
32838
32950
  init_ShowcaseCard();
@@ -49006,4 +49118,4 @@ function useGitHubBranches(owner, repo, enabled = true) {
49006
49118
  });
49007
49119
  }
49008
49120
 
49009
- export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, ActionButtons, Card2 as ActionCard, ActionPalette, ActionTile, Alert, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AuthLayout, Avatar, Badge, BattleBoard, BattleTemplate, BehaviorView, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, BuilderBoard, Button, ButtonGroup, CTABanner, CalendarGrid, CanvasEffect, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, CastleBoard, CastleTemplate, Center, Chart, ChartLegend, Checkbox, ChoiceButton, ClassifierBoard, CodeBlock, CodeExample, CodeView, CodeViewer, CollapsibleSection, CombatLog, ComboCounter, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, Container, ContentRenderer, ContentSection, ControlButton, CounterTemplate, CraftingRecipe, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DPad, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DebuggerBoard, DetailPanel, Dialog, DialogueBox, DialogueBubble, Divider, DocBreadcrumb, DocCodeBlock, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EnemyPlate, EntityDisplayEvents, ErrorBoundary, ErrorState, EventHandlerBoard, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FeatureRenderer2 as FeatureRenderer, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCanvas2D, GameHud, GameMenu, GameOverScreen, GameShell, GameTemplate, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, HStack, Header, Heading, HealthBar, HealthPanel, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, InventoryPanel, IsometricCanvas, ItemSlot, JazariStateMachine, Label, LandingPageTemplate, LawReferenceTooltip, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingStatCard, MasterDetail, MasterDetailLayout, MatrixQuestion, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, ModuleCard, Navigation, NegotiatorBoard, NotifyListener, NumberStepper, ObjectRulePanel, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PatternTile, PhysicsManager, PlatformerCanvas, Popover, PositionedCanvas, PowerupSlots, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PullQuote, PullToRefresh, QrScanner, QuestTracker, QuizBlock, Radio, RangeSlider, RelationSelect, RepeatableFormSection, ReplyTree, ResourceBar, ResourceCounter, RichBlockEditor, RuleEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreBoard, ScoreDisplay, SearchInput, Section, SectionHeader, Select, SequenceBar, SequencerBoard, ServiceCatalog, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulationCanvas, SimulationControls, SimulationGraph, SimulatorBoard, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateArchitectBoard, StateIndicator, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StatusEffect, StepFlow, StepFlowOrganism, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, Table, Tabs, TagCloud, TeamCard, TeamOrganism, TerrainPalette, Text, TextHighlight, Textarea, ThemeSelector, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TurnPanel, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UncontrolledBattleBoard, UnitCommandBar, UploadDropZone, VStack, VariablePanel, VersionDiff, ViolationAlert, VoteStack, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, WorldMapBoard, WorldMapTemplate, XPBar, applyTemporaryEffect, calculateAttackTargets, calculateDamage, calculateValidMoves, clearEntities, cn, combatAnimations, combatClasses, combatEffects, createInitialGameState, createTranslate, createUnitAnimationState, drawSprite, generateCombatMessage, getAllEntities, getByType, getCurrentFrame, getEntity, getSingleton, getTileDimensions, inferDirection, isoToScreen, mapBookData, parseQueryBinding, pendulum, projectileMotion, removeEntity, resolveFieldMap, resolveFrame, resolveSheetDirection, screenToIso, spawnEntity, springOscillator, tickAnimationState, transitionAnimation, updateEntity, updateSingleton, useAgentChat, useAuthContext, useBattleState, useCamera, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEntities, useEntitiesByType, useEntity as useEntityById, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGameAudioContext, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useInput, useLongPress, useOrbitalHistory, usePhysics, usePhysics2D, usePinchZoom, usePlayer, usePreview, usePullToRefresh, useQuerySingleton, useSingletonEntity, useSpriteAnimations, useSwipeGesture, useTraitListens, useTranslate, useUIEvents, useUISlotManager, useValidation };
49121
+ export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, ActionButtons, Card2 as ActionCard, ActionPalette, ActionTile, Alert, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AuthLayout, Avatar, Badge, BattleBoard, BattleTemplate, BehaviorView, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, BuilderBoard, Button, ButtonGroup, CTABanner, CalendarGrid, CanvasEffect, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, CastleBoard, CastleTemplate, Center, Chart, ChartLegend, Checkbox, ChoiceButton, ClassifierBoard, CodeBlock, CodeExample, CodeView, CodeViewer, CollapsibleSection, CombatLog, ComboCounter, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, Container, ContentRenderer, ContentSection, ControlButton, CounterTemplate, CraftingRecipe, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DPad, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DebuggerBoard, DetailPanel, Dialog, DialogueBox, DialogueBubble, Divider, DocBreadcrumb, DocCodeBlock, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EnemyPlate, EntityDisplayEvents, ErrorBoundary, ErrorState, EventHandlerBoard, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FeatureRenderer2 as FeatureRenderer, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCanvas2D, GameHud, GameMenu, GameOverScreen, GameShell, GameTemplate, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, HStack, Header, Heading, HealthBar, HealthPanel, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, InventoryPanel, IsometricCanvas, ItemSlot, JazariStateMachine, Label, LandingPageTemplate, LawReferenceTooltip, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingStatCard, MasterDetail, MasterDetailLayout, MatrixQuestion, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, ModuleCard, Navigation, NegotiatorBoard, NotifyListener, NumberStepper, ObjectRulePanel, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PatternTile, PhysicsManager, PlatformerCanvas, Popover, PositionedCanvas, PowerupSlots, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PullQuote, PullToRefresh, QrScanner, QuestTracker, QuizBlock, Radio, RangeSlider, RelationSelect, RepeatableFormSection, ReplyTree, ResourceBar, ResourceCounter, RichBlockEditor, RuleEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreBoard, ScoreDisplay, SearchInput, Section, SectionHeader, Select, SequenceBar, SequencerBoard, ServiceCatalog, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulationCanvas, SimulationControls, SimulationGraph, SimulatorBoard, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateArchitectBoard, StateIndicator, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StatusEffect, StepFlow, StepFlowOrganism, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, Table, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, Text, TextHighlight, Textarea, ThemeSelector, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TurnPanel, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UncontrolledBattleBoard, UnitCommandBar, UploadDropZone, VStack, VariablePanel, VersionDiff, ViolationAlert, VoteStack, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, WorldMapBoard, WorldMapTemplate, XPBar, applyTemporaryEffect, calculateAttackTargets, calculateDamage, calculateValidMoves, clearEntities, cn, combatAnimations, combatClasses, combatEffects, createInitialGameState, createTranslate, createUnitAnimationState, drawSprite, generateCombatMessage, getAllEntities, getByType, getCurrentFrame, getEntity, getSingleton, getTileDimensions, inferDirection, isoToScreen, mapBookData, parseQueryBinding, pendulum, projectileMotion, removeEntity, resolveFieldMap, resolveFrame, resolveSheetDirection, screenToIso, spawnEntity, springOscillator, tickAnimationState, transitionAnimation, updateEntity, updateSingleton, useAgentChat, useAuthContext, useBattleState, useCamera, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEntities, useEntitiesByType, useEntity as useEntityById, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGameAudioContext, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useInput, useLongPress, useOrbitalHistory, usePhysics, usePhysics2D, usePinchZoom, usePlayer, usePreview, usePullToRefresh, useQuerySingleton, useSingletonEntity, useSpriteAnimations, useSwipeGesture, useTraitListens, useTranslate, useUIEvents, useUISlotManager, useValidation };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * TagInput Molecule Component
3
+ *
4
+ * Free-form chip editor for `string[]` values. The user types into an
5
+ * `Input` and presses Enter to commit; each committed value renders as
6
+ * a removable `Badge` (`onRemove` X-chip). Backspace on an empty input
7
+ * deletes the most recently added chip. Optional `unique` flag
8
+ * (default true) suppresses duplicate entries.
9
+ *
10
+ * **Atomic Design**: Composed using `Input`, `Badge`, `Typography`,
11
+ * `HStack`, `VStack` atoms — no raw HTML. Generic primitive; no entity
12
+ * binding.
13
+ *
14
+ * Event contract (mirrors DataList / FilterGroup):
15
+ * - Emits `UI:{addEvent}` with `{ tag, value }` when a chip is added.
16
+ * - Emits `UI:{removeEvent}` with `{ tag, index, value }` when a chip
17
+ * is removed.
18
+ * - `onChange` callback stays as the direct / Storybook contract.
19
+ *
20
+ * Used by the studio Questionnaire for the `tagList` input type
21
+ * (`[string]` config knobs without `enumValues`).
22
+ */
23
+ import React from 'react';
24
+ import type { EventKey } from '@almadar/core';
25
+ import { type BadgeVariant } from '../atoms/Badge';
26
+ export interface TagInputProps {
27
+ /** Current list of tags. */
28
+ value: ReadonlyArray<string>;
29
+ /** Direct callback emitted on every change. Stays as the
30
+ * Storybook / non-trait contract; trait-driven schemas should prefer
31
+ * the bus events below. */
32
+ onChange?: (next: ReadonlyArray<string>) => void;
33
+ /** Placeholder for the entry input. Default: `"Type and press Enter…"`. */
34
+ placeholder?: string;
35
+ /** Disable add + remove interactions. */
36
+ disabled?: boolean;
37
+ /** Variant applied to each chip Badge. Default: `'default'`. */
38
+ variant?: BadgeVariant;
39
+ /** Suppress duplicate entries. Default: `true`. */
40
+ unique?: boolean;
41
+ /** Helper text rendered under the input. */
42
+ helperText?: string;
43
+ /** Additional CSS classes applied to the outer container. */
44
+ className?: string;
45
+ /** Event emitted when a tag is added: `UI:{addEvent}` with payload
46
+ * `{ tag: string, value: string[] }`. */
47
+ addEvent?: EventKey;
48
+ /** Event emitted when a tag is removed: `UI:{removeEvent}` with
49
+ * payload `{ tag: string, index: number, value: string[] }`. */
50
+ removeEvent?: EventKey;
51
+ }
52
+ export declare const TagInput: React.FC<TagInputProps>;
@@ -75,6 +75,7 @@ export { SocialProof, type SocialProofProps, type SocialProofItem } from './Soci
75
75
  export { StepFlow, type StepFlowProps, type StepItemProps } from './StepFlow';
76
76
  export { SplitSection, type SplitSectionProps } from './SplitSection';
77
77
  export { TagCloud, type TagCloudProps, type TagCloudItem } from './TagCloud';
78
+ export { TagInput, type TagInputProps } from './TagInput';
78
79
  export { CommunityLinks, type CommunityLinksProps } from './CommunityLinks';
79
80
  export { TeamCard, type TeamCardProps } from './TeamCard';
80
81
  export { ShowcaseCard, type ShowcaseCardProps } from './ShowcaseCard';
@@ -3251,7 +3251,7 @@ var sizeStyles3 = {
3251
3251
  lg: "px-3 py-1.5 text-base"
3252
3252
  };
3253
3253
  var Badge = React6__default.default.forwardRef(
3254
- ({ className, variant = "default", size = "sm", amount, label, icon, children, ...props }, ref) => {
3254
+ ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
3255
3255
  const iconSizes = { sm: "w-3 h-3", md: "w-3.5 h-3.5", lg: "w-4 h-4" };
3256
3256
  const resolvedIcon = typeof icon === "string" ? (() => {
3257
3257
  const I = resolveIcon(icon);
@@ -3265,12 +3265,31 @@ var Badge = React6__default.default.forwardRef(
3265
3265
  "inline-flex items-center gap-1 font-bold rounded-sm",
3266
3266
  variantStyles3[variant],
3267
3267
  sizeStyles3[size],
3268
+ onRemove && "pr-1",
3268
3269
  className
3269
3270
  ),
3270
3271
  ...props,
3271
3272
  children: [
3272
3273
  resolvedIcon,
3273
- children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label)
3274
+ children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label),
3275
+ onRemove ? /* @__PURE__ */ jsxRuntime.jsx(
3276
+ "button",
3277
+ {
3278
+ type: "button",
3279
+ "aria-label": removeLabel ?? "Remove",
3280
+ onClick: (e) => {
3281
+ e.stopPropagation();
3282
+ onRemove();
3283
+ },
3284
+ className: cn(
3285
+ "inline-flex items-center justify-center rounded-sm",
3286
+ "hover:bg-foreground/10 focus:outline-none focus:ring-1 focus:ring-ring",
3287
+ "transition-colors",
3288
+ size === "sm" ? "w-4 h-4 ml-0.5" : size === "md" ? "w-5 h-5 ml-1" : "w-6 h-6 ml-1"
3289
+ ),
3290
+ children: /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.X, { className: iconSizes[size] })
3291
+ }
3292
+ ) : null
3274
3293
  ]
3275
3294
  }
3276
3295
  );
@@ -203,6 +203,13 @@ interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
203
203
  label?: string | number;
204
204
  /** Icon name (Lucide icon string) or React node */
205
205
  icon?: React.ReactNode;
206
+ /** When set, renders a small X button on the right of the badge that
207
+ * invokes this handler — turns the badge into a removable chip.
208
+ * Used by the TagInput molecule and other "list of removable values"
209
+ * surfaces. */
210
+ onRemove?: () => void;
211
+ /** Accessible label for the remove button. Defaults to "Remove". */
212
+ removeLabel?: string;
206
213
  }
207
214
  declare const Badge: React.ForwardRefExoticComponent<BadgeProps & React.RefAttributes<HTMLSpanElement>>;
208
215
 
@@ -2,7 +2,7 @@ import React6, { createContext, useCallback, useState, useRef, useEffect, useCon
2
2
  import { createLogger } from '@almadar/logger';
3
3
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
4
  import * as LucideIcons from 'lucide-react';
5
- import { Loader2, Check, User } from 'lucide-react';
5
+ import { Loader2, X, Check, User } from 'lucide-react';
6
6
 
7
7
  // node_modules/clsx/dist/clsx.mjs
8
8
  function r(e) {
@@ -3227,7 +3227,7 @@ var sizeStyles3 = {
3227
3227
  lg: "px-3 py-1.5 text-base"
3228
3228
  };
3229
3229
  var Badge = React6.forwardRef(
3230
- ({ className, variant = "default", size = "sm", amount, label, icon, children, ...props }, ref) => {
3230
+ ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
3231
3231
  const iconSizes = { sm: "w-3 h-3", md: "w-3.5 h-3.5", lg: "w-4 h-4" };
3232
3232
  const resolvedIcon = typeof icon === "string" ? (() => {
3233
3233
  const I = resolveIcon(icon);
@@ -3241,12 +3241,31 @@ var Badge = React6.forwardRef(
3241
3241
  "inline-flex items-center gap-1 font-bold rounded-sm",
3242
3242
  variantStyles3[variant],
3243
3243
  sizeStyles3[size],
3244
+ onRemove && "pr-1",
3244
3245
  className
3245
3246
  ),
3246
3247
  ...props,
3247
3248
  children: [
3248
3249
  resolvedIcon,
3249
- children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label)
3250
+ children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label),
3251
+ onRemove ? /* @__PURE__ */ jsx(
3252
+ "button",
3253
+ {
3254
+ type: "button",
3255
+ "aria-label": removeLabel ?? "Remove",
3256
+ onClick: (e) => {
3257
+ e.stopPropagation();
3258
+ onRemove();
3259
+ },
3260
+ className: cn(
3261
+ "inline-flex items-center justify-center rounded-sm",
3262
+ "hover:bg-foreground/10 focus:outline-none focus:ring-1 focus:ring-ring",
3263
+ "transition-colors",
3264
+ size === "sm" ? "w-4 h-4 ml-0.5" : size === "md" ? "w-5 h-5 ml-1" : "w-6 h-6 ml-1"
3265
+ ),
3266
+ children: /* @__PURE__ */ jsx(X, { className: iconSizes[size] })
3267
+ }
3268
+ ) : null
3250
3269
  ]
3251
3270
  }
3252
3271
  );
@@ -1617,7 +1617,7 @@ var init_Badge = __esm({
1617
1617
  lg: "px-3 py-1.5 text-base"
1618
1618
  };
1619
1619
  Badge = React84__namespace.default.forwardRef(
1620
- ({ className, variant = "default", size = "sm", amount, label, icon, children, ...props }, ref) => {
1620
+ ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
1621
1621
  const iconSizes3 = { sm: "w-3 h-3", md: "w-3.5 h-3.5", lg: "w-4 h-4" };
1622
1622
  const resolvedIcon = typeof icon === "string" ? (() => {
1623
1623
  const I = resolveIcon(icon);
@@ -1631,12 +1631,31 @@ var init_Badge = __esm({
1631
1631
  "inline-flex items-center gap-1 font-bold rounded-sm",
1632
1632
  variantStyles3[variant],
1633
1633
  sizeStyles3[size],
1634
+ onRemove && "pr-1",
1634
1635
  className
1635
1636
  ),
1636
1637
  ...props,
1637
1638
  children: [
1638
1639
  resolvedIcon,
1639
- children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label)
1640
+ children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label),
1641
+ onRemove ? /* @__PURE__ */ jsxRuntime.jsx(
1642
+ "button",
1643
+ {
1644
+ type: "button",
1645
+ "aria-label": removeLabel ?? "Remove",
1646
+ onClick: (e) => {
1647
+ e.stopPropagation();
1648
+ onRemove();
1649
+ },
1650
+ className: cn(
1651
+ "inline-flex items-center justify-center rounded-sm",
1652
+ "hover:bg-foreground/10 focus:outline-none focus:ring-1 focus:ring-ring",
1653
+ "transition-colors",
1654
+ size === "sm" ? "w-4 h-4 ml-0.5" : size === "md" ? "w-5 h-5 ml-1" : "w-6 h-6 ml-1"
1655
+ ),
1656
+ children: /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.X, { className: iconSizes3[size] })
1657
+ }
1658
+ ) : null
1640
1659
  ]
1641
1660
  }
1642
1661
  );
@@ -1571,7 +1571,7 @@ var init_Badge = __esm({
1571
1571
  lg: "px-3 py-1.5 text-base"
1572
1572
  };
1573
1573
  Badge = React84__default.forwardRef(
1574
- ({ className, variant = "default", size = "sm", amount, label, icon, children, ...props }, ref) => {
1574
+ ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
1575
1575
  const iconSizes3 = { sm: "w-3 h-3", md: "w-3.5 h-3.5", lg: "w-4 h-4" };
1576
1576
  const resolvedIcon = typeof icon === "string" ? (() => {
1577
1577
  const I = resolveIcon(icon);
@@ -1585,12 +1585,31 @@ var init_Badge = __esm({
1585
1585
  "inline-flex items-center gap-1 font-bold rounded-sm",
1586
1586
  variantStyles3[variant],
1587
1587
  sizeStyles3[size],
1588
+ onRemove && "pr-1",
1588
1589
  className
1589
1590
  ),
1590
1591
  ...props,
1591
1592
  children: [
1592
1593
  resolvedIcon,
1593
- children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label)
1594
+ children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label),
1595
+ onRemove ? /* @__PURE__ */ jsx(
1596
+ "button",
1597
+ {
1598
+ type: "button",
1599
+ "aria-label": removeLabel ?? "Remove",
1600
+ onClick: (e) => {
1601
+ e.stopPropagation();
1602
+ onRemove();
1603
+ },
1604
+ className: cn(
1605
+ "inline-flex items-center justify-center rounded-sm",
1606
+ "hover:bg-foreground/10 focus:outline-none focus:ring-1 focus:ring-ring",
1607
+ "transition-colors",
1608
+ size === "sm" ? "w-4 h-4 ml-0.5" : size === "md" ? "w-5 h-5 ml-1" : "w-6 h-6 ml-1"
1609
+ ),
1610
+ children: /* @__PURE__ */ jsx(X, { className: iconSizes3[size] })
1611
+ }
1612
+ ) : null
1594
1613
  ]
1595
1614
  }
1596
1615
  );
@@ -1901,7 +1901,7 @@ var init_Badge = __esm({
1901
1901
  lg: "px-3 py-1.5 text-base"
1902
1902
  };
1903
1903
  Badge = React83__namespace.default.forwardRef(
1904
- ({ className, variant = "default", size = "sm", amount, label, icon, children, ...props }, ref) => {
1904
+ ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
1905
1905
  const iconSizes3 = { sm: "w-3 h-3", md: "w-3.5 h-3.5", lg: "w-4 h-4" };
1906
1906
  const resolvedIcon = typeof icon === "string" ? (() => {
1907
1907
  const I = resolveIcon(icon);
@@ -1915,12 +1915,31 @@ var init_Badge = __esm({
1915
1915
  "inline-flex items-center gap-1 font-bold rounded-sm",
1916
1916
  variantStyles3[variant],
1917
1917
  sizeStyles3[size],
1918
+ onRemove && "pr-1",
1918
1919
  className
1919
1920
  ),
1920
1921
  ...props,
1921
1922
  children: [
1922
1923
  resolvedIcon,
1923
- children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label)
1924
+ children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label),
1925
+ onRemove ? /* @__PURE__ */ jsxRuntime.jsx(
1926
+ "button",
1927
+ {
1928
+ type: "button",
1929
+ "aria-label": removeLabel ?? "Remove",
1930
+ onClick: (e) => {
1931
+ e.stopPropagation();
1932
+ onRemove();
1933
+ },
1934
+ className: cn(
1935
+ "inline-flex items-center justify-center rounded-sm",
1936
+ "hover:bg-foreground/10 focus:outline-none focus:ring-1 focus:ring-ring",
1937
+ "transition-colors",
1938
+ size === "sm" ? "w-4 h-4 ml-0.5" : size === "md" ? "w-5 h-5 ml-1" : "w-6 h-6 ml-1"
1939
+ ),
1940
+ children: /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.X, { className: iconSizes3[size] })
1941
+ }
1942
+ ) : null
1924
1943
  ]
1925
1944
  }
1926
1945
  );
@@ -1855,7 +1855,7 @@ var init_Badge = __esm({
1855
1855
  lg: "px-3 py-1.5 text-base"
1856
1856
  };
1857
1857
  Badge = React83__default.forwardRef(
1858
- ({ className, variant = "default", size = "sm", amount, label, icon, children, ...props }, ref) => {
1858
+ ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
1859
1859
  const iconSizes3 = { sm: "w-3 h-3", md: "w-3.5 h-3.5", lg: "w-4 h-4" };
1860
1860
  const resolvedIcon = typeof icon === "string" ? (() => {
1861
1861
  const I = resolveIcon(icon);
@@ -1869,12 +1869,31 @@ var init_Badge = __esm({
1869
1869
  "inline-flex items-center gap-1 font-bold rounded-sm",
1870
1870
  variantStyles3[variant],
1871
1871
  sizeStyles3[size],
1872
+ onRemove && "pr-1",
1872
1873
  className
1873
1874
  ),
1874
1875
  ...props,
1875
1876
  children: [
1876
1877
  resolvedIcon,
1877
- children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label)
1878
+ children || (amount != null ? `${label ? `${label} ` : ""}${amount}` : label),
1879
+ onRemove ? /* @__PURE__ */ jsx(
1880
+ "button",
1881
+ {
1882
+ type: "button",
1883
+ "aria-label": removeLabel ?? "Remove",
1884
+ onClick: (e) => {
1885
+ e.stopPropagation();
1886
+ onRemove();
1887
+ },
1888
+ className: cn(
1889
+ "inline-flex items-center justify-center rounded-sm",
1890
+ "hover:bg-foreground/10 focus:outline-none focus:ring-1 focus:ring-ring",
1891
+ "transition-colors",
1892
+ size === "sm" ? "w-4 h-4 ml-0.5" : size === "md" ? "w-5 h-5 ml-1" : "w-6 h-6 ml-1"
1893
+ ),
1894
+ children: /* @__PURE__ */ jsx(X, { className: iconSizes3[size] })
1895
+ }
1896
+ ) : null
1878
1897
  ]
1879
1898
  }
1880
1899
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "4.56.4",
3
+ "version": "4.57.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [