@almadar/ui 4.56.4 → 4.57.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.
@@ -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();
@@ -44783,6 +44895,7 @@ var init_component_registry_generated = __esm({
44783
44895
  init_Table();
44784
44896
  init_Tabs();
44785
44897
  init_TagCloud();
44898
+ init_TagInput();
44786
44899
  init_TeamCard();
44787
44900
  init_TeamOrganism();
44788
44901
  init_TextHighlight();
@@ -45098,6 +45211,7 @@ var init_component_registry_generated = __esm({
45098
45211
  "Table": Table,
45099
45212
  "Tabs": Tabs,
45100
45213
  "TagCloud": TagCloud,
45214
+ "TagInput": TagInput,
45101
45215
  "TeamCard": TeamCard,
45102
45216
  "TeamOrganism": TeamOrganism,
45103
45217
  "TextHighlight": TextHighlight,
@@ -49006,4 +49120,4 @@ function useGitHubBranches(owner, repo, enabled = true) {
49006
49120
  });
49007
49121
  }
49008
49122
 
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 };
49123
+ 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
  );
@@ -9438,7 +9457,7 @@ var init_MapView = __esm({
9438
9457
  shadowSize: [41, 41]
9439
9458
  });
9440
9459
  L.Marker.prototype.options.icon = defaultIcon;
9441
- const { useEffect: useEffect68, useRef: useRef65, useCallback: useCallback112, useState: useState97 } = React84__namespace.default;
9460
+ const { useEffect: useEffect68, useRef: useRef65, useCallback: useCallback113, useState: useState98 } = React84__namespace.default;
9442
9461
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
9443
9462
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
9444
9463
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -9483,8 +9502,8 @@ var init_MapView = __esm({
9483
9502
  showAttribution = true
9484
9503
  }) {
9485
9504
  const eventBus = useEventBus2();
9486
- const [clickedPosition, setClickedPosition] = useState97(null);
9487
- const handleMapClick = useCallback112((lat, lng) => {
9505
+ const [clickedPosition, setClickedPosition] = useState98(null);
9506
+ const handleMapClick = useCallback113((lat, lng) => {
9488
9507
  if (showClickedPin) {
9489
9508
  setClickedPosition({ lat, lng });
9490
9509
  }
@@ -9493,7 +9512,7 @@ var init_MapView = __esm({
9493
9512
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
9494
9513
  }
9495
9514
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
9496
- const handleMarkerClick = useCallback112((marker) => {
9515
+ const handleMarkerClick = useCallback113((marker) => {
9497
9516
  onMarkerClick?.(marker);
9498
9517
  if (markerClickEvent) {
9499
9518
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -29697,6 +29716,98 @@ var init_TagCloud = __esm({
29697
29716
  TagCloud.displayName = "TagCloud";
29698
29717
  }
29699
29718
  });
29719
+ var TagInput;
29720
+ var init_TagInput = __esm({
29721
+ "components/molecules/TagInput.tsx"() {
29722
+ "use client";
29723
+ init_cn();
29724
+ init_useEventBus();
29725
+ init_Input();
29726
+ init_Badge();
29727
+ init_Stack();
29728
+ init_Typography();
29729
+ TagInput = ({
29730
+ value,
29731
+ onChange,
29732
+ placeholder,
29733
+ disabled = false,
29734
+ variant = "default",
29735
+ unique = true,
29736
+ helperText,
29737
+ className,
29738
+ addEvent,
29739
+ removeEvent
29740
+ }) => {
29741
+ const eventBus = useEventBus();
29742
+ const [draft, setDraft] = React84.useState("");
29743
+ const commit = React84.useCallback(() => {
29744
+ const tag = draft.trim();
29745
+ if (!tag) return;
29746
+ if (unique && value.includes(tag)) {
29747
+ setDraft("");
29748
+ return;
29749
+ }
29750
+ const next = [...value, tag];
29751
+ onChange?.(next);
29752
+ if (addEvent) {
29753
+ eventBus.emit(`UI:${addEvent}`, { tag, value: next });
29754
+ }
29755
+ setDraft("");
29756
+ }, [draft, value, onChange, unique, addEvent, eventBus]);
29757
+ const removeAt = React84.useCallback(
29758
+ (index) => {
29759
+ if (disabled) return;
29760
+ const tag = value[index];
29761
+ const next = value.slice();
29762
+ next.splice(index, 1);
29763
+ onChange?.(next);
29764
+ if (removeEvent) {
29765
+ eventBus.emit(`UI:${removeEvent}`, { tag, index, value: next });
29766
+ }
29767
+ },
29768
+ [value, onChange, disabled, removeEvent, eventBus]
29769
+ );
29770
+ const handleKeyDown = React84.useCallback(
29771
+ (e) => {
29772
+ if (disabled) return;
29773
+ if (e.key === "Enter") {
29774
+ e.preventDefault();
29775
+ commit();
29776
+ } else if (e.key === "Backspace" && draft.length === 0 && value.length > 0) {
29777
+ e.preventDefault();
29778
+ removeAt(value.length - 1);
29779
+ }
29780
+ },
29781
+ [commit, draft.length, value, removeAt, disabled]
29782
+ );
29783
+ return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", className: cn("w-full", className), children: [
29784
+ value.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", className: "flex-wrap", children: value.map((tag, index) => /* @__PURE__ */ jsxRuntime.jsx(
29785
+ Badge,
29786
+ {
29787
+ variant,
29788
+ size: "sm",
29789
+ onRemove: disabled ? void 0 : () => removeAt(index),
29790
+ removeLabel: `Remove ${tag}`,
29791
+ children: tag
29792
+ },
29793
+ `${tag}-${index}`
29794
+ )) }) : null,
29795
+ /* @__PURE__ */ jsxRuntime.jsx(
29796
+ Input,
29797
+ {
29798
+ value: draft,
29799
+ placeholder: placeholder ?? "Type and press Enter\u2026",
29800
+ disabled,
29801
+ onChange: (e) => setDraft(e.target.value),
29802
+ onKeyDown: handleKeyDown
29803
+ }
29804
+ ),
29805
+ helperText ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "muted", children: helperText }) : null
29806
+ ] });
29807
+ };
29808
+ TagInput.displayName = "TagInput";
29809
+ }
29810
+ });
29700
29811
  var ShowcaseCard;
29701
29812
  var init_ShowcaseCard = __esm({
29702
29813
  "components/molecules/ShowcaseCard.tsx"() {
@@ -45150,6 +45261,7 @@ var init_component_registry_generated = __esm({
45150
45261
  init_Table();
45151
45262
  init_Tabs();
45152
45263
  init_TagCloud();
45264
+ init_TagInput();
45153
45265
  init_TeamCard();
45154
45266
  init_TeamOrganism();
45155
45267
  init_TextHighlight();
@@ -45465,6 +45577,7 @@ var init_component_registry_generated = __esm({
45465
45577
  "Table": Table,
45466
45578
  "Tabs": Tabs,
45467
45579
  "TagCloud": TagCloud,
45580
+ "TagInput": TagInput,
45468
45581
  "TeamCard": TeamCard,
45469
45582
  "TeamOrganism": TeamOrganism,
45470
45583
  "TextHighlight": TextHighlight,