@dimaan/ui 0.0.10 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -6,9 +6,10 @@ var clsx = require('clsx');
6
6
  var tailwindMerge = require('tailwind-merge');
7
7
  var jsxRuntime = require('react/jsx-runtime');
8
8
  var lucideReact = require('lucide-react');
9
+ var RadixDropdown = require('@radix-ui/react-dropdown-menu');
9
10
  var reactHookForm = require('react-hook-form');
10
- var RadixRadioGroup = require('@radix-ui/react-radio-group');
11
11
  var RadixSelect = require('@radix-ui/react-select');
12
+ var RadixRadioGroup = require('@radix-ui/react-radio-group');
12
13
  var RadixSwitch = require('@radix-ui/react-switch');
13
14
 
14
15
  function _interopNamespace(e) {
@@ -29,8 +30,9 @@ function _interopNamespace(e) {
29
30
  return Object.freeze(n);
30
31
  }
31
32
 
32
- var RadixRadioGroup__namespace = /*#__PURE__*/_interopNamespace(RadixRadioGroup);
33
+ var RadixDropdown__namespace = /*#__PURE__*/_interopNamespace(RadixDropdown);
33
34
  var RadixSelect__namespace = /*#__PURE__*/_interopNamespace(RadixSelect);
35
+ var RadixRadioGroup__namespace = /*#__PURE__*/_interopNamespace(RadixRadioGroup);
34
36
  var RadixSwitch__namespace = /*#__PURE__*/_interopNamespace(RadixSwitch);
35
37
 
36
38
  // src/components/app-shell/AppShell.tsx
@@ -724,6 +726,47 @@ function Avatar({ src, alt = "", fallback, size = "md", className, ...props }) {
724
726
  }
725
727
  );
726
728
  }
729
+
730
+ // src/components/badge/badgeVariants.ts
731
+ var badgeVariantClass = {
732
+ default: "bg-muted text-foreground border-transparent",
733
+ primary: "bg-primary text-primary-foreground border-transparent",
734
+ success: "bg-success text-success-foreground border-transparent",
735
+ warning: "bg-warning text-warning-foreground border-transparent",
736
+ destructive: "bg-destructive text-destructive-foreground border-transparent",
737
+ outline: "border-border bg-transparent text-foreground"
738
+ };
739
+ var badgeSizeClass = {
740
+ sm: "h-5 gap-1 px-2 text-[11px]",
741
+ md: "h-6 gap-1.5 px-2.5 text-xs"
742
+ };
743
+ var badgeDotSizeClass = {
744
+ sm: "size-1.5",
745
+ md: "size-2"
746
+ };
747
+ var badgeBaseClass = "inline-flex shrink-0 items-center rounded-full border font-medium leading-none whitespace-nowrap select-none transition-colors";
748
+ var Badge = react.forwardRef(function Badge2({ variant = "default", size = "md", dot = false, className, children, ...props }, ref) {
749
+ return /* @__PURE__ */ jsxRuntime.jsxs(
750
+ "span",
751
+ {
752
+ ref,
753
+ "data-slot": "badge",
754
+ "data-variant": variant,
755
+ className: cn(badgeBaseClass, badgeVariantClass[variant], badgeSizeClass[size], className),
756
+ ...props,
757
+ children: [
758
+ dot ? /* @__PURE__ */ jsxRuntime.jsx(
759
+ "span",
760
+ {
761
+ "aria-hidden": "true",
762
+ className: cn("inline-block rounded-full bg-current opacity-80", badgeDotSizeClass[size])
763
+ }
764
+ ) : null,
765
+ children
766
+ ]
767
+ }
768
+ );
769
+ });
727
770
  var sizeClass2 = {
728
771
  sm: "h-3.5 w-3.5",
729
772
  md: "h-4 w-4"
@@ -792,6 +835,166 @@ var Checkbox = react.forwardRef(function Checkbox2({
792
835
  )
793
836
  ] });
794
837
  });
