@optiaxiom/proteus 0.2.11 → 0.2.12

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.
@@ -1,5 +1,5 @@
1
- @layer optiaxiom._1om87vs;
2
- @layer optiaxiom._1om87vs {
1
+ @layer optiaxiom._2eth5s;
2
+ @layer optiaxiom._2eth5s {
3
3
  .ProteusChart__jmlqij1 {
4
4
  border-radius: 16px;
5
5
  }
@@ -1,5 +1,5 @@
1
- @layer optiaxiom._1om87vs;
2
- @layer optiaxiom._1om87vs {
1
+ @layer optiaxiom._2eth5s;
2
+ @layer optiaxiom._2eth5s {
3
3
  .ProteusChartTooltipContent__1gsvq810 {
4
4
  min-width: 128px;
5
5
  position: absolute;
@@ -1,5 +1,5 @@
1
- @layer optiaxiom._1om87vs;
2
- @layer optiaxiom._1om87vs {
1
+ @layer optiaxiom._2eth5s;
2
+ @layer optiaxiom._2eth5s {
3
3
  .ProteusDocumentShell__vpuvfj1 {
4
4
  margin: -4px;
5
5
  }
@@ -1,5 +1,5 @@
1
- @layer optiaxiom._1om87vs;
2
- @layer optiaxiom._1om87vs {
1
+ @layer optiaxiom._2eth5s;
2
+ @layer optiaxiom._2eth5s {
3
3
  .ProteusImageCarousel__1t6qej70 {
4
4
  outline: none;
5
5
  user-select: none;
@@ -1,5 +1,5 @@
1
- @layer optiaxiom._1om87vs;
2
- @layer optiaxiom._1om87vs {
1
+ @layer optiaxiom._2eth5s;
2
+ @layer optiaxiom._2eth5s {
3
3
  .ProteusQuestion__8f590p0 {
4
4
  outline: none;
5
5
  }
@@ -1,4 +1,4 @@
1
- import './../assets/src/proteus-chart/ProteusChart.css.ts.vanilla-Bhea5BpW.css';
1
+ import './../assets/src/proteus-chart/ProteusChart.css.ts.vanilla-B_WDPh7C.css';
2
2
  import { recipe } from '@optiaxiom/react/css-runtime';
3
3
 
4
4
  var chart = recipe({base:[{border:'1',borderColor:'border.tertiary',fontSize:'sm',p:'16'},'ProteusChart__jmlqij1','ProteusChart__jmlqij0']});
@@ -1,4 +1,4 @@
1
- import './../assets/src/proteus-chart/ProteusChartTooltipContent.css.ts.vanilla-7xvqKrcf.css';
1
+ import './../assets/src/proteus-chart/ProteusChartTooltipContent.css.ts.vanilla-UZNvVvUU.css';
2
2
  import { recipe } from '@optiaxiom/react/css-runtime';
3
3
 
4
4
  var tooltip = recipe({base:[{bg:'bg.default',border:'1',borderColor:'border.secondary',display:'grid',fontSize:'sm',gap:'6',pointerEvents:'none',px:'8',py:'10',rounded:'lg',shadow:'lg',transition:'all',z:'popover'},'ProteusChartTooltipContent__1gsvq810']});
@@ -1,4 +1,4 @@
1
- import './../assets/src/proteus-document/ProteusDocumentShell.css.ts.vanilla-Bil1PxGV.css';
1
+ import './../assets/src/proteus-document/ProteusDocumentShell.css.ts.vanilla-N08uRH65.css';
2
2
  import { recipe } from '@optiaxiom/react/css-runtime';
3
3
 
4
4
  var body = recipe({base:[{flexDirection:'column',gap:'16'},'ProteusDocumentShell__vpuvfj0'],variants:{truncate:{false:{},true:[{maxH:'sm',overflow:'auto',p:'4'},'ProteusDocumentShell__vpuvfj1']}}});
@@ -95,6 +95,7 @@ function resolveProteusValue(value, data, parentPath, mapIndices = []) {
95
95
  [...mapIndices, index]
96
96
  )
97
97
  ).filter((v) => v !== void 0);
98
+ const result = "flat" in value && value.flat ? items.flat() : items;
98
99
  if ("separator" in value) {
99
100
  const sep = resolveProteusValue(
100
101
  value.separator,
@@ -102,9 +103,9 @@ function resolveProteusValue(value, data, parentPath, mapIndices = []) {
102
103
  parentPath,
103
104
  mapIndices
104
105
  );
105
- return items.join(typeof sep === "string" ? sep : "");
106
+ return result.join(typeof sep === "string" ? sep : "");
106
107
  }
107
- return items;
108
+ return result;
108
109
  }
109
110
  if (value.$type === "Show" && "when" in value && "children" in value) {
110
111
  const conditions = Array.isArray(value.when) ? value.when : [value.when];
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { IconPlus } from '@optiaxiom/icons';
3
4
  import { Flex } from '@optiaxiom/react';
4
- import { FileUpload, VisuallyHidden, FileUploadList, FileUploadDropzone, FileUploadTrigger } from '@optiaxiom/react/unstable';
5
+ import { FileUpload, VisuallyHidden, FileUploadTrigger, FileUploadList, FileUploadDropzone } from '@optiaxiom/react/unstable';
5
6
  import { useRef, useState, useCallback } from 'react';
6
7
  import { useObserveValue } from '../hooks/useObserveValue.js';
7
8
  import { useProteusDocumentContext } from '../proteus-document/ProteusDocumentContext.js';
@@ -9,8 +10,9 @@ import { useProteusDocumentPathContext } from '../proteus-document/ProteusDocume
9
10
 
10
11
  function ProteusFileUpload({
11
12
  accept,
12
- name,
13
- required
13
+ maxFiles,
14
+ minFiles = 0,
15
+ name
14
16
  }) {
15
17
  const { onDataChange, onUpload, readOnly } = useProteusDocumentContext(
16
18
  "@optiaxiom/proteus/ProteusFileUpload"
@@ -19,71 +21,100 @@ function ProteusFileUpload({
19
21
  "@optiaxiom/proteus/ProteusFileUpload"
20
22
  );
21
23
  const inputRef = useRef(null);
22
- const [item, setItem] = useState(null);
24
+ const itemsRef = useRef([]);
25
+ const [items, setItems] = useState([]);
23
26
  const forceValueChange = useObserveValue(inputRef);
24
- const writeUrl = useCallback(
25
- (url) => {
26
- if (!name)
27
- return;
28
- onDataChange?.(`${parentPath}/${name}`, url);
29
- },
30
- [name, onDataChange, parentPath]
31
- );
27
+ const multiple = maxFiles !== 1;
28
+ const atMax = multiple && maxFiles !== void 0 && items.length >= maxFiles;
29
+ const writeValue = useCallback(() => {
30
+ setItems(itemsRef.current);
31
+ if (inputRef.current) {
32
+ forceValueChange(
33
+ itemsRef.current.filter((item) => item.status === "complete").length.toString()
34
+ );
35
+ }
36
+ if (name) {
37
+ const value = itemsRef.current.filter((item) => item.status === "complete").map((item) => item.metadata).filter((metadata) => !!metadata);
38
+ onDataChange?.(`${parentPath}/${name}`, value);
39
+ }
40
+ }, [forceValueChange, name, onDataChange, parentPath]);
32
41
  const handleFilesDrop = useCallback(
33
42
  async (incoming) => {
43
+ if (multiple) {
44
+ incoming = maxFiles !== void 0 ? incoming.slice(0, Math.max(0, maxFiles - itemsRef.current.length)) : incoming;
45
+ } else {
46
+ incoming = incoming.slice(0, 1);
47
+ }
34
48
  if (!onUpload || readOnly || incoming.length === 0) {
35
49
  return;
36
50
  }
37
- const file = incoming[0];
38
- setItem({ file, status: "uploading" });
39
- writeUrl(null);
40
- if (inputRef.current) {
41
- forceValueChange("");
42
- }
43
- try {
44
- const url = await onUpload(file);
45
- setItem(
46
- (curr) => curr?.file === file ? { file, status: "complete" } : curr
47
- );
48
- writeUrl(url);
49
- if (inputRef.current) {
50
- forceValueChange("1");
51
- }
52
- } catch {
53
- setItem(
54
- (curr) => curr?.file === file ? { file, status: "error" } : curr
55
- );
56
- }
51
+ itemsRef.current = [
52
+ ...multiple ? itemsRef.current : [],
53
+ ...incoming.map((file) => ({ file, status: "uploading" }))
54
+ ];
55
+ writeValue();
56
+ const result = new Map(
57
+ await Promise.all(
58
+ incoming.map(
59
+ (file) => onUpload(file).then(
60
+ (metadata) => [
61
+ file,
62
+ {
63
+ file,
64
+ metadata,
65
+ status: "complete"
66
+ }
67
+ ]
68
+ ).catch(
69
+ () => [
70
+ file,
71
+ {
72
+ file,
73
+ status: "error"
74
+ }
75
+ ]
76
+ )
77
+ )
78
+ )
79
+ );
80
+ itemsRef.current = itemsRef.current.map(
81
+ (item) => result.get(item.file) ?? item
82
+ );
83
+ writeValue();
57
84
  },
58
- [forceValueChange, onUpload, readOnly, writeUrl]
85
+ [maxFiles, multiple, onUpload, readOnly, writeValue]
86
+ );
87
+ const handleRemove = useCallback(
88
+ (item) => {
89
+ itemsRef.current = itemsRef.current.filter((i) => i !== item);
90
+ writeValue();
91
+ },
92
+ [writeValue]
59
93
  );
60
- const handleRemove = useCallback(() => {
61
- setItem(null);
62
- writeUrl(null);
63
- if (inputRef.current) {
64
- forceValueChange("");
65
- }
66
- }, [forceValueChange, writeUrl]);
67
94
  return /* @__PURE__ */ jsxs(
68
95
  FileUpload,
69
96
  {
70
97
  accept,
71
- disabled: !onUpload || readOnly,
98
+ disabled: !onUpload || readOnly || atMax,
72
99
  onFilesDrop: handleFilesDrop,
73
100
  children: [
74
101
  /* @__PURE__ */ jsx(VisuallyHidden, { asChild: true, children: /* @__PURE__ */ jsx(
75
102
  "input",
76
103
  {
77
104
  "aria-hidden": true,
105
+ defaultValue: 0,
106
+ max: maxFiles !== void 0 ? String(maxFiles) : void 0,
107
+ min: String(minFiles),
78
108
  name,
79
109
  ref: inputRef,
80
- required,
81
- tabIndex: -1
110
+ tabIndex: -1,
111
+ type: "number"
82
112
  }
83
113
  ) }),
84
- item ? /* @__PURE__ */ jsxs(Flex, { flexDirection: "column", gap: "8", children: [
85
- /* @__PURE__ */ jsx(FileUploadList, { items: [item], onRemove: handleRemove }),
86
- /* @__PURE__ */ jsx(FileUploadDropzone, { overlay: true })
114
+ items.length > 0 ? /* @__PURE__ */ jsxs(Flex, { flexDirection: "column", gap: "8", children: [
115
+ multiple && !atMax && /* @__PURE__ */ jsx(FileUploadTrigger, { alignSelf: "end", icon: /* @__PURE__ */ jsx(IconPlus, {}), children: "Add File" }),
116
+ /* @__PURE__ */ jsx(FileUploadList, { items, onRemove: handleRemove }),
117
+ !atMax && /* @__PURE__ */ jsx(FileUploadDropzone, { overlay: true })
87
118
  ] }) : /* @__PURE__ */ jsx(FileUploadDropzone, { children: /* @__PURE__ */ jsx(FileUploadTrigger, {}) })
88
119
  ]
89
120
  }
@@ -1,4 +1,4 @@
1
- import './../assets/src/proteus-image-carousel/ProteusImageCarousel.css.ts.vanilla-CKWS5NjD.css';
1
+ import './../assets/src/proteus-image-carousel/ProteusImageCarousel.css.ts.vanilla-DPgPnDmb.css';
2
2
  import { recipe } from '@optiaxiom/react/css-runtime';
3
3
 
4
4
  var carousel = recipe({base:[{flexDirection:'column',gap:'12'},'ProteusImageCarousel__1t6qej70']});
@@ -1,4 +1,4 @@
1
- import './../assets/src/proteus-question/ProteusQuestion.css.ts.vanilla-B04UzIcJ.css';
1
+ import './../assets/src/proteus-question/ProteusQuestion.css.ts.vanilla-BAhvFxEB.css';
2
2
  import { recipe } from '@optiaxiom/react/css-runtime';
3
3
 
4
4
  var addon = recipe({base:[{display:'grid',fontWeight:'500',placeItems:'center',rounded:'lg',size:'md',transition:'colors'},'ProteusQuestion__8f590p3'],variants:{cursor:{pointer:{cursor:'pointer'}}}});
@@ -2194,8 +2194,8 @@ var definitions = {
2194
2194
  }
2195
2195
  ]
2196
2196
  },
2197
- maxItems: 2,
2198
- minItems: 2,
2197
+ maxFiles: 2,
2198
+ minFiles: 2,
2199
2199
  type: "array"
2200
2200
  }
2201
2201
  },
@@ -2231,8 +2231,8 @@ var definitions = {
2231
2231
  }
2232
2232
  ]
2233
2233
  },
2234
- maxItems: 2,
2235
- minItems: 2,
2234
+ maxFiles: 2,
2235
+ minFiles: 2,
2236
2236
  type: "array"
2237
2237
  }
2238
2238
  },
@@ -2268,8 +2268,8 @@ var definitions = {
2268
2268
  }
2269
2269
  ]
2270
2270
  },
2271
- maxItems: 2,
2272
- minItems: 2,
2271
+ maxFiles: 2,
2272
+ minFiles: 2,
2273
2273
  type: "array"
2274
2274
  }
2275
2275
  },
@@ -2305,8 +2305,8 @@ var definitions = {
2305
2305
  }
2306
2306
  ]
2307
2307
  },
2308
- maxItems: 2,
2309
- minItems: 2,
2308
+ maxFiles: 2,
2309
+ minFiles: 2,
2310
2310
  type: "array"
2311
2311
  }
2312
2312
  },
@@ -2342,8 +2342,8 @@ var definitions = {
2342
2342
  }
2343
2343
  ]
2344
2344
  },
2345
- maxItems: 2,
2346
- minItems: 2,
2345
+ maxFiles: 2,
2346
+ minFiles: 2,
2347
2347
  type: "array"
2348
2348
  }
