@hlang-org/editor-ui 0.3.0 → 0.4.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.
@@ -0,0 +1,21 @@
1
+ /** LivePulse — one flash per run of a node, over its own rounded outline. */
2
+
3
+ .hl-live-pulse {
4
+ position: absolute;
5
+ inset: 0;
6
+ border-radius: inherit;
7
+ pointer-events: none;
8
+ box-shadow:
9
+ 0 0 0 2px var(--hl-spark),
10
+ 0 0 36px -4px var(--hl-spark);
11
+ opacity: 0;
12
+ animation: hl-live-pulse 0.6s var(--hl-ease);
13
+ }
14
+ @keyframes hl-live-pulse {
15
+ 0% {
16
+ opacity: 1;
17
+ }
18
+ 100% {
19
+ opacity: 0;
20
+ }
21
+ }
@@ -27,13 +27,6 @@
27
27
  box-shadow: var(--hl-glass-edge-hi), var(--hl-shadow-node),
28
28
  0 0 0 1px color-mix(in oklab, var(--hl-spark) 70%, transparent),
29
29
  0 0 28px -6px var(--hl-spark);
30
- animation: hl-asset-pulse 0.7s var(--hl-ease);
31
- }
32
- @keyframes hl-asset-pulse {
33
- 0% {
34
- box-shadow: var(--hl-glass-edge-hi), var(--hl-shadow-node),
35
- 0 0 0 2px var(--hl-spark), 0 0 36px -4px var(--hl-spark);
36
- }
37
30
  }
38
31
  .hl-asset.is-live-error {
39
32
  box-shadow: var(--hl-glass-edge-hi), var(--hl-shadow-node),
@@ -144,3 +137,12 @@
144
137
  background: var(--hl-silver-hi);
145
138
  transform: scale(1.2);
146
139
  }
140
+
141
+ /* A node that has finished (RFC 0001): its inputs ended and its outputs
142
+ closed. It steps back, calmly, rather than going dark. */
143
+ .hl-asset {
144
+ transition: opacity 0.4s var(--hl-ease);
145
+ }
146
+ .hl-asset.is-finished {
147
+ opacity: 0.6;
148
+ }
@@ -50,13 +50,6 @@
50
50
  box-shadow: var(--hl-glass-edge-hi), var(--hl-shadow-node),
51
51
  0 0 0 1px color-mix(in oklab, var(--hl-spark) 70%, transparent),
52
52
  0 0 28px -6px var(--hl-spark);
53
- animation: hl-node-pulse 0.7s var(--hl-ease);
54
- }
55
- @keyframes hl-node-pulse {
56
- 0% {
57
- box-shadow: var(--hl-glass-edge-hi), var(--hl-shadow-node),
58
- 0 0 0 2px var(--hl-spark), 0 0 36px -4px var(--hl-spark);
59
- }
60
53
  }
61
54
  /* A node that threw during the run goes coral. */
62
55
  .hl-node.is-live-error {
@@ -190,3 +183,12 @@
190
183
  .hl-port.is-error .hl-handle.hl-handle:hover {
191
184
  background: var(--hl-error);
192
185
  }
186
+
187
+ /* A node that has finished (RFC 0001): its inputs ended and its outputs
188
+ closed. It steps back, calmly, rather than going dark. */
189
+ .hl-node {
190
+ transition: opacity 0.4s var(--hl-ease);
191
+ }
192
+ .hl-node.is-finished {
193
+ opacity: 0.6;
194
+ }
@@ -40,13 +40,6 @@
40
40
  box-shadow: var(--hl-glass-edge-hi), var(--hl-shadow-node),
41
41
  0 0 0 1px color-mix(in oklab, var(--hl-spark) 70%, transparent),
42
42
  0 0 26px -6px var(--hl-spark);
43
- animation: hl-pill-pulse 0.7s var(--hl-ease);
44
- }
45
- @keyframes hl-pill-pulse {
46
- 0% {
47
- box-shadow: var(--hl-glass-edge-hi), var(--hl-shadow-node),
48
- 0 0 0 2px var(--hl-spark), 0 0 34px -4px var(--hl-spark);
49
- }
50
43
  }
