@almadar/ui 5.30.0 → 5.31.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.
@@ -46,7 +46,6 @@ import { CSS } from '@dnd-kit/utilities';
46
46
  import { useNodeId, ReactFlowProvider, Handle, Position } from '@xyflow/react';
47
47
  import { useUISlots } from '@almadar/ui/context';
48
48
  import { getPatternDefinition as getPatternDefinition$1, getComponentForPattern as getComponentForPattern$1 } from '@almadar/patterns';
49
- import { context, Canvas } from '@react-three/fiber';
50
49
 
51
50
  var __defProp = Object.defineProperty;
52
51
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -2139,6 +2138,8 @@ var init_Input = __esm({
2139
2138
  className,
2140
2139
  inputType,
2141
2140
  type: htmlType,
2141
+ label,
2142
+ helperText,
2142
2143
  error,
2143
2144
  leftIcon,
2144
2145
  rightIcon,
@@ -2194,82 +2195,95 @@ var init_Input = __esm({
2194
2195
  onClear?.();
2195
2196
  }
2196
2197
  };
2198
+ const wrapField = (field) => /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
2199
+ label && /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-foreground mb-1", children: label }),
2200
+ field,
2201
+ (helperText || error) && /* @__PURE__ */ jsx("p", { className: cn("mt-1 text-xs", error ? "text-error" : "text-muted-foreground"), children: error ?? helperText })
2202
+ ] });
2197
2203
  if (type === "select") {
2198
- return /* @__PURE__ */ jsxs("div", { className: "relative w-full", children: [
2199
- resolvedLeftIcon && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none text-muted-foreground", children: resolvedLeftIcon }),
2200
- /* @__PURE__ */ jsxs(
2201
- "select",
2204
+ return wrapField(
2205
+ /* @__PURE__ */ jsxs("div", { className: "relative w-full", children: [
2206
+ resolvedLeftIcon && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none text-muted-foreground", children: resolvedLeftIcon }),
2207
+ /* @__PURE__ */ jsxs(
2208
+ "select",
2209
+ {
2210
+ ref,
2211
+ value,
2212
+ onChange: handleChange,
2213
+ className: cn(baseClassName, "appearance-none pr-10", className),
2214
+ ...props,
2215
+ children: [
2216
+ /* @__PURE__ */ jsx("option", { value: "", children: t("form.selectPlaceholder", { label: "" }) }),
2217
+ options?.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label }, opt.value))
2218
+ ]
2219
+ }
2220
+ ),
2221
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none text-muted-foreground", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-down", className: "h-icon-default w-icon-default" }) })
2222
+ ] })
2223
+ );
2224
+ }
2225
+ if (type === "textarea") {
2226
+ return wrapField(
2227
+ /* @__PURE__ */ jsx("div", { className: "relative w-full", children: /* @__PURE__ */ jsx(
2228
+ "textarea",
2202
2229
  {
2203
2230
  ref,
2204
2231
  value,
2205
2232
  onChange: handleChange,
2206
- className: cn(baseClassName, "appearance-none pr-10", className),
2207
- ...props,
2208
- children: [
2209
- /* @__PURE__ */ jsx("option", { value: "", children: t("form.selectPlaceholder", { label: "" }) }),
2210
- options?.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label }, opt.value))
2211
- ]
2233
+ rows: rows2,
2234
+ className: baseClassName,
2235
+ ...props
2212
2236
  }
2213
- ),
2214
- /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none text-muted-foreground", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-down", className: "h-icon-default w-icon-default" }) })
2215
- ] });
2216
- }
2217
- if (type === "textarea") {
2218
- return /* @__PURE__ */ jsx("div", { className: "relative w-full", children: /* @__PURE__ */ jsx(
2219
- "textarea",
2220
- {
2221
- ref,
2222
- value,
2223
- onChange: handleChange,
2224
- rows: rows2,
2225
- className: baseClassName,
2226
- ...props
2227
- }
2228
- ) });
2237
+ ) })
2238
+ );
2229
2239
  }
2230
2240
  if (type === "checkbox") {
2231
- return /* @__PURE__ */ jsx(
2232
- "input",
2233
- {
2234
- ref,
2235
- type: "checkbox",
2236
- checked: props.checked,
2237
- onChange: handleChange,
2238
- className: cn(
2239
- "h-icon-default w-icon-default rounded-sm",
2240
- "border-border",
2241
- "text-primary focus:ring-ring",
2242
- "disabled:opacity-50 disabled:cursor-not-allowed",
2243
- className
2244
- ),
2245
- ...props
2246
- }
2241
+ return wrapField(
2242
+ /* @__PURE__ */ jsx(
2243
+ "input",
2244
+ {
2245
+ ref,
2246
+ type: "checkbox",
2247
+ checked: props.checked,
2248
+ onChange: handleChange,
2249
+ className: cn(
2250
+ "h-icon-default w-icon-default rounded-sm",
2251
+ "border-border",
2252
+ "text-primary focus:ring-ring",
2253
+ "disabled:opacity-50 disabled:cursor-not-allowed",
2254
+ className
2255
+ ),
2256
+ ...props
2257
+ }
2258
+ )
2247
2259
  );
2248
2260
  }
2249
- return /* @__PURE__ */ jsxs("div", { className: "relative w-full", children: [
2250
- resolvedLeftIcon && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none text-muted-foreground", children: resolvedLeftIcon }),
2251
- /* @__PURE__ */ jsx(
2252
- "input",
2253
- {
2254
- ref,
2255
- type,
2256
- value,
2257
- onChange: handleChange,
2258
- className: baseClassName,
2259
- ...props
2260
- }
2261
- ),
2262
- showClearButton && /* @__PURE__ */ jsx(
2263
- "button",
2264
- {
2265
- type: "button",
2266
- onClick: handleClear,
2267
- className: "absolute inset-y-0 right-0 pr-3 flex items-center text-muted-foreground hover:text-foreground",
2268
- children: /* @__PURE__ */ jsx(Icon, { name: "x", className: "h-icon-default w-icon-default" })
2269
- }
2270
- ),
2271
- rightIcon && !showClearButton && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center text-muted-foreground", children: resolveIconNode(rightIcon, iconCls) })
2272
- ] });
2261
+ return wrapField(
2262
+ /* @__PURE__ */ jsxs("div", { className: "relative w-full", children: [
2263
+ resolvedLeftIcon && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none text-muted-foreground", children: resolvedLeftIcon }),
2264
+ /* @__PURE__ */ jsx(
2265
+ "input",
2266
+ {
2267
+ ref,
2268
+ type,
2269
+ value,
2270
+ onChange: handleChange,
2271
+ className: baseClassName,
2272
+ ...props
2273
+ }
2274
+ ),
2275
+ showClearButton && /* @__PURE__ */ jsx(
2276
+ "button",
2277
+ {
2278
+ type: "button",
2279
+ onClick: handleClear,
2280
+ className: "absolute inset-y-0 right-0 pr-3 flex items-center text-muted-foreground hover:text-foreground",
2281
+ children: /* @__PURE__ */ jsx(Icon, { name: "x", className: "h-icon-default w-icon-default" })
2282
+ }
2283
+ ),
2284
+ rightIcon && !showClearButton && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center text-muted-foreground", children: resolveIconNode(rightIcon, iconCls) })
2285
+ ] })
2286
+ );
2273
2287
  }
2274
2288
  );
2275
2289
  Input.displayName = "Input";
@@ -2340,6 +2354,190 @@ var init_Textarea = __esm({
2340
2354
  Textarea.displayName = "Textarea";
2341
2355
  }
2342
2356
  });
