@geomak/ui 6.28.0 → 6.29.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.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { colors_default } from './chunk-I2P4JJDB.js';
2
2
  export { colors_default as COLORS, PALETTE as palette, semanticTokens, vars } from './chunk-I2P4JJDB.js';
3
3
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
- import React28, { createContext, useState, useEffect, useMemo, useId, useCallback, useRef, useContext, useSyncExternalStore, useLayoutEffect } from 'react';
4
+ import React29, { createContext, useState, useEffect, useMemo, useId, useCallback, useRef, useLayoutEffect, useContext, useSyncExternalStore } from 'react';
5
5
  import { createPortal } from 'react-dom';
6
6
  import * as AvatarPrimitive from '@radix-ui/react-avatar';
7
7
  import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
@@ -470,8 +470,8 @@ function Avatar({
470
470
  if (fallback) return fallback;
471
471
  if (alt) {
472
472
  const parts = alt.trim().split(/\s+/).slice(0, 2);
473
- const initials = parts.map((p) => p[0]?.toUpperCase() ?? "").join("");
474
- if (initials) return initials;
473
+ const initials2 = parts.map((p) => p[0]?.toUpperCase() ?? "").join("");
474
+ if (initials2) return initials2;
475
475
  }
476
476
  return /* @__PURE__ */ jsx(PersonSilhouette, {});
477
477
  })();
@@ -704,7 +704,7 @@ var SIZE_CLASSES = {
704
704
  md: "h-9 px-4 text-sm gap-1.5 rounded-lg",
705
705
  lg: "h-11 px-5 text-sm gap-2 rounded-xl"
706
706
  };
