@almadar/ui 5.22.3 → 5.23.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.
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+ import type { DeclaredTraitConfig, TraitConfig, TraitConfigValue } from '@almadar/core';
3
+ import type { DisplayStateProps } from '../organisms/types';
4
+ /**
5
+ * PropertyInspector — Storybook-style controls panel for a trait's `config`.
6
+ *
7
+ * Derives one control per declared config field directly from the schema
8
+ * (`@almadar/core` `DeclaredTraitConfig`): `boolean → Switch`, `string` with
9
+ * `values → Select`, `number → numeric Input`, `string → Input`. Non-scalar
10
+ * fields (array/object/node/SExpr) are shown read-only. Fields group + collapse
11
+ * by `@tier`. The component is controlled — it emits `onChange(field, value)`;
12
+ * text/number commit on blur (so the host can re-render without hammering it).
13
+ */
14
+ export interface PropertyInspectorProps extends DisplayStateProps {
15
+ /** The trait's declared config schema (field name → declaration). */
16
+ config: DeclaredTraitConfig;
17
+ /** Current override values keyed by field name (falls back to each field's `default`). */
18
+ values?: TraitConfig;
19
+ /** Fired when a control commits a new value. */
20
+ onChange: (field: string, value: TraitConfigValue) => void;
21
+ /** Optional reset-to-defaults handler. */
22
+ onReset?: () => void;
23
+ /** Panel heading (e.g. the trait name). */
24
+ title?: string;
25
+ }
26
+ export declare const PropertyInspector: React.FC<PropertyInspectorProps>;
@@ -106,6 +106,7 @@ export { BehaviorView, type BehaviorViewProps } from '../../avl/molecules/Behavi
106
106
  export { ModuleCard, type ModuleCardProps } from '../../avl/molecules/ModuleCard';
107
107
  export { PageHeader, type PageHeaderProps, type PageBreadcrumb, } from "./PageHeader";
108
108
  export { FormSection, FormLayout, FormActions, type FormSectionProps, type FormLayoutProps, type FormActionsProps, } from "./FormSection";
109
+ export { PropertyInspector, type PropertyInspectorProps } from "./PropertyInspector";
109
110
  export { Header, type HeaderProps } from "./Header";
110
111
  export { Navigation, type NavigationProps, type NavigationItem, } from "./Navigation";
111
112
  export { Section, type SectionProps } from "./Section";
@@ -35061,6 +35061,127 @@ var init_FormSection = __esm({
35061
35061
  exports.FormActions.displayName = "FormActions";
35062
35062
  }
35063
35063
  });
