@neo-ui-kit/react 1.4.9 → 1.4.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -65,7 +65,7 @@ import "@neo-ui-kit/react/styles.css";
65
65
  To test repository changes before publishing, run `npm run package` from the repository root and install the resulting archive in a separate application:
66
66
 
67
67
  ```bash
68
- npm install /path/to/adui/release/neo-ui-kit-react-1.4.9.tgz
68
+ npm install /path/to/adui/release/neo-ui-kit-react-1.4.11.tgz
69
69
  ```
70
70
 
71
71
  Maintainers publish new versions from `Pro100Dimka/adui` using the `release.yml` GitHub Actions workflow, a matching `v<version>` tag, and the `npm-publication` environment. npm trusts its OIDC identity; no `NPM_TOKEN` is required. The workflow checks the project and packed consumer before publishing the tested archive. Published `1.0.0` cannot be overwritten: code and README changes in npm require a new package version. See the [repository release instructions](https://github.com/Pro100Dimka/adui#npm-пакет).
@@ -25,9 +25,19 @@ function renderBorders() {
25
25
  @group(0) @binding(3) var glow0: texture_2d<f32>;
26
26
  @group(0) @binding(4) var mask1: texture_2d<f32>;
27
27
  @group(0) @binding(5) var glow1: texture_2d<f32>;
28
+ @group(0) @binding(6) var<storage, read> contour: array<vec2f, 1024>;
29
+ // Cover the 25px mask stroke and its antialiasing, without shading the empty interior.
28
30
  @vertex fn vertex(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {
29
- let positions = array<vec2f, 3>(vec2f(-1,-1), vec2f(3,-1), vec2f(-1,3));
30
- return vec4f(positions[i], 0, 1);
31
+ let at = (i / 2) % 1024;
32
+ let before = normalize(contour[at] - contour[(at + 1023) % 1024]);
33
+ let after = normalize(contour[(at + 1) % 1024] - contour[at]);
34
+ let first = vec2f(before.y, -before.x);
35
+ let second = vec2f(after.y, -after.x);
36
+ let normal = normalize(first + second);
37
+ let miter = normal / max(dot(normal, second), 0.5);
38
+ let side = select(-16.0, 16.0, i % 2 == 0);
39
+ let p = (contour[at] + vec2f(16) + miter * side) / u.size.xy;
40
+ return vec4f(p.x * 2 - 1, 1 - p.y * 2, 0, 1);
31
41
  }
32
42
  fn spot(p: vec2f, origin: vec2f, texture: texture_2d<f32>) -> vec4f {
33
43
  let uv = (p - origin) / (u.size.w * 2);
@@ -63,7 +73,7 @@ function renderBorders() {
63
73
  layout: "auto",
64
74
  vertex: { module: shader, entryPoint: "vertex" },
65
75
  fragment: { module: shader, entryPoint: "fragment", targets: [{ format }] },
66
- primitive: { topology: "triangle-list" }
76
+ primitive: { topology: "triangle-strip" }
67
77
  });
68
78
  } catch (error) {
69
79
  device.destroy();
@@ -78,7 +88,7 @@ function renderBorders() {
78
88
  throw new Error(info.message || "Border GPU device lost");
79
89
  });
80
90
  });
