@mirror-physics/fractal-ui 0.2.0-next.2 → 0.2.0-next.20
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 +476 -79
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +594 -13
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +95 -4
- package/dist/index.d.ts +95 -4
- package/dist/index.js +462 -73
- package/dist/index.js.map +1 -1
- package/dist/lattice-FAYE5KWW.svg +3 -0
- package/dist/tokens.css +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -50,7 +50,7 @@ var colorPalette = {
|
|
|
50
50
|
var sizeConfig = {
|
|
51
51
|
xs: { height: "28px", padding: "4px 8px", iconOnly: "28px", fontSize: "0.75rem" },
|
|
52
52
|
sm: { height: "32px", padding: "6px 12px", iconOnly: "32px", fontSize: "0.75rem" },
|
|
53
|
-
md: { height: "
|
|
53
|
+
md: { height: "40px", padding: "8px 16px", iconOnly: "40px", fontSize: "0.875rem" },
|
|
54
54
|
lg: { height: "44px", padding: "10px 20px", iconOnly: "44px", fontSize: "1rem" },
|
|
55
55
|
xl: { height: "56px", padding: "14px 28px", iconOnly: "56px", fontSize: "1rem" }
|
|
56
56
|
};
|
|
@@ -664,23 +664,52 @@ var Chip = React9.forwardRef(
|
|
|
664
664
|
);
|
|
665
665
|
Chip.displayName = "Chip";
|
|
666
666
|
|
|
667
|
+
// src/components/Checkbox/Checkbox.tsx
|
|
668
|
+
import { Checkbox as CheckboxIcon, CheckboxChecked } from "@mirror-physics/fractal-icons";
|
|
669
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
670
|
+
function Checkbox({ checked, onCheckedChange, className, disabled, onClick, onKeyDown, ...props }) {
|
|
671
|
+
return /* @__PURE__ */ jsx12(
|
|
672
|
+
"button",
|
|
673
|
+
{
|
|
674
|
+
...props,
|
|
675
|
+
className: cn("fractal-checkbox", checked && "fractal-checkbox--checked", className),
|
|
676
|
+
type: "button",
|
|
677
|
+
role: "checkbox",
|
|
678
|
+
"aria-checked": checked,
|
|
679
|
+
disabled,
|
|
680
|
+
onClick: (event) => {
|
|
681
|
+
onClick?.(event);
|
|
682
|
+
if (!event.defaultPrevented) onCheckedChange(!checked);
|
|
683
|
+
},
|
|
684
|
+
onKeyDown: (event) => {
|
|
685
|
+
onKeyDown?.(event);
|
|
686
|
+
if (event.key === " " || event.key === "Enter") event.stopPropagation();
|
|
687
|
+
},
|
|
688
|
+
children: checked ? /* @__PURE__ */ jsx12(CheckboxChecked, { "aria-hidden": "true", size: 18 }) : /* @__PURE__ */ jsx12(CheckboxIcon, { "aria-hidden": "true", size: 18 })
|
|
689
|
+
}
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
|
|
667
693
|
// src/components/SortableTable/SortableTable.tsx
|
|
668
694
|
import { useMemo, useState as useState3 } from "react";
|
|
669
695
|
import { ArrowUp, ArrowDown, ArrowsUpDown } from "@mirror-physics/fractal-icons";
|
|
670
|
-
import { jsx as
|
|
696
|
+
import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
671
697
|
function SortableTable({
|
|
672
698
|
columns,
|
|
673
699
|
data,
|
|
674
700
|
emptyMessage,
|
|
675
701
|
header,
|
|
676
702
|
size = "md",
|
|
703
|
+
embedded = false,
|
|
677
704
|
className,
|
|
678
705
|
defaultSortKey = void 0,
|
|
679
706
|
defaultSortDirection = null,
|
|
680
707
|
sortKey: controlledKey,
|
|
681
708
|
sortDirection: controlledDirection,
|
|
682
709
|
onSortChange,
|
|
683
|
-
highlightRow
|
|
710
|
+
highlightRow,
|
|
711
|
+
onRowClick,
|
|
712
|
+
rowAction
|
|
684
713
|
}) {
|
|
685
714
|
const [internalKey, setInternalKey] = useState3(defaultSortKey ?? null);
|
|
686
715
|
const [internalDirection, setInternalDirection] = useState3(defaultSortDirection);
|
|
@@ -733,13 +762,13 @@ function SortableTable({
|
|
|
733
762
|
onSortChange?.(nextKey, nextDirection);
|
|
734
763
|
}
|
|
735
764
|
};
|
|
736
|
-
return /* @__PURE__ */
|
|
737
|
-
header && /* @__PURE__ */
|
|
738
|
-
sorted.length === 0 ? /* @__PURE__ */
|
|
739
|
-
/* @__PURE__ */
|
|
765
|
+
return /* @__PURE__ */ jsx13("div", { className: cn("fractal-sortable-table", `fractal-sortable-table--${size}`, embedded && "fractal-sortable-table--embedded", className), children: /* @__PURE__ */ jsxs9("div", { className: "fractal-sortable-table-surface", children: [
|
|
766
|
+
header && /* @__PURE__ */ jsx13("div", { className: "fractal-sortable-table-header", children: header }),
|
|
767
|
+
sorted.length === 0 ? /* @__PURE__ */ jsx13("div", { className: "fractal-sortable-table-empty", children: emptyMessage || "No data" }) : /* @__PURE__ */ jsxs9("table", { className: "fractal-sortable-table-table", children: [
|
|
768
|
+
/* @__PURE__ */ jsx13("thead", { children: /* @__PURE__ */ jsx13("tr", { className: "fractal-sortable-table-thead-row", children: columns.map((col) => {
|
|
740
769
|
const isActive = activeKey === col.key && activeDirection !== null;
|
|
741
770
|
if (!col.sortable) {
|
|
742
|
-
return /* @__PURE__ */
|
|
771
|
+
return /* @__PURE__ */ jsx13(
|
|
743
772
|
"th",
|
|
744
773
|
{
|
|
745
774
|
className: "fractal-sortable-table-th",
|
|
@@ -749,7 +778,7 @@ function SortableTable({
|
|
|
749
778
|
col.key
|
|
750
779
|
);
|
|
751
780
|
}
|
|
752
|
-
return /* @__PURE__ */
|
|
781
|
+
return /* @__PURE__ */ jsx13(
|
|
753
782
|
"th",
|
|
754
783
|
{
|
|
755
784
|
className: "fractal-sortable-table-th fractal-sortable-table-th--sortable",
|
|
@@ -765,8 +794,8 @@ function SortableTable({
|
|
|
765
794
|
onClick: () => handleSortClick(col.key),
|
|
766
795
|
"aria-sort": isActive ? activeDirection === "asc" ? "ascending" : "descending" : "none",
|
|
767
796
|
children: [
|
|
768
|
-
/* @__PURE__ */
|
|
769
|
-
/* @__PURE__ */
|
|
797
|
+
/* @__PURE__ */ jsx13("span", { children: col.header }),
|
|
798
|
+
/* @__PURE__ */ jsx13("span", { className: "fractal-sortable-table-sort-icon", "aria-hidden": "true", children: isActive && activeDirection === "asc" ? /* @__PURE__ */ jsx13(ArrowUp, { size: 14 }) : isActive && activeDirection === "desc" ? /* @__PURE__ */ jsx13(ArrowDown, { size: 14 }) : /* @__PURE__ */ jsx13(ArrowsUpDown, { size: 14 }) })
|
|
770
799
|
]
|
|
771
800
|
}
|
|
772
801
|
)
|
|
@@ -774,21 +803,42 @@ function SortableTable({
|
|
|
774
803
|
col.key
|
|
775
804
|
);
|
|
776
805
|
}) }) }),
|
|
777
|
-
/* @__PURE__ */
|
|
806
|
+
/* @__PURE__ */ jsx13("tbody", { children: sorted.map((row, rowIndex) => {
|
|
778
807
|
const highlighted = highlightRow?.(row, rowIndex) ?? false;
|
|
779
|
-
|
|
808
|
+
const action = rowAction ? {
|
|
809
|
+
label: rowAction.label(row, rowIndex),
|
|
810
|
+
icon: rowAction.icon(row, rowIndex)
|
|
811
|
+
} : null;
|
|
812
|
+
return /* @__PURE__ */ jsx13(
|
|
780
813
|
"tr",
|
|
781
814
|
{
|
|
782
815
|
className: cn(
|
|
783
816
|
"fractal-sortable-table-row",
|
|
784
|
-
highlighted && "fractal-sortable-table-row--highlighted"
|
|
817
|
+
highlighted && "fractal-sortable-table-row--highlighted",
|
|
818
|
+
onRowClick && "fractal-sortable-table-row--interactive"
|
|
785
819
|
),
|
|
786
|
-
|
|
820
|
+
onClick: onRowClick ? () => onRowClick(row, rowIndex) : void 0,
|
|
821
|
+
onKeyDown: onRowClick ? (event) => {
|
|
822
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
823
|
+
event.preventDefault();
|
|
824
|
+
onRowClick(row, rowIndex);
|
|
825
|
+
}
|
|
826
|
+
} : void 0,
|
|
827
|
+
"aria-label": action?.label,
|
|
828
|
+
role: onRowClick ? "button" : void 0,
|
|
829
|
+
tabIndex: onRowClick ? 0 : void 0,
|
|
830
|
+
children: columns.map((col, columnIndex) => /* @__PURE__ */ jsxs9(
|
|
787
831
|
"td",
|
|
788
832
|
{
|
|
789
|
-
className:
|
|
833
|
+
className: cn(
|
|
834
|
+
"fractal-sortable-table-td",
|
|
835
|
+
action && columnIndex === columns.length - 1 && "fractal-sortable-table-td--row-action"
|
|
836
|
+
),
|
|
790
837
|
style: { width: col.width, textAlign: col.align ?? "left" },
|
|
791
|
-
children:
|
|
838
|
+
children: [
|
|
839
|
+
col.render(row, rowIndex),
|
|
840
|
+
action && columnIndex === columns.length - 1 && /* @__PURE__ */ jsx13("span", { className: "fractal-sortable-table-row-action", "aria-hidden": "true", children: /* @__PURE__ */ jsx13("span", { className: "fractal-sortable-table-row-action__icon", children: action.icon }) })
|
|
841
|
+
]
|
|
792
842
|
},
|
|
793
843
|
col.key
|
|
794
844
|
))
|
|
@@ -801,8 +851,8 @@ function SortableTable({
|
|
|
801
851
|
}
|
|
802
852
|
|
|
803
853
|
// src/components/Tabs/Tabs.tsx
|
|
804
|
-
import { useId, useRef as useRef3, useState as useState4 } from "react";
|
|
805
|
-
import { jsx as
|
|
854
|
+
import { useId, useLayoutEffect as useLayoutEffect2, useRef as useRef3, useState as useState4 } from "react";
|
|
855
|
+
import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
806
856
|
function Tabs({
|
|
807
857
|
items,
|
|
808
858
|
defaultValue,
|
|
@@ -817,7 +867,22 @@ function Tabs({
|
|
|
817
867
|
);
|
|
818
868
|
const isControlled = controlledValue !== void 0;
|
|
819
869
|
const activeId = isControlled ? controlledValue : internalValue;
|
|
870
|
+
const tabListRef = useRef3(null);
|
|
820
871
|
const tabRefs = useRef3({});
|
|
872
|
+
const [indicator, setIndicator] = useState4(null);
|
|
873
|
+
useLayoutEffect2(() => {
|
|
874
|
+
const updateIndicator = () => {
|
|
875
|
+
const activeTab = tabRefs.current[activeId];
|
|
876
|
+
if (!activeTab) return;
|
|
877
|
+
setIndicator({ offset: activeTab.offsetLeft, width: activeTab.offsetWidth });
|
|
878
|
+
};
|
|
879
|
+
updateIndicator();
|
|
880
|
+
const list = tabListRef.current;
|
|
881
|
+
if (!list || typeof ResizeObserver === "undefined") return;
|
|
882
|
+
const observer = new ResizeObserver(updateIndicator);
|
|
883
|
+
observer.observe(list);
|
|
884
|
+
return () => observer.disconnect();
|
|
885
|
+
}, [activeId, items.length]);
|
|
821
886
|
const selectTab = (id) => {
|
|
822
887
|
if (isControlled) {
|
|
823
888
|
onValueChange?.(id);
|
|
@@ -827,6 +892,10 @@ function Tabs({
|
|
|
827
892
|
}
|
|
828
893
|
};
|
|
829
894
|
const focusable = items.filter((i) => !i.disabled);
|
|
895
|
+
const indicatorStyle = indicator ? {
|
|
896
|
+
"--fractal-tabs-indicator-offset": `${indicator.offset}px`,
|
|
897
|
+
"--fractal-tabs-indicator-width": `${indicator.width}px`
|
|
898
|
+
} : void 0;
|
|
830
899
|
const onKeyDown = (event) => {
|
|
831
900
|
const currentIndex = focusable.findIndex((i) => i.id === activeId);
|
|
832
901
|
if (currentIndex === -1) return;
|
|
@@ -853,40 +922,51 @@ function Tabs({
|
|
|
853
922
|
requestAnimationFrame(() => tabRefs.current[nextId2]?.focus());
|
|
854
923
|
};
|
|
855
924
|
return /* @__PURE__ */ jsxs10("div", { className: cn("fractal-tabs", className), children: [
|
|
856
|
-
/* @__PURE__ */
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
"
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
id
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
925
|
+
/* @__PURE__ */ jsx14(
|
|
926
|
+
"div",
|
|
927
|
+
{
|
|
928
|
+
ref: tabListRef,
|
|
929
|
+
role: "tablist",
|
|
930
|
+
"aria-label": ariaLabel,
|
|
931
|
+
className: "fractal-tabs-list",
|
|
932
|
+
"data-indicator-ready": indicator ? "true" : void 0,
|
|
933
|
+
style: indicatorStyle,
|
|
934
|
+
children: items.map((item) => {
|
|
935
|
+
const isActive = item.id === activeId;
|
|
936
|
+
const tabId = `${reactId}-tab-${item.id}`;
|
|
937
|
+
const panelId = `${reactId}-panel-${item.id}`;
|
|
938
|
+
return /* @__PURE__ */ jsx14(
|
|
939
|
+
"button",
|
|
940
|
+
{
|
|
941
|
+
ref: (el) => {
|
|
942
|
+
tabRefs.current[item.id] = el;
|
|
943
|
+
},
|
|
944
|
+
id: tabId,
|
|
945
|
+
role: "tab",
|
|
946
|
+
type: "button",
|
|
947
|
+
"aria-selected": isActive,
|
|
948
|
+
"aria-controls": panelId,
|
|
949
|
+
tabIndex: isActive ? 0 : -1,
|
|
950
|
+
disabled: item.disabled,
|
|
951
|
+
className: cn(
|
|
952
|
+
"fractal-tabs-trigger",
|
|
953
|
+
isActive && "fractal-tabs-trigger--active",
|
|
954
|
+
item.disabled && "fractal-tabs-trigger--disabled"
|
|
955
|
+
),
|
|
956
|
+
onClick: () => !item.disabled && selectTab(item.id),
|
|
957
|
+
onKeyDown,
|
|
958
|
+
children: item.label
|
|
959
|
+
},
|
|
960
|
+
item.id
|
|
961
|
+
);
|
|
962
|
+
})
|
|
963
|
+
}
|
|
964
|
+
),
|
|
885
965
|
items.map((item) => {
|
|
886
966
|
const tabId = `${reactId}-tab-${item.id}`;
|
|
887
967
|
const panelId = `${reactId}-panel-${item.id}`;
|
|
888
968
|
const isActive = item.id === activeId;
|
|
889
|
-
return /* @__PURE__ */
|
|
969
|
+
return /* @__PURE__ */ jsx14(
|
|
890
970
|
"div",
|
|
891
971
|
{
|
|
892
972
|
id: panelId,
|
|
@@ -902,10 +982,55 @@ function Tabs({
|
|
|
902
982
|
] });
|
|
903
983
|
}
|
|
904
984
|
|
|
985
|
+
// src/components/ContentSwitcher/ContentSwitcher.tsx
|
|
986
|
+
import * as React10 from "react";
|
|
987
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
988
|
+
function ContentSwitcher({ items, value, onValueChange, ariaLabel, fullWidth = false, className }) {
|
|
989
|
+
const buttonRefs = React10.useRef([]);
|
|
990
|
+
const moveFocus = (index, direction) => {
|
|
991
|
+
let nextIndex = index;
|
|
992
|
+
do {
|
|
993
|
+
nextIndex = (nextIndex + direction + items.length) % items.length;
|
|
994
|
+
} while (items[nextIndex]?.disabled && nextIndex !== index);
|
|
995
|
+
if (!items[nextIndex]?.disabled) {
|
|
996
|
+
buttonRefs.current[nextIndex]?.focus();
|
|
997
|
+
onValueChange(items[nextIndex].value);
|
|
998
|
+
}
|
|
999
|
+
};
|
|
1000
|
+
return /* @__PURE__ */ jsx15("div", { className: cn("fractal-content-switcher", fullWidth && "fractal-content-switcher--full-width", className), role: "group", "aria-label": ariaLabel, children: items.map((item, index) => {
|
|
1001
|
+
const active = item.value === value;
|
|
1002
|
+
return /* @__PURE__ */ jsx15(
|
|
1003
|
+
"button",
|
|
1004
|
+
{
|
|
1005
|
+
className: cn("fractal-content-switcher__item", active && "fractal-content-switcher__item--active"),
|
|
1006
|
+
type: "button",
|
|
1007
|
+
"aria-pressed": active,
|
|
1008
|
+
disabled: item.disabled,
|
|
1009
|
+
onClick: () => onValueChange(item.value),
|
|
1010
|
+
onKeyDown: (event) => {
|
|
1011
|
+
if (event.key === "ArrowRight") {
|
|
1012
|
+
event.preventDefault();
|
|
1013
|
+
moveFocus(index, 1);
|
|
1014
|
+
}
|
|
1015
|
+
if (event.key === "ArrowLeft") {
|
|
1016
|
+
event.preventDefault();
|
|
1017
|
+
moveFocus(index, -1);
|
|
1018
|
+
}
|
|
1019
|
+
},
|
|
1020
|
+
ref: (element) => {
|
|
1021
|
+
buttonRefs.current[index] = element;
|
|
1022
|
+
},
|
|
1023
|
+
children: item.label
|
|
1024
|
+
},
|
|
1025
|
+
item.value
|
|
1026
|
+
);
|
|
1027
|
+
}) });
|
|
1028
|
+
}
|
|
1029
|
+
|
|
905
1030
|
// src/components/Disclosure/Disclosure.tsx
|
|
906
1031
|
import { useId as useId2, useState as useState5 } from "react";
|
|
907
1032
|
import { ChevronRight, ChevronDown as ChevronDown2 } from "@mirror-physics/fractal-icons";
|
|
908
|
-
import { jsx as
|
|
1033
|
+
import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
909
1034
|
function Disclosure({
|
|
910
1035
|
title,
|
|
911
1036
|
meta,
|
|
@@ -913,6 +1038,7 @@ function Disclosure({
|
|
|
913
1038
|
defaultOpen = false,
|
|
914
1039
|
open: controlledOpen,
|
|
915
1040
|
onOpenChange,
|
|
1041
|
+
disabled = false,
|
|
916
1042
|
className,
|
|
917
1043
|
variant = "card"
|
|
918
1044
|
}) {
|
|
@@ -923,6 +1049,7 @@ function Disclosure({
|
|
|
923
1049
|
const isControlled = controlledOpen !== void 0;
|
|
924
1050
|
const isOpen = isControlled ? controlledOpen : internalOpen;
|
|
925
1051
|
const toggle = () => {
|
|
1052
|
+
if (disabled) return;
|
|
926
1053
|
const next = !isOpen;
|
|
927
1054
|
if (isControlled) {
|
|
928
1055
|
onOpenChange?.(next);
|
|
@@ -938,6 +1065,7 @@ function Disclosure({
|
|
|
938
1065
|
"fractal-disclosure",
|
|
939
1066
|
variant === "card" && "fractal-disclosure--card",
|
|
940
1067
|
isOpen && "fractal-disclosure--open",
|
|
1068
|
+
disabled && "fractal-disclosure--disabled",
|
|
941
1069
|
className
|
|
942
1070
|
),
|
|
943
1071
|
children: [
|
|
@@ -949,15 +1077,16 @@ function Disclosure({
|
|
|
949
1077
|
className: "fractal-disclosure-trigger",
|
|
950
1078
|
"aria-expanded": isOpen,
|
|
951
1079
|
"aria-controls": panelId,
|
|
1080
|
+
disabled,
|
|
952
1081
|
onClick: toggle,
|
|
953
1082
|
children: [
|
|
954
|
-
/* @__PURE__ */
|
|
955
|
-
/* @__PURE__ */
|
|
956
|
-
meta && /* @__PURE__ */
|
|
1083
|
+
/* @__PURE__ */ jsx16("span", { className: "fractal-disclosure-icon", "aria-hidden": "true", children: isOpen ? /* @__PURE__ */ jsx16(ChevronDown2, { size: 16 }) : /* @__PURE__ */ jsx16(ChevronRight, { size: 16 }) }),
|
|
1084
|
+
/* @__PURE__ */ jsx16("span", { className: "fractal-disclosure-title", children: title }),
|
|
1085
|
+
meta && /* @__PURE__ */ jsx16("span", { className: "fractal-disclosure-meta", children: meta })
|
|
957
1086
|
]
|
|
958
1087
|
}
|
|
959
1088
|
),
|
|
960
|
-
/* @__PURE__ */
|
|
1089
|
+
/* @__PURE__ */ jsx16(
|
|
961
1090
|
"div",
|
|
962
1091
|
{
|
|
963
1092
|
id: panelId,
|
|
@@ -965,7 +1094,7 @@ function Disclosure({
|
|
|
965
1094
|
"aria-labelledby": headerId,
|
|
966
1095
|
className: "fractal-disclosure-panel",
|
|
967
1096
|
hidden: !isOpen,
|
|
968
|
-
children: /* @__PURE__ */
|
|
1097
|
+
children: /* @__PURE__ */ jsx16("div", { className: "fractal-disclosure-panel-inner", children })
|
|
969
1098
|
}
|
|
970
1099
|
)
|
|
971
1100
|
]
|
|
@@ -973,11 +1102,36 @@ function Disclosure({
|
|
|
973
1102
|
);
|
|
974
1103
|
}
|
|
975
1104
|
|
|
1105
|
+
// src/components/LatticeLoader/LatticeLoader.tsx
|
|
1106
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
1107
|
+
var LATTICE_COUNT = 160;
|
|
1108
|
+
var WAVE_PERIOD = 80;
|
|
1109
|
+
function LatticeLoader({ className, label = "Loading", ...props }) {
|
|
1110
|
+
return /* @__PURE__ */ jsx17(
|
|
1111
|
+
"span",
|
|
1112
|
+
{
|
|
1113
|
+
"aria-label": label,
|
|
1114
|
+
className: cn("fractal-lattice-loader", className),
|
|
1115
|
+
role: "progressbar",
|
|
1116
|
+
...props,
|
|
1117
|
+
children: Array.from({ length: LATTICE_COUNT }, (_, index) => /* @__PURE__ */ jsx17(
|
|
1118
|
+
"span",
|
|
1119
|
+
{
|
|
1120
|
+
"aria-hidden": "true",
|
|
1121
|
+
className: "fractal-lattice-loader__cell",
|
|
1122
|
+
style: { "--fractal-lattice-index": index % WAVE_PERIOD }
|
|
1123
|
+
},
|
|
1124
|
+
index
|
|
1125
|
+
))
|
|
1126
|
+
}
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
|
|
976
1130
|
// src/components/Sidebar/Sidebar.tsx
|
|
977
|
-
import * as
|
|
978
|
-
import { jsx as
|
|
979
|
-
var Sidebar =
|
|
980
|
-
({ className, width, style, ...props }, ref) => /* @__PURE__ */
|
|
1131
|
+
import * as React11 from "react";
|
|
1132
|
+
import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1133
|
+
var Sidebar = React11.forwardRef(
|
|
1134
|
+
({ className, width, style, ...props }, ref) => /* @__PURE__ */ jsx18(
|
|
981
1135
|
"aside",
|
|
982
1136
|
{
|
|
983
1137
|
ref,
|
|
@@ -988,23 +1142,23 @@ var Sidebar = React10.forwardRef(
|
|
|
988
1142
|
)
|
|
989
1143
|
);
|
|
990
1144
|
Sidebar.displayName = "Sidebar";
|
|
991
|
-
var SidebarHeader =
|
|
992
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
1145
|
+
var SidebarHeader = React11.forwardRef(
|
|
1146
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx18("div", { ref, className: cn("fractal-sidebar__header", className), ...props })
|
|
993
1147
|
);
|
|
994
1148
|
SidebarHeader.displayName = "SidebarHeader";
|
|
995
|
-
var SidebarBrand =
|
|
996
|
-
({ className, type = "button", ...props }, ref) => /* @__PURE__ */
|
|
1149
|
+
var SidebarBrand = React11.forwardRef(
|
|
1150
|
+
({ className, type = "button", ...props }, ref) => /* @__PURE__ */ jsx18("button", { ref, type, className: cn("fractal-sidebar__brand", className), ...props })
|
|
997
1151
|
);
|
|
998
1152
|
SidebarBrand.displayName = "SidebarBrand";
|
|
999
|
-
var SidebarNav =
|
|
1000
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
1153
|
+
var SidebarNav = React11.forwardRef(
|
|
1154
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx18("nav", { ref, className: cn("fractal-sidebar__nav", className), ...props })
|
|
1001
1155
|
);
|
|
1002
1156
|
SidebarNav.displayName = "SidebarNav";
|
|
1003
|
-
var SidebarSection =
|
|
1004
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
1157
|
+
var SidebarSection = React11.forwardRef(
|
|
1158
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx18("div", { ref, className: cn("fractal-sidebar__section", className), ...props })
|
|
1005
1159
|
);
|
|
1006
1160
|
SidebarSection.displayName = "SidebarSection";
|
|
1007
|
-
var SidebarNavItem =
|
|
1161
|
+
var SidebarNavItem = React11.forwardRef(
|
|
1008
1162
|
({ active = false, icon, endAdornment, className, type = "button", children, ...props }, ref) => /* @__PURE__ */ jsxs12(
|
|
1009
1163
|
"button",
|
|
1010
1164
|
{
|
|
@@ -1015,18 +1169,245 @@ var SidebarNavItem = React10.forwardRef(
|
|
|
1015
1169
|
"aria-current": active ? "page" : void 0,
|
|
1016
1170
|
...props,
|
|
1017
1171
|
children: [
|
|
1018
|
-
icon && /* @__PURE__ */
|
|
1019
|
-
/* @__PURE__ */
|
|
1020
|
-
endAdornment && /* @__PURE__ */
|
|
1172
|
+
icon && /* @__PURE__ */ jsx18("span", { className: "fractal-sidebar__nav-item-icon", "aria-hidden": "true", children: icon }),
|
|
1173
|
+
/* @__PURE__ */ jsx18("span", { className: "fractal-sidebar__nav-item-label", children }),
|
|
1174
|
+
endAdornment && /* @__PURE__ */ jsx18("span", { className: "fractal-sidebar__nav-item-end", children: endAdornment })
|
|
1021
1175
|
]
|
|
1022
1176
|
}
|
|
1023
1177
|
)
|
|
1024
1178
|
);
|
|
1025
1179
|
SidebarNavItem.displayName = "SidebarNavItem";
|
|
1026
|
-
var SidebarFooter =
|
|
1027
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
1180
|
+
var SidebarFooter = React11.forwardRef(
|
|
1181
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx18("div", { ref, className: cn("fractal-sidebar__footer", className), ...props })
|
|
1028
1182
|
);
|
|
1029
1183
|
SidebarFooter.displayName = "SidebarFooter";
|
|
1184
|
+
|
|
1185
|
+
// src/components/SidePanel/SidePanel.tsx
|
|
1186
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
1187
|
+
import { Close } from "@mirror-physics/fractal-icons";
|
|
1188
|
+
import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1189
|
+
function SidePanel({ open, onClose, title, description, children, footer, size = "md", className }) {
|
|
1190
|
+
useEscapeDismiss(80, onClose, open);
|
|
1191
|
+
if (!open) return null;
|
|
1192
|
+
return createPortal2(
|
|
1193
|
+
/* @__PURE__ */ jsx19("div", { className: "fractal-side-panel-overlay", onMouseDown: onClose, children: /* @__PURE__ */ jsxs13(
|
|
1194
|
+
"aside",
|
|
1195
|
+
{
|
|
1196
|
+
className: cn("fractal-side-panel", `fractal-side-panel--${size}`, className),
|
|
1197
|
+
"aria-modal": "true",
|
|
1198
|
+
"aria-label": typeof title === "string" ? title : "Side panel",
|
|
1199
|
+
role: "dialog",
|
|
1200
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
1201
|
+
children: [
|
|
1202
|
+
/* @__PURE__ */ jsxs13("header", { className: "fractal-side-panel__header", children: [
|
|
1203
|
+
/* @__PURE__ */ jsxs13("div", { className: "fractal-side-panel__heading", children: [
|
|
1204
|
+
/* @__PURE__ */ jsx19("h2", { className: "fractal-side-panel__title", children: title }),
|
|
1205
|
+
description && /* @__PURE__ */ jsx19("p", { className: "fractal-side-panel__description", children: description })
|
|
1206
|
+
] }),
|
|
1207
|
+
/* @__PURE__ */ jsx19("button", { type: "button", className: "fractal-side-panel__close", "aria-label": "Close panel", onClick: onClose, children: /* @__PURE__ */ jsx19(Close, { size: 18 }) })
|
|
1208
|
+
] }),
|
|
1209
|
+
/* @__PURE__ */ jsx19("div", { className: "fractal-side-panel__body", children }),
|
|
1210
|
+
footer && /* @__PURE__ */ jsx19("footer", { className: "fractal-side-panel__footer", children: footer })
|
|
1211
|
+
]
|
|
1212
|
+
}
|
|
1213
|
+
) }),
|
|
1214
|
+
document.body
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
// src/components/Textarea/Textarea.tsx
|
|
1219
|
+
import * as React12 from "react";
|
|
1220
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
1221
|
+
var Textarea = React12.forwardRef(
|
|
1222
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx20("textarea", { ref, className: cn("fractal-textarea", className), ...props })
|
|
1223
|
+
);
|
|
1224
|
+
Textarea.displayName = "Textarea";
|
|
1225
|
+
|
|
1226
|
+
// src/components/TextButton/TextButton.tsx
|
|
1227
|
+
import * as React13 from "react";
|
|
1228
|
+
import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1229
|
+
var TextButton = React13.forwardRef(
|
|
1230
|
+
({ className, icon, iconPosition = "start", size = "md", tone = "primary", children, ...props }, ref) => /* @__PURE__ */ jsxs14(
|
|
1231
|
+
"button",
|
|
1232
|
+
{
|
|
1233
|
+
ref,
|
|
1234
|
+
className: cn("fractal-text-button", `fractal-text-button--${size}`, `fractal-text-button--${tone}`, className),
|
|
1235
|
+
type: "button",
|
|
1236
|
+
...props,
|
|
1237
|
+
children: [
|
|
1238
|
+
icon && iconPosition === "start" && /* @__PURE__ */ jsx21("span", { className: "fractal-text-button__icon", "aria-hidden": "true", children: icon }),
|
|
1239
|
+
/* @__PURE__ */ jsx21("span", { children }),
|
|
1240
|
+
icon && iconPosition === "end" && /* @__PURE__ */ jsx21("span", { className: "fractal-text-button__icon", "aria-hidden": "true", children: icon })
|
|
1241
|
+
]
|
|
1242
|
+
}
|
|
1243
|
+
)
|
|
1244
|
+
);
|
|
1245
|
+
TextButton.displayName = "TextButton";
|
|
1246
|
+
|
|
1247
|
+
// src/components/FileDropzone/FileDropzone.tsx
|
|
1248
|
+
import * as React14 from "react";
|
|
1249
|
+
import { Close as Close2, FileArrowUp } from "@mirror-physics/fractal-icons";
|
|
1250
|
+
import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1251
|
+
function FileDropzone({
|
|
1252
|
+
files,
|
|
1253
|
+
onFilesChange,
|
|
1254
|
+
accept,
|
|
1255
|
+
multiple = true,
|
|
1256
|
+
disabled = false,
|
|
1257
|
+
title = "Drop files here or click to browse",
|
|
1258
|
+
description = "Files stay attached to this record.",
|
|
1259
|
+
className
|
|
1260
|
+
}) {
|
|
1261
|
+
const inputId = React14.useId();
|
|
1262
|
+
const inputRef = React14.useRef(null);
|
|
1263
|
+
const [isDragging, setIsDragging] = React14.useState(false);
|
|
1264
|
+
const addFiles = (nextFiles) => {
|
|
1265
|
+
if (disabled) return;
|
|
1266
|
+
const additions = Array.from(nextFiles);
|
|
1267
|
+
if (additions.length === 0) return;
|
|
1268
|
+
onFilesChange(multiple ? [...files, ...additions] : additions.slice(0, 1));
|
|
1269
|
+
};
|
|
1270
|
+
return /* @__PURE__ */ jsxs15("div", { className: cn("fractal-file-dropzone", className), children: [
|
|
1271
|
+
/* @__PURE__ */ jsx22(
|
|
1272
|
+
"input",
|
|
1273
|
+
{
|
|
1274
|
+
ref: inputRef,
|
|
1275
|
+
id: inputId,
|
|
1276
|
+
className: "fractal-file-dropzone__input",
|
|
1277
|
+
type: "file",
|
|
1278
|
+
accept,
|
|
1279
|
+
multiple,
|
|
1280
|
+
disabled,
|
|
1281
|
+
onChange: (event) => {
|
|
1282
|
+
if (event.target.files) addFiles(event.target.files);
|
|
1283
|
+
event.target.value = "";
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
),
|
|
1287
|
+
/* @__PURE__ */ jsxs15(
|
|
1288
|
+
"button",
|
|
1289
|
+
{
|
|
1290
|
+
className: "fractal-file-dropzone__target",
|
|
1291
|
+
"data-dragging": isDragging || void 0,
|
|
1292
|
+
type: "button",
|
|
1293
|
+
disabled,
|
|
1294
|
+
onClick: () => inputRef.current?.click(),
|
|
1295
|
+
onDragEnter: (event) => {
|
|
1296
|
+
event.preventDefault();
|
|
1297
|
+
if (!disabled) setIsDragging(true);
|
|
1298
|
+
},
|
|
1299
|
+
onDragOver: (event) => event.preventDefault(),
|
|
1300
|
+
onDragLeave: (event) => {
|
|
1301
|
+
event.preventDefault();
|
|
1302
|
+
setIsDragging(false);
|
|
1303
|
+
},
|
|
1304
|
+
onDrop: (event) => {
|
|
1305
|
+
event.preventDefault();
|
|
1306
|
+
setIsDragging(false);
|
|
1307
|
+
addFiles(event.dataTransfer.files);
|
|
1308
|
+
},
|
|
1309
|
+
children: [
|
|
1310
|
+
/* @__PURE__ */ jsx22(FileArrowUp, { "aria-hidden": "true", size: 20 }),
|
|
1311
|
+
/* @__PURE__ */ jsxs15("span", { className: "fractal-file-dropzone__copy", children: [
|
|
1312
|
+
/* @__PURE__ */ jsx22("span", { className: "fractal-file-dropzone__title", children: title }),
|
|
1313
|
+
description && /* @__PURE__ */ jsx22("span", { className: "fractal-file-dropzone__description", children: description })
|
|
1314
|
+
] })
|
|
1315
|
+
]
|
|
1316
|
+
}
|
|
1317
|
+
),
|
|
1318
|
+
files.length > 0 && /* @__PURE__ */ jsx22("ul", { className: "fractal-file-dropzone__files", "aria-label": "Attached files", children: files.map((file, index) => /* @__PURE__ */ jsxs15("li", { className: "fractal-file-dropzone__file", children: [
|
|
1319
|
+
/* @__PURE__ */ jsx22("span", { className: "fractal-file-dropzone__file-name", children: file.name }),
|
|
1320
|
+
/* @__PURE__ */ jsx22("span", { className: "fractal-file-dropzone__file-meta", children: formatFileSize(file.size) }),
|
|
1321
|
+
/* @__PURE__ */ jsx22(
|
|
1322
|
+
"button",
|
|
1323
|
+
{
|
|
1324
|
+
className: "fractal-file-dropzone__remove",
|
|
1325
|
+
type: "button",
|
|
1326
|
+
"aria-label": `Remove ${file.name}`,
|
|
1327
|
+
disabled,
|
|
1328
|
+
onClick: () => onFilesChange(files.filter((_, fileIndex) => fileIndex !== index)),
|
|
1329
|
+
children: /* @__PURE__ */ jsx22(Close2, { "aria-hidden": "true", size: 14 })
|
|
1330
|
+
}
|
|
1331
|
+
)
|
|
1332
|
+
] }, `${file.name}-${file.size}-${index}`)) })
|
|
1333
|
+
] });
|
|
1334
|
+
}
|
|
1335
|
+
function formatFileSize(bytes) {
|
|
1336
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
1337
|
+
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
|
|
1338
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
// src/components/Pagination/Pagination.tsx
|
|
1342
|
+
import { ArrowLeft, ArrowRight } from "@mirror-physics/fractal-icons";
|
|
1343
|
+
import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1344
|
+
function Pagination({
|
|
1345
|
+
page,
|
|
1346
|
+
pageSize,
|
|
1347
|
+
totalItems,
|
|
1348
|
+
onPageChange,
|
|
1349
|
+
pageSizeOptions,
|
|
1350
|
+
onPageSizeChange,
|
|
1351
|
+
ariaLabel = "Pagination",
|
|
1352
|
+
className
|
|
1353
|
+
}) {
|
|
1354
|
+
const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
|
|
1355
|
+
const currentPage = Math.min(Math.max(page, 1), totalPages);
|
|
1356
|
+
const start = totalItems === 0 ? 0 : (currentPage - 1) * pageSize + 1;
|
|
1357
|
+
const end = Math.min(currentPage * pageSize, totalItems);
|
|
1358
|
+
const canChangePageSize = pageSizeOptions != null && pageSizeOptions.length > 0 && onPageSizeChange != null;
|
|
1359
|
+
return /* @__PURE__ */ jsxs16("nav", { className: cn("fractal-pagination", className), "aria-label": ariaLabel, children: [
|
|
1360
|
+
/* @__PURE__ */ jsx23("span", { className: "fractal-pagination__summary", children: totalItems === 0 ? "No results" : `${start}-${end} of ${totalItems}` }),
|
|
1361
|
+
/* @__PURE__ */ jsxs16("div", { className: "fractal-pagination__controls", children: [
|
|
1362
|
+
canChangePageSize && /* @__PURE__ */ jsx23(
|
|
1363
|
+
Dropdown,
|
|
1364
|
+
{
|
|
1365
|
+
align: "right",
|
|
1366
|
+
className: "fractal-pagination__page-size",
|
|
1367
|
+
direction: "up",
|
|
1368
|
+
items: pageSizeOptions.map((option) => ({
|
|
1369
|
+
value: String(option),
|
|
1370
|
+
description: `${option} per page`
|
|
1371
|
+
})),
|
|
1372
|
+
onSelect: (value) => onPageSizeChange(Number(value)),
|
|
1373
|
+
selectedValue: String(pageSize),
|
|
1374
|
+
size: "sm",
|
|
1375
|
+
triggerLabel: "Results per page",
|
|
1376
|
+
triggerVariant: "tertiary"
|
|
1377
|
+
}
|
|
1378
|
+
),
|
|
1379
|
+
/* @__PURE__ */ jsx23(
|
|
1380
|
+
"button",
|
|
1381
|
+
{
|
|
1382
|
+
className: "fractal-pagination__button",
|
|
1383
|
+
type: "button",
|
|
1384
|
+
"aria-label": "Previous page",
|
|
1385
|
+
title: "Previous page",
|
|
1386
|
+
disabled: currentPage === 1 || totalItems === 0,
|
|
1387
|
+
onClick: () => onPageChange(currentPage - 1),
|
|
1388
|
+
children: /* @__PURE__ */ jsx23(ArrowLeft, { "aria-hidden": "true", size: 16 })
|
|
1389
|
+
}
|
|
1390
|
+
),
|
|
1391
|
+
/* @__PURE__ */ jsxs16("span", { className: "fractal-pagination__page", "aria-current": "page", children: [
|
|
1392
|
+
currentPage,
|
|
1393
|
+
" of ",
|
|
1394
|
+
totalPages
|
|
1395
|
+
] }),
|
|
1396
|
+
/* @__PURE__ */ jsx23(
|
|
1397
|
+
"button",
|
|
1398
|
+
{
|
|
1399
|
+
className: "fractal-pagination__button",
|
|
1400
|
+
type: "button",
|
|
1401
|
+
"aria-label": "Next page",
|
|
1402
|
+
title: "Next page",
|
|
1403
|
+
disabled: currentPage === totalPages || totalItems === 0,
|
|
1404
|
+
onClick: () => onPageChange(currentPage + 1),
|
|
1405
|
+
children: /* @__PURE__ */ jsx23(ArrowRight, { "aria-hidden": "true", size: 16 })
|
|
1406
|
+
}
|
|
1407
|
+
)
|
|
1408
|
+
] })
|
|
1409
|
+
] });
|
|
1410
|
+
}
|
|
1030
1411
|
export {
|
|
1031
1412
|
Alert,
|
|
1032
1413
|
AlertDescription,
|
|
@@ -1038,18 +1419,24 @@ export {
|
|
|
1038
1419
|
CardFooter,
|
|
1039
1420
|
CardHeader,
|
|
1040
1421
|
CardTitle,
|
|
1422
|
+
Checkbox,
|
|
1041
1423
|
Chip,
|
|
1424
|
+
ContentSwitcher,
|
|
1042
1425
|
DataTable,
|
|
1043
1426
|
Disclosure,
|
|
1044
1427
|
Dropdown,
|
|
1045
1428
|
FeatureCard,
|
|
1429
|
+
FileDropzone,
|
|
1046
1430
|
FolderCard,
|
|
1047
1431
|
Input,
|
|
1048
1432
|
Label,
|
|
1433
|
+
LatticeLoader,
|
|
1049
1434
|
Link,
|
|
1050
1435
|
Modal,
|
|
1436
|
+
Pagination,
|
|
1051
1437
|
PromptCard,
|
|
1052
1438
|
PromptGrid,
|
|
1439
|
+
SidePanel,
|
|
1053
1440
|
Sidebar,
|
|
1054
1441
|
SidebarBrand,
|
|
1055
1442
|
SidebarFooter,
|
|
@@ -1059,6 +1446,8 @@ export {
|
|
|
1059
1446
|
SidebarSection,
|
|
1060
1447
|
SortableTable,
|
|
1061
1448
|
Tabs,
|
|
1449
|
+
TextButton,
|
|
1450
|
+
Textarea,
|
|
1062
1451
|
Toggle,
|
|
1063
1452
|
cn,
|
|
1064
1453
|
useEscapeDismiss
|