@almadar/ui 6.1.0 → 6.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,13 @@
1
1
  import * as React$1 from 'react';
2
2
  import React__default, { ReactNode, ErrorInfo } from 'react';
3
- import { Asset, EventKey, EventPayload, EventEmit, AssetUrl, JsonObject, EntityRow, FieldValue, EntityRole, AnimationName, SpriteDirection, AnimationDef, ScenePos, Camera, EntityWith, TraitConfigValue, JsonValue, AssetCatalog, EventPayloadValue, DeclaredTraitConfig, TraitConfig, OrbitalSchema, Trait, OrbitalEntity, FormSubmitPayload, ControlValue, UISlot, EditFocus, TraceSubagent, TraceActivity, TraceChatMessage } from '@almadar/core';
3
+ import { Asset, EventKey, EventPayload, EventEmit, AssetUrl, FieldValue, EntityRow, EntityRole, AnimationName, SpriteDirection, AnimationDef, ScenePos, Camera, EntityWith, TraitConfigValue, JsonValue, AssetCatalog, JsonObject, EventPayloadValue, DeclaredTraitConfig, TraitConfig, ControlValue, OrbitalSchema, Trait, OrbitalEntity, FormSubmitPayload, UISlot, EditFocus, TraceSubagent, TraceActivity, TraceChatMessage } from '@almadar/core';
4
4
  export { AnimationDef, AnimationName, BusEvent, BusEventListener, BusEventSource, BusEventListener as EventListener, SpriteDirection, UISlot, Unsubscribe } from '@almadar/core';
5
5
  import { LucideIcon } from 'lucide-react';
6
6
  import { C as ColorToken, U as UiError, P as Point, L as LinkAction, I as ImageSource } from '../types-B3nHgnMG.js';
7
7
  export { R as Rect } from '../types-B3nHgnMG.js';
8
8
  import { SExpr } from '@almadar/evaluator';
9
- import { U as UnitAnimationState, F as FacingDirection, S as SpriteSheetUrls, g as SpriteFrameDims, R as ResolvedFrame, h as CanvasLighting, i as CanvasPost, a as IsometricUnit, j as CameraState, k as FieldInfo, l as OrbitalTraitInfo, m as OrbitalPageInfo, T as TraitLevelData, E as ExternalLink } from '../avl-schema-parser-BKbH_SFt.js';
10
- export { B as BoardTile, G as GameAction, n as GamePhase, o as GameState, p as GameUnit, b as IsometricFeature, I as IsometricTile, P as Position, q as UnitTrait, r as calculateAttackTargets, s as calculateValidMoves, t as createInitialGameState } from '../avl-schema-parser-BKbH_SFt.js';
9
+ import { U as UnitAnimationState, F as FacingDirection, S as SpriteSheetUrls, g as SpriteFrameDims, R as ResolvedFrame, h as CanvasLighting, i as CanvasPost, a as IsometricUnit, j as CameraState, k as FieldInfo, l as OrbitalTraitInfo, m as OrbitalPageInfo, T as TraitLevelData, E as ExternalLink } from '../avl-schema-parser-dvJKXn-o.js';
10
+ export { B as BoardTile, G as GameAction, n as GamePhase, o as GameState, p as GameUnit, b as IsometricFeature, I as IsometricTile, P as Position, q as UnitTrait, r as calculateAttackTargets, s as calculateValidMoves, t as createInitialGameState } from '../avl-schema-parser-dvJKXn-o.js';
11
11
  import { D as DrawableNode, P as Projector, F as FxOverlayItem, M as MeshShapeKind, a as MeshMaterial, b as DrawGroupProps, c as DrawTextProps, d as DrawMeshProps } from '../paintDispatch-B5ObLnUv.js';
12
12
  export { e as FxOverlayKind } from '../paintDispatch-B5ObLnUv.js';
13
13
  export { A as AudioManifest, G as GameAudioContext, a as GameAudioContextValue, e as GameAudioControls, b as GameAudioProvider, c as GameAudioProviderProps, S as SoundEntry, U as UseGameAudioOptions, f as useGameAudio, u as useGameAudioContext } from '../GameAudioProvider-B48iXwz3.js';
@@ -314,9 +314,11 @@ interface InputProps extends Omit<React__default.InputHTMLAttributes<HTMLInputEl
314
314
  value?: string | number;
315
315
  /** Whether input is disabled */
316
316
  disabled?: boolean;
317
- /** Declarative event name for trait dispatch */
317
+ /** Declarative event name for trait dispatch.
318
+ * @payloadTypeWhen value inputType=number->number
319
+ */
318
320
  action?: EventEmit<{
319
- value: string;
321
+ value: string | number;
320
322
  }>;