35064
+ function currentValue(decl, override) {
35065
+ return override !== void 0 ? override : decl.default;
35066
+ }
35067
+ function TextLikeControl({
35068
+ field,
35069
+ numeric,
35070
+ value,
35071
+ onCommit
35072
+ }) {
35073
+ const initial = value === void 0 || value === null ? "" : String(value);
35074
+ const [draft, setDraft] = React80__namespace.default.useState(initial);
35075
+ React80__namespace.default.useEffect(() => setDraft(initial), [initial]);
35076
+ const commit = () => {
35077
+ if (numeric) {
35078
+ const n = draft.trim() === "" ? 0 : Number(draft);
35079
+ onCommit(field, Number.isNaN(n) ? 0 : n);
35080
+ } else {
35081
+ onCommit(field, draft);
35082
+ }
35083
+ };
35084
+ return /* @__PURE__ */ jsxRuntime.jsx(
35085
+ exports.Input,
35086
+ {
35087
+ inputType: numeric ? "number" : "text",
35088
+ value: draft,
35089
+ onChange: (e) => setDraft(e.target.value),
35090
+ onBlur: commit,
35091
+ onKeyDown: (e) => {
35092
+ if (e.key === "Enter") commit();
35093
+ }
35094
+ }
35095
+ );
35096
+ }
35097
+ function FieldControl({
35098
+ name,
35099
+ decl,
35100
+ value,
35101
+ onChange
35102
+ }) {
35103
+ let control;
35104
+ if (decl.type === "boolean") {
35105
+ control = /* @__PURE__ */ jsxRuntime.jsx(exports.Switch, { checked: value === true, onChange: (c) => onChange(name, c) });
35106
+ } else if (decl.type === "string" && decl.values !== void 0 && decl.values.length > 0) {
35107
+ control = /* @__PURE__ */ jsxRuntime.jsx(
35108
+ exports.Select,
35109
+ {
35110
+ options: decl.values.map((v) => ({ value: v, label: v })),
35111
+ value: typeof value === "string" ? value : "",
35112
+ onChange: (e) => onChange(name, e.target.value)
35113
+ }
35114
+ );
35115
+ } else if (decl.type === "number") {
35116
+ control = /* @__PURE__ */ jsxRuntime.jsx(TextLikeControl, { field: name, numeric: true, value, onCommit: onChange });
35117
+ } else if (decl.type === "string") {
35118
+ control = /* @__PURE__ */ jsxRuntime.jsx(TextLikeControl, { field: name, numeric: false, value, onCommit: onChange });
35119
+ } else {
35120
+ control = /* @__PURE__ */ jsxRuntime.jsxs(exports.Typography, { variant: "caption", color: "muted", children: [
35121
+ decl.type,
35122
+ " \u2014 edit in source"
35123
+ ] });
35124
+ }
35125
+ return /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", children: [
35126
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "label", children: decl.label ?? name }),
35127
+ control,
35128
+ decl.description !== void 0 && decl.description !== "" && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "muted", children: decl.description })
35129
+ ] });
35130
+ }
35131
+ var TIER_ORDER; exports.PropertyInspector = void 0;
35132
+ var init_PropertyInspector = __esm({
35133
+ "components/core/molecules/PropertyInspector.tsx"() {
35134
+ "use client";
35135
+ init_cn();
35136
+ init_Stack();
35137
+ init_Typography();
35138
+ init_Button();
35139
+ init_Switch();
35140
+ init_Select();
35141
+ init_Input();
35142
+ init_FormSection();
35143
+ TIER_ORDER = ["presentation", "domain", "policy", "infra", "internal"];
35144
+ exports.PropertyInspector = ({
35145
+ config,
35146
+ values,
35147
+ onChange,
35148
+ onReset,
35149
+ title,
35150
+ className
35151
+ }) => {
35152
+ const fields = Object.entries(config);
35153
+ const byTier = /* @__PURE__ */ new Map();
35154
+ for (const [name, decl] of fields) {
35155
+ const tier = decl.tier ?? "presentation";
35156
+ const arr = byTier.get(tier) ?? [];
35157
+ arr.push([name, decl]);
35158
+ byTier.set(tier, arr);
35159
+ }
35160
+ const tiers = [...byTier.keys()].sort((a, b) => {
35161
+ const ia = TIER_ORDER.indexOf(a);
35162
+ const ib = TIER_ORDER.indexOf(b);
35163
+ return (ia === -1 ? 99 : ia) - (ib === -1 ? 99 : ib);
35164
+ });
35165
+ return /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "sm", className: cn("w-full", className), children: [
35166
+ /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { justify: "between", align: "center", children: [
35167
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", weight: "bold", children: title ?? "Config" }),
35168
+ onReset !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", icon: "rotate-ccw", label: "Reset", onClick: onReset })
35169
+ ] }),
35170
+ fields.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "muted", children: "No configurable properties." }),
35171
+ tiers.map((tier) => /* @__PURE__ */ jsxRuntime.jsx(exports.FormSection, { title: tier, collapsible: true, defaultCollapsed: tier !== "presentation", children: /* @__PURE__ */ jsxRuntime.jsx(exports.VStack, { gap: "sm", children: byTier.get(tier)?.map(([name, decl]) => /* @__PURE__ */ jsxRuntime.jsx(
35172
+ FieldControl,
35173
+ {
35174
+ name,
35175
+ decl,
35176
+ value: currentValue(decl, values?.[name]),
35177
+ onChange
35178
+ },
35179
+ name
35180
+ )) }) }, tier))
35181
+ ] });
35182
+ };
35183
+ }
35184
+ });
35064
35185
  var lookStyles8; exports.Header = void 0;
