@volter/teams 0.1.28 → 0.1.29

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/viewer/viewer.mjs CHANGED
@@ -34,6 +34,14 @@ function showHeader(shown) { $('session').classList.toggle('header-hidden', !sho
34
34
  // The host's presentation of the transcript: supercode-ui's own (the default), or `rows`, a chat's rows (every
35
35
  // message left-aligned under its author's avatar and name, one author's run grouped) in the brand's type.
36
36
  let themed = false;
37
+ // The host's words for the composer (its placeholder and the hint under it), e.g. "Message #Work".
38
+ let labels = {};
39
+ let applyLabels = () => {};
40
+ function useLabels(value) {
41
+ if (!value || typeof value !== 'object') return;
42
+ for (const key of ['composerPlaceholder', 'composerHint']) if (typeof value[key] === 'string' && value[key].length <= 200) labels[key] = value[key];
43
+ applyLabels();
44
+ }
37
45
  function useLayout(layout) {
38
46
  const rows = layout === 'rows';
39
47
  $('session').classList.toggle('layout-rows', rows);
@@ -44,14 +52,23 @@ function useLayout(layout) {
44
52
  if (!themed) document.documentElement.style.setProperty('--scui-color-scheme', 'light');
45
53
  }
46
54
  }
47
- try { applyTheme(JSON.parse(atob((fragment.get('theme') ?? '').replaceAll('-', '+').replaceAll('_', '/')) || 'null')); } catch { /* no theme */ }
55
+ // A fragment value that is base64url JSON (UTF-8), or null.
56
+ function fragmentJson(name) {
57
+ try {
58
+ const bytes = Uint8Array.from(atob((fragment.get(name) ?? '').replaceAll('-', '+').replaceAll('_', '/')), (c) => c.charCodeAt(0));
59
+ return bytes.length ? JSON.parse(decoder.decode(bytes)) : null;
60
+ } catch { return null; }
61
+ }
62
+ applyTheme(fragmentJson('theme'));
48
63
  showHeader(fragment.has('header') ? fragment.get('header') !== 'hidden' : !embedded);
49
64
  useLayout(fragment.get('layout'));
65
+ useLabels(fragmentJson('labels'));
50
66
 
51
67
  window.addEventListener('message', (event) => {
52
68
  if (event.data?.type === 'viewer-theme') { applyTheme(event.data.properties); return; }
53
69
  if (event.data?.type === 'viewer-header') { showHeader(!event.data.hidden); return; }
54
70
  if (event.data?.type === 'viewer-layout') { useLayout(event.data.layout); return; }
71
+ if (event.data?.type === 'viewer-labels') { useLabels(event.data); return; }
55
72
  if (event.data?.type !== 'delegated-token' || typeof event.data.token !== 'string') return;
56
73
  token = event.data.token;
57
74
  if (waiting) { const resume = waiting; waiting = null; resume(); }
@@ -124,6 +141,8 @@ async function showSession(session, control) {
124
141
  },
125
142
  });
126
143
  const headers = async () => ({ Authorization: `Bearer ${await freshToken()}` });
144
+ applyLabels = () => view.update({ ...labels });
145
+ applyLabels();
127
146
  const HARNESSES = { 'claude-code': 'Claude Code', codex: 'Codex', gemini: 'Gemini CLI', goose: 'Goose', opencode: 'OpenCode', pi: 'Pi', grok: 'Grok' };
128
147
  const apply = (body) => {
129
148
  view.update({ descriptor: body.descriptor, messages: body.messages.map((message) => message.value), members: body.names?.members ?? [], machines: body.names?.machines ?? [], status: 'ready', error: null });