@optilogic/core 1.0.0-beta.2 → 1.0.0-beta.3

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
@@ -894,18 +894,104 @@ var AlertDialogCancel = React33__namespace.forwardRef(({ className, ...props },
894
894
  }
895
895
  ));
896
896
  AlertDialogCancel.displayName = AlertDialogPrimitive__namespace.Cancel.displayName;
897
- var Card = React33__namespace.forwardRef(
898
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
899
- "div",
900
- {
901
- ref,
902
- className: cn(
903
- "rounded-xl border bg-card text-card-foreground shadow",
904
- className
905
- ),
906
- ...props
897
+ var cardVariants = classVarianceAuthority.cva(
898
+ "rounded-xl border bg-card text-card-foreground shadow",
899
+ {
900
+ variants: {
901
+ /**
902
+ * Card width size presets
903
+ */
904
+ size: {
905
+ auto: "",
906
+ sm: "w-64",
907
+ md: "w-80",
908
+ lg: "w-96",
909
+ xl: "w-[28rem]",
910
+ full: "w-full"
911
+ },
912
+ /**
913
+ * Hover effect styles
914
+ */
915
+ hover: {
916
+ none: "",
917
+ lift: "transition-all duration-200 hover:-translate-y-1 hover:shadow-lg",
918
+ glow: "transition-shadow duration-200 hover:shadow-lg hover:shadow-accent/20",
919
+ border: "transition-colors duration-200 hover:border-accent",
920
+ "border-success": "transition-colors duration-200 hover:border-success",
921
+ "border-warning": "transition-colors duration-200 hover:border-warning",
922
+ "border-destructive": "transition-colors duration-200 hover:border-destructive",
923
+ "border-muted": "transition-colors duration-200 hover:border-muted-foreground",
924
+ scale: "transition-transform duration-200 hover:scale-[1.02]"
925
+ },
926
+ /**
927
+ * Whether the card is interactive (clickable)
928
+ */
929
+ interactive: {
930
+ true: "cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
931
+ false: ""
932
+ },
933
+ /**
934
+ * Card padding density
935
+ */
936
+ padding: {
937
+ none: "",
938
+ sm: "[&>*:not(img)]:p-3 [&>*:not(img)]:pt-3",
939
+ md: "",
940
+ lg: "[&>*:not(img)]:p-8 [&>*:not(img)]:pt-8"
941
+ }
942
+ },
943
+ defaultVariants: {
944
+ size: "auto",
945
+ hover: "none",
946
+ interactive: false,
947
+ padding: "md"
907
948
  }
908
- )
949
+ }
950
+ );
951
+ var Card = React33__namespace.forwardRef(
952
+ ({
953
+ className,
954
+ size,
955
+ hover,
956
+ interactive,
957
+ padding,
958
+ asButton,
959
+ hoverBorderClass,
960
+ onClick,
961
+ onKeyDown,
962
+ ...props
963
+ }, ref) => {
964
+ const isInteractive = interactive || asButton || !!onClick;
965
+ const handleKeyDown = React33__namespace.useCallback(
966
+ (e) => {
967
+ if (isInteractive && (e.key === "Enter" || e.key === " ")) {
968
+ e.preventDefault();
969
+ onClick?.(e);
970
+ }
971
+ onKeyDown?.(e);
972
+ },
973
+ [isInteractive, onClick, onKeyDown]
974
+ );
975
+ return /* @__PURE__ */ jsxRuntime.jsx(
976
+ "div",
977
+ {
978
+ ref,
979
+ role: isInteractive ? "button" : void 0,
980
+ tabIndex: isInteractive ? 0 : void 0,
981
+ className: cn(
982
+ cardVariants({ size, hover, interactive: isInteractive, padding }),
983
+ "group relative",
984
+ // Custom hover border color overrides variant if provided
985
+ hoverBorderClass && "transition-colors duration-200",
986
+ hoverBorderClass,
987
+ className
988
+ ),
989
+ onClick,
990
+ onKeyDown: handleKeyDown,
991
+ ...props
992
+ }
993
+ );
994
+ }
909
995
  );
910
996
  Card.displayName = "Card";
911
997
  var CardHeader = React33__namespace.forwardRef(
@@ -956,6 +1042,300 @@ var CardFooter = React33__namespace.forwardRef(
956
1042
  )
957
1043
  );
958
1044
  CardFooter.displayName = "CardFooter";
1045
+ var cardImageVariants = classVarianceAuthority.cva("w-full object-cover", {
1046
+ variants: {
1047
+ /**
1048
+ * Image aspect ratio
1049
+ */
1050
+ aspectRatio: {
1051
+ auto: "",
1052
+ square: "aspect-square",
1053
+ video: "aspect-video",
1054
+ wide: "aspect-[2/1]",
1055
+ portrait: "aspect-[3/4]"
1056
+ },
1057
+ /**
1058
+ * Image position in the card
1059
+ */
1060
+ position: {
1061
+ top: "rounded-t-xl",
1062
+ bottom: "rounded-b-xl",
1063
+ fill: "rounded-xl"
1064
+ }
1065
+ },
1066
+ defaultVariants: {
1067
+ aspectRatio: "video",
1068
+ position: "top"
1069
+ }
1070
+ });
1071
+ var CardImage = React33__namespace.forwardRef(
1072
+ ({ className, aspectRatio, position, fallback, alt, src, onError, ...props }, ref) => {
1073
+ const [hasError, setHasError] = React33__namespace.useState(false);
1074
+ const handleError = React33__namespace.useCallback(
1075
+ (e) => {
1076
+ setHasError(true);
1077
+ onError?.(e);
1078
+ },
1079
+ [onError]
1080
+ );
1081
+ React33__namespace.useEffect(() => {
1082
+ setHasError(false);
1083
+ }, [src]);
1084
+ if (hasError && fallback) {
1085
+ return /* @__PURE__ */ jsxRuntime.jsx(
1086
+ "div",
1087
+ {
1088
+ className: cn(
1089
+ "flex items-center justify-center bg-muted",
1090
+ cardImageVariants({ aspectRatio, position }),
1091
+ className
1092
+ ),
1093
+ children: fallback
1094
+ }
1095
+ );
1096
+ }
1097
+ return /* @__PURE__ */ jsxRuntime.jsx(
1098
+ "img",
1099
+ {
1100
+ ref,
1101
+ src,
1102
+ alt,
1103
+ className: cn(cardImageVariants({ aspectRatio, position }), className),
1104
+ onError: handleError,
1105
+ ...props
1106
+ }
1107
+ );
1108
+ }
1109
+ );
1110
+ CardImage.displayName = "CardImage";
1111
+ var cardActionsVariants = classVarianceAuthority.cva(
1112
+ "absolute flex items-center gap-1 transition-opacity duration-200 z-10",
1113
+ {
1114
+ variants: {
1115
+ /**
1116
+ * When to show the actions
1117
+ */
1118
+ showOn: {
1119
+ hover: "opacity-0 group-hover:opacity-100",
1120
+ always: "opacity-100"
1121
+ },
1122
+ /**
1123
+ * Position of the actions overlay
1124
+ */
1125
+ position: {
1126
+ "top-right": "top-2 right-2",
1127
+ "top-left": "top-2 left-2",
1128
+ "bottom-right": "bottom-2 right-2",
1129
+ "bottom-left": "bottom-2 left-2"
1130
+ },
1131
+ /**
1132
+ * Visual style of the actions container
1133
+ */
1134
+ variant: {
1135
+ /** Solid background with backdrop blur */
1136
+ floating: "bg-background/90 backdrop-blur-sm rounded-md shadow-sm p-1",
1137
+ /** No background, just spacing */
1138
+ ghost: "p-1",
1139
+ /** Muted bar background */
1140
+ bar: "bg-muted/80 backdrop-blur-sm rounded-md p-1.5",
1141
+ /** No background on container, icons get background on hover */
1142
+ "icon-hover": "p-0 [&>button]:bg-transparent [&>button]:hover:bg-background/90 [&>button]:hover:shadow-sm [&>button]:transition-all"
1143
+ }
1144
+ },
1145
+ defaultVariants: {
1146
+ showOn: "hover",
1147
+ position: "top-right",
1148
+ variant: "floating"
1149
+ }
1150
+ }
1151
+ );
1152
+ var CardActions = React33__namespace.forwardRef(
1153
+ ({ className, showOn, position, variant, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1154
+ "div",
1155
+ {
1156
+ ref,
1157
+ className: cn(cardActionsVariants({ showOn, position, variant }), className),
1158
+ onClick: (e) => e.stopPropagation(),
1159
+ ...props
1160
+ }
1161
+ )
1162
+ );
1163
+ CardActions.displayName = "CardActions";
1164
+ var SelectableCard = React33__namespace.forwardRef(
1165
+ ({
1166
+ className,
1167
+ selected: controlledSelected,
1168
+ defaultSelected = false,
1169
+ onSelectedChange,
1170
+ showCheckbox = false,
1171
+ checkboxPosition = "top-right",
1172
+ disabled = false,
1173
+ children,
1174
+ onClick,
1175
+ hover = "border",
1176
+ ...props
1177
+ }, ref) => {
1178
+ const [uncontrolledSelected, setUncontrolledSelected] = React33__namespace.useState(defaultSelected);
1179
+ const isControlled = controlledSelected !== void 0;
1180
+ const isSelected = isControlled ? controlledSelected : uncontrolledSelected;
1181
+ const handleClick = React33__namespace.useCallback(
1182
+ (e) => {
1183
+ if (disabled) return;
1184
+ const newSelected = !isSelected;
1185
+ if (!isControlled) {
1186
+ setUncontrolledSelected(newSelected);
1187
+ }
1188
+ onSelectedChange?.(newSelected);
1189
+ onClick?.(e);
1190
+ },
1191
+ [disabled, isSelected, isControlled, onSelectedChange, onClick]
1192
+ );
1193
+ const handleCheckboxChange = React33__namespace.useCallback(
1194
+ (checked) => {
1195
+ if (disabled) return;
1196
+ const newSelected = checked === true;
1197
+ if (!isControlled) {
1198
+ setUncontrolledSelected(newSelected);
1199
+ }
1200
+ onSelectedChange?.(newSelected);
1201
+ },
1202
+ [disabled, isControlled, onSelectedChange]
1203
+ );
1204
+ const isInline = checkboxPosition === "inline-left";
1205
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1206
+ Card,
1207
+ {
1208
+ ref,
1209
+ className: cn(
1210
+ // Selection styling
1211
+ isSelected && "ring-2 ring-accent border-accent",
1212
+ disabled && "opacity-50 cursor-not-allowed",
1213
+ className
1214
+ ),
1215
+ interactive: !disabled,
1216
+ hover: disabled ? "none" : hover,
1217
+ onClick: handleClick,
1218
+ "aria-selected": isSelected,
1219
+ "aria-disabled": disabled,
1220
+ ...props,
1221
+ children: [
1222
+ showCheckbox && isInline && /* @__PURE__ */ jsxRuntime.jsxs(
1223
+ "div",
1224
+ {
1225
+ className: "flex items-center gap-3 px-4 py-3 border-b border-border/50",
1226
+ onClick: (e) => e.stopPropagation(),
1227
+ children: [
1228
+ /* @__PURE__ */ jsxRuntime.jsx(
1229
+ Checkbox,
1230
+ {
1231
+ checked: isSelected,
1232
+ onCheckedChange: handleCheckboxChange,
1233
+ disabled
1234
+ }
1235
+ ),
1236
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: isSelected ? "Selected" : "Click to select" })
1237
+ ]
1238
+ }
1239
+ ),
1240
+ showCheckbox && !isInline && /* @__PURE__ */ jsxRuntime.jsx(
1241
+ "div",
1242
+ {
1243
+ className: cn(
1244
+ "absolute z-10 p-1 bg-background/90 backdrop-blur-sm rounded-md",
1245
+ checkboxPosition === "top-left" ? "top-2 left-2" : "top-2 right-2"
1246
+ ),
1247
+ onClick: (e) => e.stopPropagation(),
1248
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1249
+ Checkbox,
1250
+ {
1251
+ checked: isSelected,
1252
+ onCheckedChange: handleCheckboxChange,
1253
+ disabled
1254
+ }
1255
+ )
1256
+ }
1257
+ ),
1258
+ children
1259
+ ]
1260
+ }
1261
+ );
1262
+ }
1263
+ );
1264
+ SelectableCard.displayName = "SelectableCard";
1265
+ var cardGridVariants = classVarianceAuthority.cva("grid", {
1266
+ variants: {
1267
+ /**
1268
+ * Number of columns
1269
+ */
1270
+ columns: {
1271
+ 1: "grid-cols-1",
1272
+ 2: "grid-cols-1 sm:grid-cols-2",
1273
+ 3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
1274
+ 4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
1275
+ auto: "grid-cols-[repeat(auto-fill,minmax(280px,1fr))]"
1276
+ },
1277
+ /**
1278
+ * Gap between cards
1279
+ */
1280
+ gap: {
1281
+ none: "gap-0",
1282
+ sm: "gap-3",
1283
+ md: "gap-4",
1284
+ lg: "gap-6",
1285
+ xl: "gap-8"
1286
+ }
1287
+ },
1288
+ defaultVariants: {
1289
+ columns: "auto",
1290
+ gap: "md"
1291
+ }
1292
+ });
1293
+ var CardGrid = React33__namespace.forwardRef(
1294
+ ({ className, columns, gap, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1295
+ "div",
1296
+ {
1297
+ ref,
1298
+ className: cn(cardGridVariants({ columns, gap }), className),
1299
+ ...props
1300
+ }
1301
+ )
1302
+ );
1303
+ CardGrid.displayName = "CardGrid";
1304
+ var cardListVariants = classVarianceAuthority.cva("flex flex-col", {
1305
+ variants: {
1306
+ /**
1307
+ * Gap between cards
1308
+ */
1309
+ gap: {
1310
+ none: "gap-0",
1311
+ sm: "gap-2",
1312
+ md: "gap-4",
1313
+ lg: "gap-6"
1314
+ },
1315
+ /**
1316
+ * Whether to show dividers between cards
1317
+ */
1318
+ divided: {
1319
+ true: "[&>*:not(:last-child)]:border-b [&>*:not(:last-child)]:pb-4 [&>*:not(:last-child)]:rounded-b-none",
1320
+ false: ""
1321
+ }
1322
+ },
1323
+ defaultVariants: {
1324
+ gap: "md",
1325
+ divided: false
1326
+ }
1327
+ });
1328
+ var CardList = React33__namespace.forwardRef(
1329
+ ({ className, gap, divided, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1330
+ "div",
1331
+ {
1332
+ ref,
1333
+ className: cn(cardListVariants({ gap, divided }), className),
1334
+ ...props
1335
+ }
1336
+ )
1337
+ );
1338
+ CardList.displayName = "CardList";
959
1339
  var Table = React33__namespace.forwardRef(
960
1340
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
961
1341
  "table",
@@ -5878,10 +6258,14 @@ exports.Button = Button;
5878
6258
  exports.CYBERPUNK_THEME = CYBERPUNK_THEME;
5879
6259
  exports.Calendar = Calendar;
5880
6260
  exports.Card = Card;
6261
+ exports.CardActions = CardActions;
5881
6262
  exports.CardContent = CardContent;
5882
6263
  exports.CardDescription = CardDescription;
5883
6264
  exports.CardFooter = CardFooter;
6265
+ exports.CardGrid = CardGrid;
5884
6266
  exports.CardHeader = CardHeader;
6267
+ exports.CardImage = CardImage;
6268
+ exports.CardList = CardList;
5885
6269
  exports.CardTitle = CardTitle;
5886
6270
  exports.CellEditor = CellEditor;
5887
6271
  exports.Checkbox = Checkbox;
@@ -5943,6 +6327,7 @@ exports.SelectScrollUpButton = SelectScrollUpButton;
5943
6327
  exports.SelectSeparator = SelectSeparator;
5944
6328
  exports.SelectTrigger = SelectTrigger;
5945
6329
  exports.SelectValue = SelectValue;
6330
+ exports.SelectableCard = SelectableCard;
5946
6331
  exports.Separator = Separator;
5947
6332
  exports.Skeleton = Skeleton;
5948
6333
  exports.Switch = Switch;
@@ -5978,6 +6363,11 @@ exports.applyTheme = applyTheme;
5978
6363
  exports.areThemesEqual = areThemesEqual;
5979
6364
  exports.badgeVariants = badgeVariants;
5980
6365
  exports.buttonVariants = buttonVariants;
6366
+ exports.cardActionsVariants = cardActionsVariants;
6367
+ exports.cardGridVariants = cardGridVariants;
6368
+ exports.cardImageVariants = cardImageVariants;
6369
+ exports.cardListVariants = cardListVariants;
6370
+ exports.cardVariants = cardVariants;
5981
6371
  exports.cloneTheme = cloneTheme;
5982
6372
  exports.cn = cn;
5983
6373
  exports.exportTheme = exportTheme;