35065
35186
  var init_Header = __esm({
35066
35187
  "components/core/molecules/Header.tsx"() {
@@ -37026,6 +37147,7 @@ var init_molecules2 = __esm({
37026
37147
  init_ModuleCard();
37027
37148
  init_PageHeader();
37028
37149
  init_FormSection();
37150
+ init_PropertyInspector();
37029
37151
  init_Header();
37030
37152
  init_Navigation();
37031
37153
  init_Section();
@@ -39447,13 +39569,13 @@ var init_Form = __esm({
39447
39569
  }
39448
39570
  const inputType = determineInputType(field);
39449
39571
  const label = field.label || fieldName.charAt(0).toUpperCase() + fieldName.slice(1).replace(/([A-Z])/g, " $1");
39450
- const currentValue = formData[fieldName] ?? field.defaultValue ?? "";
39572
+ const currentValue2 = formData[fieldName] ?? field.defaultValue ?? "";
39451
39573
  return /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", "data-field": fieldName, children: [
39452
39574
  inputType !== "checkbox" && /* @__PURE__ */ jsxRuntime.jsxs(exports.Typography, { as: "label", variant: "label", weight: "bold", children: [
39453
39575
  label,
39454
39576
  field.required && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { as: "span", color: "error", className: "ml-1", children: "*" })
39455
39577
  ] }),
39456
- renderFieldInput(field, fieldName, inputType, currentValue, label)
39578
+ renderFieldInput(field, fieldName, inputType, currentValue2, label)
39457
39579
  ] }, fieldName);
39458
39580
  },
39459
39581
  [formData, isFieldVisible, relationsData, relationsLoading, isLoading]
@@ -39528,7 +39650,7 @@ var init_Form = __esm({
39528
39650
  ] }, section.id);
39529
39651
  }).filter(Boolean);
39530
39652
  }, [sections, isSectionVisible, collapsedSections, renderField, gap]);
