@weavix/tracker-components 0.1.6 → 0.1.7

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 (34) hide show
  1. package/README.md +4 -0
  2. package/build/cjs/components/UserAvatar/README.md +28 -0
  3. package/build/cjs/components/UserAvatar/UserAvatar.d.ts +8 -0
  4. package/build/cjs/components/UserAvatar/UserAvatar.js +82 -0
  5. package/build/cjs/components/UserAvatar/UserAvatar.js.map +1 -0
  6. package/build/cjs/components/UserAvatar/UserAvatarProvider.d.ts +9 -0
  7. package/build/cjs/components/UserAvatar/UserAvatarProvider.js +111 -0
  8. package/build/cjs/components/UserAvatar/UserAvatarProvider.js.map +1 -0
  9. package/build/cjs/components/UserAvatar/index.d.ts +5 -0
  10. package/build/cjs/components/UserAvatar/index.js +20 -0
  11. package/build/cjs/components/UserAvatar/index.js.map +1 -0
  12. package/build/cjs/components/UserAvatar/types.d.ts +5 -0
  13. package/build/cjs/components/UserAvatar/types.js +6 -0
  14. package/build/cjs/components/UserAvatar/types.js.map +1 -0
  15. package/build/cjs/index.d.ts +1 -0
  16. package/build/cjs/index.js +12 -0
  17. package/build/cjs/index.js.map +1 -1
  18. package/build/esm/components/UserAvatar/README.md +28 -0
  19. package/build/esm/components/UserAvatar/UserAvatar.d.ts +8 -0
  20. package/build/esm/components/UserAvatar/UserAvatar.js +74 -0
  21. package/build/esm/components/UserAvatar/UserAvatar.js.map +1 -0
  22. package/build/esm/components/UserAvatar/UserAvatarProvider.d.ts +9 -0
  23. package/build/esm/components/UserAvatar/UserAvatarProvider.js +103 -0
  24. package/build/esm/components/UserAvatar/UserAvatarProvider.js.map +1 -0
  25. package/build/esm/components/UserAvatar/index.d.ts +5 -0
  26. package/build/esm/components/UserAvatar/index.js +3 -0
  27. package/build/esm/components/UserAvatar/index.js.map +1 -0
  28. package/build/esm/components/UserAvatar/types.d.ts +5 -0
  29. package/build/esm/components/UserAvatar/types.js +2 -0
  30. package/build/esm/components/UserAvatar/types.js.map +1 -0
  31. package/build/esm/index.d.ts +1 -0
  32. package/build/esm/index.js +1 -0
  33. package/build/esm/index.js.map +1 -1
  34. package/package.json +1 -1
