@mirror-physics/fractal-ui 0.2.0-next.78 → 0.2.0-next.80

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.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  Button,
3
3
  ColumnEditor,
4
4
  cn
5
- } from "./chunk-QZX655IA.js";
5
+ } from "./chunk-UNMOINWV.js";
6
6
 
7
7
  // src/components/CodeBlock/CodeBlock.tsx
8
8
  import { useEffect, useMemo, useRef, useState } from "react";
@@ -508,29 +508,50 @@ PromptGrid.displayName = "PromptGrid";
508
508
 
509
509
  // src/components/Input/Input.tsx
510
510
  import * as React3 from "react";
511
- import { jsx as jsx5 } from "react/jsx-runtime";
511
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
512
512
  var Input = React3.forwardRef(
513
- ({ className, type, controlSize = "md", ...props }, ref) => /* @__PURE__ */ jsx5(
514
- "input",
515
- {
516
- type,
517
- ref,
518
- "data-control-size": controlSize,
519
- className: cn("fractal-control", "fractal-input", className),
520
- ...props
521
- }
522
- )
513
+ ({ className, type, controlSize = "lg", fieldLabel, id, placeholder, ...props }, ref) => {
514
+ const generatedId = React3.useId();
515
+ const fieldId = id ?? generatedId;
516
+ const floatingLabel = type === "search" ? void 0 : fieldLabel;
517
+ const input = /* @__PURE__ */ jsx5(
518
+ "input",
519
+ {
520
+ type,
521
+ ref,
522
+ id: floatingLabel ? fieldId : id,
523
+ placeholder: floatingLabel ? placeholder || " " : placeholder,
524
+ "data-control-size": controlSize,
525
+ className: cn("fractal-control", "fractal-input", className),
526
+ ...props,
527
+ "aria-label": props["aria-label"] ?? (type === "search" && !props["aria-labelledby"] ? fieldLabel ?? "Search" : void 0)
528
+ }
529
+ );
530
+ if (!floatingLabel) return input;
531
+ return /* @__PURE__ */ jsxs5(
532
+ "div",
533
+ {
534
+ className: "fractal-floating-field",
535
+ "data-control-size": controlSize,
536
+ "data-always-float": ["date", "datetime-local", "time", "month", "week", "color", "file", "range"].includes(type ?? "") || void 0,
537
+ children: [
538
+ input,
539
+ /* @__PURE__ */ jsx5("label", { className: "fractal-floating-field__label", htmlFor: fieldId, children: fieldLabel })
540
+ ]
541
+ }
542
+ );
543
+ }
523
544
  );
524
545
  Input.displayName = "Input";
525
546
 
526
547
  // src/components/TableSearch/TableSearch.tsx
527
548
  import * as React4 from "react";
528
549
  import { MagnifyingGlass, MagnifyingGlassLines } from "@mirror-physics/fractal-icons";
