@geomak/ui 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -234,8 +234,45 @@ function IconButton({
234
234
  }
235
235
  );
236
236
  }
237
+ var VARIANT_CLASSES = {
238
+ primary: [
239
+ "bg-accent text-white",
240
+ "hover:bg-accent-hover",
241
+ "active:bg-accent",
242
+ "disabled:bg-roman-silver disabled:text-white/70 disabled:cursor-not-allowed",
243
+ "focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2"
244
+ ].join(" "),
245
+ secondary: [
246
+ "bg-transparent border border-accent text-accent",
247
+ "hover:bg-accent hover:text-white",
248
+ "active:bg-accent-hover active:text-white",
249
+ "disabled:border-roman-silver disabled:text-roman-silver disabled:cursor-not-allowed",
250
+ "focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2"
251
+ ].join(" "),
252
+ ghost: [
253
+ "bg-transparent text-foreground-secondary",
254
+ "hover:bg-ice dark:hover:bg-oxford-blue-700 hover:text-foreground",
255
+ "active:bg-ice-dark dark:active:bg-independence",
256
+ "disabled:text-roman-silver disabled:cursor-not-allowed",
257
+ "focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2"
258
+ ].join(" "),
259
+ danger: [
260
+ "bg-status-error text-white",
261
+ "hover:opacity-90",
262
+ "active:opacity-100",
263
+ "disabled:opacity-50 disabled:cursor-not-allowed",
264
+ "focus-visible:ring-2 focus-visible:ring-status-error focus-visible:ring-offset-2"
265
+ ].join(" ")
266
+ };
267
+ var SIZE_CLASSES = {
268
+ sm: "h-7 px-3 text-xs gap-1 rounded-md",
269
+ md: "h-9 px-4 text-sm gap-1.5 rounded-lg",
270
+ lg: "h-11 px-5 text-sm gap-2 rounded-xl"
271
+ };
237
272
  function Button({
238
273
  content,
274
+ variant = "primary",
275
+ size = "md",
239
276
  buttonType = "button",
240
277
  loading,
241
278
  disabled,
@@ -249,26 +286,33 @@ function Button({
249
286
  onClick,
250
287
  disabled: disabled || loading,
251
288
  type: buttonType,
252
- className: "bg-usafa-blue w-60 h-9 outline-offset-2 mt-5 rounded-lg disabled:bg-roman-silver disabled:cursor-not-allowed transition-all duration-300 hover:bg-true-blue active:bg-usafa-blue flex justify-center gap-1 items-center text-white",
253
- style: style ?? {},
289
+ style,
290
+ className: [
291
+ // Base — layout, transitions, focus reset
292
+ "inline-flex items-center justify-center font-medium",
293
+ "outline-none transition-colors duration-150 select-none",
294
+ "whitespace-nowrap",
295
+ SIZE_CLASSES[size],
296
+ VARIANT_CLASSES[variant]
297
+ ].join(" "),
254
298
  children: [
255
299
  loading ? /* @__PURE__ */ jsxRuntime.jsx(
256
300
  "svg",
257
301
  {
258
- xmlns: "http://www.w3.org/2000/svg",
259
302
  viewBox: "0 0 24 24",
260
- fill: "#fff",
261
- className: "w-6 h-6 animate-spin",
303
+ fill: "currentColor",
304
+ className: "w-4 h-4 animate-spin flex-shrink-0",
305
+ "aria-hidden": "true",
262
306
  children: /* @__PURE__ */ jsxRuntime.jsx(
263
307
  "path",
264
308
  {
265
309
  fillRule: "evenodd",
266
- d: "M4.755 10.059a7.5 7.5 0 0112.548-3.364l1.903 1.903h-3.183a.75.75 0 100 1.5h4.992a.75.75 0 00.75-.75V4.356a.75.75 0 00-1.5 0v3.18l-1.9-1.9A9 9 0 003.306 9.67a.75.75 0 101.45.388zm15.408 3.352a.75.75 0 00-.919.53 7.5 7.5 0 01-12.548 3.364l-1.902-1.903h3.183a.75.75 0 000-1.5H2.984a.75.75 0 00-.75.75v4.992a.75.75 0 001.5 0v-3.18l1.9 1.9a9 9 0 0015.059-4.035.75.75 0 00-.53-.918z",
267
- clipRule: "evenodd"
310
+ clipRule: "evenodd",
311
+ d: "M4.755 10.059a7.5 7.5 0 0112.548-3.364l1.903 1.903h-3.183a.75.75 0 100 1.5h4.992a.75.75 0 00.75-.75V4.356a.75.75 0 00-1.5 0v3.18l-1.9-1.9A9 9 0 003.306 9.67a.75.75 0 101.45.388zm15.408 3.352a.75.75 0 00-.919.53 7.5 7.5 0 01-12.548 3.364l-1.902-1.903h3.183a.75.75 0 000-1.5H2.984a.75.75 0 00-.75.75v4.992a.75.75 0 001.5 0v-3.18l1.9 1.9a9 9 0 0015.059-4.035.75.75 0 00-.53-.918z"
268
312
  }
269
313
  )
270
314
  }
271
- ) : icon ? icon : null,
315
+ ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", "aria-hidden": "true", children: icon }) : null,
272
316
  content
273
317
  ]
274
318
  }
@@ -691,15 +735,15 @@ var NotificationContext = React9.createContext({
691
735
  open: () => void 0,
692
736
  close: () => void 0
693
737
  });
694
- var typeClass = {
695
- info: "bg-info",
696
- success: "bg-success",
697
- warning: "bg-warning",
698
- danger: "bg-error"
738
+ var TYPE_BG = {
739
+ info: "bg-status-info",
740
+ success: "bg-status-success",
741
+ warning: "bg-status-warning",
742
+ danger: "bg-status-error"
699
743
  };
700
744
  function TypeIcon({ type }) {
701
745
  if (type === "success") {
702
- return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
746
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 28 28", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
703
747
  "path",
704
748
  {
705
749
  fillRule: "evenodd",
@@ -710,52 +754,94 @@ function TypeIcon({ type }) {
710
754
  ) });
711
755
  }
712
756
  if (type === "info") {
713
- return /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "#fff", className: "w-7 h-7", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm8.706-1.442c1.146-.573 2.437.463 2.126 1.706l-.709 2.836.042-.02a.75.75 0 01.67 1.34l-.04.022c-1.147.573-2.438-.463-2.127-1.706l.71-2.836-.042.02a.75.75 0 11-.671-1.34l.041-.022zM12 9a.75.75 0 100-1.5.75.75 0 000 1.5z", clipRule: "evenodd" }) });
757
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "#fff", className: "w-5 h-5", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm8.706-1.442c1.146-.573 2.437.463 2.126 1.706l-.709 2.836.042-.02a.75.75 0 01.67 1.34l-.04.022c-1.147.573-2.438-.463-2.127-1.706l.71-2.836-.042.02a.75.75 0 11-.671-1.34l.041-.022zM12 9a.75.75 0 100-1.5.75.75 0 000 1.5z", clipRule: "evenodd" }) });
714
758
  }
715
759
  if (type === "warning") {
716
- return /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "#fff", className: "w-7 h-7", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M9.401 3.003c1.155-2 4.043-2 5.197 0l7.355 12.748c1.154 2-.29 4.5-2.599 4.5H4.645c-2.309 0-3.752-2.5-2.598-4.5L9.4 3.003zM12 8.25a.75.75 0 01.75.75v3.75a.75.75 0 01-1.5 0V9a.75.75 0 01.75-.75zm0 8.25a.75.75 0 100-1.5.75.75 0 000 1.5z", clipRule: "evenodd" }) });
760
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "#fff", className: "w-5 h-5", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M9.401 3.003c1.155-2 4.043-2 5.197 0l7.355 12.748c1.154 2-.29 4.5-2.599 4.5H4.645c-2.309 0-3.752-2.5-2.598-4.5L9.4 3.003zM12 8.25a.75.75 0 01.75.75v3.75a.75.75 0 01-1.5 0V9a.75.75 0 01.75-.75zm0 8.25a.75.75 0 100-1.5.75.75 0 000 1.5z", clipRule: "evenodd" }) });
717
761
  }
718
- return /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "#fff", className: "w-7 h-7", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm11.378-3.917c-.89-.777-2.366-.777-3.255 0a.75.75 0 01-.988-1.129c1.454-1.272 3.776-1.272 5.23 0 1.513 1.324 1.513 3.518 0 4.842a3.75 3.75 0 01-.837.552c-.676.328-1.028.774-1.028 1.152v.75a.75.75 0 01-1.5 0v-.75c0-1.279 1.06-2.107 1.875-2.502.182-.088.351-.199.503-.331.83-.727.83-1.857 0-2.584zM12 18a.75.75 0 100-1.5.75.75 0 000 1.5z", clipRule: "evenodd" }) });
762
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "#fff", className: "w-5 h-5", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm11.378-3.917c-.89-.777-2.366-.777-3.255 0a.75.75 0 01-.988-1.129c1.454-1.272 3.776-1.272 5.23 0 1.513 1.324 1.513 3.518 0 4.842a3.75 3.75 0 01-.837.552c-.676.328-1.028.774-1.028 1.152v.75a.75.75 0 01-1.5 0v-.75c0-1.279 1.06-2.107 1.875-2.502.182-.088.351-.199.503-.331.83-.727.83-1.857 0-2.584zM12 18a.75.75 0 100-1.5.75.75 0 000 1.5z", clipRule: "evenodd" }) });
763
+ }
764
+ function NotificationItem({
765
+ n,
766
+ onClose,
767
+ reduced
768
+ }) {
769
+ return /* @__PURE__ */ jsxRuntime.jsx(
770
+ framerMotion.motion.div,
771
+ {
772
+ layout: true,
773
+ initial: { opacity: 0, x: reduced ? 0 : 56, scale: reduced ? 0.97 : 1 },
774
+ animate: { opacity: 1, x: 0, scale: 1 },
775
+ exit: { opacity: 0, x: reduced ? 0 : 40, scale: reduced ? 0.97 : 1 },
776
+ transition: reduced ? { duration: 0 } : {
777
+ opacity: { duration: 0.15 },
778
+ x: { type: "tween", duration: 0.22, ease: [0.16, 1, 0.3, 1] },
779
+ layout: { duration: 0.2 }
780
+ },
781
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
782
+ Toast__namespace.Root,
783
+ {
784
+ open: true,
785
+ duration: n.duration,
786
+ onOpenChange: (o) => {
787
+ if (!o) onClose(n.id);
788
+ },
789
+ className: [
790
+ "rounded-xl shadow-md p-3 w-[300px] text-white",
791
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-white/60",
792
+ TYPE_BG[n.type ?? "info"]
793
+ ].join(" "),
794
+ children: [
795
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
796
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(TypeIcon, { type: n.type ?? "info" }) }),
797
+ /* @__PURE__ */ jsxRuntime.jsx(Toast__namespace.Title, { className: "font-semibold text-sm leading-snug flex-1", children: n.title }),
798
+ /* @__PURE__ */ jsxRuntime.jsx(Toast__namespace.Action, { asChild: true, altText: "Close", children: /* @__PURE__ */ jsxRuntime.jsx(
799
+ "button",
800
+ {
801
+ "aria-label": "Close notification",
802
+ onClick: () => onClose(n.id),
803
+ className: "flex-shrink-0 rounded-md p-1 hover:bg-white/20 transition-colors duration-150 focus:outline-none focus-visible:ring-1 focus-visible:ring-white/60",
804
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "#fff", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
805
+ }
806
+ ) })
807
+ ] }),
808
+ n.description && /* @__PURE__ */ jsxRuntime.jsx(Toast__namespace.Description, { className: "mt-1.5 text-xs text-white/80 leading-relaxed pl-7", children: n.description })
809
+ ]
810
+ }
811
+ )
812
+ }
813
+ );
719
814
  }