2357
+ function flatOptions(opts, groups) {
2358
+ const flat = opts ?? [];
2359
+ const grp = (groups ?? []).flatMap((g) => g.options);
2360
+ return [...flat, ...grp];
2361
+ }
2362
+ function NativeSelect({
2363
+ className,
2364
+ options,
2365
+ groups,
2366
+ placeholder,
2367
+ error,
2368
+ onChange,
2369
+ value,
2370
+ ...props
2371
+ }) {
2372
+ const eventBus = useEventBus();
2373
+ const handleChange = (e) => {
2374
+ if (typeof onChange === "string") {
2375
+ eventBus.emit(`UI:${onChange}`, { value: e.target.value });
2376
+ } else {
2377
+ onChange?.(e.target.value);
2378
+ }
2379
+ };
2380
+ return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
2381
+ /* @__PURE__ */ jsxs(
2382
+ "select",
2383
+ {
2384
+ onChange: handleChange,
2385
+ value,
2386
+ className: cn(
2387
+ "block w-full border-[length:var(--border-width)] shadow-sm appearance-none",
2388
+ "px-3 py-2 pr-10 text-sm text-foreground font-medium",
2389
+ "bg-card",
2390
+ "focus:outline-none focus:ring-2 focus:ring-offset-0 focus:ring-ring",
2391
+ "disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed",
2392
+ error ? "border-error focus:border-error" : "border-border focus:border-primary",
2393
+ className
2394
+ ),
2395
+ ...props,
2396
+ children: [
2397
+ placeholder && /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: placeholder }),
2398
+ options?.map((option) => /* @__PURE__ */ jsx("option", { value: option.value, disabled: option.disabled, children: option.label }, option.value)),
2399
+ groups?.map((group) => /* @__PURE__ */ jsx("optgroup", { label: group.label, children: group.options.map((option) => /* @__PURE__ */ jsx("option", { value: option.value, disabled: option.disabled, children: option.label }, option.value)) }, group.label))
2400
+ ]
2401
+ }
2402
+ ),
2403
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-down", className: "h-icon-default w-icon-default text-foreground" }) })
2404
+ ] });
2405
+ }
2406
+ function RichSelect({
2407
+ className,
2408
+ options,
2409
+ groups,
2410
+ placeholder,
2411
+ error,
2412
+ onChange,
2413
+ value,
2414
+ multiple,
2415
+ searchable,
2416
+ clearable,
2417
+ disabled
2418
+ }) {
2419
+ const eventBus = useEventBus();
2420
+ const [open, setOpen] = useState(false);
2421
+ const [search, setSearch] = useState("");
2422
+ const containerRef = useRef(null);
2423
+ const selected = multiple ? Array.isArray(value) ? value : value ? [value] : [] : value ? [value] : [];
2424
+ const all = flatOptions(options, groups);
2425
+ const filtered = searchable && search ? all.filter((o) => o.label.toLowerCase().includes(search.toLowerCase())) : all;
2426
+ const toggle = (optValue) => {
2427
+ let next;
2428
+ if (multiple) {
2429
+ next = selected.includes(optValue) ? selected.filter((v) => v !== optValue) : [...selected, optValue];
2430
+ } else {
2431
+ next = optValue;
2432
+ setOpen(false);
2433
+ }
2434
+ if (typeof onChange === "string") {
2435
+ eventBus.emit(`UI:${onChange}`, { value: next });
2436
+ } else {
2437
+ onChange?.(next);
2438
+ }
2439
+ };
2440
+ const clear = (e) => {
2441
+ e.stopPropagation();
2442
+ const next = multiple ? [] : "";
2443
+ if (typeof onChange === "string") {
2444
+ eventBus.emit(`UI:${onChange}`, { value: next });
2445
+ } else {
2446
+ onChange?.(next);
2447
+ }
2448
+ };
2449
+ useEffect(() => {
2450
+ const handler = (e) => {
2451
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
2452
+ setOpen(false);
2453
+ setSearch("");
2454
+ }
2455
+ };
2456
+ document.addEventListener("mousedown", handler);
2457
+ return () => document.removeEventListener("mousedown", handler);
2458
+ }, []);
2459
+ const displayLabel = selected.length === 0 ? placeholder ?? "" : multiple ? `${selected.length} selected` : all.find((o) => o.value === selected[0])?.label ?? selected[0];
2460
+ const hasValue = selected.length > 0;
2461
+ const renderOptions = (opts) => opts.map((opt) => /* @__PURE__ */ jsxs(
2462
+ "button",
2463
+ {
2464
+ type: "button",
2465
+ disabled: opt.disabled,
2466
+ onClick: () => !opt.disabled && toggle(opt.value),
2467
+ className: cn(
2468
+ "w-full flex items-center justify-between px-3 py-1.5 text-sm text-start",
2469
+ "hover:bg-muted transition-colors",
2470
+ "disabled:opacity-50 disabled:cursor-not-allowed",
2471
+ selected.includes(opt.value) && "text-primary font-medium"
2472
+ ),
2473
+ children: [
2474
+ /* @__PURE__ */ jsx("span", { children: opt.label }),
2475
+ selected.includes(opt.value) && /* @__PURE__ */ jsx(Icon, { name: "check", className: "h-icon-default w-icon-default" })
2476
+ ]
2477
+ },
2478
+ opt.value
2479
+ ));
2480
+ return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: cn("relative w-full", className), children: [
2481
+ /* @__PURE__ */ jsx(
2482
+ "button",
2483
+ {
2484
+ type: "button",
2485
+ disabled,
2486
+ onClick: () => !disabled && setOpen((o) => !o),
2487
+ className: cn(
2488
+ "block w-full border-[length:var(--border-width)] shadow-sm",
2489
+ "px-3 py-2 pr-10 text-sm text-start font-medium",
2490
+ "bg-card rounded-sm",
2491
+ "focus:outline-none focus:ring-2 focus:ring-offset-0 focus:ring-ring",
2492
+ "disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed",
2493
+ error ? "border-error focus:border-error" : "border-border focus:border-primary",
2494
+ !hasValue && "text-muted-foreground"
2495
+ ),
2496
+ children: displayLabel
2497
+ }
2498
+ ),
2499
+ /* @__PURE__ */ jsxs("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center gap-1 pointer-events-none", children: [
2500
+ clearable && hasValue && /* @__PURE__ */ jsx(
2501
+ "button",
2502
+ {
2503
+ type: "button",
2504
+ onClick: clear,
2505
+ className: "pointer-events-auto text-muted-foreground hover:text-foreground",
2506
+ children: /* @__PURE__ */ jsx(Icon, { name: "x", className: "h-icon-default w-icon-default" })
2507
+ }
2508
+ ),
2509
+ /* @__PURE__ */ jsx(Icon, { name: "chevron-down", className: "h-icon-default w-icon-default text-foreground" })
2510
+ ] }),
2511
+ open && /* @__PURE__ */ jsxs("div", { className: cn(
2512
+ "absolute z-50 mt-1 w-full",
2513
+ "bg-card border-[length:var(--border-width)] border-border",
2514
+ "rounded-sm shadow-elevation-popover py-1 max-h-60 overflow-y-auto"
2515
+ ), children: [
2516
+ searchable && /* @__PURE__ */ jsx("div", { className: "px-2 pb-1 border-b border-border", children: /* @__PURE__ */ jsx(
2517
+ "input",
2518
+ {
2519
+ autoFocus: true,
2520
+ type: "text",
2521
+ value: search,
2522
+ onChange: (e) => setSearch(e.target.value),
2523
+ placeholder: "Search\u2026",
2524
+ className: cn(
2525
+ "w-full px-2 py-1 text-sm bg-transparent",
2526
+ "focus:outline-none text-foreground placeholder:text-muted-foreground"
2527
+ )
2528
+ }
2529
+ ) }),
2530
+ groups && groups.length > 0 ? groups.map((g) => {
2531
+ const groupFiltered = searchable && search ? g.options.filter((o) => o.label.toLowerCase().includes(search.toLowerCase())) : g.options;
2532
+ if (groupFiltered.length === 0) return null;
2533
+ return /* @__PURE__ */ jsxs("div", { children: [
2534
+ /* @__PURE__ */ jsx("div", { className: "px-3 py-1 text-xs font-semibold text-muted-foreground uppercase tracking-wide", children: g.label }),
2535
+ renderOptions(groupFiltered)
2536
+ ] }, g.label);
2537
+ }) : renderOptions(filtered)
2538
+ ] })
2539
+ ] });
2540
+ }
2343
2541
  var Select;