838
+
839
+ // src/components/dropdown-menu/dropdownMenuVariants.ts
840
+ var dropdownMenuContentClass = "z-50 min-w-32 overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95";
841
+ var dropdownMenuItemBaseClass = "relative flex w-full cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0";
842
+ var dropdownMenuItemVariantClass = {
843
+ default: "text-foreground data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground",
844
+ destructive: "text-destructive data-[highlighted]:bg-destructive data-[highlighted]:text-destructive-foreground"
845
+ };
846
+ var dropdownMenuItemInsetClass = "ps-8";
847
+ var dropdownMenuSeparatorClass = "-mx-1 my-1 h-px bg-border";
848
+ var dropdownMenuLabelClass = "px-2 py-1.5 text-xs font-semibold text-muted-foreground select-none";
849
+ var dropdownMenuShortcutClass = "ms-auto text-xs tracking-widest text-muted-foreground";
850
+ var DropdownMenu = RadixDropdown__namespace.Root;
851
+ var DropdownMenuTrigger = RadixDropdown__namespace.Trigger;
852
+ var DropdownMenuGroup = RadixDropdown__namespace.Group;
853
+ var DropdownMenuPortal = RadixDropdown__namespace.Portal;
854
+ var DropdownMenuContent = react.forwardRef(function DropdownMenuContent2({ className, sideOffset = 4, ...props }, ref) {
855
+ return /* @__PURE__ */ jsxRuntime.jsx(RadixDropdown__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
856
+ RadixDropdown__namespace.Content,
857
+ {
858
+ ref,
859
+ sideOffset,
860
+ "data-slot": "dropdown-menu-content",
861
+ className: cn(dropdownMenuContentClass, className),
862
+ ...props
863
+ }
864
+ ) });
865
+ });
866
+ var DropdownMenuItem = react.forwardRef(function DropdownMenuItem2({ className, variant = "default", inset = false, ...props }, ref) {
867
+ return /* @__PURE__ */ jsxRuntime.jsx(
868
+ RadixDropdown__namespace.Item,
869
+ {
870
+ ref,
871
+ "data-slot": "dropdown-menu-item",
872
+ "data-variant": variant,
873
+ className: cn(
874
+ dropdownMenuItemBaseClass,
875
+ dropdownMenuItemVariantClass[variant],
876
+ inset && dropdownMenuItemInsetClass,
877
+ className
878
+ ),
879
+ ...props
880
+ }
881
+ );
882
+ });
883
+ var DropdownMenuSeparator = react.forwardRef(function DropdownMenuSeparator2({ className, ...props }, ref) {
884
+ return /* @__PURE__ */ jsxRuntime.jsx(
885
+ RadixDropdown__namespace.Separator,
886
+ {
887
+ ref,
888
+ "data-slot": "dropdown-menu-separator",
889
+ className: cn(dropdownMenuSeparatorClass, className),
890
+ ...props
891
+ }
892
+ );
893
+ });
894
+ var DropdownMenuLabel = react.forwardRef(function DropdownMenuLabel2({ className, inset = false, ...props }, ref) {
895
+ return /* @__PURE__ */ jsxRuntime.jsx(
896
+ RadixDropdown__namespace.Label,
897
+ {
898
+ ref,
899
+ "data-slot": "dropdown-menu-label",
900
+ className: cn(dropdownMenuLabelClass, inset && dropdownMenuItemInsetClass, className),
901
+ ...props
902
+ }
903
+ );
904
+ });
905
+ var DropdownMenuShortcut = react.forwardRef(
906
+ function DropdownMenuShortcut2({ className, ...props }, ref) {
907
+ return /* @__PURE__ */ jsxRuntime.jsx(
908
+ "span",
909
+ {
910
+ ref,
911
+ "data-slot": "dropdown-menu-shortcut",
912
+ className: cn(dropdownMenuShortcutClass, className),
913
+ ...props
914
+ }
915
+ );
916
+ }
917
+ );
918
+
919
+ // src/components/empty-state/emptyStateVariants.ts
920
+ var emptyStateContainerSizeClass = {
921
+ sm: "py-8 gap-2",
922
+ md: "py-14 gap-3",
923
+ lg: "py-20 gap-4"
924
+ };
925
+ var emptyStateIconWrapperSizeClass = {
926
+ sm: "size-10 [&_svg]:size-5",
927
+ md: "size-14 [&_svg]:size-7",
928
+ lg: "size-16 [&_svg]:size-8"
929
+ };
930
+ var emptyStateTitleSizeClass = {
931
+ sm: "text-sm",
932
+ md: "text-base",
933
+ lg: "text-lg"
934
+ };
935
+ var emptyStateDescriptionSizeClass = {
936
+ sm: "text-xs",
937
+ md: "text-sm",
938
+ lg: "text-sm"
939
+ };
940
+ var emptyStateActionsSpacingClass = {
941
+ sm: "mt-2",
942
+ md: "mt-4",
943
+ lg: "mt-6"
944
+ };
945
+ var emptyStateBaseClass = "flex flex-col items-center justify-center text-center px-4";
946
+ var emptyStateIconWrapperBaseClass = "inline-flex items-center justify-center rounded-full bg-muted text-muted-foreground";
947
+ var EmptyState = react.forwardRef(function EmptyState2({ icon, title, description, action, size = "md", className, ...props }, ref) {
948
+ return /* @__PURE__ */ jsxRuntime.jsxs(
949
+ "div",
950
+ {
951
+ ref,
952
+ role: "status",
953
+ "aria-live": "polite",
954
+ "data-slot": "empty-state",
955
+ className: cn(emptyStateBaseClass, emptyStateContainerSizeClass[size], className),
956
+ ...props,
957
+ children: [
958
+ icon ? /* @__PURE__ */ jsxRuntime.jsx(
959
+ "span",
960
+ {
961
+ "aria-hidden": "true",
962
+ "data-slot": "empty-state-icon",
963
+ className: cn(emptyStateIconWrapperBaseClass, emptyStateIconWrapperSizeClass[size]),
964
+ children: icon
965
+ }
966
+ ) : null,
967
+ /* @__PURE__ */ jsxRuntime.jsx(
968
+ "p",
969
+ {
970
+ "data-slot": "empty-state-title",
971
+ className: cn("font-semibold text-foreground", emptyStateTitleSizeClass[size]),
972
+ children: title
973
+ }
974
+ ),
975
+ description ? /* @__PURE__ */ jsxRuntime.jsx(
976
+ "p",
977
+ {
978
+ "data-slot": "empty-state-description",
979
+ className: cn("max-w-sm text-muted-foreground", emptyStateDescriptionSizeClass[size]),
980
+ children: description
981
+ }
982
+ ) : null,
983
+ action ? /* @__PURE__ */ jsxRuntime.jsx(
984
+ "div",
985
+ {
986
+ "data-slot": "empty-state-actions",
987
+ className: cn(
988
+ "flex flex-wrap items-center justify-center gap-2",
989
+ emptyStateActionsSpacingClass[size]
990
+ ),
991
+ children: action
992
+ }
993
+ ) : null
994
+ ]
995
+ }
996
+ );
997
+ });
795
998
  function Field(props) {
796
999
  const formContext = reactHookForm.useFormContext();
797
1000
  if (props.name !== void 0) {
@@ -1036,130 +1239,71 @@ function LanguageSwitcher({
1036
1239
  );
1037
1240
  }
1038
1241
 
1039
- // src/components/radio-group/radioGroupVariants.ts
1040
- var radioItemSizeClass = {
1041
- sm: "size-4",
1042
- md: "size-5",
1043
- lg: "size-6"
1044
- };
1045
- var radioIndicatorSizeClass = {
1046
- sm: "size-1.5",
1047
- md: "size-2",
1048
- lg: "size-2.5"
1049
- };
1050
- var radioLabelSizeClass = {
1051
- sm: "text-xs",
1052
- md: "text-sm",
1053
- lg: "text-base"
1054
- };
1055
- var radioItemBaseClass = "aspect-square shrink-0 rounded-full border border-input bg-background text-primary outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background hover:border-ring disabled:cursor-not-allowed disabled:opacity-50 aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-visible:ring-destructive/40 data-[state=checked]:border-primary";
1056
- var radioIndicatorBaseClass = "flex h-full w-full items-center justify-center";
1057
- var radioIndicatorDotClass = "rounded-full bg-primary";
1058
- var radioOptionRowClass = "flex cursor-pointer items-start gap-2 has-[button:disabled]:cursor-not-allowed";
1059
- var radioGroupBaseClass = "flex gap-3";
1060
- var radioGroupOrientationClass = {
1061
- vertical: "flex-col",
1062
- horizontal: "flex-row flex-wrap"
1063
- };
1064
- var RadioGroup = react.forwardRef(function RadioGroup2({
1065
- radioSize = "md",
1066
- orientation = "vertical",
1067
- value,
1068
- defaultValue,
1069
- onValueChange,
1070
- onChange,
1071
- onBlur,
1072
- name,
1073
- disabled,
1074
- required,
1075
- id,
1076
- options,
1242
+ // src/components/page-header/pageHeaderVariants.ts
1243
+ var pageHeaderBaseClass = "flex w-full flex-col gap-3";
1244
+ var pageHeaderBorderedClass = "border-b border-border pb-4";
1245
+ var pageHeaderTitleRowClass = "flex flex-wrap items-start justify-between gap-3 sm:gap-4";
1246
+ var pageHeaderTitleBlockClass = "min-w-0 flex-1 space-y-1";
1247
+ var pageHeaderTitleClass = "text-2xl font-semibold tracking-tight text-foreground";
1248
+ var pageHeaderDescriptionClass = "text-sm text-muted-foreground";
1249
+ var pageHeaderActionsClass = "flex shrink-0 flex-wrap items-center gap-2";
1250
+ var pageHeaderBackClass = "inline-flex items-center gap-1.5 self-start text-sm text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded-md";
1251
+ var pageHeaderBackIconClass = "size-4 shrink-0 rtl:rotate-180";
1252
+ var pageHeaderBreadcrumbsClass = "text-xs text-muted-foreground";
1253
+ var PageHeader = react.forwardRef(function PageHeader2({
1254
+ title,
1255
+ description,
1256
+ breadcrumbs,
1257
+ back,
1258
+ actions,
1259
+ as = "h1",
1260
+ bordered = false,
1077
1261
  className,
1078
- "aria-label": ariaLabel,
1079
- "aria-labelledby": ariaLabelledBy,
1080
- "aria-describedby": ariaDescribedBy,
1081
- "aria-invalid": ariaInvalid,
1082
- children
1262
+ ...props
1083
1263
  }, ref) {
1084
- const generatedId = react.useId();
1085
- const groupId = id ?? generatedId;
1086
- const handleValueChange = react.useCallback(
1087
- (next) => {
1088
- onValueChange?.(next);
1089
- if (onChange) {
1090
- const synthetic = {
1091
- target: { value: next, name },
1092
- currentTarget: { value: next, name },
1093
- type: "change"
1094
- };
1095
- onChange(synthetic);
1096
- }
1097
- },
1098
- [onValueChange, onChange, name]
1099
- );
1100
- return /* @__PURE__ */ jsxRuntime.jsx(
1101
- RadixRadioGroup__namespace.Root,
1264
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1265
+ "header",
1102
1266
  {
1103
1267
  ref,
1104
- id: groupId,
1105
- value,
1106
- defaultValue,
1107
- onValueChange: handleValueChange,
1108
- onBlur,
1109
- disabled,
1110
- required,
1111
- name,
1112
- orientation,
1113
- "aria-label": ariaLabel,
1114
- "aria-labelledby": ariaLabelledBy,
1115
- "aria-describedby": ariaDescribedBy,
1116
- "aria-invalid": ariaInvalid,
1117
- "data-slot": "radio-group",
1118
- className: cn(radioGroupBaseClass, radioGroupOrientationClass[orientation], className),
1119
- children: children ?? options?.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
1120
- RadioGroupOptionRow,
1121
- {
1122
- option: opt,
1123
- radioSize,
1124
- groupId
1125
- },
1126
- opt.value
1127
- ))
1268
+ "data-slot": "page-header",
1269
+ className: cn(pageHeaderBaseClass, bordered && pageHeaderBorderedClass, className),
1270
+ ...props,
1271
+ children: [
1272
+ breadcrumbs ? /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "page-header-breadcrumbs", className: pageHeaderBreadcrumbsClass, children: breadcrumbs }) : null,
1273
+ back ? /* @__PURE__ */ jsxRuntime.jsx(PageHeaderBack, { ...back }) : null,
1274
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "page-header-row", className: pageHeaderTitleRowClass, children: [
1275
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: pageHeaderTitleBlockClass, children: [
1276
+ react.createElement(
1277
+ as,
1278
+ { "data-slot": "page-header-title", className: pageHeaderTitleClass },
1279
+ title
1280
+ ),
1281
+ description ? /* @__PURE__ */ jsxRuntime.jsx("p", { "data-slot": "page-header-description", className: pageHeaderDescriptionClass, children: description }) : null
1282
+ ] }),
1283
+ actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "page-header-actions", className: pageHeaderActionsClass, children: actions }) : null
1284
+ ] })
1285
+ ]
1128
1286
  }
