@molecule/app-ide-react 1.4.0 → 1.6.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 +100 -1
- package/dist/command-metadata.d.ts +39 -0
- package/dist/command-metadata.d.ts.map +1 -1
- package/dist/command-metadata.js +37 -1
- package/dist/command-metadata.js.map +1 -1
- package/dist/components/ChatPanel.d.ts +9 -1
- package/dist/components/ChatPanel.d.ts.map +1 -1
- package/dist/components/ChatPanel.js +199 -27
- package/dist/components/ChatPanel.js.map +1 -1
- package/dist/components/ShareLinkManager.d.ts +63 -0
- package/dist/components/ShareLinkManager.d.ts.map +1 -0
- package/dist/components/ShareLinkManager.js +162 -0
- package/dist/components/ShareLinkManager.js.map +1 -0
- package/dist/components/ShareModal.d.ts +7 -11
- package/dist/components/ShareModal.d.ts.map +1 -1
- package/dist/components/ShareModal.js +5 -99
- package/dist/components/ShareModal.js.map +1 -1
- package/dist/components/TipCard.d.ts +7 -2
- package/dist/components/TipCard.d.ts.map +1 -1
- package/dist/components/TipCard.js +8 -6
- package/dist/components/TipCard.js.map +1 -1
- package/dist/components/UserAvatar.d.ts +10 -1
- package/dist/components/UserAvatar.d.ts.map +1 -1
- package/dist/components/UserAvatar.js +9 -6
- package/dist/components/UserAvatar.js.map +1 -1
- package/dist/components/chat-share-utilities.d.ts +6 -0
- package/dist/components/chat-share-utilities.d.ts.map +1 -1
- package/dist/components/chat-share-utilities.js.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -0
- package/dist/components/index.js.map +1 -1
- package/dist/types.d.ts +30 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public share-link manager — the single UI for a project's public link, used
|
|
3
|
+
* both inside {@link ShareModal} (the `/share` command + header share button)
|
|
4
|
+
* and by a host's team/access panel so the two never diverge.
|
|
5
|
+
*
|
|
6
|
+
* It reflects the project's CURRENT link state rather than always offering to
|
|
7
|
+
* mint one:
|
|
8
|
+
*
|
|
9
|
+
* - On mount it lists the project's links (`GET /projects/:projectId/shares`).
|
|
10
|
+
* - When a link already exists it shows the full, absolute URL
|
|
11
|
+
* (`<origin>/share/<slug>`) as a click-to-copy field with visual confirmation,
|
|
12
|
+
* plus a Revoke control — and it does NOT offer "Create link". A project has
|
|
13
|
+
* one public link at a time; to change the role you revoke and re-create.
|
|
14
|
+
* - When none exists (and the caller may manage) it offers create at the roles
|
|
15
|
+
* the host actually grants (`roles`, default `[viewer]`).
|
|
16
|
+
*
|
|
17
|
+
* `canManage` gates the mutating controls: a read-only viewer still sees and can
|
|
18
|
+
* copy an existing link, but cannot create or revoke. All mint requests clamp to
|
|
19
|
+
* a role the host grants — a public link is an unauthenticated credential.
|
|
20
|
+
*
|
|
21
|
+
* Styling uses `getClassMap()` (`cm.*`); inline styles are layout only. All
|
|
22
|
+
* user-facing text goes through `t()`.
|
|
23
|
+
*
|
|
24
|
+
* @module
|
|
25
|
+
*/
|
|
26
|
+
import type { JSX } from 'react';
|
|
27
|
+
import type { ShareLinkResult, ShareRole } from './chat-share-utilities.js';
|
|
28
|
+
/**
|
|
29
|
+
* The reusable public-link manager. See the module doc for behavior.
|
|
30
|
+
*
|
|
31
|
+
* @param props - Component props.
|
|
32
|
+
* @returns The rendered manager.
|
|
33
|
+
*/
|
|
34
|
+
export declare function ShareLinkManager({ projectId, canManage, canCreate, canRevoke, roles, initialRole, onCreated, onRevoked, }: {
|
|
35
|
+
projectId: string;
|
|
36
|
+
/**
|
|
37
|
+
* Umbrella default for {@link canCreate} and {@link canRevoke}. A caller who
|
|
38
|
+
* can neither create nor revoke may still view and copy an existing link.
|
|
39
|
+
*/
|
|
40
|
+
canManage?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Whether the caller may CREATE a link. Defaults to `canManage`. The two are
|
|
43
|
+
* separate because a host's backend often gates them at different roles (e.g.
|
|
44
|
+
* minting is admin+, revoking editor+), and offering a control the backend
|
|
45
|
+
* will 403 is worse than not offering it.
|
|
46
|
+
*/
|
|
47
|
+
canCreate?: boolean;
|
|
48
|
+
/** Whether the caller may REVOKE a link. Defaults to `canManage`. */
|
|
49
|
+
canRevoke?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* The roles this host's backend actually grants through a public link, in the
|
|
52
|
+
* order to offer them. Defaults to `[viewer]`; pass more only when the backend
|
|
53
|
+
* really honours them.
|
|
54
|
+
*/
|
|
55
|
+
roles?: readonly ShareRole[];
|
|
56
|
+
/** Role pre-selected in the create control when more than one is offered. */
|
|
57
|
+
initialRole?: ShareRole;
|
|
58
|
+
/** Called after a link is created, with the created link. */
|
|
59
|
+
onCreated?: (result: ShareLinkResult) => void;
|
|
60
|
+
/** Called after a link is revoked, with the revoked link's id. */
|
|
61
|
+
onRevoked?: (id: string) => void;
|
|
62
|
+
}): JSX.Element;
|
|
63
|
+
//# sourceMappingURL=ShareLinkManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShareLinkManager.d.ts","sourceRoot":"","sources":["../../src/components/ShareLinkManager.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAShC,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAmB3E;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EACT,SAAgB,EAChB,SAAqB,EACrB,SAAqB,EACrB,KAA4B,EAC5B,WAAgC,EAChC,SAAS,EACT,SAAS,GACV,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,qEAAqE;IACrE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;IAC5B,6EAA6E;IAC7E,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAA;IAC7C,kEAAkE;IAClE,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CACjC,GAAG,GAAG,CAAC,OAAO,CAkRd"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { t } from '@molecule/app-i18n';
|
|
4
|
+
import { getLogger } from '@molecule/app-logger';
|
|
5
|
+
import { useHttpClient, useThemeMode } from '@molecule/app-react';
|
|
6
|
+
import { getClassMap } from '@molecule/app-ui';
|
|
7
|
+
import { useCoarsePointer, useNarrowViewport } from '../hooks/useViewport.js';
|
|
8
|
+
import { buildSharePayload, buildShareUrl, DEFAULT_SHARE_ROLE, SHARE_ROLE_LABELS, } from './chat-share-utilities.js';
|
|
9
|
+
import { Icon } from './Icon.js';
|
|
10
|
+
const logger = getLogger('share-link-manager');
|
|
11
|
+
/** The current page origin, or `''` during SSR. */
|
|
12
|
+
function pageOrigin() {
|
|
13
|
+
return typeof window !== 'undefined' ? window.location.origin : '';
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The reusable public-link manager. See the module doc for behavior.
|
|
17
|
+
*
|
|
18
|
+
* @param props - Component props.
|
|
19
|
+
* @returns The rendered manager.
|
|
20
|
+
*/
|
|
21
|
+
export function ShareLinkManager({ projectId, canManage = true, canCreate = canManage, canRevoke = canManage, roles = [DEFAULT_SHARE_ROLE], initialRole = DEFAULT_SHARE_ROLE, onCreated, onRevoked, }) {
|
|
22
|
+
const cm = getClassMap();
|
|
23
|
+
const http = useHttpClient();
|
|
24
|
+
const isLight = useThemeMode() === 'light';
|
|
25
|
+
const isNarrow = useNarrowViewport();
|
|
26
|
+
const isCoarse = useCoarsePointer();
|
|
27
|
+
const offeredRoles = roles.length ? roles : [DEFAULT_SHARE_ROLE];
|
|
28
|
+
const [role, setRole] = useState(offeredRoles.includes(initialRole) ? initialRole : offeredRoles[0]);
|
|
29
|
+
const [links, setLinks] = useState([]);
|
|
30
|
+
const [loading, setLoading] = useState(true);
|
|
31
|
+
const [creating, setCreating] = useState(false);
|
|
32
|
+
const [revokingId, setRevokingId] = useState(null);
|
|
33
|
+
const [copiedId, setCopiedId] = useState(null);
|
|
34
|
+
const [error, setError] = useState(null);
|
|
35
|
+
const copyTimer = useRef(null);
|
|
36
|
+
useEffect(() => () => {
|
|
37
|
+
if (copyTimer.current)
|
|
38
|
+
clearTimeout(copyTimer.current);
|
|
39
|
+
}, []);
|
|
40
|
+
const border = isLight ? 'rgba(0,0,0,0.12)' : 'rgba(255,255,255,0.12)';
|
|
41
|
+
const fieldStyle = {
|
|
42
|
+
width: '100%',
|
|
43
|
+
padding: '6px 8px',
|
|
44
|
+
borderRadius: 4,
|
|
45
|
+
border: `1px solid ${border}`,
|
|
46
|
+
background: 'transparent',
|
|
47
|
+
color: 'inherit',
|
|
48
|
+
outline: 'none',
|
|
49
|
+
// ≥16px on phones/touch so iOS Safari doesn't zoom the page on focus.
|
|
50
|
+
...(isNarrow || isCoarse ? { fontSize: 16 } : {}),
|
|
51
|
+
};
|
|
52
|
+
const loadLinks = useCallback(async () => {
|
|
53
|
+
try {
|
|
54
|
+
const res = await http.get(`/projects/${projectId}/shares`);
|
|
55
|
+
const body = res.data;
|
|
56
|
+
const list = Array.isArray(body) ? body : (body?.data ?? []);
|
|
57
|
+
// A revoked link is gone as far as the product is concerned.
|
|
58
|
+
setLinks(list.filter((link) => !link.revokedAt));
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
logger.warn('Failed to list share links', { error: err });
|
|
62
|
+
setLinks([]);
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
setLoading(false);
|
|
66
|
+
}
|
|
67
|
+
}, [http, projectId]);
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
void loadLinks();
|
|
70
|
+
}, [loadLinks]);
|
|
71
|
+
const handleCreate = useCallback(async () => {
|
|
72
|
+
if (creating)
|
|
73
|
+
return;
|
|
74
|
+
setCreating(true);
|
|
75
|
+
setError(null);
|
|
76
|
+
try {
|
|
77
|
+
const res = await http.post(`/projects/${projectId}/shares`, buildSharePayload(role));
|
|
78
|
+
setLinks((prev) => [res.data, ...prev]);
|
|
79
|
+
onCreated?.(res.data);
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
logger.warn('Failed to create share link', { error: err });
|
|
83
|
+
setError(t('ide.chat.share.error', undefined, {
|
|
84
|
+
defaultValue: 'Could not create a share link. Please try again.',
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
setCreating(false);
|
|
89
|
+
}
|
|
90
|
+
}, [creating, http, projectId, role, onCreated]);
|
|
91
|
+
const handleRevoke = useCallback(async (id) => {
|
|
92
|
+
if (revokingId)
|
|
93
|
+
return;
|
|
94
|
+
setRevokingId(id);
|
|
95
|
+
setError(null);
|
|
96
|
+
try {
|
|
97
|
+
await http.delete(`/projects/${projectId}/shares/${id}`);
|
|
98
|
+
setLinks((prev) => prev.filter((link) => link.id !== id));
|
|
99
|
+
onRevoked?.(id);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
logger.warn('Failed to revoke share link', { error: err });
|
|
103
|
+
setError(t('ide.chat.share.revokeFailed', undefined, {
|
|
104
|
+
defaultValue: 'Could not revoke that link. Please try again.',
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
setRevokingId(null);
|
|
109
|
+
}
|
|
110
|
+
}, [revokingId, http, projectId, onRevoked]);
|
|
111
|
+
const handleCopy = useCallback((id, url) => {
|
|
112
|
+
void navigator.clipboard.writeText(url).then(() => {
|
|
113
|
+
setCopiedId(id);
|
|
114
|
+
if (copyTimer.current)
|
|
115
|
+
clearTimeout(copyTimer.current);
|
|
116
|
+
copyTimer.current = setTimeout(() => setCopiedId(null), 1500);
|
|
117
|
+
}, (err) => {
|
|
118
|
+
// Clipboard can be blocked (permissions / insecure context); the URL is
|
|
119
|
+
// still visible and the click selected it, so the user can copy by hand.
|
|
120
|
+
logger.warn('Clipboard write failed', { error: err });
|
|
121
|
+
});
|
|
122
|
+
}, []);
|
|
123
|
+
const hasLink = links.length > 0;
|
|
124
|
+
if (loading) {
|
|
125
|
+
return (_jsx("div", { "data-mol-id": "share-links-loading", className: cm.cn(cm.textMuted, cm.textSize('sm')), children: t('ide.chat.share.loading', undefined, { defaultValue: 'Loading…' }) }));
|
|
126
|
+
}
|
|
127
|
+
return (_jsxs("div", { "data-mol-id": "share-links", style: { display: 'flex', flexDirection: 'column', gap: 10 }, children: [hasLink &&
|
|
128
|
+
links.map((link) => {
|
|
129
|
+
const url = buildShareUrl(link, pageOrigin());
|
|
130
|
+
const copied = copiedId === link.id;
|
|
131
|
+
return (_jsxs("div", { "data-mol-id": `share-link-${link.id ?? link.slug}`, style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: [_jsx("span", { className: cm.fontWeight('medium'), children: t('ide.chat.share.linkLabel', undefined, { defaultValue: 'Public link' }) }), _jsxs("div", { style: { display: 'flex', gap: 8, alignItems: 'stretch' }, children: [_jsx("input", { value: url, "data-mol-id": "share-link-url", readOnly: true, title: t('ide.chat.share.copyHint', undefined, { defaultValue: 'Click to copy' }), onClick: (e) => {
|
|
132
|
+
e.currentTarget.select();
|
|
133
|
+
handleCopy(link.id ?? link.slug, url);
|
|
134
|
+
}, className: cm.textSize('sm'), style: { ...fieldStyle, flex: 1, cursor: 'pointer' } }), _jsxs("button", { type: "button", "data-mol-id": "share-link-copy", onClick: () => handleCopy(link.id ?? link.slug, url), className: cm.cn(cm.button({ variant: 'solid', color: 'primary', size: 'sm' })), title: t('ide.chat.share.copy', undefined, { defaultValue: 'Copy link' }), "aria-label": t('ide.chat.share.copy', undefined, { defaultValue: 'Copy link' }), style: {
|
|
135
|
+
flexShrink: 0,
|
|
136
|
+
display: 'inline-flex',
|
|
137
|
+
alignItems: 'center',
|
|
138
|
+
gap: 6,
|
|
139
|
+
height: 'auto',
|
|
140
|
+
}, children: [_jsx(Icon, { name: copied ? 'check' : 'copy', size: 14, "aria-hidden": "true" }), copied
|
|
141
|
+
? t('ide.chat.share.copied', undefined, { defaultValue: 'Copied' })
|
|
142
|
+
: t('ide.chat.share.copyShort', undefined, { defaultValue: 'Copy' })] })] }), _jsxs("div", { style: {
|
|
143
|
+
display: 'flex',
|
|
144
|
+
alignItems: 'center',
|
|
145
|
+
justifyContent: 'space-between',
|
|
146
|
+
gap: 8,
|
|
147
|
+
}, children: [_jsx("span", { className: cm.cn(cm.textMuted, cm.textSize('xs')), style: { lineHeight: 1.4 }, children: t(`ide.chat.share.grants.${link.role}`, { role: link.role }, { defaultValue: 'Anyone with this link can act as {{role}}.' }) }), canRevoke && link.id && (_jsx("button", { type: "button", "data-mol-id": `share-link-revoke-${link.id}`, onClick: () => void handleRevoke(link.id), disabled: revokingId === link.id, className: cm.cn(cm.button({ variant: 'ghost', color: 'error', size: 'sm' })), style: { flexShrink: 0 }, children: revokingId === link.id
|
|
148
|
+
? t('ide.chat.share.revoking', undefined, { defaultValue: 'Revoking…' })
|
|
149
|
+
: t('ide.chat.share.revoke', undefined, { defaultValue: 'Revoke' }) }))] })] }, link.id ?? link.slug));
|
|
150
|
+
}), !hasLink && !canCreate && (_jsx("div", { "data-mol-id": "share-links-none", className: cm.cn(cm.textMuted, cm.textSize('sm')), children: t('ide.chat.share.none', undefined, { defaultValue: 'No public link yet.' }) })), !hasLink && canCreate && (_jsxs(_Fragment, { children: [offeredRoles.length > 1 && (_jsxs("label", { style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: [_jsx("span", { className: cm.fontWeight('medium'), children: t('ide.chat.share.roleLabel', undefined, { defaultValue: 'Role' }) }), _jsx("select", { value: role, "data-mol-id": "share-role", onChange: (e) => setRole(e.target.value), className: cm.textSize('sm'), style: fieldStyle, children: offeredRoles.map((r) => (_jsx("option", { value: r, children: t(`ide.chat.share.role.${r}`, undefined, {
|
|
151
|
+
defaultValue: SHARE_ROLE_LABELS[r],
|
|
152
|
+
}) }, r))) })] })), _jsxs("button", { type: "button", "data-mol-id": "share-create", onClick: () => void handleCreate(), disabled: creating, className: cm.cn(cm.button({ variant: 'solid', color: 'primary', size: 'sm' })), style: {
|
|
153
|
+
opacity: creating ? 0.6 : 1,
|
|
154
|
+
display: 'inline-flex',
|
|
155
|
+
alignItems: 'center',
|
|
156
|
+
gap: 6,
|
|
157
|
+
alignSelf: 'flex-start',
|
|
158
|
+
}, children: [_jsx(Icon, { name: "share", size: 14, "aria-hidden": "true" }), creating
|
|
159
|
+
? t('ide.chat.share.creating', undefined, { defaultValue: 'Creating…' })
|
|
160
|
+
: t('ide.chat.share.create', undefined, { defaultValue: 'Create link' })] })] })), error && (_jsx("div", { "data-mol-id": "share-error", className: cm.textError, style: { lineHeight: 1.4 }, children: error }))] }));
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=ShareLinkManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShareLinkManager.js","sourceRoot":"","sources":["../../src/components/ShareLinkManager.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `/share` link modal.
|
|
3
3
|
*
|
|
4
|
-
* A centered modal
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* A centered modal wrapping {@link ShareLinkManager} — the shared public-link UI
|
|
5
|
+
* a host also mounts in its team/access panel, so the modal and that panel never
|
|
6
|
+
* diverge. On open the manager reflects the project's CURRENT link: if one
|
|
7
|
+
* already exists it shows the absolute URL (click-to-copy) plus Revoke and does
|
|
8
|
+
* NOT offer to create another; otherwise it offers create at the roles the host
|
|
9
|
+
* grants.
|
|
9
10
|
*
|
|
10
11
|
* **Only the roles the HOST actually grants are offered**, via `roles`, which
|
|
11
12
|
* defaults to `[viewer]` — a link anyone can open is an unauthenticated
|
|
12
13
|
* credential, so write access through one is something a host has to opt into
|
|
13
|
-
* rather than something this modal offers by default.
|
|
14
|
-
* appears only when there is a genuine choice; with one role the modal simply
|
|
15
|
-
* states what the link will grant. This used to render all four contract roles
|
|
16
|
-
* unconditionally while the only shipped backend clamped every one of them to
|
|
17
|
-
* `viewer` — so picking "Editor — view & edit" minted a viewer link and the
|
|
18
|
-
* dialog told the user two contradictory things at once.
|
|
14
|
+
* rather than something this modal offers by default.
|
|
19
15
|
*
|
|
20
16
|
* Styling uses `getClassMap()` (`cm.*`); the only inline styles are layout the
|
|
21
17
|
* ClassMap can't express. All user-facing text goes through `t()`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShareModal.d.ts","sourceRoot":"","sources":["../../src/components/ShareModal.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ShareModal.d.ts","sourceRoot":"","sources":["../../src/components/ShareModal.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAMhC,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAI3E;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EACzB,SAAS,EACT,WAAgC,EAChC,KAA4B,EAC5B,OAAO,EACP,SAAS,GACV,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;IAC5B,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAA;CAC9C,GAAG,GAAG,CAAC,OAAO,CAyFd"}
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
3
|
import { t } from '@molecule/app-i18n';
|
|
4
|
-
import { getLogger } from '@molecule/app-logger';
|
|
5
|
-
import { useHttpClient, useThemeMode } from '@molecule/app-react';
|
|
6
4
|
import { getClassMap } from '@molecule/app-ui';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { Icon } from './Icon.js';
|
|
10
|
-
const logger = getLogger('share-modal');
|
|
5
|
+
import { DEFAULT_SHARE_ROLE } from './chat-share-utilities.js';
|
|
6
|
+
import { ShareLinkManager } from './ShareLinkManager.js';
|
|
11
7
|
/**
|
|
12
8
|
* The share-link modal opened by `/share`, `/share <role>`, and the header
|
|
13
9
|
* share button.
|
|
@@ -17,17 +13,6 @@ const logger = getLogger('share-modal');
|
|
|
17
13
|
*/
|
|
18
14
|
export function ShareModal({ projectId, initialRole = DEFAULT_SHARE_ROLE, roles = [DEFAULT_SHARE_ROLE], onClose, onCreated, }) {
|
|
19
15
|
const cm = getClassMap();
|
|
20
|
-
const http = useHttpClient();
|
|
21
|
-
const isLight = useThemeMode() === 'light';
|
|
22
|
-
// A requested role the host does not grant would be silently downgraded by
|
|
23
|
-
// the backend, so fall back to the first offered role rather than showing a
|
|
24
|
-
// choice that will not be honoured.
|
|
25
|
-
const offeredRoles = roles.length ? roles : [DEFAULT_SHARE_ROLE];
|
|
26
|
-
const [role, setRole] = useState(offeredRoles.includes(initialRole) ? initialRole : offeredRoles[0]);
|
|
27
|
-
const [creating, setCreating] = useState(false);
|
|
28
|
-
const [created, setCreated] = useState(null);
|
|
29
|
-
const [copied, setCopied] = useState(false);
|
|
30
|
-
const [error, setError] = useState(null);
|
|
31
16
|
// Escape closes the modal.
|
|
32
17
|
useEffect(() => {
|
|
33
18
|
const handler = (e) => {
|
|
@@ -37,58 +22,7 @@ export function ShareModal({ projectId, initialRole = DEFAULT_SHARE_ROLE, roles
|
|
|
37
22
|
window.addEventListener('keydown', handler);
|
|
38
23
|
return () => window.removeEventListener('keydown', handler);
|
|
39
24
|
}, [onClose]);
|
|
40
|
-
const
|
|
41
|
-
const isCoarse = useCoarsePointer();
|
|
42
|
-
const border = isLight ? 'rgba(0,0,0,0.12)' : 'rgba(255,255,255,0.12)';
|
|
43
|
-
const fieldStyle = {
|
|
44
|
-
width: '100%',
|
|
45
|
-
padding: '6px 8px',
|
|
46
|
-
borderRadius: 4,
|
|
47
|
-
border: `1px solid ${border}`,
|
|
48
|
-
background: 'transparent',
|
|
49
|
-
color: 'inherit',
|
|
50
|
-
outline: 'none',
|
|
51
|
-
// ≥16px on phones/touch so iOS Safari doesn't zoom the page on focus
|
|
52
|
-
// (the role <select> and the focus-selecting link input both zoom below
|
|
53
|
-
// 16px; the inline size deliberately overrides cm.textSize('sm') there).
|
|
54
|
-
...(isNarrow || isCoarse ? { fontSize: 16 } : {}),
|
|
55
|
-
};
|
|
56
|
-
const shareUrl = created
|
|
57
|
-
? buildShareUrl(created, typeof window !== 'undefined' ? window.location.origin : '')
|
|
58
|
-
: '';
|
|
59
|
-
const handleCreate = useCallback(async () => {
|
|
60
|
-
if (creating)
|
|
61
|
-
return;
|
|
62
|
-
setCreating(true);
|
|
63
|
-
setError(null);
|
|
64
|
-
try {
|
|
65
|
-
const res = await http.post(`/projects/${projectId}/shares`, buildSharePayload(role));
|
|
66
|
-
setCreated(res.data);
|
|
67
|
-
setCopied(false);
|
|
68
|
-
onCreated?.(res.data);
|
|
69
|
-
}
|
|
70
|
-
catch (err) {
|
|
71
|
-
logger.warn('Failed to create share link', { error: err });
|
|
72
|
-
setError(t('ide.chat.share.error', undefined, {
|
|
73
|
-
defaultValue: 'Could not create a share link. Please try again.',
|
|
74
|
-
}));
|
|
75
|
-
}
|
|
76
|
-
finally {
|
|
77
|
-
setCreating(false);
|
|
78
|
-
}
|
|
79
|
-
}, [creating, http, projectId, role, onCreated]);
|
|
80
|
-
const handleCopy = useCallback(() => {
|
|
81
|
-
if (!shareUrl)
|
|
82
|
-
return;
|
|
83
|
-
void navigator.clipboard.writeText(shareUrl).then(() => {
|
|
84
|
-
setCopied(true);
|
|
85
|
-
setTimeout(() => setCopied(false), 1500);
|
|
86
|
-
}, (err) => {
|
|
87
|
-
// Clipboard can be blocked (permissions / insecure context); the link
|
|
88
|
-
// is still visible and selectable in the field, so this is recoverable.
|
|
89
|
-
logger.warn('Clipboard write failed', { error: err });
|
|
90
|
-
});
|
|
91
|
-
}, [shareUrl]);
|
|
25
|
+
const offeredRoles = roles.length ? roles : [DEFAULT_SHARE_ROLE];
|
|
92
26
|
return (_jsx("div", { "data-mol-id": "share-modal-backdrop", onClick: onClose, style: {
|
|
93
27
|
position: 'fixed',
|
|
94
28
|
inset: 0,
|
|
@@ -114,34 +48,6 @@ export function ShareModal({ projectId, initialRole = DEFAULT_SHARE_ROLE, roles
|
|
|
114
48
|
})
|
|
115
49
|
: t(`ide.chat.share.subheading.${offeredRoles[0]}`, { role: offeredRoles[0] }, {
|
|
116
50
|
defaultValue: 'Create a public link. Anyone with the link can act as {{role}}.',
|
|
117
|
-
}) }),
|
|
118
|
-
defaultValue: SHARE_ROLE_LABELS[r],
|
|
119
|
-
}) }, r))) })] })), created && (_jsxs("label", { style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: [_jsx("span", { className: cm.fontWeight('medium'), children: t('ide.chat.share.linkLabel', undefined, { defaultValue: 'Public link' }) }), _jsxs("div", { style: { display: 'flex', gap: 8, alignItems: 'stretch' }, children: [_jsx("input", { value: shareUrl, "data-mol-id": "share-link", readOnly: true, onFocus: (e) => e.currentTarget.select(), className: cm.textSize('sm'), style: { ...fieldStyle, flex: 1 } }), _jsxs("button", { type: "button", "data-mol-id": "share-copy", onClick: handleCopy, className: cm.cn(cm.button({ variant: 'solid', color: 'primary', size: 'sm' })), title: t('ide.chat.share.copy', undefined, { defaultValue: 'Copy link' }), "aria-label": t('ide.chat.share.copy', undefined, { defaultValue: 'Copy link' }), style: {
|
|
120
|
-
flexShrink: 0,
|
|
121
|
-
display: 'inline-flex',
|
|
122
|
-
alignItems: 'center',
|
|
123
|
-
gap: 6,
|
|
124
|
-
// The `sm` button class hard-sets h-[26px]; an explicit height
|
|
125
|
-
// can't be stretched by the row's alignItems:'stretch', so it
|
|
126
|
-
// stays shorter than the taller hand-rolled link input beside
|
|
127
|
-
// it (16px font on touch makes that input taller still).
|
|
128
|
-
// Dropping to auto lets stretch size the button to the input.
|
|
129
|
-
height: 'auto',
|
|
130
|
-
}, children: [_jsx(Icon, { name: copied ? 'check' : 'copy', size: 14, "aria-hidden": "true" }), copied
|
|
131
|
-
? t('ide.chat.share.copied', undefined, { defaultValue: 'Copied' })
|
|
132
|
-
: t('ide.chat.share.copyShort', undefined, { defaultValue: 'Copy' })] })] }), _jsx("span", { className: cm.cn(cm.textMuted, cm.textSize('xs')), style: { lineHeight: 1.4 }, children: t(`ide.chat.share.grants.${created.role}`, { role: created.role }, {
|
|
133
|
-
defaultValue: 'Anyone with this link can act as {{role}}.',
|
|
134
|
-
}) })] })), error && (_jsx("div", { "data-mol-id": "share-error", className: cm.textError, style: { lineHeight: 1.4 }, children: error }))] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'flex-end', gap: 8, marginTop: 16 }, children: [_jsx("button", { type: "button", "data-mol-id": "share-close", onClick: onClose, className: cm.cn(cm.button({ variant: 'ghost', size: 'sm' })), children: created
|
|
135
|
-
? t('common.done', undefined, { defaultValue: 'Done' })
|
|
136
|
-
: t('common.cancel', undefined, { defaultValue: 'Cancel' }) }), _jsxs("button", { type: "button", "data-mol-id": "share-create", onClick: () => void handleCreate(), disabled: creating, className: cm.cn(cm.button({ variant: 'solid', color: 'primary', size: 'sm' })), style: {
|
|
137
|
-
opacity: creating ? 0.6 : 1,
|
|
138
|
-
display: 'inline-flex',
|
|
139
|
-
alignItems: 'center',
|
|
140
|
-
gap: 6,
|
|
141
|
-
}, children: [_jsx(Icon, { name: "share", size: 14, "aria-hidden": "true" }), creating
|
|
142
|
-
? t('ide.chat.share.creating', undefined, { defaultValue: 'Creating…' })
|
|
143
|
-
: created
|
|
144
|
-
? t('ide.chat.share.createAnother', undefined, { defaultValue: 'Create new link' })
|
|
145
|
-
: t('ide.chat.share.create', undefined, { defaultValue: 'Create link' })] })] })] }) }));
|
|
51
|
+
}) }), _jsx(ShareLinkManager, { projectId: projectId, roles: offeredRoles, initialRole: initialRole, onCreated: onCreated }), _jsx("div", { style: { display: 'flex', justifyContent: 'flex-end', gap: 8, marginTop: 16 }, children: _jsx("button", { type: "button", "data-mol-id": "share-close", onClick: onClose, className: cm.cn(cm.button({ variant: 'ghost', size: 'sm' })), children: t('common.done', undefined, { defaultValue: 'Done' }) }) })] }) }));
|
|
146
52
|
}
|
|
147
53
|
//# sourceMappingURL=ShareModal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShareModal.js","sourceRoot":"","sources":["../../src/components/ShareModal.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"ShareModal.js","sourceRoot":"","sources":["../../src/components/ShareModal.tsx"],"names":[],"mappings":"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"}
|
|
@@ -9,14 +9,19 @@
|
|
|
9
9
|
* @module
|
|
10
10
|
*/
|
|
11
11
|
import type { JSX } from 'react';
|
|
12
|
+
import type { IconName } from '@molecule/app-icons';
|
|
12
13
|
/**
|
|
13
14
|
* Renders a single dismissable onboarding tip.
|
|
14
15
|
*
|
|
15
|
-
* @param props - Component props.
|
|
16
|
+
* @param props - Component props. `accent` recolours the card tint + icon for a
|
|
17
|
+
* semantic tip (e.g. the gold viewer tip that explains the team-only message
|
|
18
|
+
* treatment); `icon` overrides the leading glyph (default `lightbulb`).
|
|
16
19
|
* @returns The rendered tip card.
|
|
17
20
|
*/
|
|
18
|
-
export declare function TipCard({ text, onDismiss }: {
|
|
21
|
+
export declare function TipCard({ text, onDismiss, accent, icon, }: {
|
|
19
22
|
text: string;
|
|
20
23
|
onDismiss: () => void;
|
|
24
|
+
accent?: string;
|
|
25
|
+
icon?: IconName;
|
|
21
26
|
}): JSX.Element;
|
|
22
27
|
//# sourceMappingURL=TipCard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TipCard.d.ts","sourceRoot":"","sources":["../../src/components/TipCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAiB,GAAG,EAAa,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"TipCard.d.ts","sourceRoot":"","sources":["../../src/components/TipCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAiB,GAAG,EAAa,MAAM,OAAO,CAAA;AAG1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAuCnD;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,EACtB,IAAI,EACJ,SAAS,EACT,MAAM,EACN,IAAI,GACL,EAAE;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,QAAQ,CAAA;CAChB,GAAG,GAAG,CAAC,OAAO,CAuEd"}
|
|
@@ -28,10 +28,12 @@ function renderTipText(text) {
|
|
|
28
28
|
/**
|
|
29
29
|
* Renders a single dismissable onboarding tip.
|
|
30
30
|
*
|
|
31
|
-
* @param props - Component props.
|
|
31
|
+
* @param props - Component props. `accent` recolours the card tint + icon for a
|
|
32
|
+
* semantic tip (e.g. the gold viewer tip that explains the team-only message
|
|
33
|
+
* treatment); `icon` overrides the leading glyph (default `lightbulb`).
|
|
32
34
|
* @returns The rendered tip card.
|
|
33
35
|
*/
|
|
34
|
-
export function TipCard({ text, onDismiss }) {
|
|
36
|
+
export function TipCard({ text, onDismiss, accent, icon, }) {
|
|
35
37
|
const cm = getClassMap();
|
|
36
38
|
return (_jsxs("div", { "data-mol-id": "chat-tip-card", className: cm.cn(cm.textSize('xs'), cm.textMuted), style: {
|
|
37
39
|
display: 'flex',
|
|
@@ -40,14 +42,14 @@ export function TipCard({ text, onDismiss }) {
|
|
|
40
42
|
// One chat-timeline rhythm: bottom margin only, never a top margin (matches
|
|
41
43
|
// ChatPanel's TIMELINE_ITEM_GAP so adjacent items never collide — P4-05).
|
|
42
44
|
marginBottom: 16,
|
|
43
|
-
// Shared card chrome: subtle
|
|
45
|
+
// Shared card chrome: subtle accent tint + a uniform 1px border on all
|
|
44
46
|
// sides. One source of truth with the other chat info cards (chat-card-style).
|
|
45
|
-
...chatCardStyle(),
|
|
47
|
+
...chatCardStyle(accent),
|
|
46
48
|
lineHeight: 1.5,
|
|
47
|
-
}, children: [_jsx(Icon, { name:
|
|
49
|
+
}, children: [_jsx(Icon, { name: icon ?? 'lightbulb', size: CHAT_CARD_ICON_SIZE, "aria-hidden": "true", style: {
|
|
48
50
|
flexShrink: 0,
|
|
49
51
|
marginTop: 1,
|
|
50
|
-
color: 'var(--mol-color-primary, #6366f1)',
|
|
52
|
+
color: accent ?? 'var(--mol-color-primary, #6366f1)',
|
|
51
53
|
} }), _jsx("span", { style: { flex: 1 }, children: renderTipText(text) }), _jsx("button", { type: "button", "data-mol-id": "chat-tip-dismiss", onClick: onDismiss, "aria-label": t('ide.chat.tip.dismiss', undefined, { defaultValue: 'Dismiss tip' }), title: t('ide.chat.tip.dismiss', undefined, { defaultValue: 'Dismiss tip' }), style: {
|
|
52
54
|
flexShrink: 0,
|
|
53
55
|
display: 'inline-flex',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TipCard.js","sourceRoot":"","sources":["../../src/components/TipCard.tsx"],"names":[],"mappings":";AAaA,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"TipCard.js","sourceRoot":"","sources":["../../src/components/TipCard.tsx"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,15 @@ export interface UserAvatarProps {
|
|
|
18
18
|
* ignored (see {@link resolveUserAvatar}) and the generic icon is shown.
|
|
19
19
|
*/
|
|
20
20
|
userAvatar?: string | null;
|
|
21
|
+
/**
|
|
22
|
+
* The message author's display name, for a TEAMMATE's message. When set and
|
|
23
|
+
* there is no renderable avatar, the fallback tile shows the name's initial
|
|
24
|
+
* (e.g. "T" for Test) instead of the generic `user` glyph — so a teammate
|
|
25
|
+
* without a profile picture is still identifiable at a glance and is NEVER
|
|
26
|
+
* shown with the viewer's own avatar. Also used as the accessible label /
|
|
27
|
+
* image alt in place of the solo "You".
|
|
28
|
+
*/
|
|
29
|
+
name?: string;
|
|
21
30
|
/** Diameter of the avatar in pixels. Defaults to 24. */
|
|
22
31
|
size?: number;
|
|
23
32
|
/**
|
|
@@ -38,7 +47,7 @@ export interface UserAvatarProps {
|
|
|
38
47
|
* @param props - {@link UserAvatarProps}.
|
|
39
48
|
* @returns The avatar image or icon fallback, optionally wrapped in a button.
|
|
40
49
|
*/
|
|
41
|
-
export declare function UserAvatar({ userAvatar, size, onClick }: UserAvatarProps): JSX.Element;
|
|
50
|
+
export declare function UserAvatar({ userAvatar, name, size, onClick }: UserAvatarProps): JSX.Element;
|
|
42
51
|
export declare namespace UserAvatar {
|
|
43
52
|
var displayName: string;
|
|
44
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserAvatar.d.ts","sourceRoot":"","sources":["../../src/components/UserAvatar.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,GAAG,EAAY,MAAM,OAAO,CAAA;AAO1C;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,EAAE,UAAU,EAAE,IAAS,EAAE,OAAO,EAAE,EAAE,eAAe,GAAG,GAAG,CAAC,OAAO,
|
|
1
|
+
{"version":3,"file":"UserAvatar.d.ts","sourceRoot":"","sources":["../../src/components/UserAvatar.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,GAAG,EAAY,MAAM,OAAO,CAAA;AAO1C;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,IAAS,EAAE,OAAO,EAAE,EAAE,eAAe,GAAG,GAAG,CAAC,OAAO,CAuGjG;yBAvGe,UAAU"}
|
|
@@ -21,13 +21,16 @@ import { resolveUserAvatar } from './user-avatar-utilities.js';
|
|
|
21
21
|
* @param props - {@link UserAvatarProps}.
|
|
22
22
|
* @returns The avatar image or icon fallback, optionally wrapped in a button.
|
|
23
23
|
*/
|
|
24
|
-
export function UserAvatar({ userAvatar, size = 24, onClick }) {
|
|
24
|
+
export function UserAvatar({ userAvatar, name, size = 24, onClick }) {
|
|
25
25
|
const [hover, setHover] = useState(false);
|
|
26
26
|
const src = resolveUserAvatar(userAvatar);
|
|
27
|
-
// The
|
|
28
|
-
//
|
|
29
|
-
// image alt and the
|
|
30
|
-
const label = t('ide.chat.you', undefined, { defaultValue: 'You' });
|
|
27
|
+
// The avatar identifies the message's sender: the author's name when we have
|
|
28
|
+
// one (a teammate's message), else the solo "You" (already-translated) — used
|
|
29
|
+
// for both the image alt and the fallback tile's accessible name.
|
|
30
|
+
const label = name || t('ide.chat.you', undefined, { defaultValue: 'You' });
|
|
31
|
+
// Named author with no renderable avatar → an initial-letter tile ("T" for
|
|
32
|
+
// Test), never the generic glyph and NEVER someone else's picture.
|
|
33
|
+
const initial = name?.trim().charAt(0).toUpperCase() ?? '';
|
|
31
34
|
const visual = src ? (_jsx("img", { src: src, alt: label, "data-mol-id": "chat-user-avatar",
|
|
32
35
|
// Rounded-square sizing / cropping the ClassMap cannot express. A solid,
|
|
33
36
|
// VISIBLE primary-tinted backdrop so a transparent PNG (or the pre-load gap)
|
|
@@ -51,7 +54,7 @@ export function UserAvatar({ userAvatar, size = 24, onClick }) {
|
|
|
51
54
|
flexShrink: 0,
|
|
52
55
|
background: 'color-mix(in srgb, var(--mol-color-primary, #6366f1) 18%, var(--mol-color-surface, #f4f4f4))',
|
|
53
56
|
color: 'var(--mol-color-primary, #6366f1)',
|
|
54
|
-
}, children: _jsx(Icon, { name: "user", size: Math.round(size * 0.6), "aria-hidden": "true" }) }));
|
|
57
|
+
}, children: initial ? (_jsx("span", { "aria-hidden": "true", style: { fontSize: Math.round(size * 0.45), fontWeight: 600, lineHeight: 1 }, children: initial })) : (_jsx(Icon, { name: "user", size: Math.round(size * 0.6), "aria-hidden": "true" })) }));
|
|
55
58
|
// Non-interactive (the default) — render the bare visual, unchanged.
|
|
56
59
|
if (!onClick)
|
|
57
60
|
return visual;
|