81
- return (scene) => {
91
+ const painter = (scene) => {
82
92
  const context = scene.canvas.getContext("webgpu");
83
93
  context.configure({ device, format, alphaMode: "premultiplied" });
84
94
  const textures = scene.layers.flatMap((layer) => [layer.mask, layer.texture]).map((image) => {
@@ -91,6 +101,8 @@ function renderBorders() {
91
101
  return texture;
92
102
  });
93
103
  const buffer = device.createBuffer({ size: 64, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST });
104
+ const contour = device.createBuffer({ size: scene.points.byteLength, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST });
105
+ device.queue.writeBuffer(contour, 0, scene.points);
94
106
  const values = new Float32Array(16);
95
107
  values.set([
96
108
  scene.width,
@@ -105,7 +117,8 @@ function renderBorders() {
105
117
  const bindGroup = device.createBindGroup({ layout: pipeline.getBindGroupLayout(0), entries: [
106
118
  { binding: 0, resource: { buffer } },
107
119
  { binding: 1, resource: sampler },
108
- ...textures.map((texture, index) => ({ binding: index + 2, resource: texture.createView() }))
120
+ ...textures.map((texture, index) => ({ binding: index + 2, resource: texture.createView() })),
121
+ { binding: 6, resource: { buffer: contour } }
109
122
  ] });
110
123
  return {
111
124
  draw(current) {
@@ -132,19 +145,22 @@ function renderBorders() {
132
145
  const b = Math.min(current.canvas.height, Math.ceil(((values[9 + i * 2] + current.radius * 2) * current.dpr + 2) * sy));
133
146
  if (r > x && b > y) {
134
147
  pass.setScissorRect(x, y, r - x, b - y);
135
- pass.draw(3);
148
+ pass.draw(2050);
136
149
  }
137
150
  }
138
151
  pass.end();
139
- device.queue.submit([encoder.finish()]);
152
+ return encoder.finish();
140
153
  },
141
154
  dispose() {
142
155
  context.unconfigure();
143
156
  buffer.destroy();
157
+ contour.destroy();
144
158
  textures.forEach((texture) => texture.destroy());
145
159
  }
146
160
  };
147
161
  };
162
+ painter.submit = (commands) => device.queue.submit(commands);
163
+ return painter;
148
164
  }
149
165
  let gpu;
150
166
  const pending = [];
@@ -159,10 +175,7 @@ function renderBorders() {
159
175
  }
160
176
  };
161
177
  const draw = (scene) => {
162
- if (scene.gpu) {
163
- scene.gpu.draw(scene);
164
- return;
165
- }
178
+ if (scene.gpu) return scene.gpu.draw(scene);
166
179
  const { ctx, width, height, points, length, radius, dpr } = scene;
167
180
  const lights = scene.lights.map((light) => {
168
181
  const index = (light.phase + scene.elapsed * light.speed / length) % 1 * 1024;
@@ -222,12 +235,15 @@ function renderBorders() {
222
235
  function tick2(now) {
223
236
  frame = null;
224
237
  if (now - last2 >= 1e3 / fps - 0.5) {
238
+ const commands = [];
225
239
  for (const scene of scenes.values()) {
226
240
  if (!scene.visible) continue;
227
241
  if (scene.previous !== null) scene.elapsed += Math.min(0.1, Math.max(0, (now - scene.previous) / 1e3));
228
242
  scene.previous = now;
229
- draw(scene);
243
+ const command = draw(scene);
244
+ if (command) commands.push(command);
230
245
  }
246
+ if (commands.length) gpu.submit(commands);
231
247
  last2 = now;
232
248
  }
233
249
  schedule2();
@@ -262,7 +278,8 @@ function renderBorders() {
262
278
  }
263
279
  }
264
280
  scenes.set(data.id, next);
265
- draw(next);
281
+ const command = draw(next);
282
+ if (command) gpu.submit([command]);
266
283
  postMessage({ id: data.id, elapsed: next.elapsed, revision: data.revision });
267
284
  }
268
285
  schedule2();
@@ -2,7 +2,7 @@ import {
2
2
  themes,
3
3
  useBorder,
4
4
  usePauseOffscreen
5
- } from "./chunk-A4ZF2JYW.js";
5
+ } from "./chunk-6URATN43.js";
6
6
  import {
7
7
  assignRef,
8
8
  clamp,
@@ -768,7 +768,7 @@ function buttonView(p, name = "Button") {
768
768
  onPointerMove: trackLight,
769
769
  onPointerLeave: resetLight,
770
770
  children: [
771
- /* @__PURE__ */ jsx8("span", { className: "ad-button-fx", "aria-hidden": "true" }),
771
+ /* @__PURE__ */ jsx8("span", { className: "ad-button-fx", "aria-hidden": "true", children: /* @__PURE__ */ jsx8("span", { className: "ad-button-plasma" }) }),
772
772
  /* @__PURE__ */ jsx8("span", { className: "ad-button-orbit", "aria-hidden": "true" }),
773
773
  loading && /* @__PURE__ */ jsx8("span", { className: "ad-spinner", "aria-hidden": "true" }),
774
774
  icon && /* @__PURE__ */ jsx8(Icon, { name: icon }),
@@ -594,10 +594,18 @@
594
594
  overflow: hidden;
595
595
  pointer-events: none;
596
596
  }
597
- .ad-button-fx::before {
598
- content: "";
597
+ .ad-button-plasma {
599
598
  position: absolute;
600
599
  inset: -40% -10% -40% 30%;
600
+ opacity: 0;
601
+ transition: opacity 0.4s;
602
+ will-change: transform;
603
+ }
604
+ .ad-button-plasma::before {
605
+ /* Cache the filtered texture independently of its moving parent. */
606
+ content: "";
607
+ position: absolute;
608
+ inset: 0;
601
609
  background:
602
610
  radial-gradient(circle at 72% 30%, #fff 0 1.2%, transparent 2.6%),
603
611
  radial-gradient(circle at 86% 68%, var(--ad-secondary-100) 0 1.4%, transparent 3.2%),
@@ -611,9 +619,6 @@
611
619
  radial-gradient(ellipse at 80% 50%, rgb(from var(--ad-secondary) r g b / 0.44), transparent 65%);
612
620
  mask-image: linear-gradient(90deg, transparent, #000 40%);
613
621
  filter: saturate(1.35);
614
- opacity: 0;
615
- transition: opacity 0.4s;
616
- will-change: transform;
617
622
  }
618
623
  /* The breath: a faint light over the face that swells and settles. */
619
624
  .ad-button-fx::after {
@@ -654,8 +659,8 @@
654
659
  );
655
660
  will-change: transform;
656
661
  }
657
- :is(.ad-button, .ad-icon-button):is([data-ad-variant="primary"], [data-ad-variant="danger"]) > .ad-button-fx::before,
658
- .ad-toggle-button[aria-pressed="true"] > .ad-button-fx::before {
662
+ :is(.ad-button, .ad-icon-button):is([data-ad-variant="primary"], [data-ad-variant="danger"]) > .ad-button-fx > .ad-button-plasma,
663
+ .ad-toggle-button[aria-pressed="true"] > .ad-button-fx > .ad-button-plasma {
659
664
  opacity: 0.85;
660
665
  animation: ad-btn-plasma 7s ease-in-out infinite alternate;
661
666
  }
@@ -671,7 +676,7 @@
671
676
  .ad-toggle-button[aria-pressed="true"] > .ad-button-orbit::before {
672
677
  animation: ad-btn-orbit 4.5s linear infinite;
673
678
  }
674
- :is(.ad-button, .ad-icon-button, .ad-toggle-button):hover:not(:disabled) > .ad-button-fx::before {
679
+ :is(.ad-button, .ad-icon-button, .ad-toggle-button):hover:not(:disabled) > .ad-button-fx > .ad-button-plasma {
675
680
  opacity: 0.9;
676
681
  animation: ad-btn-plasma 7s ease-in-out infinite alternate;
677
682
  }
@@ -685,12 +690,14 @@
685
690
  display: none;
686
691
  }
687
692
  /* Icon-only buttons are small: the plasma centres on them instead of the right side. */
688
- .ad-icon-button > .ad-button-fx::before {
693
+ .ad-icon-button > .ad-button-fx > .ad-button-plasma {
689
694
  inset: -30%;
695
+ }
696
+ .ad-icon-button .ad-button-plasma::before {
690
697
  mask-image: radial-gradient(closest-side, #000 40%, transparent);
691
698
  }
692
699
  /* Ghost buttons stay subtle: only the comet, no plasma. */
693
- :is(.ad-button, .ad-icon-button)[data-ad-variant="ghost"] > .ad-button-fx::before {
700
+ :is(.ad-button, .ad-icon-button)[data-ad-variant="ghost"] > .ad-button-fx > .ad-button-plasma {
694
701
  display: none;
695
702
  }
696
703
  @keyframes ad-btn-plasma {
package/dist/core.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  useSmoothWheel,
12
12
  useTabShape,
13
13
  useTick
14
- } from "./chunks/chunk-A4ZF2JYW.js";
14
+ } from "./chunks/chunk-6URATN43.js";
15
15
  import {
16
16
  LocaleProvider,
17
17
  addMessages,
package/dist/forms.js CHANGED
@@ -4,8 +4,8 @@ import {
4
4
  defaultFieldRegistry,
5
5
  useForm,
6
6
  useFormContext
7
- } from "./chunks/chunk-2YGODRDJ.js";
8
- import "./chunks/chunk-A4ZF2JYW.js";
7
+ } from "./chunks/chunk-GHRYZ3BG.js";
8
+ import "./chunks/chunk-6URATN43.js";
9
9
  import "./chunks/chunk-BJSFN52W.js";
10
10
  import "./chunks/chunk-FCOU3ODR.js";
11
11
  export {
package/dist/index.js CHANGED
@@ -62,7 +62,7 @@ import {
62
62
  useSvgId,
63
63
  variantMaterial,
64
64
  vectorElement
65
- } from "./chunks/chunk-2YGODRDJ.js";
65
+ } from "./chunks/chunk-GHRYZ3BG.js";
66
66
  import {
67
67
  ThemeProvider,
68
68
  createNeonRenderer,
@@ -79,7 +79,7 @@ import {
79
79
  useTabShape,
80
80
  useThemePalette,
81
81
  useTick
82
- } from "./chunks/chunk-A4ZF2JYW.js";
82
+ } from "./chunks/chunk-6URATN43.js";
83
83
  import {
84
84
  LocaleProvider,
85
85
  addMessages,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neo-ui-kit/react",
3
- "version": "1.4.9",
3
+ "version": "1.4.11",
4
4
  "description": "NEO UI — React component library",
5
5
  "type": "module",
6
6
  "license": "MIT",