51
44
  .hl-pill.is-live-error {
52
45
  box-shadow: var(--hl-glass-edge-hi), var(--hl-shadow-node),
@@ -183,3 +176,12 @@
183
176
  background: var(--hl-silver-hi);
184
177
  transform: scale(1.2);
185
178
  }
179
+
180
+ /* A node that has finished (RFC 0001): its inputs ended and its outputs
181
+ closed. It steps back, calmly, rather than going dark. */
182
+ .hl-pill {
183
+ transition: opacity 0.4s var(--hl-ease);
184
+ }
185
+ .hl-pill.is-finished {
186
+ opacity: 0.6;
187
+ }
@@ -4,6 +4,10 @@
4
4
  gap: 18px;
5
5
  padding: 14px;
6
6
  height: 100%;
7
+ min-height: 0;
8
+ /* Its own scroll region: a tall node (or a short pane) never clips it. */
9
+ overflow-y: auto;
10
+ overscroll-behavior: contain;
7
11
  }
8
12
 
9
13
  .hl-inspector-empty {
@@ -159,3 +163,58 @@
159
163
  font-weight: 600;
160
164
  color: var(--hl-ink-2);
161
165
  }
166
+
167
+ /* Run statistics of the selected node (NodeRunStats). */
168
+ .hl-runstats-hint {
169
+ text-align: left;
170
+ }
171
+ .hl-runstats {
172
+ display: grid;
173
+ grid-template-columns: repeat(3, minmax(0, 1fr));
174
+ gap: 6px;
175
+ margin: 0;
176
+ }
177
+ .hl-runstats-cell {
178
+ display: flex;
179
+ flex-direction: column;
180
+ gap: 3px;
181
+ min-width: 0;
182
+ padding: 7px 9px;
183
+ border-radius: var(--hl-r-sm);
184
+ background: rgba(255, 255, 255, 0.025);
185
+ box-shadow: var(--hl-glass-edge);
186
+ }
187
+ .hl-runstats-cell.is-wide {
188
+ grid-column: 1 / -1;
189
+ }
190
+ .hl-runstats-cell dt {
191
+ font-size: 10px;
192
+ color: var(--hl-ink-3);
193
+ }
194
+ .hl-runstats-cell dd {
195
+ margin: 0;
196
+ font-size: 12.5px;
197
+ color: var(--hl-ink);
198
+ overflow: hidden;
199
+ text-overflow: ellipsis;
200
+ white-space: nowrap;
201
+ }
202
+ .hl-runstats-cell.is-error dd {
203
+ color: var(--hl-error);
204
+ }
205
+
206
+ /* A connection in the inspector: its glyph, and the note above its form. */
207
+ .hl-inspector-kind.hl-connection {
208
+ --hl-kind: var(--hl-silver);
209
+ }
210
+ .hl-inspector-note {
211
+ text-align: left;
212
+ line-height: 1.5;
213
+ }
214
+
215
+ .hl-runstats-cell.is-warning dd {
216
+ color: var(--hl-warning);
217
+ }
218
+ .hl-runstats-cell.is-done dd {
219
+ color: var(--hl-ink-2);
220
+ }
@@ -86,3 +86,14 @@
86
86
  border: 1px dashed var(--hl-line-strong);
87
87
  border-radius: var(--hl-r-sm);
88
88
  }
