@optiaxiom/proteus 0.1.16-next.0 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/dist/esm/assets/src/proteus-chart/{ProteusChart.css.ts.vanilla-Ct8ajpEs.css → ProteusChart.css.ts.vanilla-CK0mlfvQ.css} +2 -2
  2. package/dist/esm/assets/src/proteus-chart/{ProteusChartTooltipContent.css.ts.vanilla-CV4s3EJV.css → ProteusChartTooltipContent.css.ts.vanilla-VEKfizml.css} +2 -2
  3. package/dist/esm/assets/src/proteus-image-carousel/ProteusImageCarousel.css.ts.vanilla-DV3O-VwO.css +72 -0
  4. package/dist/esm/assets/src/proteus-question/{ProteusQuestion.css.ts.vanilla-nFTJBsO_.css → ProteusQuestion.css.ts.vanilla-0cQoAJ0-.css} +2 -2
  5. package/dist/esm/index.js +1 -0
  6. package/dist/esm/proteus-chart/ProteusChart-css.js +1 -1
  7. package/dist/esm/proteus-chart/ProteusChartTooltipContent-css.js +1 -1
  8. package/dist/esm/proteus-document/ProteusDocumentPathContext.js +1 -0
  9. package/dist/esm/proteus-document/ProteusDocumentShell.js +1 -1
  10. package/dist/esm/proteus-document/resolveProteusProp.js +7 -4
  11. package/dist/esm/proteus-document/resolveProteusValue.js +44 -21
  12. package/dist/esm/proteus-document/useResolveProteusValues.js +2 -2
  13. package/dist/esm/proteus-element/ProteusElement.js +12 -4
  14. package/dist/esm/proteus-image-carousel/ProteusImageCarousel-css.js +12 -0
  15. package/dist/esm/proteus-image-carousel/ProteusImageCarousel.js +164 -0
  16. package/dist/esm/proteus-map/ProteusMap.js +2 -1
  17. package/dist/esm/proteus-question/ProteusQuestion-css.js +2 -2
  18. package/dist/esm/proteus-question/ProteusQuestion.js +15 -15
  19. package/dist/esm/proteus-show/ProteusShow.js +2 -2
  20. package/dist/esm/schema/public-schema.json.js +365 -207
  21. package/dist/esm/schema/runtime-schema.json.js +362 -207
  22. package/dist/index.d.ts +35 -1
  23. package/dist/spec.d.ts +654 -530
  24. package/package.json +4 -3