1129
1287
  );
1130
1288
  });
1131
- function RadioGroupOptionRow({ option, radioSize, groupId }) {
1132
- const itemId = `${groupId}-${option.value}`;
1133
- return /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: itemId, className: radioOptionRowClass, children: [
1134
- /* @__PURE__ */ jsxRuntime.jsx(
1135
- RadixRadioGroup__namespace.Item,
1136
- {
1137
- id: itemId,
1138
- value: option.value,
1139
- disabled: option.disabled,
1140
- "data-slot": "radio-item",
1141
- className: cn(radioItemBaseClass, radioItemSizeClass[radioSize], "mt-0.5"),
1142
- children: /* @__PURE__ */ jsxRuntime.jsx(RadixRadioGroup__namespace.Indicator, { className: radioIndicatorBaseClass, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(radioIndicatorDotClass, radioIndicatorSizeClass[radioSize]) }) })
1143
- }
1144
- ),
1145
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1 leading-tight", children: [
1146
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("block font-medium text-foreground", radioLabelSizeClass[radioSize]), children: option.label }),
1147
- option.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5 block text-xs text-muted-foreground", children: option.description }) : null
1148
- ] })
1289
+ function PageHeaderBack({ label = "Back", href, onClick, render }) {
1290
+ const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1291
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { className: pageHeaderBackIconClass, "aria-hidden": "true" }),
1292
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: label })
1149
1293
  ] });