package/README.md CHANGED
@@ -43,6 +43,10 @@ pnpm add @weavix/tracker-components
43
43
  | [`GoalIcon`](#goalicon) | Colored icon for a goal entity. Color is deterministically derived from the goal ID. | [→ README](src/components/Icon/GoalIcon/README.md) |
44
44
  | [`KeyResultIcon`](#keyresulticon) | Icon for a key result entity, with a built-in tooltip. | [→ README](src/components/Icon/KeyResultIcon/README.md) |
45
45
 
46
+ ### User avatars
47
+
48
+ [`UserAvatar` and `UserAvatarProvider`](src/components/UserAvatar/README.md) load avatar URLs through the host SDK, batch sibling requests, and show initials when unavailable.
49
+
46
50
  ### Layout components
47
51
 
48
52
  | Component | Description | README |
@@ -0,0 +1,28 @@
1
+ # UserAvatar
2
+
3
+ Аватарка пользователя с инициалами при отсутствии URL, ошибке бриджа или загрузки картинки.
4
+ URL определяет сервис, в котором открыт плагин.
5
+
6
+ ```tsx
7
+ import {hostApi} from '@weavix/tracker-plugin-sdk';
8
+ import {UserAvatar, UserAvatarProvider} from '@weavix/tracker-components';
9
+
10
+ <UserAvatarProvider getUserAvatars={hostApi.getUserAvatars}>
11
+ <UserAvatar user={{uid: '123', login: 'alice'}} name="Alice Smith" size="m" />
12
+ <UserAvatar user={{login: 'bob'}} name="Bob Jones" />
13
+ </UserAvatarProvider>;
14
+ ```
15
+
16
+ Используйте один провайдер для списка: запросы одного такта объединяются в пакеты до 100
17
+ уникальных пользователей; повторы одной пары `uid`/`login` в пакете используют общий ответ. `getUserAvatars` должен возвращать массив абсолютных HTTP(S) URL или `null`
18
+ той же длины и в том же порядке. Передавайте стабильную функцию; для другого сервиса можно
19
+ подключить совместимый метод его SDK. Компоненты не зависят от конкретного пакета SDK.
20
+
21
+ `user` содержит `uid`, `login` или оба поля (непустые строки до 1024 символов).
22
+ Некорректные идентификаторы дают инициалы и не попадают в запрос соседних аватарок. `name` задаёт инициалы и доступное имя.
23
+ Поддерживаются `size`, `className`, `title`, `qa` из Gravity UI Avatar.
24
+ Без провайдера или идентификаторов отображаются инициалы без запроса. Результаты не кешируются;
25
+ поздние ответы для предыдущего пользователя игнорируются.
26
+
27
+ Хост должен поддерживать `userAvatars.get` и разрешать домены картинок в CSP `img-src`.
28
+ Для старого хоста ошибка метода приводит к инициалам.
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { type AvatarProps } from '@gravity-ui/uikit';
3
+ import type { UserAvatarUser } from './types';
4
+ export type UserAvatarProps = Pick<AvatarProps, 'size' | 'className' | 'title' | 'qa'> & {
5
+ user: UserAvatarUser;
6
+ name: string;
7
+ };
8
+ export declare function UserAvatar({ user: { uid, login }, name, ...props }: UserAvatarProps): React.JSX.Element;
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.UserAvatar = UserAvatar;
7
+ var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
10
+ require("core-js/modules/es.function.name.js");
11
+ var _react = _interopRequireWildcard(require("react"));
12
+ var _uikit = require("@gravity-ui/uikit");
13
+ var _UserAvatarProvider = require("./UserAvatarProvider");
14
+ var _jsxRuntime = require("react/jsx-runtime");
15
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
16
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
17
+ var _excluded = ["url", "name"],
18
+ _excluded2 = ["user", "name"];
19
+ function AvatarImage(_ref) {
20
+ var url = _ref.url,
21
+ name = _ref.name,
22
+ props = (0, _objectWithoutProperties2.default)(_ref, _excluded);
23
+ var _useState = (0, _react.useState)(false),
24
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
25
+ failed = _useState2[0],
26
+ setFailed = _useState2[1];
27
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
28
+ style: {
29
+ display: 'contents'
30
+ },
31
+ onErrorCapture: function onErrorCapture() {
32
+ return setFailed(true);
33
+ },
34
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_uikit.Avatar, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, props), {}, {
35
+ "aria-label": name
36
+ }, url && !failed ? {
37
+ imgUrl: url,
38
+ alt: name
39
+ } : {
40
+ text: name || '?'
41
+ }))
42
+ });
43
+ }
44
+ function UserAvatar(_ref2) {
45
+ var _result$url;
46
+ var _ref2$user = _ref2.user,
47
+ uid = _ref2$user.uid,
48
+ login = _ref2$user.login,
49
+ name = _ref2.name,
50
+ props = (0, _objectWithoutProperties2.default)(_ref2, _excluded2);
51
+ var load = (0, _react.useContext)(_UserAvatarProvider.UserAvatarContext);
52
+ var _useState3 = (0, _react.useState)(),
53
+ _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
54
+ result = _useState4[0],
55
+ setResult = _useState4[1];
56
+ (0, _react.useEffect)(function () {
57
+ var cancelled = false;
58
+ if (load && (uid || login)) {
59
+ load((0, _objectSpread2.default)((0, _objectSpread2.default)({}, uid === undefined ? {} : {
60
+ uid: uid
61
+ }), login === undefined ? {} : {
62
+ login: login
63
+ })).then(function (url) {
64
+ if (!cancelled) setResult({
65
+ uid: uid,
66
+ login: login,
67
+ load: load,
68
+ url: url
69
+ });
70
+ });
71
+ }
72
+ return function () {
73
+ cancelled = true;
74
+ };
75
+ }, [uid, login, load]);
76
+ var url = (result === null || result === void 0 ? void 0 : result.uid) === uid && (result === null || result === void 0 ? void 0 : result.login) === login && (result === null || result === void 0 ? void 0 : result.load) === load ? (_result$url = result === null || result === void 0 ? void 0 : result.url) !== null && _result$url !== void 0 ? _result$url : null : null;
77
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(AvatarImage, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, props), {}, {
78
+ name: name,
79
+ url: url
80
+ }), url);
81
+ }
82
+ // #sourceMappingURL=UserAvatar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_react","_interopRequireWildcard","require","_uikit","_UserAvatarProvider","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_interopRequireDefault","AvatarImage","_ref","url","name","props","_objectWithoutProperties","_excluded","_useState","useState","_useState2","_slicedToArray","failed","setFailed","_jsx","style","display","onErrorCapture","children","Avatar","_objectSpread","imgUrl","alt","text","UserAvatar","_ref2","_result$url","_ref2$user","user","uid","login","_excluded2","load","useContext","UserAvatarContext","_useState3","_useState4","result","setResult","useEffect","cancelled","undefined","then"],"sources":["UserAvatar.tsx"],"sourcesContent":["import React, {useContext, useEffect, useState} from 'react';\n\nimport {Avatar, type AvatarProps} from '@gravity-ui/uikit';\n\nimport {UserAvatarContext} from './UserAvatarProvider';\nimport type {UserAvatarUser} from './types';\n\nexport type UserAvatarProps = Pick<AvatarProps, 'size' | 'className' | 'title' | 'qa'> & {\n user: UserAvatarUser;\n name: string;\n};\n\nfunction AvatarImage({url, name, ...props}: Omit<UserAvatarProps, 'user'> & {url: string | null}) {\n const [failed, setFailed] = useState(false);\n return (\n <span style={{display: 'contents'}} onErrorCapture={() => setFailed(true)}>\n <Avatar\n {...props}\n aria-label={name}\n {...(url && !failed ? {imgUrl: url, alt: name} : {text: name || '?'})}\n />\n </span>\n );\n}\n\nexport function UserAvatar({user: {uid, login}, name, ...props}: UserAvatarProps) {\n const load = useContext(UserAvatarContext);\n const [result, setResult] = useState<{\n uid?: string;\n login?: string;\n load: typeof load;\n url: string | null;\n }>();\n\n useEffect(() => {\n let cancelled = false;\n if (load && (uid || login)) {\n load({\n ...(uid === undefined ? {} : {uid}),\n ...(login === undefined ? {} : {login}),\n }).then((url) => {\n if (!cancelled) setResult({uid, login, load, url});\n });\n }\n return () => {\n cancelled = true;\n };\n }, [uid, login, load]);\n\n const url =\n result?.uid === uid && result?.login === login && result?.load === load\n ? (result?.url ?? null)\n : null;\n\n return <AvatarImage key={url} {...props} name={name} url={url} />;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import type { GetUserAvatars, UserAvatarUser } from './types';
3
+ type LoadAvatar = (user: UserAvatarUser) => Promise<string | null>;
4
+ export declare const UserAvatarContext: React.Context<LoadAvatar | undefined>;
5
+ export type UserAvatarProviderProps = React.PropsWithChildren<{
6
+ getUserAvatars: GetUserAvatars;
7
+ }>;
8
+ export declare function UserAvatarProvider({ getUserAvatars, children }: UserAvatarProviderProps): React.JSX.Element;
9
+ export {};
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.UserAvatarContext = void 0;
7
+ exports.UserAvatarProvider = UserAvatarProvider;
8
+ require("core-js/modules/es.error.cause.js");
9
+ require("core-js/modules/es.error.to-string.js");
10
+ require("core-js/modules/es.array.every.js");
11
+ require("core-js/modules/es.array.for-each.js");
12
+ require("core-js/modules/es.array.from.js");
13
+ require("core-js/modules/es.array.is-array.js");
14
+ require("core-js/modules/es.array.iterator.js");
15
+ require("core-js/modules/es.array.map.js");
16
+ require("core-js/modules/es.array.push.js");
17
+ require("core-js/modules/es.array.slice.js");
18
+ require("core-js/modules/es.date.to-json.js");
19
+ require("core-js/modules/es.iterator.constructor.js");
20
+ require("core-js/modules/es.iterator.for-each.js");
21
+ require("core-js/modules/es.iterator.map.js");
22
+ require("core-js/modules/es.json.stringify.js");
23
+ require("core-js/modules/es.map.js");
24
+ require("core-js/modules/es.object.to-string.js");
25
+ require("core-js/modules/es.promise.js");
26
+ require("core-js/modules/es.regexp.exec.js");
27
+ require("core-js/modules/es.regexp.test.js");
28
+ require("core-js/modules/es.string.iterator.js");
29
+ require("core-js/modules/es.string.trim.js");
30
+ require("core-js/modules/esnext.map.get-or-insert.js");
31
+ require("core-js/modules/esnext.map.get-or-insert-computed.js");
32
+ require("core-js/modules/web.dom-collections.for-each.js");
33
+ require("core-js/modules/web.dom-collections.iterator.js");
34
+ require("core-js/modules/web.queue-microtask.js");
35
+ var _react = _interopRequireWildcard(require("react"));
36
+ var _jsxRuntime = require("react/jsx-runtime");
37
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
38
+ var UserAvatarContext = exports.UserAvatarContext = /*#__PURE__*/(0, _react.createContext)(undefined);
39
+ function isValidUser(_ref) {
40
+ var uid = _ref.uid,
41
+ login = _ref.login;
42
+ return Boolean(uid || login) && [uid, login].every(function (value) {
43
+ return value === undefined || typeof value === 'string' && value.length <= 1024 && Boolean(value.trim());
44
+ });
45
+ }
46
+ function createLoader(getUserAvatars) {
47
+ var pending = new Map();
48
+ var flush = function flush() {
49
+ var requests = Array.from(pending.values());
50
+ pending = new Map();
51
+ var _loop = function _loop() {
52
+ var batch = requests.slice(offset, offset + 100);
53
+ Promise.resolve().then(function () {
54
+ return getUserAvatars(batch.map(function (_ref2) {
55
+ var user = _ref2.user;
56
+ return user;
57
+ }));
58
+ }).then(function (urls) {
59
+ if (!Array.isArray(urls) || urls.length !== batch.length) {
60
+ throw new Error('Avatar result must match the requested users');
61
+ }
62
+ batch.forEach(function (_ref3, index) {
63
+ var resolve = _ref3.resolve;
64
+ var url = urls[index];
65
+ var avatar = typeof url === 'string' && /^https?:\/\//i.test(url) ? url : null;
66
+ resolve.forEach(function (callback) {
67
+ return callback(avatar);
68
+ });
69
+ });
70
+ })["catch"](function () {
71
+ return batch.forEach(function (_ref4) {
72
+ var resolve = _ref4.resolve;
73
+ return resolve.forEach(function (callback) {
74
+ return callback(null);
75
+ });
76
+ });
77
+ });
78
+ };
79
+ for (var offset = 0; offset < requests.length; offset += 100) {
80
+ _loop();
81
+ }
82
+ };
83
+ return function (user) {
84
+ if (!isValidUser(user)) return Promise.resolve(null);
85
+ return new Promise(function (resolve) {
86
+ var key = JSON.stringify([user.uid, user.login]);
87
+ var request = pending.get(key);
88
+ if (request) {
89
+ request.resolve.push(resolve);
90
+ } else {
91
+ pending.set(key, {
92
+ user: user,
93
+ resolve: [resolve]
94
+ });
95
+ if (pending.size === 1) queueMicrotask(flush);
96
+ }
97
+ });
98
+ };
99
+ }
100
+ function UserAvatarProvider(_ref5) {
101
+ var getUserAvatars = _ref5.getUserAvatars,
102
+ children = _ref5.children;
103
+ var load = (0, _react.useMemo)(function () {
104
+ return createLoader(getUserAvatars);
105
+ }, [getUserAvatars]);
106
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(UserAvatarContext.Provider, {
107
+ value: load,
108
+ children: children
109
+ });
110
+ }
111
+ // #sourceMappingURL=UserAvatarProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_react","_interopRequireWildcard","require","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","UserAvatarContext","exports","createContext","undefined","isValidUser","_ref","uid","login","Boolean","every","value","length","trim","createLoader","getUserAvatars","pending","Map","flush","requests","Array","from","values","_loop","batch","slice","offset","Promise","resolve","then","map","_ref2","user","urls","isArray","Error","forEach","_ref3","index","url","avatar","test","callback","_ref4","key","JSON","stringify","request","push","size","queueMicrotask","UserAvatarProvider","_ref5","children","load","useMemo","_jsx","Provider"],"sources":["UserAvatarProvider.tsx"],"sourcesContent":["import React, {createContext, useMemo} from 'react';\n\nimport type {GetUserAvatars, UserAvatarUser} from './types';\n\ntype LoadAvatar = (user: UserAvatarUser) => Promise<string | null>;\ntype PendingAvatar = {user: UserAvatarUser; resolve: Array<(url: string | null) => void>};\n\nexport const UserAvatarContext = createContext<LoadAvatar | undefined>(undefined);\n\nfunction isValidUser({uid, login}: UserAvatarUser): boolean {\n return (\n Boolean(uid || login) &&\n [uid, login].every(\n (value) =>\n value === undefined ||\n (typeof value === 'string' && value.length <= 1024 && Boolean(value.trim())),\n )\n );\n}\n\nfunction createLoader(getUserAvatars: GetUserAvatars): LoadAvatar {\n let pending = new Map<string, PendingAvatar>();\n\n const flush = () => {\n const requests = Array.from(pending.values());\n pending = new Map();\n for (let offset = 0; offset < requests.length; offset += 100) {\n const batch = requests.slice(offset, offset + 100);\n Promise.resolve()\n .then(() => getUserAvatars(batch.map(({user}) => user)))\n .then((urls) => {\n if (!Array.isArray(urls) || urls.length !== batch.length) {\n throw new Error('Avatar result must match the requested users');\n }\n batch.forEach(({resolve}, index) => {\n const url = urls[index];\n const avatar =\n typeof url === 'string' && /^https?:\\/\\//i.test(url) ? url : null;\n resolve.forEach((callback) => callback(avatar));\n });\n })\n .catch(() =>\n batch.forEach(({resolve}) => resolve.forEach((callback) => callback(null))),\n );\n }\n };\n\n return (user) => {\n if (!isValidUser(user)) return Promise.resolve(null);\n return new Promise((resolve) => {\n const key = JSON.stringify([user.uid, user.login]);\n const request = pending.get(key);\n if (request) {\n request.resolve.push(resolve);\n } else {\n pending.set(key, {user, resolve: [resolve]});\n if (pending.size === 1) queueMicrotask(flush);\n }\n });\n };\n}\n\nexport type UserAvatarProviderProps = React.PropsWithChildren<{\n getUserAvatars: GetUserAvatars;\n}>;\n\nexport function UserAvatarProvider({getUserAvatars, children}: UserAvatarProviderProps) {\n const load = useMemo(() => createLoader(getUserAvatars), [getUserAvatars]);\n return <UserAvatarContext.Provider value={load}>{children}</UserAvatarContext.Provider>;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,5 @@
1
+ export { UserAvatar } from './UserAvatar';
2
+ export type { UserAvatarProps } from './UserAvatar';
3
+ export { UserAvatarProvider } from './UserAvatarProvider';
4
+ export type { UserAvatarProviderProps } from './UserAvatarProvider';
5
+ export type { GetUserAvatars, UserAvatarUser } from './types';
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "UserAvatar", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _UserAvatar.UserAvatar;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "UserAvatarProvider", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _UserAvatarProvider.UserAvatarProvider;
16
+ }
17
+ });
18
+ var _UserAvatar = require("./UserAvatar");
19
+ var _UserAvatarProvider = require("./UserAvatarProvider");
20
+ // #sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_UserAvatar","require","_UserAvatarProvider"],"sources":["index.ts"],"sourcesContent":["export {UserAvatar} from './UserAvatar';\nexport type {UserAvatarProps} from './UserAvatar';\nexport {UserAvatarProvider} from './UserAvatarProvider';\nexport type {UserAvatarProviderProps} from './UserAvatarProvider';\nexport type {GetUserAvatars, UserAvatarUser} from './types';\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA,IAAAA,WAAA,GAAAC,OAAA;AAEA,IAAAC,mBAAA,GAAAD,OAAA","ignoreList":[]}
@@ -0,0 +1,5 @@
1
+ export type UserAvatarUser = {
2
+ uid?: string;
3
+ login?: string;
4
+ };
5
+ export type GetUserAvatars = (users: UserAvatarUser[]) => Promise<Array<string | null>>;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ // #sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["export type UserAvatarUser = {uid?: string; login?: string};\n\nexport type GetUserAvatars = (users: UserAvatarUser[]) => Promise<Array<string | null>>;\n"],"mappings":"","ignoreList":[]}
@@ -5,3 +5,4 @@ export * from './components/QueueSelect';
5
5
  export * from './components/TrackerDisclosure';
