@almadar/ui 4.29.0 → 4.29.1

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.
@@ -3,7 +3,7 @@ import { jsx, jsxs } from 'react/jsx-runtime';
3
3
  import * as LucideIcons from 'lucide-react';
4
4
  import { Loader2, ChevronDown, X } from 'lucide-react';
5
5
 
6
- // node_modules/clsx/dist/clsx.mjs
6
+ // node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
7
7
  function r(e) {
8
8
  var t, f, n = "";
9
9
  if ("string" == typeof e || "number" == typeof e) n += e;
@@ -18,7 +18,7 @@ function clsx() {
18
18
  return n;
19
19
  }
20
20
 
21
- // node_modules/tailwind-merge/dist/bundle-mjs.mjs
21
+ // node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs
22
22
  var CLASS_PART_SEPARATOR = "-";
23
23
  var createClassGroupUtils = (config) => {
24
24
  const classMap = createClassMap(config);
@@ -27,7 +27,7 @@ function _interopNamespace(e) {
27
27
  var React6__default = /*#__PURE__*/_interopDefault(React6);
28
28
  var LucideIcons__namespace = /*#__PURE__*/_interopNamespace(LucideIcons);
29
29
 
30
- // node_modules/clsx/dist/clsx.mjs
30
+ // node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
31
31
  function r(e) {
32
32
  var t, f3, n = "";
33
33
  if ("string" == typeof e || "number" == typeof e) n += e;
@@ -42,7 +42,7 @@ function clsx() {
42
42
  return n;
43
43
  }
44
44
 
45
- // node_modules/tailwind-merge/dist/bundle-mjs.mjs
45
+ // node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs
46
46
  var CLASS_PART_SEPARATOR = "-";
47
47
  var createClassGroupUtils = (config) => {
48
48
  const classMap = createClassMap(config);
@@ -3,7 +3,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
  import * as LucideIcons from 'lucide-react';
4
4
  import { Loader2, Check, User } from 'lucide-react';
5
5
 
6
- // node_modules/clsx/dist/clsx.mjs
6
+ // node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
7
7
  function r(e) {
8
8
  var t, f3, n = "";
9
9
  if ("string" == typeof e || "number" == typeof e) n += e;
@@ -18,7 +18,7 @@ function clsx() {
18
18
  return n;
19
19
  }
20
20
 
21
- // node_modules/tailwind-merge/dist/bundle-mjs.mjs
21
+ // node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs
22
22
  var CLASS_PART_SEPARATOR = "-";
23
23
  var createClassGroupUtils = (config) => {
24
24
  const classMap = createClassMap(config);
@@ -9595,9 +9595,9 @@ var init_ScaledDiagram = __esm({
9595
9595
  }
9596
9596
  });
9597
9597
 
9598
- // node_modules/katex/dist/katex.min.css
9598
+ // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
9599
9599
  var init_katex_min = __esm({
9600
- "node_modules/katex/dist/katex.min.css"() {
9600
+ "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
9601
9601
  }
9602
9602
  });
9603
9603
  var MarkdownContent;
@@ -26091,6 +26091,8 @@ var init_Form = __esm({
26091
26091
  const [collapsedSections, setCollapsedSections] = React105__namespace.default.useState(
26092
26092
  /* @__PURE__ */ new Set()
26093
26093
  );
26094
+ const [submitError, setSubmitError] = React105__namespace.default.useState(null);
26095
+ const formRef = React105__namespace.default.useRef(null);
26094
26096
  const formMode = props.mode;
26095
26097
  const mountedRef = React105__namespace.default.useRef(false);
26096
26098
  if (!mountedRef.current) {
@@ -26216,6 +26218,7 @@ var init_Form = __esm({
26216
26218
  };
26217
26219
  const handleSubmit = (e) => {
26218
26220
  e.preventDefault();
26221
+ setSubmitError(null);
26219
26222
  debug("forms", "submit-enter", {
26220
26223
  mode: formMode,
26221
26224
  submitEvent,
@@ -26233,6 +26236,37 @@ var init_Form = __esm({
26233
26236
  eventBus.emit(`UI:${onSubmit}`, payload);
26234
26237
  }
26235
26238
  };
26239
+ const handleInvalid = (e) => {
26240
+ const target = e.target;
26241
+ const fieldName = target.getAttribute("data-field-name") ?? target.name ?? "";
26242
+ const fieldMessage = target.validationMessage || "Invalid value";
26243
+ debug("forms", "invalid", { mode: formMode, fieldName, fieldMessage });
26244
+ queueMicrotask(() => {
26245
+ const form = formRef.current;
26246
+ if (!form) return;
26247
+ const invalidEls = Array.from(
26248
+ form.querySelectorAll(
26249
+ ":invalid"
26250
+ )
26251
+ );
26252
+ if (invalidEls.length === 0) return;
26253
+ const missing = invalidEls.map(
26254
+ (el) => el.getAttribute("data-field-name") ?? el.name ?? ""
26255
+ );
26256
+ const messages = invalidEls.map((el) => ({
26257
+ field: el.getAttribute("data-field-name") ?? el.name ?? "",
26258
+ message: el.validationMessage
26259
+ }));
26260
+ const summary = missing.length === 1 ? `${missing[0]}: ${messages[0]?.message}` : `Please fix ${missing.length} fields: ${missing.join(", ")}`;
26261
+ setSubmitError(summary);
26262
+ eventBus.emit("UI:VALIDATION_FAILED", {
26263
+ submitEvent,
26264
+ missing,
26265
+ messages,
26266
+ summary
26267
+ });
26268
+ });
26269
+ };
26236
26270
  const handleCancel = () => {
26237
26271
  eventBus.emit(`UI:${cancelEvent}`);
26238
26272
  eventBus.emit("UI:CLOSE");
@@ -26336,7 +26370,8 @@ var init_Form = __esm({
26336
26370
  "data-field-name": fieldName,
26337
26371
  required: field.required,
26338
26372
  disabled: isLoading,
26339
- placeholder: field.placeholder
26373
+ placeholder: field.placeholder,
26374
+ pattern: field.pattern
26340
26375
  };
26341
26376
  switch (inputType) {
26342
26377
  case "checkbox":
@@ -26432,7 +26467,9 @@ var init_Form = __esm({
26432
26467
  ...commonProps,
26433
26468
  type: "email",
26434
26469
  value: String(currentValue),
26435
- onChange: (e) => handleChange(fieldName, e.target.value)
26470
+ onChange: (e) => handleChange(fieldName, e.target.value),
26471
+ minLength: field.min,
26472
+ maxLength: field.max
26436
26473
  }
26437
26474
  );
26438
26475
  case "url":
@@ -26442,7 +26479,9 @@ var init_Form = __esm({
26442
26479
  ...commonProps,
26443
26480
  type: "url",
26444
26481
  value: String(currentValue),
26445
- onChange: (e) => handleChange(fieldName, e.target.value)
26482
+ onChange: (e) => handleChange(fieldName, e.target.value),
26483
+ minLength: field.min,
26484
+ maxLength: field.max
26446
26485
  }
26447
26486
  );
26448
26487
  case "password":
@@ -26452,7 +26491,9 @@ var init_Form = __esm({
26452
26491
  ...commonProps,
26453
26492
  type: "password",
26454
26493
  value: String(currentValue),
26455
- onChange: (e) => handleChange(fieldName, e.target.value)
26494
+ onChange: (e) => handleChange(fieldName, e.target.value),
26495
+ minLength: field.min,
26496
+ maxLength: field.max
26456
26497
  }
26457
26498
  );
26458
26499
  case "text":
@@ -26465,8 +26506,7 @@ var init_Form = __esm({
26465
26506
  value: String(currentValue),
26466
26507
  onChange: (e) => handleChange(fieldName, e.target.value),
26467
26508
  minLength: field.min,
26468
- maxLength: field.max,
26469
- pattern: field.pattern
26509
+ maxLength: field.max
26470
26510
  }
26471
26511
  );
26472
26512
  }
@@ -26474,12 +26514,14 @@ var init_Form = __esm({
26474
26514
  return /* @__PURE__ */ jsxRuntime.jsxs(
26475
26515
  "form",
26476
26516
  {
26477
- noValidate: true,
26517
+ ref: formRef,
26478
26518
  "data-pattern": "form-section",
26479
26519
  className: cn(layoutStyles[layout], gapStyles8[gap], className),
26480
26520
  onSubmit: handleSubmit,
26521
+ onInvalid: handleInvalid,
26481
26522
  ...props,
26482
26523
  children: [
26524
+ submitError && /* @__PURE__ */ jsxRuntime.jsx(Alert, { variant: "error", className: "mb-4", children: submitError }),
26483
26525
  error && /* @__PURE__ */ jsxRuntime.jsx(Alert, { variant: "error", className: "mb-4", children: error.message || t("error.occurred") }),
26484
26526
  sectionElements && sectionElements.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: gap === "sm" ? "sm" : gap === "lg" ? "lg" : "md", children: sectionElements }),
26485
26527
  schemaFields,
@@ -1,4 +1,4 @@
1
- /* node_modules/katex/dist/katex.min.css */
1
+ /* node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css */
2
2
  @font-face {
3
3
  font-display: block;
4
4
  font-family: KaTeX_AMS;
@@ -9550,9 +9550,9 @@ var init_ScaledDiagram = __esm({
9550
9550
  }
9551
9551
  });
9552
9552
 
9553
- // node_modules/katex/dist/katex.min.css
9553
+ // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
9554
9554
  var init_katex_min = __esm({
9555
- "node_modules/katex/dist/katex.min.css"() {
9555
+ "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
9556
9556
  }
9557
9557
  });
9558
9558
  var MarkdownContent;
@@ -26046,6 +26046,8 @@ var init_Form = __esm({
26046
26046
  const [collapsedSections, setCollapsedSections] = React105__default.useState(
26047
26047
  /* @__PURE__ */ new Set()
26048
26048
  );
26049
+ const [submitError, setSubmitError] = React105__default.useState(null);
26050
+ const formRef = React105__default.useRef(null);
26049
26051
  const formMode = props.mode;
26050
26052
  const mountedRef = React105__default.useRef(false);
26051
26053
  if (!mountedRef.current) {
@@ -26171,6 +26173,7 @@ var init_Form = __esm({
26171
26173
  };
26172
26174
  const handleSubmit = (e) => {
26173
26175
  e.preventDefault();
26176
+ setSubmitError(null);
26174
26177
  debug("forms", "submit-enter", {
26175
26178
  mode: formMode,
26176
26179
  submitEvent,
@@ -26188,6 +26191,37 @@ var init_Form = __esm({
26188
26191
  eventBus.emit(`UI:${onSubmit}`, payload);
26189
26192
  }
26190
26193
  };
26194
+ const handleInvalid = (e) => {
26195
+ const target = e.target;
26196
+ const fieldName = target.getAttribute("data-field-name") ?? target.name ?? "";
26197
+ const fieldMessage = target.validationMessage || "Invalid value";
26198
+ debug("forms", "invalid", { mode: formMode, fieldName, fieldMessage });
26199
+ queueMicrotask(() => {
26200
+ const form = formRef.current;
26201
+ if (!form) return;
26202
+ const invalidEls = Array.from(
26203
+ form.querySelectorAll(
26204
+ ":invalid"
26205
+ )
26206
+ );
26207
+ if (invalidEls.length === 0) return;
26208
+ const missing = invalidEls.map(
26209
+ (el) => el.getAttribute("data-field-name") ?? el.name ?? ""
26210
+ );
26211
+ const messages = invalidEls.map((el) => ({
26212
+ field: el.getAttribute("data-field-name") ?? el.name ?? "",
26213
+ message: el.validationMessage
26214
+ }));
26215
+ const summary = missing.length === 1 ? `${missing[0]}: ${messages[0]?.message}` : `Please fix ${missing.length} fields: ${missing.join(", ")}`;
26216
+ setSubmitError(summary);
26217
+ eventBus.emit("UI:VALIDATION_FAILED", {
26218
+ submitEvent,
26219
+ missing,
26220
+ messages,
26221
+ summary
26222
+ });
26223
+ });
26224
+ };
26191
26225
  const handleCancel = () => {
26192
26226
  eventBus.emit(`UI:${cancelEvent}`);
26193
26227
  eventBus.emit("UI:CLOSE");
@@ -26291,7 +26325,8 @@ var init_Form = __esm({
26291
26325
  "data-field-name": fieldName,
26292
26326
  required: field.required,
26293
26327
  disabled: isLoading,
26294
- placeholder: field.placeholder
26328
+ placeholder: field.placeholder,
26329
+ pattern: field.pattern
26295
26330
  };
26296
26331
  switch (inputType) {
26297
26332
  case "checkbox":
@@ -26387,7 +26422,9 @@ var init_Form = __esm({
26387
26422
  ...commonProps,
26388
26423
  type: "email",
26389
26424
  value: String(currentValue),
26390
- onChange: (e) => handleChange(fieldName, e.target.value)
26425
+ onChange: (e) => handleChange(fieldName, e.target.value),
26426
+ minLength: field.min,
26427
+ maxLength: field.max
26391
26428
  }
26392
26429
  );
26393
26430
  case "url":
@@ -26397,7 +26434,9 @@ var init_Form = __esm({
26397
26434
  ...commonProps,
26398
26435
  type: "url",
26399
26436
  value: String(currentValue),
26400
- onChange: (e) => handleChange(fieldName, e.target.value)
26437
+ onChange: (e) => handleChange(fieldName, e.target.value),
26438
+ minLength: field.min,
26439
+ maxLength: field.max
26401
26440
  }
26402
26441
  );
26403
26442
  case "password":
@@ -26407,7 +26446,9 @@ var init_Form = __esm({
26407
26446
  ...commonProps,
26408
26447
  type: "password",
26409
26448
  value: String(currentValue),
26410
- onChange: (e) => handleChange(fieldName, e.target.value)
26449
+ onChange: (e) => handleChange(fieldName, e.target.value),
26450
+ minLength: field.min,
26451
+ maxLength: field.max
26411
26452
  }
26412
26453
  );
26413
26454
  case "text":
@@ -26420,8 +26461,7 @@ var init_Form = __esm({
26420
26461
  value: String(currentValue),
26421
26462
  onChange: (e) => handleChange(fieldName, e.target.value),
26422
26463
  minLength: field.min,
26423
- maxLength: field.max,
26424
- pattern: field.pattern
26464
+ maxLength: field.max
26425
26465
  }
26426
26466
  );
26427
26467
  }
@@ -26429,12 +26469,14 @@ var init_Form = __esm({
26429
26469
  return /* @__PURE__ */ jsxs(
26430
26470
  "form",
26431
26471
  {
26432
- noValidate: true,
26472
+ ref: formRef,
26433
26473
  "data-pattern": "form-section",
26434
26474
  className: cn(layoutStyles[layout], gapStyles8[gap], className),
26435
26475
  onSubmit: handleSubmit,
26476
+ onInvalid: handleInvalid,
26436
26477
  ...props,
26437
26478
  children: [
26479
+ submitError && /* @__PURE__ */ jsx(Alert, { variant: "error", className: "mb-4", children: submitError }),
26438
26480
  error && /* @__PURE__ */ jsx(Alert, { variant: "error", className: "mb-4", children: error.message || t("error.occurred") }),
26439
26481
  sectionElements && sectionElements.length > 0 && /* @__PURE__ */ jsx(VStack, { gap: gap === "sm" ? "sm" : gap === "lg" ? "lg" : "md", children: sectionElements }),
26440
26482
  schemaFields,
@@ -9495,9 +9495,9 @@ var init_ScaledDiagram = __esm({
9495
9495
  }
9496
9496
  });
9497
9497
 
9498
- // node_modules/katex/dist/katex.min.css
9498
+ // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
9499
9499
  var init_katex_min = __esm({
9500
- "node_modules/katex/dist/katex.min.css"() {
9500
+ "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
9501
9501
  }
9502
9502
  });
9503
9503
  var MarkdownContent;
@@ -25658,6 +25658,8 @@ var init_Form = __esm({
25658
25658
  const [collapsedSections, setCollapsedSections] = React104__namespace.default.useState(
25659
25659
  /* @__PURE__ */ new Set()
25660
25660
  );
25661
+ const [submitError, setSubmitError] = React104__namespace.default.useState(null);
25662
+ const formRef = React104__namespace.default.useRef(null);
25661
25663
  const formMode = props.mode;
25662
25664
  const mountedRef = React104__namespace.default.useRef(false);
25663
25665
  if (!mountedRef.current) {
@@ -25783,6 +25785,7 @@ var init_Form = __esm({
25783
25785
  };
25784
25786
  const handleSubmit = (e) => {
25785
25787
  e.preventDefault();
25788
+ setSubmitError(null);
25786
25789
  debug("forms", "submit-enter", {
25787
25790
  mode: formMode,
25788
25791
  submitEvent,
@@ -25800,6 +25803,37 @@ var init_Form = __esm({
25800
25803
  eventBus.emit(`UI:${onSubmit}`, payload);
25801
25804
  }
25802
25805
  };
25806
+ const handleInvalid = (e) => {
25807
+ const target = e.target;
25808
+ const fieldName = target.getAttribute("data-field-name") ?? target.name ?? "";
25809
+ const fieldMessage = target.validationMessage || "Invalid value";
25810
+ debug("forms", "invalid", { mode: formMode, fieldName, fieldMessage });
25811
+ queueMicrotask(() => {
25812
+ const form = formRef.current;
25813
+ if (!form) return;
25814
+ const invalidEls = Array.from(
25815
+ form.querySelectorAll(
25816
+ ":invalid"
25817
+ )
25818
+ );
25819
+ if (invalidEls.length === 0) return;
25820
+ const missing = invalidEls.map(
25821
+ (el) => el.getAttribute("data-field-name") ?? el.name ?? ""
25822
+ );
25823
+ const messages = invalidEls.map((el) => ({
25824
+ field: el.getAttribute("data-field-name") ?? el.name ?? "",
25825
+ message: el.validationMessage
25826
+ }));
25827
+ const summary = missing.length === 1 ? `${missing[0]}: ${messages[0]?.message}` : `Please fix ${missing.length} fields: ${missing.join(", ")}`;
25828
+ setSubmitError(summary);
25829
+ eventBus.emit("UI:VALIDATION_FAILED", {
25830
+ submitEvent,
25831
+ missing,
25832
+ messages,
25833
+ summary
25834
+ });
25835
+ });
25836
+ };
25803
25837
  const handleCancel = () => {
25804
25838
  eventBus.emit(`UI:${cancelEvent}`);
25805
25839
  eventBus.emit("UI:CLOSE");
@@ -25903,7 +25937,8 @@ var init_Form = __esm({
25903
25937
  "data-field-name": fieldName,
25904
25938
  required: field.required,
25905
25939
  disabled: isLoading,
25906
- placeholder: field.placeholder
25940
+ placeholder: field.placeholder,
25941
+ pattern: field.pattern
25907
25942
  };
25908
25943
  switch (inputType) {
25909
25944
  case "checkbox":
@@ -25999,7 +26034,9 @@ var init_Form = __esm({
25999
26034
  ...commonProps,
26000
26035
  type: "email",
26001
26036
  value: String(currentValue),
26002
- onChange: (e) => handleChange(fieldName, e.target.value)
26037
+ onChange: (e) => handleChange(fieldName, e.target.value),
26038
+ minLength: field.min,
26039
+ maxLength: field.max
26003
26040
  }
26004
26041
  );
26005
26042
  case "url":
@@ -26009,7 +26046,9 @@ var init_Form = __esm({
26009
26046
  ...commonProps,
26010
26047
  type: "url",
26011
26048
  value: String(currentValue),
26012
- onChange: (e) => handleChange(fieldName, e.target.value)
26049
+ onChange: (e) => handleChange(fieldName, e.target.value),
26050
+ minLength: field.min,
26051
+ maxLength: field.max
26013
26052
  }
26014
26053
  );
26015
26054
  case "password":
@@ -26019,7 +26058,9 @@ var init_Form = __esm({
26019
26058
  ...commonProps,
26020
26059
  type: "password",
26021
26060
  value: String(currentValue),
26022
- onChange: (e) => handleChange(fieldName, e.target.value)
26061
+ onChange: (e) => handleChange(fieldName, e.target.value),
26062
+ minLength: field.min,
26063
+ maxLength: field.max
26023
26064
  }
26024
26065
  );
26025
26066
  case "text":
@@ -26032,8 +26073,7 @@ var init_Form = __esm({
26032
26073
  value: String(currentValue),
26033
26074
  onChange: (e) => handleChange(fieldName, e.target.value),
26034
26075
  minLength: field.min,
26035
- maxLength: field.max,
26036
- pattern: field.pattern
26076
+ maxLength: field.max
26037
26077
  }
26038
26078
  );
26039
26079
  }
@@ -26041,12 +26081,14 @@ var init_Form = __esm({
26041
26081
  return /* @__PURE__ */ jsxRuntime.jsxs(
26042
26082
  "form",
26043
26083
  {
26044
- noValidate: true,
26084
+ ref: formRef,
26045
26085
  "data-pattern": "form-section",
26046
26086
  className: cn(layoutStyles[layout], gapStyles8[gap], className),
26047
26087
  onSubmit: handleSubmit,
26088
+ onInvalid: handleInvalid,
26048
26089
  ...props,
26049
26090
  children: [
26091
+ submitError && /* @__PURE__ */ jsxRuntime.jsx(Alert, { variant: "error", className: "mb-4", children: submitError }),
26050
26092
  error && /* @__PURE__ */ jsxRuntime.jsx(Alert, { variant: "error", className: "mb-4", children: error.message || t("error.occurred") }),
26051
26093
  sectionElements && sectionElements.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: gap === "sm" ? "sm" : gap === "lg" ? "lg" : "md", children: sectionElements }),
26052
26094
  schemaFields,
@@ -36106,6 +36148,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
36106
36148
  }
36107
36149
  console.log("[TraitStateMachine] Subscribing to events:", Array.from(allEvents));
36108
36150
  const unsubscribes = [];
36151
+ const subscribedBusKeys = /* @__PURE__ */ new Set();
36109
36152
  for (const binding of traitBindings) {
36110
36153
  const traitName = binding.trait.name;
36111
36154
  const orbitalName = orbitalsByTrait?.[traitName];
@@ -36116,6 +36159,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
36116
36159
  continue;
36117
36160
  }
36118
36161
  const selfBusKey = `UI:${orbitalName}.${traitName}.${eventKey}`;
36162
+ if (subscribedBusKeys.has(selfBusKey)) continue;
36163
+ subscribedBusKeys.add(selfBusKey);
36119
36164
  crossTraitLog.debug("self:subscribe", { traitName, busKey: selfBusKey, eventKey });
36120
36165
  const unsub = eventBus.on(selfBusKey, (event) => {
36121
36166
  if (event.source && event.source.dispatched) {
@@ -1,4 +1,4 @@
1
- /* node_modules/katex/dist/katex.min.css */
1
+ /* node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css */
2
2
  @font-face {
3
3
  font-display: block;
4
4
  font-family: KaTeX_AMS;
@@ -9450,9 +9450,9 @@ var init_ScaledDiagram = __esm({
9450
9450
  }
9451
9451
  });
9452
9452
 
9453
- // node_modules/katex/dist/katex.min.css
9453
+ // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
9454
9454
  var init_katex_min = __esm({
9455
- "node_modules/katex/dist/katex.min.css"() {
9455
+ "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
9456
9456
  }
9457
9457
  });
9458
9458
  var MarkdownContent;
@@ -25613,6 +25613,8 @@ var init_Form = __esm({
25613
25613
  const [collapsedSections, setCollapsedSections] = React104__default.useState(
25614
25614
  /* @__PURE__ */ new Set()
25615
25615
  );
25616
+ const [submitError, setSubmitError] = React104__default.useState(null);
25617
+ const formRef = React104__default.useRef(null);
25616
25618
  const formMode = props.mode;
25617
25619
  const mountedRef = React104__default.useRef(false);
25618
25620
  if (!mountedRef.current) {
@@ -25738,6 +25740,7 @@ var init_Form = __esm({
25738
25740
  };
25739
25741
  const handleSubmit = (e) => {
25740
25742
  e.preventDefault();
25743
+ setSubmitError(null);
25741
25744
  debug("forms", "submit-enter", {
25742
25745
  mode: formMode,
25743
25746
  submitEvent,
@@ -25755,6 +25758,37 @@ var init_Form = __esm({
25755
25758
  eventBus.emit(`UI:${onSubmit}`, payload);
25756
25759
  }
25757
25760
  };
25761
+ const handleInvalid = (e) => {
25762
+ const target = e.target;
25763
+ const fieldName = target.getAttribute("data-field-name") ?? target.name ?? "";
25764
+ const fieldMessage = target.validationMessage || "Invalid value";
25765
+ debug("forms", "invalid", { mode: formMode, fieldName, fieldMessage });
25766
+ queueMicrotask(() => {
25767
+ const form = formRef.current;
25768
+ if (!form) return;
25769
+ const invalidEls = Array.from(
25770
+ form.querySelectorAll(
25771
+ ":invalid"
25772
+ )
25773
+ );
25774
+ if (invalidEls.length === 0) return;
25775
+ const missing = invalidEls.map(
25776
+ (el) => el.getAttribute("data-field-name") ?? el.name ?? ""
25777
+ );
25778
+ const messages = invalidEls.map((el) => ({
25779
+ field: el.getAttribute("data-field-name") ?? el.name ?? "",
25780
+ message: el.validationMessage
25781
+ }));
25782
+ const summary = missing.length === 1 ? `${missing[0]}: ${messages[0]?.message}` : `Please fix ${missing.length} fields: ${missing.join(", ")}`;
25783
+ setSubmitError(summary);
25784
+ eventBus.emit("UI:VALIDATION_FAILED", {
25785
+ submitEvent,
25786
+ missing,
25787
+ messages,
25788
+ summary
25789
+ });
25790
+ });
25791
+ };
25758
25792
  const handleCancel = () => {
25759
25793
  eventBus.emit(`UI:${cancelEvent}`);
25760
25794
  eventBus.emit("UI:CLOSE");
@@ -25858,7 +25892,8 @@ var init_Form = __esm({
25858
25892
  "data-field-name": fieldName,
25859
25893
  required: field.required,
25860
25894
  disabled: isLoading,
25861
- placeholder: field.placeholder
25895
+ placeholder: field.placeholder,
25896
+ pattern: field.pattern
25862
25897
  };
25863
25898
  switch (inputType) {
25864
25899
  case "checkbox":
@@ -25954,7 +25989,9 @@ var init_Form = __esm({
25954
25989
  ...commonProps,
25955
25990
  type: "email",
25956
25991
  value: String(currentValue),
25957
- onChange: (e) => handleChange(fieldName, e.target.value)
25992
+ onChange: (e) => handleChange(fieldName, e.target.value),
25993
+ minLength: field.min,
25994
+ maxLength: field.max
25958
25995
  }
25959
25996
  );
25960
25997
  case "url":
@@ -25964,7 +26001,9 @@ var init_Form = __esm({
25964
26001
  ...commonProps,
25965
26002
  type: "url",
25966
26003
  value: String(currentValue),
25967
- onChange: (e) => handleChange(fieldName, e.target.value)
26004
+ onChange: (e) => handleChange(fieldName, e.target.value),
26005
+ minLength: field.min,
26006
+ maxLength: field.max
25968
26007
  }
25969
26008
  );
25970
26009
  case "password":
@@ -25974,7 +26013,9 @@ var init_Form = __esm({
25974
26013
  ...commonProps,
25975
26014
  type: "password",
25976
26015
  value: String(currentValue),
25977
- onChange: (e) => handleChange(fieldName, e.target.value)
26016
+ onChange: (e) => handleChange(fieldName, e.target.value),
26017
+ minLength: field.min,
26018
+ maxLength: field.max
25978
26019
  }
25979
26020
  );
25980
26021
  case "text":
@@ -25987,8 +26028,7 @@ var init_Form = __esm({
25987
26028
  value: String(currentValue),
25988
26029
  onChange: (e) => handleChange(fieldName, e.target.value),
25989
26030
  minLength: field.min,
25990
- maxLength: field.max,
25991
- pattern: field.pattern
26031
+ maxLength: field.max
25992
26032
  }
25993
26033
  );
25994
26034
  }
@@ -25996,12 +26036,14 @@ var init_Form = __esm({
25996
26036
  return /* @__PURE__ */ jsxs(
25997
26037
  "form",
25998
26038
  {
25999
- noValidate: true,
26039
+ ref: formRef,
26000
26040
  "data-pattern": "form-section",
26001
26041
  className: cn(layoutStyles[layout], gapStyles8[gap], className),
26002
26042
  onSubmit: handleSubmit,
26043
+ onInvalid: handleInvalid,
26003
26044
  ...props,
26004
26045
  children: [
26046
+ submitError && /* @__PURE__ */ jsx(Alert, { variant: "error", className: "mb-4", children: submitError }),
26005
26047
  error && /* @__PURE__ */ jsx(Alert, { variant: "error", className: "mb-4", children: error.message || t("error.occurred") }),
26006
26048
  sectionElements && sectionElements.length > 0 && /* @__PURE__ */ jsx(VStack, { gap: gap === "sm" ? "sm" : gap === "lg" ? "lg" : "md", children: sectionElements }),
26007
26049
  schemaFields,
@@ -36061,6 +36103,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
36061
36103
  }
36062
36104
  console.log("[TraitStateMachine] Subscribing to events:", Array.from(allEvents));
36063
36105
  const unsubscribes = [];
36106
+ const subscribedBusKeys = /* @__PURE__ */ new Set();
36064
36107
  for (const binding of traitBindings) {
36065
36108
  const traitName = binding.trait.name;
36066
36109
  const orbitalName = orbitalsByTrait?.[traitName];
@@ -36071,6 +36114,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
36071
36114
  continue;
36072
36115
  }
36073
36116
  const selfBusKey = `UI:${orbitalName}.${traitName}.${eventKey}`;
36117
+ if (subscribedBusKeys.has(selfBusKey)) continue;
36118
+ subscribedBusKeys.add(selfBusKey);
36074
36119
  crossTraitLog.debug("self:subscribe", { traitName, busKey: selfBusKey, eventKey });
36075
36120
  const unsub = eventBus.on(selfBusKey, (event) => {
36076
36121
  if (event.source && event.source.dispatched) {