39531
- function renderFieldInput(field, fieldName, inputType, currentValue, label) {
39653
+ function renderFieldInput(field, fieldName, inputType, currentValue2, label) {
39532
39654
  const commonProps = {
39533
39655
  id: fieldName,
39534
39656
  name: fieldName,
@@ -39545,7 +39667,7 @@ var init_Form = __esm({
39545
39667
  {
39546
39668
  ...commonProps,
39547
39669
  label: label + (field.required ? " *" : ""),
39548
- checked: Boolean(currentValue),
39670
+ checked: Boolean(currentValue2),
39549
39671
  onChange: (e) => handleChange(fieldName, e.target.checked)
39550
39672
  }
39551
39673
  );
@@ -39554,7 +39676,7 @@ var init_Form = __esm({
39554
39676
  exports.Textarea,
39555
39677
  {
39556
39678
  ...commonProps,
39557
- value: String(currentValue),
39679
+ value: String(currentValue2),
39558
39680
  onChange: (e) => handleChange(fieldName, e.target.value),
39559
39681
  minLength: field.min,
39560
39682
  maxLength: field.max
@@ -39567,7 +39689,7 @@ var init_Form = __esm({
39567
39689
  {
39568
39690
  ...commonProps,
39569
39691
  options,
39570
- value: String(currentValue),
39692
+ value: String(currentValue2),
39571
39693
  onChange: (e) => handleChange(fieldName, e.target.value),
39572
39694
  placeholder: field.placeholder || `Select ${label}...`
39573
39695
  }
@@ -39580,7 +39702,7 @@ var init_Form = __esm({
39580
39702
  exports.RelationSelect,
39581
39703
  {
39582
39704
  ...commonProps,
39583
- value: currentValue ? String(currentValue) : void 0,
39705
+ value: currentValue2 ? String(currentValue2) : void 0,
39584
39706
  onChange: (value) => handleChange(fieldName, value),
39585
39707
  options: relationOptions,
39586
39708
  isLoading: relationLoading,
@@ -39596,7 +39718,7 @@ var init_Form = __esm({
39596
39718
  {
39597
39719
  ...commonProps,
39598
39720
  type: "number",
39599
- value: currentValue !== void 0 && currentValue !== "" ? String(currentValue) : "",
39721
+ value: currentValue2 !== void 0 && currentValue2 !== "" ? String(currentValue2) : "",
39600
39722
  onChange: (e) => handleChange(
39601
39723
  fieldName,
39602
39724
  e.target.value ? Number(e.target.value) : void 0
@@ -39611,7 +39733,7 @@ var init_Form = __esm({
39611
39733
  {
39612
39734
  ...commonProps,
39613
39735
  type: "date",
39614
- value: formatDateValue(currentValue),
39736
+ value: formatDateValue(currentValue2),
39615
39737
  onChange: (e) => handleChange(fieldName, e.target.value)
39616
39738
  }
39617
39739
  );
@@ -39621,7 +39743,7 @@ var init_Form = __esm({
39621
39743
  {
39622
39744
  ...commonProps,
39623
39745
  type: "datetime-local",
39624
- value: formatDateTimeValue(currentValue),
39746
+ value: formatDateTimeValue(currentValue2),
39625
39747
  onChange: (e) => handleChange(fieldName, e.target.value)
39626
39748
  }
39627
39749
  );
@@ -39631,7 +39753,7 @@ var init_Form = __esm({
39631
39753
  {
39632
39754
  ...commonProps,
39633
39755
  type: "email",
39634
- value: String(currentValue),
39756
+ value: String(currentValue2),
39635
39757
  onChange: (e) => handleChange(fieldName, e.target.value),
39636
39758
  minLength: field.min,
39637
39759
  maxLength: field.max
@@ -39643,7 +39765,7 @@ var init_Form = __esm({
39643
39765
  {
39644
39766
  ...commonProps,
39645
39767
  type: "url",
39646
- value: String(currentValue),
39768
+ value: String(currentValue2),
39647
39769
  onChange: (e) => handleChange(fieldName, e.target.value),
39648
39770
  minLength: field.min,
39649
39771
  maxLength: field.max
@@ -39655,7 +39777,7 @@ var init_Form = __esm({
39655
39777
  {
39656
39778
  ...commonProps,
39657
39779
  type: "password",
39658
- value: String(currentValue),
39780
+ value: String(currentValue2),
39659
39781
  onChange: (e) => handleChange(fieldName, e.target.value),
39660
39782
  minLength: field.min,
39661
39783
  maxLength: field.max
@@ -39668,7 +39790,7 @@ var init_Form = __esm({
39668
39790
  {
39669
39791
  ...commonProps,
39670
39792
  type: "text",
39671
- value: String(currentValue),
39793
+ value: String(currentValue2),
39672
39794
  onChange: (e) => handleChange(fieldName, e.target.value),
39673
39795
  minLength: field.min,
39674
39796
  maxLength: field.max
@@ -44869,7 +44991,7 @@ var init_StatCard = __esm({
44869
44991
  title: propTitle,
44870
44992
  value: propValue,
44871
44993
  previousValue,
44872
- currentValue,
44994
+ currentValue: currentValue2,
44873
44995
  trend: manualTrend,
44874
44996
  trendDirection: manualDirection,
44875
44997
  invertTrend = false,
@@ -44950,11 +45072,11 @@ var init_StatCard = __esm({
44950
45072
  }, [metrics, data, computeMetricValue]);
44951
45073
  const calculatedTrend = React80__namespace.default.useMemo(() => {
44952
45074
  if (manualTrend !== void 0) return manualTrend;
44953
- if (previousValue === void 0 || currentValue === void 0)
45075
+ if (previousValue === void 0 || currentValue2 === void 0)
44954
45076
  return void 0;
44955
- if (previousValue === 0) return currentValue > 0 ? 100 : 0;
44956
- return (currentValue - previousValue) / previousValue * 100;
44957
- }, [manualTrend, previousValue, currentValue]);
45077
+ if (previousValue === 0) return currentValue2 > 0 ? 100 : 0;
45078
+ return (currentValue2 - previousValue) / previousValue * 100;
45079
+ }, [manualTrend, previousValue, currentValue2]);
44958
45080
  if (schemaStats && schemaStats.length > 1) {
44959
45081
  if (isLoading) {
44960
45082
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -35013,6 +35013,127 @@ var init_FormSection = __esm({
35013
35013
  FormActions.displayName = "FormActions";
35014
35014
  }
35015
35015
  });
35016
+ function currentValue(decl, override) {
35017
+ return override !== void 0 ? override : decl.default;
35018
+ }
35019
+ function TextLikeControl({
35020
+ field,
35021
+ numeric,
35022
+ value,
35023
+ onCommit
35024
+ }) {
35025
+ const initial = value === void 0 || value === null ? "" : String(value);
35026
+ const [draft, setDraft] = React80__default.useState(initial);
35027
+ React80__default.useEffect(() => setDraft(initial), [initial]);
35028
+ const commit = () => {
35029
+ if (numeric) {
35030
+ const n = draft.trim() === "" ? 0 : Number(draft);
35031
+ onCommit(field, Number.isNaN(n) ? 0 : n);
35032
+ } else {
35033
+ onCommit(field, draft);
35034
+ }
35035
+ };
35036
+ return /* @__PURE__ */ jsx(
35037
+ Input,
35038
+ {
35039
+ inputType: numeric ? "number" : "text",
35040
+ value: draft,
35041
+ onChange: (e) => setDraft(e.target.value),
35042
+ onBlur: commit,
35043
+ onKeyDown: (e) => {
35044
+ if (e.key === "Enter") commit();
35045
+ }
35046
+ }
35047
+ );
35048
+ }
35049
+ function FieldControl({
35050
+ name,
35051
+ decl,
35052
+ value,
35053
+ onChange
35054
+ }) {
35055
+ let control;
35056
+ if (decl.type === "boolean") {
35057
+ control = /* @__PURE__ */ jsx(Switch, { checked: value === true, onChange: (c) => onChange(name, c) });
35058
+ } else if (decl.type === "string" && decl.values !== void 0 && decl.values.length > 0) {
35059
+ control = /* @__PURE__ */ jsx(
35060
+ Select,
35061
+ {
35062
+ options: decl.values.map((v) => ({ value: v, label: v })),
35063
+ value: typeof value === "string" ? value : "",
35064
+ onChange: (e) => onChange(name, e.target.value)
35065
+ }
35066
+ );
35067
+ } else if (decl.type === "number") {
35068
+ control = /* @__PURE__ */ jsx(TextLikeControl, { field: name, numeric: true, value, onCommit: onChange });
35069
+ } else if (decl.type === "string") {
35070
+ control = /* @__PURE__ */ jsx(TextLikeControl, { field: name, numeric: false, value, onCommit: onChange });
35071
+ } else {
35072
+ control = /* @__PURE__ */ jsxs(Typography, { variant: "caption", color: "muted", children: [
35073
+ decl.type,
35074
+ " \u2014 edit in source"
35075
+ ] });
35076
+ }
35077
+ return /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
35078
+ /* @__PURE__ */ jsx(Typography, { variant: "label", children: decl.label ?? name }),
35079
+ control,
35080
+ decl.description !== void 0 && decl.description !== "" && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: decl.description })
35081
+ ] });
35082
+ }
35083
+ var TIER_ORDER, PropertyInspector;
35084
+ var init_PropertyInspector = __esm({
35085
+ "components/core/molecules/PropertyInspector.tsx"() {
35086
+ "use client";
35087
+ init_cn();
35088
+ init_Stack();
35089
+ init_Typography();
35090
+ init_Button();
35091
+ init_Switch();
35092
+ init_Select();
35093
+ init_Input();
35094
+ init_FormSection();
35095
+ TIER_ORDER = ["presentation", "domain", "policy", "infra", "internal"];
35096
+ PropertyInspector = ({
35097
+ config,
35098
+ values,
35099
+ onChange,
35100
+ onReset,
35101
+ title,
35102
+ className
35103
+ }) => {
35104
+ const fields = Object.entries(config);
35105
+ const byTier = /* @__PURE__ */ new Map();
35106
+ for (const [name, decl] of fields) {
35107
+ const tier = decl.tier ?? "presentation";
35108
+ const arr = byTier.get(tier) ?? [];
35109
+ arr.push([name, decl]);
35110
+ byTier.set(tier, arr);
35111
+ }
35112
+ const tiers = [...byTier.keys()].sort((a, b) => {
35113
+ const ia = TIER_ORDER.indexOf(a);
35114
+ const ib = TIER_ORDER.indexOf(b);
35115
+ return (ia === -1 ? 99 : ia) - (ib === -1 ? 99 : ib);
35116
+ });
35117
+ return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("w-full", className), children: [
35118
+ /* @__PURE__ */ jsxs(HStack, { justify: "between", align: "center", children: [
35119
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", weight: "bold", children: title ?? "Config" }),
35120
+ onReset !== void 0 && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", icon: "rotate-ccw", label: "Reset", onClick: onReset })
35121
+ ] }),
35122
+ fields.length === 0 && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: "No configurable properties." }),
35123
+ tiers.map((tier) => /* @__PURE__ */ jsx(FormSection, { title: tier, collapsible: true, defaultCollapsed: tier !== "presentation", children: /* @__PURE__ */ jsx(VStack, { gap: "sm", children: byTier.get(tier)?.map(([name, decl]) => /* @__PURE__ */ jsx(
35124
+ FieldControl,
35125
+ {
35126
+ name,
35127
+ decl,
35128
+ value: currentValue(decl, values?.[name]),
35129
+ onChange
35130
+ },
35131
+ name
35132
+ )) }) }, tier))
35133
+ ] });
35134
+ };
35135
+ }
35136
+ });
35016
35137
  var lookStyles8, Header;
35017
35138
  var init_Header = __esm({
35018
35139
  "components/core/molecules/Header.tsx"() {
@@ -36978,6 +37099,7 @@ var init_molecules2 = __esm({
36978
37099
  init_ModuleCard();
36979
37100
  init_PageHeader();
36980
37101
  init_FormSection();
37102
+ init_PropertyInspector();
36981
37103
  init_Header();
36982
37104
  init_Navigation();
36983
37105
  init_Section();
@@ -39399,13 +39521,13 @@ var init_Form = __esm({
39399
39521
  }
39400
39522
  const inputType = determineInputType(field);
39401
39523
  const label = field.label || fieldName.charAt(0).toUpperCase() + fieldName.slice(1).replace(/([A-Z])/g, " $1");
39402
- const currentValue = formData[fieldName] ?? field.defaultValue ?? "";
39524
+ const currentValue2 = formData[fieldName] ?? field.defaultValue ?? "";
39403
39525
  return /* @__PURE__ */ jsxs(VStack, { gap: "xs", "data-field": fieldName, children: [
39404
39526
  inputType !== "checkbox" && /* @__PURE__ */ jsxs(Typography, { as: "label", variant: "label", weight: "bold", children: [
39405
39527
  label,
39406
39528
  field.required && /* @__PURE__ */ jsx(Typography, { as: "span", color: "error", className: "ml-1", children: "*" })
39407
39529
  ] }),
39408
- renderFieldInput(field, fieldName, inputType, currentValue, label)
39530
+ renderFieldInput(field, fieldName, inputType, currentValue2, label)
39409
39531
  ] }, fieldName);
39410
39532
  },
39411
39533
  [formData, isFieldVisible, relationsData, relationsLoading, isLoading]
@@ -39480,7 +39602,7 @@ var init_Form = __esm({
39480
39602
  ] }, section.id);
39481
39603
  }).filter(Boolean);
39482
39604
  }, [sections, isSectionVisible, collapsedSections, renderField, gap]);
39483
- function renderFieldInput(field, fieldName, inputType, currentValue, label) {
39605
+ function renderFieldInput(field, fieldName, inputType, currentValue2, label) {
39484
39606
  const commonProps = {
39485
39607
  id: fieldName,
39486
39608
  name: fieldName,
@@ -39497,7 +39619,7 @@ var init_Form = __esm({
39497
39619
  {
39498
39620
  ...commonProps,
39499
39621
  label: label + (field.required ? " *" : ""),
39500
- checked: Boolean(currentValue),
39622
+ checked: Boolean(currentValue2),
39501
39623
  onChange: (e) => handleChange(fieldName, e.target.checked)
39502
39624
  }
39503
39625
  );
@@ -39506,7 +39628,7 @@ var init_Form = __esm({
39506
39628
  Textarea,
39507
39629
  {
39508
39630
  ...commonProps,
39509
- value: String(currentValue),
39631
+ value: String(currentValue2),
39510
39632
  onChange: (e) => handleChange(fieldName, e.target.value),
39511
39633
  minLength: field.min,
39512
39634
  maxLength: field.max
@@ -39519,7 +39641,7 @@ var init_Form = __esm({
39519
39641
  {
39520
39642
  ...commonProps,
39521
39643
  options,
39522
- value: String(currentValue),
39644
+ value: String(currentValue2),
39523
39645
  onChange: (e) => handleChange(fieldName, e.target.value),
39524
39646
  placeholder: field.placeholder || `Select ${label}...`
39525
39647
  }
@@ -39532,7 +39654,7 @@ var init_Form = __esm({
39532
39654
  RelationSelect,
39533
39655
  {
39534
39656
  ...commonProps,
39535
- value: currentValue ? String(currentValue) : void 0,
39657
+ value: currentValue2 ? String(currentValue2) : void 0,
39536
39658
  onChange: (value) => handleChange(fieldName, value),
39537
39659
  options: relationOptions,
39538
39660
  isLoading: relationLoading,
@@ -39548,7 +39670,7 @@ var init_Form = __esm({
39548
39670
  {
39549
39671
  ...commonProps,
39550
39672
  type: "number",
39551
- value: currentValue !== void 0 && currentValue !== "" ? String(currentValue) : "",
39673
+ value: currentValue2 !== void 0 && currentValue2 !== "" ? String(currentValue2) : "",
39552
39674
  onChange: (e) => handleChange(
39553
39675
  fieldName,
39554
39676
  e.target.value ? Number(e.target.value) : void 0
@@ -39563,7 +39685,7 @@ var init_Form = __esm({
39563
39685
  {
39564
39686
  ...commonProps,
39565
39687
  type: "date",
39566
- value: formatDateValue(currentValue),
39688
+ value: formatDateValue(currentValue2),
39567
39689
  onChange: (e) => handleChange(fieldName, e.target.value)
39568
39690
  }
39569
39691
  );
@@ -39573,7 +39695,7 @@ var init_Form = __esm({
39573
39695
  {
39574
39696
  ...commonProps,
39575
39697
  type: "datetime-local",
39576
- value: formatDateTimeValue(currentValue),
39698
+ value: formatDateTimeValue(currentValue2),
39577
39699
  onChange: (e) => handleChange(fieldName, e.target.value)
39578
39700
  }
39579
39701
  );
@@ -39583,7 +39705,7 @@ var init_Form = __esm({
39583
39705
  {
39584
39706
  ...commonProps,
39585
39707
  type: "email",
39586
- value: String(currentValue),
39708
+ value: String(currentValue2),
39587
39709
  onChange: (e) => handleChange(fieldName, e.target.value),
39588
39710
  minLength: field.min,
39589
39711
  maxLength: field.max
@@ -39595,7 +39717,7 @@ var init_Form = __esm({
39595
39717
  {
39596
39718
  ...commonProps,
39597
39719
  type: "url",
39598
- value: String(currentValue),
39720
+ value: String(currentValue2),
39599
39721
  onChange: (e) => handleChange(fieldName, e.target.value),
39600
39722
  minLength: field.min,
39601
39723
  maxLength: field.max
@@ -39607,7 +39729,7 @@ var init_Form = __esm({
39607
39729
  {
39608
39730
  ...commonProps,
39609
39731
  type: "password",
39610
- value: String(currentValue),
39732
+ value: String(currentValue2),
39611
39733
  onChange: (e) => handleChange(fieldName, e.target.value),
39612
39734
  minLength: field.min,
39613
39735
  maxLength: field.max
@@ -39620,7 +39742,7 @@ var init_Form = __esm({
39620
39742
  {
39621
39743
  ...commonProps,
39622
39744
  type: "text",
39623
- value: String(currentValue),
39745
+ value: String(currentValue2),
39624
39746
  onChange: (e) => handleChange(fieldName, e.target.value),
39625
39747
  minLength: field.min,
39626
39748
  maxLength: field.max
@@ -44821,7 +44943,7 @@ var init_StatCard = __esm({
44821
44943
  title: propTitle,
44822
44944
  value: propValue,
44823
44945
  previousValue,
44824
- currentValue,
44946
+ currentValue: currentValue2,
44825
44947
  trend: manualTrend,
44826
44948
  trendDirection: manualDirection,
44827
44949
  invertTrend = false,
@@ -44902,11 +45024,11 @@ var init_StatCard = __esm({
44902
45024
  }, [metrics, data, computeMetricValue]);
44903
45025
  const calculatedTrend = React80__default.useMemo(() => {
44904
45026
  if (manualTrend !== void 0) return manualTrend;
44905
- if (previousValue === void 0 || currentValue === void 0)
45027
+ if (previousValue === void 0 || currentValue2 === void 0)
44906
45028
  return void 0;
44907
- if (previousValue === 0) return currentValue > 0 ? 100 : 0;
44908
- return (currentValue - previousValue) / previousValue * 100;
44909
- }, [manualTrend, previousValue, currentValue]);
45029
+ if (previousValue === 0) return currentValue2 > 0 ? 100 : 0;
45030
+ return (currentValue2 - previousValue) / previousValue * 100;
45031
+ }, [manualTrend, previousValue, currentValue2]);
44910
45032
  if (schemaStats && schemaStats.length > 1) {
44911
45033
  if (isLoading) {
44912
45034
  return /* @__PURE__ */ jsx(
@@ -49441,4 +49563,4 @@ init_AboutPageTemplate();
49441
49563
  // components/index.ts
49442
49564
  init_cn();
49443
49565
 
49444
- export { ALL_PRESETS, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, ActionButtons, Card2 as ActionCard, ActionPalette, ActionTile, Alert, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, 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, CodeView, CodeViewer, 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, DocCodeBlock, 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, HStack, Header, Heading, HealthBar, HealthPanel, HeroOrganism, HeroSection, IDENTITY_BOOK_FIELDS, Icon, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, InventoryPanel, IsometricCanvas, ItemSlot, JazariStateMachine, 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, NotifyListener, NumberStepper, ObjectRulePanel, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PatternTile, PhysicsManager, PlatformerCanvas, Popover, PositionedCanvas, PowerupSlots, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, 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, 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, Text, 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, transitionAnimation, useAnchorRect, useBattleState, useCamera, useGameAudio, useGameAudioContext, useImageCache, usePhysics2D, useSpriteAnimations };
49566
+ export { ALL_PRESETS, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, ActionButtons, Card2 as ActionCard, ActionPalette, ActionTile, Alert, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, 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, CodeView, CodeViewer, 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, DocCodeBlock, 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, HStack, Header, Heading, HealthBar, HealthPanel, HeroOrganism, HeroSection, IDENTITY_BOOK_FIELDS, Icon, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, InventoryPanel, IsometricCanvas, ItemSlot, JazariStateMachine, 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, 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, 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, Text, 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, transitionAnimation, useAnchorRect, useBattleState, useCamera, useGameAudio, useGameAudioContext, useImageCache, usePhysics2D, useSpriteAnimations };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "5.22.3",
3
+ "version": "5.23.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -129,7 +129,7 @@
129
129
  "typecheck": "tsc --noEmit"
130
130
  },
131
131
  "dependencies": {
132
- "@almadar/core": "^10.0.0",
132
+ "@almadar/core": "^10.1.0",
133
133
  "@almadar/evaluator": ">=2.9.2",
134
134
  "@almadar/logger": "^1.3.0",
135
135
  "@almadar/patterns": ">=2.35.0",