89
+
90
+ /* A field that does not apply yet (a connection's capacity while it is
91
+ unbounded): visibly off, and not interactive. */
92
+ .hl-input:disabled,
93
+ .hl-toggle:disabled {
94
+ opacity: 0.4;
95
+ cursor: not-allowed;
96
+ }
97
+ .hl-input:disabled:hover {
98
+ border-color: var(--hl-line-strong);
99
+ }
@@ -0,0 +1,175 @@
1
+ /** RunLog — the live console of a running graph, docked under the canvas. */
2
+
3
+ .hl-runlog {
4
+ display: flex;
5
+ flex-direction: column;
6
+ min-height: 0;
7
+ height: 100%;
8
+ background: var(--hl-void-2);
9
+ border-top: 1px solid var(--hl-line);
10
+ }
11
+
12
+ .hl-runlog-head {
13
+ display: flex;
14
+ align-items: center;
15
+ gap: 12px;
16
+ padding: 7px 12px 7px 16px;
17
+ border-bottom: 1px solid var(--hl-line);
18
+ flex: none;
19
+ }
20
+ .hl-runlog-title {
21
+ font-size: 10px;
22
+ font-weight: 600;
23
+ text-transform: uppercase;
24
+ letter-spacing: 0.14em;
25
+ color: var(--hl-silver);
26
+ }
27
+ .hl-runlog-count {
28
+ font-size: 11px;
29
+ color: var(--hl-ink-3);
30
+ white-space: nowrap;
31
+ overflow: hidden;
32
+ text-overflow: ellipsis;
33
+ min-width: 0;
34
+ }
35
+ .hl-runlog-actions {
36
+ display: flex;
37
+ gap: 4px;
38
+ margin-left: auto;
39
+ flex: none;
40
+ }
41
+ .hl-runlog-toggle {
42
+ padding: 3px 9px;
43
+ border: 1px solid var(--hl-line);
44
+ border-radius: 6px;
45
+ background: transparent;
46
+ color: var(--hl-ink-3);
47
+ font-family: var(--hl-font-ui);
48
+ font-size: 11px;
49
+ font-weight: 550;
50
+ cursor: pointer;
51
+ max-width: 180px;
52
+ white-space: nowrap;
53
+ overflow: hidden;
54
+ text-overflow: ellipsis;
55
+ transition: background 0.14s var(--hl-ease), color 0.14s var(--hl-ease);
56
+ }
57
+ .hl-runlog-toggle:hover:not(:disabled) {
58
+ color: var(--hl-ink-2);
59
+ }
60
+ .hl-runlog-toggle.is-on {
61
+ color: var(--hl-ink);
62
+ background: color-mix(in oklab, var(--hl-silver) 16%, transparent);
63
+ border-color: color-mix(in oklab, var(--hl-silver) 28%, transparent);
64
+ }
65
+ .hl-runlog-toggle:disabled {
66
+ opacity: 0.45;
67
+ cursor: default;
68
+ }
69
+ .hl-runlog-toggle:focus-visible,
70
+ .hl-runlog-hit:focus-visible {
71
+ outline: 1px solid var(--hl-silver);
72
+ outline-offset: -1px;
73
+ }
74
+
75
+ .hl-runlog-empty {
76
+ margin: 0;
77
+ padding: 14px 16px;
78
+ font-size: 12px;
79
+ color: var(--hl-ink-3);
80
+ }
81
+
82
+ .hl-runlog-body {
83
+ overscroll-behavior: contain;
84
+ list-style: none;
85
+ margin: 0;
86
+ padding: 4px 0;
87
+ overflow: auto;
88
+ min-height: 0;
89
+ flex: 1;
90
+ font-size: 11.5px;
91
+ }
92
+
93
+ .hl-runlog-hit {
94
+ display: grid;
95
+ grid-template-columns: 64px minmax(0, min(22rem, 40%)) minmax(0, 1fr) 72px;
96
+ align-items: baseline;
97
+ gap: 12px;
98
+ width: 100%;
99
+ padding: 2px 12px 2px 16px;
100
+ border: none;
101
+ background: transparent;
102
+ color: var(--hl-ink-2);
103
+ font: inherit;
104
+ text-align: left;
105
+ cursor: pointer;
106
+ }
107
+ .hl-runlog-hit:hover {
108
+ background: rgba(255, 255, 255, 0.035);
109
+ }
110
+
111
+ .hl-runlog-at {
112
+ color: var(--hl-ink-3);
113
+ font-variant-numeric: tabular-nums;
114
+ }
115
+ .hl-runlog-route {
116
+ display: flex;
117
+ align-items: baseline;
118
+ gap: 5px;
119
+ min-width: 0;
120
+ overflow: hidden;
121
+ white-space: nowrap;
122
+ }
123
+ .hl-runlog-node {
124
+ color: var(--hl-ink);
125
+ overflow: hidden;
126
+ text-overflow: ellipsis;
127
+ }
128
+ .hl-runlog-port {
129
+ color: var(--hl-ink-3);
130
+ flex: none;
131
+ }
132
+ .hl-runlog-arrow {
133
+ color: var(--hl-silver-lo);
134
+ flex: none;
135
+ }
136
+ .hl-runlog-value {
137
+ color: var(--hl-silver-hi);
138
+ overflow: hidden;
139
+ text-overflow: ellipsis;
140
+ white-space: nowrap;
141
+ }
142
+ .hl-runlog-ms {
143
+ color: var(--hl-ink-3);
144
+ text-align: right;
145
+ font-variant-numeric: tabular-nums;
146
+ white-space: nowrap;
147
+ }
148
+
149
+ .hl-runlog-row.is-error .hl-runlog-port,
150
+ .hl-runlog-row.is-error .hl-runlog-value {
151
+ color: var(--hl-error);
152
+ }
153
+ /* End of stream (RFC 0001): quiet, a lifecycle note rather than data. */
154
+ .hl-runlog-row.is-end .hl-runlog-value {
155
+ color: var(--hl-ink-3);
156
+ font-style: italic;
157
+ }
158
+ /* A message a drop-oldest connection let go of: lossy, in the warning hue. */
159
+ .hl-runlog-row.is-dropped .hl-runlog-value {
160
+ color: var(--hl-warning);
161
+ }
162
+
163
+ @media (max-width: 720px) {
164
+ .hl-runlog-hit {
165
+ grid-template-columns: 56px minmax(0, 1fr) 56px;
166
+ }
167
+ .hl-runlog-ms {
168
+ grid-column: 3;
169
+ grid-row: 1;
170
+ }
171
+ .hl-runlog-value {
172
+ grid-column: 2 / 4;
173
+ grid-row: 2;
174
+ }
175
+ }
@@ -80,3 +80,85 @@
80
80
  .hl-region-footer {
81
81
  flex-shrink: 0;
82
82
  }