2344
2542
  var init_Select = __esm({
2345
2543
  "components/core/atoms/Select.tsx"() {
@@ -2347,47 +2545,12 @@ var init_Select = __esm({
2347
2545
  init_Icon();
2348
2546
  init_useEventBus();
2349
2547
  Select = React74__default.forwardRef(
2350
- ({ className, options, placeholder, error, onChange, ...props }, ref) => {
2351
- const eventBus = useEventBus();
2352
- const handleChange = (e) => {
2353
- if (typeof onChange === "string") {
2354
- eventBus.emit(`UI:${onChange}`, { value: e.target.value });
2355
- } else {
2356
- onChange?.(e);
2357
- }
2358
- };
2359
- return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
2360
- /* @__PURE__ */ jsxs(
2361
- "select",
2362
- {
2363
- ref,
2364
- onChange: handleChange,
2365
- className: cn(
2366
- "block w-full border-[length:var(--border-width)] shadow-sm appearance-none",
2367
- "px-3 py-2 pr-10 text-sm text-foreground font-medium",
2368
- "bg-card",
2369
- "focus:outline-none focus:ring-2 focus:ring-offset-0 focus:ring-ring",
2370
- "disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed",
2371
- error ? "border-error focus:border-error" : "border-border focus:border-primary",
2372
- className
2373
- ),
2374
- ...props,
2375
- children: [
2376
- placeholder && /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: placeholder }),
2377
- options.map((option) => /* @__PURE__ */ jsx(
2378
- "option",
2379
- {
2380
- value: option.value,
2381
- disabled: option.disabled,
2382
- children: option.label
2383
- },
2384
- option.value
2385
- ))
2386
- ]
2387
- }
2388
- ),
2389
- /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-down", className: "h-icon-default w-icon-default text-foreground" }) })
2390
- ] });
2548
+ (props, _ref) => {
2549
+ const { multiple, searchable, clearable } = props;
2550
+ if (multiple || searchable || clearable) {
2551
+ return /* @__PURE__ */ jsx(RichSelect, { ...props });
2552
+ }
2553
+ return /* @__PURE__ */ jsx(NativeSelect, { ...props });
2391
2554
  }
2392
2555
  );
2393
2556
  Select.displayName = "Select";
@@ -2441,11 +2604,54 @@ var init_Checkbox = __esm({
2441
2604
  Checkbox.displayName = "Checkbox";
2442
2605
  }
2443
2606
  });
2607
+ var sizeStyles2, Spinner;
2608
+ var init_Spinner = __esm({
2609
+ "components/core/atoms/Spinner.tsx"() {
2610
+ init_cn();
2611
+ init_Icon();
2612
+ sizeStyles2 = {
2613
+ xs: "h-3 w-3",
2614
+ sm: "h-icon-default w-icon-default",
2615
+ md: "h-6 w-6",
2616
+ lg: "h-8 w-8"
2617
+ };
2618
+ Spinner = React74__default.forwardRef(
2619
+ ({ className, size = "md", overlay, ...props }, ref) => {
2620
+ if (overlay) {
2621
+ return /* @__PURE__ */ jsx(
2622
+ "div",
2623
+ {
2624
+ ref,
2625
+ className: cn(
2626
+ "absolute inset-0 z-10 flex items-center justify-center",
2627
+ "bg-background/60 backdrop-blur-sm",
2628
+ className
2629
+ ),
2630
+ ...props,
2631
+ children: /* @__PURE__ */ jsx(Icon, { name: "loader", className: cn("animate-spin text-foreground", sizeStyles2[size]) })
2632
+ }
2633
+ );
2634
+ }
2635
+ return /* @__PURE__ */ jsx(
2636
+ "div",
2637
+ {
2638
+ ref,
2639
+ className: cn("text-foreground", className),
2640
+ ...props,
2641
+ children: /* @__PURE__ */ jsx(Icon, { name: "loader", className: cn("animate-spin", sizeStyles2[size]) })
2642
+ }
2643
+ );
2644
+ }
2645
+ );
2646
+ Spinner.displayName = "Spinner";
2647
+ }
2648
+ });
2444
2649
  var variantStyles2, paddingStyles, shadowStyles, lookStyles, Card, CardHeader, CardTitle, CardContent, CardBody, CardFooter;