720
815
  function NotificationProvider({ children }) {
721
816
  const [notifications, setNotifications] = React9.useState([]);
817
+ const reduced = framerMotion.useReducedMotion();
722
818
  const open = (payload) => {
723
- setNotifications((prev) => [...prev, { duration: 4e3, ...payload, id: Date.now() + Math.random() }]);
819
+ setNotifications((prev) => [
820
+ ...prev,
821
+ { duration: 4e3, ...payload, id: Date.now() + Math.random() }
822
+ ]);
724
823
  };
725
824
  const close = (id) => {
726
825
  setNotifications((prev) => prev.filter((n) => n.id !== id));
727
826
  };
728
827
  return /* @__PURE__ */ jsxRuntime.jsx(NotificationContext.Provider, { value: { open, close }, children: /* @__PURE__ */ jsxRuntime.jsxs(Toast__namespace.Provider, { swipeDirection: "right", children: [
729
828
  children,
730
- notifications.map((n) => /* @__PURE__ */ jsxRuntime.jsxs(
731
- Toast__namespace.Root,
829
+ /* @__PURE__ */ jsxRuntime.jsx(
830
+ Toast__namespace.Viewport,
732
831
  {
733
- open: true,
734
- duration: n.duration,
735
- onOpenChange: (o) => {
736
- if (!o) close(n.id);
737
- },
738
- className: `rounded-lg shadow-md p-2 w-[300px] text-white ${typeClass[n.type ?? "info"]} data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=open]:slide-in-from-right-full data-[state=closed]:slide-out-to-right-full`,
739
- children: [
740
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 border-b border-white pb-1", children: [
741
- /* @__PURE__ */ jsxRuntime.jsx(TypeIcon, { type: n.type ?? "info" }),
742
- /* @__PURE__ */ jsxRuntime.jsx(Toast__namespace.Title, { className: "text-center font-bold text-lg flex-1", children: n.title }),
743
- /* @__PURE__ */ jsxRuntime.jsx(Toast__namespace.Action, { asChild: true, altText: "Close", children: /* @__PURE__ */ jsxRuntime.jsx(
744
- "button",
745
- {
746
- "aria-label": "Close notification",
747
- onClick: () => close(n.id),
748
- className: "cursor-pointer rounded p-0.5 hover:bg-white/20 transition-colors",
749
- children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "#fff", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
750
- }
751
- ) })
752
- ] }),
753
- n.description && /* @__PURE__ */ jsxRuntime.jsx(Toast__namespace.Description, { className: "text-center mt-1 text-sm", children: n.description })
754
- ]
755
- },
756
- n.id
757
- )),
758
- /* @__PURE__ */ jsxRuntime.jsx(Toast__namespace.Viewport, { className: "fixed top-[50px] right-0 flex flex-col gap-2 w-[350px] z-[500000] p-4 outline-none" })
832
+ asChild: true,
833
+ className: "fixed top-[56px] right-0 z-[500000] flex flex-col gap-2 w-[350px] p-4 outline-none",
834
+ children: /* @__PURE__ */ jsxRuntime.jsx("ul", { children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { initial: false, children: notifications.map((n) => /* @__PURE__ */ jsxRuntime.jsx(
835
+ NotificationItem,
836
+ {
837
+ n,
838
+ onClose: close,
839
+ reduced
840
+ },
841
+ n.id
842
+ )) }) })
843
+ }
844
+ )
759
845
  ] }) });