2349
2349
  },
@@ -2379,8 +2379,8 @@ var definitions = {
2379
2379
  }
2380
2380
  ]
2381
2381
  },
2382
- maxItems: 2,
2383
- minItems: 2,
2382
+ maxFiles: 2,
2383
+ minFiles: 2,
2384
2384
  type: "array"
2385
2385
  }
2386
2386
  },
@@ -2461,7 +2461,7 @@ var definitions = {
2461
2461
  items: {
2462
2462
  $ref: "#/definitions/ProteusCondition"
2463
2463
  },
2464
- minItems: 1,
2464
+ minFiles: 1,
2465
2465
  type: "array"
2466
2466
  }
2467
2467
  },
@@ -2482,7 +2482,7 @@ var definitions = {
2482
2482
  }
2483
2483
  ]
2484
2484
  },
2485
- minItems: 1,
2485
+ minFiles: 1,
2486
2486
  type: "array"
2487
2487
  }
2488
2488
  },
@@ -2979,13 +2979,25 @@ var definitions = {
2979
2979
  },
2980
2980
  ProteusStructuredMessage: {
2981
2981
  additionalProperties: false,
2982
- description: "Structured message payload that lets file URLs travel as a typed list alongside the text parts, instead of being joined into the text.",
2982
+ description: "Structured message payload that lets file metadata travel as a typed list alongside the text parts, instead of being joined into the text.",
2983
2983
  properties: {
2984
2984
  files: {
2985
2985
  anyOf: [
2986
2986
  {
2987
2987
  items: {
2988
- type: "string"
2988
+ properties: {
2989
+ link: {
2990
+ type: "string"
2991
+ },
2992
+ name: {
2993
+ type: "string"
2994
+ }
2995
+ },
2996
+ required: [
2997
+ "name",
2998
+ "link"
2999
+ ],
3000
+ type: "object"
2989
3001
  },
2990
3002
  type: "array"
2991
3003
  },
@@ -2993,7 +3005,7 @@ var definitions = {
2993
3005
  $ref: "#/definitions/ProteusExpression"
2994
3006
  }
2995
3007
  ],
2996
- description: "List of file URLs (typically signed URLs from a host upload)."
3008
+ description: "List of uploaded file metadata objects (typically the host's onUpload return value). Hosts may attach additional fields beyond `name` and `link`."
2997
3009
  },
2998
3010
  parts: {
2999
3011
  items: {
@@ -5233,27 +5245,38 @@ var definitions = {
5233
5245
  },
5234
5246
  type: "array"
5235
5247
  },
5236
- name: {
5248
+ maxFiles: {
5237
5249
  anyOf: [
5238
5250
  {
5239
- type: "string"
5251
+ type: "number"
5240
5252
  },
5241
5253
  {
5242
5254
  $ref: "#/definitions/ProteusExpression"
5243
5255
  }
5244
5256
  ],
5245
- description: "The name of the form control element. The resolved URL is written at parentPath/name in form data."
5257
+ description: "Maximum number of files allowed. When set to 1 the field is in single-file mode; any other value (or omitted) allows multiple uploads."
5246
5258
  },
5247
- required: {
5259
+ minFiles: {
5248
5260
  anyOf: [
5249
5261
  {
5250
- type: "boolean"
5262
+ type: "number"
5263
+ },
5264
+ {
5265
+ $ref: "#/definitions/ProteusExpression"
5266
+ }
5267
+ ],
5268
+ description: "Minimum number of files required."
5269
+ },
5270
+ name: {
5271
+ anyOf: [
5272
+ {
5273
+ type: "string"
5251
5274
  },
5252
5275
  {
5253
5276
  $ref: "#/definitions/ProteusExpression"
5254
5277
  }
5255
5278
  ],
5256
- description: "Whether a file is required."
5279
+ description: "The name of the form control element. The resolved metadata array is written at parentPath/name in form data."
5257
5280
  }
5258
5281
  },
5259
5282
  required: [
@@ -6745,6 +6768,10 @@ var definitions = {
6745
6768
  $ref: "#/definitions/ProteusNode",
6746
6769
  description: "Template object to render for each item in the array. Value paths inside this template are relative to the current item (e.g., path='title' resolves to each item's 'title' field). Use a leading '/' to reference top-level data (e.g., path='/title' resolves to the root data's 'title')."
6747
6770
  },
6771
+ flat: {
6772
+ description: "When true, flattens the result array by one level. Useful when each mapped item resolves to an array and you want a single flat list.",
6773
+ type: "boolean"
6774
+ },
6748
6775
  path: {
6749
6776
  description: "JSON pointer path to the source array in the data (e.g., '/results')",
6750
6777
  type: "string"
@@ -2192,8 +2192,8 @@ var definitions = {
2192
2192
  }
2193
2193
  ]
2194
2194
  },
2195
- maxItems: 2,
2196
- minItems: 2,
2195
+ maxFiles: 2,
2196
+ minFiles: 2,
2197
2197
  type: "array"
2198
2198
  }
2199
2199
  },
@@ -2228,8 +2228,8 @@ var definitions = {
2228
2228
  }
2229
2229
  ]
2230
2230
  },