1294
+ if (render) {
1295
+ return render({
1296
+ href,
1297
+ onClick,
1298
+ className: pageHeaderBackClass,
1299
+ children: inner
1300
+ });
1301
+ }
1302
+ if (href) {
1303
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { href, onClick, className: pageHeaderBackClass, children: inner });
1304
+ }
1305
+ return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick, className: pageHeaderBackClass, children: inner });
1150
1306
  }
1151
- var RadioGroupItem = react.forwardRef(function RadioGroupItem2({ className, radioSize = "md", ...props }, ref) {
1152
- return /* @__PURE__ */ jsxRuntime.jsx(
1153
- RadixRadioGroup__namespace.Item,
1154
- {
1155
- ref,
1156
- "data-slot": "radio-item",
1157
- className: cn(radioItemBaseClass, radioItemSizeClass[radioSize], className),
1158
- ...props,
1159
- children: /* @__PURE__ */ jsxRuntime.jsx(RadixRadioGroup__namespace.Indicator, { className: radioIndicatorBaseClass, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(radioIndicatorDotClass, radioIndicatorSizeClass[radioSize]) }) })
1160
- }
1161
- );
1162
- });
1163
1307
 
1164
1308
  // src/components/select/selectVariants.ts
1165
1309
  var selectVariantClass = {
@@ -1286,81 +1430,6 @@ var SelectItem = react.forwardRef(function SelectItem2({ className, children, ..
1286
1430
  /* @__PURE__ */ jsxRuntime.jsx(RadixSelect__namespace.ItemText, { children })
1287
1431
  ] });
1288
1432
  });