760
846
  }
761
847
  function useNotification() {
@@ -1732,29 +1818,77 @@ function Table({
1732
1818
  /* @__PURE__ */ jsxRuntime.jsx("div", { children: footer })
1733
1819
  ] });
1734
1820
  }
1735
- function Switch({ checked, onChange }) {
1821
+ function ThemeSwitch({ checked, onChange, label = "Toggle dark mode" }) {
1736
1822
  const id = React9.useId();
1737
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative bottom-5", children: /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "flex items-center cursor-pointer mr-12 select-none", children: /* @__PURE__ */ jsxRuntime.jsx(
1823
+ return /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "flex items-center gap-2 cursor-pointer select-none", children: /* @__PURE__ */ jsxRuntime.jsx(
1738
1824
  SwitchPrimitive__namespace.Root,
1739
1825
  {
1740
1826
  id,
1741
1827
  checked,
1742
1828
  onCheckedChange: (c) => onChange({ target: { checked: c } }),
1743
- className: "relative inline-flex h-6 w-14 items-center rounded-full bg-prussian-blue dark:bg-white transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-usafa-blue",
1829
+ "aria-label": label,
1830
+ className: [
1831
+ "relative inline-flex h-6 w-11 items-center rounded-full",
1832
+ "transition-colors duration-200",
1833
+ "bg-foreground-secondary data-[state=checked]:bg-accent",
1834
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2"
1835
+ ].join(" "),
1744
1836
  children: /* @__PURE__ */ jsxRuntime.jsx(
1745
1837
  SwitchPrimitive__namespace.Thumb,
1746
1838
  {
1747
- className: "pointer-events-none inline-flex h-8 w-8 rounded-full shadow transition-transform duration-200 data-[state=checked]:translate-x-[22px] data-[state=unchecked]:translate-x-[-4px]",
1748
- children: /* @__PURE__ */ jsxRuntime.jsx(
1749
- "div",
1750
- {
1751
- className: `rounded-full w-8 h-8 ${checked ? "bg-success" : "bg-error"} transition-colors duration-200`
1752
- }
1839
+ className: [
1840
+ "pointer-events-none block h-5 w-5 rounded-full shadow-sm",
1841
+ "transition-transform duration-200",
1842
+ "data-[state=checked]:translate-x-[22px]",
1843
+ "data-[state=unchecked]:translate-x-[2px]",
1844
+ // Moon icon (dark mode indicator) when checked, sun when unchecked
1845
+ checked ? "bg-oxford-blue-900" : "bg-white"
1846
+ ].join(" "),
1847
+ children: checked ? (
1848
+ // Moon
1849
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 16 16", fill: "currentColor", className: "w-3 h-3 m-1 text-manatee", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z" }) })
1850
+ ) : (
1851
+ // Sun
1852
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 16 16", fill: "currentColor", className: "w-3 h-3 m-1 text-usafa-blue", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 11a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0 1a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707z" }) })
1753
1853
  )