321
323
  /**
322
324
  * Input type — selects the field's data mode. Use 'password' for masked
@@ -406,8 +408,10 @@ interface SelectProps extends Omit<React__default.SelectHTMLAttributes<HTMLSelec
406
408
  placeholder?: string;
407
409
  /** Current value (string for single, string[] for multiple) */
408
410
  value?: string | string[];
409
- /** Declarative event name for trait dispatch */
410
- action?: EventKey;
411
+ /** Declarative event name for trait dispatch — emits `{ value }` on selection commit (same gestures as `onChange`). */
412
+ action?: EventEmit<{
413
+ value: string | string[];
414
+ }>;
411
415
  /** Error message */
412
416
  error?: string;
413
417
  /** Allow selecting multiple values — activates the rich dropdown. */
@@ -1360,10 +1364,10 @@ declare const Aside: React__default.ForwardRefExoticComponent<AsideProps & React
1360
1364
  * Context for conditional evaluation
1361
1365
  */
1362
1366
  type ConditionalContext = {
1363
- formValues: JsonObject;
1364
- globalVariables: JsonObject;
1365
- localVariables?: JsonObject;
1366
- entity?: JsonObject;
1367
+ formValues: Record<string, FieldValue>;
1368
+ globalVariables: Record<string, FieldValue>;
1369
+ localVariables?: Record<string, FieldValue>;
1370
+ entity?: Record<string, FieldValue>;
1367
1371
  };
1368
1372
  interface ConditionalWrapperProps {
1369
1373
  /** The S-expression condition to evaluate */
@@ -10031,38 +10035,38 @@ interface WizardField {
10031
10035
  label: string;
10032
10036
  isDefault?: boolean;
10033
10037
  }>;
10034
- defaultValue?: JsonValue;
10035
- condition?: JsonValue[];
10038
+ defaultValue?: ControlValue;
10039
+ condition?: SExpr;
10036
10040
  placeholder?: string;
10037
10041
  entityField?: string;
10038
10042
  minLength?: number;
10039
10043
  maxLength?: number;
10040
- dataSource?: JsonObject;
10044
+ dataSource?: Record<string, FieldValue>;
10041
10045
  displayFields?: string[];
10042
- searchConfig?: JsonObject;
10046
+ searchConfig?: Record<string, FieldValue>;
10043
10047
  hiddenCalculations?: Array<{
10044
10048
  variable: string;
10045
10049
  expression: string;
10046
10050
  scope?: string;
10047
10051
  }>;
10048
- signatureConfig?: JsonObject;
10049
- displayTemplate?: JsonObject;
10050
- lawReference?: JsonObject;
10052
+ signatureConfig?: Record<string, FieldValue>;
10053
+ displayTemplate?: Record<string, FieldValue>;
10054
+ lawReference?: Record<string, FieldValue>;
10051
10055
  contextMenu?: string[];
10052
- calculated?: JsonObject;
10056
+ calculated?: Record<string, FieldValue>;
10053
10057
  readOnly?: boolean;
10054
- minDate?: JsonValue;
10058
+ minDate?: string;
10055
10059
  stats?: Array<{
10056
10060
  label: string;
10057
- value: JsonValue;
10061
+ value: ControlValue;
10058
10062
  icon?: string;
10059
10063
  }>;
10060
10064
  items?: Array<{
10061
10065
  id: string;
10062
10066
  label: string;
10063
- autoCheck?: JsonValue;
10067
+ autoCheck?: boolean;
10064
10068
  }>;
10065
- [key: string]: JsonValue | undefined;
10069
+ [key: string]: JsonValue | SExpr | ControlValue | Record<string, FieldValue> | undefined;
10066
10070
  }
10067
10071
  /** Section within a wizard step */
