@almadar/ui 5.26.2 → 5.28.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.
Files changed (102) hide show
  1. package/dist/avl/index.cjs +2617 -2958
  2. package/dist/avl/index.js +1584 -1925
  3. package/dist/components/core/atoms/Avatar.d.ts +4 -4
  4. package/dist/components/core/atoms/Badge.d.ts +3 -2
  5. package/dist/components/core/atoms/Button.d.ts +7 -7
  6. package/dist/components/core/atoms/Card.d.ts +3 -0
  7. package/dist/components/core/atoms/Checkbox.d.ts +4 -1
  8. package/dist/components/core/atoms/FilterPill.d.ts +3 -2
  9. package/dist/components/core/atoms/Icon.d.ts +10 -1
  10. package/dist/components/core/atoms/Input.d.ts +9 -10
  11. package/dist/components/core/atoms/Select.d.ts +3 -1
  12. package/dist/components/core/atoms/Textarea.d.ts +3 -1
  13. package/dist/components/core/atoms/index.d.ts +1 -1
  14. package/dist/components/core/atoms/types.d.ts +2 -1
  15. package/dist/components/core/molecules/Breadcrumb.d.ts +3 -3
  16. package/dist/components/core/molecules/Card.d.ts +4 -3
  17. package/dist/components/core/molecules/Carousel.d.ts +2 -2
  18. package/dist/components/core/molecules/DataGrid.d.ts +5 -4
  19. package/dist/components/core/molecules/DataList.d.ts +7 -6
  20. package/dist/components/core/molecules/DocumentViewer.d.ts +3 -2
  21. package/dist/components/core/molecules/EmptyState.d.ts +2 -2
  22. package/dist/components/core/molecules/FloatingActionButton.d.ts +5 -5
  23. package/dist/components/core/molecules/FormSectionHeader.d.ts +3 -2
  24. package/dist/components/core/molecules/Header.d.ts +5 -4
  25. package/dist/components/core/molecules/JsonTreeEditor.d.ts +18 -0
  26. package/dist/components/core/molecules/Lightbox.d.ts +2 -1
  27. package/dist/components/core/molecules/Menu.d.ts +3 -3
  28. package/dist/components/core/molecules/Navigation.d.ts +2 -2
  29. package/dist/components/core/molecules/PageHeader.d.ts +2 -2
  30. package/dist/components/core/molecules/Sidebar.d.ts +5 -5
  31. package/dist/components/core/molecules/StatDisplay.d.ts +3 -2
  32. package/dist/components/core/molecules/SwipeableRow.d.ts +2 -1
  33. package/dist/components/core/molecules/TableView.d.ts +5 -4
  34. package/dist/components/core/molecules/Tabs.d.ts +2 -2
  35. package/dist/components/core/molecules/UploadDropZone.d.ts +3 -2
  36. package/dist/components/core/molecules/index.d.ts +1 -0
  37. package/dist/components/core/organisms/ComponentPatterns.d.ts +0 -306
  38. package/dist/components/core/organisms/CustomPattern.d.ts +3 -3
  39. package/dist/components/core/organisms/DataTable.d.ts +5 -5
  40. package/dist/components/core/organisms/DetailPanel.d.ts +3 -3
  41. package/dist/components/core/organisms/Form.d.ts +3 -2
  42. package/dist/components/core/organisms/LayoutPatterns.d.ts +0 -74
  43. package/dist/components/core/organisms/List.d.ts +4 -4
  44. package/dist/components/core/organisms/MediaGallery.d.ts +3 -3
  45. package/dist/components/core/organisms/StatCard.d.ts +4 -4
  46. package/dist/components/core/organisms/Timeline.d.ts +2 -2
  47. package/dist/components/core/templates/DashboardLayout.d.ts +6 -6
  48. package/dist/components/game/atoms/ActionButton.d.ts +2 -2
  49. package/dist/components/game/atoms/ControlButton.d.ts +2 -2
  50. package/dist/components/game/atoms/ItemSlot.d.ts +2 -2
  51. package/dist/components/game/atoms/ResourceCounter.d.ts +2 -2
  52. package/dist/components/game/atoms/ScoreDisplay.d.ts +2 -2
  53. package/dist/components/game/atoms/StateIndicator.d.ts +2 -1
  54. package/dist/components/game/atoms/StatusEffect.d.ts +3 -2
  55. package/dist/components/game/atoms/WaypointMarker.d.ts +2 -2
  56. package/dist/components/game/molecules/ActionButtons.d.ts +2 -8
  57. package/dist/components/game/molecules/CraftingRecipe.d.ts +3 -3
  58. package/dist/components/game/molecules/EnemyPlate.d.ts +2 -2
  59. package/dist/components/game/molecules/GameCanvas2D.d.ts +3 -2
  60. package/dist/components/game/molecules/GameHud.d.ts +3 -2
  61. package/dist/components/game/molecules/GameOverScreen.d.ts +2 -2
  62. package/dist/components/game/molecules/HealthPanel.d.ts +2 -2
  63. package/dist/components/game/molecules/InventoryGrid.d.ts +2 -2
  64. package/dist/components/game/molecules/IsometricCanvas.d.ts +4 -4
  65. package/dist/components/game/molecules/PlatformerCanvas.d.ts +5 -5
  66. package/dist/components/game/molecules/PowerupSlots.d.ts +2 -2
  67. package/dist/components/game/molecules/ResourceBar.d.ts +2 -2
  68. package/dist/components/game/molecules/StatBadge.d.ts +2 -2
  69. package/dist/components/game/molecules/TurnPanel.d.ts +2 -2
  70. package/dist/components/game/molecules/UnitCommandBar.d.ts +2 -2
  71. package/dist/components/game/organisms/BattleBoard.d.ts +2 -2
  72. package/dist/components/game/organisms/CanvasEffect.d.ts +3 -3
  73. package/dist/components/game/organisms/TraitSlot.d.ts +3 -3
  74. package/dist/components/game/organisms/WorldMapBoard.d.ts +2 -2
  75. package/dist/components/game/organisms/puzzles/builder/BuilderBoard.d.ts +2 -2
  76. package/dist/components/game/organisms/puzzles/classifier/ClassifierBoard.d.ts +3 -3
  77. package/dist/components/game/organisms/types/effects.d.ts +8 -7
  78. package/dist/components/game/organisms/types/isometric.d.ts +5 -4
  79. package/dist/components/game/organisms/types/spriteAnimation.d.ts +4 -3
  80. package/dist/components/game/organisms/useCanvasEffects.d.ts +2 -1
  81. package/dist/components/index.cjs +2728 -2822
  82. package/dist/components/index.js +1851 -1945
  83. package/dist/components/marketing/atoms/AnimatedGraphic.d.ts +2 -1
  84. package/dist/components/marketing/molecules/FeatureCard.d.ts +2 -2
  85. package/dist/components/marketing/molecules/MarketingFooter.d.ts +2 -1
  86. package/dist/components/marketing/molecules/StepFlow.d.ts +2 -1
  87. package/dist/components/marketing/molecules/TeamCard.d.ts +2 -1
  88. package/dist/components/marketing/organisms/book/BookCoverPage.d.ts +2 -1
  89. package/dist/components/marketing/templates/AboutPageTemplate.d.ts +2 -1
  90. package/dist/components/marketing/templates/AuthLayout.d.ts +2 -1
  91. package/dist/components/marketing/templates/LandingPageTemplate.d.ts +3 -2
  92. package/dist/docs/index.cjs +54 -11
  93. package/dist/docs/index.d.cts +48 -37
  94. package/dist/docs/index.js +54 -11
  95. package/dist/marketing/index.cjs +27 -13
  96. package/dist/marketing/index.d.cts +72 -61
  97. package/dist/marketing/index.js +27 -13
  98. package/dist/providers/index.cjs +2444 -2785
  99. package/dist/providers/index.js +1562 -1903
  100. package/dist/runtime/index.cjs +2482 -2823
  101. package/dist/runtime/index.js +1564 -1905
  102. package/package.json +2 -2
