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

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