1754
1854
  }
1755
1855
  )
1756
1856
  }
1757
- ) }) });
1857
+ ) });
1858
+ }
1859
+ function TopBar({
1860
+ brand,
1861
+ center,
1862
+ actions,
1863
+ height = 56,
1864
+ className = ""
1865
+ }) {
1866
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1867
+ "header",
1868
+ {
1869
+ className: [
1870
+ "sticky top-0 z-[100]",
1871
+ "flex items-center justify-between gap-4",
1872
+ "border-b border-border bg-surface",
1873
+ "px-4 md:px-6",
1874
+ className
1875
+ ].join(" "),
1876
+ style: {
1877
+ height,
1878
+ // Expose as CSS var so consumers can write:
1879
+ // padding-top: calc(var(--topbar-height) + 1rem)
1880
+ ["--topbar-height"]: `${height}px`
1881
+ },
1882
+ children: [
1883
+ brand !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 flex-shrink-0", children: brand }) : (
1884
+ // Reserve leading space even when brand is null so center stays centred
1885
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", className: "flex-shrink-0 w-0" })
1886
+ ),
1887
+ center !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 items-center justify-center min-w-0", children: center }),
1888
+ actions !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 flex-shrink-0", children: actions })
1889
+ ]
1890
+ }
1891
+ );
1758
1892
  }
