dsh-ptc-plus 0.5.3 → 0.5.6
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.en.md +3 -3
- package/README.md +3 -3
- package/client.cjs +3326 -2881
- package/compiler-core.cjs +127 -127
- package/compiler-core.cjs.map +2 -2
- package/docs/README.md +1 -0
- package/docs/adr/0005-temporary-rejected-cell-edit-transport.md +2 -2
- package/docs/adr/0017-track-the-latest-dsh-public-surface.md +4 -4
- package/docs/architecture.md +1 -1
- package/docs/capability-planning-components.md +6 -6
- package/docs/capability-projection.md +1 -1
- package/docs/capability-surface.md +133 -0
- package/docs/client-ui.md +17 -15
- package/docs/client-visual-contract.md +7 -7
- package/docs/installation.md +14 -7
- package/docs/panel-concept.md +171 -0
- package/docs/publishing.md +1 -1
- package/docs/release-notes.md +1 -1
- package/docs/releases/v0.5.4.md +79 -0
- package/docs/releases/v0.5.5.md +41 -0
- package/docs/releases/v0.5.6.md +41 -0
- package/docs/runtime-reference.md +14 -0
- package/docs/verification.md +1 -1
- package/index.js +117 -30
- package/internal/binding-adoption.js +103 -11
- package/internal/capability-command-receipt.js +99 -15
- package/internal/capability-environment.js +1108 -348
- package/internal/capability-plan.js +18 -2
- package/internal/capability-policy.js +13 -0
- package/internal/capability-selection.js +330 -0
- package/internal/direct-surface-owner.js +17 -4
- package/internal/edit-transport-owner.js +3 -2
- package/internal/host-tool-sdk.js +17 -29
- package/internal/message-sources.js +21 -0
- package/internal/program-bindings.js +13 -4
- package/internal/runtime-bridge-owner.js +9 -9
- package/internal/runtime-config.js +10 -0
- package/internal/session-log-view.js +47 -5
- package/internal/settings-compat.js +6 -0
- package/internal/user-bindings-owner.js +20 -3
- package/package.json +45 -31
- package/src/client-authoring-view.js +7 -8
- package/src/client-capabilities-view.js +871 -948
- package/src/client-capability-sort.js +22 -9
- package/src/client-copy.js +116 -294
- package/src/client-settings-view.js +90 -33
- package/src/client-styles.js +67 -19
- package/src/client.js +46 -21
- package/internal/capability-delivery-proof.js +0 -70
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CONFIG_DEFAULTS, CONFIG_FIELDS, CONFIG_GROUPS, CONFIG_MODULES } from '../internal/config-spec.js'
|
|
2
2
|
import { CAPABILITY_CONFIGURATION_KEYS, capabilityProfileConfiguration, resolveConfig } from '../internal/runtime-config.js'
|
|
3
|
+
import { capabilityPolicyForConfig, capabilityPolicyFromRecord, changeCapabilityRule } from '../internal/capability-policy.js'
|
|
3
4
|
import { featureEnabled } from './client-feature-gates.js'
|
|
4
5
|
import { isHostIconComponent } from './client-host-compat.js'
|
|
5
6
|
import { capabilityPlanReason, createCapabilitySettingsViews } from './client-capabilities-view.js'
|
|
@@ -24,8 +25,8 @@ function settingsScrollGeometry(element) {
|
|
|
24
25
|
* action only while global bindings are eligible.
|
|
25
26
|
*/
|
|
26
27
|
export function createPtcSettingsView(React, deps) {
|
|
27
|
-
const { ActionButton, BindingsDialog, Modal, Select, useWorkbenchController, icons, inspectCapabilityPlans,
|
|
28
|
-
inspectCapabilityTargets, inspectCapabilityAllocation, CapabilityRefreshButton } = deps
|
|
28
|
+
const { ActionButton, BindingsDialog, Modal, Select, useWorkbenchController, icons, inspectCapabilityPlans,
|
|
29
|
+
inspectCapabilityTargets, inspectCapabilityAllocation, CapabilityRefreshButton, CapabilitySurface } = deps
|
|
29
30
|
const h = React.createElement
|
|
30
31
|
const enabledField = CONFIG_FIELDS.find(field => field.key === 'enabled')
|
|
31
32
|
|
|
@@ -44,13 +45,6 @@ export function createPtcSettingsView(React, deps) {
|
|
|
44
45
|
className: 'ptcPlusSettingsNavIcon' }, ...paths[section].map((d, key) => h('path', { key, d })))
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
function SearchIcon() {
|
|
48
|
-
return isHostIconComponent(icons.search) ? h(icons.search, { size: 16, 'aria-hidden': true })
|
|
49
|
-
: h('svg', { width: 16, height: 16, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor',
|
|
50
|
-
strokeWidth: 1.6, strokeLinecap: 'round', 'aria-hidden': true },
|
|
51
|
-
h('circle', { cx: 10.5, cy: 10.5, r: 6.5 }), h('path', { d: 'm16 16 5 5' }))
|
|
52
|
-
}
|
|
53
|
-
|
|
54
48
|
function NavigationArrow() {
|
|
55
49
|
return isHostIconComponent(icons.chevron) ? h(icons.chevron, { size: 12 })
|
|
56
50
|
: h('svg', { width: 12, height: 12, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor',
|
|
@@ -111,7 +105,7 @@ export function createPtcSettingsView(React, deps) {
|
|
|
111
105
|
: saved.invalid && draft === saved.settings ? h('p', { role: 'status', className: 'ptcPlusMessage' }, t('capabilities.savedStatisticsInvalid')) : null)
|
|
112
106
|
}
|
|
113
107
|
|
|
114
|
-
const { CapabilityWorkbench } = createCapabilitySettingsViews(React, {
|
|
108
|
+
const { CapabilityWorkbench } = createCapabilitySettingsViews(React, { Select, Modal })
|
|
115
109
|
|
|
116
110
|
function fieldInput(field, value, disabled, onChange, label) {
|
|
117
111
|
if (field.type === 'boolean') {
|
|
@@ -153,8 +147,6 @@ export function createPtcSettingsView(React, deps) {
|
|
|
153
147
|
const [plansError, setPlansError] = React.useState(null)
|
|
154
148
|
const [plansPending, setPlansPending] = React.useState(false)
|
|
155
149
|
const [plansObservedConfiguration, setPlansObservedConfiguration] = React.useState(null)
|
|
156
|
-
const [catalog, setCatalog] = React.useState(null)
|
|
157
|
-
const [catalogError, setCatalogError] = React.useState(null)
|
|
158
150
|
const [planRevision, setPlanRevision] = React.useState(0)
|
|
159
151
|
const [targets, setTargets] = React.useState(null)
|
|
160
152
|
const [targetsError, setTargetsError] = React.useState(null)
|
|
@@ -203,24 +195,6 @@ export function createPtcSettingsView(React, deps) {
|
|
|
203
195
|
})
|
|
204
196
|
return () => controller.abort()
|
|
205
197
|
}, [enabled, open, view, planRevision])
|
|
206
|
-
React.useEffect(() => {
|
|
207
|
-
if (!enabled) {
|
|
208
|
-
setCatalog(null)
|
|
209
|
-
setCatalogError(null)
|
|
210
|
-
return
|
|
211
|
-
}
|
|
212
|
-
if (!(open || view === 'page' || view === 'dialog') || !inspectCapabilityCatalog) return
|
|
213
|
-
const controller = new AbortController()
|
|
214
|
-
setCatalogError(null)
|
|
215
|
-
Promise.resolve().then(() => inspectCapabilityCatalog(controller.signal)).then(available => {
|
|
216
|
-
if (controller.signal.aborted) return
|
|
217
|
-
setCatalog(available)
|
|
218
|
-
}, error => {
|
|
219
|
-
if (controller.signal.aborted) return
|
|
220
|
-
setCatalogError(String(error?.message ?? error))
|
|
221
|
-
})
|
|
222
|
-
return () => controller.abort()
|
|
223
|
-
}, [enabled, open, view, planConfiguration, planRevision])
|
|
224
198
|
React.useEffect(() => {
|
|
225
199
|
if (!plansEnabled) {
|
|
226
200
|
setPlans(null)
|
|
@@ -340,6 +314,79 @@ export function createPtcSettingsView(React, deps) {
|
|
|
340
314
|
const fieldDisabled = field => unavailable
|
|
341
315
|
|| pending.has(field.key)
|
|
342
316
|
|| (field.key !== 'enabled' && !enabled)
|
|
317
|
+
/**
|
|
318
|
+
* The saved address's one writer.
|
|
319
|
+
*
|
|
320
|
+
* The capability surface states values, so a cell writes the value its address
|
|
321
|
+
* holds for that object; the rule chain is what answers the objects this address
|
|
322
|
+
* has not decided one by one. The receipt the surface shows is the record this
|
|
323
|
+
* call wrote, named the way every other capability write names one.
|
|
324
|
+
*
|
|
325
|
+
* The decision is merged into the policy the document holds when the write runs, not
|
|
326
|
+
* into the one this page last rendered: two cells changed before the settings
|
|
327
|
+
* snapshot republishes compose instead of the second rebuilding the policy from the
|
|
328
|
+
* older snapshot and dropping the first.
|
|
329
|
+
*/
|
|
330
|
+
const policyAtWrite = React.useRef(null)
|
|
331
|
+
const renderedPolicy = React.useRef(value.capabilityPolicy)
|
|
332
|
+
if (value.capabilityPolicy !== renderedPolicy.current) {
|
|
333
|
+
renderedPolicy.current = value.capabilityPolicy
|
|
334
|
+
policyAtWrite.current = null
|
|
335
|
+
}
|
|
336
|
+
// The newest published snapshot, for a write that runs after the render that made it. A
|
|
337
|
+
// queued write closes over its own render, and that snapshot may already be replaced by the
|
|
338
|
+
// time it composes, so the document it starts from is read from here.
|
|
339
|
+
const latestValue = React.useRef(value)
|
|
340
|
+
React.useEffect(() => { latestValue.current = value })
|
|
341
|
+
const writeSavedCapability = ({ id, dimension, selection }) => {
|
|
342
|
+
if (!updateCapabilityConfiguration) return Promise.reject(new Error(t('capabilities.configurationUnavailable')))
|
|
343
|
+
const field = CONFIG_FIELDS.find(candidate => candidate.key === 'capabilityPolicy')
|
|
344
|
+
const operation = writeTail.current.then(async () => {
|
|
345
|
+
setPending(current => new Set([...current, field.key]))
|
|
346
|
+
setCapabilityStatus(null)
|
|
347
|
+
let key = null
|
|
348
|
+
try {
|
|
349
|
+
// A configuration that saved no policy has only a synthesized document, whose bottom
|
|
350
|
+
// layer the capability-management switch shaped. Writing that document would freeze the
|
|
351
|
+
// switch's answer into the record and turn untouched cells into it, so a first saved
|
|
352
|
+
// write starts from the words the record itself wrote: the declared defaults plus the
|
|
353
|
+
// layers the override record holds, which `capabilityPolicyForConfig` folds into a
|
|
354
|
+
// document while the synthesis switches are neutral. The resolved config always carries
|
|
355
|
+
// a policy string, so the provenance marker — not the field's absence — decides which
|
|
356
|
+
// document is the record's.
|
|
357
|
+
const document = () => policyAtWrite.current
|
|
358
|
+
?? (latestValue.current.capabilityPolicySaved === true
|
|
359
|
+
? capabilityPolicyForConfig(latestValue.current) : capabilityPolicyFromRecord(latestValue.current))
|
|
360
|
+
const policy = changeCapabilityRule(document(), id, dimension, selection)
|
|
361
|
+
const written = JSON.stringify(policy)
|
|
362
|
+
key = await updateSetting(field.key, written)
|
|
363
|
+
// A null answer means either "this scope is not writable" or "the record already holds
|
|
364
|
+
// this value". The second is not a refusal: the decision the reader made is the state
|
|
365
|
+
// the record is in, so nothing is written and nothing failed.
|
|
366
|
+
if (key === null) {
|
|
367
|
+
if (latestValue.current.capabilityPolicy !== written) throw new Error(t('capabilities.configurationUnavailable'))
|
|
368
|
+
key = 'status.applied'
|
|
369
|
+
}
|
|
370
|
+
if (key === 'status.applied') policyAtWrite.current = policy
|
|
371
|
+
} catch (error) {
|
|
372
|
+
recordStatus({ key: 'status.failed', fieldKey: field.key,
|
|
373
|
+
params: { error: error instanceof Error ? error.message : String(error) } })
|
|
374
|
+
throw error
|
|
375
|
+
} finally {
|
|
376
|
+
setPending(current => {
|
|
377
|
+
const next = new Set(current)
|
|
378
|
+
next.delete(field.key)
|
|
379
|
+
return next
|
|
380
|
+
})
|
|
381
|
+
}
|
|
382
|
+
// The settings page keeps stating its own outcome; the cell states the refusal.
|
|
383
|
+
recordStatus({ key, fieldKey: field.key })
|
|
384
|
+
if (key !== 'status.applied') throw new Error(t('capabilities.configurationUnavailable'))
|
|
385
|
+
return { id, dimension, selection }
|
|
386
|
+
})
|
|
387
|
+
writeTail.current = operation.catch(() => {})
|
|
388
|
+
return operation
|
|
389
|
+
}
|
|
343
390
|
const renderField = key => {
|
|
344
391
|
const field = CONFIG_FIELDS.find(candidate => candidate.key === key)
|
|
345
392
|
if (field === undefined) return null
|
|
@@ -381,7 +428,7 @@ export function createPtcSettingsView(React, deps) {
|
|
|
381
428
|
h('table', null, h('thead', null, h('tr', null,
|
|
382
429
|
...['member', 'selection', 'reason', 'coverage'].map(key => h('th', { key }, t(`capabilities.${key}`))))),
|
|
383
430
|
h('tbody', null, ...plan.effective.entries.map(entry => h('tr', { key: entry.id },
|
|
384
|
-
h('td', null, entry.id), h('td', null, t(`capabilities.${entry.selection}`)),
|
|
431
|
+
h('td', null, entry.id), h('td', null, t(`capabilities.word.${entry.selection}`)),
|
|
385
432
|
h('td', null, capabilityPlanReason(t, entry)),
|
|
386
433
|
h('td', null, entry.evidence ? `${entry.evidence.used}/${entry.evidence.eligible} (${entry.evidence.scope})` : '—')))))))) : null
|
|
387
434
|
|
|
@@ -428,12 +475,22 @@ export function createPtcSettingsView(React, deps) {
|
|
|
428
475
|
onChange: event => persist(CONFIG_FIELDS.find(field => field.key === 'capabilityContextEnabled'), event.target.checked) }))) : heading,
|
|
429
476
|
...(group.key === 'capabilities' ? [
|
|
430
477
|
h(CapabilityWorkbench, { key: 'capability-workbench', id: `${groupIdPrefix}-capability-workbench`,
|
|
431
|
-
value, configurationReady: snapshot.status === 'ready',
|
|
478
|
+
value, configurationReady: snapshot.status === 'ready', plans: plansEnabled ? plans : null, plansError, plansPending,
|
|
432
479
|
plansStale: plansObservedConfiguration !== planConfiguration,
|
|
433
480
|
disabled: key => fieldDisabled({ key }), onChange: persist,
|
|
434
481
|
onReload: () => setPlanRevision(current => current + 1), t, renderField, renderPlans, renderRefresh,
|
|
435
482
|
selectedSessionId: refreshSessionId, onSessionSelect: setRefreshSessionId,
|
|
436
|
-
allocation, allocationError, allocationPending, saving: [...pending].some(key => CAPABILITY_CONFIGURATION_KEYS.includes(key) || key === 'capabilityProfiles'), saveStatus: capabilityStatus, configurationWritable: !unavailable && enabled, onApplyConfiguration: updateCapabilityConfiguration ? persistConfiguration : undefined
|
|
483
|
+
allocation, allocationError, allocationPending, saving: [...pending].some(key => CAPABILITY_CONFIGURATION_KEYS.includes(key) || key === 'capabilityProfiles'), saveStatus: capabilityStatus, configurationWritable: !unavailable && enabled, onApplyConfiguration: updateCapabilityConfiguration ? persistConfiguration : undefined,
|
|
484
|
+
// The one capability surface, mounted with the address this entrance fixes:
|
|
485
|
+
// the new-session default. Its row set is the Host's own declaration — the
|
|
486
|
+
// process-scope object set, not a session's full declared face (capability-surface
|
|
487
|
+
// §8.9), because this entrance names no session — so an observation target changes
|
|
488
|
+
// only what the observation reads, never these rows, and a target whose supply
|
|
489
|
+
// cannot be read leaves the rows and their controls in place.
|
|
490
|
+
surface: CapabilitySurface ? h(CapabilitySurface, { key: 'capability-surface', entrance: 'settings', inline: true,
|
|
491
|
+
t, writable: !unavailable && enabled, revision: planConfiguration,
|
|
492
|
+
onReload: () => setPlanRevision(current => current + 1),
|
|
493
|
+
savedCommands: { run: writeSavedCapability } }) : null })]
|
|
437
494
|
: fields.map(renderField)))
|
|
438
495
|
}
|
|
439
496
|
|
package/src/client-styles.js
CHANGED
|
@@ -26,12 +26,12 @@ const CLIENT_CSS = `
|
|
|
26
26
|
.ptcPlusGroup+.ptcPlusGroup{margin-top:20px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l2)}.ptcPlusGroupTitle{margin:0;padding:8px 0;color:var(--dsw-alias-label-secondary);font-size:13px;font-weight:600;letter-spacing:0;line-height:20px}.ptcPlusGroup[data-experimental=true]{padding:14px 16px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-warn-primary,#a15c00) 25%,var(--dsw-alias-border-l2));border-radius:12px;background:var(--dsw-alias-bg-layer-3)}.ptcPlusGroupTitle[data-experimental-label]{display:flex;align-items:center;gap:8px}.ptcPlusGroupTitle[data-experimental-label]::after{content:attr(data-experimental-label);padding:2px 7px;border-radius:999px;background:color-mix(in srgb,var(--dsw-alias-state-warn-primary,#a15c00) 12%,transparent);color:color-mix(in srgb,var(--dsw-alias-state-warn-primary,#a15c00) 60%,var(--dsw-alias-label-primary));font-size:10px;font-weight:600;line-height:15px}.ptcPlusRow{display:flex;align-items:center;gap:12px;min-height:48px;border-top:0.5px solid var(--dsw-alias-border-l2)}.ptcPlusGroupTitle+.ptcPlusRow{border-top:0}.ptcPlusMain{flex:1;min-width:0}.ptcPlusLabel{font-size:13px;font-weight:500;line-height:1.5}.ptcPlusDetail,.ptcPlusMessage{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;overflow-wrap:anywhere}.ptcPlusInput{box-sizing:border-box;min-width:72px;width:140px;height:34px;padding:0 12px;border:0.5px solid var(--dsw-alias-border-l4);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:1.5}.ptcPlusInput:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.ptcPlusCheck{appearance:none;position:relative;flex:0 0 auto;box-sizing:border-box;width:36px;height:20px;margin:0;padding:2px;border:0;border-radius:999px;corner-shape:round;background:var(--dsw-alias-border-l3);cursor:pointer}.ptcPlusCheck:checked{background:var(--dsw-alias-brand-primary)}.ptcPlusCheck::before{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;corner-shape:round;background:var(--dsw-alias-switch-thumb);content:'';transition:transform 120ms ease}.ptcPlusCheck:checked::before{background:var(--dsw-alias-label-primary-foreground);transform:translateX(16px)}.ptcPlusCheck:disabled{cursor:default;opacity:.5}.ptcPlusCheck:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}
|
|
27
27
|
.ptcPlusSettingsLayout .ptcPlusGroup[data-experimental=true]{background:var(--dsw-alias-bg-layer-3);border-color:var(--dsw-alias-border-l2)}.ptcPlusCapabilityHead{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.ptcPlusCapabilityHead .ptcPlusGroupTitle{margin:0}.ptcPlusCapabilityManagement{display:flex;align-items:center;gap:8px;font-size:12px}
|
|
28
28
|
.ptcPlusCapabilityWorkbench{container:ptcPlusCapabilities/inline-size;min-width:0;font-size:13px}
|
|
29
|
-
.ptcPlusCapabilityTabs{display:flex;gap:8px;overflow:auto;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityTabs button{appearance:none;flex:none;padding:10px 14px;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;text-align:center;cursor:pointer}.ptcPlusCapabilityTabs [aria-selected=true]{border-bottom-color:var(--dsw-alias-state-business-primary,#4d6bfe);color:var(--dsw-alias-state-business-primary,#4d6bfe)}.ptcPlusCapabilityPane{padding-top:16px;min-width:0}.ptcPlusCapabilityPane[hidden],.ptcPlusContextContent>[hidden]{display:none}
|
|
29
|
+
.ptcPlusCapabilityTabs{display:flex;gap:8px;overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityTabs button{appearance:none;flex:none;padding:10px 14px;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;text-align:center;cursor:pointer}.ptcPlusCapabilityTabs [aria-selected=true]{border-bottom-color:var(--dsw-alias-state-business-primary,#4d6bfe);color:var(--dsw-alias-state-business-primary,#4d6bfe)}.ptcPlusCapabilityPane{padding-top:16px;min-width:0}.ptcPlusCapabilityPane[hidden],.ptcPlusContextContent>[hidden]{display:none}
|
|
30
30
|
.ptcPlusTaskHead{display:flex;flex-wrap:wrap;align-items:center;gap:10px}.ptcPlusTaskHead h4{margin:0;flex:1;font-size:16px}.ptcPlusCapabilityManagement{display:flex;align-items:center;gap:8px;font-size:12px}.ptcPlusCapabilitySaveState{color:var(--dsw-alias-label-secondary);font-size:11px}.ptcPlusCapabilityPane>.ptcPlusDetail{margin:8px 0 16px}
|
|
31
|
-
|
|
32
|
-
.ptcPlusCapabilityFilter{display:flex;flex-direction:column;min-width:0;gap:6px;font-size:12px;color:var(--dsw-alias-label-secondary)}.ptcPlusCapabilityFilter>.ptcPlusSelectTrigger{width:100%;max-width:100%;font-size:12px}.
|
|
33
|
-
.
|
|
34
|
-
|
|
31
|
+
|
|
32
|
+
.ptcPlusCapabilityFilter{display:flex;flex-direction:column;min-width:0;gap:6px;font-size:12px;color:var(--dsw-alias-label-secondary)}.ptcPlusCapabilityFilter>.ptcPlusSelectTrigger{width:100%;max-width:100%;font-size:12px}.ptcPlusCapabilityResultLine,.ptcPlusActiveFilters{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;margin:8px 0;color:var(--dsw-alias-label-secondary);font-size:11px}.ptcPlusCapabilityLink{appearance:none;padding:4px 0;border:0;background:transparent;color:var(--dsw-alias-state-business-primary,#4d6bfe);font:inherit;font-size:12px;cursor:pointer}.ptcPlusCapabilityLink:disabled{opacity:.5;cursor:default}
|
|
33
|
+
.ptcPlusCapabilityColumns,.ptcPlusCapabilityItem{display:grid;grid-template-columns:minmax(140px,1.6fr) 54px minmax(65px,.75fr) minmax(92px,1fr) minmax(104px,1fr);align-items:center;gap:10px;padding:10px 12px}.ptcPlusCapabilityColumns{color:var(--dsw-alias-label-tertiary);font-size:11px;background:var(--dsw-alias-bg-layer-2)}.ptcPlusCapabilityItem{box-sizing:border-box;min-height:54px;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityItem:last-child{border-bottom:0}.ptcPlusCapabilityItem[data-selected=true]{background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 6%,transparent)}.ptcPlusCapabilityItem:not([data-selected=true]){cursor:pointer}.ptcPlusCapabilityItem:not([data-selected=true]):hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusCapabilityItem>*{min-width:0}.ptcPlusCapabilityIdentity{display:flex;flex-direction:column;gap:3px;min-width:0}.ptcPlusCapabilityIdentity code{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px;overflow-wrap:anywhere}.ptcPlusCapabilityIdentityText{display:flex;flex-direction:column;justify-content:center;gap:3px;min-width:0;min-height:32px}.ptcPlusCapabilityIdentityText>span,.ptcPlusCapabilityIdentityText>code{display:block;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ptcPlusCapabilitySource{color:var(--dsw-alias-label-secondary);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ptcPlusCapabilityBadge{justify-self:start;padding:2px 6px;border-radius:4px;background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 8%,transparent);color:var(--dsw-alias-state-business-primary,#4d6bfe);font-size:10px;line-height:17px}.ptcPlusCapabilityBadge[data-kind=skill]{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2)}.ptcPlusCapabilityWorkbench button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}
|
|
34
|
+
|
|
35
35
|
.ptcPlusPromptText{display:flex;flex-direction:column;gap:12px;min-width:0}
|
|
36
36
|
.ptcPlusPromptHeader{display:flex;align-items:flex-start;gap:8px;min-width:0}
|
|
37
37
|
.ptcPlusPromptHeaderIcon{display:inline-flex;align-items:center;justify-content:center;flex:none;width:20px;height:20px;color:var(--dsw-alias-label-secondary)}
|
|
@@ -100,8 +100,8 @@ const CLIENT_CSS = `
|
|
|
100
100
|
.ptcPlusConfigurationProfiles{display:grid;grid-template-columns:minmax(180px,34%) minmax(0,1fr);gap:18px;margin-top:14px;min-width:0}.ptcPlusConfigurationLibrary,.ptcPlusConfigurationDetail{min-width:0;padding:14px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px}.ptcPlusConfigurationProfiles h4{margin:0 0 12px;font-size:15px}.ptcPlusConfigurationList{max-height:320px;overflow:auto;overscroll-behavior:contain}.ptcPlusConfigurationChoice{appearance:none;display:block;width:100%;padding:12px 10px;border:0;border-left:3px solid transparent;border-radius:5px;background:transparent;color:inherit;font:inherit;text-align:start;overflow-wrap:anywhere;cursor:pointer}.ptcPlusConfigurationChoice[aria-pressed=true]{border-left-color:var(--dsw-alias-state-business-primary,#4d6bfe);background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 6%,transparent)}.ptcPlusConfigurationSave.ptcPlusButton{width:100%;margin-top:14px;border:1px dashed var(--dsw-alias-border-l2);justify-content:center}.ptcPlusConfigurationSave::before{content:'+';font-size:20px;line-height:16px}.ptcPlusConfigurationLibraryActions{display:flex;align-items:start;gap:8px;margin-top:10px}.ptcPlusConfigurationLibraryActions>.ptcPlusButton{flex:1}.ptcPlusConfigurationSummary{margin-top:14px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;overflow:hidden}.ptcPlusConfigurationSummaryRow{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px;padding:10px;font-size:12px;border-bottom:1px solid var(--dsw-alias-border-l2);overflow-wrap:anywhere}.ptcPlusConfigurationSummaryRow:last-child{border:0}.ptcPlusConfigurationSummaryRow>span:first-child{color:var(--dsw-alias-label-secondary)}.ptcPlusConfigurationAction{display:flex;flex-direction:column;gap:10px;margin-top:14px}.ptcPlusConfigurationAction .ptcPlusInput{width:100%;box-sizing:border-box}.ptcPlusTaskFeedback{grid-column:1/-1;margin:8px 0;font-size:12px;overflow-wrap:anywhere}
|
|
101
101
|
.ptcPlusCapabilityEvidenceTable{max-height:480px;overflow:auto}.ptcPlusCapabilityEvidenceTable table,.ptcPlusCapabilityPlans table{width:100%;table-layout:fixed;border-collapse:collapse;font-size:12px}.ptcPlusCapabilityEvidenceTable th,.ptcPlusCapabilityEvidenceTable td,.ptcPlusCapabilityPlans th,.ptcPlusCapabilityPlans td{padding:10px;text-align:start;border-bottom:1px solid var(--dsw-alias-border-l2);overflow-wrap:anywhere}.ptcPlusCapabilityEvidenceTable th{color:var(--dsw-alias-label-tertiary);font-weight:500;background:var(--dsw-alias-bg-layer-2)}.ptcPlusCapabilityEvidenceTable progress{display:block;width:100%;height:5px;margin-top:5px;accent-color:var(--dsw-alias-state-business-primary,#4d6bfe)}.ptcPlusCapabilityStatistics .ptcPlusInput{width:100%}.ptcPlusCapabilityStatistics .ptcPlusBindingFields{margin-top:10px}
|
|
102
102
|
.ptcPlusStatisticsParameters{margin-top:12px}.ptcPlusStatisticsParameters h5{margin:0;font-size:12px;line-height:20px;font-weight:600}.ptcPlusStatisticsObservationHeading{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 12px;min-width:0;line-height:20px}.ptcPlusStatisticsObservationHeading>span:first-child{flex:none}.ptcPlusStatisticsObservationHint{flex:1 1 260px;min-width:0;color:var(--dsw-alias-label-tertiary);white-space:normal;overflow-wrap:anywhere}
|
|
103
|
-
@container ptcPlusCapabilities (max-width:760px){.ptcPlusCapabilityColumns{display:flex;flex-wrap:wrap;gap:4px 12px}.ptcPlusCapabilityItem{grid-template-columns:minmax(0,1fr) auto;gap:8px 12px}.ptcPlusCapabilityIdentity{grid-column:1}.ptcPlusCapabilityBadge{grid-column:2}.ptcPlusCapabilitySource{grid-column:1;grid-row:2}.
|
|
104
|
-
@container ptcPlusCapabilities (max-width:480px){.ptcPlusCapabilityTabs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));overflow:visible}.ptcPlusCapabilityTabs button{min-width:0;padding:8px;overflow-wrap:anywhere}.ptcPlusCapabilityIdentity{grid-column:1/3}.ptcPlusCapabilityBadge{grid-row:2}.
|
|
103
|
+
@container ptcPlusCapabilities (max-width:760px){.ptcPlusCapabilityColumns{display:flex;flex-wrap:wrap;gap:4px 12px}.ptcPlusCapabilityItem{grid-template-columns:minmax(0,1fr) auto;gap:8px 12px}.ptcPlusCapabilityIdentity{grid-column:1}.ptcPlusCapabilityBadge{grid-column:2}.ptcPlusCapabilitySource{grid-column:1;grid-row:2}.ptcPlusContextLayout{grid-template-columns:minmax(100px,27%) minmax(0,1fr);gap:12px}.ptcPlusContextNavigation button{padding:10px 6px}.ptcPlusConfigurationProfiles{grid-template-columns:1fr}.ptcPlusConfigurationList{max-height:220px}}
|
|
104
|
+
@container ptcPlusCapabilities (max-width:480px){.ptcPlusCapabilityTabs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));overflow:visible}.ptcPlusCapabilityTabs button{min-width:0;padding:8px;overflow-wrap:anywhere}.ptcPlusCapabilityIdentity{grid-column:1/3}.ptcPlusCapabilityBadge{grid-row:2}.ptcPlusCapabilityStatistics .ptcPlusBindingFields{grid-template-columns:minmax(0,1fr)}.ptcPlusContextLayout{grid-template-columns:1fr;gap:8px}.ptcPlusContextNavigation{flex-direction:column;border-right:0;border-bottom:1px solid var(--dsw-alias-border-l2);padding:0 0 8px}.ptcPlusContextNavigation button{min-width:0;font-size:12px}.ptcPlusContextNavigation button>span{max-width:100%;white-space:normal;overflow-wrap:anywhere}.ptcPlusContextNavigation button>span:first-child{flex:1;min-width:0}.ptcPlusContextState{flex:none;text-align:end}.ptcPlusCapabilitySaveState{flex-basis:100%}}
|
|
105
105
|
.ptcPlusFooter{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:8px}.ptcPlusButton{appearance:none;display:inline-flex;align-items:center;justify-content:center;gap:5px;min-height:32px;padding:4px 14px;border:0.5px solid var(--dsw-alias-border-l3);border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;font-size:13px;line-height:1.5;transition:color .16s ease,border-color .16s ease,background-color .16s ease}.ptcPlusButton:hover:not(:disabled){border-color:var(--dsw-alias-label-dimmed);color:var(--dsw-alias-label-primary)}.ptcPlusButton[data-kind=primary]{background:var(--dsw-alias-label-primary);border-color:transparent;color:var(--dsw-alias-bg-layer-3)}.ptcPlusButton[data-kind=primary]:hover:not(:disabled){background:var(--dsw-alias-label-primary-dimmed);border-color:transparent;color:var(--dsw-alias-bg-layer-3)}.ptcPlusButton[data-kind=ghost]{border-color:transparent}.ptcPlusButton[data-kind=ghost]:hover:not(:disabled){border-color:var(--dsw-alias-border-l3)}.ptcPlusButton[data-kind=danger]{color:var(--dsw-alias-state-error-primary)}.ptcPlusButton[data-kind=danger]:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.ptcPlusButton:disabled,.ptcPlusInput:disabled,.ptcPlusCheck:disabled{cursor:not-allowed;opacity:.4}
|
|
106
106
|
.ptcPlusSettingAction{padding:4px 0 12px}
|
|
107
107
|
.ptcPlusSettingsModal.ptcPlusSettingsModal{container:ptcPlusSettingsModal/size;box-sizing:border-box;width:min(1440px,calc(100vw - 48px));height:min(1040px,calc(100dvh - 48px));max-width:100%;max-height:100%;min-height:0;display:flex;flex-direction:column;padding:0;gap:0;overflow:hidden;border-radius:16px}
|
|
@@ -192,30 +192,79 @@ const CLIENT_CSS = `
|
|
|
192
192
|
.ptcPlusFallbackModalHead{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px}.ptcPlusFallbackModalHead h2{margin:0;font-size:17px;line-height:24px}
|
|
193
193
|
|
|
194
194
|
.ptcPlusCapabilityCommandNotice{box-sizing:border-box;min-width:0;margin:8px 0;padding:0;border:0;background:transparent;color:var(--dsw-alias-label-secondary);font:13px/20px var(--dsw-font-family,system-ui,sans-serif);overflow-wrap:anywhere}.ptcPlusCapabilityCommandNotice[data-state=error]{color:var(--dsw-alias-state-error-primary)}
|
|
195
|
+
.ptcPlusCapabilityCommandNotice[data-kind=writes]{display:flex;flex-direction:column;gap:6px;margin:8px 0;padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary)}
|
|
196
|
+
.ptcPlusCapabilityCommandNoticeHead{margin:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}
|
|
197
|
+
.ptcPlusCapabilityCommandNoticeList{display:flex;flex-direction:column;gap:4px;margin:0;padding:0;list-style:none}
|
|
198
|
+
.ptcPlusCapabilityCommandNoticeRow{color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px;overflow-wrap:anywhere}
|
|
195
199
|
|
|
196
|
-
.ptcPlusCapabilityReceipt{box-sizing:border-box;min-width:0;margin:8px 0;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:13px/20px var(--dsw-font-family,system-ui,sans-serif);overflow-wrap:anywhere}.ptcPlusCapabilityReceiptHead{display:flex;align-items:center;gap:12px;justify-content:space-between}.ptcPlusCapabilityReceiptHead>code{min-width:0;font:12px/18px var(--ds-font-family-code,ui-monospace,SFMono-Regular,Consolas,monospace);font-weight:500}.ptcPlusCapabilityReceiptState{flex:none;font-size:11px;color:var(--dsw-alias-label-secondary)}.ptcPlusCapabilityReceiptState[data-state=error]{color:var(--dsw-alias-state-error-primary)}.ptcPlusCapabilityReceipt p{margin:6px 0 0}.ptcPlusCapabilityReceiptSummary{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.ptcPlusCapabilityReceipt details{margin-top:8px}.ptcPlusCapabilityReceipt summary{width:fit-content;color:var(--dsw-alias-label-secondary);font-size:12px;cursor:pointer}.ptcPlusCapabilityReceipt summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:2px}.ptcPlusCapabilityReceipt pre{box-sizing:border-box;max-height:280px;overflow:auto;overscroll-behavior:contain;margin:8px 0 0;padding:10px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;background:var(--dsw-alias-bg-layer-1);font:12px/18px var(--ds-font-family-code,ui-monospace,SFMono-Regular,Consolas,monospace);white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusCapabilityReceiptTable{max-height:320px;overflow:auto;overscroll-behavior:contain;margin-top:8px}.ptcPlusCapabilityReceipt table{width:100%;min-width:480px;table-layout:fixed;border-collapse:collapse;font:12px/18px var(--dsw-font-family,system-ui,sans-serif)}.ptcPlusCapabilityReceipt th,.ptcPlusCapabilityReceipt td{padding:8px;text-align:start;vertical-align:top;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityReceipt th{position:sticky;top:0;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font-weight:500}.ptcPlusCapabilityReceipt th:first-child{width:44%}.ptcPlusCapabilityReceipt td strong{display:block;font-weight:500}.ptcPlusCapabilityReceipt td small{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;margin-top:3px;color:var(--dsw-alias-label-secondary);font-size:11px}.ptcPlusAllocationEvidence,.ptcPlusConfigurationProfiles{min-width:0;margin-top:20px;padding-top:16px;border-top:1px solid var(--dsw-alias-border-l2)}.ptcPlusAllocationEvidence h4,.ptcPlusConfigurationProfiles h4{margin:0;font-size:14px}.ptcPlusAllocationMetrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:16px 0}.ptcPlusAllocationMetrics>div{display:flex;min-width:0;flex-direction:column;gap:4px;padding:12px;border-radius:8px;background:var(--dsw-alias-bg-layer-2)}.ptcPlusAllocationMetrics strong{font-size:18px;overflow-wrap:anywhere}.ptcPlusAllocationMetrics span{font-size:11px;color:var(--dsw-alias-label-secondary)}.ptcPlusAllocationEvidence progress{width:100%;height:6px;accent-color:var(--dsw-alias-brand-primary)}.ptcPlusCapabilityEvidenceTable{max-height:440px;overflow:auto;overscroll-behavior:contain;margin-top:12px}.ptcPlusCapabilityEvidenceTable table{width:100%;table-layout:fixed;border-collapse:collapse;font-size:12px}.ptcPlusCapabilityEvidenceTable td,.ptcPlusCapabilityEvidenceTable th{padding:10px 6px;text-align:start;overflow-wrap:anywhere;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityEvidenceTable th{color:var(--dsw-alias-label-secondary);font-weight:500}
|
|
200
|
+
.ptcPlusCapabilityReceipt{box-sizing:border-box;min-width:0;margin:8px 0;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:13px/20px var(--dsw-font-family,system-ui,sans-serif);overflow-wrap:anywhere}.ptcPlusCapabilityReceiptHead{display:flex;align-items:center;gap:12px;justify-content:space-between}.ptcPlusCapabilityReceiptHead>code{min-width:0;font:12px/18px var(--ds-font-family-code,ui-monospace,SFMono-Regular,Consolas,monospace);font-weight:500}.ptcPlusCapabilityReceiptState{flex:none;font-size:11px;color:var(--dsw-alias-label-secondary)}.ptcPlusCapabilityReceiptState[data-state=error]{color:var(--dsw-alias-state-error-primary)}.ptcPlusCapabilityReceipt p{margin:6px 0 0}.ptcPlusCapabilityReceiptSummary{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.ptcPlusCapabilityReceipt details{margin-top:8px}.ptcPlusCapabilityReceipt summary{width:fit-content;color:var(--dsw-alias-label-secondary);font-size:12px;cursor:pointer}.ptcPlusCapabilityReceipt summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:2px}.ptcPlusCapabilityReceipt pre{box-sizing:border-box;max-height:280px;overflow:auto;overscroll-behavior:contain;margin:8px 0 0;padding:10px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;background:var(--dsw-alias-bg-layer-1);font:12px/18px var(--ds-font-family-code,ui-monospace,SFMono-Regular,Consolas,monospace);white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusCapabilityReceiptTable{max-height:320px;overflow:auto;overscroll-behavior:contain;margin-top:8px}.ptcPlusCapabilityReceipt table{width:100%;min-width:480px;table-layout:fixed;border-collapse:collapse;font:12px/18px var(--dsw-font-family,system-ui,sans-serif)}.ptcPlusCapabilityReceipt th,.ptcPlusCapabilityReceipt td{padding:8px;text-align:start;vertical-align:top;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityReceipt th{position:sticky;top:0;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font-weight:500}.ptcPlusCapabilityReceipt th:first-child{width:44%}.ptcPlusCapabilityReceipt td strong{display:block;font-weight:500}.ptcPlusCapabilityReceipt td small{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;margin-top:3px;color:var(--dsw-alias-label-secondary);font-size:11px}.ptcPlusAllocationEvidence,.ptcPlusConfigurationProfiles{min-width:0;margin-top:20px;padding-top:16px;border-top:1px solid var(--dsw-alias-border-l2)}.ptcPlusAllocationEvidence h4,.ptcPlusConfigurationProfiles h4{margin:0;font-size:14px}.ptcPlusAllocationMetrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:16px 0}.ptcPlusAllocationMetrics>div{display:flex;min-width:0;flex-direction:column;gap:4px;padding:12px;border-radius:8px;background:var(--dsw-alias-bg-layer-2)}.ptcPlusAllocationMetrics strong{font-size:18px;overflow-wrap:anywhere}.ptcPlusAllocationMetrics span{font-size:11px;color:var(--dsw-alias-label-secondary)}.ptcPlusAllocationEvidence progress{width:100%;height:6px;accent-color:var(--dsw-alias-brand-primary)}.ptcPlusCapabilityEvidenceTable{max-height:440px;overflow:auto;overscroll-behavior:contain;margin-top:12px}.ptcPlusCapabilityEvidenceTable table{width:100%;table-layout:fixed;border-collapse:collapse;font-size:12px}.ptcPlusCapabilityEvidenceTable td,.ptcPlusCapabilityEvidenceTable th{padding:10px 6px;text-align:start;overflow-wrap:anywhere;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityEvidenceTable th{color:var(--dsw-alias-label-secondary);font-weight:500}
|
|
197
201
|
@container ptcPlusCapabilities (max-width:600px){.ptcPlusAllocationMetrics{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
|
198
202
|
|
|
199
203
|
.ptcPlusSessionCapabilityModal.ptcPlusSessionCapabilityModal{box-sizing:border-box;width:min(1180px,calc(100vw - 48px));height:min(800px,calc(100dvh - 48px));max-height:100%;max-width:100%;display:flex;flex-direction:column;gap:0;padding:0;border-radius:16px;overflow:hidden;background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-bg-base,#fff));color:var(--dsw-alias-label-primary,#18191c);font:13px/20px var(--dsw-font-family,system-ui,sans-serif)}
|
|
200
204
|
.ptcPlusSessionCapabilityModal>div{min-height:0}
|
|
201
|
-
.ptcPlusSessionCapabilityColumns.ptcPlusCapabilityColumns,.ptcPlusSessionCapabilityRow.ptcPlusCapabilityItem{grid-template-columns:minmax(140px,1.
|
|
205
|
+
.ptcPlusSessionCapabilityColumns.ptcPlusCapabilityColumns,.ptcPlusSessionCapabilityRow.ptcPlusCapabilityItem{grid-template-columns:minmax(140px,1.25fr) 58px minmax(70px,.6fr) minmax(88px,.62fr) minmax(112px,.85fr) minmax(96px,.7fr) minmax(118px,.85fr);gap:10px;padding:10px 12px}.ptcPlusSessionCapabilityColumns.ptcPlusSessionCapabilityColumns-8,.ptcPlusSessionCapabilityRow.ptcPlusSessionCapabilityRow-8{grid-template-columns:minmax(140px,1.25fr) 58px minmax(70px,.6fr) minmax(88px,.62fr) minmax(112px,.85fr) minmax(96px,.7fr) minmax(118px,.85fr) minmax(130px,.95fr)}.ptcPlusSessionCapabilityColumns.ptcPlusSessionCapabilityColumns-5,.ptcPlusSessionCapabilityRow.ptcPlusSessionCapabilityRow-5{grid-template-columns:minmax(160px,1.4fr) 70px minmax(90px,.8fr) minmax(120px,.9fr) minmax(150px,1.1fr)}
|
|
202
206
|
.ptcPlusSessionCapabilityColumns{position:sticky;top:0;z-index:1;border-bottom:1px solid var(--dsw-alias-border-l2)}
|
|
203
|
-
.
|
|
207
|
+
.ptcPlusSessionCapabilityMessage{box-sizing:border-box;margin:0;padding:16px 24px;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;overflow-wrap:anywhere}
|
|
204
208
|
.ptcPlusSessionCapabilityHead{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:18px 24px;border-bottom:1px solid var(--dsw-alias-border-l2)}
|
|
205
209
|
.ptcPlusSessionCapabilityHead h2{margin:0;font-size:18px;line-height:26px}.ptcPlusSessionCapabilityHead p{margin:2px 0 0;color:var(--dsw-alias-label-secondary);font-size:12px;overflow-wrap:anywhere}
|
|
206
|
-
.ptcPlusSessionCapabilityToolbar{display:grid;grid-template-columns:minmax(180px,1.6fr) repeat(3,minmax(120px,1fr));gap:10px;align-items:end;padding:12px 24px;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusSessionCapabilityToolbar .ptcPlusCapabilityFilter{min-width:0}.ptcPlusSessionCapabilityToolbar .ptcPlusSearch{min-width:0}
|
|
207
|
-
.
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
210
|
+
.ptcPlusSessionCapabilityToolbar{display:grid;grid-template-columns:minmax(180px,1.6fr) repeat(3,minmax(120px,1fr));gap:10px;align-items:end;padding:12px 24px;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusSessionCapabilityToolbar .ptcPlusCapabilityFilter{min-width:0}.ptcPlusSessionCapabilityToolbar .ptcPlusSearch{min-width:0}.ptcPlusSessionCapabilityGroup h3{margin:0;padding:10px 12px 6px;color:var(--dsw-alias-label-secondary);font-size:11px;font-weight:600}.ptcPlusSessionCapabilityRow{box-sizing:border-box;min-height:54px;width:100%;border-left:3px solid transparent;font-size:12px}.ptcPlusSessionCapabilityName{min-width:0;color:var(--dsw-alias-label-primary);font-size:13px;overflow-wrap:anywhere}.ptcPlusSessionCapabilityRow button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.ptcPlusSessionCapabilityTable{min-width:0}.ptcPlusBindingGroup{margin-top:6px;padding-top:4px;border-top:1px solid var(--dsw-alias-border-l2)}.ptcPlusBindingGroup .ptcPlusBindingToggle{appearance:none;flex:none;padding:4px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:11px;cursor:pointer}.ptcPlusBindingGroup .ptcPlusBindingToggle[data-kind=use]{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary)}.ptcPlusBindingGroup .ptcPlusBindingToggle[data-kind=disabled]{color:var(--dsw-alias-label-secondary);cursor:default}.ptcPlusBindingGroup .ptcPlusBindingToggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.ptcPlusBindingGroup .ptcPlusBindingToggle:disabled{cursor:default;opacity:.55}.ptcPlusBindingGroup .ptcPlusBindingToggle[aria-busy=true]{cursor:progress;opacity:.75}.ptcPlusSessionCapabilityFooter{display:flex;flex:none;align-items:center;justify-content:flex-end;gap:10px;padding:12px 24px;border-top:1px solid var(--dsw-alias-border-l2)}.ptcPlusSessionCapabilityFooter [role=status]{flex:0 1 auto;min-width:0;margin-right:auto;max-height:40px;overflow-y:auto;overscroll-behavior:contain;font-size:12px;overflow-wrap:anywhere}.ptcPlusSessionCapabilityFooter button{flex:none}
|
|
211
|
+
.ptcPlusSessionCapabilityList{flex:1 1 0;min-width:0;min-height:0;padding:0;overflow:auto;overscroll-behavior:contain}
|
|
212
|
+
.ptcPlusSessionCapabilitySaved{font-size:12px;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere}
|
|
213
|
+
.ptcPlusSessionCapabilityAvailability,.ptcPlusSessionCapabilityDisclosure{display:flex;flex-wrap:nowrap;align-items:center;gap:6px;min-width:0}
|
|
214
|
+
.ptcPlusSessionCapabilityAvailability .ptcPlusSelectTrigger,.ptcPlusSessionCapabilityDisclosure .ptcPlusSelectTrigger{flex:1 1 0;min-width:0;width:auto}
|
|
215
|
+
.ptcPlusSessionCapabilitySavedDisclosure{font-size:12px;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere}
|
|
216
|
+
.ptcPlusSessionCapabilitySaved,.ptcPlusSessionCapabilitySavedDisclosure{min-width:0;overflow:hidden}.ptcPlusSessionCapabilitySavedDisclosure .ptcPlusSelectTrigger,.ptcPlusSessionCapabilitySaved .ptcPlusSelectTrigger{width:100%;min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
217
|
+
.ptcPlusSessionCapabilityReceipt{font-size:11px;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere}
|
|
218
|
+
.ptcPlusSessionCapabilityAddresses{margin:2px 0 0;color:var(--dsw-alias-label-secondary);font-size:12px;overflow-wrap:anywhere}
|
|
219
|
+
.ptcPlusSessionCapabilityRow[data-session-state=enabled]{border-left-color:var(--dsw-alias-state-success-primary,#12a150)}.ptcPlusSessionCapabilityRow[data-session-state=use]{border-left-color:var(--dsw-alias-state-success-primary,#12a150)}.ptcPlusSessionCapabilityRow[data-session-state=automatic]{border-left-color:var(--dsw-alias-state-business-primary,#4d6bfe)}.ptcPlusSessionCapabilityRow[data-session-state=closed]{border-left-color:var(--dsw-alias-state-error-primary,#e5484d)}.ptcPlusSessionCapabilityRow[data-session-state=damaged]{border-left-color:var(--dsw-alias-state-error-primary,#e5484d)}.ptcPlusSessionCapabilityRow[data-session-state=inherit]{border-left-color:var(--dsw-alias-border-l2)}.ptcPlusSessionCapabilityRow[data-session-state=skip]{border-left-color:var(--dsw-alias-border-l2)}
|
|
220
|
+
.ptcPlusSessionCapabilityRow[data-session-state=closed] .ptcPlusSessionCapabilityName,.ptcPlusSessionCapabilityRow[data-session-state=closed] .ptcPlusCapabilitySource,.ptcPlusSessionCapabilityRow[data-session-state=skip] .ptcPlusSessionCapabilityName{opacity:.6}
|
|
221
|
+
.ptcPlusSessionStateMark{flex:none;box-sizing:border-box;width:9px;height:9px;border-radius:50%;border:1.5px solid var(--dsw-alias-label-tertiary);background:transparent}
|
|
222
|
+
.ptcPlusSessionCapabilityAvailability[data-state=enabled] .ptcPlusSessionStateMark,.ptcPlusSessionCapabilityAvailability[data-state=use] .ptcPlusSessionStateMark{border-color:var(--dsw-alias-state-success-primary,#12a150);background:var(--dsw-alias-state-success-primary,#12a150)}
|
|
223
|
+
.ptcPlusSessionCapabilityAvailability[data-state=automatic] .ptcPlusSessionStateMark{border-color:var(--dsw-alias-state-business-primary,#4d6bfe);background:var(--dsw-alias-state-business-primary,#4d6bfe)}
|
|
224
|
+
.ptcPlusSessionCapabilityAvailability[data-state=closed] .ptcPlusSessionStateMark,.ptcPlusSessionCapabilityAvailability[data-state=damaged] .ptcPlusSessionStateMark{border-color:var(--dsw-alias-state-error-primary,#e5484d);background:linear-gradient(135deg,transparent 42%,var(--dsw-alias-state-error-primary,#e5484d) 42% 58%,transparent 58%)}
|
|
225
|
+
/* A cell states its state with the control it owns: the trigger keeps the label colour and
|
|
226
|
+
carries a tinted fill and border, and a word-only cell states the same state as a chip. The
|
|
227
|
+
state's own colour never reaches the text, and the mark plus the word still carry the state on
|
|
228
|
+
their own, so the difference does not depend on a tint alone. The secondary label colour below
|
|
229
|
+
states precedence (a layer above this cell decided, not this cell), not a state. */
|
|
230
|
+
.ptcPlusSessionCapabilityAvailability[data-state=enabled] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilityAvailability[data-state=use] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilitySaved[data-state=enabled] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilityAvailability[data-state=use] .ptcPlusBindingToggle{border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary,#12a150) 42%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-success-primary,#12a150) 10%,transparent)}
|
|
231
|
+
.ptcPlusSessionCapabilityAvailability[data-state=automatic] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilitySaved[data-state=automatic] .ptcPlusSelectTrigger{border-color:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 42%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 10%,transparent)}
|
|
232
|
+
.ptcPlusSessionCapabilityAvailability[data-state=closed] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilityAvailability[data-state=damaged] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilitySaved[data-state=closed] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilityAvailability[data-state=closed] .ptcPlusBindingToggle,.ptcPlusSessionCapabilityAvailability[data-state=damaged] .ptcPlusBindingToggle{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary,#e5484d) 42%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#e5484d) 10%,transparent)}
|
|
233
|
+
.ptcPlusSessionCapabilityAvailability[data-state=inherit] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilityDisclosure[data-state=inherit] .ptcPlusSelectTrigger{color:var(--dsw-alias-label-secondary)}.ptcPlusSessionCapabilityAvailability[data-state=skip] .ptcPlusBindingToggle{color:var(--dsw-alias-label-secondary)}
|
|
234
|
+
span.ptcPlusSessionCapabilitySaved[data-state=enabled],span.ptcPlusSessionCapabilitySaved[data-state=automatic],span.ptcPlusSessionCapabilitySaved[data-state=closed]{box-sizing:border-box;justify-self:start;display:inline-flex;align-items:center;height:16px;padding:0 7px;border-radius:999px;border:1px solid transparent;font-size:inherit;line-height:14px}
|
|
235
|
+
span.ptcPlusSessionCapabilitySaved[data-state=enabled]{background:color-mix(in srgb,var(--dsw-alias-state-success-primary,#12a150) 10%,transparent);border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary,#12a150) 42%,transparent)}
|
|
236
|
+
span.ptcPlusSessionCapabilitySaved[data-state=automatic]{background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 10%,transparent);border-color:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 42%,transparent)}
|
|
237
|
+
span.ptcPlusSessionCapabilitySaved[data-state=closed]{background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#e5484d) 10%,transparent);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary,#e5484d) 42%,transparent)}
|
|
238
|
+
.ptcPlusCapabilitySurface-inline{border:1px solid var(--dsw-alias-border-l2);border-radius:10px;overflow:clip}
|
|
239
|
+
/* The settings entrance is a page section, not a bounded dialog: the page owns the vertical
|
|
240
|
+
wheel. A clipping box that is also a scroll container (overflow:hidden) or an inner list that
|
|
241
|
+
keeps its own vertical scrolling captures the wheel while it cannot move, so the page stops
|
|
242
|
+
under the pointer. clip only trims the corners, and the inline list gives up both its own
|
|
243
|
+
scrolling and its scroll chaining rule. The strips this surface does scroll sideways -- the
|
|
244
|
+
settings tabs, the column header and, on a short viewport, the toolbar -- contain only that
|
|
245
|
+
axis, so a vertical wheel over them still reaches the page. */
|
|
246
|
+
.ptcPlusCapabilitySurface-inline .ptcPlusSessionCapabilityList{flex:none;max-height:none;overflow:visible;overscroll-behavior:auto}
|
|
247
|
+
.ptcPlusCapabilitySurface-inline .ptcPlusSessionCapabilityHead{padding-top:10px;padding-bottom:10px}
|
|
248
|
+
.ptcPlusCapabilityRulesEntry{display:flex;justify-content:flex-end;padding:0 0 8px}
|
|
249
|
+
.ptcPlusBindingTable{min-width:0}
|
|
250
|
+
@media(max-width:900px){.ptcPlusSessionCapabilityRow.ptcPlusCapabilityItem{grid-template-columns:minmax(0,1fr) auto;gap:6px 12px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityIdentity{grid-column:1/-1;grid-row:1}.ptcPlusSessionCapabilityRow .ptcPlusCapabilitySource{grid-column:1;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityBadge{grid-column:2;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilitySaved{grid-column:1;grid-row:3}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilitySavedDisclosure{grid-column:2;grid-row:3}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityAvailability{grid-column:1/-1;grid-row:4;flex-direction:row;flex-wrap:wrap}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityDisclosure{grid-column:1/-1;grid-row:5;flex-direction:row;flex-wrap:wrap}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityReceipt{grid-column:1/-1;grid-row:6}.ptcPlusSessionCapabilityRow-5 .ptcPlusSessionCapabilitySaved{grid-column:1/-1;grid-row:3}.ptcPlusSessionCapabilityRow-5 .ptcPlusSessionCapabilitySavedDisclosure{grid-column:1/-1;grid-row:4}}
|
|
251
|
+
@media(max-width:900px){.ptcPlusSessionCapabilityToolbar{grid-template-columns:repeat(3,minmax(0,1fr))}.ptcPlusSessionCapabilityToolbar .ptcPlusSearch{grid-column:1/-1}.ptcPlusSessionCapabilityColumns.ptcPlusCapabilityColumns{display:flex;gap:4px 12px;overflow-x:auto;overscroll-behavior-x:contain;padding-block:4px}.ptcPlusSessionCapabilityColumns>span{flex:none}.ptcPlusSessionCapabilityRow.ptcPlusCapabilityItem{grid-template-columns:minmax(0,1fr) auto;gap:4px 12px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityIdentity{grid-column:1/-1}.ptcPlusSessionCapabilityRow .ptcPlusCapabilitySource{grid-column:1;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityBadge{grid-column:2;grid-row:2}}
|
|
252
|
+
@media(max-width:650px){.ptcPlusSessionCapabilityModal.ptcPlusSessionCapabilityModal{width:calc(100vw - 16px);height:calc(100dvh - 16px);max-height:100%}.ptcPlusSessionCapabilityHead,.ptcPlusSessionCapabilityToolbar,.ptcPlusSessionCapabilityFooter{padding-left:14px;padding-right:14px}.ptcPlusSessionCapabilityHead{padding-top:10px;padding-bottom:10px}.ptcPlusSessionCapabilityToolbar{gap:5px;padding-top:7px;padding-bottom:7px}.ptcPlusSessionCapabilityFooter{flex-wrap:wrap;gap:6px;padding-top:7px;padding-bottom:7px}.ptcPlusSessionCapabilityFooter [role=status]{flex-basis:100%}.ptcPlusSessionCapabilityFooter button{flex:1;min-width:0;width:auto}}
|
|
253
|
+
@media(max-height:480px){.ptcPlusSessionCapabilityModal.ptcPlusSessionCapabilityModal{height:calc(100dvh - 8px);max-height:100%}.ptcPlusSessionCapabilityHead{padding-top:2px;padding-bottom:2px}.ptcPlusSessionCapabilityHead h2{font-size:12px;line-height:16px}.ptcPlusSessionCapabilityHead .ptcPlusDialogClose{width:22px;height:22px}.ptcPlusSessionCapabilityHead p{display:none}.ptcPlusSessionCapabilityToolbar .ptcPlusCapabilityFilter>span{display:none}.ptcPlusSessionCapabilityToolbar{display:flex;gap:6px;overflow-x:auto;overscroll-behavior-x:contain;padding-block:1px}.ptcPlusSessionCapabilityToolbar .ptcPlusSearch{flex:0 0 145px;height:27px}.ptcPlusSessionCapabilityToolbar .ptcPlusCapabilityFilter{flex:0 0 130px}.ptcPlusSessionCapabilityToolbar .ptcPlusSelectTrigger{height:27px}.ptcPlusSessionCapabilityToolbar>.ptcPlusButton{flex:none;min-height:28px;padding:2px 10px;font-size:11px;line-height:14px;white-space:nowrap}.ptcPlusSessionCapabilityColumns.ptcPlusCapabilityColumns{padding-block:0}.ptcPlusSessionCapabilityGroup h3{padding-top:0;padding-bottom:0;line-height:10px}.ptcPlusSessionCapabilityRow.ptcPlusCapabilityItem{grid-template-columns:minmax(0,1.25fr) auto minmax(120px,1fr);min-height:32px;padding-block:3px;gap:0 10px;line-height:16px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityIdentity{grid-column:1;grid-row:1}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityName{font-size:12px;line-height:16px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityIdentity code{display:none}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityBadge{grid-column:2;grid-row:1;padding-block:0}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityAvailability{grid-column:3;grid-row:1;flex-direction:row;flex-wrap:nowrap}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityDisclosure{grid-column:3;grid-row:2;flex-direction:row;flex-wrap:nowrap}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityAvailability .ptcPlusSelectTrigger,.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityDisclosure .ptcPlusSelectTrigger{height:24px;padding:0 6px;font-size:11px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilitySource{grid-column:1;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilitySaved{grid-column:2;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilitySavedDisclosure{grid-column:1;grid-row:3}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityReceipt{grid-column:2/-1;grid-row:3}.ptcPlusSessionCapabilityFooter{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:4px;padding:4px 6px}.ptcPlusSessionCapabilityFooter [role=status]{grid-column:1/-1;font-size:10px;line-height:11px;max-height:22px;overflow-y:auto}.ptcPlusSessionCapabilityFooter button{min-width:0;width:100%;min-height:28px;padding:3px 10px;font-size:10px;line-height:14px;white-space:normal}}
|
|
254
|
+
@media(max-height:480px) and (max-width:650px){.ptcPlusSessionCapabilityRow.ptcPlusCapabilityItem{grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto;gap:0 8px;padding-block:4px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityIdentityText{min-height:0;gap:2px}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityName{line-height:16px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityIdentity{grid-column:1/3;grid-row:1}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityReceipt{grid-column:3;grid-row:1;justify-self:end;max-width:100%;font-size:10px;line-height:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ptcPlusSessionCapabilityRow .ptcPlusCapabilitySource{grid-column:1;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilitySaved{grid-column:2;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilitySavedDisclosure{grid-column:3;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityAvailability{grid-column:1;grid-row:3}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityDisclosure{grid-column:2;grid-row:3}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityBadge{grid-column:3;grid-row:3;justify-self:end}.ptcPlusSessionCapabilityRow-5 .ptcPlusSessionCapabilitySaved{grid-column:1/-1;grid-row:4}.ptcPlusSessionCapabilityRow-5 .ptcPlusSessionCapabilitySavedDisclosure{grid-column:1/-1;grid-row:5}}
|
|
211
255
|
|
|
212
256
|
.ptcPlusCapabilityDialog.ptcPlusCapabilityDialog{box-sizing:border-box;width:min(520px,calc(100vw - 32px));max-height:calc(100dvh - 32px);display:flex;flex-direction:column;padding:0;overflow:hidden;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-primary,#18191c)}
|
|
213
|
-
|
|
257
|
+
|
|
214
258
|
.ptcPlusCapabilityDialogHead{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 18px;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityDialogHead h2{margin:0;font-size:16px;line-height:24px;overflow-wrap:anywhere}
|
|
215
|
-
.ptcPlusCapabilityDialogBody{min-height:0;overflow:auto;overscroll-behavior:contain;padding:14px 18px}.ptcPlusCapabilityDialogBody>p{margin:0 0 10px;overflow-wrap:anywhere}
|
|
259
|
+
.ptcPlusCapabilityDialogBody{min-height:0;overflow:auto;overscroll-behavior:contain;padding:14px 18px}.ptcPlusCapabilityDialogBody>p{margin:0 0 10px;overflow-wrap:anywhere}
|
|
216
260
|
.ptcPlusCapabilityDialogFooter{display:flex;align-items:center;justify-content:flex-end;gap:10px;padding:12px 18px;border-top:1px solid var(--dsw-alias-border-l2)}
|
|
217
261
|
.ptcPlusCapabilityDialogActions{display:flex;flex-direction:column;gap:8px;margin-top:12px}.ptcPlusCapabilityDialogActions>.ptcPlusButton{justify-content:center;width:100%}
|
|
218
262
|
.ptcPlusConfigurationMore.ptcPlusButton{padding:0 10px;font-size:16px;line-height:1}
|
|
263
|
+
.ptcPlusCapabilitySort{appearance:none;display:inline-flex;align-items:center;gap:4px;min-width:0;max-width:100%;min-height:18px;margin:-3px 0;padding:0;border:0;background:transparent;color:inherit;font:inherit;line-height:18px;text-align:start;cursor:pointer}
|
|
264
|
+
.ptcPlusCapabilitySort:hover{color:var(--dsw-alias-label-primary)}
|
|
265
|
+
.ptcPlusCapabilitySort:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:-2px}
|
|
266
|
+
.ptcPlusCapabilitySortMark{flex:none;font-size:10px;line-height:1;opacity:.55}
|
|
267
|
+
[aria-sort=ascending] .ptcPlusCapabilitySortMark,[aria-sort=descending] .ptcPlusCapabilitySortMark{opacity:1;color:var(--dsw-alias-label-primary)}
|
|
219
268
|
@media(max-width:420px){.ptcPlusCapabilityDialogFooter{flex-wrap:wrap}.ptcPlusCapabilityDialogFooter button{flex:1;min-width:0}}
|
|
220
269
|
|
|
221
270
|
`
|
|
@@ -269,8 +318,7 @@ const REPL_CONSOLE_CSS = `
|
|
|
269
318
|
@media(max-width:560px){.ptcPlusConsole{padding:14px 12px}.ptcPlusBindingsModal.ptcPlusBindingsModal{width:calc(100vw - 16px);max-height:calc(100dvh - 16px)}.ptcPlusBindingsDialog{padding:16px;max-height:calc(100dvh - 16px)}.ptcPlusObservationFilters>.ptcPlusSelectTrigger{width:105px}.ptcPlusObservationTable th,.ptcPlusObservationTable td{padding:0 6px}.ptcPlusObservationValue{gap:3px}.ptcPlusObservationState{font-size:10px}.ptcPlusEditorHead{align-items:flex-start}.ptcPlusEditorHead>.ptcPlusBindingLifecycle{margin-left:auto}.ptcPlusSourceBody .cm-editor{height:300px}}
|
|
270
319
|
.ptcPlusReplIdentity{grid-column:1}.ptcPlusReplReuse{flex:none;padding:0 5px;border-radius:999px;background:var(--dsw-alias-bg-layer-2,rgba(38,49,72,.06));color:var(--dsw-alias-label-tertiary,#74777d);font:500 10px/15px system-ui,sans-serif;white-space:nowrap}
|
|
271
320
|
.ptcPlusObservationReuseTotal{font-size:13px;color:var(--dsw-alias-label-tertiary)}.ptcPlusObservationReuse{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-variant-numeric:tabular-nums}
|
|
272
|
-
.ptcPlusCapabilityIdentity{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:3px 8px;min-width:0}.ptcPlusCapabilityIdentityText{display:flex;flex-direction:column;gap:3px;min-width:0}.
|
|
273
|
-
@media(max-width:650px){.ptcPlusCapabilityBlocked{margin-inline:14px}}@media(max-width:650px) and (max-height:480px){.ptcPlusCapabilityBlocked{margin:4px 6px 0;font-size:11px}}
|
|
321
|
+
.ptcPlusCapabilityIdentity{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:3px 8px;min-width:0}.ptcPlusCapabilityIdentityText{display:flex;flex-direction:column;gap:3px;min-width:0}.ptcPlusPick{appearance:none;position:relative;flex:none;box-sizing:border-box;width:16px;height:16px;margin:0;border:1px solid var(--dsw-alias-border-l4);border-radius:4px;background:var(--dsw-alias-bg-layer-3);cursor:pointer}.ptcPlusPick:checked,.ptcPlusPick:indeterminate{border-color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-brand-primary)}.ptcPlusPick:checked::after{position:absolute;left:4px;top:1px;width:5px;height:9px;border:solid var(--dsw-alias-label-primary-foreground);border-width:0 2px 2px 0;content:'';transform:rotate(45deg)}.ptcPlusPick:indeterminate::after{position:absolute;left:3px;top:6px;width:8px;height:2px;border-radius:1px;background:var(--dsw-alias-label-primary-foreground);content:''}.ptcPlusPick:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:2px}.ptcPlusPick:disabled{cursor:not-allowed;opacity:.4}.ptcPlusCapabilityBatchCount{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:16px;padding:0 5px;border-radius:999px;background:var(--dsw-alias-state-business-primary,#4d6bfe);color:#fff;font-size:10px;line-height:16px}@media(max-width:650px){.ptcPlusSessionCapabilityMessage{padding-inline:14px}}
|
|
274
322
|
@media(max-width:650px){.ptcPlusSessionCapabilityFooter button{font-size:11px;line-height:14px}}
|
|
275
323
|
@media(max-width:650px) and (max-height:480px){.ptcPlusSessionCapabilityFooter{grid-template-columns:repeat(4,minmax(0,1fr));gap:3px;padding:3px 6px}.ptcPlusSessionCapabilityFooter [role=status]{line-height:11px}.ptcPlusSessionCapabilityFooter button{font-size:10px;line-height:12px;padding:1px 10px}}
|
|
276
324
|
`
|
package/src/client.js
CHANGED
|
@@ -3,8 +3,9 @@ import { RPC_CONTRACTS } from '../internal/rpc-contract.js'
|
|
|
3
3
|
import { CONFIG_DEFAULTS, SETTINGS_NAMESPACE } from '../internal/config-spec.js'
|
|
4
4
|
import { createPtcToolView } from './client-tool-view.js'
|
|
5
5
|
import { createPtcSettingsView } from './client-settings-view.js'
|
|
6
|
-
import { createCapabilityCommandCard, createCapabilityRefreshView,
|
|
6
|
+
import { createCapabilityCommandCard, createCapabilityRefreshView, createCapabilitySurfaceView } from './client-capabilities-view.js'
|
|
7
7
|
import { capabilityProfileConfiguration } from '../internal/runtime-config.js'
|
|
8
|
+
import { capabilityPolicyForConfig } from '../internal/capability-policy.js'
|
|
8
9
|
import { createReplView } from './client-repl-view.js'
|
|
9
10
|
import { createAuthoringView } from './client-authoring-view.js'
|
|
10
11
|
import { bindingToggleConversationDefinition } from './client-binding-toggle.js'
|
|
@@ -178,18 +179,28 @@ export function createClientPlugin(require) {
|
|
|
178
179
|
})
|
|
179
180
|
const { observeRepl } = createReplObserver({ rpc, ctx })
|
|
180
181
|
const capabilityCommands = createCommandAccess(ctx, 'capabilities')
|
|
182
|
+
// The panel's binding rows write through the same `/binding` command a human
|
|
183
|
+
// types, so they borrow its availability source instead of a second channel.
|
|
184
|
+
const bindingCommands = createBindingCommandAvailability(ctx)
|
|
181
185
|
const CapabilityCommandCard = createCapabilityCommandCard(React)
|
|
182
186
|
const CapabilityRefreshButton = createCapabilityRefreshView(React, capabilityCommands)
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
187
|
+
// One read serves both entrances. A request that names a session states that
|
|
188
|
+
// session's declared face; a request that names none states the Host's own
|
|
189
|
+
// declaration, which is the process-scope object set this entrance can state — a
|
|
190
|
+
// preset's agent-scope entries exist only in a session's declared face.
|
|
191
|
+
async function inspectSessionCatalog(sessionId, signal) {
|
|
192
|
+
const result = await rpc.call(RPC_CONTRACTS.capabilities, 'session-catalog',
|
|
193
|
+
typeof sessionId === 'string' && sessionId ? { sessionId } : {}, signal)
|
|
194
|
+
if (result?.ok !== true) throw new Error(result?.error?.message ?? 'Session capability catalog unavailable')
|
|
195
|
+
return result.value
|
|
196
|
+
}
|
|
197
|
+
// The capability page has one renderer. The session entry and the settings entry
|
|
198
|
+
// both mount it; neither adds a column, a word, a control or a receipt of its own.
|
|
199
|
+
const CapabilitySurface = createCapabilitySurfaceView(React, {
|
|
200
|
+
commands: capabilityCommands, bindingCommands, Modal, Select, inspectSessionCatalog,
|
|
190
201
|
})
|
|
191
202
|
const { PTCPlusSettingsCard, PTCPlusSettingsDialog } = createPtcSettingsView(React, {
|
|
192
|
-
ActionButton, BindingsDialog, Modal, Select, useWorkbenchController, CapabilityRefreshButton,
|
|
203
|
+
ActionButton, BindingsDialog, Modal, Select, useWorkbenchController, CapabilityRefreshButton, CapabilitySurface,
|
|
193
204
|
async inspectCapabilityTargets(signal) {
|
|
194
205
|
const result = await rpc.call(RPC_CONTRACTS.capabilities, 'targets', {}, signal)
|
|
195
206
|
if (result?.ok !== true) throw new Error(result?.error?.message ?? 'Capability refresh targets unavailable')
|
|
@@ -200,17 +211,14 @@ export function createClientPlugin(require) {
|
|
|
200
211
|
if (result?.ok !== true) throw new Error(result?.error?.message ?? 'Capability plans unavailable')
|
|
201
212
|
return result.value
|
|
202
213
|
},
|
|
203
|
-
async inspectCapabilityCatalog(signal) {
|
|
204
|
-
const result = await rpc.call(RPC_CONTRACTS.capabilities, 'catalog', {}, signal)
|
|
205
|
-
if (result?.ok !== true) throw new Error(result?.error?.message ?? 'Capability catalog unavailable')
|
|
206
|
-
return result.value
|
|
207
|
-
},
|
|
208
214
|
async inspectCapabilityAllocation(payload, signal) {
|
|
209
215
|
const result = await rpc.call(RPC_CONTRACTS.capabilities, 'allocation', payload, signal)
|
|
210
216
|
if (result?.ok !== true) throw new Error(result?.error?.message ?? 'Capability allocation unavailable')
|
|
211
217
|
return result.value
|
|
212
218
|
},
|
|
213
|
-
|
|
219
|
+
// The settings page reads one icon: its navigation chevron. The search icon belonged to
|
|
220
|
+
// the second renderer's toolbar row, which this page no longer has.
|
|
221
|
+
icons: { chevron: IconChevronDownOutline14 },
|
|
214
222
|
})
|
|
215
223
|
const { ReplComposer, ReplConsole, ReplMemoryCard, replPopoverIsOpen, placeReplPopover, useObservedReplMemory } = createReplView(React, {
|
|
216
224
|
CodeBlock, Select, featureEnabled, normalizeReplMemorySnapshot, normalizeReplMemoryView,
|
|
@@ -241,9 +249,24 @@ export function createClientPlugin(require) {
|
|
|
241
249
|
const before = preferenceScope.getSnapshot()
|
|
242
250
|
if (before.status !== 'ready' || before.writable !== true || !featureEnabled(before, 'plugin')) throw new Error('Capability settings are not writable')
|
|
243
251
|
const validated = capabilityProfileConfiguration(configuration)
|
|
244
|
-
|
|
252
|
+
const synthesized = JSON.stringify(capabilityPolicyForConfig({ ...validated, capabilityPolicy: undefined }))
|
|
253
|
+
const ops = Object.entries(validated)
|
|
254
|
+
.filter(([key]) => key !== 'capabilityPolicy')
|
|
255
|
+
.map(([key, value]) => ({ op: 'set', path: [key], value }))
|
|
256
|
+
// A policy the rest of this configuration would synthesize belongs to no record: writing it
|
|
257
|
+
// would freeze a synthesized bottom layer into the record and let the management switch
|
|
258
|
+
// reach cells that must read 自动 (capability-surface §8.1c). The record may still hold one
|
|
259
|
+
// from an earlier apply, so remove it with the service's own unset op instead of leaving it.
|
|
260
|
+
const policyWritten = validated.capabilityPolicy !== undefined && validated.capabilityPolicy !== synthesized
|
|
261
|
+
ops.push(policyWritten
|
|
262
|
+
? { op: 'set', path: ['capabilityPolicy'], value: validated.capabilityPolicy }
|
|
263
|
+
: { op: 'unset', path: ['capabilityPolicy'] })
|
|
264
|
+
await preferenceScope.mutate(ops)
|
|
245
265
|
const after = preferenceScope.getSnapshot()
|
|
246
|
-
|
|
266
|
+
const unchanged = Object.entries(validated).every(([key, value]) => key === 'capabilityPolicy'
|
|
267
|
+
? (policyWritten ? after.value?.capabilityPolicy === value : after.value?.capabilityPolicy === undefined)
|
|
268
|
+
: after.value?.[key] === value)
|
|
269
|
+
if (after.status !== 'ready' || !unchanged) throw new Error('Capability configuration was not applied')
|
|
247
270
|
return 'status.applied'
|
|
248
271
|
}
|
|
249
272
|
// One gated-registration shape for every settings-driven contribution.
|
|
@@ -307,7 +330,10 @@ export function createClientPlugin(require) {
|
|
|
307
330
|
isEnabled: () => featureEnabled(preferenceScope.getSnapshot(), 'replView')
|
|
308
331
|
&& sessionUsesPtcPreset(preset),
|
|
309
332
|
register: () => viewScope.slots.register({
|
|
310
|
-
|
|
333
|
+
// A plugin contribution trails the Host's own tabs: chat is 0 and the
|
|
334
|
+
// experimental statistics tab is 40, and a REPL tab that sorts before them
|
|
335
|
+
// pushes a Host tab to the right of a plugin's.
|
|
336
|
+
name: 'conversation.view', id: 'ptc-plus-repl', label: 'REPL', order: 50,
|
|
311
337
|
locale: LOCALE_NS, inject: () => ({ ...settingsProps(), hideComposer, observeRepl }),
|
|
312
338
|
}, props => typeof props.useProjection === 'function' ? h(ReplConsole, props) : null),
|
|
313
339
|
})
|
|
@@ -330,7 +356,7 @@ export function createClientPlugin(require) {
|
|
|
330
356
|
const { BindingAuthorButton, BindingReviewDock, BindingCommandCard } = createAuthoringView(React, {
|
|
331
357
|
ActionButton, IconButton, Menu, MenuFallback, Toast, Tooltip, CodeBlock, Modal, createPortal, BindingsDialog, PTCPlusSettingsDialog,
|
|
332
358
|
useWorkbenchController, useBindingReview, catalogOwner, callUserBindings, subscribeReset,
|
|
333
|
-
settingsCardSeat: settingsCard.seat, updateSetting, updateCapabilityConfiguration, menuChildren, SessionCapabilityControls,
|
|
359
|
+
settingsCardSeat: settingsCard.seat, updateSetting, updateCapabilityConfiguration, menuChildren, SessionCapabilityControls: CapabilitySurface,
|
|
334
360
|
icons: {
|
|
335
361
|
sparkle: IconSparkle16, chevron: IconChevronDownOutline14,
|
|
336
362
|
close: IconCloseOutline16, check: IconCheckOutline14,
|
|
@@ -366,7 +392,6 @@ export function createClientPlugin(require) {
|
|
|
366
392
|
name: 'conversation.input.dock', id: 'ptc-plus-binding-review', order: -30, locale: LOCALE_NS,
|
|
367
393
|
}, props => typeof props.useProjection === 'function' && props.sessionId !== undefined
|
|
368
394
|
? h(BindingReviewDock, { ...props, key: props.sessionId }) : null)))))
|
|
369
|
-
const availability = createBindingCommandAvailability(ctx)
|
|
370
395
|
// The composer binding entry belongs to the PTC surface, exactly like the
|
|
371
396
|
// header indicator and the REPL tab. A non-PTC session keeps plugin
|
|
372
397
|
// settings and `/binding` command cards, but shows no binding shortcut and
|
|
@@ -387,7 +412,7 @@ export function createClientPlugin(require) {
|
|
|
387
412
|
register: () => ctx.slots.register({
|
|
388
413
|
name: 'conversation.input.left', id: 'ptc-plus-binding-author', order: 20, locale: LOCALE_NS,
|
|
389
414
|
inject: sessionId => ({
|
|
390
|
-
hooks: { ptcSettings: preferenceScope, bindingCommand:
|
|
415
|
+
hooks: { ptcSettings: preferenceScope, bindingCommand: bindingCommands.source(sessionId),
|
|
391
416
|
capabilityCommand: capabilityCommands.source(sessionId) },
|
|
392
417
|
}),
|
|
393
418
|
}, props => props.sessionId === undefined ? null : h(BindingAuthorButton, { ...props, key: props.sessionId })),
|