@perspective-dev/viewer 5.2.0 → 5.3.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 (133) hide show
  1. package/dist/cdn/perspective-viewer.js +2 -2
  2. package/dist/cdn/perspective-viewer.js.map +2 -2
  3. package/dist/css/botanical.css +1 -1
  4. package/dist/css/dracula.css +1 -1
  5. package/dist/css/gruvbox-dark.css +1 -1
  6. package/dist/css/gruvbox.css +1 -1
  7. package/dist/css/icons.css +1 -1
  8. package/dist/css/monokai.css +1 -1
  9. package/dist/css/phosphor.css +1 -1
  10. package/dist/css/pro-dark.css +1 -1
  11. package/dist/css/pro.css +1 -1
  12. package/dist/css/solarized-dark.css +1 -1
  13. package/dist/css/solarized.css +1 -1
  14. package/dist/css/themes.css +1 -1
  15. package/dist/css/vaporwave.css +1 -1
  16. package/dist/docs/perspective-docs.json +1 -1
  17. package/dist/esm/perspective-viewer.d.ts +1 -0
  18. package/dist/esm/perspective-viewer.inline.js +9 -9
  19. package/dist/esm/perspective-viewer.inline.js.map +2 -2
  20. package/dist/esm/perspective-viewer.js +4 -4
  21. package/dist/esm/perspective-viewer.js.map +2 -2
  22. package/dist/esm/plugin.d.ts +10 -0
  23. package/dist/esm/ts-rs/PanelViewerConfig.d.ts +1 -1
  24. package/dist/esm/ts-rs/SaveWorkspaceOptions.d.ts +10 -0
  25. package/dist/esm/ts-rs/ViewerConfig.d.ts +1 -1
  26. package/dist/esm/ts-rs/WorkspaceConfig.d.ts +9 -1
  27. package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +13 -3
  28. package/dist/wasm/perspective-viewer.d.ts +43 -36
  29. package/dist/wasm/perspective-viewer.js +194 -136
  30. package/dist/wasm/perspective-viewer.wasm +0 -0
  31. package/dist/wasm/perspective-viewer.wasm.d.ts +19 -17
  32. package/package.json +1 -1
  33. package/src/css/column-settings-panel.css +9 -5
  34. package/src/css/column-style.css +209 -31
  35. package/src/css/dom/select.css +2 -1
  36. package/src/css/form/code-editor.css +4 -4
  37. package/src/rust/agent/tools.rs +48 -17
  38. package/src/rust/components/column_selector/active_column.rs +2 -2
  39. package/src/rust/components/column_selector/add_expression_button.rs +3 -3
  40. package/src/rust/components/column_selector/aggregate_selector.rs +2 -3
  41. package/src/rust/components/column_selector/config_selector.rs +8 -0
  42. package/src/rust/components/column_selector/expr_edit_button.rs +4 -10
  43. package/src/rust/components/column_selector/inactive_column.rs +2 -2
  44. package/src/rust/components/column_selector.rs +48 -4
  45. package/src/rust/components/column_settings_sidebar/style_tab/primitive_field.rs +293 -126
  46. package/src/rust/components/column_settings_sidebar/style_tab.rs +262 -225
  47. package/src/rust/components/column_settings_sidebar.rs +88 -69
  48. package/src/rust/components/editable_header.rs +85 -144
  49. package/src/rust/components/expression_editor.rs +9 -16
  50. package/src/rust/components/form/code_editor.rs +16 -6
  51. package/src/rust/components/form/debug.rs +1 -0
  52. package/src/rust/components/form/mod.rs +3 -1
  53. package/src/rust/components/form/multi_stop_gradient_selector.rs +476 -0
  54. package/src/rust/components/form/named_value_picker.rs +86 -0
  55. package/src/rust/components/form/palette_selector.rs +440 -0
  56. package/src/rust/components/main_panel/msg.rs +2 -2
  57. package/src/rust/components/main_panel/reconcile.rs +4 -4
  58. package/src/rust/components/plugin_tab.rs +4 -28
  59. package/src/rust/components/settings_panel.rs +25 -20
  60. package/src/rust/components/viewer/msg.rs +46 -7
  61. package/src/rust/components/viewer/panels.rs +11 -9
  62. package/src/rust/components/viewer/render.rs +8 -3
  63. package/src/rust/components/viewer/settings.rs +163 -23
  64. package/src/rust/components/viewer/snapshots.rs +46 -21
  65. package/src/rust/components/viewer/wiring.rs +14 -25
  66. package/src/rust/components/viewer.rs +12 -8
  67. package/src/rust/config/column_config_schema.rs +100 -41
  68. package/src/rust/config/css_scale.rs +882 -0
  69. package/src/rust/config/mod.rs +2 -0
  70. package/src/rust/config/options.rs +10 -0
  71. package/src/rust/config/viewer_config.rs +49 -55
  72. package/src/rust/config/workspace_config.rs +132 -5
  73. package/src/rust/custom_elements/viewer.rs +214 -155
  74. package/src/rust/custom_events.rs +14 -1
  75. package/src/rust/js/regular_layout.rs +3 -3
  76. package/src/rust/lib.rs +2 -0
  77. package/src/rust/presentation/column_locator.rs +19 -5
  78. package/src/rust/presentation.rs +192 -36
  79. package/src/rust/queries/column_locator.rs +74 -44
  80. package/src/rust/queries/get_viewer_config.rs +0 -3
  81. package/src/rust/queries/mod.rs +2 -0
  82. package/src/rust/queries/palette_set.rs +82 -0
  83. package/src/rust/queries/plugin_column_styles.rs +6 -2
  84. package/src/rust/renderer/dispatch.rs +16 -4
  85. package/src/rust/renderer/plugin_config.rs +309 -47
  86. package/src/rust/renderer.rs +15 -42
  87. package/src/rust/session/column_defaults_update.rs +15 -8
  88. package/src/rust/session/metadata.rs +5 -1
  89. package/src/rust/session/props.rs +1 -0
  90. package/src/rust/session.rs +9 -6
  91. package/src/rust/tasks/create_panel.rs +44 -57
  92. package/src/rust/tasks/edit_expression.rs +19 -23
  93. package/src/rust/tasks/edit_window.rs +8 -10
  94. package/src/rust/tasks/eject.rs +4 -1
  95. package/src/rust/tasks/pipeline.rs +2 -2
  96. package/src/rust/tasks/presize_panels.rs +44 -5
  97. package/src/rust/tasks/reset_all.rs +4 -4
  98. package/src/rust/tasks/restore_and_render.rs +17 -44
  99. package/src/rust/tasks/restore_panel.rs +11 -13
  100. package/src/rust/tasks/set_edit_mode.rs +3 -1
  101. package/src/rust/tasks/sync_update_panels.rs +11 -1
  102. package/src/rust/tasks/update_theme.rs +23 -18
  103. package/src/rust/utils/css_vars.rs +26 -0
  104. package/src/rust/utils/mod.rs +2 -0
  105. package/src/rust/utils/spawn.rs +1 -1
  106. package/src/rust/workspace.rs +435 -272
  107. package/src/svg/lock.svg +7 -0
  108. package/src/themes/botanical.css +10 -0
  109. package/src/themes/defaults.css +12 -0
  110. package/src/themes/dracula.css +17 -0
  111. package/src/themes/gruvbox-dark.css +20 -0
  112. package/src/themes/gruvbox.css +10 -0
  113. package/src/themes/icons.css +1 -0
  114. package/src/themes/monokai.css +22 -0
  115. package/src/themes/phosphor.css +5 -0
  116. package/src/themes/pro-dark.css +10 -0
  117. package/src/themes/solarized-dark.css +7 -0
  118. package/src/themes/solarized.css +7 -0
  119. package/src/themes/vaporwave.css +20 -0
  120. package/src/ts/perspective-viewer.ts +1 -0
  121. package/src/ts/plugin.ts +14 -0
  122. package/src/ts/ts-rs/PanelViewerConfig.ts +1 -1
  123. package/src/ts/ts-rs/SaveWorkspaceOptions.ts +11 -0
  124. package/src/ts/ts-rs/ViewerConfig.ts +1 -1
  125. package/src/ts/ts-rs/WorkspaceConfig.ts +8 -2
  126. package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +11 -3
  127. package/src/rust/components/form/color_range_selector.rs +0 -137
  128. /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-39c3c3b28e3cbd48}/inline0.js +0 -0
  129. /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-39c3c3b28e3cbd48}/inline1.js +0 -0
  130. /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-39c3c3b28e3cbd48}/inline2.js +0 -0
  131. /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-39c3c3b28e3cbd48}/inline3.js +0 -0
  132. /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-39c3c3b28e3cbd48}/inline4.js +0 -0
  133. /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-39c3c3b28e3cbd48}/inline5.js +0 -0
