@mirror-physics/fractal-ui 0.2.0-next.10 → 0.2.0-next.15

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
@@ -40,7 +40,9 @@ __export(index_exports, {
40
40
  CardFooter: () => CardFooter,
41
41
  CardHeader: () => CardHeader,
42
42
  CardTitle: () => CardTitle,
43
+ Checkbox: () => Checkbox,
43
44
  Chip: () => Chip,
45
+ ContentSwitcher: () => ContentSwitcher,
44
46
  DataTable: () => DataTable,
45
47
  Disclosure: () => Disclosure,
46
48
  Dropdown: () => Dropdown,
@@ -49,8 +51,10 @@ __export(index_exports, {
49
51
  FolderCard: () => FolderCard,
50
52
  Input: () => Input,
51
53
  Label: () => Label,
54
+ LatticeLoader: () => LatticeLoader,
52
55
  Link: () => Link,
53
56
  Modal: () => Modal,
57
+ Pagination: () => Pagination,
54
58
  PromptCard: () => PromptCard,
55
59
  PromptGrid: () => PromptGrid,
56
60
  SidePanel: () => SidePanel,
@@ -63,6 +67,7 @@ __export(index_exports, {
63
67
  SidebarSection: () => SidebarSection,
64
68
  SortableTable: () => SortableTable,
65
69
  Tabs: () => Tabs,
70
+ TextButton: () => TextButton,
66
71
  Textarea: () => Textarea,
67
72
  Toggle: () => Toggle,
68
73
  cn: () => cn,
@@ -736,16 +741,43 @@ var Chip = React9.forwardRef(
736
741
  );
737
742
  Chip.displayName = "Chip";
738
743
 
739
- // src/components/SortableTable/SortableTable.tsx
740
- var import_react2 = require("react");
744
+ // src/components/Checkbox/Checkbox.tsx
741
745
  var import_fractal_icons3 = require("@mirror-physics/fractal-icons");
742
746
  var import_jsx_runtime13 = require("react/jsx-runtime");
747
+ function Checkbox({ checked, onCheckedChange, className, disabled, onClick, onKeyDown, ...props }) {
748
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
749
+ "button",
750
+ {
751
+ ...props,
752
+ className: cn("fractal-checkbox", checked && "fractal-checkbox--checked", className),
753
+ type: "button",
754
+ role: "checkbox",
755
+ "aria-checked": checked,
756
+ disabled,
757
+ onClick: (event) => {
758
+ onClick?.(event);
759
+ if (!event.defaultPrevented) onCheckedChange(!checked);
760
+ },
761
+ onKeyDown: (event) => {
762
+ onKeyDown?.(event);
763
+ if (event.key === " " || event.key === "Enter") event.stopPropagation();
764
+ },
765
+ children: checked ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_fractal_icons3.CheckboxChecked, { "aria-hidden": "true", size: 18 }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_fractal_icons3.Checkbox, { "aria-hidden": "true", size: 18 })
766
+ }
767
+ );
768
+ }
769
+
770
+ // src/components/SortableTable/SortableTable.tsx
771
+ var import_react2 = require("react");
772
+ var import_fractal_icons4 = require("@mirror-physics/fractal-icons");
773
+ var import_jsx_runtime14 = require("react/jsx-runtime");
743
774
  function SortableTable({
744
775
  columns,
745
776
  data,
746
777
  emptyMessage,
747
778
  header,
748
779
  size = "md",
780
+ embedded = false,
749
781
  className,
750
782
  defaultSortKey = void 0,
751
783
  defaultSortDirection = null,
@@ -753,7 +785,8 @@ function SortableTable({
753
785
  sortDirection: controlledDirection,
754
786
  onSortChange,
755
787
  highlightRow,
756
- onRowClick
788
+ onRowClick,
789
+ rowAction
757
790
  }) {
758
791
  const [internalKey, setInternalKey] = (0, import_react2.useState)(defaultSortKey ?? null);
759
792
  const [internalDirection, setInternalDirection] = (0, import_react2.useState)(defaultSortDirection);
@@ -806,13 +839,13 @@ function SortableTable({
806
839
  onSortChange?.(nextKey, nextDirection);
807
840
  }
808
841
  };
809
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("fractal-sortable-table", `fractal-sortable-table--${size}`, className), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "fractal-sortable-table-surface", children: [
810
- header && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fractal-sortable-table-header", children: header }),
811
- sorted.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fractal-sortable-table-empty", children: emptyMessage || "No data" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("table", { className: "fractal-sortable-table-table", children: [
812
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tr", { className: "fractal-sortable-table-thead-row", children: columns.map((col) => {
842
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: cn("fractal-sortable-table", `fractal-sortable-table--${size}`, embedded && "fractal-sortable-table--embedded", className), children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "fractal-sortable-table-surface", children: [
843
+ header && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "fractal-sortable-table-header", children: header }),
844
+ sorted.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "fractal-sortable-table-empty", children: emptyMessage || "No data" }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("table", { className: "fractal-sortable-table-table", children: [
845
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("tr", { className: "fractal-sortable-table-thead-row", children: columns.map((col) => {
813
846
  const isActive = activeKey === col.key && activeDirection !== null;
814
847
  if (!col.sortable) {
815
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
848
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
816
849
  "th",
817
850
  {
818
851
  className: "fractal-sortable-table-th",
@@ -822,12 +855,12 @@ function SortableTable({
822
855
  col.key
823
856
  );
824
857
  }
825
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
858
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
826
859
  "th",
827
860
  {
828
861
  className: "fractal-sortable-table-th fractal-sortable-table-th--sortable",
829
862
  style: { width: col.width },
830
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
863
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
831
864
  "button",
832
865
  {
833
866
  type: "button",
@@ -838,8 +871,8 @@ function SortableTable({
838
871
  onClick: () => handleSortClick(col.key),
839
872
  "aria-sort": isActive ? activeDirection === "asc" ? "ascending" : "descending" : "none",
840
873
  children: [
841
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: col.header }),
842
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "fractal-sortable-table-sort-icon", "aria-hidden": "true", children: isActive && activeDirection === "asc" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_fractal_icons3.ArrowUp, { size: 14 }) : isActive && activeDirection === "desc" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_fractal_icons3.ArrowDown, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_fractal_icons3.ArrowsUpDown, { size: 14 }) })
874
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: col.header }),
875
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "fractal-sortable-table-sort-icon", "aria-hidden": "true", children: isActive && activeDirection === "asc" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_fractal_icons4.ArrowUp, { size: 14 }) : isActive && activeDirection === "desc" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_fractal_icons4.ArrowDown, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_fractal_icons4.ArrowsUpDown, { size: 14 }) })
843
876
  ]
844
877
  }
845
878
  )
@@ -847,9 +880,13 @@ function SortableTable({
847
880
  col.key
848
881
  );
849
882
  }) }) }),
