@w6w/ui 0.0.0-stage → 0.1.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.
Files changed (142) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/LICENSE +21 -0
  3. package/README.md +275 -2
  4. package/dist/ActionTestForm.d.ts +76 -0
  5. package/dist/AddConnectionModal.d.ts +24 -0
  6. package/dist/AppPicker.d.ts +83 -0
  7. package/dist/CodeBlock-CZu4TFSi.cjs +15 -0
  8. package/dist/CodeBlock-CZu4TFSi.cjs.map +1 -0
  9. package/dist/CodeBlock-Dot3Pd7P.js +2889 -0
  10. package/dist/CodeBlock-Dot3Pd7P.js.map +1 -0
  11. package/dist/CodeBlock.d.ts +65 -0
  12. package/dist/CodeEditor.d.ts +42 -0
  13. package/dist/ConfirmModal-8avl9Nv8.cjs +11 -0
  14. package/dist/ConfirmModal-8avl9Nv8.cjs.map +1 -0
  15. package/dist/ConfirmModal-CD-P8mhN.js +6335 -0
  16. package/dist/ConfirmModal-CD-P8mhN.js.map +1 -0
  17. package/dist/Copyable-1niV9gUa.js +771 -0
  18. package/dist/Copyable-1niV9gUa.js.map +1 -0
  19. package/dist/Copyable-CYZU1o4X.cjs +2 -0
  20. package/dist/Copyable-CYZU1o4X.cjs.map +1 -0
  21. package/dist/JsonEditor.d.ts +60 -0
  22. package/dist/NodeConfigForm.d.ts +70 -0
  23. package/dist/ParamsForm.d.ts +56 -0
  24. package/dist/PropertyEntryForm.d.ts +56 -0
  25. package/dist/RetryPolicyFields.d.ts +18 -0
  26. package/dist/StepBuilderModal.d.ts +375 -0
  27. package/dist/TriggerFillForm.d.ts +52 -0
  28. package/dist/WaitEditor.d.ts +6 -0
  29. package/dist/WorkflowFlowEditor.d.ts +119 -0
  30. package/dist/YamlEditor.d.ts +46 -0
  31. package/dist/app-categories.d.ts +38 -0
  32. package/dist/app-pages.d.ts +111 -0
  33. package/dist/code.cjs +2 -0
  34. package/dist/code.cjs.map +1 -0
  35. package/dist/code.d.ts +29 -0
  36. package/dist/code.mjs +8 -0
  37. package/dist/code.mjs.map +1 -0
  38. package/dist/components/ApiCallsPanel.d.ts +41 -0
  39. package/dist/components/AppIcon.d.ts +25 -0
  40. package/dist/components/AuthFieldsForm.d.ts +22 -0
  41. package/dist/components/Combobox.d.ts +24 -0
  42. package/dist/components/ConfirmModal.d.ts +33 -0
  43. package/dist/components/Copyable.d.ts +51 -0
  44. package/dist/components/CopyableText.d.ts +40 -0
  45. package/dist/components/DeleteButton.d.ts +16 -0
  46. package/dist/components/EditButton.d.ts +10 -0
  47. package/dist/components/ExecutionDetail.d.ts +70 -0
  48. package/dist/components/ExecutionFilters.d.ts +59 -0
  49. package/dist/components/ExecutionList.d.ts +60 -0
  50. package/dist/components/ExecutionLogPanel.d.ts +98 -0
  51. package/dist/components/ExecutionStats.d.ts +47 -0
  52. package/dist/components/ExpressionEditorModal.d.ts +42 -0
  53. package/dist/components/ExpressionInput.d.ts +36 -0
  54. package/dist/components/ExpressionOptions.d.ts +185 -0
  55. package/dist/components/HealthStatusPill.d.ts +25 -0
  56. package/dist/components/HistoryTimeline.d.ts +56 -0
  57. package/dist/components/Icon.d.ts +34 -0
  58. package/dist/components/IconButton.d.ts +60 -0
  59. package/dist/components/InfoTip.d.ts +15 -0
  60. package/dist/components/InternalIcon.d.ts +19 -0
  61. package/dist/components/ListItem.d.ts +25 -0
  62. package/dist/components/Modal.d.ts +29 -0
  63. package/dist/components/RepoSyncIndicator.d.ts +29 -0
  64. package/dist/components/ResolvedParams.d.ts +31 -0
  65. package/dist/components/ServerResources.d.ts +47 -0
  66. package/dist/components/StepStatusPill.d.ts +51 -0
  67. package/dist/components/UptimeStrip.d.ts +56 -0
  68. package/dist/components/execution-format.d.ts +24 -0
  69. package/dist/components/expression-dom.d.ts +154 -0
  70. package/dist/components/expression-template.d.ts +86 -0
  71. package/dist/components/history-scale.d.ts +33 -0
  72. package/dist/components/icons.d.ts +41 -0
  73. package/dist/components/resolved-clip.d.ts +42 -0
  74. package/dist/components/server-resources-format.d.ts +68 -0
  75. package/dist/components/server-resources.fixture.d.ts +9 -0
  76. package/dist/components/use-copy.d.ts +14 -0
  77. package/dist/createW6WApi.d.ts +31 -0
  78. package/dist/flow-connect.d.ts +138 -0
  79. package/dist/flow-fanout.d.ts +15 -0
  80. package/dist/flow-types.d.ts +356 -0
  81. package/dist/flow-utils.d.ts +284 -0
  82. package/dist/flow.cjs +3 -0
  83. package/dist/flow.cjs.map +1 -0
  84. package/dist/flow.d.ts +24 -0
  85. package/dist/flow.mjs +1978 -0
  86. package/dist/flow.mjs.map +1 -0
  87. package/dist/index.cjs +2 -0
  88. package/dist/index.cjs.map +1 -0
  89. package/dist/index.d.ts +94 -0
  90. package/dist/index.mjs +1812 -0
  91. package/dist/index.mjs.map +1 -0
  92. package/dist/oauth-popup.d.ts +17 -0
  93. package/dist/output-shape.d.ts +58 -0
  94. package/dist/provider.d.ts +421 -0
  95. package/dist/resolve-params.d.ts +112 -0
  96. package/dist/resolved-json.d.ts +21 -0
  97. package/dist/run-visuals.d.ts +90 -0
  98. package/dist/step-preview-state.d.ts +143 -0
  99. package/dist/theme.d.ts +32 -0
  100. package/dist/trigger-fields.d.ts +56 -0
  101. package/dist/types.d.ts +413 -0
  102. package/dist/use-app-action-defs.d.ts +7 -0
  103. package/dist/use-enter-submit.d.ts +23 -0
  104. package/dist/use-seed-sources.d.ts +16 -0
  105. package/package.json +112 -3
  106. package/src/code.css +561 -0
  107. package/src/styles/_buttons.scss +38 -0
  108. package/src/styles/_chips.scss +210 -0
  109. package/src/styles/_code.scss +139 -0
  110. package/src/styles/_copyable.scss +147 -0
  111. package/src/styles/_data-vars.scss +38 -0
  112. package/src/styles/_execution-history.scss +282 -0
  113. package/src/styles/_execution-log.scss +178 -0
  114. package/src/styles/_expression-field.scss +65 -0
  115. package/src/styles/_expression-inline.scss +63 -0
  116. package/src/styles/_expression-modal.scss +292 -0
  117. package/src/styles/_fields.scss +161 -0
  118. package/src/styles/_flow.scss +217 -0
  119. package/src/styles/_fx.scss +158 -0
  120. package/src/styles/_health.scss +46 -0
  121. package/src/styles/_history-timeline.scss +156 -0
  122. package/src/styles/_icon-button.scss +22 -0
  123. package/src/styles/_icon.scss +15 -0
  124. package/src/styles/_icons.scss +31 -0
  125. package/src/styles/_incoming-state.scss +46 -0
  126. package/src/styles/_info-tip.scss +9 -0
  127. package/src/styles/_layout.scss +6 -0
  128. package/src/styles/_lists.scss +64 -0
  129. package/src/styles/_modal.scss +125 -0
  130. package/src/styles/_multiselect.scss +69 -0
  131. package/src/styles/_repo-sync-indicator.scss +99 -0
  132. package/src/styles/_scale.scss +70 -0
  133. package/src/styles/_sections.scss +36 -0
  134. package/src/styles/_server-resources.scss +163 -0
  135. package/src/styles/_step-builder.scss +376 -0
  136. package/src/styles/_step-config.scss +195 -0
  137. package/src/styles/_tabs.scss +54 -0
  138. package/src/styles/_tester.scss +111 -0
  139. package/src/styles/_tokens.scss +160 -0
  140. package/src/styles/_uptime.scss +61 -0
  141. package/src/styles.css +4894 -0
  142. package/src/styles.scss +61 -0
