@almadar/ui 4.29.0 → 4.30.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.
@@ -182,7 +182,7 @@ var init_types = __esm({
182
182
  }
183
183
  });
184
184
 
185
- // node_modules/clsx/dist/clsx.mjs
185
+ // node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
186
186
  function r(e) {
187
187
  var t, f, n = "";
188
188
  if ("string" == typeof e || "number" == typeof e) n += e;
@@ -197,11 +197,11 @@ function clsx() {
197
197
  return n;
198
198
  }
199
199
  var init_clsx = __esm({
200
- "node_modules/clsx/dist/clsx.mjs"() {
200
+ "node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs"() {
201
201
  }
202
202
  });
203
203
 
204
- // node_modules/tailwind-merge/dist/bundle-mjs.mjs
204
+ // node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs
205
205
  function twJoin() {
206
206
  let index = 0;
207
207
  let argument;
@@ -245,7 +245,7 @@ function createTailwindMerge(createConfigFirst, ...createConfigRest) {
245
245
  }
246
246
  var CLASS_PART_SEPARATOR, createClassGroupUtils, getGroupRecursive, arbitraryPropertyRegex, getGroupIdForArbitraryProperty, createClassMap, processClassesRecursively, getPart, isThemeGetter, getPrefixedClassGroupEntries, createLruCache, IMPORTANT_MODIFIER, createParseClassName, sortModifiers, createConfigUtils, SPLIT_CLASSES_REGEX, mergeClassList, toValue, fromTheme, arbitraryValueRegex, fractionRegex, stringLengths, tshirtUnitRegex, lengthUnitRegex, colorFunctionRegex, shadowRegex, imageRegex, isLength, isArbitraryLength, isNumber, isArbitraryNumber, isInteger, isPercent, isArbitraryValue, isTshirtSize, sizeLabels, isArbitrarySize, isArbitraryPosition, imageLabels, isArbitraryImage, isArbitraryShadow, isAny, getIsArbitraryValue, isLengthOnly, isNever, isShadow, isImage, getDefaultConfig, twMerge;
247
247
  var init_bundle_mjs = __esm({
248
- "node_modules/tailwind-merge/dist/bundle-mjs.mjs"() {
248
+ "node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs"() {
249
249
  CLASS_PART_SEPARATOR = "-";
250
250
  createClassGroupUtils = (config) => {
251
251
  const classMap = createClassMap(config);
@@ -12838,9 +12838,9 @@ var init_ScaledDiagram = __esm({
12838
12838
  }
12839
12839
  });
12840
12840
 
12841
- // node_modules/katex/dist/katex.min.css
12841
+ // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
12842
12842
  var init_katex_min = __esm({
12843
- "node_modules/katex/dist/katex.min.css"() {
12843
+ "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
12844
12844
  }
12845
12845
  });
12846
12846
  var MarkdownContent;
@@ -29334,6 +29334,8 @@ var init_Form = __esm({
29334
29334
  const [collapsedSections, setCollapsedSections] = React118__namespace.default.useState(
29335
29335
  /* @__PURE__ */ new Set()
29336
29336
  );
29337
+ const [submitError, setSubmitError] = React118__namespace.default.useState(null);
29338
+ const formRef = React118__namespace.default.useRef(null);
29337
29339
  const formMode = props.mode;
29338
29340
  const mountedRef = React118__namespace.default.useRef(false);
29339
29341
  if (!mountedRef.current) {
@@ -29459,6 +29461,7 @@ var init_Form = __esm({
29459
29461
  };
29460
29462
  const handleSubmit = (e) => {
29461
29463
  e.preventDefault();
29464
+ setSubmitError(null);
29462
29465
  debug("forms", "submit-enter", {
29463
29466
  mode: formMode,
29464
29467
  submitEvent,
@@ -29476,6 +29479,37 @@ var init_Form = __esm({
29476
29479
  eventBus.emit(`UI:${onSubmit}`, payload);
29477
29480
  }
29478
29481
  };
29482
+ const handleInvalid = (e) => {
29483
+ const target = e.target;
29484
+ const fieldName = target.getAttribute("data-field-name") ?? target.name ?? "";
29485
+ const fieldMessage = target.validationMessage || "Invalid value";
29486
+ debug("forms", "invalid", { mode: formMode, fieldName, fieldMessage });
29487
+ queueMicrotask(() => {
29488
+ const form = formRef.current;
29489
+ if (!form) return;
29490
+ const invalidEls = Array.from(
29491
+ form.querySelectorAll(
29492
+ ":invalid"
29493
+ )
29494
+ );
29495
+ if (invalidEls.length === 0) return;
29496
+ const missing = invalidEls.map(
29497
+ (el) => el.getAttribute("data-field-name") ?? el.name ?? ""
29498
+ );
29499
+ const messages = invalidEls.map((el) => ({
29500
+ field: el.getAttribute("data-field-name") ?? el.name ?? "",
29501
+ message: el.validationMessage
29502
+ }));
29503
+ const summary = missing.length === 1 ? `${missing[0]}: ${messages[0]?.message}` : `Please fix ${missing.length} fields: ${missing.join(", ")}`;
29504
+ setSubmitError(summary);
29505
+ eventBus.emit("UI:VALIDATION_FAILED", {
29506
+ submitEvent,
29507
+ missing,
29508
+ messages,
29509
+ summary
29510
+ });
29511
+ });
29512
+ };
29479
29513
  const handleCancel = () => {
29480
29514
  eventBus.emit(`UI:${cancelEvent}`);
29481
29515
  eventBus.emit("UI:CLOSE");
@@ -29579,7 +29613,8 @@ var init_Form = __esm({
29579
29613
  "data-field-name": fieldName,
29580
29614
  required: field.required,
29581
29615
  disabled: isLoading,
29582
- placeholder: field.placeholder
29616
+ placeholder: field.placeholder,
29617
+ pattern: field.pattern
29583
29618
  };
29584
29619
  switch (inputType) {
29585
29620
  case "checkbox":
@@ -29675,7 +29710,9 @@ var init_Form = __esm({
29675
29710
  ...commonProps,
29676
29711
  type: "email",
29677
29712
  value: String(currentValue),
29678
- onChange: (e) => handleChange(fieldName, e.target.value)
29713
+ onChange: (e) => handleChange(fieldName, e.target.value),
29714
+ minLength: field.min,
29715
+ maxLength: field.max
29679
29716
  }
29680
29717
  );
29681
29718
  case "url":
@@ -29685,7 +29722,9 @@ var init_Form = __esm({
29685
29722
  ...commonProps,
29686
29723
  type: "url",
29687
29724
  value: String(currentValue),
29688
- onChange: (e) => handleChange(fieldName, e.target.value)
29725
+ onChange: (e) => handleChange(fieldName, e.target.value),
29726
+ minLength: field.min,
29727
+ maxLength: field.max
29689
29728
  }
29690
29729
  );
29691
29730
  case "password":
@@ -29695,7 +29734,9 @@ var init_Form = __esm({
29695
29734
  ...commonProps,
29696
29735
  type: "password",
29697
29736
  value: String(currentValue),
29698
- onChange: (e) => handleChange(fieldName, e.target.value)
29737
+ onChange: (e) => handleChange(fieldName, e.target.value),
29738
+ minLength: field.min,
29739
+ maxLength: field.max
29699
29740
  }
29700
29741
  );
29701
29742
  case "text":
@@ -29708,8 +29749,7 @@ var init_Form = __esm({
29708
29749
  value: String(currentValue),
29709
29750
  onChange: (e) => handleChange(fieldName, e.target.value),
29710
29751
  minLength: field.min,
29711
- maxLength: field.max,
29712
- pattern: field.pattern
29752
+ maxLength: field.max
29713
29753
  }
29714
29754
  );
29715
29755
  }
@@ -29717,12 +29757,14 @@ var init_Form = __esm({
29717
29757
  return /* @__PURE__ */ jsxRuntime.jsxs(
29718
29758
  "form",
29719
29759
  {
29720
- noValidate: true,
29760
+ ref: formRef,
29721
29761
  "data-pattern": "form-section",
29722
29762
  className: cn(layoutStyles[layout], gapStyles8[gap], className),
29723
29763
  onSubmit: handleSubmit,
29764
+ onInvalid: handleInvalid,
29724
29765
  ...props,
29725
29766
  children: [
29767
+ submitError && /* @__PURE__ */ jsxRuntime.jsx(Alert, { variant: "error", className: "mb-4", children: submitError }),
29726
29768
  error && /* @__PURE__ */ jsxRuntime.jsx(Alert, { variant: "error", className: "mb-4", children: error.message || t("error.occurred") }),
29727
29769
  sectionElements && sectionElements.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: gap === "sm" ? "sm" : gap === "lg" ? "lg" : "md", children: sectionElements }),
29728
29770
  schemaFields,
@@ -49283,7 +49325,18 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
49283
49325
  orbitalsByTrait: JSON.stringify(orbitalsByTrait ?? null)
49284
49326
  });
49285
49327
  const bindingMap = new Map(bindings.map((b) => [b.trait.name, b]));
49286
- const results = currentManager.sendEvent(normalizedEvent, payload);
49328
+ const entityByTrait = {};
49329
+ for (const [name, fields] of traitFieldStatesRef.current) {
49330
+ if (fields && Object.keys(fields).length > 0) {
49331
+ entityByTrait[name] = fields;
49332
+ }
49333
+ }
49334
+ const results = currentManager.sendEvent(
49335
+ normalizedEvent,
49336
+ payload,
49337
+ void 0,
49338
+ entityByTrait
49339
+ );
49287
49340
  crossTraitLog.debug("processEvent:results", {
49288
49341
  event: normalizedEvent,
49289
49342
  executedCount: results.length,
@@ -49603,6 +49656,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
49603
49656
  }
49604
49657
  console.log("[TraitStateMachine] Subscribing to events:", Array.from(allEvents));
49605
49658
  const unsubscribes = [];
49659
+ const subscribedBusKeys = /* @__PURE__ */ new Set();
49606
49660
  for (const binding of traitBindings) {
49607
49661
  const traitName = binding.trait.name;
49608
49662
  const orbitalName = orbitalsByTrait?.[traitName];
@@ -49613,6 +49667,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
49613
49667
  continue;
49614
49668
  }
49615
49669
  const selfBusKey = `UI:${orbitalName}.${traitName}.${eventKey}`;
49670
+ if (subscribedBusKeys.has(selfBusKey)) continue;
49671
+ subscribedBusKeys.add(selfBusKey);
49616
49672
  crossTraitLog.debug("self:subscribe", { traitName, busKey: selfBusKey, eventKey });
49617
49673
  const unsub = eventBus.on(selfBusKey, (event) => {
49618
49674
  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;
package/dist/avl/index.js CHANGED
@@ -136,7 +136,7 @@ var init_types = __esm({
136
136
  }
137
137
  });
138
138
 
139
- // node_modules/clsx/dist/clsx.mjs
139
+ // node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
140
140
  function r(e) {
141
141
  var t, f, n = "";
142
142
  if ("string" == typeof e || "number" == typeof e) n += e;
@@ -151,11 +151,11 @@ function clsx() {
151
151
  return n;
152
152
  }
153
153
  var init_clsx = __esm({
154
- "node_modules/clsx/dist/clsx.mjs"() {
154
+ "node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs"() {
155
155
  }
156
156
  });
157
157
 
158
- // node_modules/tailwind-merge/dist/bundle-mjs.mjs
158
+ // node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs
159
159
  function twJoin() {
160
160
  let index = 0;
161
161
  let argument;
@@ -199,7 +199,7 @@ function createTailwindMerge(createConfigFirst, ...createConfigRest) {
199
199
  }
200
200
  var CLASS_PART_SEPARATOR, createClassGroupUtils, getGroupRecursive, arbitraryPropertyRegex, getGroupIdForArbitraryProperty, createClassMap, processClassesRecursively, getPart, isThemeGetter, getPrefixedClassGroupEntries, createLruCache, IMPORTANT_MODIFIER, createParseClassName, sortModifiers, createConfigUtils, SPLIT_CLASSES_REGEX, mergeClassList, toValue, fromTheme, arbitraryValueRegex, fractionRegex, stringLengths, tshirtUnitRegex, lengthUnitRegex, colorFunctionRegex, shadowRegex, imageRegex, isLength, isArbitraryLength, isNumber, isArbitraryNumber, isInteger, isPercent, isArbitraryValue, isTshirtSize, sizeLabels, isArbitrarySize, isArbitraryPosition, imageLabels, isArbitraryImage, isArbitraryShadow, isAny, getIsArbitraryValue, isLengthOnly, isNever, isShadow, isImage, getDefaultConfig, twMerge;
201
201
  var init_bundle_mjs = __esm({
202
- "node_modules/tailwind-merge/dist/bundle-mjs.mjs"() {
202
+ "node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs"() {
203
203
  CLASS_PART_SEPARATOR = "-";
204
204
  createClassGroupUtils = (config) => {
205
205
  const classMap = createClassMap(config);
@@ -12792,9 +12792,9 @@ var init_ScaledDiagram = __esm({
12792
12792
  }
12793
12793
  });
12794
12794
 
12795
- // node_modules/katex/dist/katex.min.css
12795
+ // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
12796
12796
  var init_katex_min = __esm({
12797
- "node_modules/katex/dist/katex.min.css"() {
12797
+ "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
12798
12798
  }
12799
12799
  });
12800
12800
  var MarkdownContent;
@@ -29288,6 +29288,8 @@ var init_Form = __esm({
29288
29288
  const [collapsedSections, setCollapsedSections] = React118__default.useState(
29289
29289
  /* @__PURE__ */ new Set()
29290
29290
  );
29291
+ const [submitError, setSubmitError] = React118__default.useState(null);
29292
+ const formRef = React118__default.useRef(null);
29291
29293
  const formMode = props.mode;
29292
29294
  const mountedRef = React118__default.useRef(false);
29293
29295
  if (!mountedRef.current) {
@@ -29413,6 +29415,7 @@ var init_Form = __esm({
29413
29415
  };
29414
29416
  const handleSubmit = (e) => {
29415
29417
  e.preventDefault();
29418
+ setSubmitError(null);
29416
29419
  debug("forms", "submit-enter", {
29417
29420
  mode: formMode,
29418
29421
  submitEvent,
@@ -29430,6 +29433,37 @@ var init_Form = __esm({
29430
29433
  eventBus.emit(`UI:${onSubmit}`, payload);
29431
29434
  }
29432
29435
  };
29436
+ const handleInvalid = (e) => {
29437
+ const target = e.target;
29438
+ const fieldName = target.getAttribute("data-field-name") ?? target.name ?? "";
29439
+ const fieldMessage = target.validationMessage || "Invalid value";
29440
+ debug("forms", "invalid", { mode: formMode, fieldName, fieldMessage });
29441
+ queueMicrotask(() => {
29442
+ const form = formRef.current;
29443
+ if (!form) return;
29444
+ const invalidEls = Array.from(
29445
+ form.querySelectorAll(
29446
+ ":invalid"
29447
+ )
29448
+ );
29449
+ if (invalidEls.length === 0) return;
29450
+ const missing = invalidEls.map(
29451
+ (el) => el.getAttribute("data-field-name") ?? el.name ?? ""
29452
+ );
29453
+ const messages = invalidEls.map((el) => ({
29454
+ field: el.getAttribute("data-field-name") ?? el.name ?? "",
29455
+ message: el.validationMessage
29456
+ }));
29457
+ const summary = missing.length === 1 ? `${missing[0]}: ${messages[0]?.message}` : `Please fix ${missing.length} fields: ${missing.join(", ")}`;
29458
+ setSubmitError(summary);
29459
+ eventBus.emit("UI:VALIDATION_FAILED", {
29460
+ submitEvent,
29461
+ missing,
29462
+ messages,
29463
+ summary
29464
+ });
29465
+ });
29466
+ };
29433
29467
  const handleCancel = () => {
29434
29468
  eventBus.emit(`UI:${cancelEvent}`);
29435
29469
  eventBus.emit("UI:CLOSE");
@@ -29533,7 +29567,8 @@ var init_Form = __esm({
29533
29567
  "data-field-name": fieldName,
29534
29568
  required: field.required,
29535
29569
  disabled: isLoading,
29536
- placeholder: field.placeholder
29570
+ placeholder: field.placeholder,
29571
+ pattern: field.pattern
29537
29572
  };
29538
29573
  switch (inputType) {
29539
29574
  case "checkbox":
@@ -29629,7 +29664,9 @@ var init_Form = __esm({
29629
29664
  ...commonProps,
29630
29665
  type: "email",
29631
29666
  value: String(currentValue),
29632
- onChange: (e) => handleChange(fieldName, e.target.value)
29667
+ onChange: (e) => handleChange(fieldName, e.target.value),
29668
+ minLength: field.min,
29669
+ maxLength: field.max
29633
29670
  }
29634
29671
  );
29635
29672
  case "url":
@@ -29639,7 +29676,9 @@ var init_Form = __esm({
29639
29676
  ...commonProps,
29640
29677
  type: "url",
29641
29678
  value: String(currentValue),
29642
- onChange: (e) => handleChange(fieldName, e.target.value)
29679
+ onChange: (e) => handleChange(fieldName, e.target.value),
29680
+ minLength: field.min,
29681
+ maxLength: field.max
29643
29682
  }
29644
29683
  );
29645
29684
  case "password":
@@ -29649,7 +29688,9 @@ var init_Form = __esm({
29649
29688
  ...commonProps,
29650
29689
  type: "password",
29651
29690
  value: String(currentValue),
29652
- onChange: (e) => handleChange(fieldName, e.target.value)
29691
+ onChange: (e) => handleChange(fieldName, e.target.value),
29692
+ minLength: field.min,
29693
+ maxLength: field.max
29653
29694
  }
29654
29695
  );
29655
29696
  case "text":
@@ -29662,8 +29703,7 @@ var init_Form = __esm({
29662
29703
  value: String(currentValue),
29663
29704
  onChange: (e) => handleChange(fieldName, e.target.value),
29664
29705
  minLength: field.min,
29665
- maxLength: field.max,
29666
- pattern: field.pattern
29706
+ maxLength: field.max
29667
29707
  }
29668
29708
  );
29669
29709
  }
@@ -29671,12 +29711,14 @@ var init_Form = __esm({
29671
29711
  return /* @__PURE__ */ jsxs(
29672
29712
  "form",
29673
29713
  {
29674
- noValidate: true,
29714
+ ref: formRef,
29675
29715
  "data-pattern": "form-section",
29676
29716
  className: cn(layoutStyles[layout], gapStyles8[gap], className),
29677
29717
  onSubmit: handleSubmit,
29718
+ onInvalid: handleInvalid,
29678
29719
  ...props,
29679
29720
  children: [
29721
+ submitError && /* @__PURE__ */ jsx(Alert, { variant: "error", className: "mb-4", children: submitError }),
29680
29722
  error && /* @__PURE__ */ jsx(Alert, { variant: "error", className: "mb-4", children: error.message || t("error.occurred") }),
29681
29723
  sectionElements && sectionElements.length > 0 && /* @__PURE__ */ jsx(VStack, { gap: gap === "sm" ? "sm" : gap === "lg" ? "lg" : "md", children: sectionElements }),
29682
29724
  schemaFields,
@@ -49237,7 +49279,18 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
49237
49279
  orbitalsByTrait: JSON.stringify(orbitalsByTrait ?? null)
49238
49280
  });
49239
49281
  const bindingMap = new Map(bindings.map((b) => [b.trait.name, b]));
49240
- const results = currentManager.sendEvent(normalizedEvent, payload);
49282
+ const entityByTrait = {};
49283
+ for (const [name, fields] of traitFieldStatesRef.current) {
49284
+ if (fields && Object.keys(fields).length > 0) {
49285
+ entityByTrait[name] = fields;
49286
+ }
49287
+ }
49288
+ const results = currentManager.sendEvent(
49289
+ normalizedEvent,
49290
+ payload,
49291
+ void 0,
49292
+ entityByTrait
49293
+ );
49241
49294
  crossTraitLog.debug("processEvent:results", {
49242
49295
  event: normalizedEvent,
49243
49296
  executedCount: results.length,
@@ -49557,6 +49610,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
49557
49610
  }
49558
49611
  console.log("[TraitStateMachine] Subscribing to events:", Array.from(allEvents));
49559
49612
  const unsubscribes = [];
49613
+ const subscribedBusKeys = /* @__PURE__ */ new Set();
49560
49614
  for (const binding of traitBindings) {
49561
49615
  const traitName = binding.trait.name;
49562
49616
  const orbitalName = orbitalsByTrait?.[traitName];
@@ -49567,6 +49621,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
49567
49621
  continue;
49568
49622
  }
49569
49623
  const selfBusKey = `UI:${orbitalName}.${traitName}.${eventKey}`;
49624
+ if (subscribedBusKeys.has(selfBusKey)) continue;
49625
+ subscribedBusKeys.add(selfBusKey);
49570
49626
  crossTraitLog.debug("self:subscribe", { traitName, busKey: selfBusKey, eventKey });
49571
49627
  const unsub = eventBus.on(selfBusKey, (event) => {
49572
49628
  if (event.source && event.source.dispatched) {
@@ -8974,9 +8974,9 @@ var init_ScaledDiagram = __esm({
8974
8974
  }
8975
8975
  });
8976
8976
 
8977
- // node_modules/katex/dist/katex.min.css
8977
+ // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
8978
8978
  var init_katex_min = __esm({
8979
- "node_modules/katex/dist/katex.min.css"() {
8979
+ "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
8980
8980
  }
8981
8981
  });
8982
8982
  exports.MarkdownContent = void 0;
@@ -27962,6 +27962,8 @@ var init_Form = __esm({
27962
27962
  const [collapsedSections, setCollapsedSections] = React109__namespace.default.useState(
27963
27963
  /* @__PURE__ */ new Set()
27964
27964
  );
27965
+ const [submitError, setSubmitError] = React109__namespace.default.useState(null);
27966
+ const formRef = React109__namespace.default.useRef(null);
27965
27967
  const formMode = props.mode;
27966
27968
  const mountedRef = React109__namespace.default.useRef(false);
27967
27969
  if (!mountedRef.current) {
@@ -28087,6 +28089,7 @@ var init_Form = __esm({
28087
28089
  };
28088
28090
  const handleSubmit = (e) => {
28089
28091
  e.preventDefault();
28092
+ setSubmitError(null);
28090
28093
  debug("forms", "submit-enter", {
28091
28094
  mode: formMode,
28092
28095
  submitEvent,
@@ -28104,6 +28107,37 @@ var init_Form = __esm({
28104
28107
  eventBus.emit(`UI:${onSubmit}`, payload);
28105
28108
  }
28106
28109
  };
28110
+ const handleInvalid = (e) => {
28111
+ const target = e.target;
28112
+ const fieldName = target.getAttribute("data-field-name") ?? target.name ?? "";
28113
+ const fieldMessage = target.validationMessage || "Invalid value";
28114
+ debug("forms", "invalid", { mode: formMode, fieldName, fieldMessage });
28115
+ queueMicrotask(() => {
28116
+ const form = formRef.current;
28117
+ if (!form) return;
28118
+ const invalidEls = Array.from(
28119
+ form.querySelectorAll(
28120
+ ":invalid"
28121
+ )
28122
+ );
28123
+ if (invalidEls.length === 0) return;
28124
+ const missing = invalidEls.map(
28125
+ (el) => el.getAttribute("data-field-name") ?? el.name ?? ""
28126
+ );
28127
+ const messages = invalidEls.map((el) => ({
28128
+ field: el.getAttribute("data-field-name") ?? el.name ?? "",
28129
+ message: el.validationMessage
28130
+ }));
28131
+ const summary = missing.length === 1 ? `${missing[0]}: ${messages[0]?.message}` : `Please fix ${missing.length} fields: ${missing.join(", ")}`;
28132
+ setSubmitError(summary);
28133
+ eventBus.emit("UI:VALIDATION_FAILED", {
28134
+ submitEvent,
28135
+ missing,
28136
+ messages,
28137
+ summary
28138
+ });
28139
+ });
28140
+ };
28107
28141
  const handleCancel = () => {
28108
28142
  eventBus.emit(`UI:${cancelEvent}`);
28109
28143
  eventBus.emit("UI:CLOSE");
@@ -28207,7 +28241,8 @@ var init_Form = __esm({
28207
28241
  "data-field-name": fieldName,
28208
28242
  required: field.required,
28209
28243
  disabled: isLoading,
28210
- placeholder: field.placeholder
28244
+ placeholder: field.placeholder,
28245
+ pattern: field.pattern
28211
28246
  };
28212
28247
  switch (inputType) {
28213
28248
  case "checkbox":
@@ -28303,7 +28338,9 @@ var init_Form = __esm({
28303
28338
  ...commonProps,
28304
28339
  type: "email",
28305
28340
  value: String(currentValue),
28306
- onChange: (e) => handleChange(fieldName, e.target.value)
28341
+ onChange: (e) => handleChange(fieldName, e.target.value),
28342
+ minLength: field.min,
28343
+ maxLength: field.max
28307
28344
  }
28308
28345
  );
28309
28346
  case "url":
@@ -28313,7 +28350,9 @@ var init_Form = __esm({
28313
28350
  ...commonProps,
28314
28351
  type: "url",
28315
28352
  value: String(currentValue),
28316
- onChange: (e) => handleChange(fieldName, e.target.value)
28353
+ onChange: (e) => handleChange(fieldName, e.target.value),
28354
+ minLength: field.min,
28355
+ maxLength: field.max
28317
28356
  }
28318
28357
  );
28319
28358
  case "password":
@@ -28323,7 +28362,9 @@ var init_Form = __esm({
28323
28362
  ...commonProps,
28324
28363
  type: "password",
28325
28364
  value: String(currentValue),
28326
- onChange: (e) => handleChange(fieldName, e.target.value)
28365
+ onChange: (e) => handleChange(fieldName, e.target.value),
28366
+ minLength: field.min,
28367
+ maxLength: field.max
28327
28368
  }
28328
28369
  );
28329
28370
  case "text":
@@ -28336,8 +28377,7 @@ var init_Form = __esm({
28336
28377
  value: String(currentValue),
28337
28378
  onChange: (e) => handleChange(fieldName, e.target.value),
28338
28379
  minLength: field.min,
28339
- maxLength: field.max,
28340
- pattern: field.pattern
28380
+ maxLength: field.max
28341
28381
  }
28342
28382
  );
28343
28383
  }
@@ -28345,12 +28385,14 @@ var init_Form = __esm({
28345
28385
  return /* @__PURE__ */ jsxRuntime.jsxs(
28346
28386
  "form",
28347
28387
  {
28348
- noValidate: true,
28388
+ ref: formRef,
28349
28389
  "data-pattern": "form-section",
28350
28390
  className: cn(layoutStyles[layout], gapStyles8[gap], className),
28351
28391
  onSubmit: handleSubmit,
28392
+ onInvalid: handleInvalid,
28352
28393
  ...props,
28353
28394
  children: [
28395
+ submitError && /* @__PURE__ */ jsxRuntime.jsx(exports.Alert, { variant: "error", className: "mb-4", children: submitError }),
28354
28396
  error && /* @__PURE__ */ jsxRuntime.jsx(exports.Alert, { variant: "error", className: "mb-4", children: error.message || t("error.occurred") }),
28355
28397
  sectionElements && sectionElements.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.VStack, { gap: gap === "sm" ? "sm" : gap === "lg" ? "lg" : "md", children: sectionElements }),
28356
28398
  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;