83
+
84
+ /* A resizable footer: its height is set by `useFooterResize`, its content
85
+ fills it, and the grab handle straddles its top edge. */
86
+ .hl-region-footer.is-resizable {
87
+ position: relative;
88
+ display: flex;
89
+ flex-direction: column;
90
+ }
91
+ .hl-region-footer.is-resizable > :not(.hl-footer-resizer) {
92
+ flex: 1;
93
+ min-height: 0;
94
+ }
95
+ /* While dragging, nothing in the editor gets selected and the cursor stays. */
96
+ .hl-shell:has(.hl-region-footer.is-resizing) {
97
+ cursor: row-resize;
98
+ user-select: none;
99
+ -webkit-user-select: none;
100
+ }
101
+
102
+ .hl-footer-resizer {
103
+ position: absolute;
104
+ left: 0;
105
+ right: 0;
106
+ top: -6px;
107
+ height: 12px;
108
+ z-index: 6;
109
+ display: grid;
110
+ place-items: center;
111
+ cursor: row-resize;
112
+ /* The handle owns its drags: no scrolling or zooming of the page under it. */
113
+ touch-action: none;
114
+ outline: none;
115
+ }
116
+ .hl-footer-resizer::before {
117
+ /* The edge itself lights up while the handle is in use. */
118
+ content: '';
119
+ position: absolute;
120
+ left: 0;
121
+ right: 0;
122
+ top: 5px;
123
+ height: 2px;
124
+ background: transparent;
125
+ transition: background 0.14s var(--hl-ease);
126
+ }
127
+ .hl-footer-resizer::after {
128
+ /* The grip: a short silver bar in the middle of the edge. */
129
+ content: '';
130
+ width: 36px;
131
+ height: 4px;
132
+ border-radius: var(--hl-r-pill);
133
+ background: var(--hl-silver-lo);
134
+ opacity: 0;
135
+ transition: opacity 0.14s var(--hl-ease), background 0.14s var(--hl-ease);
136
+ }
137
+ .hl-footer-resizer:hover::after,
138
+ .hl-footer-resizer:focus-visible::after,
139
+ .hl-footer-resizer.is-dragging::after {
140
+ opacity: 1;
141
+ }
142
+ .hl-footer-resizer:hover::before,
143
+ .hl-footer-resizer:focus-visible::before,
144
+ .hl-footer-resizer.is-dragging::before {
145
+ background: color-mix(in oklab, var(--hl-silver) 45%, transparent);
146
+ }
147
+ .hl-footer-resizer.is-dragging::after {
148
+ background: var(--hl-silver-hi);
149
+ }
150
+
151
+ /* A finger needs a larger target, and a grip that shows without hovering. */
152
+ @media (pointer: coarse) {
153
+ .hl-footer-resizer {
154
+ top: -14px;
155
+ height: 28px;
156
+ }
157
+ .hl-footer-resizer::before {
158
+ top: 13px;
159
+ }
160
+ .hl-footer-resizer::after {
161
+ width: 44px;
162
+ opacity: 0.7;
163
+ }
164
+ }
package/lib/styles.css CHANGED
@@ -13,6 +13,7 @@
13
13
  @import './nodes/HlangNode.css';