package/src/code.css ADDED
@@ -0,0 +1,561 @@
1
+ /* GENERATED FILE — DO NOT EDIT.
2
+ *
3
+ * Compiled from src/code.scss by scripts/build-css.mjs (`pnpm build:css`).
4
+ * Edit the .scss partials under src/styles/ instead; `pnpm check:css` fails
5
+ * if this file has drifted from them.
6
+ */
7
+ @charset "UTF-8";
8
+ /*
9
+ * @w6w/ui — styles for the pure-presentation components.
10
+ *
11
+ * Everything is namespaced under `.w6w-*` class names so this stylesheet
12
+ * won't collide with your app's CSS.
13
+ *
14
+ * THEMING
15
+ * -------
16
+ * The library ships a complete DEFAULT theme in BOTH light and dark:
17
+ * - Light is the base.
18
+ * - Dark applies automatically when the OS prefers dark
19
+ * (`prefers-color-scheme: dark`).
20
+ * - Either mode can be forced with `data-theme="light" | "dark"` on any
21
+ * ancestor (usually <html>) — the same signal the JS components read
22
+ * (AppIcon / CodeEditor / JsonEditor: explicit prop > data-theme > OS pref),
23
+ * so CSS and components always agree.
24
+ *
25
+ * A HOST can override any subset of the tokens — set the ones you care about and
26
+ * the rest keep their themed defaults:
27
+ *
28
+ * :root { --w6w-accent: #3355e6; } // one token, both modes
29
+ * html[data-theme="dark"] { --w6w-panel: #000 } // mode-specific
30
+ *
31
+ * Every default below is declared through `:where(...)` (specificity 0), so ANY
32
+ * host rule — even a plain `:root { ... }` — wins without !important. Tokens are
33
+ * defined on :root so every `.w6w-*` component inherits them out of the box.
34
+ */
35
+ /* Light — the base defaults. */
36
+ :where(:root) {
37
+ --w6w-bg: #f7f8fa;
38
+ --w6w-panel: #ffffff;
39
+ --w6w-panel-2: #f0f2f6;
40
+ --w6w-border: #d9dee5;
41
+ --w6w-text: #1a1d24;
42
+ --w6w-muted: #5f6875;
43
+ --w6w-accent: #3355e6;
44
+ --w6w-danger: #c1362f;
45
+ --w6w-success: #2e9e5b;
46
+ --w6w-health-ok: var(--w6w-success);
47
+ --w6w-health-degraded: #c77700;
48
+ --w6w-health-down: var(--w6w-danger);
49
+ --w6w-health-unknown: #5f6875;
50
+ --w6w-icon-swatch: #f0f2f6;
51
+ --w6w-code-comment: #6b7280;
52
+ --w6w-code-keyword: #8250df;
53
+ --w6w-code-string: #0a7b34;
54
+ --w6w-code-number: #b3541e;
55
+ --w6w-code-function: #1f6feb;
56
+ --w6w-code-punctuation: #5f6875;
57
+ --w6w-code-variable: #953800;
58
+ --w6w-radius: 10px;
59
+ --w6w-scheme: light;
60
+ }
61
+
62
+ /* Dark — followed automatically from the OS preference (unless a host has
63
+ forced a mode via data-theme, which is handled by the blocks below). */
64
+ @media (prefers-color-scheme: dark) {
65
+ :where(:root) {
66
+ --w6w-bg: #0f1115;
67
+ --w6w-panel: #181b22;
68
+ --w6w-panel-2: #1f232c;
69
+ --w6w-border: #2a2f3a;
70
+ --w6w-text: #e6e8ee;
71
+ --w6w-muted: #9aa3b2;
72
+ --w6w-accent: #5b8cff;
73
+ --w6w-danger: #ff6b6b;
74
+ --w6w-success: #3fbf77;
75
+ --w6w-health-ok: var(--w6w-success);
76
+ --w6w-health-degraded: #f0a020;
77
+ --w6w-health-down: var(--w6w-danger);
78
+ --w6w-health-unknown: #9aa3b2;
79
+ --w6w-icon-swatch: #1f232c;
80
+ --w6w-scheme: dark;
81
+ --w6w-code-comment: #7d8797;
82
+ --w6w-code-keyword: #d2a8ff;
83
+ --w6w-code-string: #7ee787;
84
+ --w6w-code-number: #ffab70;
85
+ --w6w-code-function: #79c0ff;
86
+ --w6w-code-punctuation: #9aa3b2;
87
+ --w6w-code-variable: #ffa657;
88
+ }
89
+ }
90
+ /* Explicit mode. Declared AFTER the media query at equal (zero) specificity, so
91
+ a forced data-theme always beats the OS preference. */
92
+ :where([data-theme=light]) {
93
+ --w6w-scheme: light;
94
+ --w6w-bg: #f7f8fa;
95
+ --w6w-panel: #ffffff;
96
+ --w6w-panel-2: #f0f2f6;
97
+ --w6w-border: #d9dee5;
98
+ --w6w-text: #1a1d24;
99
+ --w6w-muted: #5f6875;
100
+ --w6w-accent: #3355e6;
101
+ --w6w-danger: #c1362f;
102
+ --w6w-success: #2e9e5b;
103
+ --w6w-health-ok: var(--w6w-success);
104
+ --w6w-health-degraded: #c77700;
105
+ --w6w-health-down: var(--w6w-danger);
106
+ --w6w-health-unknown: #5f6875;
107
+ --w6w-icon-swatch: #f0f2f6;
108
+ --w6w-code-comment: #6b7280;
109
+ --w6w-code-keyword: #8250df;
110
+ --w6w-code-string: #0a7b34;
111
+ --w6w-code-number: #b3541e;
112
+ --w6w-code-function: #1f6feb;
113
+ --w6w-code-punctuation: #5f6875;
114
+ --w6w-code-variable: #953800;
115
+ }
116
+
117
+ :where([data-theme=dark]) {
118
+ --w6w-scheme: dark;
119
+ --w6w-bg: #0f1115;
120
+ --w6w-panel: #181b22;
121
+ --w6w-panel-2: #1f232c;
122
+ --w6w-border: #2a2f3a;
123
+ --w6w-text: #e6e8ee;
124
+ --w6w-muted: #9aa3b2;
125
+ --w6w-accent: #5b8cff;
126
+ --w6w-danger: #ff6b6b;
127
+ --w6w-success: #3fbf77;
128
+ --w6w-health-ok: var(--w6w-success);
129
+ --w6w-health-degraded: #f0a020;
130
+ --w6w-health-down: var(--w6w-danger);
131
+ --w6w-health-unknown: #9aa3b2;
132
+ --w6w-icon-swatch: #1f232c;
133
+ --w6w-code-comment: #7d8797;
134
+ --w6w-code-keyword: #d2a8ff;
135
+ --w6w-code-string: #7ee787;
136
+ --w6w-code-number: #ffab70;
137
+ --w6w-code-function: #79c0ff;
138
+ --w6w-code-punctuation: #9aa3b2;
139
+ --w6w-code-variable: #ffa657;
140
+ }
141
+
142
+ .w6w-muted {
143
+ color: var(--w6w-muted);
144
+ }
145
+
146
+ .w6w-small {
147
+ font-size: 0.85em;
148
+ }
149
+
150
+ /* color-scheme — declared on ui COMPONENT ROOTS, never on the host's <html>.
151
+ `color-scheme` inherits and also themes the page canvas, scrollbars and form
152
+ controls, so setting it on :root / [data-theme] let importing this file flip a
153
+ host's whole document. Instead each token block above also sets the
154
+ `--w6w-scheme` custom property (light / dark), which INHERITS, so the nearest
155
+ themed ancestor wins however themes nest (a light panel inside a dark page and
156
+ the reverse). Elements ui renders (any `w6w-` class, which covers the native
157
+ <dialog> modals) and the native controls inside them read it with
158
+ `color-scheme: var(--w6w-scheme)`. Not a hand-picked root list: every ui
159
+ component carries a `w6w-` class. Only an element whose class LIST has a token
160
+ starting `w6w-` matches (`class^=` / `class*=" w6w-"`), so host elements are never
161
+ touched: not a host `data-theme` wrapper, not a host class that merely contains
162
+ `w6w-` (`my-w6w-card`), and not a host element's own color-scheme on inputs nested
163
+ in a ui root (color-scheme inherits, so no descendant rule is needed). Nothing here
164
+ ever matches <html>/:root. All zero specificity. */
165
+ :where([class^=w6w-]:not(:root), [class*=" w6w-"]:not(:root)) {
166
+ color-scheme: var(--w6w-scheme);
167
+ }
168
+
169
+ /*
170
+ * @w6w/ui — the spacing / typography scale.
171
+ *
172
+ * Values are MIRRORED, not invented, from `packages/frontend/packages/web`'s
173
+ * `src/styles/global.css:83-130` — that file is the canonical reference (it
174
+ * arrived at the same 4px base independently); this block copies its
175
+ * `--sp-*`/`--fs-*`/`--fw-*`/`--lh-*`/`--font-*` values byte-for-byte under the
176
+ * `--w6w-*` namespace this package already uses for every other token.
177
+ * `--fs-hero`'s `clamp()` stays `web`-only (a marketing-page concern; `ui` has
178
+ * no hero). Colour tokens, `--radius*`, `--shadow-*` and `--transition-fast`
179
+ * are NOT part of this scale — see `_tokens.scss`.
180
+ *
181
+ * HALF-STEPS (`--w6w-sp-0-5` / `--w6w-sp-1-5` / `--w6w-sp-2-5`) are `ui`-only
182
+ * additions on top of `web`'s set — `web` has none. The rule that keeps this a
183
+ * system rather than a free-for-all: whole steps for new code; a half-step is
184
+ * only for preserving an existing measured value that does not sit on a 4px
185
+ * step. Parity with `web` is therefore DIRECTIONAL — `ui` ⊇ `web` on the
186
+ * shared key set (every `web` token here has a byte-identical `ui` counterpart;
187
+ * `ui` additionally declares the three half-steps `web` does not).
188
+ *
189
+ * One `:where(:root)` block, not colour's three-way light / prefers-color-scheme /
190
+ * [data-theme] split — the scale is not theme-dependent, so a single specificity-0
191
+ * block covers every mode. Positioning this partial's `@use` line immediately
192
+ * after `styles/tokens` (see `styles.scss`) is a readability convention, not a
193
+ * cascade constraint: CSS custom properties resolve at computed-value time, so
194
+ * definition order relative to consumption order does not matter here, unlike
195
+ * `_tokens.scss`'s internal prefers-color-scheme / [data-theme] ordering, which
196
+ * IS load-bearing.
197
+ */
198
+ :where(:root) {
199
+ /* Spacing — 4px ramp. Values mirror frontend/web's --sp-* verbatim. */
200
+ --w6w-sp-1: 4px;
201
+ --w6w-sp-2: 8px;
202
+ --w6w-sp-3: 12px;
203
+ --w6w-sp-4: 16px;
204
+ --w6w-sp-5: 20px;
205
+ --w6w-sp-6: 24px;
206
+ --w6w-sp-8: 32px;
207
+ --w6w-sp-10: 40px;
208
+ --w6w-sp-12: 48px;
209
+ --w6w-sp-16: 64px;
210
+ --w6w-sp-20: 80px;
211
+ /* Half-steps — ui-only, see the decision above. */
212
+ --w6w-sp-0-5: 2px;
213
+ --w6w-sp-1-5: 6px;
214
+ --w6w-sp-2-5: 10px;
215
+ /* Type ramp — rem, role names mirror frontend/web's --fs-*. */
216
+ --w6w-fs-xs: 0.75rem;
217
+ --w6w-fs-sm: 0.875rem;
218
+ --w6w-fs-base: 1rem;
219
+ --w6w-fs-lg: 1.125rem;
220
+ --w6w-fs-xl: 1.25rem;
221
+ --w6w-fs-2xl: 1.5rem;
222
+ --w6w-fs-3xl: 2rem;
223
+ --w6w-fw-regular: 400;
224
+ --w6w-fw-medium: 500;
225
+ --w6w-fw-semibold: 600;
226
+ --w6w-fw-bold: 700;
227
+ --w6w-lh-tight: 1.2;
228
+ --w6w-lh-normal: 1.5;
229
+ --w6w-lh-relaxed: 1.7;
230
+ --w6w-font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
231
+ --w6w-font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
232
+ }
233
+
234
+ /*
235
+ * Breakpoints — Sass variables, NOT CSS custom properties.
236
+ *
237
+ * `@media (min-width: var(--w6w-bp-md))` is invalid in every browser: a media
238
+ * query condition cannot read a custom property. So these live as Sass
239
+ * variables instead, resolved before the browser ever sees the stylesheet.
240
+ * `!default` lets a Sass consumer override one:
241
+ *
242
+ * @use "@w6w/ui/styles/scale" with ($w6w-bp-md: 960px);
243
+ *
244
+ * `ui` itself consumes none of these — it deliberately ships no layout media
245
+ * queries (the host owns page layout; `ui` owns component internals). They
246
+ * exist purely so a consumer stops inventing its own breakpoint values (seven
247
+ * uncoordinated ones exist across the four repos today).
248
+ */
249
+ /* Copyable — an in-box copy affordance decorating a value-displaying control
250
+ (an <input>, a <textarea>, or CodeBlock's <pre>). Mirrors `.w6w-fx-wrap`
251
+ (`_fx.scss:1-88`): the WRAPPER owns the box chrome and every child it holds
252
+ is flattened below, so the value and the copy affordance read as ONE box. */
253
+ .w6w-copyable {
254
+ display: flex;
255
+ align-items: center;
256
+ gap: var(--w6w-sp-1);
257
+ background: var(--w6w-panel-2);
258
+ border: 1px solid var(--w6w-border);
259
+ border-radius: 8px;
260
+ padding: var(--w6w-sp-1) var(--w6w-sp-2);
261
+ /* Box-family invariant: byte-identical to `.w6w-fx-wrap`'s at `_fx.scss:13` —
262
+ six rules across four partials share this value (`building-blocks.md` §3
263
+ row 7); a scale token here would drift the moment that family moves. */
264
+ min-height: 38px;
265
+ }
266
+
267
+ /* A textarea/pre is taller than the button, so the button rides at the top —
268
+ mirrors `.w6w-fx-wrap:has(> textarea)` (`_fx.scss:16-18`). */
269
+ .w6w-copyable:has(> textarea),
270
+ .w6w-copyable:has(> pre) {
271
+ align-items: flex-start;
272
+ }
273
+
274
+ /* Focus reads on the box now that the inner control has no border of its own. */
275
+ .w6w-copyable:focus-within {
276
+ border-color: var(--w6w-accent);
277
+ }
278
+
279
+ .w6w-copyable > input,
280
+ .w6w-copyable > textarea,
281
+ .w6w-copyable > pre {
282
+ flex: 1 1 auto;
283
+ min-width: 0;
284
+ }
285
+
286
+ /* The control inside the wrapper carries NO chrome of its own. Mirrors
287
+ `_fx.scss:36-88`'s selector list and property list WHOLESALE
288
+ (s/w6w-fx-wrap/w6w-copyable/g) — not re-derived, gated for parity by the
289
+ project's test plan. See that file for the measured leak evidence (7.0px
290
+ alignment / 2px / 29% height) each property below defends against; a host
291
+ page's unscoped `input[type="text"], … textarea { … }` rule (studio's own,
292
+ layered AFTER this stylesheet) is exactly what these declarations beat. */
293
+ .w6w-field .w6w-copyable input[type=text],
294
+ .w6w-field .w6w-copyable input[type=password],
295
+ .w6w-field .w6w-copyable input[type=number],
296
+ .w6w-field .w6w-copyable select,
297
+ .w6w-field .w6w-copyable textarea,
298
+ .w6w-datavar-row .w6w-copyable input,
299
+ .w6w-datavar-row .w6w-copyable select,
300
+ .w6w-copyable input[type=text],
301
+ .w6w-copyable input[type=password],
302
+ .w6w-copyable input[type=number],
303
+ .w6w-copyable select,
304
+ .w6w-copyable textarea {
305
+ border: none;
306
+ background: transparent;
307
+ border-radius: 0;
308
+ /* lint-tokens-allow: mirrors _fx.scss:36-88 byte-for-byte, required by the parity gate */
309
+ padding: 4px 2px;
310
+ outline: none;
311
+ margin: 0;
312
+ min-height: 0;
313
+ }
314
+
315
+ /* The wrapper never draws a box around a box (mirrors `_fx.scss:91-98`). */
316
+ .w6w-copyable .w6w-code-block {
317
+ border: none;
318
+ background: transparent;
319
+ padding: 0;
320
+ }
321
+
322
+ /* Button chrome extends `.w6w-icon-btn` (`_icons.scss:1-11`) in markup — this
323
+ class only pins the flex behaviour and the copied state, no re-authored
324
+ hover/active states. */
325
+ .w6w-copyable-btn {
326
+ flex: none;
327
+ }
328
+
329
+ /* ── CodeBlock: the button OVERLAYS the box's top-right corner ──────────────
330
+ For an <input>/<textarea> the button is a flex sibling, which is right: the
331
+ value is one line and the control shrinks to leave room for it. A <pre> is
332
+ different — it is a block of many lines, and a flex sibling would carve a
333
+ permanent empty column out of the full height of it to seat one 28px button.
334
+ So here the button leaves the flow and sits over the corner instead.
335
+
336
+ Absolute against the WRAPPER, not the <pre>, on purpose: the <pre> is the
337
+ element that scrolls (`overflow-x: auto`, plus `overflow-y` when `maxHeight`
338
+ is set), so anchoring to it would slide the button out of view on a wide or
339
+ tall snippet. Anchored to the wrapper it stays pinned to the visible corner. */
340
+ .w6w-copyable:has(> pre) {
341
+ position: relative;
342
+ }
343
+
344
+ .w6w-copyable:has(> pre) > .w6w-copyable-btn {
345
+ position: absolute;
346
+ top: var(--w6w-sp-1);
347
+ right: var(--w6w-sp-1);
348
+ /* An opaque backdrop, which the flex-sibling case does not need: this button
349
+ sits ON the code, and `.w6w-icon-btn`'s transparent idle state would let
350
+ the first line's text read through it. It also restores the hover feedback
351
+ — `.w6w-icon-btn:hover` paints `--w6w-panel-2`, which is the wrapper's own
352
+ background here and would otherwise be a no-op. */
353
+ background: var(--w6w-panel);
354
+ border-color: var(--w6w-border);
355
+ }
356
+
357
+ /* Keep the first line clear of the button. Deliberately NOT folded into the
358
+ `.w6w-copyable .w6w-code-block` reset above — that rule mirrors
359
+ `_fx.scss:91-98` and is held byte-for-byte by the parity gate. 40px = the
360
+ button's ~28px box + its 4px inset + a 8px gap before the text. */
361
+ .w6w-copyable:has(> pre) > .w6w-code-block {
362
+ padding-right: var(--w6w-sp-10);
363
+ }
364
+
365
+ .w6w-copyable-btn.is-copied {
366
+ /* Mirrors `.w6w-expr-chip-render`'s "confirmed/success" convention exactly
367
+ (`_chips.scss:38-42`) — the one visual for a copied/success state. */
368
+ border-color: var(--w6w-success);
369
+ color: var(--w6w-success);
370
+ background: color-mix(in srgb, var(--w6w-success) 14%, transparent);
371
+ }
372
+
373
+ /* Scoped visually-hidden live region — not a new general `sr-only` utility
374
+ (none exists in `ui` to extend; see `Copyable.tsx` for why this, not the
375
+ button's own accessible name, carries the "Copied" announcement). */
376
+ .w6w-copyable-status {
377
+ position: absolute;
378
+ overflow: hidden;
379
+ width: 1px;
380
+ height: 1px;
381
+ white-space: nowrap;
382
+ clip-path: inset(50%);
383
+ border: 0;
384
+ padding: 0;
385
+ }
386
+
387
+ /* ── Bare modifier: CopyableText (D-7) ───────────────────────────────────
388
+ A self-contained modifier, NOT a widening of the shared `> input, >
389
+ textarea, > pre` selector above (`:28-33`) — that list stays untouched.
390
+ Strips the box chrome the base `.w6w-copyable` rule sets (`:5-17`: border,
391
+ background, padding, min-height), and separately gives its own `> span`
392
+ child the SAME flex-and-shrink pair the shared selector gives an
393
+ `<input>`/`<textarea>`/`<pre>` (`:28-33` below) — a bare `<span>` is not in
394
+ that list, and without this it silently reproduces the overflow bug
395
+ `studio/src/pages/VarsPage.tsx:62-79` had to hand-patch. */
396
+ .w6w-copyable--bare {
397
+ border: none;
398
+ background: transparent;
399
+ padding: 0;
400
+ min-height: 0;
401
+ }
402
+
403
+ .w6w-copyable--bare > span {
404
+ flex: 1 1 auto;
405
+ min-width: 0;
406
+ }
407
+
408
+ .w6w-code-block {
409
+ background: var(--w6w-panel-2);
410
+ border: 1px solid var(--w6w-border);
411
+ border-radius: var(--w6w-radius);
412
+ margin: 0;
413
+ overflow-x: auto;
414
+ padding: var(--w6w-sp-3) 14px;
415
+ tab-size: 2;
416
+ }
417
+
418
+ .w6w-code-block code {
419
+ background: none;
420
+ display: block;
421
+ font-family: var(--w6w-font-mono);
422
+ font-size: 13px;
423
+ line-height: 1.55;
424
+ padding: 0;
425
+ }
426
+
427
+ /* Each line is its own row so a line number can sit beside the text rather
428
+ than inside it — a number inside the flow would be caught by a copy. */
429
+ .w6w-code-line {
430
+ display: flex;
431
+ gap: var(--w6w-sp-3);
432
+ white-space: pre;
433
+ }
434
+
435
+ .w6w-code-line-text {
436
+ white-space: inherit;
437
+ }
438
+
439
+ /* `user-select: none` keeps the gutter out of a mouse selection; `aria-hidden`
440
+ on the element keeps it out of the accessibility tree. Both are needed —
441
+ neither one alone stops a copy from picking up the digits. */
442
+ .w6w-code-line-no {
443
+ color: var(--w6w-muted);
444
+ flex: 0 0 auto;
445
+ min-width: 2ch;
446
+ opacity: 0.65;
447
+ text-align: right;
448
+ user-select: none;
449
+ }
450
+
451
+ /* Wrapped mode indents continuation rows to the text column so a wrapped line
452
+ still reads as one line. */
453
+ .w6w-code-block--wrap .w6w-code-line,
454
+ .w6w-code-block--wrap .w6w-code-line-text {
455
+ white-space: pre-wrap;
456
+ word-break: break-word;
457
+ }
458
+
459
+ .w6w-code-block--wrap {
460
+ overflow-x: hidden;
461
+ }
462
+
463
+ /* Resolved params (Test tab, read-only): inline badge weight — like
464
+ JsonParamField's "Invalid JSON" hint, not a full `.w6w-result.w6w-error`
465
+ block per param, since either can appear once per configured param. */
466
+ .w6w-param-unresolved {
467
+ color: var(--w6w-danger);
468
+ font-size: 0.85em;
469
+ font-style: italic;
470
+ }
471
+
472
+ .w6w-param-unevaluated {
473
+ color: var(--w6w-muted);
474
+ font-size: 0.85em;
475
+ font-style: italic;
476
+ }
477
+
478
+ /* One resolved param: a table row, not a stacked form field — this list is
479
+ read-only display, never an editable `.w6w-field`, so it earns its own
480
+ compact key-left/value-right layout instead of a label-above-control block
481
+ (human report, 2026-09-01: key and value were indistinguishable and every
482
+ row burned a full stacked block of vertical space). ONE grid across the
483
+ whole list (`.w6w-resolved-table`), not one grid per row, so every row's
484
+ key column lines up with the one above and below it. */
485
+ .w6w-resolved-table {
486
+ display: grid;
487
+ grid-template-columns: auto 1fr;
488
+ align-items: baseline;
489
+ }
490
+
491
+ /* Each row is `display: contents` — it renders no box of its own, so its two
492
+ children (label, value) become direct items of the parent grid above,
493
+ sharing its column tracks instead of sizing their own. */
494
+ .w6w-resolved-row {
495
+ display: contents;
496
+ font-size: calc(var(--w6w-fs-sm) * 0.9);
497
+ }
498
+
499
+ /* No `column-gap` on the grid: a gap leaves a hole no cell's own border
500
+ crosses, breaking the row divider into two segments. The same visual
501
+ space between key and value comes from padding instead, which is part of
502
+ each cell's own box — the border-bottom stays one unbroken line. */
503
+ .w6w-resolved-row > * {
504
+ padding: var(--w6w-sp-1-5) 0;
505
+ border-bottom: 1px solid var(--w6w-border);
506
+ }
507
+
508
+ .w6w-resolved-row:last-child > * {
509
+ border-bottom: none;
510
+ }
511
+
512
+ .w6w-resolved-label {
513
+ padding-right: var(--w6w-sp-3);
514
+ color: var(--w6w-muted);
515
+ }
516
+
517
+ /* One resolved row's value. `anywhere` (not `break-word`) because these values
518
+ are markup and URLs as often as prose: a single unbroken 40kB attribute
519
+ string would otherwise force the whole modal to scroll sideways. Full-
520
+ strength text color (not `--w6w-muted`) so it reads as the actual content,
521
+ distinct from the label beside it. */
522
+ .w6w-resolved-value {
523
+ color: var(--w6w-text);
524
+ overflow-wrap: anywhere;
525
+ min-width: 0;
526
+ }
527
+
528
+ /* The expanded form of a clipped value (`resolved-clip.ts`). A block with its
529
+ own scroll, so "Show all" can never restore the unbounded inline paste that
530
+ buried the other params and the run's result. */
531
+ .w6w-resolved-text-full {
532
+ display: block;
533
+ margin: var(--w6w-sp-1) 0;
534
+ max-height: 14em;
535
+ overflow: auto;
536
+ padding: var(--w6w-sp-2);
537
+ background: var(--w6w-panel-2);
538
+ border: 1px solid var(--w6w-border);
539
+ border-radius: var(--w6w-radius);
540
+ font-family: var(--w6w-font-mono);
541
+ font-size: 0.85em; /* lint-tokens-allow: matches the sibling code-typography rules above in this same file */
542
+ line-height: var(--w6w-lh-normal);
543
+ white-space: pre-wrap;
544
+ }
545
+
546
+ /* Link-weight toggle — this sits inside a value, so it must not read as a
547
+ second action competing with the modal's own buttons. */
548
+ .w6w-resolved-more {
549
+ background: none;
550
+ border: none;
551
+ padding: 0;
552
+ margin-left: var(--w6w-sp-2);
553
+ color: var(--w6w-accent);
554
+ font-size: 0.85em; /* lint-tokens-allow: matches the sibling code-typography rules above in this same file */
555
+ cursor: pointer;
556
+ white-space: nowrap;
557
+ }
558
+
559
+ .w6w-resolved-more:hover {
560
+ text-decoration: underline;
561
+ }
@@ -0,0 +1,38 @@
1
+ /* Buttons */
2
+ .w6w-btn {
3
+ background: var(--w6w-accent);
4
+ color: white;
5
+ border: none;
6
+ border-radius: 8px;
7
+ padding: var(--w6w-sp-2) 14px;
8
+ font-size: var(--w6w-fs-sm);
9
+ cursor: pointer;
10
+ }
11
+ .w6w-btn:hover {
12
+ filter: brightness(1.08);
13
+ }
14
+ .w6w-btn:disabled {
15
+ opacity: 0.5;
16
+ cursor: default;
17
+ }
18
+ .w6w-btn-ghost {
19
+ background: transparent;
20
+ border: 1px solid var(--w6w-border);
21
+ color: var(--w6w-text);
22
+ }
23
+ .w6w-btn-ghost:hover {
24
+ background: var(--w6w-panel-2);
25
+ }
26
+ .w6w-btn-ghost.active {
27
+ border-color: var(--w6w-accent);
28
+ background: var(--w6w-panel-2);
29
+ }
30
+ /* Destructive confirm button (ConfirmModal's default). Styled from the same
31
+ --w6w-danger token the error notices and health pills already use. */
32
+ .w6w-btn-danger {
33
+ background: var(--w6w-danger);
34
+ color: white;
35
+ }
36
+
37
+ /* List row — a clean, reusable list item (leading icon · title/subtitle · trailing).
38
+ Mirrors the ghost saved-test button rows it replaces. */