529
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
550
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
530
551
  var TableSearch = React4.forwardRef(
531
552
  ({
532
553
  searchType = "text",
533
- controlSize = "md",
554
+ controlSize = "lg",
534
555
  className,
535
556
  inputClassName,
536
557
  placeholder,
@@ -539,7 +560,7 @@ var TableSearch = React4.forwardRef(
539
560
  }, ref) => {
540
561
  const isGlob = searchType === "glob";
541
562
  const SearchIcon = isGlob ? MagnifyingGlassLines : MagnifyingGlass;
542
- return /* @__PURE__ */ jsxs5(
563
+ return /* @__PURE__ */ jsxs6(
543
564
  "div",
544
565
  {
545
566
  className: cn("fractal-table-search", className),
@@ -569,10 +590,10 @@ TableSearch.displayName = "TableSearch";
569
590
  // src/components/NumberInput/NumberInput.tsx
570
591
  import * as React5 from "react";
571
592
  import { Minus, Plus } from "@mirror-physics/fractal-icons";
572
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
593
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
573
594
  function NumberInput({
574
595
  unit,
575
- controlSize = "md",
596
+ controlSize = "lg",
576
597
  className,
577
598
  value,
578
599
  defaultValue,
@@ -585,7 +606,7 @@ function NumberInput({
585
606
  const inputRef = React5.useRef(null);
586
607
  const numericValue = Number(value ?? defaultValue);
587
608
  const characterCount = Math.max(String(value ?? defaultValue ?? "").length, 1);
588
- const controlLabel = typeof props["aria-label"] === "string" ? props["aria-label"] : "value";
609
+ const controlLabel = typeof props["aria-label"] === "string" ? props["aria-label"] : props.fieldLabel ?? "value";
589
610
  const decrementDisabled = disabled || readOnly || Number.isFinite(numericValue) && min !== void 0 && numericValue <= Number(min);
590
611
  const incrementDisabled = disabled || readOnly || Number.isFinite(numericValue) && max !== void 0 && numericValue >= Number(max);
591
612
  const changeByStep = (direction) => {
@@ -596,7 +617,7 @@ function NumberInput({
596
617
  input.dispatchEvent(new Event("input", { bubbles: true }));
597
618
  input.focus();
598
619
  };
599
- return /* @__PURE__ */ jsxs6("div", { "data-control-size": controlSize, className: cn("fractal-number-input", unit && "fractal-number-input--with-unit", className), children: [
620
+ return /* @__PURE__ */ jsxs7("div", { "data-control-size": controlSize, className: cn("fractal-number-input", unit && "fractal-number-input--with-unit", className), children: [
600
621
  /* @__PURE__ */ jsx7(
601
622
  Input,
602
623
  {
@@ -621,7 +642,7 @@ function NumberInput({
621
642
  children: unit
622
643
  }
623
644
  ),
624
- /* @__PURE__ */ jsxs6("div", { className: "fractal-number-input-controls", children: [
645
+ /* @__PURE__ */ jsxs7("div", { className: "fractal-number-input-controls", children: [
625
646
  /* @__PURE__ */ jsx7(
626
647
  "button",
627
648
  {
@@ -649,7 +670,7 @@ function NumberInput({
649
670
  }
650
671
 
651
672
  // src/components/Slider/Slider.tsx
652
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
673
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
653
674
  function Slider(props) {
654
675
  const {
655
676
  min = 0,
@@ -695,18 +716,18 @@ function Slider(props) {
695
716
  if (!(event.key in adjustments)) return null;
696
717
  return value + adjustments[event.key];
697
718
  };
698
- return /* @__PURE__ */ jsxs7(
719
+ return /* @__PURE__ */ jsxs8(
699
720
  "div",
700
721
  {
701
722
  className: cn("fractal-slider", disabled && "fractal-slider--disabled", className),
702
723
  "data-disabled": disabled || void 0,
703
724
  "data-knobs": knobs,
704
725
  children: [
705
- showValues && /* @__PURE__ */ jsxs7("div", { className: "fractal-slider-values", "aria-hidden": "true", children: [
726
+ showValues && /* @__PURE__ */ jsxs8("div", { className: "fractal-slider-values", "aria-hidden": "true", children: [
706
727
  /* @__PURE__ */ jsx8("output", { children: formatValue(firstValue) }),
707
728
  knobs === 2 && /* @__PURE__ */ jsx8("output", { children: formatValue(secondValue) })
708
729
  ] }),
709
- /* @__PURE__ */ jsxs7(
730
+ /* @__PURE__ */ jsxs8(
710
731
  "div",
711
732
  {
712
733
  className: "fractal-slider-control",
@@ -777,11 +798,11 @@ function clamp(value, minimum, maximum) {
777
798
  // src/components/PasswordInput/PasswordInput.tsx
778
799
  import * as React6 from "react";
779
800
  import { Eye, EyeSlash } from "@mirror-physics/fractal-icons";
780
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
801
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
781
802
  var PasswordInput = React6.forwardRef(
782
803
  ({
783
804
  className,
784
- controlSize = "md",
805
+ controlSize = "lg",
785
806
  disabled,
786
807
  showPasswordLabel = "Show password",
787
808
  hidePasswordLabel = "Hide password",
@@ -789,7 +810,7 @@ var PasswordInput = React6.forwardRef(
789
810
  }, ref) => {
790
811
  const [passwordVisible, setPasswordVisible] = React6.useState(false);
791
812
  const toggleLabel = passwordVisible ? hidePasswordLabel : showPasswordLabel;
792
- return /* @__PURE__ */ jsxs8(
813
+ return /* @__PURE__ */ jsxs9(
793
814
  "div",
794
815
  {
795
816
  className: cn("fractal-password-input", className),
@@ -831,7 +852,7 @@ PasswordInput.displayName = "PasswordInput";
831
852
  import * as React7 from "react";
832
853
  import { jsx as jsx10 } from "react/jsx-runtime";
833
854
  var Label = React7.forwardRef(
834
- ({ className, controlSize = "md", ...props }, ref) => /* @__PURE__ */ jsx10(
855
+ ({ className, controlSize = "lg", ...props }, ref) => /* @__PURE__ */ jsx10(
835
856
  "label",
836
857
  {
837
858
  ref,
@@ -846,7 +867,7 @@ Label.displayName = "Label";
846
867
  // src/components/Alert/Alert.tsx
847
868
  import * as React8 from "react";
848
869
  import { CircleCheck, CircleClose, CircleInfo, Warning } from "@mirror-physics/fractal-icons";
849
- import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
870
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
850
871
  var defaultIcons = {
851
872
  default: CircleInfo,
852
873
  info: CircleInfo,
@@ -857,7 +878,7 @@ var defaultIcons = {
857
878
  var Alert = React8.forwardRef(
858
879
  ({ className, variant = "default", icon, children, ...props }, ref) => {
859
880
  const DefaultIcon = defaultIcons[variant];
860
- return /* @__PURE__ */ jsxs9(
881
+ return /* @__PURE__ */ jsxs10(
861
882
  "div",
862
883
  {
863
884
  ref,
@@ -886,7 +907,7 @@ AlertDescription.displayName = "AlertDescription";
886
907
  import * as React9 from "react";
887
908
  import { createPortal } from "react-dom";
888
909
  import { CircleCheck as CircleCheck2, CircleClose as CircleClose2, CircleInfo as CircleInfo2, Close, Warning as Warning2 } from "@mirror-physics/fractal-icons";
889
- import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
910
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
890
911
  var defaultIcons2 = {
891
912
  default: CircleInfo2,
892
913
  info: CircleInfo2,
@@ -923,7 +944,7 @@ var Toast = React9.forwardRef(function Toast2({
923
944
  return () => window.clearTimeout(timeout);
924
945
  }, [paused, resolvedDuration]);
925
946
  const announcementRole = role ?? (variant === "error" ? "alert" : "status");
926
- return /* @__PURE__ */ jsxs10(
947
+ return /* @__PURE__ */ jsxs11(
927
948
  "div",
928
949
  {
929
950
  ref,
@@ -982,9 +1003,9 @@ var ToastViewport = React9.forwardRef(function ToastViewport2({ children, classN
982
1003
  });
983
1004
 
984
1005
  // src/components/Toggle/Toggle.tsx
985
- import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
1006
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
986
1007
  function Toggle({ checked, onChange, label, className }) {
987
- return /* @__PURE__ */ jsxs11(
1008
+ return /* @__PURE__ */ jsxs12(
988
1009
  "button",
989
1010
  {
990
1011
  type: "button",
@@ -1055,13 +1076,13 @@ function useEscapeDismiss(priority, handler, enabled = true) {
1055
1076
  }
1056
1077
 
1057
1078
  // src/components/UILoader/UILoader.tsx
1058
- import { useId } from "react";
1059
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1079
+ import { useId as useId2 } from "react";
1080
+ import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
1060
1081
  var LEFT = "M0 53C0 51 1.6 49.5 3.6 49.5h16.5c1 0 1.9.4 2.5 1L42.1 69.6c.7.7 1.1 1.6 1.1 2.5v16.2c0 2-1.6 3.5-3.6 3.5H23.1c-1 0-1.9-.4-2.5-1L1.1 71.7C.4 71 0 70.1 0 69.2V53Z";
1061
1082
  var CENTER = "M0 3.5C0 1.6 1.6 0 3.6 0h16.5c1 0 1.9.4 2.5 1L92.5 69.6c.7.7 1 1.6 1 2.5v16.2c0 2-1.6 3.5-3.6 3.5H73.4c-1 0-1.9-.4-2.5-1L1.1 22.2C.4 21.6 0 20.7 0 19.7V3.5Z";
1062
1083
  var RIGHT = "M50.4 3.5C50.4 1.6 52 0 54 0h16.5c1 0 1.9.4 2.5 1l69.8 68.6c.7.7 1.1 1.6 1.1 2.5v16.2c0 2-1.6 3.5-3.6 3.5h-16.5c-1 0-1.9-.4-2.5-1L51.4 22.2c-.7-.6-1-1.5-1-2.5V3.5Z";
1063
1084
  function UILoader({ size = 48, tone = "neutral", className, style, label = "Loading", ariaHidden = false }) {
1064
- const rawId = useId().replace(/[^a-zA-Z0-9_-]/g, "");
1085
+ const rawId = useId2().replace(/[^a-zA-Z0-9_-]/g, "");
1065
1086
  const clipId = `fractal-ui-loader-clip-${rawId}`;
1066
1087
  const gradientId = `fractal-ui-loader-gradient-${rawId}`;
1067
1088
  const height = typeof size === "number" ? `${size}px` : size;
@@ -1073,18 +1094,18 @@ function UILoader({ size = 48, tone = "neutral", className, style, label = "Load
1073
1094
  className: cn("fractal-ui-loader", `fractal-ui-loader--${tone}`, className),
1074
1095
  role: ariaHidden ? void 0 : "status",
1075
1096
  style,
1076
- children: /* @__PURE__ */ jsxs12("svg", { "aria-hidden": "true", fill: "none", viewBox: "0 0 144 92", style: { height, width: "auto" }, children: [
1077
- /* @__PURE__ */ jsxs12("defs", { children: [
1078
- /* @__PURE__ */ jsxs12("linearGradient", { id: gradientId, x1: "59", x2: "94.3", y1: "0", y2: "89.1", gradientUnits: "userSpaceOnUse", children: [
1097
+ children: /* @__PURE__ */ jsxs13("svg", { "aria-hidden": "true", fill: "none", viewBox: "0 0 144 92", style: { height, width: "auto" }, children: [
1098
+ /* @__PURE__ */ jsxs13("defs", { children: [
1099
+ /* @__PURE__ */ jsxs13("linearGradient", { id: gradientId, x1: "59", x2: "94.3", y1: "0", y2: "89.1", gradientUnits: "userSpaceOnUse", children: [
1079
1100
  /* @__PURE__ */ jsx14("stop", { className: "fractal-ui-loader__stop-start", offset: "0" }),
1080
1101
  /* @__PURE__ */ jsx14("stop", { className: "fractal-ui-loader__stop-end", offset: "1" })
1081
1102
  ] }),
1082
- /* @__PURE__ */ jsxs12("linearGradient", { id: `${gradientId}-shine`, x1: "0", x2: "1", y1: "0", y2: "0", children: [
1103
+ /* @__PURE__ */ jsxs13("linearGradient", { id: `${gradientId}-shine`, x1: "0", x2: "1", y1: "0", y2: "0", children: [
1083
1104
  /* @__PURE__ */ jsx14("stop", { offset: "0.4", stopColor: "white", stopOpacity: "0" }),
1084
1105
  /* @__PURE__ */ jsx14("stop", { offset: "0.5", stopColor: "white", stopOpacity: "0.62" }),
1085
1106
  /* @__PURE__ */ jsx14("stop", { offset: "0.6", stopColor: "white", stopOpacity: "0" })
1086
1107
  ] }),
1087
- /* @__PURE__ */ jsxs12("clipPath", { id: clipId, children: [
1108
+ /* @__PURE__ */ jsxs13("clipPath", { id: clipId, children: [
1088
1109
  /* @__PURE__ */ jsx14("path", { d: LEFT }),
1089
1110
  /* @__PURE__ */ jsx14("path", { d: CENTER }),
1090
1111
  /* @__PURE__ */ jsx14("path", { d: RIGHT })
@@ -1100,7 +1121,7 @@ function UILoader({ size = 48, tone = "neutral", className, style, label = "Load
1100
1121
  }
1101
1122
 
1102
1123
  // src/components/Modal/Modal.tsx
1103
- import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
1124
+ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
1104
1125
  var CloseIcon = () => /* @__PURE__ */ jsx15("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx15("path", { d: "M12 4L4 12M4 4L12 12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
1105
1126
  function Modal({ open, onClose, title, children, danger, warn, footer, noClose, closeDisabled = false, size = "sm", loading = false, loadingLabel = "Loading", scrollable = false, className }) {
1106
1127
  const [bodyScrolled, setBodyScrolled] = React10.useState(false);
@@ -1112,13 +1133,13 @@ function Modal({ open, onClose, title, children, danger, warn, footer, noClose,
1112
1133
  const sizeClass = `fractal-modal-panel--${size}`;
1113
1134
  const accentClass = danger ? "fractal-modal-panel--danger" : warn ? "fractal-modal-panel--warn" : "";
1114
1135
  return createPortal2(
1115
- /* @__PURE__ */ jsx15("div", { className: "fractal-modal-overlay", onClick: noClose || closeDisabled ? void 0 : onClose, children: /* @__PURE__ */ jsxs13(
1136
+ /* @__PURE__ */ jsx15("div", { className: "fractal-modal-overlay", onClick: noClose || closeDisabled ? void 0 : onClose, children: /* @__PURE__ */ jsxs14(
1116
1137
  "div",
1117
1138
  {
1118
1139
  className: cn("fractal-modal-panel", sizeClass, accentClass, scrollable && "fractal-modal-panel--scrollable", className),
1119
1140
  onClick: (e) => e.stopPropagation(),
1120
1141
  children: [
1121
- /* @__PURE__ */ jsxs13(
1142
+ /* @__PURE__ */ jsxs14(
1122
1143
  "div",
1123
1144
  {
1124
1145
  className: cn(
@@ -1155,12 +1176,12 @@ function Modal({ open, onClose, title, children, danger, warn, footer, noClose,
1155
1176
  }
1156
1177
 
1157
1178
  // src/components/TableLayout/TableOverflowMenu.tsx
1158
- import { useId as useId2, useLayoutEffect, useRef as useRef5, useState as useState5 } from "react";
1179
+ import { useId as useId3, useLayoutEffect, useRef as useRef5, useState as useState5 } from "react";
1159
1180
  import { createPortal as createPortal3 } from "react-dom";
1160
1181
  import { Ellipsis } from "@mirror-physics/fractal-icons";
1161
- import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
1182
+ import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
1162
1183
  function TableOverflowMenu({ items, label, disabled, onSelect }) {
1163
- const id = useId2();
1184
+ const id = useId3();
1164
1185
  const trigger = useRef5(null);
1165
1186
  const panel = useRef5(null);
1166
1187
  const initialLast = useRef5(false);
@@ -1209,7 +1230,7 @@ function TableOverflowMenu({ items, label, disabled, onSelect }) {
1209
1230
  if (disabled || items.length === 0) setOpen(false);
1210
1231
  }, [disabled, items.length]);
1211
1232
  if (items.length === 0) return null;
1212
- return /* @__PURE__ */ jsxs14("div", { className: "fractal-table-overflow-trigger", children: [
1233
+ return /* @__PURE__ */ jsxs15("div", { className: "fractal-table-overflow-trigger", children: [
1213
1234
  /* @__PURE__ */ jsx16(
1214
1235
  Button,
1215
1236
  {
@@ -1264,7 +1285,7 @@ function TableOverflowMenu({ items, label, disabled, onSelect }) {
1264
1285
  ordered.find((button) => button.textContent?.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase()))?.focus();
1265
1286
  }
1266
1287
  },
1267
- children: items.map((item) => /* @__PURE__ */ jsxs14(
1288
+ children: items.map((item) => /* @__PURE__ */ jsxs15(
1268
1289
  "button",
1269
1290
  {
1270
1291
  type: "button",
@@ -1377,16 +1398,16 @@ function TableCellContent({ children, label }) {
1377
1398
  }
1378
1399
 
1379
1400
  // src/components/DataTable/DataTable.tsx
1380
- import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
1401
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
1381
1402
  function DataTable({ columns, data, emptyMessage, header, size = "md", className, overflowMenu, layout = "fill", stickyHeader = false, stickyFirstColumn = false, maxHeight, "aria-label": ariaLabel = "Data table" }) {
1382
- return /* @__PURE__ */ jsx18("div", { className: cn("fractal-table-layout", "fractal-datatable", `fractal-datatable--${size}`, className), "data-overflow-menu": Boolean(overflowMenu), "data-table-layout": layout, "data-sticky-first": stickyFirstColumn, "data-sticky-header": stickyHeader, children: /* @__PURE__ */ jsxs15("div", { className: "fractal-datatable-surface", children: [
1403
+ return /* @__PURE__ */ jsx18("div", { className: cn("fractal-table-layout", "fractal-datatable", `fractal-datatable--${size}`, className), "data-overflow-menu": Boolean(overflowMenu), "data-table-layout": layout, "data-sticky-first": stickyFirstColumn, "data-sticky-header": stickyHeader, children: /* @__PURE__ */ jsxs16("div", { className: "fractal-datatable-surface", children: [
1383
1404
  header && /* @__PURE__ */ jsx18("div", { className: "fractal-datatable-header", children: header }),
1384
- data.length === 0 ? /* @__PURE__ */ jsx18("div", { className: "fractal-datatable-empty", children: emptyMessage || "No data" }) : /* @__PURE__ */ jsx18(TableViewport, { maxHeight, label: ariaLabel, children: /* @__PURE__ */ jsxs15("table", { "aria-label": ariaLabel, className: "fractal-datatable-table", children: [
1385
- /* @__PURE__ */ jsx18("thead", { children: /* @__PURE__ */ jsxs15("tr", { className: "fractal-datatable-thead-row", children: [
1405
+ data.length === 0 ? /* @__PURE__ */ jsx18("div", { className: "fractal-datatable-empty", children: emptyMessage || "No data" }) : /* @__PURE__ */ jsx18(TableViewport, { maxHeight, label: ariaLabel, children: /* @__PURE__ */ jsxs16("table", { "aria-label": ariaLabel, className: "fractal-datatable-table", children: [
1406
+ /* @__PURE__ */ jsx18("thead", { children: /* @__PURE__ */ jsxs16("tr", { className: "fractal-datatable-thead-row", children: [
1386
1407
  columns.map((col, columnIndex) => /* @__PURE__ */ jsx18("th", { scope: "col", className: "fractal-datatable-th", style: columnStyle(col), "data-pinned-column": columnIndex === 0 ? "data" : void 0, children: /* @__PURE__ */ jsx18(TableCellContent, { label: `${col.header} column`, children: col.header }) }, col.key)),
1387
1408
  overflowMenu && /* @__PURE__ */ jsx18("th", { scope: "col", "aria-label": "Row actions", className: "fractal-datatable-th fractal-table-overflow-cell", "data-pinned-column": "overflow" })
1388
1409
  ] }) }),
1389
- /* @__PURE__ */ jsx18("tbody", { children: data.map((row, rowIndex) => /* @__PURE__ */ jsxs15(
1410
+ /* @__PURE__ */ jsx18("tbody", { children: data.map((row, rowIndex) => /* @__PURE__ */ jsxs16(
1390
1411
  "tr",
1391
1412
  {
1392
1413
  className: "fractal-datatable-row",
@@ -1403,7 +1424,7 @@ function DataTable({ columns, data, emptyMessage, header, size = "md", className
1403
1424
 
1404
1425
  // src/components/Dropdown/Dropdown.tsx
1405
1426
  import * as React11 from "react";
1406
- import { ChevronDown, ChevronLeft, ChevronRight as ChevronRight2, ChevronUp } from "@mirror-physics/fractal-icons";
1427
+ import { Check as Check2, MagnifyingGlass as MagnifyingGlass2, ChevronDown, ChevronLeft, ChevronRight as ChevronRight2, ChevronUp } from "@mirror-physics/fractal-icons";
1407
1428
 
1408
1429
  // src/components/Dropdown/position.ts
1409
1430
  function positionDropdown(trigger, panel, bounds, direction, align) {
@@ -1441,12 +1462,19 @@ function positionDropdown(trigger, panel, bounds, direction, align) {
1441
1462
  }
1442
1463
 
1443
1464
  // src/components/Dropdown/Dropdown.tsx
1444
- import { Fragment as Fragment2, jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
1465
+ import { Fragment as Fragment2, jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
1445
1466
  function Dropdown({
1446
1467
  items,
1447
- selectedValue,
1468
+ selectedValue = "",
1448
1469
  onSelect,
1449
- triggerLabel = "Options",
1470
+ multiple = false,
1471
+ selectedValues = [],
1472
+ onSelectionChange,
1473
+ searchable = false,
1474
+ searchPlaceholder = "Find an option",
1475
+ emptyMessage = "No matching options.",
1476
+ triggerLabel,
1477
+ fieldLabel,
1450
1478
  direction = "down",
1451
1479
  align = "left",
1452
1480
  maxHeight = 320,
@@ -1456,7 +1484,7 @@ function Dropdown({
1456
1484
  label,
1457
1485
  iconOnly = false,
1458
1486
  noChevron = false,
1459
- size: sizeAlias = "md",
1487
+ size: sizeAlias = "lg",
1460
1488
  controlSize,
1461
1489
  triggerId,
1462
1490
  triggerVariant = "outline",
@@ -1466,17 +1494,37 @@ function Dropdown({
1466
1494
  closeOnSelect = true,
1467
1495
  disabled = false
1468
1496
  }) {
1497
+ const [query, setQuery] = React11.useState("");
1498
+ const searchRef = React11.useRef(null);
1499
+ const accessibleLabel = triggerLabel ?? fieldLabel ?? "Options";
1469
1500
  const size = controlSize ?? sizeAlias;
1470
1501
  const [open, setOpen] = React11.useState(false);
1502
+ React11.useEffect(() => {
1503
+ if (!open) setQuery("");
1504
+ }, [open]);
1471
1505
  const rootRef = React11.useRef(null);
1472
1506
  const menuId = React11.useId();
1473
1507
  const focusOnOpen = React11.useRef(false);
1474
1508
  const triggerRef = React11.useRef(null);
1475
1509
  const panelRef = React11.useRef(null);
1476
1510
  const [panelStyle, setPanelStyle] = React11.useState({});
1477
- const visibleItems = items.filter(
1511
+ const renderableItems = items.filter(
1478
1512
  (item) => item.icon != null || item.description != null && (typeof item.description === "string" ? item.description !== "" : true)
1479
1513
  );
1514
+ const normalizedQuery = query.trim().toLocaleLowerCase();
1515
+ let groupTitle = "";
1516
+ const matching = new Set(renderableItems.filter((item) => {
1517
+ if (item.kind === "header") {
1518
+ groupTitle = String(item.description ?? "");
1519
+ return false;
1520
+ }
1521
+ return `${groupTitle} ${typeof item.description === "string" ? item.description : item.value}`.toLocaleLowerCase().includes(normalizedQuery);
1522
+ }).map((item) => item.value));
1523
+ const visibleItems = renderableItems.filter((item, index) => {
1524
+ if (item.kind !== "header") return matching.has(item.value);
1525
+ const nextHeader = renderableItems.findIndex((next, i) => i > index && next.kind === "header");
1526
+ return renderableItems.slice(index + 1, nextHeader < 0 ? void 0 : nextHeader).some((next) => matching.has(next.value));
1527
+ });
1480
1528
  const selectableItems = visibleItems.filter((i) => i.kind !== "header");
1481
1529
  const selected = items.find((i) => i.value === selectedValue && i.kind !== "header") ?? selectableItems[0] ?? visibleItems[0];
1482
1530
  const ChevronIcon = direction === "up" ? ChevronUp : direction === "left" ? ChevronLeft : direction === "right" ? ChevronRight2 : ChevronDown;
@@ -1536,6 +1584,7 @@ function Dropdown({
1536
1584
  setPanelStyle((previous) => Object.entries(nextStyle).every(([key, value]) => previous[key] === value) ? previous : nextStyle);
1537
1585
  };
1538
1586
  updatePosition();
1587
+ if (searchable && !panel.contains(document.activeElement)) searchRef.current?.focus({ preventScroll: true });
1539
1588
  if (focusOnOpen.current) {
1540
1589
  focusOnOpen.current = false;
1541
1590
  const option = panel.querySelector('[aria-selected="true"]') ?? panel.querySelector('[role="option"]');
@@ -1559,7 +1608,7 @@ function Dropdown({
1559
1608
  window.visualViewport?.removeEventListener("resize", updatePosition);
1560
1609
  window.visualViewport?.removeEventListener("scroll", updatePosition);
1561
1610
  };
1562
- }, [open, direction, align, maxHeight, collisionPadding, items, label]);
1611
+ }, [open, direction, align, maxHeight, collisionPadding, items, label, query, searchable]);
1563
1612
  React11.useEffect(() => {
1564
1613
  if (!open) return;
1565
1614
  const handleClickOutside = (e) => {
@@ -1570,19 +1619,19 @@ function Dropdown({
1570
1619
  document.addEventListener("mousedown", handleClickOutside);
1571
1620
  return () => document.removeEventListener("mousedown", handleClickOutside);
1572
1621
  }, [open]);
1573
- if (visibleItems.length === 0) return null;
1574
- return /* @__PURE__ */ jsxs16("div", { ref: rootRef, "data-control-size": size, className: cn("fractal-dropdown", className), children: [
1575
- /* @__PURE__ */ jsxs16(
1622
+ if (renderableItems.length === 0) return null;
1623
+ return /* @__PURE__ */ jsxs17("div", { ref: rootRef, "data-control-size": size, "data-filled": multiple ? selectedValues.length > 0 : Boolean(selectedValue), "data-open": open, className: cn("fractal-dropdown", fieldLabel && "fractal-floating-field fractal-floating-field--dropdown", className), children: [
1624
+ /* @__PURE__ */ jsxs17(
1576
1625
  "button",
1577
1626
  {
1578
1627
  ref: triggerRef,
1579
- id: triggerId,
1628
+ id: triggerId ?? `${menuId}-trigger`,
1580
1629
  "data-control-size": size,
1581
1630
  type: "button",
1582
1631
  disabled,
1583
- "aria-haspopup": "listbox",
1632
+ "aria-haspopup": searchable ? "dialog" : "listbox",
1584
1633
  "aria-expanded": open,
1585
- "aria-controls": open ? menuId : void 0,
1634
+ "aria-controls": open ? searchable ? menuId : `${menuId}-options` : void 0,
1586
1635
  onKeyDown: (event) => {
1587
1636
  if (event.key === "ArrowDown" || event.key === "ArrowUp") {
1588
1637
  event.preventDefault();
@@ -1596,7 +1645,7 @@ function Dropdown({
1596
1645
  }
1597
1646
  }
1598
1647
  },
1599
- "aria-label": triggerLabel,
1648
+ "aria-label": accessibleLabel,
1600
1649
  onClick: () => setOpen((o) => !o),
1601
1650
  className: cn(
1602
1651
  "fractal-control",
@@ -1608,20 +1657,22 @@ function Dropdown({
1608
1657
  triggerClassName
1609
1658
  ),
1610
1659
  children: [
1611
- triggerContent != null ? triggerContent : /* @__PURE__ */ jsxs16(Fragment2, { children: [
1612
- selected.icon != null && /* @__PURE__ */ jsx19("span", { className: "fractal-dropdown-icon fractal-dropdown-icon--trigger", children: selected.icon }),
1613
- selected.description != null && (typeof selected.description !== "string" || selected.description !== "") && /* @__PURE__ */ jsx19("span", { className: "fractal-dropdown-selected-text", children: selected.description })
1614
- ] }),
1660
+ /* @__PURE__ */ jsx19("span", { className: fieldLabel ? "fractal-dropdown-field-value" : void 0, style: fieldLabel ? void 0 : { display: "contents" }, children: triggerContent != null ? triggerContent : /* @__PURE__ */ jsxs17(Fragment2, { children: [
1661
+ selected?.icon != null && /* @__PURE__ */ jsx19("span", { className: "fractal-dropdown-icon fractal-dropdown-icon--trigger", children: selected?.icon }),
1662
+ selected?.description != null && (typeof selected?.description !== "string" || selected?.description !== "") && /* @__PURE__ */ jsx19("span", { className: "fractal-dropdown-selected-text", children: selected?.description })
1663
+ ] }) }),
1615
1664
  !noChevron && !iconOnly && /* @__PURE__ */ jsx19("span", { className: "fractal-dropdown-chevron", "aria-hidden": true, children: /* @__PURE__ */ jsx19(ChevronIcon, { size: size === "sm" ? 14 : 16 }) })
1616
1665
  ]
1617
1666
  }
1618
1667
  ),
1619
- open && /* @__PURE__ */ jsxs16(
1668
+ fieldLabel ? /* @__PURE__ */ jsx19("label", { className: "fractal-floating-field__label", htmlFor: triggerId ?? `${menuId}-trigger`, children: fieldLabel }) : null,
1669
+ open && /* @__PURE__ */ jsxs17(
1620
1670
  "div",
1621
1671
  {
1622
1672
  ref: panelRef,
1623
1673
  id: menuId,
1624
1674
  onKeyDown: (event) => {
1675
+ if (event.target === searchRef.current && event.key !== "ArrowDown") return;
1625
1676
  if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) return;
1626
1677
  event.preventDefault();
1627
1678
  const options = Array.from(panelRef.current?.querySelectorAll('[role="option"]') ?? []);
@@ -1630,49 +1681,58 @@ function Dropdown({
1630
1681
  options[index]?.focus({ preventScroll: true });
1631
1682
  options[index]?.scrollIntoView({ block: "nearest" });
1632
1683
  },
1633
- role: "listbox",
1634
- "aria-label": triggerLabel,
1684
+ role: searchable ? "dialog" : void 0,
1685
+ "aria-label": accessibleLabel,
1635
1686
  className: cn("fractal-dropdown-panel", `fractal-dropdown-panel--${size}`, panelClassName),
1636
1687
  style: panelStyle,
1637
1688
  children: [
1638
- label != null && /* @__PURE__ */ jsx19("div", { className: "fractal-dropdown-label", children: label }),
1639
- visibleItems.map((item, index) => {
1640
- const topDivider = item.border === "top" ? /* @__PURE__ */ jsx19("div", { className: "fractal-dropdown-separator" }) : null;
1641
- const bottomDivider = item.border === "bottom" ? /* @__PURE__ */ jsx19("div", { className: "fractal-dropdown-separator" }) : null;
1642
- if (item.kind === "header") {
1643
- return /* @__PURE__ */ jsxs16(React11.Fragment, { children: [
1689
+ searchable && /* @__PURE__ */ jsxs17("div", { className: "fractal-dropdown-search", children: [
1690
+ /* @__PURE__ */ jsx19(MagnifyingGlass2, { "aria-hidden": "true" }),
1691
+ /* @__PURE__ */ jsx19("input", { ref: searchRef, type: "search", "aria-label": searchPlaceholder, placeholder: searchPlaceholder, value: query, onChange: (event) => setQuery(event.target.value) })
1692
+ ] }),
1693
+ /* @__PURE__ */ jsxs17("div", { role: "listbox", id: `${menuId}-options`, "aria-label": accessibleLabel, "aria-multiselectable": multiple || void 0, children: [
1694
+ label != null && /* @__PURE__ */ jsx19("div", { className: "fractal-dropdown-label", children: label }),
1695
+ visibleItems.map((item, index) => {
1696
+ const topDivider = item.border === "top" ? /* @__PURE__ */ jsx19("div", { className: "fractal-dropdown-separator" }) : null;
1697
+ const bottomDivider = item.border === "bottom" ? /* @__PURE__ */ jsx19("div", { className: "fractal-dropdown-separator" }) : null;
1698
+ if (item.kind === "header") {
1699
+ return /* @__PURE__ */ jsxs17(React11.Fragment, { children: [
1700
+ topDivider,
1701
+ /* @__PURE__ */ jsx19("div", { role: "presentation", className: "fractal-dropdown-label", children: item.description }),
1702
+ bottomDivider
1703
+ ] }, `header-${index}`);
1704
+ }
1705
+ const isSelected = multiple ? selectedValues.includes(item.value) : item.value === selectedValue;
1706
+ return /* @__PURE__ */ jsxs17(React11.Fragment, { children: [
1644
1707
  topDivider,
1645
- /* @__PURE__ */ jsx19("div", { role: "presentation", className: "fractal-dropdown-label", children: item.description }),
1708
+ /* @__PURE__ */ jsxs17(
1709
+ "button",
1710
+ {
1711
+ type: "button",
1712
+ role: "option",
1713
+ "aria-selected": isSelected,
1714
+ onClick: () => {
1715
+ if (multiple) onSelectionChange?.(isSelected ? selectedValues.filter((value) => value !== item.value) : [...selectedValues, item.value]);
1716
+ else onSelect?.(item.value);
1717
+ if (!multiple && closeOnSelect) {
1718
+ setOpen(false);
1719
+ triggerRef.current?.focus();
1720
+ }
1721
+ },
1722
+ className: "fractal-dropdown-option",
1723
+ children: [
1724
+ multiple && /* @__PURE__ */ jsx19("span", { className: "fractal-dropdown-checkbox", "data-checked": isSelected, "aria-hidden": "true", children: isSelected && /* @__PURE__ */ jsx19(Check2, {}) }),
1725
+ item.icon != null && /* @__PURE__ */ jsx19("span", { className: "fractal-dropdown-icon", children: item.icon }),
1726
+ item.description != null && (typeof item.description !== "string" || item.description !== "") && /* @__PURE__ */ jsx19("span", { className: "fractal-dropdown-option-text", children: item.description }),
1727
+ item.trailing != null && /* @__PURE__ */ jsx19("span", { className: "fractal-dropdown-trailing", children: item.trailing })
1728
+ ]
1729
+ }
1730
+ ),
1646
1731
  bottomDivider
1647
- ] }, `header-${index}`);
1648
- }
1649
- const isSelected = item.value === selectedValue;
1650
- return /* @__PURE__ */ jsxs16(React11.Fragment, { children: [
1651
- topDivider,
1652
- /* @__PURE__ */ jsxs16(
1653
- "button",
1654
- {
1655
- type: "button",
1656
- role: "option",
1657
- "aria-selected": isSelected,
1658
- onClick: () => {
1659
- onSelect(item.value);
1660
- if (closeOnSelect) {
1661
- setOpen(false);
1662
- triggerRef.current?.focus();
1663
- }
1664
- },
1665
- className: "fractal-dropdown-option",
1666
- children: [
1667
- item.icon != null && /* @__PURE__ */ jsx19("span", { className: "fractal-dropdown-icon", children: item.icon }),
1668
- item.description != null && (typeof item.description !== "string" || item.description !== "") && /* @__PURE__ */ jsx19("span", { className: "fractal-dropdown-option-text", children: item.description }),
1669
- item.trailing != null && /* @__PURE__ */ jsx19("span", { className: "fractal-dropdown-trailing", children: item.trailing })
1670
- ]
1671
- }
1672
- ),
1673
- bottomDivider
1674
- ] }, item.value);
1675
- })
1732
+ ] }, item.value);
1733
+ })
1734
+ ] }),
1735
+ !selectableItems.length && /* @__PURE__ */ jsx19("p", { role: "status", className: "fractal-dropdown-label", children: emptyMessage })
1676
1736
  ]
1677
1737
  }
1678
1738
  )
@@ -1711,7 +1771,7 @@ Chip.displayName = "Chip";
1711
1771
 
1712
1772
  // src/components/Checkbox/Checkbox.tsx
1713
1773
  import { Checkbox as CheckboxIcon, CheckboxChecked, Minus as Minus2 } from "@mirror-physics/fractal-icons";
1714
- import { jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
1774
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
1715
1775
  function Checkbox({
1716
1776
  checked,
1717
1777
  indeterminate = false,
@@ -1744,7 +1804,7 @@ function Checkbox({
1744
1804
  onKeyDown?.(event);
1745
1805
  if (event.key === " " || event.key === "Enter") event.stopPropagation();
1746
1806
  },
1747
- children: indeterminate ? /* @__PURE__ */ jsxs17("span", { className: "fractal-checkbox__indeterminate-icon", "aria-hidden": "true", children: [
1807
+ children: indeterminate ? /* @__PURE__ */ jsxs18("span", { className: "fractal-checkbox__indeterminate-icon", "aria-hidden": "true", children: [
1748
1808
  /* @__PURE__ */ jsx22(CheckboxIcon, { size: 18 }),
1749
1809
  /* @__PURE__ */ jsx22(Minus2, { className: "fractal-checkbox__indeterminate-mark", size: 12 })
1750
1810
  ] }) : checked ? /* @__PURE__ */ jsx22(CheckboxChecked, { "aria-hidden": "true", size: 18 }) : /* @__PURE__ */ jsx22(CheckboxIcon, { "aria-hidden": "true", size: 18 })
@@ -1753,7 +1813,7 @@ function Checkbox({
1753
1813
  }
1754
1814
 
1755
1815
  // src/components/Radio/Radio.tsx
1756
- import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
1816
+ import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
1757
1817
  function Radio({
1758
1818
  checked,
1759
1819
  className,
@@ -1763,7 +1823,7 @@ function Radio({
1763
1823
  onCheckedChange,
1764
1824
  ...props
1765
1825
  }) {
1766
- return /* @__PURE__ */ jsxs18("label", { className: cn("fractal-radio", disabled && "fractal-radio--disabled", className), children: [
1826
+ return /* @__PURE__ */ jsxs19("label", { className: cn("fractal-radio", disabled && "fractal-radio--disabled", className), children: [
1767
1827
  /* @__PURE__ */ jsx23(
1768
1828
  "input",
1769
1829
  {
@@ -1776,7 +1836,7 @@ function Radio({
1776
1836
  }
1777
1837
  ),
1778
1838
  /* @__PURE__ */ jsx23("span", { "aria-hidden": "true", className: "fractal-radio__control", children: /* @__PURE__ */ jsx23("span", { className: "fractal-radio__dot" }) }),
1779
- /* @__PURE__ */ jsxs18("span", { className: "fractal-radio__content", children: [
1839
+ /* @__PURE__ */ jsxs19("span", { className: "fractal-radio__content", children: [
1780
1840
  /* @__PURE__ */ jsx23("span", { className: "fractal-radio__label", children: label }),
1781
1841
  description && /* @__PURE__ */ jsx23("span", { className: "fractal-radio__description", children: description })
1782
1842
  ] })
@@ -1786,7 +1846,7 @@ function Radio({
1786
1846
  // src/components/SortableTable/SortableTable.tsx
1787
1847
  import { useMemo as useMemo2, useState as useState8 } from "react";
1788
1848
  import { ArrowUp, ArrowDown, ArrowsUpDown } from "@mirror-physics/fractal-icons";
1789
- import { jsx as jsx24, jsxs as jsxs19 } from "react/jsx-runtime";
1849
+ import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
1790
1850
  function SortableTable({
1791
1851
  columns,
1792
1852
  data,
@@ -1886,10 +1946,10 @@ function SortableTable({
1886
1946
  onSortChange?.(nextKey, nextDirection);
1887
1947
  }
1888
1948
  };
1889
- return /* @__PURE__ */ jsx24("div", { className: cn("fractal-table-layout", "fractal-sortable-table", `fractal-sortable-table--${size}`, embedded && "fractal-sortable-table--embedded", className), "data-overflow-menu": Boolean(overflowMenu), "data-table-layout": layout, "data-sticky-first": stickyFirstColumn, "data-sticky-header": stickyHeader, "data-table-selection": Boolean(selection), children: /* @__PURE__ */ jsxs19("div", { className: "fractal-sortable-table-surface", children: [
1949
+ return /* @__PURE__ */ jsx24("div", { className: cn("fractal-table-layout", "fractal-sortable-table", `fractal-sortable-table--${size}`, embedded && "fractal-sortable-table--embedded", className), "data-overflow-menu": Boolean(overflowMenu), "data-table-layout": layout, "data-sticky-first": stickyFirstColumn, "data-sticky-header": stickyHeader, "data-table-selection": Boolean(selection), children: /* @__PURE__ */ jsxs20("div", { className: "fractal-sortable-table-surface", children: [
1890
1950
  header && /* @__PURE__ */ jsx24("div", { className: "fractal-sortable-table-header", children: header }),
1891
- visibleRows.length === 0 ? /* @__PURE__ */ jsx24("div", { className: "fractal-sortable-table-empty", children: emptyMessage || "No data" }) : /* @__PURE__ */ jsx24(TableViewport, { maxHeight, label: ariaLabel || "Data table", children: /* @__PURE__ */ jsxs19("table", { "aria-label": ariaLabel, className: "fractal-sortable-table-table", children: [
1892
- /* @__PURE__ */ jsx24("thead", { children: /* @__PURE__ */ jsxs19("tr", { className: "fractal-sortable-table-thead-row", children: [
1951
+ visibleRows.length === 0 ? /* @__PURE__ */ jsx24("div", { className: "fractal-sortable-table-empty", children: emptyMessage || "No data" }) : /* @__PURE__ */ jsx24(TableViewport, { maxHeight, label: ariaLabel || "Data table", children: /* @__PURE__ */ jsxs20("table", { "aria-label": ariaLabel, className: "fractal-sortable-table-table", children: [
1952
+ /* @__PURE__ */ jsx24("thead", { children: /* @__PURE__ */ jsxs20("tr", { className: "fractal-sortable-table-thead-row", children: [
1893
1953
  selection && /* @__PURE__ */ jsx24(
1894
1954
  "th",
1895
1955
  {
@@ -1941,7 +2001,7 @@ function SortableTable({
1941
2001
  scope: "col",
1942
2002
  style: columnStyle(col),
1943
2003
  "data-pinned-column": columnIndex === 0 ? "data" : void 0,
1944
- children: /* @__PURE__ */ jsx24(TableCellContent, { label: `${col.header} column`, children: /* @__PURE__ */ jsxs19(
2004
+ children: /* @__PURE__ */ jsx24(TableCellContent, { label: `${col.header} column`, children: /* @__PURE__ */ jsxs20(
1945
2005
  "button",
1946
2006
  {
1947
2007
  type: "button",
@@ -1972,7 +2032,7 @@ function SortableTable({
1972
2032
  label: rowAction.label(row, rowIndex),
1973
2033
  icon: rowAction.icon(row, rowIndex)
1974
2034
  } : null;
1975
- return /* @__PURE__ */ jsxs19(
2035
+ return /* @__PURE__ */ jsxs20(
1976
2036
  "tr",
1977
2037
  {
1978
2038
  className: cn(
@@ -2008,7 +2068,7 @@ function SortableTable({
2008
2068
  }
2009
2069
  }
2010
2070
  ) }),
2011
- columns.map((col, columnIndex) => /* @__PURE__ */ jsxs19(
2071
+ columns.map((col, columnIndex) => /* @__PURE__ */ jsxs20(
2012
2072
  "td",
2013
2073
  {
2014
2074
  className: cn(
@@ -2046,8 +2106,8 @@ function SortableTable({
2046
2106
  }
2047
2107
 
2048
2108
  // src/components/Tabs/Tabs.tsx
2049
- import { useId as useId4, useLayoutEffect as useLayoutEffect4, useRef as useRef8, useState as useState9 } from "react";
2050
- import { jsx as jsx25, jsxs as jsxs20 } from "react/jsx-runtime";
2109
+ import { useId as useId5, useLayoutEffect as useLayoutEffect4, useRef as useRef8, useState as useState9 } from "react";
2110
+ import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
2051
2111
  function Tabs({
2052
2112
  items,
2053
2113
  defaultValue,
@@ -2058,7 +2118,7 @@ function Tabs({
2058
2118
  divider = false,
2059
2119
  variant = "line"
2060
2120
  }) {
2061
- const reactId = useId4();
2121
+ const reactId = useId5();
2062
2122
  const [internalValue, setInternalValue] = useState9(
2063
2123
  defaultValue ?? items.find((i) => !i.disabled)?.id ?? items[0]?.id ?? ""
2064
2124
  );
@@ -2118,7 +2178,7 @@ function Tabs({
2118
2178
  selectTab(nextId2);
2119
2179
  requestAnimationFrame(() => tabRefs.current[nextId2]?.focus());
2120
2180
  };
2121
- return /* @__PURE__ */ jsxs20("div", { className: cn("fractal-tabs", `fractal-tabs--${variant}`, divider && "fractal-tabs--divider", className), children: [
2181
+ return /* @__PURE__ */ jsxs21("div", { className: cn("fractal-tabs", `fractal-tabs--${variant}`, divider && "fractal-tabs--divider", className), children: [
2122
2182
  /* @__PURE__ */ jsx25(
2123
2183
  "div",
2124
2184
  {
@@ -2181,7 +2241,7 @@ function Tabs({
2181
2241
 
2182
2242
  // src/components/ContentSwitcher/ContentSwitcher.tsx
2183
2243
  import * as React14 from "react";
2184
- import { jsx as jsx26, jsxs as jsxs21 } from "react/jsx-runtime";
2244
+ import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
2185
2245
  function ContentSwitcher({ items, value, onValueChange, ariaLabel, fullWidth = false, className }) {
2186
2246
  const switcherRef = React14.useRef(null);
2187
2247
  const buttonRefs = React14.useRef([]);
@@ -2239,7 +2299,7 @@ function ContentSwitcher({ items, value, onValueChange, ariaLabel, fullWidth = f
2239
2299
  onValueChange(items[nextIndex].value);
2240
2300
  }
2241
2301
  };
2242
- return /* @__PURE__ */ jsxs21(
2302
+ return /* @__PURE__ */ jsxs22(
2243
2303
  "div",
2244
2304
  {
2245
2305
  className: cn("fractal-content-switcher", fullWidth && "fractal-content-switcher--full-width", className),
@@ -2282,9 +2342,9 @@ function ContentSwitcher({ items, value, onValueChange, ariaLabel, fullWidth = f
2282
2342
  }
2283
2343
 
2284
2344
  // src/components/Disclosure/Disclosure.tsx
2285
- import { useId as useId5, useState as useState10 } from "react";
2345
+ import { useId as useId6, useState as useState10 } from "react";
2286
2346
  import { ChevronRight as ChevronRight3, ChevronDown as ChevronDown2 } from "@mirror-physics/fractal-icons";
2287
- import { jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
2347
+ import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
2288
2348
  function Disclosure({
2289
2349
  title,
2290
2350
  meta,
@@ -2296,7 +2356,7 @@ function Disclosure({
2296
2356
  className,
2297
2357
  variant = "card"
2298
2358
  }) {
2299
- const reactId = useId5();
2359
+ const reactId = useId6();
2300
2360
  const headerId = `${reactId}-header`;
2301
2361
  const panelId = `${reactId}-panel`;
2302
2362
  const [internalOpen, setInternalOpen] = useState10(defaultOpen);
@@ -2312,7 +2372,7 @@ function Disclosure({
2312
2372
  onOpenChange?.(next);
2313
2373
  }
2314
2374
  };
2315
- return /* @__PURE__ */ jsxs22(
2375
+ return /* @__PURE__ */ jsxs23(
2316
2376
  "div",
2317
2377
  {
2318
2378
  className: cn(
@@ -2323,7 +2383,7 @@ function Disclosure({
2323
2383
  className
2324
2384
  ),
2325
2385
  children: [
2326
- /* @__PURE__ */ jsxs22(
2386
+ /* @__PURE__ */ jsxs23(
2327
2387
  "button",
2328
2388
  {
2329
2389
  type: "button",
@@ -2382,7 +2442,7 @@ function LatticeLoader({ className, label = "Loading", ...props }) {
2382
2442
  }
2383
2443
 
2384
2444
  // src/components/Ghost/Ghost.tsx
2385
- import { jsx as jsx29, jsxs as jsxs23 } from "react/jsx-runtime";
2445
+ import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
2386
2446
  var toCssLength = (value) => typeof value === "number" ? `${value}px` : value;
2387
2447
  function Ghost({ className, width, height, radius, style, ...props }) {
2388
2448
  return /* @__PURE__ */ jsx29(
@@ -2403,11 +2463,11 @@ function Ghost({ className, width, height, radius, style, ...props }) {
2403
2463
  function GhostLine({ className, size = "md", width = "100%", ...props }) {
2404
2464
  return /* @__PURE__ */ jsx29(Ghost, { className: cn("fractal-ghost-line", `fractal-ghost-line--${size}`, className), width, ...props });
2405
2465
  }
2406
- function ButtonGhost({ className, size = "md", controlSize, iconOnly = false, width, ...props }) {
2466
+ function ButtonGhost({ className, size = "lg", controlSize, iconOnly = false, width, ...props }) {
2407
2467
  return /* @__PURE__ */ jsx29(Ghost, { "data-control-size": controlSize ?? size, className: cn("fractal-ghost-button", `fractal-ghost-button--${size}`, iconOnly && "fractal-ghost-button--icon-only", className), width, ...props });
2408
2468
  }
2409
2469
  function CardGhost({ className, lines = 3, showHeader = true, ...props }) {
2410
- return /* @__PURE__ */ jsxs23("div", { "aria-hidden": "true", className: cn("fractal-ghost-card", className), ...props, children: [
2470
+ return /* @__PURE__ */ jsxs24("div", { "aria-hidden": "true", className: cn("fractal-ghost-card", className), ...props, children: [
2411
2471
  showHeader && /* @__PURE__ */ jsx29(GhostLine, { width: "38%" }),
2412
2472
  /* @__PURE__ */ jsx29("div", { className: "fractal-ghost-stack", children: Array.from({ length: lines }, (_, index) => /* @__PURE__ */ jsx29(GhostLine, { width: index === lines - 1 ? "62%" : "100%" }, index)) })
2413
2473
  ] });
@@ -2423,7 +2483,7 @@ function DataTableGhost({
2423
2483
  ...props
2424
2484
  }) {
2425
2485
  const cells = Array.from({ length: columns }, (_, index) => index);
2426
- return /* @__PURE__ */ jsx29("div", { "aria-busy": "true", "aria-label": "Loading table", className: cn("fractal-ghost-table", `fractal-ghost-table--${size}`, className), role: "status", ...props, children: /* @__PURE__ */ jsxs23("table", { className: "fractal-ghost-table__table", children: [
2486
+ return /* @__PURE__ */ jsx29("div", { "aria-busy": "true", "aria-label": "Loading table", className: cn("fractal-ghost-table", `fractal-ghost-table--${size}`, className), role: "status", ...props, children: /* @__PURE__ */ jsxs24("table", { className: "fractal-ghost-table__table", children: [
2427
2487
  (showHeader || headers) && /* @__PURE__ */ jsx29("thead", { children: /* @__PURE__ */ jsx29("tr", { className: "fractal-ghost-table__head-row", children: cells.map((index) => /* @__PURE__ */ jsx29("th", { style: { width: columnWidths?.[index] }, children: headers?.[index] ?? /* @__PURE__ */ jsx29(GhostLine, { size: "sm", width: index === columns - 1 ? "62%" : "76%" }) }, index)) }) }),
2428
2488
  /* @__PURE__ */ jsx29("tbody", { children: Array.from({ length: rows }, (_, rowIndex) => /* @__PURE__ */ jsx29("tr", { className: "fractal-ghost-table__row", children: cells.map((columnIndex) => /* @__PURE__ */ jsx29("td", { style: { width: columnWidths?.[columnIndex] }, children: /* @__PURE__ */ jsx29(GhostLine, { width: `${[72, 54, 82, 63, 46][(rowIndex + columnIndex) % 5]}%` }) }, columnIndex)) }, rowIndex)) })
2429
2489
  ] }) });
@@ -2437,20 +2497,20 @@ function TextareaGhost({ className, labelWidth = "26%", ...props }) {
2437
2497
  function LabelGhost({ className, width = "26%", ...props }) {
2438
2498
  return /* @__PURE__ */ jsx29(GhostLine, { className: cn("fractal-ghost-label", className), size: "sm", width, ...props });
2439
2499
  }
2440
- function FormFieldGhost({ className, labelWidth = "26%", multiline = false, controlSize = "md", ...props }) {
2441
- return /* @__PURE__ */ jsxs23("div", { "aria-hidden": "true", "data-control-size": controlSize, className: cn("fractal-ghost-field", className), ...props, children: [
2500
+ function FormFieldGhost({ className, labelWidth = "26%", multiline = false, controlSize = "lg", ...props }) {
2501
+ return /* @__PURE__ */ jsxs24("div", { "aria-hidden": "true", "data-control-size": controlSize, className: cn("fractal-ghost-field", className), ...props, children: [
2442
2502
  /* @__PURE__ */ jsx29(LabelGhost, { width: labelWidth }),
2443
2503
  /* @__PURE__ */ jsx29(Ghost, { className: cn("fractal-ghost-field__control", multiline && "fractal-ghost-field__control--multiline") })
2444
2504
  ] });
2445
2505
  }
2446
2506
  function AlertGhost({ className, ...props }) {
2447
- return /* @__PURE__ */ jsxs23("div", { "aria-hidden": "true", className: cn("fractal-ghost-alert", className), ...props, children: [
2507
+ return /* @__PURE__ */ jsxs24("div", { "aria-hidden": "true", className: cn("fractal-ghost-alert", className), ...props, children: [
2448
2508
  /* @__PURE__ */ jsx29(GhostLine, { width: "30%" }),
2449
2509
  /* @__PURE__ */ jsx29(GhostLine, { size: "sm", width: "78%" })
2450
2510
  ] });
2451
2511
  }
2452
2512
  function CheckboxGhost({ className, ...props }) {
2453
- return /* @__PURE__ */ jsxs23("div", { "aria-hidden": "true", className: cn("fractal-ghost-choice", className), ...props, children: [
2513
+ return /* @__PURE__ */ jsxs24("div", { "aria-hidden": "true", className: cn("fractal-ghost-choice", className), ...props, children: [
2454
2514
  /* @__PURE__ */ jsx29(Ghost, { className: "fractal-ghost-choice__control" }),
2455
2515
  /* @__PURE__ */ jsx29(GhostLine, { width: "42%" })
2456
2516
  ] });
@@ -2463,8 +2523,8 @@ function LinkGhost({ className, width = 96, ...props }) {
2463
2523
  return /* @__PURE__ */ jsx29(GhostLine, { className: cn("fractal-ghost-link", className), size: "sm", width, ...props });
2464
2524
  }
2465
2525
  var TextButtonGhost = LinkGhost;
2466
- function DropdownGhost({ className, controlSize = "md", ...props }) {
2467
- return /* @__PURE__ */ jsxs23("div", { "aria-hidden": "true", "data-control-size": controlSize, className: cn("fractal-ghost-dropdown", className), ...props, children: [
2526
+ function DropdownGhost({ className, controlSize = "lg", ...props }) {
2527
+ return /* @__PURE__ */ jsxs24("div", { "aria-hidden": "true", "data-control-size": controlSize, className: cn("fractal-ghost-dropdown", className), ...props, children: [
2468
2528
  /* @__PURE__ */ jsx29(GhostLine, { width: "38%" }),
2469
2529
  /* @__PURE__ */ jsx29(Ghost, { className: "fractal-ghost-dropdown__chevron" })
2470
2530
  ] });
@@ -2474,7 +2534,7 @@ function ContentSwitcherGhost({ className, options = 3, ...props }) {
2474
2534
  }
2475
2535
  var TabsGhost = ContentSwitcherGhost;
2476
2536
  function DisclosureGhost({ className, ...props }) {
2477
- return /* @__PURE__ */ jsxs23("div", { "aria-hidden": "true", className: cn("fractal-ghost-disclosure", className), ...props, children: [
2537
+ return /* @__PURE__ */ jsxs24("div", { "aria-hidden": "true", className: cn("fractal-ghost-disclosure", className), ...props, children: [
2478
2538
  /* @__PURE__ */ jsx29(Ghost, { className: "fractal-ghost-disclosure__icon" }),
2479
2539
  /* @__PURE__ */ jsx29(GhostLine, { width: "42%" })
2480
2540
  ] });
@@ -2483,7 +2543,7 @@ function PaginationGhost({ className, pages = 5, ...props }) {
2483
2543
  return /* @__PURE__ */ jsx29("div", { "aria-hidden": "true", className: cn("fractal-ghost-pagination", className), ...props, children: Array.from({ length: pages }, (_, index) => /* @__PURE__ */ jsx29(Ghost, {}, index)) });
2484
2544
  }
2485
2545
  function FileDropzoneGhost({ className, ...props }) {
2486
- return /* @__PURE__ */ jsxs23("div", { "aria-hidden": "true", className: cn("fractal-ghost-dropzone", className), ...props, children: [
2546
+ return /* @__PURE__ */ jsxs24("div", { "aria-hidden": "true", className: cn("fractal-ghost-dropzone", className), ...props, children: [
2487
2547
  /* @__PURE__ */ jsx29(Ghost, { className: "fractal-ghost-dropzone__icon" }),
2488
2548
  /* @__PURE__ */ jsx29(GhostLine, { width: "26%" }),
2489
2549
  /* @__PURE__ */ jsx29(GhostLine, { size: "sm", width: "46%" })
@@ -2497,7 +2557,7 @@ function ConversationGhost({
2497
2557
  "aria-label": ariaLabel = "Loading conversation",
2498
2558
  ...props
2499
2559
  }) {
2500
- return /* @__PURE__ */ jsxs23(
2560
+ return /* @__PURE__ */ jsxs24(
2501
2561
  "div",
2502
2562
  {
2503
2563
  "aria-busy": "true",
@@ -2506,12 +2566,12 @@ function ConversationGhost({
2506
2566
  role: "status",
2507
2567
  ...props,
2508
2568
  children: [
2509
- /* @__PURE__ */ jsx29("div", { "aria-hidden": "true", className: "fractal-ghost-conversation__message fractal-ghost-conversation__message--user", children: /* @__PURE__ */ jsxs23("div", { className: "fractal-ghost-conversation__bubble", children: [
2569
+ /* @__PURE__ */ jsx29("div", { "aria-hidden": "true", className: "fractal-ghost-conversation__message fractal-ghost-conversation__message--user", children: /* @__PURE__ */ jsxs24("div", { className: "fractal-ghost-conversation__bubble", children: [
2510
2570
  /* @__PURE__ */ jsx29(GhostLine, { width: "100%" }),
2511
2571
  /* @__PURE__ */ jsx29(GhostLine, { width: "86%" }),
2512
2572
  /* @__PURE__ */ jsx29(GhostLine, { width: "64%" })
2513
2573
  ] }) }),
2514
- /* @__PURE__ */ jsxs23("div", { "aria-hidden": "true", className: "fractal-ghost-conversation__message fractal-ghost-conversation__message--assistant", children: [
2574
+ /* @__PURE__ */ jsxs24("div", { "aria-hidden": "true", className: "fractal-ghost-conversation__message fractal-ghost-conversation__message--assistant", children: [
2515
2575
  /* @__PURE__ */ jsx29(GhostLine, { width: "92%" }),
2516
2576
  /* @__PURE__ */ jsx29(GhostLine, { width: "78%" }),
2517
2577
  /* @__PURE__ */ jsx29(GhostLine, { width: "58%" })
@@ -2524,9 +2584,9 @@ function SortableTableGhost(props) {
2524
2584
  return /* @__PURE__ */ jsx29(DataTableGhost, { ...props });
2525
2585
  }
2526
2586
  function SidebarGhost({ className, items = 6, ...props }) {
2527
- return /* @__PURE__ */ jsxs23("aside", { "aria-hidden": "true", className: cn("fractal-ghost-sidebar", className), ...props, children: [
2587
+ return /* @__PURE__ */ jsxs24("aside", { "aria-hidden": "true", className: cn("fractal-ghost-sidebar", className), ...props, children: [
2528
2588
  /* @__PURE__ */ jsx29(Ghost, { className: "fractal-ghost-sidebar__brand" }),
2529
- /* @__PURE__ */ jsx29("div", { className: "fractal-ghost-sidebar__items", children: Array.from({ length: items }, (_, index) => /* @__PURE__ */ jsxs23("div", { className: "fractal-ghost-sidebar__item", children: [
2589
+ /* @__PURE__ */ jsx29("div", { className: "fractal-ghost-sidebar__items", children: Array.from({ length: items }, (_, index) => /* @__PURE__ */ jsxs24("div", { className: "fractal-ghost-sidebar__item", children: [
2530
2590
  /* @__PURE__ */ jsx29(Ghost, {}),
2531
2591
  /* @__PURE__ */ jsx29(GhostLine, { width: `${[54, 68, 44, 61][index % 4]}%` })
2532
2592
  ] }, index)) })
@@ -2539,8 +2599,8 @@ function SidePanelGhost({ className, title, lines = 5, ...props }) {
2539
2599
  return /* @__PURE__ */ jsx29(SurfaceGhost, { className: cn("fractal-ghost-side-panel", className), title, lines, ...props });
2540
2600
  }
2541
2601
  function SurfaceGhost({ className, title, lines = 3, ...props }) {
2542
- return /* @__PURE__ */ jsxs23("div", { "aria-hidden": "true", className: cn("fractal-ghost-surface", className), ...props, children: [
2543
- /* @__PURE__ */ jsxs23("div", { className: "fractal-ghost-surface__header", children: [
2602
+ return /* @__PURE__ */ jsxs24("div", { "aria-hidden": "true", className: cn("fractal-ghost-surface", className), ...props, children: [
2603
+ /* @__PURE__ */ jsxs24("div", { className: "fractal-ghost-surface__header", children: [
2544
2604
  /* @__PURE__ */ jsx29(GhostLine, { width: "42%" }),
2545
2605
  /* @__PURE__ */ jsx29(Ghost, { className: "fractal-ghost-surface__close" })
2546
2606
  ] }),
@@ -2551,7 +2611,7 @@ function SurfaceGhost({ className, title, lines = 3, ...props }) {
2551
2611
 
2552
2612
  // src/components/Sidebar/Sidebar.tsx
2553
2613
  import * as React15 from "react";
2554
- import { Fragment as Fragment3, jsx as jsx30, jsxs as jsxs24 } from "react/jsx-runtime";
2614
+ import { Fragment as Fragment3, jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
2555
2615
  var Sidebar = React15.forwardRef(
2556
2616
  ({ className, width, compact = false, style, ...props }, ref) => /* @__PURE__ */ jsx30(
2557
2617
  "aside",
@@ -2591,7 +2651,7 @@ function SidebarAccountMenu({
2591
2651
  panelClassName: "fractal-sidebar__account-panel",
2592
2652
  selectedValue: "",
2593
2653
  triggerClassName: "fractal-sidebar__account-trigger",
2594
- triggerContent: /* @__PURE__ */ jsxs24(Fragment3, { children: [
2654
+ triggerContent: /* @__PURE__ */ jsxs25(Fragment3, { children: [
2595
2655
  icon && /* @__PURE__ */ jsx30("span", { className: "fractal-sidebar__account-icon", "aria-hidden": "true", children: icon }),
2596
2656
  /* @__PURE__ */ jsx30("span", { className: "fractal-sidebar__account-name", children: name })
2597
2657
  ] }),
@@ -2609,7 +2669,7 @@ var SidebarSection = React15.forwardRef(
2609
2669
  );
2610
2670
  SidebarSection.displayName = "SidebarSection";
2611
2671
  var SidebarNavItem = React15.forwardRef(
2612
- ({ active = false, icon, endAdornment, className, type = "button", children, ...props }, ref) => /* @__PURE__ */ jsxs24(
2672
+ ({ active = false, icon, endAdornment, className, type = "button", children, ...props }, ref) => /* @__PURE__ */ jsxs25(
2613
2673
  "button",
2614
2674
  {
2615
2675
  ref,
@@ -2636,7 +2696,7 @@ SidebarFooter.displayName = "SidebarFooter";
2636
2696
  import * as React16 from "react";
2637
2697
  import { createPortal as createPortal4 } from "react-dom";
2638
2698
  import { Close as Close2 } from "@mirror-physics/fractal-icons";
2639
- import { jsx as jsx31, jsxs as jsxs25 } from "react/jsx-runtime";
2699
+ import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
2640
2700
  function SidePanel({ open, onClose, title, description, children, footer, size = "md", loading = false, loadingLabel = "Loading", className }) {
2641
2701
  useEscapeDismiss(80, onClose, open);
2642
2702
  const bodyRef = React16.useRef(null);
@@ -2672,7 +2732,7 @@ function SidePanel({ open, onClose, title, description, children, footer, size =
2672
2732
  }, [open, loading]);
2673
2733
  if (!open) return null;
2674
2734
  return createPortal4(
2675
- /* @__PURE__ */ jsx31("div", { className: "fractal-side-panel-overlay", onMouseDown: onClose, children: /* @__PURE__ */ jsxs25(
2735
+ /* @__PURE__ */ jsx31("div", { className: "fractal-side-panel-overlay", onMouseDown: onClose, children: /* @__PURE__ */ jsxs26(
2676
2736
  "aside",
2677
2737
  {
2678
2738
  className: cn("fractal-side-panel", `fractal-side-panel--${size}`, className),
@@ -2681,8 +2741,8 @@ function SidePanel({ open, onClose, title, description, children, footer, size =
2681
2741
  role: "dialog",
2682
2742
  onMouseDown: (event) => event.stopPropagation(),
2683
2743
  children: [
2684
- /* @__PURE__ */ jsxs25("header", { className: "fractal-side-panel__header", "data-scroll-divider": scrollEdges.above, children: [
2685
- /* @__PURE__ */ jsxs25("div", { className: "fractal-side-panel__heading", children: [
2744
+ /* @__PURE__ */ jsxs26("header", { className: "fractal-side-panel__header", "data-scroll-divider": scrollEdges.above, children: [
2745
+ /* @__PURE__ */ jsxs26("div", { className: "fractal-side-panel__heading", children: [
2686
2746
  typeof title === "string" ? /* @__PURE__ */ jsx31("h2", { className: "fractal-side-panel__title", children: title }) : /* @__PURE__ */ jsx31("div", { className: "fractal-side-panel__title", children: title }),
2687
2747
  description && /* @__PURE__ */ jsx31("p", { className: "fractal-side-panel__description", children: description })
2688
2748
  ] }),
@@ -2699,17 +2759,35 @@ function SidePanel({ open, onClose, title, description, children, footer, size =
2699
2759
 
2700
2760
  // src/components/Textarea/Textarea.tsx
2701
2761
  import * as React17 from "react";
2702
- import { jsx as jsx32 } from "react/jsx-runtime";
2762
+ import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
2703
2763
  var Textarea = React17.forwardRef(
2704
- ({ className, ...props }, ref) => /* @__PURE__ */ jsx32("textarea", { ref, className: cn("fractal-textarea", className), ...props })
2764
+ ({ className, fieldLabel, textStyle = "source", id, placeholder, ...props }, ref) => {
2765
+ const generatedId = React17.useId();
2766
+ const fieldId = id ?? generatedId;
2767
+ const input = /* @__PURE__ */ jsx32(
2768
+ "textarea",
2769
+ {
2770
+ ref,
2771
+ id: fieldLabel ? fieldId : id,
2772
+ placeholder: fieldLabel ? placeholder || " " : placeholder,
2773
+ className: cn("fractal-textarea", className),
2774
+ "data-text-style": textStyle,
2775
+ ...props
2776
+ }
2777
+ );
2778
+ return fieldLabel ? /* @__PURE__ */ jsxs27("div", { className: "fractal-floating-field fractal-floating-field--textarea", "data-control-size": "md", children: [
2779
+ input,
2780
+ /* @__PURE__ */ jsx32("label", { className: "fractal-floating-field__label", htmlFor: fieldId, children: fieldLabel })
2781
+ ] }) : input;
2782
+ }
2705
2783
  );
2706
2784
  Textarea.displayName = "Textarea";
2707
2785
 
2708
2786
  // src/components/TextButton/TextButton.tsx
2709
2787
  import * as React18 from "react";
2710
- import { jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
2788
+ import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
2711
2789
  var TextButton = React18.forwardRef(
2712
- ({ className, icon, iconPosition = "start", size = "md", tone = "primary", children, ...props }, ref) => /* @__PURE__ */ jsxs26(
2790
+ ({ className, icon, iconPosition = "start", size = "md", tone = "primary", children, ...props }, ref) => /* @__PURE__ */ jsxs28(
2713
2791
  "button",
2714
2792
  {
2715
2793
  ref,
@@ -2729,7 +2807,7 @@ TextButton.displayName = "TextButton";
2729
2807
  // src/components/FileDropzone/FileDropzone.tsx
2730
2808
  import * as React19 from "react";
2731
2809
  import { Close as Close3, FileArrowUp } from "@mirror-physics/fractal-icons";
2732
- import { jsx as jsx34, jsxs as jsxs27 } from "react/jsx-runtime";
2810
+ import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
2733
2811
  function FileDropzone({
2734
2812
  files,
2735
2813
  onFilesChange,
@@ -2749,7 +2827,7 @@ function FileDropzone({
2749
2827
  if (additions.length === 0) return;
2750
2828
  onFilesChange(multiple ? [...files, ...additions] : additions.slice(0, 1));
2751
2829
  };
2752
- return /* @__PURE__ */ jsxs27("div", { className: cn("fractal-file-dropzone", className), children: [
2830
+ return /* @__PURE__ */ jsxs29("div", { className: cn("fractal-file-dropzone", className), children: [
2753
2831
  /* @__PURE__ */ jsx34(
2754
2832
  "input",
2755
2833
  {
@@ -2766,7 +2844,7 @@ function FileDropzone({
2766
2844
  }
2767
2845
  }
2768
2846
  ),
2769
- /* @__PURE__ */ jsxs27(
2847
+ /* @__PURE__ */ jsxs29(
2770
2848
  "button",
2771
2849
  {
2772
2850
  className: "fractal-file-dropzone__target",
@@ -2790,14 +2868,14 @@ function FileDropzone({
2790
2868
  },
2791
2869
  children: [
2792
2870
  /* @__PURE__ */ jsx34(FileArrowUp, { "aria-hidden": "true", size: 20 }),
2793
- /* @__PURE__ */ jsxs27("span", { className: "fractal-file-dropzone__copy", children: [
2871
+ /* @__PURE__ */ jsxs29("span", { className: "fractal-file-dropzone__copy", children: [
2794
2872
  /* @__PURE__ */ jsx34("span", { className: "fractal-file-dropzone__title", children: title }),
2795
2873
  description && /* @__PURE__ */ jsx34("span", { className: "fractal-file-dropzone__description", children: description })
2796
2874
  ] })
2797
2875
  ]
2798
2876
  }
2799
2877
  ),
2800
- files.length > 0 && /* @__PURE__ */ jsx34("ul", { className: "fractal-file-dropzone__files", "aria-label": "Attached files", children: files.map((file, index) => /* @__PURE__ */ jsxs27("li", { className: "fractal-file-dropzone__file", children: [
2878
+ files.length > 0 && /* @__PURE__ */ jsx34("ul", { className: "fractal-file-dropzone__files", "aria-label": "Attached files", children: files.map((file, index) => /* @__PURE__ */ jsxs29("li", { className: "fractal-file-dropzone__file", children: [
2801
2879
  /* @__PURE__ */ jsx34("span", { className: "fractal-file-dropzone__file-name", children: file.name }),
2802
2880
  /* @__PURE__ */ jsx34("span", { className: "fractal-file-dropzone__file-meta", children: formatFileSize(file.size) }),
2803
2881
  /* @__PURE__ */ jsx34(
@@ -2822,7 +2900,7 @@ function formatFileSize(bytes) {
2822
2900
 
2823
2901
  // src/components/Pagination/Pagination.tsx
2824
2902
  import { ArrowLeft, ArrowRight } from "@mirror-physics/fractal-icons";
2825
- import { jsx as jsx35, jsxs as jsxs28 } from "react/jsx-runtime";
2903
+ import { jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
2826
2904
  function Pagination({
2827
2905
  page,
2828
2906
  pageSize,
@@ -2838,9 +2916,9 @@ function Pagination({
2838
2916
  const start = totalItems === 0 ? 0 : (currentPage - 1) * pageSize + 1;
2839
2917
  const end = Math.min(currentPage * pageSize, totalItems);
2840
2918
  const canChangePageSize = pageSizeOptions != null && pageSizeOptions.length > 0 && onPageSizeChange != null;
2841
- return /* @__PURE__ */ jsxs28("nav", { className: cn("fractal-pagination", className), "aria-label": ariaLabel, children: [
2919
+ return /* @__PURE__ */ jsxs30("nav", { className: cn("fractal-pagination", className), "aria-label": ariaLabel, children: [
2842
2920
  /* @__PURE__ */ jsx35("span", { className: "fractal-pagination__summary", children: totalItems === 0 ? "No results" : `${start}-${end} of ${totalItems}` }),
2843
- /* @__PURE__ */ jsxs28("div", { className: "fractal-pagination__controls", children: [
2921
+ /* @__PURE__ */ jsxs30("div", { className: "fractal-pagination__controls", children: [
2844
2922
  canChangePageSize && /* @__PURE__ */ jsx35(
2845
2923
  Dropdown,
2846
2924
  {
@@ -2870,7 +2948,7 @@ function Pagination({
2870
2948
  children: /* @__PURE__ */ jsx35(ArrowLeft, { "aria-hidden": "true", size: 16 })
2871
2949
  }
2872
2950
  ),
2873
- /* @__PURE__ */ jsxs28("span", { className: "fractal-pagination__page", "aria-current": "page", children: [
2951
+ /* @__PURE__ */ jsxs30("span", { className: "fractal-pagination__page", "aria-current": "page", children: [
2874
2952
  currentPage,
2875
2953
  " of ",
2876
2954
  totalPages