1759
1893
  function TextInput({
1760
1894
  value,
@@ -2031,7 +2165,7 @@ function Checkbox({
2031
2165
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-error text-center", children: errorMessage })
2032
2166
  ] });
2033
2167
  }
2034
- function Switch2({
2168
+ function Switch({
2035
2169
  checked = false,
2036
2170
  onChange,
2037
2171
  checkedIcon,
@@ -2673,15 +2807,16 @@ exports.OpaqueGridCard = OpaqueGridCard;
2673
2807
  exports.Password = Password;
2674
2808
  exports.ScalableContainer = ScalableContainer;
2675
2809
  exports.SearchInput = SearchInput_default;
2676
- exports.Switch = Switch2;
2810
+ exports.Switch = Switch;
2677
2811
  exports.Table = Table;
2678
2812
  exports.Tabs = Tabs;
2679
2813
  exports.Temporal = DatePicker_default;
2680
2814
  exports.TextInput = TextInput;
2681
- exports.ThemeSwitch = Switch;
2815
+ exports.ThemeSwitch = ThemeSwitch;
2682
2816
  exports.ToggleButton = ToggleButton;
2683
2817
  exports.Tooltip = Tooltip;
2684
2818
  exports.TooltipProvider = TooltipProvider;
2819
+ exports.TopBar = TopBar;
2685
2820
  exports.Tree = Tree;
2686
2821
  exports.TreeSelect = TreeSelect;
2687
2822
  exports.Wizard = Wizard;