@w6w/ui 0.0.0-stage → 0.1.0

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 (143) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/LICENSE +21 -0
  3. package/README.md +260 -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-DJPYXE9t.cjs +11 -0
  14. package/dist/ConfirmModal-DJPYXE9t.cjs.map +1 -0
  15. package/dist/ConfirmModal-sY1tzkBO.js +6335 -0
  16. package/dist/ConfirmModal-sY1tzkBO.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 +7 -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 +22 -0
  85. package/dist/flow.mjs +1977 -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 +1811 -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 +420 -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/ui.css +1 -0
  103. package/dist/use-app-action-defs.d.ts +7 -0
  104. package/dist/use-enter-submit.d.ts +23 -0
  105. package/dist/use-seed-sources.d.ts +16 -0
  106. package/package.json +111 -3
  107. package/src/code.css +542 -0
  108. package/src/styles/_buttons.scss +38 -0
  109. package/src/styles/_chips.scss +210 -0
  110. package/src/styles/_code.scss +139 -0
  111. package/src/styles/_copyable.scss +147 -0
  112. package/src/styles/_data-vars.scss +38 -0
  113. package/src/styles/_execution-history.scss +282 -0
  114. package/src/styles/_execution-log.scss +178 -0
  115. package/src/styles/_expression-field.scss +65 -0
  116. package/src/styles/_expression-inline.scss +63 -0
  117. package/src/styles/_expression-modal.scss +292 -0
  118. package/src/styles/_fields.scss +161 -0
  119. package/src/styles/_flow.scss +217 -0
  120. package/src/styles/_fx.scss +158 -0
  121. package/src/styles/_health.scss +46 -0
  122. package/src/styles/_history-timeline.scss +156 -0
  123. package/src/styles/_icon-button.scss +22 -0
  124. package/src/styles/_icon.scss +15 -0
  125. package/src/styles/_icons.scss +31 -0
  126. package/src/styles/_incoming-state.scss +46 -0
  127. package/src/styles/_info-tip.scss +9 -0
  128. package/src/styles/_layout.scss +6 -0
  129. package/src/styles/_lists.scss +64 -0
  130. package/src/styles/_modal.scss +125 -0
  131. package/src/styles/_multiselect.scss +69 -0
  132. package/src/styles/_repo-sync-indicator.scss +99 -0
  133. package/src/styles/_scale.scss +70 -0
  134. package/src/styles/_sections.scss +36 -0
  135. package/src/styles/_server-resources.scss +163 -0
  136. package/src/styles/_step-builder.scss +376 -0
  137. package/src/styles/_step-config.scss +195 -0
  138. package/src/styles/_tabs.scss +54 -0
  139. package/src/styles/_tester.scss +111 -0
  140. package/src/styles/_tokens.scss +141 -0
  141. package/src/styles/_uptime.scss +61 -0
  142. package/src/styles.css +4208 -0
  143. package/src/styles.scss +61 -0