@@ -1,10 +1,11 @@
1
1
  import React from 'react';
2
+ import type { AssetUrl } from '@almadar/core';
2
3
  export type GraphicAnimation = 'draw' | 'fill' | 'pulse' | 'morph';
3
4
  export interface AnimatedGraphicProps extends React.HTMLAttributes<HTMLDivElement> {
4
5
  /** Additional CSS classes applied to the root element. */
5
6
  className?: string;
6
7
  /** URL to an SVG file. Fetched and inlined to enable stroke/fill animations. */
7
- src?: string;
8
+ src?: AssetUrl;
8
9
  /** Inline SVG string. Takes precedence over src if both provided. */
9
10
  svgContent?: string;
10
11
  /** Animation type applied to SVG paths/shapes */
@@ -5,9 +5,9 @@
5
5
  * Composes Card, VStack, Icon, Typography, and Button atoms.
6
6
  */
7
7
  import React from 'react';
8
+ import { type IconInput } from '../../core/atoms/Icon';
8
9
  export interface FeatureCardProps {
9
- /** Icon name (Lucide string) or ReactNode */
10
- icon?: string | React.ReactNode;
10
+ icon?: IconInput;
11
11
  /** Feature title */
12
12
  title: string;
13
13
  /** Feature description */
@@ -6,6 +6,7 @@
6
6
  * Uses @almadar/ui theme CSS variables for consistent branding.
7
7
  */
8
8
  import React from 'react';
9
+ import type { AssetUrl } from '@almadar/core';
9
10
  export interface FooterLinkItem {
10
11
  label: string;
11
12
  href: string;
@@ -15,7 +16,7 @@ export interface FooterLinkColumn {
15
16
  items: FooterLinkItem[];
16
17
  }
17
18
  export interface FooterLogo {
18
- src: string;
19
+ src: AssetUrl;
19
20
  alt: string;
20
21
  href?: string;
21
22
  }
@@ -5,11 +5,12 @@
5
5
  * Composes Center, Typography, Icon, HStack, VStack, Box, and Divider atoms.
6
6
  */
7
7
  import React from 'react';
8
+ import { type IconInput } from '../../core/atoms/Icon';
8
9
  export interface StepItemProps {
9
10
  number?: number;
10
11
  title: string;
11
12
  description: string;
12
- icon?: string;
13
+ icon?: IconInput;
13
14
  }
14
15
  export interface StepFlowProps {
15
16
  steps: StepItemProps[];
@@ -5,12 +5,13 @@
5
5
  * Composes Card, VStack, Avatar, and Typography atoms.
6
6
  */
7
7
  import React from 'react';
8
+ import type { AssetUrl } from '@almadar/core';
8
9
  export interface TeamCardProps {
9
10
  name: string;
10
11
  nameAr?: string;
11
12
  role: string;
12
13
  bio: string;
13
- avatar?: string | {
14
+ avatar?: AssetUrl | {
14
15
  initials: string;
15
16
  };
16
17
  className?: string;
@@ -8,13 +8,14 @@
8
8
  * - Emits: UI:BOOK_START
9
9
  */
10
10
  import React from 'react';
11
+ import type { AssetUrl } from '@almadar/core';
11
12
  export interface BookCoverPageProps {
12
13
  /** Additional CSS classes */
13
14
  className?: string;
14
15
  title: string;
15
16
  subtitle?: string;
16
17
  author?: string;
17
- coverImageUrl?: string;
18
+ coverImageUrl?: AssetUrl;
18
19
  direction?: 'rtl' | 'ltr';
19
20
  }
20
21
  export declare const BookCoverPage: React.FC<BookCoverPageProps>;
@@ -5,6 +5,7 @@
5
5
  * Pure function: no hooks, no callbacks, no local state.
6
6
  */
7
7
  import React from 'react';
8
+ import type { AssetUrl } from '@almadar/core';
8
9
  import type { TemplateProps } from '../../core/templates/types';
9
10
  import type { LinkAction } from '../../core/atoms/types';
10
11
  interface AboutHero {
@@ -23,7 +24,7 @@ interface TeamMemberContent {
23
24
  nameAr?: string;
24
25
  role: string;
25
26
  bio: string;
26
- avatar?: string;
27
+ avatar?: AssetUrl;
27
28
  }
28
29
  interface CaseStudyContent {
29
30
  id: string;
@@ -1,11 +1,12 @@
1
1
  import React from "react";
2
+ import type { AssetUrl } from "@almadar/core";
2
3
  export interface AuthLayoutProps {
3
4
  /** App name */
4
5
  appName?: string;
5
6
  /** Logo component or URL */
6
7
  logo?: React.ReactNode;
7
8
  /** Background image URL */
8
- backgroundImage?: string;
9
+ backgroundImage?: AssetUrl;
9
10
  /** Show branding panel on the side */
10
11
  showBranding?: boolean;
11
12
  /** Branding panel content */
@@ -6,6 +6,7 @@
6
6
  * Pure function: no hooks, no callbacks, no local state.
7
7
  */
8
8
  import React from 'react';
9
+ import type { IconInput } from '../../core/atoms/Icon';
9
10
  import type { TemplateProps } from '../../core/templates/types';
10
11
  import type { LinkAction, ImageSource } from '../../core/atoms/types';
11
12
  interface MarketingHero {
@@ -23,7 +24,7 @@ interface MarketingHero {
23
24
  }
24
25
  interface FeatureContent {
25
26
  id?: string;
26
- icon?: string;
27
+ icon?: IconInput;
27
28
  title: string;
28
29
  description: string;
29
30
  href?: string;
@@ -37,7 +38,7 @@ interface StepContent {
37
38
  id?: string;
38
39
  title: string;
39
40
  description: string;
40
- icon?: string;
41
+ icon?: IconInput;
41
42
  }
42
43
  interface ShowcaseContent {
43
44
  id: string;
@@ -4056,6 +4056,7 @@ var variantStyles3, paddingStyles2, shadowStyles2, lookStyles; exports.Card = vo
4056
4056
  var init_Card = __esm({
4057
4057
  "components/core/atoms/Card.tsx"() {
4058
4058
  init_cn();
4059
+ init_useEventBus();
4059
4060
  variantStyles3 = {
4060
4061
  default: [
4061
4062
  "bg-card",
@@ -4119,8 +4120,15 @@ var init_Card = __esm({
4119
4120
  shadow,
4120
4121
  look = "elevated",
4121
4122
  children,
4123
+ action,
4124
+ onClick,
4122
4125
  ...props
4123
4126
  }, ref) => {
4127
+ const eventBus = useEventBus();
4128
+ const handleClick = action ? (e) => {
4129
+ eventBus.emit(`UI:${action}`, {});
4130
+ onClick?.(e);
4131
+ } : onClick;
4124
4132
  return /* @__PURE__ */ jsxRuntime.jsxs(
4125
4133
  "div",
4126
4134
  {
@@ -4134,6 +4142,7 @@ var init_Card = __esm({
4134
4142
  shadow && shadowStyles2[shadow],
4135
4143
  className
4136
4144
  ),
4145
+ onClick: handleClick,
4137
4146
  ...props,
4138
4147
  children: [
4139
4148
  (title || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4", children: [
@@ -4764,6 +4773,7 @@ var init_Input = __esm({
4764
4773
  init_cn();
4765
4774
  init_Icon();
4766
4775
  init_useTranslate();
4776
+ init_useEventBus();
4767
4777
  exports.Input = React7__default.default.forwardRef(
4768
4778
  ({
4769
4779
  className,
@@ -4782,9 +4792,17 @@ var init_Input = __esm({
4782
4792
  ...props
4783
4793
  }, ref) => {
4784
4794
  const { t } = useTranslate();
4795
+ const eventBus = useEventBus();
4785
4796
  const type = inputType || htmlType || "text";
4797
+ const resolveIconNode = (i, cls) => {
4798
+ if (!i) return null;
4799
+ if (typeof i === "string") return /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: i, className: cls });
4800
+ const C = i;
4801
+ return /* @__PURE__ */ jsxRuntime.jsx(C, { className: cls });
4802
+ };
4803
+ const iconCls = "h-icon-default w-icon-default";
4786
4804
  const IconComponent = typeof iconProp === "string" ? resolveIcon(iconProp) : iconProp;
4787
- const resolvedLeftIcon = leftIcon || IconComponent && /* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: "h-icon-default w-icon-default" });
4805
+ const resolvedLeftIcon = (leftIcon ? resolveIconNode(leftIcon, iconCls) : null) || IconComponent && /* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: iconCls });
4788
4806
  const showClearButton = clearable && value && String(value).length > 0;
4789
4807
  const isMultiline = type === "textarea";
4790
4808
  const baseClassName = cn(
@@ -4800,6 +4818,22 @@ var init_Input = __esm({
4800
4818
  (rightIcon || showClearButton) && "pr-10",
4801
4819
  className
4802
4820
  );
4821
+ const handleChange = (e) => {
4822
+ if (typeof onChange === "string") {
4823
+ const target = e.target;
4824
+ const payload = type === "checkbox" ? { checked: target.checked } : { value: target.value };
4825
+ eventBus.emit(`UI:${onChange}`, payload);
4826
+ } else {
4827
+ onChange?.(e);
4828
+ }
4829
+ };
4830
+ const handleClear = () => {
4831
+ if (typeof onClear === "string") {
4832
+ eventBus.emit(`UI:${onClear}`, {});
4833
+ } else {
4834
+ onClear?.();
4835
+ }
4836
+ };
4803
4837
  if (type === "select") {
4804
4838
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full", children: [
4805
4839
  resolvedLeftIcon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none text-muted-foreground", children: resolvedLeftIcon }),
@@ -4808,7 +4842,7 @@ var init_Input = __esm({
4808
4842
  {
4809
4843
  ref,
4810
4844
  value,
4811
- onChange,
4845
+ onChange: handleChange,
4812
4846
  className: cn(baseClassName, "appearance-none pr-10", className),
4813
4847
  ...props,
4814
4848
  children: [
@@ -4826,7 +4860,7 @@ var init_Input = __esm({
4826
4860
  {
4827
4861
  ref,
4828
4862
  value,
4829
- onChange,
4863
+ onChange: handleChange,
4830
4864
  rows,
4831
4865
  className: baseClassName,
4832
4866
  ...props
@@ -4840,7 +4874,7 @@ var init_Input = __esm({
4840
4874
  ref,
4841
4875
  type: "checkbox",
4842
4876
  checked: props.checked,
4843
- onChange,
4877
+ onChange: handleChange,
4844
4878
  className: cn(
4845
4879
  "h-icon-default w-icon-default rounded-sm",
4846
4880
  "border-border",
@@ -4860,7 +4894,7 @@ var init_Input = __esm({
4860
4894
  ref,
4861
4895
  type,
4862
4896
  value,
4863
- onChange,
4897
+ onChange: handleChange,
4864
4898
  className: baseClassName,
4865
4899
  ...props
4866
4900
  }
@@ -4869,12 +4903,12 @@ var init_Input = __esm({
4869
4903
  "button",
4870
4904
  {
4871
4905
  type: "button",
4872
- onClick: onClear,
4906
+ onClick: handleClear,
4873
4907
  className: "absolute inset-y-0 right-0 pr-3 flex items-center text-muted-foreground hover:text-foreground",
4874
4908
  children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "x", className: "h-icon-default w-icon-default" })
4875
4909
  }
4876
4910
  ),
4877
- rightIcon && !showClearButton && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center text-muted-foreground", children: rightIcon })
4911
+ rightIcon && !showClearButton && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center text-muted-foreground", children: resolveIconNode(rightIcon, iconCls) })
4878
4912
  ] });
4879
4913
  }
4880
4914
  );
@@ -5131,12 +5165,22 @@ var Textarea;
5131
5165
  var init_Textarea = __esm({
5132
5166
  "components/core/atoms/Textarea.tsx"() {
5133
5167
  init_cn();
5168
+ init_useEventBus();
5134
5169
  Textarea = React7__default.default.forwardRef(
5135
- ({ className, error, ...props }, ref) => {
5170
+ ({ className, error, onChange, ...props }, ref) => {
5171
+ const eventBus = useEventBus();
5172
+ const handleChange = (e) => {
5173
+ if (typeof onChange === "string") {
5174
+ eventBus.emit(`UI:${onChange}`, { value: e.target.value });
5175
+ } else {
5176
+ onChange?.(e);
5177
+ }
5178
+ };
5136
5179
  return /* @__PURE__ */ jsxRuntime.jsx(
5137
5180
  "textarea",
5138
5181
  {
5139
5182
  ref,
5183
+ onChange: handleChange,
5140
5184
  className: cn(
5141
5185
  "block w-full border-[length:var(--border-width)] shadow-sm",
5142
5186
  "px-3 py-2 text-sm text-foreground",
@@ -5205,7 +5249,7 @@ var init_Badge = __esm({
5205
5249
  md: "h-icon-default w-icon-default",
5206
5250
  lg: "h-icon-default w-icon-default"
5207
5251
  };
5208
- const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: icon, className: iconSizes[size] }) : icon;
5252
+ const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: icon, className: iconSizes[size] }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { icon, className: iconSizes[size] }) : null;
5209
5253
  return /* @__PURE__ */ jsxRuntime.jsxs(
5210
5254
  "span",
5211
5255
  {
@@ -6604,7 +6648,7 @@ function DocSearch({
6604
6648
  onChange: handleChange,
6605
6649
  onFocus: handleFocus,
6606
6650
  onKeyDown: handleKeyDown,
6607
- leftIcon: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "search", size: "sm", className: "text-muted-foreground" }),
6651
+ leftIcon: "search",
6608
6652
  clearable: query.length > 0,
6609
6653
  onClear: () => {
6610
6654
  setQuery("");
@@ -6662,7 +6706,6 @@ var init_DocSearch = __esm({
6662
6706
  init_Stack();
6663
6707
  init_Stack();
6664
6708
  init_Typography();
6665
- init_Icon();
6666
6709
  init_Input();
6667
6710
  init_useTranslate();
6668
6711
  }
@@ -168,36 +168,10 @@ interface TypographyProps {
168
168
  }
169
169
  declare const Typography: React.FC<TypographyProps>;
170
170
 
171
- type ButtonVariant = "primary" | "secondary" | "ghost" | "danger" | "success" | "warning" | "default";
172
- type ButtonSize = "sm" | "md" | "lg";
173
- interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
174
- /** Additional CSS classes applied to the root element. */
175
- className?: string;
176
- variant?: ButtonVariant;
177
- size?: ButtonSize;
178
- isLoading?: boolean;
179
- /** Left icon as ReactNode, Lucide component, or string name (e.g. "plus", "trash") */
180
- leftIcon?: React.ReactNode | LucideIcon | string;
181
- /** Right icon as ReactNode, Lucide component, or string name */
182
- rightIcon?: React.ReactNode | LucideIcon | string;
183
- /** Alias for leftIcon */
184
- icon?: React.ReactNode | LucideIcon | string;
185
- /** Alias for rightIcon */
186
- iconRight?: React.ReactNode | LucideIcon | string;
187
- /** Declarative event name — emits UI:{action} via eventBus on click */
188
- action?: EventKey;
189
- /** Payload to include with the action event */
190
- actionPayload?: EventPayload;
191
- /** Button label text (alternative to children for schema-driven rendering) */
192
- label?: string;
193
- /** Disable the button (greys out, blocks click events) */
194
- disabled?: boolean;
195
- }
196
- declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
197
-
198
171
  /**
199
172
  * Cross-cutting atom-level prop shapes shared across the design system.
200
173
  */
174
+
201
175
  /**
202
176
  * Canonical semantic color palette. Values are the Tailwind / CSS-var token
203
177
  * names that every component in the design system understands. Prefer this
@@ -234,13 +208,22 @@ type UiError = {
234
208
  type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
235
209
  type IconAnimation = 'spin' | 'pulse' | 'none';
236
210
 
211
+ /**
212
+ * Canonical icon-input type: a Lucide component reference OR a canonical
213
+ * kebab-case icon name string. The single source of truth for every
214
+ * icon-bearing prop across `@almadar/ui` — pattern-sync's parser maps this
215
+ * union to the `icon` config type, so the factory inspector renders an
216
+ * IconPicker and a string name resolves via `resolveIcon`. Never declare an
217
+ * icon prop as `React.ReactNode` (it collapses to a non-editable `node`).
218
+ */
219
+ type IconInput = LucideIcon | string;
237
220
  interface IconProps {
238
221
  /**
239
222
  * Lucide icon component (preferred for type-safe usage), OR a canonical
240
223
  * kebab-case icon name string — a string is treated exactly like `name` so
241
224
  * trait/factory authors can pass an icon by name through the `icon` prop.
242
225
  */
243
- icon?: LucideIcon | string;
226
+ icon?: IconInput;
244
227
  /** Icon name as string (resolved from iconMap) */
245
228
  name?: string;
246
229
  /** Size of the icon */
@@ -258,6 +241,33 @@ interface IconProps {
258
241
  }
259
242
  declare const Icon: React.FC<IconProps>;
260
243
 
244
+ type ButtonVariant = "primary" | "secondary" | "ghost" | "danger" | "success" | "warning" | "default";
245
+ type ButtonSize = "sm" | "md" | "lg";
246
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
247
+ /** Additional CSS classes applied to the root element. */
248
+ className?: string;
249
+ variant?: ButtonVariant;
250
+ size?: ButtonSize;
251
+ isLoading?: boolean;
252
+ /** Left icon: a Lucide component or a canonical icon name string (e.g. "plus", "trash"). */
253
+ leftIcon?: IconInput;
254
+ /** Right icon: a Lucide component or a canonical icon name string. */
255
+ rightIcon?: IconInput;
256
+ /** Alias for leftIcon */
257
+ icon?: IconInput;
258
+ /** Alias for rightIcon */
259
+ iconRight?: IconInput;
260
+ /** Declarative event name — emits UI:{action} via eventBus on click */
261
+ action?: EventKey;
262
+ /** Payload to include with the action event */
263
+ actionPayload?: EventPayload;
264
+ /** Button label text (alternative to children for schema-driven rendering) */
265
+ label?: string;
266
+ /** Disable the button (greys out, blocks click events) */
267
+ disabled?: boolean;
268
+ }
269
+ declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
270
+
261
271
  type CardShadow = "none" | "sm" | "md" | "lg";
262
272
  /**
263
273
  * Layer 2 visual treatment for the card pattern — orthogonal to the semantic
@@ -279,6 +289,8 @@ interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
279
289
  look?: CardLook;
280
290
  /** Card content */
281
291
  children?: React.ReactNode;
292
+ /** Declarative event key emitted on click for trait dispatch */
293
+ action?: EventKey;
282
294
  }
283
295
  declare const Card: React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>>;
284
296
 
@@ -330,21 +342,20 @@ interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "
330
342
  /** Input type - supports 'select' and 'textarea' in addition to standard types */
331
343
  inputType?: "text" | "email" | "password" | "number" | "tel" | "url" | "search" | "date" | "datetime-local" | "time" | "checkbox" | "select" | "textarea";
332
344
  error?: string;
333
- leftIcon?: React.ReactNode;
334
- rightIcon?: React.ReactNode;
335
- /** Lucide icon component for left side (convenience prop), or a canonical
336
- * kebab-case icon name string (resolved via `resolveIcon`). */
337
- icon?: LucideIcon | string;
345
+ leftIcon?: IconInput;
346
+ rightIcon?: IconInput;
347
+ /** Lucide icon component or canonical kebab-case icon name string for left side */
348
+ icon?: IconInput;
338
349
  /** Show clear button when input has value */
339
350
  clearable?: boolean;
340
- /** Callback when clear button is clicked */
341
- onClear?: () => void;
351
+ /** Callback or declarative event key when clear button is clicked */
352
+ onClear?: (() => void) | EventKey;
342
353
  /** Options for select type */
343
354
  options?: SelectOption[];
344
355
  /** Rows for textarea type */
345
356
  rows?: number;
346
- /** onChange handler - accepts events from input, select, or textarea */
347
- onChange?: React.ChangeEventHandler<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>;
357
+ /** onChange handler or declarative event key for trait dispatch */
358
+ onChange?: React.ChangeEventHandler<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement> | EventKey;
348
359
  }
349
360
  declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLSelectElement | HTMLInputElement | HTMLTextAreaElement>>;
350
361
 
@@ -4011,6 +4011,7 @@ var variantStyles3, paddingStyles2, shadowStyles2, lookStyles, Card, CardHeader,
4011
4011
  var init_Card = __esm({
4012
4012
  "components/core/atoms/Card.tsx"() {
4013
4013
  init_cn();
4014
+ init_useEventBus();
4014
4015
  variantStyles3 = {
4015
4016
  default: [
4016
4017
  "bg-card",
@@ -4074,8 +4075,15 @@ var init_Card = __esm({
4074
4075
  shadow,
4075
4076
  look = "elevated",
4076
4077
  children,
4078
+ action,
4079
+ onClick,
4077
4080
  ...props
4078
4081
  }, ref) => {
4082
+ const eventBus = useEventBus();
4083
+ const handleClick = action ? (e) => {
4084
+ eventBus.emit(`UI:${action}`, {});
4085
+ onClick?.(e);
4086
+ } : onClick;
4079
4087
  return /* @__PURE__ */ jsxs(
4080
4088
  "div",
4081
4089
  {
@@ -4089,6 +4097,7 @@ var init_Card = __esm({
4089
4097
  shadow && shadowStyles2[shadow],
4090
4098
  className
4091
4099
  ),
4100
+ onClick: handleClick,
4092
4101
  ...props,
4093
4102
  children: [
4094
4103
  (title || subtitle) && /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
@@ -4719,6 +4728,7 @@ var init_Input = __esm({
4719
4728
  init_cn();
4720
4729
  init_Icon();
4721
4730
  init_useTranslate();
4731
+ init_useEventBus();
4722
4732
  Input = React7.forwardRef(
4723
4733
  ({
4724
4734
  className,
@@ -4737,9 +4747,17 @@ var init_Input = __esm({
4737
4747
  ...props
4738
4748
  }, ref) => {
4739
4749
  const { t } = useTranslate();
4750
+ const eventBus = useEventBus();
4740
4751
  const type = inputType || htmlType || "text";
4752
+ const resolveIconNode = (i, cls) => {
4753
+ if (!i) return null;
4754
+ if (typeof i === "string") return /* @__PURE__ */ jsx(Icon, { name: i, className: cls });
4755
+ const C = i;
4756
+ return /* @__PURE__ */ jsx(C, { className: cls });
4757
+ };
4758
+ const iconCls = "h-icon-default w-icon-default";
4741
4759
  const IconComponent = typeof iconProp === "string" ? resolveIcon(iconProp) : iconProp;
4742
- const resolvedLeftIcon = leftIcon || IconComponent && /* @__PURE__ */ jsx(IconComponent, { className: "h-icon-default w-icon-default" });
4760
+ const resolvedLeftIcon = (leftIcon ? resolveIconNode(leftIcon, iconCls) : null) || IconComponent && /* @__PURE__ */ jsx(IconComponent, { className: iconCls });
4743
4761
  const showClearButton = clearable && value && String(value).length > 0;
4744
4762
  const isMultiline = type === "textarea";
4745
4763
  const baseClassName = cn(
@@ -4755,6 +4773,22 @@ var init_Input = __esm({
4755
4773
  (rightIcon || showClearButton) && "pr-10",
4756
4774
  className
4757
4775
  );
4776
+ const handleChange = (e) => {
4777
+ if (typeof onChange === "string") {
4778
+ const target = e.target;
4779
+ const payload = type === "checkbox" ? { checked: target.checked } : { value: target.value };
4780
+ eventBus.emit(`UI:${onChange}`, payload);
4781
+ } else {
4782
+ onChange?.(e);
4783
+ }
4784
+ };
4785
+ const handleClear = () => {
4786
+ if (typeof onClear === "string") {
4787
+ eventBus.emit(`UI:${onClear}`, {});
4788
+ } else {
4789
+ onClear?.();
4790
+ }
4791
+ };
4758
4792
  if (type === "select") {
4759
4793
  return /* @__PURE__ */ jsxs("div", { className: "relative w-full", children: [
4760
4794
  resolvedLeftIcon && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none text-muted-foreground", children: resolvedLeftIcon }),
@@ -4763,7 +4797,7 @@ var init_Input = __esm({
4763
4797
  {
4764
4798
  ref,
4765
4799
  value,
4766
- onChange,
4800
+ onChange: handleChange,
4767
4801
  className: cn(baseClassName, "appearance-none pr-10", className),
4768
4802
  ...props,
4769
4803
  children: [
@@ -4781,7 +4815,7 @@ var init_Input = __esm({
4781
4815
  {
4782
4816
  ref,
4783
4817
  value,
4784
- onChange,
4818
+ onChange: handleChange,
4785
4819
  rows,
4786
4820
  className: baseClassName,
4787
4821
  ...props
@@ -4795,7 +4829,7 @@ var init_Input = __esm({
4795
4829
  ref,
4796
4830
  type: "checkbox",
4797
4831
  checked: props.checked,
4798
- onChange,
4832
+ onChange: handleChange,
4799
4833
  className: cn(
4800
4834
  "h-icon-default w-icon-default rounded-sm",
4801
4835
  "border-border",
@@ -4815,7 +4849,7 @@ var init_Input = __esm({
4815
4849
  ref,
4816
4850
  type,
4817
4851
  value,
4818
- onChange,
4852
+ onChange: handleChange,
4819
4853
  className: baseClassName,
4820
4854
  ...props
4821
4855
  }
@@ -4824,12 +4858,12 @@ var init_Input = __esm({
4824
4858
  "button",
4825
4859
  {
4826
4860
  type: "button",
4827
- onClick: onClear,
4861
+ onClick: handleClear,
4828
4862
  className: "absolute inset-y-0 right-0 pr-3 flex items-center text-muted-foreground hover:text-foreground",
4829
4863
  children: /* @__PURE__ */ jsx(Icon, { name: "x", className: "h-icon-default w-icon-default" })
4830
4864
  }
4831
4865
  ),
4832
- rightIcon && !showClearButton && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center text-muted-foreground", children: rightIcon })
4866
+ rightIcon && !showClearButton && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center text-muted-foreground", children: resolveIconNode(rightIcon, iconCls) })
4833
4867
  ] });
4834
4868
  }
4835
4869
  );
@@ -5086,12 +5120,22 @@ var Textarea;
5086
5120
  var init_Textarea = __esm({
5087
5121
  "components/core/atoms/Textarea.tsx"() {
5088
5122
  init_cn();
5123
+ init_useEventBus();
5089
5124
  Textarea = React7.forwardRef(
5090
- ({ className, error, ...props }, ref) => {
5125
+ ({ className, error, onChange, ...props }, ref) => {
5126
+ const eventBus = useEventBus();
5127
+ const handleChange = (e) => {
5128
+ if (typeof onChange === "string") {
5129
+ eventBus.emit(`UI:${onChange}`, { value: e.target.value });
5130
+ } else {
5131
+ onChange?.(e);
5132
+ }
5133
+ };
5091
5134
  return /* @__PURE__ */ jsx(
5092
5135
  "textarea",
5093
5136
  {
5094
5137
  ref,
5138
+ onChange: handleChange,
5095
5139
  className: cn(
5096
5140
  "block w-full border-[length:var(--border-width)] shadow-sm",
5097
5141
  "px-3 py-2 text-sm text-foreground",
@@ -5160,7 +5204,7 @@ var init_Badge = __esm({
5160
5204
  md: "h-icon-default w-icon-default",
5161
5205
  lg: "h-icon-default w-icon-default"
5162
5206
  };
5163
- const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, className: iconSizes[size] }) : icon;
5207
+ const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, className: iconSizes[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes[size] }) : null;
5164
5208
  return /* @__PURE__ */ jsxs(
5165
5209
  "span",
5166
5210
  {
@@ -6559,7 +6603,7 @@ function DocSearch({
6559
6603
  onChange: handleChange,
6560
6604
  onFocus: handleFocus,
6561
6605
  onKeyDown: handleKeyDown,
6562
- leftIcon: /* @__PURE__ */ jsx(Icon, { name: "search", size: "sm", className: "text-muted-foreground" }),
6606
+ leftIcon: "search",
6563
6607
  clearable: query.length > 0,
6564
6608
  onClear: () => {
6565
6609
  setQuery("");
@@ -6617,7 +6661,6 @@ var init_DocSearch = __esm({
6617
6661
  init_Stack();
6618
6662
  init_Stack();
6619
6663
  init_Typography();
6620
- init_Icon();
6621
6664
  init_Input();
6622
6665
  init_useTranslate();
6623
6666
  }