2231
- maxItems: 2,
2232
- minItems: 2,
2231
+ maxFiles: 2,
2232
+ minFiles: 2,
2233
2233
  type: "array"
2234
2234
  }
2235
2235
  },
@@ -2264,8 +2264,8 @@ var definitions = {
2264
2264
  }
2265
2265
  ]
2266
2266
  },
2267
- maxItems: 2,
2268
- minItems: 2,
2267
+ maxFiles: 2,
2268
+ minFiles: 2,
2269
2269
  type: "array"
2270
2270
  }
2271
2271
  },
@@ -2300,8 +2300,8 @@ var definitions = {
2300
2300
  }
2301
2301
  ]
2302
2302
  },
2303
- maxItems: 2,
2304
- minItems: 2,
2303
+ maxFiles: 2,
2304
+ minFiles: 2,
2305
2305
  type: "array"
2306
2306
  }
2307
2307
  },
@@ -2336,8 +2336,8 @@ var definitions = {
2336
2336
  }
2337
2337
  ]
2338
2338
  },
2339
- maxItems: 2,
2340
- minItems: 2,
2339
+ maxFiles: 2,
2340
+ minFiles: 2,
2341
2341
  type: "array"
2342
2342
  }
2343
2343
  },
@@ -2372,8 +2372,8 @@ var definitions = {
2372
2372
  }