Binary file
@@ -46,6 +46,7 @@ export const perspectiveviewerelement_getPlugin: (a: number, b: number, c: numbe
46
46
  export const perspectiveviewerelement_getRenderStats: (a: number, b: number, c: number) => void;
47
47
  export const perspectiveviewerelement_getSelection: (a: number, b: number, c: number) => void;
48
48
  export const perspectiveviewerelement_getTable: (a: number, b: number) => number;
49
+ export const perspectiveviewerelement_getThemes: (a: number) => number;
49
50
  export const perspectiveviewerelement_getView: (a: number, b: number) => number;
50
51
  export const perspectiveviewerelement_getViewConfig: (a: number, b: number) => number;
51
52
  export const perspectiveviewerelement_load: (a: number, b: number, c: number) => void;
@@ -59,7 +60,7 @@ export const perspectiveviewerelement_restore: (a: number, b: number, c: number)
59
60
  export const perspectiveviewerelement_restoreWorkspace: (a: number, b: number) => number;
60
61
  export const perspectiveviewerelement_restyleElement: (a: number) => number;
61
62
  export const perspectiveviewerelement_save: (a: number, b: number) => number;
62
- export const perspectiveviewerelement_saveWorkspace: (a: number) => number;
63
+ export const perspectiveviewerelement_saveWorkspace: (a: number, b: number) => number;
63
64
  export const perspectiveviewerelement_setActivePanel: (a: number, b: number, c: number) => number;
64
65
  export const perspectiveviewerelement_setAutoPause: (a: number, b: number) => number;
65
66
  export const perspectiveviewerelement_setAutoSize: (a: number, b: number) => void;
@@ -99,7 +100,7 @@ export const client_table: (a: number, b: number, c: number) => number;
99
100
  export const client_terminate: (a: number, b: number) => void;
100
101
  export const genericsqlvirtualservermodel_getHostedTables: (a: number, b: number) => void;
101
102
  export const genericsqlvirtualservermodel_new: (a: number, b: number) => void;
102
- export const genericsqlvirtualservermodel_tableMakeView: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
103
+ export const genericsqlvirtualservermodel_tableMakeView: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void;
103
104
  export const genericsqlvirtualservermodel_tableSchema: (a: number, b: number, c: number, d: number) => void;
104
105
  export const genericsqlvirtualservermodel_tableSize: (a: number, b: number, c: number, d: number) => void;
105
106
  export const genericsqlvirtualservermodel_tableValidateExpression: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
@@ -166,21 +167,22 @@ export const virtualdataslice_setIntegerCol: (a: number, b: number, c: number, d
166
167
  export const virtualdataslice_setStringCol: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
167
168
  export const virtualserver_handleRequest: (a: number, b: number, c: number) => number;
168
169
  export const virtualserver_new: (a: number, b: number) => void;
169
- export const __wasm_bindgen_func_elem_17003: (a: number, b: number) => void;
170
- export const __wasm_bindgen_func_elem_17713: (a: number, b: number) => void;
171
- export const __wasm_bindgen_func_elem_18571: (a: number, b: number) => void;
172
- export const __wasm_bindgen_func_elem_3989: (a: number, b: number) => void;
173
- export const __wasm_bindgen_func_elem_23208: (a: number, b: number) => void;
174
- export const __wasm_bindgen_func_elem_31328: (a: number, b: number, c: number, d: number) => void;
175
- export const __wasm_bindgen_func_elem_17122: (a: number, b: number, c: number) => void;
176
- export const __wasm_bindgen_func_elem_17718: (a: number, b: number, c: number) => void;
177
- export const __wasm_bindgen_func_elem_6981: (a: number, b: number, c: number) => void;
178
- export const __wasm_bindgen_func_elem_6982: (a: number, b: number, c: number) => void;
179
- export const __wasm_bindgen_func_elem_6983: (a: number, b: number, c: number) => void;
180
- export const __wasm_bindgen_func_elem_6979: (a: number, b: number, c: number) => void;
181
- export const __wasm_bindgen_func_elem_23225: (a: number, b: number, c: number) => void;
182
- export const __wasm_bindgen_func_elem_19569: (a: number, b: number) => number;
183
- export const __wasm_bindgen_func_elem_17717: (a: number, b: number) => void;
170
+ export const __wasm_bindgen_func_elem_17916: (a: number, b: number) => void;
171
+ export const __wasm_bindgen_func_elem_18625: (a: number, b: number) => void;
172
+ export const __wasm_bindgen_func_elem_19491: (a: number, b: number) => void;
173
+ export const __wasm_bindgen_func_elem_4310: (a: number, b: number) => void;
174
+ export const __wasm_bindgen_func_elem_24164: (a: number, b: number) => void;
175
+ export const __wasm_bindgen_func_elem_32290: (a: number, b: number, c: number, d: number) => void;
176
+ export const __wasm_bindgen_func_elem_18035: (a: number, b: number, c: number) => void;
177
+ export const __wasm_bindgen_func_elem_18630: (a: number, b: number, c: number) => void;
178
+ export const __wasm_bindgen_func_elem_7520: (a: number, b: number, c: number) => void;
179
+ export const __wasm_bindgen_func_elem_7521: (a: number, b: number, c: number) => void;
180
+ export const __wasm_bindgen_func_elem_7522: (a: number, b: number, c: number) => void;
181
+ export const __wasm_bindgen_func_elem_7518: (a: number, b: number, c: number) => void;
182
+ export const __wasm_bindgen_func_elem_24181: (a: number, b: number, c: number) => void;
183
+ export const __wasm_bindgen_func_elem_20501: (a: number, b: number) => number;
184
+ export const __wasm_bindgen_func_elem_18629: (a: number, b: number) => void;
185
+ export const __wasm_bindgen_func_elem_20502: (a: number, b: number) => void;
184
186
  export const __wbindgen_export: (a: number, b: number) => number;
185
187
  export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
186
188
  export const __wbindgen_export3: (a: number) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@perspective-dev/viewer",
3
- "version": "5.2.0",
3
+ "version": "5.3.0",
4
4
  "description": "The `<perspective-viewer>` Custom Element, frontend for Perspective",
5
5
  "keywords": [
6
6
  "perspective",
@@ -150,15 +150,15 @@
150
150
  content: var(--psp-label--number-fg-mode--content, "Foreground");
151
151
  }
152
152
 
153
- label#pos_fg_color-label:before {
153
+ label#fg_colors-label:before {
154
154
  content: var(--psp-label--number-fg-mode--content, "Foreground");
155
155
  }
156
156
 
157
157
  label#number_bg_mode-label:before {
158
- content: var(--psp-label--number-fg-mode--content, "Background");
158
+ content: var(--psp-label--number-bg-mode--content, "Background");
159
159
  }
