impact-nova 3.0.0-alpha.7 → 3.0.0-alpha.9

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 (103) hide show
  1. package/README.md +1 -1
  2. package/dist/components/data/expandable-list-item/sku-picker-chrome.d.ts +4 -0
  3. package/dist/components/data/expandable-list-item/sku-picker-chrome.js +37 -42
  4. package/dist/components/data-display/stereo-scatter/index.d.ts +2 -0
  5. package/dist/components/data-display/stereo-scatter/index.js +10 -0
  6. package/dist/components/data-display/stereo-scatter/internals/stereo-engine-frame.d.ts +41 -0
  7. package/dist/components/data-display/stereo-scatter/internals/stereo-engine-frame.js +178 -0
  8. package/dist/components/data-display/stereo-scatter/internals/stereo-engine-theme.d.ts +14 -0
  9. package/dist/components/data-display/stereo-scatter/internals/stereo-engine-theme.js +29 -0
  10. package/dist/components/data-display/stereo-scatter/internals/stereo-engine-wedges.d.ts +23 -0
  11. package/dist/components/data-display/stereo-scatter/internals/stereo-engine-wedges.js +80 -0
  12. package/dist/components/data-display/stereo-scatter/internals/stereo-engine.d.ts +120 -0
  13. package/dist/components/data-display/stereo-scatter/internals/stereo-engine.js +519 -0
  14. package/dist/components/data-display/stereo-scatter/internals/stereo-math.d.ts +64 -0
  15. package/dist/components/data-display/stereo-scatter/internals/stereo-math.js +129 -0
  16. package/dist/components/data-display/stereo-scatter/internals/stereo-model.d.ts +37 -0
  17. package/dist/components/data-display/stereo-scatter/internals/stereo-model.js +71 -0
  18. package/dist/components/data-display/stereo-scatter/internals/stereo-scatter-context.d.ts +33 -0
  19. package/dist/components/data-display/stereo-scatter/internals/stereo-scatter-context.js +19 -0
  20. package/dist/components/data-display/stereo-scatter/internals/stereo-scatter-key.d.ts +4 -0
  21. package/dist/components/data-display/stereo-scatter/internals/stereo-scatter-key.js +19 -0
  22. package/dist/components/data-display/stereo-scatter/internals/stereo-scatter-legend.d.ts +2 -0
  23. package/dist/components/data-display/stereo-scatter/internals/stereo-scatter-legend.js +75 -0
  24. package/dist/components/data-display/stereo-scatter/internals/stereo-scatter-scene.d.ts +2 -0
  25. package/dist/components/data-display/stereo-scatter/internals/stereo-scatter-scene.js +149 -0
  26. package/dist/components/data-display/stereo-scatter/internals/stereo-scatter-toolbar.d.ts +13 -0
  27. package/dist/components/data-display/stereo-scatter/internals/stereo-scatter-toolbar.js +93 -0
  28. package/dist/components/data-display/stereo-scatter/internals/stereo-scatter-tooltip.d.ts +2 -0
  29. package/dist/components/data-display/stereo-scatter/internals/stereo-scatter-tooltip.js +62 -0
  30. package/dist/components/data-display/stereo-scatter/internals/stereo-scatter-viewport.d.ts +3 -0
  31. package/dist/components/data-display/stereo-scatter/internals/stereo-scatter-viewport.js +41 -0
  32. package/dist/components/data-display/stereo-scatter/stereo-scatter.d.ts +12 -0
  33. package/dist/components/data-display/stereo-scatter/stereo-scatter.js +107 -0
  34. package/dist/components/data-display/stereo-scatter/stereo-scatter.stories-data.d.ts +11 -0
  35. package/dist/components/data-display/stereo-scatter/stereo-scatter.types.d.ts +69 -0
  36. package/dist/components/data-display/stereo-scatter/stereo-scatter.variants.d.ts +13 -0
  37. package/dist/components/data-display/stereo-scatter/stereo-scatter.variants.js +42 -0
  38. package/dist/components/feedback/tooltip/button-icon-tooltip.d.ts +3 -1
  39. package/dist/components/feedback/tooltip/button-icon-tooltip.js +22 -19
  40. package/dist/components/flows/iris-chat/IrisChatComposerVoiceCapture.d.ts +5 -0
  41. package/dist/components/flows/iris-chat/IrisChatComposerVoiceCapture.js +73 -0
  42. package/dist/components/flows/iris-chat/IrisChatVoiceWaveform.d.ts +3 -0
  43. package/dist/components/flows/iris-chat/IrisChatVoiceWaveform.js +25 -0
  44. package/dist/components/flows/iris-chat/index.d.ts +3 -1
  45. package/dist/components/flows/iris-chat/index.js +58 -53
  46. package/dist/components/flows/iris-chat/iris-chat-chrome.d.ts +39 -0
  47. package/dist/components/flows/iris-chat/iris-chat-chrome.js +325 -0
  48. package/dist/components/flows/iris-chat/iris-chat-close-animation.d.ts +12 -0
  49. package/dist/components/flows/iris-chat/iris-chat-close-animation.js +21 -0
  50. package/dist/components/flows/iris-chat/iris-chat-composer.js +266 -238
  51. package/dist/components/flows/iris-chat/iris-chat-context.d.ts +13 -0
  52. package/dist/components/flows/iris-chat/iris-chat-context.js +14 -10
  53. package/dist/components/flows/iris-chat/iris-chat-copy-feedback.d.ts +4 -0
  54. package/dist/components/flows/iris-chat/iris-chat-copy-feedback.js +16 -0
  55. package/dist/components/flows/iris-chat/iris-chat-frame.d.ts +31 -0
  56. package/dist/components/flows/iris-chat/iris-chat-frame.js +79 -0
  57. package/dist/components/flows/iris-chat/iris-chat-icons.d.ts +1 -0
  58. package/dist/components/flows/iris-chat/iris-chat-icons.js +28 -15
  59. package/dist/components/flows/iris-chat/iris-chat-launch-animation.d.ts +11 -0
  60. package/dist/components/flows/iris-chat/iris-chat-launch-animation.js +35 -0
  61. package/dist/components/flows/iris-chat/iris-chat-markdown.js +70 -50
  62. package/dist/components/flows/iris-chat/iris-chat-menu.js +91 -86
  63. package/dist/components/flows/iris-chat/iris-chat-speech.d.ts +52 -0
  64. package/dist/components/flows/iris-chat/iris-chat-speech.js +121 -0
  65. package/dist/components/flows/iris-chat/iris-chat-thread.d.ts +3 -0
  66. package/dist/components/flows/iris-chat/iris-chat-thread.js +241 -190
  67. package/dist/components/flows/iris-chat/iris-chat-window-chrome.d.ts +30 -0
  68. package/dist/components/flows/iris-chat/iris-chat-window-chrome.js +34 -0
  69. package/dist/components/flows/iris-chat/iris-chat-window-geometry-context.d.ts +14 -0
  70. package/dist/components/flows/iris-chat/iris-chat-window-geometry-context.js +15 -0
  71. package/dist/components/flows/iris-chat/iris-chat-window-geometry.d.ts +12 -0
  72. package/dist/components/flows/iris-chat/iris-chat-window-geometry.js +113 -0
  73. package/dist/components/flows/iris-chat/iris-chat-window-handles.d.ts +6 -0
  74. package/dist/components/flows/iris-chat/iris-chat-window-handles.js +50 -0
  75. package/dist/components/flows/iris-chat/iris-chat-window-shell.d.ts +8 -0
  76. package/dist/components/flows/iris-chat/iris-chat-window-shell.js +37 -0
  77. package/dist/components/flows/iris-chat/iris-chat.d.ts +3 -39
  78. package/dist/components/flows/iris-chat/iris-chat.js +22 -330
  79. package/dist/components/flows/iris-chat/iris-chat.types.d.ts +18 -0
  80. package/dist/components/flows/iris-chat/iris-chat.variants.d.ts +3 -3
  81. package/dist/components/flows/iris-chat/iris-chat.variants.js +21 -16
  82. package/dist/components/flows/iris-chat/use-iris-chat-root.d.ts +26 -0
  83. package/dist/components/flows/iris-chat/use-iris-chat-root.js +140 -0
  84. package/dist/components/forms/choice-card/choice-card.d.ts +1 -0
  85. package/dist/components/forms/choice-card/choice-card.js +183 -186
  86. package/dist/components/layout/header/header.js +1 -0
  87. package/dist/form-react/Fields/SelectField.js +66 -57
  88. package/dist/form-react/Fields/VirtualizedListField.js +140 -96
  89. package/dist/form-react/index.d.ts +1 -1
  90. package/dist/form-react/types/fields.types.d.ts +27 -0
  91. package/dist/form-react/types/reactHookForm.types.d.ts +18 -1
  92. package/dist/i18n/defaultMessages.d.ts +37 -0
  93. package/dist/i18n/defaultMessages.js +54 -18
  94. package/dist/i18n/index.d.ts +1 -1
  95. package/dist/i18n/locales/de.js +36 -0
  96. package/dist/i18n/locales/es.js +36 -0
  97. package/dist/i18n/locales/hi.js +36 -0
  98. package/dist/i18n/locales/kn.js +36 -0
  99. package/dist/impact-nova-components.css +19 -0
  100. package/dist/impact-nova.css +1 -1
  101. package/dist/llms/rules/installation.js +1 -1
  102. package/dist/llms/rules/requirements.js +1 -1
  103. package/package.json +5 -1