6
6
  export { block, cn, NAMESPACE } from './components/cn';
7
7
  export type { CnBlock } from './components/cn';
8
+ export * from './components/UserAvatar';
@@ -87,4 +87,16 @@ Object.keys(_TrackerDisclosure).forEach(function (key) {
87
87
  });
88
88
  });
89
89
  var _cn = require("./components/cn");
90
+ var _UserAvatar = require("./components/UserAvatar");
91
+ Object.keys(_UserAvatar).forEach(function (key) {
92
+ if (key === "default" || key === "__esModule") return;
93
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
94
+ if (key in exports && exports[key] === _UserAvatar[key]) return;
95
+ Object.defineProperty(exports, key, {
96
+ enumerable: true,
97
+ get: function () {
98
+ return _UserAvatar[key];
99
+ }
100
+ });
101
+ });
90
102
  // #sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_Icon","require","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_MetaEntitiesSelect","_PluginFieldsSelect","_QueueSelect","_TrackerDisclosure","_cn"],"sources":["index.ts"],"sourcesContent":["export * from './components/Icon';\nexport * from './components/MetaEntitiesSelect';\nexport * from './components/PluginFieldsSelect';\nexport * from './components/QueueSelect';\nexport * from './components/TrackerDisclosure';\nexport {block, cn, NAMESPACE} from './components/cn';\nexport type {CnBlock} from './components/cn';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,KAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAH,KAAA,EAAAI,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAL,KAAA,CAAAK,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAb,KAAA,CAAAK,GAAA;IAAA;EAAA;AAAA;AACA,IAAAS,mBAAA,GAAAb,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAW,mBAAA,EAAAV,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAS,mBAAA,CAAAT,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAC,mBAAA,CAAAT,GAAA;IAAA;EAAA;AAAA;AACA,IAAAU,mBAAA,GAAAd,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAY,mBAAA,EAAAX,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAU,mBAAA,CAAAV,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAE,mBAAA,CAAAV,GAAA;IAAA;EAAA;AAAA;AACA,IAAAW,YAAA,GAAAf,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAa,YAAA,EAAAZ,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAW,YAAA,CAAAX,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAG,YAAA,CAAAX,GAAA;IAAA;EAAA;AAAA;AACA,IAAAY,kBAAA,GAAAhB,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAc,kBAAA,EAAAb,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAY,kBAAA,CAAAZ,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAI,kBAAA,CAAAZ,GAAA;IAAA;EAAA;AAAA;AACA,IAAAa,GAAA,GAAAjB,OAAA","ignoreList":[]}