1289
-
1290
- // src/components/switch/switchVariants.ts
1291
- var switchTrackClass = {
1292
- sm: "h-4 w-7",
1293
- md: "h-5 w-9",
1294
- lg: "h-6 w-11"
1295
- };
1296
- var switchThumbClass = {
1297
- sm: "size-3 data-[state=checked]:translate-x-3 data-[state=checked]:rtl:-translate-x-3",
1298
- md: "size-4 data-[state=checked]:translate-x-4 data-[state=checked]:rtl:-translate-x-4",
1299
- lg: "size-5 data-[state=checked]:translate-x-5 data-[state=checked]:rtl:-translate-x-5"
1300
- };
1301
- var switchTrackBaseClass = "relative inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent bg-input transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary aria-[invalid=true]:ring-2 aria-[invalid=true]:ring-destructive/40";
1302
- var switchThumbBaseClass = "pointer-events-none block rounded-full bg-background shadow-sm ring-0 transition-transform";
1303
- var Switch = react.forwardRef(function Switch2({
1304
- switchSize = "md",
1305
- checked,
1306
- defaultChecked,
1307
- onCheckedChange,
1308
- value,
1309
- onChange,
1310
- onBlur,
1311
- name,
1312
- disabled,
1313
- required,
1314
- id,
1315
- className,
1316
- "aria-label": ariaLabel,
1317
- "aria-describedby": ariaDescribedBy,
1318
- "aria-invalid": ariaInvalid
1319
- }, ref) {
1320
- const generatedId = react.useId();
1321
- const switchId = id ?? generatedId;
1322
- const resolvedChecked = checked ?? (value === void 0 ? void 0 : Boolean(value));
1323
- const handleCheckedChange = react.useCallback(
1324
- (next) => {
1325
- onCheckedChange?.(next);
1326
- if (onChange) {
1327
- const synthetic = {
1328
- target: { checked: next, value: next, name },
1329
- currentTarget: { checked: next, value: next, name },
1330
- type: "change"
1331
- };
1332
- onChange(synthetic);
1333
- }
1334
- },
1335
- [onCheckedChange, onChange, name]
1336
- );
1337
- return /* @__PURE__ */ jsxRuntime.jsx(
1338
- RadixSwitch__namespace.Root,
1339
- {
1340
- ref,
1341
- id: switchId,
1342
- checked: resolvedChecked,
1343
- defaultChecked,
1344
- onCheckedChange: handleCheckedChange,
1345
- onBlur,
1346
- disabled,
1347
- required,
1348
- name,
1349
- "aria-label": ariaLabel,
1350
- "aria-invalid": ariaInvalid,
1351
- "aria-describedby": ariaDescribedBy,
1352
- "data-slot": "switch-track",
1353
- className: cn(switchTrackBaseClass, switchTrackClass[switchSize], className),
1354
- children: /* @__PURE__ */ jsxRuntime.jsx(
1355
- RadixSwitch__namespace.Thumb,
1356
- {
1357
- "data-slot": "switch-thumb",
1358
- className: cn(switchThumbBaseClass, switchThumbClass[switchSize])
1359
- }
1360
- )
1361
- }
1362
- );
1363
- });
1364
1433
  function Pagination({
1365
1434
  pageIndex,
1366
1435
  pageSize,
@@ -1848,6 +1917,333 @@ function SortIndicator({ active, direction }) {
1848
1917
  if (!active) return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDown, { "aria-hidden": "true", className });
1849
1918
  return direction === "asc" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { "aria-hidden": "true", className }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": "true", className });
1850
1919
  }
1920
+ var DEFAULT_LABELS = {
1921
+ searchPlaceholder: "Search\u2026",
1922
+ searchAriaLabel: "Search",
1923
+ reset: "Reset filters",
1924
+ emptyTitle: "No results",
1925
+ emptyDescription: "Try clearing the search or adjusting the filters."
1926
+ };
1927
+ var FILTER_WIDTH_CLASS = {
1928
+ narrow: "w-32",
1929
+ default: "w-44",
1930
+ wide: "w-56"
1931
+ };
1932
+ function ListPage({
1933
+ title,
1934
+ description,
1935
+ bordered = true,
1936
+ actions,
1937
+ data,
1938
+ columns,
1939
+ getRowId,
1940
+ searchKeys,
1941
+ filters,
1942
+ enableRowSelection,
1943
+ bulkActions,
1944
+ emptyState,
1945
+ labels: labelsProp,
1946
+ className
1947
+ }) {
1948
+ const labels = { ...DEFAULT_LABELS, ...labelsProp };
1949
+ const initialFilterValues = react.useMemo(() => {
1950
+ const init = {};
1951
+ for (const f of filters ?? []) {
1952
+ init[f.key] = f.defaultValue ?? f.options[0]?.value ?? "";
1953
+ }
1954
+ return init;
1955
+ }, [filters]);
1956
+ const [search, setSearch] = react.useState("");
1957
+ const [filterValues, setFilterValues] = react.useState(initialFilterValues);
1958
+ const setFilter = (key, value) => {
1959
+ setFilterValues((prev) => ({ ...prev, [key]: value }));
1960
+ };
1961
+ const reset = () => {
1962
+ setSearch("");
1963
+ setFilterValues(initialFilterValues);
1964
+ };
1965
+ const hasActiveFilters = react.useMemo(() => {
1966
+ if (search.trim() !== "") return true;
1967
+ for (const f of filters ?? []) {
1968
+ const current = filterValues[f.key];
1969
+ const def = f.defaultValue ?? f.options[0]?.value ?? "";
1970
+ if (current !== def) return true;
1971
+ }
1972
+ return false;
1973
+ }, [search, filters, filterValues]);
1974
+ const filtered = react.useMemo(() => {
1975
+ return data.filter((row) => {
1976
+ if (search.trim() && searchKeys && searchKeys.length > 0) {
1977
+ const q = search.trim().toLowerCase();
1978
+ const matches = searchKeys.some((key) => {
1979
+ const val = row[key];
1980
+ return val != null && String(val).toLowerCase().includes(q);
1981
+ });
1982
+ if (!matches) return false;
1983
+ }
1984
+ for (const f of filters ?? []) {
1985
+ const value = filterValues[f.key];
1986
+ const def = f.defaultValue ?? f.options[0]?.value ?? "";
1987
+ if (value !== void 0 && value !== def) {
1988
+ if (f.accessor(row) !== value) return false;
1989
+ }
1990
+ }
1991
+ return true;
1992
+ });
1993
+ }, [data, search, searchKeys, filters, filterValues]);
1994
+ const showFilterBar = Boolean(searchKeys?.length) || Boolean(filters?.length);
1995
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "list-page", className: cn("space-y-6", className), children: [
1996
+ /* @__PURE__ */ jsxRuntime.jsx(PageHeader, { title, description, bordered, actions }),
1997
+ showFilterBar ? /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "list-page-filter-bar", className: "flex flex-wrap items-center gap-3", children: [
1998
+ searchKeys?.length ? /* @__PURE__ */ jsxRuntime.jsx(
1999
+ Input,
2000
+ {
2001
+ type: "search",
2002
+ placeholder: labels.searchPlaceholder,
2003
+ "aria-label": labels.searchAriaLabel || labels.searchPlaceholder,
2004
+ value: search,
2005
+ onChange: (e) => setSearch(e.target.value),
2006
+ leadingIcon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, {}),
2007
+ wrapperClassName: "sm:max-w-xs"
2008
+ }
2009
+ ) : null,
2010
+ filters?.map((f) => /* @__PURE__ */ jsxRuntime.jsx(
2011
+ Select,
2012
+ {
2013
+ "aria-label": f.ariaLabel,
2014
+ value: filterValues[f.key],
2015
+ onValueChange: (v) => setFilter(f.key, v),
2016
+ options: f.options,
2017
+ className: FILTER_WIDTH_CLASS[f.width ?? "default"]
2018
+ },
2019
+ f.key
2020
+ )),
2021
+ hasActiveFilters ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "ghost", onClick: reset, children: [
2022
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, {}),
2023
+ labels.reset
2024
+ ] }) : null
2025
+ ] }) : null,
2026
+ filtered.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
2027
+ Table,
2028
+ {
2029
+ "aria-label": typeof title === "string" ? title : void 0,
2030
+ data: filtered,
2031
+ columns,
2032
+ getRowId,
2033
+ enableRowSelection,
2034
+ bulkActions
2035
+ }
2036
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "list-page-empty", className: "rounded-md border border-border", children: /* @__PURE__ */ jsxRuntime.jsx(
2037
+ EmptyState,
2038
+ {
2039
+ icon: emptyState?.icon,
2040
+ title: emptyState?.title ?? labels.emptyTitle,
2041
+ description: emptyState?.description ?? labels.emptyDescription,
2042
+ action: emptyState?.action !== void 0 ? emptyState.action : hasActiveFilters ? /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", onClick: reset, children: labels.reset }) : null
2043
+ }
2044
+ ) })
2045
+ ] });
2046
+ }
2047
+
2048
+ // src/components/radio-group/radioGroupVariants.ts
2049
+ var radioItemSizeClass = {
2050
+ sm: "size-4",
2051
+ md: "size-5",
2052
+ lg: "size-6"
2053
+ };
2054
+ var radioIndicatorSizeClass = {
2055
+ sm: "size-1.5",
2056
+ md: "size-2",
2057
+ lg: "size-2.5"
2058
+ };
2059
+ var radioLabelSizeClass = {
2060
+ sm: "text-xs",
2061
+ md: "text-sm",
2062
+ lg: "text-base"
2063
+ };
2064
+ var radioItemBaseClass = "aspect-square shrink-0 rounded-full border border-input bg-background text-primary outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background hover:border-ring disabled:cursor-not-allowed disabled:opacity-50 aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-visible:ring-destructive/40 data-[state=checked]:border-primary";
2065
+ var radioIndicatorBaseClass = "flex h-full w-full items-center justify-center";
2066
+ var radioIndicatorDotClass = "rounded-full bg-primary";
2067
+ var radioOptionRowClass = "flex cursor-pointer items-start gap-2 has-[button:disabled]:cursor-not-allowed";
2068
+ var radioGroupBaseClass = "flex gap-3";
2069
+ var radioGroupOrientationClass = {
2070
+ vertical: "flex-col",
2071
+ horizontal: "flex-row flex-wrap"
2072
+ };
2073
+ var RadioGroup = react.forwardRef(function RadioGroup2({
2074
+ radioSize = "md",
2075
+ orientation = "vertical",
2076
+ value,
2077
+ defaultValue,
2078
+ onValueChange,
2079
+ onChange,
2080
+ onBlur,
2081
+ name,
2082
+ disabled,
2083
+ required,
2084
+ id,
2085
+ options,
2086
+ className,
2087
+ "aria-label": ariaLabel,
2088
+ "aria-labelledby": ariaLabelledBy,
2089
+ "aria-describedby": ariaDescribedBy,
2090
+ "aria-invalid": ariaInvalid,
2091
+ children
2092
+ }, ref) {
2093
+ const generatedId = react.useId();
2094
+ const groupId = id ?? generatedId;
2095
+ const handleValueChange = react.useCallback(
2096
+ (next) => {
2097
+ onValueChange?.(next);
2098
+ if (onChange) {
2099
+ const synthetic = {
2100
+ target: { value: next, name },
2101
+ currentTarget: { value: next, name },
2102
+ type: "change"
2103
+ };
2104
+ onChange(synthetic);
2105
+ }
2106
+ },
2107
+ [onValueChange, onChange, name]
2108
+ );
2109
+ return /* @__PURE__ */ jsxRuntime.jsx(
2110
+ RadixRadioGroup__namespace.Root,
2111
+ {
2112
+ ref,
2113
+ id: groupId,
2114
+ value,
2115
+ defaultValue,
2116
+ onValueChange: handleValueChange,
2117
+ onBlur,
2118
+ disabled,
2119
+ required,
2120
+ name,
2121
+ orientation,
2122
+ "aria-label": ariaLabel,
2123
+ "aria-labelledby": ariaLabelledBy,
2124
+ "aria-describedby": ariaDescribedBy,
2125
+ "aria-invalid": ariaInvalid,
2126
+ "data-slot": "radio-group",
2127
+ className: cn(radioGroupBaseClass, radioGroupOrientationClass[orientation], className),
2128
+ children: children ?? options?.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
2129
+ RadioGroupOptionRow,
2130
+ {
2131
+ option: opt,
2132
+ radioSize,
2133
+ groupId
2134
+ },
2135
+ opt.value
2136
+ ))
2137
+ }
2138
+ );
2139
+ });
2140
+ function RadioGroupOptionRow({ option, radioSize, groupId }) {
2141
+ const itemId = `${groupId}-${option.value}`;
2142
+ return /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: itemId, className: radioOptionRowClass, children: [
2143
+ /* @__PURE__ */ jsxRuntime.jsx(
2144
+ RadixRadioGroup__namespace.Item,
2145
+ {
2146
+ id: itemId,
2147
+ value: option.value,
2148
+ disabled: option.disabled,
2149
+ "data-slot": "radio-item",
2150
+ className: cn(radioItemBaseClass, radioItemSizeClass[radioSize], "mt-0.5"),
2151
+ children: /* @__PURE__ */ jsxRuntime.jsx(RadixRadioGroup__namespace.Indicator, { className: radioIndicatorBaseClass, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(radioIndicatorDotClass, radioIndicatorSizeClass[radioSize]) }) })
2152
+ }
2153
+ ),
2154
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1 leading-tight", children: [
2155
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("block font-medium text-foreground", radioLabelSizeClass[radioSize]), children: option.label }),
2156
+ option.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5 block text-xs text-muted-foreground", children: option.description }) : null
2157
+ ] })
2158
+ ] });
2159
+ }
2160
+ var RadioGroupItem = react.forwardRef(function RadioGroupItem2({ className, radioSize = "md", ...props }, ref) {
2161
+ return /* @__PURE__ */ jsxRuntime.jsx(
2162
+ RadixRadioGroup__namespace.Item,
2163
+ {
2164
+ ref,
2165
+ "data-slot": "radio-item",
2166
+ className: cn(radioItemBaseClass, radioItemSizeClass[radioSize], className),
2167
+ ...props,
2168
+ children: /* @__PURE__ */ jsxRuntime.jsx(RadixRadioGroup__namespace.Indicator, { className: radioIndicatorBaseClass, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(radioIndicatorDotClass, radioIndicatorSizeClass[radioSize]) }) })
2169
+ }
2170
+ );
2171
+ });
2172
+
2173
+ // src/components/switch/switchVariants.ts
2174
+ var switchTrackClass = {
2175
+ sm: "h-4 w-7",
2176
+ md: "h-5 w-9",
2177
+ lg: "h-6 w-11"
2178
+ };
2179
+ var switchThumbClass = {
2180
+ sm: "size-3 data-[state=checked]:translate-x-3 data-[state=checked]:rtl:-translate-x-3",
2181
+ md: "size-4 data-[state=checked]:translate-x-4 data-[state=checked]:rtl:-translate-x-4",
2182
+ lg: "size-5 data-[state=checked]:translate-x-5 data-[state=checked]:rtl:-translate-x-5"
2183
+ };
2184
+ var switchTrackBaseClass = "relative inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent bg-input transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary aria-[invalid=true]:ring-2 aria-[invalid=true]:ring-destructive/40";
2185
+ var switchThumbBaseClass = "pointer-events-none block rounded-full bg-background shadow-sm ring-0 transition-transform";
2186
+ var Switch = react.forwardRef(function Switch2({
2187
+ switchSize = "md",
2188
+ checked,
2189
+ defaultChecked,
2190
+ onCheckedChange,
2191
+ value,
2192
+ onChange,
2193
+ onBlur,
2194
+ name,
2195
+ disabled,
2196
+ required,
2197
+ id,
2198
+ className,
2199
+ "aria-label": ariaLabel,
2200
+ "aria-describedby": ariaDescribedBy,
2201
+ "aria-invalid": ariaInvalid
2202
+ }, ref) {
2203
+ const generatedId = react.useId();
2204
+ const switchId = id ?? generatedId;
2205
+ const resolvedChecked = checked ?? (value === void 0 ? void 0 : Boolean(value));
2206
+ const handleCheckedChange = react.useCallback(
2207
+ (next) => {
2208
+ onCheckedChange?.(next);
2209
+ if (onChange) {
2210
+ const synthetic = {
2211
+ target: { checked: next, value: next, name },
2212
+ currentTarget: { checked: next, value: next, name },
2213
+ type: "change"
2214
+ };
2215
+ onChange(synthetic);
2216
+ }
2217
+ },
2218
+ [onCheckedChange, onChange, name]
2219
+ );
2220
+ return /* @__PURE__ */ jsxRuntime.jsx(
2221
+ RadixSwitch__namespace.Root,
2222
+ {
2223
+ ref,
2224
+ id: switchId,
2225
+ checked: resolvedChecked,
2226
+ defaultChecked,
2227
+ onCheckedChange: handleCheckedChange,
2228
+ onBlur,
2229
+ disabled,
2230
+ required,
2231
+ name,
2232
+ "aria-label": ariaLabel,
2233
+ "aria-invalid": ariaInvalid,
2234
+ "aria-describedby": ariaDescribedBy,
2235
+ "data-slot": "switch-track",
2236
+ className: cn(switchTrackBaseClass, switchTrackClass[switchSize], className),
2237
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2238
+ RadixSwitch__namespace.Thumb,
2239
+ {
2240
+ "data-slot": "switch-thumb",
2241
+ className: cn(switchThumbBaseClass, switchThumbClass[switchSize])
2242
+ }
2243
+ )
2244
+ }
2245
+ );
2246
+ });
1851
2247
 