160
160
 
161
- label#pos_bg_color-label:before {
161
+ label#bg_colors-label:before {
162
162
  content: var(--psp-label--pos-bg-color--content, "Background");
163
163
  }
164
164
 
@@ -187,8 +187,12 @@
187
187
  content: var(--psp-label--series--content, "Series");
188
188
  }
189
189
 
190
- label#color-range-label:before {
191
- content: var(--psp-label--color-range--content, "Color Range");
190
+ label#palette-label:before {
191
+ content: var(--psp-label--palette--content, "Palette");
192
+ }
193
+
194
+ label#gradient-label:before {
195
+ content: var(--psp-label--gradient--content, "Gradient");
192
196
  }
193
197
 
194
198
  label#style-label:before {
@@ -221,34 +221,224 @@
221
221
  align-items: center;
222
222
  flex-wrap: nowrap;
223
223
  flex: 1 1 100%;
224
- .color-thermometer {
224
+ }
225
+
226
+ .palette-selector {
227
+ .palette-swatches {
228
+ display: flex;
229
+ flex-wrap: wrap;
230
+ align-items: center;
231
+ gap: 4px;
225
232
  flex: 1 1 auto;
233
+ width: 0px;
234
+ max-height: 84px;
235
+ overflow-y: auto;
236
+ overflow-x: hidden;
237
+ padding: 0px 0 4px 0;
238
+ }
239
+
240
+ .palette-swatch {
241
+ position: relative;
242
+ width: 24px;
226
243
  height: 24px;
244
+ touch-action: none;
245
+
246
+ input[type="color"] {
247
+ width: 24px;
248
+ height: 24px;
249
+ border-radius: 3px;
250
+ }
251
+
252
+ &.dragging {
253
+ opacity: 0.5;
254
+ outline: 1px dashed var(--psp--color);
255
+ outline-offset: -1px;
256
+ border-radius: 3px;
257
+ }
258
+
259
+ .palette-swatch-remove {
260
+ position: absolute;
261
+ top: -2px;
262
+ right: -7px;
263
+ width: 14px;
264
+ height: 14px;
265
+ cursor: pointer;
266
+ display: none;
267
+ background-color: var(--psp--color);
268
+ -webkit-mask-size: cover;
269
+ mask-size: cover;
270
+ -webkit-mask-image: var(--psp-icon--close--mask-image);
271
+ mask-image: var(--psp-icon--close--mask-image);
272
+ }
273
+
274
+ &:hover .palette-swatch-remove {
275
+ display: inline-block;
276
+ }
277
+ }
278
+
279
+ .palette-swatches.reordering .palette-swatch-remove {
280
+ display: none;
281
+ }
282
+
283
+ .palette-add {
284
+ width: 22px;
285
+ height: 22px;
286
+ border: 1px dashed var(--psp-inactive--color);
287
+ border-radius: 3px;
288
+ cursor: pointer;
289
+ display: flex;
290
+ align-items: center;
291
+ justify-content: center;
292
+
293
+ &:before {
294
+ content: "+";
295
+ font-size: 14px;
296
+ line-height: 1;
297
+ color: var(--psp-inactive--color);
298
+ }
299
+
300
+ &:hover {
301
+ border-color: var(--psp--color);
302
+
303
+ &:before {
304
+ color: var(--psp--color);
305
+ }
306
+ }
227
307
  }
228
308
  }
