@dimaan/ui 0.0.0 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
- import { HTMLAttributes, ReactNode, ReactElement, ButtonHTMLAttributes, InputHTMLAttributes, ChangeEvent, AnchorHTMLAttributes, Ref } from 'react';
3
+ import { HTMLAttributes, ReactNode, ReactElement, ButtonHTMLAttributes, InputHTMLAttributes, ChangeEvent, FieldsetHTMLAttributes, AnchorHTMLAttributes, Ref } from 'react';
4
4
  import { ClassValue } from 'clsx';
5
5
 
6
6
  interface DashboardLayoutContextValue {
@@ -34,7 +34,8 @@ type RenderLink = (props: {
34
34
  'aria-current'?: 'page';
35
35
  }) => ReactElement;
36
36
  interface AppShellNavItem {
37
- key: string;
37
+ /** Optional stable key. Falls back to array index if omitted — only safe for static nav. */
38
+ key?: string;
38
39
  label: ReactNode;
39
40
  href?: string;
40
41
  icon?: ReactNode;
@@ -44,18 +45,14 @@ interface AppShellNavItem {
44
45
  render?: RenderLink;
45
46
  }
46
47
  interface AppShellNavGroup {
47
- key: string;
48
+ /** Optional stable key. Falls back to array index if omitted — only safe for static nav. */
49
+ key?: string;
48
50
  label: ReactNode;
49
51
  icon?: ReactNode;
50
52
  active?: boolean;
51
53
  defaultOpen?: boolean;
52
54
  items: AppShellNavItem[];
53
55
  }
54
- interface AppShellNavSection {
55
- key: string;
56
- label?: ReactNode;
57
- items: Array<AppShellNavItem | AppShellNavGroup>;
58
- }
59
56
  interface AppShellBrand {
60
57
  logo?: ReactNode;
61
58
  name?: ReactNode;
@@ -63,8 +60,12 @@ interface AppShellBrand {
63
60
  }
64
61
  interface AppShellProps extends Pick<DashboardLayoutProps, 'defaultCollapsed' | 'collapsed' | 'onCollapsedChange'> {
65
62
  brand?: AppShellBrand;
66
- /** Either a flat list of items, or grouped sections. */
67
- nav: AppShellNavSection[] | Array<AppShellNavItem | AppShellNavGroup>;
63
+ /**
64
+ * Flat list of nav entries: leaf items (with `href` or `render`) and/or
65
+ * collapsible groups (with `items`). For more advanced layouts (sections,
66
+ * dividers, custom structure), compose `Sidebar` + `SidebarNav` directly.
67
+ */
68
+ nav: Array<AppShellNavItem | AppShellNavGroup>;
68
69
  title?: ReactNode;
69
70
  searchPlaceholder?: string;
70
71
  onSearch?: (value: string) => void;
@@ -150,6 +151,47 @@ declare const HeaderSearch: react.ForwardRefExoticComponent<HeaderSearchProps &
150
151
  type HeaderTitleProps = HTMLAttributes<HTMLDivElement>;
151
152
  declare function HeaderTitle({ className, children, ...props }: HeaderTitleProps): react_jsx_runtime.JSX.Element;
152
153
 
154
+ type InputVariant = 'default' | 'filled' | 'ghost';
155
+ type InputSize = 'sm' | 'md' | 'lg';
156
+ declare const inputVariantClass: Record<InputVariant, string>;
157
+ declare const inputSizeClass: Record<InputSize, string>;
158
+ declare const inputBaseClass = "group/input relative inline-flex w-full items-center text-foreground outline-none transition-[background-color,border-color,box-shadow] focus-within:ring-2 focus-within:ring-ring/40 focus-within:ring-offset-1 focus-within:ring-offset-background aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-within:ring-destructive/40 has-[input:disabled]:pointer-events-none has-[input:disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0";
159
+
160
+ interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix'> {
161
+ variant?: InputVariant;
162
+ inputSize?: InputSize;
163
+ /** Optional label rendered above the field. */
164
+ label?: ReactNode;
165
+ /** Helper text rendered under the field when not in an error state. */
166
+ helperText?: ReactNode;
167
+ /** Error message — renders in destructive style and sets aria-invalid. */
168
+ error?: ReactNode;
169
+ /** Element rendered before the input (icon, prefix text, etc.). */
170
+ leadingIcon?: ReactNode;
171
+ /** Element rendered after the input (icon, suffix text, etc.). */
172
+ trailingIcon?: ReactNode;
173
+ /** Stretch the wrapper to fill the parent's inline width. Defaults to `true`. */
174
+ fullWidth?: boolean;
175
+ /** Class applied to the outer wrapper that holds the icons + input. */
176
+ wrapperClassName?: string;
177
+ /** Class applied to the field container (`<label>` block). */
178
+ containerClassName?: string;
179
+ }
180
+ declare const Input: react.ForwardRefExoticComponent<InputProps & react.RefAttributes<HTMLInputElement>>;
181
+
182
+ interface LanguageOption<TCode extends string = string> {
183
+ code: TCode;
184
+ label?: string;
185
+ }
186
+ interface LanguageSwitcherProps<TCode extends string = string> extends Omit<FieldsetHTMLAttributes<HTMLFieldSetElement>, 'onChange'> {
187
+ languages: ReadonlyArray<LanguageOption<TCode>>;
188
+ value: TCode;
189
+ onChange: (next: TCode) => void;
190
+ /** Accessible label for the group. Defaults to "Language". */
191
+ ariaLabel?: string;
192
+ }
193
+ declare function LanguageSwitcher<TCode extends string = string>({ languages, value, onChange, ariaLabel, className, ...props }: LanguageSwitcherProps<TCode>): react_jsx_runtime.JSX.Element;
194
+
153
195
  type SidebarProps = HTMLAttributes<HTMLElement>;
154
196
  declare function Sidebar({ className, children, ...props }: SidebarProps): react_jsx_runtime.JSX.Element;
155
197
 
@@ -318,4 +360,4 @@ declare function useDirection(): Direction;
318
360
 
319
361
  declare function cn(...inputs: ClassValue[]): string;
320
362
 
321
- export { AppShell, type AppShellBrand, type AppShellNavGroup, type AppShellNavItem, type AppShellNavSection, type AppShellProps, Avatar, type AvatarProps, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Checkbox, type CheckboxProps, type CheckboxSize, type Column, type ColumnAlign, DashboardContent, type DashboardContentProps, DashboardHeader, type DashboardHeaderProps, DashboardLayout, type DashboardLayoutContextValue, type DashboardLayoutProps, DashboardMain, type DashboardMainProps, type Direction, HeaderActions, type HeaderActionsProps, HeaderCollapseTrigger, type HeaderCollapseTriggerProps, HeaderMobileTrigger, type HeaderMobileTriggerProps, HeaderSearch, type HeaderSearchProps, HeaderTitle, type HeaderTitleProps, type PaginationState, type RowSelectionState, Sidebar, SidebarFooter, type SidebarFooterProps, SidebarGroup, type SidebarGroupProps, SidebarHeader, type SidebarHeaderProps, SidebarNav, SidebarNavGroup, type SidebarNavGroupProps, SidebarNavItem, type SidebarNavItemProps, type SidebarNavItemRenderProps, type SidebarNavProps, type SidebarProps, type SortDirection, type SortState, type SortableValue, Table, type TableProps, type TableSize, type TableSizeClasses, buttonBaseClass, buttonSizeClass, buttonVariantClass, cn, alignClass as tableAlignClass, tableBaseClass, selectedRowClass as tableSelectedRowClass, tableSizeClass, sortIconClass as tableSortIconClass, useDashboardLayout, useDirection };
363
+ export { AppShell, type AppShellBrand, type AppShellNavGroup, type AppShellNavItem, type AppShellProps, Avatar, type AvatarProps, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Checkbox, type CheckboxProps, type CheckboxSize, type Column, type ColumnAlign, DashboardContent, type DashboardContentProps, DashboardHeader, type DashboardHeaderProps, DashboardLayout, type DashboardLayoutContextValue, type DashboardLayoutProps, DashboardMain, type DashboardMainProps, type Direction, HeaderActions, type HeaderActionsProps, HeaderCollapseTrigger, type HeaderCollapseTriggerProps, HeaderMobileTrigger, type HeaderMobileTriggerProps, HeaderSearch, type HeaderSearchProps, HeaderTitle, type HeaderTitleProps, Input, type InputProps, type InputSize, type InputVariant, type LanguageOption, LanguageSwitcher, type LanguageSwitcherProps, type PaginationState, type RowSelectionState, Sidebar, SidebarFooter, type SidebarFooterProps, SidebarGroup, type SidebarGroupProps, SidebarHeader, type SidebarHeaderProps, SidebarNav, SidebarNavGroup, type SidebarNavGroupProps, SidebarNavItem, type SidebarNavItemProps, type SidebarNavItemRenderProps, type SidebarNavProps, type SidebarProps, type SortDirection, type SortState, type SortableValue, Table, type TableProps, type TableSize, type TableSizeClasses, buttonBaseClass, buttonSizeClass, buttonVariantClass, cn, inputBaseClass, inputSizeClass, inputVariantClass, alignClass as tableAlignClass, tableBaseClass, selectedRowClass as tableSelectedRowClass, tableSizeClass, sortIconClass as tableSortIconClass, useDashboardLayout, useDirection };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
- import { HTMLAttributes, ReactNode, ReactElement, ButtonHTMLAttributes, InputHTMLAttributes, ChangeEvent, AnchorHTMLAttributes, Ref } from 'react';
3
+ import { HTMLAttributes, ReactNode, ReactElement, ButtonHTMLAttributes, InputHTMLAttributes, ChangeEvent, FieldsetHTMLAttributes, AnchorHTMLAttributes, Ref } from 'react';
4
4
  import { ClassValue } from 'clsx';
5
5
 
6
6
  interface DashboardLayoutContextValue {
@@ -34,7 +34,8 @@ type RenderLink = (props: {
34
34
  'aria-current'?: 'page';
35
35
  }) => ReactElement;
36
36
  interface AppShellNavItem {
37
- key: string;
37
+ /** Optional stable key. Falls back to array index if omitted — only safe for static nav. */
38
+ key?: string;
38
39
  label: ReactNode;
39
40
  href?: string;
40
41
  icon?: ReactNode;
@@ -44,18 +45,14 @@ interface AppShellNavItem {
44
45
  render?: RenderLink;
45
46
  }
46
47
  interface AppShellNavGroup {
47
- key: string;
48
+ /** Optional stable key. Falls back to array index if omitted — only safe for static nav. */
49
+ key?: string;
48
50
  label: ReactNode;
49
51
  icon?: ReactNode;
50
52
  active?: boolean;
51
53
  defaultOpen?: boolean;
52
54
  items: AppShellNavItem[];
53
55
  }
54
- interface AppShellNavSection {
55
- key: string;
56
- label?: ReactNode;
57
- items: Array<AppShellNavItem | AppShellNavGroup>;
58
- }
59
56
  interface AppShellBrand {
60
57
  logo?: ReactNode;
61
58
  name?: ReactNode;
@@ -63,8 +60,12 @@ interface AppShellBrand {
63
60
  }
64
61
  interface AppShellProps extends Pick<DashboardLayoutProps, 'defaultCollapsed' | 'collapsed' | 'onCollapsedChange'> {
65
62
  brand?: AppShellBrand;
66
- /** Either a flat list of items, or grouped sections. */
67
- nav: AppShellNavSection[] | Array<AppShellNavItem | AppShellNavGroup>;
63
+ /**
64
+ * Flat list of nav entries: leaf items (with `href` or `render`) and/or
65
+ * collapsible groups (with `items`). For more advanced layouts (sections,
66
+ * dividers, custom structure), compose `Sidebar` + `SidebarNav` directly.
67
+ */
68
+ nav: Array<AppShellNavItem | AppShellNavGroup>;
68
69
  title?: ReactNode;
69
70
  searchPlaceholder?: string;
70
71
  onSearch?: (value: string) => void;
@@ -150,6 +151,47 @@ declare const HeaderSearch: react.ForwardRefExoticComponent<HeaderSearchProps &
150
151
  type HeaderTitleProps = HTMLAttributes<HTMLDivElement>;
151
152
  declare function HeaderTitle({ className, children, ...props }: HeaderTitleProps): react_jsx_runtime.JSX.Element;
152
153
 
154
+ type InputVariant = 'default' | 'filled' | 'ghost';
155
+ type InputSize = 'sm' | 'md' | 'lg';
156
+ declare const inputVariantClass: Record<InputVariant, string>;
157
+ declare const inputSizeClass: Record<InputSize, string>;
158
+ declare const inputBaseClass = "group/input relative inline-flex w-full items-center text-foreground outline-none transition-[background-color,border-color,box-shadow] focus-within:ring-2 focus-within:ring-ring/40 focus-within:ring-offset-1 focus-within:ring-offset-background aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-within:ring-destructive/40 has-[input:disabled]:pointer-events-none has-[input:disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0";
159
+
160
+ interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix'> {
161
+ variant?: InputVariant;
162
+ inputSize?: InputSize;
163
+ /** Optional label rendered above the field. */
164
+ label?: ReactNode;
165
+ /** Helper text rendered under the field when not in an error state. */
166
+ helperText?: ReactNode;
167
+ /** Error message — renders in destructive style and sets aria-invalid. */
168
+ error?: ReactNode;
169
+ /** Element rendered before the input (icon, prefix text, etc.). */
170
+ leadingIcon?: ReactNode;
171
+ /** Element rendered after the input (icon, suffix text, etc.). */
172
+ trailingIcon?: ReactNode;
173
+ /** Stretch the wrapper to fill the parent's inline width. Defaults to `true`. */
174
+ fullWidth?: boolean;
175
+ /** Class applied to the outer wrapper that holds the icons + input. */
176
+ wrapperClassName?: string;
177
+ /** Class applied to the field container (`<label>` block). */
178
+ containerClassName?: string;
179
+ }
180
+ declare const Input: react.ForwardRefExoticComponent<InputProps & react.RefAttributes<HTMLInputElement>>;
181
+
182
+ interface LanguageOption<TCode extends string = string> {
183
+ code: TCode;
184
+ label?: string;
185
+ }
186
+ interface LanguageSwitcherProps<TCode extends string = string> extends Omit<FieldsetHTMLAttributes<HTMLFieldSetElement>, 'onChange'> {
187
+ languages: ReadonlyArray<LanguageOption<TCode>>;
188
+ value: TCode;
189
+ onChange: (next: TCode) => void;
190
+ /** Accessible label for the group. Defaults to "Language". */
191
+ ariaLabel?: string;
192
+ }
193
+ declare function LanguageSwitcher<TCode extends string = string>({ languages, value, onChange, ariaLabel, className, ...props }: LanguageSwitcherProps<TCode>): react_jsx_runtime.JSX.Element;
194
+
153
195
  type SidebarProps = HTMLAttributes<HTMLElement>;
154
196
  declare function Sidebar({ className, children, ...props }: SidebarProps): react_jsx_runtime.JSX.Element;
155
197
 
@@ -318,4 +360,4 @@ declare function useDirection(): Direction;
318
360
 
319
361
  declare function cn(...inputs: ClassValue[]): string;
320
362
 
321
- export { AppShell, type AppShellBrand, type AppShellNavGroup, type AppShellNavItem, type AppShellNavSection, type AppShellProps, Avatar, type AvatarProps, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Checkbox, type CheckboxProps, type CheckboxSize, type Column, type ColumnAlign, DashboardContent, type DashboardContentProps, DashboardHeader, type DashboardHeaderProps, DashboardLayout, type DashboardLayoutContextValue, type DashboardLayoutProps, DashboardMain, type DashboardMainProps, type Direction, HeaderActions, type HeaderActionsProps, HeaderCollapseTrigger, type HeaderCollapseTriggerProps, HeaderMobileTrigger, type HeaderMobileTriggerProps, HeaderSearch, type HeaderSearchProps, HeaderTitle, type HeaderTitleProps, type PaginationState, type RowSelectionState, Sidebar, SidebarFooter, type SidebarFooterProps, SidebarGroup, type SidebarGroupProps, SidebarHeader, type SidebarHeaderProps, SidebarNav, SidebarNavGroup, type SidebarNavGroupProps, SidebarNavItem, type SidebarNavItemProps, type SidebarNavItemRenderProps, type SidebarNavProps, type SidebarProps, type SortDirection, type SortState, type SortableValue, Table, type TableProps, type TableSize, type TableSizeClasses, buttonBaseClass, buttonSizeClass, buttonVariantClass, cn, alignClass as tableAlignClass, tableBaseClass, selectedRowClass as tableSelectedRowClass, tableSizeClass, sortIconClass as tableSortIconClass, useDashboardLayout, useDirection };
363
+ export { AppShell, type AppShellBrand, type AppShellNavGroup, type AppShellNavItem, type AppShellProps, Avatar, type AvatarProps, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Checkbox, type CheckboxProps, type CheckboxSize, type Column, type ColumnAlign, DashboardContent, type DashboardContentProps, DashboardHeader, type DashboardHeaderProps, DashboardLayout, type DashboardLayoutContextValue, type DashboardLayoutProps, DashboardMain, type DashboardMainProps, type Direction, HeaderActions, type HeaderActionsProps, HeaderCollapseTrigger, type HeaderCollapseTriggerProps, HeaderMobileTrigger, type HeaderMobileTriggerProps, HeaderSearch, type HeaderSearchProps, HeaderTitle, type HeaderTitleProps, Input, type InputProps, type InputSize, type InputVariant, type LanguageOption, LanguageSwitcher, type LanguageSwitcherProps, type PaginationState, type RowSelectionState, Sidebar, SidebarFooter, type SidebarFooterProps, SidebarGroup, type SidebarGroupProps, SidebarHeader, type SidebarHeaderProps, SidebarNav, SidebarNavGroup, type SidebarNavGroupProps, SidebarNavItem, type SidebarNavItemProps, type SidebarNavItemRenderProps, type SidebarNavProps, type SidebarProps, type SortDirection, type SortState, type SortableValue, Table, type TableProps, type TableSize, type TableSizeClasses, buttonBaseClass, buttonSizeClass, buttonVariantClass, cn, inputBaseClass, inputSizeClass, inputVariantClass, alignClass as tableAlignClass, tableBaseClass, selectedRowClass as tableSelectedRowClass, tableSizeClass, sortIconClass as tableSortIconClass, useDashboardLayout, useDirection };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createContext, forwardRef, Children, isValidElement, cloneElement, useRef, useImperativeHandle, useLayoutEffect, useContext, useState, useCallback, useMemo, useEffect, useId } from 'react';
1
+ import { createContext, forwardRef, Children, isValidElement, cloneElement, useRef, useImperativeHandle, useLayoutEffect, useId, useContext, useState, useCallback, useMemo, useEffect } from 'react';
2
2
  import { clsx } from 'clsx';
3
3
  import { twMerge } from 'tailwind-merge';
4
4
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
@@ -555,18 +555,11 @@ function SidebarNavItem({
555
555
  }
556
556
  );
557
557
  }
558
- function isSection(entry) {
559
- return "items" in entry && !("label" in entry && "href" in entry) && Array.isArray(entry.items);
560
- }
561
558
  function isGroup(entry) {
562
- return "items" in entry;
563
- }
564
- function normalize(nav) {
565
- if (nav.length === 0) return [];
566
- if (isSection(nav[0])) return nav;
567
- return [{ key: "__root", items: nav }];
559
+ return "items" in entry && Array.isArray(entry.items);
568
560
  }
569
- function renderItem(item) {
561
+ function renderItem(item, fallbackKey) {
562
+ const key = item.key ?? fallbackKey;
570
563
  if (item.render) {
571
564
  return /* @__PURE__ */ jsx(
572
565
  SidebarNavItem,
@@ -577,7 +570,7 @@ function renderItem(item) {
577
570
  render: item.render,
578
571
  children: item.label
579
572
  },
580
- item.key
573
+ key
581
574
  );
582
575
  }
583
576
  return /* @__PURE__ */ jsx(
@@ -589,7 +582,7 @@ function renderItem(item) {
589
582
  endSlot: item.endSlot,
590
583
  children: item.label
591
584
  },
592
- item.key
585
+ key
593
586
  );
594
587
  }
595
588
  function AppShell({
@@ -605,7 +598,6 @@ function AppShell({
605
598
  onCollapsedChange,
606
599
  children
607
600
  }) {
608
- const sections = normalize(nav);
609
601
  return /* @__PURE__ */ jsxs(
610
602
  DashboardLayout,
611
603
  {
@@ -618,19 +610,19 @@ function AppShell({
618
610
  brand.logo,
619
611
  brand.name ? /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-semibold", children: brand.name }) : null
620
612
  ] }),
621
- /* @__PURE__ */ jsx(SidebarNav, { children: sections.map((section) => /* @__PURE__ */ jsx(SidebarGroup, { label: section.label, children: section.items.map(
622
- (entry) => isGroup(entry) ? /* @__PURE__ */ jsx(
613
+ /* @__PURE__ */ jsx(SidebarNav, { children: nav.map(
614
+ (entry, index) => isGroup(entry) ? /* @__PURE__ */ jsx(
623
615
  SidebarNavGroup,
624
616
  {
625
617
  label: entry.label,
626
618
  icon: entry.icon,
627
619
  active: entry.active,
628
620
  defaultOpen: entry.defaultOpen ?? entry.items.some((i) => i.active),
629
- children: entry.items.map(renderItem)
621
+ children: entry.items.map((item, itemIndex) => renderItem(item, itemIndex))
630
622
  },
631
- entry.key
632
- ) : renderItem(entry)
633
- ) }, section.key)) }),
623
+ entry.key ?? index
624
+ ) : renderItem(entry, index)
625
+ ) }),
634
626
  sidebarFooter ? /* @__PURE__ */ jsx(SidebarFooter, { children: sidebarFooter }) : null
635
627
  ] }),
636
628
  /* @__PURE__ */ jsxs(DashboardMain, { children: [
@@ -750,6 +742,140 @@ var Checkbox = forwardRef(function Checkbox2({
750
742
  )
751
743
  ] });
752
744
  });
745
+
746
+ // src/components/input/inputVariants.ts
747
+ var inputVariantClass = {
748
+ default: "border border-input bg-background hover:border-ring",
749
+ filled: "border border-transparent bg-muted hover:bg-muted/80",
750
+ ghost: "border border-transparent bg-transparent hover:bg-accent"
751
+ };
752
+ var inputSizeClass = {
753
+ sm: "h-8 rounded-md px-2.5 text-sm gap-1.5",
754
+ md: "h-9 rounded-md px-3 text-sm gap-2",
755
+ lg: "h-11 rounded-md px-4 text-base gap-2.5"
756
+ };
757
+ var inputBaseClass = "group/input relative inline-flex w-full items-center text-foreground outline-none transition-[background-color,border-color,box-shadow] focus-within:ring-2 focus-within:ring-ring/40 focus-within:ring-offset-1 focus-within:ring-offset-background aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-within:ring-destructive/40 has-[input:disabled]:pointer-events-none has-[input:disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0";
758
+ var Input = forwardRef(function Input2({
759
+ variant = "default",
760
+ inputSize = "md",
761
+ label,
762
+ helperText,
763
+ error,
764
+ leadingIcon,
765
+ trailingIcon,
766
+ fullWidth = true,
767
+ type = "text",
768
+ id,
769
+ className,
770
+ wrapperClassName,
771
+ containerClassName,
772
+ "aria-invalid": ariaInvalidProp,
773
+ "aria-describedby": ariaDescribedByProp,
774
+ disabled,
775
+ ...props
776
+ }, ref) {
777
+ const generatedId = useId();
778
+ const inputId = id ?? generatedId;
779
+ const helperId = `${inputId}-helper`;
780
+ const errorId = `${inputId}-error`;
781
+ const hasError = error !== void 0 && error !== null && error !== false;
782
+ const ariaInvalid = ariaInvalidProp ?? (hasError ? true : void 0);
783
+ const describedByIds = [
784
+ ariaDescribedByProp,
785
+ hasError ? errorId : null,
786
+ !hasError && helperText ? helperId : null
787
+ ].filter(Boolean).join(" ");
788
+ const ariaDescribedBy = describedByIds.length > 0 ? describedByIds : void 0;
789
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1.5", fullWidth && "w-full", containerClassName), children: [
790
+ label !== void 0 && label !== null && /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "text-sm font-medium text-foreground select-none", children: label }),
791
+ /* @__PURE__ */ jsxs(
792
+ "div",
793
+ {
794
+ "data-slot": "input-wrapper",
795
+ className: cn(
796
+ inputBaseClass,
797
+ inputVariantClass[variant],
798
+ inputSizeClass[inputSize],
799
+ wrapperClassName
800
+ ),
801
+ "aria-invalid": ariaInvalid,
802
+ "data-disabled": disabled ? "true" : void 0,
803
+ children: [
804
+ leadingIcon ? /* @__PURE__ */ jsx(
805
+ "span",
806
+ {
807
+ "aria-hidden": "true",
808
+ className: "inline-flex h-4 w-4 items-center justify-center text-muted-foreground",
809
+ children: leadingIcon
810
+ }
811
+ ) : null,
812
+ /* @__PURE__ */ jsx(
813
+ "input",
814
+ {
815
+ ref,
816
+ id: inputId,
817
+ type,
818
+ disabled,
819
+ "aria-invalid": ariaInvalid,
820
+ "aria-describedby": ariaDescribedBy,
821
+ className: cn(
822
+ "h-full w-full min-w-0 flex-1 bg-transparent outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed",
823
+ className
824
+ ),
825
+ ...props
826
+ }
827
+ ),
828
+ trailingIcon ? /* @__PURE__ */ jsx(
829
+ "span",
830
+ {
831
+ "aria-hidden": "true",
832
+ className: "inline-flex h-4 w-4 items-center justify-center text-muted-foreground",
833
+ children: trailingIcon
834
+ }
835
+ ) : null
836
+ ]
837
+ }
838
+ ),
839
+ hasError ? /* @__PURE__ */ jsx("p", { id: errorId, className: "text-xs text-destructive", children: error }) : helperText ? /* @__PURE__ */ jsx("p", { id: helperId, className: "text-xs text-muted-foreground", children: helperText }) : null
840
+ ] });
841
+ });
842
+ function LanguageSwitcher({
843
+ languages,
844
+ value,
845
+ onChange,
846
+ ariaLabel = "Language",
847
+ className,
848
+ ...props
849
+ }) {
850
+ return /* @__PURE__ */ jsx(
851
+ "fieldset",
852
+ {
853
+ "aria-label": ariaLabel,
854
+ className: cn(
855
+ "inline-flex items-center rounded-md border border-border bg-background p-0.5 text-xs",
856
+ className
857
+ ),
858
+ ...props,
859
+ children: languages.map((lang) => {
860
+ const isActive = lang.code === value;
861
+ return /* @__PURE__ */ jsx(
862
+ "button",
863
+ {
864
+ type: "button",
865
+ onClick: () => onChange(lang.code),
866
+ "aria-pressed": isActive,
867
+ className: cn(
868
+ "rounded px-2 py-1 font-medium transition-colors",
869
+ isActive ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:text-foreground"
870
+ ),
871
+ children: lang.label ?? lang.code.toUpperCase()
872
+ },
873
+ lang.code
874
+ );
875
+ })
876
+ }
877
+ );
878
+ }
753
879
  function readDocumentDirection() {
754
880
  if (typeof document === "undefined") return "ltr";
755
881
  const dir = document.documentElement.getAttribute("dir");
@@ -1258,6 +1384,6 @@ function SortIndicator({ active, direction }) {
1258
1384
  return direction === "asc" ? /* @__PURE__ */ jsx(ChevronUp, { "aria-hidden": "true", className }) : /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": "true", className });
1259
1385
  }
1260
1386
 
1261
- export { AppShell, Avatar, Button, Checkbox, DashboardContent, DashboardHeader, DashboardLayout, DashboardMain, HeaderActions, HeaderCollapseTrigger, HeaderMobileTrigger, HeaderSearch, HeaderTitle, Sidebar, SidebarFooter, SidebarGroup, SidebarHeader, SidebarNav, SidebarNavGroup, SidebarNavItem, Table, buttonBaseClass, buttonSizeClass, buttonVariantClass, cn, alignClass as tableAlignClass, tableBaseClass, selectedRowClass as tableSelectedRowClass, tableSizeClass, sortIconClass as tableSortIconClass, useDashboardLayout, useDirection };
1387
+ export { AppShell, Avatar, Button, Checkbox, DashboardContent, DashboardHeader, DashboardLayout, DashboardMain, HeaderActions, HeaderCollapseTrigger, HeaderMobileTrigger, HeaderSearch, HeaderTitle, Input, LanguageSwitcher, Sidebar, SidebarFooter, SidebarGroup, SidebarHeader, SidebarNav, SidebarNavGroup, SidebarNavItem, Table, buttonBaseClass, buttonSizeClass, buttonVariantClass, cn, inputBaseClass, inputSizeClass, inputVariantClass, alignClass as tableAlignClass, tableBaseClass, selectedRowClass as tableSelectedRowClass, tableSizeClass, sortIconClass as tableSortIconClass, useDashboardLayout, useDirection };
1262
1388
  //# sourceMappingURL=index.js.map
1263
1389
  //# sourceMappingURL=index.js.map