@@ -1,5 +1,5 @@
1
- @layer optiaxiom.ndq0nz;
2
- @layer optiaxiom.ndq0nz {
1
+ @layer optiaxiom._1g6ippr;
2
+ @layer optiaxiom._1g6ippr {
3
3
  .ProteusChart__jmlqij1 {
4
4
  border-radius: 16px;
5
5
  }
@@ -1,5 +1,5 @@
1
- @layer optiaxiom.ndq0nz;
2
- @layer optiaxiom.ndq0nz {
1
+ @layer optiaxiom._1g6ippr;
2
+ @layer optiaxiom._1g6ippr {
3
3
  .ProteusChartTooltipContent__1gsvq810 {
4
4
  min-width: 128px;
5
5
  }
@@ -0,0 +1,72 @@
1
+ @layer optiaxiom._1g6ippr;
2
+ @layer optiaxiom._1g6ippr {
3
+ .ProteusImageCarousel__1t6qej70 {
4
+ outline: none;
5
+ user-select: none;
6
+ }
7
+ .ProteusImageCarousel__1t6qej71 {
8
+ aspect-ratio: 16 / 9;
9
+ grid-template-columns: auto 1fr auto;
10
+ grid-template-rows: auto 1fr auto;
11
+ position: relative;
12
+ }
13
+ .ProteusImageCarousel__1t6qej72 {
14
+ grid-area: 1 / 1 / -1 / -1;
15
+ }
16
+ .ProteusImageCarousel__1t6qej73 {
17
+ backface-visibility: hidden;
18
+ display: flex;
19
+ touch-action: pan-y pinch-zoom;
20
+ }
21
+ .ProteusImageCarousel__1t6qej74 {
22
+ flex: 0 0 100%;
23
+ height: 100%;
24
+ min-width: 0;
25
+ }
26
+ .ProteusImageCarousel__1t6qej75 {
27
+ align-self: center;
28
+ grid-row: 2;
29
+ opacity: 0.7;
30
+ z-index: 1;
31
+ }
32
+ .ProteusImageCarousel__1t6qej75::before {
33
+ content: "";
34
+ inset-block: 0;
35
+ padding-left: 32px;
36
+ padding-right: 16px;
37
+ position: absolute;
38
+ width: 32px;
39
+ }
40
+ .ProteusImageCarousel__1t6qej75:hover {
41
+ opacity: 1;
42
+ }
43
+ .ProteusImageCarousel__1t6qej76 {
44
+ grid-column: 1;
45
+ }
46
+ .ProteusImageCarousel__1t6qej77 {
47
+ grid-column: 3;
48
+ }
49
+ .ProteusImageCarousel__1t6qej78 {
50
+ position: relative;
51
+ }
52
+ .ProteusImageCarousel__1t6qej78::after {
53
+ content: "";
54
+ border-radius: inherit;
55
+ box-shadow: inset 0 0 0 2px var(--ax-colors-border-focus);
56
+ inset: 0;
57
+ opacity: 0;
58
+ outline: 2px solid var(--ax-colors-bg-default);
59
+ outline-offset: -4px;
60
+ position: absolute;
61
+ transition: opacity var(--ax-duration-sm);
62
+ }
63
+ .ProteusImageCarousel__1t6qej79 {
64
+ opacity: 0.7;
65
+ }
66
+ .ProteusImageCarousel__1t6qej7a {
67
+ opacity: 1;
68
+ }
69
+ .ProteusImageCarousel__1t6qej7a::after {
70
+ opacity: 1;
71
+ }
72
+ }
@@ -1,5 +1,5 @@
1
- @layer optiaxiom.ndq0nz;
2
- @layer optiaxiom.ndq0nz {
1
+ @layer optiaxiom._1g6ippr;
2
+ @layer optiaxiom._1g6ippr {
3
3
  .ProteusQuestion__8f590p0 {
4
4
  outline: none;
5
5
  }
package/dist/esm/index.js CHANGED
@@ -6,6 +6,7 @@ export { ProteusDocumentRenderer } from './proteus-document/ProteusDocumentRende
6
6
  export { ProteusDocumentShell } from './proteus-document/ProteusDocumentShell.js';
7
7
  export { safeParseDocument } from './proteus-document/schemas.js';
8
8
  export { ProteusImage } from './proteus-image/ProteusImage.js';
9
+ export { ProteusImageCarousel } from './proteus-image-carousel/ProteusImageCarousel.js';
9
10
  export { ProteusInput } from './proteus-input/ProteusInput.js';
10
11
  export { ProteusMap } from './proteus-map/ProteusMap.js';
11
12
  export { ProteusSelect } from './proteus-select/ProteusSelect.js';
@@ -1,4 +1,4 @@
1
- import './../assets/src/proteus-chart/ProteusChart.css.ts.vanilla-Ct8ajpEs.css';
1
+ import './../assets/src/proteus-chart/ProteusChart.css.ts.vanilla-CK0mlfvQ.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-CV4s3EJV.css';
1
+ import './../assets/src/proteus-chart/ProteusChartTooltipContent.css.ts.vanilla-VEKfizml.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',px:'8',py:'10',rounded:'lg',shadow:'lg'},'ProteusChartTooltipContent__1gsvq810']});
@@ -2,6 +2,7 @@
2
2
  import { createContext } from '@radix-ui/react-context';
3
3
 
4
4
  const [ProteusDocumentPathProvider, useProteusDocumentPathContext] = createContext("@optiaxiom/proteus/ProteusDocumentPath", {
5
+ mapIndices: [],
5
6
  path: ""
6
7
  });
7
8
 
@@ -77,7 +77,7 @@ function ProteusDocumentShell({
77
77
  borderColor: "border.tertiary",
78
78
  onOpenChange: setOpen,
79
79
  open,
80
- p: "16",
80
+ p: "20",
81
81
  rounded: "xl",
82
82
  children: [
83
83
  element.appName && /* @__PURE__ */ jsx(Trigger, { py: "0", ...collapsible ? { chevronPosition: "end" } : {}, children: /* @__PURE__ */ jsxs(Group, { fontSize: "sm", gap: "8", children: [
@@ -4,10 +4,13 @@ import { ProteusElement } from '../proteus-element/ProteusElement.js';
4
4
  import { getProteusValue } from './getProteusValue.js';
5
5
  import { evaluateCondition } from './resolveProteusValue.js';
6
6
 
7
- function resolveProteusProp(value, data, parentPath) {
7
+ function resolveProteusProp(value, data, parentPath, mapIndices = []) {
8
8
  if (typeof value !== "object" || value === null) {
9
9
  return value;
10
10
  }
11
+ if ("$type" in value && value.$type === "MapIndex") {
12
+ return mapIndices.at(-1);
13
+ }
11
14
  if ("$type" in value && value.$type === "Value" && "path" in value && typeof value.path === "string") {
12
15
  return getProteusValue(
13
16
  data,
@@ -20,7 +23,7 @@ function resolveProteusProp(value, data, parentPath) {
20
23
  const resolved = {};
21
24
  let length = 0;
22
25
  for (const [k, v] of Object.entries(sources)) {
23
- const arr = resolveProteusProp(v, data, parentPath);
26
+ const arr = resolveProteusProp(v, data, parentPath, mapIndices);
24
27
  if (Array.isArray(arr)) {
25
28
  resolved[k] = arr;
26
29
  length = Math.max(length, arr.length);
@@ -37,12 +40,12 @@ function resolveProteusProp(value, data, parentPath) {
37
40
  if ("$type" in value && value.$type === "Show" && "when" in value && "children" in value) {
38
41
  const conditions = Array.isArray(value.when) ? value.when : [value.when];
39
42
  const shouldShow = conditions.every(
40
- (condition) => evaluateCondition(condition, data, parentPath)
43
+ (condition) => evaluateCondition(condition, data, parentPath, mapIndices)
41
44
  );
42
45
  if (!shouldShow) {
43
46
  return void 0;
44
47
  }
45
- return resolveProteusProp(value.children, data, parentPath);
48
+ return resolveProteusProp(value.children, data, parentPath, mapIndices);
46
49
  }
47
50
  return "$type" in value || Array.isArray(value) && value.some((v) => v && typeof v === "object" && "$type" in v) ? /* @__PURE__ */ jsx(ProteusElement, { element: value }) : value;
48
51
  }
@@ -1,62 +1,75 @@
1
1
  "use client";
2
2
  import { getProteusValue } from './getProteusValue.js';
3
3
 
4
- function evaluateCondition(condition, data, parentPath) {
4
+ function evaluateCondition(condition, data, parentPath, mapIndices = []) {
5
5
  if (!condition) {
6
6
  return true;
7
7
  }
8
8
  if ("and" in condition) {
9
9
  return condition.and.every(
10
- (cond) => evaluateCondition(cond, data, parentPath)
10
+ (cond) => evaluateCondition(cond, data, parentPath, mapIndices)
11
11
  );
12
12
  }
13
13
  if ("or" in condition) {
14
14
  return condition.or.some(
15
- (cond) => evaluateCondition(cond, data, parentPath)
15
+ (cond) => evaluateCondition(cond, data, parentPath, mapIndices)
16
16
  );
17
17
  }
18
18
  if ("!!" in condition) {
19
- const value = resolveProteusValue(condition["!!"], data, parentPath);
19
+ const value = resolveProteusValue(
20
+ condition["!!"],
21
+ data,
22
+ parentPath,
23
+ mapIndices
24
+ );
20
25
  return !!value;
21
26
  }
22
27
  if ("!" in condition) {
23
- const value = resolveProteusValue(condition["!"], data, parentPath);
28
+ const value = resolveProteusValue(
29
+ condition["!"],
30
+ data,
31
+ parentPath,
32
+ mapIndices
33
+ );
24
34
  return !value;
25
35
  }
26
36
  if ("==" in condition) {
27
37
  const [left, right] = condition["=="];
28
- return resolveProteusValue(left, data, parentPath) === resolveProteusValue(right, data, parentPath);
38
+ return resolveProteusValue(left, data, parentPath, mapIndices) === resolveProteusValue(right, data, parentPath, mapIndices);
29
39
  } else if ("!=" in condition) {
30
40
  const [left, right] = condition["!="];
31
- return resolveProteusValue(left, data, parentPath) !== resolveProteusValue(right, data, parentPath);
41
+ return resolveProteusValue(left, data, parentPath, mapIndices) !== resolveProteusValue(right, data, parentPath, mapIndices);
32
42
  } else if ("<" in condition) {
33
43
  const [left, right] = condition["<"];
34
- const leftVal = resolveProteusValue(left, data, parentPath);
35
- const rightVal = resolveProteusValue(right, data, parentPath);
44
+ const leftVal = resolveProteusValue(left, data, parentPath, mapIndices);
45
+ const rightVal = resolveProteusValue(right, data, parentPath, mapIndices);
36
46
  return typeof leftVal === "number" && typeof rightVal === "number" && leftVal < rightVal;
37
47
  } else if ("<=" in condition) {
38
48
  const [left, right] = condition["<="];
39
- const leftVal = resolveProteusValue(left, data, parentPath);
40
- const rightVal = resolveProteusValue(right, data, parentPath);
49
+ const leftVal = resolveProteusValue(left, data, parentPath, mapIndices);
50
+ const rightVal = resolveProteusValue(right, data, parentPath, mapIndices);
41
51
  return typeof leftVal === "number" && typeof rightVal === "number" && leftVal <= rightVal;
42
52
  } else if (">" in condition) {
43
53
  const [left, right] = condition[">"];
44
- const leftVal = resolveProteusValue(left, data, parentPath);
45
- const rightVal = resolveProteusValue(right, data, parentPath);
54
+ const leftVal = resolveProteusValue(left, data, parentPath, mapIndices);
55
+ const rightVal = resolveProteusValue(right, data, parentPath, mapIndices);
46
56
  return typeof leftVal === "number" && typeof rightVal === "number" && leftVal > rightVal;
47
57
  } else if (">=" in condition) {
48
58
  const [left, right] = condition[">="];
49
- const leftVal = resolveProteusValue(left, data, parentPath);
50
- const rightVal = resolveProteusValue(right, data, parentPath);
59
+ const leftVal = resolveProteusValue(left, data, parentPath, mapIndices);
60
+ const rightVal = resolveProteusValue(right, data, parentPath, mapIndices);
51
61
  return typeof leftVal === "number" && typeof rightVal === "number" && leftVal >= rightVal;
52
62
  }
53
63
  return false;
54
64
  }
55
- function resolveProteusValue(value, data, parentPath) {
65
+ function resolveProteusValue(value, data, parentPath, mapIndices = []) {
56
66
  if (typeof value !== "object" || value === null) {
57
67
  return value;
58
68
  }
59
69
  if ("$type" in value) {
70
+ if (value.$type === "MapIndex") {
71
+ return mapIndices.at(-1);
72
+ }
60
73
  if (value.$type === "Value" && "path" in value && typeof value.path === "string") {
61
74
  return getProteusValue(
62
75
  data,
@@ -75,10 +88,18 @@ function resolveProteusValue(value, data, parentPath) {
75
88
  }
76
89
  const resolvedPath = value.path.startsWith("/") ? value.path : `${parentPath}/${value.path}`;
77
90
  const items = array.map(
78
- (_, index) => resolveProteusValue(value.children, data, `${resolvedPath}/${index}`)
91
+ (_, index) => resolveProteusValue(value.children, data, `${resolvedPath}/${index}`, [
92
+ ...mapIndices,
93
+ index
94
+ ])
79
95
  );
80
96
  if ("separator" in value) {
81
- const sep = resolveProteusValue(value.separator, data, parentPath);
97
+ const sep = resolveProteusValue(
98
+ value.separator,
99
+ data,
100
+ parentPath,
101
+ mapIndices
102
+ );
82
103
  return items.join(typeof sep === "string" ? sep : "");
83
104
  }
84
105
  return items;
@@ -86,18 +107,20 @@ function resolveProteusValue(value, data, parentPath) {
86
107
  if (value.$type === "Show" && "when" in value && "children" in value) {
87
108
  const conditions = Array.isArray(value.when) ? value.when : [value.when];
88
109
  const shouldShow = conditions.every(
89
- (condition) => evaluateCondition(condition, data, parentPath)
110
+ (condition) => evaluateCondition(condition, data, parentPath, mapIndices)
90
111
  );
91
112
  if (!shouldShow) {
92
113
  return void 0;
93
114
  }
94
- return resolveProteusValue(value.children, data, parentPath);
115
+ return resolveProteusValue(value.children, data, parentPath, mapIndices);
95
116
  }
96
117
  if (value.$type === "Concat" && "children" in value) {
97
118
  if (!Array.isArray(value.children)) {
98
119
  return value;
99
120
  }
100
- return value.children.map((child) => resolveProteusValue(child, data, parentPath)).filter((v) => v !== void 0).join("");
121
+ return value.children.map(
122
+ (child) => resolveProteusValue(child, data, parentPath, mapIndices)
123
+ ).filter((v) => v !== void 0).join("");
101
124
  }
102
125
  }
103
126
  return value;
@@ -6,12 +6,12 @@ function useResolveProteusValues(props) {
6
6
  const { data } = useProteusDocumentContext(
7
7
  "@optiaxiom/react/useResolveProteusValues"
8
8
  );
9
- const { path: parentPath } = useProteusDocumentPathContext(
9
+ const { mapIndices, path: parentPath } = useProteusDocumentPathContext(
10
10
  "@optiaxiom/react/useResolveProteusValues"
11
11
  );
12
12
  const resolved = {};
13
13
  for (const [key, value] of Object.entries(props)) {
14
- resolved[key] = resolveProteusValue(value, data, parentPath);
14
+ resolved[key] = resolveProteusValue(value, data, parentPath, mapIndices);
15
15
  }
16
16
  return resolved;
17
17
  }
@@ -11,6 +11,7 @@ import { useProteusDocumentContext } from '../proteus-document/ProteusDocumentCo
11
11
  import { useProteusDocumentPathContext } from '../proteus-document/ProteusDocumentPathContext.js';
12
12
  import { resolveProteusProp } from '../proteus-document/resolveProteusProp.js';
13
13
  import { safeParseElement } from '../proteus-document/schemas.js';
14
+ import { ProteusImageCarousel } from '../proteus-image-carousel/ProteusImageCarousel.js';
14
15
  import { ProteusImage } from '../proteus-image/ProteusImage.js';
15
16
  import { ProteusInput } from '../proteus-input/ProteusInput.js';
16
17
  import { ProteusMap } from '../proteus-map/ProteusMap.js';
@@ -32,7 +33,7 @@ const ProteusElement = ({
32
33
  const { data, strict } = useProteusDocumentContext(
33
34
  "@optiaxiom/proteus/ProteusElement"
34
35
  );
35
- const { path: parentPath } = useProteusDocumentPathContext(
36
+ const { mapIndices, path: parentPath } = useProteusDocumentPathContext(
36
37
  "@optiaxiom/proteus/ProteusElement"
37
38
  );
38
39
  if (!elementProp) {
@@ -54,7 +55,7 @@ const ProteusElement = ({
54
55
  const { $type: _$type, ...rest } = obj;
55
56
  const resolved = {};
56
57
  for (const [key, value] of Object.entries(rest)) {
57
- resolved[key] = resolveProteusProp(value, data, parentPath);
58
+ resolved[key] = resolveProteusProp(value, data, parentPath, mapIndices);
58
59
  }
59
60
  return resolved;
60
61
  };
@@ -72,7 +73,7 @@ const ProteusElement = ({
72
73
  case "CardHeader":
73
74
  return /* @__PURE__ */ jsx(CardHeader, { ...resolve(element) });
74
75
  case "CardLink":
75
- return /* @__PURE__ */ jsx(CardLink, { ...resolve(element) });
76
+ return /* @__PURE__ */ jsx(CardLink, { target: "_blank", ...resolve(element) });
76
77
  case "Chart":
77
78
  return /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
78
79
  ProteusChart,
@@ -97,10 +98,17 @@ const ProteusElement = ({
97
98
  return /* @__PURE__ */ jsx(Box, { asChild: true, ...resolve(element), children: /* @__PURE__ */ jsx(IconCalendar, {}) });
98
99
  case "Image":
99
100
  return /* @__PURE__ */ jsx(ProteusImage, { ...resolve(element) });
101
+ case "ImageCarousel":
102
+ return /* @__PURE__ */ jsx(
103
+ ProteusImageCarousel,
104
+ {
105
+ ...resolve(element)
106
+ }
107
+ );
100
108
  case "Input":
101
109
  return /* @__PURE__ */ jsx(ProteusInput, { ...resolve(element) });
102
110
  case "Link":
103
- return /* @__PURE__ */ jsx(Link, { ...resolve(element) });
111
+ return /* @__PURE__ */ jsx(Link, { target: "_blank", ...resolve(element) });
104
112
  case "Map":
105
113
  return /* @__PURE__ */ jsx(
106
114
  ProteusMap,
@@ -0,0 +1,12 @@
1
+ import './../assets/src/proteus-image-carousel/ProteusImageCarousel.css.ts.vanilla-DV3O-VwO.css';
2
+ import { recipe } from '@optiaxiom/react/css-runtime';
3
+
4
+ var carousel = recipe({base:[{flexDirection:'column',gap:'12'},'ProteusImageCarousel__1t6qej70']});
5
+ var content = recipe({base:[{display:'grid',overflow:'hidden',rounded:'lg'},'ProteusImageCarousel__1t6qej71']});
6
+ var navButton = recipe({base:[{bg:'bg.default',display:'grid',mx:'16',placeItems:'center',rounded:'full',size:'md',transition:'opacity'},'ProteusImageCarousel__1t6qej75'],variants:{side:{left:[{mr:'32'},'ProteusImageCarousel__1t6qej76'],right:[{ml:'32'},'ProteusImageCarousel__1t6qej77']}}});
7
+ var slide = recipe({base:[{objectFit:'cover',size:'full'},'ProteusImageCarousel__1t6qej74']});
8
+ var slideContainer = recipe({base:[{size:'full'},'ProteusImageCarousel__1t6qej73']});
9
+ var thumbnail = recipe({base:[{cursor:'pointer',flex:'none',objectFit:'cover',overflow:'hidden',rounded:'lg',size:'80',transition:'opacity'},'ProteusImageCarousel__1t6qej78'],variants:{selected:{false:'ProteusImageCarousel__1t6qej79',true:'ProteusImageCarousel__1t6qej7a'}}});
10
+ var viewport = recipe({base:[{overflow:'hidden'},'ProteusImageCarousel__1t6qej72']});
11
+
12
+ export { carousel, content, navButton, slide, slideContainer, thumbnail, viewport };
@@ -0,0 +1,164 @@
1
+ "use client";
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { Group, Box, Text, Menu, MenuTrigger, MenuContent, Button } from '@optiaxiom/react';
4
+ import useEmblaCarousel from 'embla-carousel-react';
5
+ import { useState, useCallback, useEffect } from 'react';
6
+ import { IconAngleLeft } from '../icons/IconAngleLeft.js';
7
+ import { IconAngleRight } from '../icons/IconAngleRight.js';
8
+ import { downloadFile } from '../proteus-image/downloadFile.js';
9
+ import { ProteusImage } from '../proteus-image/ProteusImage.js';
10
+ import { carousel, content, viewport, slideContainer, slide, navButton, thumbnail } from './ProteusImageCarousel-css.js';
11
+
12
+ function ProteusImageCarousel({
13
+ downloadAll,
14
+ images,
15
+ title
16
+ }) {
17
+ const [emblaMainRef, emblaMainApi] = useEmblaCarousel({ loop: false });
18
+ const [emblaThumbsRef, emblaThumbsApi] = useEmblaCarousel({
19
+ containScroll: "keepSnaps",
20
+ dragFree: true
21
+ });
22
+ const [selectedIndex, setSelectedIndex] = useState(0);
23
+ const [canScrollPrev, setCanScrollPrev] = useState(false);
24
+ const [canScrollNext, setCanScrollNext] = useState(false);
25
+ const onSelect = useCallback(() => {
26
+ if (!emblaMainApi || !emblaThumbsApi)
27
+ return;
28
+ setSelectedIndex(emblaMainApi.selectedScrollSnap());
29
+ emblaThumbsApi.scrollTo(emblaMainApi.selectedScrollSnap());
30
+ setCanScrollPrev(emblaMainApi.canScrollPrev());
31
+ setCanScrollNext(emblaMainApi.canScrollNext());
32
+ }, [emblaMainApi, emblaThumbsApi]);
33
+ useEffect(() => {
34
+ if (!emblaMainApi)
35
+ return;
36
+ onSelect();
37
+ emblaMainApi.on("select", onSelect).on("reInit", onSelect);
38
+ }, [emblaMainApi, onSelect]);
39
+ if (!images.length) {
40
+ return null;
41
+ }
42
+ return /* @__PURE__ */ jsxs(
43
+ Group,
44
+ {
45
+ "aria-label": title ?? "Image carousel",
46
+ "aria-roledescription": "carousel",
47
+ onKeyDownCapture: (event) => {
48
+ if (event.target instanceof HTMLInputElement)
49
+ return;
50
+ if (event.key === "ArrowLeft") {
51
+ event.preventDefault();
52
+ emblaMainApi?.scrollPrev();
53
+ } else if (event.key === "ArrowRight") {
54
+ event.preventDefault();
55
+ emblaMainApi?.scrollNext();
56
+ }
57
+ },
58
+ role: "region",
59
+ tabIndex: 0,
60
+ ...carousel(),
61
+ children: [
62
+ /* @__PURE__ */ jsxs(Box, { ...content(), children: [
63
+ /* @__PURE__ */ jsx(Box, { ...viewport(), ref: emblaMainRef, children: /* @__PURE__ */ jsx(Group, { ...slideContainer(), children: images.map((image, index) => /* @__PURE__ */ jsx(
64
+ ProteusImage,
65
+ {
66
+ alt: image.alt,
67
+ src: image.src,
68
+ ...slide()
69
+ },
70
+ index
71
+ )) }) }),
72
+ canScrollPrev && /* @__PURE__ */ jsx(
73
+ Box,
74
+ {
75
+ "aria-label": "Previous image",
76
+ asChild: true,
77
+ onClick: () => emblaMainApi?.scrollPrev(),
78
+ ...navButton({ side: "left" }),
79
+ children: /* @__PURE__ */ jsx("button", { children: /* @__PURE__ */ jsx(IconAngleLeft, {}) })
80
+ }
81
+ ),
82
+ canScrollNext && /* @__PURE__ */ jsx(
83
+ Box,
84
+ {
85
+ "aria-label": "Next image",
86
+ asChild: true,
87
+ onClick: () => emblaMainApi?.scrollNext(),
88
+ ...navButton({ side: "right" }),
89
+ children: /* @__PURE__ */ jsx("button", { children: /* @__PURE__ */ jsx(IconAngleRight, {}) })
90
+ }
91
+ )
92
+ ] }),
93
+ images.length > 1 && /* @__PURE__ */ jsx(Box, { overflow: "hidden", ref: emblaThumbsRef, children: /* @__PURE__ */ jsx(Group, { gap: "12", children: images.map((image, index) => /* @__PURE__ */ jsx(
94
+ Box,
95
+ {
96
+ onClick: () => emblaMainApi?.scrollTo(index),
97
+ ...thumbnail({
98
+ selected: index === selectedIndex
99
+ }),
100
+ children: /* @__PURE__ */ jsx(Box, { asChild: true, objectFit: "cover", size: "full", children: /* @__PURE__ */ jsx("img", { alt: image.alt, src: image.thumb ?? image.src }) })
101
+ },
102
+ index
103
+ )) }) }),
104
+ /* @__PURE__ */ jsxs(Group, { mt: "4", children: [
105
+ images.length > 1 && /* @__PURE__ */ jsxs(
106
+ Text,
107
+ {
108
+ bg: "bg.secondary",
109
+ color: "fg.default",
110
+ fontSize: "sm",
111
+ fontWeight: "500",
112
+ px: "8",
113
+ py: "2",
114
+ rounded: "full",
115
+ children: [
116
+ selectedIndex + 1,
117
+ " / ",
118
+ images.length
119
+ ]
120
+ }
121
+ ),
122
+ images.length > 1 ? /* @__PURE__ */ jsxs(
123
+ Menu,
124
+ {
125
+ options: [
126
+ {
127
+ execute: () => downloadFile(images[selectedIndex].src),
128
+ label: "Download this image"
129
+ },
130
+ {
131
+ execute: () => {
132
+ if (downloadAll) {
133
+ window.open(downloadAll, "_blank");
134
+ } else {
135
+ for (const image of images) {
136
+ void downloadFile(image.src);
137
+ }
138
+ }
139
+ },
140
+ label: "Download all images"
141
+ }
142
+ ],
143
+ children: [
144
+ /* @__PURE__ */ jsx(MenuTrigger, { appearance: "primary", ml: "auto", children: "Download" }),
145
+ /* @__PURE__ */ jsx(MenuContent, { align: "end" })
146
+ ]
147
+ }
148
+ ) : /* @__PURE__ */ jsx(
149
+ Button,
150
+ {
151
+ appearance: "primary",
152
+ ml: "auto",
153
+ onClick: () => downloadFile(images[0].src),
154
+ children: "Download"
155
+ }
156
+ )
157
+ ] })
158
+ ]
159
+ }
160
+ );
161
+ }
162
+ ProteusImageCarousel.displayName = "@optiaxiom/proteus/ProteusImageCarousel";
163
+
164
+ export { ProteusImageCarousel };
@@ -6,7 +6,7 @@ import { useProteusValue } from '../use-proteus-value/useProteusValue.js';
6
6
 
7
7
  function ProteusMap({ children, path, separator }) {
8
8
  const { strict } = useProteusDocumentContext("@optiaxiom/proteus/ProteusMap");
9
- const { path: parentPath } = useProteusDocumentPathContext(
9
+ const { mapIndices, path: parentPath } = useProteusDocumentPathContext(
10
10
  "@optiaxiom/proteus/ProteusMap"
11
11
  );
12
12
  const array = useProteusValue({ path });
@@ -21,6 +21,7 @@ function ProteusMap({ children, path, separator }) {
21
21
  return /* @__PURE__ */ jsx(Fragment, { children: array.map((_, index) => /* @__PURE__ */ jsxs(
22
22
  ProteusDocumentPathProvider,
23
23
  {
24
+ mapIndices: [...mapIndices, index],
24
25
  path: `${path.startsWith("/") ? path : `${parentPath}/${path}`}/${index}`,
25
26
  children: [
26
27
  index > 0 && separator,
@@ -1,9 +1,9 @@
1
- import './../assets/src/proteus-question/ProteusQuestion.css.ts.vanilla-nFTJBsO_.css';
1
+ import './../assets/src/proteus-question/ProteusQuestion.css.ts.vanilla-0cQoAJ0-.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'}}}});
5
5
  var choice = recipe({base:[{color:'fg.default',flexDirection:'column',fontSize:'md',gap:'8',px:'10',py:'16',rounded:'lg',transition:'colors'},'ProteusQuestion__8f590p2','ProteusQuestion__8f590p1'],variants:{cursor:{pointer:{borderB:'1'},text:{cursor:'text'}}}});
6
6
  var choiceGroup = recipe({base:{flexDirection:'column'}});
7
- var question = recipe({base:[{flexDirection:'column',gap:'16',p:'4'},'ProteusQuestion__8f590p0']});
7
+ var question = recipe({base:[{flexDirection:'column',gap:'16'},'ProteusQuestion__8f590p0']});
8
8
 
9
9
  export { addon, choice, choiceGroup, question };
@@ -45,9 +45,9 @@ function ProteusQuestion({ questions }) {
45
45
  }
46
46
  );
47
47
  lastIndexRef.current = currentIndex;
48
- const item = questionRef.current?.querySelector("[data-selected]") ?? questionRef.current?.querySelector("[tabindex]");
49
- item?.focus();
50
48
  }
49
+ const item = questionRef.current?.querySelector("[data-selected]") ?? questionRef.current?.querySelector("[tabindex]");
50
+ item?.focus();
51
51
  }, [currentIndex]);
52
52
  const otherInputRef = useRef(null);
53
53
  const otherItemRef = useRef(null);
@@ -90,7 +90,7 @@ A: ${value2 || "[Not specified]"}`
90
90
  onKeyDown: (event) => {
91
91
  if (event.key === "Escape") {
92
92
  event.preventDefault();
93
- if (valid) {
93
+ if (type === "multi_select" && valid) {
94
94
  onValueChange(null);
95
95
  } else {
96
96
  onSkip();
@@ -328,28 +328,28 @@ A: ${value2 || "[Not specified]"}`
328
328
  value?.length || 0,
329
329
  " selected"
330
330
  ] }),
331
- (value?.length || 0) > 0 ? /* @__PURE__ */ jsx(
331
+ /* @__PURE__ */ jsx(
332
332
  Button,
333
333
  {
334
- appearance: "primary",
335
- "aria-label": isLast ? "Submit" : "Next",
336
- disabled: !valid,
337
- icon: /* @__PURE__ */ jsx(IconNorth, {}),
338
334
  ml: "auto",
339
335
  onClick: (event) => {
340
336
  event.preventDefault();
341
- onSubmit();
342
- }
337
+ onSkip();
338
+ },
339
+ children: "Skip"
343
340
  }
344
- ) : /* @__PURE__ */ jsx(
341
+ ),
342
+ /* @__PURE__ */ jsx(
345
343
  Button,
346
344
  {
347
- ml: "auto",
345
+ appearance: valid ? "primary" : "default",
346
+ "aria-label": isLast ? "Submit" : "Next",
347
+ disabled: !valid,
348
+ icon: /* @__PURE__ */ jsx(IconNorth, {}),
348
349
  onClick: (event) => {
349
350
  event.preventDefault();
350
- onSkip();
351
- },
352
- children: "Skip"
351
+ onSubmit();
352
+ }
353
353
  }
354
354
  )
355
355
  ]