dsh-ptc-plus 0.3.1 → 0.4.1
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 +66 -73
- package/README.md +66 -73
- package/assets/ptc-plus-bindings-en.png +0 -0
- package/assets/ptc-plus-bindings-zh.png +0 -0
- package/assets/ptc-plus-repair-en.png +0 -0
- package/assets/ptc-plus-repair-zh.png +0 -0
- package/assets/ptc-plus-repl-workspace-en.png +0 -0
- package/assets/ptc-plus-repl-workspace-zh.png +0 -0
- package/assets/ptc-plus-settings-en.png +0 -0
- package/assets/ptc-plus-settings-zh.png +0 -0
- package/client.js +30610 -722
- package/compiler-amaro.cjs +5 -0
- package/compiler-amaro.cjs.map +6 -0
- package/compiler-asset-124f80c1bba92ff5fe79cfec6e8ad518f476de4a42514cae3919538887f510e8.txt +1 -0
- package/compiler-assets.json +3 -0
- package/compiler-core.cjs +554 -0
- package/compiler-core.cjs.map +6 -0
- package/compiler-platform.cjs +2 -0
- package/compiler-platform.cjs.map +6 -0
- package/compiler-typescript.cjs +388 -0
- package/compiler-typescript.cjs.map +6 -0
- package/docs/README.md +6 -0
- package/docs/adr/0004-declare-program-bindings-at-the-host.md +1 -1
- package/docs/adr/0006-rewrite-module-syntax-with-an-ast.md +6 -4
- package/docs/adr/0007-separate-worker-transport-from-session-semantics.md +15 -3
- package/docs/adr/0009-bound-expensive-acceptance-default.md +2 -0
- package/docs/adr/0010-session-log-derived-recovery-tips.md +59 -5
- package/docs/adr/0011-isolate-the-local-recovery-tip-provider.md +1 -1
- package/docs/adr/0012-preserve-mixed-destructuring-initialization.md +3 -1
- package/docs/adr/0013-isolate-repl-redeclaration-convenience.md +9 -3
- package/docs/adr/0014-persist-cell-rewrite-policy.md +11 -5
- package/docs/adr/0015-preserve-source-positions-through-rewrites.md +1 -1
- package/docs/adr/0016-archive-resolved-review-findings.md +1 -1
- package/docs/adr/0017-track-the-latest-dsh-public-surface.md +49 -0
- package/docs/adr/0018-use-versioned-fixture-for-ab-benchmark.md +3 -3
- package/docs/adr/0019-plugin-settings-and-kill-switch.md +8 -6
- package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -2
- package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +17 -3
- package/docs/adr/0023-global-user-bindings.md +104 -0
- package/docs/adr/0024-repl-console-observation.md +33 -0
- package/docs/adr/0025-use-versioned-logical-binding-identities.md +119 -0
- package/docs/adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md +21 -0
- package/docs/adr/0027-run-the-session-kernel-in-a-killable-helper-process.md +37 -0
- package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +103 -0
- package/docs/adr/0029-keep-plugin-unavailability-out-of-the-host-agent-lifecycle.md +27 -0
- package/docs/adr/0030-serve-both-typert-codec-generations-from-one-codec.md +27 -0
- package/docs/architecture.md +82 -22
- package/docs/binding-review-placement-design.md +200 -0
- package/docs/capability-projection.md +1 -1
- package/docs/client-ui.md +96 -20
- package/docs/durability-design.md +61 -24
- package/docs/evaluation.md +78 -6
- package/docs/installation.md +41 -6
- package/docs/program-data-plane.md +6 -0
- package/docs/publishing.md +5 -3
- package/docs/runtime-reference.md +79 -25
- package/docs/semantic-validation.md +29 -0
- package/docs/stateful-binding-updates-proposal.md +755 -0
- package/docs/user-bindings.en.md +64 -0
- package/docs/user-bindings.md +64 -0
- package/docs/value-wire.md +3 -3
- package/docs/verification.md +57 -0
- package/index.js +374 -92
- package/internal/ast-traversal.js +5 -2
- package/internal/binding-descriptors.js +1 -0
- package/internal/binding-pattern-traversal.js +25 -0
- package/internal/binding-pattern.js +26 -29
- package/internal/binding-source-analysis.js +391 -0
- package/internal/binding-update-policy.js +66 -0
- package/internal/bounded-worker-round.js +56 -0
- package/internal/callable-definition-environment.js +42 -0
- package/internal/callable-source-catalog.js +129 -0
- package/internal/callable-source-encoding.js +47 -0
- package/internal/callable-source-facts.js +459 -0
- package/internal/callable-source-format.js +2 -0
- package/internal/callable-source-lowering.js +123 -0
- package/internal/cell-analysis-contract.js +25 -0
- package/internal/cell-analysis.js +252 -242
- package/internal/cell-completion.js +15 -0
- package/internal/cell-error.js +7 -0
- package/internal/cell-parser.js +66 -0
- package/internal/cell-rewriter.js +3 -553
- package/internal/commonjs-export-evidence.js +63 -0
- package/internal/commonjs-source-evidence.js +72 -0
- package/internal/compiler-amaro.cjs +2 -0
- package/internal/compiler-compression.js +12 -0
- package/internal/compiler-data.js +58 -0
- package/internal/compiler-descriptors.js +54 -0
- package/internal/compiler-dynamic-cache.js +48 -0
- package/internal/compiler-entry.js +35 -0
- package/internal/compiler-generated-names.js +17 -0
- package/internal/compiler-intrinsics.js +84 -0
- package/internal/compiler-module-links.js +34 -0
- package/internal/compiler-operations.js +61 -0
- package/internal/compiler-platform-factory.js +84 -0
- package/internal/compiler-platform.js +136 -0
- package/internal/compiler-record-roles.js +53 -0
- package/internal/compiler-region-output.js +259 -0
- package/internal/compiler-resource-lowering.js +103 -0
- package/internal/compiler-scope-facts.js +115 -0
- package/internal/compiler-service.js +109 -0
- package/internal/compiler-source-cache.js +32 -0
- package/internal/compiler-source-pieces.js +93 -0
- package/internal/compiler-source-regions.js +132 -0
- package/internal/compiler-storage-source.js +54 -0
- package/internal/compiler-text.js +15 -0
- package/internal/compiler-typescript.cjs +2 -0
- package/internal/config-spec.js +91 -25
- package/internal/cordis-tools-owner.js +130 -21
- package/internal/diagnostic.js +27 -1
- package/internal/direct-surface-owner.js +76 -23
- package/internal/dynamic-binding-evidence.js +16 -0
- package/internal/dynamic-environment-compiler.js +779 -0
- package/internal/dynamic-environment-integration.js +87 -0
- package/internal/dynamic-environment-runtime.js +362 -0
- package/internal/dynamic-native-calls.js +150 -0
- package/internal/dynamic-native-runtime.js +248 -0
- package/internal/dynamic-scope-analysis.js +90 -0
- package/internal/edit-transport-owner.js +28 -3
- package/internal/execution-seam-compat.js +193 -0
- package/internal/failure-reporting.js +118 -18
- package/internal/host-rpc.js +66 -0
- package/internal/isolated-worker.js +548 -0
- package/internal/kernel-child.js +139 -0
- package/internal/kernel-worker.js +911 -116
- package/internal/language-semantics.js +14 -0
- package/internal/legacy-binding-catalog.js +48 -0
- package/internal/legacy-cell-analysis.js +600 -0
- package/internal/legacy-cell-parser.js +50 -0
- package/internal/legacy-cell-rewriter.js +631 -0
- package/internal/legacy-repl-convenience.js +291 -0
- package/internal/managed-module-operations.js +170 -0
- package/internal/module-compilation.js +321 -0
- package/internal/module-runtime-platform.js +19 -0
- package/internal/module-transform-contract.js +12 -0
- package/internal/native-await-declarations.js +68 -0
- package/internal/native-root-compilation.js +54 -0
- package/internal/native-root-dynamic.js +67 -0
- package/internal/recovery-tips.js +27 -15
- package/internal/rejected-cell-editor.js +13 -8
- package/internal/repl-convenience.js +2 -201
- package/internal/repl-memory-projection.js +81 -12
- package/internal/repl-observation-interest.js +70 -0
- package/internal/repl-rewrite-contract.js +21 -0
- package/internal/repl-scope-normalizer.js +2091 -0
- package/internal/repl-value-observer.js +114 -0
- package/internal/rpc-contract.js +52 -0
- package/internal/runtime-bridge-owner.js +172 -28
- package/internal/runtime-config.js +48 -51
- package/internal/runtime-contexts.js +82 -10
- package/internal/runtime-messages.js +111 -0
- package/internal/session-cell-executor.js +455 -91
- package/internal/session-journal-recovery.js +684 -0
- package/internal/session-journal-schema.js +106 -0
- package/internal/session-journal.js +237 -440
- package/internal/session-log-view.js +42 -9
- package/internal/session-runtime.js +325 -80
- package/internal/session-state.js +249 -40
- package/internal/source-position-map.js +211 -71
- package/internal/stateful-module-compiler.js +154 -0
- package/internal/stateful-module-runtime.js +303 -0
- package/internal/stateful-root-compiler.js +598 -0
- package/internal/stateful-root-runtime.js +340 -0
- package/internal/typert-codec-compat.js +28 -0
- package/internal/typescript-transform.js +29 -0
- package/internal/user-binding-authoring.js +70 -0
- package/internal/user-binding-console-worker.js +184 -0
- package/internal/user-binding-console.js +148 -0
- package/internal/user-binding-draft-projection.js +335 -0
- package/internal/user-binding-model-context.js +31 -0
- package/internal/user-binding-runner.js +56 -0
- package/internal/user-bindings-owner.js +1065 -0
- package/internal/user-bindings-store.js +293 -0
- package/internal/user-bindings.js +353 -0
- package/internal/value-wire-schema.js +28 -0
- package/internal/value-wire.js +29 -20
- package/internal/worker-client.js +57 -67
- package/internal/worker-environment.js +45 -0
- package/internal/worker-output-relay.js +29 -0
- package/internal/worker-shutdown.js +14 -0
- package/package.json +81 -11
- package/src/client-activity.js +109 -45
- package/src/client-authoring-view.js +580 -0
- package/src/client-binding-review.js +230 -0
- package/src/client-bindings-data.js +29 -0
- package/src/client-catalog.js +127 -0
- package/src/client-code-editor.js +84 -0
- package/src/client-console.js +112 -0
- package/src/client-copy.js +370 -0
- package/src/client-feature-gates.js +62 -0
- package/src/client-host-compat.js +150 -0
- package/src/client-indicator-view.js +267 -0
- package/src/client-repl-view.js +292 -0
- package/src/client-rpc.js +20 -0
- package/src/client-settings-view.js +221 -0
- package/src/client-styles.js +106 -0
- package/src/client-tool-view.js +108 -0
- package/src/client-transport.js +159 -0
- package/src/client-workbench.js +521 -0
- package/src/client.js +233 -615
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { CONFIG_FIELDS, CONFIG_GROUPS } from '../internal/config-spec.js'
|
|
2
|
+
import { resolveConfig } from '../internal/runtime-config.js'
|
|
3
|
+
import { featureEnabled } from './client-feature-gates.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Settings card for the plugin. One field control per config-spec entry, one
|
|
7
|
+
* serialized write tail so rapid edits cannot race, and the manage-bindings
|
|
8
|
+
* action only while global bindings are eligible.
|
|
9
|
+
*/
|
|
10
|
+
export function createPtcSettingsView(React, deps) {
|
|
11
|
+
const { ActionButton, BindingsDialog, Modal, useWorkbenchController, icons } = deps
|
|
12
|
+
const h = React.createElement
|
|
13
|
+
const focusableSelector = 'button:not(:disabled),input:not(:disabled),textarea:not(:disabled),select:not(:disabled),[href],[tabindex]:not([tabindex="-1"]),[contenteditable=true],summary'
|
|
14
|
+
|
|
15
|
+
function fieldInput(field, value, disabled, onChange, label) {
|
|
16
|
+
if (field.type === 'boolean') {
|
|
17
|
+
return h('input', {
|
|
18
|
+
type: 'checkbox', role: 'switch', className: 'ptcPlusCheck', checked: value === true,
|
|
19
|
+
disabled, 'aria-label': label,
|
|
20
|
+
onChange: event => onChange(field, event.target.checked),
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
if (field.type === 'enum') {
|
|
24
|
+
return h('input', {
|
|
25
|
+
type: 'checkbox', role: 'switch', className: 'ptcPlusCheck', checked: value !== 'protected',
|
|
26
|
+
disabled, 'aria-label': label,
|
|
27
|
+
onChange: event => onChange(field, event.target.checked ? 'stateful' : 'protected'),
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
return h('input', {
|
|
31
|
+
type: 'number', className: 'ptcPlusInput',
|
|
32
|
+
value: Number.isSafeInteger(value) ? String(value) : '',
|
|
33
|
+
min: field.min, max: field.max, step: 1, disabled, 'aria-label': label,
|
|
34
|
+
onChange: event => {
|
|
35
|
+
const input = event.target.value
|
|
36
|
+
const parsed = input === '' ? '' : Number(input)
|
|
37
|
+
onChange(field, Number.isSafeInteger(parsed) ? parsed : input)
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function PTCPlusSettingsCard({ t, usePtcSettings, updateSetting, callUserBindings, view, onBindingsOpenChange }) {
|
|
43
|
+
const [open, setOpen] = React.useState(false)
|
|
44
|
+
const [bindingsOpen, setBindingsOpen] = React.useState(false)
|
|
45
|
+
const bindingsAction = React.useRef(null)
|
|
46
|
+
const [status, setStatus] = React.useState(null)
|
|
47
|
+
const [pending, setPending] = React.useState(() => new Set())
|
|
48
|
+
const writeTail = React.useRef(Promise.resolve())
|
|
49
|
+
const snapshot = usePtcSettings(snapshot => snapshot)
|
|
50
|
+
const value = snapshot.status === 'ready' ? resolveConfig(snapshot.value ?? {}) : {}
|
|
51
|
+
const legacyKeys = ['looseTopLevelRedeclarations', 'looseTopLevelFunctionClassRedeclarations',
|
|
52
|
+
'autoRewriteImports', 'autoStripExports', 'autoSplitRedeclarations']
|
|
53
|
+
const legacyMigration = value.legacyBindingSettings === true
|
|
54
|
+
const enabled = featureEnabled(snapshot, 'plugin')
|
|
55
|
+
const globalEnabled = featureEnabled(snapshot, 'bindings')
|
|
56
|
+
const groupIdPrefix = view === 'dialog' ? 'ptc-plus-settings-dialog-group' : 'ptc-plus-settings-group'
|
|
57
|
+
// The open dialog owns the management session: closing it releases the draft
|
|
58
|
+
// and drops every response the host has not answered yet.
|
|
59
|
+
const workbench = useWorkbenchController({ enabled: globalEnabled && bindingsOpen, callUserBindings })
|
|
60
|
+
const setBindingsDialogOpen = next => {
|
|
61
|
+
setBindingsOpen(next)
|
|
62
|
+
onBindingsOpenChange?.(next)
|
|
63
|
+
}
|
|
64
|
+
React.useEffect(() => {
|
|
65
|
+
if (!globalEnabled) setBindingsDialogOpen(false)
|
|
66
|
+
}, [globalEnabled])
|
|
67
|
+
const unavailable = snapshot.status !== 'ready' || snapshot.writable !== true
|
|
68
|
+
const persist = (field, nextValue) => {
|
|
69
|
+
if (unavailable || pending.has(field.key)) return
|
|
70
|
+
const operation = writeTail.current.then(async () => {
|
|
71
|
+
setPending(current => new Set(current).add(field.key))
|
|
72
|
+
setStatus(null)
|
|
73
|
+
try {
|
|
74
|
+
const key = await updateSetting(field.key, nextValue)
|
|
75
|
+
if (key !== null) setStatus({ key })
|
|
76
|
+
} catch (error) {
|
|
77
|
+
setStatus({
|
|
78
|
+
key: 'status.failed',
|
|
79
|
+
params: { error: error instanceof Error ? error.message : String(error) },
|
|
80
|
+
})
|
|
81
|
+
} finally {
|
|
82
|
+
setPending(current => {
|
|
83
|
+
const next = new Set(current)
|
|
84
|
+
next.delete(field.key)
|
|
85
|
+
return next
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
writeTail.current = operation.catch(() => {})
|
|
90
|
+
}
|
|
91
|
+
const fieldDisabled = field => unavailable
|
|
92
|
+
|| pending.has(field.key)
|
|
93
|
+
|| (field.key !== 'enabled' && !enabled)
|
|
94
|
+
const settingsFields = () => CONFIG_GROUPS.map(group => {
|
|
95
|
+
const fields = group.key === 'syntax' && legacyMigration
|
|
96
|
+
? [...group.fields, ...legacyKeys]
|
|
97
|
+
: group.fields
|
|
98
|
+
return h('section', {
|
|
99
|
+
key: group.key,
|
|
100
|
+
className: 'ptcPlusGroup',
|
|
101
|
+
'aria-labelledby': `${groupIdPrefix}-${group.key}`,
|
|
102
|
+
},
|
|
103
|
+
h('h3', {
|
|
104
|
+
id: `${groupIdPrefix}-${group.key}`,
|
|
105
|
+
className: 'ptcPlusGroupTitle',
|
|
106
|
+
}, t(`group.${group.key}`)),
|
|
107
|
+
...fields.map(key => {
|
|
108
|
+
const field = CONFIG_FIELDS.find(candidate => candidate.key === key)
|
|
109
|
+
if (field === undefined) return null
|
|
110
|
+
const migratingPolicy = field.key === 'bindingUpdates' && legacyMigration
|
|
111
|
+
return h(React.Fragment, { key: field.key },
|
|
112
|
+
h('div', { className: 'ptcPlusRow' },
|
|
113
|
+
h('div', { className: 'ptcPlusMain' },
|
|
114
|
+
h('div', { className: 'ptcPlusLabel' }, t(`${field.key}.label`)),
|
|
115
|
+
field.description === '' ? null : h('div', { className: 'ptcPlusDetail' },
|
|
116
|
+
t(migratingPolicy ? 'bindingPolicy.migrationDescription' : `${field.key}.description`))),
|
|
117
|
+
migratingPolicy
|
|
118
|
+
? h('select', {
|
|
119
|
+
className: 'ptcPlusSelect', value: 'legacy', disabled: fieldDisabled(field),
|
|
120
|
+
'aria-label': t(`${field.key}.label`),
|
|
121
|
+
onChange: event => persist(field, event.target.value),
|
|
122
|
+
},
|
|
123
|
+
h('option', { value: 'legacy', disabled: true }, t('bindingPolicy.legacy')),
|
|
124
|
+
...field.options.map(policy => h('option', { key: policy, value: policy }, t(`bindingPolicy.${policy}`))))
|
|
125
|
+
: fieldInput(field, value[field.key], fieldDisabled(field), persist, t(`${field.key}.label`))),
|
|
126
|
+
field.key === 'userBindingsEnabled' && globalEnabled
|
|
127
|
+
? h('div', { className: 'ptcPlusSettingAction', ref: bindingsAction },
|
|
128
|
+
h(ActionButton, { type: 'button', className: 'ptcPlusButton', onClick: () => setBindingsDialogOpen(true) }, t('bindings.manage')))
|
|
129
|
+
: null)
|
|
130
|
+
}))
|
|
131
|
+
})
|
|
132
|
+
const settingsBody = (expanded, id) => h('div', {
|
|
133
|
+
id, className: 'ptcPlusBody', 'data-open': expanded, hidden: !expanded,
|
|
134
|
+
},
|
|
135
|
+
h('div', { className: 'ptcPlusBodyInner' }, h('div', { className: 'ptcPlusFields' },
|
|
136
|
+
snapshot.status === 'loading'
|
|
137
|
+
? h('p', { className: 'ptcPlusMessage' }, t('state.syncing'))
|
|
138
|
+
: snapshot.status === 'unavailable'
|
|
139
|
+
? h('p', { className: 'ptcPlusMessage' }, t('state.unavailable'))
|
|
140
|
+
: [
|
|
141
|
+
...settingsFields(),
|
|
142
|
+
h('div', { key: 'footer', className: 'ptcPlusFooter' },
|
|
143
|
+
h('span', { className: 'ptcPlusMessage', role: 'status' }, status === null
|
|
144
|
+
? t(snapshot.writable ? 'footer.live' : 'footer.readOnly')
|
|
145
|
+
: t(status.key, status.params))),
|
|
146
|
+
])))
|
|
147
|
+
const openBindings = globalEnabled && bindingsOpen
|
|
148
|
+
? h(BindingsDialog, {
|
|
149
|
+
controller: workbench, t, onClose: () => setBindingsDialogOpen(false),
|
|
150
|
+
getReturnFocus: () => bindingsAction.current?.querySelector('button'),
|
|
151
|
+
}) : null
|
|
152
|
+
// A seat that asks for views renders one entry twice: `summary` is the
|
|
153
|
+
// one-liner under the title the seat draws, `page` is the form it mounts
|
|
154
|
+
// with its own save control (the form already writes on change). The legacy
|
|
155
|
+
// card seat asks for neither and keeps the whole collapsible card.
|
|
156
|
+
if (view === 'summary') return h('span', { className: 'ptcPlusDescription' }, t('card.description'))
|
|
157
|
+
if (view === 'page') return h('div', { className: 'ptcPlusCard' }, settingsBody(true), openBindings)
|
|
158
|
+
if (view === 'dialog') return h(React.Fragment, null, settingsBody(true), openBindings)
|
|
159
|
+
return h('li', { className: 'ptcPlusCard' },
|
|
160
|
+
h('button', {
|
|
161
|
+
type: 'button', className: 'ptcPlusHeader', 'aria-expanded': open,
|
|
162
|
+
'aria-label': t(open ? 'action.collapse' : 'action.expand'),
|
|
163
|
+
'aria-controls': 'ptc-plus-settings-body', onClick: () => setOpen(current => !current),
|
|
164
|
+
},
|
|
165
|
+
h('span', { className: 'ptcPlusHeadText' },
|
|
166
|
+
h('span', { className: 'ptcPlusName' }, 'PTC Plus'),
|
|
167
|
+
h('span', { className: 'ptcPlusDescription' }, t('card.description'))),
|
|
168
|
+
h('span', { className: 'ptcPlusStatus', 'data-enabled': enabled }, t(enabled ? 'status.enabled' : 'status.disabled')),
|
|
169
|
+
h('span', { className: 'ptcPlusChevron', 'data-open': open, 'aria-hidden': true }, h(icons.chevron, { size: 14 }))),
|
|
170
|
+
settingsBody(open, 'ptc-plus-settings-body'),
|
|
171
|
+
openBindings,
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function PTCPlusSettingsDialog(props) {
|
|
176
|
+
const { t, onClose } = props
|
|
177
|
+
const body = React.useRef(null)
|
|
178
|
+
const [bindingsOpen, setBindingsOpen] = React.useState(false)
|
|
179
|
+
React.useEffect(() => {
|
|
180
|
+
const dialog = body.current?.closest('[role=dialog]')
|
|
181
|
+
const target = body.current?.querySelector(focusableSelector)
|
|
182
|
+
?? dialog?.querySelector(focusableSelector)
|
|
183
|
+
target?.focus({ preventScroll: true })
|
|
184
|
+
}, [])
|
|
185
|
+
React.useEffect(() => {
|
|
186
|
+
const trapFocus = event => {
|
|
187
|
+
if (event.key !== 'Tab' || bindingsOpen) return
|
|
188
|
+
const dialog = body.current?.closest('[role=dialog]')
|
|
189
|
+
if (dialog === undefined || dialog === null) return
|
|
190
|
+
const controls = [...dialog.querySelectorAll(focusableSelector)]
|
|
191
|
+
.filter(element => !element.closest('[hidden], [inert], [aria-hidden="true"]'))
|
|
192
|
+
const first = controls[0]
|
|
193
|
+
const last = controls.at(-1)
|
|
194
|
+
const active = document.activeElement
|
|
195
|
+
if (!dialog.contains(active)
|
|
196
|
+
|| (event.shiftKey && active === first)
|
|
197
|
+
|| (!event.shiftKey && active === last)) {
|
|
198
|
+
event.preventDefault()
|
|
199
|
+
;(event.shiftKey ? last : first)?.focus({ preventScroll: true })
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
document.addEventListener('keydown', trapFocus)
|
|
203
|
+
return () => document.removeEventListener('keydown', trapFocus)
|
|
204
|
+
}, [bindingsOpen])
|
|
205
|
+
const close = () => {
|
|
206
|
+
if (!bindingsOpen) onClose()
|
|
207
|
+
}
|
|
208
|
+
return h(Modal, {
|
|
209
|
+
open: true,
|
|
210
|
+
onClose: close,
|
|
211
|
+
title: t('settings.dialogTitle'),
|
|
212
|
+
closeLabel: t('settings.close'),
|
|
213
|
+
description: t('card.description'),
|
|
214
|
+
className: 'ptcPlusSettingsModal',
|
|
215
|
+
contentClassName: 'ptcPlusSettingsDialogContent',
|
|
216
|
+
}, h('div', { className: 'ptcPlusSettingsDialog', ref: body },
|
|
217
|
+
h(PTCPlusSettingsCard, { ...props, view: 'dialog', onBindingsOpenChange: setBindingsOpen })))
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return { PTCPlusSettingsCard, PTCPlusSettingsDialog }
|
|
221
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const CLIENT_STYLE_ID = 'ptc-plus-client-style'
|
|
2
|
+
const CLIENT_CSS = `
|
|
3
|
+
.ptcPlusBindingDockAnchor{position:relative;flex:none;block-size:0;min-width:0;width:min(calc(100% - 32px),44rem);margin-inline:auto}
|
|
4
|
+
.ptcPlusBindingDock{position:absolute;inset-inline:0;bottom:var(--ptc-plus-review-offset,8px);box-sizing:border-box;min-width:0;display:flex;flex-direction:column;border:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1));border-radius:14px;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-primary,#18191c);box-shadow:0 8px 32px rgba(0,0,0,.14),0 2px 6px rgba(0,0,0,.06);max-block-size:var(--ptc-plus-review-height,80dvh);overflow:auto;overscroll-behavior:contain}
|
|
5
|
+
.ptcPlusBindingDockHead{display:flex;flex:none;align-items:center;gap:4px;min-width:0;padding:0 10px 0 0}.ptcPlusBindingDockToggle{appearance:none;display:flex;flex:1;align-items:center;gap:10px;min-width:0;min-height:54px;padding:10px 12px;border:0;background:transparent;color:inherit;text-align:start;font:inherit;cursor:pointer}.ptcPlusBindingDockToggle:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}.ptcPlusBindingDockToggle:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);outline-offset:-3px}.ptcPlusBindingDockSymbol{display:grid;place-items:center;flex:none;width:30px;height:30px;border-radius:8px;background:var(--dsw-alias-bg-layer-2,#f3f4f6);color:var(--dsw-alias-label-secondary,#52565d);font:600 13px ui-monospace,monospace}.ptcPlusBindingDockHeading{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;font-size:13px;line-height:18px}.ptcPlusBindingDockHeading strong,.ptcPlusBindingDockHeading>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ptcPlusBindingDockHeading>span{font-size:11px;color:var(--dsw-alias-label-secondary,#52565d)}.ptcPlusBindingDockChevron{display:flex;flex:none;transform:rotate(180deg);transition:transform .16s ease}.ptcPlusBindingDockToggle[aria-expanded=true] .ptcPlusBindingDockChevron{transform:rotate(0deg)}
|
|
6
|
+
.ptcPlusBindingDockBody{flex:none;min-width:0;max-block-size:min(32dvh,20rem,var(--ptc-plus-review-space,100dvh));overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;border-top:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1))}.ptcPlusBindingDock[data-scroll=panel] .ptcPlusBindingDockBody{max-block-size:none;overflow:visible;scrollbar-gutter:auto}.ptcPlusBindingDockBody:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary);outline-offset:-2px}.ptcPlusBindingDockBody .ptcPlusAuthoringDraft{border:0;padding:12px 14px;background:transparent;gap:10px}.ptcPlusBindingDockBody .ptcPlusBindingCommandSource,.ptcPlusBindingDockBody .ptcPlusBindingCommandCode{max-height:none;margin:0}.ptcPlusBindingDockBody pre{font-size:12px;line-height:19px}.ptcPlusBindingDockBody .ptcPlusBindingMeta{font:11px/17px ui-monospace,monospace;overflow-wrap:anywhere}.ptcPlusBindingDockActions{display:flex;flex:none;flex-wrap:wrap;align-items:center;gap:6px;padding:10px 12px;border-top:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1))}.ptcPlusBindingDockActions>button{min-width:0;white-space:normal}.ptcPlusBindingDockDiscard{margin-inline-end:auto}.ptcPlusBindingDock .ptcPlusMessage{margin:0;font-size:12px;line-height:19px}.ptcPlusBindingDock>.ptcPlusMessage{padding:8px 12px}.ptcPlusComposerBindingAnchor{display:inline-flex;min-width:1px;min-height:1px}.ptcPlusComposerBindingAnchor .ptcPlusAuthorButton{position:relative}.ptcPlusDraftBadge{position:absolute;top:-2px;right:-3px;display:grid;place-items:center;box-sizing:border-box;min-width:14px;height:14px;padding-inline:3px;border:1.5px solid var(--dsw-alias-bg-base,#fff);border-radius:8px;background:var(--dsw-alias-state-business-primary,#4d6bfe);color:#fff;font:600 9px/1 system-ui,sans-serif;pointer-events:none}.ptcPlusDraftBadge[data-attention=true]{background:var(--dsw-alias-state-warning-primary,#a15c00)}.ptcPlusDraftMenuItem{display:flex;min-width:0;max-width:240px;flex-direction:column;gap:3px;white-space:normal;overflow-wrap:anywhere}.ptcPlusDraftMenuItem strong{font-size:12px;font-weight:600}.ptcPlusDraftMenuItem>span{font-size:11px;color:var(--dsw-alias-label-secondary,#52565d)}.ptcPlusComposerBindingAnchor[data-text=true] .ptcPlusAuthorButtonShell{width:auto}
|
|
7
|
+
.ptcPlusBindingCommand .ptcPlusMessage{margin:0}.ptcPlusBindingSourceDetails{min-width:0}.ptcPlusBindingSourceDetails>summary{cursor:pointer;font-size:12px;line-height:20px}.ptcPlusBindingItem>button,.ptcPlusGlobalItem>button{align-self:center}.ptcPlusAuthoringDraft>strong{font-size:13px;line-height:20px;overflow-wrap:anywhere}.ptcPlusBindingCommand .ptcPlusBindingCommandState{max-width:100%;box-sizing:border-box;white-space:normal}.ptcPlusBindingCommand .ptcPlusAuthoringDraft{min-width:0;padding:0;border:0;border-radius:0;background:transparent}
|
|
8
|
+
.ptcPlusCard{list-style:none;border:0.5px solid var(--dsw-alias-border-l4);border-radius:16px;background:var(--dsw-alias-bg-layer-3);overflow:hidden;transition:border-color .16s ease,background-color .16s ease}
|
|
9
|
+
.ptcPlusCard:hover{border-color:var(--dsw-alias-label-dimmed)}
|
|
10
|
+
.ptcPlusRow>.ptcPlusSelect{width:auto;max-width:100%;flex:none}
|
|
11
|
+
.ptcPlusCard[data-open=true]{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}
|
|
12
|
+
.ptcPlusHeader{appearance:none;width:100%;display:flex;align-items:center;gap:12px;padding:14px 16px;border:0;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer;border-radius:12px}
|
|
13
|
+
.ptcPlusHeader:hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusHeader:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}
|
|
14
|
+
.ptcPlusButton:focus-visible,.ptcPlusInput:focus-visible,.ptcPlusSelect:focus-visible,.ptcPlusTextarea:focus-visible,.ptcPlusBindingSelect:focus-visible,.ptcPlusReplBindingTrigger:focus-visible,.ptcPlusReplInspect:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}
|
|
15
|
+
.ptcPlusHeadText{display:flex;flex:1;min-width:0;flex-direction:column;align-items:flex-start;gap:3px}.ptcPlusName{font-size:15px;font-weight:600;line-height:1.4}.ptcPlusDescription{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5;overflow-wrap:anywhere}.ptcPlusStatus{display:inline-flex;align-items:center;flex:none;padding:1px 8px;border-radius:999px;corner-shape:round;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);font-size:11px;font-weight:500;line-height:17px;white-space:nowrap}.ptcPlusStatus[data-enabled=true]{color:var(--dsw-alias-state-success-primary);background:var(--dsw-alias-state-success-tertiary)}.ptcPlusStatus[data-enabled=false]{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-module-platform)}
|
|
16
|
+
.ptcPlusChevron{display:flex;color:var(--dsw-alias-label-tertiary);transition:transform .18s ease}.ptcPlusChevron[data-open=true]{transform:rotate(180deg)}.ptcPlusBody{display:grid;grid-template-rows:0fr;transition:grid-template-rows .2s ease}.ptcPlusBody[data-open=true]{grid-template-rows:1fr}.ptcPlusBodyInner{min-height:0;overflow:hidden}.ptcPlusFields{margin:0 16px;padding:8px 0 12px;border-top:0.5px solid var(--dsw-alias-border-l2)}
|
|
17
|
+
.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}.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{width:18px;height:18px;accent-color:var(--dsw-alias-brand-primary)}
|
|
18
|
+
.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}
|
|
19
|
+
.ptcPlusSettingAction{padding:4px 0 12px}
|
|
20
|
+
.ptcPlusSettingsModal.ptcPlusSettingsModal{width:min(760px,calc(100vw - 32px));max-width:none;max-height:calc(100dvh - 40px);border-radius:8px}.ptcPlusSettingsDialogContent{min-height:0;overflow:auto;overscroll-behavior:contain}.ptcPlusSettingsDialog{min-width:0}.ptcPlusSettingsDialog .ptcPlusFields{margin:0;padding:0 0 12px;border-top:0}
|
|
21
|
+
.ptcPlusDanger{color:var(--dsw-alias-state-error-primary)}
|
|
22
|
+
.ptcPlusActiveShell{display:inline-flex;align-items:center}.ptcPlusActive{appearance:none;display:inline-flex;height:24px;align-items:center;gap:5px;padding:0 8px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 32%,transparent);border-radius:6px;background:var(--dsw-alias-state-success-tertiary,#e7f7ef);color:var(--dsw-alias-state-success-primary,#16794f);cursor:help;font-family:inherit;font-size:12px;font-weight:600;line-height:18px;white-space:nowrap;transition:background-color .14s ease,border-color .14s ease}.ptcPlusActive:hover,.ptcPlusActive[aria-expanded=true]{border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 48%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 16%,var(--dsw-alias-bg-layer-3,#fff))}.ptcPlusActive:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary,#16794f);outline-offset:2px}.ptcPlusReplPopover{position:fixed;z-index:2147483000;inset:auto;display:none;box-sizing:border-box;margin:0;padding:0;border:0;overflow:visible;background:transparent;color:var(--dsw-alias-label-primary,#18191c)}.ptcPlusReplPopover:popover-open,.ptcPlusReplPopover[data-open=true]{display:block}.ptcPlusReplPopover::backdrop{background:transparent}.ptcPlusReplCard{display:flex;max-height:inherit;overflow:hidden;flex-direction:column;border:1px solid color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 22%,var(--dsw-alias-border-l2,rgba(0,0,0,.1)));border-top:3px solid var(--dsw-alias-state-success-primary,#16794f);border-radius:8px;background:var(--dsw-alias-bg-layer-3,#fff);box-shadow:0 14px 36px rgba(16,24,40,.2),0 3px 10px rgba(16,24,40,.1);color:var(--dsw-alias-label-primary,#18191c);white-space:normal}.ptcPlusReplHead{display:grid;flex:none;grid-template-columns:auto minmax(0,1fr);align-items:center;column-gap:8px;padding:11px 13px 10px;border-bottom:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));background:color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 7%,var(--dsw-alias-bg-layer-3,#fff))}.ptcPlusReplStatusDot{grid-row:1/3;width:8px;height:8px;border-radius:50%;background:var(--dsw-alias-state-success-primary,#16794f);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 14%,transparent)}.ptcPlusReplTitle,.ptcPlusReplSummary{display:block;min-width:0}.ptcPlusReplTitle{font-size:13px;font-weight:600;line-height:19px}.ptcPlusReplSummary{min-height:16px;overflow-wrap:anywhere;color:var(--dsw-alias-label-tertiary,#74777d);font-size:11px;line-height:16px}.ptcPlusReplList{min-height:0;margin:0;padding:5px 0;overflow:auto;overscroll-behavior:contain;list-style:none;scrollbar-gutter:stable}.ptcPlusReplBinding{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:4px 10px;padding:7px 12px}.ptcPlusReplBinding:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}.ptcPlusReplIdentity{display:flex;min-width:0;align-items:center;gap:7px}.ptcPlusReplName{min-width:0;overflow:hidden;font:12px/18px ui-monospace,SFMono-Regular,Consolas,monospace;text-overflow:ellipsis;white-space:nowrap}.ptcPlusReplKind{flex:none;padding:1px 6px;border:1px solid color-mix(in srgb,currentColor 22%,transparent);border-radius:999px;background:color-mix(in srgb,currentColor 10%,transparent);font-size:10px;font-weight:600;line-height:15px}.ptcPlusReplKind[data-kind=variable]{color:var(--dsw-alias-interactive-primary,#315fbd)}.ptcPlusReplKind[data-kind=function]{color:#7651b5}.ptcPlusReplKind[data-kind=class]{color:var(--dsw-alias-state-warning-primary,#946200)}.ptcPlusReplKind[data-kind=import]{color:#14766f}.ptcPlusReplPreview{grid-column:1;min-width:0;overflow:hidden;color:var(--dsw-alias-label-tertiary,#74777d);font:11px/16px ui-monospace,SFMono-Regular,Consolas,monospace;text-overflow:ellipsis;white-space:nowrap}.ptcPlusReplInspect{grid-column:2;grid-row:1/3;display:inline-flex;align-items:center;gap:4px;padding:3px 5px;border:0;border-radius:4px;background:transparent;color:var(--dsw-alias-label-secondary,#52565d);cursor:pointer;font:500 11px/17px inherit;white-space:nowrap}.ptcPlusReplInspect:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06));color:var(--dsw-alias-interactive-primary,#4d6bfe)}.ptcPlusReplInspect:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);outline-offset:1px}.ptcPlusReplDefinition{grid-column:1/-1;min-width:0;margin-top:4px;padding:8px;border-left:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);background:var(--dsw-alias-bg-layer-2,rgba(38,49,72,.03))}.ptcPlusReplLocation{display:block;margin-bottom:5px;color:var(--dsw-alias-label-tertiary,#74777d);font-size:10px;line-height:15px}.ptcPlusReplCode{max-height:180px;margin:0;overflow:auto;color:inherit;font:11px/16px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusReplEmpty,.ptcPlusReplMore{display:block;color:var(--dsw-alias-label-tertiary,#74777d)}.ptcPlusReplEmpty{padding:18px 13px;font-size:12px;line-height:18px}.ptcPlusReplMore{padding:8px 13px;border-top:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));background:var(--dsw-alias-bg-layer-2,rgba(38,49,72,.03));font-size:11px;line-height:17px}
|
|
23
|
+
.ptcPlusReplTabs{display:flex;flex:none;padding:6px 8px 0;border-bottom:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1))}.ptcPlusReplTab{flex:1;padding:5px 6px;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--dsw-alias-label-secondary,#52565d);cursor:pointer;font-family:inherit;font-size:11px;font-weight:600;line-height:17px}.ptcPlusReplTab[aria-selected=true]{border-bottom-color:var(--dsw-alias-interactive-primary,#4d6bfe);color:var(--dsw-alias-label-primary,#18191c)}.ptcPlusGlobalPane{display:flex;min-height:0;flex-direction:column;gap:8px;padding:8px 12px}.ptcPlusGlobalList{min-height:0;margin:0 -12px -8px;padding:5px 0;overflow:auto;list-style:none}.ptcPlusGlobalItem{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 10px;padding:7px 12px;border-radius:8px}.ptcPlusGlobalItem:hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusGlobalItem .ptcPlusGlobalSource,.ptcPlusGlobalItem .ptcPlusReplEmpty{grid-column:1/-1}.ptcPlusAuthoringDraft{display:flex;flex-direction:column;gap:6px;padding:10px 12px;border:0.5px solid var(--dsw-alias-border-l4);border-radius:12px;background:var(--dsw-alias-bg-layer-3)}.ptcPlusGlobalSource{max-height:180px;margin:6px 0 0;padding:8px 10px;overflow:auto;background:var(--dsw-alias-markdown-code-block);border-radius:8px;font:12px/18px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}
|
|
24
|
+
.ptcPlusReplList{max-height:min(52vh,480px)}.ptcPlusReplBinding{grid-template-columns:minmax(0,1fr) 24px;gap:3px 8px;min-height:36px;padding:5px 12px;content-visibility:auto;contain-intrinsic-size:36px;cursor:pointer;transition:background-color .16s ease}.ptcPlusReplBinding:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);outline-offset:-2px}.ptcPlusReplBinding[data-expanded=true]{background:color-mix(in srgb,var(--dsw-alias-interactive-primary,#4d6bfe) 5%,transparent)}.ptcPlusReplName{grid-column:1}.ptcPlusReplName[data-kind=variable]{color:var(--dsw-alias-interactive-primary,#315fbd)}.ptcPlusReplName[data-kind=function]{color:#7651b5}.ptcPlusReplName[data-kind=class]{color:var(--dsw-alias-state-warning-primary,#946200)}.ptcPlusReplName[data-kind=import]{color:#14766f}.ptcPlusReplPreview{grid-column:1}.ptcPlusReplChevron{grid-column:2;grid-row:1/3;display:flex;align-items:center;justify-content:center;color:var(--dsw-alias-label-tertiary,#74777d);transition:transform .2s ease}.ptcPlusReplChevron[data-open=true]{transform:rotate(180deg)}.ptcPlusReplDefinitionWrap{grid-column:1/-1;display:grid;grid-template-rows:0fr;min-width:0;transition:grid-template-rows .24s cubic-bezier(.2,.7,.2,1)}.ptcPlusReplDefinitionWrap[data-open=true]{grid-template-rows:1fr}.ptcPlusReplDefinitionInner{min-height:0;overflow:hidden}
|
|
25
|
+
.ptcPlusTool{display:flex;min-width:0;flex-direction:column}.ptcPlusToolPreview{display:flex;min-width:0;flex:1 1 auto;flex-direction:row;align-items:center;overflow:hidden;margin-left:7px}.ptcPlusToolPreview .ptcPlusFeatures{flex:0 1 auto;flex-wrap:nowrap;overflow:hidden;margin:0 0 0 7px}.ptcPlusToolSummaryLine{box-sizing:border-box;display:flex;min-width:0;min-height:20px;flex:1 1 auto;align-items:center;gap:7px;padding:0;color:inherit;line-height:20px}.ptcPlusToolSummary{box-sizing:border-box;display:flex;min-width:0;min-height:32px;align-items:center;gap:7px;padding:0;color:inherit;line-height:20px}.ptcPlusToolSummary[data-expandable=true]{cursor:pointer}.ptcPlusToolSummary[data-expandable=true]:hover .ptcPlusToolTitle{color:var(--dsw-alias-interactive-primary,#4d6bfe)}.ptcPlusToolSummary:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);outline-offset:2px}.ptcPlusToolLeading{display:flex;width:16px;height:20px;flex:none;align-items:center;justify-content:center;color:var(--dsw-alias-label-tertiary,#74777d)}.ptcPlusToolChevron{transition:transform .16s ease}.ptcPlusToolChevron[data-open=true]{transform:rotate(180deg)}.ptcPlusToolTitle{display:flex;height:20px;flex:none;align-items:center;font-size:13px;font-weight:500;line-height:20px}.ptcPlusToolState{display:flex;height:20px;flex:none;align-items:center;color:var(--dsw-alias-label-tertiary,#74777d);font-size:11px;line-height:20px}.ptcPlusToolSummaryLine[data-state=running] .ptcPlusToolState,.ptcPlusToolSummary[data-state=running] .ptcPlusToolState{color:var(--dsw-alias-interactive-primary,#4d6bfe)}.ptcPlusToolSummaryLine[data-state=error] .ptcPlusToolState,.ptcPlusToolSummary[data-state=error] .ptcPlusToolState{color:var(--dsw-alias-state-danger-primary,#c43d3d)}.ptcPlusToolSummaryLine[data-state=stopped] .ptcPlusToolState,.ptcPlusToolSummary[data-state=stopped] .ptcPlusToolState{color:var(--dsw-alias-state-warning-primary,#a15c00)}.ptcPlusToolSep{width:3px;height:3px;flex:none;border-radius:50%;background:var(--dsw-alias-label-tertiary,#74777d)}.ptcPlusToolDescription{display:flex;min-width:0;min-height:20px;flex:1 1 auto;align-items:center;overflow:hidden;color:var(--dsw-alias-label-secondary,#52565d);font-size:13px;line-height:20px;text-overflow:ellipsis;white-space:nowrap}.ptcPlusToolPreview .ptcPlusFeature{flex:none;max-width:180px;white-space:nowrap}.ptcPlusToolPreview .ptcPlusFeatureDetail{max-width:120px}.ptcPlusToolSummaryLine[data-state=error] .ptcPlusToolDescription,.ptcPlusToolSummary[data-state=error] .ptcPlusToolDescription{color:var(--dsw-alias-state-danger-primary,#c43d3d)}.ptcPlusToolSummaryLine[data-state=stopped] .ptcPlusToolDescription,.ptcPlusToolSummary[data-state=stopped] .ptcPlusToolDescription{color:var(--dsw-alias-state-warning-primary,#a15c00)}
|
|
26
|
+
.ptcPlusFeatures{display:flex;min-width:0;flex-wrap:wrap;gap:3px 14px;margin:0 0 5px 23px}.ptcPlusFeature{display:inline-flex;min-width:0;align-items:center;gap:5px;color:var(--dsw-alias-label-secondary,#52565d);font-size:11px;line-height:17px}.ptcPlusFeature::before{width:4px;height:4px;flex:none;border-radius:50%;background:var(--dsw-alias-interactive-primary,#4d6bfe);content:''}.ptcPlusFeatureName{font-weight:500}.ptcPlusFeatureDetail{min-width:0;overflow:hidden;color:var(--dsw-alias-label-tertiary,#74777d);font-family:ui-monospace,SFMono-Regular,Consolas,monospace;text-overflow:ellipsis;white-space:nowrap}
|
|
27
|
+
.ptcPlusToolBody{margin:4px 0 8px 23px;border-left:2px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));background:var(--dsw-alias-bg-layer-2,rgba(38,49,72,.03))}.ptcPlusToolSection{display:flex;min-width:0;flex-direction:column;gap:4px;padding:9px 11px}.ptcPlusToolSection+.ptcPlusToolSection{border-top:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1))}.ptcPlusToolSectionLabel{color:var(--dsw-alias-label-tertiary,#74777d);font-size:10px;font-weight:600;line-height:16px;text-transform:uppercase}.ptcPlusToolCode{max-height:320px;margin:0;overflow:auto;color:inherit;font:12px/18px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusIoCard{display:flex;flex-direction:column;border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.1));border-radius:12px;background:var(--dsw-alias-markdown-code-block,rgba(38,49,72,.06));overflow:hidden}.ptcPlusIoText{max-height:320px;margin:0;padding:12px 16px;overflow:auto;color:var(--dsw-alias-label-secondary,#52565d);font:12px/18px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusIoText[data-error]{color:var(--dsw-alias-state-error-primary,#c43d3d)}.ptcPlusInspect{display:inline-flex;align-self:flex-start;align-items:center;gap:4px;margin:4px 0 2px 4px;padding:2px 8px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));border-radius:999px;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-secondary,#52565d);cursor:pointer;opacity:0;font-size:11px;line-height:16px;transition:opacity .1s ease;display:inline-flex}.ptcPlusTool:hover .ptcPlusInspect,.ptcPlusInspect:focus-visible{opacity:1}.ptcPlusInspect:hover{background:var(--dsw-alias-interactive-bg-hover-solid,rgba(38,49,72,.06));color:var(--dsw-alias-label-primary,#18191c)}
|
|
28
|
+
.ptcPlusAuthorButtonShell{display:inline-flex;width:28px;height:28px;flex:none;align-items:center;justify-content:center}.ptcPlusAuthorButton{appearance:none;display:inline-flex;box-sizing:border-box;width:28px;height:28px;align-items:center;justify-content:center;padding:0;border:0;border-radius:6px;background:transparent;color:var(--dsw-alias-label-secondary,#52565d);cursor:pointer}.ptcPlusAuthorButton:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06));color:var(--dsw-alias-interactive-primary,#4d6bfe)}.ptcPlusAuthorButton:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);outline-offset:1px}.ptcPlusAuthorButtonShell[data-text=true]{width:auto}.ptcPlusAuthorButtonLabel{padding:0 4px;font-size:12px;line-height:18px;font-weight:500}.ptcPlusComposerNotice{max-width:160px;color:var(--dsw-alias-label-secondary,#52565d);font-size:11px;line-height:17px;overflow-wrap:anywhere}.ptcPlusButton>svg{flex:none;margin-right:5px;vertical-align:-2px}
|
|
29
|
+
@media(max-width:760px){.ptcPlusBindingsGrid{grid-template-columns:1fr}.ptcPlusBindingFields{grid-template-columns:1fr}.ptcPlusBindingField[data-wide=true]{grid-column:auto}.ptcPlusBindingSourceGrid{grid-template-columns:1fr}.ptcPlusBindingDebugBody{grid-template-columns:1fr}.ptcPlusBindingDebugBody .ptcPlusButton{width:100%}.ptcPlusBindingDebugWarning{grid-column:1}}
|
|
30
|
+
@media(max-width:560px){.ptcPlusHeader{padding:12px}.ptcPlusFields{margin:0 12px}.ptcPlusSettingsModal.ptcPlusSettingsModal{width:calc(100vw - 16px);max-height:calc(100dvh - 16px)}.ptcPlusSettingsDialog .ptcPlusFields{margin:0}.ptcPlusRow{align-items:flex-start;flex-direction:column;gap:6px;padding:10px 0}.ptcPlusInput{width:100%}.ptcPlusFooter,.ptcPlusBindingsHead{align-items:stretch;flex-direction:column}.ptcPlusButton{width:100%}.ptcPlusFeatures,.ptcPlusToolBody{margin-left:0}.ptcPlusToolSummary .ptcPlusToolDescription{white-space:normal;overflow-wrap:anywhere}}
|
|
31
|
+
@media(prefers-reduced-motion:reduce){.ptcPlusHeader,.ptcPlusChevron,.ptcPlusBody,.ptcPlusButton,.ptcPlusActive,.ptcPlusToolChevron,.ptcPlusReplChevron,.ptcPlusReplDefinitionWrap,.ptcPlusInspect,.ptcPlusBindingDockChevron{transition:none}}
|
|
32
|
+
/* The summary button owns disclosure; definition content is a separate grid item. */
|
|
33
|
+
.ptcPlusReplBinding{padding:0;cursor:default}.ptcPlusReplBindingTrigger{appearance:none;display:grid;width:100%;grid-column:1/-1;grid-template-columns:minmax(0,1fr) 24px;gap:3px 8px;min-height:36px;padding:5px 12px;border:0;background:transparent;color:inherit;text-align:left;cursor:pointer;font:inherit;transition:background-color .16s ease}.ptcPlusReplBindingTrigger:hover,.ptcPlusReplBindingTrigger[aria-expanded=true]{background:color-mix(in srgb,var(--dsw-alias-interactive-primary,#4d6bfe) 5%,transparent)}.ptcPlusReplBindingTrigger:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);outline-offset:-2px}
|
|
34
|
+
/* High-contrast TypeScript-like token colors adapt to the active text theme. */
|
|
35
|
+
.ptcPlusReplCard .ptcPlusReplName[data-kind=variable]{color:color-mix(in srgb,#005cc5 78%,var(--dsw-alias-label-primary,#18191c))}
|
|
36
|
+
.ptcPlusReplCard .ptcPlusReplName[data-kind=function]{color:color-mix(in srgb,#795e26 78%,var(--dsw-alias-label-primary,#18191c))}
|
|
37
|
+
.ptcPlusReplCard .ptcPlusReplName[data-kind=class]{color:color-mix(in srgb,#267f99 78%,var(--dsw-alias-label-primary,#18191c))}
|
|
38
|
+
.ptcPlusReplCard .ptcPlusReplName[data-kind=import]{color:color-mix(in srgb,#af00db 78%,var(--dsw-alias-label-primary,#18191c))}
|
|
39
|
+
/* Keep the session-header action on the same compact 32px rhythm as DSH chrome. */
|
|
40
|
+
.ptcPlusActiveShell{display:inline-flex;height:28px;align-items:center;justify-content:center;line-height:0;vertical-align:middle}.ptcPlusActive{box-sizing:border-box;height:28px;justify-content:center;gap:6px;padding:0 6px;border:0;background:transparent;font-family:inherit;font-size:13px;font-weight:500;line-height:18px}.ptcPlusActive::before{width:6px;height:6px;flex:none;border-radius:50%;background:currentColor;box-shadow:0 0 0 2px color-mix(in srgb,currentColor 18%,transparent);content:''}.ptcPlusActive:hover,.ptcPlusActive[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}.ptcPlusActiveLabel{display:inline-flex;height:18px;align-items:center;line-height:18px}
|
|
41
|
+
@media(max-width:560px){.ptcPlusActiveShell{display:none}}
|
|
42
|
+
[role=menu]:has(.ptcPlusBindingMenuAction,.ptcPlusDraftMenuItem){width:min(320px,calc(100vw - 24px));min-width:0;max-height:min(440px,60dvh,var(--ptc-plus-menu-space,100dvh));border-radius:12px}.ptcPlusBindingQuickRow{display:flex;min-width:0;flex-direction:column;gap:3px;white-space:normal}.ptcPlusBindingQuickName{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px}.ptcPlusBindingQuickName strong{min-width:0;overflow:hidden;text-overflow:ellipsis;font-weight:500;white-space:nowrap}.ptcPlusBindingQuickState{flex:none;font-size:11px;color:var(--dsw-alias-label-tertiary)}.ptcPlusBindingQuickRow[data-enabled=true] .ptcPlusBindingQuickState{color:var(--dsw-alias-state-success-primary)}.ptcPlusBindingQuickPurpose{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:12px}.ptcPlusBindingMenuAction{font-size:13px}
|
|
43
|
+
`
|
|
44
|
+
|
|
45
|
+
const BINDING_WORKBENCH_CSS = `
|
|
46
|
+
.ptcPlusCandidateContext{min-width:0;margin-top:4px;padding:12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-module-platform)}.ptcPlusCandidateContext h4{margin:0 0 10px;color:var(--dsw-alias-label-primary);font-size:12px;font-weight:600;line-height:18px}.ptcPlusCandidateContext dl{display:grid;gap:12px;margin:0}.ptcPlusCandidateContext dt{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:20px}.ptcPlusCandidateContext dd{min-width:0;margin:0}.ptcPlusCandidateDeclaration{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:4px 12px}.ptcPlusCandidateDeclaration dd{display:inline-flex;align-items:center;gap:4px;max-width:100%;box-sizing:border-box;padding:2px 8px;border-radius:6px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-secondary);font-size:11px;line-height:18px;overflow-wrap:anywhere}.ptcPlusCandidateDeclaration dd[data-included=true]{background:var(--dsw-alias-state-business-tertiary);color:var(--dsw-alias-state-business-primary)}.ptcPlusCandidateDeclaration svg{flex:none}.ptcPlusCandidatePrompt{display:grid;gap:6px}.ptcPlusCandidatePrompt dd{padding:8px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font-size:12px;line-height:20px;white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusCandidatePrompt dd[data-empty=true]{padding:0;border:0;background:transparent;color:var(--dsw-alias-label-tertiary)}
|
|
47
|
+
.ptcPlusBindings{margin-top:16px;padding-top:14px;border-top:0.5px solid var(--dsw-alias-border-l2)}.ptcPlusBindingsHead{display:flex;align-items:center;justify-content:space-between;gap:12px}.ptcPlusBindingsTitle{margin:0;font-size:15px;font-weight:600;line-height:1.4}.ptcPlusBindingsActions{display:flex;flex-wrap:wrap;gap:8px}.ptcPlusBindingsGrid{display:grid;grid-template-columns:minmax(240px,.7fr) minmax(340px,1.3fr);gap:12px;margin-top:12px;align-items:start}.ptcPlusBindingPane{display:flex;min-width:0;flex-direction:column;gap:8px}
|
|
48
|
+
.ptcPlusBindingList{display:flex;min-width:0;margin:0;padding:8px;flex-direction:column;gap:2px;border:0.5px solid var(--dsw-alias-border-l4);border-radius:16px;background:var(--dsw-alias-bg-layer-3);list-style:none}.ptcPlusBindingItem{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:2px 10px;padding:6px 8px;border-radius:8px;transition:background-color .12s ease}.ptcPlusBindingItem:hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusBindingItem[data-selected=true]{background:var(--dsw-alias-bg-module-platform)}.ptcPlusBindingSelect{display:flex;min-width:0;padding:0;border:0;background:transparent;color:inherit;text-align:left;cursor:pointer;flex-direction:column;align-items:flex-start;gap:1px}.ptcPlusBindingSelect:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.ptcPlusBindingName{display:block;min-width:0;max-width:100%;overflow:hidden;font:500 13px/20px ui-monospace,SFMono-Regular,Consolas,monospace;text-overflow:ellipsis;white-space:nowrap}.ptcPlusBindingMeta{display:block;min-width:0;max-width:100%;overflow:hidden;color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px;text-overflow:ellipsis;white-space:nowrap}.ptcPlusBindingState{display:inline-flex;align-items:center;gap:5px;padding:1px 8px;border-radius:999px;corner-shape:round;font-size:11px;font-weight:500;line-height:17px;white-space:nowrap}.ptcPlusBindingState[data-enabled=true]{color:var(--dsw-alias-state-success-primary);background:var(--dsw-alias-state-success-tertiary)}.ptcPlusBindingState[data-enabled=false]{color:var(--dsw-alias-state-warn-primary);background:var(--dsw-alias-state-warn-tertiary)}.ptcPlusBindingStateDot{width:6px;height:6px;border-radius:50%;background:currentColor}.ptcPlusBindingToggle{grid-column:2;grid-row:1/3;align-self:center;justify-self:end;min-height:26px;padding:2px 10px;font-size:12px;line-height:17px;border-radius:999px;corner-shape:round}.ptcPlusBindingRun{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding-top:10px;border-top:0.5px solid var(--dsw-alias-border-l2)}.ptcPlusBindingRun .ptcPlusInput{flex:1;min-width:160px;width:auto}
|
|
49
|
+
.ptcPlusBindingEditor{display:flex;min-width:0;flex-direction:column;border:0.5px solid var(--dsw-alias-border-l4);border-radius:16px;background:var(--dsw-alias-bg-layer-3);overflow:hidden}.ptcPlusBindingSection{display:flex;min-width:0;flex-direction:column;gap:12px;padding:14px 16px}.ptcPlusBindingSection+.ptcPlusBindingSection{border-top:0.5px solid var(--dsw-alias-border-l2)}.ptcPlusBindingSectionTitle{margin:0;font-size:13px;font-weight:600;line-height:1.5}.ptcPlusBindingFields{display:grid;min-width:0;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 12px}.ptcPlusBindingField{display:flex;min-width:0;flex-direction:column;gap:5px}.ptcPlusBindingField[data-wide=true]{grid-column:1/-1}.ptcPlusBindingFieldLabel{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}.ptcPlusBindingEditor .ptcPlusInput,.ptcPlusSelect{box-sizing:border-box;width:100%;min-width:0;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}.ptcPlusBindingEditor .ptcPlusInput:focus-visible,.ptcPlusSelect:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.ptcPlusTextarea{box-sizing:border-box;width:100%;min-height:220px;resize:vertical;padding:10px 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:12px/18px ui-monospace,SFMono-Regular,Consolas,monospace;tab-size:2}.ptcPlusTextarea:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.ptcPlusDeclaration{box-sizing:border-box;max-height:220px;margin:0;padding:12px;overflow:auto;background:var(--dsw-alias-markdown-code-block);border-radius:12px;color:var(--dsw-alias-label-primary);font:12px/18px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusBindingSourceGrid{display:grid;min-width:0;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px}.ptcPlusBindingSourceEditor,.ptcPlusBindingSourcePreview{display:flex;min-width:0;flex-direction:column;gap:6px}.ptcPlusBindingSourcePreview .ptcPlusCodeBlock{max-height:220px;overflow:auto}
|
|
50
|
+
.ptcPlusBindingLifecycle{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:8px}.ptcPlusBindingDebug{display:flex;min-width:0;flex-direction:column;gap:10px;padding:12px 16px;border-top:0.5px solid var(--dsw-alias-border-l2)}.ptcPlusBindingDebugSummary{display:flex;align-items:center;gap:6px;margin:0;cursor:pointer;color:var(--dsw-alias-label-secondary);font-size:13px;font-weight:500;line-height:1.5;list-style:none}.ptcPlusBindingDebugSummary::-webkit-details-marker{display:none}.ptcPlusBindingDebugSummary::after{content:'';width:7px;height:7px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(45deg);transition:transform .16s ease}.ptcPlusBindingDebug[open] .ptcPlusBindingDebugSummary::after{transform:rotate(-135deg)}.ptcPlusBindingDebugBody{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto;align-items:end;gap:10px}.ptcPlusBindingDebugBody .ptcPlusBindingField{min-width:0}.ptcPlusBindingDebugBody .ptcPlusButton{align-self:end}.ptcPlusBindingDebugWarning{grid-column:1/-1;color:var(--dsw-alias-state-warn-label);font-size:12px;line-height:1.5}.ptcPlusBindingOutput{grid-column:1/-1;margin:0;padding:10px 12px;overflow:auto;background:var(--dsw-alias-markdown-code-block);border-radius:8px;color:var(--dsw-alias-label-secondary);font:12px/18px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}
|
|
51
|
+
.ptcPlusBindingCommand{display:flex;min-width:0;flex-direction:column;gap:6px;margin:6px 0 10px;padding:10px 12px;border:0.5px solid var(--dsw-alias-border-l4);border-radius:8px;background:var(--dsw-alias-bg-layer-3)}.ptcPlusBindingCommandHeader{display:flex;min-width:0;flex-wrap:wrap;align-items:center;gap:8px}.ptcPlusBindingCommandTitle{margin:0;font-size:13px;font-weight:600;line-height:1.5}.ptcPlusBindingCommandState{display:inline-flex;align-items:center;gap:5px;padding:1px 8px;border-radius:999px;corner-shape:round;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);font-size:11px;font-weight:500;line-height:17px;white-space:nowrap}.ptcPlusBindingCommand[data-phase=pending] .ptcPlusBindingCommandState{background:var(--dsw-alias-state-business-tertiary);color:var(--dsw-alias-state-business-primary)}.ptcPlusBindingCommand[data-phase=ready] .ptcPlusBindingCommandState{background:var(--dsw-alias-state-success-tertiary);color:var(--dsw-alias-state-success-primary)}.ptcPlusBindingCommand[data-phase=failed] .ptcPlusBindingCommandState{background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.ptcPlusBindingCommandStateDot{width:6px;height:6px;border-radius:50%;background:currentColor}.ptcPlusBindingCommandRequirement{margin:0;overflow:auto;color:var(--dsw-alias-label-primary);font:12px/18px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusBindingCommandSource{max-height:280px;margin:0;padding:10px 12px;overflow:auto;background:var(--dsw-alias-markdown-code-block);border-radius:8px;color:var(--dsw-alias-label-primary);font:12px/18px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusBindingCommandCode{max-height:300px;overflow:auto}.ptcPlusBindingCommandActions{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:8px}
|
|
52
|
+
|
|
53
|
+
`
|
|
54
|
+
|
|
55
|
+
const REPL_CONSOLE_CSS = `
|
|
56
|
+
.ptcPlusBindingsSurface .ptcPlusBindingSection.ptcPlusModelPrompt{padding:12px 0}.ptcPlusModelPrompt .ptcPlusBindingSectionTitle{margin:0 0 10px}.ptcPlusModelPrompt textarea.ptcPlusInput{height:auto;min-height:80px;padding:8px 12px;resize:vertical}.ptcPlusModelPrompt .ptcPlusPromptToggle{flex-direction:row;align-items:center;justify-content:space-between;cursor:pointer}.ptcPlusModelPrompt .ptcPlusCheck{flex:none}.ptcPlusEditorHead .ptcPlusBindingLifecycle{min-width:0}.ptcPlusEditorHead .ptcPlusButton{width:auto}
|
|
57
|
+
.ptcPlusConsole{box-sizing:border-box;flex:1;min-width:0;min-height:0;width:100%;height:100%;overflow:auto;padding:20px 24px;color:var(--dsw-alias-label-primary);container-type:inline-size}
|
|
58
|
+
.ptcPlusConsoleSection{min-width:0}.ptcPlusConsoleSection+.ptcPlusConsoleSection{margin-top:22px;padding-top:20px;border-top:1px solid var(--dsw-alias-border-l2)}
|
|
59
|
+
.ptcPlusObservationHead,.ptcPlusObservationTitle{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px}.ptcPlusObservationHead{justify-content:space-between;margin-bottom:14px}
|
|
60
|
+
.ptcPlusObservationTitle h2{margin:0;font-size:15px;font-weight:600;line-height:22px}.ptcPlusObservationCount{font-size:13px;color:var(--dsw-alias-label-tertiary)}.ptcPlusObservationTime{font-size:11px;line-height:18px;color:var(--dsw-alias-label-tertiary)}
|
|
61
|
+
.ptcPlusObservationGrid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:24px}.ptcPlusObservationCatalog{min-width:0}
|
|
62
|
+
.ptcPlusObservationFilters{display:flex;gap:10px;align-items:center;margin-bottom:8px}.ptcPlusObservationFilters>.ptcPlusSelect{width:120px;height:32px;flex:none;font-size:12px}
|
|
63
|
+
.ptcPlusSearch{display:flex;align-items:center;gap:8px;box-sizing:border-box;min-width:0;flex:1;height:32px;padding:0 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;color:var(--dsw-alias-label-tertiary)}
|
|
64
|
+
.ptcPlusSearch>svg{flex:none}.ptcPlusSearch input{min-width:0;width:100%;height:100%;padding:0;border:0;outline:none;background:transparent;color:var(--dsw-alias-label-primary);font:12px/20px inherit}.ptcPlusSearch:focus-within{outline:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);outline-offset:1px}
|
|
65
|
+
.ptcPlusObservations{height:256px;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;min-width:0;border:1px solid var(--dsw-alias-border-l2);border-radius:6px}
|
|
66
|
+
.ptcPlusObservationTable{width:100%;table-layout:fixed;border-collapse:separate;border-spacing:0;font-size:12px;text-align:left}.ptcPlusObservationTable th{position:sticky;top:0;z-index:1;height:32px;padding:0 10px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-tertiary);font-weight:500;border-bottom:1px solid var(--dsw-alias-border-l2)}
|
|
67
|
+
.ptcPlusObservationTable th:first-child{width:34%}.ptcPlusObservationTable th:nth-child(2){width:16%}.ptcPlusObservationTable th:nth-child(3){width:72px}.ptcPlusObservationTable td{height:34px;padding:0 10px;border-bottom:1px solid var(--dsw-alias-border-l2);overflow:hidden}.ptcPlusObservationTable tr:last-child td{border-bottom:0}.ptcPlusObservationTable tbody tr{cursor:pointer}.ptcPlusObservationTable tbody tr:hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusObservationTable tr[data-selected=true]{background:color-mix(in srgb,var(--dsw-alias-interactive-primary,#4d6bfe) 7%,transparent)}
|
|
68
|
+
.ptcPlusObservationSelect{display:block;width:100%;min-width:0;height:34px;padding:0;border:0;background:transparent;color:inherit;cursor:pointer;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:12px/20px ui-monospace,SFMono-Regular,Consolas,monospace}.ptcPlusObservationKind{color:var(--dsw-alias-label-tertiary);white-space:nowrap}
|
|
69
|
+
.ptcPlusObservationValue{display:flex;min-width:0;align-items:center;gap:6px}.ptcPlusObservationValue code{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:11px/18px ui-monospace,SFMono-Regular,Consolas,monospace}.ptcPlusObservationState{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:18px}.ptcPlusObservationValue .ptcPlusObservationState{flex:none}.ptcPlusObservationEmpty{padding:12px}
|
|
70
|
+
.ptcPlusBindingInspector{box-sizing:border-box;min-width:0;max-height:296px;overflow:auto;padding-left:24px;border-left:1px solid var(--dsw-alias-border-l2)}
|
|
71
|
+
.ptcPlusInspectorHead{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px 12px;margin:0 0 12px}.ptcPlusInspectorHead strong{min-width:0;overflow-wrap:anywhere;font:600 13px/20px ui-monospace,SFMono-Regular,Consolas,monospace}.ptcPlusInspectorHead span{font-size:11px;color:var(--dsw-alias-label-tertiary)}
|
|
72
|
+
.ptcPlusObservationLabel{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:12px 0 6px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary)}
|
|
73
|
+
.ptcPlusObservationCode{max-height:184px;margin:0;overflow:auto;border-radius:6px;font:12px/20px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusObservationPreview{margin:0;padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;white-space:pre-wrap;overflow-wrap:anywhere;font:12px/20px ui-monospace,SFMono-Regular,Consolas,monospace}.ptcPlusObservationUnavailable{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px}
|
|
74
|
+
.ptcPlusBindingsSurface{min-width:0;container-type:inline-size}.ptcPlusBindingsSurface .ptcPlusBindings{margin:0;padding:0;border:0}.ptcPlusBindingsSurface .ptcPlusBindingsGrid{grid-template-columns:220px minmax(0,1fr);gap:20px;margin-top:12px}.ptcPlusBindingsSurface .ptcPlusBindingsTitle{font-size:15px;line-height:22px}
|
|
75
|
+
.ptcPlusBindingPane{min-width:0}.ptcPlusBindingPane>.ptcPlusSearch{flex:none;margin-bottom:2px}.ptcPlusBindingsSurface .ptcPlusBindingsHead{flex-direction:row;flex-wrap:wrap;align-items:center;gap:8px}.ptcPlusBindingsSurface .ptcPlusBindingList{max-height:350px;overflow:auto;gap:0;padding:0;border:0;border-radius:0;background:transparent}.ptcPlusBindingsSurface .ptcPlusBindingItem{min-height:52px;padding:8px;border-radius:4px;box-sizing:border-box;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusBindingsSurface .ptcPlusBindingItem[data-selected=true]{background:color-mix(in srgb,var(--dsw-alias-interactive-primary,#4d6bfe) 7%,transparent)}
|
|
76
|
+
.ptcPlusBindingsSurface .ptcPlusBindingName{font-size:12px;font-weight:500;white-space:normal;overflow-wrap:anywhere}.ptcPlusBindingsSurface .ptcPlusBindingMeta{font-size:11px;line-height:16px}.ptcPlusBindingsSurface .ptcPlusBindingEditor{border:0;border-radius:0;background:transparent;overflow:visible}
|
|
77
|
+
.ptcPlusBindingSwitch{appearance:none;position:relative;align-self:center;flex:none;width:30px;height:18px;padding:2px;border:0;border-radius:9px;background:var(--dsw-alias-label-dimmed,#a5a7ad);cursor:pointer}.ptcPlusBindingSwitch span{display:block;width:14px;height:14px;border-radius:50%;background:#fff;box-shadow:0 1px 2px #0002;transition:transform .15s ease}.ptcPlusBindingSwitch[aria-checked=true]{background:var(--dsw-alias-interactive-primary,#4d6bfe)}.ptcPlusBindingSwitch[aria-checked=true] span{transform:translateX(12px)}.ptcPlusBindingSwitch:disabled{cursor:not-allowed;opacity:.5}
|
|
78
|
+
.ptcPlusEditorHead{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-height:32px;margin-bottom:8px}.ptcPlusEditorFile{min-width:0;overflow-wrap:anywhere;font:600 13px/20px ui-monospace,SFMono-Regular,Consolas,monospace}.ptcPlusBindingLifecycle{gap:6px}
|
|
79
|
+
.ptcPlusIconButton{display:inline-flex;align-items:center;justify-content:center;flex:none;box-sizing:border-box;width:30px;height:30px;padding:0;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer}.ptcPlusIconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusIconButton[data-kind=danger]:hover{color:var(--dsw-alias-state-error-primary)}.ptcPlusIconButton:disabled{opacity:.4;cursor:not-allowed}
|
|
80
|
+
.ptcPlusCodeEditor{min-width:0;overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;--ptc-code-keyword:color-mix(in srgb,#a13d96 75%,var(--dsw-alias-label-primary));--ptc-code-string:color-mix(in srgb,#af643c 75%,var(--dsw-alias-label-primary));--ptc-code-number:color-mix(in srgb,#477ac2 75%,var(--dsw-alias-label-primary));--ptc-code-type:color-mix(in srgb,#258579 75%,var(--dsw-alias-label-primary));--ptc-code-function:color-mix(in srgb,#825bbe 75%,var(--dsw-alias-label-primary))}.ptcPlusCodeEditor:focus-within{border-color:var(--dsw-alias-interactive-primary,#4d6bfe)}.ptcPlusCodeEditor .cm-editor{height:336px}.ptcPlusCodeEditor .cm-scroller{min-height:0}.ptcPlusCodeEditor .cm-line{overflow-wrap:anywhere}
|
|
81
|
+
.ptcPlusBindingsSurface .ptcPlusBindingSection{display:block;padding:0;margin-top:0;border:0;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusBindingSection>summary,.ptcPlusBindingsSurface .ptcPlusBindingDebugSummary{padding:11px 0;cursor:pointer;font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary)}.ptcPlusEntrySettings .ptcPlusBindingFields{padding:0 0 14px}.ptcPlusBindingsSurface .ptcPlusBindingSourcePreview{display:block}.ptcPlusBindingSourcePreview>.ptcPlusCodeBlock{margin-bottom:12px}.ptcPlusBindingsSurface .ptcPlusBindingDebug{display:block;padding:0;border-top:0}.ptcPlusBindingsSurface .ptcPlusBindingDebugBody{grid-template-columns:minmax(0,1fr) minmax(0,1fr);padding-bottom:12px}
|
|
82
|
+
.ptcPlusBindingsSurface .ptcPlusBindingRun{gap:6px;margin-top:10px}.ptcPlusBindingsSurface .ptcPlusBindingRun .ptcPlusInput{flex-basis:100%;min-width:0;width:100%;height:32px;font-size:12px}.ptcPlusBindingsSurface .ptcPlusMessage[role=status]{grid-column:1/-1;margin:0}
|
|
83
|
+
.ptcPlusSessionEmpty{box-sizing:border-box;width:100%;padding:16px 18px;border:1px dashed var(--dsw-alias-border-l2);border-radius:6px;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px}.ptcPlusObservationGrid[data-empty=true]{grid-template-columns:minmax(0,1fr)}.ptcPlusObservationGrid[data-empty=true] .ptcPlusObservations{height:auto;min-height:94px}
|
|
84
|
+
.ptcPlusSourceSection{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:0 12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusSourceToggle{display:flex;min-width:0;align-items:center;gap:6px;padding:12px 0;border:0;background:transparent;color:var(--dsw-alias-label-secondary);text-align:left;cursor:pointer;font:500 12px/20px inherit}.ptcPlusSourceToggle svg{flex:none}.ptcPlusSourceFilename{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font:11px/20px ui-monospace,SFMono-Regular,Consolas,monospace}.ptcPlusSourceActions{display:flex;flex-wrap:wrap;gap:6px;padding:6px 0}.ptcPlusSourceBody{grid-column:1/-1;min-width:0;margin-bottom:12px}.ptcPlusSourceCode{max-height:336px;overflow:auto;margin:0;border-radius:6px;font:12px/20px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}
|
|
85
|
+
.ptcPlusWorkbenchFeedback{min-height:22px;padding:4px 0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;overflow-wrap:anywhere}.ptcPlusBindings[aria-busy=true] button:disabled,.ptcPlusBindings[aria-busy=true] input:disabled{opacity:1}.ptcPlusBindings[aria-busy=true] button:disabled{cursor:wait}
|
|
86
|
+
.ptcPlusExecution{min-width:0;margin:0 0 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;overflow:hidden;background:var(--dsw-alias-bg-layer-3)}.ptcPlusExecution>summary{padding:10px 12px;cursor:pointer;font-size:12px;font-weight:500;line-height:20px;color:var(--dsw-alias-label-secondary)}.ptcPlusExecutionToolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px 12px;border-top:1px solid var(--dsw-alias-border-l2);border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusExecutionLanguage{font:11px/18px ui-monospace,SFMono-Regular,Consolas,monospace;color:var(--dsw-alias-label-secondary)}.ptcPlusExecutionState{font-size:11px;line-height:18px;color:var(--dsw-alias-label-tertiary)}.ptcPlusExecutionActions{display:flex;align-items:center;gap:6px;margin-left:auto}.ptcPlusExecutionActions .ptcPlusButton{min-width:68px;min-height:30px;padding:3px 10px;font-size:12px}
|
|
87
|
+
.ptcPlusExecutionHistory{min-height:48px;max-height:320px;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable}.ptcPlusExecutionHistory:empty{min-height:0}.ptcPlusExecutionRecord{min-width:0;padding:10px 12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusExecutionCommand,.ptcPlusExecutionOutput{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font:12px/20px ui-monospace,SFMono-Regular,Consolas,monospace}.ptcPlusExecutionCommand{color:var(--dsw-alias-label-secondary)}.ptcPlusExecutionCommand>span{color:var(--dsw-alias-label-tertiary)}.ptcPlusExecutionResult{flex-direction:row;gap:12px;margin-top:8px;padding:12px 16px}.ptcPlusExecutionOutputLabel{flex:none;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px}.ptcPlusExecutionOutput{flex:1;min-width:0;max-height:240px;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;color:var(--dsw-alias-label-secondary)}.ptcPlusExecutionOutput:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary);outline-offset:-2px}.ptcPlusExecutionOutput[data-error=true]{color:var(--dsw-alias-state-error-primary)}.ptcPlusExecutionDuration{display:block;margin-top:4px;color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:16px}.ptcPlusExecutionInput .ptcPlusCodeEditor{border:0;border-radius:0}.ptcPlusExecutionInput .cm-editor{height:108px}.ptcPlusExecutionInput .cm-content{min-height:88px}
|
|
88
|
+
@container(max-width:460px){.ptcPlusSourceSection{grid-template-columns:minmax(0,1fr)}.ptcPlusSourceToggle{padding-bottom:6px}.ptcPlusSourceActions{justify-content:flex-end}.ptcPlusExecutionToolbar{gap:6px;padding:8px}.ptcPlusExecutionActions{gap:4px}.ptcPlusSourceFilename{display:none}}
|
|
89
|
+
.ptcPlusBindingsModal.ptcPlusBindingsModal{width:min(1200px,calc(100vw - 32px));max-width:none;max-height:calc(100dvh - 40px);border-radius:8px}.ptcPlusBindingsDialog{box-sizing:border-box;max-height:calc(100dvh - 40px);overflow:auto;padding:24px}.ptcPlusBindingsDialogHead{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:16px}.ptcPlusBindingsDialogHead h2{margin:0;font-size:17px;line-height:24px}.ptcPlusDialogClose{display:flex;flex:none;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:0;border-radius:4px;background:transparent;color:inherit;cursor:pointer}.ptcPlusDialogClose:hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusConsole button:focus-visible,.ptcPlusBindingsDialog button:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary);outline-offset:-2px}
|
|
90
|
+
@container(max-width:780px){.ptcPlusObservationGrid{grid-template-columns:minmax(0,1fr);gap:16px}.ptcPlusBindingInspector{max-height:none;padding:12px 0 0;border-left:0;border-top:1px solid var(--dsw-alias-border-l2)}.ptcPlusObservations{height:200px}.ptcPlusBindingsSurface .ptcPlusBindingsGrid{grid-template-columns:minmax(0,1fr);gap:18px}.ptcPlusBindingsSurface .ptcPlusBindingList{max-height:180px}.ptcPlusBindingsSurface .ptcPlusBindingFields,.ptcPlusBindingsSurface .ptcPlusBindingDebugBody{grid-template-columns:minmax(0,1fr)}.ptcPlusObservationTable th:first-child{width:35%}.ptcPlusObservationTable th:nth-child(2){width:64px}.ptcPlusObservationTable th:nth-child(3){width:64px}}
|
|
91
|
+
@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>.ptcPlusSelect{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}}
|
|
92
|
+
.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}
|
|
93
|
+
.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}
|
|
94
|
+
`
|
|
95
|
+
|
|
96
|
+
/** Install the plugin stylesheet once; returns the disposer that removes it. */
|
|
97
|
+
function installStyles() {
|
|
98
|
+
if (document.getElementById(CLIENT_STYLE_ID) !== null) return () => {}
|
|
99
|
+
const style = document.createElement('style')
|
|
100
|
+
style.id = CLIENT_STYLE_ID
|
|
101
|
+
style.textContent = `${CLIENT_CSS}${BINDING_WORKBENCH_CSS}${REPL_CONSOLE_CSS}`
|
|
102
|
+
document.head.append(style)
|
|
103
|
+
return () => style.remove()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export { CLIENT_STYLE_ID, CLIENT_CSS, BINDING_WORKBENCH_CSS, REPL_CONSOLE_CSS, installStyles }
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { derivePtcToolView } from './client-activity.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* run_code / edit_run_code tool rows. The row is a pure projection of the
|
|
5
|
+
* recorded tool block: source, result, features and inspection, with the newer
|
|
6
|
+
* DisclosureRow when the host provides it and an accessible fallback otherwise.
|
|
7
|
+
*/
|
|
8
|
+
export function createPtcToolView(React, deps) {
|
|
9
|
+
const { CodeBlock, DisclosureRow, icons } = deps
|
|
10
|
+
const h = React.createElement
|
|
11
|
+
|
|
12
|
+
function PTCPlusToolRow({ toolName, block, inspect, t }) {
|
|
13
|
+
const [open, setOpen] = React.useState(false)
|
|
14
|
+
const view = derivePtcToolView(block, toolName)
|
|
15
|
+
const expandable = view.code !== '' || view.output !== '' || typeof inspect === 'function'
|
|
16
|
+
const stateKey = {
|
|
17
|
+
running: 'tool.running',
|
|
18
|
+
ok: 'tool.completed',
|
|
19
|
+
error: 'tool.failed',
|
|
20
|
+
stopped: 'tool.stopped',
|
|
21
|
+
}[view.state]
|
|
22
|
+
const outputSummary = view.state === 'error' && view.output !== ''
|
|
23
|
+
? view.output.split(/\r?\n/, 1)[0]
|
|
24
|
+
: ''
|
|
25
|
+
const summary = outputSummary || view.description
|
|
26
|
+
const stateText = view.state === 'ok' ? null : t(stateKey)
|
|
27
|
+
const toggle = () => {
|
|
28
|
+
if (expandable) setOpen(current => !current)
|
|
29
|
+
}
|
|
30
|
+
const summaryText = summary === '' ? null : summary
|
|
31
|
+
const summaryLine = stateText === null && summaryText === null ? null
|
|
32
|
+
: h('div', { className: 'ptcPlusToolSummaryLine', 'data-state': view.state, role: 'status' },
|
|
33
|
+
stateText === null ? null : h('span', { className: 'ptcPlusToolState' }, stateText),
|
|
34
|
+
summaryText === null ? null : h('span', { className: 'ptcPlusToolSep', 'aria-hidden': true }),
|
|
35
|
+
summaryText === null ? null : h('span', { className: 'ptcPlusToolDescription' }, summaryText))
|
|
36
|
+
const body = !open ? null : h('div', { className: 'ptcPlusToolBody' },
|
|
37
|
+
view.code === '' ? null : h('div', { className: 'ptcPlusToolSection' },
|
|
38
|
+
h('span', { className: 'ptcPlusToolSectionLabel' }, t('tool.source')),
|
|
39
|
+
typeof CodeBlock === 'function'
|
|
40
|
+
? h(CodeBlock, {
|
|
41
|
+
code: view.code, lang: 'typescript', className: 'ptcPlusToolCode',
|
|
42
|
+
copyLabel: t('tool.copy'), copiedLabel: t('tool.copied'),
|
|
43
|
+
})
|
|
44
|
+
: h('pre', { className: 'ptcPlusToolCode' }, view.code)),
|
|
45
|
+
view.output === '' ? null : h('div', { className: 'ptcPlusToolSection' },
|
|
46
|
+
h('span', { className: 'ptcPlusToolSectionLabel' }, t('tool.result')),
|
|
47
|
+
h('div', { className: 'ptcPlusIoCard' },
|
|
48
|
+
h('pre', {
|
|
49
|
+
className: 'ptcPlusIoText',
|
|
50
|
+
'data-error': view.state === 'error' || undefined,
|
|
51
|
+
}, view.output))),
|
|
52
|
+
typeof inspect !== 'function' ? null : h('button', {
|
|
53
|
+
type: 'button', className: 'ptcPlusInspect', onClick: inspect,
|
|
54
|
+
}, h(icons.inspect, { 'aria-hidden': true }), t('tool.inspect')))
|
|
55
|
+
const features = view.features.length === 0 ? null : h('div', { className: 'ptcPlusFeatures' },
|
|
56
|
+
view.features.map(feature => h('span', {
|
|
57
|
+
key: `${feature.key}:${feature.detail}`, className: 'ptcPlusFeature',
|
|
58
|
+
},
|
|
59
|
+
h('span', { className: 'ptcPlusFeatureName' }, t(feature.key)),
|
|
60
|
+
feature.detail === '' ? null
|
|
61
|
+
: h('span', { className: 'ptcPlusFeatureDetail', title: feature.detail }, feature.detail))))
|
|
62
|
+
const collapsedContent = h('div', { className: 'ptcPlusToolPreview' }, summaryLine, features)
|
|
63
|
+
if (typeof DisclosureRow === 'function') {
|
|
64
|
+
return h('div', { className: 'ptcPlusTool' },
|
|
65
|
+
h(DisclosureRow, {
|
|
66
|
+
icon: expandable
|
|
67
|
+
? h(icons.chevron, { size: 14 })
|
|
68
|
+
: h(icons.check, { size: 14 }),
|
|
69
|
+
title: t(toolName === 'edit_run_code' ? 'tool.codeEdit' : 'tool.code'),
|
|
70
|
+
open,
|
|
71
|
+
expandable,
|
|
72
|
+
onToggle: toggle,
|
|
73
|
+
expandOnRowClick: true,
|
|
74
|
+
previewChevron: false,
|
|
75
|
+
keepContentWhenOpen: true,
|
|
76
|
+
collapsedContent,
|
|
77
|
+
children: body,
|
|
78
|
+
}))
|
|
79
|
+
}
|
|
80
|
+
return h('div', { className: 'ptcPlusTool' },
|
|
81
|
+
h('div', {
|
|
82
|
+
className: 'ptcPlusToolSummary', 'data-state': view.state,
|
|
83
|
+
'data-expandable': expandable || undefined,
|
|
84
|
+
role: expandable ? 'button' : undefined,
|
|
85
|
+
tabIndex: expandable ? 0 : undefined,
|
|
86
|
+
'aria-expanded': expandable ? open : undefined,
|
|
87
|
+
onClick: expandable ? toggle : undefined,
|
|
88
|
+
onKeyDown: expandable ? (event) => {
|
|
89
|
+
if (event.key !== 'Enter' && event.key !== ' ') return
|
|
90
|
+
event.preventDefault()
|
|
91
|
+
toggle()
|
|
92
|
+
} : undefined,
|
|
93
|
+
},
|
|
94
|
+
h('span', { className: 'ptcPlusToolLeading', 'aria-hidden': true }, expandable
|
|
95
|
+
? h(icons.chevron, { size: 14, className: 'ptcPlusToolChevron', 'data-open': open })
|
|
96
|
+
: h(icons.check, { size: 14 })),
|
|
97
|
+
h('span', { className: 'ptcPlusToolTitle' }, t(
|
|
98
|
+
toolName === 'edit_run_code' ? 'tool.codeEdit' : 'tool.code')),
|
|
99
|
+
view.state === 'ok' ? null
|
|
100
|
+
: h('span', { className: 'ptcPlusToolState', role: 'status' }, t(stateKey)),
|
|
101
|
+
h('span', { className: 'ptcPlusToolSep', 'aria-hidden': true }),
|
|
102
|
+
h('span', { className: 'ptcPlusToolDescription' }, summary)),
|
|
103
|
+
features,
|
|
104
|
+
body)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return { PTCPlusToolRow }
|
|
108
|
+
}
|