@goodandready/dsh-subscriptions 0.2.6 → 0.2.8

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 (2) hide show
  1. package/lib/client.js +111 -22
  2. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -6,27 +6,39 @@ window.__ModuleLoader__.load({
6
6
  const React = require('react')
7
7
 
8
8
  const CSS =
9
- '.dsub-wrap{display:flex;flex-direction:column;gap:22px;padding:4px 0;max-width:760px}' +
10
- '.dsub-block{display:flex;flex-direction:column;gap:10px}' +
11
- '.dsub-h{font-size:14px;font-weight:600;color:var(--dsw-alias-label-primary)}' +
12
- '.dsub-sub{font-size:12px;color:var(--dsw-alias-label-secondary)}' +
13
- '.dsub-card{display:flex;flex-direction:column;gap:8px;padding:10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px}' +
14
- '.dsub-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}' +
15
- '.dsub-row input,.dsub-field input,.dsub-row select{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);border-radius:6px;padding:6px 8px;font-size:13px}' +
16
- '.dsub-grow{flex:1;min-width:180px}' +
17
- '.dsub-field{display:flex;flex-direction:column;gap:4px;font-size:12px;color:var(--dsw-alias-label-secondary)}' +
18
- '.dsub-mini{border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-primary);border-radius:6px;height:28px;padding:0 8px;cursor:pointer}' +
19
- '.dsub-save{background:var(--dsw-alias-brand-primary);color:#fff;border:none;border-radius:6px;padding:7px 14px;font-size:13px;cursor:pointer}' +
20
- '.dsub-ok{font-size:12px;color:var(--dsw-alias-state-success-primary)}' +
21
- '.dsub-bad{font-size:12px;color:var(--dsw-alias-state-error-primary)}' +
22
- '.dsub-badge{font-size:11px;padding:2px 8px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);white-space:nowrap}' +
23
- '.dsub-badge-on{color:var(--dsw-alias-state-success-primary);border-color:currentColor}' +
24
- '.dsub-badge-warn{color:var(--dsw-alias-state-warning-primary);border-color:currentColor}' +
25
- '.dsub-link{background:none;border:none;color:var(--dsw-alias-label-secondary);cursor:pointer;font-size:12px;padding:0}' +
26
- '.dsub-verify{font-size:12px;color:var(--dsw-alias-state-warning-primary)}' +
27
- '.dsub-verify a{color:var(--dsw-alias-brand-primary)}'
9
+ // card — same structure as core PluginCard (bash, agent-loop, web-search)
10
+ '.dsub-card{list-style:none;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;transition:border-color .16s,background .16s}' +
11
+ '.dsub-card:hover{border-color:var(--dsw-alias-label-dimmed)}' +
12
+ '.dsub-cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}' +
13
+ '.dsub-header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}' +
14
+ '.dsub-header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}' +
15
+ '.dsub-headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}' +
16
+ '.dsub-name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}' +
17
+ '.dsub-description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}' +
18
+ '.dsub-chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}' +
19
+ '.dsub-chevronOpen{transform:rotate(180deg)}' +
20
+ '.dsub-body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding:16px 0 8px}' +
21
+ // existing dsub classes kept for SubsSection internals
22
+ '.dsub-wrap{display:flex;flex-direction:column;gap:22px;padding:4px 0;max-width:760px}' +
23
+ '.dsub-block{display:flex;flex-direction:column;gap:10px}' +
24
+ '.dsub-h{font-size:14px;font-weight:600;color:var(--dsw-alias-label-primary)}' +
25
+ '.dsub-sub{font-size:12px;color:var(--dsw-alias-label-secondary)}' +
26
+ '.dsub-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}' +
27
+ '.dsub-row input,.dsub-field input,.dsub-row select{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);border-radius:6px;padding:6px 8px;font-size:13px}' +
28
+ '.dsub-grow{flex:1;min-width:180px}' +
29
+ '.dsub-field{display:flex;flex-direction:column;gap:4px;font-size:12px;color:var(--dsw-alias-label-secondary)}' +
30
+ '.dsub-mini{border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-primary);border-radius:6px;height:28px;padding:0 8px;cursor:pointer}' +
31
+ '.dsub-save{background:var(--dsw-alias-brand-primary);color:#fff;border:none;border-radius:6px;padding:7px 14px;font-size:13px;cursor:pointer}' +
32
+ '.dsub-ok{font-size:12px;color:var(--dsw-alias-state-success-primary)}' +
33
+ '.dsub-bad{font-size:12px;color:var(--dsw-alias-state-error-primary)}' +
34
+ '.dsub-badge{font-size:11px;padding:2px 8px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);white-space:nowrap}' +
35
+ '.dsub-badge-on{color:var(--dsw-alias-state-success-primary);border-color:currentColor}' +
36
+ '.dsub-badge-warn{color:var(--dsw-alias-state-warning-primary);border-color:currentColor}' +
37
+ '.dsub-link{background:none;border:none;color:var(--dsw-alias-label-secondary);cursor:pointer;font-size:12px;padding:0}' +
38
+ '.dsub-verify{font-size:12px;color:var(--dsw-alias-state-warning-primary)}' +
39
+ '.dsub-verify a{color:var(--dsw-alias-brand-primary)}'
28
40
 
29
- const cssId = 'dsh-subscriptions/settings.module.css'
41
+ const cssId = 'dsh-subscriptions/settings.module.css'
30
42
  if (typeof document !== 'undefined' && !document.querySelector('style[data-plugin-css="' + cssId + '"]')) {
31
43
  const tag = document.createElement('style')
32
44
  tag.textContent = CSS
@@ -46,6 +58,9 @@ window.__ModuleLoader__.load({
46
58
  'usageFull': 'Usage 100%',
47
59
  'connected': 'Connected',
48
60
  'title': 'Subscriptions',
61
+ 'cardIntro': 'Subscription accounts, rotation and limits.',
62
+ 'show': 'Show',
63
+ 'hide': 'Hide',
49
64
  'intro': 'Log in with a consumer subscription. Tokens stay on the host credentials store. The browser never reads them back. After Connect, if the provider lands on localhost or a vendor page, paste the redirected URL or the code here.',
50
65
  'useOrigin': 'Use this Web UI origin as OAuth redirect_uri',
51
66
  'useOriginHint': 'Leave off unless you registered your own OAuth client for this origin. Vendor CLI clients usually require their published redirect URI plus the paste step.',
@@ -73,6 +88,9 @@ window.__ModuleLoader__.load({
73
88
  'usageFull': 'Лимит исчерпан',
74
89
  'connected': 'Подключено',
75
90
  'title': 'Подписки',
91
+ 'cardIntro': 'Аккаунты подписок, ротация и лимиты.',
92
+ 'show': 'Показать',
93
+ 'hide': 'Скрыть',
76
94
  'intro': 'Вход по обычной пользовательской подписке. Токены остаются в хранилище учётных данных харнесса, браузер их обратно не читает. Если после «Подключить» провайдер увёл на localhost или на свою страницу, вставьте сюда адрес перехода или код.',
77
95
  'useOrigin': 'Использовать адрес этого веб-интерфейса как redirect_uri',
78
96
  'useOriginHint': 'Включайте, только если зарегистрировали собственного клиента OAuth на этот адрес. Штатным консольным клиентам провайдеров нужен их опубликованный адрес возврата и вставка кода вручную.',
@@ -102,6 +120,26 @@ window.__ModuleLoader__.load({
102
120
  return t('connected')
103
121
  }
104
122
 
123
+ // Карточка во вкладке «Плагины» рисует свой заголовок и сворачивание:
124
+ // ядро даёт только рамку списка.
125
+ function PluginCard(props) {
126
+ const t = (props && props.t) || ((key) => key)
127
+ const [open, setOpen] = React.useState(false)
128
+ return React.createElement('div', { className: 'dsub-block' },
129
+ React.createElement('div', { className: 'dsub-row' },
130
+ React.createElement('span', { className: 'dsub-h' }, t('title')),
131
+ React.createElement('span', { className: 'dsub-sub' }, t('cardIntro')),
132
+ React.createElement('span', { style: { flex: 1 } }),
133
+ React.createElement('button', {
134
+ type: 'button',
135
+ className: 'dsub-mini',
136
+ onClick: () => setOpen(!open),
137
+ }, open ? t('hide') : t('show')),
138
+ ),
139
+ open ? React.createElement(SubsSection, props) : null,
140
+ )
141
+ }
142
+
105
143
  function SubsSection(props) {
106
144
  // Переводчик приходит от слота, потому что в его записи указан locale.
107
145
  const t = (props && props.t) || ((key) => key)
@@ -345,11 +383,62 @@ window.__ModuleLoader__.load({
345
383
  )
346
384
  }
347
385
 
386
+ // Карточка во вкладке «Плагины» — как карточки bash/agent-loop/web-search:
387
+ // заголовок с именем, описанием и шевроном, сворачивание, каёмка.
388
+ function PluginCard(props) {
389
+ const t = (props && props.t) || ((key) => key)
390
+ const [open, setOpen] = React.useState(false)
391
+ return React.createElement('li', {
392
+ className: 'dsub-card' + (open ? ' dsub-cardOpen' : ''),
393
+ },
394
+ React.createElement('button', {
395
+ type: 'button',
396
+ className: 'dsub-header',
397
+ onClick: () => setOpen(!open),
398
+ 'aria-expanded': open,
399
+ },
400
+ React.createElement('div', { className: 'dsub-headText' },
401
+ React.createElement('div', { className: 'dsub-name' }, t('title')),
402
+ React.createElement('div', { className: 'dsub-description' }, t('cardIntro')),
403
+ ),
404
+ React.createElement('svg', {
405
+ className: 'dsub-chevron' + (open ? ' dsub-chevronOpen' : ''),
406
+ width: 16, height: 16, viewBox: '0 0 16 16', fill: 'none',
407
+ },
408
+ React.createElement('path', {
409
+ d: 'M4 6l4 4 4-4', stroke: 'currentColor', 'stroke-width': 1.5,
410
+ 'stroke-linecap': 'round', 'stroke-linejoin': 'round',
411
+ }),
412
+ ),
413
+ ),
414
+ open ? React.createElement('div', { className: 'dsub-body' },
415
+ React.createElement(SubsSection, props),
416
+ ) : null,
417
+ )
418
+ }
419
+
348
420
  function registerSettings(ctx) {
349
421
  ctx.effect(() => ctx.locale.register(NS, { en, ru }), 'dsh-subscriptions: словари')
350
- // Подпись раздела рисует боковой список, а не наш компонент: props.t
351
- // туда не доходит, поэтому берём переводчик, привязанный к namespace.
422
+ // Подписи вне компонента берут переводчик, привязанный к namespace.
352
423
  const t = ctx.locale.bind(NS)
424
+ // Штатное место — вкладка «Плагины»: карточка со своим заголовком и
425
+ // сворачиванием вместо строки в боковом списке. Ключ регистрации обязан
426
+ // равняться пространству настроек, иначе вкладка молча не покажет слот.
427
+ let moved = false
428
+ try {
429
+ moved = !!ctx.slots.inject('settings.plugin.item', () => ctx.slots.register(
430
+ {
431
+ name: 'settings.plugin.item',
432
+ key: NS,
433
+ locale: NS,
434
+ inject: () => ({ ctx: ctx }),
435
+ },
436
+ PluginCard,
437
+ ))
438
+ } catch { moved = false }
439
+ if (moved) return
440
+ // Запасной путь для сборок без settings.plugin.item: прежний раздел,
441
+ // чтобы настройки не пропали.
353
442
  ctx.slots.inject('settings.section', () => ctx.slots.register(
354
443
  {
355
444
  name: 'settings.section',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-subscriptions",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Use ChatGPT Codex, Claude, Grok, and Antigravity subscriptions as DeepSeek Harness LLM providers via OAuth.",
5
5
  "license": "MIT",
6
6
  "type": "module",