package/README.md CHANGED
@@ -315,7 +315,7 @@ Impact Nova provides a rich set of components structured for any enterprise use-
315
315
  ### 📊 Data Display
316
316
 
317
317
  - Avatar, Badge, Tag, Chips
318
- - Calendar, Chart
318
+ - Calendar, Chart, Stereo Scatter (`molecule` and `crystal`)
319
319
  - Empty Container, Notification Panel
320
320
  - Table (AG Grid), Data Table
321
321
  - Product Tile, Value With Unit
@@ -23,6 +23,10 @@ export declare function SkuPickerChrome(props: {
23
23
  onToggleSort: () => void;
24
24
  onSelectAll: () => void;
25
25
  onClear: () => void;
26
+ /** Multi-select shows Select All and Clear. Single-select omits them. */
27
+ showBulkActions?: boolean;
28
+ /** Search, sort, view toggle, and bulk actions. Default: true. */
29
+ showToolbar?: boolean;
26
30
  children: ReactNode;
27
31
  footer?: ReactNode;
28
32
  collapsible?: boolean;
@@ -1,42 +1,42 @@
1
- import { jsx as t, jsxs as a } from "react/jsx-runtime";
2
- import { Search as s, CardView as m, ListFilter as u, Sorting as h, Back as b } from "impact-nova-icons";
1
+ import { jsx as t, jsxs as l } from "react/jsx-runtime";
2
+ import { Search as s, CardView as m, ListFilter as u, ArrowUp as h, ArrowDown as b, Back as f } from "impact-nova-icons";
3
3
  import "react";
4
4
  import { Badge as v } from "../../data-display/badge/badge.js";
5
5
  import { ButtonIconTooltip as c } from "../../feedback/tooltip/button-icon-tooltip.js";
6
- import { Input as f } from "../../forms/input/input.js";
7
- import { Accordion as x, AccordionItem as g, AccordionTrigger as w, AccordionContent as C } from "../../primitives/accordion/accordion.js";
6
+ import { Input as x } from "../../forms/input/input.js";
7
+ import { Accordion as w, AccordionItem as g, AccordionTrigger as C, AccordionContent as N } from "../../primitives/accordion/accordion.js";
8
8
  import { Button as i } from "../../primitives/button/button.js";
9
- import { cn as N } from "../../../lib/utils.js";
9
+ import { cn as S } from "../../../lib/utils.js";
10
10
  const o = "picker";
11
- function S(e) {
12
- return N(
11
+ function y(e) {
12
+ return S(
13
13
  e && "border-brand bg-accent text-brand hover:bg-accent hover:text-brand"
14
14
  );
15
15
  }
16
- function y(e) {
16
+ function A(e) {
17
17
  if (e.selectedCount === 0)
18
18
  return /* @__PURE__ */ t("p", { className: "text-xs font-medium text-content-muted", children: e.emptyLabel });
19
- const l = Math.max(0, e.selectedCount - e.previewCodes.length);
20
- return /* @__PURE__ */ a("div", { className: "flex min-w-0 items-center gap-1", children: [
19
+ const a = Math.max(0, e.selectedCount - e.previewCodes.length);
20
+ return /* @__PURE__ */ l("div", { className: "flex min-w-0 items-center gap-1", children: [
21
21
  /* @__PURE__ */ t("p", { className: "truncate text-xs font-medium text-content-muted", children: e.previewCodes.join(", ") }),
22
- l > 0 ? /* @__PURE__ */ a(v, { variant: "subtle", color: "primary", size: "sm", shape: "square", children: [
22
+ a > 0 ? /* @__PURE__ */ l(v, { variant: "subtle", color: "primary", size: "sm", shape: "square", children: [
23
23
  "+",
24
- l
24
+ a
25
25
  ] }) : null
26
26
  ] });
27
27
  }
28
- function U(e) {
29
- const l = e.title ?? "SKU", n = /* @__PURE__ */ t(
30
- y,
28
+ function V(e) {
29
+ const a = e.title?.trim() ? e.title : void 0, n = /* @__PURE__ */ t(
30
+ A,
31
31
  {
32
32
  selectedCount: e.selectedCount,
33
33
  previewCodes: e.previewCodes,
34
34
  emptyLabel: e.emptyLabel ?? "No SKUs selected"
35
35
  }
36
- ), r = /* @__PURE__ */ a("div", { className: "flex items-center justify-between gap-3", children: [
37
- /* @__PURE__ */ a("div", { className: "flex items-center gap-3", children: [
36
+ ), r = /* @__PURE__ */ l("div", { className: "flex items-center justify-between gap-3", children: [
37
+ /* @__PURE__ */ l("div", { className: "flex items-center gap-3", children: [
38
38
  /* @__PURE__ */ t(
39
- f,
39
+ x,
40
40
  {
41
41
  size: "default",
42
42
  className: "w-[200px]",
@@ -77,20 +77,15 @@ function U(e) {
77
77
  variant: "tertiary",
78
78
  "aria-label": e.sortDirection === "desc" ? "Sort Z to A" : "Sort A to Z",
79
79
  "aria-pressed": e.sortDirection !== "none",
80
- className: S(e.sortDirection !== "none"),
80
+ className: y(e.sortDirection !== "none"),
81
81
  onClick: e.onToggleSort,
82
- children: /* @__PURE__ */ t(
83
- h,
84
- {
85
- className: e.sortDirection === "desc" ? "rotate-180" : void 0
86
- }
87
- )
82
+ children: e.sortDirection === "desc" ? /* @__PURE__ */ t(h, {}) : /* @__PURE__ */ t(b, {})
88
83
  }
89
84
  )
90
85
  }
91
86
  )
92
87
  ] }),
93
- /* @__PURE__ */ a("div", { className: "flex items-center gap-3", children: [
88
+ e.showBulkActions === !1 ? null : /* @__PURE__ */ l("div", { className: "flex items-center gap-3", children: [
94
89
  /* @__PURE__ */ t(
95
90
  i,
96
91
  {
@@ -116,40 +111,40 @@ function U(e) {
116
111
  ] })
117
112
  ] });
118
113
  return e.collapsible ? /* @__PURE__ */ t(
119
- x,
114
+ w,
120
115
  {
121
116
  type: "single",
122
117
  collapsible: !0,
123
118
  defaultValue: e.defaultCollapsed ? void 0 : o,
124
119
  className: "w-full",
125
- children: /* @__PURE__ */ a(g, { value: o, className: "border border-stroke-subtle", children: [
126
- /* @__PURE__ */ t(w, { headingLevel: 3, rightActions: n, children: /* @__PURE__ */ a("span", { className: "truncate text-sm font-semibold leading-6 text-content-title", children: [
127
- l,
120
+ children: /* @__PURE__ */ l(g, { value: o, className: "border border-stroke-subtle", children: [
121
+ /* @__PURE__ */ t(C, { headingLevel: 3, rightActions: n, children: a ? /* @__PURE__ */ l("span", { className: "truncate text-sm font-semibold leading-6 text-content-title", children: [
122
+ a,
128
123
  e.required ? /* @__PURE__ */ t("span", { className: "text-destructive", children: " *" }) : null
129
- ] }) }),
130
- /* @__PURE__ */ a(C, { className: "flex flex-col gap-3", children: [
131
- r,
124
+ ] }) : null }),
125
+ /* @__PURE__ */ l(N, { className: "flex flex-col gap-3", children: [
126
+ e.showToolbar === !1 ? null : r,
132
127
  e.children,
133
128
  e.footer
134
129
  ] })
135
130
  ] })
136
131
  }
137
- ) : /* @__PURE__ */ a("div", { className: "flex w-full flex-col gap-3 overflow-hidden rounded-lg border border-stroke-subtle bg-canvas-elevated px-4 py-2", children: [
138
- /* @__PURE__ */ a("div", { className: "flex items-center justify-between gap-3", children: [
139
- /* @__PURE__ */ a("div", { className: "flex items-center gap-3", children: [
140
- e.showBack === !1 ? null : /* @__PURE__ */ t(i, { type: "button", size: "icon", variant: "ghost", "aria-label": "Back", children: /* @__PURE__ */ t(b, {}) }),
141
- /* @__PURE__ */ a("p", { className: "text-sm font-semibold leading-6 text-content-title", children: [
142
- l,
132
+ ) : /* @__PURE__ */ l("div", { className: "flex w-full flex-col gap-3 overflow-hidden rounded-lg border border-stroke-subtle bg-canvas-elevated px-4 py-2", children: [
133
+ /* @__PURE__ */ l("div", { className: "flex items-center justify-between gap-3", children: [
134
+ /* @__PURE__ */ l("div", { className: "flex items-center gap-3", children: [
135
+ e.showBack === !1 ? null : /* @__PURE__ */ t(i, { type: "button", size: "icon", variant: "ghost", "aria-label": "Back", children: /* @__PURE__ */ t(f, {}) }),
136
+ a ? /* @__PURE__ */ l("p", { className: "text-sm font-semibold leading-6 text-content-title", children: [
137
+ a,
143
138
  e.required ? /* @__PURE__ */ t("span", { className: "text-destructive", children: " *" }) : null
144
- ] })
139
+ ] }) : null
145
140
  ] }),
146
141
  n
147
142
  ] }),
148
- r,
143
+ e.showToolbar === !1 ? null : r,
149
144
  e.children,
150
145
  e.footer
151
146
  ] });
152
147
  }
153
148
  export {
154
- U as SkuPickerChrome
149
+ V as SkuPickerChrome
155
150
  };
@@ -0,0 +1,2 @@
1
+ export { StereoScatter, StereoScatterLegend, StereoScatterTooltip, StereoScatterViewport, } from './stereo-scatter';
2
+ export type { StereoScatterAxis, StereoScatterCluster, StereoScatterHover, StereoScatterLegendProps, StereoScatterPoint, StereoScatterProps, StereoScatterTarget, StereoScatterTooltipProps, StereoScatterVariant, StereoScatterView, StereoScatterViewportProps, } from './stereo-scatter.types';
@@ -0,0 +1,10 @@
1
+ import { StereoScatter as r } from "./stereo-scatter.js";
2
+ import { StereoScatterLegend as S } from "./internals/stereo-scatter-legend.js";
3
+ import { StereoScatterTooltip as a } from "./internals/stereo-scatter-tooltip.js";
4
+ import { StereoScatterViewport as f } from "./internals/stereo-scatter-viewport.js";
5
+ export {
6
+ r as StereoScatter,
7
+ S as StereoScatterLegend,
8
+ a as StereoScatterTooltip,
9
+ f as StereoScatterViewport
10
+ };
@@ -0,0 +1,41 @@
1
+ import { Group, Vector3, Camera } from 'three';
2
+ import { StereoModel } from './stereo-model';
3
+ import { StereoTheme } from './stereo-engine-theme';
4
+ export interface StereoFrameAxes {
5
+ x: {
6
+ label: string;
7
+ format: (value: number) => string;
8
+ };
9
+ y: {
10
+ label: string;
11
+ format: (value: number) => string;
12
+ };
13
+ z: {
14
+ label: string;
15
+ format: (value: number) => string;
16
+ };
17
+ }
18
+ export type StereoFrameSigns = {
19
+ x: number;
20
+ z: number;
21
+ };
22
+ /** Vertical cube edge on the left silhouette for a camera in the `signs` quadrant. */
23
+ export declare function leftSilhouette(signs: StereoFrameSigns): StereoFrameSigns;
24
+ /**
25
+ * Axis frame for the scene cube: floor grid, faint gridlines on the two back walls, and
26
+ * three solid axis rods with arrowheads, tick marks, values, and titles. Rods and labels
27
+ * follow the camera quadrant so they always sit on the near, readable edges.
28
+ */
29
+ export declare class StereoAxisFrame {
30
+ readonly group: Group<import('three').Object3DEventMap>;
31
+ private readonly walls;
32
+ private readonly rods;
33
+ private readonly labels;
34
+ private signs;
35
+ private hiddenAxis;
36
+ constructor(model: StereoModel, theme: StereoTheme, axes: StereoFrameAxes);
37
+ update(camera: Camera, target: Vector3): void;
38
+ /** Near edges that carry the X and Z rods; hover guides drop onto them. */
39
+ nearEdges(): StereoFrameSigns;
40
+ dispose(): void;
41
+ }
@@ -0,0 +1,178 @@
1
+ import { Group as C, LineBasicMaterial as g, MeshBasicMaterial as P, DoubleSide as B, Mesh as S, PlaneGeometry as U, Vector3 as a, CylinderGeometry as Q, ConeGeometry as X, Vector2 as L, BufferGeometry as q, Float32BufferAttribute as J, LineSegments as K } from "three";
2
+ import { CSS2DObject as V } from "three/addons/renderers/CSS2DRenderer.js";
3
+ import { normalizeToCube as Y } from "./stereo-math.js";
4
+ const Z = "pointer-events-none select-none whitespace-nowrap text-[10px] font-medium leading-3 tabular-nums text-content-muted", $ = "pointer-events-none select-none flex items-center gap-1 whitespace-nowrap text-[11px] font-semibold leading-4 text-content-secondary", k = "inline-flex size-4 items-center justify-center rounded-full bg-canvas-muted text-[9px] font-bold uppercase leading-none text-content", W = 55e-4, w = 0.1, I = 0.075, tt = 0.024, O = 0.045, M = 0.05, _ = 0.94;
5
+ function j(r, n = new L(0.5, 0.5)) {
6
+ const o = new V(r);
7
+ return o.center.copy(n), o;
8
+ }
9
+ function et(r, n) {
10
+ const o = document.createElement("div");
11
+ return o.className = n, o.textContent = r, o;
12
+ }
13
+ function nt(r, n) {
14
+ const o = document.createElement("div");
15
+ o.className = $;
16
+ const s = document.createElement("span");
17
+ s.className = k, s.textContent = r;
18
+ const u = document.createElement("span");
19
+ return u.textContent = n, o.append(s, u), o;
20
+ }
21
+ function G(r) {
22
+ return r.ticks.map((n) => ({ value: n, position: Y(n, r) })).filter((n) => n.position >= -1 - 1e-6 && n.position <= 1 + 1e-6);
23
+ }
24
+ function A(r, n) {
25
+ const o = new q();
26
+ return o.setAttribute(
27
+ "position",
28
+ new J(r.flatMap((s) => [s.x, s.y, s.z]), 3)
29
+ ), new K(o, n);
30
+ }
31
+ function ot(r) {
32
+ r.traverse((n) => {
33
+ if (n instanceof S || n instanceof K) {
34
+ n.geometry.dispose();
35
+ const o = n.material;
36
+ Array.isArray(o) ? o.forEach((s) => s.dispose()) : o.dispose();
37
+ }
38
+ n instanceof V && n.element.remove();
39
+ });
40
+ }
41
+ function m(r) {
42
+ return r.x * r.z > 0 ? { x: -r.x, z: r.z } : { x: r.x, z: -r.z };
43
+ }
44
+ class at {
45
+ group = new C();
46
+ walls;
47
+ rods;
48
+ labels = [];
49
+ signs = { x: 0, z: 0 };
50
+ hiddenAxis = null;
51
+ constructor(n, o, s) {
52
+ const u = new g({ color: o.grid, transparent: !0, opacity: 0.95, fog: !1 }), z = new g({ color: o.grid, transparent: !0, opacity: 0.6, fog: !1 }), f = new g({ color: o.gridStrong, transparent: !0, opacity: 0.8, fog: !1 }), x = new P({
53
+ color: o.wall,
54
+ transparent: !0,
55
+ opacity: 0.4,
56
+ side: B,
57
+ depthWrite: !1,
58
+ fog: !1
59
+ }), D = new P({ color: o.muted, side: B, fog: !1 }), h = {
60
+ x: G(n.domains.x),
61
+ y: G(n.domains.y),
62
+ z: G(n.domains.z)
63
+ }, b = new S(new U(2, 2), x);
64
+ b.rotation.x = -Math.PI / 2, b.position.y = -1.003, b.renderOrder = -2, this.group.add(b), this.group.add(
65
+ A(
66
+ [
67
+ ...h.x.flatMap((t) => [new a(t.position, -1, -1), new a(t.position, -1, 1)]),
68
+ ...h.z.flatMap((t) => [new a(-1, -1, t.position), new a(1, -1, t.position)])
69
+ ],
70
+ u
71
+ )
72
+ ), this.group.add(
73
+ A(
74
+ [
75
+ [-1, -1, -1, 1, -1, -1],
76
+ [1, -1, -1, 1, -1, 1],
77
+ [1, -1, 1, -1, -1, 1],
78
+ [-1, -1, 1, -1, -1, -1]
79
+ ].flatMap(([t, e, i, l, c, d]) => [new a(t, e, i), new a(l, c, d)]),
80
+ f
81
+ )
82
+ );
83
+ const y = (t, e) => {
84
+ const i = new C(), l = (c, d) => t === "x" ? new a(e, d, c) : new a(c, d, e);
85
+ return i.add(
86
+ A(
87
+ h.y.flatMap((c) => [l(-1, c.position), l(1, c.position)]),
88
+ z
89
+ )
90
+ ), this.group.add(i), i;
91
+ };
92
+ this.walls = {
93
+ x: { "-1": y("x", -1), 1: y("x", 1) },
94
+ z: { "-1": y("z", -1), 1: y("z", 1) }
95
+ };
96
+ const F = new Q(W, W, 2 + w, 8), H = new X(tt, I, 16), T = (t) => {
97
+ const e = new C(), i = new S(F, D), l = new S(H, D), c = 1 + w + I / 2;
98
+ t === "x" ? (i.rotation.z = -Math.PI / 2, i.position.x = w / 2, l.rotation.z = -Math.PI / 2, l.position.x = c) : t === "z" ? (i.rotation.x = Math.PI / 2, i.position.z = w / 2, l.rotation.x = Math.PI / 2, l.position.z = c) : (i.position.y = w / 2, l.position.y = c), e.add(i, l);
99
+ const d = h[t].flatMap((p) => {
100
+ if (t === "x") return [new a(p.position, 0, 0), new a(p.position, 0, O)];
101
+ if (t === "z") return [new a(0, 0, p.position), new a(O, 0, p.position)];
102
+ const N = O / Math.SQRT2;
103
+ return [new a(0, p.position, 0), new a(N, p.position, N)];
104
+ });
105
+ return e.add(A(d, new g({ color: o.muted, fog: !1 }))), this.group.add(e), e;
106
+ };
107
+ this.rods = { x: T("x"), y: T("y"), z: T("z") };
108
+ const E = (t, e, i, l) => {
109
+ for (const c of h[t]) {
110
+ const d = j(et(s[t].format(c.value), Z), l);
111
+ this.labels.push({
112
+ axis: t,
113
+ object: d,
114
+ place: (p) => e(c.position, p),
115
+ visible: (p) => i(c.position, p)
116
+ }), this.group.add(d);
117
+ }
118
+ };
119
+ E(
120
+ "x",
121
+ (t, e) => new a(t, -1.02, e.z * 1.13),
122
+ (t, e) => {
123
+ const i = m(e);
124
+ return !(i.z === e.z && Math.abs(t - i.x) < M);
125
+ }
126
+ ), E(
127
+ "z",
128
+ (t, e) => new a(e.x * 1.15, -1.02, t),
129
+ (t, e) => {
130
+ const i = m(e);
131
+ return Math.abs(t - e.z) < M ? !1 : !(i.x === e.x && Math.abs(t - i.z) < M);
132
+ }
133
+ ), E(
134
+ "y",
135
+ (t, e) => {
136
+ const i = m(e);
137
+ return new a(i.x * 1.07, t, i.z * 1.07);
138
+ },
139
+ (t) => t > -1 + M,
140
+ new L(1, 0.5)
141
+ );
142
+ const v = (t, e, i) => {
143
+ const l = j(nt(t, s[t].label), i);
144
+ this.labels.push({ axis: t, object: l, place: e }), this.group.add(l);
145
+ }, R = 1 + w + I + 0.12;
146
+ v("x", (t) => new a(R, -1, t.z)), v("z", (t) => new a(t.x, -1, R)), v(
147
+ "y",
148
+ (t) => {
149
+ const e = m(t);
150
+ return new a(e.x, R - 0.06, e.z);
151
+ },
152
+ new L(0.5, 1)
153
+ );
154
+ }
155
+ update(n, o) {
156
+ const s = {
157
+ x: n.position.x - o.x >= 0 ? 1 : -1,
158
+ z: n.position.z - o.z >= 0 ? 1 : -1
159
+ }, u = n.position.clone().sub(o).normalize(), z = Math.abs(u.y) > _ ? "y" : Math.abs(u.x) > _ ? "x" : Math.abs(u.z) > _ ? "z" : null;
160
+ if (s.x === this.signs.x && s.z === this.signs.z && z === this.hiddenAxis) return;
161
+ this.signs = s, this.hiddenAxis = z, this.walls.x[1].visible = s.x < 0, this.walls.x[-1].visible = s.x > 0, this.walls.z[1].visible = s.z < 0, this.walls.z[-1].visible = s.z > 0;
162
+ const f = m(s);
163
+ this.rods.x.position.set(0, -1, s.z), this.rods.x.scale.set(1, 1, s.z), this.rods.z.position.set(s.x, -1, 0), this.rods.z.scale.set(s.x, 1, 1), this.rods.y.position.set(f.x, 0, f.z), this.rods.y.scale.set(f.x, 1, f.z);
164
+ for (const x of this.labels)
165
+ x.object.position.copy(x.place(s)), x.object.visible = x.axis !== z && (x.visible?.(s) ?? !0);
166
+ }
167
+ /** Near edges that carry the X and Z rods; hover guides drop onto them. */
168
+ nearEdges() {
169
+ return { x: this.signs.x || 1, z: this.signs.z || 1 };
170
+ }
171
+ dispose() {
172
+ ot(this.group);
173
+ }
174
+ }
175
+ export {
176
+ at as StereoAxisFrame,
177
+ m as leftSilhouette
178
+ };
@@ -0,0 +1,14 @@
1
+ import { Color } from 'three';
2
+ import { StereoModel } from './stereo-model';
3
+ export interface StereoTheme {
4
+ surface: Color;
5
+ foreground: Color;
6
+ muted: Color;
7
+ grid: Color;
8
+ gridStrong: Color;
9
+ wall: Color;
10
+ brand: Color;
11
+ clusterColors: Map<string, Color>;
12
+ }
13
+ /** WebGL needs concrete colors, so tokens are resolved once per theme against the host element. */
14
+ export declare function readStereoTheme(scope: HTMLElement, model: StereoModel): StereoTheme;
@@ -0,0 +1,29 @@
1
+ import { Color as c } from "three";
2
+ import { resolveDesignTokenColor as s } from "../../../../lib/resolve-design-token-color.js";
3
+ function o(r, a, n) {
4
+ const e = s(r, a);
5
+ if (!e || e.startsWith("var(")) return n.clone();
6
+ const t = new c();
7
+ return t.setStyle(e), t;
8
+ }
9
+ function m(r, a) {
10
+ const n = new c(0.97, 0.97, 0.98), e = new c(0.12, 0.13, 0.16), t = o("var(--color-surface-elevated)", r, n), l = o("var(--color-foreground)", r, e), d = o("var(--color-border-hairline)", r, n), i = o("var(--color-border)", r, d);
11
+ return {
12
+ surface: t,
13
+ foreground: l,
14
+ muted: o("var(--color-muted-foreground)", r, l),
15
+ grid: d,
16
+ gridStrong: i,
17
+ wall: o("var(--color-surface-muted)", r, t),
18
+ brand: o("var(--color-primary)", r, l),
19
+ clusterColors: new Map(
20
+ a.clusters.map((u) => [
21
+ u.cluster.id,
22
+ o(u.color, r, l)
23
+ ])
24
+ )
25
+ };
26
+ }
27
+ export {
28
+ m as readStereoTheme
29
+ };
@@ -0,0 +1,23 @@
1
+ import { Color, Group, Vector3, Camera } from 'three';
2
+ export interface StereoBondSpec {
3
+ from: Vector3;
4
+ to: Vector3;
5
+ fromRadius: number;
6
+ toRadius: number;
7
+ color: Color;
8
+ }
9
+ /**
10
+ * Bonds drawn with stereochemistry notation, recomputed whenever the camera moves:
11
+ * a tapered solid cone when the substituent faces the viewer, widening rungs when it
12
+ * recedes, and a plain stick when it is level with the stereocentre.
13
+ */
14
+ export declare class StereoWedgeBonds {
15
+ readonly group: Group<import('three').Object3DEventMap>;
16
+ private readonly solid;
17
+ private readonly plain;
18
+ private readonly rungs;
19
+ private readonly scratch;
20
+ constructor(capacity: number);
21
+ update(bonds: readonly StereoBondSpec[], camera: Camera): void;
22
+ dispose(): void;
23
+ }
@@ -0,0 +1,80 @@
1
+ import { Group as V, Vector3 as s, Quaternion as v, Matrix4 as U, MeshStandardMaterial as z, InstancedMesh as m, CylinderGeometry as y, BoxGeometry as G, Color as N, PerspectiveCamera as R } from "three";
2
+ import { wedgeStyleForDepth as q, wedgeStrength as D, clamp as I } from "./stereo-math.js";
3
+ const P = new s(0, 1, 0), _ = 0.038, S = 12, A = 85e-4, C = 75e-4;
4
+ class F {
5
+ group = new V();
6
+ solid;
7
+ plain;
8
+ rungs;
9
+ scratch = {
10
+ matrix: new U(),
11
+ quaternion: new v(),
12
+ scale: new s(),
13
+ position: new s(),
14
+ direction: new s(),
15
+ unit: new s(),
16
+ view: new s(),
17
+ start: new s(),
18
+ end: new s(),
19
+ side: new s(),
20
+ depthAxis: new s()
21
+ };
22
+ constructor(r) {
23
+ const o = new z({ roughness: 0.38, metalness: 0.05 }), t = Math.max(1, r);
24
+ this.solid = new m(new y(1, 0.14, 1, 16, 1), o, t), this.plain = new m(new y(1, 1, 1, 10, 1), o, t), this.rungs = new m(new G(1, 1, 1), o, t * S);
25
+ const a = new N(1, 1, 1);
26
+ for (const i of [this.solid, this.plain, this.rungs]) {
27
+ for (let n = 0; n < i.count; n += 1) i.setColorAt(n, a);
28
+ i.count = 0, i.frustumCulled = !1, i.castShadow = !0, this.group.add(i);
29
+ }
30
+ }
31
+ update(r, o) {
32
+ const t = this.scratch, a = new s();
33
+ o.getWorldDirection(a);
34
+ const i = o instanceof R;
35
+ let n = 0, c = 0, l = 0;
36
+ for (const e of r) {
37
+ t.direction.subVectors(e.to, e.from);
38
+ const w = t.direction.length();
39
+ if (w < 1e-4) continue;
40
+ t.unit.copy(t.direction).divideScalar(w), i ? t.view.addVectors(e.from, e.to).multiplyScalar(0.5).sub(o.position).normalize() : t.view.copy(a);
41
+ const f = -t.direction.dot(t.view), x = q(f);
42
+ t.start.copy(e.from).addScaledVector(t.unit, e.fromRadius), t.end.copy(e.to).addScaledVector(t.unit, -e.toRadius * 0.35);
43
+ const d = t.start.distanceTo(t.end);
44
+ if (d < 4e-3) continue;
45
+ const h = 0.012 + 0.03 * D(f);
46
+ if (t.position.addVectors(t.start, t.end).multiplyScalar(0.5), t.quaternion.setFromUnitVectors(P, t.unit), x === "solid")
47
+ t.scale.set(h, d, h), t.matrix.compose(t.position, t.quaternion, t.scale), this.solid.setMatrixAt(n, t.matrix), this.solid.setColorAt(n, e.color), n += 1;
48
+ else if (x === "plain")
49
+ t.scale.set(A, d, A), t.matrix.compose(t.position, t.quaternion, t.scale), this.plain.setMatrixAt(c, t.matrix), this.plain.setColorAt(c, e.color), c += 1;
50
+ else {
51
+ t.side.crossVectors(t.unit, t.view), t.side.lengthSq() < 1e-8 && t.side.set(1, 0, 0), t.side.normalize(), t.depthAxis.crossVectors(t.side, t.unit).normalize();
52
+ const g = I(Math.round(d / _), 4, S);
53
+ for (let p = 1; p <= g; p += 1) {
54
+ const u = p / g, M = Math.max(6e-3, h * 1.15 * u);
55
+ t.matrix.makeBasis(
56
+ t.side.clone().multiplyScalar(M * 2),
57
+ t.unit.clone().multiplyScalar(C),
58
+ t.depthAxis.clone().multiplyScalar(C)
59
+ ), t.matrix.setPosition(
60
+ t.start.x + (t.end.x - t.start.x) * u,
61
+ t.start.y + (t.end.y - t.start.y) * u,
62
+ t.start.z + (t.end.z - t.start.z) * u
63
+ ), this.rungs.setMatrixAt(l, t.matrix), this.rungs.setColorAt(l, e.color), l += 1;
64
+ }
65
+ }
66
+ }
67
+ this.solid.count = n, this.plain.count = c, this.rungs.count = l;
68
+ for (const e of [this.solid, this.plain, this.rungs])
69
+ e.instanceMatrix.needsUpdate = !0, e.instanceColor && (e.instanceColor.needsUpdate = !0);
70
+ }
71
+ dispose() {
72
+ for (const o of [this.solid, this.plain, this.rungs])
73
+ o.geometry.dispose(), o.dispose();
74
+ const r = this.solid.material;
75
+ Array.isArray(r) || r.dispose();
76
+ }
77
+ }
78
+ export {
79
+ F as StereoWedgeBonds
80
+ };
@@ -0,0 +1,120 @@
1
+ import { StereoScatterHover, StereoScatterTarget, StereoScatterVariant, StereoScatterView } from '../stereo-scatter.types';
2
+ import { StereoModel } from './stereo-model';
3
+ import { StereoFrameAxes } from './stereo-engine-frame';
4
+ export interface StereoEmphasis {
5
+ hiddenClusterIds: ReadonlySet<string>;
6
+ activeClusterId: string | null;
7
+ focusedClusterId: string | null;
8
+ }
9
+ export interface StereoEngineOptions {
10
+ container: HTMLElement;
11
+ gizmo: SVGSVGElement | null;
12
+ variant: StereoScatterVariant;
13
+ model: StereoModel;
14
+ axes: StereoFrameAxes;
15
+ defaultView: StereoScatterView;
16
+ autoRotate: boolean;
17
+ reducedMotion: boolean;
18
+ formatStoreCount: (count: number) => string;
19
+ onHover: (hover: StereoScatterHover | null) => void;
20
+ onClick: (target: StereoScatterTarget | null) => void;
21
+ }
22
+ /**
23
+ * Imperative WebGL scene. React owns legend, tooltip, and focus state; the engine owns
24
+ * camera, meshes, and per-frame work so orbiting never re-renders React.
25
+ */
26
+ export declare class StereoEngine {
27
+ private readonly options;
28
+ private readonly config;
29
+ private readonly theme;
30
+ private readonly renderer;
31
+ private readonly labelRenderer;
32
+ private readonly scene;
33
+ private readonly camera;
34
+ private readonly controls;
35
+ private readonly raycaster;
36
+ private readonly disposables;
37
+ private readonly nodes;
38
+ private readonly positions;
39
+ private readonly targets;
40
+ private readonly sceneCenter;
41
+ /** Atoms shrink as the store count grows so dense networks stay legible. */
42
+ private readonly atomRadius;
43
+ private readonly extents;
44
+ private readonly bestOrbit;
45
+ private readonly clusters;
46
+ private readonly centroidPositions;
47
+ private readonly atoms;
48
+ private readonly centroids;
49
+ private readonly bonds;
50
+ private readonly hulls;
51
+ private readonly labels;
52
+ private readonly axisFrame;
53
+ private readonly guides;
54
+ private readonly guideMarkers;
55
+ private readonly gizmoParts;
56
+ private emphasis;
57
+ private hoverTarget;
58
+ private autoRotate;
59
+ private zoom;
60
+ private baseDistance;
61
+ private size;
62
+ private progress;
63
+ private entranceStart;
64
+ private tween;
65
+ private interacting;
66
+ private pointerInside;
67
+ private pointer;
68
+ private pointerDown;
69
+ private hoverPending;
70
+ private atomsDirty;
71
+ private cameraDirty;
72
+ private needsRender;
73
+ private onScreen;
74
+ private frameId;
75
+ private resizeObserver;
76
+ private intersectionObserver;
77
+ private envTexture;
78
+ constructor(options: StereoEngineOptions);
79
+ setEmphasis(next: StereoEmphasis): void;
80
+ setAutoRotate(enabled: boolean): void;
81
+ setView(view: StereoScatterView): void;
82
+ rotateBy(azimuth: number, elevation: number): void;
83
+ zoomBy(factor: number): void;
84
+ resetView(): void;
85
+ dispose(): void;
86
+ private orbitForView;
87
+ private createInstances;
88
+ private setupLighting;
89
+ private buildShadowPlane;
90
+ private buildHulls;
91
+ private buildGuides;
92
+ private buildLabels;
93
+ private buildGizmo;
94
+ private readonly handleControlsChange;
95
+ private readonly handleControlsStart;
96
+ private readonly handleControlsEnd;
97
+ private readonly handlePointerMove;
98
+ private readonly handlePointerLeave;
99
+ private readonly handlePointerDown;
100
+ private readonly handlePointerUp;
101
+ private readonly tick;
102
+ private resize;
103
+ private readPose;
104
+ private lerpPose;
105
+ private applyPose;
106
+ private tweenTo;
107
+ private effectiveActiveCluster;
108
+ private colorFor;
109
+ private centroidRadius;
110
+ private updateAtoms;
111
+ private updateCameraDependents;
112
+ private updateBonds;
113
+ private updateGuides;
114
+ private layoutLabels;
115
+ private updateGizmo;
116
+ private pick;
117
+ private updateHoverFromPointer;
118
+ private setHover;
119
+ }
120
+ export declare function createStereoEngine(options: StereoEngineOptions): StereoEngine | null;