a2ui-react 0.4.0 → 0.5.0
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 +9 -29
- package/dist/index.js +11 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +12 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,32 +20,19 @@ yarn add a2ui-react
|
|
|
20
20
|
|
|
21
21
|
## Setup
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
Add the `@source` directive to your CSS so Tailwind scans the component classes:
|
|
23
|
+
Add the theme import and `@source` directive to your main CSS file:
|
|
26
24
|
|
|
27
25
|
```css
|
|
28
|
-
|
|
29
|
-
@
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
Without this, Tailwind v4 won't scan node_modules and components render unstyled.
|
|
33
|
-
|
|
34
|
-
### 2. Import Theme CSS
|
|
26
|
+
/* Import the a2ui-react theme (includes Tailwind and all theme variables) */
|
|
27
|
+
@import 'a2ui-react/theme.css';
|
|
35
28
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
```tsx
|
|
39
|
-
import 'a2ui-react/theme.css'
|
|
29
|
+
/* Tell Tailwind to scan the package for class usage */
|
|
30
|
+
@source "../node_modules/a2ui-react/dist";
|
|
40
31
|
```
|
|
41
32
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
> ```
|
|
46
|
-
> Then import `'./a2ui-theme.css'` instead.
|
|
47
|
-
|
|
48
|
-
Or if using your own Tailwind setup, ensure your CSS includes the [shadcn/ui theme variables](https://ui.shadcn.com/docs/theming).
|
|
33
|
+
Both lines are required:
|
|
34
|
+
- `theme.css` provides Tailwind, shadcn/ui theme variables, and alert color tokens
|
|
35
|
+
- `@source` ensures Tailwind includes the component classes (v4 doesn't scan node_modules by default)
|
|
49
36
|
|
|
50
37
|
## Quick Start
|
|
51
38
|
|
|
@@ -243,14 +230,7 @@ The `id` must be present both in the update wrapper AND inside the component obj
|
|
|
243
230
|
|
|
244
231
|
### a2ui-go Compatibility
|
|
245
232
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
| a2ui-go format | a2ui-react format |
|
|
249
|
-
|----------------|-------------------|
|
|
250
|
-
| `surfaceUpdate.components` | `surfaceUpdate.updates` |
|
|
251
|
-
| `{"id":"x", "Text":{...}}` | `{"id":"x", "component":{"type":"Text",...}}` |
|
|
252
|
-
| `text` field | `content` field |
|
|
253
|
-
| `usageHint` field | `style` field |
|
|
233
|
+
Works out of the box with [a2ui-go](https://github.com/burka/a2ui-go) - both use the A2UI v0.9 message format.
|
|
254
234
|
|
|
255
235
|
## License
|
|
256
236
|
|
package/dist/index.js
CHANGED
|
@@ -696,8 +696,13 @@ function A2UISurface({
|
|
|
696
696
|
const surface = useSurface(surfaceId);
|
|
697
697
|
const [loading, setLoading] = React7.useState(false);
|
|
698
698
|
const [error, setError] = React7.useState(null);
|
|
699
|
+
const processedMessagesRef = React7.useRef(null);
|
|
699
700
|
React7.useEffect(() => {
|
|
700
701
|
if (messages) {
|
|
702
|
+
if (messages === processedMessagesRef.current) {
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
processedMessagesRef.current = messages;
|
|
701
706
|
try {
|
|
702
707
|
for (const message of messages) {
|
|
703
708
|
processMessage(message, store);
|
|
@@ -4771,14 +4776,14 @@ var TextScrambleRenderer = {
|
|
|
4771
4776
|
type: "TextScramble",
|
|
4772
4777
|
render: ({ component }) => {
|
|
4773
4778
|
const [displayText, setDisplayText] = React7.useState(component.content);
|
|
4774
|
-
const
|
|
4779
|
+
const isAnimatingRef = React7.useRef(false);
|
|
4775
4780
|
const prefersReducedMotion = useReducedMotion();
|
|
4776
4781
|
const speed = component.speed || 30;
|
|
4777
4782
|
const characters = component.characters || defaultCharacters;
|
|
4778
4783
|
const trigger = component.trigger || "mount";
|
|
4779
|
-
const scramble = () => {
|
|
4780
|
-
if (prefersReducedMotion ||
|
|
4781
|
-
|
|
4784
|
+
const scramble = React7.useCallback(() => {
|
|
4785
|
+
if (prefersReducedMotion || isAnimatingRef.current) return;
|
|
4786
|
+
isAnimatingRef.current = true;
|
|
4782
4787
|
const target = component.content;
|
|
4783
4788
|
const length = target.length;
|
|
4784
4789
|
let iteration = 0;
|
|
@@ -4797,10 +4802,10 @@ var TextScrambleRenderer = {
|
|
|
4797
4802
|
if (iteration >= maxIterations) {
|
|
4798
4803
|
clearInterval(interval);
|
|
4799
4804
|
setDisplayText(target);
|
|
4800
|
-
|
|
4805
|
+
isAnimatingRef.current = false;
|
|
4801
4806
|
}
|
|
4802
4807
|
}, speed);
|
|
4803
|
-
};
|
|
4808
|
+
}, [component.content, characters, speed, prefersReducedMotion]);
|
|
4804
4809
|
React7.useEffect(() => {
|
|
4805
4810
|
if (trigger === "mount") {
|
|
4806
4811
|
scramble();
|