mlola-ui 1.13.2 → 1.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mlola-ui",
3
- "version": "1.13.2",
3
+ "version": "1.14.1",
4
4
  "mcpName": "io.github.mlolahq/mlola-ui",
5
5
  "description": "Source-copy CLI that writes framework-free Mlola UI items into your project",
6
6
  "type": "module",
@@ -871,7 +871,7 @@
871
871
  "name": "ai-chat",
872
872
  "type": "registry:block",
873
873
  "title": "AI Chat",
874
- "description": "A complete chat surface that streams reasoning, tool use, answers and sources from any model through one responder function",
874
+ "description": "A complete chat surface that streams reasoning, tool use, answers, sources and interfaces from any model through one responder function",
875
875
  "category": "ai",
876
876
  "tags": [
877
877
  "block",
@@ -1200,7 +1200,7 @@
1200
1200
  "name": "chat-app",
1201
1201
  "type": "registry:page",
1202
1202
  "title": "Chat App",
1203
- "description": "A full chat product on one route: conversations, streaming chat with reasoning, tools and sources, and voice mode",
1203
+ "description": "A full chat product on one route: conversations, streaming chat with reasoning, tools, sources and answers drawn as interfaces, and voice mode",
1204
1204
  "category": "ai",
1205
1205
  "tags": [
1206
1206
  "page",
@@ -313,6 +313,7 @@
313
313
  "ml-rating-track",
314
314
  "ml-rating-value",
315
315
  "ml-render",
316
+ "ml-render-heading",
316
317
  "ml-render-surface",
317
318
  "ml-render-text",
318
319
  "ml-required-mark",
@@ -3288,7 +3288,7 @@
3288
3288
  "render-surface": {
3289
3289
  "needs": "script",
3290
3290
  "react": "\"use client\";\n\nimport * as React from \"react\";\nimport { RenderSurface } from \"@/components/ui/render-surface\";\n\n// What an agent sent: a surface, its components as a flat list, and the data its field is bound to.\nconst messages = [\n { version: \"v0.9.1\", createSurface: { surfaceId: \"feedback\", catalogId: \"https://ui.mlola.com/a2ui/catalog/v1\" } },\n {\n version: \"v0.9.1\",\n updateComponents: {\n surfaceId: \"feedback\",\n components: [\n { id: \"root\", component: \"Card\", children: [\"title\", \"note\", \"send\"] },\n { id: \"title\", component: \"Heading\", level: 3, text: \"How was your order?\" },\n { id: \"note\", component: \"Textarea\", label: \"Tell us more\", value: { path: \"/note\" }, required: true },\n { id: \"send\", component: \"Button\", text: \"Send feedback\", action: { event: { name: \"send_feedback\", context: { note: { path: \"/note\" } } } } },\n ],\n },\n },\n { version: \"v0.9.1\", updateDataModel: { surfaceId: \"feedback\", path: \"/note\", value: \"\" } },\n];\n\nexport default function Example() {\n // The action goes back to the agent; here its context is shown instead.\n const [sent, setSent] = React.useState(\"\");\n return (\n <>\n <RenderSurface messages={messages} onAction={(message) => setSent(String(message.action.context.note))} />\n <p role=\"status\">{sent ? `Sent to the agent: ${sent}` : \"\"}</p>\n </>\n );\n}",
3291
- "html": "<div class=\"ml-render\">\n <div class=\"ml-render-surface\" data-surface=\"feedback\" data-theme=\"graphite\" data-mode=\"system\" data-themed=\"\">\n <div class=\"ml-card\" data-variant=\"default\">\n <div class=\"ml-card-content ml-stack\">\n <h3>How was your order?</h3>\n <div class=\"ml-input-field\">\n <label class=\"ml-input-label\" id=\"render-surface-1-feedback-note_40-label\" for=\"render-surface-1-feedback-note_40\">Tell us more<span class=\"ml-required-mark\" aria-hidden=\"true\">*</span></label>\n <textarea class=\"ml-textarea\" id=\"render-surface-1-feedback-note_40\" rows=\"4\" required=\"\" maxLength=\"4000\" style=\"--ml-textarea-max-rows:12\"></textarea>\n </div>\n <button class=\"ml-button\" type=\"button\" data-variant=\"primary\" data-size=\"md\" id=\"render-surface-1-feedback-send_40\"><span class=\"ml-button-label\">Send feedback</span></button>\n </div>\n </div>\n </div>\n <p class=\"ml-visually-hidden\" role=\"status\"></p>\n</div>\n<p role=\"status\"></p>",
3291
+ "html": "<div class=\"ml-render\">\n <div class=\"ml-render-surface\" data-surface=\"feedback\" data-theme=\"graphite\" data-mode=\"system\" data-themed=\"\">\n <div class=\"ml-card\" data-variant=\"default\">\n <div class=\"ml-card-content ml-stack\">\n <h3 class=\"ml-render-heading\">How was your order?</h3>\n <div class=\"ml-input-field\">\n <label class=\"ml-input-label\" id=\"render-surface-1-feedback-note_40-label\" for=\"render-surface-1-feedback-note_40\">Tell us more<span class=\"ml-required-mark\" aria-hidden=\"true\">*</span></label>\n <textarea class=\"ml-textarea\" id=\"render-surface-1-feedback-note_40\" rows=\"4\" required=\"\" maxLength=\"4000\" style=\"--ml-textarea-max-rows:12\"></textarea>\n </div>\n <button class=\"ml-button\" type=\"button\" data-variant=\"primary\" data-size=\"md\" id=\"render-surface-1-feedback-send_40\"><span class=\"ml-button-label\">Send feedback</span></button>\n </div>\n </div>\n </div>\n <p class=\"ml-visually-hidden\" role=\"status\"></p>\n</div>\n<p role=\"status\"></p>",
3292
3292
  "elements": [
3293
3293
  {
3294
3294
  "class": "ml-render",
@@ -3300,6 +3300,10 @@
3300
3300
  "data-themed": []
3301
3301
  }
3302
3302
  },
3303
+ {
3304
+ "class": "ml-render-heading",
3305
+ "attributes": {}
3306
+ },
3303
3307
  {
3304
3308
  "class": "ml-render-text",
3305
3309
  "attributes": {}
@@ -2,7 +2,7 @@
2
2
  "$schema": "./schema/registry-index.schema.json",
3
3
  "schemaVersion": 2,
4
4
  "name": "mlola-ui",
5
- "version": "1.13.2",
5
+ "version": "1.14.1",
6
6
  "homepage": "https://ui.mlola.com",
7
7
  "themeContract": {
8
8
  "attribute": "data-theme",
@@ -179,8 +179,8 @@
179
179
  },
180
180
  "registryDependencies": [],
181
181
  "engineDependencies": {
182
- "@mlola-ui/behavior": "^1.13.2",
183
- "@mlola-ui/icons": "^1.13.2"
182
+ "@mlola-ui/behavior": "^1.14.1",
183
+ "@mlola-ui/icons": "^1.14.1"
184
184
  },
185
185
  "options": [
186
186
  {
@@ -241,7 +241,7 @@
241
241
  },
242
242
  "registryDependencies": [],
243
243
  "engineDependencies": {
244
- "@mlola-ui/icons": "^1.13.2"
244
+ "@mlola-ui/icons": "^1.14.1"
245
245
  },
246
246
  "options": [
247
247
  {
@@ -403,7 +403,7 @@
403
403
  },
404
404
  "registryDependencies": [],
405
405
  "engineDependencies": {
406
- "@mlola-ui/icons": "^1.13.2"
406
+ "@mlola-ui/icons": "^1.14.1"
407
407
  },
408
408
  "options": [
409
409
  {
@@ -495,7 +495,7 @@
495
495
  },
496
496
  "registryDependencies": [],
497
497
  "engineDependencies": {
498
- "@mlola-ui/icons": "^1.13.2"
498
+ "@mlola-ui/icons": "^1.14.1"
499
499
  },
500
500
  "options": [],
501
501
  "variants": [],
@@ -548,7 +548,7 @@
548
548
  "spinner"
549
549
  ],
550
550
  "engineDependencies": {
551
- "@mlola-ui/motion": "^1.13.2"
551
+ "@mlola-ui/motion": "^1.14.1"
552
552
  },
553
553
  "options": [
554
554
  {
@@ -716,8 +716,8 @@
716
716
  },
717
717
  "registryDependencies": [],
718
718
  "engineDependencies": {
719
- "@mlola-ui/behavior": "^1.13.2",
720
- "@mlola-ui/icons": "^1.13.2"
719
+ "@mlola-ui/behavior": "^1.14.1",
720
+ "@mlola-ui/icons": "^1.14.1"
721
721
  },
722
722
  "options": [
723
723
  {
@@ -786,7 +786,7 @@
786
786
  },
787
787
  "registryDependencies": [],
788
788
  "engineDependencies": {
789
- "@mlola-ui/icons": "^1.13.2"
789
+ "@mlola-ui/icons": "^1.14.1"
790
790
  },
791
791
  "options": [],
792
792
  "variants": [],
@@ -841,7 +841,7 @@
841
841
  "modal"
842
842
  ],
843
843
  "engineDependencies": {
844
- "@mlola-ui/icons": "^1.13.2"
844
+ "@mlola-ui/icons": "^1.14.1"
845
845
  },
846
846
  "options": [],
847
847
  "variants": [],
@@ -905,8 +905,8 @@
905
905
  },
906
906
  "registryDependencies": [],
907
907
  "engineDependencies": {
908
- "@mlola-ui/behavior": "^1.13.2",
909
- "@mlola-ui/icons": "^1.13.2"
908
+ "@mlola-ui/behavior": "^1.14.1",
909
+ "@mlola-ui/icons": "^1.14.1"
910
910
  },
911
911
  "options": [
912
912
  {
@@ -995,7 +995,7 @@
995
995
  "input"
996
996
  ],
997
997
  "engineDependencies": {
998
- "@mlola-ui/icons": "^1.13.2"
998
+ "@mlola-ui/icons": "^1.14.1"
999
999
  },
1000
1000
  "options": [],
1001
1001
  "variants": [],
@@ -1220,8 +1220,8 @@
1220
1220
  },
1221
1221
  "registryDependencies": [],
1222
1222
  "engineDependencies": {
1223
- "@mlola-ui/behavior": "^1.13.2",
1224
- "@mlola-ui/icons": "^1.13.2"
1223
+ "@mlola-ui/behavior": "^1.14.1",
1224
+ "@mlola-ui/icons": "^1.14.1"
1225
1225
  },
1226
1226
  "options": [
1227
1227
  {
@@ -1372,7 +1372,7 @@
1372
1372
  },
1373
1373
  "registryDependencies": [],
1374
1374
  "engineDependencies": {
1375
- "@mlola-ui/icons": "^1.13.2"
1375
+ "@mlola-ui/icons": "^1.14.1"
1376
1376
  },
1377
1377
  "options": [],
1378
1378
  "variants": [],
@@ -1423,7 +1423,7 @@
1423
1423
  },
1424
1424
  "registryDependencies": [],
1425
1425
  "engineDependencies": {
1426
- "@mlola-ui/behavior": "^1.13.2"
1426
+ "@mlola-ui/behavior": "^1.14.1"
1427
1427
  },
1428
1428
  "options": [
1429
1429
  {
@@ -1801,7 +1801,7 @@
1801
1801
  },
1802
1802
  "registryDependencies": [],
1803
1803
  "engineDependencies": {
1804
- "@mlola-ui/behavior": "^1.13.2"
1804
+ "@mlola-ui/behavior": "^1.14.1"
1805
1805
  },
1806
1806
  "options": [],
1807
1807
  "variants": [],
@@ -1854,8 +1854,8 @@
1854
1854
  "input"
1855
1855
  ],
1856
1856
  "engineDependencies": {
1857
- "@mlola-ui/behavior": "^1.13.2",
1858
- "@mlola-ui/icons": "^1.13.2"
1857
+ "@mlola-ui/behavior": "^1.14.1",
1858
+ "@mlola-ui/icons": "^1.14.1"
1859
1859
  },
1860
1860
  "options": [
1861
1861
  {
@@ -1933,8 +1933,8 @@
1933
1933
  },
1934
1934
  "registryDependencies": [],
1935
1935
  "engineDependencies": {
1936
- "@mlola-ui/behavior": "^1.13.2",
1937
- "@mlola-ui/icons": "^1.13.2"
1936
+ "@mlola-ui/behavior": "^1.14.1",
1937
+ "@mlola-ui/icons": "^1.14.1"
1938
1938
  },
1939
1939
  "options": [
1940
1940
  {
@@ -2080,7 +2080,7 @@
2080
2080
  "input"
2081
2081
  ],
2082
2082
  "engineDependencies": {
2083
- "@mlola-ui/behavior": "^1.13.2"
2083
+ "@mlola-ui/behavior": "^1.14.1"
2084
2084
  },
2085
2085
  "options": [
2086
2086
  {
@@ -2148,7 +2148,7 @@
2148
2148
  "input"
2149
2149
  ],
2150
2150
  "engineDependencies": {
2151
- "@mlola-ui/behavior": "^1.13.2"
2151
+ "@mlola-ui/behavior": "^1.14.1"
2152
2152
  },
2153
2153
  "options": [
2154
2154
  {
@@ -2308,7 +2308,7 @@
2308
2308
  },
2309
2309
  "registryDependencies": [],
2310
2310
  "engineDependencies": {
2311
- "@mlola-ui/behavior": "^1.13.2"
2311
+ "@mlola-ui/behavior": "^1.14.1"
2312
2312
  },
2313
2313
  "options": [
2314
2314
  {
@@ -2440,7 +2440,7 @@
2440
2440
  },
2441
2441
  "registryDependencies": [],
2442
2442
  "engineDependencies": {
2443
- "@mlola-ui/icons": "^1.13.2"
2443
+ "@mlola-ui/icons": "^1.14.1"
2444
2444
  },
2445
2445
  "options": [
2446
2446
  {
@@ -2528,8 +2528,8 @@
2528
2528
  "spinner"
2529
2529
  ],
2530
2530
  "engineDependencies": {
2531
- "@mlola-ui/behavior": "^1.13.2",
2532
- "@mlola-ui/icons": "^1.13.2"
2531
+ "@mlola-ui/behavior": "^1.14.1",
2532
+ "@mlola-ui/icons": "^1.14.1"
2533
2533
  },
2534
2534
  "options": [
2535
2535
  {
@@ -2684,7 +2684,7 @@
2684
2684
  },
2685
2685
  "registryDependencies": [],
2686
2686
  "engineDependencies": {
2687
- "@mlola-ui/behavior": "^1.13.2"
2687
+ "@mlola-ui/behavior": "^1.14.1"
2688
2688
  },
2689
2689
  "options": [
2690
2690
  {
@@ -2761,7 +2761,7 @@
2761
2761
  },
2762
2762
  "registryDependencies": [],
2763
2763
  "engineDependencies": {
2764
- "@mlola-ui/behavior": "^1.13.2"
2764
+ "@mlola-ui/behavior": "^1.14.1"
2765
2765
  },
2766
2766
  "options": [
2767
2767
  {
@@ -2843,7 +2843,7 @@
2843
2843
  },
2844
2844
  "registryDependencies": [],
2845
2845
  "engineDependencies": {
2846
- "@mlola-ui/icons": "^1.13.2"
2846
+ "@mlola-ui/icons": "^1.14.1"
2847
2847
  },
2848
2848
  "options": [
2849
2849
  {
@@ -2915,7 +2915,7 @@
2915
2915
  "popover"
2916
2916
  ],
2917
2917
  "engineDependencies": {
2918
- "@mlola-ui/icons": "^1.13.2"
2918
+ "@mlola-ui/icons": "^1.14.1"
2919
2919
  },
2920
2920
  "options": [
2921
2921
  {
@@ -2985,7 +2985,7 @@
2985
2985
  "popover"
2986
2986
  ],
2987
2987
  "engineDependencies": {
2988
- "@mlola-ui/icons": "^1.13.2"
2988
+ "@mlola-ui/icons": "^1.14.1"
2989
2989
  },
2990
2990
  "options": [],
2991
2991
  "variants": [],
@@ -3183,8 +3183,8 @@
3183
3183
  "input"
3184
3184
  ],
3185
3185
  "engineDependencies": {
3186
- "@mlola-ui/behavior": "^1.13.2",
3187
- "@mlola-ui/icons": "^1.13.2"
3186
+ "@mlola-ui/behavior": "^1.14.1",
3187
+ "@mlola-ui/icons": "^1.14.1"
3188
3188
  },
3189
3189
  "options": [
3190
3190
  {
@@ -3273,7 +3273,7 @@
3273
3273
  "input"
3274
3274
  ],
3275
3275
  "engineDependencies": {
3276
- "@mlola-ui/icons": "^1.13.2"
3276
+ "@mlola-ui/icons": "^1.14.1"
3277
3277
  },
3278
3278
  "options": [],
3279
3279
  "variants": [],
@@ -3328,7 +3328,7 @@
3328
3328
  "input"
3329
3329
  ],
3330
3330
  "engineDependencies": {
3331
- "@mlola-ui/icons": "^1.13.2"
3331
+ "@mlola-ui/icons": "^1.14.1"
3332
3332
  },
3333
3333
  "options": [],
3334
3334
  "variants": [],
@@ -3391,7 +3391,7 @@
3391
3391
  "popover"
3392
3392
  ],
3393
3393
  "engineDependencies": {
3394
- "@mlola-ui/icons": "^1.13.2"
3394
+ "@mlola-ui/icons": "^1.14.1"
3395
3395
  },
3396
3396
  "options": [
3397
3397
  {
@@ -3462,7 +3462,7 @@
3462
3462
  },
3463
3463
  "registryDependencies": [],
3464
3464
  "engineDependencies": {
3465
- "@mlola-ui/icons": "^1.13.2"
3465
+ "@mlola-ui/icons": "^1.14.1"
3466
3466
  },
3467
3467
  "options": [
3468
3468
  {
@@ -3581,8 +3581,8 @@
3581
3581
  },
3582
3582
  "registryDependencies": [],
3583
3583
  "engineDependencies": {
3584
- "@mlola-ui/behavior": "^1.13.2",
3585
- "@mlola-ui/icons": "^1.13.2"
3584
+ "@mlola-ui/behavior": "^1.14.1",
3585
+ "@mlola-ui/icons": "^1.14.1"
3586
3586
  },
3587
3587
  "options": [],
3588
3588
  "variants": [],
@@ -3646,7 +3646,7 @@
3646
3646
  },
3647
3647
  "registryDependencies": [],
3648
3648
  "engineDependencies": {
3649
- "@mlola-ui/behavior": "^1.13.2"
3649
+ "@mlola-ui/behavior": "^1.14.1"
3650
3650
  },
3651
3651
  "options": [
3652
3652
  {
@@ -3733,8 +3733,8 @@
3733
3733
  },
3734
3734
  "registryDependencies": [],
3735
3735
  "engineDependencies": {
3736
- "@mlola-ui/behavior": "^1.13.2",
3737
- "@mlola-ui/icons": "^1.13.2"
3736
+ "@mlola-ui/behavior": "^1.14.1",
3737
+ "@mlola-ui/icons": "^1.14.1"
3738
3738
  },
3739
3739
  "options": [],
3740
3740
  "variants": [],
@@ -3808,7 +3808,7 @@
3808
3808
  "sheet"
3809
3809
  ],
3810
3810
  "engineDependencies": {
3811
- "@mlola-ui/icons": "^1.13.2"
3811
+ "@mlola-ui/icons": "^1.14.1"
3812
3812
  },
3813
3813
  "options": [],
3814
3814
  "variants": [],
@@ -3931,7 +3931,7 @@
3931
3931
  "button"
3932
3932
  ],
3933
3933
  "engineDependencies": {
3934
- "@mlola-ui/icons": "^1.13.2"
3934
+ "@mlola-ui/icons": "^1.14.1"
3935
3935
  },
3936
3936
  "options": [
3937
3937
  {
@@ -4035,8 +4035,8 @@
4035
4035
  "input"
4036
4036
  ],
4037
4037
  "engineDependencies": {
4038
- "@mlola-ui/behavior": "^1.13.2",
4039
- "@mlola-ui/icons": "^1.13.2"
4038
+ "@mlola-ui/behavior": "^1.14.1",
4039
+ "@mlola-ui/icons": "^1.14.1"
4040
4040
  },
4041
4041
  "options": [
4042
4042
  {
@@ -4128,7 +4128,7 @@
4128
4128
  "toggle"
4129
4129
  ],
4130
4130
  "engineDependencies": {
4131
- "@mlola-ui/behavior": "^1.13.2"
4131
+ "@mlola-ui/behavior": "^1.14.1"
4132
4132
  },
4133
4133
  "options": [
4134
4134
  {
@@ -4155,7 +4155,7 @@
4155
4155
  "path": "packages/components/render-surface/render-surface.tsx",
4156
4156
  "target": "{{aliases.components}}/render-surface.tsx",
4157
4157
  "type": "registry:ui",
4158
- "integrity": "sha256-nW48kYLXoa3eeGZQ7gXMD/bTNH9MDeJlWyl1zzrvDwo="
4158
+ "integrity": "sha256-6dKHxnovy48yojPa3rukx8Vs9mH48G4avLnoYmhZf0Q="
4159
4159
  }
4160
4160
  ],
4161
4161
  "themeContract": {
@@ -6089,6 +6089,23 @@ button.ml-breadcrumb-link {
6089
6089
  background: var(--ml-background);
6090
6090
  }
6091
6091
 
6092
+ .ml-render-heading {
6093
+ font-family: var(--ml-font-display);
6094
+ font-size: var(--ml-type-md);
6095
+ font-weight: 600;
6096
+ line-height: 1.3;
6097
+ letter-spacing: -0.01em;
6098
+ text-wrap: balance;
6099
+ }
6100
+
6101
+ h2.ml-render-heading {
6102
+ font-size: var(--ml-type-xl);
6103
+ }
6104
+
6105
+ h3.ml-render-heading {
6106
+ font-size: var(--ml-type-lg);
6107
+ }
6108
+
6092
6109
  .ml-render-text {
6093
6110
  white-space: pre-line;
6094
6111
  overflow-wrap: anywhere;
@@ -8475,7 +8492,7 @@ body{min-height:0;padding:var(--ml-space-2)}#status{margin:var(--ml-space-2)}</s
8475
8492
  <main id="surfaces"></main>
8476
8493
  <p id="status" class="ml-fine-print" role="status" hidden></p>
8477
8494
  <script>"use strict";(()=>{function vt(e,t){let n=(String(t).split(".")[1]??"").length;return Number(e.toFixed(Math.min(n,10)))}function he(e,{min:t=0,max:n=100,step:i=1}={}){let o=Number.isFinite(t)?t:0,r=Number.isFinite(n)&&n>o?n:o+100,a=Number.isFinite(i)&&i>0?i:1,l=Number.isFinite(e)?e:o,s=Math.min(r,Math.max(o,l)),c=o+Math.round((s-o)/a)*a;return vt(Math.min(r,Math.max(o,c)),a)}function Ge(e,{min:t=0,max:n=100,step:i=1}={}){let o=Number.isFinite(t)?t:0,r=Number.isFinite(n)&&n>o?n:o+100,a=Number.isFinite(e)?Math.min(1,Math.max(0,e)):0;return he(o+a*(r-o),{min:o,max:r,step:i})}function _e(e,{min:t=0,max:n=100}={}){let i=Number.isFinite(t)?t:0,o=Number.isFinite(n)&&n>i?n:i+100;return o===i?0:(Math.min(o,Math.max(i,e))-i)/(o-i)*100}function Ue(e,t,{min:n=0,max:i=100,step:o=1}={}){let r=Number.isFinite(n)?n:0,a=Number.isFinite(i)&&i>r?i:r+100,l=Number.isFinite(o)&&o>0?o:1,s=Math.max(l,(a-r)/10),c={ArrowLeft:-l,ArrowDown:-l,ArrowRight:l,ArrowUp:l,PageDown:-s,PageUp:s};if(e==="Home")return he(r,{min:r,max:a,step:l});if(e==="End")return he(a,{min:r,max:a,step:l});let d=c[e];if(d!==void 0)return he(t+d,{min:r,max:a,step:l})}var an=Object.freeze({delay:250,slop:8});function Je(e,t,n=6){return Math.abs(e)>=n&&Math.abs(e)>=Math.abs(t)}function Ve(e,t,n,{horizontal:i=!0,wrap:o=!0,enabled:r=()=>!0}={}){if(e<=0)return-1;let a=(h,g)=>{let y=h;for(let I=0;I<e;I+=1){if(r(y))return y;y+=g,y<0&&(y=e-1),y>=e&&(y=0)}return-1};if(n==="Home")return a(0,1);if(n==="End")return a(e-1,-1);let c=n===(i?"ArrowRight":"ArrowDown")?1:n===(i?"ArrowLeft":"ArrowUp")?-1:0;if(!c)return-1;let d=t;for(let h=0;h<e;h+=1){if(d+=c,d<0){if(!o)return-1;d=e-1}if(d>=e){if(!o)return-1;d=0}if(r(d))return d}return-1}function Ke(e,t,n){return e<=0?-1:n&&t<=0?e-1:!n&&t===e-1?0:-1}var He={top:"bottom",bottom:"top",left:"right",right:"left"};function $e(e,t,n,{side:i="bottom",align:o="center",offset:r=8,padding:a=8}={}){let l={top:e.y-a,bottom:n.height-(e.y+e.height)-a,left:e.x-a,right:n.width-(e.x+e.width)-a},s=y=>(y==="top"||y==="bottom"?t.height:t.width)+r,c=i;l[i]<s(i)&&l[He[i]]>l[i]&&(c=He[i]);let d=c==="top"||c==="bottom",h,g;return d?(g=c==="bottom"?e.y+e.height+r:e.y-t.height-r,h=o==="start"?e.x:o==="end"?e.x+e.width-t.width:e.x+e.width/2-t.width/2):(h=c==="right"?e.x+e.width+r:e.x-t.width-r,g=o==="start"?e.y:o==="end"?e.y+e.height-t.height:e.y+e.height/2-t.height/2),h=Math.min(Math.max(h,a),Math.max(a,n.width-t.width-a)),g=Math.min(Math.max(g,a),Math.max(a,n.height-t.height-a)),{x:Math.round(h),y:Math.round(g),side:c}}function Ye(e,t,n,{side:i="top",offset:o=8,padding:r=8}={}){let a=i==="left"||i==="right",l=Math.max(e.x,n.width-e.x-e.width)-r,s=a&&t.width+o>l?"top":i,c=$e(e,t,n,{side:s,align:"center",offset:o,padding:r}),d=c.side==="top"||c.side==="bottom",h=d?e.x+e.width/2-t.width/2:e.y+e.height/2-t.height/2;return{...c,shift:Math.round((d?c.x:c.y)-h)}}var Xe=Symbol.for("mlola.scrollLock");function Ze(e=globalThis.document){if(!e?.documentElement)return()=>{};let t=e.documentElement,n=t[Xe]??(t[Xe]={count:0,saved:null});if(n.count===0){let o=e.defaultView,r=t.clientWidth;n.saved={overflow:t.style.overflow,scrollbarGutter:t.style.scrollbarGutter,paddingInlineEnd:t.style.paddingInlineEnd},t.style.scrollbarGutter="stable",t.style.overflow="hidden";let a=t.clientWidth-r,l=0;if(a>0&&o){t.style.scrollbarGutter=n.saved.scrollbarGutter;let s=Number.parseFloat(o.getComputedStyle(t).paddingInlineEnd)||0;t.style.paddingInlineEnd=`${s+a}px`,l=a}t.style.setProperty("--ml-scroll-lock-offset",`${l}px`),t.setAttribute("data-ml-scroll-locked","")}n.count+=1;let i=!1;return()=>{i||(i=!0,n.count=Math.max(0,n.count-1),!(n.count>0||!n.saved)&&(t.style.overflow=n.saved.overflow,t.style.scrollbarGutter=n.saved.scrollbarGutter,t.style.paddingInlineEnd=n.saved.paddingInlineEnd,t.style.removeProperty("--ml-scroll-lock-offset"),t.removeAttribute("data-ml-scroll-locked"),n.saved=null))}}var Ae="__mlolaEnhanced",Se=(e,t)=>e.dispatchEvent(new CustomEvent("ml-change",{detail:{value:t},bubbles:!0})),wt=["a[href]","button:not([disabled])","input:not([disabled]):not([type='hidden'])","select:not([disabled])","textarea:not([disabled])","[tabindex]:not([tabindex='-1'])"].join(",");function Qe(e){return[...e.querySelectorAll(wt)].filter(t=>t.offsetWidth>0||t.offsetHeight>0||t===document.activeElement)}function D(e,t,n,i){return e.addEventListener(t,n,i),()=>e.removeEventListener(t,n,i)}function Te(e,t,n,i=$e){let o=typeof e.showPopover=="function";o&&!e.hasAttribute("popover")&&e.setAttribute("popover","manual");let r=!1,a=0,l=()=>{let c=t.getBoundingClientRect(),{minWidth:d,...h}=n();d&&(e.style.minWidth=`${d}px`);let g=i({x:c.left,y:c.top,width:c.width,height:c.height},{width:e.offsetWidth,height:e.offsetHeight},{width:window.innerWidth,height:window.innerHeight},h);e.style.left=`${g.x}px`,e.style.top=`${g.y}px`,g.shift!==void 0&&e.style.setProperty("--ml-floating-shift",`${g.shift}px`),e.dataset.side=g.side},s=()=>{cancelAnimationFrame(a),a=requestAnimationFrame(()=>{r&&l()})};return{show(){r=!0,e.hidden=!1,o&&e.isConnected&&!e.matches(":popover-open")&&e.showPopover(),l()},hide(){r=!1,o&&e.matches(":popover-open")&&e.hidePopover(),e.hidden=!0},cleanups:[D(window,"scroll",s,!0),D(window,"resize",s),()=>cancelAnimationFrame(a)]}}function ye(e,t,n,i={}){return Ve(e.length,t,n,{...i,enabled:o=>!e[o].disabled&&e[o].getAttribute("aria-disabled")!=="true"})}var Le={accordion(e){let t=e.dataset.mlMultiple==="true",n=e.dataset.mlCollapsible!=="false",i=()=>[...e.querySelectorAll(".ml-accordion-item")],o=()=>[...e.querySelectorAll(".ml-accordion-trigger")],r=(l,s)=>{let c=l.querySelector(".ml-accordion-trigger"),d=l.querySelector(".ml-accordion-panel"),h=s?"open":"closed";l.dataset.state=h,c&&(c.dataset.state=h,c.setAttribute("aria-expanded",String(s))),d&&(d.dataset.state=h,d.hidden=!s)},a=l=>{let s=l.dataset.state==="open";if(!(s&&!n)){if(!t&&!s)for(let c of i())c!==l&&r(c,!1);r(l,!s)}};return[D(e,"click",l=>{let s=l.target.closest(".ml-accordion-trigger");s&&e.contains(s)&&a(s.closest(".ml-accordion-item"))}),D(e,"keydown",l=>{let s=l.target.closest(".ml-accordion-trigger");if(!s)return;let c=o(),d=c.indexOf(s),h=ye(c,d,l.key,{horizontal:!1});h>=0&&(l.preventDefault(),c[h].focus())})]},tabs(e){let t=e.dataset.orientation!=="vertical",n=()=>[...e.querySelectorAll(".ml-tabs-trigger")],i=o=>{for(let r of n()){let a=r===o;r.dataset.state=a?"active":"inactive",r.setAttribute("aria-selected",String(a)),r.tabIndex=a?0:-1;let l=document.getElementById(r.getAttribute("aria-controls")??"");l&&(l.dataset.state=a?"active":"inactive",l.hidden=!a)}};return[D(e,"click",o=>{let r=o.target.closest(".ml-tabs-trigger");r&&e.contains(r)&&!r.disabled&&i(r)}),D(e,"keydown",o=>{let r=o.target.closest(".ml-tabs-trigger");if(!r)return;let a=n(),l=ye(a,a.indexOf(r),o.key,{horizontal:t});l<0||(o.preventDefault(),a[l].focus(),i(a[l]))})]},"dropdown-menu":e=>{let t=e.querySelector(".ml-dropdown-trigger"),n=e.querySelector(".ml-dropdown-menu");if(!t||!n)return[];let i=()=>[...n.querySelectorAll(".ml-dropdown-item")].filter(s=>!s.disabled&&s.getAttribute("aria-disabled")!=="true"),o=Te(n,t,()=>({side:"bottom",align:n.dataset.align==="end"?"end":"start",offset:6})),r=s=>{if(e.dataset.state=s?"open":"closed",n.dataset.state=s?"open":"closed",s?o.show():o.hide(),t.setAttribute("aria-expanded",String(s)),!s)for(let c of i())delete c.dataset.highlighted},a=()=>e.dataset.state==="open",l=s=>{for(let c of i())delete c.dataset.highlighted;s&&(s.dataset.highlighted="",s.focus())};return r(!1),[D(t,"click",()=>{if(a()){r(!1);return}r(!0),l(i()[0])}),D(e,"keydown",s=>{let c=i();if(s.key==="Escape"){if(!a())return;s.preventDefault(),r(!1),t.focus();return}if(s.key==="Tab"){r(!1);return}if(s.key==="ArrowDown"||s.key==="ArrowUp"){if(s.preventDefault(),!a()){r(!0),l(c[s.key==="ArrowDown"?0:c.length-1]);return}let d=c.findIndex(g=>"highlighted"in g.dataset),h=ye(c,d,s.key,{horizontal:!1});h>=0&&l(c[h])}}),D(n,"pointermove",s=>{let c=s.target.closest(".ml-dropdown-item");c&&i().includes(c)&&l(c)}),D(document,"pointerdown",s=>{a()&&!e.contains(s.target)&&r(!1)}),...o.cleanups]},switch:e=>{let t=i=>{e.setAttribute("aria-checked",String(i)),e.dataset.state=i?"checked":"unchecked"},n=()=>{let i=e.getAttribute("aria-checked")!=="true";t(i),Se(e,i)};return e.hasAttribute("aria-checked")||t(!1),[D(e,"click",n),D(e,"keydown",i=>{i.key!=="Enter"&&i.key!==" "||(i.preventDefault(),n())})]},modal(e){let t=e.dataset.mlEscape!=="false",n=e.dataset.mlOverlay!=="false",i=null,o=()=>{},r=()=>document.querySelector(`.ml-modal-overlay[data-ml-for="${e.id}"], .ml-sheet-overlay[data-ml-for="${e.id}"]`),a=()=>{e.dataset.state="closed",e.hidden=!0;let s=r();s&&(s.hidden=!0),o(),o=()=>{},i&&document.contains(i)&&i.focus()},l=s=>{i=s??document.activeElement,e.dataset.state="open",e.hidden=!1;let c=r();c&&(c.hidden=!1),o(),o=Ze(),(Qe(e)[0]??e).focus()};return e.mlolaDialog={open:l,close:a},[D(document,"click",s=>{let c=s.target.closest(`[data-ml-opens="${e.id}"]`);if(c){s.preventDefault(),l(c);return}let d=s.target.closest(".ml-modal-close, .ml-sheet-close, [data-ml-close]");d&&e.contains(d)&&a(),n&&s.target===r()&&a()}),D(document,"keydown",s=>{if(e.hidden)return;if(s.key==="Escape"&&t&&!s.defaultPrevented){s.preventDefault(),a();return}if(s.key!=="Tab")return;let c=Qe(e),d=Ke(c.length,c.indexOf(document.activeElement),s.shiftKey);d<0||(s.preventDefault(),c[d].focus())})]},select(e){let t=e.querySelector(".ml-select"),n=e.querySelector(".ml-select-popover"),i=e.querySelector(".ml-select-list");if(!t||!n||!i)return[];let o=i.getAttribute("aria-multiselectable")==="true",r=()=>[...i.querySelectorAll(".ml-select-option")].filter(h=>h.getAttribute("aria-disabled")!=="true"),a=Te(n,t,()=>({side:"bottom",align:"start",offset:6,minWidth:t.offsetWidth})),l=h=>{if(t.dataset.state=h?"open":"closed",h?a.show():a.hide(),t.setAttribute("aria-expanded",String(h)),!h){for(let g of r())delete g.dataset.highlighted;t.removeAttribute("aria-activedescendant")}},s=()=>t.dataset.state==="open",c=h=>{for(let g of r())delete g.dataset.highlighted;h&&(h.dataset.highlighted="",h.id&&t.setAttribute("aria-activedescendant",h.id))},d=h=>{if(!h)return;let g=h.getAttribute("aria-selected")==="true";if(!o)for(let q of r())q.setAttribute("aria-selected","false"),q.dataset.state="unchecked";let y=o?!g:!0;h.setAttribute("aria-selected",String(y)),h.dataset.state=y?"checked":"unchecked";let I=e.querySelector(".ml-select-value"),E=q=>q.dataset.value??q.textContent.trim();I&&!o&&(I.textContent=h.textContent.trim(),delete I.dataset.placeholder),Se(e,o?r().filter(q=>q.dataset.state==="checked").map(E):E(h)),o||(l(!1),t.focus())};return l(!1),[D(t,"click",()=>l(!s())),D(i,"click",h=>d(h.target.closest(".ml-select-option"))),D(i,"pointermove",h=>{let g=h.target.closest(".ml-select-option");g&&r().includes(g)&&c(g)}),D(e,"keydown",h=>{let g=r();if(h.key==="Escape"){if(!s())return;h.preventDefault(),l(!1),t.focus();return}if(h.key==="Tab"){l(!1);return}if(h.key==="ArrowDown"||h.key==="ArrowUp"){if(h.preventDefault(),!s()){l(!0),c(g[h.key==="ArrowDown"?0:g.length-1]);return}let y=g.findIndex(E=>"highlighted"in E.dataset),I=ye(g,y,h.key,{horizontal:!1});I>=0&&c(g[I]);return}if(h.key==="Home"||h.key==="End"){if(!s())return;h.preventDefault(),c(h.key==="Home"?g[0]:g[g.length-1]);return}if(h.key==="Enter"||h.key===" "&&h.target!==e.querySelector(".ml-select-search")){if(h.preventDefault(),!s()){l(!0);return}d(g.find(y=>"highlighted"in y.dataset))}}),D(document,"pointerdown",h=>{s()&&!e.contains(h.target)&&l(!1)}),...a.cleanups]},slider(e){let t=e.querySelector(".ml-slider-track"),n=e.querySelector(".ml-slider-range"),i=e.querySelector(".ml-slider-thumb"),o=e.querySelector('[role="slider"]');if(!t||!o)return[];let r=()=>({min:Number(o.getAttribute("aria-valuemin")??0),max:Number(o.getAttribute("aria-valuemax")??100),step:Number(e.dataset.mlStep??1)}),a=e.dataset.disabled!==void 0||o.getAttribute("aria-disabled")==="true",l=e.querySelector(".ml-slider-output"),s=()=>Number(o.getAttribute("aria-valuenow")??r().min),c=y=>{let I=r(),E=he(y,I);o.setAttribute("aria-valuenow",String(E));let q=_e(E,I);n&&(n.style.width=`${q}%`),i&&(i.style.left=`${q}%`),l&&(l.textContent=String(E)),Se(e,E)},d=y=>{let I=t.getBoundingClientRect();return I.width?Ge((y.clientX-I.left)/I.width,r()):s()},h=e.querySelector(".ml-slider")??t,g=null;return[D(h,"pointerdown",y=>{if(a||y.button!==0)return;let I=y.pointerType==="touch";g={id:y.pointerId,touch:I,x:y.clientX,y:y.clientY,active:!I},I||(h.setPointerCapture?.(y.pointerId),c(d(y))),o.focus()}),D(h,"pointermove",y=>{if(!(a||!g||g.id!==y.pointerId)){if(!g.active){if(!Je(y.clientX-g.x,y.clientY-g.y))return;g.active=!0,h.setPointerCapture?.(y.pointerId)}c(d(y))}}),D(h,"pointerup",y=>{let I=g;g=null,h.releasePointerCapture?.(y.pointerId),!a&&I?.touch&&!I.active&&c(d(y))}),D(h,"pointercancel",()=>{g=null}),D(o,"keydown",y=>{if(a)return;let I=Ue(y.key,s(),r());I!==void 0&&(y.preventDefault(),c(I))})]},tooltip(e){let t=e.querySelector(".ml-tooltip"),n=e.firstElementChild;if(!t||!n)return[];let i=Number(e.dataset.mlDelay??200),o=t.dataset.side||"top",r=Te(t,n,()=>({side:o}),Ye),a=null,l=()=>{clearTimeout(a),a=setTimeout(()=>{t.dataset.state="open",r.show(),t.id&&n.setAttribute("aria-describedby",t.id)},Math.max(0,i))},s=()=>{clearTimeout(a),r.hide(),delete t.dataset.state,n.removeAttribute("aria-describedby")};return s(),[...r.cleanups,D(e,"pointerenter",l),D(e,"pointerleave",s),D(e,"focusin",l),D(e,"focusout",s),D(document,"keydown",c=>{c.key!=="Escape"||t.hidden||c.defaultPrevented||(c.preventDefault(),s())},!0)]},toast(e){let t=new Map,n=s=>Number(s.dataset.mlDuration??e.dataset.mlDuration??5e3),i=s=>{let c=t.get(s);c&&clearTimeout(c),t.delete(s),s.remove(),e.querySelector(".ml-toast")||e.dispatchEvent(new CustomEvent("ml-empty",{bubbles:!0}))},o=s=>{if("mlPaused"in s.dataset)return;let c=n(s),d=t.get(s);d&&clearTimeout(d),c>0&&t.set(s,setTimeout(()=>i(s),c))},r=s=>{s.dataset.mlEnhanced===void 0&&(s.dataset.mlEnhanced="",o(s))},a=()=>[...e.querySelectorAll(".ml-toast")];e.hasAttribute("role")||e.setAttribute("role","region"),e.showPopover&&(e.popover="manual",e.showPopover());for(let s of a())r(s);let l=new MutationObserver(s=>{for(let c of s)for(let d of c.addedNodes){if(d.nodeType!==1)continue;let h=d.matches?.(".ml-toast")?[d,...d.querySelectorAll(".ml-toast")]:[...d.querySelectorAll(".ml-toast")];for(let g of h)r(g)}});return l.observe(e,{childList:!0,subtree:!0}),[D(e,"click",s=>{let c=s.target.closest(".ml-toast");!c||!e.contains(c)||s.target.closest(".ml-toast-close")&&(s.preventDefault(),i(c))}),D(e,"pointerenter",s=>{let c=s.target.closest(".ml-toast");c&&(c.dataset.mlPaused="",o(c))},!0),D(e,"pointerleave",s=>{let c=s.target.closest(".ml-toast");c&&(delete c.dataset.mlPaused,o(c))},!0),D(e,"focusin",s=>{let c=s.target.closest(".ml-toast");c&&(c.dataset.mlPaused="",o(c))}),D(e,"focusout",s=>{let c=s.target.closest(".ml-toast");c&&(delete c.dataset.mlPaused,o(c))}),()=>{l.disconnect();for(let s of t.values())clearTimeout(s)}]}};Le.sheet=Le.modal;function et(e=document){let t=[...e.matches?.("[data-ml]")?[e]:[],...e.querySelectorAll("[data-ml]")],n=0;for(let i of t){if(i[Ae])continue;let o=Le[i.dataset.ml];if(!o)continue;let r=o(i)??[];i[Ae]=()=>{for(let a of r)a();delete i[Ae]},n+=1}return n}var pe=["createSurface","updateComponents","updateDataModel","deleteSurface"],xt=new Set(["id","component","accessibility"]),$t=new Set(["style","className","class","css","color","background","backgroundColor","theme","sx","tw"]),Ce=new Set(["__proto__","prototype","constructor"]),At=/^[A-Za-z][A-Za-z0-9_.:-]{0,63}$/,St=/^[A-Za-z0-9_-]{1,64}$/,Tt=/^(\d{4})-(\d{2})-(\d{2})$/,ie=e=>{let t=typeof e=="string"?Tt.exec(e):null;if(!t)return!1;let[n,i,o]=t.slice(1).map(Number),r=new Date(Date.UTC(n,i-1,o));return r.getUTCFullYear()===n&&r.getUTCMonth()===i-1&&r.getUTCDate()===o};var P=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),ce=(e,t)=>Object.hasOwn(e,t)?e[t]:void 0,Z=e=>e===null?"null":Array.isArray(e)?"an array":typeof e=="object"?"an object":`a ${typeof e}`,b=e=>e!==null&&typeof e=="object"?Z(e):typeof e=="string"&&e.length>80?JSON.stringify(`${e.slice(0,77)}\u2026`):String(JSON.stringify(e)),Lt=e=>String(e).replaceAll("~","~0").replaceAll("/","~1"),w=(e,...t)=>t.reduce((n,i)=>`${n}/${Lt(i)}`,e),ne=e=>e.map(t=>b(t)).join(", "),tt=e=>e.endsWith("s")?`${e}'`:`${e}'s`,nt=e=>e.endsWith("s")?e:`${e}s`,rt,Mt=globalThis[rt=Symbol.for("mlola-ui.render.kinds")]??(globalThis[rt]={kinds:new Map,reads:new Set}),{kinds:ot,reads:Ct}=Mt;var It=e=>({...e.align?{align:e.align}:{},...e.fields});function it(e,t){if(typeof e!="string")return{messages:e,error:null};if(t&&e.length>t.inputBytes)return{messages:null,error:`The input is ${e.length} characters; at most ${t.inputBytes} are checked at a time. Send fewer messages per call.`};let n=e.trim();if(!n)return{messages:null,error:"The input is empty. Pass A2UI messages: one object, an array, or one object per line."};try{return{messages:JSON.parse(n),error:null}}catch(i){let o=n.split(`
8478
- `).map(r=>r.trim()).filter(Boolean);if(o.length>1){let r=[];for(let[a,l]of o.entries())try{r.push(JSON.parse(l))}catch(s){return{messages:null,error:`Line ${a+1} is not JSON: ${s.message}`}}return{messages:r,error:null}}return{messages:null,error:`The input is not JSON: ${i.message}`}}}function Ie(e){return{rules:e,surfaces:new Map}}function st(e,t){let n={errors:[],advice:[]},i=P(t),o=i?[t]:t;if(!Array.isArray(o))return n.errors.push(p("","",`Expected A2UI messages: an object with "version" and one of ${pe.join(", ")}, or an array of them. Got ${Z(t)}.`)),n;let{limits:r}=e.rules;if(o.length||n.errors.push(p("","","There are no messages. Start with createSurface, then updateComponents.")),o.length>r.messages)return n.errors.push(p("","",`At most ${r.messages} messages are checked at a time; this is ${o.length}. Check the rest in another call.`)),n;for(let[a,l]of o.entries())Ot(e,l,i?"":`/${a}`,n);return n}function at(e,t){let n={errors:[],advice:[]},i=e.surfaces.get(t);if(!i||i.deleted)return n;n.errors.push(...i.problems);for(let o of i.components.values())lt(e.rules,i.id,o.props,o.at,n);return i.components.size&&Yt(e.rules,i,n),n}function p(e,t,n){return{code:"VALIDATION_FAILED",surfaceId:e??"",path:t,message:n}}function Me(e,t,n){return{code:"ADVICE",surfaceId:e??"",path:t,message:n}}function Ot(e,t,n,i){let{rules:o}=e;if(!P(t)){i.errors.push(p("",n,`A message is an object with "version" and one of ${pe.join(", ")}; this one is ${Z(t)}.`));return}let r=pe.filter(h=>h in t),a=r.length===1&&P(t[r[0]])&&typeof t[r[0]].surfaceId=="string"?t[r[0]].surfaceId:"";if(o.protocolVersions.includes(t.version)||i.errors.push(p(a,w(n,"version"),t.version===void 0?`Add "version": ${b(o.protocolVersions.at(-1))} to every message.`:`Version ${b(t.version)} is not supported; use ${ne(o.protocolVersions)}.`)),r.length!==1){i.errors.push(p(a,n,r.length?`A message carries one of ${pe.join(", ")}; this one has ${r.join(" and ")}. Send them as separate messages.`:`A message carries one of ${pe.join(", ")}; this one has none.`));return}for(let h of Object.keys(t))h!=="version"&&h!==r[0]&&i.errors.push(p(a,w(n,h),`A message holds only "version" and ${b(r[0])}; remove ${b(h)}.`));let l=r[0],s=t[l],c=w(n,l);if(!P(s)){i.errors.push(p("",c,`${l} is an object; got ${Z(s)}.`));return}let d=s.surfaceId;if(typeof d!="string"||!d.trim()||d.length>o.limits.idLength){i.errors.push(p("",w(c,"surfaceId"),`${l} needs a "surfaceId": a string of 1 to ${o.limits.idLength} characters that names the surface.`));return}if(l==="createSurface")qt(e,s,c,i);else{let h=e.surfaces.get(d);if(!h||h.deleted){i.errors.push(p(d,w(c,"surfaceId"),h?.deleted?`Surface ${b(d)} was deleted; send createSurface again before ${l}.`:`No surface is called ${b(d)}. Send createSurface for it first, in the same messages.`));return}l==="updateComponents"?Et(o,h,s,c,i):l==="updateDataModel"?Dt(o,h,s,c,i):jt(e,h,s,c,i)}}function oe(e,t,n,i,o,r){for(let a of Object.keys(e))t.includes(a)||o.errors.push(p(i,w(n,a),`${r} does not take ${b(a)}. It takes ${ne(t)}.`))}function qt(e,t,n,i){let{rules:o}=e,{surfaceId:r}=t,a=i.errors.length;oe(t,["surfaceId","catalogId","theme","sendDataModel"],n,r,i,"createSurface"),t.catalogId!==o.catalogId&&i.errors.push(p(r,w(n,"catalogId"),`Set "catalogId" to ${b(o.catalogId)}: this renderer draws the Mlola catalog${typeof t.catalogId=="string"?`, not ${b(t.catalogId)}`:""}.`)),t.sendDataModel!==void 0&&typeof t.sendDataModel!="boolean"&&i.errors.push(p(r,w(n,"sendDataModel"),'"sendDataModel" is true or false.'));let l={name:o.defaultTheme,mode:"system"};if(t.theme!==void 0){let d=w(n,"theme");if(!P(t.theme))i.errors.push(p(r,d,`"theme" is an object like {"name": ${b(o.defaultTheme)}, "mode": "system"}.`));else{for(let h of Object.keys(t.theme))h==="name"||h==="mode"||i.errors.push(p(r,w(d,h),/color|font|radius|spacing|icon/i.test(h)?`Colors, type and shape come from the theme; pick one by name instead of setting ${b(h)}: ${ne(o.themes)}.`:`"theme" takes "name" and "mode"; remove ${b(h)}.`));t.theme.name!==void 0&&(o.themes.includes(t.theme.name)?l.name=t.theme.name:i.errors.push(p(r,w(d,"name"),`Theme ${b(t.theme.name)} does not exist; use ${ne(o.themes)}.`))),t.theme.mode!==void 0&&(o.modes.includes(t.theme.mode)?l.mode=t.theme.mode:i.errors.push(p(r,w(d,"mode"),`Mode ${b(t.theme.mode)} does not exist; use ${ne(o.modes)} (system follows the reader's setting).`)))}}let s=e.surfaces.get(r);if(s&&!s.deleted){i.errors.push(p(r,w(n,"surfaceId"),`Surface ${b(r)} already exists. Use another surfaceId, or send deleteSurface first.`));return}let c=0;for(let d of e.surfaces.values())d.deleted||(c+=1);if(c>=o.limits.surfaces){i.errors.push(p(r,n,`At most ${o.limits.surfaces} surfaces are open at once; send deleteSurface for one that is done.`));return}e.surfaces.delete(r),e.surfaces.set(r,{id:r,theme:l,sendDataModel:t.sendDataModel===!0,deleted:!1,components:new Map,data:{},dataBytes:0,at:n,problems:i.errors.slice(a)})}function jt(e,t,n,i,o){oe(n,["surfaceId"],i,t.id,o,"deleteSurface"),t.deleted=!0,t.components=new Map,t.data={},t.dataBytes=0;let r=[...e.surfaces.values()].filter(a=>a.deleted);for(let a of r.slice(0,Math.max(0,r.length-e.rules.limits.surfaces)))e.surfaces.delete(a.id)}function Et(e,t,n,i,o){oe(n,["surfaceId","components"],i,t.id,o,"updateComponents");let r=w(i,"components");if(!Array.isArray(n.components)||!n.components.length){o.errors.push(p(t.id,r,'"components" is a non-empty array of components, each with an "id" and a "component".'));return}if(n.components.length>e.limits.components){o.errors.push(p(t.id,r,`This message sends ${n.components.length} components; a surface holds at most ${e.limits.components}. Split it into more surfaces.`));return}let a=new Set;for(let[l,s]of n.components.entries()){let c=w(r,l);if(!P(s)){o.errors.push(p(t.id,c,`A component is an object with "id" and "component"; got ${Z(s)}.`));continue}let{id:d}=s;if(typeof d!="string"||!d.trim()||d.length>e.limits.idLength){o.errors.push(p(t.id,w(c,"id"),`Every component needs an "id": a string of 1 to ${e.limits.idLength} characters, unique on the surface.`));continue}if(a.has(d)){o.errors.push(p(t.id,w(c,"id"),`Two components in this message have the id ${b(d)}; give each its own.`));continue}if(a.add(d),!t.components.has(d)&&t.components.size>=e.limits.components){o.errors.push(p(t.id,c,`A surface holds at most ${e.limits.components} components; split it into more surfaces.`));break}let h=lt(e,t.id,s,c,o);t.components.set(d,{id:d,type:s.component,props:s,definition:h,at:c})}}function Dt(e,t,n,i,o){oe(n,["surfaceId","path","value"],i,t.id,o,"updateDataModel");let r=n.path??"/",a=w(i,"path");if(typeof r!="string"||r!==""&&!qe(r,{absolute:!0,rules:e})){o.errors.push(p(t.id,a,'"path" is a JSON Pointer like "/form/email", or "/" for the whole data model.'));return}let l=0,s;try{let d=n.value===void 0?void 0:JSON.stringify(n.value);s=d===void 0?void 0:JSON.parse(d),l=t.dataBytes-Pt(ge(t.data,r))+(d?.length??0)}catch{o.errors.push(p(t.id,w(i,"value"),"This value is nested too deeply to read; flatten it."));return}if(l>e.limits.dataBytes){o.errors.push(p(t.id,w(i,"value"),`A surface's data model holds at most ${e.limits.dataBytes} bytes of JSON; send less, or page through it.`));return}let c=Ee(t.data,r,s);if(c.error){o.errors.push(p(t.id,a,c.error));return}t.data=c.root,t.dataBytes=l}var Pt=e=>e===void 0?0:JSON.stringify(e)?.length??0;function lt(e,t,n,i,o){let r=n.component,a=w(i,"component");if(typeof r!="string"||!r)return o.errors.push(p(t,a,'Every component names its type in "component", for example "Stack", "Text" or "Button".')),null;let l=ce(e.components,r);if(!l)return o.errors.push(p(t,a,Bt(e,r))),null;for(let[s,c]of Object.entries(n)){if(xt.has(s))continue;let d=ce(l.props,s),h=w(i,s);if(!d){o.errors.push(p(t,h,Rt(e,r,l,s)));continue}Wt(e,t,r,s,d,c,h,o)}for(let[s,c]of Object.entries(l.props))c.required&&n[s]===void 0&&o.errors.push(p(t,i,`${r} needs ${b(s)}${c.description?`: ${Nt(c.description)}`:"."}`));return n.accessibility!==void 0&&Ft(e,t,n.accessibility,w(i,"accessibility"),o),Kt(e,t,r,l,n,i,o),l}var Nt=e=>e.charAt(0).toLowerCase()+e.slice(1);function Bt(e,t){let n=ce(e.aliases,t)??Object.keys(e.components).find(o=>o.toLowerCase()===t.toLowerCase());if(n)return`${b(t)} is not in the Mlola catalog; use ${b(n)}.`;let i=ce(e.borrowed.components,t);return i?`${b(t)} is not in the Mlola catalog. ${i}`:`${b(t)} is not in the Mlola catalog. It has: ${zt(e).map(([o,r])=>`${o} (${r.join(", ")})`).join("; ")}.`}function zt(e){return Object.entries(e.groups).map(([t,n])=>[n,Object.keys(e.components).filter(i=>e.components[i].group===t)])}function Rt(e,t,n,i){let o=Object.keys(n.props),r=ce(e.borrowed.props,`${t}.${i}`)??ce(e.borrowed.props,i);return r?`${t} does not take ${b(i)}. ${r}`:$t.has(i)?`${t} takes no ${b(i)}: Mlola Render draws with the surface's theme. Choose a named value instead (${o.filter(a=>n.props[a].kind==="enum").join(", ")||"none on this component"}).`:i==="child"&&o.includes("children")?`${t} takes "children", an array of ids, not "child".`:i==="checks"?'Client-side checks are not in the Mlola catalog yet; use "required" on the field, and check the values when the action arrives.':/^on[A-Z]/.test(i)?`${t} does not take ${b(i)}. A Button's "action" sends an event to the agent; inputs bind their value with {"path": \u2026}.`:`${t} does not take ${b(i)}. It takes: ${o.join(", ")}.`}function Ft(e,t,n,i,o){if(!P(n)){o.errors.push(p(t,i,'"accessibility" is an object with "label" and "description".'));return}for(let[r,a]of Object.entries(n)){if(r!=="label"&&r!=="description"){o.errors.push(p(t,w(i,r),`"accessibility" takes "label" and "description"; remove ${b(r)}.`));continue}Oe(e,t,a,w(i,r),{maxLength:e.limits.labelLength},!1,o)}}function Wt(e,t,n,i,o,r,a,l){switch(o.kind){case"text":return Oe(e,t,r,a,o,o.required,l,`${n} ${b(i)}`);case"boolean":return typeof r=="boolean"||!o.literal&&le(e,t,r,a,l)?void 0:l.errors.push(p(t,a,`${n} ${b(i)} is true or false${o.literal?"":', or {"path": "/\u2026"}'}; got ${Z(r)}.`));case"number":return typeof r=="number"&&Number.isFinite(r)||!o.literal&&le(e,t,r,a,l)?void 0:l.errors.push(p(t,a,`${n} ${b(i)} is a number${o.literal?"":' or {"path": "/\u2026"}'}; got ${Z(r)}.`));case"integer":return Number.isInteger(r)&&r>=o.minimum&&r<=o.maximum?void 0:l.errors.push(p(t,a,`${n} ${b(i)} is a whole number from ${o.minimum} to ${o.maximum}; got ${b(r)}.`));case"date":return ie(r)||!o.literal&&le(e,t,r,a,l)?void 0:l.errors.push(p(t,a,`${n} ${b(i)} is a day written as an ISO date, like "2026-10-12"${o.literal?"":', or {"path": "/\u2026"}'}; got ${b(r)}.`));case"enum":return typeof r=="string"&&o.values.includes(r)?void 0:l.errors.push(p(t,a,Ht(e,n,i,o,r)));case"children":return Gt(e,t,n,i,o,r,a,l);case"action":return _t(e,t,r,a,l);case"options":return Ut(e,t,n,o,r,a,l);case"columns":return Jt(e,t,n,i,o,r,a,l);case"rows":return Vt(e,t,i,o,r,a,l);default:return ot.has(o.kind)?ot.get(o.kind).check(e,t,n,i,o,r,a,l):l.errors.push(p(t,a,`${n} ${b(i)} has a kind this validator does not know (${o.kind}); import @mlola-ui/behavior/render/data first.`))}}function Ht(e,t,n,i,o){if(typeof o=="string"){let r=i.values.find(l=>l.toLowerCase()===o.toLowerCase());if(r)return`${t} ${b(n)} is ${b(r)}, not ${b(o)}: values are case-sensitive.`;let a=ce(e.borrowed.props,`${t}.${n}=${o}`);if(a)return`${t} ${b(n)} ${b(o)} is not in the catalog. ${a}`;if(i.excluded?.includes(o))return`${t} ${b(n)} ${b(o)} is not in the catalog: ${i.description??"it needs content the catalog does not offer."} Use ${ne(i.values)}.`}return`${t} ${b(n)} ${typeof o=="string"?`${b(o)} does not exist`:`is a name, not ${Z(o)}`}; use ${ne(i.values)}.`}function Oe(e,t,n,i,o,r,a,l="This text"){if(typeof n=="string"){let s=o.maxLength??e.limits.textLength;n.length>s?a.errors.push(p(t,i,`${l} is ${n.length} characters; keep it to ${s}.`)):r&&!n.trim()&&a.errors.push(p(t,i,`${l} is empty. It is what a person sees and a screen reader reads; write the words.`));return}if(!le(e,t,n,i,a)){if(P(n)&&"call"in n){a.errors.push(p(t,i,'Functions are not in the Mlola catalog yet; use a literal string or {"path": "/\u2026"}.'));return}a.errors.push(p(t,i,`${l} is a string or {"path": "/\u2026"}; got ${Z(n)}.`))}}function le(e,t,n,i,o){if(!P(n)||!("path"in n))return!1;let r=Object.keys(n).filter(a=>a!=="path");return r.length&&o.errors.push(p(t,i,`A binding holds only "path"; remove ${ne(r)}.`)),(typeof n.path!="string"||!qe(n.path,{rules:e}))&&o.errors.push(p(t,w(i,"path"),`${b(n.path)} is not a data path. Write a JSON Pointer like "/form/email" (or "name" inside a template), at most ${e.limits.pathLength} characters.`)),!0}function qe(e,{absolute:t=!1,rules:n}){if(!e||e.length>n.limits.pathLength)return!1;if(t&&e==="/")return!0;if(t&&!e.startsWith("/"))return!1;let i=(e.startsWith("/")?e.slice(1):e).split("/");for(let o of i)if(/~(?![01])/.test(o)||Ce.has(je(o)))return!1;return!0}var je=e=>e.replaceAll("~1","/").replaceAll("~0","~");function Gt(e,t,n,i,o,r,a,l){if(Array.isArray(r)){r.length<(o.minItems??0)&&l.errors.push(p(t,a,`${n} needs at least ${o.minItems} ${o.minItems===1?"child":"children"}.`)),r.length>e.limits.components&&l.errors.push(p(t,a,`${n} lists ${r.length} children; a surface holds at most ${e.limits.components} components.`));let s=new Set;for(let[c,d]of r.entries())typeof d!="string"||!d?l.errors.push(p(t,w(a,c),`A child is a component id (a string); got ${Z(d)}.`)):s.has(d)?l.errors.push(p(t,w(a,c),`${b(d)} is listed twice in ${n}'s children; a component appears in one place.`)):s.add(d);return}if(P(r)&&("componentId"in r||"path"in r)){oe(r,["componentId","path"],a,t,l,"A template"),(typeof r.componentId!="string"||!r.componentId)&&l.errors.push(p(t,w(a,"componentId"),'A template names the component to repeat in "componentId".')),(typeof r.path!="string"||!qe(r.path,{rules:e}))&&l.errors.push(p(t,w(a,"path"),`A template's "path" points at an array in the data model, like "/items".`));return}l.errors.push(p(t,a,`${n} ${b(i)} is an array of component ids, or a template {"componentId", "path"}; got ${Z(r)}.`))}function _t(e,t,n,i,o){if(!P(n)){o.errors.push(p(t,i,`"action" is {"event": {"name": "\u2026", "context": {\u2026}}}; got ${Z(n)}.`));return}if("functionCall"in n){o.errors.push(p(t,w(i,"functionCall"),'Client-side functions are not in the Mlola catalog yet; send an event and handle it in the agent: {"event": {"name": "\u2026"}}.'));return}oe(n,["event"],i,t,o,"An action");let r=n.event,a=w(i,"event");if(!P(r)){o.errors.push(p(t,a,'An action sends an event: {"name": "\u2026", "context": {\u2026}}.'));return}if(oe(r,["name","context"],a,t,o,"An event"),(typeof r.name!="string"||!At.test(r.name))&&o.errors.push(p(t,w(a,"name"),`An event's "name" starts with a letter and uses letters, digits, _ . : or - (at most 64), like "create_workspace".`)),r.context===void 0)return;let l=w(a,"context");if(!P(r.context)){o.errors.push(p(t,l,`An event's "context" is an object of values or {"path": \u2026} bindings.`));return}let s=Object.keys(r.context);s.length>e.limits.contextKeys&&o.errors.push(p(t,l,`An event's context holds at most ${e.limits.contextKeys} values; bind a whole object with {"path": "/form"} instead.`));for(let c of s.slice(0,e.limits.contextKeys)){let d=r.context[c],h=w(l,c);Ce.has(c)?o.errors.push(p(t,h,`${b(c)} cannot be a context key.`)):P(d)&&!le(e,t,d,h,o)?o.errors.push(p(t,h,'A context value is a string, number, boolean, array or {"path": \u2026}; an object needs a binding.')):Array.isArray(d)&&d.some(g=>g!==null&&typeof g=="object")?o.errors.push(p(t,h,'An array in the context holds strings, numbers and true or false; for a list from the data model use {"path": "/\u2026"}.')):typeof d=="string"&&d.length>e.limits.textLength&&o.errors.push(p(t,h,`This value is ${d.length} characters; keep it to ${e.limits.textLength}.`))}}function Ut(e,t,n,i,o,r,a){if(le(e,t,o,r,a))return;if(!Array.isArray(o)){a.errors.push(p(t,r,`${n} "options" is an array of {"label", "value"}, or {"path": "/\u2026"}; got ${Z(o)}.`));return}if(o.length<(i.minItems??1)&&a.errors.push(p(t,r,`${n} needs at least ${i.minItems} options${n==="RadioGroup"?"; for one yes or no choice use a Checkbox":""}.`)),o.length>e.limits.options){a.errors.push(p(t,r,`${n} lists ${o.length} options; keep it to ${e.limits.options}.`));return}let l=new Set;for(let[s,c]of o.entries()){let d=w(r,s);if(!P(c)){a.errors.push(p(t,d,`An option is {"label": "\u2026", "value": "\u2026"}; got ${Z(c)}.`));continue}oe(c,["label","value"],d,t,a,"An option"),(typeof c.label!="string"||!c.label.trim()||c.label.length>e.limits.labelLength)&&a.errors.push(p(t,w(d,"label"),`An option's "label" is the words a person picks, 1 to ${e.limits.labelLength} characters.`)),typeof c.value!="string"||!c.value||c.value.length>e.limits.labelLength?a.errors.push(p(t,w(d,"value"),`An option's "value" is the string sent back, 1 to ${e.limits.labelLength} characters.`)):l.has(c.value)?a.errors.push(p(t,w(d,"value"),`Two options have the value ${b(c.value)}; give each its own.`)):l.add(c.value)}}function Jt(e,t,n,i,o,r,a,l){let s=o.item??"column",c=It(o);if(!Array.isArray(r)||r.length<(o.minItems??1)){l.errors.push(p(t,a,`${b(i)} is a non-empty array of {"key", "label"${Object.keys(c).map(g=>`, ${b(g)}?`).join("")}}.`));return}let d=o.maxItems??e.limits.columns;if(r.length>d){l.errors.push(p(t,a,o.maxItems?`${n} takes at most ${d} ${nt(s)}; this is ${r.length}.`:`A table shows at most ${d} columns; more cannot be read on a phone.`));return}let h=new Set;for(let[g,y]of r.entries()){let I=w(a,g);if(!P(y)){l.errors.push(p(t,I,`A ${s} is {"key": "\u2026", "label": "\u2026"}; got ${Z(y)}.`));continue}oe(y,["key","label",...Object.keys(c)],I,t,l,`A ${s}`),typeof y.key!="string"||!St.test(y.key)||Ce.has(y.key)?l.errors.push(p(t,w(I,"key"),`A ${tt(s)} "key" names the row field it shows: letters, digits, _ or -, like "order".`)):h.has(y.key)?l.errors.push(p(t,w(I,"key"),`Two ${nt(s)} have the key ${b(y.key)}.`)):h.add(y.key),Oe(e,t,y.label,w(I,"label"),{maxLength:e.limits.labelLength},!0,l,`The ${tt(s)} "label"`);for(let[E,q]of Object.entries(c)){let x=y[E];x===void 0||(q.values?q.values.includes(x):typeof x=="boolean")||l.errors.push(p(t,w(I,E),q.values?`${b(E)} is ${ne(q.values)}.`:`${b(E)} is true or false.`))}}}function Vt(e,t,n,i,o,r,a){if(le(e,t,o,r,a))return;if(!Array.isArray(o)){a.errors.push(p(t,r,`${b(n)} is an array of objects, or {"path": "/\u2026"} to one in the data model; got ${Z(o)}.`));return}if(o.length<(i.minItems??0)){a.errors.push(p(t,r,`${b(n)} needs at least ${i.minItems} ${i.minItems===1?"row":"rows"}.`));return}let l=Math.min(i.maxItems??e.limits.rows,e.limits.rows);if(o.length>l){a.errors.push(p(t,r,`${b(n)} holds at most ${l} rows; ${i.maxItems?"keep the ones that matter":"page through the rest"}.`));return}for(let[s,c]of o.entries()){let d=w(r,s);if(!P(c)){a.errors.push(p(t,d,`A row is an object of its fields, like {"name": "\u2026"}; got ${Z(c)}.`));continue}for(let[h,g]of Object.entries(c))g===null||typeof g=="number"||typeof g=="boolean"||typeof g=="string"&&g.length<=e.limits.textLength||a.errors.push(p(t,w(d,h),typeof g=="string"?`A cell holds at most ${e.limits.textLength} characters.`:`A cell holds text, a number or true/false; got ${Z(g)}.`))}}function Kt(e,t,n,i,o,r,a){let l=s=>typeof o[s]=="number"?o[s]:i.props[s]?.default;if(n==="Slider"){let s=l("min"),c=l("max"),d=l("step");typeof s=="number"&&typeof c=="number"&&s>=c&&a.errors.push(p(t,w(r,"max"),`Slider "max" (${c}) must be greater than "min" (${s}).`)),typeof d=="number"&&(d<=0||d>c-s)&&a.errors.push(p(t,w(r,"step"),'Slider "step" is greater than 0 and at most max minus min.')),typeof o.value=="number"&&(o.value<s||o.value>c)&&a.errors.push(p(t,w(r,"value"),`Slider "value" ${o.value} is outside ${s} to ${c}.`))}if(n==="Progress"){let s=l("max");typeof s=="number"&&s<=0&&a.errors.push(p(t,w(r,"max"),'Progress "max" is greater than 0.')),typeof o.value=="number"&&(o.value<0||o.value>s)&&a.errors.push(p(t,w(r,"value"),`Progress "value" ${o.value} is outside 0 to ${s}.`))}if(n==="DatePicker"){let{min:s,max:c,value:d}=o;ie(s)&&ie(c)&&s>c?a.errors.push(p(t,w(r,"max"),`DatePicker "max" (${c}) comes before "min" (${s}); make it the later day.`)):ie(d)&&(ie(s)&&d<s||ie(c)&&d>c)&&a.errors.push(p(t,w(r,"value"),`DatePicker "value" ${d} is outside ${ie(s)?s:"any day"} to ${ie(c)?c:"any day"}.`))}if((n==="Select"||n==="RadioGroup")&&typeof o.value=="string"&&Array.isArray(o.options)){let s=o.options.filter(P).map(c=>c.value);s.includes(o.value)||a.errors.push(p(t,w(r,"value"),`${n} "value" ${b(o.value)} is not one of its options (${ne(s)}).`))}for(let s of Ct)s(t,n,i,o,r,a)}function fe(e){let t=e.props.children;return Array.isArray(t)?{ids:t.filter(n=>typeof n=="string"),template:null}:P(t)&&typeof t.componentId=="string"?{ids:[t.componentId],template:t}:{ids:[],template:null}}function Yt(e,t,n){let{components:i}=t,o=i.get("root");if(!o){n.errors.push(p(t.id,t.at,'No component has the id "root". One component is the root of the tree; give it "id": "root".'));return}let r=new Map;for(let d of i.values()){let{ids:h,template:g}=fe(d),y=w(d.at,"children");for(let[I,E]of h.entries()){let q=g?w(y,"componentId"):w(y,I),x=i.get(E);if(!x){n.errors.push(p(t.id,q,`No component has the id ${b(E)}. Add it, or remove it from ${d.type}'s children.`));continue}if(E===d.id){n.errors.push(p(t.id,q,`${b(E)} lists itself as a child: the children form a loop. A component cannot be inside its own tree.`));continue}if(E==="root"){n.errors.push(p(t.id,q,'"root" is the top of the tree and cannot be a child.'));continue}let M=r.get(E);if(M&&M!==d.id){n.errors.push(p(t.id,q,`${b(E)} is already a child of ${b(M)}. A component appears in one place; give the second one its own id.`));continue}r.set(E,d.id),x.definition?.parents&&d.definition&&!x.definition.parents.includes(d.type)&&n.errors.push(p(t.id,q,`${x.type} goes directly inside ${x.definition.parents.join(" or ")}, not inside ${d.type}.`)),d.definition?.accepts&&x.definition&&!d.definition.accepts.includes(x.type)&&n.errors.push(p(t.id,q,`${d.type} holds only ${d.definition.accepts.join(" and ")} components; ${b(E)} is a ${x.type}.`))}}for(let d of i.values())d.definition?.parents&&d.id!=="root"&&!r.has(d.id)&&n.errors.push(p(t.id,d.at,`${d.type} goes directly inside ${d.definition.parents.join(" or ")}; list ${b(d.id)} in one's children.`));let a=new Set(["root"]),l=new Set,s=[],c=[{node:o,depth:1,templated:!1}];for(;c.length;){let{node:d,depth:h,templated:g}=c.pop();if(s.push(d),g&&l.add(d.id),h>e.limits.depth){n.errors.push(p(t.id,d.at,`The tree is more than ${e.limits.depth} levels deep at ${b(d.id)}; flatten it.`));continue}let{ids:y,template:I}=fe(d);for(let E=y.length-1;E>=0;E-=1){let q=i.get(y[E]);if(!(!q||r.get(q.id)!==d.id)){if(a.has(q.id)){n.errors.push(p(t.id,w(d.at,"children"),`${b(q.id)} contains itself: the children form a loop. A component cannot be inside its own tree.`));continue}a.add(q.id),c.push({node:q,depth:h+1,templated:g||!!I})}}}for(let d of i.values())!a.has(d.id)&&!(d.definition?.parents&&!r.has(d.id))&&n.advice.push(Me(t.id,d.at,`${b(d.id)} is not inside "root", so it will not show. List it in a parent's children, or remove it.`));Xt(e,t,s,l,n),Zt(t,s,n)}function Xt(e,t,n,i,o){let r=l=>P(l)&&typeof l.path=="string"&&!l.path.startsWith("/"),a=(l,s)=>o.errors.push(p(t.id,w(s,"path"),`${b(l.path)} is relative, which only works inside a template; write it from the top of the data model, like "/${l.path}".`));for(let l of n)if(!(i.has(l.id)||!l.definition))for(let[s,c]of Object.entries(l.props)){let d=w(l.at,s);if(s==="children")r(c)&&o.errors.push(p(t.id,w(d,"path"),`A template's "path" points at an array from the top of the data model, like "/${c.path}"; a relative path works only inside another template.`));else if(s==="accessibility"&&P(c))for(let h of["label","description"])r(c[h])&&a(c[h],w(d,h));else if(s==="action"&&P(c)&&P(c.event)&&P(c.event.context))for(let[h,g]of Object.entries(c.event.context))r(g)&&a(g,w(d,"event","context",h));else r(c)&&a(c,d)}}function Zt(e,t,n){let i=0,o=null,r=new Map,a=(l,s)=>l.props[s]??l.definition?.props[s]?.default;for(let l of t){if(l.type==="Heading"&&Number.isInteger(a(l,"level"))){let c=a(l,"level");i&&c>i+1&&n.errors.push(p(e.id,w(l.at,"level"),`This heading jumps from level ${i} to ${c}; use ${i+1}. A screen reader uses the levels to move through the surface.`)),i=c}l.type==="Button"&&a(l,"variant")==="primary"&&(o?n.advice.push(Me(e.id,w(l.at,"variant"),`${b(o)} is already the primary action; keep one primary Button per surface and make this one "secondary".`)):o=l.id);let s=typeof l.props.label=="string"?l.props.label.trim().toLowerCase():null;s&&l.definition?.group==="form"&&(r.has(s)?n.advice.push(Me(e.id,w(l.at,"label"),`${b(r.get(s))} has the same label; give each field its own so they can be told apart.`)):r.set(s,l.id))}}var ct=/^(0|[1-9][0-9]{0,5})$/;function ge(e,t){if(t===""||t==="/")return e;let n=e;for(let i of t.slice(1).split("/").map(je)){if(!P(n)&&!Array.isArray(n)||Array.isArray(n)&&!ct.test(i))return;n=Object.hasOwn(n,i)?n[i]:void 0}return n}function Ee(e,t,n){if(t===""||t==="/")return{root:n===void 0?{}:n};let i=t.slice(1).split("/").map(je),o=P(e)||Array.isArray(e)?e:{},r=o;for(let[l,s]of i.entries()){if(Array.isArray(r)&&!ct.test(s))return{error:`${b(i.slice(0,l).join("/")||"/")} holds an array, so the next segment is an index like 0, not ${b(s)}.`};if(Array.isArray(r)&&Number(s)>r.length)return{error:`${b(i.slice(0,l).join("/")||"/")} holds ${r.length} ${r.length===1?"item":"items"}, so the next index is at most ${r.length}, not ${s}.`};if(l===i.length-1)break;!P(r[s])&&!Array.isArray(r[s])&&(r[s]={}),r=r[s]}let a=i.at(-1);return n===void 0?delete r[a]:r[a]=n,{root:o}}var Qt=["createSurface","updateComponents","updateDataModel","deleteSurface"],en=/^(?:\/\d+)?\/(?:createSurface|updateComponents|updateDataModel|deleteSurface)(\/.*)?$/,tn=new Set(["EmptyState","Accordion"]),J=e=>P(e)&&typeof e.path=="string",De=e=>e!==null&&typeof e=="object"?JSON.parse(JSON.stringify(e)):e;function be(e,t=""){return e.startsWith("/")?e:e?`${t}/${e}`:t||"/"}function dt(e,t="v0.9.1"){let n=en.exec(e.path);return{version:t,error:{code:e.code,surfaceId:e.surfaceId,path:n?n[1]||"/":e.path||"/",message:e.message}}}function ut(e,t={}){let n=t,i=Ie(e),o=n.version??e.protocolVersions.at(-1),r=n.now??(()=>new Date),a=new Map,l=new Set,s=new Set,c=0,d=[],h=v=>{n.onError?n.onError(v):d.push(...v)},g=0,y=()=>{c+=1;for(let v of[...l])v()};function I(v){let u=new Map,T=v.get("root");if(!T)return u;let W=new Set(["root"]),L=[T],S=1;for(;L.length;){let A=L.pop();A.type==="Heading"?S=Number.isInteger(A.props.level)?A.props.level:A.definition?.props.level?.default??2:tn.has(A.type)&&u.set(A.id,Math.min(6,S+1));let{ids:G}=fe(A);for(let K=G.length-1;K>=0;K-=1){let Y=v.get(G[K]);Y&&!W.has(Y.id)&&(W.add(Y.id),L.push(Y))}}return u}function E(v,{streaming:u=!1}={}){let T=it(v,e.limits);if(T.error){let S={errors:[{code:"VALIDATION_FAILED",surfaceId:"",path:"",message:T.error}],advice:[]};return h(S.errors.map(A=>dt(A,o))),S}let L=Array.isArray(T.messages)&&!T.messages.length?{errors:[],advice:[]}:st(i,T.messages);for(let S of Array.isArray(T.messages)?T.messages:[T.messages])if(P(S))for(let A of Qt)P(S[A])&&typeof S[A].surfaceId=="string"&&s.add(S[A].surfaceId);for(let S of[...a.keys()]){let A=i.surfaces.get(S);(!A||A.deleted)&&a.delete(S)}if(!u){let S=new Set(L.errors.map(A=>`${A.path}\0${A.message}`));for(let A of s){let G=i.surfaces.get(A);if(!G||G.deleted||!G.components.size)continue;let K=at(i,A);if(K.errors.length){for(let Q of K.errors){let ee=`${Q.path}\0${Q.message}`;S.has(ee)||L.errors.push(Q),S.add(ee)}continue}L.advice.push(...K.advice);let Y=new Map(G.components);g+=1,a.set(A,{components:Y,theme:G.theme,levels:I(Y),missing:a.get(A)?.missing??new Set,structure:g})}s.clear()}return L.errors.length&&h(L.errors.map(S=>dt(S,o))),y(),L}let q=v=>a.get(v)??null,x=v=>i.surfaces.get(v)?.data;function M(v,u,T=""){return J(u)?ge(x(v),be(u.path,T)):u}function C(v,u,T=""){let W=q(v),L=W?.components.get(u);if(!L)return[];let{ids:S,template:A}=fe(L);if(!A)return S.filter(Q=>W.components.has(Q)).map(Q=>({id:Q,scope:T,key:`${Q}@${T}`}));if(!W.components.has(A.componentId))return[];let G=be(A.path,T),K=ge(x(v),G);if(!Array.isArray(K))return[];let Y=G==="/"?"":G;return K.slice(0,e.limits.components).map((Q,ee)=>({id:A.componentId,scope:`${Y}/${ee}`,key:`${A.componentId}@${Y}/${ee}`}))}function j(v,u,T,W=""){let L=i.surfaces.get(v);if(!L||L.deleted||!J(u))return!1;let S=be(u.path,W),A=Ee(L.data,S,T);if(A.error)return!1;L.data=A.root;let G=q(v);if(G?.missing.size)for(let K of[...G.missing])K.endsWith(`|${S}`)&&G.missing.delete(K);return y(),!0}function*B(v,u="root",T="",W=0){let L=q(v)?.components.get(u);if(!(!L||W>e.limits.depth)){yield{node:L,scope:T};for(let S of C(v,u,T))yield*B(v,S.id,S.scope,W+1)}}let V=v=>v==null||v===!1||typeof v=="string"&&!v.trim();function se(v,u,T=""){let W=q(v),S=W?.components.get(u)?.props.action?.event;if(!W||!P(S))return{sent:null,missing:[]};let A=P(S.context)?S.context:{},G=Object.values(A).filter(J).map(_=>be(_.path,T)),K=_=>G.some(U=>U==="/"||U===_||_.startsWith(`${U}/`)),Y=[];for(let _ of B(v)){let{props:U,definition:ae}=_.node;if(ae?.group!=="form"||M(v,U.required,_.scope)!==!0)continue;let re=J(U.value)?U.value:J(U.checked)?U.checked:null;if(!re)continue;let ue=be(re.path,_.scope);K(ue)&&V(ge(x(v),ue))&&Y.push({id:_.node.id,scope:_.scope,key:`${_.node.id}@${_.scope}`,path:ue,label:M(v,U.label,_.scope)})}if((Y.length||G.length)&&(W.missing=new Set(Y.map(_=>`${_.key}|${_.path}`))),Y.length)return y(),{sent:null,missing:Y};let Q={version:o,action:{name:S.name,surfaceId:v,sourceComponentId:u,timestamp:r().toISOString(),context:Object.fromEntries(Object.entries(A).map(([_,U])=>[_,De(M(v,U,T))??null]))}},ee=i.surfaces.get(v);return n.onAction?.(Q,ee?.sendDataModel?{dataModel:De(ee.data)}:{}),y(),{sent:Q,missing:[]}}return{rules:e,receive:E,surfaces:()=>[...a.keys()],surface:v=>a.has(v)?{id:v,theme:a.get(v).theme}:null,component:(v,u)=>q(v)?.components.get(u)??null,children:C,read:M,write:j,press:se,missing:(v,u,T="")=>{let W=q(v);if(!W?.missing.size)return!1;let L=`${u}@${T}|`;for(let S of W.missing)if(S.startsWith(L))return!0;return!1},structure:v=>q(v)?.structure??0,headingLevel:(v,u)=>q(v)?.levels.get(u)??2,configure:v=>{if(n={...n,...v},n.onError&&d.length){let u=d;d=[],n.onError(u)}},reset:()=>{i=Ie(e),a.clear(),s.clear(),y()},dataModel:v=>De(x(v)),subscribe:v=>(l.add(v),()=>l.delete(v)),revision:()=>c}}var ht={info:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><circle cx="12" cy="12" r="9.5" pathLength="1"></circle><path d="M12 11v6M12 7h.01" pathLength="1"></path></svg>',success:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><circle cx="12" cy="12" r="9.5" pathLength="1"></circle><path d="m7.5 12 3 3 6-6" pathLength="1"></path></svg>',warning:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><path d="m10.3 3.8-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.7-3.2l-8-14a2 2 0 0 0-3.4 0Z" pathLength="1"></path><path d="M12 9v4M12 17h.01" pathLength="1"></path></svg>',danger:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><circle cx="12" cy="12" r="9.5" pathLength="1"></circle><path d="m9 9 6 6M15 9l-6 6" pathLength="1"></path></svg>',check:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><polyline points="20 6 9 17 4 12" pathLength="1"></polyline></svg>',chevron:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><polyline points="6 9 12 15 18 9" pathLength="1"></polyline></svg>'};var nn={required:"Fill in this field.",missing:e=>`Fill in ${e.join(", ")} first.`,yes:"Yes",no:"No"},X=e=>e==null?"":String(e),mt=e=>e!=null&&e!=="",me=(e,t)=>`${e}-${Array.from(t,n=>/[A-Za-z0-9_-]/.test(n)?n:`_${n.codePointAt(0)?.toString(16)}`).join("")}`,on=0;function f(e,t={},...n){let i=document.createElement(e);for(let[o,r]of Object.entries(t))r==null||r===!1||i.setAttribute(o,r===!0?"":String(r));for(let o of n.flat())o!=null&&o!==!1&&i.append(o);return i}function ke(e,t){let n=document.createElement("span");n.innerHTML=ht[e];let i=n.firstElementChild;return t&&i.classList.add(t),i}function pt(e,t={}){let n=t.host??ut(t.rules,{onAction:t.onAction,onError:t.onError}),i={...nn,...t.labels},o=`ml-render-${on+=1}`,r=f("div",{class:"ml-render"}),a=f("p",{role:"status",class:"ml-visually-hidden"});r.append(a),e.append(r);let l=new Map,s=x=>x.mode==="system"&&t.systemMode?t.systemMode:x.mode;function c(){let x=t.surfaceId?n.surface(t.surfaceId)?[t.surfaceId]:[]:n.surfaces();for(let[C,j]of l)x.includes(C)||(j.node.remove(),l.delete(C));t.streaming?r.setAttribute("aria-busy","true"):r.removeAttribute("aria-busy");for(let C of x){let j=l.get(C);if(j&&j.structure===n.structure(C)&&j.lists.every(V=>V.count()===V.length)){for(let V of j.updaters)V();continue}let B=g(C,j);j?j.node.replaceWith(B.node):r.insertBefore(B.node,a),l.set(C,B),et(B.node),h(B.node,B.kept)}let M=a;for(let C of[...x].reverse()){let j=l.get(C).node;j.nextSibling!==M&&r.insertBefore(j,M),M=j}}function d(x){let M=x.contains(document.activeElement)?document.activeElement:null;return{focus:M?.id??null,selection:M&&"selectionStart"in M?[M.selectionStart,M.selectionEnd]:null,tabs:[...x.querySelectorAll('.ml-tabs-trigger[aria-selected="true"]')].map(C=>C.id),open:[...x.querySelectorAll('.ml-accordion-item[data-state="open"] .ml-accordion-trigger')].map(C=>C.id)}}function h(x,M){if(!M)return;for(let j of M.tabs)document.getElementById(j)?.click();for(let j of x.querySelectorAll(".ml-accordion-trigger"))M.open.includes(j.id)!==(j.getAttribute("aria-expanded")==="true")&&j.click();let C=M.focus?document.getElementById(M.focus):null;if(C&&(C.focus(),M.selection&&"setSelectionRange"in C))try{C.setSelectionRange(...M.selection)}catch{}}function g(x,M){let C=M?d(M.node):null,j=n.surface(x),B=t.theme==="inherit"?null:j.theme,V=f("div",{class:"ml-render-surface","data-surface":x,"data-theme":B?.name,"data-mode":B?s(B):null,"data-themed":B?!0:null}),se={surfaceId:x,base:`${o}-${x}`,updaters:[],lists:[]};return V.append(...E(se,{id:"root",scope:"",key:"root@"})),{node:V,structure:n.structure(x),lists:se.lists,updaters:se.updaters,kept:C}}function y(x,M,C){let j=n.component(x.surfaceId,M),B=n.children(x.surfaceId,M,C);return j&&!Array.isArray(j.props.children)&&j.props.children&&x.lists.push({length:B.length,count:()=>n.children(x.surfaceId,M,C).length}),B}function I(x,M,C){let{missing:j}=n.press(x,M,C);if(a.textContent=j.length?i.missing(j.map(V=>X(V.label))):"",!j.length)return;let B=document.getElementById(me(`${o}-${x}`,j[0].key));(B?.matches("input, textarea, button, [tabindex]")?B:B?.querySelector("input, textarea, button, [tabindex]"))?.focus()}function E(x,M){let{surfaceId:C,updaters:j}=x,{id:B,scope:V,key:se}=M,v=n.component(C,B);if(!v)return[];let u=v.props,T=m=>n.read(C,m,V),W=(m,k)=>n.write(C,m,k,V),L=me(x.base,se),S=m=>{m(),j.push(m)},A=(m,k)=>(S(()=>{m.textContent=X(T(k))}),m),G=()=>y(x,B,V).flatMap(m=>E(x,m)),K=u.accessibility??{},Y=m=>(S(()=>{let k=X(T(K.label)),$=X(T(K.description));k?m.setAttribute("aria-label",k):m.removeAttribute("aria-label"),$?m.setAttribute("aria-description",$):m.removeAttribute("aria-description")}),m),Q=m=>K.label===void 0?m:(m.setAttribute("role","group"),Y(m)),ee=()=>Array.isArray(T(u.options))?T(u.options).filter(m=>typeof m?.label=="string"&&typeof m?.value=="string"&&m.value):[],_=()=>{if(!J(u.options))return;let m=()=>JSON.stringify(ee());x.lists.push({length:m(),count:m})},U=()=>T(u.disabled)===!0,ae=()=>T(u.required)===!0,re=(m,k)=>{let $=f("p",{id:`${L}-error`,role:"alert",class:"ml-input-error",hidden:!0});return S(()=>{let O=n.missing(C,B,V);$.hidden=!O,$.textContent=O?i.required:"",m.toggleAttribute("data-invalid",O),O?k.setAttribute("aria-invalid","true"):k.removeAttribute("aria-invalid");let z=[mt(u.hint)?`${L}-hint`:null,O?`${L}-error`:null].filter(Boolean).join(" ");z?k.setAttribute("aria-describedby",z):k.removeAttribute("aria-describedby")}),$},ue=m=>{let k=f("label",{id:`${m}-label`,for:m,class:"ml-input-label"}),$=document.createTextNode(""),O=f("span",{"aria-hidden":"true",class:"ml-required-mark"},"*");return k.append($),S(()=>{$.textContent=X(T(u.label)),ae()?k.append(O):O.remove()}),k},Re=()=>mt(u.hint)?A(f("p",{id:`${L}-hint`,class:"ml-input-hint"}),u.hint):null,Fe=m=>(J(u.value)?(S(()=>{let k=X(T(u.value));m.value!==k&&(m.value=k)}),m.addEventListener("input",()=>W(u.value,m.value))):m.value=X(u.value),S(()=>{m.disabled=U(),m.required=ae()}),m);switch(v.type){case"Stack":return[Q(f("div",{class:"ml-stack"},G()))];case"Row":return[Q(f("div",{class:"ml-cluster"},G()))];case"Grid":return[Q(f("div",{class:"ml-grid","data-columns":u.columns},G()))];case"Heading":return[A(f(`h${u.level??2}`),u.text)];case"Text":return[A(f("p",{class:"ml-render-text"}),u.text)];case"Card":return[Q(f("div",{class:"ml-card","data-variant":u.variant??"default"},f("div",{class:"ml-card-content ml-stack"},G())))];case"Alert":{let m=u.tone??"neutral";return[f("div",{class:"ml-alert",role:m==="danger"||m==="warning"?"alert":"status","data-tone":m,"data-variant":u.variant??"card","data-state":"open"},f("span",{"aria-hidden":"true",class:"ml-alert-icon"},ke(m==="neutral"?"info":m)),f("div",{class:"ml-alert-content"},u.title!==void 0?A(f("p",{class:"ml-alert-title"}),u.title):null,A(f("div",{class:"ml-alert-description"}),u.text)))]}case"EmptyState":{let m=u.children!==void 0?G():[];return[f("section",{class:"ml-empty","data-size":u.size??"inline"},A(f(`h${n.headingLevel(C,B)}`,{class:"ml-empty-title"}),u.title),u.description!==void 0?A(f("p",{class:"ml-empty-description"}),u.description):null,m.length?f("div",{class:"ml-empty-actions"},m):null)]}case"Tabs":{let m=y(x,B,V);if(!m.length)return[];let k=f("div",{class:"ml-tabs-list",role:"tablist","aria-orientation":"horizontal"});S(()=>k.setAttribute("aria-label",X(T(u.label))));let $=[];for(let[O,z]of m.entries()){let N=me(x.base,`${z.key}-tab`),H=me(x.base,`${z.key}-panel`),R=O===0,F=f("button",{class:"ml-tabs-trigger",id:N,type:"button",role:"tab","aria-selected":String(R),"aria-controls":H,tabindex:R?"0":"-1","data-state":R?"active":"inactive"});S(()=>{F.textContent=X(n.read(C,n.component(C,z.id)?.props.label,z.scope))}),k.append(F),$.push(f("div",{class:"ml-tabs-content ml-stack",id:H,role:"tabpanel","aria-labelledby":N,tabindex:"0",hidden:!R,"data-state":R?"active":"inactive"},y(x,z.id,z.scope).flatMap(te=>E(x,te))))}return[f("div",{class:"ml-tabs","data-ml":"tabs","data-variant":u.variant??"default","data-orientation":"horizontal"},k,$)]}case"Accordion":{let m=n.headingLevel(C,B),k=y(x,B,V).map($=>{let O=me(x.base,`${$.key}-trigger`),z=me(x.base,`${$.key}-panel`),N=f("span",{class:"ml-accordion-trigger-label"});return S(()=>{N.textContent=X(n.read(C,n.component(C,$.id)?.props.title,$.scope))}),f("div",{class:"ml-accordion-item","data-state":"closed"},f(`h${m}`,{class:"ml-accordion-heading"},f("button",{class:"ml-accordion-trigger",id:O,type:"button","aria-expanded":"false","aria-controls":z,"data-state":"closed"},N,ke("chevron","ml-accordion-chevron"))),f("div",{class:"ml-accordion-panel",id:z,role:"region","aria-labelledby":O,"data-state":"closed",hidden:!0},f("div",{class:"ml-accordion-panel-inner ml-stack"},y(x,$.id,$.scope).flatMap(H=>E(x,H)))))});return[f("div",{class:"ml-accordion","data-ml":"accordion","data-ml-multiple":u.type==="multiple"?"true":null},k)]}case"Tab":case"AccordionItem":return[];case"Input":case"DatePicker":{let m=Fe(f("input",{class:"ml-input",id:L,type:v.type==="DatePicker"?"date":u.type??"text","data-variant":u.variant??"default","data-size":u.size??"md",maxlength:v.type==="Input"?n.rules.limits.textLength:null,min:u.min,max:u.max}));v.type==="DatePicker"&&J(u.value)&&m.addEventListener("change",()=>W(u.value,m.value||null)),S(()=>{let $=X(T(u.placeholder));$?m.setAttribute("placeholder",$):m.removeAttribute("placeholder")});let k=f("div",{class:"ml-input-field"});return k.append(ue(L),f("div",{class:"ml-input-control"},m),...[Re()].filter(Boolean),re(k,m)),[k]}case"Textarea":{let m=Fe(f("textarea",{class:"ml-textarea",id:L,rows:u.rows??4,maxlength:n.rules.limits.textLength}));S(()=>{let $=X(T(u.placeholder));$?m.setAttribute("placeholder",$):m.removeAttribute("placeholder")});let k=f("div",{class:"ml-input-field"});return k.append(ue(L),m,...[Re()].filter(Boolean),re(k,m)),[k]}case"Select":{let m=`${L}-label`,k=`${L}-list`,$=f("span",{class:"ml-select-value"}),O=f("button",{class:"ml-select",id:L,type:"button",role:"combobox","aria-haspopup":"listbox","aria-expanded":"false","aria-controls":k,"aria-labelledby":m,"data-size":u.size??"md","data-state":"closed"},$,ke("chevron","ml-select-chevron")),z=f("ul",{class:"ml-select-list",id:k,role:"listbox","aria-labelledby":m});_();for(let[H,R]of ee().entries())z.append(f("li",{class:"ml-select-option",id:`${L}-option-${H}`,role:"option","data-value":R.value,"aria-selected":"false","data-state":"unchecked"},R.label));let N=f("div",{class:"ml-select-root","data-ml":"select"},A(f("span",{class:"ml-select-label",id:m}),u.label),f("div",{class:"ml-select-control"},O),f("div",{class:"ml-select-popover"},z));return S(()=>{let H=X(T(u.value)),R=ee().find(F=>F.value===H);$.textContent=R?R.label:X(T(u.placeholder))||"\xA0",$.toggleAttribute("data-placeholder",!R);for(let F of z.children){let te=F.dataset.value===H;F.setAttribute("aria-selected",String(te)),F.dataset.state=te?"checked":"unchecked"}O.disabled=U(),ae()?O.setAttribute("aria-required","true"):O.removeAttribute("aria-required")}),J(u.value)&&N.addEventListener("ml-change",H=>W(u.value,H.detail.value)),N.append(re(N,O)),[N]}case"RadioGroup":{let m=`${L}-label`;_();let k=ee(),$=k.map((R,F)=>f("input",{class:"ml-radio-input",id:`${L}-${F}`,type:"radio",name:L,value:R.value})),O=k.map((R,F)=>f("label",{class:"ml-radio-item",for:`${L}-${F}`,"data-state":"unchecked"},f("span",{class:"ml-radio-control"},$[F],f("span",{class:"ml-radio-indicator","aria-hidden":"true"})),f("span",{class:"ml-radio-copy"},f("span",{class:"ml-radio-label"},R.label)))),z=u.orientation??"vertical",N=f("div",{class:"ml-radio-group",id:L,role:"radiogroup","aria-labelledby":m,"aria-orientation":z,"data-orientation":z},A(f("div",{class:"ml-radio-group-label",id:m}),u.label),f("div",{class:"ml-radio-group-items"},O)),H=X(u.value);S(()=>{let R=J(u.value)?X(T(u.value)):H;for(let[F,te]of $.entries())te.checked=te.value===R,te.disabled=U(),O[F].dataset.state=te.checked?"checked":"unchecked";ae()?N.setAttribute("aria-required","true"):N.removeAttribute("aria-required")});for(let R of $)R.addEventListener("change",()=>{if(J(u.value))W(u.value,R.value);else{H=R.value;for(let F of j)F()}});return N.append(re(N,N)),[N]}case"Checkbox":{let m=f("input",{class:"ml-checkbox-input",id:L,type:"checkbox"}),k=f("span",{class:"ml-checkbox-copy"},f("label",{class:"ml-checkbox-label",for:L},A(f("span",{class:"ml-checkbox-text"}),u.label)),u.description!==void 0?A(f("span",{class:"ml-checkbox-description",id:`${L}-description`}),u.description):null),$=f("div",{class:"ml-checkbox-field","data-state":"unchecked"},f("label",{class:"ml-checkbox-control","data-hit":"expand"},m,f("span",{class:"ml-checkbox-indicator","aria-hidden":"true"},ke("check"))),k);return J(u.checked)||(m.checked=u.checked===!0),S(()=>{J(u.checked)&&(m.checked=T(u.checked)===!0),m.disabled=U(),m.required=ae(),$.dataset.state=m.checked?"checked":"unchecked"}),m.addEventListener("change",()=>{J(u.checked)&&W(u.checked,m.checked),$.dataset.state=m.checked?"checked":"unchecked"}),$.append(re($,m)),[$]}case"Switch":{let m=`${L}-label`,k=f("button",{class:"ml-toggle",id:L,type:"button",role:"switch","data-ml":"switch","aria-checked":String(J(u.checked)?T(u.checked)===!0:u.checked===!0),"aria-labelledby":m,"data-size":u.size??"md","data-hit":"expand"},f("span",{class:"ml-toggle-thumb","aria-hidden":"true"}));return k.dataset.state=k.getAttribute("aria-checked")==="true"?"checked":"unchecked",S(()=>{if(J(u.checked)){let $=T(u.checked)===!0;k.setAttribute("aria-checked",String($)),k.dataset.state=$?"checked":"unchecked"}k.disabled=U()}),J(u.checked)&&k.addEventListener("ml-change",$=>W(u.checked,$.detail.value)),[f("span",{class:"ml-switch-field"},k,A(f("span",{class:"ml-switch-label",id:m}),u.label))]}case"Slider":{let m=u.min??0,k=u.max??100,$=`${L}-label`,O=f("span",{class:"ml-slider-output"}),z=f("span",{class:"ml-slider-range","aria-hidden":"true"}),N=f("span",{class:"ml-slider-thumb",id:L,role:"slider",tabindex:"0","aria-labelledby":$,"aria-valuemin":m,"aria-valuemax":k}),H=f("div",{class:"ml-slider-field","data-ml":"slider","data-size":u.size??"md","data-ml-step":u.step??1},f("div",{class:"ml-slider-header"},A(f("span",{class:"ml-slider-label",id:$}),u.label),O),f("div",{class:"ml-slider"},f("div",{class:"ml-slider-track"},z,N))),R=typeof u.value=="number"?u.value:m;return S(()=>{let F=J(u.value)?T(u.value):R,te=typeof F=="number"&&Number.isFinite(F)?Math.min(k,Math.max(m,F)):m,We=k>m?(te-m)/(k-m)*100:0;N.setAttribute("aria-valuenow",String(te)),O.textContent=String(te),z.style.width=`${We}%`,N.style.left=`${We}%`,U()?(H.dataset.disabled="",N.setAttribute("aria-disabled","true")):(delete H.dataset.disabled,N.removeAttribute("aria-disabled"))}),H.addEventListener("ml-change",F=>{J(u.value)?W(u.value,F.detail.value):R=F.detail.value}),[H]}case"Button":{let m=A(f("span",{class:"ml-button-label"}),u.text),k=Y(f("button",{class:"ml-button",id:L,type:"button","data-variant":u.variant??"primary","data-size":u.size??"md","data-width":u.width==="full"?"full":null},m));return S(()=>{k.disabled=U()}),k.addEventListener("click",()=>I(C,B,V)),[k]}case"Badge":return[f("span",{class:"ml-badge","data-tone":u.tone??"neutral","data-variant":u.variant??"soft","data-size":u.size??"md"},A(f("span",{class:"ml-badge-label"}),u.text))];case"Progress":{let m=u.max??100,k=f("span",{class:"ml-progress-value","aria-hidden":"true"}),$=f("div",{class:"ml-progress-fill","aria-hidden":"true"}),O=f("div",{class:"ml-progress-track",role:"progressbar","aria-valuemin":"0","aria-valuemax":m},$),z=A(f("span"),u.label),N=f("div",{class:"ml-progress-label"},z,k);return S(()=>{let H=T(u.value),R=typeof H=="number"&&Number.isFinite(H)?Math.min(m,Math.max(0,H)):0,F=Math.round(R/m*100);O.setAttribute("aria-valuenow",String(R)),O.setAttribute("aria-valuetext",`${F}%`),O.setAttribute("aria-label",X(T(u.label))),$.style.width=`${F}%`,k.textContent=`${F}%`,k.hidden=T(u.showLabel)!==!0}),[f("div",{class:"ml-progress-root","data-tone":u.tone??"primary","data-size":u.size??"md","data-state":"determinate"},N,O)]}case"Avatar":{let m=f("span",{class:"ml-avatar-fallback",role:"img"}),k=u.status?f("span",{class:"ml-avatar-status",role:"status","data-status":u.status}):null;return S(()=>{let $=X(T(u.name));m.setAttribute("aria-label",$),m.textContent=$.replace(/[^\p{L}\p{N}\s]/gu,"").trim().split(/\s+/).filter(Boolean).slice(0,2).map(O=>O[0].toUpperCase()).join(""),k?.setAttribute("aria-label",`${$} is ${u.status}`)}),[f("span",{class:"ml-avatar-root","data-size":u.size??"md"},f("span",{class:"ml-avatar"},m),k)]}case"Table":{let m=Array.isArray(u.columns)?u.columns:[],k=f("tbody",{class:"ml-table-body"}),$=A(f("caption",{class:"ml-table-caption"}),u.caption),O=f("div",{class:"ml-table-container"},f("table",{class:"ml-table","data-size":u.size??"md"},$,f("thead",{class:"ml-table-header"},f("tr",{class:"ml-table-row"},m.map(z=>A(f("th",{class:"ml-table-head",scope:"col","data-align":z.align??"left"}),z.label)))),k));return S(()=>{O.setAttribute("aria-label",X(T(u.caption)));let z=T(u.rows);k.replaceChildren(...(Array.isArray(z)?z.slice(0,n.rules.limits.rows):[]).map(N=>f("tr",{class:"ml-table-row"},m.map(H=>f("td",{class:"ml-table-cell","data-align":H.align??"left"},rn(N,H.key,i)))))),queueMicrotask(()=>{let N=O.scrollWidth>O.clientWidth+1;N?O.setAttribute("tabindex","0"):O.removeAttribute("tabindex"),O.setAttribute("role",N?"region":"presentation"),N||O.removeAttribute("role")})}),[O]}default:return[]}}let q=n.subscribe(c);return c(),{host:n,receive:(x,M={})=>(t.streaming=!!M.streaming,n.receive(x,M)),setSystemMode:x=>{if(t.systemMode=x??void 0,t.theme!=="inherit")for(let[M,C]of l){let j=n.surface(M)?.theme;j&&(C.node.dataset.mode=s(j))}},destroy:()=>{q(),r.remove()}}}function rn(e,t,n){let i=e!==null&&typeof e=="object"&&Object.hasOwn(e,t)?e[t]:void 0;return typeof i=="boolean"?i?n.yes:n.no:typeof i=="string"||typeof i=="number"?String(i):"\u2014"}var Pe={version:"1.13.2",catalogId:"https://ui.mlola.com/a2ui/catalog/v1",title:"Mlola Render catalog",description:"Mlola UI components for interfaces an agent composes at runtime. Every component is accessible by construction and follows the surface's theme; an agent picks named values (tone, variant, size) and never writes a color, size or class.",protocolVersions:["v0.9","v0.9.1"],themes:["graphite","atelier","machined","aerogel","nordic"],defaultTheme:"graphite",modes:["light","dark","system"],groups:{layout:"Layout",text:"Text",container:"Containers",form:"Forms",action:"Actions",data:"Data"},limits:{messages:200,surfaces:20,components:300,depth:24,idLength:128,textLength:4e3,labelLength:120,options:100,columns:12,rows:500,contextKeys:32,pathLength:512,dataBytes:262144,inputBytes:1048576},components:{Stack:{group:"layout",description:"Places its children in a column with the theme's spacing. Use it as the root of most surfaces.",mlola:{class:"ml-stack"},props:{children:{kind:"children",required:!0,description:"The components inside, top to bottom."}}},Row:{group:"layout",description:"Places its children side by side and wraps them on a narrow screen. Use it for a row of buttons or badges.",mlola:{class:"ml-cluster"},props:{children:{kind:"children",required:!0,description:"The components inside, start to end."}}},Grid:{group:"layout",description:"Places its children in equal columns that collapse to one column on a phone.",mlola:{class:"ml-grid"},props:{children:{kind:"children",required:!0,description:"The components inside, in reading order."},columns:{kind:"enum",description:"How many columns on a wide screen. Leave it out to fit as many as the width allows.",values:["1","2","3","4","6"]}}},Heading:{group:"text",description:"A heading. Levels follow the page outline: never skip a level going deeper.",mlola:{element:"h1-h6"},props:{text:{kind:"text",required:!0,description:"The heading's words.",maxLength:120},level:{kind:"integer",description:"The outline level, 1 to 6. Inside a chat a surface usually starts at 2.",minimum:1,maximum:6,default:2}}},Text:{group:"text",description:"A paragraph of plain text.",mlola:{element:"p"},props:{text:{kind:"text",required:!0,description:"The words. Line breaks are kept; markup is shown as text."}}},Card:{group:"container",description:"Groups related content on a surface of its own.",mlola:{item:"card",export:"Card"},props:{children:{kind:"children",required:!0,description:"The card's content."},variant:{kind:"enum",description:"How the card stands off the page.",values:["default","elevated","glass","specular"],default:"default"}}},Alert:{group:"container",description:"A message about the surface: a confirmation, a warning or an error. Warnings and errors interrupt a screen reader; calmer tones are announced politely.",mlola:{item:"alert",export:"Alert"},props:{title:{kind:"text",description:"A short summary, read first.",maxLength:120},text:{kind:"text",required:!0,description:"What happened and what to do about it."},tone:{kind:"enum",description:"What the message means.",values:["neutral","info","success","warning","danger"],default:"neutral"},variant:{kind:"enum",description:"A card, or a tinted band across the surface.",values:["card","soft"],default:"card"}}},EmptyState:{group:"container",description:"Says that there is nothing here yet and what to do next.",mlola:{item:"empty-state",export:"EmptyState"},props:{title:{kind:"text",required:!0,description:"What is empty, in a few words.",maxLength:120},description:{kind:"text",description:"What to do next."},children:{kind:"children",description:"Actions, usually one or two Buttons."},size:{kind:"enum",description:"inline inside a surface, page when it fills one.",values:["inline","page"],default:"inline"}}},Tabs:{group:"container",description:"Shows one panel at a time, chosen from a row of tabs. Its children are Tab components.",accepts:["Tab"],mlola:{item:"tabs",export:"Tabs"},props:{label:{kind:"text",required:!0,description:"What the tabs choose between, for a screen reader.",maxLength:120},children:{kind:"children",required:!0,description:"The Tab components, in order.",minItems:1},variant:{kind:"enum",description:"The look of the tab row.",values:["default","pills","enclosed"],default:"default"}}},Tab:{group:"container",description:"One tab of a Tabs: its name and its panel.",parents:["Tabs"],mlola:{item:"tabs",export:"TabsTrigger"},props:{label:{kind:"text",required:!0,description:"The tab's name.",maxLength:120},children:{kind:"children",required:!0,description:"What the panel shows."}}},Accordion:{group:"container",description:"A list of sections that open and close. Its children are AccordionItem components.",accepts:["AccordionItem"],mlola:{item:"accordion",export:"Accordion"},props:{children:{kind:"children",required:!0,description:"The AccordionItem components, in order.",minItems:1},type:{kind:"enum",description:"single keeps one section open at a time; multiple lets several stay open.",values:["single","multiple"],default:"single"}}},AccordionItem:{group:"container",description:"One section of an Accordion: its title and its content.",parents:["Accordion"],mlola:{item:"accordion",export:"AccordionItem"},props:{title:{kind:"text",required:!0,description:"The section's title, which opens and closes it.",maxLength:120},children:{kind:"children",required:!0,description:"The section's content."}}},Input:{group:"form",description:"A one-line text field with its label.",mlola:{item:"input",export:"Input"},props:{label:{kind:"text",required:!0,description:"The field's name, shown above it and read by a screen reader.",maxLength:120},value:{kind:"text",description:'Bind it to the data model ({"path": "/form/email"}) so the value comes back with the action.'},type:{kind:"enum",description:"The kind of text, which picks the phone keyboard and the browser's checks.",values:["text","email","password","url","tel","search"],default:"text"},placeholder:{kind:"text",description:"An example of what to type. Never a replacement for the label.",maxLength:120},hint:{kind:"text",description:"Help shown under the field.",maxLength:120},required:{kind:"boolean",description:"The form cannot be sent without it."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"},variant:{kind:"enum",description:"How the field sits on its surface.",values:["default","filled","subtle"],default:"default"}}},Textarea:{group:"form",description:"A text field for several lines, with its label.",mlola:{item:"textarea",export:"Textarea"},props:{label:{kind:"text",required:!0,description:"The field's name.",maxLength:120},value:{kind:"text",description:"Bind it to the data model so the value comes back with the action."},placeholder:{kind:"text",description:"An example of what to type. Never the only label.",maxLength:120},hint:{kind:"text",description:"A short help line under the field.",maxLength:120},rows:{kind:"integer",description:"How many lines show before it scrolls.",minimum:2,maximum:12,default:4},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Select:{group:"form",description:"Picks one value from a list that opens on demand. Use RadioGroup when there are only two to five options and room to show them.",mlola:{item:"select",export:"Select"},props:{label:{kind:"text",required:!0,description:"The field's name.",maxLength:120},options:{kind:"options",required:!0,description:'The choices, each {"label", "value"}.',minItems:1},value:{kind:"text",description:"The chosen option's value. Bind it to the data model."},placeholder:{kind:"text",description:"Shown while nothing is chosen.",maxLength:120},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},RadioGroup:{group:"form",description:"Picks one value from options that are all visible.",mlola:{item:"radio-group",export:"RadioGroup"},props:{label:{kind:"text",required:!0,description:"The question the options answer.",maxLength:120},options:{kind:"options",required:!0,description:'The choices, each {"label", "value"}.',minItems:2},value:{kind:"text",description:"The chosen option's value. Bind it to the data model."},orientation:{kind:"enum",description:"Options stacked or in a row.",values:["horizontal","vertical"],default:"vertical"},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Checkbox:{group:"form",description:"A yes or no choice with its label.",mlola:{item:"checkbox",export:"Checkbox"},props:{label:{kind:"text",required:!0,description:"What checking it means.",maxLength:120},checked:{kind:"boolean",description:"Bind it to the data model so the choice comes back with the action."},description:{kind:"text",description:"More about the choice, under the label.",maxLength:120},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Switch:{group:"form",description:"Turns a setting on or off right away.",mlola:{item:"toggle",export:"Switch"},props:{label:{kind:"text",required:!0,description:"The setting it turns on.",maxLength:120},checked:{kind:"boolean",description:"Bind it to the data model."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},Slider:{group:"form",description:"Picks a number in a range by dragging or with the arrow keys.",mlola:{item:"slider",export:"Slider"},props:{label:{kind:"text",required:!0,description:"What the number is.",maxLength:120},value:{kind:"number",description:"Bind it to the data model."},min:{kind:"number",description:"The lowest value.",literal:!0,default:0},max:{kind:"number",description:"The highest value.",literal:!0,default:100},step:{kind:"number",description:"How far one arrow press moves it.",literal:!0,default:1},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md"],default:"md"}}},DatePicker:{group:"form",description:"A date field that opens a calendar and picks one day. The reader sees the date in their own format; the value is an ISO date.",mlola:{item:"date-picker",export:"DatePicker"},props:{label:{kind:"text",required:!0,description:"The field's name.",maxLength:120},value:{kind:"date",description:'The chosen day as an ISO date, like "2026-10-12". Bind it to the data model so it comes back with the action.'},min:{kind:"date",description:"The earliest day that can be picked.",literal:!0},max:{kind:"date",description:"The latest day that can be picked.",literal:!0},hint:{kind:"text",description:"Help shown under the field.",maxLength:120},required:{kind:"boolean",description:"The form cannot be sent without it."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Button:{group:"action",description:'Sends an action back to the agent. Its text says what happens ("Create workspace", not "Submit").',mlola:{item:"button",export:"Button"},props:{text:{kind:"text",required:!0,description:"What pressing it does.",maxLength:120},action:{kind:"action",required:!0,description:"The event sent when it is pressed."},variant:{kind:"enum",description:"primary for the main action of a surface, one at most.",values:["primary","secondary","subtle","danger","outline","link"],default:"primary"},size:{kind:"enum",description:"Icon-only buttons are not in the catalog: every button has words.",values:["sm","md","lg"],excluded:["icon"],default:"md"},width:{kind:"enum",description:"auto fits the words, full fills the container.",values:["auto","full"],default:"auto"},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Badge:{group:"data",description:"A short label for a status or a count.",mlola:{item:"badge",export:"Badge"},props:{text:{kind:"text",required:!0,description:"The badge's words, a few at most.",maxLength:120},tone:{kind:"enum",description:"What the status means.",values:["neutral","primary","info","success","warning","danger"],default:"neutral"},variant:{kind:"enum",description:"How strongly the badge stands out.",values:["soft","solid","outline"],default:"soft"},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},Progress:{group:"data",description:"Shows how far along something is.",mlola:{item:"progress",export:"Progress"},props:{label:{kind:"text",required:!0,description:"What is in progress, for a screen reader.",maxLength:120},value:{kind:"number",description:"How far along, from 0 to max."},max:{kind:"number",description:"The value that means complete.",literal:!0,default:100},showLabel:{kind:"boolean",description:"Shows the percentage beside the bar."},tone:{kind:"enum",description:"What the progress means.",values:["primary","info","success","warning","danger"],default:"primary"},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},Avatar:{group:"data",description:"A person or a team shown by their initials.",mlola:{item:"avatar",export:"Avatar"},props:{name:{kind:"text",required:!0,description:"The full name: the initials come from it and a screen reader reads it.",maxLength:120},size:{kind:"enum",description:"The avatar's size.",values:["xs","sm","md","lg","xl"],default:"md"},status:{kind:"enum",description:"A presence dot, announced with the name.",values:["online","offline","away","busy"]}}},Table:{group:"data",description:"Rows of data under named columns. Cells hold text and numbers.",mlola:{item:"table",export:"Table"},props:{caption:{kind:"text",required:!0,description:"What the table shows, read first by a screen reader.",maxLength:120},columns:{kind:"columns",required:!0,description:'Each {"key", "label", "align"?}: key names the row field the column shows.',minItems:1,align:{values:["left","center","right"]}},rows:{kind:"rows",required:!0,description:"An array of objects keyed by column key, or a path to one in the data model."},size:{kind:"enum",description:"Row density.",values:["sm","md"],default:"md"}}}},aliases:{Column:"Stack",List:"Stack",TextField:"Input",CheckBox:"Checkbox",ChoicePicker:"Select",Toggle:"Switch",Label:"Text",Paragraph:"Text",Title:"Heading",Callout:"Alert",Banner:"Alert",Chip:"Badge",Tag:"Badge",ProgressBar:"Progress",DataTable:"Table",DataGrid:"Table",DateTimeInput:"DatePicker",DateInput:"DatePicker",Calendar:"DatePicker"},borrowed:{components:{Image:"Say what matters in Text, or leave the image out.",Icon:"Every control has words: put the meaning in the text, or in a Badge.",Video:"Describe it in Text, or leave it out.",AudioPlayer:"Describe it in Text, or leave it out.",Modal:"A surface shows inline, with no dialog. Put the content on the surface, or in a Tab or an AccordionItem to keep it out of the way.",Divider:"Spacing comes from Stack, and a Card or a Heading separates groups. Leave the divider out."},props:{weight:"Children share space by the theme's layout. For equal columns use a Grid.",justify:"A Row or a Stack places its children by the theme's layout. For equal columns use a Grid.",align:"A Row or a Stack places its children by the theme's layout. For equal columns use a Grid.","Stack.direction":"A Stack is a column. For side by side use a Row.","Text.variant":'Text is one style of paragraph. For a heading use a Heading with "level".',"Button.child":'A Button holds its words in "text", not in a child component.',"Tabs.tabs":`A Tabs' "children" are Tab components, each with a "label" and "children".`,"Checkbox.value":`A Checkbox's state is "checked": true, false or {"path": "/\u2026"}.`,"Switch.value":`A Switch's state is "checked": true, false or {"path": "/\u2026"}.`,"Input.validationRegexp":'Client-side checks are not in the Mlola catalog yet. Mark the field "required", and check the value when the action arrives.',"Select.variant":"A Select picks one value. For several choices, use a Checkbox for each.","Select.displayStyle":"A Select always opens a list. For options that are all visible use a RadioGroup.","Select.filterable":"A Select lists its options as they are. Keep to the ones that matter, at most 100.","Input.variant=longText":"For several lines use a Textarea.","Input.variant=obscured":'For a password use "type": "password".',"Input.variant=number":"Numbers are not a field type yet. Use a Slider for a number in a range, or an Input with a hint.","Input.variant=shortText":'An Input is one line already, so leave "variant" out.',"Input.type=number":"Numbers are not a field type yet. Use a Slider for a number in a range, or an Input with a hint.","Input.type=date":"For a day use a DatePicker.","Input.type=time":'Times are not a field type yet. Use a Select of the times on offer, or an Input with a hint like "19:30".',"Input.autocomplete":'The browser fills a field in by its "type": use "email", "tel" or "url" where one fits, and leave "autocomplete" out.',"Switch.description":'A Switch has only its "label". Say the rest in a Text before it, or use a Checkbox, which takes a "description".',"Switch.hint":'A Switch has only its "label". Say the rest in a Text before it, or use a Checkbox, which takes a "description".',"Button.variant=default":'For a button beside the main one use "secondary".',"Button.variant=borderless":'For a quiet button use "subtle" or "link".',"DatePicker.enableDate":'A DatePicker always picks a day, so leave "enableDate" out.',"DatePicker.enableTime":"Times are not in the Mlola catalog yet: a DatePicker picks a day. Ask for the time in an Input with a hint."}},examples:[]};var sn="2026-01-26",ze=document.documentElement,ft=document.querySelector("#status"),ve=new Map,Ne=0,we=e=>window.parent.postMessage({jsonrpc:"2.0",...e},"*"),bt=(e,t={})=>we({method:e,params:t}),yt=(e,t={})=>new Promise((n,i)=>{Ne+=1,ve.set(Ne,{resolve:n,reject:i}),we({id:Ne,method:e,params:t})}),xe=e=>{ft.textContent=e,ft.hidden=!e};function kt(e){let t=e?.theme==="dark"?"dark":e?.theme==="light"?"light":null;t&&(ze.dataset.mode=t,de.setSystemMode(t))}var de=pt(document.querySelector("#surfaces"),{rules:Pe,onAction:e=>{let{surfaceId:t,sourceComponentId:n}=e.action,o=`I pressed "${de.host.read(t,de.host.component(t,n)?.props.text)}" in the ${t} surface. A2UI action: ${JSON.stringify(e)}`;yt("ui/message",{role:"user",content:[{type:"text",text:o}]}).catch(()=>xe("The host did not take the message. Try again."))}});function gt(e,t){let n=e?.messages;if(de.host.reset(),n===void 0)return;let i=de.receive(n,{streaming:t});t||xe(i.errors.length&&!de.host.surfaces().length?"The agent's interface had errors, so it is not shown. The agent has been told what to fix.":"")}window.addEventListener("message",e=>{if(e.source!==window.parent)return;let t=e.data;if(!(!t||t.jsonrpc!=="2.0")){if(t.id!==void 0&&ve.has(t.id)&&("result"in t||"error"in t)){let{resolve:n,reject:i}=ve.get(t.id);ve.delete(t.id),"error"in t?i(t.error):n(t.result);return}switch(t.method){case"ui/notifications/tool-input-partial":gt(t.params?.arguments,!0);break;case"ui/notifications/tool-input":gt(t.params?.arguments,!1);break;case"ui/notifications/tool-cancelled":de.host.surfaces().length||xe("The agent stopped before the interface was ready.");break;case"ui/notifications/host-context-changed":kt(t.params);break;case"ui/resource-teardown":case"ping":we({id:t.id,result:{}});break;default:t.id!==void 0&&t.method&&we({id:t.id,error:{code:-32601,message:`Method not found: ${t.method}`}})}}});var Be=0;new ResizeObserver(()=>{let e=Math.ceil(ze.getBoundingClientRect().height);e!==Be&&(Be=e,bt("ui/notifications/size-changed",{width:Math.ceil(ze.getBoundingClientRect().width),height:Be}))}).observe(document.body);yt("ui/initialize",{appInfo:{name:"mlola-render",version:Pe.version},appCapabilities:{availableDisplayModes:["inline"]},protocolVersion:sn}).then(e=>{kt(e?.hostContext),bt("ui/notifications/initialized")}).catch(e=>xe(`The host did not start this view${e?.message?`: ${e.message}`:"."}`));})();
8495
+ `).map(r=>r.trim()).filter(Boolean);if(o.length>1){let r=[];for(let[a,l]of o.entries())try{r.push(JSON.parse(l))}catch(s){return{messages:null,error:`Line ${a+1} is not JSON: ${s.message}`}}return{messages:r,error:null}}return{messages:null,error:`The input is not JSON: ${i.message}`}}}function Ie(e){return{rules:e,surfaces:new Map}}function st(e,t){let n={errors:[],advice:[]},i=P(t),o=i?[t]:t;if(!Array.isArray(o))return n.errors.push(p("","",`Expected A2UI messages: an object with "version" and one of ${pe.join(", ")}, or an array of them. Got ${Z(t)}.`)),n;let{limits:r}=e.rules;if(o.length||n.errors.push(p("","","There are no messages. Start with createSurface, then updateComponents.")),o.length>r.messages)return n.errors.push(p("","",`At most ${r.messages} messages are checked at a time; this is ${o.length}. Check the rest in another call.`)),n;for(let[a,l]of o.entries())Ot(e,l,i?"":`/${a}`,n);return n}function at(e,t){let n={errors:[],advice:[]},i=e.surfaces.get(t);if(!i||i.deleted)return n;n.errors.push(...i.problems);for(let o of i.components.values())lt(e.rules,i.id,o.props,o.at,n);return i.components.size&&Yt(e.rules,i,n),n}function p(e,t,n){return{code:"VALIDATION_FAILED",surfaceId:e??"",path:t,message:n}}function Me(e,t,n){return{code:"ADVICE",surfaceId:e??"",path:t,message:n}}function Ot(e,t,n,i){let{rules:o}=e;if(!P(t)){i.errors.push(p("",n,`A message is an object with "version" and one of ${pe.join(", ")}; this one is ${Z(t)}.`));return}let r=pe.filter(h=>h in t),a=r.length===1&&P(t[r[0]])&&typeof t[r[0]].surfaceId=="string"?t[r[0]].surfaceId:"";if(o.protocolVersions.includes(t.version)||i.errors.push(p(a,w(n,"version"),t.version===void 0?`Add "version": ${b(o.protocolVersions.at(-1))} to every message.`:`Version ${b(t.version)} is not supported; use ${ne(o.protocolVersions)}.`)),r.length!==1){i.errors.push(p(a,n,r.length?`A message carries one of ${pe.join(", ")}; this one has ${r.join(" and ")}. Send them as separate messages.`:`A message carries one of ${pe.join(", ")}; this one has none.`));return}for(let h of Object.keys(t))h!=="version"&&h!==r[0]&&i.errors.push(p(a,w(n,h),`A message holds only "version" and ${b(r[0])}; remove ${b(h)}.`));let l=r[0],s=t[l],c=w(n,l);if(!P(s)){i.errors.push(p("",c,`${l} is an object; got ${Z(s)}.`));return}let d=s.surfaceId;if(typeof d!="string"||!d.trim()||d.length>o.limits.idLength){i.errors.push(p("",w(c,"surfaceId"),`${l} needs a "surfaceId": a string of 1 to ${o.limits.idLength} characters that names the surface.`));return}if(l==="createSurface")qt(e,s,c,i);else{let h=e.surfaces.get(d);if(!h||h.deleted){i.errors.push(p(d,w(c,"surfaceId"),h?.deleted?`Surface ${b(d)} was deleted; send createSurface again before ${l}.`:`No surface is called ${b(d)}. Send createSurface for it first, in the same messages.`));return}l==="updateComponents"?Et(o,h,s,c,i):l==="updateDataModel"?Dt(o,h,s,c,i):jt(e,h,s,c,i)}}function oe(e,t,n,i,o,r){for(let a of Object.keys(e))t.includes(a)||o.errors.push(p(i,w(n,a),`${r} does not take ${b(a)}. It takes ${ne(t)}.`))}function qt(e,t,n,i){let{rules:o}=e,{surfaceId:r}=t,a=i.errors.length;oe(t,["surfaceId","catalogId","theme","sendDataModel"],n,r,i,"createSurface"),t.catalogId!==o.catalogId&&i.errors.push(p(r,w(n,"catalogId"),`Set "catalogId" to ${b(o.catalogId)}: this renderer draws the Mlola catalog${typeof t.catalogId=="string"?`, not ${b(t.catalogId)}`:""}.`)),t.sendDataModel!==void 0&&typeof t.sendDataModel!="boolean"&&i.errors.push(p(r,w(n,"sendDataModel"),'"sendDataModel" is true or false.'));let l={name:o.defaultTheme,mode:"system"};if(t.theme!==void 0){let d=w(n,"theme");if(!P(t.theme))i.errors.push(p(r,d,`"theme" is an object like {"name": ${b(o.defaultTheme)}, "mode": "system"}.`));else{for(let h of Object.keys(t.theme))h==="name"||h==="mode"||i.errors.push(p(r,w(d,h),/color|font|radius|spacing|icon/i.test(h)?`Colors, type and shape come from the theme; pick one by name instead of setting ${b(h)}: ${ne(o.themes)}.`:`"theme" takes "name" and "mode"; remove ${b(h)}.`));t.theme.name!==void 0&&(o.themes.includes(t.theme.name)?l.name=t.theme.name:i.errors.push(p(r,w(d,"name"),`Theme ${b(t.theme.name)} does not exist; use ${ne(o.themes)}.`))),t.theme.mode!==void 0&&(o.modes.includes(t.theme.mode)?l.mode=t.theme.mode:i.errors.push(p(r,w(d,"mode"),`Mode ${b(t.theme.mode)} does not exist; use ${ne(o.modes)} (system follows the reader's setting).`)))}}let s=e.surfaces.get(r);if(s&&!s.deleted){i.errors.push(p(r,w(n,"surfaceId"),`Surface ${b(r)} already exists. Use another surfaceId, or send deleteSurface first.`));return}let c=0;for(let d of e.surfaces.values())d.deleted||(c+=1);if(c>=o.limits.surfaces){i.errors.push(p(r,n,`At most ${o.limits.surfaces} surfaces are open at once; send deleteSurface for one that is done.`));return}e.surfaces.delete(r),e.surfaces.set(r,{id:r,theme:l,sendDataModel:t.sendDataModel===!0,deleted:!1,components:new Map,data:{},dataBytes:0,at:n,problems:i.errors.slice(a)})}function jt(e,t,n,i,o){oe(n,["surfaceId"],i,t.id,o,"deleteSurface"),t.deleted=!0,t.components=new Map,t.data={},t.dataBytes=0;let r=[...e.surfaces.values()].filter(a=>a.deleted);for(let a of r.slice(0,Math.max(0,r.length-e.rules.limits.surfaces)))e.surfaces.delete(a.id)}function Et(e,t,n,i,o){oe(n,["surfaceId","components"],i,t.id,o,"updateComponents");let r=w(i,"components");if(!Array.isArray(n.components)||!n.components.length){o.errors.push(p(t.id,r,'"components" is a non-empty array of components, each with an "id" and a "component".'));return}if(n.components.length>e.limits.components){o.errors.push(p(t.id,r,`This message sends ${n.components.length} components; a surface holds at most ${e.limits.components}. Split it into more surfaces.`));return}let a=new Set;for(let[l,s]of n.components.entries()){let c=w(r,l);if(!P(s)){o.errors.push(p(t.id,c,`A component is an object with "id" and "component"; got ${Z(s)}.`));continue}let{id:d}=s;if(typeof d!="string"||!d.trim()||d.length>e.limits.idLength){o.errors.push(p(t.id,w(c,"id"),`Every component needs an "id": a string of 1 to ${e.limits.idLength} characters, unique on the surface.`));continue}if(a.has(d)){o.errors.push(p(t.id,w(c,"id"),`Two components in this message have the id ${b(d)}; give each its own.`));continue}if(a.add(d),!t.components.has(d)&&t.components.size>=e.limits.components){o.errors.push(p(t.id,c,`A surface holds at most ${e.limits.components} components; split it into more surfaces.`));break}let h=lt(e,t.id,s,c,o);t.components.set(d,{id:d,type:s.component,props:s,definition:h,at:c})}}function Dt(e,t,n,i,o){oe(n,["surfaceId","path","value"],i,t.id,o,"updateDataModel");let r=n.path??"/",a=w(i,"path");if(typeof r!="string"||r!==""&&!qe(r,{absolute:!0,rules:e})){o.errors.push(p(t.id,a,'"path" is a JSON Pointer like "/form/email", or "/" for the whole data model.'));return}let l=0,s;try{let d=n.value===void 0?void 0:JSON.stringify(n.value);s=d===void 0?void 0:JSON.parse(d),l=t.dataBytes-Pt(ge(t.data,r))+(d?.length??0)}catch{o.errors.push(p(t.id,w(i,"value"),"This value is nested too deeply to read; flatten it."));return}if(l>e.limits.dataBytes){o.errors.push(p(t.id,w(i,"value"),`A surface's data model holds at most ${e.limits.dataBytes} bytes of JSON; send less, or page through it.`));return}let c=Ee(t.data,r,s);if(c.error){o.errors.push(p(t.id,a,c.error));return}t.data=c.root,t.dataBytes=l}var Pt=e=>e===void 0?0:JSON.stringify(e)?.length??0;function lt(e,t,n,i,o){let r=n.component,a=w(i,"component");if(typeof r!="string"||!r)return o.errors.push(p(t,a,'Every component names its type in "component", for example "Stack", "Text" or "Button".')),null;let l=ce(e.components,r);if(!l)return o.errors.push(p(t,a,Bt(e,r))),null;for(let[s,c]of Object.entries(n)){if(xt.has(s))continue;let d=ce(l.props,s),h=w(i,s);if(!d){o.errors.push(p(t,h,Rt(e,r,l,s)));continue}Wt(e,t,r,s,d,c,h,o)}for(let[s,c]of Object.entries(l.props))c.required&&n[s]===void 0&&o.errors.push(p(t,i,`${r} needs ${b(s)}${c.description?`: ${Nt(c.description)}`:"."}`));return n.accessibility!==void 0&&Ft(e,t,n.accessibility,w(i,"accessibility"),o),Kt(e,t,r,l,n,i,o),l}var Nt=e=>e.charAt(0).toLowerCase()+e.slice(1);function Bt(e,t){let n=ce(e.aliases,t)??Object.keys(e.components).find(o=>o.toLowerCase()===t.toLowerCase());if(n)return`${b(t)} is not in the Mlola catalog; use ${b(n)}.`;let i=ce(e.borrowed.components,t);return i?`${b(t)} is not in the Mlola catalog. ${i}`:`${b(t)} is not in the Mlola catalog. It has: ${zt(e).map(([o,r])=>`${o} (${r.join(", ")})`).join("; ")}.`}function zt(e){return Object.entries(e.groups).map(([t,n])=>[n,Object.keys(e.components).filter(i=>e.components[i].group===t)])}function Rt(e,t,n,i){let o=Object.keys(n.props),r=ce(e.borrowed.props,`${t}.${i}`)??ce(e.borrowed.props,i);return r?`${t} does not take ${b(i)}. ${r}`:$t.has(i)?`${t} takes no ${b(i)}: Mlola Render draws with the surface's theme. Choose a named value instead (${o.filter(a=>n.props[a].kind==="enum").join(", ")||"none on this component"}).`:i==="child"&&o.includes("children")?`${t} takes "children", an array of ids, not "child".`:i==="checks"?'Client-side checks are not in the Mlola catalog yet; use "required" on the field, and check the values when the action arrives.':/^on[A-Z]/.test(i)?`${t} does not take ${b(i)}. A Button's "action" sends an event to the agent; inputs bind their value with {"path": \u2026}.`:`${t} does not take ${b(i)}. It takes: ${o.join(", ")}.`}function Ft(e,t,n,i,o){if(!P(n)){o.errors.push(p(t,i,'"accessibility" is an object with "label" and "description".'));return}for(let[r,a]of Object.entries(n)){if(r!=="label"&&r!=="description"){o.errors.push(p(t,w(i,r),`"accessibility" takes "label" and "description"; remove ${b(r)}.`));continue}Oe(e,t,a,w(i,r),{maxLength:e.limits.labelLength},!1,o)}}function Wt(e,t,n,i,o,r,a,l){switch(o.kind){case"text":return Oe(e,t,r,a,o,o.required,l,`${n} ${b(i)}`);case"boolean":return typeof r=="boolean"||!o.literal&&le(e,t,r,a,l)?void 0:l.errors.push(p(t,a,`${n} ${b(i)} is true or false${o.literal?"":', or {"path": "/\u2026"}'}; got ${Z(r)}.`));case"number":return typeof r=="number"&&Number.isFinite(r)||!o.literal&&le(e,t,r,a,l)?void 0:l.errors.push(p(t,a,`${n} ${b(i)} is a number${o.literal?"":' or {"path": "/\u2026"}'}; got ${Z(r)}.`));case"integer":return Number.isInteger(r)&&r>=o.minimum&&r<=o.maximum?void 0:l.errors.push(p(t,a,`${n} ${b(i)} is a whole number from ${o.minimum} to ${o.maximum}; got ${b(r)}.`));case"date":return ie(r)||!o.literal&&le(e,t,r,a,l)?void 0:l.errors.push(p(t,a,`${n} ${b(i)} is a day written as an ISO date, like "2026-10-12"${o.literal?"":', or {"path": "/\u2026"}'}; got ${b(r)}.`));case"enum":return typeof r=="string"&&o.values.includes(r)?void 0:l.errors.push(p(t,a,Ht(e,n,i,o,r)));case"children":return Gt(e,t,n,i,o,r,a,l);case"action":return _t(e,t,r,a,l);case"options":return Ut(e,t,n,o,r,a,l);case"columns":return Jt(e,t,n,i,o,r,a,l);case"rows":return Vt(e,t,i,o,r,a,l);default:return ot.has(o.kind)?ot.get(o.kind).check(e,t,n,i,o,r,a,l):l.errors.push(p(t,a,`${n} ${b(i)} has a kind this validator does not know (${o.kind}); import @mlola-ui/behavior/render/data first.`))}}function Ht(e,t,n,i,o){if(typeof o=="string"){let r=i.values.find(l=>l.toLowerCase()===o.toLowerCase());if(r)return`${t} ${b(n)} is ${b(r)}, not ${b(o)}: values are case-sensitive.`;let a=ce(e.borrowed.props,`${t}.${n}=${o}`);if(a)return`${t} ${b(n)} ${b(o)} is not in the catalog. ${a}`;if(i.excluded?.includes(o))return`${t} ${b(n)} ${b(o)} is not in the catalog: ${i.description??"it needs content the catalog does not offer."} Use ${ne(i.values)}.`}return`${t} ${b(n)} ${typeof o=="string"?`${b(o)} does not exist`:`is a name, not ${Z(o)}`}; use ${ne(i.values)}.`}function Oe(e,t,n,i,o,r,a,l="This text"){if(typeof n=="string"){let s=o.maxLength??e.limits.textLength;n.length>s?a.errors.push(p(t,i,`${l} is ${n.length} characters; keep it to ${s}.`)):r&&!n.trim()&&a.errors.push(p(t,i,`${l} is empty. It is what a person sees and a screen reader reads; write the words.`));return}if(!le(e,t,n,i,a)){if(P(n)&&"call"in n){a.errors.push(p(t,i,'Functions are not in the Mlola catalog yet; use a literal string or {"path": "/\u2026"}.'));return}a.errors.push(p(t,i,`${l} is a string or {"path": "/\u2026"}; got ${Z(n)}.`))}}function le(e,t,n,i,o){if(!P(n)||!("path"in n))return!1;let r=Object.keys(n).filter(a=>a!=="path");return r.length&&o.errors.push(p(t,i,`A binding holds only "path"; remove ${ne(r)}.`)),(typeof n.path!="string"||!qe(n.path,{rules:e}))&&o.errors.push(p(t,w(i,"path"),`${b(n.path)} is not a data path. Write a JSON Pointer like "/form/email" (or "name" inside a template), at most ${e.limits.pathLength} characters.`)),!0}function qe(e,{absolute:t=!1,rules:n}){if(!e||e.length>n.limits.pathLength)return!1;if(t&&e==="/")return!0;if(t&&!e.startsWith("/"))return!1;let i=(e.startsWith("/")?e.slice(1):e).split("/");for(let o of i)if(/~(?![01])/.test(o)||Ce.has(je(o)))return!1;return!0}var je=e=>e.replaceAll("~1","/").replaceAll("~0","~");function Gt(e,t,n,i,o,r,a,l){if(Array.isArray(r)){r.length<(o.minItems??0)&&l.errors.push(p(t,a,`${n} needs at least ${o.minItems} ${o.minItems===1?"child":"children"}.`)),r.length>e.limits.components&&l.errors.push(p(t,a,`${n} lists ${r.length} children; a surface holds at most ${e.limits.components} components.`));let s=new Set;for(let[c,d]of r.entries())typeof d!="string"||!d?l.errors.push(p(t,w(a,c),`A child is a component id (a string); got ${Z(d)}.`)):s.has(d)?l.errors.push(p(t,w(a,c),`${b(d)} is listed twice in ${n}'s children; a component appears in one place.`)):s.add(d);return}if(P(r)&&("componentId"in r||"path"in r)){oe(r,["componentId","path"],a,t,l,"A template"),(typeof r.componentId!="string"||!r.componentId)&&l.errors.push(p(t,w(a,"componentId"),'A template names the component to repeat in "componentId".')),(typeof r.path!="string"||!qe(r.path,{rules:e}))&&l.errors.push(p(t,w(a,"path"),`A template's "path" points at an array in the data model, like "/items".`));return}l.errors.push(p(t,a,`${n} ${b(i)} is an array of component ids, or a template {"componentId", "path"}; got ${Z(r)}.`))}function _t(e,t,n,i,o){if(!P(n)){o.errors.push(p(t,i,`"action" is {"event": {"name": "\u2026", "context": {\u2026}}}; got ${Z(n)}.`));return}if("functionCall"in n){o.errors.push(p(t,w(i,"functionCall"),'Client-side functions are not in the Mlola catalog yet; send an event and handle it in the agent: {"event": {"name": "\u2026"}}.'));return}oe(n,["event"],i,t,o,"An action");let r=n.event,a=w(i,"event");if(!P(r)){o.errors.push(p(t,a,'An action sends an event: {"name": "\u2026", "context": {\u2026}}.'));return}if(oe(r,["name","context"],a,t,o,"An event"),(typeof r.name!="string"||!At.test(r.name))&&o.errors.push(p(t,w(a,"name"),`An event's "name" starts with a letter and uses letters, digits, _ . : or - (at most 64), like "create_workspace".`)),r.context===void 0)return;let l=w(a,"context");if(!P(r.context)){o.errors.push(p(t,l,`An event's "context" is an object of values or {"path": \u2026} bindings.`));return}let s=Object.keys(r.context);s.length>e.limits.contextKeys&&o.errors.push(p(t,l,`An event's context holds at most ${e.limits.contextKeys} values; bind a whole object with {"path": "/form"} instead.`));for(let c of s.slice(0,e.limits.contextKeys)){let d=r.context[c],h=w(l,c);Ce.has(c)?o.errors.push(p(t,h,`${b(c)} cannot be a context key.`)):P(d)&&!le(e,t,d,h,o)?o.errors.push(p(t,h,'A context value is a string, number, boolean, array or {"path": \u2026}; an object needs a binding.')):Array.isArray(d)&&d.some(g=>g!==null&&typeof g=="object")?o.errors.push(p(t,h,'An array in the context holds strings, numbers and true or false; for a list from the data model use {"path": "/\u2026"}.')):typeof d=="string"&&d.length>e.limits.textLength&&o.errors.push(p(t,h,`This value is ${d.length} characters; keep it to ${e.limits.textLength}.`))}}function Ut(e,t,n,i,o,r,a){if(le(e,t,o,r,a))return;if(!Array.isArray(o)){a.errors.push(p(t,r,`${n} "options" is an array of {"label", "value"}, or {"path": "/\u2026"}; got ${Z(o)}.`));return}if(o.length<(i.minItems??1)&&a.errors.push(p(t,r,`${n} needs at least ${i.minItems} options${n==="RadioGroup"?"; for one yes or no choice use a Checkbox":""}.`)),o.length>e.limits.options){a.errors.push(p(t,r,`${n} lists ${o.length} options; keep it to ${e.limits.options}.`));return}let l=new Set;for(let[s,c]of o.entries()){let d=w(r,s);if(!P(c)){a.errors.push(p(t,d,`An option is {"label": "\u2026", "value": "\u2026"}; got ${Z(c)}.`));continue}oe(c,["label","value"],d,t,a,"An option"),(typeof c.label!="string"||!c.label.trim()||c.label.length>e.limits.labelLength)&&a.errors.push(p(t,w(d,"label"),`An option's "label" is the words a person picks, 1 to ${e.limits.labelLength} characters.`)),typeof c.value!="string"||!c.value||c.value.length>e.limits.labelLength?a.errors.push(p(t,w(d,"value"),`An option's "value" is the string sent back, 1 to ${e.limits.labelLength} characters.`)):l.has(c.value)?a.errors.push(p(t,w(d,"value"),`Two options have the value ${b(c.value)}; give each its own.`)):l.add(c.value)}}function Jt(e,t,n,i,o,r,a,l){let s=o.item??"column",c=It(o);if(!Array.isArray(r)||r.length<(o.minItems??1)){l.errors.push(p(t,a,`${b(i)} is a non-empty array of {"key", "label"${Object.keys(c).map(g=>`, ${b(g)}?`).join("")}}.`));return}let d=o.maxItems??e.limits.columns;if(r.length>d){l.errors.push(p(t,a,o.maxItems?`${n} takes at most ${d} ${nt(s)}; this is ${r.length}.`:`A table shows at most ${d} columns; more cannot be read on a phone.`));return}let h=new Set;for(let[g,y]of r.entries()){let I=w(a,g);if(!P(y)){l.errors.push(p(t,I,`A ${s} is {"key": "\u2026", "label": "\u2026"}; got ${Z(y)}.`));continue}oe(y,["key","label",...Object.keys(c)],I,t,l,`A ${s}`),typeof y.key!="string"||!St.test(y.key)||Ce.has(y.key)?l.errors.push(p(t,w(I,"key"),`A ${tt(s)} "key" names the row field it shows: letters, digits, _ or -, like "order".`)):h.has(y.key)?l.errors.push(p(t,w(I,"key"),`Two ${nt(s)} have the key ${b(y.key)}.`)):h.add(y.key),Oe(e,t,y.label,w(I,"label"),{maxLength:e.limits.labelLength},!0,l,`The ${tt(s)} "label"`);for(let[E,q]of Object.entries(c)){let x=y[E];x===void 0||(q.values?q.values.includes(x):typeof x=="boolean")||l.errors.push(p(t,w(I,E),q.values?`${b(E)} is ${ne(q.values)}.`:`${b(E)} is true or false.`))}}}function Vt(e,t,n,i,o,r,a){if(le(e,t,o,r,a))return;if(!Array.isArray(o)){a.errors.push(p(t,r,`${b(n)} is an array of objects, or {"path": "/\u2026"} to one in the data model; got ${Z(o)}.`));return}if(o.length<(i.minItems??0)){a.errors.push(p(t,r,`${b(n)} needs at least ${i.minItems} ${i.minItems===1?"row":"rows"}.`));return}let l=Math.min(i.maxItems??e.limits.rows,e.limits.rows);if(o.length>l){a.errors.push(p(t,r,`${b(n)} holds at most ${l} rows; ${i.maxItems?"keep the ones that matter":"page through the rest"}.`));return}for(let[s,c]of o.entries()){let d=w(r,s);if(!P(c)){a.errors.push(p(t,d,`A row is an object of its fields, like {"name": "\u2026"}; got ${Z(c)}.`));continue}for(let[h,g]of Object.entries(c))g===null||typeof g=="number"||typeof g=="boolean"||typeof g=="string"&&g.length<=e.limits.textLength||a.errors.push(p(t,w(d,h),typeof g=="string"?`A cell holds at most ${e.limits.textLength} characters.`:`A cell holds text, a number or true/false; got ${Z(g)}.`))}}function Kt(e,t,n,i,o,r,a){let l=s=>typeof o[s]=="number"?o[s]:i.props[s]?.default;if(n==="Slider"){let s=l("min"),c=l("max"),d=l("step");typeof s=="number"&&typeof c=="number"&&s>=c&&a.errors.push(p(t,w(r,"max"),`Slider "max" (${c}) must be greater than "min" (${s}).`)),typeof d=="number"&&(d<=0||d>c-s)&&a.errors.push(p(t,w(r,"step"),'Slider "step" is greater than 0 and at most max minus min.')),typeof o.value=="number"&&(o.value<s||o.value>c)&&a.errors.push(p(t,w(r,"value"),`Slider "value" ${o.value} is outside ${s} to ${c}.`))}if(n==="Progress"){let s=l("max");typeof s=="number"&&s<=0&&a.errors.push(p(t,w(r,"max"),'Progress "max" is greater than 0.')),typeof o.value=="number"&&(o.value<0||o.value>s)&&a.errors.push(p(t,w(r,"value"),`Progress "value" ${o.value} is outside 0 to ${s}.`))}if(n==="DatePicker"){let{min:s,max:c,value:d}=o;ie(s)&&ie(c)&&s>c?a.errors.push(p(t,w(r,"max"),`DatePicker "max" (${c}) comes before "min" (${s}); make it the later day.`)):ie(d)&&(ie(s)&&d<s||ie(c)&&d>c)&&a.errors.push(p(t,w(r,"value"),`DatePicker "value" ${d} is outside ${ie(s)?s:"any day"} to ${ie(c)?c:"any day"}.`))}if((n==="Select"||n==="RadioGroup")&&typeof o.value=="string"&&Array.isArray(o.options)){let s=o.options.filter(P).map(c=>c.value);s.includes(o.value)||a.errors.push(p(t,w(r,"value"),`${n} "value" ${b(o.value)} is not one of its options (${ne(s)}).`))}for(let s of Ct)s(t,n,i,o,r,a)}function fe(e){let t=e.props.children;return Array.isArray(t)?{ids:t.filter(n=>typeof n=="string"),template:null}:P(t)&&typeof t.componentId=="string"?{ids:[t.componentId],template:t}:{ids:[],template:null}}function Yt(e,t,n){let{components:i}=t,o=i.get("root");if(!o){n.errors.push(p(t.id,t.at,'No component has the id "root". One component is the root of the tree; give it "id": "root".'));return}let r=new Map;for(let d of i.values()){let{ids:h,template:g}=fe(d),y=w(d.at,"children");for(let[I,E]of h.entries()){let q=g?w(y,"componentId"):w(y,I),x=i.get(E);if(!x){n.errors.push(p(t.id,q,`No component has the id ${b(E)}. Add it, or remove it from ${d.type}'s children.`));continue}if(E===d.id){n.errors.push(p(t.id,q,`${b(E)} lists itself as a child: the children form a loop. A component cannot be inside its own tree.`));continue}if(E==="root"){n.errors.push(p(t.id,q,'"root" is the top of the tree and cannot be a child.'));continue}let M=r.get(E);if(M&&M!==d.id){n.errors.push(p(t.id,q,`${b(E)} is already a child of ${b(M)}. A component appears in one place; give the second one its own id.`));continue}r.set(E,d.id),x.definition?.parents&&d.definition&&!x.definition.parents.includes(d.type)&&n.errors.push(p(t.id,q,`${x.type} goes directly inside ${x.definition.parents.join(" or ")}, not inside ${d.type}.`)),d.definition?.accepts&&x.definition&&!d.definition.accepts.includes(x.type)&&n.errors.push(p(t.id,q,`${d.type} holds only ${d.definition.accepts.join(" and ")} components; ${b(E)} is a ${x.type}.`))}}for(let d of i.values())d.definition?.parents&&d.id!=="root"&&!r.has(d.id)&&n.errors.push(p(t.id,d.at,`${d.type} goes directly inside ${d.definition.parents.join(" or ")}; list ${b(d.id)} in one's children.`));let a=new Set(["root"]),l=new Set,s=[],c=[{node:o,depth:1,templated:!1}];for(;c.length;){let{node:d,depth:h,templated:g}=c.pop();if(s.push(d),g&&l.add(d.id),h>e.limits.depth){n.errors.push(p(t.id,d.at,`The tree is more than ${e.limits.depth} levels deep at ${b(d.id)}; flatten it.`));continue}let{ids:y,template:I}=fe(d);for(let E=y.length-1;E>=0;E-=1){let q=i.get(y[E]);if(!(!q||r.get(q.id)!==d.id)){if(a.has(q.id)){n.errors.push(p(t.id,w(d.at,"children"),`${b(q.id)} contains itself: the children form a loop. A component cannot be inside its own tree.`));continue}a.add(q.id),c.push({node:q,depth:h+1,templated:g||!!I})}}}for(let d of i.values())!a.has(d.id)&&!(d.definition?.parents&&!r.has(d.id))&&n.advice.push(Me(t.id,d.at,`${b(d.id)} is not inside "root", so it will not show. List it in a parent's children, or remove it.`));Xt(e,t,s,l,n),Zt(t,s,n)}function Xt(e,t,n,i,o){let r=l=>P(l)&&typeof l.path=="string"&&!l.path.startsWith("/"),a=(l,s)=>o.errors.push(p(t.id,w(s,"path"),`${b(l.path)} is relative, which only works inside a template; write it from the top of the data model, like "/${l.path}".`));for(let l of n)if(!(i.has(l.id)||!l.definition))for(let[s,c]of Object.entries(l.props)){let d=w(l.at,s);if(s==="children")r(c)&&o.errors.push(p(t.id,w(d,"path"),`A template's "path" points at an array from the top of the data model, like "/${c.path}"; a relative path works only inside another template.`));else if(s==="accessibility"&&P(c))for(let h of["label","description"])r(c[h])&&a(c[h],w(d,h));else if(s==="action"&&P(c)&&P(c.event)&&P(c.event.context))for(let[h,g]of Object.entries(c.event.context))r(g)&&a(g,w(d,"event","context",h));else r(c)&&a(c,d)}}function Zt(e,t,n){let i=0,o=null,r=new Map,a=(l,s)=>l.props[s]??l.definition?.props[s]?.default;for(let l of t){if(l.type==="Heading"&&Number.isInteger(a(l,"level"))){let c=a(l,"level");i&&c>i+1&&n.errors.push(p(e.id,w(l.at,"level"),`This heading jumps from level ${i} to ${c}; use ${i+1}. A screen reader uses the levels to move through the surface.`)),i=c}l.type==="Button"&&a(l,"variant")==="primary"&&(o?n.advice.push(Me(e.id,w(l.at,"variant"),`${b(o)} is already the primary action; keep one primary Button per surface and make this one "secondary".`)):o=l.id);let s=typeof l.props.label=="string"?l.props.label.trim().toLowerCase():null;s&&l.definition?.group==="form"&&(r.has(s)?n.advice.push(Me(e.id,w(l.at,"label"),`${b(r.get(s))} has the same label; give each field its own so they can be told apart.`)):r.set(s,l.id))}}var ct=/^(0|[1-9][0-9]{0,5})$/;function ge(e,t){if(t===""||t==="/")return e;let n=e;for(let i of t.slice(1).split("/").map(je)){if(!P(n)&&!Array.isArray(n)||Array.isArray(n)&&!ct.test(i))return;n=Object.hasOwn(n,i)?n[i]:void 0}return n}function Ee(e,t,n){if(t===""||t==="/")return{root:n===void 0?{}:n};let i=t.slice(1).split("/").map(je),o=P(e)||Array.isArray(e)?e:{},r=o;for(let[l,s]of i.entries()){if(Array.isArray(r)&&!ct.test(s))return{error:`${b(i.slice(0,l).join("/")||"/")} holds an array, so the next segment is an index like 0, not ${b(s)}.`};if(Array.isArray(r)&&Number(s)>r.length)return{error:`${b(i.slice(0,l).join("/")||"/")} holds ${r.length} ${r.length===1?"item":"items"}, so the next index is at most ${r.length}, not ${s}.`};if(l===i.length-1)break;!P(r[s])&&!Array.isArray(r[s])&&(r[s]={}),r=r[s]}let a=i.at(-1);return n===void 0?delete r[a]:r[a]=n,{root:o}}var Qt=["createSurface","updateComponents","updateDataModel","deleteSurface"],en=/^(?:\/\d+)?\/(?:createSurface|updateComponents|updateDataModel|deleteSurface)(\/.*)?$/,tn=new Set(["EmptyState","Accordion"]),J=e=>P(e)&&typeof e.path=="string",De=e=>e!==null&&typeof e=="object"?JSON.parse(JSON.stringify(e)):e;function be(e,t=""){return e.startsWith("/")?e:e?`${t}/${e}`:t||"/"}function dt(e,t="v0.9.1"){let n=en.exec(e.path);return{version:t,error:{code:e.code,surfaceId:e.surfaceId,path:n?n[1]||"/":e.path||"/",message:e.message}}}function ut(e,t={}){let n=t,i=Ie(e),o=n.version??e.protocolVersions.at(-1),r=n.now??(()=>new Date),a=new Map,l=new Set,s=new Set,c=0,d=[],h=v=>{n.onError?n.onError(v):d.push(...v)},g=0,y=()=>{c+=1;for(let v of[...l])v()};function I(v){let u=new Map,T=v.get("root");if(!T)return u;let W=new Set(["root"]),L=[T],S=1;for(;L.length;){let A=L.pop();A.type==="Heading"?S=Number.isInteger(A.props.level)?A.props.level:A.definition?.props.level?.default??2:tn.has(A.type)&&u.set(A.id,Math.min(6,S+1));let{ids:G}=fe(A);for(let K=G.length-1;K>=0;K-=1){let Y=v.get(G[K]);Y&&!W.has(Y.id)&&(W.add(Y.id),L.push(Y))}}return u}function E(v,{streaming:u=!1}={}){let T=it(v,e.limits);if(T.error){let S={errors:[{code:"VALIDATION_FAILED",surfaceId:"",path:"",message:T.error}],advice:[]};return h(S.errors.map(A=>dt(A,o))),S}let L=Array.isArray(T.messages)&&!T.messages.length?{errors:[],advice:[]}:st(i,T.messages);for(let S of Array.isArray(T.messages)?T.messages:[T.messages])if(P(S))for(let A of Qt)P(S[A])&&typeof S[A].surfaceId=="string"&&s.add(S[A].surfaceId);for(let S of[...a.keys()]){let A=i.surfaces.get(S);(!A||A.deleted)&&a.delete(S)}if(!u){let S=new Set(L.errors.map(A=>`${A.path}\0${A.message}`));for(let A of s){let G=i.surfaces.get(A);if(!G||G.deleted||!G.components.size)continue;let K=at(i,A);if(K.errors.length){for(let Q of K.errors){let ee=`${Q.path}\0${Q.message}`;S.has(ee)||L.errors.push(Q),S.add(ee)}continue}L.advice.push(...K.advice);let Y=new Map(G.components);g+=1,a.set(A,{components:Y,theme:G.theme,levels:I(Y),missing:a.get(A)?.missing??new Set,structure:g})}s.clear()}return L.errors.length&&h(L.errors.map(S=>dt(S,o))),y(),L}let q=v=>a.get(v)??null,x=v=>i.surfaces.get(v)?.data;function M(v,u,T=""){return J(u)?ge(x(v),be(u.path,T)):u}function C(v,u,T=""){let W=q(v),L=W?.components.get(u);if(!L)return[];let{ids:S,template:A}=fe(L);if(!A)return S.filter(Q=>W.components.has(Q)).map(Q=>({id:Q,scope:T,key:`${Q}@${T}`}));if(!W.components.has(A.componentId))return[];let G=be(A.path,T),K=ge(x(v),G);if(!Array.isArray(K))return[];let Y=G==="/"?"":G;return K.slice(0,e.limits.components).map((Q,ee)=>({id:A.componentId,scope:`${Y}/${ee}`,key:`${A.componentId}@${Y}/${ee}`}))}function j(v,u,T,W=""){let L=i.surfaces.get(v);if(!L||L.deleted||!J(u))return!1;let S=be(u.path,W),A=Ee(L.data,S,T);if(A.error)return!1;L.data=A.root;let G=q(v);if(G?.missing.size)for(let K of[...G.missing])K.endsWith(`|${S}`)&&G.missing.delete(K);return y(),!0}function*B(v,u="root",T="",W=0){let L=q(v)?.components.get(u);if(!(!L||W>e.limits.depth)){yield{node:L,scope:T};for(let S of C(v,u,T))yield*B(v,S.id,S.scope,W+1)}}let V=v=>v==null||v===!1||typeof v=="string"&&!v.trim();function se(v,u,T=""){let W=q(v),S=W?.components.get(u)?.props.action?.event;if(!W||!P(S))return{sent:null,missing:[]};let A=P(S.context)?S.context:{},G=Object.values(A).filter(J).map(_=>be(_.path,T)),K=_=>G.some(U=>U==="/"||U===_||_.startsWith(`${U}/`)),Y=[];for(let _ of B(v)){let{props:U,definition:ae}=_.node;if(ae?.group!=="form"||M(v,U.required,_.scope)!==!0)continue;let re=J(U.value)?U.value:J(U.checked)?U.checked:null;if(!re)continue;let ue=be(re.path,_.scope);K(ue)&&V(ge(x(v),ue))&&Y.push({id:_.node.id,scope:_.scope,key:`${_.node.id}@${_.scope}`,path:ue,label:M(v,U.label,_.scope)})}if((Y.length||G.length)&&(W.missing=new Set(Y.map(_=>`${_.key}|${_.path}`))),Y.length)return y(),{sent:null,missing:Y};let Q={version:o,action:{name:S.name,surfaceId:v,sourceComponentId:u,timestamp:r().toISOString(),context:Object.fromEntries(Object.entries(A).map(([_,U])=>[_,De(M(v,U,T))??null]))}},ee=i.surfaces.get(v);return n.onAction?.(Q,ee?.sendDataModel?{dataModel:De(ee.data)}:{}),y(),{sent:Q,missing:[]}}return{rules:e,receive:E,surfaces:()=>[...a.keys()],surface:v=>a.has(v)?{id:v,theme:a.get(v).theme}:null,component:(v,u)=>q(v)?.components.get(u)??null,children:C,read:M,write:j,press:se,missing:(v,u,T="")=>{let W=q(v);if(!W?.missing.size)return!1;let L=`${u}@${T}|`;for(let S of W.missing)if(S.startsWith(L))return!0;return!1},structure:v=>q(v)?.structure??0,headingLevel:(v,u)=>q(v)?.levels.get(u)??2,configure:v=>{if(n={...n,...v},n.onError&&d.length){let u=d;d=[],n.onError(u)}},reset:()=>{i=Ie(e),a.clear(),s.clear(),y()},dataModel:v=>De(x(v)),subscribe:v=>(l.add(v),()=>l.delete(v)),revision:()=>c}}var ht={info:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><circle cx="12" cy="12" r="9.5" pathLength="1"></circle><path d="M12 11v6M12 7h.01" pathLength="1"></path></svg>',success:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><circle cx="12" cy="12" r="9.5" pathLength="1"></circle><path d="m7.5 12 3 3 6-6" pathLength="1"></path></svg>',warning:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><path d="m10.3 3.8-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.7-3.2l-8-14a2 2 0 0 0-3.4 0Z" pathLength="1"></path><path d="M12 9v4M12 17h.01" pathLength="1"></path></svg>',danger:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><circle cx="12" cy="12" r="9.5" pathLength="1"></circle><path d="m9 9 6 6M15 9l-6 6" pathLength="1"></path></svg>',check:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><polyline points="20 6 9 17 4 12" pathLength="1"></polyline></svg>',chevron:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><polyline points="6 9 12 15 18 9" pathLength="1"></polyline></svg>'};var nn={required:"Fill in this field.",missing:e=>`Fill in ${e.join(", ")} first.`,yes:"Yes",no:"No"},X=e=>e==null?"":String(e),mt=e=>e!=null&&e!=="",me=(e,t)=>`${e}-${Array.from(t,n=>/[A-Za-z0-9_-]/.test(n)?n:`_${n.codePointAt(0)?.toString(16)}`).join("")}`,on=0;function f(e,t={},...n){let i=document.createElement(e);for(let[o,r]of Object.entries(t))r==null||r===!1||i.setAttribute(o,r===!0?"":String(r));for(let o of n.flat())o!=null&&o!==!1&&i.append(o);return i}function ke(e,t){let n=document.createElement("span");n.innerHTML=ht[e];let i=n.firstElementChild;return t&&i.classList.add(t),i}function pt(e,t={}){let n=t.host??ut(t.rules,{onAction:t.onAction,onError:t.onError}),i={...nn,...t.labels},o=`ml-render-${on+=1}`,r=f("div",{class:"ml-render"}),a=f("p",{role:"status",class:"ml-visually-hidden"});r.append(a),e.append(r);let l=new Map,s=x=>x.mode==="system"&&t.systemMode?t.systemMode:x.mode;function c(){let x=t.surfaceId?n.surface(t.surfaceId)?[t.surfaceId]:[]:n.surfaces();for(let[C,j]of l)x.includes(C)||(j.node.remove(),l.delete(C));t.streaming?r.setAttribute("aria-busy","true"):r.removeAttribute("aria-busy");for(let C of x){let j=l.get(C);if(j&&j.structure===n.structure(C)&&j.lists.every(V=>V.count()===V.length)){for(let V of j.updaters)V();continue}let B=g(C,j);j?j.node.replaceWith(B.node):r.insertBefore(B.node,a),l.set(C,B),et(B.node),h(B.node,B.kept)}let M=a;for(let C of[...x].reverse()){let j=l.get(C).node;j.nextSibling!==M&&r.insertBefore(j,M),M=j}}function d(x){let M=x.contains(document.activeElement)?document.activeElement:null;return{focus:M?.id??null,selection:M&&"selectionStart"in M?[M.selectionStart,M.selectionEnd]:null,tabs:[...x.querySelectorAll('.ml-tabs-trigger[aria-selected="true"]')].map(C=>C.id),open:[...x.querySelectorAll('.ml-accordion-item[data-state="open"] .ml-accordion-trigger')].map(C=>C.id)}}function h(x,M){if(!M)return;for(let j of M.tabs)document.getElementById(j)?.click();for(let j of x.querySelectorAll(".ml-accordion-trigger"))M.open.includes(j.id)!==(j.getAttribute("aria-expanded")==="true")&&j.click();let C=M.focus?document.getElementById(M.focus):null;if(C&&(C.focus(),M.selection&&"setSelectionRange"in C))try{C.setSelectionRange(...M.selection)}catch{}}function g(x,M){let C=M?d(M.node):null,j=n.surface(x),B=t.theme==="inherit"?null:j.theme,V=f("div",{class:"ml-render-surface","data-surface":x,"data-theme":B?.name,"data-mode":B?s(B):null,"data-themed":B?!0:null}),se={surfaceId:x,base:`${o}-${x}`,updaters:[],lists:[]};return V.append(...E(se,{id:"root",scope:"",key:"root@"})),{node:V,structure:n.structure(x),lists:se.lists,updaters:se.updaters,kept:C}}function y(x,M,C){let j=n.component(x.surfaceId,M),B=n.children(x.surfaceId,M,C);return j&&!Array.isArray(j.props.children)&&j.props.children&&x.lists.push({length:B.length,count:()=>n.children(x.surfaceId,M,C).length}),B}function I(x,M,C){let{missing:j}=n.press(x,M,C);if(a.textContent=j.length?i.missing(j.map(V=>X(V.label))):"",!j.length)return;let B=document.getElementById(me(`${o}-${x}`,j[0].key));(B?.matches("input, textarea, button, [tabindex]")?B:B?.querySelector("input, textarea, button, [tabindex]"))?.focus()}function E(x,M){let{surfaceId:C,updaters:j}=x,{id:B,scope:V,key:se}=M,v=n.component(C,B);if(!v)return[];let u=v.props,T=m=>n.read(C,m,V),W=(m,k)=>n.write(C,m,k,V),L=me(x.base,se),S=m=>{m(),j.push(m)},A=(m,k)=>(S(()=>{m.textContent=X(T(k))}),m),G=()=>y(x,B,V).flatMap(m=>E(x,m)),K=u.accessibility??{},Y=m=>(S(()=>{let k=X(T(K.label)),$=X(T(K.description));k?m.setAttribute("aria-label",k):m.removeAttribute("aria-label"),$?m.setAttribute("aria-description",$):m.removeAttribute("aria-description")}),m),Q=m=>K.label===void 0?m:(m.setAttribute("role","group"),Y(m)),ee=()=>Array.isArray(T(u.options))?T(u.options).filter(m=>typeof m?.label=="string"&&typeof m?.value=="string"&&m.value):[],_=()=>{if(!J(u.options))return;let m=()=>JSON.stringify(ee());x.lists.push({length:m(),count:m})},U=()=>T(u.disabled)===!0,ae=()=>T(u.required)===!0,re=(m,k)=>{let $=f("p",{id:`${L}-error`,role:"alert",class:"ml-input-error",hidden:!0});return S(()=>{let O=n.missing(C,B,V);$.hidden=!O,$.textContent=O?i.required:"",m.toggleAttribute("data-invalid",O),O?k.setAttribute("aria-invalid","true"):k.removeAttribute("aria-invalid");let z=[mt(u.hint)?`${L}-hint`:null,O?`${L}-error`:null].filter(Boolean).join(" ");z?k.setAttribute("aria-describedby",z):k.removeAttribute("aria-describedby")}),$},ue=m=>{let k=f("label",{id:`${m}-label`,for:m,class:"ml-input-label"}),$=document.createTextNode(""),O=f("span",{"aria-hidden":"true",class:"ml-required-mark"},"*");return k.append($),S(()=>{$.textContent=X(T(u.label)),ae()?k.append(O):O.remove()}),k},Re=()=>mt(u.hint)?A(f("p",{id:`${L}-hint`,class:"ml-input-hint"}),u.hint):null,Fe=m=>(J(u.value)?(S(()=>{let k=X(T(u.value));m.value!==k&&(m.value=k)}),m.addEventListener("input",()=>W(u.value,m.value))):m.value=X(u.value),S(()=>{m.disabled=U(),m.required=ae()}),m);switch(v.type){case"Stack":return[Q(f("div",{class:"ml-stack"},G()))];case"Row":return[Q(f("div",{class:"ml-cluster"},G()))];case"Grid":return[Q(f("div",{class:"ml-grid","data-columns":u.columns},G()))];case"Heading":return[A(f(`h${u.level??2}`,{class:"ml-render-heading"}),u.text)];case"Text":return[A(f("p",{class:"ml-render-text"}),u.text)];case"Card":return[Q(f("div",{class:"ml-card","data-variant":u.variant??"default"},f("div",{class:"ml-card-content ml-stack"},G())))];case"Alert":{let m=u.tone??"neutral";return[f("div",{class:"ml-alert",role:m==="danger"||m==="warning"?"alert":"status","data-tone":m,"data-variant":u.variant??"card","data-state":"open"},f("span",{"aria-hidden":"true",class:"ml-alert-icon"},ke(m==="neutral"?"info":m)),f("div",{class:"ml-alert-content"},u.title!==void 0?A(f("p",{class:"ml-alert-title"}),u.title):null,A(f("div",{class:"ml-alert-description"}),u.text)))]}case"EmptyState":{let m=u.children!==void 0?G():[];return[f("section",{class:"ml-empty","data-size":u.size??"inline"},A(f(`h${n.headingLevel(C,B)}`,{class:"ml-empty-title"}),u.title),u.description!==void 0?A(f("p",{class:"ml-empty-description"}),u.description):null,m.length?f("div",{class:"ml-empty-actions"},m):null)]}case"Tabs":{let m=y(x,B,V);if(!m.length)return[];let k=f("div",{class:"ml-tabs-list",role:"tablist","aria-orientation":"horizontal"});S(()=>k.setAttribute("aria-label",X(T(u.label))));let $=[];for(let[O,z]of m.entries()){let N=me(x.base,`${z.key}-tab`),H=me(x.base,`${z.key}-panel`),R=O===0,F=f("button",{class:"ml-tabs-trigger",id:N,type:"button",role:"tab","aria-selected":String(R),"aria-controls":H,tabindex:R?"0":"-1","data-state":R?"active":"inactive"});S(()=>{F.textContent=X(n.read(C,n.component(C,z.id)?.props.label,z.scope))}),k.append(F),$.push(f("div",{class:"ml-tabs-content ml-stack",id:H,role:"tabpanel","aria-labelledby":N,tabindex:"0",hidden:!R,"data-state":R?"active":"inactive"},y(x,z.id,z.scope).flatMap(te=>E(x,te))))}return[f("div",{class:"ml-tabs","data-ml":"tabs","data-variant":u.variant??"default","data-orientation":"horizontal"},k,$)]}case"Accordion":{let m=n.headingLevel(C,B),k=y(x,B,V).map($=>{let O=me(x.base,`${$.key}-trigger`),z=me(x.base,`${$.key}-panel`),N=f("span",{class:"ml-accordion-trigger-label"});return S(()=>{N.textContent=X(n.read(C,n.component(C,$.id)?.props.title,$.scope))}),f("div",{class:"ml-accordion-item","data-state":"closed"},f(`h${m}`,{class:"ml-accordion-heading"},f("button",{class:"ml-accordion-trigger",id:O,type:"button","aria-expanded":"false","aria-controls":z,"data-state":"closed"},N,ke("chevron","ml-accordion-chevron"))),f("div",{class:"ml-accordion-panel",id:z,role:"region","aria-labelledby":O,"data-state":"closed",hidden:!0},f("div",{class:"ml-accordion-panel-inner ml-stack"},y(x,$.id,$.scope).flatMap(H=>E(x,H)))))});return[f("div",{class:"ml-accordion","data-ml":"accordion","data-ml-multiple":u.type==="multiple"?"true":null},k)]}case"Tab":case"AccordionItem":return[];case"Input":case"DatePicker":{let m=Fe(f("input",{class:"ml-input",id:L,type:v.type==="DatePicker"?"date":u.type??"text","data-variant":u.variant??"default","data-size":u.size??"md",maxlength:v.type==="Input"?n.rules.limits.textLength:null,min:u.min,max:u.max}));v.type==="DatePicker"&&J(u.value)&&m.addEventListener("change",()=>W(u.value,m.value||null)),S(()=>{let $=X(T(u.placeholder));$?m.setAttribute("placeholder",$):m.removeAttribute("placeholder")});let k=f("div",{class:"ml-input-field"});return k.append(ue(L),f("div",{class:"ml-input-control"},m),...[Re()].filter(Boolean),re(k,m)),[k]}case"Textarea":{let m=Fe(f("textarea",{class:"ml-textarea",id:L,rows:u.rows??4,maxlength:n.rules.limits.textLength}));S(()=>{let $=X(T(u.placeholder));$?m.setAttribute("placeholder",$):m.removeAttribute("placeholder")});let k=f("div",{class:"ml-input-field"});return k.append(ue(L),m,...[Re()].filter(Boolean),re(k,m)),[k]}case"Select":{let m=`${L}-label`,k=`${L}-list`,$=f("span",{class:"ml-select-value"}),O=f("button",{class:"ml-select",id:L,type:"button",role:"combobox","aria-haspopup":"listbox","aria-expanded":"false","aria-controls":k,"aria-labelledby":m,"data-size":u.size??"md","data-state":"closed"},$,ke("chevron","ml-select-chevron")),z=f("ul",{class:"ml-select-list",id:k,role:"listbox","aria-labelledby":m});_();for(let[H,R]of ee().entries())z.append(f("li",{class:"ml-select-option",id:`${L}-option-${H}`,role:"option","data-value":R.value,"aria-selected":"false","data-state":"unchecked"},R.label));let N=f("div",{class:"ml-select-root","data-ml":"select"},A(f("span",{class:"ml-select-label",id:m}),u.label),f("div",{class:"ml-select-control"},O),f("div",{class:"ml-select-popover"},z));return S(()=>{let H=X(T(u.value)),R=ee().find(F=>F.value===H);$.textContent=R?R.label:X(T(u.placeholder))||"\xA0",$.toggleAttribute("data-placeholder",!R);for(let F of z.children){let te=F.dataset.value===H;F.setAttribute("aria-selected",String(te)),F.dataset.state=te?"checked":"unchecked"}O.disabled=U(),ae()?O.setAttribute("aria-required","true"):O.removeAttribute("aria-required")}),J(u.value)&&N.addEventListener("ml-change",H=>W(u.value,H.detail.value)),N.append(re(N,O)),[N]}case"RadioGroup":{let m=`${L}-label`;_();let k=ee(),$=k.map((R,F)=>f("input",{class:"ml-radio-input",id:`${L}-${F}`,type:"radio",name:L,value:R.value})),O=k.map((R,F)=>f("label",{class:"ml-radio-item",for:`${L}-${F}`,"data-state":"unchecked"},f("span",{class:"ml-radio-control"},$[F],f("span",{class:"ml-radio-indicator","aria-hidden":"true"})),f("span",{class:"ml-radio-copy"},f("span",{class:"ml-radio-label"},R.label)))),z=u.orientation??"vertical",N=f("div",{class:"ml-radio-group",id:L,role:"radiogroup","aria-labelledby":m,"aria-orientation":z,"data-orientation":z},A(f("div",{class:"ml-radio-group-label",id:m}),u.label),f("div",{class:"ml-radio-group-items"},O)),H=X(u.value);S(()=>{let R=J(u.value)?X(T(u.value)):H;for(let[F,te]of $.entries())te.checked=te.value===R,te.disabled=U(),O[F].dataset.state=te.checked?"checked":"unchecked";ae()?N.setAttribute("aria-required","true"):N.removeAttribute("aria-required")});for(let R of $)R.addEventListener("change",()=>{if(J(u.value))W(u.value,R.value);else{H=R.value;for(let F of j)F()}});return N.append(re(N,N)),[N]}case"Checkbox":{let m=f("input",{class:"ml-checkbox-input",id:L,type:"checkbox"}),k=f("span",{class:"ml-checkbox-copy"},f("label",{class:"ml-checkbox-label",for:L},A(f("span",{class:"ml-checkbox-text"}),u.label)),u.description!==void 0?A(f("span",{class:"ml-checkbox-description",id:`${L}-description`}),u.description):null),$=f("div",{class:"ml-checkbox-field","data-state":"unchecked"},f("label",{class:"ml-checkbox-control","data-hit":"expand"},m,f("span",{class:"ml-checkbox-indicator","aria-hidden":"true"},ke("check"))),k);return J(u.checked)||(m.checked=u.checked===!0),S(()=>{J(u.checked)&&(m.checked=T(u.checked)===!0),m.disabled=U(),m.required=ae(),$.dataset.state=m.checked?"checked":"unchecked"}),m.addEventListener("change",()=>{J(u.checked)&&W(u.checked,m.checked),$.dataset.state=m.checked?"checked":"unchecked"}),$.append(re($,m)),[$]}case"Switch":{let m=`${L}-label`,k=f("button",{class:"ml-toggle",id:L,type:"button",role:"switch","data-ml":"switch","aria-checked":String(J(u.checked)?T(u.checked)===!0:u.checked===!0),"aria-labelledby":m,"data-size":u.size??"md","data-hit":"expand"},f("span",{class:"ml-toggle-thumb","aria-hidden":"true"}));return k.dataset.state=k.getAttribute("aria-checked")==="true"?"checked":"unchecked",S(()=>{if(J(u.checked)){let $=T(u.checked)===!0;k.setAttribute("aria-checked",String($)),k.dataset.state=$?"checked":"unchecked"}k.disabled=U()}),J(u.checked)&&k.addEventListener("ml-change",$=>W(u.checked,$.detail.value)),[f("span",{class:"ml-switch-field"},k,A(f("span",{class:"ml-switch-label",id:m}),u.label))]}case"Slider":{let m=u.min??0,k=u.max??100,$=`${L}-label`,O=f("span",{class:"ml-slider-output"}),z=f("span",{class:"ml-slider-range","aria-hidden":"true"}),N=f("span",{class:"ml-slider-thumb",id:L,role:"slider",tabindex:"0","aria-labelledby":$,"aria-valuemin":m,"aria-valuemax":k}),H=f("div",{class:"ml-slider-field","data-ml":"slider","data-size":u.size??"md","data-ml-step":u.step??1},f("div",{class:"ml-slider-header"},A(f("span",{class:"ml-slider-label",id:$}),u.label),O),f("div",{class:"ml-slider"},f("div",{class:"ml-slider-track"},z,N))),R=typeof u.value=="number"?u.value:m;return S(()=>{let F=J(u.value)?T(u.value):R,te=typeof F=="number"&&Number.isFinite(F)?Math.min(k,Math.max(m,F)):m,We=k>m?(te-m)/(k-m)*100:0;N.setAttribute("aria-valuenow",String(te)),O.textContent=String(te),z.style.width=`${We}%`,N.style.left=`${We}%`,U()?(H.dataset.disabled="",N.setAttribute("aria-disabled","true")):(delete H.dataset.disabled,N.removeAttribute("aria-disabled"))}),H.addEventListener("ml-change",F=>{J(u.value)?W(u.value,F.detail.value):R=F.detail.value}),[H]}case"Button":{let m=A(f("span",{class:"ml-button-label"}),u.text),k=Y(f("button",{class:"ml-button",id:L,type:"button","data-variant":u.variant??"primary","data-size":u.size??"md","data-width":u.width==="full"?"full":null},m));return S(()=>{k.disabled=U()}),k.addEventListener("click",()=>I(C,B,V)),[k]}case"Badge":return[f("span",{class:"ml-badge","data-tone":u.tone??"neutral","data-variant":u.variant??"soft","data-size":u.size??"md"},A(f("span",{class:"ml-badge-label"}),u.text))];case"Progress":{let m=u.max??100,k=f("span",{class:"ml-progress-value","aria-hidden":"true"}),$=f("div",{class:"ml-progress-fill","aria-hidden":"true"}),O=f("div",{class:"ml-progress-track",role:"progressbar","aria-valuemin":"0","aria-valuemax":m},$),z=A(f("span"),u.label),N=f("div",{class:"ml-progress-label"},z,k);return S(()=>{let H=T(u.value),R=typeof H=="number"&&Number.isFinite(H)?Math.min(m,Math.max(0,H)):0,F=Math.round(R/m*100);O.setAttribute("aria-valuenow",String(R)),O.setAttribute("aria-valuetext",`${F}%`),O.setAttribute("aria-label",X(T(u.label))),$.style.width=`${F}%`,k.textContent=`${F}%`,k.hidden=T(u.showLabel)!==!0}),[f("div",{class:"ml-progress-root","data-tone":u.tone??"primary","data-size":u.size??"md","data-state":"determinate"},N,O)]}case"Avatar":{let m=f("span",{class:"ml-avatar-fallback",role:"img"}),k=u.status?f("span",{class:"ml-avatar-status",role:"status","data-status":u.status}):null;return S(()=>{let $=X(T(u.name));m.setAttribute("aria-label",$),m.textContent=$.replace(/[^\p{L}\p{N}\s]/gu,"").trim().split(/\s+/).filter(Boolean).slice(0,2).map(O=>O[0].toUpperCase()).join(""),k?.setAttribute("aria-label",`${$} is ${u.status}`)}),[f("span",{class:"ml-avatar-root","data-size":u.size??"md"},f("span",{class:"ml-avatar"},m),k)]}case"Table":{let m=Array.isArray(u.columns)?u.columns:[],k=f("tbody",{class:"ml-table-body"}),$=A(f("caption",{class:"ml-table-caption"}),u.caption),O=f("div",{class:"ml-table-container"},f("table",{class:"ml-table","data-size":u.size??"md"},$,f("thead",{class:"ml-table-header"},f("tr",{class:"ml-table-row"},m.map(z=>A(f("th",{class:"ml-table-head",scope:"col","data-align":z.align??"left"}),z.label)))),k));return S(()=>{O.setAttribute("aria-label",X(T(u.caption)));let z=T(u.rows);k.replaceChildren(...(Array.isArray(z)?z.slice(0,n.rules.limits.rows):[]).map(N=>f("tr",{class:"ml-table-row"},m.map(H=>f("td",{class:"ml-table-cell","data-align":H.align??"left"},rn(N,H.key,i)))))),queueMicrotask(()=>{let N=O.scrollWidth>O.clientWidth+1;N?O.setAttribute("tabindex","0"):O.removeAttribute("tabindex"),O.setAttribute("role",N?"region":"presentation"),N||O.removeAttribute("role")})}),[O]}default:return[]}}let q=n.subscribe(c);return c(),{host:n,receive:(x,M={})=>(t.streaming=!!M.streaming,n.receive(x,M)),setSystemMode:x=>{if(t.systemMode=x??void 0,t.theme!=="inherit")for(let[M,C]of l){let j=n.surface(M)?.theme;j&&(C.node.dataset.mode=s(j))}},destroy:()=>{q(),r.remove()}}}function rn(e,t,n){let i=e!==null&&typeof e=="object"&&Object.hasOwn(e,t)?e[t]:void 0;return typeof i=="boolean"?i?n.yes:n.no:typeof i=="string"||typeof i=="number"?String(i):"\u2014"}var Pe={version:"1.14.1",catalogId:"https://ui.mlola.com/a2ui/catalog/v1",title:"Mlola Render catalog",description:"Mlola UI components for interfaces an agent composes at runtime. Every component is accessible by construction and follows the surface's theme; an agent picks named values (tone, variant, size) and never writes a color, size or class.",protocolVersions:["v0.9","v0.9.1"],themes:["graphite","atelier","machined","aerogel","nordic"],defaultTheme:"graphite",modes:["light","dark","system"],groups:{layout:"Layout",text:"Text",container:"Containers",form:"Forms",action:"Actions",data:"Data"},limits:{messages:200,surfaces:20,components:300,depth:24,idLength:128,textLength:4e3,labelLength:120,options:100,columns:12,rows:500,contextKeys:32,pathLength:512,dataBytes:262144,inputBytes:1048576},components:{Stack:{group:"layout",description:"Places its children in a column with the theme's spacing. Use it as the root of most surfaces.",mlola:{class:"ml-stack"},props:{children:{kind:"children",required:!0,description:"The components inside, top to bottom."}}},Row:{group:"layout",description:"Places its children side by side and wraps them on a narrow screen. Use it for a row of buttons or badges.",mlola:{class:"ml-cluster"},props:{children:{kind:"children",required:!0,description:"The components inside, start to end."}}},Grid:{group:"layout",description:"Places its children in equal columns that collapse to one column on a phone.",mlola:{class:"ml-grid"},props:{children:{kind:"children",required:!0,description:"The components inside, in reading order."},columns:{kind:"enum",description:"How many columns on a wide screen. Leave it out to fit as many as the width allows.",values:["1","2","3","4","6"]}}},Heading:{group:"text",description:"A heading. Levels follow the page outline: never skip a level going deeper.",mlola:{element:"h1-h6"},props:{text:{kind:"text",required:!0,description:"The heading's words.",maxLength:120},level:{kind:"integer",description:"The outline level, 1 to 6. Inside a chat a surface usually starts at 2.",minimum:1,maximum:6,default:2}}},Text:{group:"text",description:"A paragraph of plain text.",mlola:{element:"p"},props:{text:{kind:"text",required:!0,description:"The words. Line breaks are kept; markup is shown as text."}}},Card:{group:"container",description:"Groups related content on a surface of its own.",mlola:{item:"card",export:"Card"},props:{children:{kind:"children",required:!0,description:"The card's content."},variant:{kind:"enum",description:"How the card stands off the page.",values:["default","elevated","glass","specular"],default:"default"}}},Alert:{group:"container",description:"A message about the surface: a confirmation, a warning or an error. Warnings and errors interrupt a screen reader; calmer tones are announced politely.",mlola:{item:"alert",export:"Alert"},props:{title:{kind:"text",description:"A short summary, read first.",maxLength:120},text:{kind:"text",required:!0,description:"What happened and what to do about it."},tone:{kind:"enum",description:"What the message means.",values:["neutral","info","success","warning","danger"],default:"neutral"},variant:{kind:"enum",description:"A card, or a tinted band across the surface.",values:["card","soft"],default:"card"}}},EmptyState:{group:"container",description:"Says that there is nothing here yet and what to do next.",mlola:{item:"empty-state",export:"EmptyState"},props:{title:{kind:"text",required:!0,description:"What is empty, in a few words.",maxLength:120},description:{kind:"text",description:"What to do next."},children:{kind:"children",description:"Actions, usually one or two Buttons."},size:{kind:"enum",description:"inline inside a surface, page when it fills one.",values:["inline","page"],default:"inline"}}},Tabs:{group:"container",description:"Shows one panel at a time, chosen from a row of tabs. Its children are Tab components.",accepts:["Tab"],mlola:{item:"tabs",export:"Tabs"},props:{label:{kind:"text",required:!0,description:"What the tabs choose between, for a screen reader.",maxLength:120},children:{kind:"children",required:!0,description:"The Tab components, in order.",minItems:1},variant:{kind:"enum",description:"The look of the tab row.",values:["default","pills","enclosed"],default:"default"}}},Tab:{group:"container",description:"One tab of a Tabs: its name and its panel.",parents:["Tabs"],mlola:{item:"tabs",export:"TabsTrigger"},props:{label:{kind:"text",required:!0,description:"The tab's name.",maxLength:120},children:{kind:"children",required:!0,description:"What the panel shows."}}},Accordion:{group:"container",description:"A list of sections that open and close. Its children are AccordionItem components.",accepts:["AccordionItem"],mlola:{item:"accordion",export:"Accordion"},props:{children:{kind:"children",required:!0,description:"The AccordionItem components, in order.",minItems:1},type:{kind:"enum",description:"single keeps one section open at a time; multiple lets several stay open.",values:["single","multiple"],default:"single"}}},AccordionItem:{group:"container",description:"One section of an Accordion: its title and its content.",parents:["Accordion"],mlola:{item:"accordion",export:"AccordionItem"},props:{title:{kind:"text",required:!0,description:"The section's title, which opens and closes it.",maxLength:120},children:{kind:"children",required:!0,description:"The section's content."}}},Input:{group:"form",description:"A one-line text field with its label.",mlola:{item:"input",export:"Input"},props:{label:{kind:"text",required:!0,description:"The field's name, shown above it and read by a screen reader.",maxLength:120},value:{kind:"text",description:'Bind it to the data model ({"path": "/form/email"}) so the value comes back with the action.'},type:{kind:"enum",description:"The kind of text, which picks the phone keyboard and the browser's checks.",values:["text","email","password","url","tel","search"],default:"text"},placeholder:{kind:"text",description:"An example of what to type. Never a replacement for the label.",maxLength:120},hint:{kind:"text",description:"Help shown under the field.",maxLength:120},required:{kind:"boolean",description:"The form cannot be sent without it."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"},variant:{kind:"enum",description:"How the field sits on its surface.",values:["default","filled","subtle"],default:"default"}}},Textarea:{group:"form",description:"A text field for several lines, with its label.",mlola:{item:"textarea",export:"Textarea"},props:{label:{kind:"text",required:!0,description:"The field's name.",maxLength:120},value:{kind:"text",description:"Bind it to the data model so the value comes back with the action."},placeholder:{kind:"text",description:"An example of what to type. Never the only label.",maxLength:120},hint:{kind:"text",description:"A short help line under the field.",maxLength:120},rows:{kind:"integer",description:"How many lines show before it scrolls.",minimum:2,maximum:12,default:4},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Select:{group:"form",description:"Picks one value from a list that opens on demand. Use RadioGroup when there are only two to five options and room to show them.",mlola:{item:"select",export:"Select"},props:{label:{kind:"text",required:!0,description:"The field's name.",maxLength:120},options:{kind:"options",required:!0,description:'The choices, each {"label", "value"}.',minItems:1},value:{kind:"text",description:"The chosen option's value. Bind it to the data model."},placeholder:{kind:"text",description:"Shown while nothing is chosen.",maxLength:120},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},RadioGroup:{group:"form",description:"Picks one value from options that are all visible.",mlola:{item:"radio-group",export:"RadioGroup"},props:{label:{kind:"text",required:!0,description:"The question the options answer.",maxLength:120},options:{kind:"options",required:!0,description:'The choices, each {"label", "value"}.',minItems:2},value:{kind:"text",description:"The chosen option's value. Bind it to the data model."},orientation:{kind:"enum",description:"Options stacked or in a row.",values:["horizontal","vertical"],default:"vertical"},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Checkbox:{group:"form",description:"A yes or no choice with its label.",mlola:{item:"checkbox",export:"Checkbox"},props:{label:{kind:"text",required:!0,description:"What checking it means.",maxLength:120},checked:{kind:"boolean",description:"Bind it to the data model so the choice comes back with the action."},description:{kind:"text",description:"More about the choice, under the label.",maxLength:120},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Switch:{group:"form",description:"Turns a setting on or off right away.",mlola:{item:"toggle",export:"Switch"},props:{label:{kind:"text",required:!0,description:"The setting it turns on.",maxLength:120},checked:{kind:"boolean",description:"Bind it to the data model."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},Slider:{group:"form",description:"Picks a number in a range by dragging or with the arrow keys.",mlola:{item:"slider",export:"Slider"},props:{label:{kind:"text",required:!0,description:"What the number is.",maxLength:120},value:{kind:"number",description:"Bind it to the data model."},min:{kind:"number",description:"The lowest value.",literal:!0,default:0},max:{kind:"number",description:"The highest value.",literal:!0,default:100},step:{kind:"number",description:"How far one arrow press moves it.",literal:!0,default:1},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md"],default:"md"}}},DatePicker:{group:"form",description:"A date field that opens a calendar and picks one day. The reader sees the date in their own format; the value is an ISO date.",mlola:{item:"date-picker",export:"DatePicker"},props:{label:{kind:"text",required:!0,description:"The field's name.",maxLength:120},value:{kind:"date",description:'The chosen day as an ISO date, like "2026-10-12". Bind it to the data model so it comes back with the action.'},min:{kind:"date",description:"The earliest day that can be picked.",literal:!0},max:{kind:"date",description:"The latest day that can be picked.",literal:!0},hint:{kind:"text",description:"Help shown under the field.",maxLength:120},required:{kind:"boolean",description:"The form cannot be sent without it."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Button:{group:"action",description:'Sends an action back to the agent. Its text says what happens ("Create workspace", not "Submit").',mlola:{item:"button",export:"Button"},props:{text:{kind:"text",required:!0,description:"What pressing it does.",maxLength:120},action:{kind:"action",required:!0,description:"The event sent when it is pressed."},variant:{kind:"enum",description:"primary for the main action of a surface, one at most.",values:["primary","secondary","subtle","danger","outline","link"],default:"primary"},size:{kind:"enum",description:"Icon-only buttons are not in the catalog: every button has words.",values:["sm","md","lg"],excluded:["icon"],default:"md"},width:{kind:"enum",description:"auto fits the words, full fills the container.",values:["auto","full"],default:"auto"},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Badge:{group:"data",description:"A short label for a status or a count.",mlola:{item:"badge",export:"Badge"},props:{text:{kind:"text",required:!0,description:"The badge's words, a few at most.",maxLength:120},tone:{kind:"enum",description:"What the status means.",values:["neutral","primary","info","success","warning","danger"],default:"neutral"},variant:{kind:"enum",description:"How strongly the badge stands out.",values:["soft","solid","outline"],default:"soft"},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},Progress:{group:"data",description:"Shows how far along something is.",mlola:{item:"progress",export:"Progress"},props:{label:{kind:"text",required:!0,description:"What is in progress, for a screen reader.",maxLength:120},value:{kind:"number",description:"How far along, from 0 to max."},max:{kind:"number",description:"The value that means complete.",literal:!0,default:100},showLabel:{kind:"boolean",description:"Shows the percentage beside the bar."},tone:{kind:"enum",description:"What the progress means.",values:["primary","info","success","warning","danger"],default:"primary"},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},Avatar:{group:"data",description:"A person or a team shown by their initials.",mlola:{item:"avatar",export:"Avatar"},props:{name:{kind:"text",required:!0,description:"The full name: the initials come from it and a screen reader reads it.",maxLength:120},size:{kind:"enum",description:"The avatar's size.",values:["xs","sm","md","lg","xl"],default:"md"},status:{kind:"enum",description:"A presence dot, announced with the name.",values:["online","offline","away","busy"]}}},Table:{group:"data",description:"Rows of data under named columns. Cells hold text and numbers.",mlola:{item:"table",export:"Table"},props:{caption:{kind:"text",required:!0,description:"What the table shows, read first by a screen reader.",maxLength:120},columns:{kind:"columns",required:!0,description:'Each {"key", "label", "align"?}: key names the row field the column shows.',minItems:1,align:{values:["left","center","right"]}},rows:{kind:"rows",required:!0,description:"An array of objects keyed by column key, or a path to one in the data model."},size:{kind:"enum",description:"Row density.",values:["sm","md"],default:"md"}}}},aliases:{Column:"Stack",List:"Stack",TextField:"Input",CheckBox:"Checkbox",ChoicePicker:"Select",Toggle:"Switch",Label:"Text",Paragraph:"Text",Title:"Heading",Callout:"Alert",Banner:"Alert",Chip:"Badge",Tag:"Badge",ProgressBar:"Progress",DataTable:"Table",DataGrid:"Table",DateTimeInput:"DatePicker",DateInput:"DatePicker",Calendar:"DatePicker"},borrowed:{components:{Image:"Say what matters in Text, or leave the image out.",Icon:"Every control has words: put the meaning in the text, or in a Badge.",Video:"Describe it in Text, or leave it out.",AudioPlayer:"Describe it in Text, or leave it out.",Modal:"A surface shows inline, with no dialog. Put the content on the surface, or in a Tab or an AccordionItem to keep it out of the way.",Divider:"Spacing comes from Stack, and a Card or a Heading separates groups. Leave the divider out."},props:{weight:"Children share space by the theme's layout. For equal columns use a Grid.",justify:"A Row or a Stack places its children by the theme's layout. For equal columns use a Grid.",align:"A Row or a Stack places its children by the theme's layout. For equal columns use a Grid.","Stack.direction":"A Stack is a column. For side by side use a Row.","Text.variant":'Text is one style of paragraph. For a heading use a Heading with "level".',"Button.child":'A Button holds its words in "text", not in a child component.',"Tabs.tabs":`A Tabs' "children" are Tab components, each with a "label" and "children".`,"Checkbox.value":`A Checkbox's state is "checked": true, false or {"path": "/\u2026"}.`,"Switch.value":`A Switch's state is "checked": true, false or {"path": "/\u2026"}.`,"Input.validationRegexp":'Client-side checks are not in the Mlola catalog yet. Mark the field "required", and check the value when the action arrives.',"Select.variant":"A Select picks one value. For several choices, use a Checkbox for each.","Select.displayStyle":"A Select always opens a list. For options that are all visible use a RadioGroup.","Select.filterable":"A Select lists its options as they are. Keep to the ones that matter, at most 100.","Input.variant=longText":"For several lines use a Textarea.","Input.variant=obscured":'For a password use "type": "password".',"Input.variant=number":"Numbers are not a field type yet. Use a Slider for a number in a range, or an Input with a hint.","Input.variant=shortText":'An Input is one line already, so leave "variant" out.',"Input.type=number":"Numbers are not a field type yet. Use a Slider for a number in a range, or an Input with a hint.","Input.type=date":"For a day use a DatePicker.","Input.type=time":'Times are not a field type yet. Use a Select of the times on offer, or an Input with a hint like "19:30".',"Input.autocomplete":'The browser fills a field in by its "type": use "email", "tel" or "url" where one fits, and leave "autocomplete" out.',"Switch.description":'A Switch has only its "label". Say the rest in a Text before it, or use a Checkbox, which takes a "description".',"Switch.hint":'A Switch has only its "label". Say the rest in a Text before it, or use a Checkbox, which takes a "description".',"Button.variant=default":'For a button beside the main one use "secondary".',"Button.variant=borderless":'For a quiet button use "subtle" or "link".',"DatePicker.enableDate":'A DatePicker always picks a day, so leave "enableDate" out.',"DatePicker.enableTime":"Times are not in the Mlola catalog yet: a DatePicker picks a day. Ask for the time in an Input with a hint."}},examples:[]};var sn="2026-01-26",ze=document.documentElement,ft=document.querySelector("#status"),ve=new Map,Ne=0,we=e=>window.parent.postMessage({jsonrpc:"2.0",...e},"*"),bt=(e,t={})=>we({method:e,params:t}),yt=(e,t={})=>new Promise((n,i)=>{Ne+=1,ve.set(Ne,{resolve:n,reject:i}),we({id:Ne,method:e,params:t})}),xe=e=>{ft.textContent=e,ft.hidden=!e};function kt(e){let t=e?.theme==="dark"?"dark":e?.theme==="light"?"light":null;t&&(ze.dataset.mode=t,de.setSystemMode(t))}var de=pt(document.querySelector("#surfaces"),{rules:Pe,onAction:e=>{let{surfaceId:t,sourceComponentId:n}=e.action,o=`I pressed "${de.host.read(t,de.host.component(t,n)?.props.text)}" in the ${t} surface. A2UI action: ${JSON.stringify(e)}`;yt("ui/message",{role:"user",content:[{type:"text",text:o}]}).catch(()=>xe("The host did not take the message. Try again."))}});function gt(e,t){let n=e?.messages;if(de.host.reset(),n===void 0)return;let i=de.receive(n,{streaming:t});t||xe(i.errors.length&&!de.host.surfaces().length?"The agent's interface had errors, so it is not shown. The agent has been told what to fix.":"")}window.addEventListener("message",e=>{if(e.source!==window.parent)return;let t=e.data;if(!(!t||t.jsonrpc!=="2.0")){if(t.id!==void 0&&ve.has(t.id)&&("result"in t||"error"in t)){let{resolve:n,reject:i}=ve.get(t.id);ve.delete(t.id),"error"in t?i(t.error):n(t.result);return}switch(t.method){case"ui/notifications/tool-input-partial":gt(t.params?.arguments,!0);break;case"ui/notifications/tool-input":gt(t.params?.arguments,!1);break;case"ui/notifications/tool-cancelled":de.host.surfaces().length||xe("The agent stopped before the interface was ready.");break;case"ui/notifications/host-context-changed":kt(t.params);break;case"ui/resource-teardown":case"ping":we({id:t.id,result:{}});break;default:t.id!==void 0&&t.method&&we({id:t.id,error:{code:-32601,message:`Method not found: ${t.method}`}})}}});var Be=0;new ResizeObserver(()=>{let e=Math.ceil(ze.getBoundingClientRect().height);e!==Be&&(Be=e,bt("ui/notifications/size-changed",{width:Math.ceil(ze.getBoundingClientRect().width),height:Be}))}).observe(document.body);yt("ui/initialize",{appInfo:{name:"mlola-render",version:Pe.version},appCapabilities:{availableDisplayModes:["inline"]},protocolVersion:sn}).then(e=>{kt(e?.hostContext),bt("ui/notifications/initialized")}).catch(e=>xe(`The host did not start this view${e?.message?`: ${e.message}`:"."}`));})();
8479
8496
  </script>
8480
8497
  </body>
8481
8498
  </html>
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://ui.mlola.com/a2ui/catalog/v1",
4
4
  "title": "Mlola Render catalog",
5
- "description": "Mlola UI components for interfaces an agent composes at runtime. Every component is accessible by construction and follows the surface's theme; an agent picks named values (tone, variant, size) and never writes a color, size or class. Generated from Mlola UI 1.13.2; check messages with `npx mlola-ui render check` or the check_render MCP tool, which also hold what a schema cannot (one root, no loops, heading order, values in range).",
5
+ "description": "Mlola UI components for interfaces an agent composes at runtime. Every component is accessible by construction and follows the surface's theme; an agent picks named values (tone, variant, size) and never writes a color, size or class. Generated from Mlola UI 1.14.1; check messages with `npx mlola-ui render check` or the check_render MCP tool, which also hold what a schema cannot (one root, no loops, heading order, values in range).",
6
6
  "catalogId": "https://ui.mlola.com/a2ui/catalog/v1",
7
7
  "components": {
8
8
  "Stack": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$comment": "Generated by scripts/build-render-catalog.mjs from packages/registry/render/definition.json. Do not edit.",
3
- "version": "1.13.2",
3
+ "version": "1.14.1",
4
4
  "catalogId": "https://ui.mlola.com/a2ui/catalog/v1",
5
5
  "title": "Mlola Render catalog",
6
6
  "description": "Mlola UI components for interfaces an agent composes at runtime. Every component is accessible by construction and follows the surface's theme; an agent picks named values (tone, variant, size) and never writes a color, size or class.",
@@ -235,7 +235,11 @@ function Node({ drawing, instance }: { drawing: Drawing; instance: RenderInstanc
235
235
  </div>
236
236
  );
237
237
  case "Heading":
238
- return <Heading level={as<HeadingLevel>(props.level ?? 2)}>{text(read(props.text))}</Heading>;
238
+ return (
239
+ <Heading className="ml-render-heading" level={as<HeadingLevel>(props.level ?? 2)}>
240
+ {text(read(props.text))}
241
+ </Heading>
242
+ );
239
243
  case "Text":
240
244
  return <p className="ml-render-text">{text(read(props.text))}</p>;
241
245
  case "Card":
@@ -48,7 +48,7 @@
48
48
  "packages/components/progress/progress.tsx": "sha256-oDxj1Ccl1pKV4+e6A7aaJL1FThW8qs9r4Gb0hEmExeM=",
49
49
  "packages/components/radio-group/radio-group.tsx": "sha256-jhnSEBLkdpe8dv5us/Q1sMsQF4sKGRgDXWGKm2JSFew=",
50
50
  "packages/components/rating/rating.tsx": "sha256-prhfNzlCqLRWqURtq0MrX6MLdtuDpIOf5fA1Ie26L54=",
51
- "packages/components/render-surface/render-surface.tsx": "sha256-nW48kYLXoa3eeGZQ7gXMD/bTNH9MDeJlWyl1zzrvDwo=",
51
+ "packages/components/render-surface/render-surface.tsx": "sha256-6dKHxnovy48yojPa3rukx8Vs9mH48G4avLnoYmhZf0Q=",
52
52
  "packages/components/resizable/resizable.tsx": "sha256-RFBpg/a2O82mmx+O5wT+um+y3y2w0rUMJJdBzRu9ONU=",
53
53
  "packages/components/segmented-control/segmented-control.tsx": "sha256-MCBG5XHFWCwbACctsYKbqe8mvSSR6pf60tyRgdCDKDA=",
54
54
  "packages/components/select/select.tsx": "sha256-7u1sshW6KAQgjgwQ1siN1P5GkBxboOiOJOdgLanForE=",