707
- var Button = React28.forwardRef(function Button2({
707
+ var Button = React29.forwardRef(function Button2({
708
708
  content,
709
709
  variant = "primary",
710
710
  size = "md",
@@ -812,7 +812,7 @@ function MenuButton({
812
812
  "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
813
813
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95"
814
814
  ].join(" "),
815
- children: items.map((item) => /* @__PURE__ */ jsxs(React28.Fragment, { children: [
815
+ children: items.map((item) => /* @__PURE__ */ jsxs(React29.Fragment, { children: [
816
816
  item.separatorBefore && /* @__PURE__ */ jsx(DropdownMenu.Separator, { className: "my-1 h-px bg-border" }),
817
817
  /* @__PURE__ */ jsxs(
818
818
  DropdownMenu.Item,
@@ -1911,7 +1911,7 @@ function Kbd({
1911
1911
  style
1912
1912
  }) {
1913
1913
  if (keys && keys.length > 0) {
1914
- return /* @__PURE__ */ jsx("span", { className: ["inline-flex items-center gap-1", className].filter(Boolean).join(" "), style, children: keys.map((k, i) => /* @__PURE__ */ jsxs(React28.Fragment, { children: [
1914
+ return /* @__PURE__ */ jsx("span", { className: ["inline-flex items-center gap-1", className].filter(Boolean).join(" "), style, children: keys.map((k, i) => /* @__PURE__ */ jsxs(React29.Fragment, { children: [
1915
1915
  i > 0 && /* @__PURE__ */ jsx("span", { className: "text-foreground-muted text-xs select-none", children: separator }),
1916
1916
  /* @__PURE__ */ jsx("kbd", { className: [cap, SIZE3[size]].join(" "), children: k })
1917
1917
  ] }, `${k}-${i}`)) });
@@ -2003,7 +2003,7 @@ function FlatCarousel({
2003
2003
  style
2004
2004
  }) {
2005
2005
  const scrollerRef = useRef(null);
2006
- const slides = React28.Children.toArray(children);
2006
+ const slides = React29.Children.toArray(children);
2007
2007
  const [active, setActive] = useState(0);
2008
2008
  const [atStart, setAtStart] = useState(true);
2009
2009
  const [atEnd, setAtEnd] = useState(false);
@@ -2058,7 +2058,7 @@ function RotatingCarousel({
2058
2058
  className = "",
2059
2059
  style
2060
2060
  }) {
2061
- const slides = React28.Children.toArray(children);
2061
+ const slides = React29.Children.toArray(children);
2062
2062
  const count = slides.length;
2063
2063
  const [active, setActive] = useState(0);
2064
2064
  const reduced = useReducedMotion();
@@ -2131,6 +2131,300 @@ function RotatingCarousel({
2131
2131
  }
2132
2132
  );
2133
2133
  }
2134
+ var FIELD_SIZE = {
2135
+ sm: { control: "h-control-sm", text: "text-xs", padX: "px-2.5", gap: "gap-1.5" },
2136
+ md: { control: "h-control-md", text: "text-sm", padX: "px-3", gap: "gap-2" },
2137
+ lg: { control: "h-control-lg", text: "text-sm", padX: "px-3.5", gap: "gap-2.5" }
2138
+ };
2139
+ var FOCUS_WITHIN = "focus-within:outline-none focus-within:border-accent";
2140
+ var FOCUS_ELEMENT = "focus:outline-none focus:border-accent data-[state=open]:border-accent";
2141
+ var FOCUS_WITHIN_ERROR = "focus-within:border-status-error";
2142
+ var FOCUS_ELEMENT_ERROR = "focus:border-status-error data-[state=open]:border-status-error";
2143
+ function fieldShell({
2144
+ size = "md",
2145
+ hasError = false,
2146
+ disabled = false,
2147
+ focusWithin = false,
2148
+ sized = true
2149
+ } = {}) {
2150
+ const s = FIELD_SIZE[size];
2151
+ return [
2152
+ "w-full rounded-lg border bg-surface text-foreground",
2153
+ "transition-[color,box-shadow,border-color] duration-150",
2154
+ s.text,
2155
+ sized ? `${s.control} ${s.padX}` : "",
2156
+ // resting border
2157
+ hasError ? "border-status-error" : "border-border",
2158
+ // hover (only when interactive + no error)
2159
+ disabled ? "bg-surface-raised text-foreground-muted cursor-not-allowed" : hasError ? "" : "hover:border-border-strong",
2160
+ // focus
2161
+ focusWithin ? FOCUS_WITHIN : FOCUS_ELEMENT,
2162
+ hasError ? focusWithin ? FOCUS_WITHIN_ERROR : FOCUS_ELEMENT_ERROR : "",
2163
+ // placeholder colour for native inputs
2164
+ "placeholder:text-foreground-muted"
2165
+ ].filter(Boolean).join(" ");
2166
+ }
2167
+ function FieldHelpIcon({ text }) {
2168
+ return /* @__PURE__ */ jsx(Tooltip, { title: text, placement: "top", children: /* @__PURE__ */ jsx(
2169
+ "button",
2170
+ {
2171
+ type: "button",
2172
+ "aria-label": "More information",
2173
+ className: "inline-flex items-center justify-center rounded-full text-foreground-muted transition-colors hover:text-foreground focus:outline-none focus-visible:text-accent",
2174
+ children: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", className: "h-3.5 w-3.5", fill: "none", stroke: "currentColor", strokeWidth: 1.5, "aria-hidden": "true", children: [
2175
+ /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "6.25" }),
2176
+ /* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "M8 7.4v3.4" }),
2177
+ /* @__PURE__ */ jsx("circle", { cx: "8", cy: "5.1", r: "0.65", fill: "currentColor", stroke: "none" })
2178
+ ] })
2179
+ }
2180
+ ) });
2181
+ }
2182
+ function FieldLabel({
2183
+ label,
2184
+ htmlFor,
2185
+ required,
2186
+ helperText,
2187
+ horizontal = false,
2188
+ align = "start",
2189
+ style,
2190
+ width,
2191
+ className = ""
2192
+ }) {
2193
+ if (label == null && helperText == null) return null;
2194
+ return /* @__PURE__ */ jsxs(
2195
+ "div",
2196
+ {
2197
+ style: { width: horizontal ? width : void 0, ...style },
2198
+ className: [
2199
+ "flex items-center gap-1",
2200
+ horizontal ? "flex-shrink-0 whitespace-nowrap" : "",
2201
+ // Only the 'start' alignment needs the top nudge; 'center' relies
2202
+ // on the row's items-center to line up with a short control.
2203
+ horizontal && align === "start" ? "mt-2" : "",
2204
+ className
2205
+ ].filter(Boolean).join(" "),
2206
+ children: [
2207
+ label != null && /* @__PURE__ */ jsxs("label", { htmlFor, className: "text-sm font-medium text-foreground select-none", children: [
2208
+ label,
2209
+ required && /* @__PURE__ */ jsx("span", { className: "text-status-error ml-0.5", "aria-hidden": "true", children: "*" })
2210
+ ] }),
2211
+ helperText != null && /* @__PURE__ */ jsx(FieldHelpIcon, { text: helperText })
2212
+ ]
2213
+ }
2214
+ );
2215
+ }
2216
+ function Field({
2217
+ label,
2218
+ htmlFor,
2219
+ errorId,
2220
+ errorMessage,
2221
+ layout = "vertical",
2222
+ required,
2223
+ helperText,
2224
+ labelAlign = "start",
2225
+ labelStyle,
2226
+ labelWidth,
2227
+ className = "",
2228
+ children
2229
+ }) {
2230
+ const hasError = errorMessage != null;
2231
+ const horizontal = layout === "horizontal";
2232
+ return /* @__PURE__ */ jsxs(
2233
+ "div",
2234
+ {
2235
+ className: [
2236
+ "flex",
2237
+ horizontal ? `flex-row gap-3 ${labelAlign === "center" ? "items-center" : "items-start"}` : "flex-col gap-1.5",
2238
+ className
2239
+ ].filter(Boolean).join(" "),
2240
+ children: [
2241
+ /* @__PURE__ */ jsx(
2242
+ FieldLabel,
2243
+ {
2244
+ label,
2245
+ htmlFor,
2246
+ required,
2247
+ helperText,
2248
+ horizontal,
2249
+ align: labelAlign,
2250
+ style: labelStyle,
2251
+ width: labelWidth
2252
+ }
2253
+ ),
2254
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
2255
+ children,
2256
+ hasError && /* @__PURE__ */ jsx("div", { id: errorId, className: "text-status-error text-xs mt-1", children: errorMessage })
2257
+ ] })
2258
+ ]
2259
+ }
2260
+ );
2261
+ }
2262
+ var toDate = (d) => d instanceof Date ? d : new Date(d);
2263
+ var timeLabel = (d) => `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
2264
+ var initials = (name) => (name ?? "").trim().split(/\s+/).slice(0, 2).map((w) => w[0]?.toUpperCase() ?? "").join("") || void 0;
2265
+ var SendIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", className: "h-4 w-4", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M22 2 11 13M22 2l-7 20-4-9-9-4 20-7z" }) });
2266
+ var ArrowDown = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", className: "h-4 w-4", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 5v14M5 12l7 7 7-7" }) });
2267
+ function TypingDots() {
2268
+ return /* @__PURE__ */ jsx("span", { className: "inline-flex items-center gap-1", "aria-hidden": "true", children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 animate-bounce rounded-full bg-foreground-muted", style: { animationDelay: `${i * 0.15}s` } }, i)) });
2269
+ }
2270
+ function Chat({
2271
+ messages,
2272
+ currentUserId,
2273
+ onSend,
2274
+ typingNames = [],
2275
+ title,
2276
+ subtitle,
2277
+ avatar,
2278
+ headerActions,
2279
+ placeholder = "Write a message\u2026",
2280
+ disabled = false,
2281
+ hideComposer = false,
2282
+ emptyState,
2283
+ height = 480,
2284
+ className = "",
2285
+ style
2286
+ }) {
2287
+ const listRef = useRef(null);
2288
+ const atBottomRef = useRef(true);
2289
+ const [showJump, setShowJump] = useState(false);
2290
+ const [draft, setDraft] = useState("");
2291
+ const taRef = useRef(null);
2292
+ const hasHeader = title != null || subtitle != null || avatar != null || headerActions != null;
2293
+ const isTyping = typingNames.length > 0;
2294
+ const scrollToBottom = useCallback((smooth = true) => {
2295
+ const el = listRef.current;
2296
+ if (!el) return;
2297
+ if (typeof el.scrollTo === "function") el.scrollTo({ top: el.scrollHeight, behavior: smooth ? "smooth" : "auto" });
2298
+ else el.scrollTop = el.scrollHeight;
2299
+ }, []);
2300
+ const onScroll = () => {
2301
+ const el = listRef.current;
2302
+ if (!el) return;
2303
+ const near = el.scrollHeight - el.scrollTop - el.clientHeight < 80;
2304
+ atBottomRef.current = near;
2305
+ setShowJump(!near);
2306
+ };
2307
+ useEffect(() => {
2308
+ if (atBottomRef.current) scrollToBottom(messages.length > 0);
2309
+ }, [messages.length, isTyping]);
2310
+ useEffect(() => {
2311
+ scrollToBottom(false);
2312
+ }, [scrollToBottom]);
2313
+ useLayoutEffect(() => {
2314
+ const ta = taRef.current;
2315
+ if (!ta) return;
2316
+ ta.style.height = "auto";
2317
+ ta.style.height = `${Math.min(ta.scrollHeight, 120)}px`;
2318
+ }, [draft]);
2319
+ const send = () => {
2320
+ const text = draft.trim();
2321
+ if (!text || disabled) return;
2322
+ onSend?.(text);
2323
+ setDraft("");
2324
+ };
2325
+ const onKeyDown = (e) => {
2326
+ if (e.key === "Enter" && !e.shiftKey) {
2327
+ e.preventDefault();
2328
+ send();
2329
+ }
2330
+ };
2331
+ return /* @__PURE__ */ jsxs(
2332
+ "div",
2333
+ {
2334
+ className: ["flex flex-col overflow-hidden rounded-xl border border-border bg-surface", className].filter(Boolean).join(" "),
2335
+ style: { height, ...style },
2336
+ children: [
2337
+ hasHeader && /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 items-center gap-3 border-b border-border px-4 py-3", children: [
2338
+ avatar != null && /* @__PURE__ */ jsx(Avatar, { src: avatar, alt: typeof title === "string" ? title : "Conversation", size: "sm" }),
2339
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
2340
+ title != null && /* @__PURE__ */ jsx("div", { className: "truncate text-sm font-semibold text-foreground", children: title }),
2341
+ subtitle != null && /* @__PURE__ */ jsx("div", { className: "truncate text-xs text-foreground-muted", children: subtitle })
2342
+ ] }),
2343
+ headerActions != null && /* @__PURE__ */ jsx("div", { className: "flex flex-shrink-0 items-center gap-1", children: headerActions })
2344
+ ] }),
2345
+ /* @__PURE__ */ jsxs("div", { className: "relative flex-1 overflow-hidden", children: [
2346
+ /* @__PURE__ */ jsxs("div", { ref: listRef, onScroll, className: "flex h-full flex-col gap-1 overflow-y-auto bg-background px-4 py-3", children: [
2347
+ messages.length === 0 && !isTyping ? /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center text-center text-sm text-foreground-muted", children: emptyState ?? "No messages yet. Say hello \u{1F44B}" }) : messages.map((m, i) => {
2348
+ const own = m.authorId === currentUserId;
2349
+ const prev = messages[i - 1];
2350
+ const next = messages[i + 1];
2351
+ const firstOfGroup = !prev || prev.authorId !== m.authorId;
2352
+ const lastOfGroup = !next || next.authorId !== m.authorId;
2353
+ const ts = m.timestamp ? toDate(m.timestamp) : null;
2354
+ return /* @__PURE__ */ jsxs("div", { className: ["flex items-end gap-2", own ? "flex-row-reverse" : "", firstOfGroup ? "mt-2 first:mt-0" : ""].filter(Boolean).join(" "), children: [
2355
+ !own && /* @__PURE__ */ jsx("div", { className: "w-7 flex-shrink-0", children: lastOfGroup && /* @__PURE__ */ jsx(Avatar, { src: m.avatar, alt: m.authorName ?? "User", fallback: initials(m.authorName), size: "xs" }) }),
2356
+ /* @__PURE__ */ jsxs("div", { className: ["flex max-w-[78%] flex-col", own ? "items-end" : "items-start"].join(" "), children: [
2357
+ firstOfGroup && !own && m.authorName && /* @__PURE__ */ jsx("span", { className: "mb-0.5 px-1 text-[11px] font-medium text-foreground-muted", children: m.authorName }),
2358
+ /* @__PURE__ */ jsx(
2359
+ "div",
2360
+ {
2361
+ className: [
2362
+ "whitespace-pre-wrap break-words px-3 py-1.5 text-sm leading-snug",
2363
+ own ? "rounded-2xl bg-accent text-accent-fg" : "rounded-2xl border border-border bg-surface text-foreground",
2364
+ lastOfGroup ? own ? "rounded-br-md" : "rounded-bl-md" : ""
2365
+ ].filter(Boolean).join(" "),
2366
+ children: m.text
2367
+ }
2368
+ ),
2369
+ lastOfGroup && (ts || own && m.status) && /* @__PURE__ */ jsxs("span", { className: "mt-0.5 px-1 text-[10px] text-foreground-muted", children: [
2370
+ ts && timeLabel(ts),
2371
+ own && m.status && /* @__PURE__ */ jsxs("span", { className: "ml-1 capitalize", children: [
2372
+ "\xB7 ",
2373
+ m.status
2374
+ ] })
2375
+ ] })
2376
+ ] })
2377
+ ] }, m.id);
2378
+ }),
2379
+ isTyping && /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-end gap-2", children: [
2380
+ /* @__PURE__ */ jsx("div", { className: "w-7 flex-shrink-0" }),
2381
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-2xl rounded-bl-md border border-border bg-surface px-3 py-2", children: [
2382
+ /* @__PURE__ */ jsx(TypingDots, {}),
2383
+ /* @__PURE__ */ jsx("span", { className: "text-[11px] text-foreground-muted", children: typingNames.length === 1 ? `${typingNames[0]} is typing` : `${typingNames.length} people are typing` })
2384
+ ] })
2385
+ ] })
2386
+ ] }),
2387
+ showJump && /* @__PURE__ */ jsx(
2388
+ "button",
2389
+ {
2390
+ type: "button",
2391
+ onClick: () => scrollToBottom(true),
2392
+ "aria-label": "Jump to latest",
2393
+ className: "absolute bottom-3 left-1/2 flex h-8 w-8 -translate-x-1/2 items-center justify-center rounded-full border border-border bg-surface text-foreground-secondary shadow-md transition-colors hover:bg-surface-raised hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
2394
+ children: /* @__PURE__ */ jsx(ArrowDown, {})
2395
+ }
2396
+ )
2397
+ ] }),
2398
+ !hideComposer && /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 items-end gap-2 border-t border-border p-3", children: [
2399
+ /* @__PURE__ */ jsx(
2400
+ "textarea",
2401
+ {
2402
+ ref: taRef,
2403
+ rows: 1,
2404
+ value: draft,
2405
+ disabled,
2406
+ placeholder,
2407
+ onChange: (e) => setDraft(e.target.value),
2408
+ onKeyDown,
2409
+ "aria-label": "Message",
2410
+ className: `${fieldShell({ size: "md", hasError: false, disabled, sized: false })} max-h-[120px] flex-1 resize-none px-3 py-2 leading-snug`
2411
+ }
2412
+ ),
2413
+ /* @__PURE__ */ jsx(
2414
+ IconButton,
2415
+ {
2416
+ type: "primary",
2417
+ icon: /* @__PURE__ */ jsx(SendIcon, {}),
2418
+ title: "Send",
2419
+ disabled: disabled || draft.trim().length === 0,
2420
+ onClick: send
2421
+ }
2422
+ )
2423
+ ] })
2424
+ ]
2425
+ }
2426
+ );
2427
+ }
2134
2428
  var VALUE_SIZE = {
2135
2429
  sm: "text-xl",
2136
2430
  md: "text-3xl",
@@ -2142,7 +2436,7 @@ var TONE2 = {
2142
2436
  neutral: "text-foreground-muted"
2143
2437
  };
2144
2438
  var ArrowUp = /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.2, "aria-hidden": "true", className: "h-3.5 w-3.5", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 19V5M5 12l7-7 7 7" }) });
2145
- var ArrowDown = /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.2, "aria-hidden": "true", className: "h-3.5 w-3.5", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 5v14M5 12l7 7 7-7" }) });
2439
+ var ArrowDown2 = /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.2, "aria-hidden": "true", className: "h-3.5 w-3.5", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 5v14M5 12l7 7 7-7" }) });
2146
2440
  function Statistic({
2147
2441
  label,
2148
2442
  value,
@@ -2174,7 +2468,7 @@ function Statistic({
2174
2468
  suffix && /* @__PURE__ */ jsx("span", { className: "text-foreground-muted text-[0.5em] font-medium self-center", children: suffix })
2175
2469
  ] }),
2176
2470
  delta && /* @__PURE__ */ jsxs("div", { className: `mt-1.5 flex items-center gap-1 text-sm font-medium ${align === "center" ? "justify-center" : ""} ${TONE2[deltaTone]}`, children: [
2177
- dir === "up" ? ArrowUp : dir === "down" ? ArrowDown : null,
2471
+ dir === "up" ? ArrowUp : dir === "down" ? ArrowDown2 : null,
2178
2472
  /* @__PURE__ */ jsx("span", { children: delta.value }),
2179
2473
  delta.label && /* @__PURE__ */ jsx("span", { className: "text-foreground-muted font-normal", children: delta.label })
2180
2474
  ] }),
@@ -2611,134 +2905,6 @@ function Calendar2({
2611
2905
  }) })
2612
2906
  ] });
2613
2907
  }
2614
- var FIELD_SIZE = {
2615
- sm: { control: "h-control-sm", text: "text-xs", padX: "px-2.5", gap: "gap-1.5" },
2616
- md: { control: "h-control-md", text: "text-sm", padX: "px-3", gap: "gap-2" },
2617
- lg: { control: "h-control-lg", text: "text-sm", padX: "px-3.5", gap: "gap-2.5" }
2618
- };
2619
- var FOCUS_WITHIN = "focus-within:outline-none focus-within:border-accent";
2620
- var FOCUS_ELEMENT = "focus:outline-none focus:border-accent data-[state=open]:border-accent";
2621
- var FOCUS_WITHIN_ERROR = "focus-within:border-status-error";
2622
- var FOCUS_ELEMENT_ERROR = "focus:border-status-error data-[state=open]:border-status-error";
2623
- function fieldShell({
2624
- size = "md",
2625
- hasError = false,
2626
- disabled = false,
2627
- focusWithin = false,
2628
- sized = true
2629
- } = {}) {
2630
- const s = FIELD_SIZE[size];
2631
- return [
2632
- "w-full rounded-lg border bg-surface text-foreground",
2633
- "transition-[color,box-shadow,border-color] duration-150",
2634
- s.text,
2635
- sized ? `${s.control} ${s.padX}` : "",
2636
- // resting border
2637
- hasError ? "border-status-error" : "border-border",
2638
- // hover (only when interactive + no error)
2639
- disabled ? "bg-surface-raised text-foreground-muted cursor-not-allowed" : hasError ? "" : "hover:border-border-strong",
2640
- // focus
2641
- focusWithin ? FOCUS_WITHIN : FOCUS_ELEMENT,
2642
- hasError ? focusWithin ? FOCUS_WITHIN_ERROR : FOCUS_ELEMENT_ERROR : "",
2643
- // placeholder colour for native inputs
2644
- "placeholder:text-foreground-muted"
2645
- ].filter(Boolean).join(" ");
2646
- }
2647
- function FieldHelpIcon({ text }) {
2648
- return /* @__PURE__ */ jsx(Tooltip, { title: text, placement: "top", children: /* @__PURE__ */ jsx(
2649
- "button",
2650
- {
2651
- type: "button",
2652
- "aria-label": "More information",
2653
- className: "inline-flex items-center justify-center rounded-full text-foreground-muted transition-colors hover:text-foreground focus:outline-none focus-visible:text-accent",
2654
- children: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", className: "h-3.5 w-3.5", fill: "none", stroke: "currentColor", strokeWidth: 1.5, "aria-hidden": "true", children: [
2655
- /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "6.25" }),
2656
- /* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "M8 7.4v3.4" }),
2657
- /* @__PURE__ */ jsx("circle", { cx: "8", cy: "5.1", r: "0.65", fill: "currentColor", stroke: "none" })
2658
- ] })
2659
- }
2660
- ) });
2661
- }
2662
- function FieldLabel({
2663
- label,
2664
- htmlFor,
2665
- required,
2666
- helperText,
2667
- horizontal = false,
2668
- align = "start",
2669
- style,
2670
- width,
2671
- className = ""
2672
- }) {
2673
- if (label == null && helperText == null) return null;
2674
- return /* @__PURE__ */ jsxs(
2675
- "div",
2676
- {
2677
- style: { width: horizontal ? width : void 0, ...style },
2678
- className: [
2679
- "flex items-center gap-1",
2680
- horizontal ? "flex-shrink-0 whitespace-nowrap" : "",
2681
- // Only the 'start' alignment needs the top nudge; 'center' relies
2682
- // on the row's items-center to line up with a short control.
2683
- horizontal && align === "start" ? "mt-2" : "",
2684
- className
2685
- ].filter(Boolean).join(" "),
2686
- children: [
2687
- label != null && /* @__PURE__ */ jsxs("label", { htmlFor, className: "text-sm font-medium text-foreground select-none", children: [
2688
- label,
2689
- required && /* @__PURE__ */ jsx("span", { className: "text-status-error ml-0.5", "aria-hidden": "true", children: "*" })
2690
- ] }),
2691
- helperText != null && /* @__PURE__ */ jsx(FieldHelpIcon, { text: helperText })
2692
- ]
2693
- }
2694
- );
2695
- }
2696
- function Field({
2697
- label,
2698
- htmlFor,
2699
- errorId,
2700
- errorMessage,
2701
- layout = "vertical",
2702
- required,
2703
- helperText,
2704
- labelAlign = "start",
2705
- labelStyle,
2706
- labelWidth,
2707
- className = "",
2708
- children
2709
- }) {
2710
- const hasError = errorMessage != null;
2711
- const horizontal = layout === "horizontal";
2712
- return /* @__PURE__ */ jsxs(
2713
- "div",
2714
- {
2715
- className: [
2716
- "flex",
2717
- horizontal ? `flex-row gap-3 ${labelAlign === "center" ? "items-center" : "items-start"}` : "flex-col gap-1.5",
2718
- className
2719
- ].filter(Boolean).join(" "),
2720
- children: [
2721
- /* @__PURE__ */ jsx(
2722
- FieldLabel,
2723
- {
2724
- label,
2725
- htmlFor,
2726
- required,
2727
- helperText,
2728
- horizontal,
2729
- align: labelAlign,
2730
- style: labelStyle,
2731
- width: labelWidth
2732
- }
2733
- ),
2734
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
2735
- children,
2736
- hasError && /* @__PURE__ */ jsx("div", { id: errorId, className: "text-status-error text-xs mt-1", children: errorMessage })
2737
- ] })
2738
- ]
2739
- }
2740
- );
2741
- }
2742
2908
  var SIZE5 = {
2743
2909
  sm: { h: "h-control-sm", text: "text-xs", pad: "px-2.5" },
2744
2910
  md: { h: "h-control-md", text: "text-sm", pad: "px-3.5" },
@@ -2853,7 +3019,7 @@ var MONTHS2 = [
2853
3019
  ];
2854
3020
  var MONTHS_SHORT = MONTHS2.map((m) => m.slice(0, 3));
2855
3021
  var WEEKDAYS2 = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
2856
- var toDate = (d) => d instanceof Date ? d : new Date(d);
3022
+ var toDate2 = (d) => d instanceof Date ? d : new Date(d);
2857
3023
  var startOfDay2 = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate());
2858
3024
  var addDays = (d, n) => {
2859
3025
  const x = new Date(d);
@@ -2901,10 +3067,10 @@ var weekLabel = (cursor, weekStartsOn) => {
2901
3067
  };
2902
3068
  var minutesIntoDay = (d) => d.getHours() * 60 + d.getMinutes();
2903
3069
  var hourLabel = (hour) => `${String(hour).padStart(2, "0")}:00`;
2904
- var timeLabel = (d) => `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
3070
+ var timeLabel2 = (d) => `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
2905
3071
  var normalize = (e) => {
2906
- const start = toDate(e.start);
2907
- const end = e.end ? toDate(e.end) : new Date(start.getTime() + 36e5);
3072
+ const start = toDate2(e.start);
3073
+ const end = e.end ? toDate2(e.end) : new Date(start.getTime() + 36e5);
2908
3074
  return { ...e, start, end };
2909
3075
  };
2910
3076
  var Spinner2 = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", className: "h-5 w-5 animate-spin text-accent", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", clipRule: "evenodd", 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" }) });
@@ -3201,7 +3367,7 @@ function EventChip({ event, onSelect }) {
3201
3367
  e.stopPropagation();
3202
3368
  onSelect?.(event);
3203
3369
  },
3204
- title: `${event.title} \xB7 ${timeLabel(event.start)}`,
3370
+ title: `${event.title} \xB7 ${timeLabel2(event.start)}`,
3205
3371
  className: "flex items-center gap-1.5 truncate rounded px-1 py-0.5 text-left text-[11px] font-medium text-foreground hover:opacity-80 focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
3206
3372
  children: [
3207
3373
  /* @__PURE__ */ jsx("span", { className: "h-2 w-2 flex-shrink-0 rounded-full", style: { backgroundColor: color } }),
@@ -3266,7 +3432,7 @@ function WeekView({
3266
3432
  ev.stopPropagation();
3267
3433
  onSelectEvent?.(e);
3268
3434
  },
3269
- title: `${e.title} \xB7 ${timeLabel(e.start)}\u2013${timeLabel(e.end)}`,
3435
+ title: `${e.title} \xB7 ${timeLabel2(e.start)}\u2013${timeLabel2(e.end)}`,
3270
3436
  className: "absolute left-0.5 right-0.5 overflow-hidden rounded-md border px-1.5 py-0.5 text-left text-[11px] leading-tight text-foreground shadow-sm transition-shadow hover:shadow-md focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
3271
3437
  style: {
3272
3438
  top: Math.max(0, top),
@@ -3276,7 +3442,7 @@ function WeekView({
3276
3442
  },
3277
3443
  children: [
3278
3444
  /* @__PURE__ */ jsx("div", { className: "truncate font-medium", children: e.title }),
3279
- /* @__PURE__ */ jsx("div", { className: "truncate", style: { color }, children: timeLabel(e.start) })
3445
+ /* @__PURE__ */ jsx("div", { className: "truncate", style: { color }, children: timeLabel2(e.start) })
3280
3446
  ]
3281
3447
  },
3282
3448
  e.id
@@ -5213,7 +5379,7 @@ function Wizard({
5213
5379
  ] });
5214
5380
  }
5215
5381
  var SearchIcon = /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "w-4 h-4", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M10.5 3.75a6.75 6.75 0 100 13.5 6.75 6.75 0 000-13.5zM2.25 10.5a8.25 8.25 0 1114.59 5.28l4.69 4.69a.75.75 0 11-1.06 1.06l-4.69-4.69A8.25 8.25 0 012.25 10.5z", clipRule: "evenodd" }) });
5216
- var SearchInput = React28.forwardRef(function SearchInput2({ value, onChange, disabled, label, htmlFor, placeholder, name, inputStyle, style, layout = "vertical", size = "md", icon, helperText, className }, ref) {
5382
+ var SearchInput = React29.forwardRef(function SearchInput2({ value, onChange, disabled, label, htmlFor, placeholder, name, inputStyle, style, layout = "vertical", size = "md", icon, helperText, className }, ref) {
5217
5383
  return /* @__PURE__ */ jsx(Field, { className, label, htmlFor, layout, helperText, children: /* @__PURE__ */ jsxs(
5218
5384
  "div",
5219
5385
  {
@@ -5412,7 +5578,7 @@ function TableBody({
5412
5578
  return /* @__PURE__ */ jsx("tbody", { children: rows.map((row, i) => {
5413
5579
  const rowKey = getRowKey(row, i);
5414
5580
  const isExpanded = expanded.has(rowKey);
5415
- return /* @__PURE__ */ jsxs(React28.Fragment, { children: [
5581
+ return /* @__PURE__ */ jsxs(React29.Fragment, { children: [
5416
5582
  /* @__PURE__ */ jsxs(
5417
5583
  "tr",
5418
5584
  {
@@ -5955,8 +6121,8 @@ function MegaMenuLink({ href, icon, description, active, onClick, children, clas
5955
6121
  function MegaMenuFeatured({ children, className = "" }) {
5956
6122
  return /* @__PURE__ */ jsx("div", { className: ["min-w-0 rounded-lg bg-surface-raised border border-border p-4 flex flex-col", className].filter(Boolean).join(" "), children });
5957
6123
  }
5958
- var elementsOfType = (children, type) => React28.Children.toArray(children).filter(
5959
- (c) => React28.isValidElement(c) && c.type === type
6124
+ var elementsOfType = (children, type) => React29.Children.toArray(children).filter(
6125
+ (c) => React29.isValidElement(c) && c.type === type
5960
6126
  );
5961
6127
  var MOBILE_CHEVRON = /* @__PURE__ */ jsx(
5962
6128
  "svg",
@@ -5993,9 +6159,9 @@ function MobileLinkRow({ link, onNavigate }) {
5993
6159
  );
5994
6160
  }
5995
6161
  function MobilePanel({ panel, onNavigate }) {
5996
- const nodes = React28.Children.toArray(panel.props.children);
6162
+ const nodes = React29.Children.toArray(panel.props.children);
5997
6163
  return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4 px-2 pb-3 pt-1", children: nodes.map((node, i) => {
5998
- if (!React28.isValidElement(node)) return null;
6164
+ if (!React29.isValidElement(node)) return null;
5999
6165
  const el = node;
6000
6166
  if (el.type === MegaMenuSection) {
6001
6167
  const { title, children } = el.props;
@@ -6404,7 +6570,7 @@ function ThemeProvider({
6404
6570
  className = "",
6405
6571
  style
6406
6572
  }) {
6407
- const id = React28.useId().replace(/:/g, "");
6573
+ const id = React29.useId().replace(/:/g, "");
6408
6574
  const scopeClass = `geo-th-${id}`;
6409
6575
  const divRef = useRef(null);
6410
6576
  useEffect(() => {
@@ -8546,7 +8712,7 @@ function OtpInput({
8546
8712
  emit(valid.join(""));
8547
8713
  focusBox(valid.length);
8548
8714
  };
8549
- return /* @__PURE__ */ jsx(Field, { className, label, htmlFor, errorId, errorMessage, required, layout, helperText, children: /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": typeof label === "string" ? label : "One-time code", children: chars.map((char, idx) => /* @__PURE__ */ jsxs(React28.Fragment, { children: [
8715
+ return /* @__PURE__ */ jsx(Field, { className, label, htmlFor, errorId, errorMessage, required, layout, helperText, children: /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": typeof label === "string" ? label : "One-time code", children: chars.map((char, idx) => /* @__PURE__ */ jsxs(React29.Fragment, { children: [
8550
8716
  /* @__PURE__ */ jsx(
8551
8717
  "input",
8552
8718
  {
@@ -9236,6 +9402,6 @@ function useJwt(token) {
9236
9402
  return { payload: decoded.payload, header: decoded.header, expiresAt, isExpired, isValid, raw: token ?? null };
9237
9403
  }
9238
9404
 
9239
- export { Accordion_default as Accordion, AppShell, AutoComplete, Avatar, Badge, Box, Breadcrumbs, Button_default as Button, CARD_BRANDS, Calendar2 as Calendar, Card_default as Card, CardCarousel, Cart, CartButton, CartProvider, Catalog, CatalogCarousel, CatalogGrid, Checkbox, Checkout, ColorPicker, ContextMenu, CreditCardForm, DateRangePicker, Drawer, Dropdown, EmptyCart, FAB, FadingBase, Field, FieldHelpIcon, FieldLabel, FileInput, Flex, Form, FormContext, FormField, FormStore, Grid2 as Grid, GridCard, icons_default as Icon, IconButton, Kbd, List2 as List, LoadingSpinner, LogoutTimer, MegaMenu_default as MegaMenu, MenuButton, Modal, NotificationProvider, NumberInput, OpaqueGridCard, OtpInput, Password, PopConfirm, Portal, RadioGroup, Rating, ScalableContainer, Scheduler, SearchInput_default as SearchInput, SecureLayout, SegmentedControl, Sidebar, SkeletonBox, SkeletonCard, SkeletonCircle, SkeletonText, Slider, Statistic, Stepper, Switch, Table, Tabs_default as Tabs, TagsInput, DatePicker as Temporal, TextArea, TextInput, ThemeProvider, ThemeSwitch, TimePicker, Timeline, Tooltip, TooltipProvider, TopBar, Tree, TreeSelect, Typography, Wizard, cardNumberError, cvvError, detectBrand, expiryError, fieldShell, formatCardNumber, formatExpiry, isRequired, luhnValid, onlyDigits, patterns, runFieldRules, useBreakpoint, useCart, useFieldArray, useForm, useFormField, useFormStore, useJwt, useLocalStorage, useMediaQuery, useNotification };
9405
+ export { Accordion_default as Accordion, AppShell, AutoComplete, Avatar, Badge, Box, Breadcrumbs, Button_default as Button, CARD_BRANDS, Calendar2 as Calendar, Card_default as Card, CardCarousel, Cart, CartButton, CartProvider, Catalog, CatalogCarousel, CatalogGrid, Chat, Checkbox, Checkout, ColorPicker, ContextMenu, CreditCardForm, DateRangePicker, Drawer, Dropdown, EmptyCart, FAB, FadingBase, Field, FieldHelpIcon, FieldLabel, FileInput, Flex, Form, FormContext, FormField, FormStore, Grid2 as Grid, GridCard, icons_default as Icon, IconButton, Kbd, List2 as List, LoadingSpinner, LogoutTimer, MegaMenu_default as MegaMenu, MenuButton, Modal, NotificationProvider, NumberInput, OpaqueGridCard, OtpInput, Password, PopConfirm, Portal, RadioGroup, Rating, ScalableContainer, Scheduler, SearchInput_default as SearchInput, SecureLayout, SegmentedControl, Sidebar, SkeletonBox, SkeletonCard, SkeletonCircle, SkeletonText, Slider, Statistic, Stepper, Switch, Table, Tabs_default as Tabs, TagsInput, DatePicker as Temporal, TextArea, TextInput, ThemeProvider, ThemeSwitch, TimePicker, Timeline, Tooltip, TooltipProvider, TopBar, Tree, TreeSelect, Typography, Wizard, cardNumberError, cvvError, detectBrand, expiryError, fieldShell, formatCardNumber, formatExpiry, isRequired, luhnValid, onlyDigits, patterns, runFieldRules, useBreakpoint, useCart, useFieldArray, useForm, useFormField, useFormStore, useJwt, useLocalStorage, useMediaQuery, useNotification };
9240
9406
  //# sourceMappingURL=index.js.map
9241
9407
  //# sourceMappingURL=index.js.map