10068
10072
  interface WizardSection {
@@ -10071,7 +10075,7 @@ interface WizardSection {
10071
10075
  description?: string;
10072
10076
  fields?: WizardField[];
10073
10077
  subsections?: WizardSection[];
10074
- condition?: JsonValue[];
10078
+ condition?: SExpr;
10075
10079
  repeatable?: boolean;
10076
10080
  minItems?: number;
10077
10081
  addButtonLabel?: string;
@@ -10080,9 +10084,9 @@ interface WizardSection {
10080
10084
  expression: string;
10081
10085
  scope?: string;
10082
10086
  }>;
10083
- dataSource?: JsonObject;
10087
+ dataSource?: Record<string, FieldValue>;
10084
10088
  readOnly?: boolean;
10085
- [key: string]: JsonValue | WizardField[] | WizardSection[] | undefined;
10089
+ [key: string]: JsonValue | SExpr | Record<string, FieldValue> | WizardField[] | WizardSection[] | undefined;
10086
10090
  }
10087
10091
  /** Entity mapping configuration */
10088
10092
  interface WizardEntityMapping {
@@ -10094,7 +10098,7 @@ interface WizardEntityMapping {
10094
10098
  }
10095
10099
  /** Validation rule for wizard steps */
10096
10100
  interface WizardValidationRule {
10097
- condition: JsonValue[];
10101
+ condition: SExpr;
10098
10102
  message: string;
10099
10103
  }
10100
10104
  /** Law reference for compliance */
@@ -1902,9 +1902,16 @@ var init_Input = __esm({
1902
1902
  }
1903
1903
  };
1904
1904
  const handleKeyDown = (e) => {
1905
- if (action && e.key === "Enter") {
1906
- eventBus.emit(`UI:${action}`, { value: e.currentTarget.value });
1905
+ if (!action || e.key !== "Enter") return;
1906
+ const raw = e.currentTarget.value;
1907
+ if (type === "number") {
1908
+ if (raw.trim() === "") return;
1909
+ const numeric = Number(raw);
1910
+ if (Number.isNaN(numeric)) return;
1911
+ eventBus.emit(`UI:${action}`, { value: numeric });
1912
+ return;
1907
1913
  }
1914
+ eventBus.emit(`UI:${action}`, { value: raw });
1908
1915
  };
1909
1916
  const wrapField = (field, fullWidth = true) => /* @__PURE__ */ jsxs("div", { className: fullWidth ? "w-full" : "w-fit", children: [
1910
1917
  label && /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-foreground mb-1", children: label }),
@@ -2087,6 +2094,7 @@ function NativeSelect({
2087
2094
  error,
2088
2095
  onChange,
2089
2096
  onValueChange,
2097
+ action,
2090
2098
  value,
2091
2099
  ...props
2092
2100
  }) {
@@ -2098,6 +2106,9 @@ function NativeSelect({
2098
2106
  onChange?.(e);
2099
2107
  }
2100
2108
  dispatchValueChange(onValueChange, eventBus, e.target.value);
2109
+ if (action) {
2110
+ eventBus.emit(`UI:${action}`, { value: e.target.value });
2111
+ }
2101
2112
  };
2102
2113
  return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
2103
2114
  /* @__PURE__ */ jsxs(
@@ -2133,6 +2144,7 @@ function RichSelect({
2133
2144
  error,
2134
2145
  onChange,
2135
2146
  onValueChange,
2147
+ action,
2136
2148
  value,
2137
2149
  multiple,
2138
2150
  searchable,
@@ -2158,6 +2170,9 @@ function RichSelect({
2158
2170
  eventBus.emit(`UI:${onChange}`, { value: next });
2159
2171
  }
2160
2172
  dispatchValueChange(onValueChange, eventBus, next);
2173
+ if (action) {
2174
+ eventBus.emit(`UI:${action}`, { value: next });
2175
+ }
2161
2176
  };
2162
2177
  const clear = (e) => {
2163
2178
  e.stopPropagation();
@@ -2166,6 +2181,9 @@ function RichSelect({
2166
2181
  eventBus.emit(`UI:${onChange}`, { value: next });
2167
2182
  }
2168
2183
  dispatchValueChange(onValueChange, eventBus, next);
2184
+ if (action) {
2185
+ eventBus.emit(`UI:${action}`, { value: next });
2186
+ }
2169
2187
  };
2170
2188
  useEffect(() => {
2171
2189
  const handler = (e) => {
@@ -9603,7 +9621,7 @@ function proceduralShapes(view, pos, fade, progress) {
9603
9621
  }
9604
9622
  }
9605
9623
  }
9606
- function expandFxItem(view, node, epochNowMs, dim) {
9624
+ function expandFxItem(view, node, epochNowMs, dim, projector) {
9607
9625
  if (view.space === "screen") return [];
9608
9626
  const tickMs = node.tickMs ?? DEFAULT_TICK_MS;
9609
9627
  const { ageMs, progress, fade } = fxLifecycle(view, epochNowMs, tickMs);
@@ -9639,24 +9657,26 @@ function expandFxItem(view, node, epochNowMs, dim) {
9639
9657
  out.push(...proceduralShapes(view, pos, fade, progress));
9640
9658
  }
9641
9659
  if (view.message) {
9660
+ const pxSize = projector && view.size !== void 0 ? Math.max(10, Math.round(view.size * projector.tileWidth)) : void 0;
9642
9661
  const text = {
9643
9662
  type: "draw-text",
9644
9663
  text: view.message,
9645
9664
  position: pos,
9646
9665
  offsetY: -(0.15 + 0.55 * progress),
9647
9666
  color: view.color ?? node.textColor ?? DEFAULT_TEXT_COLOR,
9648
- opacity: fade
9667
+ opacity: fade,
9668
+ ...pxSize ? { font: `bold ${pxSize}px system-ui, sans-serif` } : {}
9649
9669
  };
9650
9670
  out.push(text);
9651
9671
  }
9652
9672
  return out;
9653
9673
  }
9654
- function expandFxLayer(node, epochNowMs, dim) {
9674
+ function expandFxLayer(node, epochNowMs, dim, projector) {
9655
9675
  if (!Array.isArray(node.items)) return [];
9656
9676
  const out = [];
9657
9677
  for (const item of node.items) {
9658
9678
  if (!item || typeof item.id !== "string") continue;
9659
- out.push(...expandFxItem(resolveFxView(item, node.presets), node, epochNowMs, dim));
9679
+ out.push(...expandFxItem(resolveFxView(item, node.presets), node, epochNowMs, dim, projector));
9660
9680
  }
9661
9681
  return out;
9662
9682
  }
@@ -9723,7 +9743,7 @@ function paintDrawable(painter, node, dctx) {
9723
9743
  break;
9724
9744
  case "draw-fx-layer": {
9725
9745
  const epochNow = dctx.time > 0 && typeof performance !== "undefined" ? performance.timeOrigin + dctx.time : 0;
9726
- for (const child of expandFxLayer(node, epochNow, "2d")) paintDrawable(painter, child, dctx);
9746
+ for (const child of expandFxLayer(node, epochNow, "2d", dctx.projector)) paintDrawable(painter, child, dctx);
9727
9747
  break;
9728
9748
  }
9729
9749
  }
@@ -854,7 +854,7 @@ function proceduralShapes(view, pos, fade, progress) {
854
854
  }
855
855
  }
856
856
  }
857
- function expandFxItem(view, node, epochNowMs, dim) {
857
+ function expandFxItem(view, node, epochNowMs, dim, projector) {
858
858
  if (view.space === "screen") return [];
859
859
  const tickMs = node.tickMs ?? DEFAULT_TICK_MS;
860
860
  const { ageMs, progress, fade } = fxLifecycle(view, epochNowMs, tickMs);
@@ -896,13 +896,14 @@ function expandFxItem(view, node, epochNowMs, dim) {
896
896
  position: pos,
897
897
  offsetY: -(0.15 + 0.55 * progress),
898
898
  color: view.color ?? node.textColor ?? DEFAULT_TEXT_COLOR,
899
- opacity: fade
899
+ opacity: fade,
900
+ ...{}
900
901
  };
901
902
  out.push(text);
902
903
  }
903
904
  return out;
904
905
  }
905
- function expandFxLayer(node, epochNowMs, dim) {
906
+ function expandFxLayer(node, epochNowMs, dim, projector) {
906
907
  if (!Array.isArray(node.items)) return [];
907
908
  const out = [];
908
909
  for (const item of node.items) {
@@ -1,5 +1,5 @@
1
- import { C as CanvasPointLightConfig, I as IsometricTile, a as IsometricUnit, b as IsometricFeature, A as ApplicationLevelData, O as OrbitalLevelData, T as TraitLevelData, c as TransitionLevelData } from '../../../avl-schema-parser-C6Yz2MuW.cjs';
2
- export { d as Canvas3DHost, e as Canvas3DHostHandle, f as Canvas3DHostProps, d as GameCanvas3D, U as UnitAnimationState } from '../../../avl-schema-parser-C6Yz2MuW.cjs';
1
+ import { C as CanvasPointLightConfig, I as IsometricTile, a as IsometricUnit, b as IsometricFeature, A as ApplicationLevelData, O as OrbitalLevelData, T as TraitLevelData, c as TransitionLevelData } from '../../../avl-schema-parser-Bt4NzAam.cjs';
2
+ export { d as Canvas3DHost, e as Canvas3DHostHandle, f as Canvas3DHostProps, d as GameCanvas3D, U as UnitAnimationState } from '../../../avl-schema-parser-Bt4NzAam.cjs';
3
3
  import * as React$1 from 'react';
4
4
  import React__default, { Component, ReactNode, ErrorInfo } from 'react';
5
5
  import * as THREE from 'three';
@@ -1,5 +1,5 @@
1
- import { C as CanvasPointLightConfig, I as IsometricTile, a as IsometricUnit, b as IsometricFeature, A as ApplicationLevelData, O as OrbitalLevelData, T as TraitLevelData, c as TransitionLevelData } from '../../../avl-schema-parser-BKbH_SFt.js';
2
- export { d as Canvas3DHost, e as Canvas3DHostHandle, f as Canvas3DHostProps, d as GameCanvas3D, U as UnitAnimationState } from '../../../avl-schema-parser-BKbH_SFt.js';
1
+ import { C as CanvasPointLightConfig, I as IsometricTile, a as IsometricUnit, b as IsometricFeature, A as ApplicationLevelData, O as OrbitalLevelData, T as TraitLevelData, c as TransitionLevelData } from '../../../avl-schema-parser-dvJKXn-o.js';
2
+ export { d as Canvas3DHost, e as Canvas3DHostHandle, f as Canvas3DHostProps, d as GameCanvas3D, U as UnitAnimationState } from '../../../avl-schema-parser-dvJKXn-o.js';
3
3
  import * as React$1 from 'react';
4
4
  import React__default, { Component, ReactNode, ErrorInfo } from 'react';
5
5
  import * as THREE from 'three';
@@ -830,7 +830,7 @@ function proceduralShapes(view, pos, fade, progress) {
830
830
  }
831
831
  }
832
832
  }
833
- function expandFxItem(view, node, epochNowMs, dim) {
833
+ function expandFxItem(view, node, epochNowMs, dim, projector) {
834
834
  if (view.space === "screen") return [];
835
835
  const tickMs = node.tickMs ?? DEFAULT_TICK_MS;
836
836
  const { ageMs, progress, fade } = fxLifecycle(view, epochNowMs, tickMs);
@@ -872,13 +872,14 @@ function expandFxItem(view, node, epochNowMs, dim) {
872
872
  position: pos,
873
873
  offsetY: -(0.15 + 0.55 * progress),
874
874
  color: view.color ?? node.textColor ?? DEFAULT_TEXT_COLOR,
875
- opacity: fade
875
+ opacity: fade,
876
+ ...{}
876
877
  };
877
878
  out.push(text);
878
879
  }
879
880
  return out;
880
881
  }
881
- function expandFxLayer(node, epochNowMs, dim) {
882
+ function expandFxLayer(node, epochNowMs, dim, projector) {
882
883
  if (!Array.isArray(node.items)) return [];
883
884
  const out = [];
884
885
  for (const item of node.items) {
@@ -3314,9 +3314,16 @@ var init_Input = __esm({
3314
3314
  }
3315
3315
  };
3316
3316
  const handleKeyDown = (e) => {
3317
- if (action && e.key === "Enter") {
3318
- eventBus.emit(`UI:${action}`, { value: e.currentTarget.value });
3317
+ if (!action || e.key !== "Enter") return;
3318
+ const raw = e.currentTarget.value;
3319
+ if (type === "number") {
3320
+ if (raw.trim() === "") return;
3321
+ const numeric = Number(raw);
3322
+ if (Number.isNaN(numeric)) return;
3323
+ eventBus.emit(`UI:${action}`, { value: numeric });
3324
+ return;
3319
3325
  }
3326
+ eventBus.emit(`UI:${action}`, { value: raw });
3320
3327
  };
3321
3328
  const wrapField = (field, fullWidth = true) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: fullWidth ? "w-full" : "w-fit", children: [
3322
3329
  label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium text-foreground mb-1", children: label }),
@@ -3499,6 +3506,7 @@ function NativeSelect({
3499
3506
  error,
3500
3507
  onChange,
3501
3508
  onValueChange,
3509
+ action,
3502
3510
  value,
3503
3511
  ...props
3504
3512
  }) {
@@ -3510,6 +3518,9 @@ function NativeSelect({
3510
3518
  onChange?.(e);
3511
3519
  }
3512
3520
  dispatchValueChange(onValueChange, eventBus, e.target.value);
3521
+ if (action) {
3522
+ eventBus.emit(`UI:${action}`, { value: e.target.value });
3523
+ }
3513
3524
  };
3514
3525
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
3515
3526
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -3545,6 +3556,7 @@ function RichSelect({
3545
3556
  error,
3546
3557
  onChange,
3547
3558
  onValueChange,
3559
+ action,
3548
3560
  value,
3549
3561
  multiple,
3550
3562
  searchable,
@@ -3570,6 +3582,9 @@ function RichSelect({
3570
3582
  eventBus.emit(`UI:${onChange}`, { value: next });
3571
3583
  }
3572
3584
  dispatchValueChange(onValueChange, eventBus, next);
3585
+ if (action) {
3586
+ eventBus.emit(`UI:${action}`, { value: next });
3587
+ }
3573
3588
  };
3574
3589
  const clear = (e) => {
3575
3590
  e.stopPropagation();
@@ -3578,6 +3593,9 @@ function RichSelect({
3578
3593
  eventBus.emit(`UI:${onChange}`, { value: next });
3579
3594
  }
3580
3595
  dispatchValueChange(onValueChange, eventBus, next);
3596
+ if (action) {
3597
+ eventBus.emit(`UI:${action}`, { value: next });
3598
+ }
3581
3599
  };
3582
3600
  React87.useEffect(() => {
3583
3601
  const handler = (e) => {
@@ -9871,7 +9889,7 @@ function proceduralShapes(view, pos, fade, progress) {
9871
9889
  }
9872
9890
  }
9873
9891
  }
9874
- function expandFxItem(view, node, epochNowMs, dim) {
9892
+ function expandFxItem(view, node, epochNowMs, dim, projector) {
9875
9893
  if (view.space === "screen") return [];
9876
9894
  const tickMs = node.tickMs ?? DEFAULT_TICK_MS;
9877
9895
  const { ageMs, progress, fade } = fxLifecycle(view, epochNowMs, tickMs);
@@ -9907,24 +9925,26 @@ function expandFxItem(view, node, epochNowMs, dim) {
9907
9925
  out.push(...proceduralShapes(view, pos, fade, progress));
9908
9926
  }
9909
9927
  if (view.message) {
9928
+ const pxSize = projector && view.size !== void 0 ? Math.max(10, Math.round(view.size * projector.tileWidth)) : void 0;
9910
9929
  const text = {
9911
9930
  type: "draw-text",
9912
9931
  text: view.message,
9913
9932
  position: pos,
9914
9933
  offsetY: -(0.15 + 0.55 * progress),
9915
9934
  color: view.color ?? node.textColor ?? DEFAULT_TEXT_COLOR,
9916
- opacity: fade
9935
+ opacity: fade,
9936
+ ...pxSize ? { font: `bold ${pxSize}px system-ui, sans-serif` } : {}
9917
9937
  };
9918
9938
  out.push(text);
9919
9939
  }
9920
9940
  return out;
9921
9941
  }
9922
- function expandFxLayer(node, epochNowMs, dim) {
9942
+ function expandFxLayer(node, epochNowMs, dim, projector) {
9923
9943
  if (!Array.isArray(node.items)) return [];
9924
9944
  const out = [];
9925
9945
  for (const item of node.items) {
9926
9946
  if (!item || typeof item.id !== "string") continue;
9927
- out.push(...expandFxItem(resolveFxView(item, node.presets), node, epochNowMs, dim));
9947
+ out.push(...expandFxItem(resolveFxView(item, node.presets), node, epochNowMs, dim, projector));
9928
9948
  }
9929
9949
  return out;
9930
9950
  }
@@ -9991,7 +10011,7 @@ function paintDrawable(painter, node, dctx) {
9991
10011
  break;
9992
10012
  case "draw-fx-layer": {
9993
10013
  const epochNow = dctx.time > 0 && typeof performance !== "undefined" ? performance.timeOrigin + dctx.time : 0;
9994
- for (const child of expandFxLayer(node, epochNow, "2d")) paintDrawable(painter, child, dctx);
10014
+ for (const child of expandFxLayer(node, epochNow, "2d", dctx.projector)) paintDrawable(painter, child, dctx);
9995
10015
  break;
9996
10016
  }
9997
10017
  }
@@ -3240,9 +3240,16 @@ var init_Input = __esm({
3240
3240
  }
3241
3241
  };
3242
3242
  const handleKeyDown = (e) => {
3243
- if (action && e.key === "Enter") {
3244
- eventBus.emit(`UI:${action}`, { value: e.currentTarget.value });
3243
+ if (!action || e.key !== "Enter") return;
3244
+ const raw = e.currentTarget.value;
3245
+ if (type === "number") {
3246
+ if (raw.trim() === "") return;
3247
+ const numeric = Number(raw);
3248
+ if (Number.isNaN(numeric)) return;
3249
+ eventBus.emit(`UI:${action}`, { value: numeric });
3250
+ return;
3245
3251
  }
3252
+ eventBus.emit(`UI:${action}`, { value: raw });
3246
3253
  };
3247
3254
  const wrapField = (field, fullWidth = true) => /* @__PURE__ */ jsxs("div", { className: fullWidth ? "w-full" : "w-fit", children: [
3248
3255
  label && /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-foreground mb-1", children: label }),
@@ -3425,6 +3432,7 @@ function NativeSelect({
3425
3432
  error,
3426
3433
  onChange,
3427
3434
  onValueChange,
3435
+ action,
3428
3436
  value,
3429
3437
  ...props
3430
3438
  }) {
@@ -3436,6 +3444,9 @@ function NativeSelect({
3436
3444
  onChange?.(e);
3437
3445
  }
3438
3446
  dispatchValueChange(onValueChange, eventBus, e.target.value);
3447
+ if (action) {
3448
+ eventBus.emit(`UI:${action}`, { value: e.target.value });
3449
+ }
3439
3450
  };
3440
3451
  return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
3441
3452
  /* @__PURE__ */ jsxs(
@@ -3471,6 +3482,7 @@ function RichSelect({
3471
3482
  error,
3472
3483
  onChange,
3473
3484
  onValueChange,
3485
+ action,
3474
3486
  value,
3475
3487
  multiple,
3476
3488
  searchable,
@@ -3496,6 +3508,9 @@ function RichSelect({
3496
3508
  eventBus.emit(`UI:${onChange}`, { value: next });
3497
3509
  }
3498
3510
  dispatchValueChange(onValueChange, eventBus, next);
3511
+ if (action) {
3512
+ eventBus.emit(`UI:${action}`, { value: next });
3513
+ }
3499
3514
  };
3500
3515
  const clear = (e) => {
3501
3516
  e.stopPropagation();
@@ -3504,6 +3519,9 @@ function RichSelect({
3504
3519
  eventBus.emit(`UI:${onChange}`, { value: next });
3505
3520
  }
3506
3521
  dispatchValueChange(onValueChange, eventBus, next);
3522
+ if (action) {
3523
+ eventBus.emit(`UI:${action}`, { value: next });
3524
+ }
3507
3525
  };
3508
3526
  useEffect(() => {
3509
3527
  const handler = (e) => {
@@ -9797,7 +9815,7 @@ function proceduralShapes(view, pos, fade, progress) {
9797
9815
  }
9798
9816
  }
9799
9817
  }
9800
- function expandFxItem(view, node, epochNowMs, dim) {
9818
+ function expandFxItem(view, node, epochNowMs, dim, projector) {
9801
9819
  if (view.space === "screen") return [];
9802
9820
  const tickMs = node.tickMs ?? DEFAULT_TICK_MS;
9803
9821
  const { ageMs, progress, fade } = fxLifecycle(view, epochNowMs, tickMs);
@@ -9833,24 +9851,26 @@ function expandFxItem(view, node, epochNowMs, dim) {
9833
9851
  out.push(...proceduralShapes(view, pos, fade, progress));
9834
9852
  }
9835
9853
  if (view.message) {
9854
+ const pxSize = projector && view.size !== void 0 ? Math.max(10, Math.round(view.size * projector.tileWidth)) : void 0;
9836
9855
  const text = {
9837
9856
  type: "draw-text",
9838
9857
  text: view.message,
9839
9858
  position: pos,
9840
9859
  offsetY: -(0.15 + 0.55 * progress),
9841
9860
  color: view.color ?? node.textColor ?? DEFAULT_TEXT_COLOR,
9842
- opacity: fade
9861
+ opacity: fade,
9862
+ ...pxSize ? { font: `bold ${pxSize}px system-ui, sans-serif` } : {}
9843
9863
  };
9844
9864
  out.push(text);
9845
9865
  }
9846
9866
  return out;
9847
9867
  }
9848
- function expandFxLayer(node, epochNowMs, dim) {
9868
+ function expandFxLayer(node, epochNowMs, dim, projector) {
9849
9869
  if (!Array.isArray(node.items)) return [];
9850
9870
  const out = [];
9851
9871
  for (const item of node.items) {
9852
9872
  if (!item || typeof item.id !== "string") continue;
9853
- out.push(...expandFxItem(resolveFxView(item, node.presets), node, epochNowMs, dim));
9873
+ out.push(...expandFxItem(resolveFxView(item, node.presets), node, epochNowMs, dim, projector));
9854
9874
  }
9855
9875
  return out;
9856
9876
  }
@@ -9917,7 +9937,7 @@ function paintDrawable(painter, node, dctx) {
9917
9937
  break;
9918
9938
  case "draw-fx-layer": {
9919
9939
  const epochNow = dctx.time > 0 && typeof performance !== "undefined" ? performance.timeOrigin + dctx.time : 0;
9920
- for (const child of expandFxLayer(node, epochNow, "2d")) paintDrawable(painter, child, dctx);
9940
+ for (const child of expandFxLayer(node, epochNow, "2d", dctx.projector)) paintDrawable(painter, child, dctx);
9921
9941
  break;
9922
9942
  }
9923
9943
  }
@@ -3807,9 +3807,16 @@ var init_Input = __esm({
3807
3807
  }
3808
3808
  };
3809
3809
  const handleKeyDown = (e) => {
3810
- if (action && e.key === "Enter") {
3811
- eventBus.emit(`UI:${action}`, { value: e.currentTarget.value });
3810
+ if (!action || e.key !== "Enter") return;
3811
+ const raw = e.currentTarget.value;
3812
+ if (type === "number") {
3813
+ if (raw.trim() === "") return;
3814
+ const numeric = Number(raw);
3815
+ if (Number.isNaN(numeric)) return;
3816
+ eventBus.emit(`UI:${action}`, { value: numeric });
3817
+ return;
3812
3818
  }
3819
+ eventBus.emit(`UI:${action}`, { value: raw });
3813
3820
  };
3814
3821
  const wrapField = (field, fullWidth = true) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: fullWidth ? "w-full" : "w-fit", children: [
3815
3822
  label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium text-foreground mb-1", children: label }),
@@ -3992,6 +3999,7 @@ function NativeSelect({
3992
3999
  error,
3993
4000
  onChange,
3994
4001
  onValueChange,
4002
+ action,
3995
4003
  value,
3996
4004
  ...props
3997
4005
  }) {
@@ -4003,6 +4011,9 @@ function NativeSelect({
4003
4011
  onChange?.(e);
4004
4012
  }
4005
4013
  dispatchValueChange(onValueChange, eventBus, e.target.value);
4014
+ if (action) {
4015
+ eventBus.emit(`UI:${action}`, { value: e.target.value });
4016
+ }
4006
4017
  };
4007
4018
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
4008
4019
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -4038,6 +4049,7 @@ function RichSelect({
4038
4049
  error,
4039
4050
  onChange,
4040
4051
  onValueChange,
4052
+ action,
4041
4053
  value,
4042
4054
  multiple,
4043
4055
  searchable,
@@ -4063,6 +4075,9 @@ function RichSelect({
4063
4075
  eventBus.emit(`UI:${onChange}`, { value: next });
4064
4076
  }
4065
4077
  dispatchValueChange(onValueChange, eventBus, next);
4078
+ if (action) {
4079
+ eventBus.emit(`UI:${action}`, { value: next });
4080
+ }
4066
4081
  };
4067
4082
  const clear = (e) => {
4068
4083
  e.stopPropagation();
@@ -4071,6 +4086,9 @@ function RichSelect({
4071
4086
  eventBus.emit(`UI:${onChange}`, { value: next });
4072
4087
  }
4073
4088
  dispatchValueChange(onValueChange, eventBus, next);
4089
+ if (action) {
4090
+ eventBus.emit(`UI:${action}`, { value: next });
4091
+ }
4074
4092
  };
4075
4093
  React85.useEffect(() => {
4076
4094
  const handler = (e) => {
@@ -10221,7 +10239,7 @@ function proceduralShapes(view, pos, fade, progress) {
10221
10239
  }
10222
10240
  }
10223
10241
  }
10224
- function expandFxItem(view, node, epochNowMs, dim) {
10242
+ function expandFxItem(view, node, epochNowMs, dim, projector) {
10225
10243
  if (view.space === "screen") return [];
10226
10244
  const tickMs = node.tickMs ?? DEFAULT_TICK_MS;
10227
10245
  const { ageMs, progress, fade } = fxLifecycle(view, epochNowMs, tickMs);
@@ -10257,24 +10275,26 @@ function expandFxItem(view, node, epochNowMs, dim) {
10257
10275
  out.push(...proceduralShapes(view, pos, fade, progress));
10258
10276
  }
10259
10277
  if (view.message) {
10278
+ const pxSize = projector && view.size !== void 0 ? Math.max(10, Math.round(view.size * projector.tileWidth)) : void 0;
10260
10279
  const text = {
10261
10280
  type: "draw-text",
10262
10281
  text: view.message,
10263
10282
  position: pos,
10264
10283
  offsetY: -(0.15 + 0.55 * progress),
10265
10284
  color: view.color ?? node.textColor ?? DEFAULT_TEXT_COLOR,
10266
- opacity: fade
10285
+ opacity: fade,
10286
+ ...pxSize ? { font: `bold ${pxSize}px system-ui, sans-serif` } : {}
10267
10287
  };
10268
10288
  out.push(text);
10269
10289
  }
10270
10290
  return out;
10271
10291
  }
10272
- function expandFxLayer(node, epochNowMs, dim) {
10292
+ function expandFxLayer(node, epochNowMs, dim, projector) {
10273
10293
  if (!Array.isArray(node.items)) return [];
10274
10294
  const out = [];
10275
10295
  for (const item of node.items) {
10276
10296
  if (!item || typeof item.id !== "string") continue;
10277
- out.push(...expandFxItem(resolveFxView(item, node.presets), node, epochNowMs, dim));
10297
+ out.push(...expandFxItem(resolveFxView(item, node.presets), node, epochNowMs, dim, projector));
10278
10298
  }
10279
10299
  return out;
10280
10300
  }
@@ -10341,7 +10361,7 @@ function paintDrawable(painter, node, dctx) {
10341
10361
  break;
10342
10362
  case "draw-fx-layer": {
10343
10363
  const epochNow = dctx.time > 0 && typeof performance !== "undefined" ? performance.timeOrigin + dctx.time : 0;
10344
- for (const child of expandFxLayer(node, epochNow, "2d")) paintDrawable(painter, child, dctx);
10364
+ for (const child of expandFxLayer(node, epochNow, "2d", dctx.projector)) paintDrawable(painter, child, dctx);
10345
10365
  break;
10346
10366
  }
10347
10367
  }