1852
2248
  // src/components/textarea/textareaVariants.ts
1853
2249
  var textareaVariantClass = {
@@ -1917,12 +2313,23 @@ var Textarea = react.forwardRef(function Textarea2({
1917
2313
 
1918
2314
  exports.AppShell = AppShell;
1919
2315
  exports.Avatar = Avatar;
2316
+ exports.Badge = Badge;
1920
2317
  exports.Button = Button;
1921
2318
  exports.Checkbox = Checkbox;
1922
2319
  exports.DashboardContent = DashboardContent;
1923
2320
  exports.DashboardHeader = DashboardHeader;
1924
2321
  exports.DashboardLayout = DashboardLayout;
1925
2322
  exports.DashboardMain = DashboardMain;
2323
+ exports.DropdownMenu = DropdownMenu;
2324
+ exports.DropdownMenuContent = DropdownMenuContent;
2325
+ exports.DropdownMenuGroup = DropdownMenuGroup;
2326
+ exports.DropdownMenuItem = DropdownMenuItem;
2327
+ exports.DropdownMenuLabel = DropdownMenuLabel;
2328
+ exports.DropdownMenuPortal = DropdownMenuPortal;
2329
+ exports.DropdownMenuSeparator = DropdownMenuSeparator;
2330
+ exports.DropdownMenuShortcut = DropdownMenuShortcut;
2331
+ exports.DropdownMenuTrigger = DropdownMenuTrigger;
2332
+ exports.EmptyState = EmptyState;
1926
2333
  exports.Field = Field;
1927
2334
  exports.HeaderActions = HeaderActions;
1928
2335
  exports.HeaderCollapseTrigger = HeaderCollapseTrigger;
@@ -1931,6 +2338,8 @@ exports.HeaderSearch = HeaderSearch;
1931
2338
  exports.HeaderTitle = HeaderTitle;
1932
2339
  exports.Input = Input;
1933
2340
  exports.LanguageSwitcher = LanguageSwitcher;
2341
+ exports.ListPage = ListPage;
2342
+ exports.PageHeader = PageHeader;
1934
2343
  exports.RadioGroup = RadioGroup;
1935
2344
  exports.RadioGroupItem = RadioGroupItem;
1936
2345
  exports.Select = Select;
@@ -1944,13 +2353,41 @@ exports.SidebarNavItem = SidebarNavItem;
1944
2353
  exports.Switch = Switch;
1945
2354
  exports.Table = Table;
1946
2355
  exports.Textarea = Textarea;
2356
+ exports.badgeBaseClass = badgeBaseClass;
2357
+ exports.badgeDotSizeClass = badgeDotSizeClass;
2358
+ exports.badgeSizeClass = badgeSizeClass;
2359
+ exports.badgeVariantClass = badgeVariantClass;
1947
2360
  exports.buttonBaseClass = buttonBaseClass;
1948
2361
  exports.buttonSizeClass = buttonSizeClass;
1949
2362
  exports.buttonVariantClass = buttonVariantClass;
1950
2363
  exports.cn = cn;
2364
+ exports.dropdownMenuContentClass = dropdownMenuContentClass;
2365
+ exports.dropdownMenuItemBaseClass = dropdownMenuItemBaseClass;
2366
+ exports.dropdownMenuItemInsetClass = dropdownMenuItemInsetClass;
2367
+ exports.dropdownMenuItemVariantClass = dropdownMenuItemVariantClass;
2368
+ exports.dropdownMenuLabelClass = dropdownMenuLabelClass;
2369
+ exports.dropdownMenuSeparatorClass = dropdownMenuSeparatorClass;
2370
+ exports.dropdownMenuShortcutClass = dropdownMenuShortcutClass;
2371
+ exports.emptyStateActionsSpacingClass = emptyStateActionsSpacingClass;
2372
+ exports.emptyStateBaseClass = emptyStateBaseClass;
2373
+ exports.emptyStateContainerSizeClass = emptyStateContainerSizeClass;
2374
+ exports.emptyStateDescriptionSizeClass = emptyStateDescriptionSizeClass;
2375
+ exports.emptyStateIconWrapperBaseClass = emptyStateIconWrapperBaseClass;
2376
+ exports.emptyStateIconWrapperSizeClass = emptyStateIconWrapperSizeClass;
2377
+ exports.emptyStateTitleSizeClass = emptyStateTitleSizeClass;
1951
2378
  exports.inputBaseClass = inputBaseClass;
1952
2379
  exports.inputSizeClass = inputSizeClass;
1953
2380
  exports.inputVariantClass = inputVariantClass;
2381
+ exports.pageHeaderActionsClass = pageHeaderActionsClass;
2382
+ exports.pageHeaderBackClass = pageHeaderBackClass;
2383
+ exports.pageHeaderBackIconClass = pageHeaderBackIconClass;
2384
+ exports.pageHeaderBaseClass = pageHeaderBaseClass;
2385
+ exports.pageHeaderBorderedClass = pageHeaderBorderedClass;
2386
+ exports.pageHeaderBreadcrumbsClass = pageHeaderBreadcrumbsClass;
2387
+ exports.pageHeaderDescriptionClass = pageHeaderDescriptionClass;
2388
+ exports.pageHeaderTitleBlockClass = pageHeaderTitleBlockClass;
2389
+ exports.pageHeaderTitleClass = pageHeaderTitleClass;
2390
+ exports.pageHeaderTitleRowClass = pageHeaderTitleRowClass;
1954
2391
  exports.radioGroupBaseClass = radioGroupBaseClass;
1955
2392
  exports.radioGroupOrientationClass = radioGroupOrientationClass;
1956
2393
  exports.radioIndicatorBaseClass = radioIndicatorBaseClass;