@jolly-pixel/ui 1.0.1 → 2.0.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.
- package/LICENSE +44 -44
- package/NOTICE +9 -0
- package/README.md +194 -194
- package/dist/containers/Dialog.js +11 -11
- package/dist/containers/Dialog.styles.js +48 -48
- package/dist/containers/Dock.js +11 -11
- package/dist/containers/Dock.styles.js +351 -351
- package/dist/containers/DockLayout.js +4 -4
- package/dist/containers/Floating.js +23 -23
- package/dist/containers/Floating.styles.js +116 -116
- package/dist/containers/Folder.js +28 -28
- package/dist/containers/Folder.styles.js +221 -221
- package/dist/containers/Pane.js +50 -50
- package/dist/containers/Pane.styles.js +186 -186
- package/dist/containers/Rail.js +18 -18
- package/dist/containers/Tab.js +10 -10
- package/dist/containers/Tabs.js +26 -26
- package/dist/containers/Tabs.styles.js +93 -93
- package/dist/containers/Toolbar.js +25 -25
- package/dist/containers/resize.js +5 -5
- package/dist/controls/Button.js +9 -9
- package/dist/controls/Button.styles.js +79 -79
- package/dist/controls/ButtonGroup.js +28 -28
- package/dist/controls/ButtonGroup.styles.js +98 -98
- package/dist/controls/Checkbox.js +14 -14
- package/dist/controls/Checkbox.styles.js +111 -111
- package/dist/controls/Color.js +51 -51
- package/dist/controls/Color.styles.js +83 -83
- package/dist/controls/ColorPicker.js +104 -104
- package/dist/controls/ColorPicker.styles.js +296 -296
- package/dist/controls/Control.js +33 -33
- package/dist/controls/Control.styles.js +102 -102
- package/dist/controls/Controls.js +11 -11
- package/dist/controls/Controls.styles.js +98 -98
- package/dist/controls/Flags.js +18 -18
- package/dist/controls/Flags.styles.js +59 -59
- package/dist/controls/Number.js +21 -21
- package/dist/controls/Number.styles.js +44 -44
- package/dist/controls/PropertyRow.js +13 -13
- package/dist/controls/PropertyRow.styles.js +105 -105
- package/dist/controls/Range.js +24 -24
- package/dist/controls/Range.styles.js +25 -25
- package/dist/controls/Select.js +23 -23
- package/dist/controls/Select.styles.js +47 -47
- package/dist/controls/Separator.js +11 -11
- package/dist/controls/Separator.styles.js +45 -45
- package/dist/controls/Slider.js +36 -36
- package/dist/controls/Slider.styles.js +161 -161
- package/dist/controls/Text.js +17 -17
- package/dist/data/Tree.d.ts +0 -14
- package/dist/data/Tree.d.ts.map +1 -1
- package/dist/data/Tree.js +90 -120
- package/dist/data/Tree.js.map +1 -1
- package/dist/data/Tree.styles.d.ts.map +1 -1
- package/dist/data/Tree.styles.js +220 -237
- package/dist/data/Tree.styles.js.map +1 -1
- package/dist/data/dropZone.d.ts +0 -10
- package/dist/data/dropZone.d.ts.map +1 -1
- package/dist/data/dropZone.js +0 -10
- package/dist/data/dropZone.js.map +1 -1
- package/dist/data/resolveRename.d.ts +0 -3
- package/dist/data/resolveRename.d.ts.map +1 -1
- package/dist/data/resolveRename.js +0 -3
- package/dist/data/resolveRename.js.map +1 -1
- package/dist/data/resolveReparent.d.ts +0 -7
- package/dist/data/resolveReparent.d.ts.map +1 -1
- package/dist/data/resolveReparent.js +0 -6
- package/dist/data/resolveReparent.js.map +1 -1
- package/dist/data/rowDragSession.d.ts +0 -8
- package/dist/data/rowDragSession.d.ts.map +1 -1
- package/dist/data/rowDragSession.js +0 -6
- package/dist/data/rowDragSession.js.map +1 -1
- package/dist/data/treeNodes.d.ts +0 -6
- package/dist/data/treeNodes.d.ts.map +1 -1
- package/dist/data/treeNodes.js +2 -7
- package/dist/data/treeNodes.js.map +1 -1
- package/dist/feedback/JollyPixelLogo.js +84 -84
- package/dist/feedback/Loading.js +29 -29
- package/dist/feedback/Loading.styles.js +230 -230
- package/dist/feedback/Log.js +8 -8
- package/dist/feedback/Log.styles.js +61 -61
- package/dist/feedback/Progress.js +17 -17
- package/dist/feedback/Progress.styles.js +146 -146
- package/dist/field/JollyField.js +51 -51
- package/dist/field/JollyField.styles.js +429 -429
- package/dist/icon/Icon.js +24 -24
- package/dist/icon/builtins.js +126 -126
- package/dist/interaction/drag/DragSession.js +6 -6
- package/dist/interaction/scrub/ScrubController.js +6 -6
- package/dist/math/AxisController.js +22 -22
- package/dist/math/Point2d.js +12 -12
- package/dist/math/Point2d.styles.js +49 -49
- package/dist/math/Quaternion.js +4 -4
- package/dist/math/Transform.js +40 -40
- package/dist/math/Transform.styles.js +17 -17
- package/dist/math/VectorField.js +4 -4
- package/dist/math/VectorField.styles.js +102 -102
- package/dist/monitors/Graph.js +8 -8
- package/dist/monitors/Graph.styles.js +42 -42
- package/dist/monitors/Monitor.js +5 -5
- package/dist/monitors/Monitor.styles.js +31 -31
- package/dist/peer/Presence.js +33 -33
- package/dist/peer/Presence.styles.js +82 -82
- package/dist/stats/Stats.js +6 -6
- package/dist/stats/Stats.styles.js +54 -54
- package/dist/theme/components/DensityControl.js +16 -16
- package/dist/theme/components/ThemeControl.js +16 -16
- package/dist/theme/components/ThemePreferences.js +18 -18
- package/dist/theme/font.js +9 -9
- package/dist/theme/styles/hiddenStyles.js +4 -4
- package/dist/theme/styles/mixins.js +16 -16
- package/dist/theme/styles/themeStyles.js +4 -4
- package/dist/theme/tokens/density.js +19 -19
- package/dist/theme/tokens/ramps.js +40 -40
- package/dist/theme/tokens/scales.js +56 -56
- package/dist/theme/tokens/semantic.js +184 -184
- package/package.json +6 -5
|
@@ -6,434 +6,434 @@ import { fillTransition, truncate } from "../theme/styles/mixins.js";
|
|
|
6
6
|
/**
|
|
7
7
|
* Shared field layout and state styles.
|
|
8
8
|
*/
|
|
9
|
-
export const fieldStyles = css `
|
|
10
|
-
/*
|
|
11
|
-
* Rows carry no outer spacing. The container that stacks them owns the gap,
|
|
12
|
-
* so a consumer can stack fields flush when that is what they want.
|
|
13
|
-
*/
|
|
14
|
-
:host {
|
|
15
|
-
--jolly-field-active-color: light-dark(
|
|
16
|
-
var(--jolly-neutral-600),
|
|
17
|
-
var(--jolly-neutral-50)
|
|
18
|
-
);
|
|
19
|
-
--jolly-field-active-color-hover: light-dark(
|
|
20
|
-
var(--jolly-neutral-500),
|
|
21
|
-
var(--jolly-neutral-200)
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
display: block;
|
|
25
|
-
font-family: var(--jolly-font-family, ui-monospace, monospace);
|
|
26
|
-
font-size: var(--jolly-font-size, 11px);
|
|
27
|
-
color: var(--jolly-text, ${kFallback.text});
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
:host([colored]) {
|
|
31
|
-
--jolly-field-active-color: var(--jolly-accent-fill);
|
|
32
|
-
--jolly-field-active-color-hover: var(--jolly-accent-fill-hover);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
:host([disabled]) {
|
|
36
|
-
opacity: 0.5;
|
|
37
|
-
pointer-events: none;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.row {
|
|
41
|
-
display: flex;
|
|
42
|
-
align-items: center;
|
|
43
|
-
gap: var(--jolly-space-1, 4px);
|
|
44
|
-
min-height: var(--jolly-row-height, 20px);
|
|
45
|
-
padding-inline: var(--jolly-space-1, 4px)
|
|
46
|
-
var(--jolly-field-inset-end, var(--jolly-space-1, 4px));
|
|
47
|
-
border-radius: var(--jolly-radius-sm, 2px);
|
|
48
|
-
${fillTransition}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/*
|
|
52
|
-
* Flattened into the row's flex items by default, so inline layout is
|
|
53
|
-
* unaffected by the grouping these wrap for stacked layout.
|
|
54
|
-
*/
|
|
55
|
-
.leading,
|
|
56
|
-
.content {
|
|
57
|
-
display: contents;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
:host([label-position="top"]) .row {
|
|
61
|
-
flex-direction: column;
|
|
62
|
-
align-items: stretch;
|
|
63
|
-
min-height: auto;
|
|
64
|
-
gap: calc(var(--jolly-space-1, 4px) / 2);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
:host([label-position="top"]) .leading,
|
|
68
|
-
:host([label-position="top"]) .content {
|
|
69
|
-
display: flex;
|
|
70
|
-
align-items: center;
|
|
71
|
-
gap: var(--jolly-space-1, 4px);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/*
|
|
75
|
-
* The gutter sits only on the label's line, so the value line needs a
|
|
76
|
-
* matching inset to keep both lines starting at the same edge.
|
|
77
|
-
*/
|
|
78
|
-
:host([label-position="top"]) .content {
|
|
79
|
-
padding-inline-start: calc(
|
|
80
|
-
var(--jolly-gutter-width, 0px) + var(--jolly-space-1, 4px)
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/* With no label the leading line is an empty band, unless it holds a lock. */
|
|
85
|
-
:host([unlabeled]:not([locked])[label-position="top"]) .leading {
|
|
86
|
-
display: none;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
:host([unlabeled]:not([locked])[label-position="top"]) .content {
|
|
90
|
-
padding-inline-start: 0;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/*
|
|
94
|
-
* Locating the active row in a long pane. Deliberately fainter than the
|
|
95
|
-
* control's own focus tint, so the two read as a hierarchy and not a clash.
|
|
96
|
-
*/
|
|
97
|
-
.row:focus-within {
|
|
98
|
-
background: var(--jolly-row-bg-focus);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/*
|
|
102
|
-
* Zero width by default. A collaborative container opts its subtree in, which
|
|
103
|
-
* buys back the fixed inset that keeps lock state from shifting the row.
|
|
104
|
-
*/
|
|
105
|
-
.gutter {
|
|
106
|
-
display: flex;
|
|
107
|
-
align-items: center;
|
|
108
|
-
justify-content: center;
|
|
109
|
-
box-sizing: border-box;
|
|
110
|
-
flex: 0 0 auto;
|
|
111
|
-
width: var(--jolly-gutter-width, 0px);
|
|
112
|
-
height: 14px;
|
|
113
|
-
overflow: hidden;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/*
|
|
117
|
-
* Without a label the gap after a collapsed gutter is an inset paid for
|
|
118
|
-
* nothing. Locked keeps it: there the gutter paints an icon.
|
|
119
|
-
*/
|
|
120
|
-
:host([unlabeled]:not([locked])) .gutter {
|
|
121
|
-
margin-inline-end: calc(var(--jolly-space-1, 4px) * -1);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/* No label column to inset for, so both edges fall back to the row inset. */
|
|
125
|
-
:host([unlabeled]:not([locked])) .row {
|
|
126
|
-
padding-inline-start: var(--jolly-field-inset-end, var(--jolly-space-1, 4px));
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/*
|
|
130
|
-
* A lock always has to be visible, even where nothing reserved room for it.
|
|
131
|
-
* Opting the subtree in is what turns this from a widening row into a fixed
|
|
132
|
-
* inset; without it the lock still shows, it just costs a shift.
|
|
133
|
-
*/
|
|
134
|
-
:host([locked]) .gutter {
|
|
135
|
-
width: max(var(--jolly-gutter-width, 0px), 14px);
|
|
136
|
-
overflow: visible;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/*
|
|
140
|
-
* Icons default to the 16px display size, which overflows the gutter. The
|
|
141
|
-
* lock is chrome inside a 14px box, so it is sized to the box it sits in.
|
|
142
|
-
*/
|
|
143
|
-
.gutter > jolly-icon {
|
|
144
|
-
width: 14px;
|
|
145
|
-
height: 14px;
|
|
146
|
-
color: var(--jolly-locked-ring, var(--jolly-locked));
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/*
|
|
150
|
-
* A configured width aligns value columns across fields. The cap stops a long
|
|
151
|
-
* label from eating the value area; a field packed beside another on one line
|
|
152
|
-
* lifts it, since there the label is legitimately most of the row.
|
|
153
|
-
*/
|
|
154
|
-
.label {
|
|
155
|
-
flex: 0 0 auto;
|
|
156
|
-
width: var(--jolly-label-width, auto);
|
|
157
|
-
min-width: 0;
|
|
158
|
-
max-width: var(--jolly-label-max-width, 45%);
|
|
159
|
-
color: var(--jolly-text-muted);
|
|
160
|
-
text-align: start;
|
|
161
|
-
${truncate}
|
|
162
|
-
user-select: none;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
:host([label-position="top"]) .label {
|
|
166
|
-
width: auto;
|
|
167
|
-
max-width: none;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
.value {
|
|
171
|
-
display: flex;
|
|
172
|
-
align-items: center;
|
|
173
|
-
flex: 1 1 auto;
|
|
174
|
-
gap: var(--jolly-space-1, 4px);
|
|
175
|
-
min-width: 0;
|
|
176
|
-
font-variant-numeric: var(--jolly-font-numeric, tabular-nums);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/*
|
|
180
|
-
* Base input styles shared by field controls. Boundaries are carried by the
|
|
181
|
-
* fill, so there is no border to state here.
|
|
182
|
-
*/
|
|
183
|
-
.value input:not([type="color"]),
|
|
184
|
-
.value select {
|
|
185
|
-
flex: 1 1 auto;
|
|
186
|
-
min-width: 0;
|
|
187
|
-
height: var(--jolly-control-height, 20px);
|
|
188
|
-
padding: 0 var(--jolly-space-1, 4px);
|
|
189
|
-
border: 0;
|
|
190
|
-
border-radius: var(--jolly-radius-sm, 2px);
|
|
191
|
-
background: var(--jolly-control-bg, ${kFallback.controlBg});
|
|
192
|
-
color: inherit;
|
|
193
|
-
font: inherit;
|
|
194
|
-
font-variant-numeric: inherit;
|
|
195
|
-
${fillTransition}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
.value input:hover:not(:disabled),
|
|
199
|
-
.value select:hover:not(:disabled) {
|
|
200
|
-
background: var(--jolly-control-bg-hover);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/*
|
|
204
|
-
* Focus is a fill step rather than an outline. The step has to beat hover,
|
|
205
|
-
* because both are the same channel.
|
|
206
|
-
*/
|
|
207
|
-
.value input:focus,
|
|
208
|
-
.value select:focus {
|
|
209
|
-
background: var(--jolly-control-bg-focus);
|
|
210
|
-
outline: none;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/*
|
|
214
|
-
* Numeric and monitor-style rows read better against the trailing edge, where
|
|
215
|
-
* the digits line up down the pane.
|
|
216
|
-
*/
|
|
217
|
-
:host([align="end"]) .value input,
|
|
218
|
-
:host([align="end"]) .value select {
|
|
219
|
-
text-align: end;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
:host([invalid]) .value input,
|
|
223
|
-
:host([invalid]) .value select {
|
|
224
|
-
background: var(--jolly-invalid-bg);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
:host([invalid]) .value input:hover:not(:disabled),
|
|
228
|
-
:host([invalid]) .value select:hover:not(:disabled) {
|
|
229
|
-
background: var(--jolly-invalid-bg-hover);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
:host([invalid]) .value input:focus,
|
|
233
|
-
:host([invalid]) .value select:focus {
|
|
234
|
-
background: var(--jolly-invalid-bg-focus);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
:host([readonly]) .value input,
|
|
238
|
-
:host([readonly]) .value select {
|
|
239
|
-
background: var(--jolly-control-bg-muted);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/*
|
|
243
|
-
* Modified and locked both want the leading bar, so locked takes it: a locked
|
|
244
|
-
* field is not editable, which makes reverting moot anyway.
|
|
245
|
-
*/
|
|
246
|
-
:host([modified]:not([locked])) {
|
|
247
|
-
box-shadow: inset 2px 0 0 0 var(--jolly-field-active-color);
|
|
248
|
-
border-radius: var(--jolly-radius-sm, 2px);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
:host([locked]) {
|
|
252
|
-
padding-block: calc(var(--jolly-space-1, 4px) / 2);
|
|
253
|
-
box-shadow: inset 3px 0 0 0 var(--jolly-locked-ring, var(--jolly-locked));
|
|
254
|
-
border-radius: var(--jolly-radius-sm, 2px);
|
|
255
|
-
background: color-mix(
|
|
256
|
-
in oklab,
|
|
257
|
-
var(--jolly-locked-ring, var(--jolly-locked)) 12%,
|
|
258
|
-
transparent
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/*
|
|
263
|
-
* A container can reserve one trailing column across sibling fields. The
|
|
264
|
-
* negative margin absorbs the row gap; padding restores it for presence,
|
|
265
|
-
* while the revert button cancels that padding to stay joined to the value.
|
|
266
|
-
*/
|
|
267
|
-
.trailing {
|
|
268
|
-
display: flex;
|
|
269
|
-
align-items: center;
|
|
270
|
-
box-sizing: border-box;
|
|
271
|
-
flex: 0 0 auto;
|
|
272
|
-
gap: var(--jolly-space-1, 4px);
|
|
273
|
-
width: var(--jolly-field-trailing-width, auto);
|
|
274
|
-
margin-inline-start: calc(var(--jolly-space-1, 4px) * -1);
|
|
275
|
-
padding-inline-start: var(--jolly-space-1, 4px);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
.trailing:not(:has(.revert, .peers)) {
|
|
279
|
-
padding-inline-start: 0;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/*
|
|
283
|
-
* The muted action stays visible while a modified value can be restored.
|
|
284
|
-
* It joins the value edge and uses the full control height, so its hover fill
|
|
285
|
-
* reads as trailing field chrome instead of a highlight behind the glyph.
|
|
286
|
-
*/
|
|
287
|
-
.revert {
|
|
288
|
-
display: flex;
|
|
289
|
-
align-items: center;
|
|
290
|
-
justify-content: center;
|
|
291
|
-
flex: 0 0 auto;
|
|
292
|
-
width: var(--jolly-control-height, 20px);
|
|
293
|
-
height: var(--jolly-control-height, 20px);
|
|
294
|
-
margin-inline-start: calc(var(--jolly-space-1, 4px) * -1);
|
|
295
|
-
padding: 0;
|
|
296
|
-
border: 0;
|
|
297
|
-
border-radius:
|
|
298
|
-
0
|
|
299
|
-
var(--jolly-radius-sm, 2px)
|
|
300
|
-
var(--jolly-radius-sm, 2px)
|
|
301
|
-
0;
|
|
302
|
-
background: none;
|
|
303
|
-
color: var(--jolly-text-muted);
|
|
304
|
-
cursor: pointer;
|
|
305
|
-
${fillTransition}
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
.revert > jolly-icon {
|
|
309
|
-
width: 14px;
|
|
310
|
-
height: 14px;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
/* Filled values and the trailing action form a single control silhouette. */
|
|
314
|
-
.value:has(+ .trailing > .revert) input[type="text"]:last-child,
|
|
315
|
-
.value:has(+ .trailing > .revert) select {
|
|
316
|
-
border-start-end-radius: 0;
|
|
317
|
-
border-end-end-radius: 0;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
.revert:hover {
|
|
321
|
-
background: var(--jolly-control-bg);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
.revert:focus-visible {
|
|
325
|
-
background: var(--jolly-control-bg-focus);
|
|
326
|
-
outline: none;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
.peers {
|
|
330
|
-
display: flex;
|
|
331
|
-
flex: 0 0 auto;
|
|
332
|
-
align-items: center;
|
|
333
|
-
margin-inline-start: auto;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
.chip {
|
|
337
|
-
width: 10px;
|
|
338
|
-
height: 10px;
|
|
339
|
-
margin-left: -3px;
|
|
340
|
-
border: 1px solid var(--jolly-surface);
|
|
341
|
-
border-radius: 50%;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
.chip:first-child {
|
|
345
|
-
margin-left: 0;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
.overflow {
|
|
349
|
-
margin-left: var(--jolly-space-1, 4px);
|
|
350
|
-
color: var(--jolly-text-muted);
|
|
351
|
-
font-size: 0.85em;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/* Tooltips grow inward to stay within the field bounds. */
|
|
355
|
-
[data-tooltip] {
|
|
356
|
-
position: relative;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
[data-tooltip]::after {
|
|
360
|
-
content: attr(data-tooltip);
|
|
361
|
-
position: absolute;
|
|
362
|
-
bottom: calc(100% + var(--jolly-space-1, 4px));
|
|
363
|
-
z-index: 1;
|
|
364
|
-
padding: 2px 6px;
|
|
365
|
-
border-radius: var(--jolly-radius-sm, 2px);
|
|
366
|
-
background: var(--jolly-surface-raised);
|
|
367
|
-
box-shadow: var(--jolly-shadow-overlay);
|
|
368
|
-
color: var(--jolly-text);
|
|
369
|
-
font-size: 0.85em;
|
|
370
|
-
white-space: nowrap;
|
|
371
|
-
opacity: 0;
|
|
372
|
-
pointer-events: none;
|
|
373
|
-
transform: translateY(2px);
|
|
374
|
-
transition:
|
|
375
|
-
opacity var(--jolly-duration-fast, 100ms) var(--jolly-easing, ease),
|
|
376
|
-
transform var(--jolly-duration-fast, 100ms) var(--jolly-easing, ease);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
/*
|
|
380
|
-
* Offset on the tooltip rather than as gutter padding, which would widen the
|
|
381
|
-
* gutter on exactly the rows that must not change width.
|
|
382
|
-
*/
|
|
383
|
-
.gutter[data-tooltip]::after {
|
|
384
|
-
left: 3px;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
.chip::after {
|
|
388
|
-
right: 0;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
[data-tooltip]:hover::after {
|
|
392
|
-
opacity: 1;
|
|
393
|
-
transform: translateY(0);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/* Align help and error text with the value area. */
|
|
397
|
-
.description,
|
|
398
|
-
.error {
|
|
399
|
-
display: flex;
|
|
400
|
-
align-items: flex-start;
|
|
401
|
-
gap: var(--jolly-space-1, 4px);
|
|
402
|
-
margin-block: calc(var(--jolly-space-1, 4px) / 2);
|
|
403
|
-
margin-inline: calc(
|
|
404
|
-
var(--jolly-gutter-width, 0px) + (var(--jolly-space-1, 4px) * 2)
|
|
405
|
-
)
|
|
406
|
-
var(--jolly-space-1, 4px);
|
|
407
|
-
font-size: 0.9em;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
/* No label column to clear, so they follow the value back to the row inset. */
|
|
411
|
-
:host([unlabeled]:not([locked])) .description,
|
|
412
|
-
:host([unlabeled]:not([locked])) .error {
|
|
413
|
-
margin-inline-start: calc(
|
|
414
|
-
var(--jolly-gutter-width, 0px) +
|
|
415
|
-
var(--jolly-field-inset-end, var(--jolly-space-1, 4px))
|
|
416
|
-
);
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
.description jolly-icon,
|
|
420
|
-
.error jolly-icon {
|
|
421
|
-
flex: 0 0 auto;
|
|
422
|
-
width: 14px;
|
|
423
|
-
height: 14px;
|
|
424
|
-
margin-block-start: 0;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
.description {
|
|
428
|
-
color: var(--jolly-text-muted);
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
.description jolly-icon {
|
|
432
|
-
color: var(--jolly-accent-text);
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
.error {
|
|
436
|
-
color: var(--jolly-danger);
|
|
437
|
-
}
|
|
9
|
+
export const fieldStyles = css `
|
|
10
|
+
/*
|
|
11
|
+
* Rows carry no outer spacing. The container that stacks them owns the gap,
|
|
12
|
+
* so a consumer can stack fields flush when that is what they want.
|
|
13
|
+
*/
|
|
14
|
+
:host {
|
|
15
|
+
--jolly-field-active-color: light-dark(
|
|
16
|
+
var(--jolly-neutral-600),
|
|
17
|
+
var(--jolly-neutral-50)
|
|
18
|
+
);
|
|
19
|
+
--jolly-field-active-color-hover: light-dark(
|
|
20
|
+
var(--jolly-neutral-500),
|
|
21
|
+
var(--jolly-neutral-200)
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
display: block;
|
|
25
|
+
font-family: var(--jolly-font-family, ui-monospace, monospace);
|
|
26
|
+
font-size: var(--jolly-font-size, 11px);
|
|
27
|
+
color: var(--jolly-text, ${kFallback.text});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
:host([colored]) {
|
|
31
|
+
--jolly-field-active-color: var(--jolly-accent-fill);
|
|
32
|
+
--jolly-field-active-color-hover: var(--jolly-accent-fill-hover);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
:host([disabled]) {
|
|
36
|
+
opacity: 0.5;
|
|
37
|
+
pointer-events: none;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.row {
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
gap: var(--jolly-space-1, 4px);
|
|
44
|
+
min-height: var(--jolly-row-height, 20px);
|
|
45
|
+
padding-inline: var(--jolly-space-1, 4px)
|
|
46
|
+
var(--jolly-field-inset-end, var(--jolly-space-1, 4px));
|
|
47
|
+
border-radius: var(--jolly-radius-sm, 2px);
|
|
48
|
+
${fillTransition}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/*
|
|
52
|
+
* Flattened into the row's flex items by default, so inline layout is
|
|
53
|
+
* unaffected by the grouping these wrap for stacked layout.
|
|
54
|
+
*/
|
|
55
|
+
.leading,
|
|
56
|
+
.content {
|
|
57
|
+
display: contents;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
:host([label-position="top"]) .row {
|
|
61
|
+
flex-direction: column;
|
|
62
|
+
align-items: stretch;
|
|
63
|
+
min-height: auto;
|
|
64
|
+
gap: calc(var(--jolly-space-1, 4px) / 2);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
:host([label-position="top"]) .leading,
|
|
68
|
+
:host([label-position="top"]) .content {
|
|
69
|
+
display: flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
gap: var(--jolly-space-1, 4px);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/*
|
|
75
|
+
* The gutter sits only on the label's line, so the value line needs a
|
|
76
|
+
* matching inset to keep both lines starting at the same edge.
|
|
77
|
+
*/
|
|
78
|
+
:host([label-position="top"]) .content {
|
|
79
|
+
padding-inline-start: calc(
|
|
80
|
+
var(--jolly-gutter-width, 0px) + var(--jolly-space-1, 4px)
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* With no label the leading line is an empty band, unless it holds a lock. */
|
|
85
|
+
:host([unlabeled]:not([locked])[label-position="top"]) .leading {
|
|
86
|
+
display: none;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
:host([unlabeled]:not([locked])[label-position="top"]) .content {
|
|
90
|
+
padding-inline-start: 0;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
* Locating the active row in a long pane. Deliberately fainter than the
|
|
95
|
+
* control's own focus tint, so the two read as a hierarchy and not a clash.
|
|
96
|
+
*/
|
|
97
|
+
.row:focus-within {
|
|
98
|
+
background: var(--jolly-row-bg-focus);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/*
|
|
102
|
+
* Zero width by default. A collaborative container opts its subtree in, which
|
|
103
|
+
* buys back the fixed inset that keeps lock state from shifting the row.
|
|
104
|
+
*/
|
|
105
|
+
.gutter {
|
|
106
|
+
display: flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
justify-content: center;
|
|
109
|
+
box-sizing: border-box;
|
|
110
|
+
flex: 0 0 auto;
|
|
111
|
+
width: var(--jolly-gutter-width, 0px);
|
|
112
|
+
height: 14px;
|
|
113
|
+
overflow: hidden;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/*
|
|
117
|
+
* Without a label the gap after a collapsed gutter is an inset paid for
|
|
118
|
+
* nothing. Locked keeps it: there the gutter paints an icon.
|
|
119
|
+
*/
|
|
120
|
+
:host([unlabeled]:not([locked])) .gutter {
|
|
121
|
+
margin-inline-end: calc(var(--jolly-space-1, 4px) * -1);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* No label column to inset for, so both edges fall back to the row inset. */
|
|
125
|
+
:host([unlabeled]:not([locked])) .row {
|
|
126
|
+
padding-inline-start: var(--jolly-field-inset-end, var(--jolly-space-1, 4px));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/*
|
|
130
|
+
* A lock always has to be visible, even where nothing reserved room for it.
|
|
131
|
+
* Opting the subtree in is what turns this from a widening row into a fixed
|
|
132
|
+
* inset; without it the lock still shows, it just costs a shift.
|
|
133
|
+
*/
|
|
134
|
+
:host([locked]) .gutter {
|
|
135
|
+
width: max(var(--jolly-gutter-width, 0px), 14px);
|
|
136
|
+
overflow: visible;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/*
|
|
140
|
+
* Icons default to the 16px display size, which overflows the gutter. The
|
|
141
|
+
* lock is chrome inside a 14px box, so it is sized to the box it sits in.
|
|
142
|
+
*/
|
|
143
|
+
.gutter > jolly-icon {
|
|
144
|
+
width: 14px;
|
|
145
|
+
height: 14px;
|
|
146
|
+
color: var(--jolly-locked-ring, var(--jolly-locked));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/*
|
|
150
|
+
* A configured width aligns value columns across fields. The cap stops a long
|
|
151
|
+
* label from eating the value area; a field packed beside another on one line
|
|
152
|
+
* lifts it, since there the label is legitimately most of the row.
|
|
153
|
+
*/
|
|
154
|
+
.label {
|
|
155
|
+
flex: 0 0 auto;
|
|
156
|
+
width: var(--jolly-label-width, auto);
|
|
157
|
+
min-width: 0;
|
|
158
|
+
max-width: var(--jolly-label-max-width, 45%);
|
|
159
|
+
color: var(--jolly-text-muted);
|
|
160
|
+
text-align: start;
|
|
161
|
+
${truncate}
|
|
162
|
+
user-select: none;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
:host([label-position="top"]) .label {
|
|
166
|
+
width: auto;
|
|
167
|
+
max-width: none;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.value {
|
|
171
|
+
display: flex;
|
|
172
|
+
align-items: center;
|
|
173
|
+
flex: 1 1 auto;
|
|
174
|
+
gap: var(--jolly-space-1, 4px);
|
|
175
|
+
min-width: 0;
|
|
176
|
+
font-variant-numeric: var(--jolly-font-numeric, tabular-nums);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/*
|
|
180
|
+
* Base input styles shared by field controls. Boundaries are carried by the
|
|
181
|
+
* fill, so there is no border to state here.
|
|
182
|
+
*/
|
|
183
|
+
.value input:not([type="color"]),
|
|
184
|
+
.value select {
|
|
185
|
+
flex: 1 1 auto;
|
|
186
|
+
min-width: 0;
|
|
187
|
+
height: var(--jolly-control-height, 20px);
|
|
188
|
+
padding: 0 var(--jolly-space-1, 4px);
|
|
189
|
+
border: 0;
|
|
190
|
+
border-radius: var(--jolly-radius-sm, 2px);
|
|
191
|
+
background: var(--jolly-control-bg, ${kFallback.controlBg});
|
|
192
|
+
color: inherit;
|
|
193
|
+
font: inherit;
|
|
194
|
+
font-variant-numeric: inherit;
|
|
195
|
+
${fillTransition}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.value input:hover:not(:disabled),
|
|
199
|
+
.value select:hover:not(:disabled) {
|
|
200
|
+
background: var(--jolly-control-bg-hover);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/*
|
|
204
|
+
* Focus is a fill step rather than an outline. The step has to beat hover,
|
|
205
|
+
* because both are the same channel.
|
|
206
|
+
*/
|
|
207
|
+
.value input:focus,
|
|
208
|
+
.value select:focus {
|
|
209
|
+
background: var(--jolly-control-bg-focus);
|
|
210
|
+
outline: none;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/*
|
|
214
|
+
* Numeric and monitor-style rows read better against the trailing edge, where
|
|
215
|
+
* the digits line up down the pane.
|
|
216
|
+
*/
|
|
217
|
+
:host([align="end"]) .value input,
|
|
218
|
+
:host([align="end"]) .value select {
|
|
219
|
+
text-align: end;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
:host([invalid]) .value input,
|
|
223
|
+
:host([invalid]) .value select {
|
|
224
|
+
background: var(--jolly-invalid-bg);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
:host([invalid]) .value input:hover:not(:disabled),
|
|
228
|
+
:host([invalid]) .value select:hover:not(:disabled) {
|
|
229
|
+
background: var(--jolly-invalid-bg-hover);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
:host([invalid]) .value input:focus,
|
|
233
|
+
:host([invalid]) .value select:focus {
|
|
234
|
+
background: var(--jolly-invalid-bg-focus);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
:host([readonly]) .value input,
|
|
238
|
+
:host([readonly]) .value select {
|
|
239
|
+
background: var(--jolly-control-bg-muted);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/*
|
|
243
|
+
* Modified and locked both want the leading bar, so locked takes it: a locked
|
|
244
|
+
* field is not editable, which makes reverting moot anyway.
|
|
245
|
+
*/
|
|
246
|
+
:host([modified]:not([locked])) {
|
|
247
|
+
box-shadow: inset 2px 0 0 0 var(--jolly-field-active-color);
|
|
248
|
+
border-radius: var(--jolly-radius-sm, 2px);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
:host([locked]) {
|
|
252
|
+
padding-block: calc(var(--jolly-space-1, 4px) / 2);
|
|
253
|
+
box-shadow: inset 3px 0 0 0 var(--jolly-locked-ring, var(--jolly-locked));
|
|
254
|
+
border-radius: var(--jolly-radius-sm, 2px);
|
|
255
|
+
background: color-mix(
|
|
256
|
+
in oklab,
|
|
257
|
+
var(--jolly-locked-ring, var(--jolly-locked)) 12%,
|
|
258
|
+
transparent
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/*
|
|
263
|
+
* A container can reserve one trailing column across sibling fields. The
|
|
264
|
+
* negative margin absorbs the row gap; padding restores it for presence,
|
|
265
|
+
* while the revert button cancels that padding to stay joined to the value.
|
|
266
|
+
*/
|
|
267
|
+
.trailing {
|
|
268
|
+
display: flex;
|
|
269
|
+
align-items: center;
|
|
270
|
+
box-sizing: border-box;
|
|
271
|
+
flex: 0 0 auto;
|
|
272
|
+
gap: var(--jolly-space-1, 4px);
|
|
273
|
+
width: var(--jolly-field-trailing-width, auto);
|
|
274
|
+
margin-inline-start: calc(var(--jolly-space-1, 4px) * -1);
|
|
275
|
+
padding-inline-start: var(--jolly-space-1, 4px);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.trailing:not(:has(.revert, .peers)) {
|
|
279
|
+
padding-inline-start: 0;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/*
|
|
283
|
+
* The muted action stays visible while a modified value can be restored.
|
|
284
|
+
* It joins the value edge and uses the full control height, so its hover fill
|
|
285
|
+
* reads as trailing field chrome instead of a highlight behind the glyph.
|
|
286
|
+
*/
|
|
287
|
+
.revert {
|
|
288
|
+
display: flex;
|
|
289
|
+
align-items: center;
|
|
290
|
+
justify-content: center;
|
|
291
|
+
flex: 0 0 auto;
|
|
292
|
+
width: var(--jolly-control-height, 20px);
|
|
293
|
+
height: var(--jolly-control-height, 20px);
|
|
294
|
+
margin-inline-start: calc(var(--jolly-space-1, 4px) * -1);
|
|
295
|
+
padding: 0;
|
|
296
|
+
border: 0;
|
|
297
|
+
border-radius:
|
|
298
|
+
0
|
|
299
|
+
var(--jolly-radius-sm, 2px)
|
|
300
|
+
var(--jolly-radius-sm, 2px)
|
|
301
|
+
0;
|
|
302
|
+
background: none;
|
|
303
|
+
color: var(--jolly-text-muted);
|
|
304
|
+
cursor: pointer;
|
|
305
|
+
${fillTransition}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.revert > jolly-icon {
|
|
309
|
+
width: 14px;
|
|
310
|
+
height: 14px;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/* Filled values and the trailing action form a single control silhouette. */
|
|
314
|
+
.value:has(+ .trailing > .revert) input[type="text"]:last-child,
|
|
315
|
+
.value:has(+ .trailing > .revert) select {
|
|
316
|
+
border-start-end-radius: 0;
|
|
317
|
+
border-end-end-radius: 0;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.revert:hover {
|
|
321
|
+
background: var(--jolly-control-bg);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.revert:focus-visible {
|
|
325
|
+
background: var(--jolly-control-bg-focus);
|
|
326
|
+
outline: none;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.peers {
|
|
330
|
+
display: flex;
|
|
331
|
+
flex: 0 0 auto;
|
|
332
|
+
align-items: center;
|
|
333
|
+
margin-inline-start: auto;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.chip {
|
|
337
|
+
width: 10px;
|
|
338
|
+
height: 10px;
|
|
339
|
+
margin-left: -3px;
|
|
340
|
+
border: 1px solid var(--jolly-surface);
|
|
341
|
+
border-radius: 50%;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
.chip:first-child {
|
|
345
|
+
margin-left: 0;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
.overflow {
|
|
349
|
+
margin-left: var(--jolly-space-1, 4px);
|
|
350
|
+
color: var(--jolly-text-muted);
|
|
351
|
+
font-size: 0.85em;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/* Tooltips grow inward to stay within the field bounds. */
|
|
355
|
+
[data-tooltip] {
|
|
356
|
+
position: relative;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
[data-tooltip]::after {
|
|
360
|
+
content: attr(data-tooltip);
|
|
361
|
+
position: absolute;
|
|
362
|
+
bottom: calc(100% + var(--jolly-space-1, 4px));
|
|
363
|
+
z-index: 1;
|
|
364
|
+
padding: 2px 6px;
|
|
365
|
+
border-radius: var(--jolly-radius-sm, 2px);
|
|
366
|
+
background: var(--jolly-surface-raised);
|
|
367
|
+
box-shadow: var(--jolly-shadow-overlay);
|
|
368
|
+
color: var(--jolly-text);
|
|
369
|
+
font-size: 0.85em;
|
|
370
|
+
white-space: nowrap;
|
|
371
|
+
opacity: 0;
|
|
372
|
+
pointer-events: none;
|
|
373
|
+
transform: translateY(2px);
|
|
374
|
+
transition:
|
|
375
|
+
opacity var(--jolly-duration-fast, 100ms) var(--jolly-easing, ease),
|
|
376
|
+
transform var(--jolly-duration-fast, 100ms) var(--jolly-easing, ease);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/*
|
|
380
|
+
* Offset on the tooltip rather than as gutter padding, which would widen the
|
|
381
|
+
* gutter on exactly the rows that must not change width.
|
|
382
|
+
*/
|
|
383
|
+
.gutter[data-tooltip]::after {
|
|
384
|
+
left: 3px;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.chip::after {
|
|
388
|
+
right: 0;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
[data-tooltip]:hover::after {
|
|
392
|
+
opacity: 1;
|
|
393
|
+
transform: translateY(0);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/* Align help and error text with the value area. */
|
|
397
|
+
.description,
|
|
398
|
+
.error {
|
|
399
|
+
display: flex;
|
|
400
|
+
align-items: flex-start;
|
|
401
|
+
gap: var(--jolly-space-1, 4px);
|
|
402
|
+
margin-block: calc(var(--jolly-space-1, 4px) / 2);
|
|
403
|
+
margin-inline: calc(
|
|
404
|
+
var(--jolly-gutter-width, 0px) + (var(--jolly-space-1, 4px) * 2)
|
|
405
|
+
)
|
|
406
|
+
var(--jolly-space-1, 4px);
|
|
407
|
+
font-size: 0.9em;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/* No label column to clear, so they follow the value back to the row inset. */
|
|
411
|
+
:host([unlabeled]:not([locked])) .description,
|
|
412
|
+
:host([unlabeled]:not([locked])) .error {
|
|
413
|
+
margin-inline-start: calc(
|
|
414
|
+
var(--jolly-gutter-width, 0px) +
|
|
415
|
+
var(--jolly-field-inset-end, var(--jolly-space-1, 4px))
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
.description jolly-icon,
|
|
420
|
+
.error jolly-icon {
|
|
421
|
+
flex: 0 0 auto;
|
|
422
|
+
width: 14px;
|
|
423
|
+
height: 14px;
|
|
424
|
+
margin-block-start: 0;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
.description {
|
|
428
|
+
color: var(--jolly-text-muted);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.description jolly-icon {
|
|
432
|
+
color: var(--jolly-accent-text);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
.error {
|
|
436
|
+
color: var(--jolly-danger);
|
|
437
|
+
}
|
|
438
438
|
`;
|
|
439
439
|
//# sourceMappingURL=JollyField.styles.js.map
|