229
309
 
230
- .color-selector {
231
- display: grid;
310
+ .gradient-stops-selector {
311
+ padding: 12px 0 16px 0;
232
312
 
233
- input {
234
- grid-column: 1;
235
- grid-row: 1;
313
+ .gradient-stops-bar {
314
+ cursor: copy;
315
+ position: relative;
316
+ flex: 1 1 auto;
317
+ height: 24px;
318
+ border-radius: 2px;
236
319
  }
237
- .color-label {
320
+
321
+ .gradient-stops-bar.discrete {
322
+ cursor: auto;
323
+ position: relative;
324
+ flex: 1 1 auto;
325
+ height: 24px;
326
+ border-radius: 2px;
327
+ }
328
+
329
+ .gradient-stop-handle {
330
+ position: absolute;
331
+ top: 0;
332
+ transform: translateX(-50%);
238
333
  display: flex;
239
- justify-content: center;
334
+ flex-direction: column;
240
335
  align-items: center;
241
- font-size: 14px;
242
- grid-column: 1;
243
- grid-row: 1;
244
- margin: 0;
245
- font-family: var(--psp-button--font-family, inherit);
246
- color: var(--sign--color, white);
247
- width: 36px;
336
+ width: 14px;
337
+ }
338
+
339
+ .gradient-stop-grip {
340
+ width: 14px;
248
341
  height: 24px;
249
- text-align: center;
250
- z-index: 1;
251
- pointer-events: none;
342
+ cursor: ew-resize;
343
+ touch-action: none;
344
+
345
+ &.disabled {
346
+ cursor: default;
347
+ }
348
+
349
+ &:before {
350
+ content: "";
351
+ display: block;
352
+ width: 0px;
353
+ height: 100%;
354
+ margin: 0 auto;
355
+ border: 1px solid var(--psp--background-color, #fff);
356
+ }
357
+ }
358
+
359
+ .gradient-stop-remove {
360
+ position: absolute;
361
+ top: -14px;
362
+ width: 14px;
363
+ height: 13px;
364
+ cursor: pointer;
365
+ display: inline-block;
366
+ background-color: var(--psp--color);
367
+ -webkit-mask-size: cover;
368
+ mask-size: cover;
369
+ -webkit-mask-image: var(--psp-icon--close--mask-image);
370
+ mask-image: var(--psp-icon--close--mask-image);
371
+
372
+ &.disabled {
373
+ cursor: default;
374
+ background-color: var(--psp-inactive--color);
375
+ }
376
+ }
377
+
378
+ .gradient-stop-lock {
379
+ position: absolute;
380
+ top: -14px;
381
+ width: 14px;
382
+ height: 13px;
383
+ display: inline-block;
384
+ background-color: var(--psp--color);
385
+ -webkit-mask-size: cover;
386
+ mask-size: cover;
387
+ -webkit-mask-image: var(--psp-icon--lock--mask-image);
388
+ mask-image: var(--psp-icon--lock--mask-image);
389
+ }
390
+
391
+ .gradient-stop-handle input[type="color"] {
392
+ width: 14px;
393
+ height: 14px;
394
+ margin-top: 2px;
395
+ border-radius: 3px;
396
+ }
397
+ }
398
+
399
+ .named-value-controls {
400
+ display: flex;
401
+ justify-content: flex-end;
402
+ align-items: center;
403
+ gap: 10px;
404
+ flex: 1 1 100%;
405
+ height: 0;
406
+ margin-top: 10px;
407
+ margin-bottom: -10px;
408
+ margin-right: 24px;
409
+ position: relative;
410
+ z-index: 1;
411
+ font-size: var(--label--font-size, 0.75em);
412
+ color: var(--psp-inactive--color);
413
+
414
+ select.named-value-select {
415
+ height: 15px;
416
+ padding: 0;
417
+ font-size: var(--label--font-size, 0.75em);
418
+ color: inherit;
419
+ background: none;
420
+ border: none;
421
+ cursor: pointer;
422
+
423
+ &:hover {
424
+ color: var(--psp--color, inherit);
425
+ }
426
+ }
427
+
428
+ .named-value-pin {
429
+ cursor: pointer;
430
+ user-select: none;
431
+ line-height: 15px;
432
+
433
+ &:before {
434
+ font-family: var(--psp-button--font-family, inherit);
435
+ color: var(--psp-inactive--color, #666);
436
+ content: var(--psp-label--pin-button--content, "Save");
437
+ }
438
+
439
+ &:hover:before {
440
+ color: var(--psp--color, inherit);
441
+ }
252
442
  }
253
443
  }
254
444
 
@@ -259,23 +449,11 @@
259
449
  padding: 0;
260
450
  font-family: inherit;
261
451
  overflow: hidden;
262
- border-radius: 12px;
452
+ border-radius: 3px;
263
453
 
264
454
  &:hover {
265
455
  opacity: 0.8;
266
456
  }
267
-
268
- &.pos-color-param {
269
- width: 36px;
270
- border-radius: 12px 0 0 12px;
271
- margin: 0 1px 0 0;
272
- }
273
-
274
- &.neg-color-param {
275
- width: 36px;
276
- border-radius: 0 12px 12px 0;
277
- margin: 0 0 0 1px;
278
- }
279
457
  }
280
458
 
281
459
  ::-webkit-color-swatch-wrapper {
@@ -16,12 +16,13 @@
16
16
  position: relative;
17
17
  flex: 1 1 auto;
18
18
  height: 100%;
19
+ font-size: 12px;
19
20
 
20
21
  &:after {
21
22
  content: attr(data-value) " ";
22
23
  visibility: hidden;
23
24
  white-space: nowrap;
24
- padding-right: 17px;
25
+ padding-right: 20px;
25
26
  }
26
27
 
27
28
  select {
@@ -12,6 +12,10 @@
12
12
  */
13
13
 
14
14
  :host {
15
+ #editor.contained {
16
+ contain: inline-size;
17
+ }
18
+
15
19
  #editor {
16
20
  display: flex;
17
21
  flex: 1 1 auto;
@@ -65,10 +69,6 @@
65
69
  white-space: pre;
66
70
  overflow: hidden;
67
71
 
68
- span {
69
- /* display: contents; */
70
- }
71
-
72
72
  .comment {
73
73
  color: var(--psp-code-editor--comment--color, orange);
74
74
  }
@@ -630,24 +630,55 @@ fn control_schema_entries(spec: &ControlSpec) -> Vec<(String, Value)> {
630
630
  },
631
631
  ControlSpec::Color { key, default } => vec![(
632
632
  key.clone(),
633
- json!({ "type": "string", "format": "color", "default": default }),
633
+ json!({
634
+ "type": "string",
635
+ "description": "A CSS color (`#rrggbb`, `rgb()`), or a host-defined named color `var(--psp-user--color-<name>)`",
636
+ "default": default,
637
+ }),
634
638
  )],
635
- ControlSpec::ColorRange {
636
- key_pos,
637
- key_neg,
638
- default_pos,
639
- default_neg,
640
- ..
641
- } => vec![
642
- (
643
- key_pos.clone(),
644
- json!({ "type": "string", "format": "color", "default": default_pos }),
645
- ),
646
- (
647
- key_neg.clone(),
648
- json!({ "type": "string", "format": "color", "default": default_neg }),
649
- ),
650
- ],
639
+ ControlSpec::Palette { key, default, max } => {
640
+ let mut description = "Ordered discrete color palette, cycled over the column's \
641
+ categories/series: a CSS `linear-gradient(to right, #rrggbb, \
642
+ #rrggbb, …)` of N colors WITHOUT positions, or a host-defined \
643
+ named palette `var(--psp-user--palette-<name>)`"
644
+ .to_owned();
645
+ if let Some(max) = max {
646
+ description.push_str(&format!(" (at most {max} colors)"));
647
+ }
648
+
649
+ vec![(
650
+ key.clone(),
651
+ json!({
652
+ "type": "string",
653
+ "description": description,
654
+ "default": default,
655
+ }),
656
+ )]
657
+ },
658
+ ControlSpec::GradientStops {
659
+ key,
660
+ default,
661
+ discrete,
662
+ } => {
663
+ let mut description = "Multi-stop color gradient: a CSS `linear-gradient(to right, \
664
+ #rrggbb P%, …)` with positioned stops (direction normalized to \
665
+ `to right`; stops[0] maps to the most negative value), or a \
666
+ host-defined named gradient `var(--psp-user--gradient-<name>)`"
667
+ .to_owned();
668
+
669
+ if *discrete {
670
+ description.push_str(" — exactly 2 stops (the negative and positive colors)");
671
+ }
672
+
673
+ vec![(
674
+ key.clone(),
675
+ json!({
676
+ "type": "string",
677
+ "description": description,
678
+ "default": default,
679
+ }),
680
+ )]
681
+ },
651
682
  ControlSpec::DatetimeFormat => vec![(
652
683
  "date_format".to_owned(),
653
684
  json!({ "description": "Datetime display format: a style preset or custom format fields" }),
@@ -23,7 +23,7 @@ use super::expr_edit_button::*;
23
23
  use crate::components::column_dropdown::ColumnDropDownElement;
24
24
  use crate::components::column_selector::{EmptyColumn, InvalidColumn};
25
25
  use crate::config::ColumnSelectMode;
26
- use crate::presentation::{ColumnLocator, Presentation};
26
+ use crate::presentation::{ColumnSettingsTarget, Presentation};
27
27
  use crate::queries::*;
28
28
  use crate::renderer::*;
29
29
  use crate::session::*;
@@ -51,7 +51,7 @@ pub struct ActiveColumnProps {
51
51
  pub onselect: Callback<()>,
52
52
 
53
53
  /// Fires when this component's expression/config button is clicked.
54
- pub on_open_expr_panel: Callback<ColumnLocator>,
54
+ pub on_open_expr_panel: Callback<ColumnSettingsTarget>,
55
55
 
56
56
  /// Is this column in a grouped context (does the aggregate selector
57
57
  /// need to be visible)?
@@ -12,12 +12,12 @@
12
12
 
13
13
  use yew::prelude::*;
14
14
 
15
- use super::ColumnLocator;
15
+ use super::{ColumnLocator, ColumnSettingsTarget};
16
16
 
17
17
  #[derive(Clone, PartialEq, Properties)]
18
18
  pub struct AddExpressionButtonProps {
19
19
  // Fires when this button is clicked.
20
- pub on_open_expr_panel: Callback<ColumnLocator>,
20
+ pub on_open_expr_panel: Callback<ColumnSettingsTarget>,
21
21
 
22
22
  /// The column this butotn will open configuration for.
23
23
  pub selected_column: Option<ColumnLocator>,
@@ -47,7 +47,7 @@ pub fn AddExpressionButton(p: &AddExpressionButtonProps) -> Html {
47
47
 
48
48
  let onmousedown = p
49
49
  .on_open_expr_panel
50
- .reform(|_| ColumnLocator::NewExpression);
50
+ .reform(|_| ColumnSettingsTarget::NewExpression);
51
51
 
52
52
  let class = if *is_mouseover || matches!(p.selected_column, Some(ColumnLocator::NewExpression))
53
53
  {
@@ -10,9 +10,9 @@
10
10
  // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
11
  // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
12
 
13
- use std::collections::HashSet;
14
13
  use std::rc::Rc;
15
14
 
15
+ use itertools::Itertools;
16
16
  use perspective_client::config::*;
17
17
  use yew::prelude::*;
18
18
 
@@ -163,8 +163,7 @@ impl AggregateSelector {
163
163
  Aggregate::MultiAggregate(x, _) => Some(x),
164
164
  _ => None,
165
165
  })
166
- .collect::<HashSet<_>>()
167
- .into_iter()
166
+ .unique()
168
167
  .map(|x| {
169
168
  SelectItem::OptGroup(
170
169
  x.clone().into(),
@@ -279,6 +279,14 @@ impl Component for ConfigSelector {
279
279
  ctx.props().metadata.get_features().unwrap(),
280
280
  );
281
281
 
282
+ super::close_column_settings_if_displaced(
283
+ &ctx.props().presentation,
284
+ &ctx.props().renderer,
285
+ &ctx.props().metadata,
286
+ &ctx.props().view_config,
287
+ &update,
288
+ );
289
+
282
290
  {
283
291
  let session = ctx.props().session.clone();
284
292
  let renderer = ctx.props().renderer.clone();
@@ -12,7 +12,7 @@
12
12
 
13
13
  use yew::prelude::*;
14
14
 
15
- use super::ColumnLocator;
15
+ use super::ColumnSettingsTarget;
16
16
 
17
17
  #[derive(PartialEq, Clone, Properties)]
18
18
  pub struct ExprEditButtonProps {
@@ -27,7 +27,7 @@ pub struct ExprEditButtonProps {
27
27
  pub is_window: bool,
28
28
 
29
29
  /// Fires when the config/expresison button is clicked.
30
- pub on_open_expr_panel: Callback<ColumnLocator>,
30
+ pub on_open_expr_panel: Callback<ColumnSettingsTarget>,
31
31
 
32
32
  /// Is the expression/config panel open?
33
33
  pub is_editing: bool,
@@ -42,14 +42,8 @@ pub struct ExprEditButtonProps {
42
42
  #[function_component]
43
43
  pub fn ExprEditButton(p: &ExprEditButtonProps) -> Html {
44
44
  let onmousedown = yew::use_callback(p.clone(), |_, p| {
45
- let name = if p.is_window {
46
- ColumnLocator::Window(p.name.clone())
47
- } else if p.is_expression {
48
- ColumnLocator::Expression(p.name.clone())
49
- } else {
50
- ColumnLocator::Table(p.name.clone())
51
- };
52
- p.on_open_expr_panel.emit(name)
45
+ p.on_open_expr_panel
46
+ .emit(ColumnSettingsTarget::Column(p.name.clone()))
53
47
  });
54
48
 
55
49
  let class = if p.is_disabled {
@@ -18,7 +18,7 @@ use yew::prelude::*;
18
18
  use super::expr_edit_button::*;
19
19
  use crate::components::type_icon::TypeIcon;
20
20
  use crate::config::ColumnSelectMode;
21
- use crate::presentation::{ColumnLocator, Presentation};
21
+ use crate::presentation::{ColumnSettingsTarget, Presentation};
22
22
  use crate::renderer::*;
23
23
  use crate::session::*;
24
24
  use crate::tasks::apply_and_render;
@@ -61,7 +61,7 @@ pub struct InactiveColumnProps {
61
61
  pub onselect: Callback<()>,
62
62
 
63
63
  /// Fires when this column's expression/config button is clicked.
64
- pub on_open_expr_panel: Callback<ColumnLocator>,
64
+ pub on_open_expr_panel: Callback<ColumnSettingsTarget>,
65
65
 
66
66
  // State
67
67
  pub presentation: Presentation,