2445
2650
  var init_Card = __esm({
2446
2651
  "components/core/atoms/Card.tsx"() {
2447
2652
  init_cn();
2448
2653
  init_useEventBus();
2654
+ init_Spinner();
2449
2655
  variantStyles2 = {
2450
2656
  default: [
2451
2657
  "bg-card",
@@ -2510,6 +2716,7 @@ var init_Card = __esm({
2510
2716
  look = "elevated",
2511
2717
  children,
2512
2718
  action,
2719
+ loading,
2513
2720
  onClick,
2514
2721
  ...props
2515
2722
  }, ref) => {
@@ -2523,7 +2730,7 @@ var init_Card = __esm({
2523
2730
  {
2524
2731
  ref,
2525
2732
  className: cn(
2526
- "rounded-container",
2733
+ "rounded-container relative",
2527
2734
  "transition-all duration-[var(--transition-normal)]",
2528
2735
  variantStyles2[variant],
2529
2736
  paddingStyles[padding],
@@ -2534,6 +2741,7 @@ var init_Card = __esm({
2534
2741
  onClick: handleClick,
2535
2742
  ...props,
2536
2743
  children: [
2744
+ loading && /* @__PURE__ */ jsx(Spinner, { overlay: true, size: "md" }),
2537
2745
  (title || subtitle) && /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
2538
2746
  title && /* @__PURE__ */ jsx("h3", { className: "text-lg text-card-foreground font-bold", children: title }),
2539
2747
  subtitle && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: subtitle })
@@ -2575,7 +2783,7 @@ var init_Card = __esm({
2575
2783
  CardFooter.displayName = "CardFooter";
2576
2784
  }
2577
2785
  });
2578
- var variantStyles3, sizeStyles2, Badge;
2786
+ var variantStyles3, sizeStyles3, Badge;
2579
2787
  var init_Badge = __esm({
2580
2788
  "components/core/atoms/Badge.tsx"() {
2581
2789
  init_cn();
@@ -2612,7 +2820,7 @@ var init_Badge = __esm({
2612
2820
  "border-[length:var(--border-width-thin)] border-border"
2613
2821
  ].join(" ")
2614
2822
  };
2615
- sizeStyles2 = {
2823
+ sizeStyles3 = {
2616
2824
  sm: "px-2 py-0.5 text-xs",
2617
2825
  md: "px-2.5 py-1 text-sm",
2618
2826
  lg: "px-3 py-1.5 text-base"
@@ -2632,7 +2840,7 @@ var init_Badge = __esm({
2632
2840
  className: cn(
2633
2841
  "inline-flex items-center gap-1 font-bold rounded-sm",
2634
2842
  variantStyles3[variant],
2635
- sizeStyles2[size],
2843
+ sizeStyles3[size],
2636
2844
  onRemove && "pr-1",
2637
2845
  className
2638
2846
  ),
@@ -2666,7 +2874,7 @@ var init_Badge = __esm({
2666
2874
  Badge.displayName = "Badge";
2667
2875
  }
2668
2876
  });
2669
- var variantStyles4, sizeStyles3, iconSizes, FilterPill;
2877
+ var variantStyles4, sizeStyles4, iconSizes, FilterPill;
2670
2878
  var init_FilterPill = __esm({
2671
2879
  "components/core/atoms/FilterPill.tsx"() {
2672
2880
  init_cn();
@@ -2700,7 +2908,7 @@ var init_FilterPill = __esm({
2700
2908
  "border-[length:var(--border-width-thin)] border-border"
2701
2909
  ].join(" ")
2702
2910
  };
2703
- sizeStyles3 = {
2911
+ sizeStyles4 = {
2704
2912
  sm: "px-2 py-0.5 text-xs",
2705
2913
  md: "px-2.5 py-1 text-sm",
2706
2914
  lg: "px-3 py-1.5 text-base"
@@ -2744,7 +2952,7 @@ var init_FilterPill = __esm({
2744
2952
  className: cn(
2745
2953
  "inline-flex items-center gap-1 font-bold rounded-pill",
2746
2954
  variantStyles4[variant],
2747
- sizeStyles3[size],
2955
+ sizeStyles4[size],
2748
2956
  (onClick || clickEvent) && "cursor-pointer",
2749
2957
  className
2750
2958
  ),
@@ -2776,33 +2984,6 @@ var init_FilterPill = __esm({
2776
2984
  FilterPill.displayName = "FilterPill";
2777
2985
  }
2778
2986
  });
2779
- var sizeStyles4, Spinner;
2780
- var init_Spinner = __esm({
2781
- "components/core/atoms/Spinner.tsx"() {
2782
- init_cn();
2783
- init_Icon();
2784
- sizeStyles4 = {
2785
- xs: "h-3 w-3",
2786
- sm: "h-icon-default w-icon-default",
2787
- md: "h-6 w-6",
2788
- lg: "h-8 w-8"
2789
- };
2790
- Spinner = React74__default.forwardRef(
2791
- ({ className, size = "md", ...props }, ref) => {
2792
- return /* @__PURE__ */ jsx(
2793
- "div",
2794
- {
2795
- ref,
2796
- className: cn("text-foreground", className),
2797
- ...props,
2798
- children: /* @__PURE__ */ jsx(Icon, { name: "loader", className: cn("animate-spin", sizeStyles4[size]) })
2799
- }
2800
- );
2801
- }
2802
- );
2803
- Spinner.displayName = "Spinner";
2804
- }
2805
- });
2806
2987
  function generateInitials(name) {
2807
2988
  const parts = name.trim().split(/\s+/);
2808
2989
  if (parts.length === 1) {
@@ -15024,30 +15205,30 @@ var init_BranchingLogicBuilder = __esm({
15024
15205
  if (!sourceQuestion?.optionValues) return [];
15025
15206
  return sourceQuestion.optionValues.map((v) => ({ value: v, label: v }));
15026
15207
  }, [sourceQuestion]);
15027
- const handleSource = (e) => {
15028
- onChange({ ...rule, sourceQuestionId: e.target.value });
15208
+ const handleSource = (v) => {
15209
+ onChange({ ...rule, sourceQuestionId: v });
15029
15210
  };
15030
- const handleOperator = (e) => {
15031
- const next = e.target.value;
15211
+ const handleOperator = (v) => {
15212
+ const next = v;
15032
15213
  const nextValue = next === "in" && !Array.isArray(rule.value) ? rule.value ? [rule.value] : [] : next !== "in" && Array.isArray(rule.value) ? rule.value[0] ?? "" : rule.value;
15033
15214
  onChange({ ...rule, operator: next, value: nextValue });
15034
15215
  };
15035
15216
  const handleScalarValue = (e) => {
15036
15217
  onChange({ ...rule, value: e.target.value });
15037
15218
  };
15038
- const handleAddChip = (e) => {
15039
- const v = e.target.value;
15040
- if (!v) return;
15219
+ const handleAddChip = (v) => {
15220
+ const val = v;
15221
+ if (!val) return;
15041
15222
  const current = Array.isArray(rule.value) ? rule.value : [];
15042
- if (current.includes(v)) return;
15043
- onChange({ ...rule, value: [...current, v] });
15223
+ if (current.includes(val)) return;
15224
+ onChange({ ...rule, value: [...current, val] });
15044
15225
  };
15045
15226
  const handleRemoveChip = (chip) => {
15046
15227
  const current = Array.isArray(rule.value) ? rule.value : [];
15047
15228
  onChange({ ...rule, value: current.filter((c) => c !== chip) });
15048
15229
  };
15049
- const handleTarget = (e) => {
15050
- onChange({ ...rule, targetQuestionId: e.target.value });
15230
+ const handleTarget = (v) => {
15231
+ onChange({ ...rule, targetQuestionId: v });
15051
15232
  };
15052
15233
  const isMulti = rule.operator === "in";
15053
15234
  const chips = Array.isArray(rule.value) ? rule.value : [];
@@ -15128,7 +15309,7 @@ var init_BranchingLogicBuilder = __esm({
15128
15309
  options: valueOptions,
15129
15310
  value: scalarValue,
15130
15311
  placeholder: t("branchingLogic.selectValue"),
15131
- onChange: (e) => onChange({ ...rule, value: e.target.value }),
15312
+ onChange: (v) => onChange({ ...rule, value: v }),
15132
15313
  disabled: readOnly
15133
15314
  }
15134
15315
  ) : /* @__PURE__ */ jsx(
@@ -17560,7 +17741,7 @@ var init_Pagination = __esm({
17560
17741
  Select,
17561
17742
  {
17562
17743
  value: String(pageSize),
17563
- onChange: (e) => handlePageSizeChange(Number(e.target.value)),
17744
+ onChange: (v) => handlePageSizeChange(Number(v)),
17564
17745
  options: pageSizeOptions.map((size) => ({
17565
17746
  value: String(size),
17566
17747
  label: String(size)
@@ -20814,7 +20995,9 @@ var init_Menu = __esm({
20814
20995
  trigger,
20815
20996
  items,
20816
20997
  position = "bottom-left",
20817
- className
20998
+ className,
20999
+ header,
21000
+ footer
20818
21001
  }) => {
20819
21002
  const eventBus = useEventBus();
20820
21003
  const { direction } = useTranslate();
@@ -20946,14 +21129,18 @@ var init_Menu = __esm({
20946
21129
  )
20947
21130
  ] }, itemId);
20948
21131
  });
20949
- const panel = isOpen && triggerRect ? /* @__PURE__ */ jsx(
21132
+ const panel = isOpen && triggerRect ? /* @__PURE__ */ jsxs(
20950
21133
  "div",
20951
21134
  {
20952
21135
  ref: menuRef,
20953
21136
  className: cn("fixed z-50", menuContainerStyles, className),
20954
21137
  style: computeMenuStyle(effectivePosition, triggerRect),
20955
21138
  role: "menu",
20956
- children: renderMenuItems(items)
21139
+ children: [
21140
+ header && /* @__PURE__ */ jsx("div", { className: "px-4 py-2 border-b border-border", children: header }),
21141
+ renderMenuItems(items),
21142
+ footer && /* @__PURE__ */ jsx("div", { className: "px-4 py-2 border-t border-border", children: footer })
21143
+ ]
20957
21144
  }
20958
21145
  ) : null;
20959
21146
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -22368,11 +22555,15 @@ function KindSelect({
22368
22555
  function ValueNode({
22369
22556
  value,
22370
22557
  onChange,
22371
- depth
22558
+ depth,
22559
+ readonly
22372
22560
  }) {
22373
22561
  const kind = kindOf(value);
22374
22562
  if (kind === "object" || kind === "array") {
22375
- return /* @__PURE__ */ jsx(ContainerNode, { value, onChange, depth });
22563
+ return /* @__PURE__ */ jsx(ContainerNode, { value, onChange, depth, readonly });
22564
+ }
22565
+ if (readonly) {
22566
+ return /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "font-mono text-foreground", children: value === null ? "null" : String(value) });
22376
22567
  }
22377
22568
  return /* @__PURE__ */ jsx(ScalarControl, { value, onChange });
22378
22569
  }
@@ -22384,15 +22575,19 @@ function Row({
22384
22575
  onValue,
22385
22576
  onRenameKey,
22386
22577
  onChangeKind,
22387
- onRemove
22578
+ onRemove,
22579
+ readonly
22388
22580
  }) {
22389
22581
  const [keyDraft, setKeyDraft] = React74__default.useState(rowKey);
22390
22582
  React74__default.useEffect(() => setKeyDraft(rowKey), [rowKey]);
22391
22583
  const container = isObj(value) || isArr(value);
22392
22584
  return /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "group w-max min-w-full", children: [
22393
22585
  /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", className: "py-0.5 w-max", children: [
22394
- /* @__PURE__ */ jsx(KindSelect, { kind: kindOf(value), onChange: onChangeKind }),
22395
- isArrayItem ? /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", className: "w-6 shrink-0 font-mono", children: rowKey }) : /* @__PURE__ */ jsx("div", { className: "w-20 shrink-0", children: /* @__PURE__ */ jsx(
22586
+ readonly ? /* @__PURE__ */ jsx("span", { className: cn(
22587
+ "h-6 rounded-sm bg-muted text-muted-foreground text-[10px] font-mono px-1 flex items-center",
22588
+ "border-[length:var(--border-width-thin)] border-border"
22589
+ ), children: TYPE_LABEL[kindOf(value)] }) : /* @__PURE__ */ jsx(KindSelect, { kind: kindOf(value), onChange: onChangeKind }),
22590
+ isArrayItem ? /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", className: "w-6 shrink-0 font-mono", children: rowKey }) : readonly ? /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", className: "w-20 shrink-0 font-mono truncate", children: rowKey }) : /* @__PURE__ */ jsx("div", { className: "w-20 shrink-0", children: /* @__PURE__ */ jsx(
22396
22591
  Input,
22397
22592
  {
22398
22593
  inputType: "text",
@@ -22405,8 +22600,8 @@ function Row({
22405
22600
  className: "font-mono"
22406
22601
  }
22407
22602
  ) }),
22408
- !container && /* @__PURE__ */ jsx("div", { className: "w-48 shrink-0", children: /* @__PURE__ */ jsx(ValueNode, { value, onChange: onValue, depth: depth + 1 }) }),
22409
- /* @__PURE__ */ jsx(
22603
+ !container && /* @__PURE__ */ jsx("div", { className: "w-48 shrink-0", children: /* @__PURE__ */ jsx(ValueNode, { value, onChange: onValue, depth: depth + 1, readonly }) }),
22604
+ !readonly && /* @__PURE__ */ jsx(
22410
22605
  Button,
22411
22606
  {
22412
22607
  variant: "ghost",
@@ -22418,13 +22613,14 @@ function Row({
22418
22613
  }
22419
22614
  )
22420
22615
  ] }),
22421
- container && /* @__PURE__ */ jsx("div", { className: "pl-2", children: /* @__PURE__ */ jsx(ValueNode, { value, onChange: onValue, depth: depth + 1 }) })
22616
+ container && /* @__PURE__ */ jsx("div", { className: "pl-2", children: /* @__PURE__ */ jsx(ValueNode, { value, onChange: onValue, depth: depth + 1, readonly }) })
22422
22617
  ] });
22423
22618
  }
22424
22619
  function ContainerNode({
22425
22620
  value,
22426
22621
  onChange,
22427
- depth
22622
+ depth,
22623
+ readonly
22428
22624
  }) {
22429
22625
  const [open, setOpen] = React74__default.useState(depth < 2);
22430
22626
  const array = isArr(value);
@@ -22497,11 +22693,12 @@ function ContainerNode({
22497
22693
  onValue: (next) => array ? setArrValue(idx, next) : setObjValue(k, next),
22498
22694
  onRenameKey: (nk) => renameKey(k, nk),
22499
22695
  onChangeKind: (kind) => array ? changeArrKind(idx, kind) : changeObjKind(k, kind),
22500
- onRemove: () => array ? removeArrIdx(idx) : removeObjKey(k)
22696
+ onRemove: () => array ? removeArrIdx(idx) : removeObjKey(k),
22697
+ readonly
22501
22698
  },
22502
22699
  array ? idx : k
22503
22700
  )),
22504
- /* @__PURE__ */ jsx(
22701
+ !readonly && /* @__PURE__ */ jsx(
22505
22702
  Button,
22506
22703
  {
22507
22704
  variant: "ghost",
@@ -22539,9 +22736,9 @@ var init_JsonTreeEditor = __esm({
22539
22736
  null: "\u2014"
22540
22737
  };
22541
22738
  KIND_OPTIONS = ["string", "number", "boolean", "object", "array"];
22542
- JsonTreeEditor = ({ value, onChange, className }) => {
22739
+ JsonTreeEditor = ({ value, onChange, className, readonly }) => {
22543
22740
  const root = value ?? "";
22544
- return /* @__PURE__ */ jsx("div", { className: cn("w-full overflow-x-auto rounded-sm bg-card/40 p-2 border-[length:var(--border-width-thin)] border-border", className), children: /* @__PURE__ */ jsx(ValueNode, { value: root, onChange, depth: 0 }) });
22741
+ return /* @__PURE__ */ jsx("div", { className: cn("w-full overflow-x-auto rounded-sm bg-card/40 p-2 border-[length:var(--border-width-thin)] border-border", className), children: /* @__PURE__ */ jsx(ValueNode, { value: root, onChange, depth: 0, readonly }) });
22545
22742
  };
22546
22743
  }
22547
22744
  });
@@ -23034,7 +23231,7 @@ function FieldControl({
23034
23231
  {
23035
23232
  options: decl.values.map((v) => ({ value: v, label: v })),
23036
23233
  value: typeof value === "string" ? value : "",
23037
- onChange: (e) => onChange(name, e.target.value)
23234
+ onChange: (v) => onChange(name, v)
23038
23235
  }
23039
23236
  );
23040
23237
  } else if (decl.type === "number") {
@@ -23186,7 +23383,7 @@ var init_NodeSlotEditor = __esm({
23186
23383
  {
23187
23384
  options,
23188
23385
  value: type,
23189
- onChange: (e) => emit(e.target.value, props)
23386
+ onChange: (v) => emit(v, props)
23190
23387
  }
23191
23388
  ),
23192
23389
  type !== "" && /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "pl-1", children: [
@@ -23640,7 +23837,7 @@ var init_FilterGroup = __esm({
23640
23837
  Select,
23641
23838
  {
23642
23839
  value: selectedValues[filter.field] || "all",
23643
- onChange: (e) => handleFilterSelect(filter.field, e.target.value),
23840
+ onChange: (v) => handleFilterSelect(filter.field, v),
23644
23841
  options: [
23645
23842
  { value: "all", label: t("filterGroup.all") },
23646
23843
  ...filter.options?.map((opt) => ({
@@ -23723,7 +23920,7 @@ var init_FilterGroup = __esm({
23723
23920
  Select,
23724
23921
  {
23725
23922
  value: selectedValues[filter.field] || "all",
23726
- onChange: (e) => handleFilterSelect(filter.field, e.target.value),
23923
+ onChange: (v) => handleFilterSelect(filter.field, v),
23727
23924
  options: [
23728
23925
  { value: "all", label: t("filterGroup.allOf", { label: filter.label }) },
23729
23926
  ...filter.options?.map((opt) => ({
@@ -23841,7 +24038,7 @@ var init_FilterGroup = __esm({
23841
24038
  Select,
23842
24039
  {
23843
24040
  value: selectedValues[filter.field] || "all",
23844
- onChange: (e) => handleFilterSelect(filter.field, e.target.value),
24041
+ onChange: (v) => handleFilterSelect(filter.field, v),
23845
24042
  options: [
23846
24043
  { value: "all", label: t("filterGroup.all") },
23847
24044
  ...filter.options?.map((opt) => ({
@@ -28559,13 +28756,13 @@ var init_MapView = __esm({
28559
28756
  shadowSize: [41, 41]
28560
28757
  });
28561
28758
  L.Marker.prototype.options.icon = defaultIcon;
28562
- const { useEffect: useEffect71, useRef: useRef68, useCallback: useCallback114, useState: useState100 } = React74__default;
28759
+ const { useEffect: useEffect72, useRef: useRef69, useCallback: useCallback114, useState: useState101 } = React74__default;
28563
28760
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
28564
28761
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
28565
28762
  function MapUpdater({ centerLat, centerLng, zoom }) {
28566
28763
  const map = useMap();
28567
- const prevRef = useRef68({ centerLat, centerLng, zoom });
28568
- useEffect71(() => {
28764
+ const prevRef = useRef69({ centerLat, centerLng, zoom });
28765
+ useEffect72(() => {
28569
28766
  const prev = prevRef.current;
28570
28767
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
28571
28768
  map.setView([centerLat, centerLng], zoom);
@@ -28576,7 +28773,7 @@ var init_MapView = __esm({
28576
28773
  }
28577
28774
  function MapClickHandler({ onMapClick }) {
28578
28775
  const map = useMap();
28579
- useEffect71(() => {
28776
+ useEffect72(() => {
28580
28777
  if (!onMapClick) return;
28581
28778
  const handler = (e) => {
28582
28779
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -28604,7 +28801,7 @@ var init_MapView = __esm({
28604
28801
  showAttribution = true
28605
28802
  }) {
28606
28803
  const eventBus = useEventBus2();
28607
- const [clickedPosition, setClickedPosition] = useState100(null);
28804
+ const [clickedPosition, setClickedPosition] = useState101(null);
28608
28805
  const handleMapClick = useCallback114((lat, lng) => {
28609
28806
  if (showClickedPin) {
28610
28807
  setClickedPosition({ lat, lng });
@@ -34040,8 +34237,8 @@ var init_VersionDiff = __esm({
34040
34237
  return { added, removed };
34041
34238
  }, [diff]);
34042
34239
  const handleBeforeChange = useCallback(
34043
- (e) => {
34044
- const id = e.target.value;
34240
+ (v) => {
34241
+ const id = v;
34045
34242
  setInternalBefore(id);
34046
34243
  onSelectBefore?.(id);
34047
34244
  if (selectBeforeEvent) eventBus.emit(`UI:${selectBeforeEvent}`, { id });
@@ -34049,8 +34246,8 @@ var init_VersionDiff = __esm({
34049
34246
  [onSelectBefore, selectBeforeEvent, eventBus]
34050
34247
  );
34051
34248
  const handleAfterChange = useCallback(
34052
- (e) => {
34053
- const id = e.target.value;
34249
+ (v) => {
34250
+ const id = v;
34054
34251
  setInternalAfter(id);
34055
34252
  onSelectAfter?.(id);
34056
34253
  if (selectAfterEvent) eventBus.emit(`UI:${selectAfterEvent}`, { id });
@@ -38896,11 +39093,11 @@ function RuleEditor({
38896
39093
  className
38897
39094
  }) {
38898
39095
  const { t } = useTranslate();
38899
- const handleWhenChange = useCallback((e) => {
38900
- onChange({ ...rule, whenEvent: e.target.value });
39096
+ const handleWhenChange = useCallback((v) => {
39097
+ onChange({ ...rule, whenEvent: v });
38901
39098
  }, [rule, onChange]);
38902
- const handleThenChange = useCallback((e) => {
38903
- onChange({ ...rule, thenAction: e.target.value });
39099
+ const handleThenChange = useCallback((v) => {
39100
+ onChange({ ...rule, thenAction: v });
38904
39101
  }, [rule, onChange]);
38905
39102
  return /* @__PURE__ */ jsxs(HStack, { className: cn("items-center p-2 rounded-lg bg-muted/50 border border-border", className), gap: "sm", children: [
38906
39103
  /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-primary font-bold whitespace-nowrap", children: t("eventHandler.when") }),
@@ -39976,7 +40173,7 @@ var init_Form = __esm({
39976
40173
  ...commonProps,
39977
40174
  options,
39978
40175
  value: String(currentValue2),
39979
- onChange: (e) => handleChange(fieldName, e.target.value),
40176
+ onChange: (v) => handleChange(fieldName, v),
39980
40177
  placeholder: field.placeholder || `Select ${label}...`
39981
40178
  }
39982
40179
  );
@@ -47215,18 +47412,32 @@ var init_XPBar = __esm({
47215
47412
  }
47216
47413
  });
47217
47414
  function lazyThree(name, loader) {
47218
- const Lazy = React74__default.lazy(() => loader().then((m) => ({ default: m[name] })));
47415
+ const Lazy = React74__default.lazy(
47416
+ () => loader().then((m) => {
47417
+ const Resolved = m[name];
47418
+ if (!Resolved) {
47419
+ throw new Error(
47420
+ `[@almadar/ui] 3D component "${name}" was not found in the three subpath bundle.`
47421
+ );
47422
+ }
47423
+ return { default: Resolved };
47424
+ })
47425
+ );
47219
47426
  function ThreeWrapper(props) {
47220
47427
  return React74__default.createElement(
47221
- React74__default.Suspense,
47222
- { fallback: null },
47223
- React74__default.createElement(Lazy, props)
47428
+ ThreeBoundary,
47429
+ { name },
47430
+ React74__default.createElement(
47431
+ React74__default.Suspense,
47432
+ { fallback: null },
47433
+ React74__default.createElement(Lazy, props)
47434
+ )
47224
47435
  );
47225
47436
  }
47226
47437
  ThreeWrapper.displayName = `Lazy(${name})`;
47227
47438
  return ThreeWrapper;
47228
47439
  }
47229
- var FeatureRenderer, GameCanvas3D, GameCanvas3DBattleTemplate, GameCanvas3DCastleTemplate, GameCanvas3DWorldMapTemplate, COMPONENT_REGISTRY;
47440
+ var ThreeBoundary, FeatureRenderer, GameCanvas3D, GameCanvas3DBattleTemplate, GameCanvas3DCastleTemplate, GameCanvas3DWorldMapTemplate, COMPONENT_REGISTRY;
47230
47441
  var init_component_registry_generated = __esm({
47231
47442
  "components/core/organisms/component-registry.generated.ts"() {
47232
47443
  init_AboutPageTemplate();
@@ -47512,6 +47723,28 @@ var init_component_registry_generated = __esm({
47512
47723
  init_WorldMapBoard();
47513
47724
  init_WorldMapTemplate();
47514
47725
  init_XPBar();
47726
+ ThreeBoundary = class extends React74__default.Component {
47727
+ constructor() {
47728
+ super(...arguments);
47729
+ __publicField(this, "state", { failed: false });
47730
+ }
47731
+ static getDerivedStateFromError() {
47732
+ return { failed: true };
47733
+ }
47734
+ render() {
47735
+ if (this.state.failed) {
47736
+ return React74__default.createElement(
47737
+ "div",
47738
+ {
47739
+ "data-testid": "three-unavailable",
47740
+ style: { padding: 16, fontSize: 13, lineHeight: 1.5, opacity: 0.7 }
47741
+ },
47742
+ `3D pattern "${this.props.name}" requires three.js. Install the optional peers three + @react-three/fiber + @react-three/drei (matching the host React major) to render it.`
47743
+ );
47744
+ }
47745
+ return this.props.children;
47746
+ }
47747
+ };
47515
47748
  FeatureRenderer = lazyThree("FeatureRenderer", () => import('@almadar/ui/components/molecules/game/three'));
47516
47749
  GameCanvas3D = lazyThree("GameCanvas3D", () => import('@almadar/ui/components/molecules/game/three'));
47517
47750
  GameCanvas3DBattleTemplate = lazyThree("GameCanvas3DBattleTemplate", () => import('@almadar/ui/components/molecules/game/three'));
@@ -49794,195 +50027,6 @@ init_StepFlowOrganism();
49794
50027
  init_ShowcaseOrganism();
49795
50028
  init_TeamOrganism();
49796
50029
  init_CaseStudyOrganism();
49797
- var DEFAULT_FEATURE_CONFIGS = {
49798
- tree: { color: 2263842, height: 1.5, scale: 1, geometry: "tree" },
49799
- rock: { color: 8421504, height: 0.5, scale: 0.8, geometry: "rock" },
49800
- bush: { color: 3329330, height: 0.4, scale: 0.6, geometry: "bush" },
49801
- house: { color: 9127187, height: 1.2, scale: 1.2, geometry: "house" },
49802
- tower: { color: 6908265, height: 2.5, scale: 1, geometry: "tower" },
49803
- wall: { color: 8421504, height: 1, scale: 1, geometry: "wall" },
49804
- mountain: { color: 5597999, height: 2, scale: 1.5, geometry: "mountain" },
49805
- hill: { color: 7048739, height: 0.8, scale: 1.2, geometry: "hill" },
49806
- water: { color: 4491468, height: 0.1, scale: 1, geometry: "water" },
49807
- chest: { color: 16766720, height: 0.3, scale: 0.4, geometry: "chest" },
49808
- sign: { color: 9127187, height: 0.8, scale: 0.3, geometry: "sign" },
49809
- portal: { color: 10040012, height: 1.5, scale: 1, geometry: "portal" }
49810
- };
49811
- function TreeFeature({ height, color }) {
49812
- return /* @__PURE__ */ jsxs(Fragment, { children: [
49813
- /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.3, 0], children: [
49814
- /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.08, 0.1, height * 0.6, 6] }),
49815
- /* @__PURE__ */ jsx("meshStandardMaterial", { color: 9127187 })
49816
- ] }),
49817
- /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.7, 0], children: [
49818
- /* @__PURE__ */ jsx("coneGeometry", { args: [0.4, height * 0.5, 8] }),
49819
- /* @__PURE__ */ jsx("meshStandardMaterial", { color })
49820
- ] }),
49821
- /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.9, 0], children: [
49822
- /* @__PURE__ */ jsx("coneGeometry", { args: [0.3, height * 0.4, 8] }),
49823
- /* @__PURE__ */ jsx("meshStandardMaterial", { color })
49824
- ] }),
49825
- /* @__PURE__ */ jsxs("mesh", { position: [0, height * 1.05, 0], children: [
49826
- /* @__PURE__ */ jsx("coneGeometry", { args: [0.15, height * 0.25, 8] }),
49827
- /* @__PURE__ */ jsx("meshStandardMaterial", { color })
49828
- ] })
49829
- ] });
49830
- }
49831
- function RockFeature({ height, color }) {
49832
- return /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.4, 0], children: [
49833
- /* @__PURE__ */ jsx("dodecahedronGeometry", { args: [height * 0.5, 0] }),
49834
- /* @__PURE__ */ jsx("meshStandardMaterial", { color, roughness: 0.9 })
49835
- ] });
49836
- }
49837
- function BushFeature({ height, color }) {
49838
- return /* @__PURE__ */ jsxs(Fragment, { children: [
49839
- /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.3, 0], children: [
49840
- /* @__PURE__ */ jsx("sphereGeometry", { args: [height * 0.4, 8, 8] }),
49841
- /* @__PURE__ */ jsx("meshStandardMaterial", { color })
49842
- ] }),
49843
- /* @__PURE__ */ jsxs("mesh", { position: [0.1, height * 0.4, 0.1], children: [
49844
- /* @__PURE__ */ jsx("sphereGeometry", { args: [height * 0.25, 8, 8] }),
49845
- /* @__PURE__ */ jsx("meshStandardMaterial", { color })
49846
- ] })
49847
- ] });
49848
- }
49849
- function HouseFeature({ height, color }) {
49850
- return /* @__PURE__ */ jsxs(Fragment, { children: [
49851
- /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.4, 0], children: [
49852
- /* @__PURE__ */ jsx("boxGeometry", { args: [0.8, height * 0.8, 0.8] }),
49853
- /* @__PURE__ */ jsx("meshStandardMaterial", { color: 13808780 })
49854
- ] }),
49855
- /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.9, 0], children: [
49856
- /* @__PURE__ */ jsx("coneGeometry", { args: [0.6, height * 0.4, 4] }),
49857
- /* @__PURE__ */ jsx("meshStandardMaterial", { color })
49858
- ] }),
49859
- /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.25, 0.41], children: [
49860
- /* @__PURE__ */ jsx("planeGeometry", { args: [0.25, height * 0.5] }),
49861
- /* @__PURE__ */ jsx("meshStandardMaterial", { color: 4863784 })
49862
- ] })
49863
- ] });
49864
- }
49865
- function TowerFeature({ height, color }) {
49866
- return /* @__PURE__ */ jsxs(Fragment, { children: [
49867
- /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.5, 0], children: [
49868
- /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.3, 0.35, height, 8] }),
49869
- /* @__PURE__ */ jsx("meshStandardMaterial", { color })
49870
- ] }),
49871
- /* @__PURE__ */ jsxs("mesh", { position: [0, height + 0.05, 0], children: [
49872
- /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.35, 0.35, 0.1, 8] }),
49873
- /* @__PURE__ */ jsx("meshStandardMaterial", { color })
49874
- ] })
49875
- ] });
49876
- }
49877
- function ChestFeature({ height, color }) {
49878
- return /* @__PURE__ */ jsxs(Fragment, { children: [
49879
- /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.5, 0], children: [
49880
- /* @__PURE__ */ jsx("boxGeometry", { args: [0.3, height, 0.2] }),
49881
- /* @__PURE__ */ jsx("meshStandardMaterial", { color, metalness: 0.6, roughness: 0.3 })
49882
- ] }),
49883
- /* @__PURE__ */ jsxs("mesh", { position: [0, height + 0.05, 0], children: [
49884
- /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.15, 0.15, 0.3, 8, 1, false, 0, Math.PI] }),
49885
- /* @__PURE__ */ jsx("meshStandardMaterial", { color, metalness: 0.6, roughness: 0.3 })
49886
- ] })
49887
- ] });
49888
- }
49889
- function DefaultFeature({ height, color }) {
49890
- return /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.5, 0], children: [
49891
- /* @__PURE__ */ jsx("boxGeometry", { args: [0.5, height, 0.5] }),
49892
- /* @__PURE__ */ jsx("meshStandardMaterial", { color })
49893
- ] });
49894
- }
49895
- function FeatureVisual({
49896
- feature,
49897
- position,
49898
- isSelected,
49899
- onClick,
49900
- onHover
49901
- }) {
49902
- const config = DEFAULT_FEATURE_CONFIGS[feature.type] || {
49903
- color: 8947848,
49904
- height: 0.5,
49905
- scale: 1,
49906
- geometry: "default"
49907
- };
49908
- const color = feature.color ? parseInt(feature.color.replace("#", ""), 16) : config.color;
49909
- const renderGeometry = () => {
49910
- switch (config.geometry) {
49911
- case "tree":
49912
- return /* @__PURE__ */ jsx(TreeFeature, { height: config.height, color });
49913
- case "rock":
49914
- return /* @__PURE__ */ jsx(RockFeature, { height: config.height, color });
49915
- case "bush":
49916
- return /* @__PURE__ */ jsx(BushFeature, { height: config.height, color });
49917
- case "house":
49918
- return /* @__PURE__ */ jsx(HouseFeature, { height: config.height, color });
49919
- case "tower":
49920
- return /* @__PURE__ */ jsx(TowerFeature, { height: config.height, color });
49921
- case "chest":
49922
- return /* @__PURE__ */ jsx(ChestFeature, { height: config.height, color });
49923
- default:
49924
- return /* @__PURE__ */ jsx(DefaultFeature, { height: config.height, color });
49925
- }
49926
- };
49927
- return /* @__PURE__ */ jsxs(
49928
- "group",
49929
- {
49930
- position,
49931
- scale: config.scale,
49932
- onClick,
49933
- onPointerEnter: () => onHover(true),
49934
- onPointerLeave: () => onHover(false),
49935
- userData: { type: "feature", featureId: feature.id, featureType: feature.type },
49936
- children: [
49937
- isSelected && /* @__PURE__ */ jsxs("mesh", { position: [0, 0.02, 0], rotation: [-Math.PI / 2, 0, 0], children: [
49938
- /* @__PURE__ */ jsx("ringGeometry", { args: [0.4, 0.5, 32] }),
49939
- /* @__PURE__ */ jsx("meshBasicMaterial", { color: "#ffff00", transparent: true, opacity: 0.8 })
49940
- ] }),
49941
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.01, 0], rotation: [-Math.PI / 2, 0, 0], children: [
49942
- /* @__PURE__ */ jsx("circleGeometry", { args: [0.35, 16] }),
49943
- /* @__PURE__ */ jsx("meshBasicMaterial", { color: "#000000", transparent: true, opacity: 0.2 })
49944
- ] }),
49945
- renderGeometry()
49946
- ]
49947
- }
49948
- );
49949
- }
49950
- function FeatureGroup({
49951
- features,
49952
- cellSize = 1,
49953
- offsetX = 0,
49954
- offsetZ = 0,
49955
- onFeatureClick,
49956
- onFeatureHover,
49957
- selectedFeatureIds = []
49958
- }) {
49959
- return /* @__PURE__ */ jsx("group", { children: features.map((feature) => {
49960
- const x = (feature.x - offsetX) * cellSize;
49961
- const z = ((feature.z ?? feature.y ?? 0) - offsetZ) * cellSize;
49962
- const y = (feature.elevation ?? 0) * 0.1;
49963
- const isSelected = feature.id ? selectedFeatureIds.includes(feature.id) : false;
49964
- return /* @__PURE__ */ jsx(
49965
- FeatureVisual,
49966
- {
49967
- feature,
49968
- position: [x, y, z],
49969
- isSelected,
49970
- onClick: () => onFeatureClick?.(feature),
49971
- onHover: (hovered) => onFeatureHover?.(hovered ? feature : null)
49972
- },
49973
- feature.id ?? `feature-${feature.x}-${feature.y}`
49974
- );
49975
- }) });
49976
- }
49977
- function FeatureRenderer2(props) {
49978
- const insideCanvas = useContext(context) != null;
49979
- if (insideCanvas) return /* @__PURE__ */ jsx(FeatureGroup, { ...props });
49980
- return /* @__PURE__ */ jsxs(Canvas, { camera: { position: [4, 4, 6], fov: 50 }, style: { width: "100%", height: 360 }, children: [
49981
- /* @__PURE__ */ jsx("ambientLight", { intensity: 0.6 }),
49982
- /* @__PURE__ */ jsx("directionalLight", { position: [5, 8, 5], intensity: 0.8 }),
49983
- /* @__PURE__ */ jsx(FeatureGroup, { ...props })
49984
- ] });
49985
- }
49986
50030
 
49987
50031
  // components/core/templates/index.ts
49988
50032
  init_DashboardLayout();
@@ -50002,4 +50046,4 @@ init_AboutPageTemplate();
50002
50046
  // components/index.ts
50003
50047
  init_cn();
50004
50048
 
50005
- export { ALL_PRESETS, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, ActionButtons, Card2 as ActionCard, ActionPalette, ActionTile, Alert, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AuthLayout, Avatar, Badge, BattleBoard, BattleTemplate, BehaviorView, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, BuilderBoard, Button, ButtonGroup, CTABanner, CalendarGrid, CanvasEffect, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, CastleBoard, CastleTemplate, Center, Chart, ChartLegend, Checkbox, ChoiceButton, ClassifierBoard, Coachmark, CodeBlock, CollapsibleSection, CombatLog, ComboCounter, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, Container, ContentRenderer, ContentSection, ControlButton, CounterTemplate, CraftingRecipe, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DIAMOND_TOP_Y, DPad, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DebuggerBoard, DetailPanel, Dialog, DialogueBox, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EnemyPlate, EntityDisplayEvents, ErrorBoundary, ErrorState, EventHandlerBoard, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FeatureRenderer2 as FeatureRenderer, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCanvas2D, GameHud, GameMenu, GameOverScreen, GameShell, GameTemplate, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HealthPanel, HeroOrganism, HeroSection, IDENTITY_BOOK_FIELDS, Icon, IconPicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, InventoryPanel, IsometricCanvas, ItemSlot, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MatrixQuestion, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, ModuleCard, Navigation, NegotiatorBoard, NodeSlotEditor, NotifyListener, NumberStepper, ObjectRulePanel, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PatternTile, PhysicsManager, PlatformerCanvas, Popover, PositionedCanvas, PowerupSlots, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuestTracker, QuizBlock, Radio, RangeSlider, RelationSelect, RepeatableFormSection, ReplyTree, ResourceBar, ResourceCounter, RichBlockEditor, RuleEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreBoard, ScoreDisplay, SearchInput, Section, SectionHeader, Select, SequenceBar, SequencerBoard, ServiceCatalog, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulationCanvas, SimulationControls, SimulationGraph, SimulatorBoard, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateArchitectBoard, StateIndicator, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StatusEffect, StepFlow, StepFlowOrganism, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeSelector, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TurnPanel, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UncontrolledBattleBoard, UnitCommandBar, UploadDropZone, VStack, VariablePanel, VersionDiff, ViolationAlert, VoteStack, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, WorldMapBoard, WorldMapTemplate, XPBar, applyTemporaryEffect, calculateAttackTargets, calculateDamage, calculateValidMoves, cn, combatAnimations, combatClasses, combatEffects, createInitialGameState, createUnitAnimationState, drawSprite, generateCombatMessage, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, mapBookData, pendulum, projectileMotion, resolveFieldMap, resolveFrame, resolveSheetDirection, screenToIso, springOscillator, tickAnimationState, toCodeLanguage, transitionAnimation, useAnchorRect, useBattleState, useCamera, useGameAudio, useGameAudioContext, useImageCache, usePhysics2D, useSpriteAnimations };
50049
+ export { ALL_PRESETS, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, ActionButtons, Card2 as ActionCard, ActionPalette, ActionTile, Alert, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AuthLayout, Avatar, Badge, BattleBoard, BattleTemplate, BehaviorView, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, BuilderBoard, Button, ButtonGroup, CTABanner, CalendarGrid, CanvasEffect, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, CastleBoard, CastleTemplate, Center, Chart, ChartLegend, Checkbox, ChoiceButton, ClassifierBoard, Coachmark, CodeBlock, CollapsibleSection, CombatLog, ComboCounter, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, Container, ContentRenderer, ContentSection, ControlButton, CounterTemplate, CraftingRecipe, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DIAMOND_TOP_Y, DPad, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DebuggerBoard, DetailPanel, Dialog, DialogueBox, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EnemyPlate, EntityDisplayEvents, ErrorBoundary, ErrorState, EventHandlerBoard, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCanvas2D, GameHud, GameMenu, GameOverScreen, GameShell, GameTemplate, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HealthPanel, HeroOrganism, HeroSection, IDENTITY_BOOK_FIELDS, Icon, IconPicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, InventoryPanel, IsometricCanvas, ItemSlot, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MatrixQuestion, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, ModuleCard, Navigation, NegotiatorBoard, NodeSlotEditor, NotifyListener, NumberStepper, ObjectRulePanel, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PatternTile, PhysicsManager, PlatformerCanvas, Popover, PositionedCanvas, PowerupSlots, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuestTracker, QuizBlock, Radio, RangeSlider, RelationSelect, RepeatableFormSection, ReplyTree, ResourceBar, ResourceCounter, RichBlockEditor, RuleEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreBoard, ScoreDisplay, SearchInput, Section, SectionHeader, Select, SequenceBar, SequencerBoard, ServiceCatalog, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulationCanvas, SimulationControls, SimulationGraph, SimulatorBoard, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateArchitectBoard, StateIndicator, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StatusEffect, StepFlow, StepFlowOrganism, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeSelector, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TurnPanel, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UncontrolledBattleBoard, UnitCommandBar, UploadDropZone, VStack, VariablePanel, VersionDiff, ViolationAlert, VoteStack, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, WorldMapBoard, WorldMapTemplate, XPBar, applyTemporaryEffect, calculateAttackTargets, calculateDamage, calculateValidMoves, cn, combatAnimations, combatClasses, combatEffects, createInitialGameState, createUnitAnimationState, drawSprite, generateCombatMessage, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, mapBookData, pendulum, projectileMotion, resolveFieldMap, resolveFrame, resolveSheetDirection, screenToIso, springOscillator, tickAnimationState, toCodeLanguage, transitionAnimation, useAnchorRect, useBattleState, useCamera, useGameAudio, useGameAudioContext, useImageCache, usePhysics2D, useSpriteAnimations };