1
+ {"version":3,"names":["_Icon","require","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_MetaEntitiesSelect","_PluginFieldsSelect","_QueueSelect","_TrackerDisclosure","_cn","_UserAvatar"],"sources":["index.ts"],"sourcesContent":["export * from './components/Icon';\nexport * from './components/MetaEntitiesSelect';\nexport * from './components/PluginFieldsSelect';\nexport * from './components/QueueSelect';\nexport * from './components/TrackerDisclosure';\nexport {block, cn, NAMESPACE} from './components/cn';\nexport type {CnBlock} from './components/cn';\nexport * from './components/UserAvatar';\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,28 @@
1
+ # UserAvatar
2
+
3
+ Аватарка пользователя с инициалами при отсутствии URL, ошибке бриджа или загрузки картинки.
4
+ URL определяет сервис, в котором открыт плагин.
5
+
6
+ ```tsx
7
+ import {hostApi} from '@weavix/tracker-plugin-sdk';
8
+ import {UserAvatar, UserAvatarProvider} from '@weavix/tracker-components';
9
+
10
+ <UserAvatarProvider getUserAvatars={hostApi.getUserAvatars}>
11
+ <UserAvatar user={{uid: '123', login: 'alice'}} name="Alice Smith" size="m" />
12
+ <UserAvatar user={{login: 'bob'}} name="Bob Jones" />
13
+ </UserAvatarProvider>;
14
+ ```
15
+
16
+ Используйте один провайдер для списка: запросы одного такта объединяются в пакеты до 100
17
+ уникальных пользователей; повторы одной пары `uid`/`login` в пакете используют общий ответ. `getUserAvatars` должен возвращать массив абсолютных HTTP(S) URL или `null`
18
+ той же длины и в том же порядке. Передавайте стабильную функцию; для другого сервиса можно
19
+ подключить совместимый метод его SDK. Компоненты не зависят от конкретного пакета SDK.
20
+
21
+ `user` содержит `uid`, `login` или оба поля (непустые строки до 1024 символов).
22
+ Некорректные идентификаторы дают инициалы и не попадают в запрос соседних аватарок. `name` задаёт инициалы и доступное имя.
23
+ Поддерживаются `size`, `className`, `title`, `qa` из Gravity UI Avatar.
24
+ Без провайдера или идентификаторов отображаются инициалы без запроса. Результаты не кешируются;
25
+ поздние ответы для предыдущего пользователя игнорируются.
26
+
27
+ Хост должен поддерживать `userAvatars.get` и разрешать домены картинок в CSP `img-src`.
28
+ Для старого хоста ошибка метода приводит к инициалам.
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { type AvatarProps } from '@gravity-ui/uikit';
3
+ import type { UserAvatarUser } from './types';
4
+ export type UserAvatarProps = Pick<AvatarProps, 'size' | 'className' | 'title' | 'qa'> & {
5
+ user: UserAvatarUser;
6
+ name: string;
7
+ };
8
+ export declare function UserAvatar({ user: { uid, login }, name, ...props }: UserAvatarProps): React.JSX.Element;
@@ -0,0 +1,74 @@
1
+ import _objectSpread from "@babel/runtime/helpers/objectSpread2";
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
+ import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
4
+ var _excluded = ["url", "name"],
5
+ _excluded2 = ["user", "name"];
6
+ import "core-js/modules/es.function.name.js";
7
+ import React, { useContext, useEffect, useState } from 'react';
8
+ import { Avatar } from '@gravity-ui/uikit';
9
+ import { UserAvatarContext } from "./UserAvatarProvider";
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ function AvatarImage(_ref) {
12
+ var url = _ref.url,
13
+ name = _ref.name,
14
+ props = _objectWithoutProperties(_ref, _excluded);
15
+ var _useState = useState(false),
16
+ _useState2 = _slicedToArray(_useState, 2),
17
+ failed = _useState2[0],
18
+ setFailed = _useState2[1];
19
+ return /*#__PURE__*/_jsx("span", {
20
+ style: {
21
+ display: 'contents'
22
+ },
23
+ onErrorCapture: function onErrorCapture() {
24
+ return setFailed(true);
25
+ },
26
+ children: /*#__PURE__*/_jsx(Avatar, _objectSpread(_objectSpread({}, props), {}, {
27
+ "aria-label": name
28
+ }, url && !failed ? {
29
+ imgUrl: url,
30
+ alt: name
31
+ } : {
32
+ text: name || '?'
33
+ }))
34
+ });
35
+ }
36
+ export function UserAvatar(_ref2) {
37
+ var _result$url;
38
+ var _ref2$user = _ref2.user,
39
+ uid = _ref2$user.uid,
40
+ login = _ref2$user.login,
41
+ name = _ref2.name,
42
+ props = _objectWithoutProperties(_ref2, _excluded2);
43
+ var load = useContext(UserAvatarContext);
44
+ var _useState3 = useState(),
45
+ _useState4 = _slicedToArray(_useState3, 2),
46
+ result = _useState4[0],
47
+ setResult = _useState4[1];
48
+ useEffect(function () {
49
+ var cancelled = false;
50
+ if (load && (uid || login)) {
51
+ load(_objectSpread(_objectSpread({}, uid === undefined ? {} : {
52
+ uid: uid
53
+ }), login === undefined ? {} : {
54
+ login: login
55
+ })).then(function (url) {
56
+ if (!cancelled) setResult({
57
+ uid: uid,
58
+ login: login,
59
+ load: load,
60
+ url: url
61
+ });
62
+ });
63
+ }
64
+ return function () {
65
+ cancelled = true;
66
+ };
67
+ }, [uid, login, load]);
68
+ var url = (result === null || result === void 0 ? void 0 : result.uid) === uid && (result === null || result === void 0 ? void 0 : result.login) === login && (result === null || result === void 0 ? void 0 : result.load) === load ? (_result$url = result === null || result === void 0 ? void 0 : result.url) !== null && _result$url !== void 0 ? _result$url : null : null;
69
+ return /*#__PURE__*/_jsx(AvatarImage, _objectSpread(_objectSpread({}, props), {}, {
70
+ name: name,
71
+ url: url
72
+ }), url);
73
+ }
74
+ // #sourceMappingURL=UserAvatar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useContext","useEffect","useState","Avatar","UserAvatarContext","jsx","_jsx","AvatarImage","_ref","url","name","props","_objectWithoutProperties","_excluded","_useState","_useState2","_slicedToArray","failed","setFailed","style","display","onErrorCapture","children","_objectSpread","imgUrl","alt","text","UserAvatar","_ref2","_result$url","_ref2$user","user","uid","login","_excluded2","load","_useState3","_useState4","result","setResult","cancelled","undefined","then"],"sources":["UserAvatar.tsx"],"sourcesContent":["import React, {useContext, useEffect, useState} from 'react';\n\nimport {Avatar, type AvatarProps} from '@gravity-ui/uikit';\n\nimport {UserAvatarContext} from './UserAvatarProvider';\nimport type {UserAvatarUser} from './types';\n\nexport type UserAvatarProps = Pick<AvatarProps, 'size' | 'className' | 'title' | 'qa'> & {\n user: UserAvatarUser;\n name: string;\n};\n\nfunction AvatarImage({url, name, ...props}: Omit<UserAvatarProps, 'user'> & {url: string | null}) {\n const [failed, setFailed] = useState(false);\n return (\n <span style={{display: 'contents'}} onErrorCapture={() => setFailed(true)}>\n <Avatar\n {...props}\n aria-label={name}\n {...(url && !failed ? {imgUrl: url, alt: name} : {text: name || '?'})}\n />\n </span>\n );\n}\n\nexport function UserAvatar({user: {uid, login}, name, ...props}: UserAvatarProps) {\n const load = useContext(UserAvatarContext);\n const [result, setResult] = useState<{\n uid?: string;\n login?: string;\n load: typeof load;\n url: string | null;\n }>();\n\n useEffect(() => {\n let cancelled = false;\n if (load && (uid || login)) {\n load({\n ...(uid === undefined ? {} : {uid}),\n ...(login === undefined ? {} : {login}),\n }).then((url) => {\n if (!cancelled) setResult({uid, login, load, url});\n });\n }\n return () => {\n cancelled = true;\n };\n }, [uid, login, load]);\n\n const url =\n result?.uid === uid && result?.login === login && result?.load === load\n ? (result?.url ?? null)\n : null;\n\n return <AvatarImage key={url} {...props} name={name} url={url} />;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import type { GetUserAvatars, UserAvatarUser } from './types';
3
+ type LoadAvatar = (user: UserAvatarUser) => Promise<string | null>;
4
+ export declare const UserAvatarContext: React.Context<LoadAvatar | undefined>;
5
+ export type UserAvatarProviderProps = React.PropsWithChildren<{
6
+ getUserAvatars: GetUserAvatars;
7
+ }>;
8
+ export declare function UserAvatarProvider({ getUserAvatars, children }: UserAvatarProviderProps): React.JSX.Element;
9
+ export {};
@@ -0,0 +1,103 @@
1
+ import "core-js/modules/es.error.cause.js";
2
+ import "core-js/modules/es.error.to-string.js";
3
+ import "core-js/modules/es.array.every.js";
4
+ import "core-js/modules/es.array.for-each.js";
5
+ import "core-js/modules/es.array.from.js";
6
+ import "core-js/modules/es.array.is-array.js";
7
+ import "core-js/modules/es.array.iterator.js";
8
+ import "core-js/modules/es.array.map.js";
9
+ import "core-js/modules/es.array.push.js";
10
+ import "core-js/modules/es.array.slice.js";
11
+ import "core-js/modules/es.date.to-json.js";
12
+ import "core-js/modules/es.iterator.constructor.js";
13
+ import "core-js/modules/es.iterator.for-each.js";
14
+ import "core-js/modules/es.iterator.map.js";
15
+ import "core-js/modules/es.json.stringify.js";
16
+ import "core-js/modules/es.map.js";
17
+ import "core-js/modules/es.object.to-string.js";
18
+ import "core-js/modules/es.promise.js";
19
+ import "core-js/modules/es.regexp.exec.js";
20
+ import "core-js/modules/es.regexp.test.js";
21
+ import "core-js/modules/es.string.iterator.js";
22
+ import "core-js/modules/es.string.trim.js";
23
+ import "core-js/modules/esnext.map.get-or-insert.js";
24
+ import "core-js/modules/esnext.map.get-or-insert-computed.js";
25
+ import "core-js/modules/web.dom-collections.for-each.js";
26
+ import "core-js/modules/web.dom-collections.iterator.js";
27
+ import "core-js/modules/web.queue-microtask.js";
28
+ import React, { createContext, useMemo } from 'react';
29
+ import { jsx as _jsx } from "react/jsx-runtime";
30
+ export var UserAvatarContext = /*#__PURE__*/createContext(undefined);
31
+ function isValidUser(_ref) {
32
+ var uid = _ref.uid,
33
+ login = _ref.login;
34
+ return Boolean(uid || login) && [uid, login].every(function (value) {
35
+ return value === undefined || typeof value === 'string' && value.length <= 1024 && Boolean(value.trim());
36
+ });
37
+ }
38
+ function createLoader(getUserAvatars) {
39
+ var pending = new Map();
40
+ var flush = function flush() {
41
+ var requests = Array.from(pending.values());
42
+ pending = new Map();
43
+ var _loop = function _loop() {
44
+ var batch = requests.slice(offset, offset + 100);
45
+ Promise.resolve().then(function () {
46
+ return getUserAvatars(batch.map(function (_ref2) {
47
+ var user = _ref2.user;
48
+ return user;
49
+ }));
50
+ }).then(function (urls) {
51
+ if (!Array.isArray(urls) || urls.length !== batch.length) {
52
+ throw new Error('Avatar result must match the requested users');
53
+ }
54
+ batch.forEach(function (_ref3, index) {
55
+ var resolve = _ref3.resolve;
56
+ var url = urls[index];
57
+ var avatar = typeof url === 'string' && /^https?:\/\//i.test(url) ? url : null;
58
+ resolve.forEach(function (callback) {
59
+ return callback(avatar);
60
+ });
61
+ });
62
+ })["catch"](function () {
63
+ return batch.forEach(function (_ref4) {
64
+ var resolve = _ref4.resolve;
65
+ return resolve.forEach(function (callback) {
66
+ return callback(null);
67
+ });
68
+ });
69
+ });
70
+ };
71
+ for (var offset = 0; offset < requests.length; offset += 100) {
72
+ _loop();
73
+ }
74
+ };
75
+ return function (user) {
76
+ if (!isValidUser(user)) return Promise.resolve(null);
77
+ return new Promise(function (resolve) {
78
+ var key = JSON.stringify([user.uid, user.login]);
79
+ var request = pending.get(key);
80
+ if (request) {
81
+ request.resolve.push(resolve);
82
+ } else {
83
+ pending.set(key, {
84
+ user: user,
85
+ resolve: [resolve]
86
+ });
87
+ if (pending.size === 1) queueMicrotask(flush);
88
+ }
89
+ });
90
+ };
91
+ }
92
+ export function UserAvatarProvider(_ref5) {
93
+ var getUserAvatars = _ref5.getUserAvatars,
94
+ children = _ref5.children;
95
+ var load = useMemo(function () {
96
+ return createLoader(getUserAvatars);
97
+ }, [getUserAvatars]);
98
+ return /*#__PURE__*/_jsx(UserAvatarContext.Provider, {
99
+ value: load,
100
+ children: children
101
+ });
102
+ }
103
+ // #sourceMappingURL=UserAvatarProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","createContext","useMemo","jsx","_jsx","UserAvatarContext","undefined","isValidUser","_ref","uid","login","Boolean","every","value","length","trim","createLoader","getUserAvatars","pending","Map","flush","requests","Array","from","values","_loop","batch","slice","offset","Promise","resolve","then","map","_ref2","user","urls","isArray","Error","forEach","_ref3","index","url","avatar","test","callback","_ref4","key","JSON","stringify","request","get","push","set","size","queueMicrotask","UserAvatarProvider","_ref5","children","load","Provider"],"sources":["UserAvatarProvider.tsx"],"sourcesContent":["import React, {createContext, useMemo} from 'react';\n\nimport type {GetUserAvatars, UserAvatarUser} from './types';\n\ntype LoadAvatar = (user: UserAvatarUser) => Promise<string | null>;\ntype PendingAvatar = {user: UserAvatarUser; resolve: Array<(url: string | null) => void>};\n\nexport const UserAvatarContext = createContext<LoadAvatar | undefined>(undefined);\n\nfunction isValidUser({uid, login}: UserAvatarUser): boolean {\n return (\n Boolean(uid || login) &&\n [uid, login].every(\n (value) =>\n value === undefined ||\n (typeof value === 'string' && value.length <= 1024 && Boolean(value.trim())),\n )\n );\n}\n\nfunction createLoader(getUserAvatars: GetUserAvatars): LoadAvatar {\n let pending = new Map<string, PendingAvatar>();\n\n const flush = () => {\n const requests = Array.from(pending.values());\n pending = new Map();\n for (let offset = 0; offset < requests.length; offset += 100) {\n const batch = requests.slice(offset, offset + 100);\n Promise.resolve()\n .then(() => getUserAvatars(batch.map(({user}) => user)))\n .then((urls) => {\n if (!Array.isArray(urls) || urls.length !== batch.length) {\n throw new Error('Avatar result must match the requested users');\n }\n batch.forEach(({resolve}, index) => {\n const url = urls[index];\n const avatar =\n typeof url === 'string' && /^https?:\\/\\//i.test(url) ? url : null;\n resolve.forEach((callback) => callback(avatar));\n });\n })\n .catch(() =>\n batch.forEach(({resolve}) => resolve.forEach((callback) => callback(null))),\n );\n }\n };\n\n return (user) => {\n if (!isValidUser(user)) return Promise.resolve(null);\n return new Promise((resolve) => {\n const key = JSON.stringify([user.uid, user.login]);\n const request = pending.get(key);\n if (request) {\n request.resolve.push(resolve);\n } else {\n pending.set(key, {user, resolve: [resolve]});\n if (pending.size === 1) queueMicrotask(flush);\n }\n });\n };\n}\n\nexport type UserAvatarProviderProps = React.PropsWithChildren<{\n getUserAvatars: GetUserAvatars;\n}>;\n\nexport function UserAvatarProvider({getUserAvatars, children}: UserAvatarProviderProps) {\n const load = useMemo(() => createLoader(getUserAvatars), [getUserAvatars]);\n return <UserAvatarContext.Provider value={load}>{children}</UserAvatarContext.Provider>;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,5 @@
1
+ export { UserAvatar } from './UserAvatar';
2
+ export type { UserAvatarProps } from './UserAvatar';
3
+ export { UserAvatarProvider } from './UserAvatarProvider';
4
+ export type { UserAvatarProviderProps } from './UserAvatarProvider';
5
+ export type { GetUserAvatars, UserAvatarUser } from './types';
@@ -0,0 +1,3 @@
1
+ export { UserAvatar } from "./UserAvatar";
2
+ export { UserAvatarProvider } from "./UserAvatarProvider";
3
+ // #sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["UserAvatar","UserAvatarProvider"],"sources":["index.ts"],"sourcesContent":["export {UserAvatar} from './UserAvatar';\nexport type {UserAvatarProps} from './UserAvatar';\nexport {UserAvatarProvider} from './UserAvatarProvider';\nexport type {UserAvatarProviderProps} from './UserAvatarProvider';\nexport type {GetUserAvatars, UserAvatarUser} from './types';\n"],"mappings":"AAAA,SAAQA,UAAU;AAElB,SAAQC,kBAAkB","ignoreList":[]}
@@ -0,0 +1,5 @@
1
+ export type UserAvatarUser = {
2
+ uid?: string;
3
+ login?: string;
4
+ };
5
+ export type GetUserAvatars = (users: UserAvatarUser[]) => Promise<Array<string | null>>;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ // #sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["export type UserAvatarUser = {uid?: string; login?: string};\n\nexport type GetUserAvatars = (users: UserAvatarUser[]) => Promise<Array<string | null>>;\n"],"mappings":"","ignoreList":[]}
@@ -5,3 +5,4 @@ export * from './components/QueueSelect';
5
5
  export * from './components/TrackerDisclosure';
6
6
  export { block, cn, NAMESPACE } from './components/cn';
7
7
  export type { CnBlock } from './components/cn';
8
+ export * from './components/UserAvatar';
@@ -4,4 +4,5 @@ export * from "./components/PluginFieldsSelect";
4
4
  export * from "./components/QueueSelect";
5
5
  export * from "./components/TrackerDisclosure";
6
6
  export { block, cn, NAMESPACE } from "./components/cn";
7
+ export * from "./components/UserAvatar";
7
8
  // #sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["block","cn","NAMESPACE"],"sources":["index.ts"],"sourcesContent":["export * from './components/Icon';\nexport * from './components/MetaEntitiesSelect';\nexport * from './components/PluginFieldsSelect';\nexport * from './components/QueueSelect';\nexport * from './components/TrackerDisclosure';\nexport {block, cn, NAMESPACE} from './components/cn';\nexport type {CnBlock} from './components/cn';\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA,SAAQA,KAAK,EAAEC,EAAE,EAAEC,SAAS","ignoreList":[]}
1
+ {"version":3,"names":["block","cn","NAMESPACE"],"sources":["index.ts"],"sourcesContent":["export * from './components/Icon';\nexport * from './components/MetaEntitiesSelect';\nexport * from './components/PluginFieldsSelect';\nexport * from './components/QueueSelect';\nexport * from './components/TrackerDisclosure';\nexport {block, cn, NAMESPACE} from './components/cn';\nexport type {CnBlock} from './components/cn';\nexport * from './components/UserAvatar';\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA,SAAQA,KAAK,EAAEC,EAAE,EAAEC,SAAS;AAE5B","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weavix/tracker-components",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Shared UI components for Yandex Tracker plugins",
5
5
  "main": "build/cjs/index.js",
6
6
  "module": "build/esm/index.js",