@liveblocks/react-ui 3.15.0-components1 → 3.15.0-thread2

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 (145) hide show
  1. package/dist/_private/index.cjs +7 -1
  2. package/dist/_private/index.cjs.map +1 -1
  3. package/dist/_private/index.d.cts +10 -4
  4. package/dist/_private/index.d.ts +10 -4
  5. package/dist/_private/index.js +3 -1
  6. package/dist/_private/index.js.map +1 -1
  7. package/dist/components/AiChat.cjs +10 -2
  8. package/dist/components/AiChat.cjs.map +1 -1
  9. package/dist/components/AiChat.js +10 -2
  10. package/dist/components/AiChat.js.map +1 -1
  11. package/dist/components/Comment.cjs +277 -232
  12. package/dist/components/Comment.cjs.map +1 -1
  13. package/dist/components/Comment.js +263 -237
  14. package/dist/components/Comment.js.map +1 -1
  15. package/dist/components/Composer.cjs +4 -2
  16. package/dist/components/Composer.cjs.map +1 -1
  17. package/dist/components/Composer.js +5 -3
  18. package/dist/components/Composer.js.map +1 -1
  19. package/dist/components/InboxNotification.cjs +6 -4
  20. package/dist/components/InboxNotification.cjs.map +1 -1
  21. package/dist/components/InboxNotification.js +7 -5
  22. package/dist/components/InboxNotification.js.map +1 -1
  23. package/dist/components/Thread.cjs +71 -45
  24. package/dist/components/Thread.cjs.map +1 -1
  25. package/dist/components/Thread.js +56 -49
  26. package/dist/components/Thread.js.map +1 -1
  27. package/dist/components/internal/AiComposer.cjs +2 -1
  28. package/dist/components/internal/AiComposer.cjs.map +1 -1
  29. package/dist/components/internal/AiComposer.js +2 -1
  30. package/dist/components/internal/AiComposer.js.map +1 -1
  31. package/dist/components/internal/CodeBlock.cjs +2 -1
  32. package/dist/components/internal/CodeBlock.cjs.map +1 -1
  33. package/dist/components/internal/CodeBlock.js +2 -1
  34. package/dist/components/internal/CodeBlock.js.map +1 -1
  35. package/dist/components/internal/Dropdown.cjs +28 -7
  36. package/dist/components/internal/Dropdown.cjs.map +1 -1
  37. package/dist/components/internal/Dropdown.js +7 -7
  38. package/dist/components/internal/Dropdown.js.map +1 -1
  39. package/dist/components/internal/EmojiPicker.cjs +27 -6
  40. package/dist/components/internal/EmojiPicker.cjs.map +1 -1
  41. package/dist/components/internal/EmojiPicker.js +6 -6
  42. package/dist/components/internal/EmojiPicker.js.map +1 -1
  43. package/dist/components/internal/List.cjs +2 -2
  44. package/dist/components/internal/List.cjs.map +1 -1
  45. package/dist/components/internal/List.js +2 -2
  46. package/dist/components/internal/List.js.map +1 -1
  47. package/dist/components/internal/Tooltip.cjs +28 -7
  48. package/dist/components/internal/Tooltip.cjs.map +1 -1
  49. package/dist/components/internal/Tooltip.js +7 -7
  50. package/dist/components/internal/Tooltip.js.map +1 -1
  51. package/dist/index.cjs +0 -12
  52. package/dist/index.cjs.map +1 -1
  53. package/dist/index.d.cts +197 -213
  54. package/dist/index.d.ts +197 -213
  55. package/dist/index.js +0 -6
  56. package/dist/index.js.map +1 -1
  57. package/dist/primitives/AiComposer/index.cjs +4 -5
  58. package/dist/primitives/AiComposer/index.cjs.map +1 -1
  59. package/dist/primitives/AiComposer/index.js +4 -5
  60. package/dist/primitives/AiComposer/index.js.map +1 -1
  61. package/dist/primitives/AiMessage/index.cjs +2 -2
  62. package/dist/primitives/AiMessage/index.cjs.map +1 -1
  63. package/dist/primitives/AiMessage/index.js +2 -2
  64. package/dist/primitives/AiMessage/index.js.map +1 -1
  65. package/dist/primitives/Collapsible/index.cjs +4 -4
  66. package/dist/primitives/Collapsible/index.cjs.map +1 -1
  67. package/dist/primitives/Collapsible/index.js +4 -4
  68. package/dist/primitives/Collapsible/index.js.map +1 -1
  69. package/dist/primitives/Comment/index.cjs +4 -4
  70. package/dist/primitives/Comment/index.cjs.map +1 -1
  71. package/dist/primitives/Comment/index.js +4 -4
  72. package/dist/primitives/Comment/index.js.map +1 -1
  73. package/dist/primitives/Composer/index.cjs +35 -23
  74. package/dist/primitives/Composer/index.cjs.map +1 -1
  75. package/dist/primitives/Composer/index.js +16 -23
  76. package/dist/primitives/Composer/index.js.map +1 -1
  77. package/dist/primitives/Duration.cjs +2 -2
  78. package/dist/primitives/Duration.cjs.map +1 -1
  79. package/dist/primitives/Duration.js +2 -2
  80. package/dist/primitives/Duration.js.map +1 -1
  81. package/dist/primitives/FileSize.cjs +2 -2
  82. package/dist/primitives/FileSize.cjs.map +1 -1
  83. package/dist/primitives/FileSize.js +2 -2
  84. package/dist/primitives/FileSize.js.map +1 -1
  85. package/dist/primitives/Markdown.cjs +2 -2
  86. package/dist/primitives/Markdown.cjs.map +1 -1
  87. package/dist/primitives/Markdown.js +2 -2
  88. package/dist/primitives/Markdown.js.map +1 -1
  89. package/dist/primitives/Timestamp.cjs +2 -2
  90. package/dist/primitives/Timestamp.cjs.map +1 -1
  91. package/dist/primitives/Timestamp.js +2 -2
  92. package/dist/primitives/Timestamp.js.map +1 -1
  93. package/dist/utils/Portal.cjs +2 -2
  94. package/dist/utils/Portal.cjs.map +1 -1
  95. package/dist/utils/Portal.js +2 -2
  96. package/dist/utils/Portal.js.map +1 -1
  97. package/dist/utils/use-stable-component.cjs +32 -0
  98. package/dist/utils/use-stable-component.cjs.map +1 -0
  99. package/dist/utils/use-stable-component.js +30 -0
  100. package/dist/utils/use-stable-component.js.map +1 -0
  101. package/dist/version.cjs +1 -1
  102. package/dist/version.cjs.map +1 -1
  103. package/dist/version.js +1 -1
  104. package/dist/version.js.map +1 -1
  105. package/package.json +10 -6
  106. package/src/styles/dark/index.css +1 -1
  107. package/src/styles/index.css +4 -252
  108. package/styles/dark/attributes.css +1 -1
  109. package/styles/dark/attributes.css.map +1 -1
  110. package/styles/dark/media-query.css +1 -1
  111. package/styles/dark/media-query.css.map +1 -1
  112. package/styles.css +1 -1
  113. package/styles.css.map +1 -1
  114. package/dist/components/AvatarStack.cjs +0 -115
  115. package/dist/components/AvatarStack.cjs.map +0 -1
  116. package/dist/components/AvatarStack.js +0 -113
  117. package/dist/components/AvatarStack.js.map +0 -1
  118. package/dist/components/CommentPin.cjs +0 -27
  119. package/dist/components/CommentPin.cjs.map +0 -1
  120. package/dist/components/CommentPin.js +0 -25
  121. package/dist/components/CommentPin.js.map +0 -1
  122. package/dist/components/Cursor.cjs +0 -40
  123. package/dist/components/Cursor.cjs.map +0 -1
  124. package/dist/components/Cursor.js +0 -38
  125. package/dist/components/Cursor.js.map +0 -1
  126. package/dist/components/Cursors.cjs +0 -252
  127. package/dist/components/Cursors.cjs.map +0 -1
  128. package/dist/components/Cursors.js +0 -250
  129. package/dist/components/Cursors.js.map +0 -1
  130. package/dist/components/FloatingComposer.cjs +0 -82
  131. package/dist/components/FloatingComposer.cjs.map +0 -1
  132. package/dist/components/FloatingComposer.js +0 -80
  133. package/dist/components/FloatingComposer.js.map +0 -1
  134. package/dist/components/FloatingThread.cjs +0 -82
  135. package/dist/components/FloatingThread.cjs.map +0 -1
  136. package/dist/components/FloatingThread.js +0 -80
  137. package/dist/components/FloatingThread.js.map +0 -1
  138. package/dist/utils/animation-loop.cjs +0 -44
  139. package/dist/utils/animation-loop.cjs.map +0 -1
  140. package/dist/utils/animation-loop.js +0 -42
  141. package/dist/utils/animation-loop.js.map +0 -1
  142. package/dist/utils/use-pre-resolve-user.cjs +0 -18
  143. package/dist/utils/use-pre-resolve-user.cjs.map +0 -1
  144. package/dist/utils/use-pre-resolve-user.js +0 -16
  145. package/dist/utils/use-pre-resolve-user.js.map +0 -1