2373
2373
  ]
2374
2374
  },
2375
- maxItems: 2,
2376
- minItems: 2,
2375
+ maxFiles: 2,
2376
+ minFiles: 2,
2377
2377
  type: "array"
2378
2378
  }
2379
2379
  },
@@ -2451,7 +2451,7 @@ var definitions = {
2451
2451
  items: {
2452
2452
  $ref: "#/definitions/ProteusCondition"
2453
2453
  },
2454
- minItems: 1,
2454
+ minFiles: 1,
2455
2455
  type: "array"
2456
2456
  }
2457
2457
  },
@@ -2471,7 +2471,7 @@ var definitions = {
2471
2471
  }
2472
2472
  ]
2473
2473
  },
2474
- minItems: 1,
2474
+ minFiles: 1,
2475
2475
  type: "array"
2476
2476
  }
2477
2477
  },
@@ -2962,13 +2962,25 @@ var definitions = {
2962
2962
  description: "A Proteus node can be a string, number, boolean, null, a single element, or an array of these types (similar to ReactNode)"
2963
2963
  },
2964
2964
  ProteusStructuredMessage: {
2965
- description: "Structured message payload that lets file URLs travel as a typed list alongside the text parts, instead of being joined into the text.",
2965
+ description: "Structured message payload that lets file metadata travel as a typed list alongside the text parts, instead of being joined into the text.",
2966
2966
  properties: {
2967
2967
  files: {
2968
2968
  anyOf: [
2969
2969
  {
2970
2970
  items: {
2971
- type: "string"
2971
+ properties: {
2972
+ link: {
2973
+ type: "string"
2974
+ },
2975
+ name: {
2976
+ type: "string"
2977
+ }
2978
+ },
2979
+ required: [
2980
+ "name",
2981
+ "link"
2982
+ ],
2983
+ type: "object"
2972
2984
  },
2973
2985
  type: "array"
2974
2986
  },
@@ -2976,7 +2988,7 @@ var definitions = {
2976
2988
  $ref: "#/definitions/ProteusExpression"
2977
2989
  }
2978
2990
  ],
2979
- description: "List of file URLs (typically signed URLs from a host upload)."
2991
+ description: "List of uploaded file metadata objects (typically the host's onUpload return value). Hosts may attach additional fields beyond `name` and `link`."
2980
2992
  },
2981
2993
  parts: {
2982
2994
  items: {
@@ -5197,27 +5209,38 @@ var definitions = {
5197
5209
  },
5198
5210
  type: "array"
5199
5211
  },
5200
- name: {
5212
+ maxFiles: {
5201
5213
  anyOf: [
5202
5214
  {
5203
- type: "string"
5215
+ type: "number"
5204
5216
  },
5205
5217
  {
5206
5218
  $ref: "#/definitions/ProteusExpression"
5207
5219
  }
5208
5220
  ],
5209
- description: "The name of the form control element. The resolved URL is written at parentPath/name in form data."
5221
+ description: "Maximum number of files allowed. When set to 1 the field is in single-file mode; any other value (or omitted) allows multiple uploads."
5210
5222
  },
5211
- required: {
5223
+ minFiles: {
5212
5224
  anyOf: [
5213
5225
  {
5214
- type: "boolean"
5226
+ type: "number"
5227
+ },
5228
+ {
5229
+ $ref: "#/definitions/ProteusExpression"
5230
+ }
5231
+ ],
5232
+ description: "Minimum number of files required."
5233
+ },
5234
+ name: {
5235
+ anyOf: [
5236
+ {
5237
+ type: "string"
5215
5238
  },
5216
5239
  {
5217
5240
  $ref: "#/definitions/ProteusExpression"
5218
5241
  }
5219
5242
  ],
5220
- description: "Whether a file is required."
5243
+ description: "The name of the form control element. The resolved metadata array is written at parentPath/name in form data."
5221
5244
  }
5222
5245
  },
5223
5246
  required: [
@@ -6700,6 +6723,10 @@ var definitions = {
6700
6723
  $ref: "#/definitions/ProteusNode",
6701
6724
  description: "Template object to render for each item in the array. Value paths inside this template are relative to the current item (e.g., path='title' resolves to each item's 'title' field). Use a leading '/' to reference top-level data (e.g., path='/title' resolves to the root data's 'title')."
6702
6725
  },
6726
+ flat: {
6727
+ description: "When true, flattens the result array by one level. Useful when each mapped item resolves to an array and you want a single flat list.",
6728
+ type: "boolean"
6729
+ },
6703
6730
  path: {
6704
6731
  description: "JSON pointer path to the source array in the data (e.g., '/results')",
6705
6732
  type: "string"