850
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tbody", { children: sorted.map((row, rowIndex) => {
883
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("tbody", { children: sorted.map((row, rowIndex) => {
851
884
  const highlighted = highlightRow?.(row, rowIndex) ?? false;
852
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
885
+ const action = rowAction ? {
886
+ label: rowAction.label(row, rowIndex),
887
+ icon: rowAction.icon(row, rowIndex)
888
+ } : null;
889
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
853
890
  "tr",
854
891
  {
855
892
  className: cn(
@@ -864,14 +901,21 @@ function SortableTable({
864
901
  onRowClick(row, rowIndex);
865
902
  }
866
903
  } : void 0,
904
+ "aria-label": action?.label,
867
905
  role: onRowClick ? "button" : void 0,
868
906
  tabIndex: onRowClick ? 0 : void 0,
869
- children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
907
+ children: columns.map((col, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
870
908
  "td",
871
909
  {
872
- className: "fractal-sortable-table-td",
910
+ className: cn(
911
+ "fractal-sortable-table-td",
912
+ action && columnIndex === columns.length - 1 && "fractal-sortable-table-td--row-action"
913
+ ),
873
914
  style: { width: col.width, textAlign: col.align ?? "left" },
874
- children: col.render(row, rowIndex)
915
+ children: [
916
+ col.render(row, rowIndex),
917
+ action && columnIndex === columns.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "fractal-sortable-table-row-action", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "fractal-sortable-table-row-action__icon", children: action.icon }) })
918
+ ]
875
919
  },
876
920
  col.key
877
921
  ))
@@ -885,7 +929,7 @@ function SortableTable({
885
929
 
886
930
  // src/components/Tabs/Tabs.tsx
887
931
  var import_react3 = require("react");
888
- var import_jsx_runtime14 = require("react/jsx-runtime");
932
+ var import_jsx_runtime15 = require("react/jsx-runtime");
889
933
  function Tabs({
890
934
  items,
891
935
  defaultValue,
@@ -935,12 +979,12 @@ function Tabs({
935
979
  selectTab(nextId2);
936
980
  requestAnimationFrame(() => tabRefs.current[nextId2]?.focus());
937
981
  };
938
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: cn("fractal-tabs", className), children: [
939
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { role: "tablist", "aria-label": ariaLabel, className: "fractal-tabs-list", children: items.map((item) => {
982
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: cn("fractal-tabs", className), children: [
983
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { role: "tablist", "aria-label": ariaLabel, className: "fractal-tabs-list", children: items.map((item) => {
940
984
  const isActive = item.id === activeId;
941
985
  const tabId = `${reactId}-tab-${item.id}`;
942
986
  const panelId = `${reactId}-panel-${item.id}`;
943
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
987
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
944
988
  "button",
945
989
  {
946
990
  ref: (el) => {
@@ -969,7 +1013,7 @@ function Tabs({
969
1013
  const tabId = `${reactId}-tab-${item.id}`;
970
1014
  const panelId = `${reactId}-panel-${item.id}`;
971
1015
  const isActive = item.id === activeId;
972
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1016
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
973
1017
  "div",
974
1018
  {
975
1019
  id: panelId,
@@ -985,10 +1029,55 @@ function Tabs({
985
1029
  ] });
986
1030
  }
987
1031
 
1032
+ // src/components/ContentSwitcher/ContentSwitcher.tsx
1033
+ var React10 = __toESM(require("react"), 1);
1034
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1035
+ function ContentSwitcher({ items, value, onValueChange, ariaLabel, fullWidth = false, className }) {
1036
+ const buttonRefs = React10.useRef([]);
1037
+ const moveFocus = (index, direction) => {
1038
+ let nextIndex = index;
1039
+ do {
1040
+ nextIndex = (nextIndex + direction + items.length) % items.length;
1041
+ } while (items[nextIndex]?.disabled && nextIndex !== index);
1042
+ if (!items[nextIndex]?.disabled) {
1043
+ buttonRefs.current[nextIndex]?.focus();
1044
+ onValueChange(items[nextIndex].value);
1045
+ }
1046
+ };
1047
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: cn("fractal-content-switcher", fullWidth && "fractal-content-switcher--full-width", className), role: "group", "aria-label": ariaLabel, children: items.map((item, index) => {
1048
+ const active = item.value === value;
1049
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1050
+ "button",
1051
+ {
1052
+ className: cn("fractal-content-switcher__item", active && "fractal-content-switcher__item--active"),
1053
+ type: "button",
1054
+ "aria-pressed": active,
1055
+ disabled: item.disabled,
1056
+ onClick: () => onValueChange(item.value),
1057
+ onKeyDown: (event) => {
1058
+ if (event.key === "ArrowRight") {
1059
+ event.preventDefault();
1060
+ moveFocus(index, 1);
1061
+ }
1062
+ if (event.key === "ArrowLeft") {
1063
+ event.preventDefault();
1064
+ moveFocus(index, -1);
1065
+ }
1066
+ },
1067
+ ref: (element) => {
1068
+ buttonRefs.current[index] = element;
1069
+ },
1070
+ children: item.label
1071
+ },
1072
+ item.value
1073
+ );
1074
+ }) });
1075
+ }
1076
+
988
1077
  // src/components/Disclosure/Disclosure.tsx
989
1078
  var import_react4 = require("react");
990
- var import_fractal_icons4 = require("@mirror-physics/fractal-icons");
991
- var import_jsx_runtime15 = require("react/jsx-runtime");
1079
+ var import_fractal_icons5 = require("@mirror-physics/fractal-icons");
1080
+ var import_jsx_runtime17 = require("react/jsx-runtime");
992
1081
  function Disclosure({
993
1082
  title,
994
1083
  meta,
@@ -996,6 +1085,7 @@ function Disclosure({
996
1085
  defaultOpen = false,
997
1086
  open: controlledOpen,
998
1087
  onOpenChange,
1088
+ disabled = false,
999
1089
  className,
1000
1090
  variant = "card"
1001
1091
  }) {
@@ -1006,6 +1096,7 @@ function Disclosure({
1006
1096
  const isControlled = controlledOpen !== void 0;
1007
1097
  const isOpen = isControlled ? controlledOpen : internalOpen;
1008
1098
  const toggle = () => {
1099
+ if (disabled) return;
1009
1100
  const next = !isOpen;
1010
1101
  if (isControlled) {
1011
1102
  onOpenChange?.(next);
@@ -1014,17 +1105,18 @@ function Disclosure({
1014
1105
  onOpenChange?.(next);
1015
1106
  }
1016
1107
  };
1017
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1108
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1018
1109
  "div",
1019
1110
  {
1020
1111
  className: cn(
1021
1112
  "fractal-disclosure",
1022
1113
  variant === "card" && "fractal-disclosure--card",
1023
1114
  isOpen && "fractal-disclosure--open",
1115
+ disabled && "fractal-disclosure--disabled",
1024
1116
  className
1025
1117
  ),
1026
1118
  children: [
1027
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1119
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1028
1120
  "button",
1029
1121
  {
1030
1122
  type: "button",
@@ -1032,15 +1124,16 @@ function Disclosure({
1032
1124
  className: "fractal-disclosure-trigger",
1033
1125
  "aria-expanded": isOpen,
1034
1126
  "aria-controls": panelId,
1127
+ disabled,
1035
1128
  onClick: toggle,
1036
1129
  children: [
1037
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "fractal-disclosure-icon", "aria-hidden": "true", children: isOpen ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_fractal_icons4.ChevronDown, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_fractal_icons4.ChevronRight, { size: 16 }) }),
1038
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "fractal-disclosure-title", children: title }),
1039
- meta && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "fractal-disclosure-meta", children: meta })
1130
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "fractal-disclosure-icon", "aria-hidden": "true", children: isOpen ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_fractal_icons5.ChevronDown, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_fractal_icons5.ChevronRight, { size: 16 }) }),
1131
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "fractal-disclosure-title", children: title }),
1132
+ meta && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "fractal-disclosure-meta", children: meta })
1040
1133
  ]
1041
1134
  }
1042
1135
  ),
1043
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1136
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1044
1137
  "div",
1045
1138
  {
1046
1139
  id: panelId,
@@ -1048,7 +1141,7 @@ function Disclosure({
1048
1141
  "aria-labelledby": headerId,
1049
1142
  className: "fractal-disclosure-panel",
1050
1143
  hidden: !isOpen,
1051
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "fractal-disclosure-panel-inner", children })
1144
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "fractal-disclosure-panel-inner", children })
1052
1145
  }
1053
1146
  )
1054
1147
  ]
@@ -1056,11 +1149,35 @@ function Disclosure({
1056
1149
  );
1057
1150
  }
1058
1151
 
1152
+ // src/components/LatticeLoader/LatticeLoader.tsx
1153
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1154
+ var LATTICE_COUNT = 48;
1155
+ function LatticeLoader({ className, label = "Loading", ...props }) {
1156
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1157
+ "span",
1158
+ {
1159
+ "aria-label": label,
1160
+ className: cn("fractal-lattice-loader", className),
1161
+ role: "progressbar",
1162
+ ...props,
1163
+ children: Array.from({ length: LATTICE_COUNT }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1164
+ "span",
1165
+ {
1166
+ "aria-hidden": "true",
1167
+ className: "fractal-lattice-loader__cell",
1168
+ style: { "--fractal-lattice-index": index }
1169
+ },
1170
+ index
1171
+ ))
1172
+ }
1173
+ );
1174
+ }
1175
+
1059
1176
  // src/components/Sidebar/Sidebar.tsx
1060
- var React10 = __toESM(require("react"), 1);
1061
- var import_jsx_runtime16 = require("react/jsx-runtime");
1062
- var Sidebar = React10.forwardRef(
1063
- ({ className, width, style, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1177
+ var React11 = __toESM(require("react"), 1);
1178
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1179
+ var Sidebar = React11.forwardRef(
1180
+ ({ className, width, style, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1064
1181
  "aside",
1065
1182
  {
1066
1183
  ref,
@@ -1071,24 +1188,24 @@ var Sidebar = React10.forwardRef(
1071
1188
  )
1072
1189
  );
1073
1190
  Sidebar.displayName = "Sidebar";
1074
- var SidebarHeader = React10.forwardRef(
1075
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref, className: cn("fractal-sidebar__header", className), ...props })
1191
+ var SidebarHeader = React11.forwardRef(
1192
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { ref, className: cn("fractal-sidebar__header", className), ...props })
1076
1193
  );
1077
1194
  SidebarHeader.displayName = "SidebarHeader";
1078
- var SidebarBrand = React10.forwardRef(
1079
- ({ className, type = "button", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { ref, type, className: cn("fractal-sidebar__brand", className), ...props })
1195
+ var SidebarBrand = React11.forwardRef(
1196
+ ({ className, type = "button", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { ref, type, className: cn("fractal-sidebar__brand", className), ...props })
1080
1197
  );
1081
1198
  SidebarBrand.displayName = "SidebarBrand";
1082
- var SidebarNav = React10.forwardRef(
1083
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("nav", { ref, className: cn("fractal-sidebar__nav", className), ...props })
1199
+ var SidebarNav = React11.forwardRef(
1200
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("nav", { ref, className: cn("fractal-sidebar__nav", className), ...props })
1084
1201
  );
1085
1202
  SidebarNav.displayName = "SidebarNav";
1086
- var SidebarSection = React10.forwardRef(
1087
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref, className: cn("fractal-sidebar__section", className), ...props })
1203
+ var SidebarSection = React11.forwardRef(
1204
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { ref, className: cn("fractal-sidebar__section", className), ...props })
1088
1205
  );
1089
1206
  SidebarSection.displayName = "SidebarSection";
1090
- var SidebarNavItem = React10.forwardRef(
1091
- ({ active = false, icon, endAdornment, className, type = "button", children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
1207
+ var SidebarNavItem = React11.forwardRef(
1208
+ ({ active = false, icon, endAdornment, className, type = "button", children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1092
1209
  "button",
1093
1210
  {
1094
1211
  ref,
@@ -1098,28 +1215,28 @@ var SidebarNavItem = React10.forwardRef(
1098
1215
  "aria-current": active ? "page" : void 0,
1099
1216
  ...props,
1100
1217
  children: [
1101
- icon && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fractal-sidebar__nav-item-icon", "aria-hidden": "true", children: icon }),
1102
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fractal-sidebar__nav-item-label", children }),
1103
- endAdornment && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fractal-sidebar__nav-item-end", children: endAdornment })
1218
+ icon && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fractal-sidebar__nav-item-icon", "aria-hidden": "true", children: icon }),
1219
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fractal-sidebar__nav-item-label", children }),
1220
+ endAdornment && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fractal-sidebar__nav-item-end", children: endAdornment })
1104
1221
  ]
1105
1222
  }
1106
1223
  )
1107
1224
  );
1108
1225
  SidebarNavItem.displayName = "SidebarNavItem";
1109
- var SidebarFooter = React10.forwardRef(
1110
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref, className: cn("fractal-sidebar__footer", className), ...props })
1226
+ var SidebarFooter = React11.forwardRef(
1227
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { ref, className: cn("fractal-sidebar__footer", className), ...props })
1111
1228
  );
1112
1229
  SidebarFooter.displayName = "SidebarFooter";
1113
1230
 
1114
1231
  // src/components/SidePanel/SidePanel.tsx
1115
1232
  var import_react_dom2 = require("react-dom");
1116
- var import_fractal_icons5 = require("@mirror-physics/fractal-icons");
1117
- var import_jsx_runtime17 = require("react/jsx-runtime");
1233
+ var import_fractal_icons6 = require("@mirror-physics/fractal-icons");
1234
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1118
1235
  function SidePanel({ open, onClose, title, description, children, footer, size = "md", className }) {
1119
1236
  useEscapeDismiss(80, onClose, open);
1120
1237
  if (!open) return null;
1121
1238
  return (0, import_react_dom2.createPortal)(
1122
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "fractal-side-panel-overlay", onMouseDown: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1239
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "fractal-side-panel-overlay", onMouseDown: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1123
1240
  "aside",
1124
1241
  {
1125
1242
  className: cn("fractal-side-panel", `fractal-side-panel--${size}`, className),
@@ -1128,15 +1245,15 @@ function SidePanel({ open, onClose, title, description, children, footer, size =
1128
1245
  role: "dialog",
1129
1246
  onMouseDown: (event) => event.stopPropagation(),
1130
1247
  children: [
1131
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("header", { className: "fractal-side-panel__header", children: [
1132
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "fractal-side-panel__heading", children: [
1133
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h2", { className: "fractal-side-panel__title", children: title }),
1134
- description && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "fractal-side-panel__description", children: description })
1248
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("header", { className: "fractal-side-panel__header", children: [
1249
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "fractal-side-panel__heading", children: [
1250
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h2", { className: "fractal-side-panel__title", children: title }),
1251
+ description && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "fractal-side-panel__description", children: description })
1135
1252
  ] }),
1136
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", className: "fractal-side-panel__close", "aria-label": "Close panel", onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_fractal_icons5.Close, { size: 18 }) })
1253
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { type: "button", className: "fractal-side-panel__close", "aria-label": "Close panel", onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_fractal_icons6.Close, { size: 18 }) })
1137
1254
  ] }),
1138
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "fractal-side-panel__body", children }),
1139
- footer && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("footer", { className: "fractal-side-panel__footer", children: footer })
1255
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "fractal-side-panel__body", children }),
1256
+ footer && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("footer", { className: "fractal-side-panel__footer", children: footer })
1140
1257
  ]
1141
1258
  }
1142
1259
  ) }),
@@ -1145,17 +1262,38 @@ function SidePanel({ open, onClose, title, description, children, footer, size =
1145
1262
  }
1146
1263
 
1147
1264
  // src/components/Textarea/Textarea.tsx
1148
- var React11 = __toESM(require("react"), 1);
1149
- var import_jsx_runtime18 = require("react/jsx-runtime");
1150
- var Textarea = React11.forwardRef(
1151
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("textarea", { ref, className: cn("fractal-textarea", className), ...props })
1265
+ var React12 = __toESM(require("react"), 1);
1266
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1267
+ var Textarea = React12.forwardRef(
1268
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("textarea", { ref, className: cn("fractal-textarea", className), ...props })
1152
1269
  );
1153
1270
  Textarea.displayName = "Textarea";
1154
1271
 
1272
+ // src/components/TextButton/TextButton.tsx
1273
+ var React13 = __toESM(require("react"), 1);
1274
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1275
+ var TextButton = React13.forwardRef(
1276
+ ({ className, icon, iconPosition = "start", size = "md", tone = "primary", children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
1277
+ "button",
1278
+ {
1279
+ ref,
1280
+ className: cn("fractal-text-button", `fractal-text-button--${size}`, `fractal-text-button--${tone}`, className),
1281
+ type: "button",
1282
+ ...props,
1283
+ children: [
1284
+ icon && iconPosition === "start" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "fractal-text-button__icon", "aria-hidden": "true", children: icon }),
1285
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children }),
1286
+ icon && iconPosition === "end" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "fractal-text-button__icon", "aria-hidden": "true", children: icon })
1287
+ ]
1288
+ }
1289
+ )
1290
+ );
1291
+ TextButton.displayName = "TextButton";
1292
+
1155
1293
  // src/components/FileDropzone/FileDropzone.tsx
1156
- var React12 = __toESM(require("react"), 1);
1157
- var import_fractal_icons6 = require("@mirror-physics/fractal-icons");
1158
- var import_jsx_runtime19 = require("react/jsx-runtime");
1294
+ var React14 = __toESM(require("react"), 1);
1295
+ var import_fractal_icons7 = require("@mirror-physics/fractal-icons");
1296
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1159
1297
  function FileDropzone({
1160
1298
  files,
1161
1299
  onFilesChange,
@@ -1166,17 +1304,17 @@ function FileDropzone({
1166
1304
  description = "Files stay attached to this record.",
1167
1305
  className
1168
1306
  }) {
1169
- const inputId = React12.useId();
1170
- const inputRef = React12.useRef(null);
1171
- const [isDragging, setIsDragging] = React12.useState(false);
1307
+ const inputId = React14.useId();
1308
+ const inputRef = React14.useRef(null);
1309
+ const [isDragging, setIsDragging] = React14.useState(false);
1172
1310
  const addFiles = (nextFiles) => {
1173
1311
  if (disabled) return;
1174
1312
  const additions = Array.from(nextFiles);
1175
1313
  if (additions.length === 0) return;
1176
1314
  onFilesChange(multiple ? [...files, ...additions] : additions.slice(0, 1));
1177
1315
  };
1178
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: cn("fractal-file-dropzone", className), children: [
1179
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1316
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: cn("fractal-file-dropzone", className), children: [
1317
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1180
1318
  "input",
1181
1319
  {
1182
1320
  ref: inputRef,
@@ -1192,7 +1330,7 @@ function FileDropzone({
1192
1330
  }
1193
1331
  }
1194
1332
  ),
1195
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1333
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
1196
1334
  "button",
1197
1335
  {
1198
1336
  className: "fractal-file-dropzone__target",
@@ -1215,18 +1353,18 @@ function FileDropzone({
1215
1353
  addFiles(event.dataTransfer.files);
1216
1354
  },
1217
1355
  children: [
1218
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_fractal_icons6.FileArrowUp, { "aria-hidden": "true", size: 20 }),
1219
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "fractal-file-dropzone__copy", children: [
1220
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fractal-file-dropzone__title", children: title }),
1221
- description && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fractal-file-dropzone__description", children: description })
1356
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fractal_icons7.FileArrowUp, { "aria-hidden": "true", size: 20 }),
1357
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { className: "fractal-file-dropzone__copy", children: [
1358
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "fractal-file-dropzone__title", children: title }),
1359
+ description && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "fractal-file-dropzone__description", children: description })
1222
1360
  ] })
1223
1361
  ]
1224
1362
  }
1225
1363
  ),
1226
- files.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("ul", { className: "fractal-file-dropzone__files", "aria-label": "Attached files", children: files.map((file, index) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("li", { className: "fractal-file-dropzone__file", children: [
1227
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fractal-file-dropzone__file-name", children: file.name }),
1228
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fractal-file-dropzone__file-meta", children: formatFileSize(file.size) }),
1229
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1364
+ files.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("ul", { className: "fractal-file-dropzone__files", "aria-label": "Attached files", children: files.map((file, index) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("li", { className: "fractal-file-dropzone__file", children: [
1365
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "fractal-file-dropzone__file-name", children: file.name }),
1366
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "fractal-file-dropzone__file-meta", children: formatFileSize(file.size) }),
1367
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1230
1368
  "button",
1231
1369
  {
1232
1370
  className: "fractal-file-dropzone__remove",
@@ -1234,7 +1372,7 @@ function FileDropzone({
1234
1372
  "aria-label": `Remove ${file.name}`,
1235
1373
  disabled,
1236
1374
  onClick: () => onFilesChange(files.filter((_, fileIndex) => fileIndex !== index)),
1237
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_fractal_icons6.Close, { "aria-hidden": "true", size: 14 })
1375
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fractal_icons7.Close, { "aria-hidden": "true", size: 14 })
1238
1376
  }
1239
1377
  )
1240
1378
  ] }, `${file.name}-${file.size}-${index}`)) })
@@ -1245,6 +1383,77 @@ function formatFileSize(bytes) {
1245
1383
  if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
1246
1384
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1247
1385
  }
1386
+
1387
+ // src/components/Pagination/Pagination.tsx
1388
+ var import_fractal_icons8 = require("@mirror-physics/fractal-icons");
1389
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1390
+ function Pagination({
1391
+ page,
1392
+ pageSize,
1393
+ totalItems,
1394
+ onPageChange,
1395
+ pageSizeOptions,
1396
+ onPageSizeChange,
1397
+ ariaLabel = "Pagination",
1398
+ className
1399
+ }) {
1400
+ const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
1401
+ const currentPage = Math.min(Math.max(page, 1), totalPages);
1402
+ const start = totalItems === 0 ? 0 : (currentPage - 1) * pageSize + 1;
1403
+ const end = Math.min(currentPage * pageSize, totalItems);
1404
+ const canChangePageSize = pageSizeOptions != null && pageSizeOptions.length > 0 && onPageSizeChange != null;
1405
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("nav", { className: cn("fractal-pagination", className), "aria-label": ariaLabel, children: [
1406
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "fractal-pagination__summary", children: totalItems === 0 ? "No results" : `${start}-${end} of ${totalItems}` }),
1407
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "fractal-pagination__controls", children: [
1408
+ canChangePageSize && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1409
+ Dropdown,
1410
+ {
1411
+ align: "right",
1412
+ className: "fractal-pagination__page-size",
1413
+ direction: "up",
1414
+ items: pageSizeOptions.map((option) => ({
1415
+ value: String(option),
1416
+ description: `${option} per page`
1417
+ })),
1418
+ onSelect: (value) => onPageSizeChange(Number(value)),
1419
+ selectedValue: String(pageSize),
1420
+ size: "sm",
1421
+ triggerLabel: "Results per page",
1422
+ triggerVariant: "tertiary"
1423
+ }
1424
+ ),
1425
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1426
+ "button",
1427
+ {
1428
+ className: "fractal-pagination__button",
1429
+ type: "button",
1430
+ "aria-label": "Previous page",
1431
+ title: "Previous page",
1432
+ disabled: currentPage === 1 || totalItems === 0,
1433
+ onClick: () => onPageChange(currentPage - 1),
1434
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_fractal_icons8.ArrowLeft, { "aria-hidden": "true", size: 16 })
1435
+ }
1436
+ ),
1437
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "fractal-pagination__page", "aria-current": "page", children: [
1438
+ currentPage,
1439
+ " of ",
1440
+ totalPages
1441
+ ] }),
1442
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1443
+ "button",
1444
+ {
1445
+ className: "fractal-pagination__button",
1446
+ type: "button",
1447
+ "aria-label": "Next page",
1448
+ title: "Next page",
1449
+ disabled: currentPage === totalPages || totalItems === 0,
1450
+ onClick: () => onPageChange(currentPage + 1),
1451
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_fractal_icons8.ArrowRight, { "aria-hidden": "true", size: 16 })
1452
+ }
1453
+ )
1454
+ ] })
1455
+ ] });
1456
+ }
1248
1457
  // Annotate the CommonJS export names for ESM import in node:
1249
1458
  0 && (module.exports = {
1250
1459
  Alert,
@@ -1257,7 +1466,9 @@ function formatFileSize(bytes) {
1257
1466
  CardFooter,
1258
1467
  CardHeader,
1259
1468
  CardTitle,
1469
+ Checkbox,
1260
1470
  Chip,
1471
+ ContentSwitcher,
1261
1472
  DataTable,
1262
1473
  Disclosure,
1263
1474
  Dropdown,
@@ -1266,8 +1477,10 @@ function formatFileSize(bytes) {
1266
1477
  FolderCard,
1267
1478
  Input,
1268
1479
  Label,
1480
+ LatticeLoader,
1269
1481
  Link,
1270
1482
  Modal,
1483
+ Pagination,
1271
1484
  PromptCard,
1272
1485
  PromptGrid,
1273
1486
  SidePanel,
@@ -1280,6 +1493,7 @@ function formatFileSize(bytes) {
1280
1493
  SidebarSection,
1281
1494
  SortableTable,
1282
1495
  Tabs,
1496
+ TextButton,
1283
1497
  Textarea,
1284
1498
  Toggle,
1285
1499
  cn,