@@ -0,0 +1,158 @@
1
+ /* fx toggle — an end decoration INSIDE the field, not a button beside it. The
2
+ WRAPPER owns the input chrome (background/border/radius/min-height and the
3
+ focus ring) and every widget it holds is flattened below, so the value and its
4
+ ƒx affordance read as ONE box. Mirrors `.w6w-multiselect` above. */
5
+ .w6w-fx-wrap {
6
+ display: flex;
7
+ align-items: center;
8
+ gap: var(--w6w-sp-1);
9
+ background: var(--w6w-panel-2);
10
+ border: 1px solid var(--w6w-border);
11
+ border-radius: 8px;
12
+ padding: var(--w6w-sp-1) var(--w6w-sp-2);
13
+ min-height: 38px;
14
+ }
15
+ /* A textarea is taller than the ƒx, so there the decoration rides at the top. */
16
+ .w6w-fx-wrap:has(> textarea) {
17
+ align-items: flex-start;
18
+ }
19
+ /* Focus reads on the box now that the inner widget has no border of its own. */
20
+ .w6w-fx-wrap:focus-within {
21
+ border-color: var(--w6w-accent);
22
+ }
23
+ .w6w-fx-wrap > input,
24
+ .w6w-fx-wrap > select,
25
+ .w6w-fx-wrap > textarea,
26
+ .w6w-fx-wrap > .w6w-multiselect,
27
+ .w6w-fx-wrap > .w6w-expr {
28
+ flex: 1 1 auto;
29
+ min-width: 0;
30
+ }
31
+ /* The widget inside the wrapper carries NO chrome of its own. COMPOUND
32
+ selectors, because the global `.w6w-field input|select|textarea` rule is
33
+ (0,2,1) and a bare `.w6w-fx-wrap > input` at (0,1,1) would lose to it — the
34
+ same trap documented on `.w6w-multiselect-add` above. `.w6w-datavar-row
35
+ input|select` is the second rule to beat, for the `bare` vars-row cell. */
36
+ .w6w-field .w6w-fx-wrap input[type="text"],
37
+ .w6w-field .w6w-fx-wrap input[type="password"],
38
+ .w6w-field .w6w-fx-wrap input[type="number"],
39
+ .w6w-field .w6w-fx-wrap select,
40
+ .w6w-field .w6w-fx-wrap textarea,
41
+ .w6w-datavar-row .w6w-fx-wrap input,
42
+ .w6w-datavar-row .w6w-fx-wrap select,
43
+ .w6w-fx-wrap input[type="text"],
44
+ .w6w-fx-wrap input[type="password"],
45
+ .w6w-fx-wrap input[type="number"],
46
+ .w6w-fx-wrap select,
47
+ .w6w-fx-wrap textarea {
48
+ border: none;
49
+ background: transparent;
50
+ border-radius: 0;
51
+ padding: var(--w6w-sp-1) var(--w6w-sp-0-5);
52
+ outline: none;
53
+ /* EVERY property in this block is load-bearing, for the same reason
54
+ `.w6w-fx-inline-label`'s `margin: 0` is (see below): a host page layers its
55
+ own unscoped `input[type="text"], textarea { … }` rule AFTER this file
56
+ (studio's does, at `studio/src/styles.css:513-533`, `:759-771` and `:788`),
57
+ so every property this block leaves undeclared is the host's — including
58
+ inside a box this library draws. The two below were measured leaking, in
59
+ [ui+studio], before they were declared — and they fix DIFFERENT things:
60
+
61
+ margin — ALIGNMENT. A host `margin-top: 4px` in an `align-items:
62
+ center` row drops the control 2px below the ƒx it shares the
63
+ row with (string, number and the bare vars cell; select and
64
+ multiselect escaped only because the host rule does not list
65
+ them). Rendered: control cy 67 vs ƒx cy 65. On the textarea
66
+ row — `align-items: flex-start` — the same 4px showed up as
67
+ the ƒx sitting 4px off the control's first line. `margin: 0`
68
+ is the whole of that fix.
69
+
70
+ min-height — SIZE, and nothing else. Do not re-justify this one as
71
+ alignment: the counterfactual was rendered (this `margin: 0`
72
+ kept, `min-height: 0` removed) and the row measures a 0.0px
73
+ top delta with the host's 80px floor fully in effect. What it
74
+ fixes is that a host `textarea { min-height: 80px }`, written
75
+ for that host's own bare textareas, was sizing the INSIDE of
76
+ a box it cannot see — 80px/94px against the 62px/72px the
77
+ same markup renders elsewhere, i.e. one of five control types
78
+ 29% taller than the library drew it. The box is the library's
79
+ to size; how many lines it holds is `rows` on the control.
80
+ If a taller body field is ever wanted, it belongs HERE, not
81
+ in a host element selector.
82
+
83
+ Declared, not fought for: this stays at the block's existing specificity and
84
+ uses no `!important`. A component that is only aligned while the host
85
+ cooperates is broken. */
86
+ margin: 0;
87
+ min-height: 0;
88
+ }
89
+ /* …and the two widgets that own an input-like box themselves are flattened too,
90
+ so the wrapper never draws a box around a box. */
91
+ .w6w-fx-wrap .w6w-expr-field,
92
+ .w6w-fx-wrap .w6w-multiselect {
93
+ border: none;
94
+ background: transparent;
95
+ border-radius: 0;
96
+ padding: 0;
97
+ min-height: 0;
98
+ }
99
+ /* The OTHER wrapper FxField can render (`variant="inline"`). A control that does
100
+ not FILL a text-field box — today only a `boolean`'s ~13px checkbox — opts out
101
+ of the box at the component seam and lands here instead, so `.w6w-fx-wrap`'s
102
+ chrome above is never applied and nothing has to be clawed back with a more
103
+ specific selector. Layout is the review's sketch: <checkbox> <ƒx> <label>,
104
+ one row, no border/background/padding/min-height of its own. */
105
+ .w6w-fx-inline {
106
+ display: flex;
107
+ align-items: center;
108
+ gap: var(--w6w-sp-2);
109
+ }
110
+ .w6w-fx-inline > input[type="checkbox"] {
111
+ flex: 0 0 auto;
112
+ margin: 0;
113
+ }
114
+ /* The label reads as the control's own text, next to it (mirrors
115
+ `.w6w-array-check` above, the existing inline-checkbox idiom).
116
+ `margin: 0` is LOAD-BEARING, not tidiness: a host page may carry an unscoped
117
+ top-level `label { … margin-bottom: 10px }` (studio's own sheet does, at
118
+ `studio/src/styles.css:499`), and since it is layered AFTER this file any
119
+ property this block leaves undeclared is the host's. A bottom margin inside an
120
+ `align-items: center` row lifts the text off the row's centre line — measured
121
+ 5px above the checkbox and the ƒx before this declaration existed. Every other
122
+ element of the row is defended the same way: the checkbox's `margin: 0` above
123
+ out-specifies a host `input[type="checkbox"] { margin-right: … }` (0,2,1 vs
124
+ 0,1,1), and the ƒx's chrome is pinned by `.w6w-fx-inline .w6w-expr-fx` below.
125
+ A component that only lines up when the host sheet cooperates is broken. */
126
+ .w6w-fx-inline-label {
127
+ margin: 0;
128
+ color: var(--w6w-text);
129
+ font-size: 13px;
130
+ cursor: pointer;
131
+ }
132
+ /* The ƒx itself is a decoration inside whichever wrapper holds it: no chrome,
133
+ colour only. This is where the UA button border/background is removed (the
134
+ `.w6w-expr-fx` block below declares neither), so the inline wrapper has to be
135
+ listed here too or its ƒx comes back as a grey rounded button. The label row
136
+ (`json` / childless `group` params, which have no field box) is a third
137
+ placement and gets the same chrome-stripping. */
138
+ .w6w-fx-wrap .w6w-expr-fx,
139
+ .w6w-fx-inline .w6w-expr-fx,
140
+ .w6w-field-labelrow .w6w-expr-fx {
141
+ border: none;
142
+ background: transparent;
143
+ }
144
+ .w6w-expr-fx {
145
+ flex-shrink: 0;
146
+ color: var(--w6w-muted);
147
+ font-size: 13px;
148
+ font-family: var(--w6w-font-mono);
149
+ line-height: 1;
150
+ padding: var(--w6w-sp-1) var(--w6w-sp-1-5);
151
+ cursor: pointer;
152
+ }
153
+ .w6w-expr-fx:hover {
154
+ color: var(--w6w-text);
155
+ }
156
+ .w6w-expr-fx.is-active {
157
+ color: var(--w6w-accent);
158
+ }
@@ -0,0 +1,46 @@
1
+ .w6w-health-pill {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: var(--w6w-sp-1-5);
5
+ padding: var(--w6w-sp-0-5) var(--w6w-sp-2) var(--w6w-sp-0-5) 7px;
6
+ border: 1px solid color-mix(in srgb, var(--w6w-health-color) 40%, var(--w6w-border));
7
+ border-radius: 999px;
8
+ background: color-mix(in srgb, var(--w6w-health-color) 12%, transparent);
9
+ color: var(--w6w-text);
10
+ font-size: var(--w6w-fs-xs);
11
+ line-height: var(--w6w-lh-normal);
12
+ white-space: nowrap;
13
+ --w6w-health-color: var(--w6w-health-unknown);
14
+ }
15
+ .w6w-health-pill-ok {
16
+ --w6w-health-color: var(--w6w-health-ok);
17
+ }
18
+ .w6w-health-pill-degraded {
19
+ --w6w-health-color: var(--w6w-health-degraded);
20
+ }
21
+ .w6w-health-pill-down {
22
+ --w6w-health-color: var(--w6w-health-down);
23
+ }
24
+ .w6w-health-pill-unknown {
25
+ --w6w-health-color: var(--w6w-health-unknown);
26
+ }
27
+ .w6w-health-pill-dot {
28
+ flex-shrink: 0;
29
+ width: 8px;
30
+ height: 8px;
31
+ border-radius: 50%;
32
+ background: var(--w6w-health-color);
33
+ }
34
+ .w6w-health-pill-label {
35
+ overflow: hidden;
36
+ text-overflow: ellipsis;
37
+ }
38
+
39
+ /* App summary block */
40
+ .w6w-app-summary {
41
+ display: flex;
42
+ align-items: center;
43
+ gap: var(--w6w-sp-2-5);
44
+ }
45
+
46
+ /* Modal */
@@ -0,0 +1,156 @@
1
+ .w6w-history-timeline {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: var(--w6w-sp-2);
5
+ width: 100%;
6
+ }
7
+
8
+ /* One positioned container shared by both lanes AND the axis, so every
9
+ `left`/`width` percentage in any of the three is on the same coordinate
10
+ system — this is what keeps the two series from drifting apart. */
11
+ .w6w-history-plot {
12
+ position: relative;
13
+ display: flex;
14
+ flex-direction: column;
15
+ gap: var(--w6w-sp-1);
16
+ }
17
+
18
+ .w6w-history-lane {
19
+ position: relative;
20
+ height: 22px;
21
+ min-width: 0;
22
+ }
23
+
24
+ /* --- execution lane -------------------------------------------------- */
25
+
26
+ .w6w-history-cell {
27
+ --w6w-health-color: var(--w6w-health-unknown);
28
+ --w6w-history-fill: 100%;
29
+ position: absolute;
30
+ top: 0;
31
+ bottom: 0;
32
+ min-width: 1px;
33
+ border-radius: 2px;
34
+ overflow: hidden;
35
+ /* The unfilled remainder of the cell, so the lane reads as a continuous
36
+ row rather than as floating marks — same treatment as `UptimeStrip`. */
37
+ background: color-mix(in srgb, var(--w6w-border) 55%, transparent);
38
+ }
39
+ .w6w-history-cell::after {
40
+ content: "";
41
+ position: absolute;
42
+ left: 0;
43
+ right: 0;
44
+ bottom: 0;
45
+ height: var(--w6w-history-fill);
46
+ border-radius: inherit;
47
+ background: var(--w6w-health-color);
48
+ }
49
+ .w6w-history-cell-ok {
50
+ --w6w-health-color: var(--w6w-health-ok);
51
+ --w6w-history-fill: 35%;
52
+ }
53
+ .w6w-history-cell-degraded {
54
+ --w6w-health-color: var(--w6w-health-degraded);
55
+ --w6w-history-fill: 65%;
56
+ }
57
+ .w6w-history-cell-down {
58
+ --w6w-health-color: var(--w6w-health-down);
59
+ --w6w-history-fill: 100%;
60
+ }
61
+ .w6w-history-cell-unknown {
62
+ --w6w-health-color: var(--w6w-health-unknown);
63
+ --w6w-history-fill: 100%;
64
+ }
65
+ /* No solid fill for `unknown` — a hatch, same reasoning as `UptimeStrip`'s:
66
+ an unmeasured day must never be mistaken for a healthy or a failing one. */
67
+ .w6w-history-cell-unknown::after {
68
+ background: repeating-linear-gradient(
69
+ 45deg,
70
+ color-mix(in srgb, var(--w6w-health-color) 45%, transparent) 0 2px,
71
+ transparent 2px 5px
72
+ );
73
+ border: 1px solid color-mix(in srgb, var(--w6w-health-color) 35%, var(--w6w-border));
74
+ }
75
+
76
+ /* --- vendor lane ------------------------------------------------------- */
77
+
78
+ .w6w-history-bar {
79
+ --w6w-health-color: var(--w6w-health-unknown);
80
+ position: absolute;
81
+ /* Thickness is the geometry half of severity — thin for `ok`, thicker for
82
+ `degraded`, full lane height for `down`/`unknown` — using the spacing
83
+ scale rather than a one-off literal so it never drifts from it. */
84
+ top: var(--w6w-sp-1);
85
+ bottom: var(--w6w-sp-1);
86
+ min-width: 2px;
87
+ border-radius: 2px;
88
+ background: var(--w6w-health-color);
89
+ }
90
+ .w6w-history-bar-ok {
91
+ --w6w-health-color: var(--w6w-health-ok);
92
+ }
93
+ .w6w-history-bar-degraded {
94
+ --w6w-health-color: var(--w6w-health-degraded);
95
+ top: var(--w6w-sp-0-5);
96
+ bottom: var(--w6w-sp-0-5);
97
+ }
98
+ .w6w-history-bar-down {
99
+ --w6w-health-color: var(--w6w-health-down);
100
+ top: 0;
101
+ bottom: 0;
102
+ }
103
+ .w6w-history-bar-unknown {
104
+ --w6w-health-color: var(--w6w-health-unknown);
105
+ top: 0;
106
+ bottom: 0;
107
+ background: repeating-linear-gradient(
108
+ 45deg,
109
+ color-mix(in srgb, var(--w6w-health-color) 45%, transparent) 0 2px,
110
+ transparent 2px 5px
111
+ );
112
+ border: 1px solid color-mix(in srgb, var(--w6w-health-color) 35%, var(--w6w-border));
113
+ }
114
+ /* A clipped edge is squared off rather than rounded, so a bar that runs off
115
+ the window reads as continuing beyond it rather than as ending there. */
116
+ .w6w-history-bar-clip-start {
117
+ border-top-left-radius: 0;
118
+ border-bottom-left-radius: 0;
119
+ }
120
+ .w6w-history-bar-clip-end {
121
+ border-top-right-radius: 0;
122
+ border-bottom-right-radius: 0;
123
+ }
124
+
125
+ .w6w-history-empty {
126
+ position: absolute;
127
+ inset: 0;
128
+ display: flex;
129
+ align-items: center;
130
+ color: var(--w6w-muted);
131
+ font-size: var(--w6w-fs-xs);
132
+ white-space: nowrap;
133
+ overflow: hidden;
134
+ text-overflow: ellipsis;
135
+ }
136
+
137
+ /* --- axis --------------------------------------------------------------- */
138
+
139
+ .w6w-history-axis {
140
+ position: relative;
141
+ height: 16px;
142
+ }
143
+ .w6w-history-tick {
144
+ position: absolute;
145
+ top: 0;
146
+ color: var(--w6w-muted);
147
+ font-size: var(--w6w-fs-xs);
148
+ line-height: var(--w6w-lh-normal);
149
+ white-space: nowrap;
150
+ }
151
+ .w6w-history-tick-start {
152
+ transform: translateX(0);
153
+ }
154
+ .w6w-history-tick-end {
155
+ transform: translateX(-100%);
156
+ }
@@ -0,0 +1,22 @@
1
+ .w6w-icon-button {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ background: transparent;
6
+ border: none;
7
+ border-radius: 8px;
8
+ padding: var(--w6w-sp-1-5);
9
+ color: var(--w6w-muted);
10
+ cursor: pointer;
11
+ }
12
+ .w6w-icon-button:hover:not(:disabled) {
13
+ background: var(--w6w-panel-2);
14
+ color: var(--w6w-text);
15
+ }
16
+ .w6w-icon-button-danger:hover:not(:disabled) {
17
+ color: var(--w6w-danger);
18
+ }
19
+ .w6w-icon-button:disabled {
20
+ opacity: 0.4;
21
+ cursor: default;
22
+ }
@@ -0,0 +1,15 @@
1
+ /* The shared `Icon` (`src/components/Icon.tsx`).
2
+ *
3
+ * Only geometry invariants live here. The PAINT is per-entry in
4
+ * `src/components/icons.tsx` (the set mixes filled Material-style glyphs with
5
+ * stroked Feather ones, and the language marks paint their own elements), and
6
+ * the SIZE comes from the `size` prop — so there is nothing about colour or
7
+ * scale for this class to say. */
8
+ .w6w-icon {
9
+ /* Never squashed by a flex parent: a rail glyph squeezed to 9px is unreadable,
10
+ and the sources draw at 14–20px inside rows that can be tight. */
11
+ flex-shrink: 0;
12
+ /* A glyph dropped into a line of text sits on the baseline by default, which
13
+ reads as a foot below the words. */
14
+ vertical-align: middle;
15
+ }
@@ -0,0 +1,31 @@
1
+ .w6w-icon-btn {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ background: transparent;
6
+ border: 1px solid transparent;
7
+ border-radius: 8px;
8
+ padding: var(--w6w-sp-1-5);
9
+ color: var(--w6w-muted);
10
+ cursor: pointer;
11
+ }
12
+ .w6w-icon-btn:hover {
13
+ background: var(--w6w-panel-2);
14
+ color: var(--w6w-text);
15
+ }
16
+ .w6w-icon-btn.active {
17
+ background: var(--w6w-panel-2);
18
+ border-color: var(--w6w-accent);
19
+ color: var(--w6w-text);
20
+ }
21
+
22
+ /* Segmented sub-tabs inside the edit modal's form view (Parameters | Config). */
23
+ .w6w-subtabs {
24
+ display: inline-flex;
25
+ gap: var(--w6w-sp-0-5);
26
+ padding: var(--w6w-sp-0-5);
27
+ background: var(--w6w-panel-2);
28
+ border: 1px solid var(--w6w-border);
29
+ border-radius: 8px;
30
+ align-self: flex-start;
31
+ }
@@ -0,0 +1,46 @@
1
+ /* Incoming state (WorkflowFlowEditor · `IncomingStateField`, mounted by BOTH the
2
+ step editor's Test tab and the canvas ▶ Run collect form). The raw JSON box is
3
+ an OVERRIDE, so it sits behind a disclosure instead of being the first thing
4
+ the tab shows — the seed chips above it stay in plain sight. */
5
+ .w6w-state-override {
6
+ border: 1px solid var(--w6w-border);
7
+ border-radius: 6px;
8
+ padding: var(--w6w-sp-1-5) var(--w6w-sp-2);
9
+ }
10
+ .w6w-state-override > summary {
11
+ cursor: pointer;
12
+ color: var(--w6w-muted);
13
+ font-size: 0.85em;
14
+ }
15
+ /* Breathing room only once it is open: closed, the summary IS the whole box. */
16
+ .w6w-state-override[open] > summary {
17
+ margin-bottom: var(--w6w-sp-1-5);
18
+ }
19
+ .w6w-state-override > .w6w-hint {
20
+ display: block;
21
+ margin-top: var(--w6w-sp-1);
22
+ }
23
+
24
+ /* Incoming-state seed picker: upstream steps' saved tests offered as one-click
25
+ seeds for the step's incoming state (WorkflowFlowEditor · StepEditModal). */
26
+ .w6w-seed-picker {
27
+ display: flex;
28
+ flex-direction: column;
29
+ gap: var(--w6w-sp-1);
30
+ margin-bottom: var(--w6w-sp-1-5);
31
+ }
32
+ .w6w-seed-chips {
33
+ display: flex;
34
+ flex-wrap: wrap;
35
+ gap: var(--w6w-sp-1-5);
36
+ }
37
+ .w6w-seed-chip {
38
+ cursor: pointer;
39
+ }
40
+ .w6w-seed-chip:hover:not(:disabled) {
41
+ border-color: var(--w6w-text);
42
+ }
43
+ .w6w-seed-chip:disabled {
44
+ cursor: default;
45
+ opacity: 0.6;
46
+ }
@@ -0,0 +1,9 @@
1
+ .w6w-info-tip {
2
+ display: inline-flex;
3
+ flex-wrap: wrap;
4
+ align-items: center;
5
+ gap: var(--w6w-sp-1);
6
+ }
7
+ .w6w-info-tip-body {
8
+ flex-basis: 100%;
9
+ }
@@ -0,0 +1,6 @@
1
+ /* Layout helpers */
2
+ .w6w-stack {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: var(--w6w-sp-2-5);
6
+ }
@@ -0,0 +1,64 @@
1
+ .w6w-list-item {
2
+ display: flex;
3
+ align-items: center;
4
+ gap: var(--w6w-sp-2-5);
5
+ width: 100%;
6
+ padding: var(--w6w-sp-2) var(--w6w-sp-2-5);
7
+ border: 1px solid transparent;
8
+ border-radius: 8px;
9
+ background: transparent;
10
+ color: var(--w6w-text);
11
+ text-align: left;
12
+ font-size: var(--w6w-fs-sm);
13
+ cursor: pointer;
14
+ }
15
+ button.w6w-list-item {
16
+ font: inherit;
17
+ font-size: var(--w6w-fs-sm);
18
+ }
19
+ .w6w-list-item:hover {
20
+ background: var(--w6w-panel-2);
21
+ }
22
+ .w6w-list-item:focus-visible {
23
+ outline: none;
24
+ border-color: var(--w6w-accent);
25
+ box-shadow: 0 0 0 2px var(--w6w-accent);
26
+ }
27
+ .w6w-list-item.active {
28
+ border-color: var(--w6w-accent);
29
+ background: var(--w6w-panel-2);
30
+ }
31
+ .w6w-list-item-icon {
32
+ display: inline-flex;
33
+ align-items: center;
34
+ flex-shrink: 0;
35
+ }
36
+ .w6w-list-item-body {
37
+ display: flex;
38
+ flex-direction: column;
39
+ min-width: 0;
40
+ gap: var(--w6w-sp-0-5);
41
+ }
42
+ .w6w-list-item-title {
43
+ overflow: hidden;
44
+ text-overflow: ellipsis;
45
+ white-space: nowrap;
46
+ }
47
+ .w6w-list-item-subtitle {
48
+ color: var(--w6w-muted);
49
+ font-size: var(--w6w-fs-xs);
50
+ overflow: hidden;
51
+ text-overflow: ellipsis;
52
+ white-space: nowrap;
53
+ }
54
+ .w6w-list-item-trailing {
55
+ margin-left: auto;
56
+ display: inline-flex;
57
+ align-items: center;
58
+ flex-shrink: 0;
59
+ }
60
+
61
+ /* Health status pill — a small, theme-aware badge for one health state
62
+ (ok · degraded · down · unknown). Colour comes from the `--w6w-health-*`
63
+ tokens so a host can restyle every state by overriding those; the dot tints
64
+ with the state while the pill keeps a soft tinted background + border. */
@@ -0,0 +1,125 @@
1
+ .w6w-modal-backdrop {
2
+ position: fixed;
3
+ inset: 0;
4
+ background: rgba(0, 0, 0, 0.55);
5
+ display: grid;
6
+ place-items: center;
7
+ padding: var(--w6w-sp-5);
8
+ z-index: 50;
9
+ }
10
+ dialog.w6w-modal {
11
+ position: fixed;
12
+ inset: 0;
13
+ margin: auto;
14
+ background: var(--w6w-panel);
15
+ color: var(--w6w-text);
16
+ border: 1px solid var(--w6w-border);
17
+ border-radius: var(--w6w-radius);
18
+ width: 100%;
19
+ max-width: 800px;
20
+ max-height: 90vh;
21
+ overflow: auto;
22
+ padding: var(--w6w-sp-5);
23
+ display: flex;
24
+ flex-direction: column;
25
+ gap: var(--w6w-sp-3);
26
+ }
27
+ dialog.w6w-modal::backdrop {
28
+ background: rgba(0, 0, 0, 0.55);
29
+ }
30
+ dialog.w6w-modal h3,
31
+ dialog.w6w-modal h4,
32
+ dialog.w6w-modal p {
33
+ color: var(--w6w-text);
34
+ margin: 0;
35
+ }
36
+ dialog.w6w-modal.w6w-modal-wide {
37
+ max-width: min(850px, 80vw);
38
+ min-height: min(70vh, 560px);
39
+ }
40
+ dialog.w6w-modal.w6w-modal-xl {
41
+ max-width: 1040px;
42
+ min-height: min(70vh, 620px);
43
+ }
44
+ dialog.w6w-modal.w6w-modal-full {
45
+ max-width: min(1200px, 96vw);
46
+ width: 96vw;
47
+ height: 92vh;
48
+ max-height: 92vh;
49
+ overflow: hidden;
50
+ }
51
+ /* Edge-to-edge surface: the whole viewport, no rounded corners and no visible
52
+ backdrop margin. Distinct from `.w6w-modal-full` (96vw x 92vh), which is
53
+ deliberately inset so the page behind stays visible as context — the
54
+ expression editor and the action tester both rely on that.
55
+ `position: fixed; inset: 0` already sizes to the viewport, so width/height
56
+ here are belt-and-braces against a UA stylesheet's `dialog` sizing.
57
+ The header is pinned; the caller's own child scrolls (it must set
58
+ `flex: 1; min-height: 0; overflow: auto` on itself). */
59
+ dialog.w6w-modal.w6w-modal-fullscreen {
60
+ max-width: none;
61
+ width: 100vw;
62
+ height: 100vh;
63
+ max-height: 100vh;
64
+ border: none;
65
+ border-radius: 0;
66
+ overflow: hidden;
67
+ padding: var(--w6w-sp-5) var(--w6w-sp-6);
68
+ }
69
+ dialog.w6w-modal.w6w-modal-fullscreen .w6w-modal-header {
70
+ flex-shrink: 0;
71
+ padding-bottom: var(--w6w-sp-4);
72
+ border-bottom: 1px solid var(--w6w-border);
73
+ }
74
+ .w6w-modal-header {
75
+ display: flex;
76
+ align-items: center;
77
+ justify-content: space-between;
78
+ gap: var(--w6w-sp-3);
79
+ }
80
+ .w6w-modal-title {
81
+ display: flex;
82
+ align-items: center;
83
+ gap: var(--w6w-sp-2-5);
84
+ min-width: 0;
85
+ }
86
+ .w6w-modal-subtitle {
87
+ color: var(--w6w-muted);
88
+ font-size: 0.7em;
89
+ font-weight: var(--w6w-fw-regular);
90
+ white-space: nowrap;
91
+ overflow: hidden;
92
+ text-overflow: ellipsis;
93
+ }
94
+ .w6w-modal-subtitle code {
95
+ font-size: inherit;
96
+ }
97
+ /* The one scrolling region of a dialog (D-3): the body takes the leftover height
98
+ and scrolls, so the header/footer around it stay put. The dialog's own
99
+ `gap: var(--w6w-sp-3)` column is reproduced here so content-spacing is
100
+ unchanged now that body children are flex items of THIS box, not the dialog's. */
101
+ .w6w-modal-body {
102
+ display: flex;
103
+ flex-direction: column;
104
+ gap: var(--w6w-sp-3);
105
+ flex: 1;
106
+ min-height: 0;
107
+ overflow-y: auto;
108
+ }
109
+ /* Pinned below the scrolling `.w6w-modal-body`, never shrunk away by it (D-3).
110
+ Sits at the dialog's bottom for free: the body above it already absorbs the
111
+ free space, so no `margin-top: auto` is needed (or wanted — it would shrink
112
+ this row instead). */
113
+ .w6w-modal-actions {
114
+ display: flex;
115
+ gap: var(--w6w-sp-2);
116
+ justify-content: flex-end;
117
+ flex-shrink: 0;
118
+ }
119
+
120
+ /* Icon-button view toggle (e.g. Form ⇄ JSON), inline with a modal header. */
121
+ .w6w-view-toggle {
122
+ display: flex;
123
+ gap: var(--w6w-sp-1);
124
+ flex-shrink: 0;
125
+ }