@@ -1,113 +0,0 @@
1
- "use client";
2
- import { jsx, jsxs } from 'react/jsx-runtime';
3
- import { useOthers, useSelf } from '@liveblocks/react';
4
- import { forwardRef, useMemo } from 'react';
5
- import { FLOATING_ELEMENT_SIDE_OFFSET, FLOATING_ELEMENT_COLLISION_PADDING } from '../constants.js';
6
- import { useOverrides } from '../overrides.js';
7
- import { cn } from '../utils/cn.js';
8
- import { Avatar } from './internal/Avatar.js';
9
- import { TooltipProvider, Tooltip } from './internal/Tooltip.js';
10
- import { User } from './internal/User.js';
11
-
12
-
13
- const AvatarStack = forwardRef(
14
- ({
15
- userIds: additionalUserIds = [],
16
- max = 3,
17
- overrides,
18
- className,
19
- style,
20
- ...props
21
- }, forwardedRef) => {
22
- const $ = useOverrides(overrides);
23
- const otherIds = useOthers((others) => others.map((user) => user.id));
24
- const selfId = useSelf((self) => self.id);
25
- const userIds = useMemo(() => {
26
- const uniqueUserIds = /* @__PURE__ */ new Set([
27
- selfId,
28
- ...otherIds,
29
- ...additionalUserIds
30
- ]);
31
- return [...uniqueUserIds];
32
- }, [selfId, otherIds, additionalUserIds]);
33
- const maxAvatars = Math.max(1, Math.floor(max));
34
- const visibleUserIds = userIds.slice(0, maxAvatars);
35
- const hiddenUserIds = userIds.slice(visibleUserIds.length);
36
- const remainingUsersCount = hiddenUserIds.length;
37
- const visibleItemsCount = visibleUserIds.length + Number(remainingUsersCount > 0);
38
- if (userIds.length === 0) {
39
- return null;
40
- }
41
- return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(
42
- "div",
43
- {
44
- className: cn("lb-root lb-avatar-stack", className),
45
- dir: $.dir,
46
- style: {
47
- "--lb-avatar-stack-count": visibleItemsCount - 1,
48
- ...style
49
- },
50
- ...props,
51
- ref: forwardedRef,
52
- children: [
53
- visibleUserIds.map((userId, index) => {
54
- if (!userId) {
55
- return null;
56
- }
57
- return /* @__PURE__ */ jsx(
58
- Tooltip,
59
- {
60
- content: /* @__PURE__ */ jsx(User, { userId }),
61
- sideOffset: FLOATING_ELEMENT_SIDE_OFFSET,
62
- collisionPadding: FLOATING_ELEMENT_COLLISION_PADDING,
63
- side: "top",
64
- align: "center",
65
- children: /* @__PURE__ */ jsx(
66
- Avatar,
67
- {
68
- userId,
69
- className: "lb-avatar-stack-avatar",
70
- style: { "--lb-avatar-stack-index": index }
71
- }
72
- )
73
- },
74
- userId
75
- );
76
- }),
77
- remainingUsersCount > 0 ? /* @__PURE__ */ jsx(
78
- Tooltip,
79
- {
80
- content: /* @__PURE__ */ jsx("ul", { className: "lb-users-tooltip-list", children: hiddenUserIds.map(
81
- (userId) => userId ? /* @__PURE__ */ jsxs("li", { className: "lb-users-tooltip-list-item", children: [
82
- /* @__PURE__ */ jsx(Avatar, { userId }),
83
- /* @__PURE__ */ jsx(User, { userId })
84
- ] }, userId) : null
85
- ) }),
86
- sideOffset: FLOATING_ELEMENT_SIDE_OFFSET,
87
- collisionPadding: FLOATING_ELEMENT_COLLISION_PADDING,
88
- side: "top",
89
- align: "center",
90
- className: "lb-users-tooltip",
91
- children: /* @__PURE__ */ jsx(
92
- "div",
93
- {
94
- className: "lb-avatar lb-avatar-stack-avatar lb-avatar-stack-more",
95
- style: {
96
- "--lb-avatar-stack-index": visibleUserIds.length
97
- },
98
- children: /* @__PURE__ */ jsxs("span", { className: "lb-avatar-fallback", children: [
99
- "+",
100
- remainingUsersCount
101
- ] })
102
- }
103
- )
104
- }
105
- ) : null
106
- ]
107
- }
108
- ) });
109
- }
110
- );
111
-
112
- export { AvatarStack };
113
- //# sourceMappingURL=AvatarStack.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AvatarStack.js","sources":["../../src/components/AvatarStack.tsx"],"sourcesContent":["\"use client\";\n\nimport { useOthers, useSelf } from \"@liveblocks/react\";\nimport type { ComponentPropsWithoutRef, CSSProperties } from \"react\";\nimport { forwardRef, useMemo } from \"react\";\n\nimport {\n FLOATING_ELEMENT_COLLISION_PADDING,\n FLOATING_ELEMENT_SIDE_OFFSET,\n} from \"../constants\";\nimport type { GlobalOverrides } from \"../overrides\";\nimport { useOverrides } from \"../overrides\";\nimport { cn } from \"../utils/cn\";\nimport { Avatar } from \"./internal/Avatar\";\nimport { Tooltip, TooltipProvider } from \"./internal/Tooltip\";\nimport { User } from \"./internal/User\";\n\nexport interface AvatarStackProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * Optional additional user IDs to include in the stack.\n */\n userIds?: string[];\n\n /**\n * The maximum number of visible avatars.\n */\n max?: number;\n\n /**\n * Override the component's strings.\n */\n overrides?: Partial<GlobalOverrides>;\n}\n\n/**\n * Displays a stack of avatars for the users currently present in the room.\n */\nexport const AvatarStack = forwardRef<HTMLDivElement, AvatarStackProps>(\n (\n {\n userIds: additionalUserIds = [],\n max = 3,\n overrides,\n className,\n style,\n ...props\n },\n forwardedRef\n ) => {\n const $ = useOverrides(overrides);\n const otherIds = useOthers((others) => others.map((user) => user.id));\n const selfId = useSelf((self) => self.id);\n const userIds = useMemo(() => {\n const uniqueUserIds = new Set([\n selfId,\n ...otherIds,\n ...additionalUserIds,\n ]);\n\n return [...uniqueUserIds];\n }, [selfId, otherIds, additionalUserIds]);\n const maxAvatars = Math.max(1, Math.floor(max));\n const visibleUserIds = userIds.slice(0, maxAvatars);\n const hiddenUserIds = userIds.slice(visibleUserIds.length);\n const remainingUsersCount = hiddenUserIds.length;\n const visibleItemsCount =\n visibleUserIds.length + Number(remainingUsersCount > 0);\n\n if (userIds.length === 0) {\n return null;\n }\n\n return (\n <TooltipProvider>\n <div\n className={cn(\"lb-root lb-avatar-stack\", className)}\n dir={$.dir}\n style={\n {\n \"--lb-avatar-stack-count\": visibleItemsCount - 1,\n ...style,\n } as CSSProperties\n }\n {...props}\n ref={forwardedRef}\n >\n {visibleUserIds.map((userId, index) => {\n if (!userId) {\n return null;\n }\n\n return (\n <Tooltip\n key={userId}\n content={<User userId={userId} />}\n sideOffset={FLOATING_ELEMENT_SIDE_OFFSET}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n side=\"top\"\n align=\"center\"\n >\n <Avatar\n userId={userId}\n className=\"lb-avatar-stack-avatar\"\n style={{ \"--lb-avatar-stack-index\": index } as CSSProperties}\n />\n </Tooltip>\n );\n })}\n {remainingUsersCount > 0 ? (\n <Tooltip\n content={\n <ul className=\"lb-users-tooltip-list\">\n {hiddenUserIds.map((userId) =>\n userId ? (\n <li key={userId} className=\"lb-users-tooltip-list-item\">\n <Avatar userId={userId} />\n <User userId={userId} />\n </li>\n ) : null\n )}\n </ul>\n }\n sideOffset={FLOATING_ELEMENT_SIDE_OFFSET}\n collisionPadding={FLOATING_ELEMENT_COLLISION_PADDING}\n side=\"top\"\n align=\"center\"\n className=\"lb-users-tooltip\"\n >\n <div\n className=\"lb-avatar lb-avatar-stack-avatar lb-avatar-stack-more\"\n style={\n {\n \"--lb-avatar-stack-index\": visibleUserIds.length,\n } as CSSProperties\n }\n >\n <span className=\"lb-avatar-fallback\">\n +{remainingUsersCount}\n </span>\n </div>\n </Tooltip>\n ) : null}\n </div>\n </TooltipProvider>\n );\n }\n);\n"],"names":[],"mappings":";;;;;;;;;;;;AAqCO;AAAoB;AAEvB;AACgC;AACxB;AACN;AACA;AACA;AACG;AAIL;AACA;AACA;AACA;AACE;AAA8B;AAC5B;AACG;AACA;AAGL;AAAwB;AAE1B;AACA;AACA;AACA;AACA;AAGA;AACE;AAAO;AAGT;AAEI;AAAC;AAAA;AACmD;AAC3C;AAEL;AACiD;AAC5C;AACL;AAEE;AACC;AAEJ;AACC;AACE;AAAO;AAGT;AACE;AAAC;AAAA;AAEgC;AACnB;AACM;AACb;AACC;AAEN;AAAC;AAAA;AACC;AACU;AACgC;AAAA;AAC5C;AAAA;AAXK;AAYP;AAEH;AAEC;AAAC;AAAA;AAGoB;AAGT;AAAwB;AACF;AAEtB;AAER;AAEU;AACM;AACb;AACC;AACI;AAEV;AAAC;AAAA;AACW;AAER;AAC4C;AAC5C;AAGmC;AAAA;AACjC;AACJ;AAAA;AACF;AAAA;AAEA;AAAA;AAAA;AAER;AAGN;;"}
@@ -1,27 +0,0 @@
1
- "use client";
2
- 'use strict';
3
-
4
- var jsxRuntime = require('react/jsx-runtime');
5
- var react = require('react');
6
- var cn = require('../utils/cn.cjs');
7
- var Avatar = require('./internal/Avatar.cjs');
8
-
9
-
10
- const CommentPin = react.forwardRef(
11
- ({ corner = "bottom-left", userId, type = "button", className, ...props }, forwardedRef) => {
12
- return /* @__PURE__ */ jsxRuntime.jsx(
13
- "button",
14
- {
15
- className: cn.cn("lb-root lb-comment-pin", className),
16
- "data-corner": corner,
17
- type,
18
- ...props,
19
- ref: forwardedRef,
20
- children: userId ? /* @__PURE__ */ jsxRuntime.jsx(Avatar.Avatar, { className: "lb-comment-pin-avatar", userId }) : null
21
- }
22
- );
23
- }
24
- );
25
-
26
- exports.CommentPin = CommentPin;
27
- //# sourceMappingURL=CommentPin.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CommentPin.cjs","sources":["../../src/components/CommentPin.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { forwardRef } from \"react\";\n\nimport { cn } from \"../utils/cn\";\nimport { Avatar } from \"./internal/Avatar\";\n\nexport interface CommentPinProps extends ComponentPropsWithoutRef<\"button\"> {\n /**\n * The corner that points to the comment position.\n */\n corner?: \"top-left\" | \"top-right\" | \"bottom-right\" | \"bottom-left\";\n\n /**\n * The user ID to optionally display an avatar for.\n */\n userId?: string;\n}\n\n/**\n * Displays a comment pin that can be used as a trigger\n * for `FloatingComposer` and `FloatingThread`.\n */\nexport const CommentPin = forwardRef<HTMLButtonElement, CommentPinProps>(\n (\n { corner = \"bottom-left\", userId, type = \"button\", className, ...props },\n forwardedRef\n ) => {\n return (\n <button\n className={cn(\"lb-root lb-comment-pin\", className)}\n data-corner={corner}\n type={type}\n {...props}\n ref={forwardedRef}\n >\n {userId ? (\n <Avatar className=\"lb-comment-pin-avatar\" userId={userId} />\n ) : null}\n </button>\n );\n }\n);\n"],"names":[],"mappings":";;;;;;;;;AAwBO;AAAmB;AAKtB;AACE;AAAC;AAAA;AACkD;AACpC;AACb;AACI;AACC;AAID;AAAA;AACN;AAGN;;"}
@@ -1,25 +0,0 @@
1
- "use client";
2
- import { jsx } from 'react/jsx-runtime';
3
- import { forwardRef } from 'react';
4
- import { cn } from '../utils/cn.js';
5
- import { Avatar } from './internal/Avatar.js';
6
-
7
-
8
- const CommentPin = forwardRef(
9
- ({ corner = "bottom-left", userId, type = "button", className, ...props }, forwardedRef) => {
10
- return /* @__PURE__ */ jsx(
11
- "button",
12
- {
13
- className: cn("lb-root lb-comment-pin", className),
14
- "data-corner": corner,
15
- type,
16
- ...props,
17
- ref: forwardedRef,
18
- children: userId ? /* @__PURE__ */ jsx(Avatar, { className: "lb-comment-pin-avatar", userId }) : null
19
- }
20
- );
21
- }
22
- );
23
-
24
- export { CommentPin };
25
- //# sourceMappingURL=CommentPin.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CommentPin.js","sources":["../../src/components/CommentPin.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { forwardRef } from \"react\";\n\nimport { cn } from \"../utils/cn\";\nimport { Avatar } from \"./internal/Avatar\";\n\nexport interface CommentPinProps extends ComponentPropsWithoutRef<\"button\"> {\n /**\n * The corner that points to the comment position.\n */\n corner?: \"top-left\" | \"top-right\" | \"bottom-right\" | \"bottom-left\";\n\n /**\n * The user ID to optionally display an avatar for.\n */\n userId?: string;\n}\n\n/**\n * Displays a comment pin that can be used as a trigger\n * for `FloatingComposer` and `FloatingThread`.\n */\nexport const CommentPin = forwardRef<HTMLButtonElement, CommentPinProps>(\n (\n { corner = \"bottom-left\", userId, type = \"button\", className, ...props },\n forwardedRef\n ) => {\n return (\n <button\n className={cn(\"lb-root lb-comment-pin\", className)}\n data-corner={corner}\n type={type}\n {...props}\n ref={forwardedRef}\n >\n {userId ? (\n <Avatar className=\"lb-comment-pin-avatar\" userId={userId} />\n ) : null}\n </button>\n );\n }\n);\n"],"names":[],"mappings":";;;;;;;AAwBO;AAAmB;AAKtB;AACE;AAAC;AAAA;AACkD;AACpC;AACb;AACI;AACC;AAID;AAAA;AACN;AAGN;;"}
@@ -1,40 +0,0 @@
1
- 'use strict';
2
-
3
- var jsxRuntime = require('react/jsx-runtime');
4
- var react = require('react');
5
- var cn = require('../utils/cn.cjs');
6
-
7
- const Cursor = react.forwardRef(
8
- ({ className, label, color, style, ...props }, forwardedRef) => {
9
- return /* @__PURE__ */ jsxRuntime.jsxs(
10
- "div",
11
- {
12
- className: cn.cn("lb-root lb-cursor", className),
13
- style: { "--lb-cursor-color": color, ...style },
14
- ...props,
15
- ref: forwardedRef,
16
- children: [
17
- /* @__PURE__ */ jsxRuntime.jsx(
18
- "svg",
19
- {
20
- xmlns: "http://www.w3.org/2000/svg",
21
- viewBox: "0 0 32 32",
22
- className: "lb-cursor-pointer",
23
- children: /* @__PURE__ */ jsxRuntime.jsx(
24
- "path",
25
- {
26
- fill: "currentColor",
27
- d: "m.088 1.75 11.25 29.422c.409 1.07 1.908 1.113 2.377.067l5.223-11.653c.13-.288.36-.518.648-.648l11.653-5.223c1.046-.47 1.004-1.968-.067-2.377L1.75.088C.71-.31-.31.71.088 1.75Z"
28
- }
29
- )
30
- }
31
- ),
32
- label ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lb-cursor-bubble", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "lb-cursor-bubble-label", children: label }) }) : null
33
- ]
34
- }
35
- );
36
- }
37
- );
38
-
39
- exports.Cursor = Cursor;
40
- //# sourceMappingURL=Cursor.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Cursor.cjs","sources":["../../src/components/Cursor.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, CSSProperties, ReactNode } from \"react\";\nimport { forwardRef } from \"react\";\n\nimport { cn } from \"../utils/cn\";\n\nexport interface CursorProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * A floating label to display next to the cursor.\n */\n label?: ReactNode;\n\n /**\n * The color of the cursor.\n */\n color?: string;\n}\n\n/**\n * Displays a multiplayer cursor.\n */\nexport const Cursor = forwardRef<HTMLDivElement, CursorProps>(\n ({ className, label, color, style, ...props }, forwardedRef) => {\n return (\n <div\n className={cn(\"lb-root lb-cursor\", className)}\n style={{ \"--lb-cursor-color\": color, ...style } as CSSProperties}\n {...props}\n ref={forwardedRef}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 32 32\"\n className=\"lb-cursor-pointer\"\n >\n <path\n fill=\"currentColor\"\n d=\"m.088 1.75 11.25 29.422c.409 1.07 1.908 1.113 2.377.067l5.223-11.653c.13-.288.36-.518.648-.648l11.653-5.223c1.046-.47 1.004-1.968-.067-2.377L1.75.088C.71-.31-.31.71.088 1.75Z\"\n />\n </svg>\n {label ? (\n <div className=\"lb-cursor-bubble\">\n <span className=\"lb-cursor-bubble-label\">{label}</span>\n </div>\n ) : null}\n </div>\n );\n }\n);\n"],"names":["forwardRef","jsxs","cn","jsx"],"mappings":";;;;;;AAoBO,MAAM,MAAS,GAAAA,gBAAA;AAAA,EACpB,CAAC,EAAE,SAAW,EAAA,KAAA,EAAO,OAAO,KAAO,EAAA,GAAG,KAAM,EAAA,EAAG,YAAiB,KAAA;AAC9D,IACE,uBAAAC,eAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAWC,KAAG,CAAA,mBAAA,EAAqB,SAAS,CAAA;AAAA,QAC5C,KAAO,EAAA,EAAE,mBAAqB,EAAA,KAAA,EAAO,GAAG,KAAM,EAAA;AAAA,QAC7C,GAAG,KAAA;AAAA,QACJ,GAAK,EAAA,YAAA;AAAA,QAEL,QAAA,EAAA;AAAA,0BAAAC,cAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,KAAM,EAAA,4BAAA;AAAA,cACN,OAAQ,EAAA,WAAA;AAAA,cACR,SAAU,EAAA,mBAAA;AAAA,cAEV,QAAA,kBAAAA,cAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBACC,IAAK,EAAA,cAAA;AAAA,kBACL,CAAE,EAAA,gLAAA;AAAA,iBAAA;AAAA,eACJ;AAAA,aAAA;AAAA,WACF;AAAA,UACC,KAAA,mBACEA,cAAA,CAAA,KAAA,EAAA,EAAI,SAAU,EAAA,kBAAA,EACb,QAAC,kBAAAA,cAAA,CAAA,MAAA,EAAA,EAAK,SAAU,EAAA,wBAAA,EAA0B,QAAM,EAAA,KAAA,EAAA,CAAA,EAClD,CACE,GAAA,IAAA;AAAA,SAAA;AAAA,OAAA;AAAA,KACN,CAAA;AAAA,GAEJ;AACF;;;;"}
@@ -1,38 +0,0 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { forwardRef } from 'react';
3
- import { cn } from '../utils/cn.js';
4
-
5
- const Cursor = forwardRef(
6
- ({ className, label, color, style, ...props }, forwardedRef) => {
7
- return /* @__PURE__ */ jsxs(
8
- "div",
9
- {
10
- className: cn("lb-root lb-cursor", className),
11
- style: { "--lb-cursor-color": color, ...style },
12
- ...props,
13
- ref: forwardedRef,
14
- children: [
15
- /* @__PURE__ */ jsx(
16
- "svg",
17
- {
18
- xmlns: "http://www.w3.org/2000/svg",
19
- viewBox: "0 0 32 32",
20
- className: "lb-cursor-pointer",
21
- children: /* @__PURE__ */ jsx(
22
- "path",
23
- {
24
- fill: "currentColor",
25
- d: "m.088 1.75 11.25 29.422c.409 1.07 1.908 1.113 2.377.067l5.223-11.653c.13-.288.36-.518.648-.648l11.653-5.223c1.046-.47 1.004-1.968-.067-2.377L1.75.088C.71-.31-.31.71.088 1.75Z"
26
- }
27
- )
28
- }
29
- ),
30
- label ? /* @__PURE__ */ jsx("div", { className: "lb-cursor-bubble", children: /* @__PURE__ */ jsx("span", { className: "lb-cursor-bubble-label", children: label }) }) : null
31
- ]
32
- }
33
- );
34
- }
35
- );
36
-
37
- export { Cursor };
38
- //# sourceMappingURL=Cursor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Cursor.js","sources":["../../src/components/Cursor.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, CSSProperties, ReactNode } from \"react\";\nimport { forwardRef } from \"react\";\n\nimport { cn } from \"../utils/cn\";\n\nexport interface CursorProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * A floating label to display next to the cursor.\n */\n label?: ReactNode;\n\n /**\n * The color of the cursor.\n */\n color?: string;\n}\n\n/**\n * Displays a multiplayer cursor.\n */\nexport const Cursor = forwardRef<HTMLDivElement, CursorProps>(\n ({ className, label, color, style, ...props }, forwardedRef) => {\n return (\n <div\n className={cn(\"lb-root lb-cursor\", className)}\n style={{ \"--lb-cursor-color\": color, ...style } as CSSProperties}\n {...props}\n ref={forwardedRef}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 32 32\"\n className=\"lb-cursor-pointer\"\n >\n <path\n fill=\"currentColor\"\n d=\"m.088 1.75 11.25 29.422c.409 1.07 1.908 1.113 2.377.067l5.223-11.653c.13-.288.36-.518.648-.648l11.653-5.223c1.046-.47 1.004-1.968-.067-2.377L1.75.088C.71-.31-.31.71.088 1.75Z\"\n />\n </svg>\n {label ? (\n <div className=\"lb-cursor-bubble\">\n <span className=\"lb-cursor-bubble-label\">{label}</span>\n </div>\n ) : null}\n </div>\n );\n }\n);\n"],"names":[],"mappings":";;;;AAoBO,MAAM,MAAS,GAAA,UAAA;AAAA,EACpB,CAAC,EAAE,SAAW,EAAA,KAAA,EAAO,OAAO,KAAO,EAAA,GAAG,KAAM,EAAA,EAAG,YAAiB,KAAA;AAC9D,IACE,uBAAA,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,EAAG,CAAA,mBAAA,EAAqB,SAAS,CAAA;AAAA,QAC5C,KAAO,EAAA,EAAE,mBAAqB,EAAA,KAAA,EAAO,GAAG,KAAM,EAAA;AAAA,QAC7C,GAAG,KAAA;AAAA,QACJ,GAAK,EAAA,YAAA;AAAA,QAEL,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,KAAM,EAAA,4BAAA;AAAA,cACN,OAAQ,EAAA,WAAA;AAAA,cACR,SAAU,EAAA,mBAAA;AAAA,cAEV,QAAA,kBAAA,GAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBACC,IAAK,EAAA,cAAA;AAAA,kBACL,CAAE,EAAA,gLAAA;AAAA,iBAAA;AAAA,eACJ;AAAA,aAAA;AAAA,WACF;AAAA,UACC,KAAA,mBACE,GAAA,CAAA,KAAA,EAAA,EAAI,SAAU,EAAA,kBAAA,EACb,QAAC,kBAAA,GAAA,CAAA,MAAA,EAAA,EAAK,SAAU,EAAA,wBAAA,EAA0B,QAAM,EAAA,KAAA,EAAA,CAAA,EAClD,CACE,GAAA,IAAA;AAAA,SAAA;AAAA,OAAA;AAAA,KACN,CAAA;AAAA,GAEJ;AACF;;;;"}
@@ -1,252 +0,0 @@
1
- 'use strict';
2
-
3
- var jsxRuntime = require('react/jsx-runtime');
4
- var core = require('@liveblocks/core');
5
- var react = require('@liveblocks/react');
6
- var _private = require('@liveblocks/react/_private');
7
- var react$1 = require('react');
8
- var animationLoop = require('../utils/animation-loop.cjs');
9
- var cn = require('../utils/cn.cjs');
10
- var useWindowFocus = require('../utils/use-window-focus.cjs');
11
- var Cursor = require('./Cursor.cjs');
12
-
13
- const STIFFNESS = 320;
14
- const DAMPING = 32;
15
- const EPSILON = 0.01;
16
- const DEFAULT_PRESENCE_KEY = "$cursor";
17
- function $string(value) {
18
- return typeof value === "string" ? value : void 0;
19
- }
20
- function $coordinates(value) {
21
- if (core.isPlainObject(value) && typeof value.x === "number" && typeof value.y === "number") {
22
- return value;
23
- }
24
- return void 0;
25
- }
26
- const loop = animationLoop.makeAnimationLoop();
27
- function makeCoordinatesSpring() {
28
- const updates = core.makeEventSource();
29
- let value = null;
30
- let target = null;
31
- const velocity = { x: 0, y: 0 };
32
- const spring = {
33
- active: false,
34
- step(dt) {
35
- if (value === null || target === null) {
36
- spring.active = false;
37
- return;
38
- }
39
- const k = STIFFNESS;
40
- const d = DAMPING;
41
- const dx = value.x - target.x;
42
- const dy = value.y - target.y;
43
- velocity.x += (-k * dx - d * velocity.x) * dt;
44
- velocity.y += (-k * dy - d * velocity.y) * dt;
45
- const nx = value.x + velocity.x * dt;
46
- const ny = value.y + velocity.y * dt;
47
- if (nx !== value.x || ny !== value.y) {
48
- value.x = nx;
49
- value.y = ny;
50
- updates.notify(value);
51
- }
52
- if (Math.abs(velocity.x) < EPSILON && Math.abs(velocity.y) < EPSILON && Math.abs(target.x - value.x) < EPSILON && Math.abs(target.y - value.y) < EPSILON) {
53
- if (value.x !== target.x || value.y !== target.y) {
54
- value.x = target.x;
55
- value.y = target.y;
56
- updates.notify(value);
57
- }
58
- velocity.x = 0;
59
- velocity.y = 0;
60
- spring.active = false;
61
- }
62
- }
63
- };
64
- return {
65
- get() {
66
- return value;
67
- },
68
- set(point) {
69
- if (point === null) {
70
- value = null;
71
- target = null;
72
- velocity.x = 0;
73
- velocity.y = 0;
74
- spring.active = false;
75
- loop.remove(spring);
76
- updates.notify(null);
77
- return;
78
- }
79
- if (value === null) {
80
- value = { x: point.x, y: point.y };
81
- target = point;
82
- velocity.x = 0;
83
- velocity.y = 0;
84
- updates.notify(value);
85
- return;
86
- }
87
- target = point;
88
- if (!spring.active && (value.x !== target.x || value.y !== target.y)) {
89
- spring.active = true;
90
- loop.add(spring);
91
- }
92
- },
93
- subscribe: updates.subscribe,
94
- dispose() {
95
- spring.active = false;
96
- loop.remove(spring);
97
- updates.dispose();
98
- }
99
- };
100
- }
101
- function PresenceCursor({
102
- connectionId,
103
- presenceKey,
104
- sizeRef,
105
- sizeEvents
106
- }) {
107
- const room = react.useRoom();
108
- const cursorRef = react$1.useRef(null);
109
- const color = react.useOther(connectionId, (other) => $string(other.info?.color));
110
- const name = react.useOther(connectionId, (other) => $string(other.info?.name));
111
- _private.useLayoutEffect(() => {
112
- const spring = makeCoordinatesSpring();
113
- function render() {
114
- const element = cursorRef.current;
115
- const coordinates = spring.get();
116
- if (!element) {
117
- return;
118
- }
119
- if (coordinates === null) {
120
- element.style.transform = "translate3d(0, 0, 0)";
121
- element.style.display = "none";
122
- return;
123
- }
124
- if (sizeRef.current) {
125
- element.style.transform = `translate3d(${coordinates.x * sizeRef.current.width}px, ${coordinates.y * sizeRef.current.height}px, 0)`;
126
- }
127
- element.style.display = "";
128
- }
129
- const unsubscribeSpring = spring.subscribe(render);
130
- const unsubscribeSize = sizeEvents.subscribe(render);
131
- const unsubscribeOther = room.events.others.subscribe(({ others }) => {
132
- const other = others.find((other2) => other2.connectionId === connectionId);
133
- const cursor = $coordinates(other?.presence[presenceKey]);
134
- spring.set(cursor ?? null);
135
- });
136
- return () => {
137
- spring.dispose();
138
- unsubscribeSpring();
139
- unsubscribeSize();
140
- unsubscribeOther();
141
- };
142
- }, [room, connectionId, presenceKey, sizeRef, sizeEvents]);
143
- return /* @__PURE__ */ jsxRuntime.jsx(
144
- Cursor.Cursor,
145
- {
146
- color,
147
- label: name,
148
- ref: cursorRef,
149
- style: { display: "none" }
150
- }
151
- );
152
- }
153
- const Cursors = react$1.forwardRef(
154
- ({ className, children, presenceKey = DEFAULT_PRESENCE_KEY, ...props }, forwardedRef) => {
155
- const ref = react$1.useRef(null);
156
- const updateMyPresence = react.useUpdateMyPresence();
157
- const othersConnectionIds = react.useOthersConnectionIds();
158
- const sizeRef = react$1.useRef(null);
159
- const [sizeEvents] = react$1.useState(() => core.makeEventSource());
160
- const isWindowFocused = useWindowFocus.useWindowFocus();
161
- react$1.useEffect(() => {
162
- const element = ref.current;
163
- if (!element) {
164
- return;
165
- }
166
- function setSize(size) {
167
- sizeRef.current = size;
168
- sizeEvents.notify();
169
- }
170
- const observer = new ResizeObserver((entries) => {
171
- for (const entry of entries) {
172
- if (entry.target === element) {
173
- setSize({
174
- width: entry.contentRect.width,
175
- height: entry.contentRect.height
176
- });
177
- }
178
- }
179
- });
180
- setSize({
181
- width: element.clientWidth,
182
- height: element.clientHeight
183
- });
184
- observer.observe(element);
185
- return () => {
186
- observer.disconnect();
187
- };
188
- }, [sizeEvents]);
189
- const handlePointerMove = react$1.useCallback(
190
- (event) => {
191
- const element = ref.current;
192
- if (!element) {
193
- return;
194
- }
195
- const bounds = element.getBoundingClientRect();
196
- if (bounds.width === 0 || bounds.height === 0) {
197
- return;
198
- }
199
- updateMyPresence({
200
- [presenceKey]: {
201
- x: (event.clientX - bounds.left) / bounds.width,
202
- y: (event.clientY - bounds.top) / bounds.height
203
- }
204
- });
205
- },
206
- [updateMyPresence, presenceKey]
207
- );
208
- const handlePointerLeave = react$1.useCallback(() => {
209
- updateMyPresence({
210
- [presenceKey]: null
211
- });
212
- }, [updateMyPresence, presenceKey]);
213
- react$1.useEffect(() => {
214
- if (!isWindowFocused) {
215
- updateMyPresence({
216
- [presenceKey]: null
217
- });
218
- }
219
- }, [isWindowFocused, updateMyPresence, presenceKey]);
220
- react$1.useImperativeHandle(
221
- forwardedRef,
222
- () => ref.current,
223
- []
224
- );
225
- return /* @__PURE__ */ jsxRuntime.jsxs(
226
- "div",
227
- {
228
- className: cn.cn("lb-root lb-cursors", className),
229
- ...props,
230
- onPointerMove: handlePointerMove,
231
- onPointerLeave: handlePointerLeave,
232
- ref,
233
- children: [
234
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lb-cursors-container", children: othersConnectionIds.map((connectionId) => /* @__PURE__ */ jsxRuntime.jsx(
235
- PresenceCursor,
236
- {
237
- connectionId,
238
- presenceKey,
239
- sizeRef,
240
- sizeEvents
241
- },
242
- connectionId
243
- )) }),
244
- children
245
- ]
246
- }
247
- );
248
- }
249
- );
250
-
251
- exports.Cursors = Cursors;
252
- //# sourceMappingURL=Cursors.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Cursors.cjs","sources":["../../src/components/Cursors.tsx"],"sourcesContent":["import type { EventSource } from \"@liveblocks/core\";\nimport { isPlainObject, makeEventSource } from \"@liveblocks/core\";\nimport {\n useOther,\n useOthersConnectionIds,\n useRoom,\n useUpdateMyPresence,\n} from \"@liveblocks/react\";\nimport { useLayoutEffect } from \"@liveblocks/react/_private\";\nimport type {\n ComponentPropsWithoutRef,\n MutableRefObject,\n PointerEvent,\n} from \"react\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\n\nimport { type Animatable, makeAnimationLoop } from \"../utils/animation-loop\";\nimport { cn } from \"../utils/cn\";\nimport { useWindowFocus } from \"../utils/use-window-focus\";\nimport { Cursor } from \"./Cursor\";\n\nconst STIFFNESS = 320;\nconst DAMPING = 32;\nconst EPSILON = 0.01;\n\nconst DEFAULT_PRESENCE_KEY = \"$cursor\";\n\nexport interface CursorsProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * The key used to store the cursors in users' Presence.\n * This can be used to have multiple `Cursors` in a single room.\n */\n presenceKey?: string;\n}\n\ntype Coordinates = {\n x: number;\n y: number;\n};\n\ntype Size = {\n width: number;\n height: number;\n};\n\nfunction $string(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction $coordinates(value: unknown): Coordinates | undefined {\n if (\n isPlainObject(value) &&\n typeof value.x === \"number\" &&\n typeof value.y === \"number\"\n ) {\n return value as Coordinates;\n }\n\n return undefined;\n}\n\n// Use a shared animation loop for all (active) springs.\nconst loop = makeAnimationLoop();\n\nfunction makeCoordinatesSpring() {\n const updates = makeEventSource<Coordinates | null>();\n let value: Coordinates | null = null;\n let target: Coordinates | null = null;\n const velocity = { x: 0, y: 0 };\n\n const spring: Animatable = {\n active: false,\n step(dt: number) {\n if (value === null || target === null) {\n spring.active = false;\n return;\n }\n\n const k = STIFFNESS;\n const d = DAMPING;\n const dx = value.x - target.x;\n const dy = value.y - target.y;\n\n velocity.x += (-k * dx - d * velocity.x) * dt;\n velocity.y += (-k * dy - d * velocity.y) * dt;\n\n const nx = value.x + velocity.x * dt;\n const ny = value.y + velocity.y * dt;\n\n if (nx !== value.x || ny !== value.y) {\n value.x = nx;\n value.y = ny;\n updates.notify(value);\n }\n\n if (\n Math.abs(velocity.x) < EPSILON &&\n Math.abs(velocity.y) < EPSILON &&\n Math.abs(target.x - value.x) < EPSILON &&\n Math.abs(target.y - value.y) < EPSILON\n ) {\n if (value.x !== target.x || value.y !== target.y) {\n value.x = target.x;\n value.y = target.y;\n updates.notify(value);\n }\n\n velocity.x = 0;\n velocity.y = 0;\n spring.active = false;\n }\n },\n };\n\n return {\n get() {\n return value;\n },\n set(point: Coordinates | null) {\n if (point === null) {\n value = null;\n target = null;\n velocity.x = 0;\n velocity.y = 0;\n spring.active = false;\n loop.remove(spring);\n updates.notify(null);\n return;\n }\n\n if (value === null) {\n value = { x: point.x, y: point.y };\n target = point;\n velocity.x = 0;\n velocity.y = 0;\n updates.notify(value);\n return;\n }\n\n target = point;\n\n if (!spring.active && (value.x !== target.x || value.y !== target.y)) {\n spring.active = true;\n loop.add(spring);\n }\n },\n subscribe: updates.subscribe,\n dispose() {\n spring.active = false;\n loop.remove(spring);\n updates.dispose();\n },\n };\n}\n\nfunction PresenceCursor({\n connectionId,\n presenceKey,\n sizeRef,\n sizeEvents,\n}: {\n connectionId: number;\n presenceKey: string;\n sizeRef: MutableRefObject<Size | null>;\n sizeEvents: EventSource<void>;\n}) {\n const room = useRoom();\n const cursorRef = useRef<HTMLDivElement>(null);\n const color = useOther(connectionId, (other) => $string(other.info?.color));\n const name = useOther(connectionId, (other) => $string(other.info?.name));\n\n useLayoutEffect(() => {\n const spring = makeCoordinatesSpring();\n\n function render() {\n const element = cursorRef.current;\n const coordinates = spring.get();\n\n if (!element) {\n return;\n }\n\n if (coordinates === null) {\n element.style.transform = \"translate3d(0, 0, 0)\";\n element.style.display = \"none\";\n return;\n }\n\n if (sizeRef.current) {\n element.style.transform = `translate3d(${coordinates.x * sizeRef.current.width}px, ${coordinates.y * sizeRef.current.height}px, 0)`;\n }\n\n element.style.display = \"\";\n }\n\n const unsubscribeSpring = spring.subscribe(render);\n const unsubscribeSize = sizeEvents.subscribe(render);\n\n const unsubscribeOther = room.events.others.subscribe(({ others }) => {\n const other = others.find((other) => other.connectionId === connectionId);\n const cursor = $coordinates(other?.presence[presenceKey]);\n\n spring.set(cursor ?? null);\n });\n\n return () => {\n spring.dispose();\n unsubscribeSpring();\n unsubscribeSize();\n unsubscribeOther();\n };\n }, [room, connectionId, presenceKey, sizeRef, sizeEvents]);\n\n return (\n <Cursor\n color={color}\n label={name}\n ref={cursorRef}\n style={{ display: \"none\" }}\n />\n );\n}\n\n/**\n * Displays multiplayer cursors.\n */\nexport const Cursors = forwardRef<HTMLDivElement, CursorsProps>(\n (\n { className, children, presenceKey = DEFAULT_PRESENCE_KEY, ...props },\n forwardedRef\n ) => {\n const ref = useRef<HTMLDivElement>(null);\n const updateMyPresence = useUpdateMyPresence();\n const othersConnectionIds = useOthersConnectionIds();\n const sizeRef = useRef<Size | null>(null);\n const [sizeEvents] = useState(() => makeEventSource<void>());\n const isWindowFocused = useWindowFocus();\n\n useEffect(() => {\n const element = ref.current;\n\n if (!element) {\n return;\n }\n\n function setSize(size: Size) {\n sizeRef.current = size;\n sizeEvents.notify();\n }\n\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n if (entry.target === element) {\n setSize({\n width: entry.contentRect.width,\n height: entry.contentRect.height,\n });\n }\n }\n });\n\n setSize({\n width: element.clientWidth,\n height: element.clientHeight,\n });\n\n observer.observe(element);\n\n return () => {\n observer.disconnect();\n };\n }, [sizeEvents]);\n\n const handlePointerMove = useCallback(\n (event: PointerEvent) => {\n const element = ref.current;\n\n if (!element) {\n return;\n }\n\n const bounds = element.getBoundingClientRect();\n\n if (bounds.width === 0 || bounds.height === 0) {\n return;\n }\n\n updateMyPresence({\n [presenceKey]: {\n x: (event.clientX - bounds.left) / bounds.width,\n y: (event.clientY - bounds.top) / bounds.height,\n },\n });\n },\n [updateMyPresence, presenceKey]\n );\n\n const handlePointerLeave = useCallback(() => {\n updateMyPresence({\n [presenceKey]: null,\n });\n }, [updateMyPresence, presenceKey]);\n\n useEffect(() => {\n if (!isWindowFocused) {\n updateMyPresence({\n [presenceKey]: null,\n });\n }\n }, [isWindowFocused, updateMyPresence, presenceKey]);\n\n useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(\n forwardedRef,\n () => ref.current,\n []\n );\n\n return (\n <div\n className={cn(\"lb-root lb-cursors\", className)}\n {...props}\n onPointerMove={handlePointerMove}\n onPointerLeave={handlePointerLeave}\n ref={ref}\n >\n <div className=\"lb-cursors-container\">\n {othersConnectionIds.map((connectionId) => (\n <PresenceCursor\n key={connectionId}\n connectionId={connectionId}\n presenceKey={presenceKey}\n sizeRef={sizeRef}\n sizeEvents={sizeEvents}\n />\n ))}\n </div>\n\n {children}\n </div>\n );\n }\n);\n"],"names":["isPlainObject","makeAnimationLoop","makeEventSource","useRoom","useRef","useOther","useLayoutEffect","other","jsx","Cursor","forwardRef","useUpdateMyPresence","useOthersConnectionIds","useState","useWindowFocus","useEffect","useCallback","useImperativeHandle","jsxs","cn"],"mappings":"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"}