@nadicodeai/ui 12.1.150 → 12.1.151

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.
@@ -25,6 +25,13 @@ export type HivePoint = {
25
25
  x: number;
26
26
  y: number;
27
27
  };
28
+ /** A box in the scene's pixels, from its top left corner. */
29
+ export type HiveBox = {
30
+ left: number;
31
+ top: number;
32
+ right: number;
33
+ bottom: number;
34
+ };
28
35
  /** Where the work comes from and goes to in the picture, in the scene's pixels. */
29
36
  export type HiveWork = {
30
37
  senders: readonly HivePoint[];
@@ -41,13 +48,16 @@ export type HiveSceneProps = Omit<React.ComponentProps<"div">, "children"> & {
41
48
  src: string;
42
49
  label: string;
43
50
  };
44
- /** The app's picture, placed by the app's own stylesheet. */
51
+ /**
52
+ * The app's picture, placed by the app's own stylesheet, which keeps it clear of the words by
53
+ * the width the scene sets on itself as `--hive-words-width`.
54
+ */
45
55
  picture?: React.ReactNode;
46
- /** The picture's people for the scene's current size, so the work reaches them. */
47
- work?: (size: {
48
- width: number;
49
- height: number;
50
- }) => HiveWork;
56
+ /**
57
+ * The picture's people, so the work reaches them: `pictures` are the boxes the picture's
58
+ * elements are drawn in now, in their order, an element not drawn as an empty box.
59
+ */
60
+ work?: (pictures: readonly HiveBox[]) => HiveWork;
51
61
  /** Window chrome the scene must carry, such as a drag region. */
52
62
  chrome?: React.ReactNode;
53
63
  /** What `loading` is waiting for, read by assistive technology. */
@@ -62,7 +72,8 @@ export type HiveSceneProps = Omit<React.ComponentProps<"div">, "children"> & {
62
72
  * @instead Nadia's entry screens are `EntryScene`. A product page never stands on a scene.
63
73
  * @behaviour `join` puts the words in the hexagon's middle, `loading` draws the orbs in with no
64
74
  * words, `still` shows no Agent and no work. Only the orbs and the particles move; reduced motion
65
- * stops both. Black in every theme.
75
+ * stops both. Black in every theme. The scene sets the width its words are drawn at on itself as
76
+ * `--hive-words-width`, so the app's picture keeps clear of them, and draws no honeycomb near them.
66
77
  * @words The words are the screen's own: a title, a line, one action. The logo's label names
67
78
  * Alveare.
68
79
  * @access The canvases are hidden; the logo's image is named by its label. In `loading` the scene
@@ -1 +1 @@
1
- {"version":3,"file":"hive-scene.d.ts","sourceRoot":"","sources":["../../src/components/hive-scene.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,MAAM,SAAS,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,mFAAmF;AACnF,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IAC9B,SAAS,EAAE,SAAS,SAAS,EAAE,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAEzD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,OAAO,CAAC;AAElD,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,GAAG;IAC3E,IAAI,EAAE,aAAa,CAAC;IACpB,qFAAqF;IACrF,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,kFAAkF;IAClF,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,6DAA6D;IAC7D,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,mFAAmF;IACnF,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,QAAQ,CAAC;IAC7D,iEAAiE;IACjE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAmLF;;;;;;;;;;;;;GAaG;AACH,iBAAS,SAAS,CAAC,EACjB,IAAI,EACJ,MAAkB,EAClB,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,MAAM,EACN,KAAK,EACL,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,cAAc,qBA8PhB;AAED,2DAA2D;AAC3D,iBAAS,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,qBAM9E;AAED,iEAAiE;AACjE,iBAAS,QAAQ,CAAC,EAChB,QAAQ,EACR,EAAE,EACF,IAAa,GACd,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACzB,qBAMA;AAED,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"hive-scene.d.ts","sourceRoot":"","sources":["../../src/components/hive-scene.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,MAAM,SAAS,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,6DAA6D;AAC7D,MAAM,MAAM,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnF,mFAAmF;AACnF,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IAC9B,SAAS,EAAE,SAAS,SAAS,EAAE,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAEzD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,OAAO,CAAC;AAElD,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,GAAG;IAC3E,IAAI,EAAE,aAAa,CAAC;IACpB,qFAAqF;IACrF,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,kFAAkF;IAClF,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;OAGG;IACH,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,KAAK,QAAQ,CAAC;IAClD,iEAAiE;IACjE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AA4LF;;;;;;;;;;;;;;GAcG;AACH,iBAAS,SAAS,CAAC,EACjB,IAAI,EACJ,MAAkB,EAClB,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,MAAM,EACN,KAAK,EACL,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,cAAc,qBA4QhB;AAED,2DAA2D;AAC3D,iBAAS,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,qBAM9E;AAED,iEAAiE;AACjE,iBAAS,QAAQ,CAAC,EAChB,QAAQ,EACR,EAAE,EACF,IAAa,GACd,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACzB,qBAMA;AAED,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC"}
@@ -111,7 +111,7 @@ const COMB_CLUSTERS = [
111
111
  ],
112
112
  },
113
113
  ];
114
- function drawComb(canvas, width, height) {
114
+ function drawComb(canvas, width, height, words) {
115
115
  const context = sizeCanvas(canvas, width, height);
116
116
  if (!context)
117
117
  return;
@@ -120,14 +120,22 @@ function drawComb(canvas, width, height) {
120
120
  // Pointy-top cells in axial coordinates: q along the row, r down the rows.
121
121
  // One path per cluster, stroked once, so an edge two cells share is one line.
122
122
  const across = Math.sqrt(3) * COMB_RADIUS;
123
+ const reach = COMB_RADIUS + WORDS_GAP;
123
124
  for (const cluster of COMB_CLUSTERS) {
125
+ const centres = cluster.cells.map(([q, r]) => ({
126
+ x: cluster.x * width + across * (q + r / 2),
127
+ y: cluster.y * height + 1.5 * COMB_RADIUS * r,
128
+ }));
129
+ const nearWords = words &&
130
+ centres.some(({ x, y }) => x + reach > words.left &&
131
+ x - reach < words.right &&
132
+ y + reach > words.top &&
133
+ y - reach < words.bottom);
134
+ if (nearWords)
135
+ continue;
124
136
  context.globalAlpha = cluster.alpha;
125
137
  context.beginPath();
126
- for (const [q, r] of cluster.cells) {
127
- const centre = {
128
- x: cluster.x * width + across * (q + r / 2),
129
- y: cluster.y * height + 1.5 * COMB_RADIUS * r,
130
- };
138
+ for (const centre of centres) {
131
139
  for (let k = 0; k <= 6; k += 1) {
132
140
  const { x, y } = corner(k % 6, centre, COMB_RADIUS);
133
141
  if (k === 0)
@@ -158,7 +166,8 @@ function pick(items) {
158
166
  * @instead Nadia's entry screens are `EntryScene`. A product page never stands on a scene.
159
167
  * @behaviour `join` puts the words in the hexagon's middle, `loading` draws the orbs in with no
160
168
  * words, `still` shows no Agent and no work. Only the orbs and the particles move; reduced motion
161
- * stops both. Black in every theme.
169
+ * stops both. Black in every theme. The scene sets the width its words are drawn at on itself as
170
+ * `--hive-words-width`, so the app's picture keeps clear of them, and draws no honeycomb near them.
162
171
  * @words The words are the screen's own: a title, a line, one action. The logo's label names
163
172
  * Alveare.
164
173
  * @access The canvases are hidden; the logo's image is named by its label. In `loading` the scene
@@ -168,6 +177,7 @@ function HiveScene({ mode, column = "default", logo, picture, work, chrome, labe
168
177
  const sceneRef = React.useRef(null);
169
178
  const combRef = React.useRef(null);
170
179
  const flowRef = React.useRef(null);
180
+ const picturesRef = React.useRef(null);
171
181
  const orbRefs = React.useRef([]);
172
182
  const holderRefs = React.useRef([]);
173
183
  // The words' box, kept as state so the scene places the orbs again when it appears.
@@ -208,12 +218,13 @@ function HiveScene({ mode, column = "default", logo, picture, work, chrome, labe
208
218
  let height = 0;
209
219
  let context = null;
210
220
  let seats = [];
221
+ let bounds = scene.getBoundingClientRect();
211
222
  const place = () => {
212
223
  width = scene.clientWidth;
213
224
  height = scene.clientHeight;
214
225
  const centre = { x: width / 2, y: height / 2 };
215
226
  const radius = cellRadius(width, height) * (mode === "loading" ? 0.62 : 1);
216
- const bounds = scene.getBoundingClientRect();
227
+ bounds = scene.getBoundingClientRect();
217
228
  const box = wordsColumn?.getBoundingClientRect();
218
229
  const words = box?.width
219
230
  ? {
@@ -223,6 +234,7 @@ function HiveScene({ mode, column = "default", logo, picture, work, chrome, labe
223
234
  bottom: box.bottom - bounds.top,
224
235
  }
225
236
  : null;
237
+ scene.style.setProperty("--hive-words-width", `${words ? words.right - words.left : 0}px`);
226
238
  seats = still
227
239
  ? []
228
240
  : AGENTS.map((agent, index) => clearOfWords(corner(index, centre, radius), agent.size, words, { width, height }));
@@ -236,7 +248,7 @@ function HiveScene({ mode, column = "default", logo, picture, work, chrome, labe
236
248
  holder.style.left = `${seat.x}px`;
237
249
  holder.style.top = `${seat.y}px`;
238
250
  });
239
- drawComb(comb, width, height);
251
+ drawComb(comb, width, height, words);
240
252
  context = sizeCanvas(flow, width, height);
241
253
  };
242
254
  const observeLayout = (onLayout) => {
@@ -266,7 +278,16 @@ function HiveScene({ mode, column = "default", logo, picture, work, chrome, labe
266
278
  const others = seats.filter((other) => other !== null && other !== seat);
267
279
  const neighbour = (source + 1 + (Math.random() < 0.5 ? 0 : 4)) % AGENTS.length;
268
280
  const next = seats[neighbour] ?? pick(others);
269
- const people = workRef.current?.({ width, height });
281
+ const pictures = Array.from(picturesRef.current?.children ?? [], (element) => {
282
+ const drawn = element.getBoundingClientRect();
283
+ return {
284
+ left: drawn.left - bounds.left,
285
+ top: drawn.top - bounds.top,
286
+ right: drawn.right - bounds.left,
287
+ bottom: drawn.bottom - bounds.top,
288
+ };
289
+ });
290
+ const people = workRef.current?.(pictures);
270
291
  const sender = people ? pick(people.senders) : undefined;
271
292
  const receiver = people ? pick(people.receivers) : undefined;
272
293
  const roll = Math.random();
@@ -368,7 +389,7 @@ function HiveScene({ mode, column = "default", logo, picture, work, chrome, labe
368
389
  reduced.removeEventListener("change", play);
369
390
  };
370
391
  }, [mode, still, wordsColumn]);
371
- return (_jsxs("div", { ...props, className: cn("nc-hive dark", className), "data-mode": mode, "data-slot": "hive-scene", ref: sceneRef, ...(mode === "loading" ? { "aria-label": label, role: "status" } : {}), children: [chrome, _jsx("img", { alt: logo.label, className: "nc-hive-logo", "data-slot": "hive-logo", src: logo.src }), picture, _jsx("canvas", { "aria-hidden": "true", className: "nc-hive-comb", ref: combRef }), _jsx("canvas", { "aria-hidden": "true", className: "nc-hive-flow", ref: flowRef }), still
392
+ return (_jsxs("div", { ...props, className: cn("nc-hive dark", className), "data-mode": mode, "data-slot": "hive-scene", ref: sceneRef, ...(mode === "loading" ? { "aria-label": label, role: "status" } : {}), children: [chrome, _jsx("img", { alt: logo.label, className: "nc-hive-logo", "data-slot": "hive-logo", src: logo.src }), _jsx("div", { className: "nc-hive-pictures", ref: picturesRef, children: picture }), _jsx("canvas", { "aria-hidden": "true", className: "nc-hive-comb", ref: combRef }), _jsx("canvas", { "aria-hidden": "true", className: "nc-hive-flow", ref: flowRef }), still
372
393
  ? null
373
394
  : AGENTS.map((agent, index) => (_jsx("div", { "aria-hidden": "true", className: "nc-hive-agent", "data-slot": "hive-agent", "data-size": agent.size, ref: (holder) => {
374
395
  holderRefs.current[index] = holder;
@@ -1759,7 +1759,7 @@ export const USAGE = [
1759
1759
  summary: "Alveare's entry scene: its picture, its logo and six Agent orbs around the words.",
1760
1760
  when: "Alveare's entry screens, on its desktop and on Alveare Server: joining, loading, a failure.",
1761
1761
  instead: "Nadia's entry screens are `EntryScene`. A product page never stands on a scene.",
1762
- behaviour: "`join` puts the words in the hexagon's middle, `loading` draws the orbs in with no words, `still` shows no Agent and no work. Only the orbs and the particles move; reduced motion stops both. Black in every theme.",
1762
+ behaviour: "`join` puts the words in the hexagon's middle, `loading` draws the orbs in with no words, `still` shows no Agent and no work. Only the orbs and the particles move; reduced motion stops both. Black in every theme. The scene sets the width its words are drawn at on itself as `--hive-words-width`, so the app's picture keeps clear of them, and draws no honeycomb near them.",
1763
1763
  words: "The words are the screen's own: a title, a line, one action. The logo's label names Alveare.",
1764
1764
  access: 'The canvases are hidden; the logo\'s image is named by its label. In `loading` the scene is `role="status"` named by `label`; otherwise the words and their action are the reading.',
1765
1765
  },
@@ -636,6 +636,12 @@
636
636
  background: var(--nc-identity-ink);
637
637
  color: var(--nc-ink);
638
638
  color-scheme: dark;
639
+ --hive-column-width: min(20rem, 80vw);
640
+ --hive-words-width: var(--hive-column-width);
641
+ }
642
+
643
+ .nc-hive-pictures {
644
+ display: contents;
639
645
  }
640
646
 
641
647
  /*
@@ -718,7 +724,7 @@
718
724
  display: grid;
719
725
  justify-items: stretch;
720
726
  gap: var(--nc-md);
721
- width: min(20rem, 80vw);
727
+ width: var(--hive-column-width);
722
728
  text-align: center;
723
729
  text-wrap-style: balance;
724
730
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nadicodeai/ui",
3
- "version": "12.1.150",
3
+ "version": "12.1.151",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -84,7 +84,7 @@
84
84
  "@base-ui/react": "^1.9.0",
85
85
  "@iconify-icons/logos": "^2.0.3",
86
86
  "@iconify/react": "^6.0.2",
87
- "@nadicodeai/design-system": "12.1.150",
87
+ "@nadicodeai/design-system": "12.1.151",
88
88
  "@tanstack/react-table": "^9.3.1",
89
89
  "@vgpu/wgsl": "0.6.0",
90
90
  "class-variance-authority": "^0.7.1",