14
14
  @import './nodes/AssetNode.css';
15
15
  @import './nodes/PillNode.css';
16
+ @import './live/LivePulse.css';
16
17
  @import './edges/FlowEdge.css';
17
18
  @import './shell/EditorShell.css';
18
19
  @import './toolbar/Toolbar.css';
@@ -27,6 +28,7 @@
27
28
  @import './panels/RailTabs.css';
28
29
  @import './panels/AssetGrid.css';
29
30
  @import './panels/PositionPanel.css';
31
+ @import './panels/RunLog.css';
30
32
  @import './command-palette/NodeSearch.css';
31
33
  @import './context-menu/NodeContextMenu.css';
32
34
  @import './overlays/Cheatsheet.css';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hlang-org/editor-ui",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Lumen design system for hlang: node, edge, panel, and shell components for a React Flow node editor, built on @hlang-org/editor-react.",
5
5
  "keywords": [
6
6
  "hlang",
@@ -59,9 +59,9 @@
59
59
  "access": "public"
60
60
  },
61
61
  "dependencies": {
62
- "@hlang-org/editor-react": "^0.1.2",
63
- "@hlang-org/editor-core": "^0.2.0",
64
- "@hlang-org/interpreter": "^2.0.0"
62
+ "@hlang-org/editor-core": "^0.3.0",
63
+ "@hlang-org/editor-react": "^0.2.0",
64
+ "@hlang-org/interpreter": "^2.1.0"
65
65
  },
66
66
  "peerDependencies": {
67
67
  "@xyflow/react": "^12.0.0",
@@ -92,7 +92,7 @@
92
92
  "build": "tsup && node scripts/copy-css.mjs",
93
93
  "test": "vitest run --coverage",
94
94
  "lint": "eslint \"src/**/*.ts\" \"src/**/*.tsx\"",
95
- "lint:pkg": "publint && attw --pack --exclude-entrypoints ./tokens.css ./styles.css",
95
+ "lint:pkg": "publint && attw --pack",
96
96
  "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
97
97
  "clean": "rm -rf lib coverage"
98
98
  }