@axzydev/axzy_ui_system 1.7.3 → 1.8.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.
Files changed (82) hide show
  1. package/dist/index.cjs +1845 -721
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.css +1 -1
  4. package/dist/index.d.cts +386 -15
  5. package/dist/index.d.ts +386 -15
  6. package/dist/index.js +1532 -418
  7. package/dist/index.js.map +1 -1
  8. package/dist/layered.css +1 -1
  9. package/package.json +4 -2
  10. package/src/App.tsx +6 -8
  11. package/src/components/atoms/button/button.tsx +7 -0
  12. package/src/components/atoms/flex/flex.props.ts +3 -1
  13. package/src/components/atoms/flex/flex.tsx +11 -3
  14. package/src/components/atoms/input/input.tsx +5 -0
  15. package/src/components/atoms/segmented-control/segmented-control.tsx +22 -5
  16. package/src/components/atoms/textarea/textarea.props.ts +4 -0
  17. package/src/components/atoms/textarea/textarea.tsx +13 -3
  18. package/src/components/molecules/card/card.props.ts +14 -0
  19. package/src/components/molecules/card/card.tsx +66 -23
  20. package/src/components/molecules/chip-input/chip-input.tsx +2 -0
  21. package/src/components/molecules/line-bar-chart/line-bar-chart.props.ts +4 -0
  22. package/src/components/molecules/line-bar-chart/line-bar-chart.tsx +57 -41
  23. package/src/components/molecules/multi-select/multi-select.tsx +2 -0
  24. package/src/components/molecules/tabs/tabs.tsx +22 -8
  25. package/src/components/organisms/dropfile/dropfile.props.ts +8 -2
  26. package/src/components/organisms/dropfile/dropfile.tsx +17 -0
  27. package/src/components/organisms/page-header/page-header.tsx +22 -6
  28. package/src/components/organisms/sidebar/sidebar.tsx +8 -5
  29. package/src/components/organisms/topbar/topbar.props.ts +2 -0
  30. package/src/components/organisms/topbar/topbar.tsx +56 -34
  31. package/src/components/templates/layout/layout.tsx +3 -2
  32. package/src/components/theme-provider/themeProvider.props.ts +1 -1
  33. package/src/components/theme-provider/themeProvider.tsx +54 -1
  34. package/src/i18n/locales/en.ts +7 -0
  35. package/src/i18n/locales/es.ts +7 -0
  36. package/src/index.ts +35 -7
  37. package/src/json-renderer/actions/effects.test.tsx +115 -0
  38. package/src/json-renderer/actions/effects.ts +291 -0
  39. package/src/json-renderer/actions/effectsChain.test.ts +117 -0
  40. package/src/json-renderer/binding/binding.test.tsx +168 -0
  41. package/src/json-renderer/binding/resolveValue.ts +193 -0
  42. package/src/json-renderer/catalog/axzyCatalog.ts +5 -0
  43. package/src/json-renderer/estado-acciones.test.tsx +166 -0
  44. package/src/json-renderer/form/FormNode.tsx +92 -0
  45. package/src/json-renderer/form/form.test.tsx +148 -0
  46. package/src/json-renderer/form/formLength.test.tsx +99 -0
  47. package/src/json-renderer/form/rules.ts +162 -0
  48. package/src/json-renderer/index.ts +21 -0
  49. package/src/json-renderer/kernel/SchemaRenderer.tsx +83 -7
  50. package/src/json-renderer/kernel/capabilities.ts +30 -0
  51. package/src/json-renderer/kernel/renderNode.tsx +256 -3
  52. package/src/json-renderer/kernel/schemaRenderer.props.ts +29 -3
  53. package/src/json-renderer/kernel/slots.test.tsx +104 -0
  54. package/src/json-renderer/kernel/slots.ts +34 -0
  55. package/src/json-renderer/kernel/types.ts +4 -0
  56. package/src/json-renderer/routing/match.ts +82 -0
  57. package/src/json-renderer/routing/navigation.ts +71 -0
  58. package/src/json-renderer/routing/routes.ts +179 -0
  59. package/src/json-renderer/routing/routing.test.ts +147 -0
  60. package/src/json-renderer/seguridad.test.tsx +299 -0
  61. package/src/json-renderer/shared/errors.ts +1 -0
  62. package/src/json-renderer/stream/tolerantParse.ts +5 -0
  63. package/src/json-renderer/stream/useSchemaStream.test.tsx +143 -0
  64. package/src/json-renderer/stream/useSchemaStream.ts +227 -0
  65. package/src/json-renderer/validation/jsonSchema.test.ts +105 -0
  66. package/src/json-renderer/validation/jsonSchema.ts +317 -0
  67. package/src/json-renderer/validation/validate.ts +17 -0
  68. package/src/sandbox/axzyConfig.test.ts +4 -0
  69. package/src/sandbox/axzyConfig.ts +1 -1
  70. package/src/sandbox/i18n.ts +44 -0
  71. package/src/sandbox/useHashRoute.ts +2 -1
  72. package/src/showcases/DemoJsonDashboard.tsx +218 -103
  73. package/src/showcases/DemoJsonDocs.tsx +11 -11
  74. package/src/showcases/FeedbackShowcases.tsx +2 -1
  75. package/src/showcases/JsonScreenShowcase.tsx +43 -53
  76. package/src/showcases/StructureShowcases.tsx +17 -2
  77. package/src/showcases/demoApp/demoJson.test.tsx +241 -0
  78. package/src/showcases/demoApp/routes.test.ts +63 -0
  79. package/src/showcases/demoApp/schemas.test.ts +6 -17
  80. package/src/theme/theme-context.ts +10 -2
  81. package/src/theme/theme.ts +1 -1
  82. package/src/theme/theme.types.ts +2 -1
package/dist/index.js CHANGED
@@ -703,7 +703,7 @@ var components = {
703
703
  input: {
704
704
  backgroundColor: "var(--it-input-bg, #ffffff)",
705
705
  borderColor: `var(--it-input-border, ${semanticColors.gray[300]})`,
706
- borderRadius: "var(--radius-md)",
706
+ borderRadius: "var(--it-input-radius, var(--radius-md))",
707
707
  focus: {
708
708
  borderColor: `var(--it-input-focus-border, ${semanticColors.primary[500]})`,
709
709
  ring: `var(--it-input-focus-ring, 0 0 0 3px ${semanticColors.primary[100]})`
@@ -872,6 +872,26 @@ function ITText({
872
872
  );
873
873
  }
874
874
 
875
+ // src/theme/theme-context.ts
876
+ import { createContext, useContext } from "react";
877
+ var ITThemeContext = createContext(void 0);
878
+ var useITTheme = () => {
879
+ const context = useContext(ITThemeContext);
880
+ if (!context) {
881
+ throw new Error("useITTheme must be used within an ITThemeProvider");
882
+ }
883
+ return context;
884
+ };
885
+ var useITThemeSafe = () => {
886
+ return useContext(ITThemeContext);
887
+ };
888
+ var useITAppearance = () => {
889
+ return useContext(ITThemeContext)?.appearance ?? "soft";
890
+ };
891
+ var useITFlatAppearance = () => {
892
+ return useITAppearance() === "flat";
893
+ };
894
+
875
895
  // src/components/atoms/button/button.tsx
876
896
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
877
897
  function ITButton({
@@ -890,6 +910,7 @@ function ITButton({
890
910
  }) {
891
911
  const [isHovered, setIsHovered] = useState5(false);
892
912
  const [isFocused, setIsFocused] = useState5(false);
913
+ const bento = useITAppearance() === "bento";
893
914
  const isIconOnly = variant === "icon-only";
894
915
  const isIconOnlyContent = isIconOnly && Boolean(icon) && !children;
895
916
  const themeBtn = theme.button;
@@ -909,6 +930,9 @@ function ITButton({
909
930
  // Default from theme
910
931
  transition: themeConfig.transition || "all 0.2s"
911
932
  };
933
+ if (bento) {
934
+ style.borderRadius = `var(--it-bento-pill-radius, ${themeConfig.borderRadius})`;
935
+ }
912
936
  if (variant === "rounded") {
913
937
  style.borderRadius = "9999px";
914
938
  }
@@ -977,23 +1001,6 @@ function ITButton({
977
1001
  import clsx2 from "clsx";
978
1002
  import { useState as useState6 } from "react";
979
1003
 
980
- // src/theme/theme-context.ts
981
- import { createContext, useContext } from "react";
982
- var ITThemeContext = createContext(void 0);
983
- var useITTheme = () => {
984
- const context = useContext(ITThemeContext);
985
- if (!context) {
986
- throw new Error("useITTheme must be used within an ITThemeProvider");
987
- }
988
- return context;
989
- };
990
- var useITThemeSafe = () => {
991
- return useContext(ITThemeContext);
992
- };
993
- var useITFlatAppearance = () => {
994
- return useContext(ITThemeContext)?.appearance === "flat";
995
- };
996
-
997
1004
  // src/i18n/provider.tsx
998
1005
  import { useMemo as useMemo3 } from "react";
999
1006
 
@@ -1205,7 +1212,13 @@ var es = {
1205
1212
  "jsonEditor.kindString": "texto",
1206
1213
  "jsonEditor.kindNumber": "n\xFAmero",
1207
1214
  "jsonEditor.kindBoolean": "booleano",
1208
- "jsonEditor.kindNull": "nulo"
1215
+ "jsonEditor.kindNull": "nulo",
1216
+ // ---------------------------------------------------------------- jsonRenderer
1217
+ "jsonRenderer.form.required": "Campo obligatorio.",
1218
+ "jsonRenderer.form.email": "Escribe un correo v\xE1lido.",
1219
+ "jsonRenderer.form.minLength": "Escribe al menos {min} caracteres.",
1220
+ "jsonRenderer.form.maxLength": "Escribe como m\xE1ximo {max} caracteres.",
1221
+ "jsonRenderer.form.submit": "Enviar"
1209
1222
  };
1210
1223
  var es_default = es;
1211
1224
 
@@ -1411,7 +1424,13 @@ var en = {
1411
1424
  "jsonEditor.kindString": "string",
1412
1425
  "jsonEditor.kindNumber": "number",
1413
1426
  "jsonEditor.kindBoolean": "boolean",
1414
- "jsonEditor.kindNull": "null"
1427
+ "jsonEditor.kindNull": "null",
1428
+ // ---------------------------------------------------------------- jsonRenderer
1429
+ "jsonRenderer.form.required": "Required field.",
1430
+ "jsonRenderer.form.email": "Enter a valid email address.",
1431
+ "jsonRenderer.form.minLength": "Enter at least {min} characters.",
1432
+ "jsonRenderer.form.maxLength": "Enter at most {max} characters.",
1433
+ "jsonRenderer.form.submit": "Submit"
1415
1434
  };
1416
1435
  var en_default = en;
1417
1436
 
@@ -1488,6 +1507,8 @@ function useITTranslation() {
1488
1507
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
1489
1508
  function ITCard({
1490
1509
  title,
1510
+ tone,
1511
+ headerActions,
1491
1512
  image,
1492
1513
  alt,
1493
1514
  children,
@@ -1501,26 +1522,35 @@ function ITCard({
1501
1522
  }) {
1502
1523
  const { t } = useITTranslation();
1503
1524
  const [isHovered, setIsHovered] = useState6(false);
1504
- const flat = useITFlatAppearance();
1525
+ const appearance = useITAppearance();
1526
+ const bento = appearance === "bento";
1527
+ const flat = appearance === "flat";
1505
1528
  const resolvedAlt = alt ?? t("card.imageAlt");
1506
1529
  const containerStyle = {
1507
1530
  backgroundColor: "var(--it-card-bg, #ffffff)",
1508
- borderColor: flat ? "var(--it-card-flat-border, var(--color-secondary-200))" : "var(--it-card-border, rgba(15, 23, 42, 0.06))",
1509
- borderWidth: "1px",
1531
+ borderColor: bento ? "transparent" : flat ? "var(--it-card-flat-border, var(--color-secondary-200))" : "var(--it-card-border, rgba(15, 23, 42, 0.06))",
1532
+ borderWidth: bento ? "0px" : "1px",
1510
1533
  borderStyle: "solid",
1511
- borderRadius: flat ? "var(--it-card-radius, var(--radius-lg))" : "var(--it-card-radius, var(--radius-2xl))",
1534
+ borderRadius: bento ? "var(--it-card-radius, var(--it-bento-card-radius, var(--radius-2xl)))" : flat ? "var(--it-card-radius, var(--radius-lg))" : "var(--it-card-radius, var(--radius-2xl))",
1512
1535
  // Soft depth: every card floats a little at rest; interactive cards
1513
1536
  // gain visual weight on hover instead of appearing flat until clicked.
1514
1537
  // Flat appearance: the hairline border carries the surface, so a card
1515
1538
  // only gets a shadow as hover feedback when it is clickable.
1516
- boxShadow: flat ? onClick && isHovered ? "var(--shadow-sm)" : "none" : onClick ? isHovered ? "var(--shadow-lg)" : "var(--shadow-sm)" : "var(--shadow-sm)",
1539
+ // Bento: borderless, a diffuse shadow at rest and a stronger one on hover.
1540
+ boxShadow: bento ? onClick && isHovered ? "var(--it-bento-card-shadow-hover, var(--shadow-lg))" : "var(--it-bento-card-shadow, var(--shadow-sm))" : flat ? onClick && isHovered ? "var(--shadow-sm)" : "none" : onClick ? isHovered ? "var(--shadow-lg)" : "var(--shadow-sm)" : "var(--shadow-sm)",
1517
1541
  transition: onClick ? "box-shadow 0.2s ease-in-out, transform 0.2s ease-in-out" : "none",
1518
- transform: onClick && isHovered && !flat ? "translateY(-2px)" : "translateY(0)",
1542
+ transform: onClick && isHovered && !flat && !bento ? "translateY(-2px)" : "translateY(0)",
1519
1543
  cursor: onClick ? "pointer" : "default"
1520
1544
  };
1545
+ if (tone) {
1546
+ const soft = `var(--color-${tone}-soft)`;
1547
+ containerStyle.backgroundImage = `linear-gradient(${soft}, ${soft})`;
1548
+ if (!bento) containerStyle.borderColor = `var(--color-${tone}-soft-border)`;
1549
+ }
1521
1550
  const bodyStyle = {
1522
- padding: "1.25rem"
1551
+ padding: bento ? "var(--it-bento-card-padding, 1.5rem)" : "1.25rem"
1523
1552
  };
1553
+ const titleTypography = bento ? "text-lg font-bold" : flat ? "text-base font-semibold" : "text-xl font-semibold";
1524
1554
  return /* @__PURE__ */ jsxs2(
1525
1555
  "div",
1526
1556
  {
@@ -1547,14 +1577,24 @@ function ITCard({
1547
1577
  }
1548
1578
  ),
1549
1579
  /* @__PURE__ */ jsxs2("div", { className: clsx2(contentClassName), style: bodyStyle, children: [
1550
- title && /* @__PURE__ */ jsx4(
1580
+ headerActions ? /* @__PURE__ */ jsxs2("div", { className: "mb-2 flex items-center justify-between gap-3", children: [
1581
+ title && /* @__PURE__ */ jsx4(
1582
+ ITText,
1583
+ {
1584
+ as: "h3",
1585
+ className: clsx2(titleTypography, titleClassName),
1586
+ children: title
1587
+ }
1588
+ ),
1589
+ headerActions
1590
+ ] }) : title ? /* @__PURE__ */ jsx4(
1551
1591
  ITText,
1552
1592
  {
1553
1593
  as: "h3",
1554
- className: clsx2(flat ? "text-base font-semibold mb-3" : "text-xl font-semibold mb-2", titleClassName),
1594
+ className: clsx2(titleTypography, flat ? "mb-3" : bento ? "mb-4" : "mb-2", titleClassName),
1555
1595
  children: title
1556
1596
  }
1557
- ),
1597
+ ) : null,
1558
1598
  /* @__PURE__ */ jsx4(ITText, { as: "div", className: "text-secondary-600", children })
1559
1599
  ] }),
1560
1600
  actions && /* @__PURE__ */ jsx4(
@@ -1574,6 +1614,7 @@ function ITCard({
1574
1614
 
1575
1615
  // src/components/atoms/flex/flex.tsx
1576
1616
  import clsx3 from "clsx";
1617
+ import { forwardRef } from "react";
1577
1618
  import { jsx as jsx5 } from "react/jsx-runtime";
1578
1619
  var directionMap = {
1579
1620
  row: "flex-row",
@@ -1601,7 +1642,7 @@ var wrapMap = {
1601
1642
  wrap: "flex-wrap",
1602
1643
  "wrap-reverse": "flex-wrap-reverse"
1603
1644
  };
1604
- function ITFlex({
1645
+ var ITFlex = forwardRef(function ITFlex2({
1605
1646
  children,
1606
1647
  direction = "row",
1607
1648
  align,
@@ -1614,8 +1655,9 @@ function ITFlex({
1614
1655
  className,
1615
1656
  style,
1616
1657
  as: Component = "div",
1617
- onClick
1618
- }) {
1658
+ onClick,
1659
+ onScroll
1660
+ }, ref) {
1619
1661
  const resolvedStyle = {
1620
1662
  gap: gap > 0 ? `${gap * 0.25}rem` : void 0,
1621
1663
  flexGrow: typeof grow === "boolean" ? grow ? 1 : 0 : grow,
@@ -1626,6 +1668,7 @@ function ITFlex({
1626
1668
  return /* @__PURE__ */ jsx5(
1627
1669
  Component,
1628
1670
  {
1671
+ ref,
1629
1672
  className: clsx3(
1630
1673
  "flex",
1631
1674
  directionMap[direction],
@@ -1636,10 +1679,13 @@ function ITFlex({
1636
1679
  ),
1637
1680
  style: resolvedStyle,
1638
1681
  onClick,
1682
+ onScroll,
1639
1683
  children
1640
1684
  }
1641
1685
  );
1642
- }
1686
+ });
1687
+ ITFlex.displayName = "ITFlex";
1688
+ var flex_default = ITFlex;
1643
1689
 
1644
1690
  // src/components/atoms/stack/stack.tsx
1645
1691
  import clsx4 from "clsx";
@@ -1854,7 +1900,7 @@ function ITJsonRenderer({
1854
1900
  case "card":
1855
1901
  return /* @__PURE__ */ jsx9(ITCard, { ...props, children: childContent });
1856
1902
  case "flex":
1857
- return /* @__PURE__ */ jsx9(ITFlex, { ...props, children: childContent });
1903
+ return /* @__PURE__ */ jsx9(flex_default, { ...props, children: childContent });
1858
1904
  case "stack":
1859
1905
  return /* @__PURE__ */ jsx9(ITStack, { ...props, children: childContent });
1860
1906
  case "grid":
@@ -3005,6 +3051,7 @@ function ITChipInput({
3005
3051
  style.alignItems = "center";
3006
3052
  style.gap = "0.375rem";
3007
3053
  style.minHeight = "2.5rem";
3054
+ style.borderRadius = "var(--it-bento-field-radius, var(--radius-md))";
3008
3055
  if (disabled) {
3009
3056
  style.backgroundColor = inputTheme.disabled?.backgroundColor || style.backgroundColor;
3010
3057
  style.borderColor = inputTheme.disabled?.borderColor || style.borderColor;
@@ -3401,6 +3448,9 @@ function ITInput({
3401
3448
  const inputTheme = theme.input || {};
3402
3449
  const getStyle = () => {
3403
3450
  const style = inputFieldStyle(inputTheme, size);
3451
+ if (isTextArea) {
3452
+ style.borderRadius = "var(--it-bento-field-radius, var(--radius-md))";
3453
+ }
3404
3454
  if (disabled) {
3405
3455
  style.backgroundColor = inputTheme.disabled?.backgroundColor || style.backgroundColor;
3406
3456
  style.borderColor = inputTheme.disabled?.borderColor || style.borderColor;
@@ -4083,6 +4133,7 @@ function ITMultiSelect({
4083
4133
  style.alignItems = "center";
4084
4134
  style.gap = "0.375rem";
4085
4135
  style.minHeight = "2.5rem";
4136
+ style.borderRadius = "var(--it-bento-field-radius, var(--radius-md))";
4086
4137
  if (disabled) {
4087
4138
  style.backgroundColor = inputTheme.disabled?.backgroundColor || style.backgroundColor;
4088
4139
  style.borderColor = inputTheme.disabled?.borderColor || style.borderColor;
@@ -7304,7 +7355,9 @@ function ITPageHeader({
7304
7355
  }) {
7305
7356
  const { t } = useITTranslation();
7306
7357
  const showTopRow = breadcrumbs?.length || backAction;
7307
- const flat = useITFlatAppearance();
7358
+ const appearance = useITAppearance();
7359
+ const bento = appearance === "bento";
7360
+ const flat = appearance === "flat";
7308
7361
  return /* @__PURE__ */ jsxs30("div", { className: `${className} space-y-3`, children: [
7309
7362
  showTopRow && /* @__PURE__ */ jsxs30("div", { className: "flex items-center justify-between gap-4", children: [
7310
7363
  /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2 min-w-0", children: [
@@ -7312,7 +7365,8 @@ function ITPageHeader({
7312
7365
  "button",
7313
7366
  {
7314
7367
  onClick: backAction,
7315
- className: "flex items-center justify-center w-9 h-9 rounded-full border border-slate-200 dark:border-slate-700 text-slate-400 hover:text-slate-700 dark:hover:text-slate-200 hover:border-slate-300 dark:hover:border-slate-600 hover:bg-slate-50 dark:hover:bg-slate-800/60 transition-all duration-200 flex-shrink-0",
7368
+ className: bento ? "flex items-center justify-center w-10 h-10 rounded-full hover:opacity-80 transition-opacity duration-200 flex-shrink-0" : "flex items-center justify-center w-9 h-9 rounded-full border border-slate-200 dark:border-slate-700 text-slate-400 hover:text-slate-700 dark:hover:text-slate-200 hover:border-slate-300 dark:hover:border-slate-600 hover:bg-slate-50 dark:hover:bg-slate-800/60 transition-all duration-200 flex-shrink-0",
7369
+ style: bento ? { backgroundColor: "var(--it-bento-control-bg, #f1f5f9)", color: "var(--it-bento-control-text, #475569)" } : void 0,
7316
7370
  "aria-label": t("pageHeader.back"),
7317
7371
  children: /* @__PURE__ */ jsx42(FaChevronLeft3, { size: 14 })
7318
7372
  }
@@ -7323,7 +7377,7 @@ function ITPageHeader({
7323
7377
  ] }),
7324
7378
  /* @__PURE__ */ jsxs30("div", { className: "flex items-start justify-between gap-6", children: [
7325
7379
  /* @__PURE__ */ jsxs30("div", { className: "flex items-start gap-4 min-w-0", children: [
7326
- icon && !flat && /* @__PURE__ */ jsx42(
7380
+ icon && !flat && !bento && /* @__PURE__ */ jsx42(
7327
7381
  "div",
7328
7382
  {
7329
7383
  className: "flex items-center justify-center w-12 h-12 rounded-full border border-slate-200 dark:border-slate-700 bg-slate-50/50 dark:bg-slate-800/50 text-slate-600 dark:text-slate-300 flex-shrink-0 transition-all duration-200 hover:border-slate-300 dark:hover:border-slate-500 hover:shadow-sm",
@@ -7336,7 +7390,7 @@ function ITPageHeader({
7336
7390
  ITText,
7337
7391
  {
7338
7392
  as: "h1",
7339
- className: flat ? "text-[1.625rem] font-bold text-slate-900 dark:text-white tracking-tight leading-tight" : "text-3xl font-bold text-slate-800 dark:text-white tracking-tight leading-tight",
7393
+ className: bento ? "text-3xl font-bold text-slate-900 dark:text-white tracking-tighter leading-tight" : flat ? "text-[1.625rem] font-bold text-slate-900 dark:text-white tracking-tight leading-tight" : "text-3xl font-bold text-slate-800 dark:text-white tracking-tight leading-tight",
7340
7394
  children: title
7341
7395
  }
7342
7396
  ),
@@ -7344,7 +7398,7 @@ function ITPageHeader({
7344
7398
  ITText,
7345
7399
  {
7346
7400
  as: "p",
7347
- className: flat ? "text-sm font-normal text-slate-500 dark:text-slate-400 mt-0.5 leading-relaxed" : "text-sm font-light text-slate-500 dark:text-slate-400 mt-1 leading-relaxed",
7401
+ className: bento ? "text-sm font-normal text-slate-500 dark:text-slate-400 mt-1.5 leading-relaxed" : flat ? "text-sm font-normal text-slate-500 dark:text-slate-400 mt-0.5 leading-relaxed" : "text-sm font-light text-slate-500 dark:text-slate-400 mt-1 leading-relaxed",
7348
7402
  children: description
7349
7403
  }
7350
7404
  )
@@ -8256,16 +8310,19 @@ function ITSegmentedControl({
8256
8310
  disabled = false
8257
8311
  }) {
8258
8312
  const { button, container } = sizeMap3[size];
8313
+ const bento = useITAppearance() === "bento";
8259
8314
  return /* @__PURE__ */ jsx59(
8260
8315
  "div",
8261
8316
  {
8262
8317
  role: "group",
8263
8318
  className: clsx40(
8264
- "inline-flex rounded-xl bg-slate-100 dark:bg-slate-800 border border-slate-200 dark:border-slate-700",
8319
+ "inline-flex",
8320
+ bento ? "rounded-full" : "rounded-xl bg-slate-100 dark:bg-slate-800 border border-slate-200 dark:border-slate-700",
8265
8321
  container,
8266
8322
  disabled && "opacity-50 cursor-not-allowed",
8267
8323
  className
8268
8324
  ),
8325
+ style: bento ? { backgroundColor: "var(--it-bento-control-bg, #f1f5f9)" } : void 0,
8269
8326
  children: options.map((opt) => {
8270
8327
  const isActive = opt.value === value;
8271
8328
  return /* @__PURE__ */ jsxs41(
@@ -8277,10 +8334,14 @@ function ITSegmentedControl({
8277
8334
  disabled,
8278
8335
  className: clsx40(
8279
8336
  button,
8280
- "rounded-lg font-semibold transition-all flex items-center gap-1.5",
8281
- isActive ? "bg-white dark:bg-slate-700 text-slate-800 dark:text-white shadow-sm border border-slate-200 dark:border-slate-600" : "text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-slate-300 border border-transparent",
8337
+ "font-semibold transition-all flex items-center gap-1.5",
8338
+ bento ? "rounded-full border border-transparent" : isActive ? "rounded-lg bg-white dark:bg-slate-700 text-slate-800 dark:text-white shadow-sm border border-slate-200 dark:border-slate-600" : "rounded-lg text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-slate-300 border border-transparent",
8282
8339
  disabled && "pointer-events-none"
8283
8340
  ),
8341
+ style: bento ? {
8342
+ backgroundColor: isActive ? "var(--it-bento-ink-bg, #0f172a)" : "transparent",
8343
+ color: isActive ? "var(--it-bento-ink-text, #ffffff)" : "var(--it-bento-control-text, #475569)"
8344
+ } : void 0,
8284
8345
  children: [
8285
8346
  opt.icon && /* @__PURE__ */ jsx59("span", { children: opt.icon }),
8286
8347
  /* @__PURE__ */ jsx59(ITText, { as: "span", children: opt.label })
@@ -8333,7 +8394,9 @@ function ITSidebar({
8333
8394
  onToggleCollapse,
8334
8395
  expandOnHover = true
8335
8396
  }) {
8336
- const flat = useITFlatAppearance();
8397
+ const appearance = useITAppearance();
8398
+ const bento = appearance === "bento";
8399
+ const flat = appearance === "flat" || bento;
8337
8400
  const { t } = useITTranslation();
8338
8401
  const [expandedItems, setExpandedItems] = useState27(/* @__PURE__ */ new Set());
8339
8402
  const [isHovering, setIsHovering] = useState27(false);
@@ -8425,7 +8488,7 @@ function ITSidebar({
8425
8488
  color: subitem.isActive ? "var(--it-sidebar-active-color, var(--color-secondary-900))" : "var(--it-sidebar-label-color, var(--color-secondary-600))",
8426
8489
  backgroundColor: subitem.isActive ? "var(--it-sidebar-active-bg, var(--color-secondary-50))" : "transparent",
8427
8490
  fontSize: flat ? "0.84rem" : "0.78rem",
8428
- fontWeight: subitem.isActive ? 600 : 500,
8491
+ fontWeight: subitem.isActive ? bento ? 700 : 600 : 500,
8429
8492
  letterSpacing: "0.01em",
8430
8493
  marginLeft: subitemConnector === "|" ? "-1px" : "0"
8431
8494
  },
@@ -8582,7 +8645,7 @@ function ITSidebar({
8582
8645
  style: {
8583
8646
  zIndex: 50,
8584
8647
  backgroundColor: "var(--it-sidebar-bg, rgba(255, 255, 255, 0.90))",
8585
- borderRight: "1px solid var(--it-sidebar-border, var(--color-secondary-200))",
8648
+ borderRight: bento ? "none" : "1px solid var(--it-sidebar-border, var(--color-secondary-200))",
8586
8649
  ...flat ? {} : { WebkitBackdropFilter: "blur(12px)", backdropFilter: "blur(12px)" }
8587
8650
  },
8588
8651
  children: [
@@ -8676,7 +8739,7 @@ function ITSidebar({
8676
8739
  style: {
8677
8740
  color: active ? "var(--it-sidebar-active-color, #ffffff)" : "var(--it-sidebar-label-color, var(--color-secondary-300))",
8678
8741
  fontSize: flat ? "0.875rem" : "0.8rem",
8679
- fontWeight: active ? "600" : "500"
8742
+ fontWeight: active ? bento ? "700" : "600" : "500"
8680
8743
  },
8681
8744
  children: item.label
8682
8745
  }
@@ -8993,6 +9056,8 @@ function ITLineBarChart({
8993
9056
  barLabel,
8994
9057
  lineColor = "#10b981",
8995
9058
  barColor = "#3b82f6",
9059
+ showLine = true,
9060
+ showBars = true,
8996
9061
  height = 240,
8997
9062
  formatValue,
8998
9063
  formatAxis,
@@ -9010,8 +9075,11 @@ function ITLineBarChart({
9010
9075
  const plotWidth = width - padding.left - padding.right;
9011
9076
  const plotHeight = height - padding.top - padding.bottom;
9012
9077
  const max = useMemo13(
9013
- () => Math.max(...data.flatMap((d) => [d.line, d.bar]), 1),
9014
- [data]
9078
+ () => Math.max(
9079
+ ...data.flatMap((d) => [showLine ? d.line : 0, showBars ? d.bar : 0]),
9080
+ 1
9081
+ ),
9082
+ [data, showLine, showBars]
9015
9083
  );
9016
9084
  const gridValues = [0, 0.25, 0.5, 0.75, 1].map((f) => max * f);
9017
9085
  const step = data.length > 0 ? plotWidth / data.length : plotWidth;
@@ -9055,7 +9123,7 @@ function ITLineBarChart({
9055
9123
  ),
9056
9124
  /* @__PURE__ */ jsx64("text", { x: padding.left - 8, y: y(value) + 3, textAnchor: "end", fontSize: 10, fill: "#94a3b8", children: resolvedFormatAxis(Math.round(value)) })
9057
9125
  ] }, i)),
9058
- data.map((d, i) => /* @__PURE__ */ jsx64(
9126
+ showBars && data.map((d, i) => /* @__PURE__ */ jsx64(
9059
9127
  "rect",
9060
9128
  {
9061
9129
  x: x(i) - barWidth / 2,
@@ -9068,8 +9136,8 @@ function ITLineBarChart({
9068
9136
  },
9069
9137
  `bar-${d.label}`
9070
9138
  )),
9071
- areaPath && /* @__PURE__ */ jsx64("path", { d: areaPath, fill: `url(#area-${gradientId})` }),
9072
- data.length > 0 && /* @__PURE__ */ jsx64(
9139
+ showLine && areaPath && /* @__PURE__ */ jsx64("path", { d: areaPath, fill: `url(#area-${gradientId})` }),
9140
+ showLine && data.length > 0 && /* @__PURE__ */ jsx64(
9073
9141
  "polyline",
9074
9142
  {
9075
9143
  points: linePoints,
@@ -9080,7 +9148,7 @@ function ITLineBarChart({
9080
9148
  strokeLinejoin: "round"
9081
9149
  }
9082
9150
  ),
9083
- data.map((d, i) => /* @__PURE__ */ jsx64(
9151
+ showLine && data.map((d, i) => /* @__PURE__ */ jsx64(
9084
9152
  "circle",
9085
9153
  {
9086
9154
  cx: x(i),
@@ -9107,12 +9175,12 @@ function ITLineBarChart({
9107
9175
  role: "status",
9108
9176
  children: [
9109
9177
  /* @__PURE__ */ jsx64("p", { className: "text-[10px] font-semibold", style: { color: "#e2e8f0" }, children: active.label }),
9110
- /* @__PURE__ */ jsxs45("p", { className: "text-[11px] tabular-nums", style: { color: lineColor }, children: [
9178
+ showLine && /* @__PURE__ */ jsxs45("p", { className: "text-[11px] tabular-nums", style: { color: lineColor }, children: [
9111
9179
  resolvedLineLabel,
9112
9180
  ": ",
9113
9181
  resolvedFormatValue(active.line)
9114
9182
  ] }),
9115
- /* @__PURE__ */ jsxs45("p", { className: "text-[11px] tabular-nums", style: { color: "#93c5fd" }, children: [
9183
+ showBars && /* @__PURE__ */ jsxs45("p", { className: "text-[11px] tabular-nums", style: { color: "#93c5fd" }, children: [
9116
9184
  resolvedBarLabel,
9117
9185
  ": ",
9118
9186
  resolvedFormatValue(active.bar)
@@ -9121,11 +9189,11 @@ function ITLineBarChart({
9121
9189
  }
9122
9190
  ),
9123
9191
  /* @__PURE__ */ jsxs45("ul", { className: "flex flex-wrap items-center gap-4 text-[11px]", style: { color: "#475569" }, children: [
9124
- /* @__PURE__ */ jsxs45("li", { children: [
9192
+ showLine && /* @__PURE__ */ jsxs45("li", { children: [
9125
9193
  /* @__PURE__ */ jsx64("span", { className: "h-2.5 w-2.5 rounded-sm", style: { background: lineColor }, "aria-hidden": true }),
9126
9194
  resolvedLineLabel
9127
9195
  ] }),
9128
- /* @__PURE__ */ jsxs45("li", { children: [
9196
+ showBars && /* @__PURE__ */ jsxs45("li", { children: [
9129
9197
  /* @__PURE__ */ jsx64("span", { className: "h-2.5 w-2.5 rounded-sm", style: { background: barColor }, "aria-hidden": true }),
9130
9198
  resolvedBarLabel
9131
9199
  ] })
@@ -9774,6 +9842,7 @@ function ITTable({
9774
9842
 
9775
9843
  // src/components/atoms/textarea/textarea.tsx
9776
9844
  import clsx46 from "clsx";
9845
+ import { forwardRef as forwardRef2 } from "react";
9777
9846
  import { jsx as jsx66, jsxs as jsxs47 } from "react/jsx-runtime";
9778
9847
  var resizeMap = {
9779
9848
  none: "resize-none",
@@ -9781,7 +9850,7 @@ var resizeMap = {
9781
9850
  horizontal: "resize-x",
9782
9851
  both: "resize"
9783
9852
  };
9784
- function ITTextarea({
9853
+ var ITTextarea = forwardRef2(function ITTextarea2({
9785
9854
  value,
9786
9855
  onChange,
9787
9856
  label,
@@ -9792,13 +9861,16 @@ function ITTextarea({
9792
9861
  className,
9793
9862
  name,
9794
9863
  maxLength,
9795
- resize = "vertical"
9796
- }) {
9864
+ resize = "vertical",
9865
+ onKeyDown,
9866
+ autoFocus = false
9867
+ }, ref) {
9797
9868
  return /* @__PURE__ */ jsxs47("div", { className: clsx46("flex flex-col gap-1.5", className), children: [
9798
9869
  label && /* @__PURE__ */ jsx66(ITText, { as: "label", className: inputLabel(!!error), htmlFor: name, children: label }),
9799
9870
  /* @__PURE__ */ jsx66(
9800
9871
  "textarea",
9801
9872
  {
9873
+ ref,
9802
9874
  id: name,
9803
9875
  name,
9804
9876
  value,
@@ -9807,6 +9879,8 @@ function ITTextarea({
9807
9879
  rows,
9808
9880
  disabled,
9809
9881
  maxLength,
9882
+ onKeyDown,
9883
+ autoFocus,
9810
9884
  className: clsx46(
9811
9885
  "w-full border border-solid transition-all duration-200 rounded-lg px-3 py-2 text-sm outline-none",
9812
9886
  "focus:ring-2",
@@ -9818,7 +9892,9 @@ function ITTextarea({
9818
9892
  ),
9819
9893
  error && /* @__PURE__ */ jsx66(ITText, { as: "span", className: inputError, children: error })
9820
9894
  ] });
9821
- }
9895
+ });
9896
+ ITTextarea.displayName = "ITTextarea";
9897
+ var textarea_default = ITTextarea;
9822
9898
 
9823
9899
  // src/components/molecules/tabs/tabs.tsx
9824
9900
  import { useState as useState31 } from "react";
@@ -9832,6 +9908,7 @@ var ITTabs = ({
9832
9908
  className = "",
9833
9909
  containerClassName = ""
9834
9910
  }) => {
9911
+ const bento = useITAppearance() === "bento" && variant === "pill";
9835
9912
  const [activeId, setActiveId] = useState31(defaultActiveId || items[0]?.id);
9836
9913
  const handleTabClick = (id, disabled) => {
9837
9914
  if (disabled) return;
@@ -9840,39 +9917,50 @@ var ITTabs = ({
9840
9917
  };
9841
9918
  const activeContent = items.find((item) => item.id === activeId)?.content;
9842
9919
  return /* @__PURE__ */ jsxs48("div", { className: clsx47("w-full", containerClassName), children: [
9843
- /* @__PURE__ */ jsx67("div", { className: clsx47(
9844
- "flex border-secondary-200 mb-4",
9845
- variant === "line" ? "border-b" : "gap-2 p-1 bg-secondary-100 rounded-lg w-fit",
9846
- className
9847
- ), children: items.map((item) => {
9848
- const isActive = item.id === activeId;
9849
- return /* @__PURE__ */ jsxs48(
9850
- "button",
9851
- {
9852
- onClick: () => handleTabClick(item.id, item.disabled),
9853
- disabled: item.disabled,
9854
- className: clsx47(
9855
- "flex items-center gap-2 px-4 py-2 text-sm font-medium transition-all duration-200 outline-none",
9856
- // LINE VARIANT
9857
- variant === "line" && [
9858
- "border-b-2 -mb-[2px]",
9859
- isActive ? "border-primary-500 text-primary-600" : "border-transparent text-secondary-500 hover:text-secondary-700 hover:border-secondary-300"
9860
- ],
9861
- // PILL VARIANT
9862
- variant === "pill" && [
9863
- "rounded-md",
9864
- isActive ? "bg-white text-primary-600 shadow-sm" : "text-secondary-500 hover:text-secondary-700"
9865
- ],
9866
- item.disabled && "opacity-50 cursor-not-allowed"
9867
- ),
9868
- children: [
9869
- item.icon && /* @__PURE__ */ jsx67("span", { className: "w-4 h-4", children: item.icon }),
9870
- /* @__PURE__ */ jsx67(ITText, { as: "span", children: item.label })
9871
- ]
9872
- },
9873
- item.id
9874
- );
9875
- }) }),
9920
+ /* @__PURE__ */ jsx67(
9921
+ "div",
9922
+ {
9923
+ className: clsx47(
9924
+ "flex border-secondary-200 mb-4",
9925
+ variant === "line" ? "border-b" : bento ? "gap-2 p-1 rounded-full w-fit" : "gap-2 p-1 bg-secondary-100 rounded-lg w-fit",
9926
+ className
9927
+ ),
9928
+ style: bento ? { backgroundColor: "var(--it-bento-control-bg, #f1f5f9)", borderColor: "transparent" } : void 0,
9929
+ children: items.map((item) => {
9930
+ const isActive = item.id === activeId;
9931
+ return /* @__PURE__ */ jsxs48(
9932
+ "button",
9933
+ {
9934
+ onClick: () => handleTabClick(item.id, item.disabled),
9935
+ disabled: item.disabled,
9936
+ className: clsx47(
9937
+ "flex items-center gap-2 px-4 py-2 text-sm font-medium transition-all duration-200 outline-none",
9938
+ // LINE VARIANT
9939
+ variant === "line" && [
9940
+ "border-b-2 -mb-[2px]",
9941
+ isActive ? "border-primary-500 text-primary-600" : "border-transparent text-secondary-500 hover:text-secondary-700 hover:border-secondary-300"
9942
+ ],
9943
+ // PILL VARIANT
9944
+ variant === "pill" && (bento ? "rounded-full" : [
9945
+ "rounded-md",
9946
+ isActive ? "bg-white text-primary-600 shadow-sm" : "text-secondary-500 hover:text-secondary-700"
9947
+ ]),
9948
+ item.disabled && "opacity-50 cursor-not-allowed"
9949
+ ),
9950
+ style: bento ? {
9951
+ backgroundColor: isActive ? "var(--it-bento-ink-bg, #0f172a)" : "transparent",
9952
+ color: isActive ? "var(--it-bento-ink-text, #ffffff)" : "var(--it-bento-control-text, #475569)"
9953
+ } : void 0,
9954
+ children: [
9955
+ item.icon && /* @__PURE__ */ jsx67("span", { className: "w-4 h-4", children: item.icon }),
9956
+ /* @__PURE__ */ jsx67(ITText, { as: "span", children: item.label })
9957
+ ]
9958
+ },
9959
+ item.id
9960
+ );
9961
+ })
9962
+ }
9963
+ ),
9876
9964
  /* @__PURE__ */ jsx67("div", { className: "tab-content animate-fadeIn", children: activeContent })
9877
9965
  ] });
9878
9966
  };
@@ -12185,7 +12273,7 @@ function EditorToggle({
12185
12273
  }
12186
12274
 
12187
12275
  // src/json-renderer/kernel/SchemaRenderer.tsx
12188
- import { useEffect as useEffect18, useMemo as useMemo16, useRef as useRef23 } from "react";
12276
+ import { useCallback as useCallback12, useEffect as useEffect18, useMemo as useMemo16, useRef as useRef23, useState as useState38 } from "react";
12189
12277
 
12190
12278
  // src/types/loader.types.ts
12191
12279
  var sizeClasses = {
@@ -12366,6 +12454,11 @@ var AXZY_CATALOG_ENTRIES = [
12366
12454
  summary: "Tarjeta con t\xEDtulo, imagen y contenido.",
12367
12455
  props: {
12368
12456
  title: { kind: "string" },
12457
+ tone: {
12458
+ kind: "enum",
12459
+ values: ["primary", "secondary", "ternary", "success", "info", "warning", "danger"],
12460
+ doc: "Tinte pastel de la tarjeta (token --color-<tone>-soft)."
12461
+ },
12369
12462
  image: { kind: "string", doc: "URL de la imagen de cabecera." },
12370
12463
  alt: { kind: "string" },
12371
12464
  onClick: { kind: "action" },
@@ -12496,7 +12589,7 @@ var AXZY_CATALOG_ENTRIES = [
12496
12589
  },
12497
12590
  {
12498
12591
  type: "ITFlex",
12499
- component: ITFlex,
12592
+ component: flex_default,
12500
12593
  children: true,
12501
12594
  summary: "Contenedor flex completo.",
12502
12595
  props: {
@@ -12629,6 +12722,192 @@ var AXZY_EXCLUDED_TYPES = {
12629
12722
  var axzyCatalog = createCatalog(AXZY_CATALOG_ENTRIES, AXZY_EXCLUDED_TYPES);
12630
12723
  var axzyCatalogTypes = Object.keys(axzyCatalog.entries);
12631
12724
 
12725
+ // src/json-renderer/shared/errors.ts
12726
+ var JsonEngineError = class extends Error {
12727
+ constructor(code, message, path, hint) {
12728
+ super(`${code} ${path ? `en ${path}: ` : ""}${message}`);
12729
+ /** Código estable del catálogo de avisos. */
12730
+ __publicField(this, "code");
12731
+ /** Ruta del esquema donde se produjo. */
12732
+ __publicField(this, "path");
12733
+ /** Sugerencia accionable. */
12734
+ __publicField(this, "hint");
12735
+ this.name = "JsonEngineError";
12736
+ this.code = code;
12737
+ this.path = path;
12738
+ this.hint = hint;
12739
+ }
12740
+ /** Convierte el error en el aviso que consume la interfaz y el informe. */
12741
+ toIssue(severity = "error") {
12742
+ return {
12743
+ code: this.code,
12744
+ severity,
12745
+ message: this.message.replace(/^JR\d{3}\s?(en .*?: )?/, ""),
12746
+ path: this.path,
12747
+ hint: this.hint
12748
+ };
12749
+ }
12750
+ };
12751
+ function issue(code, message, path = "", options = {}) {
12752
+ return {
12753
+ code,
12754
+ severity: options.severity ?? "error",
12755
+ message,
12756
+ path,
12757
+ hint: options.hint
12758
+ };
12759
+ }
12760
+
12761
+ // src/json-renderer/shared/paths.ts
12762
+ function pushPath(path, segment) {
12763
+ return [...path, segment];
12764
+ }
12765
+ function formatPath(path) {
12766
+ let out = "";
12767
+ for (const segment of path) {
12768
+ if (typeof segment === "number") out += `[${segment}]`;
12769
+ else out += out ? `.${segment}` : segment;
12770
+ }
12771
+ return out;
12772
+ }
12773
+ function parsePath(rendered) {
12774
+ if (!rendered) return [];
12775
+ return rendered.split(/\.(?![^[]*])/).flatMap((part) => {
12776
+ const match = part.match(/^([^[\]]*)((?:\[\d+\])*)$/);
12777
+ if (!match) return [part];
12778
+ const [, key, indexes] = match;
12779
+ const segments = key ? [key] : [];
12780
+ for (const index of indexes.match(/\d+/g) ?? []) segments.push(Number(index));
12781
+ return segments;
12782
+ });
12783
+ }
12784
+ function readPath(source, path) {
12785
+ let cursor = source;
12786
+ for (const segment of path) {
12787
+ if (cursor === null || typeof cursor !== "object") return void 0;
12788
+ cursor = cursor[segment];
12789
+ }
12790
+ return cursor;
12791
+ }
12792
+ function hasPath(source, path) {
12793
+ if (path.length === 0) return true;
12794
+ const parent = readPath(source, path.slice(0, -1));
12795
+ if (parent === null || typeof parent !== "object") return false;
12796
+ return Object.prototype.hasOwnProperty.call(parent, path[path.length - 1]);
12797
+ }
12798
+ function propPath(nodePath, prop) {
12799
+ return pushPath(pushPath(nodePath, "props"), prop);
12800
+ }
12801
+
12802
+ // src/json-renderer/binding/resolveValue.ts
12803
+ var CLAVES_DE_RED = ["url", "endpoint", "href", "src"];
12804
+ var SUPPORTED_REFERENCES = ["$source", "$state", "$param"];
12805
+ function own(record, key) {
12806
+ return record !== void 0 && Object.prototype.hasOwnProperty.call(record, key);
12807
+ }
12808
+ function isDollarReference(value) {
12809
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
12810
+ return Object.keys(value).some((key) => key.startsWith("$"));
12811
+ }
12812
+ function referenceIssue(message, path, hint) {
12813
+ return issue("JR032", message, formatPath(path), { severity: "warning", hint });
12814
+ }
12815
+ function createBindingResolver(scope) {
12816
+ const readValue = (table, kind, key, path) => {
12817
+ if (own(table, key)) return table[key];
12818
+ scope.report(
12819
+ referenceIssue(
12820
+ `La referencia \`${kind}: "${key}"\` no tiene valor.`,
12821
+ path,
12822
+ kind === "$state" ? "Declara el valor en `state` del esquema." : "El host debe pasar el par\xE1metro en `params`."
12823
+ )
12824
+ );
12825
+ return void 0;
12826
+ };
12827
+ const resolveParams = (declared, path) => {
12828
+ const resolved = {};
12829
+ for (const [name, raw] of Object.entries(declared ?? {})) {
12830
+ if (!isDollarReference(raw)) {
12831
+ resolved[name] = raw;
12832
+ continue;
12833
+ }
12834
+ const [key] = Object.keys(raw).filter((candidate) => candidate.startsWith("$"));
12835
+ if (key === "$state" && typeof raw[key] === "string") {
12836
+ const value = readValue(scope.state, "$state", raw[key], path);
12837
+ if (value !== void 0) resolved[name] = value;
12838
+ } else if (key === "$param" && typeof raw[key] === "string") {
12839
+ const value = readValue(scope.params, "$param", raw[key], path);
12840
+ if (value !== void 0) resolved[name] = value;
12841
+ } else {
12842
+ scope.report(
12843
+ referenceIssue(
12844
+ "Un par\xE1metro de fuente solo admite valores, `$state` o `$param`.",
12845
+ path,
12846
+ "Las fuentes no se encadenan: declara la fuente sin referencias a otras fuentes."
12847
+ )
12848
+ );
12849
+ }
12850
+ }
12851
+ return resolved;
12852
+ };
12853
+ const failingLoader = (message, path, hint) => {
12854
+ scope.report(issue("JR030", message, formatPath(path), { severity: "error", hint }));
12855
+ return () => Promise.reject(new Error(message));
12856
+ };
12857
+ const sourceLoader = (name, path) => {
12858
+ if (!own(scope.data, name)) {
12859
+ return failingLoader(
12860
+ `La fuente \`${name}\` no est\xE1 declarada en \`data\`.`,
12861
+ path,
12862
+ "Decl\xE1rala en `data` del esquema con el `handler` que registra el host."
12863
+ );
12864
+ }
12865
+ const declared = scope.data[name];
12866
+ const claveDeRed = Object.keys(declared).find((clave) => CLAVES_DE_RED.includes(clave));
12867
+ if (claveDeRed) {
12868
+ scope.report(
12869
+ issue("JR031", `El esquema declara \`${claveDeRed}\` en la fuente "${name}": las fuentes no pueden pedir red.`, formatPath(path), {
12870
+ severity: "error",
12871
+ hint: "Una fuente solo nombra un `handler` que registra el host."
12872
+ })
12873
+ );
12874
+ return () => Promise.reject(new Error(`La fuente "${name}" no puede pedir red.`));
12875
+ }
12876
+ const handler = own(scope.handlers, declared.handler) ? scope.handlers[declared.handler] : void 0;
12877
+ if (typeof handler !== "function") {
12878
+ return failingLoader(
12879
+ `El handler \`${declared.handler}\` no est\xE1 registrado por el host.`,
12880
+ path,
12881
+ "El host debe registrarlo en `dataHandlers` del renderizador."
12882
+ );
12883
+ }
12884
+ const params = resolveParams(declared.params, path);
12885
+ return (query) => new Promise((resolve) => resolve(handler(query, params)));
12886
+ };
12887
+ const resolveReference = (ref, path) => {
12888
+ const keys = Object.keys(ref).filter((key2) => key2.startsWith("$"));
12889
+ const [key] = keys;
12890
+ if (keys.length !== 1 || !SUPPORTED_REFERENCES.includes(key) || typeof ref[key] !== "string") {
12891
+ scope.report(
12892
+ referenceIssue(
12893
+ `Referencia no soportada: ${keys.join(", ") || "sin operador"}.`,
12894
+ path,
12895
+ "Soportadas: `$source`, `$state` y `$param`. Los dem\xE1s operadores llegan con las acciones y las tablas."
12896
+ )
12897
+ );
12898
+ return void 0;
12899
+ }
12900
+ const name = ref[key];
12901
+ if (key === "$source") return sourceLoader(name, path);
12902
+ if (key === "$state") return readValue(scope.state, "$state", name, path);
12903
+ return readValue(scope.params, "$param", name, path);
12904
+ };
12905
+ return (value, path) => {
12906
+ if (isDollarReference(value)) return resolveReference(value, path);
12907
+ return scope.host ? scope.host(value, path) : value;
12908
+ };
12909
+ }
12910
+
12632
12911
  // src/json-renderer/shared/limits.ts
12633
12912
  var DEFAULT_LIMITS = {
12634
12913
  maxNodes: 5e3,
@@ -12672,46 +12951,25 @@ function createLimitTracker(limits = DEFAULT_LIMITS) {
12672
12951
  };
12673
12952
  }
12674
12953
 
12675
- // src/json-renderer/kernel/NodeBoundary.tsx
12676
- import React16 from "react";
12677
-
12678
- // src/json-renderer/shared/errors.ts
12679
- var JsonEngineError = class extends Error {
12680
- constructor(code, message, path, hint) {
12681
- super(`${code} ${path ? `en ${path}: ` : ""}${message}`);
12682
- /** Código estable del catálogo de avisos. */
12683
- __publicField(this, "code");
12684
- /** Ruta del esquema donde se produjo. */
12685
- __publicField(this, "path");
12686
- /** Sugerencia accionable. */
12687
- __publicField(this, "hint");
12688
- this.name = "JsonEngineError";
12689
- this.code = code;
12690
- this.path = path;
12691
- this.hint = hint;
12692
- }
12693
- /** Convierte el error en el aviso que consume la interfaz y el informe. */
12694
- toIssue(severity = "error") {
12695
- return {
12696
- code: this.code,
12697
- severity,
12698
- message: this.message.replace(/^JR\d{3}\s?(en .*?: )?/, ""),
12699
- path: this.path,
12700
- hint: this.hint
12701
- };
12954
+ // src/json-renderer/kernel/capabilities.ts
12955
+ function capacidadesRequeridas(requires) {
12956
+ if (requires === void 0 || requires === null) return [];
12957
+ if (typeof requires === "string") return requires === "" ? null : [requires];
12958
+ if (Array.isArray(requires) && requires.every((item) => typeof item === "string" && item !== "")) {
12959
+ return requires;
12702
12960
  }
12703
- };
12704
- function issue(code, message, path = "", options = {}) {
12705
- return {
12706
- code,
12707
- severity: options.severity ?? "error",
12708
- message,
12709
- path,
12710
- hint: options.hint
12711
- };
12961
+ return null;
12962
+ }
12963
+ function faltanCapacidades(requires, concedidas) {
12964
+ const requeridas = capacidadesRequeridas(requires);
12965
+ if (requeridas === null) return ["(requires no v\xE1lido)"];
12966
+ if (requeridas.length === 0) return [];
12967
+ const conjunto = new Set(concedidas ?? []);
12968
+ return requeridas.filter((capacidad) => !conjunto.has(capacidad));
12712
12969
  }
12713
12970
 
12714
12971
  // src/json-renderer/kernel/NodeBoundary.tsx
12972
+ import React16 from "react";
12715
12973
  var NodeBoundary = class extends React16.Component {
12716
12974
  constructor() {
12717
12975
  super(...arguments);
@@ -13059,55 +13317,14 @@ function isNodePending(node) {
13059
13317
  }
13060
13318
 
13061
13319
  // src/json-renderer/kernel/renderNode.tsx
13062
- import React17 from "react";
13320
+ import React18 from "react";
13063
13321
 
13064
- // src/json-renderer/shared/paths.ts
13065
- function pushPath(path, segment) {
13066
- return [...path, segment];
13067
- }
13068
- function formatPath(path) {
13069
- let out = "";
13070
- for (const segment of path) {
13071
- if (typeof segment === "number") out += `[${segment}]`;
13072
- else out += out ? `.${segment}` : segment;
13073
- }
13074
- return out;
13075
- }
13076
- function parsePath(rendered) {
13077
- if (!rendered) return [];
13078
- return rendered.split(/\.(?![^[]*])/).flatMap((part) => {
13079
- const match = part.match(/^([^[\]]*)((?:\[\d+\])*)$/);
13080
- if (!match) return [part];
13081
- const [, key, indexes] = match;
13082
- const segments = key ? [key] : [];
13083
- for (const index of indexes.match(/\d+/g) ?? []) segments.push(Number(index));
13084
- return segments;
13085
- });
13086
- }
13087
- function readPath(source, path) {
13088
- let cursor = source;
13089
- for (const segment of path) {
13090
- if (cursor === null || typeof cursor !== "object") return void 0;
13091
- cursor = cursor[segment];
13092
- }
13093
- return cursor;
13094
- }
13095
- function hasPath(source, path) {
13096
- if (path.length === 0) return true;
13097
- const parent = readPath(source, path.slice(0, -1));
13098
- if (parent === null || typeof parent !== "object") return false;
13099
- return Object.prototype.hasOwnProperty.call(parent, path[path.length - 1]);
13100
- }
13101
- function propPath(nodePath, prop) {
13102
- return pushPath(pushPath(nodePath, "props"), prop);
13103
- }
13104
-
13105
- // src/json-renderer/catalog/resolve.ts
13106
- function isSchemaReference(value) {
13107
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
13108
- const keys = Object.keys(value);
13109
- if (keys.length === 0) return false;
13110
- return keys.some((key) => key === "i18n" || key.startsWith("$"));
13322
+ // src/json-renderer/catalog/resolve.ts
13323
+ function isSchemaReference(value) {
13324
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
13325
+ const keys = Object.keys(value);
13326
+ if (keys.length === 0) return false;
13327
+ return keys.some((key) => key === "i18n" || key.startsWith("$"));
13111
13328
  }
13112
13329
  function coerce(value, spec) {
13113
13330
  switch (spec.kind) {
@@ -13241,11 +13458,457 @@ function resolveNode(node, catalog, path) {
13241
13458
  return { ok: true, entry, props, actions, issues };
13242
13459
  }
13243
13460
 
13461
+ // src/json-renderer/kernel/slots.ts
13462
+ var SLOT_TYPE = "slot";
13463
+ function isSlotNode(node) {
13464
+ return node.type === SLOT_TYPE;
13465
+ }
13466
+ function slotName(node) {
13467
+ const name = node.props?.name;
13468
+ return typeof name === "string" && name !== "" ? name : void 0;
13469
+ }
13470
+
13471
+ // src/json-renderer/form/FormNode.tsx
13472
+ import { useState as useState37 } from "react";
13473
+
13474
+ // src/json-renderer/form/rules.ts
13475
+ var FORM_FIELD_KINDS = ["text", "email"];
13476
+ var EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
13477
+ function longitudDeclarada(value) {
13478
+ return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : void 0;
13479
+ }
13480
+ function readFormFields(declared, fieldsPath) {
13481
+ const issues = [];
13482
+ const fields = [];
13483
+ if (!Array.isArray(declared)) {
13484
+ issues.push(issue("JR021", "El formulario necesita `props.fields` como lista.", formatPath(fieldsPath), { severity: "error" }));
13485
+ return { fields, issues };
13486
+ }
13487
+ const nombres = /* @__PURE__ */ new Set();
13488
+ declared.forEach((raw, index) => {
13489
+ const fieldPath = [...fieldsPath, index];
13490
+ const campo = raw;
13491
+ if (!campo || typeof campo !== "object" || typeof campo.name !== "string" || campo.name === "") {
13492
+ issues.push(issue("JR021", "Un campo del formulario no declara `name`.", formatPath(fieldPath), { severity: "error" }));
13493
+ return;
13494
+ }
13495
+ if (nombres.has(campo.name)) {
13496
+ issues.push(issue("JR021", `El campo "${campo.name}" se repite.`, formatPath(fieldPath), { severity: "error" }));
13497
+ return;
13498
+ }
13499
+ let kind = "text";
13500
+ if (campo.kind !== void 0) {
13501
+ if (typeof campo.kind === "string" && FORM_FIELD_KINDS.includes(campo.kind)) {
13502
+ kind = campo.kind;
13503
+ } else {
13504
+ issues.push(
13505
+ issue("JR011", `Tipo de campo "${String(campo.kind)}" no admitido.`, formatPath(fieldPath), {
13506
+ severity: "warning",
13507
+ hint: `Admitidos: ${FORM_FIELD_KINDS.join(", ")}. Se usa "text".`
13508
+ })
13509
+ );
13510
+ }
13511
+ }
13512
+ const minLength = longitudDeclarada(campo.minLength);
13513
+ const maxLength = longitudDeclarada(campo.maxLength);
13514
+ for (const [clave, valor, declarada] of [["minLength", campo.minLength, minLength], ["maxLength", campo.maxLength, maxLength]]) {
13515
+ if (valor !== void 0 && declarada === void 0) {
13516
+ issues.push(issue("JR011", `\`${clave}\` debe ser un entero no negativo.`, formatPath(fieldPath), { severity: "warning", hint: "Se ignora." }));
13517
+ }
13518
+ }
13519
+ if (minLength !== void 0 && maxLength !== void 0 && minLength > maxLength) {
13520
+ issues.push(issue("JR021", `El campo "${campo.name}" tiene minLength mayor que maxLength.`, formatPath(fieldPath), { severity: "error" }));
13521
+ return;
13522
+ }
13523
+ nombres.add(campo.name);
13524
+ fields.push({ name: campo.name, kind, required: campo.required === true, minLength, maxLength, label: campo.label });
13525
+ });
13526
+ return { fields, issues };
13527
+ }
13528
+ function validateField(field, value) {
13529
+ const texto = value.trim();
13530
+ if (texto === "") return field.required ? "required" : void 0;
13531
+ if (field.minLength !== void 0 && texto.length < field.minLength) return "minLength";
13532
+ if (field.maxLength !== void 0 && texto.length > field.maxLength) return "maxLength";
13533
+ if (field.kind === "email" && !EMAIL.test(texto)) return "email";
13534
+ return void 0;
13535
+ }
13536
+ function validateForm(fields, values) {
13537
+ const errores = {};
13538
+ for (const field of fields) {
13539
+ const code = validateField(field, values[field.name] ?? "");
13540
+ if (code) errores[field.name] = code;
13541
+ }
13542
+ return errores;
13543
+ }
13544
+
13545
+ // src/json-renderer/form/FormNode.tsx
13546
+ import { jsx as jsx75, jsxs as jsxs54 } from "react/jsx-runtime";
13547
+ function valorDe(evento) {
13548
+ if (typeof evento === "string") return evento;
13549
+ return evento?.target?.value?.toString() ?? "";
13550
+ }
13551
+ function FormNode({ id, fields, submitLabel, onSubmit }) {
13552
+ const { t } = useITTranslation();
13553
+ const [values, setValues] = useState37({});
13554
+ const [errors, setErrors] = useState37({});
13555
+ const [intentado, setIntentado] = useState37(false);
13556
+ const mensaje = (code, campo) => t(`jsonRenderer.form.${code}`, { min: String(campo.minLength ?? 0), max: String(campo.maxLength ?? 0) });
13557
+ const enviar = () => {
13558
+ const encontrados = validateForm(fields, values);
13559
+ setIntentado(true);
13560
+ setErrors(encontrados);
13561
+ if (Object.keys(encontrados).length === 0) onSubmit?.(values);
13562
+ };
13563
+ return /* @__PURE__ */ jsx75("div", { id, children: /* @__PURE__ */ jsxs54(ITStack, { direction: "column", spacing: 3, alignItems: "stretch", children: [
13564
+ fields.map((field) => /* @__PURE__ */ jsx75(
13565
+ ITInput,
13566
+ {
13567
+ name: field.name,
13568
+ label: field.label,
13569
+ type: field.kind === "email" ? "email" : "text",
13570
+ value: values[field.name] ?? "",
13571
+ touched: intentado,
13572
+ error: errors[field.name] ? mensaje(errors[field.name], field) : void 0,
13573
+ onChange: (evento) => {
13574
+ const valor = valorDe(evento);
13575
+ setValues((previo) => ({ ...previo, [field.name]: valor }));
13576
+ setErrors((previo) => {
13577
+ if (!previo[field.name]) return previo;
13578
+ const resto = { ...previo };
13579
+ delete resto[field.name];
13580
+ return resto;
13581
+ });
13582
+ }
13583
+ },
13584
+ field.name
13585
+ )),
13586
+ /* @__PURE__ */ jsx75(flex_default, { children: /* @__PURE__ */ jsx75(ITButton, { label: submitLabel ?? t("jsonRenderer.form.submit"), size: "sm", onClick: enviar }) })
13587
+ ] }) });
13588
+ }
13589
+
13590
+ // src/json-renderer/actions/effects.ts
13591
+ var MAX_EFFECT_DEPTH = 5;
13592
+ var EFFECT_KEYS = ["toast", "navigate", "refresh", "openOverlay", "closeOverlay", "set"];
13593
+ var EFFECT_KEYS_DEL_HOST = ["toast", "navigate", "refresh", "openOverlay", "closeOverlay"];
13594
+ function leerResultado(ruta, resultado) {
13595
+ return ruta.split(".").reduce(
13596
+ (actual, clave) => actual && typeof actual === "object" ? actual[clave] : void 0,
13597
+ resultado
13598
+ );
13599
+ }
13600
+ function resolverResultado(valor, resultado) {
13601
+ if (!valor || typeof valor !== "object" || Array.isArray(valor)) return valor;
13602
+ const objeto = valor;
13603
+ if (typeof objeto.$result === "string") return leerResultado(objeto.$result, resultado) ?? "";
13604
+ if (objeto.params && typeof objeto.params === "object") {
13605
+ const params = Object.fromEntries(
13606
+ Object.entries(objeto.params).map(([clave, valorParam]) => [
13607
+ clave,
13608
+ resolverResultado(valorParam, resultado)
13609
+ ])
13610
+ );
13611
+ return { ...objeto, params };
13612
+ }
13613
+ return valor;
13614
+ }
13615
+ function plantilla(texto, resultado) {
13616
+ return texto.replace(/\{([\w.]+)\}/g, (_, ruta) => {
13617
+ const valor = leerResultado(ruta, resultado);
13618
+ return valor === void 0 ? "" : String(valor);
13619
+ });
13620
+ }
13621
+ function efectosSueltos(declarada) {
13622
+ const sueltos = {};
13623
+ for (const clave of EFFECT_KEYS) {
13624
+ if (declarada[clave] !== void 0) sueltos[clave] = declarada[clave];
13625
+ }
13626
+ return Object.keys(sueltos).length > 0 ? sueltos : null;
13627
+ }
13628
+ function comprobarRegistro(efecto, context) {
13629
+ for (const clave of EFFECT_KEYS_DEL_HOST) {
13630
+ if (efecto[clave] === void 0) continue;
13631
+ if (typeof context.effects?.[clave] !== "function") {
13632
+ context.report(
13633
+ issue("JR040", `El host no implementa el efecto \`${clave}\`.`, formatPath(context.path), {
13634
+ severity: "warning",
13635
+ hint: "Reg\xEDstralo en `effects` del renderizador o quita el efecto del esquema."
13636
+ })
13637
+ );
13638
+ }
13639
+ }
13640
+ }
13641
+ function cumplirEfecto(efecto, context, resultado) {
13642
+ if (efecto.set && context.setState) {
13643
+ const cambios = {};
13644
+ for (const [clave, valor] of Object.entries(efecto.set)) {
13645
+ const conResultado = resolverResultado(valor, resultado);
13646
+ cambios[clave] = context.resolveRaw ? context.resolveRaw(conResultado, context.path) : conResultado;
13647
+ }
13648
+ context.setState(cambios);
13649
+ }
13650
+ const registro = context.effects;
13651
+ if (!registro) return;
13652
+ if (efecto.toast && registro.toast) {
13653
+ registro.toast({
13654
+ variant: efecto.toast.variant ?? "info",
13655
+ message: context.resolveText(resolverResultado(efecto.toast.message, resultado), context.path)
13656
+ });
13657
+ }
13658
+ if (typeof efecto.navigate === "string" && registro.navigate) {
13659
+ registro.navigate(plantilla(efecto.navigate, resultado));
13660
+ }
13661
+ if (typeof efecto.refresh === "string" && registro.refresh) registro.refresh(efecto.refresh);
13662
+ if (typeof efecto.openOverlay === "string" && registro.openOverlay) registro.openOverlay(efecto.openOverlay);
13663
+ if (efecto.closeOverlay !== void 0 && registro.closeOverlay) {
13664
+ registro.closeOverlay(typeof efecto.closeOverlay === "string" ? efecto.closeOverlay : void 0);
13665
+ }
13666
+ }
13667
+ function pasosDe(efectos, context) {
13668
+ const profundidad = context.depth ?? 0;
13669
+ return efectos.map((efecto) => {
13670
+ if (typeof efecto.action !== "string") {
13671
+ comprobarRegistro(efecto, context);
13672
+ return (resultado) => cumplirEfecto(efecto, context, resultado);
13673
+ }
13674
+ if (profundidad + 1 > MAX_EFFECT_DEPTH) {
13675
+ context.report(
13676
+ issue("JR042", `El encadenado de acciones supera ${MAX_EFFECT_DEPTH} niveles.`, formatPath(context.path), {
13677
+ severity: "error",
13678
+ hint: "Reduce los `then` anidados."
13679
+ })
13680
+ );
13681
+ return () => void 0;
13682
+ }
13683
+ const handler = context.resolveChained?.(efecto.action);
13684
+ if (!handler) {
13685
+ context.report(
13686
+ issue("JR040", `La acci\xF3n encadenada \`${efecto.action}\` no est\xE1 registrada por el host.`, formatPath(context.path), {
13687
+ severity: "error",
13688
+ hint: "Reg\xEDstrala en las acciones del renderizador o cambia el nombre en el esquema."
13689
+ })
13690
+ );
13691
+ return () => void 0;
13692
+ }
13693
+ const encadenada = wrapAction(handler, efecto, { ...context, depth: profundidad + 1 });
13694
+ return () => encadenada(efecto.args);
13695
+ });
13696
+ }
13697
+ function wrapAction(handler, action, context) {
13698
+ if (!action || typeof action !== "object") return handler;
13699
+ const declarada = action;
13700
+ const sueltos = efectosSueltos(declarada);
13701
+ const alTerminar = [...sueltos ? [sueltos] : [], ...Array.isArray(declarada.then) ? declarada.then : []];
13702
+ const alFallar = declarada.onError;
13703
+ if (alTerminar.length === 0 && !alFallar) return handler;
13704
+ const pasosOk = pasosDe(alTerminar, context);
13705
+ const pasoError = alFallar ? pasosDe([alFallar], context)[0] : void 0;
13706
+ const aplicar = (resultado) => pasosOk.forEach((paso) => paso(resultado));
13707
+ return (...args) => {
13708
+ let resultado;
13709
+ try {
13710
+ resultado = handler(...args);
13711
+ } catch {
13712
+ pasoError?.(void 0);
13713
+ return void 0;
13714
+ }
13715
+ if (resultado && typeof resultado.then === "function") {
13716
+ let resuelta = false;
13717
+ const limite = context.timeoutMs;
13718
+ const temporizador = limite !== void 0 && Number.isFinite(limite) ? setTimeout(() => {
13719
+ if (resuelta) return;
13720
+ resuelta = true;
13721
+ context.reportRuntime?.(
13722
+ issue("JR041", `La acci\xF3n excedi\xF3 ${limite} ms y se considera fallida.`, formatPath(context.path), {
13723
+ severity: "error",
13724
+ hint: "El host debe responder o rechazar la acci\xF3n a tiempo."
13725
+ })
13726
+ );
13727
+ pasoError?.(void 0);
13728
+ }, limite) : void 0;
13729
+ resultado.then(
13730
+ (valor) => {
13731
+ if (resuelta) return;
13732
+ resuelta = true;
13733
+ clearTimeout(temporizador);
13734
+ aplicar(valor);
13735
+ },
13736
+ () => {
13737
+ if (resuelta) return;
13738
+ resuelta = true;
13739
+ clearTimeout(temporizador);
13740
+ pasoError?.(void 0);
13741
+ }
13742
+ );
13743
+ return resultado;
13744
+ }
13745
+ aplicar(resultado);
13746
+ return resultado;
13747
+ };
13748
+ }
13749
+
13244
13750
  // src/json-renderer/kernel/renderNode.tsx
13751
+ function effectContext(options, path, node) {
13752
+ return {
13753
+ effects: options.effects,
13754
+ path,
13755
+ resolveText: (value, valuePath) => textoDe(options.resolveValue ? options.resolveValue(value, valuePath) : value),
13756
+ report: (aviso) => options.issues.push(aviso),
13757
+ // Una acción encadenada desde un efecto se resuelve con el mismo `resolveAction` del host.
13758
+ resolveChained: (name) => options.resolveAction?.(node, "chain", { action: name }, path),
13759
+ timeoutMs: options.actionTimeoutMs,
13760
+ reportRuntime: options.onIssue,
13761
+ setState: options.setState,
13762
+ resolveRaw: (value, valuePath) => options.resolveValue ? options.resolveValue(value, valuePath) : value
13763
+ };
13764
+ }
13765
+ function nombreDeAccion(action) {
13766
+ const nombre = action?.action;
13767
+ return typeof nombre === "string" ? nombre : "(sin nombre)";
13768
+ }
13769
+ function isFormNode(node) {
13770
+ return node.type === "form";
13771
+ }
13772
+ function textoDe(value) {
13773
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : "";
13774
+ }
13245
13775
  function childList(node) {
13246
13776
  if (!node || node.children === void 0 || node.children === null) return [];
13247
13777
  return Array.isArray(node.children) ? node.children : [node.children];
13248
13778
  }
13779
+ function renderSlot(node, options) {
13780
+ const { path, issues, slots, resolveValue } = options;
13781
+ const name = slotName(node);
13782
+ if (!name) {
13783
+ issues.push(
13784
+ issue("JR011", "El slot no declara `props.name`.", formatPath(propPath(path, "name")), {
13785
+ severity: "error",
13786
+ hint: 'Declara el nombre que el host registr\xF3, por ejemplo { "type": "slot", "props": { "name": "resumen" } }.'
13787
+ })
13788
+ );
13789
+ return null;
13790
+ }
13791
+ const Component = slots && Object.prototype.hasOwnProperty.call(slots, name) ? slots[name] : void 0;
13792
+ if (!Component) {
13793
+ issues.push(
13794
+ issue("JR010", `El slot \`${name}\` no est\xE1 registrado por el host.`, formatPath(path), {
13795
+ severity: "error",
13796
+ hint: "El host debe registrarlo en `slots` del renderizador."
13797
+ })
13798
+ );
13799
+ return null;
13800
+ }
13801
+ const props = {};
13802
+ for (const [key, raw] of Object.entries(node.props ?? {})) {
13803
+ if (key === "name") continue;
13804
+ props[key] = resolveValue ? resolveValue(raw, path) : raw;
13805
+ }
13806
+ return React18.createElement(Component, { key: node.id ?? path.join("-"), ...props });
13807
+ }
13808
+ function renderForm(node, options) {
13809
+ const { path, issues, resolveValue, resolveAction } = options;
13810
+ const { fields: declarados, issues: avisos } = readFormFields(node.props?.fields, [...path, "props", "fields"]);
13811
+ issues.push(...avisos);
13812
+ const campos = declarados.map((campo, index) => {
13813
+ const etiqueta = resolveValue ? resolveValue(campo.label, [...path, "props", "fields", index]) : campo.label;
13814
+ return {
13815
+ name: campo.name,
13816
+ kind: campo.kind,
13817
+ required: campo.required,
13818
+ minLength: campo.minLength,
13819
+ maxLength: campo.maxLength,
13820
+ label: textoDe(etiqueta) || campo.name
13821
+ };
13822
+ });
13823
+ const textoEnvio = node.props?.submitLabel;
13824
+ const submitLabel = textoDe(resolveValue ? resolveValue(textoEnvio, path) : textoEnvio) || void 0;
13825
+ const accion = resolveAction?.(node, "onSubmit", node.props?.onSubmit, path);
13826
+ if (node.props?.onSubmit !== void 0 && typeof accion !== "function") {
13827
+ issues.push(
13828
+ issue("JR040", `La acci\xF3n "${nombreDeAccion(node.props.onSubmit)}" no est\xE1 registrada por el host.`, formatPath(propPath(path, "onSubmit")), {
13829
+ severity: "warning",
13830
+ hint: "Reg\xEDstrala en `resolveAction` del host. Sin ella, enviar el formulario no hace nada."
13831
+ })
13832
+ );
13833
+ }
13834
+ const conEfectos = accion ? wrapAction(accion, node.props?.onSubmit, effectContext(options, path, node)) : void 0;
13835
+ return React18.createElement(FormNode, {
13836
+ key: node.id ?? path.join("-"),
13837
+ id: node.id,
13838
+ fields: campos,
13839
+ submitLabel,
13840
+ onSubmit: conEfectos ? (valores) => conEfectos(valores) : void 0
13841
+ });
13842
+ }
13843
+ function prepararColumnas(columnas, node, options, path) {
13844
+ if (!Array.isArray(columnas)) return columnas;
13845
+ return columnas.map((columna, indice) => {
13846
+ if (!columna || typeof columna !== "object") return columna;
13847
+ const declarada = columna;
13848
+ if (declarada.type !== "actions" || !Array.isArray(declarada.rowActions)) return columna;
13849
+ const colPath = [...path, "props", "columns", indice];
13850
+ const botones = declarada.rowActions.flatMap((raw, indiceAccion) => {
13851
+ const accion = raw;
13852
+ const rutaAccion = [...colPath, "rowActions", indiceAccion];
13853
+ if (!accion || typeof accion.action !== "string" || accion.action === "") {
13854
+ options.issues.push(issue("JR021", "Un bot\xF3n de fila no declara `action`.", formatPath(rutaAccion), { severity: "error" }));
13855
+ return [];
13856
+ }
13857
+ const faltan = faltanCapacidades(accion.requires, options.capabilities);
13858
+ if (faltan.length > 0) {
13859
+ options.issues.push(
13860
+ issue("JR061", `El bot\xF3n de fila "${accion.action}" exige ${faltan.join(", ")}, que no est\xE1 concedido.`, formatPath(rutaAccion), {
13861
+ severity: "warning",
13862
+ hint: "Concede la capacidad con la prop `capabilities` del renderizador."
13863
+ })
13864
+ );
13865
+ return [];
13866
+ }
13867
+ const handler = options.resolveAction?.(node, `fila:${accion.action}`, accion, rutaAccion);
13868
+ if (typeof handler !== "function") {
13869
+ options.issues.push(
13870
+ issue("JR040", `La acci\xF3n de fila "${accion.action}" no est\xE1 registrada por el host.`, formatPath(rutaAccion), {
13871
+ severity: "warning",
13872
+ hint: "Reg\xEDstrala en `resolveAction` del host, o quita el bot\xF3n del esquema."
13873
+ })
13874
+ );
13875
+ return [];
13876
+ }
13877
+ const etiqueta = textoDe(options.resolveValue ? options.resolveValue(accion.label, rutaAccion) : accion.label);
13878
+ return [
13879
+ {
13880
+ clave: String(indiceAccion),
13881
+ etiqueta: etiqueta || accion.action,
13882
+ color: typeof accion.color === "string" ? accion.color : "secondary",
13883
+ variante: typeof accion.variant === "string" ? accion.variant : "outlined",
13884
+ ejecutar: wrapAction(handler, accion, effectContext(options, rutaAccion, node))
13885
+ }
13886
+ ];
13887
+ });
13888
+ const copia = { ...declarada };
13889
+ delete copia.rowActions;
13890
+ const etiquetaColumna = textoDe(options.resolveValue ? options.resolveValue(copia.label, colPath) : copia.label);
13891
+ const Boton = ITButton;
13892
+ return {
13893
+ ...copia,
13894
+ label: etiquetaColumna || String(copia.key ?? ""),
13895
+ actions: (fila) => React18.createElement(
13896
+ React18.Fragment,
13897
+ null,
13898
+ botones.map(
13899
+ (boton) => React18.createElement(Boton, {
13900
+ key: boton.clave,
13901
+ label: boton.etiqueta,
13902
+ size: "sm",
13903
+ variant: boton.variante,
13904
+ color: boton.color,
13905
+ onClick: () => boton.ejecutar(fila)
13906
+ })
13907
+ )
13908
+ )
13909
+ };
13910
+ });
13911
+ }
13249
13912
  function renderNode(node, options) {
13250
13913
  const { catalog, path, issues, renderChildren } = options;
13251
13914
  if (!node || typeof node !== "object") {
@@ -13254,6 +13917,12 @@ function renderNode(node, options) {
13254
13917
  if (isNodePending(node)) {
13255
13918
  return options.pendingFallback ?? null;
13256
13919
  }
13920
+ if (isSlotNode(node)) {
13921
+ return renderSlot(node, options);
13922
+ }
13923
+ if (isFormNode(node)) {
13924
+ return renderForm(node, options);
13925
+ }
13257
13926
  const resolved = resolveNode(node, catalog, path);
13258
13927
  issues.push(...resolved.issues);
13259
13928
  if (!resolved.ok) {
@@ -13264,15 +13933,37 @@ function renderNode(node, options) {
13264
13933
  for (const [name, value] of Object.entries(props)) {
13265
13934
  finalProps[name] = options.resolveValue ? options.resolveValue(value, path) : value;
13266
13935
  }
13936
+ if (node.type === "ITDataTable" && finalProps.columns !== void 0) {
13937
+ finalProps.columns = prepararColumnas(finalProps.columns, node, options, path);
13938
+ }
13267
13939
  for (const [name, action] of Object.entries(actions)) {
13940
+ const faltan = faltanCapacidades(action?.requires, options.capabilities);
13941
+ if (faltan.length > 0) {
13942
+ issues.push(
13943
+ issue("JR061", `La acci\xF3n "${nombreDeAccion(action)}" exige ${faltan.join(", ")}, que no est\xE1 concedido.`, formatPath(propPath(path, name)), {
13944
+ severity: "warning",
13945
+ hint: "Concede la capacidad con la prop `capabilities` del renderizador. Sin ella, la acci\xF3n no se ejecuta."
13946
+ })
13947
+ );
13948
+ continue;
13949
+ }
13268
13950
  const handler = options.resolveAction?.(node, name, action, path);
13269
- if (typeof handler === "function") finalProps[name] = handler;
13951
+ if (typeof handler === "function") {
13952
+ finalProps[name] = wrapAction(handler, action, effectContext(options, path, node));
13953
+ } else {
13954
+ issues.push(
13955
+ issue("JR040", `La acci\xF3n "${nombreDeAccion(action)}" no est\xE1 registrada por el host.`, formatPath(propPath(path, name)), {
13956
+ severity: "warning",
13957
+ hint: "Reg\xEDstrala en `resolveAction` del host, o quita la prop del esquema."
13958
+ })
13959
+ );
13960
+ }
13270
13961
  }
13271
13962
  const content = renderChildren ? renderChildren(node, path) : null;
13272
13963
  const rawText = entry.text && node.text !== void 0 ? node.text : void 0;
13273
13964
  const text = rawText === void 0 ? void 0 : options.resolveValue ? options.resolveValue(rawText, path) : rawText;
13274
13965
  const children = content ?? text;
13275
- const element = React17.createElement(
13966
+ const element = React18.createElement(
13276
13967
  entry.component,
13277
13968
  { ...finalProps, key: node.id ?? path.join("-"), id: node.id },
13278
13969
  children
@@ -13328,7 +14019,7 @@ function countPendingNodes(schema) {
13328
14019
  }
13329
14020
 
13330
14021
  // src/json-renderer/kernel/SchemaRenderer.tsx
13331
- import { Fragment as Fragment13, jsx as jsx75 } from "react/jsx-runtime";
14022
+ import { Fragment as Fragment13, jsx as jsx76 } from "react/jsx-runtime";
13332
14023
  function renderTree(node, path, context, level) {
13333
14024
  if (!node || typeof node !== "object") return null;
13334
14025
  if (level > context.limits.maxDepth) return null;
@@ -13338,6 +14029,16 @@ function renderTree(node, path, context, level) {
13338
14029
  issues.push(issue2);
13339
14030
  context.onIssue?.(issue2);
13340
14031
  };
14032
+ const faltan = faltanCapacidades(node.requires, context.capabilities);
14033
+ if (faltan.length > 0) {
14034
+ reportIssue(
14035
+ issue("JR060", `Falta la capacidad ${faltan.join(", ")} para pintar \`${node.type}\`.`, formatPath(path), {
14036
+ severity: "warning",
14037
+ hint: "El host debe conceder la capacidad con la prop `capabilities`, o el nodo debe declarar un `fallback`."
14038
+ })
14039
+ );
14040
+ return node.fallback ? renderTree(node.fallback, [...path, "fallback"], context, level + 1) : null;
14041
+ }
13341
14042
  const issuesBefore = issues.length;
13342
14043
  const element = renderNode(node, {
13343
14044
  catalog: context.catalog,
@@ -13346,6 +14047,12 @@ function renderTree(node, path, context, level) {
13346
14047
  resolveValue: context.resolveValue,
13347
14048
  resolveAction: context.resolveAction,
13348
14049
  pendingFallback: context.pendingFallback,
14050
+ slots: context.slots,
14051
+ effects: context.effects,
14052
+ actionTimeoutMs: context.limits.actionTimeoutMs,
14053
+ onIssue: context.onIssue,
14054
+ setState: context.setState,
14055
+ capabilities: context.capabilities,
13349
14056
  renderChildren: (current, currentPath) => {
13350
14057
  const children = childList(current);
13351
14058
  if (children.length === 0) return void 0;
@@ -13358,7 +14065,7 @@ function renderTree(node, path, context, level) {
13358
14065
  context.onIssue?.(issues[index]);
13359
14066
  }
13360
14067
  const fallback = node.fallback ? renderTree(node.fallback, [...path, "fallback"], context, level + 1) : context.pendingFallback ?? null;
13361
- const wrapped = /* @__PURE__ */ jsx75(
14068
+ const wrapped = /* @__PURE__ */ jsx76(
13362
14069
  NodeBoundary,
13363
14070
  {
13364
14071
  path: path.join("."),
@@ -13380,6 +14087,11 @@ function ITSchemaRenderer({
13380
14087
  schema,
13381
14088
  catalog = axzyCatalog,
13382
14089
  limits,
14090
+ params,
14091
+ dataHandlers,
14092
+ slots,
14093
+ effects,
14094
+ capabilities,
13383
14095
  resolveValue,
13384
14096
  resolveAction,
13385
14097
  pendingFallback,
@@ -13387,6 +14099,21 @@ function ITSchemaRenderer({
13387
14099
  className
13388
14100
  }) {
13389
14101
  const resolvedLimits = useMemo16(() => resolveLimits(limits), [limits]);
14102
+ const [escrito, setEscrito] = useState38({
14103
+ origen: schema,
14104
+ valores: {}
14105
+ });
14106
+ const valoresPantalla = useMemo16(
14107
+ () => ({ ...schema?.state ?? {}, ...escrito.origen === schema ? escrito.valores : {} }),
14108
+ [schema, escrito]
14109
+ );
14110
+ const escribirEstado = useCallback12(
14111
+ (cambios) => setEscrito((previo) => ({
14112
+ origen: schema,
14113
+ valores: { ...previo.origen === schema ? previo.valores : {}, ...cambios }
14114
+ })),
14115
+ [schema]
14116
+ );
13390
14117
  const issues = [];
13391
14118
  const nodeIds = /* @__PURE__ */ new Set();
13392
14119
  const audit = useMemo16(
@@ -13400,16 +14127,37 @@ function ITSchemaRenderer({
13400
14127
  limits: resolvedLimits,
13401
14128
  issues,
13402
14129
  onIssue,
13403
- resolveValue,
14130
+ // El binding escribe sus avisos (JR030, JR032) en el mismo array que el resto del render.
14131
+ resolveValue: createBindingResolver({
14132
+ data: schema?.data,
14133
+ state: valoresPantalla,
14134
+ params,
14135
+ handlers: dataHandlers,
14136
+ report: (aviso) => issues.push(aviso),
14137
+ host: resolveValue
14138
+ }),
13404
14139
  resolveAction,
13405
- pendingFallback
14140
+ pendingFallback,
14141
+ slots,
14142
+ effects,
14143
+ capabilities,
14144
+ setState: escribirEstado
13406
14145
  }),
13407
14146
  // `issues` es un array nuevo en cada render a propósito: acumular avisos
13408
14147
  // entre renders duplicaría los avisos de esquemas que no han cambiado.
13409
14148
  // eslint-disable-next-line react-hooks/exhaustive-deps
13410
- [catalog, resolvedLimits, onIssue, resolveValue, resolveAction, pendingFallback]
14149
+ [schema, params, valoresPantalla, escribirEstado, dataHandlers, slots, effects, capabilities, catalog, resolvedLimits, onIssue, resolveValue, resolveAction, pendingFallback]
13411
14150
  );
13412
- const content = schema ? (Array.isArray(schema.content) ? schema.content : [schema.content]).filter(
14151
+ const faltanRaiz = schema ? faltanCapacidades(schema.requires, capabilities) : [];
14152
+ if (faltanRaiz.length > 0) {
14153
+ issues.push(
14154
+ issue("JR060", `Falta la capacidad ${faltanRaiz.join(", ")} para esta pantalla.`, "requires", {
14155
+ severity: "error",
14156
+ hint: "Concede la capacidad con la prop `capabilities` del renderizador."
14157
+ })
14158
+ );
14159
+ }
14160
+ const content = schema && faltanRaiz.length === 0 ? (Array.isArray(schema.content) ? schema.content : [schema.content]).filter(
13413
14161
  (node) => Boolean(node) && typeof node === "object"
13414
14162
  ) : [];
13415
14163
  const children = content.slice(0, resolvedLimits.maxNodes).map((node, index) => renderTree(node, ["content", index], context, 0)).filter(Boolean);
@@ -13435,7 +14183,159 @@ function ITSchemaRenderer({
13435
14183
  for (const issue2 of all) onIssue(issue2);
13436
14184
  }, [signature, onIssue]);
13437
14185
  if (!schema || children.length === 0) return null;
13438
- return className ? /* @__PURE__ */ jsx75("div", { className, children }) : /* @__PURE__ */ jsx75(Fragment13, { children });
14186
+ return className ? /* @__PURE__ */ jsx76("div", { className, children }) : /* @__PURE__ */ jsx76(Fragment13, { children });
14187
+ }
14188
+
14189
+ // src/json-renderer/routing/routes.ts
14190
+ function joinRoutePath(parent, own2) {
14191
+ return [parent, typeof own2 === "string" ? own2 : ""].flatMap((part) => part.split("/")).filter((segment) => segment !== "").join("/");
14192
+ }
14193
+ var SEGMENT = /^(:[A-Za-z][A-Za-z0-9_]*|[A-Za-z0-9_.-]+)$/;
14194
+ function validateRoutes(input) {
14195
+ const errors = [];
14196
+ const document2 = input;
14197
+ if (!document2 || typeof document2 !== "object" || Array.isArray(document2)) {
14198
+ return [issue("JR020", "El documento de rutas debe ser un objeto.", "", { severity: "error" })];
14199
+ }
14200
+ if (typeof document2.version !== "number") {
14201
+ errors.push(issue("JR020", "El documento de rutas no declara `version`.", "version", { severity: "error" }));
14202
+ }
14203
+ if (!Array.isArray(document2.routes)) {
14204
+ errors.push(issue("JR020", "`routes` debe ser una lista.", "routes", { severity: "error" }));
14205
+ return errors;
14206
+ }
14207
+ const seen = /* @__PURE__ */ new Map();
14208
+ const visit = (route, path, parentPath, isRoot) => {
14209
+ if (!route || typeof route !== "object") {
14210
+ errors.push(issue("JR021", "La ruta no es un objeto.", path, { severity: "error" }));
14211
+ return;
14212
+ }
14213
+ if (typeof route.id !== "string" || route.id === "") {
14214
+ errors.push(issue("JR021", "La ruta no declara `id`.", path, { severity: "error" }));
14215
+ }
14216
+ if (route.path !== void 0 && route.path !== "") {
14217
+ const parts = typeof route.path === "string" ? route.path.split("/").filter(Boolean) : [];
14218
+ if (typeof route.path !== "string" || parts.some((segment) => !SEGMENT.test(segment))) {
14219
+ errors.push(issue("JR021", `El path "${String(route.path)}" no es v\xE1lido.`, `${path}.path`, { severity: "error", hint: "Usa segmentos con letras, d\xEDgitos, guiones o `:param`." }));
14220
+ }
14221
+ }
14222
+ const full = joinRoutePath(parentPath, route.path);
14223
+ if (isRoot && full === "") {
14224
+ errors.push(issue("JR021", "Una ruta ra\xEDz necesita `path`.", `${path}.path`, { severity: "error" }));
14225
+ }
14226
+ if (route.children !== void 0) {
14227
+ if (route.page !== void 0) {
14228
+ errors.push(issue("JR020", "Un grupo no lleva `page`: la pantalla va en sus hijos.", path, { severity: "error" }));
14229
+ }
14230
+ if (!Array.isArray(route.children)) {
14231
+ errors.push(issue("JR020", "`children` debe ser una lista.", `${path}.children`, { severity: "error" }));
14232
+ } else {
14233
+ route.children.forEach((child, index) => visit(child, `${path}.children[${index}]`, full, false));
14234
+ }
14235
+ } else {
14236
+ if (typeof route.page !== "string" || route.page === "") {
14237
+ errors.push(issue("JR020", "La ruta no declara `page`.", path, { severity: "error" }));
14238
+ }
14239
+ const key = `${full}?${JSON.stringify(Object.entries(route.query ?? {}).sort())}`;
14240
+ if (seen.has(key)) {
14241
+ errors.push(issue("JR020", `La ruta "${full || "/"}" se repite con la misma query (ya est\xE1 en ${seen.get(key)}).`, path, { severity: "error" }));
14242
+ } else {
14243
+ seen.set(key, path);
14244
+ }
14245
+ }
14246
+ const nav = route.nav;
14247
+ if (nav !== void 0 && (typeof nav !== "object" || nav === null || nav.label === void 0 || nav.label === null)) {
14248
+ errors.push(issue("JR021", "La entrada de men\xFA no declara `label`.", `${path}.nav`, { severity: "error" }));
14249
+ }
14250
+ };
14251
+ document2.routes.forEach((route, index) => visit(route, `routes[${index}]`, "", true));
14252
+ return errors;
14253
+ }
14254
+ function flattenRoutes(routes) {
14255
+ const flat = [];
14256
+ const visit = (route, parentPath, groups) => {
14257
+ const full = joinRoutePath(parentPath, route.path);
14258
+ if (route.children) {
14259
+ route.children.forEach((child) => visit(child, full, [...groups, route.id]));
14260
+ return;
14261
+ }
14262
+ if (typeof route.page !== "string") return;
14263
+ flat.push({
14264
+ id: route.id,
14265
+ segments: full === "" ? [] : full.split("/"),
14266
+ page: route.page,
14267
+ query: route.query ?? {},
14268
+ nav: route.nav,
14269
+ groups
14270
+ });
14271
+ };
14272
+ routes.forEach((route) => visit(route, "", []));
14273
+ return flat;
14274
+ }
14275
+
14276
+ // src/json-renderer/routing/match.ts
14277
+ function matchRoute(routes, segments, query = {}) {
14278
+ let best = null;
14279
+ let bestStatics = -1;
14280
+ let bestConstraints = -1;
14281
+ for (const route of routes) {
14282
+ if (route.segments.length !== segments.length) continue;
14283
+ const params = {};
14284
+ let statics = 0;
14285
+ let samePath = true;
14286
+ route.segments.forEach((expected, index) => {
14287
+ if (!samePath) return;
14288
+ if (expected.startsWith(":")) {
14289
+ params[expected.slice(1)] = segments[index];
14290
+ return;
14291
+ }
14292
+ statics += 1;
14293
+ samePath = expected === segments[index];
14294
+ });
14295
+ if (!samePath) continue;
14296
+ const constraints = Object.entries(route.query);
14297
+ if (!constraints.every(([key, value]) => query[key] === value)) continue;
14298
+ if (statics > bestStatics || statics === bestStatics && constraints.length > bestConstraints) {
14299
+ best = { route, params };
14300
+ bestStatics = statics;
14301
+ bestConstraints = constraints.length;
14302
+ }
14303
+ }
14304
+ return best;
14305
+ }
14306
+ function routeHref(route, params = {}) {
14307
+ const path = route.segments.map((segment) => segment.startsWith(":") ? params[segment.slice(1)] ?? segment : segment).join("/");
14308
+ const queryString = Object.entries(route.query).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join("&");
14309
+ return `/${path}${queryString ? `?${queryString}` : ""}`;
14310
+ }
14311
+
14312
+ // src/json-renderer/routing/navigation.ts
14313
+ function buildNavigationTree(routes) {
14314
+ const hrefs = new Map(flattenRoutes(routes).map((route) => [route.id, routeHref(route)]));
14315
+ const visit = (route, parentPath) => {
14316
+ const full = joinRoutePath(parentPath, route.path);
14317
+ if (route.children) {
14318
+ const children = route.children.flatMap((child) => visit(child, full));
14319
+ if (!route.nav) return children;
14320
+ return [toNode(route.id, route.nav, children, children.find((child) => child.href)?.href)];
14321
+ }
14322
+ if (!route.nav) return [];
14323
+ return [toNode(route.id, route.nav, void 0, hrefs.get(route.id))];
14324
+ };
14325
+ return routes.flatMap((route) => visit(route, ""));
14326
+ }
14327
+ function toNode(id, nav, children, href) {
14328
+ return {
14329
+ id,
14330
+ label: nav.label,
14331
+ icon: nav.icon,
14332
+ badge: nav.badge,
14333
+ href,
14334
+ ...children ? { children } : {}
14335
+ };
14336
+ }
14337
+ function navContainsRoute(entry, routeId) {
14338
+ return entry.id === routeId || (entry.children?.some((child) => navContainsRoute(child, routeId)) ?? false);
13439
14339
  }
13440
14340
 
13441
14341
  // src/json-renderer/validation/validate.ts
@@ -13446,6 +14346,17 @@ function validateNodes(node, path, catalog, errors, warnings) {
13446
14346
  return 0;
13447
14347
  }
13448
14348
  if (isNodePending(node)) return 1;
14349
+ if (node.type === "form") {
14350
+ const { issues: avisos } = readFormFields(node.props?.fields, [...path, "props", "fields"]);
14351
+ for (const item of avisos) (item.severity === "error" ? errors : warnings).push(item);
14352
+ return 0;
14353
+ }
14354
+ if (isSlotNode(node)) {
14355
+ if (!slotName(node)) {
14356
+ errors.push(issue("JR011", "El slot no declara `props.name`.", formatPath([...path, "props", "name"]), { severity: "error" }));
14357
+ }
14358
+ return 0;
14359
+ }
13449
14360
  const resolved = resolveNode(node, catalog, path);
13450
14361
  for (const item of resolved.issues) {
13451
14362
  (item.severity === "error" ? errors : warnings).push(item);
@@ -13628,8 +14539,143 @@ function formatVocabularyForPrompt(contract) {
13628
14539
  return lines.join("\n");
13629
14540
  }
13630
14541
 
14542
+ // src/json-renderer/stream/useSchemaStream.ts
14543
+ import { useEffect as useEffect19, useState as useState39 } from "react";
14544
+ var VACIO = {
14545
+ tree: null,
14546
+ status: "complete",
14547
+ broken: false,
14548
+ pendingNodes: 0,
14549
+ streaming: false,
14550
+ text: "",
14551
+ issues: []
14552
+ };
14553
+ var grabaciones = /* @__PURE__ */ new WeakMap();
14554
+ function esAsyncIterable(value) {
14555
+ return value !== null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
14556
+ }
14557
+ async function* desdeReadable(readable) {
14558
+ const reader = readable.getReader();
14559
+ try {
14560
+ for (; ; ) {
14561
+ const { done, value } = await reader.read();
14562
+ if (done) return;
14563
+ yield value;
14564
+ }
14565
+ } finally {
14566
+ await reader.cancel().catch(() => void 0);
14567
+ }
14568
+ }
14569
+ function mensajeDe(error) {
14570
+ return error instanceof Error ? error.message : String(error);
14571
+ }
14572
+ function crearGrabacion(source) {
14573
+ const iterador = typeof source === "string" ? null : esAsyncIterable(source) ? source[Symbol.asyncIterator]() : desdeReadable(source)[Symbol.asyncIterator]();
14574
+ return {
14575
+ texto: typeof source === "string" ? source : "",
14576
+ iterador,
14577
+ terminado: typeof source === "string",
14578
+ error: null,
14579
+ avisos: [],
14580
+ activos: 0,
14581
+ ultimoValido: null,
14582
+ cerrada: false,
14583
+ cancelada: false
14584
+ };
14585
+ }
14586
+ function estadoDe(grab, streaming) {
14587
+ const parcial = parsePartialSchema(grab.texto);
14588
+ if (!parcial.broken && parcial.tree) grab.ultimoValido = parcial.tree;
14589
+ return {
14590
+ tree: parcial.broken ? grab.ultimoValido : parcial.tree,
14591
+ status: parcial.status,
14592
+ broken: parcial.broken,
14593
+ pendingNodes: parcial.pendingNodes,
14594
+ streaming,
14595
+ text: grab.texto,
14596
+ issues: [...grab.avisos]
14597
+ };
14598
+ }
14599
+ function cerrarGrabacion(grab) {
14600
+ if (grab.cerrada || grab.cancelada) return;
14601
+ grab.cerrada = true;
14602
+ if (grab.error !== null) {
14603
+ grab.avisos.push(issue("JR080", `El stream fall\xF3: ${grab.error}. Se conserva el \xFAltimo \xE1rbol v\xE1lido.`, "", { severity: "error" }));
14604
+ return;
14605
+ }
14606
+ const parcial = parsePartialSchema(grab.texto);
14607
+ if (parcial.broken || parcial.status !== "complete") {
14608
+ grab.avisos.push(
14609
+ issue("JR080", "El stream termin\xF3 con el JSON sin cerrar. Se conserva el \xFAltimo \xE1rbol v\xE1lido.", "", {
14610
+ severity: "warning",
14611
+ hint: "Revisa que el emisor cierre todas las llaves y corchetes."
14612
+ })
14613
+ );
14614
+ }
14615
+ }
14616
+ async function consumir(grab, cancelado, onTrozo) {
14617
+ while (!grab.terminado && grab.iterador) {
14618
+ let paso;
14619
+ try {
14620
+ paso = await grab.iterador.next();
14621
+ } catch (error) {
14622
+ grab.error = mensajeDe(error);
14623
+ grab.terminado = true;
14624
+ break;
14625
+ }
14626
+ if (paso.done) {
14627
+ grab.terminado = true;
14628
+ break;
14629
+ }
14630
+ grab.texto += String(paso.value);
14631
+ if (!cancelado()) onTrozo();
14632
+ if (cancelado()) return;
14633
+ }
14634
+ if (grab.terminado) cerrarGrabacion(grab);
14635
+ }
14636
+ function useSchemaStream(source) {
14637
+ const [estado, setEstado] = useState39(VACIO);
14638
+ useEffect19(() => {
14639
+ if (source === null || source === void 0) {
14640
+ setEstado(VACIO);
14641
+ return;
14642
+ }
14643
+ let registro;
14644
+ if (typeof source === "string") {
14645
+ registro = crearGrabacion(source);
14646
+ } else {
14647
+ const existente = grabaciones.get(source);
14648
+ registro = existente ?? crearGrabacion(source);
14649
+ if (!existente) grabaciones.set(source, registro);
14650
+ }
14651
+ registro.activos += 1;
14652
+ let cancelado = false;
14653
+ const proceso = consumir(
14654
+ registro,
14655
+ () => cancelado,
14656
+ () => setEstado(estadoDe(registro, true))
14657
+ );
14658
+ setEstado(estadoDe(registro, !registro.terminado));
14659
+ void proceso.then(() => {
14660
+ if (!cancelado) setEstado(estadoDe(registro, false));
14661
+ });
14662
+ return () => {
14663
+ cancelado = true;
14664
+ registro.activos -= 1;
14665
+ setTimeout(() => {
14666
+ if (registro.activos === 0 && !registro.terminado && registro.iterador) {
14667
+ registro.terminado = true;
14668
+ registro.cancelada = true;
14669
+ void registro.iterador.return?.(void 0);
14670
+ }
14671
+ }, 0);
14672
+ };
14673
+ }, [source]);
14674
+ return estado;
14675
+ }
14676
+
13631
14677
  // src/components/organisms/dropfile/dropfile.tsx
13632
- import { useState as useState37, useEffect as useEffect19 } from "react";
14678
+ import { useState as useState40, useEffect as useEffect20 } from "react";
13633
14679
  import { useDropzone } from "react-dropzone";
13634
14680
  import clsx54 from "clsx";
13635
14681
 
@@ -13659,11 +14705,12 @@ var UploadStatus = /* @__PURE__ */ ((UploadStatus2) => {
13659
14705
  })(UploadStatus || {});
13660
14706
 
13661
14707
  // src/components/organisms/dropfile/dropfile.tsx
13662
- import { Fragment as Fragment14, jsx as jsx76, jsxs as jsxs54 } from "react/jsx-runtime";
14708
+ import { Fragment as Fragment14, jsx as jsx77, jsxs as jsxs55 } from "react/jsx-runtime";
13663
14709
  var ITDropfile = ({
13664
14710
  onFileSelect,
13665
14711
  onCancel,
13666
14712
  onSubmit,
14713
+ autoUpload = false,
13667
14714
  contentClassName,
13668
14715
  containerClassName,
13669
14716
  acceptedFileTypes = ["application/pdf" /* PDF */, "application/vnd.ms-excel" /* XLS */, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" /* XLSX */, "image/jpg" /* JPG */, "image/png" /* PNG */, "image/jpeg" /* JPEG */],
@@ -13676,15 +14723,15 @@ var ITDropfile = ({
13676
14723
  modalTitle
13677
14724
  }) => {
13678
14725
  const { t } = useITTranslation();
13679
- const [isModalOpen, setIsModalOpen] = useState37(false);
13680
- const [selectedFile, setSelectedFile] = useState37(null);
13681
- const [fileType, setFileType] = useState37(null);
13682
- const [imagePreview, setImagePreview] = useState37(initialPreviewUrl || null);
13683
- const [isConfirmed, setIsConfirmed] = useState37(false);
13684
- const [internalUploadStatus, setInternalUploadStatus] = useState37(
14726
+ const [isModalOpen, setIsModalOpen] = useState40(false);
14727
+ const [selectedFile, setSelectedFile] = useState40(null);
14728
+ const [fileType, setFileType] = useState40(null);
14729
+ const [imagePreview, setImagePreview] = useState40(initialPreviewUrl || null);
14730
+ const [isConfirmed, setIsConfirmed] = useState40(false);
14731
+ const [internalUploadStatus, setInternalUploadStatus] = useState40(
13685
14732
  initialPreviewUrl ? "subido" /* UPLOADED */ : "pendiente" /* PENDING */
13686
14733
  );
13687
- useEffect19(() => {
14734
+ useEffect20(() => {
13688
14735
  if (initialPreviewUrl && !selectedFile) {
13689
14736
  setImagePreview(initialPreviewUrl);
13690
14737
  if (externalStatus === void 0) setInternalUploadStatus("subido" /* UPLOADED */);
@@ -13799,11 +14846,23 @@ var ITDropfile = ({
13799
14846
  }
13800
14847
  };
13801
14848
  const { label, color, dotColor } = config2[status];
13802
- return /* @__PURE__ */ jsxs54("div", { className: `inline-flex items-center gap-2 px-2.5 py-1 rounded-full border ${color}`, children: [
13803
- /* @__PURE__ */ jsx76("div", { className: `w-2 h-2 rounded-full ${dotColor}` }),
13804
- /* @__PURE__ */ jsx76(ITText, { as: "span", className: "text-xs font-medium flex items-center gap-1.5", children: label })
14849
+ return /* @__PURE__ */ jsxs55("div", { className: `inline-flex items-center gap-2 px-2.5 py-1 rounded-full border ${color}`, children: [
14850
+ /* @__PURE__ */ jsx77("div", { className: `w-2 h-2 rounded-full ${dotColor}` }),
14851
+ /* @__PURE__ */ jsx77(ITText, { as: "span", className: "text-xs font-medium flex items-center gap-1.5", children: label })
13805
14852
  ] });
13806
14853
  };
14854
+ const runAutoUpload = async (file) => {
14855
+ setIsConfirmed(true);
14856
+ setUploadStatus("subiendo" /* UPLOADING */);
14857
+ try {
14858
+ onFileSelect(file);
14859
+ await onSubmit?.(file);
14860
+ setUploadStatus("subido" /* UPLOADED */);
14861
+ } catch (error) {
14862
+ setUploadStatus("error" /* ERROR */);
14863
+ console.error("Error al subir archivo:", error);
14864
+ }
14865
+ };
13807
14866
  const onDrop = (acceptedFiles) => {
13808
14867
  const file = acceptedFiles[0];
13809
14868
  if (file) {
@@ -13819,6 +14878,7 @@ var ITDropfile = ({
13819
14878
  const previewUrl = URL.createObjectURL(file);
13820
14879
  setImagePreview(previewUrl);
13821
14880
  }
14881
+ if (autoUpload) void runAutoUpload(file);
13822
14882
  } else {
13823
14883
  alert(t("dropfile.fileTypeNotAllowed"));
13824
14884
  setSelectedFile(null);
@@ -13833,12 +14893,12 @@ var ITDropfile = ({
13833
14893
  accept: getAcceptedFileTypes(),
13834
14894
  maxFiles: 1
13835
14895
  });
13836
- useEffect19(() => {
14896
+ useEffect20(() => {
13837
14897
  const renderPDF = async () => {
13838
14898
  };
13839
14899
  renderPDF();
13840
14900
  }, [selectedFile, fileType]);
13841
- useEffect19(() => {
14901
+ useEffect20(() => {
13842
14902
  return () => {
13843
14903
  if (imagePreview) {
13844
14904
  URL.revokeObjectURL(imagePreview);
@@ -13875,7 +14935,7 @@ var ITDropfile = ({
13875
14935
  const handleDelete = () => {
13876
14936
  handleCancel();
13877
14937
  };
13878
- useEffect19(() => {
14938
+ useEffect20(() => {
13879
14939
  if (view === "button" && isConfirmed && uploadStatus === "subido" /* UPLOADED */) {
13880
14940
  const timeout = setTimeout(() => {
13881
14941
  setIsModalOpen(false);
@@ -13892,21 +14952,21 @@ var ITDropfile = ({
13892
14952
  return () => clearTimeout(timeout);
13893
14953
  }
13894
14954
  }, [view, isConfirmed, uploadStatus, externalStatus, onStatusChange]);
13895
- const headerRow = /* @__PURE__ */ jsxs54("div", { className: "flex items-center justify-between mb-2", children: [
13896
- /* @__PURE__ */ jsxs54("label", { className: "block text-sm font-semibold text-secondary-700", children: [
13897
- /* @__PURE__ */ jsxs54(ITText, { as: "span", children: [
14955
+ const headerRow = /* @__PURE__ */ jsxs55("div", { className: "flex items-center justify-between mb-2", children: [
14956
+ /* @__PURE__ */ jsxs55("label", { className: "block text-sm font-semibold text-secondary-700", children: [
14957
+ /* @__PURE__ */ jsxs55(ITText, { as: "span", children: [
13898
14958
  t("dropfile.upload"),
13899
14959
  " "
13900
14960
  ] }),
13901
- /* @__PURE__ */ jsxs54(ITText, { as: "span", className: "text-secondary-400 font-normal text-xs", children: [
14961
+ /* @__PURE__ */ jsxs55(ITText, { as: "span", className: "text-secondary-400 font-normal text-xs", children: [
13902
14962
  "(",
13903
14963
  getFileExtensions(),
13904
14964
  ")"
13905
14965
  ] })
13906
14966
  ] }),
13907
- showStatusBadge && selectedFile && /* @__PURE__ */ jsx76(StatusBadge, { status: uploadStatus })
14967
+ showStatusBadge && selectedFile && /* @__PURE__ */ jsx77(StatusBadge, { status: uploadStatus })
13908
14968
  ] });
13909
- const dropZoneOrPreview = /* @__PURE__ */ jsx76(Fragment14, { children: !selectedFile && !imagePreview ? /* @__PURE__ */ jsxs54(
14969
+ const dropZoneOrPreview = /* @__PURE__ */ jsx77(Fragment14, { children: !selectedFile && !imagePreview ? /* @__PURE__ */ jsxs55(
13910
14970
  "div",
13911
14971
  {
13912
14972
  ...getRootProps(),
@@ -13916,41 +14976,41 @@ var ITDropfile = ({
13916
14976
  ${isDragActive ? "border-primary-500 bg-primary-50 scale-[1.01]" : "border-secondary-300 bg-white hover:border-primary-400 hover:bg-secondary-50"}
13917
14977
  `,
13918
14978
  children: [
13919
- /* @__PURE__ */ jsx76("input", { ...getInputProps() }),
13920
- /* @__PURE__ */ jsx76("div", { className: `mb-3 p-3 rounded-full transition-colors duration-300 ${isDragActive ? "bg-primary-100" : "bg-secondary-100 group-hover:bg-primary-50"}`, children: /* @__PURE__ */ jsx76(
14979
+ /* @__PURE__ */ jsx77("input", { ...getInputProps() }),
14980
+ /* @__PURE__ */ jsx77("div", { className: `mb-3 p-3 rounded-full transition-colors duration-300 ${isDragActive ? "bg-primary-100" : "bg-secondary-100 group-hover:bg-primary-50"}`, children: /* @__PURE__ */ jsx77(
13921
14981
  "svg",
13922
14982
  {
13923
14983
  className: `w-6 h-6 transition-colors duration-300 ${isDragActive ? "text-primary-600" : "text-secondary-400 group-hover:text-primary-500"}`,
13924
14984
  fill: "none",
13925
14985
  viewBox: "0 0 24 24",
13926
14986
  stroke: "currentColor",
13927
- children: /* @__PURE__ */ jsx76("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" })
14987
+ children: /* @__PURE__ */ jsx77("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" })
13928
14988
  }
13929
14989
  ) }),
13930
- /* @__PURE__ */ jsx76("div", { className: "text-center space-y-1", children: /* @__PURE__ */ jsx76(ITText, { as: "p", className: `text-sm font-medium transition-colors duration-300 ${isDragActive ? "text-primary-700" : "text-secondary-700"}`, children: isDragActive ? t("dropfile.dropHere") : t("dropfile.clickOrDrag") }) })
14990
+ /* @__PURE__ */ jsx77("div", { className: "text-center space-y-1", children: /* @__PURE__ */ jsx77(ITText, { as: "p", className: `text-sm font-medium transition-colors duration-300 ${isDragActive ? "text-primary-700" : "text-secondary-700"}`, children: isDragActive ? t("dropfile.dropHere") : t("dropfile.clickOrDrag") }) })
13931
14991
  ]
13932
14992
  }
13933
- ) : /* @__PURE__ */ jsxs54("div", { className: "w-full bg-white border border-secondary-200 rounded-xl shadow-sm overflow-hidden animate-fade-in", children: [
13934
- /* @__PURE__ */ jsx76("div", { className: "flex items-center justify-between p-3 bg-secondary-50 border-b border-secondary-100", children: /* @__PURE__ */ jsxs54("div", { className: "flex items-center gap-3 overflow-hidden", children: [
13935
- /* @__PURE__ */ jsx76("div", { className: "flex-shrink-0 w-8 h-8 rounded-lg bg-primary-100 flex items-center justify-center text-primary-600", children: selectedFile && fileType?.startsWith("image/") || !selectedFile && imagePreview ? /* @__PURE__ */ jsx76("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx76("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) }) : /* @__PURE__ */ jsx76("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx76("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" }) }) }),
13936
- /* @__PURE__ */ jsxs54("div", { className: "min-w-0", children: [
13937
- /* @__PURE__ */ jsx76(ITText, { as: "p", className: "text-xs font-medium text-secondary-900 truncate", title: selectedFile?.name || t("dropfile.imageLoaded"), children: selectedFile?.name || t("dropfile.imageLoaded") }),
13938
- /* @__PURE__ */ jsx76(ITText, { as: "p", className: "text-[10px] text-secondary-500", children: selectedFile ? (selectedFile.size / 1024 / 1024).toFixed(2) + " MB" : "" })
14993
+ ) : /* @__PURE__ */ jsxs55("div", { className: "w-full bg-white border border-secondary-200 rounded-xl shadow-sm overflow-hidden animate-fade-in", children: [
14994
+ /* @__PURE__ */ jsx77("div", { className: "flex items-center justify-between p-3 bg-secondary-50 border-b border-secondary-100", children: /* @__PURE__ */ jsxs55("div", { className: "flex items-center gap-3 overflow-hidden", children: [
14995
+ /* @__PURE__ */ jsx77("div", { className: "flex-shrink-0 w-8 h-8 rounded-lg bg-primary-100 flex items-center justify-center text-primary-600", children: selectedFile && fileType?.startsWith("image/") || !selectedFile && imagePreview ? /* @__PURE__ */ jsx77("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx77("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) }) : /* @__PURE__ */ jsx77("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx77("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" }) }) }),
14996
+ /* @__PURE__ */ jsxs55("div", { className: "min-w-0", children: [
14997
+ /* @__PURE__ */ jsx77(ITText, { as: "p", className: "text-xs font-medium text-secondary-900 truncate", title: selectedFile?.name || t("dropfile.imageLoaded"), children: selectedFile?.name || t("dropfile.imageLoaded") }),
14998
+ /* @__PURE__ */ jsx77(ITText, { as: "p", className: "text-[10px] text-secondary-500", children: selectedFile ? (selectedFile.size / 1024 / 1024).toFixed(2) + " MB" : "" })
13939
14999
  ] })
13940
15000
  ] }) }),
13941
- /* @__PURE__ */ jsx76("div", { className: clsx54("relative bg-secondary-100 flex items-center justify-center", !contentClassName ? "max-h-[200px] min-h-[100px] overflow-auto" : contentClassName), children: selectedFile && fileType?.startsWith("image/") || !selectedFile && imagePreview ? /* @__PURE__ */ jsx76(
15001
+ /* @__PURE__ */ jsx77("div", { className: clsx54("relative bg-secondary-100 flex items-center justify-center", !contentClassName ? "max-h-[200px] min-h-[100px] overflow-auto" : contentClassName), children: selectedFile && fileType?.startsWith("image/") || !selectedFile && imagePreview ? /* @__PURE__ */ jsx77(
13942
15002
  "img",
13943
15003
  {
13944
15004
  src: imagePreview,
13945
15005
  alt: t("dropfile.previewAlt"),
13946
15006
  className: "w-full h-full object-contain max-h-[200px]"
13947
15007
  }
13948
- ) : /* @__PURE__ */ jsxs54("div", { className: "py-8 flex flex-col items-center text-secondary-400", children: [
13949
- /* @__PURE__ */ jsx76("svg", { className: "w-10 h-10 mb-2 opacity-50", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx76("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" }) }),
13950
- /* @__PURE__ */ jsx76(ITText, { as: "span", className: "text-xs", children: t("dropfile.noPreview") })
15008
+ ) : /* @__PURE__ */ jsxs55("div", { className: "py-8 flex flex-col items-center text-secondary-400", children: [
15009
+ /* @__PURE__ */ jsx77("svg", { className: "w-10 h-10 mb-2 opacity-50", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx77("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" }) }),
15010
+ /* @__PURE__ */ jsx77(ITText, { as: "span", className: "text-xs", children: t("dropfile.noPreview") })
13951
15011
  ] }) }),
13952
- /* @__PURE__ */ jsx76("div", { className: "px-3 py-2 bg-white border-t border-secondary-100 flex justify-end gap-2", children: !isConfirmed ? /* @__PURE__ */ jsxs54(Fragment14, { children: [
13953
- /* @__PURE__ */ jsx76(
15012
+ /* @__PURE__ */ jsx77("div", { className: "px-3 py-2 bg-white border-t border-secondary-100 flex justify-end gap-2", children: !isConfirmed ? /* @__PURE__ */ jsxs55(Fragment14, { children: [
15013
+ /* @__PURE__ */ jsx77(
13954
15014
  ITButton,
13955
15015
  {
13956
15016
  type: "button",
@@ -13958,10 +15018,10 @@ var ITDropfile = ({
13958
15018
  color: "secondary",
13959
15019
  size: "sm",
13960
15020
  onClick: handleCancel,
13961
- children: /* @__PURE__ */ jsx76(ITText, { children: t("common.cancel") })
15021
+ children: /* @__PURE__ */ jsx77(ITText, { children: t("common.cancel") })
13962
15022
  }
13963
15023
  ),
13964
- /* @__PURE__ */ jsx76(
15024
+ /* @__PURE__ */ jsx77(
13965
15025
  ITButton,
13966
15026
  {
13967
15027
  type: "button",
@@ -13969,13 +15029,13 @@ var ITDropfile = ({
13969
15029
  color: "primary",
13970
15030
  size: "sm",
13971
15031
  onClick: handleConfirm,
13972
- children: /* @__PURE__ */ jsxs54("div", { className: "flex items-center gap-2", children: [
13973
- /* @__PURE__ */ jsx76(ITText, { children: t("common.confirm") }),
13974
- /* @__PURE__ */ jsx76("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx76("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) })
15032
+ children: /* @__PURE__ */ jsxs55("div", { className: "flex items-center gap-2", children: [
15033
+ /* @__PURE__ */ jsx77(ITText, { children: t("common.confirm") }),
15034
+ /* @__PURE__ */ jsx77("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx77("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) })
13975
15035
  ] })
13976
15036
  }
13977
15037
  )
13978
- ] }) : /* @__PURE__ */ jsxs54(
15038
+ ] }) : /* @__PURE__ */ jsxs55(
13979
15039
  ITButton,
13980
15040
  {
13981
15041
  type: "button",
@@ -13984,12 +15044,12 @@ var ITDropfile = ({
13984
15044
  size: "sm",
13985
15045
  onClick: handleDelete,
13986
15046
  children: [
13987
- /* @__PURE__ */ jsx76("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx76("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }),
13988
- /* @__PURE__ */ jsx76(ITText, { children: t("common.delete") })
15047
+ /* @__PURE__ */ jsx77("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx77("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }),
15048
+ /* @__PURE__ */ jsx77(ITText, { children: t("common.delete") })
13989
15049
  ]
13990
15050
  }
13991
15051
  ) }),
13992
- uploadStatus === "subiendo" /* UPLOADING */ && /* @__PURE__ */ jsx76("div", { className: "px-4 pb-2", children: /* @__PURE__ */ jsx76("div", { className: "w-full bg-secondary-200 rounded-full h-1.5", children: /* @__PURE__ */ jsx76(
15052
+ uploadStatus === "subiendo" /* UPLOADING */ && /* @__PURE__ */ jsx77("div", { className: "px-4 pb-2", children: /* @__PURE__ */ jsx77("div", { className: "w-full bg-secondary-200 rounded-full h-1.5", children: /* @__PURE__ */ jsx77(
13993
15053
  "div",
13994
15054
  {
13995
15055
  className: "bg-primary-600 h-1.5 rounded-full transition-all duration-1000 ease-out",
@@ -14002,8 +15062,8 @@ var ITDropfile = ({
14002
15062
  ] }) });
14003
15063
  if (view === "button") {
14004
15064
  const hasFile = Boolean(selectedFile || imagePreview);
14005
- return /* @__PURE__ */ jsxs54("div", { className: clsx54("inline-block", containerClassName), children: [
14006
- /* @__PURE__ */ jsx76(
15065
+ return /* @__PURE__ */ jsxs55("div", { className: clsx54("inline-block", containerClassName), children: [
15066
+ /* @__PURE__ */ jsx77(
14007
15067
  ITButton,
14008
15068
  {
14009
15069
  type: "button",
@@ -14011,20 +15071,20 @@ var ITDropfile = ({
14011
15071
  color: hasFile ? "primary" : "secondary",
14012
15072
  size: "sm",
14013
15073
  onClick: () => setIsModalOpen(true),
14014
- children: /* @__PURE__ */ jsxs54("div", { className: "flex items-center gap-2 max-w-[220px]", children: [
14015
- /* @__PURE__ */ jsx76("svg", { className: "w-4 h-4 flex-shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx76("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" }) }),
14016
- /* @__PURE__ */ jsx76(ITText, { className: "truncate", children: selectedFile?.name || (hasFile ? t("dropfile.fileLoaded") : buttonLabel ?? t("dropfile.upload")) }),
14017
- showStatusBadge && hasFile && /* @__PURE__ */ jsx76(StatusBadge, { status: uploadStatus })
15074
+ children: /* @__PURE__ */ jsxs55("div", { className: "flex items-center gap-2 max-w-[220px]", children: [
15075
+ /* @__PURE__ */ jsx77("svg", { className: "w-4 h-4 flex-shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx77("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" }) }),
15076
+ /* @__PURE__ */ jsx77(ITText, { className: "truncate", children: selectedFile?.name || (hasFile ? t("dropfile.fileLoaded") : buttonLabel ?? t("dropfile.upload")) }),
15077
+ showStatusBadge && hasFile && /* @__PURE__ */ jsx77(StatusBadge, { status: uploadStatus })
14018
15078
  ] })
14019
15079
  }
14020
15080
  ),
14021
- /* @__PURE__ */ jsx76(ITDialog, { isOpen: isModalOpen, onClose: () => setIsModalOpen(false), title: modalTitle ?? buttonLabel ?? t("dropfile.upload"), children: /* @__PURE__ */ jsxs54("div", { className: "w-full transition-all duration-300", children: [
15081
+ /* @__PURE__ */ jsx77(ITDialog, { isOpen: isModalOpen, onClose: () => setIsModalOpen(false), title: modalTitle ?? buttonLabel ?? t("dropfile.upload"), children: /* @__PURE__ */ jsxs55("div", { className: "w-full transition-all duration-300", children: [
14022
15082
  headerRow,
14023
15083
  dropZoneOrPreview
14024
15084
  ] }) })
14025
15085
  ] });
14026
15086
  }
14027
- return /* @__PURE__ */ jsxs54("div", { className: clsx54("w-full transition-all duration-300", containerClassName), children: [
15087
+ return /* @__PURE__ */ jsxs55("div", { className: clsx54("w-full transition-all duration-300", containerClassName), children: [
14028
15088
  headerRow,
14029
15089
  dropZoneOrPreview
14030
15090
  ] });
@@ -14032,13 +15092,13 @@ var ITDropfile = ({
14032
15092
  var dropfile_default = ITDropfile;
14033
15093
 
14034
15094
  // src/components/templates/layout/layout.tsx
14035
- import { useState as useState39 } from "react";
15095
+ import { useState as useState42 } from "react";
14036
15096
  import clsx55 from "clsx";
14037
15097
 
14038
15098
  // src/components/organisms/topbar/topbar.tsx
14039
15099
  import { FaUserCircle as FaUserCircle2, FaBars } from "react-icons/fa";
14040
- import { useRef as useRef24, useState as useState38 } from "react";
14041
- import { jsx as jsx77, jsxs as jsxs55 } from "react/jsx-runtime";
15100
+ import { useRef as useRef24, useState as useState41 } from "react";
15101
+ import { jsx as jsx78, jsxs as jsxs56 } from "react/jsx-runtime";
14042
15102
  function ITTopBar({
14043
15103
  logo,
14044
15104
  logoText,
@@ -14052,41 +15112,46 @@ function ITTopBar({
14052
15112
  hideBrandOnDesktop = false,
14053
15113
  showDesktopMenuButton = false
14054
15114
  }) {
14055
- const flat = useITFlatAppearance();
15115
+ const appearance = useITAppearance();
15116
+ const bento = appearance === "bento";
15117
+ const flat = appearance === "flat" || bento;
14056
15118
  const { t } = useITTranslation();
14057
15119
  const initials = (userMenu?.userName ?? "").trim().split(/\s+/).slice(0, 2).map((word) => word.charAt(0).toUpperCase()).join("");
14058
- const [isUserMenuOpen, setIsUserMenuOpen] = useState38(false);
15120
+ const userRestBg = bento ? "var(--it-bento-control-bg, #f1f5f9)" : "transparent";
15121
+ const userHoverBg = bento ? "var(--it-bento-control-bg-hover, #e2e8f0)" : "var(--it-topbar-user-hover, #f1f5f9)";
15122
+ const [isUserMenuOpen, setIsUserMenuOpen] = useState41(false);
14059
15123
  const userMenuRef = useRef24(null);
14060
15124
  useClickOutside_default(userMenuRef, () => setIsUserMenuOpen(false));
14061
- return /* @__PURE__ */ jsx77(
15125
+ return /* @__PURE__ */ jsx78(
14062
15126
  "header",
14063
15127
  {
14064
15128
  className: `sticky top-0 z-40 transition-all duration-300 ${flat ? "" : "backdrop-blur-md"}`,
14065
15129
  style: {
14066
- backgroundColor: "var(--it-topbar-bg, rgba(255, 255, 255, 0.9))",
14067
- borderBottom: "1px solid var(--it-topbar-border, rgba(15, 23, 42, 0.06))",
15130
+ backgroundColor: bento ? "var(--it-layout-bg, #f4f4f6)" : "var(--it-topbar-bg, rgba(255, 255, 255, 0.9))",
15131
+ borderBottom: bento ? "none" : "1px solid var(--it-topbar-border, rgba(15, 23, 42, 0.06))",
14068
15132
  boxShadow: flat ? "none" : "var(--shadow-xs)"
14069
15133
  },
14070
- children: /* @__PURE__ */ jsxs55("div", { className: `flex items-center justify-between px-6 lg:px-8 ${flat ? "h-[64px]" : "h-[72px]"}`, children: [
14071
- /* @__PURE__ */ jsxs55("div", { className: "flex items-center gap-5", children: [
14072
- showMobileMenuButton && /* @__PURE__ */ jsx77(
15134
+ children: /* @__PURE__ */ jsxs56("div", { className: `flex items-center justify-between px-6 lg:px-8 ${flat ? "h-[64px]" : "h-[72px]"}`, children: [
15135
+ /* @__PURE__ */ jsxs56("div", { className: "flex items-center gap-5", children: [
15136
+ showMobileMenuButton && /* @__PURE__ */ jsx78(
14073
15137
  "button",
14074
15138
  {
14075
15139
  type: "button",
14076
15140
  "aria-label": t("common.menu"),
14077
- className: `${showDesktopMenuButton ? "" : "lg:hidden"} p-2.5 -ml-2.5 rounded-xl transition-colors duration-200`,
15141
+ className: `${showDesktopMenuButton ? "" : "lg:hidden"} ${bento ? "w-10 h-10 flex items-center justify-center rounded-full" : "p-2.5 -ml-2.5 rounded-xl"} transition-colors duration-200`,
14078
15142
  style: {
14079
- color: "var(--it-topbar-icon, #64748b)"
15143
+ color: bento ? "var(--it-bento-control-text, #475569)" : "var(--it-topbar-icon, #64748b)",
15144
+ backgroundColor: bento ? "var(--it-bento-control-bg, #f1f5f9)" : void 0
14080
15145
  },
14081
- onMouseEnter: (e) => e.currentTarget.style.backgroundColor = "var(--it-topbar-user-hover, #f1f5f9)",
14082
- onMouseLeave: (e) => e.currentTarget.style.backgroundColor = "transparent",
15146
+ onMouseEnter: (e) => e.currentTarget.style.backgroundColor = bento ? "var(--it-bento-control-bg-hover, #e2e8f0)" : "var(--it-topbar-user-hover, #f1f5f9)",
15147
+ onMouseLeave: (e) => e.currentTarget.style.backgroundColor = bento ? "var(--it-bento-control-bg, #f1f5f9)" : "transparent",
14083
15148
  onClick: onToggleMobileMenu,
14084
- children: /* @__PURE__ */ jsx77(FaBars, { className: "w-[1.125rem] h-[1.125rem]" })
15149
+ children: /* @__PURE__ */ jsx78(FaBars, { className: "w-[1.125rem] h-[1.125rem]" })
14085
15150
  }
14086
15151
  ),
14087
- /* @__PURE__ */ jsxs55("div", { className: `items-center gap-3 ${hideBrandOnDesktop ? "flex lg:hidden" : "flex"}`, children: [
14088
- logo && /* @__PURE__ */ jsx77("div", { className: "flex-shrink-0 drop-shadow-sm", children: logo }),
14089
- logoText && /* @__PURE__ */ jsx77(
15152
+ /* @__PURE__ */ jsxs56("div", { className: `items-center gap-3 ${hideBrandOnDesktop ? "flex lg:hidden" : "flex"}`, children: [
15153
+ logo && /* @__PURE__ */ jsx78("div", { className: "flex-shrink-0 drop-shadow-sm", children: logo }),
15154
+ logoText && /* @__PURE__ */ jsx78(
14090
15155
  ITText,
14091
15156
  {
14092
15157
  as: "span",
@@ -14096,57 +15161,70 @@ function ITTopBar({
14096
15161
  }
14097
15162
  )
14098
15163
  ] }),
14099
- navItems && navItems.length > 0 && /* @__PURE__ */ jsx77("nav", { className: "hidden md:flex ml-8 space-x-1 border-l pl-8", style: { borderColor: "var(--it-topbar-border, rgba(15, 23, 42, 0.06))" }, children: navItems.map((item) => /* @__PURE__ */ jsx77(
14100
- "button",
15164
+ navItems && navItems.length > 0 && /* @__PURE__ */ jsx78(
15165
+ "nav",
14101
15166
  {
14102
- onClick: () => onNavItemClick?.(item.id),
14103
- className: "px-4 py-2 rounded-lg font-medium text-[0.9rem] transition-all duration-200 ease-[cubic-bezier(0.2,0,0,1)]",
14104
- style: { color: "var(--it-topbar-text, #475569)" },
14105
- onMouseEnter: (e) => {
14106
- e.currentTarget.style.color = "var(--it-topbar-text, #0f172a)";
14107
- e.currentTarget.style.backgroundColor = "var(--it-topbar-user-hover, #f1f5f9)";
14108
- },
14109
- onMouseLeave: (e) => {
14110
- e.currentTarget.style.color = "var(--it-topbar-text, #475569)";
14111
- e.currentTarget.style.backgroundColor = "transparent";
14112
- },
14113
- children: /* @__PURE__ */ jsxs55("div", { className: "flex items-center gap-2", children: [
14114
- item.icon && /* @__PURE__ */ jsx77("span", { className: "opacity-70", children: item.icon }),
14115
- /* @__PURE__ */ jsx77(ITText, { as: "span", children: item.label })
14116
- ] })
14117
- },
14118
- item.id
14119
- )) })
15167
+ className: bento ? "hidden md:flex ml-4 gap-2" : "hidden md:flex ml-8 space-x-1 border-l pl-8",
15168
+ style: bento ? void 0 : { borderColor: "var(--it-topbar-border, rgba(15, 23, 42, 0.06))" },
15169
+ children: navItems.map((item) => {
15170
+ const restBg = bento ? item.isActive ? "var(--it-bento-ink-bg, #0f172a)" : "var(--it-bento-control-bg, #f1f5f9)" : item.isActive ? "var(--it-topbar-user-hover, #f1f5f9)" : "transparent";
15171
+ const restColor = bento ? item.isActive ? "var(--it-bento-ink-text, #ffffff)" : "var(--it-bento-control-text, #475569)" : "var(--it-topbar-text, #475569)";
15172
+ return /* @__PURE__ */ jsx78(
15173
+ "button",
15174
+ {
15175
+ onClick: () => onNavItemClick?.(item.id),
15176
+ "aria-current": item.isActive ? "page" : void 0,
15177
+ className: `px-4 py-2 ${bento ? "rounded-full" : "rounded-lg"} font-medium text-[0.9rem] transition-all duration-200 ease-[cubic-bezier(0.2,0,0,1)]`,
15178
+ style: { color: restColor, backgroundColor: restBg },
15179
+ onMouseEnter: (e) => {
15180
+ if (bento && item.isActive) return;
15181
+ e.currentTarget.style.color = bento ? "var(--it-bento-control-text, #0f172a)" : "var(--it-topbar-text, #0f172a)";
15182
+ e.currentTarget.style.backgroundColor = bento ? "var(--it-bento-control-bg-hover, #e2e8f0)" : "var(--it-topbar-user-hover, #f1f5f9)";
15183
+ },
15184
+ onMouseLeave: (e) => {
15185
+ e.currentTarget.style.color = restColor;
15186
+ e.currentTarget.style.backgroundColor = restBg;
15187
+ },
15188
+ children: /* @__PURE__ */ jsxs56("div", { className: "flex items-center gap-2", children: [
15189
+ item.icon && /* @__PURE__ */ jsx78("span", { className: "opacity-70", children: item.icon }),
15190
+ /* @__PURE__ */ jsx78(ITText, { as: "span", children: item.label })
15191
+ ] })
15192
+ },
15193
+ item.id
15194
+ );
15195
+ })
15196
+ }
15197
+ )
14120
15198
  ] }),
14121
- centerContent && /* @__PURE__ */ jsx77("div", { className: `hidden lg:flex flex-1 min-w-0 items-center ${hideBrandOnDesktop ? "justify-start pr-4" : "justify-center px-4"}`, children: /* @__PURE__ */ jsx77("div", { className: "w-full max-w-[420px]", children: centerContent }) }),
14122
- (children || userMenu) && /* @__PURE__ */ jsxs55("div", { className: "flex items-center gap-2", children: [
15199
+ centerContent && /* @__PURE__ */ jsx78("div", { className: `hidden lg:flex flex-1 min-w-0 items-center ${hideBrandOnDesktop ? "justify-start pr-4" : "justify-center px-4"}`, children: /* @__PURE__ */ jsx78("div", { className: "w-full max-w-[420px]", children: centerContent }) }),
15200
+ (children || userMenu) && /* @__PURE__ */ jsxs56("div", { className: "flex items-center gap-2", children: [
14123
15201
  children,
14124
- userMenu && /* @__PURE__ */ jsxs55("div", { className: "relative", children: [
14125
- /* @__PURE__ */ jsxs55(
15202
+ userMenu && /* @__PURE__ */ jsxs56("div", { className: "relative", children: [
15203
+ /* @__PURE__ */ jsxs56(
14126
15204
  "button",
14127
15205
  {
14128
15206
  type: "button",
14129
- className: `flex items-center gap-3 rounded-full py-1.5 transition-all duration-200 ease-[cubic-bezier(0.2,0,0,1)] border border-transparent hover:border-secondary-200 ${flat ? "flex-row-reverse pl-4 pr-2" : "pl-2 pr-4"}`,
15207
+ className: `flex items-center gap-3 rounded-full py-1.5 transition-all duration-200 ease-[cubic-bezier(0.2,0,0,1)] border border-transparent ${bento ? "" : "hover:border-secondary-200"} ${flat ? "flex-row-reverse pl-4 pr-2" : "pl-2 pr-4"}`,
14130
15208
  style: {
14131
- backgroundColor: isUserMenuOpen ? "var(--it-topbar-user-hover, #f1f5f9)" : "transparent"
15209
+ backgroundColor: isUserMenuOpen ? userHoverBg : userRestBg
14132
15210
  },
14133
15211
  onMouseEnter: (e) => {
14134
- if (!isUserMenuOpen) e.currentTarget.style.backgroundColor = "var(--it-topbar-user-hover, #f1f5f9)";
15212
+ if (!isUserMenuOpen) e.currentTarget.style.backgroundColor = userHoverBg;
14135
15213
  },
14136
15214
  onMouseLeave: (e) => {
14137
- if (!isUserMenuOpen) e.currentTarget.style.backgroundColor = "transparent";
15215
+ if (!isUserMenuOpen) e.currentTarget.style.backgroundColor = userRestBg;
14138
15216
  },
14139
15217
  onClick: () => setIsUserMenuOpen(!isUserMenuOpen),
14140
15218
  children: [
14141
- /* @__PURE__ */ jsxs55("div", { className: "relative", children: [
14142
- userMenu.userImage ? /* @__PURE__ */ jsx77(
15219
+ /* @__PURE__ */ jsxs56("div", { className: "relative", children: [
15220
+ userMenu.userImage ? /* @__PURE__ */ jsx78(
14143
15221
  "img",
14144
15222
  {
14145
15223
  className: "w-9 h-9 rounded-full object-cover ring-2 ring-white shadow-sm",
14146
15224
  src: userMenu.userImage,
14147
15225
  alt: t("common.userAvatar")
14148
15226
  }
14149
- ) : flat && initials ? /* @__PURE__ */ jsx77(
15227
+ ) : flat && initials ? /* @__PURE__ */ jsx78(
14150
15228
  "div",
14151
15229
  {
14152
15230
  "aria-hidden": "true",
@@ -14157,11 +15235,11 @@ function ITTopBar({
14157
15235
  },
14158
15236
  children: initials
14159
15237
  }
14160
- ) : /* @__PURE__ */ jsx77("div", { className: "w-9 h-9 rounded-full bg-slate-100 flex items-center justify-center ring-2 ring-white shadow-sm", children: /* @__PURE__ */ jsx77(FaUserCircle2, { className: "w-6 h-6", style: { color: "var(--it-topbar-icon, #94a3b8)" } }) }),
14161
- !flat && /* @__PURE__ */ jsx77("div", { className: "absolute bottom-0 right-0 w-2.5 h-2.5 bg-green-500 border-2 border-white rounded-full" })
15238
+ ) : /* @__PURE__ */ jsx78("div", { className: "w-9 h-9 rounded-full bg-slate-100 flex items-center justify-center ring-2 ring-white shadow-sm", children: /* @__PURE__ */ jsx78(FaUserCircle2, { className: "w-6 h-6", style: { color: "var(--it-topbar-icon, #94a3b8)" } }) }),
15239
+ !flat && /* @__PURE__ */ jsx78("div", { className: "absolute bottom-0 right-0 w-2.5 h-2.5 bg-green-500 border-2 border-white rounded-full" })
14162
15240
  ] }),
14163
- /* @__PURE__ */ jsxs55("div", { className: `hidden sm:flex flex-col py-0.5 ${flat ? "text-right" : "text-left"}`, children: [
14164
- /* @__PURE__ */ jsx77(
15241
+ /* @__PURE__ */ jsxs56("div", { className: `hidden sm:flex flex-col py-0.5 ${flat ? "text-right" : "text-left"}`, children: [
15242
+ /* @__PURE__ */ jsx78(
14165
15243
  ITText,
14166
15244
  {
14167
15245
  as: "span",
@@ -14170,7 +15248,7 @@ function ITTopBar({
14170
15248
  children: userMenu.userName
14171
15249
  }
14172
15250
  ),
14173
- /* @__PURE__ */ jsx77(
15251
+ /* @__PURE__ */ jsx78(
14174
15252
  ITText,
14175
15253
  {
14176
15254
  as: "span",
@@ -14183,7 +15261,7 @@ function ITTopBar({
14183
15261
  ]
14184
15262
  }
14185
15263
  ),
14186
- /* @__PURE__ */ jsxs55(
15264
+ /* @__PURE__ */ jsxs56(
14187
15265
  "div",
14188
15266
  {
14189
15267
  ref: userMenuRef,
@@ -14196,15 +15274,15 @@ function ITTopBar({
14196
15274
  border: "1px solid var(--it-topbar-user-dropdown-border, #f1f5f9)"
14197
15275
  },
14198
15276
  children: [
14199
- /* @__PURE__ */ jsxs55("div", { className: "px-5 py-4 border-b", style: { borderColor: "var(--it-topbar-user-dropdown-border, #f1f5f9)", backgroundColor: "var(--it-topbar-user-bg, #f8fafc)" }, children: [
14200
- /* @__PURE__ */ jsx77(ITText, { as: "span", className: "block font-bold text-[0.9rem]", style: { color: "var(--it-topbar-user-text, #0f172a)" }, children: userMenu.userName }),
14201
- /* @__PURE__ */ jsx77(ITText, { as: "span", className: "block text-xs font-medium truncate mt-0.5", style: { color: "var(--it-topbar-user-subtitle, #64748b)" }, children: userMenu.userEmail })
15277
+ /* @__PURE__ */ jsxs56("div", { className: "px-5 py-4 border-b", style: { borderColor: "var(--it-topbar-user-dropdown-border, #f1f5f9)", backgroundColor: "var(--it-topbar-user-bg, #f8fafc)" }, children: [
15278
+ /* @__PURE__ */ jsx78(ITText, { as: "span", className: "block font-bold text-[0.9rem]", style: { color: "var(--it-topbar-user-text, #0f172a)" }, children: userMenu.userName }),
15279
+ /* @__PURE__ */ jsx78(ITText, { as: "span", className: "block text-xs font-medium truncate mt-0.5", style: { color: "var(--it-topbar-user-subtitle, #64748b)" }, children: userMenu.userEmail })
14202
15280
  ] }),
14203
- /* @__PURE__ */ jsx77("ul", { className: "py-2", children: userMenu.menuItems.map((m, i) => {
15281
+ /* @__PURE__ */ jsx78("ul", { className: "py-2", children: userMenu.menuItems.map((m, i) => {
14204
15282
  const isDestructive = m.label.toLowerCase().includes("salir") || m.label.toLowerCase().includes("cerrar") || m.label.toLowerCase().includes("logout");
14205
- return /* @__PURE__ */ jsxs55("li", { className: "px-2", children: [
14206
- i === userMenu.menuItems.length - 1 && isDestructive && i > 0 && /* @__PURE__ */ jsx77("div", { className: "h-px bg-slate-100 my-1 mx-2" }),
14207
- /* @__PURE__ */ jsx77(
15283
+ return /* @__PURE__ */ jsxs56("li", { className: "px-2", children: [
15284
+ i === userMenu.menuItems.length - 1 && isDestructive && i > 0 && /* @__PURE__ */ jsx78("div", { className: "h-px bg-slate-100 my-1 mx-2" }),
15285
+ /* @__PURE__ */ jsx78(
14208
15286
  "button",
14209
15287
  {
14210
15288
  onClick: () => {
@@ -14219,7 +15297,7 @@ function ITTopBar({
14219
15297
  onMouseLeave: (e) => {
14220
15298
  e.currentTarget.style.backgroundColor = "transparent";
14221
15299
  },
14222
- children: /* @__PURE__ */ jsx77(ITText, { as: "span", children: m.label })
15300
+ children: /* @__PURE__ */ jsx78(ITText, { as: "span", children: m.label })
14223
15301
  }
14224
15302
  )
14225
15303
  ] }, i);
@@ -14235,7 +15313,7 @@ function ITTopBar({
14235
15313
  }
14236
15314
 
14237
15315
  // src/components/templates/layout/layout.tsx
14238
- import { jsx as jsx78, jsxs as jsxs56 } from "react/jsx-runtime";
15316
+ import { jsx as jsx79, jsxs as jsxs57 } from "react/jsx-runtime";
14239
15317
  function ITLayout({
14240
15318
  topBar,
14241
15319
  sidebar,
@@ -14244,9 +15322,9 @@ function ITLayout({
14244
15322
  contentClassName = "",
14245
15323
  sidebarFullHeight = false
14246
15324
  }) {
14247
- const [internalCollapsed, setInternalCollapsed] = useState39(true);
14248
- const [mobileSidebarOpen, setMobileSidebarOpen] = useState39(false);
14249
- const flat = useITFlatAppearance();
15325
+ const [internalCollapsed, setInternalCollapsed] = useState42(true);
15326
+ const [mobileSidebarOpen, setMobileSidebarOpen] = useState42(false);
15327
+ const flat = useITAppearance() !== "soft";
14250
15328
  const isControlled = sidebar.isCollapsed !== void 0;
14251
15329
  const desktopCollapsed = isControlled ? sidebar.isCollapsed : internalCollapsed;
14252
15330
  const handleToggleCollapse = isControlled ? sidebar.onToggleCollapse ?? (() => {
@@ -14259,7 +15337,7 @@ function ITLayout({
14259
15337
  else setMobileSidebarOpen((v) => !v);
14260
15338
  };
14261
15339
  const brand = sidebarFullHeight ? sidebar.brand ?? { logo: topBar.logo, text: topBar.logoText } : sidebar.brand;
14262
- const topBarNode = /* @__PURE__ */ jsx78(
15340
+ const topBarNode = /* @__PURE__ */ jsx79(
14263
15341
  ITTopBar,
14264
15342
  {
14265
15343
  ...topBar,
@@ -14272,9 +15350,9 @@ function ITLayout({
14272
15350
  const desktopSidebar = (
14273
15351
  // Full-height: the sidebar sits beside the top bar, so it needs to win the
14274
15352
  // stacking order when the collapsed rail expands over the content on hover.
14275
- /* @__PURE__ */ jsxs56("div", { className: `hidden lg:block relative h-full ${sidebarFullHeight ? "z-50" : "z-40"}`, children: [
14276
- /* @__PURE__ */ jsx78("div", { className: `${reservedWidth} h-full flex-shrink-0` }),
14277
- /* @__PURE__ */ jsx78("div", { className: "absolute top-0 left-0 h-full", children: /* @__PURE__ */ jsx78(
15353
+ /* @__PURE__ */ jsxs57("div", { className: `hidden lg:block relative h-full ${sidebarFullHeight ? "z-50" : "z-40"}`, children: [
15354
+ /* @__PURE__ */ jsx79("div", { className: `${reservedWidth} h-full flex-shrink-0` }),
15355
+ /* @__PURE__ */ jsx79("div", { className: "absolute top-0 left-0 h-full", children: /* @__PURE__ */ jsx79(
14278
15356
  ITSidebar,
14279
15357
  {
14280
15358
  ...sidebar,
@@ -14287,17 +15365,17 @@ function ITLayout({
14287
15365
  ) })
14288
15366
  ] })
14289
15367
  );
14290
- const mobileSidebar = mobileSidebarOpen && /* @__PURE__ */ jsx78(
15368
+ const mobileSidebar = mobileSidebarOpen && /* @__PURE__ */ jsx79(
14291
15369
  "div",
14292
15370
  {
14293
15371
  className: "lg:hidden fixed inset-0 z-[40] transition-opacity duration-300 backdrop-blur-sm bg-black/40",
14294
15372
  onClick: () => setMobileSidebarOpen(false),
14295
- children: /* @__PURE__ */ jsx78(
15373
+ children: /* @__PURE__ */ jsx79(
14296
15374
  "div",
14297
15375
  {
14298
15376
  className: "h-full w-fit flex transform transition-transform duration-300 ease-[cubic-bezier(0.2,0,0,1)]",
14299
15377
  onClick: (e) => e.stopPropagation(),
14300
- children: /* @__PURE__ */ jsx78(
15378
+ children: /* @__PURE__ */ jsx79(
14301
15379
  ITSidebar,
14302
15380
  {
14303
15381
  ...sidebar,
@@ -14314,16 +15392,16 @@ function ITLayout({
14314
15392
  )
14315
15393
  }
14316
15394
  );
14317
- const main = /* @__PURE__ */ jsx78("main", { className: "flex-1 overflow-y-auto w-full custom-scrollbar relative z-0", children: /* @__PURE__ */ jsx78("div", { className: clsx55("mx-auto w-full max-w-7xl px-4 sm:px-6 lg:px-8 py-6 h-full", contentClassName), children }) });
15395
+ const main = /* @__PURE__ */ jsx79("main", { className: "flex-1 overflow-y-auto w-full custom-scrollbar relative z-0", children: /* @__PURE__ */ jsx79("div", { className: clsx55("mx-auto w-full max-w-7xl px-4 sm:px-6 lg:px-8 py-6 h-full", contentClassName), children }) });
14318
15396
  if (sidebarFullHeight) {
14319
- return /* @__PURE__ */ jsxs56(
15397
+ return /* @__PURE__ */ jsxs57(
14320
15398
  "div",
14321
15399
  {
14322
15400
  className: `flex h-screen overflow-hidden w-full relative ${className}`,
14323
15401
  style: { backgroundColor: layoutTokens.backgroundColor },
14324
15402
  children: [
14325
15403
  desktopSidebar,
14326
- /* @__PURE__ */ jsxs56("div", { className: "flex flex-col flex-1 min-w-0 overflow-hidden", children: [
15404
+ /* @__PURE__ */ jsxs57("div", { className: "flex flex-col flex-1 min-w-0 overflow-hidden", children: [
14327
15405
  topBarNode,
14328
15406
  main
14329
15407
  ] }),
@@ -14332,9 +15410,9 @@ function ITLayout({
14332
15410
  }
14333
15411
  );
14334
15412
  }
14335
- return /* @__PURE__ */ jsxs56("div", { className: `flex flex-col h-screen overflow-hidden w-full ${className}`, children: [
15413
+ return /* @__PURE__ */ jsxs57("div", { className: `flex flex-col h-screen overflow-hidden w-full ${className}`, children: [
14336
15414
  topBarNode,
14337
- /* @__PURE__ */ jsxs56(
15415
+ /* @__PURE__ */ jsxs57(
14338
15416
  "div",
14339
15417
  {
14340
15418
  className: "flex flex-1 overflow-hidden relative",
@@ -14351,9 +15429,9 @@ function ITLayout({
14351
15429
 
14352
15430
  // src/components/molecules/stepper/stepper.tsx
14353
15431
  import clsx56 from "clsx";
14354
- import { useEffect as useEffect20, useRef as useRef25, useState as useState40 } from "react";
15432
+ import { useEffect as useEffect21, useRef as useRef25, useState as useState43 } from "react";
14355
15433
  import { FaChevronLeft as FaChevronLeft4, FaChevronRight as FaChevronRight7, FaCheck as FaCheck6 } from "react-icons/fa";
14356
- import { jsx as jsx79, jsxs as jsxs57 } from "react/jsx-runtime";
15434
+ import { jsx as jsx80, jsxs as jsxs58 } from "react/jsx-runtime";
14357
15435
  function ITStepper({
14358
15436
  steps,
14359
15437
  currentStep,
@@ -14369,15 +15447,15 @@ function ITStepper({
14369
15447
  color = "primary"
14370
15448
  }) {
14371
15449
  const { t } = useITTranslation();
14372
- const [direction, setDirection] = useState40("next");
15450
+ const [direction, setDirection] = useState43("next");
14373
15451
  const contentRef = useRef25(null);
14374
15452
  const progressRef = useRef25(null);
14375
15453
  const isThemeColor = color in theme.colors;
14376
15454
  const resolvedColor = isThemeColor ? theme.colors[color][500] : color;
14377
- useEffect20(() => {
15455
+ useEffect21(() => {
14378
15456
  onStepChange?.(currentStep);
14379
15457
  }, [currentStep, onStepChange]);
14380
- useEffect20(() => {
15458
+ useEffect21(() => {
14381
15459
  const pct = currentStep / Math.max(1, steps.length - 1) * 100;
14382
15460
  if (progressRef.current) {
14383
15461
  progressRef.current.style.width = `${pct}%`;
@@ -14421,23 +15499,23 @@ function ITStepper({
14421
15499
  const renderStepContent = (index, isCompleted) => {
14422
15500
  const step = steps[index];
14423
15501
  if (isCompleted) {
14424
- return /* @__PURE__ */ jsx79(FaCheck6, { className: "w-4 h-4" });
15502
+ return /* @__PURE__ */ jsx80(FaCheck6, { className: "w-4 h-4" });
14425
15503
  }
14426
15504
  if (step.icon && useIcons) {
14427
- return /* @__PURE__ */ jsx79("div", { className: "flex items-center justify-center w-5 h-5", children: step.icon });
15505
+ return /* @__PURE__ */ jsx80("div", { className: "flex items-center justify-center w-5 h-5", children: step.icon });
14428
15506
  }
14429
- return /* @__PURE__ */ jsx79(ITText, { as: "span", className: "text-sm font-semibold", children: index + 1 });
15507
+ return /* @__PURE__ */ jsx80(ITText, { as: "span", className: "text-sm font-semibold", children: index + 1 });
14430
15508
  };
14431
- return /* @__PURE__ */ jsxs57("div", { className: clsx56("w-full max-w-5xl mx-auto px-4", containerClassName), children: [
14432
- /* @__PURE__ */ jsxs57("div", { className: "relative mb-8", children: [
14433
- /* @__PURE__ */ jsx79(
15509
+ return /* @__PURE__ */ jsxs58("div", { className: clsx56("w-full max-w-5xl mx-auto px-4", containerClassName), children: [
15510
+ /* @__PURE__ */ jsxs58("div", { className: "relative mb-8", children: [
15511
+ /* @__PURE__ */ jsx80(
14434
15512
  "div",
14435
15513
  {
14436
15514
  className: "absolute left-6 right-6 top-5 h-1 bg-secondary-200 rounded-full z-0",
14437
15515
  "aria-hidden": true
14438
15516
  }
14439
15517
  ),
14440
- /* @__PURE__ */ jsx79(
15518
+ /* @__PURE__ */ jsx80(
14441
15519
  "div",
14442
15520
  {
14443
15521
  ref: progressRef,
@@ -14445,11 +15523,11 @@ function ITStepper({
14445
15523
  "aria-hidden": true
14446
15524
  }
14447
15525
  ),
14448
- /* @__PURE__ */ jsx79("div", { className: "flex items-start justify-between space-x-2 relative z-20", children: steps.map((step, idx) => {
15526
+ /* @__PURE__ */ jsx80("div", { className: "flex items-start justify-between space-x-2 relative z-20", children: steps.map((step, idx) => {
14449
15527
  const isActive = idx === currentStep;
14450
15528
  const isCompleted = idx < currentStep;
14451
15529
  const hasIcon = step.icon && useIcons;
14452
- return /* @__PURE__ */ jsx79(
15530
+ return /* @__PURE__ */ jsx80(
14453
15531
  "button",
14454
15532
  {
14455
15533
  type: "button",
@@ -14459,8 +15537,8 @@ function ITStepper({
14459
15537
  "aria-label": t("stepper.stepAria", { n: idx + 1, label: step.label }),
14460
15538
  className: "flex-1 group",
14461
15539
  title: step.label,
14462
- children: /* @__PURE__ */ jsxs57("div", { className: "flex flex-col items-center", children: [
14463
- /* @__PURE__ */ jsx79(
15540
+ children: /* @__PURE__ */ jsxs58("div", { className: "flex flex-col items-center", children: [
15541
+ /* @__PURE__ */ jsx80(
14464
15542
  "div",
14465
15543
  {
14466
15544
  className: clsx56(
@@ -14474,7 +15552,7 @@ function ITStepper({
14474
15552
  children: renderStepContent(idx, isCompleted)
14475
15553
  }
14476
15554
  ),
14477
- /* @__PURE__ */ jsx79(
15555
+ /* @__PURE__ */ jsx80(
14478
15556
  ITText,
14479
15557
  {
14480
15558
  as: "span",
@@ -14492,7 +15570,7 @@ function ITStepper({
14492
15570
  );
14493
15571
  }) })
14494
15572
  ] }),
14495
- /* @__PURE__ */ jsx79(
15573
+ /* @__PURE__ */ jsx80(
14496
15574
  "div",
14497
15575
  {
14498
15576
  ref: contentRef,
@@ -14508,32 +15586,32 @@ function ITStepper({
14508
15586
  children: steps[currentStep].content
14509
15587
  }
14510
15588
  ),
14511
- /* @__PURE__ */ jsxs57("div", { className: "flex justify-between items-center mt-6", children: [
14512
- /* @__PURE__ */ jsx79(
15589
+ /* @__PURE__ */ jsxs58("div", { className: "flex justify-between items-center mt-6", children: [
15590
+ /* @__PURE__ */ jsx80(
14513
15591
  ITButton,
14514
15592
  {
14515
15593
  variant: "outlined",
14516
15594
  color: "secondary",
14517
15595
  disabled: currentStep === 0,
14518
15596
  onClick: prevStep,
14519
- children: /* @__PURE__ */ jsxs57("div", { className: "flex items-center gap-2", children: [
14520
- /* @__PURE__ */ jsx79(FaChevronLeft4, {}),
14521
- /* @__PURE__ */ jsx79(ITText, { as: "span", children: t("common.back") })
15597
+ children: /* @__PURE__ */ jsxs58("div", { className: "flex items-center gap-2", children: [
15598
+ /* @__PURE__ */ jsx80(FaChevronLeft4, {}),
15599
+ /* @__PURE__ */ jsx80(ITText, { as: "span", children: t("common.back") })
14522
15600
  ] })
14523
15601
  }
14524
15602
  ),
14525
- /* @__PURE__ */ jsxs57("div", { className: "flex items-center gap-3", children: [
14526
- /* @__PURE__ */ jsx79(ITText, { as: "div", className: "text-sm text-secondary-500 mr-2 hidden sm:block", children: t("stepper.stepOf", { current: currentStep + 1, total: steps.length }) }),
14527
- /* @__PURE__ */ jsx79(
15603
+ /* @__PURE__ */ jsxs58("div", { className: "flex items-center gap-3", children: [
15604
+ /* @__PURE__ */ jsx80(ITText, { as: "div", className: "text-sm text-secondary-500 mr-2 hidden sm:block", children: t("stepper.stepOf", { current: currentStep + 1, total: steps.length }) }),
15605
+ /* @__PURE__ */ jsx80(
14528
15606
  ITButton,
14529
15607
  {
14530
15608
  variant: "solid",
14531
15609
  color,
14532
15610
  disabled: disableNext,
14533
15611
  onClick: nextStep,
14534
- children: /* @__PURE__ */ jsxs57("div", { className: "flex items-center gap-2", children: [
14535
- /* @__PURE__ */ jsx79(ITText, { as: "span", children: currentStep === steps.length - 1 ? t("common.finish") : t("common.next") }),
14536
- currentStep === steps.length - 1 ? /* @__PURE__ */ jsx79(FaCheck6, {}) : /* @__PURE__ */ jsx79(FaChevronRight7, {})
15612
+ children: /* @__PURE__ */ jsxs58("div", { className: "flex items-center gap-2", children: [
15613
+ /* @__PURE__ */ jsx80(ITText, { as: "span", children: currentStep === steps.length - 1 ? t("common.finish") : t("common.next") }),
15614
+ currentStep === steps.length - 1 ? /* @__PURE__ */ jsx80(FaCheck6, {}) : /* @__PURE__ */ jsx80(FaChevronRight7, {})
14537
15615
  ] })
14538
15616
  }
14539
15617
  )
@@ -14543,7 +15621,7 @@ function ITStepper({
14543
15621
  }
14544
15622
 
14545
15623
  // src/components/theme-provider/themeProvider.tsx
14546
- import { useState as useState41, useEffect as useEffect21, useLayoutEffect as useLayoutEffect5 } from "react";
15624
+ import { useState as useState44, useEffect as useEffect22, useLayoutEffect as useLayoutEffect5 } from "react";
14547
15625
  import { MdPalette, MdClose, MdRefresh } from "react-icons/md";
14548
15626
 
14549
15627
  // src/components/theme-provider/themePresets.ts
@@ -14721,7 +15799,7 @@ var PRESETS = [
14721
15799
  ];
14722
15800
 
14723
15801
  // src/components/theme-provider/themeProvider.tsx
14724
- import { jsx as jsx80, jsxs as jsxs58 } from "react/jsx-runtime";
15802
+ import { jsx as jsx81, jsxs as jsxs59 } from "react/jsx-runtime";
14725
15803
  var STORAGE_KEY = "it-theme-palette";
14726
15804
  var SHADOW_LEVELS = {
14727
15805
  0: {
@@ -14824,7 +15902,7 @@ function ITThemeProvider({
14824
15902
  appearance = "soft"
14825
15903
  }) {
14826
15904
  const { t } = useITTranslation();
14827
- const [palette2, setPaletteState] = useState41(() => {
15905
+ const [palette2, setPaletteState] = useState44(() => {
14828
15906
  const basePalette = {
14829
15907
  ...DEFAULT_PALETTE,
14830
15908
  ...theme2,
@@ -14850,8 +15928,8 @@ function ITThemeProvider({
14850
15928
  }
14851
15929
  return basePalette;
14852
15930
  });
14853
- const [isOpen, setIsOpen] = useState41(false);
14854
- const [customPresets, setCustomPresets] = useState41(() => {
15931
+ const [isOpen, setIsOpen] = useState44(false);
15932
+ const [customPresets, setCustomPresets] = useState44(() => {
14855
15933
  try {
14856
15934
  const saved = localStorage.getItem("it-theme-custom-presets");
14857
15935
  return saved ? JSON.parse(saved) : [];
@@ -14860,8 +15938,8 @@ function ITThemeProvider({
14860
15938
  return [];
14861
15939
  }
14862
15940
  });
14863
- const [newPresetName, setNewPresetName] = useState41("");
14864
- const [isSavingPreset, setIsSavingPreset] = useState41(false);
15941
+ const [newPresetName, setNewPresetName] = useState44("");
15942
+ const [isSavingPreset, setIsSavingPreset] = useState44(false);
14865
15943
  const handleSavePreset = () => {
14866
15944
  if (!newPresetName.trim()) return;
14867
15945
  const newPreset = {
@@ -14880,8 +15958,8 @@ function ITThemeProvider({
14880
15958
  setCustomPresets(updated);
14881
15959
  localStorage.setItem("it-theme-custom-presets", JSON.stringify(updated));
14882
15960
  };
14883
- const [resolvedTheme, setResolvedTheme] = useState41("light");
14884
- const [darkModeMode, setDarkModeMode] = useState41(
15961
+ const [resolvedTheme, setResolvedTheme] = useState44("light");
15962
+ const [darkModeMode, setDarkModeMode] = useState44(
14885
15963
  () => {
14886
15964
  const saved = localStorage.getItem("it-theme-dark-mode");
14887
15965
  if (saved === "light" || saved === "dark" || saved === "system") {
@@ -14890,7 +15968,7 @@ function ITThemeProvider({
14890
15968
  return "system";
14891
15969
  }
14892
15970
  );
14893
- useEffect21(() => {
15971
+ useEffect22(() => {
14894
15972
  localStorage.setItem("it-theme-dark-mode", darkModeMode);
14895
15973
  const applyDarkMode = (isDark) => {
14896
15974
  if (isDark) {
@@ -14915,7 +15993,7 @@ function ITThemeProvider({
14915
15993
  applyDarkMode(darkModeMode === "dark");
14916
15994
  }
14917
15995
  }, [darkModeMode]);
14918
- useEffect21(() => {
15996
+ useEffect22(() => {
14919
15997
  if (!showFab) {
14920
15998
  setPaletteState({
14921
15999
  ...DEFAULT_PALETTE,
@@ -14972,7 +16050,33 @@ function ITThemeProvider({
14972
16050
  surfaceStyle?.remove();
14973
16051
  };
14974
16052
  }, [radius, shadow]);
14975
- useEffect21(() => {
16053
+ useLayoutEffect5(() => {
16054
+ const STYLE_ID = "it-theme-bento-tokens";
16055
+ let tag = document.getElementById(STYLE_ID);
16056
+ if (appearance !== "bento") {
16057
+ tag?.remove();
16058
+ return;
16059
+ }
16060
+ if (!tag) {
16061
+ tag = document.createElement("style");
16062
+ tag.id = STYLE_ID;
16063
+ document.head.appendChild(tag);
16064
+ }
16065
+ const hasRadius = typeof radius === "number" && isFinite(radius);
16066
+ const hasShadow = shadowLevel(shadow) !== null;
16067
+ const shapeLight = hasRadius ? "" : "--it-bento-card-radius:24px;--it-bento-pill-radius:9999px;--it-bento-field-radius:1rem;--it-input-radius:var(--it-bento-pill-radius);";
16068
+ const shadowLight = hasShadow ? "" : "--it-bento-card-shadow:0 1px 2px rgba(16,24,40,.04),0 12px 32px -16px rgba(16,24,40,.10);--it-bento-card-shadow-hover:0 1px 2px rgba(16,24,40,.06),0 18px 40px -16px rgba(16,24,40,.18);";
16069
+ const shadowDark = hasShadow ? "" : "--it-bento-card-shadow:0 1px 2px rgba(0,0,0,.4),0 12px 32px -16px rgba(0,0,0,.55);--it-bento-card-shadow-hover:0 1px 2px rgba(0,0,0,.5),0 18px 40px -16px rgba(0,0,0,.7);";
16070
+ const navTokens = "--it-sidebar-active-bg:var(--it-bento-nav-active-bg);--it-sidebar-active-color:var(--it-bento-nav-active-text);--it-sidebar-active-icon:var(--it-bento-nav-active-text);";
16071
+ const light = "--it-layout-bg:#f4f4f6;--it-card-bg:#ffffff;--it-bento-card-padding:1.5rem;--it-input-bg:#f1f5f9;--it-input-border:transparent;--it-input-focus-ring:0 0 0 2px color-mix(in srgb,var(--color-primary) 50%,transparent);--it-bento-control-bg:#f1f5f9;--it-bento-control-bg-hover:#e2e8f0;--it-bento-control-text:#475569;--it-bento-ink-bg:#0f172a;--it-bento-ink-text:#ffffff;--it-bento-nav-active-bg:#f1f5f9;--it-bento-nav-active-text:#0f172a;" + navTokens;
16072
+ const dark = "--it-layout-bg:#020617;--it-card-bg:#0f172a;--it-input-bg:#1e293b;--it-input-border:transparent;--it-bento-control-bg:#1e293b;--it-bento-control-bg-hover:#334155;--it-bento-control-text:#cbd5e1;--it-bento-ink-bg:#ffffff;--it-bento-ink-text:#0f172a;--it-bento-nav-active-bg:#1e293b;--it-bento-nav-active-text:#ffffff;" + navTokens;
16073
+ const A = '[data-it-appearance="bento"]';
16074
+ tag.textContent = `:root${A}{${light}${shapeLight}${shadowLight}}:root${A}.dark,:root${A} .dark,:root${A} [data-theme="dark"]{${dark}${shadowDark}}:root${A} [data-theme="light"]{${light}${shadowLight}}`;
16075
+ return () => {
16076
+ tag?.remove();
16077
+ };
16078
+ }, [appearance, radius, shadow]);
16079
+ useEffect22(() => {
14976
16080
  const injectStyles = (obj, prefix = "") => {
14977
16081
  Object.entries(obj).forEach(([key, val]) => {
14978
16082
  if (typeof val === "object" && val !== null) {
@@ -16126,14 +17230,14 @@ function ITThemeProvider({
16126
17230
  const isNested = colorKey.includes(".");
16127
17231
  const label = isNested ? colorKey.split(".")[1] : colorKey;
16128
17232
  const value = getNestedValue3(palette2, colorKey);
16129
- return /* @__PURE__ */ jsxs58(
17233
+ return /* @__PURE__ */ jsxs59(
16130
17234
  "div",
16131
17235
  {
16132
17236
  className: "flex items-center justify-between p-3 rounded-xl border border-slate-100 dark:border-slate-800 bg-white dark:bg-slate-900/50 gap-3 hover:border-slate-200 dark:hover:border-slate-700 transition-colors",
16133
17237
  children: [
16134
- /* @__PURE__ */ jsxs58("div", { className: "flex items-center gap-3 flex-1 min-w-0", children: [
16135
- /* @__PURE__ */ jsxs58("div", { className: "relative w-10 h-10 rounded-xl border-2 border-slate-200 dark:border-slate-700 overflow-hidden cursor-pointer flex-shrink-0 shadow-sm hover:scale-105 transition-transform", children: [
16136
- /* @__PURE__ */ jsx80(
17238
+ /* @__PURE__ */ jsxs59("div", { className: "flex items-center gap-3 flex-1 min-w-0", children: [
17239
+ /* @__PURE__ */ jsxs59("div", { className: "relative w-10 h-10 rounded-xl border-2 border-slate-200 dark:border-slate-700 overflow-hidden cursor-pointer flex-shrink-0 shadow-sm hover:scale-105 transition-transform", children: [
17240
+ /* @__PURE__ */ jsx81(
16137
17241
  "input",
16138
17242
  {
16139
17243
  type: "color",
@@ -16142,23 +17246,23 @@ function ITThemeProvider({
16142
17246
  className: "absolute inset-0 opacity-0 cursor-pointer w-full h-full"
16143
17247
  }
16144
17248
  ),
16145
- /* @__PURE__ */ jsx80("div", { className: "w-full h-full", style: { backgroundColor: value } })
17249
+ /* @__PURE__ */ jsx81("div", { className: "w-full h-full", style: { backgroundColor: value } })
16146
17250
  ] }),
16147
- /* @__PURE__ */ jsxs58("div", { className: "flex flex-col min-w-0", children: [
16148
- /* @__PURE__ */ jsx80(ITText, { as: "span", className: "text-xs font-bold text-slate-700 dark:text-slate-300 truncate capitalize", children: label.replace(/([A-Z])/g, " $1").trim() }),
16149
- /* @__PURE__ */ jsxs58("div", { className: "flex items-center gap-2 mt-0.5", children: [
16150
- /* @__PURE__ */ jsx80(
17251
+ /* @__PURE__ */ jsxs59("div", { className: "flex flex-col min-w-0", children: [
17252
+ /* @__PURE__ */ jsx81(ITText, { as: "span", className: "text-xs font-bold text-slate-700 dark:text-slate-300 truncate capitalize", children: label.replace(/([A-Z])/g, " $1").trim() }),
17253
+ /* @__PURE__ */ jsxs59("div", { className: "flex items-center gap-2 mt-0.5", children: [
17254
+ /* @__PURE__ */ jsx81(
16151
17255
  "span",
16152
17256
  {
16153
17257
  className: "w-3 h-3 rounded-full border border-slate-200 dark:border-slate-600",
16154
17258
  style: { backgroundColor: value }
16155
17259
  }
16156
17260
  ),
16157
- /* @__PURE__ */ jsx80(ITText, { as: "span", className: "font-mono text-[11px] text-slate-400", children: value })
17261
+ /* @__PURE__ */ jsx81(ITText, { as: "span", className: "font-mono text-[11px] text-slate-400", children: value })
16158
17262
  ] })
16159
17263
  ] })
16160
17264
  ] }),
16161
- /* @__PURE__ */ jsx80(
17265
+ /* @__PURE__ */ jsx81(
16162
17266
  "input",
16163
17267
  {
16164
17268
  type: "text",
@@ -16177,14 +17281,14 @@ function ITThemeProvider({
16177
17281
  isCustom
16178
17282
  }) => {
16179
17283
  const isSelected = JSON.stringify(preset.colors) === JSON.stringify(palette2);
16180
- return /* @__PURE__ */ jsxs58(
17284
+ return /* @__PURE__ */ jsxs59(
16181
17285
  "button",
16182
17286
  {
16183
17287
  type: "button",
16184
17288
  onClick: () => applyPreset(preset.colors),
16185
17289
  className: `relative flex flex-col items-start p-2.5 rounded-xl border text-left transition-all group ${isSelected ? "border-primary-500 bg-primary-500/5 shadow-sm ring-1 ring-primary-500/20" : "border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900/50 hover:border-slate-300 dark:hover:border-slate-600"}`,
16186
17290
  children: [
16187
- isCustom && /* @__PURE__ */ jsx80(
17291
+ isCustom && /* @__PURE__ */ jsx81(
16188
17292
  "span",
16189
17293
  {
16190
17294
  onClick: (e) => {
@@ -16193,11 +17297,11 @@ function ITThemeProvider({
16193
17297
  },
16194
17298
  className: "absolute top-1.5 right-1.5 opacity-0 group-hover:opacity-100 p-0.5 rounded-md hover:bg-danger-500/10 hover:text-danger-500 text-slate-400 dark:text-slate-500 cursor-pointer transition-all z-10",
16195
17299
  title: t("themeProvider.designer.deletePreset"),
16196
- children: /* @__PURE__ */ jsx80(MdClose, { size: 12 })
17300
+ children: /* @__PURE__ */ jsx81(MdClose, { size: 12 })
16197
17301
  }
16198
17302
  ),
16199
- /* @__PURE__ */ jsx80(ITText, { as: "span", className: "text-xs font-semibold truncate w-full mb-1.5 pr-4 text-slate-700 dark:text-slate-300", children: PRESET_I18N_KEY[preset.name] ? t(PRESET_I18N_KEY[preset.name]) : preset.name }),
16200
- /* @__PURE__ */ jsx80("div", { className: "flex gap-1", children: ["primary", "secondary", "ternary", "success"].map((c) => /* @__PURE__ */ jsx80(
17303
+ /* @__PURE__ */ jsx81(ITText, { as: "span", className: "text-xs font-semibold truncate w-full mb-1.5 pr-4 text-slate-700 dark:text-slate-300", children: PRESET_I18N_KEY[preset.name] ? t(PRESET_I18N_KEY[preset.name]) : preset.name }),
17304
+ /* @__PURE__ */ jsx81("div", { className: "flex gap-1", children: ["primary", "secondary", "ternary", "success"].map((c) => /* @__PURE__ */ jsx81(
16201
17305
  "span",
16202
17306
  {
16203
17307
  className: "w-3 h-3 rounded-full border border-black/10",
@@ -16209,7 +17313,7 @@ function ITThemeProvider({
16209
17313
  }
16210
17314
  );
16211
17315
  };
16212
- return /* @__PURE__ */ jsxs58(
17316
+ return /* @__PURE__ */ jsxs59(
16213
17317
  ITThemeContext.Provider,
16214
17318
  {
16215
17319
  value: {
@@ -16226,28 +17330,28 @@ function ITThemeProvider({
16226
17330
  },
16227
17331
  children: [
16228
17332
  children,
16229
- showFab && /* @__PURE__ */ jsx80(
17333
+ showFab && /* @__PURE__ */ jsx81(
16230
17334
  "button",
16231
17335
  {
16232
17336
  onClick: () => setIsOpen((prev) => !prev),
16233
17337
  className: "it-theme-fab it-theme-bounce",
16234
17338
  style: { backgroundColor: "var(--color-primary)" },
16235
17339
  "aria-label": t("themeProvider.fab.ariaLabel"),
16236
- children: /* @__PURE__ */ jsx80(MdPalette, { size: 28 })
17340
+ children: /* @__PURE__ */ jsx81(MdPalette, { size: 28 })
16237
17341
  }
16238
17342
  ),
16239
- showFab && /* @__PURE__ */ jsx80(
17343
+ showFab && /* @__PURE__ */ jsx81(
16240
17344
  ITDialog,
16241
17345
  {
16242
17346
  isOpen,
16243
17347
  onClose: () => setIsOpen(false),
16244
17348
  title: t("themeProvider.designer.title"),
16245
17349
  useFormHeader: true,
16246
- children: /* @__PURE__ */ jsxs58("div", { className: "flex gap-6 h-[580px]", children: [
16247
- /* @__PURE__ */ jsxs58("div", { className: "w-64 flex-shrink-0 flex flex-col gap-5 overflow-y-auto pr-1", children: [
16248
- /* @__PURE__ */ jsxs58("div", { children: [
16249
- /* @__PURE__ */ jsx80(ITText, { as: "span", className: "text-[11px] font-bold uppercase tracking-wider text-slate-400 dark:text-slate-500 mb-2.5 block", children: t("themeProvider.designer.appearance") }),
16250
- /* @__PURE__ */ jsx80(
17350
+ children: /* @__PURE__ */ jsxs59("div", { className: "flex gap-6 h-[580px]", children: [
17351
+ /* @__PURE__ */ jsxs59("div", { className: "w-64 flex-shrink-0 flex flex-col gap-5 overflow-y-auto pr-1", children: [
17352
+ /* @__PURE__ */ jsxs59("div", { children: [
17353
+ /* @__PURE__ */ jsx81(ITText, { as: "span", className: "text-[11px] font-bold uppercase tracking-wider text-slate-400 dark:text-slate-500 mb-2.5 block", children: t("themeProvider.designer.appearance") }),
17354
+ /* @__PURE__ */ jsx81(
16251
17355
  ITSegmentedControl,
16252
17356
  {
16253
17357
  options: [
@@ -16261,16 +17365,16 @@ function ITThemeProvider({
16261
17365
  }
16262
17366
  )
16263
17367
  ] }),
16264
- /* @__PURE__ */ jsxs58("div", { children: [
16265
- /* @__PURE__ */ jsx80("div", { className: "flex items-center justify-between mb-2.5", children: /* @__PURE__ */ jsx80(ITText, { as: "span", className: "text-[11px] font-bold uppercase tracking-wider text-slate-400 dark:text-slate-500", children: t("themeProvider.designer.presets") }) }),
16266
- /* @__PURE__ */ jsx80("div", { className: "grid grid-cols-2 gap-2", children: PRESETS.map((preset) => /* @__PURE__ */ jsx80(PresetCard, { preset }, preset.name)) })
17368
+ /* @__PURE__ */ jsxs59("div", { children: [
17369
+ /* @__PURE__ */ jsx81("div", { className: "flex items-center justify-between mb-2.5", children: /* @__PURE__ */ jsx81(ITText, { as: "span", className: "text-[11px] font-bold uppercase tracking-wider text-slate-400 dark:text-slate-500", children: t("themeProvider.designer.presets") }) }),
17370
+ /* @__PURE__ */ jsx81("div", { className: "grid grid-cols-2 gap-2", children: PRESETS.map((preset) => /* @__PURE__ */ jsx81(PresetCard, { preset }, preset.name)) })
16267
17371
  ] }),
16268
- customPresets.length > 0 && /* @__PURE__ */ jsxs58("div", { children: [
16269
- /* @__PURE__ */ jsx80(ITText, { as: "span", className: "text-[11px] font-bold uppercase tracking-wider text-slate-400 dark:text-slate-500 mb-2.5 block", children: t("themeProvider.designer.myThemes") }),
16270
- /* @__PURE__ */ jsx80("div", { className: "flex flex-col gap-1.5", children: customPresets.map((preset) => /* @__PURE__ */ jsx80(PresetCard, { preset, isCustom: true }, preset.name)) })
17372
+ customPresets.length > 0 && /* @__PURE__ */ jsxs59("div", { children: [
17373
+ /* @__PURE__ */ jsx81(ITText, { as: "span", className: "text-[11px] font-bold uppercase tracking-wider text-slate-400 dark:text-slate-500 mb-2.5 block", children: t("themeProvider.designer.myThemes") }),
17374
+ /* @__PURE__ */ jsx81("div", { className: "flex flex-col gap-1.5", children: customPresets.map((preset) => /* @__PURE__ */ jsx81(PresetCard, { preset, isCustom: true }, preset.name)) })
16271
17375
  ] }),
16272
- isSavingPreset && /* @__PURE__ */ jsxs58("div", { className: "flex flex-col gap-2 p-3 rounded-xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900/50", children: [
16273
- /* @__PURE__ */ jsx80(
17376
+ isSavingPreset && /* @__PURE__ */ jsxs59("div", { className: "flex flex-col gap-2 p-3 rounded-xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900/50", children: [
17377
+ /* @__PURE__ */ jsx81(
16274
17378
  ITInput,
16275
17379
  {
16276
17380
  name: "presetName",
@@ -16288,8 +17392,8 @@ function ITThemeProvider({
16288
17392
  }
16289
17393
  }
16290
17394
  ),
16291
- /* @__PURE__ */ jsxs58("div", { className: "flex gap-2", children: [
16292
- /* @__PURE__ */ jsx80(
17395
+ /* @__PURE__ */ jsxs59("div", { className: "flex gap-2", children: [
17396
+ /* @__PURE__ */ jsx81(
16293
17397
  ITButton,
16294
17398
  {
16295
17399
  label: t("themeProvider.designer.save"),
@@ -16300,7 +17404,7 @@ function ITThemeProvider({
16300
17404
  className: "flex-1"
16301
17405
  }
16302
17406
  ),
16303
- /* @__PURE__ */ jsx80(
17407
+ /* @__PURE__ */ jsx81(
16304
17408
  ITButton,
16305
17409
  {
16306
17410
  label: t("themeProvider.designer.cancelSave"),
@@ -16314,31 +17418,31 @@ function ITThemeProvider({
16314
17418
  )
16315
17419
  ] })
16316
17420
  ] }),
16317
- !isSavingPreset && /* @__PURE__ */ jsx80(
17421
+ !isSavingPreset && /* @__PURE__ */ jsx81(
16318
17422
  ITButton,
16319
17423
  {
16320
17424
  variant: "outlined",
16321
- icon: /* @__PURE__ */ jsx80(MdPalette, { size: 14 }),
17425
+ icon: /* @__PURE__ */ jsx81(MdPalette, { size: 14 }),
16322
17426
  label: t("themeProvider.designer.saveCurrent"),
16323
17427
  onClick: () => setIsSavingPreset(true),
16324
17428
  size: "sm"
16325
17429
  }
16326
17430
  ),
16327
- /* @__PURE__ */ jsx80(
17431
+ /* @__PURE__ */ jsx81(
16328
17432
  ITButton,
16329
17433
  {
16330
17434
  variant: "outlined",
16331
17435
  color: "danger",
16332
- icon: /* @__PURE__ */ jsx80(MdRefresh, { size: 14 }),
17436
+ icon: /* @__PURE__ */ jsx81(MdRefresh, { size: 14 }),
16333
17437
  label: t("themeProvider.designer.reset"),
16334
17438
  onClick: resetTheme,
16335
17439
  size: "sm"
16336
17440
  }
16337
17441
  )
16338
17442
  ] }),
16339
- /* @__PURE__ */ jsx80(ITDivider, { orientation: "vertical" }),
16340
- /* @__PURE__ */ jsxs58("div", { className: "flex-1 flex flex-col min-w-0", children: [
16341
- /* @__PURE__ */ jsx80(
17443
+ /* @__PURE__ */ jsx81(ITDivider, { orientation: "vertical" }),
17444
+ /* @__PURE__ */ jsxs59("div", { className: "flex-1 flex flex-col min-w-0", children: [
17445
+ /* @__PURE__ */ jsx81(
16342
17446
  tabs_default,
16343
17447
  {
16344
17448
  variant: "pill",
@@ -16346,7 +17450,7 @@ function ITThemeProvider({
16346
17450
  {
16347
17451
  id: "brand",
16348
17452
  label: t("themeProvider.tabs.brand"),
16349
- content: /* @__PURE__ */ jsx80("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3 max-h-[480px] overflow-y-auto pr-2 mt-3", children: [
17453
+ content: /* @__PURE__ */ jsx81("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3 max-h-[480px] overflow-y-auto pr-2 mt-3", children: [
16350
17454
  "primary",
16351
17455
  "secondary",
16352
17456
  "ternary",
@@ -16355,35 +17459,35 @@ function ITThemeProvider({
16355
17459
  "info",
16356
17460
  "alert",
16357
17461
  "warning"
16358
- ].map((key) => /* @__PURE__ */ jsx80(ColorRow, { colorKey: key }, key)) })
17462
+ ].map((key) => /* @__PURE__ */ jsx81(ColorRow, { colorKey: key }, key)) })
16359
17463
  },
16360
17464
  {
16361
17465
  id: "layout",
16362
17466
  label: t("themeProvider.tabs.layout"),
16363
- content: /* @__PURE__ */ jsx80("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3 max-h-[480px] overflow-y-auto pr-2 mt-3", children: [
17467
+ content: /* @__PURE__ */ jsx81("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3 max-h-[480px] overflow-y-auto pr-2 mt-3", children: [
16364
17468
  "layout.sidebarBg",
16365
17469
  "layout.sidebarText",
16366
17470
  "layout.navbarBg",
16367
17471
  "layout.navbarText"
16368
- ].map((key) => /* @__PURE__ */ jsx80(ColorRow, { colorKey: key }, key)) })
17472
+ ].map((key) => /* @__PURE__ */ jsx81(ColorRow, { colorKey: key }, key)) })
16369
17473
  },
16370
17474
  {
16371
17475
  id: "tables",
16372
17476
  label: t("themeProvider.tabs.tables"),
16373
- content: /* @__PURE__ */ jsx80("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3 max-h-[480px] overflow-y-auto pr-2 mt-3", children: [
17477
+ content: /* @__PURE__ */ jsx81("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3 max-h-[480px] overflow-y-auto pr-2 mt-3", children: [
16374
17478
  "table.headerBg",
16375
17479
  "table.headerText",
16376
17480
  "table.rowBg",
16377
17481
  "table.rowText",
16378
17482
  "table.rowHover"
16379
- ].map((key) => /* @__PURE__ */ jsx80(ColorRow, { colorKey: key }, key)) })
17483
+ ].map((key) => /* @__PURE__ */ jsx81(ColorRow, { colorKey: key }, key)) })
16380
17484
  }
16381
17485
  ]
16382
17486
  }
16383
17487
  ),
16384
- /* @__PURE__ */ jsxs58("div", { className: "flex items-center justify-end gap-3 mt-auto pt-4 border-t border-slate-100 dark:border-slate-800", children: [
16385
- /* @__PURE__ */ jsx80(ITText, { as: "p", className: "text-[11px] text-slate-400 mr-auto", children: t("themeProvider.designer.autosave") }),
16386
- /* @__PURE__ */ jsx80(
17488
+ /* @__PURE__ */ jsxs59("div", { className: "flex items-center justify-end gap-3 mt-auto pt-4 border-t border-slate-100 dark:border-slate-800", children: [
17489
+ /* @__PURE__ */ jsx81(ITText, { as: "p", className: "text-[11px] text-slate-400 mr-auto", children: t("themeProvider.designer.autosave") }),
17490
+ /* @__PURE__ */ jsx81(
16387
17491
  ITButton,
16388
17492
  {
16389
17493
  label: t("themeProvider.designer.close"),
@@ -16441,7 +17545,7 @@ export {
16441
17545
  dropfile_default as ITDropfile,
16442
17546
  ITEmptyState,
16443
17547
  ITField,
16444
- ITFlex,
17548
+ flex_default as ITFlex,
16445
17549
  ITFormBuilder,
16446
17550
  ITFormHeader,
16447
17551
  ITGrid,
@@ -16478,7 +17582,7 @@ export {
16478
17582
  ITTable,
16479
17583
  tabs_default as ITTabs,
16480
17584
  ITText,
16481
- ITTextarea,
17585
+ textarea_default as ITTextarea,
16482
17586
  ITThemeProvider,
16483
17587
  ITTimePicker,
16484
17588
  ITToast,
@@ -16490,13 +17594,16 @@ export {
16490
17594
  auditTree,
16491
17595
  axzyCatalog,
16492
17596
  axzyCatalogTypes,
17597
+ buildNavigationTree,
16493
17598
  buildVocabularyContract,
16494
17599
  countPendingNodes,
17600
+ createBindingResolver,
16495
17601
  createCatalog,
16496
17602
  createLimitTracker,
16497
17603
  createValidationSchema,
16498
17604
  en_default as enMessages,
16499
17605
  es_default as esMessages,
17606
+ flattenRoutes,
16500
17607
  formatPath,
16501
17608
  formatVocabularyForPrompt,
16502
17609
  getCatalogEntry,
@@ -16507,7 +17614,10 @@ export {
16507
17614
  isLightColor,
16508
17615
  isNodePending,
16509
17616
  issue,
17617
+ joinRoutePath,
17618
+ matchRoute,
16510
17619
  migrateSchema,
17620
+ navContainsRoute,
16511
17621
  parsePartialSchema,
16512
17622
  parsePath,
16513
17623
  propPath,
@@ -16517,16 +17627,20 @@ export {
16517
17627
  resolveCssColor,
16518
17628
  resolveLimits,
16519
17629
  resolveNode,
17630
+ routeHref,
16520
17631
  useClickOutside_default as useClickOutside,
16521
17632
  useDebouncedSearch,
16522
17633
  useEditableRow,
16523
17634
  useFloatingPanel,
17635
+ useITAppearance,
16524
17636
  useITFlatAppearance,
16525
17637
  useITTheme,
16526
17638
  useITThemeSafe,
16527
17639
  useITTranslation,
16528
17640
  useJsonRender_default as useJsonRender,
17641
+ useSchemaStream,
16529
17642
  useTableState,
17643
+ validateRoutes,
16530
17644
  validateSchema
16531
17645
  };
16532
17646
  //# sourceMappingURL=index.js.map